pax_global_header00006660000000000000000000000064151614414760014523gustar00rootroot0000000000000052 comment=adfbf1855c348766beb4b790dcc8ebc02f908f63 rocq-9.2.0/000077500000000000000000000000001516144147600124775ustar00rootroot00000000000000rocq-9.2.0/.github/000077500000000000000000000000001516144147600140375ustar00rootroot00000000000000rocq-9.2.0/.github/CODEOWNERS000066400000000000000000000223611516144147600154360ustar00rootroot00000000000000# This file associates maintainer teams to each component. # See CONTRIBUTING.md ########## Contributing process ########## /.github/ @rocq-prover/contributing-process-maintainers /CONTRIBUTING.md @rocq-prover/contributing-process-maintainers ########## Build system ########## /Makefile @rocq-prover/build-maintainers /dev/tools/make_git_revision.sh @rocq-prover/build-maintainers /configure @rocq-prover/build-maintainers /tools/configure/* @rocq-prover/build-maintainers /tools/coqdep/ @rocq-prover/build-maintainers /boot/ @rocq-prover/build-maintainers ########## CI infrastructure ########## /dev/ci/ @rocq-prover/ci-maintainers /dev/lint-*.sh @rocq-prover/ci-maintainers /.travis.yml @rocq-prover/ci-maintainers /.gitlab-ci.yml @rocq-prover/ci-maintainers /.github/workflows @rocq-prover/ci-maintainers /dev/ci/platform/ @rocq-prover/windows-build-maintainers /Makefile.ci @rocq-prover/ci-maintainers /dev/ci/nix @rocq-prover/nix-maintainers *.nix @rocq-prover/nix-maintainers /flake.lock @rocq-prover/nix-maintainers /dev/ci/user-overlays/*.sh # Trick to avoid getting review requests # each time someone adds an overlay /dev/bench/ @rocq-prover/bench-maintainers ########## Documentation ########## /README.md @rocq-prover/doc-maintainers /INSTALL.md @rocq-prover/doc-maintainers /CODE_OF_CONDUCT.md @rocq-prover/code-of-conduct-team /doc/ @rocq-prover/doc-maintainers /dev/doc/ @rocq-prover/doc-maintainers /doc/changelog/*/*.rst /dev/doc/changes.md # Trick to avoid getting review requests # each time someone modifies the changelog /dev/doc/build-system.dune.md @rocq-prover/build-maintainers /dev/doc/critical-bugs @rocq-prover/kernel-maintainers /dev/doc/econstr.md @rocq-prover/engine-maintainers /dev/doc/proof-engine.md @rocq-prover/engine-maintainers /dev/doc/release-process.md @rocq-prover/contributing-process-maintainers /dev/doc/shield-icon.png @rocq-prover/contributing-process-maintainers /dev/doc/SProp.md @rocq-prover/universes-maintainers /dev/doc/style.md @rocq-prover/contributing-process-maintainers /dev/doc/unification.txt @rocq-prover/pretyper-maintainers /dev/doc/universes.md @rocq-prover/universes-maintainers /dev/doc/xml-protocol.md @rocq-prover/stm-maintainers /man/ @rocq-prover/doc-maintainers /doc/plugin_tutorial/ @rocq-prover/plugin-tutorial-maintainers ########## Coqchk ########## /checker/ @rocq-prover/kernel-maintainers /test-suite/coqchk/ @rocq-prover/kernel-maintainers ########## Coq lib ########## /clib/ @rocq-prover/lib-maintainers /test-suite/unit-tests/clib/ @rocq-prover/lib-maintainers /lib/ @rocq-prover/lib-maintainers ########## Proof engine ########## /engine/ @rocq-prover/engine-maintainers /engine/univ* @rocq-prover/universes-maintainers /engine/uState.* @rocq-prover/universes-maintainers ########## CoqIDE ########## /ide/ @rocq-prover/coqide-maintainers /ide/protocol/ @rocq-prover/stm-maintainers /test-suite/ide/ @rocq-prover/stm-maintainers ########## Desugaring ########## /interp/ @rocq-prover/extensible-syntax-maintainers ########## Kernel ########## /kernel/ @rocq-prover/kernel-maintainers /kernel/byterun/ @rocq-prover/vm-native-maintainers /kernel/native* @rocq-prover/vm-native-maintainers /kernel/vm* @rocq-prover/vm-native-maintainers /kernel/vconv.* @rocq-prover/vm-native-maintainers /kernel/genOpcodeFiles.* @rocq-prover/vm-native-maintainers /kernel/sorts.* @rocq-prover/universes-maintainers /kernel/uGraph.* @rocq-prover/universes-maintainers /kernel/univ.* @rocq-prover/universes-maintainers ########## Library ########## /library/ @rocq-prover/library-maintainers ########## Parser ########## /coqpp/ @rocq-prover/parsing-maintainers /gramlib/ @rocq-prover/parsing-maintainers /parsing/ @rocq-prover/parsing-maintainers ########## Standard library and plugins ########## /theories/Corelib/ @rocq-prover/stdlib-maintainers /theories/Corelib/Classes/ @rocq-prover/typeclasses-maintainers /theories/Corelib/Compat/ @rocq-prover/compat-maintainers /plugins/btauto/ @rocq-prover/btauto-maintainers /plugins/cc/ @rocq-prover/cc-maintainers /plugins/derive/ @rocq-prover/derive-maintainers /theories/Corelib/derive/ @rocq-prover/derive-maintainers /plugins/extraction/ @rocq-prover/extraction-maintainers /theories/Corelib/extraction/ @rocq-prover/extraction-maintainers /plugins/firstorder/ @rocq-prover/firstorder-maintainers /plugins/funind/ @rocq-prover/funind-maintainers /plugins/ltac/ @rocq-prover/ltac-maintainers /plugins/micromega/ @rocq-prover/micromega-maintainers /plugins/nsatz/ @rocq-prover/nsatz-maintainers /plugins/ring/ @rocq-prover/ring-maintainers /plugins/ssrmatching/ @rocq-prover/ssreflect-maintainers /theories/Corelib/ssrmatching/ @rocq-prover/ssreflect-maintainers /plugins/ssr/ @rocq-prover/ssreflect-maintainers /theories/Corelib/ssr/ @rocq-prover/ssreflect-maintainers /test-suite/ssr/ @rocq-prover/ssreflect-maintainers /plugins/syntax/ @rocq-prover/parsing-maintainers /plugins/rtauto/ @rocq-prover/rtauto-maintainers /plugins/ltac2/ @rocq-prover/ltac2-maintainers /theories/Ltac2 @rocq-prover/ltac2-maintainers ########## Pretyper ########## /pretyping/ @rocq-prover/pretyper-maintainers /pretyping/vnorm.* @rocq-prover/vm-native-maintainers /pretyping/nativenorm.* @rocq-prover/vm-native-maintainers ########## Pretty printer ########## /printing/ @rocq-prover/extensible-syntax-maintainers ########## Proof infrastructure ########## /proofs/ @rocq-prover/engine-maintainers ########## STM ########## /stm/ @rocq-prover/stm-maintainers /test-suite/interactive/ @rocq-prover/stm-maintainers /test-suite/stm/ @rocq-prover/stm-maintainers /test-suite/vio/ @rocq-prover/stm-maintainers ########## Tactics ########## /tactics/ @rocq-prover/tactics-maintainers /tactics/class_tactics.* @rocq-prover/typeclasses-maintainers ########## Number ########## /interp/numTok.* @rocq-prover/number-maintainers /kernel/float64* @rocq-prover/number-maintainers /kernel/uint63* @rocq-prover/number-maintainers /plugins/syntax/g_number_string.mlg @rocq-prover/number-maintainers /plugins/syntax/int63_syntax_plugin.mllib @rocq-prover/number-maintainers /plugins/syntax/number.ml @rocq-prover/number-maintainers /plugins/syntax/number_string_notation_plugin.mllib @rocq-prover/number-maintainers /test-suite/output/*Number* @rocq-prover/number-maintainers /test-suite/primitive/float/ @rocq-prover/number-maintainers /test-suite/primitive/sint63/ @rocq-prover/number-maintainers /test-suite/primitive/uint63/ @rocq-prover/number-maintainers /theories/Corelib/Init/Decimal.v @rocq-prover/number-maintainers /theories/Corelib/Init/Hexadecimal.v @rocq-prover/number-maintainers /theories/Corelib/Init/Nat.v @rocq-prover/number-maintainers /theories/Corelib/Init/Number.v @rocq-prover/number-maintainers /theories/Corelib/Numbers/ @rocq-prover/number-maintainers /theories/Corelib/Floats/ @rocq-prover/number-maintainers ########## Tools ########## /tools/coqdoc/ @rocq-prover/coqdoc-maintainers /test-suite/coqdoc/ @rocq-prover/coqdoc-maintainers /tools/coqwc* @rocq-prover/coqdoc-maintainers /test-suite/coqwc/ @rocq-prover/coqdoc-maintainers /tools/coq_makefile* @rocq-prover/coq-makefile-maintainers /tools/CoqMakefile* @rocq-prover/coq-makefile-maintainers /test-suite/coq-makefile/ @rocq-prover/coq-makefile-maintainers /tools/TimeFileMaker.py @rocq-prover/coq-makefile-maintainers /tools/make-*-tim*.py @rocq-prover/coq-makefile-maintainers /tools/coq_tex* @silene # Secondary maintainer @gares ########## Toplevel ########## /toplevel/ @rocq-prover/toplevel-maintainers /topbin/ @rocq-prover/toplevel-maintainers /sysinit/ @rocq-prover/toplevel-maintainers ########## Vernacular ########## /vernac/ @rocq-prover/vernac-maintainers /vernac/metasyntax.* @rocq-prover/parsing-maintainers /vernac/classes.* @rocq-prover/typeclasses-maintainers ########## Test suite ########## /test-suite/Makefile @rocq-prover/test-suite-maintainers /test-suite/README.md @rocq-prover/test-suite-maintainers /test-suite/report.sh @rocq-prover/test-suite-maintainers /test-suite/unit-tests/src/ @rocq-prover/test-suite-maintainers /test-suite/success/Compat*.v @rocq-prover/compat-maintainers ########## Developer tools ########## /dev/tools/ @rocq-prover/dev-tools-maintainers ########## Dune ########## /.ocamlinit @rocq-prover/build-maintainers *dune* @rocq-prover/build-maintainers *.opam @rocq-prover/build-maintainers @erikmd rocq-9.2.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001516144147600162225ustar00rootroot00000000000000rocq-9.2.0/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000031561516144147600211220ustar00rootroot00000000000000name: Bug report description: Report an unexpected behavior. labels: ["kind: bug", "needs: triage"] body: - type: markdown attributes: value: | Thank you for your contribution. It is helpful to explain how to reproduce the bug and what the problem is. If you have a small reproducible example, you can use the second field to provide it. Otherwise, please provide a link to a repository, a gist (https://gist.github.com) or drag-and-drop a `.zip` archive in the first field. - type: textarea attributes: label: Description of the problem placeholder: What happens and what you would have expected instead. - type: textarea attributes: label: Small Rocq / Coq file to reproduce the bug placeholder: | Goal True. ok tactic. buggy tactic. (* the last line raises an error or an anomaly *) render: coq - type: input attributes: label: Version of Rocq / Coq where this bug occurs description: | You can get this information by running `rocq -v` or `coqtop -v`. Feel free to provide a comma-separated list or a range of versions if you can reproduce the bug on several versions of Rocq / Coq. placeholder: X.Y.Z - type: input attributes: label: Interface of Rocq / Coq where this bug occurs description: | e.g. Proof General, VsRocq, RocqIDE, etc Can be omitted if the issue occurs with `rocq compile` - type: input attributes: label: Last version of Rocq / Coq where the bug did not occur description: You can fill this optional field if the bug is a regression compared to a previous version of Rocq / Coq. rocq-9.2.0/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000016511516144147600202150ustar00rootroot00000000000000blank_issues_enabled: true contact_links: - name: The Rocq Prover Zulip Chat url: https://rocq-prover.zulipchat.com about: For casual and high traffic discussions. You can ask questions about the Rocq Prover (#Rocq users) or questions about Rocq internals (#Rocq devs & plugin devs). There are also many streams dedicated to external Rocq projects. - name: The Rocq Prover Discourse Forum url: https://discourse.rocq-prover.org about: Our official, multilingual forum, for more structured and easy to search discussions. You can also ask about the Rocq Prover or internals here, and this is the place to send any announcements. - name: Proof Assistants Stack Exchange url: https://proofassistants.stackexchange.com about: For questions about the Rocq Prover, Lean, Agda, Isabelle, etc. This is a Q&A site, where numerous Rocq users are available to answer questions, but this is not an official Rocq forum. rocq-9.2.0/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000013021516144147600221440ustar00rootroot00000000000000name: Feature request description: Suggest an idea of improvement. labels: ["kind: wish", "needs: triage"] body: - type: textarea attributes: label: Is your feature request related to a problem? placeholder: A clear and concise description of what the problem is. E.g., I'm frustrated when [...] - type: textarea attributes: label: Proposed solution placeholder: Describe your ideal solution. - type: textarea attributes: label: Alternative solutions placeholder: List any alternative solutions or features you've considered. - type: textarea attributes: label: Additional context placeholder: Add any other context or screenshots about the feature request here. rocq-9.2.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000031721516144147600176430ustar00rootroot00000000000000 Fixes / closes #???? - [ ] Added / updated **test-suite**. - [ ] Added **changelog**. - [ ] Added / updated **documentation**. - [ ] Documented any new / changed **user messages**. - [ ] Updated **documented syntax** by running `make doc_gram_rsts`. - [ ] Opened **overlay** pull requests. We have a number of channels to reach the user community and the development team: - Our [Zulip chat][zulip-link], for casual and high traffic discussions. - Our [Discourse forum][discourse-link], for more structured and easily browsable discussions and Q&A. See also [rocq-prover.org/community](https://rocq-prover.org/community), which lists several other active platforms. rocq-9.2.0/.github/workflows/000077500000000000000000000000001516144147600160745ustar00rootroot00000000000000rocq-9.2.0/.github/workflows/check-conflicts.yml000066400000000000000000000007301516144147600216560ustar00rootroot00000000000000name: "Check conflicts" on: [push] # Only on push because @coqbot already takes care of checking for # conflicts when PRs are opened or synchronized permissions: contents: read jobs: main: permissions: pull-requests: write runs-on: ubuntu-latest steps: - uses: eps1lon/actions-label-merge-conflict@b8bf8341285ec9a4567d4318ba474fee998a6919 with: dirtyLabel: "needs: rebase" repoToken: "${{ secrets.GITHUB_TOKEN }}" rocq-9.2.0/.github/workflows/ci-github.yml000066400000000000000000000035211516144147600204730ustar00rootroot00000000000000name: Github CI on: [push, pull_request] permissions: contents: read # Cancels previous runs of the same workflow concurrency: group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" cancel-in-progress: true jobs: build: strategy: matrix: include: - name: macOS os: macos-latest ocaml: 4.14 test_disabled: # We exclude the coq-core package packages: ./coqide-server.opam ./rocq*.opam - name: Windows os: windows-latest ocaml: 4.14 test_disabled: misc coq-makefile precomputed-time-tests # we don't support rocqide on Windows yet, so we filter it, see #20631 packages: ./coqide-server.opam ./rocq-*.opam - name: Linux (latest OCaml) os: ubuntu-latest ocaml: 5 test_disabled: packages: ./coqide-server.opam ./rocq*.opam fail-fast: false name: ${{ matrix.name }} runs-on: ${{ matrix.os }} timeout-minutes: 45 steps: - name: πŸ› Special macOS Config if: matrix.os == 'macos-latest' run: brew install gnu-time - name: APT update if: matrix.os == 'ubuntu-latest' run: sudo apt-get update - name: πŸ”­ Checkout code uses: actions/checkout@v4 - name: 🐫 Setup OCaml uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: ${{ matrix.ocaml }} dune-cache: true - name: 🐫πŸͺ🐫 Get Rocq dependencies run: opam install --deps-only ${{ matrix.packages }} - name: 🧱 Build Rocq run: opam exec -- make world - name: πŸ› Test Rocq run: opam exec -- make -j 4 -C test-suite TIMED=1 DISABLED_SUBSYSTEMS='${{ matrix.test_disabled }}' rocq-9.2.0/.github/workflows/stale.yml000066400000000000000000000007201516144147600177260ustar00rootroot00000000000000name: Stale PRs on: schedule: # Every workday at 2am - cron: '0 2 * * 1-5' permissions: contents: read jobs: stale_prs: # Do not run on forks (we want this request to happen only once every night) permissions: contents: none if: github.repository_owner == 'rocq-prover' runs-on: ubuntu-latest steps: - run: curl -d "rocq-prover:rocq:${{ secrets.DAILY_SCHEDULE_SECRET }}" https://coqbot.herokuapp.com/check-stale-pr rocq-9.2.0/.gitlab-ci.yml000066400000000000000000001006311516144147600151340ustar00rootroot00000000000000image: $BASE_IMAGE include: - local: '/dev/ci/gitlab-modes/protected-mode.yml' rules: - if: $CI_COMMIT_BRANCH == "master" - if: $CI_COMMIT_BRANCH =~ /^v.*\..*$/ - local: "/dev/ci/gitlab-modes/normal-mode.yml" rules: - if: $CI_COMMIT_BRANCH != "master" && $CI_COMMIT_BRANCH !~ /^v.*\..*$/ - local: "/dev/ci/gitlab-modes/tagged-runners.yml" rules: - if: $TAGGED_RUNNERS - local: "/dev/ci/gitlab-modes/untagged-runners.yml" rules: - if: $TAGGED_RUNNERS == null - local: '/dev/bench/gitlab-bench.yml' stages: - docker - build-0 - build-1 - build-2 - build-3+ - deploy - stats # We set "needs" to contain all transitive dependencies. We include the # transitive dependencies as otherwise we don't get their artifacts # (eg if color had just needs: bignums it wouldn't get the artifact containing coq) # some default values variables: # Format: image_name-V$DATE-$hash # $DATE is so we can tell what's what in the image list # The $hash is the first 10 characters of the md5 of the Dockerfile. e.g. # echo $(md5sum dev/ci/docker/old_ubuntu_lts/Dockerfile | head -c 10) # echo $(md5sum dev/ci/docker/edge_ubuntu/Dockerfile | head -c 10) BASE_CACHEKEY: "old_ubuntu_lts-v9.2-V2025-11-14-69405188ee" EDGE_CACHEKEY: "edge_ubuntu-v9.2-V2025-12-02-e6edb0cc32" BASE_IMAGE: "$CI_REGISTRY_IMAGE:$BASE_CACHEKEY" EDGE_IMAGE: "$CI_REGISTRY_IMAGE:$EDGE_CACHEKEY" # Used to select special compiler switches such as flambda, 32bits, etc... OPAM_VARIANT: "" GIT_DEPTH: "10" before_script: - dev/ci/gitlab-section.sh start before_script before_script - cat /proc/{cpu,mem}info || true - ulimit -s - ls -a # figure out if artifacts are around - printenv -0 | sort -z | tr '\0' '\n' - opam switch set -y "${COMPILER}${OPAM_VARIANT}" - eval $(opam env) - opam list - opam config list - dune printenv --root . - dev/tools/check-cachekey.sh - dev/tools/list-potential-artifacts.sh > downloaded_artifacts.txt - if [ -d saved_build_ci ]; then mv saved_build_ci _build_ci; fi - dev/ci/gitlab-section.sh end before_script # Regular "release" build of Rocq, with final installed layout .build-template: stage: build-0 interruptible: true extends: .auto-use-tags variables: ROCQIDE: "opt" artifacts: name: "$CI_JOB_NAME" paths: - _install_ci # All those are for the test-suite jobs, to be discarded soon - config/Makefile - config/coq_config.py - config/coq_config.ml - config/coq_byte_config.ml - config/dune.c_flags expire_in: 1 week script: - cp dev/ci/dune-workspace.ci dune-workspace - PKGS=rocq-runtime,coq-core,rocq-core,coqide-server,rocq-devtools - if [ "$ROCQIDE" != "no" ]; then PKGS=${PKGS},rocqide; fi - dev/ci/gitlab-section.sh start coq.clean coq.clean - make clean # ensure that `make clean` works on a fresh clone - dev/ci/gitlab-section.sh end coq.clean - dev/ci/gitlab-section.sh start coq.config coq.config - ./configure -relocatable $COQ_EXTRA_CONF - dev/ci/gitlab-section.sh end coq.config - dev/ci/gitlab-section.sh start coq.build coq.build - make dunestrap - dune build -p $PKGS - dev/ci/gitlab-section.sh end coq.build - dev/ci/gitlab-section.sh start coq.install coq.install - dune install --prefix="$(pwd)/_install_ci" $(sed -e 's/,/ /g' <<< ${PKGS}) - dev/ci/gitlab-section.sh end coq.install # Developer build, with build layout. Faster and useful for those # jobs needing _build .build-template:base:dev: stage: build-0 interruptible: true extends: .auto-use-tags script: - cp dev/ci/dune-workspace.ci dune-workspace - make $DUNE_TARGET - tar cfj _build.tar.bz2 _build variables: DUNE_TARGET: "world rocqide" artifacts: name: "$CI_JOB_NAME" when: always paths: - _build/log - _build.tar.bz2 - theories/Corelib/dune - theories/Ltac2/dune expire_in: 1 day .doc-template: stage: build-1 interruptible: true extends: .auto-use-tags needs: - build:base:dev script: - ulimit -S -s 16384 - tar xfj _build.tar.bz2 - make "$DUNE_TARGET" artifacts: when: always name: "$CI_JOB_NAME" expire_in: 2 months # The used Rocq must be set explicitly for each job with "needs:". # We add a spurious dependency `not-a-real-job` that must be # overridden otherwise the CI will fail (to help debugging missing needs). # set "needs" when using .test-suite-template: stage: build-1 interruptible: true extends: .auto-use-tags needs: - not-a-real-job script: - cd test-suite - make clean - export OCAMLPATH=$(readlink -f ../_install_ci/lib/):"$OCAMLPATH" - COQEXTRAFLAGS="${COQEXTRAFLAGS}" make -j "$NJOBS" TIMED=1 all ROCQ_EXE=$(pwd)/../_install_ci/bin/rocq artifacts: name: "$CI_JOB_NAME.logs" when: on_failure paths: - test-suite/logs expire_in: 1 week # set "needs" when using .validate-template: stage: build-2 interruptible: true extends: .auto-use-tags needs: - not-a-real-job script: - for target in $CI_TARGETS; do dev/ci/ci-wrapper.sh "$target"; done - cd _install_ci - find lib/coq/ -name '*.vo' -fprint0 vofiles - xargs -0 --arg-file=vofiles bin/coqchk -o -m -coqlib lib/coq/ > ../coqchk.log 2>&1 || touch coqchk.failed - tail -n 1000 ../coqchk.log # the log is too big for gitlab so pipe to a file and display the tail - "[ ! -f coqchk.failed ]" # needs quoting for yml syntax reasons artifacts: name: "$CI_JOB_NAME.logs" when: always paths: - coqchk.log expire_in: 1 week # This template defaults to "needs: build:base" # Remember to include it as a transitive dependency if you want additional "needs:" .ci-template: stage: build-1 interruptible: true extends: .auto-use-tags script: - ulimit -S -s 16384 # For flambda + native # set CI_TARGETS from job name if not already provided, then print - echo CI_TARGETS = ${CI_TARGETS:=${CI_JOB_NAME#*:ci-}} - for target in $CI_TARGETS; do dev/ci/ci-wrapper.sh "$target"; done - touch ci-success after_script: - if { [ "$SAVE_BUILD_CI" ] || [ "$CI_COMMIT_REF_NAME" = master ] || ! [ -e ci-success ]; } && [ -d _build_ci ]; then mv _build_ci saved_build_ci; fi - dev/tools/list-potential-artifacts.sh > available_artifacts.txt - dev/tools/cleanup-artifacts.sh downloaded_artifacts.txt available_artifacts.txt artifacts: name: "$CI_JOB_NAME" paths: - _install_ci - saved_build_ci exclude: # reduce artifact size - saved_build_ci/**/.git # exclude .git directory itself as well - saved_build_ci/**/.git/**/* when: always expire_in: 1 week needs: - build:base only: &full-ci variables: - $FULL_CI == "true" .ci-template-flambda: extends: .ci-template image: $EDGE_IMAGE needs: - build:edge+flambda variables: OPAM_VARIANT: "+flambda" .deploy-template: stage: deploy extends: .auto-use-tags before_script: - which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y ) - eval $(ssh-agent -s) - mkdir -p ~/.ssh - chmod 700 ~/.ssh - ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts - git config --global user.name "coqbot" - git config --global user.email "coqbot@users.noreply.github.com" .pkg:opam-template: stage: build-0 image: $EDGE_IMAGE interruptible: true extends: .auto-use-tags # OPAM will build out-of-tree so no point in importing artifacts script: - if [ "$ROCQ_CI_NATIVE" = true ]; then opam install -y rocq-native; fi - opam pin add --kind=path rocq-runtime.dev . - opam pin add --kind=path rocq-core.dev . - if [ "$ROCQ_CI_NATIVE" = true ]; then echo "Definition f x := x + x." > test_native.v; fi - if [ "$ROCQ_CI_NATIVE" = true ]; then rocq c test_native.v; fi - if [ "$ROCQ_CI_NATIVE" = true ]; then test -f .coq-native/Ntest_native.cmxs; fi - opam pin add --kind=path coqide-server.dev . - opam pin add --kind=path rocqide.dev . - opam pin add --kind=path rocq-devtools . - opam pin add --kind=path rocq-test-suite.dev . -v - if command -v coqc; then exit 1; fi # coq-core didn't get autoinstalled - opam pin add --kind=path coq-core.dev . after_script: - eval $(opam env) - du -ha "$(coqc -where)" > files.listing artifacts: name: "$CI_JOB_NAME" paths: - files.listing when: always expire_in: 1 week variables: OPAM_VARIANT: "+flambda" only: *full-ci .nix-template: stage: build-0 needs: [] interruptible: true image: nixos/nix:latest extends: .auto-use-tags variables: GIT_STRATEGY: none # Required because we don't have git USER: root # Variable required by Cachix before_script: - cat /proc/{cpu,mem}info || true # Use current worktree as tmpdir to allow exporting artifacts in case of failure - export TMPDIR=$PWD # Install Cachix - nix-env -iA nixpkgs.cachix - cachix use coq artifacts: name: "$CI_JOB_NAME.logs" when: on_failure paths: - nix-build-coq.drv-0/*/test-suite/logs expire_in: 1 week ############################################################################## ########################## End of templates ################################## ############################################################################## docker-boot: stage: docker image: docker:stable services: - docker:dind before_script: [] script: - dev/tools/check-cachekey.sh - docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY" - cd dev/ci/docker/old_ubuntu_lts - if docker pull "$BASE_IMAGE"; then echo "Base image prebuilt!"; else docker build -t "$BASE_IMAGE" .; docker push "$BASE_IMAGE"; fi - cd ../edge_ubuntu - if docker pull "$EDGE_IMAGE"; then echo "Edge image prebuilt!"; else docker build -t "$EDGE_IMAGE" .; docker push "$EDGE_IMAGE"; fi except: variables: - $SKIP_DOCKER == "true" extends: .auto-use-docker-tags timeout: 2h build:base: extends: .build-template variables: COQ_EXTRA_CONF: "-native-compiler yes" only: *full-ci # no rocqide for 32bit: libgtk installation problems build:base+32bit: extends: .build-template variables: OPAM_VARIANT: "+32bit" COQ_EXTRA_CONF: "-native-compiler yes" ROCQIDE: "no" only: *full-ci build:edge+flambda: extends: .build-template image: $EDGE_IMAGE variables: OPAM_VARIANT: "+flambda" COQ_EXTRA_CONF: "-native-compiler yes" only: *full-ci build:base:dev: extends: .build-template:base:dev # Build using native dune rules build:base:dev:dune: stage: build-0 image: $EDGE_IMAGE variables: OPAM_VARIANT: "+flambda" interruptible: true extends: .auto-use-tags script: - cp theories/Corelib/dune.disabled theories/Corelib/dune - cp theories/Ltac2/dune.disabled theories/Ltac2/dune - dune build -p rocq-runtime,coq-core,rocq-core,coqide-server - ls _build/install/default/lib/coq/theories/Init/Prelude.vo - ls _build/install/default/lib/coq/user-contrib/Ltac2/Ltac2.vo only: *full-ci build:base+async: extends: .build-template variables: COQ_EXTRA_CONF: "-native-compiler yes" COQ_DUNE_EXTRA_OPT: "-async" after_script: - dmesg > dmesg.txt allow_failure: true # See https://github.com/rocq-prover/rocq/issues/9658 only: variables: - $UNRELIABLE =~ /enabled/ && $FULL_CI == "true" artifacts: when: always paths: - _install_ci # All those are for the test-suite jobs, to be discarded once we have dune for the test-suite - config/Makefile - config/coq_config.py - config/coq_config.ml - config/coq_byte_config.ml - config/dune.c_flags - dmesg.txt timeout: 1h 30min lint: stage: build-0 image: $EDGE_IMAGE script: dev/lint-repository.sh extends: .auto-use-tags variables: GIT_DEPTH: "" # we need an unknown amount of history for per-commit linting OPAM_VARIANT: "+flambda" # pkg:opam: # extends: .pkg:opam-template pkg:opam:native: extends: .pkg:opam-template variables: ROCQ_CI_NATIVE: "true" # broken, see eg https://gitlab.com/coq/coq/-/jobs/1754045983 # pkg:nix:deploy: # extends: .nix-template # environment: # name: cachix # url: https://coq.cachix.org # script: # - nix-build https://coq.inria.fr/nix/toolbox --argstr job coq --arg override "{coq = coq:$CI_COMMIT_SHA;}" -K | cachix push coq # only: # refs: # - master # - /^v.*\..*$/ # variables: # - $CACHIX_AUTH_TOKEN # pkg:nix:deploy:channel: # extends: .deploy-template # environment: # name: cachix # url: https://coq.cachix.org # only: # refs: # Repeat conditions from pkg:nix:deploy # - master # - /^v.*\..*$/ # variables: # - $CACHIX_AUTH_TOKEN && $CACHIX_DEPLOYMENT_KEY # # if the $CACHIX_AUTH_TOKEN variable isn't set, the job it depends on doesn't exist # needs: # - pkg:nix:deploy # script: # - echo "$CACHIX_DEPLOYMENT_KEY" | tr -d '\r' | ssh-add - > /dev/null # # Remove all pr branches because they could be missing when we run git fetch --unshallow # - git branch --list 'pr-*' | xargs -r git branch -D # - git fetch --unshallow # - git branch -v # - git push git@github.com:rocq-prover/coq-on-cachix "${CI_COMMIT_SHA}":"refs/heads/${CI_COMMIT_REF_NAME}" pkg:nix: extends: .nix-template script: - nix-build "$CI_PROJECT_URL/-/archive/$CI_COMMIT_SHA.tar.gz" -K only: *full-ci doc:refman: extends: .doc-template variables: DUNE_TARGET: refman-html artifacts: paths: - _build/log - _build/default/doc/refman-html doc:refman-pdf: extends: .doc-template variables: DUNE_TARGET: refman-pdf artifacts: paths: - _build/log - _build/default/doc/refman-pdf doc:init: extends: .doc-template variables: DUNE_TARGET: corelib-html artifacts: paths: - _build/log - _build/default/doc/corelib/html doc:refman:deploy: extends: .deploy-template environment: name: deployment url: https://coq.github.io/ only: variables: - $DOCUMENTATION_DEPLOY_KEY needs: - doc:ml-api:odoc - doc:ci-refman - doc:init - library:ci-stdlib_doc script: - echo "$DOCUMENTATION_DEPLOY_KEY" | tr -d '\r' | ssh-add - > /dev/null - git clone git@github.com:rocq-prover/doc.git _deploy --depth 1 - rm -rf _deploy/$CI_COMMIT_REF_NAME/api - rm -rf _deploy/$CI_COMMIT_REF_NAME/refman - rm -rf _deploy/$CI_COMMIT_REF_NAME/corelib - if [ $CI_COMMIT_REF_NAME = "master" ] ; then rm -rf _deploy/$CI_COMMIT_REF_NAME/refman-stdlib ; fi - if [ $CI_COMMIT_REF_NAME = "master" ] ; then rm -rf _deploy/$CI_COMMIT_REF_NAME/stdlib ; fi - mkdir -p _deploy/$CI_COMMIT_REF_NAME - cp -rv _build/default/_doc/_html _deploy/$CI_COMMIT_REF_NAME/api - cp -rv _build/default/doc/refman-html _deploy/$CI_COMMIT_REF_NAME/refman - cp -rv _build/default/doc/corelib/html _deploy/$CI_COMMIT_REF_NAME/corelib - if [ $CI_COMMIT_REF_NAME = "master" ] ; then cp -rv saved_build_ci/stdlib/_build/default/doc/refman-html _deploy/$CI_COMMIT_REF_NAME/refman-stdlib ; fi - if [ $CI_COMMIT_REF_NAME = "master" ] ; then cp -rv saved_build_ci/stdlib/_build/default/doc/stdlib/html _deploy/$CI_COMMIT_REF_NAME/stdlib ; fi - cd _deploy/$CI_COMMIT_REF_NAME/ - git add api refman corelib - if [ $CI_COMMIT_REF_NAME = "master" ] ; then git add refman-stdlib stdlib ; fi - git commit -m "Documentation of branch β€œ$CI_COMMIT_REF_NAME” at $CI_COMMIT_SHORT_SHA" - git push # TODO: rebase and retry on failure doc:ml-api:odoc: extends: .doc-template variables: DUNE_TARGET: apidoc artifacts: paths: - _build/log - _build/default/_doc/ test-suite:base: extends: .test-suite-template needs: - build:base only: *full-ci test-suite:base+32bit: extends: .test-suite-template needs: - build:base+32bit variables: OPAM_VARIANT: "+32bit" only: *full-ci test-suite:edge+flambda: extends: .test-suite-template image: $EDGE_IMAGE needs: - build:edge+flambda variables: OPAM_VARIANT: "+flambda" only: *full-ci test-suite:base:dev: stage: build-1 interruptible: true extends: .auto-use-tags needs: - build:base:dev script: - tar xfj _build.tar.bz2 - make test-suite artifacts: name: "$CI_JOB_NAME.logs" when: on_failure paths: - _build/default/test-suite/logs expire_in: 1 week .test-suite:ocaml+beta+dune-template: stage: build-1 # even though it has no deps we put it with the other test suite jobs needs: - docker-boot interruptible: true script: - opam switch create $OCAMLVER --empty - eval $(opam env) - opam repo add ocaml-beta https://github.com/ocaml/ocaml-beta-repository.git - opam update - opam install ocaml-variants=$OCAMLVER - opam install dune zarith - eval $(opam env) - export COQ_UNIT_TEST=noop - make test-suite artifacts: name: "$CI_JOB_NAME.logs" when: always paths: - _build/log - _build/default/test-suite/logs expire_in: 1 week allow_failure: true test-suite:base+async: extends: .test-suite-template needs: - build:base variables: COQEXTRAFLAGS: "-async-proofs on -async-proofs-cache force" allow_failure: true only: variables: - $UNRELIABLE =~ /enabled/ && $FULL_CI == "true" validate:base: extends: .validate-template variables: CI_TARGETS: "stdlib" needs: - build:base - library:ci-stdlib only: *full-ci # we currently don't have a stdlib+32bit job validate:base+32bit: extends: .validate-template needs: - build:base+32bit variables: OPAM_VARIANT: "+32bit" only: *full-ci validate:edge+flambda: extends: .validate-template image: $EDGE_IMAGE variables: CI_TARGETS: "stdlib" needs: - build:edge+flambda - library:ci-stdlib+flambda variables: OPAM_VARIANT: "+flambda" only: *full-ci # Libraries are by convention the projects that depend on Rocq # but not on its ML API library:ci-argosy: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-autosubst: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-bbv: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-bedrock2: extends: .ci-template-flambda variables: NJOBS: "1" SAVE_BUILD_CI: "1" # for bedrock2_examples needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil - library:ci-kami - library:ci-riscv_coq stage: build-3+ library:ci-bedrock2_examples: extends: .ci-template-flambda variables: NJOBS: "1" needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil - library:ci-kami - library:ci-riscv_coq - library:ci-bedrock2 stage: build-3+ timeout: 2h library:ci-category_theory: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-equations stage: build-2 library:ci-color: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-bignums stage: build-2 library:ci-compcert: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-flocq - library:ci-menhir stage: build-2 library:ci-coq_performance_tests: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-coq_tools: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-coqprime: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-bignums stage: build-2 library:ci-coqtail: extends: .ci-template library:ci-coquelicot: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-coqutil: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-cross_crypto: extends: .ci-template needs: - build:base - library:ci-stdlib variables: SAVE_BUILD_CI: "1" # for the minimizer (no install target available) library:ci-engine_bench: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-ext_lib: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-fcsl_pcm: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-2 library:ci-fiat_crypto: extends: .ci-template-flambda variables: COQEXTRAFLAGS: "-async-proofs-tac-j 0" SAVE_BUILD_CI: "1" # for fiat_crypto_ocaml needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil - library:ci-kami - library:ci-riscv_coq - library:ci-bedrock2 - library:ci-coqprime - library:ci-rupicola - plugin:ci-rewriter stage: build-3+ timeout: 3h library:ci-fiat_crypto_legacy: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqprime stage: build-3+ timeout: 1h 30min # We cannot use flambda due to # https://github.com/ocaml/ocaml/issues/7842, see # https://github.com/rocq-prover/rocq/pull/11916#issuecomment-609977375 library:ci-fiat_crypto_ocaml: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil - library:ci-kami - library:ci-riscv_coq - library:ci-bedrock2 - library:ci-coqprime - library:ci-rupicola - plugin:ci-rewriter - library:ci-fiat_crypto stage: build-3+ artifacts: paths: [] # These artifacts would go over the size limit library:ci-flocq: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-kami: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-menhir: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-oddorder: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-fourcolor: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-corn: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-bignums - plugin:ci-elpi_hb # CoRN uses elpi only (not HB) - depending on ci-elpi_hb reduces CI package count - library:ci-math_classes stage: build-3+ library:ci-hott: extends: .ci-template-flambda library:ci-iris: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-autosubst stage: build-2 library:ci-math_classes: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-bignums stage: build-2 library:ci-mathcomp: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb # for Hierarchy Builder stage: build-2 variables: SAVE_BUILD_CI: "1" # for mathcomp_test library:ci-mathcomp_test: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-mczify: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-algebra_tactics: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp - library:ci-mczify stage: build-3+ library:ci-finmap: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-bigenough: extends: .ci-template-flambda needs: - build:edge+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-analysis: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-mathcomp - library:ci-finmap - library:ci-bigenough - plugin:ci-elpi_hb # for Hierarchy Builder stage: build-3+ variables: SAVE_BUILD_CI: "1" # for analysis_stdlib library:ci-analysis_stdlib: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-mathcomp - library:ci-finmap - library:ci-bigenough - library:ci-analysis - plugin:ci-elpi_hb # for Hierarchy Builder - library:ci-stdlib+flambda stage: build-3+ library:ci-neural_net_interp: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-paco: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-itree: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-ext_lib - library:ci-paco stage: build-2 library:ci-itree_io: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-ext_lib - library:ci-paco - library:ci-simple_io - library:ci-itree stage: build-3+ library:ci-simple_io: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-ext_lib stage: build-2 .library:ci-sf: # disabled until https://github.com/DeepSpec/sf/pull/16 can get in / the process for overlays there can be documented extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-stdlib: extends: .ci-template variables: SAVE_BUILD_CI: "1" # for test suite library:ci-stdlib+flambda: extends: .ci-template-flambda variables: CI_TARGETS: "stdlib" SAVE_BUILD_CI: "1" # for test suite library:ci-stdlib_test: extends: .ci-template needs: - build:base - library:ci-stdlib stage: build-2 library:ci-stdlib_doc: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda stage: build-2 variables: SAVE_BUILD_CI: "1" # for doc:refman:deploy library:ci-tlc: extends: .ci-template needs: - build:base - library:ci-stdlib library:ci-unimath: extends: .ci-template-flambda library:ci-verdi_raft: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-vst: extends: .ci-template-flambda variables: NJOBS: "1" needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-flocq - library:ci-menhir - library:ci-compcert stage: build-3+ timeout: 2h library:ci-deriving: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ library:ci-mathcomp_word: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-2 .library:ci-jasmin: # disabled until repaired extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp - library:ci-mathcomp_word - library:ci-mczify - library:ci-algebra_tactics - library:ci-ext_lib - library:ci-paco - library:ci-itree stage: build-3+ library:ci-http: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp - library:ci-menhir - library:ci-ext_lib - library:ci-simple_io - library:ci-paco - library:ci-itree - library:ci-itree_io - plugin:ci-quickchick stage: build-3+ variables: CI_TARGETS: "ceres parsec json async_test http" # Plugins are by definition the projects that depend on Rocq's ML API plugin:ci-aac_tactics: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-atbr: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-autosubst_ocaml: extends: .ci-template-flambda plugin:ci-itauto: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda allow_failure: true plugin:ci-bignums: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-coinduction: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-coq_dpdgraph: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-coqhammer: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-elpi_hb: extends: .ci-template-flambda needs: - build:edge+flambda variables: CI_TARGETS: "elpi hb" SAVE_BUILD_CI: "1" # for elpi_test and hb_test plugin:ci-elpi_test: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb stage: build-2 plugin:ci-hb_test: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb stage: build-2 plugin:ci-equations: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda variables: SAVE_BUILD_CI: "1" # for equations_test plugin:ci-equations_test: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-equations stage: build-2 plugin:ci-fiat_parsers: extends: .ci-template needs: - build:base - library:ci-stdlib plugin:ci-lean_importer: extends: .ci-template needs: - build:base - library:ci-stdlib plugin:ci-ltac2_compiler: extends: .ci-template plugin:ci-metarocq: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-equations stage: build-2 timeout: 1h 30min plugin:ci-mtac2: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda variables: CI_TARGETS: "unicoq mtac2" plugin:ci-paramcoq: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:ci-perennial: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda plugin:plugin-tutorial: stage: build-0 interruptible: true extends: .auto-use-tags script: - ./configure -prefix "$(pwd)/_install_ci" - make -j "$NJOBS" plugin-tutorial plugin:ci-quickchick: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-ext_lib - library:ci-simple_io - plugin:ci-elpi_hb - library:ci-mathcomp stage: build-3+ variables: SAVE_BUILD_CI: "1" # for quickchick_test plugin:ci-quickchick_test: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-ext_lib - library:ci-simple_io - plugin:ci-elpi_hb - library:ci-mathcomp - plugin:ci-quickchick stage: build-3+ plugin:ci-reduction_effects: extends: .ci-template-flambda plugin:ci-relation_algebra: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp - plugin:ci-aac_tactics stage: build-3+ plugin:ci-rewriter: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda library:ci-riscv_coq: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil stage: build-2 library:ci-rupicola: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - library:ci-coqutil - library:ci-kami - library:ci-riscv_coq - library:ci-bedrock2 stage: build-3+ # Disabled until a new maintainer is available # # plugin:ci-coq_lsp: # extends: .ci-template-flambda # needs: # - build:edge+flambda # - library:ci-stdlib+flambda plugin:ci-vsrocq: extends: .ci-template-flambda plugin:ci-smtcoq: extends: .ci-template needs: - build:base - library:ci-stdlib plugin:ci-stalmarck: extends: .ci-template needs: - build:base - library:ci-stdlib plugin:ci-tactician: extends: .ci-template-flambda plugin:ci-waterproof: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda doc:ci-refman: extends: .ci-template-flambda needs: - build:edge+flambda - library:ci-stdlib+flambda - plugin:ci-elpi_hb - library:ci-mathcomp - library:ci-mczify stage: build-3+ artifacts: paths: - _build/log - _build/default/doc/refman-html - _build/default/doc/refman-pdf pipeline-stats: image: $EDGE_IMAGE extends: .auto-use-tags stage: stats dependencies: [] before_script: [] script: - dev/tools/pipeline-stats.py when: always rocq-9.2.0/.ocp-indent000066400000000000000000000000211516144147600145310ustar00rootroot00000000000000strict_with=auto rocq-9.2.0/CODE_OF_CONDUCT.md000066400000000000000000000001721516144147600152760ustar00rootroot00000000000000# Code of Conduct This project has adopted the [Rocq Code of Conduct](https://rocq-prover.org/policies/code-of-conduct). rocq-9.2.0/CONTRIBUTING.md000066400000000000000000002107471516144147600147430ustar00rootroot00000000000000# Guide to contributing to Rocq # ## Foreword ## As with any documentation, this guide is most useful if it's promptly updated to reflect changes in processes, development tools, or the Rocq ecosystem. If you notice anything inaccurate or outdated, please signal it in a new issue, or fix it in a new pull request. If you find some parts are not sufficiently clear, you may open an issue as well. ## Table of contents ## - [Guide to contributing to Rocq](#guide-to-contributing-to-rocq) - [Foreword](#foreword) - [Table of contents](#table-of-contents) - [Introduction](#introduction) - [Contributing to the ecosystem](#contributing-to-the-ecosystem) - [Asking and answering questions](#asking-and-answering-questions) - [Writing tutorials and blog posts](#writing-tutorials-and-blog-posts) - [Contributing to the wiki](#contributing-to-the-wiki) - [Creating and maintaining Rocq packages](#creating-and-maintaining-rocq-packages) - [Distribution of Rocq packages](#distribution-of-rocq-packages) - [Support for plugin and library authors](#support-for-plugin-and-library-authors) - [Standard libraries](#standard-libraries) - [Maintaining existing packages in Rocq-community](#maintaining-existing-packages-in-rocq-community) - [Contributing to the editor support packages](#contributing-to-the-editor-support-packages) - [Contributing to the website or the package archive](#contributing-to-the-website-or-the-package-archive) - [Other ways of creating content](#other-ways-of-creating-content) - [Issues](#issues) - [Reporting a bug, requesting an enhancement](#reporting-a-bug-requesting-an-enhancement) - [Beta testing](#beta-testing) - [Helping triage existing issues](#helping-triage-existing-issues) - [Code changes](#code-changes) - [Using GitHub pull requests](#using-github-pull-requests) - [Fixing bugs and performing small changes](#fixing-bugs-and-performing-small-changes) - [Proposing large changes: Rocq RFCs](#proposing-large-changes-rocq-rfcs) - [Seeking early feedback on work-in-progress](#seeking-early-feedback-on-work-in-progress) - [Taking feedback into account](#taking-feedback-into-account) - [Understanding automatic feedback](#understanding-automatic-feedback) - [Test-suite failures](#test-suite-failures) - [Linter failures](#linter-failures) - [Plugin failures](#plugin-failures) - [Library failures](#library-failures) - [Understanding reviewers' feedback](#understanding-reviewers-feedback) - [Fixing your branch](#fixing-your-branch) - [Improving the official documentation](#improving-the-official-documentation) - [Becoming a maintainer](#becoming-a-maintainer) - [Reviewing pull requests](#reviewing-pull-requests) - [Collaborating on a pull request](#collaborating-on-a-pull-request) - [Merging pull requests](#merging-pull-requests) - [Additional notes for pull request reviewers and assignees](#additional-notes-for-pull-request-reviewers-and-assignees) - [Joining / leaving maintainer teams](#joining--leaving-maintainer-teams) - [Core development team](#core-development-team) - [Release management](#release-management) - [Packaging Rocq](#packaging-rocq) - [Additional resources](#additional-resources) - [Developer documentation](#developer-documentation) - [Where to find the resources](#where-to-find-the-resources) - [Building Rocq](#building-rocq) - [Continuous integration](#continuous-integration) - [Restarting failed jobs](#restarting-failed-jobs) - [Code owners, issue and pull request templates](#code-owners-issue-and-pull-request-templates) - [Style guide](#style-guide) - [OCaml resources](#ocaml-resources) - [Git documentation, tips and tricks](#git-documentation-tips-and-tricks) - [GitHub documentation, tips and tricks](#github-documentation-tips-and-tricks) - [Watching the repository](#watching-the-repository) - [Draft pull requests](#draft-pull-requests) - [Turning a PR into draft mode](#turning-a-pr-into-draft-mode) - [GitLab documentation, tips and tricks](#gitlab-documentation-tips-and-tricks) - [Merge script dependencies](#merge-script-dependencies) - [Coqbot](#coqbot) - [Online forum and chat to talk to developers](#online-forum-and-chat-to-talk-to-developers) - [Rocq calls](#rocq-calls) - [Rocq remote working groups](#rocq-remote-working-groups) - [Rocq Users and Developers Workshops](#rocq-users-and-developers-workshops) ## Introduction ## Thank you for your interest in contributing to Rocq! There are many ways to contribute, and we appreciate all of them. People often begin by making small contributions, and contributions to the ecosystem, before working their way up incrementally to the core parts of the system, and start to propose larger changes, or take an active role in maintaining the system. So this is the way this contributing guide is organized. However, it is by no means necessary that you go through these steps in this order. Feel free to use this guide as a reference and quickly jump to the part that is most relevant to you at the current time. We want to make sure that contributing to Rocq is a fun and positive experience for everyone, so please make sure you read and abide by our [Code of Conduct][Code-of-conduct]. ## Contributing to the ecosystem ## In this section, we present all the ways to contribute to Rocq outside of the Rocq repository itself. ### Asking and answering questions ### One very important way of contributing is by asking and answering questions, in order to create a body of easily-browsable, problem-oriented, additional documentation. There are many platforms for this purpose: - Our [Zulip chat][Zulip], which contains a main "#Rocq users" stream, but also many other streams dedicated to specific Rocq packages, such as Equations, MathComp, etc. - Our [Discourse forum][Discourse], which contains a main "Using Rocq" category, but also categories dedicated to asking questions in other languages than English. They have yet to find their public, so do not hesitate to advertise them to people you know who might not be at ease with English. - The [Proof Assistants Stack Exchange][Proof-Assistants-SE], a Q&A site for users of proof assistants, including the Rocq Prover. - Other [Stack Exchange][Stack-Exchange] sites, and particularly [Stack Overflow][Stack-Overflow], receive questions about Rocq. Questions asked anywhere on Stack Exchange with the `coq` tag are automatically relayed to Zulip in a [dedicated topic][Stack-Exchange-to-Zulip]. Other active places to answer questions include the [Coq-Club][] mailing list, the [Coq IRC channel][IRC], the [/r/Coq subreddit][Reddit], etc. ### Writing tutorials and blog posts ### Writing about the Rocq Prover, in the form of tutorials or blog posts, is also a very important contribution. In particular, it can help new users get interested in Rocq, and learn about it, and existing users learn about advanced features. The [reference manual][refman] is not suited for learning Rocq, but we now also provide short, action-oriented tutorials as part of our official resources. See the [Platform Docs][Platform-docs] repository for more information. The Rocq website has a page listing known [books][Rocq-books], including non-English books, which you can expand through a pull request on the [Rocq website repository][Rocq-website-repository]. Blog posts from the Rocq ecosystem are aggregated on the [Rocq Planet][Rocq-planet] page. If your blog is mainly about Rocq, you can contribute by adding it to the list. ### Contributing to the wiki ### Rocq's [wiki][] is an informal source of additional documentation which anyone with a GitHub account can edit directly. In particular, it contains the Rocq [FAQ][] which has not seen so many updates in the recent years. You should feel free to fix it, expand it, and even refactor it (if you are not sure if some changes would be welcome, you can open an issue to discuss them before performing them). People who watch the Rocq repository will see recent wiki edits in their GitHub feed. It is recommended to review them *a posteriori* to check no mistake was introduced. The wiki is also a standard git repository, so people can follow the changes using any standard git tool. Rocq's wiki is formatted using GitHub's flavored Markdown, with some wiki-specific extensions. See: - [GitHub's Markdown guide][GitHub-markdown] - [GitHub's wiki extensions][GitHub-wiki-extensions] ### Creating and maintaining Rocq packages ### *Note: this sub-section is about packages extending Rocq, such as plugins or libraries. A different, but also very valuable, contribution is to package Rocq for your preferred package manager (see [Packaging Rocq](#packaging-rocq)).* Sharing reusable assets in the form of new libraries, plugins, and tools is great so that others can start building new things on top. Having an extensive and healthy package ecosystem is key to the success of Rocq. #### Distribution of Rocq packages #### You can distribute your library or plugin through the [Rocq package index][Rocq-package-index]. Important packages and tools can be advertised on the [Awesome Coq][Awesome-Coq] list. Some packages are distributed along Rocq, within the [Rocq Platform][Rocq-Platform]. Check the Platform's charter if you consider adding your package to it. #### Support for plugin and library authors #### You can find advice and best practices about maintaining a Rocq project on the [Rocq-community wiki][rocq-community-wiki]. Learn how to write a Rocq plugin, and about best practices, in the Rocq [plugin tutorial][plugin-tutorial]. This tutorial is still a work in progress, so do not hesitate to expand it, or ask questions. If you want quick feedback on best practices, or how to talk to the Rocq API, a good place to hang out is the [Rocq devs & plugin devs stream][Zulip-dev] of our Zulip chat. Finally, we strongly encourage authors of plugins to submit their plugins to join Rocq's continuous integration (CI) early on. Indeed, the Rocq API gets continuously reworked, so this is the best way of ensuring your plugin stays compatible with new Rocq versions, as this means Rocq developers will fix your plugin for you. Learn more about this in the [CI README (user part)][CI-README-users]. Pure Rocq libraries are also welcome to join Rocq's CI, especially if they test underused / undertested features. #### Standard libraries #### There are many general purpose Rocq libraries, so before you publish yours, consider whether you could contribute to an existing one instead (either the official [standard library][standard-library], or one of the many [alternative standard libraries][other-standard-libraries]). #### Maintaining existing packages in Rocq-community #### Some Rocq packages are not maintained by their initial authors anymore (for instance if they've moved on to new jobs or new projects) even if they were useful, or interesting. The Rocq-community organization is a place for volunteers to take over the maintenance of such packages. If you want to contribute by becoming a maintainer, there is [a list of packages waiting for a maintainer][rocq-community-maintainer-wanted]. You can also propose a package that is not listed. Find out more about Rocq-community in [the manifesto's README][rocq-community-manifesto]. ### Contributing to the editor support packages ### Besides Rocqide, whose sources are available in this repository, and to which you are welcome to contribute, there are a number of alternative user interfaces for the Rocq Prover, more often as an editor support package. Here are the URLs of the repositories of the various editor support packages: - Proof-General (Emacs major mode) - Company-coq (Emacs minor mode) - Coqtail (Vim) - VsCoq (VsCode) And here are alternative user interfaces to be run in the web browser: - JsCoq (Coq executed in your browser) - Jupyter kernel for Coq Each of them has their own contribution process. ### Contributing to the website or the package archive ### The website and the package archive have their own repositories: - - You can contribute to them by using issues and pull requests on these repositories. These repositories should get their own contributing guides, but they don't have any at the time of writing this. ### Other ways of creating content ### There are many other ways of creating content and making the Rocq community thrive, including many which we might not have thought about. Feel free to add more references / ideas to this sub-section. You can post about Rocq on social media, give talks about Rocq both in academic and non-academic venues (such as developer conferences). [Codewars][] is a platform where people can try to solve some programming challenges that were proposed by other community members. Rocq is supported and the community is eager to get more challenges. ## Issues ## ### Reporting a bug, requesting an enhancement ### Bug reports are enormously useful to identify issues with Rocq; we can't fix what we don't know about. To report a bug, please open an issue in the [Rocq issue tracker][Rocq-issue-tracker] (you'll need a GitHub account). You can file a bug for any of the following: - An anomaly. These are always considered bugs, so the Rocq Prover will even ask you to file a bug report! - An error you didn't expect. If you're not sure whether it's a bug or intentional, feel free to file a bug anyway. We may want to improve the documentation or error message. - Missing or incorrect documentation. It's helpful to track where the documentation should be improved, so please file a bug if you can't find or don't understand some bit of documentation. - An error message that wasn't as helpful as you'd like. Bonus points for suggesting what information would have helped you. - Bugs in Rocqide should also be filed in the [Rocq issue tracker][Rocq-issue-tracker]. Bugs in the Emacs plugin should be filed against [ProofGeneral][ProofGeneral-issues], or against [company-coq][company-coq-issues] if they are specific to company-coq features. It would help if you search the existing issues before reporting a bug. This can be difficult, so consider it extra credit. We don't mind duplicate bug reports. If unsure, you are always very welcome to ask on our [Discourse forum][Discourse] or [Zulip chat][Zulip] before, after, or while writing a bug report. It is better if you can test that your bug is still present in the current testing or development version of the Rocq Prover (see the [next sub-section](#beta-testing)) before reporting it, but if you can't, it should not discourage you from reporting it. When it applies, it's extremely helpful for bug reports to include sample code, and much better if the code is self-contained and complete. It's not necessary to minimize your bug or identify precisely where the issue is, since someone else can often do this if you include a complete example. We tend to include the code in the bug description itself, but if you have a very large input file then you can add it as an attachment. If you want to minimize your bug (or help minimize someone else's) for more extra credit, then you can use the [Rocq bug minimizer][JasonGross-coq-tools] (specifically, the bug minimizer is the `find-bug.py` script in that repo). Nowadays, the easiest way to use the Rocq bug minimizer is to call it through `@coqbot`, as documented [here][coqbot-minimize]. ### Beta testing ### The Rocq Prover gets a new major release about every six months, which is then distributed through the [Rocq Platform][Rocq-Platform]. New major versions of Rocq are first made available for beta-testing, before being declared stable and the new default version of the Rocq Platform. You can help make by testing the beta version, and trying to port your projects to it. You should report any bug you notice, but also any change of behavior that is not documented in the changelog. Then Rocq developers will be able to check if what you reported is a regression that needs to be fixed, or an expected change that needs to be mentioned in the changelog. You can go even further by using the development version (`master` branch) of Rocq on a day by day basis, and report problems as soon as you notice them. If you wish to do so, the easiest way to install Rocq is through opam (using the `dev` version of the Rocq package, available in the repository) or through [Nix][]. The documentation of the development version is [available online][master-doc], including the [unreleased changelog][unreleased-changelog]. ### Helping triage existing issues ### The Rocq Prover has too many bug reports for its core developers alone to manage. You can help a lot by: - confirming that reported bugs are still active with the current version of the Rocq Prover; - determining if the bug is a regression (new, and unexpected, behavior from a recent Rocq version); - more generally, by reproducing a bug, on another system, configuration, another version of Rocq, and by documenting what you did; - giving a judgement about whether the reported behavior is really a bug, or is expected but just improperly documented, or expected and already documented; - producing a trace if it is relevant and you know how to do it; - producing another example exhibiting the same bug, or minimizing the initial example using the bug minimizer mentioned above; - using `git bisect` to find the commit that introduced a regression; - fixing the bug if you have an idea of how to do so (see the [following section](#code-changes)). Once you have some experience with the Rocq issue tracker, you can request to join the **@rocq-prover/contributors** team (any member of the **@rocq-prover/core** team can give you access using [this link][add-contributor]). Being in this team will grant you the following access: - **Updating labels:** every open issue and pull request should ideally get one or several `kind:` and `part:` labels. In particular, valid issues should generally get either a `kind: bug` (the reported behavior can indeed be considered a bug, this can be completed with the `kind: anomaly`, and `kind: regression` labels), `kind: documentation` (e.g. if a reported behavior is expected but improperly documented), `kind: enhancement` (a request for enhancement of an existing feature), or `kind: feature` label (an idea for a new feature). - **Creating new labels:** if you feel a `part:` label is missing, do not hesitate to create it. If you are not sure, you may discuss it with other contributors and developers on [Zulip][Zulip-dev] first. - **Closing issues:** if a bug cannot be reproduced anymore, is a duplicate, or should not be considered a bug report in the first place, you should close it. When doing so, try putting an appropriate `resolved:` label to indicate the reason. If the bug has been fixed already, and you know in which version, you can add a milestone to it, even a milestone that's already closed, instead of a `resolved:` label. When closing a duplicate issue, try to add all the additional info that could be gathered to the original issue. - **Editing issue titles:** you may want to do so to better reflect the current understanding of the underlying issue. - **Editing comments:** feel free to do so to fix typos and formatting only (in particular, some old comments from the Bugzilla era or before are not properly formatted). You may also want to edit the OP's initial comment (a.k.a. body of the issue) to better reflect the current understanding of the issue, especially if the discussion is long. If you do so, only add to the original comment, and mark it clearly with an `EDITED by @YourNickname:`. - **Hiding comments:** when the discussion has become too long, this can be done to hide irrelevant comments (off-topic, outdated or resolved sub-issues). - **Deleting things:** please don't delete any comment or issue, our policy doesn't allow for comments to be deleted, unless done by the community moderators. You should hide them instead. An audit log is available to track deleted items if needed (but does not allow recovering them). However, and contrary to most other repositories, it will not give you the ability to push new branches or tags to the repository. This is disabled because we prefer to use forks to work on feature branches. Yet to be fully specified: use of priority, difficulty, `help wanted`, and `good first issue` labels, milestones, assignments, and GitHub projects. ## Code changes ## ### Using GitHub pull requests ### If you want to contribute a documentation update, bug fix or feature yourself, pull requests (PRs) on the [GitHub repository][rocq-repository] are the way to contribute directly to the Rocq Prover implementation (all changes, even the smallest changes from core developers, go through PRs). You will need to create a fork of the repository on GitHub and push your changes to a new "topic branch" in that fork (instead of using an existing branch name like `master`). PRs should always target the `master` branch. Make sure that your copy of this branch is up-to-date before starting to do your changes, and that there are no conflicts before submitting your PR. If you need to fix conflicts, we generally prefer that you rebase your branch on top of `master`, instead of creating a merge commit. If you are not familiar with `git` or GitHub, Sections [Git documentation, tips and tricks](#git-documentation-tips-and-tricks), and [GitHub documentation, tips and tricks](#github-documentation-tips-and-tricks), should be helpful (and even if you are, you might learn a few tricks). Once you have submitted your PR, it may take some time to get feedback, in the form of reviews from maintainers, and test results from our continuous integration system. Our code owner system will automatically request reviews from relevant maintainers. Then, one maintainer should self-assign the PR (if that does not happen after a few days, feel free to ping the maintainers that were requested a review). The PR assignee will then become your main point of contact for handling the PR: they should ensure that everything is in order and merge when it is the case (you can ping them if the PR is ready from your side but nothing happens for a few days). After your PR is accepted and merged, it may get backported to a release branch if appropriate, and will eventually make it to a release. You do not have to worry about this, it is the role of the assignee and the release manager to do so (see Section [Release management](#release-management)). The milestone should give you an indication of when to expect your change to be released (this could be several months after your PR is merged). That said, you can start using the latest Rocq `master` branch to take advantage of all the new features, improvements, and fixes. #### Fixing bugs and performing small changes #### Before fixing a bug, it is best to check that it was reported before: - If it was already reported and you intend to fix it, self-assign the issue (if you have the permission), or leave a comment marking your intention to work on it (and a contributor with write-access may then assign the issue to you). - If the issue already has an assignee, you should check with them if they still intend to work on it. If the assignment is several weeks, months, or even years (!) old, there are good chances that it does not reflect their current priorities. - If the bug has not been reported before, it can be a good idea to open an issue about it, while stating that you are preparing a fix. The issue can be the place to discuss about the bug itself while the PR will be the place to discuss your proposed fix. It is generally a good idea to add a regression test to the test-suite. See the test-suite [README][test-suite-README] for how to do so. Small fixes do not need any documentation, or changelog update. New, or updated, user-facing features, and major bug fixes do. See the [corresponding section](#improving-the-official-documentation) for on how to contribute to the documentation, and the README in [`doc/changelog`][user-changelog] for how to add a changelog entry. #### Proposing large changes: Rocq RFCs #### Please refrain to open very large PRs without discussing them first. Indeed, you should be aware that the larger the change, the higher the chances it will take very long to review, and possibly never get merged. So it is recommended that before spending a lot of time coding, you seek feedback from maintainers to see if your change would be supported, and if they have recommendations about its implementation. You can do this informally by opening an issue, or more formally by producing a design document as a [RFCs][RFCs]. Another recommendation is that you do not put several unrelated changes in the same PR (even if you produced them together). In particular, make sure you split bug fixes into separate PRs when this is possible. More generally, smaller-sized PRs, or PRs changing fewer components, are more likely to be reviewed and merged promptly. #### Seeking early feedback on work-in-progress #### You should always feel free to open your PR before the documentation, changelog entry and tests are ready. That's the purpose of the checkboxes in the PR template which you can leave unticked. This can be a way of getting reviewers' approval before spending time on writing the documentation (but you should still do it before your PR can be merged). If even the implementation is not ready but you are still looking for early feedback on your code changes, please use the [draft PR](#draft-pull-requests) mechanism. If you are looking for feedback on the design of your change, rather than on its implementation, then please refrain from opening a PR. You may open an issue to start a discussion, or create a [Rocq RFC][RFCs] if you have a clear enough view of the design to write a document about it. ### Taking feedback into account ### #### Understanding automatic feedback #### When you open or update a PR, you get automatically some feedback: we have a bot whose job will be to push a branch to our GitLab mirror to run some continuous integration (CI) tests. The tests will run on a commit merging your branch with the base branch, so if there is a conflict and this merge cannot be performed automatically, the bot will put a `needs: rebase` label, and the tests won't run. Otherwise, a suite of tests will be run on GitLab, plus some additional tests on GitHub Actions for Windows and macOS compatibility. The complete suite of tests is no longer run by default to save resources. But it is still required before merging a PR, so this is why the bot will put a `needs: full CI` label if it has only run the lightweight tests. If you are a member of **@rocq-prover/contributors**, you can request a full run of the CI by putting the `request: full CI` label before pushing to your PR branch, or by commenting `@coqbot: run full CI` after having pushed. (In case you need to re-run the tests, e.g., because the results are outdated, you can also request the bot to do so by commenting `@coqbot: run full CI` or `@coqbot: run light CI`. If you comment `@coqbot: run CI`, the bot will decide whether to run the full or the lightweight tests based on the presence of the `request: full CI` label.) If a test fails on GitLab, you will see in the GitHub PR interface, both the failure of the whole pipeline, and of the specific failed job. Most of these failures indicate problems that should be addressed, but some can still be due to synchronization issues out of your control. In particular, if you get a failure in one of the tested plugins but you didn't change the Rocq API, it is probably a transient issue and you shouldn't have to worry about it. In case of doubt, ask the reviewers. To re-run a specific failed job, you can use the Re-run jobs button in the GitHub interface (if you are a member of **@rocq-prover/contributors**). This won't create a new merge commits with the base branch, so if you need this, you can use the `@coqbot: run ... CI` commands instead. ##### Test-suite failures ##### If you broke the test-suite, you should get many failed jobs, because the test-suite is run multiple times in various settings. You should get the same failure locally by running `make test-suite`. It's helpful to run this locally and ensure the test-suite is not broken before submitting a PR as this will spare a lot of runtime on distant machines. To learn more about the test-suite, you should refer to its [README][test-suite-README]. ##### Linter failures ##### We have a linter that checks a few different things: - **Every commit can build.** This is an important requirement to allow the use of `git bisect` in the future. It should be possible to build every commit, and in principle even the test-suite should pass on every commit (but this isn't tested in CI because it would take too long). A good way to test this locally is to use `git rebase master --exec "make check"`. - **No tabs or end-of-line spaces on updated lines**. We are trying to get rid of all tabs and all end-of-line spaces from the code base (except in some very special files that need them). This checks not only that you didn't introduce new ones, but also that updated lines are clean (even if they were there before). You can avoid worrying about tabs and end-of-line spaces by installing our [pre-commit git hook][git-hook], which will fix these issues at commit time. Running `./configure` once will install this hook automatically unless you already have a pre-commit hook installed. If you are encountering these issues nonetheless, you can fix them by rebasing your branch with `git rebase --whitespace=fix`. - **All files should end with a single newline**. See the section [Style guide](#style-guide) for additional style recommendations. - **Documented syntax is up-to-date**. If you update the grammar, you should run `make doc_gram_rsts` to update the documented syntax. You should then update the text describing the syntax in the documentation and commit the changes. In some cases, the documented syntax is edited to make the documentation more readable. In this case, you may have to edit `doc/tools/docgram/common.edit_mlg` to make `doc_gram_rsts` pass. See [doc_grammar's README][doc_gram] for details. Note that in the case where you added new commands or tactics, you will have to manually insert them in the documentation, the tool won't do that for you, although it should detect in most cases if you have forgotten to add documentation for your new command or tactic, or if the documentation is not consistent with the parser. - **.opam files are up to date**. Rocq's `*.opam` files are generated automatically from metadata in `dune-project`. If the meta-data becomes out of sync, the linter will complain. This can be fixed doing `dune build *.opam` at the root of Rocq's repository. You may run the linter yourself with `dev/lint-repository.sh`. ##### Plugin failures ##### If you did change the Rocq API, then you may have broken a plugin. After ensuring that the failure comes from your change, you will have to provide a fix to the plugin, and the PR assignee will have to ensure that this fix is merged in the plugin simultaneously with your PR on the Rocq repository. If your changes to the API are not straightforward, you should also document them in `dev/doc/changes.md`. The [CI README (developer part)][CI-README-developers] contains more information on how to fix plugins, test and submit your changes, and how you can anticipate the results of the CI before opening a PR. ##### Library failures ##### Such a failure can indicate either a bug in your branch, or a breaking change that you introduced voluntarily. All such breaking changes should be properly documented in the [user changelog][user-changelog]. Furthermore, a backward-compatible fix should be found, properly documented in the changelog when non-obvious, and this fix should be merged in the broken projects *before* your PR to the Rocq repository can be. Note that once the breaking change is well understood, it should not feel like it is your role to fix every project that is affected: as long as reviewers have approved and are ready to integrate your breaking change, you are entitled to (politely) request project authors / maintainers to fix the breakage on their own, or help you fix it. Obviously, you should leave enough time for this to happen (you cannot expect a project maintainer to allocate time for this as soon as you request it) and you should be ready to listen to more feedback and reconsider the impact of your change. If you need help figuring out why your PR is breaking a tested project, you may consider requesting automatic minimization of the failure with the bot. In principle, the bot should automatically propose this option to you if it is available (it needs to detect a failure in a Rocq file and it needs to confirm that the failure was not already present in the base branch to propose to run the minimization process). #### Understanding reviewers' feedback #### The reviews you get are highly dependent on the kind of changes you did. In any case, you should always remember that reviewers are friendly volunteers that do their best to help you get your changes in (and should abide by our [Code of Conduct][Code-of-Conduct]). But at the same time, they try to ensure that code that is introduced or updated is of the highest quality and will be easy to maintain in the future, and that's why they may ask you to perform small or even large changes. If you need a clarification, do not hesitate to ask. Here are a few labels that reviewers may add to your PR to track its status. In general, this will come in addition to comments from the reviewers, with specific requests. - [needs: fixing][needs-fixing] indicates the PR needs a fix, as discussed in the comments. - [needs: documentation][needs-documentation] indicates the PR introduces changes that should be documented before it can be merged. This label may be used to reflect that the corresponding checkbox is not yet checked in the PR template (so that we don't forget when we intend to merge the PR). - [needs: changelog entry][needs-changelog] indicates the PR introduces changes that should be documented in the [user changelog][user-changelog]. Similarly to the previous label, this may be used to reflect that the corresponding checkbox is not yet checked in the PR template. - [needs: test-suite update][needs-test-suite] indicates that tests should be added to the test-suite / modified to ensure that the changes are properly tested. Similarly to the previous two labels, this may be used to reflect that the corresponding checkbox is not yet checked in the PR template. - [needs: benchmarking][needs-benchmarking] and [needs: testing][needs-testing] indicate the PR needs testing beyond what the test suite can handle. For example, performance benchmarking is currently performed with a different infrastructure ([documented in the wiki][Benchmarking]). Unless some followup is specifically requested, you aren't expected to do this additional testing. More generally, such labels should come with a description that should allow you to understand what they mean. #### Fixing your branch #### If you have changes to perform before your PR can be merged, you might want to do them in separate commits at first to ease the reviewers' task, but we generally appreciate that they are squashed with the commits that they fix before merging. This is especially true of commits fixing previously introduced bugs or failures. ### Improving the official documentation ### The documentation is usually a good place to start contributing, because you can get used to the pull request submitting and review process, without needing to learn about the code source of Rocq at the same time. The official documentation is formed of two components: - the [reference manual][refman], - the [documentation of the prelude][stdlib-doc]. The sources of the reference manual are located in the [`doc/sphinx`][refman-sources] directory. They are written in rst (Sphinx) format with some Rocq-specific extensions, which are documented in the [README][refman-README] in the above directory. This README was written to be read from begin to end. As soon as your edits to the documentation are more than changing the textual content, we strongly encourage you to read this document. The documentation of the prelude is generated with [rocq doc][rocqdoc-documentation] from the comments in the sources of the standard library. The [README in the `doc` directory][doc-README] contains more information about the documentation's build dependencies, and the `make` targets. You can browse through the list of open documentation issues using the [kind: documentation][kind-documentation] label, or the [user documentation GitHub project][documentation-github-project] (you can look in particular at the "Writing" and "Fixing" columns). ## Becoming a maintainer ## ### Reviewing pull requests ### You can start reviewing PRs as soon as you feel comfortable doing so (anyone can review anything, although some designated reviewers will have to give a final approval before a PR can be merged, as is explained in the next sub-section). Reviewers should ensure that the code that is changed or introduced is in good shape and will not be a burden to maintain, is unlikely to break anything, or the compatibility-breakage has been identified and validated, includes documentation, changelog entries, and test files when necessary. Reviewers can use `needs:` labels, or change requests to further emphasize what remains to be changed before they can approve the PR. Once reviewers are satisfied (regarding the part they reviewed), they should formally approve the PR, possibly stating what they reviewed. That being said, reviewers should also make sure that they do not make the contributing process harder than necessary: they should make it clear which comments are really required to perform before approving, and which are just suggestions. They should strive to reduce the number of rounds of feedback that are needed by posting most of their comments at the same time. If they are opposed to the change, they should clearly say so from the beginning to avoid the contributor spending time in vain. They should avoid making nitpick comments when in fact, they have larger concerns that should be addressed first (these larger concerns should then be made very clear). Furthermore, when reviewing a first contribution (GitHub highlights first-time contributors), be extra careful to be welcoming, whatever the decision on the PR is. When approving a PR, consider thanking the newcomer for their contribution, even if it is a very small one (in cases where, if the PR had come from a regular contributor, it would have felt OK to just merge it without comment). When rejecting a PR, take some extra steps to explain the reasons, so that it doesn't feel hurtful. Don't hesitate to still thank the contributor and possibly redirect them to smaller tasks that might be more appropriate for a newcomer. #### Collaborating on a pull request #### Beyond making suggestions to a PR author during the review process, you may want to collaborate further by checking out the code, making changes, and pushing them. There are two main ways of doing this: - **Pull requests on pull requests:** You can checkout the PR branch (GitHub provides the link to the remote to pull from and the branch name on the top and the bottom of the PR discussion thread), checkout a new personal branch from there, do some changes, commit them, push to your fork, and open a new PR on the PR author's fork. - **Pushing to the PR branch:** If the PR author has not unchecked the "Allow edit from maintainers" checkbox, and you have write-access to the repository (i.e. you are in the **@rocq-prover/contributors** team), then you can also push (and even force-push) directly to the PR branch, on the main author's fork. Obviously, don't do it without coordinating with the PR author first (in particular, in case you need to force-push). When several people have co-authored a single commit (e.g. because someone fixed something in a commit initially authored by someone else), this should be reflected by adding ["Co-authored-by:" tags][GitHub-co-authored-by] at the end of the commit message. The line should contain the co-author name and committer e-mail address. ### Merging pull requests ### Our [CODEOWNERS][] file associates a team of maintainers to each component. When a PR is opened (or a [draft PR](#draft-pull-requests) is marked as ready for review), GitHub will automatically request reviews to maintainer teams of affected components. As soon as it is the case, one available member of a team that was requested a review should self-assign the PR, and will act as its shepherd from then on. The PR assignee is responsible for making sure that all the proposed changes have been reviewed by relevant maintainers (at least one reviewer for each component that is significantly affected), that change requests have been implemented, that CI is passing, and eventually will be the one who merges the PR. The PR assignee may use their own judgement to decide to merge a PR that has not received reviews from all maintainers of affected components, depending on how large or controversial the changes to these components are. It is also admissible to have an assignee who is not a maintainer of any of the affected components, in case relevant maintainers are not available, and as long as the assignee is a member of the **@rocq-prover/pushers** team and is able to understand the changes in the PR. *If you have already frequently contributed to a component, we would be happy to have you join one of the maintainer teams.* See the [section below](#joining--leaving-maintainer-teams) on joining / leaving maintainer teams. The complete list of maintainer teams is available [here][rocq-pushers] (link only accessible to people who are already members of the Rocq Prover organization, however, this list is also used to [generate](https://github.com/rocq-prover/rocq-prover.org/tree/main/data#github-teams) the various [Rocq team][rocq-team] subpages on the website). #### Additional notes for pull request reviewers and assignees #### - NEVER USE GITHUB'S MERGE BUTTON. Instead, you should either: - post a comment containing "@coqbot: merge now"; This is the recommended method and more convenient than the previous script based method (see next bullet) e.g. for developers who do not have a GPG key and for when you do not have access to a console. "coqbot" will **not** check CI status - it is expected that the merger does this manually upfront, but coqbot will deny the merge with an error response in the following cases: - no assignee - no milestone - no `kind` label - left-over `needs` labels - you try to merge a PR which you authored (this is decided by the creator of the PR - reviewers can still do minor changes and merge) - alternatively run the [`dev/tools/merge-pr.sh`][merge-pr] script; Since "coqbot" this method is deprecated with a few exceptions, like merges to release branches - which only release managers do. This requires having configured gpg with git. - PR authors or co-authors cannot review, self-assign, or merge the PR they contributed to. However, reviewers may push small fixes to the PR branch to facilitate the PR integration. - PRs are merged when there is consensus. Consensus is defined by an explicit approval from at least one maintainer for each component that is significantly affected and an absence of dissent. As soon as a developer opposes a PR, it should not be merged without being discussed first (usually in a call or working group). - Sometimes (especially for large or potentially controversial PRs), it is a good practice to announce the intent to merge, one or several days in advance, when unsure that everyone had a chance to voice their opinion, or to finish reviewing the PR. - Only PRs targeting the `master` branch can be merged by a maintainer. For PRs targeting an actively maintained release branch, the assignee should always be the release manager. For older release branches, any **@rocq-prover/core** member can merge any PR (but such PRs should be limited to fixing build issues). - Before merging, the assignee must also select a milestone for the PR (see also Section [Release management](#release-management)). - To know which files you are a maintainer of, you can look for black shields icons in the "Files changed" tab. ![shield icon](dev/doc/shield-icon.png) - When a PR has [overlays][user-overlays], then: - the overlays that are backward-compatible (normally the case for overlays fixing Rocq code) should have been merged *before* the PR can be merged; it might be a good idea to ask the PR author to remove the overlay information from the PR to get a fresh CI run and ensure that all the overlays have been merged; the PR assignee may also push a commit removing the overlay information (in that case the assignee is not considered a co-author, hence no need to change the assignee) - the overlays that are not backward-compatible (normally only the case for overlays fixing OCaml code) should be merged *just after* the PR has been merged (and thus the assignee should ping the maintainers of the affected projects to ask them to merge the overlays). #### Joining / leaving maintainer teams #### We are always happy to have more people involved in the PR reviewing and merging process, so do not hesitate to propose yourself if you already have experience on a component. Maintainers can leave teams at any time (and core members can also join any team where they feel able to help) but you should always announce it to other maintainers when you do join or leave a team. ### Core development team ### The core developers are the active developers with a lengthy and significant contribution track record. They are the ones with admin powers over the Rocq organization, and the ones who take part in [votes][voting-process] in case of conflicts to take a decision (rare). One of them is designated as a development coordinator, and has to approve the changes in the core team membership (until we get a more formal joining and leaving process). The core developers are the members of the **@rocq-prover/core** team ([member list][rocq-core] only visible to the Rocq organization members because of a limitation of GitHub). They are also listed on the [Rocq Team page][rocq-team]. ## Release management ## The Rocq Prover major release cycles generally span about six months, with about 4-5 months of development, and 1-2 months of stabilization / release candidates. The release manager (RM) role is a rolling position among core developers. The [release plan][release-plan] is published on the wiki. Development of new features, refactorings, deprecations and clean-ups always happens on `master`. Stabilization starts by branching (creating a new `v...` release branch from the current `master`), which marks the beginning of a feature freeze (new features will continue to be merged into `master` but won't make it for the upcoming major release, but only for the next one). After branching, most changes are introduced in the release branch by a backporting process. PR authors and assignee can signal a desire to have a PR backported by selecting an appropriate milestone. Most of the time, the choice of milestone is between two options: the next major version that has yet to branch from `master`, or the next version (rc, final, or patch-level release) of the active release branch. In the end, it is the RM who decides whether to follow or not the recommendation of the PR assignee, and who backports PRs to the release branch. Very specific changes that are only relevant for the release branch and not for the `master` branch can result in a PR targeting the release branch instead of `master`. In this case, the RM is the only one who can merge the PR, and they may even do so if they are the author of the PR. Examples of such PRs include bug fixes to a feature that has been removed in `master`, and PRs from the RM changing the version number in preparation for the next release. Some automation is in place to help the RM in their task: a GitHub project is created at branching time to manage PRs to backport; when a PR is merged in a milestone corresponding to the release branch, our bot will add this PR in a "Request inclusion" column in this project; the RM can browse through the list of PRs waiting to be backported in this column, possibly reject some of them by simply removing the PR from the column (in which case, the bot will update the PR milestone), and proceed to backport others; when a backported PR is pushed to the release branch, the bot moves the PR from the "Request inclusion" column to a "Shipped" column. More information about the RM tasks can be found in the [release process checklist][RM-checklist]. ### Packaging Rocq ### The RM role does not include the task of making Rocq available through the various package managers out there: several contributors (most often external to the development team) take care of this, and we thank them for this. If your preferred package manager does not include the Rocq Prover, it is a very worthy contribution to make it available there. But be careful not to let a package get outdated, as this could lead some users to install an outdated version of Rocq without even being aware of it. Beyond packaging the Rocq Prover itself, you might want to consider packaging the rest of Rocq packages available to users through the [Rocq Platform][Rocq-Platform]. In this case, it would be helpful if you try to favor the same versions as in the Rocq Platform. This [Repology page][repology-coq] lists the versions of the Rocq Prover which are packaged in many repositories, although it is missing information on some repositories, like opam. The Windows and macOS installers are created as part of the preparation of the Rocq Platform. ## Additional resources ## ### Developer documentation ### #### Where to find the resources #### - You can find developer resources in the `dev` directory, and more specifically developer documentation in `dev/doc`. The [README][dev-README] in the `dev` directory lists what's available. For example, [`dev/doc/README.md`][dev-doc-README] is a beginner's guide to hacking Rocq, and documentation on debugging Rocq can be found in [`dev/doc/debugging.md`][debugging-doc]. - When it makes sense, the documentation is kept even closer to the sources, in README files in various directories (e.g. the test-suite [README][test-suite-README] or the refman [README][refman-README]). - Documentation of the Rocq API is written directly in comments in `.mli` files. You can browse it on [the Rocq website][api-doc], or rebuild it locally (`make apidoc`, requires `odoc` and `dune`). - A plugin tutorial is located in [`doc/plugin_tutorial`][plugin-tutorial]. - The Rocq [wiki][] contains additional developer resources. #### Building Rocq #### The list of dependencies can be found in the first section of the [`INSTALL.md`](INSTALL.md) file. The Rocq Prover is built using the `dune` build system. Run `make` to get help on the various available targets. Additional documentation can be found in [`dev/doc/build-system.dune.md`][dev-doc-dune], and in [the official Dune documentation][dune-doc]. #### Continuous integration #### Continuous integration (CI) testing is key in ensuring that the `master` branch is kept in a well-functioning state at all times, and that no accidental compatibility breakages are introduced. Our CI is quite extensive since it includes testing many external projects, some of them taking more than an hour to compile. However, you can get partial results much more quickly (when our CI is not overloaded). Nowadays, the full CI is not run by default as already explained in [Understanding automatic feedback](#understanding-automatic-feedback). The main documentation resources on our CI are: - the [README for users, i.e. plugin and library authors][CI-README-users]; - the [README for developers, and contributors][CI-README-developers]; - the README of the [user-overlays][] directory. Preparing an overlay (i.e. a patch to an external project that we test in our CI, to make it compile with the modified version of Rocq in your branch) is a step that everyone goes through at some point. All you need to know to prepare an overlay manually is in the README in the [user-overlays][] directory. You might want to use some additional tooling such as the `make ci-*` targets of `Makefile.ci`, the Nix support for getting the dependencies of the external projects (see the README in [`dev/ci/nix`][dev-ci-nix], and the (so far undocumented) [`dev/tools/create_overlays.sh`][dev-tools-create_overlays.sh] script. More work is to be done on understanding how each developer proceeds to prepare overlays, and propose a simplified and documented procedure. We also have a benchmarking infrastructure, which is documented [on the wiki][Benchmarking]. ##### Restarting failed jobs ##### When CI has a few failures which look spurious, restarting the corresponding jobs is a good way to ensure this was indeed the case. Most failed jobs can be restarted directly from the "Checks" tab on GitHub. In case you need to restart a job on GitLab CI using the GitLab interface, then you should sign into GitLab (this can be done using a GitHub account) and join the [Coq GitLab organization][GitLab-organization]. #### Code owners, issue and pull request templates #### These files can be found in the [`.github`](.github) directory. The templates are particularly useful to remind contributors what information we need for them, and, in the case of PRs, to update the documentation, changelog, and test-suite when relevant. GitHub now supports setting up multiple issue templates, and we could use this to define distinct requirements for various kind of bugs, enhancement and feature requests. #### Style guide #### There exists an [old style guide][old-style-guide] whose content is still mostly relevant. Yet to be done: extract the parts that are most relevant, and put them in this section instead. We don't use a code formatter at the current time, and we are reluctant to merge changes to parts of the code that are unchanged aside from formatting. However, it is still a good idea if you don't know how to format a block of code to use the formatting that [ocamlformat][] would give #### OCaml resources #### You can find lots of OCaml resources on , including documentation, a Discourse forum, the package archive, etc. You may also want to refer to the [Dune documentation][dune-doc]. Another resource is , especially its [community page][ocamlverse-community], which lists the various OCaml discussion platforms. #### Git documentation, tips and tricks #### Lots of resources about git, the version control system, are available on the web, starting with the [official website][git]. We recommend a setup with two configured remotes, one for the official Rocq repository, called `upstream`, and one for your fork, called `origin`. Here is a way to do this for a clean clone: ``` shell git clone https://github.com/rocq-prover/rocq -o upstream cd rocq git remote add origin git@github.com:$YOURNAME/rocq # Make sure you click the fork button on GitHub so that this repository exists cp dev/tools/pre-commit .git/hooks/ # Setup the pre-commit hook ``` Then, if you want to prepare a fix: ``` shell # Make sure we start from an up-to-date master git checkout master git pull --ff-only # If this fails, then your master branch is messy git checkout -b my-topic-branch # Modify some files git add . # Every untracked or modified file will be included in the next commit # You can also replace the dot with an explicit list of files git commit -m "My commit summary. You can add more information on multiple lines, but you need to skip a line first." git push -u origin my-topic-branch # Next time, you push to this branch, you can just do git push ``` When you push a new branch for the first time, GitHub gives you a link to open a PR. If you need to fix the last commit in your branch (typically, if your branch has a single commit on top of `master`), you can do so with ``` git add . git commit --amend --no-edit ``` If you need to fix another commit in your branch, or if you need to fix a conflict with `master`, you will need to learn about `git rebase`. GitHub provides [a short introduction][GitHub-rebase] to `git rebase`. #### GitHub documentation, tips and tricks #### GitHub has [extensive documentation][GitHub-doc] about everything you can do on the platform, and tips about using `git` as well. See in particular, [how to configure your commit e-mail address][GitHub-commit-email] and [how to open a PR from a fork][GitHub-PR-from-fork]. ##### Watching the repository ##### ["Watching" this repository][GitHub-watching] can result in a very large number of notifications. We recommend you, either, [configure your mailbox][notification-email] to handle incoming notifications efficiently, or you read your notifications within a web browser. You can configure how you receive notifications in [your GitHub settings][GitHub-notification-settings], you can use the GitHub interface to mark as read, save for later or mute threads. Nowadays, you have also the option to watch only part of the activity (only issues, only PRs, only releases, etc.). ##### Draft pull requests ##### [Draft PRs][GitHub-draft-PR] are a mechanism proposed by GitHub to open a pull request before it is ready for review. Opening a draft PR is a way of announcing a change and seeking early feedback without formally requesting maintainers' reviews. Indeed, you should avoid cluttering our maintainers' review request lists before a change is ready on your side. When opening a draft PR, make sure to give it a descriptive enough title so that interested developers still notice it in their notification feed. You may also advertise it by talking about it in our [developer chat][Zulip-dev]. If you know which developer would be able to provide useful feedback to you, you may also ping them. ###### Turning a PR into draft mode ###### If a PR was opened as ready for review, but it turns out that it still needs work, it can be transformed into a draft PR. In this case, previous review requests won't be removed automatically. Someone with write access to the repository should remove them manually. Afterwards, upon marking the PR as ready for review, someone with write access will have to manually add the review requests that were previously removed. #### GitLab documentation, tips and tricks #### We use GitLab mostly for its CI service. The [Coq organization on GitLab][GitLab-coq] hosts a number of CI/CD-only mirrors. If you are a regular contributor, you can request access to it from [the organization page][GitLab-coq], although in most cases, you won't need this. GitLab too has [extensive documentation][GitLab-doc], in particular on configuring CI. #### Merge script dependencies #### Nowadays, most assignees should use the `@coqbot: merge now` command instead of the merge script. However, the merge script is still available, and is still needed to merge PRs into release branches. The merge script passes option `-S` to `git merge` to ensure merge commits are signed. Consequently, it depends on the GnuPG command utility being installed and a GPG key being available. Here is a short documentation on how to use GPG, git & GitHub: https://help.github.com/articles/signing-commits-with-gpg/. The script depends on a few other utilities. If you are a Nix user, the simplest way of getting them is to run `nix-shell` first. **Note for homebrew (MacOS) users:** it has been reported that installing GnuPG is not out of the box. Installing explicitly `pinentry-mac` seems important for typing of passphrase to work correctly (see also this [Stack Overflow Q-and-A][pinentry-mac]). #### Coqbot #### Our bot sources can be found at . Its documentation is still a work-in-progress. ### Online forum and chat to talk to developers ### We have a [Discourse forum][Discourse] (see in particular the [Rocq development][Discourse-development-category] category) and a [Zulip chat][Zulip] (see in particular the [Rocq devs & plugin devs][Zulip-dev] stream). Feel free to join any of them and ask questions. People are generally happy to help and very reactive. Obviously, the issue tracker is also a good place to ask questions, especially if the development processes are unclear, or the developer documentation should be improved. ### Rocq calls ### We try to gather every week for one hour through video-conference to discuss current and urgent matters. When longer discussions are needed, topics are left out for the next working group. See the [wiki][wiki-calls] for more information about Rocq calls, as well as notes of past ones. ### Rocq remote working groups ### We semi-regularly (up to every month) organize remote working groups, which can be accessed through video-conference, and are most often live streamed on [YouTube][]. Summary notes and announcements of the next working group can be found [on the wiki][wiki-WG] These working groups are where important decisions are taken, most often by consensus, but also, if it is needed, by a vote of core developers. ### Rocq Users and Developers Workshops ### We have an annual gathering late Spring in France where most core developers are present, and whose objective is to help new contributors get started with the Rocq codebase, provide help to plugin and library authors, and more generally have fun together. The list of past (and upcoming, when it's already planned) workshops can be found [on the wiki][wiki-CUDW]. [add-contributor]: https://github.com/orgs/rocq-prover/teams/contributors/members?add=true [api-doc]: https://rocq-prover.org/doc/master/api/ [Awesome-Coq]: https://github.com/rocq-community/awesome-coq [Benchmarking]: https://github.com/rocq-prover/rocq/wiki/Benchmarking [RFCs]: https://github.com/rocq-prover/rfcs [CI-README-developers]: dev/ci/README-developers.md [CI-README-users]: dev/ci/README-users.md [Code-of-Conduct]: CODE_OF_CONDUCT.md [CODEOWNERS]: .github/CODEOWNERS [Codewars]: https://www.codewars.com/?language=coq [company-coq-issues]: https://github.com/cpitclaudel/company-coq/issues [coqbot-minimize]: https://github.com/rocq-prover/rocq/wiki/Coqbot-minimize-feature [Coq-Club]: https://sympa.inria.fr/sympa/arc/coq-club [rocq-community-maintainer-wanted]: https://github.com/rocq-community/manifesto/issues?q=is%3Aissue+is%3Aopen+label%3Amaintainer-wanted [rocq-community-manifesto]: https://github.com/rocq-community/manifesto [rocq-community-wiki]: https://github.com/rocq-community/manifesto/wiki [rocq-core]: https://github.com/orgs/rocq-prover/teams/core/members [rocqdoc-documentation]: https://rocq-prover.org/refman/using/tools/coqdoc.html [Rocq-books]: https://rocq-prover.org/books [Rocq-issue-tracker]: https://github.com/rocq-prover/rocq/issues [Rocq-package-index]: https://rocq-prover.org/packages [Rocq-Platform]: https://github.com/rocq-prover/platform [rocq-pushers]: https://github.com/orgs/rocq-prover/teams/pushers/teams [rocq-repository]: https://github.com/rocq-prover/rocq [rocq-team]: https://rocq-prover.org/rocq-team [Rocq-website-repository]: https://github.com/rocq-prover/rocq-prover.org [debugging-doc]: dev/doc/debugging.md [dev-ci-nix]: dev/ci/nix/README.md [dev-doc-README]: dev/doc/README.md [dev-doc-dune]: dev/doc/build-system.dune.md [dev-README]: dev/README.md [dev-tools-create_overlays.sh]: dev/tools/create_overlays.sh [Discourse]: https://discourse.rocq-prover.org/ [Discourse-development-category]: https://discourse.rocq-prover.org/c/rocq-development [doc_gram]: doc/tools/docgram/README.md [doc-README]: doc/README.md [documentation-github-project]: https://github.com/orgs/rocq-prover/projects/6 [dune-doc]: https://dune.readthedocs.io/en/latest/ [FAQ]: https://github.com/rocq-prover/rocq/wiki/The-Rocq-FAQ [git]: https://git-scm.com/ [git-hook]: dev/tools/pre-commit [GitHub-co-authored-by]: https://github.blog/2018-01-29-commit-together-with-co-authors/ [GitHub-commit-email]: https://help.github.com/en/articles/setting-your-commit-email-address-in-git [GitHub-doc]: https://help.github.com/ [GitHub-draft-PR]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ [GitHub-markdown]: https://guides.github.com/features/mastering-markdown/ [GitHub-notification-settings]: https://github.com/settings/notifications [GitHub-PR-from-fork]: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork [GitHub-rebase]: https://help.github.com/articles/about-git-rebase/ [GitHub-watching]: https://github.com/rocq-prover/rocq/subscription [GitHub-wiki-extensions]: https://help.github.com/en/articles/editing-wiki-content [GitLab-coq]: https://gitlab.com/coq [GitLab-doc]: https://docs.gitlab.com/ [IRC]: irc://irc.libera.chat:6697/#coq [GitLab-organization]: https://gitlab.com/coq [JasonGross-coq-tools]: https://github.com/JasonGross/coq-tools [kind-documentation]: https://github.com/rocq-prover/rocq/issues?q=is%3Aopen+is%3Aissue+label%3A%22kind%3A+documentation%22 [master-doc]: https://rocq-prover.org/doc/master/refman/ [merge-pr]: dev/tools/merge-pr.sh [needs-benchmarking]: https://github.com/rocq-prover/rocq/labels/needs%3A%20benchmarking [needs-changelog]: https://github.com/rocq-prover/rocq/labels/needs%3A%20changelog%20entry [needs-documentation]: https://github.com/rocq-prover/rocq/labels/needs%3A%20documentation [needs-fixing]: https://github.com/rocq-prover/rocq/labels/needs%3A%20fixing [needs-rebase]: https://github.com/rocq-prover/rocq/labels/needs%3A%20rebase [needs-testing]: https://github.com/rocq-prover/rocq/labels/needs%3A%20testing [needs-test-suite]: https://github.com/rocq-prover/rocq/labels/needs%3A%20test-suite%20update [Nix]: https://github.com/rocq-prover/rocq/wiki/Nix [notification-email]: https://blog.github.com/2017-07-18-managing-large-numbers-of-github-notifications/#prioritize-the-notifications-you-receive [OCaml-planet]: http://ocaml.org/community/planet/ [ocamlformat]: https://github.com/ocaml-ppx/ocamlformat [ocamlverse-community]: https://ocamlverse.github.io/content/community.html [old-style-guide]: dev/doc/style.md [standard-library]: https://github.com/rocq-prover/stdlib [other-standard-libraries]: https://github.com/rocq-archive/stdlib2/wiki/Other-%22standard%22-libraries [pinentry-mac]: https://stackoverflow.com/questions/39494631/gpg-failed-to-sign-the-data-fatal-failed-to-write-commit-object-git-2-10-0 [Platform-docs]: https://github.com/rocq-prover/platform-docs [plugin-tutorial]: doc/plugin_tutorial [Proof-Assistants-SE]: https://proofassistants.stackexchange.com/ [ProofGeneral-issues]: https://github.com/ProofGeneral/PG/issues [Reddit]: https://www.reddit.com/r/Coq/ [refman]: https://rocq-prover.org/refman/ [refman-sources]: doc/sphinx [refman-README]: doc/sphinx/README.rst [release-plan]: https://github.com/rocq-prover/rocq/wiki/Release-Plan [repology-coq]: https://repology.org/project/coq/versions [Rocq-planet]: https://rocq-prover.org/rocq-planet [RM-checklist]: dev/doc/release-process.md [Stack-Exchange]: https://stackexchange.com/filters/299857/questions-tagged-coq-on-stackexchange-sites [Stack-Exchange-to-Zulip]: https://rocq-prover.zulipchat.com/#narrow/stream/237977-Rocq-users/topic/New.20Stack.20Exchange.20question [Stack-Overflow]: https://stackoverflow.com/questions/tagged/coq [stdlib-doc]: https://rocq-prover.org/stdlib/ [test-suite-README]: test-suite/README.md [tools-website]: https://github.com/rocq-community/awesome-coq?tab=readme-ov-file#tools [tools-wiki]: https://github.com/rocq-prover/rocq/wiki/Tools [unreleased-changelog]: https://rocq-prover.org/doc/master/refman/changes.html#unreleased-changes [user-changelog]: doc/changelog [user-overlays]: dev/ci/user-overlays [voting-process]: https://github.com/rocq-prover/rocq/wiki/Core-Team-Voting-Process [wiki]: https://github.com/rocq-prover/rocq/wiki [wiki-calls]: https://github.com/rocq-prover/rocq/wiki/Rocq-Calls [wiki-CUDW]: https://github.com/rocq-prover/rocq/wiki/CoqImplementorsWorkshop [wiki-WG]: https://github.com/rocq-prover/rocq/wiki/Coq-Working-Groups [YouTube]: https://www.youtube.com/channel/UCbJo6gYYr0OF18x01M4THdQ [Zulip]: https://rocq-prover.zulipchat.com [Zulip-dev]: https://rocq-prover.zulipchat.com/#narrow/stream/237656-Rocq-devs.20.26.20plugin.20devs rocq-9.2.0/CREDITS000066400000000000000000000175651516144147600135350ustar00rootroot00000000000000The "Coq proof assistant" was jointly developed by - INRIA Formel, Coq, LogiCal, ProVal, TypiCal, Marelle, pi.r2, Ascola, Galinette projects (starting 1985), - Laboratoire de l'Informatique du Parallelisme (LIP) associated to CNRS and ENS Lyon (Sep. 1989 to Aug. 1997), - Laboratoire de Recherche en Informatique (LRI) associated to CNRS and university Paris Sud (since Sep. 1997), - Laboratoire d'Informatique de l'Ecole Polytechnique (LIX) associated to CNRS and Ecole Polytechnique (since Jan. 2003). - Laboratoire PPS associated to CNRS and University Paris Diderot (Jan. 2009 - Dec. 2015 when it was merged into IRIF). - Institut de Recherche en Informatique Fondamentale (IRIF), associated to CNRS and University Paris Diderot (since Jan. 2016). - And many contributors from various institutions. All files but the material of the reference manual are distributed under the term of the GNU Lesser General Public License Version 2.1. The material of the reference manual is distributed under the terms of the Open Publication License v1.0 or above, as indicated in file doc/LICENCE. The following directories contain independent contributions supported by the Coq development team. All of them are released under the terms of the GNU Lesser General Public License Version 2.1. plugins/cc developed by Pierre Corbineau (ENS Cachan, 2001, LRI, 2001-2005, Radboud University at Nijmegen, 2005-2008, Grenoble 1, 2010-2014) plugins/extraction developed by Pierre Letouzey (LRI, 2000-2004, PPS, 2005-now) plugins/firstorder developed by Pierre Corbineau (LRI, 2003-2008) plugins/funind developed by Pierre Courtieu (INRIA-Lemme, 2003-2004, CNAM, 2006-now), Julien Forest (INRIA-Everest, 2006, CNAM, 2007-2008, ENSIIE, 2008-now) and Yves Bertot (INRIA-Marelle, 2005-2006) plugins/micromega developed by FrΓ©dΓ©ric Besson (IRISA/INRIA, 2006-now), with some extensions by Evgeny Makarov (INRIA, 2007); sum-of-squares solver and interface to the csdp solver uses code from John Harrison (University of Cambridge, 1998) plugins/nsatz developed by LoΓ―c Pottier (INRIA-Marelle, 2009-2011) plugins/omega developed by Pierre CrΓ©gut (France Telecom R&D, 1996) plugins/rtauto developed by Pierre Corbineau (LRI, 2005) plugins/ring developed by Benjamin GrΓ©goire (INRIA-Everest, 2005-2006), Assia Mahboubi, Laurent ThΓ©ry (INRIA-Marelle, 2006) and Bruno Barras (INRIA LogiCal, 2005-2006), plugins/ssr developed by Georges Gonthier (Microsoft Research - Inria Joint Centre, 2007-2013, Inria, 2013-now), Assia Mahboubi and Enrico Tassi (Inria, 2011-now). plugins/ssrmatching developed by Georges Gonthier (Microsoft Research - Inria Joint Centre, 2007-2011, Inria, 2013-now), and Enrico Tassi (Inria-Marelle, 2011-now) theories/ZArith started by Pierre CrΓ©gut (France Telecom R&D, 1996) theories/Strings developed by Laurent ThΓ©ry (INRIA-Lemme, 2003) theories/Numbers/Cyclic developed by Benjamin GrΓ©goire (INRIA-Everest, 2007), Laurent ThΓ©ry (INRIA-Marelle, 2007-2008), Arnaud Spiwack (INRIA-LogiCal, 2007) and Pierre Letouzey (PPS, 2008) ide/utils some files come from Maxence Guesdon's Cameleon tool The development of Coq significantly benefited from feedback, suggestions or short contributions from the following non exhaustive list of persons and groups: C. Alvarado, C. Auger, F. Blanqui, P. CastΓ©ran, C. Cohen, J. Courant, J. Duprat, F. Garillot, G. Gonthier, J. Goubault, J.-P. Jouannaud, S. Lescuyer, A. Miquel, J.-F. Monin, P.-Y. Strub the Foundations Group (Radboud University, Nijmegen, The Netherlands), Laboratoire J.-A. DieudonnΓ© (University of Nice-Sophia Antipolis), L. Lee (https://orcid.org/0000-0002-7128-9257, 2018), INRIA-Gallium project, the CS dept at Yale, the CIS dept at U. Penn, the CSE dept at Harvard, the CS dept at Princeton, the CS dept at MIT as well as a lot of users on coq-club, coqdev, coq-bugs The following people have contributed to the development of different versions of the Coq Proof assistant during the indicated time: Bruno Barras (INRIA, 1995-now) Yves Bertot (INRIA, 2000-now) Pierre Boutillier (INRIA-PPS, 2010-2015) Xavier Clerc (INRIA, 2012-2014) Tej Chajed (MIT, 2016-now) Jacek Chrzaszcz (LRI, 1998-2003) Thierry Coquand (INRIA, 1985-1989) Pierre Corbineau (LRI, 2003-2005, Nijmegen, 2005-2008, Grenoble 1, 2008-2011) Cristina Cornes (INRIA, 1993-1996) Yann Coscoy (INRIA Sophia-Antipolis, 1995-1996) Pierre Courtieu (CNAM, 2006-now) David Delahaye (INRIA, 1997-2002) Maxime DΓ©nΓ¨s (INRIA, 2013-now) Daniel de Rauglaudre (INRIA, 1996-1998, 2012, 2016) Olivier Desmettre (INRIA, 2001-2003) Gilles Dowek (INRIA, 1991-1994) Jim Fehrle (2018-now) Amy Felty (INRIA, 1993) Jean-Christophe FilliΓ’tre (ENS Lyon, 1994-1997, LRI, 1997-2008) Emilio JesΓΊs Gallego Arias (MINES ParisTech 2015-now) Gaetan Gilbert (INRIA-Galinette, 2016-now) Eduardo GimΓ©nez (ENS Lyon, 1993-1996, INRIA, 1997-1998) StΓ©phane Glondu (INRIA-PPS, 2007-2013) Benjamin GrΓ©goire (INRIA, 2003-2011) Jason Gross (MIT 2013-now) Hugo Herbelin (INRIA, 1996-now) SΓ©bastien Hinderer (INRIA, 2014) GΓ©rard Huet (INRIA, 1985-1997) Konstantinos Kallas (U. Penn, 2019) Matej KoΕ‘Γ­k (INRIA, 2015-2017) Leonidas Lampropoulos (University of Pennsylvania, 2018) Pierre Letouzey (LRI, 2000-2004, PPS, 2005-2008, INRIA-PPS then IRIF, 2009-2018) Yao Li (ORCID: https://orcid.org/0000-0001-8720-883X, University of Pennsylvania, 2018) Yishuai Li (ORCID: https://orcid.org/0000-0002-5728-5903 U. Penn, 2018-2019) Patrick Loiseleur (Paris Sud, 1997-1999) Andreas Lynge (Aarhus University, 2019) Evgeny Makarov (INRIA, 2007) Gregory Malecha (Harvard University 2013-2015, University of California, San Diego 2016) Cyprien Mangin (INRIA-PPS then IRIF, 2015-now) Pascal Manoury (INRIA, 1993) Claude MarchΓ© (INRIA, 2003-2004 & LRI, 2004) Micaela Mayero (INRIA, 1997-2002) Guillaume Melquiond (INRIA, 2009-now) Benjamin Monate (LRI, 2003) CΓ©sar MuΓ±oz (INRIA, 1994-1995) Chetan Murthy (INRIA, 1992-1994) Julien Narboux (INRIA, 2005-2006, Strasbourg, 2007-2011) Jean-Marc Notin (CNRS, 2006-now) Catherine Parent-Vigouroux (ENS Lyon, 1992-1995) Christine Paulin-Mohring (INRIA, 1985-1989, ENS Lyon, 1989-1997, LRI, 1997-2006) Pierre-Marie PΓ©drot (INRIA-PPS, 2011-2015, INRIA-Ascola, 2015-2016, University of Ljubljana, 2016-2017, MPI-SWS, 2017-2018, INRIA 2018-now) ClΓ©ment Pit-Claudel (MIT, 2015-now) Matthias Puech (INRIA-Bologna, 2008-2011) Yann RΓ©gis-Gianas (INRIA-PPS then IRIF, 2009-2016) ClΓ©ment Renard (INRIA, 2001-2004) Talia Ringer (University of Washington, 2019) Claudio Sacerdoti Coen (INRIA, 2004-2005) Amokrane SaΓ―bi (INRIA, 1993-1998) Vincent Semeria (2018-now) Vincent Siles (INRIA, 2007) Γ‰lie Soubiran (INRIA, 2007-2010) Matthieu Sozeau (INRIA, 2005-now) Arnaud Spiwack (INRIA-LIX-Chalmers University, 2006-2010, INRIA, 2011-2014, MINES ParisTech 2014-2015, Tweag/IO 2015-now) Paul Steckler (MIT 2016-2018) Enrico Tassi (INRIA, 2011-now) Amin Timany (Katholieke Universiteit Leuven, 2017) Benjamin Werner (INRIA, 1989-1994) Nickolai Zeldovich (MIT 2014-2016) ThΓ©o Zimmermann (ORCID: https://orcid.org/0000-0002-3580-8806, INRIA-PPS then IRIF, 2015-now) *************************************************************************** INRIA refers to: Institut National de la Recherche en Informatique et Automatique CNRS refers to: Centre National de la Recherche Scientifique LRI refers to: Laboratoire de Recherche en Informatique, UMR 8623 CNRS and UniversitΓ© Paris-Sud ENS Lyon refers to: Ecole Normale SupΓ©rieure de Lyon PPS refers to: Laboratoire Preuve, Programmation, SystΓ¨me, UMR 7126, CNRS and UniversitΓ© Paris 7 **************************************************************************** rocq-9.2.0/INSTALL.md000066400000000000000000000107561516144147600141400ustar00rootroot00000000000000Installing From Sources ======================= To install and use Rocq, we recommend relying on [the Rocq platform](https://github.com/rocq-prover/platform) or on a package manager (e.g. opam or Nix). Opam 2.3 is known to work on Unix-like, macOS, and native Windows platforms. See https://rocq-prover.org/install to learn more. If you need to build Rocq from sources manually (e.g. to contribute to Rocq or to write a Rocq package), the remainder of this file explains how to do so. Build Requirements ------------------ To compile Rocq yourself, you need: - [OCaml](https://ocaml.org/) (version >= 4.14.0) (This version of Rocq has been tested up to OCaml 4.14.1, for the 4.x series) Support for OCaml 5.x remains experimental. - The [Dune OCaml build system](https://github.com/ocaml/dune/) >= 3.8 - The [ZArith library](https://github.com/ocaml/Zarith) >= 1.11 - The [findlib](http://projects.camlcity.org/projects/findlib.html) library (version >= 1.9.1) - a C compiler - an IEEE-754 compliant architecture with rounding to nearest ties to even as default rounding mode (most architectures should work nowadays) - for RocqIDE, the [lablgtk3-sourceview3](https://github.com/garrigue/lablgtk) library (version >= 3.1.2), and the corresponding GTK 3.x libraries, as of today (gtk+3 >= 3.18 and gtksourceview3 >= 3.18) - [optional] GNU Make (version >= 3.81) Primitive floating-point numbers require IEEE-754 compliance (`Require Import Floats`). Common sources of incompatibility are checked at configure time, preventing compilation. In the unlikely event an incompatibility remains undetected, using `Floats` would enable proving `False` on this architecture. Note that OCaml dependencies (`zarith` and `lablgtk3-sourceview3` at this moment) must be properly registered with `findlib/ocamlfind` since Rocq's build system uses `findlib` to locate them. Debian / Ubuntu users can get the necessary system packages for RocqIDE with: $ sudo apt-get install libgtksourceview-3.0-dev Opam (https://opam.ocaml.org/) is recommended to install OCaml and the corresponding packages. $ opam switch create rocq --packages="ocaml-variants.4.14.1+options,ocaml-option-flambda" $ eval $(opam env) $ opam install dune ocamlfind zarith lablgtk3-sourceview3 should get you a reasonable OCaml environment to compile Rocq. See the OPAM documentation for more help. Nix users can also get all the required dependencies by running: $ nix-shell Run-time dependencies of native compilation ------------------------------------------- The OCaml compiler and findlib are build-time dependencies, but also run-time dependencies if you wish to use the native compiler. Build and install procedure --------------------------- Note that Rocq supports a faster, but less optimized developer build, but final users must always use the release build. See [dev/doc/build-system.dune.md](dev/doc/build-system.dune.md) for more details. To build and install Rocq (and RocqIDE if desired) do: $ make dunestrap $ dune build -p rocq-runtime,coq-core,rocq-core,coqide-server,rocqide $ dune install --prefix= rocq-runtime coq-core rocq-core coqide-server rocqide You can drop the `rocqide` packages if not needed. Packagers may want to play with `dune install` options as to tweak installation paths, and the `-libdir` argument for `./configure` to tell Rocq where to find its standard library, (`configure` doesn't control installation paths these days). See refman "Command-line and graphical tools" -> "The Rocq Prover commands" -> "System configuration" for more info. OCaml toolchain advisory ------------------------ When loading plugins or `vo` files, you should make sure that these were compiled with the same OCaml setup (version, flags, dependencies...) as Rocq. Distribution of pre-compiled plugins and `.vo` files is only possible if users are guaranteed to have the same Rocq version compiled with the same OCaml toolchain. An OCaml setup mismatch is the most probable cause for an `Error while loading ...: implementation mismatch on ...`. coq_environment.txt ------------------- Rocq binaries which honor environment variables, such as `ROCQLIB`, can be seeded values for these variables by placing a text file named `coq_environment.txt` next to them. The file can contain assignments like `ROCQLIB="some path"`, that is a variable name followed by `=` and a string that follows OCaml's escaping conventions. This feature can be used by installers of binary package to make Rocq aware of its installation path. rocq-9.2.0/LICENSE000066400000000000000000000574751516144147600135260ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS rocq-9.2.0/Makefile000066400000000000000000000241751516144147600141500ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## rocq-runtime coq-core rocq-core" @echo "" @echo " Provided opam/dune packages are:" @echo "" @echo " - rocq-runtime: base Rocq package, toplevel compilers, plugins, tools, no corelib, no stdlib, no GTK" @echo " - coq-core: compat binaries (coqc instead of rocq compile, etc)" @echo " - rocq-core: Rocq's prelude and corelib" @echo " - coqide-server: XML protocol language server" @echo " - rocqide: RocqIDE gtk application" @echo "" @echo " To build a package, you can use:" @echo "" @echo " - 'dune build package.install' : build package in developer mode" @echo " - 'dune build -p package' : build package in release mode" @echo "" @echo " Packages _must_ be installed only if built using release mode, to install a package use: " @echo "" @echo " - 'dune install --prefix= package'" @echo "" @echo " Note that '--prefix' must be passed to dune install. The '-prefix' passed to" @echo " configure tells Rocq where to look for libraries." @echo "" @echo " Note that building a package in release mode ignores other packages present in" @echo " the worktree. See Dune documentation for more information." # We setup the root even in dev mode, to avoid some problems. We used # this in the past to workaround a bug in opam, but the bug was that # we didn't pass `-p` to the dune build below. # # This would be fixed once dune can directly use `(include # theories_dune)` in our files. DUNESTRAPOPT=--root . # We regenerate always as to correctly track deps, can do better # We do a single call to dune as to avoid races and locking ifneq ($(COQ_SPLIT),) # avoid depending on local rocq-runtime _build/default/corelib_dune_split _build/default/ltac2_dune_split .dune-stamp: FORCE dune build $(DUNEOPT) $(DUNESTRAPOPT) corelib_dune_split ltac2_dune_split touch .dune-stamp theories/Corelib/dune: .dune-stamp cp -a _build/default/corelib_dune_split $@ && chmod +w $@ theories/Ltac2/dune: .dune-stamp cp -a _build/default/ltac2_dune_split $@ && chmod +w $@ else _build/default/corelib_dune _build/default/ltac2_dune .dune-stamp: FORCE dune build $(DUNEOPT) $(DUNESTRAPOPT) corelib_dune ltac2_dune touch .dune-stamp theories/Corelib/dune: .dune-stamp cp -a _build/default/corelib_dune $@ && chmod +w $@ theories/Ltac2/dune: .dune-stamp cp -a _build/default/ltac2_dune $@ && chmod +w $@ endif FORCE: ; DUNE_FILES=theories/Corelib/dune theories/Ltac2/dune dunestrap: $(DUNE_FILES) states: world echo "'make states' is an alias for 'make world'" MAIN_TARGETS:=rocq-runtime.install coq-core.install rocq-core.install \ coqide-server.install rocq-devtools.install world: dunestrap dune build $(DUNEOPT) $(MAIN_TARGETS) rocqide: dune build $(DUNEOPT) rocqide.install watch: dune build $(DUNEOPT) $(MAIN_TARGETS) -w check: dune build $(DUNEOPT) @check test-suite: dunestrap dune runtest --no-buffer $(DUNEOPT) refman-html: dunestrap dune build --no-buffer @refman-html refman-pdf: dunestrap dune build --no-buffer @refman-pdf corelib-html: dunestrap dune build @corelib-html apidoc: dune build $(DUNEOPT) @doc # We define this target as to override Make's built-in one install: @echo "To install Rocq using dune, use 'dune build -p P && dune install P'" @echo "where P is any of the packages defined by opam files in the root dir" @false fmt: dune build @fmt --auto-promote ocheck: dune build $(DUNEOPT) @check --workspace=dev/dune-workspace.all obuild: dunestrap dune build $(DUNEOPT) @default --workspace=dev/dune-workspace.all ireport: dune clean dune build $(DUNEOPT) @install --profile=ireport clean: rm -f .dune-stamp theories/Corelib/dune theories/Ltac2/dune dune clean # docgram DOC_GRAM:=_build/default/doc/tools/docgram/doc_grammar.exe # not worth figuring out dependencies, just leave it to dune .PHONY: $(DOC_GRAM) $(DOC_GRAM): dune build $(DUNEOPT) $@ include doc/Makefile.docgram # This requires a install layout to be available. CONTEXT=_build/install/default # XXX: Port this to a dune alias so the build is hygienic! .PHONY: plugin-tutorial plugin-tutorial: world $(MAKE) OCAMLPATH=$(shell pwd)/$(CONTEXT)/lib/ COQBIN="$(shell pwd)/$(CONTEXT)/bin/" -C doc/plugin_tutorial # This is broken in a very weird way with a permission error... see # the rule in doc/plugin_tutorial/dune: # plugin-tutorial: dunestrap # dune build @plugin-tutorial # ci-* targets CI_PURE_DUNE:=1 export CI_PURE_DUNE include Makefile.ci # Custom targets to create subsets of the world target but with less # compiled files. This is desired when we want to have our Rocq Dune # build with Rocq developments that are not dunerized and thus still # expect an install layout with a working Rocq setup, but smaller than # world. # # Unfortunately, Dune still lacks the capability to refer to install # targets in rules, see https://github.com/ocaml/dune/issues/3192 ; # thus we can't simply yet use `%{pkg:coq:theories/Corelib/Arith/Arith.vo` to # have the rule install the target, we thus imitate such behavior # using make as a helper. # $(1) is the directory (theories/Corelib/Foo/) # $(2) is the name (foo) define subtarget = .PHONY: theories-$(2) $(2)_FILES=$$(wildcard $(1)*.v) $(2)_FILES_PATH=$$(addprefix _build/install/default/lib/coq/, $$($(2)_FILES:.v=.vo)) theories-$(2): @echo "DUNE $(1)*.vo" @dune build $$($(2)_FILES_PATH) endef $(foreach subdir,$(wildcard theories/Corelib/*/),$(eval $(call subtarget,$(subdir),$(shell echo $(subst /,,$(subst theories/Corelib/,,$(subdir))) | tr A-Z a-z)))) # Other common dev targets: # # dune build rocq-runtime.install # dune build coq.install # dune build rocqide.install # # Packaging / OPAM targets: # # dune -p coq @install # dune -p rocqide @install rocq-9.2.0/Makefile.ci000066400000000000000000000140721516144147600145350ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## (* We give up to find a canonical name and just simplify it... *) Filename.concat current p let theories_dir = "theories" let plugins_dir = "plugins" let prelude = Filename.concat theories_dir "Init/Prelude.vo" let find_in_PATH f = match Sys.getenv_opt "PATH" with | None -> None | Some paths -> let sep = if Coq_config.arch_is_win32 then ';' else ':' in let paths = String.split_on_char sep paths in paths |> List.find_opt (fun path -> Sys.file_exists (if path = "" then f else Filename.concat path f)) let rocqbin = (* avoid following symlinks if possible (Sys.executable_name followed symlinks) *) if Filename.basename Sys.argv.(0) <> Sys.argv.(0) then (* explicit directory (maybe relative to current dir) *) canonical_path_name (Filename.dirname Sys.argv.(0)) else match find_in_PATH Sys.argv.(0) with | Some p -> p | None -> canonical_path_name (Filename.dirname Sys.executable_name) (** The following only makes sense when executables are running from source tree (e.g. during build or in local mode). *) let rocqroot = let rec search = function | [] -> (* couldn't recognize the layout, guess the executable is 1 dir below the root (eg "mybin/rocq") XXX we should search only when we need the root and produce an error if we can't find it *) Filename.dirname rocqbin | path :: rest -> if Sys.file_exists (Filename.concat path "bin") then path else search rest in (* we can be "bin/rocq" or "lib/rocq-runtime/rocqworker" so rocqbin can be "bin/" or "lib/rocq-runtime/" *) let dirname = Filename.dirname in search [ dirname rocqbin; dirname @@ dirname rocqbin ] let relocate = function | Coq_config.NotRelocatable p -> p | Coq_config.Relocatable p -> Filename.concat rocqroot p (** [check_file_else ~dir ~file oth] checks if [file] exists in the installation directory [dir] given relatively to [coqroot], which maybe has been relocated. If the check fails, then [oth ()] is evaluated. Using file system equality seems well enough for this heuristic *) let check_file_else ~dir ~file oth = let path = use_suffix rocqroot dir in if Sys.file_exists (Filename.concat path file) then path else oth () let guess_coqlib () = match Util.getenv_rocq "LIB" with | Some v -> v | None -> check_file_else ~dir:Coq_config.coqlibsuffix ~file:prelude (fun () -> relocate Coq_config.coqlib) (* Build layout uses coqlib = coqcorelib XXX we should be using -boot in build layout so is that dead code? *) let guess_coqcorelib lib = match Util.getenv_rocq_gen ~rocq:"ROCQRUNTIMELIB" ~coq:"COQCORELIB" with | Some v -> v | None -> if Sys.file_exists (Path.relative lib plugins_dir) then lib else Path.relative lib "../rocq-runtime" let fail_lib lib = let open Printf in eprintf "File not found: %s\n" lib; eprintf "The path for Rocq libraries is wrong.\n"; eprintf "Rocq prelude is shipped in the rocq-core package.\n"; eprintf "Please check the ROCQLIB env variable or the -coqlib option.\n"; exit 1 let fail_core plugin = let open Printf in eprintf "File not found: %s\n" plugin; eprintf "The path for Rocq plugins is wrong.\n"; eprintf "Rocq plugins are shipped in the rocq-runtime package.\n"; eprintf "Please check the ROCQRUNTIMELIB env variable.\n"; exit 1 let validate_env ({ runtimelib; coqlib } as env) = let coqlib = Filename.concat coqlib prelude in if not (Sys.file_exists coqlib) then fail_lib coqlib; let plugin = Filename.concat runtimelib plugins_dir in if not (Sys.file_exists plugin) then fail_core plugin; env type maybe_env = | Env of t | Boot let env_ref = ref None (* Should we fail on double initialization? That seems a way to avoid mis-use for example when we pass command line arguments *) let init_with ~coqlib = let coqlib = match coqlib with | None -> guess_coqlib () | Some coqlib -> coqlib in let env = validate_env { coqlib; runtimelib = guess_coqcorelib coqlib } in env_ref := Some (Env env); env let initialized () = !env_ref let ignored_coqlib_msg = "Command line options -boot and -coqlib are incompatible, ignored -coqlib." let maybe_init ~warn_ignored_coqlib ~boot ~coqlib = match boot, coqlib with | true, None -> Boot | false, (None | Some _ as coqlib) -> (Env (init_with ~coqlib)) | true, Some _ -> warn_ignored_coqlib (); Boot let coqlib { coqlib; _ } = coqlib let runtimelib { runtimelib; _ } = runtimelib let plugins { runtimelib; _ } = Path.relative runtimelib plugins_dir let corelib { coqlib; _ } = Path.relative coqlib theories_dir let user_contrib { coqlib; _ } = Path.relative coqlib "user-contrib" let tool { runtimelib; _ } tool = Path.(relative (relative runtimelib "tools") tool) let revision { runtimelib; _ } = Path.relative runtimelib "revision" let native_cmi { runtimelib; _ } lib = let install_path = Path.relative runtimelib lib in if Sys.file_exists install_path then install_path else (* Dune build layout, we need to improve this *) let obj_dir = Format.asprintf ".%s.objs" lib in Filename.(concat (concat (concat runtimelib lib) obj_dir) "byte") (** {2 Caml paths} *) let ocamlfind () = match Util.getenv_opt "OCAMLFIND" with | None -> Coq_config.ocamlfind | Some v -> v let docdir () = (* This assumes implicitly that the suffix is non-trivial *) let path = use_suffix rocqroot Coq_config.docdirsuffix in if Sys.file_exists path then path else relocate Coq_config.docdir (* Print the configuration information *) let print_config ?(prefix_var_name="") env f = let coqlib = coqlib env |> Path.to_string in let runtimelib = runtimelib env |> Path.to_string in let open Printf in fprintf f "%sCOQLIB=%s/\n" prefix_var_name coqlib; fprintf f "%sCOQCORELIB=%s/\n" prefix_var_name runtimelib; fprintf f "%sDOCDIR=%s/\n" prefix_var_name (docdir ()); fprintf f "%sOCAMLFIND=%s\n" prefix_var_name (ocamlfind ()); fprintf f "%sCAMLFLAGS=%s\n" prefix_var_name Coq_config.caml_flags; fprintf f "%sWARN=%s\n" prefix_var_name "-warn-error +a-3"; fprintf f "%sHASNATDYNLINK=%s\n" prefix_var_name (if Coq_config.has_natdynlink then "true" else "false"); fprintf f "%sCOQ_SRC_SUBDIRS=%s\n" prefix_var_name (String.concat " " Coq_config.all_src_dirs); fprintf f "%sCOQ_NATIVE_COMPILER_DEFAULT=%s\n" prefix_var_name (match Coq_config.native_compiler with | Coq_config.NativeOn {ondemand=false} -> "yes" | Coq_config.NativeOff -> "no" | Coq_config.NativeOn {ondemand=true} -> "ondemand") let query_getenv = function | Boot -> assert false | Env v -> v let print_query envopt usage : Usage.query -> unit = function | PrintVersion -> Usage.version () | PrintMachineReadableVersion -> Usage.machine_readable_version () | PrintWhere -> let env = query_getenv envopt in let coqlib = coqlib env |> Path.to_string in print_endline coqlib | PrintHelp -> begin match usage with | Some usage -> Usage.print_usage stderr usage | None -> assert false end | PrintConfig -> let env = query_getenv envopt in print_config env stdout let query_needs_env : Usage.query -> string option = function | PrintVersion | PrintMachineReadableVersion | PrintHelp -> None | PrintWhere -> Some "-where" | PrintConfig -> Some "-config" let print_queries_maybe_init ~warn_ignored_coqlib ~boot ~coqlib usage = function | [] -> Ok (maybe_init ~warn_ignored_coqlib ~boot ~coqlib) | _ :: _ as qs -> let needs_env = CList.find_map query_needs_env qs in let res = match boot, needs_env with | true, Some q -> Error ("Command line option -boot is not compatible with " ^ q ^ ".") | true, None -> (* warn_ignored_coqlib if coqlib and boot used together *) Ok (maybe_init ~warn_ignored_coqlib ~boot ~coqlib) | false, None -> Ok Boot | false, Some _ -> Ok (Env (init_with ~coqlib)) in let () = match res with | Error _ -> () | Ok envopt -> List.iter (print_query envopt usage) qs in res rocq-9.2.0/boot/env.mli000066400000000000000000000120471516144147600147410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> t (** We should gradually add some more functions to handle common dirs here such the theories directories or share files. Abstracting it hereere does allow to use system-specific functionalities *) (** [exists file] checks if [file] exists *) val exists : t -> bool (** String representation *) val to_string : t -> string end (** Rocq runtime enviroment, including location of Rocq's Corelib *) type t type maybe_env = | Env of t | Boot (** Returns [None] if the environment has not been initialized. *) val initialized : unit -> maybe_env option (** Init, possibly with a user provided coqlib *) val init_with : coqlib:string option -> t (** Init if boot:false, possibly with a user provided coqlib. Incompatible arguments run [warn_ignored_coqlib] (ie with boot:true and coqlib:Some) *) val maybe_init : warn_ignored_coqlib:(unit -> unit) -> boot:bool -> coqlib:string option -> maybe_env (** Usual messsage used for warn_ignored_coqlib *) val ignored_coqlib_msg : string (** If the query list is empty, behave as [maybe_init]. Otherwise, print the queries. If the [usage] argument is [None], the queries must not be PrintHelp. If a query needs an environment, [boot] must not be [true]. If there are queries and none need an environment, returns [Ok Boot] even if [boot] was [false]. *) val print_queries_maybe_init : warn_ignored_coqlib:(unit -> unit) -> boot:bool -> coqlib:string option -> Usage.specific_usage option -> Usage.query list -> (maybe_env, string) result (** [Corelib directory] *) val corelib : t -> Path.t (** [plugins directory] *) val plugins : t -> Path.t (** [user contrib directory] *) val user_contrib : t -> Path.t (** [tool-specific directory] *) val tool : t -> string -> Path.t (** .cmi files needed for native compilation *) val native_cmi : t -> string -> Path.t (** The location of the revision file *) val revision : t -> Path.t (** rocq-runtime/lib directory, not sure if to keep this *) val runtimelib : t -> Path.t (** coq/lib directory, not sure if to keep this *) val coqlib : t -> Path.t (** [camlfind ()] is the path to the ocamlfind binary. *) val ocamlfind : unit -> string val print_config : ?prefix_var_name:string -> t -> out_channel -> unit val relocate : Coq_config.relocatable_path -> string val rocqbin : string rocq-9.2.0/boot/path.ml000066400000000000000000000013271516144147600147330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* set the output directory for native objects\ \n -nI dir OCaml include directories for the native compiler (default if not set) \ \n -h, -help, --help print this list of options\ \n" (* print the usage *) type specific_usage = { executable_name : string; extra_args : string; extra_options : string; } let print_usage co { executable_name; extra_args; extra_options } = print_usage_common co ("Usage: " ^ executable_name ^ " " ^ extra_args ^ "\n\n"); output_string co extra_options type query = | PrintWhere | PrintConfig | PrintVersion | PrintMachineReadableVersion | PrintHelp rocq-9.2.0/boot/usage.mli000066400000000000000000000023621516144147600152540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val machine_readable_version : unit -> unit (** {6 extra arguments or options to print when asking usage for a given executable. } *) type specific_usage = { executable_name : string; extra_args : string; extra_options : string; } (** {6 Prints the generic part and specific part of usage for a given executable. } *) val print_usage : out_channel -> specific_usage -> unit type query = | PrintWhere | PrintConfig | PrintVersion | PrintMachineReadableVersion | PrintHelp rocq-9.2.0/boot/util.ml000066400000000000000000000037551516144147600147630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some(name,value)) with Scanf.Scan_failure _ | End_of_file -> None let with_ic file f = let ic = open_in file in try let rc = f ic in close_in ic; rc with e -> close_in ic; raise e let getenv_from_file name = let base = Filename.dirname Sys.executable_name in try with_ic (base ^ "/coq_environment.txt") (fun ic -> let rec find () = let l = input_line ic in match parse_env_line l with | Some(n,v) when n = name -> Some v | _ -> find () in find ()) with | Sys_error s -> None | End_of_file -> None let getenv_opt name = match Sys.getenv_opt name with | Some _ as v -> v | None -> getenv_from_file name let warn_deprecated_coq_var = ref (fun ~rocq ~coq -> Printf.eprintf "Deprecated environment variable %s, use %s instead.\n%!" coq rocq) let set_warn_deprecated_coq_var f = warn_deprecated_coq_var := f let warn_deprecated_coq_var ~rocq ~coq = !warn_deprecated_coq_var ~rocq ~coq let getenv_rocq_gen ~rocq ~coq = match getenv_opt rocq with | Some _ as v -> v | None -> match getenv_opt coq with | Some _ as v -> warn_deprecated_coq_var ~rocq ~coq; v | None -> None let getenv_rocq name = getenv_rocq_gen ~rocq:("ROCQ"^name) ~coq:("COQ"^name) rocq-9.2.0/boot/util.mli000066400000000000000000000023571516144147600151310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string option val getenv_rocq : string -> string option (** [getenv_rocq name] returns the value of "ROCQ$name" if it exists, otherwise the value of "COQ$name" if it exists and warns that it is deprecated, otherwise [None]. *) val getenv_rocq_gen : rocq:string -> coq:string -> string option (** [getenv_rocq_gen ~rocq ~coq] returns the value of [rocq] if it exists, otherwise the value of [coq] if it exists and warns that it is deprecated, otherwise [None]. *) val set_warn_deprecated_coq_var : (rocq:string -> coq:string -> unit) -> unit rocq-9.2.0/checker/000077500000000000000000000000001516144147600141035ustar00rootroot00000000000000rocq-9.2.0/checker/analyze.ml000066400000000000000000000321521516144147600161030ustar00rootroot00000000000000(** Headers *) let prefix_small_block = 0x80 let prefix_small_int = 0x40 let prefix_small_string = 0x20 [@@@ocaml.warning "-32"] let code_int8 = 0x00 let code_int16 = 0x01 let code_int32 = 0x02 let code_int64 = 0x03 let code_shared8 = 0x04 let code_shared16 = 0x05 let code_shared32 = 0x06 let code_double_array32_little = 0x07 let code_block32 = 0x08 let code_string8 = 0x09 let code_string32 = 0x0A let code_double_big = 0x0B let code_double_little = 0x0C let code_double_array8_big = 0x0D let code_double_array8_little = 0x0E let code_double_array32_big = 0x0F let code_codepointer = 0x10 let code_infixpointer = 0x11 let code_custom = 0x12 let code_block64 = 0x13 let code_shared64 = 0x14 let code_string64 = 0x15 let code_double_array64_big = 0x16 let code_double_array64_little = 0x17 let code_custom_len = 0x18 let code_custom_fixed = 0x19 [@@@ocaml.warning "-37"] type code_descr = | CODE_INT8 | CODE_INT16 | CODE_INT32 | CODE_INT64 | CODE_SHARED8 | CODE_SHARED16 | CODE_SHARED32 | CODE_DOUBLE_ARRAY32_LITTLE | CODE_BLOCK32 | CODE_STRING8 | CODE_STRING32 | CODE_DOUBLE_BIG | CODE_DOUBLE_LITTLE | CODE_DOUBLE_ARRAY8_BIG | CODE_DOUBLE_ARRAY8_LITTLE | CODE_DOUBLE_ARRAY32_BIG | CODE_CODEPOINTER | CODE_INFIXPOINTER | CODE_CUSTOM | CODE_BLOCK64 | CODE_SHARED64 | CODE_STRING64 | CODE_DOUBLE_ARRAY64_BIG | CODE_DOUBLE_ARRAY64_LITTLE | CODE_CUSTOM_LEN | CODE_CUSTOM_FIXED let code_max = 0x19 let magic_number = "\132\149\166\190" (** Memory reification *) module LargeArray : sig type 'a t val empty : 'a t val length : 'a t -> int val make : int -> 'a -> 'a t val get : 'a t -> int -> 'a val set : 'a t -> int -> 'a -> unit end = struct let max_length = Sys.max_array_length type 'a t = 'a array array * 'a array (** Invariants: - All subarrays of the left array have length [max_length]. - The right array has length < [max_length]. *) let empty = [||], [||] let length (vl, vr) = (max_length * Array.length vl) + Array.length vr let make n x = let k = n / max_length in let r = n mod max_length in let vl = Array.init k (fun _ -> Array.make max_length x) in let vr = Array.make r x in (vl, vr) let get (vl, vr) n = let k = n / max_length in let r = n mod max_length in let len = Array.length vl in if k < len then vl.(k).(r) else if k == len then vr.(r) else invalid_arg "index out of bounds" let set (vl, vr) n x = let k = n / max_length in let r = n mod max_length in let len = Array.length vl in if k < len then vl.(k).(r) <- x else if k == len then vr.(r) <- x else invalid_arg "index out of bounds" end type repr = | RInt of int | Rint64 of Int64.t | RFloat64 of float | RBlock of (int * int) (* tag Γ— len *) | RString of string | RPointer of int | RCode of int type data = | Int of int (* value *) | Ptr of int (* pointer *) | Atm of int (* tag *) | Fun of int (* address *) type obj = | Struct of int * data array (* tag Γ— data *) | Int64 of Int64.t (* Primitive integer *) | Float64 of float (* Primitive float *) | String of string module type Input = sig type t val input_byte : t -> int val input_binary_int : t -> int end module type S = sig type input val parse : input -> (data * obj LargeArray.t) end module Make(M : Input) = struct open M type input = M.t let current_offset = ref 0 let input_byte chan = let () = incr current_offset in input_byte chan let input_binary_int chan = let () = current_offset := !current_offset + 4 in input_binary_int chan let input_char chan = Char.chr (input_byte chan) let input_string len chan = String.init len (fun _ -> input_char chan) let parse_header chan = let () = current_offset := 0 in let magic = input_string 4 chan in let length = input_binary_int chan in let objects = input_binary_int chan in let size32 = input_binary_int chan in let size64 = input_binary_int chan in (magic, length, size32, size64, objects) let input_int8s chan = let i = input_byte chan in if i land 0x80 = 0 then i else i lor ((-1) lsl 8) let input_int8u = input_byte let input_int16s chan = let i = input_byte chan in let j = input_byte chan in let ans = (i lsl 8) lor j in if i land 0x80 = 0 then ans else ans lor ((-1) lsl 16) let input_int16u chan = let i = input_byte chan in let j = input_byte chan in (i lsl 8) lor j let input_int32s chan = 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 ans = (i lsl 24) lor (j lsl 16) lor (k lsl 8) lor l in if i land 0x80 = 0 then ans else ans lor ((-1) lsl 31) let input_int32u chan = let i = input_byte chan in let j = input_byte chan in let k = input_byte chan in let l = input_byte chan in (i lsl 24) lor (j lsl 16) lor (k lsl 8) lor l let input_int64s chan = 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 ans = (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 p in if i land 0x80 = 0 then ans else ans lor ((-1) lsl 63) let input_int64u chan = 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 (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 p let input_header32 chan = 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 tag = l in let len = (i lsl 14) lor (j lsl 6) lor (k lsr 2) in (tag, len) let input_header64 chan = 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 tag = p in let len = (i lsl 46) lor (j lsl 38) lor (k lsl 30) lor (l lsl 22) lor (m lsl 14) lor (n lsl 6) lor (o lsr 2) 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 input_double_big chan : float = Int64.float_of_bits (input_intL chan) let input_double_little chan : float = 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 let bits = (p lsl 56) lor (o lsl 48) lor (n lsl 40) lor (m lsl 32) lor (l lsl 24) lor (k lsl 16) lor (j lsl 8) lor (Int64.of_int i) in Int64.float_of_bits bits let parse_object chan = let data = input_byte chan in if prefix_small_block <= data then let tag = data land 0x0F in let len = (data lsr 4) land 0x07 in RBlock (tag, len) else if prefix_small_int <= data then RInt (data land 0x3F) else if prefix_small_string <= data then let len = data land 0x1F in RString (input_string len chan) else if data > code_max then assert false else match (Obj.magic data) with | CODE_INT8 -> RInt (input_int8s chan) | CODE_INT16 -> RInt (input_int16s chan) | CODE_INT32 -> RInt (input_int32s chan) | CODE_INT64 -> RInt (input_int64s chan) | CODE_SHARED8 -> RPointer (input_int8u chan) | CODE_SHARED16 -> RPointer (input_int16u chan) | CODE_SHARED32 -> RPointer (input_int32u chan) | CODE_BLOCK32 -> RBlock (input_header32 chan) | CODE_BLOCK64 -> RBlock (input_header64 chan) | CODE_STRING8 -> let len = input_int8u chan in RString (input_string len chan) | CODE_STRING32 -> let len = input_int32u chan in RString (input_string len chan) | CODE_CODEPOINTER -> let addr = input_int32u chan in for _i = 0 to 15 do ignore (input_byte chan); done; RCode addr | CODE_CUSTOM | CODE_CUSTOM_FIXED -> begin match input_cstring chan with | "_j" -> Rint64 (input_intL chan) | s -> Printf.eprintf "Unhandled custom code: %s" s; assert false end | CODE_DOUBLE_BIG -> RFloat64 (input_double_big chan) | CODE_DOUBLE_LITTLE -> RFloat64 (input_double_little chan) | CODE_DOUBLE_ARRAY32_LITTLE | CODE_DOUBLE_ARRAY8_BIG | CODE_DOUBLE_ARRAY8_LITTLE | CODE_DOUBLE_ARRAY32_BIG | CODE_INFIXPOINTER | CODE_SHARED64 | CODE_STRING64 | CODE_DOUBLE_ARRAY64_BIG | CODE_DOUBLE_ARRAY64_LITTLE | CODE_CUSTOM_LEN -> Printf.eprintf "Unhandled code %04x\n%!" data; assert false let parse chan = let (magic, len, _, _, size) = parse_header chan in let () = assert (magic = magic_number) in let memory = LargeArray.make size (Struct ((-1), [||])) in let current_object = ref 0 in let fill_obj = function | RPointer n -> let data = Ptr (!current_object - n) in data, None | RInt n -> let data = Int n in data, None | RString s -> let data = Ptr !current_object in let () = LargeArray.set memory !current_object (String s) in let () = incr current_object in data, None | RBlock (tag, 0) -> (* Atoms are never shared *) let data = Atm tag in data, None | RBlock (tag, len) -> let data = Ptr !current_object in let nblock = Array.make len (Atm (-1)) in let () = LargeArray.set memory !current_object (Struct (tag, nblock)) in let () = incr current_object in data, Some nblock | RCode addr -> let data = Fun addr in data, None | Rint64 i -> let data = Ptr !current_object in let () = LargeArray.set memory !current_object (Int64 i) in let () = incr current_object in data, None | RFloat64 f -> let data = Ptr !current_object in let () = LargeArray.set memory !current_object (Float64 f) in let () = incr current_object in data, None in let rec fill block off accu = if Array.length block = off then match accu with | [] -> () | (block, off) :: accu -> fill block off accu else let data, nobj = fill_obj (parse_object chan) in let () = block.(off) <- data in let block, off, accu = match nobj with | None -> block, succ off, accu | Some nblock -> nblock, 0, ((block, succ off) :: accu) in fill block off accu in let ans = [|Atm (-1)|] in let () = fill ans 0 [] in (ans.(0), memory) let parse chan : _ * _ = NewProfile.profile "analyze" (fun () -> parse chan) () end module IChannel = struct type t = in_channel let input_byte = input_byte let input_binary_int = input_binary_int end module IString = struct type t = (string * int ref) let input_byte (s, off) = let ans = Char.code (s.[!off]) in let () = incr off in ans let input_binary_int chan = 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 ans = (i lsl 24) lor (j lsl 16) lor (k lsl 8) lor l in if i land 0x80 = 0 then ans else ans lor ((-1) lsl 31) end module PChannel = Make(IChannel) module PString = Make(IString) let parse_channel = PChannel.parse let parse_string s = PString.parse (s, ref 0) let instantiate (p, mem) = let len = LargeArray.length mem in let ans = LargeArray.make len (Obj.repr 0) in (* First pass: initialize the subobjects *) 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) | Int64 i -> Obj.repr i | Float64 f -> Obj.repr f | String str -> Obj.repr str in LargeArray.set ans i obj done; let get_data = function | Int n -> Obj.repr n | Ptr p -> LargeArray.get ans p | Atm tag -> Obj.new_block tag 0 | Fun _ -> assert false (* We shouldn't serialize closures *) in (* Second pass: set the pointers *) for i = 0 to len - 1 do match LargeArray.get mem i with | Struct (_, blk) -> let obj = LargeArray.get ans i in for k = 0 to Array.length blk - 1 do Obj.set_field obj k (get_data blk.(k)) done | Int64 _ | Float64 _ | String _ -> () done; get_data p let instantiate pmem : Obj.t = NewProfile.profile "instantiate" (fun () -> instantiate pmem) () rocq-9.2.0/checker/analyze.mli000066400000000000000000000025401516144147600162520ustar00rootroot00000000000000(** Representation of data allocated on the OCaml heap. *) type data = | Int of int | Ptr of int | Atm of int (* tag *) | Fun of int (* address *) type obj = | Struct of int * data array (* tag Γ— data *) | Int64 of Int64.t (* Primitive integer *) | Float64 of float (* Primitive float *) | String of string module LargeArray : sig type 'a t val empty : 'a t val length : 'a t -> int val make : int -> 'a -> 'a t val get : 'a t -> int -> 'a val set : 'a t -> int -> 'a -> unit end (** A data structure similar to arrays but allowing to overcome the 2^22 length limitation on 32-bit architecture. *) val parse_channel : in_channel -> (data * obj LargeArray.t) val parse_string : string -> (data * obj LargeArray.t) (** {6 Functorized version} *) module type Input = sig type t val input_byte : t -> int (** Input a single byte *) val input_binary_int : t -> int (** Input a big-endian 31-bits signed integer *) end (** Type of inputs *) module type S = sig type input val parse : input -> (data * obj LargeArray.t) (** Return the entry point and the reification of the memory out of a marshalled structure. *) end module Make (M : Input) : S with type input = M.t (** Functorized version of the previous code. *) val instantiate : data * obj LargeArray.t -> Obj.t (** Create the OCaml object out of the reified representation. *) rocq-9.2.0/checker/checkFlags.ml000066400000000000000000000026431516144147600164740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Environ.env -> Environ.env (** Set flags except for those ignored by the checker (see .ml file for those). *) rocq-9.2.0/checker/checkInductive.ml000066400000000000000000000255561516144147600174020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Array.for_all @@ fun p -> match mb.mind_packets.(0).mind_record, p.mind_record with | NotRecord, NotRecord | FakeRecord, FakeRecord | PrimRecord _, PrimRecord _ -> true | (NotRecord | FakeRecord | PrimRecord _), _ -> false); match mb.mind_packets.(0).mind_record with | NotRecord -> None | FakeRecord -> Some None | PrimRecord _ -> let get_id p = match p.mind_record with | NotRecord | FakeRecord -> assert false | PrimRecord {id; _ } -> id in Some (Some (Array.map get_id mb.mind_packets)) in let template = Option.map template_univ_entry mb.mind_template in let mind_entry_universes = match mb.mind_universes with | Monomorphic -> begin match template with | None -> Monomorphic_ind_entry | Some template -> template end | Polymorphic auctx -> Polymorphic_ind_entry (AbstractContext.repr auctx) in let ntyps = Array.length mb.mind_packets in let mind_entry_params = match mb.mind_template with | None -> mb.mind_params_ctxt | Some template -> let open Context.Rel.Declaration in let rec fix_params acc params template = match params, template with | [], [] -> acc | (LocalDef _ as d) :: params , _ -> fix_params (d::acc) params template | (LocalAssum _ as d) :: params, None :: template -> fix_params (d :: acc) params template | LocalAssum (na, t) :: params, Some s :: template -> let ctx, _ = Term.destArity t in let d = LocalAssum (na, Term.mkArity (ctx, s)) in fix_params (d :: acc) params template | _ :: _, [] | [], _ :: _ -> assert false in fix_params [] (List.rev mb.mind_params_ctxt) template.template_param_arguments in let mind_entry_inds = Array.map_to_list (fun ind -> let mind_entry_arity = match mb.mind_template with | None -> let ctx, arity = Term.decompose_prod_n_decls nparams ind.mind_user_arity in ignore ctx; (* we will check that the produced user_arity is equal to the input *) arity | Some template -> let ctx = ind.mind_arity_ctxt in let ctx = List.firstn (List.length ctx - nparams) ctx in Term.mkArity (ctx, template.template_concl) in { mind_entry_typename = ind.mind_typename; mind_entry_arity; mind_entry_consnames = Array.to_list ind.mind_consnames; mind_entry_lc = Array.map_to_list (fun c -> let c = Inductive.abstract_constructor_type_relatively_to_inductive_types_context ntyps mind c in let ctx, c = Term.decompose_prod_n_decls nparams c in ignore ctx; (* we will check that the produced user_lc is equal to the input *) c ) ind.mind_user_lc; }) mb.mind_packets in let mind_entry_variance = Option.map (Array.map (fun v -> Some v)) mb.mind_variance in { mind_entry_record; mind_entry_finite = mb.mind_finite; mind_entry_params; mind_entry_inds; mind_entry_universes; mind_entry_variance; mind_entry_private = mb.mind_private; } let check_abstract_uctx a b = eq_sizes (AbstractContext.size a) (AbstractContext.size b) && PConstraints.equal (UContext.constraints @@ AbstractContext.repr a) (UContext.constraints @@ AbstractContext.repr b) let check_template ar1 ar2 = match ar1, ar2 with | None, None -> true | Some ar, Some {template_context; template_param_arguments; template_concl; template_defaults} -> List.equal (Option.equal Sorts.equal) ar.template_param_arguments template_param_arguments && check_abstract_uctx template_context ar.template_context && Sorts.equal ar.template_concl template_concl && Instance.equal ar.template_defaults template_defaults | None, Some _ | Some _, None -> false (* if the generated inductive is squashed the original one must be squashed *) let check_squashed orig generated = match orig, generated with | None, None -> true | Some _, None -> (* the inductive is from functor instantiation which removed the need for squash *) true | None, Some _ -> (* missing squash *) false | Some s1, Some s2 -> (* functor instantiation can change sort qualities (from Type -> Prop) Condition: every quality which can make the generated inductive squashed must also make the original inductive squashed *) match s1, s2 with | AlwaysSquashed, AlwaysSquashed -> true | AlwaysSquashed, SometimesSquashed _ -> true | SometimesSquashed _, AlwaysSquashed -> false | SometimesSquashed s1, SometimesSquashed s2 -> Sorts.Quality.Set.subset s2 s1 (* Use [UserOrd] 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 *) let eq_recarg_type ty1 ty2 = match ty1, ty2 with | RecArgInd ind1, RecArgInd ind2 -> Names.Ind.UserOrd.equal ind1 ind2 | RecArgPrim c1, RecArgPrim c2 -> Names.Constant.UserOrd.equal c1 c2 | (RecArgInd _ | RecArgPrim _), _ -> false let eq_recarg r1 r2 = match r1, r2 with | Norec, Norec -> true | Mrec ty1, Mrec ty2 -> eq_recarg_type ty1 ty2 | (Norec | Mrec _), _ -> false let eq_reloc_tbl = Array.equal (fun x y -> Int.equal (fst x) (fst y) && Int.equal (snd x) (snd y)) let eq_in_context (ctx1, t1) (ctx2, t2) = Context.Rel.equal Sorts.relevance_equal Constr.equal ctx1 ctx2 && Constr.equal t1 t2 let check_same_record r1 r2 = match r1, r2 with | NotRecord, NotRecord | FakeRecord, FakeRecord -> true | PrimRecord { relevances = r1; tys = tys1 ; _ }, PrimRecord { relevances = r2; tys = tys2 ; _ } -> (* The kernel doesn't care about the names, we just need to check that the saved types are correct. *) Array.equal Sorts.relevance_equal r1 r2 && Array.equal Constr.equal tys1 tys2 | (NotRecord | FakeRecord | PrimRecord _), _ -> false let check_packet mind ind { mind_typename; mind_arity_ctxt; mind_user_arity; mind_record; mind_sort; mind_consnames; mind_user_lc; mind_nrealargs; mind_nrealdecls; mind_squashed; mind_nf_lc; mind_consnrealargs; mind_consnrealdecls; mind_recargs; mind_relevance; mind_nb_constant; mind_nb_args; mind_reloc_tbl } = let check = check mind in ignore mind_typename; (* passed through *) check "mind_arity_ctxt" (Context.Rel.equal Sorts.relevance_equal Constr.equal ind.mind_arity_ctxt mind_arity_ctxt); check "mind_arity" (Constr.equal ind.mind_user_arity mind_user_arity); check "mind_sort" (Sorts.equal ind.mind_sort mind_sort); ignore mind_consnames; (* passed through *) check "mind_record" (check_same_record ind.mind_record mind_record); 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_squashed" (check_squashed ind.mind_squashed mind_squashed); check "mind_nf_lc" (Array.equal eq_in_context ind.mind_nf_lc mind_nf_lc); (* NB: here syntactic equality is not just an optimisation, we also care about the shape of the terms *) check "mind_consnrealargs" (Array.equal Int.equal ind.mind_consnrealargs mind_consnrealargs); check "mind_consnrealdecls" (Array.equal Int.equal ind.mind_consnrealdecls mind_consnrealdecls); check "mind_recargs" (Rtree.equal eq_recarg ind.mind_recargs mind_recargs); check "mind_relevant" (Sorts.relevance_equal ind.mind_relevance mind_relevance); check "mind_nb_args" Int.(equal ind.mind_nb_args mind_nb_args); check "mind_nb_constant" Int.(equal ind.mind_nb_constant mind_nb_constant); check "mind_reloc_tbl" (eq_reloc_tbl ind.mind_reloc_tbl mind_reloc_tbl); () let check_inductive env mind mb = let entry = to_entry mind mb in let { mind_packets; mind_finite; mind_hyps; mind_univ_hyps; mind_nparams; mind_nparams_rec; mind_params_ctxt; mind_universes; mind_template; mind_variance; mind_sec_variance; mind_private; mind_typing_flags; } = (* Locally set typing flags for further typechecking *) let env = CheckFlags.set_local_flags mb.mind_typing_flags env in let mib, not_prim_record = Indtypes.check_inductive env ~sec_univs:None mind entry in assert (Option.is_empty not_prim_record); mib in let check = check mind in Array.iter2 (check_packet mind) mb.mind_packets mind_packets; check "mind_finite" (mb.mind_finite == mind_finite); check "mind_hyps" (List.is_empty mind_hyps); check "mind_univ_hyps" (UVars.Instance.is_empty mind_univ_hyps); check "mind_nparams" Int.(equal mb.mind_nparams mind_nparams); check "mind_nparams_rec" (mb.mind_nparams_rec <= mind_nparams_rec); (* module substitution can increase the real number of recursively uniform parameters, so be tolerant and use [<=]. *) check "mind_params_ctxt" (Context.Rel.equal Sorts.relevance_equal Constr.equal mb.mind_params_ctxt mind_params_ctxt); ignore mind_universes; (* Indtypes did the necessary checking *) check "mind_template" (check_template mb.mind_template mind_template); check "mind_variance" (Option.equal (Array.equal UVars.Variance.equal) mb.mind_variance mind_variance); check "mind_sec_variance" (Option.is_empty mind_sec_variance); ignore mind_private; (* passed through Indtypes *) ignore mind_typing_flags; (* TODO non oracle flags *) add_mind mind mb env let check_inductive env mind mb : Environ.env = NewProfile.profile "check_inductive" ~args:(fun () -> [("name", `String (MutInd.to_string mind))]) (fun () -> check_inductive env mind mb) () rocq-9.2.0/checker/checkInductive.mli000066400000000000000000000017251516144147600175430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* MutInd.t -> Declarations.mutual_inductive_body -> env rocq-9.2.0/checker/checkLibrary.ml000066400000000000000000000404611516144147600170440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* failwith "path_of_dirpath" | l::dir -> {dirpath=List.map Id.to_string dir;basename=Id.to_string l} let pr_dirlist dp = prlist_with_sep (fun _ -> str".") str (List.rev dp) let pr_path sp = match sp.dirpath with [] -> str sp.basename | sl -> pr_dirlist sl ++ str"." ++ str sp.basename (************************************************************************) (*s Modules loaded in memory contain the following informations. They are kept in the global table [libraries_table]. *) type compilation_unit_name = DirPath.t type seg_proofs = Opaqueproof.opaque_proofterm option array type library_t = { library_name : compilation_unit_name; library_filename : CUnix.physical_path; library_compiled : Safe_typing.compiled_library; library_opaques : seg_proofs; library_deps : (compilation_unit_name * Safe_typing.vodigest) array; library_digest : Safe_typing.vodigest; library_vm : Vmlibrary.on_disk; } module LibraryOrdered = struct type t = DirPath.t let compare d1 d2 = compare (List.rev (DirPath.repr d1)) (List.rev (DirPath.repr d2)) end module LibrarySet = Set.Make(LibraryOrdered) module LibraryMap = Map.Make(LibraryOrdered) (* This is a map from names to loaded libraries *) let libraries_table = ref LibraryMap.empty (* various requests to the tables *) let find_library dir = LibraryMap.find dir !libraries_table let library_full_filename dir = (find_library dir).library_filename (* If a library is loaded several time, then the first occurrence must be performed first, thus the libraries_loaded_list ... *) let register_loaded_library m = libraries_table := LibraryMap.add m.library_name m !libraries_table (* Map from library names to table of opaque terms *) let opaque_tables = ref LibraryMap.empty let access_opaque_table dp i = let t = try LibraryMap.find dp !opaque_tables with Not_found -> assert false in let i = Opaqueproof.repr_handle i in let () = assert (0 <= i && i < Array.length t) in t.(i) let indirect_accessor o = let (sub, ci, dp, i) = Opaqueproof.repr o in let c = access_opaque_table dp i in let c = match c with | None -> CErrors.user_err Pp.(str "Cannot access opaque delayed proof.") | Some c -> c in let (c, prv) = Discharge.cook_opaque_proofterm ci c in let c = Mod_subst.subst_mps_list sub c in (c, prv) let () = Mod_checking.set_indirect_accessor indirect_accessor let check_one_lib admit senv (dir,m) = let md = m.library_compiled in let dig = m.library_digest in (* Look up if the library is to be admitted correct. We could also check if it carries a validation certificate (yet to be implemented). *) let senv = if LibrarySet.mem dir admit then (Flags.if_verbose Feedback.msg_notice (str "Admitting library: " ++ pr_dirpath dir); Safe_checking.unsafe_import (fst senv) md m.library_vm dig), (snd senv) else (Flags.if_verbose Feedback.msg_notice (str "Checking library: " ++ pr_dirpath dir); Safe_checking.import (fst senv) (snd senv) md m.library_vm dig) in register_loaded_library m; senv (*************************************************************************) (*s Load path. Mapping from physical to logical paths etc.*) type logical_path = DirPath.t let load_paths = ref ([],[] : CUnix.physical_path list * logical_path list) let find_logical_path phys_dir = let phys_dir = CUnix.canonical_path_name phys_dir in let physical, logical = !load_paths in match List.filter2 (fun p d -> p = phys_dir) physical logical with | _,[dir] -> dir | _,[] -> default_root_prefix | _,l -> CErrors.anomaly (Pp.str ("Two logical paths are associated to "^phys_dir^".")) let remove_load_path dir = let physical, logical = !load_paths in load_paths := List.filter2 (fun p d -> p <> dir) physical logical let add_load_path (phys_path,rocq_path) = if CDebug.(get_flag misc) then Feedback.msg_notice (str "path: " ++ pr_dirpath rocq_path ++ str " ->" ++ spc() ++ str phys_path); let phys_path = CUnix.canonical_path_name phys_path in let physical, logical = !load_paths in match List.filter2 (fun p d -> p = phys_path) physical logical with | _,[dir] -> if rocq_path <> dir (* If this is not the default -I . to coqtop *) && not (phys_path = CUnix.canonical_path_name Filename.current_dir_name && rocq_path = default_root_prefix) then begin (* Assume the user is concerned by library naming *) if dir <> default_root_prefix then Feedback.msg_warning (str phys_path ++ strbrk " was previously bound to " ++ pr_dirpath dir ++ strbrk "; it is remapped to " ++ pr_dirpath rocq_path); remove_load_path phys_path; load_paths := (phys_path::fst !load_paths, rocq_path::snd !load_paths) end | _,[] -> load_paths := (phys_path :: fst !load_paths, rocq_path :: snd !load_paths) | _ -> CErrors.anomaly (Pp.str ("Two logical paths are associated to "^phys_path^".")) let load_paths_of_dir_path dir = let physical, logical = !load_paths in fst (List.filter2 (fun p d -> d = dir) physical logical) (************************************************************************) (*s Locate absolute or partially qualified library names in the path *) exception LibUnmappedDir exception LibNotFound let locate_absolute_library dir = (* Search in loadpath *) let pref, base = split_dirpath dir in let loadpath = load_paths_of_dir_path pref in if loadpath = [] then raise LibUnmappedDir; try let name = Id.to_string base^".vo" in let _, file = System.where_in_path ~warn:false loadpath name in (dir, file) with Not_found -> (* Last chance, removed from the file system but still in memory *) try (dir, library_full_filename dir) with Not_found -> raise LibNotFound let locate_qualified_library qid = try (* we assume qid is an absolute dirpath *) let loadpath = load_paths_of_dir_path (dir_of_path qid) in if loadpath = [] then raise LibUnmappedDir; let name = qid.basename^".vo" in let path, file = System.where_in_path loadpath name in let dir = extend_dirpath (find_logical_path path) (Id.of_string qid.basename) in (* Look if loaded *) try (dir, library_full_filename dir) with Not_found -> (dir, file) with Not_found -> raise LibNotFound let error_unmapped_dir qid = let prefix = qid.dirpath in CErrors.user_err (str "Cannot load " ++ pr_path qid ++ str ":" ++ spc () ++ str "no physical path bound to" ++ spc () ++ pr_dirlist prefix ++ str "." ++ fnl ()) let error_lib_not_found qid = CErrors.user_err (str "Cannot find library " ++ pr_path qid ++ str " in loadpath.") let try_locate_absolute_library dir = try locate_absolute_library dir with | LibUnmappedDir -> error_unmapped_dir (path_of_dirpath dir) | LibNotFound -> error_lib_not_found (path_of_dirpath dir) let try_locate_qualified_library lib = match lib with | PhysicalFile f -> let () = if not (Sys.file_exists f) then CErrors.user_err Pp.(str f ++ str ": file not found.") in let dir = Filename.dirname f in let base = Filename.chop_extension (Filename.basename f) in let dir = extend_dirpath (find_logical_path dir) (Id.of_string base) in (dir, f) | LogicalFile qid -> try locate_qualified_library qid with | LibUnmappedDir -> error_unmapped_dir qid | LibNotFound -> error_lib_not_found qid let lib_to_string = function | PhysicalFile f -> f | LogicalFile qid -> String.concat "." (List.rev (qid.basename :: qid.dirpath)) let try_locate_qualified_library lib : _ * _ = NewProfile.profile "try_locate_qualified_library" ~args:(fun () -> [("name", `String (lib_to_string lib))]) (fun () -> try_locate_qualified_library lib) () (************************************************************************) (*s Low-level interning of libraries from files *) let raw_intern_library f = ObjFile.open_in ~file:f (************************************************************************) (* Internalise libraries *) type library_info type summary_disk = { md_name : compilation_unit_name; md_deps : (compilation_unit_name * Safe_typing.vodigest) array; md_ocaml : string; md_info : library_info; } type library_objects type library_disk = { md_compiled : Safe_typing.compiled_library; md_syntax_objects : library_objects; md_objects : library_objects; } let mk_library sd md f table digest vm = { library_name = sd.md_name; library_filename = f; library_compiled = md.md_compiled; library_opaques = table; library_deps = sd.md_deps; library_digest = digest; library_vm = vm; } let name_clash_message dir mdir f = str ("The file " ^ f ^ " contains library") ++ spc () ++ pr_dirpath mdir ++ spc () ++ str "and not library" ++ spc() ++ pr_dirpath dir type intern_mode = Rec | Root | Dep (* Rec = standard, Root = -norec, Dep = dependency of norec *) (* Dependency graph *) let depgraph = ref LibraryMap.empty let marshal_in_segment (type a) ~validate ~value ~(segment : a ObjFile.segment) f ch : a = NewProfile.profile "marshal_in_segment" (fun () -> let () = LargeFile.seek_in ch segment.ObjFile.pos in if validate then let v = try let v = Analyze.parse_channel ch in let digest = Digest.input ch in let () = if not (String.equal digest segment.ObjFile.hash) then raise_notrace Exit in v with exn when CErrors.noncritical exn -> CErrors.user_err (str "Corrupted file " ++ quote (str f)) in let () = Validate.validate value v in let v = Analyze.instantiate v in Obj.obj v else System.marshal_in f ch) () let summary_seg : summary_disk ObjFile.id = ObjFile.make_id "summary" let library_seg : library_disk ObjFile.id = ObjFile.make_id "library" let opaques_seg : seg_proofs ObjFile.id = ObjFile.make_id "opaques" let vm_seg = Vmlibrary.vm_segment let intern_from_file ~intern_mode ~enable_VM (dir, f) = let validate = intern_mode <> Dep in Flags.if_verbose chk_pp (str"[intern "++str f++str" ..."); let (sd,md,table,vmlib,digest) = try (* First pass to read the metadata of the file *) let ch = System.with_magic_number_check raw_intern_library f in let seg_sd = ObjFile.get_segment ch ~segment:summary_seg in let seg_md = ObjFile.get_segment ch ~segment:library_seg in let seg_opaque = ObjFile.get_segment ch ~segment:opaques_seg in let seg_vmlib = ObjFile.get_segment ch ~segment:vm_seg in let () = ObjFile.close_in ch in (* Actually read the data *) let ch = open_in_bin f in let sd = marshal_in_segment ~validate ~value:Values.v_libsum ~segment:seg_sd f ch in let md = marshal_in_segment ~validate ~value:Values.v_lib ~segment:seg_md f ch in let table = marshal_in_segment ~validate ~value:Values.v_opaquetable ~segment:seg_opaque f ch in let vmlib = if enable_VM then marshal_in_segment ~validate ~value:Values.v_vmlib ~segment:seg_vmlib f ch else Vmlibrary.(export (set_path dir empty)) in (* Verification of the final checksum *) let () = close_in ch in let () = System.check_caml_version ~caml:sd.md_ocaml ~file:f in if dir <> sd.md_name then CErrors.user_err (name_clash_message dir sd.md_name f); Flags.if_verbose chk_pp (str" done]" ++ fnl ()); let digest = Safe_typing.Dvo_or_vi seg_md.hash in sd,md,table,vmlib,digest with e -> Flags.if_verbose chk_pp (str" failed!]" ++ fnl ()); raise e in depgraph := LibraryMap.add sd.md_name sd.md_deps !depgraph; opaque_tables := LibraryMap.add sd.md_name table !opaque_tables; mk_library sd md f table digest (Vmlibrary.inject vmlib) let intern_from_file ~intern_mode ~enable_VM dirf : library_t = NewProfile.profile "intern_from_file" ~args:(fun () -> [("name", `String (DirPath.to_string (fst dirf)))]) (fun () -> intern_from_file ~intern_mode ~enable_VM dirf) () (* Read a compiled library and all dependencies, in reverse order. Do not include files that are already in the context. *) let rec intern_library ~intern_mode ~enable_VM seen (dir, f) needed = if LibrarySet.mem dir seen then failwith "Recursive dependencies!"; (* Look if in the current logical environment *) try let _ = find_library dir in needed with Not_found -> (* Look if already listed and consequently its dependencies too *) if List.mem_assoc_f DirPath.equal dir needed then needed else (* [dir] is an absolute name which matches [f] which must be in loadpath *) let m = intern_from_file ~intern_mode ~enable_VM (dir,f) in let seen' = LibrarySet.add dir seen in let deps = Array.map (fun (d,_) -> try_locate_absolute_library d) m.library_deps in let intern_mode = match intern_mode with Rec -> Rec | Root | Dep -> Dep in (dir,m) :: Array.fold_right (intern_library ~intern_mode ~enable_VM seen') deps needed (* Compute the reflexive transitive dependency closure *) let rec fold_deps seen ff (dir,f) (s,acc) = if LibrarySet.mem dir seen then failwith "Recursive dependencies!"; if LibrarySet.mem dir s then (s,acc) else let deps = match LibraryMap.find_opt dir !depgraph with | Some deps -> deps | None -> CErrors.anomaly Pp.(str "missing dep when computing closure (" ++ DirPath.print dir ++ str ")") in let deps = Array.map (fun (d,_) -> try_locate_absolute_library d) deps in let seen' = LibrarySet.add dir seen in let (s',acc') = Array.fold_right (fold_deps seen' ff) deps (s,acc) in (LibrarySet.add dir s', ff dir acc') and fold_deps_list seen ff modl needed = List.fold_right (fold_deps seen ff) modl needed let fold_deps_list ff modl acc = snd (fold_deps_list LibrarySet.empty ff modl (LibrarySet.empty,acc)) let recheck_library senv ~norec ~admit ~check = let enable_VM = (Environ.typing_flags (Safe_typing.env_of_safe_env senv)).enable_VM in let ml = List.map try_locate_qualified_library check in let nrl = List.map try_locate_qualified_library norec in let al = List.map try_locate_qualified_library admit in let needed = List.fold_right (intern_library ~intern_mode:Rec ~enable_VM LibrarySet.empty) ml [] in let needed = List.fold_right (intern_library ~intern_mode:Root ~enable_VM LibrarySet.empty) nrl needed in let needed = List.rev needed in (* first compute the closure of norec, remove closure of check, add closure of admit, and finally remove norec and check *) let nochk = fold_deps_list LibrarySet.add nrl LibrarySet.empty in let nochk = fold_deps_list LibrarySet.remove ml nochk in let nochk = fold_deps_list LibrarySet.add al nochk in (* explicitly required modules cannot be skipped... *) let nochk = List.fold_right LibrarySet.remove (List.map fst (nrl@ml)) nochk in (* *) Flags.if_verbose Feedback.msg_notice (fnl()++hv 2 (str "Ordered list:" ++ fnl() ++ prlist (fun (dir,_) -> pr_dirpath dir ++ fnl()) needed)); let senv = List.fold_left (check_one_lib nochk) (senv, Cmap.empty) needed in Flags.if_verbose Feedback.msg_notice (str"Modules were successfully checked"); senv rocq-9.2.0/checker/checkLibrary.mli000066400000000000000000000022021516144147600172040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val recheck_library : safe_environment -> norec:object_file list -> admit:object_file list -> check:object_file list -> safe_environment * Cset.t Cmap.t rocq-9.2.0/checker/check_stat.ml000066400000000000000000000067251516144147600165570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* " else hv 2 (str ass ++ str ":" ++ fnl() ++ prlist_with_sep fnl str axs) let pr_axioms env opac = let add c cb acc = if Declareops.constant_has_body cb then acc else match Cmap.find_opt c opac with | None -> Cset.add c acc | Some s -> Cset.union s acc in let csts = fold_constants add env Cset.empty in let csts = Cset.fold (fun c acc -> Constant.to_string c :: acc) csts [] in pr_assumptions "Axioms" csts let pr_type_in_type env = let csts = fold_constants (fun c cb acc -> if not cb.const_typing_flags.check_universes then Constant.to_string c :: acc else acc) env [] in let csts = fold_inductives (fun c cb acc -> if not cb.mind_typing_flags.check_universes then MutInd.to_string c :: acc else acc) env csts in pr_assumptions "Constants/Inductives relying on type-in-type" csts let pr_unguarded env = let csts = fold_constants (fun c cb acc -> if not cb.const_typing_flags.check_guarded then Constant.to_string c :: acc else acc) env [] in let csts = fold_inductives (fun c cb acc -> if not cb.mind_typing_flags.check_guarded then MutInd.to_string c :: acc else acc) env csts in pr_assumptions "Constants/Inductives relying on unsafe (co)fixpoints" csts let pr_nonpositive env = let inds = fold_inductives (fun c cb acc -> if not cb.mind_typing_flags.check_positive then MutInd.to_string c :: acc else acc) env [] in pr_assumptions "Inductives whose positivity is assumed" inds let print_context env opac = if !output_context then begin Feedback.msg_notice (hov 0 (fnl() ++ str"CONTEXT SUMMARY" ++ fnl() ++ str"===============" ++ fnl() ++ fnl() ++ str "* " ++ hov 0 (pr_impredicative_set env ++ fnl()) ++ fnl() ++ str "* " ++ hov 0 (pr_rewrite_rules env ++ fnl()) ++ fnl() ++ str "* " ++ hov 0 (pr_axioms env opac ++ fnl()) ++ fnl() ++ str "* " ++ hov 0 (pr_type_in_type env ++ fnl()) ++ fnl() ++ str "* " ++ hov 0 (pr_unguarded env ++ fnl()) ++ fnl() ++ str "* " ++ hov 0 (pr_nonpositive env ++ fnl())) ) end let stats env opac = print_context env opac; print_memory_stat () rocq-9.2.0/checker/check_stat.mli000066400000000000000000000014321516144147600167160ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Names.Cset.t Names.Cmap.t -> unit rocq-9.2.0/checker/coqchk.ml000066400000000000000000000000361516144147600157040ustar00rootroot00000000000000 let () = Coqchk_main.main () rocq-9.2.0/checker/coqchk.mli000066400000000000000000000014501516144147600160560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* =len then dirs else let pos = try String.index_from s n '.' with Not_found -> len in let dir = String.sub s n (pos-n) in decoupe_dirs (dir::dirs) (pos+1) in decoupe_dirs [] 0 let dirpath_of_string s = match parse_dir s with | [] -> CheckLibrary.default_root_prefix | dir -> DirPath.make (List.map Id.of_string dir) let path_of_string s = if Filename.check_suffix s ".vo" then CheckLibrary.PhysicalFile s else match parse_dir s with | [] -> invalid_arg "path_of_string" | l::dir -> CheckLibrary.LogicalFile {dirpath=dir; basename=l} let get_version env () = match env with | Boot.Env.Boot -> Coq_config.version | Env env -> try let revision = Boot.Env.(Path.to_string (revision env)) in let ch = open_in revision in let ver = input_line ch in let rev = input_line ch in let () = close_in ch in Printf.sprintf "%s (%s)" ver rev with Sys_error _ | End_of_file -> Coq_config.version let print_header env () = Printf.printf "Welcome to Chicken %s\n%!" (get_version env ()) (* Adding files to Rocq loadpath *) let add_path ~unix_path:dir ~rocq_root:rocq_dirpath = if exists_dir dir then begin CheckLibrary.add_load_path (dir,rocq_dirpath) end else Feedback.msg_warning (str "Cannot open " ++ str dir) let convert_string d = try Id.of_string d with CErrors.UserError _ -> Flags.if_verbose Feedback.msg_warning (str "Directory " ++ str d ++ str " cannot be used as a Rocq identifier (skipped)"); raise_notrace Exit let add_rec_path ~unix_path ~rocq_root = if exists_dir unix_path then let dirs = all_subdirs ~unix_path in let prefix = DirPath.repr rocq_root in let convert_dirs (lp, cp) = try let path = List.rev_map convert_string cp @ prefix in Some (lp, Names.DirPath.make path) with Exit -> None in let dirs = List.map_filter convert_dirs dirs in List.iter CheckLibrary.add_load_path dirs; CheckLibrary.add_load_path (unix_path, rocq_root) else Feedback.msg_warning (str "Cannot open " ++ str unix_path) (* By the option -R/-Q of the command line *) let includes = ref [] let push_include (s, alias) = includes := (s,alias) :: !includes let set_include d p = let p = if String.equal p "Coq" then "Corelib" else p in let p = dirpath_of_string p in push_include (d,p) (* Initializes the LoadPath *) let init_load_path rocqenv = (* the to_string casting won't be necessary once Boot handles include paths *) let plugins = Boot.Env.plugins rocqenv |> Boot.Path.to_string in let theories = Boot.Env.corelib rocqenv |> Boot.Path.to_string in let user_contrib = Boot.Env.user_contrib rocqenv |> Boot.Path.to_string in let xdg_dirs = Envars.xdg_dirs in let rocqpath = Envars.coqpath in (* NOTE: These directories are searched from last to first *) (* first standard library *) add_rec_path ~unix_path:theories ~rocq_root:(Names.DirPath.make[rocq_root]); (* then plugins *) add_rec_path ~unix_path:plugins ~rocq_root:(Names.DirPath.make [rocq_root]); (* then user-contrib *) if Sys.file_exists user_contrib then add_rec_path ~unix_path:user_contrib ~rocq_root:CheckLibrary.default_root_prefix; (* then directories in XDG_DATA_DIRS and XDG_DATA_HOME *) List.iter (fun s -> add_rec_path ~unix_path:s ~rocq_root:CheckLibrary.default_root_prefix) (xdg_dirs ~warn:(fun x -> Feedback.msg_warning (str x))); (* then directories in ROCQPATH *) List.iter (fun s -> add_rec_path ~unix_path:s ~rocq_root:CheckLibrary.default_root_prefix) (rocqpath()); (* then current directory *) add_path ~unix_path:"." ~rocq_root:CheckLibrary.default_root_prefix let init_load_path env : unit = NewProfile.profile "init_load_path" (fun () -> init_load_path env) () let impredicative_set = ref false let set_impredicative_set () = impredicative_set := true let boot = ref false let set_boot () = boot := true let coqlib = ref None let set_coqlib v = coqlib := Some v let indices_matter = ref false let enable_vm = ref false let make_senv () = let senv = Safe_typing.empty_environment in let senv = Safe_typing.set_impredicative_set !impredicative_set senv in let senv = Safe_typing.set_indices_matter !indices_matter senv in let senv = Safe_typing.set_VM !enable_vm senv in let senv = Safe_typing.set_allow_sprop true senv in (* be smarter later *) Safe_typing.set_native_compiler false senv let admit_list = ref ([] : CheckLibrary.object_file list) let add_admit s = admit_list := path_of_string s :: !admit_list let norec_list = ref ([] : CheckLibrary.object_file list) let add_norec s = norec_list := path_of_string s :: !norec_list let compile_list = ref ([] : CheckLibrary.object_file list) let add_compile s = compile_list := path_of_string s :: !compile_list (*s Parsing of the command line. We no longer use [Arg.parse], in order to use share [Usage.print_usage] between coqtop and coqc. *) let compile_files senv = CheckLibrary.recheck_library senv ~norec:(List.rev !norec_list) ~admit:(List.rev !admit_list) ~check:(List.rev !compile_list) let version () = Printf.printf "The Rocq Proof Checker, version %s\n" Coq_config.version; exit 0 (* print the usage of coqtop (or coqc) on channel co *) let print_usage_channel co command = output_string co command; output_string co "coqchk options are:\n"; output_string co "\ \n -Q dir coqdir map physical dir to logical coqdir\ \n -R dir coqdir synonymous for -Q\ \n -coqlib dir set coqchk's standard library location\ \n -boot don't initialize the library paths automatically\ \n\ \n -admit module load module and dependencies without checking\ \n -norec module check module but admit dependencies without checking\ \n\ \n -d (d1,..,dn) enable specified debug messages\ \n -debug enable all debug messages\ \n -profile file output profiling info to file\ \n -where print coqchk's standard library location and exit\ \n -v, --version print coqchk version and exit\ \n -o, --output-context print the list of assumptions\ \n -m, --memory print the maximum heap size\ \n -silent disable trace of constants being checked\ \n\ \n -impredicative-set set sort Set impredicative\ \n -indices-matter levels of indices (and nonuniform parameters)\ \n contribute to the level of inductives\ \n -bytecode-compiler (yes|no) enable the vm_compute reduction machine (default is no)\ \n\ \n -h, --help print this list of options\ \n" (* print the usage on standard error *) let print_usage = print_usage_channel stderr let print_usage_rocqtop () = print_usage "Usage: coqchk modules\n\n" let usage exitcode = print_usage_rocqtop (); flush stderr; exit exitcode open Type_errors let anomaly_string () = str "Anomaly: " let report () = strbrk (". Please report at " ^ Coq_config.wwwbugtracker ^ ".") let guill s = str "\"" ++ str s ++ str "\"" let explain_exn = function | Sys_error msg -> hov 0 (anomaly_string () ++ str "uncaught exception Sys_error " ++ guill msg ++ report() ) | UserError pps -> hov 1 (str "User error: " ++ pps) | Out_of_memory -> hov 0 (str "Out of memory") | Stack_overflow -> hov 0 (str "Stack overflow") | Match_failure(filename,pos1,pos2) -> hov 1 (anomaly_string () ++ str "Match failure in file " ++ guill filename ++ str " at line " ++ int pos1 ++ str " character " ++ int pos2 ++ report ()) | Not_found -> hov 0 (anomaly_string () ++ str "uncaught exception Not_found" ++ report ()) | Failure s -> hov 0 (str "Failure: " ++ str s ++ report ()) | Invalid_argument s -> hov 0 (anomaly_string () ++ str "uncaught exception Invalid_argument " ++ guill s ++ report ()) | Sys.Break -> hov 0 (fnl () ++ str "User interrupt.") | UGraph.UniverseInconsistency i -> let msg = if CDebug.(get_flag misc) then str "." ++ spc() ++ UGraph.explain_universe_inconsistency Sorts.QVar.raw_pr Univ.Level.raw_pr i else mt() in hov 0 (str "Error: Universe inconsistency" ++ msg ++ str ".") | QGraph.EliminationError e -> let msg = if CDebug.(get_flag misc) then str "." ++ spc() ++ QGraph.explain_elimination_error Sorts.QVar.raw_pr e else mt() in hov 0 (str "Error: Elimination error" ++ msg ++ str ".") | TypeError(ctx,te) -> hov 0 (str "Type error: " ++ (match te with | UnboundRel i -> str"UnboundRel " ++ int i | UnboundVar v -> str"UnboundVar" ++ str(Names.Id.to_string v) | NotAType _ -> str"NotAType" | BadAssumption _ -> str"BadAssumption" | ReferenceVariables _ -> str"ReferenceVariables" | ElimArity _ -> str"ElimArity" | CaseNotInductive _ -> str"CaseNotInductive" | CaseOnPrivateInd _ -> str"CaseOnPrivateInd" | WrongCaseInfo _ -> str"WrongCaseInfo" | NumberBranches _ -> str"NumberBranches" | IllFormedBranch _ -> str"IllFormedBranch" | IllFormedCaseParams -> str "IllFormedCaseParams" | BadProjType _ -> str "BadProjType" | Generalization _ -> str"Generalization" | ActualType _ -> str"ActualType" | IncorrectPrimitive _ -> str"IncorrectPrimitive" | CantApplyBadType ((n,a,b),{uj_val = hd; uj_type = hdty},args) -> let pp_arg i judge = hv 1 (str"arg " ++ int (i+1) ++ str"= " ++ Constr.debug_print judge.uj_val ++ str ",type= " ++ Constr.debug_print judge.uj_type) ++ fnl () in Feedback.msg_notice (str"====== ill-typed term ====" ++ fnl () ++ hov 2 (str"application head= " ++ Constr.debug_print hd) ++ fnl () ++ hov 2 (str"head type= " ++ Constr.debug_print hdty) ++ fnl () ++ str"arguments:" ++ fnl () ++ hv 1 (prvecti pp_arg args)); Feedback.msg_notice (str"====== type error ====@" ++ fnl () ++ Constr.debug_print b ++ fnl () ++ str"is not convertible with" ++ fnl () ++ Constr.debug_print a ++ fnl ()); Feedback.msg_notice (str"====== universes ====" ++ fnl () ++ (UGraph.pr_universes Univ.Level.raw_pr (UGraph.repr (Environ.universes ctx)))); str "CantApplyBadType at argument " ++ int n | CantApplyNonFunctional _ -> str"CantApplyNonFunctional" | IllFormedRecBody _ -> str"IllFormedRecBody" | IllTypedRecBody _ -> str"IllTypedRecBody" | UnsatisfiedUnivConstraints _ -> str"UnsatisfiedUnivConstraints" | UnsatisfiedPConstraints _ -> str"UnsatisfiedPConstraints" | NotAllowedSProp -> str"NotAllowedSProp" | BadBinderRelevance _ -> str"BadBinderRelevance" | BadCaseRelevance _ -> str"BadCaseRelevance" | BadInvert -> str"BadInvert" | UndeclaredQualities _ -> str"UndeclaredQualities" | UndeclaredUniverses _ -> str"UndeclaredUniverse" | BadVariance _ -> str "BadVariance" | UndeclaredUsedVariables _ -> str "UndeclaredUsedVariables" | IllFormedConstant _ -> str "IllFormedConstant" | IllFormedInductive _ -> str "IllFormedInductive" )) | InductiveError (env,e) -> hov 0 (str "Error related to inductive types") (* let ctx = Check.get_env() in hov 0 (str "Error:" ++ spc () ++ Himsg.explain_inductive_error ctx e)*) | CheckInductive.InductiveMismatch (mind,field) -> hov 0 (MutInd.print mind ++ str ": field " ++ str field ++ str " is incorrect.") | Mod_checking.BadConstant (cst, why) -> hov 0 (Constant.print cst ++ spc() ++ why) | Assert_failure (s,b,e) -> hov 0 (anomaly_string () ++ str "assert failure" ++ spc () ++ (if s = "" then mt () else (str "(file \"" ++ str s ++ str "\", line " ++ int b ++ str ", characters " ++ int e ++ str "-" ++ int (e+6) ++ str ")")) ++ report ()) | e -> CErrors.print e (* for anomalies and other uncaught exceptions *) let profile = ref None let parse_args argv = let rec parse = function | [] -> () | "-impredicative-set" :: rem -> set_impredicative_set (); parse rem | "-indices-matter" :: rem -> indices_matter:=true; parse rem | "-bytecode-compiler" :: "yes" :: rem -> enable_vm := true; parse rem | "-bytecode-compiler" :: "no" :: rem -> enable_vm := false; parse rem | "-coqlib" :: s :: rem -> if not (exists_dir s) then fatal_error (str "Directory '" ++ str s ++ str "' does not exist") 1; set_coqlib s; parse rem | "-boot" :: rem -> set_boot (); parse rem | ("-Q"|"-R") :: d :: p :: rem -> set_include d p;parse rem | ("-Q"|"-R") :: ([] | [_]) -> usage 1 | "-d" :: s :: rem -> CDebug.set_flags s; parse rem | "-debug" :: rem -> CDebug.set_debug_all true; parse rem | "-profile" :: s :: rem -> profile := Some s; parse rem | "-profile" :: [] -> usage 1 | "-where" :: _ -> let env = Boot.Env.init_with ~coqlib:!coqlib in let rocqlib = Boot.Env.coqlib env |> Boot.Path.to_string in print_endline rocqlib; exit 0 | ("-?"|"-h"|"-H"|"-help"|"--help") :: _ -> usage 0 | ("-v"|"--version") :: _ -> version () | ("-m" | "--memory") :: rem -> Check_stat.memory_stat := true; parse rem | ("-o" | "--output-context") :: rem -> Check_stat.output_context := true; parse rem | "-admit" :: s :: rem -> add_admit s; parse rem | "-admit" :: [] -> usage 1 | "-norec" :: s :: rem -> add_norec s; parse rem | "-norec" :: [] -> usage 1 | "-silent" :: rem -> Flags.quiet := true; parse rem | s :: _ when s<>"" && s.[0]='-' -> fatal_error (str "Unknown option " ++ str s) 1 | s :: rem -> add_compile s; parse rem in parse (List.tl (Array.to_list argv)) let init_profile ~file = let ch = open_out file in let fname = Filename.basename file in NewProfile.init { output = Format.formatter_of_out_channel ch; fname; }; at_exit (fun () -> NewProfile.finish (); close_out ch) (* XXX: At some point we need to either port the checker to use the feedback system or to remove its use completely. *) let init_with_argv argv = let _fhandle = Feedback.(add_feeder (console_feedback_listener Format.err_formatter)) in try parse_args argv; Option.iter (fun file -> init_profile ~file) !profile; if CDebug.(get_flag misc) then Printexc.record_backtrace true; let coqenv = Boot.Env.maybe_init ~boot:!boot ~coqlib:!coqlib ~warn_ignored_coqlib:CWarnings.warn_ignored_coqlib in Flags.if_verbose (fun () -> print_header coqenv ()) (); let () = match coqenv with | Boot -> () | Env coqenv -> init_load_path coqenv in (* additional loadpath, given with -R/-Q options *) NewProfile.profile "add_load_paths" (fun () -> List.iter (fun (unix_path, rocq_root) -> add_rec_path ~unix_path ~rocq_root) (List.rev !includes)) (); includes := []; make_senv () with e -> fatal_error (str "Error during initialization :" ++ (explain_exn e)) (CErrors.exit_code e) let init() = init_with_argv Sys.argv let run senv = try let senv = compile_files senv in flush_all(); senv with e -> if CDebug.(get_flag misc) then Printexc.print_backtrace stderr; fatal_error (explain_exn e) (CErrors.exit_code e) let main () = let senv = init() in let senv, opac = run senv in Check_stat.stats (Safe_typing.env_of_safe_env senv) opac; exit 0 rocq-9.2.0/checker/coqchk_main.mli000066400000000000000000000012741516144147600170660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit rocq-9.2.0/checker/dune000066400000000000000000000017571516144147600147730ustar00rootroot00000000000000; Careful with bug https://github.com/ocaml/odoc/issues/148 ; ; If we don't pack checker we will have a problem here due to ; duplicate module names in the whole build. (library (name coq_checklib) (public_name rocq-runtime.checklib) (synopsis "Rocq's Standalone Proof Checker") (modules :standard \ rocqchk coqchk votour) (wrapped true) (libraries rocq-runtime.boot rocq-runtime.kernel)) (deprecated_library_name (old_public_name coq-core.checklib) (new_public_name rocq-runtime.checklib)) (executable (name rocqchk) (public_name rocqchk) (modes exe byte) (package rocq-runtime) (modules rocqchk) (flags :standard -open Coq_checklib) (libraries coq_checklib)) (executable (name coqchk) (public_name coqchk) (modes exe byte) (package coq-core) (modules coqchk) (flags :standard -open Coq_checklib) (libraries coq_checklib)) (executable (name votour) (public_name votour) (package rocq-runtime) (modules votour) (flags :standard -open Coq_checklib) (libraries coq_checklib)) rocq-9.2.0/checker/include000066400000000000000000000114351516144147600154550ustar00rootroot00000000000000(* -*-tuareg-*- *) (* Caml script to include for debugging the checker. Usage: from the checker/ directory launch ocaml toplevel and then type #use"include";; This command loads the relevant modules, defines some pretty printers, and provides functions to interactively check modules (mainly run_l and norec). *) #cd "..";; #directory "lib";; #directory "kernel";; #directory "checker";; #directory "+threads";; #load "unix.cma";; #load"threads.cma";; #load "str.cma";; #load "gramlib.cma";; (*#load "toplevellib.cma";; #directory "/usr/lib/ocaml/compiler-libs/utils";; let _ = Clflags.recursive_types:=true;; *) #load "check.cma";; open Typeops;; open Check;; open Pp;; open CErrors;; open Util;; open Names;; open Term;; open Environ;; open Declarations;; open Mod_checking;; open Cic;; let pr_id id = str(string_of_id id) let pr_na = function Name id -> pr_id id | _ -> str"_";; let prdp dp = pp(str(string_of_dirpath dp));; (* let prc c = pp(Himsg.pr_lconstr_env (Check.get_env()) c);; let prcs cs = prc (Declarations.force cs);; let pru u = pp(str(Univ.string_of_universe u));;*) let pru u = pp(Univ.pr_uni u);; let prlab l = pp(str(string_of_label l));; let prid id = pp(pr_id id);; let prcon c = pp(Indtypes.prcon c);; let prkn kn = pp(Indtypes.prkn kn);; let prus g = pp(Univ.pr_universes g);; let prcstrs c = let g = Univ.merge_constraints c Univ.initial_universes in pp(Univ.pr_universes g);; (*let prcstrs c = pp(Univ.pr_constraints c);; *) (* let prenvu e = let u = universes e in let pu = str "UNIVERSES:"++fnl()++str" "++hov 0 (Univ.pr_universes u) ++fnl() in pp pu;; let prenv e = let ctx1 = named_context e in let ctx2 = rel_context e in let pe = hov 1 (str"[" ++ prlist_with_sep spc (fun (na,_,_) -> pr_id na) (List.rev ctx1)++ str"]") ++ spc() ++ hov 1 (str"[" ++ prlist_with_sep spc (fun (na,_,_) -> pr_na na) (List.rev ctx2)++ str"]") in pp pe;; *) (* let prsub s = let string_of_mp mp = let s = string_of_mp mp in (match mp with MPbound _ -> "#bound."|_->"")^s in pp (hv 0 (fold_subst (fun msid mp strm -> str "S " ++ str (debug_string_of_msid msid) ++ str " |-> " ++ str (string_of_mp mp) ++ fnl() ++ strm) (fun mbid mp strm -> str"B " ++ str (debug_string_of_mbid mbid) ++ str " |-> " ++ str (string_of_mp mp) ++ fnl() ++ strm) (fun mp1 mp strm -> str"P " ++ str (string_of_mp mp1) ++ str " |-> " ++ str (string_of_mp mp) ++ fnl() ++ strm) s (mt()))) ;; *) #install_printer prid;; #install_printer prcon;; #install_printer prlab;; #install_printer prdp;; #install_printer prkn;; #install_printer pru;; (* #install_printer prc;; #install_printer prcs;; *) #install_printer prcstrs;; (*#install_printer prus;;*) (*#install_printer prenv;;*) (*#install_printer prenvu;; #install_printer prsub;;*) Checker.init_with_argv [|"";"-coqlib";"."|];; Flags.quiet := false;; Flags.debug := true;; Sys.catch_break true;; let module_of_file f = let (_,mb,_,_) = Obj.magic ((intern_from_file f).library_compiled) in (mb:Cic.module_body) ;; let deref_mod md s = let l = match md.mod_expr with Struct(NoFunctor l) -> l | FullStruct -> (match md.mod_type with NoFunctor l -> l) in List.assoc (label_of_id(id_of_string s)) l ;; (* let mod_access m fld = match m.mod_expr with Some(SEBstruct l) -> List.assoc fld l | _ -> failwith "bad structure type" ;; *) let parse_dp s = make_dirpath(List.rev_map id_of_string (Str.split(Str.regexp"\\.") s)) ;; let parse_sp s = let l = List.rev (Str.split(Str.regexp"\\.") s) in {dirpath=List.tl l; basename=List.hd l};; let parse_kn s = let l = List.rev (Str.split(Str.regexp"\\.") s) in let dp = make_dirpath(List.map id_of_string(List.tl l)) in make_kn(MPfile dp) empty_dirpath (label_of_id (id_of_string (List.hd l))) ;; let parse_con s = let l = List.rev (Str.split(Str.regexp"\\.") s) in let dp = make_dirpath(List.map id_of_string(List.tl l)) in make_con(MPfile dp) empty_dirpath (label_of_id (id_of_string (List.hd l))) ;; let get_mod dp = lookup_module dp (Safe_typing.get_env()) ;; let get_mod_type dp = lookup_modtype dp (Safe_typing.get_env()) ;; let get_cst kn = lookup_constant kn (Safe_typing.get_env()) ;; let read_mod s f = let lib = intern_from_file (parse_dp s,f) in ((Obj.magic lib.library_compiled): dir_path * module_body * (dir_path * Digest.t) list);; let expln f x = try f x with UserError(_,strm) as e -> msgnl strm; raise e let admit_l l = let l = List.map parse_sp l in Check.recheck_library ~admit:l ~check:l;; let run_l l = Check.recheck_library ~admit:[] ~check:(List.map parse_sp l);; let norec q = Check.recheck_library ~norec:[parse_sp q] ~admit:[] ~check:[];; (* admit_l["Bool";"OrderedType";"DecidableType"];; run_l["FSetInterface"];; *) rocq-9.2.0/checker/mod_checking.ml000066400000000000000000000327121516144147600170540ustar00rootroot00000000000000open Pp open Util open Names open Conversion open Declarations open Mod_declarations open Environ (** {6 Checking constants } *) let indirect_accessor : (Opaqueproof.opaque -> Opaqueproof.opaque_proofterm) ref = ref (fun _ -> assert false) let set_indirect_accessor f = indirect_accessor := f let register_opacified_constant env opac kn cb = let rec gather_consts s c = match Constr.kind c with | Constr.Const (c, _) -> Cset.add c s | _ -> Constr.fold gather_consts s c in let wo_body = Cset.fold (fun kn s -> if Declareops.constant_has_body (lookup_constant kn env) then s else match Cmap.find_opt kn opac with | None -> Cset.add kn s | Some s' -> Cset.union s' s) (gather_consts Cset.empty cb) Cset.empty in Cmap.add kn wo_body opac exception BadConstant of Constant.t * Pp.t let check_constant_declaration env opac kn cb opacify = Flags.if_verbose Feedback.msg_notice (str " checking cst:" ++ Constant.print kn); let env = CheckFlags.set_local_flags cb.const_typing_flags env in let poly, env = match cb.const_universes with | Monomorphic -> (* Monomorphic universes are stored at the library level, the ones in const_universes should not be needed *) false, env | Polymorphic auctx -> let ctx = UVars.AbstractContext.repr auctx in (* [env] contains De Bruijn universe variables *) let () = check_ucontext ctx env in let env = push_context ~strict:false ctx env in true, env in let ty = cb.const_type in let jty = Typeops.infer_type env ty in if not (Sorts.relevance_equal cb.const_relevance (Sorts.relevance_of_sort jty.utj_type)) then raise Pp.(BadConstant (kn, str "incorrect const_relevance")); let body, env = match cb.const_body with | Undef _ | Primitive _ | Symbol _ -> None, env | Def c -> Some c, env | OpaqueDef o -> let c, u = !indirect_accessor o in let env = match u, cb.const_universes with | Opaqueproof.PrivateMonomorphic (), Monomorphic -> env | Opaqueproof.PrivatePolymorphic local, Polymorphic _ -> push_subgraph local env | _ -> assert false in Some c, env in let () = match body with | Some bd -> let j = Typeops.infer env bd in begin match conv_leq env j.uj_type ty with | Result.Ok () -> () | Result.Error () -> Type_errors.error_actual_type env j ty end | None -> () in match body with | Some body when opacify -> register_opacified_constant env opac kn body | Some _ | None -> opac let check_constant_declaration env opac kn cb opacify = let opac = NewProfile.profile "check_constant" ~args:(fun () -> [("name", `String (Constant.to_string kn))]) (fun () -> check_constant_declaration env opac kn cb opacify) () in Environ.add_constant kn cb env, opac let check_quality_mask env qmask lincheck = let open Sorts.Quality in match qmask with | PQConstant QSProp -> if Environ.sprop_allowed env then lincheck else Type_errors.error_not_allowed_sprop env | PQConstant (QProp | QType) -> lincheck | PQVar qio -> Partial_subst.maybe_add_quality qio () lincheck let check_instance_mask env udecl umask lincheck = match udecl, umask with | Monomorphic, ([||], [||]) -> lincheck | Polymorphic uctx, (qmask, umask) -> let lincheck = Array.fold_left_i (fun i lincheck mask -> check_quality_mask env mask lincheck) lincheck qmask in let lincheck = Array.fold_left_i (fun i lincheck mask -> Partial_subst.maybe_add_univ mask () lincheck) lincheck umask in if (Array.length qmask, Array.length umask) <> UVars.AbstractContext.size uctx then CErrors.anomaly Pp.(str "Bad univ mask length."); lincheck | _ -> CErrors.anomaly Pp.(str "Bad univ mask length.") let rec get_holes_profiles env nargs ndecls lincheck el = List.fold_left (get_holes_profiles_elim env nargs ndecls) lincheck el and get_holes_profiles_elim env nargs ndecls lincheck = function | PEApp args -> Array.fold_left (get_holes_profiles_parg env nargs ndecls) lincheck args | PECase (ind, ret, brs) -> let mib, mip = Inductive.lookup_mind_specif env ind in let lincheck = get_holes_profiles_parg env (nargs + mip.mind_nrealargs + 1) (ndecls + mip.mind_nrealdecls + 1) lincheck ret in Array.fold_left3 (fun lincheck nargs_b ndecls_b -> get_holes_profiles_parg env (nargs + nargs_b) (ndecls + ndecls_b) lincheck) lincheck mip.mind_consnrealargs mip.mind_consnrealdecls brs | PEProj proj -> let () = lookup_projection (Projection.make proj false) env |> ignore in lincheck and get_holes_profiles_headelim env nargs ndecls lincheck (h, el) = let lincheck = get_holes_profiles_head env nargs ndecls lincheck h in get_holes_profiles env nargs ndecls lincheck el and get_holes_profiles_parg env nargs ndecls lincheck = function | EHoleIgnored -> lincheck | EHole i -> Partial_subst.add_term i nargs lincheck | ERigid hel -> get_holes_profiles_headelim env nargs ndecls lincheck hel and get_holes_profiles_head env nargs ndecls lincheck = function | PHRel n -> if n <= ndecls then lincheck else Type_errors.error_unbound_rel env n | PHSymbol (c, u) -> let cb = lookup_constant c env in check_instance_mask env cb.const_universes u lincheck | PHConstr (c, u) -> let (mib, _) = Inductive.lookup_mind_specif env (inductive_of_constructor c) in check_instance_mask env mib.mind_universes u lincheck | PHInd (ind, u) -> let (mib, _) = Inductive.lookup_mind_specif env ind in check_instance_mask env mib.mind_universes u lincheck | PHInt _ | PHFloat _ | PHString _ -> lincheck | PHSort PSSProp -> if Environ.sprop_allowed env then lincheck else Type_errors.error_not_allowed_sprop env | PHSort PSType io -> Partial_subst.maybe_add_univ io () lincheck | PHSort PSQSort (qio, uio) -> lincheck |> Partial_subst.maybe_add_quality qio () |> Partial_subst.maybe_add_univ uio () | PHSort _ -> lincheck | PHLambda (tys, bod) -> let lincheck = Array.fold_left_i (fun i -> get_holes_profiles_parg env (nargs + i) (ndecls + i)) lincheck tys in let lincheck = get_holes_profiles_headelim env (nargs + Array.length tys) (ndecls + Array.length tys) lincheck bod in lincheck | PHProd (tys, bod) -> let lincheck = Array.fold_left_i (fun i -> get_holes_profiles_parg env (nargs + i) (ndecls + i)) lincheck tys in let lincheck = get_holes_profiles_parg env (nargs + Array.length tys) (ndecls + Array.length tys) lincheck bod in lincheck let check_rhs env holes_profile rhs = let rec check i c = match Constr.kind c with | App (f, args) when Constr.isRel f -> let n = Constr.destRel f in if n <= i then () else if n - i > Array.length holes_profile then CErrors.anomaly Pp.(str "Malformed right-hand-side substitution site"); let d = holes_profile.(n-i-1) in if Array.length args >= d then () else CErrors.anomaly Pp.(str "Malformed right-hand-side substitution site") | Rel n when n > i -> if n - i > Array.length holes_profile then CErrors.anomaly Pp.(str "Malformed right-hand-side substitution site"); let d = holes_profile.(n-i-1) in if d = 0 then () else CErrors.anomaly Pp.(str "Malformed right-hand-side substitution site") | _ -> Constr.iter_with_binders succ check i c in check 0 rhs let check_rewrite_rule env lab i (symb, rule) = Flags.if_verbose Feedback.msg_notice (str " checking rule:" ++ Id.print lab ++ str"#" ++ Pp.int i); let { nvars; lhs_pat; rhs } = rule in let symb_cb = Environ.lookup_constant symb env in let () = match symb_cb.const_body with Symbol _ -> () | _ -> ignore @@ invalid_arg "Rule defined on non-symbol" in let lincheck = Partial_subst.make nvars in let lincheck = check_instance_mask env symb_cb.const_universes (fst lhs_pat) lincheck in let lincheck = get_holes_profiles env 0 0 lincheck (snd lhs_pat) in let holes_profile, _, _ = Partial_subst.to_arrays lincheck in let () = check_rhs env holes_profile rhs in () let check_rewrite_rules_body env lab rrb = List.iteri (check_rewrite_rule env lab) rrb.rewrules_rules (** {6 Checking modules } *) (** We currently ignore the [mod_type_alg] and [typ_expr_alg] fields. The only delicate part is when [mod_expr] is an algebraic expression : we need to expand it before checking it is indeed a subtype of [mod_type]. Fortunately, [mod_expr] cannot contain any [MEwith]. *) let lookup_module mp env = try Environ.lookup_module mp env with Not_found -> failwith ("Unknown module: "^ModPath.to_string mp) let mk_mtb sign delta = Mod_declarations.make_module_type sign delta let rec collect_constants_without_body sign mp accu = let collect_field s lab = function | SFBconst cb -> let c = Constant.make2 mp lab in if Declareops.constant_has_body cb then s else Cset.add c s | SFBmodule msb -> collect_constants_without_body (mod_type msb) (MPdot(mp,lab)) s | SFBmind _ | SFBrules _ | SFBmodtype _ -> s in match sign with | MoreFunctor _ -> Cset.empty (* currently ignored *) | NoFunctor struc -> List.fold_left (fun s (lab,mb) -> collect_field s lab mb) accu struc let rec check_mexpr env opac mse mp_mse res = match mse with | MEident mp -> let mb = lookup_module mp env in let mb = Modops.strengthen_and_subst_module_body mp mb mp_mse false in mod_type mb, mod_delta mb | MEapply (f,mp) -> let sign, delta = check_mexpr env opac f mp_mse res in let farg_id, farg_b, fbody_b = Modops.destr_functor sign in let state = (Environ.universes env, Conversion.checked_universes) in let _ : UGraph.t = Subtyping.check_subtypes state env mp (MPbound farg_id) farg_b in let mp_delta = let mb = lookup_module mp env in match mod_type mb with | NoFunctor _ -> mod_delta mb | MoreFunctor _ -> Mod_subst.empty_delta_resolver mp in let subst = Mod_subst.map_mbid farg_id mp mp_delta in Modops.subst_signature subst mp_mse fbody_b, Mod_subst.subst_codom_delta_resolver subst delta | MEwith _ -> CErrors.user_err Pp.(str "Unsupported 'with' constraint in module implementation") let rec check_mexpression env opac sign mbtyp mp_mse res = match sign with | MEMoreFunctor body -> let arg_id, mtb, mbtyp = Modops.destr_functor mbtyp in let env' = Modops.add_module_parameter arg_id mtb env in let body, delta = check_mexpression env' opac body mbtyp mp_mse res in MoreFunctor(arg_id,mtb,body), delta | MENoFunctor me -> check_mexpr env opac me mp_mse res let rec check_module env opac mp mb opacify = Flags.if_verbose Feedback.msg_notice (str " checking module: " ++ str (ModPath.to_string mp)); let env = Modops.add_retroknowledge (mod_retroknowledge mb) env in let delta_mb = mod_delta mb in let opac = check_signature env opac (mod_type mb) mp delta_mb opacify in let optsign, opac = match Mod_declarations.mod_expr mb with | Struct (reso, sign_struct) -> let opacify = collect_constants_without_body (mod_type mb) mp opacify in (* TODO: a bit wasteful, we recheck the types of parameters twice *) let sign_struct = Modops.annotate_struct_body sign_struct (mod_type mb) in let opac = check_signature env opac sign_struct mp reso opacify in Some (sign_struct, reso), opac | Algebraic me -> Some (check_mexpression env opac me (mod_type mb) mp delta_mb), opac | Abstract|FullStruct -> None, opac in let () = match optsign with | None -> () | Some (sign,delta) -> let mtb1 = mk_mtb sign delta and mtb2 = mk_mtb (mod_type mb) delta_mb in let state = (Environ.universes env, Conversion.checked_universes) in let env = Modops.add_module mp (module_body_of_type mtb1) env in let _ : UGraph.t = Subtyping.check_subtypes state env mp mp mtb2 in () in opac and check_module_type env mp mty = Flags.if_verbose Feedback.msg_notice (str " checking module type: " ++ str (ModPath.to_string @@ mp)); let _ : _ Cmap.t = check_signature env Cmap.empty (mod_type mty) mp (mod_delta mty) Cset.empty in () and check_structure_field env opac mp lab res opacify = function | SFBconst cb -> let kn = KerName.make mp lab in let kn = Mod_subst.constant_of_delta_kn res kn in check_constant_declaration env opac kn cb (Cset.mem kn opacify) | SFBmind mib -> let kn = KerName.make mp lab in let kn = Mod_subst.mind_of_delta_kn res kn in CheckInductive.check_inductive env kn mib, opac | SFBmodule msb -> let mp = MPdot(mp, lab) in let opac = check_module env opac mp msb opacify in Modops.add_module mp msb env, opac | SFBmodtype mty -> let mp = MPdot (mp, lab) in let () = check_module_type env mp mty in add_modtype mp mty env, opac | SFBrules rrb -> check_rewrite_rules_body env lab rrb; Environ.add_rewrite_rules rrb.rewrules_rules env, opac and check_signature env opac sign mp_mse res opacify = match sign with | MoreFunctor (arg_id, mtb, body) -> let () = check_module_type env (MPbound arg_id) mtb in let env' = Modops.add_module_parameter arg_id mtb env in let opac = check_signature env' opac body mp_mse res Cset.empty in opac | NoFunctor struc -> let (_:env), opac = List.fold_left (fun (env, opac) (lab,mb) -> check_structure_field env opac mp_mse lab res opacify mb) (env, opac) struc in opac let check_module env opac mp mb = NewProfile.profile "check_module" ~args:(fun () -> [("name", `String (ModPath.to_string mp))]) (fun () -> check_module env opac mp mb Cset.empty) () rocq-9.2.0/checker/mod_checking.mli000066400000000000000000000016741516144147600172300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Opaqueproof.opaque_proofterm) -> unit val check_module : Environ.env -> Names.Cset.t Names.Cmap.t -> Names.ModPath.t -> Mod_declarations.module_body -> Names.Cset.t Names.Cmap.t exception BadConstant of Names.Constant.t * Pp.t rocq-9.2.0/checker/rocqchk.ml000066400000000000000000000000361516144147600160660ustar00rootroot00000000000000 let () = Coqchk_main.main () rocq-9.2.0/checker/rocqchk.mli000066400000000000000000000000001516144147600162260ustar00rootroot00000000000000rocq-9.2.0/checker/safe_checking.ml000066400000000000000000000037131516144147600172120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let dp = Safe_typing.dirpath_of_library clib in [("name", `String (Names.DirPath.to_string dp))]) (fun () ->import senv opac clib vmtab digest) () let unsafe_import senv clib vmtab digest = let (_,senv) = Safe_typing.import clib vmtab digest senv in senv rocq-9.2.0/checker/safe_checking.mli000066400000000000000000000017451516144147600173660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Names.Cset.t Names.Cmap.t -> compiled_library -> Vmlibrary.on_disk -> vodigest -> safe_environment * Names.Cset.t Names.Cmap.t val unsafe_import : safe_environment -> compiled_library -> Vmlibrary.on_disk -> vodigest -> safe_environment rocq-9.2.0/checker/validate.ml000066400000000000000000000163531516144147600162360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Format.print_int i | Ptr p -> let v = LargeArray.get mem p in begin match v with | Struct (tag, data) -> let n = Array.length data in Format.print_string ("#"^string_of_int tag^"("); Format.open_hvbox 0; for i = 0 to n-1 do pr_obj_rec mem (Array.get data i); if i<>n-1 then (Format.print_string ","; Format.print_cut()) done; Format.close_box(); Format.print_string ")" | String s -> Format.print_string ("\""^String.escaped s^"\"") | Int64 _ | Float64 _ -> Format.print_string "?" end | Atm tag -> Format.print_string ("#"^string_of_int tag^"()"); | Fun addr -> Format.printf "fun@%x" addr let pr_obj mem o = pr_obj_rec mem o; Format.print_newline() (**************************************************************************) (* Obj low-level validators *) type error_frame = | CtxAnnot of string | CtxType of string | CtxField of int | CtxTag of int type error_context = error_frame list let mt_ec : error_context = [] let (/) (ctx:error_context) s : error_context = s::ctx exception ValidObjError of string * error_context * data let fail _mem ctx o s = raise (ValidObjError(s,ctx,o)) let is_block mem o = match o with | Ptr _ | Atm _ -> true | Fun _ | Int _ -> false let is_int _mem o = match o with | Int _ -> true | Fun _ | Ptr _ | Atm _ -> false let is_int64 mem o = match o with | Int _ | Fun _ | Atm _ -> false | Ptr p -> match LargeArray.get mem p with | Int64 _ -> true | Float64 _ | Struct _ | String _ -> false let is_float64 mem o = match o with | Int _ | Fun _ | Atm _ -> false | Ptr p -> match LargeArray.get mem p with | Float64 _ -> true | Int64 _ | Struct _ | String _ -> false let get_int _mem = function | Int i -> i | Fun _ | Ptr _ | Atm _ -> assert false let tag mem o = match o with | Atm tag -> tag | Fun _ -> Obj.out_of_heap_tag | Int _ -> Obj.int_tag | Ptr p -> match LargeArray.get mem p with | Struct (tag, _) -> tag | String _ -> Obj.string_tag | Float64 _ -> Obj.double_tag | Int64 _ -> Obj.custom_tag let size mem o = match o with | Atm _ -> 0 | Fun _ | Int _ -> assert false | Ptr p -> match LargeArray.get mem p with | Struct (tag, blk) -> Array.length blk | String _ | Float64 _ | Int64 _ -> assert false let field mem o i = match o with | Atm _ | Fun _ | Int _ -> assert false | Ptr p -> match LargeArray.get mem p with | Struct (tag, blk) -> Array.get blk i | String _ | Float64 _ | Int64 _ -> assert false (* Check that object o is a block with tag t *) let val_tag t mem ctx o = if is_block mem o && tag mem o = t then () else fail mem ctx o ("expected tag "^string_of_int t) let val_block mem ctx o = if is_block mem o then (if tag mem o > Obj.no_scan_tag then fail mem ctx o "block: found no scan tag") else fail mem ctx o "expected block obj" open Values type memory = { mem : obj LargeArray.t; seen : value list LargeArray.t; } let rec val_gen v mem ctx o = match o with | Ptr p -> let seen = LargeArray.get mem.seen p in if List.exists (fun v' -> Values.equal v' v) seen then () else begin (* Setting before we recurse means we allow recursive values. Do we care? *) LargeArray.set mem.seen p (v::seen); val_gen_aux v mem ctx o end | Int _ | Atm _ | Fun _ -> val_gen_aux v mem ctx o and val_gen_aux v mem ctx o = match kind v with | Tuple (name,vs) -> val_tuple ~name vs mem ctx o | Sum (name,cc,vv) -> val_sum name cc vv mem ctx o | Array v -> val_array v mem ctx o | List v0 -> val_sum "list" 1 [|[|v0;v|]|] mem ctx o | Opt v -> val_sum "option" 1 [|[|v|]|] mem ctx o | Int -> if not (is_int mem o) then fail mem ctx o "expected an int" | String -> (try val_tag Obj.string_tag mem.mem ctx o with Failure _ -> fail mem ctx o "expected a string") | Any -> () | Fail s -> fail mem ctx o ("unexpected object " ^ s) | Annot (s,v) -> val_gen v mem (ctx/CtxAnnot s) o | Int64 -> val_int64 mem ctx o | Float64 -> val_float64 mem 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 expected size of the object. *) and val_tuple ?name vs mem ctx o = let ctx = match name with | Some n -> ctx/CtxType n | _ -> ctx in let n = Array.length vs in let val_fld i v = val_gen v mem (ctx/(CtxField i)) (field mem.mem o i) in val_block mem.mem ctx o; if size mem.mem o = n then Array.iteri val_fld vs else fail mem ctx o ("tuple size: found "^string_of_int (size mem.mem o)^ ", expected "^string_of_int n) (* Check that the object is either a constant constructor of tag < cc, or a constructed variant. each element of vv is an array of value representations of the constructor arguments. The size of vv corresponds to the number of non-constant constructors, and the size of vv.(i) is the expected arity of the i-th non-constant constructor. *) and val_sum name cc vv mem ctx o = let ctx = ctx/CtxType name in if is_block mem o then (val_block mem.mem ctx o; let n = Array.length vv in let i = tag mem.mem o in let ctx' = if n=1 then ctx else ctx/CtxTag i in if i < n then val_tuple vv.(i) mem ctx' o else fail mem ctx' o ("sum: unexpected tag")) else if is_int mem o then let (n:int) = get_int mem o in (if n<0 || n>=cc then fail mem ctx o ("bad constant constructor "^string_of_int n)) else fail mem ctx o "not a sum" (* Check the o is an array of values satisfying f. *) and val_array v mem ctx o = val_block mem.mem (ctx/CtxType "array") o; for i = 0 to size mem.mem o - 1 do val_gen v mem ctx (field mem.mem o i) done and val_int64 mem ctx o = if not (is_int64 mem.mem o) then fail mem ctx o "not a 63-bit unsigned integer" and val_float64 mem ctx o = if not (is_float64 mem.mem o) then fail mem ctx o "not a 64-bit float" let val_gen v mem ctx o = let mem = { mem; seen = LargeArray.make (LargeArray.length mem) []; } in val_gen v mem ctx o let print_frame = function | CtxType t -> t | CtxAnnot t -> t | CtxField i -> Printf.sprintf "fld=%i" i | CtxTag i -> Printf.sprintf "tag=%i" i let validate v (o, mem) : unit = try NewProfile.profile "validate" (fun () -> val_gen v mem mt_ec o) () with ValidObjError(msg,ctx,obj) -> let rctx = List.rev_map print_frame ctx in print_endline ("Context: "^String.concat"/"rctx); pr_obj mem obj; failwith ("Validation failed: "^msg^" (in "^(print_frame (List.hd ctx))^")") rocq-9.2.0/checker/validate.mli000066400000000000000000000013611516144147600164000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* data * obj LargeArray.t -> unit rocq-9.2.0/checker/values.ml000066400000000000000000000435031516144147600157410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ('a, [`S of 's]) t type 'n size = (unit,'n) t let rec vmap : 'n 'a 'b. ('a -> 'b) -> ('a,'n) t -> ('b, 'n) t = fun (type n) f (v:(_,n) t) : (_,n) t -> match v with | [] -> [] | x :: tl -> let x = f x in x :: vmap f tl let rec viter2 : 'n 'a 'b. ('a -> 'b -> unit) -> ('a,'n) t -> ('b,'n) t -> unit = fun (type n) f (v1:(_,n) t) (v2:(_,n) t) -> match v1, v2 with | [], []-> () | x1 :: tl1, x2 :: tl2 -> let () = f x1 x2 in viter2 f tl1 tl2 end module Internal : sig type value val equal : value -> value -> bool val kind : value -> value kind val of_kind : value kind -> value val mfix : 'n Vector.size -> ((value,'n) Vector.t -> (value,'n) Vector.t) -> (value,'n) Vector.t end = struct type value = | V of value kind | Proxy of value kind ref let kind = function | V v -> v | Proxy v -> !v (* Proxy is equal to its contents *) let equal a b = kind a == kind b let of_kind v = V v let check_productive = function | Proxy _ -> assert false | V v -> v let mfix (type n) (n:n Vector.size) (f : (value,n) Vector.t -> (value,n) Vector.t) : (value,n) Vector.t = let open Vector in let self = vmap (fun () -> Proxy (ref Any)) n in let ans = f self in let () = viter2 (fun self ans -> let ans = check_productive ans in match self with | Proxy self -> self := ans | _ -> assert false) self ans in ans end type nonrec value = Internal.value let equal = Internal.equal let kind = Internal.kind let of_kind = Internal.of_kind let mfix = Internal.mfix let fix f = let [v] : _ Vector.t = mfix [()] (fun [v] -> [f v]) in v (** Some pseudo-constructors *) let v_tuple name v = of_kind @@ Tuple(name,v) let v_sum name cc vv = of_kind @@ Sum(name,cc,vv) let v_enum name n = of_kind @@ Sum(name,n,[||]) let v_annot a v = of_kind @@ Annot (a, v) let v_fail f = of_kind @@ Fail f (* uncurried forms *) let v_tuple_c (name,v) = v_tuple name v let v_sum_c (name,cc,vv) = v_sum name cc vv let v_annot_c (a, v) = v_annot a v (** Ocaml standard library *) let v_any = of_kind Any let v_int = of_kind Int let v_int64 = of_kind Int64 let v_float64 = of_kind Float64 let v_string = of_kind String let v_opt v = of_kind @@ Opt v let v_list v = of_kind @@ List v let v_array v = of_kind @@ Array v let v_pair v1 v2 = v_tuple "*" [|v1; v2|] let v_bool = v_enum "bool" 2 let v_unit = v_enum "unit" 1 let v_set v = fix (fun s -> v_sum_c ("Set.t",1, [|[|s; v_annot_c ("elem", v); s; v_annot_c ("bal", v_int)|]|])) let v_map vk vd = fix (fun m -> v_sum_c ("Map.t",1, [|[|m; v_annot_c("key",vk); v_annot_c("data",vd); m; v_annot_c("bal",v_int)|]|])) let v_hset v = v_map v_int (v_set v) let v_hmap vk vd = v_map v_int (v_map vk vd) let v_pred v = v_pair v_bool (v_set v) (** kernel/names *) let v_id = v_string let v_dp = v_annot_c ("dirpath", v_list v_id) let v_name = v_sum "name" 1 [|[|v_id|]|] let v_uid = v_tuple "uniq_ident" [|v_int;v_string;v_dp|] let v_mp = fix (fun v_mp -> v_sum_c("module_path",0, [|[|v_dp|]; [|v_uid|]; [|v_mp;v_id|]|])) let v_kn = v_tuple "kernel_name" [|v_mp;v_id;v_int|] let v_cst = v_sum "cst|mind" 0 [|[|v_kn|];[|v_kn;v_kn|]|] let v_ind = v_tuple "inductive" [|v_cst;v_int|] let v_cons = v_tuple "constructor" [|v_ind;v_int|] (** kernel/univ *) let v_level_global = v_tuple "Level.Global.t" [|v_dp;v_string;v_int|] let v_raw_level = v_sum "raw_level" 1 (* Set *) [|(*Level*)[|v_level_global|]; (*Var*)[|v_int|]|] let v_level = v_tuple "level" [|v_int;v_raw_level|] let v_expr = v_tuple "levelexpr" [|v_level;v_int|] let v_univ = v_list v_expr let v_qglobal = v_pair v_dp v_id (* perhaps the "Unif" constructor should be forbidden in vo files *) let v_qvar = v_sum "qvar" 0 [|[|v_int|];[|v_string;v_int|];[|v_qglobal|]|] let v_constant_quality = v_enum "constant_quality" 3 let v_quality = v_sum "quality" 0 [|[|v_qvar|];[|v_constant_quality|]|] let v_elim_cstrs = v_annot_c ("Quality.ElimConstraints.t", v_set (v_tuple "Quality.ElimConstraint.t" [|v_quality;v_enum "elim_request" 2;v_quality|])) let v_univ_cstrs = v_annot_c ("Univ.UnivConstraints.t", v_set (v_tuple "Univ.UnivConstraint.t" [|v_level;v_enum "order_request" 3;v_level|])) let v_cstrs = v_tuple "PConstraints.t" [|v_elim_cstrs;v_univ_cstrs|] let v_variance = v_enum "variance" 3 let v_instance = v_annot_c ("instance", v_pair (v_array v_quality) (v_array v_level)) let v_abs_context = v_tuple "abstract_universe_context" [|v_pair (v_array v_name) (v_array v_name); v_cstrs|] let v_univ_context_set = v_tuple "universe_context_set" [|v_hset v_level;v_univ_cstrs|] let v_sort_context_set = v_tuple "sort_context_set" [|v_set v_qvar; v_elim_cstrs|] (** kernel/term *) let v_sort = v_sum "sort" 3 (*SProp, Prop, Set*) [|[|v_univ(*Type*)|];[|v_qvar;v_univ(*QSort*)|]|] let v_relevance = v_sum "relevance" 2 [|[|v_qvar|]|] let v_binder_annot x = v_tuple "binder_annot" [|x;v_relevance|] let v_puniverses v = v_tuple "punivs" [|v;v_instance|] let v_caseinfo = let v_cstyle = v_enum "case_style" 5 in let v_cprint = v_tuple "case_printing" [|v_cstyle|] in v_tuple "case_info" [|v_ind;v_int;v_array v_int;v_array v_int;v_cprint|] let v_cast = v_enum "cast_kind" 3 let v_proj_repr = v_tuple "projection_repr" [|v_ind;v_int;v_int;v_cst|] let v_proj = v_tuple "projection" [|v_proj_repr; v_bool|] let v_uint63 = if Sys.word_size == 64 then v_int else v_int64 let v_constr = fix (fun v_constr -> let v_prec = v_tuple_c ("prec_declaration", [|v_array (v_binder_annot v_name); v_array v_constr; v_array v_constr|]) in let v_fix = v_tuple_c ("pfixpoint", [|v_tuple_c ("fix2",[|v_array v_int;v_int|]);v_prec|]) in let v_cofix = v_tuple_c ("pcofixpoint",[|v_int;v_prec|]) in let v_case_invert = v_sum_c ("case_inversion", 1, [|[|v_array v_constr|]|]) in let v_case_branch = v_tuple_c ("case_branch", [|v_array (v_binder_annot v_name); v_constr|]) in let v_case_return = v_tuple_c ("case_return", [|v_tuple_c ("case_return'", [|v_array (v_binder_annot v_name); v_constr|]); v_relevance|]) in v_sum_c ("constr",0,[| [|v_int|]; (* Rel *) [|v_id|]; (* Var *) [|v_fail "Meta"|]; (* Meta *) [|v_fail "Evar"|]; (* Evar *) [|v_sort|]; (* Sort *) [|v_constr;v_cast;v_constr|]; (* Cast *) [|v_binder_annot v_name;v_constr;v_constr|]; (* Prod *) [|v_binder_annot v_name;v_constr;v_constr|]; (* Lambda *) [|v_binder_annot v_name;v_constr;v_constr;v_constr|]; (* LetIn *) [|v_constr;v_array v_constr|]; (* App *) [|v_puniverses v_cst|]; (* Const *) [|v_puniverses v_ind|]; (* Ind *) [|v_puniverses v_cons|]; (* Construct *) [|v_caseinfo;v_instance; v_array v_constr; v_case_return; v_case_invert; v_constr; v_array v_case_branch|]; (* Case *) [|v_fix|]; (* Fix *) [|v_cofix|]; (* CoFix *) [|v_proj;v_relevance;v_constr|]; (* Proj *) [|v_uint63|]; (* v_int *) [|v_float64|]; (* Float *) [|v_string|]; (* v_string *) [|v_instance;v_array v_constr;v_constr;v_constr|] (* v_array *) |])) let v_rdecl = v_sum "rel_declaration" 0 [| [|v_binder_annot v_name; v_constr|]; (* LocalAssum *) [|v_binder_annot v_name; v_constr; v_constr|] |] (* LocalDef *) let v_rctxt = v_list v_rdecl let v_ndecl = v_sum "named_declaration" 0 [| [|v_binder_annot v_id; v_constr|]; (* LocalAssum *) [|v_binder_annot v_id; v_constr; v_constr|] |] (* LocalDef *) let v_nctxt = v_list v_ndecl let v_section_ctxt = v_enum "emptylist" 1 (** kernel/mod_subst *) let v_univ_abstracted v = v_tuple "univ_abstracted" [|v;v_abs_context|] let v_delta_hint = v_sum "delta_hint" 0 [|[|v_int; v_opt (v_univ_abstracted v_constr)|];[|v_kn|]|] let v_resolver = v_tuple "delta_resolver" [|v_mp; v_map v_mp v_mp; v_hmap v_kn v_delta_hint|] let v_subst = v_annot_c ("substitution", v_map v_mp v_resolver) (** kernel/lazyconstr *) let v_abstr_info = v_tuple_c ("abstr_info", [|v_nctxt; v_abs_context; v_instance|]) let v_abstr_inst_info = v_tuple_c ("abstr_inst_info", [|v_list v_id; v_instance|]) let v_expand_info = v_tuple_c ("expand_info", [|v_hmap v_cst v_abstr_inst_info; v_hmap v_cst v_abstr_inst_info|]) let v_cooking_info = v_tuple_c ("cooking_info", [|v_expand_info; v_abstr_info|]) let v_opaque = v_sum "opaque" 0 [|[|v_list v_subst; v_list v_cooking_info; v_dp; v_int|]|] (** kernel/declarations *) let v_conv_level = v_sum "conv_level" 2 [|[|v_int|]|] let v_oracle = v_tuple "oracle" [| v_map v_id v_conv_level; v_hmap v_cst v_conv_level; v_hmap v_proj_repr v_conv_level; v_pred v_id; v_pred v_cst; v_pred v_proj_repr; |] let v_template_universes = v_tuple "template_universes" [| v_list (v_opt v_sort); v_sort; v_abs_context; v_instance; |] let v_primitive = v_enum "primitive" 63 (* Number of constructors of the CPrimitives.t type *) let v_cst_def = v_sum "constant_def" 0 [|[|v_opt v_int|]; [|v_constr|]; [|v_opaque|]; [|v_primitive|]; [|v_bool|]|] let v_typing_flags = v_tuple "typing_flags" [|v_bool; v_bool; v_bool; v_oracle; v_bool; v_bool; v_bool; v_bool; v_bool; v_bool; v_bool|] let v_univs = v_sum "universes" 1 [|[|v_abs_context|]|] let v_vm_reloc_table = v_array (v_pair v_int v_int) let v_vm_annot_switch = v_tuple "vm_annot_switch" [|v_vm_reloc_table; v_bool; v_int|] let v_vm_caml_prim = v_enum "vm_caml_prim" 6 let v_non_subst_reloc = v_sum "vm_non_subst_reloc" 0 [| [|v_sort|]; [|v_fail "Evar"|]; [|v_int|]; [|v_instance|]; [|v_any|]; (* contains a Vmvalues.value *) [|v_uint63|]; [|v_float64|]; [|v_string|]; [|v_vm_annot_switch|]; [|v_vm_caml_prim|]; |] let v_reloc = v_sum "vm_reloc" 0 [| [|v_ind|]; [|v_cst|]; [|v_int|]; |] let v_vm_patches = v_tuple "vm_patches" [|v_array v_reloc|] let v_vm_pbody_code index = v_sum "pbody_code" 1 [| [|v_array v_bool; index; v_vm_patches|]; [|v_cst|]; |] let v_vm_index = v_pair v_dp v_int let v_vm_indirect_code = v_vm_pbody_code v_vm_index let v_vm_emitcodes = v_string let v_vm_fv_elem = v_sum "vm_fv_elem" 0 [| [|v_id|]; [|v_int|] |] let v_vm_fv = v_array v_vm_fv_elem let v_vm_positions = v_string let v_vm_to_patch = v_tuple "vm_to_patch" [|v_vm_emitcodes; v_vm_fv; v_vm_positions; v_array v_non_subst_reloc|] let v_cb = v_tuple "constant_body" [|v_section_ctxt; v_instance; v_cst_def; v_constr; v_relevance; v_opt v_vm_indirect_code; v_univs; v_bool; v_typing_flags|] let v_recarg_type = v_sum "recarg_type" 0 [|[|v_ind|] (* Mrec *);[|v_cst|] (* NestedPrimitive *)|] let v_recarg = v_sum "recarg" 1 (* Norec *) [|[|v_recarg_type|] (* Mrec *)|] let v_wfp = fix (fun v_wfp -> v_sum_c ("wf_paths",0, [|[|v_int;v_int|]; (* Rtree.Param *) [|v_recarg;v_array (v_array v_wfp)|]; (* Rtree.Node *) [|v_int;v_array v_wfp|] (* Rtree.Rec *) |])) let v_squash_info = v_sum "squash_info" 1 [|[|v_set v_quality|]|] let v_has_eta = v_enum "has_eta" 2 let v_record_info = v_sum "record_info" 2 [| [| v_id; v_array v_id; v_array v_relevance; v_array v_constr; v_has_eta |] |] let v_one_ind = v_tuple "one_inductive_body" [|v_id; v_rctxt; v_sort; v_constr; v_record_info; v_array v_id; v_array v_constr; v_int; v_int; v_opt v_squash_info; v_array (v_pair v_rctxt v_constr); v_array v_int; v_array v_int; v_wfp; v_relevance; v_int; v_int; v_vm_reloc_table|] let v_finite = v_enum "recursivity_kind" 3 let v_ind_pack = v_tuple "mutual_inductive_body" [|v_array v_one_ind; v_finite; v_section_ctxt; v_instance; v_int; v_int; v_rctxt; v_univs; (* universes *) v_opt v_template_universes; v_opt (v_array v_variance); v_opt (v_array v_variance); v_opt v_bool; v_typing_flags|] let v_prim_ind = v_enum "prim_ind" 6 (* Number of "Register ... as kernel.ind_..." in Primv_int63.v and PrimFloat.v *) let v_prim_type = v_enum "prim_type" 4 (* Number of constructors of prim_type in "kernel/cPrimitives.ml" *) let v_retro_action = v_sum "retro_action" 0 [| [|v_prim_ind; v_ind|]; [|v_prim_type; v_cst|]; |] let v_retroknowledge = v_sum "module_retroknowledge" 0 [|[|v_list v_retro_action|]|] let v_puniv = v_opt v_int let v_pqvar = v_opt v_int let v_quality_pattern = v_sum "quality_pattern" 0 [|[|v_pqvar|];[|v_constant_quality|]|] let v_instance_mask = v_pair (v_array v_quality_pattern) (v_array v_puniv) let v_sort_pattern = v_sum_c ("sort_pattern", 3, [|[|v_puniv|]; (* PSType *) [|v_pqvar; v_puniv|] (* PSQSort *) |]) let [_v_hpattern;v_elimination;_v_head_elim;_v_patarg] : _ Vector.t = mfix [();();();()] (fun [v_hpattern;v_elimination;v_head_elim;v_patarg] -> let v_hpattern = v_sum_c ("head_pattern", 0, [|[|v_int|]; (* PHRel *) [|v_sort_pattern|]; (* PHSort *) [|v_cst; v_instance_mask|]; (* PHSymbol *) [|v_ind; v_instance_mask|]; (* PHInd *) [|v_cons; v_instance_mask|]; (* PHConstr *) [|v_uint63|]; (* PHInt *) [|v_float64|]; (* PHFloat *) [|v_string|]; (* PHString *) [|v_array v_patarg; v_head_elim|]; (* PHLambda *) [|v_array v_patarg; v_patarg|]; (* PHProd *) |]) and v_elimination = v_sum_c ("pattern_elimination", 0, [|[|v_array v_patarg|]; (* PEApp *) [|v_ind; v_patarg; v_array v_patarg|]; (* PECase *) [|v_proj_repr|]; (* PEProj *) |]) and v_head_elim = v_tuple_c ("head*elims", [|v_hpattern; v_list v_elimination|]) and v_patarg = v_sum_c ("pattern_argument", 1, [|[|v_int|]; (* EHole *) [|v_head_elim|]; (* ERigid *) |]) in [v_hpattern;v_elimination;v_head_elim;v_patarg]) let v_rewrule = v_tuple "rewrite_rule" [| v_tuple "nvars" [| v_int; v_int; v_int |]; v_pair v_instance_mask (v_list v_elimination); v_constr |] let v_rrb = v_tuple "rewrite_rules_body" [| v_list (v_pair v_cst v_rewrule) |] let v_module_with_decl = v_sum "with_declaration" 0 [| [|v_list v_id; v_mp|]; [|v_list v_id; v_pair v_constr (v_opt v_abs_context)|]; |] let v_mae = fix (fun v_mae -> v_sum_c ("module_alg_expr",0, [|[|v_mp|]; (* SEBident *) [|v_mae;v_mp|]; (* SEBapply *) [|v_mae; v_module_with_decl|] (* SEBwith *) |])) let [_v_sfb;_v_struc;_v_sign;_v_mexpr;_v_impl;v_module;_v_modtype] : _ Vector.t = mfix [();();();();();();()] (fun [v_sfb;v_struc;v_sign;v_mexpr;v_impl;v_module;v_modtype] -> let v_noimpl = v_unit in let v_sfb = v_sum_c ("struct_field_body",0, [|[|v_cb|]; (* SFBconst *) [|v_ind_pack|]; (* SFBmind *) [|v_rrb|]; (* SFBrules *) [|v_module|]; (* SFBmodule *) [|v_modtype|] (* SFBmodtype *) |]) and v_struc = v_list (v_tuple_c ("label*sfb",[|v_id;v_sfb|])) and v_sign = v_sum_c ("module_sign",0, [|[|v_struc|]; (* NoFunctor *) [|v_uid;v_modtype;v_sign|]|]) (* MoreFunctor *) and v_mexpr = v_sum_c ("module_expr",0, [|[|v_mae|]; (* MENoFunctor *) [|v_mexpr|]|]) (* MEMoreFunctor *) and v_impl = v_sum_c ("module_impl",2, (* Abstract, FullStruct *) [|[|v_mexpr|]; (* Algebraic *) [|v_resolver; v_struc|]|]) (* Struct *) and v_module = v_tuple_c ("module_body", [|v_sum_c ("when_mod_body", 0, [|[|v_impl|]|]);v_sign;v_opt v_mexpr;v_resolver;v_retroknowledge|]) and v_modtype = v_tuple_c ("module_type_body", [|v_noimpl;v_sign;v_opt v_mexpr;v_resolver;v_unit|]) in [v_sfb;v_struc;v_sign;v_mexpr;v_impl;v_module;v_modtype]) (** kernel/safe_typing *) let v_vodigest = v_sum_c ("module_impl",0, [| [|v_string|]; [|v_string;v_string|] |]) let v_deps = v_array (v_tuple "dep" [|v_dp;v_vodigest|]) let v_flags = v_tuple "flags" [|v_bool|] (* Allow Rewrite Rules *) let v_compiled_lib = v_tuple "compiled" [|v_dp; v_module; v_univ_context_set; v_sort_context_set; v_deps; v_flags|] (** Toplevel structures in a vo (see Cic.mli) *) let v_libsum = v_tuple_c ("summary", [|v_dp;v_deps;v_string;v_any|]) let v_lib = v_tuple_c ("library",[|v_compiled_lib;v_any;v_any|]) let v_delayed_universes = v_sum_c ("delayed_universes", 0, [| [| v_unit |]; [| v_univ_context_set |] |]) let v_opaquetable = v_array (v_opt (v_pair v_constr v_delayed_universes)) let v_vmlib = v_tuple "vmlibrary" [|v_dp; v_array v_vm_to_patch|] rocq-9.2.0/checker/values.mli000066400000000000000000000035311516144147600161070ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* value -> bool val kind : value -> value kind val v_any : value val v_fail : string -> value val v_tuple : string -> value array -> value val v_sum : string -> int -> value array array -> value val v_array : value -> value val v_list : value -> value val v_opt : value -> value val v_int : value val v_string : value val v_annot : string -> value -> value val v_int64 : value val v_float64 : value (** Define a recursive value. [fix (fun v -> v)] is invalid. *) val fix : (value -> value) -> value val v_libsum : value val v_lib : value val v_opaquetable : value val v_vmlib : value rocq-9.2.0/checker/votour.ml000066400000000000000000000331051516144147600157750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* \tenter the -th child\n\ u\tgo up 1 level\n\ s\tsort\n\ l\ttreat current node as a list\n\ x\texit\n\n%!" let quit () = Printf.printf "\nGoodbye!\n%!"; exit 0 let rec read_num max = Printf.printf "# %!"; let l = try read_line () with End_of_file -> quit () in match l with | "u" -> CmdParent | "s" -> CmdSort | "x" -> CmdExit | "h" -> CmdHelp | "l" -> CmdList | _ -> match int_of_string l with | v -> if v < 0 || v >= max then let () = Printf.printf "Out-of-range input! (only %d children)\n%!" max in read_num max else CmdChild v | exception Failure _ -> Printf.printf "Unrecognized input! Input h for help\n%!"; read_num max type 'a repr = | INT of int | STRING of string | BLOCK of int * 'a array | OTHER module type S = sig type obj val input : in_channel -> obj val repr : obj -> obj repr val size : obj -> int val oid : obj -> int option end module ReprObj : S = struct type obj = Obj.t * int list let input chan = let obj = input_value chan in let () = CObj.register_shared_size obj in (obj, []) let repr (obj, pos) = if Obj.is_block obj then let tag = Obj.tag obj in if tag = Obj.string_tag then STRING (Obj.magic obj) else if tag < Obj.no_scan_tag then let init i = (Obj.field obj i, i :: pos) in let data = Array.init (Obj.size obj) init in BLOCK (tag, Obj.magic data) else OTHER else INT (Obj.magic obj) let size (_, p) = CObj.shared_size_of_pos p let oid _ = None end module ReprMem : S = struct open Analyze type obj = data let memory = ref LargeArray.empty let sizes = ref LargeArray.empty (** size, in words *) let ws = Sys.word_size / 8 let rec init_size seen k = function | Int _ | Atm _ | Fun _ -> k 0 | Ptr p -> if LargeArray.get seen p then k 0 else let () = LargeArray.set seen p true in match LargeArray.get !memory p with | Struct (tag, os) -> let len = Array.length os in let rec fold i accu k = if i == len then k accu else 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) | Int64 _ -> k 0 | Float64 _ -> k 0 | String s -> let size = 2 + (String.length s / ws) in let () = LargeArray.set !sizes p size in k size let size = function | Int _ | Atm _ | Fun _ -> 0 | Ptr p -> LargeArray.get !sizes p let repr = function | Int i -> INT i | Atm t -> BLOCK (t, [||]) | Fun _ -> OTHER | Ptr p -> match LargeArray.get !memory p with | Struct (tag, os) -> BLOCK (tag, os) | Int64 _ -> OTHER (* TODO: pretty-print int63 values *) | Float64 _ -> OTHER (* TODO: pretty-print float64 values *) | String s -> STRING s let input ch = let obj, mem = parse_channel ch in let () = memory := mem in let () = sizes := LargeArray.make (LargeArray.length mem) (-1) in let seen = LargeArray.make (LargeArray.length mem) false in let () = init_size seen ignore obj in obj let oid = function | Int _ | Atm _ | Fun _ -> None | Ptr p -> Some p end module Visit (Repr : S) : sig val init : unit -> unit val visit : Values.value -> Repr.obj -> int list -> unit end = struct (** Name of a value *) let rec get_name ?(extra=false) v = match kind v with |Any -> "?" |Fail s -> "Invalid node: "^s |Tuple (name,_) -> name |Sum (name,_,_) -> name |Array v -> "array"^(if extra then "/"^get_name ~extra v else "") |List v -> "list"^(if extra then "/"^get_name ~extra v else "") |Opt v -> "option"^(if extra then "/"^get_name ~extra v else "") |Int -> "int" |String -> "string" |Annot (s,v) -> s^"/"^get_name ~extra v | Int64 -> "Int64" | Float64 -> "Float64" (** For tuples, its quite handy to display the inner 1st string (if any). Cf. [structure_body] for instance *) exception TupleString of string let get_string_in_tuple o = try for i = 0 to Array.length o - 1 do match Repr.repr o.(i) with | STRING s -> let len = min max_string_length (String.length s) in raise (TupleString (Printf.sprintf " [..%s..]" (String.sub s 0 len))) | _ -> () done; "" with TupleString s -> s (** Some details : tags, integer value for non-block, etc etc *) let rec get_details v o = match kind v, Repr.repr o with | (String | Any), STRING s -> let len = min max_string_length (String.length s) in Printf.sprintf " [%s]" (String.escaped (String.sub s 0 len)) |Tuple (_,v), BLOCK (_, o) -> get_string_in_tuple o |(Sum _|Any), BLOCK (tag, _) -> Printf.sprintf " [tag=%i]" tag |(Sum _|Any), INT i -> Printf.sprintf " [imm=%i]" i |Int, INT i -> Printf.sprintf " [imm=%i]" i |Annot (s,v), _ -> get_details v o |_ -> "" let get_oid obj = match Repr.oid obj with | None -> "" | Some id -> Printf.sprintf " [0x%08x]" id let node_info (v,o,p) = get_name ~extra:true v ^ get_details v o ^ " (size "^ string_of_int (Repr.size o)^"w)" ^ get_oid o (** Children of a block : type, object, position. For lists, we collect all elements of the list at once *) let access_children vs os pos = if Array.length os = Array.length vs then Array.mapi (fun i v -> v, os.(i), i::pos) vs else raise_notrace Exit let access_list v o pos = let rec loop o pos accu = match Repr.repr o with | INT 0 -> List.rev accu | BLOCK (0, [|hd; tl|]) -> loop tl (1 :: pos) ((v, hd, 0 :: pos) :: accu) | _ -> raise_notrace Exit in Array.of_list (loop o pos []) let access_block o = match Repr.repr o with | BLOCK (tag, os) -> (tag, os) | _ -> raise_notrace Exit (** raises Exit if the object has not the expected structure *) exception Forbidden let rec get_children v o pos = match kind v with |Tuple (_, v) -> let (_, os) = access_block o in access_children v os pos |Sum (_, _, vv) -> begin match Repr.repr o with | BLOCK (tag, os) -> access_children vv.(tag) os pos | INT _ -> [||] | _ -> raise_notrace Exit end |Array v -> let (_, os) = access_block o in access_children (Array.make (Array.length os) v) os pos |List v -> access_list v o pos |Opt v -> begin match Repr.repr o with | INT 0 -> [||] | BLOCK (0, [|x|]) -> [|(v, x, 0 :: pos)|] | _ -> raise_notrace Exit end | String -> begin match Repr.repr o with | STRING _ -> [||] | _ -> raise_notrace Exit end | Int -> begin match Repr.repr o with | INT _ -> [||] | _ -> raise_notrace Exit end |Annot (s,v) -> get_children v o pos |Any -> raise_notrace Exit | Fail s -> raise Forbidden | Int64 -> raise_notrace Exit | Float64 -> raise_notrace Exit let get_children v o pos = try get_children v o pos with Exit -> match Repr.repr o with | BLOCK (_, os) -> Array.mapi (fun i o -> v_any, o, i :: pos) os | _ -> [||] type info = { nam : string; typ : value; obj : Repr.obj; pos : int list } let stk = ref ([] : info list) let init () = stk := [] let push name v o p = stk := { nam = name; typ = v; obj = o; pos = p } :: !stk exception EmptyStack let pop () = match !stk with | i::s -> stk := s; i | _ -> raise EmptyStack let print_state v o pos children = Printf.printf "\nDepth %d Pos %s Context %s\n" (List.length !stk) (String.concat "." (List.rev_map string_of_int pos)) (String.concat "/" (List.rev_map (fun i -> i.nam) !stk)); Printf.printf "-------------\n"; let nchild = Array.length children in Printf.printf "Here: %s, %d child%s\n" (node_info (v,o,pos)) nchild (if nchild = 0 then "" else "ren:"); Array.iter (fun (i, vop) -> Printf.printf " %d: %s\n" i (node_info vop)) children; Printf.printf "-------------\n" let rec visit v o pos = let children = get_children v o pos in let children = Array.mapi (fun i vop -> (i, vop)) children in let () = print_state v o pos children in read_command v o pos children and read_command v o pos children = try match read_num (Array.length children) with | CmdParent -> let info = pop () in visit info.typ info.obj info.pos | CmdChild child -> let _, (v',o',pos') = children.(child) in push (get_name v) v o pos; visit v' o' pos' | CmdSort -> let children = get_children v o pos in let children = Array.mapi (fun i vop -> (i, vop)) children in let sort (_, (_, o, _)) (_, (_, o', _)) = Int.compare (Repr.size o) (Repr.size o') in let sorted = Array.copy children in let () = Array.sort sort sorted in let () = print_state v o pos sorted in read_command v o pos children | CmdList -> visit (v_list v_any) o pos | CmdHelp -> let () = help () in read_command v o pos children | CmdExit -> quit () with | EmptyStack -> () | Forbidden -> let info = pop () in visit info.typ info.obj info.pos | Failure _ | Invalid_argument _ -> visit v o pos end (** Loading the vo *) type header = { magic : string; (** Magic number of the marshaller *) length : int; (** Size on disk in bytes *) size32 : int; (** Size in words when loaded on 32-bit systems *) size64 : int; (** Size in words when loaded on 64-bit systems *) objects : int; (** Number of blocks defined in the marshalled structure *) } let dummy_header = { magic = "\000\000\000\000"; length = 0; size32 = 0; size64 = 0; objects = 0; } let parse_header chan = let magic = really_input_string chan 4 in let length = input_binary_int chan in let objects = input_binary_int chan in let size32 = input_binary_int chan in let size64 = input_binary_int chan in { magic; length; size32; size64; objects } module ObjFile = struct type segment = { name : string; pos : int64; len : int64; hash : Digest.t; mutable header : header; } let input_int32 ch = let accu = ref 0l in for _i = 0 to 3 do let c = input_byte ch in accu := Int32.add (Int32.shift_left !accu 8) (Int32.of_int c) done; !accu let input_int64 ch = let accu = ref 0L in for _i = 0 to 7 do let c = input_byte ch in accu := Int64.add (Int64.shift_left !accu 8) (Int64.of_int c) done; !accu let input_segment_summary ch = let nlen = input_int32 ch in let name = really_input_string ch (Int32.to_int nlen) in let pos = input_int64 ch in let len = input_int64 ch in let hash = Digest.input ch in { name; pos; len; hash; header = dummy_header } let rec input_segment_summaries ch n accu = if Int32.equal n 0l then Array.of_list (List.rev accu) else let s = input_segment_summary ch in let accu = s :: accu in input_segment_summaries ch (Int32.pred n) accu let parse_segments ch = let magic = input_int32 ch in let version = input_int32 ch in let summary_pos = input_int64 ch in let () = LargeFile.seek_in ch summary_pos in let nsum = input_int32 ch in let seg = input_segment_summaries ch nsum [] in for i = 0 to Array.length seg - 1 do let () = LargeFile.seek_in ch seg.(i).pos in let header = parse_header ch in seg.(i).header <- header done; (magic, version, seg) end let visit_vo f = Printf.printf "\nWelcome to votour !\n"; Printf.printf "Enjoy your guided tour of a Rocq .vo or .vi file\n"; Printf.printf "Object sizes are in words (%d bits)\n" Sys.word_size; Printf.printf "Input h for help\n\n%!"; let known_segments = [ "summary", Values.v_libsum; "library", Values.v_lib; "opaques", Values.v_opaquetable; "vmlibrary", Values.v_vmlib; ] in let repr = if Sys.word_size = 64 then (module ReprMem : S) else (module ReprObj : S) (* On 32-bit machines, representation may exceed the max size of arrays *) in let module Repr = (val repr : S) in let module Visit = Visit(Repr) in while true do let ch = open_in_bin f in let (_magic, version, segments) = ObjFile.parse_segments ch in Printf.printf "File format: %ld\n%!" version; Printf.printf "The file has %d segments, choose the one to visit:\n" (Array.length segments); Array.iteri (fun i ObjFile.{ name; pos; header } -> let size = if Sys.word_size = 64 then header.size64 else header.size32 in Printf.printf " %d: %s, starting at byte %Ld (size %iw)\n" i name pos size) segments; match read_num (Array.length segments) with | CmdChild seg -> let seg = segments.(seg) in let open ObjFile in LargeFile.seek_in ch seg.pos; let o = Repr.input ch in let () = Visit.init () in let typ = try List.assoc seg.name known_segments with Not_found -> v_any in Visit.visit typ o [] | CmdParent | CmdSort | CmdList -> () | CmdHelp -> help () | CmdExit -> quit () done let () = if not !Sys.interactive then Arg.parse [] visit_vo ("votour: guided tour of a Rocq .vo or .vi file\n"^ "Usage: votour file.v[oi]") rocq-9.2.0/checker/votour.mli000066400000000000000000000014501516144147600161440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 then c else let rec loop i = if i < 0 then 0 else let x = uget v1 i in let y = uget v2 i in let c = cmp x y in if c <> 0 then c else loop (i - 1) in loop (len - 1) let equal_norefl cmp t1 t2 = let len = Array.length t1 in if not (Int.equal len (Array.length t2)) then false else let rec aux i = if i < 0 then true else let x = uget t1 i in let y = uget t2 i in cmp x y && aux (pred i) in aux (len - 1) let equal cmp t1 t2 = if t1 == t2 then true else equal_norefl cmp t1 t2 let is_empty array = Int.equal (Array.length array) 0 let exists2 f v1 v2 = let rec exrec = function | -1 -> false | n -> f (uget v1 n) (uget v2 n) || (exrec (n-1)) in let lv1 = Array.length v1 in lv1 = Array.length v2 && exrec (lv1-1) let for_all2 f v1 v2 = let rec allrec = function | -1 -> true | n -> let ans = f (uget v1 n) (uget v2 n) in ans && (allrec (n-1)) in let lv1 = Array.length v1 in lv1 = Array.length v2 && allrec (pred lv1) let for_all3 f v1 v2 v3 = let rec allrec = function | -1 -> true | n -> let ans = f (uget v1 n) (uget v2 n) (uget v3 n) in ans && (allrec (n-1)) in let lv1 = Array.length v1 in lv1 = Array.length v2 && lv1 = Array.length v3 && allrec (pred lv1) let for_all4 f v1 v2 v3 v4 = let rec allrec = function | -1 -> true | n -> let ans = f (uget v1 n) (uget v2 n) (uget v3 n) (uget v4 n) in ans && (allrec (n-1)) in let lv1 = Array.length v1 in lv1 = Array.length v2 && lv1 = Array.length v3 && lv1 = Array.length v4 && allrec (pred lv1) let for_all_i f i v = let len = Array.length v in let rec allrec i n = n = len || f i (uget v n) && allrec (i+1) (n+1) in allrec i 0 exception Found of int let findi (pred: int -> 'a -> bool) (arr: 'a array) : int option = try for i=0 to Array.length arr - 1 do if pred i (uget arr i) then raise (Found i) done; None with Found i -> Some i let find2_map (type a) pred arr1 arr2 = let exception Found of a in let n = Array.length arr1 in if not (Array.length arr2 = n) then failwith "Array.find2_map"; try for i=0 to n - 1 do match pred (Array.unsafe_get arr1 i) (Array.unsafe_get arr2 i) with | Some r -> raise (Found r) | None -> () done; None with Found i -> Some i let hd v = match Array.length v with | 0 -> failwith "Array.hd" | _ -> uget v 0 let tl v = match Array.length v with | 0 -> failwith "Array.tl" | n -> Array.sub v 1 (pred n) let last v = match Array.length v with | 0 -> failwith "Array.last" | n -> uget v (pred n) let cons e v = let len = Array.length v in let ans = Array.make (Array.length v + 1) e in let () = Array.blit v 0 ans 1 len in ans let rev t = let n=Array.length t in if n <=0 then () else for i = 0 to pred (n/2) do let tmp = uget t ((pred n)-i) in Array.unsafe_set t ((pred n)-i) (uget t i); Array.unsafe_set t i tmp done let fold_right_i f v a = let rec fold a n = if n=0 then a else let k = n-1 in fold (f k (uget v k) a) k in fold a (Array.length v) let fold_left_i f v a = let n = Array.length a in let rec fold i v = if i = n then v else fold (succ i) (f i v (uget a i)) in fold 0 v let fold_right2 f v1 v2 a = let lv1 = Array.length v1 in let rec fold a n = if n=0 then a else let k = n-1 in fold (f (uget v1 k) (uget v2 k) a) k in if Array.length v2 <> lv1 then invalid_arg "Array.fold_right2"; fold a lv1 let fold_left2 f a v1 v2 = let lv1 = Array.length v1 in let rec fold a n = if n >= lv1 then a else fold (f a (uget v1 n) (uget v2 n)) (succ n) in if Array.length v2 <> lv1 then invalid_arg "Array.fold_left2"; fold a 0 let fold_left2_i f a v1 v2 = let lv1 = Array.length v1 in let rec fold a n = if n >= lv1 then a else fold (f n a (uget v1 n) (uget v2 n)) (succ n) in if Array.length v2 <> lv1 then invalid_arg "Array.fold_left2_i"; fold a 0 let fold_right3 f v1 v2 v3 a = let lv1 = Array.length v1 in let rec fold a n = if n=0 then a else let k = n-1 in fold (f (uget v1 k) (uget v2 k) (uget v3 k) a) k in if Array.length v2 <> lv1 || Array.length v3 <> lv1 then invalid_arg "Array.fold_right3"; fold a lv1 let fold_left3 f a v1 v2 v3 = let lv1 = Array.length v1 in let rec fold a n = if n >= lv1 then a else fold (f a (uget v1 n) (uget v2 n) (uget v3 n)) (succ n) in if Array.length v2 <> lv1 || Array.length v3 <> lv1 then invalid_arg "Array.fold_left3"; fold a 0 let fold_left3_i f a v1 v2 v3 = let lv1 = Array.length v1 in let rec fold a n = if n >= lv1 then a else fold (f n a (uget v1 n) (uget v2 n) (uget v3 n)) (succ n) in if Array.length v2 <> lv1 || Array.length v3 <> lv1 then invalid_arg "Array.fold_left3_i"; fold a 0 let fold_left4 f a v1 v2 v3 v4 = let lv1 = Array.length v1 in let rec fold a n = if n >= lv1 then a else fold (f a (uget v1 n) (uget v2 n) (uget v3 n) (uget v4 n)) (succ n) in if Array.length v2 <> lv1 || Array.length v3 <> lv1 || Array.length v4 <> lv1 then invalid_arg "Array.fold_left4"; fold a 0 let fold_left_from n f a v = let len = Array.length v in let () = if n < 0 then invalid_arg "Array.fold_left_from" in let rec fold a n = if n >= len then a else fold (f a (uget v n)) (succ n) in fold a n let rev_of_list = function | [] -> [| |] | x :: l -> let len = List.length l in let ans = Array.make (succ len) x in let rec set i = function | [] -> () | x :: l -> Array.unsafe_set ans i x; set (pred i) l in let () = set (len - 1) l in ans let map_to_list = CList.map_of_array let map_of_list f l = let len = List.length l in let rec fill i v = function | [] -> () | x :: l -> Array.unsafe_set v i (f x); fill (succ i) v l in match l with | [] -> [||] | x :: l -> let ans = Array.make len (f x) in let () = fill 1 ans l in ans let chop n v = let vlen = Array.length v in if n > vlen then failwith "Array.chop"; (Array.sub v 0 n, Array.sub v n (vlen-n)) let split v = (Array.map fst v, Array.map snd v) let split3 v = (Array.map (fun (a, _, _) -> a) v, Array.map (fun (_, b, _) -> b) v, Array.map (fun (_, _, c) -> c) v) let split4 v = (Array.map (fun (a, _, _, _) -> a) v, Array.map (fun (_, b, _, _) -> b) v, Array.map (fun (_, _, c, _) -> c) v, Array.map (fun (_, _, _, d) -> d) v) let transpose a = let n = Array.length a in if n = 0 then [||] else let n' = Array.length (Array.unsafe_get a 0) in Array.init n' (fun i -> Array.init n (fun j -> a.(j).(i))) let map2_i f v1 v2 = let len1 = Array.length v1 in let len2 = Array.length v2 in let () = if not (Int.equal len1 len2) then invalid_arg "Array.map2" in if Int.equal len1 0 then [| |] else begin let res = Array.make len1 (f 0 (uget v1 0) (uget v2 0)) in for i = 1 to pred len1 do Array.unsafe_set res i (f i (uget v1 i) (uget v2 i)) done; res end let map3 f v1 v2 v3 = let len1 = Array.length v1 in let () = if len1 <> Array.length v2 || len1 <> Array.length v3 then invalid_arg "Array.map3" in if Int.equal len1 0 then [| |] else begin let res = Array.make len1 (f (uget v1 0) (uget v2 0) (uget v3 0)) in for i = 1 to pred len1 do Array.unsafe_set res i (f (uget v1 i) (uget v2 i) (uget v3 i)) done; res end let map3_i f v1 v2 v3 = let len1 = Array.length v1 in let len2 = Array.length v2 in let len3 = Array.length v3 in let () = if not (Int.equal len1 len2 && Int.equal len1 len3) then invalid_arg "Array.map3_i" in if Int.equal len1 0 then [| |] else begin let res = Array.make len1 (f 0 (uget v1 0) (uget v2 0) (uget v3 0)) in for i = 1 to pred len1 do Array.unsafe_set res i (f i (uget v1 i) (uget v2 i) (uget v3 i)) done; res end let map_left f a = (* Ocaml does not guarantee Array.map is LR *) let l = Array.length a in (* (even if so), then we rewrite it *) if Int.equal l 0 then [||] else begin let r = Array.make l (f (uget a 0)) in for i = 1 to l - 1 do Array.unsafe_set r i (f (uget a i)) done; r end let iter2_i f v1 v2 = let len1 = Array.length v1 in let len2 = Array.length v2 in let () = if not (Int.equal len2 len1) then invalid_arg "Array.iter2" in for i = 0 to len1 - 1 do f i (uget v1 i) (uget v2 i) done let iter3 f v1 v2 v3 = let len1 = Array.length v1 in let len2 = Array.length v2 in let len3 = Array.length v3 in let () = if not (Int.equal len2 len1) || not (Int.equal len1 len3) then invalid_arg "Array.iter3" in for i = 0 to len1 - 1 do f (uget v1 i) (uget v2 i) (uget v3 i) done let map_right f a = let l = length a in if l = 0 then [||] else begin let r = Array.make l (f (unsafe_get a (l-1))) in for i = l-2 downto 0 do unsafe_set r i (f (unsafe_get a i)) done; r end let map2_right f a b = let l = length a in if l <> length b then invalid_arg "CArray.map2_right: length mismatch"; if l = 0 then [||] else begin let r = Array.make l (f (unsafe_get a (l-1)) (unsafe_get b (l-1))) in for i = l-2 downto 0 do unsafe_set r i (f (unsafe_get a i) (unsafe_get b i)) done; r end let fold_right_map f v e = let e' = ref e in let v' = map_right (fun x -> let (y,e) = f x !e' in e' := e; y) v in (v',!e') let fold_left_map f e v = let e' = ref e in let v' = Array.map (fun x -> let (e,y) = f !e' x in e' := e; y) v in (!e',v') let fold_right2_map f v1 v2 e = let e' = ref e in let v' = map2_right (fun x1 x2 -> let (y,e) = f x1 x2 !e' in e' := e; y) v1 v2 in (v',!e') let fold_left2_map f e v1 v2 = let e' = ref e in let v' = map2 (fun x1 x2 -> let (e,y) = f !e' x1 x2 in e' := e; y) v1 v2 in (!e',v') let fold_left_map_i f e v = let e' = ref e in let v' = mapi (fun idx x -> let (e,y) = f idx !e' x in e' := e; y) v in (!e',v') let fold_left2_map_i f e v1 v2 = let e' = ref e in let v' = map2_i (fun idx x1 x2 -> let (e,y) = f idx !e' x1 x2 in e' := e; y) v1 v2 in (!e',v') let distinct v = let visited = Hashtbl.create 23 in try Array.iter (fun x -> if Hashtbl.mem visited x then raise_notrace Exit else Hashtbl.add visited x x) v; true with Exit -> false let rev_to_list a = let rec tolist i res = if i >= Array.length a then res else tolist (i+1) (uget a i :: res) in tolist 0 [] let filter_with filter v = Array.of_list (CList.filter_with filter (Array.to_list v)) module Smart = struct (* If none of the elements is changed by f we return ar itself. The while loop looks for the first such an element. If found, we break here and the new array is produced, but f is not re-applied to elements that are already checked *) let map f (ar : 'a array) = let len = Array.length ar in let i = ref 0 in let break = ref true in let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let v' = f v in if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin (* The array is not the same as the original one *) let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ans !i in let v' = f v in if v != v' then Array.unsafe_set ans !i v'; incr i done; ans end else ar (* Same as map_i but smart *) let map_i f (ar : 'a array) = let len = Array.length ar in let i = ref 0 in let break = ref true in let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let v' = f !i v in if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin (* The array is not the same as the original one *) let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ans !i in let v' = f !i v in if v != v' then Array.unsafe_set ans !i v'; incr i done; ans end else ar let map2 f aux_ar ar = let len = Array.length ar in let aux_len = Array.length aux_ar in let () = if not (Int.equal len aux_len) then invalid_arg "Array.Smart.map2" in let i = ref 0 in let break = ref true in let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let w = Array.unsafe_get aux_ar !i in let v' = f w v in if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin (* The array is not the same as the original one *) let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ans !i in let w = Array.unsafe_get aux_ar !i in let v' = f w v in if v != v' then Array.unsafe_set ans !i v'; incr i done; ans end else ar (** Same as [Smart.map] but threads a state meanwhile *) let fold_left_map f accu (ar : 'a array) = let len = Array.length ar in let i = ref 0 in let break = ref true in let r = ref accu in (* This variable is never accessed unset *) let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let (accu, v') = f !r v in r := accu; if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ar !i in let (accu, v') = f !r v in r := accu; if v != v' then Array.unsafe_set ans !i v'; incr i done; !r, ans end else !r, ar (** Same as [Smart.mapi] but threads a state meanwhile *) let fold_left_map_i f accu (ar : 'a array) = let len = Array.length ar in let i = ref 0 in let break = ref true in let r = ref accu in (* This variable is never accessed unset *) let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let (accu, v') = f !i !r v in r := accu; if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ar !i in let (accu, v') = f !i !r v in r := accu; if v != v' then Array.unsafe_set ans !i v'; incr i done; !r, ans end else !r, ar (** Same as [Smart.map2] but threads a state meanwhile *) let fold_left2_map f accu aux_ar ar = let len = Array.length ar in let aux_len = Array.length aux_ar in let () = if not (Int.equal len aux_len) then invalid_arg "Array.Smart.fold_left2_map" in let i = ref 0 in let break = ref true in let r = ref accu in (* This variable is never accessed unset *) let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let w = Array.unsafe_get aux_ar !i in let (accu, v') = f !r w v in r := accu; if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ar !i in let w = Array.unsafe_get aux_ar !i in let (accu, v') = f !r w v in r := accu; if v != v' then Array.unsafe_set ans !i v'; incr i done; !r, ans end else !r, ar end module Fun1 = struct let map f arg v = match v with | [| |] -> [| |] | _ -> let len = Array.length v in let x0 = Array.unsafe_get v 0 in let ans = Array.make len (f arg x0) in for i = 1 to pred len do let x = Array.unsafe_get v i in Array.unsafe_set ans i (f arg x) done; ans let iter f arg v = let len = Array.length v in for i = 0 to pred len do let x = uget v i in f arg x done let iter2 f arg v1 v2 = let len1 = Array.length v1 in let len2 = Array.length v2 in let () = if not (Int.equal len2 len1) then invalid_arg "Array.Fun1.iter2" in for i = 0 to pred len1 do let x1 = uget v1 i in let x2 = uget v2 i in f arg x1 x2 done module Smart = struct let map f arg (ar : 'a array) = let len = Array.length ar in let i = ref 0 in let break = ref true in let temp = ref None in while !break && (!i < len) do let v = Array.unsafe_get ar !i in let v' = f arg v in if v == v' then incr i else begin break := false; temp := Some v'; end done; if !i < len then begin (* The array is not the same as the original one *) let ans : 'a array = Array.copy ar in let v = match !temp with None -> assert false | Some x -> x in Array.unsafe_set ans !i v; incr i; while !i < len do let v = Array.unsafe_get ans !i in let v' = f arg v in if v != v' then Array.unsafe_set ans !i v'; incr i done; ans end else ar end end rocq-9.2.0/clib/cArray.mli000066400000000000000000000201111516144147600153270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a -> int) -> 'a array -> 'a array -> int (** First size comparison, then lexicographic order. *) val equal : ('a -> 'a -> bool) -> 'a array -> 'a array -> bool (** Lift equality to array type. *) val equal_norefl : ('a -> 'a -> bool) -> 'a array -> 'a array -> bool (** Like {!equal} but does not assume that equality is reflexive: no optimisation is performed if both arrays are physically the same. *) val is_empty : 'a array -> bool (** True whenever the array is empty. *) val exists2 : ('a -> 'b -> bool) -> 'a array -> 'b array -> bool val for_all2 : ('a -> 'b -> bool) -> 'a array -> 'b array -> bool val for_all3 : ('a -> 'b -> 'c -> bool) -> 'a array -> 'b array -> 'c array -> bool val for_all4 : ('a -> 'b -> 'c -> 'd -> bool) -> 'a array -> 'b array -> 'c array -> 'd array -> bool val for_all_i : (int -> 'a -> bool) -> int -> 'a array -> bool val findi : (int -> 'a -> bool) -> 'a array -> int option val find2_map : ('a -> 'b -> 'c option) -> 'a array -> 'b array -> 'c option (** First result which is not None, or None; [Failure "Array.find2_map"] if the arrays don't have the same length *) val hd : 'a array -> 'a (** First element of an array, or [Failure "Array.hd"] if empty. *) val tl : 'a array -> 'a array (** Remaining part of [hd], or [Failure "Array.tl"] if empty. *) val last : 'a array -> 'a (** Last element of an array, or [Failure "Array.last"] if empty. *) val cons : 'a -> 'a array -> 'a array (** Append an element on the left. *) val rev : 'a array -> unit (** In place reversal. *) val fold_right_i : (int -> 'b -> 'a -> 'a) -> 'b array -> 'a -> 'a val fold_left_i : (int -> 'a -> 'b -> 'a) -> 'a -> 'b array -> 'a val fold_right2 : ('a -> 'b -> 'c -> 'c) -> 'a array -> 'b array -> 'c -> 'c val fold_right3 : ('a -> 'b -> 'c -> 'd -> 'd) -> 'a array -> 'b array -> 'c array -> 'd -> 'd val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b array -> 'c array -> 'a val fold_left3 : ('a -> 'b -> 'c -> 'd -> 'a) -> 'a -> 'b array -> 'c array -> 'd array -> 'a val fold_left4 : ('a -> 'b -> 'c -> 'd -> 'e -> 'a) -> 'a -> 'b array -> 'c array -> 'd array -> 'e array -> 'a val fold_left2_i : (int -> 'a -> 'b -> 'c -> 'a) -> 'a -> 'b array -> 'c array -> 'a val fold_left3_i : (int -> 'a -> 'b -> 'c -> 'd -> 'a) -> 'a -> 'b array -> 'c array -> 'd array -> 'a val fold_left_from : int -> ('a -> 'b -> 'a) -> 'a -> 'b array -> 'a val map_to_list : ('a -> 'b) -> 'a array -> 'b list (** Composition of [map] and [to_list]. *) val map_of_list : ('a -> 'b) -> 'a list -> 'b array (** Composition of [map] and [of_list]. *) val chop : int -> 'a array -> 'a array * 'a array (** [chop i a] returns [(a1, a2)] s.t. [a = a1 + a2] and [length a1 = n]. Raise [Failure "Array.chop"] if [i] is not a valid index. *) val split : ('a * 'b) array -> 'a array * 'b array val split3 : ('a * 'b * 'c) array -> 'a array * 'b array * 'c array val split4 : ('a * 'b * 'c * 'd) array -> 'a array * 'b array * 'c array * 'd array val transpose : 'a array array -> 'a array array val map2_i : (int -> 'a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array val map3 : ('a -> 'b -> 'c -> 'd) -> 'a array -> 'b array -> 'c array -> 'd array val map3_i : (int -> 'a -> 'b -> 'c -> 'd) -> 'a array -> 'b array -> 'c array -> 'd array val map_left : ('a -> 'b) -> 'a array -> 'b array (** As [map] but guaranteed to be left-to-right. *) val iter2_i : (int -> 'a -> 'b -> unit) -> 'a array -> 'b array -> unit (** Iter on two arrays. Raise [Invalid_argument "Array.iter2_i"] if sizes differ. *) val iter3 : ('a -> 'b -> 'c -> unit) -> 'a array -> 'b array -> 'c array -> unit (** Iter on three arrays. Raise [Invalid_argument "Array.iter3"] if sizes differ. *) val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b array -> 'a * 'c array (** [fold_left_map f e_0 [|l_1...l_n|] = e_n,[|k_1...k_n|]] where [(e_i,k_i)=f e_{i-1} l_i]; see also [Smart.fold_left_map] *) val fold_right_map : ('a -> 'c -> 'b * 'c) -> 'a array -> 'c -> 'b array * 'c (** Same, folding on the right *) val fold_left_map_i : (int -> 'a -> 'b -> 'a * 'c) -> 'a -> 'b array -> 'a * 'c array (** Same than [fold_left_map] but passing the index of the array *) val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'd) -> 'a -> 'b array -> 'c array -> 'a * 'd array (** Same with two arrays, folding on the left; see also [Smart.fold_left2_map] *) val fold_left2_map_i : (int -> 'a -> 'b -> 'c -> 'a * 'd) -> 'a -> 'b array -> 'c array -> 'a * 'd array (** Same than [fold_left2_map] but passing the index of the array *) val fold_right2_map : ('a -> 'b -> 'c -> 'd * 'c) -> 'a array -> 'b array -> 'c -> 'd array * 'c (** Same with two arrays, folding on the right *) val distinct : 'a array -> bool (** Return [true] if every element of the array is unique (for default equality). *) val rev_of_list : 'a list -> 'a array (** [rev_of_list l] is equivalent to [Array.of_list (List.rev l)]. *) val rev_to_list : 'a array -> 'a list (** [rev_to_list a] is equivalent to [List.rev (List.of_array a)]. *) val filter_with : bool list -> 'a array -> 'a array (** [filter_with b a] selects elements of [a] whose corresponding element in [b] is [true]. Raise [Invalid_argument _] when sizes differ. *) module Smart : sig val map : ('a -> 'a) -> 'a array -> 'a array (** [Smart.map f a] behaves as [map f a] but returns [a] instead of a copy when [f x == x] for all [x] in [a]. *) val map_i : (int -> 'a -> 'a) -> 'a array -> 'a array val map2 : ('a -> 'b -> 'b) -> 'a array -> 'b array -> 'b array (** [Smart.map2 f a b] behaves as [map2 f a b] but returns [a] instead of a copy when [f x y == y] for all [x] in [a] and [y] in [b] pointwise. *) val fold_left_map : ('a -> 'b -> 'a * 'b) -> 'a -> 'b array -> 'a * 'b array (** [Smart.fold_left_map f a b] behaves as [fold_left_map] but returns [b] as second component instead of a copy of [b] when the output array is pointwise the same as the input array [b] *) val fold_left_map_i : (int -> 'a -> 'b -> 'a * 'b) -> 'a -> 'b array -> 'a * 'b array (** [Smart.fold_left_map_i f a b] behaves as [fold_left_map_i] but returns [b] as second component instead of a copy of [b] when the output array is pointwise the same as the input array [b] *) val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'c) -> 'a -> 'b array -> 'c array -> 'a * 'c array (** [Smart.fold_left2_map f a b c] behaves as [fold_left2_map] but returns [c] as second component instead of a copy of [c] when the output array is pointwise the same as the input array [c] *) end (** The functions defined in this module are optimized specializations of the main ones, when the returned array is of same type as one of the original array. *) module Fun1 : sig val map : ('r -> 'a -> 'b) -> 'r -> 'a array -> 'b array (** [Fun1.map f x v = map (f x) v] *) val iter : ('r -> 'a -> unit) -> 'r -> 'a array -> unit (** [Fun1.iter f x v = iter (f x) v] *) val iter2 : ('r -> 'a -> 'b -> unit) -> 'r -> 'a array -> 'b array -> unit (** [Fun1.iter2 f x v1 v2 = iter (f x) v1 v2] *) module Smart : sig val map : ('r -> 'a -> 'a) -> 'r -> 'a array -> 'a array (** [Fun1.Smart.map f x v = Smart.map (f x) v] *) end end (** The functions defined in this module are the same as the main ones, except that they are all higher-order, and their function arguments have an additional parameter. This allows us to prevent closure creation in critical cases. *) rocq-9.2.0/clib/cEphemeron.ml000066400000000000000000000067171516144147600160420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* a | _ -> b *) if x.0 == constr_Y then a else b and the polymorphic comparison function works like: let equal = fun (c1, ...) (c2, ...) -> c1.id == c2.id In every new extension constructor, the name field is a constant string and the id field is filled with an unique[1] value returned by %caml_fresh_oo_id. Moreover, every value of an extensible variant type is allocated as a new block. [1]: On 64-bit systems. On 32-bit systems, calling %caml_fresh_oo_id 2**30 times will result in a wraparound. Note that this does not affect soundness because constructors are compared by physical equality during matching. See OCaml PR7809 for code demonstrating this. An extensible variant can be marshalled and unmarshalled, and is guaranteed to not be equal to itself after unmarshalling, since the id field is filled with another unique value. Note that the explanation above is purely informative and we do not depend on the exact representation of extensible variants, only on the fact that no two constructor representations ever alias. In particular, if the definition of constr is replaced with: type constr = int (where the value is truly unique for every created constructor), correctness is preserved. *) type 'a typ = .. (* Erases the contained type so that the key can be put in a hash table. *) type boxkey = Box : 'a typ -> boxkey [@@unboxed] (* Carry the type we just erased with the actual key. *) type 'a key = 'a typ * boxkey module EHashtbl = Ephemeron.K1.Make(struct type t = boxkey let equal = (==) let hash = Hashtbl.hash end) type value = { get : 'k. 'k typ -> 'k } [@@unboxed] let values : value EHashtbl.t = EHashtbl.create 1001 let create : type v. v -> v key = fun value -> let module M = struct type _ typ += Typ : v typ let get : type k. k typ -> k = fun typ -> match typ with | Typ -> value | _ -> assert false let boxkey = Box Typ let key = Typ, boxkey let value = { get } end in EHashtbl.add values M.boxkey M.value; M.key (* Avoid raising Not_found *) exception InvalidKey let get (typ, boxkey) = try (EHashtbl.find values boxkey).get typ with Not_found -> raise InvalidKey let default (typ, boxkey) default = try (EHashtbl.find values boxkey).get typ with Not_found -> default let clean () = EHashtbl.clean values rocq-9.2.0/clib/cEphemeron.mli000066400000000000000000000046111516144147600162020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a key exception InvalidKey val get : 'a key -> 'a (** May raise InvalidKey *) val default : 'a key -> 'a -> 'a (** Never fails. *) val clean : unit -> unit rocq-9.2.0/clib/cList.ml000066400000000000000000000625411516144147600150300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int type 'a eq = 'a -> 'a -> bool include List (** Tail-rec implementation of usual functions. This is a well-known trick used in, for instance, ExtLib and Batteries. *) type 'a cell = { head : 'a; mutable tail : 'a list; } external cast : 'a cell -> 'a list = "%identity" (** Extensions and redefinitions of OCaml Stdlib *) (** {6 Equality, testing} *) let rec same_length l1 l2 = match l1, l2 with | [], [] -> true | _ :: l1, _ :: l2 -> same_length l1 l2 | ([], _ :: _) | (_ :: _, []) -> false let rec compare cmp l1 l2 = if l1 == l2 then 0 else match l1,l2 with | [], [] -> 0 | _::_, [] -> 1 | [], _::_ -> -1 | x1::l1, x2::l2 -> match cmp x1 x2 with | 0 -> compare cmp l1 l2 | c -> c let rec equal cmp l1 l2 = l1 == l2 || match l1, l2 with | [], [] -> true | x1 :: l1, x2 :: l2 -> cmp x1 x2 && equal cmp l1 l2 | _ -> false let is_empty = function | [] -> true | _ -> false let mem_f cmp x l = List.exists (cmp x) l let for_all_i p = let rec for_all_p i = function | [] -> true | a::l -> p i a && for_all_p (i+1) l in for_all_p let for_all2eq f l1 l2 = try List.for_all2 f l1 l2 with Invalid_argument _ -> false let exists_i p = let rec exists_p i = function | [] -> false | a::l -> p i a || exists_p (i+1) l in exists_p let prefix_of cmp prefl l = let rec prefrec = function | (h1::t1, h2::t2) -> cmp h1 h2 && prefrec (t1,t2) | ([], _) -> true | _ -> false in prefrec (prefl,l) (** {6 Creating lists} *) let interval n m = let rec interval_n (l,m) = if n > m then l else interval_n (m::l, pred m) in interval_n ([], m) let addn n v = let rec aux n l = if Int.equal n 0 then l else aux (pred n) (v :: l) in if n < 0 then invalid_arg "List.addn" else aux n let make n v = addn n v [] let rec init_loop len f p i = if Int.equal i len then () else let c = { head = f i; tail = [] } in p.tail <- cast c; init_loop len f c (succ i) let init len f = if len < 0 then invalid_arg "List.init" else if Int.equal len 0 then [] else let c = { head = f 0; tail = [] } in init_loop len f c 1; cast c let rec append_loop p tl = function | [] -> p.tail <- tl | x :: l -> let c = { head = x; tail = [] } in p.tail <- cast c; append_loop c tl l let append l1 l2 = match l1 with | [] -> l2 | x :: l -> let c = { head = x; tail = [] } in append_loop c l2 l; cast c let rec copy p = function | [] -> p | x :: l -> let c = { head = x; tail = [] } in p.tail <- cast c; copy c l let rec concat_loop p = function | [] -> () | x :: l -> concat_loop (copy p x) l let concat l = let dummy = { head = Obj.magic 0; tail = [] } in concat_loop dummy l; dummy.tail let flatten = concat (** {6 Lists as arrays} *) let assign l n e = let rec assrec stk l i = match l, i with | (h :: t, 0) -> List.rev_append stk (e :: t) | (h :: t, n) -> assrec (h :: stk) t (pred n) | ([], _) -> failwith "List.assign" in assrec [] l n (** {6 Filtering} *) (* [filter_loop f (Some (c0,l0)) c l] will do c0.tail <- l0 if [for_all f l] *) let rec filter_loop f reset p = function | [] -> begin match reset with | None -> () | Some (c,orig) -> c.tail <- orig end | x :: l as orig -> if f x then let c = { head = x; tail = [] } in let () = p.tail <- cast c in let reset = match reset with | Some _ -> reset | None -> Some (p,orig) in filter_loop f reset c l else filter_loop f None p l let rec filter f = function | [] -> [] | x :: l' as orig -> if f x then let c = { head = x; tail = [] } in filter_loop f None c l'; if c.tail == l' then orig else cast c else filter f l' let rec filter2_loop f p q l1 l2 = match l1, l2 with | [], [] -> () | x :: l1', y :: l2' -> let b = f x y in filter2_loop f p q l1' l2'; if b then if p.tail == l1' then begin p.tail <- l1; q.tail <- l2 end else begin p.tail <- x :: p.tail; q.tail <- y :: q.tail end | _ -> invalid_arg "List.filter2" let rec filter2 f l1 l2 = match l1, l2 with | [], [] -> ([],[]) | x1 :: l1', x2 :: l2' -> let b = f x1 x2 in if b then let c1 = { head = x1; tail = [] } in let c2 = { head = x2; tail = [] } in filter2_loop f c1 c2 l1' l2'; if c1.tail == l1' then (l1, l2) else (cast c1, cast c2) else filter2 f l1' l2' | _ -> invalid_arg "List.filter2" let filteri p = let rec filter_i_rec i = function | [] -> [] | x :: l -> let l' = filter_i_rec (succ i) l in if p i x then x :: l' else l' in filter_i_rec 0 let rec filter_with_loop filter p l = match filter, l with | [], [] -> () | b :: filter, x :: l' -> filter_with_loop filter p l'; if b then if p.tail == l' then p.tail <- l else p.tail <- x :: p.tail | _ -> invalid_arg "List.filter_with" let rec filter_with filter l = match filter, l with | [], [] -> [] | b :: filter, x :: l' -> if b then let c = { head = x; tail = [] } in filter_with_loop filter c l'; if c.tail == l' then l else cast c else filter_with filter l' | _ -> invalid_arg "List.filter_with" let rec map_filter_loop f p = function | [] -> () | x :: l -> match f x with | None -> map_filter_loop f p l | Some y -> let c = { head = y; tail = [] } in p.tail <- cast c; map_filter_loop f c l let rec map_filter f = function | [] -> [] | x :: l' -> match f x with | None -> map_filter f l' | Some y -> let c = { head = y; tail = [] } in map_filter_loop f c l'; cast c let rec map_filter_i_loop f i p = function | [] -> () | x :: l -> match f i x with | None -> map_filter_i_loop f (succ i) p l | Some y -> let c = { head = y; tail = [] } in p.tail <- cast c; map_filter_i_loop f (succ i) c l let rec map_filter_i_loop' f i = function | [] -> [] | x :: l' -> match f i x with | None -> map_filter_i_loop' f (succ i) l' | Some y -> let c = { head = y; tail = [] } in map_filter_i_loop f (succ i) c l'; cast c let map_filter_i f l = map_filter_i_loop' f 0 l let partitioni p = let rec aux i = function | [] -> [], [] | x :: l -> let (l1, l2) = aux (succ i) l in if p i x then (x :: l1, l2) else (l1, x :: l2) in aux 0 (** {6 Applying functorially} *) let rec map_loop f p = function | [] -> () | x :: l -> let c = { head = f x; tail = [] } in p.tail <- cast c; map_loop f c l let map f = function | [] -> [] | x :: l -> let c = { head = f x; tail = [] } in map_loop f c l; cast c let rec map2_loop f p l1 l2 = match l1, l2 with | [], [] -> () | x :: l1, y :: l2 -> let c = { head = f x y; tail = [] } in p.tail <- cast c; map2_loop f c l1 l2 | _ -> invalid_arg "List.map2" let map2 f l1 l2 = match l1, l2 with | [], [] -> [] | x :: l1, y :: l2 -> let c = { head = f x y; tail = [] } in map2_loop f c l1 l2; cast c | _ -> invalid_arg "List.map2" (* remove when requiring OCaml >= 5.1.0 *) let rec concat_map_loop f p = function | [] -> () | x :: l -> concat_map_loop f (copy p (f x)) l (* remove when requiring OCaml >= 5.1.0 *) let concat_map f l = let dummy = { head = Obj.magic 0; tail = [] } in concat_map_loop f dummy l; dummy.tail (** Like OCaml [List.mapi] but tail-recursive *) let rec map_i_loop f i p = function | [] -> () | x :: l -> let c = { head = f i x; tail = [] } in p.tail <- cast c; map_i_loop f (succ i) c l let map_i f i = function | [] -> [] | x :: l -> let c = { head = f i x; tail = [] } in map_i_loop f (succ i) c l; cast c let map_left = map let map2_i f i l1 l2 = let rec map_i i = function | ([], []) -> [] | (h1 :: t1, h2 :: t2) -> let v = f i h1 h2 in v :: map_i (succ i) (t1,t2) | (_, _) -> invalid_arg "map2_i" in map_i i (l1,l2) let rec map3_loop f p l1 l2 l3 = match l1, l2, l3 with | [], [], [] -> () | x :: l1, y :: l2, z :: l3 -> let c = { head = f x y z; tail = [] } in p.tail <- cast c; map3_loop f c l1 l2 l3 | _ -> invalid_arg "List.map3" let map3 f l1 l2 l3 = match l1, l2, l3 with | [], [], [] -> [] | x :: l1, y :: l2, z :: l3 -> let c = { head = f x y z; tail = [] } in map3_loop f c l1 l2 l3; cast c | _ -> invalid_arg "List.map3" let rec map4_loop f p l1 l2 l3 l4 = match l1, l2, l3, l4 with | [], [], [], [] -> () | x :: l1, y :: l2, z :: l3, t :: l4 -> let c = { head = f x y z t; tail = [] } in p.tail <- cast c; map4_loop f c l1 l2 l3 l4 | _ -> invalid_arg "List.map4" let map4 f l1 l2 l3 l4 = match l1, l2, l3, l4 with | [], [], [], [] -> [] | x :: l1, y :: l2, z :: l3, t :: l4 -> let c = { head = f x y z t; tail = [] } in map4_loop f c l1 l2 l3 l4; cast c | _ -> invalid_arg "List.map4" let rec map_until_loop f p = function | [] -> [] | x :: l as l' -> match f x with | None -> l' | Some fx -> let c = { head = fx; tail = [] } in p.tail <- cast c; map_until_loop f c l let map_until f = function | [] -> [], [] | x :: l as l' -> match f x with | None -> [], l' | Some fx -> let c = { head = fx; tail = [] } in let l = map_until_loop f c l in cast c, l let rec map_of_array_loop f p a i l = if Int.equal i l then () else let c = { head = f (Array.unsafe_get a i); tail = [] } in p.tail <- cast c; map_of_array_loop f c a (i + 1) l let map_of_array f a = let l = Array.length a in if Int.equal l 0 then [] else let c = { head = f (Array.unsafe_get a 0); tail = [] } in map_of_array_loop f c a 1 l; cast c let map_append f l = flatten (map f l) let map_append2 f l1 l2 = flatten (map2 f l1 l2) let rec extend l a l' = match l,l' with | true :: l, b :: l' -> b :: extend l a l' | false :: l, l' -> a :: extend l a l' | [], [] -> [] | _ -> invalid_arg "extend" let count f l = let rec aux acc = function | [] -> acc | h :: t -> if f h then aux (acc + 1) t else aux acc t in aux 0 l (** {6 Finding position} *) let rec index_f f x l n = match l with | [] -> raise Not_found | y :: l -> if f x y then n else index_f f x l (succ n) let index f x l = index_f f x l 1 let index_opt f x l = try Some (index f x l) with Not_found -> None let index0 f x l = index_f f x l 0 (** {6 Folding} *) let fold_left_error f accu s = let rec aux accu = function | [] -> Ok accu | x :: xs -> match f accu x with Error _ as x -> x | Ok i -> aux i xs in aux accu s let fold_left_until f accu s = let rec aux accu = function | [] -> accu | x :: xs -> match f accu x with CSig.Stop x -> x | CSig.Cont i -> aux i xs in aux accu s let fold_right_i f i l = let rec it_f i l a = match l with | [] -> a | b :: l -> f (i-1) b (it_f (i-1) l a) in it_f (List.length l + i) l let fold_left_i f = let rec it_list_f i a = function | [] -> a | b :: l -> it_list_f (i+1) (f i a b) l in it_list_f let rec fold_left3 f accu l1 l2 l3 = match (l1, l2, l3) with | ([], [], []) -> accu | (a1 :: l1, a2 :: l2, a3 :: l3) -> fold_left3 f (f accu a1 a2 a3) l1 l2 l3 | (_, _, _) -> invalid_arg "List.fold_left3" let rec fold_left4 f accu l1 l2 l3 l4 = match (l1, l2, l3, l4) with | ([], [], [], []) -> accu | (a1 :: l1, a2 :: l2, a3 :: l3, a4 :: l4) -> fold_left4 f (f accu a1 a2 a3 a4) l1 l2 l3 l4 | (_, _, _, _) -> invalid_arg "List.fold_left4" let rec fold_left5 f accu l1 l2 l3 l4 l5 = match (l1, l2, l3, l4, l5) with | ([], [], [], [], []) -> accu | (a1 :: l1, a2 :: l2, a3 :: l3, a4 :: l4, a5 :: l5) -> fold_left5 f (f accu a1 a2 a3 a4 a5) l1 l2 l3 l4 l5 | (_, _, _, _, _) -> invalid_arg "List.fold_left5" (* [fold_right_and_left f [a1;...;an] hd = f (f (... (f (f hd an [an-1;...;a1]) an-1 [an-2;...;a1]) ...) a2 [a1]) a1 []] *) let fold_right_and_left f l hd = let rec aux tl = function | [] -> hd | a :: l -> let hd = aux (a :: tl) l in f hd a tl in aux [] l (* Match sets as lists according to a matching function, also folding a side effect *) let rec fold_left2_set e f x l1 l2 = match l1 with | a1 :: l1 -> let rec find seen = function | [] -> raise e | a2 :: l2 -> try fold_left2_set e f (f x a1 a2 l1 l2) l1 (List.rev_append seen l2) with e' when e' = e -> find (a2 :: seen) l2 in find [] l2 | [] -> if l2 = [] then x else raise e (* Poor man's monadic map *) let rec fold_left_map f e = function | [] -> (e,[]) | h :: t -> let e',h' = f e h in let e'',t' = fold_left_map f e' t in e'',h' :: t' (* (* tail-recursive version of the above function *) let fold_left_map f e l = let g (e,b') h = let (e',h') = f e h in (e',h'::b') in let (e',lrev) = List.fold_left g (e,[]) l in (e',List.rev lrev) *) (* The same, based on fold_right, with the effect accumulated on the right *) let fold_right_map f l e = List.fold_right (fun x (l,e) -> let (y,e) = f x e in (y::l,e)) l ([],e) let on_snd f (x,y) = (x,f y) let fold_left2_map f e l l' = on_snd List.rev @@ List.fold_left2 (fun (e,l) x x' -> let (e,y) = f e x x' in (e, y::l) ) (e, []) l l' let fold_right2_map f l l' e = List.fold_right2 (fun x x' (l,e) -> let (y,e) = f x x' e in (y::l,e)) l l' ([],e) let fold_left3_map f e l l' l'' = on_snd List.rev @@ fold_left3 (fun (e,l) x x' x'' -> let (e,y) = f e x x' x'' in (e,y::l)) (e,[]) l l' l'' let fold_left4_map f e l1 l2 l3 l4 = on_snd List.rev @@ fold_left4 (fun (e,l) x1 x2 x3 x4 -> let (e,y) = f e x1 x2 x3 x4 in (e,y::l)) (e,[]) l1 l2 l3 l4 let fold_left5_map f e l1 l2 l3 l4 l5 = on_snd List.rev @@ fold_left5 (fun (e,l) x1 x2 x3 x4 x5 -> let (e,y) = f e x1 x2 x3 x4 x5 in (e,y::l)) (e,[]) l1 l2 l3 l4 l5 (** {6 Splitting} *) let remove cmp x l = List.filter (fun y -> not (cmp x y)) l let rec remove_first p = function | b :: l when p b -> l | b :: l -> b :: remove_first p l | [] -> raise Not_found let extract_first p li = let rec loop rev_left = function | [] -> raise Not_found | x :: right -> if p x then List.rev_append rev_left right, x else loop (x :: rev_left) right in loop [] li let insert p v l = let rec insrec = function | [] -> [v] | h :: tl -> if p v h then v :: h :: tl else h :: insrec tl in insrec l let find_map_exn f l = match find_map f l with | Some v -> v | None -> raise Not_found (* FIXME: again, generic hash function *) let subset l1 l2 = let t2 = Hashtbl.create 151 in List.iter (fun x -> Hashtbl.add t2 x ()) l2; let rec look = function | [] -> true | x :: ll -> try Hashtbl.find t2 x; look ll with Not_found -> false in look l1 (** [goto i l] splits [l] into two lists [(l1,l2)] such that [(List.rev l1)++l2=l] and [l1] has length [i]. It raises [IndexOutOfRange] when [i] is negative or greater than the length of [l]. *) exception IndexOutOfRange let goto n l = let rec goto i acc = function | tl when Int.equal i 0 -> (acc, tl) | h :: t -> goto (pred i) (h :: acc) t | [] -> raise IndexOutOfRange in goto n [] l (* [chop i l] splits [l] into two lists [(l1,l2)] such that [l1++l2=l] and [l1] has length [i]. It raises [Failure] when [i] is negative or greater than the length of [l] *) let chop n l = try let (h,t) = goto n l in (List.rev h,t) with IndexOutOfRange -> failwith "List.chop" (* spiwack: should raise [IndexOutOfRange] but I'm afraid of missing a try/with when replacing the exception. *) (* [split_when p l] splits [l] into two lists [(l1,a::l2)] such that [l1++(a::l2)=l], [p a=true] and [p b = false] for every element [b] of [l1]. If there is no such [a], then it returns [(l,[])] instead *) let split_when p = let rec split_when_loop x y = match y with | [] -> (List.rev x,[]) | (a :: l) -> if (p a) then (List.rev x,y) else split_when_loop (a :: x) l in split_when_loop [] let firstn n ol = let rec aux acc n l = match n, l with | 0, [] -> ol | 0, _ :: _ -> List.rev acc | n, h :: t -> aux (h :: acc) (pred n) t | _ -> failwith "firstn" in aux [] n ol let sep_first = function | [] -> failwith "sep_first" | hd :: tl -> (hd, tl) let rec sep_last = function | [] -> failwith "sep_last" | hd :: [] -> (hd,[]) | hd :: tl -> let (l,tl) = sep_last tl in (l,hd :: tl) (* Drop the last element of a list *) let rec drop_last = function | [] -> failwith "drop_last" | hd :: [] -> [] | hd :: tl -> hd :: drop_last tl let rec last = function | [] -> failwith "List.last" | hd :: [] -> hd | _ :: tl -> last tl let lastn n l = let len = List.length l in let rec aux m l = if Int.equal m n then l else aux (m - 1) (List.tl l) in if len < n then failwith "lastn" else aux len l let rec skipn n l = match n,l with | 0, _ -> l | _, [] -> failwith "List.skipn" | n, _ :: l -> skipn (pred n) l let skipn_at_best n l = try skipn n l with Failure _ when n >= 0 -> [] (** if [l=p++t] then [drop_prefix p l] is [t] else [l] *) let drop_prefix cmp p l = let rec drop_prefix_rec = function | (h1 :: tp, h2 :: tl) when cmp h1 h2 -> drop_prefix_rec (tp,tl) | ([], tl) -> tl | _ -> l in drop_prefix_rec (p,l) let share_tails eq l1 l2 = let rec shr_rev acc = function | (x1 :: l1, x2 :: l2) when eq x1 x2 -> shr_rev (x1 :: acc) (l1,l2) | (l1, l2) -> (List.rev l1, List.rev l2, acc) in shr_rev [] (List.rev l1, List.rev l2) (** {6 Association lists} *) let map_assoc f = map (fun (x,a) -> (x,f a)) let rec assoc_f f a = function | (x, e) :: xs -> if f a x then e else assoc_f f a xs | [] -> raise Not_found let rec assoc_f_opt f a = function | (x, e) :: xs -> if f a x then Some e else assoc_f_opt f a xs | [] -> None let remove_assoc_f f a l = try remove_first (fun (x,_) -> f a x) l with Not_found -> l let mem_assoc_f f a l = List.exists (fun (x,_) -> f a x) l (** {6 Operations on lists of tuples} *) let rec split_loop p q = function | [] -> () | (x, y) :: l -> let cl = { head = x; tail = [] } in let cr = { head = y; tail = [] } in p.tail <- cast cl; q.tail <- cast cr; split_loop cl cr l let split = function | [] -> [], [] | (x, y) :: l -> let cl = { head = x; tail = [] } in let cr = { head = y; tail = [] } in split_loop cl cr l; (cast cl, cast cr) let rec combine_loop p l1 l2 = match l1, l2 with | [], [] -> () | x :: l1, y :: l2 -> let c = { head = (x, y); tail = [] } in p.tail <- cast c; combine_loop c l1 l2 | _ -> invalid_arg "List.combine" let combine l1 l2 = match l1, l2 with | [], [] -> [] | x :: l1, y :: l2 -> let c = { head = (x, y); tail = [] } in combine_loop c l1 l2; cast c | _ -> invalid_arg "List.combine" let rec split3_loop p q r = function | [] -> () | (x, y, z) :: l -> let cp = { head = x; tail = [] } in let cq = { head = y; tail = [] } in let cr = { head = z; tail = [] } in p.tail <- cast cp; q.tail <- cast cq; r.tail <- cast cr; split3_loop cp cq cr l let split3 = function | [] -> [], [], [] | (x, y, z) :: l -> let cp = { head = x; tail = [] } in let cq = { head = y; tail = [] } in let cr = { head = z; tail = [] } in split3_loop cp cq cr l; (cast cp, cast cq, cast cr) (** XXX TODO tailrec *) let rec split4 = function | [] -> ([], [], [], []) | (a,b,c,d)::l -> let (ra, rb, rc, rd) = split4 l in (a::ra, b::rb, c::rc, d::rd) let rec combine3_loop p l1 l2 l3 = match l1, l2, l3 with | [], [], [] -> () | x :: l1, y :: l2, z :: l3 -> let c = { head = (x, y, z); tail = [] } in p.tail <- cast c; combine3_loop c l1 l2 l3 | _ -> invalid_arg "List.combine3" let combine3 l1 l2 l3 = match l1, l2, l3 with | [], [], [] -> [] | x :: l1, y :: l2, z :: l3 -> let c = { head = (x, y, z); tail = [] } in combine3_loop c l1 l2 l3; cast c | _ -> invalid_arg "List.combine3" (** {6 Operations on lists seen as sets, preserving uniqueness of elements} *) (** Add an element, preserving uniqueness of elements *) let add_set cmp x l = if mem_f cmp x l then l else x :: l (** List equality up to permutation (but considering multiple occurrences) *) let eq_set cmp l1 l2 = let rec aux l1 = function | [] -> is_empty l1 | a :: l2 -> aux (remove_first (cmp a) l1) l2 in try aux l1 l2 with Not_found -> false let rec merge_set cmp l1 l2 = match l1, l2 with | [], l2 -> l2 | l1, [] -> l1 | h1 :: t1, h2 :: t2 -> let c = cmp h1 h2 in if Int.equal c 0 then h1 :: merge_set cmp t1 t2 else if c <= 0 then h1 :: merge_set cmp t1 l2 else h2 :: merge_set cmp l1 t2 let intersect cmp l1 l2 = filter (fun x -> mem_f cmp x l2) l1 let union cmp l1 l2 = let rec urec = function | [] -> l2 | a :: l -> if mem_f cmp a l2 then urec l else a :: urec l in urec l1 let subtract cmp l1 l2 = if is_empty l2 then l1 else List.filter (fun x -> not (mem_f cmp x l2)) l1 let unionq l1 l2 = union (==) l1 l2 let subtractq l1 l2 = subtract (==) l1 l2 (** {6 Uniqueness and duplication} *) (* FIXME: we should avoid relying on the generic hash function, just as we'd better avoid Pervasives.compare *) let distinct l = let visited = Hashtbl.create 23 in let rec loop = function | h :: t -> if Hashtbl.mem visited h then false else begin Hashtbl.add visited h h; loop t end | [] -> true in loop l let distinct_f cmp l = let rec loop = function | a :: b :: _ when Int.equal (cmp a b) 0 -> false | a :: l -> loop l | [] -> true in loop (List.sort cmp l) (* FIXME: again, generic hash function *) let uniquize_key f l = let visited = Hashtbl.create 23 in let rec aux acc changed = function | h :: t -> let x = f h in if Hashtbl.mem visited x then aux acc true t else begin Hashtbl.add visited x x; aux (h :: acc) changed t end | [] -> if changed then List.rev acc else l in aux [] false l let uniquize l = uniquize_key (fun x -> x) l (** [sort_uniquize] might be an alternative to the hashtbl-based [uniquize], when the order of the elements is irrelevant *) let rec uniquize_sorted cmp = function | a :: b :: l when Int.equal (cmp a b) 0 -> uniquize_sorted cmp (a :: l) | a :: l -> a :: uniquize_sorted cmp l | [] -> [] let sort_uniquize cmp l = uniquize_sorted cmp (List.sort cmp l) let min cmp l = let rec aux cur = function | [] -> cur | x :: l -> if cmp x cur < 0 then aux x l else aux cur l in match l with | x :: l -> aux x l | [] -> raise Not_found let rec duplicates cmp = function | [] -> [] | x :: l -> let l' = duplicates cmp l in if mem_f cmp x l then add_set cmp x l' else l' (** {6 Cartesian product} *) (* A generic cartesian product: for any operator (**), [cartesian (**) [x1;x2] [y1;y2] = [x1**y1; x1**y2; x2**y1; x2**y1]], and so on if there are more elements in the lists. *) let cartesian op l1 l2 = map_append (fun x -> map (op x) l2) l1 (* [cartesians] is an n-ary cartesian product: it iterates [cartesian] over a list of lists. *) let cartesians op init ll = List.fold_right (cartesian op) ll [init] (* combinations [[a;b];[c;d]] gives [[a;c];[a;d];[b;c];[b;d]] *) let combinations l = cartesians (fun x l -> x :: l) [] l (* Keep only those products that do not return None *) let cartesian_filter op l1 l2 = map_append (fun x -> map_filter (op x) l2) l1 (* Keep only those products that do not return None *) let cartesians_filter op init ll = List.fold_right (cartesian_filter op) ll [init] (* Factorize lists of pairs according to the left argument *) let rec factorize_left cmp = function | (a,b) :: l -> let al,l' = partition (fun (a',_) -> cmp a a') l in (a,(b :: map snd al)) :: factorize_left cmp l' | [] -> [] module Smart = struct let rec map f l = match l with | [] -> l | h :: tl -> let h' = f h in let tl' = map f tl in if h' == h && tl' == tl then l else h' :: tl' let rec fold_left_map f e l = match l with | [] -> e, [] | h :: tl -> let e', h' = f e h in let e'', tl' = fold_left_map f e' tl in e'', (if h' == h && tl' == tl then l else h' :: tl') let rec fold_right_map f l e = match l with | [] -> [], e | h :: tl -> let tl', e' = fold_right_map f tl e in let h', e'' = f h e' in (if h' == h && tl' == tl then l else h' :: tl'), e'' end module type MonoS = sig type elt val equal : elt list -> elt list -> bool val mem : elt -> elt list -> bool val assoc : elt -> (elt * 'a) list -> 'a val mem_assoc : elt -> (elt * 'a) list -> bool val remove_assoc : elt -> (elt * 'a) list -> (elt * 'a) list val mem_assoc_sym : elt -> ('a * elt) list -> bool end rocq-9.2.0/clib/cList.mli000066400000000000000000000436311516144147600152000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int type 'a eq = 'a -> 'a -> bool include module type of List (** {6 Equality, testing} *) val compare : 'a cmp -> 'a list cmp (** Lexicographic order on lists. *) val equal : 'a eq -> 'a list eq (** Lift equality to list type. *) val is_empty : 'a list -> bool (** Check whether a list is empty *) val mem_f : 'a eq -> 'a -> 'a list -> bool (** Same as [List.mem], for some specific equality *) val for_all_i : (int -> 'a -> bool) -> int -> 'a list -> bool (** Same as [List.for_all] but with an index *) val for_all2eq : ('a -> 'b -> bool) -> 'a list -> 'b list -> bool (** Same as [List.for_all2] but returning [false] when of different length *) val exists_i : (int -> 'a -> bool) -> int -> 'a list -> bool (** Same as [List.exists] but with an index *) val prefix_of : 'a eq -> 'a list eq (** [prefix_of eq l1 l2] returns [true] if [l1] is a prefix of [l2], [false] otherwise. It uses [eq] to compare elements *) val same_length : 'a list -> 'b list -> bool (** A more efficient variant of [for_all2eq (fun _ _ -> true)] *) (** {6 Creating lists} *) val interval : int -> int -> int list (** [interval i j] creates the list [[i; i + 1; ...; j]], or [[]] when [j < i]. *) val make : int -> 'a -> 'a list (** [make n x] returns a list made of [n] times [x]. Raise [Invalid_argument _] if [n] is negative. *) val addn : int -> 'a -> 'a list -> 'a list (** [addn n x l] adds [n] times [x] on the left of [l]. *) val init : int -> (int -> 'a) -> 'a list (** [init n f] constructs the list [f 0; ... ; f (n - 1)]. Raise [Invalid_argument _] if [n] is negative *) val append : 'a list -> 'a list -> 'a list (** Like OCaml's [List.append] but tail-recursive. *) val concat : 'a list list -> 'a list (** Like OCaml's [List.concat] but tail-recursive. *) val flatten : 'a list list -> 'a list (** Synonymous of [concat] *) (** {6 Lists as arrays} *) val assign : 'a list -> int -> 'a -> 'a list (** [assign l i x] sets the [i]-th element of [l] to [x], starting from [0]. Raise [Failure _] if [i] is out of range. *) (** {6 Filtering} *) val filter : ('a -> bool) -> 'a list -> 'a list (** Like OCaml [List.filter] but tail-recursive and physically returns the original list if the predicate holds for all elements. *) val filter2 : ('a -> 'b -> bool) -> 'a list -> 'b list -> 'a list * 'b list (** Like [List.filter] but with 2 arguments, raise [Invalid_argument _] if the lists are not of same length. *) val filteri : (int -> 'a -> bool) -> 'a list -> 'a list (** Like [List.filter] but with an index starting from [0] *) val filter_with : bool list -> 'a list -> 'a list (** [filter_with bl l] selects elements of [l] whose corresponding element in [bl] is [true]. Raise [Invalid_argument _] if sizes differ. *) val map_filter : ('a -> 'b option) -> 'a list -> 'b list (** Like [map] but keeping only non-[None] elements *) val map_filter_i : (int -> 'a -> 'b option) -> 'a list -> 'b list (** Like [map_filter] but with an index starting from [0] *) val partitioni : (int -> 'a -> bool) -> 'a list -> 'a list * 'a list (** Like [List.partition] but with an index starting from [0] *) (** {6 Applying functorially} *) val map : ('a -> 'b) -> 'a list -> 'b list (** Like OCaml [List.map] but tail-recursive *) val map2 : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list (** Like OCaml [List.map2] but tail-recursive *) val map_left : ('a -> 'b) -> 'a list -> 'b list (** As [map] but ensures the left-to-right order of evaluation. *) val concat_map : ('a -> 'b list) -> 'a list -> 'b list (** Like OCaml [List.concat_map] but tail-recursive. Alternatively, the composition of [concat] and [map] *) val map_i : (int -> 'a -> 'b) -> int -> 'a list -> 'b list (** Like OCaml [List.mapi] but tail-recursive. Alternatively, like [map] but with an index *) val map2_i : (int -> 'a -> 'b -> 'c) -> int -> 'a list -> 'b list -> 'c list (** Like [map2] but with an index *) val map3 : ('a -> 'b -> 'c -> 'd) -> 'a list -> 'b list -> 'c list -> 'd list (** Like [map] but for 3 lists. *) val map4 : ('a -> 'b -> 'c -> 'd -> 'e) -> 'a list -> 'b list -> 'c list -> 'd list -> 'e list (** Like [map] but for 4 lists. *) val map_until : ('a -> 'b option) -> 'a list -> 'b list * 'a list (** [map_until f l] applies f to the elements of l until one returns None, then returns the list of elements where f was applied and the tail where f was not applied *) val map_of_array : ('a -> 'b) -> 'a array -> 'b list (** [map_of_array f a] behaves as [List.map f (Array.to_list a)] *) val map_append : ('a -> 'b list) -> 'a list -> 'b list (** [map_append f [x1; ...; xn]] returns [f x1 @ ... @ f xn]. *) val map_append2 : ('a -> 'b -> 'c list) -> 'a list -> 'b list -> 'c list (** Like [map_append] but for two lists; raises [Invalid_argument _] if the two lists do not have the same length. *) val extend : bool list -> 'a -> 'a list -> 'a list (** [extend l a [a1..an]] assumes that the number of [true] in [l] is [n]; it extends [a1..an] by inserting [a] at the position of [false] in [l] *) val count : ('a -> bool) -> 'a list -> int (** Count the number of elements satisfying a predicate *) (** {6 Finding position} *) val index : 'a eq -> 'a -> 'a list -> int (** [index] returns the 1st index of an element in a list (counting from 1). *) val index_opt : 'a eq -> 'a -> 'a list -> int option (** [index_opt] returns the 1st index of an element in a list (counting from 1) and None otherwise. *) val index0 : 'a eq -> 'a -> 'a list -> int (** [index0] behaves as [index] except that it starts counting at 0. *) (** {6 Folding} *) val fold_left_error : ('c -> 'a -> ('c,'e) result) -> 'c -> 'a list -> ('c,'e) result (** acts like [Ok (fold_left f acc s)] while [f] returns [Ok acc']; it stops returning [Error c] as soon as [f] returns [Error c]. *) val fold_left_until : ('c -> 'a -> 'c CSig.until) -> 'c -> 'a list -> 'c (** acts like [fold_left f acc s] while [f] returns [Cont acc']; it stops returning [c] as soon as [f] returns [Stop c]. *) val fold_right_i : (int -> 'a -> 'b -> 'b) -> int -> 'a list -> 'b -> 'b (** Like [List.fold_right] but with an index *) val fold_left_i : (int -> 'a -> 'b -> 'a) -> int -> 'a -> 'b list -> 'a (** Like [List.fold_left] but with an index *) val fold_right_and_left : ('b -> 'a -> 'a list -> 'b) -> 'a list -> 'b -> 'b (** [fold_right_and_left f [a1;...;an] hd] is [f (f (... (f (f hd an [an-1;...;a1]) an-1 [an-2;...;a1]) ...) a2 [a1]) a1 []] *) val fold_left3 : ('a -> 'b -> 'c -> 'd -> 'a) -> 'a -> 'b list -> 'c list -> 'd list -> 'a (** Like [List.fold_left] but for 3 lists; raise [Invalid_argument _] if not all lists of the same size *) val fold_left4 : ('a -> 'b -> 'c -> 'd -> 'e -> 'a) -> 'a -> 'b list -> 'c list -> 'd list -> 'e list -> 'a (** Like [List.fold_left] but for 4 lists; raise [Invalid_argument _] if not all lists of the same size *) val fold_left2_set : exn -> ('a -> 'b -> 'c -> 'b list -> 'c list -> 'a) -> 'a -> 'b list -> 'c list -> 'a (** Fold sets, i.e. lists up to order; the folding function tells when elements match by returning a value and raising the given exception otherwise; sets should have the same size; raise the given exception if no pairing of the two sets is found;; complexity in O(n^2) *) val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b list -> 'a * 'c list (** [fold_left_map f e_0 [a1;...;an]] is [e_n,[k_1...k_n]] where [(e_i,k_i)] is [f e_{i-1} ai] for each i<=n *) val fold_right_map : ('b -> 'a -> 'c * 'a) -> 'b list -> 'a -> 'c list * 'a (** Same, folding on the right *) val fold_left2_map : ('a -> 'b -> 'c -> 'a * 'd) -> 'a -> 'b list -> 'c list -> 'a * 'd list (** Same with two lists, folding on the left *) val fold_right2_map : ('b -> 'c -> 'a -> 'd * 'a) -> 'b list -> 'c list -> 'a -> 'd list * 'a (** Same with two lists, folding on the right *) val fold_left3_map : ('a -> 'b -> 'c -> 'd -> 'a * 'e) -> 'a -> 'b list -> 'c list -> 'd list -> 'a * 'e list (** Same with three lists, folding on the left *) val fold_left4_map : ('a -> 'b -> 'c -> 'd -> 'e -> 'a * 'r) -> 'a -> 'b list -> 'c list -> 'd list -> 'e list -> 'a * 'r list (** Same with four lists, folding on the left *) val fold_left5_map : ('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'a * 'r) -> 'a -> 'b list -> 'c list -> 'd list -> 'e list -> 'f list -> 'a * 'r list (** Same with five lists, folding on the left *) (** {6 Splitting} *) val remove : 'a eq -> 'a -> 'a list -> 'a list (** [remove eq a l] Remove all occurrences of [a] in [l] *) val remove_first : ('a -> bool) -> 'a list -> 'a list (** Remove the first element satisfying a predicate, or raise [Not_found] *) val extract_first : ('a -> bool) -> 'a list -> 'a list * 'a (** Remove and return the first element satisfying a predicate, or raise [Not_found] *) val find_map_exn : ('a -> 'b option) -> 'a list -> 'b (** Like [find_map] but raises [Not_found] instead of returning [None]. *) exception IndexOutOfRange val goto: int -> 'a list -> 'a list * 'a list (** [goto i l] splits [l] into two lists [(l1,l2)] such that [(List.rev l1)++l2=l] and [l1] has length [i]. It raises [IndexOutOfRange] when [i] is negative or greater than the length of [l]. *) val split_when : ('a -> bool) -> 'a list -> 'a list * 'a list (** [split_when p l] splits [l] into two lists [(l1,a::l2)] such that [l1++(a::l2)=l], [p a=true] and [p b = false] for every element [b] of [l1]. if there is no such [a], then it returns [(l,[])] instead. *) val sep_first : 'a list -> 'a * 'a list (** [sep_first l] returns [(a,l')] such that [l] is [a::l']. It raises [Failure _] if the list is empty. *) val sep_last : 'a list -> 'a * 'a list (** [sep_last l] returns [(a,l')] such that [l] is [l'@[a]]. It raises [Failure _] if the list is empty. *) val drop_last : 'a list -> 'a list (** Remove the last element of the list. It raises [Failure _] if the list is empty. This is the second part of [sep_last]. *) val last : 'a list -> 'a (** Return the last element of the list. It raises [Failure _] if the list is empty. This is the first part of [sep_last]. *) val lastn : int -> 'a list -> 'a list (** [lastn n l] returns the [n] last elements of [l]. It raises [Failure _] if [n] is less than 0 or larger than the length of [l] *) val chop : int -> 'a list -> 'a list * 'a list (** [chop i l] splits [l] into two lists [(l1,l2)] such that [l1++l2=l] and [l1] has length [i]. It raises [Failure _] when [i] is negative or greater than the length of [l]. *) val firstn : int -> 'a list -> 'a list (** [firstn n l] Returns the [n] first elements of [l]. It raises [Failure _] if [n] negative or too large. This is the first part of [chop]. *) val skipn : int -> 'a list -> 'a list (** [skipn n l] drops the [n] first elements of [l]. It raises [Failure _] if [n] is less than 0 or larger than the length of [l]. This is the second part of [chop]. *) val skipn_at_best : int -> 'a list -> 'a list (** Same as [skipn] but returns [] if [n] is larger than the length of the list. *) val drop_prefix : 'a eq -> 'a list -> 'a list -> 'a list (** [drop_prefix eq l1 l] returns [l2] if [l=l1++l2] else return [l]. *) val insert : 'a eq -> 'a -> 'a list -> 'a list (** Insert at the (first) position so that if the list is ordered wrt to the total order given as argument, the order is preserved *) val share_tails : 'a eq -> 'a list -> 'a list -> 'a list * 'a list * 'a list (** [share_tails l1 l2] returns [(l1',l2',l)] such that [l1] is [l1'\@l] and [l2] is [l2'\@l] and [l] is maximal amongst all such decompositions *) (** {6 Association lists} *) val map_assoc : ('a -> 'b) -> ('c * 'a) list -> ('c * 'b) list (** Applies a function on the codomain of an association list *) val assoc_f : 'a eq -> 'a -> ('a * 'b) list -> 'b (** Like [List.assoc] but using the equality given as argument *) val assoc_f_opt : 'a eq -> 'a -> ('a * 'b) list -> 'b option (** Like [List.assoc_opt] but using the equality given as argument *) val remove_assoc_f : 'a eq -> 'a -> ('a * 'b) list -> ('a * 'b) list (** Remove first matching element; unchanged if no such element *) val mem_assoc_f : 'a eq -> 'a -> ('a * 'b) list -> bool (** Like [List.mem_assoc] but using the equality given as argument *) val factorize_left : 'a eq -> ('a * 'b) list -> ('a * 'b list) list (** Create a list of associations from a list of pairs *) (** {6 Operations on lists of tuples} *) val split : ('a * 'b) list -> 'a list * 'b list (** Like OCaml's [List.split] but tail-recursive. *) val combine : 'a list -> 'b list -> ('a * 'b) list (** Like OCaml's [List.combine] but tail-recursive. *) val split3 : ('a * 'b * 'c) list -> 'a list * 'b list * 'c list (** Like [split] but for triples *) val split4 : ('a * 'b * 'c * 'd) list -> 'a list * 'b list * 'c list * 'd list (** Like [split] but for quads *) val combine3 : 'a list -> 'b list -> 'c list -> ('a * 'b * 'c) list (** Like [combine] but for triples *) (** {6 Operations on lists seen as sets, preserving uniqueness of elements} *) val add_set : 'a eq -> 'a -> 'a list -> 'a list (** [add_set x l] adds [x] in [l] if it is not already there, or returns [l] otherwise. *) val eq_set : 'a eq -> 'a list eq (** Test equality up to permutation. It respects multiple occurrences and thus works also on multisets. *) val subset : 'a list eq (** Tell if a list is a subset of another up to permutation. It expects each element to occur only once. *) val merge_set : 'a cmp -> 'a list -> 'a list -> 'a list (** Merge two sorted lists and preserves the uniqueness property. *) val intersect : 'a eq -> 'a list -> 'a list -> 'a list (** Return the intersection of two lists, assuming and preserving uniqueness of elements *) val union : 'a eq -> 'a list -> 'a list -> 'a list (** Return the union of two lists, assuming and preserving uniqueness of elements *) val unionq : 'a list -> 'a list -> 'a list (** [union] specialized to physical equality *) val subtract : 'a eq -> 'a list -> 'a list -> 'a list (** Remove from the first list all elements from the second list. *) val subtractq : 'a list -> 'a list -> 'a list (** [subtract] specialized to physical equality *) (** {6 Uniqueness and duplication} *) val distinct : 'a list -> bool (** Return [true] if all elements of the list are distinct. *) val distinct_f : 'a cmp -> 'a list -> bool (** Like [distinct] but using the equality given as argument *) val duplicates : 'a eq -> 'a list -> 'a list (** Return the list of unique elements which appear at least twice. Elements are kept in the order of their first appearance. *) val uniquize_key : ('a -> 'b) -> 'a list -> 'a list (** Return the list of elements without duplicates using the function to associate a comparison key to each element. This is the list unchanged if there was none. *) val uniquize : 'a list -> 'a list (** Return the list of elements without duplicates. This is the list unchanged if there was none. *) val sort_uniquize : 'a cmp -> 'a list -> 'a list (** Return a sorted version of a list without duplicates according to some comparison function. *) val min : 'a cmp -> 'a list -> 'a (** Return minimum element according to some comparison function. @raise Not_found on an empty list. *) (** {6 Cartesian product} *) val cartesian : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list (** A generic binary cartesian product: for any operator (**), [cartesian (**) [x1;x2] [y1;y2] = [x1**y1; x1**y2; x2**y1; x2**y1]], and so on if there are more elements in the lists. *) val cartesians : ('a -> 'b -> 'b) -> 'b -> 'a list list -> 'b list (** [cartesians op init l] is an n-ary cartesian product: it builds the list of all [op a1 .. (op an init) ..] for [a1], ..., [an] in the product of the elements of the lists *) val combinations : 'a list list -> 'a list list (** [combinations l] returns the list of [n_1] * ... * [n_p] tuples [[a11;...;ap1];...;[a1n_1;...;apn_pd]] whenever [l] is a list [[a11;..;a1n_1];...;[ap1;apn_p]]; otherwise said, it is [cartesians (::) [] l] *) val cartesians_filter : ('a -> 'b -> 'b option) -> 'b -> 'a list list -> 'b list (** Like [cartesians op init l] but keep only the tuples for which [op] returns [Some _] on all the elements of the tuple. *) (** When returning a list of same type as the input, maximally shares the suffix of the output which is physically equal to the corresponding suffix of the input *) module Smart : sig val map : ('a -> 'a) -> 'a list -> 'a list (** Like [List.map] but sharing with the input the longest suffix of the output which is physically the same as the input; in particular, [Smart.map f l == l] (physically) if [f a == a] (physically) for all members of the list *) val fold_left_map : ('a -> 'b -> 'a * 'b) -> 'a -> 'b list -> 'a * 'b list (** Idem for the second argument of [List.fold_left_map f e l] relatively to the second argument of [f] *) val fold_right_map : ('b -> 'a -> 'b * 'a) -> 'b list -> 'a -> 'b list * 'a (** Idem for the first argument of [List.fold_right_map f l e] relatively to the second argument of [f] *) end module type MonoS = sig type elt val equal : elt list -> elt list -> bool val mem : elt -> elt list -> bool val assoc : elt -> (elt * 'a) list -> 'a val mem_assoc : elt -> (elt * 'a) list -> bool val remove_assoc : elt -> (elt * 'a) list -> (elt * 'a) list val mem_assoc_sym : elt -> ('a * elt) list -> bool end rocq-9.2.0/clib/cMap.ml000066400000000000000000000252651516144147600146340ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type MonadS = sig type +'a t val return : 'a -> 'a t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t end module type S = Map.S module type UExtS = sig include CSig.UMapS module Set : CSig.USetS with type elt = key val get : key -> 'a t -> 'a val set : key -> 'a -> 'a t -> 'a t val modify : key -> (key -> 'a -> 'a) -> 'a t -> 'a t val domain : 'a t -> Set.t val bind : (key -> 'a) -> Set.t -> 'a t val height : 'a t -> int val filter_range : (key -> int) -> 'a t -> 'a t val of_list : (key * 'a) list -> 'a t val symmetric_diff_fold : (key -> 'a option -> 'a option -> 'b -> 'b) -> 'a t -> 'a t -> 'b -> 'b module Smart : sig val map : ('a -> 'a) -> 'a t -> 'a t val mapi : (key -> 'a -> 'a) -> 'a t -> 'a t end module Monad(M : MonadS) : sig val fold : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t val mapi : (key -> 'a -> 'b M.t) -> 'a t -> 'b t M.t end end module type ExtS = sig include CSig.MapS module Set : CSig.SetS with type elt = key include UExtS with type key := key and type 'a t := 'a t and module Set := Set module Monad(M:MonadS) : sig include module type of Monad(M) val fold_left : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t val fold_right : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t end val fold_left : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val fold_right : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val fold_left_map : (key -> 'a -> 'b -> 'b * 'c) -> 'a t -> 'b -> 'b * 'c t val fold_right_map : (key -> 'a -> 'b -> 'b * 'c) -> 'a t -> 'b -> 'b * 'c t end module MapExt (M : Map.OrderedType) : sig type 'a map = 'a Map.Make(M).t val set : M.t -> 'a -> 'a map -> 'a map val get : M.t -> 'a map -> 'a val modify : M.t -> (M.t -> 'a -> 'a) -> 'a map -> 'a map val domain : 'a map -> Set.Make(M).t val bind : (M.t -> 'a) -> Set.Make(M).t -> 'a map val fold_left : (M.t -> 'a -> 'b -> 'b) -> 'a map -> 'b -> 'b val fold_right : (M.t -> 'a -> 'b -> 'b) -> 'a map -> 'b -> 'b val fold_left_map : (M.t -> 'a -> 'b -> 'b * 'c) -> 'a map -> 'b -> 'b * 'c map val fold_right_map : (M.t -> 'a -> 'b -> 'b * 'c) -> 'a map -> 'b -> 'b * 'c map val height : 'a map -> int val filter_range : (M.t -> int) -> 'a map -> 'a map val symmetric_diff_fold : (M.t -> 'a option -> 'a option -> 'b -> 'b) -> 'a map -> 'a map -> 'b -> 'b val of_list : (M.t * 'a) list -> 'a map module Smart : sig val map : ('a -> 'a) -> 'a map -> 'a map val mapi : (M.t -> 'a -> 'a) -> 'a map -> 'a map end module Monad(MS : MonadS) : sig val fold : (M.t -> 'a -> 'b -> 'b MS.t) -> 'a map -> 'b -> 'b MS.t val fold_left : (M.t -> 'a -> 'b -> 'b MS.t) -> 'a map -> 'b -> 'b MS.t val fold_right : (M.t -> 'a -> 'b -> 'b MS.t) -> 'a map -> 'b -> 'b MS.t val mapi : (M.t -> 'a -> 'b MS.t) -> 'a map -> 'b map MS.t end end = struct (** This unsafe module is a way to access to the actual implementations of OCaml sets and maps without reimplementing them ourselves. It is quite dubious that these implementations will ever be changed... Nonetheless, if this happens, we can still implement a less clever version of [domain]. *) module F = Map.Make(M) type 'a map = 'a F.t module S = Set.Make(M) type set = S.t type 'a _map = | MEmpty | MNode of {l:'a map; v:F.key; d:'a; r:'a map; h:int} type _set = | SEmpty | SNode of set * M.t * set * int let map_prj : 'a map -> 'a _map = Obj.magic let map_inj : 'a _map -> 'a map = Obj.magic let set_prj : set -> _set = Obj.magic let set_inj : _set -> set = Obj.magic let rec set k v (s : 'a map) : 'a map = match map_prj s with | MEmpty -> raise Not_found | MNode {l; v=k'; d=v'; r; h} -> let c = M.compare k k' in if c < 0 then let l' = set k v l in if l == l' then s else map_inj (MNode {l=l'; v=k'; d=v'; r; h}) else if c = 0 then if v' == v then s else map_inj (MNode {l; v=k'; d=v; r; h}) else let r' = set k v r in if r == r' then s else map_inj (MNode {l; v=k'; d=v'; r=r'; h}) let rec get k (s:'a map) : 'a = match map_prj s with | MEmpty -> assert false | MNode {l; v=k'; d=v; r; h} -> let c = M.compare k k' in if c < 0 then get k l else if c = 0 then v else get k r let rec modify k f (s : 'a map) : 'a map = match map_prj s with | MEmpty -> raise Not_found | MNode {l; v; d; r; h} -> let c = M.compare k v in if c < 0 then let l' = modify k f l in if l == l' then s else map_inj (MNode {l=l'; v; d; r; h}) else if c = 0 then let d' = f v d in if d' == d then s else map_inj (MNode {l; v; d=d'; r; h}) else let r' = modify k f r in if r == r' then s else map_inj (MNode {l; v; d; r=r'; h}) let rec domain (s : 'a map) : set = match map_prj s with | MEmpty -> set_inj SEmpty | MNode {l; v; r; h; _} -> set_inj (SNode (domain l, v, domain r, h)) (** This function is essentially identity, but OCaml current stdlib does not take advantage of the similarity of the two structures, so we introduce this unsafe loophole. *) let rec bind f (s : set) : 'a map = match set_prj s with | SEmpty -> map_inj MEmpty | SNode (l, k, r, h) -> map_inj (MNode { l=bind f l; v=k; d=f k; r=bind f r; h}) (** Dual operation of [domain]. *) let rec fold_left f (s : 'a map) accu = match map_prj s with | MEmpty -> accu | MNode {l; v=k; d=v; r; h} -> let accu = f k v (fold_left f l accu) in fold_left f r accu let rec fold_right f (s : 'a map) accu = match map_prj s with | MEmpty -> accu | MNode {l; v=k; d=v; r; h} -> let accu = f k v (fold_right f r accu) in fold_right f l accu let rec fold_left_map f (s : 'a map) accu = match map_prj s with | MEmpty -> accu, map_inj MEmpty | MNode {l; v=k; d=v; r; h} -> let accu, l = fold_left_map f l accu in let accu, v = f k v accu in let accu, r = fold_left_map f r accu in accu, map_inj (MNode {l; v=k; d=v; r; h}) let rec fold_right_map f (s : 'a map) accu = match map_prj s with | MEmpty -> accu, map_inj MEmpty | MNode {l; v=k; d=v; r; h} -> let accu, r = fold_right_map f r accu in let accu, v = f k v accu in let accu, l = fold_right_map f l accu in accu, map_inj (MNode {l; v=k; d=v; r; h}) let height s = match map_prj s with | MEmpty -> 0 | MNode {h;_} -> h (* Filter based on a range *) let filter_range in_range m = let rec aux m = function | MEmpty -> m | MNode {l; v; d; r; _} -> let vr = in_range v in (* the range is below the current value *) if vr < 0 then aux m (map_prj l) (* the range is above the current value *) else if vr > 0 then aux m (map_prj r) (* The current value is in the range *) else let m = aux m (map_prj l) in let m = aux m (map_prj r) in F.add v d m in aux F.empty (map_prj m) let of_list l = let fold accu (x, v) = F.add x v accu in List.fold_left fold F.empty l type 'a sequenced = | End | More of M.t * 'a * 'a F.t * 'a sequenced let rec seq_cons m rest = match map_prj m with | MEmpty -> rest | MNode {l; v; d; r; _ } -> seq_cons l (More (v, d, r, rest)) let rec fold_seq f acc = function | End -> acc | More (k, v, m, r) -> f k v @@ fold_seq f (F.fold f m acc) r let move_to_acc (m, acc) = match map_prj m with | MEmpty -> assert false | MNode {l; v; d; r; _ } -> l, More (v, d, r, acc) let rec symmetric_cons ((lm, la) as l) ((rm, ra) as r) = if lm == rm then la, ra else let lh = height lm in let rh = height rm in if lh == rh then symmetric_cons (move_to_acc l) (move_to_acc r) else if lh < rh then symmetric_cons l (move_to_acc r) else symmetric_cons (move_to_acc l) r let symmetric_diff_fold f lm rm acc = let rec aux s acc = match s with | End, rs -> fold_seq (fun k v -> f k None (Some v)) acc rs | ls, End -> fold_seq (fun k v -> f k (Some v) None) acc ls | (More (kl, vl, tl, rl) as ls), (More (kr, vr, tr, rr) as rs) -> let cmp = M.compare kl kr in if cmp == 0 then let rem = aux (symmetric_cons (tl, rl) (tr, rr)) acc in if vl == vr then rem else f kl (Some vl) (Some vr) rem else if cmp < 0 then f kl (Some vl) None @@ aux (seq_cons tl rl, rs) acc else f kr None (Some vr) @@ aux (ls, seq_cons tr rr) acc in aux (symmetric_cons (lm, End) (rm, End)) acc module Smart = struct let rec map f (s : 'a map) = match map_prj s with | MEmpty -> map_inj MEmpty | MNode {l; v=k; d=v; r; h} -> let l' = map f l in let r' = map f r in let v' = f v in if l == l' && r == r' && v == v' then s else map_inj (MNode {l=l'; v=k; d=v'; r=r'; h}) let rec mapi f (s : 'a map) = match map_prj s with | MEmpty -> map_inj MEmpty | MNode {l; v=k; d=v; r; h} -> let l' = mapi f l in let r' = mapi f r in let v' = f k v in if l == l' && r == r' && v == v' then s else map_inj (MNode {l=l'; v=k; d=v'; r=r'; h}) end module Monad(M : MonadS) = struct open M let rec fold_left f s accu = match map_prj s with | MEmpty -> return accu | MNode {l; v=k; d=v; r; h} -> fold_left f l accu >>= fun accu -> f k v accu >>= fun accu -> fold_left f r accu let rec fold_right f s accu = match map_prj s with | MEmpty -> return accu | MNode {l; v=k; d=v; r; h} -> fold_right f r accu >>= fun accu -> f k v accu >>= fun accu -> fold_right f l accu let fold = fold_left let rec mapi f s = match map_prj s with | MEmpty -> return (map_inj MEmpty) | MNode {l; v=k; d=v; r; h} -> mapi f l >>= fun l -> mapi f r >>= fun r -> f k v >>= fun v -> return (map_inj (MNode {l; v=k; d=v; r; h})) end end module Make(M : Map.OrderedType) = struct include Map.Make(M) include MapExt(M) end rocq-9.2.0/clib/cMap.mli000066400000000000000000000101751516144147600147770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type MonadS = sig type +'a t val return : 'a -> 'a t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t end module type S = Map.S module type UExtS = sig include CSig.UMapS (** The underlying Map library *) module Set : CSig.USetS with type elt = key (** Sets used by the domain function *) val get : key -> 'a t -> 'a (** Same as {!find} but fails an assertion instead of raising [Not_found] *) val set : key -> 'a -> 'a t -> 'a t (** Same as [add], but expects the key to be present, and thus faster. @raise Not_found when the key is unbound in the map. *) val modify : key -> (key -> 'a -> 'a) -> 'a t -> 'a t (** Apply the given function to the binding of the given key. @raise Not_found when the key is unbound in the map. *) val domain : 'a t -> Set.t (** Recover the set of keys defined in the map. *) val bind : (key -> 'a) -> Set.t -> 'a t (** [bind f s] transform the set [x1; ...; xn] into [x1 := f x1; ...; xn := f xn]. *) val height : 'a t -> int (** An indication of the logarithmic size of a map *) val filter_range : (key -> int) -> 'a t -> 'a t (** [find_range in_range m] Given a comparison function [in_range x], that tests if [x] is below, above, or inside a given range [filter_range] returns the submap of [m] whose keys are in range. Note that [in_range] has to define a continouous range. *) val of_list : (key * 'a) list -> 'a t (** Turns an association list into a map *) val symmetric_diff_fold : (key -> 'a option -> 'a option -> 'b -> 'b) -> 'a t -> 'a t -> 'b -> 'b (** [symmetric_diff f ml mr acc] will efficiently fold over the difference between [ml] and [mr], assumed that they share most of their internal structure. A call to [f k vl vr] means that if [vl] is [Some], then [k] exists in [ml]. Similarly, if [vr] is [Some], then [k] exists in [mr]. If both [vl] and [vr] are [Some], then [vl != vr]. *) module Smart : sig val map : ('a -> 'a) -> 'a t -> 'a t (** As [map] but tries to preserve sharing. *) val mapi : (key -> 'a -> 'a) -> 'a t -> 'a t (** As [mapi] but tries to preserve sharing. *) end module Monad(M : MonadS) : sig val fold : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t val mapi : (key -> 'a -> 'b M.t) -> 'a t -> 'b t M.t end (** Fold operators parameterized by any monad. *) end module type ExtS = sig include CSig.MapS module Set : CSig.SetS with type elt = key include UExtS with type key := key and type 'a t := 'a t and module Set := Set module Monad(M:MonadS) : sig include module type of Monad(M) val fold_left : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t val fold_right : (key -> 'a -> 'b -> 'b M.t) -> 'a t -> 'b -> 'b M.t end val fold_left : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b (** Alias for {!fold}, to easily track where we depend on fold order. *) val fold_right : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b (** Folding keys in decreasing order. *) val fold_left_map : (key -> 'a -> 'b -> 'b * 'c) -> 'a t -> 'b -> 'b * 'c t (** Combination of fold_left and map *) val fold_right_map : (key -> 'a -> 'b -> 'b * 'c) -> 'a t -> 'b -> 'b * 'c t (** Combination of fold_right and map *) end module Make(M : Map.OrderedType) : ExtS with type key = M.t and type 'a t = 'a Map.Make(M).t and module Set := Set.Make(M) rocq-9.2.0/clib/cObj.ml000066400000000000000000000141731516144147600146250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* = Obj.no_scan_tag then if Obj.tag t = Obj.string_tag then (c := !c + Obj.size t; b := !b + 1; m := max d !m) else if Obj.tag t = Obj.double_tag then (s := !s + 2; b := !b + 1; m := max d !m) else if Obj.tag t = Obj.double_array_tag then (s := !s + 2 * Obj.size t; b := !b + 1; m := max d !m) else (b := !b + 1; m := max d !m) else let n = Obj.size t in s := !s + n; b := !b + 1; block_stats (d + 1) (n - 1) t and block_stats d i t = if i >= 0 then (obj_stats d (Obj.field t i); block_stats d (i-1) t) let obj_stats a = c := 0; s:= 0; b:= 0; m:= 0; obj_stats 0 (Obj.repr a); (!c, !s + !b, !m) (** {6 Physical sizes} *) (*s Pointers already visited are stored in a hash-table, where comparisons are done using physical equality. *) module H = Hashtbl.Make( struct type t = Obj.t let equal = (==) let hash = Hashtbl.hash end) let node_table = (H.create 257 : unit H.t) let in_table o = try H.find node_table o; true with Not_found -> false let add_in_table o = H.add node_table o () let reset_table () = H.clear node_table (*s Objects are traversed recursively, as soon as their tags are less than [no_scan_tag]. [count] records the numbers of words already visited. *) let size_of_double = Obj.size (Obj.repr 1.0) let count = ref 0 let rec traverse t = if not (in_table t) && Obj.is_block t then begin add_in_table t; let n = Obj.size t in let tag = Obj.tag t in if tag < Obj.no_scan_tag then begin count := !count + 1 + n; for i = 0 to n - 1 do traverse (Obj.field t i) done end else if tag = Obj.string_tag then count := !count + 1 + n else if tag = Obj.double_tag then count := !count + size_of_double else if tag = Obj.double_array_tag then count := !count + 1 + size_of_double * n else incr count end (*s Sizes of objects in words and in bytes. The size in bytes is computed system-independently according to [Sys.word_size]. *) let size o = reset_table (); count := 0; traverse (Obj.repr o); !count let size_b o = (size o) * (Sys.word_size / 8) let size_kb o = (size o) / (8192 / Sys.word_size) (** {6 Physical sizes with sharing} *) (** This time, all the size of objects are computed with respect to a larger object containing them all, and we only count the new blocks not already seen earlier in the left-to-right visit of the englobing object. The very same object could have a zero size or not, depending of the occurrence we're considering in the englobing object. For speaking of occurrences, we use an [int list] for a path of field indexes from the outmost block to the one we're looking. In the list, the leftmost integer is the field index in the deepest block. *) (** We now store in the hashtable the size (with sharing), and also the position of the first occurrence of the object *) let node_sizes = (H.create 257 : (int*int list) H.t) let get_size o = H.find node_sizes o let add_size o n pos = H.replace node_sizes o (n,pos) let reset_sizes () = H.clear node_sizes let global_object = ref (Obj.repr 0) (** [sum n f] is [f 0 + f 1 + ... + f (n-1)], evaluated from left to right *) let sum n f = let rec loop k acc = if k >= n then acc else loop (k+1) (acc + f k) in loop 0 0 (** Recursive visit of the main object, filling the hashtable *) let rec compute_size o pos = if not (Obj.is_block o) then 0 else try let _ = get_size o in 0 (* already seen *) with Not_found -> let n = Obj.size o in add_size o (-1) pos (* temp size, for cyclic values *); let tag = Obj.tag o in let size = if tag < Obj.no_scan_tag then 1 + n + sum n (fun i -> compute_size (Obj.field o i) (i::pos)) else if tag = Obj.string_tag then 1 + n else if tag = Obj.double_tag then size_of_double else if tag = Obj.double_array_tag then size_of_double * n else 1 in add_size o size pos; size (** Provides the global object in which we'll search shared sizes *) let register_shared_size t = let o = Obj.repr t in reset_sizes (); global_object := o; ignore (compute_size o []) (** Shared size of an object with respect to the global object given by the last [register_shared_size] *) let shared_size pos o = if not (Obj.is_block o) then 0 else let size,pos' = try get_size o with Not_found -> failwith "shared_size: unregistered structure ?" in match pos with | Some p when p <> pos' -> 0 | _ -> size let shared_size_of_obj t = shared_size None (Obj.repr t) (** Shared size of the object at some positiion in the global object given by the last [register_shared_size] *) let shared_size_of_pos pos = let rec obj_of_pos o = function | [] -> o | n::pos' -> let o' = obj_of_pos o pos' in assert (Obj.is_block o' && n < Obj.size o'); Obj.field o' n in shared_size (Some pos) (obj_of_pos !global_object pos) (*s Total size of the allocated ocaml heap. *) let heap_size () = let stat = Gc.stat () and control = Gc.get () in let max_words_total = stat.Gc.heap_words + control.Gc.minor_heap_size in (max_words_total * (Sys.word_size / 8)) let heap_size_kb () = (heap_size () + 1023) / 1024 rocq-9.2.0/clib/cObj.mli000066400000000000000000000044351516144147600147760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int (** Physical size of an object in words. *) val size_b : 'a -> int (** Same as [size] in bytes. *) val size_kb : 'a -> int (** Same as [size] in kilobytes. *) (** {6 Physical size of an ocaml value with sharing.} *) (** This time, all the size of objects are computed with respect to a larger object containing them all, and we only count the new blocks not already seen earlier in the left-to-right visit of the englobing object. *) (** Provides the global object in which we'll search shared sizes *) val register_shared_size : 'a -> unit (** Shared size (in word) of an object with respect to the global object given by the last [register_shared_size]. *) val shared_size_of_obj : 'a -> int (** Same, with an object indicated by its occurrence in the global object. The very same object could have a zero size or not, depending of the occurrence we're considering in the englobing object. For speaking of occurrences, we use an [int list] for a path of field indexes (leftmost = deepest block, rightmost = top block of the global object). *) val shared_size_of_pos : int list -> int (** {6 Logical size of an OCaml value.} *) val obj_stats : 'a -> int * int * int (** Return the (logical) value size, the string size, and the maximum depth of the object. This loops on cyclic structures. *) (** {6 Total size of the allocated ocaml heap. } *) val heap_size : unit -> int (** Heap size, in words. *) val heap_size_kb : unit -> int (** Heap size, in kilobytes. *) rocq-9.2.0/clib/cSet.ml000066400000000000000000000046461516144147600146520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type S = Set.S module type ExtS = sig include CSig.SetS module List : sig val union : t list -> t end end module SetExt (M : Set.OrderedType) : sig type set = Set.Make(M).t module List : sig val union : set list -> set end end = struct module S = Set.Make(M) type set = S.t module List = struct let union = List.fold_left S.union S.empty end end module Make(M : Set.OrderedType) = struct include Set.Make(M) include SetExt(M) end module type HashedType = sig type t val hash : t -> int end module Hashcons(M : OrderedType)(H : Hashcons.HashedType with type t = M.t) = struct module Set = Make(M) type set = Set.t type _set = | SEmpty | SNode of set * M.t * set * int let set_prj : set -> _set = Obj.magic let set_inj : _set -> set = Obj.magic (* equivalent sets may have different structure, so we don't hash and compare by the actual structure but only by the list of elements *) let rec spine s accu = match set_prj s with | SEmpty -> accu | SNode (l, v, r, _) -> spine l ((v, r) :: accu) let rec umap hacc s = match set_prj s with | SEmpty -> hacc, set_inj SEmpty | SNode (l, v, r, h) -> let hacc, l' = umap hacc l in let hv, v' = H.hcons v in let hacc = Hashset.Combine.combine hacc hv in let hacc, r' = umap hacc r in hacc, set_inj (SNode (l', v', r', h)) let rec eqeq s1 s2 = match s1, s2 with | [], [] -> true | (v1, r1) :: s1, (v2, r2) :: s2 -> v1 == v2 && eqeq (spine r1 s1) (spine r2 s2) | _ -> false module Hashed = struct type t = set let eq s1 s2 = s1 == s2 || eqeq (spine s1 []) (spine s2 []) let hashcons v = umap 0 v end include Hashcons.Make(Hashed) end rocq-9.2.0/clib/cSet.mli000066400000000000000000000025031516144147600150110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type S = Set.S module type ExtS = sig include CSig.SetS (** The underlying Set library *) module List : sig val union : t list -> t (** Union of sets from a list *) end end module Make(M : Map.OrderedType) : ExtS with type elt = M.t and type t = Set.Make(M).t module type HashedType = sig type t val hash : t -> int end module Hashcons (M : OrderedType) (_ : Hashcons.HashedType with type t = M.t) : Hashcons.S with type t = Set.Make(M).t (** Create hash-consing for sets. The hashing function provided must be compatible with the comparison function. *) rocq-9.2.0/clib/cSig.mli000066400000000000000000000102401516144147600147750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool val mem: elt -> t -> bool val add: elt -> t -> t val singleton: elt -> t val remove: elt -> t -> t val union: t -> t -> t val inter: t -> t -> t val diff: t -> t -> t val compare: t -> t -> int val equal: t -> t -> bool val subset: t -> t -> bool val iter: (elt -> unit) -> t -> unit val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a val for_all: (elt -> bool) -> t -> bool val exists: (elt -> bool) -> t -> bool val filter: (elt -> bool) -> t -> t val filter_map: (elt -> elt option) -> t -> t val partition: (elt -> bool) -> t -> t * t val cardinal: t -> int val elements: t -> elt list val choose: t -> elt end (** Redeclaration of OCaml set signature, to preserve compatibility. See OCaml documentation for more information. Operations which can't be efficiently implemented for HSets are moved to OSetS. *) module type SetS = sig include USetS val disjoint: t -> t -> bool val min_elt: t -> elt val min_elt_opt: t -> elt option val max_elt: t -> elt val max_elt_opt: t -> elt option val choose: t -> elt val choose_opt: t -> elt option val split: elt -> t -> t * bool * t val find: elt -> t -> elt val find_opt: elt -> t -> elt option val find_first: (elt -> bool) -> t -> elt val find_first_opt: (elt -> bool) -> t -> elt option val find_last: (elt -> bool) -> t -> elt val find_last_opt: (elt -> bool) -> t -> elt option val of_list: elt list -> t val to_seq_from : elt -> t -> elt Seq.t val to_seq : t -> elt Seq.t val to_rev_seq : t -> elt Seq.t val add_seq : elt Seq.t -> t -> t val of_seq : elt Seq.t -> t end (** OCaml set operations which require the order structure to be efficient. *) module type UMapS = sig type key type (+'a) t val empty: 'a t val is_empty: 'a t -> bool val mem: key -> 'a t -> bool val add: key -> 'a -> 'a t -> 'a t val update : key -> ('a option -> 'a option) -> 'a t -> 'a t val singleton: key -> 'a -> 'a t val remove: key -> 'a t -> 'a t val merge: (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t val union: (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t val compare: ('a -> 'a -> int) -> 'a t -> 'a t -> int val equal: ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter: (key -> 'a -> unit) -> 'a t -> unit val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val for_all: (key -> 'a -> bool) -> 'a t -> bool val exists: (key -> 'a -> bool) -> 'a t -> bool val filter: (key -> 'a -> bool) -> 'a t -> 'a t val filter_map: (key -> 'a -> 'b option) -> 'a t -> 'b t val partition: (key -> 'a -> bool) -> 'a t -> 'a t * 'a t val cardinal: 'a t -> int val bindings: 'a t -> (key * 'a) list val choose: 'a t -> (key * 'a) val choose_opt: 'a t -> (key * 'a) option val find: key -> 'a t -> 'a val find_opt : key -> 'a t -> 'a option val map: ('a -> 'b) -> 'a t -> 'b t val mapi: (key -> 'a -> 'b) -> 'a t -> 'b t end module type MapS = sig include UMapS val min_binding: 'a t -> (key * 'a) val max_binding: 'a t -> (key * 'a) val split: key -> 'a t -> 'a t * 'a option * 'a t end rocq-9.2.0/clib/cString.ml000066400000000000000000000165751516144147600153710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* = String.length s then [] else String.make 1 (String.get s n) :: explode_rec (succ n) in explode_rec 0 let implode sl = String.concat "" sl let is_empty s = String.length s = 0 let drop_simple_quotes s = let n = String.length s in if n > 2 && s.[0] = '\'' && s.[n-1] = '\'' then String.sub s 1 (n-2) else s let quote_coq_string s = let b = Buffer.create (String.length s + 2) in Buffer.add_char b '"'; for i = 0 to String.length s - 1 do Buffer.add_char b s.[i]; if s.[i] = '"' then Buffer.add_char b s.[i]; done; Buffer.add_char b '"'; Buffer.contents b let unquote_coq_string s = let b = Buffer.create (String.length s) in let n = String.length s in if n < 2 || s.[0] <> '"' || s.[n-1] <> '"' then None else let i = ref 1 in try while !i < n - 1 do Buffer.add_char b s.[!i]; if s.[!i] = '"' then if !i < n - 2 && s.[!i+1] = '"' then incr i else raise Exit; incr i done; Some (Buffer.contents b) with Exit -> None let html_escape msg = let buf = Buffer.create (String.length msg) in String.iter (fun c -> if String.contains "\"&'<>" c then Buffer.add_string buf (Printf.sprintf "&#%d;" (Char.code c)) else Buffer.add_char buf c) msg; Buffer.contents buf (* substring searching... *) (* gdzie = where, co = what *) (* gdzie=gdzie(string) gl=gdzie(length) gi=gdzie(index) *) let rec raw_is_sub gdzie gl gi co cl ci = (ci>=cl) || ((String.unsafe_get gdzie gi = String.unsafe_get co ci) && (raw_is_sub gdzie gl (gi+1) co cl (ci+1))) let rec raw_str_index i gdzie l c co cl = (* First adapt to ocaml 3.11 new semantics of index_from *) if (i+cl > l) then raise Not_found; (* Then proceed as in ocaml < 3.11 *) let i' = String.index_from gdzie i c in if (i'+cl <= l) && (raw_is_sub gdzie l i' co cl 0) then i' else raw_str_index (i'+1) gdzie l c co cl let string_index_from gdzie i co = if co="" then i else raw_str_index i gdzie (String.length gdzie) (String.unsafe_get co 0) co (String.length co) let string_contains ~where ~what = try let _ = string_index_from where 0 what in true with Not_found -> false let is_sub p s off = let lp = String.length p in let ls = String.length s in if ls < off + lp then false else let rec aux i = if lp <= i then true else let cp = String.unsafe_get p i in let cs = String.unsafe_get s (off + i) in if cp = cs then aux (succ i) else false in aux 0 let is_prefix p s = is_sub p s 0 let is_suffix p s = is_sub p s (String.length s - String.length p) let plural n s = if n<>1 then s^"s" else s let lplural l s = match l with | [_] -> s | _ -> s^"s" let conjugate_verb_to_be n = if n<>1 then "are" else "is" let ordinal n = let s = if (n / 10) mod 10 = 1 then "th" else match n mod 10 with | 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th" in string_of_int n ^ s let uchar_array_of_utf_8_string s = let slen = length s in (* is an upper bound on Uchar.t count *) let uchars = Array.make slen Uchar.max in let k = ref 0 and i = ref 0 in while (!i < slen) do let dec = get_utf_8_uchar s !i in i := !i + Uchar.utf_decode_length dec; uchars.(!k) <- Uchar.utf_decode_uchar dec; incr k; done; uchars, !k let edit_distance ?(limit = Stdlib.Int.max_int) s0 s1 = if limit <= 1 then (if equal s0 s1 then 0 else limit) else let[@inline] minimum a b c = Stdlib.Int.min a (Stdlib.Int.min b c) in let s0, len0 = uchar_array_of_utf_8_string s0 in let s1, len1 = uchar_array_of_utf_8_string s1 in let limit = Stdlib.Int.min (Stdlib.Int.max len0 len1) limit in if Stdlib.Int.abs (len1 - len0) >= limit then limit else let s0, s1 = if len0 > len1 then s0, s1 else s1, s0 in let len0, len1 = if len0 > len1 then len0, len1 else len1, len0 in let rec loop row_minus2 row_minus1 row i len0 limit s0 s1 = if i > len0 then row_minus1.(Array.length row_minus1 - 1) else let len1 = Array.length row - 1 in let row_min = ref Stdlib.Int.max_int in row.(0) <- i; let jmax = let jmax = Stdlib.Int.min len1 (i + limit - 1) in if jmax < 0 then (* overflow *) len1 else jmax in for j = Stdlib.Int.max 1 (i - limit) to jmax do let cost = if Uchar.equal s0.(i-1) s1.(j-1) then 0 else 1 in let min = minimum (row_minus1.(j-1) + cost) (* substitute *) (row_minus1.(j) + 1) (* delete *) (row.(j-1) + 1) (* insert *) (* Note when j = i - limit, the latter [row] read makes a bogus read on the value that was in the matrix at d.(i-2).(i - limit - 1). Since by induction for all i,j, d.(i).(j) >= abs (i - j), (row.(j-1) + 1) is greater or equal to [limit] and thus does not affect adversely the minimum computation. *) in let min = if (i > 1 && j > 1 && Uchar.equal s0.(i-1) s1.(j-2) && Uchar.equal s0.(i-2) s1.(j-1)) then Stdlib.Int.min min (row_minus2.(j-2) + cost) (* transpose *) else min in row.(j) <- min; row_min := Stdlib.Int.min !row_min min; done; if !row_min >= limit then (* can no longer decrease *) limit else loop row_minus1 row row_minus2 (i + 1) len0 limit s0 s1 in let ignore = (* Value used to make the values around the diagonal stripe ignored by the min computations when we have a limit. *) limit + 1 in let row_minus2 = Array.make (len1 + 1) ignore in let row_minus1 = Array.init (len1 + 1) (fun x -> x) in let row = Array.make (len1 + 1) ignore in let d = loop row_minus2 row_minus1 row 1 len0 limit s0 s1 in if d > limit then limit else d (* string parsing *) module Self = struct type t = string let compare = compare end module Set = CSet.Make(Self) module Map = CMap.Make(Self) module Pred = Predicate.Make(Self) module List = struct type elt = string let mem id l = List.exists (fun s -> equal id s) l let assoc id l = CList.assoc_f equal id l let remove_assoc id l = CList.remove_assoc_f equal id l let mem_assoc id l = List.exists (fun (a,_) -> equal id a) l let mem_assoc_sym id l = List.exists (fun (_,b) -> equal id b) l let equal l l' = CList.equal equal l l' end module Hstring = Hashcons.Make(struct type t = string let hashcons s = hash s, s let eq = String.equal end) let hcons = Hashcons.simple_hcons Hstring.generate Hstring.hcons () rocq-9.2.0/clib/cString.mli000066400000000000000000000071761516144147600155370ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int (** Hashing on strings. Should be compatible with generic one. *) val is_empty : string -> bool (** Test whether a string is empty. *) val explode : string -> string list (** [explode "x1...xn"] returns [["x1"; ...; "xn"]] *) val implode : string list -> string (** [implode [s1; ...; sn]] returns [s1 ^ ... ^ sn] *) val drop_simple_quotes : string -> string (** Remove the eventual first surrounding simple quotes of a string. *) val quote_coq_string : string -> string (** Quote a string according to Rocq conventions (i.e. doubling double quotes and surrounding by double quotes) *) val unquote_coq_string : string -> string option (** Unquote a quoted string according to Rocq conventions (i.e. removing surrounding double quotes and undoubling double quotes); returns [None] if not a quoted string *) val html_escape : string -> string (** replace HTML reserved characters with escape sequences, e.g. `&` -> "&" *) val string_index_from : string -> int -> string -> int (** As [index_from], but takes a string instead of a char as pattern argument *) val string_contains : where:string -> what:string -> bool (** As [contains], but takes a string instead of a char as pattern argument *) val plural : int -> string -> string (** [plural n s] adds a optional 's' to the [s] when [2 <= n]. *) val lplural : _ list -> string -> string (** [lplural l s] is [plural (List.length l) s]. *) val conjugate_verb_to_be : int -> string (** [conjugate_verb_to_be] returns "is" when [n=1] and "are" otherwise *) val ordinal : int -> string (** Generate the ordinal number in English. *) val is_sub : string -> string -> int -> bool (** [is_sub p s off] tests whether [s] contains [p] at offset [off]. *) val is_prefix : string -> string -> bool (** [is_prefix p s] tests whether [p] is a prefix of [s]. *) val is_suffix : string -> string -> bool (** [is_suffix suf s] tests whether [suf] is a suffix of [s]. *) val edit_distance : ?limit:int -> string -> string -> int (** [edit_distance s0 s1] is the number of single character edits (understood as insertion, deletion, substitution, transposition) that are needed to change [s0] into [s1]. If [limit] is provided the function returns with [limit] as soon as it was determined that [s0] and [s1] have distance of at least [limit]. This is faster if you have a fixed limit, for example for spellchecking. copied from ocaml 5.4 *) (** {6 Generic operations} **) module Set : CSet.ExtS with type elt = t (** Finite sets on [string] *) module Map : CMap.ExtS with type key = t and module Set := Set (** Finite maps on [string] *) module Pred : Predicate.S with type elt = t module List : CList.MonoS with type elt = t (** Association lists with [string] as keys *) val hcons : string Hashcons.f (** Hashconsing on [string] *) rocq-9.2.0/clib/cThread.ml000066400000000000000000000073501516144147600153210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* loop () in loop () let thread_friendly_read ic s ~off ~len = try let fd = Unix.descr_of_in_channel ic in thread_friendly_read_fd fd s ~off ~len with Unix.Unix_error _ -> 0 let really_read_fd fd s off len = let i = ref 0 in while !i < len do let off = off + !i in let len = len - !i in let r = thread_friendly_read_fd fd s ~off ~len in if r = 0 then raise End_of_file; i := !i + r done let really_read_fd_2_oc fd oc len = let i = ref 0 in let size = 4096 in let s = Bytes.create size in while !i < len do let len = len - !i in let r = thread_friendly_read_fd fd s ~off:0 ~len:(min len size) in if r = 0 then raise End_of_file; i := !i + r; output oc s 0 r; done let thread_friendly_really_read ic s ~off ~len = try let fd = Unix.descr_of_in_channel ic in really_read_fd fd s off len with Unix.Unix_error _ -> raise End_of_file let thread_friendly_really_read_line ic = try let fd = Unix.descr_of_in_channel ic in let b = Buffer.create 1024 in let s = Bytes.make 1 '\000' in let endl = Bytes.of_string "\n" in while not (Bytes.equal s endl) do let n = thread_friendly_read_fd fd s ~off:0 ~len:1 in if n = 0 then raise End_of_file; if not (Bytes.equal s endl) then Buffer.add_bytes b s; done; Buffer.contents b with Unix.Unix_error _ -> raise End_of_file let thread_friendly_input_value ic = try let fd = Unix.descr_of_in_channel ic in let header = Bytes.create Marshal.header_size in really_read_fd fd header 0 Marshal.header_size; let body_size = Marshal.data_size header 0 in let desired_size = body_size + Marshal.header_size in if desired_size <= Sys.max_string_length then begin let msg = Bytes.create desired_size in Bytes.blit header 0 msg 0 Marshal.header_size; really_read_fd fd msg Marshal.header_size body_size; Marshal.from_bytes msg 0 end else begin (* Workaround for 32 bit systems and data > 16M *) let name, oc = Filename.open_temp_file ~mode:[Open_binary] "coq" "marshal" in try output oc header 0 Marshal.header_size; really_read_fd_2_oc fd oc body_size; close_out oc; let ic = open_in_bin name in let data = Marshal.from_channel ic in close_in ic; Sys.remove name; data with e -> Sys.remove name; raise e end with Unix.Unix_error _ | Sys_error _ -> raise End_of_file (* On the ocaml runtime used in some opam-for-windows version the * [Thread.sigmask] API raises Invalid_argument "not implemented", * hence we protect the call and turn the exception into a no-op *) let mask_sigalrm f x = begin try ignore(Thread.sigmask Unix.SIG_BLOCK [Sys.sigalrm]) with Invalid_argument _ -> () end; f x let create f x = Thread.create (mask_sigalrm f) x let with_lock = Memprof_coq.Mutex_aux.with_lock rocq-9.2.0/clib/cThread.mli000066400000000000000000000033721516144147600154720ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* thread_ic val thread_friendly_input_value : thread_ic -> 'a val thread_friendly_read : thread_ic -> Bytes.t -> off:int -> len:int -> int val thread_friendly_really_read : thread_ic -> Bytes.t -> off:int -> len:int -> unit val thread_friendly_really_read_line : thread_ic -> string (* Wrapper around Thread.create that blocks signals such as Sys.sigalrm (used * for Timeout *) val create : ('a -> 'b) -> 'a -> Thread.t (* Atomic mutex lock taken from https://gitlab.com/gadmm/memprof-limits/-/blob/master/src/thread_map.ml#L23-34 *) val with_lock : Mutex.t -> scope:(unit -> 'a) -> 'a rocq-9.2.0/clib/cUnix.ml000066400000000000000000000132111516144147600150260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (* We give up to find a canonical name and just simplify it... *) current ^ dirsep ^ strip_path p let make_suffix name suffix = if Filename.check_suffix name suffix then name else (name ^ suffix) let correct_path f dir = if Filename.is_relative f then Filename.concat dir f else f let file_readable_p name = try Unix.access name [Unix.R_OK];true with Unix.Unix_error (_, _, _) -> false (* As for [Unix.close_process], a [Unix.waipid] that ignores all [EINTR] *) let rec waitpid_non_intr pid = try snd (Unix.waitpid [] pid) with Unix.Unix_error (Unix.EINTR, _, _) -> waitpid_non_intr pid (** [run_command com] launches command [com] (via /bin/sh), and returns the contents of stdout and stderr. If given, [~hook] is called on each elements read on stdout or stderr. *) let run_command ?(hook=(fun _ ->())) c = let result = Buffer.create 127 in let cin,cout,cerr = Unix.open_process_full c (Unix.environment ()) in let buff = Bytes.make 127 ' ' in let buffe = Bytes.make 127 ' ' in let n = ref 0 in let ne = ref 0 in while n:= input cin buff 0 127 ; ne := input cerr buffe 0 127 ; !n+ !ne <> 0 do let r = Bytes.sub buff 0 !n in (hook r; Buffer.add_bytes result r); let r = Bytes.sub buffe 0 !ne in (hook r; Buffer.add_bytes result r); done; (Unix.close_process_full (cin,cout,cerr), Buffer.contents result) (** [sys_command] launches program [prog] with arguments [args]. It behaves like [Sys.command], except that we rely on [Unix.create_process], it's hardly more complex and avoids dealing with shells. In particular, no need to quote arguments (against whitespace or other funny chars in paths), hence no need to care about the different quoting conventions of /bin/sh and cmd.exe. *) let sys_command prog args = let argv = Array.of_list (prog::args) in let pid = Unix.create_process prog argv Unix.stdin Unix.stdout Unix.stderr in waitpid_non_intr pid (* checks if two file names refer to the same (existing) file by comparing their device and inode. It seems that under Windows, inode is always 0, so we cannot accurately check if *) (* Optimised for partial application (in case many candidates must be compared to f1). *) let same_file f1 = try let s1 = Unix.stat f1 in (fun f2 -> try let s2 = Unix.stat f2 in s1.Unix.st_dev = s2.Unix.st_dev && if Sys.os_type = "Win32" then f1 = f2 else s1.Unix.st_ino = s2.Unix.st_ino with Unix.Unix_error _ -> false) with Unix.Unix_error _ -> (fun _ -> false) (* Copied from ocaml filename.ml *) let prng = lazy(Random.State.make_self_init ()) let temp_file_name temp_dir prefix suffix = let rnd = (Random.State.bits (Lazy.force prng)) land 0xFFFFFF in Filename.concat temp_dir (Printf.sprintf "%s%06x%s" prefix rnd suffix) let mktemp_dir ?(temp_dir=Filename.get_temp_dir_name()) prefix suffix = let rec try_name counter = let name = temp_file_name temp_dir prefix suffix in match Unix.mkdir name 0o700 with | () -> name | exception (Sys_error _ as e) -> if counter >= 1000 then raise e else try_name (counter + 1) in try_name 0 rocq-9.2.0/clib/cUnix.mli000066400000000000000000000053601516144147600152050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* physical_path val string_of_physical_path : physical_path -> string (** Escape what has to be escaped (e.g. surround with quotes if with spaces) *) val escaped_string_of_physical_path : physical_path -> string val canonical_path_name : string -> string (** Remove all initial "./" in a path *) val remove_path_dot : string -> string (** If a path [p] starts with the current directory $PWD then [strip_path p] returns the sub-path relative to $PWD. Any leading "./" are also removed from the result. *) val strip_path : string -> string (** correct_path f dir = dir/f if f is relative *) val correct_path : string -> string -> string val path_to_list : string -> string list (** [make_suffix file suf] catenate [file] with [suf] when [file] does not already end with [suf]. *) val make_suffix : string -> string -> string val file_readable_p : string -> bool (** {6 Executing commands } *) (** [run_command com] launches command [com], and returns the contents of stdout and stderr. If given, [~hook] is called on each elements read on stdout or stderr. *) val run_command : ?hook:(bytes->unit) -> string -> Unix.process_status * string (** [sys_command] launches program [prog] with arguments [args]. It behaves like [Sys.command], except that we rely on [Unix.create_process], it's hardly more complex and avoids dealing with shells. In particular, no need to quote arguments (against whitespace or other funny chars in paths), hence no need to care about the different quoting conventions of /bin/sh and cmd.exe. *) val sys_command : string -> string list -> Unix.process_status (** A version of [Unix.waitpid] immune to EINTR exceptions *) val waitpid_non_intr : int -> Unix.process_status (** Check if two file names refer to the same (existing) file *) val same_file : string -> string -> bool (** Like [Stdlib.Filename.temp_file] but producing a directory. *) val mktemp_dir : ?temp_dir:string -> string -> string -> string rocq-9.2.0/clib/diff2.ml000066400000000000000000000110731516144147600147360ustar00rootroot00000000000000(* copied from https://github.com/leque/ocaml-diff.git and renamed from "diff.ml" *) (* * Copyright (C) 2016 OOHASHI Daichi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *) type 'a common = [ `Common of int * int * 'a ] type 'a edit = [ `Added of int * 'a | `Removed of int * 'a | 'a common ] module type SeqType = sig type t type elem val get : t -> int -> elem val length : t -> int end module type S = sig type t type elem val lcs : ?equal:(elem -> elem -> bool) -> t -> t -> elem common list val diff : ?equal:(elem -> elem -> bool) -> t -> t -> elem edit list val fold_left : ?equal:(elem -> elem -> bool) -> f:('a -> elem edit -> 'a) -> init:'a -> t -> t -> 'a val iter : ?equal:(elem -> elem -> bool) -> f:(elem edit -> unit) -> t -> t -> unit end module Make(M : SeqType) : (S with type t = M.t and type elem = M.elem) = struct type t = M.t type elem = M.elem let lcs ?(equal = (=)) a b = let n = M.length a in let m = M.length b in let mn = m + n in let sz = 2 * mn + 1 in let vd = Array.make sz 0 in let vl = Array.make sz 0 in let vr = Array.make sz [] in let get v i = Array.get v (i + mn) in let set v i x = Array.set v (i + mn) x in let finish () = let rec loop i maxl r = if i > mn then List.rev r else if get vl i > maxl then loop (i + 1) (get vl i) (get vr i) else loop (i + 1) maxl r in loop (- mn) 0 [] in if mn = 0 then [] else (* For d <- 0 to mn Do *) let rec dloop d = assert (d <= mn); (* For k <- -d to d in steps of 2 Do *) let rec kloop k = if k > d then dloop @@ d + 1 else let x, l, r = if k = -d || (k <> d && get vd (k - 1) < get vd (k + 1)) then get vd (k + 1), get vl (k + 1), get vr (k + 1) else get vd (k - 1) + 1, get vl (k - 1), get vr (k - 1) in let x, y, l, r = let rec xyloop x y l r = if x < n && y < m && equal (M.get a x) (M.get b y) then xyloop (x + 1) (y + 1) (l + 1) (`Common(x, y, M.get a x) :: r) else x, y, l, r in xyloop x (x - k) l r in set vd k x; set vl k l; set vr k r; if x >= n && y >= m then (* Stop *) finish () else kloop @@ k + 2 in kloop @@ -d in dloop 0 let fold_left ?(equal = (=)) ~f ~init a b = let ff x y = f y x in let fold_map f g x from to_ init = let rec loop i init = if i >= to_ then init else loop (i + 1) (f (g i @@ M.get x i) init) in loop from init in let added i x = `Added (i, x) in let removed i x = `Removed (i, x) in let rec loop cs apos bpos init = match cs with | [] -> init |> fold_map ff removed a apos (M.length a) |> fold_map ff added b bpos (M.length b) | `Common (aoff, boff, _) as e :: rest -> init |> fold_map ff removed a apos aoff |> fold_map ff added b bpos boff |> ff e |> loop rest (aoff + 1) (boff + 1) in loop (lcs ~equal a b) 0 0 init let diff ?(equal = (=)) a b = fold_left ~equal ~f:(fun xs x -> x::xs) ~init:[] a b let iter ?(equal = (=)) ~f a b = fold_left a b ~equal ~f:(fun () x -> f x) ~init:() end rocq-9.2.0/clib/diff2.mli000066400000000000000000000057611516144147600151160ustar00rootroot00000000000000(* copied from https://github.com/leque/ocaml-diff.git and renamed from "diff.mli" *) (** An implementation of Eugene Myers' O(ND) Difference Algorithm\[1\]. This implementation is a port of util.lcs module of {{:http://practical-scheme.net/gauche} Gauche Scheme interpreter}. - \[1\] Eugene Myers, An O(ND) Difference Algorithm and Its Variations, Algorithmica Vol. 1 No. 2, pp. 251-266, 1986. *) type 'a common = [ `Common of int * int * 'a ] (** an element of lcs of seq1 and seq2 *) type 'a edit = [ `Removed of int * 'a | `Added of int * 'a | 'a common ] (** an element of diff of seq1 and seq2. *) module type SeqType = sig type t (** The type of the sequence. *) type elem (** The type of the elements of the sequence. *) val get : t -> int -> elem (** [get t n] returns [n]-th element of the sequence [t]. *) val length : t -> int (** [length t] returns the length of the sequence [t]. *) end (** Input signature of {!Diff.Make}. *) module type S = sig type t (** The type of input sequence. *) type elem (** The type of the elements of result / input sequence. *) val lcs : ?equal:(elem -> elem -> bool) -> t -> t -> elem common list (** [lcs ~equal seq1 seq2] computes the LCS (longest common sequence) of [seq1] and [seq2]. Elements of [seq1] and [seq2] are compared with [equal]. [equal] defaults to [Pervasives.(=)]. Elements of lcs are [`Common (pos1, pos2, e)] where [e] is an element, [pos1] is a position in [seq1], and [pos2] is a position in [seq2]. *) val diff : ?equal:(elem -> elem -> bool) -> t -> t -> elem edit list (** [diff ~equal seq1 seq2] computes the diff of [seq1] and [seq2]. Elements of [seq1] and [seq2] are compared with [equal]. Elements only in [seq1] are represented as [`Removed (pos, e)] where [e] is an element, and [pos] is a position in [seq1]; those only in [seq2] are represented as [`Added (pos, e)] where [e] is an element, and [pos] is a position in [seq2]; those common in [seq1] and [seq2] are represented as [`Common (pos1, pos2, e)] where [e] is an element, [pos1] is a position in [seq1], and [pos2] is a position in [seq2]. *) val fold_left : ?equal:(elem -> elem -> bool) -> f:('a -> elem edit -> 'a) -> init:'a -> t -> t -> 'a (** [fold_left ~equal ~f ~init seq1 seq2] is same as [diff ~equal seq1 seq2 |> ListLabels.fold_left ~f ~init], but does not create an intermediate list. *) val iter : ?equal:(elem -> elem -> bool) -> f:(elem edit -> unit) -> t -> t -> unit (** [iter ~equal ~f seq1 seq2] is same as [diff ~equal seq1 seq2 |> ListLabels.iter ~f], but does not create an intermediate list. *) end (** Output signature of {!Diff.Make}. *) module Make : functor (M : SeqType) -> (S with type t = M.t and type elem = M.elem) (** Functor building an implementation of the diff structure given a sequence type. *) rocq-9.2.0/clib/dune000066400000000000000000000017551516144147600142760ustar00rootroot00000000000000(library (name clib) (synopsis "Coq's Utility Library [general purpose]") (public_name rocq-runtime.clib) (wrapped false) (modules_without_implementation cSig) (modules :standard \ unicodetable_gen) (libraries (select memprof_coq.ml from (!memprof-limits -> memprof_coq.std.ml) (memprof-limits -> memprof_coq.memprof.ml)) str unix threads)) (deprecated_library_name (old_public_name coq-core.clib) (new_public_name rocq-runtime.clib)) (executable (name unicodetable_gen) (modules unicodetable_gen)) (rule (targets unicodetable.ml) (deps (:gen ./unicodetable_gen.exe)) (action (run %{gen} %{targets}))) (rule (target mutex_aux.ml) (action (copy mutex_aux_4.x.ml %{target})) (enabled_if (< %{ocaml_version} 5.0))) (rule (target mutex_aux.ml) (action (copy mutex_aux_5.0.ml %{target})) (enabled_if (and (>= %{ocaml_version} 5.0) (< %{ocaml_version} 5.1)))) (rule (target mutex_aux.ml) (action (copy mutex_aux_5.x.ml %{target})) (enabled_if (>= %{ocaml_version} 5.1))) rocq-9.2.0/clib/dyn.ml000066400000000000000000000124001516144147600145310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a value -> t -> t val remove : 'a key -> t -> t val find : 'a key -> t -> 'a value val mem : 'a key -> t -> bool val modify : 'a key -> ('a value -> 'a value) -> t -> t type map = { map : 'a. 'a key -> 'a value -> 'a value } val map : map -> t -> t type any = Any : 'a key * 'a value -> any val iter : (any -> unit) -> t -> unit val fold : (any -> 'r -> 'r) -> t -> 'r -> 'r type filter = { filter : 'a. 'a key -> 'a value -> bool } val filter : filter -> t -> t end module type PreS = sig type 'a tag type t = Dyn : 'a tag * 'a -> t val create : string -> 'a tag val eq : 'a tag -> 'b tag -> ('a, 'b) CSig.eq option val repr : 'a tag -> string val dump : unit -> (int * string) list type any = Any : 'a tag -> any val name : string -> any option module Map(Value : ValueS) : MapS with type 'a key = 'a tag and type 'a value = 'a Value.t module HMap (V1 : ValueS)(V2 : ValueS) : sig type map = { map : 'a. 'a tag -> 'a V1.t -> 'a V2.t } val map : map -> Map(V1).t -> Map(V2).t type filter = { filter : 'a. 'a tag -> 'a V1.t -> bool } val filter : filter -> Map(V1).t -> Map(V1).t end end module type S = sig include PreS module Easy : sig val make_dyn_tag : string -> ('a -> t) * (t -> 'a) * 'a tag val make_dyn : string -> ('a -> t) * (t -> 'a) val inj : 'a -> 'a tag -> t val prj : t -> 'a tag -> 'a option end end module Make () = struct module Self : PreS = struct (* Dynamics, programmed with DANGER !!! *) type 'a tag = int type t = Dyn : 'a tag * 'a -> t type any = Any : 'a tag -> any let dyntab = ref (Int.Map.empty : string Int.Map.t) (** Instead of working with tags as strings, which are costly, we use their hash. We ensure unicity of the hash in the [create] function. If ever a collision occurs, which is unlikely, it is sufficient to tweak the offending dynamic tag. *) let create (s : string) = let hash = Hashtbl.hash s in if Int.Map.mem hash !dyntab then begin let old = Int.Map.find hash !dyntab in Printf.eprintf "Dynamic tag collision: %s vs. %s\n%!" s old; assert false end; dyntab := Int.Map.add hash s !dyntab; hash let eq : 'a 'b. 'a tag -> 'b tag -> ('a, 'b) CSig.eq option = fun h1 h2 -> if Int.equal h1 h2 then Some (Obj.magic CSig.Refl) else None let repr s = try Int.Map.find s !dyntab with Not_found -> let () = Printf.eprintf "Unknown dynamic tag %i\n%!" s in assert false let name s = let hash = Hashtbl.hash s in if Int.Map.mem hash !dyntab then Some (Any hash) else None let dump () = Int.Map.bindings !dyntab module Map(Value: ValueS) = struct type t = Obj.t Value.t Int.Map.t type 'a key = 'a tag type 'a value = 'a Value.t let cast : 'a value -> 'b value = Obj.magic let empty = Int.Map.empty let add tag v m = Int.Map.add tag (cast v) m let remove tag m = Int.Map.remove tag m let find tag m = cast (Int.Map.find tag m) let mem = Int.Map.mem let modify tag f m = Int.Map.modify tag (fun _ v -> cast (f (cast v))) m type map = { map : 'a. 'a tag -> 'a value -> 'a value } let map f m = Int.Map.mapi f.map m type any = Any : 'a tag * 'a value -> any let iter f m = Int.Map.iter (fun k v -> f (Any (k, v))) m let fold f m accu = Int.Map.fold (fun k v accu -> f (Any (k, v)) accu) m accu type filter = { filter : 'a. 'a tag -> 'a value -> bool } let filter f m = Int.Map.filter f.filter m end module HMap (V1 : ValueS) (V2 : ValueS) = struct type map = { map : 'a. 'a tag -> 'a V1.t -> 'a V2.t } let map (f : map) (m : Map(V1).t) : Map(V2).t = Int.Map.mapi f.map m type filter = { filter : 'a. 'a tag -> 'a V1.t -> bool } let filter (f : filter) (m : Map(V1).t) : Map(V1).t = Int.Map.filter f.filter m end end include Self module Easy = struct (* now tags are opaque, we can do the trick *) let make_dyn_tag (s : string) = (fun (type a) (tag : a tag) -> let infun : (a -> t) = fun x -> Dyn (tag, x) in let outfun : (t -> a) = fun (Dyn (t, x)) -> match eq tag t with | None -> assert false | Some CSig.Refl -> x in infun, outfun, tag) (create s) let make_dyn (s : string) = let inf, outf, _ = make_dyn_tag s in inf, outf let inj x tag = Dyn(tag,x) let prj : type a. t -> a tag -> a option = fun (Dyn(tag',x)) tag -> match eq tag tag' with | None -> None | Some CSig.Refl -> Some x end end rocq-9.2.0/clib/dyn.mli000066400000000000000000000062221516144147600147070ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a value -> t -> t val remove : 'a key -> t -> t val find : 'a key -> t -> 'a value val mem : 'a key -> t -> bool val modify : 'a key -> ('a value -> 'a value) -> t -> t type map = { map : 'a. 'a key -> 'a value -> 'a value } val map : map -> t -> t type any = Any : 'a key * 'a value -> any val iter : (any -> unit) -> t -> unit val fold : (any -> 'r -> 'r) -> t -> 'r -> 'r type filter = { filter : 'a. 'a key -> 'a value -> bool } val filter : filter -> t -> t end module type S = sig type 'a tag (** Type of dynamic tags *) type t = Dyn : 'a tag * 'a -> t (** Type of dynamic values *) val create : string -> 'a tag (** [create n] returns a tag describing a type called [n]. [create] raises an exception if [n] is already registered. Type names are hashed, so [create] may raise even if no type with the exact same name was registered due to a collision. *) val eq : 'a tag -> 'b tag -> ('a, 'b) CSig.eq option (** [eq t1 t2] returns [Some witness] if [t1] is the same as [t2], [None] otherwise. *) val repr : 'a tag -> string (** [repr tag] returns the name of the type represented by [tag]. *) val dump : unit -> (int * string) list (** [dump ()] returns a list of (tag, name) pairs for every type tag registered in this [Dyn.Make] instance. *) type any = Any : 'a tag -> any (** Type of boxed dynamic tags *) val name : string -> any option (** [name n] returns [Some t] where t is a boxed tag previously registered with [create n], or [None] if there is no such tag. *) module Map(Value : ValueS) : MapS with type 'a key = 'a tag and type 'a value = 'a Value.t (** Map from type tags to values parameterized by the tag type *) module HMap (V1 : ValueS)(V2 : ValueS) : sig type map = { map : 'a. 'a tag -> 'a V1.t -> 'a V2.t } val map : map -> Map(V1).t -> Map(V2).t type filter = { filter : 'a. 'a tag -> 'a V1.t -> bool } val filter : filter -> Map(V1).t -> Map(V1).t end module Easy : sig (* To create a dynamic type on the fly *) val make_dyn_tag : string -> ('a -> t) * (t -> 'a) * 'a tag val make_dyn : string -> ('a -> t) * (t -> 'a) (* For types declared with the [create] function above *) val inj : 'a -> 'a tag -> t val prj : t -> 'a tag -> 'a option end end module Make () : S rocq-9.2.0/clib/exninfo.ml000066400000000000000000000074241516144147600154170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t (** Create a new piece of information. *) val null : info (** No information *) val add : info -> 'a t -> 'a -> info (** Add information to an exception. *) val get : info -> 'a t -> 'a option (** Get information worn by an exception. Returns [None] if undefined. *) val info : exn -> info (** Retrieve the information of the last exception raised. *) type backtrace val get_backtrace : info -> backtrace option (** [get_backtrace info] does get the backtrace associated to info *) val backtrace_to_string : backtrace -> string (** [backtrace_to_string info] does get the backtrace associated to info *) val record_backtrace : bool -> unit val capture : exn -> iexn (** Add the current backtrace information and other meta-data to the given exception. The intended use case is to re-raise an exception while preserving the meta-data: {[ try foo with | Bar -> bar | My_exn _ as exn -> let (exn, info) = Exninfo.capture err in ... let info = ... in Exninfo.iraise (exn, info) | exn when CErrors.noncritical exn -> let iexn = Exninfo.capture err in ... Exninfo.iraise iexn ]} where [baz] should re-raise using [iraise] below. WARNING: any intermediate code between the [with] and the handler may modify the backtrace. Yes, that includes [when] clauses. Ideally, what you should do is something like: {[ try foo with exn when CErrors.noncritical exn -> let (err, info) = Exninfo.capture exn in match err with | exception Bar -> ... | err -> ... ]} I admit that's a bit heavy, but there is not much to do... *) val iraise : iexn -> 'a (** Raise the given enriched exception. *) val reify : unit -> info rocq-9.2.0/clib/hMap.ml000066400000000000000000000266021516144147600146350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int val hash : t -> int end module SetMake(M : HashedType) = struct (** Hash Sets use hashes to prevent doing too many comparison tests. They associate to each hash the set of keys having that hash. Invariants: 1. There is no empty set in the intmap. 2. All values in the same set have the same hash, which is the int to which it is associated in the intmap. *) module Set = Set.Make(M) type elt = M.t type t = Set.t Int.Map.t let empty = Int.Map.empty let is_empty = Int.Map.is_empty let mem x s = if Int.Map.is_empty s then false else let h = M.hash x in try let m = Int.Map.find h s in Set.mem x m with Not_found -> false let add x s = let h = M.hash x in Int.Map.update h (function | None -> Some (Set.singleton x) | Some m -> Some (Set.add x m)) s let singleton x = let h = M.hash x in let m = Set.singleton x in Int.Map.singleton h m let remove x s = if Int.Map.is_empty s then s else let h = M.hash x in Int.Map.update h (function | None -> None | Some m -> let m = Set.remove x m in if Set.is_empty m then None else Some m) s let height s = Int.Map.height s let is_smaller s1 s2 = height s1 <= height s2 + 3 (** Assumes s1 << s2 *) let fast_union s1 s2 = let fold h s accu = try Int.Map.modify h (fun _ s' -> Set.fold Set.add s s') accu with Not_found -> Int.Map.add h s accu in Int.Map.fold fold s1 s2 let union s1 s2 = if is_smaller s1 s2 then fast_union s1 s2 else if is_smaller s2 s1 then fast_union s2 s1 else let fu _ m1 m2 = match m1, m2 with | None, None -> None | (Some _ as m), None | None, (Some _ as m) -> m | Some m1, Some m2 -> Some (Set.union m1 m2) in Int.Map.merge fu s1 s2 (** Assumes s1 << s2 *) let fast_inter s1 s2 = let fold h s accu = try let s' = Int.Map.find h s2 in let si = Set.filter (fun e -> Set.mem e s') s in if Set.is_empty si then accu else Int.Map.add h si accu with Not_found -> accu in Int.Map.fold fold s1 Int.Map.empty let inter s1 s2 = if is_smaller s1 s2 then fast_inter s1 s2 else if is_smaller s2 s1 then fast_inter s2 s1 else let fu _ m1 m2 = match m1, m2 with | None, None -> None | Some _, None | None, Some _ -> None | Some m1, Some m2 -> let m = Set.inter m1 m2 in if Set.is_empty m then None else Some m in Int.Map.merge fu s1 s2 (** Assumes s1 << s2 *) let fast_diff_l s1 s2 = let fold h s accu = try let s' = Int.Map.find h s2 in let si = Set.filter (fun e -> not (Set.mem e s')) s in if Set.is_empty si then accu else Int.Map.add h si accu with Not_found -> Int.Map.add h s accu in Int.Map.fold fold s1 Int.Map.empty (** Assumes s2 << s1 *) let fast_diff_r s1 s2 = let fold h s accu = try let s' = Int.Map.find h accu in let si = Set.filter (fun e -> not (Set.mem e s)) s' in if Set.is_empty si then Int.Map.remove h accu else Int.Map.set h si accu with Not_found -> accu in Int.Map.fold fold s2 s1 let diff s1 s2 = if is_smaller s1 s2 then fast_diff_l s1 s2 else if is_smaller s2 s2 then fast_diff_r s1 s2 else let fu _ m1 m2 = match m1, m2 with | None, None -> None | (Some _ as m), None -> m | None, Some _ -> None | Some m1, Some m2 -> let m = Set.diff m1 m2 in if Set.is_empty m then None else Some m in Int.Map.merge fu s1 s2 let compare s1 s2 = Int.Map.compare Set.compare s1 s2 let equal s1 s2 = Int.Map.equal Set.equal s1 s2 let subset s1 s2 = let check h m1 = let m2 = try Int.Map.find h s2 with Not_found -> Set.empty in Set.subset m1 m2 in Int.Map.for_all check s1 let iter f s = let fi _ m = Set.iter f m in Int.Map.iter fi s let fold f s accu = let ff _ m accu = Set.fold f m accu in Int.Map.fold ff s accu let for_all f s = let ff _ m = Set.for_all f m in Int.Map.for_all ff s let exists f s = let fe _ m = Set.exists f m in Int.Map.exists fe s let filter f s = let ff m = Set.filter f m in let s = Int.Map.map ff s in Int.Map.filter (fun _ m -> not (Set.is_empty m)) s let filter_map f s = Int.Map.filter_map (fun _ m -> let m = Set.filter_map f m in if Set.is_empty m then None else Some m) s let partition f s = let fold h m (sl, sr) = let (ml, mr) = Set.partition f m in let sl = if Set.is_empty ml then sl else Int.Map.add h ml sl in let sr = if Set.is_empty mr then sr else Int.Map.add h mr sr in (sl, sr) in Int.Map.fold fold s (Int.Map.empty, Int.Map.empty) let cardinal s = let fold _ m accu = accu + Set.cardinal m in Int.Map.fold fold s 0 let elements s = let fold _ m accu = Set.fold (fun x accu -> x :: accu) m accu in Int.Map.fold fold s [] let choose s = let (_, m) = Int.Map.choose s in Set.choose m end module Make(M : HashedType) = struct (** This module is essentially the same as SetMake, except that we have maps instead of sets in the intmap. Invariants are the same. *) module Set = SetMake(M) module Map = CMap.Make(M) type key = M.t type 'a t = 'a Map.t Int.Map.t let empty = Int.Map.empty let is_empty = Int.Map.is_empty let mem k s = if Int.Map.is_empty s then false else let h = M.hash k in try let m = Int.Map.find h s in Map.mem k m with Not_found -> false let add k x s = let h = M.hash k in Int.Map.update h (function | None -> Some (Map.singleton k x) | Some m -> Some (Map.add k x m)) s let singleton k x = let h = M.hash k in Int.Map.singleton h (Map.singleton k x) let remove k s = if Int.Map.is_empty s then s else let h = M.hash k in Int.Map.update h (function | None -> None | Some m -> let m = Map.remove k m in if Map.is_empty m then None else Some m) s let merge f s1 s2 = let fm h m1 m2 = match m1, m2 with | None, None -> None | Some m, None -> let m = Map.merge f m Map.empty in if Map.is_empty m then None else Some m | None, Some m -> let m = Map.merge f Map.empty m in if Map.is_empty m then None else Some m | Some m1, Some m2 -> let m = Map.merge f m1 m2 in if Map.is_empty m then None else Some m in Int.Map.merge fm s1 s2 let union f s1 s2 = let fm h m1 m2 = let m = Map.union f m1 m2 in if Map.is_empty m then None else Some m in Int.Map.union fm s1 s2 let compare f s1 s2 = let fc m1 m2 = Map.compare f m1 m2 in Int.Map.compare fc s1 s2 let equal f s1 s2 = let fe m1 m2 = Map.equal f m1 m2 in Int.Map.equal fe s1 s2 let iter f s = let fi _ m = Map.iter f m in Int.Map.iter fi s let fold f s accu = let ff _ m accu = Map.fold f m accu in Int.Map.fold ff s accu let for_all f s = let ff _ m = Map.for_all f m in Int.Map.for_all ff s let exists f s = let fe _ m = Map.exists f m in Int.Map.exists fe s let filter f s = let ff m = Map.filter f m in let s = Int.Map.map ff s in Int.Map.filter (fun _ m -> not (Map.is_empty m)) s let filter_map f s = let ff m = Map.filter_map f m in let s = Int.Map.map ff s in Int.Map.filter (fun _ m -> not (Map.is_empty m)) s let partition f s = let fold h m (sl, sr) = let (ml, mr) = Map.partition f m in let sl = if Map.is_empty ml then sl else Int.Map.add h ml sl in let sr = if Map.is_empty mr then sr else Int.Map.add h mr sr in (sl, sr) in Int.Map.fold fold s (Int.Map.empty, Int.Map.empty) let cardinal s = let fold _ m accu = accu + Map.cardinal m in Int.Map.fold fold s 0 let bindings s = let fold _ m accu = Map.fold (fun k x accu -> (k, x) :: accu) m accu in Int.Map.fold fold s [] let choose s = let (_, m) = Int.Map.choose s in Map.choose m let choose_opt s = try Some (choose s) with Not_found -> None let find k s = if Int.Map.is_empty s then raise Not_found else let h = M.hash k in let m = Int.Map.find h s in Map.find k m let find_opt k s = if Int.Map.is_empty s then None else let h = M.hash k in match Int.Map.find_opt h s with | None -> None | Some m -> Map.find_opt k m let get k s = let h = M.hash k in let m = Int.Map.get h s in Map.get k m let map f s = let fs m = Map.map f m in Int.Map.map fs s let mapi f s = let fs m = Map.mapi f m in Int.Map.map fs s let modify k f s = if Int.Map.is_empty s then raise Not_found else let h = M.hash k in Int.Map.modify h (fun _ m -> Map.modify k f m) s let bind f s = let fb m = Map.bind f m in Int.Map.map fb s let domain s = Int.Map.map Map.domain s let set k x s = if Int.Map.is_empty s then raise Not_found else let h = M.hash k in Int.Map.modify h (fun _ m -> Map.set k x m) s module Smart = struct let map f s = let fs m = Map.Smart.map f m in Int.Map.Smart.map fs s let mapi f s = let fs m = Map.Smart.mapi f m in Int.Map.Smart.map fs s end let height s = Int.Map.height s (* Not as efficient as the original version *) let filter_range f s = filter (fun x _ -> f x = 0) s let of_list l = let fold accu (x, v) = add x v accu in List.fold_left fold empty l let update k f m = if Int.Map.is_empty m then begin match f None with | None -> m | Some v -> singleton k v end else let aux = function | None -> (match f None with | None -> None | Some v -> Some (Map.singleton k v)) | Some m -> let m = Map.update k f m in if Map.is_empty m then None else Some m in Int.Map.update (M.hash k) aux m module Monad(M : CMap.MonadS) = struct module IntM = Int.Map.Monad(M) module ExtM = Map.Monad(M) let fold f s accu = let ff _ m accu = ExtM.fold f m accu in IntM.fold ff s accu let mapi f s = IntM.mapi (fun _ m -> ExtM.mapi f m) s end let symmetric_diff_fold f lm rm acc = Int.Map.symmetric_diff_fold (fun _ l r -> match l, r with | Some m, None -> Map.fold (fun k v acc -> f k (Some v) None acc) m | None, Some m -> Map.fold (fun k v acc -> f k None (Some v) acc) m | Some lm, Some rm -> Map.symmetric_diff_fold f lm rm | None, None -> assert false) lm rm acc end rocq-9.2.0/clib/hMap.mli000066400000000000000000000024541516144147600150050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int (** Total ordering *) val hash : t -> int (** Hashing function compatible with [compare], i.e. [compare x y = 0] implies [hash x = hash y]. *) end (** Hash maps are maps that take advantage of having a hash on keys. This is essentially a hash table, except that it uses purely functional maps instead of arrays. CAVEAT: order-related functions like [fold] or [iter] do not respect the provided order anymore! It's your duty to do something sensible to prevent this if you need it. *) module Make(M : HashedType) : CMap.UExtS with type key = M.t rocq-9.2.0/clib/hashcons.ml000066400000000000000000000076001516144147600155530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool end module type HashconsedRecType = sig type t val hashcons : t f -> t f val eq : t -> t -> bool end (** The output is a function [generate] such that [generate args] creates a hash-table of the hash-consed objects, together with [hcons], a function taking a table and an object, and hashcons it. For simplicity of use, we use the wrapper functions defined below. *) module type S = sig type t type table val generate : unit -> table val hcons : table -> t f val stats : table -> Hashset.statistics end module Make (X : HashconsedType) : (S with type t = X.t) = struct type t = X.t (* We create the type of hashtables for t, with our comparison fun. * An invariant is that the table never contains two entries equals * w.r.t (=), although the equality on keys is X.eq. This is * granted since we hcons the subterms before looking up in the table. *) module Htbl = Hashset.Make(X) type table = Htbl.t let generate () = let tab = Htbl.create 97 in tab let hcons tab x = let h, y = X.hashcons x in h, Htbl.repr h y tab let stats = Htbl.stats end module MakeRec (X : HashconsedRecType) : (S with type t = X.t) = struct type t = X.t module Htbl = Hashset.Make(X) type table = Htbl.t let generate () = let tab = Htbl.create 97 in tab let rec hcons tab x = let h, y = X.hashcons (hcons tab) x in h, Htbl.repr h y tab let stats = Htbl.stats end (* A few useful wrappers: * takes as argument the function [generate] above and build a function of type * u -> t -> t that creates a fresh table each time it is applied to the * sub-hcons functions. *) (* For non-recursive types it is quite easy. *) let simple_hcons h f u = let table = h u in fun x -> f table x (* Basic hashcons modules for string and obj. Integers do not need be hashconsed. *) module type HashedType = sig type t val hcons : t f end (* list *) module Hlist (D:HashedType) : S with type t = D.t list = struct module X = struct type t = D.t list let eq l1 l2 = l1 == l2 || match l1, l2 with | [], [] -> true | x1::l1, x2::l2 -> x1==x2 && l1==l2 | _ -> false end type t = X.t module Htbl = Hashset.Make(X) type table = Htbl.t let generate () = let tab = Htbl.create 97 in tab let rec hcons tab l = let h, l = match l with | [] -> 0, [] | x :: l -> let hx, x = D.hcons x in let h, l = hcons tab l in let h = Hashset.Combine.combine hx h in h, x :: l in h, Htbl.repr h l tab let stats = Htbl.stats end let hashcons_array hcons a = CArray.Smart.fold_left_map (fun acc x -> let hx, x = hcons x in Hashset.Combine.combine acc hx, x) 0 a rocq-9.2.0/clib/hashcons.mli000066400000000000000000000072441516144147600157300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool (** A comparison function. It is allowed to use physical equality on the sub-terms hashconsed by the [hashcons] function, but it should be insensible to shallow copy of the compared object. It should be compatible with the hash returned by [hashcons], ie [eq x y] implies [fst @@ hashcons x = fst @@ hashcons y]. *) end module type HashconsedRecType = sig type t val hashcons : t f -> t f (** Hashcons the given constructor, calling the provided function on children. *) val eq : t -> t -> bool end module type S = sig type t (** Type of objects to hashcons. *) type table (** Type of hashconsing tables *) val generate : unit -> table (** This create a hashtable of the hashconsed objects. *) val hcons : table -> t f (** Perform the hashconsing of the given object within the table, and returns the hash. *) val stats : table -> Hashset.statistics (** Recover statistics of the hashconsing table. *) end module Make (X : HashconsedType) : (S with type t = X.t) (** Create a new hashconsing, given canonicalization functions. *) module MakeRec (X : HashconsedRecType) : (S with type t = X.t) (** Create a new hashconsing, given canonicalization functions. [hashcons] will get the resulting [hcons] as first argument. *) (** {6 Wrappers} *) (** These are intended to be used together with instances of the [Make] functor. *) val simple_hcons : ('u -> 'tab) -> ('tab -> 't -> 'v) -> 'u -> 't -> 'v (** Typically used as [let hcons = simple_hcons H.generate H.hcons ()] where [H] is of type [S]. *) (** {6 Hashconsing of usual structures} *) module type HashedType = sig type t val hcons : t f end module Hlist (D:HashedType) : (S with type t = D.t list) (** Hashconsing of lists. *) val hashcons_array : 'v f -> 'v array f (** Helper for array hashconsing. Shares the elements producing a new array if needed, does not mutate the array, does not share the array itself. *) rocq-9.2.0/clib/hashset.ml000066400000000000000000000172611516144147600154100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool end type statistics = { num_bindings: int; num_buckets: int; max_bucket_length: int; bucket_histogram: int array } module type S = sig type elt type t val create : int -> t val clear : t -> unit val repr : int -> elt -> t -> elt val stats : t -> statistics end module Make (E : EqType) = struct type elt = E.t let emptybucket = Weak.create 0 type t = { mutable table : elt Weak.t array; mutable hashes : int array array; mutable limit : int; (* bucket size limit *) mutable oversize : int; (* number of oversize buckets *) mutable rover : int; (* for internal bookkeeping *) } let get_index t h = (h land max_int) mod (Array.length t) let limit = 7 let over_limit = 2 let create sz = let sz = if sz < 7 then 7 else sz in let sz = if sz > Sys.max_array_length then Sys.max_array_length else sz in { table = Array.make sz emptybucket; hashes = Array.make sz [| |]; limit = limit; oversize = 0; rover = 0; } let clear t = for i = 0 to Array.length t.table - 1 do t.table.(i) <- emptybucket; t.hashes.(i) <- [| |]; done; t.limit <- limit; t.oversize <- 0 let iter_weak f t = let rec iter_bucket i j b = if i >= Weak.length b then () else match Weak.check b i with | true -> f b t.hashes.(j) i; iter_bucket (i+1) j b | false -> iter_bucket (i+1) j b in for i = 0 to pred (Array.length t.table) do iter_bucket 0 i (Array.unsafe_get t.table i) done let rec count_bucket i b accu = if i >= Weak.length b then accu else count_bucket (i+1) b (accu + (if Weak.check b i then 1 else 0)) let min x y = if x - y < 0 then x else y let next_sz n = min (3 * n / 2 + 3) Sys.max_array_length let prev_sz n = ((n - 3) * 2 + 2) / 3 let test_shrink_bucket t = let bucket = t.table.(t.rover) in let hbucket = t.hashes.(t.rover) in let len = Weak.length bucket in let prev_len = prev_sz len in let live = count_bucket 0 bucket 0 in if live <= prev_len then begin let rec loop i j = if j >= prev_len then begin if Weak.check bucket i then loop (i + 1) j else if Weak.check bucket j then begin Weak.blit bucket j bucket i 1; hbucket.(i) <- hbucket.(j); loop (i + 1) (j - 1); end else loop i (j - 1); end; in loop 0 (Weak.length bucket - 1); if prev_len = 0 then begin t.table.(t.rover) <- emptybucket; t.hashes.(t.rover) <- [| |]; end else begin let newbucket = Weak.create prev_len in Weak.blit bucket 0 newbucket 0 prev_len; t.table.(t.rover) <- newbucket; t.hashes.(t.rover) <- Array.sub hbucket 0 prev_len end; if len > t.limit && prev_len <= t.limit then t.oversize <- t.oversize - 1; end; t.rover <- (t.rover + 1) mod (Array.length t.table) let rec resize t = let oldlen = Array.length t.table in let newlen = next_sz oldlen in if newlen > oldlen then begin let newt = create newlen in let add_weak ob oh oi = let setter nb ni _ = Weak.blit ob oi nb ni 1 in let h = oh.(oi) in add_aux newt setter None h (get_index newt.table h); in iter_weak add_weak t; t.table <- newt.table; t.hashes <- newt.hashes; t.limit <- newt.limit; t.oversize <- newt.oversize; t.rover <- t.rover mod Array.length newt.table; end else begin t.limit <- max_int; (* maximum size already reached *) t.oversize <- 0; end and add_aux t setter d h index = let bucket = t.table.(index) in let hashes = t.hashes.(index) in let sz = Weak.length bucket in let rec loop i = if i >= sz then begin let newsz = min (3 * sz / 2 + 3) (Sys.max_array_length - 1) in if newsz <= sz then failwith "Weak.Make: hash bucket cannot grow more"; let newbucket = Weak.create newsz in let newhashes = Array.make newsz 0 in Weak.blit bucket 0 newbucket 0 sz; Array.blit hashes 0 newhashes 0 sz; setter newbucket sz d; newhashes.(sz) <- h; t.table.(index) <- newbucket; t.hashes.(index) <- newhashes; if sz <= t.limit && newsz > t.limit then begin t.oversize <- t.oversize + 1; for _i = 0 to over_limit do test_shrink_bucket t done; end; if t.oversize > Array.length t.table / over_limit then resize t end else if Weak.check bucket i then begin loop (i + 1) end else begin setter bucket i d; hashes.(i) <- h end in loop 0 external unsafe_weak_get : 'a Weak.t -> int -> 'a option = "caml_weak_get" let repr h d t = let table = t.table in let index = get_index table h in let bucket = Array.unsafe_get table index in let hashes = Array.unsafe_get t.hashes index in let sz = Weak.length bucket in let pos = ref 0 in let ans = ref None in while !pos < sz && !ans == None do let i = !pos in if Int.equal h (Array.unsafe_get hashes i) then begin match unsafe_weak_get bucket i with | Some v as res when E.eq v d -> ans := res | _ -> incr pos end else incr pos done; match !ans with | Some v -> v | None -> let () = add_aux t Weak.set (Some d) h index in d let stats t = let fold accu bucket = max (count_bucket 0 bucket 0) accu in let max_length = Array.fold_left fold 0 t.table in let histogram = Array.make (max_length + 1) 0 in let iter bucket = let len = count_bucket 0 bucket 0 in histogram.(len) <- succ histogram.(len) in let () = Array.iter iter t.table in let fold (num, len, i) k = (num + k * i, len + k, succ i) in let (num, len, _) = Array.fold_left fold (0, 0, 0) histogram in { num_bindings = num; num_buckets = len; max_bucket_length = Array.length histogram; bucket_histogram = histogram; } end module Combine = struct (* These are helper functions to combine the hash keys in a similar way as [Hashtbl.hash] does. The constants [alpha] and [beta] must be prime numbers. There were chosen empirically. Notice that the problem of hashing trees is hard and there are plenty of study on this topic. Therefore, there must be room for improvement here. *) let alpha = 65599 let beta = 7 let combine x y = x * alpha + y let combine3 x y z = combine x (combine y z) let combine4 x y z t = combine x (combine3 y z t) let combine5 x y z t u = combine x (combine4 y z t u) let combinesmall x y = beta * x + y end rocq-9.2.0/clib/hashset.mli000066400000000000000000000042141516144147600155530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool end type statistics = { num_bindings: int; num_buckets: int; max_bucket_length: int; bucket_histogram: int array } module type S = sig type elt (** Type of hashsets elements. *) type t (** Type of hashsets. *) val create : int -> t (** [create n] creates a fresh hashset with initial size [n]. *) val clear : t -> unit (** Clear the contents of a hashset. *) val repr : int -> elt -> t -> elt (** [repr key constr set] uses [key] to look for [constr] in the hashet [set]. If [constr] is in [set], returns the specific representation that is stored in [set]. Otherwise, [constr] is stored in [set] and will be used as the canonical representation of this value in the future. *) val stats : t -> statistics (** Recover statistics on the table. *) end module Make (E : EqType) : S with type elt = E.t module Combine : sig val combine : int -> int -> int val combinesmall : int -> int -> int val combine3 : int -> int -> int -> int val combine4 : int -> int -> int -> int -> int val combine5 : int -> int -> int -> int -> int -> int end rocq-9.2.0/clib/heap.ml000066400000000000000000000071551516144147600146670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type S =sig (* Type of functional heaps *) type t (* Type of elements *) type elt (* The empty heap *) val empty : t (* [add x h] returns a new heap containing the elements of [h], plus [x]; complexity $O(log(n))$ *) val add : elt -> t -> t (* [maximum h] returns the maximum element of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(1)$ *) val maximum : t -> elt (* [remove h] returns a new heap containing the elements of [h], except the maximum of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(log(n))$ *) val remove : t -> t (* usual iterators and combinators; elements are presented in arbitrary order *) val iter : (elt -> unit) -> t -> unit val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a end exception EmptyHeap (*s Functional implementation *) module Functional(X : Ordered) = struct (* Heaps are encoded as Braun trees, that are binary trees where size r <= size l <= size r + 1 for each node Node (l, x, r) *) type t = | Leaf | Node of t * X.t * t type elt = X.t let empty = Leaf let rec add x = function | Leaf -> Node (Leaf, x, Leaf) | Node (l, y, r) -> if X.compare x y >= 0 then Node (add y r, x, l) else Node (add x r, y, l) let rec extract = function | Leaf -> assert false | Node (Leaf, y, r) -> assert (r = Leaf); y, Leaf | Node (l, y, r) -> let x, l = extract l in x, Node (r, y, l) let is_above x = function | Leaf -> true | Node (_, y, _) -> X.compare x y >= 0 let rec replace_min x = function | Node (l, _, r) when is_above x l && is_above x r -> Node (l, x, r) | Node ((Node (_, lx, _) as l), _, r) when is_above lx r -> (* lx <= x, rx necessarily *) Node (replace_min x l, lx, r) | Node (l, _, (Node (_, rx, _) as r)) -> (* rx <= x, lx necessarily *) Node (l, rx, replace_min x r) | Leaf | Node (Leaf, _, _) | Node (_, _, Leaf) -> assert false (* merges two Braun trees [l] and [r], with the assumption that [size r <= size l <= size r + 1] *) let rec merge l r = match l, r with | _, Leaf -> l | Node (ll, lx, lr), Node (_, ly, _) -> if X.compare lx ly >= 0 then Node (r, lx, merge ll lr) else let x, l = extract l in Node (replace_min x r, ly, l) | Leaf, _ -> assert false (* contradicts the assumption *) let maximum = function | Leaf -> raise EmptyHeap | Node (_, x, _) -> x let remove = function | Leaf -> raise EmptyHeap | Node (l, _, r) -> merge l r let rec iter f = function | Leaf -> () | Node (l, x, r) -> iter f l; f x; iter f r let rec fold f h x0 = match h with | Leaf -> x0 | Node (l, x, r) -> fold f l (fold f r (f x x0)) end rocq-9.2.0/clib/heap.mli000066400000000000000000000032531516144147600150330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type S =sig (** Type of functional heaps *) type t (** Type of elements *) type elt (** The empty heap *) val empty : t (** [add x h] returns a new heap containing the elements of [h], plus [x]; complexity {% $ %}O(log(n)){% $ %} *) val add : elt -> t -> t (** [maximum h] returns the maximum element of [h]; raises [EmptyHeap] when [h] is empty; complexity {% $ %}O(1){% $ %} *) val maximum : t -> elt (** [remove h] returns a new heap containing the elements of [h], except the maximum of [h]; raises [EmptyHeap] when [h] is empty; complexity {% $ %}O(log(n)){% $ %} *) val remove : t -> t (** usual iterators and combinators; elements are presented in arbitrary order *) val iter : (elt -> unit) -> t -> unit val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a end exception EmptyHeap (** {6 Functional implementation. } *) module Functional(X: Ordered) : S with type elt=X.t rocq-9.2.0/clib/iStream.ml000066400000000000000000000042411516144147600153470ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Nil | Cons (x,s) -> app_node (peek (f x)) (concat_map f s) and concat_map f l = lazy (concat_map_node f (peek l)) rocq-9.2.0/clib/iStream.mli000066400000000000000000000044371516144147600155270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t -> 'a t (** Append an element in front of a stream. *) val thunk : (unit -> 'a node) -> 'a t (** Internalize the laziness of a stream. *) (** {6 Destructors} *) val is_empty : 'a t -> bool (** Whethere a stream is empty. *) val peek : 'a t -> 'a node (** Return the head and the tail of a stream, if any. *) (** {6 Standard operations} All stream-returning functions are lazy. The other ones are eager. *) val app : 'a t -> 'a t -> 'a t (** Append two streams. Not tail-rec. *) val map : ('a -> 'b) -> 'a t -> 'b t (** Mapping of streams. Not tail-rec. *) val iter : ('a -> unit) -> 'a t -> unit (** Iteration over streams. *) val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a (** Fold over streams. *) val concat : 'a t t -> 'a t (** Appends recursively a stream of streams. *) val map_filter : ('a -> 'b option) -> 'a t -> 'b t (** Mixing [map] and [filter]. Not tail-rec. *) val concat_map : ('a -> 'b t) -> 'a t -> 'b t (** [concat_map f l] is the same as [concat (map f l)]. *) (** {6 Conversions} *) val of_list : 'a list -> 'a t (** Convert a list into a stream. *) val to_list : 'a t -> 'a list (** Convert a stream into a list. *) (** {6 Other}*) val force : 'a t -> 'a t (** Forces the whole stream. *) rocq-9.2.0/clib/int.ml000066400000000000000000000153611516144147600145420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int -> bool = "%eq" external compare : int -> int -> int = "caml_int_compare" let hash i = i land 0x3FFFFFFF module Self = struct type t = int let compare = compare end module Set = Set.Make(Self) module Map = struct include CMap.Make(Self) type 'a map = 'a CMap.Make(Self).t type 'a _map = | MEmpty | MNode of {l:'a map; v:int; d:'a; r:'a map; h:int} let map_prj : 'a map -> 'a _map = Obj.magic let map_inj : 'a _map -> 'a map = Obj.magic let rec find i s = match map_prj s with | MEmpty -> raise Not_found | MNode {l; v; d; r; h} -> if i < v then find i l else if i = v then d else find i r let rec get i s = match map_prj s with | MEmpty -> assert false | MNode {l; v; d; r; h} -> if i < v then get i l else if i = v then d else get i r let rec find_opt i s = match map_prj s with | MEmpty -> None | MNode {l; v; d; r; h} -> if i < v then find_opt i l else if i = v then Some d else find_opt i r let rec set k v (s : 'a map) : 'a map = match map_prj s with | MEmpty -> raise Not_found | MNode {l; v=k'; d=v'; r; h} -> if k < k' then let l' = set k v l in if l == l' then s else map_inj (MNode {l=l'; v=k'; d=v'; r; h}) else if k = k' then if v' == v then s else map_inj (MNode {l; v=k'; d=v; r; h}) else let r' = set k v r in if r == r' then s else map_inj (MNode {l; v=k'; d=v'; r=r'; h}) let rec modify k f (s : 'a map) : 'a map = match map_prj s with | MEmpty -> raise Not_found | MNode {l; v; d; r; h} -> if k < v then let l' = modify k f l in if l == l' then s else map_inj (MNode {l=l'; v; d; r; h}) else if k = v then let d' = f v d in if d' == d then s else map_inj (MNode {l; v; d=d'; r; h}) else let r' = modify k f r in if r == r' then s else map_inj (MNode {l; v; d; r=r'; h}) end module List = struct let mem = List.memq let assoc = List.assq let mem_assoc = List.mem_assq let remove_assoc = List.remove_assq end let min (i : int) j = if i < j then i else j (** Utility function *) let rec next from upto = if from < upto then next (2 * from + 1) upto else from module PArray = struct type 'a t = 'a data ref and 'a data = | Root of 'a option array | DSet of int * 'a option * 'a t let empty n = ref (Root (Array.make n None)) let rec rerootk t k = match !t with | Root _ -> k () | DSet (i, v, t') -> let next () = match !t' with | Root a as n -> let v' = Array.unsafe_get a i in let () = Array.unsafe_set a i v in let () = t := n in let () = t' := DSet (i, v', t) in k () | DSet _ -> assert false in rerootk t' next let reroot t = rerootk t (fun () -> ()) let get t i = let () = assert (0 <= i) in match !t with | Root a -> if Array.length a <= i then None else Array.unsafe_get a i | DSet _ -> let () = reroot t in match !t with | Root a -> if Array.length a <= i then None else Array.unsafe_get a i | DSet _ -> assert false let set t i v = let () = assert (0 <= i) in let () = reroot t in match !t with | DSet _ -> assert false | Root a as n -> let len = Array.length a in if i < len then let old = Array.unsafe_get a i in if old == v then t else let () = Array.unsafe_set a i v in let res = ref n in let () = t := DSet (i, old, res) in res else match v with | None -> t (* Nothing to do! *) | Some _ -> (* we must resize *) let nlen = next len (succ i) in let nlen = min nlen Sys.max_array_length in let () = assert (i < nlen) in let a' = Array.make nlen None in let () = Array.blit a 0 a' 0 len in let () = Array.unsafe_set a' i v in let res = ref (Root a') in let () = t := DSet (i, None, res) in res end module PMap = struct type key = int (** Invariants: 1. an empty map is always [Empty]. 2. the set of the [Map] constructor remembers the present keys. *) type 'a t = Empty | Map of Set.t * 'a PArray.t let empty = Empty let is_empty = function | Empty -> true | Map _ -> false let singleton k x = let len = next 19 (k + 1) in let len = min Sys.max_array_length len in let v = PArray.empty len in let v = PArray.set v k (Some x) in let s = Set.singleton k in Map (s, v) let add k x = function | Empty -> singleton k x | Map (s, v) -> let s = match PArray.get v k with | None -> Set.add k s | Some _ -> s in let v = PArray.set v k (Some x) in Map (s, v) let remove k = function | Empty -> Empty | Map (s, v) -> let s = Set.remove k s in if Set.is_empty s then Empty else let v = PArray.set v k None in Map (s, v) let mem k = function | Empty -> false | Map (_, v) -> match PArray.get v k with | None -> false | Some _ -> true let find k = function | Empty -> raise Not_found | Map (_, v) -> match PArray.get v k with | None -> raise Not_found | Some x -> x let iter f = function | Empty -> () | Map (s, v) -> let iter k = match PArray.get v k with | None -> () | Some x -> f k x in Set.iter iter s let fold f m accu = match m with | Empty -> accu | Map (s, v) -> let fold k accu = match PArray.get v k with | None -> accu | Some x -> f k x accu in Set.fold fold s accu let exists f m = match m with | Empty -> false | Map (s, v) -> let exists k = match PArray.get v k with | None -> false | Some x -> f k x in Set.exists exists s let for_all f m = match m with | Empty -> true | Map (s, v) -> let for_all k = match PArray.get v k with | None -> true | Some x -> f k x in Set.for_all for_all s let cast = function | Empty -> Map.empty | Map (s, v) -> let bind k = match PArray.get v k with | None -> assert false | Some x -> x in Map.bind bind s let domain = function | Empty -> Set.empty | Map (s, _) -> s end rocq-9.2.0/clib/int.mli000066400000000000000000000065141516144147600147130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool = "%eq" external compare : t -> t -> int = "caml_int_compare" val hash : t -> int module Set : Set.S with type elt = t module Map : CMap.ExtS with type key = t and module Set := Set module List : sig val mem : int -> int list -> bool val assoc : int -> (int * 'a) list -> 'a val mem_assoc : int -> (int * 'a) list -> bool val remove_assoc : int -> (int * 'a) list -> (int * 'a) list end module PArray : sig type 'a t (** Persistent, auto-resizable arrays. The [get] and [set] functions never fail whenever the index is between [0] and [Sys.max_array_length - 1]. *) val empty : int -> 'a t (** The empty array, with a given starting size. *) val get : 'a t -> int -> 'a option (** Get a value at the given index. Returns [None] if undefined. *) val set : 'a t -> int -> 'a option -> 'a t (** Set/unset a value at the given index. *) end module PMap : sig type key = int type 'a t val empty : 'a t val is_empty : 'a t -> bool val mem : key -> 'a t -> bool val add : key -> 'a -> 'a t -> 'a t val singleton : key -> 'a -> 'a t val remove : key -> 'a t -> 'a t (* val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t *) (* val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int *) (* val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool *) val iter : (key -> 'a -> unit) -> 'a t -> unit val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val for_all : (key -> 'a -> bool) -> 'a t -> bool val exists : (key -> 'a -> bool) -> 'a t -> bool (* val filter : (key -> 'a -> bool) -> 'a t -> 'a t *) (* val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t *) (* val cardinal : 'a t -> int *) (* val bindings : 'a t -> (key * 'a) list *) (* val min_binding : 'a t -> key * 'a *) (* val max_binding : 'a t -> key * 'a *) (* val choose : 'a t -> key * 'a *) (* val split : key -> 'a t -> 'a t * 'a option * 'a t *) val find : key -> 'a t -> 'a (* val map : ('a -> 'b) -> 'a t -> 'b t *) (* val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t *) val domain : 'a t -> Set.t val cast : 'a t -> 'a Map.t end (** This is a (partial) implementation of a [Map] interface on integers, except that it internally uses persistent arrays. This ensures O(1) accesses in non-backtracking cases. It is thus better suited for zero-starting, contiguous keys, or otherwise a lot of space will be empty. To keep track of the present keys, a binary tree is also used, so that adding a key is still logarithmic. It is therefore essential that most of the operations are accesses and not add/removes. *) rocq-9.2.0/clib/memprof_coq.memprof.ml000066400000000000000000000034141516144147600177170ustar00rootroot00000000000000(* From memprof_limits, see also https://gitlab.com/gadmm/memprof-limits/-/issues/7 *) let is_interrupted () = Memprof_limits.is_interrupted () [@@inline] module Resource_bind = Memprof_limits.Resource_bind (* Not exported by memprof limits :( *) (* module Thread_map = Memprof_limits.Thread_map *) (* module Mutex_aux = Memprof_limits.Mutex_aux *) (* We do our own Mutex_aux for OCaml 5.x *) module Mutex_aux = Mutex_aux module Thread_map_core = struct open Resource_bind module IMap = Map.Make ( struct type t = int let compare = Stdlib.compare end) type 'a t = { mutex : Mutex.t ; mutable map : 'a IMap.t } let create () = { mutex = Mutex.create () ; map = IMap.empty } let current_thread () = Thread.id (Thread.self ()) let get s = (* Concurrent threads do not alter the value for the current thread, so we do not need a lock. *) IMap.find_opt (current_thread ()) s.map (* For set and clear we need a lock *) let set s v = let& () = Mutex_aux.with_lock s.mutex in let new_map = match v with | None -> IMap.remove (current_thread ()) s.map | Some v -> IMap.add (current_thread ()) v s.map in s.map <- new_map let _clear s = let& () = Mutex_aux.with_lock s.mutex in s.map <- IMap.empty end module Masking = Memprof_limits.Masking module Thread_map = struct include Thread_map_core let with_value tls ~value ~scope = let old_value = get tls in (* FIXME: needs proper masking here as there is a race between resources and asynchronous exceptions. For now, it is exception-safe only for exceptions arising from Memprof_callbacks. *) Masking.with_resource ~acquire:(fun () -> set tls (Some value)) () ~scope ~release:(fun () -> set tls old_value) end rocq-9.2.0/clib/memprof_coq.mli000066400000000000000000000023151516144147600164230ustar00rootroot00000000000000(* From memprof-limits *) val is_interrupted : unit -> bool module Masking : sig val with_resource : acquire:('a -> 'b) -> 'a -> scope:('b -> 'c) -> release:('b -> unit) -> 'c end module Thread_map : sig (** An async-safe, scoped thread-local store *) type 'a t val create : unit -> 'a t (** Create an empty map *) val with_value : 'a t -> value:'a -> scope:(unit -> 'b) -> 'b (** Associate [~value] to the current thread for the duration of a scope. It can be nested: the previous association is restored on exit. *) val get : 'a t -> 'a option (** Get the value currently associated with the current thread. *) end module Resource_bind : sig (** Open {!Memprof_limits.Resource_bind} to enable the [let&] binder for resources. *) val ( let& ) : (scope:('a -> 'b) -> 'b) -> ('a -> 'b) -> 'b (** RAII-style notation for resources cleaned-up at the end of scope. Example: {[open Memprof_limits.Resource_bind let with_my_resource x = Memprof_limits.Masking.with_resource ~acquire x ~release let f x = let& resource = with_my_resource x in …]} *) end module Mutex_aux : sig val with_lock : Mutex.t -> scope:(unit -> 'a) -> 'a end rocq-9.2.0/clib/memprof_coq.std.ml000066400000000000000000000034511516144147600170450ustar00rootroot00000000000000let is_interrupted _ = false [@@inline] module Resource_bind = struct let ( let& ) f scope = f ~scope end (* We do our own Mutex_aux for OCaml 5.x *) module Mutex_aux = Mutex_aux module Thread_map_core = struct open Resource_bind module IMap = Map.Make ( struct type t = int let compare = Stdlib.compare end) type 'a t = { mutex : Mutex.t ; mutable map : 'a IMap.t } let create () = { mutex = Mutex.create () ; map = IMap.empty } let current_thread () = Thread.id (Thread.self ()) let get s = (* Concurrent threads do not alter the value for the current thread, so we do not need a lock. *) IMap.find_opt (current_thread ()) s.map (* For set and clear we need a lock *) let set s v = let& () = Mutex_aux.with_lock s.mutex in let new_map = match v with | None -> IMap.remove (current_thread ()) s.map | Some v -> IMap.add (current_thread ()) v s.map in s.map <- new_map let _clear s = let& () = Mutex_aux.with_lock s.mutex in s.map <- IMap.empty end module Masking = struct (* There's no mechanism to block OCaml's async exceptions, so without memprof there is nothing interesting to do. *) let with_resource ~acquire arg ~scope ~(release : _ -> unit) = let r = acquire arg in Fun.protect ~finally:(fun () -> release r) (fun () -> scope r) end module Thread_map = struct include Thread_map_core let with_value tls ~value ~scope = let old_value = get tls in (* FIXME: needs proper masking here as there is a race between resources and asynchronous exceptions. For now, it is exception-safe only for exceptions arising from Memprof_callbacks. *) Masking.with_resource ~acquire:(fun () -> set tls (Some value)) () ~scope ~release:(fun () -> set tls old_value) end rocq-9.2.0/clib/monad.ml000066400000000000000000000117221516144147600150430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t val (>>) : unit t -> 'a t -> 'a t val map : ('a -> 'b) -> 'a t -> 'b t (** The monadic laws must hold: - [(x>>=f)>>=g] = [x>>=fun x' -> (f x'>>=g)] - [return a >>= f] = [f a] - [x>>=return] = [x] As well as the following identities: - [x >> y] = [x >>= fun () -> y] - [map f x] = [x >>= fun x' -> f x'] *) end module type ListS = sig type 'a t (** [List.map f l] maps [f] on the elements of [l] in left to right order. *) val map : ('a -> 'b t) -> 'a list -> 'b list t (** [List.map f l] maps [f] on the elements of [l] in right to left order. *) val map_right : ('a -> 'b t) -> 'a list -> 'b list t (** Like the regular [List.fold_right]. The monadic effects are threaded right to left. Note: many monads behave poorly with right-to-left order. For instance a failure monad would still have to traverse the whole list in order to fail and failure needs to be propagated through the rest of the list in binds which are now spurious. It is also the worst case for substitution monads (aka free monads), exposing the quadratic behaviour.*) val fold_right : ('a -> 'b -> 'b t) -> 'a list -> 'b -> 'b t (** Like the regular [List.fold_left]. The monadic effects are threaded left to right. It is tail-recursive if the [(>>=)] operator calls its second argument in a tail position. *) val fold_left : ('a -> 'b -> 'a t) -> 'a -> 'b list -> 'a t (** Like the regular [List.iter]. The monadic effects are threaded left to right. It is tail-recurisve if the [>>] operator calls its second argument in a tail position. *) val iter : ('a -> unit t) -> 'a list -> unit t (** Like the regular {!CList.map_filter}. The monadic effects are threaded left*) val map_filter : ('a -> 'b option t) -> 'a list -> 'b list t (** {6 Two-list iterators} *) (** [fold_left2 r f s l1 l2] behaves like {!fold_left} but acts simultaneously on two lists. Runs [r] (presumably an exception-raising computation) if both lists do not have the same length. *) val fold_left2 : 'a t -> ('a -> 'b -> 'c -> 'a t) -> 'a -> 'b list -> 'c list -> 'a t end module type S = sig include Def (** List combinators *) module List : ListS with type 'a t := 'a t end module Make (M:Def) : S with type +'a t = 'a M.t = struct include M module List = struct (* The combinators are loop-unrolled to spare a some monadic binds (it is a common optimisation to treat the last of a list of bind specially) and hopefully gain some efficiency using fewer jump. *) let rec map f = function | [] -> return [] | [a] -> M.map (fun a' -> [a']) (f a) | a::b::l -> f a >>= fun a' -> f b >>= fun b' -> M.map (fun l' -> a'::b'::l') (map f l) let rec map_right f = function | [] -> return [] | [a] -> M.map (fun a' -> [a']) (f a) | a::b::l -> map_right f l >>= fun l' -> f b >>= fun b' -> M.map (fun a' -> a'::b'::l') (f a) let rec fold_right f l x = match l with | [] -> return x | [a] -> f a x | a::b::l -> fold_right f l x >>= fun acc -> f b acc >>= fun acc -> f a acc let rec fold_left f x = function | [] -> return x | [a] -> f x a | a::b::l -> f x a >>= fun x' -> f x' b >>= fun x'' -> fold_left f x'' l let rec iter f = function | [] -> return () | [a] -> f a | a::b::l -> f a >> f b >> iter f l let rec map_filter f = function | [] -> return [] | a::l -> f a >>= function | None -> map_filter f l | Some b -> map_filter f l >>= fun filtered -> return (b::filtered) let rec fold_left2 r f x l1 l2 = match l1,l2 with | [] , [] -> return x | [a] , [b] -> f x a b | a1::a2::l1 , b1::b2::l2 -> f x a1 b1 >>= fun x' -> f x' a2 b2 >>= fun x'' -> fold_left2 r f x'' l1 l2 | _ , _ -> r end end rocq-9.2.0/clib/monad.mli000066400000000000000000000064261516144147600152210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t val (>>=) : 'a t -> ('a -> 'b t) -> 'b t val (>>) : unit t -> 'a t -> 'a t val map : ('a -> 'b) -> 'a t -> 'b t (** The monadic laws must hold: - [(x>>=f)>>=g] = [x>>=fun x' -> (f x'>>=g)] - [return a >>= f] = [f a] - [x>>=return] = [x] As well as the following identities: - [x >> y] = [x >>= fun () -> y] - [map f x] = [x >>= fun x' -> f x'] *) end (** List combinators *) module type ListS = sig type 'a t (** [List.map f l] maps [f] on the elements of [l] in left to right order. *) val map : ('a -> 'b t) -> 'a list -> 'b list t (** [List.map f l] maps [f] on the elements of [l] in right to left order. *) val map_right : ('a -> 'b t) -> 'a list -> 'b list t (** Like the regular [List.fold_right]. The monadic effects are threaded right to left. Note: many monads behave poorly with right-to-left order. For instance a failure monad would still have to traverse the whole list in order to fail and failure needs to be propagated through the rest of the list in binds which are now spurious. It is also the worst case for substitution monads (aka free monads), exposing the quadratic behaviour.*) val fold_right : ('a -> 'b -> 'b t) -> 'a list -> 'b -> 'b t (** Like the regular [List.fold_left]. The monadic effects are threaded left to right. It is tail-recursive if the [(>>=)] operator calls its second argument in a tail position. *) val fold_left : ('a -> 'b -> 'a t) -> 'a -> 'b list -> 'a t (** Like the regular [List.iter]. The monadic effects are threaded left to right. It is tail-recurisve if the [>>] operator calls its second argument in a tail position. *) val iter : ('a -> unit t) -> 'a list -> unit t (** Like the regular {!CList.map_filter}. The monadic effects are threaded left to right. *) val map_filter : ('a -> 'b option t) -> 'a list -> 'b list t (** {6 Two-list iterators} *) (** [fold_left2 r f s l1 l2] behaves like {!fold_left} but acts simultaneously on two lists. Runs [r] (presumably an exception-raising computation) if both lists do not have the same length. *) val fold_left2 : 'a t -> ('a -> 'b -> 'c -> 'a t) -> 'a -> 'b list -> 'c list -> 'a t end module type S = sig include Def module List : ListS with type 'a t := 'a t end (** Expands the monadic definition to extra combinators. *) module Make (M:Def) : S with type +'a t = 'a M.t rocq-9.2.0/clib/mutex_aux.mli000066400000000000000000000000641516144147600161320ustar00rootroot00000000000000val with_lock : Mutex.t -> scope:(unit -> 'a) -> 'a rocq-9.2.0/clib/mutex_aux_4.x.ml000066400000000000000000000011401516144147600164460ustar00rootroot00000000000000external unlock: Mutex.t -> unit = "caml_mutex_unlock" (* Critical sections : - Mutex.lock does not poll on leaving the blocking section since 4.12. - Never inline, to avoid theoretically-possible reorderings with flambda. - Inline the call to Mutex.unlock to avoid polling in bytecode. (workaround to the lack of masking) *) let[@inline never] with_lock m ~scope = let () = Mutex.lock m (* BEGIN ATOMIC *) in match (* END ATOMIC *) scope () with | (* BEGIN ATOMIC *) x -> unlock m ; (* END ATOMIC *) x | (* BEGIN ATOMIC *) exception e -> unlock m ; (* END ATOMIC *) raise e rocq-9.2.0/clib/mutex_aux_5.0.ml000066400000000000000000000012221516144147600163400ustar00rootroot00000000000000(* backport of Mutex.protect from OCaml 5.1 *) external unlock: Mutex.t -> unit = "caml_ml_mutex_unlock" (* Critical sections : - Mutex.lock does not poll on leaving the blocking section since 4.12. - Never inline, to avoid theoretically-possible reorderings with flambda. - Inline the call to Mutex.unlock to avoid polling in bytecode. (workaround to the lack of masking) *) let[@inline never] with_lock m ~scope = let () = Mutex.lock m (* BEGIN ATOMIC *) in match (* END ATOMIC *) scope () with | (* BEGIN ATOMIC *) x -> unlock m ; (* END ATOMIC *) x | (* BEGIN ATOMIC *) exception e -> unlock m ; (* END ATOMIC *) raise e rocq-9.2.0/clib/mutex_aux_5.x.ml000066400000000000000000000000571516144147600164550ustar00rootroot00000000000000let with_lock m ~scope = Mutex.protect m scope rocq-9.2.0/clib/neList.ml000066400000000000000000000023711516144147600152030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* None | y::tl -> Some (y,tl) let singleton x = x,[] let iter f (x,tl) = f x; List.iter f tl let map f (x,tl) = let x = f x in let tl = List.map f tl in x, tl let map2 f (x,tl) (x',tl') = let x = f x x' in let tl = List.map2 f tl tl' in x, tl let map_head f (x,tl) = f x, tl let push x = function | None -> x, [] | Some (y,tl) -> x, y::tl let to_list (x,tl) = x::tl let of_list = function | [] -> invalid_arg "NeList.of_list" | x::tl -> x,tl let repr x = x let of_repr x = x rocq-9.2.0/clib/neList.mli000066400000000000000000000022231516144147600153500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a val tail : 'a t -> 'a t option val singleton : 'a -> 'a t val iter : ('a -> unit) -> 'a t -> unit val map : ('a -> 'b) -> 'a t -> 'b t val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t val map_head : ('a -> 'a) -> 'a t -> 'a t val push : 'a -> 'a t option -> 'a t val to_list : 'a t -> 'a list (** May raise Invalid_argument *) val of_list : 'a list -> 'a t val repr : 'a t -> 'a * 'a list val of_repr : 'a * 'a list -> 'a t rocq-9.2.0/clib/option.ml000066400000000000000000000116001516144147600152500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* false | _ -> true let is_empty = function | None -> true | Some _ -> false (** Lifting equality onto option types. *) let equal f x y = match x, y with | None, None -> true | Some x, Some y -> f x y | _, _ -> false let compare f x y = match x, y with | None, None -> 0 | Some x, Some y -> f x y | None, Some _ -> -1 | Some _, None -> 1 let hash f = function | None -> 0 | Some x -> f x (** [get x] returns [y] where [x] is [Some y] and asserts false otherwise. *) let get = function | Some y -> y | None -> assert false (** [make x] returns [Some x]. *) let make x = Some x (** [bind x f] is [f y] if [x] is [Some y] and [None] otherwise *) let bind x f = match x with Some y -> f y | None -> None let filter f x = bind x (fun v -> if f v then x else None) (** [init b x] returns [Some x] if [b] is [true] and [None] otherwise. *) let init b x = if b then Some x else None (** [flatten x] is [Some y] if [x] is [Some (Some y)] and [None] otherwise. *) let flatten = function | Some (Some y) -> Some y | _ -> None (** [append x y] is the first element of the concatenation of [x] and [y] seen as lists. *) let append o1 o2 = match o1 with | Some _ -> o1 | None -> o2 (** {6 "Iterators"} ***) (** [iter f x] executes [f y] if [x] equals [Some y]. It does nothing otherwise. *) let iter f = function | Some y -> f y | _ -> () exception Heterogeneous (** [iter2 f x y] executes [f z w] if [x] equals [Some z] and [y] equals [Some w]. It does nothing if both [x] and [y] are [None]. And raises [Heterogeneous] otherwise. *) let iter2 f x y = match x,y with | Some z, Some w -> f z w | None,None -> () | _,_ -> raise Heterogeneous (** [map f x] is [None] if [x] is [None] and [Some (f y)] if [x] is [Some y]. *) let map f = function | Some y -> Some (f y) | _ -> None (** [fold_left f a x] is [f a y] if [x] is [Some y], and [a] otherwise. *) let fold_left f a = function | Some y -> f a y | _ -> a (** [fold_left2 f a x y] is [f z w] if [x] is [Some z] and [y] is [Some w]. It is [a] if both [x] and [y] are [None]. Otherwise it raises [Heterogeneous]. *) let fold_left2 f a x y = match x,y with | Some x, Some y -> f a x y | None, None -> a | _ -> raise Heterogeneous (** [fold_right f x a] is [f y a] if [x] is [Some y], and [a] otherwise. *) let fold_right f x a = match x with | Some y -> f y a | _ -> a (** [fold_left_map f a x] is [a, f y] if [x] is [Some y], and [a] otherwise. *) let fold_left_map f a x = match x with | Some y -> let a, z = f a y in a, Some z | _ -> a, None let fold_right_map f x a = match x with | Some y -> let z, a = f y a in Some z, a | _ -> None, a (** [cata f a x] is [a] if [x] is [None] and [f y] if [x] is [Some y]. *) let cata f a = function | Some c -> f c | None -> a (** {6 More Specific operations} ***) (** [default a x] is [y] if [x] is [Some y] and [a] otherwise. *) let default a = function | Some y -> y | _ -> a (** {6 Smart operations} *) module Smart = struct (** [Smart.map f x] does the same as [map f x] except that it tries to share some memory. *) let map f = function | Some y as x -> let y' = f y in if y' == y then x else Some y' | _ -> None end (** {6 Operations with Lists} *) module List = struct (** [List.cons x l] equals [y::l] if [x] is [Some y] and [l] otherwise. *) let cons x l = match x with | Some y -> y::l | _ -> l (** [List.flatten l] is the list of all the [y]s such that [l] contains [Some y] (in the same order). *) let rec flatten = function | x::l -> cons x (flatten l) | [] -> [] let map f l = let rec aux f l = match l with | [] -> [] | x :: l -> match f x with | None -> raise_notrace Exit | Some y -> y :: aux f l in try Some (aux f l) with Exit -> None end rocq-9.2.0/clib/option.mli000066400000000000000000000115571516144147600154340ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool (** Negation of [has_some] *) val is_empty : 'a option -> bool (** [equal f x y] lifts the equality predicate [f] to option types. That is, if both [x] and [y] are [None] then it returns [true], if they are both [Some _] then [f] is called. Otherwise it returns [false]. *) val equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool (** Same as [equal], but with comparison. *) val compare : ('a -> 'a -> int) -> 'a option -> 'a option -> int (** Lift a hash to option types. *) val hash : ('a -> int) -> 'a option -> int (** [get x] returns [y] where [x] is [Some y], and asserts false otherwise. *) val get : 'a option -> 'a (** [make x] returns [Some x]. *) val make : 'a -> 'a option (** [bind x f] is [f y] if [x] is [Some y] and [None] otherwise *) val bind : 'a option -> ('a -> 'b option) -> 'b option (** [filter f x] is [x] if [x] [Some y] and [f y] is true, [None] otherwise *) val filter : ('a -> bool) -> 'a option -> 'a option (** [init b x] returns [Some x] if [b] is [true] and [None] otherwise. *) val init : bool -> 'a -> 'a option (** [flatten x] is [Some y] if [x] is [Some (Some y)] and [None] otherwise. *) val flatten : 'a option option -> 'a option (** [append x y] is the first element of the concatenation of [x] and [y] seen as lists. In other words, [append (Some a) y] is [Some a], [append None (Some b)] is [Some b], and [append None None] is [None]. *) val append : 'a option -> 'a option -> 'a option (** {6 "Iterators"} *) (** [iter f x] executes [f y] if [x] equals [Some y]. It does nothing otherwise. *) val iter : ('a -> unit) -> 'a option -> unit exception Heterogeneous (** [iter2 f x y] executes [f z w] if [x] equals [Some z] and [y] equals [Some w]. It does nothing if both [x] and [y] are [None]. @raise Heterogeneous otherwise. *) val iter2 : ('a -> 'b -> unit) -> 'a option -> 'b option -> unit (** [map f x] is [None] if [x] is [None] and [Some (f y)] if [x] is [Some y]. *) val map : ('a -> 'b) -> 'a option -> 'b option (** [fold_left f a x] is [f a y] if [x] is [Some y], and [a] otherwise. *) val fold_left : ('b -> 'a -> 'b) -> 'b -> 'a option -> 'b (** [fold_left2 f a x y] is [f z w] if [x] is [Some z] and [y] is [Some w]. It is [a] if both [x] and [y] are [None]. @raise Heterogeneous otherwise. *) val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b option -> 'c option -> 'a (** [fold_right f x a] is [f y a] if [x] is [Some y], and [a] otherwise. *) val fold_right : ('a -> 'b -> 'b) -> 'a option -> 'b -> 'b (** [fold_left_map f a x] is [a, f y] if [x] is [Some y], and [a] otherwise. *) val fold_left_map : ('a -> 'b -> 'a * 'c) -> 'a -> 'b option -> 'a * 'c option (** Same as [fold_left_map] on the right *) val fold_right_map : ('b -> 'a -> 'c * 'a) -> 'b option -> 'a -> 'c option * 'a (** [cata f e x] is [e] if [x] is [None] and [f a] if [x] is [Some a] *) val cata : ('a -> 'b) -> 'b -> 'a option -> 'b (** {6 More Specific Operations} *) (** [default a x] is [y] if [x] is [Some y] and [a] otherwise. *) val default : 'a -> 'a option -> 'a (** {6 Smart operations} *) module Smart : sig (** [Smart.map f x] does the same as [map f x] except that it tries to share some memory. *) val map : ('a -> 'a) -> 'a option -> 'a option end (** {6 Operations with Lists} *) module List : sig (** [List.cons x l] equals [y::l] if [x] is [Some y] and [l] otherwise. *) val cons : 'a option -> 'a list -> 'a list (** [List.flatten l] is the list of all the [y]s such that [l] contains [Some y] (in the same order). *) val flatten : 'a option list -> 'a list (** [List.map f [a1;...;an]] is the list [Some [b1;...;bn]] if for all i, there is a [bi] such that [f ai] is [Some bi]; it is [None] if, for at least one i, [f ai] is [None]. *) val map : ('a -> 'b option) -> 'a list -> 'b list option end rocq-9.2.0/clib/orderedType.ml000066400000000000000000000022101516144147600162230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module Pair (M:S) (N:S) = struct type t = M.t * N.t let compare (a,b) (a',b') = let i = M.compare a a' in if Int.equal i 0 then N.compare b b' else i end module UnorderedPair (M:S) = struct type t = M.t * M.t let reorder (a,b as p) = if M.compare a b <= 0 then p else (b,a) let compare p p' = let p = reorder p and p' = reorder p' in let module P = Pair(M)(M) in P.compare p p' end rocq-9.2.0/clib/orderedType.mli000066400000000000000000000015201516144147600163770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module Pair (M:S) (N:S) : S with type t = M.t * N.t module UnorderedPair (M:S) : S with type t = M.t * M.t rocq-9.2.0/clib/polyMap.ml000066400000000000000000000062111516144147600153630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* refl | _ -> None let make (type a) () : a onetag = (module struct type nonrec a = a type _ tag += T : a tag end) let tag_of_onetag (type a) (tag:a onetag) : a tag = let module T = (val tag) in T.T module type MapS = sig type t type _ value val empty : t val find : 'a tag -> t -> 'a value val add : 'a onetag -> 'a value -> t -> t val mem : 'a tag -> t -> bool val update : 'a onetag -> ('a value option -> 'a value option) -> t -> t val modify : 'a tag -> ('a value -> 'a value) -> t -> t type 'acc fold = { fold : 'a. 'a onetag -> 'a value -> 'acc -> 'acc } val fold : 'acc fold -> t -> 'acc -> 'acc end module Map (V:ValueS) = struct type v = V : 'a onetag * 'a V.t -> v let key t = Obj.Extension_constructor.(id (of_val t)) let onekey t = key (tag_of_onetag t) module M = Int.Map type t = v M.t let empty = M.empty let find (type a) (tag:a tag) m : a V.t = let V (tag', v) = M.find (key tag) m in let module T = (val tag') in match tag with | T.T -> v | _ -> assert false let add tag v m = M.add (onekey tag) (V (tag, v)) m let mem tag m = M.mem (key tag) m let update (type a) (tag:a onetag) (f:a V.t option -> a V.t option) m = M.update (key tag) (fun optv -> let optv : a V.t option = match optv with | None -> None | Some (V (tag', v)) -> let module T = (val tag) in match tag_of_onetag tag' with | T.T -> Some v | _ -> assert false in match f optv with | None -> None | Some v -> Some (V (tag,v))) m let modify (type a) (tag:a tag) (f:a V.t -> a V.t) m = M.modify (key tag) (fun _ (V (tag', v)) -> let module T = (val tag') in match tag with | T.T -> V (tag', f v) | _ -> assert false) m type 'acc fold = { fold : 'a. 'a onetag -> 'a V.t -> 'acc -> 'acc } let fold f m acc = M.fold (fun _ (V (tag,v)) acc -> f.fold tag v acc) m acc end end rocq-9.2.0/clib/polyMap.mli000066400000000000000000000036241516144147600155410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'b tag -> ('a,'b) CSig.eq option val make : unit -> 'a onetag val tag_of_onetag : 'a onetag -> 'a tag module type MapS = sig type t type _ value val empty : t val find : 'a tag -> t -> 'a value val add : 'a onetag -> 'a value -> t -> t val mem : 'a tag -> t -> bool val update : 'a onetag -> ('a value option -> 'a value option) -> t -> t val modify : 'a tag -> ('a value -> 'a value) -> t -> t type 'acc fold = { fold : 'a. 'a onetag -> 'a value -> 'acc -> 'acc } val fold : 'acc fold -> t -> 'acc -> 'acc end module Map(V:ValueS) : MapS with type 'a value := 'a V.t end rocq-9.2.0/clib/predicate.ml000066400000000000000000000073661516144147600157160ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int end module type S = sig type elt type t val empty: t val full: t val is_empty: t -> bool val is_full: t -> bool val mem: elt -> t -> bool val singleton: elt -> t val add: elt -> t -> t val remove: elt -> t -> t val union: t -> t -> t val inter: t -> t -> t val diff: t -> t -> t val complement: t -> t val equal: t -> t -> bool val subset: t -> t -> bool val elements: t -> bool * elt list val is_finite : t -> bool end module Make(Ord: OrderedType) = struct module EltSet = Set.Make(Ord) type elt = Ord.t (* (false, s) represents a set which is equal to the set s (true, s) represents a set which is equal to the complement of set s *) type t = bool * EltSet.t let is_finite (b,_) = not b let elements (b,s) = (b, EltSet.elements s) let empty = (false,EltSet.empty) let full = (true,EltSet.empty) (* assumes the set is infinite *) let is_empty (b,s) = not b && EltSet.is_empty s let is_full (b,s) = b && EltSet.is_empty s let mem x (b,s) = if b then not (EltSet.mem x s) else EltSet.mem x s let singleton x = (false,EltSet.singleton x) let add x (b,s) = if b then (b,EltSet.remove x s) else (b,EltSet.add x s) let remove x (b,s) = if b then (b,EltSet.add x s) else (b,EltSet.remove x s) let complement (b,s) = (not b, s) let union s1 s2 = match (s1,s2) with ((false,p1),(false,p2)) -> (false,EltSet.union p1 p2) | ((true,n1),(true,n2)) -> (true,EltSet.inter n1 n2) | ((false,p1),(true,n2)) -> (true,EltSet.diff n2 p1) | ((true,n1),(false,p2)) -> (true,EltSet.diff n1 p2) let inter s1 s2 = complement (union (complement s1) (complement s2)) let diff s1 s2 = inter s1 (complement s2) (* assumes the set is infinite *) let subset s1 s2 = match (s1,s2) with ((false,p1),(false,p2)) -> EltSet.subset p1 p2 | ((true,n1),(true,n2)) -> EltSet.subset n2 n1 | ((false,p1),(true,n2)) -> EltSet.is_empty (EltSet.inter p1 n2) | ((true,_),(false,_)) -> false (* assumes the set is infinite *) let equal (b1,s1) (b2,s2) = b1=b2 && EltSet.equal s1 s2 end rocq-9.2.0/clib/predicate.mli000066400000000000000000000052701516144147600160570ustar00rootroot00000000000000(** Infinite sets over a chosen [OrderedType]. All operations over sets are purely applicative (no side-effects). *) (** Input signature of the functor [Make]. *) module type OrderedType = sig type t (** The type of the elements in the set. The chosen [t] {b must be infinite}. *) val compare : t -> t -> int (** A total ordering function over the set elements. This is a two-argument function [f] such that: - [f e1 e2] is zero if the elements [e1] and [e2] are equal, - [f e1 e2] is strictly negative if [e1] is smaller than [e2], - and [f e1 e2] is strictly positive if [e1] is greater than [e2]. *) end module type S = sig type elt (** The type of the elements in the set. *) type t (** The type of sets. *) val empty: t (** The empty set. *) val full: t (** The set of all elements (of type [elm]). *) val is_empty: t -> bool (** Test whether a set is empty or not. *) val is_full: t -> bool (** Test whether a set contains the whole type or not. *) val mem: elt -> t -> bool (** [mem x s] tests whether [x] belongs to the set [s]. *) val singleton: elt -> t (** [singleton x] returns the one-element set containing only [x]. *) val add: elt -> t -> t (** [add x s] returns a set containing all elements of [s], plus [x]. If [x] was already in [s], then [s] is returned unchanged. *) val remove: elt -> t -> t (** [remove x s] returns a set containing all elements of [s], except [x]. If [x] was not in [s], then [s] is returned unchanged. *) val union: t -> t -> t (** Set union. *) val inter: t -> t -> t (** Set intersection. *) val diff: t -> t -> t (** Set difference. *) val complement: t -> t (** Set complement. *) val equal: t -> t -> bool (** [equal s1 s2] tests whether the sets [s1] and [s2] are equal, that is, contain equal elements. *) val subset: t -> t -> bool (** [subset s1 s2] tests whether the set [s1] is a subset of the set [s2]. *) val elements: t -> bool * elt list (** Gives a finite representation of the predicate: if the boolean is false, then the predicate is given in extension. if it is true, then the complement is given *) val is_finite : t -> bool (** [true] if the predicate can be given as a finite set (if [elt] is a finite type, we can have [is_finite x = false] yet [x] is finite, but we don't know how to list its elements) *) end (** The [Make] functor constructs an implementation for any [OrderedType]. *) module Make (Ord : OrderedType) : (S with type elt = Ord.t) rocq-9.2.0/clib/range.ml000066400000000000000000000051471516144147600150450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if Int.equal h1 h2 then Cons (1 + h1 + h2, Node (x, t1, t2), rem) else Cons (1, Leaf x, l) | _ -> Cons (1, Leaf x, l) let is_empty = function | Nil -> true | _ -> false let rec tree_get h t i = match t with | Leaf x -> if i = 0 then x else oob () | Node (x, t1, t2) -> if i = 0 then x else let h = h / 2 in if i <= h then tree_get h t1 (i - 1) else tree_get h t2 (i - h - 1) let rec get l i = match l with | Nil -> oob () | Cons (h, t, rem) -> if i < h then tree_get h t i else get rem (i - h) let length l = let rec length accu = function | Nil -> accu | Cons (h, _, l) -> length (h + accu) l in length 0 l let rec tree_map f = function | Leaf x -> Leaf (f x) | Node (x, t1, t2) -> Node (f x, tree_map f t1, tree_map f t2) let rec map f = function | Nil -> Nil | Cons (h, t, l) -> Cons (h, tree_map f t, map f l) let rec tree_fold_left f accu = function | Leaf x -> f accu x | Node (x, t1, t2) -> tree_fold_left f (tree_fold_left f (f accu x) t1) t2 let rec fold_left f accu = function | Nil -> accu | Cons (_, t, l) -> fold_left f (tree_fold_left f accu t) l let rec tree_fold_right f t accu = match t with | Leaf x -> f x accu | Node (x, t1, t2) -> f x (tree_fold_right f t1 (tree_fold_right f t2 accu)) let rec fold_right f l accu = match l with | Nil -> accu | Cons (_, t, l) -> tree_fold_right f t (fold_right f l accu) let hd = function | Nil -> failwith "hd" | Cons (_, Leaf x, _) -> x | Cons (_, Node (x, _, _), _) -> x let tl = function | Nil -> failwith "tl" | Cons (_, Leaf _, l) -> l | Cons (h, Node (_, t1, t2), l) -> let h = h / 2 in Cons (h, t1, Cons (h, t2, l)) let rec skipn n l = if n = 0 then l else if is_empty l then failwith "List.skipn" else skipn (pred n) (tl l) rocq-9.2.0/clib/range.mli000066400000000000000000000024321516144147600152100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t -> 'a t (** {5 List operations} *) val is_empty : 'a t -> bool val length : 'a t -> int val map : ('a -> 'b) -> 'a t -> 'b t val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b val hd : 'a t -> 'a val tl : 'a t -> 'a t val skipn : int -> 'a t -> 'a t (** {5 Indexing operations} *) val get : 'a t -> int -> 'a rocq-9.2.0/clib/sList.ml000066400000000000000000000065621516144147600150510ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 *) let empty = Nil let cons x l = Cons (x, l) let defaultn n l = if Int.equal n 0 then l else match l with | Nil | Cons _ -> Default (n, l) | Default (m, l) -> Default (n + m, l) let default l = match l with | Nil | Cons _ -> Default (1, l) | Default (m, l) -> Default (m + 1, l) let cons_opt o l = match o with | None -> default l | Some x -> cons x l let is_empty = function | Nil -> true | Cons _ | Default _ -> false let is_default = function | Nil -> true | Default (_, Nil) -> true | Cons _ | Default _ -> false let view = function | Nil -> None | Cons (x, l) -> Some (Some x, l) | Default (1, l) -> Some (None, l) | Default (n, l) -> Some (None, Default (n - 1, l)) let rec to_list l = match l with | Nil -> [] | Cons (x, l) -> Some x :: to_list l | Default (n, l) -> let l = to_list l in let rec iterate n l = if n <= 0 then l else iterate (n - 1) (None :: l) in iterate n l let of_full_list l = List.fold_right cons l empty let equal eq l1 l2 = let eq o1 o2 = match o1, o2 with | None, None -> true | Some x1, Some x2 -> eq x1 x2 | Some _, None | None, Some _ -> false in CList.for_all2eq eq (to_list l1) (to_list l2) let compare cmp l1 l2 = CList.compare (Option.compare cmp) (to_list l1) (to_list l2) let length l = let rec length n = function | Nil -> n | Cons (_, l) -> length (n + 1) l | Default (k, l) -> length (k + n) l in length 0 l module Skip = struct let rec iter f = function | Nil -> () | Cons (x, l) -> let () = f x in iter f l | Default (_, l) -> iter f l let rec map f = function | Nil -> Nil | Cons (x, l) -> Cons (f x, map f l) | Default (n, l) -> Default (n, map f l) let rec fold f accu = function | Nil -> accu | Cons (x, l) -> fold f (f accu x) l | Default (_, l) -> fold f accu l let rec for_all f l = match l with | Nil -> true | Cons (x, l) -> f x && for_all f l | Default (_, l) -> for_all f l let rec exists f l = match l with | Nil -> false | Cons (x, l) -> f x || exists f l | Default (_, l) -> exists f l end module Smart = struct let rec map f l = match l with | Nil -> empty | Cons (x, r) -> let x' = f x in let r' = map f r in if x' == x && r' == r then l else cons x' r' | Default (n, r) -> let r' = map f r in if r' == r then l else Default (n, r') let rec fold_left_map f accu l0 = match l0 with | Nil -> accu, empty | Cons (x, l) -> let accu, x' = f accu x in let accu, l' = fold_left_map f accu l in let r = if x' == x && l' == l then l0 else Cons (x', l') in accu, r | Default (n, l) -> let accu, l' = fold_left_map f accu l in let r = if l' == l then l0 else Default (n, l') in accu, r end rocq-9.2.0/clib/sList.mli000066400000000000000000000041351516144147600152140ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t -> 'a t (** Isomorphic to [Some x :: l]. *) val default : 'a t -> 'a t (** Isomorphic to [None :: l]. *) val cons_opt : 'a option -> 'a t -> 'a t (** {!cons} if [Some], {!default} otherwise *) val defaultn : int -> 'a t -> 'a t (** Iterated variant of [default]. *) (** {5 Destructor} *) val view : 'a t -> ('a option * 'a t) option val is_empty : 'a t -> bool val is_default : 'a t -> bool (** {5 Usual list-like operators} *) val length : 'a t -> int val equal : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int val to_list : 'a t -> 'a option list val of_full_list : 'a list -> 'a t (** {5 Iterators ignoring optional values} *) module Skip : sig val iter : ('a -> unit) -> 'a t -> unit val map : ('a -> 'b) -> 'a t -> 'b t val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a val for_all : ('a -> bool) -> 'a t -> bool val exists : ('a -> bool) -> 'a t -> bool end (** These iterators ignore the default values in the list. *) (** {5 Smart iterators} *) module Smart : sig val map : ('a -> 'a) -> 'a t -> 'a t val fold_left_map : ('a -> 'b -> 'a * 'b) -> 'a -> 'b t -> 'a * 'b t end (** These iterators also ignore the default values in the list. *) rocq-9.2.0/clib/segmenttree.ml000066400000000000000000000122241516144147600162650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* () | x :: xs -> f i x; loop (i + 1) xs in loop 0 l let log2 x = log x /. log 2. let log2n x = int_of_float (ceil (log2 (float_of_int x))) (** We focus on integers but this module can be generalized. *) type elt = int (** A value of type [domain] is interpreted differently given its position in the tree. On internal nodes, a domain represents the set of integers which are _not_ in the set of keys handled by the tree. On leaves, a domain represents the st of integers which are in the set of keys. *) type domain = | Interval of elt * elt (** On internal nodes, a domain [Interval (a, b)] represents the interval [a + 1; b - 1]. On leaves, it represents [a; b]. We always have [a] <= [b]. *) | Universe (** On internal node or root, a domain [Universe] represents all the integers. When the tree is not a trivial root, [Universe] has no interpretation on leaves. (The lookup function should never reach the leaves.) *) (** We use an array to store the almost complete tree. This array contains at least one element. *) type 'a t = (domain * 'a option) array (** The root is the first item of the array. *) (** Standard layout for left child. *) let left_child i = 2 * i + 1 (** Standard layout for right child. *) let right_child i = 2 * i + 2 (** Extract the annotation of a node, be it internal or a leaf. *) let value_of i t = match t.(i) with (_, Some x) -> x | _ -> raise Not_found (** Initialize the array to store [n] leaves. *) let create n init = Array.make (1 lsl (log2n n + 1) - 1) init (** Make a complete interval tree from a list of disjoint segments. Precondition : the segments must be sorted. *) let make segments = let nsegments = List.length segments in let tree = create nsegments (Universe, None) in let leaves_offset = (1 lsl (log2n nsegments)) - 1 in (* The algorithm proceeds in two steps using an intermediate tree to store minimum and maximum of each subtree as annotation of the node. *) (* We start from leaves: the last level of the tree is initialized with the given segments... *) list_iteri (fun i ((start, stop), value) -> let k = leaves_offset + i in let i = Interval (start, stop) in tree.(k) <- (i, Some i)) segments; (* ... the remaining leaves are initialized with neutral information. *) for k = leaves_offset + nsegments to Array.length tree -1 do tree.(k) <- (Universe, Some Universe) done; (* We traverse the tree bottom-up and compute the interval and annotation associated to each node from the annotations of its children. *) for k = leaves_offset - 1 downto 0 do let node, annotation = match value_of (left_child k) tree, value_of (right_child k) tree with | Interval (left_min, left_max), Interval (right_min, right_max) -> (Interval (left_max, right_min), Interval (left_min, right_max)) | Interval (min, max), Universe -> (Interval (max, max), Interval (min, max)) | Universe, Universe -> Universe, Universe | Universe, _ -> assert false in tree.(k) <- (node, Some annotation) done; (* Finally, annotation are replaced with the image related to each leaf. *) let final_tree = Array.mapi (fun i (segment, value) -> (segment, None)) tree in list_iteri (fun i ((start, stop), value) -> final_tree.(leaves_offset + i) <- (Interval (start, stop), Some value)) segments; final_tree (** [lookup k t] looks for an image for key [k] in the interval tree [t]. Raise [Not_found] if it fails. *) let lookup k t = let i = ref 0 in while (snd t.(!i) = None) do match fst t.(!i) with | Interval (start, stop) -> if k <= start then i := left_child !i else if k >= stop then i:= right_child !i else raise Not_found | Universe -> raise Not_found done; match fst t.(!i) with | Interval (start, stop) -> if k >= start && k <= stop then match snd t.(!i) with | Some v -> v | None -> assert false else raise Not_found | Universe -> assert false rocq-9.2.0/clib/segmenttree.mli000066400000000000000000000025431516144147600164410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t (** [lookup k t] looks for an image for key [k] in the interval tree [t]. Raise [Not_found] if it fails. *) val lookup : int -> 'a t -> 'a rocq-9.2.0/clib/store.ml000066400000000000000000000031721516144147600151010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a field val empty : t val set : t -> 'a field -> 'a -> t val get : t -> 'a field -> 'a option val remove : t -> 'a field -> t val merge : t -> t -> t end module Make() : S = struct module Dyn = Dyn.Make() module Map = Dyn.Map(struct type 'a t = 'a end) type t = Map.t type 'a field = 'a Dyn.tag let field = Dyn.create let empty = Map.empty let set s f v = Map.add f v s let get s f = try Some (Map.find f s) with Not_found -> None let remove s f = Map.remove f s let merge s1 s2 = Map.fold (fun (Map.Any (f, v)) s -> Map.add f v s) s1 s2 end rocq-9.2.0/clib/store.mli000066400000000000000000000026151516144147600152530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a field (** Create a new field. See also [Dyn.create]. *) val empty : t (** Empty store *) val set : t -> 'a field -> 'a -> t (** Set a field *) val get : t -> 'a field -> 'a option (** Get the value of a field, if any *) val remove : t -> 'a field -> t (** Unset the value of the field *) val merge : t -> t -> t (** [merge s1 s2] adds all the fields of [s1] into [s2]. *) end module Make() : S (** Create a new store type. *) rocq-9.2.0/clib/terminal.ml000066400000000000000000000177031516144147600155650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* o2 | Some _ -> match o2 with | None -> o1 | Some _ -> o2 let default = { fg_color = None; bg_color = None; bold = None; italic = None; underline = None; negative = None; prefix = None; suffix = None; } let reset = "\027[0m" let reset_style = { fg_color = Some `DEFAULT; bg_color = Some `DEFAULT; bold = Some false; italic = Some false; underline = Some false; negative = Some false; prefix = None; suffix = None; } let make ?fg_color ?bg_color ?bold ?italic ?underline ?negative ?style ?prefix ?suffix () = let st = match style with | None -> default | Some st -> st in { fg_color = set st.fg_color fg_color; bg_color = set st.bg_color bg_color; bold = set st.bold bold; italic = set st.italic italic; underline = set st.underline underline; negative = set st.negative negative; prefix = set st.prefix prefix; suffix = set st.suffix suffix; } let merge s1 s2 = { fg_color = set s1.fg_color s2.fg_color; bg_color = set s1.bg_color s2.bg_color; bold = set s1.bold s2.bold; italic = set s1.italic s2.italic; underline = set s1.underline s2.underline; negative = set s1.negative s2.negative; prefix = set s1.prefix s2.prefix; suffix = set s1.suffix s2.suffix; } let diff s1 s2 = let diff_op o1 o2 reset_val = match o1 with | None -> o2 | Some _ -> match o2 with | None -> reset_val | Some _ -> if o1 = o2 then None else o2 in { fg_color = diff_op s1.fg_color s2.fg_color reset_style.fg_color; bg_color = diff_op s1.bg_color s2.bg_color reset_style.bg_color; bold = diff_op s1.bold s2.bold reset_style.bold; italic = diff_op s1.italic s2.italic reset_style.italic; underline = diff_op s1.underline s2.underline reset_style.underline; negative = diff_op s1.negative s2.negative reset_style.negative; prefix = diff_op s1.prefix s2.prefix reset_style.prefix; suffix = diff_op s1.suffix s2.suffix reset_style.suffix; } let base_color = function | `DEFAULT -> 9 | `BLACK -> 0 | `RED -> 1 | `GREEN -> 2 | `YELLOW -> 3 | `BLUE -> 4 | `MAGENTA -> 5 | `CYAN -> 6 | `WHITE -> 7 | `LIGHT_BLACK -> 0 | `LIGHT_RED -> 1 | `LIGHT_GREEN -> 2 | `LIGHT_YELLOW -> 3 | `LIGHT_BLUE -> 4 | `LIGHT_MAGENTA -> 5 | `LIGHT_CYAN -> 6 | `LIGHT_WHITE -> 7 | _ -> invalid_arg "base_color" let extended_color off = function | `INDEX i -> [off + 8; 5; i] | `RGB (r, g, b) -> [off + 8; 2; r; g; b] | _ -> invalid_arg "extended_color" let is_light = function | `LIGHT_BLACK | `LIGHT_RED | `LIGHT_GREEN | `LIGHT_YELLOW | `LIGHT_BLUE | `LIGHT_MAGENTA | `LIGHT_CYAN | `LIGHT_WHITE -> true | _ -> false let is_extended = function | `INDEX _ | `RGB _ -> true | _ -> false let repr st = let fg = match st.fg_color with | None -> [] | Some c -> if is_light c then [90 + base_color c] else if is_extended c then extended_color 30 c else [30 + base_color c] in let bg = match st.bg_color with | None -> [] | Some c -> if is_light c then [100 + base_color c] else if is_extended c then extended_color 40 c else [40 + base_color c] in let bold = match st.bold with | None -> [] | Some true -> [1] | Some false -> [22] in let italic = match st.italic with | None -> [] | Some true -> [3] | Some false -> [23] in let underline = match st.underline with | None -> [] | Some true -> [4] | Some false -> [24] in let negative = match st.negative with | None -> [] | Some true -> [7] | Some false -> [27] in fg @ bg @ bold @ italic @ underline @ negative let eval st = let tags = repr st in let tags = List.map string_of_int tags in if List.length tags = 0 then "" else Printf.sprintf "\027[%sm" (String.concat ";" tags) let has_style t = Unix.isatty t && Sys.os_type = "Unix" let split c s = let len = String.length s in let rec split n = try let pos = String.index_from s n c in let dir = String.sub s n (pos-n) in dir :: split (succ pos) with | Not_found -> [String.sub s n (len-n)] in if len = 0 then [] else split 0 let check_char i = if i < 0 || i > 255 then invalid_arg "check_char" let parse_color off rem = match off with | 0 -> (`BLACK, rem) | 1 -> (`RED, rem) | 2 -> (`GREEN, rem) | 3 -> (`YELLOW, rem) | 4 -> (`BLUE, rem) | 5 -> (`MAGENTA, rem) | 6 -> (`CYAN, rem) | 7 -> (`WHITE, rem) | 9 -> (`DEFAULT, rem) | 8 -> begin match rem with | 5 :: i :: rem -> check_char i; (`INDEX i, rem) | 2 :: r :: g :: b :: rem -> check_char r; check_char g; check_char b; (`RGB (r, g, b), rem) | _ -> invalid_arg "parse_color" end | _ -> invalid_arg "parse_color" let set_light = function | `BLACK -> `LIGHT_BLACK | `RED -> `LIGHT_RED | `GREEN -> `LIGHT_GREEN | `YELLOW -> `LIGHT_YELLOW | `BLUE -> `LIGHT_BLUE | `MAGENTA -> `LIGHT_MAGENTA | `CYAN -> `LIGHT_CYAN | `WHITE -> `LIGHT_WHITE | _ -> invalid_arg "parse_color" let rec parse_style style = function | [] -> style | 0 :: rem -> let style = merge style reset_style in parse_style style rem | 1 :: rem -> let style = make ~style ~bold:true () in parse_style style rem | 3 :: rem -> let style = make ~style ~italic:true () in parse_style style rem | 4 :: rem -> let style = make ~style ~underline:true () in parse_style style rem | 7 :: rem -> let style = make ~style ~negative:true () in parse_style style rem | 22 :: rem -> let style = make ~style ~bold:false () in parse_style style rem | 23 :: rem -> let style = make ~style ~italic:false () in parse_style style rem | 24 :: rem -> let style = make ~style ~underline:false () in parse_style style rem | 27 :: rem -> let style = make ~style ~negative:false () in parse_style style rem | code :: rem when (30 <= code && code < 40) -> let color, rem = parse_color (code mod 10) rem in let style = make ~style ~fg_color:color () in parse_style style rem | code :: rem when (40 <= code && code < 50) -> let color, rem = parse_color (code mod 10) rem in let style = make ~style ~bg_color:color () in parse_style style rem | code :: rem when (90 <= code && code < 100) -> let color, rem = parse_color (code mod 10) rem in let style = make ~style ~fg_color:(set_light color) () in parse_style style rem | code :: rem when (100 <= code && code < 110) -> let color, rem = parse_color (code mod 10) rem in let style = make ~style ~bg_color:(set_light color) () in parse_style style rem | _ :: rem -> parse_style style rem (** Parse LS_COLORS-like strings *) let parse s = let defs = split ':' s in let fold accu s = match split '=' s with | [name; attrs] -> let attrs = split ';' attrs in let accu = try let attrs = List.map int_of_string attrs in let attrs = parse_style (make ()) attrs in (name, attrs) :: accu with Failure _ | Invalid_argument _ -> accu in accu | _ -> accu in List.fold_left fold [] defs rocq-9.2.0/clib/terminal.mli000066400000000000000000000044011516144147600157250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ?bg_color:color -> ?bold:bool -> ?italic:bool -> ?underline:bool -> ?negative:bool -> ?style:style -> ?prefix:string -> ?suffix:string -> unit -> style (** Create a style from the given flags. It is derived from the optional [style] argument if given. *) val merge : style -> style -> style (** [merge s1 s2] returns [s1] with all defined values of [s2] overwritten. *) val diff : style -> style -> style (** [diff s1 s2] returns the differences between [s1] and [s2]. *) val repr : style -> int list (** Generate the ANSI code representing the given style. *) val eval : style -> string (** Generate an escape sequence from a style. *) val reset : string (** This escape sequence resets all attributes. *) val reset_style : style (** The default style *) val has_style : Unix.file_descr -> bool (** Whether an output file descriptor handles styles. Very heuristic, only checks it is a terminal. *) val parse : string -> (string * style) list (** Parse strings describing terminal styles in the LS_COLORS syntax. For robustness, ignore meaningless entries and drops undefined styles. *) rocq-9.2.0/clib/trie.ml000066400000000000000000000047431516144147600147150ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* data val next : t -> label -> t val labels : t -> label list val add : label list -> data -> t -> t val remove : label list -> data -> t -> t val iter : (label list -> data -> unit) -> t -> unit end module type Grp = sig type t val nil : t val is_nil : t -> bool val add : t -> t -> t val sub : t -> t -> t end module Make (Y : Map.OrderedType) (X : Grp) = struct module T_codom = Map.Make(Y) type data = X.t type label = Y.t type t = Node of X.t * t T_codom.t let codom_for_all f m = let fold key v accu = f v && accu in T_codom.fold fold m true let empty = Node (X.nil, T_codom.empty) let next (Node (_,m)) lbl = T_codom.find lbl m let get (Node (hereset,_)) = hereset let labels (Node (_,m)) = (* FIXME: this is order-dependent. Try to find a more robust presentation? *) List.rev (T_codom.fold (fun x _ acc -> x::acc) m []) let is_empty_node (Node(a,b)) = (X.is_nil a) && (T_codom.is_empty b) let assure_arc m lbl = if T_codom.mem lbl m then m else T_codom.add lbl (Node (X.nil,T_codom.empty)) m let cleanse_arcs (Node (hereset,m)) = let m = if codom_for_all is_empty_node m then T_codom.empty else m in Node(hereset, m) let rec at_path f (Node (hereset,m)) = function | [] -> cleanse_arcs (Node(f hereset,m)) | h::t -> let m = assure_arc m h in cleanse_arcs (Node(hereset, T_codom.add h (at_path f (T_codom.find h m) t) m)) let add path v tm = at_path (fun hereset -> X.add v hereset) tm path let remove path v tm = at_path (fun hereset -> X.sub hereset v) tm path let iter f tlm = let rec apprec pfx (Node(hereset,m)) = let path = List.rev pfx in f path hereset; T_codom.iter (fun l tm -> apprec (l::pfx) tm) m in apprec [] tlm end rocq-9.2.0/clib/trie.mli000066400000000000000000000040121516144147600150530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* data (** Get the data at the current node. *) val next : t -> label -> t (** [next t lbl] returns the subtrie of [t] pointed by [lbl]. @raise Not_found if there is none. *) val labels : t -> label list (** Get the list of defined labels at the current node. *) val add : label list -> data -> t -> t (** [add t path v] adds [v] at path [path] in [t]. *) val remove : label list -> data -> t -> t (** [remove t path v] removes [v] from path [path] in [t]. *) val iter : (label list -> data -> unit) -> t -> unit (** Apply a function to all contents. *) end module type Grp = sig type t val nil : t val is_nil : t -> bool val add : t -> t -> t val sub : t -> t -> t end module Make (Label : Set.OrderedType) (Data : Grp) : S with type label = Label.t and type data = Data.t (** Generating functor, for a given type of labels and data. *) rocq-9.2.0/clib/unicode.ml000066400000000000000000000351221516144147600153730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 1 lsl ((i land 7) * 3) (* 001 *) | IdentPart -> 2 lsl ((i land 7) * 3) (* 010 *) | Symbol -> 3 lsl ((i land 7) * 3) (* 011 *) | IdentSep -> 4 lsl ((i land 7) * 3) (* 100 *) | Separator -> 5 lsl ((i land 7) * 3) (* 101 *) | Control -> 6 lsl ((i land 7) * 3) (* 110 *) | Unknown -> 0 lsl ((i land 7) * 3) (* 000 *) (* Helper to reset 3 bits in a word. *) let reset_mask i = lnot (7 lsl ((i land 7) * 3)) (* Initialize the lookup table from a list of segments, assigning a status to every character of each segment. The order of these assignments is relevant: it is possible to assign status [s] to a segment [(c1, c2)] and later assign [s'] to [c] even if [c] is between [c1] and [c2]. *) let mk_lookup_table_from_unicode_tables_for status tables = List.iter (List.iter (fun (c1, c2) -> for i = c1 to c2 do table.(i lsr 3) <- (table.(i lsr 3) land (reset_mask i)) lor (mask i status) done)) tables (* Look up into the table and interpret the found pattern. *) let lookup x = let v = (table.(x lsr 3) lsr ((x land 7) * 3)) land 7 in if v = 1 then Letter else if v = 2 then IdentPart else if v = 3 then Symbol else if v = 4 then IdentSep else if v = 5 then Separator else if v = 6 then Control else Unknown (* [classify] discriminates between 5 different kinds of symbols based on the standard unicode classification (extracted from Camomile). *) let classify = let single c = [ (c, c) ] in (* General tables. *) mk_lookup_table_from_unicode_tables_for Symbol [ Unicodetable.sk; (* Symbol, modifiers. *) Unicodetable.sm; (* Symbol, maths. *) Unicodetable.sc; (* Symbol, currency. *) Unicodetable.so; (* Symbol, modifier. *) Unicodetable.pd; (* Punctuation, dash. *) Unicodetable.pc; (* Punctuation, connector. *) Unicodetable.pe; (* Punctuation, open. *) Unicodetable.ps; (* Punctution, close. *) Unicodetable.pi; (* Punctuation, initial quote. *) Unicodetable.pf; (* Punctuation, final quote. *) Unicodetable.po; (* Punctuation, other. *) ]; mk_lookup_table_from_unicode_tables_for Letter [ Unicodetable.lu; (* Letter, uppercase. *) Unicodetable.ll; (* Letter, lowercase. *) Unicodetable.lt; (* Letter, titlecase. *) Unicodetable.lo; (* Letter, others. *) Unicodetable.lm; (* Letter, modifier. *) ]; mk_lookup_table_from_unicode_tables_for IdentPart [ Unicodetable.nd; (* Number, decimal digits. *) Unicodetable.nl; (* Number, letter. *) Unicodetable.no; (* Number, other. *) Unicodetable.mn; (* Non-spacing marks. *) ]; (* Exceptions from Number, other. *) mk_lookup_table_from_unicode_tables_for Symbol [ [(0x000B2, 0x000B3)]; (* Superscript 2-3. *) single 0x000B9; (* Superscript 1. *) single 0x02070; (* Superscript 0. *) [(0x02074, 0x02079)]; (* Superscript 4-9. *) ]; mk_lookup_table_from_unicode_tables_for Separator [ Unicodetable.zs; (* Separator, Space. *) Unicodetable.zl; (* Separator, Line. *) Unicodetable.zp; (* Separator, Paragraph. *) ]; mk_lookup_table_from_unicode_tables_for Control [ Unicodetable.cc; (* Other, Control. *) ]; mk_lookup_table_from_unicode_tables_for IdentSep [ single 0x005F; (* Underscore. *) single 0x00A0; (* Non breaking space, overrides Sep *) ]; mk_lookup_table_from_unicode_tables_for IdentPart [ single 0x0027; (* Single quote. *) ]; (* Lookup *) lookup exception End_of_input let utf8_of_unicode n = if n < 128 then String.make 1 (Char.chr n) else let (m,s) = if n < 2048 then (2,192) else if n < 65536 then (3,224) else (4,240) in String.init m (fun i -> let j = (n lsr ((m - 1 - i) * 6)) land 63 in Char.chr (j + if i = 0 then s else 128)) (* If [s] is some UTF-8 encoded string and [i] is a position of some UTF-8 character within [s] then [next_utf8 s i] returns [(j,n)] where: - [j] indicates the position of the next UTF-8 character - [n] represents the UTF-8 character at index [i] *) let next_utf8 s i = let err () = invalid_arg "utf8" in let l = String.length s - i in if l = 0 then raise End_of_input else let a = Char.code s.[i] in if a <= 0x7F then 1, a else if a land 0x40 = 0 || l = 1 then err () else let b = Char.code s.[i+1] in if b land 0xC0 <> 0x80 then err () else if a land 0x20 = 0 then 2, (a land 0x1F) lsl 6 + (b land 0x3F) else if l = 2 then err () else let c = Char.code s.[i+2] in if c land 0xC0 <> 0x80 then err () else if a land 0x10 = 0 then 3, (a land 0x0F) lsl 12 + (b land 0x3F) lsl 6 + (c land 0x3F) else if l = 3 then err () else let d = Char.code s.[i+3] in if d land 0xC0 <> 0x80 then err () else if a land 0x08 = 0 then 4, (a land 0x07) lsl 18 + (b land 0x3F) lsl 12 + (c land 0x3F) lsl 6 + (d land 0x3F) else err () let is_utf8 s = let rec check i = let (off, _) = next_utf8 s i in check (i + off) in try check 0 with End_of_input -> true | Invalid_argument _ -> false (* Escape string if it contains non-utf8 characters *) let escaped_non_utf8 s = let mk_escape x = Printf.sprintf "%%%X" x in let buff = Buffer.create (String.length s * 3) in let rec process_trailing_aux i j = if i = j then i else match String.unsafe_get s i with | '\128'..'\191' -> process_trailing_aux (i+1) j | _ -> i in let process_trailing i n = let j = if i+n-1 >= String.length s then i+1 else process_trailing_aux (i+1) (i+n) in (if j = i+n then Buffer.add_string buff (String.sub s i n) else let v = Array.init (j-i) (fun k -> mk_escape (Char.code s.[i+k])) in Buffer.add_string buff (String.concat "" (Array.to_list v))); j in let rec process i = if i >= String.length s then Buffer.contents buff else let c = String.unsafe_get s i in match c with | '\000'..'\127' -> Buffer.add_char buff c; process (i+1) | '\128'..'\191' | '\248'..'\255' -> Buffer.add_string buff (mk_escape (Char.code c)); process (i+1) | '\192'..'\223' -> process (process_trailing i 2) | '\224'..'\239' -> process (process_trailing i 3) | '\240'..'\247' -> process (process_trailing i 4) in process 0 let escaped_if_non_utf8 s = if is_utf8 s then s else escaped_non_utf8 s (* Check the well-formedness of an identifier *) let is_valid_ident_initial = function | Letter | IdentSep -> true | IdentPart | Symbol | Separator | Control | Unknown -> false let initial_refutation j n s = if is_valid_ident_initial (classify n) then None else let c = String.sub s 0 j in Some (false, "Invalid character '"^c^"' at beginning of identifier \""^s^"\".") let is_valid_ident_trailing = function | Letter | IdentSep | IdentPart -> true | Symbol | Separator | Control | Unknown -> false let trailing_refutation i j n s = if is_valid_ident_trailing (classify n) then None else let c = String.sub s i j in Some (false, "Invalid character '"^c^"' in identifier \""^s^"\".") let is_unknown = function | Unknown -> true | Letter | IdentSep | IdentPart | Symbol | Separator | Control -> false let is_ident_part = function | IdentPart -> true | Letter | IdentSep | Symbol | Unknown | Separator | Control -> false let is_ident_sep = function | IdentSep -> true | Letter | IdentPart | Symbol | Unknown | Separator | Control -> false let is_letter = function | Letter -> true | IdentSep | IdentPart | Symbol | Unknown | Separator | Control -> false let ident_refutation s = if s = ".." then None else try let j, n = next_utf8 s 0 in match initial_refutation j n s with |None -> begin try let rec aux i = let j, n = next_utf8 s i in match trailing_refutation i j n s with |None -> aux (i + j) |x -> x in aux j with End_of_input -> None end |x -> x with | End_of_input -> Some (true,"The empty string is not an identifier.") | Invalid_argument _ -> Some (true,escaped_non_utf8 s^": invalid utf8 sequence.") let lowercase_unicode = let tree = Segmenttree.make Unicodetable.to_lower in fun unicode -> try match Segmenttree.lookup unicode tree with | `Abs c -> c | `Delta d -> unicode + d with Not_found -> unicode let lowercase_first_char s = assert (s <> ""); let j, n = next_utf8 s 0 in utf8_of_unicode (lowercase_unicode n) let split_at_first_letter s = let n, v = next_utf8 s 0 in if ((* optim *) n = 1 && s.[0] != '_') || not (is_ident_sep (classify v)) then None else begin let n = ref n in let p = ref 0 in while !n < String.length s && let n', v = next_utf8 s !n in p := n'; (* Test if not letter *) ((* optim *) n' = 1 && (s.[!n] = '_' || s.[!n] = '\'')) || let st = classify v in is_ident_sep st || is_ident_part st do n := !n + !p done; let s1 = String.sub s 0 !n in let s2 = String.sub s !n (String.length s - !n) in Some (s1,s2) end (** For extraction, we need to encode unicode character into ascii ones *) let is_basic_ascii s = let ok = ref true in String.iter (fun c -> if Char.code c >= 128 then ok := false) s; !ok let ascii_of_ident s = let len = String.length s in let has_UU i = i+2 < len && s.[i]='_' && s.[i+1]='U' && s.[i+2]='U' in let i = ref 0 in while !i < len && Char.code s.[!i] < 128 && not (has_UU !i) do incr i done; if !i = len then s else let out = Buffer.create (2*len) in Buffer.add_substring out s 0 !i; while !i < len do let j, n = next_utf8 s !i in if n >= 128 then (Printf.bprintf out "_UU%04x_" n; i := !i + j) else if has_UU !i then (Buffer.add_string out "_UUU"; i := !i + 3) else (Buffer.add_char out s.[!i]; incr i) done; Buffer.contents out (* Compute length of an UTF-8 encoded string Rem 1 : utf8_length <= String.length (equal if pure ascii) Rem 2 : if used for an iso8859_1 encoded string, the result is wrong in very rare cases. Such a wrong case corresponds to any sequence of a character in range 192..253 immediately followed by a character in range 128..191 (typical case in french is "déçu" which is counted 3 instead of 4); then no real harm to use always utf8_length even if using an iso8859_1 encoding *) (** FIXME: duplicate code with Pp *) let utf8_length s = let len = String.length s and cnt = ref 0 and nc = ref 0 and p = ref 0 in while !p < len do begin match s.[!p] with | '\000'..'\127' -> nc := 0 (* ascii char *) | '\128'..'\191' -> nc := 0 (* cannot start with a continuation byte *) | '\192'..'\223' -> nc := 1 (* expect 1 continuation byte *) | '\224'..'\239' -> nc := 2 (* expect 2 continuation bytes *) | '\240'..'\247' -> nc := 3 (* expect 3 continuation bytes *) | '\248'..'\255' -> nc := 0 (* invalid byte *) end ; incr p ; while !p < len && !nc > 0 do match s.[!p] with | '\128'..'\191' (* next continuation byte *) -> incr p ; decr nc | _ (* not a continuation byte *) -> nc := 0 done ; incr cnt done ; !cnt (* Variant of String.sub for UTF8 character positions *) let utf8_sub s start_u len_u = let len_b = String.length s and end_u = start_u + len_u and cnt = ref 0 and nc = ref 0 and p = ref 0 in let start_b = ref len_b in while !p < len_b && !cnt < end_u do if !cnt <= start_u then start_b := !p ; begin match s.[!p] with | '\000'..'\127' -> nc := 0 (* ascii char *) | '\128'..'\191' -> nc := 0 (* cannot start with a continuation byte *) | '\192'..'\223' -> nc := 1 (* expect 1 continuation byte *) | '\224'..'\239' -> nc := 2 (* expect 2 continuation bytes *) | '\240'..'\247' -> nc := 3 (* expect 3 continuation bytes *) | '\248'..'\255' -> nc := 0 (* invalid byte *) end ; incr p ; while !p < len_b && !nc > 0 do match s.[!p] with | '\128'..'\191' (* next continuation byte *) -> incr p ; decr nc | _ (* not a continuation byte *) -> nc := 0 done ; incr cnt done ; let end_b = !p in String.sub s !start_b (end_b - !start_b) rocq-9.2.0/clib/unicode.mli000066400000000000000000000051301516144147600155400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* status (** Return [None] if a given string can be used as a (Rocq) identifier. Return [Some (b,s)] otherwise, where [s] is an explanation and [b] is severity. *) val ident_refutation : string -> (bool * string) option (** Tells if a valid initial character for an identifier *) val is_valid_ident_initial : status -> bool (** Tells if a valid non-initial character for an identifier *) val is_valid_ident_trailing : status -> bool (** Tells if a letter *) val is_letter : status -> bool (** Tells if a character is unclassified *) val is_unknown : status -> bool (** First char of a string, converted to lowercase @raise Assert_failure if the input string is empty. *) val lowercase_first_char : string -> string (** Split a string supposed to be an ident at the first letter; as an optimization, return None if the first character is a letter *) val split_at_first_letter : string -> (string * string) option (** Return [true] if all UTF-8 characters in the input string are just plain ASCII characters. Returns [false] otherwise. *) val is_basic_ascii : string -> bool (** [ascii_of_ident s] maps UTF-8 string to a string composed solely from ASCII characters. The non-ASCII characters are translated to ["_UUxxxx_"] where {i xxxx} is the Unicode index of the character in hexadecimal (from four to six hex digits). To avoid potential name clashes, any preexisting substring ["_UU"] is turned into ["_UUU"]. *) val ascii_of_ident : string -> string (** Validate an UTF-8 string *) val is_utf8 : string -> bool (** Return the length of a valid UTF-8 string. *) val utf8_length : string -> int (** Variant of {!String.sub} for UTF-8 strings. *) val utf8_sub : string -> int -> int -> string (** Return a "%XX"-escaped string if it contains non UTF-8 characters. *) val escaped_if_non_utf8 : string -> string rocq-9.2.0/clib/unicodetable.mli000066400000000000000000000015211516144147600165500ustar00rootroot00000000000000val lu : (int * int) list val ll : (int * int) list val lt : (int * int) list val mn : (int * int) list val mc : (int * int) list val me : (int * int) list val nd : (int * int) list val nl : (int * int) list val no : (int * int) list val zs : (int * int) list val zl : (int * int) list val zp : (int * int) list val cc : (int * int) list val cf : (int * int) list val cs : (int * int) list val co : (int * int) list val cn : (int * int) list val lm : (int * int) list val lo : (int * int) list val pc : (int * int) list val pd : (int * int) list val ps : (int * int) list val pe : (int * int) list val pi : (int * int) list val pf : (int * int) list val po : (int * int) list val sm : (int * int) list val sc : (int * int) list val sk : (int * int) list val so : (int * int) list val to_lower : ((int * int) * [> `Abs of int | `Delta of int ]) list rocq-9.2.0/clib/unicodetable_gen.ml000066400000000000000000006277171516144147600172550ustar00rootroot00000000000000(** Unicode tables generated using UUCD. *) (* Letter, Uppercase *) let lu = [ (0x00041,0x0005A); (0x000C0,0x000D6); (0x000D8,0x000DE); (0x00100,0x00100); (0x00102,0x00102); (0x00104,0x00104); (0x00106,0x00106); (0x00108,0x00108); (0x0010A,0x0010A); (0x0010C,0x0010C); (0x0010E,0x0010E); (0x00110,0x00110); (0x00112,0x00112); (0x00114,0x00114); (0x00116,0x00116); (0x00118,0x00118); (0x0011A,0x0011A); (0x0011C,0x0011C); (0x0011E,0x0011E); (0x00120,0x00120); (0x00122,0x00122); (0x00124,0x00124); (0x00126,0x00126); (0x00128,0x00128); (0x0012A,0x0012A); (0x0012C,0x0012C); (0x0012E,0x0012E); (0x00130,0x00130); (0x00132,0x00132); (0x00134,0x00134); (0x00136,0x00136); (0x00139,0x00139); (0x0013B,0x0013B); (0x0013D,0x0013D); (0x0013F,0x0013F); (0x00141,0x00141); (0x00143,0x00143); (0x00145,0x00145); (0x00147,0x00147); (0x0014A,0x0014A); (0x0014C,0x0014C); (0x0014E,0x0014E); (0x00150,0x00150); (0x00152,0x00152); (0x00154,0x00154); (0x00156,0x00156); (0x00158,0x00158); (0x0015A,0x0015A); (0x0015C,0x0015C); (0x0015E,0x0015E); (0x00160,0x00160); (0x00162,0x00162); (0x00164,0x00164); (0x00166,0x00166); (0x00168,0x00168); (0x0016A,0x0016A); (0x0016C,0x0016C); (0x0016E,0x0016E); (0x00170,0x00170); (0x00172,0x00172); (0x00174,0x00174); (0x00176,0x00176); (0x00178,0x00179); (0x0017B,0x0017B); (0x0017D,0x0017D); (0x00181,0x00182); (0x00184,0x00184); (0x00186,0x00187); (0x00189,0x0018B); (0x0018E,0x00191); (0x00193,0x00194); (0x00196,0x00198); (0x0019C,0x0019D); (0x0019F,0x001A0); (0x001A2,0x001A2); (0x001A4,0x001A4); (0x001A6,0x001A7); (0x001A9,0x001A9); (0x001AC,0x001AC); (0x001AE,0x001AF); (0x001B1,0x001B3); (0x001B5,0x001B5); (0x001B7,0x001B8); (0x001BC,0x001BC); (0x001C4,0x001C4); (0x001C7,0x001C7); (0x001CA,0x001CA); (0x001CD,0x001CD); (0x001CF,0x001CF); (0x001D1,0x001D1); (0x001D3,0x001D3); (0x001D5,0x001D5); (0x001D7,0x001D7); (0x001D9,0x001D9); (0x001DB,0x001DB); (0x001DE,0x001DE); (0x001E0,0x001E0); (0x001E2,0x001E2); (0x001E4,0x001E4); (0x001E6,0x001E6); (0x001E8,0x001E8); (0x001EA,0x001EA); (0x001EC,0x001EC); (0x001EE,0x001EE); (0x001F1,0x001F1); (0x001F4,0x001F4); (0x001F6,0x001F8); (0x001FA,0x001FA); (0x001FC,0x001FC); (0x001FE,0x001FE); (0x00200,0x00200); (0x00202,0x00202); (0x00204,0x00204); (0x00206,0x00206); (0x00208,0x00208); (0x0020A,0x0020A); (0x0020C,0x0020C); (0x0020E,0x0020E); (0x00210,0x00210); (0x00212,0x00212); (0x00214,0x00214); (0x00216,0x00216); (0x00218,0x00218); (0x0021A,0x0021A); (0x0021C,0x0021C); (0x0021E,0x0021E); (0x00220,0x00220); (0x00222,0x00222); (0x00224,0x00224); (0x00226,0x00226); (0x00228,0x00228); (0x0022A,0x0022A); (0x0022C,0x0022C); (0x0022E,0x0022E); (0x00230,0x00230); (0x00232,0x00232); (0x0023A,0x0023B); (0x0023D,0x0023E); (0x00241,0x00241); (0x00243,0x00246); (0x00248,0x00248); (0x0024A,0x0024A); (0x0024C,0x0024C); (0x0024E,0x0024E); (0x00370,0x00370); (0x00372,0x00372); (0x00376,0x00376); (0x0037F,0x0037F); (0x00386,0x00386); (0x00388,0x0038A); (0x0038C,0x0038C); (0x0038E,0x0038F); (0x00391,0x003A1); (0x003A3,0x003AB); (0x003CF,0x003CF); (0x003D2,0x003D4); (0x003D8,0x003D8); (0x003DA,0x003DA); (0x003DC,0x003DC); (0x003DE,0x003DE); (0x003E0,0x003E0); (0x003E2,0x003E2); (0x003E4,0x003E4); (0x003E6,0x003E6); (0x003E8,0x003E8); (0x003EA,0x003EA); (0x003EC,0x003EC); (0x003EE,0x003EE); (0x003F4,0x003F4); (0x003F7,0x003F7); (0x003F9,0x003FA); (0x003FD,0x0042F); (0x00460,0x00460); (0x00462,0x00462); (0x00464,0x00464); (0x00466,0x00466); (0x00468,0x00468); (0x0046A,0x0046A); (0x0046C,0x0046C); (0x0046E,0x0046E); (0x00470,0x00470); (0x00472,0x00472); (0x00474,0x00474); (0x00476,0x00476); (0x00478,0x00478); (0x0047A,0x0047A); (0x0047C,0x0047C); (0x0047E,0x0047E); (0x00480,0x00480); (0x0048A,0x0048A); (0x0048C,0x0048C); (0x0048E,0x0048E); (0x00490,0x00490); (0x00492,0x00492); (0x00494,0x00494); (0x00496,0x00496); (0x00498,0x00498); (0x0049A,0x0049A); (0x0049C,0x0049C); (0x0049E,0x0049E); (0x004A0,0x004A0); (0x004A2,0x004A2); (0x004A4,0x004A4); (0x004A6,0x004A6); (0x004A8,0x004A8); (0x004AA,0x004AA); (0x004AC,0x004AC); (0x004AE,0x004AE); (0x004B0,0x004B0); (0x004B2,0x004B2); (0x004B4,0x004B4); (0x004B6,0x004B6); (0x004B8,0x004B8); (0x004BA,0x004BA); (0x004BC,0x004BC); (0x004BE,0x004BE); (0x004C0,0x004C1); (0x004C3,0x004C3); (0x004C5,0x004C5); (0x004C7,0x004C7); (0x004C9,0x004C9); (0x004CB,0x004CB); (0x004CD,0x004CD); (0x004D0,0x004D0); (0x004D2,0x004D2); (0x004D4,0x004D4); (0x004D6,0x004D6); (0x004D8,0x004D8); (0x004DA,0x004DA); (0x004DC,0x004DC); (0x004DE,0x004DE); (0x004E0,0x004E0); (0x004E2,0x004E2); (0x004E4,0x004E4); (0x004E6,0x004E6); (0x004E8,0x004E8); (0x004EA,0x004EA); (0x004EC,0x004EC); (0x004EE,0x004EE); (0x004F0,0x004F0); (0x004F2,0x004F2); (0x004F4,0x004F4); (0x004F6,0x004F6); (0x004F8,0x004F8); (0x004FA,0x004FA); (0x004FC,0x004FC); (0x004FE,0x004FE); (0x00500,0x00500); (0x00502,0x00502); (0x00504,0x00504); (0x00506,0x00506); (0x00508,0x00508); (0x0050A,0x0050A); (0x0050C,0x0050C); (0x0050E,0x0050E); (0x00510,0x00510); (0x00512,0x00512); (0x00514,0x00514); (0x00516,0x00516); (0x00518,0x00518); (0x0051A,0x0051A); (0x0051C,0x0051C); (0x0051E,0x0051E); (0x00520,0x00520); (0x00522,0x00522); (0x00524,0x00524); (0x00526,0x00526); (0x00528,0x00528); (0x0052A,0x0052A); (0x0052C,0x0052C); (0x0052E,0x0052E); (0x00531,0x00556); (0x010A0,0x010C5); (0x010C7,0x010C7); (0x010CD,0x010CD); (0x013A0,0x013F5); (0x01E00,0x01E00); (0x01E02,0x01E02); (0x01E04,0x01E04); (0x01E06,0x01E06); (0x01E08,0x01E08); (0x01E0A,0x01E0A); (0x01E0C,0x01E0C); (0x01E0E,0x01E0E); (0x01E10,0x01E10); (0x01E12,0x01E12); (0x01E14,0x01E14); (0x01E16,0x01E16); (0x01E18,0x01E18); (0x01E1A,0x01E1A); (0x01E1C,0x01E1C); (0x01E1E,0x01E1E); (0x01E20,0x01E20); (0x01E22,0x01E22); (0x01E24,0x01E24); (0x01E26,0x01E26); (0x01E28,0x01E28); (0x01E2A,0x01E2A); (0x01E2C,0x01E2C); (0x01E2E,0x01E2E); (0x01E30,0x01E30); (0x01E32,0x01E32); (0x01E34,0x01E34); (0x01E36,0x01E36); (0x01E38,0x01E38); (0x01E3A,0x01E3A); (0x01E3C,0x01E3C); (0x01E3E,0x01E3E); (0x01E40,0x01E40); (0x01E42,0x01E42); (0x01E44,0x01E44); (0x01E46,0x01E46); (0x01E48,0x01E48); (0x01E4A,0x01E4A); (0x01E4C,0x01E4C); (0x01E4E,0x01E4E); (0x01E50,0x01E50); (0x01E52,0x01E52); (0x01E54,0x01E54); (0x01E56,0x01E56); (0x01E58,0x01E58); (0x01E5A,0x01E5A); (0x01E5C,0x01E5C); (0x01E5E,0x01E5E); (0x01E60,0x01E60); (0x01E62,0x01E62); (0x01E64,0x01E64); (0x01E66,0x01E66); (0x01E68,0x01E68); (0x01E6A,0x01E6A); (0x01E6C,0x01E6C); (0x01E6E,0x01E6E); (0x01E70,0x01E70); (0x01E72,0x01E72); (0x01E74,0x01E74); (0x01E76,0x01E76); (0x01E78,0x01E78); (0x01E7A,0x01E7A); (0x01E7C,0x01E7C); (0x01E7E,0x01E7E); (0x01E80,0x01E80); (0x01E82,0x01E82); (0x01E84,0x01E84); (0x01E86,0x01E86); (0x01E88,0x01E88); (0x01E8A,0x01E8A); (0x01E8C,0x01E8C); (0x01E8E,0x01E8E); (0x01E90,0x01E90); (0x01E92,0x01E92); (0x01E94,0x01E94); (0x01E9E,0x01E9E); (0x01EA0,0x01EA0); (0x01EA2,0x01EA2); (0x01EA4,0x01EA4); (0x01EA6,0x01EA6); (0x01EA8,0x01EA8); (0x01EAA,0x01EAA); (0x01EAC,0x01EAC); (0x01EAE,0x01EAE); (0x01EB0,0x01EB0); (0x01EB2,0x01EB2); (0x01EB4,0x01EB4); (0x01EB6,0x01EB6); (0x01EB8,0x01EB8); (0x01EBA,0x01EBA); (0x01EBC,0x01EBC); (0x01EBE,0x01EBE); (0x01EC0,0x01EC0); (0x01EC2,0x01EC2); (0x01EC4,0x01EC4); (0x01EC6,0x01EC6); (0x01EC8,0x01EC8); (0x01ECA,0x01ECA); (0x01ECC,0x01ECC); (0x01ECE,0x01ECE); (0x01ED0,0x01ED0); (0x01ED2,0x01ED2); (0x01ED4,0x01ED4); (0x01ED6,0x01ED6); (0x01ED8,0x01ED8); (0x01EDA,0x01EDA); (0x01EDC,0x01EDC); (0x01EDE,0x01EDE); (0x01EE0,0x01EE0); (0x01EE2,0x01EE2); (0x01EE4,0x01EE4); (0x01EE6,0x01EE6); (0x01EE8,0x01EE8); (0x01EEA,0x01EEA); (0x01EEC,0x01EEC); (0x01EEE,0x01EEE); (0x01EF0,0x01EF0); (0x01EF2,0x01EF2); (0x01EF4,0x01EF4); (0x01EF6,0x01EF6); (0x01EF8,0x01EF8); (0x01EFA,0x01EFA); (0x01EFC,0x01EFC); (0x01EFE,0x01EFE); (0x01F08,0x01F0F); (0x01F18,0x01F1D); (0x01F28,0x01F2F); (0x01F38,0x01F3F); (0x01F48,0x01F4D); (0x01F59,0x01F59); (0x01F5B,0x01F5B); (0x01F5D,0x01F5D); (0x01F5F,0x01F5F); (0x01F68,0x01F6F); (0x01FB8,0x01FBB); (0x01FC8,0x01FCB); (0x01FD8,0x01FDB); (0x01FE8,0x01FEC); (0x01FF8,0x01FFB); (0x02102,0x02102); (0x02107,0x02107); (0x0210B,0x0210D); (0x02110,0x02112); (0x02115,0x02115); (0x02119,0x0211D); (0x02124,0x02124); (0x02126,0x02126); (0x02128,0x02128); (0x0212A,0x0212D); (0x02130,0x02133); (0x0213E,0x0213F); (0x02145,0x02145); (0x02183,0x02183); (0x02C00,0x02C2E); (0x02C60,0x02C60); (0x02C62,0x02C64); (0x02C67,0x02C67); (0x02C69,0x02C69); (0x02C6B,0x02C6B); (0x02C6D,0x02C70); (0x02C72,0x02C72); (0x02C75,0x02C75); (0x02C7E,0x02C80); (0x02C82,0x02C82); (0x02C84,0x02C84); (0x02C86,0x02C86); (0x02C88,0x02C88); (0x02C8A,0x02C8A); (0x02C8C,0x02C8C); (0x02C8E,0x02C8E); (0x02C90,0x02C90); (0x02C92,0x02C92); (0x02C94,0x02C94); (0x02C96,0x02C96); (0x02C98,0x02C98); (0x02C9A,0x02C9A); (0x02C9C,0x02C9C); (0x02C9E,0x02C9E); (0x02CA0,0x02CA0); (0x02CA2,0x02CA2); (0x02CA4,0x02CA4); (0x02CA6,0x02CA6); (0x02CA8,0x02CA8); (0x02CAA,0x02CAA); (0x02CAC,0x02CAC); (0x02CAE,0x02CAE); (0x02CB0,0x02CB0); (0x02CB2,0x02CB2); (0x02CB4,0x02CB4); (0x02CB6,0x02CB6); (0x02CB8,0x02CB8); (0x02CBA,0x02CBA); (0x02CBC,0x02CBC); (0x02CBE,0x02CBE); (0x02CC0,0x02CC0); (0x02CC2,0x02CC2); (0x02CC4,0x02CC4); (0x02CC6,0x02CC6); (0x02CC8,0x02CC8); (0x02CCA,0x02CCA); (0x02CCC,0x02CCC); (0x02CCE,0x02CCE); (0x02CD0,0x02CD0); (0x02CD2,0x02CD2); (0x02CD4,0x02CD4); (0x02CD6,0x02CD6); (0x02CD8,0x02CD8); (0x02CDA,0x02CDA); (0x02CDC,0x02CDC); (0x02CDE,0x02CDE); (0x02CE0,0x02CE0); (0x02CE2,0x02CE2); (0x02CEB,0x02CEB); (0x02CED,0x02CED); (0x02CF2,0x02CF2); (0x0A640,0x0A640); (0x0A642,0x0A642); (0x0A644,0x0A644); (0x0A646,0x0A646); (0x0A648,0x0A648); (0x0A64A,0x0A64A); (0x0A64C,0x0A64C); (0x0A64E,0x0A64E); (0x0A650,0x0A650); (0x0A652,0x0A652); (0x0A654,0x0A654); (0x0A656,0x0A656); (0x0A658,0x0A658); (0x0A65A,0x0A65A); (0x0A65C,0x0A65C); (0x0A65E,0x0A65E); (0x0A660,0x0A660); (0x0A662,0x0A662); (0x0A664,0x0A664); (0x0A666,0x0A666); (0x0A668,0x0A668); (0x0A66A,0x0A66A); (0x0A66C,0x0A66C); (0x0A680,0x0A680); (0x0A682,0x0A682); (0x0A684,0x0A684); (0x0A686,0x0A686); (0x0A688,0x0A688); (0x0A68A,0x0A68A); (0x0A68C,0x0A68C); (0x0A68E,0x0A68E); (0x0A690,0x0A690); (0x0A692,0x0A692); (0x0A694,0x0A694); (0x0A696,0x0A696); (0x0A698,0x0A698); (0x0A69A,0x0A69A); (0x0A722,0x0A722); (0x0A724,0x0A724); (0x0A726,0x0A726); (0x0A728,0x0A728); (0x0A72A,0x0A72A); (0x0A72C,0x0A72C); (0x0A72E,0x0A72E); (0x0A732,0x0A732); (0x0A734,0x0A734); (0x0A736,0x0A736); (0x0A738,0x0A738); (0x0A73A,0x0A73A); (0x0A73C,0x0A73C); (0x0A73E,0x0A73E); (0x0A740,0x0A740); (0x0A742,0x0A742); (0x0A744,0x0A744); (0x0A746,0x0A746); (0x0A748,0x0A748); (0x0A74A,0x0A74A); (0x0A74C,0x0A74C); (0x0A74E,0x0A74E); (0x0A750,0x0A750); (0x0A752,0x0A752); (0x0A754,0x0A754); (0x0A756,0x0A756); (0x0A758,0x0A758); (0x0A75A,0x0A75A); (0x0A75C,0x0A75C); (0x0A75E,0x0A75E); (0x0A760,0x0A760); (0x0A762,0x0A762); (0x0A764,0x0A764); (0x0A766,0x0A766); (0x0A768,0x0A768); (0x0A76A,0x0A76A); (0x0A76C,0x0A76C); (0x0A76E,0x0A76E); (0x0A779,0x0A779); (0x0A77B,0x0A77B); (0x0A77D,0x0A77E); (0x0A780,0x0A780); (0x0A782,0x0A782); (0x0A784,0x0A784); (0x0A786,0x0A786); (0x0A78B,0x0A78B); (0x0A78D,0x0A78D); (0x0A790,0x0A790); (0x0A792,0x0A792); (0x0A796,0x0A796); (0x0A798,0x0A798); (0x0A79A,0x0A79A); (0x0A79C,0x0A79C); (0x0A79E,0x0A79E); (0x0A7A0,0x0A7A0); (0x0A7A2,0x0A7A2); (0x0A7A4,0x0A7A4); (0x0A7A6,0x0A7A6); (0x0A7A8,0x0A7A8); (0x0A7AA,0x0A7AE); (0x0A7B0,0x0A7B4); (0x0A7B6,0x0A7B6); (0x0FF21,0x0FF3A); (0x10400,0x10427); (0x104B0,0x104D3); (0x10C80,0x10CB2); (0x118A0,0x118BF); (0x1D400,0x1D419); (0x1D434,0x1D44D); (0x1D468,0x1D481); (0x1D49C,0x1D49C); (0x1D49E,0x1D49F); (0x1D4A2,0x1D4A2); (0x1D4A5,0x1D4A6); (0x1D4A9,0x1D4AC); (0x1D4AE,0x1D4B5); (0x1D4D0,0x1D4E9); (0x1D504,0x1D505); (0x1D507,0x1D50A); (0x1D50D,0x1D514); (0x1D516,0x1D51C); (0x1D538,0x1D539); (0x1D53B,0x1D53E); (0x1D540,0x1D544); (0x1D546,0x1D546); (0x1D54A,0x1D550); (0x1D56C,0x1D585); (0x1D5A0,0x1D5B9); (0x1D5D4,0x1D5ED); (0x1D608,0x1D621); (0x1D63C,0x1D655); (0x1D670,0x1D689); (0x1D6A8,0x1D6C0); (0x1D6E2,0x1D6FA); (0x1D71C,0x1D734); (0x1D756,0x1D76E); (0x1D790,0x1D7A8); (0x1D7CA,0x1D7CA) ] (* Letter, Lowercase *) let ll = [ (0x00061,0x0007A); (0x000B5,0x000B5); (0x000DF,0x000F6); (0x000F8,0x000FF); (0x00101,0x00101); (0x00103,0x00103); (0x00105,0x00105); (0x00107,0x00107); (0x00109,0x00109); (0x0010B,0x0010B); (0x0010D,0x0010D); (0x0010F,0x0010F); (0x00111,0x00111); (0x00113,0x00113); (0x00115,0x00115); (0x00117,0x00117); (0x00119,0x00119); (0x0011B,0x0011B); (0x0011D,0x0011D); (0x0011F,0x0011F); (0x00121,0x00121); (0x00123,0x00123); (0x00125,0x00125); (0x00127,0x00127); (0x00129,0x00129); (0x0012B,0x0012B); (0x0012D,0x0012D); (0x0012F,0x0012F); (0x00131,0x00131); (0x00133,0x00133); (0x00135,0x00135); (0x00137,0x00138); (0x0013A,0x0013A); (0x0013C,0x0013C); (0x0013E,0x0013E); (0x00140,0x00140); (0x00142,0x00142); (0x00144,0x00144); (0x00146,0x00146); (0x00148,0x00149); (0x0014B,0x0014B); (0x0014D,0x0014D); (0x0014F,0x0014F); (0x00151,0x00151); (0x00153,0x00153); (0x00155,0x00155); (0x00157,0x00157); (0x00159,0x00159); (0x0015B,0x0015B); (0x0015D,0x0015D); (0x0015F,0x0015F); (0x00161,0x00161); (0x00163,0x00163); (0x00165,0x00165); (0x00167,0x00167); (0x00169,0x00169); (0x0016B,0x0016B); (0x0016D,0x0016D); (0x0016F,0x0016F); (0x00171,0x00171); (0x00173,0x00173); (0x00175,0x00175); (0x00177,0x00177); (0x0017A,0x0017A); (0x0017C,0x0017C); (0x0017E,0x00180); (0x00183,0x00183); (0x00185,0x00185); (0x00188,0x00188); (0x0018C,0x0018D); (0x00192,0x00192); (0x00195,0x00195); (0x00199,0x0019B); (0x0019E,0x0019E); (0x001A1,0x001A1); (0x001A3,0x001A3); (0x001A5,0x001A5); (0x001A8,0x001A8); (0x001AA,0x001AB); (0x001AD,0x001AD); (0x001B0,0x001B0); (0x001B4,0x001B4); (0x001B6,0x001B6); (0x001B9,0x001BA); (0x001BD,0x001BF); (0x001C6,0x001C6); (0x001C9,0x001C9); (0x001CC,0x001CC); (0x001CE,0x001CE); (0x001D0,0x001D0); (0x001D2,0x001D2); (0x001D4,0x001D4); (0x001D6,0x001D6); (0x001D8,0x001D8); (0x001DA,0x001DA); (0x001DC,0x001DD); (0x001DF,0x001DF); (0x001E1,0x001E1); (0x001E3,0x001E3); (0x001E5,0x001E5); (0x001E7,0x001E7); (0x001E9,0x001E9); (0x001EB,0x001EB); (0x001ED,0x001ED); (0x001EF,0x001F0); (0x001F3,0x001F3); (0x001F5,0x001F5); (0x001F9,0x001F9); (0x001FB,0x001FB); (0x001FD,0x001FD); (0x001FF,0x001FF); (0x00201,0x00201); (0x00203,0x00203); (0x00205,0x00205); (0x00207,0x00207); (0x00209,0x00209); (0x0020B,0x0020B); (0x0020D,0x0020D); (0x0020F,0x0020F); (0x00211,0x00211); (0x00213,0x00213); (0x00215,0x00215); (0x00217,0x00217); (0x00219,0x00219); (0x0021B,0x0021B); (0x0021D,0x0021D); (0x0021F,0x0021F); (0x00221,0x00221); (0x00223,0x00223); (0x00225,0x00225); (0x00227,0x00227); (0x00229,0x00229); (0x0022B,0x0022B); (0x0022D,0x0022D); (0x0022F,0x0022F); (0x00231,0x00231); (0x00233,0x00239); (0x0023C,0x0023C); (0x0023F,0x00240); (0x00242,0x00242); (0x00247,0x00247); (0x00249,0x00249); (0x0024B,0x0024B); (0x0024D,0x0024D); (0x0024F,0x00293); (0x00295,0x002AF); (0x00371,0x00371); (0x00373,0x00373); (0x00377,0x00377); (0x0037B,0x0037D); (0x00390,0x00390); (0x003AC,0x003CE); (0x003D0,0x003D1); (0x003D5,0x003D7); (0x003D9,0x003D9); (0x003DB,0x003DB); (0x003DD,0x003DD); (0x003DF,0x003DF); (0x003E1,0x003E1); (0x003E3,0x003E3); (0x003E5,0x003E5); (0x003E7,0x003E7); (0x003E9,0x003E9); (0x003EB,0x003EB); (0x003ED,0x003ED); (0x003EF,0x003F3); (0x003F5,0x003F5); (0x003F8,0x003F8); (0x003FB,0x003FC); (0x00430,0x0045F); (0x00461,0x00461); (0x00463,0x00463); (0x00465,0x00465); (0x00467,0x00467); (0x00469,0x00469); (0x0046B,0x0046B); (0x0046D,0x0046D); (0x0046F,0x0046F); (0x00471,0x00471); (0x00473,0x00473); (0x00475,0x00475); (0x00477,0x00477); (0x00479,0x00479); (0x0047B,0x0047B); (0x0047D,0x0047D); (0x0047F,0x0047F); (0x00481,0x00481); (0x0048B,0x0048B); (0x0048D,0x0048D); (0x0048F,0x0048F); (0x00491,0x00491); (0x00493,0x00493); (0x00495,0x00495); (0x00497,0x00497); (0x00499,0x00499); (0x0049B,0x0049B); (0x0049D,0x0049D); (0x0049F,0x0049F); (0x004A1,0x004A1); (0x004A3,0x004A3); (0x004A5,0x004A5); (0x004A7,0x004A7); (0x004A9,0x004A9); (0x004AB,0x004AB); (0x004AD,0x004AD); (0x004AF,0x004AF); (0x004B1,0x004B1); (0x004B3,0x004B3); (0x004B5,0x004B5); (0x004B7,0x004B7); (0x004B9,0x004B9); (0x004BB,0x004BB); (0x004BD,0x004BD); (0x004BF,0x004BF); (0x004C2,0x004C2); (0x004C4,0x004C4); (0x004C6,0x004C6); (0x004C8,0x004C8); (0x004CA,0x004CA); (0x004CC,0x004CC); (0x004CE,0x004CF); (0x004D1,0x004D1); (0x004D3,0x004D3); (0x004D5,0x004D5); (0x004D7,0x004D7); (0x004D9,0x004D9); (0x004DB,0x004DB); (0x004DD,0x004DD); (0x004DF,0x004DF); (0x004E1,0x004E1); (0x004E3,0x004E3); (0x004E5,0x004E5); (0x004E7,0x004E7); (0x004E9,0x004E9); (0x004EB,0x004EB); (0x004ED,0x004ED); (0x004EF,0x004EF); (0x004F1,0x004F1); (0x004F3,0x004F3); (0x004F5,0x004F5); (0x004F7,0x004F7); (0x004F9,0x004F9); (0x004FB,0x004FB); (0x004FD,0x004FD); (0x004FF,0x004FF); (0x00501,0x00501); (0x00503,0x00503); (0x00505,0x00505); (0x00507,0x00507); (0x00509,0x00509); (0x0050B,0x0050B); (0x0050D,0x0050D); (0x0050F,0x0050F); (0x00511,0x00511); (0x00513,0x00513); (0x00515,0x00515); (0x00517,0x00517); (0x00519,0x00519); (0x0051B,0x0051B); (0x0051D,0x0051D); (0x0051F,0x0051F); (0x00521,0x00521); (0x00523,0x00523); (0x00525,0x00525); (0x00527,0x00527); (0x00529,0x00529); (0x0052B,0x0052B); (0x0052D,0x0052D); (0x0052F,0x0052F); (0x00561,0x00587); (0x013F8,0x013FD); (0x01C80,0x01C88); (0x01D00,0x01D2B); (0x01D6B,0x01D77); (0x01D79,0x01D9A); (0x01E01,0x01E01); (0x01E03,0x01E03); (0x01E05,0x01E05); (0x01E07,0x01E07); (0x01E09,0x01E09); (0x01E0B,0x01E0B); (0x01E0D,0x01E0D); (0x01E0F,0x01E0F); (0x01E11,0x01E11); (0x01E13,0x01E13); (0x01E15,0x01E15); (0x01E17,0x01E17); (0x01E19,0x01E19); (0x01E1B,0x01E1B); (0x01E1D,0x01E1D); (0x01E1F,0x01E1F); (0x01E21,0x01E21); (0x01E23,0x01E23); (0x01E25,0x01E25); (0x01E27,0x01E27); (0x01E29,0x01E29); (0x01E2B,0x01E2B); (0x01E2D,0x01E2D); (0x01E2F,0x01E2F); (0x01E31,0x01E31); (0x01E33,0x01E33); (0x01E35,0x01E35); (0x01E37,0x01E37); (0x01E39,0x01E39); (0x01E3B,0x01E3B); (0x01E3D,0x01E3D); (0x01E3F,0x01E3F); (0x01E41,0x01E41); (0x01E43,0x01E43); (0x01E45,0x01E45); (0x01E47,0x01E47); (0x01E49,0x01E49); (0x01E4B,0x01E4B); (0x01E4D,0x01E4D); (0x01E4F,0x01E4F); (0x01E51,0x01E51); (0x01E53,0x01E53); (0x01E55,0x01E55); (0x01E57,0x01E57); (0x01E59,0x01E59); (0x01E5B,0x01E5B); (0x01E5D,0x01E5D); (0x01E5F,0x01E5F); (0x01E61,0x01E61); (0x01E63,0x01E63); (0x01E65,0x01E65); (0x01E67,0x01E67); (0x01E69,0x01E69); (0x01E6B,0x01E6B); (0x01E6D,0x01E6D); (0x01E6F,0x01E6F); (0x01E71,0x01E71); (0x01E73,0x01E73); (0x01E75,0x01E75); (0x01E77,0x01E77); (0x01E79,0x01E79); (0x01E7B,0x01E7B); (0x01E7D,0x01E7D); (0x01E7F,0x01E7F); (0x01E81,0x01E81); (0x01E83,0x01E83); (0x01E85,0x01E85); (0x01E87,0x01E87); (0x01E89,0x01E89); (0x01E8B,0x01E8B); (0x01E8D,0x01E8D); (0x01E8F,0x01E8F); (0x01E91,0x01E91); (0x01E93,0x01E93); (0x01E95,0x01E9D); (0x01E9F,0x01E9F); (0x01EA1,0x01EA1); (0x01EA3,0x01EA3); (0x01EA5,0x01EA5); (0x01EA7,0x01EA7); (0x01EA9,0x01EA9); (0x01EAB,0x01EAB); (0x01EAD,0x01EAD); (0x01EAF,0x01EAF); (0x01EB1,0x01EB1); (0x01EB3,0x01EB3); (0x01EB5,0x01EB5); (0x01EB7,0x01EB7); (0x01EB9,0x01EB9); (0x01EBB,0x01EBB); (0x01EBD,0x01EBD); (0x01EBF,0x01EBF); (0x01EC1,0x01EC1); (0x01EC3,0x01EC3); (0x01EC5,0x01EC5); (0x01EC7,0x01EC7); (0x01EC9,0x01EC9); (0x01ECB,0x01ECB); (0x01ECD,0x01ECD); (0x01ECF,0x01ECF); (0x01ED1,0x01ED1); (0x01ED3,0x01ED3); (0x01ED5,0x01ED5); (0x01ED7,0x01ED7); (0x01ED9,0x01ED9); (0x01EDB,0x01EDB); (0x01EDD,0x01EDD); (0x01EDF,0x01EDF); (0x01EE1,0x01EE1); (0x01EE3,0x01EE3); (0x01EE5,0x01EE5); (0x01EE7,0x01EE7); (0x01EE9,0x01EE9); (0x01EEB,0x01EEB); (0x01EED,0x01EED); (0x01EEF,0x01EEF); (0x01EF1,0x01EF1); (0x01EF3,0x01EF3); (0x01EF5,0x01EF5); (0x01EF7,0x01EF7); (0x01EF9,0x01EF9); (0x01EFB,0x01EFB); (0x01EFD,0x01EFD); (0x01EFF,0x01F07); (0x01F10,0x01F15); (0x01F20,0x01F27); (0x01F30,0x01F37); (0x01F40,0x01F45); (0x01F50,0x01F57); (0x01F60,0x01F67); (0x01F70,0x01F7D); (0x01F80,0x01F87); (0x01F90,0x01F97); (0x01FA0,0x01FA7); (0x01FB0,0x01FB4); (0x01FB6,0x01FB7); (0x01FBE,0x01FBE); (0x01FC2,0x01FC4); (0x01FC6,0x01FC7); (0x01FD0,0x01FD3); (0x01FD6,0x01FD7); (0x01FE0,0x01FE7); (0x01FF2,0x01FF4); (0x01FF6,0x01FF7); (0x0210A,0x0210A); (0x0210E,0x0210F); (0x02113,0x02113); (0x0212F,0x0212F); (0x02134,0x02134); (0x02139,0x02139); (0x0213C,0x0213D); (0x02146,0x02149); (0x0214E,0x0214E); (0x02184,0x02184); (0x02C30,0x02C5E); (0x02C61,0x02C61); (0x02C65,0x02C66); (0x02C68,0x02C68); (0x02C6A,0x02C6A); (0x02C6C,0x02C6C); (0x02C71,0x02C71); (0x02C73,0x02C74); (0x02C76,0x02C7B); (0x02C81,0x02C81); (0x02C83,0x02C83); (0x02C85,0x02C85); (0x02C87,0x02C87); (0x02C89,0x02C89); (0x02C8B,0x02C8B); (0x02C8D,0x02C8D); (0x02C8F,0x02C8F); (0x02C91,0x02C91); (0x02C93,0x02C93); (0x02C95,0x02C95); (0x02C97,0x02C97); (0x02C99,0x02C99); (0x02C9B,0x02C9B); (0x02C9D,0x02C9D); (0x02C9F,0x02C9F); (0x02CA1,0x02CA1); (0x02CA3,0x02CA3); (0x02CA5,0x02CA5); (0x02CA7,0x02CA7); (0x02CA9,0x02CA9); (0x02CAB,0x02CAB); (0x02CAD,0x02CAD); (0x02CAF,0x02CAF); (0x02CB1,0x02CB1); (0x02CB3,0x02CB3); (0x02CB5,0x02CB5); (0x02CB7,0x02CB7); (0x02CB9,0x02CB9); (0x02CBB,0x02CBB); (0x02CBD,0x02CBD); (0x02CBF,0x02CBF); (0x02CC1,0x02CC1); (0x02CC3,0x02CC3); (0x02CC5,0x02CC5); (0x02CC7,0x02CC7); (0x02CC9,0x02CC9); (0x02CCB,0x02CCB); (0x02CCD,0x02CCD); (0x02CCF,0x02CCF); (0x02CD1,0x02CD1); (0x02CD3,0x02CD3); (0x02CD5,0x02CD5); (0x02CD7,0x02CD7); (0x02CD9,0x02CD9); (0x02CDB,0x02CDB); (0x02CDD,0x02CDD); (0x02CDF,0x02CDF); (0x02CE1,0x02CE1); (0x02CE3,0x02CE4); (0x02CEC,0x02CEC); (0x02CEE,0x02CEE); (0x02CF3,0x02CF3); (0x02D00,0x02D25); (0x02D27,0x02D27); (0x02D2D,0x02D2D); (0x0A641,0x0A641); (0x0A643,0x0A643); (0x0A645,0x0A645); (0x0A647,0x0A647); (0x0A649,0x0A649); (0x0A64B,0x0A64B); (0x0A64D,0x0A64D); (0x0A64F,0x0A64F); (0x0A651,0x0A651); (0x0A653,0x0A653); (0x0A655,0x0A655); (0x0A657,0x0A657); (0x0A659,0x0A659); (0x0A65B,0x0A65B); (0x0A65D,0x0A65D); (0x0A65F,0x0A65F); (0x0A661,0x0A661); (0x0A663,0x0A663); (0x0A665,0x0A665); (0x0A667,0x0A667); (0x0A669,0x0A669); (0x0A66B,0x0A66B); (0x0A66D,0x0A66D); (0x0A681,0x0A681); (0x0A683,0x0A683); (0x0A685,0x0A685); (0x0A687,0x0A687); (0x0A689,0x0A689); (0x0A68B,0x0A68B); (0x0A68D,0x0A68D); (0x0A68F,0x0A68F); (0x0A691,0x0A691); (0x0A693,0x0A693); (0x0A695,0x0A695); (0x0A697,0x0A697); (0x0A699,0x0A699); (0x0A69B,0x0A69B); (0x0A723,0x0A723); (0x0A725,0x0A725); (0x0A727,0x0A727); (0x0A729,0x0A729); (0x0A72B,0x0A72B); (0x0A72D,0x0A72D); (0x0A72F,0x0A731); (0x0A733,0x0A733); (0x0A735,0x0A735); (0x0A737,0x0A737); (0x0A739,0x0A739); (0x0A73B,0x0A73B); (0x0A73D,0x0A73D); (0x0A73F,0x0A73F); (0x0A741,0x0A741); (0x0A743,0x0A743); (0x0A745,0x0A745); (0x0A747,0x0A747); (0x0A749,0x0A749); (0x0A74B,0x0A74B); (0x0A74D,0x0A74D); (0x0A74F,0x0A74F); (0x0A751,0x0A751); (0x0A753,0x0A753); (0x0A755,0x0A755); (0x0A757,0x0A757); (0x0A759,0x0A759); (0x0A75B,0x0A75B); (0x0A75D,0x0A75D); (0x0A75F,0x0A75F); (0x0A761,0x0A761); (0x0A763,0x0A763); (0x0A765,0x0A765); (0x0A767,0x0A767); (0x0A769,0x0A769); (0x0A76B,0x0A76B); (0x0A76D,0x0A76D); (0x0A76F,0x0A76F); (0x0A771,0x0A778); (0x0A77A,0x0A77A); (0x0A77C,0x0A77C); (0x0A77F,0x0A77F); (0x0A781,0x0A781); (0x0A783,0x0A783); (0x0A785,0x0A785); (0x0A787,0x0A787); (0x0A78C,0x0A78C); (0x0A78E,0x0A78E); (0x0A791,0x0A791); (0x0A793,0x0A795); (0x0A797,0x0A797); (0x0A799,0x0A799); (0x0A79B,0x0A79B); (0x0A79D,0x0A79D); (0x0A79F,0x0A79F); (0x0A7A1,0x0A7A1); (0x0A7A3,0x0A7A3); (0x0A7A5,0x0A7A5); (0x0A7A7,0x0A7A7); (0x0A7A9,0x0A7A9); (0x0A7B5,0x0A7B5); (0x0A7B7,0x0A7B7); (0x0A7FA,0x0A7FA); (0x0AB30,0x0AB5A); (0x0AB60,0x0AB65); (0x0AB70,0x0ABBF); (0x0FB00,0x0FB06); (0x0FB13,0x0FB17); (0x0FF41,0x0FF5A); (0x10428,0x1044F); (0x104D8,0x104FB); (0x10CC0,0x10CF2); (0x118C0,0x118DF); (0x1D41A,0x1D433); (0x1D44E,0x1D454); (0x1D456,0x1D467); (0x1D482,0x1D49B); (0x1D4B6,0x1D4B9); (0x1D4BB,0x1D4BB); (0x1D4BD,0x1D4C3); (0x1D4C5,0x1D4CF); (0x1D4EA,0x1D503); (0x1D51E,0x1D537); (0x1D552,0x1D56B); (0x1D586,0x1D59F); (0x1D5BA,0x1D5D3); (0x1D5EE,0x1D607); (0x1D622,0x1D63B); (0x1D656,0x1D66F); (0x1D68A,0x1D6A5); (0x1D6C2,0x1D6DA); (0x1D6DC,0x1D6E1); (0x1D6FC,0x1D714); (0x1D716,0x1D71B); (0x1D736,0x1D74E); (0x1D750,0x1D755); (0x1D770,0x1D788); (0x1D78A,0x1D78F); (0x1D7AA,0x1D7C2); (0x1D7C4,0x1D7C9); (0x1D7CB,0x1D7CB) ] (* Letter, Titlecase *) let lt = [ (0x001C5,0x001C5); (0x001C8,0x001C8); (0x001CB,0x001CB); (0x001F2,0x001F2); (0x01F88,0x01F8F); (0x01F98,0x01F9F); (0x01FA8,0x01FAF); (0x01FBC,0x01FBC); (0x01FCC,0x01FCC) ] (* Mark, Non-Spacing *) let mn = [ (0x00300,0x0036F); (0x00483,0x00487); (0x00591,0x005BD); (0x005BF,0x005BF); (0x005C1,0x005C2); (0x005C4,0x005C5); (0x005C7,0x005C7); (0x00610,0x0061A); (0x0064B,0x0065F); (0x00670,0x00670); (0x006D6,0x006DC); (0x006DF,0x006E4); (0x006E7,0x006E8); (0x006EA,0x006ED); (0x00711,0x00711); (0x00730,0x0074A); (0x007A6,0x007B0); (0x007EB,0x007F3); (0x00816,0x00819); (0x0081B,0x00823); (0x00825,0x00827); (0x00829,0x0082D); (0x00859,0x0085B); (0x008D4,0x008E1); (0x008E3,0x00902); (0x0093A,0x0093A); (0x0093C,0x0093C); (0x00941,0x00948); (0x0094D,0x0094D); (0x00951,0x00957); (0x00962,0x00963); (0x00981,0x00981); (0x009BC,0x009BC); (0x009C1,0x009C4); (0x009CD,0x009CD); (0x009E2,0x009E3); (0x00A01,0x00A02); (0x00A3C,0x00A3C); (0x00A41,0x00A42); (0x00A47,0x00A48); (0x00A4B,0x00A4D); (0x00A51,0x00A51); (0x00A70,0x00A71); (0x00A75,0x00A75); (0x00A81,0x00A82); (0x00ABC,0x00ABC); (0x00AC1,0x00AC5); (0x00AC7,0x00AC8); (0x00ACD,0x00ACD); (0x00AE2,0x00AE3); (0x00B01,0x00B01); (0x00B3C,0x00B3C); (0x00B3F,0x00B3F); (0x00B41,0x00B44); (0x00B4D,0x00B4D); (0x00B56,0x00B56); (0x00B62,0x00B63); (0x00B82,0x00B82); (0x00BC0,0x00BC0); (0x00BCD,0x00BCD); (0x00C00,0x00C00); (0x00C3E,0x00C40); (0x00C46,0x00C48); (0x00C4A,0x00C4D); (0x00C55,0x00C56); (0x00C62,0x00C63); (0x00C81,0x00C81); (0x00CBC,0x00CBC); (0x00CBF,0x00CBF); (0x00CC6,0x00CC6); (0x00CCC,0x00CCD); (0x00CE2,0x00CE3); (0x00D01,0x00D01); (0x00D41,0x00D44); (0x00D4D,0x00D4D); (0x00D62,0x00D63); (0x00DCA,0x00DCA); (0x00DD2,0x00DD4); (0x00DD6,0x00DD6); (0x00E31,0x00E31); (0x00E34,0x00E3A); (0x00E47,0x00E4E); (0x00EB1,0x00EB1); (0x00EB4,0x00EB9); (0x00EBB,0x00EBC); (0x00EC8,0x00ECD); (0x00F18,0x00F19); (0x00F35,0x00F35); (0x00F37,0x00F37); (0x00F39,0x00F39); (0x00F71,0x00F7E); (0x00F80,0x00F84); (0x00F86,0x00F87); (0x00F8D,0x00F97); (0x00F99,0x00FBC); (0x00FC6,0x00FC6); (0x0102D,0x01030); (0x01032,0x01037); (0x01039,0x0103A); (0x0103D,0x0103E); (0x01058,0x01059); (0x0105E,0x01060); (0x01071,0x01074); (0x01082,0x01082); (0x01085,0x01086); (0x0108D,0x0108D); (0x0109D,0x0109D); (0x0135D,0x0135F); (0x01712,0x01714); (0x01732,0x01734); (0x01752,0x01753); (0x01772,0x01773); (0x017B4,0x017B5); (0x017B7,0x017BD); (0x017C6,0x017C6); (0x017C9,0x017D3); (0x017DD,0x017DD); (0x0180B,0x0180D); (0x01885,0x01886); (0x018A9,0x018A9); (0x01920,0x01922); (0x01927,0x01928); (0x01932,0x01932); (0x01939,0x0193B); (0x01A17,0x01A18); (0x01A1B,0x01A1B); (0x01A56,0x01A56); (0x01A58,0x01A5E); (0x01A60,0x01A60); (0x01A62,0x01A62); (0x01A65,0x01A6C); (0x01A73,0x01A7C); (0x01A7F,0x01A7F); (0x01AB0,0x01ABD); (0x01B00,0x01B03); (0x01B34,0x01B34); (0x01B36,0x01B3A); (0x01B3C,0x01B3C); (0x01B42,0x01B42); (0x01B6B,0x01B73); (0x01B80,0x01B81); (0x01BA2,0x01BA5); (0x01BA8,0x01BA9); (0x01BAB,0x01BAD); (0x01BE6,0x01BE6); (0x01BE8,0x01BE9); (0x01BED,0x01BED); (0x01BEF,0x01BF1); (0x01C2C,0x01C33); (0x01C36,0x01C37); (0x01CD0,0x01CD2); (0x01CD4,0x01CE0); (0x01CE2,0x01CE8); (0x01CED,0x01CED); (0x01CF4,0x01CF4); (0x01CF8,0x01CF9); (0x01DC0,0x01DF5); (0x01DFB,0x01DFF); (0x020D0,0x020DC); (0x020E1,0x020E1); (0x020E5,0x020F0); (0x02CEF,0x02CF1); (0x02D7F,0x02D7F); (0x02DE0,0x02DFF); (0x0302A,0x0302D); (0x03099,0x0309A); (0x0A66F,0x0A66F); (0x0A674,0x0A67D); (0x0A69E,0x0A69F); (0x0A6F0,0x0A6F1); (0x0A802,0x0A802); (0x0A806,0x0A806); (0x0A80B,0x0A80B); (0x0A825,0x0A826); (0x0A8C4,0x0A8C5); (0x0A8E0,0x0A8F1); (0x0A926,0x0A92D); (0x0A947,0x0A951); (0x0A980,0x0A982); (0x0A9B3,0x0A9B3); (0x0A9B6,0x0A9B9); (0x0A9BC,0x0A9BC); (0x0A9E5,0x0A9E5); (0x0AA29,0x0AA2E); (0x0AA31,0x0AA32); (0x0AA35,0x0AA36); (0x0AA43,0x0AA43); (0x0AA4C,0x0AA4C); (0x0AA7C,0x0AA7C); (0x0AAB0,0x0AAB0); (0x0AAB2,0x0AAB4); (0x0AAB7,0x0AAB8); (0x0AABE,0x0AABF); (0x0AAC1,0x0AAC1); (0x0AAEC,0x0AAED); (0x0AAF6,0x0AAF6); (0x0ABE5,0x0ABE5); (0x0ABE8,0x0ABE8); (0x0ABED,0x0ABED); (0x0FB1E,0x0FB1E); (0x0FE00,0x0FE0F); (0x0FE20,0x0FE2F); (0x101FD,0x101FD); (0x102E0,0x102E0); (0x10376,0x1037A); (0x10A01,0x10A03); (0x10A05,0x10A06); (0x10A0C,0x10A0F); (0x10A38,0x10A3A); (0x10A3F,0x10A3F); (0x10AE5,0x10AE6); (0x11001,0x11001); (0x11038,0x11046); (0x1107F,0x11081); (0x110B3,0x110B6); (0x110B9,0x110BA); (0x11100,0x11102); (0x11127,0x1112B); (0x1112D,0x11134); (0x11173,0x11173); (0x11180,0x11181); (0x111B6,0x111BE); (0x111CA,0x111CC); (0x1122F,0x11231); (0x11234,0x11234); (0x11236,0x11237); (0x1123E,0x1123E); (0x112DF,0x112DF); (0x112E3,0x112EA); (0x11300,0x11301); (0x1133C,0x1133C); (0x11340,0x11340); (0x11366,0x1136C); (0x11370,0x11374); (0x11438,0x1143F); (0x11442,0x11444); (0x11446,0x11446); (0x114B3,0x114B8); (0x114BA,0x114BA); (0x114BF,0x114C0); (0x114C2,0x114C3); (0x115B2,0x115B5); (0x115BC,0x115BD); (0x115BF,0x115C0); (0x115DC,0x115DD); (0x11633,0x1163A); (0x1163D,0x1163D); (0x1163F,0x11640); (0x116AB,0x116AB); (0x116AD,0x116AD); (0x116B0,0x116B5); (0x116B7,0x116B7); (0x1171D,0x1171F); (0x11722,0x11725); (0x11727,0x1172B); (0x11C30,0x11C36); (0x11C38,0x11C3D); (0x11C3F,0x11C3F); (0x11C92,0x11CA7); (0x11CAA,0x11CB0); (0x11CB2,0x11CB3); (0x11CB5,0x11CB6); (0x16AF0,0x16AF4); (0x16B30,0x16B36); (0x16F8F,0x16F92); (0x1BC9D,0x1BC9E); (0x1D167,0x1D169); (0x1D17B,0x1D182); (0x1D185,0x1D18B); (0x1D1AA,0x1D1AD); (0x1D242,0x1D244); (0x1DA00,0x1DA36); (0x1DA3B,0x1DA6C); (0x1DA75,0x1DA75); (0x1DA84,0x1DA84); (0x1DA9B,0x1DA9F); (0x1DAA1,0x1DAAF); (0x1E000,0x1E006); (0x1E008,0x1E018); (0x1E01B,0x1E021); (0x1E023,0x1E024); (0x1E026,0x1E02A); (0x1E8D0,0x1E8D6); (0x1E944,0x1E94A) ] (* Mark, Spacing Combining *) let mc = [ (0x00903,0x00903); (0x0093B,0x0093B); (0x0093E,0x00940); (0x00949,0x0094C); (0x0094E,0x0094F); (0x00982,0x00983); (0x009BE,0x009C0); (0x009C7,0x009C8); (0x009CB,0x009CC); (0x009D7,0x009D7); (0x00A03,0x00A03); (0x00A3E,0x00A40); (0x00A83,0x00A83); (0x00ABE,0x00AC0); (0x00AC9,0x00AC9); (0x00ACB,0x00ACC); (0x00B02,0x00B03); (0x00B3E,0x00B3E); (0x00B40,0x00B40); (0x00B47,0x00B48); (0x00B4B,0x00B4C); (0x00B57,0x00B57); (0x00BBE,0x00BBF); (0x00BC1,0x00BC2); (0x00BC6,0x00BC8); (0x00BCA,0x00BCC); (0x00BD7,0x00BD7); (0x00C01,0x00C03); (0x00C41,0x00C44); (0x00C82,0x00C83); (0x00CBE,0x00CBE); (0x00CC0,0x00CC4); (0x00CC7,0x00CC8); (0x00CCA,0x00CCB); (0x00CD5,0x00CD6); (0x00D02,0x00D03); (0x00D3E,0x00D40); (0x00D46,0x00D48); (0x00D4A,0x00D4C); (0x00D57,0x00D57); (0x00D82,0x00D83); (0x00DCF,0x00DD1); (0x00DD8,0x00DDF); (0x00DF2,0x00DF3); (0x00F3E,0x00F3F); (0x00F7F,0x00F7F); (0x0102B,0x0102C); (0x01031,0x01031); (0x01038,0x01038); (0x0103B,0x0103C); (0x01056,0x01057); (0x01062,0x01064); (0x01067,0x0106D); (0x01083,0x01084); (0x01087,0x0108C); (0x0108F,0x0108F); (0x0109A,0x0109C); (0x017B6,0x017B6); (0x017BE,0x017C5); (0x017C7,0x017C8); (0x01923,0x01926); (0x01929,0x0192B); (0x01930,0x01931); (0x01933,0x01938); (0x01A19,0x01A1A); (0x01A55,0x01A55); (0x01A57,0x01A57); (0x01A61,0x01A61); (0x01A63,0x01A64); (0x01A6D,0x01A72); (0x01B04,0x01B04); (0x01B35,0x01B35); (0x01B3B,0x01B3B); (0x01B3D,0x01B41); (0x01B43,0x01B44); (0x01B82,0x01B82); (0x01BA1,0x01BA1); (0x01BA6,0x01BA7); (0x01BAA,0x01BAA); (0x01BE7,0x01BE7); (0x01BEA,0x01BEC); (0x01BEE,0x01BEE); (0x01BF2,0x01BF3); (0x01C24,0x01C2B); (0x01C34,0x01C35); (0x01CE1,0x01CE1); (0x01CF2,0x01CF3); (0x0302E,0x0302F); (0x0A823,0x0A824); (0x0A827,0x0A827); (0x0A880,0x0A881); (0x0A8B4,0x0A8C3); (0x0A952,0x0A953); (0x0A983,0x0A983); (0x0A9B4,0x0A9B5); (0x0A9BA,0x0A9BB); (0x0A9BD,0x0A9C0); (0x0AA2F,0x0AA30); (0x0AA33,0x0AA34); (0x0AA4D,0x0AA4D); (0x0AA7B,0x0AA7B); (0x0AA7D,0x0AA7D); (0x0AAEB,0x0AAEB); (0x0AAEE,0x0AAEF); (0x0AAF5,0x0AAF5); (0x0ABE3,0x0ABE4); (0x0ABE6,0x0ABE7); (0x0ABE9,0x0ABEA); (0x0ABEC,0x0ABEC); (0x11000,0x11000); (0x11002,0x11002); (0x11082,0x11082); (0x110B0,0x110B2); (0x110B7,0x110B8); (0x1112C,0x1112C); (0x11182,0x11182); (0x111B3,0x111B5); (0x111BF,0x111C0); (0x1122C,0x1122E); (0x11232,0x11233); (0x11235,0x11235); (0x112E0,0x112E2); (0x11302,0x11303); (0x1133E,0x1133F); (0x11341,0x11344); (0x11347,0x11348); (0x1134B,0x1134D); (0x11357,0x11357); (0x11362,0x11363); (0x11435,0x11437); (0x11440,0x11441); (0x11445,0x11445); (0x114B0,0x114B2); (0x114B9,0x114B9); (0x114BB,0x114BE); (0x114C1,0x114C1); (0x115AF,0x115B1); (0x115B8,0x115BB); (0x115BE,0x115BE); (0x11630,0x11632); (0x1163B,0x1163C); (0x1163E,0x1163E); (0x116AC,0x116AC); (0x116AE,0x116AF); (0x116B6,0x116B6); (0x11720,0x11721); (0x11726,0x11726); (0x11C2F,0x11C2F); (0x11C3E,0x11C3E); (0x11CA9,0x11CA9); (0x11CB1,0x11CB1); (0x11CB4,0x11CB4); (0x16F51,0x16F7E); (0x1D165,0x1D166) ] (* Mark, Enclosing *) let me = [ (0x00488,0x00489); (0x01ABE,0x01ABE); (0x020DD,0x020E0); (0x020E2,0x020E4) ] (* Number, Decimal Digit *) let nd = [ (0x00030,0x00039); (0x00660,0x00669); (0x006F0,0x006F9); (0x007C0,0x007C9); (0x00966,0x0096F); (0x009E6,0x009EF); (0x00A66,0x00A6F); (0x00AE6,0x00AEF); (0x00B66,0x00B6F); (0x00BE6,0x00BEF); (0x00C66,0x00C6F); (0x00CE6,0x00CEF); (0x00D66,0x00D6F); (0x00DE6,0x00DEF); (0x00E50,0x00E59); (0x00ED0,0x00ED9); (0x00F20,0x00F29); (0x01040,0x01049); (0x01090,0x01099); (0x017E0,0x017E9); (0x01810,0x01819); (0x01946,0x0194F); (0x019D0,0x019D9); (0x01A80,0x01A89); (0x01A90,0x01A99); (0x01B50,0x01B59); (0x01BB0,0x01BB9); (0x01C40,0x01C49); (0x01C50,0x01C59); (0x0A620,0x0A629); (0x0A8D0,0x0A8D9); (0x0A900,0x0A909); (0x0A9D0,0x0A9D9); (0x0A9F0,0x0A9F9); (0x0AA50,0x0AA59); (0x0ABF0,0x0ABF9); (0x0FF10,0x0FF19); (0x104A0,0x104A9); (0x11066,0x1106F); (0x110F0,0x110F9); (0x11136,0x1113F); (0x111D0,0x111D9); (0x112F0,0x112F9); (0x11450,0x11459); (0x114D0,0x114D9); (0x11650,0x11659); (0x116C0,0x116C9); (0x11730,0x11739); (0x118E0,0x118E9); (0x11C50,0x11C59); (0x16A60,0x16A69); (0x16B50,0x16B59); (0x1D7CE,0x1D7FF) ] (* Number, Letter *) let nl = [ (0x016EE,0x016F0); (0x02160,0x02182); (0x02185,0x02188); (0x03007,0x03007); (0x03021,0x03029); (0x03038,0x0303A); (0x0A6E6,0x0A6EF); (0x10140,0x10174); (0x10341,0x10341); (0x1034A,0x1034A); (0x103D1,0x103D5) ] (* Number, Other *) let no = [ (0x000B2,0x000B3); (0x000B9,0x000B9); (0x000BC,0x000BE); (0x009F4,0x009F9); (0x00B72,0x00B77); (0x00BF0,0x00BF2); (0x00C78,0x00C7E); (0x00D58,0x00D5E); (0x00D70,0x00D78); (0x00F2A,0x00F33); (0x01369,0x0137C); (0x017F0,0x017F9); (0x019DA,0x019DA); (0x02070,0x02070); (0x02074,0x02079); (0x02080,0x02089); (0x02150,0x0215F); (0x02189,0x02189); (0x02460,0x0249B); (0x024EA,0x024FF); (0x02776,0x02793); (0x02CFD,0x02CFD); (0x03192,0x03195); (0x03220,0x03229); (0x03248,0x0324F); (0x03251,0x0325F); (0x03280,0x03289); (0x032B1,0x032BF); (0x0A830,0x0A835); (0x10107,0x10133); (0x10175,0x10178); (0x1018A,0x1018B); (0x102E1,0x102FB); (0x10320,0x10323); (0x10858,0x1085F); (0x10879,0x1087F); (0x108A7,0x108AF); (0x108FB,0x108FF); (0x10916,0x1091B); (0x109BC,0x109BD); (0x109C0,0x109CF); (0x109D2,0x109FF); (0x10A40,0x10A47); (0x10A7D,0x10A7E); (0x10A9D,0x10A9F); (0x10AEB,0x10AEF); (0x10B58,0x10B5F); (0x10B78,0x10B7F); (0x10BA9,0x10BAF); (0x10CFA,0x10CFF); (0x10E60,0x10E7E); (0x11052,0x11065); (0x111E1,0x111F4); (0x1173A,0x1173B); (0x118EA,0x118F2); (0x11C5A,0x11C6C); (0x16B5B,0x16B61); (0x1D360,0x1D371); (0x1E8C7,0x1E8CF) ] (* Separator, Space *) let zs = [ (0x00020,0x00020); (0x000A0,0x000A0); (0x01680,0x01680); (0x02000,0x0200A); (0x0202F,0x0202F); (0x0205F,0x0205F) ] (* Separator, Line *) let zl = [ ] (* Separator, Paragraph *) let zp = [ ] (* Other, Control *) let cc = [ (0x00000,0x0001F) ] (* Other, Format *) let cf = [ (0x000AD,0x000AD); (0x00600,0x00605); (0x0061C,0x0061C); (0x006DD,0x006DD); (0x0070F,0x0070F); (0x008E2,0x008E2); (0x0180E,0x0180E); (0x0200B,0x0200F); (0x0202A,0x0202E); (0x02060,0x02064); (0x02066,0x0206F); (0x0FEFF,0x0FEFF); (0x0FFF9,0x0FFFB); (0x110BD,0x110BD); (0x1BCA0,0x1BCA3); (0x1D173,0x1D17A); (0xE0001,0xE0001) ] (* Other, Surrogate *) let cs = [ ] (* Other, Private Use *) let co = [ (0x0E000,0x0F8FF); (0xF0000,0xFFFFD) ] (* Other, Not Assigned *) let cn = [ (0x00378,0x00379); (0x00380,0x00383); (0x0038B,0x0038B); (0x0038D,0x0038D); (0x003A2,0x003A2); (0x00530,0x00530); (0x00557,0x00558); (0x00560,0x00560); (0x00588,0x00588); (0x0058B,0x0058C); (0x00590,0x00590); (0x005C8,0x005CF); (0x005EB,0x005EF); (0x005F5,0x005FF); (0x0061D,0x0061D); (0x0070E,0x0070E); (0x0074B,0x0074C); (0x007B2,0x007BF); (0x007FB,0x007FF); (0x0082E,0x0082F); (0x0083F,0x0083F); (0x0085C,0x0085D); (0x0085F,0x0089F); (0x008B5,0x008B5); (0x008BE,0x008D3); (0x00984,0x00984); (0x0098D,0x0098E); (0x00991,0x00992); (0x009A9,0x009A9); (0x009B1,0x009B1); (0x009B3,0x009B5); (0x009BA,0x009BB); (0x009C5,0x009C6); (0x009C9,0x009CA); (0x009CF,0x009D6); (0x009D8,0x009DB); (0x009DE,0x009DE); (0x009E4,0x009E5); (0x009FC,0x00A00); (0x00A04,0x00A04); (0x00A0B,0x00A0E); (0x00A11,0x00A12); (0x00A29,0x00A29); (0x00A31,0x00A31); (0x00A34,0x00A34); (0x00A37,0x00A37); (0x00A3A,0x00A3B); (0x00A3D,0x00A3D); (0x00A43,0x00A46); (0x00A49,0x00A4A); (0x00A4E,0x00A50); (0x00A52,0x00A58); (0x00A5D,0x00A5D); (0x00A5F,0x00A65); (0x00A76,0x00A80); (0x00A84,0x00A84); (0x00A8E,0x00A8E); (0x00A92,0x00A92); (0x00AA9,0x00AA9); (0x00AB1,0x00AB1); (0x00AB4,0x00AB4); (0x00ABA,0x00ABB); (0x00AC6,0x00AC6); (0x00ACA,0x00ACA); (0x00ACE,0x00ACF); (0x00AD1,0x00ADF); (0x00AE4,0x00AE5); (0x00AF2,0x00AF8); (0x00AFA,0x00B00); (0x00B04,0x00B04); (0x00B0D,0x00B0E); (0x00B11,0x00B12); (0x00B29,0x00B29); (0x00B31,0x00B31); (0x00B34,0x00B34); (0x00B3A,0x00B3B); (0x00B45,0x00B46); (0x00B49,0x00B4A); (0x00B4E,0x00B55); (0x00B58,0x00B5B); (0x00B5E,0x00B5E); (0x00B64,0x00B65); (0x00B78,0x00B81); (0x00B84,0x00B84); (0x00B8B,0x00B8D); (0x00B91,0x00B91); (0x00B96,0x00B98); (0x00B9B,0x00B9B); (0x00B9D,0x00B9D); (0x00BA0,0x00BA2); (0x00BA5,0x00BA7); (0x00BAB,0x00BAD); (0x00BBA,0x00BBD); (0x00BC3,0x00BC5); (0x00BC9,0x00BC9); (0x00BCE,0x00BCF); (0x00BD1,0x00BD6); (0x00BD8,0x00BE5); (0x00BFB,0x00BFF); (0x00C04,0x00C04); (0x00C0D,0x00C0D); (0x00C11,0x00C11); (0x00C29,0x00C29); (0x00C3A,0x00C3C); (0x00C45,0x00C45); (0x00C49,0x00C49); (0x00C4E,0x00C54); (0x00C57,0x00C57); (0x00C5B,0x00C5F); (0x00C64,0x00C65); (0x00C70,0x00C77); (0x00C84,0x00C84); (0x00C8D,0x00C8D); (0x00C91,0x00C91); (0x00CA9,0x00CA9); (0x00CB4,0x00CB4); (0x00CBA,0x00CBB); (0x00CC5,0x00CC5); (0x00CC9,0x00CC9); (0x00CCE,0x00CD4); (0x00CD7,0x00CDD); (0x00CDF,0x00CDF); (0x00CE4,0x00CE5); (0x00CF0,0x00CF0); (0x00CF3,0x00D00); (0x00D04,0x00D04); (0x00D0D,0x00D0D); (0x00D11,0x00D11); (0x00D3B,0x00D3C); (0x00D45,0x00D45); (0x00D49,0x00D49); (0x00D50,0x00D53); (0x00D64,0x00D65); (0x00D80,0x00D81); (0x00D84,0x00D84); (0x00D97,0x00D99); (0x00DB2,0x00DB2); (0x00DBC,0x00DBC); (0x00DBE,0x00DBF); (0x00DC7,0x00DC9); (0x00DCB,0x00DCE); (0x00DD5,0x00DD5); (0x00DD7,0x00DD7); (0x00DE0,0x00DE5); (0x00DF0,0x00DF1); (0x00DF5,0x00E00); (0x00E3B,0x00E3E); (0x00E5C,0x00E80); (0x00E83,0x00E83); (0x00E85,0x00E86); (0x00E89,0x00E89); (0x00E8B,0x00E8C); (0x00E8E,0x00E93); (0x00E98,0x00E98); (0x00EA0,0x00EA0); (0x00EA4,0x00EA4); (0x00EA6,0x00EA6); (0x00EA8,0x00EA9); (0x00EAC,0x00EAC); (0x00EBA,0x00EBA); (0x00EBE,0x00EBF); (0x00EC5,0x00EC5); (0x00EC7,0x00EC7); (0x00ECE,0x00ECF); (0x00EDA,0x00EDB); (0x00EE0,0x00EFF); (0x00F48,0x00F48); (0x00F6D,0x00F70); (0x00F98,0x00F98); (0x00FBD,0x00FBD); (0x00FCD,0x00FCD); (0x00FDB,0x00FFF); (0x010C6,0x010C6); (0x010C8,0x010CC); (0x010CE,0x010CF); (0x01249,0x01249); (0x0124E,0x0124F); (0x01257,0x01257); (0x01259,0x01259); (0x0125E,0x0125F); (0x01289,0x01289); (0x0128E,0x0128F); (0x012B1,0x012B1); (0x012B6,0x012B7); (0x012BF,0x012BF); (0x012C1,0x012C1); (0x012C6,0x012C7); (0x012D7,0x012D7); (0x01311,0x01311); (0x01316,0x01317); (0x0135B,0x0135C); (0x0137D,0x0137F); (0x0139A,0x0139F); (0x013F6,0x013F7); (0x013FE,0x013FF); (0x0169D,0x0169F); (0x016F9,0x016FF); (0x0170D,0x0170D); (0x01715,0x0171F); (0x01737,0x0173F); (0x01754,0x0175F); (0x0176D,0x0176D); (0x01771,0x01771); (0x01774,0x0177F); (0x017DE,0x017DF); (0x017EA,0x017EF); (0x017FA,0x017FF); (0x0180F,0x0180F); (0x0181A,0x0181F); (0x01878,0x0187F); (0x018AB,0x018AF); (0x018F6,0x018FF); (0x0191F,0x0191F); (0x0192C,0x0192F); (0x0193C,0x0193F); (0x01941,0x01943); (0x0196E,0x0196F); (0x01975,0x0197F); (0x019AC,0x019AF); (0x019CA,0x019CF); (0x019DB,0x019DD); (0x01A1C,0x01A1D); (0x01A5F,0x01A5F); (0x01A7D,0x01A7E); (0x01A8A,0x01A8F); (0x01A9A,0x01A9F); (0x01AAE,0x01AAF); (0x01ABF,0x01AFF); (0x01B4C,0x01B4F); (0x01B7D,0x01B7F); (0x01BF4,0x01BFB); (0x01C38,0x01C3A); (0x01C4A,0x01C4C); (0x01C89,0x01CBF); (0x01CC8,0x01CCF); (0x01CF7,0x01CF7); (0x01CFA,0x01CFF); (0x01DF6,0x01DFA); (0x01F16,0x01F17); (0x01F1E,0x01F1F); (0x01F46,0x01F47); (0x01F4E,0x01F4F); (0x01F58,0x01F58); (0x01F5A,0x01F5A); (0x01F5C,0x01F5C); (0x01F5E,0x01F5E); (0x01F7E,0x01F7F); (0x01FB5,0x01FB5); (0x01FC5,0x01FC5); (0x01FD4,0x01FD5); (0x01FDC,0x01FDC); (0x01FF0,0x01FF1); (0x01FF5,0x01FF5); (0x01FFF,0x01FFF); (0x02065,0x02065); (0x02072,0x02073); (0x0208F,0x0208F); (0x0209D,0x0209F); (0x020BF,0x020CF); (0x020F1,0x020FF); (0x0218C,0x0218F); (0x023FF,0x023FF); (0x02427,0x0243F); (0x0244B,0x0245F); (0x02B74,0x02B75); (0x02B96,0x02B97); (0x02BBA,0x02BBC); (0x02BC9,0x02BC9); (0x02BD2,0x02BEB); (0x02BF0,0x02BFF); (0x02C2F,0x02C2F); (0x02C5F,0x02C5F); (0x02CF4,0x02CF8); (0x02D26,0x02D26); (0x02D28,0x02D2C); (0x02D2E,0x02D2F); (0x02D68,0x02D6E); (0x02D71,0x02D7E); (0x02D97,0x02D9F); (0x02DA7,0x02DA7); (0x02DAF,0x02DAF); (0x02DB7,0x02DB7); (0x02DBF,0x02DBF); (0x02DC7,0x02DC7); (0x02DCF,0x02DCF); (0x02DD7,0x02DD7); (0x02DDF,0x02DDF); (0x02E45,0x02E7F); (0x02E9A,0x02E9A); (0x02EF4,0x02EFF); (0x02FD6,0x02FEF); (0x02FFC,0x02FFF); (0x03040,0x03040); (0x03097,0x03098); (0x03100,0x03104); (0x0312E,0x03130); (0x0318F,0x0318F); (0x031BB,0x031BF); (0x031E4,0x031EF); (0x0321F,0x0321F); (0x032FF,0x032FF); (0x04DB6,0x04DBF); (0x09FD6,0x09FFF); (0x0A48D,0x0A48F); (0x0A4C7,0x0A4CF); (0x0A62C,0x0A63F); (0x0A6F8,0x0A6FF); (0x0A7AF,0x0A7AF); (0x0A7B8,0x0A7F6); (0x0A82C,0x0A82F); (0x0A83A,0x0A83F); (0x0A878,0x0A87F); (0x0A8C6,0x0A8CD); (0x0A8DA,0x0A8DF); (0x0A8FE,0x0A8FF); (0x0A954,0x0A95E); (0x0A97D,0x0A97F); (0x0A9CE,0x0A9CE); (0x0A9DA,0x0A9DD); (0x0A9FF,0x0A9FF); (0x0AA37,0x0AA3F); (0x0AA4E,0x0AA4F); (0x0AA5A,0x0AA5B); (0x0AAC3,0x0AADA); (0x0AAF7,0x0AB00); (0x0AB07,0x0AB08); (0x0AB0F,0x0AB10); (0x0AB17,0x0AB1F); (0x0AB27,0x0AB27); (0x0AB2F,0x0AB2F); (0x0AB66,0x0AB6F); (0x0ABEE,0x0ABEF); (0x0ABFA,0x0ABFF); (0x0D7A4,0x0D7AF); (0x0D7C7,0x0D7CA); (0x0D7FC,0x0D7FF); (0x0FA6E,0x0FA6F); (0x0FADA,0x0FAFF); (0x0FB07,0x0FB12); (0x0FB18,0x0FB1C); (0x0FB37,0x0FB37); (0x0FB3D,0x0FB3D); (0x0FB3F,0x0FB3F); (0x0FB42,0x0FB42); (0x0FB45,0x0FB45); (0x0FBC2,0x0FBD2); (0x0FD40,0x0FD4F); (0x0FD90,0x0FD91); (0x0FDC8,0x0FDEF); (0x0FDFE,0x0FDFF); (0x0FE1A,0x0FE1F); (0x0FE53,0x0FE53); (0x0FE67,0x0FE67); (0x0FE6C,0x0FE6F); (0x0FE75,0x0FE75); (0x0FEFD,0x0FEFE); (0x0FF00,0x0FF00); (0x0FFBF,0x0FFC1); (0x0FFC8,0x0FFC9); (0x0FFD0,0x0FFD1); (0x0FFD8,0x0FFD9); (0x0FFDD,0x0FFDF); (0x0FFE7,0x0FFE7); (0x0FFEF,0x0FFF8); (0x0FFFE,0x0FFFF); (0x1000C,0x1000C); (0x10027,0x10027); (0x1003B,0x1003B); (0x1003E,0x1003E); (0x1004E,0x1004F); (0x1005E,0x1007F); (0x100FB,0x100FF); (0x10103,0x10106); (0x10134,0x10136); (0x1018F,0x1018F); (0x1019C,0x1019F); (0x101A1,0x101CF); (0x101FE,0x1027F); (0x1029D,0x1029F); (0x102D1,0x102DF); (0x102FC,0x102FF); (0x10324,0x1032F); (0x1034B,0x1034F); (0x1037B,0x1037F); (0x1039E,0x1039E); (0x103C4,0x103C7); (0x103D6,0x103FF); (0x1049E,0x1049F); (0x104AA,0x104AF); (0x104D4,0x104D7); (0x104FC,0x104FF); (0x10528,0x1052F); (0x10564,0x1056E); (0x10570,0x105FF); (0x10737,0x1073F); (0x10756,0x1075F); (0x10768,0x107FF); (0x10806,0x10807); (0x10809,0x10809); (0x10836,0x10836); (0x10839,0x1083B); (0x1083D,0x1083E); (0x10856,0x10856); (0x1089F,0x108A6); (0x108B0,0x108DF); (0x108F3,0x108F3); (0x108F6,0x108FA); (0x1091C,0x1091E); (0x1093A,0x1093E); (0x10940,0x1097F); (0x109B8,0x109BB); (0x109D0,0x109D1); (0x10A04,0x10A04); (0x10A07,0x10A0B); (0x10A14,0x10A14); (0x10A18,0x10A18); (0x10A34,0x10A37); (0x10A3B,0x10A3E); (0x10A48,0x10A4F); (0x10A59,0x10A5F); (0x10AA0,0x10ABF); (0x10AE7,0x10AEA); (0x10AF7,0x10AFF); (0x10B36,0x10B38); (0x10B56,0x10B57); (0x10B73,0x10B77); (0x10B92,0x10B98); (0x10B9D,0x10BA8); (0x10BB0,0x10BFF); (0x10C49,0x10C7F); (0x10CB3,0x10CBF); (0x10CF3,0x10CF9); (0x10D00,0x10E5F); (0x10E7F,0x10FFF); (0x1104E,0x11051); (0x11070,0x1107E); (0x110C2,0x110CF); (0x110E9,0x110EF); (0x110FA,0x110FF); (0x11135,0x11135); (0x11144,0x1114F); (0x11177,0x1117F); (0x111CE,0x111CF); (0x111E0,0x111E0); (0x111F5,0x111FF); (0x11212,0x11212); (0x1123F,0x1127F); (0x11287,0x11287); (0x11289,0x11289); (0x1128E,0x1128E); (0x1129E,0x1129E); (0x112AA,0x112AF); (0x112EB,0x112EF); (0x112FA,0x112FF); (0x11304,0x11304); (0x1130D,0x1130E); (0x11311,0x11312); (0x11329,0x11329); (0x11331,0x11331); (0x11334,0x11334); (0x1133A,0x1133B); (0x11345,0x11346); (0x11349,0x1134A); (0x1134E,0x1134F); (0x11351,0x11356); (0x11358,0x1135C); (0x11364,0x11365); (0x1136D,0x1136F); (0x11375,0x113FF); (0x1145A,0x1145A); (0x1145C,0x1145C); (0x1145E,0x1147F); (0x114C8,0x114CF); (0x114DA,0x1157F); (0x115B6,0x115B7); (0x115DE,0x115FF); (0x11645,0x1164F); (0x1165A,0x1165F); (0x1166D,0x1167F); (0x116B8,0x116BF); (0x116CA,0x116FF); (0x1171A,0x1171C); (0x1172C,0x1172F); (0x11740,0x1189F); (0x118F3,0x118FE); (0x11900,0x11ABF); (0x11AF9,0x11BFF); (0x11C09,0x11C09); (0x11C37,0x11C37); (0x11C46,0x11C4F); (0x11C6D,0x11C6F); (0x11C90,0x11C91); (0x11CA8,0x11CA8); (0x11CB7,0x11FFF); (0x1239A,0x123FF); (0x1246F,0x1246F); (0x12475,0x1247F); (0x12544,0x12FFF); (0x1342F,0x143FF); (0x14647,0x167FF); (0x16A39,0x16A3F); (0x16A5F,0x16A5F); (0x16A6A,0x16A6D); (0x16A70,0x16ACF); (0x16AEE,0x16AEF); (0x16AF6,0x16AFF); (0x16B46,0x16B4F); (0x16B5A,0x16B5A); (0x16B62,0x16B62); (0x16B78,0x16B7C); (0x16B90,0x16EFF); (0x16F45,0x16F4F); (0x16F7F,0x16F8E); (0x16FA0,0x16FDF); (0x16FE1,0x16FFF); (0x187ED,0x187FF); (0x18AF3,0x1AFFF); (0x1B002,0x1BBFF); (0x1BC6B,0x1BC6F); (0x1BC7D,0x1BC7F); (0x1BC89,0x1BC8F); (0x1BC9A,0x1BC9B); (0x1BCA4,0x1CFFF); (0x1D0F6,0x1D0FF); (0x1D127,0x1D128); (0x1D1E9,0x1D1FF); (0x1D246,0x1D2FF); (0x1D357,0x1D35F); (0x1D372,0x1D3FF); (0x1D455,0x1D455); (0x1D49D,0x1D49D); (0x1D4A0,0x1D4A1); (0x1D4A3,0x1D4A4); (0x1D4A7,0x1D4A8); (0x1D4AD,0x1D4AD); (0x1D4BA,0x1D4BA); (0x1D4BC,0x1D4BC); (0x1D4C4,0x1D4C4); (0x1D506,0x1D506); (0x1D50B,0x1D50C); (0x1D515,0x1D515); (0x1D51D,0x1D51D); (0x1D53A,0x1D53A); (0x1D53F,0x1D53F); (0x1D545,0x1D545); (0x1D547,0x1D549); (0x1D551,0x1D551); (0x1D6A6,0x1D6A7); (0x1D7CC,0x1D7CD); (0x1DA8C,0x1DA9A); (0x1DAA0,0x1DAA0); (0x1DAB0,0x1DFFF); (0x1E007,0x1E007); (0x1E019,0x1E01A); (0x1E022,0x1E022); (0x1E025,0x1E025); (0x1E02B,0x1E7FF); (0x1E8C5,0x1E8C6); (0x1E8D7,0x1E8FF); (0x1E94B,0x1E94F); (0x1E95A,0x1E95D); (0x1E960,0x1EDFF); (0x1EE04,0x1EE04); (0x1EE20,0x1EE20); (0x1EE23,0x1EE23); (0x1EE25,0x1EE26); (0x1EE28,0x1EE28); (0x1EE33,0x1EE33); (0x1EE38,0x1EE38); (0x1EE3A,0x1EE3A); (0x1EE3C,0x1EE41); (0x1EE43,0x1EE46); (0x1EE48,0x1EE48); (0x1EE4A,0x1EE4A); (0x1EE4C,0x1EE4C); (0x1EE50,0x1EE50); (0x1EE53,0x1EE53); (0x1EE55,0x1EE56); (0x1EE58,0x1EE58); (0x1EE5A,0x1EE5A); (0x1EE5C,0x1EE5C); (0x1EE5E,0x1EE5E); (0x1EE60,0x1EE60); (0x1EE63,0x1EE63); (0x1EE65,0x1EE66); (0x1EE6B,0x1EE6B); (0x1EE73,0x1EE73); (0x1EE78,0x1EE78); (0x1EE7D,0x1EE7D); (0x1EE7F,0x1EE7F); (0x1EE8A,0x1EE8A); (0x1EE9C,0x1EEA0); (0x1EEA4,0x1EEA4); (0x1EEAA,0x1EEAA); (0x1EEBC,0x1EEEF); (0x1EEF2,0x1EFFF); (0x1F02C,0x1F02F); (0x1F094,0x1F09F); (0x1F0AF,0x1F0B0); (0x1F0C0,0x1F0C0); (0x1F0D0,0x1F0D0); (0x1F0F6,0x1F0FF); (0x1F10D,0x1F10F); (0x1F12F,0x1F12F); (0x1F16C,0x1F16F); (0x1F1AD,0x1F1E5); (0x1F203,0x1F20F); (0x1F23C,0x1F23F); (0x1F249,0x1F24F); (0x1F252,0x1F2FF); (0x1F6D3,0x1F6DF); (0x1F6ED,0x1F6EF); (0x1F6F7,0x1F6FF); (0x1F774,0x1F77F); (0x1F7D5,0x1F7FF); (0x1F80C,0x1F80F); (0x1F848,0x1F84F); (0x1F85A,0x1F85F); (0x1F888,0x1F88F); (0x1F8AE,0x1F90F); (0x1F91F,0x1F91F); (0x1F928,0x1F92F); (0x1F931,0x1F932); (0x1F93F,0x1F93F); (0x1F94C,0x1F94F); (0x1F95F,0x1F97F); (0x1F992,0x1F9BF); (0x1F9C1,0x1FFFF); (0x2A6D7,0x2A6FF); (0x2B735,0x2B73F); (0x2B81E,0x2B81F); (0x2CEA2,0x2F7FF); (0x2FA1E,0xE0000); (0xE0002,0xE001F); (0xE0080,0xE00FF); (0xE01F0,0xEFFFF); (0xFFFFE,0xFFFFF) ] (* Letter, Modifier *) let lm = [ (0x002B0,0x002C1); (0x002C6,0x002D1); (0x002E0,0x002E4); (0x002EC,0x002EC); (0x002EE,0x002EE); (0x00374,0x00374); (0x0037A,0x0037A); (0x00559,0x00559); (0x00640,0x00640); (0x006E5,0x006E6); (0x007F4,0x007F5); (0x007FA,0x007FA); (0x0081A,0x0081A); (0x00824,0x00824); (0x00828,0x00828); (0x00971,0x00971); (0x00E46,0x00E46); (0x00EC6,0x00EC6); (0x010FC,0x010FC); (0x017D7,0x017D7); (0x01843,0x01843); (0x01AA7,0x01AA7); (0x01C78,0x01C7D); (0x01D2C,0x01D6A); (0x01D78,0x01D78); (0x01D9B,0x01DBF); (0x02071,0x02071); (0x0207F,0x0207F); (0x02090,0x0209C); (0x02C7C,0x02C7D); (0x02D6F,0x02D6F); (0x02E2F,0x02E2F); (0x03005,0x03005); (0x03031,0x03035); (0x0303B,0x0303B); (0x0309D,0x0309E); (0x030FC,0x030FE); (0x0A015,0x0A015); (0x0A4F8,0x0A4FD); (0x0A60C,0x0A60C); (0x0A67F,0x0A67F); (0x0A69C,0x0A69D); (0x0A717,0x0A71F); (0x0A770,0x0A770); (0x0A788,0x0A788); (0x0A7F8,0x0A7F9); (0x0A9CF,0x0A9CF); (0x0A9E6,0x0A9E6); (0x0AA70,0x0AA70); (0x0AADD,0x0AADD); (0x0AAF3,0x0AAF4); (0x0AB5C,0x0AB5F); (0x0FF70,0x0FF70); (0x0FF9E,0x0FF9F); (0x16B40,0x16B43); (0x16F93,0x16F9F) ] (* Letter, Other *) let lo = [ (0x000AA,0x000AA); (0x000BA,0x000BA); (0x001BB,0x001BB); (0x001C0,0x001C3); (0x00294,0x00294); (0x005D0,0x005EA); (0x005F0,0x005F2); (0x00620,0x0063F); (0x00641,0x0064A); (0x0066E,0x0066F); (0x00671,0x006D3); (0x006D5,0x006D5); (0x006EE,0x006EF); (0x006FA,0x006FC); (0x006FF,0x006FF); (0x00710,0x00710); (0x00712,0x0072F); (0x0074D,0x007A5); (0x007B1,0x007B1); (0x007CA,0x007EA); (0x00800,0x00815); (0x00840,0x00858); (0x008A0,0x008B4); (0x008B6,0x008BD); (0x00904,0x00939); (0x0093D,0x0093D); (0x00950,0x00950); (0x00958,0x00961); (0x00972,0x00980); (0x00985,0x0098C); (0x0098F,0x00990); (0x00993,0x009A8); (0x009AA,0x009B0); (0x009B2,0x009B2); (0x009B6,0x009B9); (0x009BD,0x009BD); (0x009CE,0x009CE); (0x009DC,0x009DD); (0x009DF,0x009E1); (0x009F0,0x009F1); (0x00A05,0x00A0A); (0x00A0F,0x00A10); (0x00A13,0x00A28); (0x00A2A,0x00A30); (0x00A32,0x00A33); (0x00A35,0x00A36); (0x00A38,0x00A39); (0x00A59,0x00A5C); (0x00A5E,0x00A5E); (0x00A72,0x00A74); (0x00A85,0x00A8D); (0x00A8F,0x00A91); (0x00A93,0x00AA8); (0x00AAA,0x00AB0); (0x00AB2,0x00AB3); (0x00AB5,0x00AB9); (0x00ABD,0x00ABD); (0x00AD0,0x00AD0); (0x00AE0,0x00AE1); (0x00AF9,0x00AF9); (0x00B05,0x00B0C); (0x00B0F,0x00B10); (0x00B13,0x00B28); (0x00B2A,0x00B30); (0x00B32,0x00B33); (0x00B35,0x00B39); (0x00B3D,0x00B3D); (0x00B5C,0x00B5D); (0x00B5F,0x00B61); (0x00B71,0x00B71); (0x00B83,0x00B83); (0x00B85,0x00B8A); (0x00B8E,0x00B90); (0x00B92,0x00B95); (0x00B99,0x00B9A); (0x00B9C,0x00B9C); (0x00B9E,0x00B9F); (0x00BA3,0x00BA4); (0x00BA8,0x00BAA); (0x00BAE,0x00BB9); (0x00BD0,0x00BD0); (0x00C05,0x00C0C); (0x00C0E,0x00C10); (0x00C12,0x00C28); (0x00C2A,0x00C39); (0x00C3D,0x00C3D); (0x00C58,0x00C5A); (0x00C60,0x00C61); (0x00C80,0x00C80); (0x00C85,0x00C8C); (0x00C8E,0x00C90); (0x00C92,0x00CA8); (0x00CAA,0x00CB3); (0x00CB5,0x00CB9); (0x00CBD,0x00CBD); (0x00CDE,0x00CDE); (0x00CE0,0x00CE1); (0x00CF1,0x00CF2); (0x00D05,0x00D0C); (0x00D0E,0x00D10); (0x00D12,0x00D3A); (0x00D3D,0x00D3D); (0x00D4E,0x00D4E); (0x00D54,0x00D56); (0x00D5F,0x00D61); (0x00D7A,0x00D7F); (0x00D85,0x00D96); (0x00D9A,0x00DB1); (0x00DB3,0x00DBB); (0x00DBD,0x00DBD); (0x00DC0,0x00DC6); (0x00E01,0x00E30); (0x00E32,0x00E33); (0x00E40,0x00E45); (0x00E81,0x00E82); (0x00E84,0x00E84); (0x00E87,0x00E88); (0x00E8A,0x00E8A); (0x00E8D,0x00E8D); (0x00E94,0x00E97); (0x00E99,0x00E9F); (0x00EA1,0x00EA3); (0x00EA5,0x00EA5); (0x00EA7,0x00EA7); (0x00EAA,0x00EAB); (0x00EAD,0x00EB0); (0x00EB2,0x00EB3); (0x00EBD,0x00EBD); (0x00EC0,0x00EC4); (0x00EDC,0x00EDF); (0x00F00,0x00F00); (0x00F40,0x00F47); (0x00F49,0x00F6C); (0x00F88,0x00F8C); (0x01000,0x0102A); (0x0103F,0x0103F); (0x01050,0x01055); (0x0105A,0x0105D); (0x01061,0x01061); (0x01065,0x01066); (0x0106E,0x01070); (0x01075,0x01081); (0x0108E,0x0108E); (0x010D0,0x010FA); (0x010FD,0x01248); (0x0124A,0x0124D); (0x01250,0x01256); (0x01258,0x01258); (0x0125A,0x0125D); (0x01260,0x01288); (0x0128A,0x0128D); (0x01290,0x012B0); (0x012B2,0x012B5); (0x012B8,0x012BE); (0x012C0,0x012C0); (0x012C2,0x012C5); (0x012C8,0x012D6); (0x012D8,0x01310); (0x01312,0x01315); (0x01318,0x0135A); (0x01380,0x0138F); (0x01401,0x0166C); (0x0166F,0x0167F); (0x01681,0x0169A); (0x016A0,0x016EA); (0x016F1,0x016F8); (0x01700,0x0170C); (0x0170E,0x01711); (0x01720,0x01731); (0x01740,0x01751); (0x01760,0x0176C); (0x0176E,0x01770); (0x01780,0x017B3); (0x017DC,0x017DC); (0x01820,0x01842); (0x01844,0x01877); (0x01880,0x01884); (0x01887,0x018A8); (0x018AA,0x018AA); (0x018B0,0x018F5); (0x01900,0x0191E); (0x01950,0x0196D); (0x01970,0x01974); (0x01980,0x019AB); (0x019B0,0x019C9); (0x01A00,0x01A16); (0x01A20,0x01A54); (0x01B05,0x01B33); (0x01B45,0x01B4B); (0x01B83,0x01BA0); (0x01BAE,0x01BAF); (0x01BBA,0x01BE5); (0x01C00,0x01C23); (0x01C4D,0x01C4F); (0x01C5A,0x01C77); (0x01CE9,0x01CEC); (0x01CEE,0x01CF1); (0x01CF5,0x01CF6); (0x02135,0x02138); (0x02D30,0x02D67); (0x02D80,0x02D96); (0x02DA0,0x02DA6); (0x02DA8,0x02DAE); (0x02DB0,0x02DB6); (0x02DB8,0x02DBE); (0x02DC0,0x02DC6); (0x02DC8,0x02DCE); (0x02DD0,0x02DD6); (0x02DD8,0x02DDE); (0x03006,0x03006); (0x0303C,0x0303C); (0x03041,0x03096); (0x0309F,0x0309F); (0x030A1,0x030FA); (0x030FF,0x030FF); (0x03105,0x0312D); (0x03131,0x0318E); (0x031A0,0x031BA); (0x031F0,0x031FF); (0x03400,0x04DB5); (0x04E00,0x09FD5); (0x0A000,0x0A014); (0x0A016,0x0A48C); (0x0A4D0,0x0A4F7); (0x0A500,0x0A60B); (0x0A610,0x0A61F); (0x0A62A,0x0A62B); (0x0A66E,0x0A66E); (0x0A6A0,0x0A6E5); (0x0A78F,0x0A78F); (0x0A7F7,0x0A7F7); (0x0A7FB,0x0A801); (0x0A803,0x0A805); (0x0A807,0x0A80A); (0x0A80C,0x0A822); (0x0A840,0x0A873); (0x0A882,0x0A8B3); (0x0A8F2,0x0A8F7); (0x0A8FB,0x0A8FB); (0x0A8FD,0x0A8FD); (0x0A90A,0x0A925); (0x0A930,0x0A946); (0x0A960,0x0A97C); (0x0A984,0x0A9B2); (0x0A9E0,0x0A9E4); (0x0A9E7,0x0A9EF); (0x0A9FA,0x0A9FE); (0x0AA00,0x0AA28); (0x0AA40,0x0AA42); (0x0AA44,0x0AA4B); (0x0AA60,0x0AA6F); (0x0AA71,0x0AA76); (0x0AA7A,0x0AA7A); (0x0AA7E,0x0AAAF); (0x0AAB1,0x0AAB1); (0x0AAB5,0x0AAB6); (0x0AAB9,0x0AABD); (0x0AAC0,0x0AAC0); (0x0AAC2,0x0AAC2); (0x0AADB,0x0AADC); (0x0AAE0,0x0AAEA); (0x0AAF2,0x0AAF2); (0x0AB01,0x0AB06); (0x0AB09,0x0AB0E); (0x0AB11,0x0AB16); (0x0AB20,0x0AB26); (0x0AB28,0x0AB2E); (0x0ABC0,0x0ABE2); (0x0AC00,0x0D7A3); (0x0D7B0,0x0D7C6); (0x0D7CB,0x0D7FB); (0x0F900,0x0FA6D); (0x0FA70,0x0FAD9); (0x0FB1D,0x0FB1D); (0x0FB1F,0x0FB28); (0x0FB2A,0x0FB36); (0x0FB38,0x0FB3C); (0x0FB3E,0x0FB3E); (0x0FB40,0x0FB41); (0x0FB43,0x0FB44); (0x0FB46,0x0FBB1); (0x0FBD3,0x0FD3D); (0x0FD50,0x0FD8F); (0x0FD92,0x0FDC7); (0x0FDF0,0x0FDFB); (0x0FE70,0x0FE74); (0x0FE76,0x0FEFC); (0x0FF66,0x0FF6F); (0x0FF71,0x0FF9D); (0x0FFA0,0x0FFBE); (0x0FFC2,0x0FFC7); (0x0FFCA,0x0FFCF); (0x0FFD2,0x0FFD7); (0x0FFDA,0x0FFDC); (0x10000,0x1000B); (0x1000D,0x10026); (0x10028,0x1003A); (0x1003C,0x1003D); (0x1003F,0x1004D); (0x10050,0x1005D); (0x10080,0x100FA); (0x10280,0x1029C); (0x102A0,0x102D0); (0x10300,0x1031F); (0x10330,0x10340); (0x10342,0x10349); (0x10350,0x10375); (0x10380,0x1039D); (0x103A0,0x103C3); (0x103C8,0x103CF); (0x10450,0x1049D); (0x10500,0x10527); (0x10530,0x10563); (0x10600,0x10736); (0x10740,0x10755); (0x10760,0x10767); (0x10800,0x10805); (0x10808,0x10808); (0x1080A,0x10835); (0x10837,0x10838); (0x1083C,0x1083C); (0x1083F,0x10855); (0x10860,0x10876); (0x10880,0x1089E); (0x108E0,0x108F2); (0x108F4,0x108F5); (0x10900,0x10915); (0x10920,0x10939); (0x10980,0x109B7); (0x109BE,0x109BF); (0x10A00,0x10A00); (0x10A10,0x10A13); (0x10A15,0x10A17); (0x10A19,0x10A33); (0x10A60,0x10A7C); (0x10A80,0x10A9C); (0x10AC0,0x10AC7); (0x10AC9,0x10AE4); (0x10B00,0x10B35); (0x10B40,0x10B55); (0x10B60,0x10B72); (0x10B80,0x10B91); (0x10C00,0x10C48); (0x11003,0x11037); (0x11083,0x110AF); (0x110D0,0x110E8); (0x11103,0x11126); (0x11150,0x11172); (0x11176,0x11176); (0x11183,0x111B2); (0x111C1,0x111C4); (0x111DA,0x111DA); (0x111DC,0x111DC); (0x11200,0x11211); (0x11213,0x1122B); (0x11280,0x11286); (0x11288,0x11288); (0x1128A,0x1128D); (0x1128F,0x1129D); (0x1129F,0x112A8); (0x112B0,0x112DE); (0x11305,0x1130C); (0x1130F,0x11310); (0x11313,0x11328); (0x1132A,0x11330); (0x11332,0x11333); (0x11335,0x11339); (0x1133D,0x1133D); (0x11350,0x11350); (0x1135D,0x11361); (0x11400,0x11434); (0x11447,0x1144A); (0x11480,0x114AF); (0x114C4,0x114C5); (0x114C7,0x114C7); (0x11580,0x115AE); (0x115D8,0x115DB); (0x11600,0x1162F); (0x11644,0x11644); (0x11680,0x116AA); (0x11700,0x11719); (0x118FF,0x118FF); (0x11AC0,0x11AF8); (0x11C00,0x11C08); (0x11C0A,0x11C2E); (0x11C40,0x11C40); (0x11C72,0x11C8F); (0x12000,0x12399); (0x12480,0x12543); (0x13000,0x1342E); (0x14400,0x14646); (0x16800,0x16A38); (0x16A40,0x16A5E); (0x16AD0,0x16AED); (0x16B00,0x16B2F); (0x16B63,0x16B77); (0x16B7D,0x16B8F); (0x16F00,0x16F44); (0x16F50,0x16F50); (0x17000,0x187EC); (0x18800,0x18AF2); (0x1B000,0x1B001); (0x1BC00,0x1BC6A); (0x1BC70,0x1BC7C); (0x1BC80,0x1BC88); (0x1BC90,0x1BC99); (0x1E800,0x1E8C4); (0x1EE00,0x1EE03); (0x1EE05,0x1EE1F); (0x1EE21,0x1EE22); (0x1EE24,0x1EE24); (0x1EE27,0x1EE27); (0x1EE29,0x1EE32); (0x1EE34,0x1EE37); (0x1EE39,0x1EE39); (0x1EE3B,0x1EE3B); (0x1EE42,0x1EE42); (0x1EE47,0x1EE47); (0x1EE49,0x1EE49); (0x1EE4B,0x1EE4B); (0x1EE4D,0x1EE4F); (0x1EE51,0x1EE52); (0x1EE54,0x1EE54); (0x1EE57,0x1EE57); (0x1EE59,0x1EE59); (0x1EE5B,0x1EE5B); (0x1EE5D,0x1EE5D); (0x1EE5F,0x1EE5F); (0x1EE61,0x1EE62); (0x1EE64,0x1EE64); (0x1EE67,0x1EE6A); (0x1EE6C,0x1EE72); (0x1EE74,0x1EE77); (0x1EE79,0x1EE7C); (0x1EE7E,0x1EE7E); (0x1EE80,0x1EE89); (0x1EE8B,0x1EE9B); (0x1EEA1,0x1EEA3); (0x1EEA5,0x1EEA9); (0x1EEAB,0x1EEBB); (0x20000,0x2A6D6); (0x2A700,0x2B734); (0x2B740,0x2B81D); (0x2B820,0x2CEA1) ] (* Punctuation, Connector *) let pc = [ (0x0005F,0x0005F); (0x0203F,0x02040); (0x02054,0x02054); (0x0FE33,0x0FE34); (0x0FE4D,0x0FE4F) ] (* Punctuation, Dash *) let pd = [ (0x0002D,0x0002D); (0x0058A,0x0058A); (0x005BE,0x005BE); (0x01400,0x01400); (0x01806,0x01806); (0x02010,0x02015); (0x02E17,0x02E17); (0x02E1A,0x02E1A); (0x02E3A,0x02E3B); (0x02E40,0x02E40); (0x0301C,0x0301C); (0x03030,0x03030); (0x030A0,0x030A0); (0x0FE31,0x0FE32); (0x0FE58,0x0FE58); (0x0FE63,0x0FE63) ] (* Punctuation, Open *) let ps = [ (0x00028,0x00028); (0x0005B,0x0005B); (0x0007B,0x0007B); (0x00F3A,0x00F3A); (0x00F3C,0x00F3C); (0x0169B,0x0169B); (0x0201A,0x0201A); (0x0201E,0x0201E); (0x02045,0x02045); (0x0207D,0x0207D); (0x0208D,0x0208D); (0x02308,0x02308); (0x0230A,0x0230A); (0x02329,0x02329); (0x02768,0x02768); (0x0276A,0x0276A); (0x0276C,0x0276C); (0x0276E,0x0276E); (0x02770,0x02770); (0x02772,0x02772); (0x02774,0x02774); (0x027C5,0x027C5); (0x027E6,0x027E6); (0x027E8,0x027E8); (0x027EA,0x027EA); (0x027EC,0x027EC); (0x027EE,0x027EE); (0x02983,0x02983); (0x02985,0x02985); (0x02987,0x02987); (0x02989,0x02989); (0x0298B,0x0298B); (0x0298D,0x0298D); (0x0298F,0x0298F); (0x02991,0x02991); (0x02993,0x02993); (0x02995,0x02995); (0x02997,0x02997); (0x029D8,0x029D8); (0x029DA,0x029DA); (0x029FC,0x029FC); (0x02E22,0x02E22); (0x02E24,0x02E24); (0x02E26,0x02E26); (0x02E28,0x02E28); (0x02E42,0x02E42); (0x03008,0x03008); (0x0300A,0x0300A); (0x0300C,0x0300C); (0x0300E,0x0300E); (0x03010,0x03010); (0x03014,0x03014); (0x03016,0x03016); (0x03018,0x03018); (0x0301A,0x0301A); (0x0301D,0x0301D); (0x0FD3F,0x0FD3F); (0x0FE17,0x0FE17); (0x0FE35,0x0FE35); (0x0FE37,0x0FE37); (0x0FE39,0x0FE39); (0x0FE3B,0x0FE3B); (0x0FE3D,0x0FE3D); (0x0FE3F,0x0FE3F); (0x0FE41,0x0FE41); (0x0FE43,0x0FE43); (0x0FE47,0x0FE47); (0x0FE59,0x0FE59); (0x0FE5B,0x0FE5B); (0x0FE5D,0x0FE5D); (0x0FF08,0x0FF08); (0x0FF3B,0x0FF3B); (0x0FF5B,0x0FF5B); (0x0FF5F,0x0FF5F) ] (* Punctuation, Close *) let pe = [ (0x00029,0x00029); (0x0005D,0x0005D); (0x0007D,0x0007D); (0x00F3B,0x00F3B); (0x00F3D,0x00F3D); (0x0169C,0x0169C); (0x02046,0x02046); (0x0207E,0x0207E); (0x0208E,0x0208E); (0x02309,0x02309); (0x0230B,0x0230B); (0x0232A,0x0232A); (0x02769,0x02769); (0x0276B,0x0276B); (0x0276D,0x0276D); (0x0276F,0x0276F); (0x02771,0x02771); (0x02773,0x02773); (0x02775,0x02775); (0x027C6,0x027C6); (0x027E7,0x027E7); (0x027E9,0x027E9); (0x027EB,0x027EB); (0x027ED,0x027ED); (0x027EF,0x027EF); (0x02984,0x02984); (0x02986,0x02986); (0x02988,0x02988); (0x0298A,0x0298A); (0x0298C,0x0298C); (0x0298E,0x0298E); (0x02990,0x02990); (0x02992,0x02992); (0x02994,0x02994); (0x02996,0x02996); (0x02998,0x02998); (0x029D9,0x029D9); (0x029DB,0x029DB); (0x029FD,0x029FD); (0x02E23,0x02E23); (0x02E25,0x02E25); (0x02E27,0x02E27); (0x02E29,0x02E29); (0x03009,0x03009); (0x0300B,0x0300B); (0x0300D,0x0300D); (0x0300F,0x0300F); (0x03011,0x03011); (0x03015,0x03015); (0x03017,0x03017); (0x03019,0x03019); (0x0301B,0x0301B); (0x0301E,0x0301F); (0x0FD3E,0x0FD3E); (0x0FE18,0x0FE18); (0x0FE36,0x0FE36); (0x0FE38,0x0FE38); (0x0FE3A,0x0FE3A); (0x0FE3C,0x0FE3C); (0x0FE3E,0x0FE3E); (0x0FE40,0x0FE40); (0x0FE42,0x0FE42); (0x0FE44,0x0FE44); (0x0FE48,0x0FE48); (0x0FE5A,0x0FE5A); (0x0FE5C,0x0FE5C); (0x0FE5E,0x0FE5E); (0x0FF09,0x0FF09); (0x0FF3D,0x0FF3D); (0x0FF5D,0x0FF5D); (0x0FF60,0x0FF60) ] (* Punctuation, Initial quote *) let pi = [ (0x000AB,0x000AB); (0x02018,0x02018); (0x0201B,0x0201C); (0x0201F,0x0201F); (0x02039,0x02039); (0x02E02,0x02E02); (0x02E04,0x02E04); (0x02E09,0x02E09); (0x02E0C,0x02E0C); (0x02E1C,0x02E1C) ] (* Punctuation, Final quote *) let pf = [ (0x000BB,0x000BB); (0x02019,0x02019); (0x0201D,0x0201D); (0x0203A,0x0203A); (0x02E03,0x02E03); (0x02E05,0x02E05); (0x02E0A,0x02E0A); (0x02E0D,0x02E0D); (0x02E1D,0x02E1D) ] (* Punctuation, Other *) let po = [ (0x00021,0x00023); (0x00025,0x00027); (0x0002A,0x0002A); (0x0002C,0x0002C); (0x0002E,0x0002F); (0x0003A,0x0003B); (0x0003F,0x00040); (0x0005C,0x0005C); (0x000A1,0x000A1); (0x000A7,0x000A7); (0x000B6,0x000B7); (0x000BF,0x000BF); (0x0037E,0x0037E); (0x00387,0x00387); (0x0055A,0x0055F); (0x00589,0x00589); (0x005C0,0x005C0); (0x005C3,0x005C3); (0x005C6,0x005C6); (0x005F3,0x005F4); (0x00609,0x0060A); (0x0060C,0x0060D); (0x0061B,0x0061B); (0x0061E,0x0061F); (0x0066A,0x0066D); (0x006D4,0x006D4); (0x00700,0x0070D); (0x007F7,0x007F9); (0x00830,0x0083E); (0x0085E,0x0085E); (0x00964,0x00965); (0x00970,0x00970); (0x00AF0,0x00AF0); (0x00DF4,0x00DF4); (0x00E4F,0x00E4F); (0x00E5A,0x00E5B); (0x00F04,0x00F12); (0x00F14,0x00F14); (0x00F85,0x00F85); (0x00FD0,0x00FD4); (0x00FD9,0x00FDA); (0x0104A,0x0104F); (0x010FB,0x010FB); (0x01360,0x01368); (0x0166D,0x0166E); (0x016EB,0x016ED); (0x01735,0x01736); (0x017D4,0x017D6); (0x017D8,0x017DA); (0x01800,0x01805); (0x01807,0x0180A); (0x01944,0x01945); (0x01A1E,0x01A1F); (0x01AA0,0x01AA6); (0x01AA8,0x01AAD); (0x01B5A,0x01B60); (0x01BFC,0x01BFF); (0x01C3B,0x01C3F); (0x01C7E,0x01C7F); (0x01CC0,0x01CC7); (0x01CD3,0x01CD3); (0x02016,0x02017); (0x02020,0x02027); (0x02030,0x02038); (0x0203B,0x0203E); (0x02041,0x02043); (0x02047,0x02051); (0x02053,0x02053); (0x02055,0x0205E); (0x02CF9,0x02CFC); (0x02CFE,0x02CFF); (0x02D70,0x02D70); (0x02E00,0x02E01); (0x02E06,0x02E08); (0x02E0B,0x02E0B); (0x02E0E,0x02E16); (0x02E18,0x02E19); (0x02E1B,0x02E1B); (0x02E1E,0x02E1F); (0x02E2A,0x02E2E); (0x02E30,0x02E39); (0x02E3C,0x02E3F); (0x02E41,0x02E41); (0x02E43,0x02E44); (0x03001,0x03003); (0x0303D,0x0303D); (0x030FB,0x030FB); (0x0A4FE,0x0A4FF); (0x0A60D,0x0A60F); (0x0A673,0x0A673); (0x0A67E,0x0A67E); (0x0A6F2,0x0A6F7); (0x0A874,0x0A877); (0x0A8CE,0x0A8CF); (0x0A8F8,0x0A8FA); (0x0A8FC,0x0A8FC); (0x0A92E,0x0A92F); (0x0A95F,0x0A95F); (0x0A9C1,0x0A9CD); (0x0A9DE,0x0A9DF); (0x0AA5C,0x0AA5F); (0x0AADE,0x0AADF); (0x0AAF0,0x0AAF1); (0x0ABEB,0x0ABEB); (0x0FE10,0x0FE16); (0x0FE19,0x0FE19); (0x0FE30,0x0FE30); (0x0FE45,0x0FE46); (0x0FE49,0x0FE4C); (0x0FE50,0x0FE52); (0x0FE54,0x0FE57); (0x0FE5F,0x0FE61); (0x0FE68,0x0FE68); (0x0FE6A,0x0FE6B); (0x0FF01,0x0FF03); (0x0FF05,0x0FF07); (0x0FF0A,0x0FF0A); (0x0FF0C,0x0FF0C); (0x0FF0E,0x0FF0F); (0x0FF1A,0x0FF1B); (0x0FF1F,0x0FF20); (0x0FF3C,0x0FF3C); (0x0FF61,0x0FF61); (0x0FF64,0x0FF65); (0x10100,0x10102); (0x1039F,0x1039F); (0x103D0,0x103D0); (0x1056F,0x1056F); (0x10857,0x10857); (0x1091F,0x1091F); (0x1093F,0x1093F); (0x10A50,0x10A58); (0x10A7F,0x10A7F); (0x10AF0,0x10AF6); (0x10B39,0x10B3F); (0x10B99,0x10B9C); (0x11047,0x1104D); (0x110BB,0x110BC); (0x110BE,0x110C1); (0x11140,0x11143); (0x11174,0x11175); (0x111C5,0x111C9); (0x111CD,0x111CD); (0x111DB,0x111DB); (0x111DD,0x111DF); (0x11238,0x1123D); (0x112A9,0x112A9); (0x1144B,0x1144F); (0x1145B,0x1145B); (0x1145D,0x1145D); (0x114C6,0x114C6); (0x115C1,0x115D7); (0x11641,0x11643); (0x11660,0x1166C); (0x1173C,0x1173E); (0x11C41,0x11C45); (0x11C70,0x11C71); (0x12470,0x12474); (0x16A6E,0x16A6F); (0x16AF5,0x16AF5); (0x16B37,0x16B3B); (0x16B44,0x16B44); (0x1BC9F,0x1BC9F); (0x1DA87,0x1DA8B) ] (* Symbol, Math *) let sm = [ (0x0002B,0x0002B); (0x0003C,0x0003E); (0x0007C,0x0007C); (0x0007E,0x0007E); (0x000AC,0x000AC); (0x000B1,0x000B1); (0x000D7,0x000D7); (0x000F7,0x000F7); (0x003F6,0x003F6); (0x00606,0x00608); (0x02044,0x02044); (0x02052,0x02052); (0x0207A,0x0207C); (0x0208A,0x0208C); (0x02118,0x02118); (0x02140,0x02144); (0x0214B,0x0214B); (0x02190,0x02194); (0x0219A,0x0219B); (0x021A0,0x021A0); (0x021A3,0x021A3); (0x021A6,0x021A6); (0x021AE,0x021AE); (0x021CE,0x021CF); (0x021D2,0x021D2); (0x021D4,0x021D4); (0x021F4,0x022FF); (0x02320,0x02321); (0x0237C,0x0237C); (0x0239B,0x023B3); (0x023DC,0x023E1); (0x025B7,0x025B7); (0x025C1,0x025C1); (0x025F8,0x025FF); (0x0266F,0x0266F); (0x027C0,0x027C4); (0x027C7,0x027E5); (0x027F0,0x027FF); (0x02900,0x02982); (0x02999,0x029D7); (0x029DC,0x029FB); (0x029FE,0x02AFF); (0x02B30,0x02B44); (0x02B47,0x02B4C); (0x0FB29,0x0FB29); (0x0FE62,0x0FE62); (0x0FE64,0x0FE66); (0x0FF0B,0x0FF0B); (0x0FF1C,0x0FF1E); (0x0FF5C,0x0FF5C); (0x0FF5E,0x0FF5E); (0x0FFE2,0x0FFE2); (0x0FFE9,0x0FFEC); (0x1D6C1,0x1D6C1); (0x1D6DB,0x1D6DB); (0x1D6FB,0x1D6FB); (0x1D715,0x1D715); (0x1D735,0x1D735); (0x1D74F,0x1D74F); (0x1D76F,0x1D76F); (0x1D789,0x1D789); (0x1D7A9,0x1D7A9); (0x1D7C3,0x1D7C3) ] (* Symbol, Currency *) let sc = [ (0x00024,0x00024); (0x000A2,0x000A5); (0x0058F,0x0058F); (0x0060B,0x0060B); (0x009F2,0x009F3); (0x009FB,0x009FB); (0x00AF1,0x00AF1); (0x00BF9,0x00BF9); (0x00E3F,0x00E3F); (0x017DB,0x017DB); (0x020A0,0x020BE); (0x0A838,0x0A838); (0x0FDFC,0x0FDFC); (0x0FE69,0x0FE69); (0x0FF04,0x0FF04); (0x0FFE0,0x0FFE1) ] (* Symbol, Modifier *) let sk = [ (0x0005E,0x0005E); (0x00060,0x00060); (0x000A8,0x000A8); (0x000AF,0x000AF); (0x000B4,0x000B4); (0x000B8,0x000B8); (0x002C2,0x002C5); (0x002D2,0x002DF); (0x002E5,0x002EB); (0x002ED,0x002ED); (0x002EF,0x002FF); (0x00375,0x00375); (0x00384,0x00385); (0x01FBD,0x01FBD); (0x01FBF,0x01FC1); (0x01FCD,0x01FCF); (0x01FDD,0x01FDF); (0x01FED,0x01FEF); (0x01FFD,0x01FFE); (0x0309B,0x0309C); (0x0A700,0x0A716); (0x0A720,0x0A721); (0x0A789,0x0A78A); (0x0AB5B,0x0AB5B); (0x0FBB2,0x0FBC1); (0x0FF3E,0x0FF3E); (0x0FF40,0x0FF40); (0x0FFE3,0x0FFE3) ] (* Symbol, Other *) let so = [ (0x000A6,0x000A6); (0x000A9,0x000A9); (0x000AE,0x000AE); (0x000B0,0x000B0); (0x00482,0x00482); (0x0058D,0x0058E); (0x0060E,0x0060F); (0x006DE,0x006DE); (0x006E9,0x006E9); (0x006FD,0x006FE); (0x007F6,0x007F6); (0x009FA,0x009FA); (0x00B70,0x00B70); (0x00BF3,0x00BF8); (0x00BFA,0x00BFA); (0x00C7F,0x00C7F); (0x00D4F,0x00D4F); (0x00D79,0x00D79); (0x00F01,0x00F03); (0x00F13,0x00F13); (0x00F15,0x00F17); (0x00F1A,0x00F1F); (0x00F34,0x00F34); (0x00F36,0x00F36); (0x00F38,0x00F38); (0x00FBE,0x00FC5); (0x00FC7,0x00FCC); (0x00FCE,0x00FCF); (0x00FD5,0x00FD8); (0x0109E,0x0109F); (0x01390,0x01399); (0x01940,0x01940); (0x019DE,0x019FF); (0x01B61,0x01B6A); (0x01B74,0x01B7C); (0x02100,0x02101); (0x02103,0x02106); (0x02108,0x02109); (0x02114,0x02114); (0x02116,0x02117); (0x0211E,0x02123); (0x02125,0x02125); (0x02127,0x02127); (0x02129,0x02129); (0x0212E,0x0212E); (0x0213A,0x0213B); (0x0214A,0x0214A); (0x0214C,0x0214D); (0x0214F,0x0214F); (0x0218A,0x0218B); (0x02195,0x02199); (0x0219C,0x0219F); (0x021A1,0x021A2); (0x021A4,0x021A5); (0x021A7,0x021AD); (0x021AF,0x021CD); (0x021D0,0x021D1); (0x021D3,0x021D3); (0x021D5,0x021F3); (0x02300,0x02307); (0x0230C,0x0231F); (0x02322,0x02328); (0x0232B,0x0237B); (0x0237D,0x0239A); (0x023B4,0x023DB); (0x023E2,0x023FE); (0x02400,0x02426); (0x02440,0x0244A); (0x0249C,0x024E9); (0x02500,0x025B6); (0x025B8,0x025C0); (0x025C2,0x025F7); (0x02600,0x0266E); (0x02670,0x02767); (0x02794,0x027BF); (0x02800,0x028FF); (0x02B00,0x02B2F); (0x02B45,0x02B46); (0x02B4D,0x02B73); (0x02B76,0x02B95); (0x02B98,0x02BB9); (0x02BBD,0x02BC8); (0x02BCA,0x02BD1); (0x02BEC,0x02BEF); (0x02CE5,0x02CEA); (0x02E80,0x02E99); (0x02E9B,0x02EF3); (0x02F00,0x02FD5); (0x02FF0,0x02FFB); (0x03004,0x03004); (0x03012,0x03013); (0x03020,0x03020); (0x03036,0x03037); (0x0303E,0x0303F); (0x03190,0x03191); (0x03196,0x0319F); (0x031C0,0x031E3); (0x03200,0x0321E); (0x0322A,0x03247); (0x03250,0x03250); (0x03260,0x0327F); (0x0328A,0x032B0); (0x032C0,0x032FE); (0x03300,0x033FF); (0x04DC0,0x04DFF); (0x0A490,0x0A4C6); (0x0A828,0x0A82B); (0x0A836,0x0A837); (0x0A839,0x0A839); (0x0AA77,0x0AA79); (0x0FDFD,0x0FDFD); (0x0FFE4,0x0FFE4); (0x0FFE8,0x0FFE8); (0x0FFED,0x0FFEE); (0x0FFFC,0x0FFFD); (0x10137,0x1013F); (0x10179,0x10189); (0x1018C,0x1018E); (0x10190,0x1019B); (0x101A0,0x101A0); (0x101D0,0x101FC); (0x10877,0x10878); (0x10AC8,0x10AC8); (0x1173F,0x1173F); (0x16B3C,0x16B3F); (0x16B45,0x16B45); (0x1BC9C,0x1BC9C); (0x1D000,0x1D0F5); (0x1D100,0x1D126); (0x1D129,0x1D164); (0x1D16A,0x1D16C); (0x1D183,0x1D184); (0x1D18C,0x1D1A9); (0x1D1AE,0x1D1E8); (0x1D200,0x1D241); (0x1D245,0x1D245); (0x1D300,0x1D356); (0x1D800,0x1D9FF); (0x1DA37,0x1DA3A); (0x1DA6D,0x1DA74); (0x1DA76,0x1DA83); (0x1DA85,0x1DA86); (0x1F000,0x1F02B); (0x1F030,0x1F093); (0x1F0A0,0x1F0AE); (0x1F0B1,0x1F0BF); (0x1F0C1,0x1F0CF); (0x1F0D1,0x1F0F5); (0x1F110,0x1F12E); (0x1F130,0x1F16B); (0x1F170,0x1F1AC); (0x1F1E6,0x1F202); (0x1F210,0x1F23B); (0x1F240,0x1F248); (0x1F250,0x1F251); (0x1F300,0x1F3FA); (0x1F400,0x1F6D2); (0x1F6E0,0x1F6EC); (0x1F6F0,0x1F6F6); (0x1F700,0x1F773); (0x1F780,0x1F7D4); (0x1F800,0x1F80B); (0x1F810,0x1F847); (0x1F850,0x1F859); (0x1F860,0x1F887); (0x1F890,0x1F8AD); (0x1F910,0x1F91E); (0x1F920,0x1F927); (0x1F930,0x1F930); (0x1F933,0x1F93E); (0x1F940,0x1F94B); (0x1F950,0x1F95E); (0x1F980,0x1F991) ] let to_lower = [ (0x00041,0x0005A), `Delta (32); (0x000C0,0x000D6), `Delta (32); (0x000D8,0x000DE), `Delta (32); (0x00100,0x00100), `Abs (0x00101); (0x00102,0x00102), `Abs (0x00103); (0x00104,0x00104), `Abs (0x00105); (0x00106,0x00106), `Abs (0x00107); (0x00108,0x00108), `Abs (0x00109); (0x0010A,0x0010A), `Abs (0x0010B); (0x0010C,0x0010C), `Abs (0x0010D); (0x0010E,0x0010E), `Abs (0x0010F); (0x00110,0x00110), `Abs (0x00111); (0x00112,0x00112), `Abs (0x00113); (0x00114,0x00114), `Abs (0x00115); (0x00116,0x00116), `Abs (0x00117); (0x00118,0x00118), `Abs (0x00119); (0x0011A,0x0011A), `Abs (0x0011B); (0x0011C,0x0011C), `Abs (0x0011D); (0x0011E,0x0011E), `Abs (0x0011F); (0x00120,0x00120), `Abs (0x00121); (0x00122,0x00122), `Abs (0x00123); (0x00124,0x00124), `Abs (0x00125); (0x00126,0x00126), `Abs (0x00127); (0x00128,0x00128), `Abs (0x00129); (0x0012A,0x0012A), `Abs (0x0012B); (0x0012C,0x0012C), `Abs (0x0012D); (0x0012E,0x0012E), `Abs (0x0012F); (0x00130,0x00130), `Abs (0x00069); (0x00132,0x00132), `Abs (0x00133); (0x00134,0x00134), `Abs (0x00135); (0x00136,0x00136), `Abs (0x00137); (0x00139,0x00139), `Abs (0x0013A); (0x0013B,0x0013B), `Abs (0x0013C); (0x0013D,0x0013D), `Abs (0x0013E); (0x0013F,0x0013F), `Abs (0x00140); (0x00141,0x00141), `Abs (0x00142); (0x00143,0x00143), `Abs (0x00144); (0x00145,0x00145), `Abs (0x00146); (0x00147,0x00147), `Abs (0x00148); (0x0014A,0x0014A), `Abs (0x0014B); (0x0014C,0x0014C), `Abs (0x0014D); (0x0014E,0x0014E), `Abs (0x0014F); (0x00150,0x00150), `Abs (0x00151); (0x00152,0x00152), `Abs (0x00153); (0x00154,0x00154), `Abs (0x00155); (0x00156,0x00156), `Abs (0x00157); (0x00158,0x00158), `Abs (0x00159); (0x0015A,0x0015A), `Abs (0x0015B); (0x0015C,0x0015C), `Abs (0x0015D); (0x0015E,0x0015E), `Abs (0x0015F); (0x00160,0x00160), `Abs (0x00161); (0x00162,0x00162), `Abs (0x00163); (0x00164,0x00164), `Abs (0x00165); (0x00166,0x00166), `Abs (0x00167); (0x00168,0x00168), `Abs (0x00169); (0x0016A,0x0016A), `Abs (0x0016B); (0x0016C,0x0016C), `Abs (0x0016D); (0x0016E,0x0016E), `Abs (0x0016F); (0x00170,0x00170), `Abs (0x00171); (0x00172,0x00172), `Abs (0x00173); (0x00174,0x00174), `Abs (0x00175); (0x00176,0x00176), `Abs (0x00177); (0x00178,0x00178), `Abs (0x000FF); (0x00179,0x00179), `Abs (0x0017A); (0x0017B,0x0017B), `Abs (0x0017C); (0x0017D,0x0017D), `Abs (0x0017E); (0x00181,0x00181), `Abs (0x00253); (0x00182,0x00182), `Abs (0x00183); (0x00184,0x00184), `Abs (0x00185); (0x00186,0x00186), `Abs (0x00254); (0x00187,0x00187), `Abs (0x00188); (0x00189,0x0018A), `Delta (205); (0x0018B,0x0018B), `Abs (0x0018C); (0x0018E,0x0018E), `Abs (0x001DD); (0x0018F,0x0018F), `Abs (0x00259); (0x00190,0x00190), `Abs (0x0025B); (0x00191,0x00191), `Abs (0x00192); (0x00193,0x00193), `Abs (0x00260); (0x00194,0x00194), `Abs (0x00263); (0x00196,0x00196), `Abs (0x00269); (0x00197,0x00197), `Abs (0x00268); (0x00198,0x00198), `Abs (0x00199); (0x0019C,0x0019C), `Abs (0x0026F); (0x0019D,0x0019D), `Abs (0x00272); (0x0019F,0x0019F), `Abs (0x00275); (0x001A0,0x001A0), `Abs (0x001A1); (0x001A2,0x001A2), `Abs (0x001A3); (0x001A4,0x001A4), `Abs (0x001A5); (0x001A6,0x001A6), `Abs (0x00280); (0x001A7,0x001A7), `Abs (0x001A8); (0x001A9,0x001A9), `Abs (0x00283); (0x001AC,0x001AC), `Abs (0x001AD); (0x001AE,0x001AE), `Abs (0x00288); (0x001AF,0x001AF), `Abs (0x001B0); (0x001B1,0x001B2), `Delta (217); (0x001B3,0x001B3), `Abs (0x001B4); (0x001B5,0x001B5), `Abs (0x001B6); (0x001B7,0x001B7), `Abs (0x00292); (0x001B8,0x001B8), `Abs (0x001B9); (0x001BC,0x001BC), `Abs (0x001BD); (0x001C4,0x001C4), `Abs (0x001C6); (0x001C7,0x001C7), `Abs (0x001C9); (0x001CA,0x001CA), `Abs (0x001CC); (0x001CD,0x001CD), `Abs (0x001CE); (0x001CF,0x001CF), `Abs (0x001D0); (0x001D1,0x001D1), `Abs (0x001D2); (0x001D3,0x001D3), `Abs (0x001D4); (0x001D5,0x001D5), `Abs (0x001D6); (0x001D7,0x001D7), `Abs (0x001D8); (0x001D9,0x001D9), `Abs (0x001DA); (0x001DB,0x001DB), `Abs (0x001DC); (0x001DE,0x001DE), `Abs (0x001DF); (0x001E0,0x001E0), `Abs (0x001E1); (0x001E2,0x001E2), `Abs (0x001E3); (0x001E4,0x001E4), `Abs (0x001E5); (0x001E6,0x001E6), `Abs (0x001E7); (0x001E8,0x001E8), `Abs (0x001E9); (0x001EA,0x001EA), `Abs (0x001EB); (0x001EC,0x001EC), `Abs (0x001ED); (0x001EE,0x001EE), `Abs (0x001EF); (0x001F1,0x001F1), `Abs (0x001F3); (0x001F4,0x001F4), `Abs (0x001F5); (0x001F6,0x001F6), `Abs (0x00195); (0x001F7,0x001F7), `Abs (0x001BF); (0x001F8,0x001F8), `Abs (0x001F9); (0x001FA,0x001FA), `Abs (0x001FB); (0x001FC,0x001FC), `Abs (0x001FD); (0x001FE,0x001FE), `Abs (0x001FF); (0x00200,0x00200), `Abs (0x00201); (0x00202,0x00202), `Abs (0x00203); (0x00204,0x00204), `Abs (0x00205); (0x00206,0x00206), `Abs (0x00207); (0x00208,0x00208), `Abs (0x00209); (0x0020A,0x0020A), `Abs (0x0020B); (0x0020C,0x0020C), `Abs (0x0020D); (0x0020E,0x0020E), `Abs (0x0020F); (0x00210,0x00210), `Abs (0x00211); (0x00212,0x00212), `Abs (0x00213); (0x00214,0x00214), `Abs (0x00215); (0x00216,0x00216), `Abs (0x00217); (0x00218,0x00218), `Abs (0x00219); (0x0021A,0x0021A), `Abs (0x0021B); (0x0021C,0x0021C), `Abs (0x0021D); (0x0021E,0x0021E), `Abs (0x0021F); (0x00220,0x00220), `Abs (0x0019E); (0x00222,0x00222), `Abs (0x00223); (0x00224,0x00224), `Abs (0x00225); (0x00226,0x00226), `Abs (0x00227); (0x00228,0x00228), `Abs (0x00229); (0x0022A,0x0022A), `Abs (0x0022B); (0x0022C,0x0022C), `Abs (0x0022D); (0x0022E,0x0022E), `Abs (0x0022F); (0x00230,0x00230), `Abs (0x00231); (0x00232,0x00232), `Abs (0x00233); (0x0023A,0x0023A), `Abs (0x02C65); (0x0023B,0x0023B), `Abs (0x0023C); (0x0023D,0x0023D), `Abs (0x0019A); (0x0023E,0x0023E), `Abs (0x02C66); (0x00241,0x00241), `Abs (0x00242); (0x00243,0x00243), `Abs (0x00180); (0x00244,0x00244), `Abs (0x00289); (0x00245,0x00245), `Abs (0x0028C); (0x00246,0x00246), `Abs (0x00247); (0x00248,0x00248), `Abs (0x00249); (0x0024A,0x0024A), `Abs (0x0024B); (0x0024C,0x0024C), `Abs (0x0024D); (0x0024E,0x0024E), `Abs (0x0024F); (0x00370,0x00370), `Abs (0x00371); (0x00372,0x00372), `Abs (0x00373); (0x00376,0x00376), `Abs (0x00377); (0x0037F,0x0037F), `Abs (0x003F3); (0x00386,0x00386), `Abs (0x003AC); (0x00388,0x0038A), `Delta (37); (0x0038C,0x0038C), `Abs (0x003CC); (0x0038E,0x0038F), `Delta (63); (0x00391,0x003A1), `Delta (32); (0x003A3,0x003AB), `Delta (32); (0x003CF,0x003CF), `Abs (0x003D7); (0x003D2,0x003D4), `Delta (0); (0x003D8,0x003D8), `Abs (0x003D9); (0x003DA,0x003DA), `Abs (0x003DB); (0x003DC,0x003DC), `Abs (0x003DD); (0x003DE,0x003DE), `Abs (0x003DF); (0x003E0,0x003E0), `Abs (0x003E1); (0x003E2,0x003E2), `Abs (0x003E3); (0x003E4,0x003E4), `Abs (0x003E5); (0x003E6,0x003E6), `Abs (0x003E7); (0x003E8,0x003E8), `Abs (0x003E9); (0x003EA,0x003EA), `Abs (0x003EB); (0x003EC,0x003EC), `Abs (0x003ED); (0x003EE,0x003EE), `Abs (0x003EF); (0x003F4,0x003F4), `Abs (0x003B8); (0x003F7,0x003F7), `Abs (0x003F8); (0x003F9,0x003F9), `Abs (0x003F2); (0x003FA,0x003FA), `Abs (0x003FB); (0x003FD,0x003FF), `Delta (-130); (0x00400,0x0040F), `Delta (80); (0x00410,0x0042F), `Delta (32); (0x00460,0x00460), `Abs (0x00461); (0x00462,0x00462), `Abs (0x00463); (0x00464,0x00464), `Abs (0x00465); (0x00466,0x00466), `Abs (0x00467); (0x00468,0x00468), `Abs (0x00469); (0x0046A,0x0046A), `Abs (0x0046B); (0x0046C,0x0046C), `Abs (0x0046D); (0x0046E,0x0046E), `Abs (0x0046F); (0x00470,0x00470), `Abs (0x00471); (0x00472,0x00472), `Abs (0x00473); (0x00474,0x00474), `Abs (0x00475); (0x00476,0x00476), `Abs (0x00477); (0x00478,0x00478), `Abs (0x00479); (0x0047A,0x0047A), `Abs (0x0047B); (0x0047C,0x0047C), `Abs (0x0047D); (0x0047E,0x0047E), `Abs (0x0047F); (0x00480,0x00480), `Abs (0x00481); (0x0048A,0x0048A), `Abs (0x0048B); (0x0048C,0x0048C), `Abs (0x0048D); (0x0048E,0x0048E), `Abs (0x0048F); (0x00490,0x00490), `Abs (0x00491); (0x00492,0x00492), `Abs (0x00493); (0x00494,0x00494), `Abs (0x00495); (0x00496,0x00496), `Abs (0x00497); (0x00498,0x00498), `Abs (0x00499); (0x0049A,0x0049A), `Abs (0x0049B); (0x0049C,0x0049C), `Abs (0x0049D); (0x0049E,0x0049E), `Abs (0x0049F); (0x004A0,0x004A0), `Abs (0x004A1); (0x004A2,0x004A2), `Abs (0x004A3); (0x004A4,0x004A4), `Abs (0x004A5); (0x004A6,0x004A6), `Abs (0x004A7); (0x004A8,0x004A8), `Abs (0x004A9); (0x004AA,0x004AA), `Abs (0x004AB); (0x004AC,0x004AC), `Abs (0x004AD); (0x004AE,0x004AE), `Abs (0x004AF); (0x004B0,0x004B0), `Abs (0x004B1); (0x004B2,0x004B2), `Abs (0x004B3); (0x004B4,0x004B4), `Abs (0x004B5); (0x004B6,0x004B6), `Abs (0x004B7); (0x004B8,0x004B8), `Abs (0x004B9); (0x004BA,0x004BA), `Abs (0x004BB); (0x004BC,0x004BC), `Abs (0x004BD); (0x004BE,0x004BE), `Abs (0x004BF); (0x004C0,0x004C0), `Abs (0x004CF); (0x004C1,0x004C1), `Abs (0x004C2); (0x004C3,0x004C3), `Abs (0x004C4); (0x004C5,0x004C5), `Abs (0x004C6); (0x004C7,0x004C7), `Abs (0x004C8); (0x004C9,0x004C9), `Abs (0x004CA); (0x004CB,0x004CB), `Abs (0x004CC); (0x004CD,0x004CD), `Abs (0x004CE); (0x004D0,0x004D0), `Abs (0x004D1); (0x004D2,0x004D2), `Abs (0x004D3); (0x004D4,0x004D4), `Abs (0x004D5); (0x004D6,0x004D6), `Abs (0x004D7); (0x004D8,0x004D8), `Abs (0x004D9); (0x004DA,0x004DA), `Abs (0x004DB); (0x004DC,0x004DC), `Abs (0x004DD); (0x004DE,0x004DE), `Abs (0x004DF); (0x004E0,0x004E0), `Abs (0x004E1); (0x004E2,0x004E2), `Abs (0x004E3); (0x004E4,0x004E4), `Abs (0x004E5); (0x004E6,0x004E6), `Abs (0x004E7); (0x004E8,0x004E8), `Abs (0x004E9); (0x004EA,0x004EA), `Abs (0x004EB); (0x004EC,0x004EC), `Abs (0x004ED); (0x004EE,0x004EE), `Abs (0x004EF); (0x004F0,0x004F0), `Abs (0x004F1); (0x004F2,0x004F2), `Abs (0x004F3); (0x004F4,0x004F4), `Abs (0x004F5); (0x004F6,0x004F6), `Abs (0x004F7); (0x004F8,0x004F8), `Abs (0x004F9); (0x004FA,0x004FA), `Abs (0x004FB); (0x004FC,0x004FC), `Abs (0x004FD); (0x004FE,0x004FE), `Abs (0x004FF); (0x00500,0x00500), `Abs (0x00501); (0x00502,0x00502), `Abs (0x00503); (0x00504,0x00504), `Abs (0x00505); (0x00506,0x00506), `Abs (0x00507); (0x00508,0x00508), `Abs (0x00509); (0x0050A,0x0050A), `Abs (0x0050B); (0x0050C,0x0050C), `Abs (0x0050D); (0x0050E,0x0050E), `Abs (0x0050F); (0x00510,0x00510), `Abs (0x00511); (0x00512,0x00512), `Abs (0x00513); (0x00514,0x00514), `Abs (0x00515); (0x00516,0x00516), `Abs (0x00517); (0x00518,0x00518), `Abs (0x00519); (0x0051A,0x0051A), `Abs (0x0051B); (0x0051C,0x0051C), `Abs (0x0051D); (0x0051E,0x0051E), `Abs (0x0051F); (0x00520,0x00520), `Abs (0x00521); (0x00522,0x00522), `Abs (0x00523); (0x00524,0x00524), `Abs (0x00525); (0x00526,0x00526), `Abs (0x00527); (0x00528,0x00528), `Abs (0x00529); (0x0052A,0x0052A), `Abs (0x0052B); (0x0052C,0x0052C), `Abs (0x0052D); (0x0052E,0x0052E), `Abs (0x0052F); (0x00531,0x00556), `Delta (48); (0x010A0,0x010C5), `Delta (7264); (0x010C7,0x010C7), `Abs (0x02D27); (0x010CD,0x010CD), `Abs (0x02D2D); (0x013A0,0x013EF), `Delta (38864); (0x013F0,0x013F5), `Delta (8); (0x01E00,0x01E00), `Abs (0x01E01); (0x01E02,0x01E02), `Abs (0x01E03); (0x01E04,0x01E04), `Abs (0x01E05); (0x01E06,0x01E06), `Abs (0x01E07); (0x01E08,0x01E08), `Abs (0x01E09); (0x01E0A,0x01E0A), `Abs (0x01E0B); (0x01E0C,0x01E0C), `Abs (0x01E0D); (0x01E0E,0x01E0E), `Abs (0x01E0F); (0x01E10,0x01E10), `Abs (0x01E11); (0x01E12,0x01E12), `Abs (0x01E13); (0x01E14,0x01E14), `Abs (0x01E15); (0x01E16,0x01E16), `Abs (0x01E17); (0x01E18,0x01E18), `Abs (0x01E19); (0x01E1A,0x01E1A), `Abs (0x01E1B); (0x01E1C,0x01E1C), `Abs (0x01E1D); (0x01E1E,0x01E1E), `Abs (0x01E1F); (0x01E20,0x01E20), `Abs (0x01E21); (0x01E22,0x01E22), `Abs (0x01E23); (0x01E24,0x01E24), `Abs (0x01E25); (0x01E26,0x01E26), `Abs (0x01E27); (0x01E28,0x01E28), `Abs (0x01E29); (0x01E2A,0x01E2A), `Abs (0x01E2B); (0x01E2C,0x01E2C), `Abs (0x01E2D); (0x01E2E,0x01E2E), `Abs (0x01E2F); (0x01E30,0x01E30), `Abs (0x01E31); (0x01E32,0x01E32), `Abs (0x01E33); (0x01E34,0x01E34), `Abs (0x01E35); (0x01E36,0x01E36), `Abs (0x01E37); (0x01E38,0x01E38), `Abs (0x01E39); (0x01E3A,0x01E3A), `Abs (0x01E3B); (0x01E3C,0x01E3C), `Abs (0x01E3D); (0x01E3E,0x01E3E), `Abs (0x01E3F); (0x01E40,0x01E40), `Abs (0x01E41); (0x01E42,0x01E42), `Abs (0x01E43); (0x01E44,0x01E44), `Abs (0x01E45); (0x01E46,0x01E46), `Abs (0x01E47); (0x01E48,0x01E48), `Abs (0x01E49); (0x01E4A,0x01E4A), `Abs (0x01E4B); (0x01E4C,0x01E4C), `Abs (0x01E4D); (0x01E4E,0x01E4E), `Abs (0x01E4F); (0x01E50,0x01E50), `Abs (0x01E51); (0x01E52,0x01E52), `Abs (0x01E53); (0x01E54,0x01E54), `Abs (0x01E55); (0x01E56,0x01E56), `Abs (0x01E57); (0x01E58,0x01E58), `Abs (0x01E59); (0x01E5A,0x01E5A), `Abs (0x01E5B); (0x01E5C,0x01E5C), `Abs (0x01E5D); (0x01E5E,0x01E5E), `Abs (0x01E5F); (0x01E60,0x01E60), `Abs (0x01E61); (0x01E62,0x01E62), `Abs (0x01E63); (0x01E64,0x01E64), `Abs (0x01E65); (0x01E66,0x01E66), `Abs (0x01E67); (0x01E68,0x01E68), `Abs (0x01E69); (0x01E6A,0x01E6A), `Abs (0x01E6B); (0x01E6C,0x01E6C), `Abs (0x01E6D); (0x01E6E,0x01E6E), `Abs (0x01E6F); (0x01E70,0x01E70), `Abs (0x01E71); (0x01E72,0x01E72), `Abs (0x01E73); (0x01E74,0x01E74), `Abs (0x01E75); (0x01E76,0x01E76), `Abs (0x01E77); (0x01E78,0x01E78), `Abs (0x01E79); (0x01E7A,0x01E7A), `Abs (0x01E7B); (0x01E7C,0x01E7C), `Abs (0x01E7D); (0x01E7E,0x01E7E), `Abs (0x01E7F); (0x01E80,0x01E80), `Abs (0x01E81); (0x01E82,0x01E82), `Abs (0x01E83); (0x01E84,0x01E84), `Abs (0x01E85); (0x01E86,0x01E86), `Abs (0x01E87); (0x01E88,0x01E88), `Abs (0x01E89); (0x01E8A,0x01E8A), `Abs (0x01E8B); (0x01E8C,0x01E8C), `Abs (0x01E8D); (0x01E8E,0x01E8E), `Abs (0x01E8F); (0x01E90,0x01E90), `Abs (0x01E91); (0x01E92,0x01E92), `Abs (0x01E93); (0x01E94,0x01E94), `Abs (0x01E95); (0x01E9E,0x01E9E), `Abs (0x000DF); (0x01EA0,0x01EA0), `Abs (0x01EA1); (0x01EA2,0x01EA2), `Abs (0x01EA3); (0x01EA4,0x01EA4), `Abs (0x01EA5); (0x01EA6,0x01EA6), `Abs (0x01EA7); (0x01EA8,0x01EA8), `Abs (0x01EA9); (0x01EAA,0x01EAA), `Abs (0x01EAB); (0x01EAC,0x01EAC), `Abs (0x01EAD); (0x01EAE,0x01EAE), `Abs (0x01EAF); (0x01EB0,0x01EB0), `Abs (0x01EB1); (0x01EB2,0x01EB2), `Abs (0x01EB3); (0x01EB4,0x01EB4), `Abs (0x01EB5); (0x01EB6,0x01EB6), `Abs (0x01EB7); (0x01EB8,0x01EB8), `Abs (0x01EB9); (0x01EBA,0x01EBA), `Abs (0x01EBB); (0x01EBC,0x01EBC), `Abs (0x01EBD); (0x01EBE,0x01EBE), `Abs (0x01EBF); (0x01EC0,0x01EC0), `Abs (0x01EC1); (0x01EC2,0x01EC2), `Abs (0x01EC3); (0x01EC4,0x01EC4), `Abs (0x01EC5); (0x01EC6,0x01EC6), `Abs (0x01EC7); (0x01EC8,0x01EC8), `Abs (0x01EC9); (0x01ECA,0x01ECA), `Abs (0x01ECB); (0x01ECC,0x01ECC), `Abs (0x01ECD); (0x01ECE,0x01ECE), `Abs (0x01ECF); (0x01ED0,0x01ED0), `Abs (0x01ED1); (0x01ED2,0x01ED2), `Abs (0x01ED3); (0x01ED4,0x01ED4), `Abs (0x01ED5); (0x01ED6,0x01ED6), `Abs (0x01ED7); (0x01ED8,0x01ED8), `Abs (0x01ED9); (0x01EDA,0x01EDA), `Abs (0x01EDB); (0x01EDC,0x01EDC), `Abs (0x01EDD); (0x01EDE,0x01EDE), `Abs (0x01EDF); (0x01EE0,0x01EE0), `Abs (0x01EE1); (0x01EE2,0x01EE2), `Abs (0x01EE3); (0x01EE4,0x01EE4), `Abs (0x01EE5); (0x01EE6,0x01EE6), `Abs (0x01EE7); (0x01EE8,0x01EE8), `Abs (0x01EE9); (0x01EEA,0x01EEA), `Abs (0x01EEB); (0x01EEC,0x01EEC), `Abs (0x01EED); (0x01EEE,0x01EEE), `Abs (0x01EEF); (0x01EF0,0x01EF0), `Abs (0x01EF1); (0x01EF2,0x01EF2), `Abs (0x01EF3); (0x01EF4,0x01EF4), `Abs (0x01EF5); (0x01EF6,0x01EF6), `Abs (0x01EF7); (0x01EF8,0x01EF8), `Abs (0x01EF9); (0x01EFA,0x01EFA), `Abs (0x01EFB); (0x01EFC,0x01EFC), `Abs (0x01EFD); (0x01EFE,0x01EFE), `Abs (0x01EFF); (0x01F08,0x01F0F), `Delta (-8); (0x01F18,0x01F1D), `Delta (-8); (0x01F28,0x01F2F), `Delta (-8); (0x01F38,0x01F3F), `Delta (-8); (0x01F48,0x01F4D), `Delta (-8); (0x01F59,0x01F59), `Abs (0x01F51); (0x01F5B,0x01F5B), `Abs (0x01F53); (0x01F5D,0x01F5D), `Abs (0x01F55); (0x01F5F,0x01F5F), `Abs (0x01F57); (0x01F68,0x01F6F), `Delta (-8); (0x01FB8,0x01FB9), `Delta (-8); (0x01FBA,0x01FBB), `Delta (-74); (0x01FC8,0x01FCB), `Delta (-86); (0x01FD8,0x01FD9), `Delta (-8); (0x01FDA,0x01FDB), `Delta (-100); (0x01FE8,0x01FE9), `Delta (-8); (0x01FEA,0x01FEB), `Delta (-112); (0x01FEC,0x01FEC), `Abs (0x01FE5); (0x01FF8,0x01FF9), `Delta (-128); (0x01FFA,0x01FFB), `Delta (-126); (0x02102,0x02102), `Abs (0x02102); (0x02107,0x02107), `Abs (0x02107); (0x0210B,0x0210D), `Delta (0); (0x02110,0x02112), `Delta (0); (0x02115,0x02115), `Abs (0x02115); (0x02119,0x0211D), `Delta (0); (0x02124,0x02124), `Abs (0x02124); (0x02126,0x02126), `Abs (0x003C9); (0x02128,0x02128), `Abs (0x02128); (0x0212A,0x0212A), `Abs (0x0006B); (0x0212B,0x0212B), `Abs (0x000E5); (0x0212C,0x0212D), `Delta (0); (0x02130,0x02131), `Delta (0); (0x02132,0x02132), `Abs (0x0214E); (0x02133,0x02133), `Abs (0x02133); (0x0213E,0x0213F), `Delta (0); (0x02145,0x02145), `Abs (0x02145); (0x02183,0x02183), `Abs (0x02184); (0x02C00,0x02C2E), `Delta (48); (0x02C60,0x02C60), `Abs (0x02C61); (0x02C62,0x02C62), `Abs (0x0026B); (0x02C63,0x02C63), `Abs (0x01D7D); (0x02C64,0x02C64), `Abs (0x0027D); (0x02C67,0x02C67), `Abs (0x02C68); (0x02C69,0x02C69), `Abs (0x02C6A); (0x02C6B,0x02C6B), `Abs (0x02C6C); (0x02C6D,0x02C6D), `Abs (0x00251); (0x02C6E,0x02C6E), `Abs (0x00271); (0x02C6F,0x02C6F), `Abs (0x00250); (0x02C70,0x02C70), `Abs (0x00252); (0x02C72,0x02C72), `Abs (0x02C73); (0x02C75,0x02C75), `Abs (0x02C76); (0x02C7E,0x02C7F), `Delta (-10815); (0x02C80,0x02C80), `Abs (0x02C81); (0x02C82,0x02C82), `Abs (0x02C83); (0x02C84,0x02C84), `Abs (0x02C85); (0x02C86,0x02C86), `Abs (0x02C87); (0x02C88,0x02C88), `Abs (0x02C89); (0x02C8A,0x02C8A), `Abs (0x02C8B); (0x02C8C,0x02C8C), `Abs (0x02C8D); (0x02C8E,0x02C8E), `Abs (0x02C8F); (0x02C90,0x02C90), `Abs (0x02C91); (0x02C92,0x02C92), `Abs (0x02C93); (0x02C94,0x02C94), `Abs (0x02C95); (0x02C96,0x02C96), `Abs (0x02C97); (0x02C98,0x02C98), `Abs (0x02C99); (0x02C9A,0x02C9A), `Abs (0x02C9B); (0x02C9C,0x02C9C), `Abs (0x02C9D); (0x02C9E,0x02C9E), `Abs (0x02C9F); (0x02CA0,0x02CA0), `Abs (0x02CA1); (0x02CA2,0x02CA2), `Abs (0x02CA3); (0x02CA4,0x02CA4), `Abs (0x02CA5); (0x02CA6,0x02CA6), `Abs (0x02CA7); (0x02CA8,0x02CA8), `Abs (0x02CA9); (0x02CAA,0x02CAA), `Abs (0x02CAB); (0x02CAC,0x02CAC), `Abs (0x02CAD); (0x02CAE,0x02CAE), `Abs (0x02CAF); (0x02CB0,0x02CB0), `Abs (0x02CB1); (0x02CB2,0x02CB2), `Abs (0x02CB3); (0x02CB4,0x02CB4), `Abs (0x02CB5); (0x02CB6,0x02CB6), `Abs (0x02CB7); (0x02CB8,0x02CB8), `Abs (0x02CB9); (0x02CBA,0x02CBA), `Abs (0x02CBB); (0x02CBC,0x02CBC), `Abs (0x02CBD); (0x02CBE,0x02CBE), `Abs (0x02CBF); (0x02CC0,0x02CC0), `Abs (0x02CC1); (0x02CC2,0x02CC2), `Abs (0x02CC3); (0x02CC4,0x02CC4), `Abs (0x02CC5); (0x02CC6,0x02CC6), `Abs (0x02CC7); (0x02CC8,0x02CC8), `Abs (0x02CC9); (0x02CCA,0x02CCA), `Abs (0x02CCB); (0x02CCC,0x02CCC), `Abs (0x02CCD); (0x02CCE,0x02CCE), `Abs (0x02CCF); (0x02CD0,0x02CD0), `Abs (0x02CD1); (0x02CD2,0x02CD2), `Abs (0x02CD3); (0x02CD4,0x02CD4), `Abs (0x02CD5); (0x02CD6,0x02CD6), `Abs (0x02CD7); (0x02CD8,0x02CD8), `Abs (0x02CD9); (0x02CDA,0x02CDA), `Abs (0x02CDB); (0x02CDC,0x02CDC), `Abs (0x02CDD); (0x02CDE,0x02CDE), `Abs (0x02CDF); (0x02CE0,0x02CE0), `Abs (0x02CE1); (0x02CE2,0x02CE2), `Abs (0x02CE3); (0x02CEB,0x02CEB), `Abs (0x02CEC); (0x02CED,0x02CED), `Abs (0x02CEE); (0x02CF2,0x02CF2), `Abs (0x02CF3); (0x0A640,0x0A640), `Abs (0x0A641); (0x0A642,0x0A642), `Abs (0x0A643); (0x0A644,0x0A644), `Abs (0x0A645); (0x0A646,0x0A646), `Abs (0x0A647); (0x0A648,0x0A648), `Abs (0x0A649); (0x0A64A,0x0A64A), `Abs (0x0A64B); (0x0A64C,0x0A64C), `Abs (0x0A64D); (0x0A64E,0x0A64E), `Abs (0x0A64F); (0x0A650,0x0A650), `Abs (0x0A651); (0x0A652,0x0A652), `Abs (0x0A653); (0x0A654,0x0A654), `Abs (0x0A655); (0x0A656,0x0A656), `Abs (0x0A657); (0x0A658,0x0A658), `Abs (0x0A659); (0x0A65A,0x0A65A), `Abs (0x0A65B); (0x0A65C,0x0A65C), `Abs (0x0A65D); (0x0A65E,0x0A65E), `Abs (0x0A65F); (0x0A660,0x0A660), `Abs (0x0A661); (0x0A662,0x0A662), `Abs (0x0A663); (0x0A664,0x0A664), `Abs (0x0A665); (0x0A666,0x0A666), `Abs (0x0A667); (0x0A668,0x0A668), `Abs (0x0A669); (0x0A66A,0x0A66A), `Abs (0x0A66B); (0x0A66C,0x0A66C), `Abs (0x0A66D); (0x0A680,0x0A680), `Abs (0x0A681); (0x0A682,0x0A682), `Abs (0x0A683); (0x0A684,0x0A684), `Abs (0x0A685); (0x0A686,0x0A686), `Abs (0x0A687); (0x0A688,0x0A688), `Abs (0x0A689); (0x0A68A,0x0A68A), `Abs (0x0A68B); (0x0A68C,0x0A68C), `Abs (0x0A68D); (0x0A68E,0x0A68E), `Abs (0x0A68F); (0x0A690,0x0A690), `Abs (0x0A691); (0x0A692,0x0A692), `Abs (0x0A693); (0x0A694,0x0A694), `Abs (0x0A695); (0x0A696,0x0A696), `Abs (0x0A697); (0x0A698,0x0A698), `Abs (0x0A699); (0x0A69A,0x0A69A), `Abs (0x0A69B); (0x0A722,0x0A722), `Abs (0x0A723); (0x0A724,0x0A724), `Abs (0x0A725); (0x0A726,0x0A726), `Abs (0x0A727); (0x0A728,0x0A728), `Abs (0x0A729); (0x0A72A,0x0A72A), `Abs (0x0A72B); (0x0A72C,0x0A72C), `Abs (0x0A72D); (0x0A72E,0x0A72E), `Abs (0x0A72F); (0x0A732,0x0A732), `Abs (0x0A733); (0x0A734,0x0A734), `Abs (0x0A735); (0x0A736,0x0A736), `Abs (0x0A737); (0x0A738,0x0A738), `Abs (0x0A739); (0x0A73A,0x0A73A), `Abs (0x0A73B); (0x0A73C,0x0A73C), `Abs (0x0A73D); (0x0A73E,0x0A73E), `Abs (0x0A73F); (0x0A740,0x0A740), `Abs (0x0A741); (0x0A742,0x0A742), `Abs (0x0A743); (0x0A744,0x0A744), `Abs (0x0A745); (0x0A746,0x0A746), `Abs (0x0A747); (0x0A748,0x0A748), `Abs (0x0A749); (0x0A74A,0x0A74A), `Abs (0x0A74B); (0x0A74C,0x0A74C), `Abs (0x0A74D); (0x0A74E,0x0A74E), `Abs (0x0A74F); (0x0A750,0x0A750), `Abs (0x0A751); (0x0A752,0x0A752), `Abs (0x0A753); (0x0A754,0x0A754), `Abs (0x0A755); (0x0A756,0x0A756), `Abs (0x0A757); (0x0A758,0x0A758), `Abs (0x0A759); (0x0A75A,0x0A75A), `Abs (0x0A75B); (0x0A75C,0x0A75C), `Abs (0x0A75D); (0x0A75E,0x0A75E), `Abs (0x0A75F); (0x0A760,0x0A760), `Abs (0x0A761); (0x0A762,0x0A762), `Abs (0x0A763); (0x0A764,0x0A764), `Abs (0x0A765); (0x0A766,0x0A766), `Abs (0x0A767); (0x0A768,0x0A768), `Abs (0x0A769); (0x0A76A,0x0A76A), `Abs (0x0A76B); (0x0A76C,0x0A76C), `Abs (0x0A76D); (0x0A76E,0x0A76E), `Abs (0x0A76F); (0x0A779,0x0A779), `Abs (0x0A77A); (0x0A77B,0x0A77B), `Abs (0x0A77C); (0x0A77D,0x0A77D), `Abs (0x01D79); (0x0A77E,0x0A77E), `Abs (0x0A77F); (0x0A780,0x0A780), `Abs (0x0A781); (0x0A782,0x0A782), `Abs (0x0A783); (0x0A784,0x0A784), `Abs (0x0A785); (0x0A786,0x0A786), `Abs (0x0A787); (0x0A78B,0x0A78B), `Abs (0x0A78C); (0x0A78D,0x0A78D), `Abs (0x00265); (0x0A790,0x0A790), `Abs (0x0A791); (0x0A792,0x0A792), `Abs (0x0A793); (0x0A796,0x0A796), `Abs (0x0A797); (0x0A798,0x0A798), `Abs (0x0A799); (0x0A79A,0x0A79A), `Abs (0x0A79B); (0x0A79C,0x0A79C), `Abs (0x0A79D); (0x0A79E,0x0A79E), `Abs (0x0A79F); (0x0A7A0,0x0A7A0), `Abs (0x0A7A1); (0x0A7A2,0x0A7A2), `Abs (0x0A7A3); (0x0A7A4,0x0A7A4), `Abs (0x0A7A5); (0x0A7A6,0x0A7A6), `Abs (0x0A7A7); (0x0A7A8,0x0A7A8), `Abs (0x0A7A9); (0x0A7AA,0x0A7AA), `Abs (0x00266); (0x0A7AB,0x0A7AB), `Abs (0x0025C); (0x0A7AC,0x0A7AC), `Abs (0x00261); (0x0A7AD,0x0A7AD), `Abs (0x0026C); (0x0A7AE,0x0A7AE), `Abs (0x0026A); (0x0A7B0,0x0A7B0), `Abs (0x0029E); (0x0A7B1,0x0A7B1), `Abs (0x00287); (0x0A7B2,0x0A7B2), `Abs (0x0029D); (0x0A7B3,0x0A7B3), `Abs (0x0AB53); (0x0A7B4,0x0A7B4), `Abs (0x0A7B5); (0x0A7B6,0x0A7B6), `Abs (0x0A7B7); (0x0FF21,0x0FF3A), `Delta (32); (0x10400,0x10427), `Delta (40); (0x104B0,0x104D3), `Delta (40); (0x10C80,0x10CB2), `Delta (64); (0x118A0,0x118BF), `Delta (32); (0x1D400,0x1D419), `Delta (0); (0x1D434,0x1D44D), `Delta (0); (0x1D468,0x1D481), `Delta (0); (0x1D49C,0x1D49C), `Abs (0x1D49C); (0x1D49E,0x1D49F), `Delta (0); (0x1D4A2,0x1D4A2), `Abs (0x1D4A2); (0x1D4A5,0x1D4A6), `Delta (0); (0x1D4A9,0x1D4AC), `Delta (0); (0x1D4AE,0x1D4B5), `Delta (0); (0x1D4D0,0x1D4E9), `Delta (0); (0x1D504,0x1D505), `Delta (0); (0x1D507,0x1D50A), `Delta (0); (0x1D50D,0x1D514), `Delta (0); (0x1D516,0x1D51C), `Delta (0); (0x1D538,0x1D539), `Delta (0); (0x1D53B,0x1D53E), `Delta (0); (0x1D540,0x1D544), `Delta (0); (0x1D546,0x1D546), `Abs (0x1D546); (0x1D54A,0x1D550), `Delta (0); (0x1D56C,0x1D585), `Delta (0); (0x1D5A0,0x1D5B9), `Delta (0); (0x1D5D4,0x1D5ED), `Delta (0); (0x1D608,0x1D621), `Delta (0); (0x1D63C,0x1D655), `Delta (0); (0x1D670,0x1D689), `Delta (0); (0x1D6A8,0x1D6C0), `Delta (0); (0x1D6E2,0x1D6FA), `Delta (0); (0x1D71C,0x1D734), `Delta (0); (0x1D756,0x1D76E), `Delta (0); (0x1D790,0x1D7A8), `Delta (0); (0x1D7CA,0x1D7CA), `Abs (0x1D7CA); (0x1E900,0x1E921), `Delta (34); (0x00061,0x0007A), `Delta (0); (0x000B5,0x000B5), `Abs (0x000B5); (0x000DF,0x000F6), `Delta (0); (0x000F8,0x000FF), `Delta (0); (0x00101,0x00101), `Abs (0x00101); (0x00103,0x00103), `Abs (0x00103); (0x00105,0x00105), `Abs (0x00105); (0x00107,0x00107), `Abs (0x00107); (0x00109,0x00109), `Abs (0x00109); (0x0010B,0x0010B), `Abs (0x0010B); (0x0010D,0x0010D), `Abs (0x0010D); (0x0010F,0x0010F), `Abs (0x0010F); (0x00111,0x00111), `Abs (0x00111); (0x00113,0x00113), `Abs (0x00113); (0x00115,0x00115), `Abs (0x00115); (0x00117,0x00117), `Abs (0x00117); (0x00119,0x00119), `Abs (0x00119); (0x0011B,0x0011B), `Abs (0x0011B); (0x0011D,0x0011D), `Abs (0x0011D); (0x0011F,0x0011F), `Abs (0x0011F); (0x00121,0x00121), `Abs (0x00121); (0x00123,0x00123), `Abs (0x00123); (0x00125,0x00125), `Abs (0x00125); (0x00127,0x00127), `Abs (0x00127); (0x00129,0x00129), `Abs (0x00129); (0x0012B,0x0012B), `Abs (0x0012B); (0x0012D,0x0012D), `Abs (0x0012D); (0x0012F,0x0012F), `Abs (0x0012F); (0x00131,0x00131), `Abs (0x00131); (0x00133,0x00133), `Abs (0x00133); (0x00135,0x00135), `Abs (0x00135); (0x00137,0x00138), `Delta (0); (0x0013A,0x0013A), `Abs (0x0013A); (0x0013C,0x0013C), `Abs (0x0013C); (0x0013E,0x0013E), `Abs (0x0013E); (0x00140,0x00140), `Abs (0x00140); (0x00142,0x00142), `Abs (0x00142); (0x00144,0x00144), `Abs (0x00144); (0x00146,0x00146), `Abs (0x00146); (0x00148,0x00149), `Delta (0); (0x0014B,0x0014B), `Abs (0x0014B); (0x0014D,0x0014D), `Abs (0x0014D); (0x0014F,0x0014F), `Abs (0x0014F); (0x00151,0x00151), `Abs (0x00151); (0x00153,0x00153), `Abs (0x00153); (0x00155,0x00155), `Abs (0x00155); (0x00157,0x00157), `Abs (0x00157); (0x00159,0x00159), `Abs (0x00159); (0x0015B,0x0015B), `Abs (0x0015B); (0x0015D,0x0015D), `Abs (0x0015D); (0x0015F,0x0015F), `Abs (0x0015F); (0x00161,0x00161), `Abs (0x00161); (0x00163,0x00163), `Abs (0x00163); (0x00165,0x00165), `Abs (0x00165); (0x00167,0x00167), `Abs (0x00167); (0x00169,0x00169), `Abs (0x00169); (0x0016B,0x0016B), `Abs (0x0016B); (0x0016D,0x0016D), `Abs (0x0016D); (0x0016F,0x0016F), `Abs (0x0016F); (0x00171,0x00171), `Abs (0x00171); (0x00173,0x00173), `Abs (0x00173); (0x00175,0x00175), `Abs (0x00175); (0x00177,0x00177), `Abs (0x00177); (0x0017A,0x0017A), `Abs (0x0017A); (0x0017C,0x0017C), `Abs (0x0017C); (0x0017E,0x00180), `Delta (0); (0x00183,0x00183), `Abs (0x00183); (0x00185,0x00185), `Abs (0x00185); (0x00188,0x00188), `Abs (0x00188); (0x0018C,0x0018D), `Delta (0); (0x00192,0x00192), `Abs (0x00192); (0x00195,0x00195), `Abs (0x00195); (0x00199,0x0019B), `Delta (0); (0x0019E,0x0019E), `Abs (0x0019E); (0x001A1,0x001A1), `Abs (0x001A1); (0x001A3,0x001A3), `Abs (0x001A3); (0x001A5,0x001A5), `Abs (0x001A5); (0x001A8,0x001A8), `Abs (0x001A8); (0x001AA,0x001AB), `Delta (0); (0x001AD,0x001AD), `Abs (0x001AD); (0x001B0,0x001B0), `Abs (0x001B0); (0x001B4,0x001B4), `Abs (0x001B4); (0x001B6,0x001B6), `Abs (0x001B6); (0x001B9,0x001BA), `Delta (0); (0x001BD,0x001BF), `Delta (0); (0x001C6,0x001C6), `Abs (0x001C6); (0x001C9,0x001C9), `Abs (0x001C9); (0x001CC,0x001CC), `Abs (0x001CC); (0x001CE,0x001CE), `Abs (0x001CE); (0x001D0,0x001D0), `Abs (0x001D0); (0x001D2,0x001D2), `Abs (0x001D2); (0x001D4,0x001D4), `Abs (0x001D4); (0x001D6,0x001D6), `Abs (0x001D6); (0x001D8,0x001D8), `Abs (0x001D8); (0x001DA,0x001DA), `Abs (0x001DA); (0x001DC,0x001DD), `Delta (0); (0x001DF,0x001DF), `Abs (0x001DF); (0x001E1,0x001E1), `Abs (0x001E1); (0x001E3,0x001E3), `Abs (0x001E3); (0x001E5,0x001E5), `Abs (0x001E5); (0x001E7,0x001E7), `Abs (0x001E7); (0x001E9,0x001E9), `Abs (0x001E9); (0x001EB,0x001EB), `Abs (0x001EB); (0x001ED,0x001ED), `Abs (0x001ED); (0x001EF,0x001F0), `Delta (0); (0x001F3,0x001F3), `Abs (0x001F3); (0x001F5,0x001F5), `Abs (0x001F5); (0x001F9,0x001F9), `Abs (0x001F9); (0x001FB,0x001FB), `Abs (0x001FB); (0x001FD,0x001FD), `Abs (0x001FD); (0x001FF,0x001FF), `Abs (0x001FF); (0x00201,0x00201), `Abs (0x00201); (0x00203,0x00203), `Abs (0x00203); (0x00205,0x00205), `Abs (0x00205); (0x00207,0x00207), `Abs (0x00207); (0x00209,0x00209), `Abs (0x00209); (0x0020B,0x0020B), `Abs (0x0020B); (0x0020D,0x0020D), `Abs (0x0020D); (0x0020F,0x0020F), `Abs (0x0020F); (0x00211,0x00211), `Abs (0x00211); (0x00213,0x00213), `Abs (0x00213); (0x00215,0x00215), `Abs (0x00215); (0x00217,0x00217), `Abs (0x00217); (0x00219,0x00219), `Abs (0x00219); (0x0021B,0x0021B), `Abs (0x0021B); (0x0021D,0x0021D), `Abs (0x0021D); (0x0021F,0x0021F), `Abs (0x0021F); (0x00221,0x00221), `Abs (0x00221); (0x00223,0x00223), `Abs (0x00223); (0x00225,0x00225), `Abs (0x00225); (0x00227,0x00227), `Abs (0x00227); (0x00229,0x00229), `Abs (0x00229); (0x0022B,0x0022B), `Abs (0x0022B); (0x0022D,0x0022D), `Abs (0x0022D); (0x0022F,0x0022F), `Abs (0x0022F); (0x00231,0x00231), `Abs (0x00231); (0x00233,0x00239), `Delta (0); (0x0023C,0x0023C), `Abs (0x0023C); (0x0023F,0x00240), `Delta (0); (0x00242,0x00242), `Abs (0x00242); (0x00247,0x00247), `Abs (0x00247); (0x00249,0x00249), `Abs (0x00249); (0x0024B,0x0024B), `Abs (0x0024B); (0x0024D,0x0024D), `Abs (0x0024D); (0x0024F,0x00293), `Delta (0); (0x00295,0x002AF), `Delta (0); (0x00371,0x00371), `Abs (0x00371); (0x00373,0x00373), `Abs (0x00373); (0x00377,0x00377), `Abs (0x00377); (0x0037B,0x0037D), `Delta (0); (0x00390,0x00390), `Abs (0x00390); (0x003AC,0x003CE), `Delta (0); (0x003D0,0x003D1), `Delta (0); (0x003D5,0x003D7), `Delta (0); (0x003D9,0x003D9), `Abs (0x003D9); (0x003DB,0x003DB), `Abs (0x003DB); (0x003DD,0x003DD), `Abs (0x003DD); (0x003DF,0x003DF), `Abs (0x003DF); (0x003E1,0x003E1), `Abs (0x003E1); (0x003E3,0x003E3), `Abs (0x003E3); (0x003E5,0x003E5), `Abs (0x003E5); (0x003E7,0x003E7), `Abs (0x003E7); (0x003E9,0x003E9), `Abs (0x003E9); (0x003EB,0x003EB), `Abs (0x003EB); (0x003ED,0x003ED), `Abs (0x003ED); (0x003EF,0x003F3), `Delta (0); (0x003F5,0x003F5), `Abs (0x003F5); (0x003F8,0x003F8), `Abs (0x003F8); (0x003FB,0x003FC), `Delta (0); (0x00430,0x0045F), `Delta (0); (0x00461,0x00461), `Abs (0x00461); (0x00463,0x00463), `Abs (0x00463); (0x00465,0x00465), `Abs (0x00465); (0x00467,0x00467), `Abs (0x00467); (0x00469,0x00469), `Abs (0x00469); (0x0046B,0x0046B), `Abs (0x0046B); (0x0046D,0x0046D), `Abs (0x0046D); (0x0046F,0x0046F), `Abs (0x0046F); (0x00471,0x00471), `Abs (0x00471); (0x00473,0x00473), `Abs (0x00473); (0x00475,0x00475), `Abs (0x00475); (0x00477,0x00477), `Abs (0x00477); (0x00479,0x00479), `Abs (0x00479); (0x0047B,0x0047B), `Abs (0x0047B); (0x0047D,0x0047D), `Abs (0x0047D); (0x0047F,0x0047F), `Abs (0x0047F); (0x00481,0x00481), `Abs (0x00481); (0x0048B,0x0048B), `Abs (0x0048B); (0x0048D,0x0048D), `Abs (0x0048D); (0x0048F,0x0048F), `Abs (0x0048F); (0x00491,0x00491), `Abs (0x00491); (0x00493,0x00493), `Abs (0x00493); (0x00495,0x00495), `Abs (0x00495); (0x00497,0x00497), `Abs (0x00497); (0x00499,0x00499), `Abs (0x00499); (0x0049B,0x0049B), `Abs (0x0049B); (0x0049D,0x0049D), `Abs (0x0049D); (0x0049F,0x0049F), `Abs (0x0049F); (0x004A1,0x004A1), `Abs (0x004A1); (0x004A3,0x004A3), `Abs (0x004A3); (0x004A5,0x004A5), `Abs (0x004A5); (0x004A7,0x004A7), `Abs (0x004A7); (0x004A9,0x004A9), `Abs (0x004A9); (0x004AB,0x004AB), `Abs (0x004AB); (0x004AD,0x004AD), `Abs (0x004AD); (0x004AF,0x004AF), `Abs (0x004AF); (0x004B1,0x004B1), `Abs (0x004B1); (0x004B3,0x004B3), `Abs (0x004B3); (0x004B5,0x004B5), `Abs (0x004B5); (0x004B7,0x004B7), `Abs (0x004B7); (0x004B9,0x004B9), `Abs (0x004B9); (0x004BB,0x004BB), `Abs (0x004BB); (0x004BD,0x004BD), `Abs (0x004BD); (0x004BF,0x004BF), `Abs (0x004BF); (0x004C2,0x004C2), `Abs (0x004C2); (0x004C4,0x004C4), `Abs (0x004C4); (0x004C6,0x004C6), `Abs (0x004C6); (0x004C8,0x004C8), `Abs (0x004C8); (0x004CA,0x004CA), `Abs (0x004CA); (0x004CC,0x004CC), `Abs (0x004CC); (0x004CE,0x004CF), `Delta (0); (0x004D1,0x004D1), `Abs (0x004D1); (0x004D3,0x004D3), `Abs (0x004D3); (0x004D5,0x004D5), `Abs (0x004D5); (0x004D7,0x004D7), `Abs (0x004D7); (0x004D9,0x004D9), `Abs (0x004D9); (0x004DB,0x004DB), `Abs (0x004DB); (0x004DD,0x004DD), `Abs (0x004DD); (0x004DF,0x004DF), `Abs (0x004DF); (0x004E1,0x004E1), `Abs (0x004E1); (0x004E3,0x004E3), `Abs (0x004E3); (0x004E5,0x004E5), `Abs (0x004E5); (0x004E7,0x004E7), `Abs (0x004E7); (0x004E9,0x004E9), `Abs (0x004E9); (0x004EB,0x004EB), `Abs (0x004EB); (0x004ED,0x004ED), `Abs (0x004ED); (0x004EF,0x004EF), `Abs (0x004EF); (0x004F1,0x004F1), `Abs (0x004F1); (0x004F3,0x004F3), `Abs (0x004F3); (0x004F5,0x004F5), `Abs (0x004F5); (0x004F7,0x004F7), `Abs (0x004F7); (0x004F9,0x004F9), `Abs (0x004F9); (0x004FB,0x004FB), `Abs (0x004FB); (0x004FD,0x004FD), `Abs (0x004FD); (0x004FF,0x004FF), `Abs (0x004FF); (0x00501,0x00501), `Abs (0x00501); (0x00503,0x00503), `Abs (0x00503); (0x00505,0x00505), `Abs (0x00505); (0x00507,0x00507), `Abs (0x00507); (0x00509,0x00509), `Abs (0x00509); (0x0050B,0x0050B), `Abs (0x0050B); (0x0050D,0x0050D), `Abs (0x0050D); (0x0050F,0x0050F), `Abs (0x0050F); (0x00511,0x00511), `Abs (0x00511); (0x00513,0x00513), `Abs (0x00513); (0x00515,0x00515), `Abs (0x00515); (0x00517,0x00517), `Abs (0x00517); (0x00519,0x00519), `Abs (0x00519); (0x0051B,0x0051B), `Abs (0x0051B); (0x0051D,0x0051D), `Abs (0x0051D); (0x0051F,0x0051F), `Abs (0x0051F); (0x00521,0x00521), `Abs (0x00521); (0x00523,0x00523), `Abs (0x00523); (0x00525,0x00525), `Abs (0x00525); (0x00527,0x00527), `Abs (0x00527); (0x00529,0x00529), `Abs (0x00529); (0x0052B,0x0052B), `Abs (0x0052B); (0x0052D,0x0052D), `Abs (0x0052D); (0x0052F,0x0052F), `Abs (0x0052F); (0x00561,0x00587), `Delta (0); (0x013F8,0x013FD), `Delta (0); (0x01C80,0x01C88), `Delta (0); (0x01D00,0x01D2B), `Delta (0); (0x01D6B,0x01D77), `Delta (0); (0x01D79,0x01D9A), `Delta (0); (0x01E01,0x01E01), `Abs (0x01E01); (0x01E03,0x01E03), `Abs (0x01E03); (0x01E05,0x01E05), `Abs (0x01E05); (0x01E07,0x01E07), `Abs (0x01E07); (0x01E09,0x01E09), `Abs (0x01E09); (0x01E0B,0x01E0B), `Abs (0x01E0B); (0x01E0D,0x01E0D), `Abs (0x01E0D); (0x01E0F,0x01E0F), `Abs (0x01E0F); (0x01E11,0x01E11), `Abs (0x01E11); (0x01E13,0x01E13), `Abs (0x01E13); (0x01E15,0x01E15), `Abs (0x01E15); (0x01E17,0x01E17), `Abs (0x01E17); (0x01E19,0x01E19), `Abs (0x01E19); (0x01E1B,0x01E1B), `Abs (0x01E1B); (0x01E1D,0x01E1D), `Abs (0x01E1D); (0x01E1F,0x01E1F), `Abs (0x01E1F); (0x01E21,0x01E21), `Abs (0x01E21); (0x01E23,0x01E23), `Abs (0x01E23); (0x01E25,0x01E25), `Abs (0x01E25); (0x01E27,0x01E27), `Abs (0x01E27); (0x01E29,0x01E29), `Abs (0x01E29); (0x01E2B,0x01E2B), `Abs (0x01E2B); (0x01E2D,0x01E2D), `Abs (0x01E2D); (0x01E2F,0x01E2F), `Abs (0x01E2F); (0x01E31,0x01E31), `Abs (0x01E31); (0x01E33,0x01E33), `Abs (0x01E33); (0x01E35,0x01E35), `Abs (0x01E35); (0x01E37,0x01E37), `Abs (0x01E37); (0x01E39,0x01E39), `Abs (0x01E39); (0x01E3B,0x01E3B), `Abs (0x01E3B); (0x01E3D,0x01E3D), `Abs (0x01E3D); (0x01E3F,0x01E3F), `Abs (0x01E3F); (0x01E41,0x01E41), `Abs (0x01E41); (0x01E43,0x01E43), `Abs (0x01E43); (0x01E45,0x01E45), `Abs (0x01E45); (0x01E47,0x01E47), `Abs (0x01E47); (0x01E49,0x01E49), `Abs (0x01E49); (0x01E4B,0x01E4B), `Abs (0x01E4B); (0x01E4D,0x01E4D), `Abs (0x01E4D); (0x01E4F,0x01E4F), `Abs (0x01E4F); (0x01E51,0x01E51), `Abs (0x01E51); (0x01E53,0x01E53), `Abs (0x01E53); (0x01E55,0x01E55), `Abs (0x01E55); (0x01E57,0x01E57), `Abs (0x01E57); (0x01E59,0x01E59), `Abs (0x01E59); (0x01E5B,0x01E5B), `Abs (0x01E5B); (0x01E5D,0x01E5D), `Abs (0x01E5D); (0x01E5F,0x01E5F), `Abs (0x01E5F); (0x01E61,0x01E61), `Abs (0x01E61); (0x01E63,0x01E63), `Abs (0x01E63); (0x01E65,0x01E65), `Abs (0x01E65); (0x01E67,0x01E67), `Abs (0x01E67); (0x01E69,0x01E69), `Abs (0x01E69); (0x01E6B,0x01E6B), `Abs (0x01E6B); (0x01E6D,0x01E6D), `Abs (0x01E6D); (0x01E6F,0x01E6F), `Abs (0x01E6F); (0x01E71,0x01E71), `Abs (0x01E71); (0x01E73,0x01E73), `Abs (0x01E73); (0x01E75,0x01E75), `Abs (0x01E75); (0x01E77,0x01E77), `Abs (0x01E77); (0x01E79,0x01E79), `Abs (0x01E79); (0x01E7B,0x01E7B), `Abs (0x01E7B); (0x01E7D,0x01E7D), `Abs (0x01E7D); (0x01E7F,0x01E7F), `Abs (0x01E7F); (0x01E81,0x01E81), `Abs (0x01E81); (0x01E83,0x01E83), `Abs (0x01E83); (0x01E85,0x01E85), `Abs (0x01E85); (0x01E87,0x01E87), `Abs (0x01E87); (0x01E89,0x01E89), `Abs (0x01E89); (0x01E8B,0x01E8B), `Abs (0x01E8B); (0x01E8D,0x01E8D), `Abs (0x01E8D); (0x01E8F,0x01E8F), `Abs (0x01E8F); (0x01E91,0x01E91), `Abs (0x01E91); (0x01E93,0x01E93), `Abs (0x01E93); (0x01E95,0x01E9D), `Delta (0); (0x01E9F,0x01E9F), `Abs (0x01E9F); (0x01EA1,0x01EA1), `Abs (0x01EA1); (0x01EA3,0x01EA3), `Abs (0x01EA3); (0x01EA5,0x01EA5), `Abs (0x01EA5); (0x01EA7,0x01EA7), `Abs (0x01EA7); (0x01EA9,0x01EA9), `Abs (0x01EA9); (0x01EAB,0x01EAB), `Abs (0x01EAB); (0x01EAD,0x01EAD), `Abs (0x01EAD); (0x01EAF,0x01EAF), `Abs (0x01EAF); (0x01EB1,0x01EB1), `Abs (0x01EB1); (0x01EB3,0x01EB3), `Abs (0x01EB3); (0x01EB5,0x01EB5), `Abs (0x01EB5); (0x01EB7,0x01EB7), `Abs (0x01EB7); (0x01EB9,0x01EB9), `Abs (0x01EB9); (0x01EBB,0x01EBB), `Abs (0x01EBB); (0x01EBD,0x01EBD), `Abs (0x01EBD); (0x01EBF,0x01EBF), `Abs (0x01EBF); (0x01EC1,0x01EC1), `Abs (0x01EC1); (0x01EC3,0x01EC3), `Abs (0x01EC3); (0x01EC5,0x01EC5), `Abs (0x01EC5); (0x01EC7,0x01EC7), `Abs (0x01EC7); (0x01EC9,0x01EC9), `Abs (0x01EC9); (0x01ECB,0x01ECB), `Abs (0x01ECB); (0x01ECD,0x01ECD), `Abs (0x01ECD); (0x01ECF,0x01ECF), `Abs (0x01ECF); (0x01ED1,0x01ED1), `Abs (0x01ED1); (0x01ED3,0x01ED3), `Abs (0x01ED3); (0x01ED5,0x01ED5), `Abs (0x01ED5); (0x01ED7,0x01ED7), `Abs (0x01ED7); (0x01ED9,0x01ED9), `Abs (0x01ED9); (0x01EDB,0x01EDB), `Abs (0x01EDB); (0x01EDD,0x01EDD), `Abs (0x01EDD); (0x01EDF,0x01EDF), `Abs (0x01EDF); (0x01EE1,0x01EE1), `Abs (0x01EE1); (0x01EE3,0x01EE3), `Abs (0x01EE3); (0x01EE5,0x01EE5), `Abs (0x01EE5); (0x01EE7,0x01EE7), `Abs (0x01EE7); (0x01EE9,0x01EE9), `Abs (0x01EE9); (0x01EEB,0x01EEB), `Abs (0x01EEB); (0x01EED,0x01EED), `Abs (0x01EED); (0x01EEF,0x01EEF), `Abs (0x01EEF); (0x01EF1,0x01EF1), `Abs (0x01EF1); (0x01EF3,0x01EF3), `Abs (0x01EF3); (0x01EF5,0x01EF5), `Abs (0x01EF5); (0x01EF7,0x01EF7), `Abs (0x01EF7); (0x01EF9,0x01EF9), `Abs (0x01EF9); (0x01EFB,0x01EFB), `Abs (0x01EFB); (0x01EFD,0x01EFD), `Abs (0x01EFD); (0x01EFF,0x01F07), `Delta (0); (0x01F10,0x01F15), `Delta (0); (0x01F20,0x01F27), `Delta (0); (0x01F30,0x01F37), `Delta (0); (0x01F40,0x01F45), `Delta (0); (0x01F50,0x01F57), `Delta (0); (0x01F60,0x01F67), `Delta (0); (0x01F70,0x01F7D), `Delta (0); (0x01F80,0x01F87), `Delta (0); (0x01F90,0x01F97), `Delta (0); (0x01FA0,0x01FA7), `Delta (0); (0x01FB0,0x01FB4), `Delta (0); (0x01FB6,0x01FB7), `Delta (0); (0x01FBE,0x01FBE), `Abs (0x01FBE); (0x01FC2,0x01FC4), `Delta (0); (0x01FC6,0x01FC7), `Delta (0); (0x01FD0,0x01FD3), `Delta (0); (0x01FD6,0x01FD7), `Delta (0); (0x01FE0,0x01FE7), `Delta (0); (0x01FF2,0x01FF4), `Delta (0); (0x01FF6,0x01FF7), `Delta (0); (0x0210A,0x0210A), `Abs (0x0210A); (0x0210E,0x0210F), `Delta (0); (0x02113,0x02113), `Abs (0x02113); (0x0212F,0x0212F), `Abs (0x0212F); (0x02134,0x02134), `Abs (0x02134); (0x02139,0x02139), `Abs (0x02139); (0x0213C,0x0213D), `Delta (0); (0x02146,0x02149), `Delta (0); (0x0214E,0x0214E), `Abs (0x0214E); (0x02184,0x02184), `Abs (0x02184); (0x02C30,0x02C5E), `Delta (0); (0x02C61,0x02C61), `Abs (0x02C61); (0x02C65,0x02C66), `Delta (0); (0x02C68,0x02C68), `Abs (0x02C68); (0x02C6A,0x02C6A), `Abs (0x02C6A); (0x02C6C,0x02C6C), `Abs (0x02C6C); (0x02C71,0x02C71), `Abs (0x02C71); (0x02C73,0x02C74), `Delta (0); (0x02C76,0x02C7B), `Delta (0); (0x02C81,0x02C81), `Abs (0x02C81); (0x02C83,0x02C83), `Abs (0x02C83); (0x02C85,0x02C85), `Abs (0x02C85); (0x02C87,0x02C87), `Abs (0x02C87); (0x02C89,0x02C89), `Abs (0x02C89); (0x02C8B,0x02C8B), `Abs (0x02C8B); (0x02C8D,0x02C8D), `Abs (0x02C8D); (0x02C8F,0x02C8F), `Abs (0x02C8F); (0x02C91,0x02C91), `Abs (0x02C91); (0x02C93,0x02C93), `Abs (0x02C93); (0x02C95,0x02C95), `Abs (0x02C95); (0x02C97,0x02C97), `Abs (0x02C97); (0x02C99,0x02C99), `Abs (0x02C99); (0x02C9B,0x02C9B), `Abs (0x02C9B); (0x02C9D,0x02C9D), `Abs (0x02C9D); (0x02C9F,0x02C9F), `Abs (0x02C9F); (0x02CA1,0x02CA1), `Abs (0x02CA1); (0x02CA3,0x02CA3), `Abs (0x02CA3); (0x02CA5,0x02CA5), `Abs (0x02CA5); (0x02CA7,0x02CA7), `Abs (0x02CA7); (0x02CA9,0x02CA9), `Abs (0x02CA9); (0x02CAB,0x02CAB), `Abs (0x02CAB); (0x02CAD,0x02CAD), `Abs (0x02CAD); (0x02CAF,0x02CAF), `Abs (0x02CAF); (0x02CB1,0x02CB1), `Abs (0x02CB1); (0x02CB3,0x02CB3), `Abs (0x02CB3); (0x02CB5,0x02CB5), `Abs (0x02CB5); (0x02CB7,0x02CB7), `Abs (0x02CB7); (0x02CB9,0x02CB9), `Abs (0x02CB9); (0x02CBB,0x02CBB), `Abs (0x02CBB); (0x02CBD,0x02CBD), `Abs (0x02CBD); (0x02CBF,0x02CBF), `Abs (0x02CBF); (0x02CC1,0x02CC1), `Abs (0x02CC1); (0x02CC3,0x02CC3), `Abs (0x02CC3); (0x02CC5,0x02CC5), `Abs (0x02CC5); (0x02CC7,0x02CC7), `Abs (0x02CC7); (0x02CC9,0x02CC9), `Abs (0x02CC9); (0x02CCB,0x02CCB), `Abs (0x02CCB); (0x02CCD,0x02CCD), `Abs (0x02CCD); (0x02CCF,0x02CCF), `Abs (0x02CCF); (0x02CD1,0x02CD1), `Abs (0x02CD1); (0x02CD3,0x02CD3), `Abs (0x02CD3); (0x02CD5,0x02CD5), `Abs (0x02CD5); (0x02CD7,0x02CD7), `Abs (0x02CD7); (0x02CD9,0x02CD9), `Abs (0x02CD9); (0x02CDB,0x02CDB), `Abs (0x02CDB); (0x02CDD,0x02CDD), `Abs (0x02CDD); (0x02CDF,0x02CDF), `Abs (0x02CDF); (0x02CE1,0x02CE1), `Abs (0x02CE1); (0x02CE3,0x02CE4), `Delta (0); (0x02CEC,0x02CEC), `Abs (0x02CEC); (0x02CEE,0x02CEE), `Abs (0x02CEE); (0x02CF3,0x02CF3), `Abs (0x02CF3); (0x02D00,0x02D25), `Delta (0); (0x02D27,0x02D27), `Abs (0x02D27); (0x02D2D,0x02D2D), `Abs (0x02D2D); (0x0A641,0x0A641), `Abs (0x0A641); (0x0A643,0x0A643), `Abs (0x0A643); (0x0A645,0x0A645), `Abs (0x0A645); (0x0A647,0x0A647), `Abs (0x0A647); (0x0A649,0x0A649), `Abs (0x0A649); (0x0A64B,0x0A64B), `Abs (0x0A64B); (0x0A64D,0x0A64D), `Abs (0x0A64D); (0x0A64F,0x0A64F), `Abs (0x0A64F); (0x0A651,0x0A651), `Abs (0x0A651); (0x0A653,0x0A653), `Abs (0x0A653); (0x0A655,0x0A655), `Abs (0x0A655); (0x0A657,0x0A657), `Abs (0x0A657); (0x0A659,0x0A659), `Abs (0x0A659); (0x0A65B,0x0A65B), `Abs (0x0A65B); (0x0A65D,0x0A65D), `Abs (0x0A65D); (0x0A65F,0x0A65F), `Abs (0x0A65F); (0x0A661,0x0A661), `Abs (0x0A661); (0x0A663,0x0A663), `Abs (0x0A663); (0x0A665,0x0A665), `Abs (0x0A665); (0x0A667,0x0A667), `Abs (0x0A667); (0x0A669,0x0A669), `Abs (0x0A669); (0x0A66B,0x0A66B), `Abs (0x0A66B); (0x0A66D,0x0A66D), `Abs (0x0A66D); (0x0A681,0x0A681), `Abs (0x0A681); (0x0A683,0x0A683), `Abs (0x0A683); (0x0A685,0x0A685), `Abs (0x0A685); (0x0A687,0x0A687), `Abs (0x0A687); (0x0A689,0x0A689), `Abs (0x0A689); (0x0A68B,0x0A68B), `Abs (0x0A68B); (0x0A68D,0x0A68D), `Abs (0x0A68D); (0x0A68F,0x0A68F), `Abs (0x0A68F); (0x0A691,0x0A691), `Abs (0x0A691); (0x0A693,0x0A693), `Abs (0x0A693); (0x0A695,0x0A695), `Abs (0x0A695); (0x0A697,0x0A697), `Abs (0x0A697); (0x0A699,0x0A699), `Abs (0x0A699); (0x0A69B,0x0A69B), `Abs (0x0A69B); (0x0A723,0x0A723), `Abs (0x0A723); (0x0A725,0x0A725), `Abs (0x0A725); (0x0A727,0x0A727), `Abs (0x0A727); (0x0A729,0x0A729), `Abs (0x0A729); (0x0A72B,0x0A72B), `Abs (0x0A72B); (0x0A72D,0x0A72D), `Abs (0x0A72D); (0x0A72F,0x0A731), `Delta (0); (0x0A733,0x0A733), `Abs (0x0A733); (0x0A735,0x0A735), `Abs (0x0A735); (0x0A737,0x0A737), `Abs (0x0A737); (0x0A739,0x0A739), `Abs (0x0A739); (0x0A73B,0x0A73B), `Abs (0x0A73B); (0x0A73D,0x0A73D), `Abs (0x0A73D); (0x0A73F,0x0A73F), `Abs (0x0A73F); (0x0A741,0x0A741), `Abs (0x0A741); (0x0A743,0x0A743), `Abs (0x0A743); (0x0A745,0x0A745), `Abs (0x0A745); (0x0A747,0x0A747), `Abs (0x0A747); (0x0A749,0x0A749), `Abs (0x0A749); (0x0A74B,0x0A74B), `Abs (0x0A74B); (0x0A74D,0x0A74D), `Abs (0x0A74D); (0x0A74F,0x0A74F), `Abs (0x0A74F); (0x0A751,0x0A751), `Abs (0x0A751); (0x0A753,0x0A753), `Abs (0x0A753); (0x0A755,0x0A755), `Abs (0x0A755); (0x0A757,0x0A757), `Abs (0x0A757); (0x0A759,0x0A759), `Abs (0x0A759); (0x0A75B,0x0A75B), `Abs (0x0A75B); (0x0A75D,0x0A75D), `Abs (0x0A75D); (0x0A75F,0x0A75F), `Abs (0x0A75F); (0x0A761,0x0A761), `Abs (0x0A761); (0x0A763,0x0A763), `Abs (0x0A763); (0x0A765,0x0A765), `Abs (0x0A765); (0x0A767,0x0A767), `Abs (0x0A767); (0x0A769,0x0A769), `Abs (0x0A769); (0x0A76B,0x0A76B), `Abs (0x0A76B); (0x0A76D,0x0A76D), `Abs (0x0A76D); (0x0A76F,0x0A76F), `Abs (0x0A76F); (0x0A771,0x0A778), `Delta (0); (0x0A77A,0x0A77A), `Abs (0x0A77A); (0x0A77C,0x0A77C), `Abs (0x0A77C); (0x0A77F,0x0A77F), `Abs (0x0A77F); (0x0A781,0x0A781), `Abs (0x0A781); (0x0A783,0x0A783), `Abs (0x0A783); (0x0A785,0x0A785), `Abs (0x0A785); (0x0A787,0x0A787), `Abs (0x0A787); (0x0A78C,0x0A78C), `Abs (0x0A78C); (0x0A78E,0x0A78E), `Abs (0x0A78E); (0x0A791,0x0A791), `Abs (0x0A791); (0x0A793,0x0A795), `Delta (0); (0x0A797,0x0A797), `Abs (0x0A797); (0x0A799,0x0A799), `Abs (0x0A799); (0x0A79B,0x0A79B), `Abs (0x0A79B); (0x0A79D,0x0A79D), `Abs (0x0A79D); (0x0A79F,0x0A79F), `Abs (0x0A79F); (0x0A7A1,0x0A7A1), `Abs (0x0A7A1); (0x0A7A3,0x0A7A3), `Abs (0x0A7A3); (0x0A7A5,0x0A7A5), `Abs (0x0A7A5); (0x0A7A7,0x0A7A7), `Abs (0x0A7A7); (0x0A7A9,0x0A7A9), `Abs (0x0A7A9); (0x0A7B5,0x0A7B5), `Abs (0x0A7B5); (0x0A7B7,0x0A7B7), `Abs (0x0A7B7); (0x0A7FA,0x0A7FA), `Abs (0x0A7FA); (0x0AB30,0x0AB5A), `Delta (0); (0x0AB60,0x0AB65), `Delta (0); (0x0AB70,0x0ABBF), `Delta (0); (0x0FB00,0x0FB06), `Delta (0); (0x0FB13,0x0FB17), `Delta (0); (0x0FF41,0x0FF5A), `Delta (0); (0x10428,0x1044F), `Delta (0); (0x104D8,0x104FB), `Delta (0); (0x10CC0,0x10CF2), `Delta (0); (0x118C0,0x118DF), `Delta (0); (0x1D41A,0x1D433), `Delta (0); (0x1D44E,0x1D454), `Delta (0); (0x1D456,0x1D467), `Delta (0); (0x1D482,0x1D49B), `Delta (0); (0x1D4B6,0x1D4B9), `Delta (0); (0x1D4BB,0x1D4BB), `Abs (0x1D4BB); (0x1D4BD,0x1D4C3), `Delta (0); (0x1D4C5,0x1D4CF), `Delta (0); (0x1D4EA,0x1D503), `Delta (0); (0x1D51E,0x1D537), `Delta (0); (0x1D552,0x1D56B), `Delta (0); (0x1D586,0x1D59F), `Delta (0); (0x1D5BA,0x1D5D3), `Delta (0); (0x1D5EE,0x1D607), `Delta (0); (0x1D622,0x1D63B), `Delta (0); (0x1D656,0x1D66F), `Delta (0); (0x1D68A,0x1D6A5), `Delta (0); (0x1D6C2,0x1D6DA), `Delta (0); (0x1D6DC,0x1D6E1), `Delta (0); (0x1D6FC,0x1D714), `Delta (0); (0x1D716,0x1D71B), `Delta (0); (0x1D736,0x1D74E), `Delta (0); (0x1D750,0x1D755), `Delta (0); (0x1D770,0x1D788), `Delta (0); (0x1D78A,0x1D78F), `Delta (0); (0x1D7AA,0x1D7C2), `Delta (0); (0x1D7C4,0x1D7C9), `Delta (0); (0x1D7CB,0x1D7CB), `Abs (0x1D7CB); (0x1E922,0x1E943), `Delta (0); (0x001C5,0x001C5), `Abs (0x001C6); (0x001C8,0x001C8), `Abs (0x001C9); (0x001CB,0x001CB), `Abs (0x001CC); (0x001F2,0x001F2), `Abs (0x001F3); (0x01F88,0x01F8F), `Delta (-8); (0x01F98,0x01F9F), `Delta (-8); (0x01FA8,0x01FAF), `Delta (-8); (0x01FBC,0x01FBC), `Abs (0x01FB3); (0x01FCC,0x01FCC), `Abs (0x01FC3); (0x01FFC,0x01FFC), `Abs (0x01FF3); (0x00300,0x0036F), `Delta (0); (0x00483,0x00487), `Delta (0); (0x00591,0x005BD), `Delta (0); (0x005BF,0x005BF), `Abs (0x005BF); (0x005C1,0x005C2), `Delta (0); (0x005C4,0x005C5), `Delta (0); (0x005C7,0x005C7), `Abs (0x005C7); (0x00610,0x0061A), `Delta (0); (0x0064B,0x0065F), `Delta (0); (0x00670,0x00670), `Abs (0x00670); (0x006D6,0x006DC), `Delta (0); (0x006DF,0x006E4), `Delta (0); (0x006E7,0x006E8), `Delta (0); (0x006EA,0x006ED), `Delta (0); (0x00711,0x00711), `Abs (0x00711); (0x00730,0x0074A), `Delta (0); (0x007A6,0x007B0), `Delta (0); (0x007EB,0x007F3), `Delta (0); (0x00816,0x00819), `Delta (0); (0x0081B,0x00823), `Delta (0); (0x00825,0x00827), `Delta (0); (0x00829,0x0082D), `Delta (0); (0x00859,0x0085B), `Delta (0); (0x008D4,0x008E1), `Delta (0); (0x008E3,0x00902), `Delta (0); (0x0093A,0x0093A), `Abs (0x0093A); (0x0093C,0x0093C), `Abs (0x0093C); (0x00941,0x00948), `Delta (0); (0x0094D,0x0094D), `Abs (0x0094D); (0x00951,0x00957), `Delta (0); (0x00962,0x00963), `Delta (0); (0x00981,0x00981), `Abs (0x00981); (0x009BC,0x009BC), `Abs (0x009BC); (0x009C1,0x009C4), `Delta (0); (0x009CD,0x009CD), `Abs (0x009CD); (0x009E2,0x009E3), `Delta (0); (0x00A01,0x00A02), `Delta (0); (0x00A3C,0x00A3C), `Abs (0x00A3C); (0x00A41,0x00A42), `Delta (0); (0x00A47,0x00A48), `Delta (0); (0x00A4B,0x00A4D), `Delta (0); (0x00A51,0x00A51), `Abs (0x00A51); (0x00A70,0x00A71), `Delta (0); (0x00A75,0x00A75), `Abs (0x00A75); (0x00A81,0x00A82), `Delta (0); (0x00ABC,0x00ABC), `Abs (0x00ABC); (0x00AC1,0x00AC5), `Delta (0); (0x00AC7,0x00AC8), `Delta (0); (0x00ACD,0x00ACD), `Abs (0x00ACD); (0x00AE2,0x00AE3), `Delta (0); (0x00B01,0x00B01), `Abs (0x00B01); (0x00B3C,0x00B3C), `Abs (0x00B3C); (0x00B3F,0x00B3F), `Abs (0x00B3F); (0x00B41,0x00B44), `Delta (0); (0x00B4D,0x00B4D), `Abs (0x00B4D); (0x00B56,0x00B56), `Abs (0x00B56); (0x00B62,0x00B63), `Delta (0); (0x00B82,0x00B82), `Abs (0x00B82); (0x00BC0,0x00BC0), `Abs (0x00BC0); (0x00BCD,0x00BCD), `Abs (0x00BCD); (0x00C00,0x00C00), `Abs (0x00C00); (0x00C3E,0x00C40), `Delta (0); (0x00C46,0x00C48), `Delta (0); (0x00C4A,0x00C4D), `Delta (0); (0x00C55,0x00C56), `Delta (0); (0x00C62,0x00C63), `Delta (0); (0x00C81,0x00C81), `Abs (0x00C81); (0x00CBC,0x00CBC), `Abs (0x00CBC); (0x00CBF,0x00CBF), `Abs (0x00CBF); (0x00CC6,0x00CC6), `Abs (0x00CC6); (0x00CCC,0x00CCD), `Delta (0); (0x00CE2,0x00CE3), `Delta (0); (0x00D01,0x00D01), `Abs (0x00D01); (0x00D41,0x00D44), `Delta (0); (0x00D4D,0x00D4D), `Abs (0x00D4D); (0x00D62,0x00D63), `Delta (0); (0x00DCA,0x00DCA), `Abs (0x00DCA); (0x00DD2,0x00DD4), `Delta (0); (0x00DD6,0x00DD6), `Abs (0x00DD6); (0x00E31,0x00E31), `Abs (0x00E31); (0x00E34,0x00E3A), `Delta (0); (0x00E47,0x00E4E), `Delta (0); (0x00EB1,0x00EB1), `Abs (0x00EB1); (0x00EB4,0x00EB9), `Delta (0); (0x00EBB,0x00EBC), `Delta (0); (0x00EC8,0x00ECD), `Delta (0); (0x00F18,0x00F19), `Delta (0); (0x00F35,0x00F35), `Abs (0x00F35); (0x00F37,0x00F37), `Abs (0x00F37); (0x00F39,0x00F39), `Abs (0x00F39); (0x00F71,0x00F7E), `Delta (0); (0x00F80,0x00F84), `Delta (0); (0x00F86,0x00F87), `Delta (0); (0x00F8D,0x00F97), `Delta (0); (0x00F99,0x00FBC), `Delta (0); (0x00FC6,0x00FC6), `Abs (0x00FC6); (0x0102D,0x01030), `Delta (0); (0x01032,0x01037), `Delta (0); (0x01039,0x0103A), `Delta (0); (0x0103D,0x0103E), `Delta (0); (0x01058,0x01059), `Delta (0); (0x0105E,0x01060), `Delta (0); (0x01071,0x01074), `Delta (0); (0x01082,0x01082), `Abs (0x01082); (0x01085,0x01086), `Delta (0); (0x0108D,0x0108D), `Abs (0x0108D); (0x0109D,0x0109D), `Abs (0x0109D); (0x0135D,0x0135F), `Delta (0); (0x01712,0x01714), `Delta (0); (0x01732,0x01734), `Delta (0); (0x01752,0x01753), `Delta (0); (0x01772,0x01773), `Delta (0); (0x017B4,0x017B5), `Delta (0); (0x017B7,0x017BD), `Delta (0); (0x017C6,0x017C6), `Abs (0x017C6); (0x017C9,0x017D3), `Delta (0); (0x017DD,0x017DD), `Abs (0x017DD); (0x0180B,0x0180D), `Delta (0); (0x01885,0x01886), `Delta (0); (0x018A9,0x018A9), `Abs (0x018A9); (0x01920,0x01922), `Delta (0); (0x01927,0x01928), `Delta (0); (0x01932,0x01932), `Abs (0x01932); (0x01939,0x0193B), `Delta (0); (0x01A17,0x01A18), `Delta (0); (0x01A1B,0x01A1B), `Abs (0x01A1B); (0x01A56,0x01A56), `Abs (0x01A56); (0x01A58,0x01A5E), `Delta (0); (0x01A60,0x01A60), `Abs (0x01A60); (0x01A62,0x01A62), `Abs (0x01A62); (0x01A65,0x01A6C), `Delta (0); (0x01A73,0x01A7C), `Delta (0); (0x01A7F,0x01A7F), `Abs (0x01A7F); (0x01AB0,0x01ABD), `Delta (0); (0x01B00,0x01B03), `Delta (0); (0x01B34,0x01B34), `Abs (0x01B34); (0x01B36,0x01B3A), `Delta (0); (0x01B3C,0x01B3C), `Abs (0x01B3C); (0x01B42,0x01B42), `Abs (0x01B42); (0x01B6B,0x01B73), `Delta (0); (0x01B80,0x01B81), `Delta (0); (0x01BA2,0x01BA5), `Delta (0); (0x01BA8,0x01BA9), `Delta (0); (0x01BAB,0x01BAD), `Delta (0); (0x01BE6,0x01BE6), `Abs (0x01BE6); (0x01BE8,0x01BE9), `Delta (0); (0x01BED,0x01BED), `Abs (0x01BED); (0x01BEF,0x01BF1), `Delta (0); (0x01C2C,0x01C33), `Delta (0); (0x01C36,0x01C37), `Delta (0); (0x01CD0,0x01CD2), `Delta (0); (0x01CD4,0x01CE0), `Delta (0); (0x01CE2,0x01CE8), `Delta (0); (0x01CED,0x01CED), `Abs (0x01CED); (0x01CF4,0x01CF4), `Abs (0x01CF4); (0x01CF8,0x01CF9), `Delta (0); (0x01DC0,0x01DF5), `Delta (0); (0x01DFB,0x01DFF), `Delta (0); (0x020D0,0x020DC), `Delta (0); (0x020E1,0x020E1), `Abs (0x020E1); (0x020E5,0x020F0), `Delta (0); (0x02CEF,0x02CF1), `Delta (0); (0x02D7F,0x02D7F), `Abs (0x02D7F); (0x02DE0,0x02DFF), `Delta (0); (0x0302A,0x0302D), `Delta (0); (0x03099,0x0309A), `Delta (0); (0x0A66F,0x0A66F), `Abs (0x0A66F); (0x0A674,0x0A67D), `Delta (0); (0x0A69E,0x0A69F), `Delta (0); (0x0A6F0,0x0A6F1), `Delta (0); (0x0A802,0x0A802), `Abs (0x0A802); (0x0A806,0x0A806), `Abs (0x0A806); (0x0A80B,0x0A80B), `Abs (0x0A80B); (0x0A825,0x0A826), `Delta (0); (0x0A8C4,0x0A8C5), `Delta (0); (0x0A8E0,0x0A8F1), `Delta (0); (0x0A926,0x0A92D), `Delta (0); (0x0A947,0x0A951), `Delta (0); (0x0A980,0x0A982), `Delta (0); (0x0A9B3,0x0A9B3), `Abs (0x0A9B3); (0x0A9B6,0x0A9B9), `Delta (0); (0x0A9BC,0x0A9BC), `Abs (0x0A9BC); (0x0A9E5,0x0A9E5), `Abs (0x0A9E5); (0x0AA29,0x0AA2E), `Delta (0); (0x0AA31,0x0AA32), `Delta (0); (0x0AA35,0x0AA36), `Delta (0); (0x0AA43,0x0AA43), `Abs (0x0AA43); (0x0AA4C,0x0AA4C), `Abs (0x0AA4C); (0x0AA7C,0x0AA7C), `Abs (0x0AA7C); (0x0AAB0,0x0AAB0), `Abs (0x0AAB0); (0x0AAB2,0x0AAB4), `Delta (0); (0x0AAB7,0x0AAB8), `Delta (0); (0x0AABE,0x0AABF), `Delta (0); (0x0AAC1,0x0AAC1), `Abs (0x0AAC1); (0x0AAEC,0x0AAED), `Delta (0); (0x0AAF6,0x0AAF6), `Abs (0x0AAF6); (0x0ABE5,0x0ABE5), `Abs (0x0ABE5); (0x0ABE8,0x0ABE8), `Abs (0x0ABE8); (0x0ABED,0x0ABED), `Abs (0x0ABED); (0x0FB1E,0x0FB1E), `Abs (0x0FB1E); (0x0FE00,0x0FE0F), `Delta (0); (0x0FE20,0x0FE2F), `Delta (0); (0x101FD,0x101FD), `Abs (0x101FD); (0x102E0,0x102E0), `Abs (0x102E0); (0x10376,0x1037A), `Delta (0); (0x10A01,0x10A03), `Delta (0); (0x10A05,0x10A06), `Delta (0); (0x10A0C,0x10A0F), `Delta (0); (0x10A38,0x10A3A), `Delta (0); (0x10A3F,0x10A3F), `Abs (0x10A3F); (0x10AE5,0x10AE6), `Delta (0); (0x11001,0x11001), `Abs (0x11001); (0x11038,0x11046), `Delta (0); (0x1107F,0x11081), `Delta (0); (0x110B3,0x110B6), `Delta (0); (0x110B9,0x110BA), `Delta (0); (0x11100,0x11102), `Delta (0); (0x11127,0x1112B), `Delta (0); (0x1112D,0x11134), `Delta (0); (0x11173,0x11173), `Abs (0x11173); (0x11180,0x11181), `Delta (0); (0x111B6,0x111BE), `Delta (0); (0x111CA,0x111CC), `Delta (0); (0x1122F,0x11231), `Delta (0); (0x11234,0x11234), `Abs (0x11234); (0x11236,0x11237), `Delta (0); (0x1123E,0x1123E), `Abs (0x1123E); (0x112DF,0x112DF), `Abs (0x112DF); (0x112E3,0x112EA), `Delta (0); (0x11300,0x11301), `Delta (0); (0x1133C,0x1133C), `Abs (0x1133C); (0x11340,0x11340), `Abs (0x11340); (0x11366,0x1136C), `Delta (0); (0x11370,0x11374), `Delta (0); (0x11438,0x1143F), `Delta (0); (0x11442,0x11444), `Delta (0); (0x11446,0x11446), `Abs (0x11446); (0x114B3,0x114B8), `Delta (0); (0x114BA,0x114BA), `Abs (0x114BA); (0x114BF,0x114C0), `Delta (0); (0x114C2,0x114C3), `Delta (0); (0x115B2,0x115B5), `Delta (0); (0x115BC,0x115BD), `Delta (0); (0x115BF,0x115C0), `Delta (0); (0x115DC,0x115DD), `Delta (0); (0x11633,0x1163A), `Delta (0); (0x1163D,0x1163D), `Abs (0x1163D); (0x1163F,0x11640), `Delta (0); (0x116AB,0x116AB), `Abs (0x116AB); (0x116AD,0x116AD), `Abs (0x116AD); (0x116B0,0x116B5), `Delta (0); (0x116B7,0x116B7), `Abs (0x116B7); (0x1171D,0x1171F), `Delta (0); (0x11722,0x11725), `Delta (0); (0x11727,0x1172B), `Delta (0); (0x11C30,0x11C36), `Delta (0); (0x11C38,0x11C3D), `Delta (0); (0x11C3F,0x11C3F), `Abs (0x11C3F); (0x11C92,0x11CA7), `Delta (0); (0x11CAA,0x11CB0), `Delta (0); (0x11CB2,0x11CB3), `Delta (0); (0x11CB5,0x11CB6), `Delta (0); (0x16AF0,0x16AF4), `Delta (0); (0x16B30,0x16B36), `Delta (0); (0x16F8F,0x16F92), `Delta (0); (0x1BC9D,0x1BC9E), `Delta (0); (0x1D167,0x1D169), `Delta (0); (0x1D17B,0x1D182), `Delta (0); (0x1D185,0x1D18B), `Delta (0); (0x1D1AA,0x1D1AD), `Delta (0); (0x1D242,0x1D244), `Delta (0); (0x1DA00,0x1DA36), `Delta (0); (0x1DA3B,0x1DA6C), `Delta (0); (0x1DA75,0x1DA75), `Abs (0x1DA75); (0x1DA84,0x1DA84), `Abs (0x1DA84); (0x1DA9B,0x1DA9F), `Delta (0); (0x1DAA1,0x1DAAF), `Delta (0); (0x1E000,0x1E006), `Delta (0); (0x1E008,0x1E018), `Delta (0); (0x1E01B,0x1E021), `Delta (0); (0x1E023,0x1E024), `Delta (0); (0x1E026,0x1E02A), `Delta (0); (0x1E8D0,0x1E8D6), `Delta (0); (0x1E944,0x1E94A), `Delta (0); (0xE0100,0xE01EF), `Delta (0); (0x00903,0x00903), `Abs (0x00903); (0x0093B,0x0093B), `Abs (0x0093B); (0x0093E,0x00940), `Delta (0); (0x00949,0x0094C), `Delta (0); (0x0094E,0x0094F), `Delta (0); (0x00982,0x00983), `Delta (0); (0x009BE,0x009C0), `Delta (0); (0x009C7,0x009C8), `Delta (0); (0x009CB,0x009CC), `Delta (0); (0x009D7,0x009D7), `Abs (0x009D7); (0x00A03,0x00A03), `Abs (0x00A03); (0x00A3E,0x00A40), `Delta (0); (0x00A83,0x00A83), `Abs (0x00A83); (0x00ABE,0x00AC0), `Delta (0); (0x00AC9,0x00AC9), `Abs (0x00AC9); (0x00ACB,0x00ACC), `Delta (0); (0x00B02,0x00B03), `Delta (0); (0x00B3E,0x00B3E), `Abs (0x00B3E); (0x00B40,0x00B40), `Abs (0x00B40); (0x00B47,0x00B48), `Delta (0); (0x00B4B,0x00B4C), `Delta (0); (0x00B57,0x00B57), `Abs (0x00B57); (0x00BBE,0x00BBF), `Delta (0); (0x00BC1,0x00BC2), `Delta (0); (0x00BC6,0x00BC8), `Delta (0); (0x00BCA,0x00BCC), `Delta (0); (0x00BD7,0x00BD7), `Abs (0x00BD7); (0x00C01,0x00C03), `Delta (0); (0x00C41,0x00C44), `Delta (0); (0x00C82,0x00C83), `Delta (0); (0x00CBE,0x00CBE), `Abs (0x00CBE); (0x00CC0,0x00CC4), `Delta (0); (0x00CC7,0x00CC8), `Delta (0); (0x00CCA,0x00CCB), `Delta (0); (0x00CD5,0x00CD6), `Delta (0); (0x00D02,0x00D03), `Delta (0); (0x00D3E,0x00D40), `Delta (0); (0x00D46,0x00D48), `Delta (0); (0x00D4A,0x00D4C), `Delta (0); (0x00D57,0x00D57), `Abs (0x00D57); (0x00D82,0x00D83), `Delta (0); (0x00DCF,0x00DD1), `Delta (0); (0x00DD8,0x00DDF), `Delta (0); (0x00DF2,0x00DF3), `Delta (0); (0x00F3E,0x00F3F), `Delta (0); (0x00F7F,0x00F7F), `Abs (0x00F7F); (0x0102B,0x0102C), `Delta (0); (0x01031,0x01031), `Abs (0x01031); (0x01038,0x01038), `Abs (0x01038); (0x0103B,0x0103C), `Delta (0); (0x01056,0x01057), `Delta (0); (0x01062,0x01064), `Delta (0); (0x01067,0x0106D), `Delta (0); (0x01083,0x01084), `Delta (0); (0x01087,0x0108C), `Delta (0); (0x0108F,0x0108F), `Abs (0x0108F); (0x0109A,0x0109C), `Delta (0); (0x017B6,0x017B6), `Abs (0x017B6); (0x017BE,0x017C5), `Delta (0); (0x017C7,0x017C8), `Delta (0); (0x01923,0x01926), `Delta (0); (0x01929,0x0192B), `Delta (0); (0x01930,0x01931), `Delta (0); (0x01933,0x01938), `Delta (0); (0x01A19,0x01A1A), `Delta (0); (0x01A55,0x01A55), `Abs (0x01A55); (0x01A57,0x01A57), `Abs (0x01A57); (0x01A61,0x01A61), `Abs (0x01A61); (0x01A63,0x01A64), `Delta (0); (0x01A6D,0x01A72), `Delta (0); (0x01B04,0x01B04), `Abs (0x01B04); (0x01B35,0x01B35), `Abs (0x01B35); (0x01B3B,0x01B3B), `Abs (0x01B3B); (0x01B3D,0x01B41), `Delta (0); (0x01B43,0x01B44), `Delta (0); (0x01B82,0x01B82), `Abs (0x01B82); (0x01BA1,0x01BA1), `Abs (0x01BA1); (0x01BA6,0x01BA7), `Delta (0); (0x01BAA,0x01BAA), `Abs (0x01BAA); (0x01BE7,0x01BE7), `Abs (0x01BE7); (0x01BEA,0x01BEC), `Delta (0); (0x01BEE,0x01BEE), `Abs (0x01BEE); (0x01BF2,0x01BF3), `Delta (0); (0x01C24,0x01C2B), `Delta (0); (0x01C34,0x01C35), `Delta (0); (0x01CE1,0x01CE1), `Abs (0x01CE1); (0x01CF2,0x01CF3), `Delta (0); (0x0302E,0x0302F), `Delta (0); (0x0A823,0x0A824), `Delta (0); (0x0A827,0x0A827), `Abs (0x0A827); (0x0A880,0x0A881), `Delta (0); (0x0A8B4,0x0A8C3), `Delta (0); (0x0A952,0x0A953), `Delta (0); (0x0A983,0x0A983), `Abs (0x0A983); (0x0A9B4,0x0A9B5), `Delta (0); (0x0A9BA,0x0A9BB), `Delta (0); (0x0A9BD,0x0A9C0), `Delta (0); (0x0AA2F,0x0AA30), `Delta (0); (0x0AA33,0x0AA34), `Delta (0); (0x0AA4D,0x0AA4D), `Abs (0x0AA4D); (0x0AA7B,0x0AA7B), `Abs (0x0AA7B); (0x0AA7D,0x0AA7D), `Abs (0x0AA7D); (0x0AAEB,0x0AAEB), `Abs (0x0AAEB); (0x0AAEE,0x0AAEF), `Delta (0); (0x0AAF5,0x0AAF5), `Abs (0x0AAF5); (0x0ABE3,0x0ABE4), `Delta (0); (0x0ABE6,0x0ABE7), `Delta (0); (0x0ABE9,0x0ABEA), `Delta (0); (0x0ABEC,0x0ABEC), `Abs (0x0ABEC); (0x11000,0x11000), `Abs (0x11000); (0x11002,0x11002), `Abs (0x11002); (0x11082,0x11082), `Abs (0x11082); (0x110B0,0x110B2), `Delta (0); (0x110B7,0x110B8), `Delta (0); (0x1112C,0x1112C), `Abs (0x1112C); (0x11182,0x11182), `Abs (0x11182); (0x111B3,0x111B5), `Delta (0); (0x111BF,0x111C0), `Delta (0); (0x1122C,0x1122E), `Delta (0); (0x11232,0x11233), `Delta (0); (0x11235,0x11235), `Abs (0x11235); (0x112E0,0x112E2), `Delta (0); (0x11302,0x11303), `Delta (0); (0x1133E,0x1133F), `Delta (0); (0x11341,0x11344), `Delta (0); (0x11347,0x11348), `Delta (0); (0x1134B,0x1134D), `Delta (0); (0x11357,0x11357), `Abs (0x11357); (0x11362,0x11363), `Delta (0); (0x11435,0x11437), `Delta (0); (0x11440,0x11441), `Delta (0); (0x11445,0x11445), `Abs (0x11445); (0x114B0,0x114B2), `Delta (0); (0x114B9,0x114B9), `Abs (0x114B9); (0x114BB,0x114BE), `Delta (0); (0x114C1,0x114C1), `Abs (0x114C1); (0x115AF,0x115B1), `Delta (0); (0x115B8,0x115BB), `Delta (0); (0x115BE,0x115BE), `Abs (0x115BE); (0x11630,0x11632), `Delta (0); (0x1163B,0x1163C), `Delta (0); (0x1163E,0x1163E), `Abs (0x1163E); (0x116AC,0x116AC), `Abs (0x116AC); (0x116AE,0x116AF), `Delta (0); (0x116B6,0x116B6), `Abs (0x116B6); (0x11720,0x11721), `Delta (0); (0x11726,0x11726), `Abs (0x11726); (0x11C2F,0x11C2F), `Abs (0x11C2F); (0x11C3E,0x11C3E), `Abs (0x11C3E); (0x11CA9,0x11CA9), `Abs (0x11CA9); (0x11CB1,0x11CB1), `Abs (0x11CB1); (0x11CB4,0x11CB4), `Abs (0x11CB4); (0x16F51,0x16F7E), `Delta (0); (0x1D165,0x1D166), `Delta (0); (0x1D16D,0x1D172), `Delta (0); (0x00488,0x00489), `Delta (0); (0x01ABE,0x01ABE), `Abs (0x01ABE); (0x020DD,0x020E0), `Delta (0); (0x020E2,0x020E4), `Delta (0); (0x0A670,0x0A672), `Delta (0); (0x00030,0x00039), `Delta (0); (0x00660,0x00669), `Delta (0); (0x006F0,0x006F9), `Delta (0); (0x007C0,0x007C9), `Delta (0); (0x00966,0x0096F), `Delta (0); (0x009E6,0x009EF), `Delta (0); (0x00A66,0x00A6F), `Delta (0); (0x00AE6,0x00AEF), `Delta (0); (0x00B66,0x00B6F), `Delta (0); (0x00BE6,0x00BEF), `Delta (0); (0x00C66,0x00C6F), `Delta (0); (0x00CE6,0x00CEF), `Delta (0); (0x00D66,0x00D6F), `Delta (0); (0x00DE6,0x00DEF), `Delta (0); (0x00E50,0x00E59), `Delta (0); (0x00ED0,0x00ED9), `Delta (0); (0x00F20,0x00F29), `Delta (0); (0x01040,0x01049), `Delta (0); (0x01090,0x01099), `Delta (0); (0x017E0,0x017E9), `Delta (0); (0x01810,0x01819), `Delta (0); (0x01946,0x0194F), `Delta (0); (0x019D0,0x019D9), `Delta (0); (0x01A80,0x01A89), `Delta (0); (0x01A90,0x01A99), `Delta (0); (0x01B50,0x01B59), `Delta (0); (0x01BB0,0x01BB9), `Delta (0); (0x01C40,0x01C49), `Delta (0); (0x01C50,0x01C59), `Delta (0); (0x0A620,0x0A629), `Delta (0); (0x0A8D0,0x0A8D9), `Delta (0); (0x0A900,0x0A909), `Delta (0); (0x0A9D0,0x0A9D9), `Delta (0); (0x0A9F0,0x0A9F9), `Delta (0); (0x0AA50,0x0AA59), `Delta (0); (0x0ABF0,0x0ABF9), `Delta (0); (0x0FF10,0x0FF19), `Delta (0); (0x104A0,0x104A9), `Delta (0); (0x11066,0x1106F), `Delta (0); (0x110F0,0x110F9), `Delta (0); (0x11136,0x1113F), `Delta (0); (0x111D0,0x111D9), `Delta (0); (0x112F0,0x112F9), `Delta (0); (0x11450,0x11459), `Delta (0); (0x114D0,0x114D9), `Delta (0); (0x11650,0x11659), `Delta (0); (0x116C0,0x116C9), `Delta (0); (0x11730,0x11739), `Delta (0); (0x118E0,0x118E9), `Delta (0); (0x11C50,0x11C59), `Delta (0); (0x16A60,0x16A69), `Delta (0); (0x16B50,0x16B59), `Delta (0); (0x1D7CE,0x1D7FF), `Delta (0); (0x1E950,0x1E959), `Delta (0); (0x016EE,0x016F0), `Delta (0); (0x02160,0x0216F), `Delta (16); (0x02170,0x02182), `Delta (0); (0x02185,0x02188), `Delta (0); (0x03007,0x03007), `Abs (0x03007); (0x03021,0x03029), `Delta (0); (0x03038,0x0303A), `Delta (0); (0x0A6E6,0x0A6EF), `Delta (0); (0x10140,0x10174), `Delta (0); (0x10341,0x10341), `Abs (0x10341); (0x1034A,0x1034A), `Abs (0x1034A); (0x103D1,0x103D5), `Delta (0); (0x12400,0x1246E), `Delta (0); (0x000B2,0x000B3), `Delta (0); (0x000B9,0x000B9), `Abs (0x000B9); (0x000BC,0x000BE), `Delta (0); (0x009F4,0x009F9), `Delta (0); (0x00B72,0x00B77), `Delta (0); (0x00BF0,0x00BF2), `Delta (0); (0x00C78,0x00C7E), `Delta (0); (0x00D58,0x00D5E), `Delta (0); (0x00D70,0x00D78), `Delta (0); (0x00F2A,0x00F33), `Delta (0); (0x01369,0x0137C), `Delta (0); (0x017F0,0x017F9), `Delta (0); (0x019DA,0x019DA), `Abs (0x019DA); (0x02070,0x02070), `Abs (0x02070); (0x02074,0x02079), `Delta (0); (0x02080,0x02089), `Delta (0); (0x02150,0x0215F), `Delta (0); (0x02189,0x02189), `Abs (0x02189); (0x02460,0x0249B), `Delta (0); (0x024EA,0x024FF), `Delta (0); (0x02776,0x02793), `Delta (0); (0x02CFD,0x02CFD), `Abs (0x02CFD); (0x03192,0x03195), `Delta (0); (0x03220,0x03229), `Delta (0); (0x03248,0x0324F), `Delta (0); (0x03251,0x0325F), `Delta (0); (0x03280,0x03289), `Delta (0); (0x032B1,0x032BF), `Delta (0); (0x0A830,0x0A835), `Delta (0); (0x10107,0x10133), `Delta (0); (0x10175,0x10178), `Delta (0); (0x1018A,0x1018B), `Delta (0); (0x102E1,0x102FB), `Delta (0); (0x10320,0x10323), `Delta (0); (0x10858,0x1085F), `Delta (0); (0x10879,0x1087F), `Delta (0); (0x108A7,0x108AF), `Delta (0); (0x108FB,0x108FF), `Delta (0); (0x10916,0x1091B), `Delta (0); (0x109BC,0x109BD), `Delta (0); (0x109C0,0x109CF), `Delta (0); (0x109D2,0x109FF), `Delta (0); (0x10A40,0x10A47), `Delta (0); (0x10A7D,0x10A7E), `Delta (0); (0x10A9D,0x10A9F), `Delta (0); (0x10AEB,0x10AEF), `Delta (0); (0x10B58,0x10B5F), `Delta (0); (0x10B78,0x10B7F), `Delta (0); (0x10BA9,0x10BAF), `Delta (0); (0x10CFA,0x10CFF), `Delta (0); (0x10E60,0x10E7E), `Delta (0); (0x11052,0x11065), `Delta (0); (0x111E1,0x111F4), `Delta (0); (0x1173A,0x1173B), `Delta (0); (0x118EA,0x118F2), `Delta (0); (0x11C5A,0x11C6C), `Delta (0); (0x16B5B,0x16B61), `Delta (0); (0x1D360,0x1D371), `Delta (0); (0x1E8C7,0x1E8CF), `Delta (0); (0x1F100,0x1F10C), `Delta (0); (0x00020,0x00020), `Abs (0x00020); (0x000A0,0x000A0), `Abs (0x000A0); (0x01680,0x01680), `Abs (0x01680); (0x02000,0x0200A), `Delta (0); (0x0202F,0x0202F), `Abs (0x0202F); (0x0205F,0x0205F), `Abs (0x0205F); (0x03000,0x03000), `Abs (0x03000); (0x02028,0x02029), `Delta (0); (0x00001,0x0001F), `Delta (0); (0x0007F,0x0009F), `Delta (0); (0x000AD,0x000AD), `Abs (0x000AD); (0x00600,0x00605), `Delta (0); (0x0061C,0x0061C), `Abs (0x0061C); (0x006DD,0x006DD), `Abs (0x006DD); (0x0070F,0x0070F), `Abs (0x0070F); (0x008E2,0x008E2), `Abs (0x008E2); (0x0180E,0x0180E), `Abs (0x0180E); (0x0200B,0x0200F), `Delta (0); (0x0202A,0x0202E), `Delta (0); (0x02060,0x02064), `Delta (0); (0x02066,0x0206F), `Delta (0); (0x0FEFF,0x0FEFF), `Abs (0x0FEFF); (0x0FFF9,0x0FFFB), `Delta (0); (0x110BD,0x110BD), `Abs (0x110BD); (0x1BCA0,0x1BCA3), `Delta (0); (0x1D173,0x1D17A), `Delta (0); (0xE0001,0xE0001), `Abs (0xE0001); (0xE0020,0xE007F), `Delta (0); (0x0D800,0x0F8FF), `Delta (0); (0xF0000,0xFFFFD), `Delta (0); (0x100000,0x10FFFD), `Delta (0); (0x00378,0x00379), `Delta (0); (0x00380,0x00383), `Delta (0); (0x0038B,0x0038B), `Abs (0x0038B); (0x0038D,0x0038D), `Abs (0x0038D); (0x003A2,0x003A2), `Abs (0x003A2); (0x00530,0x00530), `Abs (0x00530); (0x00557,0x00558), `Delta (0); (0x00560,0x00560), `Abs (0x00560); (0x00588,0x00588), `Abs (0x00588); (0x0058B,0x0058C), `Delta (0); (0x00590,0x00590), `Abs (0x00590); (0x005C8,0x005CF), `Delta (0); (0x005EB,0x005EF), `Delta (0); (0x005F5,0x005FF), `Delta (0); (0x0061D,0x0061D), `Abs (0x0061D); (0x0070E,0x0070E), `Abs (0x0070E); (0x0074B,0x0074C), `Delta (0); (0x007B2,0x007BF), `Delta (0); (0x007FB,0x007FF), `Delta (0); (0x0082E,0x0082F), `Delta (0); (0x0083F,0x0083F), `Abs (0x0083F); (0x0085C,0x0085D), `Delta (0); (0x0085F,0x0089F), `Delta (0); (0x008B5,0x008B5), `Abs (0x008B5); (0x008BE,0x008D3), `Delta (0); (0x00984,0x00984), `Abs (0x00984); (0x0098D,0x0098E), `Delta (0); (0x00991,0x00992), `Delta (0); (0x009A9,0x009A9), `Abs (0x009A9); (0x009B1,0x009B1), `Abs (0x009B1); (0x009B3,0x009B5), `Delta (0); (0x009BA,0x009BB), `Delta (0); (0x009C5,0x009C6), `Delta (0); (0x009C9,0x009CA), `Delta (0); (0x009CF,0x009D6), `Delta (0); (0x009D8,0x009DB), `Delta (0); (0x009DE,0x009DE), `Abs (0x009DE); (0x009E4,0x009E5), `Delta (0); (0x009FC,0x00A00), `Delta (0); (0x00A04,0x00A04), `Abs (0x00A04); (0x00A0B,0x00A0E), `Delta (0); (0x00A11,0x00A12), `Delta (0); (0x00A29,0x00A29), `Abs (0x00A29); (0x00A31,0x00A31), `Abs (0x00A31); (0x00A34,0x00A34), `Abs (0x00A34); (0x00A37,0x00A37), `Abs (0x00A37); (0x00A3A,0x00A3B), `Delta (0); (0x00A3D,0x00A3D), `Abs (0x00A3D); (0x00A43,0x00A46), `Delta (0); (0x00A49,0x00A4A), `Delta (0); (0x00A4E,0x00A50), `Delta (0); (0x00A52,0x00A58), `Delta (0); (0x00A5D,0x00A5D), `Abs (0x00A5D); (0x00A5F,0x00A65), `Delta (0); (0x00A76,0x00A80), `Delta (0); (0x00A84,0x00A84), `Abs (0x00A84); (0x00A8E,0x00A8E), `Abs (0x00A8E); (0x00A92,0x00A92), `Abs (0x00A92); (0x00AA9,0x00AA9), `Abs (0x00AA9); (0x00AB1,0x00AB1), `Abs (0x00AB1); (0x00AB4,0x00AB4), `Abs (0x00AB4); (0x00ABA,0x00ABB), `Delta (0); (0x00AC6,0x00AC6), `Abs (0x00AC6); (0x00ACA,0x00ACA), `Abs (0x00ACA); (0x00ACE,0x00ACF), `Delta (0); (0x00AD1,0x00ADF), `Delta (0); (0x00AE4,0x00AE5), `Delta (0); (0x00AF2,0x00AF8), `Delta (0); (0x00AFA,0x00B00), `Delta (0); (0x00B04,0x00B04), `Abs (0x00B04); (0x00B0D,0x00B0E), `Delta (0); (0x00B11,0x00B12), `Delta (0); (0x00B29,0x00B29), `Abs (0x00B29); (0x00B31,0x00B31), `Abs (0x00B31); (0x00B34,0x00B34), `Abs (0x00B34); (0x00B3A,0x00B3B), `Delta (0); (0x00B45,0x00B46), `Delta (0); (0x00B49,0x00B4A), `Delta (0); (0x00B4E,0x00B55), `Delta (0); (0x00B58,0x00B5B), `Delta (0); (0x00B5E,0x00B5E), `Abs (0x00B5E); (0x00B64,0x00B65), `Delta (0); (0x00B78,0x00B81), `Delta (0); (0x00B84,0x00B84), `Abs (0x00B84); (0x00B8B,0x00B8D), `Delta (0); (0x00B91,0x00B91), `Abs (0x00B91); (0x00B96,0x00B98), `Delta (0); (0x00B9B,0x00B9B), `Abs (0x00B9B); (0x00B9D,0x00B9D), `Abs (0x00B9D); (0x00BA0,0x00BA2), `Delta (0); (0x00BA5,0x00BA7), `Delta (0); (0x00BAB,0x00BAD), `Delta (0); (0x00BBA,0x00BBD), `Delta (0); (0x00BC3,0x00BC5), `Delta (0); (0x00BC9,0x00BC9), `Abs (0x00BC9); (0x00BCE,0x00BCF), `Delta (0); (0x00BD1,0x00BD6), `Delta (0); (0x00BD8,0x00BE5), `Delta (0); (0x00BFB,0x00BFF), `Delta (0); (0x00C04,0x00C04), `Abs (0x00C04); (0x00C0D,0x00C0D), `Abs (0x00C0D); (0x00C11,0x00C11), `Abs (0x00C11); (0x00C29,0x00C29), `Abs (0x00C29); (0x00C3A,0x00C3C), `Delta (0); (0x00C45,0x00C45), `Abs (0x00C45); (0x00C49,0x00C49), `Abs (0x00C49); (0x00C4E,0x00C54), `Delta (0); (0x00C57,0x00C57), `Abs (0x00C57); (0x00C5B,0x00C5F), `Delta (0); (0x00C64,0x00C65), `Delta (0); (0x00C70,0x00C77), `Delta (0); (0x00C84,0x00C84), `Abs (0x00C84); (0x00C8D,0x00C8D), `Abs (0x00C8D); (0x00C91,0x00C91), `Abs (0x00C91); (0x00CA9,0x00CA9), `Abs (0x00CA9); (0x00CB4,0x00CB4), `Abs (0x00CB4); (0x00CBA,0x00CBB), `Delta (0); (0x00CC5,0x00CC5), `Abs (0x00CC5); (0x00CC9,0x00CC9), `Abs (0x00CC9); (0x00CCE,0x00CD4), `Delta (0); (0x00CD7,0x00CDD), `Delta (0); (0x00CDF,0x00CDF), `Abs (0x00CDF); (0x00CE4,0x00CE5), `Delta (0); (0x00CF0,0x00CF0), `Abs (0x00CF0); (0x00CF3,0x00D00), `Delta (0); (0x00D04,0x00D04), `Abs (0x00D04); (0x00D0D,0x00D0D), `Abs (0x00D0D); (0x00D11,0x00D11), `Abs (0x00D11); (0x00D3B,0x00D3C), `Delta (0); (0x00D45,0x00D45), `Abs (0x00D45); (0x00D49,0x00D49), `Abs (0x00D49); (0x00D50,0x00D53), `Delta (0); (0x00D64,0x00D65), `Delta (0); (0x00D80,0x00D81), `Delta (0); (0x00D84,0x00D84), `Abs (0x00D84); (0x00D97,0x00D99), `Delta (0); (0x00DB2,0x00DB2), `Abs (0x00DB2); (0x00DBC,0x00DBC), `Abs (0x00DBC); (0x00DBE,0x00DBF), `Delta (0); (0x00DC7,0x00DC9), `Delta (0); (0x00DCB,0x00DCE), `Delta (0); (0x00DD5,0x00DD5), `Abs (0x00DD5); (0x00DD7,0x00DD7), `Abs (0x00DD7); (0x00DE0,0x00DE5), `Delta (0); (0x00DF0,0x00DF1), `Delta (0); (0x00DF5,0x00E00), `Delta (0); (0x00E3B,0x00E3E), `Delta (0); (0x00E5C,0x00E80), `Delta (0); (0x00E83,0x00E83), `Abs (0x00E83); (0x00E85,0x00E86), `Delta (0); (0x00E89,0x00E89), `Abs (0x00E89); (0x00E8B,0x00E8C), `Delta (0); (0x00E8E,0x00E93), `Delta (0); (0x00E98,0x00E98), `Abs (0x00E98); (0x00EA0,0x00EA0), `Abs (0x00EA0); (0x00EA4,0x00EA4), `Abs (0x00EA4); (0x00EA6,0x00EA6), `Abs (0x00EA6); (0x00EA8,0x00EA9), `Delta (0); (0x00EAC,0x00EAC), `Abs (0x00EAC); (0x00EBA,0x00EBA), `Abs (0x00EBA); (0x00EBE,0x00EBF), `Delta (0); (0x00EC5,0x00EC5), `Abs (0x00EC5); (0x00EC7,0x00EC7), `Abs (0x00EC7); (0x00ECE,0x00ECF), `Delta (0); (0x00EDA,0x00EDB), `Delta (0); (0x00EE0,0x00EFF), `Delta (0); (0x00F48,0x00F48), `Abs (0x00F48); (0x00F6D,0x00F70), `Delta (0); (0x00F98,0x00F98), `Abs (0x00F98); (0x00FBD,0x00FBD), `Abs (0x00FBD); (0x00FCD,0x00FCD), `Abs (0x00FCD); (0x00FDB,0x00FFF), `Delta (0); (0x010C6,0x010C6), `Abs (0x010C6); (0x010C8,0x010CC), `Delta (0); (0x010CE,0x010CF), `Delta (0); (0x01249,0x01249), `Abs (0x01249); (0x0124E,0x0124F), `Delta (0); (0x01257,0x01257), `Abs (0x01257); (0x01259,0x01259), `Abs (0x01259); (0x0125E,0x0125F), `Delta (0); (0x01289,0x01289), `Abs (0x01289); (0x0128E,0x0128F), `Delta (0); (0x012B1,0x012B1), `Abs (0x012B1); (0x012B6,0x012B7), `Delta (0); (0x012BF,0x012BF), `Abs (0x012BF); (0x012C1,0x012C1), `Abs (0x012C1); (0x012C6,0x012C7), `Delta (0); (0x012D7,0x012D7), `Abs (0x012D7); (0x01311,0x01311), `Abs (0x01311); (0x01316,0x01317), `Delta (0); (0x0135B,0x0135C), `Delta (0); (0x0137D,0x0137F), `Delta (0); (0x0139A,0x0139F), `Delta (0); (0x013F6,0x013F7), `Delta (0); (0x013FE,0x013FF), `Delta (0); (0x0169D,0x0169F), `Delta (0); (0x016F9,0x016FF), `Delta (0); (0x0170D,0x0170D), `Abs (0x0170D); (0x01715,0x0171F), `Delta (0); (0x01737,0x0173F), `Delta (0); (0x01754,0x0175F), `Delta (0); (0x0176D,0x0176D), `Abs (0x0176D); (0x01771,0x01771), `Abs (0x01771); (0x01774,0x0177F), `Delta (0); (0x017DE,0x017DF), `Delta (0); (0x017EA,0x017EF), `Delta (0); (0x017FA,0x017FF), `Delta (0); (0x0180F,0x0180F), `Abs (0x0180F); (0x0181A,0x0181F), `Delta (0); (0x01878,0x0187F), `Delta (0); (0x018AB,0x018AF), `Delta (0); (0x018F6,0x018FF), `Delta (0); (0x0191F,0x0191F), `Abs (0x0191F); (0x0192C,0x0192F), `Delta (0); (0x0193C,0x0193F), `Delta (0); (0x01941,0x01943), `Delta (0); (0x0196E,0x0196F), `Delta (0); (0x01975,0x0197F), `Delta (0); (0x019AC,0x019AF), `Delta (0); (0x019CA,0x019CF), `Delta (0); (0x019DB,0x019DD), `Delta (0); (0x01A1C,0x01A1D), `Delta (0); (0x01A5F,0x01A5F), `Abs (0x01A5F); (0x01A7D,0x01A7E), `Delta (0); (0x01A8A,0x01A8F), `Delta (0); (0x01A9A,0x01A9F), `Delta (0); (0x01AAE,0x01AAF), `Delta (0); (0x01ABF,0x01AFF), `Delta (0); (0x01B4C,0x01B4F), `Delta (0); (0x01B7D,0x01B7F), `Delta (0); (0x01BF4,0x01BFB), `Delta (0); (0x01C38,0x01C3A), `Delta (0); (0x01C4A,0x01C4C), `Delta (0); (0x01C89,0x01CBF), `Delta (0); (0x01CC8,0x01CCF), `Delta (0); (0x01CF7,0x01CF7), `Abs (0x01CF7); (0x01CFA,0x01CFF), `Delta (0); (0x01DF6,0x01DFA), `Delta (0); (0x01F16,0x01F17), `Delta (0); (0x01F1E,0x01F1F), `Delta (0); (0x01F46,0x01F47), `Delta (0); (0x01F4E,0x01F4F), `Delta (0); (0x01F58,0x01F58), `Abs (0x01F58); (0x01F5A,0x01F5A), `Abs (0x01F5A); (0x01F5C,0x01F5C), `Abs (0x01F5C); (0x01F5E,0x01F5E), `Abs (0x01F5E); (0x01F7E,0x01F7F), `Delta (0); (0x01FB5,0x01FB5), `Abs (0x01FB5); (0x01FC5,0x01FC5), `Abs (0x01FC5); (0x01FD4,0x01FD5), `Delta (0); (0x01FDC,0x01FDC), `Abs (0x01FDC); (0x01FF0,0x01FF1), `Delta (0); (0x01FF5,0x01FF5), `Abs (0x01FF5); (0x01FFF,0x01FFF), `Abs (0x01FFF); (0x02065,0x02065), `Abs (0x02065); (0x02072,0x02073), `Delta (0); (0x0208F,0x0208F), `Abs (0x0208F); (0x0209D,0x0209F), `Delta (0); (0x020BF,0x020CF), `Delta (0); (0x020F1,0x020FF), `Delta (0); (0x0218C,0x0218F), `Delta (0); (0x023FF,0x023FF), `Abs (0x023FF); (0x02427,0x0243F), `Delta (0); (0x0244B,0x0245F), `Delta (0); (0x02B74,0x02B75), `Delta (0); (0x02B96,0x02B97), `Delta (0); (0x02BBA,0x02BBC), `Delta (0); (0x02BC9,0x02BC9), `Abs (0x02BC9); (0x02BD2,0x02BEB), `Delta (0); (0x02BF0,0x02BFF), `Delta (0); (0x02C2F,0x02C2F), `Abs (0x02C2F); (0x02C5F,0x02C5F), `Abs (0x02C5F); (0x02CF4,0x02CF8), `Delta (0); (0x02D26,0x02D26), `Abs (0x02D26); (0x02D28,0x02D2C), `Delta (0); (0x02D2E,0x02D2F), `Delta (0); (0x02D68,0x02D6E), `Delta (0); (0x02D71,0x02D7E), `Delta (0); (0x02D97,0x02D9F), `Delta (0); (0x02DA7,0x02DA7), `Abs (0x02DA7); (0x02DAF,0x02DAF), `Abs (0x02DAF); (0x02DB7,0x02DB7), `Abs (0x02DB7); (0x02DBF,0x02DBF), `Abs (0x02DBF); (0x02DC7,0x02DC7), `Abs (0x02DC7); (0x02DCF,0x02DCF), `Abs (0x02DCF); (0x02DD7,0x02DD7), `Abs (0x02DD7); (0x02DDF,0x02DDF), `Abs (0x02DDF); (0x02E45,0x02E7F), `Delta (0); (0x02E9A,0x02E9A), `Abs (0x02E9A); (0x02EF4,0x02EFF), `Delta (0); (0x02FD6,0x02FEF), `Delta (0); (0x02FFC,0x02FFF), `Delta (0); (0x03040,0x03040), `Abs (0x03040); (0x03097,0x03098), `Delta (0); (0x03100,0x03104), `Delta (0); (0x0312E,0x03130), `Delta (0); (0x0318F,0x0318F), `Abs (0x0318F); (0x031BB,0x031BF), `Delta (0); (0x031E4,0x031EF), `Delta (0); (0x0321F,0x0321F), `Abs (0x0321F); (0x032FF,0x032FF), `Abs (0x032FF); (0x04DB6,0x04DBF), `Delta (0); (0x09FD6,0x09FFF), `Delta (0); (0x0A48D,0x0A48F), `Delta (0); (0x0A4C7,0x0A4CF), `Delta (0); (0x0A62C,0x0A63F), `Delta (0); (0x0A6F8,0x0A6FF), `Delta (0); (0x0A7AF,0x0A7AF), `Abs (0x0A7AF); (0x0A7B8,0x0A7F6), `Delta (0); (0x0A82C,0x0A82F), `Delta (0); (0x0A83A,0x0A83F), `Delta (0); (0x0A878,0x0A87F), `Delta (0); (0x0A8C6,0x0A8CD), `Delta (0); (0x0A8DA,0x0A8DF), `Delta (0); (0x0A8FE,0x0A8FF), `Delta (0); (0x0A954,0x0A95E), `Delta (0); (0x0A97D,0x0A97F), `Delta (0); (0x0A9CE,0x0A9CE), `Abs (0x0A9CE); (0x0A9DA,0x0A9DD), `Delta (0); (0x0A9FF,0x0A9FF), `Abs (0x0A9FF); (0x0AA37,0x0AA3F), `Delta (0); (0x0AA4E,0x0AA4F), `Delta (0); (0x0AA5A,0x0AA5B), `Delta (0); (0x0AAC3,0x0AADA), `Delta (0); (0x0AAF7,0x0AB00), `Delta (0); (0x0AB07,0x0AB08), `Delta (0); (0x0AB0F,0x0AB10), `Delta (0); (0x0AB17,0x0AB1F), `Delta (0); (0x0AB27,0x0AB27), `Abs (0x0AB27); (0x0AB2F,0x0AB2F), `Abs (0x0AB2F); (0x0AB66,0x0AB6F), `Delta (0); (0x0ABEE,0x0ABEF), `Delta (0); (0x0ABFA,0x0ABFF), `Delta (0); (0x0D7A4,0x0D7AF), `Delta (0); (0x0D7C7,0x0D7CA), `Delta (0); (0x0D7FC,0x0D7FF), `Delta (0); (0x0FA6E,0x0FA6F), `Delta (0); (0x0FADA,0x0FAFF), `Delta (0); (0x0FB07,0x0FB12), `Delta (0); (0x0FB18,0x0FB1C), `Delta (0); (0x0FB37,0x0FB37), `Abs (0x0FB37); (0x0FB3D,0x0FB3D), `Abs (0x0FB3D); (0x0FB3F,0x0FB3F), `Abs (0x0FB3F); (0x0FB42,0x0FB42), `Abs (0x0FB42); (0x0FB45,0x0FB45), `Abs (0x0FB45); (0x0FBC2,0x0FBD2), `Delta (0); (0x0FD40,0x0FD4F), `Delta (0); (0x0FD90,0x0FD91), `Delta (0); (0x0FDC8,0x0FDEF), `Delta (0); (0x0FDFE,0x0FDFF), `Delta (0); (0x0FE1A,0x0FE1F), `Delta (0); (0x0FE53,0x0FE53), `Abs (0x0FE53); (0x0FE67,0x0FE67), `Abs (0x0FE67); (0x0FE6C,0x0FE6F), `Delta (0); (0x0FE75,0x0FE75), `Abs (0x0FE75); (0x0FEFD,0x0FEFE), `Delta (0); (0x0FF00,0x0FF00), `Abs (0x0FF00); (0x0FFBF,0x0FFC1), `Delta (0); (0x0FFC8,0x0FFC9), `Delta (0); (0x0FFD0,0x0FFD1), `Delta (0); (0x0FFD8,0x0FFD9), `Delta (0); (0x0FFDD,0x0FFDF), `Delta (0); (0x0FFE7,0x0FFE7), `Abs (0x0FFE7); (0x0FFEF,0x0FFF8), `Delta (0); (0x0FFFE,0x0FFFF), `Delta (0); (0x1000C,0x1000C), `Abs (0x1000C); (0x10027,0x10027), `Abs (0x10027); (0x1003B,0x1003B), `Abs (0x1003B); (0x1003E,0x1003E), `Abs (0x1003E); (0x1004E,0x1004F), `Delta (0); (0x1005E,0x1007F), `Delta (0); (0x100FB,0x100FF), `Delta (0); (0x10103,0x10106), `Delta (0); (0x10134,0x10136), `Delta (0); (0x1018F,0x1018F), `Abs (0x1018F); (0x1019C,0x1019F), `Delta (0); (0x101A1,0x101CF), `Delta (0); (0x101FE,0x1027F), `Delta (0); (0x1029D,0x1029F), `Delta (0); (0x102D1,0x102DF), `Delta (0); (0x102FC,0x102FF), `Delta (0); (0x10324,0x1032F), `Delta (0); (0x1034B,0x1034F), `Delta (0); (0x1037B,0x1037F), `Delta (0); (0x1039E,0x1039E), `Abs (0x1039E); (0x103C4,0x103C7), `Delta (0); (0x103D6,0x103FF), `Delta (0); (0x1049E,0x1049F), `Delta (0); (0x104AA,0x104AF), `Delta (0); (0x104D4,0x104D7), `Delta (0); (0x104FC,0x104FF), `Delta (0); (0x10528,0x1052F), `Delta (0); (0x10564,0x1056E), `Delta (0); (0x10570,0x105FF), `Delta (0); (0x10737,0x1073F), `Delta (0); (0x10756,0x1075F), `Delta (0); (0x10768,0x107FF), `Delta (0); (0x10806,0x10807), `Delta (0); (0x10809,0x10809), `Abs (0x10809); (0x10836,0x10836), `Abs (0x10836); (0x10839,0x1083B), `Delta (0); (0x1083D,0x1083E), `Delta (0); (0x10856,0x10856), `Abs (0x10856); (0x1089F,0x108A6), `Delta (0); (0x108B0,0x108DF), `Delta (0); (0x108F3,0x108F3), `Abs (0x108F3); (0x108F6,0x108FA), `Delta (0); (0x1091C,0x1091E), `Delta (0); (0x1093A,0x1093E), `Delta (0); (0x10940,0x1097F), `Delta (0); (0x109B8,0x109BB), `Delta (0); (0x109D0,0x109D1), `Delta (0); (0x10A04,0x10A04), `Abs (0x10A04); (0x10A07,0x10A0B), `Delta (0); (0x10A14,0x10A14), `Abs (0x10A14); (0x10A18,0x10A18), `Abs (0x10A18); (0x10A34,0x10A37), `Delta (0); (0x10A3B,0x10A3E), `Delta (0); (0x10A48,0x10A4F), `Delta (0); (0x10A59,0x10A5F), `Delta (0); (0x10AA0,0x10ABF), `Delta (0); (0x10AE7,0x10AEA), `Delta (0); (0x10AF7,0x10AFF), `Delta (0); (0x10B36,0x10B38), `Delta (0); (0x10B56,0x10B57), `Delta (0); (0x10B73,0x10B77), `Delta (0); (0x10B92,0x10B98), `Delta (0); (0x10B9D,0x10BA8), `Delta (0); (0x10BB0,0x10BFF), `Delta (0); (0x10C49,0x10C7F), `Delta (0); (0x10CB3,0x10CBF), `Delta (0); (0x10CF3,0x10CF9), `Delta (0); (0x10D00,0x10E5F), `Delta (0); (0x10E7F,0x10FFF), `Delta (0); (0x1104E,0x11051), `Delta (0); (0x11070,0x1107E), `Delta (0); (0x110C2,0x110CF), `Delta (0); (0x110E9,0x110EF), `Delta (0); (0x110FA,0x110FF), `Delta (0); (0x11135,0x11135), `Abs (0x11135); (0x11144,0x1114F), `Delta (0); (0x11177,0x1117F), `Delta (0); (0x111CE,0x111CF), `Delta (0); (0x111E0,0x111E0), `Abs (0x111E0); (0x111F5,0x111FF), `Delta (0); (0x11212,0x11212), `Abs (0x11212); (0x1123F,0x1127F), `Delta (0); (0x11287,0x11287), `Abs (0x11287); (0x11289,0x11289), `Abs (0x11289); (0x1128E,0x1128E), `Abs (0x1128E); (0x1129E,0x1129E), `Abs (0x1129E); (0x112AA,0x112AF), `Delta (0); (0x112EB,0x112EF), `Delta (0); (0x112FA,0x112FF), `Delta (0); (0x11304,0x11304), `Abs (0x11304); (0x1130D,0x1130E), `Delta (0); (0x11311,0x11312), `Delta (0); (0x11329,0x11329), `Abs (0x11329); (0x11331,0x11331), `Abs (0x11331); (0x11334,0x11334), `Abs (0x11334); (0x1133A,0x1133B), `Delta (0); (0x11345,0x11346), `Delta (0); (0x11349,0x1134A), `Delta (0); (0x1134E,0x1134F), `Delta (0); (0x11351,0x11356), `Delta (0); (0x11358,0x1135C), `Delta (0); (0x11364,0x11365), `Delta (0); (0x1136D,0x1136F), `Delta (0); (0x11375,0x113FF), `Delta (0); (0x1145A,0x1145A), `Abs (0x1145A); (0x1145C,0x1145C), `Abs (0x1145C); (0x1145E,0x1147F), `Delta (0); (0x114C8,0x114CF), `Delta (0); (0x114DA,0x1157F), `Delta (0); (0x115B6,0x115B7), `Delta (0); (0x115DE,0x115FF), `Delta (0); (0x11645,0x1164F), `Delta (0); (0x1165A,0x1165F), `Delta (0); (0x1166D,0x1167F), `Delta (0); (0x116B8,0x116BF), `Delta (0); (0x116CA,0x116FF), `Delta (0); (0x1171A,0x1171C), `Delta (0); (0x1172C,0x1172F), `Delta (0); (0x11740,0x1189F), `Delta (0); (0x118F3,0x118FE), `Delta (0); (0x11900,0x11ABF), `Delta (0); (0x11AF9,0x11BFF), `Delta (0); (0x11C09,0x11C09), `Abs (0x11C09); (0x11C37,0x11C37), `Abs (0x11C37); (0x11C46,0x11C4F), `Delta (0); (0x11C6D,0x11C6F), `Delta (0); (0x11C90,0x11C91), `Delta (0); (0x11CA8,0x11CA8), `Abs (0x11CA8); (0x11CB7,0x11FFF), `Delta (0); (0x1239A,0x123FF), `Delta (0); (0x1246F,0x1246F), `Abs (0x1246F); (0x12475,0x1247F), `Delta (0); (0x12544,0x12FFF), `Delta (0); (0x1342F,0x143FF), `Delta (0); (0x14647,0x167FF), `Delta (0); (0x16A39,0x16A3F), `Delta (0); (0x16A5F,0x16A5F), `Abs (0x16A5F); (0x16A6A,0x16A6D), `Delta (0); (0x16A70,0x16ACF), `Delta (0); (0x16AEE,0x16AEF), `Delta (0); (0x16AF6,0x16AFF), `Delta (0); (0x16B46,0x16B4F), `Delta (0); (0x16B5A,0x16B5A), `Abs (0x16B5A); (0x16B62,0x16B62), `Abs (0x16B62); (0x16B78,0x16B7C), `Delta (0); (0x16B90,0x16EFF), `Delta (0); (0x16F45,0x16F4F), `Delta (0); (0x16F7F,0x16F8E), `Delta (0); (0x16FA0,0x16FDF), `Delta (0); (0x16FE1,0x16FFF), `Delta (0); (0x187ED,0x187FF), `Delta (0); (0x18AF3,0x1AFFF), `Delta (0); (0x1B002,0x1BBFF), `Delta (0); (0x1BC6B,0x1BC6F), `Delta (0); (0x1BC7D,0x1BC7F), `Delta (0); (0x1BC89,0x1BC8F), `Delta (0); (0x1BC9A,0x1BC9B), `Delta (0); (0x1BCA4,0x1CFFF), `Delta (0); (0x1D0F6,0x1D0FF), `Delta (0); (0x1D127,0x1D128), `Delta (0); (0x1D1E9,0x1D1FF), `Delta (0); (0x1D246,0x1D2FF), `Delta (0); (0x1D357,0x1D35F), `Delta (0); (0x1D372,0x1D3FF), `Delta (0); (0x1D455,0x1D455), `Abs (0x1D455); (0x1D49D,0x1D49D), `Abs (0x1D49D); (0x1D4A0,0x1D4A1), `Delta (0); (0x1D4A3,0x1D4A4), `Delta (0); (0x1D4A7,0x1D4A8), `Delta (0); (0x1D4AD,0x1D4AD), `Abs (0x1D4AD); (0x1D4BA,0x1D4BA), `Abs (0x1D4BA); (0x1D4BC,0x1D4BC), `Abs (0x1D4BC); (0x1D4C4,0x1D4C4), `Abs (0x1D4C4); (0x1D506,0x1D506), `Abs (0x1D506); (0x1D50B,0x1D50C), `Delta (0); (0x1D515,0x1D515), `Abs (0x1D515); (0x1D51D,0x1D51D), `Abs (0x1D51D); (0x1D53A,0x1D53A), `Abs (0x1D53A); (0x1D53F,0x1D53F), `Abs (0x1D53F); (0x1D545,0x1D545), `Abs (0x1D545); (0x1D547,0x1D549), `Delta (0); (0x1D551,0x1D551), `Abs (0x1D551); (0x1D6A6,0x1D6A7), `Delta (0); (0x1D7CC,0x1D7CD), `Delta (0); (0x1DA8C,0x1DA9A), `Delta (0); (0x1DAA0,0x1DAA0), `Abs (0x1DAA0); (0x1DAB0,0x1DFFF), `Delta (0); (0x1E007,0x1E007), `Abs (0x1E007); (0x1E019,0x1E01A), `Delta (0); (0x1E022,0x1E022), `Abs (0x1E022); (0x1E025,0x1E025), `Abs (0x1E025); (0x1E02B,0x1E7FF), `Delta (0); (0x1E8C5,0x1E8C6), `Delta (0); (0x1E8D7,0x1E8FF), `Delta (0); (0x1E94B,0x1E94F), `Delta (0); (0x1E95A,0x1E95D), `Delta (0); (0x1E960,0x1EDFF), `Delta (0); (0x1EE04,0x1EE04), `Abs (0x1EE04); (0x1EE20,0x1EE20), `Abs (0x1EE20); (0x1EE23,0x1EE23), `Abs (0x1EE23); (0x1EE25,0x1EE26), `Delta (0); (0x1EE28,0x1EE28), `Abs (0x1EE28); (0x1EE33,0x1EE33), `Abs (0x1EE33); (0x1EE38,0x1EE38), `Abs (0x1EE38); (0x1EE3A,0x1EE3A), `Abs (0x1EE3A); (0x1EE3C,0x1EE41), `Delta (0); (0x1EE43,0x1EE46), `Delta (0); (0x1EE48,0x1EE48), `Abs (0x1EE48); (0x1EE4A,0x1EE4A), `Abs (0x1EE4A); (0x1EE4C,0x1EE4C), `Abs (0x1EE4C); (0x1EE50,0x1EE50), `Abs (0x1EE50); (0x1EE53,0x1EE53), `Abs (0x1EE53); (0x1EE55,0x1EE56), `Delta (0); (0x1EE58,0x1EE58), `Abs (0x1EE58); (0x1EE5A,0x1EE5A), `Abs (0x1EE5A); (0x1EE5C,0x1EE5C), `Abs (0x1EE5C); (0x1EE5E,0x1EE5E), `Abs (0x1EE5E); (0x1EE60,0x1EE60), `Abs (0x1EE60); (0x1EE63,0x1EE63), `Abs (0x1EE63); (0x1EE65,0x1EE66), `Delta (0); (0x1EE6B,0x1EE6B), `Abs (0x1EE6B); (0x1EE73,0x1EE73), `Abs (0x1EE73); (0x1EE78,0x1EE78), `Abs (0x1EE78); (0x1EE7D,0x1EE7D), `Abs (0x1EE7D); (0x1EE7F,0x1EE7F), `Abs (0x1EE7F); (0x1EE8A,0x1EE8A), `Abs (0x1EE8A); (0x1EE9C,0x1EEA0), `Delta (0); (0x1EEA4,0x1EEA4), `Abs (0x1EEA4); (0x1EEAA,0x1EEAA), `Abs (0x1EEAA); (0x1EEBC,0x1EEEF), `Delta (0); (0x1EEF2,0x1EFFF), `Delta (0); (0x1F02C,0x1F02F), `Delta (0); (0x1F094,0x1F09F), `Delta (0); (0x1F0AF,0x1F0B0), `Delta (0); (0x1F0C0,0x1F0C0), `Abs (0x1F0C0); (0x1F0D0,0x1F0D0), `Abs (0x1F0D0); (0x1F0F6,0x1F0FF), `Delta (0); (0x1F10D,0x1F10F), `Delta (0); (0x1F12F,0x1F12F), `Abs (0x1F12F); (0x1F16C,0x1F16F), `Delta (0); (0x1F1AD,0x1F1E5), `Delta (0); (0x1F203,0x1F20F), `Delta (0); (0x1F23C,0x1F23F), `Delta (0); (0x1F249,0x1F24F), `Delta (0); (0x1F252,0x1F2FF), `Delta (0); (0x1F6D3,0x1F6DF), `Delta (0); (0x1F6ED,0x1F6EF), `Delta (0); (0x1F6F7,0x1F6FF), `Delta (0); (0x1F774,0x1F77F), `Delta (0); (0x1F7D5,0x1F7FF), `Delta (0); (0x1F80C,0x1F80F), `Delta (0); (0x1F848,0x1F84F), `Delta (0); (0x1F85A,0x1F85F), `Delta (0); (0x1F888,0x1F88F), `Delta (0); (0x1F8AE,0x1F90F), `Delta (0); (0x1F91F,0x1F91F), `Abs (0x1F91F); (0x1F928,0x1F92F), `Delta (0); (0x1F931,0x1F932), `Delta (0); (0x1F93F,0x1F93F), `Abs (0x1F93F); (0x1F94C,0x1F94F), `Delta (0); (0x1F95F,0x1F97F), `Delta (0); (0x1F992,0x1F9BF), `Delta (0); (0x1F9C1,0x1FFFF), `Delta (0); (0x2A6D7,0x2A6FF), `Delta (0); (0x2B735,0x2B73F), `Delta (0); (0x2B81E,0x2B81F), `Delta (0); (0x2CEA2,0x2F7FF), `Delta (0); (0x2FA1E,0xE0000), `Delta (0); (0xE0002,0xE001F), `Delta (0); (0xE0080,0xE00FF), `Delta (0); (0xE01F0,0xEFFFF), `Delta (0); (0xFFFFE,0xFFFFF), `Delta (0); (0x10FFFE,0x10FFFF), `Delta (0); (0x002B0,0x002C1), `Delta (0); (0x002C6,0x002D1), `Delta (0); (0x002E0,0x002E4), `Delta (0); (0x002EC,0x002EC), `Abs (0x002EC); (0x002EE,0x002EE), `Abs (0x002EE); (0x00374,0x00374), `Abs (0x00374); (0x0037A,0x0037A), `Abs (0x0037A); (0x00559,0x00559), `Abs (0x00559); (0x00640,0x00640), `Abs (0x00640); (0x006E5,0x006E6), `Delta (0); (0x007F4,0x007F5), `Delta (0); (0x007FA,0x007FA), `Abs (0x007FA); (0x0081A,0x0081A), `Abs (0x0081A); (0x00824,0x00824), `Abs (0x00824); (0x00828,0x00828), `Abs (0x00828); (0x00971,0x00971), `Abs (0x00971); (0x00E46,0x00E46), `Abs (0x00E46); (0x00EC6,0x00EC6), `Abs (0x00EC6); (0x010FC,0x010FC), `Abs (0x010FC); (0x017D7,0x017D7), `Abs (0x017D7); (0x01843,0x01843), `Abs (0x01843); (0x01AA7,0x01AA7), `Abs (0x01AA7); (0x01C78,0x01C7D), `Delta (0); (0x01D2C,0x01D6A), `Delta (0); (0x01D78,0x01D78), `Abs (0x01D78); (0x01D9B,0x01DBF), `Delta (0); (0x02071,0x02071), `Abs (0x02071); (0x0207F,0x0207F), `Abs (0x0207F); (0x02090,0x0209C), `Delta (0); (0x02C7C,0x02C7D), `Delta (0); (0x02D6F,0x02D6F), `Abs (0x02D6F); (0x02E2F,0x02E2F), `Abs (0x02E2F); (0x03005,0x03005), `Abs (0x03005); (0x03031,0x03035), `Delta (0); (0x0303B,0x0303B), `Abs (0x0303B); (0x0309D,0x0309E), `Delta (0); (0x030FC,0x030FE), `Delta (0); (0x0A015,0x0A015), `Abs (0x0A015); (0x0A4F8,0x0A4FD), `Delta (0); (0x0A60C,0x0A60C), `Abs (0x0A60C); (0x0A67F,0x0A67F), `Abs (0x0A67F); (0x0A69C,0x0A69D), `Delta (0); (0x0A717,0x0A71F), `Delta (0); (0x0A770,0x0A770), `Abs (0x0A770); (0x0A788,0x0A788), `Abs (0x0A788); (0x0A7F8,0x0A7F9), `Delta (0); (0x0A9CF,0x0A9CF), `Abs (0x0A9CF); (0x0A9E6,0x0A9E6), `Abs (0x0A9E6); (0x0AA70,0x0AA70), `Abs (0x0AA70); (0x0AADD,0x0AADD), `Abs (0x0AADD); (0x0AAF3,0x0AAF4), `Delta (0); (0x0AB5C,0x0AB5F), `Delta (0); (0x0FF70,0x0FF70), `Abs (0x0FF70); (0x0FF9E,0x0FF9F), `Delta (0); (0x16B40,0x16B43), `Delta (0); (0x16F93,0x16F9F), `Delta (0); (0x16FE0,0x16FE0), `Abs (0x16FE0); (0x000AA,0x000AA), `Abs (0x000AA); (0x000BA,0x000BA), `Abs (0x000BA); (0x001BB,0x001BB), `Abs (0x001BB); (0x001C0,0x001C3), `Delta (0); (0x00294,0x00294), `Abs (0x00294); (0x005D0,0x005EA), `Delta (0); (0x005F0,0x005F2), `Delta (0); (0x00620,0x0063F), `Delta (0); (0x00641,0x0064A), `Delta (0); (0x0066E,0x0066F), `Delta (0); (0x00671,0x006D3), `Delta (0); (0x006D5,0x006D5), `Abs (0x006D5); (0x006EE,0x006EF), `Delta (0); (0x006FA,0x006FC), `Delta (0); (0x006FF,0x006FF), `Abs (0x006FF); (0x00710,0x00710), `Abs (0x00710); (0x00712,0x0072F), `Delta (0); (0x0074D,0x007A5), `Delta (0); (0x007B1,0x007B1), `Abs (0x007B1); (0x007CA,0x007EA), `Delta (0); (0x00800,0x00815), `Delta (0); (0x00840,0x00858), `Delta (0); (0x008A0,0x008B4), `Delta (0); (0x008B6,0x008BD), `Delta (0); (0x00904,0x00939), `Delta (0); (0x0093D,0x0093D), `Abs (0x0093D); (0x00950,0x00950), `Abs (0x00950); (0x00958,0x00961), `Delta (0); (0x00972,0x00980), `Delta (0); (0x00985,0x0098C), `Delta (0); (0x0098F,0x00990), `Delta (0); (0x00993,0x009A8), `Delta (0); (0x009AA,0x009B0), `Delta (0); (0x009B2,0x009B2), `Abs (0x009B2); (0x009B6,0x009B9), `Delta (0); (0x009BD,0x009BD), `Abs (0x009BD); (0x009CE,0x009CE), `Abs (0x009CE); (0x009DC,0x009DD), `Delta (0); (0x009DF,0x009E1), `Delta (0); (0x009F0,0x009F1), `Delta (0); (0x00A05,0x00A0A), `Delta (0); (0x00A0F,0x00A10), `Delta (0); (0x00A13,0x00A28), `Delta (0); (0x00A2A,0x00A30), `Delta (0); (0x00A32,0x00A33), `Delta (0); (0x00A35,0x00A36), `Delta (0); (0x00A38,0x00A39), `Delta (0); (0x00A59,0x00A5C), `Delta (0); (0x00A5E,0x00A5E), `Abs (0x00A5E); (0x00A72,0x00A74), `Delta (0); (0x00A85,0x00A8D), `Delta (0); (0x00A8F,0x00A91), `Delta (0); (0x00A93,0x00AA8), `Delta (0); (0x00AAA,0x00AB0), `Delta (0); (0x00AB2,0x00AB3), `Delta (0); (0x00AB5,0x00AB9), `Delta (0); (0x00ABD,0x00ABD), `Abs (0x00ABD); (0x00AD0,0x00AD0), `Abs (0x00AD0); (0x00AE0,0x00AE1), `Delta (0); (0x00AF9,0x00AF9), `Abs (0x00AF9); (0x00B05,0x00B0C), `Delta (0); (0x00B0F,0x00B10), `Delta (0); (0x00B13,0x00B28), `Delta (0); (0x00B2A,0x00B30), `Delta (0); (0x00B32,0x00B33), `Delta (0); (0x00B35,0x00B39), `Delta (0); (0x00B3D,0x00B3D), `Abs (0x00B3D); (0x00B5C,0x00B5D), `Delta (0); (0x00B5F,0x00B61), `Delta (0); (0x00B71,0x00B71), `Abs (0x00B71); (0x00B83,0x00B83), `Abs (0x00B83); (0x00B85,0x00B8A), `Delta (0); (0x00B8E,0x00B90), `Delta (0); (0x00B92,0x00B95), `Delta (0); (0x00B99,0x00B9A), `Delta (0); (0x00B9C,0x00B9C), `Abs (0x00B9C); (0x00B9E,0x00B9F), `Delta (0); (0x00BA3,0x00BA4), `Delta (0); (0x00BA8,0x00BAA), `Delta (0); (0x00BAE,0x00BB9), `Delta (0); (0x00BD0,0x00BD0), `Abs (0x00BD0); (0x00C05,0x00C0C), `Delta (0); (0x00C0E,0x00C10), `Delta (0); (0x00C12,0x00C28), `Delta (0); (0x00C2A,0x00C39), `Delta (0); (0x00C3D,0x00C3D), `Abs (0x00C3D); (0x00C58,0x00C5A), `Delta (0); (0x00C60,0x00C61), `Delta (0); (0x00C80,0x00C80), `Abs (0x00C80); (0x00C85,0x00C8C), `Delta (0); (0x00C8E,0x00C90), `Delta (0); (0x00C92,0x00CA8), `Delta (0); (0x00CAA,0x00CB3), `Delta (0); (0x00CB5,0x00CB9), `Delta (0); (0x00CBD,0x00CBD), `Abs (0x00CBD); (0x00CDE,0x00CDE), `Abs (0x00CDE); (0x00CE0,0x00CE1), `Delta (0); (0x00CF1,0x00CF2), `Delta (0); (0x00D05,0x00D0C), `Delta (0); (0x00D0E,0x00D10), `Delta (0); (0x00D12,0x00D3A), `Delta (0); (0x00D3D,0x00D3D), `Abs (0x00D3D); (0x00D4E,0x00D4E), `Abs (0x00D4E); (0x00D54,0x00D56), `Delta (0); (0x00D5F,0x00D61), `Delta (0); (0x00D7A,0x00D7F), `Delta (0); (0x00D85,0x00D96), `Delta (0); (0x00D9A,0x00DB1), `Delta (0); (0x00DB3,0x00DBB), `Delta (0); (0x00DBD,0x00DBD), `Abs (0x00DBD); (0x00DC0,0x00DC6), `Delta (0); (0x00E01,0x00E30), `Delta (0); (0x00E32,0x00E33), `Delta (0); (0x00E40,0x00E45), `Delta (0); (0x00E81,0x00E82), `Delta (0); (0x00E84,0x00E84), `Abs (0x00E84); (0x00E87,0x00E88), `Delta (0); (0x00E8A,0x00E8A), `Abs (0x00E8A); (0x00E8D,0x00E8D), `Abs (0x00E8D); (0x00E94,0x00E97), `Delta (0); (0x00E99,0x00E9F), `Delta (0); (0x00EA1,0x00EA3), `Delta (0); (0x00EA5,0x00EA5), `Abs (0x00EA5); (0x00EA7,0x00EA7), `Abs (0x00EA7); (0x00EAA,0x00EAB), `Delta (0); (0x00EAD,0x00EB0), `Delta (0); (0x00EB2,0x00EB3), `Delta (0); (0x00EBD,0x00EBD), `Abs (0x00EBD); (0x00EC0,0x00EC4), `Delta (0); (0x00EDC,0x00EDF), `Delta (0); (0x00F00,0x00F00), `Abs (0x00F00); (0x00F40,0x00F47), `Delta (0); (0x00F49,0x00F6C), `Delta (0); (0x00F88,0x00F8C), `Delta (0); (0x01000,0x0102A), `Delta (0); (0x0103F,0x0103F), `Abs (0x0103F); (0x01050,0x01055), `Delta (0); (0x0105A,0x0105D), `Delta (0); (0x01061,0x01061), `Abs (0x01061); (0x01065,0x01066), `Delta (0); (0x0106E,0x01070), `Delta (0); (0x01075,0x01081), `Delta (0); (0x0108E,0x0108E), `Abs (0x0108E); (0x010D0,0x010FA), `Delta (0); (0x010FD,0x01248), `Delta (0); (0x0124A,0x0124D), `Delta (0); (0x01250,0x01256), `Delta (0); (0x01258,0x01258), `Abs (0x01258); (0x0125A,0x0125D), `Delta (0); (0x01260,0x01288), `Delta (0); (0x0128A,0x0128D), `Delta (0); (0x01290,0x012B0), `Delta (0); (0x012B2,0x012B5), `Delta (0); (0x012B8,0x012BE), `Delta (0); (0x012C0,0x012C0), `Abs (0x012C0); (0x012C2,0x012C5), `Delta (0); (0x012C8,0x012D6), `Delta (0); (0x012D8,0x01310), `Delta (0); (0x01312,0x01315), `Delta (0); (0x01318,0x0135A), `Delta (0); (0x01380,0x0138F), `Delta (0); (0x01401,0x0166C), `Delta (0); (0x0166F,0x0167F), `Delta (0); (0x01681,0x0169A), `Delta (0); (0x016A0,0x016EA), `Delta (0); (0x016F1,0x016F8), `Delta (0); (0x01700,0x0170C), `Delta (0); (0x0170E,0x01711), `Delta (0); (0x01720,0x01731), `Delta (0); (0x01740,0x01751), `Delta (0); (0x01760,0x0176C), `Delta (0); (0x0176E,0x01770), `Delta (0); (0x01780,0x017B3), `Delta (0); (0x017DC,0x017DC), `Abs (0x017DC); (0x01820,0x01842), `Delta (0); (0x01844,0x01877), `Delta (0); (0x01880,0x01884), `Delta (0); (0x01887,0x018A8), `Delta (0); (0x018AA,0x018AA), `Abs (0x018AA); (0x018B0,0x018F5), `Delta (0); (0x01900,0x0191E), `Delta (0); (0x01950,0x0196D), `Delta (0); (0x01970,0x01974), `Delta (0); (0x01980,0x019AB), `Delta (0); (0x019B0,0x019C9), `Delta (0); (0x01A00,0x01A16), `Delta (0); (0x01A20,0x01A54), `Delta (0); (0x01B05,0x01B33), `Delta (0); (0x01B45,0x01B4B), `Delta (0); (0x01B83,0x01BA0), `Delta (0); (0x01BAE,0x01BAF), `Delta (0); (0x01BBA,0x01BE5), `Delta (0); (0x01C00,0x01C23), `Delta (0); (0x01C4D,0x01C4F), `Delta (0); (0x01C5A,0x01C77), `Delta (0); (0x01CE9,0x01CEC), `Delta (0); (0x01CEE,0x01CF1), `Delta (0); (0x01CF5,0x01CF6), `Delta (0); (0x02135,0x02138), `Delta (0); (0x02D30,0x02D67), `Delta (0); (0x02D80,0x02D96), `Delta (0); (0x02DA0,0x02DA6), `Delta (0); (0x02DA8,0x02DAE), `Delta (0); (0x02DB0,0x02DB6), `Delta (0); (0x02DB8,0x02DBE), `Delta (0); (0x02DC0,0x02DC6), `Delta (0); (0x02DC8,0x02DCE), `Delta (0); (0x02DD0,0x02DD6), `Delta (0); (0x02DD8,0x02DDE), `Delta (0); (0x03006,0x03006), `Abs (0x03006); (0x0303C,0x0303C), `Abs (0x0303C); (0x03041,0x03096), `Delta (0); (0x0309F,0x0309F), `Abs (0x0309F); (0x030A1,0x030FA), `Delta (0); (0x030FF,0x030FF), `Abs (0x030FF); (0x03105,0x0312D), `Delta (0); (0x03131,0x0318E), `Delta (0); (0x031A0,0x031BA), `Delta (0); (0x031F0,0x031FF), `Delta (0); (0x03400,0x04DB5), `Delta (0); (0x04E00,0x09FD5), `Delta (0); (0x0A000,0x0A014), `Delta (0); (0x0A016,0x0A48C), `Delta (0); (0x0A4D0,0x0A4F7), `Delta (0); (0x0A500,0x0A60B), `Delta (0); (0x0A610,0x0A61F), `Delta (0); (0x0A62A,0x0A62B), `Delta (0); (0x0A66E,0x0A66E), `Abs (0x0A66E); (0x0A6A0,0x0A6E5), `Delta (0); (0x0A78F,0x0A78F), `Abs (0x0A78F); (0x0A7F7,0x0A7F7), `Abs (0x0A7F7); (0x0A7FB,0x0A801), `Delta (0); (0x0A803,0x0A805), `Delta (0); (0x0A807,0x0A80A), `Delta (0); (0x0A80C,0x0A822), `Delta (0); (0x0A840,0x0A873), `Delta (0); (0x0A882,0x0A8B3), `Delta (0); (0x0A8F2,0x0A8F7), `Delta (0); (0x0A8FB,0x0A8FB), `Abs (0x0A8FB); (0x0A8FD,0x0A8FD), `Abs (0x0A8FD); (0x0A90A,0x0A925), `Delta (0); (0x0A930,0x0A946), `Delta (0); (0x0A960,0x0A97C), `Delta (0); (0x0A984,0x0A9B2), `Delta (0); (0x0A9E0,0x0A9E4), `Delta (0); (0x0A9E7,0x0A9EF), `Delta (0); (0x0A9FA,0x0A9FE), `Delta (0); (0x0AA00,0x0AA28), `Delta (0); (0x0AA40,0x0AA42), `Delta (0); (0x0AA44,0x0AA4B), `Delta (0); (0x0AA60,0x0AA6F), `Delta (0); (0x0AA71,0x0AA76), `Delta (0); (0x0AA7A,0x0AA7A), `Abs (0x0AA7A); (0x0AA7E,0x0AAAF), `Delta (0); (0x0AAB1,0x0AAB1), `Abs (0x0AAB1); (0x0AAB5,0x0AAB6), `Delta (0); (0x0AAB9,0x0AABD), `Delta (0); (0x0AAC0,0x0AAC0), `Abs (0x0AAC0); (0x0AAC2,0x0AAC2), `Abs (0x0AAC2); (0x0AADB,0x0AADC), `Delta (0); (0x0AAE0,0x0AAEA), `Delta (0); (0x0AAF2,0x0AAF2), `Abs (0x0AAF2); (0x0AB01,0x0AB06), `Delta (0); (0x0AB09,0x0AB0E), `Delta (0); (0x0AB11,0x0AB16), `Delta (0); (0x0AB20,0x0AB26), `Delta (0); (0x0AB28,0x0AB2E), `Delta (0); (0x0ABC0,0x0ABE2), `Delta (0); (0x0AC00,0x0D7A3), `Delta (0); (0x0D7B0,0x0D7C6), `Delta (0); (0x0D7CB,0x0D7FB), `Delta (0); (0x0F900,0x0FA6D), `Delta (0); (0x0FA70,0x0FAD9), `Delta (0); (0x0FB1D,0x0FB1D), `Abs (0x0FB1D); (0x0FB1F,0x0FB28), `Delta (0); (0x0FB2A,0x0FB36), `Delta (0); (0x0FB38,0x0FB3C), `Delta (0); (0x0FB3E,0x0FB3E), `Abs (0x0FB3E); (0x0FB40,0x0FB41), `Delta (0); (0x0FB43,0x0FB44), `Delta (0); (0x0FB46,0x0FBB1), `Delta (0); (0x0FBD3,0x0FD3D), `Delta (0); (0x0FD50,0x0FD8F), `Delta (0); (0x0FD92,0x0FDC7), `Delta (0); (0x0FDF0,0x0FDFB), `Delta (0); (0x0FE70,0x0FE74), `Delta (0); (0x0FE76,0x0FEFC), `Delta (0); (0x0FF66,0x0FF6F), `Delta (0); (0x0FF71,0x0FF9D), `Delta (0); (0x0FFA0,0x0FFBE), `Delta (0); (0x0FFC2,0x0FFC7), `Delta (0); (0x0FFCA,0x0FFCF), `Delta (0); (0x0FFD2,0x0FFD7), `Delta (0); (0x0FFDA,0x0FFDC), `Delta (0); (0x10000,0x1000B), `Delta (0); (0x1000D,0x10026), `Delta (0); (0x10028,0x1003A), `Delta (0); (0x1003C,0x1003D), `Delta (0); (0x1003F,0x1004D), `Delta (0); (0x10050,0x1005D), `Delta (0); (0x10080,0x100FA), `Delta (0); (0x10280,0x1029C), `Delta (0); (0x102A0,0x102D0), `Delta (0); (0x10300,0x1031F), `Delta (0); (0x10330,0x10340), `Delta (0); (0x10342,0x10349), `Delta (0); (0x10350,0x10375), `Delta (0); (0x10380,0x1039D), `Delta (0); (0x103A0,0x103C3), `Delta (0); (0x103C8,0x103CF), `Delta (0); (0x10450,0x1049D), `Delta (0); (0x10500,0x10527), `Delta (0); (0x10530,0x10563), `Delta (0); (0x10600,0x10736), `Delta (0); (0x10740,0x10755), `Delta (0); (0x10760,0x10767), `Delta (0); (0x10800,0x10805), `Delta (0); (0x10808,0x10808), `Abs (0x10808); (0x1080A,0x10835), `Delta (0); (0x10837,0x10838), `Delta (0); (0x1083C,0x1083C), `Abs (0x1083C); (0x1083F,0x10855), `Delta (0); (0x10860,0x10876), `Delta (0); (0x10880,0x1089E), `Delta (0); (0x108E0,0x108F2), `Delta (0); (0x108F4,0x108F5), `Delta (0); (0x10900,0x10915), `Delta (0); (0x10920,0x10939), `Delta (0); (0x10980,0x109B7), `Delta (0); (0x109BE,0x109BF), `Delta (0); (0x10A00,0x10A00), `Abs (0x10A00); (0x10A10,0x10A13), `Delta (0); (0x10A15,0x10A17), `Delta (0); (0x10A19,0x10A33), `Delta (0); (0x10A60,0x10A7C), `Delta (0); (0x10A80,0x10A9C), `Delta (0); (0x10AC0,0x10AC7), `Delta (0); (0x10AC9,0x10AE4), `Delta (0); (0x10B00,0x10B35), `Delta (0); (0x10B40,0x10B55), `Delta (0); (0x10B60,0x10B72), `Delta (0); (0x10B80,0x10B91), `Delta (0); (0x10C00,0x10C48), `Delta (0); (0x11003,0x11037), `Delta (0); (0x11083,0x110AF), `Delta (0); (0x110D0,0x110E8), `Delta (0); (0x11103,0x11126), `Delta (0); (0x11150,0x11172), `Delta (0); (0x11176,0x11176), `Abs (0x11176); (0x11183,0x111B2), `Delta (0); (0x111C1,0x111C4), `Delta (0); (0x111DA,0x111DA), `Abs (0x111DA); (0x111DC,0x111DC), `Abs (0x111DC); (0x11200,0x11211), `Delta (0); (0x11213,0x1122B), `Delta (0); (0x11280,0x11286), `Delta (0); (0x11288,0x11288), `Abs (0x11288); (0x1128A,0x1128D), `Delta (0); (0x1128F,0x1129D), `Delta (0); (0x1129F,0x112A8), `Delta (0); (0x112B0,0x112DE), `Delta (0); (0x11305,0x1130C), `Delta (0); (0x1130F,0x11310), `Delta (0); (0x11313,0x11328), `Delta (0); (0x1132A,0x11330), `Delta (0); (0x11332,0x11333), `Delta (0); (0x11335,0x11339), `Delta (0); (0x1133D,0x1133D), `Abs (0x1133D); (0x11350,0x11350), `Abs (0x11350); (0x1135D,0x11361), `Delta (0); (0x11400,0x11434), `Delta (0); (0x11447,0x1144A), `Delta (0); (0x11480,0x114AF), `Delta (0); (0x114C4,0x114C5), `Delta (0); (0x114C7,0x114C7), `Abs (0x114C7); (0x11580,0x115AE), `Delta (0); (0x115D8,0x115DB), `Delta (0); (0x11600,0x1162F), `Delta (0); (0x11644,0x11644), `Abs (0x11644); (0x11680,0x116AA), `Delta (0); (0x11700,0x11719), `Delta (0); (0x118FF,0x118FF), `Abs (0x118FF); (0x11AC0,0x11AF8), `Delta (0); (0x11C00,0x11C08), `Delta (0); (0x11C0A,0x11C2E), `Delta (0); (0x11C40,0x11C40), `Abs (0x11C40); (0x11C72,0x11C8F), `Delta (0); (0x12000,0x12399), `Delta (0); (0x12480,0x12543), `Delta (0); (0x13000,0x1342E), `Delta (0); (0x14400,0x14646), `Delta (0); (0x16800,0x16A38), `Delta (0); (0x16A40,0x16A5E), `Delta (0); (0x16AD0,0x16AED), `Delta (0); (0x16B00,0x16B2F), `Delta (0); (0x16B63,0x16B77), `Delta (0); (0x16B7D,0x16B8F), `Delta (0); (0x16F00,0x16F44), `Delta (0); (0x16F50,0x16F50), `Abs (0x16F50); (0x17000,0x187EC), `Delta (0); (0x18800,0x18AF2), `Delta (0); (0x1B000,0x1B001), `Delta (0); (0x1BC00,0x1BC6A), `Delta (0); (0x1BC70,0x1BC7C), `Delta (0); (0x1BC80,0x1BC88), `Delta (0); (0x1BC90,0x1BC99), `Delta (0); (0x1E800,0x1E8C4), `Delta (0); (0x1EE00,0x1EE03), `Delta (0); (0x1EE05,0x1EE1F), `Delta (0); (0x1EE21,0x1EE22), `Delta (0); (0x1EE24,0x1EE24), `Abs (0x1EE24); (0x1EE27,0x1EE27), `Abs (0x1EE27); (0x1EE29,0x1EE32), `Delta (0); (0x1EE34,0x1EE37), `Delta (0); (0x1EE39,0x1EE39), `Abs (0x1EE39); (0x1EE3B,0x1EE3B), `Abs (0x1EE3B); (0x1EE42,0x1EE42), `Abs (0x1EE42); (0x1EE47,0x1EE47), `Abs (0x1EE47); (0x1EE49,0x1EE49), `Abs (0x1EE49); (0x1EE4B,0x1EE4B), `Abs (0x1EE4B); (0x1EE4D,0x1EE4F), `Delta (0); (0x1EE51,0x1EE52), `Delta (0); (0x1EE54,0x1EE54), `Abs (0x1EE54); (0x1EE57,0x1EE57), `Abs (0x1EE57); (0x1EE59,0x1EE59), `Abs (0x1EE59); (0x1EE5B,0x1EE5B), `Abs (0x1EE5B); (0x1EE5D,0x1EE5D), `Abs (0x1EE5D); (0x1EE5F,0x1EE5F), `Abs (0x1EE5F); (0x1EE61,0x1EE62), `Delta (0); (0x1EE64,0x1EE64), `Abs (0x1EE64); (0x1EE67,0x1EE6A), `Delta (0); (0x1EE6C,0x1EE72), `Delta (0); (0x1EE74,0x1EE77), `Delta (0); (0x1EE79,0x1EE7C), `Delta (0); (0x1EE7E,0x1EE7E), `Abs (0x1EE7E); (0x1EE80,0x1EE89), `Delta (0); (0x1EE8B,0x1EE9B), `Delta (0); (0x1EEA1,0x1EEA3), `Delta (0); (0x1EEA5,0x1EEA9), `Delta (0); (0x1EEAB,0x1EEBB), `Delta (0); (0x20000,0x2A6D6), `Delta (0); (0x2A700,0x2B734), `Delta (0); (0x2B740,0x2B81D), `Delta (0); (0x2B820,0x2CEA1), `Delta (0); (0x2F800,0x2FA1D), `Delta (0); (0x0005F,0x0005F), `Abs (0x0005F); (0x0203F,0x02040), `Delta (0); (0x02054,0x02054), `Abs (0x02054); (0x0FE33,0x0FE34), `Delta (0); (0x0FE4D,0x0FE4F), `Delta (0); (0x0FF3F,0x0FF3F), `Abs (0x0FF3F); (0x0002D,0x0002D), `Abs (0x0002D); (0x0058A,0x0058A), `Abs (0x0058A); (0x005BE,0x005BE), `Abs (0x005BE); (0x01400,0x01400), `Abs (0x01400); (0x01806,0x01806), `Abs (0x01806); (0x02010,0x02015), `Delta (0); (0x02E17,0x02E17), `Abs (0x02E17); (0x02E1A,0x02E1A), `Abs (0x02E1A); (0x02E3A,0x02E3B), `Delta (0); (0x02E40,0x02E40), `Abs (0x02E40); (0x0301C,0x0301C), `Abs (0x0301C); (0x03030,0x03030), `Abs (0x03030); (0x030A0,0x030A0), `Abs (0x030A0); (0x0FE31,0x0FE32), `Delta (0); (0x0FE58,0x0FE58), `Abs (0x0FE58); (0x0FE63,0x0FE63), `Abs (0x0FE63); (0x0FF0D,0x0FF0D), `Abs (0x0FF0D); (0x00028,0x00028), `Abs (0x00028); (0x0005B,0x0005B), `Abs (0x0005B); (0x0007B,0x0007B), `Abs (0x0007B); (0x00F3A,0x00F3A), `Abs (0x00F3A); (0x00F3C,0x00F3C), `Abs (0x00F3C); (0x0169B,0x0169B), `Abs (0x0169B); (0x0201A,0x0201A), `Abs (0x0201A); (0x0201E,0x0201E), `Abs (0x0201E); (0x02045,0x02045), `Abs (0x02045); (0x0207D,0x0207D), `Abs (0x0207D); (0x0208D,0x0208D), `Abs (0x0208D); (0x02308,0x02308), `Abs (0x02308); (0x0230A,0x0230A), `Abs (0x0230A); (0x02329,0x02329), `Abs (0x02329); (0x02768,0x02768), `Abs (0x02768); (0x0276A,0x0276A), `Abs (0x0276A); (0x0276C,0x0276C), `Abs (0x0276C); (0x0276E,0x0276E), `Abs (0x0276E); (0x02770,0x02770), `Abs (0x02770); (0x02772,0x02772), `Abs (0x02772); (0x02774,0x02774), `Abs (0x02774); (0x027C5,0x027C5), `Abs (0x027C5); (0x027E6,0x027E6), `Abs (0x027E6); (0x027E8,0x027E8), `Abs (0x027E8); (0x027EA,0x027EA), `Abs (0x027EA); (0x027EC,0x027EC), `Abs (0x027EC); (0x027EE,0x027EE), `Abs (0x027EE); (0x02983,0x02983), `Abs (0x02983); (0x02985,0x02985), `Abs (0x02985); (0x02987,0x02987), `Abs (0x02987); (0x02989,0x02989), `Abs (0x02989); (0x0298B,0x0298B), `Abs (0x0298B); (0x0298D,0x0298D), `Abs (0x0298D); (0x0298F,0x0298F), `Abs (0x0298F); (0x02991,0x02991), `Abs (0x02991); (0x02993,0x02993), `Abs (0x02993); (0x02995,0x02995), `Abs (0x02995); (0x02997,0x02997), `Abs (0x02997); (0x029D8,0x029D8), `Abs (0x029D8); (0x029DA,0x029DA), `Abs (0x029DA); (0x029FC,0x029FC), `Abs (0x029FC); (0x02E22,0x02E22), `Abs (0x02E22); (0x02E24,0x02E24), `Abs (0x02E24); (0x02E26,0x02E26), `Abs (0x02E26); (0x02E28,0x02E28), `Abs (0x02E28); (0x02E42,0x02E42), `Abs (0x02E42); (0x03008,0x03008), `Abs (0x03008); (0x0300A,0x0300A), `Abs (0x0300A); (0x0300C,0x0300C), `Abs (0x0300C); (0x0300E,0x0300E), `Abs (0x0300E); (0x03010,0x03010), `Abs (0x03010); (0x03014,0x03014), `Abs (0x03014); (0x03016,0x03016), `Abs (0x03016); (0x03018,0x03018), `Abs (0x03018); (0x0301A,0x0301A), `Abs (0x0301A); (0x0301D,0x0301D), `Abs (0x0301D); (0x0FD3F,0x0FD3F), `Abs (0x0FD3F); (0x0FE17,0x0FE17), `Abs (0x0FE17); (0x0FE35,0x0FE35), `Abs (0x0FE35); (0x0FE37,0x0FE37), `Abs (0x0FE37); (0x0FE39,0x0FE39), `Abs (0x0FE39); (0x0FE3B,0x0FE3B), `Abs (0x0FE3B); (0x0FE3D,0x0FE3D), `Abs (0x0FE3D); (0x0FE3F,0x0FE3F), `Abs (0x0FE3F); (0x0FE41,0x0FE41), `Abs (0x0FE41); (0x0FE43,0x0FE43), `Abs (0x0FE43); (0x0FE47,0x0FE47), `Abs (0x0FE47); (0x0FE59,0x0FE59), `Abs (0x0FE59); (0x0FE5B,0x0FE5B), `Abs (0x0FE5B); (0x0FE5D,0x0FE5D), `Abs (0x0FE5D); (0x0FF08,0x0FF08), `Abs (0x0FF08); (0x0FF3B,0x0FF3B), `Abs (0x0FF3B); (0x0FF5B,0x0FF5B), `Abs (0x0FF5B); (0x0FF5F,0x0FF5F), `Abs (0x0FF5F); (0x0FF62,0x0FF62), `Abs (0x0FF62); (0x00029,0x00029), `Abs (0x00029); (0x0005D,0x0005D), `Abs (0x0005D); (0x0007D,0x0007D), `Abs (0x0007D); (0x00F3B,0x00F3B), `Abs (0x00F3B); (0x00F3D,0x00F3D), `Abs (0x00F3D); (0x0169C,0x0169C), `Abs (0x0169C); (0x02046,0x02046), `Abs (0x02046); (0x0207E,0x0207E), `Abs (0x0207E); (0x0208E,0x0208E), `Abs (0x0208E); (0x02309,0x02309), `Abs (0x02309); (0x0230B,0x0230B), `Abs (0x0230B); (0x0232A,0x0232A), `Abs (0x0232A); (0x02769,0x02769), `Abs (0x02769); (0x0276B,0x0276B), `Abs (0x0276B); (0x0276D,0x0276D), `Abs (0x0276D); (0x0276F,0x0276F), `Abs (0x0276F); (0x02771,0x02771), `Abs (0x02771); (0x02773,0x02773), `Abs (0x02773); (0x02775,0x02775), `Abs (0x02775); (0x027C6,0x027C6), `Abs (0x027C6); (0x027E7,0x027E7), `Abs (0x027E7); (0x027E9,0x027E9), `Abs (0x027E9); (0x027EB,0x027EB), `Abs (0x027EB); (0x027ED,0x027ED), `Abs (0x027ED); (0x027EF,0x027EF), `Abs (0x027EF); (0x02984,0x02984), `Abs (0x02984); (0x02986,0x02986), `Abs (0x02986); (0x02988,0x02988), `Abs (0x02988); (0x0298A,0x0298A), `Abs (0x0298A); (0x0298C,0x0298C), `Abs (0x0298C); (0x0298E,0x0298E), `Abs (0x0298E); (0x02990,0x02990), `Abs (0x02990); (0x02992,0x02992), `Abs (0x02992); (0x02994,0x02994), `Abs (0x02994); (0x02996,0x02996), `Abs (0x02996); (0x02998,0x02998), `Abs (0x02998); (0x029D9,0x029D9), `Abs (0x029D9); (0x029DB,0x029DB), `Abs (0x029DB); (0x029FD,0x029FD), `Abs (0x029FD); (0x02E23,0x02E23), `Abs (0x02E23); (0x02E25,0x02E25), `Abs (0x02E25); (0x02E27,0x02E27), `Abs (0x02E27); (0x02E29,0x02E29), `Abs (0x02E29); (0x03009,0x03009), `Abs (0x03009); (0x0300B,0x0300B), `Abs (0x0300B); (0x0300D,0x0300D), `Abs (0x0300D); (0x0300F,0x0300F), `Abs (0x0300F); (0x03011,0x03011), `Abs (0x03011); (0x03015,0x03015), `Abs (0x03015); (0x03017,0x03017), `Abs (0x03017); (0x03019,0x03019), `Abs (0x03019); (0x0301B,0x0301B), `Abs (0x0301B); (0x0301E,0x0301F), `Delta (0); (0x0FD3E,0x0FD3E), `Abs (0x0FD3E); (0x0FE18,0x0FE18), `Abs (0x0FE18); (0x0FE36,0x0FE36), `Abs (0x0FE36); (0x0FE38,0x0FE38), `Abs (0x0FE38); (0x0FE3A,0x0FE3A), `Abs (0x0FE3A); (0x0FE3C,0x0FE3C), `Abs (0x0FE3C); (0x0FE3E,0x0FE3E), `Abs (0x0FE3E); (0x0FE40,0x0FE40), `Abs (0x0FE40); (0x0FE42,0x0FE42), `Abs (0x0FE42); (0x0FE44,0x0FE44), `Abs (0x0FE44); (0x0FE48,0x0FE48), `Abs (0x0FE48); (0x0FE5A,0x0FE5A), `Abs (0x0FE5A); (0x0FE5C,0x0FE5C), `Abs (0x0FE5C); (0x0FE5E,0x0FE5E), `Abs (0x0FE5E); (0x0FF09,0x0FF09), `Abs (0x0FF09); (0x0FF3D,0x0FF3D), `Abs (0x0FF3D); (0x0FF5D,0x0FF5D), `Abs (0x0FF5D); (0x0FF60,0x0FF60), `Abs (0x0FF60); (0x0FF63,0x0FF63), `Abs (0x0FF63); (0x000AB,0x000AB), `Abs (0x000AB); (0x02018,0x02018), `Abs (0x02018); (0x0201B,0x0201C), `Delta (0); (0x0201F,0x0201F), `Abs (0x0201F); (0x02039,0x02039), `Abs (0x02039); (0x02E02,0x02E02), `Abs (0x02E02); (0x02E04,0x02E04), `Abs (0x02E04); (0x02E09,0x02E09), `Abs (0x02E09); (0x02E0C,0x02E0C), `Abs (0x02E0C); (0x02E1C,0x02E1C), `Abs (0x02E1C); (0x02E20,0x02E20), `Abs (0x02E20); (0x000BB,0x000BB), `Abs (0x000BB); (0x02019,0x02019), `Abs (0x02019); (0x0201D,0x0201D), `Abs (0x0201D); (0x0203A,0x0203A), `Abs (0x0203A); (0x02E03,0x02E03), `Abs (0x02E03); (0x02E05,0x02E05), `Abs (0x02E05); (0x02E0A,0x02E0A), `Abs (0x02E0A); (0x02E0D,0x02E0D), `Abs (0x02E0D); (0x02E1D,0x02E1D), `Abs (0x02E1D); (0x02E21,0x02E21), `Abs (0x02E21); (0x00021,0x00023), `Delta (0); (0x00025,0x00027), `Delta (0); (0x0002A,0x0002A), `Abs (0x0002A); (0x0002C,0x0002C), `Abs (0x0002C); (0x0002E,0x0002F), `Delta (0); (0x0003A,0x0003B), `Delta (0); (0x0003F,0x00040), `Delta (0); (0x0005C,0x0005C), `Abs (0x0005C); (0x000A1,0x000A1), `Abs (0x000A1); (0x000A7,0x000A7), `Abs (0x000A7); (0x000B6,0x000B7), `Delta (0); (0x000BF,0x000BF), `Abs (0x000BF); (0x0037E,0x0037E), `Abs (0x0037E); (0x00387,0x00387), `Abs (0x00387); (0x0055A,0x0055F), `Delta (0); (0x00589,0x00589), `Abs (0x00589); (0x005C0,0x005C0), `Abs (0x005C0); (0x005C3,0x005C3), `Abs (0x005C3); (0x005C6,0x005C6), `Abs (0x005C6); (0x005F3,0x005F4), `Delta (0); (0x00609,0x0060A), `Delta (0); (0x0060C,0x0060D), `Delta (0); (0x0061B,0x0061B), `Abs (0x0061B); (0x0061E,0x0061F), `Delta (0); (0x0066A,0x0066D), `Delta (0); (0x006D4,0x006D4), `Abs (0x006D4); (0x00700,0x0070D), `Delta (0); (0x007F7,0x007F9), `Delta (0); (0x00830,0x0083E), `Delta (0); (0x0085E,0x0085E), `Abs (0x0085E); (0x00964,0x00965), `Delta (0); (0x00970,0x00970), `Abs (0x00970); (0x00AF0,0x00AF0), `Abs (0x00AF0); (0x00DF4,0x00DF4), `Abs (0x00DF4); (0x00E4F,0x00E4F), `Abs (0x00E4F); (0x00E5A,0x00E5B), `Delta (0); (0x00F04,0x00F12), `Delta (0); (0x00F14,0x00F14), `Abs (0x00F14); (0x00F85,0x00F85), `Abs (0x00F85); (0x00FD0,0x00FD4), `Delta (0); (0x00FD9,0x00FDA), `Delta (0); (0x0104A,0x0104F), `Delta (0); (0x010FB,0x010FB), `Abs (0x010FB); (0x01360,0x01368), `Delta (0); (0x0166D,0x0166E), `Delta (0); (0x016EB,0x016ED), `Delta (0); (0x01735,0x01736), `Delta (0); (0x017D4,0x017D6), `Delta (0); (0x017D8,0x017DA), `Delta (0); (0x01800,0x01805), `Delta (0); (0x01807,0x0180A), `Delta (0); (0x01944,0x01945), `Delta (0); (0x01A1E,0x01A1F), `Delta (0); (0x01AA0,0x01AA6), `Delta (0); (0x01AA8,0x01AAD), `Delta (0); (0x01B5A,0x01B60), `Delta (0); (0x01BFC,0x01BFF), `Delta (0); (0x01C3B,0x01C3F), `Delta (0); (0x01C7E,0x01C7F), `Delta (0); (0x01CC0,0x01CC7), `Delta (0); (0x01CD3,0x01CD3), `Abs (0x01CD3); (0x02016,0x02017), `Delta (0); (0x02020,0x02027), `Delta (0); (0x02030,0x02038), `Delta (0); (0x0203B,0x0203E), `Delta (0); (0x02041,0x02043), `Delta (0); (0x02047,0x02051), `Delta (0); (0x02053,0x02053), `Abs (0x02053); (0x02055,0x0205E), `Delta (0); (0x02CF9,0x02CFC), `Delta (0); (0x02CFE,0x02CFF), `Delta (0); (0x02D70,0x02D70), `Abs (0x02D70); (0x02E00,0x02E01), `Delta (0); (0x02E06,0x02E08), `Delta (0); (0x02E0B,0x02E0B), `Abs (0x02E0B); (0x02E0E,0x02E16), `Delta (0); (0x02E18,0x02E19), `Delta (0); (0x02E1B,0x02E1B), `Abs (0x02E1B); (0x02E1E,0x02E1F), `Delta (0); (0x02E2A,0x02E2E), `Delta (0); (0x02E30,0x02E39), `Delta (0); (0x02E3C,0x02E3F), `Delta (0); (0x02E41,0x02E41), `Abs (0x02E41); (0x02E43,0x02E44), `Delta (0); (0x03001,0x03003), `Delta (0); (0x0303D,0x0303D), `Abs (0x0303D); (0x030FB,0x030FB), `Abs (0x030FB); (0x0A4FE,0x0A4FF), `Delta (0); (0x0A60D,0x0A60F), `Delta (0); (0x0A673,0x0A673), `Abs (0x0A673); (0x0A67E,0x0A67E), `Abs (0x0A67E); (0x0A6F2,0x0A6F7), `Delta (0); (0x0A874,0x0A877), `Delta (0); (0x0A8CE,0x0A8CF), `Delta (0); (0x0A8F8,0x0A8FA), `Delta (0); (0x0A8FC,0x0A8FC), `Abs (0x0A8FC); (0x0A92E,0x0A92F), `Delta (0); (0x0A95F,0x0A95F), `Abs (0x0A95F); (0x0A9C1,0x0A9CD), `Delta (0); (0x0A9DE,0x0A9DF), `Delta (0); (0x0AA5C,0x0AA5F), `Delta (0); (0x0AADE,0x0AADF), `Delta (0); (0x0AAF0,0x0AAF1), `Delta (0); (0x0ABEB,0x0ABEB), `Abs (0x0ABEB); (0x0FE10,0x0FE16), `Delta (0); (0x0FE19,0x0FE19), `Abs (0x0FE19); (0x0FE30,0x0FE30), `Abs (0x0FE30); (0x0FE45,0x0FE46), `Delta (0); (0x0FE49,0x0FE4C), `Delta (0); (0x0FE50,0x0FE52), `Delta (0); (0x0FE54,0x0FE57), `Delta (0); (0x0FE5F,0x0FE61), `Delta (0); (0x0FE68,0x0FE68), `Abs (0x0FE68); (0x0FE6A,0x0FE6B), `Delta (0); (0x0FF01,0x0FF03), `Delta (0); (0x0FF05,0x0FF07), `Delta (0); (0x0FF0A,0x0FF0A), `Abs (0x0FF0A); (0x0FF0C,0x0FF0C), `Abs (0x0FF0C); (0x0FF0E,0x0FF0F), `Delta (0); (0x0FF1A,0x0FF1B), `Delta (0); (0x0FF1F,0x0FF20), `Delta (0); (0x0FF3C,0x0FF3C), `Abs (0x0FF3C); (0x0FF61,0x0FF61), `Abs (0x0FF61); (0x0FF64,0x0FF65), `Delta (0); (0x10100,0x10102), `Delta (0); (0x1039F,0x1039F), `Abs (0x1039F); (0x103D0,0x103D0), `Abs (0x103D0); (0x1056F,0x1056F), `Abs (0x1056F); (0x10857,0x10857), `Abs (0x10857); (0x1091F,0x1091F), `Abs (0x1091F); (0x1093F,0x1093F), `Abs (0x1093F); (0x10A50,0x10A58), `Delta (0); (0x10A7F,0x10A7F), `Abs (0x10A7F); (0x10AF0,0x10AF6), `Delta (0); (0x10B39,0x10B3F), `Delta (0); (0x10B99,0x10B9C), `Delta (0); (0x11047,0x1104D), `Delta (0); (0x110BB,0x110BC), `Delta (0); (0x110BE,0x110C1), `Delta (0); (0x11140,0x11143), `Delta (0); (0x11174,0x11175), `Delta (0); (0x111C5,0x111C9), `Delta (0); (0x111CD,0x111CD), `Abs (0x111CD); (0x111DB,0x111DB), `Abs (0x111DB); (0x111DD,0x111DF), `Delta (0); (0x11238,0x1123D), `Delta (0); (0x112A9,0x112A9), `Abs (0x112A9); (0x1144B,0x1144F), `Delta (0); (0x1145B,0x1145B), `Abs (0x1145B); (0x1145D,0x1145D), `Abs (0x1145D); (0x114C6,0x114C6), `Abs (0x114C6); (0x115C1,0x115D7), `Delta (0); (0x11641,0x11643), `Delta (0); (0x11660,0x1166C), `Delta (0); (0x1173C,0x1173E), `Delta (0); (0x11C41,0x11C45), `Delta (0); (0x11C70,0x11C71), `Delta (0); (0x12470,0x12474), `Delta (0); (0x16A6E,0x16A6F), `Delta (0); (0x16AF5,0x16AF5), `Abs (0x16AF5); (0x16B37,0x16B3B), `Delta (0); (0x16B44,0x16B44), `Abs (0x16B44); (0x1BC9F,0x1BC9F), `Abs (0x1BC9F); (0x1DA87,0x1DA8B), `Delta (0); (0x1E95E,0x1E95F), `Delta (0); (0x0002B,0x0002B), `Abs (0x0002B); (0x0003C,0x0003E), `Delta (0); (0x0007C,0x0007C), `Abs (0x0007C); (0x0007E,0x0007E), `Abs (0x0007E); (0x000AC,0x000AC), `Abs (0x000AC); (0x000B1,0x000B1), `Abs (0x000B1); (0x000D7,0x000D7), `Abs (0x000D7); (0x000F7,0x000F7), `Abs (0x000F7); (0x003F6,0x003F6), `Abs (0x003F6); (0x00606,0x00608), `Delta (0); (0x02044,0x02044), `Abs (0x02044); (0x02052,0x02052), `Abs (0x02052); (0x0207A,0x0207C), `Delta (0); (0x0208A,0x0208C), `Delta (0); (0x02118,0x02118), `Abs (0x02118); (0x02140,0x02144), `Delta (0); (0x0214B,0x0214B), `Abs (0x0214B); (0x02190,0x02194), `Delta (0); (0x0219A,0x0219B), `Delta (0); (0x021A0,0x021A0), `Abs (0x021A0); (0x021A3,0x021A3), `Abs (0x021A3); (0x021A6,0x021A6), `Abs (0x021A6); (0x021AE,0x021AE), `Abs (0x021AE); (0x021CE,0x021CF), `Delta (0); (0x021D2,0x021D2), `Abs (0x021D2); (0x021D4,0x021D4), `Abs (0x021D4); (0x021F4,0x022FF), `Delta (0); (0x02320,0x02321), `Delta (0); (0x0237C,0x0237C), `Abs (0x0237C); (0x0239B,0x023B3), `Delta (0); (0x023DC,0x023E1), `Delta (0); (0x025B7,0x025B7), `Abs (0x025B7); (0x025C1,0x025C1), `Abs (0x025C1); (0x025F8,0x025FF), `Delta (0); (0x0266F,0x0266F), `Abs (0x0266F); (0x027C0,0x027C4), `Delta (0); (0x027C7,0x027E5), `Delta (0); (0x027F0,0x027FF), `Delta (0); (0x02900,0x02982), `Delta (0); (0x02999,0x029D7), `Delta (0); (0x029DC,0x029FB), `Delta (0); (0x029FE,0x02AFF), `Delta (0); (0x02B30,0x02B44), `Delta (0); (0x02B47,0x02B4C), `Delta (0); (0x0FB29,0x0FB29), `Abs (0x0FB29); (0x0FE62,0x0FE62), `Abs (0x0FE62); (0x0FE64,0x0FE66), `Delta (0); (0x0FF0B,0x0FF0B), `Abs (0x0FF0B); (0x0FF1C,0x0FF1E), `Delta (0); (0x0FF5C,0x0FF5C), `Abs (0x0FF5C); (0x0FF5E,0x0FF5E), `Abs (0x0FF5E); (0x0FFE2,0x0FFE2), `Abs (0x0FFE2); (0x0FFE9,0x0FFEC), `Delta (0); (0x1D6C1,0x1D6C1), `Abs (0x1D6C1); (0x1D6DB,0x1D6DB), `Abs (0x1D6DB); (0x1D6FB,0x1D6FB), `Abs (0x1D6FB); (0x1D715,0x1D715), `Abs (0x1D715); (0x1D735,0x1D735), `Abs (0x1D735); (0x1D74F,0x1D74F), `Abs (0x1D74F); (0x1D76F,0x1D76F), `Abs (0x1D76F); (0x1D789,0x1D789), `Abs (0x1D789); (0x1D7A9,0x1D7A9), `Abs (0x1D7A9); (0x1D7C3,0x1D7C3), `Abs (0x1D7C3); (0x1EEF0,0x1EEF1), `Delta (0); (0x00024,0x00024), `Abs (0x00024); (0x000A2,0x000A5), `Delta (0); (0x0058F,0x0058F), `Abs (0x0058F); (0x0060B,0x0060B), `Abs (0x0060B); (0x009F2,0x009F3), `Delta (0); (0x009FB,0x009FB), `Abs (0x009FB); (0x00AF1,0x00AF1), `Abs (0x00AF1); (0x00BF9,0x00BF9), `Abs (0x00BF9); (0x00E3F,0x00E3F), `Abs (0x00E3F); (0x017DB,0x017DB), `Abs (0x017DB); (0x020A0,0x020BE), `Delta (0); (0x0A838,0x0A838), `Abs (0x0A838); (0x0FDFC,0x0FDFC), `Abs (0x0FDFC); (0x0FE69,0x0FE69), `Abs (0x0FE69); (0x0FF04,0x0FF04), `Abs (0x0FF04); (0x0FFE0,0x0FFE1), `Delta (0); (0x0FFE5,0x0FFE6), `Delta (0); (0x0005E,0x0005E), `Abs (0x0005E); (0x00060,0x00060), `Abs (0x00060); (0x000A8,0x000A8), `Abs (0x000A8); (0x000AF,0x000AF), `Abs (0x000AF); (0x000B4,0x000B4), `Abs (0x000B4); (0x000B8,0x000B8), `Abs (0x000B8); (0x002C2,0x002C5), `Delta (0); (0x002D2,0x002DF), `Delta (0); (0x002E5,0x002EB), `Delta (0); (0x002ED,0x002ED), `Abs (0x002ED); (0x002EF,0x002FF), `Delta (0); (0x00375,0x00375), `Abs (0x00375); (0x00384,0x00385), `Delta (0); (0x01FBD,0x01FBD), `Abs (0x01FBD); (0x01FBF,0x01FC1), `Delta (0); (0x01FCD,0x01FCF), `Delta (0); (0x01FDD,0x01FDF), `Delta (0); (0x01FED,0x01FEF), `Delta (0); (0x01FFD,0x01FFE), `Delta (0); (0x0309B,0x0309C), `Delta (0); (0x0A700,0x0A716), `Delta (0); (0x0A720,0x0A721), `Delta (0); (0x0A789,0x0A78A), `Delta (0); (0x0AB5B,0x0AB5B), `Abs (0x0AB5B); (0x0FBB2,0x0FBC1), `Delta (0); (0x0FF3E,0x0FF3E), `Abs (0x0FF3E); (0x0FF40,0x0FF40), `Abs (0x0FF40); (0x0FFE3,0x0FFE3), `Abs (0x0FFE3); (0x1F3FB,0x1F3FF), `Delta (0); (0x000A6,0x000A6), `Abs (0x000A6); (0x000A9,0x000A9), `Abs (0x000A9); (0x000AE,0x000AE), `Abs (0x000AE); (0x000B0,0x000B0), `Abs (0x000B0); (0x00482,0x00482), `Abs (0x00482); (0x0058D,0x0058E), `Delta (0); (0x0060E,0x0060F), `Delta (0); (0x006DE,0x006DE), `Abs (0x006DE); (0x006E9,0x006E9), `Abs (0x006E9); (0x006FD,0x006FE), `Delta (0); (0x007F6,0x007F6), `Abs (0x007F6); (0x009FA,0x009FA), `Abs (0x009FA); (0x00B70,0x00B70), `Abs (0x00B70); (0x00BF3,0x00BF8), `Delta (0); (0x00BFA,0x00BFA), `Abs (0x00BFA); (0x00C7F,0x00C7F), `Abs (0x00C7F); (0x00D4F,0x00D4F), `Abs (0x00D4F); (0x00D79,0x00D79), `Abs (0x00D79); (0x00F01,0x00F03), `Delta (0); (0x00F13,0x00F13), `Abs (0x00F13); (0x00F15,0x00F17), `Delta (0); (0x00F1A,0x00F1F), `Delta (0); (0x00F34,0x00F34), `Abs (0x00F34); (0x00F36,0x00F36), `Abs (0x00F36); (0x00F38,0x00F38), `Abs (0x00F38); (0x00FBE,0x00FC5), `Delta (0); (0x00FC7,0x00FCC), `Delta (0); (0x00FCE,0x00FCF), `Delta (0); (0x00FD5,0x00FD8), `Delta (0); (0x0109E,0x0109F), `Delta (0); (0x01390,0x01399), `Delta (0); (0x01940,0x01940), `Abs (0x01940); (0x019DE,0x019FF), `Delta (0); (0x01B61,0x01B6A), `Delta (0); (0x01B74,0x01B7C), `Delta (0); (0x02100,0x02101), `Delta (0); (0x02103,0x02106), `Delta (0); (0x02108,0x02109), `Delta (0); (0x02114,0x02114), `Abs (0x02114); (0x02116,0x02117), `Delta (0); (0x0211E,0x02123), `Delta (0); (0x02125,0x02125), `Abs (0x02125); (0x02127,0x02127), `Abs (0x02127); (0x02129,0x02129), `Abs (0x02129); (0x0212E,0x0212E), `Abs (0x0212E); (0x0213A,0x0213B), `Delta (0); (0x0214A,0x0214A), `Abs (0x0214A); (0x0214C,0x0214D), `Delta (0); (0x0214F,0x0214F), `Abs (0x0214F); (0x0218A,0x0218B), `Delta (0); (0x02195,0x02199), `Delta (0); (0x0219C,0x0219F), `Delta (0); (0x021A1,0x021A2), `Delta (0); (0x021A4,0x021A5), `Delta (0); (0x021A7,0x021AD), `Delta (0); (0x021AF,0x021CD), `Delta (0); (0x021D0,0x021D1), `Delta (0); (0x021D3,0x021D3), `Abs (0x021D3); (0x021D5,0x021F3), `Delta (0); (0x02300,0x02307), `Delta (0); (0x0230C,0x0231F), `Delta (0); (0x02322,0x02328), `Delta (0); (0x0232B,0x0237B), `Delta (0); (0x0237D,0x0239A), `Delta (0); (0x023B4,0x023DB), `Delta (0); (0x023E2,0x023FE), `Delta (0); (0x02400,0x02426), `Delta (0); (0x02440,0x0244A), `Delta (0); (0x0249C,0x024B5), `Delta (0); (0x024B6,0x024CF), `Delta (26); (0x024D0,0x024E9), `Delta (0); (0x02500,0x025B6), `Delta (0); (0x025B8,0x025C0), `Delta (0); (0x025C2,0x025F7), `Delta (0); (0x02600,0x0266E), `Delta (0); (0x02670,0x02767), `Delta (0); (0x02794,0x027BF), `Delta (0); (0x02800,0x028FF), `Delta (0); (0x02B00,0x02B2F), `Delta (0); (0x02B45,0x02B46), `Delta (0); (0x02B4D,0x02B73), `Delta (0); (0x02B76,0x02B95), `Delta (0); (0x02B98,0x02BB9), `Delta (0); (0x02BBD,0x02BC8), `Delta (0); (0x02BCA,0x02BD1), `Delta (0); (0x02BEC,0x02BEF), `Delta (0); (0x02CE5,0x02CEA), `Delta (0); (0x02E80,0x02E99), `Delta (0); (0x02E9B,0x02EF3), `Delta (0); (0x02F00,0x02FD5), `Delta (0); (0x02FF0,0x02FFB), `Delta (0); (0x03004,0x03004), `Abs (0x03004); (0x03012,0x03013), `Delta (0); (0x03020,0x03020), `Abs (0x03020); (0x03036,0x03037), `Delta (0); (0x0303E,0x0303F), `Delta (0); (0x03190,0x03191), `Delta (0); (0x03196,0x0319F), `Delta (0); (0x031C0,0x031E3), `Delta (0); (0x03200,0x0321E), `Delta (0); (0x0322A,0x03247), `Delta (0); (0x03250,0x03250), `Abs (0x03250); (0x03260,0x0327F), `Delta (0); (0x0328A,0x032B0), `Delta (0); (0x032C0,0x032FE), `Delta (0); (0x03300,0x033FF), `Delta (0); (0x04DC0,0x04DFF), `Delta (0); (0x0A490,0x0A4C6), `Delta (0); (0x0A828,0x0A82B), `Delta (0); (0x0A836,0x0A837), `Delta (0); (0x0A839,0x0A839), `Abs (0x0A839); (0x0AA77,0x0AA79), `Delta (0); (0x0FDFD,0x0FDFD), `Abs (0x0FDFD); (0x0FFE4,0x0FFE4), `Abs (0x0FFE4); (0x0FFE8,0x0FFE8), `Abs (0x0FFE8); (0x0FFED,0x0FFEE), `Delta (0); (0x0FFFC,0x0FFFD), `Delta (0); (0x10137,0x1013F), `Delta (0); (0x10179,0x10189), `Delta (0); (0x1018C,0x1018E), `Delta (0); (0x10190,0x1019B), `Delta (0); (0x101A0,0x101A0), `Abs (0x101A0); (0x101D0,0x101FC), `Delta (0); (0x10877,0x10878), `Delta (0); (0x10AC8,0x10AC8), `Abs (0x10AC8); (0x1173F,0x1173F), `Abs (0x1173F); (0x16B3C,0x16B3F), `Delta (0); (0x16B45,0x16B45), `Abs (0x16B45); (0x1BC9C,0x1BC9C), `Abs (0x1BC9C); (0x1D000,0x1D0F5), `Delta (0); (0x1D100,0x1D126), `Delta (0); (0x1D129,0x1D164), `Delta (0); (0x1D16A,0x1D16C), `Delta (0); (0x1D183,0x1D184), `Delta (0); (0x1D18C,0x1D1A9), `Delta (0); (0x1D1AE,0x1D1E8), `Delta (0); (0x1D200,0x1D241), `Delta (0); (0x1D245,0x1D245), `Abs (0x1D245); (0x1D300,0x1D356), `Delta (0); (0x1D800,0x1D9FF), `Delta (0); (0x1DA37,0x1DA3A), `Delta (0); (0x1DA6D,0x1DA74), `Delta (0); (0x1DA76,0x1DA83), `Delta (0); (0x1DA85,0x1DA86), `Delta (0); (0x1F000,0x1F02B), `Delta (0); (0x1F030,0x1F093), `Delta (0); (0x1F0A0,0x1F0AE), `Delta (0); (0x1F0B1,0x1F0BF), `Delta (0); (0x1F0C1,0x1F0CF), `Delta (0); (0x1F0D1,0x1F0F5), `Delta (0); (0x1F110,0x1F12E), `Delta (0); (0x1F130,0x1F16B), `Delta (0); (0x1F170,0x1F1AC), `Delta (0); (0x1F1E6,0x1F202), `Delta (0); (0x1F210,0x1F23B), `Delta (0); (0x1F240,0x1F248), `Delta (0); (0x1F250,0x1F251), `Delta (0); (0x1F300,0x1F3FA), `Delta (0); (0x1F400,0x1F6D2), `Delta (0); (0x1F6E0,0x1F6EC), `Delta (0); (0x1F6F0,0x1F6F6), `Delta (0); (0x1F700,0x1F773), `Delta (0); (0x1F780,0x1F7D4), `Delta (0); (0x1F800,0x1F80B), `Delta (0); (0x1F810,0x1F847), `Delta (0); (0x1F850,0x1F859), `Delta (0); (0x1F860,0x1F887), `Delta (0); (0x1F890,0x1F8AD), `Delta (0); (0x1F910,0x1F91E), `Delta (0); (0x1F920,0x1F927), `Delta (0); (0x1F930,0x1F930), `Abs (0x1F930); (0x1F933,0x1F93E), `Delta (0); (0x1F940,0x1F94B), `Delta (0); (0x1F950,0x1F95E), `Delta (0); (0x1F980,0x1F991), `Delta (0) ];; let gen_one na (data:(int*int) list) f = Printf.fprintf f "let %s : (int * int) list = Marshal.from_string %S 0\n\n" na (Marshal.to_string data []) let gen_lower (data:((int * int) * [> `Abs of int | `Delta of int ]) list) f = Printf.fprintf f "let to_lower : ((int * int) * [> `Abs of int | `Delta of int ]) list = Marshal.from_string %S 0" (Marshal.to_string data []) let gen () = let f = Sys.argv.(1) in let ch = open_out_bin f in gen_one "lu" lu ch; gen_one "ll" ll ch; gen_one "lt" lt ch; gen_one "mn" mn ch; gen_one "mc" mc ch; gen_one "me" me ch; gen_one "nd" nd ch; gen_one "nl" nl ch; gen_one "no" no ch; gen_one "zs" zs ch; gen_one "zl" zl ch; gen_one "zp" zp ch; gen_one "cc" cc ch; gen_one "cf" cf ch; gen_one "cs" cs ch; gen_one "co" co ch; gen_one "cn" cn ch; gen_one "lm" lm ch; gen_one "lo" lo ch; gen_one "pc" pc ch; gen_one "pd" pd ch; gen_one "ps" ps ch; gen_one "pe" pe ch; gen_one "pi" pi ch; gen_one "pf" pf ch; gen_one "po" po ch; gen_one "sm" sm ch; gen_one "sc" sc ch; gen_one "sk" sk ch; gen_one "so" so ch; gen_lower to_lower ch; close_out ch let () = gen () rocq-9.2.0/clib/unicodetable_gen.mli000066400000000000000000000000001516144147600173700ustar00rootroot00000000000000rocq-9.2.0/clib/unionfind.ml000066400000000000000000000073301516144147600157360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t (** Add (in place) an element in the partition, or do nothing if the element is already in the partition. *) val add : elt -> t -> unit (** Find the canonical representative of an element. Raise [not_found] if the element isn't known yet. *) val find : elt -> t -> elt (** Merge (in place) the equivalence classes of two elements. This will add the elements in the partition if necessary. *) val union : elt -> elt -> t -> unit (** Merge (in place) the equivalence classes of many elements. *) val union_set : set -> t -> unit (** Listing the different components of the partition *) val partition : t -> set list end module type SetS = sig type t type elt val singleton : elt -> t val union : t -> t -> t val choose : t -> elt val iter : (elt -> unit) -> t -> unit end module type MapS = sig type key type +'a t val empty : 'a t val find : key -> 'a t -> 'a val add : key -> 'a -> 'a t -> 'a t val mem : key -> 'a t -> bool val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b end module Make (S:SetS)(M:MapS with type key = S.elt) = struct type elt = S.elt type set = S.t type node = | Canon of set | Equiv of elt type t = node ref M.t ref let create () = ref (M.empty : node ref M.t) let fresh x p = let node = ref (Canon (S.singleton x)) in p := M.add x node !p; x, node let rec lookup x p = let node = M.find x !p in match !node with | Canon _ -> x, node | Equiv y -> let ((z,_) as res) = lookup y p in if not (z == y) then node := Equiv z; res let add x p = if not (M.mem x !p) then ignore (fresh x p) let find x p = fst (lookup x p) let canonical x p = try lookup x p with Not_found -> fresh x p let union x y p = let ((x,_) as xcan) = canonical x p in let ((y,_) as ycan) = canonical y p in if x = y then () else let xcan, ycan = if x < y then xcan, ycan else ycan, xcan in let x,xnode = xcan and y,ynode = ycan in match !xnode, !ynode with | Canon lx, Canon ly -> xnode := Canon (S.union lx ly); ynode := Equiv x; | _ -> assert false let union_set s p = try let x = S.choose s in S.iter (fun y -> union x y p) s with Not_found -> () let partition p = List.rev (M.fold (fun x node acc -> match !node with | Equiv _ -> acc | Canon lx -> lx::acc) !p []) end rocq-9.2.0/clib/unionfind.mli000066400000000000000000000050651516144147600161120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t (** Add (in place) an element in the partition, or do nothing if the element is already in the partition. *) val add : elt -> t -> unit (** Find the canonical representative of an element. Raise [not_found] if the element isn't known yet. *) val find : elt -> t -> elt (** Merge (in place) the equivalence classes of two elements. This will add the elements in the partition if necessary. *) val union : elt -> elt -> t -> unit (** Merge (in place) the equivalence classes of many elements. *) val union_set : set -> t -> unit (** Listing the different components of the partition *) val partition : t -> set list end module type SetS = sig type t type elt val singleton : elt -> t val union : t -> t -> t val choose : t -> elt val iter : (elt -> unit) -> t -> unit end (** Minimal interface for sets, subtype of stdlib's Set. *) module type MapS = sig type key type +'a t val empty : 'a t val find : key -> 'a t -> 'a val add : key -> 'a -> 'a t -> 'a t val mem : key -> 'a t -> bool val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b end (** Minimal interface for maps, subtype of stdlib's Map. *) module Make : functor (S:SetS) -> functor (_:MapS with type key = S.elt) -> PartitionSig with type elt = S.elt and type set = S.t rocq-9.2.0/clib/writeOnceArray.ml000066400000000000000000000037111516144147600167020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* a | None -> invalid_arg "Tried to reuse invalidated NoDupArray." (** Non-destructive get operator *) let (let+) r f = f (if_valid r) let destruct_get r = let+ a = r in r := None; a (** Destructive get operator *) let (let-) r f = f (destruct_get r) let update r f : 'b t = let- a = r in return (f a) (** Updating functor operator *) let (let*) = update let make n = return (Array.make n None) let get i a = let+ a = a in a.(i) let is_filled i a = let+ a = a in Option.has_some a.(i) let add i e a = let* a = a in begin match a.(i) with | None -> a.(i) <- Some e | Some _ -> invalid_arg "Tried to add duplicate in NoDupArray." end; a let fill_remaining e a = let* a = a in Array.iteri (fun i elt -> begin match elt with | None -> a.(i) <- Some e | Some _ -> () end) a; a let to_array a = let- a = a in Array.map (function Some e -> e | None -> invalid_arg "Tried to cast non-full NoDupArray.") a let to_array_opt a = let- a = a in let exception Stop in try Some (Array.map (function Some e -> e | None -> raise Stop) a) with Stop -> None module Internal = struct let unsafe_to_array = if_valid end rocq-9.2.0/clib/writeOnceArray.mli000066400000000000000000000022031516144147600170460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t val get : int -> 'a t -> 'a option val is_filled : int -> 'a t -> bool val add : int -> 'a -> 'a t -> 'a t val fill_remaining : 'a -> 'a t -> 'a t val to_array : 'a t -> 'a array val to_array_opt : 'a t -> 'a array option (** The NoDupArray is still invalidated if the result is None *) module Internal : sig val unsafe_to_array : 'a t -> 'a option array end rocq-9.2.0/config/000077500000000000000000000000001516144147600137445ustar00rootroot00000000000000rocq-9.2.0/config/coq_byte_config.mli000066400000000000000000000004011516144147600175740ustar00rootroot00000000000000(* Functions that should be used differently depending on the OCaml version *) val toploop_use_silently : Format.formatter -> string -> bool val compenv_handle_exit_with_status_0 : (unit -> unit) -> unit val toploop_prep_and_loop : Format.formatter -> unit rocq-9.2.0/config/coq_config.mli000066400000000000000000000060301516144147600165550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* =5.4), [Gc.ramp_up] dropping the [suspended_collection_work] data. Otherwise just call the given function. *) val gc_ramp_up : (unit -> 'a) -> 'a type relocatable_path = | NotRelocatable of string (* absolute path *) | Relocatable of string (* relative to the inferred prefix *) (* The fields below are absolute paths *) val install_prefix : relocatable_path (* Install prefix passed by the user *) val coqlib : relocatable_path (* where the std library is installed *) val configdir : relocatable_path (* where configuration files are installed *) val datadir : relocatable_path (* where extra data files are installed *) val docdir : relocatable_path (* where the doc is installed *) (* The fields below are paths relative to the installation prefix *) (* However, if an absolute path, it means discarding the actual prefix *) val coqlibsuffix : string (* std library relative to installation prefix *) val configdirsuffix : string (* config files relative to installation prefix *) val datadirsuffix : string (* data files relative to installation prefix *) val docdirsuffix : string (* doc directory relative to installation prefix *) (* used in envars (likely for coq_makefile) *) val ocamlfind : string (* used in envars for coq_makefile *) val caml_flags : string (* arguments passed to ocamlc (ie. CAMLFLAGS) *) (* Used in rocqide *) val arch : string (* architecture *) (* dubious use in envars, use in coqmakefile *) val arch_is_win32 : bool val version : string (* version number of Rocq *) val caml_version : string (* OCaml version used to compile Rocq *) val caml_version_nums : int list (* OCaml version used to compile Rocq by components *) val vo_version : int32 (* used in envars for coq_makefile *) val all_src_dirs : string list (* Used in micromega *) val exec_extension : string (* "" under Unix, ".exe" under MS-windows *) (* Used in rocqide *) val browser : string (** default web browser to use, may be overridden by environment variable COQREMOTEBROWSER *) (* used in coqdep *) val has_natdynlink : bool (* used in coqdoc *) val wwwcoq : string val wwwstdlib : string (* used in rocqide *) val wwwrefman : string (* for error reporting *) val wwwbugtracker : string val bytecode_compiler : bool type native_compiler = NativeOff | NativeOn of { ondemand : bool } val native_compiler : native_compiler rocq-9.2.0/config/dune000066400000000000000000000023321516144147600146220ustar00rootroot00000000000000(library (name config) (synopsis "Rocq Configuration Variables") (public_name rocq-runtime.config) (modules coq_config) (wrapped false)) (deprecated_library_name (old_public_name coq-core.config) (new_public_name rocq-runtime.config)) (library (name byte_config) (synopsis "Rocq Configuration Variables (for bytecode only)") (public_name rocq-runtime.config.byte) (modules coq_byte_config) (wrapped false) (libraries compiler-libs.toplevel) (modes byte)) (deprecated_library_name (old_public_name coq-core.config.byte) (new_public_name rocq-runtime.config.byte)) (executable (name list_plugins) (modules list_plugins)) (rule (targets plugin_list) (deps (source_tree %{project_root}/plugins)) (action (with-stdout-to %{targets} (chdir %{project_root} (run config/list_plugins.exe))))) ; add "-native-compiler yes" to the arguments of configure to enable native (rule (targets coq_config.ml coq_byte_config.ml coq_config.py dune.c_flags) (mode fallback) (deps %{project_root}/dev/ocamldebug-coq.run %{project_root}/dev/header.c ; Needed to generate include lists for coq_makefile plugin_list) (action (chdir %{project_root} (run %{project_root}/tools/configure/configure.exe -quiet -relocatable)))) rocq-9.2.0/config/list_plugins.ml000066400000000000000000000003511516144147600170110ustar00rootroot00000000000000let plugins = try Sys.readdir "plugins" with _ -> [||] let () = Array.sort compare plugins let () = Array.iter (fun f -> let f' = "plugins/"^f in if Sys.is_directory f' && f.[0] <> '.' then print_endline f) plugins rocq-9.2.0/config/list_plugins.mli000066400000000000000000000000001516144147600171510ustar00rootroot00000000000000rocq-9.2.0/configure000077500000000000000000000010071516144147600144040ustar00rootroot00000000000000#!/bin/sh ## This micro-configure shell script is here only to ## launch the real configuration via ocaml configure=./tools/configure/configure.exe ## Check that dune is available, provide an error message otherwise if ! command -v dune > /dev/null then 1>&2 echo "Dune could not be found, please ensure you have a working OCaml enviroment" exit 1 fi if [ "x$1" = 'x-release' ]; then shift 1 dune_release='--profile=release' else dune_release='' fi dune exec $dune_release --root . -- $configure "$@" rocq-9.2.0/coq-core.opam000066400000000000000000000033171516144147600150710ustar00rootroot00000000000000# This file is generated by dune, edit dune-project instead opam-version: "2.0" version: "dev" synopsis: "Compatibility binaries for Coq after the Rocq renaming" description: """ The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package includes compatibility binaries to call Rocq through previous Coq commands like coqc coqtop,...""" maintainer: [ "The Rocq development team " ] authors: ["The Rocq development team, INRIA, CNRS, and contributors"] license: "LGPL-2.1-only" homepage: "https://rocq-prover.org/" doc: "https://rocq-prover.org/docs/" bug-reports: "https://github.com/rocq-prover/rocq/issues" depends: [ "dune" {>= "3.8"} "rocq-runtime" {= version} "odoc" {with-doc} ] build: [ ["dune" "subst"] {dev} [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/rocq-prover/rocq.git" post-messages: [ "Coq has been renamed to The Rocq Prover, see https://rocq-prover.org/refman/changes.html#porting-to-the-rocq-prover for details. This package provides compatibility binaries to ease the transition to the new rocq binary." ] rocq-9.2.0/coq-core.opam.template000066400000000000000000000003701516144147600166770ustar00rootroot00000000000000post-messages: [ "Coq has been renamed to The Rocq Prover, see https://rocq-prover.org/refman/changes.html#porting-to-the-rocq-prover for details. This package provides compatibility binaries to ease the transition to the new rocq binary." ] rocq-9.2.0/coqide-server.opam000066400000000000000000000024341516144147600161300ustar00rootroot00000000000000# This file is generated by dune, edit dune-project instead opam-version: "2.0" version: "dev" synopsis: "The Rocq Prover, XML protocol server" description: """ The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. This package provides the `coqidetop` language server, an implementation of Rocq's [XML protocol](https://github.com/rocq-prover/rocq/blob/master/dev/doc/xml-protocol.md) which allows clients, such as RocqIDE, to interact with the Rocq Prover in a structured way.""" maintainer: [ "The Rocq development team " ] authors: ["The Rocq development team, INRIA, CNRS, and contributors"] license: "LGPL-2.1-only" homepage: "https://rocq-prover.org/" doc: "https://rocq-prover.org/docs/" bug-reports: "https://github.com/rocq-prover/rocq/issues" depends: [ "dune" {>= "3.8"} "rocq-runtime" {= version} "odoc" {with-doc} ] build: [ ["dune" "subst"] {dev} [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/rocq-prover/rocq.git" rocq-9.2.0/coqpp/000077500000000000000000000000001516144147600136215ustar00rootroot00000000000000rocq-9.2.0/coqpp/coqpp.ml000066400000000000000000000000741516144147600152760ustar00rootroot00000000000000let () = Coqpp_main.main (List.tl (Array.to_list Sys.argv)) rocq-9.2.0/coqpp/coqpp_ast.mli000066400000000000000000000075051516144147600163240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Coqpp_ast.loc val token : Lexing.lexbuf -> Coqpp_parse.token rocq-9.2.0/coqpp/coqpp_lex.mll000066400000000000000000000132271516144147600163260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Buffer.add_string ocaml_buf "{" | Extend -> ocaml_start_pos := lexeme_start_p lexbuf in incr num_braces let end_ocaml lexbuf = let () = decr num_braces in if !num_braces < 0 then lex_error lexbuf "Unexpected end of OCaml code" else if !num_braces = 0 then let s = Buffer.contents ocaml_buf in let () = Buffer.reset ocaml_buf in let loc = Some { Coqpp_ast.loc_start = !ocaml_start_pos; Coqpp_ast.loc_end = lexeme_end_p lexbuf } in Some (CODE { Coqpp_ast.code = s; loc }) else let () = Buffer.add_string ocaml_buf "}" in None } let letter = ['a'-'z' 'A'-'Z'] let letterlike = ['_' 'a'-'z' 'A'-'Z'] let alphanum = ['_' 'a'-'z' 'A'-'Z' '0'-'9' '\''] let ident = letterlike alphanum* let qualid = ident ('.' ident)* let space = [' ' '\t' '\r'] let number = [ '0'-'9' ] rule extend = parse | "(*" { start_comment (); comment lexbuf } | "{" { start_ocaml lexbuf; ocaml lexbuf } | "GRAMMAR" { GRAMMAR } | "VERNAC" { VERNAC } | "COMMAND" { COMMAND } | "TACTIC" { TACTIC } | "EXTEND" { EXTEND } | "DOC_GRAMMAR" { DOC_GRAMMAR } | "END" { END } | "DECLARE" { DECLARE } | "PLUGIN" { PLUGIN } | "DEPRECATED" { DEPRECATED } | "CLASSIFIED" { CLASSIFIED } | "STATE" { STATE } | "PRINTED" { PRINTED } | "TYPED" { TYPED } | "INTERPRETED" { INTERPRETED } | "GLOBALIZED" { GLOBALIZED } | "SUBSTITUTED" { SUBSTITUTED } | "ARGUMENT" { ARGUMENT } | "RAW_PRINTED" { RAW_PRINTED } | "GLOB_PRINTED" { GLOB_PRINTED } | "SYNTERP" { SYNTERP } | "BY" { BY } | "AS" { AS } (** Camlp5 specific keywords *) | "GLOBAL" { GLOBAL } | "TOP" { TOP } | "FIRST" { FIRST } | "LAST" { LAST } | "BEFORE" { BEFORE } | "AFTER" { AFTER } | "LEVEL" { LEVEL } | "LEFTA" { LEFTA } | "RIGHTA" { RIGHTA } | "NONA" { NONA } | "BOTHA" { BOTHA } | "IGNORE" { IGNORE } | "KEYWORDS" { KEYWORDS } (** Standard *) | ident { IDENT (Lexing.lexeme lexbuf) } | qualid { QUALID (Lexing.lexeme lexbuf) } | number { INT (int_of_string (Lexing.lexeme lexbuf)) } | space { extend lexbuf } | '\"' { string lexbuf } | '\n' { newline lexbuf; extend lexbuf } | "![" { BANGBRACKET } | "#[" { HASHBRACKET } | '[' { LBRACKET } | ']' { RBRACKET } | '|' { PIPE } | "->" { ARROW } | "=>" { FUN } | ',' { COMMA } | ':' { COLON } | ';' { SEMICOLON } | '(' { LPAREN } | ')' { RPAREN } | '=' { EQUAL } | '*' { STAR } | _ { lex_error lexbuf "syntax error" } | eof { EOF } and ocaml = parse | "{" { start_ocaml lexbuf; ocaml lexbuf } | "}" { match end_ocaml lexbuf with Some tk -> tk | None -> ocaml lexbuf } | '\n' { newline lexbuf; Buffer.add_char ocaml_buf '\n'; ocaml lexbuf } | '\"' { Buffer.add_char ocaml_buf '\"'; ocaml_string lexbuf } | (_ as c) { Buffer.add_char ocaml_buf c; ocaml lexbuf } | eof { lex_unexpected_eof lexbuf "OCaml code" } and comment = parse | "*)" { match end_comment lexbuf with Some _ -> extend lexbuf | None -> comment lexbuf } | "(*" { start_comment lexbuf; comment lexbuf } | '\n' { newline lexbuf; Buffer.add_char comment_buf '\n'; comment lexbuf } | (_ as c) { Buffer.add_char comment_buf c; comment lexbuf } | eof { lex_unexpected_eof lexbuf "comment" } and string = parse | '\"' { let s = Buffer.contents string_buf in let () = Buffer.reset string_buf in STRING s } | "\\\"" { Buffer.add_char string_buf '\"'; string lexbuf } | '\n' { newline lexbuf; Buffer.add_char string_buf '\n'; string lexbuf } | (_ as c) { Buffer.add_char string_buf c; string lexbuf } | eof { lex_unexpected_eof lexbuf "string" } and ocaml_string = parse | "\\\"" { Buffer.add_string ocaml_buf "\\\""; ocaml_string lexbuf } | '\"' { Buffer.add_char ocaml_buf '\"'; ocaml lexbuf } | (_ as c) { Buffer.add_char ocaml_buf c; ocaml_string lexbuf } | eof { lex_unexpected_eof lexbuf "OCaml string" } { let token lexbuf = match mode () with | OCaml -> ocaml lexbuf | Extend -> extend lexbuf } rocq-9.2.0/coqpp/coqpp_main.ml000066400000000000000000000664461516144147600163210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* %s" ("\n"^exit_code_str^"\n") let fix_exit_code ~filename str = let lines = String.split_on_char '\n' str in let lines = List.mapi (fun i l -> if String.equal l exit_code_str then asprintf "# %i \"%s\"" (i+2) filename else l) lines in String.concat "\n" lines let print_code fmt c = match c.loc with | None -> fprintf fmt "%s" c.code | Some loc -> (* Print the line location as a source annotation *) let loc = loc.loc_start in let padding = String.make (loc.pos_cnum - loc.pos_bol + 1) ' ' in let code_insert = asprintf "\n# %i \"%s\"\n%s%s" loc.pos_lnum loc.pos_fname padding c.code in fprintf fmt "@[@<0>%s@]" code_insert; exit_code fmt () module StringSet = Set.Make(String) let string_split s = let len = String.length s in let rec split n = try let pos = String.index_from s n '.' in let dir = String.sub s n (pos-n) in dir :: split (succ pos) with | Not_found -> [String.sub s n (len-n)] in if len == 0 then [] else split 0 (* Used to generate unique ids *) let file_name = ref "" (* We used to output __plugin_name = "bla" then refer to __plugin_name in generated code but this is not robust to eg DECLARE PLUGIN "bla" open G_ltac use the plugin name since g_ltac has no mli its __plugin_name will shadow the local one and wreak havoc *) let plugin_name = ref None let force_is_plugin ~what () = match !plugin_name with | Some (Some n) -> n | Some None | None -> fatal ("DECLARE PLUGIN required before "^what) let check_is_plugin ~what () = match !plugin_name with | Some b -> b | None -> fatal ("DECLARE PLUGIN required before "^what) let pp_opt_plugin_arg ~what () = match check_is_plugin ~what () with | Some name -> "(Some \""^name^"\")" | None -> "None" let ignore_kw = ref false let print_ignore_kw fmt () = let s = if !ignore_kw then "true" else "false" in Format.pp_print_string fmt s let print_list fmt pr l = let rec prl fmt = function | [] -> () | [x] -> fprintf fmt "%a" pr x | x :: l -> fprintf fmt "%a;@ %a" pr x prl l in fprintf fmt "@[[%a]@]" prl l let rec print_binders fmt = function | [] -> () | ExtTerminal _ :: rem -> print_binders fmt rem | ExtNonTerminal (_, TokNone) :: rem -> fprintf fmt "_@ %a" print_binders rem | ExtNonTerminal (_, TokName id) :: rem -> fprintf fmt "%s@ %a" id print_binders rem let rec print_symbol fmt = function | Ulist1 s -> fprintf fmt "@[Extend.TUlist1 (%a)@]" print_symbol s | Ulist1sep (s, sep) -> fprintf fmt "@[Extend.TUlist1sep (%a, \"%s\")@]" print_symbol s sep | Ulist0 s -> fprintf fmt "@[Extend.TUlist0 (%a)@]" print_symbol s | Ulist0sep (s, sep) -> fprintf fmt "@[Extend.TUlist0sep (%a, \"%s\")@]" print_symbol s sep | Uopt s -> fprintf fmt "@[Extend.TUopt (%a)@]" print_symbol s | Uentry e -> fprintf fmt "@[Extend.TUentry (Genarg.get_arg_tag wit_%s)@]" e | Uentryl (e, l) -> assert (e = "tactic"); fprintf fmt "@[Extend.TUentryl (Genarg.get_arg_tag wit_%s, %i)@]" e l let print_string fmt s = fprintf fmt "\"%s\"" s let print_opt fmt pr = function | None -> fprintf fmt "None" | Some x -> fprintf fmt "Some@ @[(%a)@]" pr x module GramExt : sig val print_extrule : Format.formatter -> (symb list * string option list * code) -> unit val print_ast : Format.formatter -> grammar_ext -> unit end = struct let is_uident s = match s.[0] with | 'A'..'Z' -> true | _ -> false let is_qualified = is_uident let get_local_entries ext = let global = StringSet.of_list ext.gramext_globals in let map e = e.gentry_name in let entries = List.map map ext.gramext_entries in let local = List.filter (fun e -> not (is_qualified e || StringSet.mem e global)) entries in let rec uniquize seen = function | [] -> [] | id :: rem -> let rem = uniquize (StringSet.add id seen) rem in if StringSet.mem id seen then rem else id :: rem in uniquize StringSet.empty local let print_local fmt ext = let locals = get_local_entries ext in match locals with | [] -> () | e :: locals -> let mk_e fmt e = fprintf fmt "Procq.Entry.make \"%s\"" e in let () = fprintf fmt "@[let %s =@ @[%a@]@]@ " e mk_e e in let iter e = fprintf fmt "@[and %s =@ @[%a@]@]@ " e mk_e e in let () = List.iter iter locals in fprintf fmt "in@ " let print_position fmt pos = match pos with | First -> fprintf fmt "Gramlib.Gramext.First" | Last -> fprintf fmt "Gramlib.Gramext.Last" | Before s -> fprintf fmt "Gramlib.Gramext.Before@ \"%s\"" s | After s -> fprintf fmt "Gramlib.Gramext.After@ \"%s\"" s let print_assoc fmt = function | LeftA -> fprintf fmt "Gramlib.Gramext.LeftA" | RightA -> fprintf fmt "Gramlib.Gramext.RightA" | NonA -> fprintf fmt "Gramlib.Gramext.NonA" | BothA -> fprintf fmt "Gramlib.Gramext.BothA" let is_token s = match string_split s with | [s] -> is_uident s | _ -> false let rec parse_tokens ?(in_anon=false) = let err_anon () = if in_anon then fatal (Printf.sprintf "'SELF' or 'NEXT' illegal in anonymous entry level") in function | [GSymbString s] -> SymbToken ("", Some s) | [GSymbQualid ("QUOTATION", None); GSymbString s] -> SymbToken ("QUOTATION", Some s) | [GSymbQualid ("SELF", None)] -> err_anon (); SymbSelf | [GSymbQualid ("NEXT", None)] -> err_anon (); SymbNext | [GSymbQualid ("LIST0", None); tkn] -> SymbList0 (parse_token ~in_anon tkn, None) | [GSymbQualid ("LIST1", None); tkn] -> SymbList1 (parse_token ~in_anon tkn, None) | [GSymbQualid ("LIST0", None); tkn; GSymbQualid ("SEP", None); tkn'] -> SymbList0 (parse_token ~in_anon tkn, Some (parse_token ~in_anon tkn')) | [GSymbQualid ("LIST1", None); tkn; GSymbQualid ("SEP", None); tkn'] -> SymbList1 (parse_token ~in_anon tkn, Some (parse_token ~in_anon tkn')) | [GSymbQualid ("OPT", None); tkn] -> SymbOpt (parse_token ~in_anon tkn) | [GSymbQualid (e, None)] when is_token e -> SymbToken (e, None) | [GSymbQualid (e, None); GSymbString s] when is_token e -> SymbToken (e, Some s) | [GSymbQualid (e, lvl)] when not (is_token e) -> SymbEntry (e, lvl) | [GSymbParen tkns] -> parse_tokens ~in_anon tkns | [GSymbProd prds] -> let map p = let map (pat, tkns) = (pat, parse_tokens ~in_anon:true tkns) in (List.map map p.gprod_symbs, p.gprod_body) in SymbRules (List.map map prds) | t -> let rec db_token = function | GSymbString s -> Printf.sprintf "\"%s\"" s | GSymbQualid (s, _) -> Printf.sprintf "%s" s | GSymbParen s -> Printf.sprintf "(%s)" (db_tokens s) | GSymbProd _ -> Printf.sprintf "[...]" and db_tokens tkns = let s = List.map db_token tkns in String.concat " " s in fatal (Printf.sprintf "Invalid token: %s" (db_tokens t)) and parse_token ~in_anon tkn = parse_tokens ~in_anon [tkn] let print_fun fmt (vars, body) = let vars = List.rev vars in let iter = function | None -> fprintf fmt "_@ " | Some id -> fprintf fmt "%s@ " id in let () = fprintf fmt "fun@ " in let () = List.iter iter vars in let () = fprintf fmt "loc ->@ @[%a@]" print_code body in () (** Meta-program instead of calling Tok.of_pattern here because otherwise violates value restriction *) let print_tok fmt = let print_pat fmt = print_opt fmt print_string in function | "", Some s -> fprintf fmt "Tok.PKEYWORD (%a)" print_string s | "IDENT", s -> fprintf fmt "Tok.PIDENT (%a)" print_pat s | "FIELD", s -> fprintf fmt "Tok.PFIELD (%a)" print_pat s | "NUMBER", None -> fprintf fmt "Tok.PNUMBER None" | "NUMBER", Some s -> fprintf fmt "Tok.PNUMBER (Some (Option.get (NumTok.Unsigned.parse_string %a)))" print_string s | "STRING", s -> fprintf fmt "Tok.PSTRING (%a)" print_pat s | "LEFTQMARK", None -> fprintf fmt "Tok.PLEFTQMARK" | "BULLET", s -> fprintf fmt "Tok.PBULLET (%a)" print_pat s | "QUOTATION", Some s -> fprintf fmt "Tok.PQUOTATION %a" print_string s | "EOI", None -> fprintf fmt "Tok.PEOI" | _ -> failwith "Tok.of_pattern: not a constructor" let rec print_prod fmt p = let (vars, tkns) = List.split p.gprod_symbs in let tkn = List.map parse_tokens tkns in print_extrule fmt (tkn, vars, p.gprod_body) and print_extrule fmt (tkn, vars, body) = let tkn = List.rev tkn in fprintf fmt "@[Procq.Production.make@ @[(%a)@]@ @[(%a)@]@]" (print_symbols ~norec:false) tkn print_fun (vars, body) and print_symbols ~norec fmt = function | [] -> fprintf fmt "Procq.Rule.stop" | tkn :: tkns -> let c = if norec then "Procq.Rule.next_norec" else "Procq.Rule.next" in fprintf fmt "@[%s@ (%a)@ (%a)@]" c (print_symbols ~norec) tkns print_symbol tkn and print_symbol fmt tkn = match tkn with | SymbToken (t, s) -> fprintf fmt "(Procq.Symbol.token (%a))" print_tok (t, s) | SymbEntry (e, None) -> fprintf fmt "(Procq.Symbol.nterm %s)" e | SymbEntry (e, Some l) -> fprintf fmt "(Procq.Symbol.nterml %s (%a))" e print_string l | SymbSelf -> fprintf fmt "Procq.Symbol.self" | SymbNext -> fprintf fmt "Procq.Symbol.next" | SymbList0 (s, None) -> fprintf fmt "(Procq.Symbol.list0 %a)" print_symbol s | SymbList0 (s, Some sep) -> fprintf fmt "(Procq.Symbol.list0sep (%a) (%a))" print_symbol s print_anonymized_symbol sep | SymbList1 (s, None) -> fprintf fmt "(Procq.Symbol.list1 (%a))" print_symbol s | SymbList1 (s, Some sep) -> fprintf fmt "(Procq.Symbol.list1sep (%a) (%a))" print_symbol s print_anonymized_symbol sep | SymbOpt s -> fprintf fmt "(Procq.Symbol.opt %a)" print_symbol s | SymbRules rules -> let pr fmt (r, body) = let (vars, tkn) = List.split r in let tkn = List.rev tkn in fprintf fmt "Procq.Rules.make @[(%a)@ (%a)@]" (print_symbols ~norec:true) tkn print_fun (vars, body) in let pr fmt rules = print_list fmt pr rules in fprintf fmt "(Procq.Symbol.rules %a)" pr (List.rev rules) | SymbQuote c -> fprintf fmt "(%s)" c and print_anonymized_symbol fmt tkn = match tkn with | SymbToken (t, s) -> fprintf fmt "(Procq.Symbol.tokens [Procq.TPattern (%a)])" print_tok (t, s) | _ -> print_symbol fmt (SymbRules [[None, tkn], mk_code "()"]) let print_rule fmt r = let pr_lvl fmt lvl = print_opt fmt print_string lvl in let pr_asc fmt asc = print_opt fmt print_assoc asc in let pr_prd fmt prd = print_list fmt print_prod prd in fprintf fmt "@[(%a,@ %a,@ %a)@]" pr_lvl r.grule_label pr_asc r.grule_assoc pr_prd (List.rev r.grule_prods) let gramext_count = ref 0 let gramext_plugin_uid name = let cnt = !gramext_count in incr gramext_count; " ~plugin_uid:(\""^name^"\", \""^(!file_name)^":"^string_of_int cnt^"\")" let grammar_extend fmt () = match check_is_plugin ~what:"GRAMMAR EXTEND" () with | Some name -> Format.fprintf fmt "Egramml.grammar_extend%s ~ignore_kw:%a" (gramext_plugin_uid name) print_ignore_kw () | None -> Format.fprintf fmt "Procq.grammar_extend ~ignore_kw:%a" print_ignore_kw () let print_entry fmt e = match e.gentry_rules with | GDataReuse (pos, r) -> let rules = List.rev r in let pr_pos fmt pos = print_opt fmt print_string pos in let pr_prd fmt prd = print_list fmt print_prod prd in fprintf fmt "let () =@ @[%a@ %s@ @[(Procq.Reuse (%a, %a))@]@]@ in@ " grammar_extend () e.gentry_name pr_pos pos pr_prd rules | GDataFresh (pos, rules) -> let print_rules fmt rules = print_list fmt print_rule rules in let pr_check fmt () = match pos with | None -> fprintf fmt "let () =@ @[assert@ (Procq.Entry.is_empty@ %s)@]@ in@\n" e.gentry_name | Some _ -> fprintf fmt "" in let pos = match pos with None -> First | Some pos -> pos in fprintf fmt "%alet () =@ @[%a@ %s@ @[(Procq.Fresh@ (%a, %a))@]@]@ in@ " pr_check () grammar_extend () e.gentry_name print_position pos print_rules rules let print_ast fmt ext = let () = fprintf fmt "@[<2>let _ =@ " in let () = fprintf fmt "@[%a@]" print_local ext in let () = List.iter (fun e -> print_entry fmt e) ext.gramext_entries in let () = fprintf fmt "()@]@\n" in () end module VernacExt : sig val print_ast : Format.formatter -> vernac_ext -> unit end = struct let print_rule_classifier fmt r = match r.vernac_class with | None -> fprintf fmt "None" | Some f -> let no_binder = function ExtTerminal _ -> true | ExtNonTerminal _ -> false in if List.for_all no_binder r.vernac_toks then fprintf fmt "Some @[(fun ~atts -> %a)@]" print_code f else fprintf fmt "Some @[(fun %a ~atts -> %a)@]" print_binders r.vernac_toks print_code f (* let print_atts fmt = function *) (* | None -> fprintf fmt "@[let () = Attributes.unsupported_attributes atts in@] " *) (* | Some atts -> *) (* let rec print_left fmt = function *) (* | [] -> assert false *) (* | [x,_] -> fprintf fmt "%s" x *) (* | (x,_) :: rem -> fprintf fmt "(%s, %a)" x print_left rem *) (* in *) (* let rec print_right fmt = function *) (* | [] -> assert false *) (* | [_,y] -> fprintf fmt "%s" y *) (* | (_,y) :: rem -> fprintf fmt "(%s ++ %a)" y print_right rem *) (* in *) (* let nota = match atts with [_] -> "" | _ -> "Attributes.Notations." in *) (* fprintf fmt "@[let %a = Attributes.parse %s(%a) atts in@] " *) (* print_left atts nota print_right atts *) let print_atts_left fmt = function | None -> fprintf fmt "()" | Some atts -> let rec aux fmt = function | [] -> assert false | [x,_] -> fprintf fmt "%s" x | (x,_) :: rem -> fprintf fmt "(%s, %a)" x aux rem in aux fmt atts let print_atts_right fmt = function | None -> fprintf fmt "(Attributes.unsupported_attributes atts)" | Some atts -> let rec aux fmt = function | [] -> assert false | [_,y] -> print_code fmt y | (_,y) :: rem -> fprintf fmt "(%a ++ %a)" print_code y aux rem in let nota = match atts with [_] -> "" | _ -> "Attributes.Notations." in fprintf fmt "(Attributes.parse %s%a atts)" nota aux atts let understand_state = function | "close_proof" -> "vtcloseproof", ["lemma"; "pm"] | "open_proof" -> "vtopenproof", [] | "proof" -> "vtmodifyproof", ["pstate"] | "proof_opt_query" -> "vtreadproofopt", ["pstate"] | "proof_query" -> "vtreadproof", ["pstate"] | "read_program" -> "vtreadprogram", ["pm"] | "program" -> "vtmodifyprogram", ["pm"] | "declare_program" -> "vtdeclareprogram", ["pm"] | "program_interactive" -> "vtopenproofprogram", ["pm"] | "opaque_access" -> "vtopaqueaccess", ["opaque_access"] | s -> fatal ("unsupported state specifier: " ^ s) let rec pr_named_arguments fmt = function | [] -> assert false | [s] -> fprintf fmt "~%s" s | s :: l -> fprintf fmt "~%s@ %a" s pr_named_arguments l let pr_begin_wrapper fmt = function | [] -> fprintf fmt "fun () ->" | args -> fprintf fmt "fun %a ->" pr_named_arguments args let pr_end_wrapper fmt = function | [] -> fprintf fmt "" | args -> fprintf fmt "@ %a" pr_named_arguments args let print_body_state state fmt r = let state = match r.vernac_state with Some _ as s -> s | None -> state in match state with | None -> fprintf fmt "Vernactypes.vtdefault (fun () -> %a)" print_code r.vernac_body | Some "CUSTOM" -> print_code fmt r.vernac_body | Some state -> let state, wrap = understand_state state in fprintf fmt "Vernactypes.%s (%a (%a)%a)" state pr_begin_wrapper wrap print_code r.vernac_body pr_end_wrapper wrap let print_body_fun state fmt r = match r.vernac_synterp with | None -> fprintf fmt "let coqpp_body %a%a =@ @[%a@] in@ " print_binders r.vernac_toks print_atts_left r.vernac_atts (print_body_state state) r | Some (id,pe) -> fprintf fmt "let coqpp_body %a%a =@ @[(let %s = %a in %a)@] in@ " print_binders r.vernac_toks print_atts_left r.vernac_atts id print_code pe (print_body_state state) r let print_body state fmt r = fprintf fmt "@[<2>(%a@[<2>fun %a?loc ~atts () ->@]@ @[<2>coqpp_body@ %a%a@])@]" (print_body_fun state) r print_binders r.vernac_toks print_binders r.vernac_toks print_atts_right r.vernac_atts let rec print_sig fmt = function | [] -> fprintf fmt "@[Vernacextend.TyNil@]" | ExtTerminal s :: rem -> fprintf fmt "@[Vernacextend.TyTerminal@ @[<1>(\"%s\",@ %a)@]@]" s print_sig rem | ExtNonTerminal (symb, _) :: rem -> fprintf fmt "@[Vernacextend.TyNonTerminal (%a,@ %a)@]" print_symbol symb print_sig rem let print_rule state fmt r = fprintf fmt "Vernacextend.TyML@ @[(%b,@ %a,@ %a,@ %a)@]" r.vernac_depr print_sig r.vernac_toks (print_body state) r print_rule_classifier r let print_rules state fmt rules = print_list fmt (fun fmt r -> fprintf fmt "(%a)" (print_rule state) r) rules let print_classifier fmt = function (* error could be interesting but would need to check that not all of the rules have a classifier, if we do that we could also check that at least 1 rule has no classifier when the block level classifier is specified *) | ClassifDefault -> fprintf fmt "" | ClassifName "QUERY" -> fprintf fmt "~classifier:(fun ~atts:_ _ -> Vernacextend.classify_as_query)" | ClassifName "SIDEFF" -> fprintf fmt "~classifier:(fun ~atts:_ _ -> Vernacextend.classify_as_sideeff)" | ClassifName s -> fatal (Printf.sprintf "Unknown classifier %s" s) | ClassifCode c -> fprintf fmt "~classifier:(fun ~atts -> %s)" c.code let print_entry fmt = function | None -> fprintf fmt "None" | Some e -> fprintf fmt "(Some (%s))" e.code let print_ast fmt ext = let pr fmt () = fprintf fmt "Vernacextend.static_vernac_extend ~plugin:%s ~command:\"%s\" %a ~ignore_kw:%a ?entry:%a %a" (pp_opt_plugin_arg ~what:"VERNAC EXTEND" ()) ext.vernacext_name print_classifier ext.vernacext_class print_ignore_kw () print_entry ext.vernacext_entry (print_rules ext.vernacext_state) ext.vernacext_rules in let () = fprintf fmt "let () = @[%a@]@\n" pr () in () end module TacticExt : sig val print_ast : Format.formatter -> tactic_ext -> unit end = struct let rec print_clause fmt = function | [] -> fprintf fmt "@[Tacentries.TyNil@]" | ExtTerminal s :: cl -> fprintf fmt "@[Tacentries.TyIdent (\"%s\", %a)@]" s print_clause cl | ExtNonTerminal (g, _) :: cl -> fprintf fmt "@[Tacentries.TyArg (%a, %a)@]" print_symbol g print_clause cl let print_rule fmt r = fprintf fmt "@[Tacentries.TyML (%a, @[(fun %aist@ -> %a)@])@]" print_clause r.tac_toks print_binders r.tac_toks print_code r.tac_body let print_rules fmt rules = print_list fmt (fun fmt r -> fprintf fmt "(%a)" print_rule r) rules let print_ast fmt ext = let deprecation fmt = function | None -> () | Some { code } -> fprintf fmt "~deprecation:(%s) " code in let pr fmt () = let level = match ext.tacext_level with None -> 0 | Some i -> i in let name = force_is_plugin ~what:"TACTIC EXTEND" () in fprintf fmt "Tacentries.tactic_extend \"%s\" \"%s\" ~level:%i %a%a" name ext.tacext_name level deprecation ext.tacext_deprecated print_rules ext.tacext_rules in let () = fprintf fmt "let () = @[%a@]\n" pr () in () end module VernacArgumentExt : sig val print_ast : Format.formatter -> vernac_argument_ext -> unit val print_rules : Format.formatter -> string * tactic_rule list -> unit end = struct let terminal s = let p = if s <> "" && s.[0] >= '0' && s.[0] <= '9' then "CLexer.terminal_number" else "CLexer.terminal" in let c = Printf.sprintf "Procq.Symbol.token (%s \"%s\")" p s in SymbQuote c let rec parse_symb self = function | Ulist1 s -> SymbList1 (parse_symb self s, None) | Ulist1sep (s, sep) -> SymbList1 (parse_symb self s, Some (terminal sep)) | Ulist0 s -> SymbList0 (parse_symb self s, None) | Ulist0sep (s, sep) -> SymbList0 (parse_symb self s, Some (terminal sep)) | Uopt s -> SymbOpt (parse_symb self s) | Uentry e -> if e = self then SymbSelf else SymbEntry (e, None) | Uentryl (e, l) -> assert (e = "tactic"); if l = 5 then SymbEntry ("Pltac.binder_tactic", None) else SymbEntry ("Pltac.ltac_expr", Some (string_of_int l)) let parse_token self = function | ExtTerminal s -> (terminal s, None) | ExtNonTerminal (e, TokNone) -> (parse_symb self e, None) | ExtNonTerminal (e, TokName s) -> (parse_symb self e, Some s) let parse_rule self r = let symbs = List.map (fun t -> parse_token self t) r.tac_toks in let symbs, vars = List.split symbs in (symbs, vars, r.tac_body) let print_rules fmt (name, rules) = (* Rules are reversed. *) let rules = List.rev rules in let rules = List.map (fun r -> parse_rule name r) rules in let pr fmt l = print_list fmt (fun fmt r -> fprintf fmt "(%a)" GramExt.print_extrule r) l in match rules with | [([SymbEntry (e, None)], [Some s], { code = c } )] when String.trim c = s -> (* This is a horrible hack to work around limitations of camlp5 regarding factorization of parsing rules. It allows to recognize rules of the form [ entry(x) ] -> [ x ] so as not to generate a proxy entry and reuse the same entry directly. *) fprintf fmt "@[Vernacextend.Arg_alias@ @[<2>(%s)@]@]" e | _ -> fprintf fmt "@[Vernacextend.Arg_rules@ %a@]" pr rules let print_printer fmt = function | None -> fprintf fmt "@[fun _ -> Pp.str \"missing printer\"@]" | Some f -> print_code fmt f let print_ast fmt arg = let name = arg.vernacargext_name in let pr fmt () = fprintf fmt "Vernacextend.vernac_argument_extend ~plugin:%s ~name:%a ~ignore_kw:%a@[<2>{@\n\ Vernacextend.arg_parsing =@ %a;@\n\ Vernacextend.arg_printer = fun env sigma ->@ %a;@\n}@]" (pp_opt_plugin_arg ~what:"VERNAC ARGUMENT EXTEND" ()) print_string name print_ignore_kw () print_rules (name, arg.vernacargext_rules) print_printer arg.vernacargext_printer in fprintf fmt "@[<2>let (wit_%s, %s) =@ @[%a@]@]@\nlet _ = (wit_%s, %s)@\n" name name pr () name name end module ArgumentExt : sig val print_ast : Format.formatter -> argument_ext -> unit end = struct let rec print_argtype fmt = function | ExtraArgType s -> fprintf fmt "Geninterp.val_tag (Genarg.topwit wit_%s)" s | PairArgType (arg1, arg2) -> fprintf fmt "Geninterp.Val.Pair (@[(%a)@], @[(%a)@])" print_argtype arg1 print_argtype arg2 | ListArgType arg -> fprintf fmt "Geninterp.Val.List @[(%a)@]" print_argtype arg | OptArgType arg -> fprintf fmt "Geninterp.Val.Opt @[(%a)@]" print_argtype arg let rec print_wit fmt = function | ExtraArgType s -> fprintf fmt "wit_%s" s | PairArgType (arg1, arg2) -> fprintf fmt "Genarg.PairArg (@[(%a)@], @[(%a)@])" print_wit arg1 print_wit arg2 | ListArgType arg -> fprintf fmt "Genarg.ListArg @[(%a)@]" print_wit arg | OptArgType arg -> fprintf fmt "Genarg.OptArg @[(%a)@]" print_wit arg let print_ast fmt arg = let name = arg.argext_name in let pr_tag fmt t = print_opt fmt print_argtype t in let intern fmt () = match arg.argext_glob, arg.argext_type with | Some f, (None | Some _) -> fprintf fmt "@[Tacentries.ArgInternFun ((fun f ist v -> (ist, f ist v)) (%a))@]" print_code f | None, Some t -> fprintf fmt "@[Tacentries.ArgInternWit (%a)@]" print_wit t | None, None -> fprintf fmt "@[Tacentries.ArgInternFun (fun ist v -> (ist, v))@]" in let subst fmt () = match arg.argext_subst, arg.argext_type with | Some f, (None | Some _) -> fprintf fmt "@[Tacentries.ArgSubstFun (%a)@]" print_code f | None, Some t -> fprintf fmt "@[Tacentries.ArgSubstWit (%a)@]" print_wit t | None, None -> fprintf fmt "@[Tacentries.ArgSubstFun (fun s v -> v)@]" in let interp fmt () = match arg.argext_interp, arg.argext_type with | Some (None, f), (None | Some _) -> fprintf fmt "@[Tacentries.ArgInterpSimple (%a)@]" print_code f | Some (Some kind, f), (None | Some _) -> fatal (Printf.sprintf "Unknown kind %s of interpretation function" kind) | None, Some t -> fprintf fmt "@[Tacentries.ArgInterpWit (%a)@]" print_wit t | None, None -> fprintf fmt "@[Tacentries.ArgInterpRet@]" in let default_printer = mk_code "fun _ _ _ _ -> Pp.str \"missing printer\"" in let rpr = match arg.argext_rprinter, arg.argext_tprinter with | Some f, (None | Some _) -> f | None, Some f -> f | None, None -> default_printer in let gpr = match arg.argext_gprinter, arg.argext_tprinter with | Some f, (None | Some _) -> f | None, Some f -> f | None, None -> default_printer in let tpr = match arg.argext_tprinter with | Some f -> f | None -> default_printer in let pr fmt () = fprintf fmt "Tacentries.argument_extend ~plugin:\"%s\" ~name:%a ~ignore_kw:%a@ @[{@\n\ Tacentries.arg_parsing =@ %a;@\n\ Tacentries.arg_tag = @[%a@];@\n\ Tacentries.arg_intern = @[%a@];@\n\ Tacentries.arg_subst = @[%a@];@\n\ Tacentries.arg_interp = @[%a@];@\n\ Tacentries.arg_printer = @[((fun env sigma -> %a), (fun env sigma -> %a), (fun env sigma -> %a))@];@\n}@]" (force_is_plugin ~what:"ARGUMENT EXTEND" ()) print_string name print_ignore_kw () VernacArgumentExt.print_rules (name, arg.argext_rules) pr_tag arg.argext_type intern () subst () interp () print_code rpr print_code gpr print_code tpr in fprintf fmt "@[<2>let (wit_%s, %s) =@ @[%a@]@]@\nlet _ = (wit_%s, %s)@\n" name name pr () name name end let declare_plugin fmt name = let () = match !plugin_name with | None -> plugin_name := Some name | Some _ -> fatal "Multiple DECLARE PLUGIN not allowed"; in () let pr_ast fmt = function | Code s -> fprintf fmt "%a@\n" print_code s | Comment s -> fprintf fmt "%s@\n" s | DeclarePlugin name -> declare_plugin fmt name | GramExt gram -> fprintf fmt "%a@\n" GramExt.print_ast gram | VernacExt vernac -> fprintf fmt "%a@\n" VernacExt.print_ast vernac | VernacArgumentExt arg -> fprintf fmt "%a@\n" VernacArgumentExt.print_ast arg | TacticExt tac -> fprintf fmt "%a@\n" TacticExt.print_ast tac | ArgumentExt arg -> fprintf fmt "%a@\n" ArgumentExt.print_ast arg | IgnoreKeywords -> ignore_kw := true let help () = Format.eprintf "Usage: rocq preprocess-mlg file.mlg@\n%!"; exit 1 let parse = function | ["-help"|"--help"] -> help() | [file] -> file | _ -> help () let output_name file = try Filename.chop_extension file ^ ".ml" with | Invalid_argument _ -> fatal "Input file must have an extension for coqpp [input.ext -> input.ml]" let main args = let file = parse args in let output = output_name file in let ast = parse_file file in let () = file_name := Filename.basename file in let iter fmt ast = Format.fprintf fmt "@[%a@]%!" pr_ast ast in let str = asprintf "%a" (fun fmt ast -> List.iter (iter fmt) ast) ast in let str = fix_exit_code ~filename:output str in let chan = open_out output in let () = output_string chan str in let () = close_out chan in exit 0 rocq-9.2.0/coqpp/coqpp_main.mli000066400000000000000000000000371516144147600164520ustar00rootroot00000000000000val main : string list -> unit rocq-9.2.0/coqpp/coqpp_parse.mly000066400000000000000000000242351516144147600166660ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* None | Some s -> ends s pat2 let without_sep k sep r = if sep <> "" then raise Parsing.Parse_error else k r let parse_user_entry s sep = let table = [ "ne_", "_list", without_sep (fun r -> Ulist1 r); "ne_", "_list_sep", (fun sep r -> Ulist1sep (r, sep)); "", "_list", without_sep (fun r -> Ulist0 r); "", "_list_sep", (fun sep r -> Ulist0sep (r, sep)); "", "_opt", without_sep (fun r -> Uopt r); ] in let rec parse s sep = function | [] -> let () = without_sep ignore sep () in begin match starts s "tactic" with | Some ("0"|"1"|"2"|"3"|"4"|"5" as s) -> Uentryl ("tactic", int_of_string s) | Some _ | None -> Uentry s end | (pat1, pat2, k) :: rem -> match between s pat1 pat2 with | None -> parse s sep rem | Some s -> let r = parse s "" table in k sep r in parse s sep table let rhs_loc n = { loc_start = Parsing.rhs_start_pos n; loc_end = Parsing.rhs_end_pos n } %} %token CODE %token COMMENT %token IDENT QUALID %token STRING %token INT %token VERNAC TACTIC GRAMMAR DOC_GRAMMAR EXTEND END DECLARE PLUGIN DEPRECATED ARGUMENT %token RAW_PRINTED GLOB_PRINTED %token SYNTERP COMMAND CLASSIFIED STATE PRINTED TYPED INTERPRETED GLOBALIZED SUBSTITUTED BY AS %token BANGBRACKET HASHBRACKET LBRACKET RBRACKET PIPE ARROW FUN COMMA EQUAL STAR %token LPAREN RPAREN COLON SEMICOLON %token GLOBAL TOP FIRST LAST BEFORE AFTER LEVEL LEFTA RIGHTA NONA BOTHA %token IGNORE KEYWORDS %token EOF %type file %start file %% file: | nodes EOF { $1 } ; nodes: | { [] } | node nodes { $1 :: $2 } ; node: | CODE { Code $1 } | COMMENT { Comment $1 } | IGNORE KEYWORDS { IgnoreKeywords } | declare_plugin { $1 } | grammar_extend { $1 } | vernac_extend { $1 } | tactic_extend { $1 } | argument_extend { $1 } | doc_gram { $1 } ; declare_plugin: | DECLARE PLUGIN STRING { DeclarePlugin (Some $3) } | DECLARE GLOBAL PLUGIN { DeclarePlugin None } ; grammar_extend: | GRAMMAR EXTEND qualid_or_ident globals gram_entries END { GramExt { gramext_name = $3; gramext_globals = $4; gramext_entries = $5 } } ; argument_extend: | ARGUMENT EXTEND IDENT typed_opt printed_opt interpreted_opt globalized_opt substituted_opt raw_printed_opt glob_printed_opt tactic_rules END { ArgumentExt { argext_name = $3; argext_rules = $11; argext_rprinter = $9; argext_gprinter = $10; argext_tprinter = $5; argext_interp = $6; argext_glob = $7; argext_subst = $8; argext_type = $4; } } | VERNAC ARGUMENT EXTEND IDENT printed_opt tactic_rules END { VernacArgumentExt { vernacargext_name = $4; vernacargext_printer = $5; vernacargext_rules = $6; } } ; printed_opt: | { None } | PRINTED BY CODE { Some $3 } ; raw_printed_opt: | { None } | RAW_PRINTED BY CODE { Some $3 } ; glob_printed_opt: | { None } | GLOB_PRINTED BY CODE { Some $3 } ; interpreted_modifier_opt: | { None } | LBRACKET IDENT RBRACKET { Some $2 } ; interpreted_opt: | { None } | INTERPRETED interpreted_modifier_opt BY CODE { Some ($2,$4) } ; globalized_opt: | { None } | GLOBALIZED BY CODE { Some $3 } ; substituted_opt: | { None } | SUBSTITUTED BY CODE { Some $3 } ; typed_opt: | { None } | TYPED AS argtype { Some $3 } ; argtype: | IDENT { ExtraArgType $1 } | argtype IDENT { match $2 with | "list" -> ListArgType $1 | "option" -> OptArgType $1 | _ -> raise Parsing.Parse_error } | LPAREN argtype STAR argtype RPAREN { PairArgType ($2, $4) } ; vernac_extend: | VERNAC vernac_entry EXTEND IDENT vernac_classifier vernac_state vernac_rules END { VernacExt { vernacext_name = $4; vernacext_entry = $2; vernacext_class = $5; vernacext_state = $6; vernacext_rules = $7; } } ; vernac_entry: | COMMAND { None } | CODE { Some $1 } ; vernac_classifier: | { ClassifDefault } | CLASSIFIED BY CODE { ClassifCode $3 } | CLASSIFIED AS IDENT { ClassifName $3 } ; vernac_state: | { None } | STATE IDENT { Some $2 } ; vernac_rules: | vernac_rule { [$1] } | vernac_rule vernac_rules { $1 :: $2 } ; vernac_rule: | PIPE vernac_attributes_opt rule_state LBRACKET ext_tokens RBRACKET rule_deprecation rule_classifier synterp_fun ARROW CODE { { vernac_atts = $2; vernac_state = $3; vernac_toks = $5; vernac_depr = $7; vernac_class= $8; vernac_synterp = $9; vernac_body = $11; } } ; rule_state: | { None } | BANGBRACKET IDENT RBRACKET { Some $2 } ; vernac_attributes_opt: | { None } | HASHBRACKET vernac_attributes RBRACKET { Some $2 } ; vernac_attributes: | vernac_attribute { [$1] } | vernac_attribute SEMICOLON { [$1] } | vernac_attribute SEMICOLON vernac_attributes { $1 :: $3 } ; vernac_attribute: | qualid_or_ident EQUAL qualid_or_ident { ($1, { code = $3; loc = Some (rhs_loc 3) }) } | qualid_or_ident { ($1, { code = $1; loc = Some (rhs_loc 1) }) } ; rule_deprecation: | { false } | DEPRECATED { true } ; rule_classifier: | { None } | FUN CODE { Some $2 } ; synterp_fun: | { None } | SYNTERP AS IDENT CODE { Some ($3,$4) } tactic_extend: | TACTIC EXTEND IDENT tactic_deprecated tactic_level tactic_rules END { TacticExt { tacext_name = $3; tacext_deprecated = $4; tacext_level = $5; tacext_rules = $6 } } ; tactic_deprecated: | { None } | DEPRECATED CODE { Some $2 } ; tactic_level: | { None } | LEVEL INT { Some $2 } ; tactic_rules: | { [] } | tactic_rule tactic_rules { $1 :: $2 } ; tactic_rule: | PIPE LBRACKET ext_tokens RBRACKET ARROW CODE { { tac_toks = $3; tac_body = $6 } } ; ext_tokens: | { [] } | ext_token ext_tokens { $1 :: $2 } ; ext_token: | STRING { ExtTerminal $1 } | IDENT { let e = parse_user_entry $1 "" in ExtNonTerminal (e, TokNone) } | IDENT LPAREN IDENT RPAREN { let e = parse_user_entry $1 "" in ExtNonTerminal (e, TokName $3) } | IDENT LPAREN IDENT COMMA STRING RPAREN { let e = parse_user_entry $1 $5 in ExtNonTerminal (e, TokName $3) } ; qualid_or_ident: | QUALID { $1 } | IDENT { $1 } ; globals: | { [] } | GLOBAL COLON idents SEMICOLON { $3 } ; idents: | { [] } | qualid_or_ident idents { $1 :: $2 } ; gram_entries: | { [] } | gram_entry gram_entries { $1 :: $2 } ; gram_entry: | qualid_or_ident COLON reuse LBRACKET LBRACKET rules_opt RBRACKET RBRACKET SEMICOLON { { gentry_name = $1; gentry_rules = GDataReuse ($3, $6); } } | qualid_or_ident COLON position_opt LBRACKET levels RBRACKET SEMICOLON { { gentry_name = $1; gentry_rules = GDataFresh ($3, $5); } } ; reuse: | TOP { None } | LEVEL STRING { Some $2 } ; position_opt: | { None } | position { Some $1 } ; position: | FIRST { First } | LAST { Last } | BEFORE STRING { Before $2 } | AFTER STRING { After $2 } ; string_opt: | { None } | STRING { Some $1 } ; assoc_opt: | { None } | assoc { Some $1 } ; assoc: | LEFTA { LeftA } | RIGHTA { RightA } | NONA { NonA } | BOTHA { BothA } ; levels: | level { [$1] } | level PIPE levels { $1 :: $3 } ; level: | string_opt assoc_opt LBRACKET rules_opt RBRACKET { { grule_label = $1; grule_assoc = $2; grule_prods = $4; } } ; rules_opt: | { [] } | rules { $1 } ; rules: | rule { [$1] } | rule PIPE rules { $1 :: $3 } ; rule: | symbols_opt ARROW CODE { { gprod_symbs = $1; gprod_body = $3; } } ; symbols_opt: | { [] } | symbols { $1 } ; symbols: | symbol { [$1] } | symbol SEMICOLON symbols { $1 :: $3 } ; symbol: | IDENT EQUAL gram_tokens { (Some $1, $3) } | gram_tokens { (None, $1) } ; gram_token: | qualid_or_ident { GSymbQualid ($1, None) } | qualid_or_ident LEVEL STRING { GSymbQualid ($1, Some $3) } | LPAREN gram_tokens RPAREN { GSymbParen $2 } | LBRACKET rules RBRACKET { GSymbProd $2 } | STRING { GSymbString $1 } ; gram_tokens: | gram_token { [$1] } | gram_token gram_tokens { $1 :: $2 } ; doc_gram: | DOC_GRAMMAR doc_gram_entries { GramExt { gramext_name = ""; gramext_globals=[]; gramext_entries = $2 } } doc_gram_entries: | { [] } | doc_gram_entry doc_gram_entries { $1 :: $2 } ; doc_gram_entry: | qualid_or_ident COLON LBRACKET PIPE doc_gram_rules RBRACKET { { gentry_name = $1; gentry_rules = GDataFresh (None, [{ grule_label = None; grule_assoc = None; grule_prods = $5; }]) } } | qualid_or_ident COLON LBRACKET RBRACKET { { gentry_name = $1; gentry_rules = GDataFresh (None, [{ grule_label = None; grule_assoc = None; grule_prods = []; }]) } } ; doc_gram_rules: | doc_gram_rule { [$1] } | doc_gram_rule PIPE doc_gram_rules { $1 :: $3 } ; /* hack: put the location in the dummy code data */ doc_gram_rule: | doc_gram_symbols_opt { { gprod_symbs = $1; gprod_body = { code = ""; loc = Some (rhs_loc 1) }; } } ; doc_gram_symbols_opt: | { [] } | doc_gram_symbols { $1 } | doc_gram_symbols SEMICOLON { $1 } ; doc_gram_symbols: | doc_gram_symbol { [$1] } | doc_gram_symbols SEMICOLON doc_gram_symbol { $1 @ [$3] } ; doc_gram_symbol: | IDENT EQUAL doc_gram_gram_tokens { (Some $1, $3) } | doc_gram_gram_tokens { (None, $1) } ; doc_gram_gram_tokens: | doc_gram_gram_token { [$1] } | doc_gram_gram_token doc_gram_gram_tokens { $1 :: $2 } ; doc_gram_gram_token: | qualid_or_ident { GSymbQualid ($1, None) } | LPAREN doc_gram_gram_tokens RPAREN { GSymbParen $2 } | LBRACKET doc_gram_rules RBRACKET { GSymbProd $2 } | STRING { GSymbString $1 } ; rocq-9.2.0/coqpp/coqpp_parser.ml000066400000000000000000000032171516144147600166540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let () = close_in chan in let () = Printf.eprintf "%s\n%!" (pr_loc loc) in fatal msg | Parsing.Parse_error -> let () = close_in chan in let loc = Coqpp_lex.loc lexbuf in let () = Printf.eprintf "%s\n%!" (pr_loc loc) in fatal "syntax error" in let () = close_in chan in ans rocq-9.2.0/coqpp/coqpp_parser.mli000066400000000000000000000014151516144147600170230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string val fatal : string -> unit val parse_file : string -> Coqpp_ast.t rocq-9.2.0/coqpp/dune000066400000000000000000000004371516144147600145030ustar00rootroot00000000000000(ocamllex coqpp_lex) (ocamlyacc coqpp_parse) (library (name coqpp) (wrapped false) (modules :standard \ coqpp) (modules_without_implementation coqpp_ast)) (executable (public_name coqpp) (empty_module_interface_if_absent) (package coq-core) (libraries coqpp) (modules coqpp)) rocq-9.2.0/default.nix000066400000000000000000000116431516144147600146500ustar00rootroot00000000000000# How to use? # If you have Nix installed, you can get in an environment with everything # needed to compile Rocq and RocqIDE by running: # $ nix-shell # at the root of the Rocq repository. # How to tweak default arguments? # nix-shell supports the --arg option (see Nix doc) that allows you for # instance to do this: # $ nix-shell --arg ocamlPackages "(import {}).ocaml-ng.ocamlPackages_4_14" --arg buildIde false # You can also compile Rocq and "install" it by running: # $ make clean # (only needed if you have left-over compilation files) # $ nix-build # at the root of the Rocq repository. # nix-build also supports the --arg option, so you will be able to do: # $ nix-build --arg doInstallCheck false # if you want to speed up things by not running the test-suite. # Once the build is finished, you will find, in the current directory, # a symlink to where Rocq was installed. { pkgs ? import ./dev/nixpkgs.nix {} , ocamlPackages ? pkgs.ocaml-ng.ocamlPackages_4_14 , buildIde ? true , buildDoc ? true , doInstallCheck ? true , shell ? false # We don't use lib.inNixShell because that would also apply # when in a nix-shell of some package depending on this one. , coq-version ? "8.14-git" }: with pkgs; with pkgs.lib; stdenv.mkDerivation rec { name = "coq"; buildInputs = [ hostname python311 ocamlPackages.yojson ocamlPackages.camlzip # coq-makefile timing tools time dune_3 ] ++ optionals buildIde [ ocamlPackages.lablgtk3-sourceview3 glib gnome.adwaita-icon-theme wrapGAppsHook ] ++ optionals buildDoc [ # Sphinx doc dependencies pkg-config (python311.withPackages (ps: [ ps.sphinx ps.sphinx_rtd_theme ps.pexpect ps.beautifulsoup4 (ps.antlr4-python3-runtime.override {antlr4 = pkgs.antlr4_9;}) ps.sphinxcontrib-bibtex ])) antlr4_9 ocamlPackages.odoc ] ++ optionals doInstallCheck [ # Test-suite dependencies ocamlPackages.ounit rsync which ] ++ optionals shell ( [ # Dependencies of the merging script jq curl gitFull gnupg ] ++ (with ocamlPackages; [ # Dev tools ocaml-lsp merlin ocp-indent ocp-index utop ocamlformat ]) ++ [ # Useful for STM debugging graphviz ] ); # OCaml and findlib are needed so that native_compute works # This follows a similar change in the nixpkgs repo (cf. NixOS/nixpkgs#101058) # ocamlfind looks for zarith when building plugins # This follows a similar change in the nixpkgs repo (cf. NixOS/nixpkgs#94230) propagatedBuildInputs = with ocamlPackages; [ ocaml findlib zarith ]; propagatedUserEnvPkgs = with ocamlPackages; [ ocaml findlib ]; src = if shell then null else with builtins; filterSource (path: _: !elem (baseNameOf path) [".git" "result" "bin" "_build" "_build_ci" "_build_vo" "nix"]) ./.; preConfigure = '' patchShebangs dev/tools/ doc/corelib ''; prefixKey = "-prefix "; enableParallelBuilding = true; buildFlags = [ "world" ] ++ optional buildIde "rocqide"; # TODO, building of documentation package when not in dev mode # https://github.com/rocq-prover/rocq/issues/16198 # buildFlags = [ "world" ] ++ optional buildDoc "refman-html"; # From https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/ocaml/dune.nix installPhase = '' runHook preInstall dune install --prefix $out --libdir $OCAMLFIND_DESTDIR rocq-runtime coq-core rocq-core coqide-server ${optionalString buildIde "rocqide"} runHook postInstall ''; # installTargets = # [ "install" ]; # fixme, do we have to do a target, or can we just do a copy? # ++ optional buildDoc "install-doc-html"; createFindlibDestdir = !shell; postInstall = "ln -s $out/lib/rocq-runtime $OCAMLFIND_DESTDIR/rocq-runtime && ln -s $out/lib/coq-core $OCAMLFIND_DESTDIR/coq-core"; inherit doInstallCheck; preInstallCheck = '' patchShebangs tools/ patchShebangs test-suite/ export OCAMLPATH=$OCAMLFIND_DESTDIR:$OCAMLPATH ''; installCheckTarget = [ "check" ]; passthru = { inherit coq-version ocamlPackages; dontFilter = true; # Useful to use mkCoqPackages from }; setupHook = writeText "setupHook.sh" " addCoqPath () { if test -d \"$1/lib/coq/${coq-version}/user-contrib\"; then export ROCQPATH=\"\${ROCQPATH-}\${ROCQPATH:+:}$1/lib/coq/${coq-version}/user-contrib/\" fi } addEnvHooks \"$targetOffset\" addCoqPath "; meta = { description = "Rocq Prover"; longDescription = '' The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. ''; homepage = https://rocq-prover.org; license = licenses.lgpl21; platforms = platforms.unix; }; } rocq-9.2.0/dev/000077500000000000000000000000001516144147600132555ustar00rootroot00000000000000rocq-9.2.0/dev/Bugzilla_Coq_autolink.user.js000066400000000000000000000011621516144147600210510ustar00rootroot00000000000000ο»Ώ// ==UserScript== // @name Bugzilla Coq autolink // @namespace CoqScript // @include https://coq.inria.fr/bugs/* // @description Makes #XXXX into links to Github Coq PRs // @version 1 // @grant none // ==/UserScript== var regex = /#(\d+)/g; var substr = '$&'; function doNode(node) { node.innerHTML = node.innerHTML.replace(regex,substr); } var comments = document.getElementsByClassName("bz_comment_table")[0]; var pars = comments.getElementsByClassName("bz_comment_text"); for(var j=0; j 1) { var range = document.createRange(); var start = content.search(regex); var end = start + matches[0].length; range.setStart(node, start); range.setEnd(node, end); var linkNode = document.createElement("a"); linkNode.href = "https://coq.inria.fr/bugs/show_bug.cgi?id=" + matches[1]; range.surroundContents(linkNode); //handle multiple matches in one text node doNode(linkNode.parentNode); } } } for(var i=0; i /dev/null > /dev/null; then : else echo echo "ERROR: num_of_iterations \"$num_of_iterations\" is not a positive integer." > /dev/stderr print_man_page_hint exit 1 fi bench_dirname="_bench" mkdir -p "${bench_dirname}" working_dir="$PWD/${bench_dirname}" log_dir=$working_dir/logs mkdir "$log_dir" export COQ_LOG_DIR=$log_dir echo "DEBUG: ocaml -version = $(ocaml -version)" echo "DEBUG: working_dir = $working_dir" echo "DEBUG: new_ocaml_switch = $new_ocaml_switch" echo "DEBUG: new_coq_repository = $new_coq_repository" echo "DEBUG: new_coq_commit = $new_coq_commit" echo "DEBUG: new_coq_opam_archive_git_uri = $new_coq_opam_archive_git_uri" echo "DEBUG: new_coq_opam_archive_git_branch = $new_coq_opam_archive_git_branch" echo "DEBUG: old_ocaml_switch = $old_ocaml_switch" echo "DEBUG: old_coq_repository = $old_coq_repository" echo "DEBUG: old_coq_commit = $old_coq_commit" echo "DEBUG: old_coq_opam_archive_git_uri = $old_coq_opam_archive_git_uri" echo "DEBUG: old_coq_opam_archive_git_branch = $old_coq_opam_archive_git_branch" echo "DEBUG: num_of_iterations = $num_of_iterations" echo "DEBUG: coq_opam_packages = $coq_opam_packages" echo "DEBUG: new_opam_override_urls = $new_opam_override_urls" echo "DEBUG: old_opam_override_urls = $old_opam_override_urls" echo "DEBUG: coq_pr_number = $coq_pr_number" echo "DEBUG: coq_pr_comment_id = $coq_pr_comment_id" echo "DEBUG: coq_native = $coq_native" # We put local binaries such as opam in .bin and extend PATH BIN=$(pwd)/.bin mkdir "$BIN" wget https://github.com/ocaml/opam/releases/download/2.3.0/opam-2.3.0-x86_64-linux -O "$BIN"/opam chmod +x "$BIN"/opam export OPAMSKIPUPDATE=1 # stop opam from messing with our pin edits # generate per file info in test suite and coq_makefile devs export TIMED=1 export PATH="$BIN":$PATH echo "Global env info:" echo "----------------" echo "pwd: $PWD" echo "path: $PATH" echo "opam version: `opam --version`" number_of_processors=$(cat /proc/cpuinfo | grep '^processor *' | wc -l) program_name="$0" program_path=$(readlink -f "${program_name%/*}") coqbot_url_prefix="https://coqbot.herokuapp.com/pendulum/" # -------------------------------------------------------------------------------- # Some sanity checks of command-line arguments provided by the user that can be done right now. if which perf > /dev/null; then echo -n else echo > /dev/stderr echo "ERROR: \"perf\" program is not available." > /dev/stderr echo > /dev/stderr exit 1 fi if which curl > /dev/null; then : else echo > /dev/stderr echo "ERROR: \"curl\" program is not available." > /dev/stderr echo > /dev/stderr exit 1 fi if which du > /dev/null; then : else echo > /dev/stderr echo "ERROR: \"du\" program is not available." > /dev/stderr echo > /dev/stderr exit 1 fi if [ ! -e "$working_dir" ]; then echo > /dev/stderr echo "ERROR: \"$working_dir\" does not exist." > /dev/stderr echo > /dev/stderr exit 1 fi if [ ! -d "$working_dir" ]; then echo > /dev/stderr echo "ERROR: \"$working_dir\" is not a directory." > /dev/stderr echo > /dev/stderr exit 1 fi if [ ! -w "$working_dir" ]; then echo > /dev/stderr echo "ERROR: \"$working_dir\" is not writable." > /dev/stderr echo > /dev/stderr exit 1 fi coq_opam_packages_on_separate_lines=$(echo "$coq_opam_packages" | sed 's/ /\n/g') if [ $(echo "$coq_opam_packages_on_separate_lines" | wc -l) != $(echo "$coq_opam_packages_on_separate_lines" | sort | uniq | wc -l) ]; then echo "ERROR: The provided set of OPAM packages contains duplicates." exit 1 fi # -------------------------------------------------------------------------------- # Tell coqbot to update the initial comment, if we know which one to update function coqbot_update_comment() { is_done="$1" comment_body="$2" uninstallable_packages="$3" if [ ! -z "${coq_pr_number}" ]; then comment_text="" artifact_text="" if [ -z "${is_done}" ]; then comment_text="in progress, " artifact_text="eventually " else comment_text="" artifact_text="" fi comment_text="Benchmarking ${comment_text}log available [here](${CI_JOB_URL}) ([raw log here](${CI_JOB_URL}/raw)), artifacts ${artifact_text}available for [download](${CI_JOB_URL}/artifacts/download) and [browsing](${CI_JOB_URL}/artifacts/browse)" if [ ! -z "${comment_body}" ]; then comment_text="${comment_text}${nl}${start_code_block}${nl}${comment_body}${nl}${end_code_block}" fi if [ ! -z "${uninstallable_packages}" ]; then comment_text="${comment_text}${nl}The following packages failed to install: ${uninstallable_packages}" fi comment_text="${comment_text}${nl}${nl}
Old Rocq version ${old_coq_commit}" comment_text="${comment_text}${nl}${nl}${start_code_block}${nl}$(git log -n 1 "${old_coq_commit}")${nl}${end_code_block}${nl}
" comment_text="${comment_text}${nl}${nl}
New Rocq version ${new_coq_commit}" comment_text="${comment_text}${nl}${nl}${start_code_block}${nl}$(git log -n 1 "${new_coq_commit}")${nl}${end_code_block}${nl}
" comment_text="${comment_text}${nl}${nl}[Diff: ${bt}${old_coq_commit}..${new_coq_commit}${bt}](https://github.com/rocq-prover/rocq/compare/${old_coq_commit}..${new_coq_commit})" # if there's a comment id, we update the comment while we're # in progress; otherwise, we wait until the end to post a new # comment if [ ! -z "${coq_pr_comment_id}" ]; then # Tell coqbot to update the in-progress comment curl -X POST --data-binary "${coq_pr_number}${nl}${coq_pr_comment_id}${nl}${comment_text}" "${coqbot_url_prefix}/update-comment" elif [ ! -z "${is_done}" ]; then # Tell coqbot to post a new comment that we're done benchmarking curl -X POST --data-binary "${coq_pr_number}${nl}${comment_text}" "${coqbot_url_prefix}/new-comment" fi if [ ! -z "${is_done}" ]; then # Tell coqbot to remove the `needs: benchmarking` label curl -X POST --data-binary "${coq_pr_number}" "${coqbot_url_prefix}/benchmarking-done" fi fi } # initial update to the comment, to say that we're in progress coqbot_update_comment "" "" "" # -------------------------------------------------------------------------------- zulip_post="" if [[ $ZULIP_BENCH_BOT ]]; then pr_full=$(git log -n 1 --pretty=%s) pr_full=${pr_full#"[CI merge] PR #"} pr_num=${pr_full%%:*} pr_msg=${pr_full#*:} zulip_header="Bench at $CI_JOB_URL Testing [$pr_msg](https://github.com/rocq-prover/rocq/pull/$pr_num) On packages $coq_opam_packages " # 24008 is the "github notifications" stream resp=$(curl -sSX POST https://rocq-prover.zulipchat.com/api/v1/messages \ -u "$ZULIP_BENCH_BOT" \ --data-urlencode type=stream \ --data-urlencode to='240008' \ --data-urlencode subject='Bench Notifications' \ --data-urlencode content="$zulip_header") zulip_post=$(echo "$resp" | jq .id) case "$zulip_post" in ''|*[!0-9]*) # not an int echo "Failed to post to zulip: $resp" zulip_post="" ;; esac fi zulip_edit() { if ! [[ $zulip_post ]]; then return; fi ending=$1 if [[ $rendered_results ]]; then msg="$zulip_header ~~~ $rendered_results ~~~ $ending " else msg="$zulip_header $ending " fi curl -sSX PATCH https://rocq-prover.zulipchat.com/api/v1/messages/"$zulip_post" \ -u "$ZULIP_BENCH_BOT" \ --data-urlencode content="$msg" >/dev/null || echo "Failed to edit zulip post" >&2 } zulip_autofail() { code=$? com=$BASH_COMMAND zulip_edit "Failed '$com' with exit code $code." } if [[ $zulip_post ]]; then trap zulip_autofail ERR; fi # see https://github.com/rocq-prover/rocq/pull/15807 if [ "$(ulimit -s)" != "unlimited" ]; then ulimit -S -s $((2 * $(ulimit -s))) fi # Clone the indicated git-repository. coq_dir="$working_dir/coq" git clone -q "$new_coq_repository" "$coq_dir" cd "$coq_dir" git remote rename origin new_coq_repository git remote add old_coq_repository "$old_coq_repository" git fetch -q "$old_coq_repository" git checkout -q $new_coq_commit coq_opam_version=dev # -------------------------------------------------------------------------------- new_opam_root="$working_dir/opam.NEW" old_opam_root="$working_dir/opam.OLD" # -------------------------------------------------------------------------------- old_coq_opam_archive_dir="$working_dir/old_coq_opam_archive" git clone -q --depth 1 -b "$old_coq_opam_archive_git_branch" "$old_coq_opam_archive_git_uri" "$old_coq_opam_archive_dir" new_coq_opam_archive_dir="$working_dir/new_coq_opam_archive" git clone -q --depth 1 -b "$new_coq_opam_archive_git_branch" "$new_coq_opam_archive_git_uri" "$new_coq_opam_archive_dir" initial_opam_packages="num zarith ocamlfind dune yojson camlzip" # Create an opam root and install Rocq # $1 = root_name {ex: NEW / OLD} # $2 = compiler name # $3 = git hash of Rocq to be installed # $4 = directory of coq opam archive # $5 = use flambda if nonempty create_opam() { local RUNNER="$1" local OPAM_DIR="$working_dir/opam.$RUNNER" local OCAML_VER="$2" local COQ_HASH="$3" local COQ_VER="$4" local OPAM_COQ_DIR="$5" local OPAM_OVERRIDE_URLS="$6" local USE_FLAMBDA="$7" local OPAM_COMP=ocaml-base-compiler.$OCAML_VER export OPAMROOT="$OPAM_DIR" export COQ_RUNNER="$RUNNER" opam init --disable-sandboxing -qn -j "$number_of_processors" --bare # Allow beta compiler switches opam repo add -q --set-default beta https://github.com/ocaml/ocaml-beta-repository.git # Allow experimental compiler switches opam repo add -q --set-default ocaml-pr https://github.com/ejgallego/ocaml-pr-repository.git # Rest of default switches opam repo add -q --set-default iris-dev "https://gitlab.mpi-sws.org/FP/opam-dev.git" if [[ $USE_FLAMBDA = 1 ]]; then flambda=--packages=ocaml-variants.${OCAML_VER}+options,ocaml-option-flambda else flambda= fi opam switch create -qy -j "$number_of_processors" "ocaml-$RUNNER" "$OPAM_COMP" $flambda eval $(opam env) if [ ! -z "$BENCH_DEBUG" ]; then opam config list; fi opam repo add -q --this-switch coq-core-dev "$OPAM_COQ_DIR/core-dev" # For rocq-stdlib opam repo add -q --this-switch coq-extra-dev "$OPAM_COQ_DIR/extra-dev" opam repo add -q --this-switch coq-released "$OPAM_COQ_DIR/released" local override_package local url_or_package for url_or_package in $OPAM_OVERRIDE_URLS; do if [ "$override_package" ]; then echo "Setting source url for $override_package to $url_or_package in $RUNNER" # NB opam editor start seems to ignore -y but works with > " opam pin add -nye "$override_package" - &2 echo "malformed opam_override_urls for $RUNNER (odd length)" zulip_edit "Bench failed: malformed opam_override_urls for $RUNNER (odd length)" exit 1 fi opam install -qy -j "$number_of_processors" $initial_opam_packages if [ ! -z "$BENCH_DEBUG" ]; then opam repo list; fi cd "$coq_dir" echo "$1_coq_commit = $COQ_HASH" echo "wrap-build-commands: [\"$program_path/wrapper.sh\"]" >> "$OPAM_DIR/config" git checkout -q $COQ_HASH COQ_HASH_LONG=$(git log --pretty=%H | head -n 1) echo "$1_coq_commit_long = $COQ_HASH_LONG" if [ ! -z "$coq_native" ]; then opam install coq-native rocq-native; fi } # Create an OPAM-root to which we will install the NEW version of Rocq. create_opam "NEW" "$new_ocaml_version" "$new_coq_commit" "$new_coq_version" \ "$new_coq_opam_archive_dir" "$new_opam_override_urls" "$new_ocaml_flambda" new_coq_commit_long="$COQ_HASH_LONG" # pre build needed helpers (needs an opam switch) dune build --root "$program_path/../.." -- dev/bench/render_results.exe dev/bench/render_line_results.exe rocq-devtools.install render_results=$(readlink -f "$program_path/../../_build/default/dev/bench/render_results.exe") render_line_results=$(readlink -f "$program_path/../../_build/default/dev/bench//render_line_results.exe") timelog2html=$(readlink -f "$program_path/../../_build/default/dev/bench/rocqtimelog2html.exe") # Create an OPAM-root to which we will install the OLD version of Rocq. create_opam "OLD" "$old_ocaml_version" "$old_coq_commit" "$old_coq_version" \ "$old_coq_opam_archive_dir" "$old_opam_override_urls" "$old_ocaml_flambda" old_coq_commit_long="$COQ_HASH_LONG" installable_coq_opam_packages="" zulip_edit "Opam setup, benching continues..." format_vosize() { old=$(stat -c%s $2) new=$(stat -c%s $3) diff=$((new - old)) diffpercent=$(((diff * 100) / $old)) echo "$1 $old $new $diff $diffpercent%" } # -------------------------------------------------------------------------------- # Measure the compilation times of the specified OPAM packages in both switches failed_packages= skipped_packages= # Generate per line timing info in devs that use coq_makefile export TIMING=1 export PROFILING=1 export ROCQ_PROFILE_COMPONENTS=command,parse_command,partac.perform # packages tied to the coq commit need to be pinned accordingly core_packages='rocq-runtime coq-core rocq-core coqide-server' for coq_opam_package in $core_packages $coq_opam_packages; do export COQ_OPAM_PACKAGE=$coq_opam_package is_core= for core in $core_packages; do if [ "$coq_opam_package" = "$core" ]; then is_core=1; fi done if [[ $is_core ]]; then : not getting info from opam repo else if [ ! -z "$BENCH_DEBUG" ]; then opam list opam show $coq_opam_package || { failed_packages="$failed_packages $coq_opam_package (unknown package)" continue } else # cause to skip with error if unknown package opam show $coq_opam_package >/dev/null || { failed_packages="$failed_packages $coq_opam_package (unknown package)" continue } fi fi echo "coq_opam_package = $coq_opam_package" for RUNNER in NEW OLD; do export COQ_RUNNER=$RUNNER # perform measurements for the NEW/OLD commit (provided by the user) if [ $RUNNER = "NEW" ]; then export OPAMROOT="$new_opam_root" COQ_HASH=$new_coq_commit_long echo "Testing NEW commit: $(date)" else export OPAMROOT="$old_opam_root" COQ_HASH=$old_coq_commit_long echo "Testing OLD commit: $(date)" fi git checkout -q $COQ_HASH if { [ "$coq_opam_package" = rocq-core ] || [ "$coq_opam_package" = rocq-runtime ]; } \ && ! [ -e $coq_opam_package.opam ]; then echo "Skipping $coq_opam_package for $RUNNER" continue 2 fi if [ -e "$coq_opam_package.opam" ]; then local_opam_dir=. elif [ -e "stdlib/$coq_opam_package.opam" ]; then local_opam_dir=stdlib else local_opam_dir= fi if [[ $local_opam_dir ]]; then opam pin add -ny "$coq_opam_package.dev" -k path $local_opam_dir fi eval $(opam env) # If a given OPAM-package was already installed (as a # dependency of some OPAM-package that we have benchmarked # before), remove it. opam uninstall -q $coq_opam_package >/dev/null 2>&1 # 'βˆ—' is a unicode star used by opam for packags to be installed for dep in $(opam install --show-actions "$coq_opam_package" | grep -o 'βˆ—\s*[^ ]*' | sed 's/βˆ—\s*//g'); do # show-actions will print transitive deps # so we don't need to look at the skipped_packages if echo "$failed_packages" | grep -q "^$dep "; then skipped_packages="$skipped_packages $coq_opam_package (dependency $dep failed)" continue 3 fi done opam install $coq_opam_package -v -b -j "$number_of_processors" --deps-only -y \ 3>$log_dir/$coq_opam_package.$RUNNER.opam_install.deps_only.stdout.log 1>&3 \ 4>$log_dir/$coq_opam_package.$RUNNER.opam_install.deps_only.stderr.log 2>&4 || { failed_packages="$failed_packages $coq_opam_package (dependency install failed in $RUNNER)" continue 2 } if [ ! -z "$BENCH_DEBUG" ]; then ls -l $working_dir; fi for iteration in $(seq $num_of_iterations); do export COQ_ITERATION=$iteration _RES=0 timeout "$timeout" opam install -y -v -b -j 1 $coq_opam_package \ 3>$log_dir/$coq_opam_package.$RUNNER.opam_install.$iteration.stdout.log 1>&3 \ 4>$log_dir/$coq_opam_package.$RUNNER.opam_install.$iteration.stderr.log 2>&4 || \ _RES=$? if [ $_RES = 0 ]; then echo $_RES > $log_dir/$coq_opam_package.$RUNNER.opam_install.$iteration.exit_status # "opam install" was successful. # Remove the benchmarked OPAM-package, unless this is the # very last iteration (we want to keep this OPAM-package # because other OPAM-packages we will benchmark later # might depend on it --- it would be a waste of time to # remove it now just to install it later) if [ $iteration != $num_of_iterations ]; then opam uninstall -q $coq_opam_package fi else # "opam install" failed. echo $_RES > $log_dir/$coq_opam_package.$RUNNER.opam_install.$iteration.exit_status failed_packages="$failed_packages $coq_opam_package (in $RUNNER)" continue 3 fi done # avoid opam downgrading rocq if some package has weird constraints # there is no "opam switch add-invariant" so we do this sed instead, # cf https://github.com/ocaml/opam/issues/6269 if [ "$coq_opam_package" = "rocq-runtime" ]; then opam switch set-invariant --formula \ "$(opam switch invariant | sed 's/]/ \"'"$coq_opam_package"'\"]/')" fi done case $coq_opam_package in coqide-server|coq) # don't render results for these ;; *) installable_coq_opam_packages="$installable_coq_opam_packages $coq_opam_package" esac # -------------------------------------------------------------- cat $log_dir/$coq_opam_package.$RUNNER.1.*.time || true cat $log_dir/$coq_opam_package.$RUNNER.1.*.perf || true # Print the intermediate results after we finish benchmarking each OPAM package if [ "$coq_opam_package" = "$(echo $coq_opam_packages | sed 's/ /\n/g' | tail -n 1)" ]; then # It does not make sense to print the intermediate results when # we finished bechmarking the very last OPAM package because the # next thing will do is that we will print the final results. # It would look lame to print the same table twice. : else echo "DEBUG: $render_results "$log_dir" $num_of_iterations 1 user_time_pdiff $installable_coq_opam_packages" rendered_results="$($render_results "$log_dir" $num_of_iterations 1 user_time_pdiff $installable_coq_opam_packages)" echo "${rendered_results}" # update the comment coqbot_update_comment "" "${rendered_results}" "" msg="Benching continues ($coq_opam_package done)..." if [ -n "$failed_packages" ]; then msg="$msg Failed: $failed_packages $skipped_packages" fi zulip_edit "$msg" fi # N.B. Not all packages end in .dev, e.g., coq-lambda-rust uses .dev.timestamp. # So we use a wildcard to catch such packages. coq_opam_package_nover=${coq_opam_package%%.*} new_base_path=$(echo "$new_opam_root/ocaml-NEW/.opam-switch/build/$coq_opam_package_nover".*/) old_base_path=$(echo "$old_opam_root/ocaml-OLD/.opam-switch/build/$coq_opam_package_nover".*/) # Generate per-file comparison for iteration in $(seq $num_of_iterations); do # opam logs prefix the printing with "- " so remove that # remove the base path for nicer printing and so the script can identify common files "$program_path"/../../tools/make-both-time-files.py --real \ <(sed -e 's/^- //' -e "s:$new_base_path::" "$log_dir/$coq_opam_package.NEW.opam_install.$iteration.stdout.log") \ <(sed -e 's/^- //' -e "s:$old_base_path::" "$log_dir/$coq_opam_package.OLD.opam_install.$iteration.stdout.log") \ > "$log_dir/$coq_opam_package.BOTH.perfile_timings.$iteration.log" done # Generate HTML report for LAST run for vo in $(cd $new_base_path/; find . -name '*.vo'); do if [ -e $old_base_path/$vo ]; then format_vosize "$coq_opam_package/$vo" "$old_base_path/$vo" "$new_base_path/$vo" >> "$log_dir/vosize.log" fi # use profile if it exists, otherwise timing # NB: timelog2html sometimes randomly fails old_data= new_data= if [ -e "$old_base_path/$vo.prof.json.gz" ]; then old_data="$old_base_path/$vo.prof.json.gz" elif [ -e "$old_base_path/${vo%%o}.timing" ]; then old_data="$old_base_path/${vo%%o}.timing" fi if [ -e "$new_base_path/$vo.prof.json.gz" ]; then new_data="$new_base_path/$vo.prof.json.gz" elif [ -e "$new_base_path/${vo%%o}.timing" ]; then new_data="$new_base_path/${vo%%o}.timing" fi if [ "$old_data" ] && [ "$new_data" ]; then mkdir -p "$working_dir/html/$coq_opam_package/$(dirname "$vo")/" $timelog2html \ "-o" "$working_dir/html/$coq_opam_package/${vo%%o}.html" \ "-raw-o" "$working_dir/html/$coq_opam_package/${vo%%o}.rocq-timediff" \ "$new_base_path/${vo%%o}" \ "$old_data" \ "$new_data" \ || echo "Failed (code $?): timelog2html for $vo on $old_data $new_data" fi done done # Since we do not upload all files, store a list of the files # available so that if we at some point want to tweak which files we # upload, we'll know which ones are available for upload du -ha "$working_dir" > "$working_dir/files.listing" # The following directories in $working_dir are no longer used: # # - coq, opam.OLD, opam.NEW # Measured data for each `$coq_opam_package`, `$iteration`, `status \in {NEW,OLD}`: # # - $working_dir/$coq_opam_package.$status.$iteration.time # => output of /usr/bin/time --format="%U" ... # # - $working_dir/$coq_opam_package.NEW.$iteration.perf # => output of perf stat -e instructions:u,cycles:u ... # # The next script processes all these files and prints results in a table. # Generate per-file comparison for everything at once new_base_path=$new_opam_root/ocaml-NEW/.opam-switch/build/ old_base_path=$old_opam_root/ocaml-OLD/.opam-switch/build/ for iteration in $(seq $num_of_iterations); do "$program_path"/../../tools/make-both-time-files.py --real \ <(sed -e 's/^- //' -e "s:$new_base_path::" "$log_dir/"*".NEW.opam_install.$iteration.stdout.log") \ <(sed -e 's/^- //' -e "s:$old_base_path::" "$log_dir/"*".OLD.opam_install.$iteration.stdout.log") \ > "$log_dir/ALL.BOTH.perfile_timings.$iteration.log" done # timings data timings=$working_dir/timings mkdir -p $timings # Print line by line slow downs and speed ups if [ -d "$working_dir/html" ]; then # might not exist if all jobs failed cd "$working_dir/html" $render_line_results # Move line timing files to timings folder (they will become artifacts) mv fast_table slow_table timings_table $timings # html tables don't get generated if the bench is run locally ie without CI variables for f in fast_table.html slow_table.html timings_table.html; do if [ -f "$f" ]; then mv "$f" $timings; fi done fi echo "INFO: workspace = ${CI_JOB_URL:-.}/artifacts/browse/${bench_dirname}" # Print the final results. if [ -z "$installable_coq_opam_packages" ]; then # Tell the user that none of the OPAM-package(s) the user provided # /are installable. printf "\n\nINFO: failed to install: $coq_opam_packages" coqbot_update_comment "done" "" "$coq_opam_packages" exit 1 fi echo "DEBUG: $render_results $log_dir $num_of_iterations 1 user_time_pdiff $installable_coq_opam_packages" rendered_results="$($render_results "$log_dir" $num_of_iterations 1 user_time_pdiff $installable_coq_opam_packages)" echo "${rendered_results}" echo "${rendered_results}" > $timings/bench_summary echo "INFO: per line timing: ${CI_JOB_URL:-.}/artifacts/browse/${bench_dirname}/html/" cd "$coq_dir" echo INFO: Old Rocq version git log -n 1 "$old_coq_commit" echo INFO: New Rocq version git log -n 1 "$new_coq_commit" if [ -n "$failed_packages" ]; then not_installable_coq_opam_packages=$failed_packages if [ -n "$skipped_packages" ]; then not_installable_coq_opam_packages="$not_installable_coq_opam_packages $skipped_packages" fi else # in case the failed package detection is bugged not_installable_coq_opam_packages=$(comm -23 <(echo $coq_opam_packages | sed 's/ /\n/g' | sort | uniq) <(echo $installable_coq_opam_packages | sed 's/ /\n/g' | sort | uniq) | sed 's/\t//g') fi coqbot_update_comment "done" "${rendered_results}" "${not_installable_coq_opam_packages}" touch $timings/bench_failures if [ -n "$not_installable_coq_opam_packages" ]; then # Tell the user that some of the provided OPAM-package(s) # is/are not installable. printf '\n\nINFO: failed to install %s\n' "$not_installable_coq_opam_packages" | tee $timings/bench_failures zulip_edit "Bench complete, failed to install packages: $not_installable_coq_opam_packages" exit 1 fi zulip_edit "Bench complete: all packages successfully installed." rocq-9.2.0/dev/bench/benchUtil.ml000066400000000000000000000041371516144147600166100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* exit 1) stderr fmt type char_loc = { start_char : int; stop_char : int; } type source_loc = { chars : char_loc; line : int; text : string; } let same_char_locs a b = a.start_char = b.start_char && a.stop_char = b.stop_char type measure = { str: string; q: Q.t; } let dummy_measure = { str="0"; q=Q.zero; } type memory = { major_words : string; minor_words : string; major_collect : int; minor_collect : int; } type data = { time : measure; memory : memory option; instructions : int option } let dummy_data = { time = dummy_measure; memory = None; instructions = None } let combine_related_data data = let nvals = Array.length (snd (data.(0))) in let fname0, data0 = data.(0) in let () = Array.iter (fun (fname, v) -> if nvals <> Array.length v then die "Mismatch between %s and %s: different measurement counts\n" fname0 fname) data in Array.init nvals (fun i -> let loc0, _ = data0.(i) in let data = data |> Array.map (fun (fname, fdata) -> let floc, v = fdata.(i) in if same_char_locs loc0 floc then v else die "Mismatch between %s and %s (measurement %d)\n" fname0 fname (i+1)) in loc0, data) let read_whole_file f = let sourcelen = (Unix.stat f).st_size in let ch = try open_in f with Sys_error e -> die "Could not open %s: %s" f e in let s = really_input_string ch sourcelen in close_in ch; s rocq-9.2.0/dev/bench/benchUtil.mli000066400000000000000000000026541516144147600167630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (char_loc * 'a array) array (** Combine data from multiple files about the same source, ensuring that the locations do not have inconsistencies. *) val read_whole_file : string -> string rocq-9.2.0/dev/bench/dune000066400000000000000000000011371516144147600152140ustar00rootroot00000000000000(library (name table) (modules table) (libraries clib)) (executable (name render_results) (modules render_results) (libraries unix table clib)) (executable (name render_line_results) (modules render_line_results) (libraries unix table str clib)) (library (name benchlib) (modules :standard \ render_results render_line_results rocqtimelog2html table) (libraries unix str clib zarith yojson camlzip)) (executable (name rocqtimelog2html) (modules rocqtimelog2html) (libraries benchlib)) (install (section libexec) (package rocq-devtools) (files (rocqtimelog2html.exe as timelog2html))) rocq-9.2.0/dev/bench/gitlab-bench.yml000066400000000000000000000011611516144147600173750ustar00rootroot00000000000000 bench: stage: build-0 needs: [] when: manual before_script: - printenv -0 | sort -z | tr '\0' '\n' script: dev/bench/bench.sh tags: - timing variables: GIT_DEPTH: "" artifacts: name: "$CI_JOB_NAME" paths: - _bench/html/**/*.v.html - _bench/logs - _bench/timings/* - _bench/files.listing - _bench/opam.NEW/**/*.log - _bench/opam.NEW/**/*.timing - _bench/opam.NEW/**/*.prof.json.gz - _bench/opam.OLD/**/*.log - _bench/opam.OLD/**/*.timing when: always expire_in: 1 year environment: bench interruptible: false timeout: 1d rocq-9.2.0/dev/bench/htmloutput.ml000066400000000000000000000126471516144147600171250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* exit 1) stderr (fmt^^"\n%!") let colors = [|"#F08080"; "#EEE8AA"; "#98FB98"|] let max_data_count = Array.length colors let htmlescape = let r = Str.regexp "[&<>\"]" in let subst s = match Str.matched_string s with | "&" -> "&" | "<" -> "<" | ">" -> ">" | "\"" -> """ | _ -> assert false in fun s -> Str.global_substitute r subst s let percentage ~max:m v = Q.to_float Q.(v * of_int 100 / m) let pp_words ~need_comma which w = if w = "0 w" then need_comma, "" else true, (if need_comma then ", " else "")^(String.sub w 0 (String.length w - 1))^which^" w" let pp_collect ~need_comma which c = if c = 0 then need_comma, "" else true, Printf.sprintf "%s%d %s %s" (if need_comma then ", " else "") c which (if c = 1 then "collection" else "collections") let pp_memory ch = function | None -> () | Some {major_words; minor_words; major_collect; minor_collect} -> (* need_comma <-> prefix is nontrivial *) let need_comma, minor_words = pp_words ~need_comma:false "minor" minor_words in let need_comma, major_words = pp_words ~need_comma "major" major_words in let need_comma, minor_collect = pp_collect ~need_comma "minor" minor_collect in let need_comma, major_collect = pp_collect ~need_comma "major" major_collect in if need_comma then Printf.fprintf ch " (%s%s%s%s)" minor_words major_words minor_collect major_collect let pp_instr ch = function | None -> () | Some i -> Printf.fprintf ch ", %d instr" i let output ch ~vname ~data_files all_data = let out fmt = Printf.fprintf ch fmt in let ndata = Array.length data_files in let totals = Array.fold_left (fun acc (_,data) -> Array.map2 (fun acc d -> Q.add acc d.time.q) acc data) (Array.make ndata Q.zero) all_data in let maxq = Array.fold_left (fun max (_,data) -> Array.fold_left (fun max d -> let dq = d.time.q in if Q.lt max dq then dq else max) max data) Q.zero all_data in let () = out {| %s |} in let () = out "

Timings for %s

\n" vname in let () = out "
    \n" in let () = data_files |> Array.iteri (fun i data_file -> out "
  1. %s (total time: %.3Gs)
  2. \n" colors.(i) data_file (Q.to_float totals.(i))) in let () = out "
\n" in let () = out "
" in

let last_seen_line = ref 0 in

let line_id fmt l =
  if l > !last_seen_line then begin
    last_seen_line := l;
    Printf.fprintf fmt "id=\"L%d\" " l
  end
in

let () = all_data |> Array.iteri (fun j (loc,data) ->
    let () = out {|
|} in let () = data |> Array.iteri (fun k d -> out {|
|} (k+1) (percentage d.time.q ~max:maxq)) in let text = loc.text in let text = if text <> "" && text.[0] = '\n' then String.sub text 1 (String.length text - 1) else text in let sublines = String.split_on_char '\n' text in let () = sublines |> List.iteri (fun i line -> let lnum = loc.line + i in out "%s\n" line_id lnum lnum (htmlescape line)) in let () = out "
" in ()) in let () = out {|
|} in () let raw_output ch ~min_diff all_data = all_data |> Array.iteri @@ fun j (loc,data) -> let d1, d2 = match data with | [|d1; d2|] -> d1, d2 | _ -> die "-raw-o only supports 2 data files, got %d" (Array.length data) in let diff = Q.(d2.time.q - d1.time.q) in let ignore = Q.lt (Q.abs diff) min_diff in if not ignore then begin let pdiff = if Q.(equal zero d1.time.q) then Float.infinity else Q.(to_float @@ ((of_int 100 * diff) / d1.time.q)) in (* XXX %.4f makes sense for min_diff=1e-4 but should be smarter for other min_diff *) Printf.fprintf ch "%s %s %.4f %3.2f%% %d\n" d1.time.str d2.time.str (Q.to_float diff) pdiff loc.line end rocq-9.2.0/dev/bench/htmloutput.mli000066400000000000000000000017541516144147600172730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* vname:string -> data_files:string array -> (BenchUtil.source_loc * BenchUtil.data array) array -> unit val max_data_count : int (** Max length supported for the inner [data array]. *) val raw_output : out_channel -> min_diff:Q.t -> (BenchUtil.source_loc * BenchUtil.data array) array -> unit rocq-9.2.0/dev/bench/plotter000077500000000000000000000103721516144147600157560ustar00rootroot00000000000000#!/usr/bin/env python3 import matplotlib.pyplot as plt import xdg import re import pycurl import certifi import os import sys from bs4 import BeautifulSoup from io import BytesIO # where we get the bench list from # sadly message edits don't appear in the public archive so we have to # download the gitlab raw logs too # (maybe we should be getting the messages from the zulip API instead??) archive = 'https://coq.gitlab.io/zulip-archive/stream/240008-GitHub-notifications/topic/Bench.20Notifications.html' print ('Getting bench list.') buffer = BytesIO() c = pycurl.Curl() c.setopt(c.URL, archive) c.setopt(c.WRITEFUNCTION, buffer.write) c.setopt(c.CAINFO, certifi.where()) c.perform() c.close() str = buffer.getvalue().decode('utf8') print ('Parsing bench list.') # parse HTML and remove tags # NB since coq was made default language on zulip the tables are full of tags # so we really don't want to keep them str = BeautifulSoup(str, "html.parser").text # NB: the line with the date starts with a space # (in the original there is the avatar broken image) datere = re.compile(' Bench bot \((.*)\):') jobre = re.compile('Bench at https://gitlab.com/coq/coq/-/jobs/(.*)$') benches=[] curdate=None for line in iter(str.splitlines()): match = re.match(datere, line) if match: # Next post curdate = match[1] else: match = re.match(jobre, line) if match: job = match[1] benches += [(curdate, match[1])] cachedir = xdg.xdg_cache_home() / "coq-bench-plotter" os.makedirs(cachedir, exist_ok=True) ## download job logs print ('Downloading job logs.') m = pycurl.CurlMulti() m.setopt(pycurl.M_MAX_HOST_CONNECTIONS, 8) files=[] for _, job in benches: fname = cachedir / (job + '.log') if not(os.path.exists(fname)): f = open(fname, 'xb') # x: will error if already exists files += [f] c = pycurl.Curl() c.setopt(c.URL, 'https://gitlab.com/coq/coq/-/jobs/' + job + '/raw') c.setopt(c.WRITEFUNCTION, f.write) c.setopt(c.CAINFO, certifi.where()) c.setopt(c.FOLLOWLOCATION, True) m.add_handle(c) num_handles = len(files) while num_handles: print (f'Downloading {num_handles} log files.') ret = m.select(5.0) if ret == -1: continue while 1: ret, num_handles = m.perform() if ret != pycurl.E_CALL_MULTI_PERFORM: break for f in files: f.flush() f.close() ## parse job logs print ('Parsing job logs.') # captures package name and OLD time # the numerals are to avoid matching the table header packre = re.compile('β”‚[ ]+([^ ]+) β”‚[ ]+[^ ]+[ ]+([0-9][^ ]*)[ ]+([^ ]+)') parsed=[] for date, job in benches: cur={} fname = cachedir / (job + '.log') with open(fname) as f: for l in f: match = re.match(packre, l) if match: # the table appears multiple times in the log so this may be overriding the value # that is OK (it's not worth bothering to find the last table) cur[match[1]] = (match[2], match[3]) if cur: parsed += [(date, job, cur)] def filter_to(packname): dates=[] jobs=[] times=[] changes=[] for date, job, packs in parsed: if packname in packs: dates += [date] jobs += [job] time, change = packs[packname] times += [float(time)] changes += [float(change)] return dates, jobs, times, changes def plot(packname): dates, jobs, times, changes = filter_to(packname) # alternatively you can use dates for x axis, times for y axis # with x = jobs, if you find an interesting point, hover the mouse on it # pyplot will say somewhere in the window "x=..., y=..." # now if you don't want to read and type the whole 10 digit number # export as svg and search for the last 3 digits followed by a space # it should be easy to find a xml comment with the job number eg "" plt.plot(jobs, changes) plt.ylabel(packname) plt.show() def list_packs(): known={} for _, _, packs in parsed: for pack in packs.keys(): if pack in known.keys(): known[pack] += 1 else: known[pack] = 1 return known plot(sys.argv[1]) rocq-9.2.0/dev/bench/profparser.ml000066400000000000000000000126421516144147600170560ustar00rootroot00000000000000(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* exit 1) stderr (fmt^^"\n%!") module YB = Yojson.Basic module YBU = YB.Util let assoc a b : YB.t = CList.assoc_f String.equal a b (* Profile files can be large, we want to parse 1 record at a time and only keep the info we're interested in (ie the "command" events). We use undocumented Yojson.Basic.read_comma to detect the end. *) let rec find_cmds acc (lstate,lex as ch) = let v = YB.from_lexbuf lstate ~stream:true lex in let fname = Option.get lstate.Yojson.fname in let lnum = lstate.Yojson.lnum in let is_last = try YB.read_comma lstate lex; false with Yojson.Json_error _ -> true in let acc = match v with | `Assoc l -> begin match assoc "name" l with | `String "command" -> (lnum,l) :: acc | _ -> acc end | _ -> die "File %S line %d: unrecognised value" fname lnum in if is_last then acc else find_cmds acc ch type 'ch channel = { open_in : string -> 'ch; close_in : 'ch -> unit; really_input : 'ch -> Bytes.t -> int -> int -> unit; input : 'ch -> Bytes.t -> int -> int -> int; } let file_channel = { open_in = open_in; close_in = close_in; really_input = really_input; input = input; } let gzip_channel = { open_in = Gzip.open_in; close_in = Gzip.close_in; really_input = Gzip.really_input; input = Gzip.input; } type any_channel = AnyChannel : 'ch channel -> any_channel let channel_for fname = if CString.is_suffix ".json" fname then AnyChannel file_channel else AnyChannel gzip_channel let input_exactly ch_fns ch expected = let buf = Bytes.create (String.length expected) in ch_fns.really_input ch buf 0 (String.length expected); assert (Bytes.to_string buf = expected) let read_file fname = let AnyChannel ch_fns = channel_for fname in let ch = ch_fns.open_in fname in try (* ignore initial line *) let () = input_exactly ch_fns ch {|{ "traceEvents": [|} in let lex = Lexing.from_function ~with_positions:false (fun buf n -> ch_fns.input ch buf 0 n) in let lstate = Yojson.init_lexer ~fname ~lnum:2 () in let cmds = find_cmds [] (lstate,lex) in ch_fns.close_in ch; cmds with e -> ch_fns.close_in ch; raise e open BenchUtil let force_string lnum = function | `String s -> s | _ -> die "line %d: malformed value (expected string)" lnum let get_ts (lnum, l) = match assoc "ts" l with | `Int ts -> ts | _ -> die "line %d: malformed ts" lnum let get_src_info (lnum, l) = match assoc "args" l with | `Assoc l -> let hdr = force_string lnum (assoc "cmd" l) in let line = match assoc "line" l with | `Int l -> l | `String l -> int_of_string l | _ -> die "line %d: malformed line number" lnum in hdr, line | _ -> die "line %d: malformed args" lnum let hdr_regex = Str.regexp {|^Chars \([0-9]+\) - \([0-9]+\) |} let get_src_chars ~lnum hdr = if not (Str.string_match hdr_regex hdr 0) then die "line %d: malformed command header" lnum else { start_char = int_of_string @@ Str.matched_group 1 hdr; stop_char = int_of_string @@ Str.matched_group 2 hdr; } let mk_memory (lnum, l) = let args = assoc "args" l in try Some { major_words = YBU.(to_string @@ member "major_words" args) ; minor_words = YBU.(to_string @@ member "minor_words" args); major_collect = YBU.(to_int @@ member "major_collect" args); minor_collect = YBU.(to_int @@ member "minor_collect" args); } with YBU.Type_error (msg,_) -> die "line %d: %s" lnum msg let mk_time start stop = let time = stop - start in (* time unit is microsecond *) let timeq = Q.(div (of_int time) (of_int 1000000)) in let timef = (float_of_int time) /. 1e6 in let str = (* 3 significant digits *) if timef > 100. then Printf.sprintf "%.0f" timef else if timef > 10. then Printf.sprintf "%.1f" timef else if timef > 1. then Printf.sprintf "%.2f" timef else if timef > 0.1 then Printf.sprintf "%.3f" timef else if timef > 0.01 then Printf.sprintf "%.4f" timef else if timef > 0.001 then Printf.sprintf "%.5f" timef else Printf.sprintf "%.6f" timef in { str; q = timeq; } let get_instr (lnum, l) = let args = assoc "args" l in YBU.(to_int @@ member "instr" args) let rec process_cmds acc = function | [] -> acc | end_event :: start_event :: rest -> let hdr, line = get_src_info start_event in let start_ts = get_ts start_event in let end_ts = get_ts end_event in let src_chars = get_src_chars ~lnum:(fst start_event) hdr in let time = mk_time start_ts end_ts in let memory = mk_memory end_event in let instructions = Some (get_instr end_event) in process_cmds ((src_chars, { time; memory; instructions; }) :: acc) rest | [_] -> die "ill parenthesized events" let parse ~file = let cmds = read_file file in let cmds = process_cmds [] cmds in cmds rocq-9.2.0/dev/bench/profparser.mli000066400000000000000000000013461516144147600172260ustar00rootroot00000000000000(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (char_loc * data) list rocq-9.2.0/dev/bench/render_line_results.ml000066400000000000000000000110561516144147600207400ustar00rootroot00000000000000 (** Recursively list .rocq-timediff files' relative directories in given directory *) let list_timediff_files dir = let rec loop result = function | f :: fs when Sys.is_directory f -> Sys.readdir f |> Array.to_list |> CList.map (Filename.concat f) |> CList.append fs |> loop result | f :: fs -> if Filename.check_suffix f ".rocq-timediff" then loop (f::result) fs else loop result fs | [] -> result in Sys.readdir dir |> Array.to_list |> loop [] type one_data = { time1 : string; time2 : string; diff : string; pdiff : string; lnum : string; file : string; } exception UnableToParse (** Read all the lines of a file into a list *) let read_timing_lines file = let ic = open_in file in let html_file = (Filename.chop_extension file) ^ ".html" in (* We tail recursively read lines in the file discarding the uninteresting ones *) let rec read_lines_aux acc = match input_line ic with | exception End_of_file -> acc | "" -> read_lines_aux acc | line -> match String.split_on_char ' ' line with | [time1; time2; diff; pdiff; lnum] -> {time1; time2; diff; pdiff; lnum; file=html_file} :: acc |> read_lines_aux | _ -> raise UnableToParse in let lines = try Some (read_lines_aux []) with End_of_file -> Printf.eprintf "*** Error: Could not read file %s.\n" file; None in close_in ic; lines type html_data = { link_prefix : string } let get_html_data () = match Sys.getenv_opt "CI_PAGES_DOMAIN", Sys.getenv_opt "CI_PROJECT_NAMESPACE", Sys.getenv_opt "CI_PROJECT_NAME", Sys.getenv_opt "CI_JOB_ID" with | Some domain, Some ns, Some project, Some id -> Some { link_prefix = Printf.sprintf "https://%s.%s/-/%s/-/jobs/%s/artifacts/_bench/html/" ns domain project id } | None, _, _, _ | _, None, _, _ | _, _, None, _ | _, _, _, None -> None let html_str ?html lnum s = match html with | None -> Table.raw_str s | Some html -> let size = String.length s in let s = Printf.sprintf "%s" html.link_prefix s lnum s in { Table.str = s; size } let list_timing_data ?html {time1; time2; diff; pdiff; lnum; file} = List.append (List.map Table.raw_str [ time1; time2; diff; pdiff; lnum]) [ html_str ?html lnum file ] let render_table ?(reverse=false) title num table = let open Table.Align in let headers = [Table.raw_str title] in let top = Table.raw_row [["OLD"; "NEW"; "DIFF"; "%DIFF"; "Ln"; "FILE"]] in let align_top = [[Middle; Middle; Middle; Middle; Middle; MidLeft]] in let align_rows = [[Right; Right; Right; Right; Right; Left]] in (if reverse then CList.rev table else table) |> CList.firstn num |> fun x -> Table.print headers top x ~align_top ~align_rows () let to_file fname fmt = Printf.kfprintf close_out (open_out fname) fmt let main () = let () = Printexc.record_backtrace true in let data = Unix.getcwd () |> list_timediff_files |> CList.filter_map read_timing_lines |> CList.flatten |> CList.sort (fun x y -> Float.compare (float_of_string x.diff) (float_of_string y.diff)) in let table = data |> CList.map list_timing_data |> CList.map (fun x -> [ x ]) in (* What is a good number to choose? *) let num = 25 in let num = min num (CList.length table) in let slow_table = render_table (Printf.sprintf "TOP %d SLOW DOWNS" num) ~reverse:true num table in let fast_table = render_table (Printf.sprintf "TOP %d SPEED UPS" num) num table in let timings_table = render_table "Significant line time changes in bench" (CList.length table) table in (* Print tables to stdout *) Printf.printf "%s\n%s\n" slow_table fast_table; (* Print tables to files *) to_file "slow_table" "%s\n" slow_table; to_file "fast_table" "%s\n" fast_table; to_file "timings_table" "%s\n" timings_table; (* html tables *) match get_html_data () with | None -> () | Some html -> let table = data |> CList.map (list_timing_data ~html) |> CList.map (fun x -> [ x ]) in let slow_table = render_table (Printf.sprintf "TOP %d SLOW DOWNS" num) ~reverse:true num table in let fast_table = render_table (Printf.sprintf "TOP %d SPEED UPS" num) num table in let timings_table = render_table "Significant line time changes in bench" (CList.length table) table in to_file "slow_table.html" "
%s
\n" slow_table; to_file "fast_table.html" "
%s
\n" fast_table; to_file "timings_table.html" "
%s
\n" timings_table; () let () = main () rocq-9.2.0/dev/bench/render_line_results.mli000066400000000000000000000000001516144147600210740ustar00rootroot00000000000000rocq-9.2.0/dev/bench/render_results.ml000077500000000000000000000204031516144147600177300ustar00rootroot00000000000000 (* ASSUMPTIONS: - the 1-st command line argument (working directory): - designates an existing readable directory - which contains *.time and *.perf files produced by bench.sh script - the 2-nd command line argument (number of iterations): - is a positive integer - the 3-rd command line argument (minimal user time): - is a positive floating point number - the 4-th command line argument determines the name of the column according to which the resulting table will be sorted. Valid values are: - package_name - user_time_pdiff - the rest of the command line-arguments - are names of benchamarked Coq OPAM packages for which bench.sh script generated *.time and *.perf files *) open Printf ;; let _ = Printexc.record_backtrace true ;; type ('a,'b) pkg_timings = { user_time : 'a; num_instr : 'b; num_mem : 'b; } ;; let reduce_pkg_timings (m_f : 'a list -> 'c) (m_a : 'b list -> 'd) (t : ('a,'b) pkg_timings list) : ('c,'d) pkg_timings = { user_time = m_f @@ CList.map (fun x -> x.user_time) t ; num_instr = m_a @@ CList.map (fun x -> x.num_instr) t ; num_mem = m_a @@ CList.map (fun x -> x.num_mem) t } ;; (******************************************************************************) (* BEGIN Copied from batteries, to remove *) (******************************************************************************) let run_and_read cmd = (* This code is before the open of BatInnerIO to avoid using batteries' wrapped IOs *) let string_of_file fn = let buff_size = 1024 in let buff = Buffer.create buff_size in let ic = open_in fn in let line_buff = Bytes.create buff_size in begin let was_read = ref (input ic line_buff 0 buff_size) in while !was_read <> 0 do Buffer.add_subbytes buff line_buff 0 !was_read; was_read := input ic line_buff 0 buff_size; done; close_in ic; end; Buffer.contents buff in let tmp_fn = Filename.temp_file "" "" in let cmd_to_run = cmd ^ " > " ^ tmp_fn in let status = Unix.system cmd_to_run in let output = string_of_file tmp_fn in Unix.unlink tmp_fn; (status, output) ;; let ( %> ) f g x = g (f x) let run = run_and_read %> snd module Float = struct let nan = nan end module CList = struct include CList let rec init_tailrec_aux acc i n f = if i >= n then acc else init_tailrec_aux (f i :: acc) (i+1) n f let rec init_aux i n f = if i >= n then [] else let r = f i in r :: init_aux (i+1) n f let rev_init_threshold = match Sys.backend_type with | Sys.Native | Sys.Bytecode -> 10_000 (* We don't known the size of the stack, better be safe and assume it's small. *) | Sys.Other _ -> 50 let init len f = if len < 0 then invalid_arg "CList.init" else if len > rev_init_threshold then rev (init_tailrec_aux [] 0 len f) else init_aux 0 len f let rec drop n = function | _ :: l when n > 0 -> drop (n-1) l | l -> l let reduce f = function | [] -> invalid_arg "CList.reduce: Empty CList" | h :: t -> fold_left f h t let min l = reduce Stdlib.min l end ;; module String = struct include String let rchop ?(n = 1) s = if n < 0 then invalid_arg "String.rchop: number of characters to chop is negative" else let slen = length s in if slen <= n then "" else sub s 0 (slen - n) end ;; (******************************************************************************) (* END Copied from batteries, to remove *) (******************************************************************************) let add_timings a b = { user_time = a.user_time +. b.user_time; num_instr = a.num_instr + b.num_instr; num_mem = a.num_mem + b.num_mem; } let mk_pkg_timings work_dir pkg_name suffix iteration = let command_prefix = "cat " ^ work_dir ^ "/" ^ pkg_name ^ suffix ^ string_of_int iteration in let ncoms = command_prefix ^ ".ncoms" |> run |> String.rchop ~n:1 |> int_of_string in let timings = CList.init ncoms (fun ncom -> let command_prefix = command_prefix ^ "." ^ string_of_int (ncom+1) in let time_command_output = command_prefix ^ ".time" |> run |> String.rchop ~n:1 |> String.split_on_char ' ' in let nth x i = CList.nth i x in { user_time = time_command_output |> nth 0 |> float_of_string (* Perf can indeed be not supported in some systems, so we must fail gracefully *) ; num_instr = (try command_prefix ^ ".perf | grep instructions:u | awk '{print $1}' | sed 's/,//g'" |> run |> String.rchop ~n:1 |> int_of_string with Failure _ -> 0) ; num_mem = time_command_output |> nth 1 |> int_of_string }) in match timings with | [] -> assert false | timing :: rest -> CList.fold_left add_timings timing rest ;; (* process command line paramters *) assert (Array.length Sys.argv > 5); let work_dir = Sys.argv.(1) in let num_of_iterations = int_of_string Sys.argv.(2) in let minimal_user_time = float_of_string Sys.argv.(3) in let sorting_column = Sys.argv.(4) in let coq_opam_packages = Sys.argv |> Array.to_list |> CList.drop 5 in (* ASSUMPTIONS: "working_dir" contains all the files produced by the following command: two_points_on_the_same_branch.sh $working_directory $coq_repository $coq_branch[:$new:$old] $num_of_iterations coq_opam_package_1 coq_opam_package_2 ... coq_opam_package_N -sf *) (* Run a given bash command; wait until it termines; check if its exit status is 0; return its whole stdout as a string. *) let proportional_difference_of_integers new_value old_value = if old_value = 0 then Float.nan else float_of_int (new_value - old_value) /. float_of_int old_value *. 100.0 in (* parse the *.time and *.perf files *) coq_opam_packages |> CList.map (fun package_name -> package_name,(* compilation_results_for_NEW : (float * int * int * int) list *) CList.init num_of_iterations succ |> CList.map (mk_pkg_timings work_dir package_name ".NEW."), CList.init num_of_iterations succ |> CList.map (mk_pkg_timings work_dir package_name ".OLD.")) (* from the list of measured values, select just the minimal ones *) |> CList.map (fun ((package_name : string), (new_measurements : (float, int) pkg_timings list), (old_measurements : (float, int) pkg_timings list)) -> let f_min : float list -> float = CList.min in let i_min : int list -> int = CList.min in package_name, reduce_pkg_timings f_min i_min new_measurements, reduce_pkg_timings f_min i_min old_measurements ) (* compute the "proportional differences in % of the NEW measurement and the OLD measurement" of all measured values *) |> CList.map (fun (package_name, new_t, old_t) -> package_name, new_t, old_t, { user_time = (new_t.user_time -. old_t.user_time) /. old_t.user_time *. 100.0 ; num_instr = proportional_difference_of_integers new_t.num_instr old_t.num_instr ; num_mem = proportional_difference_of_integers new_t.num_mem old_t.num_mem }) (* sort the table with results *) |> CList.sort (match sorting_column with | "user_time_pdiff" -> fun (_,_,_,perf1) (_,_,_,perf2) -> compare perf1.user_time perf2.user_time | "package_name" -> fun (n1,_,_,_) (n2,_,_,_) -> compare n1 n2 | _ -> assert false ) (* Keep only measurements that took at least "minimal_user_time" (in seconds). *) |> CList.filter (fun (_, new_t, old_t, _) -> minimal_user_time <= new_t.user_time || minimal_user_time <= old_t.user_time) (* Below we take the measurements and format them to stdout. *) |> CList.map begin fun (package_name, new_t, old_t, perc) -> let precision = 2 in let prf f = Printf.sprintf "%.*f" precision f in let pri n = Printf.sprintf "%d" n in [ [ package_name ]; [ prf new_t.user_time; prf old_t.user_time; prf perc.user_time ]; [ pri new_t.num_instr; pri old_t.num_instr; prf perc.num_instr ]; [ pri new_t.num_mem; pri old_t.num_mem; prf perc.num_mem ]; ] end |> fun measurements -> let headers = [ ""; "user time [s]"; "CPU instructions"; "max resident mem [KB]"; ] in let descr = ["NEW"; "OLD"; "PDIFF"] in let top = [ [ "package_name" ]; descr; descr; descr ] in printf "%s%!" (Table.raw_print headers top measurements ()) rocq-9.2.0/dev/bench/render_results.mli000066400000000000000000000000001516144147600200650ustar00rootroot00000000000000rocq-9.2.0/dev/bench/rocqtimelog2html.ml000066400000000000000000000013531516144147600201640ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* [] | [], deferred -> sort (List.rev deferred, []) | arg :: rest, deferred -> (* check if any remaining package reverse-depends on this one *) if List.exists (fun other_arg -> depends_on arg other_arg) rest then (* defer this package *) sort (rest, arg :: deferred) else (* emit this package, and then try again with any deferred packages *) arg :: sort (List.rev deferred @ rest, []) let main () = let args = Array.to_list Sys.argv in let pkgs = List.tl args in let sorted_pkgs = sort (pkgs, []) in Printf.printf "%s\n%!" (String.concat " " (List.map get_pkg_name sorted_pkgs)) let () = main () rocq-9.2.0/dev/bench/sort-by-deps.sh000077500000000000000000000011711516144147600172230ustar00rootroot00000000000000#!/usr/bin/env bash program_name="$0" program_path=$(readlink -f "${program_name%/*}") # We add || true (which may not be needed without set -e) to be # explicit about the fact that this script does not fail even if `opam # install --show-actions` does, e.g., because of a non-existent # package # # TODO: Figure out how to use the OPAM API # (https://opam.ocaml.org/doc/api/) to call this from OCaml. for i in "$@"; do echo -n "$i:"; ((echo -n "$(opam install --show-actions "$i" | grep -o 'βˆ—\s*install\s*[^ ]*' | sed 's/βˆ—\s*install\s*//g')" | tr '\n' ',') || true); echo done | xargs ocaml "${program_path}/sort-by-deps" rocq-9.2.0/dev/bench/sourcehandler.ml000066400000000000000000000054141516144147600175300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if c = '\n' then n+1 else n) 0 s let is_white_char = function ' '|'\n'|'\t' -> true | _ -> false let rec join_loop ~dummy ~source ~last_end ~lines acc = function | [] -> let sourcelen = String.length source in let acc = if last_end + 1 <= sourcelen then let text = source_substring source (last_end+1) sourcelen in if String.for_all is_white_char text then acc else ({ chars = { start_char = last_end+1; stop_char = sourcelen; }; line = lines+1; text}, dummy) :: acc else acc in List.rev acc | (loc,v) :: rest -> let acc, lines, last_end = if loc.start_char > last_end + 1 then let text = source_substring source (last_end + 1) (loc.start_char - 1) in (* if only spaces since last command, include them in the next command typically "Module Foo.\n Cmd." *) if not (String.for_all is_white_char text) then let n = count_newlines text in let acc = ({ chars = { start_char = last_end + 1; stop_char = loc.start_char - 1; }; line = lines; text }, dummy) :: acc in acc, (lines+n), loc.start_char - 1 else acc, lines, last_end else acc, lines, last_end in let text = source_substring source (last_end+1) loc.stop_char in let lines, n = if text <> "" && text.[0] = '\n' then lines+1, 1 else lines, 0 in let n = count_newlines text - n in let acc = ({ chars = { start_char = last_end + 1; stop_char = loc.stop_char; }; line = lines; text }, v) :: acc in join_loop ~dummy ~source ~last_end:loc.stop_char ~lines:(lines + n) acc rest let join_to_source ~dummy ~source vals = join_loop ~dummy ~source ~last_end:(-1) ~lines:1 [] vals rocq-9.2.0/dev/bench/sourcehandler.mli000066400000000000000000000020551516144147600176770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* source:string -> (char_loc * 'a) list -> (source_loc * 'a) list (** Given a list of values ordered by locations with no overlaps but maybe gaps, associate them to substrings of the source and fill in the gaps using [dummy]. When a gap is all whitespace in the source, it is merged to the next value (dropped if at the end). *) rocq-9.2.0/dev/bench/table.ml000066400000000000000000000127621516144147600157650ustar00rootroot00000000000000type sized_string = { str : string; size : int } let size s = s.size type header = sized_string type row = sized_string list list module Align = struct type t = | Left | MidLeft | Middle | MidRight | Right end let rec map3 f l1 l2 l3 = match (l1, l2, l3) with | ([], [], []) -> [] | (a1::l1, a2::l2, a3::l3) -> let r = f a1 a2 a3 in r :: map3 f l1 l2 l3 | (_, _, _) -> invalid_arg "Table.map3" let val_padding = 2 (* Padding between data in the same row *) let row_padding = 1 (* Padding between rows *) let homogeneous b = if b then () else failwith "Heterogeneous data" let vert_split (ls : 'a list list) = let split l = match l with | [] -> failwith "vert_split" | x :: l -> (x, l) in let ls = CList.map split ls in CList.split ls let justify align n s = let len = s.size in let s = s.str in let () = assert (len <= n) in let pad = n - len in match align with | Align.Left -> s ^ String.make pad ' ' | Align.Right -> String.make pad ' ' ^ s | Align.Middle -> let pad = pad / 2 in String.make pad ' ' ^ s ^ String.make (n - pad - len) ' ' | Align.MidLeft -> let pad = pad / 5 in String.make pad ' ' ^ s ^ String.make (n - pad - len) ' ' | Align.MidRight -> let pad = pad / 5 in String.make (n - pad - len) ' ' ^ s ^ String.make pad ' ' let justify_row align_row layout data = let data = map3 justify align_row layout data in { str = String.concat (String.make val_padding ' ') data; size = List.fold_left (+) (val_padding * (List.length data - 1)) layout; } let angle hkind vkind = match hkind, vkind with | `Lft, `Top -> "β”Œ" | `Rgt, `Top -> "┐" | `Mid, `Top -> "┬" | `Lft, `Mid -> "β”œ" | `Rgt, `Mid -> "─" | `Mid, `Mid -> "β”Ό" | `Lft, `Bot -> "β””" | `Rgt, `Bot -> "β”˜" | `Mid, `Bot -> "β”΄" let print_separator vkind col_size = let rec dashes n = if n = 0 then "" else "─" ^ dashes (n - 1) in let len = CList.length col_size in let pad = dashes row_padding in let () = assert (0 < len) in let map n = dashes n in angle `Lft vkind ^ pad ^ String.concat (pad ^ angle `Mid vkind ^ pad) (CList.map map col_size) ^ pad ^ angle `Rgt vkind let print_blank col_size = let len = CList.length col_size in let () = assert (0 < len) in let pad = String.make row_padding ' ' in let map n = String.make n ' ' in "β”‚" ^ pad ^ String.concat (pad ^ "β”‚" ^ pad) (CList.map map col_size) ^ pad ^ "β”‚" let print_row row = let len = CList.length row in let () = assert (0 < len) in let pad = String.make row_padding ' ' in "β”‚" ^ pad ^ String.concat (pad ^ "β”‚" ^ pad) row ^ pad ^ "β”‚" let default_align_headers = CList.map (fun _ -> Align.Middle) let default_align_top = CList.map @@ CList.map (fun _ -> Align.Middle) let default_align_rows rows = CList.hd rows |> CList.map @@ CList.map (fun _ -> Align.Right) (* Invariant : all rows must have the same shape *) let print (headers : header list) (top : row) (rows : row list) ?(align_headers = default_align_headers headers) ?(align_top = default_align_top top) ?(align_rows = default_align_rows rows) () = (* Sanitize input *) let ncolums = CList.length headers in let shape = ref None in let check row = let () = homogeneous (CList.length row = ncolums) in let rshape : int list = CList.map (fun data -> CList.length data) row in match !shape with | None -> shape := Some rshape | Some s -> homogeneous (rshape = s) in let () = CList.iter check rows in (* TODO: check is broken please fix *) (* let () = CList.iter check (CList.map (CList.map (fun _ -> [])) align_rows) in *) let () = homogeneous (CList.length align_headers = ncolums) in (* Compute layout *) let rec layout n (rows : row list) = if n = 0 then [] else let (col, rows) = vert_split rows in let ans = layout (n - 1) rows in let data = ref None in let iter args = let size = CList.map size args in match !data with | None -> data := Some size | Some s -> data := Some (CList.map2 (fun len1 len2 -> max len1 len2) s size) in let () = CList.iter iter col in let data = match !data with None -> [] | Some s -> s in data :: ans in let layout = layout ncolums (top::rows) in let map hd shape = let data_size = match shape with | [] -> 0 | n :: shape -> CList.fold_left (fun accu n -> accu + n + val_padding) n shape in max (size hd) data_size in let col_size = CList.map2 map headers layout in (* Justify the data *) let headers = map3 justify align_headers col_size headers in let top = CList.map2 (justify Align.Middle) col_size (map3 justify_row align_top layout top) in let rows = CList.map (fun row -> CList.map2 (justify Align.Right) col_size (map3 justify_row align_rows layout row)) rows in (* Print the table *) let lines = print_separator `Top col_size :: print_row headers :: print_blank col_size :: print_row top :: print_separator `Mid col_size :: CList.map print_row rows @ print_separator `Bot col_size :: [] in String.concat "\n" lines type raw_header = string type raw_row = string list list let raw_str s = { str = s; size = String.length s } let raw_row r : row = List.map (List.map raw_str) r let raw_print (headers : raw_header list) (top : raw_row) (rows : raw_row list) ?align_headers ?align_top ?align_rows () = let headers = List.map raw_str headers in let top = raw_row top in let rows = List.map raw_row rows in print headers top rows ?align_headers ?align_top ?align_rows () rocq-9.2.0/dev/bench/table.mli000066400000000000000000000025301516144147600161260ustar00rootroot00000000000000module Align : sig type t = | Left | MidLeft | Middle | MidRight | Right (** Type of Alignments. During the justification phase of printing, the alignment decides how much space should be left on the left and right of the data. *) end type sized_string = { str : string; size : int } (** String with a display size. [size] is usually but not always [String.length str] (or rather unicode length but currently no unicode support). *) type header = sized_string type row = sized_string list list (** Print the table with optional alignment parameters. The alignment parametrs must have the same shape as the corresponding data. Due to a limitation of OCaml, the entire thing has to be thunked in order for optional arguments to come at the end. *) val print : header list -> row -> row list -> ?align_headers:Align.t list -> ?align_top:Align.t list list -> ?align_rows:Align.t list list -> unit -> string type raw_header = string type raw_row = string list list val raw_str : string -> sized_string (** string which displays as itself *) val raw_row : raw_row -> row val raw_print : raw_header list -> raw_row -> raw_row list -> ?align_headers:Align.t list -> ?align_top:Align.t list list -> ?align_rows:Align.t list list -> unit -> string (** Print with display size = string length *) rocq-9.2.0/dev/bench/timelog2html.ml000066400000000000000000000072701516144147600173030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* exit 1) stderr (fmt^^"\n%!") let usage () = die "Usage: rocq timelog2html [options] VFILE DATAFILES\n\n%a\n%s" (fun fmt len -> Printf.fprintf fmt "1 to %d data files are supported." len) Htmloutput.max_data_count "Data files may be .json or .json.gz profile files (as produced by rocq c -profile),\ \nor timing files (as produced by rocq c -time-file).\ \n\ \nOptions:\ \n -o FILE: output to FILE (default is - meaning stdout)\ \n -raw-o FILE: output machine readable data to FILE (default off, - means stdout)\ \n (only supported with 2 data files)\ \n -min-diff DIFF: in -raw-o, only output lines with time diff greater than DIFF\ \n (DIFF in OCaml float format, default 1e-4)" let parse_files = function | [] | [_] -> usage () | vfile :: data_files -> let data_files = Array.of_list data_files in let () = if Array.length data_files > Htmloutput.max_data_count then usage () in vfile, data_files type output = Stdout | File of string type opts = { output : output; raw_output : output option; min_diff : Q.t; } let defaults = { output = Stdout; raw_output = None; min_diff = Q.(one / of_int 10_000); } let with_output f out = match out with | Stdout -> f stdout | File fname -> let ch = open_out fname in Fun.protect ~finally:(fun () -> close_out ch) (fun () -> f ch) let parse_output = function | "-" -> Stdout | f -> File f let parse_min_diff d = try Q.of_float @@ float_of_string d with Failure _ -> usage () let rec parse_args opts = function | "-o" :: f :: args -> parse_args { opts with output = parse_output f } args | "-raw-o" :: f :: args -> parse_args { opts with raw_output = Some (parse_output f) } args | "-min-diff" :: d :: args -> parse_args { opts with min_diff = parse_min_diff d } args | ["-o"|"-raw-o"|"-min-diff"] -> usage() | args -> opts, parse_files args let file_data data_file = if List.exists (fun suf -> CString.is_suffix suf data_file) [".json"; ".json.gz"] then let data = Profparser.parse ~file:data_file in data_file, CArray.of_list data else let data = Timelogparser.parse ~file:data_file in data_file, data |> CArray.map_of_list (fun (loc, time) -> loc, { BenchUtil.time; memory = None; instructions = None }) let main args = let opts, (vfile, data_files) = parse_args defaults args in let source = BenchUtil.read_whole_file vfile in let all_data = Array.map file_data data_files in let all_data = BenchUtil.combine_related_data all_data in let dummy = Array.make (Array.length data_files) BenchUtil.dummy_data in let all_data = Array.of_list (Sourcehandler.join_to_source ~dummy ~source (Array.to_list all_data)) in let vname = Filename.basename vfile in let () = opts.raw_output |> Option.iter @@ with_output @@ fun ch -> Htmloutput.raw_output ch ~min_diff:opts.min_diff all_data in let () = opts.output |> with_output @@ fun ch -> Htmloutput.output ch ~vname ~data_files all_data in () rocq-9.2.0/dev/bench/timelog2html.mli000066400000000000000000000013031516144147600174430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit rocq-9.2.0/dev/bench/timelogparser.ml000066400000000000000000000024771516144147600175550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* List.rev acc | l -> if not (Str.string_match time_regex l 0) then parse_loop filech acc else let b = int_of_string @@ Str.matched_group 1 l and e = int_of_string @@ Str.matched_group 2 l and t = Str.matched_group 3 l in let v = { start_char = b; stop_char = e; }, { str = t; q = Q.of_string t } in parse_loop filech (v :: acc) let parse ~file = let ch = open_in file in let v = parse_loop ch [] in close_in ch; v rocq-9.2.0/dev/bench/timelogparser.mli000066400000000000000000000013551516144147600177200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (BenchUtil.char_loc * BenchUtil.measure) list rocq-9.2.0/dev/bench/wrapper.sh000077500000000000000000000014241516144147600163540ustar00rootroot00000000000000#!/bin/sh log_dir=$COQ_LOG_DIR runner=$COQ_RUNNER package=$COQ_OPAM_PACKAGE iteration=$COQ_ITERATION echo "wrap[$package.$runner.$iteration|$OPAM_PACKAGE_NAME]" "$@" >> "$log_dir/wraplog.txt" echo >> "$log_dir/wraplog.txt" # we could be running commands for a dependency # NB $package may contain the version if [ "$package" ] && [ "$OPAM_PACKAGE_NAME" = "${package%%.*}" ] ; then prefix=$log_dir/$package.$runner.$iteration if [ -e "$prefix.ncoms" ]; then ncoms=$(cat "$prefix.ncoms") ncoms=$((ncoms+1)) else ncoms=1 fi echo $ncoms > "$prefix.ncoms" exec /usr/bin/time \ -o "$prefix.$ncoms.time" --format="%U %M %F" \ perf stat -e instructions:u,cycles:u -o "$prefix.$ncoms.perf" \ "$@" else exec "$@" fi rocq-9.2.0/dev/bugzilla2github_stripped.csv000066400000000000000000000116231516144147600210050ustar00rootroot000000000000002, 1156 3, 1157 4, 1158 7, 1160 8, 1161 10, 1163 12, 1164 13, 1165 14, 1169 16, 1171 17, 1184 18, 1190 19, 1191 20, 1193 21, 1200 23, 1201 24, 1203 25, 1208 26, 1210 27, 1212 28, 1216 30, 1217 31, 1223 34, 1227 35, 1232 36, 1235 38, 1238 39, 1244 40, 1245 41, 1246 42, 1247 44, 1248 45, 1249 46, 1250 47, 1252 48, 1253 49, 1254 50, 1256 52, 1262 54, 1263 55, 1264 56, 1265 59, 1266 60, 1267 61, 1268 63, 1270 64, 1272 65, 1274 66, 1275 69, 1276 70, 1279 71, 1283 72, 1284 73, 1285 74, 1286 75, 1287 78, 1288 79, 1291 80, 1292 82, 1293 83, 1295 84, 1296 85, 1297 86, 1299 88, 1301 89, 1303 90, 1304 91, 1305 92, 1307 93, 1308 94, 1310 95, 1312 96, 1313 97, 1314 98, 1316 99, 1318 100, 1319 101, 1320 102, 1321 103, 1323 105, 1324 106, 1327 107, 1328 108, 1330 109, 1334 112, 1335 115, 1336 119, 1337 121, 1341 123, 1342 124, 1343 125, 1344 126, 1345 127, 1346 128, 1348 129, 1349 134, 1350 135, 1351 136, 1352 137, 1353 138, 1354 139, 1355 140, 1356 142, 1357 143, 1358 144, 1359 145, 1360 147, 1361 148, 1362 149, 1363 150, 1365 152, 1366 154, 1368 155, 1369 160, 1370 161, 1371 162, 1372 164, 1373 165, 1374 166, 1376 167, 1377 169, 1378 170, 1380 178, 1382 179, 1383 180, 1384 181, 1385 182, 1386 183, 1387 184, 1390 185, 1391 186, 1392 187, 1393 189, 1394 190, 1398 191, 1401 192, 1402 194, 1403 195, 1404 196, 1405 197, 1407 198, 1409 199, 1410 202, 1412 204, 1413 205, 1421 207, 1422 209, 1423 210, 1426 212, 1427 213, 1428 214, 1429 215, 1433 216, 1435 219, 1436 220, 1437 221, 1440 222, 1444 224, 1445 225, 1450 228, 1452 229, 1453 235, 1457 236, 1458 238, 1459 239, 1460 240, 1462 242, 1465 243, 1466 244, 1470 245, 1471 248, 1472 250, 1473 253, 1474 254, 1475 259, 1476 261, 1478 262, 1479 263, 1480 264, 1481 265, 1484 266, 1485 267, 1486 268, 1488 269, 1489 270, 1490 271, 1492 272, 1493 273, 1494 274, 1498 275, 1500 277, 1503 278, 1504 279, 1505 282, 1506 283, 1511 289, 1513 290, 1514 291, 1516 292, 1517 294, 1520 295, 1521 299, 1523 301, 1524 302, 1525 303, 1527 305, 1529 311, 1530 315, 1531 316, 1532 317, 1534 320, 1535 322, 1539 324, 1541 328, 1542 329, 1543 330, 1544 331, 1545 333, 1546 335, 1547 336, 1548 338, 1549 343, 1550 348, 1551 350, 1552 351, 1553 352, 1554 353, 1555 356, 1556 363, 1557 368, 1558 371, 1559 372, 1560 413, 1561 418, 1562 420, 1563 426, 1564 431, 1565 444, 1566 447, 1567 452, 1569 459, 1570 462, 1571 463, 1573 468, 1574 472, 1575 473, 1577 509, 1578 519, 1579 529, 1580 540, 1581 541, 1583 545, 1584 546, 1585 547, 1589 550, 1590 552, 1591 553, 1592 554, 1593 574, 1594 592, 1595 602, 1597 603, 1598 606, 1599 607, 1600 667, 1601 668, 1602 686, 1603 690, 1605 699, 1606 705, 1607 708, 1609 711, 1610 728, 1611 739, 1612 742, 1613 743, 1615 774, 1617 775, 1619 776, 1623 777, 1624 778, 1625 779, 1627 780, 1628 781, 1629 782, 1630 783, 1631 784, 1632 785, 1633 786, 1636 787, 1637 788, 1638 789, 1639 790, 1640 793, 1641 794, 1642 795, 1644 797, 1645 798, 1646 803, 1647 804, 1649 805, 1650 808, 1652 813, 1653 815, 1655 816, 1656 818, 1657 820, 1658 821, 1659 822, 1660 823, 1661 826, 1662 828, 1663 829, 1664 830, 1665 831, 1666 832, 1667 834, 1668 835, 1669 836, 1670 837, 5689 839, 5791 840, 5792 841, 5793 842, 5794 843, 5795 844, 5796 846, 5797 849, 5798 850, 5799 854, 5800 855, 5801 856, 5802 857, 5803 860, 5804 861, 5805 862, 5806 863, 5807 864, 5808 865, 5809 867, 5810 868, 5811 869, 5812 870, 5813 871, 5814 872, 5815 874, 5816 875, 5817 878, 5818 879, 5819 881, 5820 883, 5821 884, 5822 885, 5823 886, 5824 888, 5825 889, 5826 890, 5827 891, 5828 892, 5829 893, 5830 894, 5831 896, 5832 898, 5833 901, 5834 903, 5835 905, 5836 906, 5837 909, 5838 914, 5839 915, 5840 922, 5841 923, 5842 925, 5843 927, 5844 931, 5845 932, 5846 934, 5847 935, 5848 936, 5849 937, 5850 938, 5851 939, 5852 940, 5853 941, 5854 945, 5855 946, 5856 947, 5857 949, 5858 950, 5859 951, 5860 952, 5861 953, 5862 954, 5863 957, 5864 960, 5865 963, 5866 965, 5867 967, 5868 968, 5869 969, 5870 972, 5871 973, 5872 974, 5873 975, 5874 976, 5875 977, 5876 979, 5877 983, 5878 984, 5879 985, 5880 986, 5881 987, 5882 988, 5883 990, 5884 991, 5885 993, 5886 996, 5887 997, 5888 1000, 5889 1001, 5890 1002, 5891 1003, 5892 1004, 5893 1005, 5894 1006, 5895 1007, 5896 1010, 5897 1012, 5898 1013, 5899 1014, 5900 1015, 5901 1016, 5902 1017, 5903 1018, 5904 1025, 5905 1028, 5906 1029, 5907 1030, 5908 1031, 5909 1033, 5910 1035, 5911 1036, 5912 1037, 5913 1039, 5914 1041, 5915 1042, 5916 1044, 5917 1045, 5918 1052, 5919 1053, 5920 1054, 5921 1055, 5922 1056, 5923 1060, 5924 1064, 5925 1067, 5926 1070, 5927 1072, 5928 1075, 5929 1076, 5930 1085, 5931 1086, 5932 1087, 5933 1089, 5934 1091, 5935 1096, 5936 1097, 5937 1098, 5938 1099, 5939 1100, 5940 1101, 5941 1102, 5942 1104, 5943 1107, 5944 1108, 5945 1111, 5946 1113, 5947 1114, 5948 1115, 5949 1116, 5950 1118, 5951 1119, 5952 1120, 5953 1122, 5954 1123, 5955 1124, 5956 1128, 5957 1129, 5958 1132, 5959 1136, 5960 1137, 5961 1138, 5962 1140, 5963 1141, 5964 1142, 5965 1144, 5966 1145, 5967 1149, 5968 1151, 5969 1153, 5970 rocq-9.2.0/dev/ci/000077500000000000000000000000001516144147600136505ustar00rootroot00000000000000rocq-9.2.0/dev/ci/README-developers.md000066400000000000000000000255531516144147600173070ustar00rootroot00000000000000Information for developers about the CI system ---------------------------------------------- When you submit a pull request (PR) on the Rocq GitHub repository, this will launch a battery of CI tests. The PR will not be integrated unless these tests pass. We are currently running tests on the following platforms: - GitLab CI is the main CI platform. It tests the compilation of Rocq, of the documentation, and of RocqIDE on Linux with several versions of OCaml and with warnings as errors; it runs the test-suite and tests the compilation of several external developments. It also runs a linter that checks whitespace discipline. A [pre-commit hook](../tools/pre-commit) is automatically installed by `./configure`. It should allow complying with this discipline without pain. - Github Actions are used to test the compilation of Rocq on Windows and macOS. For Windows, the Rocq platform script is used, producing an installer that can be used to test Rocq. 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: 1. Log into GitLab CI (the easiest way is to sign in with your GitHub account). 2. Click on "New Project". 3. Choose "CI / CD for external repository" then click on "GitHub". 4. Find your fork of the Rocq repository and click on "Connect". 5. If GitLab did not do so automatically, [enable the Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html#enable-the-container-registry-for-your-project). 6. You are encouraged to go to the CI / CD general settings and increase the timeout from 1h to 2h for better reliability. Now every time you push (including force-push unless you changed the default GitLab setting) to your fork on GitHub, it will be synchronized on GitLab and CI will be run. You will receive an e-mail with a report of the failures if there are some. You can also run one CI target locally (using `make ci-somedev`). If using `bash` interactively you can update environment variables to use the locally built Rocq (i.e. setting PATH, OCAMLPATH etc) by sourcing `dev/ci/ci-env.sh`. See also [`test-suite/README.md`](../../test-suite/README.md) for information about adding new tests to the test-suite. ### Light and full CI By default, only a light CI is run, mostly testing only Rocq itself. Before merging a PR, it must also pass full CI testing multiple third party developments. See [`CONTRIBUTING.md`](../../CONTRIBUTING.md#understanding-automatic-feedback) for more details. ### Breaking changes When your PR breaks external projects we test in our CI, you must: 1. Assess the breakage. * If it is a bug your PR introduces, it should be fixed. * Otherwise, you must assess the impact of the breakage and porting effort required on a few CI entries that exercise the functionality being changed. 2. Some breakages can be accepted, for instance to remove something already deprecated for long. Less obvious cases are to be determined with the PR assignee and reviewers, or discussed during a [weekly Call](https://github.com/rocq-prover/rocq/wiki/Rocq-Calls) when doubts remain. 3. For intentional breakages, you must then write porting instructions (typically the PR changelog), based on your previous assesment. For instance something like "ensuring compilation with Rocq X.Y and option -w +thing-we-are-removing-deprecated". You can also offer a script to help porting if you wish. 4. The PR assignee will finally ask the project maintainers to prepare a patch. For plugins, you must prepare yourself an overlay (you can ask the CI project maintainer for help). Ultimately, for non-plugin CI projects, the responsibility of preparing a patch falls on the project maintainer, but PR writers are encouraged to be helpful and may prepare patches themselves to facilitate a smooth process of adaptation. To ask project maintainers to adapt their development, the PR assignee can use the following template > @maintainer please update . You can do so by to update, typically the PR changelog entry> > If is not updated in 7 days from now, it will be disabled in Rocq CI > so as to not further delay the current PR (the project can be reenabled > later, once fixed). In case you encounter > unanticipated difficulties, please come back to us (for instance below) > and feel free to request an extension. You can find the maintainers to ping in [ci-basic.sh](./ci-basic.sh). Of course, it's not in the interest of any developer to disable large spans of the CI, so best efforts will be made, in collaboration with the respective project maintainers to not disable some projects, considered flagship projects, particularly towards the base of the hierarchy. There is experimental support for an improved workflow, see [the next section](#experimental-automatic-overlay-creation-and-building), below are the steps to manually prepare a patch: 1. Fork the external project, create a new branch, push a commit adapting the project to your changes. We recommend that the commit message mention your PR's number and a short explanation of what changed, eg `Adapt to rocq-prover/rocq#XXXXX (changed order of arguments of foo)`. The explanation makes it possible to understand what's going on without having to dereference github PR numbers. 2. Test your pull request with your adapted version of the external project by adding an overlay file to your pull request (cf. [`dev/ci/user-overlays/README.md`](user-overlays/README.md)). 3. Fixes to external libraries (pure Rocq projects) *must* be backward compatible (i.e. they should also work with the development version of Rocq, and the latest stable version). This will allow you to open a PR on the external project repository to have your changes merged *before* your PR on Rocq can be integrated. On the other hand, patches to plugins (projects linking to the Rocq ML API) can very rarely be made backward compatible and plugins we test will generally have a dedicated branch per Rocq version. You can still open a pull request but the merging will be requested by the developer who merges the PR on Rocq. To avoid early merges of such PR, which would break Rocq CI, it is recommended to keep them as draft PRs. Moreover, in case of user visible change, your PR must absolutely add a changelog entry. See the README in [`doc/changelog`][user-changelog] for how to add a changelog entry. ### Experimental automatic overlay creation and building If you break external projects that are hosted on GitHub, you can use the `create_overlays.sh` script to automatically perform most of the above steps. In order to do so: - determine the list of failing projects: IDs can be found as ci-XXX1 ci-XXX2 ci-XXX3 in the list of GitLab CI failures; - for each project XXXi, look in [ci-basic-overlay.sh](https://github.com/rocq-prover/rocq/blob/master/dev/ci/ci-basic-overlay.sh) to see if the corresponding `XXXi_CI_GITURL` is hosted on GitHub; - log on GitHub and fork all the XXXi projects hosted there; - call the script as: ``` ./dev/tools/create_overlays.sh ejgallego 9873 XXX1 XXX2 XXX3 ``` replacing `ejgallego` by your GitHub nickname, `9873` by the actual PR number, and selecting the XXXi hosted on GitHub. The script will: + checkout the contributions and prepare the branch/remote so you can just commit the fixes and push, + add the corresponding overlay file in `dev/ci/user-overlays`; - go to `_build_ci/XXXi` to prepare your overlay (you can test your modifications by using `make -C ../.. ci-XXXi`) and push using `git push ejgallego` (replacing `ejgallego` by your GitHub nickname); - finally push the `dev/ci/user-overlays/9873-elgallego-YYY.sh` file on your Rocq fork (replacing `9873` by the actual PR number, and `ejgallego` by your GitHub nickname). For problems related to ML-plugins, if you use `dune build` to build Rocq, it will actually be aware of the broken contributions and perform a global build. This is very convenient when using `merlin` as you will get a coherent view of all the broken plugins, with full incremental cross-project rebuild. Advanced GitLab CI information ------------------------------ GitLab CI is set up to use the "build artifact" feature to avoid rebuilding Rocq. In one job, Rocq is built with `./configure -relocatable` and `dune install --prefix=$(pwd)/_install_ci` is run, then the `_install_ci` directory persists to and is used by the next jobs. ### Artifacts Build artifacts from GitLab can be linked / downloaded in a systematic way, see [GitLab's documentation](https://docs.gitlab.com/ce/user/project/pipelines/job_artifacts.html#downloading-the-latest-job-artifacts) for more information. For example, to access the documentation of the `master` branch, you can do: https://gitlab.com/rocq-prover/rocq/-/jobs/artifacts/master/file/_install_ci/share/doc/coq/sphinx/html/index.html?job=doc:refman Browsing artifacts is also possible: https://gitlab.com/rocq-prover/rocq/-/jobs/artifacts/master/browse/_install_ci/?job=build:base Above, you can replace `master` and `job` by the desired GitLab branch and job name. Currently available artifacts are: - the Rocq executables and stdlib, in four copies varying in architecture and OCaml version used to build Rocq: https://gitlab.com/rocq-prover/rocq/-/jobs/artifacts/master/browse/_install_ci/?job=build:base Additionally, an experimental Dune build is provided: https://gitlab.com/rocq-prover/rocq/-/jobs/artifacts/master/browse/_build/?job=build:edge:dune:dev - the Rocq documentation, built in the `doc:*` jobs. When submitting a documentation PR, this can help reviewers checking the rendered result. **@coqbot** will automatically post links to these artifacts in the PR checks section. Furthermore, these artifacts are automatically deployed at: + Rocq's Reference Manual [master branch]: + Rocq's Standard Library Documentation [master branch]: + Rocq's ML API Documentation [master branch]: ### GitLab and Docker System and opam packages are installed in a Docker image. The image is automatically built and uploaded to your GitLab registry, and is loaded by subsequent jobs. **IMPORTANT**: When updating Rocq's CI docker image, you must modify the `CACHEKEY` variable in [`.gitlab-ci.yml`](../../.gitlab-ci.yml) (see comment near it for details). The Docker building job reuses the uploaded image if it is available, but if you wish to save more time you can skip the job by setting `SKIP_DOCKER` to `true`. In the case of the main Rocq repository, this variable is set to true by default, but coqbot will set it to `false` anytime a PR modifies a path matching `dev/ci/docker/.*Dockerfile.*`. See also [`docker/README.md`](docker/README.md). rocq-9.2.0/dev/ci/README-users.md000066400000000000000000000204221516144147600162660ustar00rootroot00000000000000Information for external library / Rocq plugin authors ----------------------------------------------------- You are encouraged to consider submitting your project for addition to Rocq's CI. This means that: - Any time that a proposed change is breaking your project, Rocq developers and contributors will send you patches to adapt it (systematically only for plugins) or will explain how to adapt it and work with you to ensure that you manage to do it. On the condition that: - At the time of the submission, your project works with Rocq's `master` branch. - Your project is publicly available in a git repository and we can easily send patches to you (e.g. through pull / merge requests). - You react in a timely manner to adapt to the few requested changes required by Rocq developers or to integrate their patches (in a 7 days timeframe, extensions can be requested for exceptionally complex changes). - You do not push, to the branch that we test, commits that haven't been first tested to compile with the corresponding branch of Rocq. For that, we recommend setting a CI system for you project, see for instance [supported CI images for Rocq](#supported-ci-images-for-rocq) below. - You maintain a reasonable build time for your project, or you provide a "lite" target that we can use. - You keep points of contact up to date. In case you forget to comply with these last four conditions, we would reach out to you and give you a 30-day grace period during which your project would be moved into our "allow failure" category. At the end of the grace period, in the absence of progress, the project would be removed from our CI. Due to a lack of computing resources, submitted libraries which do not clearly expand what Rocq's CI covers might not be integrated. You are encouraged to discuss the addition of your project on [Rocq's Zulip](https://coq.zulipchat.com/). You are also encouraged to test your project with Rocq master and report any issues you find (not just bugs) even if it is not in Rocq's CI; if your project repeatedly finds issues they will be evidence that it would expand the CI's coverage. There is no such requirement for plugins: developers may reduce the cost of working with Rocq's unstable OCaml API by adding their plugin to Rocq's CI and getting it fixed when the API changes (as long as fixing the plugin doesn't put an undue burden on Rocq developers). ### Timely merging of overlays A pitfall of the current CI setup is that when a breaking change is merged in Rocq upstream, CI for your contrib will be broken until you merge the corresponding pull request with the fix for your contribution. As of today, you have to worry about synchronizing with Rocq upstream every once in a while; a workaround is to give merge permissions to someone from the Rocq team as to help with these kind of merges. ### OCaml and plugin-specific considerations Projects that link against Rocq's OCaml API [most of them are known as "plugins"] do have some special requirements: - Rocq's OCaml API is not stable. We hope to improve this in the future but as of today you should expect to have to merge a fair amount of "overlays", usually in the form of Pull Requests from Rocq developers in order to keep your plugin compatible with Rocq master. In order to alleviate the load, you can delegate the merging of such compatibility pull requests to Rocq developers themselves, by granting access to the plugin repository or by using `bots` such as [Bors](https://github.com/apps/bors) that allow for automatic management of Pull Requests. ### Add your project by submitting a pull request Add a new `ci-mydev.sh` script to [`dev/ci/scripts`](scripts); set the corresponding variables in [`ci-basic-overlay.sh`](ci-basic-overlay.sh); add the corresponding target to [`Makefile.ci`](../../Makefile.ci) and a new job to [`.gitlab-ci.yml`](../../.gitlab-ci.yml) so that this new target is run. Have a look at [#17241](https://github.com/rocq-prover/rocq/pull/17241/files) for an example. **Do not hesitate to submit an incomplete pull request if you need help to finish it.** Some important points: - Mention one or a few points of contact in [`ci-basic-overlay.sh`](ci-basic-overlay.sh). - Let `$job` be the name of the new job as used for the name of the added script file `dev/ci/scripts/ci-$job.sh`. Then the added target in `Makefile.ci` must be named `ci-$job` and the added job in `.gitlab-ci.yml` must be named `library:$job` or `plugin:$job`. `$job` must be a valid shell variable name, typically this means replacing dashs (`-`) with underscores (`_`). - Let `$project` be the name of your project as used for the first argument to `project` in `ci-basic-overlay.sh`. Usually this is the same as `$job` in the above bullet. It must also be a valid shell variable name. In some cases a script will handle multiple source repositories and so will need multiple `$project`, see for instance script `verdi_raft`. - If you wish to run a test suite for your project which takes non-negligible time, it may be useful to run the test suite in a separate `Makefile.ci` target and GitLab job, using a separate shell script. In terms of the above bullet points this means a `$project` used in multiple `$job`s. See for instance `mathcomp` and `mathcomp_test`. - When declaring the job in `.gitlab-ci.yml` you must choose the opam switch by using `extends: .ci-template` or `extends: .ci-template-flambda`. The first one uses the minimum version of OCaml supported by Rocq. The second one uses the highest version of OCaml supported by Rocq, with flambda enabled (currently it actually uses OCaml 4.14.1 as 5.0 has significant performance issues). See also the corresponding [`Dockerfiles`](docker/) to find out what specific packages are available in each switch. If your job depends on other jobs, you must use the same opam switch. If you wish to depend on jobs currently declared in separate switches, please open a draft pull request and the Rocq developers will decide which jobs should change switches. If you need an exception to this rule for some other reason, please discuss with the Rocq developers. - Job dependencies are declared in 2 places: `Makefile.ci` using the usual Makefile syntax, and `.gitlab-ci.yml` using `needs`. If you only depend on Rocq itself the implicit `needs` from the template suffices. Otherwise the `needs` list must include all transitive dependencies. See for instance the declaration for `library:ci-analysis`. - If you depend on more than Rocq itself you must specify the `stage`: `build-2` if all your dependencies depend only on Rocq itself, otherwise `build-3+` (the number is the max depth of the dependency chain, with Rocq itself at 0 and the default from the template at 1). - If needed you can disable native compilation by doing `export COQEXTRAFLAGS='-native-compiler no'` before the build commands in the script file. If any of your dependencies disable native compilation you must do the same. You may also be interested in having your project tested in our performance benchmark. Currently this is done by providing a `.dev` OPAM package in https://github.com/coq/opam-coq-archive and opening an issue at https://github.com/rocq-prover/rocq/issues. ### Recommended branching policy. It is sometimes the case that you will need to maintain a branch of your project for particular Rocq versions. This is in fact very likely if your project includes a Rocq ML plugin. For such projects, we recommend a branching convention that mirrors Rocq's branching policy. Then, you would have a `master` branch that follows Rocq's `master`, a `v9.0` branch that works with Rocq's `v9.0` branch and so on. This convention will be supported by tools in the future to make some developer commands work more seamlessly. ### Supported CI images for Rocq The Rocq developers and contributors provide official Docker and Nix images for testing against Rocq master. Using these images is highly recommended: - For Docker, see: https://github.com/coq-community/docker-coq The https://github.com/coq-community/docker-coq/wiki/CI-setup wiki page contains additional information and templates to help setting Docker-based CI up for your Rocq project - For Nix, see the setup at https://github.com/coq-community/manifesto/wiki/Continuous-Integration-with-Nix rocq-9.2.0/dev/ci/README.md000066400000000000000000000016471516144147600151370ustar00rootroot00000000000000Continuous Integration for the Rocq Prover ========================================== Changes to Rocq are systematically tested for regression and compatibility breakage on our Continuous Integration (CI) platforms *before* integration, so as to ensure better robustness and catch problems as early as possible. These tests include the compilation of several external libraries / plugins. This README is split into two specific documents: - [README-users.md](./README-users.md) which contains information for authors of external libraries and plugins who might be interested in having their development tested in our CI system. - [README-developers.md](./README-developers.md) for Rocq developers / contributors, who must ensure that they don't break these external developments accidentally. *Remark:* the CI policy outlined in these documents is susceptible to evolve and specific accommodations are of course possible. rocq-9.2.0/dev/ci/ci-basic-overlay.sh000066400000000000000000000634361516144147600173510ustar00rootroot00000000000000#!/usr/bin/env bash # This is the list of repositories used by the CI scripts, unless overridden # by a call to the "overlay" function in ci-common declare -a projects # the list of project repos that can be be overlayed # checks if the given argument is a known project function is_in_projects { for x in "${projects[@]}"; do if [ "$1" = "$x" ]; then return 0; fi; done return 1 } # project [] # [] defaults to /archive on github.com # and /-/archive on gitlab function project { local var_ref=${1}_CI_REF local var_giturl=${1}_CI_GITURL local var_archiveurl=${1}_CI_ARCHIVEURL local giturl=$2 local ref=$3 local archiveurl=$4 case $giturl in *github.com*) archiveurl=${archiveurl:-$giturl/archive} ;; *gitlab*) archiveurl=${archiveurl:-$giturl/-/archive} ;; esac # register the project in the list of projects projects[${#projects[*]}]=$1 # bash idiom for setting a variable if not already set : "${!var_ref:=$ref}" : "${!var_giturl:=$giturl}" : "${!var_archiveurl:=$archiveurl}" } # subproject # In the case of nested submodules, each subproject should be declared # a subproject of its immediate parent, to ensure overlays are applied # in the right order function subproject { local var_parent_project=${1}_CI_PARENT_PROJECT local var_submodule_folder=${1}_CI_SUBMODULE_FOLDER local var_submodule_giturl=${1}_CI_SUBMODULE_GITURL local var_submodule_branch=${1}_CI_SUBMODULE_BRANCH local parent_project=$2 local submodule_folder=$3 local submodule_giturl=$4 local submodule_branch=$5 # register the project in the list of projects projects[${#projects[*]}]=$1 : "${!var_parent_project:=$parent_project}" : "${!var_submodule_folder:=$submodule_folder}" : "${!var_submodule_giturl:=$submodule_giturl}" : "${!var_submodule_branch:=$submodule_branch}" } ######################################################################## # MathComp ######################################################################## project mathcomp 'https://github.com/math-comp/math-comp' '1378d07ead40985f5251ae92bbe3eb7905aa37b4' # Contact @CohenCyril, @proux01 on github project fourcolor 'https://github.com/math-comp/fourcolor' '9990abd7a15f80916c14367ac6dec947a836e60e' # Contact @ybertot, @proux01 on github project oddorder 'https://github.com/math-comp/odd-order' 'e170ac09942df7d4f2b2bab364624dd073619075' # Contact @gares, @proux01 on github project mczify 'https://github.com/math-comp/mczify' '96dfac88f969ded4b4db5b3e2805ce9efaa0bcaa' # Contact @pi8027 on github project algebra_tactics 'https://github.com/math-comp/algebra-tactics' '88aab35361541ddf1ba199438122f3a91469e27e' # Contact @pi8027, @proux01 on github project finmap 'https://github.com/math-comp/finmap' 'c0cf3df180b7279a7e6ac9367bd5a7aa66af56a7' # Contact @CohenCyril on github project bigenough 'https://github.com/math-comp/bigenough' 'eed6cf38d6d20e2b20d29b3778dacbe9f85394c3' # Contact @CohenCyril on github project analysis 'https://github.com/math-comp/analysis' '4d9168b8779c870d49fe7d9071c7d755ab1081a2' # Contact @affeldt-aist, @CohenCyril on github ######################################################################## # UniMath ######################################################################## project unimath 'https://github.com/UniMath/UniMath' '7563807290859c82b029534d9187318456c1e0f7' # Contact @benediktahrens, @m-lindgren, @nmvdw, @rmatthes on github ######################################################################## # Unicoq + Mtac2 ######################################################################## project unicoq 'https://github.com/unicoq/unicoq' 'd52374ca86e3885197f114555e742420fa9bbe94' # Contact @beta-ziliani, @Janno, @mattam82 on github project mtac2 'https://github.com/Mtac2/Mtac2' 'fe8b6049835caa793436e277a64ee7e4910f7b04' # Contact @beta-ziliani, @Janno, @mattam82 on github ######################################################################## # Mathclasses + Corn ######################################################################## project math_classes 'https://github.com/coq-community/math-classes' '257619f0479a90ed97a53e2edd1425002c20ea95' # Contact @Lysxia and @spitters on github project corn 'https://github.com/coq-community/corn' '225384e459d911441f4b473419d00c2fb2fa6eab' # Contact @Lysxia and @spitters on github ######################################################################## # Iris ######################################################################## # NB: stdpp and Iris refs are gotten from the opam files in the Iris and # iris_examples repos respectively. So just getting a fix landed in stdpp or # Iris is not enough. Ping @RalfJung and @robbertkrebbers if you need the # versions of stdpp or Iris to be bumped. Perennial also has its own pinned # versions of stdpp and Iris; ping @tchajed and @zeldovich to get that bumped. project stdpp "https://gitlab.mpi-sws.org/iris/stdpp" "" # Contact @RalfJung, @robbertkrebbers on github project iris "https://gitlab.mpi-sws.org/iris/iris" "" # Contact @RalfJung, @robbertkrebbers on github project autosubst 'https://github.com/coq-community/autosubst' '50dfe574c0bd415925eea47c1f5b1a533aa85269' # Contact @RalfJung, @co-dan on github project iris_examples 'https://gitlab.mpi-sws.org/iris/examples' '4a2b79da62a386895afd6586c77998182f262704' # Contact @RalfJung, @robbertkrebbers on github ######################################################################## # HoTT ######################################################################## project hott 'https://github.com/HoTT/HoTT' '4e1662f5ea7a10b31b794adcee1392671db77b1c' # Contact @Alizter, @jdchristensen on github ######################################################################## # CoqHammer ######################################################################## project coqhammer 'https://github.com/lukaszcz/coqhammer' '1d581299c2a85af175b53bd35370ea074af922ec' # Contact @lukaszcz on github ######################################################################## # Flocq ######################################################################## project flocq 'https://gitlab.inria.fr/flocq/flocq' '54cadd27b64daafa1b94a97dba6011ae46048113' # Contact @silene on github ######################################################################## # coq-performance-tests ######################################################################## project coq_performance_tests 'https://github.com/coq-community/coq-performance-tests' '940baa2bc2753ba65d2c9d0918618aa50721902c' # Contact @JasonGross on github ######################################################################## # coq-tools ######################################################################## project coq_tools 'https://github.com/JasonGross/coq-tools' '1b4ec4a46c9c0737da361aae5b9b812f99a9cb5d' # Contact @JasonGross on github ######################################################################## # Coquelicot ######################################################################## project coquelicot 'https://gitlab.inria.fr/coquelicot/coquelicot' '22314576d5d067fa49f5c9cced0a94d409f8cb65' # Contact @silene on github ######################################################################## # CompCert ######################################################################## project compcert 'https://github.com/AbsInt/CompCert' '821abd5f3d7eaf5a430c4d163726f2743a23cb79' # Contact @xavierleroy on github ######################################################################## # VST ######################################################################## project vst 'https://github.com/PrincetonUniversity/VST' 'bde826e50ab2a6ca67c38de2ab689ffd6920fef2' # Contact @andrew-appel on github ######################################################################## # cross-crypto ######################################################################## project cross_crypto 'https://github.com/mit-plv/cross-crypto' '64d06b2be33c4d4d1bdeea4854d4bb04d66a162d' # Contact @andres-erbsen on github ######################################################################## # rewriter ######################################################################## project rewriter 'https://github.com/mit-plv/rewriter' 'dd37fb28ed7f01a3b7edc0675a86b95dd3eb1545' # Contact @JasonGross on github ######################################################################## # fiat_parsers ######################################################################## project fiat_parsers 'https://github.com/mit-plv/fiat' 'c171d6d1b31b2282c7d2623e93e8c3791cf40508' # Contact @JasonGross on github ######################################################################## # fiat_crypto_legacy ######################################################################## project fiat_crypto_legacy 'https://github.com/mit-plv/fiat-crypto' '09f4c780b4e7f1a6a5b71df4f169c0c5c9378d5d' # Contact @JasonGross on github ######################################################################## # fiat_crypto ######################################################################## project fiat_crypto 'https://github.com/mit-plv/fiat-crypto' 'fc8ce4b3ced2e8a24773b708666a74d132a8425e' # Contact @andres-erbsen, @JasonGross on github # bedrock2, coqutil, rupicola, kami, riscv_coq # fiat-crypto is not guaranteed to build with the latest version of # bedrock2, so we use the pinned version of bedrock2 for fiat-crypto # overlays do not have to follow suite subproject rupicola fiat_crypto "rupicola" "https://github.com/mit-plv/rupicola" "master" subproject bedrock2 rupicola "bedrock2" "https://github.com/mit-plv/bedrock2" "master" subproject coqutil bedrock2 "deps/coqutil" "https://github.com/mit-plv/coqutil" "master" subproject kami bedrock2 "deps/kami" "https://github.com/mit-plv/kami" "rv32i" subproject riscv_coq bedrock2 "deps/riscv-coq" "https://github.com/mit-plv/riscv-coq" "master" # Contact @samuelgruetter, @andres-erbsen on github ######################################################################## # coq_dpdgraph ######################################################################## project coq_dpdgraph 'https://github.com/coq-community/coq-dpdgraph' '7a0fba21287dd8889c55e6611f8ba219d012b81b' # Contact @Karmaki, @ybertot on github ######################################################################## # CoLoR ######################################################################## project color 'https://github.com/fblanqui/color' '42d00eb8030fabdedf2d8eee4010fe0f89bd544a' # Contact @fblanqui on github ######################################################################## # TLC ######################################################################## project tlc 'https://github.com/charguer/tlc' 'fd53b3b2f0a0d7c24c8363fbd4570a451198ded7' # Contact @charguer on github ######################################################################## # Bignums ######################################################################## project bignums 'https://github.com/coq/bignums' '30a45625546da0a88db8689a8009d580aa3f557f' # Contact @erikmd, @proux01 on github ######################################################################## # coqprime ######################################################################## project coqprime 'https://github.com/thery/coqprime' '589b9761e4efcb37277d5548ece6174255c9ac83' # Contact @thery on github ######################################################################## # bbv ######################################################################## project bbv 'https://github.com/mit-plv/bbv' '032537e726ad2b235a16162e83357f054a3039be' # Contact @JasonGross, @samuelgruetter on github ######################################################################## # Coinduction ######################################################################## project coinduction 'https://github.com/damien-pous/coinduction' '9502ae09e9f87518330f37c08bc19a8c452dcd91' # Contact @damien-pous on github ######################################################################## # coq-lsp ######################################################################## project coq_lsp 'https://github.com/ejgallego/coq-lsp' 'bd6fb39fc0ac51330c3543ef727d7fa3c81d7b96' # Contact @ejgallego on github ######################################################################## # Equations ######################################################################## project equations 'https://github.com/mattam82/Coq-Equations' '757662b9c875d7169a07b861d48e82157520ab1a' # Contact @mattam82 on github ######################################################################## # Elpi + Hierarchy Builder ######################################################################## project elpi 'https://github.com/LPCIC/coq-elpi' '1ab7fcc7dc5eae1e25f4a61ebd4d6cf97dbbbfd8' # Contact @gares on github project hierarchy_builder 'https://github.com/math-comp/hierarchy-builder' '2156a76d8a59d2b8a3571fc6c02e3b44010ab7d7' # Contact @CohenCyril, @gares on github ######################################################################## # Engine-Bench ######################################################################## project engine_bench 'https://github.com/mit-plv/engine-bench' '08ecd3ae6e73ff6e62b47fd62f5c57e4ec4fb42d' # Contact @JasonGross on github ######################################################################## # fcsl-pcm ######################################################################## project fcsl_pcm 'https://github.com/imdea-software/fcsl-pcm' '69c244e93e6790100065eb59a307adba6d1775a8' # Contact @aleksnanevski, @clayrat on github ######################################################################## # ext-lib ######################################################################## project ext_lib 'https://github.com/coq-community/coq-ext-lib' '07d35df4c9e7ae3bf390e553822fb9ddbd943dd2' # Contact @gmalecha, @liyishuai on github ######################################################################## # simple-io ######################################################################## project simple_io 'https://github.com/Lysxia/coq-simple-io' 'f6cadf769e94ceca204ca9c54282df07714422a7' # Contact @Lysxia, @liyishuai on github ######################################################################## # quickchick ######################################################################## project quickchick 'https://github.com/QuickChick/QuickChick' '4a3a725dfca7dccbfc3ebdce548a41ccd78e0507' # Contact @lemonidas, @Lysxia, @liyishuai on github ######################################################################## # reduction-effects ######################################################################## project reduction_effects 'https://github.com/coq-community/reduction-effects' '29541ef53bfbd75f055ebade16cf8ea60f9528c4' # Contact @liyishuai, @JasonGross on github ######################################################################## # menhirlib ######################################################################## # Note: menhirlib is now in subfolder coq-menhirlib of menhir project menhirlib 'https://gitlab.inria.fr/fpottier/menhir' '276ae1d97e6c6e5154ff9f6f3ca7b4783e6d1218' # Contact @fpottier, @jhjourdan on github ######################################################################## # coq-neural-net-interp ######################################################################## project neural_net_interp 'https://github.com/JasonGross/neural-net-coq-interp' '5b496f9ae337e0fca44fcc20df450dc828bab16c' # Contact @JasonGross on github ######################################################################## # aac_tactics ######################################################################## project aac_tactics 'https://github.com/coq-community/aac-tactics' '4f796a7b0ee88330162727fc6ea988a7e0ea46e3' # Contact @palmskog on github ######################################################################## # paco ######################################################################## project paco 'https://github.com/snu-sf/paco' 'd0561bf7f0a96cac486ba3bd8ca0b72ce01fb9cf' # Contact @minkiminki on github ######################################################################## # coq-itree ######################################################################## project itree 'https://github.com/DeepSpec/InteractionTrees' 'bd356ec0d2ea1cf13ed08b129967027f0f81b882' # Contact @Lysxia on github ######################################################################## # coq-itree_io ######################################################################## project itree_io 'https://github.com/Lysxia/coq-itree-io' 'af0326793a19f142eba800dba6044143b108ceaa' # Contact @Lysxia, @liyishuai on github ######################################################################## # coq-ceres ######################################################################## project ceres 'https://github.com/Lysxia/coq-ceres' 'f61b24d48222db0100de19f88c19151a3aeb826f' # Contact @Lysxia on github ######################################################################## # coq-parsec ######################################################################## project parsec 'https://github.com/liyishuai/coq-parsec' '3feabc998705927ca2d2f9249a21a6e15c394162' # Contact @liyishuai on github ######################################################################## # coq-json ######################################################################## project json 'https://github.com/liyishuai/coq-json' '60c1994f2005e01efcfc3d935702748e86dafe2b' # Contact @liyishuai on github ######################################################################## # coq-async-test ######################################################################## project async_test 'https://github.com/liyishuai/coq-async-test' '0637b95ae52060d8a808261ca97890d03c9a4503' # Contact @liyishuai on github ######################################################################## # coq-http ######################################################################## project http 'https://github.com/liyishuai/coq-http' 'ab051acc4471876b45ed462f5763d2132204613a' # Contact @liyishuai on github ######################################################################## # paramcoq ######################################################################## project paramcoq 'https://github.com/coq-community/paramcoq' 'f8026210f37faf6c4031de24ada9fdded29d67e5' # Contact @ppedrot on github ######################################################################## # relation_algebra ######################################################################## project relation_algebra 'https://github.com/damien-pous/relation-algebra' 'ba3db5783060d9e25d1db5e377fc9d71338a5160' # Contact @damien-pous on github ######################################################################## # StructTact + InfSeqExt + Cheerios + Verdi + Verdi Raft ######################################################################## project struct_tact 'https://github.com/uwplse/StructTact' '97268e11564c8fe59aa72b062478458d7aa53e9d' # Contact @palmskog on github project inf_seq_ext 'https://github.com/DistributedComponents/InfSeqExt' '601e89ec019501c48c27fcfc14b9a3c70456e408' # Contact @palmskog on github project cheerios 'https://github.com/uwplse/cheerios' '5c9318c269f9cae1c1c6583a44405969ac0be0dd' # Contact @palmskog on github project verdi 'https://github.com/uwplse/verdi' '20a587e075c6b3da3f8172ff0095c756059cc308' # Contact @palmskog on github project verdi_raft 'https://github.com/uwplse/verdi-raft' 'a3375e867326a82225e724cc1a7b4758b029376f' # Contact @palmskog on github ######################################################################## # Stdlib ######################################################################## project stdlib 'https://github.com/coq/stdlib' 'd722e595fb5a520717fdca676fe1545c4fa35626' # Contact TODO on github ######################################################################## # argosy ######################################################################## project argosy 'https://github.com/mit-pdos/argosy' '9fa42b78b7f9b7b989fb3434dfbfec4abcfcbff8' # Contact @tchajed on github ######################################################################## # ATBR ######################################################################## project atbr 'https://github.com/coq-community/atbr' '47ac8fb6bf244d9a4049e04c01e561191490f543' # Contact @palmskog, @tchajed on github ######################################################################## # perennial ######################################################################## project perennial 'https://github.com/mit-pdos/perennial' '394e461a6d0815c66656d28d4749adcde950cab7' # Contact @upamanyus, @tchajed on github # PRs to fix Perennial failures should be submitted against the Perennial # `master` branch. `coq/tested` is automatically updated every night to the # `master` branch if CI on `master` is green. This is to avoid breaking Coq CI # when Perennial CI breaks. ######################################################################## # metarocq ######################################################################## project metarocq 'https://github.com/MetaRocq/metarocq' 'e8f8078e756cc378b830eb5a8e4637df43d481af' # Contact @mattam82, @yforster on github ######################################################################## # SF suite ######################################################################## project sf 'https://github.com/DeepSpec/sf' '5e863a9f92e515a0e11641f28077a64919f8482e' # Contact @bcpierce00, @liyishuai on github ######################################################################## # Coqtail ######################################################################## project coqtail 'https://github.com/whonore/Coqtail' 'a25018e4f371016aefea267038ac5d083b615da9' # Contact @whonore on github ######################################################################## # Deriving ######################################################################## project deriving 'https://github.com/arthuraa/deriving' '1eac44362d895d84c37ac2db308caa7833035f2a' # Contact @arthuraa on github ######################################################################## # VsRocq ######################################################################## project vsrocq 'https://github.com/rocq-prover/vsrocq' 'cf0e9c3b327e155b391df40ed84fd0270dadfffb' # Contact @rtetley, @gares on github ######################################################################## # category-theory ######################################################################## project category_theory 'https://github.com/jwiegley/category-theory' '7da7ce8777b721b98d28027e5c475a75790181ed' # Contact @jwiegley on github ######################################################################## # itauto ######################################################################## project itauto 'https://gitlab.inria.fr/fbesson/itauto' '8190a58b730b0439b55d05d7238435da8224c22f' # Contact @fajb on github ######################################################################## # Mathcomp-word ######################################################################## project mathcomp_word 'https://github.com/jasmin-lang/coqword' '95f0a6a0a290d6b78ee39af7053a93cec5327060' # Contact @vbgl, @strub on github ######################################################################## # Jasmin ######################################################################## project jasmin 'https://github.com/jasmin-lang/jasmin' 'a60227fb7a9e60f8bcc15eb30ea5cf2abadc2496' # Contact @vbgl, @bgregoir on github ######################################################################## # Lean Importer ######################################################################## project lean_importer 'https://github.com/coq-community/rocq-lean-import' 'b8291b9dae4f5ed780112e95eea484e435199b46' # Contact @SkySkimmer on github ######################################################################## # SMTCoq ######################################################################## project smtcoq 'https://github.com/smtcoq/smtcoq' 'cff0a8cdb7c73b6c59965a749a4304f3c4ac01bf' # Contact @ckeller on github project smtcoq_trakt 'https://github.com/smtcoq/smtcoq' '9392f7446a174b770110445c155a07b183cdca3d' # Contact @ckeller on github ######################################################################## # Stalmarck ######################################################################## project stalmarck 'https://github.com/coq-community/stalmarck' 'd32acd3c477c57b48dd92bdd96d53fb8fa628512' # Contact @palmskog on github ######################################################################## # Tactician ######################################################################## project tactician 'https://github.com/coq-tactician/coq-tactician' '6750c1d7d58b2ca3057cb23f6e1d19f5674cfb08' # Contact @LasseBlaauwbroek on github ######################################################################## # Ltac2 compiler ######################################################################## project ltac2_compiler 'https://github.com/SkySkimmer/coq-ltac2-compiler' '0401985b54ce426f4901f35ff6e827685927030a' # Contact @SkySkimmer on github ######################################################################## # Waterproof ######################################################################## project waterproof 'https://github.com/impermeable/coq-waterproof' '99ad6ff78fa700c84ba0cb1d1bda27d8e0f11e1a' # Contact @jellooo038, @jim-portegies on github ######################################################################## # Autosubst (2) OCaml ######################################################################## project autosubst_ocaml 'https://github.com/uds-psl/autosubst-ocaml' '772acb2248738fd4bc51b122c454ccb3f01cdeec' # Contact @yforster on github ######################################################################## # Trakt ######################################################################## project trakt 'https://github.com/ecranceMERCE/trakt' 'bd49a3077b8aa0522368c84dae349e5006b36f0b' # Contact @ckeller on github rocq-9.2.0/dev/ci/ci-env.sh000066400000000000000000000035041516144147600153670ustar00rootroot00000000000000#!/usr/bin/env bash if which cygpath >/dev/null 2>&1; then OCAMLFINDSEP=\;; else OCAMLFINDSEP=:; fi if [ "${BASH_SOURCE[0]}" ]; then root="$(dirname "${BASH_SOURCE[0]}")/../.." # make path absolute if relative root=$(cd "$root" && echo "$PWD") elif [ -e "$PWD/dev/ci/ci-env.sh" ]; then root=$PWD else >&2 echo "BASH_SOURCE not working (too old bash version?)" >&2 echo "update bash or run this script from the rocq repository's root directory" exit 1 fi # We can remove setting ROCQLIB and ROCQRUNTIMELIB from here, but better to # wait until we have merged the coq.boot patch so we can do this in a # more controlled way. if [ -n "${GITLAB_CI}" ]; then # Gitlab build, Rocq installed into `_install_ci` export COQBIN="$root/_install_ci/bin" export OCAMLPATH="$root/_install_ci/lib$OCAMLFINDSEP$OCAMLPATH" export PATH="$root/_install_ci/bin:$PATH" # Where we install external binaries and ocaml libraries # also generally used for dune install --prefix so needs to match coq's expected user-contrib path CI_INSTALL_DIR="$root/_install_ci" export CI_BRANCH="$CI_COMMIT_REF_NAME" if [[ ${CI_BRANCH#pr-} =~ ^[0-9]*$ ]] then export CI_PULL_REQUEST="${CI_BRANCH#pr-}" fi elif [ -d "$root/_build/install/default/" ]; then # Full Dune build, we basically do what `dune exec --` does export OCAMLPATH="$root/_build/install/default/lib/$OCAMLFINDSEP$OCAMLPATH" export COQBIN="$root/_build/install/default/bin" export ROCQLIB="$root/_build/install/default/lib/coq" export ROCQRUNTIMELIB="$root/_build/install/default/lib/rocq-runtime" CI_INSTALL_DIR="$root/_build/install/default/" CI_BRANCH="$(git rev-parse --abbrev-ref HEAD)" export CI_BRANCH fi export PATH="$COQBIN:$PATH" # Rocq's tools need an ending slash :S, we should fix them. export COQBIN="$COQBIN/" rocq-9.2.0/dev/ci/ci-reset.sh000077500000000000000000000031571516144147600157300ustar00rootroot00000000000000#!/usr/bin/env bash CI_QUIET=1 set +x ci_dir="$(dirname "$0")" . "${ci_dir}/scripts/ci-common.sh" # [git_reset ] will reset the repository for to the upstream branch git_reset() { local project=$1 local dest="${CI_BUILD_DIR}/$project" local ref_var="${project}_CI_REF" local ref="${!ref_var}" # Check whether it may be a submodule if [ -z "$ref" ]; then ref_var="${project}_CI_SUBMODULE_BRANCH" ref="${!ref_var}" fi echo "Resetting $project..." if [ ! -d "$dest" ]; then echo "Warning: reset of $project skipped because $dest does not exist." else if [ -z "$ref" ]; then echo "Warning: reset of $project skipped as no branch could be found." else # TODO: properly handle submodules pushd "$dest" > /dev/null # check that the reference is an actual branch local ref_hash=$(git rev-parse --verify --quiet "refs/heads/$ref") if [ -n "$ref_hash" ]; then git reset --hard --quiet git checkout $ref --quiet git reset --hard "origin/$ref" --quiet echo "$project reset to $ref ($ref_hash)" else if [ $(git rev-parse --verify --quiet "$ref") ]; then # if the reference is a hash just check it out git reset --hard --quiet git checkout $ref --quiet echo "$project reset to $ref" else echo "Warning: reset of $project skipped as $ref is not valid reference." fi fi popd > /dev/null fi fi } git_reset_all() { for project in "${projects[@]}"; do if [ -d "${CI_BUILD_DIR}/$project" ]; then git_reset $project fi done } if [ -n "$1" ]; then git_reset "$1" else git_reset_all fi rocq-9.2.0/dev/ci/ci-update.sh000077500000000000000000000013001516144147600160540ustar00rootroot00000000000000#!/usr/bin/env bash CI_QUIET=1 set +x ci_dir="$(dirname "$0")" . "${ci_dir}/scripts/ci-common.sh" # [git_update ] will update the git repository associated to git_update() { local project=$1 local dest="${CI_BUILD_DIR}/$project" echo "Updating $project..." if [ ! -d "$dest" ]; then echo "Warning: update of $project skipped because $dest does not exist." else pushd "$dest" > /dev/null git remote update > /dev/null popd > /dev/null fi } git_update_all() { for project in "${projects[@]}"; do if [ -d "${CI_BUILD_DIR}/$project" ]; then git_update $project fi done } if [ -n "$1" ]; then git_update "$1" else git_update_all fi rocq-9.2.0/dev/ci/ci-wrapper.sh000077500000000000000000000070111516144147600162570ustar00rootroot00000000000000#!/usr/bin/env bash # Use this script to preserve the exit code of $CI_SCRIPT when piping # it to `tee $log_file`. We have a separate script, because # this only works in bash, which we don't require project-wide. set -o pipefail set -x CI_NAME="$1" CI_SCRIPT="scripts/ci-${CI_NAME}.sh" log_file="_build_ci/${CI_NAME}.log" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # assume this script is in dev/ci/, cd to the root Rocq directory cd "${DIR}/../.." || exit 1 mkdir -p _build_ci # needs to exist so we can write the log_file export TIMED=1 # if COQ_CI_COLOR is set (from the environment) keep it intact (even when it's the empty string)' if ! [ "${COQ_CI_COLOR+1}" ]; then # NB: in CI TERM is unset in the environment # when TERM is unset, bash sets it to "dumb" as a bash variable (not exported?) if { [ -t 1 ] && ! [ "$TERM" = dumb ]; } || [ "$CI" ] then COQ_CI_COLOR=1 else COQ_CI_COLOR= fi fi # we don't want to block commands on user interaction export GIT_PAGER= if [ "$COQ_CI_COLOR" = 1 ] && command -v script > /dev/null; then # prevent piping from disabling auto colors / enable auto colors in CI if [ "$CI" ]; then export TERM=xterm-color fi # on some macos systems OSTYPE is just "darwin", on others it's followed by version info if [[ "$OSTYPE" =~ ^darwin ]]; then script -q /dev/null bash "${DIR}/${CI_SCRIPT}" 2>&1 | tee "$log_file" else script --quiet --flush --return -c "bash '${DIR}/${CI_SCRIPT}'" /dev/null 2>&1 | tee "$log_file" fi else if [ "$COQ_CI_COLOR" = 1 ]; then >&2 echo 'script command not available, colors will be hidden' fi bash "${DIR}/${CI_SCRIPT}" 2>&1 | tee "$log_file" fi code=$? printf "\n%s exit code: %s\n" "$CI_NAME" "$code" >> "$log_file" # the test suite already prints a timing table if [ "$CI_NAME" != stdlib_test ]; then echo 'Aggregating timing log...' echo tools/make-one-time-file.py --real "$log_file" fi # don't print error summary for coq_tools as it gets spammy, and hides jason_msg # see eg https://gitlab.inria.fr/coq/coq/-/jobs/6292796 if [ "$CI" ] && ! [ $code = 0 ] && [ "$CI_NAME" != coq_tools ]; then set +x escape_re=$(printf '\033%s' '\[[0-9;]+m') # File ".* file_re="($escape_re)?"'File ".*\n' # OCaml: error message may contain some code extracts starting with the line number, # followed by a line containing "^^^" to point at the columns (possibly colored) codeline_re='([0-9].*\n)*' carets_re="((($escape_re)|[ ^])*\n)?" # Error messages may be multiline, but it's hard to find the end # heuristic: if the line ends with ":" or ",", also print the next # (typically if the start of the message got moved to the next line, # the first line is just "Error:", # also note that OCaml colors just "Error" but Rocq colors the whole "Error:") error_re="($escape_re)?Error(.*[:,]($escape_re)?\n)*.*\n" # for some reason when testing with colors on # I also got carriage returns in my output which confused grep, so remove them # -P: perl-like # -z: multiline using \0 chars (which is why we have to tr to cleanup the output) # -o: print only matched (otherwise it prints the whole file due to -z) # || true: if no error is matched by this pattern, we still want to use the error code from the build < "$log_file" tr -d "$(printf '\r')" \ | grep -Pzo "$file_re$codeline_re$carets_re$error_re" \ | tr -d '\0' > errors \ || true if [ -s errors ]; then { echo echo "Error list (may be incomplete):" echo cat errors } >&2 fi rm errors fi exit $code rocq-9.2.0/dev/ci/docker/000077500000000000000000000000001516144147600151175ustar00rootroot00000000000000rocq-9.2.0/dev/ci/docker/README.md000066400000000000000000000037221516144147600164020ustar00rootroot00000000000000## Overall Docker Setup for Rocq's CI. This directory provides Docker images to be used by Rocq's CI. The images do support Docker autobuild on `hub.docker.com` and Gitlab's private registry. The Gitlab CI will build a Docker image unless the CI environment variable `SKIP_DOCKER` is set to `true`. This image will be stored in the [Gitlab container registry](https://gitlab.com/coq/coq/container_registry) under the name given by the `CACHEKEY` variable from the [Gitlab CI configuration file](../../../.gitlab-ci.yml). `SKIP_DOCKER` is set to "true" in `https://gitlab.com/coq/coq` to avoid running a lengthy redundant job. For efficiency, users should enable that setting in forked repositories after the initial Docker build in the fork succeeds. The steps to generate a new Docker image are: - Update the `CACHEKEY` variable in .gitlab-ci.yml with the date and md5. - Submit the change in a PR. coqbot will detect that the Dockerfile has changed and will trigger a pipeline build with `SKIP_DOCKER` set to `false`. This will run a `docker-boot` process, and once completed, a new Docker image will be available in the container registry, with the name set in `CACHEKEY`. - Any pipeline with the same `CACHEKEY` will now automatically reuse that image without rebuilding it from scratch. ## Manual Building You can also manually build and push any image: - Build the image `docker build -t base:$VERSION .` To upload/push to your hub: - Create a https://hub.docker.com account. - Login into your space `docker login --username=$USER` - Push the image: + `docker tag base:$VERSION $USER/base:$VERSION` + `docker push $USER/base:$VERSION` ## Debugging / Misc To open a shell inside an image do `docker run -ti --entrypoint /bin/bash ` Each `RUN` command creates an "layer", thus a Docker build is incremental and it always help to put things updated more often at the end. ## Possible Improvements: - Use ARG for customizing versions, centralize variable setup; rocq-9.2.0/dev/ci/docker/edge_ubuntu/000077500000000000000000000000001516144147600174255ustar00rootroot00000000000000rocq-9.2.0/dev/ci/docker/edge_ubuntu/Dockerfile000066400000000000000000000065771516144147600214360ustar00rootroot00000000000000# Update CACHEKEY in the .gitlab-ci.yml when modifying this file. FROM ubuntu:24.04 LABEL maintainer="e@x80.org" ENV DEBIAN_FRONTEND="noninteractive" # We need libgmp-dev:i386 for zarith; maybe we could also install GTK RUN dpkg --add-architecture i386 RUN apt-get update -qq && apt-get install --no-install-recommends -y -qq \ # Dependencies of the image, the test-suite and external projects m4 automake autoconf time wget rsync git gcc-multilib build-essential unzip jq \ # Dependencies of ZArith perl libgmp-dev libgmp-dev:i386 \ # Dependencies of devtools zlib1g-dev \ # Dependencies of lablgtk (for CoqIDE) libgtksourceview-3.0-dev adwaita-icon-theme-full \ # Dependencies of stdlib and sphinx doc texlive-latex-extra texlive-fonts-recommended texlive-xetex latexmk \ python3-pip python3-setuptools python3-pexpect python3-bs4 fonts-freefont-otf \ # pipeline-stats python3-gitlab python3-tabulate \ # Dependency of stdlib-doc graphviz \ # Dependencies of source-doc and coq-makefile texlive-latex-extra texlive-science tipa \ # Dependencies of HB (test suite) wdiff \ # Required to get the wget step to succeed ca-certificates \ # Required for fiat-crypto and Coqtail python-is-python3 \ && rm -rf /var/lib/apt/lists /usr/share/doc # More dependencies of the sphinx doc RUN pip3 install --break-system-packages docutils==0.21.2 sphinx==8.2.3 sphinx_rtd_theme==3.0.2 \ antlr4-python3-runtime==4.7.1 sphinxcontrib-bibtex==2.6.3 \ && rm -rf ~/.cache/pip # We need to install OPAM 2.0 manually for now. RUN wget https://github.com/ocaml/opam/releases/download/2.1.5/opam-2.1.5-x86_64-linux -O /usr/bin/opam && chmod 755 /usr/bin/opam # Basic OPAM setup ENV NJOBS="2" \ OPAMJOBS="2" \ OPAMROOT=/root/.opamcache \ OPAMROOTISOK="true" \ OPAMYES="true" RUN mkdir -p ~/.config/dune && printf '(lang dune 2.1)\n(jobs %s)\n' $NJOBS > ~/.config/dune/config # Edge opam is the set of edge packages required by Coq ENV COMPILER="4.14.2" \ BASE_OPAM="zarith.1.13 ounit2.2.2.6 camlzip.1.13" \ CI_OPAM="ocamlgraph.2.0.0 cppo.1.6.9" \ BASE_OPAM_EDGE="dune.3.14.0 dune-build-info.3.14.0 dune-release.2.0.0 ocamlfind.1.9.6 odoc.2.3.1" \ CI_OPAM_EDGE="elpi.3.0.1 ppx_import.1.10.0 cmdliner.1.1.1 sexplib.v0.15.1 ppx_sexp_conv.v0.15.1 ppx_hash.v0.15.0 ppx_compare.v0.15.0 ppx_deriving_yojson.3.7.0 yojson.2.1.0 uri.4.2.0 ppx_yojson_conv.v0.15.1 ppx_inline_test.v0.15.1 ppx_assert.v0.15.0 ppx_optcomp.v0.15.0 lsp.1.16.2 sel.0.8.0" \ COQIDE_OPAM_EDGE="lablgtk3-sourceview3.3.1.3" # EDGE+flambda switch, we install CI_OPAM as to be able to use # `ci-template-flambda` with everything. RUN opam init -a --disable-sandboxing --bare && eval $(opam env) && \ opam switch create "${COMPILER}+flambda" \ --repositories default,ocaml-beta=git+https://github.com/ocaml/ocaml-beta-repository.git,coq-core-dev=https://coq.inria.fr/opam/core-dev \ --packages="ocaml-variants.${COMPILER}+options,ocaml-option-flambda" && eval $(opam env) && \ opam repo add archive git+https://github.com/ocaml/opam-repository-archive && \ opam update && \ opam install $BASE_OPAM $BASE_OPAM_EDGE $COQIDE_OPAM_EDGE $CI_OPAM $CI_OPAM_EDGE && \ opam clean -a -c # set the locale for the benefit of Python ENV LANG C.UTF-8 rocq-9.2.0/dev/ci/docker/old_ubuntu_lts/000077500000000000000000000000001516144147600201615ustar00rootroot00000000000000rocq-9.2.0/dev/ci/docker/old_ubuntu_lts/Dockerfile000066400000000000000000000063551516144147600221640ustar00rootroot00000000000000# Update CACHEKEY in the .gitlab-ci.yml when modifying this file. FROM ubuntu:22.04 LABEL maintainer="e@x80.org" ENV DEBIAN_FRONTEND="noninteractive" # We need libgmp-dev:i386 for zarith; maybe we could also install GTK RUN dpkg --add-architecture i386 RUN apt-get update -qq && apt-get install --no-install-recommends -y -qq \ # Dependencies of the image, the test-suite and external projects m4 automake autoconf time wget rsync git gcc-multilib build-essential unzip jq \ # Dependencies of ZArith perl libgmp-dev libgmp-dev:i386 \ # Dependencies of devtools zlib1g-dev zlib1g-dev:i386 \ # Dependencies of lablgtk (for CoqIDE) libgtksourceview-3.0-dev adwaita-icon-theme-full \ # Dependencies of stdlib and sphinx doc texlive-latex-extra texlive-fonts-recommended texlive-xetex latexmk \ python3-sphinx python3-docutils python3-sphinx-rtd-theme \ python3-antlr4 python3-sphinxcontrib.bibtex \ python3-setuptools python3-pexpect python3-bs4 fonts-freefont-otf \ # Dependency of stdlib-doc graphviz \ # Dependencies of source-doc and coq-makefile texlive-science tipa \ # Dependencies of HB (test suite) wdiff \ # Required for fiat-crypto and Coqtail python-is-python3 python3-pytest \ # for coq-tools python3-venv \ && rm -rf /var/lib/apt/lists /usr/share/doc # We need to install OPAM 2.0 manually for now. RUN wget https://github.com/ocaml/opam/releases/download/2.0.6/opam-2.0.6-x86_64-linux -O /usr/bin/opam && chmod 755 /usr/bin/opam # Basic OPAM setup ENV NJOBS="2" \ OPAMJOBS="2" \ OPAMROOT=/root/.opamcache \ OPAMROOTISOK="true" \ OPAMYES="true" RUN mkdir -p ~/.config/dune && printf '(lang dune 2.1)\n(jobs %s)\n' $NJOBS > ~/.config/dune/config # Base opam is the set of base packages required by Coq ENV COMPILER="4.14.0" # Common OPAM packages ENV BASE_OPAM="zarith.1.11 ounit2.2.2.6 yojson.1.7.0 camlzip.1.10" \ CI_OPAM="ocamlgraph.2.0.0 cppo.1.6.9" \ BASE_ONLY_OPAM="dune.3.8.3 stdlib-shims.0.1.0 ocamlfind.1.9.1 odoc.2.0.2 num.1.4" # BASE switch; CI_OPAM contains Coq's CI dependencies. ENV COQIDE_OPAM="cairo2.0.6.1 lablgtk3-sourceview3.3.1.2" # Must add this to COQIDE_OPAM{,_EDGE} when we update the opam # packages "lablgtk3-gtksourceview3" # base switch RUN opam init -a --disable-sandboxing --compiler="$COMPILER" default https://opam.ocaml.org && eval $(opam env) && \ opam repo add archive git+https://github.com/ocaml/opam-repository-archive && \ opam update && \ opam install $BASE_OPAM $COQIDE_OPAM $CI_OPAM $BASE_ONLY_OPAM && \ opam clean -a -c && \ find ~ '(' -name '*.cmt' -o -name '*.cmti' ')' -delete # base+32bit switch, note the zarith hack RUN opam switch create "${COMPILER}+32bit" \ --packages="ocaml-variants.${COMPILER}+options,ocaml-option-32bit" && \ eval $(opam env) && \ opam repo add archive git+https://github.com/ocaml/opam-repository-archive && \ opam update && \ i386 env CC='gcc -m32' opam install zarith.1.11 && \ opam install $BASE_OPAM && \ opam clean -a -c && \ find ~ '(' -name '*.cmt' -o -name '*.cmti' ')' -delete # set the locale for the benefit of Python ENV LANG C.UTF-8 rocq-9.2.0/dev/ci/dune-workspace.ci000066400000000000000000000000761516144147600171170ustar00rootroot00000000000000(lang dune 3.8) (context default) (env (_ (bin_annot false))) rocq-9.2.0/dev/ci/gitlab-modes/000077500000000000000000000000001516144147600162175ustar00rootroot00000000000000rocq-9.2.0/dev/ci/gitlab-modes/normal-mode.yml000066400000000000000000000001131516144147600211470ustar00rootroot00000000000000 default: interruptible: true timeout: 1h tags: - not-a-real-tag rocq-9.2.0/dev/ci/gitlab-modes/protected-mode.yml000066400000000000000000000001141516144147600216510ustar00rootroot00000000000000 default: interruptible: false timeout: 1h tags: - not-a-real-tag rocq-9.2.0/dev/ci/gitlab-modes/tagged-runners.yml000066400000000000000000000003761516144147600216750ustar00rootroot00000000000000.auto-use-tags: tags: - $TAGGED_RUNNERS # making this configurable is too annoying if we want to support > 1 tag # and not sure small is enough # so just hardcode ci.inria.fr && medium .auto-use-docker-tags: tags: - ci.inria.fr - medium rocq-9.2.0/dev/ci/gitlab-modes/untagged-runners.yml000066400000000000000000000002671516144147600222370ustar00rootroot00000000000000.auto-use-tags: tags: [] .auto-use-docker-tags: tags: # https://docs.gitlab.com/ee/ci/runners/hosted_runners/linux.html#docker-in-docker-support - saas-linux-small-amd64 rocq-9.2.0/dev/ci/gitlab-section.sh000077500000000000000000000004571516144147600171210ustar00rootroot00000000000000#!/bin/sh case "$1" in start) printf '\e[0Ksection_start:%s:%s\r\e[0K%s\n' "$(date +%s)" "$2" "$3" ;; end) printf '\e[0Ksection_end:%s:%s\r\e[0K\n' "$(date +%s)" "$2" ;; *) >&2 echo "usage: $0 start|end section_name [header_content]" ;; esac rocq-9.2.0/dev/ci/nix/000077500000000000000000000000001516144147600144465ustar00rootroot00000000000000rocq-9.2.0/dev/ci/nix/CoLoR.nix000066400000000000000000000000621516144147600161420ustar00rootroot00000000000000{ bignums }: { coqBuildInputs = [ bignums ]; } rocq-9.2.0/dev/ci/nix/CompCert.nix000066400000000000000000000002651516144147600167050ustar00rootroot00000000000000{ ocamlPackages }: { buildInputs = with ocamlPackages; [ ocaml findlib menhir ]; configure = "./configure -ignore-coq-version x86_64-linux"; make = "make all check-proof"; } rocq-9.2.0/dev/ci/nix/Corn.nix000066400000000000000000000001151516144147600160640ustar00rootroot00000000000000{ bignums, math-classes }: { coqBuildInputs = [ bignums math-classes ]; } rocq-9.2.0/dev/ci/nix/Elpi.nix000066400000000000000000000001231516144147600160530ustar00rootroot00000000000000{ ocamlPackages }: { buildInputs = with ocamlPackages; [ ocaml findlib elpi ]; } rocq-9.2.0/dev/ci/nix/HoTT.nix000066400000000000000000000002161516144147600160030ustar00rootroot00000000000000{ autoconf, automake }: { buildInputs = [ autoconf automake ]; configure = "./autogen.sh && ./configure"; make = "make all validate"; } rocq-9.2.0/dev/ci/nix/README.md000066400000000000000000000022421516144147600157250ustar00rootroot00000000000000# Working on third-party developments with *this* version of Rocq Aim: getting an environment suitable for working on a third-party development using the current version of Rocq (i.e., built from the current state of this repository). Dive into such an environment, for the project `example` by running, from the root of this repository: ./dev/ci/nix/shell example This will build Rocq and the other dependencies of the `example` project, then open a shell with all these dependencies available (e.g., `coqtop` is in path). Additionally, three environment variables are set, to abstract over the 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 Rocq libraries. In case you only want the non-coq dependencies (because you want to use Rocq from your `PATH`), set the environment variable `NOCOQ` to some non-empty value. rocq-9.2.0/dev/ci/nix/VST.nix000066400000000000000000000001171516144147600156410ustar00rootroot00000000000000{}: rec { make = "make IGNORECOQVERSION=true"; clean = "${make} clean"; } rocq-9.2.0/dev/ci/nix/bedrock2.nix000066400000000000000000000003071516144147600166610ustar00rootroot00000000000000{}: { configure = "git submodule update --init --recursive"; clean = "(cd deps/bbv && make clean); (cd deps/riscv-coq && make clean); (cd compiler && make clean); (cd bedrock2 && make clean)"; } rocq-9.2.0/dev/ci/nix/bignums.nix000066400000000000000000000001011516144147600166220ustar00rootroot00000000000000{ ocamlPackages }: { buildInputs = [ ocamlPackages.ocaml ]; } rocq-9.2.0/dev/ci/nix/coq.nix000066400000000000000000000003341516144147600157500ustar00rootroot00000000000000{ stdenv, callPackage, branch, wd }: let coq = callPackage wd { buildDoc = false; doInstallCheck = false; coq-version = "8.9"; }; in coq.overrideAttrs (o: { name = "coq-local-${branch}"; src = fetchGit "${wd}"; }) rocq-9.2.0/dev/ci/nix/coq_dpdgraph.nix000066400000000000000000000003061516144147600176200ustar00rootroot00000000000000{ autoconf, ocamlPackages }: { buildInputs = [ autoconf ] ++ (with ocamlPackages; [ ocaml findlib camlp5 ocamlgraph ]); configure = "autoconf && ./configure"; make = "make all test-suite"; } rocq-9.2.0/dev/ci/nix/coquelicot.nix000066400000000000000000000003171516144147600173360ustar00rootroot00000000000000{ autoconf, automake, ssreflect }: { buildInputs = [ autoconf automake ]; coqBuildInputs = [ ssreflect ]; configure = "./autogen.sh && ./configure"; make = "./remake"; clean = "./remake clean"; } rocq-9.2.0/dev/ci/nix/cross_crypto.nix000066400000000000000000000001341516144147600177150ustar00rootroot00000000000000{}: { configure = "git submodule update --init --recursive"; clean = "make cleanall"; } rocq-9.2.0/dev/ci/nix/default.nix000066400000000000000000000112001516144147600166040ustar00rootroot00000000000000{ pkgs ? import ../../nixpkgs.nix {} , branch , wd , project ? "xyz" , withCoq ? true , bn ? "master" }: with pkgs; # Rocq from this directory let coq = callPackage ./coq.nix { inherit branch wd; }; in # Third-party libraries, built with this Rocq let coqPackages = mkCoqPackages coq; in 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.overrideAttrs (o: { src = fetchTarball "https://github.com/coq-community/coq-ext-lib/tarball/master"; }); in let simple-io = (coqPackages.simple-io.override { inherit coq-ext-lib; }) .overrideAttrs (o: { src = fetchTarball "https://github.com/Lysxia/coq-simple-io/tarball/master"; }); 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 { src = fetchTarball bn; } ); in let coqprime = coqPackages.coqprime.override { inherit coq bignums; }; in let math-classes = (coqPackages.math-classes.override { inherit coq bignums; }) .overrideAttrs (o: { src = fetchTarball "https://github.com/coq-community/math-classes/archive/master.tar.gz"; }); 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 stdpp = coqPackages.stdpp.overrideAttrs (o: { src = fetchTarball "https://gitlab.mpi-sws.org/iris/stdpp/-/archive/master/stdpp-master.tar.bz2"; }); in let iris = (coqPackages.iris.override { inherit coq stdpp; }) .overrideAttrs (o: { src = fetchTarball "https://gitlab.mpi-sws.org/iris/iris/-/archive/master/iris-master.tar.bz2"; propagatedBuildInputs = [ stdpp ]; }); in let unicoq = callPackage ./unicoq { inherit coq; }; in let StructTact = coqPackages.StructTact.overrideAttrs (o: { src = fetchTarball "https://github.com/uwplse/StructTact/tarball/master"; }); in let Cheerios = (coqPackages.Cheerios.override { inherit StructTact; }) .overrideAttrs (o: { src = fetchTarball "https://github.com/uwplse/cheerios/tarball/master"; }); in let Verdi = (coqPackages.Verdi.override { inherit Cheerios ssreflect; }) .overrideAttrs (o: { src = fetchTarball "https://github.com/uwplse/verdi/tarball/master"; }); in let flocq = coqPackages.flocq.overrideAttrs (o: { src = fetchTarball "https://gitlab.inria.fr/flocq/flocq/-/archive/master/flocq-master.tar.gz"; configurePhase = '' autoreconf ${bash}/bin/bash configure --libdir=$out/lib/coq/${coq.coq-version}/user-contrib/Flocq ''; buildPhase = '' ./remake ''; }); in let callPackage = newScope { inherit coq bignums coq-ext-lib coqprime corn iris math-classes mathcomp simple-io ssreflect stdpp unicoq Verdi flocq; }; in # Environments for building CI libraries with this Rocq let projects = { bedrock2 = callPackage ./bedrock2.nix {}; bignums = callPackage ./bignums.nix {}; CoLoR = callPackage ./CoLoR.nix {}; CompCert = callPackage ./CompCert.nix {}; coq_dpdgraph = callPackage ./coq_dpdgraph.nix {}; coquelicot = callPackage ./coquelicot.nix {}; Corn = callPackage ./Corn.nix {}; cross_crypto = callPackage ./cross_crypto.nix {}; Elpi = callPackage ./Elpi.nix {}; fiat_crypto = callPackage ./fiat_crypto.nix {}; flocq = callPackage ./flocq.nix {}; formal-topology = callPackage ./formal-topology.nix {}; HoTT = callPackage ./HoTT.nix {}; iris = callPackage ./iris.nix {}; lambda-rust = callPackage ./lambda-rust.nix {}; math_classes = callPackage ./math_classes.nix {}; mathcomp = {}; mtac2 = callPackage ./mtac2.nix {}; oddorder = callPackage ./oddorder.nix {}; quickchick = callPackage ./quickchick.nix {}; simple-io = callPackage ./simple-io.nix {}; verdi-raft = callPackage ./verdi-raft.nix {}; VST = callPackage ./VST.nix {}; }; in if !builtins.hasAttr project projects then throw "Unknown project β€œ${project}”; choose from: ${pkgs.lib.concatStringsSep ", " (builtins.attrNames projects)}." else let prj = projects."${project}"; in let inherit (stdenv.lib) optional optionals; in stdenv.mkDerivation { name = "shell-for-${project}-in-${branch}"; buildInputs = [ python ] ++ optional withCoq coq ++ (prj.buildInputs or []) ++ optionals withCoq (prj.coqBuildInputs or []) ; configure = prj.configure or "true"; make = prj.make or "make"; clean = prj.clean or "make clean"; } rocq-9.2.0/dev/ci/nix/fiat_crypto.nix000066400000000000000000000003231516144147600175070ustar00rootroot00000000000000{ ocamlPackages }: { buildInputs = with ocamlPackages; [ ocaml findlib ]; configure = "git submodule update --init --recursive && ulimit -s 32768"; make = "make c-files printlite lite && make -j 1 coq"; } rocq-9.2.0/dev/ci/nix/flocq.nix000066400000000000000000000002421516144147600162700ustar00rootroot00000000000000{ autoconf, automake }: { buildInputs = [ autoconf automake ]; configure = "./autogen.sh && ./configure"; make = "./remake"; clean = "./remake clean"; } rocq-9.2.0/dev/ci/nix/formal-topology.nix000066400000000000000000000000531516144147600203160ustar00rootroot00000000000000{ corn }: { coqBuildInputs = [ corn ]; } rocq-9.2.0/dev/ci/nix/iris.nix000066400000000000000000000000551516144147600161340ustar00rootroot00000000000000{ stdpp }: { coqBuildInputs = [ stdpp ]; } rocq-9.2.0/dev/ci/nix/lambda-rust.nix000066400000000000000000000000531516144147600173770ustar00rootroot00000000000000{ iris }: { coqBuildInputs = [ iris ]; } rocq-9.2.0/dev/ci/nix/math_classes.nix000066400000000000000000000001221516144147600176270ustar00rootroot00000000000000{ bignums }: { coqBuildInputs = [ bignums ]; configure = "./configure.sh"; } rocq-9.2.0/dev/ci/nix/mtac2.nix000066400000000000000000000002261516144147600161740ustar00rootroot00000000000000{ coq, unicoq }: { buildInputs = with coq.ocamlPackages; [ ocaml findlib camlp5 ]; coqBuildInputs = [ unicoq ]; configure = "./configure.sh"; } rocq-9.2.0/dev/ci/nix/oddorder.nix000066400000000000000000000000631516144147600167670ustar00rootroot00000000000000{ mathcomp }: { coqBuildInputs = [ mathcomp ]; } rocq-9.2.0/dev/ci/nix/quickchick.nix000066400000000000000000000002541516144147600173050ustar00rootroot00000000000000{ ocamlPackages, ssreflect, coq-ext-lib, simple-io }: { buildInputs = with ocamlPackages; [ ocaml findlib ocamlbuild num ]; coqBuildInputs = [ ssreflect simple-io ]; } rocq-9.2.0/dev/ci/nix/shell000077500000000000000000000007301516144147600155030ustar00rootroot00000000000000#!/usr/bin/env sh ## This file should be run from the root of the Rocq source tree BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "Branch: $BRANCH in $PWD" if [ "$#" -ne 1 ]; then PROJECT="" else PROJECT="--argstr project $1" fi if [ "$BN" ]; then BN="--argstr bn ${BN}" else BN="" fi 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 rocq-9.2.0/dev/ci/nix/simple-io.nix000066400000000000000000000002561516144147600170670ustar00rootroot00000000000000{ ocamlPackages, ssreflect, coq-ext-lib, simple-io }: { buildInputs = with ocamlPackages; [ ocaml findlib ocamlbuild num ]; coqBuildInputs = [ ssreflect coq-ext-lib ]; } rocq-9.2.0/dev/ci/nix/unicoq/000077500000000000000000000000001516144147600157445ustar00rootroot00000000000000rocq-9.2.0/dev/ci/nix/unicoq/default.nix000066400000000000000000000013641516144147600201140ustar00rootroot00000000000000{ stdenv, writeText, coq }: let META = writeText "META" '' archive(native) = "unicoq.cmxa" plugin(native) = "unicoq.cmxs" ''; in 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 = [ "ROCQLIB=$(out)/lib/coq/${coq.coq-version}/" ]; postInstall = '' cp ${META} META 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 ''; } rocq-9.2.0/dev/ci/nix/unicoq/unicoq-num.patch000066400000000000000000000005361516144147600210640ustar00rootroot00000000000000commit f29bc64ee3d8b36758d17e1f5d50812e0c93063b Author: Vincent Laporte Date: Thu Nov 29 08:59:22 2018 +0000 Make explicit dependency to num 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 rocq-9.2.0/dev/ci/nix/verdi-raft.nix000066400000000000000000000000551516144147600172310ustar00rootroot00000000000000{ Verdi }: { coqBuildInputs = [ Verdi ]; } rocq-9.2.0/dev/ci/platform/000077500000000000000000000000001516144147600154745ustar00rootroot00000000000000rocq-9.2.0/dev/ci/platform/coq-pf-01-sysinfo.bat000066400000000000000000000003051516144147600212550ustar00rootroot00000000000000REM Print some debug information ECHO "Root folders" DIR C:\ ECHO "Powershell version" powershell -Command "Get-Host" ECHO "Git installation of Mingw" DIR "C:\Program Files\Git\mingw64\bin\*.exe" rocq-9.2.0/dev/ci/platform/coq-pf-02-download.bat000066400000000000000000000002741516144147600214000ustar00rootroot00000000000000REM Download platform script SET PATH=%PATH%;C:\Program Files\7-Zip;C:\Program Files\Git\mingw64\bin ECHO "Downloading %PLATFORM%" curl -L -o platform.zip "%PLATFORM%" 7z x platform.zip rocq-9.2.0/dev/ci/platform/coq-pf-03-build.bat000066400000000000000000000020131516144147600206620ustar00rootroot00000000000000REM Build the platform SET CYGROOT=C:\ci\cygwin%ARCH% SET CYGCACHE=C:\ci\cache\cgwin REM Try CYGWIN_QUIET, but still this stage is super verbose SET CYGWIN_QUIET=y SET COQREGTESTING=y REM XXX: make this a variable with the branch name cd platform-* call coq_platform_make_windows.bat ^ -arch=%ARCH% ^ -pick=ci ^ -destcyg=%CYGROOT% ^ -cygcache=%CYGCACHE% ^ -extent=i ^ -parallel=p ^ -jobs=2 ^ -switch=d ^ -set-switch=y ^ -override-dev-pkg="rocq-runtime=%GITHUB_SERVER_URL%/%GITHUB_REPOSITORY%/archive/%GITHUB_SHA%.tar.gz" ^ -override-dev-pkg="rocq-core=%GITHUB_SERVER_URL%/%GITHUB_REPOSITORY%/archive/%GITHUB_SHA%.tar.gz" ^ -override-dev-pkg="coq-core=%GITHUB_SERVER_URL%/%GITHUB_REPOSITORY%/archive/%GITHUB_SHA%.tar.gz" ^ -override-dev-pkg="coqide-server=%GITHUB_SERVER_URL%/%GITHUB_REPOSITORY%/archive/%GITHUB_SHA%.tar.gz" ^ -override-dev-pkg="rocqide=%GITHUB_SERVER_URL%/%GITHUB_REPOSITORY%/archive/%GITHUB_SHA%.tar.gz" ^ || GOTO ErrorExit GOTO :EOF :ErrorExit ECHO ERROR %0 failed EXIT /b 1 rocq-9.2.0/dev/ci/platform/coq-pf-04-installer.bat000066400000000000000000000015751516144147600215750ustar00rootroot00000000000000REM build the installer artifact REM XXX: make this a variable with the branch name cd platform-* REM XXX: This is redundant with the previous scripts, we could centralize it REM In fact, the variable is only needed to access bash SET CYGROOT=C:\ci\cygwin%ARCH% SET BASH=%CYGROOT%\bin\bash MKDIR %GITHUB_WORKSPACE%\artifacts %BASH% --login -c "pwd && ls -la && cd /platform && windows/create_installer_windows.sh" || GOTO ErrorExit REM Output is in cygwin home; in general the script has a bit of a REM mess in terms of using the GITHUB_WORKSPACE sometimes, and the REM CYGWIN home some others. I use the path here directly as to avoid REM issues with quoting, which in the previous script required some REM really obscure code. COPY /v /b %CYGROOT%\platform\windows_installer\*.exe %GITHUB_WORKSPACE%\artifacts || GOTO ErrorExit GOTO :EOF :ErrorExit ECHO ERROR %0 failed EXIT /b 1 rocq-9.2.0/dev/ci/scripts/000077500000000000000000000000001516144147600153375ustar00rootroot00000000000000rocq-9.2.0/dev/ci/scripts/ci-aac_tactics.sh000066400000000000000000000003211516144147600205160ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download aac_tactics if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/aac_tactics" make make install ) rocq-9.2.0/dev/ci/scripts/ci-algebra_tactics.sh000066400000000000000000000004051516144147600213720ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download algebra_tactics if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/algebra_tactics" make make install ) rocq-9.2.0/dev/ci/scripts/ci-analysis.sh000066400000000000000000000005751516144147600201160ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download analysis if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/analysis" make -C classical make -C classical install make -C reals make -C reals install make -C theories make -C theories install make -C experimental_reals make -C experimental_reals install ) rocq-9.2.0/dev/ci/scripts/ci-analysis_stdlib.sh000066400000000000000000000004201516144147600214440ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/analysis" make -C reals_stdlib make -C reals_stdlib install make -C analysis_stdlib make -C analysis_stdlib install ) rocq-9.2.0/dev/ci/scripts/ci-argosy.sh000066400000000000000000000003121516144147600175640ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download argosy if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/argosy" make ) rocq-9.2.0/dev/ci/scripts/ci-async_test.sh000066400000000000000000000003171516144147600204410ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download async_test if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/async_test" make make install ) rocq-9.2.0/dev/ci/scripts/ci-atbr.sh000066400000000000000000000003031516144147600172100ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download atbr if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/atbr" make make install ) rocq-9.2.0/dev/ci/scripts/ci-autosubst.sh000066400000000000000000000003151516144147600203140ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download autosubst if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/autosubst" make make install ) rocq-9.2.0/dev/ci/scripts/ci-autosubst_ocaml.sh000066400000000000000000000005341516144147600214720ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download autosubst_ocaml if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/autosubst_ocaml" dune build @install -p coq-autosubst-ocaml dune install -p coq-autosubst-ocaml --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-bbv.sh000066400000000000000000000003011516144147600170270ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download bbv if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/bbv" make make install ) rocq-9.2.0/dev/ci/scripts/ci-bedrock2.sh000066400000000000000000000007221516144147600177600ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download bedrock2 if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi make_args=(EXTERNAL_COQUTIL=1 EXTERNAL_RISCV_COQ=1 EXTERNAL_KAMI=1) export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/bedrock2" COQMF_ARGS='-arg "-async-proofs-tac-j 1"' make "${make_args[@]}" bedrock2_ex compiler_noex make "${make_args[@]}" install_bedrock2_ex install_compiler ) rocq-9.2.0/dev/ci/scripts/ci-bedrock2_examples.sh000066400000000000000000000005521516144147600216570ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi make_args=(EXTERNAL_COQUTIL=1 EXTERNAL_RISCV_COQ=1 EXTERNAL_KAMI=1) export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/bedrock2" COQMF_ARGS='-arg "-async-proofs-tac-j 1"' make "${make_args[@]}" make "${make_args[@]}" ) rocq-9.2.0/dev/ci/scripts/ci-bigenough.sh000066400000000000000000000003151516144147600202320ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download bigenough if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/bigenough" make make install ) rocq-9.2.0/dev/ci/scripts/ci-bignums.sh000066400000000000000000000003331516144147600177270ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download bignums if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/bignums" make make install cd tests make ) rocq-9.2.0/dev/ci/scripts/ci-category_theory.sh000066400000000000000000000004041516144147600214710ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download category_theory if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/category_theory" make make install ) rocq-9.2.0/dev/ci/scripts/ci-ceres.sh000066400000000000000000000003131516144147600173620ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download ceres if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/ceres" make build make install ) rocq-9.2.0/dev/ci/scripts/ci-coinduction.sh000066400000000000000000000003211516144147600205760ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coinduction if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coinduction" make make install ) rocq-9.2.0/dev/ci/scripts/ci-color.sh000066400000000000000000000003411516144147600174000ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download color if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/color" make ) rocq-9.2.0/dev/ci/scripts/ci-common.sh000066400000000000000000000136511516144147600175620ustar00rootroot00000000000000#!/usr/bin/env bash if [ -z "${CI_QUIET}" ]; then set -x fi set -e # default value for NJOBS : "${NJOBS:=1}" export NJOBS . "$(dirname "${BASH_SOURCE[0]}")/../ci-env.sh" # Where we download and build external developments CI_BUILD_DIR="$PWD/_build_ci" declare -A overlays # overlay [] # creates an overlay for project using a given url and branch which is # active for prnumber or prbranch. prbranch defaults to ref. function overlay() { local project=$1 local ov_url=$2 local ov_ref=$3 local ov_prnumber=$4 local ov_prbranch=$5 : "${ov_prbranch:=$ov_ref}" if [ "$CI_PULL_REQUEST" = "$ov_prnumber" ] || [ "$CI_BRANCH" = "$ov_prbranch" ]; then if ! is_in_projects "$project"; then echo "Error: $1 is not a known project which can be overlayed" exit 1 fi overlays[${project}_URL]=$ov_url overlays[${project}_REF]=$ov_ref fi } set +x . "$(dirname "${BASH_SOURCE[0]}")/../ci-basic-overlay.sh" for overlay in "$(dirname "${BASH_SOURCE[0]}")"/../user-overlays/*.sh; do # shellcheck source=/dev/null # the directoy can be empty if [ -e "${overlay}" ]; then . "${overlay}"; fi done if [ -z "${CI_QUIET}" ]; then set -x fi # [git_download []] will download and # unpack it in (if given; default: # $CI_BUILD_DIR/) if the folder does not exist already; if it # does, it will do nothing except print a warning (this can be useful # when building locally). # Note: when there is an overlay, $WITH_SUBMODULES is set to 1 or $CI # is unset or empty (local build), it uses git clone to perform the # download. git_download() { local project=$1 local dest="${2:-$CI_BUILD_DIR/$project}" local giturl_var="${project}_CI_GITURL" local giturl="${!giturl_var}" local ref_var="${project}_CI_REF" local ref="${!ref_var}" local parent_project_var="${project}_CI_PARENT_PROJECT" local parent_project="${!parent_project_var}" local submodule_folder_var="${project}_CI_SUBMODULE_FOLDER" local submodule_folder="${!submodule_folder_var}" local ov_url=${overlays[${project}_URL]} local ov_ref=${overlays[${project}_REF]} local dest_prefix="$(dirname "$dest")/" if [ "${CI}${USE_CI_DIRECTORY_STRUCTURE}" = "" ]; then # we can reuse the parent project download when not on CI local parent_project_dest="$CI_BUILD_DIR/$parent_project" # we use relative symlinks so they are relocatable local parent_project_relative_dest="${parent_project_dest#$dest_prefix}" else # on CI, we need to ensure that there's no overlap in directory tree # between sibling jobs, since otherwise they will scribble over # each others .v timestamps and result in duplicated builds local parent_project_dest="${dest}-PARENT-${parent_project}" # we use relative symlinks so they are relocatable local parent_project_relative_dest="${parent_project_dest#$dest_prefix}" fi if [ -d "$dest" ]; then echo "Warning: download and unpacking of $project skipped because $dest already exists." elif [[ $ov_url ]] || [ "$WITH_SUBMODULES" = "1" ] || [ "$CI" = "" ] || [ -n "${parent_project}" ]; then if [ -n "${parent_project}" ]; then # if there is a parent project, we first download the parent # project then symlink the submodule_folder to dest; this allows # project CI scripts to be transparent w.r.t. whether or not the # project is cloned from a submodule / submodule_folder. if [ ! -d "${parent_project_dest}" ]; then WITH_SUBMODULES=1 git_download "${parent_project}" "${parent_project_dest}" fi # now we can create the symlinks ln -s "${parent_project_relative_dest}/${submodule_folder}" "$dest" pushd "$dest" ref="$(git rev-parse HEAD)" else # if $ref isn't a branch (eg it's a commit hash or a tag) git clone -b will fail # in that case do a full git clone git clone "$giturl" "$dest" -b "$ref" --depth 10 || git clone "$giturl" "$dest" pushd "$dest" git checkout "$ref" fi git log -n 1 if [[ $ov_url ]]; then # In CI we merge into the upstream branch to stay synchronized # Locally checkout the overlay and rebase on upstream # We act differently because merging is what will happen when the PR is merged # but rebasing produces something that is nicer to edit if [[ $CI ]]; then git -c pull.rebase=false -c user.email=nobody@example.invalid -c user.name=Nobody \ pull --no-edit --no-ff "$ov_url" "$ov_ref" git log -n 1 HEAD^2 || true # no merge commit if the overlay was merged upstream git log -n 1 else git remote add -t "$ov_ref" -f overlay "$ov_url" git checkout -b "$ov_ref" overlay/"$ov_ref" git rebase "$ref" git log -n 1 fi fi if [ "$WITH_SUBMODULES" = 1 ]; then git submodule update --init --recursive --depth 10 fi popd else # When possible, we download tarballs to reduce bandwidth and latency local archiveurl_var="${project}_CI_ARCHIVEURL" local archiveurl="${!archiveurl_var}" mkdir -p "$dest" pushd "$dest" local commit commit=$(git ls-remote "$giturl" "refs/heads/$ref" | cut -f 1) if [[ "$commit" == "" ]]; then # $ref must have been a tag or hash, not a branch commit="$ref" fi wget "$archiveurl/$commit.tar.gz" tar xfz "$commit.tar.gz" --strip-components=1 rm -f "$commit.tar.gz" popd fi } make() { # +x: add x only if defined if [ -z "${MAKEFLAGS+x}" ] && [ -n "${NJOBS}" ]; then # Not submake and parallel make requested command make -j "$NJOBS" "$@" else command make "$@" fi } # run make -k; make again if it failed so that the failing file comes last # makes it easier to find the error messages in the CI log function make_full() { if ! make -k "$@"; then make -k "$@"; exit 1; fi } rocq-9.2.0/dev/ci/scripts/ci-compcert.sh000066400000000000000000000012461516144147600201030ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download compcert if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi # CompCert does compile with -native-compiler yes # but with excessive memory requirements export COQCOPTS='-native-compiler no -w -undeclared-scope -w -omega-is-deprecated' ( cd "${CI_BUILD_DIR}/compcert" [ -e Makefile.config ] || ./configure -ignore-coq-version x86_32-linux -install-coqdev -clightgen -use-external-MenhirLib -use-external-Flocq -prefix ${CI_INSTALL_DIR} -coqdevdir ${CI_INSTALL_DIR}/lib/coq/user-contrib/compcert make make check-proof COQCHK='"$(COQBIN)coqchk" -silent -o $(COQINCLUDES)' make install ) rocq-9.2.0/dev/ci/scripts/ci-coq_dpdgraph.sh000066400000000000000000000003261516144147600207200ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coq_dpdgraph if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coq_dpdgraph" make make test-suite ) rocq-9.2.0/dev/ci/scripts/ci-coq_lsp.sh000066400000000000000000000011471516144147600177270ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coq_lsp if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi if [ -n "${GITLAB_CI}" ]; then export ROCQLIB="$PWD/_install_ci/lib/coq" export ROCQRUNTIMELIB="$PWD/_install_ci/lib/rocq-runtime" fi ( cd "${CI_BUILD_DIR}/coq_lsp" dune build --root . --only-packages=coq-lsp @install # Tests _build/install/default/bin/coq-lsp --version dune runtest --root . test/serlib dune runtest --root . test/compiler # It was needed by coq-serapi in CI, we keep it for now dune install -p coq-lsp --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-coq_performance_tests.sh000066400000000000000000000004121516144147600226460ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coq_performance_tests if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coq_performance_tests" make_full coq perf-Sanity make validate make install ) rocq-9.2.0/dev/ci/scripts/ci-coq_tools.sh000066400000000000000000000007711516144147600202730ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coq_tools if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi jason_msg() { echo "The build broke, if an overlay is needed, mention @JasonGross in describing the expected change in Rocq that needs to be taken into account, and he'll prepare a fix for coq-tools" exit $1 } ( cd "${CI_BUILD_DIR}/coq_tools" python -m venv .venv && . .venv/bin/activate && python -m pip install . make check || jason_msg $? ) rocq-9.2.0/dev/ci/scripts/ci-coqhammer.sh000066400000000000000000000003531516144147600202410ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coqhammer if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coqhammer" make tactics make install-tactics make plugin ) rocq-9.2.0/dev/ci/scripts/ci-coqprime.sh000066400000000000000000000003571516144147600201100ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coqprime if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ulimit -s ulimit -s 65536 ulimit -s ( cd "${CI_BUILD_DIR}/coqprime" make make install ) rocq-9.2.0/dev/ci/scripts/ci-coqtail.sh000066400000000000000000000003431516144147600177200ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coqtail if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coqtail" PYTHONPATH=python python3 -m pytest tests/coq ) rocq-9.2.0/dev/ci/scripts/ci-coquelicot.sh000066400000000000000000000004621516144147600204350ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download coquelicot if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/coquelicot" if ! [ -x ./configure ]; then autoreconf -i -s ./configure fi ./remake "-j${NJOBS}" ./remake install ) rocq-9.2.0/dev/ci/scripts/ci-coqutil.sh000066400000000000000000000004331516144147600177440ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download coqutil if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' # following bedrock2 ( cd "${CI_BUILD_DIR}/coqutil" make make install ) rocq-9.2.0/dev/ci/scripts/ci-corn.sh000066400000000000000000000003771516144147600172340ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download corn if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/corn" ./configure.sh make make install ) rocq-9.2.0/dev/ci/scripts/ci-cross_crypto.sh000066400000000000000000000003261516144147600210160ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download cross_crypto if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/cross_crypto" make ) rocq-9.2.0/dev/ci/scripts/ci-deriving.sh000066400000000000000000000003301516144147600200670ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download deriving if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/deriving" make make tests make install ) rocq-9.2.0/dev/ci/scripts/ci-elpi.sh000066400000000000000000000005151516144147600172160ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download elpi if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/elpi" touch dune-workspace make dune-files dune build --root . --only-packages=rocq-elpi @install dune install --root . rocq-elpi --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-elpi_test.sh000066400000000000000000000003071516144147600202540ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/elpi" make -j1 all-tests make -j1 all-examples ) rocq-9.2.0/dev/ci/scripts/ci-engine_bench.sh000066400000000000000000000004201516144147600206640ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download engine_bench if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler ondemand' ( cd "${CI_BUILD_DIR}/engine_bench" make coq make coq-perf-Sanity ) rocq-9.2.0/dev/ci/scripts/ci-equations.sh000066400000000000000000000005511516144147600202750ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download equations if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/equations" dune build --root . --only-packages rocq-equations dune install --root . --only-packages rocq-equations --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-equations_test.sh000066400000000000000000000004351516144147600213350ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/equations" dune build --root . --only-packages rocq-equations-tests,rocq-equations-examples ) rocq-9.2.0/dev/ci/scripts/ci-ext_lib.sh000066400000000000000000000003111516144147600177050ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download ext_lib if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/ext_lib" make make install ) rocq-9.2.0/dev/ci/scripts/ci-fcsl_pcm.sh000066400000000000000000000002741516144147600200550ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download fcsl_pcm if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/fcsl_pcm" make ) rocq-9.2.0/dev/ci/scripts/ci-fiat_crypto.sh000066400000000000000000000016501516144147600206110ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download fiat_crypto if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi # We need a larger stack size to not overflow ocamlopt+flambda when # building the executables. # c.f. https://github.com/rocq-prover/rocq/pull/8313#issuecomment-416650241 stacksize=32768 # fiat-crypto is not guaranteed to build with the latest version of # bedrock2, so we use the pinned version of bedrock2 (set in # ci-basic-overlay), but the external version of other developments make_args=(EXTERNAL_REWRITER=1 EXTERNAL_COQPRIME=1 EXTERNAL_COQUTIL=1 EXTERNAL_BEDROCK2=1) export COQEXTRAFLAGS='-native-compiler no' # following bedrock2 ( cd "${CI_BUILD_DIR}/fiat_crypto" ulimit -s $stacksize make "${make_args[@]}" pre-standalone-extracted printlite lite check-output || make -j 1 "${make_args[@]}" pre-standalone-extracted printlite lite check-output ) rocq-9.2.0/dev/ci/scripts/ci-fiat_crypto_legacy.sh000066400000000000000000000014121516144147600221310ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download fiat_crypto_legacy if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi targets1=( print-old-pipeline-lite-hardcoded old-pipeline-lite-hardcoded lite-display-hardcoded ) targets2=( print-old-pipeline-nobigmem-hardcoded old-pipeline-nobigmem-hardcoded nonautogenerated-specific nonautogenerated-specific-display selected-specific selected-specific-display ) # Use external dependencies to avoid building coqprime from scratch make_args=(EXTERNAL_DEPENDENCIES=1) export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/fiat_crypto_legacy" make "${make_args[@]}" "${targets1[@]}" make -j 1 "${make_args[@]}" "${targets2[@]}" ) rocq-9.2.0/dev/ci/scripts/ci-fiat_crypto_ocaml.sh000066400000000000000000000013431516144147600217630ustar00rootroot00000000000000#!/usr/bin/env bash set -e # fiat-crypto job sets up the sources if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" # We set the stack size to 128MiB to be able to build with flambda # See https://github.com/ocaml/ocaml/issues/7842 ulimit -s 131072 # Regardless of where the dependencies came from when building # ci-fiat_crypto, we don't need them for building the OCaml # binaries and lite C files, so we use all external dependencies. # we explicitly pass OCAMLFIND so that we pick up the opam # (non-flambda one) rather than the one used to build coq make_args=(EXTERNAL_DEPENDENCIES=1 OCAMLFIND=ocamlfind) ( cd "${CI_BUILD_DIR}/fiat_crypto" make "${make_args[@]}" -j 1 lite-c-files ) rocq-9.2.0/dev/ci/scripts/ci-fiat_parsers.sh000066400000000000000000000004441516144147600207500ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download fiat_parsers if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ulimit -s ulimit -s 65536 ulimit -s ( cd "${CI_BUILD_DIR}/fiat_parsers" make parsers parsers-examples make fiat-core ) rocq-9.2.0/dev/ci/scripts/ci-finmap.sh000066400000000000000000000003071516144147600175360ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download finmap if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/finmap" make make install ) rocq-9.2.0/dev/ci/scripts/ci-flocq.sh000066400000000000000000000004551516144147600173740ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download flocq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/flocq" if ! [ -x ./configure ]; then autoconf ./configure fi ./remake "-j${NJOBS}" ./remake install install-glob ) rocq-9.2.0/dev/ci/scripts/ci-fourcolor.sh000066400000000000000000000003151516144147600202750ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download fourcolor if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/fourcolor" make make install ) rocq-9.2.0/dev/ci/scripts/ci-hb.sh000066400000000000000000000003611516144147600166550ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download hierarchy_builder if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/hierarchy_builder" make config make build make install ) rocq-9.2.0/dev/ci/scripts/ci-hb_test.sh000066400000000000000000000002711516144147600177140ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/hierarchy_builder" make test-suite ) rocq-9.2.0/dev/ci/scripts/ci-hott.sh000066400000000000000000000003231516144147600172400ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download hott if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/hott" make make validate make install ) rocq-9.2.0/dev/ci/scripts/ci-http.sh000066400000000000000000000003401516144147600172400ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download http if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/http" make make INSTALLDIR="$CI_INSTALL_DIR" install ) rocq-9.2.0/dev/ci/scripts/ci-iris.sh000066400000000000000000000017741516144147600172430ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download iris_examples # Extract required version of Iris (avoiding "+" which does not work on MacOS :( *) iris_CI_REF=$(grep -F '"rocq-iris-heap-lang"' < "${CI_BUILD_DIR}/iris_examples/coq-iris-examples.opam" | sed 's/.*"dev\.[0-9][0-9.-]*\.\([0-9a-z][0-9a-z]*\)".*/\1/') [ -n "$iris_CI_REF" ] || { echo "Could not find Iris dependency version" && exit 1; } # Download Iris git_download iris # Extract required version of std++ stdpp_CI_REF=$(grep -F '"rocq-stdpp"' < "${CI_BUILD_DIR}/iris/rocq-iris.opam" | sed 's/.*"dev\.[0-9][0-9.-]*\.\([0-9a-z][0-9a-z]*\)".*/\1/') [ -n "$stdpp_CI_REF" ] || { echo "Could not find stdpp dependency version" && exit 1; } # Download std++ git_download stdpp if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi # Build ( cd "${CI_BUILD_DIR}/stdpp" make make install ) ( cd "${CI_BUILD_DIR}/iris" make make validate make install ) ( cd "${CI_BUILD_DIR}/iris_examples" make make install ) rocq-9.2.0/dev/ci/scripts/ci-itauto.sh000066400000000000000000000003631516144147600175730ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download itauto if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQCOPTS='-native-compiler ondemand' ( cd "${CI_BUILD_DIR}/itauto" make make install ) rocq-9.2.0/dev/ci/scripts/ci-itree.sh000066400000000000000000000003111516144147600173670ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download itree if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/itree" make all make install ) rocq-9.2.0/dev/ci/scripts/ci-itree_io.sh000066400000000000000000000003131516144147600200600ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download itree_io if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/itree_io" make make install ) rocq-9.2.0/dev/ci/scripts/ci-jasmin.sh000066400000000000000000000003561516144147600175510ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download jasmin if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/jasmin" make -C proofs ) rocq-9.2.0/dev/ci/scripts/ci-json.sh000066400000000000000000000004031516144147600172320ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download json if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/json" dune build -p coq-json @install dune install -p coq-json --prefix=$CI_INSTALL_DIR ) rocq-9.2.0/dev/ci/scripts/ci-kami.sh000066400000000000000000000004251516144147600172060ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download kami if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' # following bedrock2 ( cd "${CI_BUILD_DIR}/kami" make make install ) rocq-9.2.0/dev/ci/scripts/ci-lean_importer.sh000066400000000000000000000004151516144147600211240ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download lean_importer if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/lean_importer" make .merlin make make test ) rocq-9.2.0/dev/ci/scripts/ci-ltac2_compiler.sh000066400000000000000000000004361516144147600211660ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download ltac2_compiler if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/ltac2_compiler" make .merlin make make test make install ) rocq-9.2.0/dev/ci/scripts/ci-math_classes.sh000066400000000000000000000003441516144147600207330ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download math_classes if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/math_classes" ./configure.sh make make install ) rocq-9.2.0/dev/ci/scripts/ci-mathcomp.sh000066400000000000000000000003131516144147600200710ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download mathcomp if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/mathcomp" make make install ) rocq-9.2.0/dev/ci/scripts/ci-mathcomp_test.sh000066400000000000000000000002601516144147600211310ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/mathcomp" make test-suite ) rocq-9.2.0/dev/ci/scripts/ci-mathcomp_word.sh000066400000000000000000000004511516144147600211270ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download mathcomp_word if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/mathcomp_word" dune build @install -p coq-mathcomp-word dune install -p coq-mathcomp-word --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-mczify.sh000066400000000000000000000003071516144147600175650ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download mczify if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/mczify" make make install ) rocq-9.2.0/dev/ci/scripts/ci-menhir.sh000066400000000000000000000006641516144147600175540ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download menhirlib if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/menhirlib" if grep -q unreleased dune-project; then date=$(date +%Y%m%d) sed -i.bak "s/unreleased/$date/" dune-project echo "Definition require_$date := tt." > coq-menhirlib/src/Version.v fi make -C coq-menhirlib make -C coq-menhirlib install ) rocq-9.2.0/dev/ci/scripts/ci-metarocq.sh000066400000000000000000000006211516144147600200760ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download metarocq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/metarocq" [ -e pcuic/metarocq-config ] || ./configure.sh local make template-rocq TIMED=pretty-timed make all TIMED=pretty-timed make test-suite TIMED=pretty-timed make install ) rocq-9.2.0/dev/ci/scripts/ci-mtac2.sh000066400000000000000000000003571516144147600172770ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download mtac2 if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/mtac2" coq_makefile -f _CoqProject -o Makefile make .merlin make ) rocq-9.2.0/dev/ci/scripts/ci-neural_net_interp.sh000066400000000000000000000003341516144147600220010ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download neural_net_interp if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/neural_net_interp" make coq-ci-target ) rocq-9.2.0/dev/ci/scripts/ci-oddorder.sh000066400000000000000000000003131516144147600200630ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download oddorder if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/oddorder" make make install ) rocq-9.2.0/dev/ci/scripts/ci-paco.sh000066400000000000000000000003271516144147600172100ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download paco if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/paco/src" make make -f Makefile.coq install ) rocq-9.2.0/dev/ci/scripts/ci-paramcoq.sh000066400000000000000000000003531516144147600200700ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download paramcoq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/paramcoq" make make install cd test-suite make examples ) rocq-9.2.0/dev/ci/scripts/ci-parsec.sh000066400000000000000000000004131516144147600175370ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download parsec if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/parsec" dune build -p coq-parsec @install dune install -p coq-parsec --prefix=$CI_INSTALL_DIR ) rocq-9.2.0/dev/ci/scripts/ci-perennial.sh000066400000000000000000000004051516144147600202400ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download perennial if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ulimit -s ulimit -s 65536 ulimit -s ( cd "${CI_BUILD_DIR}/perennial" make TIMED=false lite ) rocq-9.2.0/dev/ci/scripts/ci-quickchick.sh000066400000000000000000000004671516144147600204110ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download quickchick if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/quickchick" dune build --root . --only-packages=coq-quickchick @install dune install --root . coq-quickchick --prefix=$CI_INSTALL_DIR ) rocq-9.2.0/dev/ci/scripts/ci-quickchick_test.sh000066400000000000000000000003721516144147600214430ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/quickchick" dune build --root . --only-packages=coq-quickchick @runtest @cram --stop-on-first-error ) rocq-9.2.0/dev/ci/scripts/ci-reduction_effects.sh000066400000000000000000000003511516144147600217560ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download reduction_effects if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/reduction_effects" make make test make install ) rocq-9.2.0/dev/ci/scripts/ci-refman.sh000066400000000000000000000005041516144147600175330ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi sed -i.bak doc/dune -e '/package coq-core/ d' sed -i.bak doc/dune -e '/package rocq-core/ d' ROCQRST_EXTRA=all dune build --no-buffer @refman-html ROCQRST_EXTRA=all dune build --no-buffer @refman-pdf rocq-9.2.0/dev/ci/scripts/ci-relation_algebra.sh000066400000000000000000000004261516144147600215600ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download relation_algebra if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/relation_algebra" make .merlin make make install ) rocq-9.2.0/dev/ci/scripts/ci-rewriter.sh000066400000000000000000000003131516144147600201240ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download rewriter if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/rewriter" make make install ) rocq-9.2.0/dev/ci/scripts/ci-riscv_coq.sh000066400000000000000000000005471516144147600202620ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download riscv_coq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi make_args=(EXTERNAL_COQUTIL=1) export COQEXTRAFLAGS='-native-compiler no' # following bedrock2 ( cd "${CI_BUILD_DIR}/riscv_coq" make "${make_args[@]}" all make "${make_args[@]}" install ) rocq-9.2.0/dev/ci/scripts/ci-rupicola.sh000066400000000000000000000005651516144147600201100ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" WITH_SUBMODULES=1 git_download rupicola if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi make_args=(EXTERNAL_COQUTIL=1 EXTERNAL_BEDROCK2=1) export COQEXTRAFLAGS='-native-compiler no' # following bedrock2 ( cd "${CI_BUILD_DIR}/rupicola" make "${make_args[@]}" make "${make_args[@]}" install ) rocq-9.2.0/dev/ci/scripts/ci-sf.sh000066400000000000000000000004751516144147600167020ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download sf if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi cd "$CI_BUILD_DIR/sf" ( cd lf-current make ) ( cd plf-current make ) ( cd vfa-current make ) ( cd slf-current make ) # ( cd qc-current # make clean # make # ) rocq-9.2.0/dev/ci/scripts/ci-simple_io.sh000066400000000000000000000004271516144147600202470ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download simple_io if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/simple_io" dune build -p coq-simple-io @install dune install -p coq-simple-io --prefix=$CI_INSTALL_DIR ) rocq-9.2.0/dev/ci/scripts/ci-smtcoq.sh000066400000000000000000000003351516144147600175730ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download smtcoq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/smtcoq" make -C src .merlin make make install ) rocq-9.2.0/dev/ci/scripts/ci-smtcoq_trakt.sh000066400000000000000000000003511516144147600207760ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download smtcoq_trakt if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/smtcoq_trakt" make -C src .merlin make make install ) rocq-9.2.0/dev/ci/scripts/ci-stalmarck.sh000066400000000000000000000006211516144147600202440ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download stalmarck if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/stalmarck" make make install rm -f coq-stalmarck.opam # work around https://github.com/ocaml/dune/issues/4814 dune build @install -p coq-stalmarck-tactic dune install -p coq-stalmarck-tactic --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-stdlib.sh000066400000000000000000000005271516144147600175510ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download stdlib if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/stdlib" dev/with-rocq-wrap.sh dune build --root . --only-packages=rocq-stdlib @install dev/with-rocq-wrap.sh dune install --root . rocq-stdlib --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-stdlib_doc.sh000066400000000000000000000003021516144147600203650ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/stdlib" make refman-html make stdlib-html ) rocq-9.2.0/dev/ci/scripts/ci-stdlib_test.sh000066400000000000000000000002561516144147600206070ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/stdlib/test-suite" make ) rocq-9.2.0/dev/ci/scripts/ci-tactician.sh000077500000000000000000000003371516144147600202310ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download tactician if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/tactician" dune build --root . theories/Ltac1.vo ) rocq-9.2.0/dev/ci/scripts/ci-tlc.sh000066400000000000000000000003011516144147600170400ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download tlc if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/tlc" make make install ) rocq-9.2.0/dev/ci/scripts/ci-trakt.sh000066400000000000000000000003051516144147600174070ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download trakt if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/trakt" make make install ) rocq-9.2.0/dev/ci/scripts/ci-unicoq.sh000066400000000000000000000004001516144147600175540ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download unicoq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/unicoq" coq_makefile -f _CoqProject -o Makefile make .merlin make make install ) rocq-9.2.0/dev/ci/scripts/ci-unimath.sh000066400000000000000000000010061516144147600177260ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download unimath if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/unimath" # these files consumes too much memory for the shared workers # (at least with -j 2 when the scheduler runs them in parallel) for p in SubstitutionSystems Bicategories ModelCategories; do sed -i.bak "s|PACKAGES += $p||" Makefile done make BUILD_COQ=no make BUILD_COQ=no install ) rocq-9.2.0/dev/ci/scripts/ci-verdi_raft.sh000066400000000000000000000010021516144147600204020ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download struct_tact git_download inf_seq_ext git_download cheerios git_download verdi git_download verdi_raft if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/struct_tact" make make install ) ( cd "${CI_BUILD_DIR}/inf_seq_ext" make make install ) ( cd "${CI_BUILD_DIR}/cheerios" make make install ) ( cd "${CI_BUILD_DIR}/verdi" make make install ) ( cd "${CI_BUILD_DIR}/verdi_raft" make ) rocq-9.2.0/dev/ci/scripts/ci-vsrocq.sh000066400000000000000000000010041516144147600175740ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download vsrocq if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi if [ -n "${GITLAB_CI}" ]; then export ROCQLIB="$PWD/_install_ci/lib/coq" export ROCQRUNTIMELIB="$PWD/_install_ci/lib/rocq-runtime" fi ( cd "$CI_BUILD_DIR/vsrocq/language-server" make dune-files dune build --root . --only-packages=vsrocq-language-server @install dune runtest --root . dune install --root . vsrocq-language-server --prefix="$CI_INSTALL_DIR" ) rocq-9.2.0/dev/ci/scripts/ci-vst.sh000066400000000000000000000010011516144147600170700ustar00rootroot00000000000000#!/usr/bin/env bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download vst if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi # sometimes (rarely) CompCert master can break VST and it can take # weeks or months for VST to catch up, in this case, just uncomment # the line below to use the compcert version bundled in VST # export COMPCERT=bundled # See ci-compcert.sh export COQEXTRAFLAGS='-native-compiler no' ( cd "${CI_BUILD_DIR}/vst" make IGNORECOQVERSION=true IGNORECOMPCERTVERSION=true ) rocq-9.2.0/dev/ci/scripts/ci-waterproof.sh000066400000000000000000000004571516144147600204620ustar00rootroot00000000000000#!/usr/bin/env/ bash set -e ci_dir="$(dirname "$0")" . "${ci_dir}/ci-common.sh" git_download waterproof if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi ( cd "${CI_BUILD_DIR}/waterproof" dune build --root . --only-packages=coq-waterproof dune install --root . coq-waterproof --prefix=$CI_INSTALL_DIR ) rocq-9.2.0/dev/ci/user-overlays/000077500000000000000000000000001516144147600164705ustar00rootroot00000000000000rocq-9.2.0/dev/ci/user-overlays/20506-jrosain-elimination-constraints-graph.sh000066400000000000000000000002701516144147600271140ustar00rootroot00000000000000overlay coq_lsp https://github.com/jrosain/rocq-lsp elimination-constraints-graph 20506 overlay equations https://github.com/jrosain/Rocq-Equations elimination-constraint-graph 20506 rocq-9.2.0/dev/ci/user-overlays/20606-SkySkimmer-clean-flags.sh000066400000000000000000000001051516144147600237430ustar00rootroot00000000000000overlay vsrocq https://github.com/SkySkimmer/vscoq clean-flags 20606 rocq-9.2.0/dev/ci/user-overlays/20809-ppedrot-autonaming-goals.sh000066400000000000000000000001221516144147600244170ustar00rootroot00000000000000overlay tactician https://github.com/ppedrot/coq-tactician autonaming-goals 20809 rocq-9.2.0/dev/ci/user-overlays/20812-SkySkimmer-extensible-attributes.sh000066400000000000000000000001161516144147600261160ustar00rootroot00000000000000overlay mtac2 https://github.com/SkySkimmer/Mtac2 extensible-attributes 20812 rocq-9.2.0/dev/ci/user-overlays/20953-SkySkimer-warn-more-tolerance.sh000066400000000000000000000001061516144147600253010ustar00rootroot00000000000000overlay mathcomp https://github.com/proux01/math-comp rocq20953 20953 rocq-9.2.0/dev/ci/user-overlays/21016-rlepigre-skylabs-ai-fold_abbreviations.sh000066400000000000000000000001261516144147600271720ustar00rootroot00000000000000overlay elpi https://github.com/rlepigre-skylabs-ai/coq-elpi fold_abbreviations 21016 rocq-9.2.0/dev/ci/user-overlays/21069-SkySkimmer-mip-mind-record.sh000066400000000000000000000005021516144147600245620ustar00rootroot00000000000000overlay metarocq https://github.com/SkySkimmer/metarocq mip-mind-record 21069 overlay lean_importer https://github.com/SkySkimmer/rocq-lean-import mip-mind-record 21069 overlay elpi https://github.com/SkySkimmer/coq-elpi mip-mind-record 21069 overlay coq_lsp https://github.com/SkySkimmer/coq-lsp mip-mind-record 21069 rocq-9.2.0/dev/ci/user-overlays/21097-Yann-Leray-einstance.sh000066400000000000000000000004671516144147600234410ustar00rootroot00000000000000overlay elpi https://github.com/Yann-Leray/coq-elpi einstance 21097 overlay equations https://github.com/Yann-Leray/Coq-Equations einstance 21097 overlay paramcoq https://github.com/Yann-Leray/paramcoq einstance 21097 overlay reduction_effects https://github.com/Yann-Leray/reduction-effects einstance 21097 rocq-9.2.0/dev/ci/user-overlays/21098-tabareau-sortpoly-equality.sh000066400000000000000000000001061516144147600250120ustar00rootroot00000000000000overlay hott https://github.com/tabareau/HoTT sortpoly-equality 21098 rocq-9.2.0/dev/ci/user-overlays/21107-proux01-test-strict-right-assoc.sh000066400000000000000000000001011516144147600255060ustar00rootroot00000000000000overlay stdlib https://github.com/proux01/stdlib rocq21107 21107 rocq-9.2.0/dev/ci/user-overlays/21110-ppedrot-proof-solve-explicit-env.sh000066400000000000000000000006541516144147600260260ustar00rootroot00000000000000overlay coq_lsp https://github.com/ppedrot/coq-lsp proof-solve-explicit-env 21110 overlay equations https://github.com/ppedrot/Coq-Equations proof-solve-explicit-env 21110 overlay mtac2 https://github.com/ppedrot/Mtac2 proof-solve-explicit-env 21110 overlay rewriter https://github.com/ppedrot/rewriter proof-solve-explicit-env 21110 overlay tactician https://github.com/ppedrot/coq-tactician proof-solve-explicit-env 21110 rocq-9.2.0/dev/ci/user-overlays/21126-ia0-assoc.sh000066400000000000000000000002261516144147600212540ustar00rootroot00000000000000overlay coq_lsp https://github.com/proux01/coq-lsp rocq21126 21126 overlay autosubst_ocaml https://github.com/proux01/autosubst-ocaml rocq21126 21126 rocq-9.2.0/dev/ci/user-overlays/21149-SkySkimmer-timeout-exns.sh000066400000000000000000000003761516144147600242450ustar00rootroot00000000000000overlay lean_importer https://github.com/SkySkimmer/rocq-lean-import timeout-exns 21149 overlay waterproof https://github.com/SkySkimmer/coq-waterproof timeout-exns 21149 overlay tactician https://github.com/SkySkimmer/coq-tactician timeout-exns 21149 rocq-9.2.0/dev/ci/user-overlays/21159-proux01-refine-common-prefix.sh000066400000000000000000000001011516144147600250400ustar00rootroot00000000000000overlay stdlib https://github.com/proux01/stdlib rocq21159 21159 rocq-9.2.0/dev/ci/user-overlays/21161-tabareau-parametrize-typeclass_db-.sh000066400000000000000000000001221516144147600263230ustar00rootroot00000000000000overlay elpi https://github.com/tabareau/coq-elpi parametrize-typeclass_db- 21161 rocq-9.2.0/dev/ci/user-overlays/21163-SkySkimmer-scheme-attr.sh000066400000000000000000000001061516144147600240030ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi scheme-attr 21163 rocq-9.2.0/dev/ci/user-overlays/21174-SkySkimmer-nolab.sh000066400000000000000000000003321516144147600226650ustar00rootroot00000000000000overlay coq_lsp https://github.com/SkySkimmer/coq-lsp nolab 21174 overlay tactician https://github.com/SkySkimmer/coq-tactician nolab 21174 overlay waterproof https://github.com/SkySkimmer/coq-waterproof nolab 21174 rocq-9.2.0/dev/ci/user-overlays/21175-SkySkimmer-ass-lab.sh000066400000000000000000000001061516144147600231140ustar00rootroot00000000000000overlay paramcoq https://github.com/SkySkimmer/paramcoq ass-lab 21175 rocq-9.2.0/dev/ci/user-overlays/21182-ppedrot-rm-canord-structures-indmap.sh000066400000000000000000000002451516144147600265240ustar00rootroot00000000000000overlay elpi https://github.com/ppedrot/coq-elpi rm-canord-structures-indmap 21182 overlay mtac2 https://github.com/ppedrot/Mtac2 rm-canord-structures-indmap 21182 rocq-9.2.0/dev/ci/user-overlays/21193-ppedrot-factor-tc-hint-exact.sh000066400000000000000000000001201516144147600250710ustar00rootroot00000000000000overlay metarocq https://github.com/ppedrot/metarocq factor-tc-hint-exact 21193 rocq-9.2.0/dev/ci/user-overlays/21195-jrosain-elimination-constraints.sh000066400000000000000000000020221516144147600260170ustar00rootroot00000000000000overlay equations https://github.com/jrosain/Rocq-Equations elimination-constraints 21195 overlay coq_dpdgraph https://github.com/jrosain/rocq-dpdgraph elimination-constraints 21195 overlay lean_importer https://github.com/jrosain/rocq-lean-import elimination-constraints 21195 overlay mtac2 https://github.com/jrosain/Mtac2 elimination-constraints 21195 overlay paramcoq https://github.com/jrosain/paramcoq elimination-constraints 21195 overlay rewriter https://github.com/jrosain/rewriter elimination-constraints 21195 overlay tactician https://github.com/jrosain/rocq-tactician elimination-constraints 21195 overlay waterproof https://github.com/jrosain/rocq-waterproof elimination-constraints 21195 overlay coq_lsp https://github.com/jrosain/rocq-lsp elimination-constraints 21195 overlay metarocq https://github.com/jrosain/metarocq elimination-constraints 21195 overlay elpi https://github.com/TDiazT/coq-elpi elimination-constraints 21195 overlay itauto https://gitlab.inria.fr/tdiaztro/itauto elimination-constraints 21195 rocq-9.2.0/dev/ci/user-overlays/21211-proux01-parray-notation.sh000066400000000000000000000001331516144147600241300ustar00rootroot00000000000000overlay neural_net_interp https://github.com/proux01/neural-net-coq-interp rocq21211 21211 rocq-9.2.0/dev/ci/user-overlays/21228-SkySkimmer-not-enough-abs.sh000066400000000000000000000001111516144147600244130ustar00rootroot00000000000000overlay stdlib https://github.com/SkySkimmer/stdlib not-enough-abs 21228 rocq-9.2.0/dev/ci/user-overlays/21241-SkySkimmer-no-opt-schemes.sh000066400000000000000000000010061516144147600244250ustar00rootroot00000000000000overlay stdlib https://github.com/SkySkimmer/stdlib no-opt-schemes 21241 overlay bbv https://github.com/SkySkimmer/bbv no-opt-schemes 21241 overlay kami https://github.com/SkySkimmer/kami no-opt-schemes 21241 # Make PRs against https://github.com/mit-plv/kami base branch rv32i overlay bedrock2 https://github.com/SkySkimmer/bedrock2 no-opt-schemes 21241 # Make PRs against https://github.com/mit-plv/bedrock2 base branch master overlay coq_dpdgraph https://github.com/SkySkimmer/coq-dpdgraph no-opt-schemes 21241 rocq-9.2.0/dev/ci/user-overlays/21243-ppedrot-side-effect-abstract-evd-api.sh000066400000000000000000000001361516144147600264520ustar00rootroot00000000000000overlay tactician https://github.com/ppedrot/coq-tactician side-effect-abstract-evd-api 21243 rocq-9.2.0/dev/ci/user-overlays/21245-SkySkimmer-no-auto-scheme.sh000066400000000000000000000002511516144147600244150ustar00rootroot00000000000000overlay category_theory https://github.com/SkySkimmer/category-theory no-auto-scheme 21248 overlay metarocq https://github.com/SkySkimmer/metarocq no-auto-scheme 21248 rocq-9.2.0/dev/ci/user-overlays/21254-SkySkimmer-stop-anomalies.sh000066400000000000000000000003511516144147600245250ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi stop-anomalies 21254 overlay equations https://github.com/SkySkimmer/Coq-Equations stop-anomalies 21254 overlay coq_lsp https://github.com/SkySkimmer/coq-lsp stop-anomalies 21254 rocq-9.2.0/dev/ci/user-overlays/21268-SkySkimmer-rm-unused-metaashole.sh000066400000000000000000000001171516144147600256360ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi rm-unused-metaashole 21268 rocq-9.2.0/dev/ci/user-overlays/21275-SkySkimmer-extern-print-univs.sh000066400000000000000000000002451516144147600254000ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi extern-print-univs 21275 overlay tactician https://github.com/SkySkimmer/coq-tactician extern-print-univs 21275 rocq-9.2.0/dev/ci/user-overlays/21276-SkySkimmer-reserve-env.sh000066400000000000000000000001061516144147600240350ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi reserve-env 21276 rocq-9.2.0/dev/ci/user-overlays/21277-SkySkimmer-extern-env-record.sh000066400000000000000000000001261516144147600251460ustar00rootroot00000000000000overlay tactician https://github.com/SkySkimmer/coq-tactician extern-env-record 21277 rocq-9.2.0/dev/ci/user-overlays/21281-SkySkimmer-print-flags.sh000066400000000000000000000015301516144147600240200ustar00rootroot00000000000000overlay simple_io https://github.com/SkySkimmer/coq-simple-io print-flags 21281 overlay autosubst_ocaml https://github.com/SkySkimmer/autosubst-ocaml print-flags 21281 overlay coq_lsp https://github.com/SkySkimmer/coq-lsp print-flags 21281 overlay coqhammer https://github.com/SkySkimmer/coqhammer print-flags 21281 overlay elpi https://github.com/SkySkimmer/coq-elpi print-flags 21281 overlay equations https://github.com/SkySkimmer/Coq-Equations print-flags 21281 overlay smtcoq https://github.com/SkySkimmer/smtcoq print-flags 21281 overlay tactician https://github.com/SkySkimmer/coq-tactician print-flags 21281 overlay vsrocq https://github.com/SkySkimmer/vsrocq print-flags 21281 overlay waterproof https://github.com/SkySkimmer/coq-waterproof print-flags 21281 overlay quickchick https://github.com/SkySkimmer/QuickChick print-flags 21281 rocq-9.2.0/dev/ci/user-overlays/21287-ppedrot-genredexpr-open-api.sh000066400000000000000000000003571516144147600250360ustar00rootroot00000000000000overlay coq_lsp https://github.com/ppedrot/coq-lsp genredexpr-open-api 21287 overlay elpi https://github.com/ppedrot/coq-elpi genredexpr-open-api 21287 overlay tactician https://github.com/ppedrot/coq-tactician genredexpr-open-api 21287 rocq-9.2.0/dev/ci/user-overlays/21326-thomas-lamiaux-indtab_globref.sh000066400000000000000000000001151516144147600253640ustar00rootroot00000000000000overlay elpi https://github.com/thomas-lamiaux/coq-elpi indtab_globref 21326 rocq-9.2.0/dev/ci/user-overlays/21342-SkySkimmer-print-raw.sh000066400000000000000000000001041516144147600235070ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi print-raw 21342 rocq-9.2.0/dev/ci/user-overlays/21347-SkySkimmer-ignore-keywords.sh000066400000000000000000000001121516144147600247200ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi ignore-keywords 21347 rocq-9.2.0/dev/ci/user-overlays/21365-SkySkimmer-declmods-compat.sh000066400000000000000000000002311516144147600246450ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi declmods-compat 21365 overlay paramcoq https://github.com/SkySkimmer/paramcoq declmods-compat 21365 rocq-9.2.0/dev/ci/user-overlays/21366-ppedrot-evar-names-use-full-path.sh000066400000000000000000000002651516144147600257030ustar00rootroot00000000000000overlay equations https://github.com/ppedrot/Coq-Equations evar-names-use-full-path 21366 overlay tactician https://github.com/ppedrot/coq-tactician evar-names-use-full-path 21366 rocq-9.2.0/dev/ci/user-overlays/21381-ppedrot-rm-deprecated-intro-pattern.sh000066400000000000000000000002731516144147600264750ustar00rootroot00000000000000overlay equations https://github.com/ppedrot/Coq-Equations rm-deprecated-intro-pattern 21381 overlay tactician https://github.com/ppedrot/coq-tactician rm-deprecated-intro-pattern 21381 rocq-9.2.0/dev/ci/user-overlays/21384-ppedrot-declare-clear-cruft.sh000066400000000000000000000002451516144147600247630ustar00rootroot00000000000000overlay equations https://github.com/ppedrot/Coq-Equations declare-clear-cruft 21384 overlay metarocq https://github.com/ppedrot/metarocq declare-clear-cruft 21384 rocq-9.2.0/dev/ci/user-overlays/21391-ppedrot-reintroduce-univ-contextset.sh000066400000000000000000000011701516144147600266530ustar00rootroot00000000000000overlay equations https://github.com/ppedrot/Coq-Equations reintroduce-univ-contextset 21391 overlay lean_importer https://github.com/ppedrot/rocq-lean-import reintroduce-univ-contextset 21391 overlay mtac2 https://github.com/ppedrot/Mtac2 reintroduce-univ-contextset 21391 overlay waterproof https://github.com/ppedrot/coq-waterproof reintroduce-univ-contextset 21391 overlay elpi https://github.com/ppedrot/coq-elpi reintroduce-univ-contextset 21391 overlay rewriter https://github.com/ppedrot/rewriter reintroduce-univ-contextset 21391 overlay metarocq https://github.com/ppedrot/metarocq reintroduce-univ-contextset 21391 rocq-9.2.0/dev/ci/user-overlays/21394-ppedrot-reduce-pcontext-api.sh000066400000000000000000000007331516144147600250420ustar00rootroot00000000000000overlay elpi https://github.com/ppedrot/coq-elpi reduce-pcontext-api 21394 overlay equations https://github.com/ppedrot/Coq-Equations reduce-pcontext-api 21394 overlay mtac2 https://github.com/ppedrot/Mtac2 reduce-pcontext-api 21394 overlay paramcoq https://github.com/ppedrot/paramcoq reduce-pcontext-api 21394 overlay rewriter https://github.com/ppedrot/rewriter reduce-pcontext-api 21394 overlay metarocq https://github.com/ppedrot/metarocq reduce-pcontext-api 21394 rocq-9.2.0/dev/ci/user-overlays/21395-SkySkimmer-univ-decl.sh000066400000000000000000000003341516144147600234670ustar00rootroot00000000000000overlay elpi https://github.com/SkySkimmer/coq-elpi univ-decl 21395 overlay equations https://github.com/SkySkimmer/Coq-Equations univ-decl 21395 overlay rewriter https://github.com/SkySkimmer/rewriter univ-decl 21395 rocq-9.2.0/dev/ci/user-overlays/21417-mattam82-elab-elim-constraints.sh000066400000000000000000000001161516144147600253250ustar00rootroot00000000000000overlay elpi https://github.com/mattam82/coq-elpi elab-elim-constraints 21417 rocq-9.2.0/dev/ci/user-overlays/21419-mattam82-sort-poly-flags.sh000066400000000000000000000015141516144147600242000ustar00rootroot00000000000000overlay equations https://github.com/mattam82/Coq-Equations sort-poly-flags 21419 overlay rewriter https://github.com/mattam82/rewriter sort-poly-flags 21419 overlay smtcoq https://github.com/mattam82/smtcoq sort-poly-flags 21419 overlay mtac2 https://github.com/mattam82/Mtac2 sort-poly-flags 21419 overlay elpi https://github.com/mattam82/coq-elpi sort-poly-flags 21419 overlay simple_io https://github.com/mattam82/coq-simple-io sort-poly-flags 21419 overlay paramcoq https://github.com/mattam82/paramcoq sort-poly-flags 21419 overlay waterproof https://github.com/mattam82/coq-waterproof sort-poly-flags 21419 overlay itauto https://gitlab.inria.fr/sozeau/itauto sort-poly-flags 21419 overlay metarocq https://github.com/mattam82/metacoq sort-poly-flags 21419 overlay quickchick https://github.com/mattam82/quickchick sort-poly-flags 21419 rocq-9.2.0/dev/ci/user-overlays/21424-ppedrot-chase-pconstraint-context-set.sh000066400000000000000000000001251516144147600270470ustar00rootroot00000000000000overlay elpi https://github.com/ppedrot/coq-elpi chase-pconstraint-context-set 21424 rocq-9.2.0/dev/ci/user-overlays/21426-ppedrot-chase-pconstraint-context-set-II.sh000066400000000000000000000004511516144147600273520ustar00rootroot00000000000000overlay equations https://github.com/ppedrot/Coq-Equations chase-pconstraint-context-set-II 21426 overlay lean_importer https://github.com/ppedrot/rocq-lean-import chase-pconstraint-context-set-II 21426 overlay metarocq https://github.com/ppedrot/metarocq chase-pconstraint-context-set-II 21426 rocq-9.2.0/dev/ci/user-overlays/21438-TDiazT-primitive-postponed-eta.sh000066400000000000000000000002611516144147600254270ustar00rootroot00000000000000overlay metarocq https://github.com/TDiazT/metarocq primitive-postponed-eta 21438 overlay lean_importer https://github.com/TDiazT/rocq-lean-import primitive-postponed-eta 21438 rocq-9.2.0/dev/ci/user-overlays/21467-ppedrot-centralize-declare-build-by-tactic.sh000066400000000000000000000002671516144147600276740ustar00rootroot00000000000000overlay mtac2 https://github.com/ppedrot/Mtac2 centralize-declare-build-by-tactic 21467 overlay rewriter https://github.com/ppedrot/rewriter centralize-declare-build-by-tactic 21467 rocq-9.2.0/dev/ci/user-overlays/21477-JasonGross-print-assumptions-list.sh000066400000000000000000000002521516144147600262630ustar00rootroot00000000000000overlay paramcoq https://github.com/JasonGross/paramcoq print-assumptions-list 21477 overlay metarocq https://github.com/JasonGross/metacoq print-assumptions-list 21477 rocq-9.2.0/dev/ci/user-overlays/21486-ppedrot-track-elimination-source-constraints.sh000066400000000000000000000012671516144147600304440ustar00rootroot00000000000000overlay coq_dpdgraph https://github.com/ppedrot/coq-dpdgraph track-elimination-source-constraints 21486 overlay elpi https://github.com/ppedrot/coq-elpi track-elimination-source-constraints 21486 overlay equations https://github.com/ppedrot/Coq-Equations track-elimination-source-constraints 21486 overlay lean_importer https://github.com/ppedrot/rocq-lean-import track-elimination-source-constraints 21486 overlay metarocq https://github.com/ppedrot/metarocq track-elimination-source-constraints 21486 overlay mtac2 https://github.com/ppedrot/Mtac2 track-elimination-source-constraints 21486 overlay paramcoq https://github.com/ppedrot/paramcoq track-elimination-source-constraints 21486 rocq-9.2.0/dev/ci/user-overlays/README.md000066400000000000000000000123041516144147600177470ustar00rootroot00000000000000# Add overlays for your pull requests in this directory _Overlays_ let you test pull requests that break the base version of external projects by applying PRs of the external project during CI testing (1 PR per broken external project). Once Rocq CI's tests of the external projects pass, the Rocq PR can be merged, then the assignee must ask the external projects to merge their PRs (for example by commenting in the external PRs). External projects are then expected to merge their PRs promptly. ## Typical workflow Overlay files can be created automatically using the script [`create_overlays.sh`](../../tools/create_overlays.sh). - Observe that your changes breaks some external projects `` ... `` in CI (`` is the name of a project, without the `ci-` prefix. Note that some jobs run multiple projects, e.g. `plugin:ci-elpi_hb` runs `elpi` and `hb`) - If necessary, fork the broken projects from their github pages. (Only needs to be done once per project for the lifetime of your github account) (Ask for help for projects not on github) - Compile your PR locally (`make world`). - Run `dev/tools/create_overlays.sh ... ` where `` is your github account name and `PR` is the PR number. This will download the given projects to `_build_ci` (and their dependencies), declare your fork (using the account name) as a remote and checkout a new branch for your fixes. - For each broken project: - run `make ci-`, e.g. `make ci-elpi`. This should produce the error observed in CI. - Make necessary changes, then rerun the script to verify they work. - From the `_build_ci/` subdirectory, commit your changes to the current branch (it was created by create_overlays). - Push to your fork of the project and create a new PR. Make sure you pick the correct base branch in the github GUI for the comparison (c.f. `dev/ci/ci-basic-overlay.sh`, e.g. `master` for elpi). If the fix is backwards compatible (preferred for library changes), open the PR as ready and ask for it to be merged (eg "Should be backwards compatible, please merge."). Otherwise (typical for plugin changes, including plugins with optional compilation to support multiple Rocq versions) the PR needs to be merged in sync with the Rocq PR, so open as draft. - link the overlay PR in the Rocq PR (at the end of the opening post add a list ~~~ Overlays: - - ~~~ ) - Commit the overlay file (`git add dev/ci/user-overlays && git commit`), push to the Rocq PR and run full CI (wait for the assignee to run full CI if you don't have the rights) - When your PR is merged, the assignee notifies the maintainers of the external project to merge the changes you submitted. This should happen promptly; the external project's CI will fail until the change is merged. - Beer. Notes: - running `create_overlays` multiple times is fine - running `make ci-foo` before `create_overlays` it's also fine So for instance you can have an alternate workflow of - run `make ci-project1` - fix - `dev/tools/create_overlays.sh ` - commit, push and PR for project 1 - run `make ci-project2` - fix - `dev/tools/create_overlays.sh ` - commit push and PR for project 2 - repeat until project `n` is done - commit and push overlay file ## Overlay file specification An overlay file specifies the external PRs that should be applied during CI. A single file can cover multiple external projects. Create your overlay file in the `dev/ci/user-overlays` directory. The name of the overlay file should start with a five-digit pull request number, followed by a dash, anything (by convention, your GitHub nickname and the branch name), then an `.sh` extension (`[0-9]{5}-[a-zA-Z0-9-_]+.sh`). The file must contain a call to the `overlay` function for each affected external project: ``` overlay [] ``` Each call creates an overlay for `project` using a given `giturl` and `ref` which is active for `prnumber` or `prbranch` (`prbranch` defaults to `ref`). For example, an overlay for the project `elpi` that uses the branch `noinstance` from the fork of `SkySkimmer` and is active for pull request `13128`: ``` overlay elpi https://github.com/SkySkimmer/coq-elpi noinstance 13128 ``` The github URL and base branch name for each external project are listed in [`ci-basic-overlay.sh`](../ci-basic-overlay.sh). For example, the entry for `elpi` is ``` project elpi "https://github.com/LPCIC/coq-elpi" "master" ``` But substitute the name of your fork into the URL, e.g. `SkySkimmer/coq-elpi` rather than `LPCIC/coq-elpi`. Use `#` to mark any comments. If the branch name in the external project differs from the Rocq branch name, include the external branch name as `[prbranch]` to apply it when you run the test suite locally, e.g. `make ci-elpi`. ## Branching conventions We suggest you use the convention of identical branch names for the Rocq branch and the CI project branch used in the overlay. For example, if your Rocq PR is in your branch `more_efficient_tc` and breaks `ltac2`, we suggest you create an `ltac2` overlay with a branch named `more_efficient_tc`. rocq-9.2.0/dev/core_dune.dbg000066400000000000000000000011771516144147600157040ustar00rootroot00000000000000load_printer threads.cma load_printer str.cma load_printer zarith.cma load_printer config.cma load_printer clib.cma load_printer boot.cma load_printer perf.cma load_printer lib.cma load_printer gramlib.cma load_printer coqrun.cma load_printer kernel.cma load_printer library.cma load_printer engine.cma load_printer pretyping.cma load_printer interp.cma load_printer proofs.cma load_printer parsing.cma load_printer printing.cma load_printer tactics.cma load_printer findlib.cma load_printer findlib_dynload.cma load_printer vernac.cma load_printer sysinit.cma load_printer coqworkmgrlib.cma load_printer stm.cma load_printer toplevel.cma rocq-9.2.0/dev/db000066400000000000000000000013501516144147600135640ustar00rootroot00000000000000load_printer threads.cma load_printer str.cma load_printer zarith.cma load_printer memprof_limits.cma load_printer findlib.cma load_printer findlib_dynload.cma load_printer config.cma load_printer clib.cma load_printer boot.cma load_printer coqperf.cma load_printer lib.cma load_printer gramlib.cma load_printer coqrun.cma load_printer kernel.cma load_printer library.cma load_printer engine.cma load_printer pretyping.cma load_printer interp.cma load_printer proofs.cma load_printer parsing.cma load_printer printing.cma load_printer tactics.cma load_printer vernac.cma load_printer cc_core_plugin.cma load_printer ltac_plugin.cma load_printer ltac2_plugin.cma load_printer dev.cma load_printer debugger_support.cma source top_printers.dbg rocq-9.2.0/dev/debugger_support.ml000066400000000000000000000024271516144147600171740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prod (x, a, type_of (push_rel (LocalAssum (x,a)) env) b)`. Otherwise see `context.mli` for a few combinators on the `binder_annot` type. When making `Relevant` annotations you can use some convenience functions from `Context` (eg `annotR x = make_annot x Relevant`), also `mkArrowR` from `Constr`/`EConstr` which has the signature of the old `mkArrow`. Relevance can be inferred from a well-typed term using functions in `Retypeops` (for `Constr`) and `Retyping` (for `EConstr`). For `x` a term, note the difference between its relevance as a term (is `x : (_ : SProp)`) and as a type (is `x : SProp`), there are functions for both kinds. ## Case inversion Inductives in SProp with 1 constructor which has no arguments have a special reduction rule for matches. To implement it the Case constructor is extended with a `case_invert` field. If you are constructing a match on a normal (non-special reduction) inductive you must fill the new field with `NoInvert`. Otherwise you must fill it with `CaseInvert {univs ; args}` where `univs` is the universe instance of the type you are matching and `args` the parameters and indices. For instance, in ~~~coq Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. Definition seq_to_eq {A x y} (e:seq x y) : x = y :> A := match e with srefl => eq_refl end. ~~~ the `match e with ...` has `CaseInvert {univs = Instance.empty; args = [|A x y|]}`. (empty instance since we defined a universe monomorphic `seq`). In practice, you should use `Inductiveops.make_case_or_project` which will take care of this for you (and also handles primitive records correctly etc). rocq-9.2.0/dev/doc/archive/000077500000000000000000000000001516144147600154435ustar00rootroot00000000000000rocq-9.2.0/dev/doc/archive/COMPATIBILITY000066400000000000000000000010251516144147600173750ustar00rootroot00000000000000Note: this file isn't used anymore. Incompatibilities are documented as part of CHANGES. Incompatibilities beyond 8.4... - Syntax: "x -> y" has now lower priority than "<->" "A -> B <-> C" is now "A -> (B <-> C)" - Tactics: tauto and intuition no longer accidentally destruct binary connectives or records other than and, or, prod, sum, iff. In most of cases, dtauto or dintuition, though stronger than 8.3 tauto and 8.3 intuition will provide compatibility. - "Solve Obligations using" is now "Solve Obligations with". rocq-9.2.0/dev/doc/archive/Translator.tex000066400000000000000000000755731516144147600203370ustar00rootroot00000000000000\ifx\pdfoutput\undefined % si on est pas en pdflatex \documentclass[11pt,a4paper]{article} \else \documentclass[11pt,a4paper,pdftex]{article} \fi \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage{pslatex} \usepackage{url} \usepackage{verbatim} \usepackage{amsmath} \usepackage{amssymb} \usepackage{array} \usepackage{fullpage} \title{Translation from Coq V7 to V8} \author{The Coq Development Team} %% Macros etc. \catcode`\_=13 \let\subscr=_ \def_{\ifmmode\sb\else\subscr\fi} \def\NT#1{\langle\textit{#1}\rangle} \def\NTL#1#2{\langle\textit{#1}\rangle_{#2}} %\def\TERM#1{\textsf{\bf #1}} \def\TERM#1{\texttt{#1}} \newenvironment{transbox} {\begin{center}\tt\begin{tabular}{l|ll} \hfil\textrm{V7} & \hfil\textrm{V8} \\ \hline} {\end{tabular}\end{center}} \def\TRANS#1#2 {\begin{tabular}[t]{@{}l@{}}#1\end{tabular} & \begin{tabular}[t]{@{}l@{}}#2\end{tabular} \\} \def\TRANSCOM#1#2#3 {\begin{tabular}[t]{@{}l@{}}#1\end{tabular} & \begin{tabular}[t]{@{}l@{}}#2\end{tabular} & #3 \\} %% %% %% \begin{document} \maketitle \section{Introduction} Coq version 8.0 is a major version and carries major changes: the concrete syntax was redesigned almost from scratch, and many notions of the libraries were renamed for uniformisation purposes. We felt that these changes could discourage users with large theories from switching to the new version. The goal of this document is to introduce these changes on simple examples (mainly the syntactic changes), and describe the automated tools to help moving to V8.0. Essentially, it consists of a translator that takes as input a Coq source file in old syntax and produces a file in new syntax and adapted to the new standard library. The main extra features of this translator is that it keeps comments, even those within expressions\footnote{The position of those comment might differ slightly since there is no exact matching of positions between old and new syntax.}. The document is organised as follows: first section describes the new syntax on simple examples. It is very translation-oriented. This should give users of older versions the flavour of the new syntax, and allow them to make translation manually on small examples. Section~\ref{Translation} explains how the translation process can be automatised for the most part (the boring one: applying similar changes over thousands of lines of code). We strongly advise users to follow these indications, in order to avoid many potential complications of the translation process. \section{The new syntax on examples} The goal of this section is to introduce to the new syntax of Coq on simple examples, rather than just giving the new grammar. It is strongly recommended to read first the definition of the new syntax (in the reference manual), but this document should also be useful for the eager user who wants to start with the new syntax quickly. The toplevel has an option {\tt -translate} which allows interactively translating commands. This toplevel translator accepts a command, prints the translation on standard output (after a % \verb+New syntax:+ balise), executes the command, and waits for another command. The only requirements is that they should be syntactically correct, but they do not have to be well-typed. This interactive translator proved to be useful in two main usages. First as a ``debugger'' of the translation. Before the translation, it may help in spotting possible conflicts between the new syntax and user notations. Or when the translation fails for some reason, it makes it easy to find the exact reason why it failed and make attempts in fixing the problem. The second usage of the translator is when trying to make the first proofs in new syntax. Well trained users will automatically think their scripts in old syntax and might waste much time (and the intuition of the proof) if they have to search the translation in a document. Running a translator in the background will allow the user to instantly have the answer. The rest of this section is a description of all the aspects of the syntax that changed and how they were translated. All the examples below can be tested by entering the V7 commands in the toplevel translator. %% \subsection{Changes in lexical conventions w.r.t. V7} \subsubsection{Identifiers} The lexical conventions changed: \TERM{_} is not a regular identifier anymore. It is used in terms as a placeholder for subterms to be inferred at type-checking, and in patterns as a non-binding variable. Furthermore, only letters (Unicode letters), digits, single quotes and _ are allowed after the first character. \subsubsection{Quoted string} Quoted strings are used typically to give a filename (which may not be a regular identifier). As before they are written between double quotes ("). Unlike for V7, there is no escape character: characters are written normally except the double quote which is doubled. \begin{transbox} \TRANS{"abcd$\backslash\backslash$efg"}{"abcd$\backslash$efg"} \TRANS{"abcd$\backslash$"efg"}{"abcd""efg"} \end{transbox} \subsection{Main changes in terms w.r.t. V7} \subsubsection{Precedence of application} In the new syntax, parentheses are not really part of the syntax of application. The precedence of application (10) is tighter than all prefix and infix notations. It makes it possible to remove parentheses in many contexts. \begin{transbox} \TRANS{(A x)->(f x)=(g y)}{A x -> f x = g y} \TRANS{(f [x]x)}{f (fun x => x)} \end{transbox} \subsubsection{Arithmetics and scopes} The specialized notation for \TERM{Z} and \TERM{R} (introduced by symbols \TERM{`} and \TERM{``}) have disappeared. They have been replaced by the general notion of scope. \begin{center} \begin{tabular}{l|l|l} type & scope name & delimiter \\ \hline types & type_scope & \TERM{type} \\ \TERM{bool} & bool_scope & \\ \TERM{nat} & nat_scope & \TERM{nat} \\ \TERM{Z} & Z_scope & \TERM{Z} \\ \TERM{R} & R_scope & \TERM{R} \\ \TERM{positive} & positive_scope & \TERM{P} \end{tabular} \end{center} In order to use notations of arithmetics on \TERM{Z}, its scope must be opened with command \verb+Open Scope Z_scope.+ Another possibility is using the scope change notation (\TERM{\%}). The latter notation is to be used when notations of several scopes appear in the same expression. In examples below, scope changes are not needed if the appropriate scope has been opened. Scope \verb|nat_scope| is opened in the initial state of Coq. \begin{transbox} \TRANSCOM{`0+x=x+0`}{0+x=x+0}{\textrm{Z_scope}} \TRANSCOM{``0 + [if b then ``1`` else ``2``]``}{0 + if b then 1 else 2}{\textrm{R_scope}} \TRANSCOM{(0)}{0}{\textrm{nat_scope}} \end{transbox} Below is a table that tells which notation is available in which scope. The relative precedences and associativity of operators is the same as in usual mathematics. See the reference manual for more details. However, it is important to remember that unlike V7, the type operators for product and sum are left-associative, in order not to clash with arithmetic operators. \begin{center} \begin{tabular}{l|l} scope & notations \\ \hline nat_scope & \texttt{+ - * < <= > >=} \\ Z_scope & \texttt{+ - * / mod < <= > >= ?=} \\ R_scope & \texttt{+ - * / < <= > >=} \\ type_scope & \texttt{* +} \\ bool_scope & \texttt{\&\& || -} \\ list_scope & \texttt{:: ++} \end{tabular} \end{center} \subsubsection{Notation for implicit arguments} The explicitation of arguments is closer to the \emph{bindings} notation in tactics. Argument positions follow the argument names of the head constant. The example below assumes \verb+f+ is a function with two implicit dependent arguments named \verb+x+ and \verb+y+. \begin{transbox} \TRANS{f 1!t1 2!t2 t3}{f (x:=t1) (y:=t2) t3} \TRANS{!f t1 t2}{@f t1 t2} \end{transbox} \subsubsection{Inferred subterms} Subterms that can be automatically inferred by the type-checker is now written {\tt _} \begin{transbox} \TRANS{?}{_} \end{transbox} \subsubsection{Universal quantification} The universal quantification and dependent product types are now introduced by the \texttt{forall} keyword before the binders and a comma after the binders. The syntax of binders also changed significantly. A binder can simply be a name when its type can be inferred. In other cases, the name and the type of the variable are put between parentheses. When several consecutive variables have the same type, they can be grouped. Finally, if all variables have the same type, parentheses can be omitted. \begin{transbox} \TRANS{(x:A)B}{forall (x:~A), B ~~\textrm{or}~~ forall x:~A, B} \TRANS{(x,y:nat)P}{forall (x y :~nat), P ~~\textrm{or}~~ forall x y :~nat, P} \TRANS{(x,y:nat;z:A)P}{forall (x y :~nat) (z:A), P} \TRANS{(x,y,z,t:?)P}{forall x y z t, P} \TRANS{(x,y:nat;z:?)P}{forall (x y :~nat) z, P} \end{transbox} \subsubsection{Abstraction} The notation for $\lambda$-abstraction follows that of universal quantification. The binders are surrounded by keyword \texttt{fun} and \verb+=>+. \begin{transbox} \TRANS{[x,y:nat; z](f a b c)}{fun (x y:nat) z => f a b c} \end{transbox} \subsubsection{Pattern-matching} Beside the usage of the keyword pair \TERM{match}/\TERM{with} instead of \TERM{Cases}/\TERM{of}, the main change is the notation for the type of branches and return type. It is no longer written between \TERM{$<$ $>$} before the \TERM{Cases} keyword, but interleaved with the destructured objects. The idea is that for each destructured object, one may specify a variable name (after the \TERM{as} keyword) to tell how the branches types depend on this destructured objects (case of a dependent elimination), and also how they depend on the value of the arguments of the inductive type of the destructured objects (after the \TERM{in} keyword). The type of branches is then given after the keyword \TERM{return}, unless it can be inferred. Moreover, when the destructured object is a variable, one may use this variable in the return type. \begin{transbox} \TRANS{Cases n of\\~~ O => O \\| (S k) => (1) end}{match n with\\~~ 0 => 0 \\| S k => 1 end} \TRANS{Cases m n of \\~~0 0 => t \\| ... end}{match m, n with \\~~0, 0 => t \\| ... end} \TRANS{<[n:nat](P n)>Cases T of ... end}{match T as n return P n with ... end} \TRANS{<[n:nat][p:(even n)]\~{}(odd n)>Cases p of\\~~ ... \\end}{match p in even n return \~{} odd n with\\~~ ...\\end} \end{transbox} The annotations of the special pattern-matching operators (\TERM{if}/\TERM{then}/\TERM{else}) and \TERM{let()} also changed. The only restriction is that the destructuring \TERM{let} does not allow dependent case analysis. \begin{transbox} \TRANS{ \begin{tabular}{@{}l} <[n:nat;x:(I n)](P n x)>if t then t1 \\ else t2 \end{tabular}}% {\begin{tabular}{@{}l} if t as x in I n return P n x then t1 \\ else t2 \end{tabular}} \TRANS{<[n:nat](P n)>let (p,q) = t1 in t2}% {let (p,q) in I n return P n := t1 in t2} \end{transbox} \subsubsection{Fixpoints and cofixpoints} An simpler syntax for non-mutual fixpoints is provided, making it very close to the usual notation for non-recursive functions. The decreasing argument is now indicated by an annotation between curly braces, regardless of the binders grouping. The annotation can be omitted if the binders introduce only one variable. The type of the result can be omitted if inferable. \begin{transbox} \TRANS{Fix plus\{plus [n:nat] : nat -> nat :=\\~~ [m]...\}}{fix plus (n m:nat) \{struct n\}: nat := ...} \TRANS{Fix fact\{fact [n:nat]: nat :=\\ ~~Cases n of\\~~~~ O => (1) \\~~| (S k) => (mult n (fact k)) end\}}{fix fact (n:nat) :=\\ ~~match n with \\~~~~0 => 1 \\~~| (S k) => n * fact k end} \end{transbox} There is a syntactic sugar for single fixpoints (defining one variable) associated to a local definition: \begin{transbox} \TRANS{let f := Fix f \{f [x:A] : T := M\} in\\(g (f y))}{let fix f (x:A) : T := M in\\g (f x)} \end{transbox} The same applies to cofixpoints, annotations are not allowed in that case. \subsubsection{Notation for type cast} \begin{transbox} \TRANS{O :: nat}{0 : nat} \end{transbox} \subsection{Main changes in tactics w.r.t. V7} The main change is that all tactic names are lowercase. This also holds for Ltac keywords. \subsubsection{Renaming of induction tactics} \begin{transbox} \TRANS{NewDestruct}{destruct} \TRANS{NewInduction}{induction} \TRANS{Induction}{simple induction} \TRANS{Destruct}{simple destruct} \end{transbox} \subsubsection{Ltac} Definitions of macros are introduced by \TERM{Ltac} instead of \TERM{Tactic Definition}, \TERM{Meta Definition} or \TERM{Recursive Definition}. They are considered recursive by default. \begin{transbox} \TRANS{Meta Definition my_tac t1 t2 := t1; t2.}% {Ltac my_tac t1 t2 := t1; t2.} \end{transbox} Rules of a match command are not between square brackets anymore. Context (understand a term with a placeholder) instantiation \TERM{inst} became \TERM{context}. Syntax is unified with subterm matching. \begin{transbox} \TRANS{Match t With [C[x=y]] -> Inst C[y=x]}% {match t with context C[x=y] => context C[y=x] end} \end{transbox} Arguments of macros use the term syntax. If a general Ltac expression is to be passed, it must be prefixed with ``{\tt ltac :}''. In other cases, when a \'{} was necessary, it is replaced by ``{\tt constr :}'' \begin{transbox} \TRANS{my_tac '(S x)}{my_tac (S x)} \TRANS{my_tac (Let x=tac In x)}{my_tac ltac:(let x:=tac in x)} \TRANS{Let x = '[x](S (S x)) In Apply x}% {let x := constr:(fun x => S (S x)) in apply x} \end{transbox} {\tt Match Context With} is now called {\tt match goal with}. Its argument is an Ltac expression by default. \subsubsection{Named arguments of theorems ({\em bindings})} \begin{transbox} \TRANS{Apply thm with x:=t 1:=u}{apply thm with (x:=t) (1:=u)} \end{transbox} \subsubsection{Occurrences} To avoid ambiguity between a numeric literal and the optional occurrence numbers of this term, the occurrence numbers are put after the term itself and after keyword \TERM{as}. \begin{transbox} \TRANS{Pattern 1 2 (f x) 3 4 d y z}{pattern f x at 1 2, d at 3 4, y, z} \end{transbox} \subsubsection{{\tt LetTac} and {\tt Pose}} Tactic {\tt LetTac} was renamed into {\tt set}, and tactic {\tt Pose} was a particular case of {\tt LetTac} where the abbreviation is folded in the conclusion\footnote{There is a tactic called {\tt pose} in V8, but its behaviour is not to fold the abbreviation at all.}. \begin{transbox} \TRANS{LetTac x = t in H}{set (x := t) in H} \TRANS{Pose x := t}{set (x := t)} \end{transbox} {\tt LetTac} could be followed by a specification (called a clause) of the places where the abbreviation had to be folded (hypothese and/or conclusion). Clauses are the syntactic notion to denote in which parts of a goal a given transformation should occur. Its basic notation is either \TERM{*} (meaning everywhere), or {\tt\textrm{\em hyps} |- \textrm{\em concl}} where {\em hyps} is either \TERM{*} (to denote all the hypotheses), or a comma-separated list of either hypothesis name, or {\tt (value of $H$)} or {\tt (type of $H$)}. Moreover, occurrences can be specified after every hypothesis after the {\TERM{at}} keyword. {\em concl} is either empty or \TERM{*}, and can be followed by occurrences. \begin{transbox} \TRANS{in Goal}{in |- *} \TRANS{in H H1}{in H1, H2 |-} \TRANS{in H H1 ...}{in * |-} \TRANS{in H H1 Goal}{in H1, H2 |- *} \TRANS{in H H1 H2 ... Goal}{in *} \TRANS{in 1 2 H 3 4 H0 1 3 Goal}{in H at 1 2, H0 at 3 4 |- * at 1 3} \end{transbox} \subsection{Main changes in vernacular commands w.r.t. V7} \subsubsection{Require} The default behaviour of {\tt Require} is not to open the loaded module. \begin{transbox} \TRANS{Require Arith}{Require Import Arith} \end{transbox} \subsubsection{Binders} The binders of vernacular commands changed in the same way as those of fixpoints. This also holds for parameters of inductive definitions. \begin{transbox} \TRANS{Definition x [a:A] : T := M}{Definition x (a:A) : T := M} \TRANS{Inductive and [A,B:Prop]: Prop := \\~~conj : A->B->(and A B)}% {Inductive and (A B:Prop): Prop := \\~~conj : A -> B -> and A B} \end{transbox} \subsubsection{Hints} Both {\tt Hints} and {\tt Hint} commands are beginning with {\tt Hint}. Command {\tt HintDestruct} has disappeared. The syntax of \emph{Extern} hints changed: the pattern and the tactic to be applied are separated by a {\tt =>}. \begin{transbox} \TRANS{Hint name := Resolve (f ? x)}% {Hint Resolve (f _ x)} \TRANS{Hint name := Extern 4 (toto ?) Apply lemma}% {Hint Extern 4 (toto _) => apply lemma} \TRANS{Hints Resolve x y z}{Hint Resolve x y z} \TRANS{Hints Resolve f : db1 db2}{Hint Resolve f : db1 db2} \TRANS{Hints Immediate x y z}{Hint Immediate x y z} \TRANS{Hints Unfold x y z}{Hint Unfold x y z} %% \TRANS{\begin{tabular}{@{}l} %% HintDestruct Local Conclusion \\ %% ~~name (f ? ?) 3 [Apply thm] %% \end{tabular}}% %% {\begin{tabular}{@{}l} %% Hint Local Destuct name := \\ %% ~~3 Conclusion (f _ _) => apply thm %% \end{tabular}} \end{transbox} \subsubsection{Implicit arguments} {\tt Set Implicit Arguments} changed its meaning in V8: the default is to turn implicit only the arguments that are {\em strictly} implicit (or rigid), i.e. that remains inferable whatever the other arguments are. For instance {\tt x} inferable from {\tt P x} is not strictly inferable since it can disappears if {\tt P} is instantiated by a term which erases {\tt x}. \begin{transbox} \TRANS{Set Implicit Arguments}% {\begin{tabular}{l} Set Implicit Arguments. \\ Unset Strict Implicits. \end{tabular}} \end{transbox} However, you may wish to adopt the new semantics of {\tt Set Implicit Arguments} (for instance because you think that the choice of arguments it sets implicit is more ``natural'' for you). \subsection{Changes in standard library} Many lemmas had their named changed to improve uniformity. The user generally do not have to care since the translators performs the renaming. Type {\tt entier} from fast_integer.v is renamed into {\tt N} by the translator. As a consequence, user-defined objects of same name {\tt N} are systematically qualified even tough it may not be necessary. The following table lists the main names with which the same problem arises: \begin{transbox} \TRANS{IF}{IF_then_else} \TRANS{ZERO}{Z0} \TRANS{POS}{Zpos} \TRANS{NEG}{Zneg} \TRANS{SUPERIEUR}{Gt} \TRANS{EGAL}{Eq} \TRANS{INFERIEUR}{Lt} \TRANS{add}{Pplus} \TRANS{true_sub}{Pminus} \TRANS{entier}{N} \TRANS{Un_suivi_de}{Ndouble_plus_one} \TRANS{Zero_suivi_de}{Ndouble} \TRANS{Nul}{N0} \TRANS{Pos}{Npos} \end{transbox} \subsubsection{Implicit arguments} %% Hugo: Main definitions of standard library have now implicit arguments. These arguments are dropped in the translated files. This can exceptionally be a source of incompatibilities which has to be solved by hand (it typically happens for polymorphic functions applied to {\tt nil} or {\tt None}). %% preciser: avant ou apres trad ? \subsubsection{Logic about {\tt Type}} Many notations that applied to {\tt Set} have been extended to {\tt Type}, so several definitions in {\tt Type} are superseded by them. \begin{transbox} \TRANS{x==y}{x=y} \TRANS{(EXT x:Prop | Q)}{exists x:Prop, Q} \TRANS{identityT}{identity} \end{transbox} %% Doc of the translator \section{A guide to translation} \label{Translation} %%\subsection{Overview of the translation process} Here is a short description of the tools involved in the translation process: \begin{description} \item{\tt coqc -translate} is the automatic translator. It is a parser/pretty-printer. This means that the translation is made by parsing every command using a parser of old syntax, which is printed using the new syntax. Many efforts were made to preserve as much as possible of the quality of the presentation: it avoids expansion of syntax extensions, comments are not discarded and placed at the same place. \item{\tt translate-v8} (in the translation package) is a small shell-script that will help translate developments that compile with a Makefile with minimum requirements. \end{description} \subsection{Preparation to translation} This step is very important because most of work shall be done before translation. If a problem occurs during translation, it often means that you will have to modify the original source and restart the translation process. This also means that it is recommended not to edit the output of the translator since it would be overwritten if the translation has to be restarted. \subsubsection{Compilation with {\tt coqc -v7}} First of all, it is mandatory that files compile with the current version of Coq (8.0) with option {\tt -v7}. Translation is a complicated task that involves the full compilation of the development. If your development was compiled with older versions, first upgrade to Coq V8.0 with option {\tt -v7}. If you use a Makefile similar to those produced by {\tt coq\_makefile}, you probably just have to do {\tt make OPT="-opt -v7"} ~~~or~~~ {\tt make OPT="-byte -v7"} When the development compiles successfully, there are several changes that might be necessary for the translation. Essentially, this is about syntax extensions (see section below dedicated to porting syntax extensions). If you do not use such features, then you are ready to try and make the translation. \subsection{Translation} \subsubsection{The general case} The preferred way is to use script {\tt translate-v8} if your development is compiled by a Makefile with the following constraints: \begin{itemize} \item compilation is achieved by invoking make without specifying a target \item options are passed to Coq with make variable COQFLAGS that includes variables OPT, COQLIBS, and OTHERFLAGS. \end{itemize} These constraints are met by the makefiles produced by {\tt coq\_makefile} Otherwise, modify your build program so as to pass option {\tt -translate} to program {\tt coqc}. The effect of this option is to output the translated source of any {\tt .v} file in a file with extension {\tt .v8} located in the same directory than the original file. \subsubsection{What may happen during the translation} This section describes events that may happen during the translation and measures to adopt. These are the warnings that may arise during the translation, but they generally do not require any modification for the user: Warnings: \begin{itemize} \item {\tt Unable to detect if $id$ denotes a local definition}\\ This is due to a semantic change in clauses. In a command such as {\tt simpl in H}, the old semantics were to perform simplification in the type of {\tt H}, or in its body if it is defined. With the new semantics, it is performed both in the type and the body (if any). It might lead to incompatibilities \item {\tt Forgetting obsolete module}\\ Some modules have disappeared in V8.0 (new syntax). The user does not need to worry about it, since the translator deals with it. \item {\tt Replacing obsolete module}\\ Same as before but with the module that were renamed. Here again, the translator deals with it. \end{itemize} \subsection{Verification of the translation} The shell-script {\tt translate-v8} also renames {\tt .v8} files into {\tt .v} files (older {\tt .v} files are put in a subdirectory called {\tt v7}) and tries to recompile them. To do so it invokes {\tt make} without option (which should cause the compilation using {\tt coqc} without particular option). If compilation fails at this stage, you should refrain from repairing errors manually on the new syntax, but rather modify the old syntax script and restart the translation. We insist on that because the problem encountered can show up in many instances (especially if the problem comes from a syntactic extension), and fixing the original sources (for instance the {\tt V8only} parts of notations) once will solve all occurrences of the problem. %%\subsubsection{Errors occurring after translation} %%Equality in {\tt Z} or {\tt R}... \subsection{Particular cases} \subsubsection{Lexical conventions} The definition of identifiers changed. Most of those changes are handled by the translator. They include: \begin{itemize} \item {\tt \_} is not an identifier anymore: it is translated to {\tt x\_} \item avoid clash with new keywords by adding a trailing {\tt \_} \end{itemize} If the choices made by translation is not satisfactory or in the following cases: \begin{itemize} \item use of latin letters \item use of iso-latin characters in notations \end{itemize} users should change their development prior to translation. \subsubsection{{\tt Case} and {\tt Match}} These very low-level case analysis are no longer supported. The translator tries hard to translate them into a user-friendly one, but it might lack type information to do so\footnote{The translator tries to typecheck terms before printing them, but it is not always possible to determine the context in which terms appearing in tactics live.}. If this happens, it is preferable to transform it manually before translation. \subsubsection{Syntax extensions with {\tt Grammar} and {\tt Syntax}} {\tt Grammar} and {\tt Syntax} are no longer supported. They should be replaced by an equivalent {\tt Notation} command and be processed as described above. Before attempting translation, users should verify that compilation with option {\tt -v7} succeeds. In the cases where {\tt Grammar} and {\tt Syntax} cannot be emulated by {\tt Notation}, users have to change manually they development as they wish to avoid the use of {\tt Grammar}. If this is not done, the translator will simply expand the notations and the output of the translator will use the regular Coq syntax. \subsubsection{Syntax extensions with {\tt Notation} and {\tt Infix}} These commands do not necessarily need to be changed. Some work will have to be done manually if the notation conflicts with the new syntax (for instance, using keywords like {\tt fun} or {\tt exists}, overloading of symbols of the old syntax, etc.) or if the precedences are not right. Precedence levels are now from 0 to 200. In V8, the precedence and associativity of an operator cannot be redefined. Typical level are (refer to the chapter on notations in the Reference Manual for the full list): \begin{center} \begin{tabular}{|cll|} \hline Notation & Precedence & Associativity \\ \hline \verb!_ <-> _! & 95 & no \\ \verb!_ \/ _! & 85 & right \\ \verb!_ /\ _! & 80 & right \\ \verb!~ _! & 75 & right \\ \verb!_ = _!, \verb!_ <> _!, \verb!_ < _!, \verb!_ > _!, \verb!_ <= _!, \verb!_ >= _! & 70 & no \\ \verb!_ + _!, \verb!_ - _! & 50 & left \\ \verb!_ * _!, \verb!_ / _! & 40 & left \\ \verb!- _! & 35 & right \\ \verb!_ ^ _! & 30 & left \\ \hline \end{tabular} \end{center} By default, the translator keeps the associativity given in V7 while the levels are mapped according to the following table: \begin{center} \begin{tabular}{l|l|l} V7 level & mapped to & associativity \\ \hline 0 & 0 & no \\ 1 & 20 & left \\ 2 & 30 & right \\ 3 & 40 & left \\ 4 & 50 & left \\ 5 & 70 & no \\ 6 & 80 & right \\ 7 & 85 & right \\ 8 & 90 & right \\ 9 & 95 & no \\ 10 & 100 & left \end{tabular} \end{center} If this is OK, just simply apply the translator. \paragraph{Associativity conflict} Since the associativity of the levels obtained by translating a V7 level (as shown on table above) cannot be changed, you have to choose another level with a compatible associativity. You can choose any level between 0 and 200, knowing that the standard operators are already set at the levels shown on the list above. Assume you have a notation \begin{verbatim} Infix NONA 2 "=_S" my_setoid_eq. \end{verbatim} By default, the translator moves it to level 30 which is right associative, hence a conflict with the expected no associativity. To solve the problem, just add the "V8only" modifier to reset the level and enforce the associativity as follows: \begin{verbatim} Infix NONA 2 "=_S" my_setoid_eq V8only (at level 70, no associativity). \end{verbatim} The translator now knows that it has to translate "=_S" at level 70 with no associativity. Remark: 70 is the "natural" level for relations, hence the choice of 70 here, but any other level accepting a no-associativity would have been OK. Second example: assume you have a notation \begin{verbatim} Infix RIGHTA 1 "o" my_comp. \end{verbatim} By default, the translator moves it to level 20 which is left associative, hence a conflict with the expected right associativity. To solve the problem, just add the "V8only" modifier to reset the level and enforce the associativity as follows: \begin{verbatim} Infix RIGHTA 1 "o" my_comp V8only (at level 20, right associativity). \end{verbatim} The translator now knows that it has to translate "o" at level 20 which has the correct "right associativity". Remark: we assumed here that the user wants a strong precedence for composition, in such a way, say, that "f o g + h" is parsed as "(f o g) + h". To get "o" binding less than the arithmetical operators, an appropriated level would have been close of 70, and below, e.g. 65. \paragraph{Conflict: notation hides another notation} Remark: use {\tt Print Grammar constr} in V8 to diagnose the overlap and see the section on factorization in the chapter on notations of the Reference Manual for hints on how to factorize. Example: \begin{verbatim} Notation "{ x }" := (my_embedding x) (at level 1). \end{verbatim} overlaps in V8 with notation \verb#{ x : A & P }# at level 0 and with x at level 99. The conflicts can be solved by left-factorizing the notation as follows: \begin{verbatim} Notation "{ x }" := (my_embedding x) (at level 1) V8only (at level 0, x at level 99). \end{verbatim} \paragraph{Conflict: a notation conflicts with the V8 grammar} Again, use the {\tt V8only} modifier to tell the translator to automatically take in charge the new syntax. Example: \begin{verbatim} Infix 3 "@" app. \end{verbatim} Since {\tt @} is used in the new syntax for deactivating the implicit arguments, another symbol has to be used, e.g. {\tt @@}. This is done via the {\tt V8only} option as follows: \begin{verbatim} Infix 3 "@" app V8only "@@" (at level 40, left associativity). \end{verbatim} or, alternatively by \begin{verbatim} Notation "x @ y" := (app x y) (at level 3, left associativity) V8only "x @@ y" (at level 40, left associativity). \end{verbatim} \paragraph{Conflict: my notation is already defined at another level (or with another associativity)} In V8, the level and associativity of a given notation can no longer be changed. Then, either you adopt the standard reserved levels and associativity for this notation (as given on the list above) or you change your notation. \begin{itemize} \item To change the notation, follow the directions in the previous paragraph \item To adopt the standard level, just use {\tt V8only} without any argument. \end{itemize} Example: \begin{verbatim} Infix 6 "*" my_mult. \end{verbatim} is not accepted as such in V8. Write \begin{verbatim} Infix 6 "*" my_mult V8only. \end{verbatim} to tell the translator to use {\tt *} at the reserved level (i.e. 40 with left associativity). Even better, use interpretation scopes (look at the Reference Manual). \subsubsection{Strict implicit arguments} In the case you want to adopt the new semantics of {\tt Set Implicit Arguments} (only setting rigid arguments as implicit), add the option {\tt -strict-implicit} to the translator. Warning: changing the number of implicit arguments can break the notations. Then use the {\tt V8only} modifier of {\tt Notation}. \end{document} rocq-9.2.0/dev/doc/archive/extensions.txt000066400000000000000000000013221516144147600204010ustar00rootroot00000000000000Comment ajouter une nouvelle entrΓ©e primitive pour les TACTIC EXTEND ? ====================================================================== Exemple de l'ajout de l'entrΓ©e "clause": - ajouter un type ClauseArgType dans interp/genarg.ml{,i}, avec les wit_, rawwit_, et globwit_ correspondants - ajouter partout oΓΉ Genarg.argument_type est filtrΓ© le cas traitant de ce nouveau ClauseArgType - utiliser le rawwit_clause pour dΓ©finir une entrΓ©e clause du bon type et du bon nom dans le module Tactic de pcoq.ml4 - il faut aussi exporter la rΓ¨gle hors de g_tactic.ml4. Pour cela, il faut rejouter clause dans le GLOBAL du GEXTEND - seulement aprΓ¨s, le nom clause sera accessible dans les TACTIC EXTEND ! rocq-9.2.0/dev/doc/archive/naming-conventions.tex000066400000000000000000000544271516144147600220150ustar00rootroot00000000000000\documentclass[a4paper]{article} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{amsfonts} \parindent=0pt \parskip=10pt %%%%%%%%%%%%% % Macros \newcommand\itemrule[3]{ \subsubsection{#1} \begin{quote} \begin{tt} #3 \end{tt} \end{quote} \begin{quote} Name: \texttt{#2} \end{quote}} \newcommand\formula[1]{\begin{tt}#1\end{tt}} \newcommand\tactic[1]{\begin{tt}#1\end{tt}} \newcommand\command[1]{\begin{tt}#1\end{tt}} \newcommand\term[1]{\begin{tt}#1\end{tt}} \newcommand\library[1]{\texttt{#1}} \newcommand\name[1]{\texttt{#1}} \newcommand\zero{\texttt{zero}} \newcommand\op{\texttt{op}} \newcommand\opPrime{\texttt{op'}} \newcommand\opSecond{\texttt{op''}} \newcommand\phimapping{\texttt{phi}} \newcommand\D{\texttt{D}} \newcommand\elt{\texttt{elt}} \newcommand\rel{\texttt{rel}} \newcommand\relp{\texttt{rel'}} %%%%%%%%%%%%% \begin{document} \begin{center} \begin{huge} Proposed naming conventions for the Coq standard library \end{huge} \end{center} \bigskip The following document describes a proposition of canonical naming schemes for the Coq standard library. Obviously and unfortunately, the current state of the library is not as homogeneous as it would be if it would systematically follow such a scheme. To tend in this direction, we however recommend to follow the following suggestions. \tableofcontents \section{General conventions} \subsection{Variable names} \begin{itemize} \item Variables are preferably quantified at the head of the statement, even if some premisses do not depend of one of them. For instance, one would state \begin{quote} \begin{tt} {forall x y z:D, x <= y -> x+z <= y+z} \end{tt} \end{quote} and not \begin{quote} \begin{tt} {forall x y:D, x <= y -> forall z:D, x+z <= y+z} \end{tt} \end{quote} \item Variables are preferably quantified (and named) in the order of ``importance'', then of appearance, from left to right, even if for the purpose of some tactics it would have been more convenient to have, say, the variables not occurring in the conclusion first. For instance, one would state \begin{quote} \begin{tt} {forall x y z:D, x+z <= y+z -> x <= y} \end{tt} \end{quote} and not \begin{quote} \begin{tt} {forall z x y:D, x+z <= y+z -> x <= y} \end{tt} \end{quote} nor \begin{quote} \begin{tt} {forall x y z:D, y+x <= z+x -> y <= z} \end{tt} \end{quote} \item Choice of effective names is domain-dependent. For instance, on natural numbers, the convention is to use the variables $n$, $m$, $p$, $q$, $r$, $s$ in this order. On generic domains, the convention is to use the letters $x$, $y$, $z$, $t$. When more than three variables are needed, indexing variables It is conventional to use specific names for variables having a special meaning. For instance, $eps$ or $\epsilon$ can be used to denote a number intended to be as small as possible. Also, $q$ and $r$ can be used to denote a quotient and a rest. This is good practice. \end{itemize} \subsection{Disjunctive statements} A disjunctive statement with a computational content will be suffixed by \name{\_inf}. For instance, if \begin{quote} \begin{tt} {forall x y, op x y = zero -> x = zero \/ y = zero} \end{tt} \end{quote} has name \texttt{D\_integral}, then \begin{quote} \begin{tt} {forall x y, op x y = zero -> \{x = zero\} + \{y = zero\}} \end{tt} \end{quote} will have name \texttt{D\_integral\_inf}. As an exception, decidability statements, such as \begin{quote} \begin{tt} {forall x y, \{x = y\} + \{x <> y\}} \end{tt} \end{quote} will have a named ended in \texttt{\_dec}. Idem for cotransitivity lemmas which are inherently computational that are ended in \texttt{\_cotrans}. \subsection{Inductive types constructor names} As a general rule, constructor names start with the name of the inductive type being defined as in \texttt{Inductive Z := Z0 : Z | Zpos : Z -> Z | Zneg : Z -> Z} to the exception of very standard types like \texttt{bool}, \texttt{nat}, \texttt{list}... For inductive predicates, constructor names also start with the name of the notion being defined with one or more suffixes separated with \texttt{\_} for discriminating the different cases as e.g. in \begin{verbatim} Inductive even : nat -> Prop := | even_O : even 0 | even_S n : odd n -> even (S n) with odd : nat -> Prop := | odd_S n : even n -> odd (S n). \end{verbatim} As a general rule, inductive predicate names should be lowercase (to the exception of notions referring to a proper name, e.g. \texttt{Bezout}) and multiple words must be separated by ``{\_}''. As an exception, when extending libraries whose general rule is that predicates names start with a capital letter, the convention of this library should be kept and the separation between multiple words is done by making the initial of each work a capital letter (if one of these words is a proper name, then a ``{\_}'' is added to emphasize that the capital letter is proper and not an application of the rule for marking the change of word). Inductive predicates that characterize the specification of a function should be named after the function it specifies followed by \texttt{\_spec} as in: \begin{verbatim} Inductive nth_spec : list A -> nat -> A -> Prop := | nth_spec_O a l : nth_spec (a :: l) 0 a | nth_spec_S n a b l : nth_spec l n a -> nth_spec (b :: l) (S n) a. \end{verbatim} \section{Equational properties of operations} \subsection{General conventions} If the conclusion is in the other way than listed below, add suffix \name{\_reverse} to the lemma name. \subsection{Specific conventions} \itemrule{Associativity of binary operator {\op} on domain {\D}}{Dop\_assoc} {forall x y z:D, op x (op y z) = op (op x y) z} Remark: Symmetric form: \name{Dop\_assoc\_reverse}: \formula{forall x y z:D, op (op x y) z = op x (op y z)} \itemrule{Commutativity of binary operator {\op} on domain {\D}}{Dop\_comm} {forall x y:D, op x y = op y x} Remark: Avoid \formula{forall x y:D, op y x = op x y}, or at worst, call it \name{Dop\_comm\_reverse} \itemrule{Left neutrality of element elt for binary operator {\op}}{Dop\_elt\_l} {forall x:D, op elt x = x} Remark: In English, ``{\elt} is an identity for {\op}'' seems to be a more common terminology. \itemrule{Right neutrality of element elt for binary operator {\op}}{Dop\_elt\_r} {forall x:D, op x elt = x} Remark: By convention, if the identities are reminiscent to zero or one, they are written 1 and 0 in the name of the property. \itemrule{Left absorption of element elt for binary operator {\op}}{Dop\_elt\_l} {forall x:D, op elt x = elt} Remarks: \begin{itemize} \item In French school, this property is named "elt est absorbant pour op" \item English, the property seems generally named "elt is a zero of op" \item In the context of lattices, this a boundedness property, it may be called "elt is a bound on D", or referring to a (possibly arbitrarily oriented) order "elt is a least element of D" or "elt is a greatest element of D" \end{itemize} \itemrule{Right absorption of element {\elt} for binary operator {\op}}{Dop\_elt\_l [BAD ??]} {forall x:D, op x elt = elt} \itemrule{Left distributivity of binary operator {\op} over {\opPrime} on domain {\D}}{Dop\_op'\_distr\_l} {forall x y z:D, op (op' x y) z = op' (op x z) (op y z)} Remark: Some authors say ``distribution''. \itemrule{Right distributivity of binary operator {\op} over {\opPrime} on domain {\D}}{Dop\_op'\_distr\_r} {forall x y z:D, op z (op' x y) = op' (op z x) (op z y)} Remark: Note the order of arguments. \itemrule{Distributivity of unary operator {\op} over binary op' on domain {\D}}{Dop\_op'\_distr} {forall x y:D, op (op' x y) = op' (op x) (op y)} \itemrule{Distributivity of unary operator {\op} over binary op' on domain {\D}}{Dop\_op'\_distr} {forall x y:D, op (op' x y) = op' (op x) (op y)} Remark: For a non commutative operation with inversion of arguments, as in \formula{forall x y z:D, op (op' x y) = op' (op y) (op y z)}, we may probably still call the property distributivity since there is no ambiguity. Example: \formula{forall n m : Z, -(n+m) = (-n)+(-m)}. Example: \formula{forall l l' : list A, rev (l++l') = (rev l)++(rev l')}. \itemrule{Left extrusion of unary operator {\op} over binary op' on domain {\D}}{Dop\_op'\_distr\_l} {forall x y:D, op (op' x y) = op' (op x) y} Question: Call it left commutativity ?? left swap ? \itemrule{Right extrusion of unary operator {\op} over binary op' on domain {\D}}{Dop\_op'\_distr\_r} {forall x y:D, op (op' x y) = op' x (op y)} \itemrule{Idempotency of binary operator {\op} on domain {\D}}{Dop\_idempotent} {forall x:D, op x x = x} \itemrule{Idempotency of unary operator {\op} on domain {\D}}{Dop\_idempotent} {forall x:D, op (op x) = op x} Remark: This is actually idempotency of {\op} wrt to composition and identity. \itemrule{Idempotency of element elt for binary operator {\op} on domain {\D}}{Dop\_elt\_idempotent} {op elt elt = elt} Remark: Generally useless in CIC for concrete, computable operators Remark: The general definition is ``exists n, iter n op x = x''. \itemrule{Nilpotency of element elt wrt a ring D with additive neutral element {\zero} and multiplicative binary operator {\op}}{Delt\_nilpotent} {op elt elt = zero} Remark: We leave the ring structure of D implicit; the general definition is ``exists n, iter n op elt = zero''. \itemrule{Zero-product property in a ring D with additive neutral element {\zero} and multiplicative binary operator {\op}}{D\_integral} {forall x y, op x y = zero -> x = zero \/ y = zero} Remark: We leave the ring structure of D implicit; the Coq library uses either \texttt{\_is\_O} (for \texttt{nat}), \texttt{\_integral} (for \texttt{Z}, \texttt{Q} and \texttt{R}), \texttt{eq\_mul\_0} (for \texttt{NZ}). Remark: The French school says ``integritΓ©''. \itemrule{Nilpotency of binary operator {\op} wrt to its absorbing element zero in D}{Dop\_nilpotent} {forall x, op x x = zero} Remark: Did not find this definition on the web, but it used in the Coq library (to characterize \name{xor}). \itemrule{Involutivity of unary op on D}{Dop\_involutive} {forall x:D, op (op x) = x} \itemrule{Absorption law on the left for binary operator {\op} over binary operator {\op}' on the left}{Dop\_op'\_absorption\_l\_l} {forall x y:D, op x (op' x y) = x} \itemrule{Absorption law on the left for binary operator {\op} over binary operator {\op}' on the right}{Dop\_op'\_absorption\_l\_r} {forall x y:D, op x (op' y x) = x} Remark: Similarly for \name{Dop\_op'\_absorption\_r\_l} and \name{Dop\_op'\_absorption\_r\_r}. \itemrule{De Morgan law's for binary operators {\opPrime} and {\opSecond} wrt to unary op on domain {\D}}{Dop'\_op''\_de\_morgan, Dop''\_op'\_de\_morgan ?? \mbox{leaving the complementing operation implicit})} {forall x y:D, op (op' x y) = op'' (op x) (op y)\\ forall x y:D, op (op'' x y) = op' (op x) (op y)} \itemrule{Left complementation of binary operator {\op} by means of unary {\opPrime} wrt neutral element {\elt} of {\op} on domain {\D}}{Dop\_op'\_opp\_l} {forall x:D, op (op' x) x = elt} Remark: If the name of the opposite function is reminiscent of the notion of complement (e.g. if it is called \texttt{opp}), one can simply say {Dop\_opp\_l}. \itemrule{Right complementation of binary operator {\op} by means of unary {\op'} wrt neutral element {\elt} of {\op} on domain {\D}}{Dop\_opp\_r} {forall x:D, op x (op' x) = elt} Example: \formula{Radd\_opp\_l: forall r : R, - r + r = 0} \itemrule{Associativity of binary operators {\op} and {\op'}}{Dop\_op'\_assoc} {forall x y z, op x (op' y z) = op (op' x y) z} Example: \formula{forall x y z, x + (y - z) = (x + y) - z} \itemrule{Right extrusion of binary operator {\opPrime} over binary operator {\op}}{Dop\_op'\_extrusion\_r} {forall x y z, op x (op' y z) = op' (op x y) z} Remark: This requires {\op} and {\opPrime} to have their right and left argument respectively and their return types identical. Example: \formula{forall x y z, x + (y - z) = (x + y) - z} Remark: Other less natural combinations are possible, such as \formula{forall x y z, op x (op' y z) = op' y (op x z)}. \itemrule{Left extrusion of binary operator {\opPrime} over binary operator {\op}}{Dop\_op'\_extrusion\_l} {forall x y z, op (op' x y) z = op' x (op y z)} Remark: Operations are not necessarily internal composition laws. It is only required that {\op} and {\opPrime} have their right and left argument respectively and their return type identical. Remark: When the type are heterogeneous, only one extrusion law is possible and it can simply be named {Dop\_op'\_extrusion}. Example: \formula{app\_cons\_extrusion : forall a l l', (a :: l) ++ l' = a :: (l ++ l')}. %====================================================================== %\section{Properties of elements} %Remark: Not used in current library %====================================================================== \section{Preservation and compatibility properties of operations} \subsection{With respect to equality} \itemrule{Injectivity of unary operator {\op}}{Dop\_inj} {forall x y:D, op x = op y -> x = y} \itemrule{Left regularity of binary operator {\op}}{Dop\_reg\_l, Dop\_inj\_l, or Dop\_cancel\_l} {forall x y z:D, op z x = op z y -> x = y} Remark: Note the order of arguments. Remark: The Coq usage is to called it regularity but the English standard seems to be cancellation. The recommended form is not decided yet. Remark: Shall a property like $n^p \leq n^q \rightarrow p \leq q$ (for $n\geq 1$) be called cancellation or should it be reserved for operators that have an inverse? \itemrule{Right regularity of binary operator {\op}}{Dop\_reg\_r, Dop\_inj\_r, Dop\_cancel\_r} {forall x y z:D, op x z = op y z -> x = y} \subsection{With respect to a relation {\rel}} \itemrule{Compatibility of unary operator {\op}}{Dop\_rel\_compat} {forall x y:D, rel x y -> rel (op x) (op y)} \itemrule{Left compatibility of binary operator {\op}}{Dop\_rel\_compat\_l} {forall x y z:D, rel x y -> rel (op z x) (op z y)} \itemrule{Right compatibility of binary operator {\op}}{Dop\_rel\_compat\_r} {forall x y z:D, rel x y -> rel (op x z) (op y z)} Remark: For equality, use names of the form \name{Dop\_eq\_compat\_l} or \name{Dop\_eq\_compat\_r} (\formula{forall x y z:D, y = x -> op y z = op x z} and \formula{forall x y z:D, y = x -> op y z = op x z}) Remark: Should we admit (or even prefer) the name \name{Dop\_rel\_monotone}, \name{Dop\_rel\_monotone\_l}, \name{Dop\_rel\_monotone\_r} when {\rel} is an order ? \itemrule{Left regularity of binary operator {\op}}{Dop\_rel\_reg\_l} {forall x y z:D, rel (op z x) (op z y) -> rel x y} \itemrule{Right regularity of binary operator {\op}}{Dop\_rel\_reg\_r} {forall x y z:D, rel (op x z) (op y z) -> rel x y} Question: Would it be better to have \name{z} as first argument, since it is missing in the conclusion ?? (or admit we shall use the options ``\texttt{with p}''?) \itemrule{Left distributivity of binary operator {\op} over {\opPrime} along relation {\rel} on domain {\D}}{Dop\_op'\_rel\_distr\_l} {forall x y z:D, rel (op (op' x y) z) (op' (op x z) (op y z))} Example: standard property of (not necessarily distributive) lattices Remark: In a (non distributive) lattice, by swapping join and meet, one would like also, \formula{forall x y z:D, rel (op' (op x z) (op y z)) (op (op' x y) z)}. How to name it with a symmetric name (use \name{Dop\_op'\_rel\_distr\_mon\_l} and \name{Dop\_op'\_rel\_distr\_anti\_l})? \itemrule{Commutativity of binary operator {\op} along (equivalence) relation {\rel} on domain {\D}}{Dop\_op'\_rel\_comm} {forall x y z:D, rel (op x y) (op y x)} Example: \formula{forall l l':list A, Permutation (l++l') (l'++l)} \itemrule{Irreducibility of binary operator {\op} on domain {\D}}{Dop\_irreducible} {forall x y z:D, z = op x y -> z = x $\backslash/$ z = y} Question: What about the constructive version ? Call it \name{Dop\_irreducible\_inf} ? \formula{forall x y z:D, z = op x y -> \{z = x\} + \{z = y\}} \itemrule{Primality of binary operator {\op} along relation {\rel} on domain {\D}}{Dop\_rel\_prime} {forall x y z:D, rel z (op x y) -> rel z x $\backslash/$ rel z y} %====================================================================== \section{Morphisms} \itemrule{Morphism between structures {\D} and {\D'}}{\name{D'\_of\_D}}{D -> D'} Remark: If the domains are one-letter long, one can used \texttt{IDD'} as for \name{INR} or \name{INZ}. \itemrule{Morphism {\phimapping} mapping unary operators {\op} to {\op'}}{phi\_op\_op', phi\_op\_op'\_morphism} {forall x:D, phi (op x) = op' (phi x)} Remark: If the operators have the same name in both domains, one use \texttt{D'\_of\_D\_op} or \texttt{IDD'\_op}. Example: \formula{Z\_of\_nat\_mult: forall n m : nat, Z\_of\_nat (n * m) = (Z\_of\_nat n * Z\_of\_nat m)\%Z}. Remark: If the operators have different names on distinct domains, one can use \texttt{op\_op'}. \itemrule{Morphism {\phimapping} mapping binary operators {\op} to {\op'}}{phi\_op\_op', phi\_op\_op'\_morphism} {forall x y:D, phi (op x y) = op' (phi x) (phi y)} Remark: If the operators have the same name in both domains, one use \texttt{D'\_of\_D\_op} or \texttt{IDD'\_op}. Remark: If the operators have different names on distinct domains, one can use \texttt{op\_op'}. \itemrule{Morphism {\phimapping} mapping binary operator {\op} to binary relation {\rel}}{phi\_op\_rel, phi\_op\_rel\_morphism} {forall x y:D, phi (op x y) <-> rel (phi x) (phi y)} Remark: If the operator and the relation have similar name, one uses \texttt{phi\_op}. Question: How to name each direction? (add \_elim for -> and \_intro for <- ?? -- as done in Bool.v ??) Example: \formula{eq\_true\_neg: \~{} eq\_true b <-> eq\_true (negb b)}. %====================================================================== \section{Preservation and compatibility properties of operations wrt order} \itemrule{Compatibility of binary operator {\op} wrt (strict order) {\rel} and (large order) {\rel'}}{Dop\_rel\_rel'\_compat} {forall x y z t:D, rel x y -> rel' z t -> rel (op x z) (op y t)} \itemrule{Compatibility of binary operator {\op} wrt (large order) {\relp} and (strict order) {\rel}}{Dop\_rel'\_rel\_compat} {forall x y z t:D, rel' x y -> rel z t -> rel (op x z) (op y t)} %====================================================================== \section{Properties of relations} \itemrule{Reflexivity of relation {\rel} on domain {\D}}{Drel\_refl} {forall x:D, rel x x} \itemrule{Symmetry of relation {\rel} on domain {\D}}{Drel\_sym} {forall x y:D, rel x y -> rel y x} \itemrule{Transitivity of relation {\rel} on domain {\D}}{Drel\_trans} {forall x y z:D, rel x y -> rel y z -> rel x z} \itemrule{Antisymmetry of relation {\rel} on domain {\D}}{Drel\_antisym} {forall x y:D, rel x y -> rel y x -> x = y} \itemrule{Irreflexivity of relation {\rel} on domain {\D}}{Drel\_irrefl} {forall x:D, \~{} rel x x} \itemrule{Asymmetry of relation {\rel} on domain {\D}}{Drel\_asym} {forall x y:D, rel x y -> \~{} rel y x} \itemrule{Cotransitivity of relation {\rel} on domain {\D}}{Drel\_cotrans} {forall x y z:D, rel x y -> \{rel z y\} + \{rel x z\}} \itemrule{Linearity of relation {\rel} on domain {\D}}{Drel\_trichotomy} {forall x y:D, \{rel x y\} + \{x = y\} + \{rel y x\}} Questions: Or call it \name{Drel\_total}, or \name{Drel\_linear}, or \name{Drel\_connected}? Use $\backslash/$ ? or use a ternary sumbool, or a ternary disjunction, for nicer elimination. \itemrule{Informative decidability of relation {\rel} on domain {\D}}{Drel\_dec (or Drel\_dect, Drel\_dec\_inf ?)} {forall x y:D, \{rel x y\} + \{\~{} rel x y\}} Remark: If equality: \name{D\_eq\_dec} or \name{D\_dec} (not like \name{eq\_nat\_dec}) \itemrule{Non informative decidability of relation {\rel} on domain {\D}}{Drel\_dec\_prop (or Drel\_dec)} {forall x y:D, rel x y $\backslash/$ \~{} rel x y} \itemrule{Inclusion of relation {\rel} in relation {\rel}' on domain {\D}}{Drel\_rel'\_incl (or Drel\_incl\_rel')} {forall x y:D, rel x y -> rel' x y} Remark: Use \name{Drel\_rel'\_weak} for a strict inclusion ?? %====================================================================== \section{Relations between properties} \itemrule{Equivalence of properties \texttt{P} and \texttt{Q}}{P\_Q\_iff} {forall x1 .. xn, P <-> Q} Remark: Alternatively use \name{P\_iff\_Q} if it is too difficult to recover what pertains to \texttt{P} and what pertains to \texttt{Q} in their concatenation (as e.g. in \texttt{Godel\_Dummett\_iff\_right\_distr\_implication\_over\_disjunction}). %====================================================================== \section{Arithmetical conventions} \begin{minipage}{6in} \renewcommand{\thefootnote}{\thempfootnote} % For footnotes... \begin{tabular}{lll} Zero on domain {\D} & D0 & (notation \verb=0=)\\ One on domain {\D} & D1 (if explicitly defined) & (notation \verb=1=)\\ Successor on domain {\D} & Dsucc\\ Predecessor on domain {\D} & Dpred\\ Addition on domain {\D} & Dadd/Dplus\footnote{Coq historically uses \texttt{plus} and \texttt{mult} for addition and multiplication which are inconsistent notations, the recommendation is to use \texttt{add} and \texttt{mul} except in existing libraries that already use \texttt{plus} and \texttt{mult}} & (infix notation \verb=+= [50,L])\\ Multiplication on domain {\D} & Dmul/Dmult\footnotemark[\value{footnote}] & (infix notation \verb=*= [40,L]))\\ Subtraction on domain {\D} & Dminus & (infix notation \verb=-= [50,L])\\ Opposite on domain {\D} & Dopp (if any) & (prefix notation \verb=-= [35,R]))\\ Inverse on domain {\D} & Dinv (if any) & (prefix notation \verb=/= [35,R]))\\ Power on domain {\D} & Dpower & (infix notation \verb=^= [30,R])\\ Minimal element on domain {\D} & Dmin\\ Maximal element on domain {\D} & Dmax\\ Large less than order on {\D} & Dle & (infix notations \verb!<=! and \verb!>=! [70,N]))\\ Strict less than order on {\D} & Dlt & (infix notations \verb=<= and \verb=>= [70,N]))\\ \end{tabular} \bigskip \end{minipage} \bigskip The status of \verb!>=! and \verb!>! is undecided yet. It will eithet be accepted only as parsing notations or may also accepted as a {\em definition} for the \verb!<=! and \verb! ... \end{verbatim} ce qui introduit un constructeur moralement Γ©quivalent Γ  une application situΓ© Γ  une prioritΓ© totalement diffΓ©rente (les ``bindings'' seraient au plus haut niveau alors que l'application est Γ  un niveau bas). \begin{figure} \begin{rulebox} \DEFNT{binding-term} \NT{constr} ~\TERM{with} ~\STAR{\NT{binding}} \SEPDEF \DEFNT{binding} \NT{constr} \end{rulebox} \caption{Grammaire des bindings} \label{bindings} \end{figure} \subsection{Enregistrements} Il faudrait amΓ©nager la syntaxe des enregistrements dans l'optique d'avoir des enregistrements anonymes (termes de premiΓ¨re classe), mΓͺme si pour l'instant, on ne dispose que d'enregistrements dΓ©finis a toplevel. Exemple de syntaxe pour les types d'enregistrements: \begin{verbatim} { x1 : A1; x2 : A2(x1); _ : T; (* Pas de projection disponible *) y; (* Type infere *) ... (* ; optionnel pour le dernier champ *) } \end{verbatim} Exemple de syntaxe pour le constructeur: \begin{verbatim} { x1 = O; x2 : A2(x1) = v1; _ = v2; ... } \end{verbatim} Quant aux dΓ©pendences, une convention pourrait Γͺtre de considΓ©rer les champs non annotΓ©s par le type comme non dΓ©pendants. Plusieurs interrogations: \begin{itemize} \item l'ordre des champs doit-il Γͺtre respectΓ© ? sinon, que faire pour les champs sans projection ? \item autorise-t-on \texttt{v1} a mentionner \texttt{x1} (comme dans la dΓ©finition d'un module), ce qui se comporterait comme si on avait Γ©crit \texttt{v1} Γ  la place. Cela pourrait Γͺtre une autre maniΓ¨re de dΓ©clarer les dΓ©pendences \end{itemize} La notation pointΓ©e pour les projections pose un problΓ¨me de parsing, sauf si l'on a une convention lexicale qui discrimine les noms de modules des projections et identificateurs: \texttt{x.y.z} peut Γͺtre compris comme \texttt{(x.y).z} ou texttt{x.(y.z)}. \section{Grammaire des termes} \label{constrsyntax} \subsection{Quelques principes} \begin{enumerate} \item Diminuer le nombre de niveaux de prioritΓ© en regroupant les rΓ¨gles qui se ressemblent: infixes, prΓ©fixes, lieurs (constructions ouvertes Γ  droite), etc. \item Γ‰viter de surcharger la signification d'un symbole (ex: \verb+( )+ comme parenthΓ©sage et produit dans la V7). \item Faire en sorte que les membres gauches (motifs de Cases, lieurs d'abstraction ou de produits) utilisent une syntaxe compatible avec celle des membres droits (branches de Cases et corps de fonction). \end{enumerate} \subsection{PrΓ©sentation de la grammaire} \begin{figure} \begin{rulebox} \DEFNT{paren-constr} \NT{cast-constr}~\TERM{,}~\NT{paren-constr} &\RNAME{pair} \nlsep \NT{cast-constr} \SEPDEF \DEFNT{cast-constr} \NT{constr}~\TERM{\!\!:}~\NT{cast-constr} &\RNAME{cast} \nlsep \NT{constr} \SEPDEF \DEFNT{constr} \NT{appl-constr}~\NT{infix}~\NT{constr} &\RNAME{infix} \nlsep \NT{prefix}~\NT{constr} &\RNAME{prefix} \nlsep \NT{constr}~\NT{postfix} &\RNAME{postfix} \nlsep \NT{appl-constr} \SEPDEF \DEFNT{appl-constr} \NT{appl-constr}~\PLUS{\NT{appl-arg}} &\RNAME{apply} \nlsep \TERM{@}~\NT{global}~\PLUS{\NT{simple-constr}} &\RNAME{expl-apply} \nlsep \NT{simple-constr} \SEPDEF \DEFNT{appl-arg} \TERM{@}~\NT{int}~\TERM{\!:=}~\NT{simple-constr} &\RNAME{impl-arg} \nlsep \NT{simple-constr} \SEPDEF \DEFNT{simple-constr} \NT{atomic-constr} \nlsep \TERM{(}~\NT{paren-constr}~\TERM{)} \nlsep \NT{match-constr} \nlsep \NT{fix-constr} %% \nlsep \TERM{<\!\!:ast\!\!:<}~\NT{ast}~\TERM{>\!>} &\RNAME{quotation} \end{rulebox} \caption{Grammaire des termes} \label{constr} \end{figure} \begin{figure} \begin{rulebox} \DEFNT{prefix} \TERM{!}~\PLUS{\NT{binder}}~\TERM{.}~ &\RNAME{prod} \nlsep \TERM{fun} ~\PLUS{\NT{binder}} ~\TERM{$\Rightarrow$} &\RNAME{lambda} \nlsep \TERM{let}~\NT{ident}~\STAR{\NT{binder}} ~\TERM{=}~\NT{constr} ~\TERM{in} &\RNAME{let} %\nlsep \TERM{let (}~\NT{comma-ident-list}~\TERM{) =}~\NT{constr} % ~\TERM{in} &~~~\RNAME{let-case} \nlsep \TERM{if}~\NT{constr}~\TERM{then}~\NT{constr}~\TERM{else} &\RNAME{if-case} \nlsep \TERM{eval}~\NT{red-fun}~\TERM{in} &\RNAME{eval} \SEPDEF \DEFNT{infix} \TERM{$\rightarrow$} & \RNAME{impl} \SEPDEF \DEFNT{atomic-constr} \TERM{_} \nlsep \TERM{?}\NT{int} \nlsep \NT{sort} \nlsep \NT{global} \SEPDEF \DEFNT{binder} \NT{ident} &\RNAME{infer} \nlsep \TERM{(}~\NT{ident}~\NT{type}~\TERM{)} &\RNAME{binder} \SEPDEF \DEFNT{type} \TERM{\!:}~\NT{constr} \nlsep \epsilon \end{rulebox} \caption{Grammaires annexes aux termes} \label{gram-annexes} \end{figure} La grammaire des termes (correspondant Γ  l'Γ©tat \texttt{barestate}) est dΓ©crite figures~\ref{constr} et~\ref{gram-annexes}. On constate par rapport aux prΓ©cΓ©dentes versions de Coq d'importants changements de prioritΓ©, le plus marquant Γ©tant celui de l'application qui se trouve dΓ©sormais juste au dessus\footnote{La convention est de considΓ©rer les opΓ©rateurs moins lieurs comme ``au dessus'', c'est-Γ -dire ayant un niveau de prioritΓ© plus Γ©lΓ©vΓ© (comme c'est le cas avec le niveau de la grammaire actuelle des termes).} des constructions fermΓ©es Γ  gauche et Γ  droite. La grammaire des noms globaux est la suivante: \begin{eqnarray*} \DEFNT{global} \NT{ident} %% \nlsep \TERM{\$}\NT{ident} \nlsep \NT{ident}\TERM{.}\NT{global} \end{eqnarray*} Le $\TERM{_}$ dΓ©note les termes Γ  synthΓ©tiser. Les mΓ©tavariables sont reconnues au niveau du lexer pour ne pas entrer en conflit avec le $\TERM{?}$ de l'existentielle. Les opΓ©rateurs infixes ou prΓ©fixes sont tous au mΓͺme niveau de prioritΓ© du point de vue de Camlp4. La solution envisagΓ©e est de les gΓ©rer Γ  la maniΓ¨re de Yacc, avec une pile (voir discussions plus bas). Ainsi, l'implication est un infixe normal; la quantification universelle et le let sont vus comme des opΓ©rateurs prΓ©fixes avec un niveau de prioritΓ© plus haut (i.e. moins lieur). Il subsiste des problΓ¨mes si l'on ne veut pas Γ©crire de parenthΓ¨ses dans: \begin{verbatim} A -> (!x. B -> (let y = C in D)) \end{verbatim} La solution proposΓ©e est d'analyser le membre droit d'un infixe de maniΓ¨re Γ  autoriser les prΓ©fixes et les infixes de niveau infΓ©rieur, et d'exiger le parenthΓ©sage que pour les infixes de niveau supΓ©rieurs. En revanche, Γ  l'affichage, certains membres droits seront plus lisibles s'ils n'utilisent pas cette astuce: \begin{verbatim} (fun x => x) = fun x => x \end{verbatim} La proposition est d'autoriser ce type d'Γ©critures au parsing, mais l'afficheur Γ©crit de maniΓ¨re standardisΓ©e en mettant quelques parenthΓ¨ses superflues: $\TERM{=}$ serait symΓ©trique alors que $\rightarrow$ appellerait l'afficheur de prioritΓ© Γ©levΓ©e pour son sous-terme droit. Les prioritΓ©s des opΓ©rateurs primitifs sont les suivantes (le signe $*$ signifie que pour le membre droit les opΓ©rateurs prΓ©fixes seront affichΓ©s sans parenthΓ¨ses quel que soit leur prioritΓ©): $$ \begin{array}{c|l} $symbole$ & $prioritΓ©$ \\ \hline \TERM{!} & 200\,R* \\ \TERM{fun} & 200\,R* \\ \TERM{let} & 200\,R* \\ \TERM{if} & 200\,R \\ \TERM{eval} & 200\,R \\ \rightarrow & 90\,R* \end{array} $$ Il y a deux points d'entrΓ©e pour les termes: $\NT{constr}$ et $\NT{simple-constr}$. Le premier peut Γͺtre utilisΓ© lorsqu'il est suivi d'un sΓ©parateur particulier. Dans le cas oΓΉ l'on veut une liste de termes sΓ©parΓ©s par un espace, il faut lire des $\NT{simple-constr}$. Les constructions $\TERM{fix}$ et $\TERM{cofix}$ (voir aussi figure~\ref{gram-fix}) sont fermΓ©es par end pour simplifier l'analyse. Sinon, une expression de point fixe peut Γͺtre suivie par un \TERM{in} ou un \TERM{and}, ce qui pose les mΓͺmes problΓ¨mes que le ``dangling else'': dans \begin{verbatim} fix f1 x {x} = fix f2 y {y} = ... and ... in ... \end{verbatim} il faut dΓ©finir une stratΓ©gie pour associer le \TERM{and} et le \TERM{in} au bon point fixe. Un autre avantage est de faire apparaitre que le \TERM{fix} est un constructeur de terme de premiΓ¨re classe et pas un lieur: \begin{verbatim} fix f1 ... and f2 ... in f1 end x \end{verbatim} Les propositions prΓ©cΓ©dentes laissaient \texttt{f1} et \texttt{x} accolΓ©s, ce qui est source de confusion lorsque l'on fait par exemple \texttt{Pattern (f1 x)}. Les corps de points fixes et co-points fixes sont identiques, bien que ces derniers n'aient pas d'information de dΓ©croissance. Cela fonctionne puisque l'annotation est optionnelle. Cela prΓ©figure des cas oΓΉ l'on arrive Γ  infΓ©rer quel est l'argument qui dΓ©croit structurellement (en particulier dans le cas oΓΉ il n'y a qu'un seul argument). \begin{figure} \begin{rulebox} \DEFNT{fix-expr} \TERM{fix}~\NT{fix-decls} ~\NT{fix-select} ~\TERM{end} &\RNAME{fix} \nlsep \TERM{cofix}~\NT{cofix-decls}~\NT{fix-select} ~\TERM{end} &\RNAME{cofix} \SEPDEF \DEFNT{fix-decls} \NT{fix-decl}~\TERM{and}~\NT{fix-decls} \nlsep \NT{fix-decl} \SEPDEF \DEFNT{fix-decl} \NT{ident}~\PLUS{\NT{binder}}~\NT{type}~\NT{annot} ~\TERM{=}~\NT{constr} \SEPDEF \DEFNT{annot} \TERM{\{}~\NT{ident}~\TERM{\}} \nlsep \epsilon \SEPDEF \DEFNT{fix-select} \TERM{in}~\NT{ident} \nlsep \epsilon \end{rulebox} \caption{Grammaires annexes des points fixes} \label{gram-fix} \end{figure} La construction $\TERM{Case}$ peut-Γͺtre considΓ©rΓ©e comme obsolΓ¨te. Quant au $\TERM{Match}$ de la V6, il disparaΓt purement et simplement. \begin{figure} \begin{rulebox} \DEFNT{match-expr} \TERM{match}~\NT{case-items}~\NT{case-type}~\TERM{with}~ \NT{branches}~\TERM{end} &\RNAME{match} \nlsep \TERM{match}~\NT{case-items}~\TERM{with}~ \NT{branches}~\TERM{end} &\RNAME{infer-match} %%\nlsep \TERM{case}~\NT{constr}~\NT{case-predicate}~\TERM{of}~ %% \STAR{\NT{constr}}~\TERM{end} &\RNAME{case} \SEPDEF \DEFNT{case-items} \NT{case-item} ~\TERM{\&} ~\NT{case-items} \nlsep \NT{case-item} \SEPDEF \DEFNT{case-item} \NT{constr}~\NT{pred-pattern} &\RNAME{dep-case} \nlsep \NT{constr} &\RNAME{nodep-case} \SEPDEF \DEFNT{case-type} \TERM{$\Rightarrow$}~\NT{constr} \nlsep \epsilon \SEPDEF \DEFNT{pred-pattern} \TERM{as}~\NT{ident} ~\TERM{\!:}~\NT{constr} \SEPDEF \DEFNT{branches} \TERM{|} ~\NT{patterns} ~\TERM{$\Rightarrow$} ~\NT{constr} ~\NT{branches} \nlsep \epsilon \SEPDEF \DEFNT{patterns} \NT{pattern} ~\TERM{\&} ~\NT{patterns} \nlsep \NT{pattern} \SEPDEF \DEFNT{pattern} ... \end{rulebox} \caption{Grammaires annexes du filtrage} \label{gram-match} \end{figure} De maniΓ¨re globale, l'introduction de dΓ©finitions dans les termes se fait avec le symbole $=$, et le $\!:=$ est rΓ©servΓ© aux dΓ©finitions au niveau vernac. Il y avait un manque de cohΓ©rence dans la V6, puisque l'on utilisait $=$ pour le $\TERM{let}$ et $\!:=$ pour les points fixes et les commandes vernac. % OBSOLETE: lieurs multiples supprimes %On peut remarquer que $\NT{binder}$ est un sous-ensemble de %$\NT{simple-constr}$, Γ  l'exception de $\texttt{(a,b\!\!:T)}$: en tant %que lieur, {\tt a} et {\tt b} sont tous deux contraints, alors qu'en %tant que terme, seul {\tt b} l'est. Cela qui signifie que l'objectif %de rendre compatibles les membres gauches et droits est {\it presque} %atteint. \subsection{Infixes} \subsubsection{Infixes extensibles} Le problΓ¨me de savoir si la liste des symboles pouvant apparaΓtre en infixe est fixΓ©e ou extensible par l'utilisateur reste Γ  voir. Notons que la solution oΓΉ les symboles infixes sont des identificateurs que l'on peut dΓ©finir paraΓt difficilement praticable: par exemple $\texttt{Logic.eq}$ n'est pas un opΓ©rateur binaire, mais ternaire. Il semble plus simple de garder des dΓ©clarations infixes qui relient un symbole infixe Γ  un terme avec deux ``trous''. Par exemple: $$\begin{array}{c|l} $infixe$ & $identificateur$ \\ \hline = & \texttt{Logic.eq _ ?1 ?2} \\ == & \texttt{JohnMajor.eq _ ?1 _ ?2} \end{array}$$ La syntaxe d'une dΓ©claration d'infixe serait par exemple: \begin{verbatim} Infix "=" 50 := Logic.eq _ ?1 ?2; \end{verbatim} \subsubsection{Gestion des prΓ©cΓ©dences} Les infixes peuvent Γͺtre soit laissΓ© Γ  Camlp4, ou bien (comme ici) considΓ©rer que tous les opΓ©rateurs ont la mΓͺme prΓ©cΓ©dence et gΓ©rer soit mΓͺme la recomposition des termes Γ  l'aide d'une pile (comme Yacc). \subsection{Extensions de syntaxe} \subsubsection{LitΓ©raux numΓ©riques} La proposition est de considerer les litΓ©raux numΓ©riques comme de simples identificateurs. Comme il en existe une infinitΓ©, il faut un nouveau mΓ©canisme pour leur associer une dΓ©finition. Par exemple, en ce qui concerne \texttt{Arith}, la dΓ©finition de $5$ serait $\texttt{S}~4$. Pour \texttt{ZArith}, $5$ serait $\texttt{xI}~2$. Comme les infixes, les constantes numΓ©riques peuvent Γͺtre qualifiΓ©es pour indiquer dans quels module est le type que l'on veut rΓ©fΓ©rencer. Par exemple (si on renomme \texttt{Arith} en \texttt{N} et \texttt{ZArith} en \texttt{Z}): \verb+N.5+, \verb+Z.5+. \begin{eqnarray*} \EXTNT{global} \NT{int} \end{eqnarray*} \subsubsection{Nouveaux lieurs} $$ \begin{array}{rclr} \EXTNT{constr} \TERM{ex}~\PLUS{\NT{binder}}~\TERM{.}~\NT{constr} &\RNAME{ex} \nlsep \TERM{ex}~\PLUS{\NT{binder}}~\TERM{.}~\NT{constr}~\TERM{,}~\NT{constr} &\RNAME{ex2} \nlsep \TERM{ext}~\PLUS{\NT{binder}}~\TERM{.}~\NT{constr} &\RNAME{exT} \nlsep \TERM{ext}~\PLUS{\NT{binder}}~\TERM{.}~\NT{constr}~\TERM{,}~\NT{constr} &\RNAME{exT2} \end{array} $$ Pour l'instant l'existentielle n'admet qu'une seule variable, ce qui oblige Γ  Γ©crire des cascades de $\TERM{ex}$. Pour parser les existentielles avec deux prΓ©dicats, on peut considΓ©rer \TERM{\&} comme un infixe intermΓ©diaire et l'opΓ©rateur existentiel en prΓ©sence de cet infixe se transforme en \texttt{ex2}. \subsubsection{Nouveaux infixes} PrΓ©cΓ©dences des opΓ©rateurs infixes (les plus grands associent moins fort): $$ \begin{array}{l|l|c|l} $identificateur$ & $module$ & $infixe/prΓ©fixe$ & $prΓ©cΓ©dence$ \\ \hline \texttt{iff} & $Logic$ & \longleftrightarrow & 100 \\ \texttt{or} & $Logic$ & \vee & 80\, R \\ \texttt{sum} & $Datatypes$ & + & 80\, R \\ \texttt{and} & $Logic$ & \wedge & 70\, R \\ \texttt{prod} & $Datatypes$ & * & 70\, R \\ \texttt{not} & $Logic$ & \tilde{} & 60\, L \\ \texttt{eq _} & $Logic$ & = & 50 \\ \texttt{eqT _} & $Logic_Type$ & = & 50 \\ \texttt{identityT _} & $Data_Type$ & = & 50 \\ \texttt{le} & $Peano$ & $<=$ & 50 \\ \texttt{lt} & $Peano$ & $<$ & 50 \\ \texttt{ge} & $Peano$ & $>=$ & 50 \\ \texttt{gt} & $Peano$ & $>$ & 50 \\ \texttt{Zle} & $zarith_aux$ & $<=$ & 50 \\ \texttt{Zlt} & $zarith_aux$ & $<$ & 50 \\ \texttt{Zge} & $zarith_aux$ & $>=$ & 50 \\ \texttt{Zgt} & $zarith_aux$ & $>$ & 50 \\ \texttt{Rle} & $Rdefinitions$ & $<=$ & 50 \\ \texttt{Rlt} & $Rdefinitions$ & $<$ & 50 \\ \texttt{Rge} & $Rdefinitions$ & $>=$ & 50 \\ \texttt{Rgt} & $Rdefinitions$ & $>$ & 50 \\ \texttt{plus} & $Peano$ & + & 40\,L \\ \texttt{Zplus} & $fast_integer$ & + & 40\,L \\ \texttt{Rplus} & $Rdefinitions$ & + & 40\,L \\ \texttt{minus} & $Minus$ & - & 40\,L \\ \texttt{Zminus} & $zarith_aux$ & - & 40\,L \\ \texttt{Rminus} & $Rdefinitions$ & - & 40\,L \\ \texttt{Zopp} & $fast_integer$ & - & 40\,L \\ \texttt{Ropp} & $Rdefinitions$ & - & 40\,L \\ \texttt{mult} & $Peano$ & * & 30\,L \\ \texttt{Zmult} & $fast_integer$ & * & 30\,L \\ \texttt{Rmult} & $Rdefinitions$ & * & 30\,L \\ \texttt{Rdiv} & $Rdefinitions$ & / & 30\,L \\ \texttt{pow} & $Rfunctions$ & \hat & 20\,L \\ \texttt{fact} & $Rfunctions$ & ! & 20\,L \\ \end{array} $$ Notons qu'il faudrait dΓ©couper {\tt Logic_Type} en deux car celui-ci dΓ©finit deux Γ©galitΓ©s, ou alors les mettre dans des modules diffΓ©rents. \subsection{Exemples} \begin{verbatim} Definition not (A:Prop) := A->False; Inductive eq (A:Set) (x:A) : A->Prop := refl_equal : eq A x x; Inductive ex (A:Set) (P:A->Prop) : Prop := ex_intro : !x. P x -> ex A P; Lemma not_all_ex_not : !(P:U->Prop). ~(!n. P n) -> ?n. ~ P n; Fixpoint plus n m : nat {struct n} := match n with O => m | (S k) => S (plus k m) end; \end{verbatim} \subsection{Questions ouvertes} Voici les points sur lesquels la discussion est particuliΓ¨rement ouverte: \begin{itemize} \item choix d'autres symboles pour les quantificateurs \TERM{!} et \TERM{?}. En l'Γ©tat actuel des discussions, on garderait le \TERM{!} pour la qunatification universelle, mais on choisirait quelquechose comme \TERM{ex} pour l'existentielle, afin de ne pas suggΓ©rer trop de symΓ©trie entre ces quantificateurs (l'un est primitif, l'autre pas). \item syntaxe particuliΓ¨re pour les \texttt{sig}, \texttt{sumor}, etc. \item la possibilitΓ© d'introduire plusieurs variables du mΓͺme type est pour l'instant supprimΓ©e au vu des problΓ¨mes de compatibilitΓ© de syntaxe entre les membres gauches et membres droits. L'idΓ©e Γ©tant que l'inference de type permet d'Γ©viter le besoin de dΓ©clarer tous les types. \end{itemize} \subsection{Autres extensions} \subsubsection{Lieur multiple} L'Γ©criture de types en prΓ©sence de polymorphisme est souvent assez pΓ©nible: \begin{verbatim} Check !(A:Set) (x:A) (B:Set) (y:B). P A x B y; \end{verbatim} On pourrait avoir des dΓ©clarations introduisant Γ  la fois un type d'une certaine sorte et une variable de ce type: \begin{verbatim} Check !(x:A:Set) (y:B:Set). P A x B y; \end{verbatim} Noter que l'on aurait pu Γ©crire: \begin{verbatim} Check !A x B y. P A (x:A:Set) B (y:B:Set); \end{verbatim} \section{Syntaxe des tactiques} \subsection{Questions diverses} Changer ``Pattern nl c ... nl c'' en ``Pattern [ nl ] c ... [ nl ] c'' pour permettre des chiffres seuls dans la catΓ©gorie syntaxique des termes. Par uniformitΓ© remplacer ``Unfold nl c'' par ``Unfold [ nl ] c'' ? MΓͺme problΓ¨me pour l'entier de Specialize (ou virer Specialize ?) ? \subsection{Questions en suspens} \verb=EAuto= : deux syntaxes diffΓ©rentes pour la recherche en largeur et en profondeur ? Quelle recherche par dΓ©faut ? \section*{Remarques pΓͺle-mΓͺle (HH)} Autoriser la syntaxe \begin{verbatim} Variable R (a : A) (b : B) : Prop. Hypotheses H (a : A) (b : B) : Prop; Y (u : U) : V. Variables H (a : A) (b : B), J (k : K) : nat; Z (v : V) : Set. \end{verbatim} Renommer eqT, refl_eqT, eqT_ind, eqT_rect, eqT_rec en eq, refl_equal, etc. Remplacer == en =. Mettre des \verb=?x= plutot que des \verb=?1= dans les motifs de ltac ?? \section{Moulinette} \begin{itemize} \item Mettre \verb=/= et * au mΓͺme niveau dans R. \item Changer la prΓ©cΓ©dence du - unaire dans R. \item Ajouter Require Arith par necessite si Require ArithRing ou Require ZArithRing. \item Ajouter Require ZArith par necessite si Require ZArithRing ou Require Omega. \item Enlever le Export de Bool, Arith et ZARith de Ring quand inappropriΓ© et l'ajouter Γ  cΓ΄tΓ© des Require Ring. \item Remplacer "Check n" par "n:Check ..." \item Renommer Variable/Hypothesis hors section en Parameter/Axiom. \item Renommer les \verb=command0=, \verb=command1=, ... \verb=lcommand= etc en \verb=constr0=, \verb=constr1=, ... \verb=lconstr=. \item Remplacer les noms Coq.omega.Omega par Coq.Omega ... \item Remplacer AddPath par Add LoadPath (ou + court) \item Unify + and \{\}+\{\} and +\{\} using Prop $\leq$ Set ?? \item Remplacer Implicit Arguments On/Off par Set/Unset Implicit Arguments. \item La syntaxe \verb=Intros (a,b)= est inutile, \verb=Intros [a b]= fait l'affaire. \item Virer \verb=Goal= sans argument (synonyme de \verb=Proof= et sans effets). \item Remplacer Save. par Qed. \item Remplacer \verb=Zmult_Zplus_distr= par \verb=Zmult_plus_distr_r= et \verb=Zmult_plus_distr= par \verb=Zmult_plus_distr_l=. \end{itemize} \end{document} rocq-9.2.0/dev/doc/archive/notes-on-conversion.v000066400000000000000000000050141516144147600215570ustar00rootroot00000000000000(**********************************************************************) (* A few examples showing the current limits of the conversion algorithm *) (**********************************************************************) (*** We define (pseudo-)divergence from Ackermann function ***) Definition ack (n : nat) := (fix F (n0 : nat) : nat -> nat := match n0 with | O => S | S n1 => fun m : nat => (fix F0 (n2 : nat) : nat := match n2 with | O => F n1 1 | S n3 => F n1 (F0 n3) end) m end) n. Notation OMEGA := (ack 4 4). Definition f (x:nat) := x. (* Evaluation in tactics can somehow be controlled *) Lemma l1 : OMEGA = OMEGA. reflexivity. (* succeed: identity *) Qed. (* succeed: identity *) Lemma l2 : OMEGA = f OMEGA. reflexivity. (* fail: conversion wants to convert OMEGA with f OMEGA *) Abort. (* but it reduces the right side first! *) Lemma l3 : f OMEGA = OMEGA. reflexivity. (* succeed: reduce left side first *) Qed. (* succeed: expected concl (the one with f) is on the left *) Lemma l4 : OMEGA = OMEGA. assert (f OMEGA = OMEGA) by reflexivity. (* succeed *) unfold f in H. (* succeed: no type-checking *) exact H. (* succeed: identity *) Qed. (* fail: "f" is on the left *) (* This example would fail whatever the preferred side is *) Lemma l5 : OMEGA = f OMEGA. unfold f. assert (f OMEGA = OMEGA) by reflexivity. unfold f in H. exact H. Qed. (* needs to convert (f OMEGA = OMEGA) and (OMEGA = f OMEGA) *) (**********************************************************************) (* Analysis of the inefficiency in Nijmegen/LinAlg/LinAlg/subspace_dim.v *) (* (proof of span_ind_uninject_prop *) In the proof, a problem of the form (Equal S t1 t2) is "simpl"ified, then "red"uced to (Equal S' t1 t1) where the new t1's are surrounded by invisible coercions. A reflexivity steps conclude the proof. The trick is that Equal projects the equality in the setoid S, and that (Equal S) itself reduces to some (fun x y => Equal S' (f x) (g y)). At the Qed time, the problem to solve is (Equal S t1 t2) = (Equal S' t1 t1) and the algorithm is to first compare S and S', and t1 and t2. Unfortunately it does not work, and since t1 and t2 involve concrete instances of algebraic structures, it takes a lot of time to realize that it is not convertible. The only hope to improve this problem is to observe that S' hides (behind two indirections) a Setoid constructor. This could be the argument to solve the problem. rocq-9.2.0/dev/doc/archive/old_svn_branches.txt000066400000000000000000000025011516144147600215130ustar00rootroot00000000000000## During the migration to git, some old branches and tags have not been ## converted to directly visible git branches or tags. They are still there ## in the archive, their names on the gforge repository are in the 3rd ## column below (e.g. remotes/V8-0-bugfix). After a git clone, they ## could always be accessed by their git hashref (2nd column below). # SVN # GIT # Symbolic name on gforge repository r5 d2f789d remotes/tags/start r1714 0605b7c remotes/V7 r2583 372f3f0 remotes/tags/modules-2-branching r2603 6e15d9a remotes/modules r2866 76a93fa remotes/tags/modules-2-before-grammar r2951 356f749 remotes/tags/before-modules r2952 8ee67df remotes/tags/modules-2-update r2956 fb11bd9 remotes/modules-2 r3193 4d23172 remotes/mowgli r3194 c91e99b remotes/tags/mowgli-before-merge r3500 5078d29 remotes/mowgli2 r3672 63b0886 remotes/V7-3-bugfix r5086 bdceb72 remotes/V7-4-bugfix r5731 a274456 remotes/recriture r9046 e19553c remotes/tags/trunk r9146 b38ce05 remotes/coq-diff-tool r9786 a05abf8 remotes/ProofIrrelevance r10294 fdf8871 remotes/InternalExtraction r10408 df97909 remotes/TypeClasses r10673 4e19bca remotes/bertot r11130 bfd1cb3 remotes/proofs r12282 a726b30 remotes/revised-theories r13855 bae3a8e remotes/native r14062 b77191b remotes/recdef r16421 9f4bfa8 remotes/V8-0-bugfix rocq-9.2.0/dev/doc/archive/perf-analysis000066400000000000000000000131231516144147600201430ustar00rootroot00000000000000Performance analysis (trunk repository) --------------------------------------- Jun 7, 2010: delayed re-typing of Ltac instances in matching (-1% on HighSchoolGeometry, -2% on JordanCurveTheorem) Jun 4, 2010: improvement in eauto and type classes inference by removing systematic preparation of debugging pretty-printing streams (std_ppcmds) (-7% in ATBR, visible only on V8.3 logs since ATBR is broken in trunk; -6% in HighSchoolGeometry) Apr 19, 2010: small improvement obtained by reducing evar instantiation from O(n^3) to O(n^2) in the size of the instance (-2% in Compcert, -2% AreaMethod, -15% in Ssreflect) Apr 17, 2010: small improvement obtained by not repeating unification twice in auto (-2% in Compcert, -2% in Algebra) Feb 15, 2010: Global decrease due to unicode inefficiency repaired Jan 8, 2010: Global increase due to an inefficiency in unicode treatment Dec 1, 2009 - Dec 19, 2009: Temporary addition of [forall x, P x] hints to exact (generally not significative but, e.g., +25% on Subst, +8% on ZFC, +5% on AreaMethod) Oct 19, 2009: Change in modules (CoLoR +35%) Aug 9, 2009: new files added in AreaMethod May 21, 2008: New version of CoRN (needs +84% more time to compile) Apr 25-29, 2008: Temporary attempt with delta in eauto (Matthieu) (+28% CoRN) Apr 17, 2008: improvement probably due to commit 10807 or 10813 (bug fixes, control of zeta in rewrite, auto (??)) (-18% Buchberger, -40% PAutomata, -28% IntMap, -43% CoRN, -13% LinAlg, but CatsInZFC -0.5% only, PiCalc stable, PersistentUnionFind -1%) Mar 11, 2008: (+19% PersistentUnionFind wrt Mar 3, +21% Angles, +270% Continuations between 7/3 and 18/4) Mar 7, 2008: (-10% PersistentUnionFind wrt Mar 3) Feb 20, 2008: temporary 1-day slow down (+64% LinAlg) Feb 14, 2008: (-10% PersistentUnionFind, -19% Groups) Feb 7, 8, 2008: temporary 2-days long slow down (+20 LinAlg, +50% BDDs) Feb 2, 2008: many updates of the module system (-13% LinAlg, -50% AMM11262, -5% Goedel, -1% PersistentUnionFind, -42% ExactRealArithmetic, -41% Icharate, -42% Kildall, -74% SquareMatrices) Jan 1, 2008: merge of TypeClasses branch (+8% PersistentUnionFind, +36% LinAlg, +76% Goedel) Nov 16, 17, 2007: (+18% Cantor, +4% LinAlg, +27% IEEE1394 on 2 days) Nov 8, 2007: (+18% Cantor, +16% LinAlg, +55% Continuations, +200% IEEE1394, +170% CTLTCTL, +220% SquareMatrices) Oct 29, V8.1 (+ 3% geometry but CoRN, Godel, Kildall, Stalmark stables) Between Oct 12 and Oct 27, 2007: inefficiency temporarily introduced in the tactic interpreter (from revision 10222 to 10267) (+22% CoRN, +10% geometry, ...) Sep 16, 2007: (+16% PersistentUnionFind on 3 days, LinAlg stable, Sep 4, 2007: (+26% PersistentUnionFind, LinAlg stable, Jun 6, 2007: optimization of the need for type unification in with-bindings (-3.5% Stalmark, -6% Kildall) May 20, 21, 22, 2007: improved inference of with-bindings (including activation of unification on types) (+4% PICALC, +5% Stalmark, +7% Kildall) May 11, 2007: added primitive integers (+6% CoLoR, +7% CoRN, +5% FSets, ...) Between Feb 22 and March 16, 2007: bench temporarily moved on JMN's computer (-25% CoRN, -25% Fairisle, ...) Oct 29 and Oct 30, 2006: abandoned attempt to add polymorphism on definitions (+4% in general during these two days) Oct 17, 2006: improvement in new field [r9248] (QArith -3%, geometry: -2%) Oct 5, 2006: fixing wrong unification of Meta below binders (e.g. CatsInZFC: +10%, CoRN: -2.5%, Godel: +4%, LinAlg: +7%, DISTRIBUTED_REFERENCE_COUNTING: +10%, CoLoR: +1%) Sep 26, 2006: new field [r9178-9181] (QArith: -16%, geometry: -5%, Float: +6%, BDDS:+5% but no ring in it) Sep 12, 2006: Rocq/AREA_METHOD extended (~ 530s) Aug 12, 2006: Rocq/AREA_METHOD added (~ 480s) May 30, 2006: Nancy/CoLoR added (~ 319s) May 23, 2006: new, lighter version of polymorphic inductive types (CoRN: -27%, back to Mar-24 time) May 17, 2006: changes in List.v (DISTRIBUTED_REFERENCE_COUNTING: -) May 5, 2006: improvement in closure (array instead of lists) (e.g. CatsInZFC: -10%, CoRN: -3%, May 23, 2006: polymorphic inductive types (precise, heavy algorithm) (CoRN: +37%) Dec 29, 2005: new test and use of -vm in Stalmarck Dec 27, 2005: contrib Karatsuba added (~ 30s) Dec 28, 2005: size decrease mainly due to Defined moved to Qed in FSets (reduction from 95M to 7Mo) Dec 1-14, 2005: benchmarking server down between the two dates: Godel: -10%, CoRN: -10% probably due to changes around vm (new informative Cast, change of equality in named_context_val) Oct 6, 2005: contribs IPC and Tait added (~ 22s and ~ 25s) Aug 19, 2005: time decrease after application of "Array.length x=0" Xavier's suggestions for optimisation (e.g. Nijmegen/QArith: -3%, Nijmegen/CoRN: -7%, Godel: -3%) Aug 1, 2005: contrib Kildall added (~ 65s) Jul 26-Aug 2, 2005: bench down Jul 14-15, 2005: 4 contribs failed including CoRN Jul 14, 2005: time increase after activation of "closure optimisation" (e.g. Nijmegen/QArith: +8%, Nijmegen/CoRN: +3%, Godel: +13%) Jul 7, 2005: adding contrib Fermat4 Jun 17, 2005: contrib Goodstein extended and moved to CantorOrdinals (~ 30s) May 19, 2005: contrib Goodstein and prfx (~ 9s) added Apr 21, 2005: strange time decrease (could it be due to the change of Back and Reset mechanism) (e.g. Nijmegen/CoRN: -2%, Nijmegen/QARITH: -4%, Godel: -11%) Mar 20, 2005: fixed Logic.with_check bug global time decrease (e.g. Nijmegen/CoRN: -3%, Nijmegen/QARITH: -1.5%) Jan 31-Feb 8, 2005: small instability (e.g. CoRN: ~2015s -> ~1999s -> ~2032s, Godel: ~340s -> ~370s) Jan 13, 2005: contrib SumOfTwoSquare added (~ 38s) rocq-9.2.0/dev/doc/archive/v8-syntax/000077500000000000000000000000001516144147600173245ustar00rootroot00000000000000rocq-9.2.0/dev/doc/archive/v8-syntax/check-grammar000077500000000000000000000022711516144147600217550ustar00rootroot00000000000000#!/bin/sh # This scripts checks that the new grammar of Coq as defined in syntax-v8.tex # is consistent in the sense that all invoked non-terminals are defined defined_nt() { grep "\\DEFNT{.*}" syntax-v8.tex | sed -e "s|.*DEFNT{\([^}]*\)}.*|\1|"|\ sort | sort -u } used_nt() { cat syntax-v8.tex | tr \\\\ \\n | grep "^NT{.*}" |\ sed -e "s|^NT{\([^}]*\)}.*|\1|" | egrep -v ^\#1\|non-terminal | sort -u } used_term() { cat syntax-v8.tex | tr \\\\ \\n | grep "^TERM{.*}" |\ sed -e "s|^TERM{\([^}]*\)}.*|\1|" -e "s|\\$||g" | egrep -v ^\#1\|terminal | sort -u } used_kwd() { cat syntax-v8.tex | tr \\\\ \\n | grep "^KWD{.*}" |\ sed -e "s|^KWD{\([^}]*\)}.*|\1|" -e "s|\\$||g" | egrep -v ^\#1 | sort -u } defined_nt > def used_nt > use used_term > use-t used_kwd > use-k diff def use > df ############################### echo if grep ^\> df > /dev/null 2>&1 ; then echo Undefined non-terminals: echo ======================== echo grep ^\> df | sed -e "s|^> ||" echo fi if grep ^\< df > /dev/null 2>&1 ; then echo Unused non-terminals: echo ===================== echo grep ^\< df | sed -e "s|^< ||" echo fi #echo Used terminals: #echo =============== #echo #cat use-trocq-9.2.0/dev/doc/archive/v8-syntax/memo-v8.tex000066400000000000000000000230511516144147600213370ustar00rootroot00000000000000 \documentclass{article} \usepackage{verbatim} \usepackage{amsmath} \usepackage{amssymb} \usepackage{array} \usepackage{fullpage} \author{B.~Barras} \title{An introduction to syntax of Coq V8} %% Le _ est un caractΓ¨re normal \catcode`\_=13 \let\subscr=_ \def_{\ifmmode\sb\else\subscr\fi} \def\NT#1{\langle\textit{#1}\rangle} \def\NTL#1#2{\langle\textit{#1}\rangle_{#2}} \def\TERM#1{\textsf{\bf #1}} \newenvironment{transbox} {\begin{center}\tt\begin{tabular}{l|ll} \hfil\textrm{V7} & \hfil\textrm{V8} \\ \hline} {\end{tabular}\end{center}} \def\TRANS#1#2 {\begin{tabular}[t]{@{}l@{}}#1\end{tabular} & \begin{tabular}[t]{@{}l@{}}#2\end{tabular} \\} \def\TRANSCOM#1#2#3 {\begin{tabular}[t]{@{}l@{}}#1\end{tabular} & \begin{tabular}[t]{@{}l@{}}#2\end{tabular} & #3 \\} \begin{document} \maketitle The goal of this document is to introduce by example to the new syntax of Coq. It is strongly recommended to read first the definition of the new syntax, but this document should also be useful for the eager user who wants to start with the new syntax quickly. \section{Changes in lexical conventions w.r.t. V7} \subsection{Identifiers} The lexical conventions changed: \TERM{_} is not a regular identifier anymore. It is used in terms as a placeholder for subterms to be inferred at type-checking, and in patterns as a non-binding variable. Furthermore, only letters (unicode letters), digits, single quotes and _ are allowed after the first character. \subsection{Quoted string} Quoted strings are used typically to give a filename (which may not be a regular identifier). As before they are written between double quotes ("). Unlike for V7, there is no escape character: characters are written normally but the double quote which is doubled. \section{Main changes in terms w.r.t. V7} \subsection{Precedence of application} In the new syntax, parentheses are not really part of the syntax of application. The precedence of application (10) is tighter than all prefix and infix notations. It makes it possible to remove parentheses in many contexts. \begin{transbox} \TRANS{(A x)->(f x)=(g y)}{A x -> f x = g y} \TRANS{(f [x]x)}{f (fun x => x)} \end{transbox} \subsection{Arithmetics and scopes} The specialized notation for \TERM{Z} and \TERM{R} (introduced by symbols \TERM{`} and \TERM{``}) have disappeared. They have been replaced by the general notion of scope. \begin{center} \begin{tabular}{l|l|l} type & scope name & delimiter \\ \hline types & type_scope & \TERM{T} \\ \TERM{bool} & bool_scope & \\ \TERM{nat} & nat_scope & \TERM{nat} \\ \TERM{Z} & Z_scope & \TERM{Z} \\ \TERM{R} & R_scope & \TERM{R} \\ \TERM{positive} & positive_scope & \TERM{P} \end{tabular} \end{center} In order to use notations of arithmetics on \TERM{Z}, its scope must be opened with command \verb+Open Scope Z_scope.+ Another possibility is using the scope change notation (\TERM{\%}). The latter notation is to be used when notations of several scopes appear in the same expression. In examples below, scope changes are not needed if the appropriate scope has been opened. Scope nat_scope is opened in the initial state of Coq. \begin{transbox} \TRANSCOM{`0+x=x+0`}{0+x=x+0}{\textrm{Z_scope}} \TRANSCOM{``0 + [if b then ``1`` else ``2``]``}{0 + if b then 1 else 2}{\textrm{R_scope}} \TRANSCOM{(0)}{0}{\textrm{nat_scope}} \end{transbox} Below is a table that tells which notation is available in which scope. The relative precedences and associativity of operators is the same as in usual mathematics. See the reference manual for more details. However, it is important to remember that unlike V7, the type operators for product and sum are left associative, in order not to clash with arithmetic operators. \begin{center} \begin{tabular}{l|l} scope & notations \\ \hline nat_scope & $+ ~- ~* ~< ~\leq ~> ~\geq$ \\ Z_scope & $+ ~- ~* ~/ ~\TERM{mod} ~< ~\leq ~> ~\geq ~?=$ \\ R_scope & $+ ~- ~* ~/ ~< ~\leq ~> ~\geq$ \\ type_scope & $* ~+$ \\ bool_scope & $\TERM{\&\&} ~\TERM{$||$} ~\TERM{-}$ \\ list_scope & $\TERM{::} ~\TERM{++}$ \end{tabular} \end{center} (Note: $\leq$ is written \TERM{$<=$}) \subsection{Notation for implicit arguments} The explicitation of arguments is closer to the \emph{bindings} notation in tactics. Argument positions follow the argument names of the head constant. \begin{transbox} \TRANS{f 1!t1 2!t2}{f (x:=t1) (y:=t2)} \TRANS{!f t1 t2}{@f t1 t2} \end{transbox} \subsection{Universal quantification} The universal quantification and dependent product types are now materialized with the \TERM{forall} keyword before the binders and a comma after the binders. The syntax of binders also changed significantly. A binder can simply be a name when its type can be inferred. In other cases, the name and the type of the variable are put between parentheses. When several consecutive variables have the same type, they can be grouped. Finally, if all variables have the same type parentheses can be omitted. \begin{transbox} \TRANS{(x:A)B}{forall (x:~A), B ~~\textrm{or}~~ forall x:~A, B} \TRANS{(x,y:nat)P}{forall (x y :~nat), P ~~\textrm{or}~~ forall x y :~nat, P} \TRANS{(x,y:nat;z:A)P}{forall (x y :~nat) (z:A), P} \TRANS{(x,y,z,t:?)P}{forall x y z t, P} \TRANS{(x,y:nat;z:?)P}{forall (x y :~nat) z, P} \end{transbox} \subsection{Abstraction} The notation for $\lambda$-abstraction follows that of universal quantification. The binders are surrounded by keyword \TERM{fun} and $\Rightarrow$ (\verb+=>+ in ascii). \begin{transbox} \TRANS{[x,y:nat; z](f a b c)}{fun (x y:nat) z => f a b c} \end{transbox} \subsection{Pattern-matching} Beside the usage of the keyword pair \TERM{match}/\TERM{with} instead of \TERM{Cases}/\TERM{of}, the main change is the notation for the type of branches and return type. It is no longer written between \TERM{$<$ $>$} before the \TERM{Cases} keyword, but interleaved with the destructured objects. The idea is that for each destructured object, one may specify a variable name to tell how the branches types depend on this destructured objects (case of a dependent elimination), and also how they depend on the value of the arguments of the inductive type of the destructured objects. The type of branches is then given after the keyword \TERM{return}, unless it can be inferred. Moreover, when the destructured object is a variable, one may use this variable in the return type. \begin{transbox} \TRANS{Cases n of\\~~ O => O \\| (S k) => (1) end}{match n with\\~~ 0 => 0 \\| (S k) => 1 end} \TRANS{Cases m n of \\~~0 0 => t \\| ... end}{match m, n with \\~~0, 0 => t \\| .. end} \TRANS{<[n:nat](P n)>Cases T of ... end}{match T as n return P n with ... end} \TRANS{<[n:nat][p:(even n)]\~{}(odd n)>Cases p of\\~~ ... \\end}{match p in even n return \~{} odd n with\\~~ ...\\end} \end{transbox} \subsection{Fixpoints and cofixpoints} An easier syntax for non-mutual fixpoints is provided, making it very close to the usual notation for non-recursive functions. The decreasing argument is now indicated by an annotation between curly braces, regardless of the binders grouping. The annotation can be omitted if the binders introduce only one variable. The type of the result can be omitted if inferable. \begin{transbox} \TRANS{Fix plus\{plus [n:nat] : nat -> nat :=\\~~ [m]...\}}{fix plus (n m:nat) \{struct n\}: nat := ...} \TRANS{Fix fact\{fact [n:nat]: nat :=\\ ~~Cases n of\\~~~~ O => (1) \\~~| (S k) => (mult n (fact k)) end\}}{fix fact (n:nat) :=\\ ~~match n with \\~~~~0 => 1 \\~~| (S k) => n * fact k end} \end{transbox} There is a syntactic sugar for mutual fixpoints associated to a local definition: \begin{transbox} \TRANS{let f := Fix f \{f [x:A] : T := M\} in\\(g (f y))}{let fix f (x:A) : T := M in\\g (f x)} \end{transbox} The same applies to cofixpoints, annotations are not allowed in that case. \subsection{Notation for type cast} \begin{transbox} \TRANS{O :: nat}{0 : nat} \end{transbox} \section{Main changes in tactics w.r.t. V7} The main change is that all tactic names are lowercase. This also holds for Ltac keywords. \subsection{Ltac} Definitions of macros are introduced by \TERM{Ltac} instead of \TERM{Tactic Definition}, \TERM{Meta Definition} or \TERM{Recursive Definition}. Rules of a match command are not between square brackets anymore. Context (understand a term with a placeholder) instantiation \TERM{inst} became \TERM{context}. Syntax is unified with subterm matching. \begin{transbox} \TRANS{match t with [C[x=y]] => inst C[y=x]}{match t with context C[x=y] => context C[y=x]} \end{transbox} \subsection{Named arguments of theorems} \begin{transbox} \TRANS{Apply thm with x:=t 1:=u}{apply thm with (x:=t) (1:=u)} \end{transbox} \subsection{Occurrences} To avoid ambiguity between a numeric literal and the optional occurrence numbers of this term, the occurrence numbers are put after the term itself. This applies to tactic \TERM{pattern} and also \TERM{unfold} \begin{transbox} \TRANS{Pattern 1 2 (f x) 3 4 d y z}{pattern (f x at 1 2) (d at 3 4) y z} \end{transbox} \section{Main changes in vernacular commands w.r.t. V7} \subsection{Binders} The binders of vernacular commands changed in the same way as those of fixpoints. This also holds for parameters of inductive definitions. \begin{transbox} \TRANS{Definition x [a:A] : T := M}{Definition x (a:A) : T := M} \TRANS{Inductive and [A,B:Prop]: Prop := \\~~conj : A->B->(and A B)}% {Inductive and (A B:Prop): Prop := \\~~conj : A -> B -> and A B} \end{transbox} \subsection{Hints} The syntax of \emph{extern} hints changed: the pattern and the tactic to be applied are separated by a \TERM{$\Rightarrow$}. \begin{transbox} \TRANS{Hint Extern 4 (toto ?) Apply lemma}{Hint Extern 4 (toto _) => apply lemma} \end{transbox} \end{document} rocq-9.2.0/dev/doc/archive/v8-syntax/syntax-v8.tex000066400000000000000000001162261516144147600217370ustar00rootroot00000000000000 \documentclass{article} \usepackage{verbatim} \usepackage{amsmath} \usepackage{amssymb} \usepackage{array} \usepackage{fullpage} \author{B.~Barras} \title{Syntax of Coq V8} %% Le _ est un caractΓ¨re normal \catcode`\_=13 \let\subscr=_ \def_{\ifmmode\sb\else\subscr\fi} \def\bfbar{\ensuremath{|\hskip -0.22em{}|\hskip -0.24em{}|}} \def\TERMbar{\bfbar} \def\TERMbarbar{\bfbar\bfbar} \def\notv{\text{_}} \def\infx#1{\notv#1\notv} %% Macros pour les grammaires \def\GR#1{\text{\large(}#1\text{\large)}} \def\NT#1{\langle\textit{#1}\rangle} \def\NTL#1#2{\langle\textit{#1}\rangle_{#2}} \def\TERM#1{{\bf\textrm{\bf #1}}} %\def\TERM#1{{\bf\textsf{#1}}} \def\KWD#1{\TERM{#1}} \def\ETERM#1{\TERM{#1}} \def\CHAR#1{\TERM{#1}} \def\STAR#1{#1*} \def\STARGR#1{\GR{#1}*} \def\PLUS#1{#1+} \def\PLUSGR#1{\GR{#1}+} \def\OPT#1{#1?} \def\OPTGR#1{\GR{#1}?} %% Tableaux de definition de non-terminaux \newenvironment{cadre} {\begin{array}{|c|}\hline\\} {\\\\\hline\end{array}} \newenvironment{rulebox} {$$\begin{cadre}\begin{array}{r@{~}c@{~}l@{}l@{}r}} {\end{array}\end{cadre}$$} \def\DEFNT#1{\NT{#1} & ::= &} \def\EXTNT#1{\NT{#1} & ::= & ... \\&|&} \def\RNAME#1{(\textsc{#1})} \def\SEPDEF{\\\\} \def\nlsep{\\&|&} \def\nlcont{\\&&} \newenvironment{rules} {\begin{center}\begin{rulebox}} {\end{rulebox}\end{center}} \begin{document} \maketitle \section{Meta notations used in this document} Non-terminals are printed between angle brackets (e.g. $\NT{non-terminal}$) and terminal symbols are printed in bold font (e.g. $\ETERM{terminal}$). Lexemes are displayed as non-terminals. The usual operators on regular expressions: \begin{center} \begin{tabular}{l|l} \hfil notation & \hfil meaning \\ \hline $\STAR{regexp}$ & repeat $regexp$ 0 or more times \\ $\PLUS{regexp}$ & repeat $regexp$ 1 or more times \\ $\OPT{regexp}$ & $regexp$ is optional \\ $regexp_1~\mid~regexp_2$ & alternative \end{tabular} \end{center} Parenthesis are used to group regexps. Beware to distinguish this operator $\GR{~}$ from the terminals $\ETERM{( )}$, and $\mid$ from terminal \TERMbar. Rules are optionally annotated in the right margin with: \begin{itemize} \item a precedence and associativity (L for left, R for right and N for no associativity), indicating how to solve conflicts; lower levels are tighter; \item a rule name. \end{itemize} In order to solve some conflicts, a non-terminal may be invoked with a precedence (notation: $\NTL{entry}{prec}$), meaning that rules with higher precedence do not apply. \section{Lexical conventions} Lexical categories are: \begin{rules} \DEFNT{ident} \STARGR{\NT{letter}\mid\CHAR{_}} \STARGR{\NT{letter}\mid \NT{digit} \mid \CHAR{'} \mid \CHAR{_}} \SEPDEF \DEFNT{field} \CHAR{.}\NT{ident} \SEPDEF \DEFNT{meta-ident} \CHAR{?}\NT{ident} \SEPDEF \DEFNT{num} \PLUS{\NT{digit}} \SEPDEF \DEFNT{int} \NT{num} \mid \CHAR{-}\NT{num} \SEPDEF \DEFNT{digit} \CHAR{0}-\CHAR{9} \SEPDEF \DEFNT{letter} \CHAR{a}-\CHAR{z}\mid\CHAR{A}-\CHAR{Z} \mid\NT{unicode-letter} \SEPDEF \DEFNT{string} \CHAR{"}~\STARGR{\CHAR{""}\mid\NT{unicode-char-but-"}}~\CHAR{"} \end{rules} Reserved identifiers for the core syntax are: \begin{quote} \KWD{as}, \KWD{cofix}, \KWD{else}, \KWD{end}, \KWD{fix}, \KWD{for}, \KWD{forall}, \KWD{fun}, \KWD{if}, \KWD{in}, \KWD{let}, \KWD{match}, \KWD{Prop}, \KWD{return}, \KWD{Set}, \KWD{then}, \KWD{Type}, \KWD{with} \end{quote} Symbols used in the core syntax: $$ \KWD{(} ~~ \KWD{)} ~~ \KWD{\{} ~~ \KWD{\}} ~~ \KWD{:} ~~ \KWD{,} ~~ \Rightarrow ~~ \rightarrow ~~ \KWD{:=} ~~ \KWD{_} ~~ \TERMbar ~~ \KWD{@} ~~ \KWD{\%} ~~ \KWD{.(} $$ Note that \TERM{struct} is not a reserved identifier. \section{Syntax of terms} \subsection{Core syntax} The main entry point of the term grammar is $\NTL{constr}{9}$. When no conflict can appear, $\NTL{constr}{200}$ is also used as entry point. \begin{rules} \DEFNT{constr} \NT{binder-constr} &200R~~ &\RNAME{binders} \nlsep \NT{constr}~\KWD{:}~\NT{constr} &100R &\RNAME{cast} \nlsep \NT{constr}~\KWD{:}~\NT{binder-constr} &100R &\RNAME{cast'} \nlsep \NT{constr}~\KWD{$\rightarrow$}~\NT{constr} &80R &\RNAME{arrow} \nlsep \NT{constr}~\KWD{$\rightarrow$}~\NT{binder-constr} &80R &\RNAME{arrow'} \nlsep \NT{constr}~\PLUS{\NT{appl-arg}} &10L &\RNAME{apply} \nlsep \KWD{@}~\NT{reference}~\STAR{\NTL{constr}{9}} &10L &\RNAME{expl-apply} \nlsep \NT{constr}~\KWD{.(} ~\NT{reference}~\STAR{\NT{appl-arg}}~\TERM{)} &1L & \RNAME{proj} \nlsep \NT{constr}~\KWD{.(}~\TERM{@} ~\NT{reference}~\STAR{\NTL{constr}{9}}~\TERM{)} &1L & \RNAME{expl-proj} \nlsep \NT{constr} ~ \KWD{\%} ~ \NT{ident} &1L &\RNAME{scope-chg} \nlsep \NT{atomic-constr} &0 \nlsep \NT{match-expr} &0 \nlsep \KWD{(}~\NT{constr}~\KWD{)} &0 \SEPDEF \DEFNT{binder-constr} \KWD{forall}~\NT{binder-list}~\KWD{,}~\NTL{constr}{200} &&\RNAME{prod} \nlsep \KWD{fun} ~\NT{binder-list} ~\KWD{$\Rightarrow$}~\NTL{constr}{200} &&\RNAME{lambda} \nlsep \NT{fix-expr} \nlsep \KWD{let}~\NT{ident-with-params} ~\KWD{:=}~\NTL{constr}{200} ~\KWD{in}~\NTL{constr}{200} &&\RNAME{let} \nlsep \KWD{let}~\NT{single-fix} ~\KWD{in}~\NTL{constr}{200} &&\RNAME{rec-let} \nlsep \KWD{let}~\KWD{(}~\OPT{\NT{let-pattern}}~\KWD{)}~\OPT{\NT{return-type}} ~\KWD{:=}~\NTL{constr}{200}~\KWD{in}~\NTL{constr}{200} &&\RNAME{let-case} \nlsep \KWD{if}~\NT{if-item} ~\KWD{then}~\NTL{constr}{200}~\KWD{else}~\NTL{constr}{200} &&\RNAME{if-case} \SEPDEF \DEFNT{appl-arg} \KWD{(}~\NT{ident}~\!\KWD{:=}~\NTL{constr}{200}~\KWD{)} &&\RNAME{impl-arg} \nlsep \KWD{(}~\NT{num}~\!\KWD{:=}~\NTL{constr}{200}~\KWD{)} &&\RNAME{impl-arg} \nlsep \NTL{constr}{9} \SEPDEF \DEFNT{atomic-constr} \NT{reference} && \RNAME{variables} \nlsep \NT{sort} && \RNAME{CIC-sort} \nlsep \NT{num} && \RNAME{number} \nlsep \KWD{_} && \RNAME{hole} \nlsep \NT{meta-ident} && \RNAME{meta/evar} \end{rules} \begin{rules} \DEFNT{ident-with-params} \NT{ident}~\STAR{\NT{binder-let}}~\NT{type-cstr} \SEPDEF \DEFNT{binder-list} \NT{binder}~\STAR{\NT{binder-let}} \nlsep \PLUS{\NT{name}}~\KWD{:}~\NT{constr} \SEPDEF \DEFNT{binder} \NT{name} &&\RNAME{infer} \nlsep \KWD{(}~\PLUS{\NT{name}}~\KWD{:}~\NT{constr} ~\KWD{)} &&\RNAME{binder} \SEPDEF \DEFNT{binder-let} \NT{binder} \nlsep \KWD{(}~\NT{name}~\NT{type-cstr}~\KWD{:=}~\NT{constr}~\KWD{)} \SEPDEF \DEFNT{let-pattern} \NT{name} \nlsep \NT{name} ~\KWD{,} ~\NT{let-pattern} \SEPDEF \DEFNT{type-cstr} \OPTGR{\KWD{:}~\NT{constr}} \SEPDEF \DEFNT{reference} \NT{ident} && \RNAME{short-ident} \nlsep \NT{ident}~\PLUS{\NT{field}} && \RNAME{qualid} \SEPDEF \DEFNT{sort} \KWD{Prop} ~\mid~ \KWD{Set} ~\mid~ \KWD{Type} \SEPDEF \DEFNT{name} \NT{ident} ~\mid~ \KWD{_} \end{rules} \begin{rules} \DEFNT{fix-expr} \NT{single-fix} \nlsep \NT{single-fix}~\PLUSGR{\KWD{with}~\NT{fix-decl}} ~\KWD{for}~\NT{ident} \SEPDEF \DEFNT{single-fix} \NT{fix-kw}~\NT{fix-decl} \SEPDEF \DEFNT{fix-kw} \KWD{fix} ~\mid~ \KWD{cofix} \SEPDEF \DEFNT{fix-decl} \NT{ident}~\STAR{\NT{binder-let}}~\OPT{\NT{annot}}~\NT{type-cstr} ~\KWD{:=}~\NTL{constr}{200} \SEPDEF \DEFNT{annot} \KWD{\{}~\TERM{struct}~\NT{ident}~\KWD{\}} \end{rules} \begin{rules} \DEFNT{match-expr} \KWD{match}~\NT{match-items}~\OPT{\NT{return-type}}~\KWD{with} ~\OPT{\TERMbar}~\OPT{\NT{branches}}~\KWD{end} &&\RNAME{match} \SEPDEF \DEFNT{match-items} \NT{match-item} ~\KWD{,} ~\NT{match-items} \nlsep \NT{match-item} \SEPDEF \DEFNT{match-item} \NTL{constr}{100}~\OPTGR{\KWD{as}~\NT{name}} ~\OPTGR{\KWD{in}~\NTL{constr}{100}} \SEPDEF \DEFNT{return-type} \KWD{return}~\NTL{constr}{100} \SEPDEF \DEFNT{if-item} \NT{constr}~\OPTGR{\OPTGR{\KWD{as}~\NT{name}}~\NT{return-type}} \SEPDEF \DEFNT{branches} \NT{eqn}~\TERMbar~\NT{branches} \nlsep \NT{eqn} \SEPDEF \DEFNT{eqn} \NT{pattern} ~\STARGR{\KWD{,}~\NT{pattern}} ~\KWD{$\Rightarrow$}~\NT{constr} \SEPDEF \DEFNT{pattern} \NT{reference}~\PLUS{\NT{pattern}} &1L~~ & \RNAME{constructor} \nlsep \NT{pattern}~\KWD{as}~\NT{ident} &1L & \RNAME{alias} \nlsep \NT{pattern}~\KWD{\%}~\NT{ident} &1L & \RNAME{scope-change} \nlsep \NT{reference} &0 & \RNAME{pattern-var} \nlsep \KWD{_} &0 & \RNAME{hole} \nlsep \NT{num} &0 \nlsep \KWD{(}~\NT{tuple-pattern}~\KWD{)} \SEPDEF \DEFNT{tuple-pattern} \NT{pattern} \nlsep \NT{tuple-pattern}~\KWD{,}~\NT{pattern} && \RNAME{pair} \end{rules} \subsection{Notations of the prelude (logic and basic arithmetic)} Reserved notations: $$ \begin{array}{l|c} \text{Symbol} & \text{precedence} \\ \hline \infx{,} & 250L \\ \KWD{IF}~\notv~\KWD{then}~\notv~\KWD{else}~\notv & 200R \\ \infx{:} & 100R \\ \infx{\leftrightarrow} & 95N \\ \infx{\rightarrow} & 90R \\ \infx{\vee} & 85R \\ \infx{\wedge} & 80R \\ \tilde{}\notv & 75R \\ \begin{array}[c]{@{}l@{}} \infx{=}\quad \infx{=}\KWD{$:>$}\notv \quad \infx{=}=\notv \quad \infx{\neq} \quad \infx{\neq}\KWD{$:>$}\notv \\ \infx{<}\quad\infx{>} \quad \infx{\leq}\quad\infx{\geq} \quad \infx{<}<\notv \quad \infx{<}\leq\notv \quad \infx{\leq}<\notv \quad \infx{\leq}\leq\notv \end{array} & 70N \\ \infx{+}\quad\infx{-}\quad -\notv & 50L \\ \infx{*}\quad\infx{/}\quad /\notv & 40L \\ \end{array} $$ Existential quantifiers follows the \KWD{forall} notation (with same precedence 200), but only one quantified variable is allowed. \begin{rules} \EXTNT{binder-constr} \NT{quantifier-kwd}~\NT{name}~\NT{type-cstr}~\KWD{,}~\NTL{constr}{200} \\ \SEPDEF \DEFNT{quantifier-kwd} \TERM{exists} && \RNAME{ex} \nlsep \TERM{exists2} && \RNAME{ex2} \end{rules} $$ \begin{array}{l|c|l} \text{Symbol} & \text{precedence} \\ \hline \notv+\{\notv\} & 50 & \RNAME{sumor} \\ \{\notv:\notv~|~\notv\} & 0 & \RNAME{sig} \\ \{\notv:\notv~|~\notv \& \notv \} & 0 & \RNAME{sig2} \\ \{\notv:\notv~\&~\notv \} & 0 & \RNAME{sigS} \\ \{\notv:\notv~\&~\notv \& \notv \} & 0 & \RNAME{sigS2} \\ \{\notv\}+\{\notv\} & 0 & \RNAME{sumbool} \\ \end{array} $$ %% Strange: nat + {x:nat|x=x} * nat == ( + ) * \section{Grammar of tactics} \def\tacconstr{\NTL{constr}{9}} \def\taclconstr{\NTL{constr}{200}} Additional symbols are: $$ \TERM{'} ~~ \KWD{;} ~~ \TERM{()} ~~ \TERMbarbar ~~ \TERM{$\vdash$} ~~ \TERM{[} ~~ \TERM{]} ~~ \TERM{$\leftarrow$} $$ Additional reserved keywords are: $$ \KWD{at} ~~ \TERM{using} $$ \subsection{Basic tactics} \begin{rules} \DEFNT{simple-tactic} \TERM{intros}~\TERM{until}~\NT{quantified-hyp} \nlsep \TERM{intros}~\NT{intro-patterns} \nlsep \TERM{intro}~\OPT{\NT{ident}}~\OPTGR{\TERM{after}~\NT{ident}} %% \nlsep \TERM{assumption} \nlsep \TERM{exact}~\tacconstr %% \nlsep \TERM{apply}~\NT{constr-with-bindings} \nlsep \TERM{elim}~\NT{constr-with-bindings}~\OPT{\NT{eliminator}} \nlsep \TERM{elimtype}~\tacconstr \nlsep \TERM{case}~\NT{constr-with-bindings} \nlsep \TERM{casetype}~\tacconstr \nlsep \KWD{fix}~\OPT{\NT{ident}}~\NT{num} \nlsep \KWD{fix}~\NT{ident}~\NT{num}~\KWD{with}~\PLUS{\NT{fix-spec}} \nlsep \KWD{cofix}~\OPT{\NT{ident}} \nlsep \KWD{cofix}~\NT{ident}~\PLUS{\NT{fix-spec}} %% \nlsep \TERM{cut}~\tacconstr \nlsep \TERM{assert}~\tacconstr \nlsep \TERM{assert}~ \TERM{(}~\NT{ident}~\KWD{:}~\taclconstr~\TERM{)} \nlsep \TERM{assert}~ \TERM{(}~\NT{ident}~\KWD{:=}~\taclconstr~\TERM{)} \nlsep \TERM{pose}~\tacconstr \nlsep \TERM{pose}~ \TERM{(}~\NT{ident}~\KWD{:=}~\taclconstr~\TERM{)} \nlsep \TERM{generalize}~\PLUS{\tacconstr} \nlsep \TERM{generalize}~\TERM{dependent}~\tacconstr \nlsep \TERM{set}~\tacconstr~\OPT{\NT{clause}} \nlsep \TERM{set}~ \TERM{(}~\NT{ident}~\KWD{:=}~\taclconstr~\TERM{)}~\OPT{\NT{clause}} \nlsep \TERM{instantiate}~ \TERM{(}~\NT{num}~\TERM{:=}~\taclconstr~\TERM{)}~\OPT{\NT{clause}} %% \nlsep \TERM{specialize}~\OPT{\NT{num}}~\NT{constr-with-bindings} \nlsep \TERM{lapply}~\tacconstr %% \nlsep \TERM{simple}~\TERM{induction}~\NT{quantified-hyp} \nlsep \TERM{induction}~\NT{induction-arg}~\OPT{\NT{with-names}} ~\OPT{\NT{eliminator}} \nlsep \TERM{double}~\TERM{induction}~\NT{quantified-hyp}~\NT{quantified-hyp} \nlsep \TERM{simple}~\TERM{destruct}~\NT{quantified-hyp} \nlsep \TERM{destruct}~\NT{induction-arg}~\OPT{\NT{with-names}} ~\OPT{\NT{eliminator}} \nlsep \TERM{decompose}~\TERM{record}~\tacconstr \nlsep \TERM{decompose}~\TERM{sum}~\tacconstr \nlsep \TERM{decompose}~\TERM{[}~\PLUS{\NT{reference}}~\TERM{]} ~\tacconstr %% \nlsep ... \end{rules} \begin{rules} \EXTNT{simple-tactic} \TERM{trivial}~\OPT{\NT{hint-bases}} \nlsep \TERM{auto}~\OPT{\NT{num}}~\OPT{\NT{hint-bases}} %% %%\nlsep \TERM{autotdb}~\OPT{\NT{num}} %%\nlsep \TERM{cdhyp}~\NT{ident} %%\nlsep \TERM{dhyp}~\NT{ident} %%\nlsep \TERM{dconcl} %%\nlsep \TERM{superauto}~\NT{auto-args} \nlsep \TERM{auto}~\OPT{\NT{num}}~\TERM{decomp}~\OPT{\NT{num}} %% \nlsep \TERM{clear}~\PLUS{\NT{ident}} \nlsep \TERM{clearbody}~\PLUS{\NT{ident}} \nlsep \TERM{move}~\NT{ident}~\TERM{after}~\NT{ident} \nlsep \TERM{rename}~\NT{ident}~\TERM{into}~\NT{ident} %% \nlsep \TERM{left}~\OPT{\NT{with-binding-list}} \nlsep \TERM{right}~\OPT{\NT{with-binding-list}} \nlsep \TERM{split}~\OPT{\NT{with-binding-list}} \nlsep \TERM{exists}~\OPT{\NT{binding-list}} \nlsep \TERM{constructor}~\NT{num}~\OPT{\NT{with-binding-list}} \nlsep \TERM{constructor}~\OPT{\NT{tactic}} %% \nlsep \TERM{reflexivity} \nlsep \TERM{symmetry}~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{transitivity}~\tacconstr %% \nlsep \NT{inversion-kwd}~\NT{quantified-hyp}~\OPT{\NT{with-names}}~\OPT{\NT{clause}} \nlsep \TERM{dependent}~\NT{inversion-kwd}~\NT{quantified-hyp} ~\OPT{\NT{with-names}}~\OPTGR{\KWD{with}~\tacconstr} \nlsep \TERM{inversion}~\NT{quantified-hyp}~\TERM{using}~\tacconstr~\OPT{\NT{clause}} %% \nlsep \NT{red-expr}~\OPT{\NT{clause}} \nlsep \TERM{change}~\NT{conversion}~\OPT{\NT{clause}} \SEPDEF \DEFNT{red-expr} \TERM{red} ~\mid~ \TERM{hnf} ~\mid~ \TERM{compute} \nlsep \TERM{simpl}~\OPT{\NT{pattern-occ}} \nlsep \TERM{cbv}~\PLUS{\NT{red-flag}} \nlsep \TERM{lazy}~\PLUS{\NT{red-flag}} \nlsep \TERM{unfold}~\NT{unfold-occ}~\STARGR{\KWD{,}~\NT{unfold-occ}} \nlsep \TERM{fold}~\PLUS{\tacconstr} \nlsep \TERM{pattern}~\NT{pattern-occ}~\STARGR{\KWD{,}~\NT{pattern-occ}} \SEPDEF \DEFNT{conversion} \NT{pattern-occ}~\KWD{with}~\tacconstr \nlsep \tacconstr \SEPDEF \DEFNT{inversion-kwd} \TERM{inversion} ~\mid~ \TERM{invesion_clear} ~\mid~ \TERM{simple}~\TERM{inversion} \end{rules} Conflicts exists between integers and constrs. \begin{rules} \DEFNT{quantified-hyp} \NT{int}~\mid~\NT{ident} \SEPDEF \DEFNT{induction-arg} \NT{int}~\mid~\tacconstr \SEPDEF \DEFNT{fix-spec} \KWD{(}~\NT{ident}~\STAR{\NT{binder}}~\OPT{\NT{annot}} ~\KWD{:}~\taclconstr~\KWD{)} \SEPDEF \DEFNT{intro-patterns} \STAR{\NT{intro-pattern}} \SEPDEF \DEFNT{intro-pattern} \NT{name} \nlsep \TERM{[}~\NT{intro-patterns}~\STARGR{\TERMbar~\NT{intro-patterns}} ~\TERM{]} \nlsep \KWD{(}~\NT{intro-pattern}~\STARGR{\KWD{,}~\NT{intro-pattern}} ~\KWD{)} \SEPDEF \DEFNT{with-names} % \KWD{as}~\TERM{[}~\STAR{\NT{ident}}~\STARGR{\TERMbar~\STAR{\NT{ident}}} % ~\TERM{]} \KWD{as}~\NT{intro-pattern} \SEPDEF \DEFNT{eliminator} \TERM{using}~\NT{constr-with-bindings} \SEPDEF \DEFNT{constr-with-bindings} % dangling ``with'' of ``fix'' can conflict with ``with'' \tacconstr~\OPT{\NT{with-binding-list}} \SEPDEF \DEFNT{with-binding-list} \KWD{with}~\NT{binding-list} \SEPDEF \DEFNT{binding-list} \PLUS{\tacconstr} \nlsep \PLUS{\NT{simple-binding}} \SEPDEF \DEFNT{simple-binding} \KWD{(}~\NT{quantified-hyp}~\KWD{:=}~\taclconstr~\KWD{)} \SEPDEF \DEFNT{red-flag} \TERM{beta} ~\mid~ \TERM{iota} ~\mid~ \TERM{zeta} ~\mid~ \TERM{delta} ~\mid~ \TERM{delta}~\OPT{\TERM{-}}~\TERM{[}~\PLUS{\NT{reference}}~\TERM{]} \SEPDEF \DEFNT{clause} \KWD{in}~\TERM{*} \nlsep \KWD{in}~\TERM{*}~\KWD{$\vdash$}~\OPT{\NT{concl-occ}} \nlsep \KWD{in}~\OPT{\NT{hyp-ident-list}} ~\KWD{$\vdash$} ~\OPT{\NT{concl-occ}} \nlsep \KWD{in}~\OPT{\NT{hyp-ident-list}} \SEPDEF \DEFNT{hyp-ident-list} \NT{hyp-ident} \nlsep \NT{hyp-ident}~\KWD{,}~\NT{hyp-ident-list} \SEPDEF \DEFNT{hyp-ident} \NT{ident} \nlsep \KWD{(}~\TERM{type}~\TERM{of}~\NT{ident}~\KWD{)} \nlsep \KWD{(}~\TERM{value}~\TERM{of}~\NT{ident}~\KWD{)} \SEPDEF \DEFNT{concl-occ} \TERM{*} ~\NT{occurrences} \SEPDEF \DEFNT{pattern-occ} \tacconstr ~\NT{occurrences} \SEPDEF \DEFNT{unfold-occ} \NT{reference}~\NT{occurrences} \SEPDEF \DEFNT{occurrences} ~\OPTGR{\KWD{at}~\PLUS{\NT{int}}} \SEPDEF \DEFNT{hint-bases} \KWD{with}~\TERM{*} \nlsep \KWD{with}~\PLUS{\NT{ident}} \SEPDEF \DEFNT{auto-args} \OPT{\NT{num}}~\OPTGR{\TERM{adding}~\TERM{[}~\PLUS{\NT{reference}} ~\TERM{]}}~\OPT{\TERM{destructuring}}~\OPTGR{\TERM{using}~\TERM{tdb}} \end{rules} \subsection{Ltac} %% Currently, there are conflicts with keyword \KWD{in}: in the following, %% has the keyword to be associated to \KWD{let} or to tactic \TERM{simpl} ? %% \begin{center} %% \texttt{let x := simpl in ...} %% \end{center} \begin{rules} \DEFNT{tactic} \NT{tactic} ~\KWD{;} ~\NT{tactic} &5 &\RNAME{Then} \nlsep \NT{tactic} ~\KWD{;}~\TERM{[} ~\OPT{\NT{tactic-seq}} ~\TERM{]} &5 &\RNAME{Then-seq} %% \nlsep \TERM{try} ~\NT{tactic} &3R &\RNAME{Try} \nlsep \TERM{do} ~\NT{int-or-var} ~\NT{tactic} \nlsep \TERM{repeat} ~\NT{tactic} \nlsep \TERM{progress} ~\NT{tactic} \nlsep \TERM{info} ~\NT{tactic} \nlsep \TERM{abstract}~\NTL{tactic}{2}~\OPTGR{\TERM{using}~\NT{ident}} %% \nlsep \NT{tactic} ~\TERMbarbar ~\NT{tactic} &2R &\RNAME{Orelse} %% \nlsep \KWD{fun} ~\PLUS{\NT{name}} ~\KWD{$\Rightarrow$} ~\NT{tactic} &1 &\RNAME{Fun-tac} \nlsep \KWD{let} ~\NT{let-clauses} ~\KWD{in} ~\NT{tactic} \nlsep \KWD{let} ~\TERM{rec} ~\NT{rec-clauses} ~\KWD{in} ~\NT{tactic} \nlsep \KWD{match}~\OPT{\TERM{reverse}}~\TERM{goal}~\KWD{with} ~\OPT{\TERMbar}~\OPT{\NT{match-goal-rules}} ~\KWD{end} \nlsep \KWD{match} ~\NT{tactic} ~\KWD{with} ~\OPT{\TERMbar}~\OPT{\NT{match-rules}} ~\KWD{end} \nlsep \TERM{first}~\TERM{[} ~\NT{tactic-seq} ~\TERM{]} \nlsep \TERM{solve}~\TERM{[} ~\NT{tactic-seq} ~\TERM{]} \nlsep \TERM{idtac} \nlsep \TERM{fail} ~\OPT{\NT{num}} ~\OPT{\NT{string}} \nlsep \TERM{constr}~\KWD{:}~\tacconstr \nlsep \TERM{ipattern}~\KWD{:}~\NT{intro-pattern} \nlsep \NT{term-ltac} \nlsep \NT{reference}~\STAR{\NT{tactic-arg}} &&\RNAME{call-tactic} \nlsep \NT{simple-tactic} %% \nlsep \NT{tactic-atom} &0 &\RNAME{atomic} \nlsep \KWD{(} ~\NT{tactic} ~\KWD{)} \SEPDEF \DEFNT{tactic-arg} \TERM{ltac}~\KWD{:}~\NTL{tactic}{0} \nlsep \TERM{ipattern}~\KWD{:}~\NT{intro-pattern} \nlsep \NT{term-ltac} \nlsep \NT{tactic-atom} \nlsep \tacconstr \SEPDEF \DEFNT{term-ltac} \TERM{fresh} ~\OPT{\NT{string}} \nlsep \TERM{context} ~\NT{ident} ~\TERM{[} ~\taclconstr ~\TERM{]} \nlsep \TERM{eval} ~\NT{red-expr} ~\KWD{in} ~\tacconstr \nlsep \TERM{type} ~\tacconstr \SEPDEF \DEFNT{tactic-atom} \NT{reference} \nlsep \TERM{()} \SEPDEF \DEFNT{tactic-seq} \NT{tactic} ~\TERMbar ~\NT{tactic-seq} \nlsep \NT{tactic} \end{rules} \begin{rules} \DEFNT{let-clauses} \NT{let-clause} ~\STARGR{\KWD{with}~\NT{let-clause}} \SEPDEF \DEFNT{let-clause} \NT{ident} ~\STAR{\NT{name}} ~\KWD{:=} ~\NT{tactic} \SEPDEF \DEFNT{rec-clauses} \NT{rec-clause} ~\KWD{with} ~\NT{rec-clauses} \nlsep \NT{rec-clause} \SEPDEF \DEFNT{rec-clause} \NT{ident} ~\PLUS{\NT{name}} ~\KWD{:=} ~\NT{tactic} \SEPDEF \DEFNT{match-goal-rules} \NT{match-goal-rule} \nlsep \NT{match-goal-rule} ~\TERMbar ~\NT{match-goal-rules} \SEPDEF \DEFNT{match-goal-rule} \NT{match-hyps-list} ~\TERM{$\vdash$} ~\NT{match-pattern} ~\KWD{$\Rightarrow$} ~\NT{tactic} \nlsep \KWD{[}~\NT{match-hyps-list} ~\TERM{$\vdash$} ~\NT{match-pattern} ~\KWD{]}~\KWD{$\Rightarrow$} ~\NT{tactic} \nlsep \KWD{_} ~\KWD{$\Rightarrow$} ~\NT{tactic} \SEPDEF \DEFNT{match-hyps-list} \NT{match-hyps} ~\KWD{,} ~\NT{match-hyps-list} \nlsep \NT{match-hyps} \SEPDEF \DEFNT{match-hyps} \NT{name} ~\KWD{:} ~\NT{match-pattern} \SEPDEF \DEFNT{match-rules} \NT{match-rule} \nlsep \NT{match-rule} ~\TERMbar ~\NT{match-rules} \SEPDEF \DEFNT{match-rule} \NT{match-pattern} ~\KWD{$\Rightarrow$} ~\NT{tactic} \nlsep \KWD{_} ~\KWD{$\Rightarrow$} ~\NT{tactic} \SEPDEF \DEFNT{match-pattern} \TERM{context}~\OPT{\NT{ident}} ~\TERM{[} ~\NT{constr-pattern} ~\TERM{]} &&\RNAME{subterm} \nlsep \NT{constr-pattern} \SEPDEF \DEFNT{constr-pattern} \tacconstr \end{rules} \subsection{Other tactics} \begin{rules} \EXTNT{simple-tactic} \TERM{rewrite} ~\NT{orient} ~\NT{constr-with-bindings} ~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{replace} ~\tacconstr ~\KWD{with} ~\tacconstr ~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{replace} ~\OPT{\NT{orient}} ~\tacconstr ~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{symplify_eq} ~\OPT{\NT{quantified-hyp}} \nlsep \TERM{discriminate} ~\OPT{\NT{quantified-hyp}} \nlsep \TERM{injection} ~\OPT{\NT{quantified-hyp}} \nlsep \TERM{conditional}~\NT{tactic}~\TERM{rewrite}~\NT{orient} ~\NT{constr-with-bindings}~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{dependent}~\TERM{rewrite}~\NT{orient}~\NT{ident} \nlsep \TERM{cutrewrite}~\NT{orient}~\tacconstr ~\OPTGR{\KWD{in}~\NT{ident}} \nlsep \TERM{absurd} ~\tacconstr \nlsep \TERM{contradiction} \nlsep \TERM{autorewrite}~\NT{hint-bases}~\OPTGR{\KWD{using}~\NT{tactic}} \nlsep \TERM{refine}~\tacconstr \nlsep \TERM{setoid_replace} ~\tacconstr ~\KWD{with} ~\tacconstr \nlsep \TERM{setoid_rewrite} ~\NT{orient} ~\tacconstr \nlsep \TERM{subst} ~\STAR{\NT{ident}} %% eqdecide.mlg \nlsep \TERM{decide}~\TERM{equality} ~\OPTGR{\tacconstr~\tacconstr} \nlsep \TERM{compare}~\tacconstr~\tacconstr %% eauto \nlsep \TERM{eexact}~\tacconstr \nlsep \TERM{eapply}~\NT{constr-with-bindings} \nlsep \TERM{prolog}~\TERM{[}~\STAR{\tacconstr}~\TERM{]} ~\NT{quantified-hyp} \nlsep \TERM{eauto}~\OPT{\NT{quantified-hyp}}~\OPT{\NT{quantified-hyp}} ~\NT{hint-bases} \nlsep \TERM{eautod}~\OPT{\NT{quantified-hyp}}~\OPT{\NT{quantified-hyp}} ~\NT{hint-bases} %% tauto \nlsep \TERM{tauto} \nlsep \TERM{simplif} \nlsep \TERM{intuition}~\OPT{\NTL{tactic}{0}} \nlsep \TERM{linearintuition}~\OPT{\NT{num}} %% plugins/cc \nlsep \TERM{cc} %% plugins/field \nlsep \TERM{field}~\STAR{\tacconstr} %% plugins/firstorder \nlsep \TERM{ground}~\OPT{\NTL{tactic}{0}} \nlsep \TERM{ground}~\OPT{\NTL{tactic}{0}}~\KWD{with}~\PLUS{\NT{reference}} \nlsep \TERM{ground}~\OPT{\NTL{tactic}{0}}~\KWD{using}~\PLUS{\NT{ident}} %%\nlsep \TERM{gtauto} \nlsep \TERM{gintuition}~\OPT{\NTL{tactic}{0}} %% plugins/fourier \nlsep \TERM{fourierZ} %% plugins/funind \nlsep \TERM{functional}~\TERM{induction}~\tacconstr~\PLUS{\tacconstr} %% plugins/jprover \nlsep \TERM{jp}~\OPT{\NT{num}} %% plugins/omega \nlsep \TERM{omega} %% plugins/ring \nlsep \TERM{quote}~\NT{ident}~\OPTGR{\KWD{[}~\PLUS{\NT{ident}}~\KWD{]}} \nlsep \TERM{ring}~\STAR{\tacconstr} \SEPDEF \DEFNT{orient} \KWD{$\rightarrow$}~\mid~\KWD{$\leftarrow$} \end{rules} \section{Grammar of commands} New symbols: $$ \TERM{.} ~~ \TERM{..} ~~ \TERM{\tt >->} ~~ \TERM{:$>$} ~~ \TERM{$<$:} $$ New keyword: $$ \KWD{where} $$ \subsection{Classification of commands} \begin{rules} \DEFNT{vernac} \TERM{Time}~\NT{vernac} &2~~ &\RNAME{Timing} %% \nlsep \NT{gallina}~\TERM{.} &1 \nlsep \NT{command}~\TERM{.} \nlsep \NT{syntax}~\TERM{.} \nlsep \TERM{[}~\PLUS{\NT{vernac}}~\TERM{]}~\TERM{.} %% \nlsep \OPTGR{\NT{num}~\KWD{:}}~\NT{subgoal-command}~\TERM{.} ~~~&0 \SEPDEF \DEFNT{subgoal-command} \NT{check-command} \nlsep %\OPT{\TERM{By}}~ \NT{tactic}~\OPT{\KWD{..}} \end{rules} \subsection{Gallina and extensions} \begin{rules} \DEFNT{gallina} \NT{thm-token}~\NT{ident}~\STAR{\NT{binder-let}}~\KWD{:}~\NT{constr} \nlsep \NT{def-token}~\NT{ident}~\NT{def-body} \nlsep \NT{assum-token}~\NT{assum-list} \nlsep \NT{finite-token}~\NT{inductive-definition} ~\STARGR{\KWD{with}~\NT{inductive-definition}} \nlsep \TERM{Fixpoint}~\NT{fix-decl}~\STARGR{\KWD{with}~\NT{fix-decl}} \nlsep \TERM{CoFixpoint}~\NT{fix-decl}~\STARGR{\KWD{with}~\NT{fix-decl}} \nlsep \TERM{Scheme}~\NT{scheme}~\STARGR{\KWD{with}~\NT{scheme}} %% Extension: record \nlsep \NT{record-tok}~\OPT{\TERM{$>$}}~\NT{ident}~\STAR{\NT{binder-let}} ~\KWD{:}~\NT{constr}~\KWD{:=} ~\OPT{\NT{ident}}~\KWD{\{}~\NT{field-list}~\KWD{\}} \nlsep \TERM{Ltac}~\NT{ltac-def}~\STARGR{~\TERM{with}~\NT{ltac-def}} \end{rules} \begin{rules} \DEFNT{thm-token} \TERM{Theorem} ~\mid~ \TERM{Lemma} ~\mid~ \TERM{Fact} ~\mid~ \TERM{Remark} \SEPDEF \DEFNT{def-token} \TERM{Definition} ~\mid~ \TERM{Let} ~\mid~ \OPT{\TERM{Local}}~\TERM{SubClass} \SEPDEF \DEFNT{assum-token} \TERM{Hypothesis} ~\mid~ \TERM{Variable} ~\mid~ \TERM{Axiom} ~\mid~ \TERM{Parameter} \SEPDEF \DEFNT{finite-token} \TERM{Inductive} ~\mid~ \TERM{CoInductive} \SEPDEF \DEFNT{record-tok} \TERM{Record} ~\mid~ \TERM{Structure} \end{rules} \begin{rules} \DEFNT{def-body} \STAR{\NT{binder-let}}~\NT{type-cstr}~\KWD{:=} ~\OPT{\NT{reduce}}~\NT{constr} \nlsep \STAR{\NT{binder-let}}~\KWD{:}~\NT{constr} \SEPDEF \DEFNT{reduce} \TERM{Eval}~\NT{red-expr}~\KWD{in} \SEPDEF \DEFNT{ltac-def} \NT{ident}~\STAR{\NT{name}}~\KWD{:=}~\NT{tactic} \SEPDEF \DEFNT{rec-definition} \NT{fix-decl}~\OPT{\NT{decl-notation}} \SEPDEF \DEFNT{inductive-definition} \OPT{\NT{string}}~\NT{ident}~\STAR{\NT{binder-let}}~\KWD{:} ~\NT{constr}~\KWD{:=} ~\OPT{\TERMbar}~\OPT{\NT{constructor-list}} ~\OPT{\NT{decl-notation}} \SEPDEF \DEFNT{constructor-list} \NT{constructor}~\TERMbar~\NT{constructor-list} \nlsep \NT{constructor} \SEPDEF \DEFNT{constructor} \NT{ident}~\STAR{\NT{binder-let}}\OPTGR{\NT{coerce-kwd}~\NT{constr}} \SEPDEF \DEFNT{decl-notation} \TERM{where}~\NT{string}~\TERM{:=}~\NT{constr} \SEPDEF \DEFNT{field-list} \NT{field}~\KWD{;}~\NT{field-list} \nlsep \NT{field} \SEPDEF \DEFNT{field} \NT{ident}~\OPTGR{\NT{coerce-kwd}~\NT{constr}} \nlsep \NT{ident}~\NT{type-cstr-coe}~\KWD{:=}~\NT{constr} \SEPDEF \DEFNT{assum-list} \PLUS{\GR{\KWD{(}~\NT{simple-assum-coe}~\KWD{)}}} \nlsep \NT{simple-assum-coe} \SEPDEF \DEFNT{simple-assum-coe} \PLUS{\NT{ident}}~\NT{coerce-kwd}~\NT{constr} \SEPDEF \DEFNT{coerce-kwd} \TERM{:$>$} ~\mid~ \KWD{:} \SEPDEF \DEFNT{type-cstr-coe} \OPTGR{\NT{coerce-kwd}~\NT{constr}} \SEPDEF \DEFNT{scheme} \NT{ident}~\KWD{:=}~\NT{dep-scheme}~\KWD{for}~\NT{reference} ~\TERM{Sort}~\NT{sort} \SEPDEF \DEFNT{dep-scheme} \TERM{Induction}~\mid~\TERM{Minimality} \end{rules} \subsection{Modules and sections} \begin{rules} \DEFNT{gallina} \TERM{Module}~\NT{ident}~\STAR{\NT{mbinder}}~\OPT{\NT{of-mod-type}} ~\OPTGR{\KWD{:=}~\NT{mod-expr}} \nlsep \TERM{Module}~\KWD{Type}~\NT{ident}~\STAR{\NT{mbinder}} ~\OPTGR{\KWD{:=}~\NT{mod-type}} \nlsep \TERM{Declare}~\TERM{Module}~\NT{ident}~\STAR{\NT{mbinder}} ~\OPT{\NT{of-mod-type}} ~\OPTGR{\KWD{:=}~\NT{mod-expr}} \nlsep \TERM{Section}~\NT{ident} \nlsep \TERM{Chapter}~\NT{ident} \nlsep \TERM{End}~\NT{ident} %% \nlsep \TERM{Require}~\OPT{\NT{export-token}}~\OPT{\NT{specif-token}} ~\PLUS{\NT{reference}} \nlsep \TERM{Require}~\OPT{\NT{export-token}}~\OPT{\NT{specif-token}} ~\NT{string} \nlsep \TERM{Import}~\PLUS{\NT{reference}} \nlsep \TERM{Export}~\PLUS{\NT{reference}} \SEPDEF \DEFNT{export-token} \TERM{Import} ~\mid~ \TERM{Export} \SEPDEF \DEFNT{specif-token} \TERM{Implementation} ~\mid~ \TERM{Specification} \SEPDEF \DEFNT{mod-expr} \NT{reference} \nlsep \NT{mod-expr}~\NT{mod-expr} & L \nlsep \KWD{(}~\NT{mod-expr}~\KWD{)} \SEPDEF \DEFNT{mod-type} \NT{reference} \nlsep \NT{mod-type}~\KWD{with}~\NT{with-declaration} \SEPDEF \DEFNT{with-declaration} %on forcera les ( ) %si exceptionnellemt %un fixpoint ici \TERM{Definition}~\NT{ident}~\KWD{:=}~\NTL{constr}{} %{100} \nlsep \TERM{Module}~\NT{ident}~\KWD{:=}~\NT{reference} \SEPDEF \DEFNT{of-mod-type} \KWD{:}~\NT{mod-type} \nlsep \TERM{$<$:}~\NT{mod-type} \SEPDEF \DEFNT{mbinder} \KWD{(}~\PLUS{\NT{ident}}~\KWD{:}~\NT{mod-type}~\KWD{)} \end{rules} \begin{rules} \DEFNT{gallina} \TERM{Transparent}~\PLUS{\NT{reference}} \nlsep \TERM{Opaque}~\PLUS{\NT{reference}} \nlsep \TERM{Canonical}~\TERM{Structure}~\NT{reference}~\OPT{\NT{def-body}} \nlsep \TERM{Coercion}~\OPT{\TERM{Local}}~\NT{reference}~\NT{def-body} \nlsep \TERM{Coercion}~\OPT{\TERM{Local}}~\NT{reference}~\KWD{:} ~\NT{class-rawexpr}~\TERM{$>->$}~\NT{class-rawexpr} \nlsep \TERM{Identity}~\TERM{Coercion}~\OPT{\TERM{Local}}~\NT{ident}~\KWD{:} ~\NT{class-rawexpr}~\TERM{$>->$}~\NT{class-rawexpr} \nlsep \TERM{Implicit}~\TERM{Arguments}~\NT{reference}~\TERM{[}~\STAR{\NT{num}}~\TERM{]} \nlsep \TERM{Implicit}~\TERM{Arguments}~\NT{reference} \nlsep \TERM{Implicit}~\KWD{Type}~\PLUS{\NT{ident}}~\KWD{:}~\NT{constr} \SEPDEF \DEFNT{command} \TERM{Comments}~\STAR{\NT{comment}} \nlsep \TERM{Pwd} \nlsep \TERM{Cd}~\OPT{\NT{string}} \nlsep \TERM{Drop} ~\mid~ \TERM{ProtectedLoop} ~\mid~\TERM{Quit} %% \nlsep \TERM{Load}~\OPT{\TERM{Verbose}}~\NT{ident} \nlsep \TERM{Load}~\OPT{\TERM{Verbose}}~\NT{string} \nlsep \TERM{Declare}~\TERM{ML}~\TERM{Module}~\PLUS{\NT{string}} \nlsep \TERM{Locate}~\NT{locatable} \nlsep \TERM{Add}~\OPT{\TERM{Rec}}~\TERM{LoadPath}~\NT{string}~\OPT{\NT{as-dirpath}} \nlsep \TERM{Remove}~\TERM{LoadPath}~\NT{string} \nlsep \TERM{Add}~\OPT{\TERM{Rec}}~\TERM{ML}~\TERM{Path}~\NT{string} %% \nlsep \KWD{Type}~\NT{constr} \nlsep \TERM{Print}~\NT{printable} \nlsep \TERM{Print}~\NT{reference} \nlsep \TERM{Inspect}~\NT{num} \nlsep \TERM{About}~\NT{reference} %% \nlsep \TERM{Search}~\NT{reference}~\OPT{\NT{in-out-modules}} \nlsep \TERM{SearchPattern}~\NT{constr-pattern}~\OPT{\NT{in-out-modules}} \nlsep \TERM{SearchRewrite}~\NT{constr-pattern}~\OPT{\NT{in-out-modules}} \nlsep \TERM{SearchAbout}~\NT{reference}~\OPT{\NT{in-out-modules}} \nlsep \TERM{SearchAbout}~\TERM{[}~\STAR{\NT{ref-or-string}}~\TERM{]}\OPT{\NT{in-out-modules}} \nlsep \KWD{Set}~\NT{ident}~\OPT{\NT{opt-value}} \nlsep \TERM{Unset}~\NT{ident} \nlsep \KWD{Set}~\NT{ident}~\NT{ident}~\OPT{\NT{opt-value}} \nlsep \KWD{Set}~\NT{ident}~\NT{ident}~\PLUS{\NT{opt-ref-value}} \nlsep \TERM{Unset}~\NT{ident}~\NT{ident}~\STAR{\NT{opt-ref-value}} %% \nlsep \TERM{Print}~\TERM{Table}~\NT{ident}~\NT{ident} \nlsep \TERM{Print}~\TERM{Table}~\NT{ident} \nlsep \TERM{Add}~\NT{ident}~\OPT{\NT{ident}}~\PLUS{\NT{opt-ref-value}} %% \nlsep \TERM{Test}~\NT{ident}~\OPT{\NT{ident}}~\STAR{\NT{opt-ref-value}} %% \nlsep \TERM{Remove}~\NT{ident}~\OPT{\NT{ident}}~\PLUS{\NT{opt-ref-value}} \SEPDEF \DEFNT{check-command} \TERM{Eval}~\NT{red-expr}~\KWD{in}~\NT{constr} \nlsep \TERM{Check}~\NT{constr} \SEPDEF \DEFNT{ref-or-string} \NT{reference} \nlsep \NT{string} \end{rules} \begin{rules} \DEFNT{printable} \TERM{Term}~\NT{reference} \nlsep \TERM{All} \nlsep \TERM{Section}~\NT{reference} \nlsep \TERM{Grammar}~\NT{ident} \nlsep \TERM{LoadPath} \nlsep \TERM{Module}~\OPT{\KWD{Type}}~\NT{reference} \nlsep \TERM{Modules} \nlsep \TERM{ML}~\TERM{Path} \nlsep \TERM{ML}~\TERM{Modules} \nlsep \TERM{Graph} \nlsep \TERM{Classes} \nlsep \TERM{Coercions} \nlsep \TERM{Coercion}~\TERM{Paths}~\NT{class-rawexpr}~\NT{class-rawexpr} \nlsep \TERM{Tables} % \nlsep \TERM{Proof}~\NT{reference} % Obsolete, useful in V6.3 ?? \nlsep \TERM{Hint}~\OPT{\NT{reference}} \nlsep \TERM{Hint}~\TERM{*} \nlsep \TERM{HintDb}~\NT{ident} \nlsep \TERM{Scopes} \nlsep \TERM{Scope}~\NT{ident} \nlsep \TERM{Visibility}~\OPT{\NT{ident}} \nlsep \TERM{Implicit}~\NT{reference} \SEPDEF \DEFNT{class-rawexpr} \TERM{Funclass}~\mid~\TERM{Sortclass}~\mid~\NT{reference} \SEPDEF \DEFNT{locatable} \NT{reference} \nlsep \TERM{File}~\NT{string} \nlsep \TERM{Library}~\NT{reference} \nlsep \NT{string} \SEPDEF \DEFNT{opt-value} \NT{ident} ~\mid~ \NT{string} \SEPDEF \DEFNT{opt-ref-value} \NT{reference} ~\mid~ \NT{string} \SEPDEF \DEFNT{as-dirpath} \KWD{as}~\NT{reference} \SEPDEF \DEFNT{in-out-modules} \TERM{inside}~\PLUS{\NT{reference}} \nlsep \TERM{outside}~\PLUS{\NT{reference}} \SEPDEF \DEFNT{comment} \NT{constr} \nlsep \NT{string} \end{rules} \subsection{Other commands} %% TODO: min/maj pas a jour \begin{rules} \EXTNT{command} \TERM{Debug}~\TERM{On} \nlsep \TERM{Debug}~\TERM{Off} %% TODO: vernac \nlsep \TERM{Add}~\TERM{setoid}~\tacconstr~\tacconstr~\tacconstr \nlsep \TERM{Add}~\TERM{morphism}~\tacconstr~\KWD{:}~\NT{ident} \nlsep \TERM{Derive}~\TERM{inversion_clear} ~\OPT{\NT{num}}~\NT{ident}~\NT{ident} \nlsep \TERM{Derive}~\TERM{inversion_clear} ~\NT{ident}~\KWD{with}~\tacconstr~\OPTGR{\TERM{Sort}~\NT{sort}} \nlsep \TERM{Derive}~\TERM{inversion} ~\OPT{\NT{num}}~\NT{ident}~\NT{ident} \nlsep \TERM{Derive}~\TERM{inversion} ~\NT{ident}~\KWD{with}~\tacconstr~\OPTGR{\TERM{Sort}~\NT{sort}} \nlsep \TERM{Derive}~\TERM{dependent}~\TERM{inversion_clear} ~\NT{ident}~\KWD{with}~\tacconstr~\OPTGR{\TERM{Sort}~\NT{sort}} \nlsep \TERM{Derive}~\TERM{dependent}~\TERM{inversion} ~\NT{ident}~\KWD{with}~\tacconstr~\OPTGR{\TERM{Sort}~\NT{sort}} %% Correctness: obsolete ? %\nlsep Correctness %\nlsep Global Variable %% TODO: extraction \nlsep Extraction ... %% field \nlsep \TERM{Add}~\TERM{Field}~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\tacconstr~\OPT{\NT{minus-div}} %% funind \nlsep \TERM{Functional}~\TERM{Scheme}~\NT{ident}~\KWD{:=} ~\TERM{Induction}~\KWD{for}~\tacconstr ~\OPTGR{\KWD{with}~\PLUS{\tacconstr}} %% ring \nlsep \TERM{Add}~\TERM{Ring}~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\tacconstr~\KWD{[}~\PLUS{\tacconstr}~\KWD{]} \nlsep \TERM{Add}~\TERM{Semi}~\TERM{Ring}~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\KWD{[}~\PLUS{\tacconstr}~\KWD{]} \nlsep \TERM{Add}~\TERM{Abstract}~\TERM{Ring}~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\tacconstr \nlsep \TERM{Add}~\TERM{Abstract}~\TERM{Semi}~\TERM{Ring}~\tacconstr ~\tacconstr~\tacconstr~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr \nlsep \TERM{Add}~\TERM{Setoid}~\TERM{Ring}~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\tacconstr~\tacconstr~\tacconstr~\tacconstr~\tacconstr ~\tacconstr~\KWD{[}~\PLUS{\tacconstr}~\KWD{]} \nlsep \TERM{Add}~\TERM{Setoid}~\TERM{Semi}~\TERM{Ring}~\tacconstr~\tacconstr ~\tacconstr~\tacconstr~\tacconstr~\tacconstr \nlcont~~~~\tacconstr~\tacconstr~\tacconstr~\tacconstr~\tacconstr ~\KWD{[}~\PLUS{tacconstr}~\KWD{]} \SEPDEF \DEFNT{minus-div} \KWD{with}~\NT{minus-arg}~\NT{div-arg} \nlsep \KWD{with}~\NT{div-arg}~\NT{minus-arg} \SEPDEF \DEFNT{minus-arg} \TERM{minus}~\KWD{:=}~\tacconstr \SEPDEF \DEFNT{div-arg} \TERM{div}~\KWD{:=}~\tacconstr \end{rules} \begin{rules} \EXTNT{command} \TERM{Write}~\TERM{State}~\NT{ident} \nlsep \TERM{Write}~\TERM{State}~\NT{string} \nlsep \TERM{Restore}~\TERM{State}~\NT{ident} \nlsep \TERM{Restore}~\TERM{State}~\NT{string} \nlsep \TERM{Reset}~\NT{ident} \nlsep \TERM{Reset}~\TERM{Initial} \nlsep \TERM{Back}~\OPT{\NT{num}} \end{rules} \subsection{Proof-editing commands} \begin{rules} \EXTNT{command} \TERM{Goal}~\NT{constr} \nlsep \TERM{Proof}~\OPT{\NT{constr}} \nlsep \TERM{Proof}~\KWD{with}~\NT{tactic} \nlsep \TERM{Abort}~\OPT{\TERM{All}} \nlsep \TERM{Abort}~\NT{ident} \nlsep \TERM{Existential}~\NT{num}~\KWD{:=}~\NT{constr-body} \nlsep \TERM{Qed} \nlsep \TERM{Save}~\NT{ident} \nlsep \TERM{Defined}~\OPT{\NT{ident}} \nlsep \TERM{Suspend} \nlsep \TERM{Resume}~\OPT{\NT{ident}} \nlsep \TERM{Restart} \nlsep \TERM{Undo}~\OPT{\NT{num}} \nlsep \TERM{Focus}~\OPT{\NT{num}} \nlsep \TERM{Unfocus} \nlsep \TERM{Show}~\OPT{\NT{num}} \nlsep \TERM{Show}~\TERM{Implicit}~\TERM{Arguments}~\OPT{\NT{num}} \nlsep \TERM{Show}~\TERM{Node} \nlsep \TERM{Show}~\TERM{Existentials} \nlsep \TERM{Show}~\TERM{Tree} \nlsep \TERM{Show}~\TERM{Conjecture} \nlsep \TERM{Show}~\TERM{Proof} \nlsep \TERM{Show}~\TERM{Intro} \nlsep \TERM{Show}~\TERM{Intros} %% Correctness: obsolete ? %%\nlsep \TERM{Show}~\TERM{Programs} \nlsep \TERM{Hint}~\OPT{\TERM{Local}}~\NT{hint}~\OPT{\NT{inbases}} %% PrintConstr not documented \end{rules} \begin{rules} \DEFNT{constr-body} \NT{type-cstr}~\KWD{:=}~\NT{constr} \SEPDEF \DEFNT{hint} \TERM{Resolve}~\PLUS{\NTL{constr}{9}} \nlsep \TERM{Immediate}~\PLUS{\NTL{constr}{9}} \nlsep \TERM{Unfold}~\PLUS{\NT{reference}} \nlsep \TERM{Constructors}~\PLUS{\NT{reference}} \nlsep \TERM{Extern}~\NT{num}~\NT{constr}~\KWD{$\Rightarrow$}~\NT{tactic} \nlsep \TERM{Destruct}~\NT{ident}~\KWD{:=}~\NT{num}~\NT{destruct-loc} ~\NT{constr}~\KWD{$\Rightarrow$}~\NT{tactic} \nlsep \TERM{Rewrite}~\NT{orient}~\PLUS{\NTL{constr}{9}} ~\OPTGR{\KWD{using}~\NT{tactic}} \SEPDEF \DEFNT{inbases} \KWD{:}~\PLUS{\NT{ident}} \SEPDEF \DEFNT{destruct-loc} \TERM{Conclusion} \nlsep \OPT{\TERM{Discardable}}~\TERM{Hypothesis} \end{rules} \subsection{Syntax extensions} \begin{rules} \DEFNT{syntax} \TERM{Open}~\TERM{Scope}~\NT{ident} \nlsep \TERM{Close}~\TERM{Scope}~\NT{ident} \nlsep \TERM{Delimit}~\TERM{Scope}~\NT{ident}~\KWD{with}~\NT{ident} \nlsep \TERM{Bind}~\TERM{Scope}~\NT{ident}~\KWD{with}~\PLUS{\NT{class-rawexpr}} \nlsep \TERM{Arguments}~\TERM{Scope}~\NT{reference} ~\TERM{[}~\PLUS{\NT{name}}~\TERM{]} \nlsep \TERM{Infix}~\OPT{\TERM{Local}} %%% ~\NT{prec}~\OPT{\NT{num}} ~\NT{string}~\KWD{:=}~\NT{reference}~\OPT{\NT{modifiers}} ~\OPT{\NT{in-scope}} \nlsep \TERM{Notation}~\OPT{\TERM{Local}}~\NT{string}~\KWD{:=}~\NT{constr} ~\OPT{\NT{modifiers}}~\OPT{\NT{in-scope}} \nlsep \TERM{Notation}~\OPT{\TERM{Local}}~\NT{ident}~\KWD{:=}~\NT{constr} ~\OPT{\KWD{(}\TERM{only~\TERM{parsing}\KWD{)}}} \nlsep \TERM{Reserved}~\TERM{Notation}~\OPT{\TERM{Local}}~\NT{string} ~\OPT{\NT{modifiers}} \nlsep \TERM{Tactic}~\TERM{Notation}~\NT{string}~\STAR{\NT{tac-production}} ~\KWD{:=}~\NT{tactic} \SEPDEF \DEFNT{modifiers} \KWD{(}~\NT{mod-list}~\KWD{)} \SEPDEF \DEFNT{mod-list} \NT{modifier} \nlsep \NT{modifier}~\KWD{,}~\NT{mod-list} \SEPDEF \DEFNT{modifier} \NT{ident}~\KWD{at}~\NT{num} \nlsep \NT{ident}~\STARGR{\KWD{,}~\NT{ident}}~\KWD{at}~\NT{num} \nlsep \KWD{at}~\TERM{next}~\TERM{level} \nlsep \KWD{at}~\TERM{level}~\NT{num} \nlsep \TERM{left}~\TERM{associativity} \nlsep \TERM{right}~\TERM{associativity} \nlsep \TERM{no}~\TERM{associativity} \nlsep \NT{ident}~\NT{syntax-entry} \nlsep \TERM{only}~\TERM{parsing} \nlsep \TERM{format}~\NT{string} \SEPDEF \DEFNT{in-scope} \KWD{:}~\NT{ident} \SEPDEF \DEFNT{syntax-entry} \TERM{ident}~\mid~\TERM{global}~\mid~\TERM{bigint} \SEPDEF \DEFNT{tac-production} \NT{string} \nlsep \NT{ident}~\TERM{(}~\NT{ident}~\TERM{)} %%% \SEPDEF %%% \DEFNT{prec} %%% \TERM{LeftA}~\mid~\TERM{RightA}~\mid~\TERM{NonA} \end{rules} \end{document} rocq-9.2.0/dev/doc/archive/versions-history.tex000066400000000000000000000347361516144147600215510ustar00rootroot00000000000000\documentclass[a4paper]{book} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{amsfonts} \newcommand{\feature}[1]{{\em #1}} \begin{document} \begin{center} \begin{huge} A history of Coq versions \end{huge} \end{center} \bigskip \centerline{\large 1984-1989: The Calculus of Constructions} \bigskip \centerline{\large (see README.V1-V5 for details)} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline CONSTR V1.10& mention of dates from 6 December & \feature{type-checker for Coquand's Calculus }\\ & 1984 to 13 February 1985 & \feature{of Constructions}, implementation \\ & frozen 22 December 1984 & language is a predecessor of CAML\\ CONSTR V1.11& mention of dates from 6 December\\ & 1984 to 19 February 1985 (freeze date) &\\ CoC V2.8& dated 16 December 1985 (freeze date)\\ CoC V2.9& & \feature{cumulative hierarchy of universes}\\ CoC V2.13& dated 25 June 1986 (freeze date)\\ CoC V3.1& started summer 1986 & \feature{AUTO tactic}\\ & dated 20 November 1986 & implementation language now named CAML\\ CoC V3.2& dated 27 November 1986\\ CoC V3.3& dated 1 January 1987 & creation of a directory for examples\\ CoC V3.4& dated 1 January 1987 & \feature{lambda and product distinguished in the syntax}\\ CoC V4.1& dated 24 July 1987 (freeze date)\\ CoC V4.2& dated 10 September 1987\\ CoC V4.3& dated 15 September 1987 & \feature{mathematical vernacular toplevel}\\ & frozen November 1987 & \feature{section mechanism}\\ & & \feature{logical vs computational content (sorte Spec)}\\ & & \feature{LCF engine}\\ CoC V4.4& dated 27 January 1988 & \feature{impredicatively encoded inductive types}\\ & frozen March 1988\\ CoC V4.5 and V4.5.5& dated 15 March 1988 & \feature{program extraction}\\ & demonstrated in June 1988\\ CoC V4.6& dated 1 September 1988 & start of LEGO fork\\ CoC V4.7& started 6 September 1988 \\ CoC V4.8& dated 1 December 1988 (release time) & \feature{floating universes}\\ CoC V4.8.5& dated 1 February 1989 & \\ CoC V4.9& dated 1 March 1989 (release date)\\ CoC V4.10 and 4.10.1& dated 1 May 1989 & released with documentation in English\\ \end{tabular} \bigskip \noindent Note: CoC above stands as an abbreviation for {\em Calculus of Constructions}, official name of the system. \bigskip \bigskip \newpage \centerline{\large 1989-now: The Calculus of Inductive Constructions} \mbox{}\\ \centerline{I- RCS archives in Caml and Caml-Light} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline Coq V5.0 & headers dated 1 January 1990 & internal use \\ & & \feature{inductive types with primitive recursor}\\ Coq V5.1 & ended 12 July 1990 & internal use \\ Coq V5.2 & log dated 4 October 1990 & internal use \\ Coq V5.3 & log dated 12 October 1990 & internal use \\ Coq V5.4 & headers dated 24 October 1990 & internal use, new \feature{extraction} (version 1) [3-12-90]\\ Coq V5.5 & started 6 December 1990 & internal use \\ Coq V5.6 beta & 1991 & first announce of the new Coq based on CIC \\ & & (in May at TYPES?)\\ & & \feature{rewrite tactic}\\ & & use of RCS at least from February 1991\\ Coq V5.6& 7 August 1991 & \\ Coq V5.6 patch 1& 13 November 1991 & \\ Coq V5.6 (last) & mention of 27 November 1992\\ Coq V5.7.0& 1992 & translation to Caml-Light \footnotemark\\ Coq V5.8& 12 February 1993 & \feature{Program} (version 1), \feature{simpl}\\ & & has the xcoq graphical interface\\ & & first explicit notion of standard library\\ & & includes a MacOS 7-9 version\\ Coq V5.8.1& released 28 April 1993 & with xcoq graphical interface and MacOS 7-9 support\\ Coq V5.8.2& released 9 July 1993 & with xcoq graphical interface and MacOS 7-9 support\\ Coq V5.8.3& released 6 December 1993 % Announce on coq-club & with xcoq graphical interface and MacOS 7-9 support\\ & & 3 branches: Lyon (V5.8.x), Ulm (V5.10.x) and Rocq (V5.9)\\ Coq V5.9 alpha& 7 July 1993 & experimental version based on evars refinement \\ & & (merge from experimental ``V6.0'' and some pre-V5.8.3 \\ & & version), not released\\ & March 1994 & \feature{tauto} tactic in V5.9 branch\\ Coq V5.9 & 27 January 1993 & experimental version based on evars refinement\\ & & not released\\ \end{tabular} \bigskip \bigskip \footnotetext{archive lost?} \newpage \centerline{II- Starting with CVS archives in Caml-Light} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline Coq V5.10 ``Murthy'' & 22 January 1994 & introduction of the ``DOPN'' structure\\ & & \feature{eapply/prolog} tactics\\ & & private use of cvs on madiran.inria.fr\\ Coq V5.10.1 ``Murthy''& 15 April 1994 \\ Coq V5.10.2 ``Murthy''& 19 April 1994 & \feature{mutual inductive types, fixpoint} (from Lyon's branch)\\ Coq V5.10.3& 28 April 1994 \\ Coq V5.10.5& dated 13 May 1994 & \feature{inversion}, \feature{discriminate}, \feature{injection} \\ & & \feature{type synthesis of hidden arguments}\\ & & \feature{separate compilation}, \feature{reset mechanism} \\ Coq V5.10.6& dated 30 May 1994\\ Coq Lyon's archive & in 1994 & cvs server set up on woodstock.ens-lyon.fr\\ Coq V5.10.9& announced on 17 August 1994 & % Announced by Catherine Parent on coqdev % Version avec une copie de THEORIES pour les inductifs mutuels \\ Coq V5.10.11& announced on 2 February 1995 & \feature{compute}\\ Coq Rocq's archive & on 16 February 1995 & set up of ``V5.10'' cvs archive on pauillac.inria.fr \\ & & with first dispatch of files over src/* directories\\ Coq V5.10.12& dated 30 January 1995 & on Lyon's cvs\\ Coq V5.10.13& dated 9 June 1995 & on Lyon's cvs\\ Coq V5.10.14.OO& dated 30 June 1995 & on Lyon's cvs\\ Coq V5.10.14.a& announced 5 September 1995 & bug-fix release \\ % Announce on coq-club by BW Coq V5.10.14.b& released 2 October 1995 & bug-fix release\\ & & MS-DOS version released on 30 October 1995\\ % still available at ftp://ftp.ens-lyon.fr/pub/LIP/COQ/V5.10.14.old/ in May 2009 % also known in /net/pauillac/constr archive as ``V5.11 old'' \\ % A copy of Coq V5.10.15 dated 1 January 1996 coming from Lyon's CVS is % known in /net/pauillac/constr archive as ``V5.11 new old'' \\ Coq V5.10.15 & released 20 February 1996 & \feature{Logic, Sorting, new Sets and Relations libraries} \\ % Announce on coq-club by BW % dated 15 February 1996 and bound to pauillac's cvs in /net/pauillac/constr archive & & MacOS 7-9 version released on 1 March 1996 \\ % Announce on coq-club by BW Coq V5.11 & dated 1 March 1996 & not released, not in pauillac's CVS, \feature{eauto} \\ \end{tabular} \bigskip \bigskip \newpage \centerline{III- A CVS archive in Caml Special Light} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline Coq ``V6'' archive & 20 March 1996 & new cvs repository on pauillac.inria.fr with code ported \\ & & to Caml Special Light (to later become Objective Caml)\\ & & has implicit arguments and coercions\\ & & has coinductive types\\ Coq V6.1beta& released 18 November 1996 & \feature{coercions} [23-5-1996], \feature{user-level implicit arguments} [23-5-1996]\\ & & \feature{omega} [10-9-1996] \\ & & \feature{natural language proof printing} (stopped from Coq V7) [6-9-1996]\\ & & \feature{pattern-matching compilation} [7-10-1996]\\ & & \feature{ring} (version 1, ACSimpl) [11-12-1996]\\ Coq V6.1& released December 1996 & \\ Coq V6.2beta& released 30 January 1998 & % Announced on coq-club 2-2-1998 by CP \feature{SearchIsos} (stopped from Coq V7) [9-11-1997]\\ & & grammar extension mechanism moved to Camlp4 [12-6-1997]\\ & & \feature{refine tactic}\\ & & includes a Windows version\\ Coq V6.2& released 4 May 1998 & % Announced on coq-club 5-5-1998 by CP \feature{ring} (version 2) [7-4-1998] \\ Coq V6.2.1& released 23 July 1998\\ Coq V6.2.2 beta& released 30 January 1998\\ Coq V6.2.2& released 23 September 1998\\ Coq V6.2.3& released 22 December 1998 & \feature{Real numbers library} [from 13-11-1998] \\ Coq V6.2.4& released 8 February 1999\\ Coq V6.3& released 27 July 1999 & \feature{autorewrite} [25-3-1999]\\ & & \feature{Correctness} (deprecated in V8, led to Why) [28-10-1997]\\ Coq V6.3.1& released 7 December 1999\\ \end{tabular} \medskip \bigskip \newpage \centerline{IV- New CVS, back to a kernel-centric implementation} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline 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{${\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] \\ & & \feature{field} (version 1) [19-4-2001], \feature{fourier} [20-4-2001] \\ Coq V7.1& released 25 September 2001 & \feature{setoid rewriting} (version 1) [10-7-2001]\\ Coq V7.2& released 10 January 2002\\ Coq V7.3& released 16 May 2002\\ Coq V7.3.1& released 5 October 2002 & \feature{module system} [2-8-2002]\\ & & \feature{pattern-matching compilation} (version 2) [13-6-2002]\\ Coq V7.4& released 6 February 2003 & \feature{notation}, \feature{scopes} [13-10-2002]\\ \end{tabular} \medskip \bigskip \centerline{V- New concrete syntax} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline Coq V8.0& released 21 April 2004 & \feature{new concrete syntax}, \feature{Set predicative}, \feature{CoqIDE} [from 4-2-2003]\\ Coq V8.0pl1& released 18 July 2004\\ Coq V8.0pl2& released 22 January 2005\\ Coq V8.0pl3& released 13 January 2006\\ Coq V8.0pl4& released 26 January 2007\\ Coq ``svn'' archive & 6 March 2006 & cvs archive moved to subversion control management\\ Coq V8.1beta& released 12 July 2006 & \feature{bytecode compiler} [20-10-2004] \\ & & \feature{setoid rewriting} (version 2) [3-9-2004]\\ & & \feature{functional induction} [1-2-2006]\\ & & \feature{Strings library} [8-2-2006], \feature{FSets/FMaps library} [15-3-2006] \\ & & \feature{Program} (version 2, Russell) [5-3-2006] \\ & & \feature{declarative language} [20-9-2006]\\ & & \feature{ring} (version 3) [18-11-2005]\\ Coq V8.1gamma& released 7 November 2006 & \feature{field} (version 2) [29-9-2006]\\ Coq V8.1& released 10 February 2007 & \\ Coq V8.1pl1& released 27 July 2007 & \\ Coq V8.1pl2& released 13 October 2007 & \\ Coq V8.1pl3& released 13 December 2007 & \\ Coq V8.1pl4& released 9 October 2008 & \\ Coq V8.2 beta1& released 13 June 2008 & \\ Coq V8.2 beta2& released 19 June 2008 & \\ Coq V8.2 beta3& released 27 June 2008 & \\ Coq V8.2 beta4& released 8 August 2008 & \\ Coq V8.2 & released 17 February 2009 & \feature{type classes} [10-12-2007], \feature{machine words} [11-5-2007]\\ & & \feature{big integers} [11-5-2007], \feature{abstract arithmetics} [9-2007]\\ & & \feature{setoid rewriting} (version 3) [18-12-2007] \\ & & \feature{micromega solving platform} [19-5-2008]\\ & & a first package released on February 11 was incomplete\\ Coq V8.2pl1& released 4 July 2009 & \\ Coq V8.2pl2& released 29 June 2010 & \\ \end{tabular} \medskip \bigskip \newpage \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} Coq V8.3 beta & released 16 February 2010 & \feature{MSets library} [13-10-2009] \\ Coq V8.3 & released 14 October 2010 & \feature{nsatz} [3-6-2010] \\ Coq V8.3pl1& released 23 December 2010 & \\ Coq V8.3pl2& released 19 April 2011 & \\ Coq V8.3pl3& released 19 December 2011 & \\ Coq V8.3pl3& released 26 March 2012 & \\ Coq V8.3pl5& released 28 September 2012 & \\ Coq V8.4 beta & released 27 December 2011 & \feature{modular arithmetic library} [2010-2012]\\ && \feature{vector library} [10-12-2010]\\ && \feature{structured scripts} [22-4-2010]\\ && \feature{eta-conversion} [20-9-2010]\\ && \feature{new proof engine available} [10-12-2010]\\ Coq V8.4 beta2 & released 21 May 2012 & \\ Coq V8.4 & released 12 August 2012 &\\ Coq V8.4pl1& released 22 December 2012 & \\ Coq V8.4pl2& released 4 April 2013 & \\ Coq V8.4pl3& released 21 December 2013 & \\ Coq V8.4pl4& released 24 April 2014 & \\ Coq V8.4pl5& released 22 October 2014 & \\ Coq V8.4pl6& released 9 April 2015 & \\ Coq V8.5 beta1 & released 21 January 2015 & \feature{computation via compilation to OCaml} [22-1-2013]\\ && \feature{asynchronous evaluation} [8-8-2013]\\ && \feature{new proof engine deployed} [2-11-2013]\\ && \feature{universe polymorphism} [6-5-2014]\\ && \feature{primitive projections} [6-5-2014]\\ && \feature{miscellaneous optimizations}\\ Coq V8.5 beta2 & released 22 April 2015 & \feature{MMaps library} [4-3-2015]\\ Coq V8.5 & released 22 January 2016 & \\ Coq V8.6 beta 1 & released 19 November 2016 & \feature{irrefutable patterns} [15-2-2016]\\ && \feature{Ltac profiling} [14-6-2016]\\ && \feature{warning system} [29-6-2016]\\ && \feature{miscellaneous optimizations}\\ Coq V8.6 & released 14 December 2016 & \\ Coq V8.7 beta 1 & released 6 September 2017 & \feature{bundled with Ssreflect plugin} [6-6-2017]\\ && \feature{cumulative polymorphic inductive types} [19-6-2017]\\ && \feature{further optimizations}\\ Coq V8.7 beta 2 & released 6 October 2017 & \\ Coq V8.7.0 & released 18 October 2017 & \\ Coq V8.7.1 & released 15 December 2017 & \\ Coq V8.7.2 & released 17 February 2018 & \\ Coq V8.8 beta1 & released 19 March 2018 & \\ Coq V8.8.0 & released 17 April 2018 & \feature{reference manual moved to Sphinx} \\ && \feature{effort towards better documented, better structured ML API}\\ && \feature{miscellaneous changes/improvements of existing features}\\ \end{tabular} \medskip \bigskip \newpage \centerline{\large Other important dates} \mbox{}\\ \mbox{}\\ \begin{tabular}{l|l|l} version & date & comments \\ \hline Lechenadec's version in C& mention of \\ & 13 January 1985 on \\ & some vernacular files\\ Set up of the coq-club mailing list & 28 July 1993\\ Coq V6.0 ``evars'' & & experimentation based on evars refinement started \\ & & in 1991 by Gilles from V5.6 beta,\\ & & with work by Hugo in July 1992\\ Coq V6.0 ``evars'' ``light'' & July 1993 & Hugo's port of the first evars-based experimentation \\ & & to Coq V5.7, version from October/November 1992\\ CtCoq & released 25 October 1995 & first beta-version \\ % Announce on coq-club by Janet Proto with explicit substitutions & 1997 &\\ Coq web site & 15 April 1998 & new site designed by David Delahaye \\ Coq web site & January 2004 & web site new style \\ & & designed by Julien Narboux and Florent Kirchner \\ Coq web site & April 2009 & new Drupal-based site \\ & & designed by Jean-Marc Notin and Denis Cousineau \\ \end{tabular} \end{document} rocq-9.2.0/dev/doc/archive/whodidwhat/000077500000000000000000000000001516144147600176055ustar00rootroot00000000000000rocq-9.2.0/dev/doc/archive/whodidwhat/whodidwhat-8.2update.tex000066400000000000000000000316601516144147600242070ustar00rootroot00000000000000\documentclass{article} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage{t1enc} \begin{document} \title{Who did what in the Coq archive?} \author{The Coq development team} \maketitle \centerline{(updated for Coq 8.2)} \section{The Calculus of Inductive Constructions} \begin{itemize} \item The Calculus of Constructions \begin{itemize} \item Core type-checker: GΓ©rard Huet and Thierry Coquand with optimizations by Chet Murthy, Bruno Barras \item Head reduction functions: GΓ©rard Huet, Christine Paulin, Bruno Barras \end{itemize} \item Conversion and reduction \begin{itemize} \item Lazy conversion machine: Bruno Barras \item Transparency/opacity: Bruno Barras \item Bytecode-based conversion: Benjamin GrΓ©goire \item Binary-words retroknowledge: Arnaud Spiwack \end{itemize} \item The universe hierarchy \begin{itemize} \item Floating universes: GΓ©rard Huet, with contributions from Bruno Barras \item Algebraic universes: Hugo Herbelin \end{itemize} \item Mutual inductive types and recursive definitions \begin{itemize} \item Type-checking: Christine Paulin \item Positivity condition: Christine Paulin \item Guardness condition for fixpoints: Christine Paulin; extensions by Eduardo Gimenez and Bruno Barras \item Recursively non-uniform parameters: Christine Paulin \item Sort-polymorphism of inductive types: Hugo Herbelin \end{itemize} \item Local definitions: Hugo Herbelin \item Mutual coinductive types and corecursive definitions: Eduardo Gimenez \item Module system \begin{itemize} \item Core system: Jacek Chrz\k{a}szcz \item Inlining: Claudio Sacerdoti Coen and Γ‰lie Soubiran \item Module inclusion: Γ‰lie Soubiran \item Functorial signature application: Γ‰lie Soubiran \item Transparent name space: Γ‰lie Soubiran \item Resolution of qualified names: Hugo Herbelin \end{itemize} \item Minimalist stand-alone type-checker (\texttt{coqchk}): Bruno Barras \end{itemize} \section{Specification language} \begin{itemize} \item Sections: Gilles Dowek with extra contributions by GΓ©rard Huet, Chet Murthy, Hugo Herbelin \item The \texttt{Russell} specifications language, proof obligations (\texttt{Program}): Matthieu Sozeau \item Type inference: Chet Murthy, with extra contributions by Bruno Barras, Hugo Herbelin and Matthieu Sozeau \item Pattern-matching: Hugo Herbelin on top of a first version by Cristina Cornes \item Implicit arguments: Amokrane SaΓ―bi, with extensions by Hugo Herbelin and Matthieu Sozeau \item Coercions: Amokrane SaΓ―bi \item Records: Amokrane SaΓ―bi with extensions by Arnaud Spiwack and Matthieu Sozeau \item Canonical structures: Amokrane SaΓ―bi \item Type classes: Matthieu Sozeau \item Functional schemes (\texttt{Function}, \texttt{Functional Scheme}, ...): Julien Forest and Pierre Courtieu (preliminary version by Yves Bertot) \item Generation of induction schemes: Christine Paulin, Vincent Siles, Matthieu Sozeau \end{itemize} \section{Tactics} \subsection{General tactic support} \begin{itemize} \item Proof engine: Chet Murthy (first version by Thierry Coquand) \item Ltac: David Delahaye, with extensions by Hugo Herbelin, Bruno Barras, ... \item Tactic notations: Hugo Herbelin (first version by Chet Murthy) \item Main tactic unification procedure: Chet Murthy with contributions from Hugo Herbelin and Matthieu Sozeau \item Mathematical-style language (C-Zar): Pierre Corbineau \item Communication with external tools (\texttt{external}): Hugo Herbelin \end{itemize} \subsection{Predefined tactics} \begin{itemize} \item Basic tactics (\texttt{intro}, \texttt{apply}, \texttt{assumption}, \texttt{exact}): Thierry Coquand, with further collective extensions \item Reduction tactics: Christine Paulin (\texttt{simpl}), Bruno Barras (\texttt{cbv}, \texttt{lazy}), ... \item Tacticals: Thierry Coquand, Chet Murthy, Eduardo Gimenez, ... \item Induction: Christine Paulin (\texttt{elim}, \texttt{case}), Hugo Herbelin (\texttt{induction}, \texttt{destruct} \item Refinement (\texttt{refine}): Jean-Christophe FilliΓ’tre \item Introduction patterns: Eduardo Gimenez with collective extensions \item Forward reasoning: Hugo Herbelin (\texttt{assert}, \texttt{apply in}), Pierre Letouzey (\texttt{specialize}, initial version by Amy Felty) \item Rewriting tactics (\texttt{rewrite}): basic version by Christine Paulin, extensions by Jean-Christophe FilliΓ’tre and Pierre Letouzey \item Tactics about equivalence properties (\texttt{reflexivity}, \texttt{symmetry}, \texttt{transitivity}): Christine Paulin (?), \item Equality tactics (\texttt{injection}/\texttt{discriminate}): Cristina Cornes \item Inversion tactics (\texttt{inversion}): Cristina Cornes, Chet Murthy \item Setoid rewriting: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen), contributions from Nicolas Tabareau \item Decision of equality: Eduardo Gimenez \item Basic Ltac-level tactics: Pierre Letouzey, Matthieu Sozeau, Evgeny Makarov \end{itemize} \subsection{General automation tactics} \begin{itemize} \item Resolution (\texttt{auto}, \texttt{trivial}): Christine Paulin with extensions from Chet Murthy, Eduardo Gimenez, Patrick Loiseleur (hint bases), Matthieu Sozeau \item Resolution with existential variables (\texttt{eauto}): Chet Murthy, Jean-Christophe FilliΓ’tre, with extensions from Matthieu Sozeau \item Automatic rewriting (\texttt{autorewrite}): David Delahaye \end{itemize} \subsection{Domain-specific decision tactics} \begin{itemize} \item Congruence closure (\texttt{cc}): Pierre Corbineau \item Decision of first-order logic (\texttt{firstorder}): Pierre Corbineau \item Simplification of polynomial fractions (\texttt{field}): Laurent ThΓ©ry and Benjamin GrΓ©goire (first version by David Delahaye and Micaela Mayero) \item Simplification of polynomial expressions (\texttt{ring}): Assia Mahboubi, Bruno Barras and Benjamin GrΓ©goire (first version by Samuel Boutin, second version by Patrick Loiseleur) \item Decision of systems of linear inequations: FrΓ©dΓ©ric Besson (\texttt{psatzl}); LoΓ―c Pottier (\texttt{fourier}) \item Decision of systems of linear inequations over integers: FrΓ©dΓ©ric Besson (\texttt{lia}); Pierre CrΓ©gut (\texttt{omega} and \texttt{romega}) \item (Partial) decision of systems of polynomical inequations (\texttt{sos}, \texttt{psatz}): FrΓ©dΓ©ric Besson, with generalization over arbitrary rings by Evgeny Makarov; uses HOL-Light interface to \texttt{csdp} by John Harrisson \item Decision/simplification of intuitionistic propositional logic: David Delahaye (\texttt{tauto}, \texttt{intuition}, first version by Cesar Mu\~noz, second version by Chet Murthy), with contributions from JudicaΓ«l Courant; Pierre Corbineau (\texttt{rtauto}) \item Decision/simplification of intuition first-order logic: Pierre Corbineau (\texttt{firstorder}) \end{itemize} \section{Extra tools} \begin{itemize} \item Program extraction: Pierre Letouzey (first implementation by Benjamin Werner, second by Jean-Christophe FilliΓ’tre) \item Export of context to external communication tools (\texttt{dp}): Nicolas Ayache and Jean-Christophe FilliΓ’tre, with contributions by Claude MarchΓ© \item Export of terms and environments to XML format: Claudio Sacerdoti Coen, with extensions from Cezary Kaliszyk \end{itemize} \section{Environment management} \begin{itemize} \item Separate compilation: initiated by Chet Murthy \item Import/Export: initiated by Chet Murthy \item Options management: Hugo Herbelin with contributions by Arnaud Spiwack \item Resetting and backtracking: Chet Murthy with contributions from Pierre Courtieu \item Searching: Hugo Herbelin, Yves Bertot \item Whelp support: Hugo Herbelin \end{itemize} \section{Parsing and printing} \begin{itemize} \item General parsing support: Chet Murthy, Bruno Barras, Daniel de Rauglaudre \item General printing support: Chet Murthy, Jean-Christophe FilliΓ’tre \item Lexing: Daniel de Rauglaudre \item Support for UTF-8: Hugo Herbelin, with contributions from Alexandre Miquel \item Numerical notations: Hugo Herbelin, Patrick Loiseleur, Micaela Mayero \item String notations: Hugo Herbelin \item New ``V8'' syntax: Bruno Barras, Hugo Herbelin with contributions by Olivier Desmettre \item Abbreviations: Chet Murthy \item Notations: Chet Murthy, Hugo Herbelin \end{itemize} \section{Libraries} \begin{itemize} \item Init: collective (initiated by Christine Paulin and GΓ©rard Huet) \item Arith: collective (initiated by Christine Paulin) \item ZArith: collective (initiated by Pierre CrΓ©gut) \item Bool: collective (initiated by Christine Paulin) \item NArith: Hugo Herbelin, Pierre Letouzey, Evgeny Makarov (out of initial contibution by Pierre CrΓ©gut) \item Lists: Pierre Letouzey, Jean-Marc Notin (initiated by Christine Paulin) \item Reals: Micaela Mayero (axiomatization and main properties), Olivier Desmettre (convergence, derivability, integrals, trigonometric functions), contributions from Russell O'Connor and Cezary Kaliszyk \item Relations: Bruno Barras, Cristina Cornes with contributions from Pierre CastΓ©ran \item Wellfounded: Bruno Barras, Cristina Cornes \item FSets: Pierre Letouzey, from initial work with Jean-Christophe FilliΓ’tre, decision tactic for FSets by Aaron Bohannon \item Logic: Christine Paulin, Hugo Herbelin, Bruno Barras \item Numbers: Evgeny Makarov (abstractions), Laurent ThΓ©ry and Benjamin GrΓ©goire (big numbers), Arnaud Spiwack and Pierre Letouzey (word-based arithmetic) \item Classes: Matthieu Sozeau \item QArith: Pierre Letouzey, with contributions from Russell O'Connor \item Setoid: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen) \item Sets: Gilles Kahn and GΓ©rard Huet \item Sorting: GΓ©rard Huet \item Strings: Laurent ThΓ©ry \item Program: Matthieu Sozeau \item Unicode: Claude MarchΓ© \end{itemize} \section{Commands} \begin{itemize} \item Batch compiler (\texttt{coqc}): Chet Murthy (?) \item Compilation dependency calculator (\texttt{coqdep}): Jean-Christophe FilliΓ’tre \item Statistic tool (\texttt{coqwc}): Jean-Christophe FilliΓ’tre \item Simple html presentation tool (\texttt{gallina}) (deprecated): Jean-Christophe FilliΓ’tre \item Auto-maker (\texttt{coq\_makefile}): Jean-Christophe FilliΓ’tre, with contributions from JudicaΓ«l Courant \item LaTeX presentation tool (\texttt{coq-tex}): Jean-Christophe FilliΓ’tre \item Multi-purpose presentation tool (\texttt{coqdoc}): Jean-Christophe FilliΓ’tre with extensions from Matthieu Sozeau, Jean-Marc Notin, Hugo Herbelin \item Interactive toplevel (\texttt{coqtop}): Jean-Christophe FilliΓ’tre (?) \item Custom toplevel builder (\texttt{coqmktop}): Jean-Christophe FilliΓ’tre (?) \end{itemize} \section{Graphical interfaces} \begin{itemize} \item Support for {\em PCoq}: Yves Bertot with contributions by Laurence Rideau and LoΓ―c Pottier; additional support for {\em TmEgg} by Lionel Mamane \item Support for {\em Proof General}: Pierre Courtieu \item {\em CoqIDE}: Benjamin Monate with contributions from Jean-Christophe FilliΓ’tre, Claude MarchΓ©, Pierre Letouzey, Julien Narboux, Hugo Herbelin, Pierre Corbineau; uses the Cameleon library by Maxence Guesdon \end{itemize} \section{Architecture} \begin{itemize} \item Functional-kernel-based architecture: Jean-Christophe FilliΓ’tre \item Extensible objects and summaries: Chet Murthy \item Hash-consing: Bruno Barras \item Error locations: Jean-Christophe FilliΓ’tre, Bruno Barras, Hugo Herbelin \item Existential variables engine: Chet Murthy with a revision by Bruno Barras and extensions by ClΓ©ment Renard and Hugo Herbelin \end{itemize} \section{Development tools} \begin{itemize} \item Makefile's: Chet Murthy, Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Lionel Mamane, Pierre Corbineau, Pierre Letouzey \item Debugging: Jean-Christophe FilliΓ’tre with contributions from Jacek Chrz\k{a}szcz, Hugo Herbelin, Bruno Barras, ... \item ML quotations: David Delahaye and Daniel de Rauglaudre \item ML tactic and vernacular extensions: Hugo Herbelin (first version by Chet Murthy) \item Test suite: collective content, initiated by Jean-Christophe FilliΓ’tre with further extensions by Hugo Herbelin, Jean-Marc Notin \end{itemize} \section{Documentation} \begin{itemize} \item Reference Manual: collective, layout by Patrick Loiseleur, Claude MarchΓ© (former User's Guide in 1991 by Gilles Dowek, Amy Felty, Hugo Herbelin, GΓ©rard Huet, Christine Paulin, Benjamin Werner; initial documentation in 1989 by Thierry Coquand, Gilles Dowek, GΓ©rard Huet, Christine Paulin), \item Basic tutorial: GΓ©rard Huet, Gilles Kahn, Christine Paulin \item Tutorial on recursive types: Eduardo Gimenez with updates by Pierre CastΓ©ran \item FAQ: Hugo Herbelin, Julien Narboux, Florent Kirchner \end{itemize} \section{Features discontinued by lack of support} \begin{itemize} \item Searching modulo isomorphism: David Delahaye \item Explanation of proofs in pseudo-natural language: Yann Coscoy \end{itemize} Errors may have been inopportunely introduced, please report them to Hugo~\verb=.=~Herbelin~\verb=@=~inria~\verb=.=~fr \end{document} rocq-9.2.0/dev/doc/archive/whodidwhat/whodidwhat-8.3update.tex000066400000000000000000000333731516144147600242130ustar00rootroot00000000000000\documentclass{article} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage{t1enc} \begin{document} \title{Who did what in the Coq archive?} \author{The Coq development team} \maketitle \centerline{(updated for Coq 8.3)} \section{The Calculus of Inductive Constructions} \begin{itemize} \item The Calculus of Constructions \begin{itemize} \item Core type-checker: GΓ©rard Huet and Thierry Coquand with optimizations by Chet Murthy, Bruno Barras \item Head reduction functions: GΓ©rard Huet, Christine Paulin, Bruno Barras \end{itemize} \item Conversion and reduction \begin{itemize} \item Lazy conversion machine: Bruno Barras \item Transparency/opacity: Bruno Barras \item Bytecode-based conversion: Benjamin GrΓ©goire \item Binary-words retroknowledge: Arnaud Spiwack \end{itemize} \item The universe hierarchy \begin{itemize} \item Floating universes: GΓ©rard Huet, with contributions from Bruno Barras \item Algebraic universes: Hugo Herbelin \end{itemize} \item Mutual inductive types and recursive definitions \begin{itemize} \item Type-checking: Christine Paulin \item Positivity condition: Christine Paulin \item Guardness condition for fixpoints: Christine Paulin; extensions by Eduardo Gimenez and Bruno Barras \item Recursively non-uniform parameters: Christine Paulin \item Sort-polymorphism of inductive types: Hugo Herbelin \end{itemize} \item Local definitions: Hugo Herbelin \item Mutual coinductive types and corecursive definitions: Eduardo Gimenez \item Module system \begin{itemize} \item Core system: Jacek Chrz\k{a}szcz \item Inlining: Claudio Sacerdoti Coen and Γ‰lie Soubiran \item Module inclusion: Γ‰lie Soubiran \item Functorial signature application: Γ‰lie Soubiran \item Transparent name space: Γ‰lie Soubiran \item Resolution of qualified names: Hugo Herbelin \item Operator for nested functor application: Γ‰lie Soubiran and Pierre Letouzey \end{itemize} \item Minimalist stand-alone type-checker (\texttt{coqchk}): Bruno Barras, with extra support for modules by Γ‰lie Soubiran \end{itemize} \section{Specification language} \begin{itemize} \item Sections: Gilles Dowek with extra contributions by GΓ©rard Huet, Chet Murthy, Hugo Herbelin \item The \texttt{Russell} specifications language, proof obligations (\texttt{Program}): Matthieu Sozeau \item Type inference: Chet Murthy, with extra contributions by Bruno Barras, Hugo Herbelin and Matthieu Sozeau \item Pattern-matching: Hugo Herbelin on top of a first version by Cristina Cornes \item Implicit arguments: Amokrane SaΓ―bi, with extensions by Hugo Herbelin and Matthieu Sozeau \item Coercions: Amokrane SaΓ―bi \item Records: Amokrane SaΓ―bi with extensions by Arnaud Spiwack and Matthieu Sozeau \item Canonical structures: Amokrane SaΓ―bi \item Type classes: Matthieu Sozeau \item Functional schemes (\texttt{Function}, \texttt{Functional Scheme}, ...): Julien Forest and Pierre Courtieu (preliminary version by Yves Bertot) \item Generation of induction schemes: Christine Paulin, Vincent Siles, Matthieu Sozeau \end{itemize} \section{Tactics} \subsection{General tactic support} \begin{itemize} \item Proof engine: Chet Murthy (first version by Thierry Coquand) \item Ltac: David Delahaye, with extensions by Hugo Herbelin, Bruno Barras, ... \item Tactic notations: Hugo Herbelin (first version by Chet Murthy) \item Main tactic unification procedure: Chet Murthy with contributions from Hugo Herbelin and Matthieu Sozeau \item Mathematical-style language (C-Zar): Pierre Corbineau \item Communication with external tools (\texttt{external}): Hugo Herbelin \end{itemize} \subsection{Predefined tactics} \begin{itemize} \item Basic tactics (\texttt{intro}, \texttt{apply}, \texttt{assumption}, \texttt{exact}): Thierry Coquand, with further collective extensions \item Reduction tactics: Christine Paulin (\texttt{simpl}), Bruno Barras (\texttt{cbv}, \texttt{lazy}), ... \item Tacticals: Thierry Coquand, Chet Murthy, Eduardo Gimenez, ... \item Induction: Christine Paulin (\texttt{elim}, \texttt{case}), Hugo Herbelin (\texttt{induction}, \texttt{destruct}, {\tt e}-variants of them), Matthieu Sozeau ({\tt dependent destruction}, {\tt dependent induction}) \item Refinement (\texttt{refine}): Jean-Christophe FilliΓ’tre \item Introduction patterns: Eduardo Gimenez with collective extensions \item Forward reasoning: Hugo Herbelin (\texttt{assert}, \texttt{apply in}), Pierre Letouzey (\texttt{specialize}, initial version by Amy Felty) \item Rewriting tactics (\texttt{rewrite}): basic version by Christine Paulin, extensions by Jean-Christophe FilliΓ’tre ({\tt subst}), Pierre Letouzey (\verb=!=, \verb=?= modifiers) and Matthieu Sozeau (\verb=*=) \item Tactics about equivalence properties (\texttt{reflexivity}, \texttt{symmetry}, \texttt{transitivity}): Christine Paulin (?), {\tt e}-variants by Hugo Herbelin, type-classes-based generalization to arbitrary appropriate relations by Matthieu Sozeau \item Equality tactics (\texttt{injection}/\texttt{discriminate}): Cristina Cornes \item Inversion tactics (\texttt{inversion}): Cristina Cornes, Chet Murthy \item Setoid rewriting: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen), contributions from Nicolas Tabareau \item Decision of equality: Eduardo Gimenez \item Basic Ltac-level tactics: Pierre Letouzey, Matthieu Sozeau, Evgeny Makarov, Hugo Herbelin \end{itemize} \subsection{General automation tactics} \begin{itemize} \item Resolution (\texttt{auto}, \texttt{trivial}): Christine Paulin with extensions from Chet Murthy, Eduardo Gimenez, Patrick Loiseleur (hint bases), Matthieu Sozeau \item Resolution with existential variables (\texttt{eauto}): Chet Murthy, Jean-Christophe FilliΓ’tre, with extensions from Matthieu Sozeau \item Automatic rewriting (\texttt{autorewrite}): David Delahaye \end{itemize} \subsection{Domain-specific decision tactics} \begin{itemize} \item Congruence closure (\texttt{cc}): Pierre Corbineau \item Decision of first-order logic (\texttt{firstorder}): Pierre Corbineau \item Simplification of polynomial fractions (\texttt{field}): Laurent ThΓ©ry and Benjamin GrΓ©goire (first version by David Delahaye and Micaela Mayero) \item Simplification of polynomial expressions (\texttt{ring}): Assia Mahboubi, Bruno Barras and Benjamin GrΓ©goire (first version by Samuel Boutin, second version by Patrick Loiseleur) \item Decision of systems of polynomial equations: LoΓ―c Pottier (\texttt{nsatz}) \item Decision of systems of linear inequations: FrΓ©dΓ©ric Besson (\texttt{psatzl}); LoΓ―c Pottier (\texttt{fourier}) \item Decision of systems of linear inequations over integers: FrΓ©dΓ©ric Besson (\texttt{lia}); Pierre CrΓ©gut (\texttt{omega} and \texttt{romega}) \item (Partial) decision of systems of polynomical inequations (\texttt{sos}, \texttt{psatz}): FrΓ©dΓ©ric Besson, with generalization over arbitrary rings by Evgeny Makarov; uses HOL-Light interface to \texttt{csdp} by John Harrisson \item Decision/simplification of intuitionistic propositional logic: David Delahaye (\texttt{tauto}, \texttt{intuition}, first version by Cesar Mu\~noz, second version by Chet Murthy), with contributions from JudicaΓ«l Courant; Pierre Corbineau (\texttt{rtauto}) \item Decision/simplification of intuition first-order logic: Pierre Corbineau (\texttt{firstorder}) \item Reification ({\tt quote}): Patrick Loiseleur, with generalization by StΓ©phane Glondu \end{itemize} \section{Extra tools} \begin{itemize} \item Program extraction: Pierre Letouzey (first implementation by Benjamin Werner, second by Jean-Christophe FilliΓ’tre) \item Export of context to external communication tools (\texttt{dp}): Nicolas Ayache and Jean-Christophe FilliΓ’tre, with contributions by Claude MarchΓ© \item Export of terms and environments to XML format: Claudio Sacerdoti Coen, with extensions from Cezary Kaliszyk \end{itemize} \section{Environment management} \begin{itemize} \item Separate compilation: initiated by Chet Murthy \item Import/Export: initiated by Chet Murthy \item Options management: Hugo Herbelin with contributions by Arnaud Spiwack \item Resetting and backtracking: Chet Murthy with contributions from Pierre Courtieu \item Searching: Hugo Herbelin and Yves Bertot with extensions by Matthias Puech \item Whelp support: Hugo Herbelin \end{itemize} \section{Parsing and printing} \begin{itemize} \item General parsing support: Chet Murthy, Bruno Barras, Daniel de Rauglaudre \item General printing support: Chet Murthy, Jean-Christophe FilliΓ’tre \item Lexing: Daniel de Rauglaudre \item Support for UTF-8: Hugo Herbelin, with contributions from Alexandre Miquel and Yann RΓ©gis-Gianas \item Numerical notations: Hugo Herbelin, Patrick Loiseleur, Micaela Mayero \item String notations: Hugo Herbelin \item New ``V8'' syntax: Bruno Barras, Hugo Herbelin with contributions by Olivier Desmettre \item Abbreviations: Chet Murthy \item Notations: Chet Murthy, Hugo Herbelin \end{itemize} \section{Libraries} \begin{itemize} \item Init: collective (initiated by Christine Paulin and GΓ©rard Huet) \item Arith: collective (initiated by Christine Paulin) \item ZArith: collective (initiated by Pierre CrΓ©gut) \item Bool: collective (initiated by Christine Paulin) \item NArith: Hugo Herbelin, Pierre Letouzey, Evgeny Makarov (out of initial contibution by Pierre CrΓ©gut) \item Lists: Pierre Letouzey, Jean-Marc Notin (initiated by Christine Paulin) \item Reals: Micaela Mayero (axiomatization and main properties), Olivier Desmettre (convergence, derivability, integrals, trigonometric functions), contributions from Russell O'Connor, Cezary Kaliszyk, Guillaume Melquiond \item Relations: Bruno Barras, Cristina Cornes with contributions from Pierre CastΓ©ran \item Wellfounded: Bruno Barras, Cristina Cornes \item FSets: Pierre Letouzey, from initial work with Jean-Christophe FilliΓ’tre, decision tactic for FSets by Aaron Bohannon \item MSets: Pierre Letouzey \item Logic: Christine Paulin, Hugo Herbelin, Bruno Barras \item Numbers: Evgeny Makarov (abstractions), Laurent ThΓ©ry and Benjamin GrΓ©goire (big numbers), Arnaud Spiwack and Pierre Letouzey (word-based arithmetic), further extensions by Pierre Letouzey \item Classes: Matthieu Sozeau \item QArith: Pierre Letouzey, with contributions from Russell O'Connor \item Setoid: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen) \item Sets: Gilles Kahn and GΓ©rard Huet \item Sorting: GΓ©rard Huet with revisions by Hugo Herbelin \item Strings: Laurent ThΓ©ry \item Program: Matthieu Sozeau \item Unicode: Claude MarchΓ© \end{itemize} \section{Commands} \begin{itemize} \item Batch compiler (\texttt{coqc}): Chet Murthy (?) \item Compilation dependency calculator (\texttt{coqdep}): Jean-Christophe FilliΓ’tre \item Statistic tool (\texttt{coqwc}): Jean-Christophe FilliΓ’tre \item Simple html presentation tool (\texttt{gallina}) (deprecated): Jean-Christophe FilliΓ’tre \item Auto-maker (\texttt{coq\_makefile}): Jean-Christophe FilliΓ’tre, with contributions from JudicaΓ«l Courant \item LaTeX presentation tool (\texttt{coq-tex}): Jean-Christophe FilliΓ’tre \item Multi-purpose presentation tool (\texttt{coqdoc}): Jean-Christophe FilliΓ’tre with extensions from Matthieu Sozeau, Jean-Marc Notin, Hugo Herbelin \item Interactive toplevel (\texttt{coqtop}): Jean-Christophe FilliΓ’tre (?) \item Custom toplevel builder (\texttt{coqmktop}): Jean-Christophe FilliΓ’tre (?) \end{itemize} \section{Graphical interfaces} \begin{itemize} \item Support for {\em PCoq}: Yves Bertot with contributions by Laurence Rideau and LoΓ―c Pottier; additional support for {\em TmEgg} by Lionel Mamane \item Support for {\em Proof General}: Pierre Courtieu \item {\em CoqIDE}: Benjamin Monate with contributions from Jean-Christophe FilliΓ’tre, Claude MarchΓ©, Pierre Letouzey, Julien Narboux, Hugo Herbelin, Pierre Corbineau, Vincent Gross; uses the Cameleon library by Maxence Guesdon \end{itemize} \section{Architecture} \begin{itemize} \item Functional-kernel-based architecture: Jean-Christophe FilliΓ’tre \item Extensible objects and summaries: Chet Murthy \item Hash-consing: Bruno Barras \item Error locations: Jean-Christophe FilliΓ’tre, Bruno Barras, Hugo Herbelin \item Existential variables engine: Chet Murthy with revisions by Bruno Barras and Arnaud Spiwack and extensions by ClΓ©ment Renard and Hugo Herbelin \end{itemize} \section{Development tools} \begin{itemize} \item Makefile's: Chet Murthy, Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Lionel Mamane, Pierre Corbineau, Pierre Letouzey \item Debugging: Jean-Christophe FilliΓ’tre with contributions from Jacek Chrz\k{a}szcz, Hugo Herbelin, Bruno Barras, ... \item ML quotations: David Delahaye and Daniel de Rauglaudre \item ML tactic and vernacular extensions: Hugo Herbelin (first version by Chet Murthy) \item Test suite: collective content, initiated by Jean-Christophe FilliΓ’tre with further extensions by Hugo Herbelin, Jean-Marc Notin \end{itemize} \section{Documentation} \begin{itemize} \item Reference Manual: collective, layout by Patrick Loiseleur, Claude MarchΓ© (former User's Guide in 1991 by Gilles Dowek, Amy Felty, Hugo Herbelin, GΓ©rard Huet, Christine Paulin, Benjamin Werner; initial documentation in 1989 by Thierry Coquand, Gilles Dowek, GΓ©rard Huet, Christine Paulin), \item Basic tutorial: GΓ©rard Huet, Gilles Kahn, Christine Paulin \item Tutorial on recursive types: Eduardo Gimenez with updates by Pierre CastΓ©ran \item FAQ: Hugo Herbelin, Julien Narboux, Florent Kirchner \end{itemize} \section{Features discontinued by lack of support} \begin{itemize} \item Searching modulo isomorphism: David Delahaye \item Explanation of proofs in pseudo-natural language: Yann Coscoy \end{itemize} Errors may have been inopportunely introduced, please report them to Hugo~\verb=.=~Herbelin~\verb=@=~inria~\verb=.=~fr \end{document} rocq-9.2.0/dev/doc/archive/whodidwhat/whodidwhat-8.4update.tex000066400000000000000000000372261516144147600242150ustar00rootroot00000000000000\documentclass{article} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage{t1enc} \usepackage{hyperref} \begin{document} \title{Who did what in the Coq archive?} \author{The Coq development team} \maketitle \centerline{(updated for Coq 8.4)} \section{The Calculus of Inductive Constructions} \begin{itemize} \item The Calculus of Constructions \begin{itemize} \item Core type-checker: GΓ©rard Huet and Thierry Coquand with optimizations by Chet Murthy, Bruno Barras \item Head reduction functions: GΓ©rard Huet, Christine Paulin, Bruno Barras \end{itemize} \item Conversion and reduction \begin{itemize} \item Lazy conversion machine: Bruno Barras \item Transparency/opacity: Bruno Barras \item Bytecode-based conversion: Benjamin GrΓ©goire \item Binary-words retroknowledge: Arnaud Spiwack \end{itemize} \item The universe hierarchy \begin{itemize} \item Floating universes: GΓ©rard Huet, with contributions from Bruno Barras and Pierre Letouzey \item Algebraic universes: Hugo Herbelin \end{itemize} \item Mutual inductive types and recursive definitions \begin{itemize} \item Type-checking: Christine Paulin \item Positivity condition: Christine Paulin \item Guardness condition for fixpoints: Christine Paulin; extensions by Eduardo Gimenez, Bruno Barras, Pierre Boutillier \item Recursively non-uniform parameters: Christine Paulin \item Sort-polymorphism of inductive types: Hugo Herbelin \end{itemize} \item Local definitions: Hugo Herbelin \item Mutual coinductive types and corecursive definitions: Eduardo Gimenez \item Module system \begin{itemize} \item Core system: Jacek Chrz\k{a}szcz \item Inlining: Claudio Sacerdoti Coen and Γ‰lie Soubiran \item Module inclusion: Γ‰lie Soubiran \item Functorial signature application: Γ‰lie Soubiran \item Transparent name space: Γ‰lie Soubiran \item Resolution of qualified names: Hugo Herbelin \item Operator for nested functor application: Γ‰lie Soubiran and Pierre Letouzey \end{itemize} \item Minimalist stand-alone type-checker (\texttt{coqchk}): Bruno Barras, with extra support for modules by Γ‰lie Soubiran and Pierre Letouzey \item Eta-conversion: Hugo Herbelin, with contributions from StΓ©phane Glondu, Benjamin GrΓ©goire \end{itemize} \section{Specification language} \begin{itemize} \item Sections: Gilles Dowek with extra contributions by GΓ©rard Huet, Chet Murthy, Hugo Herbelin \item The \texttt{Russell} specifications language, proof obligations (\texttt{Program}): Matthieu Sozeau \item Type inference: Chet Murthy, with extra contributions by Bruno Barras, Hugo Herbelin, Matthieu Sozeau, Enrico Tassi \item Pattern-matching: Hugo Herbelin on top of a first version by Cristina Cornes \item Implicit arguments: Amokrane SaΓ―bi, with extensions by Hugo Herbelin, Matthieu Sozeau, Pierre Boutillier \item Synthetic {\tt Arguments} command: Enrico Tassi \item Coercions: Amokrane SaΓ―bi \item Records: Amokrane SaΓ―bi with extensions by Arnaud Spiwack and Matthieu Sozeau \item Canonical structures: Amokrane SaΓ―bi \item Type classes: Matthieu Sozeau \item Functional schemes (\texttt{Function}, \texttt{Functional Scheme}, ...): Julien Forest and Pierre Courtieu (preliminary version by Yves Bertot) \item Generation of induction schemes: Christine Paulin, Vincent Siles, Matthieu Sozeau \end{itemize} \section{Tactics} \subsection{General tactic support} \begin{itemize} \item Proof engine: Arnaud Spiwack (first version by Thierry Coquand, second version by Chet Murthy) \item Ltac: David Delahaye, with extensions by Hugo Herbelin, Bruno Barras, ... \item Tactic notations: Hugo Herbelin (first version by Chet Murthy) \item Main tactic unification procedure: Chet Murthy with contributions from Hugo Herbelin and Matthieu Sozeau \item Mathematical-style language (C-Zar): Pierre Corbineau \item Communication with external tools (\texttt{external}): Hugo Herbelin \item Proof structuring (bullets and brackets): Arnaud Spiwack \end{itemize} \subsection{Predefined tactics} \begin{itemize} \item Basic tactics (\texttt{intro}, \texttt{apply}, \texttt{assumption}, \texttt{exact}): Thierry Coquand, with further collective extensions \item Reduction tactics: Christine Paulin (\texttt{simpl}), Bruno Barras (\texttt{cbv}, \texttt{lazy}), with contributions from Hugo Herbelin, Enrico Tassi, ... \item Tacticals: Thierry Coquand, Chet Murthy, Eduardo Gimenez, ...; new versions of {\tt info} and {\tt Show Script} by Pierre Letouzey; {\tt timeout} by Pierre Letouzey \item Induction: Christine Paulin (\texttt{elim}, \texttt{case}), Hugo Herbelin (\texttt{induction}, \texttt{destruct} \item Refinement (\texttt{refine}): Jean-Christophe FilliΓ’tre \item Introduction patterns: Eduardo Gimenez with collective extensions \item Forward reasoning: Hugo Herbelin (\texttt{assert}, \texttt{apply in}), Pierre Letouzey (\texttt{specialize}, initial version by Amy Felty) \item Rewriting tactics (\texttt{rewrite}): basic version by Christine Paulin, extensions by Jean-Christophe FilliΓ’tre and Pierre Letouzey \item Tactics about equivalence properties (\texttt{reflexivity}, \texttt{symmetry}, \texttt{transitivity}): Christine Paulin (?), \item Equality tactics (\texttt{injection}/\texttt{discriminate}): Cristina Cornes \item Inversion tactics (\texttt{inversion}): Cristina Cornes, Chet Murthy \item Setoid rewriting: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen), contributions from Nicolas Tabareau \item Decision of equality: Eduardo Gimenez \item Basic Ltac-level tactics: Pierre Letouzey, Matthieu Sozeau, Evgeny Makarov \item Tactics about existential variables: ClΓ©ment Renard, Pierre Corbineau, StΓ©phane Glondu, Arnaud Spiwack, ... \end{itemize} \subsection{General automation tactics} \begin{itemize} \item Resolution (\texttt{auto}, \texttt{trivial}): Christine Paulin with extensions from Chet Murthy, Eduardo Gimenez, Patrick Loiseleur (hint bases), Matthieu Sozeau \item Resolution with existential variables (\texttt{eauto}): Chet Murthy, Jean-Christophe FilliΓ’tre, with extensions from Matthieu Sozeau \item Automatic rewriting (\texttt{autorewrite}): David Delahaye \end{itemize} \subsection{Domain-specific decision tactics} \begin{itemize} \item Congruence closure (\texttt{cc}): Pierre Corbineau \item Decision of first-order logic (\texttt{firstorder}): Pierre Corbineau \item Simplification of polynomial fractions (\texttt{field}): Laurent ThΓ©ry and Benjamin GrΓ©goire (first version by David Delahaye and Micaela Mayero) \item Simplification of polynomial expressions (\texttt{ring}): Assia Mahboubi, Bruno Barras and Benjamin GrΓ©goire (first version by Samuel Boutin, second version by Patrick Loiseleur) \item Decision of systems of polynomial equations: LoΓ―c Pottier (\texttt{nsatz}) \item Decision of systems of linear inequations: FrΓ©dΓ©ric Besson (\texttt{psatzl}); LoΓ―c Pottier (\texttt{fourier}) \item Decision of systems of linear inequations over integers: FrΓ©dΓ©ric Besson (\texttt{lia}); Pierre CrΓ©gut (\texttt{omega} and \texttt{romega}) \item (Partial) decision of systems of polynomical inequations (\texttt{sos}, \texttt{psatz}): FrΓ©dΓ©ric Besson, with generalization over arbitrary rings by Evgeny Makarov; uses HOL-Light interface to \texttt{csdp} by John Harrisson \item Decision/simplification of intuitionistic propositional logic: David Delahaye (\texttt{tauto}, \texttt{intuition}, first version by Cesar Mu\~noz, second version by Chet Murthy), with contributions from JudicaΓ«l Courant; Pierre Corbineau (\texttt{rtauto}) \item Decision/simplification of intuition first-order logic: Pierre Corbineau (\texttt{firstorder}) \end{itemize} \section{Extra tools} \begin{itemize} \item Program extraction: Pierre Letouzey (first implementation by Benjamin Werner, second by Jean-Christophe FilliΓ’tre) \item Export of context to external communication tools (\texttt{dp}): Nicolas Ayache and Jean-Christophe FilliΓ’tre, with contributions by Claude MarchΓ© \item Export of terms and environments to XML format: Claudio Sacerdoti Coen, with extensions from Cezary Kaliszyk \end{itemize} \section{Environment management} \begin{itemize} \item Separate compilation: initiated by Chet Murthy \item Import/Export: initiated by Chet Murthy \item Options management: Hugo Herbelin with contributions by Arnaud Spiwack \item Resetting and backtracking: Chet Murthy with contributions from Pierre Courtieu \item Searching: Hugo Herbelin and Yves Bertot with extensions by Matthias Puech \item Whelp support: Hugo Herbelin \end{itemize} \section{Parsing and printing} \begin{itemize} \item General parsing support: Chet Murthy, Bruno Barras, Daniel de Rauglaudre \item General printing support: Chet Murthy, Jean-Christophe FilliΓ’tre \item Lexing: Daniel de Rauglaudre \item Support for UTF-8: Hugo Herbelin, with contributions from Alexandre Miquel and Yann RΓ©gis-Gianas \item Numerical notations: Hugo Herbelin, Patrick Loiseleur, Micaela Mayero \item String notations: Hugo Herbelin \item New ``V8'' syntax: Bruno Barras, Hugo Herbelin with contributions by Olivier Desmettre \item Abbreviations: Chet Murthy \item Notations: Chet Murthy, Hugo Herbelin \end{itemize} \section{Libraries} \begin{itemize} \item Init: collective (initiated by Christine Paulin and GΓ©rard Huet) \item Arith: collective (initiated by Christine Paulin) \item ZArith: collective (initiated by Pierre CrΓ©gut) \item Bool: collective (initiated by Christine Paulin) \item NArith: Hugo Herbelin, Pierre Letouzey, Evgeny Makarov (out of initial contibution by Pierre CrΓ©gut) \item Lists: Pierre Letouzey, Jean-Marc Notin (initiated by Christine Paulin) \item Vectors: Pierre Boutillier \item Reals: Micaela Mayero (axiomatization and main properties), Olivier Desmettre (convergence, derivability, integrals, trigonometric functions), contributions from Russell O'Connor, Cezary Kaliszyk, Guillaume Melquiond, Yves Bertot, Guillaume Allais \item Relations: Bruno Barras, Cristina Cornes with contributions from Pierre CastΓ©ran \item Wellfounded: Bruno Barras, Cristina Cornes \item FSets: Pierre Letouzey, from initial work with Jean-Christophe FilliΓ’tre, decision tactic for FSets by Aaron Bohannon, red-black trees by Andrew Appel and Pierre Letouzey \item MSets: Pierre Letouzey \item Logic: Christine Paulin, Hugo Herbelin, Bruno Barras \item Numbers: Evgeny Makarov (abstractions), Laurent ThΓ©ry and Benjamin GrΓ©goire (big numbers), Arnaud Spiwack and Pierre Letouzey (word-based arithmetic), further extensions by Pierre Letouzey; integration of Arith and ZArith to Numbers by Pierre Letouzey \item Classes: Matthieu Sozeau \item QArith: Pierre Letouzey, with contributions from Russell O'Connor \item Setoid: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen) \item Sets: Gilles Kahn and GΓ©rard Huet \item Sorting: GΓ©rard Huet with revisions by Hugo Herbelin \item Strings: Laurent ThΓ©ry \item Program: Matthieu Sozeau \item Unicode: Claude MarchΓ© \end{itemize} \section{Commands} \begin{itemize} \item Batch compiler (\texttt{coqc}): Chet Murthy (?) \item Compilation dependency calculator (\texttt{coqdep}): Jean-Christophe FilliΓ’tre \item Statistic tool (\texttt{coqwc}): Jean-Christophe FilliΓ’tre \item Simple html presentation tool (\texttt{gallina}) (deprecated): Jean-Christophe FilliΓ’tre \item Auto-maker (\texttt{coq\_makefile}): Jean-Christophe FilliΓ’tre, with contributions from JudicaΓ«l Courant, updated by Pierre Boutillier \item LaTeX presentation tool (\texttt{coq-tex}): Jean-Christophe FilliΓ’tre \item Multi-purpose presentation tool (\texttt{coqdoc}): Jean-Christophe FilliΓ’tre with extensions from Matthieu Sozeau, Jean-Marc Notin, Hugo Herbelin and contributions from Adam Chlipala \item Interactive toplevel (\texttt{coqtop}): Jean-Christophe FilliΓ’tre (?) \item Custom toplevel builder (\texttt{coqmktop}): Jean-Christophe FilliΓ’tre (?) \end{itemize} \section{Graphical interfaces} \begin{itemize} \item Support for {\em PCoq}: Yves Bertot with contributions by Laurence Rideau and LoΓ―c Pottier; additional support for {\em TmEgg} by Lionel Mamane \item Support for {\em Proof General}: Pierre Courtieu with contributions from Arnaud Spiwack \item {\em CoqIDE}: Benjamin Monate with contributions from Jean-Christophe FilliΓ’tre, Claude MarchΓ©, Pierre Letouzey, Julien Narboux, Hugo Herbelin, Pierre Corbineau, Pierre Boutillier, Pierre-Marie PΓ©drot; processus-based communication protocol by Vincent Gross with contributions from Pierre Letouzey, Pierre Boutillier, Pierre-Marie PΓ©drot; backtracking revised by Pierre Letouzey; uses the Cameleon library by Maxence Guesdon; \end{itemize} \section{Architecture} \begin{itemize} \item Functional-kernel-based architecture: Jean-Christophe FilliΓ’tre \item Extensible objects and summaries: Chet Murthy \item Hash-consing: Bruno Barras \item Error locations: Jean-Christophe FilliΓ’tre, Bruno Barras, Hugo Herbelin, with contributions from Arnaud Spiwack \item Existential variables engine: Chet Murthy with revisions by Bruno Barras and Arnaud Spiwack and extensions by ClΓ©ment Renard and Hugo Herbelin \end{itemize} \section{Development tools} \begin{itemize} \item Makefile's: Chet Murthy, Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Lionel Mamane, Pierre Corbineau, Pierre Letouzey with contributions from StΓ©phane Glondu, Hugo Herbelin, ... \item Debugging: Jean-Christophe FilliΓ’tre with contributions from Jacek Chrz\k{a}szcz, Hugo Herbelin, Bruno Barras, ... \item ML quotations: David Delahaye and Daniel de Rauglaudre \item ML tactic and vernacular extensions: Hugo Herbelin (first version by Chet Murthy) \item Test suite: collective content, initiated by Jean-Christophe FilliΓ’tre with further extensions by Hugo Herbelin, Jean-Marc Notin \end{itemize} \section{Maintenance and system engineering} \begin{itemize} %\item General maintenance in version 8.0: Bruno Barras, Hugo Herbelin %\item General maintenance in version 8.1: Bruno Barras, Hugo Herbelin, Jean-Marc Notin %\item General maintenance in version 8.2: Hugo Herbelin, Pierre Letouzey, Jean-Marc Notin, %\item General maintenance in version 8.3: Hugo Herbelin, Pierre % Letouzey \item General maintenance in version 8.4: Pierre Letouzey, Hugo Herbelin, Pierre Boutillier, Matthieu Sozeau, StΓ©phane Glondu with contributions from Guillaume Melquiond, Julien Narboux and Pierre-Marie PΓ©drot \item Team coordination: GΓ©rard Huet, Christine Paulin, Hugo Herbelin, with various other contributions \item Packaging tools: Henri Laulhere, David Delahaye, Julien Narboux, Pierre Letouzey, Enrico Tassi (Windows); Damien Doligez, Hugo Herbelin, Pierre Boutillier (MacOS); Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Hugo Herbelin, StΓ©phane Glondu (Linux) \end{itemize} \section{Documentation} \begin{itemize} \item Reference Manual: collective, layout by Patrick Loiseleur, Claude MarchΓ© (former User's Guide in 1991 by Gilles Dowek, Amy Felty, Hugo Herbelin, GΓ©rard Huet, Christine Paulin, Benjamin Werner; initial documentation in 1989 by Thierry Coquand, Gilles Dowek, GΓ©rard Huet, Christine Paulin), \item Basic tutorial: GΓ©rard Huet, Gilles Kahn, Christine Paulin \item Tutorial on recursive types: Eduardo Gimenez with updates by Pierre CastΓ©ran \item FAQ: Hugo Herbelin, Julien Narboux, Florent Kirchner \end{itemize} \section{Features discontinued by lack of support} \begin{itemize} \item Searching modulo isomorphism: David Delahaye \item Explanation of proofs in pseudo-natural language: Yann Coscoy \item Dp: Jean-Christophe FilliΓ’tre, Nicolas Ayache with contributions from Claude MarchΓ© (now integrated to \href{http://why3.lri.fr/}{Why3}) \end{itemize} For oversights or accidental errors, please report to Hugo~\verb=.=~Herbelin~\verb=@=~inria~\verb=.=~fr \end{document} rocq-9.2.0/dev/doc/archive/whodidwhat/whodidwhat-8.5update.tex000066400000000000000000000376661516144147600242260ustar00rootroot00000000000000\documentclass{article} \usepackage{fullpage} \usepackage[utf8]{inputenc} \usepackage{t1enc} \begin{document} \title{Who did what in the Coq archive?} \author{The Coq development team} \maketitle \centerline{(updated for Coq 8.5)} \section{The Calculus of Inductive Constructions} \begin{itemize} \item The Calculus of Constructions \begin{itemize} \item Core type-checker: GΓ©rard Huet and Thierry Coquand with optimizations by Chet Murthy, Bruno Barras \item Head reduction functions: GΓ©rard Huet, Christine Paulin, Bruno Barras \end{itemize} \item Conversion and reduction \begin{itemize} \item Lazy conversion machine: Bruno Barras \item Transparency/opacity: Bruno Barras \item Bytecode-based conversion: Benjamin GrΓ©goire \item Binary-words retroknowledge: Arnaud Spiwack \item Native code based conversion: Maxime DΓ©nΓ¨s, Benjamin GrΓ©goire \end{itemize} \item The universe hierarchy \begin{itemize} \item Floating universes: GΓ©rard Huet, with contributions from Bruno Barras \item Algebraic universes: Hugo Herbelin \end{itemize} \item Mutual inductive types and recursive definitions \begin{itemize} \item Type-checking: Christine Paulin \item Positivity condition: Christine Paulin \item Guardness condition for fixpoints: Christine Paulin; extensions by Eduardo Gimenez, Bruno Barras, Pierre Boutillier; fixes by Bruno Barras, Maxime DΓ©nΓ¨s \item Recursively non-uniform parameters: Christine Paulin \item Sort-polymorphism of inductive types: Hugo Herbelin \end{itemize} \item Local definitions: Hugo Herbelin \item Mutual coinductive types and corecursive definitions: Eduardo Gimenez \item Module system \begin{itemize} \item Core system: Jacek Chrz\k{a}szcz \item Inlining: Claudio Sacerdoti Coen and Γ‰lie Soubiran \item Module inclusion: Γ‰lie Soubiran \item Functorial signature application: Γ‰lie Soubiran \item Transparent name space: Γ‰lie Soubiran \item Resolution of qualified names: Hugo Herbelin \item Operator for nested functor application: Γ‰lie Soubiran and Pierre Letouzey \end{itemize} \item Minimalist stand-alone type-checker (\texttt{coqchk}): Bruno Barras, with extra support for modules by Γ‰lie Soubiran and Pierre Letouzey \item Eta-conversion: Hugo Herbelin, with contributions from StΓ©phane Glondu, Benjamin GrΓ©goire \end{itemize} \section{Specification language} \begin{itemize} \item Sections: Gilles Dowek with extra contributions by GΓ©rard Huet, Chet Murthy, Hugo Herbelin \item The \texttt{Russell} specifications language, proof obligations (\texttt{Program}): Matthieu Sozeau \item Type inference: Chet Murthy, with extra contributions by Bruno Barras, Hugo Herbelin, Matthieu Sozeau, Enrico Tassi \item Pattern-matching: Hugo Herbelin on top of a first version by Cristina Cornes, contributions by Arnaud Spiwack \item Implicit arguments: Amokrane SaΓ―bi, with extensions by Hugo Herbelin, Matthieu Sozeau, Pierre Boutillier \item Synthetic {\tt Arguments} command: Enrico Tassi \item Coercions: Amokrane SaΓ―bi \item Records \begin{itemize} \item Core implementation: Amokrane SaΓ―bi with extensions by Matthieu Sozeau \item Extension to inductive and co-inductive records: Arnaud Spiwack \item Non-recursive variants: Arnaud Spiwack \end{itemize} \item Canonical structures: Amokrane SaΓ―bi \item Type classes: Matthieu Sozeau \item Function (\texttt{Function}, \texttt{functional induction}...): Julien Forest (preliminary versions by Pierre Courtieu (\texttt{Functional Schemes}) and Yves Bertot (\texttt{Recursive Definition})) \item Generation of induction schemes: Christine Paulin, Vincent Siles, Matthieu Sozeau \end{itemize} \section{Tactics} \subsection{General tactic support} \begin{itemize} \item Proof engine: Arnaud Spiwack (first version by Thierry Coquand, second version by Chet Murthy) \item Ltac: David Delahaye, with extensions by Hugo Herbelin, Bruno Barras, ... Evolution to the new proof engine Arnaud Spiwack, Pierre-Marie P\'edrot \item Tactic notations: Hugo Herbelin (first version by Chet Murthy) \item Main tactic unification procedure: Chet Murthy with contributions from Hugo Herbelin and Matthieu Sozeau \item Mathematical-style language (C-Zar): Pierre Corbineau \item Communication with external tools (\texttt{external}): Hugo Herbelin \item Proof structuring (bullets and brackets): Arnaud Spiwack \end{itemize} \subsection{Predefined tactics} \begin{itemize} \item Basic refinement tactic (\texttt{refine}): Arnaud Spiwack (previous non-basic version by Jean-Christophe FilliΓ’tre) \item Core tactics (\texttt{intro}, \texttt{apply}, \texttt{assumption}, \texttt{exact}): Thierry Coquand, with further collective extensions \item Reduction tactics: Christine Paulin (\texttt{simpl}), Bruno Barras (\texttt{cbv}, \texttt{lazy}), Pierre Boutillier (\texttt{cbn}) with contributions from Hugo Herbelin, Enrico Tassi, ... \item Tacticals: Thierry Coquand, Chet Murthy, Eduardo Gimenez, ...; new versions of {\tt info} and {\tt Show Script} by Pierre Letouzey; {\tt timeout} by Pierre Letouzey; backtracking-related tacticals by Arnaud Spiwack \item Generic tactic traces ({\tt Info}) by Arnaud Spiwack (based on the former {\tt info} tactical) \item Induction: Christine Paulin (\texttt{elim}, \texttt{case}), Hugo Herbelin (\texttt{induction}, \texttt{destruct} \item Introduction patterns: Eduardo Gimenez with collective extensions \item Forward reasoning: Hugo Herbelin (\texttt{assert}, \texttt{enough}, \texttt{apply in}), Pierre Letouzey (\texttt{specialize}, initial version by Amy Felty) \item Rewriting tactics (\texttt{rewrite}): basic version by Christine Paulin, extensions by Jean-Christophe FilliΓ’tre and Pierre Letouzey \item Setoid rewriting: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen), contributions from Nicolas Tabareau \item Tactics about equivalence properties (\texttt{reflexivity}, \texttt{symmetry}, \texttt{transitivity}): Christine Paulin (?), \item Equality tactics (\texttt{injection}/\texttt{discriminate}): Cristina Cornes, extensions by Hugo Herbelin \item Inversion tactics (\texttt{inversion}): Cristina Cornes, Chet Murthy \item Decision of equality: Eduardo Gimenez \item Basic Ltac-level tactics: Pierre Letouzey, Matthieu Sozeau, Evgeny Makarov \item Tactics about existential variables: ClΓ©ment Renard, Pierre Corbineau, StΓ©phane Glondu, Arnaud Spiwack, ... \end{itemize} \subsection{General automation tactics} \begin{itemize} \item Resolution (\texttt{auto}, \texttt{trivial}): Christine Paulin with extensions from Chet Murthy, Eduardo Gimenez, Patrick Loiseleur (hint bases), Matthieu Sozeau \item Resolution with existential variables (\texttt{eauto}): Chet Murthy, Jean-Christophe FilliΓ’tre, with extensions from Matthieu Sozeau \item Automatic rewriting (\texttt{autorewrite}): David Delahaye \end{itemize} \subsection{Domain-specific decision tactics} \begin{itemize} \item Congruence closure (\texttt{cc}): Pierre Corbineau \item Decision of first-order logic (\texttt{firstorder}): Pierre Corbineau \item Simplification of polynomial fractions (\texttt{field}): Laurent ThΓ©ry and Benjamin GrΓ©goire (first version by David Delahaye and Micaela Mayero) \item Simplification of polynomial expressions (\texttt{ring}): Assia Mahboubi, Bruno Barras and Benjamin GrΓ©goire (first version by Samuel Boutin, second version by Patrick Loiseleur) \item Decision of systems of polynomial equations: LoΓ―c Pottier (\texttt{nsatz}) \item Decision of systems of linear inequations: FrΓ©dΓ©ric Besson (\texttt{psatzl}); LoΓ―c Pottier (\texttt{fourier}) \item Decision of systems of linear inequations over integers: FrΓ©dΓ©ric Besson (\texttt{lia}); Pierre CrΓ©gut (\texttt{omega} and \texttt{romega}) \item (Partial) decision of systems of polynomical inequations (\texttt{sos}, \texttt{psatz}): FrΓ©dΓ©ric Besson, with generalization over arbitrary rings by Evgeny Makarov; uses HOL-Light interface to \texttt{csdp} by John Harrisson \item Decision/simplification of intuitionistic propositional logic: David Delahaye (\texttt{tauto}, \texttt{intuition}, first version by Cesar Mu\~noz, second version by Chet Murthy), with contributions from JudicaΓ«l Courant; Pierre Corbineau (\texttt{rtauto}) \item Decision/simplification of intuition first-order logic: Pierre Corbineau (\texttt{firstorder}) \end{itemize} \section{Extra tools} \begin{itemize} \item Program extraction: Pierre Letouzey (first implementation by Benjamin Werner, second by Jean-Christophe FilliΓ’tre) \end{itemize} \section{Environment management} \begin{itemize} \item Separate compilation: initiated by Chet Murthy \item Import/Export: initiated by Chet Murthy \item Options management: Hugo Herbelin with contributions by Arnaud Spiwack \item Resetting and backtracking: Chet Murthy with contributions from Pierre Courtieu \item Searching: Hugo Herbelin and Yves Bertot with extensions by Matthias Puech \item Whelp support: Hugo Herbelin \end{itemize} \section{Parsing and printing} \begin{itemize} \item General parsing support: Chet Murthy, Bruno Barras, Daniel de Rauglaudre \item General printing support: Chet Murthy, Jean-Christophe FilliΓ’tre \item Lexing: Daniel de Rauglaudre \item Support for UTF-8: Hugo Herbelin, with contributions from Alexandre Miquel and Yann RΓ©gis-Gianas \item Numerical notations: Hugo Herbelin, Patrick Loiseleur, Micaela Mayero \item String notations: Hugo Herbelin \item New ``V8'' syntax: Bruno Barras, Hugo Herbelin with contributions by Olivier Desmettre \item Abbreviations: Chet Murthy \item Notations: Chet Murthy, Hugo Herbelin \end{itemize} \section{Libraries} \begin{itemize} \item Init: collective (initiated by Christine Paulin and GΓ©rard Huet) \item Arith: collective (initiated by Christine Paulin) \item ZArith: collective (initiated by Pierre CrΓ©gut) \item Bool: collective (initiated by Christine Paulin) \item NArith: Hugo Herbelin, Pierre Letouzey, Evgeny Makarov (out of initial contibution by Pierre CrΓ©gut) \item Lists: Pierre Letouzey, Jean-Marc Notin (initiated by Christine Paulin) \item Vectors: Pierre Boutillier \item Reals: Micaela Mayero (axiomatization and main properties), Olivier Desmettre (convergence, derivability, integrals, trigonometric functions), contributions from Russell O'Connor, Cezary Kaliszyk, Guillaume Melquiond, Yves Bertot, Guillaume Allais \item Relations: Bruno Barras, Cristina Cornes with contributions from Pierre CastΓ©ran \item Wellfounded: Bruno Barras, Cristina Cornes \item FSets: Pierre Letouzey, from initial work with Jean-Christophe FilliΓ’tre, decision tactic for FSets by Aaron Bohannon, red-black trees by Andrew Appel and Pierre Letouzey \item MSets: Pierre Letouzey \item Logic: Christine Paulin, Hugo Herbelin, Bruno Barras, contributions by Arnaud Spiwack \item Numbers: Evgeny Makarov (abstractions), Laurent ThΓ©ry and Benjamin GrΓ©goire (big numbers), Arnaud Spiwack and Pierre Letouzey (word-based arithmetic), further extensions by Pierre Letouzey; integration of Arith and ZArith to Numbers by Pierre Letouzey \item Classes: Matthieu Sozeau \item QArith: Pierre Letouzey, with contributions from Russell O'Connor \item Setoid: Matthieu Sozeau (first version by ClΓ©ment Renard, second version by Claudio Sacerdoti Coen) \item Sets: Gilles Kahn and GΓ©rard Huet \item Sorting: GΓ©rard Huet with revisions by Hugo Herbelin \item Strings: Laurent ThΓ©ry \item Program: Matthieu Sozeau \item Unicode: Claude MarchΓ© \end{itemize} \section{Commands} \begin{itemize} \item Batch compiler (\texttt{coqc}): Chet Murthy (?) \item Compilation dependency calculator (\texttt{coqdep}): Jean-Christophe FilliΓ’tre \item Statistic tool (\texttt{coqwc}): Jean-Christophe FilliΓ’tre \item Simple html presentation tool (\texttt{gallina}) (deprecated): Jean-Christophe FilliΓ’tre \item Auto-maker (\texttt{coq\_makefile}): Jean-Christophe FilliΓ’tre, with contributions from JudicaΓ«l Courant, updated by Pierre Boutillier \item LaTeX presentation tool (\texttt{coq-tex}): Jean-Christophe FilliΓ’tre \item Multi-purpose presentation tool (\texttt{coqdoc}): Jean-Christophe FilliΓ’tre with extensions from Matthieu Sozeau, Jean-Marc Notin, Hugo Herbelin and contributions from Adam Chlipala \item Interactive toplevel (\texttt{coqtop}): Jean-Christophe FilliΓ’tre (?) \item Custom toplevel builder (\texttt{coqmktop}): Jean-Christophe FilliΓ’tre (?) \end{itemize} \section{Graphical interfaces} \begin{itemize} \item Support for {\em Proof General}: Pierre Courtieu with contributions from Arnaud Spiwack \item {\em CoqIDE}: Benjamin Monate with contributions from Jean-Christophe FilliΓ’tre, Claude MarchΓ©, Pierre Letouzey, Julien Narboux, Hugo Herbelin, Pierre Corbineau, Pierre Boutillier, Pierre-Marie PΓ©drot; processus-based communication protocol by Vincent Gross with contributions from Pierre Letouzey, Pierre Boutillier, Pierre-Marie PΓ©drot; backtracking revised by Pierre Letouzey; uses the Cameleon library by Maxence Guesdon; \end{itemize} \section{Architecture} \begin{itemize} \item Functional-kernel-based architecture: Jean-Christophe FilliΓ’tre \item Extensible objects and summaries: Chet Murthy \item Hash-consing: Bruno Barras \item Error locations: Jean-Christophe FilliΓ’tre, Bruno Barras, Hugo Herbelin, with contributions from Arnaud Spiwack \item Existential variables engine: Chet Murthy with revisions by Bruno Barras and Arnaud Spiwack and extensions by ClΓ©ment Renard and Hugo Herbelin \end{itemize} \section{Development tools} \begin{itemize} \item Makefile's: Chet Murthy, Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Lionel Mamane, Pierre Corbineau, Pierre Letouzey with contributions from StΓ©phane Glondu, Hugo Herbelin, ... \item Debugging: Jean-Christophe FilliΓ’tre with contributions from Jacek Chrz\k{a}szcz, Hugo Herbelin, Bruno Barras, ... \item ML quotations: David Delahaye and Daniel de Rauglaudre \item ML tactic and vernacular extensions: Hugo Herbelin (first version by Chet Murthy) \item Test suite: collective content, initiated by Jean-Christophe FilliΓ’tre with further extensions by Hugo Herbelin, Jean-Marc Notin \end{itemize} \section{Maintenance and system engineering} \begin{itemize} \item General bug support: GΓ©rard Huet, Christine Paulin, Chet Murthy, Jean-Christophe FilliΓ’tre, Hugo Herbelin, Bruno Barras, Pierre Letouzey with contributions at some time from Benjamin Werner, Jean-Marc Notin, Pierre Boutillier, ... \item Team coordination: GΓ©rard Huet, Christine Paulin, Hugo Herbelin, with various other contributions \item Packaging tools: Henri Laulhere, David Delahaye, Julien Narboux, Pierre Letouzey, Enrico Tassi (Windows); Damien Doligez, Hugo Herbelin, Pierre Boutillier (MacOS); Jean-Christophe FilliΓ’tre, JudicaΓ«l Courant, Hugo Herbelin, StΓ©phane Glondu (Linux) \end{itemize} \section{Documentation} \begin{itemize} \item Reference Manual: collective, layout by Patrick Loiseleur, Claude MarchΓ© (former User's Guide in 1991 by Gilles Dowek, Amy Felty, Hugo Herbelin, GΓ©rard Huet, Christine Paulin, Benjamin Werner; initial documentation in 1989 by Thierry Coquand, Gilles Dowek, GΓ©rard Huet, Christine Paulin), \item Basic tutorial: GΓ©rard Huet, Gilles Kahn, Christine Paulin \item Tutorial on recursive types: Eduardo Gimenez with updates by Pierre CastΓ©ran \item FAQ: Hugo Herbelin, Julien Narboux, Florent Kirchner \end{itemize} \section{Features discontinued by lack of support} \begin{itemize} \item Searching modulo isomorphism: David Delahaye \item Explanation of proofs in pseudo-natural language: Yann Coscoy \item Export of context to external communication tools (\texttt{dp}): Nicolas Ayache and Jean-Christophe FilliΓ’tre, with contributions by Claude MarchΓ© \item Support for {\em PCoq}: Yves Bertot with contributions by Laurence Rideau and LoΓ―c Pottier; additional support for {\em TmEgg} by Lionel Mamane \item Export of terms and environments to XML format: Claudio Sacerdoti Coen, with extensions from Cezary Kaliszyk \end{itemize} For probable oversights or accidental errors, please report to Hugo~\verb=.=~Herbelin~\verb=@=~inria~\verb=.=~fr \end{document} rocq-9.2.0/dev/doc/build-system.dune.md000066400000000000000000000315231516144147600177230ustar00rootroot00000000000000This file documents what a Rocq developer needs to know about the Dune-based build system. About Dune ========== Rocq uses the [Dune](https://github.com/ocaml/dune) build system. ## Quick Start Usually, using the latest version of Dune is recommended, see the first line of the `dune-project` file for the minimum required version. It is strongly recommended that you use the helper targets available in `Makefile`, `make` will display help. Note that dune will call configure for you if needed, so no need to call `./configure` in the regular development workflow, unless you want to tweak options. 2 common operations are: - `make check` : build all ml targets as fast as possible - `make world` : build a complete Rocq distribution For more targeted builds, you can also call `dune` directly. First, call `make dunestrap` to generate necessary build files (the `make` targets above do it automatically). Then you can use: - `dune exec -- rocq `: build and launch rocq (does not build the worker and Prelude.vo). with arguments of your choice - `dune build $target`: where `$target` can refer to the build directory or the source directory [but will be placed under `_build`] You need to run `make dunestrap` again if the dependencies between the core library .v files have changed. `dune build @install` will build all the public Rocq artifacts; `dune build` builds the `@default` alias, defined in the top level `dune` file. Dune puts build artifacts in a separate directory `_build/$context`; usual `context` is `default`; dune also produces an "install" layout under `_build/install/$context/`. Depending on whether you want refer to the source layout or to the install layout, you may refer to targets in one or the other directory. It will also generate an `.install` file so files can be properly installed by package managers. Dune doesn't allow leftovers of object files it may generate in-tree [as to avoid conflicts], so please be sure your tree is clean from objects files generated by the make-based system or from manual compilation. Contrary to other systems, Dune doesn't use a global `Makefile` but local build files named `dune` which are later composed to form a global build, for example `plugins/ltac/dune` or `kernel/dune`. As a developer, Dune should take care of all OCaml-related build tasks including library management, `merlin` setup, linking order, etc... You should not have to modify `dune` files in regular workflow unless you are adding a new binary, library, or plugin, or want to tweak some low-level option. ## The bootstrap process / rule generation Dune is able to build all the OCaml parts of Rocq in a pretty standard way, using its built-in rule generation for OCaml. Public tools written in OCaml are distributed in the `rocq-runtime` package. The set of public `.v` files present in this repository, usually referred as the "Rocq prelude" are distributed in the `rocq-core` package. As of June 2022, Dune has a set of built-in rules for `.v` files which is capable of building Rocq's core library. However, in order to have a bit more control, we generate ourselves a set of custom rules using the `tools/dune_rule_gen` binary, which are then stored in the `theories/dune` file. This allows us to have a finer control over the build rules without having to bump the Dune version. The generation of the `theories/dune` and `user-contrib/*/dune` files is known as "bootstrap". The rule generation code in `tools/dune_rule_gen` is mostly derived from Dune's built-in rules, and it works in an straightforward way: it will scan a directory with `.v` files in it, and output the corresponding build rule. The script will look at some configuration values such as whether native is enabled or not and adapt rule generation accordingly. In the case of native, the script supports two modes, `coqc -native-compiler on` and `coqnative`. The default is the first, as currently `coqnative` incurs a 33% build time overhead on a powerful 16-core machine. There are several modes for the rule generation script to work, depending on the parameter passed. As of today, it support `-async`. `-async` will pass `-async-proofs on` to `coqc`. ## Per-User Custom Settings Dune will read the file `~/.config/dune/config`; see `man dune-config`. Among others, you can set in this file the custom number of build threads `(jobs N)` and display options `(display _mode_)`. ## Running binaries (rocq compile, rocq top) You should generally run `make world` before running rocq so that the corelib is built and placed in `_build/install`. If building the corelib produces an error outside the prelude, `make world` will still result in a usable state (of course you won't be able to Require any failed files). For errors inside the prelude, invoke rocq with `-boot -noinit -R _build/default/theories/Corelib Corelib`. For instance if you get an error in Datatypes, ~~~bash dune exec -- rocq compile -boot -noinit -R _build/default/theories/Corelib Corelib _build/default/theories/Corelib/Init/Datatypes.v ~~~ should reproduce it. ~~~bash dune exec -- rocq compile -boot -noinit -R _build/default/theories/Corelib Corelib -R theories/Corelib Corelib theories/Corelib/Init/Datatypes.v ~~~ should be equivalent. Giving `-boot -R _build/default/theories/Corelib Corelib` to an IDE while visiting a file in `theories/Corelib/Init` should combine with `theories/Corelib/Init/_CoqProject` to produce the above result, eg ~~~bash dune exec -- rocqide -boot -R _build/default/theories/Corelib Corelib theories/Corelib/Init/Datatypes.v ~~~ should work to reproduce the error interactively. ## Building custom toplevels You can build custom toplevels by tweaking the `toplevel/dune` files, for example, to add plugins to be linked statically using the `(libraries ...)` field. Note that Rocq relies on a hidden Dune hack, which will add `-linkall` to binaries if they depend on the `findlib.dynload` library. As of today, `rocq-runtime.vernac` uses `findlib.dynload`, so if your toplevel hooks at the `rocq-runtime.vernac` or above level, you should be OK, otherwise add `-linkall` to Dune's `(link_flags ...)` field for your binary. ## Targets The default dune target is `dune build` (or `dune build @install`), which will scan all sources in the Rocq tree and then build the whole project, creating an "install" overlay in `_build/install/default`. You can build some other target by doing `dune build $TARGET`, where `$TARGET` can be a `.cmxa`, a binary, a file that Dune considers a target, an alias, etc... In order to build a single package, you can do `dune build $PACKAGE.install`. A very useful target is `dune build @check`, that will compile all the ml files in quick mode. Dune also provides targets for documentation, testing, and release builds, please see below. ## Testing and documentation targets There are two ways to run the test suite using Dune: - After building Rocq with `make world`, you can run the test-suite in place, generating output files in the source tree by running `make -C test-suite` from the top directory of the source tree (equivalent to running `make test-suite` from the `test-suite` directory). This permits incremental usage since output files will be preserved. - You can also run the test suite in a hygienic way using `make test-suite` or `dune runtest`. This is convenient for full runs from scratch, for instance in CI. Since `dune` still invokes the test-suite makefile, the environment variable `NJOBS` is used to set the `-j` option that is passed to make (for example, with the command `NJOBS=8 dune runtest`). This use of `NJOBS` will be removed when the test suite is fully ported to Dune. There is preliminary support to build the API documentation and reference manual in HTML format, use `dune build {@doc,@refman-html}` to generate them. So far these targets will build the documentation artifacts, however no install rules are generated yet. ## Developer shell You can create a developer shell with `dune utop $library`, where `$library` can be any directory in the current workspace. For example, `dune utop engine` or `dune utop plugins/ltac` will launch `utop` with the right libraries already loaded. ## ocamldebug You can use [ocamldebug](https://ocaml.org/learn/tutorials/debug.html#The-OCaml-debugger) with Dune; after a build, do: ``` dune exec -- dev/dune-dbg coqc foo.v (ocd) source db ``` to start `coqc.byte foo.v`, other targets are `{checker,rocqide,coqtop}`: ``` dune exec -- dev/dune-dbg checker foo.vo (ocd) source db ``` More info in the [wiki](https://github.com/rocq-prover/rocq/wiki/OCamldebug). Unfortunately, dependency handling is not fully refined / automated, you may find the occasional hiccup due to libraries being renamed, etc... Please report any issue. For running in emacs, use `coqdev-ocamldebug` from `coqdev.el`. ### Debugging hints - To debug a failure/error/anomaly, add a breakpoint in `Vernacinterp.interp_gen` (in `vernac/vernacinterp.ml`) at the with clause of the "try ... with ..." block, then go "back" a few steps to find where the failure/error/anomaly has been raised - Alternatively, for an error or an anomaly, add breakpoints where it was raised (eg in `user_err` or `anomaly` in `lib/cErrors.ml`, or the functions in `pretyping/pretype_errors.ml`, or other raises depending on the error) - If there is a linking error (eg from "source db"), do a "dune build rocq-runtime.install" and try again. ## Dropping from coqtop: The following should work: ``` dune exec -- rocq repl-with-drop > Drop. ``` ## Compositionality, developer and release modes. By default [in "developer mode"], Dune will compose all the packages present in the tree and perform a global build. That means that for example you could drop the `ltac2` folder under `plugins` and get a build using `ltac2`, that will use the current Rocq version. This is very useful to develop plugins and Rocq libraries as your plugin will correctly track dependencies and rebuild incrementally as needed. However, it is not always desirable to go this way. For example, the current Rocq source tree contains two packages [Rocq and RocqIDE], and in the OPAM RocqIDE package we don't want to build RocqIDE against the local copy of Rocq. For this purpose, Dune supports the `-p` option, so `dune build -p rocqide` will build RocqIDE against the system-installed version of Rocq libs, and use a "release" profile that for example enables stronger compiler optimizations. ## OPAM file generation `.opam` files will be automatically generated by Dune from the package descriptions in the `dune-project` file; see Dune's manual for more details. For now we have disabled this due to some bugs. ## Stanzas `dune` files contain the so-called "stanzas", that may declare: - libraries, - executables, - documentation, arbitrary blobs. The concrete options for each stanza can be seen in the Dune manual, but usually the default setup will work well with the current Rocq sources. Note that declaring a library or an executable won't make it installed by default, for that, you need to provide a "public name". ## Workspaces and Profiles Dune provides support for tree workspaces so the developer can set global options --- such as flags --- on all packages, or build Rocq with different OPAM switches simultaneously [for example to test compatibility]; for more information, please refer to the Dune manual. ## Inlining reports The `ireport` profile will produce standard OCaml [inlining reports](https://caml.inria.fr/pub/docs/manual-ocaml/flambda.html#sec488). These are to be found under `_build/default/$lib/$lib.objs/$module.$round.inlining.org` and are in Emacs `org-mode` format. Note that due to https://github.com/ocaml/dune/issues/1401 , we must perform a full rebuild each time as otherwise Dune will remove the files. We hope to solve this in the future. ## Planned and Advanced features Dune supports or will support extra functionality that may result very useful to Rocq, some examples are: - Cross-compilation. - Automatic Generation of OPAM files. - Multi-directory libraries. ## FAQ - I get "Error: Dynlink error: Interface mismatch": You are likely running a partial build which doesn't include implicitly loaded plugins / vo files. See the "Running binaries [coqtop / rocqide]" section above as to how to correctly call Rocq's binaries. ## Dune cheat sheet - `dune build` build all targets in the current workspace - `dune build @check` build all ML targets as fast as possible, setup merlin - `dune utop $dir` open a shell for libraries in `$dir` - `dune exec -- $file` build and execute binary `$file`, can be in path or be an specific name - `dune build _build/$context/$foo` build target `$foo$` in `$context`, with build dir layout - `dune build _build/install/$context/foo` build target `$foo$` in `$context`, with install dir layout ### packaging: - `dune subst` generate metadata for a package to be installed / distributed, necessary for opam - `dune build -p $pkg` build a package in release mode rocq-9.2.0/dev/doc/case-repr.md000066400000000000000000000107001516144147600162230ustar00rootroot00000000000000## Case representation Starting from Coq 8.14, the term representation of pattern-matching uses a so-called *compact form*. Compared to the previous representation, the major difference is that all type and term annotations on lambda and let abstractions that were present in branches and return clause of pattern-matchings were removed. In order to keep the ability to construct the old expanded form out of the new compact form, the case node also makes explicit data that was stealthily present in the expanded return clause, namely universe instances and parameters of the inductive type being eliminated. ### ML Representation The case node now looks like ``` Case of case_info * Instance.t * (* universe instances of the inductive *) constr array * (* parameters of the inductive *) case_return * (* erased return clause *) case_invert * (* SProp inversion data *) constr * (* scrutinee *) case_branch array (* erased branches *) ``` where ``` type case_branch = Name.t binder_annot array * constr type case_return = Name.t binder_annot array * types ``` For comparison, pre-8.14 case nodes were defined as follows. ``` Case of case_info * constr * (* annotated return clause *) case_invert * (* SProp inversion data *) constr * (* scrutinee *) constr array (* annotated branches *) ``` ### Typing Rules and Invariants Disregarding the `case_info` cache and the SProp inversion, the typing rules for the case node can be given as follows. Provided - Ξ“ ⊒ c : Ind@{u} pms Indices - Inductive Ind@{i} Ξ” : forall Θ, Type := cα΅’ : forall Ξᡒ, Ind Ξ” Aα΅’ - Ξ“, Θ@{i := u}{Ξ” := pms} ⊒ p : Type - Ξ“, Ξᡒ@{i := u}{Ξ” := pms} ⊒ snd brα΅’ : p{Θ := Aα΅’{Ξ” := pms}} Then Ξ“ ⊒ Case (_, u, pms, ( _, p), _, c, br) : p{Θ := Indices} In particular, this implies that Ξ“ ⊒ pms : Ξ”@{i := u}. Parameters are stored in the same order as in the application node. The u universe instance must be a valid instance for the corresponding inductive type, in particular their length must coincide. The `Name.t binder_annot array` appearing both in the return clause and in the branches must satisfy these invariants: - For branches, it must have the same length as the corresponding Ξᡒ context (including let-ins) - For the return clause, it must have the same length as the context Θ, self : Ind@{u} pms Θ (including let-ins). The last variable appears as the term being destructed and corresponds to the variable introduced by the "as" clause of the user-facing syntax. - The relevance annotations must match with the corresponding sort of the variable from the context. Note that the annotated variable array is reversed w.r.t. the context, i.e. variables appear left to right as in standard practice. Let-bindings can appear in Ξ”, Θ or Ξᡒ, since they are arbitrary contexts. As a general rule, let bindings appear as binders but not as instances. That is, they MUST appear in the variable array, but they MUST NOT appear in the parameter array. Example: ``` Inductive foo (X := tt) : forall (Y := X), Type := Foo : forall (Z := X), foo. Definition case (x : foo) : unit := match x as xβ‚€ in foo with Foo _ z => z end ``` The case node of the `case` function is represented as ``` Case ( _, Instance.empty, [||], ([|(Y, Relevant); (xβ‚€, Relevant)|], unit), (* let (Y := tt) in fun (xβ‚€ : foo) => unit *) NoInvert, #1, [| ([|(z, Relevant)|], #1) (* let z := tt in z *) |] ) ``` This choice of representation for let-bindings requires access to the environment in some cases, e.g. to compute branch reduction. There is a fast-path for non-let-containing inductive types though, which are the vast majority. ### Porting plugins The conversion functions from and to the expanded form are: - `[Inductive, EConstr].expand_case` which goes from the compact to the expanded form and cannot fail (assuming the term was well-typed) - `[Inductive, EConstr].contract_case` which goes the other way and will raise anomalies if the expanded forms are not fully eta-expanded. As such, it is always painless to convert to the old representation. Converting the other way, you must ensure that all the terms you provide the compatibility function with are fully eta-expanded, **including let-bindings**. This works as expected for the common case with eta-expanded branches but will fail for plugins that generate non-eta-expanded branches. Some other useful variants of these functions are: - `Inductive.expand_case_specif` - `EConstr.annotate_case` - `EConstr.expand_branch` rocq-9.2.0/dev/doc/changes.md000066400000000000000000002152271516144147600157650ustar00rootroot00000000000000## Changes between Coq 8.17 and Coq 8.18 ### XML protocol Version 20230413, see xml-protocol.md for details. - Coq locations are now fully transmitted, including line and column information vs the previous start/end offset. ## Changes between Coq 8.15 and Coq 8.16 ### Plugin Interface Plugins are now identified by a findlib library name of the form `pkg.lib`. This way, plugins can depend on other libraries and Coq can properly load the required dependencies. It is necessary to adjust plugin code: - `.mlg` files must now use `DECLARE PLUGIN "pkg.lib"` instead of `DECLARE PLUGIN "library_name"`. - `.v` files should use `Declare ML Module "pkg.lib"`, or, if using Dune, `Declare ML Module "library_name:pkg.lib"` until Dune is adapted. You must also provide the corresponding `META` file if your build system doesn't generate it automatically (see the documentation of `-generate-meta-for-package` for how `coq_makefile` can generate it automatically). ### XML protocol See xml-protocol.md for details. - Added a `Subgoals` command to give more fine-grained control over which of the foreground, background, shelved and given up goals are returned. ## Changes between Coq 8.14 and Coq 8.15 ### XML protocol See xmlprotocol.md for details. - Added 4 new "db_*" messages to support the Ltac debugger - Modified the "add" request (not backward compatible), adding 3 additional parameters to the request giving the buffer offset of the added statement. The parameters are Loc.bp, Loc.line_nb and Loc.bol_pos, which are needed so the debugger gets back a buffer-relative Loc.t rather than a sentence-relative Loc.t. For other use cases, these can be set to 0. ### Internal representation of the type of constructors The type of constructors in fields `mind_user_lc` and `mind_nf_lc` of an inductive packet (see `declarations.ml`) now directly refer to the inductive type rather than to a `Rel` poimting in a context made of the declaration of the inductive types of the block. Thus, instead of `Rel n`, one finds `Ind((mind,ntypes-n),u)` where `ntypes` is the number of types in the block and `u` is the canonical instance of polymoprhic universes (i.e. `Level.Var 0` ... `Level.Var (nbuniv-1)`). In general, code can be adapted by: - either removing a substitution `Rel`->`Ind` if such substitution was applied - or inserting a call to `Inductive.abstract_constructor_type_relatively_to_inductive_types_context` to restore `Rel`s in place of `Ind`s if `Rel`s were expected. ### Universes - Type `UVars.UContext` now embeds universe user names, generally resulting in more concise code. - Renaming `Univ.Constraint` into `Univ.Constraints` - Renaming `LSet` into `Level.Set` and `LMap` into `Level.Map` ### Concrete syntax - Explicit nodes `CProj` and `GProj` have been added for the syntax of projections `t.(f)` in `constr_expr` and `glob_constr`, while they were previously encoded in the `CApp` and `GApp` nodes. There may be a need for adding a new case in pattern-matching. The types of `CApp` and `CAppExpl` have been simplified accordingly. ### Functions manipulating contexts A few functions in Vars, Context, Termops, EConstr have moved. The deprecation warning tells what to do. ### Build system and infrastructure - The Windows installer CI build has been moved from the custom workers based on Inria cloud to a standard Github Action, see https://github.com/rocq-prover/rocq/pull/12425 . Fixes https://github.com/rocq-prover/rocq/issues/6807 https://github.com/rocq-prover/rocq/issues/7428 https://github.com/rocq-prover/rocq/issues/8046 https://github.com/rocq-prover/rocq/issues/8622 https://github.com/rocq-prover/rocq/issues/9401 https://github.com/rocq-prover/rocq/issues/11073 . - Location of Coq's runtime environment and files is now handled by a new library, `coq-core.boot`, which provides a more uniform and centralized API to locate files. ## Changes between Coq 8.13 and Coq 8.14 ### Build system and library infrastructure - ocamlfind library names `coq.*` have been renamed to `coq-core.*`. - Dune is now used to build the OCaml parts of Coq, thus: + ML object files live now in `_build`, as standard in Dune world + you can build object files using `make _build/install/default/bin/coqc`, thanks to our implementation of a make-Dune bridge + .vo files live now in `_build_vo/` + `_build_vo` follows a standard "Coq install layout", that is to say: * `_build_vo/default/bin`: coq-core binaries * `_build_vo/default/lib/coq-core`: coq-core libraries * `_build_vo/default/lib/coq`: coq libraries, such as stdlib This greatly simplifies layout as tooling can assume that `_build_vo/default` has the structure of an installed Coq, thus making the `-local` flag obsolete. + Some developer targets have changed or have been removed in favor of Dune's counterparts, for example `byte` and `install-byte` are no longer needed. For the large majority of developers, we recommend using the full dune build, which is accessible by `make -f Makefile.dune` or by setting the `COQ_USE_DUNE` environment variable. - As a consequence of the above, the packing of plugins has changed. Plugins are now packed using modules aliases which is in general safer w.r.t. scoping, as the container module is just a regular OCaml module. ### Gramlib - A few functions change their interfaces to take benefit of a new abstraction level `LStream` for streams with location function. - Grammar extensions now require specifying whether they create a level or they reuse an existing one. In addition to the Gramlib API changes, GRAMMAR EXTEND stanzas may need a few tweaks. Their grammar was changed so that level and associativity arguments that would have been ignored are now forbidden. Furthermore, extensions without an explicit position now expect the entry to be empty. If it is not the case, the extension will fail at runtime with an assertion failure located near the offending entry. To recover the old behaviour, one needs to explicitly add the new TOP position to the extension. This position expects the entry to be non-empty and populates the topmost defined level with the provided rules. Note that this differs from FIRST, which creates a new level and prepends it to the list of levels of the entry. ### Notations: - The type `notation_entry_level` has been split into two: the name `notation_entry_level` still exists and is used to characterize the level and custom entry name (if any) where a grammar rule lives; the new `notation_subentry_level` is to characterize the level (possibly none) and custom entry name associated to the variables (= non-terminal subentries) of the grammar rule. ## Changes between Coq 8.12 and Coq 8.13 ### Code formatting - The automatic code formatting tool `ocamlformat` has been disabled and its git hook removed. If desired, automatic formatting can be achieved by calling the `fmt` target of the dune build system. ### ML API Abstract syntax of tactic: - TacGeneric now takes an argument to tell if it comes from a notation. Use `None` if not and `Some foo` to tell to print such TacGeneric surrounded with `foo:( )`. Printing functions: - `Pp.h` does not take a `int` argument anymore (the argument was not used). In general, where `h n` for `n` non zero was used, `hv n` was instead intended. If cancelling the breaking role of cuts in the box was intended, turn `h n c` into `h c`. Grammar entries: - `Prim.pattern_identref` is deprecated, use `Prim.pattern_ident` which now returns a located identifier. Generic arguments: - Generic arguments: `wit_var` is deprecated, use `wit_hyp`. Dumpglob: - The function `Dumpglob.pause` and `Dumpglob.continue` are replaced by `Dumpglob.push_output` and `Dumpglob.pop_output`. This allows plugins to temporarily change/pause the output of Dumpglob, and then restore it to the original setting. Glob_term: - Removing useless `binding_kind` argument of `GLocalDef` in `extended_glob_local_binder`. ## Changes between Coq 8.11 and Coq 8.12 ### Code formatting - The automatic code formatting tool `ocamlformat` is enabled now for the micromega codebase. Version 0.13.0 is required. See `ocalmformat`'s documentation for more details on integration with your editor. ### ML API Proof state and constant declaration: - A large consolidation of the API handling interactive and non-interactive constant has been performed; low-level APIs are no longer available, and the functionality of the `Proof_global` module has been merged into `Declare`. Notations: - Most operators on numerals have moved to file numTok.ml. - Types `precedence`, `parenRelation`, `tolerability` in `notgram_ops.ml` have been reworked. See `entry_level` and `entry_relative_level` in `constrexpr.ml`. Exception handling: - Coq's custom `Backtrace` module has been removed in favor of OCaml's native backtrace implementation. Please use the functions in `Exninfo.capture` and `iraise` when re-raising inside an exception handler. - Registration of exception printers now follows more closely OCaml's API, thus: + printers are of type `exn -> Pp.t option` [`None` == not handled] + it is forbidden for exception printers to raise. - Refiner.catchable_exception is deprecated, use instead CErrors.noncritical in try-with block. Note that nothing is needed in tclORELSE block since the exceptions there are supposed to be non-critical by construction. Printers: - Functions such as Printer.pr_lconstr_goal_style_env have been removed, use instead functions such as pr_lconstr with label `goal_concl_style:true`. Functions such as Constrextern.extern_constr which were taking a boolean argument for the goal style now take instead a label. Implicit arguments: - The type `Impargs.implicit_kind` was removed in favor of `Glob_term.binding_kind`. ## Changes between Coq 8.10 and Coq 8.11 ### ML API - Function UnivGen.global_of_constr has been removed. - Functions and types deprecated in 8.10 have been removed in Coq 8.11. - Type Decl_kinds.locality has been restructured, see commit message. Main change to do generally is to change the flag "Global" to "Global ImportDefaultBehavior". Proof state: Proofs that are attached to a top-level constant (such as lemmas) are represented by `Lemmas.t`, as they do contain additional information related to the constant declaration. Some functions have been renamed from `start_proof` to `start_lemma` Plugins that require access to the information about currently opened lemmas can add one of the `![proof]` attributes to their `mlg` entry, which will refine the type accordingly. See documentation in `vernacentries` for more information. Proof `terminators` have been removed in favor of a principled proof-saving path. This should not affect the regular API user, but if plugin writes need special handling of the proof term they should now work with Coq upstream to unsure the provided API does work and is principled. Closing `hooks` are still available for simple registration on constant save path, and essentially they do provide the same power as terminators, but don't encourage their use other than for simple tasks [such as adding a constant to a database] Additionally, the API for proof/lemma handling has been refactored, triples have been split into named arguments, and a few bits of duplicated information among layers has been cleaned up. Most proof information is now represented in a direct-style, as opposed to it living inside closures in previous Coq versions; thus, proof manipulation possibilities have been improved. ## Changes between Coq 8.9 and Coq 8.10 ### ML4 Pre Processing - Support for `.ml4` files, processed by camlp5 has been removed in favor of `.mlg` files processed by `coqpp`. Porting is usually straightforward, and involves renaming the `file.ml4` file to `file.mlg` and adding a few brackets. See "Transitioning away from Camlp5" below for update instructions. ### ML API SProp was added, see General deprecation - All functions marked [@@ocaml.deprecated] in 8.8 have been removed. Please, make sure your plugin is warning-free in 8.8 before trying to port it over 8.9. Warnings - Coq now builds plugins with `-warn-error` enabled by default. The amount of dangerous warnings in plugin code was very high, so we now require plugins in the CI to adhere to the Coq warning policy. We _strongly_ recommend against disabling the default set of warnings. If you have special needs, see the documentation of your build system and/or OCaml for further help. Names - Kernel names no longer contain a section path. They now have only two components (module path and label), which led to some changes in the API: KerName.make takes only 2 components KerName.repr returns only 2 components KerName.make2 is now KerName.make Constant.make3 has been removed, use Constant.make2 Constant.repr3 has been removed, use Constant.repr2 - `Names.transparent_state` has been moved to its own module `TransparentState`. This module gathers utility functions that used to be defined in several places. Coqlib: - Most functions from the `Coqlib` module have been deprecated in favor of `register_ref` and `lib_ref`. The first one is available through the vernacular `Register` command; it binds a name to a constant. The second command then enables to locate the registered constant through its name. The name resolution is dynamic. Proof state: - Handling of proof state has been fully functionalized, thus it is not possible to call global functions such as `get_current_context ()`. The main type for functions that need to handle proof state is `Proof_global.t`. Unfortunately, this change was not possible to do in a backwards-compatible way, but in most case the api changes are straightforward, with functions taking and returning an extra argument. Macros: - The RAW_TYPED AS and GLOB_TYPED AS stanzas of the ARGUMENT EXTEND macro are deprecated. Use TYPED AS instead. - coqpp (.mlg) based VERNAC EXTEND accesses attributes through a `#[ x = att ]` syntax, where `att : 'a Attributes.attribute` and `x` will be bound with type `'a` in the expression, unlike the old system where `atts : Vernacexpr.vernac_flags` was bound in the expression and had to be manually parsed. - `PRINTED BY` now binds `env` and `sigma`, and expects printers which take as parameters term printers parametrized by an environment and an `evar_map`. Printers - `Ppconstr.pr_constr_expr`, `Ppconstr.lconstr_expr`, `Ppconstr.pr_constr_pattern_expr` and `Ppconstr.pr_lconstr_pattern_expr` now all take an environment and an `evar_map`. Libobject - A Higher-level API for objects with fixed scope was introduced. It supports the following kinds of objects: * Local objects, meaning that objects cannot be imported from outside. * Global objects, meaning that they can be imported (by importing the module that contains the object). * Superglobal objects, meaning that objects survive to closing a module, and are imported when the file which contains them is Required (even without Import). * Objects that survive section closing or don't (see `nodischarge` variants, however we discourage defining such objects) This API is made of the following functions: * `Libobject.local_object` * `Libobject.local_object_nodischarge` * `Libobject.global_object` * `Libobject.global_object_nodischarge` * `Libobject.superglobal_object` * `Libobject.superglobal_object_nodischarge` AST - Minor changes in the AST have been performed, for example https://github.com/rocq-prover/rocq/pull/9165 Implicit Arguments - `Impargs.declare_manual_implicits` is restricted to only support declaration of implicit binders at constant declaration time. `Impargs.set_implicits` should be used for redeclaration of implicit arguments. ## Changes between Coq 8.8 and Coq 8.9 ### ML API Names - In `Libnames`, the type `reference` and its two constructors `Qualid` and `Ident` have been removed in favor of `qualid`. `Qualid` is now the identity, `Ident` can be replaced by `qualid_of_ident`. Matching over `reference` can be replaced by a test using `qualid_is_ident`. Extracting the `ident` part of a `qualid` can be done using `qualid_basename`. Misctypes - Syntax for universe sorts and kinds has been moved from `Misctypes` to `Glob_term`, as these are turned into kernel terms by `Pretyping`. Proof engine - More functions have been changed to use `EConstr`, notably the functions in `Evd`, and in particular `Evd.define`. Note that the core function `EConstr.to_constr` now _enforces_ by default that the resulting term is ground, that is to say, free of Evars. This is usually what you want, as open terms should be of type `EConstr.t` to benefit from the invariants the `EConstr` API is meant to guarantee. In case you'd like to violate this API invariant, you can use the `abort_on_undefined_evars` flag to `EConstr.to_constr`, but note that setting this flag to false is deprecated so it is only meant to be used as to help port pre-EConstr code. - A few type alias have been deprecated, in all cases the message should indicate what the canonical form is. An important change is the move of `Globnames.global_reference` to `Names.GlobRef.t`. - Unification API returns `evar_map option` instead of `bool * evar_map` with the guarantee that the `evar_map` was unchanged if the boolean was false. ML Libraries used by Coq - Introduction of a `Smart` module for collecting `smart*` functions, e.g. `Array.Smart.map`. - Uniformization of some names, e.g. `Array.Smart.fold_left_map` instead of `Array.smartfoldmap`. Printer.ml API - The mechanism in `Printer` that allowed dynamically overriding `pr_subgoals`, `pr_subgoal` and `pr_goal` was removed to simplify the code. It was earlier used by PCoq. Kernel - The following renamings happened: - `Context.Rel.t` into `Constr.rel_context` - `Context.Named.t` into `Constr.named_context` - `Context.Compacted.t` into `Constr.compacted_context` - `Context.Rel.Declaration.t` into `Constr.rel_declaration` - `Context.Named.Declaration.t` into `Constr.named_declaration` - `Context.Compacted.Declaration.t` into `Constr.compacted_declaration` Source code organization - We have eliminated / fused some redundant modules and relocated a few interfaces files. The `intf` folder is gone, and now for example `Constrexpr` is located in `interp/`, `Vernacexpr` in `vernac/` and so on. Changes should be compatible, but in a few cases stricter layering requirements may mean that functions have moved. In all cases adapting is a matter of changing the module name. Vernacular commands - The implementation of vernacular commands has been refactored so it is self-contained now, including the parsing and extension mechanisms. This involves a couple of non-backward compatible changes due to layering issues, where some functions have been moved from `Pcoq` to `Pvernac` and from `Vernacexpr` to modules in `tactics/`. In all cases adapting is a matter of changing the module name. Primitive number parsers - For better modularity, the primitive parsers for `positive`, `N` and `Z` have been split over three files (`plugins/syntax/positive_syntax.ml`, `plugins/syntax/n_syntax.ml`, `plugins/syntax/z_syntax.ml`). Parsing - Manual uses of the `Pcoq.Gram` module have been deprecated. Wrapper modules `Pcoq.Entry` and `Pcoq.Parsable` were introduced to replace it. Termops - Internal printing functions have been placed under the `Termops.Internal` namespace. ### Unit testing The test suite now allows writing unit tests against OCaml code in the Coq code base. Those unit tests create a dependency on the OUnit test framework. ### Transitioning away from Camlp5 In an effort to reduce dependency on camlp5, the use of several grammar macros is discouraged. Coq is now shipped with its own preprocessor, called coqpp, which serves the same purpose as camlp5. To perform the transition to coqpp macros, one first needs to change the extension of a macro file from `.ml4` to `.mlg`. Not all camlp5 macros are handled yet. Due to parsing constraints, the syntax of the macros is slightly different, but updating the source code is mostly a matter of straightforward search-and-replace. The main differences are summarized below. #### OCaml code Every piece of toplevel OCaml code needs to be wrapped into braces. For instance, code of the form ``` let myval = 0 ``` should be turned into ``` { let myval = 0 } ``` #### TACTIC EXTEND Steps to perform: - replace the brackets enclosing OCaml code in actions with braces - if not there yet, add a leading `|` to the first rule For instance, code of the form: ``` TACTIC EXTEND my_tac [ "tac1" int_or_var(i) tactic(t) ] -> [ mytac1 ist i t ] | [ "tac2" tactic(t) ] -> [ mytac2 t ] END ``` should be turned into ``` TACTIC EXTEND my_tac | [ "tac1" int_or_var(i) tactic(t) ] -> { mytac1 ist i t } | [ "tac2" tactic(t) ] -> { mytac2 t } END ``` #### VERNAC EXTEND Steps to perform: - replace the brackets enclosing OCaml code in actions and rule classifiers with braces - if not there yet, add a leading `|Μ€ to the first rule Handwritten classifiers declared through the `CLASSIFIED BY` statement are considered OCaml code, so they also need to be wrapped in braces. For instance, code of the form: ``` VERNAC COMMAND EXTEND my_command CLASSIFIED BY classifier [ "foo" int(i) ] => [ classif' ] -> [ cmd1 i ] | [ "bar" ] -> [ cmd2 ] END ``` should be turned into ``` VERNAC COMMAND EXTEND my_command CLASSIFIED BY { classifier } | [ "foo" int(i) ] => { classif' } -> { cmd1 i } | [ "bar" ] -> { cmd2 } END ``` #### ARGUMENT EXTEND Steps to perform: - replace the brackets enclosing OCaml code in actions with braces - if not there yet, add a leading `|` to the first rule - syntax of `TYPED AS` has been restricted not to accept compound generic arguments as a literal, e.g. `foo_opt` should be rewritten into `foo option` and similarly `foo_list` into `foo list`. - parenthesis around pair types in `TYPED AS` are now mandatory - `RAW_TYPED AS` and `GLOB_TYPED AS` clauses need to be removed `BY` clauses are considered OCaml code, and thus need to be wrapped in braces, but not the `TYPED AS` clauses. For instance, code of the form: ``` ARGUMENT EXTEND my_arg TYPED AS int_opt PRINTED BY printer INTERPRETED BY interp_f GLOBALIZED BY glob_f SUBSTITUTED BY subst_f RAW_TYPED AS int_opt RAW_PRINTED BY raw_printer GLOB_TYPED AS int_opt GLOB_PRINTED BY glob_printer [ "foo" int(i) ] -> [ my_arg1 i ] | [ "bar" ] -> [ my_arg2 ] END ``` should be turned into ``` ARGUMENT EXTEND my_arg TYPED AS { int_opt } PRINTED BY { printer } INTERPRETED BY { interp_f } GLOBALIZED BY { glob_f } SUBSTITUTED BY { subst_f } RAW_PRINTED BY { raw_printer } GLOB_PRINTED BY { glob_printer } | [ "foo" int(i) ] -> { my_arg1 i } | [ "bar" ] -> { my_arg2 } END ``` #### GEXTEND Most plugin writers do not need this low-level interface, but for the sake of completeness we document it. Steps to perform are: - replace `GEXTEND` with `GRAMMAR EXTEND` - wrap every occurrence of OCaml code in actions into braces `{ }` For instance, code of the form ``` GEXTEND Gram GLOBAL: my_entry; my_entry: [ [ x = bar; y = qux -> do_something x y | "("; z = LIST0 my_entry; ")" -> do_other_thing z ] ]; END ``` should be turned into ``` GRAMMAR EXTEND Gram GLOBAL: my_entry; my_entry: [ [ x = bar; y = qux -> { do_something x y } | "("; z = LIST0 my_entry; ")" -> { do_other_thing z } ] ]; END ``` Caveats: - No `GLOBAL` entries mean that they are all local, while camlp5 special-cases this as a shorthand for all global entries. Solution: always define a `GLOBAL` section. - No complex patterns allowed in token naming. Solution: match on it inside the OCaml quotation. ## Changes between Coq 8.7 and Coq 8.8 ### Bug tracker As of 18/10/2017, Coq uses [GitHub issues](https://github.com/rocq-prover/rocq/issues) as bug tracker. Old bug reports were migrated from Bugzilla to GitHub issues using [this migration script](https://gist.github.com/Zimmi48/d923e52f64fe17c72852d9c148bfcdc6#file-bugzilla2github) as detailed in [this blog post](https://www.theozimmermann.net/2017/10/bugzilla-to-github/). All the bugs with a number below 1154 had to be renumbered, you can find a correspondence table [here](/dev/bugzilla2github_stripped.csv). All the other bugs kept their number. ### ML API General deprecation - All functions marked `[@@ocaml.deprecated]` in 8.7 have been removed. Please, make sure your plugin is warning-free in 8.7 before trying to port it over 8.8. Proof engine - Due to the introduction of `EConstr` in 8.7, it is not necessary to track "goal evar normal form status" anymore, thus the type `'a Proofview.Goal.t` loses its ghost argument. This may introduce some minor incompatibilities at the typing level. Code-wise, things should remain the same. We removed the following functions: - `Universes.unsafe_constr_of_global`: use `Global.constr_of_global_in_context` instead. The returned term contains De Bruijn universe variables. If you don't depend on universes being instantiated, simply drop the context. - `Universes.unsafe_type_of_global`: same as above with `Global.type_of_global_in_context` We changed the type of the following functions: - `Global.body_of_constant_body`: now also returns the abstract universe context. The returned term contains De Bruijn universe variables. - `Global.body_of_constant`: same as above. - `Constrinterp.*`: generally, many functions that used to take an `evar_map ref` have now been switched to functions that will work in a functional way. The old style of passing `evar_map`s as references is not supported anymore. Changes in the abstract syntax tree: - The practical totality of the AST has been nodified using `CAst.t`. This means that all objects coming from parsing will be indeed wrapped in a `CAst.t`. `Loc.located` is on its way to deprecation. Some minor interfaces changes have resulted from this. We have changed the representation of the following types: - `Lib.object_prefix` is now a record instead of a nested tuple. Some tactics and related functions now support static configurability, e.g.: - `injectable`, `dEq`, etc. take an argument `~keep_proofs` which, - if `None`, tells to behave as told with the flag `Keep Proof Equalities` - if `Some b`, tells to keep proof equalities iff `b` is true Declaration of printers for arguments used only in vernac command - It should now use `declare_extra_vernac_genarg_pprule` rather than `declare_extra_genarg_pprule`, otherwise, a failure at runtime might happen. An alternative is to register the corresponding argument as a value, using `Geninterp.register_val0 wit None`. Types Alias deprecation and type relocation. - A few type alias have been deprecated, in all cases the message should indicate what the canonical form is. ### STM API The STM API has seen a general overhaul. The main change is the introduction of a "Coq document" type, which all operations now take as a parameter. This effectively functionalize the STM API and will allow in the future to handle several documents simultaneously. The main remarkable point is that key implicit global parameters such as load-paths and required modules are now arguments to the document creation function. This helps enforcing some key invariants. ### XML IDE Protocol - Before 8.8, `Query` only executed the first command present in the `query` string; starting with 8.8, the caller may include several statements. This is useful for instance for temporarily setting an option and then executing a command. ## Changes between Coq 8.6 and Coq 8.7 ### Ocaml Coq is compiled with `-safe-string` enabled and requires plugins to do the same. This means that code using `String` in an imperative way will fail to compile now. They should switch to `Bytes.t` Configure supports passing flambda options, use `-flambda-opts OPTS` with a flambda-enabled Ocaml to tweak the compilation to your taste. ### ML API - Added two functions for declaring hooks to be executed in reduction functions when some given constants are traversed: * `declare_reduction_effect`: to declare a hook to be applied when some constant are visited during the execution of some reduction functions (primarily `cbv`). * `set_reduction_effect`: to declare a constant on which a given effect hook should be called. - We renamed the following functions: ``` Context.Rel.Declaration.fold -> Context.Rel.Declaration.fold_constr Context.Named.Declaration.fold -> Context.Named.Declaration.fold_constr Printer.pr_var_list_decl -> Printer.pr_compacted_decl Printer.pr_var_decl -> Printer.pr_named_decl Nameops.lift_subscript -> Nameops.increment_subscript ``` - We removed the following functions: * `Termops.compact_named_context_reverse`: practical substitute is `Termops.compact_named_context`. * `Namegen.to_avoid`: equivalent substitute is `Names.Id.List.mem`. - We renamed the following modules: * `Context.ListNamed` -> `Context.Compacted` - The following type aliases where removed * `Context.section_context`: it was just an alias for `Context.Named.t` which is still available. - The module `Constrarg` was merged into `Stdarg`. - The following types have been moved and modified: * `local_binder` -> `local_binder_expr` * `glob_binder` merged with `glob_decl` - The following constructors have been renamed: ``` LocalRawDef -> CLocalDef LocalRawAssum -> CLocalAssum LocalPattern -> CLocalPattern ``` - In `Constrexpr_ops`: Deprecating `abstract_constr_expr` in favor of `mkCLambdaN`, and `prod_constr_expr` in favor of `mkCProdN`. Note: the first ones were interpreting `(x y z:_)` as `(x:_) (y:_) (z:_)` while the second ones were preserving the original sharing of the type. - In `Nameops`: The API has been made more uniform. New combinators added in the `Name` space name. Function `out_name` now fails with `IsAnonymous` rather than with `Failure "Nameops.out_name"`. - Location handling and AST attributes: Location handling has been reworked. First, `Loc.ghost` has been removed in favor of an option type, all objects carrying an optional source code location have been switched to use `Loc.t option`. Storage of location information has been also refactored. The main datatypes representing Coq AST (`constrexpr`, `glob_expr`) have been switched to a generic "node with attributes" representation `'a CAst.ast`, which is a record of the form: ```ocaml type 'a ast = private { v : 'a; loc : Loc.t option; ... } ``` consumers of AST nodes are recommended to use accessor-based pattern matching `{ v; loc }` to destruct `ast` object. Creation is done with `CAst.make ?loc obj`, where the attributes are optional. Some convenient combinators are provided in the module. A typical match: ```ocaml | CCase(loc, a1) -> CCase(loc, f a1) ``` is now done as: ```ocaml | { v = CCase(a1); loc } -> CAst.make ?loc @@ CCase(f a1) ``` or even better, if plan to preserve the attributes you can wrap your top-level function in `CAst.map` to have: ```ocaml | CCase(a1) -> CCase(f a1) ``` This scheme based on records enables easy extensibility of the AST node type without breaking compatibility. Not all objects carrying a location have been converted to the generic node representation, some of them may be converted in the future, for some others the abstraction is not just worth it. Thus, we still maintain a `'a Loc.located == Loc.t option * a'`, tuple type which should be treated as private datatype (ok to match against, but forbidden to manually build), and it is mandatory to use it for objects that carry a location. This policy has been implemented in the whole code base. Matching a located object hasn't changed, however, `Loc.tag ?loc obj` must be used to build one. - In `GOption`: Support for non-synchronous options has been removed. Now all options are handled as a piece of normal document state, and thus passed to workers, etc... As a consequence, the field `Goptions.optsync` has been removed. - In `Coqlib` / reference location: We have removed from Coqlib functions returning `constr` from names. Now it is only possible to obtain references, that must be processed wrt the particular needs of the client. We have changed in constrintern the functions returnin `constr` as well to return global references instead. Users of `coq_constant/gen_constant` can do `Universes.constr_of_global (find_reference dir r)` _however_ note the warnings in the `Universes.constr_of_global` in the documentation. It is very likely that you were previously suffering from problems with polymorphic universes due to using `Coqlib.coq_constant` that used to do this. You must rather use `pf_constr_of_global` in tactics and `Evarutil.new_global` variants when constructing terms in ML (see univpoly.txt for more information). ### Tactic API - `pf_constr_of_global` now returns a tactic instead of taking a continuation. Thus it only generates one instance of the global reference, and it is the caller's responsibility to perform a focus on the goal. - `pf_global`, `construct_reference`, `global_reference`, `global_reference_in_absolute_module` now return a `global_reference` instead of a `constr`. - The `tclWEAK_PROGRESS` and `tclNOTSAMEGOAL` tacticals were removed. Their usecase was very specific. Use `tclPROGRESS` instead. - New (internal) tactical `tclINDEPENDENTL` that combined with enter_one allows to iterate a non-unit tactic on all goals and access their returned values. - The unsafe flag of the `Refine.refine` function and its variants has been renamed and dualized into typecheck and has been made mandatory. ### Ltac API Many Ltac specific API has been moved in its own ltac/ folder. Amongst other important things: - `Pcoq.Tactic` -> `Pltac` - `Constrarg.wit_tactic` -> `Tacarg.wit_tactic` - `Constrarg.wit_ltac` -> `Tacarg.wit_ltac` - API below `ltac/` that accepted a *`_tactic_expr` now accept a *`_generic_argument` instead - Some printing functions were moved from `Pptactic` to `Pputils` - A part of `Tacexpr` has been moved to `Tactypes` - The `TacFun` tactic expression constructor now takes a `Name.t list` for the variable list rather than an `Id.t option list`. The folder itself has been turned into a plugin. This does not change much, but because it is a packed plugin, it may wreak havoc for third-party plugins depending on any module defined in the `ltac/` directory. Namely, even if everything looks OK at compile time, a plugin can fail to load at link time because it mistakenly looks for a module `Foo` instead of `Ltac_plugin.Foo`, with an error of the form: ``` Error: while loading myplugin.cmxs, no implementation available for Foo. ``` In particular, most `EXTEND` macros will trigger this problem even if they seemingly do not use any Ltac module, as their expansion do. The solution is simple, and consists in adding a statement `open Ltac_plugin` in each file using a Ltac module, before such a module is actually called. An alternative solution would be to fully qualify Ltac modules, e.g. turning any call to Tacinterp into `Ltac_plugin.Tacinterp`. Note that this solution does not work for `EXTEND` macros though. ### Additional changes in tactic extensions Entry `constr_with_bindings` has been renamed into `open_constr_with_bindings`. New entry `constr_with_bindings` now uses type classes and rejects terms with unresolved holes. ### Error handling - All error functions now take an optional parameter `?loc:Loc.t`. For functions that used to carry a suffix `_loc`, such suffix has been dropped. - `errorlabstrm` and `error` has been removed in favor of `user_err`. - The header parameter to `user_err` has been made optional. ### Pretty printing Some functions have been removed, see pretty printing below for more details. #### Pretty Printing and XML protocol The type `std_cmdpps` has been reworked and made the canonical "Coq rich document type". This allows for a more uniform handling of printing (specially in IDEs). The main consequences are: - Richpp has been confined to IDE use. Most of previous uses of the `richpp` type should be replaced now by `Pp.std_cmdpps`. Main API has been updated. - The XML protocol will send a new message type of `pp`, which should be rendered client-wise. - `Set Printing Width` is deprecated, now width is controlled client-side. - `Pp_control` has removed. The new module `Topfmt` implements console control for the toplevel. - The impure tag system in `Pp` has been removed. This also does away with the printer signatures and functors. Now printers tag unconditionally. - The following functions have been removed from `Pp`: ```ocaml val stras : int * string -> std_ppcmds val tbrk : int * int -> std_ppcmds val tab : unit -> std_ppcmds val pifb : unit -> std_ppcmds val comment : int -> std_ppcmds val comments : ((int * int) * string) list ref val eval_ppcmds : std_ppcmds -> std_ppcmds val is_empty : std_ppcmds -> bool val t : std_ppcmds -> std_ppcmds val hb : int -> std_ppcmds val vb : int -> std_ppcmds val hvb : int -> std_ppcmds val hovb : int -> std_ppcmds val tb : unit -> std_ppcmds val close : unit -> std_ppcmds val tclose : unit -> std_ppcmds val open_tag : Tag.t -> std_ppcmds val close_tag : unit -> std_ppcmds val msg_with : ... module Tag ``` ### Stm API - We have streamlined the `Stm` API, now `add` and `query` take a `coq_parsable` instead a `string` so clients can have more control over their input stream. As a consequence, their types have been modified. - The main parsing entry point has also been moved to the `Stm`. Parsing is considered a synchronous operation so it will either succeed or raise an exception. - `Feedback` is now only emitted for asynchronous operations. As a consequence, it always carries a valid stateid and the type has changed to accommodate that. - A few unused hooks were removed due to cleanups, no clients known. ### Toplevel and Vernacular API - The components related to vernacular interpretation have been moved to their own folder `vernac/` whereas toplevel now contains the proper toplevel shell and compiler. - Coq's toplevel has been ported to directly use the common `Stm` API. The signature of a few functions has changed as a result. ### XML Protocol - The legacy `Interp` call has been turned into a noop. - The `query` call has been modified, now it carries a mandatory `route_id` integer parameter, that associated the result of such query with its generated feedback. ## Changes between Coq 8.5 and Coq 8.6 ### Parsing `Pcoq.parsable` now takes an extra optional filename argument so as to bind locations to a file name when relevant. ### Files To avoid clashes with OCaml's compiler libs, the following files were renamed: ``` kernel/closure.ml{,i} -> kernel/cClosure.ml{,i} lib/errors.ml{,i} -> lib/cErrors.ml{,i} toplevel/cerror.ml{,i} -> toplevel/explainErr.mli{,i} ``` All IDE-specific files, including the XML protocol have been moved to `ide/` ### Reduction functions In `closure.ml`, we introduced the more precise reduction flags `fMATCH`, `fFIX`, `fCOFIX`. We renamed the following functions: ``` Closure.betadeltaiota -> Closure.all Closure.betadeltaiotanolet -> Closure.allnolet Reductionops.beta -> Closure.beta Reductionops.zeta -> Closure.zeta Reductionops.betaiota -> Closure.betaiota Reductionops.betaiotazeta -> Closure.betaiotazeta Reductionops.delta -> Closure.delta Reductionops.betalet -> Closure.betazeta Reductionops.betadelta -> Closure.betadeltazeta Reductionops.betadeltaiota -> Closure.all Reductionops.betadeltaiotanolet -> Closure.allnolet Closure.no_red -> Closure.nored Reductionops.nored -> Closure.nored Reductionops.nf_betadeltaiota -> Reductionops.nf_all Reductionops.whd_betadelta -> Reductionops.whd_betadeltazeta Reductionops.whd_betadeltaiota -> Reductionops.whd_all Reductionops.whd_betadeltaiota_nolet -> Reductionops.whd_allnolet Reductionops.whd_betadelta_stack -> Reductionops.whd_betadeltazeta_stack Reductionops.whd_betadeltaiota_stack -> Reductionops.whd_all_stack Reductionops.whd_betadeltaiota_nolet_stack -> Reductionops.whd_allnolet_stack Reductionops.whd_betadelta_state -> Reductionops.whd_betadeltazeta_state Reductionops.whd_betadeltaiota_state -> Reductionops.whd_all_state Reductionops.whd_betadeltaiota_nolet_state -> Reductionops.whd_allnolet_state Reductionops.whd_eta -> Reductionops.shrink_eta Tacmach.pf_whd_betadeltaiota -> Tacmach.pf_whd_all Tacmach.New.pf_whd_betadeltaiota -> Tacmach.New.pf_whd_all ``` And removed the following ones: ``` Reductionops.whd_betaetalet Reductionops.whd_betaetalet_stack Reductionops.whd_betaetalet_state Reductionops.whd_betadeltaeta_stack Reductionops.whd_betadeltaeta_state Reductionops.whd_betadeltaeta Reductionops.whd_betadeltaiotaeta_stack Reductionops.whd_betadeltaiotaeta_state Reductionops.whd_betadeltaiotaeta ``` In `intf/genredexpr.mli`, `fIota` was replaced by `FMatch`, `FFix` and `FCofix`. Similarly, `rIota` was replaced by `rMatch`, `rFix` and `rCofix`. ### Notation_ops Use `Glob_ops.glob_constr_eq` instead of `Notation_ops.eq_glob_constr`. ### Logging and Pretty Printing * Printing functions have been removed from `Pp.mli`, which is now a purely pretty-printing interface. Functions affected are: ```` ocaml val pp : std_ppcmds -> unit val ppnl : std_ppcmds -> unit val pperr : std_ppcmds -> unit val pperrnl : std_ppcmds -> unit val pperr_flush : unit -> unit val pp_flush : unit -> unit val flush_all : unit -> unit val msg : std_ppcmds -> unit val msgnl : std_ppcmds -> unit val msgerr : std_ppcmds -> unit val msgerrnl : std_ppcmds -> unit val message : string -> unit ```` which are no more available. Users of `Pp.pp msg` should now use the proper `Feedback.msg_*` function. Clients also have no control over flushing, the back end takes care of it. Also, the `msg_*` functions now take an optional `?loc` parameter for relaying location to the client. * Feedback related functions and definitions have been moved to the `Feedback` module. `message_level` has been renamed to level. Functions moved from `Pp` to `Feedback` are: ```` ocaml val set_logger : logger -> unit val std_logger : logger val emacs_logger : logger val feedback_logger : logger ```` * Changes in the Feedback format/Protocol. - The `Message` feedback type now carries an optional location, the main payload is encoded using the richpp document format. - The `ErrorMsg` feedback type is thus unified now with `Message` at level `Error`. * We now provide several loggers, `log_via_feedback` is removed in favor of `set_logger feedback_logger`. Output functions are: ```` ocaml val with_output_to_file : string -> ('a -> 'b) -> 'a -> 'b val msg_error : ?loc:Loc.t -> Pp.std_ppcmds -> unit val msg_warning : ?loc:Loc.t -> Pp.std_ppcmds -> unit val msg_notice : ?loc:Loc.t -> Pp.std_ppcmds -> unit val msg_info : ?loc:Loc.t -> Pp.std_ppcmds -> unit val msg_debug : ?loc:Loc.t -> Pp.std_ppcmds -> unit ```` with the `msg_*` functions being just an alias for `logger $Level`. * The main feedback functions are: ```` ocaml val set_feeder : (feedback -> unit) -> unit val feedback : ?id:edit_or_state_id -> ?route:route_id -> feedback_content -> unit val set_id_for_feedback : ?route:route_id -> edit_or_state_id -> unit ```` Note that `feedback` doesn't take two parameters anymore. After refactoring the following function has been removed: ```` ocaml val get_id_for_feedback : unit -> edit_or_state_id * route_id ```` ### Kernel API changes - The interface of the `Context` module was changed. Related types and functions were put in separate submodules. The mapping from old identifiers to new identifiers is the following: ``` Context.named_declaration ---> Context.Named.Declaration.t Context.named_list_declaration ---> Context.NamedList.Declaration.t Context.rel_declaration ---> Context.Rel.Declaration.t Context.map_named_declaration ---> Context.Named.Declaration.map_constr Context.map_named_list_declaration ---> Context.NamedList.Declaration.map Context.map_rel_declaration ---> Context.Rel.Declaration.map_constr Context.fold_named_declaration ---> Context.Named.Declaration.fold Context.fold_rel_declaration ---> Context.Rel.Declaration.fold Context.exists_named_declaration ---> Context.Named.Declaration.exists Context.exists_rel_declaration ---> Context.Rel.Declaration.exists Context.for_all_named_declaration ---> Context.Named.Declaration.for_all Context.for_all_rel_declaration ---> Context.Rel.Declaration.for_all Context.eq_named_declaration ---> Context.Named.Declaration.equal Context.eq_rel_declaration ---> Context.Rel.Declaration.equal Context.named_context ---> Context.Named.t Context.named_list_context ---> Context.NamedList.t Context.rel_context ---> Context.Rel.t Context.empty_named_context ---> Context.Named.empty Context.add_named_decl ---> Context.Named.add Context.vars_of_named_context ---> Context.Named.to_vars Context.lookup_named ---> Context.Named.lookup Context.named_context_length ---> Context.Named.length Context.named_context_equal ---> Context.Named.equal Context.fold_named_context ---> Context.Named.fold_outside Context.fold_named_list_context ---> Context.NamedList.fold Context.fold_named_context_reverse ---> Context.Named.fold_inside Context.instance_from_named_context ---> Context.Named.to_instance Context.extended_rel_list ---> Context.Rel.to_extended_list Context.extended_rel_vect ---> Context.Rel.to_extended_vect Context.fold_rel_context ---> Context.Rel.fold_outside Context.fold_rel_context_reverse ---> Context.Rel.fold_inside Context.map_rel_context ---> Context.Rel.map_constr Context.map_named_context ---> Context.Named.map_constr Context.iter_rel_context ---> Context.Rel.iter Context.iter_named_context ---> Context.Named.iter Context.empty_rel_context ---> Context.Rel.empty Context.add_rel_decl ---> Context.Rel.add Context.lookup_rel ---> Context.Rel.lookup Context.rel_context_length ---> Context.Rel.length Context.rel_context_nhyps ---> Context.Rel.nhyps Context.rel_context_tags ---> Context.Rel.to_tags ``` - Originally, rel-context was represented as: ```ocaml type Context.rel_context = Names.Name.t * Constr.t option * Constr.t ``` Now it is represented as: ```ocaml type Context.Rel.Declaration.t = LocalAssum of Names.Name.t * Constr.t | LocalDef of Names.Name.t * Constr.t * Constr.t ``` - Originally, named-context was represented as: ```ocaml type Context.named_context = Names.Id.t * Constr.t option * Constr.t ``` Now it is represented as: ```ocaml type Context.Named.Declaration.t = LocalAssum of Names.Id.t * Constr.t | LocalDef of Names.Id.t * Constr.t * Constr.t ``` - The various `EXTEND` macros do not handle specially the Coq-defined entries anymore. Instead, they just output a name that have to exist in the scope of the ML code. The parsing rules (`VERNAC`) `ARGUMENT EXTEND` will look for variables `$name` of type `Gram.entry`, while the parsing rules of (`VERNAC COMMAND` | `TACTIC`) `EXTEND`, as well as the various `TYPED AS` clauses will look for variables `wit_$name` of type `Genarg.genarg_type`. The small DSL for constructing compound entries still works over this scheme. Note that in the case of (`VERNAC`) `ARGUMENT EXTEND`, the name of the argument entry is bound in the parsing rules, so beware of recursive calls. For example, to get `wit_constr` you must `open Constrarg` at the top of the file. - `Evarutil` was split in two parts. The new `Evardefine` file exposes functions `define_evar_`* mostly used internally in the unification engine. - The `Refine` module was moved out of `Proofview`. ``` Proofview.Refine.* ---> Refine.* ``` - A statically monotonic evarmap type was introduced in `Sigma`. Not all the API has been converted, so that the user may want to use compatibility functions `Sigma.to_evar_map` and `Sigma.Unsafe.of_evar_map` or `Sigma.Unsafe.of_pair` when needed. Code can be straightforwardly adapted in the following way: ```ocaml let (sigma, x1) = ... in ... let (sigma, xn) = ... in (sigma, ans) ``` should be turned into: ```ocaml open Sigma.Notations let Sigma (x1, sigma, p1) = ... in ... let Sigma (xn, sigma, pn) = ... in Sigma (ans, sigma, p1 +> ... +> pn) ``` Examples of `Sigma.Unsafe.of_evar_map` include: ``` Evarutil.new_evar env (Tacmach.project goal) ty ----> Evarutil.new_evar env (Sigma.Unsafe.of_evar_map (Tacmach.project goal)) ty ``` - The `Proofview.Goal.`*`enter` family of functions now takes a polymorphic continuation given as a record as an argument. ```ocaml Proofview.Goal.enter begin fun gl -> ... end ``` should be turned into ```ocaml open Proofview.Notations Proofview.Goal.enter { enter = begin fun gl -> ... end } ``` - `Tacexpr.TacDynamic(Loc.dummy_loc, Pretyping.constr_in c)` ---> `Tacinterp.Value.of_constr c` - `Vernacexpr.HintsResolveEntry(priority, poly, hnf, path, atom)` ---> `Vernacexpr.HintsResolveEntry(Vernacexpr.({hint_priority = priority; hint_pattern = None}), poly, hnf, path, atom)` - `Pretyping.Termops.mem_named_context` ---> `Engine.Termops.mem_named_context_val` - `Global.named_context` ---> `Global.named_context_val` - `Context.Named.lookup` ---> `Environ.lookup_named_val` ### Search API The main search functions now take a function iterating over the results. This allows for clients to use streaming or more economic printing. ### XML Protocol - In several places, flat text wrapped in `` tags now appears as structured text inside `` tags. - The "errormsg" feedback has been replaced by a "message" feedback which contains `` tag, with a message_level attribute of "error". ## Changes between Coq 8.4 and Coq 8.5 ### Refactoring : more mli interfaces and simpler grammar.cma - A new directory intf/ now contains mli-only interfaces : * `Constrexpr` : definition of `constr_expr`, was in `Topconstr` * `Decl_kinds` : now contains `binding_kind = Explicit | Implicit` * `Evar_kinds` : type `Evar_kinds.t` was previously `Evd.hole_kind` * `Extend` : was `parsing/extend.mli` * `Genredexpr` : regroup `Glob_term.red_expr_gen` and `Tacexpr.glob_red_flag` * `Glob_term` : definition of `glob_constr` * `Locus` : definition of occurrences and stuff about clauses * `Misctypes` : `intro_pattern_expr`, `glob_sort`, `cast_type`, `or_var`, ... * `Notation_term` : contains `notation_constr`, was `Topconstr.aconstr` * `Pattern` : contains `constr_pattern` * `Tacexpr` : was `tactics/tacexpr.ml` * `Vernacexpr` : was `toplevel/vernacexpr.ml` - Many files have been divided : * vernacexpr: vernacexpr.mli + Locality * decl_kinds: decl_kinds.mli + Kindops * evd: evar_kinds.mli + evd * tacexpr: tacexpr.mli + tacops * glob_term: glob_term.mli + glob_ops + genredexpr.mli + redops * topconstr: constrexpr.mli + constrexpr_ops + notation_expr.mli + notation_ops + topconstr * pattern: pattern.mli + patternops * libnames: libnames (qualid, reference) + globnames (global_reference) * egrammar: egramml + egramcoq - New utility files : miscops (cf. misctypes.mli) and redops (cf genredexpr.mli). - Some other directory changes : * grammar.cma and the source files specific to it are now in grammar/ * pretty-printing files are now in printing/ - Inner-file changes : * aconstr is now notation_constr, all constructors for this type now start with a N instead of a A (e.g. NApp instead of AApp), and functions about aconstr may have been renamed (e.g. match_aconstr is now match_notation_constr). * occurrences (now in Locus.mli) is now an algebraic type, with - AllOccurrences instead of all_occurrences_expr = (false,[]) - (AllOccurrencesBut l) instead of (all_occurrences_expr_but l) = (false,l) - NoOccurrences instead of no_occurrences_expr = (true,[]) - (OnlyOccurrences l) instead of (no_occurrences_expr_but l) = (true,l) * move_location (now in Misctypes) has two new constructors MoveFirst and MoveLast replacing (MoveToEnd false) and (MoveToEnd true) - API of pretyping.ml and constrintern.ml has been made more uniform * Parametrization of understand_* functions is now made using "inference flags" * Functions removed: - interp_constr_judgment (inline its former body if really needed) - interp_casted_constr, interp_type: use instead interp_constr with expected_type set to OfType or to IsType - interp_gen: use any of interp_constr, interp_casted_constr, interp_type - interp_open_constr_patvar - interp_context: use interp_context_evars (with a "evar_map ref") and call solve_remaining_evars afterwards with a failing flag (e.g. all_and_fail_flags) - understand_type, understand_gen: use understand with appropriate parameters * Change of semantics: - Functions interp_*_evars_impls have a different interface and do not any longer check resolution of evars by default; use check_evars_are_solved explicitly to check that evars are solved. See also the corresponding commit log. - Tactics API: new_induct -> induction; new_destruct -> destruct; letin_pat_tac do not accept a type anymore - New file find_subterm.ml for gathering former functions `subst_closed_term_occ_modulo`, `subst_closed_term_occ_decl` (which now take and outputs also an `evar_map`), and `subst_closed_term_occ_modulo`, `subst_closed_term_occ_decl_modulo` (now renamed into `replace_term_occ_modulo` and `replace_term_occ_decl_modulo`). - API of Inductiveops made more uniform (see commit log or file itself). - API of intros_pattern style tactic changed; "s" is dropped in "intros_pattern" and "intros_patterns" is not anymore behaving like tactic "intros" on the empty list. - API of cut tactics changed: for instance, cut_intro should be replaced by "assert_after Anonymous" - All functions taking an env and a sigma (or an evdref) now takes the env first. ## Changes between Coq 8.3 and Coq 8.4 - Functions in unification.ml have now the evar_map coming just after the env - Removal of Tacinterp.constr_of_id Use instead either global_reference or construct_reference in constrintern.ml. - Optimizing calls to Evd functions Evars are split into defined evars and undefined evars; for efficiency, when an evar is known to be undefined, it is preferable to use specific functions about undefined evars since these ones are generally fewer than the defined ones. - Type changes in TACTIC EXTEND rules Arguments bound with tactic(_) in TACTIC EXTEND rules are now of type glob_tactic_expr, instead of glob_tactic_expr * tactic. Only the first component is kept, the second one can be obtained via Tacinterp.eval_tactic. - ARGUMENT EXTEND It is now forbidden to use TYPED simultaneously with {RAW,GLOB}_TYPED in ARGUMENT EXTEND statements. - Renaming of rawconstr to glob_constr The "rawconstr" type has been renamed to "glob_constr" for consistency. The "raw" in everything related to former rawconstr has been changed to "glob". For more details about the rationale and scripts to migrate code using Coq's internals, see commits 13743, 13744, 13755, 13756, 13757, 13758, 13761 (by glondu, end of December 2010) in Subversion repository. Contribs have been fixed too, and commit messages there might also be helpful for migrating. ## Changes between Coq 8.2 and Coq 8.3 ### Light cleaning in evaruil.ml whd_castappevar is now whd_head_evar obsolete whd_ise disappears ### Restructuration of the syntax of binders ``` binders_let -> binders binders_let_fixannot -> binders_fixannot binder_let -> closed_binder (and now covers only bracketed binders) binder was already obsolete and has been removed ``` ### Semantical change of h_induction_destruct Warning, the order of the isrec and evar_flag was inconsistent and has been permuted. Tactic induction_destruct in tactics.ml is unchanged. ### Internal tactics renamed There is no more difference between bindings and ebindings. The following tactics are therefore renamed ``` apply_with_ebindings_gen -> apply_with_bindings_gen left_with_ebindings -> left_with_bindings right_with_ebindings -> right_with_bindings split_with_ebindings -> split_with_bindings ``` and the following tactics are removed - apply_with_ebindings (use instead apply_with_bindings) - eapply_with_ebindings (use instead eapply_with_bindings) ### Obsolete functions in typing.ml For mtype_of, msort_of, mcheck, now use type_of, sort_of, check ### Renaming functions renamed ``` concrete_name -> compute_displayed_name_in concrete_let_name -> compute_displayed_let_name_in rename_rename_bound_var -> rename_bound_vars_as_displayed lookup_name_as_renamed -> lookup_name_as_displayed next_global_ident_away true -> next_ident_away_in_goal next_global_ident_away false -> next_global_ident_away ``` ### Cleaning in command.ml Functions about starting/ending a lemma are in lemmas.ml Functions about inductive schemes are in indschemes.ml Functions renamed: ``` declare_one_assumption -> declare_assumption declare_assumption -> declare_assumptions Command.syntax_definition -> Metasyntax.add_syntactic_definition declare_interning_data merged with add_notation_interpretation compute_interning_datas -> compute_full_internalization_env implicits_env -> internalization_env full_implicits_env -> full_internalization_env build_mutual -> do_mutual_inductive build_recursive -> do_fixpoint build_corecursive -> do_cofixpoint build_induction_scheme -> build_mutual_induction_scheme build_indrec -> build_induction_scheme instantiate_type_indrec_scheme -> weaken_sort_scheme instantiate_indrec_scheme -> modify_sort_scheme make_case_dep, make_case_nodep -> build_case_analysis_scheme make_case_gen -> build_case_analysis_scheme_default ``` Types: decl_notation -> decl_notation option ### Cleaning in libnames/nametab interfaces Functions: ``` dirpath_prefix -> pop_dirpath extract_dirpath_prefix pop_dirpath_n extend_dirpath -> add_dirpath_suffix qualid_of_sp -> qualid_of_path pr_sp -> pr_path make_short_qualid -> qualid_of_ident sp_of_syntactic_definition -> path_of_syntactic_definition sp_of_global -> path_of_global id_of_global -> basename_of_global absolute_reference -> global_of_path locate_syntactic_definition -> locate_syndef path_of_syntactic_definition -> path_of_syndef push_syntactic_definition -> push_syndef ``` Types: section_path -> full_path ### Cleaning in parsing extensions (commit 12108) Many moves and renamings, one new file (Extrawit, that contains wit_tactic). ### Cleaning in tactical.mli ``` tclLAST_HYP -> onLastHyp tclLAST_DECL -> onLastDecl tclLAST_NHYPS -> onNLastHypsId tclNTH_DECL -> onNthDecl tclNTH_HYP -> onNthHyp onLastHyp -> onLastHypId onNLastHyps -> onNLastDecls onClauses -> onClause allClauses -> allHypsAndConcl ``` and removal of various unused combinators on type "clause" ## Changes between Coq 8.1 and Coq 8.2 ### Datatypes List of occurrences moved from "int list" to "Termops.occurrences" (an alias to "bool * int list") ETIdent renamed to ETName ### Functions ``` Eauto: e_resolve_constr, vernac_e_resolve_constr -> simplest_eapply Tactics: apply_with_bindings -> apply_with_bindings_wo_evars Eauto.simplest_apply -> Hiddentac.h_simplest_apply Evarutil.define_evar_as_arrow -> define_evar_as_product Old version of Tactics.assert_tac disappears Tactics.true_cut renamed into Tactics.assert_tac Constrintern.interp_constrpattern -> intern_constr_pattern Hipattern.match_with_conjunction is a bit more restrictive Hipattern.match_with_disjunction is a bit more restrictive ``` ### Universe names (univ.mli) ```ocaml base_univ -> type0_univ (* alias of Set is the Type hierarchy *) prop_univ -> type1_univ (* the type of Set in the Type hierarchy *) neutral_univ -> lower_univ (* semantic alias of Prop in the Type hierarchy *) is_base_univ -> is_type1_univ is_empty_univ -> is_lower_univ ``` ### Sort names (term.mli) ``` mk_Set -> set_sort mk_Prop -> prop_sort type_0 -> type1_sort ``` ## Changes between Coq 8.0 and Coq 8.1 ### Functions - Util: option_app -> option_map - Term: substl_decl -> subst_named_decl - Lib: library_part -> remove_section_part - Printer: prterm -> pr_lconstr - Printer: prterm_env -> pr_lconstr_env - Ppconstr: pr_sort -> pr_rawsort - Evd: in_dom, etc got standard ocaml names (i.e. mem, etc) - Pretyping: - understand_gen_tcc and understand_gen_ltac merged into understand_ltac - type_constraints can now say typed by a sort (use OfType to get the previous behavior) - Library: import_library -> import_module ### Constructors * Declarations: mind_consnrealargs -> mind_consnrealdecls * NoRedun -> NoDup * Cast and RCast have an extra argument: you can recover the previous behavior by setting the extra argument to "CastConv DEFAULTcast" and "DEFAULTcast" respectively * Names: "kernel_name" is now "constant" when argument of Term.Const * Tacexpr: TacTrueCut and TacForward(false,_,_) merged into new TacAssert * Tacexpr: TacForward(true,_,_) branched to TacLetTac ### Modules * module Decl_kinds: new interface * module Bigint: new interface * module Tacred spawned module Redexpr * module Symbols -> Notation * module Coqast, Ast, Esyntax, Termast, and all other modules related to old syntax are removed * module Instantiate: integrated to Evd * module Pretyping now a functor: use Pretyping.Default instead ### Internal names OBJDEF and OBJDEF1 -> CANONICAL-STRUCTURE ### Tactic extensions * printers have an extra parameter which is a constr printer at high precedence * the tactic printers have an extra arg which is the expected precedence * level is now a precedence in declare_extra_tactic_pprule * "interp" functions now of types the actual arg type, not its encapsulation as a generic_argument ## Changes between Coq 7.4 and Coq 8.0 See files in dev/syntax-v8 ## Main changes between Coq 7.4 and Coq 8.0 ### Changes due to introduction of modules #### Kernel The module level has no effect on constr except for the structure of section_path. The type of unique names for constructions (what section_path served) is now called a kernel name and is defined by ```ocaml type uniq_ident = int * string * dir_path (* int may be enough *) type module_path = | MPfile of dir_path (* reference to physical module, e.g. file *) | MPbound of uniq_ident (* reference to a module parameter in a functor *) | MPself of uniq_ident (* reference to one of the containing module *) | MPdot of module_path * label type label = identifier type kernel_name = module_path * dir_path * label ^^^^^^^^^^^ ^^^^^^^^ ^^^^^ | | \ | | the base name | \ / the (true) section path example: (non empty only inside open sections) L = (* i.e. some file of logical name L *) struct module A = struct Def a = ... end end M = (* i.e. some file of logical name M *) struct Def t = ... N = functor (X : sig module T = struct Def b = ... end end) -> struct module O = struct Def u = ... end Def x := ... .t ... .O.u ... X.T.b ... L.A.a ``` and are self-references, X is a bound reference and L is a reference to a physical module. Notice that functor application is not part of a path: it must be named by a "module M = F(A)" declaration to be used in a kernel name. Notice that Jacek chose a practical approach, making directories not modules. Another approach could have been to replace the constructor MPfile by a constant constructor MProot representing the root of the world. Other relevant informations are in kernel/entries.ml (type module_expr) and kernel/declarations.ml (type module_body and module_type_body). #### Library 1. tables [Summaries] - the only change is the special treatment of the global environment. 2. objects [Libobject] declares persistent objects, given with methods: * cache_function specifying how to add the object in the current scope; * load_function, specifying what to do when the module containing the object is loaded; * open_function, specifying what to do when the module containing the object is opened (imported); * classify_function, specyfying what to do with the object, when the current module (containing the object) is ended. * subst_function * export_function, to signal end_section survival (Almost) Each of these methods is called with a parameter of type object_name = section_path * kernel_name where section_path is the full user name of the object (such as Coq.Init.Datatypes.Fst) and kernel_name is its substitutive internal version such as (MPself,[],"Fst") (see above) #### What happens at the end of an interactive module ? (or when a file is stored and reloaded from disk) All summaries (except Global environment) are reverted to the state from before the beginning of the module, and: 1. the objects (again, since last Declaremods.start_module or Library.start_library) are classified using the classify_function. To simplify consider only those who returned Substitute _ or Keep _. 2. If the module is not a functor, the subst_function for each object of the first group is called with the substitution [MPself "" |-> MPfile "Coq.Init.Datatypes"]. Then the load_function is called for substituted objects and the "keep" object. (If the module is a library the substitution is done at reloading). 3. The objects which returned substitute are stored in the modtab together with the self ident of the module, and functor argument names if the module was a functor. They will be used (substituted and loaded) when a command like Module M := F(N) or Module Z := N is evaluated #### The difference between "substitute" and "keep" objects 1. The "keep" objects can _only_ reference other objects by section_paths and qualids. They do not need the substitution function. They will work after end_module (or reloading a compiled library), because these operations do not change section_path's They will obviously not work after Module Z:=N. These would typically be grammar rules, pretty printing rules etc. 2. The "substitute" objects can _only_ reference objects by kernel_names. They must have a valid subst_function. They will work after end_module _and_ after Module Z:=N or Module Z:=F(M). Other kinds of objects: 3. "Dispose" - objects which do not survive end_module As a consequence, objects which reference other objects sometimes by kernel_names and sometimes by section_path must be of this kind... 4. "Anticipate" - objects which must be treated individually by end_module (typically "REQUIRE" objects) #### Writing subst_thing functions The subst_thing should not copy the thing if it hasn't actually changed. to help writing subst functions this way quickly and without errors. Also there are *_smartmap functions in Util. The subst_thing functions are already written for many types, including constr (Term.subst_mps), global_reference (Libnames.subst_global), rawconstr (Rawterm.subst_raw) etc They are all (apart from constr, for now) written in the non-copying way. #### Nametab Nametab has been made more uniform. For every kind of thing there is only one "push" function and one "locate" function. #### Lib library_segment is now a list of object_name * library_item, where object_name = section_path * kernel_name (see above) New items have been added for open modules and module types #### Declaremods Functions to declare interactive and noninteractive modules and module types. #### Library Uses Declaremods to actually communicate with Global and to register objects. ### Other changes Internal representation of tactics bindings has changed (see type Rawterm.substitution). New parsing model for tactics and vernacular commands - Introduction of a dedicated type for tactic expressions (Tacexpr.raw_tactic_expr) - Introduction of a dedicated type for vernac expressions (Vernacexpr.vernac_expr) - Declaration of new vernacular parsing rules by a new camlp4 macro GRAMMAR COMMAND EXTEND ... END to be used in ML files - Declaration of new tactics parsing/printing rules by a new camlp4 macro TACTIC EXTEND ... END to be used in ML files New organisation of THENS: - tclTHENS tac tacs : tacs is now an array - tclTHENSFIRSTn tac1 tacs tac2 : apply tac1 then, apply the array tacs on the first n subgoals and tac2 on the remaining subgoals (previously tclTHENST) - tclTHENSLASTn tac1 tac2 tacs : apply tac1 then, apply tac2 on the first subgoals and apply the array tacs on the last n subgoals - tclTHENFIRSTn tac1 tacs = tclTHENSFIRSTn tac1 tacs tclIDTAC (prev. tclTHENSI) - tclTHENLASTn tac1 tacs = tclTHENSLASTn tac1 tclIDTAC tacs - tclTHENFIRST tac1 tac2 = tclTHENFIRSTn tac1 [|tac2|] - tclTHENLAST tac1 tac2 = tclTHENLASTn tac1 [|tac2|] (previously tclTHENL) - tclTHENS tac1 tacs = tclTHENSFIRSTn tac1 tacs (fun _ -> error "wrong number") - tclTHENSV same as tclTHENS but with an array - tclTHENSi : no longer available Proof_type: subproof field in type proof_tree glued with the ref field Tacmach: no more echo from functions of module Refiner Files plugins/*/g_*.ml4 take the place of files plugins/*/*.v. Files parsing/{vernac,tac}extend.ml{4,i} implements TACTIC EXTEND andd VERNAC COMMAND EXTEND macros File syntax/PPTactic.v moved to parsing/pptactic.ml Tactics about False and not now in tactics/contradiction.ml Tactics depending on Init now tactics/*.ml4 (no longer in tactics/*.v) File tacinterp.ml moved from proofs to directory tactics ## Changes between Coq 7.1 and Coq 7.2 The core of Coq (kernel) has meen minimized with the following effects: - kernel/term.ml split into kernel/term.ml, pretyping/termops.ml - kernel/reduction.ml split into kernel/reduction.ml, pretyping/reductionops.ml - kernel/names.ml split into kernel/names.ml, library/nameops.ml - kernel/inductive.ml split into kernel/inductive.ml, pretyping/inductiveops.ml the prefixes "Is" ans "IsMut" have been dropped from kind_of_term constructors, e.g. IsRel is now Rel, IsMutCase is now Case, etc. rocq-9.2.0/dev/doc/critical-bugs.md000066400000000000000000001656751516144147600171200ustar00rootroot00000000000000Compilation of critical bugs in stable releases of Coq ====================================================== This file recollects knowledge about critical bugs found in Coq since version 8.0. ## Table of Contents - [Non fixed bugs](#non-fixed-bugs) - [buffer overflow on large records and closures (infinite loop with OCaml 5)](#buffer-overflow-on-large-records-and-closures-infinite-loop-with-ocaml-5) - [memory corruption by evaluating on ill-typed terms (obtained from unsafe tactics)](#memory-corruption-by-evaluating-on-ill-typed-terms-obtained-from-unsafe-tactics) - [kernel and checker accept incorrect name aliasing information](#kernel-and-checker-accept-incorrect-name-aliasing-information) - [coqchk checks too little about primitive declarations](#coqchk-checks-too-little-about-primitive-declarations) - [Print Assumptions + Parameter Inline fails to report some inconsistent flags](#print-assumptions-parameter-inline-fails-to-report-some-inconsistent-flags) - [Print Assumptions does not report Unset Universe Checking used during functor application](#print-assumptions-does-not-report-unset-universe-checking-used-during-functor-application) - [Fixed bugs](#fixed-bugs) - [Typing constructions](#typing-constructions) - [substitution missing in the body of a let](#substitution-missing-in-the-body-of-a-let) - [missing lift in checking guard](#missing-lift-in-checking-guard) - [de Bruijn indice bug in checking guard of nested cofixpoints](#de-bruijn-indice-bug-in-checking-guard-of-nested-cofixpoints) - [de Bruijn indice bug in computing allowed elimination principle](#de-bruijn-indice-bug-in-computing-allowed-elimination-principle) - [bug in Prop<=Set conversion which made Set identifiable with Prop, preventing a proof-irrelevant interpretation of Prop](#bug-in-propset-conversion-which-made-set-identifiable-with-prop-preventing-a-proof-irrelevant-interpretation-of-prop) - [incorrect abstraction of sort variables in relevance marks on opaque constants](#incorrect-abstraction-of-sort-variables-in-relevance-marks-on-opaque-constants) - [guard checker forgot to check non-structural arguments of fixpoint](#guard-checker-forgot-to-check-non-structural-arguments-of-fixpoint) - [guard checker incorrectly detects match on match as returning a subterm](#guard-checker-incorrectly-detects-match-on-match-as-returning-a-subterm) - [guard checker does incorrect reduction across inner fixpoint, accepting wrong fixpoints](#guard-checker-does-incorrect-reduction-across-inner-fixpoint-accepting-wrong-fixpoints) - [guard checker does not account for cross calls to compute uniform arguments of a nested mutual fixpoint](#guard-checker-does-not-account-for-cross-calls-to-compute-uniform-arguments-of-a-nested-mutual-fixpoint) - [guard checker does not check for correct recursive calls when passed as uniform argument in a nested fixpoint](#guard-checker-does-not-check-for-correct-recursive-calls-when-passed-as-uniform-argument-in-a-nested-fixpoint) - [guard checker does not count argument-less recursive calls to compute uniform arguments of a nested mutual fixpoint](#guard-checker-does-not-count-argument-less-recursive-calls-to-compute-uniform-arguments-of-a-nested-mutual-fixpoint) - [guard checker does not check arguments of recursive calls in uniformity analysis](#guard-checker-does-not-check-arguments-of-recursive-calls-in-uniformity-analysis) - [Module system](#module-system) - [missing universe constraints in typing "with" clause of a module type](#missing-universe-constraints-in-typing-with-clause-of-a-module-type) - [universe constraints for module subtyping not stored in vo files](#universe-constraints-for-module-subtyping-not-stored-in-vo-files) - [module subtyping disrespected squashing status of inductives](#module-subtyping-disrespected-squashing-status-of-inductives) - [Functor inlining drops universe substitution](#functor-inlining-drops-universe-substitution) - [Primitives are incorrectly considered convertible to anything by module subtyping](#primitives-are-incorrectly-considered-convertible-to-anything-by-module-subtyping) - [Missing substitution when strengthening functors](#missing-substitution-when-strengthening-functors) - [Missing substitution when strengthening aliased functors](#missing-substitution-when-strengthening-aliased-functors) - [Incorrect subtyping rule for universe polymorphic "with Definition".](#incorrect-subtyping-rule-for-universe-polymorphic-with-definition) - [Subtyping ignored elimination constraints](#subtyping-ignored-elimination-constraints) - [Universes](#universes) - [issue with two parameters in the same universe level](#issue-with-two-parameters-in-the-same-universe-level) - [universe polymorphism can capture global universes](#universe-polymorphism-can-capture-global-universes) - [template polymorphism not collecting side constraints on the universe level of a parameter](#template-polymorphism-not-collecting-side-constraints-on-the-universe-level-of-a-parameter) - [more template polymorphism missing constraints](#more-template-polymorphism-missing-constraints) - [universe constraints erroneously discarded when forcing an asynchronous proof containing delayed monomorphic constraints inside a universe polymorphic section](#universe-constraints-erroneously-discarded-when-forcing-an-asynchronous-proof-containing-delayed-monomorphic-constraints-inside-a-universe-polymorphic-section) - [Set+2 incorrectly simplified to Set+1](#set2-incorrectly-simplified-to-set1) - [variance inference for section universes ignored use of section universes in inductives and axioms defined before the inductive being inferred](#variance-inference-for-section-universes-ignored-use-of-section-universes-in-inductives-and-axioms-defined-before-the-inductive-being-inferred) - [Missing substitution for relevance of product domain in lazy](#missing-substitution-for-relevance-of-product-domain-in-lazy) - [Missing stack conversion for irrelevant-to-relevant match](#missing-stack-conversion-for-irrelevant-to-relevant-match) - [Incorrect discharge of sort polymorphic inductive squashing with section polymorphic sort](#incorrect-discharge-of-sort-polymorphic-inductive-squashing-with-section-polymorphic-sort) - [Missing universe substitution in primitive array instance in lazy](#missing-universe-substitution-in-primitive-array-instance-in-lazy) - [Double universe substitution in letins from indices in match return clause](#double-universe-substitution-in-letins-from-indices-in-match-return-clause) - [Primitive projections](#primitive-projections) - [check of guardedness of extra arguments of primitive projections missing](#check-of-guardedness-of-extra-arguments-of-primitive-projections-missing) - [records based on primitive projections became possibly recursive without the guard condition being updated](#records-based-on-primitive-projections-became-possibly-recursive-without-the-guard-condition-being-updated) - [incorrect checking of subtyping with algebraic universes](#incorrect-checking-of-subtyping-with-algebraic-universes) - [Conversion machines](#conversion-machines) - [the invariant justifying some optimization was wrong for some combination of sharing side effects](#the-invariant-justifying-some-optimization-was-wrong-for-some-combination-of-sharing-side-effects) - [collision between constructors when more than 256 constructors in a type](#collision-between-constructors-when-more-than-256-constructors-in-a-type) - [wrong universe constraints](#wrong-universe-constraints) - [missing pops in executing 31bit arithmetic](#missing-pops-in-executing-31bit-arithmetic) - [primitive integer emulation layer on 32 bits not robust to garbage collection](#primitive-integer-emulation-layer-on-32-bits-not-robust-to-garbage-collection) - [broken long multiplication primitive integer emulation layer on 32 bits](#broken-long-multiplication-primitive-integer-emulation-layer-on-32-bits) - [broken addmuldiv operation for large shifts](#broken-addmuldiv-operation-for-large-shifts) - [translation of identifier from Coq to OCaml was not bijective, leading to identify True and False](#translation-of-identifier-from-coq-to-ocaml-was-not-bijective-leading-to-identify-true-and-false) - [stuck primitive projections computed incorrectly by native_compute](#stuck-primitive-projections-computed-incorrectly-by-native_compute) - [incorrect De Bruijn handling when inferring the relevance mark for a lambda](#incorrect-de-bruijn-handling-when-inferring-the-relevance-mark-for-a-lambda) - [buffer overflow on large accumulators](#buffer-overflow-on-large-accumulators) - [buffer overflow, arbitrary code execution on floating-point operations](#buffer-overflow-arbitrary-code-execution-on-floating-point-operations) - [arbitrary code execution on irreducible PArray.set](#arbitrary-code-execution-on-irreducible-parrayset) - [arbitrary code execution on arrays of floating point numbers](#arbitrary-code-execution-on-arrays-of-floating-point-numbers) - [conversion of Prod / Prod values was comparing the wrong components](#conversion-of-prod-prod-values-was-comparing-the-wrong-components) - [Ξ·-expansion of cofixpoints was performed in the wrong environment](#-expansion-of-cofixpoints-was-performed-in-the-wrong-environment) - [conversion would compare the mutated version of primitive arrays instead of undoing mutation where needed](#conversion-would-compare-the-mutated-version-of-primitive-arrays-instead-of-undoing-mutation-where-needed) - [tactic code could mutate a global cache of values for section variables](#tactic-code-could-mutate-a-global-cache-of-values-for-section-variables) - [incorrect handling of universe polymorphism](#incorrect-handling-of-universe-polymorphism) - [Forgotten universe substitution with Register Inline on universe polymorphic definition](#forgotten-universe-substitution-with-register-inline-on-universe-polymorphic-definition) - [Side-effects](#side-effects) - [polymorphic side-effects inside monomorphic definitions incorrectly handled as not inlined](#polymorphic-side-effects-inside-monomorphic-definitions-incorrectly-handled-as-not-inlined) - [Section variables used in side effects not checked by Proof using](#section-variables-used-in-side-effects-not-checked-by-proof-using) - [Forgetting unsafe flags](#forgetting-unsafe-flags) - [unsafe typing flags used inside a section would not be reported by Print Assumptions after closing the section](#unsafe-typing-flags-used-inside-a-section-would-not-be-reported-by-print-assumptions-after-closing-the-section) - [Conflicts with axioms in library](#conflicts-with-axioms-in-library) - [axiom of description and decidability of equality on real numbers in library Reals was inconsistent with impredicative Set](#axiom-of-description-and-decidability-of-equality-on-real-numbers-in-library-reals-was-inconsistent-with-impredicative-set) - [guard condition was unknown to be inconsistent with propositional extensionality in library Sets](#guard-condition-was-unknown-to-be-inconsistent-with-propositional-extensionality-in-library-sets) - [incompatibility axiom of choice and excluded-middle with elimination of large singletons to Set](#incompatibility-axiom-of-choice-and-excluded-middle-with-elimination-of-large-singletons-to-set) - [Incorrect specification of PrimFloat.leb](#incorrect-specification-of-primfloatleb) - [Incorrect implementation of SFclassify.](#incorrect-implementation-of-sfclassify) - [nativenorm reading back closures as arbitrary floating-point values](#nativenorm-reading-back-closures-as-arbitrary-floating-point-values) - [guard condition issue made it inconsistent with propositional extensionality in library Sets](#guard-condition-issue-made-it-inconsistent-with-propositional-extensionality-in-library-sets) - [Deserialization](#deserialization) - [deserialization of .vo data not properly checked](#deserialization-of-vo-data-not-properly-checked) - [Probably non exploitable fixed bugs](#probably-non-exploitable-fixed-bugs) - [bug in 31bit arithmetic](#bug-in-31bit-arithmetic) ## Non fixed bugs #### buffer overflow on large records and closures (infinite loop with OCaml 5) - component: VM reduction machine - introduced: 8.1 - impacted versions: 8.1-NOW - impacted coqchk versions: none (no VM in coqchk) - fixed in: NONE - found by: Dolan, Roux, Melquiond - GH issue number: ocaml/ocaml#6385, rocq-prover/rocq#13439 - exploit: ?? - risk: requires very large number of arguments, fix block size or nested letins #### memory corruption by evaluating on ill-typed terms (obtained from unsafe tactics) - component: VM and native reduction machines - introduced: 8.1 - impacted versions: 8.1-NOW - impacted coqchk versions: none (no VM or native in coqchk) - fixed in: NONE - found by: GaΓ«tan Gilbert, Andres Erbsen - GH issue number: rocq-prover/rocq#16891 - exploit: requires a memory corruption to craft something that doesn't just SIGSEV - risk: could be activated by chance but unlikely to produce anything other than SIGSEV outside a deliberate attack #### kernel and checker accept incorrect name aliasing information - component: name handling / typechecker - introduced: a long time ago - impacted versions: -NOW - impacted coqchk versions: same - fixed in: NONE - found by: Pierre-Marie PΓ©drot - GH issue number: rocq-prover/rocq#7609 - exploit: see issue (requires a plugin or hand crafted .vo file) - risk: low #### coqchk checks too little about primitive declarations - component: primitive types and operators - introduced: v8.10 (#6914 primitive integers) - impacted versions: coqchk only - impacted coqchk versions: V8.10-NOW - fixed in: NONE - found by: GaΓ«tan Gilbert - GH issue number: rocq-prover/rocq#12439 - exploit: not fully worked out, requires crafted .vo file - risk: none (requires crafted .vo file) #### Print Assumptions + Parameter Inline fails to report some inconsistent flags - component: module functors - introduced: rocq-prover/rocq#79 - impacted versions: V8.6-NOW - impacted coqchk versions: none - found by: Jason Gross - GH issue number: rocq-prover/rocq#12155 - exploit: see issue - risk: moderate if not using coqchk, none if using coqchk (coqchk rejects the produced file) #### Print Assumptions does not report Unset Universe Checking used during functor application - component: module functors - introduced: v8.11 (#10291) or earlier - impacted versions: V8.11-NOW - impacted coqchk versions: none - found by: GaΓ«tan Gilbert - GH issue number: rocq-prover/rocq#16646 - exploit: see issue - risk: moderate if not using coqchk, none if using coqchk (coqchk rejects the produced file) ## Fixed bugs ### Typing constructions #### substitution missing in the body of a let - component: "match" - introduced: ? - impacted released versions: V8.3-V8.3pl2, V8.4-V8.4pl4 - impacted development branches: none - impacted coqchk versions: ? - fixed in: master/trunk/v8.5 ([e583a79b5](https://github.com/rocq-prover/rocq/commit/e583a79b5a0298fd08f34305cc876d5117913e95), 22 Nov 2015, Herbelin), v8.4 ([525056f1](https://github.com/rocq-prover/rocq/commit/525056f1a630426b78668ab583e228c25b492c35), 22 Nov 2015, Herbelin), v8.3 ([4bed0289](https://github.com/rocq-prover/rocq/commit/4bed0289d66e6e413ccdea7a33dc747c83bce92e), 22 Nov 2015, Herbelin) - found by: Herbelin - exploit: test-suite/success/Case22.v - GH issue number: ? - risk: ? #### missing lift in checking guard - component: fixpoint, guard - introduced: probably from V5.10 - impacted released versions: probably V5-V7, V8.0-V8.0pl4, V8.1-V8.1pl4 - impacted development branches: v8.0 ? - impacted coqchk versions: ? - fixed in: master/trunk/v8.2 ([ff45afa8](https://github.com/rocq-prover/rocq/commit/ff45afa83a9235cbe33af525b6b0c7985dc7e091), r11646, 2 Dec 2008, Barras), v8.1 ([f8e7f273](https://github.com/rocq-prover/rocq/commit/f8e7f273f2e6009c3c0f0eee47c33542a6fdf361), r11648, 2 Dec 2008, Barras) - found by: Barras - exploit: test-suite/failure/guard.v - GH issue number: none - risk: unprobable by chance #### de Bruijn indice bug in checking guard of nested cofixpoints - component: cofixpoint, guard - introduced: after V6.3.1, before V7.0 - impacted released versions: V8.0-V8.0pl4, V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2, V8.4-V8.4pl4 - impacted development branches: none - impacted coqchk versions: ? - fixed in: master ([9f81e2c36](https://github.com/rocq-prover/rocq/commit/9f81e2c360c2be764e71d21ed7c266ee6e8a88c5), 10 Apr 2014, DΓ©nΓ¨s), v8.4 ([f50ec9e7d](https://github.com/rocq-prover/rocq/commit/f50ec9e7dbd082c9a465aedda25427d93e12cabe), 11 Apr 2014, DΓ©nΓ¨s), v8.3 ([40c0fe7f4](https://github.com/rocq-prover/rocq/commit/40c0fe7f44b3c99bec5188e01197c8a77348a4ee), 11 Apr 2014, DΓ©nΓ¨s), v8.2 ([06d66df8c](https://github.com/rocq-prover/rocq/commit/06d66df8c713307625b1c40c054ca06c00ff74b3), 11 Apr 2014, DΓ©nΓ¨s), v8.1 ([977afae90](https://github.com/rocq-prover/rocq/commit/977afae90c4e2aa974232b0c664346db72aadaa3), 11 Apr 2014, DΓ©nΓ¨s), v8.0 ([f1d632992](https://github.com/rocq-prover/rocq/commit/f1d632992e33a74b30e79271bd3748d69c5a2152), 29 Nov 2015, Herbelin, backport) - found by: DΓ©nΓ¨s - exploit: ? - GH issue number: none ? - risk: ? #### de Bruijn indice bug in computing allowed elimination principle - component: inductive types, elimination principle - introduced: 23 May 2006, [9c2d70b](https://github.com/rocq-prover/rocq/commit/9c2d70b91341552e964979ba09d5823cc023a31c), r8845, Herbelin (part of template polymorphism) - impacted released versions: V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2, V8.4-V8.4pl4 - impacted development branches: none - impacted coqchk versions: ? - fixed in: master ([8a01c3685](https://github.com/rocq-prover/rocq/commit/8a01c36850353c1875383cbc788cec9c42590b57), 24 Jan 2014, DΓ©nΓ¨s), v8.4 ([8a01c3685](https://github.com/rocq-prover/rocq/commit/8a01c36850353c1875383cbc788cec9c42590b57), 25 Feb 2014, DΓ©nΓ¨s), v8.3 ([2b3cc4f85](https://github.com/rocq-prover/rocq/commit/2b3cc4f85cc134fe58c21d720851e275e6a77ea0), 25 Feb 2014, DΓ©nΓ¨s), v8.2 ([459888488](https://github.com/rocq-prover/rocq/commit/4598884884d6db00c485189e3a3b793b05814928), 25 Feb 2014, DΓ©nΓ¨s), v8.1 ([79aa20872](https://github.com/rocq-prover/rocq/commit/79aa208728420747a933f38b3aa101c92f4dcde0), 25 Feb 2014, DΓ©nΓ¨s) - found by: DΓ©nΓ¨s - exploit: see rocq-prover/rocq#3211 - GH issue number: rocq-prover/rocq#3211 - risk: ? #### bug in Prop<=Set conversion which made Set identifiable with Prop, preventing a proof-irrelevant interpretation of Prop - component: universe subtyping - introduced: V8.2 ([bba897d5f](https://github.com/rocq-prover/rocq/commit/bba897d5fd964bef0aa10102ef41cee1ac5fc3bb), 12 May 2008, Herbelin) - impacted released versions: V8.2-V8.2pl2 - impacted development branches: none - impacted coqchk versions: ? - fixed in: master/trunk ([679801](https://github.com/rocq-prover/rocq/commit/679801623c1f55d0081f952c2094c3572fa39d4f), r13450, 23 Sep 2010, Glondu), v8.3 ([309a53f2](https://github.com/rocq-prover/rocq/commit/309a53f2e1aa9b2a39654cf5fa23eb632a04c22f), r13449, 22 Sep 2010, Glondu), v8.2 (41ea5f08, r14263, 6 Jul 2011, Herbelin, backport) - found by: Georgi Guninski - exploit: test-suite/failure/prop_set_proof_irrelevance.v - GH issue number: none? - risk: ? #### incorrect abstraction of sort variables in relevance marks on opaque constants and lack of checking of relevance marks on constants in coqchk - component: sort polymorphism / proof irrelevance - introduced: V8.10 for the coqchk bug, V8.19 for the coqc bug - impacted released versions: V8.19.0 - impacted coqchk: versions: V8.10-V8.19.0 - fixed in: V8.19.1, V8.20 - found by: GaΓ«tan Gilbert - exploit / GH issue: [#18629](https://github.com/rocq-prover/rocq/issues/18629) - risk: low (requires specific plugin code unlikely to be found in non malicious plugin) #### guard checker forgot to check non-structural arguments of fixpoint - component: guard checking - introduced: V8.16 ([#15434](https://github.com/rocq-prover/rocq/pull/15434)) - impacted released versions: V8.16 to V9.0.0 - impacted coqchk versions: Same - fixed in: V9.0.1, V9.1.0 - found by: ccz181078 - exploit / GH issue: [#20413](https://github.com/rocq-prover/rocq/issues/20413) - risk: significant (bad terms may be generated by Program machinery) #### guard checker incorrectly detects match on match as returning a subterm - component: guard checking - introduced: V8.16 ([#15434](https://github.com/rocq-prover/rocq/pull/15434)) - impacted released versions: V8.16 to V9.0.0 - impacted coqchk versions: Same - fixed in: V9.0.1, V9.1.0 - found by: Yann Leray - exploit / GH issue: [#20455](https://github.com/rocq-prover/rocq/issues/20455) - risk: unknown (no development in CI was affected) #### guard checker does incorrect reduction across inner fixpoint, accepting wrong fixpoints - component: guard checking - introduced: V8.16 ([#15434](https://github.com/rocq-prover/rocq/pull/15434)) - impacted released versions: V8.16 to V9.0.0 - impacted coqchk versions: Same - fixed in: V9.0.1, V9.1.0 ([#20648](https://github.com/rocq-prover/rocq/issues/20648)) - found by: Yann Leray - exploit / GH issue: [#20555](https://github.com/rocq-prover/rocq/issues/20555) - risk: unknown (no development in CI was affected) #### guard checker does not account for cross calls to compute uniform arguments of a nested mutual fixpoint - component: guard checking - introduced: V8.20 ([#17986](https://github.com/rocq-prover/rocq/pull/17986)) - impacted released versions: V8.20, V9.0, V9.1 - impacted coqchk versions: Same - fixed in: V9.2.0 ([#21684](https://github.com/rocq-prover/rocq/pull/21684)) - found by: Tristan StΓ©rin - exploit / GH issue: [#21682](https://github.com/rocq-prover/rocq/issues/21682) - risk: unknown (no development in CI was affected) #### guard checker does not check for correct recursive calls when passed as uniform argument in a nested fixpoint - component: guard checking - introduced: V9.0.1, V9.1.0 ([#20648](https://github.com/rocq-prover/rocq/issues/20648), see 2 above) - impacted released versions: V9.0.1, V9.1.0, V9.1.1 - impacted coqchk versions: Same - fixed in: V9.2.0 ([#21684](https://github.com/rocq-prover/rocq/pull/21684)) - found by: Tristan StΓ©rin - exploit / GH issue: [#21683](https://github.com/rocq-prover/rocq/issues/21683) - risk: unknown (no development in CI was affected) #### guard checker does not count argument-less recursive calls to compute uniform arguments of a nested mutual fixpoint - component: guard checking - introduced: V8.20 ([#17986](https://github.com/rocq-prover/rocq/pull/17986)) - impacted released versions: V8.20, V9.0, V9.1 - impacted coqchk versions: Same - fixed in: V9.2.0 ([#21684](https://github.com/rocq-prover/rocq/pull/21684)) - found by: Tristan StΓ©rin - exploit / GH issue: [#21701](https://github.com/rocq-prover/rocq/issues/21701) - risk: unknown (no development in CI was affected) #### guard checker does not check arguments of recursive calls in uniformity analysis - component: guard checking - introduced: V8.20 ([#17986](https://github.com/rocq-prover/rocq/pull/17986)) - impacted released versions: V8.20, V9.0, V9.1 - impacted coqchk versions: Same - fixed in: V9.2.0 ([#21798](https://github.com/rocq-prover/rocq/pull/21798)) - found by: Pierre-Marie PΓ©drot - exploit / GH issue: [#21797](https://github.com/rocq-prover/rocq/issues/21797) - risk: unknown (no development in CI was affected) ### Module system #### missing universe constraints in typing "with" clause of a module type - component: modules, universes - introduced: ? - impacted released versions: V8.3-V8.3pl2, V8.4-V8.4pl6; unclear for V8.2 and previous versions - impacted development branches: none - impacted coqchk versions: ? - fixed in: master/trunk ([d4869e059](https://github.com/rocq-prover/rocq/commit/d4869e059bfb73d99e1f5ef1b0a1f0906fa27056), 2 Oct 2015, Sozeau), v8.4 ([40350ef3b](https://github.com/rocq-prover/rocq/commit/40350ef3b34b0be9d5ceddde772218c2f2dafe32), 9 Sep 2015, Sozeau) - found by: DΓ©nΓ¨s - exploit: test-suite/bugs/bug_4294.v - GH issue number: rocq-prover/rocq#4294 - risk: ? #### universe constraints for module subtyping not stored in vo files - component: modules, universes - introduced: presumably 8.2 ([b3d3b56](https://github.com/rocq-prover/rocq/commit/b3d3b566c5b5f34ab518c587f62530abde131be8)) - impacted released versions: 8.2, 8.3, 8.4 - impacted development branches: v8.5 - impacted coqchk versions: none - fixed in: v8.2 ([c1d9889](https://github.com/rocq-prover/rocq/commit/c1d988904483eb1f3a8917ea08fced1240e3844b)), v8.3 (8056d02), v8.4 ([a07deb4](https://github.com/rocq-prover/rocq/commit/a07deb4eac1d5f886159784ef5d8d006892be547)), trunk ([0cd0a3e](https://github.com/rocq-prover/rocq/commit/0cd0a3ecdc7f942da153c59369ca3572bd18dd10)) Mar 5, 2014, Tassi - found by: Tassi by running coqchk on the mathematical components library - exploit: requires multiple files, no test provided - GH issue number: rocq-prover/rocq#3243 - risk: could be exploited by mistake #### module subtyping disrespected squashing status of inductives - component: modules, universes, inductives - introduced: probably 7.4 ([1296520](https://github.com/rocq-prover/rocq/commit/12965209478bd99dfbe57f07d5b525e51b903f22)) - impacted released versions: until 8.15.0 - impacted coqchk versions: none - fixed in: 8.15.1, 8.16 - found by: PΓ©drot - exploit: see GitHub issue - GH issue number: rocq-prover/rocq#15838 - risk: unlikely (caught by coqchk, needs Unset Elimination Schemes in the module type) #### Functor inlining drops universe substitution - component: Modules - introduced: ? - impacted released versions: ??-V8.8.0 - impacted coqchk versions: same? not sure if coqchk has a this bug - fixed in: V8.8.1, V8.9.0 (#7616) - found by: Pierre-Marie PΓ©drot - GH issue number: rocq-prover/rocq#7615 - exploit: see issue - risk: medium #### Primitives are incorrectly considered convertible to anything by module subtyping - component: modules, primitive types - introduced: 8.11 - impacted released versions: V8.11.0-V8.18.0 - impacted coqchk versions: same - fixed in: V8.19.0 - found by: GaΓ«tan Gilbert - GH issue number: rocq-prover/rocq#18503 - exploit: see issue - risk: high if there is a Primitive in a Module Type, otherwise low #### Missing substitution when strengthening functors - component: modules - introduced: 8.5 for the kernel (c5b699f), 8.10 for the checker (#8773) - impacted released versions: 8.5-9.0.0 - impacted coqchk version: 8.10-9.0.0 - fixed in: V9.0.1 - found by: Pierre-Marie PΓ©drot - GH issue number: rocq-prover/rocq#21051 - exploit: see issue - risk: could be exploited by mistake when using heavy module machinery #### Missing substitution when strengthening aliased functors - component: modules - introduced: 8.5 for the kernel (c5b699f), 8.10 for the checker (#8773) - impacted released versions: 8.5-9.1 - impacted coqchk version: 8.10-9.1 - fixed in: V9.2.0 - found by: Tristan StΓ©rin - GH issue number: rocq-prover/rocq#21685 - exploit: see issue - risk: could be exploited by mistake when using heavy module machinery #### Incorrect subtyping rule for universe polymorphic "with Definition". - component: modules - introduced: 8.5 - impacted released versions: 8.5-9.1 - impacted coqchk version: none - fixed in: V9.2.0 - found by: Tristan StΓ©rin - GH issue number: rocq-prover/rocq#21702 - exploit: see issue - risk: moderate, requires uncommon features #### Subtyping ignored elimination constraints - component: modules, sort polymorphism - introduced: V9.2+rc1 - impacted released versions: none - impacted coqchk versions: none - fixed in: V9.2.0 - found by: Yann Leray - GH issue number: rocq-prover/rocq#21750 - exploit: see issue - risk: high when combining module subyping with sort polymorphism (but not possible in non-rc version) ### Universes #### issue with two parameters in the same universe level - component: template polymorphism - introduced: 23 May 2006, [9c2d70b](https://github.com/rocq-prover/rocq/commit/9c2d70b91341552e964979ba09d5823cc023a31c), r8845, Herbelin - impacted released versions: V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2 - impacted development branches: none - impacted coqchk versions: ? - fixed in: trunk/master/v8.4 ([8082d1faf](https://github.com/rocq-prover/rocq/commit/8082d1faf85a0ab29f6c144a137791902a4e9c1f), 5 Oct 2011, Herbelin), V8.3pl3 ([bb582bca2](https://github.com/rocq-prover/rocq/commit/bb582bca2ca3fd94df01aad8d8070f8d129b25b3), 5 Oct 2011, Herbelin), v8.2 branch ([3333e8d3](https://github.com/rocq-prover/rocq/commit/3333e8d3387b3bc4d3ceb75aad853f8e455af444), 5 Oct 2011, Herbelin), v8.1 branch ([a8fc2027](https://github.com/rocq-prover/rocq/commit/a8fc2027258e1fb2defd05344e1249374f6e4e19), 5 Oct 2011, Herbelin), - found by: Barras - exploit: test-suite/failure/inductive.v - GH issue number: none - risk: unlikely to be activated by chance #### universe polymorphism can capture global universes - component: universe polymorphism - impacted released versions: V8.5 to V8.8 - impacted coqchk versions: V8.5 to V8.9 - fixed in: [ec4aa4971f](https://github.com/rocq-prover/rocq/commit/ec4aa4971f7789eeccec2f38f2bb7ec976f87ede) ([58e1d0f200](https://github.com/rocq-prover/rocq/commit/58e1d0f2006f3243cbf7b57a9858f5119ffea666) for the checker) - found by: GaΓ«tan Gilbert - exploit: test-suite/misc/poly-capture-global-univs - GH issue number: rocq-prover/rocq#8341 - risk: unlikely to be activated by chance (requires a plugin) #### template polymorphism not collecting side constraints on the universe level of a parameter this is a general form of the previous issue about template polymorphism exploiting other ways to generate untracked constraints - component: template polymorphism - introduced: morally at the introduction of template polymorphism, 23 - May 2006, [9c2d70b](https://github.com/rocq-prover/rocq/commit/9c2d70b91341552e964979ba09d5823cc023a31c), r8845, Herbelin - impacted released versions: at least V8.4-V8.4pl6, V8.5-V8.5pl3, V8.6-V8.6pl2, V8.7.0-V8.7.1, V8.8.0-V8.8.1, V8.9.0-V8.9.1, in theory also V8.1-V8.1pl4, V8.2-V8.2pl2, V8.3-V8.3pl2 but not exploit found there yet (an exploit using a plugin to force sharing of universe level is in principle possible though) - impacted development branches: all from 8.4 to 8.9 at the time of writing and suspectingly also all from 8.1 to 8.4 if a way to create untracked constraints can be found - impacted coqchk versions: a priori all (tested with V8.4 and V8.9 which accept the exploit) - fixed in: V8.10.0 ([eb3f8225a2](https://github.com/rocq-prover/rocq/commit/eb3f8225a286aef3a57ad876584b4a927241ff69), PR rocq-prover/rocq#9918, Aug 2019, DΓ©nΓ¨s and Sozeau) - found by: Gilbert using explicit sharing of universes, exploit found for 8.5-8.9 by PΓ©drot, other variants generating sharing using sections, or using ltac tricks by Sozeau, exploit in 8.4 by Herbelin and Jason Gross by adding new tricks to Sozeau's variants - exploit: test-suite/failure/Template.v - GH issue number: rocq-prover/rocq#9294 - risk: moderate risk to be activated by chance #### more template polymorphism missing constraints using the same universe in the parameters and the constructor arguments of a template polymorphic inductive (using named universes in modern Coq, or unification tricks in older Coq) produces implicit equality constraints not caught by the previous template polymorphism fix. - component: template polymorphism - introduced: same as the previous template polymorphism bug, morally from V8.1, first verified impacted version V8.5 (the universe unification is sufficiently different in V8.4 to prevent our trick from working) - fixed in: expected in 8.10.2, 8.11+beta, master (#11128, Nov 2019, Gilbert) - found by: Gilbert - exploit: test-suite/bugs/bug_11039.v - GH issue number: rocq-prover/rocq#11039 - risk: moderate risk (found by investigating rocq-prover/rocq#10504) #### universe constraints erroneously discarded when forcing an asynchronous proof containing delayed monomorphic constraints inside a universe polymorphic section - component: universe polymorphism, asynchronous proofs - introduced: between 8.4 and 8.5 by merging the asynchronous proofs feature branch and universe polymorphism one - impacted released versions: V8.5-V8.10 - impacted development branches: none - impacted coqchk versions: immune - fixed in: rocq-prover/rocq#10664 - found by: PΓ©drot - exploit: no test - GH issue number: none - risk: unlikely to be triggered in interactive mode, not present in batch mode (i.e. coqc) #### Set+2 incorrectly simplified to Set+1 - component: algebraic universes - introduced: V8.10 (with the SProp commit [7550876976](https://github.com/rocq-prover/rocq/commit/75508769762372043387c67a9abe94e8f940e80a)) - impacted released versions: V8.10.0 V8.10.1 V8.10.2 - impacted coqchk versions: same - fixed in: rocq-prover/rocq#11422 - found by: Gilbert - exploit: see PR (custom application of Hurkens to get around the refreshing at elaboration) - GH issue number: see PR - risk: unlikely to be triggered through the vernacular (the system "refreshes" algebraic universes such that +2 increments do not appear), mild risk from plugins which manipulate algebraic universes. #### variance inference for section universes ignored use of section universes in inductives and axioms defined before the inductive being inferred - component: cumulative inductives and sections - introduced: V8.12 ([73c3b87463](https://github.com/rocq-prover/rocq/commit/73c3b874633d6f6f8af831d4a37d0c1ae52575bc)) - impacted released versions: V8.12 to V8.15 including patch releases - impacted coqchk versions: none - fixed in: V8.16 rocq-prover/rocq#15950 ([118ffbc010](https://github.com/rocq-prover/rocq/commit/118ffbc010ce53ebd45baa42edd28335301ca9a5)) - found by: Gilbert and PΓ©drot - exploit: see rocq-prover/rocq#15916 - risk: could be used inadvertently in developments with complex universe usage, only when using cumulative inductives declared in sections. coqchk still works. #### Missing substitution for relevance of product domain in lazy - component: lazy reduction, sort polymorphism - introduced: V8.19 (with sort polymorphism, [1e7473812cec](https://github.com/rocq-prover/rocq/commit/1e7473812cec6e735394ca5f5fbefb9c78600893)) - impacted released versions: V8.19 to V9.1 including patch releases - impacted coqchk versions: same - fixed in: V9.2 [rocq-prover/rocq#21697](https://github.com/rocq-prover/rocq/pull/21697) - found by: Tristan StΓ©rin, GaΓ«tan Gilbert - exploit: not fully worked out, see bug_21691.v for example error - risk: low (needs sort polymorphism and to exploit the incorrect substitution from a reduction done by the kernel instead of in the higher layers) #### Missing stack conversion for irrelevant-to-relevant match - component: conversion, SProp - introduced: V8.16 ([57081c1ae01a](https://github.com/rocq-prover/rocq/commit/57081c1ae01a742033dec44a2a42bffa08a9f5af)) (V8.13 with the introduction of Definitional UIP for the Definitional UIP variant) - impacted released versions: V8.16 to V9.1 including patch releases (V8.13 to V9.1 for Definitional UIP variant) - impacted coqchk versions: same - fixed in: V9.2 [rocq-prover/rocq#21696](https://github.com/rocq-prover/rocq/pull/21696) - found by: Tristan StΓ©rin, GaΓ«tan Gilbert - exploit: see bug_21690.v - risk: without Definitional UIP, believed to only contradict axioms incompatible with equality reflection (i.e. no axiom-free proof of False). With Definitional UIP, could be used inadvertently. #### Incorrect discharge of sort polymorphic inductive squashing with section polymorphic sort - component: sections, sort polymorphism - introduced: V9.1 ([0706a177b5cb](https://github.com/rocq-prover/rocq/commit/0706a177b5cb4c829108ec8953d6087161ddb8b4)) - impacted released versions: V9.1 including patch releases - impacted coqchk versions: none - fixed in: V9.2 [rocq-prover/rocq#21699](https://github.com/rocq-prover/rocq/pull/21699) - found by: Tristan StΓ©rin, GaΓ«tan Gilbert - exploit: bug_21694.v - risk: needs a sort polymorphic inductive declared in a section with a section polymorphic sort and sort polymorphism in the inductive command (cf bug file) #### Missing universe substitution in primitive array instance in lazy - component: lazy, primitive arrays - introduced: V8.17 ([2db83c8a7e5b](https://github.com/rocq-prover/rocq/commit/2db83c8a7e5b823d2c8d25ef07dac40b38408d3c)) - impacted released versions: V8.17 to V9.1 including patch releases - impacted coqchk versions: same - fixed in: V9.2 [rocq-prover/rocq#21698](https://github.com/rocq-prover/rocq/pull/21698) - found by: Tristan StΓ©rin, GaΓ«tan Gilbert - exploit: not fully worked out, see bug_21692.v for example error - risk: low, the instance on primitive array literals is irrelevant for conversion #### Double universe substitution in letins from indices in match return clause - component: conversion - introduced: V8.14 ([d72e5c154f](https://github.com/rocq-prover/rocq/commit/d72e5c154faeea1d55387bc8c039d97f63ebd1c4)) - impacted released versions: V8.14 to V9.1 including patch releases - impacted coqchk versions: same - fixed in: V9.2 [rocq-prover/rocq#21688](https://github.com/rocq-prover/pull/21688) - found by: GaΓ«tan Gilbert - exploit: no full exploit known, anomaly in bug_21689.v - risk: low (needs to use universe substitution in letin from the inductive indices to incorrectly convert match return clauses and somehow derive inconsistency from there) ### Primitive projections #### check of guardedness of extra arguments of primitive projections missing - component: primitive projections, guard condition - introduced: 6 May 2014, [a4043608f](https://github.com/rocq-prover/rocq/commit/a4043608f704f026de7eb5167a109ca48e00c221), Sozeau - impacted released versions: V8.5-V8.5pl2, - impacted development branches: none - impacted coqchk versions: ? - fixed in: trunk/master/v8.5 ([ba00867d5](https://github.com/rocq-prover/rocq/commit/ba00867d515624aee734d998bfbe3880f559d907), 25 Jul 2016, Sozeau) - found by: Sozeau, by analyzing bug report rocq-prover/rocq#4876 - exploit: to be done (?) - GH issue number: rocq-prover/rocq#4876 - risk: consequence of bug found by chance, unlikely to be exploited by chance (MS?) #### records based on primitive projections became possibly recursive without the guard condition being updated - component: primitive projections, guard condition - introduced: 10 Sep 2014, [6624459e4](https://github.com/rocq-prover/rocq/commit/6624459e492164b3d189e3518864379ff985bf8c), Sozeau (?) - impacted released versions: V8.5 - impacted development branches: none - impacted coqchk versions: ? - fixed in: trunk/master/v8.5 ([120053a50](https://github.com/rocq-prover/rocq/commit/120053a50f87bd53398eedc887fa5e979f56f112), 4 Mar 2016, DΓ©nΓ¨s) - found by: DΓ©nΓ¨s exploiting bug rocq-prover/rocq#4588 - exploit: test-suite/bugs/bug_4588.v - GH issue number: rocq-prover/rocq#4588 - risk: ? #### incorrect checking of subtyping with algebraic universes - component: modules and universes - introduced: a long time ago - impacted released versions: ??-V8.8.0 - impacted coqchk versions: same - fixed in: V8.8.1, V8.9.0 (#7798) - found by: GaΓ«tan Gilbert - GH issue number: rocq-prover/rocq#7695 - exploit: see issue - risk: needs usage of explicit algebraic universe annotations, coqchk may catch through defunctorialization ### Conversion machines #### the invariant justifying some optimization was wrong for some combination of sharing side effects - component: "lazy machine" (lazy krivine abstract machine) - introduced: prior to V7.0 - impacted released versions: V8.0-V8.0pl4, V8.1-V8.1pl3 - impacted development branches: none - impacted coqchk versions: ([eefe63d52](https://github.com/rocq-prover/rocq/commit/eefe63d523b1b4c1b855e0f18e2574f98ff4ae64), Barras, 20 May 2008), was in beta-development for 8.2 at this time - fixed in: master/trunk/8.2 ([f13aaec57](https://github.com/rocq-prover/rocq/commit/f13aaec57df12380323edf450aec14c372422d58) / [a8b034513](https://github.com/rocq-prover/rocq/commit/a8b034513e0c03ceb7e154949b15f62ac6862f3b), 15 May 2008, Barras), v8.1 ([e7611477a](https://github.com/rocq-prover/rocq/commit/e7611477a0a0d1b7e8c233330def46a066985cdc), 15 May 2008, Barras), v8.0 ([6ed40a8bc](https://github.com/rocq-prover/rocq/commit/6ed40a8bc000b0419f3f4731bf83d05ab5062e76), 29 Nov 2016, Herbelin, backport) - found by: Gonthier - exploit: by Gonthier - GH issue number: none - risk: unrealistic to be exploited by chance #### collision between constructors when more than 256 constructors in a type - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: V8.1 - impacted released versions: V8.1-V8.5pl3, V8.2-V8.2pl2, V8.3-V8.3pl3, V8.4-V8.4pl5 - impacted development branches: none - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: master/trunk/v8.5 ([00894adf6](https://github.com/rocq-prover/rocq/commit/00894adf6fc11f4336a3ece0c347676bbf0b4c11) / [596a4a525](https://github.com/rocq-prover/rocq/commit/596a4a5251cc50f50bd6d25e36c81341bf65cfed), 26-39 Mar 2015, GrΓ©goire), v8.4 ([cd2101a39](https://github.com/rocq-prover/rocq/commit/cd2101a39b3b8d58ce569761c905a5baf1dcdc86), 1 Apr 2015, GrΓ©goire), v8.3 ([a0c7fc05b](https://github.com/rocq-prover/rocq/commit/a0c7fc05b302e38a2869c20f6db1dc376cdb59da), 1 Apr 2015, GrΓ©goire), v8.2 ([2c6189f61](https://github.com/rocq-prover/rocq/commit/2c6189f61b85bbe1a2a56754c9effc2d7a72f16d), 1 Apr 2015, GrΓ©goire), v8.1 ([bb877e5b5](https://github.com/rocq-prover/rocq/commit/bb877e5b54678bc34e4362fcf0315224e7c4f4cc), 29 Nov 2015, Herbelin, backport) - found by: DΓ©nΓ¨s, PΓ©drot - exploit: test-suite/bugs/bug_4157.v - GH issue number: rocq-prover/rocq#4157 - risk: #### wrong universe constraints - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: possibly exploitable from V8.1; exploitable at least from V8.5 - impacted released versions: V8.1-V8.4pl5 unknown, V8.5-V8.5pl3, V8.6-V8.6.1, V8.7.0-V8.7.1 - impacted development branches: unknown for v8.1-v8.4, none from v8.5 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: master ([c9f3a6cbe](https://github.com/rocq-prover/rocq/commit/c9f3a6cbe5c410256fe88580019f5c7183bab097), 12 Feb 2018, rocq-prover/rocq#6713, DΓ©nΓ¨s), v8.7 ([c058a4182](https://github.com/rocq-prover/rocq/commit/c058a4182b39460ba2b256c479a1389216c25ca9), 15 Feb 2018, Zimmermann, backport), v8.6 ([a2cc54c64](https://github.com/rocq-prover/rocq/commit/a2cc54c649c0b13190268cc5d490342d5f0cec10), 21 Feb 2018, Herbelin, backport), v8.5 ([d4d550d0f](https://github.com/rocq-prover/rocq/commit/d4d550d0f1ae5f4a8d29bbcdf991a2526ab555a6), 21 Feb 2018, Herbelin, backport) - found by: DΓ©nΓ¨s - exploit: test-suite/bugs/bug_6677.v - GH issue number: rocq-prover/rocq#6677 - risk: #### missing pops in executing 31bit arithmetic - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: V8.5 - impacted released versions: V8.1-V8.4pl5 - impacted development branches: v8.1 (probably) - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: master/trunk/v8.5 ([a5e04d9dd](https://github.com/rocq-prover/rocq/commit/a5e04d9dd178b2870b79776e1fbf1a858cdac49d), 6 Sep 2015, DΓ©nΓ¨s), v8.4 ([d5aa3bf6](https://github.com/rocq-prover/rocq/commit/d5aa3bf6fc7382e31b6f1bac58b644843d783f13), 9 Sep 2015, DΓ©nΓ¨s), v8.3 ([5da5d751](https://github.com/rocq-prover/rocq/commit/5da5d751c92df23ff3f42a04061960b287a4d3ea), 9 Sep 2015, DΓ©nΓ¨s), v8.2 ([369e82d2](https://github.com/rocq-prover/rocq/commit/369e82d2cdcd0d66d0c474dc1d062a4fc62aa24a), 9 Sep 2015, DΓ©nΓ¨s), - found by: Catalin Hritcu - exploit: lost? - GH issue number: ? - risk: #### primitive integer emulation layer on 32 bits not robust to garbage collection - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: master (before v8.10 in GH pull request rocq-prover/rocq#6914) - impacted released versions: none - impacted development branches: v8.10 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: [5914313](https://github.com/rocq-prover/rocq/commit/591431312465291e85fb352a69e947eedeb2e199) (v8.10) - found by: Roux, Melquiond - exploit: - GH issue number: rocq-prover/rocq#9925 - risk: #### broken long multiplication primitive integer emulation layer on 32 bits - component: all 3 kernel conversion machines (lazy, VM, native) - introduced: [e43b176](https://github.com/rocq-prover/rocq/commit/e43b1768d0f8399f426b92f4dfe31955daceb1a4) - impacted released versions: 8.10.0, 8.10.1, 8.10.2 - impacted development branches: 8.11 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: [4e176a7](https://github.com/rocq-prover/rocq/commit/4e176a7ee4660d505321ca55c5ce70a6c3d50d3b) - found by: Soegtrop, Melquiond - exploit: test-suite/bugs/bug_11321.v - GH issue number: rocq-prover/rocq#11321 - risk: critical, as any BigN computation on 32-bit architectures is wrong #### broken addmuldiv operation for large shifts - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - impacted released versions: 8.10 to 8.19 - impacted development branches: 8.20 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: [bc0adb4](https://github.com/rocq-prover/rocq/commit/bc0adb41a7c311f8d8305839c19e4812ff602720) - found by: Martin Karup Jensen - GH issue number: rocq-prover/rocq#19402 - risk: could be exploited by chance (though not in BigNums) #### translation of identifier from Coq to OCaml was not bijective, leading to identify True and False For instance `Ξ±` and `__U03b1_` were the same in the native compiler. - component: "native" conversion machine (translation to OCaml which compiles to native code) - introduced: V8.5 - impacted released versions: V8.5-V8.5pl1 - impacted development branches: none - impacted coqchk versions: none (no native computation in coqchk) - fixed in: master/trunk/v8.6 ([244d7a9aa](https://github.com/rocq-prover/rocq/commit/244d7a9aafe7ad613dd2095ca3126560cb3ea1d0), 19 May 2016, letouzey), v8.5 ([088b3161c](https://github.com/rocq-prover/rocq/commit/088b3161c93e46ec2d865fe71a206cee15acd30c), 19 May 2016, letouzey), - found by: Letouzey, DΓ©nΓ¨s - exploit: see commit message for [244d7a9aa](https://github.com/rocq-prover/rocq/commit/244d7a9aafe7ad613dd2095ca3126560cb3ea1d0) - GH issue number: ? - risk: #### stuck primitive projections computed incorrectly by native_compute - component: primitive projections, native_compute - introduced: 1 Jun 2018, [e1e7888a](https://github.com/rocq-prover/rocq/commit/e1e7888ac4519f4b7470cc8469f9fd924514e352), ppedrot - impacted released versions: 8.9.0 - impacted coqchk versions: none - fixed in: 8.9.1 rocq-prover/rocq#9900 - found by: maximedenes exploiting bug rocq-prover/rocq#9684 - exploit: test-suite/bugs/bug_9684.v - GH issue number: rocq-prover/rocq#9684 #### incorrect De Bruijn handling when inferring the relevance mark for a lambda - component: lazy machine - introduced: 2019-03-15, [23f84f37c6](https://github.com/rocq-prover/rocq/commit/23f84f37c674a07e925925b7e0d50d7ee8414093) and [71b9ad8526](https://github.com/rocq-prover/rocq/commit/71b9ad8526155020c8451dd326a52e391a9a8585), SkySkimmer - impacted released versions: 8.10.0 - impacted coqchk versions: 8.10.0 - fixed in: 8.10.1 rocq-prover/rocq#10904 - found by: ppedrot investigating unexpected conversion failures with SProp - exploit: test-suite/bugs/bug_10904.v - GH issue number: rocq-prover/rocq#10904 - risk: none without using -allow-sprop (off by default in 8.10.0), otherwise could be exploited by mistake #### buffer overflow on large accumulators - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: 8.1 - impacted released versions: 8.1-8.12.1 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: 8.13.0 (#13431) - found by: Dolan, Roux, Melquiond - GH issue number: ocaml/ocaml#6385, rocq-prover/rocq#11170 - risk: medium, as it can happen for large irreducible applications #### buffer overflow, arbitrary code execution on floating-point operations - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: 8.13 - impacted released versions: 8.13.0 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: 8.13.1 - found by: Melquiond - GH issue number: rocq-prover/rocq#13867 - risk: none, unless using floating-point operations; high otherwise; noticeable if activated by chance, since it usually breaks control-flow integrity #### arbitrary code execution on irreducible PArray.set - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: 8.13 - impacted released versions: 8.13.0, 8.13.1 - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: 8.13.2 - found by: Melquiond - GH issue number: rocq-prover/rocq#13998 - risk: none, unless using primitive array operations; systematic otherwise #### arbitrary code execution on arrays of floating point numbers - component: "virtual" and "native" conversion machines - introduced: 8.13 - impacted released versions: 8.13.0, 8.13.1, 8.14.0 - impacted coqchk versions: none (no VM / native computation in coqchk) - fixed in: 8.14.1 - found by: Melquiond - GH issue number: rocq-prover/rocq#15070 - risk: none, unless mixing open terms and primitive floats inside primitive - arrays; critical otherwise #### conversion of Prod / Prod values was comparing the wrong components - component: "native" conversion machine (translation to OCaml which compiles to native code) - introduced: V8.5 - impacted released versions: V8.5-V8.16.0 (when built with native computation enabled) - impacted coqchk versions: none (no native computation in coqchk) - fixed in: 8.16.1 - found by: Melquiond - GH issue number: rocq-prover/rocq#16645 - risk: systematic #### Ξ·-expansion of cofixpoints was performed in the wrong environment - component: "virtual" and "native" conversion machines - introduced: V8.9 - impacted released versions: V8.9-V8.16.0 - impacted coqchk versions: none (no VM / native computation in coqchk) - fixed in: 8.16.1 - found by: GaΓ«tan Gilbert and Pierre-Marie PΓ©drot - GH issue number: rocq-prover/rocq#16831 - risk: low, as it requires carefully crafted cofixpoints #### conversion would compare the mutated version of primitive arrays instead of undoing mutation where needed - component: all 3 kernel conversion machines (lazy, VM, native), primitive arrays - introduced: V8.13 - impacted released versions: V8.13 to V8.16.0 - impacted coqchk versions: same - fixed in: V8.16.1, V8.17 - found by: Maxime Buyse and Andres Erbsen - exploit: Andres Erbsen - GH issue number: rocq-prover/rocq#16829 - risk: some if using primitive arrays #### tactic code could mutate a global cache of values for section variables - component: "virtual" reduction machine - introduced: V8.1 - impacted released versions: V8.1-V8.16.1 - impacted coqchk versions: none (no tactics in coqchk, VM only sees checked terms) - fixed in: V8.17.0 - found by: GaΓ«tan Gilbert with hint from Pierre-Marie PΓ©drot - GH issue number: rocq-prover/rocq#16957 - risk: the full exploitation seems to require "Definition := ltac:()" with change_no_check on a section variable in the ltac #### incorrect handling of universe polymorphism - component: VM machine - introduced: V8.5 - impacted released versions: V8.5-V8.8.0 - impacted coqchk versions: none (no VM in coqchk) - fixed in: V8.8.1, V8.9.0 - found by: Jason Gross - GH issue number: rocq-prover/rocq#7723 - exploit: see issue - risk: ?? #### Forgotten universe substitution with Register Inline on universe polymorphic definition - component: VM and native - introduced: V8.5 - impacted released versions: V8.5-V9.1 (all patch versions) - impacted coqchk versions: same (only when using -bytecode-compiler yes) - fixed in: V9.2.0 - found by: GaΓ«tan Gilbert - GH issue number: rocq-prover/rocq#21736 - exploit: see issue - risk: requires Register Inline on universe polymorphic constant - additional note: does not seem to be exploitable before 8.8 (until 8.6 Register Inline fails with anomaly on universe polymorphic constants, and before 8.8 Register Inline only affects native which fails in ocamlopt) ### Side-effects #### polymorphic side-effects inside monomorphic definitions incorrectly handled as not inlined - component: side-effects - introduced: ? - impacted released versions: at least from 8.6 to 8.12.0 - impacted coqchk versions: none (no side-effects in the checker) - fixed in: V8.12.1 (rocq-prover/rocq#13331) - found by: ppedrot - exploit: test-suite/bugs/bug_13330.v - GH issue number: rocq-prover/rocq#13330 - risk: unlikely to be exploited by mistake, requires the use of unsafe tactics #### Section variables used in side effects not checked by Proof using - component: side-effects / sections - introduced: 8.11 - impacted released versions: from 8.11.0 to 8.20.0 - impacted coqchk versions: none (no side-effects in the checker) - fixed in: V9.0 (rocq-prover/rocq#19476) - found by: Pierre Courtieu - exploit: test-suite/output/bug_19861.v - GH issue number: rocq-prover/rocq#19861 - risk: requires incorrect `Proof using` and no use of coqchk ### Forgetting unsafe flags #### unsafe typing flags used inside a section would not be reported by Print Assumptions after closing the section - component: sections - introduced: [abab878b8d](https://github.com/rocq-prover/rocq/commit/abab878b8d8b5ca85a4da688abed68518f0b17bd) (#10291, 8.11), technically available earlier through plugins - impacted coqchk versions: none (coqchk rejects affected files) - fixed in: 8.14 rocq-prover/rocq#14395 - found by: Anton Trunov - GH issue number: rocq-prover/rocq#14317 - risk: low as it needs the use of explicit unsafe flags ### Conflicts with axioms in library #### axiom of description and decidability of equality on real numbers in library Reals was inconsistent with impredicative Set - component: library of real numbers - introduced: [67c75fa01](https://github.com/rocq-prover/rocq/commit/67c75fa01adbbe1d4e39eff2b930ad168510072c), 20 Jun 2002 - impacted released versions: 7.3.1, 7.4 - impacted coqchk versions: - fixed by deciding to drop impredicativity of Set: [bac707973](https://github.com/rocq-prover/rocq/commit/bac707973955ef64eadae24ea01e029a5394626e), 28 Oct 2004 - found by: Herbelin & Werner - exploit: need to find the example again - GH issue number: no - risk: unlikely to be exploited by chance #### guard condition was unknown to be inconsistent with propositional extensionality in library Sets - component: library of extensional sets, guard condition - introduced: not a bug per se but an incompatibility discovered late - impacted released versions: technically speaking from V6.1 with the introduction of the Sets library which was then inconsistent from the very beginning without we knew it - impacted coqchk versions: ? - fixed by constraining the guard condition: ([9b272a8](https://github.com/rocq-prover/rocq/commit/9b272a861bc3263c69b699cd2ac40ab2606543fa), [ccd7546c](https://github.com/rocq-prover/rocq/commit/ccd7546cd32c8a7901a4234f86aa23b4a7e1a043) 28 Oct 2014, Barras, DΓ©nΓ¨s) - found by: Schepler, DΓ©nΓ¨s, Azevedo de Amorim - exploit: ? - GH issue number: none - risk: unlikely to be exploited by chance (?) #### incompatibility axiom of choice and excluded-middle with elimination of large singletons to Set - component: library for axiom of choice and excluded-middle - introduced: not a bug but a change of intended "model" - impacted released versions: strictly before 8.1 - impacted coqchk versions: ? - fixed by constraining singleton elimination: [b19397ed8](https://github.com/rocq-prover/rocq/commit/b19397ed88ef8aa1ea1ca228b5d23b94e15f419f), r9633, 9 Feb 2007, Herbelin - found by: Benjamin Werner - exploit: - GH issue number: none - risk: #### Incorrect specification of PrimFloat.leb - component: primitive floating-points - introduced: 8.11 - impacted released versions: 8.11.0, 8.11.1, 8.11.2 - fixed by fixing the spec: rocq-prover/rocq#12484 - found by: Pierre Roux - exploit: test-suite/bugs/bug_12483.v - GH issue number: rocq-prover/rocq#12483 - risk: proof of false when using the incorrect axiom #### Incorrect implementation of SFclassify. - component: floating-point library - introduced: 8.11 - impacted released versions: 8.11.0-8.15.1 - fixed by fixing the implementation: rocq-prover/rocq#16101 - found by: FranΓ§ois Bobot - exploit: test-suite/bugs/bug_16096.v - GH_issue_number: rocq-prover/rocq#16096 - risk: proof of false when using the axioms in Floats.Axioms. #### nativenorm reading back closures as arbitrary floating-point values - component: primitive floating-points + "native" conversion machine (translation to OCaml which compiles to native code) - introduced: 8.11 - impacted released versions: 8.11.0-8.17.1 - impacted coqchk versions: none (no native computation in coqchk) - fixed in: 8.18.0 - found by: Jason Gross - GH issue number: rocq-prover/rocq#17871 - risk: proof of false when using primitive floats and native_compute #### guard condition issue made it inconsistent with propositional extensionality in library Sets - component: library of extensional sets, guard condition - introduced: variant of [the issue with propositional extensionality](#guard-condition-was-unknown-to-be-inconsistent-with-propositional-extensionality-in-library-Sets) that was not fixed then - impacted released versions: the relative inconsistency was present from the very beginning, until 9.0 - impacted coqchk versions: *-9.0 - fixed in: 9.0.1 - fixed by further constraining the guard condition: [PR 21050](https://github.com/rocq-prover/rocq/pull/21050) - found by: Thomas Lamiaux, Yann Leray, Pierre-Marie PΓ©drot, Nicolas Tabareau - GH issue number: [21053](https://github.com/rocq-prover/issues/21053) - risk: unlikely to be exploited by chance (?) ### Deserialization #### deserialization of .vo data not properly checked - component: coqchk (coqc trusts that .vo files are well formed) - introduced: 8.16 (univ levels), 8.10 (retroknowledge) - impacted released versions: 8.10-8.18.1 - impacted coqchk versions: same - fixed in: 8.19 - found by: Mario Carneiro - GH issue number: N/A (fix pull requests: rocq-prover/rocq#18403, rocq-prover/rocq#18406) - risk: can lead to segfaults or arbitrary code execution on crafted .vo files (files produced by coqc are fine) There were otherwise several bugs in beta-releases, from memory, bugs with beta versions of primitive projections or template polymorphism or native compilation or guard (e7fc96366, 2a4d714a1). ## Probably non exploitable fixed bugs There were otherwise maybe unexploitable kernel bugs, e.g. 2df88d83 (Require overloading), 0adf0838 ("Univs: uncovered bug in strengthening of opaque polymorphic definitions."), 5122a398 (#3746 about functors), rocq-prover/rocq#4346 (casts in VM), a14bef4 (guard condition in 8.1), 6ed40a8 ("Georges' bug" with ill-typed lazy machine), and various other bugs in 8.0 or 8.1 without knowing if they are critical. #### bug in 31bit arithmetic - component: "virtual machine" (compilation to bytecode ran by a C-interpreter) - introduced: V8.1 - impacted released versions: none - impacted development branches: - impacted coqchk versions: none (no virtual machine in coqchk) - fixed in: master/trunk/v8.5 (0f8d1b92c, 6 Sep 2015, DΓ©nΓ¨s) - found by: DΓ©nΓ¨s, from a bug report by Tahina Ramananandro - exploit: non exploitable? - GH issue number: ? - risk: rocq-9.2.0/dev/doc/debugging.md000066400000000000000000000024601516144147600163010ustar00rootroot00000000000000Debugging from Rocq toplevel using OCaml toplevel ====================================================== 1. Launch bytecode version of Rocq (`dune exec -- rocq repl-with-drop`) 2. Access OCaml toplevel using vernacular command `Drop.` 3. Use `#trace` to tell which function(s) to trace, or type any other OCaml toplevel commands or OCaml expressions 4. Go back to Rocq toplevel with `#quit;;` or `#go;;` 5. Test your Rocq command and observe the result of tracing your functions 6. Freely switch from Rocq to OCaml toplevels with `Drop.` and `#quit;;`/`#go;;` > [!NOTE] > To access plugin modules in the OCaml toplevel, you have to > use names such as `Ltac_plugin__Tacinterp`. > [!TIP] > To remove high-level pretty-printing features (coercions, > notations, ...), use `Set Printing All`. It will affect the `#trace` > printers too. Debugging with ocamldebug from Emacs or command line ==================================================== See [build-system.dune.md#ocamldebug](build-system.dune.md#ocamldebug) Global gprof-based profiling ============================ Rocq must be configured with option `-profile`. 1. Run native Rocq which must end normally (use `Quit` or option `-batch`) 2. `gprof ./coqtop gmon.out` Per function profiling ====================== See the documentation in `lib/newProfile.mli`. rocq-9.2.0/dev/doc/drop.txt000066400000000000000000000025511516144147600155320ustar00rootroot00000000000000When you start byte-compiled Rocq toplevel: rlwrap bin/coqtop.byte then if you type: Drop. you will decend from Rocq toplevel down to Ocaml toplevel. So if you want to learn: - the current values of some global variables you are interested in - or see what happens when you invoke certain functions this is the place where you can do that. When you try to print values belonging to abstract data types: # let sigma, env = Lemmas.get_current_context ();; val sigma : Evd.evar_map = val env : Environ.env = # Typeops.infer env (snd (Pretyping.understand_tcc env sigma (Constrintern.intern_constr env (Procq.parse_string Procq.Constr.lconstr "plus"))));; - : Environ.unsafe_judgment = {Environ.uj_val = ; uj_type = } the printed values are not very helpful. One way how to deal with that is to load the corresponding printers: # #use "dev/include";; Consequently, the result of: # Typeops.infer env (snd (Pretyping.understand_tcc env sigma (Constrintern.intern_constr env (Procq.parse_string Procq.Constr.lconstr "plus"))));; will be printed as: - : Environ.unsafe_judgment = Nat.add : nat -> nat -> nat which makes more sense. To be able to understand the meaning of the data types, sometimes the best option is to turn those data types from abstract to concrete and look at them without any kind of pretty printing. rocq-9.2.0/dev/doc/econstr.md000066400000000000000000000130061516144147600160210ustar00rootroot00000000000000# Evar-insensitive terms (EConstr) Evar-insensitive terms were introduced in 8.7, following [CEP #10](https://github.com/coq/ceps/blob/master/text/010-econstr.md). We will not recap the motivations in this document and rather summarize the code changes to perform. ## Overview The essential datastructures are defined in [the `EConstr` module](/engine/eConstr.mli) module. It defines the tactic counterparts of kernel data structures such as terms (`EConstr.constr`), universes (`EConstr.ESorts.t`) and contexts (`EConstr.*_context`). The main difference with kernel-side types is that observing them requires an evar-map at hand in order to normalize evars on the fly. The basic primitive to observe an `EConstr.t` is the following function: ``` val kind : Evd.evar_map -> t -> (t, t, ESorts.t, EInstance.t) Constr.kind_of_term (** Same as {!Constr.kind} except that it expands evars and normalizes universes on the fly. *) ``` Essentially, each time it sees an evar which happens to be defined in the provided evar-map, it replaces it with the corresponding body and carries on. Due to universe unification occurring at the tactic level, the same goes for universe instances and sorts. See the `ESort` and `EInstance` modules in `EConstr`. This normalization is critical for the soundness of tactics. Before EConstr, a lot of bugs were lurking in the code base, a few still are (most notably in meta-based unification) and failure to respect the guidelines thereafter may result in nasal demons. ## Transition path ### Types As a rule of thumb, all functions living at the tactic level should manipulate `EConstr.t` instead of `Constr.t`, and similarly for the other data structures. To ease the transition, the `EConstr` module defines a handful of aliases to shadow the type names from the kernel. It is recommended to perform the following replacement in headers. ```ocaml (** Kernel types. You may remove the two following opens if you want. Beware that [kind_of_term] needs to be in scope if you use [EConstr.kind] so that you may still need to open one of the two. *) open Term open Constr (** Tactic types. Open this after to shadow kernel types. *) open EConstr ``` Note that the `EConstr` module also redefines a `Vars` submodule. ### Evar-map-passing All functions deconstructing an econstr need to take an evar-map as a parameter. Therefore, you need to pass one as an argument virtually everywhere. In the Rocq source code, it is recommended to take the evar-map as a first argument called `sigma`, except if the function also takes an environment in which case it is passed second. Namely, the two typical instances are: ```ocaml let foo sigma c = mycode val foo : Evd.evar_map -> EConstr.t -> Foo.t let bar env sigma c = mycode val bar : Environ.env -> Evd.evar_map -> EConstr.t -> Bar.t ``` The EConstr API makes the code much more sensitive to evar-maps, because a lot of now useless normalizations were removed. Thus one should be cautious of **not** dropping the evar-map when it has been updated, and should rather stick to a strict state-passing discipline. Unsound primitives like `Typing.unsafe_type_of` are also a known source of problems, so you should replace them with the corresponding evar-map-returning function and thread it properly. ### Functions Many functions from `Constr` and `Term` are redefined to work on econstr in the `EConstr` module, so that it is often enough to perform the `open` as described above to replace them. Their type may differ though, because they now need access to an evar-map. A lot of econstr-manipulating functions are also defined in [`Termops`](/engine/termops.mli). Functions manipulating tactic terms and kernel terms share the same name if they are the equivalent one of the other. Do not hesitate to grep Rocq mli files to find the equivalent of a function you want to port if it is neither in `EConstr` nor in `Termops` (this should be very rare). ### Conversion Sometimes you do not have any other choice than calling kernel-side functions on terms, and conversely to turn a kernel term into a tactic term. There are two functions to do so. * `EConstr.of_constr` turns kernel terms into tactic terms. It is currently the physical identity, and thus O(1), but this may change in the future. * `EConstr.to_constr` turns tactic terms into kernel terms. It performs a full-blown normalization of the given term, which is O(n) and potentially costly. For performance reasons, avoiding to jump back and forth between kernel and tactic terms is recommended. There are also a few unsafe conversion functions that take advantage of the fact that `EConstr.t` is internally the same as `Constr.t`. Namely, `EConstr.Unsafe.to_constr` is the physical identity. It should **not** be used in typical code and is instead provided for efficiency **when you know what you are doing**. Either use it to reimplement low-level functions that happen to be insensitive externally, or use it to provide backward compatibility with broken code that relies on evar-sensitivity. **Do not use it because it is easier than stuffing evar-maps everywhere.** You've been warned. ## Notes The EConstr branch fixed a lot of eisenbugs linked to lack of normalization everywhere, most notably in unification. It may also have introduced a few, so if you see a change in behaviour *that looks like a bug*, please report it. Obviously, unification is not specified, so it's hard to tell apart, but still. Efficiency has been affected as well. We now pay an overhead when observing a term, but at the same time a lot of costly upfront normalizations were removed. rocq-9.2.0/dev/doc/parsing.md000066400000000000000000000552141516144147600160160ustar00rootroot00000000000000# Parsing Rocq's parser is based on Camlp5 using an extensible grammar. Somewhat helpful Camlp5 documentation is available [here](http://camlp5.github.io/doc/htmlc/grammars.html). However, the Camlp5 code has been copied into the Rocq source tree and may differ from the Camlp5 release. Notable attributes of the parser include: * The grammar is extensible at run time. This is essential for supporting notations and optionally-loaded plugins that extend the grammar. * The grammar is split into multiple source files. Nonterminals can be local to a file or global. * While 95% of the nonterminals and almost all the productions are defined in the grammar, a few are defined directly in OCaml code. Since many developers have worked on the parser over the years, this code can be idiosyncratic, reflecting various coding styles. * The parser is a recursive descent parser that, by default, only looks at the next token to make a parsing decision. It's possible to hand-code additional lookahead where necessary by writing OCaml code. * There's no code that checks whether a grammar is ambiguous or whether every production can be recognized. Developers who modify the grammar may, in some cases, need to structure their added productions in specific ways to ensure that their additions are parsable and that they don't break existing productions. ## Contents ## - [Vocabulary](#vocabulary) - [Grammars: `*.mlg` File Structure](#grammars-mlg-file-structure) - [Grammars: Nonterminals and Productions](#grammars-nonterminals-and-productions) - [Alternate production syntax](#alternate-production-syntax) - [Usage notes](#usage-notes) - [Other components](#other-components) - [Parsing productions](#parsing-productions) - [Lookahead](#lookahead) ## Vocabulary - *entry*: a nonterminal. Entries are values of type `'a Procq.Entry.t` (`Entry.t` in the rest of this document), where `'a` is the type of the parsed value. For instance `Procq.Prim.qualid : qualid Entry.t` parses qualified identifiers ("qualid"). - *argument*: a nonterminal with associated functions (e.g. how to print its values). Arguments are values of type `('raw,'glb,'top) Genarg.genarg_type`, typically named `wit_foo`, with an associated entry of type `'raw Entry.t` typically named `foo`. ## Grammars: `*.mlg` File Structure ## Grammars are defined in `*.mlg` files, which `rocq preprocess-mlg` compiles into `*.ml` files at build time. `preprocess-mlg` code is in the `coqpp` directory. `coqpp` uses yacc and lex to parse the grammar files. You can examine its yacc and lex input files in `coqpp_lex.mll` and `coqpp_parse.mly` for details not fully covered here. In addition, there is a `doc_grammar` build utility that uses the `coqpp` parser to extract the grammar, then edits and inserts it into the documentation. This is described in [`doc/tools/docgram/README.md`](../../doc/tools/docgram/README.md). `doc_grammar` generates [`doc/tools/docgram/fullGrammar`](../../doc/tools/docgram/fullGrammar), which has the full grammar for Rocq (not including some optionally-loaded plugins). This may be easier to read since everything is in one file and the parser action routines and other OCaml code are omitted. `*.mlg` files contain the following types of nodes (See `node` in the yacc grammar). This part is very specific to Rocq (not so similar to Camlp5). Note that you can reverse engineer many details by comparing the `.mlg` input file with the `.ml` generated by `coqpp`. ### OCaml code OCaml code enclosed in curly braces, which is copied verbatim to the generated `*.ml` file ### Comments Comments in the `*.mlg` file are in the form `(* … *)`. They are not copied to the generated `*.ml` file. Comments in OCaml code are preserved. ### DECLARE PLUGIN `DECLARE PLUGIN "plugin"` - associates the file with a specific plugin, for example "rocq-runtime.plugins.ltac". The string is the plugin's ocamlfind name (also used to load it in the `.v` file with `Declare ML Module`). ### GRAMMAR EXTEND `GRAMMAR EXTEND` - adds additional entries and productions to the grammar and declares global entries referenced in the `GRAMMAR EXTEND`: ``` GRAMMAR EXTEND Gram GLOBAL: bignat bigint …; END ``` Global entries should be available in the current OCaml scope, eg `open Procq.Prim` makes `qualid` available. (qualified entry names are not supported) `GRAMMAR EXTEND` should be used only for large syntax additions. To add new commands and tactics, use these instead: - `VERNAC COMMAND EXTEND` (and variant `VERNAC { entry } EXTEND`) to add new commands - `TACTIC EXTEND` to add new ltac1 tactics - `ARGUMENT EXTEND` to add new arguments for `TACTIC EXTEND` and `VERNAC EXTEND` - `VERNAC ARGUMENT EXTEND` to add new arguments for `VERNAC EXTEND` These constructs provide essential semantic information that's provided in a more complex, less readable way with `GRAMMAR EXTEND`. ### VERNAC EXTEND `VERNAC COMMAND EXTEND` - adds new command syntax by adding productions to the `command` entry. `VERNAC { entry } EXTEND` - adds new command syntax to the `entry` entry. This is typically used for proof modes (see also `Pvernac.register_proof_mode` and the user doc for proof modes). Simple example: ``` VERNAC COMMAND EXTEND CmdName CLASSIFIED AS SIDEFF | [ "Cmd" arg(a) ] -> { do_interp a } END ``` defines a command composed of the string `Cmd` followed by argument `wit_arg`. Running the command calls `do_interp a` where `a` is the result of parsing `arg`. Example with all optional elements: ``` VERNAC COMMAND EXTEND CmdName CLASSIFIED AS SIDEFF | #[ attr ] ![ state ] [ "Cmd" arg(a) ] => { rule_classif a } SYNTERP AS synv { do_synterp attr a } -> { do_interp attr a synv } END ``` Productions here are represented with [alternate syntax](#alternate-production-syntax), described later. Nonterminals in `VERNAC EXTEND` parsing rules (e.g. `arg` in the example) are arguments, possibly with [nonterminal modifiers](#nonterminal-modifiers). The name prefixed by `wit_` must be available in the current OCaml scope. New commands should be added using this construct rather than `GRAMMAR EXTEND` so they are correctly registered, such as having the correct command classifier. #### Extend name Each `VERNAC EXTEND` must have a unique name ("CmdName" in the example) (unique for the plugin, you will get an anomaly at runtime if it's not). #### Classification Commands must be "classified" for the STM. Classifying a command is generating a `Vernacextend.vernac_classification` (see comments on its declaration for the meaning of the different values). This is done by appending one of the following annotations to the `VERNAC COMMAND EXTEND CmdName` grammar extension: - `CLASSIFIED AS QUERY` for `VtQuery` - `CLASSIFIED AS SIDEFF` for `VtSideff ([], VtLater)` (most commands are in this case) - `CLASSIFIED BY { code }` where code is the classification, when it is static - adding `=> { code }` after the parsing rule (before its interpretation), where `code` is the classification and has access to argument values. Used when the classification is not the same for the whole block or depends on the parsed values (eg `| [ "foo" arg(x) ] => { classify x } -> { interpret x }`). Per-rule classification overrides block level classification. Block classification should be omitted (it will be ignored) if all rules have their own classification. #### State access Commands must explicitly declare when they use some of the global state: the current proof state, program obligations state, and bodies of `Qed` proofs. This is done by adding a `STATE state` specifier for the whole block, or overriding it per-rule with `![ state ]` before the parsing rule (after attributes if any). `preprocess-mlg` associates the state specifier with combinators in `Vernactypes`, and the interpretation must have the type expected by the combinator (except when it expects a thunk, in which case thunking is implicit). The following state specifiers are understood (see `Coqpp_main.understand_state` if this isn't up to date): - `close_proof` for `vtcloseproof`, note that closing proofs from plugin commands is buggy. - `open_proof` for `vtopenproof`. - `proof` for `vtmodifyproof` - `proof_opt_query` for `vtreadproofopt` - `proof_query` for `vtreadproof` - `read_program` for `vtreadprogram` - `program` for `vtmodifyprogram` - `declare_program` for `vtdeclareprogram` - `program_interactive` for `vtopenproofprogram` - `opaque_access` for `vtopaqueaccess` So for instance `open_proof` requires the interpretation to have type `Declare.Proof.t` (implicitly thunked), `proof` requires it to have type `pstate:Declare.Proof.t -> Declare.Proof.t`. #### Attributes By default commands support no attributes (except for the general attributes like `#[warnings]`). Attributes may be supported by adding the list of supported attributes `#[ x = a; y = b ]` before the parsing rule. `x` and `y` will be bound to the parsed attribute in the interpretation, `a` and `b` are qualified identifiers of type `'att Attributes.attribute`. Punning `#[ x ]` for `#[ x = x ]` is supported. You can delay attribute interpretation (e.g. if it depends on the command arguments) by using `Attributes.raw_attributes`. #### Synterp If the command modifies the parser or modifies state which may be used to change the parser in a later command, these operations must be separated from the main interpretation and done in the "synterp" phase. The "synterp" phase does not have access to the "interp" state (which notably includes the global env). This is done with `SYNTERP AS synv { synterp }`: `synterp` will be evaluated in the synterp phase with the command arguments and attributes bound, and its result will be bound to `synv` for the interp phase. ### TACTIC EXTEND `TACTIC EXTEND` - adds new tactic (Ltac1) syntax by adding productions to `simple_tactic`. For example: ``` TACTIC EXTEND field_lookup | [ "field_lookup" tactic(f) "[" constr_list(lH) "]" ne_constr_list(lt) ] -> { let (t,l) = List.sep_last lt in field_lookup f lH l t } END ``` adds a new tactic `field_lookup`. New tactics should be added using this construct rather than `GRAMMAR EXTEND`. Nonterminals in `VERNAC EXTEND` parsing rules (eg `tactic`, `constr_list`, `ne_constr_list` in the example) are arguments, possibly with [nonterminal modifiers](#nonterminal-modifiers). The name prefixed by `wit_` must be available in the current OCaml scope. TODO: explain DEPRECATED, LEVEL (not shown) ### ARGUMENT EXTEND `ARGUMENT EXTEND` - defines a new argument which can be used in `TACTIC EXTEND` and `VERNAC EXTEND` ``` ARGUMENT EXTEND ast_closure_term TYPED AS type_info PRINTED BY { pp_ast_closure_term } INTERPRETED BY { interp_ast_closure_term } GLOBALIZED BY { glob_ast_closure_term } SUBSTITUTED BY { subst_ast_closure_term } RAW_PRINTED BY { pp_ast_closure_term } GLOB_PRINTED BY { pp_ast_closure_term } | [ term_annotation(a) constr(c) ] -> { mk_ast_closure_term a c } END ``` See comments in `tacentries.mli` for partial information on the various arguments. Nonterminals in `ARGUMENT EXTEND` parsing rules (eg `term_annotation` and `constr` in the example) are entry names, possibly with [nonterminal modifiers](#nonterminal-modifiers). ### VERNAC ARGUMENT EXTEND `VERNAC ARGUMENT EXTEND` - (part of `argument_extend` in the yacc grammar) defines productions for a single nonterminal which can be used in `VERNAC EXTEND`. For example: ``` VERNAC ARGUMENT EXTEND ring_mod PRINTED BY { pr_ring_mod env sigma } | [ "decidable" constr(eq_test) ] -> { Ring_kind(Computational eq_test) } | [ "abstract" ] -> { Ring_kind Abstract } | [ "morphism" constr(morph) ] -> { Ring_kind(Morphism morph) } | [ "constants" "[" tactic(cst_tac) "]" ] -> { Const_tac(CstTac cst_tac) } | [ "closed" "[" ne_global_list(l) "]" ] -> { Const_tac(Closed l) } | [ "preprocess" "[" tactic(pre) "]" ] -> { Pre_tac pre } | [ "postprocess" "[" tactic(post) "]" ] -> { Post_tac post } | [ "setoid" constr(sth) constr(ext) ] -> { Setoid(sth,ext) } | [ "sign" constr(sign_spec) ] -> { Sign_spec sign_spec } | [ "power" constr(pow_spec) "[" ne_global_list(l) "]" ] -> { Pow_spec (Closed l, pow_spec) } | [ "power_tac" constr(pow_spec) "[" tactic(cst_tac) "]" ] -> { Pow_spec (CstTac cst_tac, pow_spec) } | [ "div" constr(div_spec) ] -> { Div_spec div_spec } END ``` `PRINTED BY` specifies how the argument should be printed (used by `-beautify`, `-time`, and various debug printers). The `PRINTED BY` code has variables `env : Environ.env` and `sigma : Evd.evar_map` bound. Nonterminals in `VERNAC ARGUMENT EXTEND` (e.g. `constr`, `tactic`, `ne_global_list` in the example) are entry names, possibly with [nonterminal modifiers](#nonterminal-modifiers). ### DOC_GRAMMAR `DOC_GRAMMAR` - Used in `doc_grammar`-generated files to permit simplified syntax ## Grammars: Nonterminals and Productions Here's a simple nonterminal definition in the Camlp5 format: ``` universe: [ [ IDENT "max"; "("; ids = LIST1 universe_expr SEP ","; ")" -> { ids } | u = universe_expr -> { [u] } ] ] ; ``` In which: * `universe` is the nonterminal being defined * productions are separated by `|` and, as a group, are enclosed in `[ [ … ] ];` * `u = universe_expr` refers to the `universe_expr` nonterminal. `u` is bound to the value returned by that nonterminal's action routine, which can be referred to in the action routine. For `ids = LIST1 universe_expr SEP ","`, `ids` is bound to the list of values returned by `universe_expr`. * `-> { … }` contains the OCaml action routine, which is executed when the production is recognized and returns a value * Semicolons separate adjacent grammatical elements (nonterminals, strings or other constructs) Grammatical elements that appear in productions are: - nonterminal names - identifiers in the form `[a-zA-Z0-9_]*`. These correspond to variables in the generated `.ml` code. In some cases a qualified name, such as `Prim.name`, is used. - `"…"` - a literal string that becomes a keyword and cannot be used as an `ident`. The string doesn't have to be a valid identifier; frequently the string will contain only punctuation characters. Generally we try to avoid adding new keywords that are also valid identifiers--though there is an unresolved debate among the developers about whether having more such keywords in general is good (e.g. it makes it easier to highlight keywords in GUIs) or bad (more keywords for the user to avoid and new keywords may require changes to existing proof files). - `IDENT "…"` - a literal string that has the form of an `ident` that doesn't become a keyword - `OPT element` - optionally include `element` (e.g. a nonterminal, IDENT "…" or "…"). The value is of type `'a option`. - `LIST1 element` - a list of one or more `element`s. The value is of type `'a list`. - `LIST0 element` - an optional list of `element`s - `LIST1 element SEP sep` - a list of `element`s separated by `sep` - `LIST0 element SEP sep` - an optional list of `element`s separated by `sep` - `( elements )` - grouping to represent a series of elements as a unit, useful within `OPT` and `LIST*`. - `[ elements1 | elements2 | … ]` - alternatives (either `elements1` or `elements2` or …), actually nested productions, each of which can have its own action routines Nonterminals can also be defined with multiple levels to specify precedence and associativity of its productions. This is described in the Rocq documentation under the `Print Grammar` command. The first square bracket around a nonterminal definition is for grouping level definitions, which are separated with `|`, for example: ``` ltac_expr: [ "5" RIGHTA [ te = binder_tactic -> { te } ] | "4" LEFTA : ``` Grammar extensions can specify what level they are modifying, for example: ``` ltac_expr: LEVEL "1" [ RIGHTA [ tac = ltac_expr; intros = ssrintros_ne -> { tclintros_expr ~loc tac intros } ] ]; ``` ### Alternate production syntax ### Except for `GRAMMAR EXTEND`, the `EXTEND` nodes in the `*.mlg`s use simplified syntax in productions that's similar to what's used in the `Tactic Notation` and `Ltac2 Notation` commands. For example: ``` TACTIC EXTEND cc | [ "congruence" ] -> { congruence_tac 1000 [] } | [ "congruence" integer(n) ] -> { congruence_tac n [] } | [ "congruence" "with" ne_constr_list(l) ] -> { congruence_tac 1000 l } | [ "congruence" integer(n) "with" ne_constr_list(l) ] -> { congruence_tac n l } END ``` For `VERNAC EXTEND` and `TACTIC EXTEND`, nonterminals appearing in the alternate production syntax are "arguments" (`Genarg.genarg_type`) accessed by prefixing the name with `wit_`. Some commonly used arguments are defined in `stdarg.ml`. Others are defined in the code generated by `ARGUMENT EXTEND` and `VERNAC ARGUMENT EXTEND` constructs. References to nonterminals that don't have `wit_*` symbols cause compilation errors. The differences are: * The outer `: [ … ];` is omitted. Each production is enclosed in `| [ … ]`. * The action routine is outside the square brackets * Literal strings that are valid identifiers don't become reserved keywords * No semicolons separating elements of the production * `integer(n)` is used to bind a nonterminal value to a variable instead of `n = integer` * [nonterminal modifiers](#nonterminal-modifiers) are used * There's no way to define `LEVEL`s * There's no equivalent to `( elements )` or `[ elements1 | elements2 | … ]`, which may require repeating similar syntax several times. For example, this single production is equivalent to 8 productions in `TACTIC EXTEND` representing all possible expansions of three `OPT`s: ``` | IDENT "Add"; IDENT "Parametric"; IDENT "Relation"; LIST0 binder; ":"; constr; constr; OPT [ IDENT "reflexivity"; IDENT "proved"; IDENT "by"; constr -> { … } ]; OPT [ IDENT "symmetry"; IDENT "proved"; IDENT "by"; constr -> { … } ]; OPT [ IDENT "transitivity"; IDENT "proved"; IDENT "by"; constr -> { … } ]; IDENT "as"; ident -> { … } ``` ### Nonterminal modifiers In the alternate syntax nonterminal names may be mangled by adding prefixes and suffixes to parse lists and options: * `ne_entry_list` for `LIST1 entry` * `entry_list` for `LIST0 entry` * `ne_entry_list_sep(var, sep)` for `LIST1 entry SEP sep` where the list is bound to `var` * `entry_list_sep(var, sep)` for `LIST0 entry SEP sep` where the list is bound to `var` * `entry_opt` for `OPT entry` This works regardless of whether the nonterminal is an entry or an argument. The demangled entry or argument name must be available in the current OCaml scope (with `wit_` prefix for arguments). ## Usage notes ### Other components Rocq's lexer is in `clexer.ml`. Its 10 token types are defined in `tok.ml`. The parser is in `grammar.ml`. The extensive use of GADT (generalized algebraic datatypes) makes it harder for the uninitiated to understand it. When the parser is invoked, the call tells the parser which nonterminal to parse. `vernac_control` is the start symbol for commands. `tactic_mode` is the start symbol for tactics. Tactics give syntax errors if Rocq is not in proof mode. There are additional details not mentioned here. ### Parsing productions Some thoughts, not to be taken as identifying all the issues: Since the parser examines only the next token to make a parsing decision (and perhaps because of other potentially fixable limitations), some productions have to be ordered or structured in a particular way to parse correctly in all cases. For example, consider these productions: ``` command: [ [ | IDENT "Print"; p = printable -> { VernacPrint p } | IDENT "Print"; qid = smart_global; l = OPT univ_name_list -> { VernacPrint (PrintName (qid,l)) } | IDENT "Print"; IDENT "Module"; "Type"; qid = global -> { VernacPrint (PrintModuleType qid) } | IDENT "Print"; IDENT "Module"; qid = global -> { VernacPrint (PrintModule qid) } | IDENT "Print"; IDENT "Namespace" ; ns = dirpath -> { VernacPrint (PrintNamespace ns) } : printable: [ [ IDENT "Term"; qid = smart_global; l = OPT univ_name_list -> { PrintName (qid,l) } | IDENT "All" -> { PrintFullContext } | IDENT "Section"; s = global -> { PrintSectionContext s } : ``` Reversing the order of the first two productions in `command` causes the `All` in `Print All` to be parsed incorrectly as a `smart_global`, making that command unavailable. `Print Namespace nat.` still works correctly, though. Similarly, the production for `Print Module Type` has to appear before `Print Module ` in order to be reachable. Internally, the parser generates a tree that represents the possible prefixes for the productions of a nonterminal as described in [the Camlp5 documentation](http://camlp5.github.io/doc/htmlc/grammars.html#b:Rules-insertion). Here's another example in which the way the productions are written matters. `OPT` at the beginning of a production doesn't always work well: ``` command: [ [ | IDENT "Foo"; n = natural -> { VernacBack 1 } | OPT (IDENT "ZZ"); IDENT "Foo" -> { VernacBack 1 } : ``` `Foo.` looks like it should be accepted, but it gives a parse error: ``` Unnamed_thm < Foo. Toplevel input, characters 3-4: > Foo. > ^ Error: Syntax error: [prim:natural] expected after 'Foo' (in [vernac:command]). ``` Reversing the order of the productions doesn't help, but splitting the 'OPT' production into 2 productions works: ``` | IDENT "Foo" -> { VernacBack 1 } | IDENT "ZZ"; IDENT "Foo" -> { VernacBack 1 } | IDENT "Foo"; n = natural -> { VernacBack 1 } ``` On the other hand, `OPT` works just fine when the parser has already found the right production. For example `Back` and `Back ` can be combined using an `OPT`: ``` | IDENT "Back"; n = OPT natural -> { VernacBack (Option.default 1 n) } ``` ### Lookahead It's possible to look ahead more than one symbol using OCaml code. Generally we avoid doing this unless there's a strong reason to do so. For example, this code defines a new nonterminal `local_test_lpar_id_colon` that checks that the next 3 tokens are `"("` `ident` and `":"` without consuming any input: ``` let local_test_lpar_id_colon = let open Procq.Lookahead in to_entry "lpar_id_colon" begin lk_kw "(" >> lk_ident >> lk_kw ":" end ``` This one checks that the next 2 tokens are `"["` and `"|"` with no space between. This is a special case: intropatterns can have sequences like `"[|]"` that are 3 different tokens with empty nonterminals between them. Making `"[|"` a keyword would break existing code with "[|]": ``` let test_array_opening = let open Procq.Lookahead in to_entry "test_array_opening" begin lk_kw "[" >> lk_kw "|" >> check_no_space end ``` TODO: how to add a tactic or command rocq-9.2.0/dev/doc/primproj.md000066400000000000000000000044601516144147600162120ustar00rootroot00000000000000Primitive Projections --------------------- | Proj of Projection.t * constr Projections are always applied to a term, which must be of a record type (i.e. reducible to an inductive type `I params`). Type-checking, reduction and conversion are fast (not as fast as they could be yet) because we don't keep parameters around. As you can see, it's currently a `constant` that is used here to refer to the projection, that will change to an abstract `projection` type in the future. Basically a projection constant records which inductive it is a projection for, the number of params and the actual position in the constructor that must be projected. For compatibility reason, we also define an eta-expanded form (accessible from user syntax `@f`). The constant_entry of a projection has both informations. Declaring a record (under `Set Primitive Projections`) will generate such definitions. The API to declare them is not stable at the moment, but the inductive type declaration also knows about the projections, i.e. a record inductive type decl contains an array of terms representing the projections. This is used to implement eta-conversion for record types (with at least one field and having all projections definable). The canonical value being `Build_R (pn x) ... (pn x)`. Unification and conversion work up to this eta rule. The records can also be universe polymorphic of course, and we don't need to keep track of the universe instance for the projections either. Projections are reduced _eagerly_ everywhere, and introduce a new `Zproj` constructor in the abstract machines that obeys both the delta (for the constant opacity) and iota laws (for the actual reduction). Refolding works as well (afaict), but there is a slight hack there related to universes (not projections). For the ML programmer, the biggest change is that pattern-matchings on kind_of_term require an additional case, that is handled usually exactly like an `App (Const p) arg`. There are slight hacks related to hints is well, to use the primitive projection form of f when one does `Hint Resolve f`. Usually hint resolve will typecheck the term, resulting in a partially applied projection (disallowed), so we allow it to take `constr_or_global_reference` arguments instead and special-case on projections. Other tactic extensions might need similar treatment. rocq-9.2.0/dev/doc/profiling.md000066400000000000000000000061341516144147600163410ustar00rootroot00000000000000# How to profile Rocq? I (Pierre-Marie PΓ©drot) mainly use two OCaml branches to profile Rocq, whether I want to profile time or memory consumption. AFAIK, this only works for Linux. ## Time In Rocq source folder: ``` opam switch 4.14.0+trunk+fp make world perf record -g _build/install/default/bin/coqc file.v perf report -g fractal,callee --no-children ``` To profile only part of a file, first load it using ``` bin/coqtop -l file.v ``` and plug into the process ``` perf record -g -p PID ``` ### Per-component [flame graphs](https://github.com/brendangregg/FlameGraph) I (Andres Erbsen) have found it useful to look at library-wide flame graphs of rocq time consumption. As the Ltac interpreter stack is reflected in the OCaml stack, calls to the same primitive can appear on top of multiple essentially equivalent stacks. To make the profiles more readable, one could either try to edit the stack trace to merge "equivalent" frames, or simply look at the aggregate profile on a component-by-component basis. Here is how to do the second for the standard library ([example output](https://cdn.rawgit.com/andres-erbsen/b29b29cb6480dfc6a662062e4fcd0ae3/raw/304fc3fea9630c8e453929aa7920ca8a2a570d0b/stdlib_categorized_outermost.svg)). ``` #!/usr/bin/env bash make clean make states perf record -F99 `# ~1GB of data` --call-graph=dwarf -- make world perf script --time '0%-100%' | stackcollapse-perf.pl | grep Coqtop__compile | sed -rf <(cat <<'EOF' s/;caml/;/g s/_[0-9]*;/;/g s/Logic_monad__fun;//g s/_apply[0-9];//g s/;System/@&@/ s/;Hashcons/@&@/ s/;Grammar/@&@/ s/;Declaremods/@&@/ s/;Tactics/@&@/ s/;Pretyping/@&@/ s/;Typeops/@&@/ s/;Reduction/@&@/ s/;Unification/@&@/ s/;Evarutil/@&@/ s/;Evd/@&@/ s/;EConstr/@&@/ s/;Constr/@&@/ s/;Univ/@&@/ s/;Ugraph/@&@/ s/;UState/@&@/ s/;Micromega/@&@/ s/;Omega/@&@/ s/;Auto/@&@/ s/;Ltac_plugin__Tacinterp/@&@/ s/;Ltac_plugin__Rewrite/@&@/ s/[^@]*@;([^@]*)@/\1;\1/ s/@//g :a; s/;([^;]+);\1;/;\1;/g;ta EOF ) | flamegraph.pl ``` ## Memory (memtrace) [memtrace](https://github.com/janestreet/memtrace) is a client library for OCaml's Memprof statistical memory profiler. See this blog post for more details: https://blog.janestreet.com/finding-memory-leaks-with-memtrace/ To profile a file, you need to install the `memtrace` library, then recompile Rocq. We also recommend you make a copy of the .v file (if working on the stdlib to avoid issues with artifacts. The following command sequence will do all that: ``` opam install memtrace make world # to build deps cp theories/Corelib/Classes/RelationClasses.v /tmp MEMTRACE=trace-byte.tcr dune exec -- rocq c /tmp/RelationClasses.v memtrace-viewer trace-byte.tcr ``` rocq-9.2.0/dev/doc/proof-engine.md000066400000000000000000000155701516144147600167440ustar00rootroot00000000000000Tutorial on the new proof engine for ML tactic writers ====================================================== Starting from Coq 8.5, a new proof engine has been introduced, replacing the old meta-based engine which had a lot of drawbacks, ranging from expressivity to soundness, the major one being that the type of tactics was transparent. This was pervasively abused and made virtually impossible to tweak the implementation of the engine. The old engine is deprecated and is slowly getting removed from the source code. The new engine relies on a monadic API defined in the `Proofview` module. Helper functions and higher-level operations are defined in the `Tacmach` and `Tacticals` modules, and end-user tactics are defined amongst other in the `Tactics` module. At the root of the engine is a representation of proofs as partial terms that can contain typed holes, called evars, short for *existential variable*. An evar is essentially defined by its context and return type, that we will write `?e : [Ξ“ ⊒ _ : A]`. An evar `?e` must be applied to a substitution `Οƒ` of type `Ξ“` (i.e. a list of terms) to produce a term of type `A`, which is done by applying `EConstr.mkEvar`, and which we will write `?e{Οƒ}`. The engine monad features a notion of global state called `evar_map`, defined in the `Evd` module, which is the structure containing the incremental refinement of evars. `Evd` is a low-level API and its use is discouraged in favour of the `Evarutil` module which provides more abstract primitives. In addition to this state, the monad also features a goal state, that is an ordered list of current holes to be filled. While these holes are referred to as goals at a high-enough level, they are actually no more than evars. The API provided to deal with these holes can be found in the `Proofview.Goal` module. Tactics are naturally operating on several goals at once, so that it is usual to use the `Proofview.Goal.enter` function and its variants to dispatch a tactic to each of the goals under focus. Primitive tactics by term refining ------------------------------------- A typical low-level tactic will be defined by plugging partial terms in the goal holes thanks to the `Refine` module, and in particular to the `Refine.refine` primitive. ```ocaml val refine : typecheck:bool -> (Evd.evar_map -> Evd.evar_map * EConstr.t) -> unit tactic (** In [refine ~typecheck t], [t] is a term with holes under some [evar_map] context. The term [t] is used as a partial solution for the current goal (refine is a goal-dependent tactic), the new holes created by [t] become the new subgoals. Exceptions raised during the interpretation of [t] are caught and result in tactic failures. If [typecheck] is [true] [t] is type-checked beforehand. *) ``` What the function does is first evaluate the `t` argument in the current proof state, and then use the resulting term as a filler for the proof under focus. All evars that have been created by the invocation of this thunk are then turned into new goals added in the order of their creation. To see how we can use it, let us have a look at an idealized example, the `cut` tactic. Assuming `X` is a type, `cut X` fills the current goal `[Ξ“ ⊒ _ : A]` with a term `let x : X := ?e2{Ξ“} in ?e1{Ξ“} x` where `x` is a fresh variable and `?e1 : [Ξ“ ⊒ _ : X -> A]` and `?e2 : [Ξ“ ⊒ _ : X]`. The current goal is solved and two new holes `[e1, e2]` are added to the goal state in this order. ```ocaml let cut c = Proofview.Goal.enter begin fun gl -> (* In this block, we focus on one goal at a time indicated by gl *) let env = Proofview.Goal.env gl in (* Get the context of the goal, essentially [Ξ“] *) let concl = Proofview.Goal.concl gl in (* Get the conclusion [A] of the goal *) let hyps = Tacmach.pf_ids_set_of_hyps gl in (* List of hypotheses from the context of the goal *) let id = Namegen.next_name_away Anonymous hyps in (* Generate a fresh identifier *) let t = mkArrowR c (Vars.lift 1 concl) in (* Build [X -> A]. Note the lifting of [A] due to being on the right hand side of the arrow. *) Refine.refine ~typecheck:true begin fun sigma -> (* All evars generated by this block will be added as goals *) let sigma, f = Evarutil.new_evar env sigma t in (* Generate ?e1 : [Ξ“ ⊒ _ : X -> A], add it to sigma, and return the term [f := Ξ“ ⊒ ?e1{Ξ“} : X -> A] with the updated sigma. The identity substitution for [Ξ“] is extracted from the [env] argument, so that one must be careful to pass the correct context here in order for the resulting term to be well-typed. The [p] return value is a proof term used to enforce sigma monotonicity. *) let sigma, x = Evarutil.new_evar env sigma c in (* Generate ?e2 : [Ξ“ ⊒ _ : X] in sigma and return [x := Ξ“ ⊒ ?e2{Ξ“} : X]. *) let r = mkLetIn (Context.annotR (Name id), x, c, mkApp (Vars.lift 1 f, [|mkRel 1|])) in (* Build [r := Ξ“ ⊒ let id : X := ?e2{Ξ“} in ?e1{Ξ“} id : A] *) (sigma, r) end end ``` The `Evarutil.new_evar` function is the preferred way to generate evars in tactics. It returns a ready-to-use term, so that one does not have to call the `mkEvar` primitive. There are lower-level variants whose use is dedicated to special use cases, *e.g.* whenever one wants a non-identity substitution. One should take care to call it with the proper `env` argument so that the evar and term it generates make sense in the context they will be plugged in. For the sake of completeness, the old engine was relying on the `Tacmach.refine` function to provide a similar feature. Nonetheless, it was using untyped metas instead of evars, so that it had to mangle the argument term to actually produce the term that would be put into the hole. For instance, to work around the untypedness, some metas had to be coerced with a cast to enforce their type, otherwise leading to runtime errors. This was working for very simple instances, but was unreliable for everything else. High-level composition of tactics ------------------------------------ It is possible to combine low-level refinement tactics to create more powerful abstractions. While it was the standard way of doing things in the old engine to overcome its technical limitations (namely that one was forced to go through a limited set of derivation rules), it is recommended to generate proofs as much as possible by refining in ML tactics when it is possible and easy enough. Indeed, this prevents dependence on fragile constructions such as unification. Obviously, it does not forbid the use of tacticals to mimic what one would do in Ltac. Each Ltac primitive has a corresponding ML counterpart with simple semantics. A list of such tacticals can be found in the `Tacticals` module. Most of them are a porting of the tacticals from the old engine to the new one, so that if they share the same name they are expected to have the same semantics. rocq-9.2.0/dev/doc/release-process.md000066400000000000000000000303531516144147600174440ustar00rootroot00000000000000# Release checklist # ## When the release managers for version `X.X` get nominated ## - [ ] Create a new issue to track the release process where you can copy-paste the present checklist from `dev/doc/release-process.md` (we recommend duplicating the "For each release" section for X.Y+rc1 and for X.Y.0, removing the useless entries in each copy). - [ ] Decide the release calendar with the team (date of branching, preview and final release). - [ ] Create a wiki page that you link to from https://github.com/rocq-prover/rocq/wiki/Release-Plan with this information and the link to the issue. ## About one month before the branching date ## - [ ] Create both the upcoming final release (`X.X.0`) and the following major release (`Y.Y+rc1`) milestones if they do not already exist. - [ ] Send an announcement of the upcoming branching date on the Rocq development category on Discourse (rocq+rocq-development@discoursemail.com) and ask people to remove from the `X.X+rc1` milestone any feature and clean up PRs that they already know won't be ready on time. - [ ] Prepare a PR on `master` (not yet to be merged) changing the version name to the next major version and both magic numbers in [`tools/configure/configure.ml`](../../tools/configure/configure.ml). For example, for `8.5`, the version name will be `8.5+alpha` while the magic numbers will end with `80490`. This PR should be opened before the branching date to have time to deal with CI issues, but should not be merged until branching. ## On the branching date ## - [ ] Merge the above PR and create the `vX.X` branch from the last merge commit before this one (using this name will ensure that the branch will be automatically protected). - [ ] Set the next major version alpha tag using `git tag -s` (you can leave the tag message empty). The `VY.Y+alpha` tag marks the first commit to be in `master` and not in the `vX.X` release branch (be careful about small `v` for branches and big `V` for tags). Note that this commit is the first commit in the first PR merged in master, not the merge commit for that PR. Therefore, if you proceeded as described above, this should be the commit updating the version and magic numbers. After tagging, double-check that `git describe` picks up the tag you just made (if not, you tagged the wrong commit). - [ ] Push the new tag with `git push upstream VY.Y+alpha --dry-run` (remove the `--dry-run` and redo if everything looks OK). - [ ] In the milestone, add to the description a line like `@coqbot: backport to v8.20 (move rejected PRs to: https://github.com/rocq-prover/rocq/milestone/60)` - [ ] Monitor the [Release management project](https://github.com/orgs/rocq-prover/projects/11) in which coqbot will keep track of PRs to be backported (according to the previous command) The release manager is the person responsible for merging PRs that target the release branch and backporting appropriate PRs (mostly safe bug fixes, user message improvements and documentation updates) that are merged into `master`. - [ ] For major releases, you can create new views in the above project by using the "Duplicate view" button in the menu of the views from the previous major release. After duplicating the view, you can edit the filter to match the field for the new branch, update the fields displayed, rename the view, and "save", so that the view is shared with everyone. This is best done after the first PR requiring backporting has been merged, because the new field will have been created by coqbot at that point. - [ ] Pin the versions of libraries and plugins in [`dev/ci/ci-basic-overlay.sh`](../ci/ci-basic-overlay.sh) to use commit hashes. You can use the [`dev/tools/pin-ci.sh`](../tools/pin-ci.sh) script to do this semi-automatically. - [ ] In a PR on `master` to be backported, add a new link to the `'versions'` list of the refman (in `html_context` in [`doc/sphinx/conf.py`](../../doc/sphinx/conf.py)). At the same time, update the links of previous versions that were targeting branches to target a tag instead if the latest patch-level release is out. - [ ] Add `{rocq-runtime,coq-core,rocq-core,coqide-server}.X.X.dev` packages in [`core-dev`](https://github.com/rocq-prover/opam/tree/master/core-dev) - [ ] Ensure a `rocq-stdlib` package compatible with the new packages above exists either in [`ocaml repo`](https://github.com/ocaml/opam-repository) or in [`core-dev`](https://github.com/rocq-prover/opam/tree/master/core-dev) - [ ] Add `coq.X.X.dev` package in [`core-dev`](https://github.com/rocq-prover/opam/tree/master/core-dev) - [ ] Ping `@erikmd` and `@Zimmi48` to set up the infrastructure to have alpha Docker images built for the branch: the main steps amount to release `coq-bignums v9.Y.Y+coqX.X` in [`extra-dev`](https://github.com/rocq-prover/opam/tree/master/extra-dev), prepare a new [Docker-Rocq](https://github.com/rocq-community/docker-rocq) image `rocq/rocq-prover:X.X-alpha`, then browse to copy the `dev` webhook into a new `vX.X` webhook: `https://gitlab.com/api/v4/projects/19687072/trigger/pipeline?ref=master&variables[CRON_MODE]=rebuild-keyword&variables[ITEM]=X.X&token=_`, Push events β†’ Wildcard pattern β†’ `vX.X`, Test Push events. (If need be, the token can be regenerated at .) ## In the days following the branching ## - [ ] Make sure that all the last feature PRs that you want to include in the release are finished and backported quickly and clean up the milestone. We recommend backporting as few feature PRs as possible after branching. In particular, any PR with overlays will require manually bumping the pinned commits when backporting. - [ ] Delay non-blocking issues to the appropriate milestone and ensure blocking issues are solved. If required to solve some blocking issues, it is possible to revert some feature PRs in the release branch only (but in this case, the blocking issue should be postponed to the next major release instead of being closed). - [ ] Once the final list of features is known, in a PR on `master` to be backported, generate the release changelog by calling [`dev/tools/generate-release-changelog.sh`](../tools/generate-release-changelog.sh) and include it in a new section in [`doc/sphinx/changes.rst`](../../doc/sphinx/changes.rst). The script automatically reorders the entries to show first the **Changed**, then the **Removed**, **Deprecated**, **Added** and last the **Fixed**. Manual adjustement is still needed when multiple entries are combined in a single changelog file. - [ ] Start a draft release summary taking inspiration from the previous one. The [`dev/tools/list-contributors.sh`](../tools/list-contributors.sh) script computes the number and list of contributors between Rocq revisions. Typically used with `VX.X+alpha..vX.X` to check the contributors of version `VX.X`. Note that this script relies on [`.mailmap`](../../.mailmap) to merge multiple identities. If you notice anything incorrect while using it, use the opportunity to fix the `.mailmap` file. Same thing if you want to have the full name of a contributor shown instead of a pseudonym. Be sure the PR is not draft for better visibility and ask everyone in the dev team to contribute the main features and breaking changes sections before the final release. - [ ] Put the branch name in the `CACHEKEY` variables in [`.gitlab-ci.yml`](../../.gitlab-ci.yml) (for instance ``old_ubuntu_lts-V2022-05-20-c34331afa5`` to ``"old_ubuntu_lts-v8.16-V2022-05-20-c34331afa5``) to indicate that it shouldn't be cleaned up even once it gets old. This should be done after all PRs touching the `CACHEKEY` variables have been merged. ## For each release (preview, final, patch-level, copy-paste for each) ## - [ ] Ensure that there exists a milestone for the following version (both major and minor versions like X.Y.1). - [ ] When doing so, add the new milestone to the coqbot command in the description of still-open previous milestones. For instance, when creating a milestone `8.20.1`, if there is an open milestone `8.19.3`, something tagged with the milestone `8.19.3` means: to be backported to the `v8.19` *and* the `v8.20` branches. The coqbot syntax is `@coqbot: backport to v8.19 (move rejected PRs to: ); backport to v8.20 (move rejected PRs to: ); ...`. - [ ] Ensure the release changelog has been merged (for release candidates the release summary can be left empty, it is required only for the final release). - [ ] In a PR against `vX.X` (for testing): - Update the version number in [`tools/configure/configure.ml`](../../tools/configure/configure.ml). - Only update the magic numbers for the final release. - Set `is_a_released_version` to `true`. - [ ] Set the tag `VX.X...` using `git tag -s`. - [ ] Push the new tag with `git push upstream VX.X... --dry-run` (remove the `--dry-run` and redo if everything looks OK). - [ ] Set `is_a_released_version` to `false` (if you forget about it, you'll be reminded by the test-suite failing whenever you try to backport a PR with a changelog entry). - [ ] Close the milestone. - [ ] Publish a release on GitHub with the PDF version of the reference manual attached. The PDF can be recovered from the artifacts of the `doc:ci-refman` job from continuous integration. Also attach a `tar.gz` archive of the sources (to ensure a stable hash, you can copy the archive autogenerated by github when the release is published). - [ ] Ping `@rocq-prover/packaging` to request Nix and opam packages (either in the main [ocaml/opam-repository](https://github.com/ocaml/opam-repository) for standard releases or in the `core-dev` category of the [rocq-prover/opam](https://github.com/rocq-prover/opam) for preview releases). - [ ] If pinged by opam package providers in pull requests to [ocaml/opam-repository](https://github.com/ocaml/opam-repository), transfer any changes to opam packages (`*.opam` files) required by opam-repository CI (such as missing dependencies) to the corresponding package definitions in the Rocq repository. - [ ] Cc `@proux01` to ensure that a `coq-bignums` opam package is available in [`extra-dev`](https://github.com/rocq-prover/opam/tree/master/extra-dev) or [`released`](https://github.com/rocq-prover/opam/tree/master/released), respectively. - [ ] Cc `@erikmd` to ensure that the necessary configuration is ready to release the Docker images in [`rocq/rocq-prover`](https://hub.docker.com/r/rocq/rocq-prover) (gathering `rocq-prover` and `coq-bignums` opam packages). - [ ] For X.Y+rc1, once opam and Nix packages are ready (and ideally Docker images), send an e-mail on the Rocq announcement category on Discourse (rocq+announcements@discoursemail.com) announcing that the RC is out so that package maintainers can start preparing package updates and library authors can safely start preparing compatible releases. - [ ] For X.Y.0, once opam and Nix packages are ready (and ideally Docker images), announce the release to Discourse (rocq+announcements@discoursemail.com). ## For each non-preview release ## - [ ] Ping `@rocq-prover/website-maintainers` to update the website. ## Only for the final release of each major version ## - [ ] Ping `@rocq-prover/zenodo-maintainers` to publish a new version on Zenodo. Process: 1. Go to the [Zenodo Rocq Prover community](https://zenodo.org/communities/rocq-prover) and click on the existing "Rocq Prover" record. 2. Click on "New version". 3. Click on "Upload files" and upload the PDF manual and the source tarball, copied from the GitHub release. 4. Select the manual as the default preview. 5. Enter the release date as publication date. 6. Replace the release summary in the description with the one from the https://rocq-prover.org/refman/changes.html page for the current release (copy-pasting from the HTML page to the rich text editor works, except that bullet-point lists appear as quoted text, which you can fix easily in the rich text editor). Note that the first paragraph of the description is not the release summary but the general description of Rocq, which should not change from one release to another. 7. Change the "Project manager" to the current release manager, and update the project members to match the current maintainers if necessary. 8. Add the (major) version number. 9. Update the link to the release on GitHub (in the related works section). 10. Click "Publish". rocq-9.2.0/dev/doc/rocq-src-description.txt000066400000000000000000000040701516144147600206360ustar00rootroot00000000000000Rocq main source components (in link order) ------------------------------------------- clib : Basic files in lib/, such as util.ml lib : Other files in lib/ kernel library pretyping interp proofs printing parsing tactics toplevel Special components ------------------ grammar : Camlp5 syntax extensions. The file grammar/grammar.cma is used to pre-process .mlg files containing EXTEND constructions, either TACTIC EXTEND, ARGUMENTS EXTEND or VERNAC ... EXTEND. This grammar.cma incorporates many files from other directories (mainly parsing/), plus some specific files in grammar/. The other syntax extension grammar/q_constr.cmo is a addition to grammar.cma with a constr PATTERN quotation. Hierarchy of A.S.T. ------------------- *** Terms *** ... ... | /\ parsing | | printing | | V | Constrexpr.constr_expr | /\ constrintern | | constrextern (in interp) | | (in interp) globalization | | V | Glob_term.glob_constr | /\ pretyping | | detyping | | (in pretyping) V | Term.constr | /\ safe_typing | | (validation | | by kernel) |______| *** Patterns *** | | parsing V constr_pattern_expr = constr_expr | | Constrintern.interp_constr_pattern (in interp) | reverse way in Constrextern V Pattern.constr_pattern | ---> used for instance by Matching.matches (in pretyping) *** Notations *** Notation_term.notation_constr Conversion from/to glob_constr in Notation_ops TODO... *** Tactics *** | | parsing V Tacexpr.raw_tactic_expr | | Tacinterp.intern_pure_tactic (?) V Tacexpr.glob_tactic_expr | | Tacinterp.eval_tactic (?) V unit Proofview.tactic TODO: check with Hugo *** Vernac expressions *** Vernacexpr.vernac_expr, produced by parsing, used in Vernacentries and Vernac rocq-9.2.0/dev/doc/shield-icon.png000066400000000000000000000206061516144147600167320ustar00rootroot00000000000000‰PNG  IHDRΛMFώΨasBITΫαOΰ IDATx^ν TSYš¨Oυͺ:gΊΛ“™u9NO%Μ\Bέ©„Ymΰ^ϋ*ΪΕ«δaAŠΡί(…\ ¨((Ay)" "…‚­ˆ" (\©βαj!–²0ΩϋίγΫ{ΩgŸΞ[ϟ?ΗЁ ˆ"0~2:‘JD@†Κ°h ˆ"0_P†/²H/"€ (Γ’1€ ˆΐ|@vΎΘ"½ˆ"€  ‹Ζ"€ σEeΨω"‹τ"ˆ"πΆƒΐM³Οžύ ~φÏ?ώθ`$† ˆΐNΰ-GΎqπγο{ϊ_ρwή&—Όϋ“Ÿ eο>fPψˆ"ΰ(‡Φ°“ΖYς.AΰŽjErˆ"€ Ž|γΰΩόπφΫoΥ_‘τŠΖ "€ ³#0σ)Ώζٟšσ.ϊλ³γŠ€Dpd ϋ—όΟ·ήz ±BD˜-™Χ°@#ZΐΞ+’GDp(Γ"Rˆ"€ s €2μ ‘&ˆ"€8DeX‡0!!D@ζ@eΨ9@CMDpˆΚ°aBBˆ"€́ʰs€†š ˆ"ΰ‡Ύ5됦…mΌwΏ£σ `60ΰΓȏΧyxΦd @Μό—_ΎU~ήΟ©Τ,Tu{‡΄σ‹/@bΥh4ΐf€―ΐοNι—ΰ7I’ Υϊϋƒί 岃 ˆ€=Ξ”a¦ŸhlΊΏdɐC}½½ό9§Vk::₯}2ȼϞ=G~|ζτ){A£:D@„€3νΓ‚τ±οQΧΩLΙ'βCz”ΐ π‚* ΠΠxot?<ΉπYV‰tb9§¨–σίvM9gWUΧ6GμΧΞ¦½μ€ΖΛ h Εεθ_ξy8+ml=Σ.M4&Y΅ΖKτΛƒl±ΕY2ž mwϊnH_$Μ—Pζ&TΥ|ΞΟΉΈκdϋ°\žύ(gψϊχ?―ύκΟφΥ0΅’Ϋ‘P‘‘υGώ(‡Vy|ΰώ« †^V‘Ίσb-g{•ρ’rΕΉWΓ\^H›ΉKK#‹»"5ww†χΌ$ζ[Ν\yNŽ*˜]―—}Ό„ξ€Ί4Χ0‘Κζ£pžxΞΕU'Λ°ζ!~§TξΨJ>ΏRζΚ›!σ~Ϋ(9έώοο!䌌ΞΧbi£ξΙί“ΩJγ\aΐr“OZEΣ©τ²ΎI ΓΉ~ϋN ΰ‚*­’υlϊΕN•#Έ~ '3"ωfωo¬’t<πtφR½ νθνcΗ?d ”oΒΙ3‘|  δ"<φZ6RNRΞΕ Ν•½ωΫ’₯ŠIL˜pήP8rac|J«Υyžώ²<Τ š—Q yΛ°JE“ΡgΛw‰ZϊΏb«½αr—΄­­τ#eξΡkfgχπγ㌷`h:JΛ΄ 7Ϋ›šΫkβ©ή'#ϊΘqlΈŸώψ\ιεϊΚxμΚ™γvΔxθςό¦ζΆšυtiY‡š‘τΨw³«·-c•0ΠΌGρΡ™Κ«υWvh+υ’”™ΓοΥ¦_—cšξΜ"eτY³τŠYΊe?V‘ώ;|ίΝφ–Ά&‹sοΆz †°±ŠΣχ¨Γ ₯DλCT›‘ͺΪ|¬ψpyΉ @Ξυξ;žoˆέ Εy˜$ΦŠG=“Λc˜%Α_ϋ ΈcH‹)ΎxH―Œ a³sy§~εh8΄²β+ΟΆ&ψsŒοq‚ΐ-­}ΰt•³ς@ζzcω{~‘z Τς@Ύ’oΜ°ΗΚ Œυ+_‚ΏL„OφNpΉ~‘"ΖΟMH>3Hr2xwŽ%§fΣΏ>³ΛδXΆYΉ4εͺΕ`ώά?ΐΔΞ-#iσ9Β,Cτπΰδς°U@’p^ow#¦Ϊ\)λQ-ίΙ@αǟπŸ0 ‡•σ6$mΖnΤ2υŸζ01[g₯|ΪΒFΦ}Cΰ$‘ω fίJΓιcʓ壑€ΰ ά Šδ ωEΉhΑC³Uκ8%Ψ”±β'3),œ_Έ]‚؍ΏώαΟIΨ½=ό6€WΏ•+@”ŠU!—ϋ^_Ώ,‹7”ƒΌ6ί"@ΜmN,£™Τ€lH¬Α1<}B3©&)Ž‘ΉuMΗάΠ rͺ#Œm˜ΠεuEύ>IG§σ˜ώ[uiΩω„‹£?lz?€˜l'€Nώ5N α6 Πίf’˜I’\½σΓμ ·ω9ΩξfX.AjGZς j†™Δͺ€±§„X†€³8aτLW{Οθ€ιψΨΝ5RkΎH 6ΥiE †…΅σ6%α±[‡ o€XabΆ:ΞZ%3Ψ#„‘š…Nλ01:½eΒmΩτήxεΙςΡP@ΰ†ήb’ρ˜¨R”Τ­#³z˜̍)eφ"ΰSΖ:ˆŸΜ<±p~α2,bΟ&±’,ψ›³`υ «‘JΕͺP(ψ _φ•IpΫΦθhΈI֎˜ΣW‘.€F₯‹'0ώΤγ’tαhΖΤ†BύpY³(ΔΤJ…–β/eZI‹k–ΔΥx›0Γ„#ψδΘωOŽ€MΙλIΙ'k½ 'wSϊN5Πi/Q9 VU›ϋ³Ώͺτbίͺ4_Γ*κ[£βwiΉγ⚫[Α~ςPVP:[bͺψͺΣ)i5΄3nΥOΗ¬Σ PΠζδ{”ΛΪDι©ΥVfΩΞΫ’Δ`±³ƒ°Ωœ-j«γX’ΠΒ’2@;L(:¨N(O Ιξxsδ‘ΒΠBhDœ3—3KœΰΖ!tΚ@ΡΩ;u›φ`αv 6A>Y$ΩΩ¦WΠ\2Ηέ†&“ϋB‘ό˜ή‚»bψ”0Sψ—Ι‘§COžώσŸ~ΐ°Ζ‡ΑkΉ~ΡΉή2!ωδA/θa­Ό₯iΠΰ<₯ŸΛ“ΪNύΪnτή]…w8Ήη― ε>©maφ ΅ŠλIN>ԟTT–)B> ³ψ‰βZrκ]ύ6+G 0»6ΩσPΖ0RJ;ΖΎΖ- ƒΙ9ώVήΚΈLΖg9–0|*χ‘‘`.Mι'0-ψg8΄“Zp}9M§»ŸΠΰz—-/¨₯Ž~=₯ΖΫSgσ.0Νa±Ϊκ8–,t„°€τp0‘θ :‘<1Xw@›ΟhΟβi#" ΙαPK)j)gκ¬ :efΞΪϋ]ΓŒƒ$ϋ³ŸώΌvpsΐδrP ΏΟςεΩyηΐbΦπΩ£GRL΅ΰ{΄  1λ(Mο}θVIύ7Ζ·_U•|υŽΧφΔε/eafΣθΛ―%¦˜t<|M.Wύq υΏυ‰ΉIǎo *Θna§Oι¨`kn©τέk.€{ άΟ2Χ覂·Δ[Ζ»¦Όγ‡FR) αΕΜ{Κsη±γ’ΟΝ“Ί—}FAc’„³b[_ξS^ί[6 ²V§•―Θ$¨ˆsΝG`‘+«$Τ¬;tKŽΖΝξΉyF(…ΉdhN Wρ ― ώΞίήάυλ8ΡΑcΡΫx<·°Iβώ3Η—We72,ν‰<*ˆδznψȏΊ§―ε‹VΖgnΪΘ}'ZιΗcΚ„PώΠζ[sSž₯ΰCi+XψΨΰ ‘„ΖξœΔΔ.Ϋs$Ψ Γ)·EΧwx`|HsN€γΰέ!‚¨R˜Nh˜6ΠMoΏN«wΈ; Νhα ‘7›2°ΙεΰΜ™ΎΣ€€;΄’’7η†UU”™!^·ΗΕ?ώΌΎξ†£wnΑω’Rsζ7Σ85ζΆ3Ϛ«S³ε›ΟΦάk/ρ\θ]‚; {^½RN’K~σ›β2°ρ ~ΐ π‚*”^_πλΤ|πΒƍ˜νukρΠ±{¦M^°ωλDς₯Δςfς|»/Ψ[`ιZλ&ΘͺΰηZΝο€6°χΊeσoβMί£}A¨ωλAΐ3:^xψh°Ώ#έΔ§Ο{Ξ2ͺl>Kk―Ώψ›ΙΣΙv Μ‡!Ψ1I–CrΆΔnBKΧΧ‚’'$ΰΔΦ i#—DΰΝ"ΰdϋ°VS\R~ή¬CΡ"ˆ€σpΎ}X[&½^2¦ΧΔ½ρΞΓyŠ o g]Ú§WgΡJφM°(NDΐ©8e†5O―Ϊ(Ι:Υ¨CΞ"o ηΛ°μτŠ’μ›2ZQœˆ€³X€χh΅Ϊ;wU_φ|gτ9†½e—ρŒv[£JD@μψ‡ΏwέΆuK”8ΒόΥΩj²3μΏόΛχqρ rΕΈ-§Q9"€ ―–ΐϋο»_.-ώ»ΏϋΉ}7γ.AςC(½Ϊο6T‹ ―–ΐ7ίΘSŽ›Ρ‡E—aλnΧύυŒ~#D@^-―ž>ρΙΦ‹.ΓΦ74ΎZjΘ:"€ ¨­»m_rΡeΨoδfΟκ³ο;ͺEDΰ•˜1_-Ί ϋμΩ³WJ GDΐQ3ζ«E—a Ι!ˆ"°θ 8τw ώτύΤ#“}<ΘAD@’€ύτθP†Υύt†{Ύ2d @ΕCΰo({ιΡ©v pATjIέύŽ'Ώο~t§ %€ϋrŸ`ΘΫR]³ΑΕΤs”Έ€1ΞνΥt€DšoϋyŽ/ζPπυΝypVnα«SωšY΅‚?+] gK›P°ͺl6aIΞ¦€•‘¬UΦ -Š˜εΣml˜³#£’εΛξ'_v΄” 2M[³_{εi~Δ4i¨ΛίμiθU|m‰±T1?uqϊΗ9Cτΰ«σ»Ms„·₯φλ/Ӎ’ #<­Ψψ?’[ž>ψ˜ΊYvΏb#x˜&ά„°ϋ{½Ρίw?i«ΞεB₯|v”άi‚αwΏΊ`‹·ΕΣ8υ3εΊ χΨ_Ϋ’ΊlΚPς½‘Ί `… 8$ ˜N6ΈΟPμΠv TνΆ­Ό$J‘»S«\ƒS’ΙΉŠ Δ–½'ΘώλbFΧ“ΉvH§ΔΦ:wmvΡN’!/?)WΟ’%έύΦ§œ© ―Ψ»«aά! P!ά{ Φ›gσIάΠ6/Z8ψ,τΜΎ N’:α!α6μŸ\ΪΛ°\Ξλέ·I upΜάΦ†JP̍**Ψ¦ΚΫ,UκpwqΞ•ςεΊΒΜξ¬ΡφωΥώvΖ27θhAiΎ&"ΎI8ψ©ςi{p=Gz†]CEdΕΈsYHi1ο`!68 ίλν!οΝϊ7Ξv-ž‘|'*oΠͺ―!&Έ˜VvbΝήf½$):TW~(¨c;±6'Υγψ {Α£ŒΙe)ε$JρήN Δ³ο&c`Έ(9{+Ÿ¨ΥΏ%ύΣΞΪφˆo*ΈΫͺ*RόzS;λΎ+ΫιΫ“ΧχΥiΦ°Έ_BJIΟ-9uχΑZ¬‘&Υ_Ώvΰ†gTƒO­–9ρz σƒFgίh~ω .+ΒΗWg=( ΥΠγή’ϋ%QΣ¦μ*7 QΏθ+‰σfΪψI€Y+ ʁžl?s;.AΥϊ"ψπ\kΆ’a)Dδ²:΅΄ώKŠάctΫΖ"L¨Ιψ(:5ΦΓ}­DY‘ήΫ‹€*₯)ίpAΚΉXΝ©ΈύΥC˜O΄$K’κF’ͺ²”BmbϊFf…αβ»ΏDο9XqΈι›±|ΖΈAο”Hςk g Έο*¬G¦ƒΐg7g›˜rό€Ϊ–š^PU[—΅τuEγC«β,ͺLΰή¬QΑšFα`&L끀χ$ϋΞΓJ±HۊjυkŠ«υΎKp Υή©ξ…§&xρB$YkyζmΩνΕ8…B΄9‰Χšz €WP’“7džhPSf{֘1dZ¨ΪΟvΉG‡3} 9lιqνλ• ½½ΐΌ!½ƒ(i^ƒv…£ΒέO –ƒ\­ΈΧΏJ’ΈΜzjAŒXi†€ZŠF'OΔΣ w3OŠδ.~jXΚΰ= °ΊΙάι~”[mΘP†ϋDxυΥΤ37‹ͺξŸ`κx{Ώ`σΈυΉN“aίχLtτN}Ϊ3λ@Λ<)U_ζϊ¬!i­h™;†{ωΉ t λ0‚γ#’‹OμOΪU€‰ήξ‹γ>ΙΏ‘#QaώΑ»ͺ¨d‰Ψ…Ϊ Iα6Ζ‡…$5βž|Β‚$ξκIΆ'‰ύwƒJΞ‰‘7ΘάΓVήΈo„―’±mϊϊŸΞͺκKᑜΐ‘Τπ0π’4?֘07ΔΩDΥν ^νmν ηλp?ΆλˆΘΠt Ώ ΄ Iκ€DζσΓ _³kFδ­'NI™ „|ϊ얐ΰ EΪX@ΙδψiΠhaސΦ#ξJA ]•WΟ;\™(ΒF[«zΈΑΎ$p8GΨΙxΎ©’8N‚)mν3%NOγ·μ  ‰―™"Œ―πΓΊϊtlψμζl]Ί˜ œΟάΏ§π»Π™ϋ“φζ+C’ΐ™© ͺ˜υ¨ λM(mHz΅ό€Πθκq*4y;·68lν±^χΐeχ⌠0Π'›³+”-©i­J³ΆlŒf[1N± „"’ΏwdΝdwΕηέ4f{ΦXRοtcJ—»ΎœX•£ίΠ<(ΐmκΡΙkD+ΐ”σ\ε>ΪΩά!#WRι%€Ί ™‹ξ>Ÿ;˜ώ™Πr °LX:„σό"ΌhYψ$’·tcλ―άΘIΩΰοΙ%5CM7ϋmΆZΟφ|7³B₯&γ—3›§ξΏwuηj© `E₯ί%pΥ‹ΚϋΖAڝ½–޳ή9Ν.ŽAΒΤιΗF@Ώξ^Fϊ,¬lψR\…ͺ Ξhηcύšw‚ΦΙχύΌ]έ’rύ'εβ‘ύΗώ@΅ώ4~t£CuΘΠDO];3TυΥ½)[Ό‰Ϊ¦>ώζ5€T-άΝ4?QΡ ZTΉ&+οŽ0Ÿ»cυwUu~¬‡ΕήT ΈžpJΰ±Ϊέ;˜G<žJσήΦJXGδ(©=’χΏυFανfFμa±ςe°₯ elς;•P2Ύyχ_•΄…._ǜ=PjνDOΣ †ω‚ε‰σ τ–7Χ[—ξοΕuΛη_xρΥϋ˜΅•‰0³E ΛΣαΑ«­α³š ΌHkEΧ ω™ˆλα.’wδi†t}ΌΝ+(•―PfψlΡ<ΚʎlΚΨ\ΏMfΗSExKΊ:@$Ξαhξο‰a>3tΓYQβϋ~ώΑΡι1Ι€n¨όXf½Βκ΄Ϊζ;k0fg*T―+άΩ9Iˆ§Z“„+₯9²]<¨q /ͺΞ‰ŽVa΄BΓγrΐΰΆ1»WN“aεƒcKcDTΕψt¨όUžΨΨ}θΞ~HΈw’§°K»)tεRτΣP§3yZZ+Ώv$€3xPΡ4/ Q6FP­ΊίŸ/ŽΠ ‡ͺŽYφ±UΥj`ΪL…ΕΪ'8L0ΈΟ‘ΊTnwmΛγΎ¦6?θN3ŸXJ,"žι­&Ω¨m,ζ&ΐk:?A p w£|Ωφͺ;m γχ‘UΧ`ΣΦq“N³eΰ摃υΦW€ΜNΓ·βf–; &” G’¦]lγ°KήՎ7a $°_bΒ¨λΟ‹Ψ$X°rMbIQ³kϋm~g8Μ»ΐζΘ±©cbTAˆΑΩ›lʐΛΖͺ[+*BOΨ™5V+œοΕS ΨpΤφμӍτ Ή‡E―γ]`Ι1Τ5( ί²Κ]Υ[&ΰΤκ]Σ“›%ΞΩ:9`3}…Ω>,ΨΜ©;σ©ΗΊΌ‰P‰„ͺά[}{°σ6Αύ$­©ώmρ­π½ξζ»Ι<ΉBΌΚ](h›u$εŠ]h!3?€'ϊ[½“]ͺ47°΄²ο―#΅N³K ιΈTO&—¦διG)W`ΦΕ•}ΰnΈ[αF<Τ tyΕΕ’}2σύy Gλ·[ΑΗTCA1Π1ζ΅%„Ωϊ$½7…q-2!†-υ‹^ΝμSr£bΌΑ’PƒιϊΘά“έ{κX›ίUςO⠁+°ŸpwŒ3ι„Ηe”QώQ"‹Ρνκι=,ΜΏΥΪ­rρβO'_ˆS$ΖΊž1―OBŒj­6ŒΖb­uκύHχ˜G¨?₯‘ζWIU%„ Κͺ;#jNΚμΦ€³‡!±ήJɍœuΖςωŸΊ–„ίρ $χƒ,’cΓg5g›°ε­UΉ-ͺvš;ή„5,v<βͺKC΅ν·>?‘R*ηϋ0ΓΐtΠͺ ©m'ΨlΛNΧθϊ+«t±9Ζفσ’·σzλuφfΉ^άeυCkδuΝ6RŠ=šώ^ΉΟϊ(¬·YϋθwŒ­ˆ‰ΰ šr½ΑΜd{vαDLrψτ₯‹ʔLvZ1ιΎ5y£Π@ΨΕΛO@Π6VJmw“¦9ήwω―ΐΎ\XtφΠw ϋB€γ=RΪ'DC78;?Ζh£Έ€R₯žΑY{ΥN³†ϋDωΫχm<P|z)‰cΚαζβ½'F„ζq‡Š#PUTΏ’³Lή‘§cy0+¦ΡK©΅ιΩυBGwδξλΤΠXfΎgNMΫN-=V 7ϋdΤͺUmQE  Sφδ1œ_ Ά<ΦzΣ ΓΦΪΑ{³*MOαŸΣΝ›9˜F^{βHΓ―WiΑEΆhZ)»PΆΤlύ&P)/ΊΠHΣΚήϋ ͺMϋΧ»W0κ!JDfΊ!3Λ3§m§Z.kξQx€SχιΓ.υψ‘P5kΈ ‰Σt^ͺJ,ΘΛvU6HζαΖ₯*xO?Μ<α™s₯m'‘Υ TΏOc:Vΰ4žYδyΊ¦νSL=Φ=¨ΠΎύOΑDοE=gΰΌ|vΘ ƒ¬Lΐ<΅. T‹­Εΐ{†— E1«#l5a $Μ¬kFΤLœ+‘Ζ€•²f ΰx—ωšT#kWGz"§lζšΝ°θjlΌ|Ο>mΖαšΠjΕ£ς=Ήΰ#lRٞ5ΖύVύˆΡ(ϋλRτ7€CΏIjIΪώ܈”V›zhYΝαυS*“p ο‰Φ€[OGΆfL}Ϊ@L˜cbΞ«h-…o*έ{69-«φ3Š9•RφT&d?²5§2ύ:ία’†RUέ‰†8˜NΩ‘i˜οc 0ϋ3Oγ•œοdΥS)ŸωΨ’»υΞ;οΌ.δQl(½²™ '&@όl “T9<G«žΎβ–Ζ€Wp,Ί λώίNΜΉŽ oŸWΓ„˜«pΠ{]† GΏI„bE'&πΛπ φ½_tφ£p±ΐγφF΅ˆ"€Όrούυρώ(ΒΎ‹(ΓŸ;~€»ΐ_BZ|³\uΗS2IDATΙ~ ¨@&ΰζΖ{ώύ.’{ FΎfn+σψ…'xρξΫqEmυezβΞ@D`ΑΈΊΊΖnΩIX|ϋneXΈƒ―’τoίuΐͺϊwΫGΑχιJΆn΅«~Ρ -t@ΩlE΄—*ΤΏI\σjVϊ/jJ Z8[.σ/―lΞ¬ΕΆwΥΚwφ*ΆϋΤolόύμojSoP™{ΞηtΌ`σ9ΩDζΚ°¨eXH;TτP?­-―€΅ικ·)>ΜέκOY˜Ό`Š|Αζo@G8Iˆ(ΓB: eXT„ ³'°ˆtΝήyΤ@EMeΨEέ=Θ9Dpj(Γ:uχ!ηD`Q@vQwr@œšΐHg”έ 1IENDB`‚rocq-9.2.0/dev/doc/style.md000066400000000000000000000153121516144147600155060ustar00rootroot00000000000000# OCaml Style for Rocq > Style uniformity is more important than style itself > -- Kernigan & Pike, The Practice of Programming ## Spacing and indentation - indent your code (using tuareg default) - no strong constraints in formatting `let in`; possible styles are: ```ocaml let x = ... in ``` ```ocaml let x = ... in ``` ```ocaml let x = ... in ``` - but: no extra indentation before a `in` coming on next line, otherwise, it first shifts further and further on the right, reducing the amount of space available; second, it is not robust to insertion of a new `let` - it is established usage to have space around `|` as in ```ocaml match c with | [] | [a] -> ... | a::b::l -> ... ``` - the tendency is to use the following format which limit excessive indentation while providing an interesting "block" aspect ```ocaml type t = | A | B of machin let f expr = match expr with | A -> ... | B x -> ... let f expr = function | A -> ... | B x -> ... ``` - add spaces around `=` and `==` (make the code "breathe") (note that use of ocaml stdlib `=` is discouraged) - the common usage is to write `let x,y = ... in ...` rather than `let (x,y) = ... in ...` - parenthesizing with either `(` and `)` or with `begin` and `end` is common practice - preferred layout for conditionals: ```ocaml if condition then first-case else second-case ``` - in case of effects in branches, use `begin ... end` rather than parentheses ```ocaml if condition then begin instr1; instr2 end else begin instr3; instr4 end ``` - avoid semicolon after single branch `if`, ie instead of ~~~ocaml if foo then bar; baz ~~~ do ~~~ocaml let () = if foo then bar in baz ~~~ - if the first branch raises an exception, avoid the `else`, i.e. use ```ocaml let () = if condition then error "foo" in bar ``` instead of ```ocaml if condition then error "foo" else bar ``` - it is the usage not to use `;;` to end OCaml sentences (however, inserting `;;` can be useful for debugging syntax errors crossing the boundary of functions) - relevant options in tuareg: ``` (setq tuareg-in-indent 2) (setq tuareg-with-indent 0) (setq tuareg-function-indent 0) (setq tuareg-let-always-indent nil) ``` - when a match fails to compile due to unbound constructors (eg `match x with VarRef x -> bla | ConstRef x -> bli | _ -> blo` when `GlobRef` is not open) it can be resolved in several ways: + locally or globally open `GlobRef` + type annotate `x : GlobRef.t` (where it is introduced, or in the `match` expression, whichever is nicer) + annotate the first branch `GlobRef.VarRef x -> bla` this last solution is not robust to branch reordering so should not be prefered ## Coding methodology - no catchall `try ... with _ -> ...` which catches even `Sys.Break` (Ctrl-C), `Out_of_memory`, `Stack_overflow`, etc. at least, use `try with e when CErrors.noncritical e -> ...` - do not abuse fancy combinators: sometimes what a `let rec` loop does is more readable and simpler to grasp than what a `fold` does - do not break abstractions: if an internal property is hidden behind an interface, do no rely on it in code which uses this interface (e.g. do not use `List.map` thinking it is left-to-right, use `map_left`) - in particular, do not use `=` on abstract types: there is no reason a priori that it is the intended equality on this type; use the `equal` function normally provided with the abstract type - avoid polymorphically typed `=` whose implementation is not optimized in OCaml and which has moreover no reason to be the intended implementation of the equality when it comes to be instantiated on a particular type (e.g. use `List.mem_f`, `List.assoc_f`, rather than `List.mem`, `List.assoc`, etc, unless it is absolutely clear that `=` will implement the intended equality, and with the right complexity) - any new general-purpose enough combinator on list should be put in `cList.ml`, on type option in `option.ml`, etc. - unless for a good reason not to do so, follow the style of the surrounding code in the same file as much as possible, the general guidelines are otherwise "let spacing breathe" (we have large screen nowadays), "make your code easy to read and to understand" - document what is tricky, but do not overdocument, sometimes the choice of names and the structure of the code are better documentation than a long discourse; use of unicode in comments is welcome if it can make comments more readable (then `toggle-enable-multibyte-characters` can help when using the debugger in emacs) - all of initial `open Module`, or of small-scope `let open Module in` or `Module.(...)`, or per-ident `Module.foo` are common practices. `open Module` in the middle of a file should probably be avoided (keep global opens at the top) ## Choice of variable names - be consistent when naming from one function to another - be consistent with the naming adopted in the functions from the same file, or with the naming used elsewhere by similar functions - use variable names which express meaning - keep `cst` or `con` for constants and avoid it for constructors which is otherwise a source of confusion - for constructors, use `ctor` in type constructor (resp. `ctoru` in constructor puniverse); avoid `constr` for `constructor` which could be think as the name of an arbitrary Constr.t - for inductive types, use `ind` in the type inductive (resp `indu` in inductive puniverse) - for `env`, use `env` - for `evar_map`, use `sigma`, with tolerance for `evm` and `evd` - for `named_context` or `rel_context`, use `ctxt` or `ctx` (or `sign`) - for formal/actual indices of inductive types: `realdecls`, `realargs` - for formal/actual parameters of inductive types: `paramdecls`, `paramargs` - for terms, use e.g. `c`, `b`, `a`, ... - if a term is known to be a function: `f`, ... - if a term is known to be a type: `t`, `u`, `typ`, ... - for a declaration, use `d` or `decl` - for errors, exceptions, use `e` ## Common OCaml pitfalls - in ```ocaml match ... with Case1 -> try ... with ... -> ... | Case2 -> ... ``` or in ```ocaml match ... with Case1 -> match ... with SubCase -> ... | Case2 -> ... ``` parentheses (or `begin`/`end` which looks nicer) are needed around the `try` and the inner `match` - in ```ocaml if ... then ... else ... ++ ... ``` the default parenthesizing is somehow counter-intuitive; use ```ocaml (if ... then ... else ...) ++ ... ``` - in `let myspecialfun = mygenericfun args`, be sure that it does not do side-effect; prefer otherwise ```ocaml let myspecialfun arg = mygenericfun args arg ``` to ensure that the function is evaluated at runtime. rocq-9.2.0/dev/doc/unification.txt000066400000000000000000000122271516144147600170770ustar00rootroot00000000000000Some notes about the use of unification in Rocq ----------------------------------------------- There are several applications of unification and pattern-matching ** Unification of types ** - For type inference, inference of implicit arguments * this basically amounts to solve problems of the form T <= U or T = U where T and U are types coming from a given typing problem * this kind of problem has to succeed and all the power of unification is a priori expected (full beta/delta/iota/zeta/nu/mu, pattern-unification, pruning, imitation/projection heuristics, ...) - For lemma application (apply, auto, ...) * these are also problems of the form T <= U on types but with T coming from a lemma and U from the goal * it is not obvious that we always want unification and not matching * it is not clear which amounts of delta one wants to use ** Looking for subterms ** - For tactics applying on subterms: induction, destruct, rewrite - As part of unification of types in the presence of higher-order evars (e.g. when applying a lemma of conclusion "?P t") ---------------------------------------------------------------------- Here are examples of features one may want or not when looking for subterms A- REWRITING 1- Full conversion on closed terms 1a- Full conversion on closed terms in the presence of at least one evars (meta) Section A1. Variable y: nat. Hypothesis H: forall x, x+2 = 0. Goal y+(1+1) = 0. rewrite H. (* 0 = 0 *) Abort. Goal 2+(1+1) = 0. rewrite H. (* 0 = 0 *) Abort. (* This exists since the very beginning of Chet's unification for tactics *) (* But this fails for setoid rewrite *) 1b- Full conversion on closed terms without any evars in the lemma 1b.1- Fails on rewrite (because Unification.w_unify_to_subterm_list replaces unification by check for a syntactic subterm if terms has no evar/meta) Goal 0+1 = 0 -> 0+(1+0) = 0. intros H; rewrite H. (* fails *) Abort. 1b.2- Works with setoid rewrite Require Import Setoid. Goal 0+1 = 0 -> 0+(1+0) = 0. intros H; rewrite H at 1. (* 0 = 0 *) Abort. 2- Using known instances in full conversion on closed terms Section A2. Hypothesis H: forall x, x+(2+x) = 0. Goal 1+(1+2) = 0. rewrite H. Abort. End A2. (* This exists since 8.2 (HH) *) 3- Pattern-unification on Rels Section A3a. Variable F: (nat->nat->nat)->nat. Goal exists f, F (fun x y => f x y) = 0 -> F (fun x y => plus y x) = 0. eexists. intro H; rewrite H. (* 0 = 0 *) Abort. End A3a. (* Works since pattern unification on Meta applied to Rel was introduced *) (* in unification.ml (8.1, Sep 2006, HH) *) Section A3b. Variables x y: nat. Variable H: forall f, f x y = 0. Goal plus y x = 0. rewrite H. (* 0 = 0 *) Abort. End A3b. (* Works since pattern unification on all Meta was supported *) (* in unification.ml (8.4, Jun 2011, HH) *) 4- Unification with open terms Section A4. Hypothesis H: forall x, S x = 0. Goal S 0 = 0. rewrite (H _). (* 0 = 0 *) Abort. End A4. (* Works since unification on Evar was introduced so as to support rewriting *) (* with open terms (8.2, MS, r11543, Unification.w_unify_to_subterm_list ) *) 5- Unification of pre-existing evars 5a- Basic unification of pre-existing evars Section A4. Variables x y: nat. Goal exists z, S z = 0 -> S (plus y x) = 0. eexists. intro H; rewrite H. (* 0 = 0 *) Abort. End A4. (* This worked in 8.2 and 8.3 as a side-effect of support for rewriting *) (* with open terms (8.2, MS, r11543) *) 5b- Pattern-unification of pre-existing evars in rewriting lemma Goal exists f, forall x y, f x y = 0 -> plus y x = 0. eexists. intros x y H; rewrite H. (* 0 = 0 *) Abort. (* Works since pattern-unification on Evar was introduced *) (* in unification.ml (8.3, HH, r12229) *) (* currently governed by a flag: use_evars_pattern_unification *) 5c- Pattern-unification of pre-existing evars in goal Goal exists f, forall x y, plus x y = 0 -> f y x = 0. eexists. intros x y H; rewrite H. (* 0 = 0 *) Abort. (* This worked in 8.2 and 8.3 but was removed for autorewrite in 8.4 *) 5d- Mixing pattern-unification of pre-existing evars in goal and evars in lemma Goal exists f, forall x, (forall y, plus x y = 0) -> forall y:nat, f y x = 0. eexists. intros x H y. rewrite H. (* 0 = 0 *) Abort. (* This worked in 8.2 and 8.3 but was removed for autorewrite in 8.4 *) 6- Multiple non-identical but convertible occurrences Tactic rewrite only considers the first one, from left-to-right, e.g.: Section A6. Variable y: nat. Hypothesis H: forall x, x+2 = 0. Goal (y+(2+0))+(y+(1+1)) = (y+(1+1))+(y+(2+0)). rewrite H. (* 0+(y+(1+1)) = y+(1+1)+0 *) Abort. End A6. Tactic setoid rewrite first looks for syntactically equal terms and if not uses the leftmost occurrence modulo delta. Require Import Setoid. Section A6. Variable y: nat. Hypothesis H: forall x, x+2 = 0. Goal (y+(2+0))+(y+2) = (y+2)+(y+(2+0)). rewrite H at 1 2 3 4. (* (y+(2+0))+0 = 0+(y+(2+0)) *) Abort. Goal (y+(2+0))+(y+(1+1)) = (y+(1+1))+(y+(2+0)). rewrite H at 1 2 3 4. (* 0+(y+(1+1)) = y+(1+1)+0 *) Abort. End A6. 7- Conversion Section A6. Variable y: nat. Hypothesis H: forall x, S x = 0. Goal id 1 = 0. rewrite H. B- ELIMINATION (INDUCTION / CASE ANALYSIS) This is simpler because open terms are not allowed and no unification is involved (8.3). rocq-9.2.0/dev/doc/universes.md000066400000000000000000000245551516144147600164020ustar00rootroot00000000000000Notes on universe polymorphism ------------------------------ The implementation of universe polymorphism introduces a few changes to the API of Rocq. First and foremost, the term language changes, as global references now carry a universe level substitution: ~~~ocaml type 'a puniverses = 'a * UVars.Instance.t type pconstant = constant puniverses type pinductive = inductive puniverses type pconstructor = constructor puniverses type constr = ... | Const of puniverses | Ind of pinductive | Constr of pconstructor ~~~ Universes --------- Universe instances (an array of levels) gets substituted when unfolding definitions, are used to typecheck and are unified according to the rules in the ITP'14 paper on universe polymorphism in Coq. ~~~ocaml type Level.t = Set | Prop | Level of int * dirpath (* hashconsed *) type Instance.t = Level.t array type Universe.t = Level.t list (* hashconsed *) ~~~ The universe module defines modules and abstract types for levels, universes etc.. Structures are hashconsed (with a hack to take care of the fact that deserialization breaks sharing). Definitions (constants, inductives) now carry around not only constraints but also the universes they introduced (a UVars.UContext.t). There is another kind of contexts `Univ.ContextSet.t`, the latter has a set of universes, while the former has serialized the levels in an array, and is used for polymorphic objects. Both have "reified" constraints depending on global and local universes. A polymorphic definition is abstract w.r.t. the variables in this context, while a monomorphic one (or template polymorphic) just adds the universes and constraints to the global universe context when it is put in the environment. No other universes than the global ones and the declared local ones are needed to check a declaration, hence the kernel does not produce any constraints anymore, apart from module subtyping.... There are hence two conversion functions now: `check_conv` and `infer_conv`: the former just checks the definition in the current env (in which we usually push_universe_context of the associated context), and `infer_conv` which produces constraints that were not implied by the ambient constraints. Ideally, that one could be put out of the kernel, but currently module subtyping needs it. Inference of universes is now done during refinement, and the evar_map carries the incrementally built universe context, starting from the global universe constraints (see `Evd.from_env`). `Evd.conversion` is a wrapper around `infer_conv` that will do the bookkeeping for you, it uses `evar_conv_x`. There is a universe substitution being built incrementally according to the constraints, so one should normalize at the end of a proof (or during a proof) with that substitution just like we normalize evars. There are some nf_* functions in library/universes.ml to do that. Additionally, there is a minimization algorithm in there that can be applied at the end of a proof to simplify the universe constraints used in the term. It is heuristic but validity-preserving. No user-introduced universe (i.e. coming from a user-written anonymous Type) gets touched by this, only the fresh universes generated for each global application. Using ~~~ocaml val pf_constr_of_global : Globnames.global_reference -> (constr -> tactic) -> tactic ~~~ Is the way to make a constr out of a global reference in the new API. If they constr is polymorphic, it will add the necessary constraints to the evar_map. Even if a constr is not polymorphic, we have to take care of keeping track of its universes. Typically, using: ~~~ocaml mkApp (coq_id_function, [| A; a |]) ~~~ and putting it in a proof term is not enough now. One has to somehow show that A's type is in cumululativity relation with id's type argument, incurring a universe constraint. To do this, one can simply call Typing.resolve_evars env evdref c which will do some infer_conv to produce the right constraints and put them in the evar_map. Of course in some cases you might know from an invariant that no new constraint would be produced and get rid of it. Anyway the kernel will tell you if you forgot some. As a temporary way out, `Universes.constr_of_global` allows you to make a constr from any non-polymorphic constant, but it will fail on polymorphic ones. Other than that, unification (w_unify and evarconv) now take account of universes and produce only well-typed evar_maps. Some syntactic comparisons like the one used in `change` have to be adapted to allow identification up-to-universes (when dealing with polymorphic references), `make_eq_univs_test` is there to help. In constr, there are actually many new comparison functions to deal with that: ~~~ocaml (** [equal a b] is true if [a] equals [b] modulo alpha, casts, and application grouping *) val equal : constr -> constr -> bool (** [eq_constr_univs u a b] is [true] if [a] equals [b] modulo alpha, casts, application grouping and the universe equalities in [u]. *) val eq_constr_univs : constr Univ.check_function (** [leq_constr_univs u a b] is [true] if [a] is convertible to [b] modulo alpha, casts, application grouping and the universe inequalities in [u]. *) val leq_constr_univs : constr Univ.check_function (** [eq_constr_universes a b] [true, c] if [a] equals [b] modulo alpha, casts, application grouping and the universe equalities in [c]. *) val eq_constr_universes : constr -> constr -> bool Univ.universe_constrained (** [leq_constr_universes a b] [true, c] if [a] is convertible to [b] modulo alpha, casts, application grouping and the universe inequalities in [c]. *) val leq_constr_universes : constr -> constr -> bool Univ.universe_constrained (** [eq_constr_univs a b] [true, c] if [a] equals [b] modulo alpha, casts, application grouping and ignoring universe instances. *) val eq_constr_nounivs : constr -> constr -> bool ~~~ The `_univs` versions are doing checking of universe constraints according to a graph, while the `_universes` are producing (non-atomic) universe constraints. The non-atomic universe constraints include the `ULub` constructor: when comparing `f (* u1 u2 *) c` and `f (* u1' u2' *) c` we add ULub constraints on `u1, u1'` and `u2, u2'`. These are treated specially: as unfolding `f` might not result in these unifications, we need to keep track of the fact that failure to satisfy them does not mean that the term are actually equal. This is used in unification but probably not necessary to the average programmer. Another issue for ML programmers is that tables of constrs now usually need to take a `constr Univ.in_universe_context_set` instead, and properly refresh the universes context when using the constr, e.g. using Clenv.refresh_undefined_univs clenv or: ~~~ocaml (** Get fresh variables for the universe context. Useful to make tactics that manipulate constrs in universe contexts polymorphic. *) val fresh_universe_context_set_instance : universe_context_set -> universe_level_subst * universe_context_set ~~~ The substitution should be applied to the constr(s) under consideration, and the context_set merged with the current evar_map with: ~~~ocaml val merge_context_set : rigid -> evar_map -> Univ.universe_context_set -> evar_map ~~~ The `rigid` flag here should be `Evd.univ_flexible` most of the time. This means the universe levels of polymorphic objects in the constr might get instantiated instead of generating equality constraints (Evd.univ_rigid does that). On this issue, I recommend forcing commands to take `global_reference`s only. Users can declare their specialized terms used as hints as constants and this is cleaner. Alas, backward-compatibility-wise, this is the only solution I found. In the case of global_references only, it's just a matter of using `Evd.fresh_global` / `pf_constr_of_global` to let the system take care of universes. The universe graph ------------------ To accommodate universe polymorphic definitions, the graph structure in kernel/univ.ml was modified. The new API forces every universe to be declared before it is mentioned in any constraint. This forces to declare every universe to be >= Set or > Set. Every universe variable introduced during elaboration is >= Set. Every _global_ universe is now declared explicitly > Set, _after_ typechecking the definition. In polymorphic definitions Type@{i} ranges over Set and any other universe j. However, at instantiation time for polymorphic references, one can try to instantiate a universe parameter with Prop as well, if the instantiated constraints allow it. The graph invariants ensure that no universe i can be set lower than Set, so the chain of universes always bottoms down at Prop < Set. Modules ------- One has to think of universes in modules as being globally declared, so when including a module (type) which declares a type i (e.g. through a parameter), we get back a copy of i and not some fresh universe. Incompatibilities ----------------- Old-style universe polymorphic definitions were implemented by taking advantage of the fact that elaboration (i.e., pretyping and unification) were _not_ universe aware, so some of the constraints generated during pretypechecking would be forgotten. In the current setting, this is not possible, as unification ensures that the substitution is built is entirely well-typed, even w.r.t universes. This means that some terms that type-checked before no longer do, especially projections of the pair: ~~~coq @fst ?x ?y : prod ?x ?y : Type (max(Datatypes.i, Datatypes.j)). ~~~ The "template universe polymorphic" variables i and j appear during typing without being refreshed, meaning that they can be lowered (have upper constraints) with user-introduced universes. In most cases this won't work, so ?x and ?y have to be instantiated earlier, either from the type of the actual projected pair term (some t : prod A B) or the typing constraint. Adding the correct type annotations will always fix this. Unification semantics --------------------- In Ltac, matching with: - a universe polymorphic constant `c` matches any instance of the constant. - a variable ?x already bound to a term `t` (non-linear pattern) uses strict equality of universes (e.g., Type@{i} and Type@{j} are not equal). In tactics: - `change foo with bar`, `pattern foo` will unify all instances of `foo` (and convert them with `bar`). This might incur unifications of universes. `change` uses conversion while `pattern` only does syntactic matching up-to unification of universes. - `apply`, `refine` use unification up to universes. rocq-9.2.0/dev/doc/xml-protocol.md000066400000000000000000000736331516144147600170170ustar00rootroot00000000000000# Coq XML Protocol This document is based on documentation originally written by CJ Bell for his [vscoq](https://github.com/coq-community/vscoq/) project. Here, the aim is to provide a "hands on" description of the XML protocol that coqtop and IDEs use to communicate. The protocol first appeared with Coq 8.5, and is used by RocqDE, [vscoq legacy](https://github.com/coq-community/vscoq-legacy/), and other user interfaces. A somewhat out-of-date description of the async state machine is [documented here](https://github.com/ejgallego/jscoq/blob/v8.16/etc/notes/coq-notes.md). OCaml types for the protocol can be found in the [`ide/protocol/interface.ml` file](/ide/protocol/interface.ml). Changes to the XML protocol are documented as part of [`dev/doc/changes.md`](/dev/doc/changes.md). * [Commands](#commands) - [About](#command-about) - [Add](#command-add) - [EditAt](#command-editAt) - [Init](#command-init) - [Goal](#command-goal) - [Subgoals](#command-subgoals) - [Status](#command-status) - [Query](#command-query) - [Evars](#command-evars) - [Hints](#command-hints) - [Search](#command-search) - [GetOptions](#command-getoptions) - [SetOptions](#command-setoptions) - [MkCases](#command-mkcases) - [StopWorker](#command-stopworker) - [PrintAst](#command-printast) - [Annotate](#command-annotate) - [Db_cmd](#command-db_cmd) - [Db_upd_bpts](#command-db_upd_bpts) - [Db_continue](#command-db_continue) - [Db_stack](#command-db_stack) - [Db_vars](#command-db_vars) * [Feedback messages](#feedback) - [Added Axiom](#feedback-addedaxiom) - [Processing](#feedback-processing) - [Processed](#feedback-processed) - [Incomplete](#feedback-incomplete) - [Complete](#feedback-complete) - [GlobRef](#feedback-globref) - [Error](#feedback-error) - [InProgress](#feedback-inprogress) - [WorkerStatus](#feedback-workerstatus) - [File Dependencies](#feedback-filedependencies) - [File Loaded](#feedback-fileloaded) - [Message](#feedback-message) - [Custom](#feedback-custom) * [Ltac-debug messages](ltac_debug) * [Highlighting Text](#highlighting) Sentences: each command sent to Coqtop is a "sentence"; they are typically terminated by ".\s" (followed by whitespace or EOF). Examples: "Lemma a: True.", "(* asdf *) Qed.", "auto; reflexivity." In practice, the command sentences sent to Coqtop are terminated at the "." and start with any previous whitespace. Each sentence is assigned a unique stateId after being sent to Coq (via Add). States: * Processing: has been received by Coq and has no obvious syntax error (that would prevent future parsing) * Processed: * InProgress: * Incomplete: the validity of the sentence cannot be checked due to a prior error * Complete: * Error: the sentence has an error State ID 0 is reserved as a 'dummy' state. -------------------------- ## Commands ### **About(unit)** Returns information about the protocol and build dates for Coqtop. ``` ``` #### *Returns* ```html 8.6 20150913 December 2016 Dec 23 2016 16:16:30 ``` The string fields are the Coq version, the protocol version, the release date, and the compile time of Coqtop. The protocol version is a date in YYYYMMDD format, where "20150913" corresponds to Coq 8.6. An IDE that wishes to support multiple Coq versions can use the protocol version information to know how to handle output from Coqtop. ### **Add(command: string, editId: integer, stateId: integer, verbose: boolean, bp: integer, line_nb: integer, bol_pos: integer)** Adds a toplevel command (e.g. vernacular, definition, tactic) to the given state. `verbose` controls whether out-of-band messages will be generated for the added command (e.g. "foo is assumed" in response to adding "Axiom foo: nat."). `bp`, `line_nb` and `bol_pos` are the `Loc.t` values relative to the IDE buffer. ```html ${command} ${editId} ${bp} ${line_nb} ${bol_pos} ``` #### *Returns* * The added command is given a fresh `stateId` and becomes the next "tip". ```html ``` * When closing a focused proof (in the middle of a bunch of interpreted commands), the `Qed` will be assigned a prior `stateId` and `nextStateId` will be the id of an already-interpreted state that should become the next tip. ```html ${message} ``` * Failure: - Syntax error. Error offsets are byte offsets (not character offsets) with respect to the start of the sentence, starting at 0. ```html ${errorMessage} ``` - Another kind of error, for example, Qed with a pending goal. ```html ${errorMessage} ``` Note that IDEs may need to convert byte offsets passed in the four position fields of the location to character offsets to correctly handle multi-byte characters. Also, due to asynchronous evaluation, line number fields of locations may need to be adjusted if the sentence has moved since it was sent to Coqtop. ------------------------------- ### **EditAt(stateId: integer)** Moves current tip to `${stateId}`, such that commands may be added to the new state ID. ```html ``` #### *Returns* * Simple backtrack; focused stateId becomes the parent state ```html ``` * New focus; focusedQedStateId is the closing Qed of the new focus; sentences between the two should be cleared ```html ``` * Failure: If `stateId` is in an error-state and cannot be jumped to, `errorFreeStateId` is the parent state of `stateId` that should be edited instead. ```html ${errorMessage} ``` ------------------------------- ### **Init()** * No options. ```html ``` * With options: ```html ``` Providing the script file `$v_file.v` enables Coq to use the `.$v_file.aux` file created during compilation. Those file contain timing information that allow Coq to choose smartly between asynchronous and synchronous processing of proofs. #### *Returns* * The initial stateId (not associated with a sentence) ```html ``` ------------------------------- ### **Goal()** ```html ``` #### *Returns* * If there is a goal. `shelvedGoals` and `abandonedGoals` have the same structure as the first set of (current/foreground) goals. `backgroundGoals` contains a list of pairs of lists of goals (list ((list Goal)*(list Goal))); it represents a "focus stack" ([see code for reference](https://github.com/rocq-prover/rocq/blob/trunk/engine/proofview.ml#L113)). Each time a proof is focused, it will add a new pair of lists-of-goals. The first pair is the most nested set of background goals, the last pair is the top level set of background goals. The first list in the pair is in reverse order. Each time you focus the goal (e.g. using `Focus` or a bullet), a new pair will be prefixed to the list. ```html ``` For example, this script: ```coq Goal P -> (1=1/\2=2) /\ (3=3 /\ (4=4 /\ 5=5) /\ 6=6) /\ 7=7. intros. split; split. (* current visible goals are [1=1, 2=2, 3=3/\(4=4/\5=5)/\6=6, 7=7] *) Focus 3. (* focus on 3=3/\(4=4/\5=5)/\6=6; bg-before: [1=1, 2=2], bg-after: [7=7] *) split; [ | split ]. (* current visible goals are [3=3, 4=4/\5=5, 6=6] *) Focus 2. (* focus on 4=4/\5=5; bg-before: [3=3], bg-after: [6=6] *) * (* focus again on 4=4/\5=5; bg-before: [], bg-after: [] *) split. (* current visible goals are [4=4,5=5] *) ``` should generate the following goals structure: ``` goals: [ P|-4=4, P|-5=5 ] background: [ ( [], [] ), (* bullet with one goal has no before or after background goals *) ( [ P|-3=3 ], [ P|-6=6 ] ), (* Focus 2 *) ( [ P|-2=2, P|-1=1 ], [ P|-7=7 ] ) (* Focus 3; notice that 1=1 and 2=2 are reversed *) ] ``` Pseudocode for listing all of the goals in order: `rev (flat_map fst background) ++ goals ++ flat_map snd background`. * No goal: ```html ``` ------------------------------- ### **Subgoals(flags: goal_flags)** Similar to [Goal](#command-goal), but with `flags` to control whether to include information about `fg`, `bg`, `shelved`, or `given_up` goals. The flags also include `mode`, which is either "full" (return hypotheses and conclusion for each goal) or "short" (return only the conclusion). The "short" mode is useful for speeding up goal display when there are many shelved or admitted goals with large proof contexts, but the IDE only needs to know their conclusions or how many there are. ```html ${mode} ``` #### Returns * The same as [Goal](#command-goal). ------------------------------- ### **Status(force: bool)** Returns information about the current proofs. RocqIDE typically sends this message with `force = false` after each sentence, and with `force = true` if the user wants to force the checking of all proofs (wheels button). In terms of the STM API, `force` triggers a `Join`. ```html ``` #### *Returns* * ```html ${path} ${proofName} ${allProofs} ${proofNumber} ``` ------------------------------- ### **Query(route_id: integer, query: string, stateId: integer)** `routeId` can be used to distinguish the result of a particular query, `stateId` should be set to the state the query should be run. ```html ${query} ``` #### *Returns* * ```html ${message} ``` Before 8.8, `Query` only executed the first command present in the `query` string; starting with 8.8, the caller may include several statements. This is useful for instance for temporarily setting an option and then executing a command. ------------------------------- ### **Evars()** ```html ``` #### *Returns* * ```html ``` ------------------------------- ### **Hints()** ```html ``` #### *Returns* * ```html ``` ------------------------------- ### **Search([(constraintTypeN: string, constraintValueN: string, positiveConstraintN: boolean)])** Searches for objects that satisfy a list of constraints. If `${positiveConstraint}` is `false`, then the constraint is inverted. ```html ${constraintValue1} ... bool_rect ``` #### *Returns* * ```html ${metaInfo} ... ${name} ${definition} ... ``` ##### Types of constraints: * Name pattern: `${constraintType} = "name_pattern"`; `${constraintValue}` is a regular expression string. * Type pattern: `${constraintType} = "type_pattern"`; `${constraintValue}` is a pattern (???: an open gallina term) string. * SubType pattern: `${constraintType} = "subtype_pattern"`; `${constraintValue}` is a pattern (???: an open gallina term) string. * In module: `${constraintType} = "in_module"`; `${constraintValue}` is a list of strings specifying the module/directory structure. * Include blacklist: `${constraintType} = "include_blacklist"`; `${constraintValue}` *is omitted*. ------------------------------- ### **GetOptions()** ```html ``` #### *Returns* * ```html ${string1}... ${sync} ${deprecated} ${name} ${option_value} ... ``` ------------------------------- ### **SetOptions(options)** Sends a list of option settings, where each setting roughly looks like: `([optionNamePart1, ..., optionNamePartN], value)`. ```html optionNamePart1 ... optionNamePartN ... Printing Width ``` RocqIDE sends the following settings (defaults in parentheses): ``` Printing Width : (60), Printing Coercions : (), Printing Matching : (...true...) Printing Notations : (...true...) Printing Existential Instances : (...false...) Printing Implicit : (...false...) Printing All : (...false...) Printing Universes : (...false...) ``` #### *Returns* * ```html ``` ------------------------------- ### **MkCases(...)** ```html ... ``` #### *Returns* * ```html ${string1}... ... ``` ------------------------------- ### **StopWorker(worker: string)** ```html ${worker} ``` #### *Returns* * ```html ``` ------------------------------- ### **PrintAst(stateId: integer)** ```html ``` #### *Returns* * ```html ... ${token} ... ... ... ``` ------------------------------- ### **Annotate(annotation: string)** ```html ${annotation} ``` #### *Returns* * take `Theorem plus_0_r : forall n : nat, n + 0 = n.` as an example. ```html Theorem  plus_0_r :  forall  n :  nat n  +   0  =   n . ``` ------------------------------- ### **Db_cmd(user_input: string)** ```html ${user_input} ``` #### *Returns* * `h` directs Coq to process the debugger command "h". It returns unit. This call is processed only when the debugger is stopped and has just sent a `prompt` message. ------------------------------- ### **Db_upd_bpts(...)** The call passes a list of breakpoints to set or clear. The string is the absolute pathname of the .v file (or "ToplevelInput"), the int is the byte offset within the file and the boolean is true to set a breakpoint and false to clear it. Breakpoints can be updated when Coq is not busy or when Coq is stopped in the debugger. If this message is sent in other states, it will be received and processed when Coq is no longer busy or execution stops in the debugger. ```html /home/proj/coq/ide/rocqide/debug.v 22 ``` #### *Returns* * Unit. ------------------------------- ### **Db_continue(option: integer)** Tells Coq to continue processing the proof when it is stopped in the debugger. The integer indicates when the debugger should stop again: ``` 0: StepIn - step one tactic. If it is an Ltac tactic, stop at the first tactic within it 1: StepOver - step over one tactic. if it is an Ltac tactic, don't stop within it 2: StepOut - stop on the first tactic after exiting the current Ltac tactic 3: Continue - continue running until the next breakpoint or the debugger exits 4: Interrupt - generate a User interrupt (for use when stopped in the debugger; otherwise interrupt is sent as a signal) ``` If the debugger encounters a breakpoint during a StepOver or a StepOut, it will stop at the breakpoint. ```html 1 ``` #### *Returns* * Unit. ### **Db_stack()** Returns the Ltac call stack. Each entry has a description of what was called (e.g. the tactic name) plus the absolute pathname of the file and the offset of the call therein. The top of stack is the first entry in the list. Offsets are in bytes, not counts of unicode characters. ```html ``` #### *Returns* ```html vars2.z : ``` ### **Db_vars(frame: integer)** Returns a list of the names and values of the local variables defined in the specified frame of the Ltac call stack. (0 = top of stack, 1, 2, ...). ```html 0 ``` #### *Returns* ```html w 0 : ``` ------------------------------- ## Feedback messages Feedback messages are issued out-of-band, giving updates on the current state of sentences/stateIds, worker-thread status, etc. In the descriptions of feedback syntax below, wherever a `state_id` tag may occur, there may instead be an `edit_id` tag. * Added Axiom: in response to `Axiom`, `admit`, `Admitted`, etc. ```html ``` * Processing ```html ${workerName} ``` * Processed ```html ``` * Incomplete ```html ``` * Complete * GlobRef * Error. Issued, for example, when a processed tactic has failed or is unknown. The error offsets may both be 0 if there is no particular syntax involved. * InProgress ```html 1 ``` * WorkerStatus Ex: `workername = "proofworker:0"` Ex: `status = "Idle"` or `status = "proof: myLemmaName"` or `status = "Dead"` ```html ${workerName} ${status} ``` * File Dependencies. Typically in response to a `Require`. Dependencies are *.vo files. - State `stateId` directly depends on `dependency`: ```html ``` - State `stateId` depends on `dependency` via dependency `sourceDependency` ```xml ${dependency} ``` * File Loaded. For state `stateId`, module `module` is being loaded from `voFileName` ```xml ${module} ${voFileName`} ``` * Message. `level` is one of `{info,warning,notice,error,debug}`. For example, in response to an add `"Axiom foo: nat."` with `verbose=true`, message `foo is assumed` will be emitted in response. ```xml ${message} ``` * Location, a Coq location (`Loc.t`) ```xml Custom. A feedback message that Coq plugins can use to return structured results, including results from Ltac profiling. `customTag` is intended as a unique string that identifies what kind of payload is contained in `customXML`. An optional location may be attached if present in the message. ```xml ${customTag} ${customXML} ``` ------------------------------- ## Ltac-debug messages Ltac-debug messages are issued out-of-band, similar to Feedback messages. The response contains an identifying tag and a ``. Currently these tags are used: * **output** - ordinary output for display in the Messages panel * **goal** - the current goal for the debugger, for display in the Messages panel or elsewhere * **prompt** - output for display in the Messages panel prompting the user to enter a debug command, allowing RocqIDE to display it without appending a newline. It also signals that coqidetop is waiting to receive a debugger-specific message such as [Db_cmd](#command-db_cmd). ```xml prompt : ``` ------------------------------- ## Highlighting Text [Proof diffs](https://coq.inria.fr/distrib/current/refman/proof-engine/proof-handling.html#showing-differences-between-proof-steps) highlight differences between the current and previous proof states in the displayed output. These are represented by tags embedded in output fields of the XML document. There are 4 tags that indicate how the enclosed text should be highlighted: - diff.added - added text - diff.removed - removed text - diff.added.bg - unchanged text in a line that has additions ("bg" for "background") - diff.removed.bg - unchanged text in a line that has removals RocqIDE, Proof General and coqtop currently use 2 shades of green and 2 shades of red as the background color for highlights. Coqtop and RocqIDE also apply underlining and/or strikeout highlighting for the sake of the color blind. For example, `ABC` indicates that "ABC" should be highlighted as added text. Tags can be nested, such as: `A + 1 + B`. IDE code displaying highlighted strings should maintain a stack for nested tags and the associated highlight. Currently the diff code only nests at most 2 tags deep. If an IDE uses other highlights such as text foreground color or italic text, it may need to merge the background color with those other highlights to give the desired (IDE dependent) behavior. The current implementations avoid highlighting white space at the beginning or the end of a line. This gives a better appearance. There may be additional text that is marked with other tags in the output text. IDEs probably should ignore and not display tags they don't recognize. Some internal details about generating tags within Coq (e.g. if you want to add additional tags): Tagged output strings are generated from Pp.t's. Use Pp.tag to highlight a Pp.t using one of the tags listed above. A span of tokens can be marked by using "start." on the first token and "end." on the last token. (Span markers are needed because a span of tokens in the output may not match nesting of layout boxes in the Pp.t.) The conversion from the Pp.t to the XML-tagged string replaces the "start.\*" and "end.\*" tags with the basic tags. rocq-9.2.0/dev/dune000066400000000000000000000047711516144147600141440ustar00rootroot00000000000000(library (name dev) (public_name rocq-runtime.dev) (synopsis "Rocq's Debug Printers") (wrapped false) (modules top_printers vm_printers) ; NB currently we have no "install_printer" using ltac2, ; but we still want to load_printer ltac2 ; so that its genarg printers are present in the debugger's printer process (libraries rocq-runtime.vernac rocq-runtime.plugins.ltac rocq-runtime.plugins.ltac2)) (library (name debugger_support) (public_name rocq-runtime.debugger_support) (synopsis "Rocq Support for ocamldebug") (wrapped false) (modules debugger_support) (libraries rocq-runtime.dev)) (rule (targets dune-dbg) (deps dune-dbg.in ../checker/coqchk.bc ../topbin/rocqworker.bc ../topbin/rocqnative.bc ; We require all the OCaml libs to be in place and searchable ; by OCamlfind, this is a bit of a hack but until Dune gets ; proper ocamldebug support we have to live with that. %{lib:rocq-runtime.config:config.cma} %{lib:rocq-runtime.clib:clib.cma} %{lib:rocq-runtime.lib:lib.cma} %{lib:rocq-runtime.kernel:kernel.cma} %{lib:rocq-runtime.vm:coqrun.cma} %{lib:rocq-runtime.vm:../../stublibs/dllcoqrun_stubs.so} %{lib:rocq-runtime.library:library.cma} %{lib:rocq-runtime.engine:engine.cma} %{lib:rocq-runtime.pretyping:pretyping.cma} %{lib:rocq-runtime.gramlib:gramlib.cma} %{lib:rocq-runtime.interp:interp.cma} %{lib:rocq-runtime.proofs:proofs.cma} %{lib:rocq-runtime.parsing:parsing.cma} %{lib:rocq-runtime.printing:printing.cma} %{lib:rocq-runtime.tactics:tactics.cma} %{lib:rocq-runtime.vernac:vernac.cma} %{lib:rocq-runtime.plugins.ltac:ltac_plugin.cma} %{lib:rocq-runtime.plugins.ltac2:ltac2_plugin.cma} %{lib:rocq-runtime.dev:dev.cma} %{lib:rocq-runtime.debugger_support:debugger_support.cmi} %{lib:rocq-runtime.debugger_support:debugger_support.cma} %{lib:rocq-runtime.debugger_support:../META}) (action (copy dune-dbg.in dune-dbg))) (alias (name ml_toplevel_files) (deps (glob_files ml_toplevel/**))) (install (section lib) (package rocq-runtime) (files (ml_toplevel/include as dev/ml_toplevel/include) (ml_toplevel/include_directories as dev/ml_toplevel/include_directories) (ml_toplevel/include_printers as dev/ml_toplevel/include_printers) (ml_toplevel/include_utilities as dev/ml_toplevel/include_utilities))) ; TODO: the above can be written as follow: ; (files (glob_files (ml_toplevel/** with_prefix dev))) ; , but this is only possible with dune language 3.11 or later rocq-9.2.0/dev/dune-dbg.in000077500000000000000000000025331516144147600153000ustar00rootroot00000000000000#!/usr/bin/env bash # Run in a proper install dune env. opts=() while [[ $# -gt 0 ]]; do case $1 in -emacs) shift opts+=("-emacs") ;; -I) shift opts+=("-I" "$1") shift ;; coqchk) shift exe=_build/default/checker/coqchk.bc opts+=($(ocamlfind query -recursive -i-format rocq-runtime.checklib)) break ;; rocqide) shift exe=_build/default/ide/rocqide/rocqide_main.bc break ;; coqc) shift exe="_build/default/topbin/rocqworker.bc --kind=compile" break ;; coqtop) shift exe=_build/default/topbin/coqtop_byte_bin.bc break ;; coqnative) shift exe=_build/default/topbin/rocqnative.bc break ;; *) echo "usage: dune exec -- dev/dune-dbg [-emacs] {coqchk|rocqide|coqc|coqtop|coqdep|coqnative} coqargs" exit 1 ;; esac done export ROCQLIB=$PWD/_build/install/default/lib/coq ocamldebug "${opts[@]}" $(ocamlfind query -recursive -i-format rocq-runtime.dev) $(ocamlfind query -i-format -descendants rocq-runtime.vernac) -I +threads -I dev $exe "$@" rocq-9.2.0/dev/dune-workspace.all000066400000000000000000000002251516144147600166750ustar00rootroot00000000000000(lang dune 2.0) ; Add custom flags here. Default developer profile is `dev` (context (opam (switch 4.14.0))) (context (opam (switch 4.14.0+32bit))) rocq-9.2.0/dev/dynlink.ml000066400000000000000000000033141516144147600152600ustar00rootroot00000000000000 (** Some architectures may have a native ocaml compiler but no native dynlink.cmxa (e.g. ARM). If you still want to build a native coqtop there, you'll need this dummy implementation of Dynlink. Compile it and install with: ocamlopt -a -o dynlink.cmxa dynlink.ml sudo cp -i dynlink.cmxa `ocamlopt -where` Then build coq this way: ./configure -natdynlink no && make world *) let is_native = true (* This file will only be given to the native compiler *) type linking_error = | Undefined_global of string | Unavailable_primitive of string | Uninitialized_global of string type error = | Not_a_bytecode_file of string | Inconsistent_import of string | Unavailable_unit of string | Unsafe_file | Linking_error of string * linking_error | Corrupted_interface of string | File_not_found of string | Cannot_open_dll of string | Inconsistent_implementation of string exception Error of error let error_message = function | Not_a_bytecode_file s -> "Native dynamic link not supported (module "^s^")" | _ -> "Native dynamic link not supported" let loadfile : string -> unit = fun s -> raise (Error (Not_a_bytecode_file s)) let loadfile_private = loadfile let adapt_filename s = s let init () = () let allow_only : string list -> unit = fun _ -> () let prohibit : string list -> unit = fun _ -> () let default_available_units : unit -> unit = fun _ -> () let allow_unsafe_modules : bool -> unit = fun _ -> () let add_interfaces : string list -> string list -> unit = fun _ _ -> () let add_available_units : (string * Digest.t) list -> unit = fun _ -> () let clear_available_units : unit -> unit = fun _ -> () let digest_interface : string -> string list -> Digest.t = fun _ _ -> failwith "digest_interface" rocq-9.2.0/dev/header.c000066400000000000000000000012431516144147600146510ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* &2 echo "usage: $CALLNAME " >&2 echo "The order of commits is as given to 'git diff'" } if [ "$#" != 2 ]; then usage exit 1 fi REDBOLD="\033[31;1m" RESET="\033[0m" function redprint { if true || [ "$COQ_CI_COLOR" ]; then printf "$REDBOLD%s$RESET\n" "$1" else printf '%s\n' "$1" fi } BASE_COMMIT="$1" HEAD_COMMIT="$2" tmp=$(mktemp -d) git worktree add "$tmp" "$HEAD_COMMIT" pushd "$tmp" bad_ws=() bad_compile=() while IFS= read -r commit; do echo Checking "$commit" git checkout "$commit" # git diff --check # uses .gitattributes to know what to check if ! git diff --check "${commit}^" "$commit"; then bad_ws+=("$commit") fi if ! make check then bad_compile+=("$commit") fi done < <(git rev-list "$HEAD_COMMIT" --not "$BASE_COMMIT" --) popd git worktree remove "$tmp" # report errors CODE=0 if [ "${#bad_ws[@]}" != 0 ] then >&2 redprint "Whitespace errors!" >&2 echo "In commits ${bad_ws[*]}" >&2 echo "If you use emacs, you can prevent this kind of error from reoccurring by installing ws-butler and enabling ws-butler-convert-leading-tabs-or-spaces." >&2 echo CODE=1 fi if [ "${#bad_compile[@]}" != 0 ] then >&2 redprint "Compilation errors!" >&2 echo "In commits ${bad_compile[*]}" >&2 echo CODE=1 fi exit $CODE rocq-9.2.0/dev/lint-repository.sh000077500000000000000000000033051516144147600170000ustar00rootroot00000000000000#!/usr/bin/env bash # A script to check prettyness over the repository. # lint-commits.sh seeks to prevent the worsening of already present # problems, such as tab indentation in ml files. lint-repository.sh # also seeks to prevent the (re-)introduction of solved problems, such # as newlines at the end of .v files. CODE=0 # if COQ_CI_COLOR is set (from the environment) keep it intact (even when it's the empty string)' if ! [ "${COQ_CI_COLOR+1}" ]; then # NB: in CI TERM is unset in the environment # when TERM is unset, bash sets it to "dumb" as a bash variable (not exported?) if { [ -t 1 ] && ! [ "$TERM" = dumb ]; } || [ "$CI" ] then export COQ_CI_COLOR=1 else export COQ_CI_COLOR= fi fi if [[ $(git log -n 1 --pretty='format:%s') == "[CI merge]"* ]]; then # The second parent of bot merges is from the PR, the first is # current master head=$(git rev-parse HEAD^2) else head=$(git rev-parse HEAD) fi # We assume that all non-bot merge commits are from the main branch # For Rocq it is extremely rare for this assumption to be broken read -r base < <(git log -n 1 --merges --pretty='format:%H' "$head") dev/lint-commits.sh "$base" "$head" || CODE=1 # Check that the files with 'whitespace' gitattribute end in a newline. # xargs exit status is 123 if any file failed the test echo Checking end of file newlines find . "(" -path ./.git -prune ")" -o -type f -print0 | xargs -0 dev/tools/check-eof-newline.sh || CODE=1 echo Checking overlays dev/tools/check-overlays.sh || CODE=1 echo Checking CACHEKEY dev/tools/check-cachekey.sh || CODE=1 # Check that doc/tools/docgram/fullGrammar is up-to-date echo Checking grammar files make SHOW='@true ""' doc_gram_verify || CODE=1 exit $CODE rocq-9.2.0/dev/macosify_accel.sh000077500000000000000000000001641516144147600165560ustar00rootroot00000000000000#!/usr/bin/sed -f s/^;\{0,1\} *\(.*\)\(.*\)$/\1\2/ s/^;\{0,1\} *\(.*\)\(.*\)$/\1\2/ rocq-9.2.0/dev/ml_toplevel/000077500000000000000000000000001516144147600155775ustar00rootroot00000000000000rocq-9.2.0/dev/ml_toplevel/include000066400000000000000000000014001516144147600171400ustar00rootroot00000000000000(* The main file included in the OCaml toplevel. *) #use "ml_toplevel/include_directories";; #use "ml_toplevel/include_printers";; #use "ml_toplevel/include_utilities";; let go () = Flags.with_option Toploop.may_trace (fun () -> Coqloop.ml_toplevel_state := Some (Coqloop.loop ~state:(Option.get !Coqloop.ml_toplevel_state))) (); print_newline () let () = if not !Coqloop.ml_toplevel_include_ran then Toploop.add_directive "go" (Toploop.Directive_none go) Toploop.{section="Coq"; doc="Run Rocq toplevel loop"} let _ = print_newline (); print_endline "OCaml toplevel with Rocq printers and utilities (to go back to Rocq, use `#quit;;`, or `#go;;` if `#trace` was used)" let _ = Coqloop.ml_toplevel_include_ran := true rocq-9.2.0/dev/ml_toplevel/include_directories000066400000000000000000000017421516144147600215450ustar00rootroot00000000000000#directory "+compiler-libs";; #directory "_build/default/lib/.lib.objs/byte/";; #directory "_build/default/clib/.clib.objs/byte/";; #directory "_build/default/kernel/.kernel.objs/byte/";; #directory "_build/default/library/.library.objs/byte/";; #directory "_build/default/engine/.engine.objs/byte/";; #directory "_build/default/pretyping/.pretyping.objs/byte/";; #directory "_build/default/interp/.interp.objs/byte/";; #directory "_build/default/parsing/.parsing.objs/byte/";; #directory "_build/default/gramlib/.gramlib.objs/byte/";; #directory "_build/default/proofs/.proofs.objs/byte/";; #directory "_build/default/tactics/.tactics.objs/byte/";; #directory "_build/default/printing/.printing.objs/byte/";; #directory "_build/default/vernac/.vernac.objs/byte/";; #directory "_build/default/stm/.stm.objs/byte/";; #directory "_build/default/toplevel/.toplevel.objs/byte/";; #directory "_build/default/plugins/ltac/.ltac_plugin.objs/byte/";; #directory "_build/default/dev/.dev.objs/byte/";; rocq-9.2.0/dev/ml_toplevel/include_printers000066400000000000000000000111471516144147600210770ustar00rootroot00000000000000#install_printer (* identifier *) Top_printers.ppid;; #install_printer (* identifier *) Top_printers.ppidset;; #install_printer (* Intset.t *) Top_printers.ppintset;; #install_printer (* mod_bound_id *) Top_printers.ppmbid;; #install_printer (* dir_path *) Top_printers.ppdir;; #install_printer (* module_path *) Top_printers.ppmp;; #install_printer (* section_path *) Top_printers.ppsp;; #install_printer (* qualid *) Top_printers.ppqualid;; #install_printer (* kernel_name *) Top_printers.ppkn;; #install_printer (* constant *) Top_printers.ppcon;; #install_printer (* projection *) Top_printers.ppproj;; #install_printer (* projection *) Top_printers.ppprojrepr;; #install_printer (* recarg *) Top_printers.pprecarg;; #install_printer (* recarg Rtree.t *) Top_printers.ppwf_paths;; #install_printer (* constr *) Top_printers.print_pure_constr;; #install_printer (* Idpred.t *) Top_printers.pp_idpred;; #install_printer (* Cpred.t *) Top_printers.pp_cpred;; #install_printer (* loc *) Top_printers.pploc;; #install_printer (* substitution *) Top_printers.ppsubst;; #install_printer (* pp_stdcmds *) Top_printers.pp;; #install_printer (* pattern *) Top_printers.pppattern;; #install_printer (* glob_constr *) Top_printers.ppglob_constr;; #install_printer (* constr *) Top_printers.ppconstr;; #install_printer (* econstr *) Top_printers.ppeconstr;; #install_printer (* constraints *) Top_printers.ppconstraints;; #install_printer (* univ constraints *) Top_printers.ppuniverseconstraints;; #install_printer (* universe *) Top_printers.ppuni;; #install_printer (* universes *) Top_printers.ppuniverses;; #install_printer (* univ level *) Top_printers.ppuni_level;; #install_printer (* sort variable *) Top_printers.ppqvar;; #install_printer (* univ context *) Top_printers.ppuniverse_context;; #install_printer (* univ context *) Top_printers.ppaucontext;; #install_printer (* univ context future *) Top_printers.ppuniverse_context_future;; #install_printer (* qvar set *) Top_printers.ppqvarset;; #install_printer (* univ set *) Top_printers.ppuniverse_set;; #install_printer (* univ instance *) Top_printers.ppuniverse_instance;; #install_printer (* univ subst *) Top_printers.ppuniverse_subst;; #install_printer (* univ full subst *) Top_printers.ppuniverse_level_subst;; #install_printer Top_printers.ppqvar_subst;; #install_printer (* univ opt subst *) Top_printers.ppuniverse_opt_subst;; #install_printer (* evar univ ctx *) Top_printers.ppustate;; #install_printer (* cclosure partial_subst *) Top_printers.pp_partialfsubst;; #install_printer (* reductionops partial_subst *) Top_printers.pp_partialsubst;; #install_printer (* inductive *) Top_printers.ppind;; #install_printer (* 'a scheme_kind *) Top_printers.ppscheme;; #install_printer (* type_judgement *) Top_printers.pptype;; #install_printer (* judgement *) Top_printers.ppj;; #install_printer (* id set *) Top_printers.ppidset;; #install_printer (* int set *) Top_printers.ppintset;; #install_printer (* id set *) Top_printers.ppidmapgen;; #install_printer (* int set *) Top_printers.ppintmapgen;; (* #install_printer (* hint_db *) Top_printers.print_hint_db;; *) (* #install_printer (* hints_path *) Top_printers.pphintspath;; *) #install_printer (* goal *) Top_printers.ppgoal;; #install_printer Top_printers.ppgoal_with_state;; (* #install_printer (* sigma goal *) Top_printers.ppsigmagoal;; *) #install_printer (* proof *) Top_printers.pproof;; #install_printer (* proofview *) Top_printers.ppproofview;; #install_printer (* metaset.t *) Top_printers.ppmetas;; #install_printer (* evar *) Top_printers.ppevar;; #install_printer (* evar_map *) Top_printers.ppevm;; #install_printer (* Evar.Set.t *) Top_printers.ppexistentialset;; #install_printer (* clenv *) Top_printers.ppclenv;; #install_printer (* env *) Top_printers.ppenv;; #install_printer (* Hint_db.t *) Top_printers.pphintdb;; #install_printer (* named_context_val *) Top_printers.ppnamedcontextval;; #install_printer (* tactic *) Top_printers.pptac;; #install_printer (* object *) Top_printers.ppobj;; #install_printer (* global_reference *) Top_printers.ppglobal;; #install_printer (* generic_argument *) Top_printers.pp_generic_argument;; #install_printer (* fconstr *) Top_printers.ppfconstr;; #install_printer (* HConstr.t *) Top_printers.pphconstr;; #install_printer (* fsubst *) Top_printers.ppfsubst;; #install_printer (* Future.computation *) Top_printers.ppfuture;; #install_printer (* patch *) Vm_printers.ppripos;; #install_printer (* values *) Vm_printers.ppvalues;; #install_printer Vm_printers.ppzipper;; #install_printer Vm_printers.ppstack;; #install_printer Vm_printers.ppatom;; #install_printer Vm_printers.ppwhd;; #install_printer Vm_printers.ppvblock;; rocq-9.2.0/dev/ml_toplevel/include_utilities000066400000000000000000000024441516144147600212440ustar00rootroot00000000000000(* File included to get some Coq facilities under the OCaml toplevel. *) (* parsing of terms *) let parse_constr = Procq.parse_string Procq.Constr.constr let parse_vernac = Procq.parse_string Pvernac.Vernac_.vernac_control let parse_tac = Procq.parse_string Ltac_plugin.Pltac.tactic (* build a term of type glob_constr without type-checking or resolution of implicit syntax *) let e s = let env = Global.env () in let sigma = Evd.from_env env in Constrintern.intern_constr env sigma (parse_constr s) (* build a term of type constr with type-checking and resolution of implicit syntax *) let constr_of_string s = let env = Global.env () in let sigma = Evd.from_env env in Constrintern.interp_constr env sigma (parse_constr s) (* get the body of a constant *) let constbody_of_string s = let b = Global.lookup_constant (Nametab.locate_constant (Libnames.qualid_of_string s)) in Option.get (Global.body_of_constant_body Library.indirect_accessor b) (* Get the current goal *) (* let getgoal x = top_goal_of_pftreestate (Pfedit.get_pftreestate x);; let get_nth_goal n = nth_goal_of_pftreestate n (Pfedit.get_pftreestate ());; let current_goal () = get_nth_goal 1;; *) let pf_e gl s = Constrintern.interp_constr (Proofview.Goal.env gl) (Proofview.Goal.sigma gl) (parse_constr s) rocq-9.2.0/dev/nixpkgs.nix000066400000000000000000000003011516144147600154520ustar00rootroot00000000000000import (fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/1c0bec249943cd3e03f876554b8af7d1e32a09e1.tar.gz"; sha256 = "06wpxiykzrwqsham8v8kzd79nyh0qb707r0svycz32w8j0x6b1mq"; }) rocq-9.2.0/dev/ocamldebug-coq.run000066400000000000000000000031651516144147600166720ustar00rootroot00000000000000#!/bin/sh # Wrapper around ocamldebug for Rocq # This file is to be launched via the generated script ocamldebug-coq, # which will set the env variables $OCAMLDEBUG, $CAMLP5LIB, $COQTOP # Anyway, just in case someone tries to use this script directly, # here are some reasonable default values [ -z "$OCAMLDEBUG" ] && OCAMLDEBUG=ocamldebug [ -z "$COQTOP" -a -d "$PWD/kernel" ] && COQTOP=$PWD [ -z "$COQTOP" -a -d "$PWD/../kernel" ] && COQTOP=`dirname $PWD` export CAML_LD_LIBRARY_PATH=$COQTOP/kernel/byterun:$CAML_LD_LIBRARY_PATH exec $OCAMLDEBUG \ -I +threads \ -I $COQTOP \ -I $COQTOP/config -I $COQTOP/printing -I $COQTOP/grammar -I $COQTOP/clib \ -I $COQTOP/gramlib/.pack \ -I $COQTOP/lib -I $COQTOP/kernel -I $COQTOP/kernel/byterun \ -I $COQTOP/library -I $COQTOP/engine -I $COQTOP/sysinit \ -I $COQTOP/pretyping -I $COQTOP/parsing -I $COQTOP/vernac \ -I $COQTOP/interp -I $COQTOP/proofs -I $COQTOP/tactics -I $COQTOP/stm \ -I $COQTOP/toplevel -I $COQTOP/dev -I $COQTOP/config -I $COQTOP/ltac \ -I $COQTOP/plugins/cc -I $COQTOP/plugins/dp \ -I $COQTOP/plugins/extraction -I $COQTOP/plugins/field \ -I $COQTOP/plugins/firstorder \ -I $COQTOP/plugins/funind -I $COQTOP/plugins/groebner \ -I $COQTOP/plugins/interface -I $COQTOP/plugins/micromega \ -I $COQTOP/plugins/omega -I $COQTOP/plugins/quote \ -I $COQTOP/plugins/ring \ -I $COQTOP/plugins/rtauto \ -I $COQTOP/plugins/subtac -I $COQTOP/plugins/syntax \ -I $COQTOP/plugins/xml -I $COQTOP/plugins/ltac \ -I $COQTOP/ide \ $(ocamlfind query -recursive -i-format zarith) \ "$@" rocq-9.2.0/dev/tools/000077500000000000000000000000001516144147600144155ustar00rootroot00000000000000rocq-9.2.0/dev/tools/backport-pr.sh000077500000000000000000000066011516144147600172030ustar00rootroot00000000000000#!/usr/bin/env bash set -e if [[ $# == 0 ]]; then echo "Usage: $0 [--no-conflict] [--no-signature-check] [--stop-before-merging] prnum" exit 1 fi while [[ $# -gt 0 ]]; do case "$1" in --no-conflict) NO_CONFLICTS="true" shift ;; --no-signature-check) NO_SIGNATURE_CHECK="true" shift ;; --stop-before-merging) STOP_BEFORE_MERGING="true" shift ;; *) if [[ "$PRNUM" != "" ]]; then echo "PRNUM was already set to $PRNUM and is now being overridden with $1." fi PRNUM="$1" shift esac done REMOTE=$(git config --get "branch.master.remote" || true) if [ -z "$REMOTE" ]; then echo "Branch master has no remote. Using the local state of the master branch instead." MASTER=master else MASTER="$REMOTE/master" fi if ! git log $MASTER --grep "Merge PR #$PRNUM" | grep "." > /dev/null; then echo "PR #${PRNUM} does not exist." exit 1 fi SIGNATURE_STATUS=$(git log $MASTER --grep "Merge PR #$PRNUM" --format="%G?") git log $MASTER --grep "Merge PR #$PRNUM" --format="%GG" if [[ "$NO_SIGNATURE_CHECK" != "true" && "$SIGNATURE_STATUS" != "G" ]]; then echo read -p "Merge commit does not have a good (valid) signature. Bypass? [y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi BRANCH=backport-pr-${PRNUM} RANGE=$(git log $MASTER --grep "Merge PR #$PRNUM" --format="%P" | sed 's/ /../') MESSAGE=$(git log $MASTER --grep "Merge PR #$PRNUM" --format="%s" | sed 's/Merge/Backport/') if [[ "$(git rev-parse --abbrev-ref HEAD)" == "$BRANCH" ]]; then if ! git cherry-pick --continue; then echo "Please fix the conflicts, then relaunch the script." exit 1 fi git checkout - elif git checkout -b "$BRANCH"; then if ! git cherry-pick -x "${RANGE}"; then if [[ "$NO_CONFLICTS" == "true" ]]; then git status echo "Conflicts! Aborting..." git cherry-pick --abort git checkout - git branch -d "$BRANCH" exit 1 fi echo "Please fix the conflicts, then relaunch the script." exit 1 fi git checkout - else echo read -p "Skip directly to merging phase? [y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi if ! git diff --exit-code HEAD "${BRANCH}" -- "*.mli"; then echo read -p "Some mli files are modified. Bypass? [y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi if [[ "$STOP_BEFORE_MERGING" == "true" ]]; then exit 0 fi git merge -S --no-ff "${BRANCH}" -m "${MESSAGE}" git branch -d "${BRANCH}" # To-Do: # - Support for backporting a PR before it is merged # - Automatically backport all PRs in the "Waiting to be backported" column using a command like: # $ curl -s -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github.inertia-preview+json" https://api.github.com/projects/columns/1358120/cards | jq -r '.[].content_url' | grep issue | sed 's/^.*issues\/\([0-9]*\)$/\1/' | tac # (The ID of the column must first be obtained through https://api.github.com/repos/coq/coq/projects then https://api.github.com/projects/819866/columns.) # - Then move each of the backported PR to the subsequent columns automatically as well... rocq-9.2.0/dev/tools/change-header000077500000000000000000000024531516144147600170220ustar00rootroot00000000000000#!/bin/sh #This script changes the header of .ml* files if [ ! $# = 2 ]; then echo Usage: change-header old-header-file new-header-file exit 1 fi oldheader=$1 newheader=$2 if [ ! -f $oldheader ]; then echo Cannot read file $oldheader; exit 1; fi if [ ! -f $newheader ]; then echo Cannot read file $newheader; exit 1; fi n=$(wc -l $oldheader | sed -e "s/ *\([0-9]*\).*/\1/g") nsucc=$(expr $n + 1) modified=0 kept=0 for i in $(git grep --name-only --fixed-strings "$(head -1 $oldheader)"); do headline=$(head -n 1 $i) if $(echo $headline | grep "(\* -\*- .* \*)" > /dev/null) || $(echo $headline | grep "^#\!" > /dev/null); then # Has header head -n +$nsucc $i | tail -n $n > $i.head.tmp$$ hasheadline=1 nnext=$(expr $nsucc + 1) else head -n +$n $i > $i.head.tmp$$ hasheadline=0 nnext=$nsucc fi if diff -a -q $oldheader $i.head.tmp$$ > /dev/null; then echo "$i: header changed" if [ $hasheadline = 1 ]; then echo $headline > $i.tmp$$ else touch $i.tmp$$ fi cat $newheader >> $i.tmp$$ tail -n +$nnext $i >> $i.tmp$$ mv $i.tmp$$ $i modified=$(expr $modified + 1) else echo "$i: header unchanged" kept=$(expr $kept + 1) fi rm $i.head.tmp$$ done echo $modified files updated echo $kept files unchanged rocq-9.2.0/dev/tools/check-cachekey.sh000077500000000000000000000014621516144147600176060ustar00rootroot00000000000000#!/bin/sh REDBOLD="\033[31;1m" RESET="\033[0m" redprint() { if [ "$COQ_CI_COLOR" ]; then printf "$REDBOLD%s$RESET\n" "$1" else printf '%s\n' "$1" fi } base_hash=$(md5sum dev/ci/docker/old_ubuntu_lts/Dockerfile | head -c 10) base_key=$(grep BASE_CACHEKEY: .gitlab-ci.yml) base_keyhash=${base_key%\"} base_keyhash=${base_keyhash##*-} if ! [ "$base_hash" = "$base_keyhash" ]; then >&2 redprint "Bad BASE_CACHEKEY: expected '$base_hash' but got '$base_keyhash'" exit 1 fi edge_hash=$(md5sum dev/ci/docker/edge_ubuntu/Dockerfile | head -c 10) edge_key=$(grep EDGE_CACHEKEY: .gitlab-ci.yml) edge_keyhash=${edge_key%\"} edge_keyhash=${edge_keyhash##*-} if ! [ "$edge_hash" = "$edge_keyhash" ]; then >&2 redprint "Bad EDGE_CACHEKEY: expected '$edge_hash' but got '$edge_keyhash'" exit 1 fi rocq-9.2.0/dev/tools/check-eof-newline.sh000077500000000000000000000024351516144147600202430ustar00rootroot00000000000000#!/usr/bin/env bash # Usage: check-eof-newline.sh [--fix] FILES... # Detect missing end of file newlines for FILES. # Files are skipped if untracked by git and depending on gitattributes. # With --fix, automatically append a newline. # Exit status: # Without --fix: 1 if any file had a missing newline, 0 otherwise. # With --fix: 1 if any non writable file had a missing newline, 0 otherwise. FIX= if [ "$1" = --fix ]; then FIX=1 shift fi REDBOLD="\033[31m" YELLOW="\033[33m" RESET="\033[0m" function colorprint { if [ "$COQ_CI_COLOR" ]; then printf "$1%s$RESET\n" "$2" else printf '%s\n' "$2" fi } CODE=0 for f in "$@"; do if git ls-files --error-unmatch "$f" >/dev/null 2>&1 && \ git check-attr whitespace -- "$f" | grep -q -v -e 'unset$' -e 'unspecified$' && \ [ -n "$(tail -c 1 "$f")" ] then if [ -n "$FIX" ]; then if [ -w "$f" ]; then echo >> "$f" colorprint "$YELLOW" "Newline appended to file $f!" else colorprint "$REDBOLD" "File $f is missing a newline and not writable!" CODE=1 fi else colorprint "$REDBOLD" "No newline at end of file $f!" CODE=1 fi fi done exit "$CODE" rocq-9.2.0/dev/tools/check-overlays.sh000077500000000000000000000007271516144147600177010ustar00rootroot00000000000000#!/usr/bin/env bash REDBOLD="\033[31;1m" RESET="\033[0m" function redprint { if [ "$COQ_CI_COLOR" ]; then printf "$REDBOLD%s$RESET\n" "$1" else printf '%s\n' "$1" fi } for f in $(git ls-files "dev/ci/user-overlays/") do if ! { [[ "$f" = dev/ci/user-overlays/README.md ]] || [[ "$f" == *.sh ]]; } then >&2 redprint "Bad overlay '$f'." >&2 echo "User overlays need to have extension .sh to be picked up!" exit 1 fi done rocq-9.2.0/dev/tools/cleanup-artifacts.sh000077500000000000000000000005441516144147600203640ustar00rootroot00000000000000#!/bin/sh before=$1 after=$2 # https://unix.stackexchange.com/questions/418429/find-intersection-of-lines-in-two-files awk 'BEGIN{while( (getline k < "'"$before"'")>0 ){a[k]}} $0 in a' "$after" > removed_artifacts.txt xargs -a removed_artifacts.txt rm for d in _install_ci saved_build_ci; do if [ -d $d ]; then find $d -type d -empty -delete fi done rocq-9.2.0/dev/tools/coqdev.el000066400000000000000000000234121516144147600162220ustar00rootroot00000000000000;;; coqdev.el --- Emacs helpers for Rocq development -*- lexical-binding:t -*- ;; Copyright (C) 2018 The Rocq Development Team ;; Maintainer: coqdev@inria.fr ;;; Commentary: ;; Helpers to set compilation commands, proof general variables, etc ;; for Rocq development ;; You can disable individual features without editing this file by ;; using `remove-hook', for instance ;; (remove-hook 'hack-local-variables-hook #'coqdev-setup-compile-command) ;;; Installation: ;; To use this, with coqdev.el located at /path/to/coqdev.el, add the ;; following to your init: ;; (add-to-list 'load-path "/path/to/coqdev/") ;; (require 'coqdev) ;; If you load this file from a git repository, checking out an old ;; commit will make it disappear and cause errors for your Emacs ;; startup. To ignore those errors use (require 'coqdev nil t). If you ;; check out a malicious commit Emacs startup would allow it to run ;; arbitrary code, to avoid this you can copy coqdev.el to any ;; location and adjust the load path accordingly (of course if you run ;; ./configure to compile Rocq it is already too late). ;;; Code: (require 'ocamldebug nil 'noerror) (require 'seq) (require 'subr-x) ;; locate-dominating-file would call tramp handlers which call ;; hack-local-variables-hook which call this recursively ;; a proper fix would use some hook other than hack-local-variables ;; for now just return nil for remote files (defun coqdev-default-directory () "Return the Rocq repository containing `default-directory'." (unless (file-remote-p default-directory) (let ((dir (seq-some (lambda (f) (locate-dominating-file default-directory f)) '("META.coq" "META.coq.in" "META.coq-core.in" "coqpp")))) (when dir (expand-file-name dir))))) (defun coqdev-setup-compile-command () "Setup `compile-command' for Rocq development." (let ((dir (coqdev-default-directory))) (when dir (setq-local compile-command (concat "cd " (shell-quote-argument dir) " dune build @check # rocq-runtime.install"))))) (add-hook 'hack-local-variables-hook #'coqdev-setup-compile-command) (defvar camldebug-command-name) ; from camldebug.el (caml package) (defvar ocamldebug-command-name) ; from ocamldebug.el (tuareg package) (defun coqdev-setup-camldebug () "Setup ocamldebug for Rocq development. Specifically `camldebug-command-name' and `ocamldebug-command-name'." (let ((dir (coqdev-default-directory))) (when dir (setq-local camldebug-command-name (concat dir "dev/ocamldebug-coq")) (setq-local ocamldebug-command-name (concat dir "dev/ocamldebug-coq"))))) (add-hook 'hack-local-variables-hook #'coqdev-setup-camldebug) (defun coqdev-setup-tags () "Setup `tags-file-name' for Rocq development." (let ((dir (coqdev-default-directory))) (when dir (setq-local tags-file-name (concat dir "TAGS"))))) (add-hook 'hack-local-variables-hook #'coqdev-setup-tags) (defvar coq-prog-args) (defvar coq-prog-name) ;; Lets us detect whether there are file local variables ;; even though PG sets it with `setq' when there's a _Coqproject. ;; Also makes sense generally, so might make it into PG someday. (make-variable-buffer-local 'coq-prog-args) (setq-default coq-prog-args nil) (defun coqdev-setup-proofgeneral () "Setup Proofgeneral variables for Rocq development. Note that this function is executed before _Coqproject is read if it exists." (let ((dir (coqdev-default-directory))) (when dir (setq-local coq-prog-name (concat dir "_build/install/default/bin/coqtop"))))) (add-hook 'hack-local-variables-hook #'coqdev-setup-proofgeneral) (defvar coqdev-ocamldebug-command "dune exec -- dev/dune-dbg -emacs coqc /tmp/foo.v" "Command run by `coqdev-ocamldebug'") (declare-function comint-check-proc "comint") (declare-function tuareg--split-args "tuareg") (declare-function ocamldebug-filter "ocamldebug") (declare-function ocamldebug-sentinel "ocamldebug") (declare-function ocamldebug-mode "ocamldebug") (declare-function ocamldebug-set-buffer "ocamldebug") (defun coqdev-ocamldebug () "Runs a command in an ocamldebug buffer." (interactive) (require 'ocamldebug) (let* ((dir (read-directory-name "Run from directory: " (coqdev-default-directory))) (name "ocamldebug-coq") (buffer-name (concat "*" name "*"))) (pop-to-buffer buffer-name) (unless (comint-check-proc buffer-name) (setq default-directory dir) (setq coqdev-ocamldebug-command (read-from-minibuffer "Command to run: " coqdev-ocamldebug-command)) (let* ((cmdlist (tuareg--split-args coqdev-ocamldebug-command)) (cmdlist (mapcar #'substitute-in-file-name cmdlist))) (apply #'make-comint name (car cmdlist) nil (cdr cmdlist)) (set-process-filter (get-buffer-process (current-buffer)) #'ocamldebug-filter) (set-process-sentinel (get-buffer-process (current-buffer)) #'ocamldebug-sentinel) (ocamldebug-mode))) (ocamldebug-set-buffer) (insert "source db"))) ;; Provide correct breakpoint setting in dune wrapped libraries ;; (assuming only 1 library/dune file) (defun coqdev--read-from-file (file) "Read FILE as a list of sexps. If invalid syntax, return nil and message the error." (with-temp-buffer (save-excursion (insert "(\n") (insert-file-contents file) (goto-char (point-max)) (insert "\n)\n")) (condition-case err (read (current-buffer)) ((error err) (progn (message "Error reading file %S: %S" file err) nil))))) (defun coqdev--find-single-library (sexps) "If list SEXPS has an element whose `car' is \"library\", return the first one. Otherwise return `nil'." (let ((libs (seq-filter (lambda (elt) (equal (car elt) 'library)) sexps))) (and libs (car libs)))) (defun coqdev--dune-library-name (lib) "With LIB a dune-syntax library stanza, get its name as a string." (let ((field (or (seq-find (lambda (field) (and (consp field) (equal (car field) 'name))) lib) (seq-find (lambda (field) (and (consp field) (equal (car field) 'public\_name))) lib)))) (symbol-name (car (cdr field))))) (defun coqdev--upcase-first-char (arg) "Set the first character of ARG to uppercase." (concat (upcase (substring arg 0 1)) (substring arg 1 (length arg)))) (defun coqdev--real-module-name (filename) "Return module name for ocamldebug, taking into account dune wrapping. (for now only understands dune files with a single library stanza)" (let ((mod (substring filename (string-match "\\([^/]*\\)\\.ml$" filename) (match-end 1))) (dune (concat (file-name-directory filename) "dune"))) (if (file-exists-p dune) (if-let* ((contents (coqdev--read-from-file dune)) (lib (coqdev--find-single-library contents)) (is-wrapped (null (seq-contains-p lib '(wrapped false)))) (libname (coqdev--dune-library-name lib))) (concat libname "__" (coqdev--upcase-first-char mod)) mod) mod))) (with-eval-after-load 'ocamldebug (defun ocamldebug-module-name (arg) (coqdev--real-module-name arg))) ;; This Elisp snippet adds a regexp parser for the format of Anomaly ;; backtraces (coqc -bt ...), to the error parser of the Compilation ;; mode (C-c C-c: "Compile command: ..."). File locations in traces ;; are recognized and can be jumped from easily in the *compilation* ;; buffer. (defvar compilation-error-regexp-alist-alist) (defvar compilation-error-regexp-alist) (with-eval-after-load 'compile (add-to-list 'compilation-error-regexp-alist-alist '(coq-backtrace "^ *\\(?:raise\\|frame\\) @ file \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1,\ lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\ \\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:?\\)?\\)" 2 (3 . 4) (5 . 6))) (add-to-list 'compilation-error-regexp-alist 'coq-backtrace)) (defvar bug-reference-bug-regexp) (defvar bug-reference-url-format) (defun coqdev-setup-bug-reference-mode () "Setup `bug-reference-bug-regexp' and `bug-reference-url-format' for Rocq. This does not enable `bug-reference-mode'." (let ((dir (coqdev-default-directory))) (when dir (setq-local bug-reference-bug-regexp "\\(#\\(?2:[0-9]+\\)\\)") (setq-local bug-reference-url-format "https://github.com/rocq-prover/rocq/issues/%s") (when (derived-mode-p 'prog-mode) (bug-reference-prog-mode 1))))) (add-hook 'hack-local-variables-hook #'coqdev-setup-bug-reference-mode) (defun coqdev-sphinx-quote-coq-refman-region (left right &optional offset beg end) "Add LEFT and RIGHT around the BEG..END. Leave the point after RIGHT. BEG and END default to the bounds of the current region. Leave point OFFSET characters after the left quote (if OFFSET is nil, leave the point after the right quote)." (unless beg (if (region-active-p) (setq beg (region-beginning) end (region-end)) (setq beg (point) end nil))) (save-excursion (goto-char (or end beg)) (insert right)) (save-excursion (goto-char beg) (insert left)) (if (and end (not offset)) ;; Second test handles the ::`` case (goto-char (+ end (length left) (length right))) (goto-char (+ beg (or offset (length left)))))) (defun coqdev-sphinx-rst-coq-action () "Insert a Sphinx role template or quote the current region." (interactive) (pcase (read-char "Command [gntm:`]?") (?g (coqdev-sphinx-quote-coq-refman-region ":g:`" "`")) (?n (coqdev-sphinx-quote-coq-refman-region ":n:`" "`")) (?t (coqdev-sphinx-quote-coq-refman-region ":token:`" "`")) (?m (coqdev-sphinx-quote-coq-refman-region ":math:`" "`")) (?: (coqdev-sphinx-quote-coq-refman-region "::`" "`" 1)) (?` (coqdev-sphinx-quote-coq-refman-region "``" "``")))) (provide 'coqdev) ;;; coqdev ends here rocq-9.2.0/dev/tools/create_overlays.sh000077500000000000000000000062101516144147600201420ustar00rootroot00000000000000#!/usr/bin/env bash # TODO: # # - Check if the branch already exists in the remote => checkout # - Better error handling # - Just checkout, don't build # - Rebase functionality # set -x set -e set -o pipefail # setup_contrib_git("_build_ci/fiat", "https://github.com/ejgallego/fiat-core.git") setup_contrib_git() { local _DIR=$1 local _GITURL=$2 ( cd $_DIR git checkout -b $OVERLAY_BRANCH || true # allow the branch to exist already git remote add $DEVELOPER_NAME $_GITURL || true # allow the remote to exist already if [ -d .git ]; then # TODO handle submodules template_file=.git/OVERLAY_COMMIT_TEMPLATE printf 'Adapt to rocq-prover/rocq#%s (short decription here)\n' "$PR_NUMBER" > "$template_file" # don't override config if already set, maybe the user prefers something else if ! git config --get --local commit.template; then git config --local commit.template "$template_file" fi fi ) } if [ $# -lt 3 ]; then echo "usage: $0 github_username pr_number contrib1 ... contribN" exit 1 fi set +x . dev/ci/ci-basic-overlay.sh set -x DEVELOPER_NAME=$1 shift PR_NUMBER=$1 shift OVERLAY_BRANCH=$(git rev-parse --abbrev-ref HEAD) OVERLAY_FILE=$(mktemp overlay-XXXX) # Create the overlay file > "$OVERLAY_FILE" skipped_repos= # We first try to build the contribs while test $# -gt 0 do _CONTRIB_NAME=$1 _CONTRIB_GITURL=${_CONTRIB_NAME}_CI_GITURL _CONTRIB_GITURL=${!_CONTRIB_GITURL} _CONTRIB_SUBMODULE_GITURL=${_CONTRIB_NAME}_CI_SUBMODULE_GITURL _CONTRIB_SUBMODULE_GITURL=${!_CONTRIB_SUBMODULE_GITURL} _CONTRIB_SUBMODULE_BRANCH=${_CONTRIB_NAME}_CI_SUBMODULE_BRANCH _CONTRIB_SUBMODULE_BRANCH=${!_CONTRIB_SUBMODULE_BRANCH} if [[ -n "${_CONTRIB_SUBMODULE_GITURL}" ]]; then _CONTRIB_GITURL="${_CONTRIB_SUBMODULE_GITURL}" fi echo "Processing Contrib $_CONTRIB_NAME" shift # check _CONTRIB_GIT exists and it is of the from github... _CONTRIB_DIR=_build_ci/$_CONTRIB_NAME # extract the relevant part of the repository if [[ $_CONTRIB_GITURL == https://github.com/*/* ]]; then _CONTRIB_GITSUFFIX=${_CONTRIB_GITURL#https://github.com/*/} _CONTRIB_GITURL="https://github.com/$DEVELOPER_NAME/$_CONTRIB_GITSUFFIX" _CONTRIB_GITPUSHURL="git@github.com:$DEVELOPER_NAME/${_CONTRIB_GITSUFFIX}.git" else skipped_repos="$skipped_repos $_CONTRIB_NAME" continue fi DOWNLOAD_ONLY=1 make ci-$_CONTRIB_NAME || true setup_contrib_git $_CONTRIB_DIR $_CONTRIB_GITPUSHURL echo "overlay ${_CONTRIB_NAME} $_CONTRIB_GITURL $OVERLAY_BRANCH $PR_NUMBER" >> $OVERLAY_FILE if [ -n "${_CONTRIB_SUBMODULE_BRANCH}${_CONTRIB_SUBMODULE_GITURL}" ]; then echo "# Make PRs against ${_CONTRIB_SUBMODULE_GITURL} base branch ${_CONTRIB_SUBMODULE_BRANCH}" >> $OVERLAY_FILE fi if [ $# -gt 0 ]; then echo "" >> $OVERLAY_FILE; fi done # Copy to overlays folder. PR_NUMBER=$(printf '%05d' "$PR_NUMBER") mv $OVERLAY_FILE dev/ci/user-overlays/$PR_NUMBER-$DEVELOPER_NAME-${OVERLAY_BRANCH///}.sh if [ -n "$skipped_repos" ]; then >&2 echo "Skipped non-github repos: $skipped_repos" exit 1 fi rocq-9.2.0/dev/tools/deprecate_file.sh000077500000000000000000000014331516144147600177100ustar00rootroot00000000000000#!/bin/sh usage() { cat 1>&2 <&2 exit 1 fi attr="((Local|Global|Program|Canonical)[[:space:]]+)" deprable="Theorem|Lemma|Fact|Corollary|Proposition|Property|\ Definition|Example|Fixpoint|\ Instance|Axiom|Parameter|Notation|Coercion" annot="#[deprecated(since=\"$vers\", note=\"$note\")]" tmp="$file".depr sed -E "s/(^[[:space:]]*)(($attr)*($deprable).*\$)/\\1$annot\\n\\1\\2/" \ "$file" >"$tmp" mv "$tmp" "$file" rocq-9.2.0/dev/tools/generate-release-changelog.sh000077500000000000000000000064551516144147600221230ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -o pipefail if [ $# != 1 ]; then echo "Usage: $0 BRANCH" exit fi branch=$1 # Set SLOW_CONF to have the confirmation output wait for a newline # Emacs doesn't send characters until the RET so we can't quick_conf if [ -z ${SLOW_CONF+x} ] || [ -n "$INSIDE_EMACS" ]; then quick_conf=(-n 1) else quick_conf=() fi ask_confirmation() { read -p "Continue anyway? [y/N] " "${quick_conf[@]}" -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi } if ! git diff --quiet; then echo "Warning: current tree is dirty." ask_confirmation fi remote=$(git config --get "branch.${branch}.remote" || true) if [ -z "$remote" ]; then echo "Warning: branch $branch has no associated remote." ask_confirmation else if [[ "$remote" != $(git config --get "branch.master.remote") ]]; then echo "Warning: branch master and branch $branch do not have the same remote." ask_confirmation fi official_remote_git_url="git@github.com:rocq-prover/rocq" official_remote_https_url="github.com/rocq-prover/rocq" remote_url=$(git remote get-url "$remote" --all) if [ "$remote_url" != "${official_remote_git_url}" ] && \ [ "$remote_url" != "${official_remote_git_url}.git" ] && \ [ "$remote_url" != "https://${official_remote_https_url}" ] && \ [ "$remote_url" != "https://${official_remote_https_url}.git" ] && \ [[ "$remote_url" != "https://"*"@${official_remote_https_url}" ]] && \ [[ "$remote_url" != "https://"*"@${official_remote_https_url}.git" ]] ; then echo "Warning: remote $remote does not point to the official Rocq repo," echo "that is $official_remote_git_url" echo "It points to $remote_url instead." ask_confirmation fi git fetch "$remote" if [[ $(git rev-parse master) != $(git rev-parse "${remote}/master") ]]; then echo "Warning: branch master is not up-to-date with ${remote}/master." ask_confirmation fi if [[ $(git rev-parse "$branch") != $(git rev-parse "${remote}/${branch}") ]]; then echo "Warning: branch ${branch} is not up-to-date with ${remote}/${branch}." ask_confirmation fi fi git checkout "$branch" --detach > /dev/null 2>&1 changelog_entries_with_title=(doc/changelog/*/*.rst) git checkout master > /dev/null 2>&1 tmp=$(mktemp) for f in "${changelog_entries_with_title[@]}"; do if ! [ -f "$f" ]; then >&2 echo "Warning: $f is missing in master branch." continue fi cat=${f%/*} # dirname if [[ ${f##*/} = 00000-title.rst ]]; then type=0 else type_name=$(head -n 1 "$f" | cut -f 2 -d ' ') type_name=${type_name%":**"} type_name=${type_name#"**"} case "$type_name" in Changed) type=1;; Removed) type=2;; Deprecated) type=3;; Added) type=4;; Fixed) type=5;; *) >&2 echo "Unknown changelog type $type_name in $f"; type=6;; esac fi printf '%s %s %s\n' "$cat" "$type" "$f" >> "$tmp" done while read -r _ type f; do cat "$f" >> released.rst if ! [[ $type = 0 ]]; then git rm "$f" >> /dev/null; fi done < <(sort "$tmp") echo echo "Changelog written in released.rst. Move its content to a new section in doc/sphinx/changes.rst." rocq-9.2.0/dev/tools/list-contributors.sh000077500000000000000000000024511516144147600204640ustar00rootroot00000000000000#!/usr/bin/env bash # For compat with OSX which has a non-gnu sed which doesn't support -z SED=`(which gsed || which sed) 2> /dev/null` if [ $# != 1 ]; then echo "usage: $0 rev0..rev1" exit 1 fi git shortlog -s -n --no-merges --group=author --group=trailer:Co-authored-by $1 | cut -f2 | sort -k 2 | grep -v -e "coqbot" -e "copilot" -e "^$" > contributors.tmp cat contributors.tmp | wc -l | xargs echo "Contributors:" cat contributors.tmp | $SED -z "s/\n/, /g" echo rm contributors.tmp git shortlog -s -n --merges --group=author --group=trailer:Co-authored-by $1 | cut -f2 | sort -k 2 | grep -v -e "coqbot" -e "copilot" -e "^$" > assignees.tmp cat assignees.tmp | wc -l | xargs echo "Assignees:" cat assignees.tmp | $SED -z "s/\n/, /g" echo rm assignees.tmp git shortlog -s -n --merges --group=trailer:reviewed-by --group=trailer:ack-by $1 | cut -f2 > reviewers-pseudos.tmp rm -f reviewers-names.tmp for i in `cat reviewers-pseudos.tmp` do res=`grep $i .mailmap` if [[ $? == 1 ]] then echo $i" not found" continue fi echo $res | tail -n1 | cut -d'<' -f1 >> reviewers-names.tmp done cat reviewers-names.tmp | sort -k 2 > reviewers.tmp rm reviewers-pseudos.tmp reviewers-names.tmp cat reviewers.tmp | wc -l | xargs echo "Reviewers:" cat reviewers.tmp | $SED -z "s/ \n/, /g" echo rm reviewers.tmp rocq-9.2.0/dev/tools/list-potential-artifacts.sh000077500000000000000000000001701516144147600217000ustar00rootroot00000000000000#!/bin/sh for d in _install_ci saved_build_ci; do if [ -d $d ]; then find $d -type f -o -type l | sort fi done rocq-9.2.0/dev/tools/make-changelog.sh000077500000000000000000000031551516144147600176220ustar00rootroot00000000000000#!/bin/sh printf "PR number? " read -r PR printf "Category? (type a prefix)\n" (cd doc/changelog && ls -d */) read -r where printf "Type? (type first letter)\n" printf "[A]dded \t[C]hanged \t[D]eprecated \t[F]ixed \t[R]emoved\n" read -r type_first_letter case "$type_first_letter" in [Aa]) type_full="Added";; [Cc]) type_full="Changed";; [Dd]) type_full="Deprecated";; [Ff]) type_full="Fixed";; [Rr]) type_full="Removed";; *) printf "Invalid input!\n" exit 1;; esac where="doc/changelog/$where" if ! [ -d "$where" ]; then where=$(echo "$where"*); fi where="${where}/${PR}-$(git rev-parse --abbrev-ref HEAD | tr / -)-${type_full}.rst" printf "Fixes? (space separated list of bug numbers)\n" read -r fixes_list fixes_string="$(echo $fixes_list | sed 's/ /~ and /g; s,\([0-9][0-9]*\),`#\1 `_,g' | tr '~' '\n')" if [ ! -z "$fixes_string" ]; then fixes_string="$(printf '\n fixes %s,' "$fixes_string")"; fi # shellcheck disable=SC2016 # the ` are regular strings, this is intended # use %s for the leading - to avoid looking like an option (not sure # if necessary but doesn't hurt) printf '%s **%s:**\n Describe your change here but do not end with a period\n (`#%s `_,%s\n by %s).\n' - "$type_full" "$PR" "$PR" "$fixes_string" "$(git config user.name)" > "$where" printf 'Name of created changelog file:\n' printf '%s\n' "$where" giteditor=$(git config core.editor) if [ "$giteditor" ]; then $giteditor "$where" elif [ "$EDITOR" ]; then $EDITOR "$where" else printf "Describe the changes in the above file\n" fi rocq-9.2.0/dev/tools/make_git_revision.sh000077500000000000000000000007621516144147600204570ustar00rootroot00000000000000#!/usr/bin/env bash if ! command -v git >/dev/null; then >&2 echo "skipping make_git_revision: git not found" exit 0 fi if [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1 then export LANG=C GIT_BRANCH=$(git branch -a | sed -ne '/^\* /s/^\* \(.*\)/\1/p') GIT_HOST=$(hostname) GIT_PATH=$(pwd) echo "${GIT_HOST}:${GIT_PATH},${GIT_BRANCH}" echo $(git log -1 --pretty='format:%H') else >&2 echo "skipping make_git_revision: git dir not found" exit 0 fi rocq-9.2.0/dev/tools/markdown-toc000077500000000000000000000033511516144147600167520ustar00rootroot00000000000000#!/usr/bin/env bash # from https://github.com/Lirt/markdown-toc-bash # MIT license FILE=${1:?No file was specified as first argument} declare -a TOC CODE_BLOCK=0 CODE_BLOCK_REGEX='^```' HEADING_REGEX='^#{1,}' while read -r LINE; do # Treat code blocks if [[ "${LINE}" =~ $CODE_BLOCK_REGEX ]]; then # Ignore things until we see code block ending CODE_BLOCK=$((CODE_BLOCK + 1)) if [[ "${CODE_BLOCK}" -eq 2 ]]; then # We hit the closing code block CODE_BLOCK=0 fi continue fi # Treat normal line if [[ "${CODE_BLOCK}" == 0 ]]; then # If we see heading, we save it to ToC map if [[ "${LINE}" =~ ${HEADING_REGEX} ]]; then TOC+=("${LINE}") fi fi done < <(grep -v '## Table of Contents' "${FILE}") echo -e "## Table of Contents\n" for LINE in "${TOC[@]}"; do case "${LINE}" in '#####'*) echo -n " - " ;; '####'*) echo -n " - " ;; '###'*) echo -n " - " ;; '##'*) echo -n " - " ;; '#'*) echo -n "- " ;; esac LINK=${LINE} # Detect markdown links in heading and remove link part from them if grep -qE "\[.*\]\(.*\)" <<< "${LINK}"; then LINK=$(sed 's/\(\]\)\((.*)\)/\1/' <<< "${LINK}") fi # Special characters (besides '-') in page links in markdown # are deleted and spaces are converted to dashes LINK=$(tr -dc "[:alnum:] _-" <<< "${LINK}") LINK=${LINK/ /} LINK=${LINK// /-} LINK=${LINK,,} LINK=$(tr -s "-" <<< "${LINK}") # Print in format [Very Special Heading](#very-special-heading) echo "[${LINE#\#* }](#${LINK})" done rocq-9.2.0/dev/tools/merge-pr.sh000077500000000000000000000171551516144147600165030ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -o pipefail ORG=rocq-prover REPO=rocq API=https://api.github.com/repos/$ORG/$REPO OFFICIAL_REMOTE_GIT_URL="git@github.com:$ORG/$REPO" OFFICIAL_REMOTE_HTTPS_URL="github.com/$ORG/$REPO" # This script depends (at least) on git (>= 2.7) and jq. # It should be used like this: dev/tools/merge-pr.sh /PR number/ # Set SLOW_CONF to have the confirmation output wait for a newline # E.g. call $ SLOW_CONF= dev/tools/merge-pr.sh /PR number/ # emacs doesn't send characters until the RET so we can't quick_conf if [ -z ${SLOW_CONF+x} ] || [ -n "$INSIDE_EMACS" ]; then QUICK_CONF="-n 1" else QUICK_CONF="" fi RED="\033[31m" RESET="\033[0m" GREEN="\033[32m" YELLOW="\033[33m" info() { echo -e "${GREEN}info:${RESET} $1 ${RESET}" } error() { echo -e "${RED}error:${RESET} $1 ${RESET}" } warning() { echo -e "${YELLOW}warning:${RESET} $1 ${RESET}" } check_util() { if ! command -v "$1" > /dev/null 2>&1; then error "this script requires the $1 command line utility" exit 1 fi } ask_confirmation() { read -p "Continue anyway? [y/N] " $QUICK_CONF -r echo if [[ ! $REPLY =~ ^[Yy]$ ]] then exit 1 fi } curl_paginate_array() { # as per https://developer.github.com/v3/guides/traversing-with-pagination/#changing-the-number-of-items-received, GitHub will never give us more than 100 url="$1?per_page=100" # we keep fetching pages until the response is below the per-page limit (possibly 0 elements) page=1 while true; do response="$(curl -s "${url}&page=${page}")" echo "${response}" if [ "$(jq 'length' <<< "$response")" -lt 100 ]; then # done break fi page=$(($page + 1)) done | jq '[.[]]' # we concatenate the arrays } check_util jq check_util curl check_util git check_util gpg check_util grep # command line parsing if [ $# != 1 ]; then error "usage: $0 PR-number" exit 1 fi if [[ "$1" =~ ^[1-9][0-9]*$ ]]; then PR=$1 else error "$1 is not a number" exit 1 fi # Fetching PR metadata # The main API call returns a dict/object, not an array, so we don't # bother paginating PRDATA=$(curl -s "$API/pulls/$PR") TITLE=$(echo "$PRDATA" | jq -r '.title') info "title for PR $PR is $TITLE" BASE_BRANCH=$(echo "$PRDATA" | jq -r '.base.ref') info "PR $PR targets branch $BASE_BRANCH" CURRENT_LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD) info "you are merging in $CURRENT_LOCAL_BRANCH" REMOTE=$(git config --get "branch.$CURRENT_LOCAL_BRANCH.remote" || true) if [ -z "$REMOTE" ]; then error "branch $CURRENT_LOCAL_BRANCH has not associated remote" error "don't know where to fetch the PR from" error "please run: git branch --set-upstream-to=THE_REMOTE/$CURRENT_LOCAL_BRANCH" exit 1 fi REMOTE_URL=$(git remote get-url "$REMOTE" --all) if [ "$REMOTE_URL" != "${OFFICIAL_REMOTE_GIT_URL}" ] && \ [ "$REMOTE_URL" != "${OFFICIAL_REMOTE_GIT_URL}.git" ] && \ [ "$REMOTE_URL" != "https://${OFFICIAL_REMOTE_HTTPS_URL}" ] && \ [ "$REMOTE_URL" != "https://${OFFICIAL_REMOTE_HTTPS_URL}.git" ] && \ [[ "$REMOTE_URL" != "https://"*"@${OFFICIAL_REMOTE_HTTPS_URL}" ]] && \ [[ "$REMOTE_URL" != "https://"*"@${OFFICIAL_REMOTE_HTTPS_URL}.git" ]] ; then error "remote $REMOTE does not point to the official Rocq repo" error "that is $OFFICIAL_REMOTE_GIT_URL" error "it points to $REMOTE_URL instead" ask_confirmation fi info "remote for $CURRENT_LOCAL_BRANCH is $REMOTE" info "fetching from $REMOTE the PR" git remote update "$REMOTE" if ! git ls-remote "$REMOTE" | grep pull >/dev/null; then error "remote $REMOTE is not configured to fetch pull requests" error "run: git config remote.$REMOTE.fetch +refs/pull/*/head:refs/remotes/$REMOTE/pr/*" exit 1 fi git fetch "$REMOTE" "refs/pull/$PR/head" COMMIT=$(git rev-parse FETCH_HEAD) info "commit for PR $PR is $COMMIT" # Sanity check: merge to a different branch if [ "$BASE_BRANCH" != "$CURRENT_LOCAL_BRANCH" ]; then error "PR requests merge in $BASE_BRANCH but you are merging in $CURRENT_LOCAL_BRANCH" ask_confirmation fi; # Sanity check: the local branch is up-to-date with upstream LOCAL_BRANCH_COMMIT=$(git rev-parse HEAD) UPSTREAM_COMMIT=$(git rev-parse @{u}) if [ "$LOCAL_BRANCH_COMMIT" != "$UPSTREAM_COMMIT" ]; then # Is it just that the upstream branch is behind? # It could just be that we merged other PRs and we didn't push yet if [ "$BASE_BRANCH" = master ] \ && git merge-base --is-ancestor -- "$UPSTREAM_COMMIT" "$LOCAL_BRANCH_COMMIT"; then warning "Your branch is ahead of ${REMOTE}." warning "On master, GitHub's branch protection rule prevents merging several PRs at once." warning "You should run [git push ${REMOTE}] between each call to the merge script." ask_confirmation else error "Local branch is not up-to-date with ${REMOTE}." error "Pull before merging." # This check should never be bypassed. exit 1 fi fi # Sanity check: PR has an outdated version of CI BASE_COMMIT=$(echo "$PRDATA" | jq -r '.base.sha') CI_FILES=(".gitlab-ci.yml" ".github/workflows/ci.yml") if ! git diff --quiet "$BASE_COMMIT" "$LOCAL_BRANCH_COMMIT" -- "${CI_FILES[@]}" then warning "This PR didn't run with the latest version of CI." warning "It is probably a good idea to ask for a rebase." read -p "Do you want to see the diff? [Y/n] " $QUICK_CONF -r echo if [[ ! $REPLY =~ ^[Nn]$ ]] then git diff "$BASE_COMMIT" "$LOCAL_BRANCH_COMMIT" -- "${CI_FILES[@]}" fi ask_confirmation fi # Sanity check: CI failed STATUS=$(curl -s "$API/commits/$COMMIT/status") if [ "$(echo "$STATUS" | jq -r '.state')" != "success" ]; then error "CI unsuccessful on $(echo "$STATUS" | jq -r -c '.statuses|map(select(.state != "success"))|map(.context)')" ask_confirmation fi; # Sanity check: has labels named "needs:" NEEDS_LABELS=$(echo "$PRDATA" | jq -rc '.labels | map(select(.name | match("needs:"))) | map(.name)') if [ "$NEEDS_LABELS" != "[]" ]; then error "needs:something labels still present: $NEEDS_LABELS" ask_confirmation fi # Sanity check: has milestone MILESTONE=$(echo "$PRDATA" | jq -rc '.milestone.title') if [ "$MILESTONE" = "null" ]; then error "no milestone set, please set one" ask_confirmation fi # Sanity check: has kind KIND=$(echo "$PRDATA" | jq -rc '.labels | map(select(.name | match("kind:"))) | map(.name)') if [ "$KIND" = "[]" ]; then error "no kind:something label set, please set one" ask_confirmation fi # Sanity check: user.signingkey if [ -z "$(git config user.signingkey)" ]; then warning "git config user.signingkey is empty" warning "gpg will guess a key out of your git config user.* data" fi # Generate commit message info "Fetching review data" reviews=$(curl_paginate_array "$API/pulls/$PR/reviews") msg="Merge PR #$PR: $TITLE" has_state() { [ "$(jq -rc 'map(select(.user.login == "'"$1"'") | .state) | any(. == "'"$2"'")' <<< "$reviews")" = true ] } author=$(echo "$PRDATA" | jq -rc '.user.login') for reviewer in $(jq -rc 'map(.user.login | select(. != "'"$author"'")) | unique | join(" ")' <<< "$reviews" ); do if has_state "$reviewer" APPROVED; then msg=$(printf '%s\n' "$msg" | git interpret-trailers --trailer Reviewed-by="$reviewer") elif has_state "$reviewer" COMMENTED; then msg=$(printf '%s\n' "$msg" | git interpret-trailers --trailer Ack-by="$reviewer") fi done info "merging" git merge -v -S --no-ff FETCH_HEAD -m "$msg" -e # TODO: improve this check if ! git diff --quiet --diff-filter=A "$REMOTE/$CURRENT_LOCAL_BRANCH" -- dev/ci/user-overlays; then warning "this PR has overlays, please check the following:" warning "- each overlay has a corresponding open PR on the upstream repo" warning "- after merging please notify the upstream they can merge the PR" fi rocq-9.2.0/dev/tools/pin-ci.sh000077500000000000000000000021601516144147600161320ustar00rootroot00000000000000#!/usr/bin/env bash # Use this script to pin the commit used by the developments tracked by the CI OVERLAYS="./dev/ci/ci-basic-overlay.sh" process_development() { local DEV=$1 local REPO_VAR="${DEV}_CI_GITURL" local REPO=${!REPO_VAR} local BRANCH_VAR="${DEV}_CI_REF" local BRANCH=${!BRANCH_VAR} local HASH if [[ -z "$BRANCH" ]] then echo "$DEV has no branch set, skipping" return 0 fi if [[ $BRANCH =~ ^[a-f0-9]{40}$ ]] then echo "$DEV is already set to hash $BRANCH, skipping" return 0 fi echo "Resolving $DEV as $BRANCH from $REPO" HASH=$(git ls-remote --heads "$REPO" "$BRANCH" | cut -f 1) if [[ -z "$HASH" ]] then echo "Could not resolve reference $BRANCH for $DEV (something went wrong), skipping" return 0 fi echo "Expandin $DEV from $BRANCH to $HASH" # use -i.bak to be compatible with MacOS; see, e.g., https://stackoverflow.com/a/7573438/377022 sed -i.bak -E "s|project +$DEV +.*|project $DEV '$REPO' '$HASH'|" $OVERLAYS } # Execute the script to set the overlay variables . $OVERLAYS for project in "${projects[@]}" do process_development "$project" done rocq-9.2.0/dev/tools/pipeline-stats.py000077500000000000000000000033761516144147600177440ustar00rootroot00000000000000#!/usr/bin/env python3 import os import gitlab from tabulate import tabulate gt = gitlab.Gitlab(url="https://gitlab.inria.fr", private_token=os.getenv("PIPELINE_STATS_TOKEN"), api_version="4") prj = gt.projects.get("coq/coq") pipeline_id=os.getenv("CI_PIPELINE_ID") pipeline = prj.pipelines.get(pipeline_id) def pptime(seconds): if seconds >= 60 * 60: hours = seconds / (60 * 60) minutes = (seconds % (60 * 60)) / 60 return f"{hours:.0f}h {minutes:.0f}min" elif seconds >= 60: minutes = seconds / 60 rest = seconds % 60 return f"{minutes:.0f}min {rest:.0f}s" else: return f"{seconds:.0f}s" def ppsize(size, decimal_places=2): for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']: if size < 1024.0 or unit == 'PiB': break size /= 1024.0 return f"{size:.{decimal_places}f} {unit}" res=[] total_time=0.0 total_size=0 total_log_size=0 for j in pipeline.jobs.list(iterator=True): if j.duration is None: continue # non-finished job, eg bench or pipeline stats size=0 log_size=0 if 'artifacts' in j.attributes: for art in j.attributes['artifacts']: if art['file_type'] == 'trace': log_size += art['size'] else: size += art['size'] res += [[j.name, j.duration, size, log_size, j.id]] total_time += j.duration total_size += size total_log_size += log_size res += [['total', total_time, total_size, total_log_size, pipeline_id]] def sortkey(v): return v[1] ppres = [ [v[0], pptime(v[1]), ppsize(v[2]), ppsize(v[3]), v[4]] for v in sorted(res, key=sortkey) ] print(tabulate(ppres, headers=['name', 'duration', 'artifacts size', 'log size', 'id'], tablefmt='orgtbl')) rocq-9.2.0/dev/tools/pre-commit000077500000000000000000000045661516144147600164320ustar00rootroot00000000000000#!/bin/sh # configure automatically sets up a wrapper at .git/hooks/pre-commit # which calls this script (if it exists). set -e dev/tools/check-overlays.sh log=$(mktemp "git-fix-ws-log.XXXXXX") exec > "$log" 1>&2 echo "Auto fixing whitespace issues ($log)..." # We fix whitespace in the index and in the working tree # separately to preserve non-added changes. index=$(mktemp "git-fix-ws-index.XXXXXX") fixed_index=$(mktemp "git-fix-ws-index-fixed.XXXXXX") tree=$(mktemp "git-fix-ws-tree.XXXXXX") echo "Patches are saved in '$index', '$fixed_index' and '$tree'." echo "If an error destroys your changes you can recover using them." echo "(The files are cleaned up on success.)" echo #newline git diff-index -p --binary --cached HEAD > "$index" git diff-index -p --binary HEAD > "$tree" # reset work tree and index # NB: untracked files which were not added are untouched if [ -s "$index" ]; then git apply --whitespace=nowarn --cached -R "$index"; fi if [ -s "$tree" ]; then git apply --whitespace=nowarn -R "$tree"; fi # Fix index # For end of file newlines we must go through the worktree if [ -s "$index" ]; then echo "Fixing staged changes..." git apply --cached --whitespace=fix "$index" git apply --whitespace=fix "$index" 2>/dev/null # no need to repeat yourself git diff --cached --name-only -z | xargs -0 dev/tools/check-eof-newline.sh --fix git add -u echo #newline fi # reset work tree git diff-index -p --binary --cached HEAD > "$fixed_index" # If all changes were bad whitespace changes the patch is empty # making git fail. Don't fail now: we fix the worktree first. if [ -s "$fixed_index" ]; then git apply --whitespace=nowarn -R "$fixed_index"; fi # Fix worktree if [ -s "$tree" ]; then echo "Fixing unstaged changes..." git apply --whitespace=fix "$tree" git diff --name-only -z | xargs -0 dev/tools/check-eof-newline.sh --fix echo #newline fi if [ -s "$index" ] && ! [ -s "$fixed_index" ]; then echo "Fixing whitespace issues cancelled all changes." exit 1 fi # Check that we did fix whitespace if ! git diff-index --check --cached HEAD; then echo "Auto-fixing whitespace failed: errors remain." echo "This may fix itself if you try again." echo "(Consider whether the number of errors decreases after each run.)" exit 1 fi echo "Whitespace pass complete." # clean up temporary files rm "$index" "$tree" "$fixed_index" "$log" rocq-9.2.0/dev/top_printers.dbg000066400000000000000000000104231516144147600164630ustar00rootroot00000000000000install_printer Top_printers.pP install_printer Top_printers.ppexninfo install_printer Top_printers.ppfuture install_printer Top_printers.ppid install_printer Top_printers.ppmbid install_printer Top_printers.ppdir install_printer Top_printers.ppmp install_printer Top_printers.ppcon install_printer Top_printers.ppproj install_printer Top_printers.ppprojrepr install_printer Top_printers.ppkn install_printer Top_printers.ppmind install_printer Top_printers.ppseff install_printer Top_printers.ppind install_printer Top_printers.ppsp install_printer Top_printers.ppqualid install_printer Top_printers.ppscheme install_printer Top_printers.ppwf_paths install_printer Top_printers.ppevar install_printer Top_printers.ppuint63 install_printer Top_printers.pp_constr_parray install_printer Top_printers.pp_fconstr_parray install_printer Top_printers.ppconstr install_printer Top_printers.ppeconstr install_printer Top_printers.ppconstr_expr install_printer Top_printers.ppglob_constr install_printer Top_printers.pppattern install_printer Top_printers.ppfconstr install_printer Top_printers.pphconstr install_printer Top_printers.ppfsubst install_printer Top_printers.ppnumtokunsigned install_printer Top_printers.ppnumtokunsignednat install_printer Top_printers.ppintset install_printer Top_printers.ppidset install_printer Top_printers.ppidmapgen install_printer Top_printers.ppintmapgen install_printer Top_printers.ppmpmapgen install_printer Top_printers.ppdpmapgen install_printer Top_printers.ppconmapenvgen install_printer Top_printers.ppmindmapenvgen install_printer Top_printers.ppididmap install_printer Top_printers.ppconstrunderbindersidmap install_printer Top_printers.ppevarsubst install_printer Top_printers.ppunbound_ltac_var_map install_printer Top_printers.ppclosure install_printer Top_printers.ppclosedglobconstr install_printer Top_printers.ppclosedglobconstridmap install_printer Top_printers.ppglobal install_printer Top_printers.ppconst install_printer Top_printers.ppvar install_printer Top_printers.ppj install_printer Top_printers.ppsubst install_printer Top_printers.ppdelta install_printer Top_printers.pp_idpred install_printer Top_printers.pp_cpred install_printer Top_printers.pp_transparent_state install_printer Top_printers.pp_estack_t install_printer Top_printers.pp_state_t install_printer Top_printers.ppmetas install_printer Top_printers.ppmetamap install_printer Top_printers.ppevm install_printer Top_printers.ppexistentialset install_printer Top_printers.ppexistentialfilter install_printer Top_printers.ppclenv install_printer Top_printers.ppgoal install_printer Top_printers.ppgoal_with_state install_printer Top_printers.pphintdb install_printer Top_printers.ppproofview install_printer Top_printers.pproof install_printer Top_printers.ppuni install_printer Top_printers.ppesorts install_printer Top_printers.pperelevance install_printer Top_printers.ppqvar install_printer Top_printers.ppuni_level install_printer Top_printers.ppqvarset install_printer Top_printers.ppqset install_printer Top_printers.ppuniverse_set install_printer Top_printers.ppuniverse_instance install_printer Top_printers.ppuniverse_einstance install_printer Top_printers.ppuniverse_context install_printer Top_printers.ppaucontext install_printer Top_printers.ppuniverse_subst install_printer Top_printers.ppuniverse_opt_subst install_printer Top_printers.ppqvar_subst install_printer Top_printers.pppoly_flags install_printer Top_printers.ppuniverse_level_subst install_printer Top_printers.ppustate install_printer Top_printers.ppconstraints install_printer Top_printers.ppqconstraints install_printer Top_printers.ppuniverseconstraints install_printer Top_printers.ppuniverse_context_future install_printer Top_printers.ppuniverses install_printer Top_printers.ppqualities install_printer Top_printers.ppelim_constraints install_printer Top_printers.pp_partialfsubst install_printer Top_printers.pp_partialsubst install_printer Top_printers.ppnamedcontextval install_printer Top_printers.ppenv install_printer Top_printers.ppglobenv install_printer Top_printers.pptac install_printer Top_printers.ppobj install_printer Top_printers.pploc install_printer Top_printers.pp_argument_type install_printer Top_printers.pp_generic_argument install_printer Top_printers.ppgenarginfo install_printer Top_printers.ppgenargargt install_printer Top_printers.ppist rocq-9.2.0/dev/top_printers.ml000066400000000000000000000667601516144147600163560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Option.map Pp.(fun loc -> str "exn loc: " ++ Loc.pr loc ++ fnl()) |> Option.default (mt()) in pp (loc ++ CErrors.print_extra e) (** Future printer *) let ppfuture kx = pp (Future.print (fun _ -> str "_") kx) (* name printers *) let ppid id = pp (Id.print id) let ppmbid mbid = pp (str (MBId.debug_to_string mbid)) let ppdir dir = pp (DirPath.print dir) let ppmp mp = pp(str (ModPath.debug_to_string mp)) let ppcon con = pp(Constant.debug_print con) let ppprojrepr con = pp(Constant.debug_print (Projection.Repr.constant con)) let ppproj p = pp(Projection.debug_print p) let ppkn kn = pp(str (KerName.to_string kn)) let ppmind kn = pp(MutInd.debug_print kn) let ppind (kn,i) = pp(MutInd.debug_print kn ++ str"," ++int i) let ppsp sp = pp(pr_path sp) let ppqualid qid = pp(pr_qualid qid) let ppscheme k = pp (Ind_tables.pr_scheme_kind k) let pprecarg r = pp (Declareops.pr_recarg r) let ppwf_paths x = pp (Declareops.pr_wf_paths x) let get_current_context () = try Vernacstate.Declare.get_current_context () with Vernacstate.Declare.NoCurrentProof -> let env = Global.env() in Evd.from_env env, env [@@ocaml.warning "-3"] (* term printers *) let envpp pp = let sigma,env = get_current_context () in pp env sigma let ppevar evk = pp (Evar.print evk) let pr_constr t = let sigma, env = get_current_context () in Printer.pr_constr_env env sigma t let pr_econstr t = let sigma, env = get_current_context () in Printer.pr_econstr_env env sigma t let ppconstr x = pp (pr_constr x) let ppeconstr x = pp (pr_econstr x) let ppconstr_expr x = let sigma,env = get_current_context () in let flags = Ppconstr.current_flags() in pp (Ppconstr.pr_constr_expr ~flags env sigma x) let ppconstr_univ x = Flags.with_option PrintingFlags.print_universes ppconstr x let ppglob_constr = (fun x -> pp(with_env_evm pr_lglob_constr_env x)) let pppattern = (fun x -> pp(envpp pr_constr_pattern_env x)) let pptype = (fun x -> try pp(envpp (fun env evm t -> pr_ltype_env env evm t) x) with e -> pp (str (Printexc.to_string e))) let ppfconstr c = ppconstr (CClosure.term_of_fconstr c) (* XXX we could also try to have a printer which shows which parts are shared, but this is probably better for most uses (ie stepping through typeops and wanting to print the current constr) *) let pphconstr c = ppconstr (HConstr.self c) let ppuint63 i = pp (str (Uint63.to_string i)) let pp_parray pr a = let a, def = Parray.to_array a in let a = Array.to_list a in pp (str "[|" ++ prlist_with_sep (fun () -> str ";" ++ spc()) pr a ++ spc() ++ str "|" ++ spc() ++ pr def ++ str "|]") let pp_constr_parray = pp_parray pr_constr let pp_fconstr_parray = pp_parray (fun f -> pr_constr (CClosure.term_of_fconstr f)) let pplift el = pp @@ Esubst.Internal.pp_lift el let ppfsubst s = let (s, k) = Esubst.Internal.repr s in let sep () = str ";" ++ spc () in let pr = function | Esubst.Internal.REL n -> str "<#" ++ int n ++ str ">" | Esubst.Internal.VAL (k, x) -> pr_constr (Vars.lift k (CClosure.term_of_fconstr x)) in pp @@ str "[" ++ prlist_with_sep sep pr s ++ str "| " ++ int k ++ str "]" let ppnumtokunsigned n = pp (NumTok.Unsigned.print n) let ppnumtokunsignednat n = pp (NumTok.UnsignedNat.print n) let prset pr l = str "[" ++ hov 0 (prlist_with_sep spc pr l) ++ str "]" let ppintset l = pp (prset int (Int.Set.elements l)) let ppidset l = pp (prset Id.print (Id.Set.elements l)) let prset' pr l = str "[" ++ hov 0 (prlist_with_sep pr_comma pr l) ++ str "]" let pridmap pr l = let pr (id,b) = Id.print id ++ str "=>" ++ pr id b in prset' pr (Id.Map.fold (fun a b l -> (a,b)::l) l []) let ppidmap pr l = pp (pridmap pr l) let prmapgen pr dom = if dom = [] then str "[]" else str "[domain= " ++ hov 0 (prlist_with_sep spc pr dom) ++ str "]" let pridmapgen l = prmapgen Id.print (Id.Set.elements (Id.Map.domain l)) let ppidmapgen l = pp (pridmapgen l) let printmapgen l = prmapgen int (Int.Set.elements (Int.Map.domain l)) let ppintmapgen l = pp (printmapgen l) let ppmpmapgen l = pp (prmapgen (fun mp -> str (ModPath.debug_to_string mp)) (ModPath.Set.elements (ModPath.Map.domain l))) let ppdpmapgen l = pp (prmapgen (fun mp -> str (DirPath.to_string mp)) (DirPath.Set.elements (DirPath.Map.domain l))) let ppconmapenvgen l = pp (prmapgen (fun mp -> str (Constant.debug_to_string mp)) (Cset_env.elements (Cmap_env.domain l))) let ppmindmapenvgen l = pp (prmapgen (fun mp -> str (MutInd.debug_to_string mp)) (Mindmap_env.Set.elements (Mindmap_env.domain l))) let ppevarsubst = ppidmap (fun id0 -> prset (fun (c,copt,id) -> hov 0 (pr_constr c ++ (match copt with None -> mt () | Some c -> spc () ++ str "") ++ (if id = id0 then mt () else spc () ++ str "")))) let prididmap = pridmap (fun _ -> Id.print) let ppididmap = ppidmap (fun _ -> Id.print) let prconstrunderbindersidmap = pridmap (fun _ (l,c) -> hov 1 (str"[" ++ prlist_with_sep spc Id.print l ++ str"]") ++ str "," ++ spc () ++ pr_econstr c) let ppconstrunderbindersidmap l = pp (prconstrunderbindersidmap l) let ppunbound_ltac_var_map l = ppidmap (fun _ arg -> str"") l open Ltac_pretype let rec pr_closure {idents=idents;typed=typed;untyped=untyped} = hov 1 (str"{idents=" ++ prididmap idents ++ str";" ++ spc() ++ str"typed=" ++ prconstrunderbindersidmap typed ++ str";" ++ spc() ++ str"untyped=" ++ pr_closed_glob_constr_idmap untyped ++ str"}") and pr_closed_glob_constr_idmap x = pridmap (fun _ -> pr_closed_glob_constr) x and pr_closed_glob_constr {closure=closure;term=term} = pr_closure closure ++ with_env_evm pr_lglob_constr_env term let ppclosure x = pp (pr_closure x) let ppclosedglobconstr x = pp (pr_closed_glob_constr x) let ppclosedglobconstridmap x = pp (pr_closed_glob_constr_idmap x) let pP s = pp (hov 0 s) let pp_as_format s = let fmt, args = pp_as_format s in let pr_escaped s = str ("\"" ^ String.escaped s ^ "\"") in pp (hov 0 (str "printf" ++ spc() ++ str "\"" ++ str fmt ++ str "\"" ++ pr_non_empty_arg (prlist_with_sep spc pr_escaped) args)) let safe_pr_global = let open GlobRef in function | ConstRef kn -> pp (str "CONSTREF(" ++ Constant.debug_print kn ++ str ")") | IndRef (kn,i) -> pp (str "INDREF(" ++ MutInd.debug_print kn ++ str "," ++ int i ++ str ")") | ConstructRef ((kn,i),j) -> pp (str "CONSTRUCTREF(" ++ MutInd.debug_print kn ++ str "," ++ int i ++ str "," ++ int j ++ str ")") | VarRef id -> pp (str "VARREF(" ++ Id.print id ++ str ")") let ppglobal x = try pp(pr_global x) with _ -> safe_pr_global x let ppconst (sp,j) = pp (str"#" ++ KerName.print sp ++ str"=" ++ envpp pr_lconstr_env j.uj_val) let ppvar ((id,a)) = pp (str"#" ++ Id.print id ++ str":" ++ envpp pr_lconstr_env a) let genppj f j = let (c,t) = f j in (c ++ str " : " ++ t) let ppj j = pp (genppj (envpp pr_ljudge_env) j) let ppsubst s = pp (Mod_subst.debug_pr_subst s) let ppdelta s = pp (Mod_subst.debug_pr_delta s) let pp_idpred s = pp (pr_idpred s) let pp_cpred s = pp (pr_cpred s) let pp_transparent_state s = pp (pr_transparent_state s) let pp_estack_t n = pp (Reductionops.Stack.pr pr_econstr n) let pp_state_t n = pp (Reductionops.pr_state Global.(env()) Evd.empty n) (* proof printers *) let pr_evar ev = Pp.int (Evar.repr ev) let ppmetas metas = pp (Unification.Meta.pr_metaset metas) let ppmetamap metas = let env = Global.env () in let sigma = Evd.from_env env in pp (Unification.Meta.pr_metamap env sigma metas) let ppevm evd = pp(Termops.pr_evar_map ~with_univs:!PrintingFlags.print_universes (Some 2) (Global.env ()) evd) let ppevmall evd = pp(Termops.pr_evar_map ~with_univs:!PrintingFlags.print_universes None (Global.env ()) evd) let pr_existentialset evars = prlist_with_sep spc pr_evar (Evar.Set.elements evars) let ppexistentialset evars = pp (pr_existentialset evars) let ppexistentialfilter filter = match Evd.Filter.repr filter with | None -> pp (Pp.str "ΓΈ") | Some f -> pp (prlist_with_sep spc bool f) let pr_goal e = Pp.(str "GOAL:" ++ int (Evar.repr e)) let ppclenv clenv = pp(pr_clenv clenv) let ppgoal g = pp(Printer.Debug.pr_goal g) let ppgoal_with_state g = ppevar (Proofview_monad.drop_state g) let pphintdb db = pp(envpp Hints.pr_hint_db_env db) let ppproofview p = let gls,sigma = Proofview.proofview p in pp(pr_enum pr_goal gls ++ fnl () ++ Termops.pr_evar_map (Some 1) (Global.env ()) sigma) let ppseff seff = pp (Safe_typing.debug_print_private_constants seff) (* spiwack: deactivated until a replacement is found let pppftreestate p = pp(print_pftreestate p) *) (* let ppgoal g = pp(db_pr_goal g) *) (* let pr_gls gls = *) (* hov 0 (pr_evar_defs (sig_sig gls) ++ fnl () ++ db_pr_goal (sig_it gls)) *) (* let pr_glls glls = *) (* hov 0 (pr_evar_defs (sig_sig glls) ++ fnl () ++ *) (* prlist_with_sep fnl db_pr_goal (sig_it glls)) *) (* let ppsigmagoal g = pp(pr_goal (sig_it g)) *) (* let prgls gls = pp(pr_gls gls) *) (* let prglls glls = pp(pr_glls glls) *) let pproof p = pp(Proof.pr_proof p) let ppuni u = pp(Universe.raw_pr u) let ppuni_level u = pp (Level.raw_pr u) let ppqvar q = pp (QVar.raw_pr q) let ppesorts s = pp (Sorts.debug_print (EConstr.Unsafe.to_sorts s)) (* pprelevance not directly useful since it's transparent, but used for pperelevance *) let pprelevance (r:Sorts.relevance) = match r with | Relevant -> pp (str "Relevant") | Irrelevant -> pp (str "Irrelevant") | RelevanceVar q -> pp (surround (str "RelevanceVar " ++ spc() ++ Sorts.QVar.raw_pr q)) let pperelevance r = pprelevance (EConstr.Unsafe.to_relevance r) let prlev l = UnivNames.pr_level_with_global_universes l let prqvar q = UnivNames.pr_quality_with_global_universes q let ppqvarset l = pp (hov 1 (str "{" ++ prlist_with_sep spc prqvar (QVar.Set.elements l) ++ str "}")) let ppqset qs = pp (hov 1 (str "{" ++ prlist_with_sep spc (Quality.pr prqvar) (Quality.Set.elements qs) ++ str "}")) let ppuniverse_set l = pp (Level.Set.pr prlev l) let ppuniverse_instance l = pp (Instance.pr prqvar prlev l) let ppuniverse_einstance l = ppuniverse_instance (EConstr.Unsafe.to_instance l) let ppuniverse_context l = pp (UVars.UContext.pr prqvar prlev l) let ppuniverse_subst l = pp (UnivSubst.pr_universe_subst Level.raw_pr l) let ppuniverse_opt_subst l = pp (UnivFlex.pr Level.raw_pr l) let ppqvar_subst l = pp (UVars.pr_quality_level_subst QVar.raw_pr l) let ppuniverse_level_subst l = pp (UVars.pr_universe_level_subst Level.raw_pr l) let pppoly_flags f = pp (PolyFlags.pr f) let ppustate l = pp (UState.pr l) let ppconstraints c = pp (UnivConstraints.pr Level.raw_pr c) let ppqconstraints c = pp (ElimConstraints.pr prqvar c) let ppuniverseconstraints c = pp (UnivProblem.Set.pr c) let ppuniverse_context_future c = let ctx = Future.force c in ppuniverse_context ctx let ppuniverses u = pp (UGraph.pr_universes Level.raw_pr (UGraph.repr u)) let ppqualities q = pp (QGraph.pr_qualities Quality.raw_pr q) let ppelim_constraints cstrs = pp (Sorts.ElimConstraints.pr prqvar cstrs) let ppnamedcontextval e = let env = Global.env () in let sigma = Evd.from_env env in pp (pr_named_context env sigma (named_context_of_val e)) let ppaucontext auctx = let {quals = qnas; univs = unas} = AbstractContext.names auctx in let prgen pr var_index nas l = match var_index l with | Some n -> (match nas.(n) with | Anonymous -> pr l | Name id -> Id.print id) | None -> pr l in let prqvar l = prgen prqvar Sorts.QVar.var_index qnas l in let prlev l = prgen prlev Level.var_index unas l in pp (UContext.pr prqvar prlev (AbstractContext.repr auctx)) let pp_partialfsubst psubst = pp (Partial_subst.pr (fun f -> pr_constr (CClosure.term_of_fconstr f)) (Quality.pr prqvar) (Universe.pr prlev) psubst) let pp_partialsubst psubst = pp (Partial_subst.pr pr_econstr (Quality.pr prqvar) (Universe.pr prlev) psubst) let ppenv e = pp (str "[" ++ pr_named_context_of e Evd.empty ++ str "]" ++ spc() ++ str "[" ++ pr_rel_context e Evd.empty (rel_context e) ++ str "]") let ppglobenv e = ppenv (GlobEnv.env e) let ppenvwithcst e = pp (str "[" ++ pr_named_context_of e Evd.empty ++ str "]" ++ spc() ++ str "[" ++ pr_rel_context e Evd.empty (rel_context e) ++ str "]" ++ spc() ++ str "{" ++ Environ.fold_constants (fun a _ s -> Constant.print a ++ spc () ++ s) e (mt ()) ++ str "}") let pptac = (fun x -> pp(Ltac_plugin.Pptactic.pr_glob_tactic (Global.env()) x)) let ppobj obj = let Libobject.Dyn.Dyn (tag, _) = obj in Format.print_string (Libobject.Dyn.repr tag) let cnt = ref 0 let cast_kind_display k = match k with | VMcast -> "VMcast" | DEFAULTcast -> "DEFAULTcast" | NATIVEcast -> "NATIVEcast" let constr_display csr = let rec term_display c = match kind c with | Rel n -> "Rel("^(string_of_int n)^")" | Meta n -> "Meta("^(string_of_int n)^")" | Var id -> "Var("^(Id.to_string id)^")" | Sort s -> "Sort("^(sort_display s)^")" | Cast (c,k, t) -> "Cast("^(term_display c)^","^(cast_kind_display k)^","^(term_display t)^")" | Prod (na,t,c) -> "Prod("^(name_display na)^","^(term_display t)^","^(term_display c)^")\n" | Lambda (na,t,c) -> "Lambda("^(name_display na)^","^(term_display t)^","^(term_display c)^")\n" | LetIn (na,b,t,c) -> "LetIn("^(name_display na)^","^(term_display b)^"," ^(term_display t)^","^(term_display c)^")" | App (c,l) -> "App("^(term_display c)^","^(array_display l)^")\n" | Evar (e,l) -> let l = SList.to_list l in let map = function None -> "?" | Some t -> term_display t in let l = List.map map l in "Evar("^(Pp.string_of_ppcmds (Evar.print e))^", [|"^(String.concat "; " l)^"|])" | Const (c,u) -> "Const("^(Constant.to_string c)^","^(universes_display u)^")" | Ind ((sp,i),u) -> "MutInd("^(MutInd.to_string sp)^","^(string_of_int i)^","^(universes_display u)^")" | Construct (((sp,i),j),u) -> "MutConstruct(("^(MutInd.to_string sp)^","^(string_of_int i)^")," ^","^(universes_display u)^(string_of_int j)^")" | Proj (p, r, c) -> "Proj("^(Projection.to_string p)^","^term_display c ^")" | Case (ci,u,pms,((_,p),_),iv,c,bl) -> "MutCase(,"^(term_display p)^","^(term_display c)^"," ^(array_display (Array.map snd bl))^")" | Fix ((t,i),(lna,tl,bl)) -> "Fix(([|"^(Array.fold_right (fun x i -> (string_of_int x)^(if not(i="") then (";"^i) else "")) t "")^"|],"^(string_of_int i)^")," ^(array_display tl)^",[|" ^(Array.fold_right (fun x i -> (name_display x)^(if not(i="") then (";"^i) else "")) lna "")^"|]," ^(array_display bl)^")" | CoFix(i,(lna,tl,bl)) -> "CoFix("^(string_of_int i)^")," ^(array_display tl)^"," ^(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)^")" | Float f -> "Float("^(Float64.to_string f)^")" | String s -> Printf.sprintf "String(%S)" (Pstring.to_string s) | Array (u,t,def,ty) -> "Array("^(array_display t)^","^(term_display def)^","^(term_display ty)^")@{" ^universes_display u^"\n" and array_display v = "[|"^ (Array.fold_right (fun x i -> (term_display x)^(if not(i="") then (";"^i) else "")) v "")^"|]" and univ_display u = incr cnt; pp (str "with " ++ int !cnt ++ str" " ++ Universe.raw_pr u ++ fnl ()) and quality_display q = incr cnt; pp (str "with " ++ int !cnt ++ str" " ++ Sorts.Quality.raw_pr q ++ fnl ()) and level_display u = incr cnt; pp (str "with " ++ int !cnt ++ str" " ++ Level.raw_pr u ++ fnl ()) and sort_display = function | SProp -> "SProp" | Set -> "Set" | Prop -> "Prop" | Type u -> univ_display u; "Type("^(string_of_int !cnt)^")" | QSort (q, u) -> univ_display u; Printf.sprintf "QSort(%s, %i)" (Sorts.QVar.to_string q) !cnt and universes_display l = let qs, us = Instance.to_array l in let qs = Array.fold_right (fun x i -> quality_display x; (string_of_int !cnt)^ (if not(i="") then (" "^i) else "")) qs "" in Array.fold_right (fun x i -> level_display x; (string_of_int !cnt)^(if not(i="") then (" "^i) else "")) us (if qs = "" then "" else (qs^" | ")) and name_display x = match x.binder_name with | Name id -> "Name("^(Id.to_string id)^")" | Anonymous -> "Anonymous" in pp (str (term_display csr) ++fnl ()) let econstr_display c = constr_display EConstr.Unsafe.(to_constr c) ;; open Format;; let print_pure_constr csr = let rec term_display c = match Constr.kind c with | Rel n -> print_string "#"; print_int n | Meta n -> print_string "Meta("; print_int n; print_string ")" | Var id -> print_string (Id.to_string id) | Sort s -> sort_display s | Cast (c,_, t) -> open_hovbox 1; print_string "("; (term_display c); print_cut(); print_string "::"; (term_display t); print_string ")"; close_box() | Prod ({binder_name=Name(id)},t,c) -> open_hovbox 1; print_string"("; print_string (Id.to_string id); print_string ":"; box_display t; print_string ")"; print_cut(); box_display c; close_box() | Prod ({binder_name=Anonymous},t,c) -> print_string"("; box_display t; print_cut(); print_string "->"; box_display c; print_string ")"; | Lambda (na,t,c) -> print_string "["; name_display na; print_string ":"; box_display t; print_string "]"; print_cut(); box_display c; | LetIn (na,b,t,c) -> print_string "["; name_display na; print_string "="; box_display b; print_cut(); print_string ":"; box_display t; print_string "]"; print_cut(); box_display c; | App (c,l) -> print_string "("; box_display c; Array.iter (fun x -> print_space (); box_display x) l; print_string ")" | Evar (e,l) -> print_string "Evar#"; print_int (Evar.repr e); print_string "{"; let iter = function None -> print_space (); print_string "?" | Some t -> print_space (); box_display t in List.iter iter (SList.to_list l); print_string"}" | Const (c,u) -> print_string "Cons("; sp_con_display c; print_string ","; universes_display u; print_string ")" | Proj (p,_,c') -> print_string "Proj("; sp_prj_display p; print_string ","; box_display c'; print_string ")" | Ind ((sp,i),u) -> print_string "Ind("; sp_display sp; print_string ","; print_int i; print_string ","; universes_display u; print_string ")" | Construct (((sp,i),j),u) -> print_string "Constr("; sp_display sp; print_string ","; print_int i; print_string ","; print_int j; print_string ","; universes_display u; print_string ")" | Case (ci,u,pms,(p,_),iv,c,bl) -> let pr_ctx (nas, c) = Array.iter (fun na -> print_cut (); name_display na) nas; print_string " |- "; box_display c in open_vbox 0; print_cut(); print_string "Case"; print_space(); box_display c; print_space (); print_cut(); print_string "in"; print_cut(); print_string "Ind("; sp_display (fst ci.ci_ind); print_string ","; print_int (snd ci.ci_ind); print_string ")"; print_string "@{"; universes_display u; print_string "}"; Array.iter (fun x -> print_space (); box_display x) pms; print_cut(); print_string "return <"; pr_ctx p; print_string ">"; print_cut(); print_string "with"; open_vbox 0; Array.iter (fun x -> print_cut(); pr_ctx x) bl; close_box(); print_cut(); print_string "end"; close_box() | Fix ((t,i),(lna,tl,bl)) -> print_string "Fix("; print_int i; print_string ")"; print_cut(); open_vbox 0; let print_fix () = for k = 0 to (Array.length tl) - 1 do open_vbox 0; name_display lna.(k); print_string "/"; print_int t.(k); print_cut(); print_string ":"; box_display tl.(k) ; print_cut(); print_string ":="; box_display bl.(k); close_box (); print_cut() done in print_string"{"; print_fix(); print_string"}" | CoFix(i,(lna,tl,bl)) -> print_string "CoFix("; print_int i; print_string ")"; print_cut(); open_vbox 0; let print_fix () = for k = 0 to (Array.length tl) - 1 do open_vbox 1; name_display lna.(k); print_cut(); print_string ":"; box_display tl.(k) ; print_cut(); print_string ":="; box_display bl.(k); close_box (); print_cut(); done in print_string"{"; print_fix (); print_string"}" | Int i -> print_string ("Int("^(Uint63.to_string i)^")") | Float f -> print_string ("Float("^(Float64.to_string f)^")") | String s -> print_string (Printf.sprintf "String(%S)" (Pstring.to_string s)) | Array (u,t,def,ty) -> print_string "Array("; Array.iter (fun x -> box_display x; print_space()) t; print_string "|"; box_display def; print_string ":"; box_display ty; print_string ")@{"; universes_display u; print_string "}" and box_display c = open_hovbox 1; term_display c; close_box() and universes_display u = let qs, us = Instance.to_array u in Array.iter (fun u -> print_space (); pp (Sorts.Quality.raw_pr u)) qs; Array.iter (fun u -> print_space (); pp (Level.raw_pr u)) us and sort_display = function | SProp -> print_string "SProp" | Set -> print_string "Set" | Prop -> print_string "Prop" | Type u -> open_hbox(); print_string "Type("; pp (Universe.raw_pr u); print_string ")"; close_box() | QSort (q, u) -> open_hbox(); print_string "QSort("; pp (QVar.raw_pr q); print_string ", "; pp (Universe.raw_pr u); print_string ")"; close_box() and name_display x = match x.binder_name with | Name id -> print_string (Id.to_string id) | Anonymous -> print_string "_" (* Remove the top names for library and Scratch to avoid long names *) and sp_display sp = (* let dir,l = decode_kn sp in let ls = match List.rev_map Id.to_string (DirPath.repr dir) with ("Top"::l)-> l | ("Stdlib"::_::l) -> l | l -> l in List.iter (fun x -> print_string x; print_string ".") ls;*) print_string (MutInd.debug_to_string sp) and sp_con_display sp = (* let dir,l = decode_kn sp in let ls = match List.rev_map Id.to_string (DirPath.repr dir) with ("Top"::l)-> l | ("Stdlib"::_::l) -> l | l -> l in List.iter (fun x -> print_string x; print_string ".") ls;*) print_string (Constant.debug_to_string sp) and sp_prj_display sp = print_string (Projection.debug_to_string sp) in try box_display csr; print_flush() with e -> print_string (Printexc.to_string e);print_flush (); raise e let print_pure_econstr c = print_pure_constr EConstr.Unsafe.(to_constr c) ;; let pploc x = let (l,r) = Loc.unloc x in print_string"(";print_int l;print_string",";print_int r;print_string")" let pp_argument_type t = pp (pr_argument_type t) let pp_generic_argument arg = pp(str"") let prgenarginfo arg = let Geninterp.Val.Dyn (tag, _) = arg in let tpe = Geninterp.Val.pr tag in (* FIXME *) (* try *) (* let data = Pptactic.pr_top_generic (Global.env ()) arg in *) (* str "" *) (* with _any -> *) str "" let ppgenarginfo arg = pp (prgenarginfo arg) let ppgenargargt arg = pp (str (Genarg.ArgT.repr arg)) let ppist ist = let pr id arg = prgenarginfo arg in pp (pridmap pr ist.Geninterp.lfun) (**********************************************************************) (* Vernac-level debugging commands *) let in_current_context f c = let (evmap,sign) = get_current_context () in f (fst (Constrintern.interp_constr sign evmap c))(*FIXME*) (* We expand the result of preprocessing to be independent of camlp5 VERNAC COMMAND EXTEND PrintPureConstr | [ "PrintPureConstr" constr(c) ] -> [ in_current_context print_pure_constr c ] END VERNAC COMMAND EXTEND PrintConstr [ "PrintConstr" constr(c) ] -> [ in_current_context constr_display c ] END *) let () = let open Vernacextend in let open Vernactypes in let ty_constr = Extend.TUentry (get_arg_tag Stdarg.wit_constr) in let cmd_sig = TyTerminal("PrintConstr", TyNonTerminal(ty_constr, TyNil)) in let cmd_fn c ?loc:_ ~atts () = vtdefault (fun () -> in_current_context econstr_display c) in let cmd_class _ ~atts:_ = VtQuery in let cmd : ty_ml = TyML (false, cmd_sig, cmd_fn, Some cmd_class) in static_vernac_extend ~ignore_kw:false ~plugin:None ~command:"PrintConstr" [cmd] let () = let open Vernacextend in let open Vernactypes in let ty_constr = Extend.TUentry (get_arg_tag Stdarg.wit_constr) in let cmd_sig = TyTerminal("PrintPureConstr", TyNonTerminal(ty_constr, TyNil)) in let cmd_fn c ?loc:_ ~atts () = vtdefault (fun () -> in_current_context print_pure_econstr c) in let cmd_class _ ~atts:_ = VtQuery in let cmd : ty_ml = TyML (false, cmd_sig, cmd_fn, Some cmd_class) in static_vernac_extend ~ignore_kw:false ~plugin:None ~command:"PrintPureConstr" [cmd] (* Setting printer of unbound global reference *) open Names open Libnames let encode_path ?loc prefix mpdir suffix id = let dir = match mpdir with | None -> [] | Some mp -> DirPath.repr (dirpath_of_string (ModPath.to_string mp)) in make_qualid ?loc (DirPath.make (List.rev (Id.of_string prefix::dir@suffix))) id let raw_string_of_ref ?loc _ = let open GlobRef in function | ConstRef cst -> let (mp,id) = KerName.repr (Constant.user cst) in encode_path ?loc "CST" (Some mp) [] id | IndRef (kn,i) -> let (mp,id) = KerName.repr (MutInd.user kn) in encode_path ?loc "IND" (Some mp) [id] (Id.of_string ("_"^string_of_int i)) | ConstructRef ((kn,i),j) -> let (mp,id) = KerName.repr (MutInd.user kn) in encode_path ?loc "CSTR" (Some mp) [id;Id.of_string ("_"^string_of_int i)] (Id.of_string ("_"^string_of_int j)) | VarRef id -> encode_path ?loc "SECVAR" None [] id let short_string_of_ref ?loc _ = let open GlobRef in function | VarRef id -> qualid_of_ident ?loc id | ConstRef cst -> qualid_of_ident ?loc (Constant.label cst) | IndRef (kn,0) -> qualid_of_ident ?loc (MutInd.label kn) | IndRef (kn,i) -> encode_path ?loc "IND" None [MutInd.label kn] (Id.of_string ("_"^string_of_int i)) | ConstructRef ((kn,i),j) -> encode_path ?loc "CSTR" None [MutInd.label kn; Id.of_string ("_"^string_of_int i)] (Id.of_string ("_"^string_of_int j)) rocq-9.2.0/dev/top_printers.mli000066400000000000000000000165661516144147600165260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val pP : Pp.t -> unit (* with surrounding box *) val ppexninfo : Exninfo.info -> unit val pp_as_format : Pp.t -> unit val ppfuture : 'a Future.computation -> unit val ppid : Names.Id.t -> unit val ppmbid : Names.MBId.t -> unit val ppdir : Names.DirPath.t -> unit val ppmp : Names.ModPath.t -> unit val ppcon : Names.Constant.t -> unit val ppproj : Names.Projection.t -> unit val ppprojrepr : Names.Projection.Repr.t -> unit val ppkn : Names.KerName.t -> unit val ppmind : Names.MutInd.t -> unit val ppind : Names.inductive -> unit val ppseff : Safe_typing.private_constants -> unit val ppuint63 : Uint63.t -> unit val ppsp : Libnames.full_path -> unit val ppqualid : Libnames.qualid -> unit val ppscheme : 'a Ind_tables.scheme_kind -> unit val pprecarg : Declarations.recarg -> unit val ppwf_paths : Declarations.recarg Rtree.t -> unit val pr_evar : Evar.t -> Pp.t val ppevar : Evar.t -> unit (* Multiple printers for Constr.t *) val ppconstr : Constr.t -> unit (* by Termops printer *) val ppconstr_univ : Constr.t -> unit val pp_constr_parray : Constr.t Parray.t -> unit val pp_fconstr_parray : CClosure.fconstr Parray.t -> unit (* Extern as type *) val pptype : Constr.types -> unit val ppeconstr : EConstr.constr -> unit (* Termops printer *) val ppconstr_expr : Constrexpr.constr_expr -> unit val ppglob_constr : 'a Glob_term.glob_constr_g -> unit val pppattern : Pattern.constr_pattern -> unit val ppfconstr : CClosure.fconstr -> unit val pphconstr : HConstr.t -> unit val pplift : Esubst.lift -> unit val ppfsubst : CClosure.fconstr Esubst.subs -> unit val ppnumtokunsigned : NumTok.Unsigned.t -> unit val ppnumtokunsignednat : NumTok.UnsignedNat.t -> unit val ppintset : Int.Set.t -> unit val ppidset : Names.Id.Set.t -> unit val pridmap : (Names.Id.Map.key -> 'a -> Pp.t) -> 'a Names.Id.Map.t -> Pp.t val ppidmap : (Names.Id.Map.key -> 'a -> Pp.t) -> 'a Names.Id.Map.t -> unit val pridmapgen : 'a Names.Id.Map.t -> Pp.t val ppidmapgen : 'a Names.Id.Map.t -> unit val printmapgen : 'a Int.Map.t -> Pp.t val ppintmapgen : 'a Int.Map.t -> unit val ppmpmapgen : 'a Names.ModPath.Map.t -> unit val ppdpmapgen : 'a Names.DirPath.Map.t -> unit val ppconmapenvgen : 'a Names.Cmap_env.t -> unit val ppmindmapenvgen : 'a Names.Mindmap_env.t -> unit val prididmap : Names.Id.t Names.Id.Map.t -> Pp.t val ppididmap : Names.Id.t Names.Id.Map.t -> unit val prconstrunderbindersidmap : (Names.Id.t list * EConstr.constr) Names.Id.Map.t -> Pp.t val ppconstrunderbindersidmap : (Names.Id.t list * EConstr.constr) Names.Id.Map.t -> unit val ppevarsubst : (Constr.t * Constr.t option * Names.Id.Map.key) list Names.Id.Map.t -> unit val ppunbound_ltac_var_map : 'a Genarg.generic_argument Names.Id.Map.t -> unit val pr_closure : Ltac_pretype.closure -> Pp.t val pr_closed_glob_constr_idmap : Ltac_pretype.closed_glob_constr Names.Id.Map.t -> Pp.t val pr_closed_glob_constr : Ltac_pretype.closed_glob_constr -> Pp.t val ppclosure : Ltac_pretype.closure -> unit val ppclosedglobconstr : Ltac_pretype.closed_glob_constr -> unit val ppclosedglobconstridmap : Ltac_pretype.closed_glob_constr Names.Id.Map.t -> unit val ppglobal : Names.GlobRef.t -> unit val ppconst : Names.KerName.t * (Constr.constr, 'a) Environ.punsafe_judgment -> unit val ppvar : Names.Id.t * Constr.constr -> unit val genppj : ('a -> Pp.t * Pp.t) -> 'a -> Pp.t val ppj : EConstr.unsafe_judgment -> unit val ppsubst : Mod_subst.substitution -> unit val ppdelta : Mod_subst.delta_resolver -> unit val pp_idpred : Names.Id.Pred.t -> unit val pp_cpred : Names.Cpred.t -> unit val pp_transparent_state : TransparentState.t -> unit val pp_estack_t : Reductionops.Stack.t -> unit val pp_state_t : Reductionops.state -> unit val ppmetas : Unification.Metaset.t -> unit val ppmetamap : Unification.Meta.t -> unit val ppevm : Evd.evar_map -> unit val ppevmall : Evd.evar_map -> unit val pr_existentialset : Evar.Set.t -> Pp.t val ppexistentialset : Evar.Set.t -> unit val ppexistentialfilter : Evd.Filter.t -> unit val ppclenv : Clenv.clausenv -> unit val ppgoal : Proofview.Goal.t -> unit val ppgoal_with_state : Proofview_monad.goal_with_state -> unit val pphintdb : Hints.Hint_db.t -> unit val ppproofview : Proofview.proofview -> unit val pproof : Proof.t -> unit (* Universes *) val ppuni : Univ.Universe.t -> unit val ppuni_level : Univ.Level.t -> unit (* raw *) val ppqvar : Sorts.QVar.t -> unit val ppesorts : EConstr.ESorts.t -> unit val pperelevance : EConstr.ERelevance.t -> unit val prlev : Univ.Level.t -> Pp.t (* with global names (does this work?) *) val ppqvarset : Sorts.QVar.Set.t -> unit val ppqset : Sorts.Quality.Set.t -> unit val ppuniverse_set : Univ.Level.Set.t -> unit val ppuniverse_instance : UVars.Instance.t -> unit val ppuniverse_einstance : EConstr.EInstance.t -> unit val ppuniverse_context : UVars.UContext.t -> unit val ppaucontext : UVars.AbstractContext.t -> unit val ppuniverse_subst : UnivSubst.universe_subst -> unit val ppuniverse_opt_subst : UState.universe_opt_subst -> unit val pppoly_flags : PolyFlags.t -> unit val ppqvar_subst : Sorts.Quality.t Sorts.QVar.Map.t -> unit val ppuniverse_level_subst : UVars.universe_level_subst -> unit val ppustate : UState.t -> unit val ppconstraints : Univ.UnivConstraints.t -> unit val ppqconstraints : Sorts.ElimConstraints.t -> unit val ppuniverseconstraints : UnivProblem.Set.t -> unit val ppuniverse_context_future : UVars.UContext.t Future.computation -> unit val ppuniverses : UGraph.t -> unit val ppqualities : QGraph.t -> unit val ppelim_constraints : Sorts.ElimConstraints.t -> unit val pp_partialfsubst : (CClosure.fconstr, Sorts.Quality.t, Univ.Universe.t) Partial_subst.t -> unit val pp_partialsubst : (EConstr.constr, Sorts.Quality.t, Univ.Universe.t) Partial_subst.t -> unit val ppnamedcontextval : Environ.named_context_val -> unit val ppenv : Environ.env -> unit val ppglobenv : GlobEnv.t -> unit val ppenvwithcst : Environ.env -> unit val pptac : Ltac_plugin.Tacexpr.glob_tactic_expr -> unit val ppobj : Libobject.obj -> unit (* Some super raw printers *) val cast_kind_display : Constr.cast_kind -> string val constr_display : Constr.constr -> unit val econstr_display : EConstr.constr -> unit val print_pure_constr : Constr.types -> unit val print_pure_econstr : EConstr.types -> unit val pploc : Loc.t -> unit val pp_argument_type : Genarg.argument_type -> unit val pp_generic_argument : 'a Genarg.generic_argument -> unit val prgenarginfo : Geninterp.Val.t -> Pp.t val ppgenarginfo : Geninterp.Val.t -> unit val ppgenargargt : ('a, 'b, 'c) Genarg.ArgT.tag -> unit val ppist : Geninterp.interp_sign -> unit val raw_string_of_ref : ?loc:Loc.t -> Names.Id.Set.t -> Names.GlobRef.t -> Libnames.qualid val short_string_of_ref : ?loc:Loc.t -> Names.Id.Set.t -> Names.GlobRef.t -> Libnames.qualid rocq-9.2.0/dev/vm_printers.ml000066400000000000000000000055501516144147600161640ustar00rootroot00000000000000open Format open Sorts open Names open Vmemitcodes open Values open Vmvalues let ppripos (ri,pos) = (match ri with | Reloc_annot a -> print_string "switch\n" | Reloc_const _ -> print_string "structured constant\n" | Reloc_getglobal kn -> print_string ("getglob "^(Constant.to_string kn)^"\n") | Reloc_caml_prim op -> print_string ("caml primitive "^ CPrimitives.to_string @@ Vmbytecodes.caml_prim_to_prim op) ); print_flush () let ppsort = function | SProp -> print_string "SProp" | Set -> print_string "Set" | Prop -> print_string "Prop" | Type _ -> print_string "Type" | QSort _ -> print_string "QSort" let print_idkey idk = match idk with | ConstKey sp -> print_string "Cons("; print_string (Constant.to_string sp); print_string ")" | VarKey id -> print_string (Id.to_string id) | RelKey i -> print_string "~";print_int i | EvarKey evk -> print_string "Evar("; print_int (Evar.repr evk); print_string ")" let rec ppzipper z = match z with | Zapp args -> let n = nargs args in open_hbox (); for i = 0 to n-2 do ppvalues (arg args i);print_string ";";print_space() done; if n-1 >= 0 then ppvalues (arg args (n-1)); close_box() | Zfix _ -> print_string "Zfix" | Zswitch _ -> print_string "Zswitch" | Zproj _ -> print_string "Zproj" and ppstack s = open_hovbox 0; print_string "["; List.iter (fun z -> ppzipper z;print_string " | ") s; print_string "]"; close_box() and ppatom a = match a with | Aid idk -> print_idkey idk | Asort u -> print_string "Sort(...)" | Aind(sp,i) -> print_string "Ind("; print_string (MutInd.to_string sp); print_string ","; print_int i; print_string ")" and ppwhd whd = match whd with | Vprod _ -> print_string "product" | Vfun _ -> print_string "function" | Vfix _ -> print_string "vfix" | Vcofix _ -> print_string "cofix" | Vconst i -> print_string "C(";print_int i;print_string")" | Vblock b -> ppvblock b | Vint64 i -> printf "int64(%LiL)" i | Vfloat64 f -> printf "float64(%.17g)" f | Vstring s -> printf "string(%S)" (Pstring.to_string s) | Varray t -> ppvarray t | Vaccu (a, s) -> open_hbox();ppatom a;close_box(); print_string"@";ppstack s and ppvblock b = open_hbox(); print_string "Cb(";print_int (btag b); let n = bsize b in for i = 0 to n -1 do print_string ",";ppvalues (bfield b i) done; print_string")"; close_box() and ppvarray t = let length = Parray.length_int t in open_hbox(); print_string "[|"; for i = 0 to length - 2 do ppvalues (Parray.get t (Uint63.of_int i)); print_string "; " done; ppvalues (Parray.get t (Uint63.of_int (length - 1))); print_string " | "; ppvalues (Parray.default t); print_string " |]"; close_box() and ppvalues v = open_hovbox 0;ppwhd (whd_val v);close_box(); print_flush() rocq-9.2.0/dev/vm_printers.mli000066400000000000000000000020541516144147600163310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val ppsort : Sorts.t -> unit val print_idkey : Vmvalues.id_key -> unit val ppzipper : Vmvalues.zipper -> unit val ppstack : Vmvalues.stack -> unit val ppatom : Vmvalues.atom -> unit val ppwhd : Vmvalues.kind -> unit val ppvblock : Vmvalues.vblock -> unit val ppvarray : Vmvalues.values Parray.t -> unit val ppvalues : Vmvalues.values -> unit rocq-9.2.0/doc/000077500000000000000000000000001516144147600132445ustar00rootroot00000000000000rocq-9.2.0/doc/LICENSE000066400000000000000000000751261516144147600142640ustar00rootroot00000000000000The Rocq Reference Manual is a collective work from the Rocq Development Team whose members are listed on https://rocq-prover.org/governance. All related documents (the LaTeX and BibTeX sources, the embedded png files, and the PostScript, PDF and html outputs) are copyright Inria, CNRS and contributors, with the exception of the Ubuntu font file UbuntuMono-B.ttf, which is Copyright 2010,2011 Canonical Ltd and licensed under the Ubuntu font license, version 1.0 (https://www.ubuntu.com/legal/terms-and-policies/font-licence), its derivative CoqNotations.ttf distributed under the same license, and the _templates/versions.html file derived from sphinx_rtd_theme, which is Copyright 2013-2018 Dave Snider, Read the Docs, Inc. & contributors and distributed under the MIT License included in that file. The material connected to the Reference Manual may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Options A and B are *not* elected. The Rocq Core Library is a collective work from the Rocq Development Team. All related documents (the Rocq vernacular source files and the PostScript, PDF and html outputs) are copyright Inria, CNRS and contributors. The material connected to the Standard Library is distributed under the terms of the Lesser General Public License version 2.1 or later. ---------------------------------------------------------------------- *Open Publication License* v1.0, 8 June 1999 *I. REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS* The Open Publication works may be reproduced and distributed in whole or in part, in any medium physical or electronic, provided that the terms of this license are adhered to, and that this license or an incorporation of it by reference (with any options elected by the author(s) and/or publisher) is displayed in the reproduction. Proper form for an incorporation by reference is as follows: Copyright (c) by . This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, vX.Y or later (the latest version is presently available at http://www.opencontent.org/openpub/). The reference must be immediately followed with any options elected by the author(s) and/or publisher of the document (see section VI). Commercial redistribution of Open Publication-licensed material is permitted. Any publication in standard (paper) book form shall require the citation of the original publisher and author. The publisher and author's names shall appear on all outer surfaces of the book. On all outer surfaces of the book the original publisher's name shall be as large as the title of the work and cited as possessive with respect to the title. *II. COPYRIGHT* The copyright to each Open Publication is owned by its author(s) or designee. *III. SCOPE OF LICENSE* The following license terms apply to all Open Publication works, unless otherwise explicitly stated in the document. Mere aggregation of Open Publication works or a portion of an Open Publication work with other works or programs on the same media shall not cause this license to apply to those other works. The aggregate work shall contain a notice specifying the inclusion of the Open Publication material and appropriate copyright notice. SEVERABILITY. If any part of this license is found to be unenforceable in any jurisdiction, the remaining portions of the license remain in force. NO WARRANTY. Open Publication works are licensed and provided "as is" without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement. *IV. REQUIREMENTS ON MODIFIED WORKS* All modified versions of documents covered by this license, including translations, anthologies, compilations and partial documents, must meet the following requirements: 1. The modified version must be labeled as such. 2. The person making the modifications must be identified and the modifications dated. 3. Acknowledgement of the original author and publisher if applicable must be retained according to normal academic citation practices. 4. The location of the original unmodified document must be identified. 5. The original author's (or authors') name(s) may not be used to assert or imply endorsement of the resulting document without the original author's (or authors') permission. *V. GOOD-PRACTICE RECOMMENDATIONS * In addition to the requirements of this license, it is requested from and strongly recommended of redistributors that: 1. If you are distributing Open Publication works on hardcopy or CD-ROM, you provide email notification to the authors of your intent to redistribute at least thirty days before your manuscript or media freeze, to give the authors time to provide updated documents. This notification should describe modifications, if any, made to the document. 2. All substantive modifications (including deletions) be either clearly marked up in the document or else described in an attachment to the document. 3. Finally, while it is not mandatory under this license, it is considered good form to offer a free copy of any hardcopy and CD-ROM expression of an Open Publication-licensed work to its author(s). *VI. LICENSE OPTIONS* The author(s) and/or publisher of an Open Publication-licensed document may elect certain options by appending language to the reference to or copy of the license. These options are considered part of the license instance and must be included with the license (or its incorporation by reference) in derived works. A. To prohibit distribution of substantively modified versions without the explicit permission of the author(s). "Substantive modification" is defined as a change to the semantic content of the document, and excludes mere changes in format or typographical corrections. To accomplish this, add the phrase `Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.' to the license reference or copy. B. To prohibit any publication of this work or derivative works in whole or in part in standard (paper) book form for commercial purposes is prohibited unless prior permission is obtained from the copyright holder. To accomplish this, add the phrase 'Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.' to the license reference or copy. ---------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS rocq-9.2.0/doc/Makefile.docgram000066400000000000000000000057241516144147600163270ustar00rootroot00000000000000###################################################################### # doc_grammar tool ###################################################################### DOCGRAMWARN ?= 0 ifeq ($(DOCGRAMWARN),0) DOCGRAMWARNFLAG=-no-warn else DOCGRAMWARNFLAG= endif # List mlg files explicitly to avoid ordering problems (across # different installations / make versions). DOC_MLGS := \ parsing/g_constr.mlg parsing/g_prim.mlg \ toplevel/g_toplevel.mlg \ vernac/g_proofs.mlg vernac/g_redexpr.mlg vernac/g_vernac.mlg vernac/g_obligations.mlg \ plugins/btauto/g_btauto.mlg \ plugins/cc/g_congruence.mlg \ plugins/derive/g_derive.mlg \ plugins/extraction/g_extraction.mlg \ plugins/firstorder/g_ground.mlg \ plugins/funind/g_indfun.mlg \ plugins/ltac/coretactics.mlg plugins/ltac/extraargs.mlg plugins/ltac/extratactics.mlg \ plugins/ltac/g_auto.mlg plugins/ltac/g_class.mlg plugins/ltac/g_eqdecide.mlg \ plugins/ltac/g_ltac.mlg plugins/ltac/g_rewrite.mlg \ plugins/ltac/g_tactic.mlg plugins/ltac/profile_ltac_tactics.mlg \ plugins/micromega/g_micromega.mlg plugins/micromega/g_zify.mlg \ plugins/nsatz/g_nsatz.mlg \ plugins/ring/g_ring.mlg \ plugins/rtauto/g_rtauto.mlg \ plugins/syntax/g_number_string.mlg \ plugins/ltac2/g_ltac2.mlg plugins/ltac2_ltac1/g_ltac2_ltac1.mlg DOC_EDIT_MLGS := $(wildcard doc/tools/docgram/*.edit_mlg) DOC_RSTS := $(wildcard doc/sphinx/*/*.rst) $(wildcard doc/sphinx/*/*/*.rst) REAL_DOC_MLGS := $(wildcard */*.mlg plugins/*/*.mlg) # omit SSR MLGS and chapter for now SSR_MLGS := \ plugins/ssr/ssrparser.mlg plugins/ssr/ssrtacs.mlg plugins/ssr/ssrvernac.mlg \ plugins/ssrmatching/g_ssrmatching.mlg REAL_DOC_MLGS := $(filter-out $(SSR_MLGS),$(REAL_DOC_MLGS)) SSR_RSTS := doc/sphinx/proof-engine/ssreflect-proof-language.rst DOC_RSTS := $(filter-out $(SSR_RSTS),$(DOC_RSTS)) ifneq ($(sort $(DOC_MLGS)),$(sort $(REAL_DOC_MLGS))) missing_mlgs := $(filter-out $(REAL_DOC_MLGS),$(DOC_MLGS)) extra_mlgs := $(filter-out $(DOC_MLGS),$(SSR_MLGS),$(REAL_DOC_MLGS)) $(error mlg file list mismatch in Makefile.doc: $(if $(missing_mlgs),$(missing_mlgs) not found) $(if $(extra_mlgs),$(extra_mlgs) not listed)) endif doc/tools/docgram/fullGrammar: $(DOC_GRAM) $(DOC_MLGS) $(SHOW)'DOC_GRAM' $(HIDE)$(DOC_GRAM) -short -no-warn $(DOC_MLGS) #todo: add a dependency of sphinx on updated_rsts when we're ready doc/tools/docgram/orderedGrammar doc/tools/docgram/updated_rsts: doc/tools/docgram/fullGrammar $(DOC_GRAM) $(DOC_EDIT_MLGS) $(SHOW)'DOC_GRAM_RSTS' $(HIDE)$(DOC_GRAM) $(DOCGRAMWARNFLAG) -check-cmds -check-tacs $(DOC_MLGS) $(DOC_RSTS) .PRECIOUS: doc/tools/docgram/orderedGrammar doc/tools/docgram/updated_rsts: doc/tools/docgram/orderedGrammar .PHONY: doc_gram doc_gram_verify doc_gram_rsts doc_gram: doc/tools/docgram/fullGrammar doc_gram_verify: $(DOC_GRAM) $(DOC_MLGS) $(SHOW)'DOC_GRAM_VERIFY' $(HIDE)$(DOC_GRAM) -no-warn -verify -check-cmds -check-tacs $(DOC_MLGS) $(DOC_RSTS) doc_gram_rsts: doc/tools/docgram/updated_rsts # For emacs: # Local Variables: # mode: makefile # End: rocq-9.2.0/doc/README.md000066400000000000000000000113601516144147600145240ustar00rootroot00000000000000The Coq documentation ===================== The Coq documentation includes - A Reference Manual - A document presenting the Coq standard library The documentation of the latest released version is available on the Coq web site at [rocq-prover.org/docs](https://rocq-prover.org/docs). Additionally, you can view the reference manual for the development version at , and the documentation of the standard library for the development version at . The reference manual is written in reStructuredText and compiled using Sphinx. See [`sphinx/README.rst`](sphinx/README.rst) to learn more about the format that is used. The documentation for the standard library is generated from the `.v` source files using `rocq doc`. Dependencies ------------ ### HTML documentation To produce the complete documentation in HTML, you will need Coq dependencies listed in [`INSTALL.md`](../INSTALL.md). Additionally, the Sphinx-based reference manual requires Python 3, and the following Python packages: - sphinx >= 5.0.0 - sphinx_rtd_theme >= 1.1.0 - beautifulsoup4 >= 4.10.0 - antlr4-python3-runtime >= 4.7.1 & <= 4.9.3 - pexpect >= 4.8.0 - sphinxcontrib-bibtex >= 2.4.2 To install them, you should first install pip and setuptools (for instance, with `apt install python3-pip python3-setuptools` on Debian / Ubuntu) then run: pip3 install sphinx sphinx_rtd_theme beautifulsoup4 \ antlr4-python3-runtime==4.7.1 pexpect sphinxcontrib-bibtex Nix users should get the correct development environment to build the HTML documentation from Coq's [`default.nix`](../default.nix) (note this doesn't include the LaTeX packages needed to build the full documentation). You can check the dependencies using the `doc/tools/coqrst/checkdeps.py` script. ### Other formats To produce the documentation in PDF and PostScript formats, the following additional tools are required: - latex (latex2e) - pdflatex - dvips - makeindex - xelatex - latexmk All of them are part of the TexLive distribution. E.g. on Debian / Ubuntu, install them with: apt install texlive-full Or if you want to use less disk space: apt install texlive-latex-extra texlive-fonts-recommended texlive-xetex \ latexmk fonts-freefont-otf ### Setting the locale for Python Make sure that the locale is configured on your platform so that Python encodes printed messages with utf-8 rather than generating runtime exceptions for non-ascii characters. The `.UTF-8` in `export LANG=C.UTF-8` sets UTF-8 encoding. The `C` can be replaced with any supported language code. You can set the default for a Docker build with `ENV LANG C.UTF-8`. (Python may look at other environment variables to determine the locale; see the [Python documentation](https://docs.python.org/3/library/locale.html#locale.getdefaultlocale)). ### Libraries Most of the refman compiles with only the rocq-core package. However, in order to showcase some nice advertising examples with some external libraries included in Coq CI, a few code blocks in the refman depend on those libraries. These blocks are marked with the `extra` parameter (see [`sphinx/README.rst`](sphinx/README.rst) for more details). The targets below make those blocks optional but their correct compilation is checked in the CI target `doc:ci-refman`. Compilation ----------- The current documentation targets are: - `make refman-html` Build the reference manual in HTML form into `_build/default/doc/refman-html` - `make refman-pdf` Build the reference manual in PDF form into `_build/default/doc/refman-pdf` - `make corelib-html` Build Rocq core library documentation into `_build/default/doc/corelib/html` - `make apidoc` Build the ML API's documentation into `_build/default/_doc/_html` To build the Sphinx documentation without stopping at the first warning, change the value of the `SPHINXWARNOPT` variable (default is `-W`). The following will build the Sphinx documentation without stopping at the first warning, and store all the warnings in the file `/tmp/warn.log`: ``` SPHINXWARNOPT="-w/tmp/warn.log" make refman-html ``` Note that inspecting local copies of the docs may behave in unexpected ways if opening the sources with a browser (eg with `firefox _build/default/doc/refman-html/index.html`). In order to avoid this, either inspect the version generated by the CI or run a local server, for example with: ``` cd _build/default/doc/refman-html/ && python3 -m http.server ``` Installation ------------ The produced documents are stored in the described directories above, you can install them just by copying the contents to the desired directory. In the future, the `rocq-doc` and `rocq-core` opam packages will install the documentation automatically. rocq-9.2.0/doc/changelog/000077500000000000000000000000001516144147600151735ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/00-title.rst000066400000000000000000000001001516144147600172520ustar00rootroot00000000000000Unreleased changes ------------------ .. contents:: :local: rocq-9.2.0/doc/changelog/01-kernel/000077500000000000000000000000001516144147600166715ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/01-kernel/00000-title.rst000066400000000000000000000000201516144147600211710ustar00rootroot00000000000000 Kernel ^^^^^^ rocq-9.2.0/doc/changelog/02-specification-language/000077500000000000000000000000001516144147600220135ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/02-specification-language/00000-title.rst000066400000000000000000000001201516144147600243140ustar00rootroot00000000000000 Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/03-notations/000077500000000000000000000000001516144147600174315ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/03-notations/00000-title.rst000066400000000000000000000000261516144147600217370ustar00rootroot00000000000000 Notations ^^^^^^^^^ rocq-9.2.0/doc/changelog/04-tactics/000077500000000000000000000000001516144147600170465ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/04-tactics/00000-title.rst000066400000000000000000000000221516144147600213500ustar00rootroot00000000000000 Tactics ^^^^^^^ rocq-9.2.0/doc/changelog/05-Ltac-language/000077500000000000000000000000001516144147600200615ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/05-Ltac-language/00000-title.rst000066400000000000000000000000361516144147600223700ustar00rootroot00000000000000 Ltac language ^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/06-Ltac2-language/000077500000000000000000000000001516144147600201445ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/06-Ltac2-language/00000-title.rst000066400000000000000000000000401516144147600224460ustar00rootroot00000000000000 Ltac2 language ^^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/07-ssreflect/000077500000000000000000000000001516144147600174115ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/07-ssreflect/00000-title.rst000066400000000000000000000000261516144147600217170ustar00rootroot00000000000000 SSReflect ^^^^^^^^^ rocq-9.2.0/doc/changelog/08-vernac-commands-and-options/000077500000000000000000000000001516144147600227265ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/08-vernac-commands-and-options/00000-title.rst000066400000000000000000000000541516144147600252350ustar00rootroot00000000000000 Commands and options ^^^^^^^^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/09-cli-tools/000077500000000000000000000000001516144147600173265ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/09-cli-tools/00000-title.rst000066400000000000000000000000501516144147600216310ustar00rootroot00000000000000 Command-line tools ^^^^^^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/10-rocqide/000077500000000000000000000000001516144147600170375ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/10-rocqide/00000-title.rst000066400000000000000000000000221516144147600213410ustar00rootroot00000000000000 RocqIDE ^^^^^^^ rocq-9.2.0/doc/changelog/11-corelib/000077500000000000000000000000001516144147600170315ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/11-corelib/00000-title.rst000066400000000000000000000000221516144147600213330ustar00rootroot00000000000000 Corelib ^^^^^^^ rocq-9.2.0/doc/changelog/12-infrastructure-and-dependencies/000077500000000000000000000000001516144147600236575ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/12-infrastructure-and-dependencies/00000-title.rst000066400000000000000000000001021516144147600261600ustar00rootroot00000000000000 Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/13-extraction/000077500000000000000000000000001516144147600175745ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/13-extraction/00000-title.rst000066400000000000000000000000301516144147600220750ustar00rootroot00000000000000 Extraction ^^^^^^^^^^ rocq-9.2.0/doc/changelog/14-misc/000077500000000000000000000000001516144147600163505ustar00rootroot00000000000000rocq-9.2.0/doc/changelog/14-misc/00000-title.rst000066400000000000000000000000361516144147600206570ustar00rootroot00000000000000 Miscellaneous ^^^^^^^^^^^^^ rocq-9.2.0/doc/changelog/README.md000066400000000000000000000037771516144147600164700ustar00rootroot00000000000000# Unreleased changelog # ## When to add an entry? ## All new features, user-visible changes to features, user-visible or otherwise important infrastructure changes, and important bug fixes should get a changelog entry. Compatibility-breaking changes should always get a changelog entry, which should explain what compatibility breakage is to expect. Pull requests changing the ML API in significant ways should add an entry in [`dev/doc/changes.md`](../../dev/doc/changes.md). ## How to add an entry? ## Run `./dev/tools/make-changelog.sh`: it will ask you for your PR number, and to choose among the predefined categories, and the predefined types of changes. Afterward, fill in the automatically generated entry with a short description of your change (which should describe any compatibility issues in particular). You may also add a reference to the relevant fixed issue, and credit reviewers, co-authors, and anyone who helped advance the PR. The format for changelog entries is the same as in the reference manual. In particular, you may reference the documentation you just added with `:ref:`, `:tacn:`, `:cmd:`, `:opt:`, `:token:`, etc. See the [documentation of the Sphinx format](../sphinx/README.rst) of the manual for details. Here is a summary of the structure of a changelog entry: ``` rst - **Added / Changed / Deprecated / Fixed / Removed:** Description of the changes, with possible link to :ref:`relevant-section` of the updated documentation (`#PRNUM `_, [fixes `#ISSUE1 `_ [ and `#ISSUE2 `_],] by Full Name[, with help / review of Full Name]). ``` The first line indicates the type of change. Available types come from the [Keep a Changelog 1.0.0](https://keepachangelog.com/en/1.0.0/) specification. We exclude the "Security" type for now because of the absence of a process for handling critical bugs (proof of False) as security vulnerabilities. rocq-9.2.0/doc/common/000077500000000000000000000000001516144147600145345ustar00rootroot00000000000000rocq-9.2.0/doc/common/macros.tex000066400000000000000000000476611516144147600165600ustar00rootroot00000000000000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MACROS FOR THE REFERENCE MANUAL OF COQ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % For commentaries (define \com as {} for the release manual) %\newcommand{\com}[1]{{\it(* #1 *)}} %\newcommand{\com}[1]{} %%OPTIONS for HACHA %\renewcommand{\cuttingunit}{section} %BEGIN LATEX \newenvironment{centerframe}% {\bgroup \dimen0=\textwidth \advance\dimen0 by -2\fboxrule \advance\dimen0 by -2\fboxsep \setbox0=\hbox\bgroup \begin{minipage}{\dimen0}% \begin{center}}% {\end{center}% \end{minipage}\egroup \centerline{\fbox{\box0}}\egroup } %END LATEX %HEVEA \newenvironment{centerframe}{\begin{center}}{\end{center}} %HEVEA \renewcommand{\vec}[1]{\mathbf{#1}} %\renewcommand{\ominus}{-} % Hevea does a good job translating these commands %\renewcommand{\oplus}{+} %\renewcommand{\otimes}{\times} %\newcommand{\land}{\wedge} %\newcommand{\lor}{\vee} %HEVEA \renewcommand{\k}[1]{#1} % \k{a} is supposed to produce a with a little stroke %HEVEA \newcommand{\phantom}[1]{\qquad} %%%%%%%%%%%%%%%%%%%%%%% % Formatting commands % %%%%%%%%%%%%%%%%%%%%%%% \newcommand{\ErrMsg}{\medskip \noindent {\bf Error message: }} \newcommand{\ErrMsgx}{\medskip \noindent {\bf Error messages: }} \newcommand{\variant}{\medskip \noindent {\bf Variant: }} \newcommand{\variants}{\medskip \noindent {\bf Variants: }} \newcommand{\SeeAlso}{\medskip \noindent {\bf See also: }} \newcommand{\Rem}{\medskip \noindent {\bf Remark: }} \newcommand{\Rems}{\medskip \noindent {\bf Remarks: }} \newcommand{\Example}{\medskip \noindent {\bf Example: }} \newcommand{\examples}{\medskip \noindent {\bf Examples: }} \newcommand{\Warning}{\medskip \noindent {\bf Warning: }} \newcommand{\Warns}{\medskip \noindent {\bf Warnings: }} \newcounter{ex} \newcommand{\firstexample}{\setcounter{ex}{1}} \newcommand{\example}[1]{ \medskip \noindent \textbf{Example \arabic{ex}: }\textit{#1} \addtocounter{ex}{1}} \newenvironment{Variant}{\variant\begin{enumerate}}{\end{enumerate}} \newenvironment{Variants}{\variants\begin{enumerate}}{\end{enumerate}} \newenvironment{ErrMsgs}{\ErrMsgx\begin{enumerate}}{\end{enumerate}} \newenvironment{Remarks}{\Rems\begin{enumerate}}{\end{enumerate}} \newenvironment{Warnings}{\Warns\begin{enumerate}}{\end{enumerate}} \newenvironment{Examples}{\medskip\noindent{\bf Examples:} \begin{enumerate}}{\end{enumerate}} %\newcommand{\bd}{\noindent\bf} %\newcommand{\sbd}{\vspace{8pt}\noindent\bf} %\newcommand{\sdoll}[1]{\begin{small}$ #1~ $\end{small}} %\newcommand{\sdollnb}[1]{\begin{small}$ #1 $\end{small}} \newcommand{\kw}[1]{\textsf{#1}} %\newcommand{\spec}[1]{\{\,#1\,\}} % Building regular expressions \newcommand{\zeroone}[1]{\mbox{\sl [}{#1}\mbox{\sl ]}} \newcommand{\zeroonelax}[1]{\mbox{\sl [}#1\mbox{\sl ]}} %\newcommand{\zeroonemany}[1]{$\{$#1$\}$*} %\newcommand{\onemany}[1]{$\{$#1$\}$+} \newcommand{\nelistnosep}[1]{{#1} \mbox{\dots} {#1}} \newcommand{\nelist}[2]{{#1} {\tt #2} \mbox{\dots} {\tt #2} {#1}} \newcommand{\sequence}[2]{{\sl [}{#1} {\tt #2} \mbox{\dots} {\tt #2} {#1}{\sl ]}} \newcommand{\nelistwithoutblank}[2]{#1{\tt #2}\mbox{\dots}{\tt #2}#1} \newcommand{\sequencewithoutblank}[2]{$[$#1{\tt #2}\mbox{\dots}{\tt #2}#1$]$} % Used for RefMan-gal %\newcommand{\ml}[1]{\hbox{\tt{#1}}} %\newcommand{\op}{\,|\,} %%%%%%%%%%%%%%%%%%%%%%%% % Trademarks and so on % %%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\Coq}{\textsc{Coq}} \newcommand{\gallina}{\textsc{Gallina}} \newcommand{\Gallina}{\textsc{Gallina}} \newcommand{\RocqIDE}{\textsc{RocqIDE}} \newcommand{\ocaml}{\textsc{OCaml}} \newcommand{\camlpppp}{\textsc{Camlp5}} \newcommand{\emacs}{\textsc{GNU Emacs}} \newcommand{\ProofGeneral}{\textsc{Proof General}} \newcommand{\CIC}{\textsc{Cic}} \newcommand{\iCIC}{\textsc{Cic}} \newcommand{\FW}{\ensuremath{F_{\omega}}} \newcommand{\Program}{\textsc{Program}} \newcommand{\Russell}{\textsc{Russell}} \newcommand{\PVS}{\textsc{PVS}} %\newcommand{\bn}{{\sf BNF}} %%%%%%%%%%%%%%%%%%% % Name of tactics % %%%%%%%%%%%%%%%%%%% %\newcommand{\Natural}{\mbox{\tt Natural}} %%%%%%%%%%%%%%%%% % \rm\sl series % %%%%%%%%%%%%%%%%% \newcommand{\nterm}[1]{\textrm{\textsl{#1}}} \newcommand{\qstring}{\nterm{string}} %% New syntax specific entries \newcommand{\annotation}{\nterm{annotation}} \newcommand{\assums}{\nterm{assums}} % vernac \newcommand{\simpleassums}{\nterm{simple\_assums}} % assumptions \newcommand{\binder}{\nterm{binder}} \newcommand{\binders}{\nterm{binders}} \newcommand{\caseitems}{\nterm{match\_items}} \newcommand{\caseitem}{\nterm{match\_item}} \newcommand{\eqn}{\nterm{equation}} \newcommand{\ifitem}{\nterm{dep\_ret\_type}} \newcommand{\hyplocation}{\nterm{hyp\_location}} \newcommand{\convclause}{\nterm{conversion\_clause}} \newcommand{\occclause}{\nterm{occurrence\_clause}} \newcommand{\occgoalset}{\nterm{goal\_occurrences}} \newcommand{\atoccurrences}{\nterm{at\_occurrences}} \newcommand{\occlist}{\nterm{occurrences}} \newcommand{\params}{\nterm{params}} % vernac \newcommand{\returntype}{\nterm{return\_type}} \newcommand{\idparams}{\nterm{ident\_with\_params}} \newcommand{\statkwd}{\nterm{assertion\_keyword}} % vernac \newcommand{\termarg}{\nterm{arg}} \newcommand{\hintdef}{\nterm{hint\_definition}} \newcommand{\typecstr}{\zeroone{{\tt :}~{\term}}} \newcommand{\typecstrwithoutblank}{\zeroone{{\tt :}{\term}}} \newcommand{\typecstrtype}{\zeroone{{\tt :}~{\type}}} \newcommand{\Fwterm}{\nterm{Fwterm}} \newcommand{\Index}{\nterm{index}} \newcommand{\abbrev}{\nterm{abbreviation}} \newcommand{\atomictac}{\nterm{atomic\_tactic}} \newcommand{\bindinglist}{\nterm{bindings\_list}} \newcommand{\cast}{\nterm{cast}} \newcommand{\cofixpointbodies}{\nterm{cofix\_bodies}} \newcommand{\cofixpointbody}{\nterm{cofix\_body}} \newcommand{\commandtac}{\nterm{tactic\_invocation}} \newcommand{\constructor}{\nterm{constructor}} \newcommand{\convtactic}{\nterm{conv\_tactic}} \newcommand{\assumptionkeyword}{\nterm{assumption\_keyword}} \newcommand{\assumption}{\nterm{assumption}} \newcommand{\definition}{\nterm{definition}} \newcommand{\digit}{\nterm{digit}} \newcommand{\exteqn}{\nterm{ext\_eqn}} \newcommand{\field}{\nterm{field}} \newcommand{\fielddef}{\nterm{field\_def}} \newcommand{\firstletter}{\nterm{first\_letter}} \newcommand{\fixpg}{\nterm{fix\_pgm}} \newcommand{\fixpointbodies}{\nterm{fix\_bodies}} \newcommand{\fixpointbody}{\nterm{fix\_body}} \newcommand{\fixpoint}{\nterm{fixpoint}} \newcommand{\flag}{\nterm{flag}} \newcommand{\form}{\nterm{form}} \newcommand{\entry}{\nterm{entry}} \newcommand{\proditem}{\nterm{prod\_item}} \newcommand{\taclevel}{\nterm{tactic\_level}} \newcommand{\tacargtype}{\nterm{tactic\_argument\_type}} \newcommand{\scope}{\nterm{scope}} \newcommand{\delimkey}{\nterm{key}} \newcommand{\optscope}{\nterm{opt\_scope}} \newcommand{\declnotation}{\nterm{decl\_notation}} \newcommand{\symbolentry}{\nterm{symbol}} \newcommand{\modifiers}{\nterm{modifiers}} \newcommand{\binderinterp}{\nterm{binder\_interp}} \newcommand{\localdef}{\nterm{local\_def}} \newcommand{\localdecls}{\nterm{local\_decls}} \newcommand{\ident}{\nterm{ident}} \newcommand{\accessident}{\nterm{access\_ident}} \newcommand{\possiblybracketedident}{\nterm{possibly\_bracketed\_ident}} \newcommand{\inductivebody}{\nterm{ind\_body}} \newcommand{\inductive}{\nterm{inductive}} \newcommand{\naturalnumber}{\nterm{natural}} \newcommand{\integer}{\nterm{integer}} \newcommand{\multpattern}{\nterm{mult\_pattern}} \newcommand{\mutualcoinductive}{\nterm{mutual\_coinductive}} \newcommand{\mutualinductive}{\nterm{mutual\_inductive}} \newcommand{\nestedpattern}{\nterm{nested\_pattern}} \newcommand{\name}{\nterm{name}} \newcommand{\num}{\nterm{num}} \newcommand{\pattern}{\nterm{pattern}} % pattern for pattern-matching \newcommand{\orpattern}{\nterm{or\_pattern}} \newcommand{\intropattern}{\nterm{intro\_pattern}} \newcommand{\intropatternlist}{\nterm{intro\_pattern\_list}} \newcommand{\disjconjintropattern}{\nterm{disj\_conj\_intro\_pattern}} \newcommand{\namingintropattern}{\nterm{naming\_intro\_pattern}} \newcommand{\termpattern}{\nterm{term\_pattern}} % term with holes \newcommand{\pat}{\nterm{pat}} \newcommand{\pgs}{\nterm{pgms}} \newcommand{\pg}{\nterm{pgm}} \newcommand{\abullet}{\nterm{bullet}} %BEGIN LATEX \newcommand{\proof}{\nterm{proof}} %END LATEX %HEVEA \renewcommand{\proof}{\nterm{proof}} \newcommand{\record}{\nterm{record}} \newcommand{\recordkw}{\nterm{record\_keyword}} \newcommand{\rewrule}{\nterm{rewriting\_rule}} \newcommand{\sentence}{\nterm{sentence}} \newcommand{\simplepattern}{\nterm{simple\_pattern}} \newcommand{\sort}{\nterm{sort}} \newcommand{\specif}{\nterm{specif}} \newcommand{\assertion}{\nterm{assertion}} \newcommand{\str}{\nterm{string}} \newcommand{\subsequentletter}{\nterm{subsequent\_letter}} \newcommand{\switch}{\nterm{switch}} \newcommand{\messagetoken}{\nterm{message\_token}} \newcommand{\tac}{\nterm{tactic}} \newcommand{\terms}{\nterm{terms}} \newcommand{\term}{\nterm{term}} \newcommand{\module}{\nterm{module}} \newcommand{\modexpr}{\nterm{module\_expression}} \newcommand{\modtype}{\nterm{module\_type}} \newcommand{\onemodbinding}{\nterm{module\_binding}} \newcommand{\modbindings}{\nterm{module\_bindings}} \newcommand{\qualid}{\nterm{qualid}} \newcommand{\qualidorstring}{\nterm{qualid\_or\_string}} \newcommand{\class}{\nterm{class}} \newcommand{\dirpath}{\nterm{dirpath}} \newcommand{\typedidents}{\nterm{typed\_idents}} \newcommand{\type}{\nterm{type}} \newcommand{\vref}{\nterm{ref}} \newcommand{\zarithformula}{\nterm{zarith\_formula}} \newcommand{\zarith}{\nterm{zarith}} \newcommand{\ltac}{\mbox{${\mathcal{L}}_{tac}$}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \mbox{\sf } series for roman text in maths formulas % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\alors}{\mbox{\textsf{then}}} \newcommand{\alter}{\mbox{\textsf{alter}}} \newcommand{\bool}{\mbox{\textsf{bool}}} \newcommand{\conc}{\mbox{\textsf{conc}}} \newcommand{\cons}{\mbox{\textsf{cons}}} \newcommand{\consf}{\mbox{\textsf{consf}}} \newcommand{\emptyf}{\mbox{\textsf{emptyf}}} \newcommand{\EqSt}{\mbox{\textsf{EqSt}}} \newcommand{\false}{\mbox{\textsf{false}}} \newcommand{\filter}{\mbox{\textsf{filter}}} \newcommand{\forest}{\mbox{\textsf{forest}}} \newcommand{\from}{\mbox{\textsf{from}}} \newcommand{\hd}{\mbox{\textsf{hd}}} \newcommand{\haslength}{\mbox{\textsf{has\_length}}} \newcommand{\length}{\mbox{\textsf{length}}} \newcommand{\haslengthA}{\mbox {\textsf{has\_length~A}}} \newcommand{\List}{\mbox{\textsf{list}}} \newcommand{\ListA}{\mbox{\textsf{list}}~\ensuremath{A}} \newcommand{\nilhl}{\mbox{\textsf{nil\_hl}}} \newcommand{\conshl}{\mbox{\textsf{cons\_hl}}} \newcommand{\nat}{\mbox{\textsf{nat}}} \newcommand{\nO}{\mbox{\textsf{O}}} \newcommand{\nS}{\mbox{\textsf{S}}} \newcommand{\node}{\mbox{\textsf{node}}} \newcommand{\Nil}{\mbox{\textsf{nil}}} \newcommand{\SProp}{\mbox{\textsf{SProp}}} \newcommand{\Prop}{\mbox{\textsf{Prop}}} \newcommand{\Set}{\mbox{\textsf{Set}}} \newcommand{\si}{\mbox{\textsf{if}}} \newcommand{\sinon}{\mbox{\textsf{else}}} \newcommand{\Str}{\mbox{\textsf{Stream}}} \newcommand{\tl}{\mbox{\textsf{tl}}} \newcommand{\tree}{\mbox{\textsf{tree}}} \newcommand{\true}{\mbox{\textsf{true}}} \newcommand{\Type}{\mbox{\textsf{Type}}} \newcommand{\unfold}{\mbox{\textsf{unfold}}} \newcommand{\zeros}{\mbox{\textsf{zeros}}} \newcommand{\even}{\mbox{\textsf{even}}} \newcommand{\odd}{\mbox{\textsf{odd}}} \newcommand{\evenO}{\mbox{\textsf{even\_O}}} \newcommand{\evenS}{\mbox{\textsf{even\_S}}} \newcommand{\oddS}{\mbox{\textsf{odd\_S}}} \newcommand{\Prod}{\mbox{\textsf{prod}}} \newcommand{\Pair}{\mbox{\textsf{pair}}} %%%%%%%%% % Misc. % %%%%%%%%% \newcommand{\T}{\texttt{T}} \newcommand{\U}{\texttt{U}} \newcommand{\real}{\textsf{Real}} \newcommand{\Data}{\textit{Data}} \newcommand{\In} {{\textbf{in }}} \newcommand{\AND} {{\textbf{and}}} \newcommand{\If}{{\textbf{if }}} \newcommand{\Else}{{\textbf{else }}} \newcommand{\Then} {{\textbf{then }}} %\newcommand{\Let}{{\textbf{let }}} % looks like this is never used \newcommand{\Where}{{\textbf{where rec }}} \newcommand{\Function}{{\textbf{function }}} \newcommand{\Rec}{{\textbf{rec }}} %\newcommand{\cn}{\centering} \newcommand{\nth}{\mbox{$^{\mbox{\scriptsize th}}$}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math commands and symbols % %%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\la}{\leftarrow} \newcommand{\ra}{\rightarrow} \newcommand{\Ra}{\Rightarrow} \newcommand{\rt}{\Rightarrow} \newcommand{\lla}{\longleftarrow} \newcommand{\lra}{\longrightarrow} \newcommand{\Llra}{\Longleftrightarrow} \newcommand{\mt}{\mapsto} \newcommand{\ov}{\overrightarrow} \newcommand{\wh}{\widehat} \newcommand{\up}{\uparrow} \newcommand{\dw}{\downarrow} \newcommand{\nr}{\nearrow} \newcommand{\se}{\searrow} \newcommand{\sw}{\swarrow} \newcommand{\nw}{\nwarrow} \newcommand{\mto}{.\;} \newcommand{\vm}[1]{\vspace{#1em}} \newcommand{\vx}[1]{\vspace{#1ex}} \newcommand{\hm}[1]{\hspace{#1em}} \newcommand{\hx}[1]{\hspace{#1ex}} \newcommand{\sm}{\mbox{ }} \newcommand{\mx}{\mbox} %\newcommand{\nq}{\neq} %\newcommand{\eq}{\equiv} \newcommand{\fa}{\forall} %\newcommand{\ex}{\exists} \newcommand{\impl}{\rightarrow} %\newcommand{\Or}{\vee} %\newcommand{\And}{\wedge} \newcommand{\ms}{\models} \newcommand{\bw}{\bigwedge} \newcommand{\ts}{\times} \newcommand{\cc}{\circ} %\newcommand{\es}{\emptyset} %\newcommand{\bs}{\backslash} \newcommand{\vd}{\vdash} %\newcommand{\lan}{{\langle }} %\newcommand{\ran}{{\rangle }} %\newcommand{\al}{\alpha} \newcommand{\bt}{\beta} %\newcommand{\io}{\iota} \newcommand{\lb}{\lambda} %\newcommand{\sg}{\sigma} %\newcommand{\sa}{\Sigma} %\newcommand{\om}{\Omega} %\newcommand{\tu}{\tau} %%%%%%%%%%%%%%%%%%%%%%%%% % Custom maths commands % %%%%%%%%%%%%%%%%%%%%%%%%% \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{{\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 {\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$}} \newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}} \newcommand{\WTRED}[5]{\mbox{$#1[#2] \vdash #3 #4 #5$}} \newcommand{\WTERED}[4]{\mbox{$E[#1] \vdash #2 #3 #4$}} \newcommand{\WTELECONV}[3]{\WTERED{#1}{#2}{\leconvert}{#3}} \newcommand{\WTEGRED}[3]{\WTERED{\Gamma}{#1}{#2}{#3}} \newcommand{\WTECONV}[3]{\WTERED{#1}{#2}{\convert}{#3}} \newcommand{\WTEGCONV}[2]{\WTERED{\Gamma}{#1}{\convert}{#2}} \newcommand{\WTEGLECONV}[2]{\WTERED{\Gamma}{#1}{\leconvert}{#2}} \newcommand{\lab}[1]{\mathit{labels}(#1)} \newcommand{\dom}[1]{\mathit{dom}(#1)} \newcommand{\CI}[2]{\mbox{$\{#1\}^{#2}$}} \newcommand{\CIP}[3]{\mbox{$\{#1\}_{#2}^{#3}$}} \newcommand{\CIPV}[1]{\CIP{#1}{I_1.. I_k}{P_1.. P_k}} \newcommand{\CIPI}[1]{\CIP{#1}{I}{P}} \newcommand{\CIF}[1]{\mbox{$\{#1\}_{f_1.. f_n}$}} %BEGIN LATEX \newcommand{\NInd}[3]{\mbox{{\sf Ind}$(\begin{array}[t]{@{}l}#2:=#3 \,)\end{array}$}} \newcommand{\Ind}[4]{\mbox{{\sf Ind}$[#2](\begin{array}[t]{@{}l@{}}#3:=#4 \,)\end{array}$}} %END LATEX %HEVEA \newcommand{\NInd}[3]{\mbox{{\sf Ind}$(#2\,:=\,#3)$}} %HEVEA \newcommand{\Ind}[4]{\mbox{{\sf Ind}$[#2](#3\,:=\,#4)$}} \newcommand{\Indp}[5]{\mbox{{\sf Ind}$_{#5}(#1)[#2](\begin{array}[t]{@{}l}#3:=#4 \,)\end{array}$}} \newcommand{\Indpstr}[6]{\mbox{{\sf Ind}$_{#5}(#1)[#2](\begin{array}[t]{@{}l}#3:=#4 \,)/{#6}\end{array}$}} \newcommand{\Def}[4]{\mbox{{\sf Def}$(#1)(#2:=#3:#4)$}} \newcommand{\Assum}[3]{\mbox{{\sf Assum}$(#1)(#2:#3)$}} \newcommand{\Match}[3]{\mbox{$<\!#1\!>\!{\mbox{\tt Match}}~#2~{\mbox{\tt with}}~#3~{\mbox{\tt end}}$}} \newcommand{\Case}[3]{\mbox{$\kw{case}(#2,#1,#3)$}} \newcommand{\match}[3]{\mbox{$\kw{match}~ #2 ~\kw{with}~ #3 ~\kw{end}$}} \newcommand{\Fix}[2]{\mbox{\tt Fix}~#1\{#2\}} \newcommand{\CoFix}[2]{\mbox{\tt CoFix}~#1\{#2\}} \newcommand{\With}[2]{\mbox{\tt ~with~}} \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{$\mathcal{S}$}} \newcommand{\convert}{=_{\beta\delta\iota\zeta\eta}} \newcommand{\leconvert}{\leq_{\beta\delta\iota\zeta\eta}} \newcommand{\NN}{\mathbb{N}} \newcommand{\inference}[1]{$${#1}$$} \newcommand{\compat}[2]{\mbox{$[#1|#2]$}} \newcommand{\tristackrel}[3]{\mathrel{\mathop{#2}\limits_{#3}^{#1}}} \newcommand{\Impl}{{\it Impl}} \newcommand{\elem}{{\it e}} \newcommand{\Mod}[3]{{\sf Mod}({#1}:{#2}\,\zeroone{:={#3}})} \newcommand{\ModS}[2]{{\sf Mod}({#1}:{#2})} \newcommand{\ModType}[2]{{\sf ModType}({#1}:={#2})} \newcommand{\ModA}[2]{{\sf ModA}({#1}=={#2})} \newcommand{\functor}[3]{\ensuremath{{\sf Functor}(#1:#2)\;#3}} \newcommand{\funsig}[3]{\ensuremath{{\sf Funsig}(#1:#2)\;#3}} \newcommand{\sig}[1]{\ensuremath{{\sf Sig}~#1~{\sf End}}} \newcommand{\struct}[1]{\ensuremath{{\sf Struct}~#1~{\sf End}}} \newcommand{\structe}[1]{\ensuremath{ {\sf Struct}~\elem_1;\ldots;\elem_i;#1;\elem_{i+2};\ldots ;\elem_n~{\sf End}}} \newcommand{\structes}[2]{\ensuremath{ {\sf Struct}~\elem_1;\ldots;\elem_i;#1;\elem_{i+2}\{#2\} ;\ldots;\elem_n\{#2\}~{\sf End}}} \newcommand{\with}[3]{\ensuremath{#1~{\sf with}~#2 := #3}} \newcommand{\Spec}{{\it Spec}} \newcommand{\ModSEq}[3]{{\sf Mod}({#1}:{#2}:={#3})} %\newbox\tempa %\newbox\tempb %\newdimen\tempc %\newcommand{\mud}[1]{\hfil $\displaystyle{\mathstrut #1}$\hfil} %\newcommand{\rig}[1]{\hfil $\displaystyle{#1}$} % \newcommand{\irulehelp}[3]{\setbox\tempa=\hbox{$\displaystyle{\mathstrut #2}$}% % \setbox\tempb=\vbox{\halign{##\cr % \mud{#1}\cr % \noalign{\vskip\the\lineskip} % \noalign{\hrule height 0pt} % \rig{\vbox to 0pt{\vss\hbox to 0pt{${\; #3}$\hss}\vss}}\cr % \noalign{\hrule} % \noalign{\vskip\the\lineskip} % \mud{\copy\tempa}\cr}} % \tempc=\wd\tempb % \advance\tempc by \wd\tempa % \divide\tempc by 2 } % \newcommand{\irule}[3]{{\irulehelp{#1}{#2}{#3} % \hbox to \wd\tempa{\hss \box\tempb \hss}}} \newcommand{\sverb}[1]{{\tt #1}} \newcommand{\mover}[2]{{#1\over #2}} \newcommand{\jd}[2]{#1 \vdash #2} \newcommand{\mathline}[1]{\[#1\]} \newcommand{\zrule}[2]{#2: #1} \newcommand{\orule}[3]{#3: {\mover{#1}{#2}}} \newcommand{\trule}[4]{#4: \mover{#1 \qquad #2} {#3}} \newcommand{\thrule}[5]{#5: {\mover{#1 \qquad #2 \qquad #3}{#4}}} % placement of figures %BEGIN LATEX \renewcommand{\topfraction}{.99} \renewcommand{\bottomfraction}{.99} \renewcommand{\textfraction}{.01} \renewcommand{\floatpagefraction}{.9} %END LATEX % Macros Bruno pour description de la syntaxe \def\bfbar{\ensuremath{|\hskip -0.22em{}|\hskip -0.24em{}|}} \def\TERMbar{\bfbar} \def\TERMbarbar{\bfbar\bfbar} %% Macros pour les grammaires \def\GR#1{\text{\large(}#1\text{\large)}} \def\NT#1{\langle\textit{#1}\rangle} \def\NTL#1#2{\langle\textit{#1}\rangle_{#2}} \def\TERM#1{{\bf\textrm{\bf #1}}} %\def\TERM#1{{\bf\textsf{#1}}} \def\KWD#1{\TERM{#1}} \def\ETERM#1{\TERM{#1}} \def\CHAR#1{\TERM{#1}} \def\STAR#1{#1*} \def\STARGR#1{\GR{#1}*} \def\PLUS#1{#1+} \def\PLUSGR#1{\GR{#1}+} \def\OPT#1{#1?} \def\OPTGR#1{\GR{#1}?} %% Tableaux de definition de non-terminaux \newenvironment{cadre} {\begin{array}{|c|}\hline\\} {\\\\\hline\end{array}} \newenvironment{rulebox} {$$\begin{cadre}\begin{array}{r@{~}c@{~}l@{}l@{}r}} {\end{array}\end{cadre}$$} \def\DEFNT#1{\NT{#1} & ::= &} \def\EXTNT#1{\NT{#1} & ::= & ... \\&|&} \def\RNAME#1{(\textsc{#1})} \def\SEPDEF{\\\\} \def\nlsep{\\&|&} \def\nlcont{\\&&} \newenvironment{rules} {\begin{center}\begin{rulebox}} {\end{rulebox}\end{center}} %%% Local Variables: %%% mode: latex %%% TeX-master: "Reference-Manual" %%% End: rocq-9.2.0/doc/common/styles/000077500000000000000000000000001516144147600160575ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/000077500000000000000000000000001516144147600170235ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/000077500000000000000000000000001516144147600210215ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/cover.html000066400000000000000000000062311516144147600230270ustar00rootroot00000000000000 Reference Manual | The Coq Proof Assistant

Reference Manual

Version COQVERSION


The Coq Development Team




Copyright Β© 1999-2019, Inria, CNRS and contributors

This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub). Options A and B are not elected.

rocq-9.2.0/doc/common/styles/html/coqremote/footer.html000066400000000000000000000736171516144147600232230ustar00rootroot00000000000000 rocq-9.2.0/doc/common/styles/html/coqremote/header.html000066400000000000000000000420161516144147600231420ustar00rootroot00000000000000 Rocq Core Library: @@TITLE@@
rocq-9.2.0/doc/common/styles/html/coqremote/hevea.css000066400000000000000000000034461516144147600226320ustar00rootroot00000000000000 .li-itemize{margin:1ex 0ex;} .li-enumerate{margin:1ex 0ex;} .dd-description{margin:0ex 0ex 1ex 4ex;} .dt-description{margin:0ex;} .toc{list-style:none;} .thefootnotes{text-align:left;margin:0ex;} .dt-thefootnotes{margin:0em;} .dd-thefootnotes{margin:0em 0em 0em 2em;} .footnoterule{margin:1em auto 1em 0px;width:50%;} .caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto} .title{margin:2ex auto;text-align:center} .center{text-align:center;margin-left:auto;margin-right:auto;} .flushleft{text-align:left;margin-left:0ex;margin-right:auto;} .flushright{text-align:right;margin-left:auto;margin-right:0ex;} DIV TABLE{margin-left:inherit;margin-right:inherit;} PRE{text-align:left;margin-left:0ex;margin-right:auto;} BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;} TD P{margin:0px;} .boxed{border:1px solid black} .textboxed{border:1px solid black} .vbar{border:none;width:2px;background-color:black;} .hbar{border:none;height:2px;width:100%;background-color:black;} .hfill{border:none;height:1px;width:200%;background-color:black;} .vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;} .vdcell{white-space:nowrap;padding:0px;width:auto; border:2px solid green;} .display{border-collapse:separate;border-spacing:2px;width:auto; border:none;} .dcell{white-space:nowrap;padding:0px;width:auto; border:none;} .dcenter{margin:0ex auto;} .vdcenter{border:solid #FF8000 2px; margin:0ex auto;} .minipage{text-align:left; margin-left:0em; margin-right:auto;} .marginpar{border:solid thin black; width:20%; text-align:left;} .marginparleft{float:left; margin-left:0ex; margin-right:1ex;} .marginparright{float:right; margin-left:1ex; margin-right:0ex;} .theorem{text-align:left;margin:1ex auto 1ex 0ex;} .part{margin:2ex auto;text-align:center} rocq-9.2.0/doc/common/styles/html/coqremote/modules/000077500000000000000000000000001516144147600224715ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/modules/node/000077500000000000000000000000001516144147600234165ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/modules/node/node.css000066400000000000000000000012531516144147600250560ustar00rootroot00000000000000 .node-unpublished { background-color: #fff4f4; } .preview .node { background-color: #ffffea; } #node-admin-filter ul { list-style-type: none; padding: 0; margin: 0; width: 100%; } #node-admin-buttons { float: left; /* LTR */ margin-left: 0.5em; /* LTR */ clear: right; /* LTR */ } td.revision-current { background: #ffc; } .node-form .form-text { display: block; width: 95%; } .node-form .container-inline .form-text { display: inline; width: auto; } .node-form .standard { clear: both; } .node-form textarea { display: block; width: 95%; } .node-form .attachments fieldset { float: none; display: block; } .terms-inline { display: inline; } rocq-9.2.0/doc/common/styles/html/coqremote/modules/system/000077500000000000000000000000001516144147600240155ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/modules/system/defaults.css000066400000000000000000000012671516144147600263440ustar00rootroot00000000000000 /* ** HTML elements */ fieldset { margin-bottom: 1em; padding: .5em; } form { margin: 0; padding: 0; } hr { height: 1px; border: 1px solid gray; } img { border: 0; } table { border-collapse: collapse; } th { text-align: left; /* LTR */ padding-right: 1em; /* LTR */ border-bottom: 3px solid #ccc; } /* ** Markup free clearing ** Details: http://www.positioniseverything.net/easyclearing.html */ .clear-block:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .clear-block { display: inline-block; } /* Hides from IE-mac \*/ * html .clear-block { height: 1%; } .clear-block { display: block; } /* End hide from IE-mac */ rocq-9.2.0/doc/common/styles/html/coqremote/modules/system/system.css000066400000000000000000000233511516144147600260570ustar00rootroot00000000000000 /* ** HTML elements */ body.drag { cursor: move; } th.active img { display: inline; } tr.even, tr.odd { background-color: #eee; border-bottom: 1px solid #ccc; padding: 0.1em 0.6em; } tr.drag { background-color: #fffff0; } tr.drag-previous { background-color: #ffd; } td.active { background-color: #ddd; } td.checkbox, th.checkbox { text-align: center; } tbody { border-top: 1px solid #ccc; } tbody th { border-bottom: 1px solid #ccc; } thead th { text-align: left; /* LTR */ padding-right: 1em; /* LTR */ border-bottom: 3px solid #ccc; } /* ** Other common styles */ .breadcrumb { padding-bottom: .5em } div.indentation { width: 20px; height: 1.7em; margin: -0.4em 0.2em -0.4em -0.4em; /* LTR */ padding: 0.42em 0 0.42em 0.6em; /* LTR */ float: left; /* LTR */ } div.tree-child { background: url(../../misc/tree.png) no-repeat 11px center; /* LTR */ } div.tree-child-last { background: url(../../misc/tree-bottom.png) no-repeat 11px center; /* LTR */ } div.tree-child-horizontal { background: url(../../misc/tree.png) no-repeat -11px center; } .error { color: #e55; } div.error { border: 1px solid #d77; } div.error, tr.error { background: #fcc; color: #200; padding: 2px; } .warning { color: #e09010; } div.warning { border: 1px solid #f0c020; } div.warning, tr.warning { background: #ffd; color: #220; padding: 2px; } .ok { color: #008000; } div.ok { border: 1px solid #00aa00; } div.ok, tr.ok { background: #dfd; color: #020; padding: 2px; } .item-list .icon { color: #555; float: right; /* LTR */ padding-left: 0.25em; /* LTR */ clear: right; /* LTR */ } .item-list .title { font-weight: bold; } .item-list ul { margin: 0 0 0.75em 0; padding: 0; } .item-list ul li { margin: 0 0 0.25em 1.5em; /* LTR */ padding: 0; list-style: disc; } ol.task-list li.active { font-weight: bold; } .form-item { margin-top: 1em; margin-bottom: 1em; } tr.odd .form-item, tr.even .form-item { margin-top: 0; margin-bottom: 0; white-space: nowrap; } tr.merge-down, tr.merge-down td, tr.merge-down th { border-bottom-width: 0 !important; } tr.merge-up, tr.merge-up td, tr.merge-up th { border-top-width: 0 !important; } .form-item input.error, .form-item textarea.error, .form-item select.error { border: 2px solid red; } .form-item .description { font-size: 0.85em; } .form-item label { display: block; font-weight: bold; } .form-item label.option { display: inline; font-weight: normal; } .form-checkboxes, .form-radios { margin: 1em 0; } .form-checkboxes .form-item, .form-radios .form-item { margin-top: 0.4em; margin-bottom: 0.4em; } .marker, .form-required { color: #f00; } .more-link { text-align: right; /* LTR */ } .more-help-link { font-size: 0.85em; text-align: right; /* LTR */ } .nowrap { white-space: nowrap; } .item-list .pager { clear: both; text-align: center; } .item-list .pager li { background-image:none; display:inline; list-style-type:none; padding: 0.5em; } .pager-current { font-weight:bold; } .tips { margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; font-size: 0.9em; } dl.multiselect dd.b, dl.multiselect dd.b .form-item, dl.multiselect dd.b select { font-family: inherit; font-size: inherit; width: 14em; } dl.multiselect dd.a, dl.multiselect dd.a .form-item { width: 10em; } dl.multiselect dt, dl.multiselect dd { float: left; /* LTR */ line-height: 1.75em; padding: 0; margin: 0 1em 0 0; /* LTR */ } dl.multiselect .form-item { height: 1.75em; margin: 0; } /* ** Inline items (need to override above) */ .container-inline div, .container-inline label { display: inline; } /* ** Tab navigation */ ul.primary { border-collapse: collapse; padding: 0 0 0 1em; /* LTR */ white-space: nowrap; list-style: none; margin: 5px; height: auto; line-height: normal; border-bottom: 1px solid #bbb; } ul.primary li { display: inline; } ul.primary li a { background-color: #ddd; border-color: #bbb; border-width: 1px; border-style: solid solid none solid; height: auto; margin-right: 0.5em; /* LTR */ padding: 0 1em; text-decoration: none; } ul.primary li.active a { background-color: #fff; border: 1px solid #bbb; border-bottom: #fff 1px solid; } ul.primary li a:hover { background-color: #eee; border-color: #ccc; border-bottom-color: #eee; } ul.secondary { border-bottom: 1px solid #bbb; padding: 0.5em 1em; margin: 5px; } ul.secondary li { display: inline; padding: 0 1em; border-right: 1px solid #ccc; /* LTR */ } ul.secondary a { padding: 0; text-decoration: none; } ul.secondary a.active { border-bottom: 4px solid #999; } /* ** Autocomplete styles */ /* Suggestion list */ #autocomplete { position: absolute; border: 1px solid; overflow: hidden; z-index: 100; } #autocomplete ul { margin: 0; padding: 0; list-style: none; } #autocomplete li { background: #fff; color: #000; white-space: pre; cursor: default; } #autocomplete li.selected { background: #0072b9; color: #fff; } /* Animated throbber */ html.js input.form-autocomplete { background-image: url(../../misc/throbber.gif); background-repeat: no-repeat; background-position: 100% 2px; /* LTR */ } html.js input.throbbing { background-position: 100% -18px; /* LTR */ } /* ** Collapsing fieldsets */ html.js fieldset.collapsed { border-bottom-width: 0; border-left-width: 0; border-right-width: 0; margin-bottom: 0; height: 1em; } html.js fieldset.collapsed * { display: none; } html.js fieldset.collapsed legend { display: block; } html.js fieldset.collapsible legend a { padding-left: 15px; /* LTR */ background: url(../../misc/menu-expanded.png) 5px 75% no-repeat; /* LTR */ } html.js fieldset.collapsed legend a { background-image: url(../../misc/menu-collapsed.png); /* LTR */ background-position: 5px 50%; /* LTR */ } /* Note: IE-only fix due to '* html' (breaks Konqueror otherwise). */ * html.js fieldset.collapsed legend, * html.js fieldset.collapsed legend *, * html.js fieldset.collapsed table * { display: inline; } /* For Safari 2 to prevent collapsible fieldsets containing tables from disappearing due to tableheader.js. */ html.js fieldset.collapsible { position: relative; } html.js fieldset.collapsible legend a { display: block; } /* Avoid jumping around due to margins collapsing into collapsible fieldset border */ html.js fieldset.collapsible .fieldset-wrapper { overflow: auto; } /* ** Resizable text areas */ .resizable-textarea { width: 95%; } .resizable-textarea .grippie { height: 9px; overflow: hidden; background: #eee url(../../misc/grippie.png) no-repeat center 2px; border: 1px solid #ddd; border-top-width: 0; cursor: s-resize; } html.js .resizable-textarea textarea { margin-bottom: 0; width: 100%; display: block; } /* ** Table drag and drop. */ .draggable a.tabledrag-handle { cursor: move; float: left; /* LTR */ height: 1.7em; margin: -0.4em 0 -0.4em -0.5em; /* LTR */ padding: 0.42em 1.5em 0.42em 0.5em; /* LTR */ text-decoration: none; } a.tabledrag-handle:hover { text-decoration: none; } a.tabledrag-handle .handle { margin-top: 4px; height: 13px; width: 13px; background: url(../../misc/draggable.png) no-repeat 0 0; } a.tabledrag-handle-hover .handle { background-position: 0 -20px; } /* ** Teaser splitter */ .joined + .grippie { height: 5px; background-position: center 1px; margin-bottom: -2px; } /* Keeps inner content contained in Opera 9. */ .teaser-checkbox { padding-top: 1px; } div.teaser-button-wrapper { float: right; /* LTR */ padding-right: 5%; /* LTR */ margin: 0; } .teaser-checkbox div.form-item { float: right; /* LTR */ margin: 0 5% 0 0; /* LTR */ padding: 0; } textarea.teaser { display: none; } html.js .no-js { display: none; } /* ** Progressbar styles */ .progress { font-weight: bold; } .progress .bar { background: #fff url(../../misc/progress.gif); border: 1px solid #00375a; height: 1.5em; margin: 0 0.2em; } .progress .filled { background: #0072b9; height: 1em; border-bottom: 0.5em solid #004a73; width: 0%; } .progress .percentage { float: right; /* LTR */ } .progress-disabled { float: left; /* LTR */ } .ahah-progress { float: left; /* LTR */ } .ahah-progress .throbber { width: 15px; height: 15px; margin: 2px; background: transparent url(../../misc/throbber.gif) no-repeat 0px -18px; float: left; /* LTR */ } tr .ahah-progress .throbber { margin: 0 2px; } .ahah-progress-bar { width: 16em; } /* ** Formatting for welcome page */ #first-time strong { display: block; padding: 1.5em 0 .5em; } /* ** To be used with tableselect.js */ tr.selected td { background: #ffc; } /* ** Floating header for tableheader.js */ table.sticky-header { margin-top: 0; background: #fff; } /* ** Installation clean URLs */ #clean-url.install { display: none; } /* ** For anything you want to hide on page load when JS is enabled, so ** that you can use the JS to control visibility and avoid flicker. */ html.js .js-hide { display: none; } /* ** Styles for the system modules page (admin/build/modules) */ #system-modules div.incompatible { font-weight: bold; } /* ** Styles for the system themes page (admin/build/themes) */ #system-themes-form div.incompatible { font-weight: bold; } /* ** Password strength indicator */ span.password-strength { visibility: hidden; } input.password-field { margin-right: 10px; /* LTR */ } div.password-description { padding: 0 2px; margin: 4px 0 0 0; font-size: 0.85em; max-width: 500px; } div.password-description ul { margin-bottom: 0; } .password-parent { margin: 0 0 0 0; } /* ** Password confirmation checker */ input.password-confirm { margin-right: 10px; /* LTR */ } .confirm-parent { margin: 5px 0 0 0; } span.password-confirm { visibility: hidden; } span.password-confirm span { font-weight: normal; } rocq-9.2.0/doc/common/styles/html/coqremote/modules/user/000077500000000000000000000000001516144147600234475ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/coqremote/modules/user/user.css000066400000000000000000000020531516144147600251370ustar00rootroot00000000000000 #permissions td.module { font-weight: bold; } #permissions td.permission { padding-left: 1.5em; /* LTR */ } #access-rules .access-type, #access-rules .rule-type { margin-right: 1em; /* LTR */ float: left; /* LTR */ } #access-rules .access-type .form-item, #access-rules .rule-type .form-item { margin-top: 0; } #access-rules .mask { clear: both; } #user-login-form { text-align: center; } #user-admin-filter ul { list-style-type: none; padding: 0; margin: 0; width: 100%; } #user-admin-buttons { float: left; /* LTR */ margin-left: 0.5em; /* LTR */ clear: right; /* LTR */ } #user-admin-settings fieldset .description { font-size: 0.85em; padding-bottom: .5em; } /* Generated by user.module but used by profile.module: */ .profile { clear: both; margin: 1em 0; } .profile .picture { float: right; /* LTR */ margin: 0 1em 1em 0; /* LTR */ } .profile h3 { border-bottom: 1px solid #ccc; } .profile dl { margin: 0 0 1.5em 0; } .profile dt { margin: 0 0 0.2em 0; font-weight: bold; } .profile dd { margin: 0 0 1em 0; } rocq-9.2.0/doc/common/styles/html/coqremote/styles.hva000066400000000000000000000047561516144147600230600ustar00rootroot00000000000000\renewcommand{\@meta}{ \begin{rawhtml} \end{rawhtml}} % for HeVeA \htmlhead{\begin{rawhtml} \end{rawhtml}} rocq-9.2.0/doc/common/styles/html/simple/000077500000000000000000000000001516144147600203145ustar00rootroot00000000000000rocq-9.2.0/doc/common/styles/html/simple/cover.html000066400000000000000000000033141516144147600223210ustar00rootroot00000000000000 Reference Manual | The Coq Proof Assistant

Reference Manual

Version COQVERSION


The Coq Development Team




Copyright Β© 1999-2019, Inria, CNRS and contributors

This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub). Options A and B are not elected.

rocq-9.2.0/doc/common/styles/html/simple/footer.html000066400000000000000000000000201516144147600224700ustar00rootroot00000000000000 rocq-9.2.0/doc/common/styles/html/simple/header.html000066400000000000000000000005721516144147600224360ustar00rootroot00000000000000 The Coq Core Library rocq-9.2.0/doc/common/styles/html/simple/hevea.css000066400000000000000000000034461516144147600221250ustar00rootroot00000000000000 .li-itemize{margin:1ex 0ex;} .li-enumerate{margin:1ex 0ex;} .dd-description{margin:0ex 0ex 1ex 4ex;} .dt-description{margin:0ex;} .toc{list-style:none;} .thefootnotes{text-align:left;margin:0ex;} .dt-thefootnotes{margin:0em;} .dd-thefootnotes{margin:0em 0em 0em 2em;} .footnoterule{margin:1em auto 1em 0px;width:50%;} .caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto} .title{margin:2ex auto;text-align:center} .center{text-align:center;margin-left:auto;margin-right:auto;} .flushleft{text-align:left;margin-left:0ex;margin-right:auto;} .flushright{text-align:right;margin-left:auto;margin-right:0ex;} DIV TABLE{margin-left:inherit;margin-right:inherit;} PRE{text-align:left;margin-left:0ex;margin-right:auto;} BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;} TD P{margin:0px;} .boxed{border:1px solid black} .textboxed{border:1px solid black} .vbar{border:none;width:2px;background-color:black;} .hbar{border:none;height:2px;width:100%;background-color:black;} .hfill{border:none;height:1px;width:200%;background-color:black;} .vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;} .vdcell{white-space:nowrap;padding:0px;width:auto; border:2px solid green;} .display{border-collapse:separate;border-spacing:2px;width:auto; border:none;} .dcell{white-space:nowrap;padding:0px;width:auto; border:none;} .dcenter{margin:0ex auto;} .vdcenter{border:solid #FF8000 2px; margin:0ex auto;} .minipage{text-align:left; margin-left:0em; margin-right:auto;} .marginpar{border:solid thin black; width:20%; text-align:left;} .marginparleft{float:left; margin-left:0ex; margin-right:1ex;} .marginparright{float:right; margin-left:1ex; margin-right:0ex;} .theorem{text-align:left;margin:1ex auto 1ex 0ex;} .part{margin:2ex auto;text-align:center} rocq-9.2.0/doc/common/styles/html/simple/style.css000066400000000000000000000003061516144147600221650ustar00rootroot00000000000000#footer { border-top: solid black 1pt; text-align: center; text-indent: 0pt; } .menu { } .menu li { display: inline; margin: 0pt; padding: .5ex 1em; list-style: none } rocq-9.2.0/doc/common/styles/html/simple/styles.hva000066400000000000000000000017351516144147600223450ustar00rootroot00000000000000\renewcommand{\@meta}{ \begin{rawhtml} \end{rawhtml}} % for HeVeA \htmlhead{\begin{rawhtml}
\end{rawhtml}} rocq-9.2.0/doc/common/title.tex000066400000000000000000000026611516144147600164040ustar00rootroot00000000000000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % File title.tex % Page formatting commands % Macro \coverpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %\setlength{\marginparwidth}{0pt} %\setlength{\oddsidemargin}{0pt} %\setlength{\evensidemargin}{0pt} %\setlength{\marginparsep}{0pt} %\setlength{\topmargin}{0pt} %\setlength{\textwidth}{16.9cm} %\setlength{\textheight}{22cm} %\usepackage{fullpage} %\newcommand{\printingdate}{\today} %\newcommand{\isdraft}{\Large\bf\today\\[20pt]} %\newcommand{\isdraft}{\vspace{20pt}} \newcommand{\coverpage}[3]{ \thispagestyle{empty} \begin{center} \bfseries % for the rest of this page, until \end{center} \Huge The Coq Proof Assistant\\[12pt] #1\\[20pt] \Large\today\\[20pt] Version \coqversion\footnote[1]{This research was partly supported by IST working group ``Types''} \vspace{0pt plus .5fill} #2 \par\vfill $\pi r^2$ Project (formerly LogiCal, then TypiCal) \vspace*{15pt} \end{center} \newpage \thispagestyle{empty} \hbox{}\vfill % without \hbox \vfill does not work at the top of the page \begin{flushleft} %BEGIN LATEX V\coqversion, \today \par\vspace{20pt} %END LATEX \copyright 1999-2019, Inria, CNRS and contributors #3 \end{flushleft} } % end of \coverpage definition % \newcommand{\shorttitle}[1]{ % \begin{center} % \begin{huge} % \begin{bf} % The Coq Proof Assistant\\ % \vspace{10pt} % #1\\ % \end{bf} % \end{huge} % \end{center} % \vspace{5pt} % } % Local Variables: % mode: LaTeX % TeX-master: "" % End: rocq-9.2.0/doc/corelib/000077500000000000000000000000001516144147600146635ustar00rootroot00000000000000rocq-9.2.0/doc/corelib/Library.tex000066400000000000000000000043371516144147600170200ustar00rootroot00000000000000\documentclass[11pt]{report} \usepackage[mathletters]{ucs} \usepackage[utf8x]{inputenc} \usepackage[T1]{fontenc} \usepackage{fullpage} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{url} \usepackage[color]{../../lib/rocq-runtime/tools/coqdoc/coqdoc} \input{../common/version} \input{../common/title} \input{../common/macros} \begin{document} \coverpage{The standard library}% {\ } {This material is distributed under the terms of the GNU Lesser General Public License Version 2.1.} \tableofcontents \newpage % \section*{The \Coq\ standard library} This document is a short description of the \Coq\ standard library. This library comes with the system as a complement of the core library (the {\bf Init} library ; see the Reference Manual for a description of this library). It provides a set of modules directly available through the \verb!Require! command. The standard library is composed of the following subdirectories: \begin{description} \item[Logic] Classical logic and dependent equality \item[Bool] Booleans (basic functions and results) \item[Arith] Basic Peano arithmetic \item[ZArith] Basic integer arithmetic \item[Reals] Classical Real Numbers and Analysis \item[Lists] Monomorphic and polymorphic lists (basic functions and results), Streams (infinite sequences defined with co-inductive types) \item[Sets] Sets (classical, constructive, finite, infinite, power set, etc.) \item[Relations] Relations (definitions and basic results). \item[Sorting] Sorted list (basic definitions and heapsort correctness). \item[Wellfounded] Well-founded relations (basic results). \item[Program] Tactics to deal with dependently-typed programs and their proofs. \item[Classes] Standard type class instances on relations and Coq part of the setoid rewriting tactic. \end{description} Each of these subdirectories contains a set of modules, whose specifications (\gallina{} files) have been roughly, and automatically, pasted in the following pages. There is also a version of this document in HTML format on the WWW, which you can access from the \Coq\ home page at \texttt{http://coq.inria.fr/library}. \input{Library.coqdoc} \end{document} rocq-9.2.0/doc/corelib/dune000066400000000000000000000027161516144147600155470ustar00rootroot00000000000000; This is an ad-hoc rule to ease the migration, it should be handled ; natively by Dune in the future. (rule (targets index-list.html) (deps make-library-index index-list.html.template hidden-files (source_tree %{project_root}/theories) (source_tree %{project_root}/user-contrib)) (action (chdir %{project_root} ; On windows run will fail (bash "doc/corelib/make-library-index doc/corelib/index-list.html doc/corelib/hidden-files")))) (rule (targets (dir html)) (alias corelib-html) (deps ; This will be replaced soon by `theories/**/*.v` soon, thanks to rgrinberg (source_tree %{project_root}/theories) (source_tree %{project_root}/user-contrib) (:header %{project_root}/doc/common/styles/html/coqremote/header.html) (:footer %{project_root}/doc/common/styles/html/coqremote/footer.html) ; For .glob files, should be gone when Coq Dune is smarter. (package rocq-runtime) (package coq-core) (package rocq-core)) (action (progn (run mkdir -p html) (bash "%{bin:coqdoc} -q -d html --with-header %{header} --with-footer %{footer} --multi-index --html -g -R %{project_root}/theories/Corelib Corelib -Q %{project_root}/theories/Ltac2 Ltac2 $(find %{project_root}/theories -name *.v)") (run mv html/index.html html/genindex.html) (with-stdout-to _index.html (progn (bash "sed 's/@@TITLE@@/Table of contents/' %{header}") (cat index-list.html) (cat %{footer}))) (run cp _index.html html/index.html)))) rocq-9.2.0/doc/corelib/hidden-files000066400000000000000000000003471516144147600171450ustar00rootroot00000000000000theories/Corelib/derive/Derive.v theories/Corelib/ssr/ssrsetoid.v theories/Corelib/ssr/ssrunder.v theories/Corelib/extraction/Extraction.v theories/Corelib/extraction/ExtrHaskellBasic.v theories/Corelib/extraction/ExtrOcamlBasic.v rocq-9.2.0/doc/corelib/index-list.html.template000066400000000000000000000126621516144147600214520ustar00rootroot00000000000000

The Core Library

Here is a short description of the core library, which is distributed with the system. It provides a set of modules directly available through the Require Import command.

The core library is composed of the following subdirectories:

Init: The prelude (automatically loaded when starting Coq)
theories/Corelib/Init/Ltac.v theories/Corelib/Init/Notations.v theories/Corelib/Init/Equality.v theories/Corelib/Init/Datatypes.v theories/Corelib/Init/Logic.v theories/Corelib/Init/Byte.v theories/Corelib/Init/Nat.v theories/Corelib/Init/Decimal.v theories/Corelib/Init/Hexadecimal.v theories/Corelib/Init/Number.v theories/Corelib/Init/Peano.v theories/Corelib/Init/Specif.v theories/Corelib/Init/Sumbool.v theories/Corelib/Init/Tactics.v theories/Corelib/Init/Tauto.v theories/Corelib/Init/Wf.v (theories/Corelib/Init/Prelude.v)
Binary numbers: Basic definitions of binary arithmetic
theories/Corelib/Numbers/BinNums.v theories/Corelib/BinNums/PosDef.v theories/Corelib/BinNums/NatDef.v theories/Corelib/BinNums/IntDef.v
Cyclic: 63-bits-based cyclic arithmetic
theories/Corelib/Numbers/Cyclic/Int63/CarryType.v theories/Corelib/Numbers/Cyclic/Int63/PrimInt63.v theories/Corelib/Numbers/Cyclic/Int63/Uint63Axioms.v theories/Corelib/Numbers/Cyclic/Int63/Sint63Axioms.v
Floats: Floating-point arithmetic
theories/Corelib/Floats/FloatClass.v theories/Corelib/Floats/PrimFloat.v theories/Corelib/Floats/SpecFloat.v theories/Corelib/Floats/FloatOps.v theories/Corelib/Floats/FloatAxioms.v
Relations: Relations (definitions)
theories/Corelib/Relations/Relation_Definitions.v
Classes:
theories/Corelib/Classes/Init.v theories/Corelib/Classes/RelationClasses.v theories/Corelib/Classes/Morphisms.v theories/Corelib/Classes/Morphisms_Prop.v theories/Corelib/Classes/Equivalence.v theories/Corelib/Classes/CRelationClasses.v theories/Corelib/Classes/CMorphisms.v theories/Corelib/Classes/SetoidTactics.v
Setoids:
theories/Corelib/Setoids/Setoid.v
Lists: Polymorphic lists
theories/Corelib/Lists/ListDef.v
Program: Support for dependently-typed programming
theories/Corelib/Program/Basics.v theories/Corelib/Program/Wf.v theories/Corelib/Program/Tactics.v theories/Corelib/Program/Utils.v
SSReflect: Base libraries for the SSReflect proof language and the small scale reflection formalization technique
theories/Corelib/ssrmatching/ssrmatching.v theories/Corelib/ssr/ssrclasses.v theories/Corelib/ssr/ssreflect.v theories/Corelib/ssr/ssrbool.v theories/Corelib/ssr/ssrfun.v
Ltac2: The Ltac2 tactic programming language
theories/Ltac2/Ltac2.v theories/Ltac2/Array.v theories/Ltac2/Bool.v theories/Ltac2/Char.v theories/Ltac2/Constant.v theories/Ltac2/Constr.v theories/Ltac2/Constructor.v theories/Ltac2/Control.v theories/Ltac2/Env.v theories/Ltac2/Evar.v theories/Ltac2/Float.v theories/Ltac2/FMap.v theories/Ltac2/FSet.v theories/Ltac2/Fresh.v theories/Ltac2/Ident.v theories/Ltac2/Ind.v theories/Ltac2/Init.v theories/Ltac2/Int.v theories/Ltac2/Lazy.v theories/Ltac2/List.v theories/Ltac2/Ltac1.v theories/Ltac2/Ltac1CompatNotations.v theories/Ltac2/Message.v theories/Ltac2/Meta.v theories/Ltac2/Module.v theories/Ltac2/Notations.v theories/Ltac2/Option.v theories/Ltac2/Pattern.v theories/Ltac2/Printf.v theories/Ltac2/Proj.v theories/Ltac2/Pstring.v theories/Ltac2/RedFlags.v theories/Ltac2/Ref.v theories/Ltac2/Reference.v theories/Ltac2/Rewrite.v theories/Ltac2/Std.v theories/Ltac2/String.v theories/Ltac2/TransparentState.v theories/Ltac2/Uint63.v theories/Ltac2/Unification.v
Compat: Compatibility wrappers for previous versions of Coq
theories/Corelib/Compat/Coq818.v theories/Corelib/Compat/Coq819.v theories/Corelib/Compat/Coq820.v theories/Corelib/Compat/Rocq90.v theories/Corelib/Compat/Rocq91.v theories/Ltac2/Compat/Coq818.v theories/Ltac2/Compat/Coq819.v
Array: Persistent native arrays
theories/Corelib/Array/PrimArray.v theories/Corelib/Array/ArrayAxioms.v
Primitive strings: Native string type
theories/Corelib/Strings/PrimString.v theories/Corelib/Strings/PrimStringAxioms.v
rocq-9.2.0/doc/corelib/make-library-index000077500000000000000000000025301516144147600202750ustar00rootroot00000000000000#!/usr/bin/env bash # Instantiate links to library files in index template set -e FILE=$1 HIDDEN=$2 tmp=$(mktemp) tmp2=$(mktemp) cp -f "$FILE.template" "$tmp" echo -n "Building file index-list.prehtml... " LIBDIRS=$(find theories -type d ! -name .coq-native) missing= for k in $LIBDIRS; do d=$(basename "$k") p=$(echo "$k" | sed 's:^[^/]*/::' | sed 's:/:.:g') for j in "$k"/*.v; do if ! [ -e "$j" ]; then break; fi b=$(basename "$j" .v) a=0; grep -q "$k/$b.v" "$tmp" || a=$? h=0; grep -q "$k/$b.v" "$HIDDEN" || h=$? if [ $a = 0 ]; then if [ $h = 0 ]; then echo "Error: $FILE and $HIDDEN both mention $k/$b.v" >&2 exit 1 else sed -e "s:$k/$b.v:$b:g" "$tmp" > "$tmp2" mv -f "$tmp2" "$tmp" fi else if [ $h = 0 ]; then # Skipping file from the index : else missing="$missing $k/$b.v" fi fi done sed -e "s/#$d#//" "$tmp" > "$tmp2" mv -f "$tmp2" "$tmp" done if [ "$missing" ]; then echo "Error: none of $FILE and $HIDDEN mention$missing" >&2 exit 1 fi if a=$(grep theories "$tmp"); then echo Error: extra files: >&2; echo "$a" >&2; exit 1; fi mv "$tmp" "$FILE" echo Done rocq-9.2.0/doc/dune000066400000000000000000000020641516144147600141240ustar00rootroot00000000000000(rule (targets unreleased.rst) (deps (source_tree changelog)) (action (with-stdout-to %{targets} (bash "cat changelog/00-title.rst changelog/*/*.rst")))) (alias (name refman-deps) (deps ; We could use finer dependencies here so the build is faster: ; ; - vo files: generated by sphinx after parsing the doc, promoted, ; - Static files: ; + %{bin:coqdoc} etc... ; + config/coq_config.py ; + tools/coqdoc/coqdoc.css (package rocq-runtime) (package rocq-core) (source_tree sphinx) (source_tree tools/rocqrst) ../config/coq_config.py unreleased.rst (env_var SPHINXWARNOPT) (env_var ROCQRST_EXTRA))) (rule (targets (dir refman-html)) (alias refman-html) (deps (alias refman-deps)) (action (run env sphinx-build -q %{env:SPHINXWARNOPT=-W} -b html sphinx %{targets}))) (rule (targets (dir refman-pdf)) (alias refman-pdf) (deps ../ide/rocqide/coq.png (alias refman-deps)) (action (progn (run env sphinx-build -q %{env:SPHINXWARNOPT=-W} -b latex sphinx %{targets}) (chdir %{targets} (run make LATEXMKOPTS=-silent))))) rocq-9.2.0/doc/index.mld000066400000000000000000000001661516144147600150540ustar00rootroot00000000000000{0 rocq-doc } The rocq-doc package only contains user documentation on the Coq proof assistant and no OCaml library. rocq-9.2.0/doc/plugin_tutorial/000077500000000000000000000000001516144147600164655ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/LICENSE000066400000000000000000000022721516144147600174750ustar00rootroot00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to rocq-9.2.0/doc/plugin_tutorial/Makefile000066400000000000000000000003571516144147600201320ustar00rootroot00000000000000 TUTOS:= \ tuto0 \ tuto1 \ tuto2 \ tuto3 \ tuto4 all: $(TUTOS) .PHONY: $(TUTOS) all $(TUTOS): %: +$(MAKE) -C $@ CLEANS:=$(addsuffix -clean, $(TUTOS)) .PHONY: clean $(CLEANS) clean: $(CLEANS) %-clean: +$(MAKE) -C $* clean rocq-9.2.0/doc/plugin_tutorial/README.md000066400000000000000000000116101516144147600177430ustar00rootroot00000000000000How to write plugins in Rocq =========================== This document describes how to extend Rocq by writing plugins in the [OCaml](https://ocaml.org/) functional programming language. Before writing a plugin, you should consider whether easier approaches can achieve your goal. It is often easier to use an extension language such as Ltac2 or Elpi. Ltac2 is documented in the [refman](https://rocq-prover.org/refman/proof-engine/ltac2.html) and Elpi comes with excellent [tutorials](https://github.com/LPCIC/coq-elpi/#tutorials). Plugin development is harder due to the lower level OCaml API it uses. It is also more maintenance intensive because the OCaml API can change from release to release without any backward compatibility (it's not uncommon for plugins to only work with a given version of Rocq). # Working environment In addition to installing OCaml and Rocq, you need to make sure that you also have the development headers for Rocq, because you will need them to compile extensions. If you installed Rocq from source or from [OPAM](http://opam.ocaml.org/doc/Install.html), you already have the required headers. If you installed them from your system package manager, there may be a separate package which contains the development headers (for example, in Ubuntu they are contained in the package `libcoq-ocaml-dev`). It can help to install several tools for development. ## Tuareg and Merlin These instructions use [OPAM](http://opam.ocaml.org/doc/Install.html) ```shell opam install merlin # prints instructions for vim and emacs opam install tuareg # syntax highlighting for OCaml opam user-setup install # automatically configures editors for merlin ``` Adding this line to your .emacs helps Tuareg recognize the .mlg extension: ```shell (add-to-list 'auto-mode-alist '("\\.mlg$" . tuareg-mode) t) ``` If you are using [vscoq](https://github.com/coq-community/vscoq), you will need to ensure that vscoq loads the `_CoqProject` file for the extension you are working on. You can do this by opening Visual Studio Code with the `_CoqProject` file in the project root directory, or by editing the `coqtop.coqProjectRoot` setting for vscoq. ## This tutorial ```shell cd plugin_tutorials/tuto0 make .merlin # run before opening .ml files in your editor make # build ``` # tuto0 : basics of project organization package an mlg file in a plugin, organize a `Makefile`, `_CoqProject` (note comments in those files) - Example of syntax to add a new toplevel command - Example of function call to print a simple message - Example of function call to print a simple warning - Example of function call to raise a simple error to the user - Example of syntax to add a simple tactic (that does nothing and prints a message) - To use it: ```bash cd tuto0; make rocq top -I src -R theories Tuto0 ``` In the Rocq session type: ```coq Require Import Tuto0.Loader. HelloWorld. ``` You can also modify and run `theories/Demo.v`. Because the `.mlpack` file format does not support comments, we explain it here: this file is used by `rocq makefile` to compile the plugin. It lists the OCaml modules used in the plugin in dependency order. From `foo.mlpack`, `rocq makefile` will build `foo.cma` (bytecode plugin) and `foo.cmxs` (native plugin), so the file names in the `META` file must match this. # tuto1 : OCaml to Rocq communication Explore the memory of Rocq, modify it - Commands that take arguments: strings, integers, symbols, expressions of the calculus of constructions - Examples of using environments correctly - Examples of using state (the evar_map) correctly - Commands that interact with type-checking in Rocq - A command that checks convertibility between two terms - A command that adds a new definition or theorem - A command that uses a name and exploits the existing definitions or theorems - A command that exploits an existing ongoing proof - A command that defines a new tactic Compilation and loading must be performed as for `tuto0`. # tuto2 : OCaml to Rocq communication A more step by step introduction to writing commands - Explanation of the syntax of entries - Adding a new type to and parsing to the available choices - Handling commands that store information in user-chosen registers and tables Compilation and loading must be performed as for `tuto0`. # tuto3 : manipulating terms of the calculus of constructions Manipulating terms, inside commands and tactics. - Obtaining existing values from memory - Composing values - Verifying types - Using these terms in commands - Using these terms in tactics - Automatic proofs without tactics using type classes and canonical structures Compilation and loading must be performed as for `tuto0`. # tuto4: extending Ltac2 Define new primitives ("externals") for Ltac2. Note that in this case we have no `.mlg` file, but the `Loader.v` is less trivial. Compilation and loading must be performed as for `tuto0`. rocq-9.2.0/doc/plugin_tutorial/dune000066400000000000000000000005021516144147600173400ustar00rootroot00000000000000; We get a super bizarre error here... ; (rule ; (alias plugin-tutorial) ; (deps ; (source_tree .) ; (package rocq-runtime) ; ../../tools/CoqMakefile.in ; ../../theories/Init/Prelude.vo) ; (action ; (bash "make ROCQRUNTIMELIB=$(pwd)/../../ ROCQLIB=$(pwd)/../../"))) (env (dev (flags :standard -w -70))) rocq-9.2.0/doc/plugin_tutorial/tuto0/000077500000000000000000000000001516144147600175405ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto0/Makefile000066400000000000000000000010461516144147600212010ustar00rootroot00000000000000# define COQBIN to the empty string if it's not already defined # (in case we want to run make with --warn-undefined-variables) COQBIN?= # all unknown targets depend on the generated Rocq makefile %: Makefile.rocq # rule to generate the Rocq makefile Makefile.rocq: _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o Makefile.rocq # use the generated Rocq makefile # -include instead of include: don't error if it's not there # (IIRC some version of make doesn't realize that it should be built if we don't use -include) -include Makefile.rocq rocq-9.2.0/doc/plugin_tutorial/tuto0/_CoqProject000066400000000000000000000015711516144147600216770ustar00rootroot00000000000000# Comments in _CoqProject start with # and end with newline # .v files in theories/ are modules whose name starts with "Tuto0" -R theories/ Tuto0 # META (an ocamlfind library specification) is necessary for rocq to find the plugin # in tuto0 we use rocq makefile's "-generate-meta-for-package" # it assumes that the plugin is called rocq-plugin-tutorial.plugin # and depends on ltac1 (rocq-runtime.plugins.ltac) # see tuto1 for an example of a custom META file -generate-meta-for-package rocq-plugin-tutorial # rocq makefile uses -I to tell the ocaml compiler where previously compiled files are located # (in our case g_tuto0 depends on tuto0_main) -I src # list our .v files theories/Loader.v theories/Demo.v # list our ocaml files src/tuto0_main.ml src/tuto0_main.mli src/g_tuto0.mlg # mlpack is a "rocq makefile" specific file # cf plugin tutorial README src/tuto0_plugin.mlpack rocq-9.2.0/doc/plugin_tutorial/tuto0/src/000077500000000000000000000000001516144147600203275ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto0/src/dune000066400000000000000000000003531516144147600212060ustar00rootroot00000000000000(library (name tuto0_plugin) (public_name rocq-runtime.plugins.tutorial.p0) (libraries rocq-runtime.plugins.ltac)) (rule (targets g_tuto0.ml) (deps (:mlg g_tuto0.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/doc/plugin_tutorial/tuto0/src/g_tuto0.mlg000066400000000000000000000032641516144147600224160ustar00rootroot00000000000000(** See dev/doc/parsing.md for mlg doc *) DECLARE PLUGIN "rocq-plugin-tutorial.plugin" { open Pp open Ltac_plugin let cat = CWarnings.create_category ~name:"plugin-tuto-cat" () let tuto_warn = CWarnings.create ~name:"name" ~category:cat (fun () -> strbrk Tuto0_main.message) } (*** Printing messages ***) (* * This defines a command that prints HelloWorld. * Note that Feedback.msg_notice can be used to print messages. *) VERNAC COMMAND EXTEND HelloWorld CLASSIFIED AS QUERY | [ "HelloWorld" ] -> { Feedback.msg_notice (strbrk Tuto0_main.message) } END (* * This is a tactic version of the same thing. *) TACTIC EXTEND hello_world_tactic | [ "hello_world" ] -> { let () = Feedback.msg_notice (str Tuto0_main.message) in Tacticals.tclIDTAC } END (*** Printing warnings ***) (* * This defines a command that prints HelloWorld as a warning. * tuto_warn is defined at the top-level, before the command runs, * which is standard. *) VERNAC COMMAND EXTEND HelloWarning CLASSIFIED AS QUERY | [ "HelloWarning" ] -> { tuto_warn () } END (* * This is a tactic version of the same thing. *) TACTIC EXTEND hello_warning_tactic | [ "hello_warning" ] -> { let () = tuto_warn () in Tacticals.tclIDTAC } END (*** Printing errors ***) (* * This defines a command that prints HelloWorld inside of an error. * Note that CErrors.user_err can be used to raise errors to the user. *) VERNAC COMMAND EXTEND HelloError CLASSIFIED AS QUERY | [ "HelloError" ] -> { CErrors.user_err (str Tuto0_main.message) } END (* * This is a tactic version of the same thing. *) TACTIC EXTEND hello_error_tactic | [ "hello_error" ] -> { CErrors.user_err (str Tuto0_main.message) } END rocq-9.2.0/doc/plugin_tutorial/tuto0/src/tuto0_main.ml000066400000000000000000000000351516144147600227360ustar00rootroot00000000000000let message = "Hello world!" rocq-9.2.0/doc/plugin_tutorial/tuto0/src/tuto0_main.mli000066400000000000000000000000251516144147600231060ustar00rootroot00000000000000val message : string rocq-9.2.0/doc/plugin_tutorial/tuto0/src/tuto0_plugin.mlpack000066400000000000000000000000231516144147600241440ustar00rootroot00000000000000Tuto0_main G_tuto0 rocq-9.2.0/doc/plugin_tutorial/tuto0/theories/000077500000000000000000000000001516144147600213625ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto0/theories/Demo.v000066400000000000000000000004721516144147600224400ustar00rootroot00000000000000From Tuto0 Require Import Loader. (*** Printing messages ***) HelloWorld. Lemma test : True. Proof. hello_world. Abort. (*** Printing warnings ***) HelloWarning. Lemma test : True. Proof. hello_warning. Abort. (*** Signaling errors ***) Fail HelloError. Lemma test : True. Proof. Fail hello_error. Abort. rocq-9.2.0/doc/plugin_tutorial/tuto0/theories/Loader.v000066400000000000000000000000611516144147600227540ustar00rootroot00000000000000Declare ML Module "rocq-plugin-tutorial.plugin". rocq-9.2.0/doc/plugin_tutorial/tuto1/000077500000000000000000000000001516144147600175415ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto1/META.rocq-plugin-tutorial000066400000000000000000000020401516144147600243060ustar00rootroot00000000000000# Comments in META start with # and end with newline # our plugin is called rocq-plugin-tutorial.tuto1 # rocq-plugin-tutorial from the META filename # tuto1 from this "package" name package "tuto1" ( # the plugin files are in "src" directory = "src" version = "dev" description = "A tuto1 plugin" # we define ltac1 tactics so we depend on ltac # otherwise we would depend only on rocq-runtime.vernac # (it contains the APIs for declaring new commands) # (ltac depends on vernac so if we depend on ltac, vernac is also implicitly depended on) requires = "rocq-runtime.plugins.ltac" # the compiled plugin files (rocq makefile bases these filenames on the .mlpack filename) # (only the "plugin" keys are used by rocq, # "archive" is for packages which depend on this package) archive(byte) = "tuto1_plugin.cma" archive(native) = "tuto1_plugin.cmxa" plugin(byte) = "tuto1_plugin.cma" plugin(native) = "tuto1_plugin.cmxs" ) # paths in this file are relative to this directory directory = "." rocq-9.2.0/doc/plugin_tutorial/tuto1/Makefile000066400000000000000000000002071516144147600212000ustar00rootroot00000000000000COQBIN?= %: Makefile.rocq Makefile.rocq: _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o Makefile.rocq -include Makefile.rocq rocq-9.2.0/doc/plugin_tutorial/tuto1/_CoqProject000066400000000000000000000011311516144147600216700ustar00rootroot00000000000000META.rocq-plugin-tutorial -R theories Tuto1 # rocq makefile uses -I in 2 ways: # to tell rocq where the META file is located -I . # and to tell the ocaml compiler where previously compiled files are located # (eg g_tuto1 depends on inspector) -I src # in tuto0 with -generate-meta-for-package, the META was generated next to the mlpack # so -I src did both jobs theories/Loader.v theories/Demo.v src/inspector.mli src/inspector.ml src/simple_check.mli src/simple_check.ml src/simple_declare.mli src/simple_declare.ml src/simple_print.ml src/simple_print.mli src/g_tuto1.mlg src/tuto1_plugin.mlpack rocq-9.2.0/doc/plugin_tutorial/tuto1/src/000077500000000000000000000000001516144147600203305ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto1/src/dune000066400000000000000000000003531516144147600212070ustar00rootroot00000000000000(library (name tuto1_plugin) (public_name rocq-runtime.plugins.tutorial.p1) (libraries rocq-runtime.plugins.ltac)) (rule (targets g_tuto1.ml) (deps (:mlg g_tuto1.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/doc/plugin_tutorial/tuto1/src/g_tuto1.mlg000066400000000000000000000261001516144147600224120ustar00rootroot00000000000000(** See dev/doc/parsing.md for mlg doc *) DECLARE PLUGIN "rocq-plugin-tutorial.tuto1" { (* If we forget this line and include our own tactic definition using TACTIC EXTEND, as below, then we get the strange error message no implementation available for Tacentries, only when compiling theories/Loader.v *) open Ltac_plugin open Pp (* This module defines the types of arguments to be used in the EXTEND directives below, for example the string one. *) open Stdarg } (*** Printing inputs ***) (* * This command prints an input from the user. * * A list with allowable inputs can be found in tactics/stdarg.mli, * plugin/ltac/extraargs.mli, and plugin/ssr/ssrparser.mli * (remove the wit_ prefix), but not all of these are allowable * (unit and bool, for example, are not usable from within here). * * We include only some examples that are standard and useful for commands. * Some of the omitted examples are useful for tactics. * * Inspector is our own file that defines a simple messaging function. * The printing functions (pr_qualid and so on) are in printing. * * Some of these cases would be ambiguous if we used "What's" for each of * these. For example, all of these are terms. We purposely disambiguate. *) VERNAC COMMAND EXTEND WhatIsThis CLASSIFIED AS QUERY | [ "What's" constr(e) ] -> { let env = Global.env () in (* we'll explain later *) let sigma = Evd.from_env env in (* we'll explain later *) (* current Printing settings (specifically the ones applicable to printing constr_expr) *) let flags = Ppconstr.current_flags() in Inspector.print_input e (Ppconstr.pr_constr_expr ~flags env sigma) "term" } | [ "What" "kind" "of" "term" "is" string(s) ] -> { Inspector.print_input s strbrk "string" } | [ "What" "kind" "of" "term" "is" int(i) ] -> { Inspector.print_input i Pp.int "int" } | [ "What" "kind" "of" "term" "is" ident(id) ] -> { Inspector.print_input id Ppconstr.pr_id "identifier" } | [ "What" "kind" "of" "identifier" "is" reference(r) ] -> { Inspector.print_input r Ppconstr.pr_qualid "reference" } END (* * This command demonstrates basic combinators built into the DSL here. * You can generalize this for constr_list, constr_opt, int_list, and so on. *) VERNAC COMMAND EXTEND WhatAreThese CLASSIFIED AS QUERY | [ "What" "is" int_list(l) "a" "list" "of" ] -> { let print l = str "[" ++ Pp.prlist_with_sep (fun () -> str ";") Pp.int l ++ str "]" in Inspector.print_input l print "int list" } | [ "Is" ne_int_list(l) "nonempty" ] -> { let print l = str "[" ++ Pp.prlist_with_sep (fun () -> str ";") Pp.int l ++ str "]" in Inspector.print_input l print "nonempty int list" } | [ "And" "is" int_opt(o) "provided" ] -> { let print o = strbrk (if Option.has_some o then "Yes" else "No") in Feedback.msg_notice (print o) } END (*** Interning terms ***) (* * The next step is to make something of parsed expression. * Interesting information in interp/constrintern.mli. * * When you read in constr(e), e will have type Constrexpr.constr_expr, * which is defined in pretyping/constrexpr.ml. Your plugin * will want a different representation. * * The important function is Constrintern.interp_constr_evars, * which converts between a constr_expr and an * (EConstr.constr, evar_map) pair. This essentially contains * an internal representation of the term along with some state. * For more on the state, read /dev/doc/econstr.md. * * NOTE ON INTERNING: Always prefer Constrintern.interp_constr_evars * over Constrintern.interp_constr. The latter is an internal function * not meant for external use. * * To get your initial environment, call Global.env (). * To get state from that environment, call Evd.from_env on that environment. * It is important to NEVER use the empty environment or Evd.empty; * if you do, you will get confusing errors. * * NOTE ON STATE: It is important to use the evar_map that is returned to you. * Otherwise, you may get cryptic errors later in your plugin. * For example, you may get universe inconsistency errors. * In general, if a function returns an evar_map to you, that's the one * you want to thread through the rest of your command. * * NOTE ON STYLE: In general, it's better practice to move large * chunks of OCaml code like this one into an .ml file. We include * this here because it's really important to understand how to * thread state in a plugin, and it's easier to see that if it's in the * top-level file itself. *) VERNAC COMMAND EXTEND Intern CLASSIFIED AS QUERY | [ "Intern" constr(e) ] -> { let env = Global.env () in (* use this; never use empty *) let sigma = Evd.from_env env in (* use this; never use empty *) let debug sigma = Termops.pr_evar_map ~with_univs:true None env sigma in Feedback.msg_notice (strbrk "State before intern: " ++ debug sigma); let (sigma, t) = Constrintern.interp_constr_evars env sigma e in Feedback.msg_notice (strbrk "State after intern: " ++ debug sigma); let print t = Printer.pr_econstr_env env sigma t in Feedback.msg_notice (strbrk "Interned: " ++ print t) } END (*** Defining terms ***) (* * To define a term, we start similarly to our intern functionality, * then we call another function. We define this function in * the Simple_declare module. * * The line #[ poly = Attributes.poly_def ] says that this command accepts * universe polymorphism attributes for definitions. * @SkySkimmer: Here, poly is what the result is bound to in the * rule's code. Multiple attributes may be used separated by ;, and we have * punning so foo is equivalent to foo = foo. * * The declare_definition function returns the reference * that was defined. This reference will be present in the new environment. * If you want to refer to it later in your plugin, you must use an * updated environment and the constructed reference. * * Note since we are now defining a term, we must classify this * as a side-effect (CLASSIFIED AS SIDEFF). *) VERNAC COMMAND EXTEND MyDefine CLASSIFIED AS SIDEFF | #[ poly = Attributes.poly_def ] [ "MyDefine" ident(i) ":=" constr(e) ] -> { let env = Global.env () in let sigma = Evd.from_env env in let (sigma, t) = Constrintern.interp_constr_evars env sigma e in let r = Simple_declare.declare_definition ~poly i sigma t in let print r = strbrk "Defined " ++ Printer.pr_global r ++ strbrk "." in Feedback.msg_notice (print r) } END (*** Printing terms ***) (* * This command takes a name and return its value. It does less * than Print, because it fails on constructors, axioms, and inductive types. * It signals an error to the user for unsupported terms. * * Simple_print contains simple_body_access, which shows how to look up * a global reference. * * It needs the ability to access the body of opaque constants, which is given by STATE opaque_access. * This makes the expected type of the implementation be * [opaque_access:Global.indirect_accessor -> unit] instead of [unit]. *) VERNAC COMMAND EXTEND ExamplePrint CLASSIFIED AS QUERY STATE opaque_access | [ "MyPrint" reference(r) ] -> { fun ~opaque_access -> let env = Global.env () in let sigma = Evd.from_env env in try let t = Simple_print.simple_body_access ~opaque_access (Nametab.global r) in Feedback.msg_notice (Printer.pr_econstr_env env sigma t) with Failure s -> CErrors.user_err (str s) } END (* * This command shows that after you define a new term, * you can also look it up. But there's a catch! You need to actually * refresh your environment. Otherwise, the defined term * will not be in the environment. * * Using the global reference as opposed to the ID is generally * a good idea, otherwise you might end up running into unforeseen * problems inside of modules and sections and so on. * * Inside of simple_body_access, note that it uses Global.env (), * which refreshes the environment before looking up the term. * * [![opaque_access]] is equivalent to [STATE opaque_access] but is specific to that parsing rule. *) VERNAC COMMAND EXTEND DefineLookup CLASSIFIED AS SIDEFF | #[ poly = Attributes.poly_def ] ![opaque_access] [ "DefineLookup" ident(i) ":=" constr(e) ] -> { fun ~opaque_access -> let env = Global.env () in let sigma = Evd.from_env env in let (sigma, t) = Constrintern.interp_constr_evars env sigma e in let r = Simple_declare.declare_definition ~poly i sigma t in let print r = strbrk "Defined " ++ Printer.pr_global r ++ strbrk "." in Feedback.msg_notice (print r); let env = Global.env () in let sigma = Evd.from_env env in let t = Simple_print.simple_body_access ~opaque_access r in let print t = strbrk "Found " ++ Printer.pr_econstr_env env sigma t in Feedback.msg_notice (print t) } END (*** Checking terms ***) (* * These are two commands for simple type-checking of terms. * The bodies and explanations of the differences are in simple_check.ml. *) VERNAC COMMAND EXTEND Check1 CLASSIFIED AS QUERY | [ "Check1" constr(e) ] -> { let env = Global.env () in let sigma = Evd.from_env env in let (sigma, t) = Constrintern.interp_constr_evars env sigma e in let (sigma, typ) = Simple_check.simple_check1 env sigma t in Feedback.msg_notice (Printer.pr_econstr_env env sigma typ) } END VERNAC COMMAND EXTEND Check2 CLASSIFIED AS QUERY | [ "Check2" constr(e) ] -> { let env = Global.env () in let sigma = Evd.from_env env in let (sigma, t) = Constrintern.interp_constr_evars env sigma e in let typ = Simple_check.simple_check2 env sigma t in Feedback.msg_notice (Printer.pr_econstr_env env sigma typ) } END (*** Convertibility ***) (* * This command checks if there is a possible assignment of * constraints in the state under which the two terms are * convertible. *) VERNAC COMMAND EXTEND Convertible CLASSIFIED AS QUERY | [ "Convertible" constr(e1) constr(e2) ] -> { let env = Global.env () in let sigma = Evd.from_env env in let (sigma, t1) = Constrintern.interp_constr_evars env sigma e1 in let (sigma, t2) = Constrintern.interp_constr_evars env sigma e2 in match Reductionops.infer_conv env sigma t1 t2 with | Some _ -> Feedback.msg_notice (strbrk "Yes :)") | None -> Feedback.msg_notice (strbrk "No :(") } END (*** Introducing terms ***) (* * We can call the tactics defined in Tactics within our tactics. * Here we call intros. *) TACTIC EXTEND my_intro | [ "my_intro" ident(i) ] -> { Tactics.introduction i } END (*** Exploring proof state ***) (* * This command demonstrates exploring the proof state from within * a command. * * Note that Pfedit.get_current_context gets us the environment * and state within a proof, as opposed to the global environment * and state. This is important within tactics. *) VERNAC COMMAND EXTEND ExploreProof CLASSIFIED AS QUERY | ![ proof_query ] [ "ExploreProof" ] -> { fun ~pstate -> let sigma, env = Declare.Proof.get_current_context pstate in let pprf = Proof.partial_proof (Declare.Proof.get pstate) in Feedback.msg_notice (Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf) } END rocq-9.2.0/doc/plugin_tutorial/tuto1/src/inspector.ml000066400000000000000000000004071516144147600226710ustar00rootroot00000000000000open Pp (* * Inspect an input and print a feedback message explaining what it is *) let print_input (a : 'a) (printer : 'a -> Pp.t) (type_str : string) : unit = let msg = printer a ++ strbrk (Printf.sprintf " is a %s." type_str) in Feedback.msg_notice msg rocq-9.2.0/doc/plugin_tutorial/tuto1/src/inspector.mli000066400000000000000000000002051516144147600230360ustar00rootroot00000000000000(* * Inspect an input and print a feedback message explaining what it is *) val print_input : 'a -> ('a -> Pp.t) -> string -> unit rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_check.ml000066400000000000000000000012351516144147600233110ustar00rootroot00000000000000let simple_check1 env sigma evalue = (* This version should be preferred if you want to really verify that the input is well-typed, and if you want to obtain the type. *) (* Note that the output value is a pair containing a new evar_map: typing will fill out blanks in the term by add evar bindings. *) Typing.type_of env sigma evalue let simple_check2 env sigma evalue = (* This version should be preferred if you already expect the input to have been type-checked before. Set ~lax to false if you want an anomaly to be raised in case of a type error. Otherwise a ReTypeError exception is raised. *) Retyping.get_type_of ~lax:true env sigma evalue rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_check.mli000066400000000000000000000002741516144147600234640ustar00rootroot00000000000000val simple_check1 : Environ.env -> Evd.evar_map -> EConstr.constr -> Evd.evar_map * EConstr.constr val simple_check2 : Environ.env -> Evd.evar_map -> EConstr.constr -> EConstr.constr rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_declare.ml000066400000000000000000000003251516144147600236320ustar00rootroot00000000000000let declare_definition ~poly name sigma body = let cinfo = Declare.CInfo.make ~name ~typ:None () in let info = Declare.Info.make ~poly () in Declare.declare_definition ~info ~cinfo ~opaque:false ~body sigma rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_declare.mli000066400000000000000000000001601516144147600240000ustar00rootroot00000000000000open Names val declare_definition : poly:PolyFlags.t -> Id.t -> Evd.evar_map -> EConstr.t -> Names.GlobRef.t rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_print.ml000066400000000000000000000014361516144147600233730ustar00rootroot00000000000000(* A more advanced example of how to explore the structure of terms of type constr is given in the coq-dpdgraph plugin. *) let simple_body_access ~opaque_access gref = let open Names.GlobRef in match gref with | VarRef _ -> failwith "variables are not covered in this example" | IndRef _ -> failwith "inductive types are not covered in this example" | ConstructRef _ -> failwith "constructors are not covered in this example" | ConstRef cst -> let cb = Environ.lookup_constant cst (Global.env()) in (* most commands should not use body_of_constant_body and opaque accessors, but for printing it's ok *) match Global.body_of_constant_body opaque_access cb with | Some(e, _, _) -> EConstr.of_constr e | None -> failwith "This term has no value" rocq-9.2.0/doc/plugin_tutorial/tuto1/src/simple_print.mli000066400000000000000000000001451516144147600235400ustar00rootroot00000000000000val simple_body_access : opaque_access:Global.indirect_accessor -> Names.GlobRef.t -> EConstr.constr rocq-9.2.0/doc/plugin_tutorial/tuto1/src/tuto1_plugin.mlpack000066400000000000000000000000731516144147600241530ustar00rootroot00000000000000Inspector Simple_check Simple_declare Simple_print G_tuto1 rocq-9.2.0/doc/plugin_tutorial/tuto1/theories/000077500000000000000000000000001516144147600213635ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto1/theories/Demo.v000066400000000000000000000034741516144147600224460ustar00rootroot00000000000000From Tuto1 Require Import Loader. (*** Printing user inputs ***) Definition definition := 5. What's definition. What kind of term is definition. What kind of identifier is definition. What is 1 2 3 a list of. What is a list of. (* no arguments = empty list *) Is 1 2 3 nonempty. (* Is nonempty *) (* does not parse *) And is 1 provided. And is provided. (*** Interning terms ***) Intern 3. Intern definition. Intern (fun (x : Prop) => x). Intern (fun (x : Type) => x). Intern (forall (T : Type), T). Intern (fun (T : Type) (t : T) => t). Intern _. Intern (Type : Type). (*** Defining terms ***) MyDefine n := 1. Print n. MyDefine f := (fun (x : Type) => x). Print f. (*** Printing terms ***) MyPrint f. MyPrint n. Fail MyPrint nat. DefineLookup n' := 1. DefineLookup f' := (fun (x : Type) => x). (*** Checking terms ***) Check1 3. Check1 definition. Check1 (fun (x : Prop) => x). Check1 (fun (x : Type) => x). Check1 (forall (T : Type), T). Check1 (fun (T : Type) (t : T) => t). Check1 _. Check1 (Type : Type). Check2 3. Check2 definition. Check2 (fun (x : Prop) => x). Check2 (fun (x : Type) => x). Check2 (forall (T : Type), T). Check2 (fun (T : Type) (t : T) => t). Check2 _. Check2 (Type : Type). (*** Convertibility ***) Convertible 1 1. Convertible (fun (x : Type) => x) (fun (x : Type) => x). Convertible Type Type. Convertible 1 ((fun (x : nat) => x) 1). Convertible 1 2. Convertible (fun (x : Type) => x) (fun (x : Prop) => x). Convertible Type Prop. Convertible 1 ((fun (x : nat) => x) 2). (*** Introducing variables ***) Theorem foo: forall (T : Set) (t : T), T. Proof. my_intro T. my_intro t. apply t. Qed. (*** Exploring proof state ***) Fail ExploreProof. (* not in a proof *) Theorem bar: forall (T : Set) (t : T), T. Proof. ExploreProof. my_intro T. ExploreProof. my_intro t. ExploreProof. apply t. Qed. rocq-9.2.0/doc/plugin_tutorial/tuto1/theories/Loader.v000066400000000000000000000000601516144147600227540ustar00rootroot00000000000000Declare ML Module "rocq-plugin-tutorial.tuto1". rocq-9.2.0/doc/plugin_tutorial/tuto2/000077500000000000000000000000001516144147600175425ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto2/Makefile000066400000000000000000000002071516144147600212010ustar00rootroot00000000000000COQBIN?= %: Makefile.rocq Makefile.rocq: _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o Makefile.rocq -include Makefile.rocq rocq-9.2.0/doc/plugin_tutorial/tuto2/_CoqProject000066400000000000000000000004051516144147600216740ustar00rootroot00000000000000src/META.rocq-plugin-tutorial -R theories Tuto2 -I src theories/Loader.v theories/Demo.v theories/Count.v src/custom.ml src/custom.mli src/counter.ml src/counter.mli src/persistent_counter.ml src/persistent_counter.mli src/g_tuto2.mlg src/tuto2_plugin.mlpack rocq-9.2.0/doc/plugin_tutorial/tuto2/src/000077500000000000000000000000001516144147600203315ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto2/src/META.rocq-plugin-tutorial000066400000000000000000000004721516144147600251050ustar00rootroot00000000000000package "tuto2" ( directory = "." version = "dev" description = "A tuto2 plugin" requires = "rocq-runtime.plugins.ltac" archive(byte) = "tuto2_plugin.cma" archive(native) = "tuto2_plugin.cmxa" plugin(byte) = "tuto2_plugin.cma" plugin(native) = "tuto2_plugin.cmxs" ) directory = "." rocq-9.2.0/doc/plugin_tutorial/tuto2/src/counter.ml000066400000000000000000000006651516144147600223510ustar00rootroot00000000000000(* * This file defines our counter, which we use in the Count command. *) (* * Our counter is simply a reference called "counter" to an integer. * * Summary.ref behaves like ref, but also registers a summary to Coq. *) let counter = Summary.ref ~name:"counter" 0 (* * We can increment our counter: *) let increment () = counter := succ !counter (* * We can also read the value of our counter: *) let value () = !counter rocq-9.2.0/doc/plugin_tutorial/tuto2/src/counter.mli000066400000000000000000000003201516144147600225060ustar00rootroot00000000000000(* * This file defines our counter, which we use in the Count command. *) (* * Increment the counter *) val increment : unit -> unit (* * Determine the value of the counter *) val value : unit -> int rocq-9.2.0/doc/plugin_tutorial/tuto2/src/custom.ml000066400000000000000000000001441516144147600221740ustar00rootroot00000000000000(* * This file defines a custom type for the PassCustom command. *) type custom_type = Foo | Bar rocq-9.2.0/doc/plugin_tutorial/tuto2/src/custom.mli000066400000000000000000000001441516144147600223450ustar00rootroot00000000000000(* * This file defines a custom type for the PassCustom command. *) type custom_type = Foo | Bar rocq-9.2.0/doc/plugin_tutorial/tuto2/src/dune000066400000000000000000000003531516144147600212100ustar00rootroot00000000000000(library (name tuto2_plugin) (public_name rocq-runtime.plugins.tutorial.p2) (libraries rocq-runtime.plugins.ltac)) (rule (targets g_tuto2.ml) (deps (:mlg g_tuto2.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/doc/plugin_tutorial/tuto2/src/g_tuto2.mlg000066400000000000000000000475141516144147600224300ustar00rootroot00000000000000(** See dev/doc/parsing.md for mlg doc *) (* -------------------------------------------------------------------------- *) (* *) (* Initial ritual dance *) (* *) (* -------------------------------------------------------------------------- *) DECLARE PLUGIN "rocq-plugin-tutorial.tuto2" (* Use this macro before any of the other OCaml macros. Each plugin has a unique name made of a package name (here "rocq-plugin-tutorial") followed by an internal plugin name. We have decided to name this plugin as "rocq-plugin-tutorial.tuto2". That means that: (1) We write the following command in a file called Loader.v: Declare ML Module "rocq-plugin-tutorial.tuto2". to load this command into the Coq top-level. (2) Users can then load our plugin in other Coq files by writing: From Tuto2 Require Import Loader. where Loader is the name of the file that declares "rocq-plugin-tutorial.tuto2", and where Tuto2 is the name passed to the -R argument in our _CoqProject. (3) The above commands will succeed only if there is a META.rocq-plugin-tutorial file mapping the name "rocq-plugin-tutorial.tuto2" to an actual "tuto2_plugin.cmxs" file. The META file can be had written and listed in _CoqProject, or generated by coq_makefile using the "-generate-meta-for-package rocq-plugin-tutorial" flag. (4) The file "tuto2_plugin.mlpack" lists the OCaml modules to be linked in "tuto2_plugin.cmxs". (5) The file "tuto2_plugin.mlpack" as well as all .ml, .mli and .mlg files are listed in the "_CoqProject" file. *) (* -------------------------------------------------------------------------- *) (* *) (* Importing OCaml dependencies *) (* *) (* -------------------------------------------------------------------------- *) (* * This .mlg file is parsed into a .ml file. You can put OCaml in this file * inside of curly braces. It's best practice to use this only to import * other modules, and include most of your functionality in those modules. * * Here we list all of the dependencies that these commands have, and explain * why. We also refer to the first command that uses them, where further * explanation can be found in context. *) { (*** Dependencies from Coq ***) (* * This lets us take non-terminal arguments to a command (for example, * the PassInt command that takes an integer argument needs this * this dependency). * * First used by: PassInt *) open Stdarg (* * This is Coq's pretty-printing module. Here, we need it to use some * useful syntax for pretty-printing. * * First use by: Count *) open Pp } (* -------------------------------------------------------------------------- *) (* *) (* How to define a new Vernacular command? *) (* *) (* -------------------------------------------------------------------------- *) (* This command does nothing: *) VERNAC COMMAND EXTEND NoOp CLASSIFIED AS QUERY | [ "Nothing" ] -> { () } END (* --- Defining a Command --- These: VERNAC COMMAND EXTEND and END mark the beginning and the end of the definition of a new Vernacular command. --- Assigning a Command a Unique Identifier --- NoOp is a unique identifier (which must start with an upper-case letter) associated with the new Vernacular command we are defining. It is good to make this identifier descriptive. --- Classifying a Command --- CLASSIFIED AS QUERY tells Coq that the new Vernacular command neither: - changes the global environment, nor - modifies the plugin's state. If the new command could: - change the global environment - or modify a plugin's state then one would have to use CLASSIFIED AS SIDEFF instead. --- Defining Parsing and Interpretation Rules --- This: [ "Nothing" ] -> { () } defines: - the parsing rule (left) - the interpretation rule (right) The parsing rule and the interpretation rule are separated by -> token. The parsing rule, in this case, is: [ "Nothing" ] By convention, all vernacular command start with an upper-case letter. The '[' and ']' characters mark the beginning and the end of the parsing rule, respectively. The parsing rule itself says that the syntax of the newly defined command is composed from a single terminal Nothing. The interpretation rule, in this case, is: { () } Similarly to the case of the parsing rule, the '{' and '}' characters mark the beginning and the end of the interpretation rule. In this case, the following Ocaml expression: () defines the effect of the Vernacular command we have just defined. That is, it behaves is no-op. --- Calling a Command --- In Demo.v, we call this command by writing: Nothing. since our parsing rule is "Nothing". This does nothing, since our interpretation rule is (). *) (* -------------------------------------------------------------------------- *) (* *) (* How to define a new Vernacular command with some terminal parameters? *) (* *) (* -------------------------------------------------------------------------- *) (* This command takes some terminal parameters and does nothing. *) VERNAC COMMAND EXTEND NoOpTerminal CLASSIFIED AS QUERY | [ "Command" "With" "Some" "Terminal" "Parameters" ] -> { () } END (* --- Defining a Command with Terminal Parameters --- As shown above, the Vernacular command can be composed from any number of terminals. By convention, each of these terminals starts with an upper-case letter. --- Calling a Command with Terminal Parameters --- In Demo.v, we call this command by writing: Command With Some Terminal Parameters. to match our parsing rule. As expected, this does nothing. --- Recognizing Syntax Errors --- Note that if we were to omit any of these terminals, for example by writing: Command. it would fail to parse (as expected), showing this error to the user: Syntax error: illegal begin of vernac. *) (* -------------------------------------------------------------------------- *) (* *) (* How to define a new Vernacular command with some non-terminal parameter? *) (* *) (* -------------------------------------------------------------------------- *) (* This command takes an integer argument and does nothing. *) VERNAC COMMAND EXTEND PassInt CLASSIFIED AS QUERY | [ "Pass" int(i) ] -> { () } END (* --- Dependencies --- Since this command takes a non-terminal argument, it is the first to depend on Stdarg (opened at the top of this file). --- Defining a Command with Non-Terminal Arguments --- This: int(i) means that the new command is expected to be followed by an integer. The integer is bound in the parsing rule to variable i. This variable i then can be used in the interpretation rule. To see value of which Ocaml types can be bound this way, look at the wit_* function declared in interp/stdarg.mli (in the Coq's codebase). There are more examples in tuto1. If we drop the wit_ prefix, we will get the token that we can use in the parsing rule. That is, since there exists wit_int, we know that we can write: int(i) By looking at the signature of the wit_int function: val wit_int : int uniform_genarg_type we also know that variable i will have the type int. --- Recognizing Build Errors --- The mapping from int(i) to wit_int is automatic. This is why, if we forget to open Stdarg, we will get this error: Unbound value wit_int when we try to build our plugin. It is good to recognize this error, since this is a common mistake in plugin development, and understand that the fix is to open the file (Stdarg) where wit_int is defined. --- Calling a Command with Terminal Arguments --- We call this command in Demo.v by writing: Pass 42. We could just as well pass any other integer. As expected, this command does nothing. --- Recognizing Syntax Errors --- As in our previous command, if we were to omit the arguments to the command, for example by writing: Pass. it would fail to parse (as expected), showing this error to the user: Syntax error: [prim:integer] expected after 'Pass' (in [vernac:command]). The same thing would happen if we passed the wrong argument type: Pass True. If we pass too many arguments: Pass 15 20. we will get a different syntax error: Syntax error: '.' expected after [vernac:command] (in [vernac_aux]). It is good to recognize these errors, since doing so can help you catch mistakes you make defining your parser rules during plugin development. *) (* -------------------------------------------------------------------------- *) (* *) (* How to define a new Vernacular command with variable number of arguments? *) (* *) (* -------------------------------------------------------------------------- *) (* This command takes a list of integers and does nothing: *) VERNAC COMMAND EXTEND AcceptIntList CLASSIFIED AS QUERY | [ "Accept" int_list(l) ] -> { () } END (* --- Dependencies --- Much like PassInt, this command depends on Stdarg. --- Defining a Command that Takes a Variable Number of Arguments --- This: int_list(l) means that the new Vernacular command is expected to be followed by a (whitespace separated) list of integers. This list of integers is bound to the indicated l. In this case, as well as in the cases we point out below, instead of int in int_list we could use any other supported type, e.g. ident, bool, ... --- Other Ways to Take a Variable Number of Arguments --- To see which other Ocaml type constructors (in addition to list) are supported, have a look at the parse_user_entry function defined in the coqpp/coqpp_parse.mly file. E.g.: - ne_int_list(x) would represent a non-empty list of integers, - int_list(x) would represent a list of integers, - int_opt(x) would represent a value of type int option, - Β·Β·Β· Much like with int_list, we could use any other supported type here. There are some more examples of this in tuto1. --- Calling a Command with a Variable Number of Arguments --- We call this command in Demo.v by writing: Accept 100 200 300 400. As expected, this does nothing. Since our parser rule uses int_list, the arguments to Accept can be a list of integers of any length. For example, we can pass the empty list: Accept. or just one argument: Accept 2. and so on. *) (* -------------------------------------------------------------------------- *) (* *) (* How to define a new Vernacular command that takes values of a custom type? *) (* *) (* -------------------------------------------------------------------------- *) (* --- Defining Custom Types --- Vernacular commands can take custom types in addition to the built-in ones. The first step to taking these custom types as arguments is to define them. We define a type of values that we want to pass to our Vernacular command in custom.ml/custom.mli. The type is very simple: type custom_type : Foo | Bar. --- Using our New Module --- Now that we have a new OCaml module Custom, in order to use it, we must do the following: 1. Add src/custom.ml and src/custom.mli to our _CoqProject 2. Add Custom to our tuto2_plugin.mlpack This workflow will become very familiar to you when you add new modules to your plugins, so it is worth getting used to. --- Depending on our New Module --- Now that our new module is listed in both _CoqProject and tuto2_plugin.mlpack, we can use fully qualified names Custom.Foo and Custom.Bar. Alternatively, we could add the dependency on our module: open Custom. to the top of the file, and then refer to Foo and Bar directly. --- Telling Coq About our New Argument Type --- By default, we are able to define new Vernacular commands that can take parameters of some of the supported types. Which types are supported, that was discussed earlier. If we want to be able to define Vernacular command that takes parameters of a type that is not supported by default, we must use the following macro: *) VERNAC ARGUMENT EXTEND custom | [ "Foo" ] -> { Custom.Foo } | [ "Bar" ] -> { Custom.Bar } END (* where: custom indicates that, from now on, in our parsing rules we can write: custom(some_variable) in those places where we expect user to provide an input that can be parsed by the parsing rules above (and interpreted by the interpretations rules above). *) (* --- Defining a Command that Takes an Argument of a Custom Type --- Now that Coq is aware of our new argument type, we can define a command that uses it. This command takes an argument Foo or Bar and does nothing: *) VERNAC COMMAND EXTEND PassCustom CLASSIFIED AS QUERY | [ "Foobar" custom(x) ] -> { () } END (* --- Calling a Command that Takes an Argument of a Custom Type --- We call this command in Demo.v by writing: Foobar Foo. Foobar Bar. As expected, both of these do nothing. In the first case, x gets the value Custom.Foo : Custom.custom_type, since our custom parsing and interpretation rules (VERNAC ARGUMENT EXTEND custom ...) map the input Foo to Custom.Foo. Similarly, in the second case, x gets the value Custom.Bar : Custom.custom_type. *) (* -------------------------------------------------------------------------- *) (* *) (* How to give a feedback to the user? *) (* *) (* -------------------------------------------------------------------------- *) (* So far we have defined commands that do nothing. We can also signal feedback to the user. This command tells the user that everything is awesome: *) VERNAC COMMAND EXTEND Awesome CLASSIFIED AS QUERY | [ "Is" "Everything" "Awesome" ] -> { Feedback.msg_notice (Pp.str "Everything is awesome!") } END (* --- Pretty Printing --- User feedback functions like Feedback.msg_notice take a Pp.t as an argument. Check the Pp module to see which functions are available to construct a Pp.t. The Pp module enable us to represent and construct pretty-printing instructions. The concepts defined and the services provided by the Pp module are in various respects related to the concepts and services provided by the Format module that is part of the Ocaml standard library. --- Giving Feedback --- Once we have a Pp.t, we can use the following functions: - Feedback.msg_info : Pp.t -> unit - Feedback.msg_notice : Pp.t -> unit - Feedback.msg_debug : Pp.t -> unit to give user a textual feedback. Examples of some of these can be found in tuto0. --- Signaling Errors and Warnings --- While there is a Feedback.msg_error and Feedback.msg_warning, when signaling an error or warning, it is currently better practice to use CErrors or the CWarnings APIs. There are examples of this in tuto0. *) (* -------------------------------------------------------------------------- *) (* *) (* How to implement a Vernacular command with (undoable) side-effects? *) (* *) (* -------------------------------------------------------------------------- *) (* This command counts how many times it has been called since importing our plugin, and signals that information to the user: *) VERNAC COMMAND EXTEND Count CLASSIFIED AS SIDEFF | [ "Count" ] -> { Counter.increment (); let v = Counter.value () in Feedback.msg_notice (Pp.str "Times Count has been called: " ++ Pp.int v) } END (* --- Dependencies --- If we want to use the ++ syntax, then we need to depend on Pp explicitly. This is why, at the top, we write: open Pp. --- Defining the Counter --- We define our counter in the Counter module. Please see counter.ml and counter.mli for details. As with Custom, we must modify our _CoqProject and tuto2_plugin.mlpack so that we can use Counter in our code. --- Classifying the Command --- This command has undoable side-effects: When the plugin is first loaded, the counter is instantiated to 0. After each time we call Count, the value of the counter increases by 1. Thus, we must write CLASSIFIED AS SIDEEFF for this command, rather than CLASSIFIED AS QUERY. See the explanation from the NoOp command earlier if you do not remember the distinction. --- Calling the Command --- We call our command three times in Demo.v by writing: Count. Count. Count. This gives us the following output: Times Count has been called: 1 Times Count has been called: 2 Times Count has been called: 3 Note that when the plugin is first loaded, the counter is 0. It increases each time Count is called. --- Behavior with Imports --- Count.v shows the behavior with imports. Note that if we import Demo.v, the counter is set to 0 from the beginning, even though Demo.v calls Count three times. In other words, this is not persistent! *) (* -------------------------------------------------------------------------- *) (* *) (* How to implement a Vernacular command that uses persistent storage? *) (* *) (* -------------------------------------------------------------------------- *) (* * This command is like Count, but it is persistent across modules: *) VERNAC COMMAND EXTEND CountPersistent CLASSIFIED AS SIDEFF | [ "Count" "Persistent" ] -> { Persistent_counter.increment (); let v = Persistent_counter.value () in Feedback.msg_notice (Pp.str "Times Count Persistent has been called: " ++ Pp.int v) } END (* --- Persistent Storage --- Everything is similar to the Count command, except that we use a counter that is persistent. See persistent_counter.ml for details. The key trick is that we must create a persistent object for our counter to persist across modules. Coq has some useful APIs for this in Libobject. We demonstrate these in persistent_counter.ml. This is really, really useful if you want, for example, to cache some results that your plugin computes across modules. A persistent object can be a hashtable, for example, that maps inputs to outputs your command has already computed, if you know the result will not change. --- Calling the Command --- We call the command in Demo.v and in Count.v, just like we did with Count. Note that this time, the value of the counter from Demo.v persists in Count.v. *) rocq-9.2.0/doc/plugin_tutorial/tuto2/src/persistent_counter.ml000066400000000000000000000031731516144147600246260ustar00rootroot00000000000000(* * This file defines our persistent counter, which we use in the * CountPersistent command. *) (* * At its core, our persistent counter looks exactly the same as * our non-persistent counter (with a different name to prevent collisions): *) let counter = Summary.ref ~name:"persistent_counter" 0 (* * The difference is that we need to declare it as a persistent object * using Libobject.declare_object. To do that, we define a function that * saves the value that is passed to it into the reference we have just defined: *) let cache_count v = counter := v (* * We then use declare_object to create a function that takes an integer value * (the type our counter refers to) and creates a persistent object from that * value: *) let declare_counter : int -> Libobject.obj = let open Libobject in declare_object { (default_object "COUNTER") with cache_function = cache_count; load_function = (fun _ -> cache_count); classify_function = (fun _ -> Keep); } (* * See Libobject for more information on what other information you * can pass here, and what all of these functions mean. * * For example, if we passed the same thing that we pass to load_function * to open_function, then our last call to Count Persistent in Count.v * would return 4 and not 6. *) (* * Incrementing our counter looks almost identical: *) let increment () = Lib.add_leaf (declare_counter (succ !counter)) (* * except that we must call our declare_counter function to get a persistent * object. We then pass this object to Lib.add_leaf. *) (* * Reading a value does not change at all: *) let value () = !counter rocq-9.2.0/doc/plugin_tutorial/tuto2/src/persistent_counter.mli000066400000000000000000000003761516144147600250010ustar00rootroot00000000000000(* * This file defines our persistent counter, which we use in the * CountPersistent command. *) (* * Increment the persistent counter *) val increment : unit -> unit (* * Determine the value of the persistent counter *) val value : unit -> int rocq-9.2.0/doc/plugin_tutorial/tuto2/src/tuto2_plugin.mlpack000066400000000000000000000000521516144147600241520ustar00rootroot00000000000000Custom Counter Persistent_counter G_tuto2 rocq-9.2.0/doc/plugin_tutorial/tuto2/theories/000077500000000000000000000000001516144147600213645ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto2/theories/Count.v000066400000000000000000000002471516144147600226460ustar00rootroot00000000000000Require Import Demo. (*** Local ***) Count. Count. Import Demo. Count. (*** Persistent ***) Count Persistent. Count Persistent. Import Demo. Count Persistent. rocq-9.2.0/doc/plugin_tutorial/tuto2/theories/Demo.v000066400000000000000000000016361516144147600224450ustar00rootroot00000000000000From Tuto2 Require Import Loader. (*** A no-op command ***) Nothing. (*** No-op commands with arguments ***) (* * Terminal parameters: *) Command With Some Terminal Parameters. (* Command. *) (* does not parse *) (* * A single non-terminal argument: *) Pass 42. (* Pass. *) (* does not parse *) (* Pass True. *) (* does not parse *) (* Pass 15 20. *) (* does not parse *) (* * A list of non-terminal arguments: *) Accept 100 200 300 400. Accept. Accept 2. (* * A custom argument: *) Foobar Foo. Foobar Bar. (*** Commands that give feedback ***) (* * Simple feedback: *) Is Everything Awesome. (*** Storage and side effects ***) (* * Local side effects: *) Count. Count. Count. (* * See Count.v for behavior in modules that import this one. *) (* * Persistent side effects: *) Count Persistent. Count Persistent. Count Persistent. (* * See Count.v for behavior in modules that import this one. *) rocq-9.2.0/doc/plugin_tutorial/tuto2/theories/Loader.v000066400000000000000000000000601516144147600227550ustar00rootroot00000000000000Declare ML Module "rocq-plugin-tutorial.tuto2". rocq-9.2.0/doc/plugin_tutorial/tuto3/000077500000000000000000000000001516144147600175435ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto3/Makefile000066400000000000000000000002071516144147600212020ustar00rootroot00000000000000COQBIN?= %: Makefile.rocq Makefile.rocq: _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o Makefile.rocq -include Makefile.rocq rocq-9.2.0/doc/plugin_tutorial/tuto3/_CoqProject000066400000000000000000000003351516144147600216770ustar00rootroot00000000000000src/META.rocq-plugin-tutorial -R theories Tuto3 -I src theories/Data.v theories/Loader.v src/tuto_tactic.ml src/tuto_tactic.mli src/construction_game.ml src/construction_game.mli src/g_tuto3.mlg src/tuto3_plugin.mlpack rocq-9.2.0/doc/plugin_tutorial/tuto3/src/000077500000000000000000000000001516144147600203325ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto3/src/META.rocq-plugin-tutorial000066400000000000000000000004721516144147600251060ustar00rootroot00000000000000package "tuto3" ( directory = "." version = "dev" description = "A tuto3 plugin" requires = "rocq-runtime.plugins.ltac" archive(byte) = "tuto3_plugin.cma" archive(native) = "tuto3_plugin.cmxa" plugin(byte) = "tuto3_plugin.cma" plugin(native) = "tuto3_plugin.cmxs" ) directory = "." rocq-9.2.0/doc/plugin_tutorial/tuto3/src/construction_game.ml000066400000000000000000000164221516144147600244140ustar00rootroot00000000000000open Pp open EConstr let example_sort sigma = (* creating a new sort requires that universes should be recorded in the evd datastructure, so this datastructure also needs to be passed around. *) let sigma, s = Evd.new_sort_variable Evd.univ_rigid sigma in let new_type = mkSort s in sigma, new_type let c_one env sigma = (* In the general case, global references may refer to universe polymorphic objects, and their universe has to be made afresh when creating an instance. *) let gr_S = Rocqlib.lib_ref "num.nat.S" in (* the long name of "S" was found with the command "Print Registered." *) let gr_O = Rocqlib.lib_ref "num.nat.O" in let sigma, c_O = Evd.fresh_global env sigma gr_O in let sigma, c_S = Evd.fresh_global env sigma gr_S in (* Here is the construction of a new term by applying functions to argument. *) sigma, mkApp (c_S, [| c_O |]) let dangling_identity env sigma = (* I call this a dangling identity, because it is not polymorph, but the type on which it applies is left unspecified, as it is represented by an existential variable. The declaration for this existential variable needs to be added in the evd datastructure. *) let sigma, type_type = example_sort sigma in let sigma, arg_type = Evarutil.new_evar env sigma type_type in (* Notice the use of a De Bruijn index for the inner occurrence of the bound variable. *) sigma, mkLambda(nameR (Names.Id.of_string "x"), arg_type, mkRel 1) let dangling_identity2 env sigma = (* This example uses directly a function that produces an evar that is meant to be a type. *) let sigma, (arg_type, type_type) = Evarutil.new_type_evar env sigma Evd.univ_rigid in sigma, mkLambda(nameR (Names.Id.of_string "x"), arg_type, mkRel 1) let example_sort_app_lambda () = let env = Global.env () in let sigma = Evd.from_env env in let sigma, c_v = c_one env sigma in (* dangling_identity and dangling_identity2 can be used interchangeably here *) let sigma, c_f = dangling_identity2 env sigma in let c_1 = mkApp (c_f, [| c_v |]) in let _ = Feedback.msg_notice (Printer.pr_econstr_env env sigma c_1) in (* type verification happens here. Type verification will update existential variable information in the evd part. *) let sigma, the_type = Typing.type_of env sigma c_1 in (* At display time, you will notice that the system knows about the existential variable being instantiated to the "nat" type, even though c_1 still contains the meta-variable. *) Feedback.msg_notice ((Printer.pr_econstr_env env sigma c_1) ++ str " has type " ++ (Printer.pr_econstr_env env sigma the_type)) let c_S env sigma = let gr = Rocqlib.lib_ref "num.nat.S" in Evd.fresh_global env sigma gr let c_O env sigma = let gr = Rocqlib.lib_ref "num.nat.O" in Evd.fresh_global env sigma gr let c_E env sigma = let gr = Rocqlib.lib_ref "Tuto3.EvenNat" in Evd.fresh_global env sigma gr let c_D env sigma = let gr = Rocqlib.lib_ref "Tuto3.tuto_div2" in Evd.fresh_global env sigma gr let c_Q env sigma = let gr = Rocqlib.lib_ref "core.eq.type" in Evd.fresh_global env sigma gr let c_R env sigma = let gr = Rocqlib.lib_ref "core.eq.eq_refl" in Evd.fresh_global env sigma gr let c_N env sigma = let gr = Rocqlib.lib_ref "num.nat.type" in Evd.fresh_global env sigma gr let c_C env sigma = let gr = Rocqlib.lib_ref "Tuto3.C" in Evd.fresh_global env sigma gr let c_F env sigma = let gr = Rocqlib.lib_ref "Tuto3.S_ev" in Evd.fresh_global env sigma gr let c_P env sigma = let gr = Rocqlib.lib_ref "Tuto3.s_half_proof" in Evd.fresh_global env sigma gr (* If c_S was universe polymorphic, we should have created a new constant at each iteration of buildup. *) let mk_nat env sigma n = let sigma, c_S = c_S env sigma in let sigma, c_O = c_O env sigma in let rec buildup = function | 0 -> c_O | n -> mkApp (c_S, [| buildup (n - 1) |]) in if n <= 0 then sigma, c_O else sigma, buildup n let example_classes n = let env = Global.env () in let sigma = Evd.from_env env in let sigma, c_n = mk_nat env sigma n in let sigma, n_half = mk_nat env sigma (n / 2) in let sigma, c_N = c_N env sigma in let sigma, c_div = c_D env sigma in let sigma, c_even = c_E env sigma in let sigma, c_Q = c_Q env sigma in let sigma, c_R = c_R env sigma in let arg_type = mkApp (c_even, [| c_n |]) in let sigma0 = sigma in let sigma, instance = Evarutil.new_evar env sigma arg_type in let c_half = mkApp (c_div, [|c_n; instance|]) in let _ = Feedback.msg_notice (Printer.pr_econstr_env env sigma c_half) in let sigma, the_type = Typing.type_of env sigma c_half in let _ = Feedback.msg_notice (Printer.pr_econstr_env env sigma c_half) in let proved_equality = mkCast(mkApp (c_R, [| c_N; c_half |]), Constr.DEFAULTcast, mkApp (c_Q, [| c_N; c_half; n_half|])) in (* This is where we force the system to compute with type classes. *) (* Question to coq developers: why do we pass two evd arguments to solve_remaining_evars? Is the choice of sigma0 relevant here? *) let sigma = Pretyping.solve_remaining_evars (Pretyping.default_inference_flags true) env sigma ~initial:sigma0 in let sigma, final_type = Typing.type_of env sigma proved_equality in Feedback.msg_notice (Printer.pr_econstr_env env sigma proved_equality) (* This function, together with definitions in Data.v, shows how to trigger automatic proofs at the time of typechecking, based on canonical structures. n is a number for which we want to find the half (and a proof that this half is indeed the half) *) let example_canonical n = let env = Global.env () in let sigma = Evd.from_env env in (* Construct a natural representation of this integer. *) let sigma, c_n = mk_nat env sigma n in (* terms for "nat", "eq", "S_ev", "eq_refl", "C" *) let sigma, c_N = c_N env sigma in let sigma, c_F = c_F env sigma in let sigma, c_R = c_R env sigma in let sigma, c_C = c_C env sigma in let sigma, c_P = c_P env sigma in (* the last argument of C *) let refl_term = mkApp (c_R, [|c_N; c_n |]) in (* Now we build two existential variables, for the value of the half and for the "S_ev" structure that triggers the proof search. *) let sigma, ev1 = Evarutil.new_evar env sigma c_N in (* This is the type for the second existential variable *) let csev = mkApp (c_F, [| ev1 |]) in let sigma, ev2 = Evarutil.new_evar env sigma csev in (* Now we build the C structure. *) let test_term = mkApp (c_C, [| c_n; ev1; ev2; refl_term |]) in (* Type-checking this term will compute values for the existential variables *) let sigma, final_type = Typing.type_of env sigma test_term in (* The computed type has two parameters, the second one is the proof. *) let value = match kind sigma final_type with | Constr.App(_, [| _; the_half |]) -> the_half | _ -> failwith "expecting the whole type to be \"cmp _ the_half\"" in let _ = Feedback.msg_notice (Printer.pr_econstr_env env sigma value) in (* I wish for a nicer way to get the value of ev2 in the evar_map *) let prf_struct = of_constr (to_constr sigma ev2) in let the_prf = mkApp (c_P, [| ev1; prf_struct |]) in let sigma, the_statement = Typing.type_of env sigma the_prf in Feedback.msg_notice (Printer.pr_econstr_env env sigma the_prf ++ str " has type " ++ Printer.pr_econstr_env env sigma the_statement) rocq-9.2.0/doc/plugin_tutorial/tuto3/src/construction_game.mli000066400000000000000000000003011516144147600245520ustar00rootroot00000000000000val dangling_identity : Environ.env -> Evd.evar_map -> Evd.evar_map * EConstr.t val example_sort_app_lambda : unit -> unit val example_classes : int -> unit val example_canonical : int -> unit rocq-9.2.0/doc/plugin_tutorial/tuto3/src/dune000066400000000000000000000004151516144147600212100ustar00rootroot00000000000000(library (name tuto3_plugin) (public_name rocq-runtime.plugins.tutorial.p3) (flags :standard -warn-error -3) (libraries rocq-runtime.plugins.ltac)) (rule (targets g_tuto3.ml) (deps (:mlg g_tuto3.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/doc/plugin_tutorial/tuto3/src/g_tuto3.mlg000066400000000000000000000023651516144147600224250ustar00rootroot00000000000000(** See dev/doc/parsing.md for mlg doc *) DECLARE PLUGIN "rocq-plugin-tutorial.tuto3" { open Ltac_plugin open Construction_game (* This one is necessary, to avoid message about missing wit_string *) open Stdarg } VERNAC COMMAND EXTEND ShowTypeConstruction CLASSIFIED AS QUERY | [ "Tuto3_1" ] -> { let env = Global.env () in let sigma = Evd.from_env env in let sigma, s = Evd.new_sort_variable Evd.univ_rigid sigma in let new_type_2 = EConstr.mkSort s in let sigma, _ = Typing.type_of env (Evd.from_env env) new_type_2 in Feedback.msg_notice (Printer.pr_econstr_env env sigma new_type_2) } END VERNAC COMMAND EXTEND ShowOneConstruction CLASSIFIED AS QUERY | [ "Tuto3_2" ] -> { example_sort_app_lambda () } END TACTIC EXTEND collapse_hyps | [ "pack" "hypothesis" ident(i) ] -> { Tuto_tactic.pack_tactic i } END (* More advanced examples, where automatic proof happens but no tactic is being called explicitly. The first one uses type classes. *) VERNAC COMMAND EXTEND TriggerClasses CLASSIFIED AS QUERY | [ "Tuto3_3" int(n) ] -> { example_classes n } END (* The second one uses canonical structures. *) VERNAC COMMAND EXTEND TriggerCanonical CLASSIFIED AS QUERY | [ "Tuto3_4" int(n) ] -> { example_canonical n } END rocq-9.2.0/doc/plugin_tutorial/tuto3/src/tuto3_plugin.mlpack000066400000000000000000000000461516144147600241570ustar00rootroot00000000000000Construction_game Tuto_tactic G_tuto3 rocq-9.2.0/doc/plugin_tutorial/tuto3/src/tuto_tactic.ml000066400000000000000000000127631516144147600232170ustar00rootroot00000000000000open Proofview let constants = ref ([] : EConstr.t list) (* This is a pattern to collect terms from the Coq memory of valid terms and proofs. This pattern extends all the way to the definition of function c_U *) let collect_constants () = if (!constants = []) then let open Names in let open EConstr in let open UnivGen in let find_reference path id = let path = DirPath.make (List.rev_map Id.of_string path) in let fp = Libnames.make_path path (Id.of_string id) in Nametab.global_of_path fp in let gr_H = find_reference ["Tuto3"; "Data"] "pack" in let gr_M = find_reference ["Tuto3"; "Data"] "packer" in let gr_R = find_reference ["Corelib"; "Init"; "Datatypes"] "pair" in let gr_P = find_reference ["Corelib"; "Init"; "Datatypes"] "prod" in let gr_U = find_reference ["Tuto3"; "Data"] "uncover" in constants := List.map (fun x -> of_constr (constr_of_monomorphic_global (Global.env ()) x)) [gr_H; gr_M; gr_R; gr_P; gr_U]; !constants else !constants let c_H () = match collect_constants () with it :: _ -> it | _ -> failwith "could not obtain an internal representation of pack" let c_M () = match collect_constants () with _ :: it :: _ -> it | _ -> failwith "could not obtain an internal representation of pack_marker" let c_R () = match collect_constants () with _ :: _ :: it :: _ -> it | _ -> failwith "could not obtain an internal representation of pair" let c_P () = match collect_constants () with _ :: _ :: _ :: it :: _ -> it | _ -> failwith "could not obtain an internal representation of prod" let c_U () = match collect_constants () with _ :: _ :: _ :: _ :: it :: _ -> it | _ -> failwith "could not obtain an internal representation of prod" (* The following tactic is meant to pack an hypothesis when no other data is already packed. The main difficulty in defining this tactic is to understand how to construct the input expected by apply_in. *) let package i = Goal.enter begin fun gl -> Tactics.apply_in true false i [(* this means that the applied theorem is not to be cleared. *) None, (CAst.make (c_M (), (* we don't specialize the theorem with extra values. *) Tactypes.NoBindings))] (* we don't destruct the result according to any intro_pattern *) None end (* This function is meant to observe a type of shape (f a) and return the value a. *) (* Remark by Maxime: look for destApp combinator. *) let unpack_type sigma term = let report () = CErrors.user_err (Pp.str "expecting a packed type") in match EConstr.kind sigma term with | Constr.App (_, [| ty |]) -> ty | _ -> report () (* This function is meant to observe a type of shape A -> pack B -> C and return A, B, C but it is not used in the current version of our tactic. It is kept as an example. *) let two_lambda_pattern sigma term = let report () = CErrors.user_err (Pp.str "expecting two nested implications") in (* Note that pattern-matching is always done through the EConstr.kind function, which only provides one-level deep patterns. *) match EConstr.kind sigma term with (* Here we recognize the outer implication *) | Constr.Prod (_, ty1, l1) -> (* Here we recognize the inner implication *) (match EConstr.kind sigma l1 with | Constr.Prod (n2, packed_ty2, deep_conclusion) -> (* Here we recognized that the second type is an application *) ty1, unpack_type sigma packed_ty2, deep_conclusion | _ -> report ()) | _ -> report () (* In the environment of the goal, we can get the type of an assumption directly by a lookup. The other solution is to call a low-cost retyping function like *) let get_type_of_hyp env id = match EConstr.lookup_named id env with | Context.Named.Declaration.LocalAssum (_, ty) -> ty | _ -> CErrors.user_err (let open Pp in str (Names.Id.to_string id) ++ str " is not a plain hypothesis") let repackage i h_hyps_id = Goal.enter begin fun gl -> let env = Goal.env gl in let sigma = Goal.sigma gl in let concl = Goal.concl gl in let (ty1 : EConstr.t) = get_type_of_hyp env i in let (packed_ty2 : EConstr.t) = get_type_of_hyp env h_hyps_id in let ty2 = unpack_type sigma packed_ty2 in let new_packed_type = EConstr.mkApp (c_P (), [| ty1; ty2 |]) in let open EConstr in let new_packed_value = mkApp (c_R (), [| ty1; ty2; mkVar i; mkApp (c_U (), [| ty2; mkVar h_hyps_id|]) |]) in Refine.refine ~typecheck:true begin fun sigma -> let sigma, new_goal = Evarutil.new_evar env sigma (mkArrowR (mkApp(c_H (), [| new_packed_type |])) (Vars.lift 1 concl)) in sigma, mkApp (new_goal, [|mkApp(c_M (), [|new_packed_type; new_packed_value |]) |]) end end let pack_tactic i = let h_hyps_id = (Names.Id.of_string "packed_hyps") in Proofview.Goal.enter begin fun gl -> let hyps = Environ.named_context_val (Proofview.Goal.env gl) in if not (Termops.mem_named_context_val i hyps) then (CErrors.user_err (Pp.str ("no hypothesis named" ^ (Names.Id.to_string i)))) else if Termops.mem_named_context_val h_hyps_id hyps then tclTHEN (repackage i h_hyps_id) (tclTHEN (Tactics.clear [h_hyps_id; i]) (Tactics.introduction h_hyps_id)) else tclTHEN (package i) (tclTHEN (Tactics.rename_hyp [i, h_hyps_id]) (Tactics.move_hyp h_hyps_id Logic.MoveLast)) end rocq-9.2.0/doc/plugin_tutorial/tuto3/src/tuto_tactic.mli000066400000000000000000000002221516144147600233530ustar00rootroot00000000000000val two_lambda_pattern : Evd.evar_map -> EConstr.t -> EConstr.t * EConstr.t * EConstr.t val pack_tactic : Names.Id.t -> unit Proofview.tactic rocq-9.2.0/doc/plugin_tutorial/tuto3/theories/000077500000000000000000000000001516144147600213655ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto3/theories/Data.v000066400000000000000000000036351516144147600224340ustar00rootroot00000000000000 Inductive pack (A: Type) : Type := packer : A -> pack A. Arguments packer {A}. Definition uncover (A : Type) (packed : pack A) : A := match packed with packer v => v end. Notation "!!!" := (pack _) (at level 0, only printing). (* The following data is used as material for automatic proofs based on type classes. *) Class EvenNat the_even := {half : nat; half_prop : 2 * half = the_even}. #[export] Instance EvenNat0 : EvenNat 0 := {half := 0; half_prop := eq_refl}. Register EvenNat as Tuto3.EvenNat. Lemma even_rec n h : 2 * h = n -> 2 * S h = S (S n). Proof. intros []. simpl. rewrite <-plus_n_O, <-plus_n_Sm. reflexivity. Qed. #[export] Instance EvenNat_rec n (p : EvenNat n) : EvenNat (S (S n)) := {half := S (@half _ p); half_prop := even_rec n (@half _ p) (@half_prop _ p)}. Definition tuto_div2 n (p : EvenNat n) := @half _ p. Register tuto_div2 as Tuto3.tuto_div2. (* to be used in the following examples Compute (@half 8 _). Check (@half_prop 8 _). Check (@half_prop 7 _). and in command Tuto3_3 8. *) (* The following data is used as material for automatic proofs based on canonical structures. *) Record S_ev n := Build_S_ev {double_of : nat; _ : 2 * n = double_of}. Register S_ev as Tuto3.S_ev. Definition s_half_proof n (r : S_ev n) : 2 * n = double_of n r := match r with Build_S_ev _ _ h => h end. Register s_half_proof as Tuto3.s_half_proof. Canonical Structure can_ev_default n d (Pd : 2 * n = d) : S_ev n := Build_S_ev n d Pd. Canonical Structure can_ev0 : S_ev 0 := Build_S_ev 0 0 (@eq_refl _ 0). Lemma can_ev_rec n : forall (s : S_ev n), S_ev (S n). Proof. intros s; exists (S (S (double_of _ s))). destruct s as [a P]. exact (even_rec _ _ P). Defined. Canonical Structure can_ev_rec. Record cmp (n : nat) (k : nat) := C {h : S_ev k; _ : double_of k h = n}. Register C as Tuto3.C. (* To be used in, e.g., Check (C _ _ _ eq_refl : cmp 6 _). Check (C _ _ _ eq_refl : cmp 7 _). *) rocq-9.2.0/doc/plugin_tutorial/tuto3/theories/Loader.v000066400000000000000000000001211516144147600227540ustar00rootroot00000000000000From Tuto3 Require Export Data. Declare ML Module "rocq-plugin-tutorial.tuto3". rocq-9.2.0/doc/plugin_tutorial/tuto3/theories/test.v000066400000000000000000000013111516144147600225270ustar00rootroot00000000000000(* to be used e.g. in : coqtop -I src -R theories Tuto3 < theories/test.v *) Require Import Tuto3.Loader. (* This should print Type. *) Tuto3_1. (* This should print a term that contains an existential variable. *) (* And then print the same term, where the variable has been correctly instantiated. *) Tuto3_2. Lemma tutu x y (A : 0 < x) (B : 10 < y) : True. Proof. pack hypothesis A. (* Hypothesis A should have disappeared and a "packed_hyps" hypothesis should have appeared, with unreadable content. *) pack hypothesis B. (* Hypothesis B should have disappeared *) destruct packed_hyps as [unpacked_hyps]. (* Hypothesis unpacked_hyps should contain the previous contents of A and B. *) exact I. Qed. rocq-9.2.0/doc/plugin_tutorial/tuto4/000077500000000000000000000000001516144147600175445ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto4/Makefile000066400000000000000000000002071516144147600212030ustar00rootroot00000000000000COQBIN?= %: Makefile.rocq Makefile.rocq: _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o Makefile.rocq -include Makefile.rocq rocq-9.2.0/doc/plugin_tutorial/tuto4/Makefile.rocq.local000066400000000000000000000000601516144147600232340ustar00rootroot00000000000000CAMLPKGS := -package rocq-runtime.plugins.ltac2 rocq-9.2.0/doc/plugin_tutorial/tuto4/_CoqProject000066400000000000000000000002321516144147600216740ustar00rootroot00000000000000src/META.rocq-plugin-tutorial -R theories Tuto4 -I src theories/Loader.v theories/Demo.v src/myexternals.ml src/myexternals.mli src/tuto4_plugin.mlpack rocq-9.2.0/doc/plugin_tutorial/tuto4/src/000077500000000000000000000000001516144147600203335ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto4/src/META.rocq-plugin-tutorial000066400000000000000000000004731516144147600251100ustar00rootroot00000000000000package "tuto4" ( directory = "." version = "dev" description = "A tuto4 plugin" requires = "rocq-runtime.plugins.ltac2" archive(byte) = "tuto4_plugin.cma" archive(native) = "tuto4_plugin.cmxa" plugin(byte) = "tuto4_plugin.cma" plugin(native) = "tuto4_plugin.cmxs" ) directory = "." rocq-9.2.0/doc/plugin_tutorial/tuto4/src/dune000066400000000000000000000001671516144147600212150ustar00rootroot00000000000000(library (name tuto4_plugin) (public_name rocq-runtime.plugins.tutorial.p4) (libraries rocq-runtime.plugins.ltac2)) rocq-9.2.0/doc/plugin_tutorial/tuto4/src/myexternals.ml000066400000000000000000000172141516144147600232450ustar00rootroot00000000000000open Names (* kernel names, ie ModPath, KerName, Id etc *) open Ltac2_plugin (* the Ltac2 plugin is "packaged" ie its modules are all contained in module Ltac2_plugin without this open we would have to refer to eg Ltac2_plugin.Tac2externals below *) open Tac2externals (* APIs to register new externals, including the convenience "@->" infix operator *) open Tac2ffi (* Translation operators between Ltac2 values and OCaml values in various types *) (** **** Two simple examples of tactics *) (* Rocq tactics are values of the [Proofview.tactic] monad. tclUnit in Proofview is the return operation of this monad. We define an alias for convenience. *) let return = Proofview.tclUNIT (* Used to distinguish our primitives from some other plugin's primitives. By convention matches the plugin's ocamlfind name. *) let plugin_name = "rocq-plugin-tutorial.tuto4" let pname s = { Tac2expr.mltac_plugin = plugin_name; mltac_tactic = s } (* We define for convenience a wrapper around Tac2externals.define. [define "foo"] has type [('a, 'b) Ltac2_plugin.Tac2externals.spec -> 'b -> unit]. Type [('a, 'b) spec] represents a high-level Ltac2 tactic specification. It indicates how to turn a value of type ['b] into an Ltac2 tactic. The type parameter ['a] gives the type of value produced by interpreting the specification. *) let define s = define (pname s) (* We define a tactic taking an Ltac2 integer and returning an Ltac2 boolean "@->" is an infix function from Tac2externals combining a "type representation" (Tac2ffi.repr) and a [Tac2externals.spec]. Here, [int @-> ret bool] means that we want to define an Ltac2 tactic which takes an Ltac2 int and returns an Ltac2 bool. [ret] means we return the answer without doing tactic operations (no access to the Proofview monad). *) let () = define "the_question" (int @-> ret bool) @@ fun i -> Int.equal i 42 (* Now, we define a wrapper around "exact", it takes a constr (ie a term) and returns the trivial value (and does side effects on the goal). "tac" means we have access to the tactic monad. *) let () = define "my_exact" (constr @-> tac unit) @@ fun c -> Tactics.exact_check c (* We can see our new Ltac2 tactics in action in the beginning of the theories/Demo.v file. *) (** **** Transparent custom type *) (* We have seen before how to use the int and bool "reprs" (representations) in Ltac2. In this section, we will learn to define a "repr" for a custom OCaml type. *) (* We define a custom type in OCaml and in Ltac2 (this is the OCaml side): *) type my_custom = | A | B of EConstr.t (* EConstr.t is the type of terms (it wraps around the kernel Constr.t to enforce invariants when handling terms with existential variables). *) (* Translate from OCaml to the Ltac2 representation (Tac2val.valexpr). Values of Ltac2 algebraic datatypes are represented - for constant (without arguments) constructors, by ValInt where the int is the 0-based index of the constructor (excluding non-constant constructors) - for non-constant (with arguments) constructors, by ValBlk where the first argument is the 0-based index of the constructor (excluding constant constructors) and the second is an array containing the arguments. eg with [Ltac2 Type foo := [ A | B (x) | C | D (y, z) ]], - [A] is [ValInt 0] - [B v] is [ValBlk (0, [|v|])] - [C] is [ValInt 1] - [D v1 v2] is [ValBlk (1, [|v1; v2|])] When building values from OCaml we can use [of_int] and [of_block] instead of [ValInt] and [ValBlk]. *) let of_custom = function | A -> of_int 0 | B c -> (* Here [of_constr] is [Tac2ffi.of_constr] *) of_block (0, [|of_constr c|]) (* Go from the Ltac2 representation to the OCaml representation. This needs to look at the low-level valexpr data. If an external is declared with an incorrect Ltac2 type it may be passed invalid values, in which case we assert false. *) let to_custom = let open Tac2val in function | ValInt 0 -> A | ValBlk (0, [|c|]) -> (* [to_constr] is [Tac2ffi.to_constr] *) B (to_constr c) | _ -> assert false (* Now we package both translation functions into a Tac2ffi.repr which is just a record holding these two translation functions *) let custom = make_repr of_custom to_custom (* We can now use custom just like we used the "int" and "bool" reprs before. For instance, here is a tactic returning true if passed [A] or [B] of some inductive type. We need the evar map to inspect the term in the B case, but we don't need the current goal's hypotheses, so we use "eret" (in fact we don't use the environment at all). *) let () = define "is_ind_or_a" (custom @-> eret bool) @@ fun v env sigma -> match v with | A -> true | B c -> EConstr.isInd sigma c (* We can now use custom just like we used the "int" and "bool" reprs before. For instance, here is a tactic returning true if passed [A] or [B] of some inductive type. We need the evar map to inspect the term in the B case, but we don't need the current goal's hypotheses, so we use "eret" (in fact we don't use the environment at all). We could also use "gret", but that fails (with an anomaly) when 0 goals are focused. *) let () = define "check_in_goal" (ident @-> tac custom) @@ fun id -> (* pf_apply gives us the "current" environment, ie the global env if no goals are focused and the current goal env if 1 goal is focused. If >1 goals are focused it throws an exception. *) Tac2core.pf_apply @@ fun env sigma -> match EConstr.lookup_named id env with | exception Not_found -> return A | d -> return (B (Context.Named.Declaration.get_type d)) (* **** Abstract custom type *) (* Now we define a custom type in OCaml, but we do not want to expose its representation in Ltac2. *) type custom2 = int * int (* The string given to Val.create must be GLOBALLY unique (not just unique to the current plugin). If we wanted to be safe we could do [create (plugin_name^":mycustom2")]. *) let val_custom2 = Tac2dyn.Val.create "mycustom2" (* the "repr" for our custom values *) let custom2 = repr_ext val_custom2 (* a couple toy functions *) let () = define "mk_custom2" (int @-> int @-> ret custom2) @@ fun i j -> (i, j) let () = define "sum2" (custom2 @-> ret int) @@ fun (i,j) -> i + j (* we can also declare a printer for our custom values. *) (* Ltac2 printers are type-directed, so we need to tell which type we know how to print. The type is identified by its nma of type [Tac2expr.type_constant = KerName.t]. Current APIs for this are not very nice, we have to write module paths by hand. *) (* the loader module is a file whose logical name is Tuto4.Loader *) let loader_module_name = ModPath.MPfile (DirPath.make @@ List.map Id.of_string ["Loader"; "Tuto4"]) (* the type in that module is "custom2" *) let custom2_type_name = KerName.make loader_module_name (Id.of_string "custom2") (* the printing system gives us the current env and evar map, the value to be printed, and the type arguments at which we are printing. *) let pr_custom2 env sigma v tys = assert (CList.is_empty tys); (* Since custom2 has no arguments, tys is the empty list. *) (* by typing, v must be a custom2 value *) let (i, j) = repr_to custom2 v in (* NB: open Pp would shadow "v" if we did it between binding "v" and using it *) let open Pp in int i ++ str "," ++ int j (* Finally, we register our printer for custom2 to be used in Ltac2. It will be used every time Ltac2 needs to output values of type custom2. *) let () = Tac2print.register_val_printer custom2_type_name { val_printer = pr_custom2 } (* The end of Demo.v show how Ltac2 will use this printer function whenever it needs to print a value of type custom2. *) rocq-9.2.0/doc/plugin_tutorial/tuto4/src/myexternals.mli000066400000000000000000000003231516144147600234070ustar00rootroot00000000000000open Ltac2_plugin open Tac2ffi (** We don't need to expose any APIs for the plugin to work, but we may if we want to allow further plugins to build on this one. *) type custom2 val custom2 : custom2 repr rocq-9.2.0/doc/plugin_tutorial/tuto4/src/tuto4_plugin.mlpack000066400000000000000000000000141516144147600241540ustar00rootroot00000000000000Myexternals rocq-9.2.0/doc/plugin_tutorial/tuto4/theories/000077500000000000000000000000001516144147600213665ustar00rootroot00000000000000rocq-9.2.0/doc/plugin_tutorial/tuto4/theories/Demo.v000066400000000000000000000011521516144147600224400ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. From Tuto4 Require Import Loader. (* try out our "question" primitive *) Ltac2 Eval question 2. (* false *) Ltac2 Eval question 42. (* true *) (* try out our "tuto_exact" primitive *) Goal True. Fail tuto_exact '0. tuto_exact 'I. Qed. (* try out our custom type functions *) Ltac2 Eval ind_or_a A. Ltac2 Eval ind_or_a (B '0). Ltac2 Eval ind_or_a (B 'nat). Goal nat -> nat. intros x. Ltac2 Eval check_in_goal @x. Ltac2 Eval check_in_goal @y. Abort. (* try out our custom2 functions *) Ltac2 Eval mk_custom2 2 4. (* our printer works *) Ltac2 Eval sum2 (mk_custom2 2 4). rocq-9.2.0/doc/plugin_tutorial/tuto4/theories/Loader.v000066400000000000000000000023421516144147600227640ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. Declare ML Module "rocq-plugin-tutorial.tuto4". (** A simple function taking an integer and returning a boolean. Note that the internal name "the_question" does not need to match the exposed name "question". *) Ltac2 @external question : int -> bool := "rocq-plugin-tutorial.tuto4" "the_question". (** a wrapper around "exact" *) Ltac2 @external tuto_exact : constr -> unit := "rocq-plugin-tutorial.tuto4" "my_exact". (** Some custom type. *) Ltac2 Type custom := [ A | B (constr) ]. (** A function returning true if passed [A] or [B] of some inductive type. *) Ltac2 @external ind_or_a : custom -> bool := "rocq-plugin-tutorial.tuto4" "is_ind_or_a". (** a function returning [A] if the ident is not an hypothesis, or [B t] where [t] is its type if it is. *) Ltac2 @external check_in_goal : ident -> custom := "rocq-plugin-tutorial.tuto4" "check_in_goal". (** Another custom type, this one abstract on the Ltac2 side. *) Ltac2 Type custom2. (** Build a custom2 value. *) Ltac2 @external mk_custom2 : int -> int -> custom2 := "rocq-plugin-tutorial.tuto4" "mk_custom2". (** Get something from a custom2 value. *) Ltac2 @external sum2 : custom2 -> int := "rocq-plugin-tutorial.tuto4" "sum2". rocq-9.2.0/doc/sphinx/000077500000000000000000000000001516144147600145555ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/README.rst000066400000000000000000000442321516144147600162510ustar00rootroot00000000000000============================= Documenting Coq with Sphinx ============================= .. README.rst is auto-generated from README.template.rst and the coqrst/*.py files (in particular coqdomain.py). Use ``doc/tools/coqrst/regen_readme.py`` to rebuild it. Coq's reference manual is written in `reStructuredText `_ (β€œreST”), and compiled with `Sphinx `_. See `this README <../README.md>`_ for compilation instructions. In addition to standard reST directives (a directive is similar to a LaTeX environment) and roles (a role is similar to a LaTeX command), the ``coqrst`` plugin loaded by the documentation uses a custom *Coq domain* β€” a set of Coq-specific directives that define *objects* like tactics, commands (vernacs), warnings, etc. β€”, some custom *directives*, and a few custom *roles*. Finally, this manual uses a small DSL to describe tactic invocations and commands. Coq objects =========== Our Coq domain define multiple `objects`_. Each object has a *signature* (think *type signature*), followed by an optional body (a description of that object). The following example defines two objects: a variant of the ``simpl`` tactic, and an error that it may raise:: .. tacv:: simpl @pattern at {+ @natural} :name: simpl_at This applies ``simpl`` only to the :n:`{+ @natural}` occurrences of the subterms matching :n:`@pattern` in the current goal. .. exn:: Too few occurrences :undocumented: Objects are automatically collected into indices, and can be linked to using the role version of the object's directive. For example, you could link to the tactic variant above using ``:tacv:`simpl_at```, and to its exception using ``:exn:`Too few occurrences```. Names (link targets) are auto-generated for most simple objects, though they can always be overwritten using a ``:name:`` option, as shown above. - Options, errors, warnings have their name set to their signature, with ``...`` replacing all notation bits. For example, the auto-generated name of ``.. exn:: @qualid is not a module`` is ``... is not a module``, and a link to it would take the form ``:exn:`... is not a module```. - Vernacs (commands) have their name set to the first word of their signature. For example, the auto-generated name of ``Axiom @ident : @term`` is ``Axiom``, and a link to it would take the form ``:cmd:`Axiom```. - Vernac variants, tactic notations, and tactic variants do not have a default name. Most objects should have a body (i.e. a block of indented text following the signature, called β€œcontents” in Sphinx terms). Undocumented objects should have the ``:undocumented:`` flag instead, as shown above. When multiple objects have a single description, they can be grouped into a single object, like this (semicolons can be used to separate the names of the objects; names starting with ``_`` will be omitted from the indexes):: .. cmdv:: Lemma @ident {* @binder } : @type Remark @ident {* @binder } : @type Fact @ident {* @binder } : @type Corollary @ident {* @binder } : @type Proposition @ident {* @binder } : @type :name: Lemma; Remark; Fact; Corollary; Proposition These commands are all synonyms of :n:`Theorem @ident {* @binder } : type`. Notations --------- The signatures of most objects can be written using a succinct DSL for Coq notations (think regular expressions written with a Lispy syntax). A typical signature might look like ``Hint Extern @natural {? @pattern} => @tactic``, which means that the ``Hint Extern`` command takes a number (``natural``), followed by an optional pattern, and a mandatory tactic. The language has the following constructs (the full grammar is in `TacticNotations.g `_): ``@…`` A placeholder (``@ident``, ``@natural``, ``@tactic``\ …) ``{? …}`` an optional block ``{* …}``, ``{+ …}`` an optional (``*``) or mandatory (``+``) block that can be repeated, with repetitions separated by spaces ``{*, …}``, ``{+, …}`` an optional or mandatory repeatable block, with repetitions separated by commas ``{| … | … | … }`` an alternative, indicating than one of multiple constructs can be used ``%{``, ``%}``, ``%|`` an escaped character (rendered without the leading ``%``). In most cases, escaping is not necessary. In particular, the following expressions are all parsed as plain text, and do not need escaping: ``{ xyz }``, ``x |- y``. But the following escapes *are* needed: ``{| a b %| c | d }``, ``all: %{``. (We use ``%`` instead of the usual ``\`` because you'd have to type ``\`` twice in your reStructuredText file.) For more details and corner cases, see `Advanced uses of notations`_ below. .. FIXME document the new subscript support As an exercise, what do the following patterns mean? .. code:: pattern {+, @term {? at {+ @natural}}} generalize {+, @term at {+ @natural} as @ident} fix @ident @natural with {+ (@ident {+ @binder} {? {struct @ident'}} : @type)} Objects ------- Here is the list of all objects of the Coq domain (The symbol :black_nib: indicates an object whose signature can be written using the notations DSL): ``.. attr::`` :black_nib: An attribute. Example:: .. attr:: local ``.. cmd::`` :black_nib: A Rocq command. Example:: .. cmd:: Infix @string := @one_term {? ( {+, @syntax_modifier } ) } {? : @ident } This command is equivalent to :n:`…`. ``.. cmdv::`` :black_nib: A variant of a Rocq command. Example:: .. cmd:: Axiom @ident : @term. This command links :token:`term` to the name :token:`term` as its specification in the global environment. The fact asserted by :token:`term` is thus assumed as a postulate. .. cmdv:: Parameter @ident : @term. This is equivalent to :n:`Axiom @ident : @term`. ``.. exn::`` :black_nib: An error raised by a Rocq command or tactic. This commonly appears nested in the ``.. tacn::`` that raises the exception. Example:: .. tacv:: assert @form by @tactic This tactic applies :n:`@tactic` to solve the subgoals generated by ``assert``. .. exn:: Proof is not complete Raised if :n:`@tactic` does not fully solve the goal. ``.. flag::`` :black_nib: A Rocq flag (i.e. a boolean setting). Example:: .. flag:: Nonrecursive Elimination Schemes Controls whether types declared with the keywords :cmd:`Variant` and :cmd:`Record` get an automatic declaration of induction principles. ``.. opt::`` :black_nib: A Rocq option (a setting with non-boolean value, e.g. a string or numeric value). Example:: .. opt:: Hyps Limit @natural :name Hyps Limit Controls the maximum number of hypotheses displayed in goals after application of a tactic. ``.. prodn::`` A grammar production. Use ``.. prodn`` to document grammar productions instead of Sphinx `production lists `_. prodn displays multiple productions together with alignment similar to ``.. productionlist``, however unlike ``.. productionlist``\ s, this directive accepts notation syntax. Example:: .. prodn:: occ_switch ::= { {? {| + | - } } {* @natural } } term += let: @pattern := @term in @term | second_production The first line defines "occ_switch", which must be unique in the document. The second references and expands the definition of "term", whose main definition is elsewhere in the document. The third form is for continuing the definition of a nonterminal when it has multiple productions. It leaves the first column in the output blank. ``.. table::`` :black_nib: A Rocq table, i.e. a setting that is a set of values. Example:: .. table:: Search Blacklist @string :name: Search Blacklist Controls ... ``.. tacn::`` :black_nib: A tactic, or a tactic notation. Example:: .. tacn:: do @natural @expr :token:`expr` is evaluated to ``v`` which must be a tactic value. … ``.. tacv::`` :black_nib: A variant of a tactic. Example:: .. tacn:: fail This is the always-failing tactic: it does not solve any goal. It is useful for defining other tacticals since it can be caught by :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching tacticals. … .. tacv:: fail @natural The number is the failure level. If no level is specified, it defaults to 0. … ``.. thm::`` A theorem. Example:: .. thm:: Bound on the ceiling function Let :math:`p` be an integer and :math:`c` a rational constant. Then :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`. ``.. warn::`` :black_nib: An warning raised by a Rocq command or tactic.. Do not mistake this for ``.. warning::``; this directive is for warning messages produced by Rocq. Example:: .. warn:: Ambiguous path When the coercion :token:`qualid` is added to the inheritance graph, non valid coercion paths are ignored. Coq directives ============== In addition to the objects above, the ``coqrst`` Sphinx plugin defines the following directives: ``.. rocqtop::`` A reST directive to describe interactions with Rocqtop. Usage:: .. rocqtop:: options… Rocq code to send to rocq top Example:: .. rocqtop:: in reset Print nat. Definition a := 1. The blank line after the directive is required. If you begin a proof, use the ``abort`` option to reset rocq top for the next example. Here is a list of permissible options: - Display options (choose exactly one) - ``all``: Display input and output - ``in``: Display only input - ``out``: Display only output - ``none``: Display neither (useful for setup commands) - Behavior options - ``reset``: Send a ``Reset Initial`` command before running this block - ``fail``: Don't die if a command fails, implies ``warn`` (so no need to put both) - ``warn``: Don't die if a command emits a warning - ``restart``: Send a ``Restart`` command before running this block (only works in proof mode) - ``abort``: Send an ``Abort All`` command after running this block (leaves all pending proofs if any) - ``extra-foo``: if environment variable 'ROCQRST_EXTRA' is set to `all` or to a `,`-separated list containing `foo` this is ignored, otherwise behaves as ``fail`` This is typically used to showcase examples of things outside coq-core or rocq-core. `foo` should be the name of the external requirement, e.g. `stdlib` or `mathcomp`. ``rocqtop``\ 's state is preserved across consecutive ``.. rocqtop::`` blocks of the same document (``rocqrst`` creates a single ``rocqtop`` process per reST source file). Use the ``reset`` option to reset Rocq's state. ``.. rocqdoc::`` A reST directive to display Rocqtop-formatted source code. Usage:: .. rocqdoc:: Rocq code to highlight Example:: .. rocqdoc:: Definition test := 1. ``.. example::`` A reST directive for examples. This behaves like a generic admonition; see http://docutils.sourceforge.net/docs/ref/rst/directives.html#generic-admonition for more details. Optionally, any text immediately following the ``.. example::`` header is used as the example's title. Example:: .. example:: Adding a hint to a database The following adds ``plus_comm`` to the ``plu`` database: .. rocqdoc:: Hint Resolve plus_comm : plu. ``.. inference::`` A reST directive to format inference rules. This also serves as a small illustration of the way to create new Sphinx directives. Usage:: .. inference:: name newline-separated premises -------------------------- conclusion Example:: .. inference:: Prod-Pro \WTEG{T}{s} s \in \Sort \WTE{\Gamma::(x:T)}{U}{\Prop} ----------------------------- \WTEG{\forall~x:T,U}{\Prop} ``.. preamble::`` A reST directive to include a TeX file. Mostly useful to let MathJax know about `\def`\s and `\newcommand`\s. The contents of the TeX file are wrapped in a math environment, as MathJax doesn't process LaTeX definitions otherwise. Usage:: .. preamble:: preamble.tex Coq roles ========= In addition to the objects and directives above, the ``coqrst`` Sphinx plugin defines the following roles: ``:g:`` Rocq code. Use this for Gallina and Ltac snippets:: :g:`apply plus_comm; reflexivity` :g:`Set Printing All.` :g:`forall (x: t), P(x)` ``:n:`` Any text using the notation syntax (``@id``, ``{+, …}``, etc.). Use this to explain tactic equivalences. For example, you might write this:: :n:`generalize @term as @ident` is just like :n:`generalize @term`, but it names the introduced hypothesis :token:`ident`. Note that this example also uses ``:token:``. That's because ``ident`` is defined in the Rocq manual as a grammar production, and ``:token:`` creates a link to that. When referring to a placeholder that happens to be a grammar production, ``:token:`…``` is typically preferable to ``:n:`@…```. ``:production:`` A grammar production not included in a ``prodn`` directive. Useful to informally introduce a production, as part of running text. Example:: :production:`string` indicates a quoted string. You're not likely to use this role very commonly; instead, use a ``prodn`` directive and reference its tokens using ``:token:`…```. ``:gdef:`` Marks the definition of a glossary term inline in the text. Matching :term:`XXX` constructs will link to it. Use the form :gdef:`text ` to display "text" for the definition of "term", such as when "term" must be capitalized or plural for grammatical reasons. The term will also appear in the Glossary Index. Examples:: A :gdef:`prime` number is divisible only by itself and 1. :gdef:`Composite ` numbers are the non-prime numbers. Common mistakes =============== Improper nesting ---------------- DO .. code:: .. cmd:: Foo @bar Foo the first instance of :token:`bar`\ s. .. cmdv:: Foo All Foo all the :token:`bar`\ s in the current context DON'T .. code:: .. cmd:: Foo @bar Foo the first instance of :token:`bar`\ s. .. cmdv:: Foo All Foo all the :token:`bar`\ s in the current context You can set the ``report_undocumented_coq_objects`` setting in ``conf.py`` to ``"info"`` or ``"warning"`` to get a list of all Coq objects without a description. Overusing ``:token:`` --------------------- DO .. code:: This is equivalent to :n:`Axiom @ident : @term`. DON'T .. code:: This is equivalent to ``Axiom`` :token:`ident` : :token:`term`. .. DO .. code:: :n:`power_tac @term [@ltac]` allows :tacn:`ring` and :tacn:`ring_simplify` to recognize … DON'T .. code:: power_tac :n:`@term` [:n:`@ltac`] allows :tacn:`ring` and :tacn:`ring_simplify` to recognize … .. DO .. code:: :n:`name={*; attr}` DON'T .. code:: ``name=``:n:`{*; attr}` Omitting annotations -------------------- DO .. code:: .. tacv:: assert @form as @simple_intropattern DON'T .. code:: .. tacv:: assert form as simple_intropattern Using the ``.. rocqtop::`` directive for syntax highlighting ----------------------------------------------------------- DO .. code:: A tactic of the form: .. rocqdoc:: do [ t1 | … | tn ]. is equivalent to the standard Ltac expression: .. rocqdoc:: first [ t1 | … | tn ]. DON'T .. code:: A tactic of the form: .. rocqtop:: in do [ t1 | … | tn ]. is equivalent to the standard Ltac expression: .. rocqtop:: in first [ t1 | … | tn ]. Overusing plain quotes ---------------------- DO .. code:: The :tacn:`refine` tactic can raise the :exn:`Invalid argument` exception. The term :g:`let a = 1 in a a` is ill-typed. DON'T .. code:: The ``refine`` tactic can raise the ``Invalid argument`` exception. The term ``let a = 1 in a a`` is ill-typed. Plain quotes produce plain text, without highlighting or cross-references. Overusing the ``example`` directive ----------------------------------- DO .. code:: Here is a useful axiom: .. rocqdoc:: Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. DO .. code:: .. example:: Using proof-irrelevance If you assume the axiom above, … DON'T .. code:: Here is a useful axiom: .. example:: .. rocqdoc:: Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. Tips and tricks =============== Nested lemmas ------------- The ``.. rocqtop::`` directive does *not* reset Coq after running its contents. That is, the following will create two nested lemmas (which by default results in a failure):: .. rocqtop:: all Lemma l1: 1 + 1 = 2. .. rocqtop:: all Lemma l2: 2 + 2 <> 1. Add either ``abort`` to the first block or ``reset`` to the second block to avoid nesting lemmas. Abbreviations and macros ------------------------ Substitutions for specially-formatted names (like ``|Cic|``, ``|Ltac|`` and ``|Latex|``), along with some useful LaTeX macros, are defined in a `separate file `_. This file is automatically included in all manual pages. Emacs ----- The ``dev/tools/coqdev.el`` folder contains a convenient Emacs function to quickly insert Sphinx roles and quotes. It takes a single character (one of ``gntm:```), and inserts one of ``:g:``, ``:n:``, ``:t:``, or an arbitrary role, or double quotes. You can also select a region of text, and wrap it in single or double backticks using that function. Use the following snippet to bind it to `F12` in ``rst-mode``:: (with-eval-after-load 'rst (define-key rst-mode-map (kbd "") #'coqdev-sphinx-rst-coq-action)) Advanced uses of notations -------------------------- - Use `%` to escape grammar literal strings that are the same as metasyntax, such as ``{``, ``|``, ``}`` and ``{|``. (While this is optional for ``|`` and ``{ ... }`` outside of ``{| ... }``, always using the escape requires less thought.) - Literals such as ``|-`` and ``||`` don't need to be escaped. - The literal ``%`` shouldn't be escaped. - Don't use the escape for a ``|`` separator in ``{*`` and ``{+``. These should appear as ``{*|`` and ``{+|``. rocq-9.2.0/doc/sphinx/_static/000077500000000000000000000000001516144147600162035ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/_static/RocqNotations.ttf000066400000000000000000001121441516144147600215300ustar00rootroot00000000000000 FFTMt₯Λ•”HGDEF5Ρ‘ˆ*GPOS5ΞN°”@GSUBΜDχ:‘΄ROS/2‰υr¨`cmap{Ψ1¨jcvt :[)v \zfpgmv½DΔ#gasp‘€glyfZ- :tzhead£·Λ,6hheaΣ/d$hmtx a loca“Ίv Ψšmaxpβˆ name‘Ύ5»‰x΅postPε‰Œ0NprepφXΓ» 8#ΜΜ‘pυ3_<υτΙεΎΛΦχλOώ~ξ>Vτώ~ΰΜ`/Y§sτΌΌŠŒΌŠέ2ϊ  ΰP [DAMA Ύ΅[1>ͺ ŸV΅ ττττ§W"Ί^U.(~q‘/#0+)#.1&-‘v-((E 66??-6*-G.66('  .q1m˜,>,$!?$1?$??Y6$; C?½?§.& ½1Sh2-qll(qq˜;‘ŸJ2 2$- Δ€ Δ^Uq/q1m??„r6›©22EO‘m†JJJo‹wwMMM`«ͺ§ώΧώτ\]Zfώώ­ώ°ώžώφώφkGώ~ώœώΛώ½ώώώ - dH ~Ύ   ωυδγΒ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz@?XUTSRQPONMLKJIHGFEDCBA@?>=<;:98765/.-,(&%$#" ,E#F` °&`°&#HH-,E#F#a °&a°&#HH-,E#F`° a °F`°&#HH-,E#F#a° ` °&a° a°&#HH-,E#F`°@a °f`°&#HH-,E#F#a°@` °&a°@a°&#HH-, <<-, E# °ΝD# ΈZQX# °D#Y °νQX# °MD#Y °&QX# ° D#Y!!-, EhD °` E°FvhŠE`D-,± C#Ce -,± C#C -,°(#p±(>°(#p±(E:± -, E°%Ead°PQXED!!Y-, E°C`D-,°C°Ce -, i°@a°‹ ±,ΐŠŒΈb`+ d#da\X°aY-,ŠEŠŠ‡°+°)#D°)zδ-,Ee°,#DE°+#D-,KRXED!!Y-,°%# Šυ°`#νμ-,°%# Šυ°a#νμ-,°%υνμ-, °` <<-, °a <<-,°C°C -,!! d#d‹Έ@b-,!°€QX d#d‹Έ b²@/+Y°`-,!°ΐQX d#d‹ΈUb²€/+Y°`-, d#d‹Έ@b`#!-,E#E`#E`#E`#vh°€b -,°&°&°%°%E#E °&`bch °&aeŠ#DD-, E°TX°@D E°@aD!!Y-,E±0/E#Ea`°`iD-,KQX°/#p°#B!!Y-,KQX °%EiSXD!!Y!!Y-,E°C°`c°`iD-,°/ED-,E# EŠ`D-,E#E`D-,K#QXΉ3ΰ±4 ³34YDD-,°CX°&EŠXdf°`d° `f X!°@Y°aY#XeY°)#D#°)ΰ!!!!!Y-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°% F°%°`#B< XY°%°%°)ΰ°%°%°)ΰ°%°% XY°%°%CH°%°%°`CH!Y!!!!!!!-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°%°%°% F°%°`#B< XY°%°%°)ΰ°) EeD°%°%°)ΰ°%°% XY°%°%CH°%°%°%°%°`CH!Y!!!!!!!-,°% F°%#B°%°%EH!!!!-,°% °%°%CH!!!-,E# E °P X#e#Y#h °@PX!°@Y#XeYŠ`D-,KS#KQZX EŠ`D!!Y-,KTX EŠ`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,°CTX°F+!!!!Y-,°CTX°G+!!!Y-,°CTX°H+!!!!Y-,°CTX°I+!!!Y-, Š#KSŠKQZX#8!!Y-, ŠI°QX°@# Š84!!Y-,F#F`#Fa#  FŠaΈ€bб@@ŠpE`h:-, Š#IdŠ#SX<!Y-,KRX}zY-,°KKTB-,±B±#ˆQ±@ˆSZXΉ ˆTX±BYY-,Eh#KQX# E d°@PX|YhŠ`YD-,°°%°%°#>°#>± ° #eB° #B°#?°#?± °#eB°#B°-@ vn)uodtrdrC)qodpndoBnBia)gedeC)dBcadaBYQ)XBWUdUC)TBSQdRBQBLD)JHdHC)FDdDBCA/B?Bœ* * U*Uœœ*U * U*U*U *U*UTSΈ³ΈKΈRK°P[°ˆ°%S°ˆ°@QZ°ˆ°UZ[X±ŽY…BK°SX° YK°€SX°±BY++++++++t+++s++++++++++++++++++++++++++++°kkυσΦ σ[ύ»[||f|P}fPkr{d}›fk›{}ofk{Ž}¦fTk¦vf³³PP<<::dd_@Ÿ~ΖrϊϋU*ΨW‡!ŒŒ‡£Gxo{΅ͺ9j•Z\Ά.rΣΎ+z4Y*CrrQY§τέ=****b¨ŒϊΎ‚Ίβ –ς"8„¨>ŠN€6  h ˜ Π ϊ  J ¨ ΄ r ΐ  N ˆ Ψ 8p²ΨΐN–κNΎΰ †|Ψl–Ίδ &<ͺ V΄pΠlΔRΠL–δ†ζhF‚ΠhŠβ""\Ό  Μ!>!b""<"β#X#’#Ύ#Μ$ͺ$ΐ$ϊ%T%ž&J&`&€&ζ''8'p'( (),)**2*¨+$+:+^+|+’++Κ+Ψ+ζ,F,X,f,x,ͺ,β,τ--"-0-B-j-†-’-κ. .Z.€.Ξ//\/²00040P0ž0π1V1Μ22Œ2Ά2Μ3"3v34.4Š4ζ5Z5Μ66T6ž6θ727|7ή8@8¦9 9x9δ:P:Ό;@;Δ<<.<|<Β=’M.±/<²»ν2±ά<²»ν2±/<²»ν2²Όό<²»ν233'3#‚rbbMώ³-§ΎM6 @qo u ??ύΞΦνΤν10#.=3#"&54632AfŽ 3 33 3’$:44 44:$€ύά(,,(&,,WmŸ‡ 6@n n@ °Έΐ@ H   ?Ε?Ε/Φ+]_qύήν10#.=##.=Ÿ H B G †0:><<><00:><<><0Δγ0jΉΐ³MΈΐ·LOΈΐ³ MΈΐ΄ LΈΐ³MΈΐ· LpΈ€³MΈΐ³ MΈψ@ M@MΈΐ³ MΈΠ³MΈΐ· L|Έΐ΄ LΈΐ³ M ΈΐΆ M@  Έΐ³ MΈΐ³MΈΐ΄L Έΐ@e My  y!yy  r r??Ν]22/2ν23??έ22ν22ήέ9]νν9]]ήΐΤ]]ν]ή]ΐά]9]ν910++++]+++]+++++++]++++]++733733#3##7##7#537#537#ŠfPf>RgzfPf753.#"#Α?M& V08,!08,!6'r.GO*0% &'B0%=.r' b %5'4,! a\g " !+:'5-!k·ς='3ο΅' M"Έΐ³ M ΈπΆ MΈΰ@ M MΈΐ³MΈΰ³MΈπ@BM" "°""|(―Ώ|(((―Ώ|` p €  55 .°..|44+Έΐ@,H+}―ΏΟ} p}%}1ΐ·Ο111??99//]]]νν]?ν]?ν+ΦΝΦν]ήΝΦ]ν]99//]]ν]ν]10+++++]+++#34632#"&74&#"3264632#"&74&#"326[Y—Yι<45<<54<‘ώp<36<<63<  <kώ#LOOLLOOL*$$**""zLOOLLPPL*##**""Ήβ;)5AΒΉ?ψ@ M%@ M"@ MΈΐ³ M Έΐ@ M9@ M.Έ€³ M.Έΐ³ M-Έΐ@ L9-  &C""y#C?<_<3267'.'326>54&#"m "H#-C-11.96*:>,f& Ύ<#*.f ">.>"0X H((<("6"0\ 24F8`&"F"|$B * "2x.<"Ίd= =ΆnR  Έ€@ H ΰ π  Έ€³H Έΐ· H  ?ΕΦ++]q+_qν10#.== H B:>>>>:B^B‘² @ p Š??ΕΦνήΖ107.5467Πm`9ˆ~‚ˆ9`qφ{΅8LKΰ‰ŠηKL8ΌUB˜² @ p  Š?Ε?Ζ2ήν10%4&'7'>&q`9ˆ‚~ˆ9`mφ|Ό8LKηŠ‰ΰKL8΅.6ΚΎ@Y@<@M<:.'4"'Έΐ@M AB/-;4 ' ?έΐέΕέΖΥΝΤΝ9/ΕΕέΖ2+έΕΕ9=/έΖ2+107'7>7*./7.=3>?"#'.ό ^ #$" %   t   $ "$# ^ Θ "" B  n  $" "$  p D ""(ΜΫ Ήΐ³ MΈΐ@ M@M@M@ MΈΐ³ MΈΐ³ MΈΐ@4 M@M@M R`@ P €   ΟUΟ ?έΐ]ύΝ]ΐ9/]Ν]3ύ2Ν]10++++++++++3533##5#(jj,d~Z[š@z {?ν?ΕήΞΦν107>7.54632~%!&*3'*/1N8ͺ 4 '280#F<,q½ƒ7΅‘?ΕΦΝ10!!qώξ6x‘‘TS_Ήΰ³MΈΰ@He L H M HjΈΰ³MΈΰ@Hez {?νΦύΞ10]++]++++]++%#".54>32T6#  #6ϋ,. !! ./JΕͺ-@v??/Α‡+Α‡}Δ10#3―€~Ά`#·Ρ= #U@4οΡΐŸd d%d$±! !!@e e ?ν?ν9/]Ν]]ΦνΪι/9/ν]]]]10%#"&546324&#"326'#"&54632Ρniinpgino532662350ϋ€  €’ Ÿ£joojkoou''((0ΔΛ0/@@ M a  ee ??νν9ήέύΝ3Ξ10+7'>733!5ΥH(882T{ώˆ*Z f "&ύϊff+½Ξ7%&@c ' c&g! e ?ν?ν2ΦνΖήΦν10!!&654>54&#"'>32²(2 " ώl%9A9%.#@=(i4&F6 † <84 $$f 2TF>84&*"V*(,B)·Γ=0€Ή-ΐ³ M,Έΐ³ M+Έΐ³ MΈΐ³ M Έΐ³ M Έΐ@* M L)c&, c,,21g!))e! g ?ν2?9/ν9=/ν2ΦΖΦ]ύΞΤν310+++++++".'732654&+532>54&#"'>32Υ3/( I3?3N<&.&)$#E,Y84M2*#05:ZI g 6(1'f"'Z%/@%%DN6+H5ΔΫ00@ ae  ??9/93ν22Φ2έ22ύΝ31033##5!5>7&%" Œ{CC{ώώ7!##".'732>A3^L <Υ|z>\=2.% D3$/ +T‘Kf Fh^+I6 f  .ΌΗ8->@&c`p/+cc Έΐ@ H .e&g% g ?ν?ν9νΦ+ννή]νΔ107"32>54&'2#"&54>3>ρ( # *$6K00J3hm5bŠT(L@/ $ο  5*$/3f 6H($J>'‰ZŠ^0i!4' 1ΔΕ0)Άa cΈΐ@ H ee ??ννΦ+έύήν10>7!5!„$3<ώό”@9+<@Œ|.f^pŽ’P&ΆΟ>+7ύ΅6@ M4Έ€³ M2Έΐ@ M0@ M/Έΐ³ M/Έΰ³ M.Έΐ΄ L,ΈΐΆ M ,Έΐ³ MΈΰ@ M @ M M5Έΐ³ M/Έΐ΄ L#Έΐ³M#ΈΐΆ M#"Έΐ@ M"2#dΈΐ³ MΈΐ@& H95d9//d&dP82##),g)g ?ν?ν9/9Φ]νΠι/Φ]νΦ++ν910]+]++++++++]++++++++#".5467.54>324.'326">54&Ύ*-9/3R2 *@&0R D&B4"Xώ€8(*,$$",8"$-»Ι9*@@%))c c@  ,&c 0@+e&g% g?ν?ν9νΦ]νΔΪ]ι/ι/10267>54.#"".54>32#'267*  # ,$6L01J2hn4a‰TP~' 4*&02f 6F*$J>&Œ|ZŒ^0jDH‘ Tλ#".54>32#".54>32T6#  #66#  #6’,.    .ώ¨,. "" .vΒT2##".54>32>7.54632T6#  #6ή%!&*3'*/1N8Ϊ,. "" .ώ 4 &280"F<,-!ΟΣ*@??9=/999Βήΐ910% %-€"ώθ"ώ€2‘lmml’(ȅ!@ UU£?ύΦνΦΐή2ΐ210!!!!(€ώ\€ώ\Žf\f(!ΛΣ.@??9=/9999ΦΐΞ910%'-7Λώ€#ώη#€Γ’lmml‘E·²=01@22q'''1,u" g?ύΒ?ύΖΖή]νήΕήΝ107&5467>54&#"'>32#".54>32¦*"(* <#"#^.9J*#(##3 € (H*^.80*$$&š&,  zΤz5EZΉ>ΐ³M8Έΐ@M!@M!8 M @ MΈΰ³ MΈΐ@M: M:@ M Έΐ@ MŸ @M@M@M MΈΐ³MΈΐ@ M@ LΈΰ΄LΈΐ³MΈΐ³MΈΐ΄LΈΰ@rL@ M@ M@ M@ M M MP==@>>y 505`55GO6_66y+!GŸ|+F@Py=@APAAy &> = = &}0 }&/ύ]Ζ?ν99//999ν]ν]]Φν]Ζ9/ν]Φ]ν]22]10++++++++++++++++++]++++++++++%#".54>3254&#"3267#".54>323275.#"ΤG&A0$9*0.!;+3U?/6 BrS0)FZ2)H6 Ε 8 1O9*J7 &5FuYFlI& W$Y“ol“['6W>ž( Θ" Δλ0 DΉ ΰ@' L L   H ????9/9νΖΖ910++'##6733.g₯€,Z*†,W)ς  y <Έ,ˆˆώΞ²τ$>>> >>>6½Υ7#0T@'F Fp€20D Έΐ@ H   1#H$$,J J ?ν?ν9/ν9=/Φ^]+ν2ή]]νΤν10%#"&'>32%32>54&#'2654.#"Υ&AY3)X+#T)FX2+$?-ώά (90/0  €8K- Y /:,DN)¨#-'f)$Ž·Υ=:Ά`  Έΐ@H!F J JJJ ?νΥν?νΥνΦνΦ+2Ζ]210"&54>32.#"3267(ƒŠ*Kg=!5( A*7+IS0?YI¨›MxS+ b1R=jq a6½Ω7!6@ F#DΈΐ@ H" HH ?ν?νΦ^]+ν}/ή]ν107232>54.#"#"&'>32± *9# 4)(+Li?!?$*J =eF') 8M.(L:#ΞVyL#\ $Mw?ΔΜ0 Q@ 0  D 0 H@MΈΐ³MΈΐ@ M H H?ν?ν9/+++νΦ]ν2Φ]ΖΖ10!#3#!?wόΫΫ<lfŒff?ΔΊ0 J@/@ M@€ D@ M0 H H?ν??9/νΦ]+ν2Φ^]]+Δ10!!3#?{ΰΰ<lf–fώφ·Π=#4@ %F$ D0  !JJ ??ν?ύΖ?9//]νΦνΞ10"326753#".54>32.8,<'FD  {]B:]B$*Hb8$9* @ 9O0oiβώΛ)QyPOyR) b-ΔΗ0 ;@  D  DΈΐ@ H  H@???9/]ν?Φ+ν2ήν210###335Η{€{{€0ύ”ώξlττ6ΔΏ0 .Ά  DΈΐ@ H H H?ν2?ν2Φ+ΐέύάΐ1053#5!#36‡‡‰††73^ )27{{0+$ ‹'29@9.<$PNBώδlώώDDBDLN$NX^,GΔΜ0,Ήΐ· HDΈΐ@ HH?ν?ή+νΖ+10!3!Μώ{| <lύϊΔέ0o΅ MΈΐ@ M0 MΈΰ@[ M@ L?@ M? M M L @ M M @ M @ L @ L?  @M L M MΈΰ@M@ M M L@ LΈΐ@ M@ M M M?Έ€³ MΈΐ@1 M@ M@ M/?@ M DDΈΐ@Mo  ??9/9??9/9|ή]]+νΡΙ/Φν9=/9999ΩΙ/10+]++]++]+++]++++++++++]++++++++]+]]+++]++>73###>7‘ f qLZIq 0BLN $PH@Rš–šPβώϊώL€’˜B.ΔΖ0S@ @ M Έΐ@ M?/ ?  DDΈΐ@ H  ????99Φ+ν2ήν]210]+]+.'#33c*c9oc85-o54.#"4632#"&˜& '& &}vimrtjmsϊ-O:"";N--O:"";N- ££  ££6ΑΨ3?@ F`D Έΐ@ H  HJ?ν?99//ν?Φ+ν2ή]ν102+#>"32654&ΰv‚ƒx,{-., ' 2;<;3anocΡckΘ/96-jΩŠ&/@F (F' J J  "J?ν?3νένΦνΪ2ι/9104632.'.732>54.#"vimrZU UJuw QW}& '& &G ££ Œ‘! XKFŸ‰-N;"";N--O:"";N6Αι3$Y@D` p €  &F`p€&!DDΈΐ@ H%H!!  J?ν????9/ν2Φ+ννή]νή]2ν2102#.'##>4&#"326Φ5V>!,3&$! =#@{+,(|<1 ?832M46X?EE54.'.54632.#"#"&'7θ) "*<1 qc9U$=(b'?5"qsM\$K  (;,Wb_G -C3W_!dΔΫ0@DH???ν2ΦέύΝ10###5Ϋ£|£0fύϊf'ΎΝ6/@ D`pDΈΐ@ H J ?ν?3Φ+νή]ν10".5332>53ψX6‹ώ}'5 !5'‚ώu6X>! Δθ0ƒ@ MMHΈΰ@ M$ M+Έΰ³MΈψ@0LG @ M   /  ???3??9]ΖΞ]910+]++]+]+]++.'3>73Ί60& ‚!  #-67( r f,0f r T8DN*4x|~”@Fš  L<~|x4 LJ> Δι0f΅ MΈΰ³MΈΰ³ M Έΰ@'M    ??9??//Ζ99=//99Ζ10++++.'#>7373d7:… '/4’…bg|ž4-" <4|><~4LX\,$ΖΖώή*^ZL Δθ0>@!D€      ???9??9/]Ξ2ν9=/Ν210>73#5.'3ώ  &*0|7S&„8FNP 4`^\2μμ`ΊfH–.ΔΖ0f΅@ MΈΰΆ MΈΐ@ HΈΐ΄ H Έΐ@ H Έΐ@ HHH?ν?ν?Ν/+]Ζ+Ζ+99Ξ+]10++!!5>7#5!½+H>7 ώh2>I,ξ‚ΪBtj`0fH*`l~JfqJ†ͺ/@_@_@ nrr?ν?νΦνΞ]]Ξ]]10!#3!q  ώλͺ`ύ``1JΗͺ*@v???/ΖΑ‡+‡}Δ103#1~ͺό mJƒͺ/@n@@ Prr?ν?νΦ]ΐΞ]ή]ν210!53#5!ƒώκ  Ά` `Dλ°)@r?ύΝ29=/9910%''3λo~~pΉiz6ΪΪ66Δμ0@ U??νΖΖ10!!δώ0l˜‘sS΅}?ΕΦΕ10'՞-SoCT,Ήρ.S@ $QS0, SΈΐ@$ H/_oWP"`"""@W(@ M(W ?ν+?ν]9/]ν]Φ+νΔήνν10]72675.#"2#".54>3254&#"'>ϋ& "$0:M.jB-I4 6F&0%,6#ATfl  Š2F,ώθ$<**8""0 d >™Φ[ [@ @ M @ M@ MΈΐ@ MS` p  !QQΈΐ@ H UW W?ν???νΥνΦ+ννή]ν10++++%4&#"3267#"&'7>32Y+,' 08}:T60d"{0.F/’BF @L8\@" ”κ "BZ,ρ5@0@`p!SΈΐ@ H W W ?ν?νΦ+νή]Ζ10]74>32.#"3267#"., BeF*D#1&,;$IX?J2HgBϊ2ZD& b $4BJ f &BZ™[ `@@Δ@ΐ@ΐ Έΐ³ MΈΐ@ M@ MQSU W W?ν?νΥν??Φνήν210+++]q]q]q73267.#"#"&5463257™/4$,("b/nq_]0{’>P Fώή ‚pt„ ΦΡρ%\Ήΐ@7LS ?  '% Sp& @MO _  U@W0  W ?ν]?ύ]Ζ9/]ν]+Φ]ν2ή]Ζν10+74>32!3267#".%4.#"&>P*hlώΟL<%C H-<_C$; "# φ>^> zv .6h >Zl"$$ŸμUVΉΐΆ MPΈΐ@) MP  Q`pOU W U ?ν?ν?ν?Φ]]έ2ν2Ζ]Ξ10]+]+#5354>32.#"3#‹gg!8H&'R!EΑΑ`pf:J.d&fώ!ΆΆ> 'GΉΐ@'LQQ`  )S`"p""(W W% @W?ύ]Ζ?ν9/νΦ]νΦ]νν10+32675.#"#"&'732>=#"&54632ž*-# lo{,Q%@0 * +\_€nMZX:= βώ½sn h # tgtr?ŸΉUB@Q@ ` p  QQΈΐ@ H W ????ν??}/Φ+νΠνή]ν107>32#54&#"?{*4F*{*! a‘δ 9O0ώχωB:ώ–$žΣV LΉψ@. MQp?!! !`!T `pWUX ?ύήν?ύΖ/]ν]ά]]]ύΝ10+#"&54632#".=#533267. -- .·&C0A'‚ύ$0$**$&**ύ’6L0fώά*(1O₯M@ MQ Έΐ@! H!T @PpUX W?ύΖ?ύήν/]νή+]ύΠΝ10+%#"&'73265#5!'#"&546321C'0R&&G"Ύ9. -- .9M/h%2Wf‡$**$%**?ŸηUQ@ @`0 QΈΐ@ H0p  ??9??/]3Φ+ν22]Ζ]2107>73#.'#7»%# ”.11:8/ ',-||»/2/684CHH?=7ή‘$œΣX6@!`p? Q P ` p   U W?ύΖ?ν?Φ]ΥνΞ]]10#"&5#533267Σ"1UN‚ύ&%2D f`fώ0" Χθ'„@^+@M@M/?_ŸίοR@M/?OΟR_) 0@R€(W" % W ?ν3??9/?νΦ]ν]ή]ν]+9/ν]++10_]]2#4.#"#54&#"#>32>W'2 d  dd'L).θ0J0ώζ ".^l0&ώŽΔ  ? Ήκ-Ά QQΈΐ@ H 0W ?ν]??Φ+νήν10>32#54&#"#?!a98J+{.{Ρ 9O0ώχωB:ώΨς&@S@ M!S W W?ν?νΦνή+ν10%#".54>3232654&#"Ψ :Q22Q; !;R01Q; ώΒ-201-201ό8\B$$B\86\@$$@\8>NN>@LL?·Υ= 6@S` p  QQΈΐ@ HW  W?ν??νΦ+ννή]ν104&#"#3267#"'#>32X23 (,*}.F./2{"c0mtD>Rώώ FF6\@$°l „·Ά= !5@QQ`p#Sp  "UW W ?ν??ύΦνΦ]νή]νν103267"&#"4>32#5#".œ+,% 33}9U630+{3.F/DBF R:6Z@$ ύ”² "@\Y Λκ!³Q Έΐ@ H W ??νΦ+ύΝ10.#"#>32΅ !" 2|1gE %*+dώ’Έ6Ίρ1LΉ/ΐ@ MS &&Έΐ@ H&3S .Έΐ@ H.2!W+W ?ν?ν99Φ+Φνή+]νΔ10+72654.'.54>32.#"#"&'7δ-0#8.1L5.OH-/!!:/3R<=V#Ol   0&4* h "2&4& h$ΔΨ0fΉΐ@@ M 0€@M@ Mo ` QP`pW U ?3έΕν2?νΦ]έ2ν2]Ξ^]]++Ζ]+10#53573#32>7#".5kk{ΕΕ "O%+B.@fvŠfΎ  j (J:; Άλ2@ Q Q Έΐ@ H   W?ν??Φ]+νή]ν10%#".533273Ά"a9:J+{-|$ :P0φ@@pζεPΉΰ³MΈΐ³ M Έΰ³ MΈΰ΄ LΈΰ@ L   ???ΒΞ910+++++7.'3>73Β-]*   }*f-YοŽ&VWR""RWV&ŽοY ιε(@Ή(ΠΆ M`('Έΐ³M'ΈΠ³ M!Έΐ@ M@MΈΐ³MΈΐ³ MΈΐ@ M@MΈΐ³ MΈΐ@ M M Έΐ³ M Έΐ³ M Έΐ³M Έΐ@ M@MΈΐ³MΈΐ³MΈ ³MΈΐ΄ LΈΐ΄ LΈΐ³MΈΐ@> M(`$$  ) %`%%*@ M0)(%   ??9/9??Ζ]+Ζ]9///q33Ζ333Ζ]310+++++++++++++++++++++++]+%.'#.'3>73>73B   ] i  Y  i '415 324 ,ky‚DW¦X&A;77;A&.TSS-‰ς[αε)@     ????/Ζ/Ζ91073#.'#>7'3ώ`}˜.*" €60}'+/₯R“βAB<3P (L/=?>δ»Ψ9"/@"Q$ #Q   ??έΖ?/νΖΦν9]10#"&'73267.'3>7Ψ#&+%-7%3$, ,X$€  9Byt7(:% g 0!Xγ‰%TTQ##QST&C΄εW΅Έΐ΅ HΈΐ· HΈΐ@ H@Pp U U?ν??ν?Ν/]/+99Ζ+Ξ+]103!5>7#5!ͺ4==ήώ664Β]‹?NU$fK&PMFf?J΅ͺ$7@"n n%r rr ?ν?ν9/ν9=/ή2ήύάΐΠν107;#"&=4&+5326=46;#"»6/ ]hZE66EZh] /ω D@q*&`NJ“*+`+)”JN`%+q@D½J9ͺ(@€ΰ_ @??ΖΖ]]]2103#½||ͺό ?J΅ͺ(C@%(@ M@ Mn&n* )r !r r ?ν?ν9/ν9=/ΖΖή2ΦύΠν10++%.=4&+532;#"+5326=46960 \g-=%77%=-g\ 0ϋ D@q*&`&9%“*+`+)”%9&`%+q@DηW@  ƒ?ΔέΞΤΕΦΔ]10%".#"'>3232>7Y/,) [!2#/,( ["1ž8.60§ΏM5 #@q ou  ??_]ύΞΦνΤν1074>73#4632#"&³fŽ 3 33 3c$944 449$€$'++''++.”Η`![Ήΐ@2 M #QQS 0P"W" W??έ2ύΖ9/ύ2ΕΦ]νΤν]Τν]Φ]Ζ10+746753.#"3267#5..Y`|-/$S@ES<2|0F-όT|€| h @<<@j ~‚ *7#5354>32.#"κ””ιώ MM4K/#?!$$f&&$fH|2f4BZ6b * βΪ)Ϋ΅%@MΈΰ³MΈΘ³ MΈΐ΄ LΈΰ³MΈΐ@ L@ M M @ L M@ LΈΐ³ MΈΐ@ M@ M M@ MΈΐ΄ L Έΐ@/ L@ M@ M P„$„*+ '„*!„§§??ήνήνήΖ9/ήΐύά]ν]ήΐ10++++++++++++++++++++27'#"&''7&547'764&#"326ϋ,&BS@@TB''BS@@TB$v++++ͺ?Q>$,,$>R@  ?Q>"..">R@°&((&&(( Δθ0!…Ή ΰ@E MD# !!  "#D" ss ????9/93ή2ν2ν2?Φν9=////////993333Φν10+%##5#535#53.'36733#3ΐ‡|ˆˆˆe)&! „3$G% #'^‡‡,hhT>T"LJH@‚HŽ|FLL"T>½J9ͺ$@ n?Ε??ΕΖΦ2ύ2ΦΖ1073#3#½||||¬ώž`ώž1ŒΑh4D„΅'@ M Έΰ@ M=@L5Έΐ@>LF.F5=/@?@@d((F#F8d0044E&5= =5& g1 g?ύΖ?ύΖ9////Ζ]Φ]νΤνΞΦ]ν]99ήν10++++732654&'.5467.54632.#"#"&'>54.R$$(!#%-#=. &d^(V#!=()*₯ d[E`œ 5- 5  &2#$@$,EMb  0q&8-#KG)(SΆ€>  @ 0 ŸŸ?Ν?ΝΦ]έήΝ107"&546323"&54632˜))**¬))))Ά$ $$ $$ $$ $έξ1E‰ΉDΰ³ MCΈΰ³ M?Έΰ@G L: MO94 M7?(_(((G@AF€ €O 0  <2€-<€# ?ν?ν99//]]ννΦύΦ]νή]ν99//9910+]++++%#".54>32.#"3267%4>32#".2>54.#"G%++#  !  ώγ&?Q,+R?&&?R+,Q?&α8-,98--8‹#-.$6( %:=\==\==[==[w.D,+C..C+,D.hG•­ +l@ )@M @MΈΐ³MΈΐ³ MΈΐ@* M!…`-) „0`p,Ÿ }°(%} ?ύΒ/]ν9ν]Φ]νΔή]ν210+++++%2635.#"2#"&54>3254&#"'> ( +:#N4FQ)6 %2 C”F$2 Κ 2>*  N 2*ΓΚ [@ _y R_yΈΐ@ H     ??99=//99=//ή+ΡΙύ]ών]ΩΙΩΙΡΙ10'%'ΊA^^?ŠOB]]@ˆΚ(§§*ΡΟ(§§*Ρ-Yΐ›@ yrƒ?ύΕΦέν10%#5!5!ΐiώΦ“ZΪfq½ƒ7!!qώξ6xέξ1EψΉDΰΆ MDC?Έΰ@! L:@ M: M4 MK4`M@MΈΐ³MΈΐ@tM@M@M@ M‚ @M_  @Hϋ δ ? O  7(?(_(((G‚@HAF€<2€-€/?<€# ?ύώqν?ν99//ν3ΦύΦ+νq2/23ή]ύή]]]+qν+Β2/ι/2/10+++++++]++++]+7#5>32#./32654&#"4>32#".2>54.#"ά6"97(  9  $  Γ&?Q,+R?&&?R+,Q?&α8-,98--8ΞMξ,*0/%2 J=\==\==[==[w.D,+C..C+,D.lΞŒ&Άs“?νΦΝ10!!l ώΰ&XloŒ…@||  }}?ύήνΦύήύΖ102#"&5462654&#"ό5&&5BNP@ „$4 4$HB@Jΐ(γΜ}Ήΐ³ MΈΐ@ Mp €  ΰ  Rp€pΈΐ@& Mp€Up €  @ L@ / ?  U?ύΦ]]+έ]2ύ2Ν]+?Φ]Πέ]2ύ]2έ]ΐ10++7!!3533##5#(€ώ\jjIf’œœfqD‚°7@„„ | °ΐ}t?ύΞ9/]99ν2ΦνΖήΦν103!5467>54&#"'>32y. Œώ/-,.H(F;B(4 R,F& D">qA€³*ί@ "@ M!@ M Έΐ³MΈΐ³MΈΐ@ M@ M(Έΐ³M(Έΐ³M(Έΰ³M(Έΐ³ M(Έΰ³ M(Έΐ@O L@L@M L@ L M―@M „?„,'+($}}, }t?ύΞ9=///ννΞΦΖΪι/Ξ2ΐ/]ν10+]+++++++++++++++++72654+532654#"'>32#"&'7η ?%%'("C $1 $:*E*”$IF%! -* O ˜‘sS΅}?ΝΦΕ10%'7s-žυTCo;ΌΆ87@ Q  °  QΈΐ@ H W ??ν??Φ+2ν2ή]ν1032673#"&'#Ά  | ^30{8$, rώ:  &T|nΗ†>@) 0 ΐ Π ΰ  R 0ΐΠΰR r?ν??9/ΦΤύ]Φν]107.54>32#.#¬LM#A\90e&e 0fό\V0J4 όώ°ύN‘‘TS%#".54>32T6#  #6ϋ,. !! .ŸœgX@   ?ΥΖ?ΦάΕ10#"'73254/>73,!!,-# ")$P . ' ? $ H¦¬;@!@M @L  yys   ?9/999ν2ΦΖύύΕ210++7535'>733Šd%&FMRHQ   N&ώνQJF§dΉ ΐ³M Έΐ³M Έΐ³M Έΐ³M Έΐ³MΈΐ³MΈΐ@M_„„@  ttž?ύΦνΦ]ύΦν]10+++++++%#".54>324&#"326§.@''@..@''@.f%#"'&##%ω*B..B**D..D*+11+)002*ΓΚ 8@         ?Δ?ΔΖ9///999ΥΔ10%'7'7'7'7;A^^?Šώ±B]]@ˆ*(¨§)ΠΠ(¨§)ΠΑο3  ΣΉΐ³MΈΐ³M Έΰ³M Έΐ³M Έΰ³ MΈΰ΄LΈΐ³ MΈΐ³MΈΐ@L M@ L  ―"@"! !!  !   ŒŽ Ž?ν2?Ε2ΕΥΖ?ν????99//9ΦΤν]ΖΦΥ]2ν2Τ‡+‡}Δ10++++++++++%3##5#5>7>73#53#Λ$$P|- ώŸ"2?Uf 3EώΓd=»”?''-+L/3ϊ– ώΘ)ύ•kΑλ3(,o@A @M M*),+*+,―)*)*). |.+-##$-%(-",+ )#Œ"™š ?ν?ύΖ?ν???9ΦΤν]ΒΦΦνΠ‡+Α‡}Δ10++!#&4546?>54#"'>32>73#5%#λΡ)  ): '= $ώ„"2?U«ώΓd=? #&   5(*" ξϊ– yύ•k ½ο7(5:>’@U+ M(@M@M<>=>―;<;<;@ |  @=?(?€ %€  ?>= < ;6:,0/ 5). €?ν?ν2?Υ2ΥΖ????9=///ννΤΖΒ9///93ν2Π‡+‡}Δ10+++32654+532654&#"'>32#"&'3##5#5>73# '; ( 840 *"-3Ώ$$P|-  3WώΓd=z  :  6 ( , †”@&&.*L0@(ύ–j2ƒΒq2@!0@‚‚ 0`pΈ?ν?νΦ]ύΦν]10!'!22ώΤ}ξύ2Šύv$žΣV #"&54632#".=#533267. -- .·&C0A'‚ύ$0$**$&**ύ’6L0fώά*(- T*e@ a,$@,,Έΐ@ H  0QΈΐ@ H+*#Ÿ   ???99//9??ΔΦ+ν]22/2/3+Τ]ΤΕΦν10.'#3>73.7>7 $&rr ‚ *3$:-"  E`$PNBώδlώώDDBDJP("RXX&Ί "4,(2X0   ŸΖU@ @L@LΈΐ@M 0@€Έθ@CMŸΏ@ H!/?Oo`p€/O_ Ÿ ????99?ΔΦΥΦ]]ν]qΦ+]Ε+Πν]q10+++.'#33'>54&'{WK  XώΔ  E`4^^b6ώxj&Z^`,jύ–΄&.($(F& č1g΅Ÿ?ΕΦΕ10#51OgΪΪ€»P9Ά ’?ΕΦήΝ103#"&'52>5ξ_=8# 80.<  £MQΆ Š?ΔΦΥΞ10%#&67mB>,€JR<*(Δ€/P΅Ÿ?ΕΦΕ10#5/MP¬¬^B‘² 7.5467Πm`9ˆ~‚ˆ9`qφ{΅8LKΰ‰ŠηKL8ΌUB˜² %4&'7'>&q`9ˆ‚~ˆ9`mφ|Ό8LKηŠ‰ΰKL8΅q½ƒ7!!qώξ6x/JΕͺ#3―€~Ά`zΤz5E%#".54>3254&#"3267#".54>323275.#"ΤG&A0$9*0.!;+3U?/6 BrS0)FZ2)H6 Ε 8 1O9*J7 &5FuYFlI& W$Y“ol“['6W>ž( Θ"qJ†ͺ!#3!q  ώλͺ`ύ``1JΗͺ3#1~ͺό mJƒͺ!53#5!ƒώκ  Ά` `?J΅ͺ$7;#"&=4&+5326=46;#"»6/ ]hZE66EZh] /ω D@q*&`NJ“*+`+)”JN`%+q@D?J΅ͺ(%.=4&+532;#"+5326=46960 \g-=%77%=-g\ 0ϋ D@q*&`&9%“*+`+)”%9&`%+q@D„#|Ρ%'7![e““eϊ¦0ΦΦ.rk‚‰%#".54>32‚#3 2##2 3#ϊ3((34((46ΜΏ(!!6‰ώw(\Μτ(!!τώ (\›#“Ρ7'7›e““e[’.ΦΦ0¦©ΏO5 74>73#4632#"&΅fŽ 3 33 3c$944 449$€$'++''++2*ΓΚ '%'ΊA^^?ŠOB]]@ˆΚ(§§*ΡΟ(§§*Ρ2*ΓΚ %'7'7'7'7;A^^?Šώ±B]]@ˆ*(¨§)ΠΠ(¨§)ΠEΌ²8 23267#".54>5'4632#".Q*"  * <#"#^.9J*#(##3 K (I  ^/7/'#"$š',  O ͺT@ ŸŸ?Ε?ΕΦΥΦΕ10/'>l6zgl6zTˆ,pDˆ,p‘^V–#+@‚Ο‚$$ !†?ΥήύΦνΦΕΦύΦ]ν10'7#".54>324&#"326R˜‘#    8  T8.Lΰ" "   m‘‡c >@%°o0 JJΟίPJ‹J ‹?ν?νήΕΦ]]ύΦνΤ]]]Ν107#"&54632#"&54632%3#ί"!!"¨""""ώώθθΚ~F†’nb @ J  J ‹?νήΕΦΝΤν10%#"&54632'3#3""""­θθΚ~GJx©|-@J   JJ‹ J‹·?Ε?ν?νΦνΤΕΦ]ν10'4632#"&'4632#"&Εk9xΈ"!!"ν"!!"|˜*ˆ’Jx©|7@!J―ΏJ °ΰJ‹J ‹·?Ε?ν?νΤ]ΕΦύΦ]ν10'7#"&54632#"&54632tx8jr!!!!ν""""Bˆ*˜ΜJ©s JΉΐ΄MΈΐ@"!H J―ΏίJ΄J‹J ‹?ν?ν?ΕΕΕΦύΦ]νΤ+Δ10+7#"&54632#"&54632%77Ό!!!!ν""""ώΞ,UW-„Ίj4@@4ro’…b>Ήΐ³ MΈΰ@ M /?  ˜?ΕήέΞήήΕήΝ]ήΝ10++%#".#"'>323267'3#…  1  Οθθθ  (   \H‹iF΅†?ΝήΝ10%'7iΓΎμ>>Zw}F·†?έΝΝΦΕ10%''7}&\^&„η9669_w}F@ ††?έΕ?ΦΕ107'77ϋ„&^\&`8668M§W C@*JOOJ@  †JΐΠΈ JΐΠΈ?]ν?]ν?ΕΦ]νΤqΕ]Τ]ν10%4632#"&'4632#"&7'5"!!"θ""""“V-^ΥœP5EM§W K@2 J//?O―ΏOJ@†JΐΠΈJΐ Π  Έ?]ν?]ν?ΕΦ]νΤΕ]Τ]qν107#"&54632#"&54632''7Ώ"!!"θ""""_]-UΥ(E5PM§W j@JJί   O _   O_J@P`°ΐ†Ÿ†JΐΠΈJΐ Π  Έ?]ν?]ν?έΕ]?Φ]qνΤΕ]Φ]]]ν107#"&54632#"&54632%77Ώ"!!"θ""""ώύ%1/'VΥ:.##.N™Χ[,<@@&-F #@#`#p##>F7Fp=2W :J(W ?ν?ν9/νΦ]νΤΕνΦ]Δν1074>7.54>3:63#"#".%4.'326 5+$)?,($! #R&  -!;F9Q12Q; :$#5**3€8:88*4$Z "&hH6Z> 32+3"32654&Π{CCCC*+)lwxn"Θ– '300XXcHbώVabWGc― -+)"`•F@    ??ήΕΦΔ107".'73267ϊ6*\""\*6!0##0 «‹Ii΅“?ΝήΝ10'7IGW1KΐΘͺeλ &6%'##6733.>7.546323#"&5473g₯€,Z*†,W)ς  y ώ§ $'B3N #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@ " ""(P"ώ, <.0§eλ &6%'##6733..546323#"&5473g₯€,Z*†,W)ς  y η3B'$ ά #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@0"P("" "ώ <.0ώΧeλ *:%'##6733.%'>7.546323#"&5473g₯€,Z*†,W)ς  y ώάl;Ί " ?0" #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@¬ͺ, €" ""(P"ώ, <.0ώτeλ *:%'##6733.%'.546323#"&5473g₯€,Z*†,W)ς  y ώΫl;.0> " !– #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@¬ͺ, ¦ R("" "ώ <.0eλ *:%'##6733.''7>7.546323#"&5473g₯€,Z*†,W)ς  y ‘~;lώφ! "!@/ή #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@v ,ͺΆ" ""(P"ώ, <.0eλ *:%'##6733.''7.546323#"&5473g₯€,Z*†,W)ς  y ‘;l§0?!" !| #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@v ,ͺά R("" "ώ <.0\=λ· ,>N'##6733.'.#"#>32>7.546323#"&5473g₯€,Z*†,W)ς  y Τ   E'11'Ρ   ""] #8=_·-‡ˆώΟ²σ#?=>!!>=?s%5##5%    !ώ- ;.0]=λ· ,>N'##6733.'.#"#>32.546323#"&5473g₯€,Z*†,W)ς  y Σ   E'11'h#"   σ #8=_·-‡ˆώΟ²σ#?=>!!>=?s%5##5%€!    ώ ;.0ZeǏ +###335>7.546323#"&5473Η{€{{€ώ $'B3§ #8=_zύ–ώπjττ€" ""(P"ώ, <.0feǏ +###335.546323#"&5473Η{€{{€ώ3B'$ & #8=_zύ–ώπjττΚ"P("" "ώ <.0ώeǏ /###335%'>7.546323#"&5473Η{€{{€ώLl;Ί " ?0r #8=_zύ–ώπjττͺ, €" ""(P"ώ, <.0ώ­eǏ /###335%'.546323#"&5473Η{€{{€ώKl;.0> " !ζ #8=_zύ–ώπjττͺ, ¦ R("" "ώ <.0ώ°eǏ /###335'7>7.546323#"&5473Η{€{{€ώ»~;lώφ! "!@/R #8=_zύ–ώπjττ$ ,ͺΆ" ""(P"ώ, <.0ώžeǏ /###335'7.546323#"&5473Η{€{{€ώΆ;l§0?!" !υ #8=_zύ–ώπjττ$ ,ͺά R("" "ώ <.0ώφ=Η· !3C###335.#"#>32>7.546323#"&5473Η{€{{€ώ}   E'11'Ρ   ""Μ #8=_Rύ•ώοkττ(%5##5%    !ώ- ;.0ώφ=Η· !3C###335.#"#>32.546323#"&5473Η{€{{€ώ}   E'11'h#"   c #8=_Rύ•ώοkττ(%5##5%€!    ώ ;.0keλG>7.546323#"&54734>323#5>54.#"#53.• $'B3– #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Φ" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.D3B'$ E #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%°"P("" "ώ <.0JjDDjJB~7.546323#"&54734>323#5>54.#"#53.zl;Ί " ?0„ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Œͺ, €" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.zl;.0> " !χ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Œͺ, ¦ R("" "ώ <.0JjDDjJB~7.546323#"&54734>323#5>54.#"#53."~;lώφ! "!@/7 #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%V ,ͺΆ" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.!;l§0?!" !Φ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%V ,ͺά R("" "ώ <.0JjDDjJB~32>7.546323#"&54734>323#5>54.#"#53..   E'11'Ρ   ""Γ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%*%5##5%    !ώ- ;.0KjCCjKB~32.546323#"&54734>323#5>54.#"#53./   E'11'h#"   [ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%*%5##5%€!    ώ ;.0KjCCjKB~""><@ύό <.0-oΗ… ###3353#"&5473Η{€{{€" #8=_„ύ–ώπjττύb <.0 hλŒ73#"&54734>323#5>54.#"#53.* #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%" :.0ŽLjB BjLB~?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a£„…½–θ†Ž‹©€ŠΪƒ“ςσ—ˆΓήρžͺυτφ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNuni00A0uni00AD SF030000.001i.loclkgreenlandic.casenapostrophe.case caron.alt commaaccentrevcommaaccentcaron.alt.short Parenleft ParenrightHyphenSlashAt Bracketleft Backslash Bracketright Braceleft Braceright GuilsinglleftBulletEndashEmdashGuilsinglright Exclamdown GuillemotleftGuillemotright Questiondown double_grave ring_acutedieresis_macron dot_macrondieresis_gravedieresis_acutedieresis_breve tilde_macron acute.asccircumflex.asc caron.ascdieresis_grave.capdieresis_acute.capdieresis_breve.capafii10066.locltengeroublekratka tonos.cap uni1F88.alt uni1F89.alt uni1F8A.alt uni1F8B.alt uni1F8C.alt uni1F8D.alt uni1F8E.alt uni1F8F.alt uni1F98.alt uni1F99.alt uni1F9A.alt uni1F9B.alt uni1F9C.alt uni1F9D.alt uni1F9E.alt uni1F9F.alt uni1FA8.alt uni1FA9.alt uni1FAA.alt uni1FAB.alt uni1FAC.alt uni1FAD.alt uni1FAE.alt uni1FAF.alt uni1FBC.alt uni1FCC.alt uni1FFC.alt SF540000.001 SF530000.001 "}~€Λ Β*cyrlgrek8latnJBGR MKD SRB "AZE 2CRT BMOL RROM RTRK ^afrc2case:loclBloclHloclNnumrTordnZss02` $,4<DLTHLPTblzŽΔ6L6L6L {tu l|DR {tutu{ ‰Š‹ŒŽ‘’˜™š #>?@^`cm}ΰD] <>cyrlgreklatn(ΣΘ!zΙεΎΛΦχλOrocq-9.2.0/doc/sphinx/_static/ansi-dark.css000066400000000000000000000042661516144147600205760ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* Φα?ΞAχG$Χ Ί―Γ]―¨ΗϋΡλεέΦͺ~t™’ŠεΗ₯ΘχwΐΛ‚„χΌϋ vΥͺήηr…œ ΎΟgc·°g{εs&ΫΙύXS½O§z¬™π_' ½pοO€ŸΗE«ΗuΓ¦Ν#¦]{]ΎuΫφ9χ5h|J‘ΛΈoηTΥΌ?§όUυsͺ6-ψ>Κ½l£œΪνNρ1jΧ:§ΒUήε*΅ώαc[ΐυΊwοœS»Rθ2Νσ} »woŸS5t,ηεE=^ΑΧΛ{{ΎΫ$θ}τk{o#ονΤχ^ο½ύSάW!vΩ χv|=@iqriΫ¨jξI:Ÿ Uς„Jauκ”’“omΪΆ |}€Β]&’λ…œ<9™wΒ2λE+VχOˆN,WΝ;™ͺχ₯BNΥF§8™}ŠνA—‰δ„tΠΙαpΧ+κρΜΧ?υ1Š"Ά—ί—‘\¦ AδGoO…Π  a!χΏmP(ΚγΉ°ƒHaίFanξεƒ/έ½―cώcόΰǏ›pοS€·έύ8υzω^ζΎ?ξύζσΈ(bυΈ?‚<Ψ&χvwθΨ)pρ ]Ζ};α„‚DzYwTˆδz…DŠzΌ^VΏ`Q"‘·Υ¨fή(’γyΡ¦ΑƒƒHDB'‰ˆˆˆˆˆˆˆˆˆˆˆ’­“ƒˆύ&%['{Ϊ"""""""""""’dλδ ’ϋœχ "DDDDDDDDDDD”|Dr/ƒ%_ "DDDDDDDDDDD”τDμ%[ "DDDDDDDDDDD”τ1ˆQΗ BDDDDDDDDDDDIƒ%} "DDDDDDDDDDD”τ1ˆQΗ BDDDDDDDDDDDI_©DŽ|½8ηϋ£‡rώωΟ潄ˆˆˆˆˆˆˆˆˆˆˆ(v•Ψ r`ρk9©/tΛYσ|ηœUΟu:i݌Ύ9υ_•w)"""""""""""’θ+‘AdW3sΦNν’³ςَή~ϋνœύίΝ»4Qt•Θ ²ώΕξCΘ:δdggη]šˆˆˆˆˆˆˆˆˆˆˆ(ΊJd =MVπςƒ+Vδ]šˆˆˆˆˆˆˆˆˆˆΚR§vZLQΑmΪ΄9§V­»rΎύφ»Ό—ΎΠuCΗ«4χAδώοrV?Χ)pρϋδ“OςADDDDDDDDDDe© Q#Tp‘!γg§Ÿ‘σΧJ•Š4Š„Ίnθ‘c•Ζβ>ˆ„r~ΘΆE/z^ΘY29EύΥ€N9«W―Ξ»4•₯b5d0ˆDžΠ(μ(ΝuγY‰ "ψΗ?rV=Χ)gΛGOi1οN₯—80ηψργy—&"""""""""’²ƒHΙT”a#QƐP%2ˆ„ς!f€I9Sž”σΩgŸι©΅¬ΠφwlJΛI[0)'₯jΥ“ŸΉͺζTM™”³ -οb%‚œέ–οωKΛ™TΥ[σ«κ½/)ή}xκΫ~κcHJώ·JDDDDDDDDDΟμ\e΄Εκ8e©Β ‰4†„*±AdέΊu9ŸΌ3%ί ςάsΟε=z4ηŸόgNζŽ%ω^gΆ¬Πλ£)mAJNΥΌO„\U5&TυU'ε”ά&Α ’Ϋλc·;OhΤ Ύύ§8†a!""""""""’ΜΞsF[¬ŽS֊dθH΄1$ΤΙA€mΫΆ9!ρκΏϋΏsώηώ'ίΨDBen*ίΛ]ο½χ^‘ΕHΪ$ϋ!‘M± p4HK[“vPˆG "Us&ήΈΠΏzIΙ99μTu―ʎτ:"""""""""’’/VCF¬ŽS;Υΰ‘ˆcH¨Φ­[KάλθαΜ“CΗδΙ“5tψǏ Kί&η›oΎΙ;B!Z’χ RΒO‰UPED,ίΏωΡΏφ`!""""""""’]¬†ŒX§¬4|$κκδ ο§Μ²όΘΣO?σ·#{σαlήΌ9ο‘f#CAcBi(ΪA$TΈχ—A„ˆˆˆˆˆˆˆˆˆJw "₯'wIΤ1$ΤΙ§Μ*©A$”Γ‡Ο7zœΚ’E‹ςaφ―C’ϊϋi9 &ωž’JBs£€?džΆ gRŠwΉ“Χ ύΠΣu…'b1ˆ„ήεΌ·•οΒ "DDDDDDDDDEι‡s‚±Aα‹Υ}Δ}›ό£H’Ž!‘J|ٳ杓#ǘOδ=N₯°ƒˆEήC&ωͺ9)))’οeAΗφ_―ͺ]/οο˜Tυώw1"Α#ƒQQΚ=;ΎXέGάΧ±‰A$F™ζΈB>eV!‡„eEhPωρBΘ<χ+ά°t=»M§Ί^”ƒˆ1ƒH8E½ˆˆˆˆˆˆˆˆˆˆb“―ŒΆX§,ηCBΧΏm)±Aδ›ΜcG$z葜cǎε)’’ϋWi“ςώEΗ)ώy‰]ΖτTA/ΛΧΙ=RBƒHΥͺ9U$…A„ˆˆˆˆˆˆˆˆˆJ4ΏτD[¬ŽSVsǐΠ½,Q*‘A$hδςΨcΎ|̘19όη?σŽI…œrŸn«€λΪψPu’χΦr+ψzα†šx "E‡ˆˆˆˆˆˆˆˆˆˆŠ;‘’οTΓG’Ž"qD}½0pδςφΫoθex$gεΚ•yG‹ΌˆFΐ"ςFŒ“ƒH$Χ+ζA$ο©Όψ£κDDDDDDDDD”H1ˆ”l‘ ‰8ŠΔ}ωίύߜ₯ŸΌω£‘#ΘOδ#λ“F?š3}ϊτœώοΞ;ZδψτUaKάA$ψΙ3ˆQι.VCF¬ŽS–*ΜΠ‘h£Hά‘P‘Qdχξέ9λ>}1ίΰαχΥ{sΆ~ωΓ‡nΫ{ο½—σ_υ_yG)da^GAE8Bόθι©"Ή^Έα#ƒˆύ‘wίSxεΖ BDDDDDDDDD₯;‘’©(G""%2ˆXσ?“³zYπSh=:gΜ99C‡ΝyύυΧsΣΣsώοώ/οšEΛώΕďG‚SWΤ?ͺno/μΏJ±Ρ"ΦƒΘΙρ'θr "DDDDDDDDDTΊΛ=oΚ Ο’6e)ΡA$Thδpǐ~ύϊε;vL$ττXΡ!?dc€§jJΞ€Α«BΪ‚I9))ώΡΔŠΰq#-ά°qͺa"ν‡cΖlIKΛYR5οm†ž*+πB "DDDDDDDDDTͺΛ=o;Tp΅jέΥ αEBΗ*•ψ jϋβ—ς "³fΝΚ{Mq”–3)%ο_|δ©Z΅jί'‰ϋ―HNŽ!ήeSRrR<ώ—'uIHΥάλ€δ½ͺ“„' DBDzۜλδΫΠλRNρ/HΒγŒ%DDDDDDDDDTrε;ίTp›6m֐ΝΏξ]7tŒΠ±Jc₯bρ!!}τQήkŠ―΄΄F~4r…”I ς!–σ/0δT—ΟKβ$ίΨβ]Gz#ܿֈ`ωοv₯„W/?tͺc""""""""""JJ|qǐ—^œ’σΟώ3οΙ\ΈA„ˆˆˆˆˆˆˆˆˆˆˆbY‰"ΗnDBΆoߞw©dŽA„ˆˆˆˆˆˆˆˆˆˆ(•μ ’Ύ%p YΊtiή₯’9""""""""""’xT’ƒΘ7ΫǐE‹ε]*™c!""""""""""ŠG%:ˆόίύ_Ξ={rΆmΫφ#'NœΘ»T2Η BDDDDDDDDDDJt!""""""""""’xΔ BDDDDDDDDDDDIƒ%} "DDDDDDDDDDD”τ1ˆQΗ BDDDDDDDDDDDIƒ%} "DDDDDDDDDDD”τ1ˆQΗ BDDDDDDDDDDDIƒ%} "DDDDDDDDDDD”τ1ˆQΗ BDDDDDDDDDDDIƒ%} "DDDDDDDDDDD”τύh9|8 ©0ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz 3ˆ4iΩJ^yυU Ί ΒΫΎc»\{c%Ω½{—]Ύο(*Ύ~ ˆ|4ožΨ/’{φμ‘ Λ†¬ί°^»ιfYΉj•]‘³Η±°YY™β^ήW "ESΪ?/Uχ^½€£IΠeΚ‚βώΎΛγχΤμϋš0±_|·lέ"»ΣvΛλoΌ)Ujά.O/AΗDς(ν_§’υηφηΟϋΌ6j”€_/ΥkVΛ¨±OΙ;ο½+AΗ,Λ’υqbΒύ~—‘qHRΧ§Κpο1Rρζ*2ηύχΕ¬X`)š5k׈ύ½e‹χ}Ψγ^K‡δލd䘱β^Ξώo¨\Uφοί/ξεJ ƒH|…ϋ:Ž}έd€θ΄nέZDJX¬ο/ƒH~ "ΕΓΗ "ρQΪ?/ƒHβώΎΛγχΤDp* "%ƒA$Ά’υqbΒύ~Η ’XDDŠSΈ―αΨΧMˆΞΙAδα‡Ξ ΊPQυ {Έ/Ό½ή~μ½­Zu뉝 θΨ΅›„ϋ¦€φώrmίΎMμύ΄§ΤΈηςβΛ/KΈlΒέΏ=Gμz.»ž]Ύ€Ψ wϋΈΏ0}Ί]6Δ~ρhΦͺ΅Έ―w˜’>ήޝ3WξΎΏΎψ2φι§Εξߍ›6н~ρ’%RΉϊm’™™!ώc”${Ϋ ‚Zw{χ‹'άύh'DΓ "v?Ϊύa֝wί#γ'M–μμ,±λ½πKς@ο?˜~›6o{j‘Ν[6‹½Ύ ΗΑΧΫΆI‡Ξ]ΕύΌ³Η‘έ~χσ¨ο_a?/ z?vξά)½ϊτ•[οΈSͺΧΚΥgΐIΫ“&ξυνl{ό>ΨΎƒΨύaχω >χϊ₯MA'£ύ~cχΧΠ#€E›6Rι–κbϋ|Ξϋά©Y»ŽΨηΐΗ—pƒ£½;!goΗ>.φTKφ”Lξυ zάΔλρνύmOaa·λ¦j·ŠέΛW¬χz%Εξ/»½‘>₯£ΰ χυΜ?v"Ζݐ―·}-φqp bυΈύΤ8iΥΆ½ά|ku™ύΞ;RΠγ¬=Β)θλT΄_Χ£½~AΗDΌ|μΙ'%貑ˆφώ΅Ο§D>RΠλ£ύ|/i…ύύί GΕ>NφΈ³ΧG{Dϋρ΄ΫUΤο#Ρώά\n»«ŽΌϊϊλb/·ΟŸͺ·έ.οΞ™#š΅1BFzχ}H‹6mΕ}}AŸφq,κΟέў7(κΧ―βώ=8QΏΏφλ„=>Β "Ρ~ˆτρWΤ―#PZ<ά³­0ˆ”°Βή_.‘ΐΗ "‘ύbWΤχ―°Ÿ—½±:1c_‘SΏ±ϋ‹AδǏέ{»vωhοοD?ρΚ ’8eνρƒH|ΉŸ— "±ω>RΠλ£ύ|/i…ύύŽA„A$€ Ο ϋ8υηn‘όo·€φλ„=>D :I3ˆt}¨§ΨXv’sίΎ½b'hν tΈόKJaο/—ύ@eΏ Ϋ*6nϋ,ά6έΏvβΊ΄?΅Ιψ‰“ΔžͺΙ}½ύuϋΑ-άϋS\7ϋΕΐNXΩSŸΨq›ΆzPκήW_^žωͺΨλ'L~FμxΪΛK {7Nޜ=[n»³ΆΨhvω‚—ݏφmέϋξ{;v9»Ÿν)-V¬\)ώc…ΨSΛ΄ξΠQάΧτ8hήΊτμέGvνΪ)φ|γ­$άη+χΟDϊyYΠϋa'&;vι*ΫΌ_VCΆ~½Uμ-{½{}ϋΑΨ~ΰΆ?6kOb[ϋEΙύΏ΄)θDc΄ίoμώ²_Ψ–-_.φωΡoΰ ±_,μ„•ύbiOωgŸWοΌχžψo£νΨ/θŸ/\(v;νύΪ/–φψ΅λτΈqΧγ·¨χ·=…=%…ύbf¬ϊ«Ε‹Ες ·]Φ[+φuΓN]ΦΟήo{ݏ[΄'²bυΈ·Ην—_y{Ή‚weνρNA_§’ύΊνυΓ}“εσngΠe#νύkŸO‰ώ}€ ΧGϋu§€φχ»O?ϋLμqΆ.uΨλ£½?’ύxFϋ}$Φ?7Η›ύρϋ‡σΨΛνηήzυˆύΎiχ£{?4jήRΖM˜(φrSΠη…}‹ϊsw΄η ŠϊυΛξ‡Xœθίί ϋuΒα‘hΏNDϊψ+κΧ(-Dœγ””Βή_.‘\ "%ΛΗ " "…ωΕ¬΄±―£ "§~άΈŠλρ[Τϋ;YNΌ2ˆόpCΚΪγ!œ‚ΎNEϋu=Ϊλ‡ϋ8&Λη₯έΞ ΛF"ΪϋΧ>ŸDNύu§€φχ;‘‚>/μγΘ ’ϋςDώ^Ψ―φψ`€θϋ bίHΓ™σώRΠήp―wπ²oΘώλ†ΨzϋΒΌjυjq/WR"½ΏŒύ`b?ΈΨΛνχψŸ|φ©ΈΧ·ΧtGzβͺ€ΩΗίώ(‘{"ινwίϋn?8ϊR܏7ϋAΣώΙ΅ύa”Υ^ή½ΧΓbΧkΥΞϋΤc€ά^^ZΨγΨϋά~Α;~ΌΨενqι β²mOΑγΎΎΗΓ½ΕώΙ°½άn—=₯Χ³g‹Ί!αλ7lpŸOΖύΕ6άεΒ)θύ‹τσ2άϋaΏ€ΪνsŸbΗΨ‡΅ΛΩ?΅·ΧΫΖS¦NuCμ »Ύ=e‚{Ή"ά‰ΖX}ώŸΌΏ¦½ ώλ†Ψ/φTμχrφ‹Ή=υ‚ϋz{;φOΪέΧ{ŠχΟp›HEϋψφώΆ_ν)d܏CiυωήΗίcο·έA— b'H&=ϋ¬ΨΛ‹z"Λ}y΄{;‘αΏ_ΈΗ]΄·#Qα„ϋ:νΧυX}_χqL–ΟK;ρtΩS‰ΥύkŸO‰ώ}$άλcυu§€ΩΟΕ‘žθ΄‘Κήo;±«ϋ#ڏgQΏΔληζβf?―ؐh/·ο· "φς»Θ{sηΚή½{ΔϋψΪεMAŸ7φq ύΜβΎήξw»νηξhΟΔκλW¬NτοοφuΒξ―HΉƒH¬ΎNDϊψ+κΧ(-DœΛ•”Β~#΄LDς³?ƒHΙ°Η1ƒH.‘\α~1s/WZ0ˆδΎ<άγ&RΡ>~£½Ώ“εΔ«έA— Β ’\‡pDβ‹A„A€(μηb‘― "ωΩΧ »Ώ"Ε Ρ)φA$ ϊΒξυ_|ω₯ψΏ9D⃏>Ϋ(I…½ΏŒύ‚f?]&Δ~`±χίύ³ ϋ?―₯E—‰ύqB{Ή=5C‡‰:~Εύx³_<νΡΝύΰ±œ·οΨ.Υn«)φφPkΧ­;^iacDμε_|ΉHμΫΩζφΈ 7ˆΨS8Ψ?ι΅ΗΉ{Ϊ?Αw―ρόωrΛνwˆύvϋAί~πNO?(ξυΓ=μσΞώ°:~}ήEϋώEϊyYΠϋa’:~φOΞνφΨ?Ν·ΧΫΖφGύΧ q―oΏ»—+-hŒΥηAχ—ύΣ~{<Έ―7vϋΒ}ί°·γ~ά]φΗέΑ2άγΖχγ7Vχ·ύ·}}²·kO)³bΥJρΏν’«§ΜrοΧ’žΘŠυγ~Φ›o‰mϋ…{ά•ΥΗC8αΎNEϋu=Vί ϊϊ‘h‡X=eV¬ξ_ϋ|Jτο#α^«Οχ’fοpχ―ΛRΧ§J¬ξh?žEύ>bϋhn.i6„Ϊν³― m;¦ˆύΡp»ό3S¦ˆ %φϋžέφ{‰m„τycΗpŸξΧϋΉΫ>}]χq°λGϋυ«Έ~ΆΗ{’|_1…ύ:aw‰ΥΧ‰Hα^oΒ}€‚AΔχ6JRaο/ν6φϊ‚ξϋ"ά‰«†A€dΨγ˜A$WAŸwΕ}BΩτ~χ‰χϊ "§ΎΏεDVq?~cuΫΫΧ'{»‰rβ•A$χεeυρƒH|ΉŸ—φu:θ²§«ϋΧ>ŸύϋHΈΧΗκσ½€Ωγ;άύλb9υΟΝ%A$6_ΏDς+μΧ {|0ˆ@t~±?ΖeτtwΪnρ_7φώ2‘ώΣWχlχΜ‚ξϋγoαN\•6ϟ'φŸύ‘_{κϋ§ΌAΧ )ξΗ›―Qλ.yόΙ!βώΣηϋ6–ρ“&Λνή/!!ώc•&φ8vΣ­g/ι3` Ψͺξ ²cη±ϋٞZoίώ}bOyυό /Š}Όόo+ΔNΪ/pφOΦιΧ_=ρ„ΈΧ3αφ‹EΈΟ'ξσ.Vο_€Ÿ—αήχŸΎΫγΫݐ‚ώι{Q1s/WZ„;Ρ«Ο‚ξ―XŸΘύΤ8q_oΒύ“φp›x=~cu»μλ‚έφ”αžB1ήμώ³?–lί‚.λgο "vBΑ^oδήύΕΧΨχIϋ<΅Yρzά›p»²ϊx'άΧ©hΏΗκϋBΈc8ΙϊyιŠΥύ[ΠηSi>RΠλν~‰υη{Όφχ;ϋδͺY»Ψγ.VχG΄Ο’~‰φηfχr%νξϋλΛ³Ο?/φyζ~\–._&wί€ΨCž(φΣ― Οϋ8†ϋόχsw΄η bυυ+^Ώ'ΚχχΒ~°Η‡;ˆΔκλD€Ώ’~€‚A€”(μύeD‚1ˆ” {3ˆδ χy―Κ&άϋ―3 "ωt1ˆδŠΥύν*νΏ ΫύΗ R<ί]₯ύρƒH|υσ«ϋ· Ο'‘‘°Ώί1ˆ0ˆ„τycΗpŸ "Ήεϋ{aΏNΨγƒA’“πƒˆιϊΠC©[wI]Ώ^μήeKΕ.wΘϋ!!Δ=NI)μύε²§$ιρπ#²kΧN±\μZΫ&ξ˜έΏ»χ‘#FHff†Έ—+-μ ϋ£ΩwΥ»Wš?θέOž λψχγΝώϋΖͺ·ˆύ€ΆrΥ*±Λ >\μυ} {}icγpƒˆύ@nδΩώ)΄;ˆΨ?ΥΆλ³Ο?»ί-ώJμΫΗΛΆό쏾΅jΫ^μ©»άΒν*θqΠ¬UkιΩ»Dϊy«χ/Ο˂ޏ–mΪ‰=žν{j€Ϋw»Š{ύ’ώbζ^΄w’ΡDϋω_ΠύλYφyfOu`Γ…}ήUΎ΅†ΨγΧξqοΗoQοοωŸ|"φωo;{ύλoΌ!6 ΨS2ΈoΏ€|ψΡGb·Ο~ρ΅ΟΛ΄=ibOAeOh'hάγΩ'νϊPO99xlρ~φΨS~Ψη©½ή_ԏƒ]Ώ Η½ χΈ3E½‰ώxpτu*Ϊ―λΡ^?άΗ1Ρ?φTœ7z?Γ„Œ3VμaΫγpΝΪ5b'Œήyο]±γD{τωTΪΏDϊϊ’~Ύ»Η))α~Ώ³§J²§Δ>j΄ΨSΝy}ρ+$Ϊϋ#ڏg΄ίGŠϊs³]Ώ΄xμΙ'ΕώΈϊMΌϋΥγ^Ξ~­zΫνb—Ÿ2νq/o ϊΌ°cΈΟ‚~ξŽφΌA΄_Ώμq«ίƒύϋJΈ―αΨγΓDL΄_'"}όυλ” "ΞqJJaο/ƒH~ "%ΓΗ " "~ "ω? ΊΏDς_¨χw’‚Μ ΫοΏ‰ώxp1ˆ” ‘Βχϋƒƒƒƒˆ χu"{|0ˆ@t’f±/ΐΓG’Ϊχά'φ‹€]ίώh—{ύ’fχ—ύΰQχ)FμTΫφ Θώ©β‹/Ώ,v}χ›‚ξί/-’zυˆύΐnΧs/_ZL˜όŒΨϋm?]Φ― ϋ#V·vR€z­;ΕώiΌ½ώ£yσΔnΏψς£4±ΗqΈAΔΨΈφ~ΩNξεμεφOͺνΩ¦­;Žέίξυ¨°·woƒFtY?;nΈΗύΰϊ€!φygŸ'vϋννξΫ·WμϊΡΎ‘~^Ϊ‡{?μ©uμΤ[jΦ’[οΈSμ)Ζά―&Ϊ_ΜJ›‚N4Fϋω_ΠύλYφΗ+ν`ϋcžφ ΌύFχϊ=nβυψ-κύm'œμšΪS}Ψ/ΰvΨS~ΩυJ›…_~!v’Ι>~φωdΓ”{ΒΥe':Z΄i+6 ΫSRLy†ΨqέYΕύΈ7vœp»²ώx0}Šφλz΄ΧχqL–ƒύ?T€tλ!vbΘޏϋ5{?ΣΣŠ]?ΪϋΧξ§D>RΠλ£ύΊSΒύ~gAφlτν'φKAΗ ‰φώˆφγνχ‘hn.-μ)xνv9R‚.b vωU«WKΠeCμγξσΒ>Žα> ϊΉ;ΪσΡ~ύ2±ϊ=8ΡΏ―ΨΧ‰p_‡]φψ7ˆDϋuΒ^_Πγ―¨_G ΄`)%μώ²oψa‰ ƒH|Ωγ˜A„AďA$υ ΊΏDς_Ύ¨χw²œxeΙϊ²ώx0 "%‹A„A$α~Ώcaaa1φu"άΧa—=>D :Ε6ˆ@Yg?ΘΫ?•Ί P\μ–pΏ0#±ΩSΨ eΏ˜]Š‚ο#ˆ'~nJ?Ύ/H "PLψΕ%‰_X’ƒ€βΖχΔ?7₯ί$ (’·ί}Gޝ3WμŸ(―X΅Rμ)μ/(.όΒR6|τρΗr}₯Κbδ>θ²P|A,ρs3ψψΎ Y0ˆ@ρ‹J3~a)DΎ –ψΉH||_,D ˆv§ν–‡ι#φOόkΦ+ƒ‡ χ©ρΐ/,€hπ}±ΔΟΝ@βγϋ€dΑ EΔ/v(Νψ… Ύ –ψΉH||_,D@cIA$=τD@cIA$=τ~4ˆlήΌ ©0ˆ€€χ£A$θŸ‘$2τD@cIA$=τD@cIA$=τD@cIA$=τD@cIA$=τβ6ˆ8°_/^,σηΟ—yσζΙ‡~(sηΞ•wί}WfϞ-oΌρ†ΌφΪkςΚ+―ΘK/½$/Ύψ’L:Užώω@Σ¦M“·ί~[φμI“ Ϋ H~ ΜϋΎ`>ώψcΙΞΞ’ λ q0ˆ0ˆ@™Ζ P6ΔmωςΛ/eέΊu’––&»wο–;vHjjͺ΄žp΅4sa‘Ψυμ8fΛ–-²qγFωδ“OΔ†– ΫŒ”uHvΎ>DΦχ»5Wίκ²σΥ'εp¦wΉ c$±΄χŸ• ύkΘϊ qμ|}¨μ]WŽ6HNδΩ1{yΘΜ!tŒd’•);f<*i“›Θ7KFΙ‰/‡Ιφ‘wΛΆ©}%;+C‚ŽYšeH“νΣΚ5’–€Οl-™otΜΣAφOm,[žΌ]vΞ"Ω™ιτ6Κ‚―zχƒgϋΠ;εψΗ}δΨGΉΆρ^ξΩ1γI :FiΆdΙ±§ΔΪΆm›Ψχ%cC½=΅γW_}%AΗLjιδΐ3OΙΞ»n’τž­δΔ”'εϋχ§ΙΏωFEΉμεv9»ή»*ΙώgΗ‰½ΐΫP lzς.ωfιhωΗ¦iωmœšί†ηεϋυfJΤης[χ¬ό}έ3ΉΦζY39Ο$Ι~§»lθ{›έΖD”±cƒlΣJRΊIΆŒφώΫ“±c£]7dμτή?Oψχ?χώ Ί. πΪΆm+ " "IA$?‘’`aΙ‡ADDŠƒƒΔS±"ϋφν•/ΎψBφοί/v"jϞ=bƒ„±aγΠ·SdΗα”S²ΛΩυΆoί.λΧ―ϋ#ξ6ˆlΪ΄I^}υUΩ΅k§½%Α€ζΝ›Λ₯K$θ²…a;ξ’E_JΠeΡϊGBOλsKΞ±ω}εψG=r½ίMŽ}τˆ¬λQE‚Ž‘ςžΚθλg{ΘώΪΙχ©/Θ7Ÿ’oηχΞυΥPΩ9ζ>Ω:±›$ΚS"e¦m“-cZΚήgλΛ‘Ήέs½ΫQΟn+Gf·Λυn'9:·‡μ}lyͺ™dΨ#Ao3™₯φͺ*G>θ%ΗBŸ;!s:Λ‘χΌϋΤ³[e :Fid_χί}±!Δσ5kΦδc/·ο'|πlΨ°A‚ήF2ΙάΆUΆ7#ϋ:6‘o_™ {=ΧwӞoŸρΎ–„Lμ‘_ήΛνrv½ogδΪΧ±±loRWμνέ¦’΄ρρ;εΘǏȷ_φ•oφΞυω#Ή>ν%'>ι™k~9ώ±χ}(δ£Ή>θ"ΗήOΙ5§“}―CwΪΛ‘·½―YžƒΣΚϊή5$θ6&ϋϊΊρ±z’ωφΓςές§δΠ«eσΘ–tŒd°yt+Ιx£›|·bœdΞξ)½[Κκχ#ˆ5ΫADD’ƒH‘(0ˆ0ˆ„0ˆδΗ [φυ•A„Aβ©Ψ‘;wˆ=EɁdŊ’™™)G•οΎϋNšŽ»X}ϋŒ ~v9Dμ©NΆnέ*‹/ϋγκvb̞²ΛώhnΠϋO³gΏ%-[Ά”aΓ‡I³fΝč λžΚgŸ}*6„ ~r°ΨΫ‰Ύ λ&’΅)ΧΘ7Ÿ ;‘tτνvrb^YΣ‚#‘e§ο—­γΪΙώ)ςuΣδΨ‚>ςΓύV޽ΫIΎωόQΩυτ²iX )­'b²33dϋΜ1²gj;IŸΡJΝh&Y―yοƒ'ϋVrΨqτ­6Ήζv“ƒΣšΘ–‘ Şz,θ6$£5–σ½ΟΟ‘·»ΏŽ}ΠSV·ΎJ‚ŽQš|πΑϋςΪk―‰=e’}_²§X|γ7ςY½z΅,]ΊTμϋ†gξάΉ’llέ‰ΝwU•ƒ½;Λ7Ϗ•£w‘#ύ½Η…ηθcήΧΟ±'ΫΛρ!ς±—ΫεN^/ο8vάƒt{»₯m9°μΩ0πYΧνΊόΊζιr­μ™ΪRΎ[:Fάαγψ'dηΨϋΔ>οNjŸ'οϋΥϊ^5dβχ%θ6&„lοk©gλψN’>³‹όΝ»BŽΟο'ί-)kS*Jΰ±’ΐΊ.•o½χ=δΔ§ύδΫΕ#δΰΛdΛSΕξΏ c Ζ Β Β ’DDDbΑNΘ2ˆ0ˆ0ˆό€A$FDςa€ψ*φAdΛ–Νbˆ=υˆ=uΥαΓ‡Ε‘μμl±a#ύ›I4‚ψΩεάAĞΕN€Ήƒˆ=uΚΚ•+$θ}ˆ‡—_~YZ·n-Ο<;Y&?3I&Nš -Z΄ωσηIΠ±ό>ύτ±αcόΔ§εΩηž‘I“'I«[Ɍ3$θX‰ΐN$˜ίWŽΌω žΥJŽ}ΨSεDn€²φο’MCIΖ›=εο©Sε„χ>‡y«dΏΪB²f6—Γ―·#ox―χŸίG&4” ƒ¬}ήΫρέ†’°ωBΩύΚ`ΩJw9πr;IŸΡB2^o-‡ίι$GίK‘#zϊ¬Ά'Oτ™ε=^<Ηήν,;‡Υ’m/τ— ΫŒV·­ Η?κ%‡_υ#žμ™MεΨ{]eUΛ+$θ₯ΙK/½$6ΘΫχ{κ+8μϋ“±—ΫS/Ϊ[·§~΄―—™™τΆIvϊΩψΐέ²·{{92βQΙμΨ8WJ#Ιξξ=<‡{yή-εH_οsΙΗ^n—³λΩqμΈφvφvk'Τ•μC%θ6— ™ιςυ€.²Zkω~έ49± ΈCτ‘ΠΧ Ο7Ÿ?&»Η5Ν£ΫKφ!ογα |› lΧ›csyοkΘw+ΖΛα·Ό―Şo>)―t”MC›KΠ±’Α¦aήϋηΙx-EΎ]8XŽΞφ+žo—Œ‘£ξΟυΊχΏ=AΗ,΄tθΠ”A„A„A$‘1ˆ0ˆΔƒƒƒH!0ˆ ƒH~ "_εΛ_sυ-u‹oY·nΨ©΅?’Ύoί>±?’n' μ©Iš>υΩwlœlΙhJvΉpƒˆίDζΝ›' ~.AοCq3fŒ΄οΠ^&?;I† {Rισ°Œ5\ž?Nl±AΗ=ξΗ$6„Œ{ϊ)5z€Ψq‡"6Œ΄kΧN¦M›&ξqK»d;‘[Μέ[eΓΐ»%σGδοkž•£οuΙ•wb%ϋΥ–bˆέ?™/7ϋοΓ/7ϋcγϋži"λzέ%™»ΆHΠmЧ½_|(ζŒ•ύ³ȁ™]%ύυNΉ^m/ΫGή)»ž'Gήι,‡g…F³s²_i’λ5ο~ςdΞΘ΅¦Ν5t’Ρκ―”γsΊIΦˍsMo(Gfw’•Ν.— c”&/Ύψ’ؐaΓ†}˜9s¦όπύ"Χ+―Ό"6ΰ'ϋ ²cόS²₯Ρ}rxΨ£r°Eύ<χΚώ–χΙwΚήΆυΕެΞήcΕΗ^ΎΟ»Lˆ]oθXyΗ”–ήΫπΨΫέθΩ1ρi ΊΝ%)λΰ^±?ϊ½χΕΆς}κT9>±!:+4BΡΚ±ϋΘ§ΘΖΑM₯΄>eaaν[τžlμW]Ύ]2VŽΎΧ]ŽΝν)G>μ/©]+Λ‘­k%θ˜Ι γλ΅²Ξ{_CŽΌίWŽΏίS‡ΎGyΎωbΈlxΈŠμϋβ] :& <ΫADDDƒƒHq`aa)ƒHα0ˆc€ψ*φAdωςebOMbCΘΞ]Ϋ₯ωΣ—K£1ζσΰ„ΛeGΦpY»―Υ)Ωεμzξρμν€nX'v"lαΒ…RRTΌoί>΅kτΨ@ιυHΟ@6”Œ7Vl±?Ζ>wξiή’ΉŒ}jŒΨπt̐ƒJΫΆmŞ*&θ6—fΙv"7œCΫR%΅χν’ύώ ωΫͺ‰rtvωf^o9<»‹y;E²g4‘¬—Ια7BOΥ6'γ•\G½Λ„dN{@ŽΌΡAφMj$λ:אC[ΧIΠmŒ‡τuKδΰ'/ΙώwGδšΥWίκ-[‡5”΄χŸ‘/υ‘­ύo‘#oΆ“¬½Η‰'σΕϊrψΥV²ΆνΥ’Ύq₯έ–d²ͺΕrτνN’ω‚w„L½_ΏήFV6ΎL‚ŽQšΌωζ2uκT±?–nΘβΕ‹ΕžΊΠΨ]·ΛΩΐoƒρ¬Y³Δύ£κŸώΉΌύφΫωΨΛύ·­4ΘΪ“&Λ«έ,<"ϋ[7‘} λΚώΖwˊΘρMdEΧΆ’ΦμIou_>φςε)ΚρΝeE«FbΗ΅·³οΑΖrp`oY^­’dξΩ#AοC<ΩSn|βΩ?½ƒό}έ9φAO99Dη ¬ξυJ3ɞΩ"Χ+Mε؜²g|CYίο>ΙΪ»S‚nSi–±u­¬οUMŽ}ςd–Γ―>(Η?~T6t»Yφ~φΆ3νϋς=Yί₯’ϋ°―ύ?1x޽ΫMŽ~8@R;έ,ι›ΌοKž c~ŒA„ADD ƒH.‘βΑ Β Β ƒHα0ˆD†Aβ£Ψ;dOU΅kΧ.±bφS€Λs•ε;zΛ¦ηyL–ξh|Jv9»ήŠ}₯λσ7Κ+?%Ÿ}φ™ΨY·§θzσΝ7%θ}(N‡₯KΏώύδΑ[ΙC½zœcO<*£ΗŒ–V­Z‰ $£ΖŒ”ΑO>!AΗιώP7iΦΌ™Ψ‰Ύ Ϋš’νDn8φGfχΏΨZΎ[2VŽΜj#Η>xH²ήθ,kΫ^#GΌϋ$$σΕrMσξΟαYmeM«+%}jsΙz½­šTW²g΄=£ο–υύB'λήΖxΘΪΏW-HΞ›*ϋί&»_μŸkΞσrςΊ‘“Χž΅)7Iϊσ$cΪΉž»GlHΫςHeΩωϊxρί†ddƒα‘7ڊέΟή-Y―΄ /‘ c”FλΦ­|·nέ*iiibO­hμ)νr6€¬\ΉBlπίΆνkΙΚΚ”·ήzKώώχΏηc/·ΛΩυμ8‡$θΆ§―½*λξΏOφμ*»οΉSξΏKφ>PGώί–Mbύη7'diΗeGΓ:²³a]Yζ½,Δ.gύΓ;FˆΧގ½]»kο»OvΎώͺ½ρ΄el9ψR{ωۚηδπ»έ囏–μ·»JΨ!:ολnΦΜvrςϋΦΤΠχ¬ϊ'‡θ΄§κΛΖ!m$θ6•Fφ”b©½kKζμ‡εψΌώbƒϋ±ϋΘΧƒjɎWFKΠ1Λ‚3½χί³ΉO 9:§§zφ^9ϊήC’1£“¬λ^S2χ₯IΠ1?`aaI@ "ΉDŠƒƒƒHx "‘a)(^Ε>ˆ|όρΗb'˜μΏν©Gφξέ+³ΏxVlΐψjkY΄΅…|ΎιώSZ΄΅Ή,ώϊ!ιρΒΝ2cή±AfωςεbO•΅jΥ*±§H zβΑώ(ο A₯e«–½G7ιρPχ@ƒυ.ο±?–>rδyτ±Atnέ»I³fΝdβΔ‰tΫI²žΘu­ιPQŽΌχ}§c9έ%γ•bO©aχΛα7ΪIΖ”{s=WO²fΆ»_Φ΄ρŽοΩ?α~ɚαέožŒgCχε=9‡¦4”•*HΠmŒ§μύir`ΩΩϋρ«²oΡG’ν}n…ΈΧΫρ0ΩωΔν’9υ94©NΠϋκΩυD Ω2¦›ΈΗI6+_*Ωήc"Δξτ wIζτΖ²ΌώΕtŒμ‹/Ύϋcλ6ŒοΨ±#Ÿ•+WΚτιΣΕώyσζΙ’E‹dΜ9ςή{ο‰]ξΫoΏΝΗ^n—³λΩqμΈρFVΆn-[[΄΄¦dgš²λξZrr¨θ^ώηΔq±ώσΫodI‡eqΫςǏ‹υ?ί}+{€ˆΧގ½έ΄fήνπlmΩLVΆn#AοC\δ ©λ:_/ί-%GίλšλέΞ’ύvwYΫξ:)pˆ~π*94½…dΏφ š\WŽx— YΣς±ΫxKƒΌΫ·etGΩϋ\K91€?[O²^ρΎοxvΌW6 m'‡³3s»,Θ»6μ(»ί%/4–ƒγΌΟA %»Gέ/·–2@DDDƒH~ "±Ε Β Β  οD5ƒHςnƒHεέ "P<Šm±?2k'|Ύώϊk±Pφ%W>-έ§έ(Ÿmκ( RΦΦΙg~j}YΈ)Ez½XY¦}π„Ψ²yσf±§Κ²§>Y»v­ΨSEΩS™½Oρ`oȐ'₯E‹ζ΅{ιΦ£k ώϋεt™;Ž=΅– (ξNTΙ~"ΧlΪJvΌ[ŽΌΣ]<ΫTΦu©&Χ/““χΛ«­δΠdο~ ™X[2_j"vΏL]*kZW’]ί.Ο> ΫzU–υύšHΠmLϋΎϊH6u»Q2¦ά/ιγξΘ5ώNΩ3μYΘύt¬d²’Α%’9έ{\xμώ8ψTM±ϋiω½‘ c$ϋ~0i$±οfΚ”)bώ’%‹εΛ/Ώ”'NΘ‘C‡ς±‘?555{Ή{y;ŽΧήNΠm.ŸέRCvΆk'Ϋλά)Ϋξ¨!ΫοΌ]vΤ);λά!ϋSΪΙ|sB¬ϊξΫ|¬ωζΩίΉ½ΨqμΈφvNΎέΌΫa·λσκ·KΠϋO©½ο’Γοt‘c>"Yov‘υ]o–ΒΡk[]/žm(Ω3½―מCS›Θš”št›J“oŒ—mέ%Ηη’ŒΙήϋς|Ω3²¬νz»dνO“ c–Ev¬ι|»μ~²–dLτ?žCOί%Ηήν)[ͺ&;fŒ• cDDDƒHl0ˆcaa AδΤDbƒAŠG± "ϋχ>ϊHμ„ΠΫoΏ-φΗΥ]»wο–gζφ—‡¦έ(―m#sVΤΝSGζ­}Pz½x“LžΣGά!dΣ¦M²aΓ±§@±§D™1c†μΩ“&AοS<Ω02tΨPiή’Ήtξš"]Ίu.’-[ΘΠ‘ήq=Ι2„˜²r"7sΧΩ4Έ₯¬~°’lx¬™ϊz½ΨεtΏ<]K†ξOΖσυΕ½_mM•υ}ˊd}ί&’±c³ΨεK+{Κ,»½ΩYή{·¬•u­―–C“£kΘ‘Q·Ιώ΅duλͺrςΈyΗΙΨξΧ“yHόo»4 wΨλ—ί±d<€Ψύ‘>²ΊdNΊG–έ}‘œΈζ―τ>ΔΣΑ5_Κϊ5dΛΓΥ$΅Ϋmr`υRΨ!ϊΐJοzž5νo‘ΤΆΧΛΪvΥδΐŠ…t›J“Υmo’Γ³:Ι!ο{KHϊSήχ㐉χΛκVήχ-Ο‘Ν«%θXπΎoςξΟκζΧKϊ˜Ίrhθ­’=ξξ\Ο5’•M— cDDDƒHα0ˆδΗ ’ƒƒHa0ˆœƒHl1ˆ@lΫ ²sηY°`ΎΨSf͝;WΆmΫ&ξ±έΉs§Ψ{ϋ!ιυb%yoYγ\Λ›Θ#Σo–1o₯HACȚ5kdζΜ™²z΅χK¦ηΝ7ߐxŸˆ*Θ‘Cι²eKiίΎtξ’‘.];KΧn]₯iΣ¦rπΰ z›₯IζΞΝ²αρζ²ͺεu²aPSqOόυDψO}€‘,ΏοJI}€‘dlί$vωDsς~™κέ/žƒ£o“τQή}γɜ|―ΈχK’;°κ Y—RU6v»YΦu¬.ϋΞ‘•.“Œρu$}Ψ-rhhž5eeӿʁε eU‹J²ρ²¦ω²Ωηt›Jξξ•e]'οώπXι½_žeχ\$Οά#'ο!Υ$k\mYZϋΟrςώhιέž΅―”ΥΝn’z„cˆ Σφrϋο·ήzKμ)°lπX±b…lίΎ]όcHˆ½ά.gμ8v\χν·w+όUΆ5o)«x Ο¦<›«U“-·ή"[«ηJ½΅š,lάPώσΔ qϋΟoΏ•…‰]ώcΗ΅·coΧΨνzχjοvz‚ή‡’prXτΎG…ΈΓbQ‡θ‹ΉoΗ^_Ϊ­~πFɚήJ―›k΄χuΤspL]Yέό:±ώAΗΒƒΘͺ¦ΧΚΑ‘ήcΘ“9ΈŠd ΏM2ΗyίΗ=+^'AΗ0ˆ0ˆΌΝ„A$6DDBD"Γ Β  ‘` "±Ε ±UlƒΘ¦MεΣO?Dμ 6|Ψ@βϊz›w=Ο°Ym€χτJω }ύAΩΌΕ;^H˜!Δώxξ₯KΕn— $οΎϋ¬Y³Z‚ή§xΚΘ8$ƒ ”φνΫΛΘQ#€[χ)₯γ)ΩεFŒ!6ŒτμΩSJϋ0²aP3Ωυd-9ςZ[IΉ£¬mWE]*…=‘{pw=ΟΚfeOΏ[${LmΩΦ©’¬{¨έΖDπΓύr―€Ώ5ΧΠj’υ΄wΏxμ~ :F"²?Bœ>ι>9ϊf9ς^?Yχΰ²Β»oB2ŸΊS ’λρΚ’9μ6YZοrYqο²―_UΙ^SσξSΟΚ·HΠm*I'οΙυεθ[έεȜ’ΪΊ’,«{‘d=]Gάϋ#kT-YRλO²ςž+δΐ€[επΘZ’ώXu)­χG€>ψΰ±§Vœ7ožΨS=.Y²Dμϋ– Ÿ}φi>oΎω¦ΨεμzφT‘v\{;φvƒnS,Ν­|‡lΈ§~*·δΊρζ\•*ΛΖ›s­©t³|ZωcΗΔϊŸoΏΝΗϊγΗΕgΗ±γΪΫ9ωvσnΗϊ{ΉUkJΠϋP•Υ!zΗΜq²©σrδΕ’1¬ΊdŽυΎΞzV—ΥνseξK“ c–Ev¬js«μκSE²‡V—ŒGo–ΓγλΙϊ–ΧΚφGKΠ1 " " " " " " "§Δ Β R " "Ρ`€βQlƒΘͺU+eαΒ…bOeelΙΚ =-IΦΙ§ ±αdλΦ­ωlΩΊY₯q>›6oΜ•7€Ψπaμ„•ύΡZ@Œ=eΦϋοΏ/‹})AοS<€§”GyDμ)²† }RΊχθ&:Ά/{ ­ΑO>!]Ίv‘=zȁϋ%θ6•€+Hζ‹MδΠ3υδψœ>rψ-ο1λYές―RΨΉ+\%ϋά*YCoΛ5πfΙxόYrηΕtAχΛhο~ρΨύtŒ„’%+^&™Ο= cξc―΄“#oχ–ε\)Y#n—ŒA•r ΈQ2«*ΛοΉXφ―*Ωήc#$λ‘Š’ύ˜χߞ₯΅.»·1žάϋγω†’1Ά–}΅y§―¬¨ο}^x²Fί!ξύ‘5΄†œV“ΓOά*v~ΌΊ”Ίϋ£^zι%IOOΟΗψΤΤTωκ«―δΣO?χ8Ÿ|²@μrv=ϋΎθίή{œX›ί΄½,ΎεY_΅†¬»ξFI­˜η†›δσzχΙΏ=*ΦŸψFΆ7k!Ϋ5‘>vL¬8qBΎ¨ί@μΈφvμνΪνX|K-YΠ¬ƒ½₯QY’νσ|Σΰv²£ou9όL}Ιx<τ½Υϋ›χ}g{χJ²~@+9œ™+θΨeAήύ·ρΡΦ²½«wx²Ÿ¬.™ύnΓ#ο”mo”υ}ZH™Ώ  " " " "'OL1ˆ0ˆ0ˆόƒƒHQ0ˆ0ˆIήύΗ Ε£Ψ‘/ΎψBΎόςK±G.{ͺΓ‡ΛργΗΕ†;1΄~Ω³gO>6€Ψλ322δθΡ£’ϊΉΩ'˜­;„¬]»Vμ©JLΠϋTœφοί'έ»w“φΪΛ ΗJη)CΫ@­Z·ΜΣJ‚.1₯ƒ |t€tξμΧΣ­[7±ΫtKBjο²cΠν’ύ|CI^C޽ΥMŽΜ~XV6ΈB :‘»μ?ΛώώΥδπ“·HΦΓεπ£ήΛ<ΫΪ\-k:έ#A·1Ψ 7;uς~x“Ψύ²€ζtŒD΄a`KωΊϋ’=ιΙτ>Φ!Η^n'‡gt–¬ΠΈαΙμ{C>%λ‘δΰ#•%ϋΡ*’ωΠur€ίM²­UYΧ³©έ¦’dχΗΆξήmυ~ζ~Ι|²š›Ρ^ŽΌE²{χ‡ηGχΗ€Κ’ή»Š~΄ͺΨύqΈΝ²­•χωγ)­χG€^|ρE9pΰ@>6ΰΫoίο,˜/ξqμεv9ςν8ξρννΊΗ‰΅Τ―Λά›n—Τ[οΥWU”5WηZ{Ν ςݚubύχρςuƒΖ²ξϊσ±—Ϋε,;ŽΧގ½]»soΊMΦ͘%AοCiTζ†hGց½²Ίέm²χ±š’5κΞ\Όο=ž#cλΙϊζdΫσΓ$θ˜eΑΆ)CeΓƒΧΘ‘΅$λ‘λ%ϋ‰[eο#Udeσ\<εD†A„A„A„A„A„A„AδDDŠ‚A„A€(D xΫ ςΡGŠύΡΨΩ³gΛϊυλΕN ;1dC‡ "ί~ϋ­|ύχςόCμΏφ·ΏΙ‰'δΠ‘C²sηNY·nΈCΘςεΛeξάΉbOab·3θ}*{χ†F=9)))};ιΫ―tμΤAΪΆk¨eΛ¨Q#i€‰΄lΥR‚ΎC;ιέηιΨ©£Ψν°Ϋt›γιΠζu²ͺΥΝ²³ ±ΫOV•c3;ΚΡ™]₯ Ή{η²ΉY=―“£o–νm+Θςϋ*JϊΖ5tpΛv›όθ~yά»<‹kœ/AΗHD™i;dM§»δλεΘΨΪ’ύhhάπV‘CW”¬‡½ΗCHΟk%£λ5’έ#O·«εpοekΣ+deΛΫ%s·χv=A·©$ύθώθθέž#γκJφcU$34φœβώ8Τν9μ}Ξ„d{;δpοώπlmv₯”–ϋΓΎΟL:U-Z$ξε–,Y,³fΝ’;wΘ»οΎ+Σ¦MϋΎaίgμ)―6lΨ ―Ύϊͺ̟?OζΝϋXμεv9»ž=΅£Χގ½]χvΖZzΪyιŠͺ²€Κ²²ΒMΉ.»VV]~€V«)[½V6ίΫ@lΘΗ.gΧ³γΨqννΨΫ]\ωyιΚjb·3θ}(Κκν:΄q΅¬|ΰ94Έ¦d ςΎξ†τυξ OφΠZ²ΌήΕ’φα, :f2Ϊ3mYuο%’υ„wy²Ύ^Žx_[C2ϊ{?χxVΤ»B[.AΗόƒHή (‘XaΙΕ ˆbDή~ϋmY΅j•¬X±BμD #‘²ΑΔN ;ž φXξβ²Λ-[ΆLl ™9s¦½OΕ‘S§NΊuky¨giΧΎ­΄nσ` ζ-šIγƍeŊε²vνiΪ΄©΄hΡ\‚ަmkιρPwiΣ¦Ψ0t›KBƎͲΊMuΩΦυ&9<ΆΆdΈ)W'r3Ίζ:όP¬ξWΛ‘Ύ7ΙΆfWΘςFU$c›χv=A·)‘,Ήύ’ύXUqο—μώ•δ«[ώ AΗHdYϋχΘΪnχΙ¦WΙα'«Kvο$λ‘k$³K…\)WIvG―λeΓύΛκφwK’±AεΚ•bΗΩΈqƒLŸ>]μϋ› »wο;޽c/·§†t;½ϋ™ιιςς-υeΦ•5dA…Ϋdή_*Ι‚‹n’Oώr£|šη³Ώόυ”μrv=;ΞΙγ潝ׯ¨!3n}@²₯KΠm.ΝΚϊΞΧΟ ‘Τϊ—ΚαήΧߍ¬ž‡oέ­―‘ΥλIΠ±’ΑšNχJZϋkΔήϋΊ{δ‘ΏΚΪΊΙΦIOJΠ±cΙΓ Β Β Β Β Β Β Β  "ΑDςc€ψ*_ΎΌΔ|ΉγŽ;ŞzɞΪι·Ώύ­T¨PAnΏύviΨ°‘΄oί^μφ<ϊθ£2lΨ0=z΄Œ;6ŸQ£FΙΠ‘CερΗ—AƒΙ€€oίΎ»woιΥ«—ΨSWΥ©SW‚ή§β4{φ[bC‡ -Z6—¦M›ˆέOΛ–-• cωΩSƒΩυ›δ±γΪΫ±Ο«―Ξ” c•&YχIκC ec£Λεπ jbO1QΠ‰άυwύYV·―'‰ς”G…υΥ-ηΛ'ZΘ•wΏύpΟ’›/AΗH&6lΨ^ΦΤΉP²{V”Γ½ϋΔs€}Γ)WΙΪΫ/Τ>mŎτ6J“= ή‘ευ―—Ε·ž/v"φ«[Κηͺ–kM]οώπœ|Όt =VΘ9!Wvη«dmMοώπ|yγyωύ5Ώ₯wV΄fKΠmŒ{j,{J¬wήyGήΨS'ΪSjΉΧδ“bμάΤέ§Δ²?–nμεv9»žǎkoΗ}ϋΕ-#γl[»N&^~›LΏΈ†ΌwyΝ\UΛυ§*2ηΟ•enμrv½“ΗΙ;ξKήΫ™xΕν²}mͺΨν ΊΝ₯Ωβ”Γύ+‰;Dg?μ}½ ΡU½ΟAOΠ1’QvV¦¬λΩTΆ4Ύ\?t}φ—Ι‘ξΧΛWΥ. c%ƒ―nύ“ιyƒΨϋ¬Ϋ5²υKd]χ&bχ_Π±kΪ‘˜ώ…ƒHα0ˆƒHα0ˆδΗ Β Β ςc "±Ε ŒA$?ˆ/Ϋb>ˆ4nάDš4i*φGΎπ‡?Θ5Χ\#·έv›Ψ‰ώΆmΫΚC=$6d 2DFŽ)6ŒŒ1B,wπθΡ£‡tνΪU:wξ,:t† I›6m%θ}*NφGtηΜyOliΤ¨ažάΆe[·n‘Ν›7Ϊ²e³|ύυVωβ‹…bO‰ΥΈq#±ϋέύγΑ‰";㐀φm-λξΎP~8ρŸ;ˆιx™œ<‘{Η²W+I”ΫE΅δΛ%£S9yΒΏέ₯’Ρ6ΧβΫs#)egΙζ½eU?JF«K$³ΥΕ²²ϊdΓγέ$ΡNH-Ώ:ΙvΏœ˜&ΏηZηzφΑ\“›‹ GΪ^’«ΝΕr,εjωfBσόž6ΝδΫqM%£έυ²€ζ•tγΑž’jΡ’E2gΜ|l@Ά§Φr―θPΊΌώϊλb_7_xα…|ήxγ ΩΊuk>φrχςv;½χνǚ}ί9xπ€μή½KΆmϋZVω•Lώλ=2ρΒκ2γΟ·ΛλζO5r]pk?ή’Ÿ½ά.—w½)Όc†LΎρ^±·k·Γn—έN»έAοSi²΄Ξ•’ΡΝ{ό{μ)‘²;‡FΕ+N~=^rΗetŒd–Ήw·,―_Iv4ΊDμ) ·ΥΏHV΅Ή[‚Ž‘ V·»[v4ΈXŽtΎZv6ΌX–έWIμώ : r " "b'δ‚n[iΖ ‘0DDDDŠ ƒΘ©1ˆδb€ψ*ΆA€[·ξR·ξέb'βν)¬μ)†.6|τλΧO쿍=uΦc=&φί6€τιΣGΊwο.φX6xΨΠͺU+iΡ’…ΨPcO•υΔƒ%θ}Š%χDԞ=i²cΗv±?κk·oξάΉ²fΝjY΅j₯¬\ΉBV¬ΘΟ^n—³λ}τΡ‡bΗ΅pΫ·o“΄΄έ’h'ž²³2dγΰξ²²ζ’Ωξ Ιhs™Ψ‰νΤώ%;σ3™lΩGΦΥό£d΄ΎT2[^"©5Ξ—MΓzKΠ1Κ‚mSFΛβΫ.ΛUγRωϊΉQtD°όžkδ`—εp‡Λr΅ΏTάΑγHλΏδju‘m™§Ε…Ήšύ9WΣ?Ι±&δjτΗ\ ΟΟΥΰr φοdq+$θ6'ϋ:ψκ«―ŠύqσU«V‰=uΥαΓ‡ΕΎήώπςόΗ³Αbώόy²aΓz±―—'NϋcιΖ^n—³λΩqβ5„»φυήD6nά(«½ο)!―=φς ΏΏUμzvœY½Ÿ{;φv}Ω<ΪϋΊλYWϋO’ΩρΚ\ν½οKžuwœ/›Fx_w=AΗ( 7­“U­λΘ’JηΛΚVu$}Sͺ]7Ψϋφύίθέ?ž λ A$o`aIf "‘aaaa‰‘Θ0ˆ0ˆ@<Ϋ b¬ΆJ•jrΣM7—jΥ«ί&_~ω₯½OΕ!33CμD 6ŒΨS_Ω‰³uλΦΚΪ΅kΔ†³zυ*q_n—·λΫ '{J­]»vΚή½{ΔNΜeggIΠm/Ν’υΔvQΩS‹mφˆ,~‰|uλΕ²qΘΓ’μOVVνωψmYVη χΗΟΏΌα·Ή*ζϊβϊίδΊΞqν―eα5yΞSαά@6„€}π–έΖβ4kΦ,ωκ«―δ½χή“W^yEl(±!$55U>όπC :ζ©ΌφΪk2~όψ|μεAΧ) 쏗οίΏOlˆ°Αܞ’qΝe2gΤ³2ΉV+qιςΔο«δ3β2οεžΙwΆ–9£Ÿ;ŽΧގ½]»‰ϊGΥO~έΝ<ίζ}έ ©‘ΛΎσu€ψaΙΓ Β ’ΜDΚ6‘H0ˆΔƒ₯O± "ƞ ΚNΘ―X±ΌT±Ϋe·3θ}(IφΤ vBΘ†ŠφΛΎ}{Ε† {?μΏν„’]ήoΗK”§€’²μφΗΛ/^,ξεV = αʜχί_μzξεΚ*ϋ~aίGlΘχύΘΨΛνrv=;ί‡@Ό0ˆ0ˆp" @Rc‰ ϋ~aίGD@’)φA €1ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz " ι1ˆ€€Η ’ƒHz " ι1ˆ€€Wΰ ²qγz€„βξ " ιΈ{ƒH:ξήΑ ’Ž»w”/_^D@pχŽy;ƒHξήa;ƒHξήΑ ’Ž»w0ˆ€€γξ " ιΈ{ƒH:ξήΑ ’Ž»w0ˆ€€γξD@²qχŽςεΛ ƒHξήa;ƒHξήΑ ’Ž»w0ˆ€€γξ " ιΈ{ƒH:ξήΑ ΖΔwΊJŸι·Λk ΖJκ†5tP:Έ{ƒH "$.wο`qΜ_ό† {γ>Ω–1I^ψ€­ œQ[–ώ\‚ŽJ–»w0ˆ8DH|ξήΑ ’gΓΖTόΪύ²rχ09pb΄d~χ’LΌΌυιd :V2Έ΅ζr퍕dΚΤη%ΧdΩ²%bΧ7οΝyO‚@€ά½ƒA$ƒH~ "€Dζξ "yή]8MΖΝi"ιί>#iGϋʎΜρ{ϊm²zέR :V2`$2wο`ΙΓ ’ƒ ‘Ή{G™DR7¬ϋcιλφ •΄£ύεΰ7γdκ‚–2sή( :V2‰vπ(ƒ 8Ή{ƒƒH @"sχŽ2?ˆΌ6)yv^sI;2BΆe=,kχEά〦•zυ닝ط!bεΚε­gO±ΧχξΧOάγύhyν5±Χ4ˆόp{r‡{}Η.]dΙ’ΕςΙ§ Δn§6„u±·W½{Ε^Đ!bCM—ξ=Δ^oD±ΰξ " " "€€γξI3ˆ¬M])C^o$_©#Ÿ-›#ξε_ψπ1y~~Ωx ·¬Ϋ›" 6t“GgΦ“ SΕ=Ξ+3gŠΠ―xsY»v΅Ψεζ~0WμrΧWͺ,«V­»œ;ˆΌ6λ5±Χ4ˆΈ·Η,]ΊXμ8)κ ςϊoˆ½ά¬\΅Rμϊ|ψΈ—cΔ‚»w0ˆ0ˆb$2wοHšAdά۝δΉy εΓ΅€ΟτκςφηΟΚς5_Κ#ΣkΘ²ν=sνh)kΣ–'_―+.zM‚ήfΘΈ Δ=±©η},vΌhχφΨQ·λGͺ¨ƒΘδgŸ{ΉύQy±CΎϊj‘Ψε ƒ ά½ƒA„A$ƒ ‘Ή{GΒ"sΏxYΟͺ-K·w•ΕΫΪΚ§:Θc―έ)fΤ‘>i$KΆ·•―Ά=(o,n&Γf5‘ ·ι7cζ+b'τZ₯šΨΊΞ©άPΉͺΨρμψφϊχ?x_μυΖž2 ίΫ:@"sχŽ„D>Y2[ϊN―!sW6“…›šΛ§Κη[Λ³Χ“Ο7xνωdύύ²pSkιϋςmςω²9τ6ύlψΈϋώϊb'φϋ?ϊ¨ΨM·§Ίš2mͺ΄λ”"ξράγτξΧOV\.Ίv{½±AΔnO½ϊˆ½Ύc—.²dΙbωμσOe€wCάΫQΤAΔήώwΧ{ύC†ΘŠΛ€Kχb―7 "€Xpχ@qχŽ„DΜΗ_½&½_¬!/v―Μ_ΧH>\SO€6–Χޟ§ΎΨPςΤμŽτ6NeωςebΓ]υξ{ ­;κά-=zυ’yσ?χ8οΌχŽΨ aΧΏ§~yjόxq‡Dμ86<<ϊΔb·ΗώΘω} Ι[oΏ%ώΫRΤAΔ^ιgŸHΣV­€-·J{ο—±O?-v}Γ ˆwο`aa$wοHšAΔ,^Ή@쏧?=χN™»²žΌ³ΌVž;ςά#O»U–¬ϊT‚Ž ƒ»w0ˆ0ˆtά½#ι³jέ2φz2λ6™΅θysq‘³o“ηζφ‘ c€Δβξ " "$wοHΪAΔ¬ί°V&ΏΧSϊΏ\]&XE~αVY΅v±$wο`a ιΈ{G"Χ<-=§U“YŸL Λ€Δδξ " "$wο(sƒH~ξήΑ ’Ž»w0ˆ€€γξ " ιΈ{ƒH:ξήΑ ’Ž»w0ˆ€€γξ " ιΈ{ƒH:ξήΑ ’Ž»w0ˆ€€γξ " ιΈ{ƒH:ξήΑ ’Ž»w0ˆ€€γξ " ιΈ{G±"wOΪ”:AU@ςpχ”IAU@ςpχ”IAU@ςpχ”IAU@ςpχŽ‘ >ŽJΠΙh €=VΙΓέ;DP&=VΙΓέ; Dˆˆˆˆˆˆˆˆˆˆˆˆ-wο`!""""""""""’€Λέ;Dˆˆˆˆˆˆˆˆˆˆˆ(ιrχ"""""""""""JΊά½ƒA„ˆˆˆˆˆˆˆˆˆˆˆ’.wο`!""""""""""’€Λέ;Dˆˆˆˆˆˆˆˆˆˆˆ(ιrχ"""""""""""JΊά½ƒA„ˆˆˆˆˆˆˆˆˆˆˆ’.wο`!""""""""""’€Λέ;b6ˆ,Xπ1@±Š4wο` #ά½#ζƒΘ?ώρ}™β6ι›I1qΑυH‹ηZHΠeN%ΪλΗΪ%Υ.‘zΧ“ ΛHlDDD§*55U,/3~DDDDDD±Κέ;D’δt’°(D$""’SΕ BDDDDDρΞέ;b>ˆμΩ“&Λ–-=%»άΏϋ;₯~ΌΜΜL±_πϊ,κθιOΛ›{σ”μrΏ»μwR§)μρξn~·΄›ΨNάλ» :ž±ΛΓΟ.7κΛQrSε›δΕ}/JQηΏ-A8^0ŽŒγ+κρμλ ΛΎN”ϋυ4ŽΗ Ζρ‚γxΑ8^pΕu<βGDDDDD«ά½ƒA$ŒHgΏΠΩ/‚ώ“Š~…=ΑΘ ’Ÿ]Ξ[‚pΌ`/Η VΤγωOŠωΩΧΙ‚rΏž†Γρ‚γxΑ8^p/Η ΈŽηAόˆˆˆˆˆˆb•»wΔ| zZ©dζτ42E‘θO™υϋ+~/Ώ<ο—dB Ί,’Ηi§V$φx :fa;±zϋeQaς ~DDDDDD±Κέ;D’δt’°(Dˆ‚Ζ†HΔj:v$bυφΛ:""’ΒδAόˆˆˆˆˆˆb•»w0ˆDΙ-θ$!”DDD…Ι?‚ψΕ*wο`‰’[ΠIB( ˆˆˆ “ρ#"""""ŠUξήΑ %· “„(;ˆˆˆˆ(²ό#ˆQ¬rχ‘(Ή$GΩADDDD‘εAόˆˆˆˆˆˆb•»w0ˆDΙ-θ$9Κ""""Š,βGDDDDD«ά½ƒA$JnA'ΙQvQdωG?"""""’Xεξ "Qr :I^ ή4XώTρOςΣω©\Rν ΊŽίνέo—Κ­*KΠeIq½?DDDD\jjͺXώˆˆˆ(VΉ{ƒH”ά‚N’— "ω1ˆΕ7"""""ŠwξήΑ %· “δ₯ψ―֚L8:A‚.[0ˆΕ7"""""ŠwξήΑ %· “δ₯ƒH~ "DDDDρA„ˆˆˆˆˆβ»wΔ}™7οc©R₯Š”+w¦\xαŸeψπαtݐυλS₯FR\99οΌσdΠ t]Ώ#Fȟό'9γŒ3€uλεΨ±£t]?7{jͺΣN;-ŸΣΟ:].z±ty―‹T/\΄{΅]¦,a!"""Šo "DDDDDοά½ƒA„A€Lb!"""Šo "DDDDDοά½#ξƒHέΊudΑ‚ωrδΘaYΈπs9묳dΪ΄ibΧϋώϋΏΛε—_.:΄—μμ,YΎ|™Ψ02uκTρΏν1cFΛωηŸ/Ÿ|²@Ž="/½4]ζϟ'ξυ]nξ 2hυ Ί}¨4Σ@ώυτ•nοw“ “λ±τ›ΏόF:½ΥI‚.S–0ˆΕ7"""""ŠwξήΑ Β R&1ˆΕ7"""""ŠwξήχA€ ΅kΧ{κ*{ωΝ;Δ††mΫΆ‰Ί!½zυ’š5kŠϋϊ?ώρςΚ+3Δ}}aΉύhY3Hά畬,—ΥΈLά׏=4Vͺ§T—sώpŽœω«3ε¦f7ɘƒcΔ½ώE7_$v;ΒΉ€Ϊ%β^ΏΕs-Δ½|€‚½ύZΧ’‹*yνωΩ?{ΏGν%ξυ£}ŸΨψ„\zλ₯ςσ3.v»nhxƒ0ˆΕ'"""""ŠwξήΑ βΌΎ°άDrΩΫg!"""’P "DDDDDοά½£Τ "'N—ςεΛΛ€I“Δ^ο"Ϋ·o1BlΉΰ‚ Δ^Ύ>±λΫU··wφΩgΛ< 챃ΈE:ˆ4ΤTΞψεβΎήNΨ_rΛ%2x³w\ΟΘ΄‘rν=׊ +ξυ]ΏΉθ7RΤ§Μ*μSLΩπ`OΥeO6|ΧpωύΏ—{ί#ξυ£}/ΌιB±αdτώΡbOQfOYΖ BDDDT2ωG?"""""’Xεξ " "a‰ E–ρ#"""""ŠUξήQj‘φνΫI΅jΥδ»οΎ{½ύQυΛ.»L:vμ(ξU·?–~ξΉηŠ]σζMbC…½]»vʞ=iRΉrei€‰ΨυΓq‹tiσrωΙO~"OL”1ƈ]ΐςβ^ΏοβΎnPq•Τ Rw`]q_G―;δΖ&7н<ΪχΨΞabΧ|ύγβΏnΘΙA…A„ˆˆˆ¨Dς ~DDDDDD±Κέ;DD"Β """"Š,βGDDDDD«ά½£Δ‘~ύϊΚ΅Χ^+‡$θ²!kΧ4Κ•;SΌςJιΣ§·\tΡ…bΧKKΫ-v’ό7f‰Ψ!3gΎ"ΏύνoΕ}½Λ-A€ΩδfrΖ/Ξ{yeύΕ©±ιcΕ6όJji<Ύ±Έ――3 Ž\wοub/φύο·€ŸΨ˟Κ|Jόo;δΦN· ƒQΙδAόˆˆˆˆˆˆb•»w0ˆψŽΒ ŒA$2DDDDYώˆˆˆ(VΉ{G‰ "ύϋχBΣJΠe £K—. A±—ΫSnύ⿐7ί|CόΧ yε•ς»ίύNάΧ»ά"Dͺ΄"—ΥΈLμεφΗΏνϊφGΘύΧ-ŠDD’}νςvύΠΣe…Έ—γ)³ˆˆˆˆJ6βGDDDDD«ά½ƒAΔwέ‘` "‘!"""’Θς ~DDDDDD±Κέ;β>ˆτνΫG»ξ:9t(]‚.dΚ”)ςΩgŸJVV¦Ότt±§Πϊβ‹…β^ΏmΫ6R©Mξͺ·lΩRάλ»άΒ "Γv “FγΙΟN™tΫUάλ¨(ΧΤ»FžΨψ„Œ98F:½ΩIlXq―οJ”AΔDϋώ₯ς_€R‹Jb¬½ϋέΕξHߟ³ΛŸ-Wέu•]&„ˆˆˆˆ"Λ?‚ψΕ*wο`a‰ƒƒQ,σ ~DDDDDD±Κέ;β6ˆ?~Ll((H­Z΅Δ=Žύqτš5kΚgœ!*TΩ³g‹{=“%Mš4‘³Ξ:K~υ«_‰½<‘ΖΝDΜιεN—ΏTω‹t~·³T±?^£K ωΥ½Ϋη±?Β^‘Žχώz, AΗπ+μ rξηŠϋ~ΈΞψ₯w{<ξυ£D’}oφ>žK«_*?·Ÿ‹ %7·ΌYDˆˆˆˆβSjjͺXώˆˆˆ(VΉ{ƒƒH ‘όDˆˆˆˆ’‹A„ˆˆˆˆˆβ»wΔmIVnA'ΙQvQp "DDDDDοά½ƒA$JnA'ΙQvQp "DDDDDοά½Γ7ˆtφώGη] μ˜ Ρ ™Ή$GΩADDDDΑ1ˆQΌsχ‘(Ή$GΩADDDDΑ1ˆQΌsχ‘(Ή$GΩADDDDΑ1ˆQΌsχ‘(Ή$GΩADDDDΑ1ˆQΌsχ‘(Ή$GΩADDDDΑ1ˆQΌsχ‘(Ή$GΩADDDDΑ1ˆQΌsχ‘(Qασ ~DDDDDD±Κέ;D’DDDDDD…Ο?‚ψΕ*wο`‰>βGDDDDD«ά½ƒA$JDDDDDTψό#ˆQ¬rχ‘(Qασ ~DDDDDD±Κέ;D’DDDDDD…Ο?‚ψΕ*wο`‰>βGDDDDD«ά½ƒA$JDDDDDTψό#ˆQ¬rχŽΈ"σζ},UͺT‘rεΞ” /ό³ >\‚²~}ͺΤ¨QCΚ•+'ηwž 4PάλmΫΆMN;ν΄ˆάpΓ βΗEDDDDD…Ο?‚ψΕ*wο` ƒA„ˆˆˆˆ¨ψς ~DDDDDD±Κέ;β>ˆΤ­[G,˜/GŽ–… ?—³Ξ:K¦M›&v½οΏ»\~ωε‘C{ΙΞΞ’εΛ—‰ #S§Nێč7ώUF)A—ρ#""""’‚KMMΛ?‚ψΕ*wο`q0ˆΕ>"""""ŠwξήχA€ ΅kΧ–Φ­{ωΝ;ĞʞΛݐ^½zI͚5Ε}}86¨œ~ϊιrπΰ Ί¬ƒΕ;wο`ΙΓ BDDDDT|1ˆQΌsχŽR3ˆœ8q\Κ—//“&M{½;ˆlίΎMόΗ±Aδ‚ .χυα΄iΣZ7n,A— BDDDDDΗ BDDDDDρΞέ;Dς0ˆ_ "DDDDDοά½£Τ "νΫ·“jΥͺΙwί}+φzϋ£κ—]v™tμΨQά?ͺ~ώωηΛΉηž+ώ·$33CΞ<σLωδ“tΩ DDDDDTp "DDDDDοά½ƒA„A„ˆˆˆˆ¨Ψc!""""’xηξ%>ˆτλΧW½φZΙΘ8$A— Y»vΨpRά™rε•WJŸ>½ε’‹.” cψ=υΤXΉτK%θ2§BDDDDDΗ BDDDDDρΞέ;DDˆˆˆˆˆŠ="""""ŠwξήQbƒHώύΔ†ττƒtΩΒθ₯‹4hΠ@‚.γgOΑ5jΤH ΊΜ©Qασ ~DDDDDD±Κέ;DDˆˆˆˆˆβžρ#"""""ŠUξήχA€oί>rέuΧΙ‘CιtΩ S¦L‘Ο>ϋT²²2ε₯—¦‹=…Φ_,” c„ΜŸ?O~ώσŸΛΑƒ$θ²§BDDDDD…Ο?‚ψΕ*wο`a!""""Š{ώˆˆˆ(VΉ{Gά‘γǏΙi§‘Z΅j‰{œ΄΄έR³fM9γŒ3€B… 2{φlq―ηͺ_ΏΎ4jΤH‚. """""*|ώˆˆˆ(VΉ{ƒƒQάσ ~DDDDDD±Κέ;β6ˆ$+"""""*|ώˆˆˆ(VΉ{ƒH”ˆˆˆˆˆ¨πωG?"""""’Xεξ "Q"""""’ΒηAόˆˆˆˆˆˆb•»w0ˆD‰ˆˆˆˆˆ Ÿρ#"""""ŠUξήΑ %"""""*ΈΤΤT±ό#ˆQ¬rχ‘(QΑ1ˆQΌsχ‘(QΑ1ˆQΌsχ‘(QΑ1ˆQΌsχί ’ϋ?ά Dšύ4$3·IίLŠŒˆˆˆ(Yc!""""’xηξ "Qr :Ι DŠˆˆˆ(Yc!""""’xηξ "Qr :Ι DŠˆˆˆ(Yc!""""’xηξ "Qr :Ι DŠˆˆˆ(Yc!""""’xηξ "Qr :Ιν7£[=™6«›]Ιγ₯!MεΕ ­%θ2~DDDDΙƒΕ;wο`‰’[ΠIn?‘²…A„ˆˆˆ(7"""""ŠwξήΑ %· “ά!Ο­|L^Ώ½’L>6Q‚.‹δρ̞Q2λζŠ2y ΊlQYΙ?‚ψΕ*wο`‰’[ΠIξ‘²‰A„ˆˆˆ(8βGDDDDD«ά½#ξƒΘΌyK•*U€\Ή3εΒ ,Γ‡— λ†¬_Ÿ*5jԐrεΚΙyη'ƒ ” λ†lΫΆMjΧ-ΏψΕ/δΧΏώ΅<ψ`+9rδ°ΓΟ-θ$wΘΛύι#›KΠeNε…)νδωOϊHΠebιΉUΛ+λΘ¬―“ΧkU»=A׍…)Ÿχ“™ΝjΚ¬•“oΩΆtέβνύJο~τΌ0΅ƒ]&„ˆˆˆ¨¬δAόˆˆˆˆˆˆb•»w0ˆ0ˆbΙ/ΪϋŸA„ˆˆˆ(ώˆˆˆ(VΉ{Gά‘ΊuλΘ‚σΕ†‡… ?—³Ξ:K¦M›&v½οΏ»\~ωε‘C{ΙΞΞ’εΛ—‰ #S§NΫ±!ΕnΗ‘Cι²}ϋ6Ήκͺ«€gϞβ^ίεφ£“ά'&Κλ•+Κ”/ȏ.η˜Ρ§ΎLΧ[Nž_ΠG^x₯³ΌψτƒtŒhΌμ½ν&&gŽ“)+{¦ΎέC‚Ž b¦|Ρ_NΎύΕΕšβϊγτ±Ύ_x‘£Ψΐt™"""’²’ρ#"""""ŠUξήΑ Β ˆA„A„ˆˆˆ¨8σ ~DDDDDD±Κέ;β>ˆĞΚͺuλΕ^Ύsη9ν΄ΣĞϊΚݐ^½zI͚5Ε}ύoϋ[™>ύEq_πΓ½€V­ZβΎήεζžΰ~vΣyγͺ«dς‘§Δ½œkrΦΣ2}LKy­vyυώ[ε…—:Ι€cr£8½ωnyιρFt™βdOAeOEt™hΔϊώ?9δ\„»QYΙ?‚ψΕ*wο`q^Ο """’hς ~DDDDDD±Κέ;JΝ rβΔq)_ΎΌLš4Iμυξ bOqε?Fˆ "\pΈ―οΨ±ƒΤ«w·dd;ώΥW_-Ο>ϋ¬ΈΧwΉΉ'ΈŸ_Ψ_Nžw^ŽqlKωΡ ω—S$ςњ|l’LY2HN>eΦϋ½$θ:Εaςαρςzυ›dڌ Ίl4b}?»y¨Ψ0φΜήΡβ^Žˆˆˆ¨¬δAόˆˆˆˆˆˆb•»w0ˆ0ˆD„A„A„ˆˆˆ(–ωG?"""""’Xεξ₯fiίΎT«VMΎϋξ[±ΧΫUΏμ²Λ€cǎβώQυσΟ?_Ξ=χ\ρΏΜΜ ©\Ή²Ψΐbš6m*ξΫΗΝ=Α]ΤA€ ?κmC@qύQu3έ;vˆΘ7ΣG· λ§—6”™-ξj‚.XίΟm*v1ˆQY+55U,βGDDDDD«ά½ƒA„Aδ”DDˆˆˆˆbƒΕ;wο(ρA€_ΏΎrν΅ΧŠ=…UΠeCΦ]#6œ”+w¦\yε•§OoΉθ’ ΕχχΏM»ξ:ιάΉ³deeʞ=ibΤ½I“&βΫAάάάξU&ύ)q/W“'δ?ι#A—)N6<<·ϊqy΅nUyαΩΆtX²?nnOY5ωΰX ΊlqˆφώηͺQYA„ˆˆˆˆˆβ»w0ˆ0ˆD„A„A„ˆˆˆ(šDˆˆˆˆˆ(ήΉ{G‰ "ύϋχBΣJΠe £K—. A±—oΫΆMμ©±Φ­[+ώλ†ΜœωŠ”+WNάΧ»άάά“NLϋ#δSΎ ?Ί\‚yqR™Ω Ί]&쏚ŸBφ‘ Λ–f/ΌΨQf6½]‚.BDDD”¬1ˆQΌsχίuCD"Γ R8 "DDDTΦc!""""’xηξεΛ——Έ "}ϋφ{κͺC‡%θ²A¦L™"Ÿ}φ©ΨS^½τt±§Πϊβ‹…bΧϋζ›rΞ9ηˆ=e–ύQφ½{χˆ=eΦΝ7WΫβt’;δε~Θτ‘Ν%θ2₯Α3;FΘΛ}κΛsλΛ€ΓOΛskžΧξ&/ j(AΗς{½ΖM2£c ΊŒŸύΡφWλW—gŒ• Λ&‚WΪΥ–¦u Λ„%k "DDDDDοά½Γva) "DDDTΦc!""""’xηξqDŽ?&φ”U©U«–ΈΗIKΫ-5kΦ”3Ξ8C*T¨ ³gΟχzζΛ/Ώ”ͺU«Š=5– %υκέ-_ύ΅ΓΟ-θ$wΘs+“Χn»I쏔]ΆDε=ΕΧ΄Ω=δΥ5dVΕkΕ†—žh,“³ž–ΐcωD<ˆδ /φGθ ςJΫ»$πX₯ΐ3i£dV₯λ₯ §ό""""JΦDˆˆˆˆˆ(ήΉ{ƒƒH~ "1Ε BDDD”ƒΕ;wοˆΫ ’¬ά‚NrϋΝθ~L{½«]Ιγ₯!MeϊψΦt?"""’²’ρ#"""""ŠUξήΑ %· “ά~ "e ƒQpώˆˆˆ(VΉ{ƒH”ά‚Nr‘""""*+ωG?"""""’Xεξ "Qr :Ι DŠˆˆˆ¨¬δAόˆˆˆˆˆˆb•»w0ˆDΙ-θ$7)"""’²’ρ#"""""ŠUξήΑ %· “ά@€ˆˆˆˆΚJώˆˆˆ(VΉ{Gωςε…A€ˆά‚Nr‘""""*+ωG?"""""’XεξΆƒ0ˆ‘[ΠIn RDDDDe%βGDDDDD«ά½ƒA$JnA'Ήΐ©QΩΛ?‚ψΕ*wο`‰’[ΠIpjDTφς ~DDDDDD±Κέ;D’δt’œ%©©©bωG?"""""’Xεξ "Qr :ΙNˆ’?"""""ŠwξήΑ %· “ˆ(ωc!""""’xηξ "Qr :ΙS "(N "₯[iDD”ό1ˆQΌsχ‘(Ήδ) §DDμvVk7Z&$A—M&CΎž eu(λοYCDΙƒΕ;wο`‰’[ΠIž’`AqbI " "e % "DDDDDοά½#ξƒΘΌyK•*U€\Ή3εΒ ,Γ‡— λ†¬_Ÿ*5jԐrεΚΙyη'ƒ ” λ†D{}—ΫWo6”œ;O+”χ–υ;1Δ ‚β”hƒΘΧ—v―Ž“ Λ$£hnο?-g—*A—)Ν}Iτϋ?ވ(ωc!""""’xηξ " "(ƒDƒƒHYBDΙƒΕ;wοˆϋ R·nY°`Ύ9rX.ό\Ξ:λ,™6mšΨυΎώοrωε—K‡ν%;;K–/_&6lL:Ubuύpάά<Ο› 6||ΣϊJάγŒά3Qnh0Jμςg~˜άΦu΄<=Iάλ?±q‚\zλωω™Cδ’›‡Λ GJq "Ρή~»v"<œKͺχϊE«ŸέώΖγNJϋϊ:ΖΘuχŽχυ¦°ƒΐ€γΕŠ cξqZ<χ”Έ—τρbOqV½σh±ϋοŒ_ {ό98Q‚ŽRΤAd쑉R=Ε{ϋžsώ0LμγvS³QRΠΫ/¬Xέ±ΊύWέ5B*΅π§ž‹«Ž=}ˆΨνh7sœΔκρο:»όΩrΥ]WIΠeBˆ¨μεAόˆˆˆˆˆˆb•»w0ˆψΒ ’‹A€hbuB‘A„A$„A„A„A„ˆ’9βGDDDDD«ά½£Τ "'N—ςεΛΛ€I“Δ^οΫ·o1BlΠΈΰ‚ Δ^νυΓqsOπD;ˆΨυ>ό"Eζ.ξ"φς½ƒ»ή3GΗΛρvΏl xmk.8²Ί_$“NL”ΙyŽ€όQμrvύΉKΊJΞ]?‘C*ώΫb—·Ϋi–ΎzŸLK%,κ,s–t“hoΏ "φφfm vœμnΚGŸu»ά;«z‰ϋ~–PόΕo‡Κ¨½εΒ›†Λ΅χŒ”α»&ΚΟN*#vO;NΕϊ£δ²#Δ.ΨΊ b',λ#ώΫboΟNœΪ‰d{ ;!Z\ƒH΄·ίυ›‹†Iq?eV¬>~%5ˆΈbυ”MvβΎ°ƒˆΘ·‘`ΨΞ bχ§π:FHQί\.Ήe„ ήk¬ΨλέAĞ2ΛŒ Ρή~w±§τ²Εž‚λ ύΔ.η>eWQΩ Ε‹*{ΉH;pŒΨΛΟ½`˜τ_6^&›$?ύΧ!sώx±Λ›FγΖJω«†‰½άN8Ϋ δΗΧOuCNžPπw€’½ύαΔ{)κΗΟ^Ξ ’;ˆΨϋιΎΎύkγδ—Ώ*ξλMaί1rΩε,Ÿ ξεϊ./gόrˆΈ―•Βή±Ύύ6ˆTm3Z‚.γ«ΗQQΩΛ?‚ψΕ*wο`a‘X`Ι}9ƒƒHƒHαQΩΛ?‚ψΕ*wο(ρA€_ΏΎrν΅ΧJFΖ! ΊlΘΪ΅kΔ†“rεΞ”+―ΌRϊτι-]t‘Δϊϊ.7χO΄ƒˆύρq{Ήΰ·γι|ΨλΞm.φϊH½U™?ΏΨΛWΏP[μψfΟc׊]ξ΅-Ε^ο"ϋϋ_%ώc‰φφu™I; ΊM…a'έ?φ]΅ν(Ήgπ±—Ϋ‰ώ>‹Ζ‹;h<±a‚ΨεM‡YήΫρ”ϋυP±—χ[2^μϊαžηΦN£%ά‘Šφφ‡οA€¨?{9ƒHξ dβXq_ίϋ‹ρς“Ÿ‘‰Η'‰{ΉΒΎvbή.©±ι“$θ˜Ρ(μύλΫoƒΘ=OŒχυX=ώ‹ŠˆΚ^ώˆˆˆ(VΉ{ƒƒˆ0ˆ0ˆΔƒHξΛDDBD ‡ˆΚ^ώˆˆˆ(VΉ{G‰ "ύϋχBΣJΠe £K—. A ΊΜ©φϊnξ žx"'θyήλSŸ©)φϊ‚ΧSfνp•ψ$Ϊ۟°ƒΘ—γ%Ϊ§œ²?vl'JyΚ¬Β‰φγg/·?&ΐΘ±b/7Υڏ’‚‘‘{&Š}<νγtΩ έ?xZΞώύ0 ΊL$Š:ˆΨπγΎήξgϋγέξλMaίLŠzΕZaοXίώ“ƒˆσΈ 'V’"’²—ρ#"""""ŠUξήΑ β`a‰F΄'D‚ΩύΔ Β rͺχŸA$?"*νωG?"""""’XεξqDϊφν#Χ]w:”.A— 2eΚωμ³O%++S^ziΊΨS`}ρΕB‰υυ]nξ žx"ΟyZμνόΏΖΏ”·Φυ–η?%³½b]ςρ r΄Σωςο Λ‰ύΡς9KΊΙέυΩ9τ―bΧ7ED’½ύ‰>ˆΨΛ―Ώ€\q{»&Κγ©δw—χ›ΏT!•ZŒϋcΝv‚φg§•X"&ΪΫο²ϋ)Q‘κ)£εβͺ#dΤΎ‰b ϋ—η “‚cOΉΤdΒS2ρΔ$ Ί¬ί£k'ˆ Tύ–Ž— ΛžJQ‘_ύq˜ \5^μΏ=₯˜ CAΗπ+μϋ_ρ‘rM½\Olœ cN”No>-UZ’ cΔBQοXέώ2ˆœ]ώlΉκ«$θ2!D”ό₯¦¦ŠεAόˆˆˆˆˆˆb•»w0ˆ0ˆδD~|› #V'Dς³ϋ‰A„A„A„A„ˆ7"""""ŠwξήQΎ|y)φAδψρcrΪi§E€V­Zβ'-m·Τ¬YSΞ8γ ©P‘‚Μž=[άλ™h―οrsOπΔ{1/ο,»žΌAώΡδlω―{O—Œ‡ώ"ο/κ,ξυ_Ϊ3DΏVώγ3ε)[žͺ&ξSe™’"¦¨·?Y‘»'JΕϊ£δΜs†Κ/—«zηΡ2.{’ΨυΜΰΝδκ#δη6Tl(ΉΉε()A$ΪΫο²ϋ)Q‘'·L?uΈΨuEΝrKΗQι ’ςφ89ηό‘bO©T£Λh ΊŽŸ]ξΜ_y]ί†χςη^0LμrαœρΛ\ξυmΉ£ηωνΕΓδŒ_ ;αoC{}Waίϋ#γφzfμνW¨3B,Ÿ ξυcΝnG€χ¬n?ƒ•ΆDˆˆˆˆˆ(ήΉ{G‡Ό„A„A$‘’‰Υ E‘όμ~baaa!’čA„ˆˆˆˆˆβ»wΨ·§ΜJ6nA'y ,±A€ΕsOIΠe% "DDDDDοά½ƒA$JnA'y ,aAQQςΗ BDDDDDρΞέ;D’δt’Κ% "DDDDDοά½ƒA$JnA'y ,aAQQςΗ BDDDDDρΞέ;D’δt’HφǞ λχW “ cΖSΠm‹DiΉύΙ"Q‘ ΗF$xόΔ% "DDDDDοά½ƒA$JnA'y€Dt²7₯ε„pΠm‹'΄c‹AEADΙƒΕ;wο`‰’[ΠIpjDTφς ~DDDDDD±Κέ;:0ˆDΗ-θ$85"*{ωG?"""""’XεξεΛ—‘"r :Ι(•­ό#ˆQ¬rχΫADŠΘ-θ$ `DDTΆς ~DDDDDD±Κέ;D’δt’P0""*[ωG?"""""’Xεξ "Qr :Ι(•­ό#ˆQ¬rχ‘(ΉδKƒχ–? ω“ό4ε§rΙ¨K$θ:‰ΜήΏΣ:ž–ΟθΜΡtΏh―”EDDTΆς ~DDDDDD±Κέ;niΚ · “|Ι€A€pƒF΄ΧΚ"""*[ωG?"""""’XεξΆƒ0ˆ‘[ΠIΎdPω…ΚRν₯j2αψ Ίl2²ˆuЈφϊ@YBDDe+βGDDDDD«ά½ƒA$JnA'ω’ƒƒP܈ˆ¨lεAόˆˆˆˆˆˆb•»wΔ}YΎ|™Τ­[GΞ:λ,ΉπΒ?ΛΘ‘#$θΊ!G‘ζΝ›KΉrεδΧΏώ΅ Π_‚νυ]nA'ω’ΑC.vKΫIΠe’ƒΚ²nοw“³ΛŸ-A—‰%""JξRSSΕς ~DDDDDD±Κέ;DD"Β Β ‚²‡A„ˆˆbƒΕ;wοˆϋ ’E ™7οc9rδ°,^ΌX~υ«_Ɍ/‹{ύ.]ΊΘε—_.Ϋ·o“%KΛ9ηœ#Ο?ΌΔϊϊ.· “|Ιΰ7#Vt’ Λ$#”e "DDΛDˆˆˆˆˆ(ήΉ{ƒƒHDDDPφ0ˆQ,c!""""’xηξ'‘vνΪε„Έˆ4ϋ&h4(Œ{ξ©')))b/ώϋΏ‹ S¦LuCΊuλ&ΥͺU{y΄ΧΗ-θ$_"ΊhΔEb'ςΓΉdΤ%β^δ‘‘rΓ³7Θ™=Ο”³{Ÿ-·½z›<}τiq―o•TšVI.u±όk—»ν–x_]oπήΑRρيςoύ›œυπYboΏ ?Ÿ¨ƒΘE7{?O­‡kΙE•Όφό쌟Ιe5.“QϋFIΠ1Š’ΓλδΌKΞ“ί_ώ{ωέeΏ“ϋ†ή'gώΚ{ž cEγ‚λ/κ«‹½ύ3~q†άΠΠ{\zΖ#AΗπ³Aΰͺ»ΌΗ£'θ2±νΗoπfορο©ψ€χψχόΫΩήγίsΦoΌΗΏηΆήγί3α˜χψχΨυ¬ §ζ=^#p{χΫΕΆ£ADDΙƒΕ;wο`ρ]7„A$ƒH.‘Βa‰ ""JΖDˆˆˆˆˆ(ήΉ{G‰"ί}χ­|ρΕB±§ΜzγYb—Ϋ³'MμDœ=Ε–X!6tœ{ξΉb/φϊḝδKΏπ‰τ)³*>SQ.s™ O.ν~LΞtžΤ}§#Δ‘Ÿuω™tXΪAž:ς”]'δ·ξϋ#π㎎χν7όΈ‘#$Ρ‘ίόΕϋΈy­$ΓwyΟο―ψ½ά3ψ :FQΨ ς‹ίώBFν%ήt‘\{Ο΅b·γg§{Wψέ#$θ˜EaƒΘ98GμD°ΓΔnOυ”κt Ώ’DŠϊρ»«―χψχ΄{Υ{ό{ΖeyΟcλΌΗΏΗ«†c½ΗΏΗ½Ύα)³ˆˆ(–1ˆQΌsχίuCD‚1ˆ0ˆD‚A$6Dˆˆ(c!""""’xηξ%6ˆ<ϊθ ±ΒτνΫGάΛoήΌIμr6¬—zυξ–~ύϊΚλ―Ώ&§Ÿ~ΊΔκϊḝδK‘"φT?Mω©τ\ίSάΛ5šίHΚ?^^άΧDͺN―*A—)Š:oΧ‘λ&_'A— IτA€ξΐΊβΎώŽ^wȍMnχυEeƒˆ=Ε“½Όr«Κβޞs/8Wϊ/λ/φςhΩ Rg€χqφΈ―oZ{ωεο~)ξλKZqόμ~Ήξ>ορο ΊLƒΕ2"""""ŠwξήΑ Β οqΓ R ‘Ψ`!"’dŒA„ˆˆˆˆˆβ»w”Ψ bμ)³V¬X.—_~Ή >\μr*?ύןJΏ₯ύ$θ²§rώΥη˟ϊg ΊL•­ό#ˆQ¬rχ‘ˆ0ˆ0ˆD‚A$6Šϊρc!"’DΚ?‚ψΕ*wοˆΫ bOYυςΛ/IŊείώνίδόσϗΝ;Λ‘#GΔ=ΞΡ£G€yσζRά™bCFώύΔ½ž‰φϊ.· “|Ι °ƒˆ Ÿρ>Ξ3:S~ωΘ/₯ϊΜκ2ξθ8 :FHaΣxAc±!βg]~&6€άώΪνι ’²2EΞι{ŽΨS`՘YC‚γνυ «¨'Τ£UΪ‘;zή!Ώ½ψ·rΖ/ΐŠxKϘc$θ~‰2ˆ»žέξ=ώ=6€άήέ{ό{ DL.ήγΤsζ―ΌΟcύQv;NΠuόμώ―P§‚]&„ˆˆΚVώˆˆˆ(VΉ{ƒƒHDDD"Α  "DDTς ~DDDDDD±Κέ;Κ—//₯ζͺ'· “|βΛ‘Ο΅ Λ ψL)φ^=>κ!A— !"’²•ρ#"""""ŠUξή·!’¬ά‚Nςˆ/‘A„ˆˆN•ρ#"""""ŠUξήΑ %· “|β‹A€thZ{Ή¨Et?""JξRSSΕς ~DDDDDD±Κέ;D’δt’@|1ˆ” "DDδA„ˆˆˆˆˆβ»wπ7D’δt’@|1ˆ$&""JξDˆˆˆˆˆ(ήΉ{B$JnA'ωΔƒHb""’δŽA„ˆˆˆˆˆβ»w0ˆDΙ-θ$ `DD”ά1ˆQΌsχ‘(ΉδŒˆˆ’;"""""ŠwξήΑ %· “| t#’βA„ˆˆˆˆˆβ»w„Ɛš2ˆ•[ΠIPΊQρΗ BDDDDDρΞέ;Κ—Ώ:ηκ[κ2ˆ•[ΠIPΊQρΗ BDDDDDρΞέ;xΚ¬(Ήd₯ "DDDDDοά½ƒA$JnA'Y’Ιuχ]'-žk!A—bεΆ·IέAu%θ2eΡνέo—Κ­*KΠe€β’¬?"Šώˆˆˆ(VΉ{ƒH”ά‚N²$ΔƒH0”$"ŠUώˆˆˆ(VΉ{ƒH”ά‚N²$ƒ>‹ϊΘ―ώψ+™pt‚]ˆ•a;‡Ι™ηœ)#χŒ” Λ–% "(I "D«ό#ˆQ¬rχ‘(ΉdI "( "ΑDP’Dˆ(VωG?"""""’XεξqD–/_&uλΦ‘³Ξ:K.ΌπΟ2rδ ΊnΘΡ£G€yσζR\9ωυ―-τ— λ†Œ;FN;ν΄|ώε_ώE‚s*nA'Y’ΑΝ-o–;zέ!A—)ΝξvŸt~·³]₯ΧUw^%Œ|@‚.S–0ˆ $1ˆQ¬ς ~DDDDDD±Κέ;DD"Β ‚’Δ ’ƒJƒΕ*βGDDDDD«ά½£C—φρDZ΄h!σζ},GŽ–Ε‹Λ―~υ+™1γeq―ί₯KΉόςΛeϋφm²dΙb9ηœsδωηŸχϊwί}WD‚M<1QΞόΥ™γ£tΩ€RσJ’2;EN"οt–&šHu$θΙΔξDŒn ©ό ΊLYΒ ‚’Δ BD±Κ?‚ψΕ*wοhάΆaN«Ž-DD‚1ˆ$‘δΒ ‚’Δ BD±Κ?‚ψΕ*wού ‘Π(Rjώ¨ϊ=χΤ“””±—ύίŏ)S¦ˆΊ!έΊu“jΥͺ‰ϋzƒΘ©=ΊφQ±§spŒ]Φο’›/’ZΧ’‹*yνωΩ?“Λj\&£φ’ cD㩌§δΞήwΚo/ώ­œΝωh\#™pl‚#\Tο\]~wΩοδŒ_œ!74ΌA"½?£―A€ΓλδΌKΞ“ί_ώ{±χΎ‘χ‰ lv»‚ŽεΧsAOωΧΣUŠλγ«Ϋoόύ†ήΗΩc—?ϋχgΛm]o“§³ŸχϊOl|B.½υRωω™?ϋΌ²ΗOq.mίx)Ηo€xόε*©ΗΕΏΟήy€MQέϋ RΕ±`»`{‰"H4V^K ±δJ1 4j©P,€μ  EDDQkb7¨IŒζ&Ή{sοχ;ώΜp<ΛΞξΜΞξϋξησ<Ÿη ;ηΜΜΞΜ™}ηχ5gΒ!HX€€pσŽΤί!’O‘Κ’@€8+­ l…S‘uKA:°ί΄,ΥυUΏΐr]>α$,@RΈyGΩ‘―Ώώ‹œ3ηYiSfM›6UZ»χή{WZaή¦Ψ ―+«%­Z΅’ξrW‘u;ΰ‘ ΡΎ6>­pΆιv›Κ‘K†Κo›wΪ\φΈ²‡τ­#Žί"‘n rκoO•₯DjΆ¨‘—-ΊL^σΦ5²ΓΎδ‘}•Ύu$©NΣ D6n³±Όξύλ€}ί=zμ!ν:hΨ¨‘ωΞHι[gΦΛ_Ύ\ΪψΟΧΎX“ΪΞ'v–όY{ϋVπξ6΄› οCVΫήΎgμ+ύ‡_Λ Ύ@Ϊx,uA:νλΧO;ΟQ΅γβ[g!–κϊ*Χ_`Ή?(=Λ–-“F8 nήA B ²N Dг\½\ˆD“‚t`Ή_Ώ¬εΊώ τˆ@ΪΈyGΩ‘aΓ†J·°5hΠ@ιΆ_±β5iν–/Evο~Ό·‚―}Ο+^ΉB†ϋf΅ΒΈν—»<εΊ~Λm©ί¨rύ–λϊ€C iγζ""λ”@€8ΛUΠ#‰'ιΐr]ΏεΆTΧoTΉώΛuύ@ι!€΄qσŽοϋnƒ¨ΨŒ/4X—6eΦ’E eǎεˆ#€΅cΚ¬ςψƒ—ͺp½τ΅ kˆξr+tνyž]ž΄ί"3ϊI_›$΅‚ήi7Ÿ&έε—ΞΉT·ώzςζ―n–n»€΄€Θ_›$΄‚ξ]wφωAη$έ)6έvS9πΉ>wMϋ₯κΕξΏ[PώΥς_Ikoφ™šΩNΖf­›Iϋ|πόΑϊίψι2ά7λ!?;D–Ί ])ΧoZ–κϊ*Χ_`Ή?(="6nήA B ²N Dг Κ"Ρ€ XiΧoZ–κϊ*Χ_`Ή?(="6nήQφ@Δuψπα²K—.>φΫodMM7nœ χΝ:`ΐΩ΅kWι.w%Y·7ιfΩ΄eSyαcJ_Ϋ°•ˆ€­τμ{ΊΛ­πi/Ov—'mΕ"sJϋάυ'ΧDΪuεk“„qχί‚šb§,²—_[AΊR§,²γ”τυkΧ§}¨&=ε[ΧoTγnŸλ/žPzD mάΌƒ@„@dˆgΉ zΉ$‰fάύ§ OΏ¬εΊώ τˆ@ΪΈyGjΘκΥ«dmm­\²δEωΥW_ΚΕ‹ΙN:Ι>}zKw=ύϋχ—ΦnΥͺ•rΑ‚€M••+0q%‰ζώgξ/νeθΎ6a D‚‚^Λ-[Κ_ΎψKiG;>]{w•Ύu$i]Dv>jgyβ΅'J_›$Ljχϊρ^²Σ™ϋTΖ‘o”W,»BΆέ±­t_’mnwΐvrΏΪΜyΛhSΥ xd€lΨ¨‘,uAΊRί΄,ΥυUΏΐ€―ΏMΪm"wωΡ.Χ&+”H7ο !‰$HaVZA™@$š€+νϊMΛR]ΏQεϊ Lϊϊ#¨D mάΌ#΅@Δ¦Όš8ρNΩΉsgΩ€IΩΎ}{Ω―_?ΉfΝιη‹/ΦΘ^½zΙf͚J B† ,έ~ζΓ?$ΓΣ­ψlΡ’…τ­#¬‹―ΘR΄—φΦ΄―‘7}q“τ΅Νj«jDŽΊψ(Ωfϋ6²ρƍeη“2ΧF+4ϊΦQMΊ |Νκkd“M2χ‰ŒΧΎw­tΫ%eRϋ?ς‘²σ‰™σœ±iMSΩ’mζΎ’ρΠ~‡Κί|ώiύΜ+W\)wα$,@RΈyHL]|E–ϊ$H4)('#HyδϊΕrZλ'‚„H 7οhם$)R_‘«O ΚX—εϊΕrZλ'‚„H 7ο°„@€H]|E¬>)(c]–λΛiΉ?HŸp )άΌƒ@$¦.Ύ" VŸ”±.Λυ‹ε΄\Χ€O8 nήA S_‘«O ΚX—εϊΕrZλ'‚„H 7ο ‰©‹―Θ‚ˆˆˆ•-€O8 nήA S_‘+[HŸp )άΌƒ@$¦.Ύ" ¦'T&Λ–-“F8 nήA S_‘Σ*H7ο ‰©‹―Hι • €›wˆΔΤΕW€Ητ€Κ„@ΖΝ;Dbκβ+γ-7κΦιrtϋ—ε˜υ_ά*σΏ3ϊϊ#T&"6nήA S_‘ DͺH7ο ‰©‹―H_Υ~~«Σd…½Σy˚QΎ>1€Κ„@ΖΝ;Dbκβ+W΅"@ΖΝ;RD.\ »u;N6oή\v谍ΌφΪ‘Χ7λ_¬‘½zυ’Νš5“­[·–—]6Dϊϊf={–<πΐe³fM₯mĈΧΧ§‹ζΗ4ZΨΰΐυG·x5πΠωrΤάI2\Τ―OŽZ~›΄γpλqΟI_Ϋ$€Κ„@ΖΝ;DDJ*d!€΄qσŽΤ‘ΪΪZiΑĚ5”σζΝ“-[Ά”“&M”nώύϋˎ;ΚU«VΚωσηɚš9nά8ιφ· ζ‰'—ΆύgŸ}FZ@3aΒιφwu±ΒόχH›Wδ-_’£ž›(Η4}MŽn»LήςΩ­‘β~}pΤ’;€"£^ϊΪ&!Τ Β!HX€€pσ‘’J >Β!HX€€pσŽΤ‘|φθΡ]φνΫWΪηί~ϋ΄ΐcμΨ±2ά7λ\ »vν*έεω<φΨcε9ηœ-}mΒΊXaώH¨hŸuτ‘σ€”|ίζ₯ΫεχAΒ/~7Υ–M½υ})ΣδχύW—·φœ#Η΄Z.G·[&oνσ€ΌεγсΦ/‘ώΦΞφ/§[½,έώΕ uƒp )άΌƒ@Δ‘@$™ώΦΞφ/§"UI8 nήQφ@δλ―"ηΜyVΪ”YΣ¦M•Φξ½χή• 46ΕVx]Y-(iΥͺ•t—ηςOϊJΆkΧNήrΛ-Χ6¬‹ζσ"GΜ— δ DΎowΝCς–χΗΚQΣ§>δ9jξ$.κK79fžόA;ΗQ“ξ•ΦοΦ!I·έθΟIkwΛ‹wΘΈύέv"ΰ#‚„H 7ο !‘"&α$,@RΈyGΩΧαΓ‡Λ.]ΊHϋόΫoΏ‘555rάΈq2ά7λ€€M}ε.7‡ ,-ωθ£₯―νΊt±ΒόχˆM™*ΪG DnύΡσΫ6$Sf@%²lΩ2i„C°Iαζ""’@J €›w€ˆ¬^½JΦΦΦΚ%K^”_}υ₯\Όx‘μΤ©“μΣ§·tΧΣΏiνV­Z),xAΪTYΉ{iϋž{ξ)?ώψ#ιΆ‹ͺ‹ζΛˆάςeΰθέΆ~EŽZz{ΰΓ“ε˜υ_—£O™#λο;qŽƒWoیP™ˆ@ΪΈy”H7οH-±)―&NΌSvξάY6iDΆoί^φλΧOY³FΊλωβ‹5²W―^²Y³¦‚› ΛνgΑ‹½”=ŸG}΄tΧγκb…ω²"ζ›γε­'Μ•cZ.—£Ϋ. <ο)™kͺ«ΨύΏ“@²ˆ@ΪΈyH DD 9D mάΌ#΅@€Ύκβ+cz@eB iγζ"1uρι1= 2!€΄qσ‘˜ΊψŠτ˜žP™ˆ@ΪΈyHL]|EzLO¨LD mάΌƒ@$¦.Ύ"=¦'Τ Β!HX€€pσ‘˜ΊψŠτ˜žP7‡ a’ΒΝ;Dbκβ+cz@έ ‚„H 7ο ‰©‹―Hι uƒp )άΌƒ@$¦.Ύ"="Fͺ‡p )άΌƒ@$¦.Ύ"/"Fͺ‡p )άΌƒ@$¦.Ύ"/"Fͺ‡p )άΌƒ@$¦.Ύ"/"Fͺ‡p )άΌƒ@$¦.Ύ"oΦ#!8λιkƒXν@υAΒ$…›wˆΔΤΕWδΝJ ‚˜_¨Β!HX€€pσ‘˜ΊψŠΌˆM¨Ώ,[ΆLα$,@RΈyHL]|E^DŒ&Τ_D mάΌ#υ@dαΒ²[·γdσζΝe‡ΫΘk―)}}³~ρΕΩ«W/Ω¬Y3ΩΊukyΩeC€―oΦΈΫwuρyΛι_ 7i·‰τ΅A¬ ώB iγζ""ˆ#Τ_D mάΌ#υ@€ΆΆVΞ=KYσG9oή<Ω²eK9iDιφοίΏΏμΨ±£\΅j₯œ?ž¬©©‘γƍ“nΈΫwuρyΛ)Φ% ώB iγζ""ˆ#Τ_D mάΌ#υ@$Ÿ=zt—}ϋφ•φω·ί~#-π;v¬ χΝzΑΘ]»Jwy>sm?—.VΨ­S+4h°–œu€ }n»Άςθ_-·έ/σοŒ 7”;Ά“ΌξχΧIλwΩ’Λ€»έ\1ΰήvΨ]~΄‹ά―v?ΉύAΫΛ m(m=ηέ}ž΄~ΧΎw­μς“.²iΛ¦r“Ν7‘‡όpωΫΟ+ΓΫΜjίk{Θ&›4‘ΦΏϋεέεΝ_έ,έώq-φψΗ΅Ο”>r³6“›wά\Άέ©­μyuOiΗsΏ^™σ’Ρ·8n΅ΧVςΠ~‡JΫ~γΛ.'gΞkΖλ?Ό^ϊΦQŒP!€΄qσG‘΅%)μψΗ•@κ+"6nήQφ@δλ―"ηΜyVΪ”UΣ¦M•Φξ½χή•V€·)ΒλΚjAI«V­€»ά5κφsιβ+ςf΅ΰ‘Π@dΣν6•C— •#ή!7ο΄Ήμqeι[GΦΈSfY bA€μoότFιλ“΅σ‰₯Άί—Ώ|Ή΄‚·‘݀ۘK‘DŒ|{€Όζ­k䱃•v\άώqMκψͺߍΫl,―{:Ωaί"ۏ†2η%γΘw2Η'£oΕhHΝ5‚6;ώΆ?‡φ=TϊΦQŒP!€΄qσ‘uJ B B I@ iγζe D† *-ΰ0 (έφ+VΌ&­έςε―Θξݏ—ƒ’S¦ά#5j$έυ˜…n?—.Ύ"oΦb‘nΏμ&έεG]r”άη΄}€»άL*9θ§I_›°7}y“\Γυεŏ_,έv§όζΩn—v]~μcε]wIOM•Ο€Ž‘Z bA}n׍»?­Άj%‡,"νσΈZ rάeΗIwyο{zΛm[Hwy±@υAΒ$…›wˆ„Ά•@dm DDD „C°Iαζe DL›²jΡ’…²cǎrĈΪ•zΚ¬|ΫΟ₯‹―Θ›΅Ψ@δΤߝ*έεV¨ήσ„=₯»άL*ιρ«Χ&¬M©dηιWΛ%έv}¦φ‘ΝZ7“ξς?ΉQΪΤXφι ΫοΦ^Z ‘λ₯μqMκψͺ"Ωη{t§θΪtΫMεΐηJϋ<ˆœvσi]~ιœKεzλ―'“zΉ=Tα$,@RΈyΘ:%!!€RAΒ$…›w”=q>|Έμ₯‹΄ΟΏύφYSS#Ǎ'Γ}³0@vνΪUΊΛσ™kϋΉtρy³–+πHζxdάdσM€―ΝΊό>q ρΉLjΚ¬\^ϋή΅ϊ|ΓΙΧ6Žu.™;PΪηq΅@ΔΎ§»άφΣ^ώξ./V¨Β!HX€€pσG‘΅%!Ικ.'€Έ„C°Iαζ©"«W―’΅΅΅rΙ’εW_})/^$;uκ$ϋτι-έυτοί_Z»U«VΚ ^6U–˜$΅}W_‘7kΉ‘aK‡I (Ώ0XϊΪϊ,41χϊρ^²Σ™γ™qδΫ#εːmwl+s½΄ό˜ΗȟNό©Όώƒλε―^ύ•άt»Mεi7&έώq% ‘–[Ά”Ώ|ρ—rΔΫ#€Ÿ½»Jί:ΒΪ”mv=ωΪd€κ!‚„H 7ο !Y§"""P Β!HX€€pσŽΤ›ςjβΔ;eηΝe“&MdϋφνeΏ~ύδš5k€»ž/ΎX#{υκ%›5k*-2d°tϋ%΅}W+μΆΪ*³?νεβΉlά’± …³&]?¬a²iΛ¦ΆoA―OΦb‘‘οŒ”OΜηŒMk2ΫΝΨ’m yhΏCεo>tϋ_ΉβJΩω€LŒvœlЦƒΟ?XώnΝο€Ϋ?I¨VZ rΤΕGΙ6Ϋ·‘7Μ‡Œv^,¨ς­#,Έ„C°Iαζ""" DD ΄„C°Iαζ©"υU_‘±iHν˜ZιkS  ώ²lΩ2i„C°Iαζ"1uρyλš"4"6nήA S_‘±I IC iγζ"1uρyλš"4"6nήA S_‘±I IC iγζ"1uρyλš"4"6nήA S_‘£ υH7ο ‰©‹―Θ‹ˆΡ€ϊ €›wˆΔτdςq-—M™"νία$,@RΈyHL@θ‘ D mάΌƒ@$¦? τΠ‡ˆˆˆˆˆίΉjUΰw‡ a’ΒΝ;DbϊΒ}ˆˆˆˆˆH )γζ"1ύα‡ΎuyΦY?ώq ― ’λQGθkƒυ_ξuΓΪΪΐώύ}m0·Ο?Ψ ΑΪφθθλS‰vλxΙ%Ύ6•θΞ;Ϊqίl³@_ΫJ΄Ύ\?ε6ιίH7ο ‰ι?τ­K šXŒ"˜•ϋGݐ@$ž"ε•@³&ύ{C )γζ"1ύα‡ΎuIA 1ϋ¬›oψKΎΆXεώQ7|ϊιΐ-ηΞ τ΅Εκ΄Ÿx"ΠΧΆ’­«ˆy뭁u=©«ΧO}“@RΖΝ;DbϊΒ}λ’‚&"†εώQ7$‰'HeH ‚IJ )γζ©" .έΊ'›7o.;tΨF^{νHιλ›υ‹/ΦΘ^½zΙf͚ΙΦ­[ΛΛ."}}}ώιO_ΙwάQΆhΡBϊΪϊόα‡ΎuYW šγΖΦ΅BHRVΚχοΩ3π§? τ΅Αδ­ΤλŸ@€΄.\xόρM›ΦΤφιθλλ³kΧΐK/ τ΅ΑZhAϋ±Η­ύΜ™n»nl$Π]nηΙΦcΏ~ Ϋ>ŸQ‘Jέ,Ζ\ΏŸ"2nήA B ²n+΅ œ–•ςύ DΚc₯^"₯•@€2$!‰#HyΝυϋI )γζ©"΅΅΅rφμYr͚?ΚyσζΙ–-[ΚI“&J·ώύeǎεͺU+εόωσdMM—yΛκφw8πRΉώϋKΗ\΄ΥbΉΏΛ/fIyΫmΎΆ˜Ό•zύˆ”ΦΣOάvΫΐY³οΉ'ΠΖγ•WϊΦvΠ ΐ½φ τ΅ΑZ@Δυζ›λJ βw D°sύ~ˆ@ΚΈyΘΊΝυ@[-–ϋϋˆ”ΧJ½ώ DJ+HeH B G‘ςšλχ“@RΖΝ;RDςΩ£GwΩ·o_iŸϋν7±cΗΚpί¬\pμΪ΅«t—›6uWηΝεέwί% D¬°±Ο>VΈΨsΟΐc ΜUΠ|α…@+ΜΩ₯βΊwœ??ΠνάsGΈρƁmΪfŽ‘\Ί4Πϊ=π@ ςi…ΩπΆΓ|pΰ 'vιΈΡFΆ+πX?;NC‡†Χ™5smΘ# t—›cΖξΆ[ M}³σ΁'Zϋ€Ώ\|0ΠΆ—λ|»Ζ½~žy&πΠCνΈν²K MαeηΧνW;ηžΈΗξ·_ ]ηn+`θGvύ·lX[XκλΏXΛ}0 ?Iiλ?γŒ@ &š5 ΄οŸo Υ υ«@·]―^v?s—»ήyg έχάλ.i‹½ώΝb?’–@€~"Φ―TΏΉŒˆΨώϊχK±χίΆm-H°ΟsiS£ε:ΕξπၢάΜυ{cFόύ\φφϋAΒ$…›wˆˆ¬]ΠJΊ \μΉ'‘το&HaΏ{%YK€€pσ޲"_ύ9gΞ³¦Μš6mͺ΄vο½χlyˆΚjSl…Χ•Υ‚’V­ZIwω_ώςgΉΗ{ΘΉsηΚ©S§ΘΔ+ΰΪƒ―=˜Ϋƒ=ζzΐ΄‚ίή{ZkΜ@+Txb ΫΏwο@Ϋ+p?ύtΰωηΘθφ7mνήΧf]ΪΉ²ϋΫ@{i±―OV+όˆΨΤ6 ^uU  ξΏ?Π {n3ξχλψρv½ψΪψŒ{ύuT`φEΠY3cDNšΨΌy _·\νόo΅U ]§vo·]ΰ…Ίύν₯Χ7ήΈhQΰCn³Mΰ!n³\ηΏάχ€ΖO±Z bΗέ mv²γcGί:Šρ©§³ΕΊ¬“'Ίν,(Ωd“@wΉ«]wΆήgŸ τ΅MΒΈΧRΏq΅λގH`Ϊϋ_νH‘Ώ{=ξΈΐŸ<0ΌNŸΗxΡEξςbχίΥ‚\Ώ7ΉΜρϋΉlΚi‡ a’ΒΝ;DDΦ]ΠΚρ@ΩbΘ D DDDD •@$@$@$@$Ϊώ»ˆ@ΗΝ;Κˆ 6TZΐa4PΊνW¬xMZ»εΛ_‘έ»/$§LΉG6Κ<όeuΧsωε—Λή½Ο“φybˆŒ2ϋ(y$π»Ώο΅bχsήΌ@λo…Ηpί¬Σ¦ZaΪ]ώ³ŸΪ Ή¦ΚgŽΪΘΪωO~θkγ3n b…+0ΈΛ£χϋΗ΅Π@$ξυcSΰl°A`)‘š2«_Ώ@wωOxόρξς|ΪυcΑ―MΦ΄Ο₯ά?’?Εjˆ'wωo~Έι¦ξςbuƒ +HΫΤq\}`Τqι·ΤH>σ]Iύ~Δ5n ’ΟJDςYW‘r™T υο—Έχί_ώ2Πύ]΅)"Ο>;Π>ί|σ@ϋμs³ΠύΟ%ΤqάΌƒ@δ»Ο³aHVΗΈαbΘ D DDD~Έœ@$žω‘΅%!‰ςχKάϋ/ΘZ$…›w”-1mΚ¬E‹ʎ;Κ#FHkwΚ, PΪ·o/?ωδciΛ³aHΦ؁ȽχΪq© N;-Π}ΐΌοΎ@λU{‰§­gΑ‚@›ΪdχέwΪ)Π Κ‹Z?ΧΈa{ 0 ΠΧΖgά@dύ­»<ͺqΏ\έ—ͺ[ΑΕΧ6kάλΗ-Θ?ϊh »»μόΊΛγχό[Π^o/η¬θφ7Σ>•rHjό«"Γ†ΊΛm*++πZηΆ+ΤRM™•φKΥγ^Iύ~Δ5n b–ΫŽ)³ ³Ϊ‘¨ΏΔ½ΪΤ€556mοΊk ύNΫύδΕέύ)tsI u7ο ωn9Θwύ\γ„‹} ' $!!ωαr‘uχϊOκχ#""q$)lsI u7ο({ β:|ψpΩ₯KiŸϋν7²&σ˜u\ζ!+kΈoΦ™‡Ύ¬]»v•φωwή!-P‰κ /Μ—αm„ύφςΩL_Yθ”7ξΌ­/ά7ŽφrμvΜχRi›²©M›@_›uiδΉ^~K›"βKέ姜˜« žΤ”?qΏ\_~9°E‹ΐΫn τ΅Νχϊyι₯@+œεš2Λ[;ΏξςΈˆXΙ}Έ}nνlκ£ ΄Ο]Σ>vΎμό•λώQιSfΩˁ[΅ t—«;ήΌ2ΠmW[hSJΉΛ]΄λΪΧ& “Ύώ] ύύˆ«{=ˆˆD³ΠλΗ΅ΠΏ_άνzuο?Ϊv‡8hP`ΎϋO‘ϋŸΛb‘ΏŸ"6nήA ’G‘˜αbΘ Dέ H ΘMϊϊw%).P )…^?…ώύβn―Πϋ―{!H7οH-Y½z•¬­­•K–Ό(ΏϊκKΉxρ"Ω©S'Ω§Ooι§ώΪ­Z΅R.Xπ‚΄©²r&ΉLlΚ¬οπώo―½O8!Π¦:²D›κ Χζ~xψαV(™??π¦›O:)Πνo―λ ΄νΫzΆΪ*0Χ”4¦MΩd/ΩΆ)}|m}ϋ@~ϊιφΐo/υ΅—‘Άn˜+±©n¬0xΝ565Ετι]θφ7γ~€΄—˜ΫT5Ύ6aγ^?ΦοC­zχ݁ohηΧνΧb»NΦ[/Π y6΅M]dš|αrrί?’?Εjˆ½4ΨΆgF»>,υ­#ŽvΩn»ΐY³³EΌ¬6UVΐΔΥ¦¦Κπ&eRΧRΏq-΄ mϋgν DΛˆΨTk»νθkS ½~\‹ύϋ%ξύΧ~w7έ4Π~w/Ώ<ΠΖoŸ>n³Ψύw-6ΙυϋΉjUΰwνΒ!HX€€pσ‘οœJ β7nAΈΨr‘΅%Y[‘šΤυO ²Ά""ь{%‘Iαζ©"6εΥΔ‰wΚΝ;Λ&™‡ω¬φ²σ~ύϊΙ5kΦHw=_|±FφκΥK6kΦTZ2dΘ`ιφΛηΤ€+ ν»o`γƁVθ΄wL+ˆ¬-ΘΪˆˆd%ρχϊOϊχ£X DDβH Rάώˆ@=ΓΝ;R Dκ«?ΐχ0ˆ˜”GuͺžRωσŸZΑΕΧ±X-><ΠΧ¦.˜}ρzΦ~ύ}m0·nAΫμΡ#ΠΧ§ˆTš6νΈˆΜ™hSΈέv[ ―m)¬/ΧO}“)³ eάΌƒ@$¦? όΠ‡˜΄"X ˆ`V‘ςJ ‚₯@RΖΝ;DbϊάoDDDDDόχ”Yίύ;‚„H 7ο ‰ι?τ!""""b €Œ›wˆΔτ„§@¬―ζš2+\τ(ΔνΆ o£.κϋnQ¬/ί?)λΛ”YˆˆΈΆL™)γζ"1ύα‡>Δϊ*ˆ_ίw‹"ΘΪˆ "ΦO D eάΌƒ@$¦? όΠ‡ˆˆˆˆˆrΩ”)ώAΒ$…›wˆΔτ„ϊ1@ΖΝ;Dbκςΰ[Ÿ!""""¦f]aY6Ι†!ίAΒ$…›wˆΔΤΕχŠˆˆˆˆX*λ "6nήA SίC*""""b©¬+ˆ@ΪΈyHL]|©ˆˆˆˆˆ₯²@ iγζ"1uρ=€brxlyα―o–Ύ6Xωφ<―Ώ<κ”^Χ&l‘νqέr<Λ#χ/LΣΞν+ΟΈx°τ΅Α™φρ―+ˆ@ΪΈyHL]|©˜œλ‡…δ)ΰ'+Η³%7mΧ^N_ω‘τ΅ΕΚ—‚|yεψ§+χ/,‡Ύ&›·ΨDή½d₯τ΅ΕδMϋψΧD mάΌƒ@$¦.Ύ‡TŒ/Εϊ%ωςΚρOWξ_X DΚ+ˆH7οH=YΈpμΦν8ΩΌysΩ‘Γ6ςΪkGJ_ί¬_|±FφκΥK6kΦLΆnέZ^vΩιλ›΅Gξ²Aƒλτν·ί’Ύu„uρ=€b|<ω yΟH_›¬γηΎ$ν<ήϊΔ m7hΤν²Q“¦]~Υ]ΣεΞ{ο'­έf[n-Οt…tϋa4)Θ—WŽΊF½Uͺη ω•ΌβŽiΧ+Χ.‡%Οz΅τ΅©&υϋoΗΙΦcΏΑmŸΟ΄Ž]%‚„H 7ο Ι!HeI RΏ€ _^9ώιJ ‚ε”@dνv"•E8 nή‘z R[[+gϞ%Χ¬ω£œ7ožlΩ²₯œ4i’tϋχοί_vμΨQZ΅RΟ?OΦΤΤΘqγΖI·Ώ"ΏϊΥ―€»ΌP]|©XΌ3W*›oR#―Ήg¦τ΅ΝšTAdŸΓ‘WOž!§-WŽœφˆl¬ΉδεΘΕIAΎΌrόΣ±ΠϋW₯xψ‰§Ιaξ‘ˆ\~ϋTΩοκδι”ΎuΤ'νx”Ί ]*{_>BZΐοkSLκχίuθ„Ι²Ψ@$­γ_W ‡ a’ΒΝ;Dœε…κβ{HΕβ%©ŸR/―t$©ˆΤ Dκ&α$,@RΈyGκH>-°θΫ·―΄ΟΏύφiΗΨ±ceΈoΦ .Έ@vνΪUΊΛΣ DΆίuΩύμ>rΛνw”Mšo,ξ~’œΊμm~¨Νj/ί<Έϋ₯ΤZmΦVžpn_yλH·δ₯«εώΗt“ΝZ΄ΦΏφ—Ι™«>‘n Ž?«·l½y;iϋqψ‰§Κ\ϋŸ”£Ÿ\ ­ΐ‘o{₯*ˆΈΪ6Ž―M’Άj»Ήάϋπ£₯―M%9~ΞΉΫώ]₯ηN]φ•vύη*Θ[ΠdηΡΜWΐΏιΡΉr£ΖεΤWή‘n»ί<τ΄lΤΈ‰΄λέmW¨—™$·Ψv{Ήε;~7ώΟ|…όχ8 ­ξz⎸Η?)νz=β€Σε.ϋ n΄‘΄σjγΡϊΕ½Δ½&e‘χ/ΣΞΣI}/”;ο#νΊήγ C€έη}λˆγ½―Ύ'Oξw±l·ΝΆr۝w•?»ς:9cεΗ·Ž8VΚω3Σ D’ΊΈZoγTηΝ,Χω«Τ@$­γ_W ‡ a’ΒΝ;Dœε…κb¦q "… D*C‘¬""ΕX)ηΟ΄qJ Νr?‘ΊI8 nήQφ@δλ―"ηΜyVΪ”YΣ¦M•Φξ½χή•φ kSl…Χ•Υ‚’V­ZIwΉ"›l²‰lΤ¨‘άn»νδ 7\/έ~Ήt±S+X!οζYΟΙ‰ _“χΪ[ZΑ/όP›υ n=₯Ύ&.Z!G?΅PZΑδŒ‹K·Ώ²¬6iΡλΆκ!G=>_Ίύ­`±λ~Ι Ο-•w½ψ¦΄ εθSk₯Ϋ?)―Ί{Ί΄B‚―MΨR"V€ΆΒtί«—ΎΆI5±‚}¨Ÿτ€τ­³νϊΆΒυ=Kί’Ά;ŸQ ς…Nρ΄ΝN;Λ‹%έεΆΎCzœ$έεΕj͚Φmδδ—VI;6nl<7Μά{²ή΅ψ iλ‰;ώ“>ώΕjΧ«ςνψάϋΪϋΧ'kάϋOάϋoRz2-Ω|λξΣvl΅CGyΦ₯Γ€oqό>ι‰t‘ΎΓ-KUΨ­”σg¦ˆΔ½ΈŽyz‘΄ϋ}Ύφq-Χω«Τ@$­γ_W ‡ a’ΒΝ;DˆˆˆX‘ά·Ξb΄λ›@„@„@„@€P+εό™"…YσG R7 ‡ a’ΒΝ;Κˆ 6TΪ’9hΠ@ιΆ_±β5iν–/Evο~ΌΩ΄iSyΫm€―OX{0΅‚ΐi”α‡Φ¬CFO”-Ϋ΄•φΉ˜6Ψ`C9rκΓ2ά7«MYb…_wω©.•»ξ{ Œ:΅Κ”—ί’vœozltΫύφ‘gdӍ[HwyRΖ DςYh rΜigI›ϊgϊʏ€―m5j/;ΎcŸY,έvVΨ‹Z/49kΰεr―ƒ—φΉMg“½$:ά7ŽVΠ΄ >·ύ>γ’A>o³Ε–¦ϊŠ;ώKuό‹Υ7Ύ6a“Ί{MΪΈˆ{½˜'ύl€<΄ηΙ]W r½Tέ‚ΰR½T½\η―܁rάϋ‡}ξjAͺνoZHΪη―TΏq‘΄Ž]%‚„H 7ο !YK‘uK ²n DDΒˆˆcΉΞH2–λόˆΤMΒ!HX€€pσ޲"¦M™΅hΡBΩ±cG9bΔiν’š2+Ÿ}ϊτ–΄ψΪ„u±S+τΏζF~hΝzύτΗεzλ―/­Pλ4Η=ϋ’tϋ_6φ.Ω’e+ι.·)Olj¬φά[vθ΄‹΄‚šMeύ¬°bۏj—WΗuτ“kΏ”Ψ ¦ΎΆYέ‚HRSfΨd6eLΤ€©ΪόνΓΟJ;ώΉ¦Fκvζy2jAΎΠ@δφy―Θ 6”6eάΥ“gΘMZo*“΄¬ iA€}ώ£ΣΟ–ξG6%>%γŽRb΅@δΜK‡J_›°IέнΊνβZθύΛ΄@Δ‚wΉšψQwι.OZ DΈcšτ΅IJ9¦D˜ψΪ$aάϋ‡}ξZ—ͺ§}ώJυϋ7α₯κk³lΩ2i„C°Iαζ"Ž""> D’I B –@„@€+εό™"…YσG R7 €΄qσ޲"Γ‡—]Ίt‘φω·ί~#kjjδΈqγdΈoΦΘ]»Jwy>Ο?Ώ΄—―ϋΪ„u±S+Xα*όΠšΥ 5ί½<Υ>·εΈSfεςξ%+₯υ;WΧJ[n/_Ά‚‚½Ό5ΌŽ4ΉϊSΩ|“yΝ=3₯―mΦ€ "φRa BμψωΪV‚V°³οΥ€¦|±λΕΦ[)³L{)·]ηΦΏϋΩ}€―O‹.hΞ|RΖ₯:ώΕjˆϋ½s™Τύ§Ψϋoz2+-IΫJ9fΕ"ίέ?μsΧ>WŒ”v]ωΪ$iΉΞ_₯"iΊ€›wˆ8ˆˆ„%)L»^l½"ΑηQ š""Y­pJ B ’5κύΓ>w%Y»Hy!€΄qσŽΤ‘Υ«WΙΪΪZΉdΙ‹ς«―Ύ”‹/’:u’6u•»žώύϋKk·jΥJΉ`Α ¦Κr“ίώ}yφΩgΙW^Y&ν₯κ3gΞ”Νš5•'ή)ΓΫφιb¦VΨ΄]{9jφ{0>ΆΧOeψ‘6λAǝ χμz˜΄)¬ΐΩ~»δ9^Ίk…όKoš mͺ–ρs–H+€τ»ϊιφοz|OΉίΡΗIλ7uΩΫrθψΙς˜ΣΞ”n€=ςδ3€Mυεk“5©‚ΘOϊ^$·έe79ω₯Um—–φp+0ϋΪT’;⦅<β€Σ₯]ίΏdΊQ#΅ _l rΑΘίΙνwΫS6kΡBή0γ ιλΗ€ šqΗΗΏX DΜΈχŸΈχί€z2mͺ=©”σWΧ‘Ξ‡!ΟύεUΧ&IΛuώ*5‰{ό£ώώΧD mάΌƒ@„@„@„@$q DD²Ϊυκ~ο|ˆˆTω#)Μr?‘Ί€›w€ˆΨ”W4tξάY6iDΆoί^φλΧOY³FΊλ±£W―^ B† ,έ~ζ­·ή*νενΆ}ϋχ-·ά"}}}ΊΨƒ©N<ΉE‡νd“ζK+ψY‘2όP›υΕoΘƒΊυ”Ν[l"[Άi+mʟϋWόAΊύ'<·TΪvšnάBΪφRειo~(έώφ’βξηœ/­°aϋΏΟΗΘ››+έώIk/έ΄έ2ΧΛ°γDμxZ|ξuπα2ΌξRXΧ»ώv?ΰ`Ω¨qi…ϊ#rΊΜUo³Ε–wΜΓΪuνφ7m|Y`γΠΧ6 “*h&5ώ‹=ώIiΧ«ϋ½σχώχώ›΄Qο_¦Œ³aHVwy΅"•rώ2ι@δΞ―J ‚Σšς±\η/©@δŠ;¦ΙπoΟ|Ώ?I€xΈyHβΖ-ΘˆˆˆˆTΚωKK‘xˆΤ D mάΌ#΅@€Ύκb¦VΈπΧ7ΛπC+―M%4ΰΊ›₯― "V·•zεώM~?“ρ„sϋΚ3rL­W*9iΊ€›wˆΔΤΕL)”F Šˆ˜ΟJ½rŠ&ΏŸΙH R^ Dόˆ@ΪΈyHL]μΑ”‚"byδώ[·εόΥm9ε±AΒ$…›wˆΔΤΕL) "–GξΏu[Ξ_έ–σWλ*α$,@RΈyHL]μΑ”‚bέΣχβά(n΅CGι[g]χέ’Xiߟϋoέ–σW·εό•ΗΊJ8 nήA S{0₯ €Xχτϋ£H B ‚ΙΙω«ΫrώΚc]%‚„H 7ο ‰©‹ο!±TΦUΒ!HX€€pσ‘˜ΊψRKe]%‚„H 7ο ‰©‹ο!λ―Pα$,@RΈyHL]|ɈˆˆˆX…β‡ a’ΒΝ;Dbκβ{HFDDDΔϊ+G8 nήA SίC2""""Φ_‘8Β!HX€€pσ‘˜Ίψ’ρ³λy^yΤ)½€―M5xΰ±=δ…ΏΎYϊΪD±ΠγΙρOVŽ'Vƒ'œΫWžqρ`ιk“†='dΖ[Ζ£FeΖ[F_Δr ΡXΆl™4Β!HX€€pσ‘˜Ίψ’‘²I R?δxb5H ‚]ˆ€›wˆΔΤΕχŒxγƒOΙMΫ΅—ΣW~$}m£HAΎΌrό±œΈπ5ΩΌΕ&ςξ%+₯―-b΅ Ρ €΄qσ‘˜Ίψ’ Dκ—¬ D£ Ρ €΄qσŽΤ‘§Ÿ~Jxΰ²Q£F²M›6ς”SN‘οΏžtϋφΩ§ςδ“O–Νš5•-[Ά”^x‘όλ_Ώ–nσ†—ΫoΏ½lάΈ±<ꨣδΫoΏ%}}ΓΊψ’±x‡Oz@Άj»Ήτ΅© yςς€Ÿ Ύ6…HAΎΌrό±ŽŸϋ’lΠ Όυ‰€ΫnΠ¨Ϋe£&M₯»όΌ‘WK[ΉώH·}>»v”΄υϊΪ`rηοͺ»¦ΛχήOZ»ΝΆάZž=θ ιφ«4ΛυϋτυUˆ€›wˆˆT΄"~)Θ—WŽ?–B‘Ί-ΘΪˆ€H7οH=ιΩ³§œ;wŽόӟΎ’“'ί-νΑΥ·mm­\ύυε³Ο>#o½υViύGŽ)έώΧ^;RZ;λχωηŸΙGyXώξwΏ•nWίC2o]DfώT6ί€F^sΟLιk[ˆδΛ+ΗKaRuΧ‘&Λb Β½/!­@οkƒΙΏ}?F^=y†œΆό]9rΪ#²I³ζςΒ_ί,έώ•b₯ό~Η½ώ£ Ρ €΄qσ‘Š–@Δ/ωςΚρΗRH R·%Y[πA iγζ©"6΅Υ½χή+­pΡEIkgΑ‰MmΥ©S'ι.oΨ°‘άuΧ]₯-77ί|sΉώϋKwy‘ΊΈΘ{~΄<β€Σε.ϋ n΄‘΄οkλgγΟκ-[oήNZaύπO•S—½-­ί¦νΆ6ε†}žΛsy•΄ύt—»V¨±εfΎςΝ³ž“nΏ\ZaΪ]O±Η/iG?Ή@ΪώFέήψ9Kδnϋw•V8λΤe_ypχeγYμρΏιΡΉr£ΜΛ:υ•w€Ϋξ7=-5n"νx»ν υ²1“δΫn/·άa§ΐνw”η ΎBώϋ<ž&έυΨ˟ξώciν[mΦVžpn_yλH·άγŸ”ΕŽΏΈΧφ»ξ!»ŸέGΪρo|ciί?κυΥ€Ξ\Λυύ+5±BΌ]w3V~,}m“πΒ3χ―Œ ΞΟ‡GΚŒ·ŒΎ>a; όӌ'έq‘μxε>r£ώ™ϋZΖ=F"'―X-}λ(ΖR?W›ΒΜ¦bτ΅‰γ„η–ΚΗχ”ΝZ΄-Z΅–vt―ƒ€~Ώ“–@€² €΄qσgy‘ΊΈΘi4 Dγ„“2†d΅ύΊ=‘¬ΕŽΏΈΧ?HX‘hˆˆ@~D mάΌ£lΘ!ƒ₯ϋ€|ζ™gΚoΎω«΄φ―Ό²LZ»£>ZώψΗ?–—_~ΉlםάpΓ ε·ί~#ί}χiύwΪi'i/Uo€‰άwί}δ’%/Κπ>ϋtq­ if+ψέϋΪϋmoZΑmΧύ’V ΈλΕ7εώΗt“GŸZ+­ί!=N’½."ΓλτyP·žς¬—Kwy±ϋοj…B ΘΕNΉQμρKΪ«ξž.­θkγ³γ^{K+\ί³τ-iΗΓΦυxzό·ΩigyΡυ£€»άΦgΧ›»ΌXνϊͺiέFN~i•΄γaηmβ’²a£FςΕoH[]Χ{tˆ΄φ£ŸZ(­ΰ~ΖΕƒex²&}ό‹5νϋ‡i€)V蜸π5iΗΗ·±&uώγZο_©Θ˜§IΫ―€w>{NΘάo2ˆl>¨ƒ΅hΎœΈίύΐƒε{\Ϊη›Άk/―»ο1iŸ›…ξ. -Θ›…TβΏ€-4±‚«νΨgK·†£ΟBΏd{|Έ΄ΟgϊDΪωΈόφ©2ά7ŽVοΨyiŸΫ~ŸqΡ iŸ·ΩbKiS}Ω.l°‘9υaiν͟]y΄ΰΗ>/Υρ/ΦBΗ_RΧΏ§]8PΊΛ‡Œž([Άi+έεΕχόΫηq-Χχw κωL+± ΡΆ[W‘3&e—Œξς“n ½ιdι./ΦR?Σξ6uήτ•I_ΫRzzfLd=πΨΧ&+D!‚„H 7ο !!ρ„“’@€0 DΦΆΠρ—ΤυO B –@$š"kK Q‡ a’ΒΝ;ΚˆΈΆmΫVnΆΩf>w ›2+ά7k)³V­Z)­Φ[o-έώΗ{¬΄vŸ|ς±tΫ™.ξ²4ΟΌt¨t—»ZaΟΆU{ω΅Mν’e+yο«οΙvίKξΈGgi…_›rζ7>”ξώΊΉL+‰{ό|λŒγθ'Χ~©Ί¬}m³ώφαg₯΅Ο55R·3Ο“Qg‘Ηφy―Θ 6”“½.―ž6©‘Χά3SϊΪf΅ύ΅ύ/Χ”Y¦½”Ϋ^žkύ»ŸέGϊϊΔ±θ‚ψΜ'₯j‹ž2«DΗΏXΣΎ˜δš2ΚΞSφΕηYέεΕχόΫηq-Χχ―Τ@€Ο#e§.ϋJ_›RZ­ΘΙύ/‘„ά½d₯τ΅MBϋ(,Ώθϊ[€}nνlΏά)] ύύ.•"•M8 nήA ςέr“@dm έ\ˆˆD1nAœ@„@$ DΦ–@$š"kK Q‡ a’ΒΝ;R D/^$Ο?|ωKKδš5kδ„ €Ξ;ο\ι§ΆΆVΏώϊrΜgε˜1c€υ9r€tϋŸuΦ™Ϊ=ώψlωκ«Λ₯½TύΠC•nWχΉΨ@‘λρ=ε~G'ΗΟY"§.{[ŸyΐΟxΜigJ·>‡#ν₯ΏΧ?0[φΏζ7 §όόνo»ΕδG?L9eξί=2GϊΪ†{ό’φȓϐ'ύl€τ΅ »σήϋΙ#N:]ΪT[V`²©Ξ’Οb#'mκ”f-ZΘfUήϊ¦N³Ώς"Ωίξ¬…ώ~'mάλί¦ό²ϋ±―MV(Žp )άΌƒ@„@„@Δsό’–@$š"k[ϋHX‘hˆ¬mφ·;+¬‹p )άΌ#΅@Δ¦¬ΊυΦ[εξ»ο.›4i"·Ϊj+9`ΐΉfΝ₯»žΟ>ϋTž|ςΙ²iΣ¦²¦¦FZ۞ΫσΟ?“gœq†lΡ’ΕZvο~Ό|ϋν·€ΫίΥΕ}@.Ά i/9ξ~Ξω sMšo,χ9βyΣcs₯ΫμAWH{i΄½τχŽωΛ₯lœxŸtϋ›Εξ›-Ά”Ά\6έΈ…τ­#¬›zΚϊ[‘ίmχψ%­½τyΣv[Θ|/#ŸπάRΉϋΛF›H+Τω“Σe‚|RΗί‚ Άθ°τ΅MΒ€ βw-~CΤ­§΄)δ, ΄)Ώξ_ρiύΜΈΗ?)Λu°@ΰΔσ/vή­Ώ.v}Έύ‹΅‘΄ΏRυ+ξ˜&ΓcέgΎρη‚W₯‘₯ž²Ιlsiζώ•±Αω™ύ\‡Mdφ?£ΫΏ"v? Ÿ£u™/(ΦΎWeŽ[F μώoΫ³ίέ¨Ϋ·ϋPΤίοΈ&uύ›"Ι²lΩ2i„C°Iαζ"‘0„@䇻"kK M‘΅-Χύƒ@„@$+Haˆψ΅ϋd!€΄qσŽΤ‘ϊͺ‹ο!Ρ΄©œ\w³τ΅A,·\ψλ›₯―M}ΆΪΏΏyΒΉ}ε9¦–CΔ Ρ €΄qσ‘˜Ίψ’M¬ ˆˆd%AŒ.Dƒ@ΖΝ;Dbκβ{HFD¬Kˆˆ baB4D mάΌƒ@$¦.Ύ‡dDΔΊ$"&Dƒ@ΖΝ;Dbκβ{HF¬}/βV;t”ΎuΦ%}ί-Š•φύ DD±0!"6nήA SίC2b΅θ+φG‘@„@€’$AΔB…hˆ@ΪΈyHL]|ɈˆˆˆX…hˆ@ΪΈyHL]|ɈˆˆˆX…hˆ@ΪΈyHL]|Ɉˆˆω¨6Β!HX€€pσ‘˜ΊψŠ\ˆˆˆω¨6Β!HX€€pσ‘˜ΊψŠ\ˆˆˆω¨6Β!HX€€pσ‘˜ΊψŠ\ˆˆˆω¨6Β!HX€€pσ‘˜ΊψŠ\ψΩυ<―Ώ<κ”^Χνϊl 4h°–χ,}Kϊϊ –Κž2γ7γQ£2γ7£― Ζ Ϊ‡ a’ΒΝ;Dbκβ+r!H‘ˆ`%I ’ŽΥF8 nήA S_‘ ±XoŸχŠ$A¬Tα$,@RΈyHL]|E.Δb%A¬ͺp )άΌ#υ@dαΒ²[·γdσζΝe‡ΫΘk―)}}³~ρΕΩ«W/Ω¬Y3ΩΊukyΩeC€ΫoεΚ• Λωμ₯‹tΧγκβ+raρŸτ€lΥvsιkSŸ%AŒξψΉ/I/·>ρ‚tΫ u»lΤ€©t—_uΧtΉσήϋIk·Ω–[Λ³]!έ~q¨6Β!HX€€pσ‘ˆT†""ˆQ%¨[„C°Iαζ©"΅΅΅rφμYr͚?ΚyσζΙ–-[ΚI“&J·ώύeǎεͺU+εόωσdMM7nœtϋηsŸ}φ–Χ]w­τ΅ λβ+raρˆˆ F5©@dŸΓ‘WOž!§-WŽœφˆl¬ΉΌπΧ7K·±Τw–-[&p )άΌƒ@Δ‘@€²$!AŒ*@eC iγζ©"ωμΡ£»μΫ·―΄ΟΏύφiΗΨ±ceΈoΦ .Έ@vνΪUΊΛsiSy5jΤH~ψαΧ6¬‹[ΰΪϋπ£ε'.wΩχΩp£€ξ¬@gύ¬wόY½eλΝΫΙζ›ΤΘΓO‘nΈNxn©μz|OiΫoΡͺ΅<αάΎrΖʏ₯Ϋ?ξώΗνχ’•ςΰξ?–vέYΫϋ_@ΊύΝ+'ή'wά³‹΄BΌ]_Χήϋ¨τυγ…fΖoΖηg»GΚŒίŒΎ>a; Ο\OΊγBΩρΚ}δFύΛ=F"'―Θ猾ucRH>»v”<ςδ3€―M1ΤwD mάΌƒ@δ; DD’”@$ž""…I PΩˆ@ΪΈyGΩ‘―Ώώ‹œ3ηYiSfM›6UZ»χή{WZ‘Λ¦Ψ ―+«%­Z΅’ξς\ώτ§ηΘSO=UϊΪψtq \(lΤΈ±ΌlΜ$yοkοK·½iσ]χ;HZψί”V¨=ϊΤZiύιq’μuΙ^§ΟƒΊυ”g Ό\ΊΛ‹έW .ς"ΕN™UμρKJ+X[cAΟΔ…―Ɏ{ν--°ρ­#kΉ‘“ϋ],;vήGNZτΊ΄ύ?υ‚£Ÿ/έώq=ε翐ƒo½CήχΪο嘧Ι-Άέ^ž«k₯Ϋ?ξώΗνoγjƒ‘­£ŸZ(mΟΈx°tϋί0γ ΉaΓ†ς’λo‘ έτΨ\iΑŒΫ?i{NȌߌ…"›κ G-Κ§Œ—gŽCΖ­.λ(Ϛίύΐƒε{\Ϊη›Άk/―»ο1iŸ›…ξ.Σ DβΏ€΄@Δ‚wωΡeΛ6m₯»ά,W rκ€Kεϋ(m )·]Ή<=³οY<Ά‡t—ΗέbϋΫ^l°‘9υaιΆϋΩ•ΧΙmvΪYΊΛ-¨³€Σ]žΆΕ"gL$έε'έ>@zΣΙ]^¬n ’ΟB»ΪԁΣW~$}m‹ ΎC iγζ""""?X7P(΅"ιJ hχA€β €΄qσ޲"¦M™΅hΡBΩ±cG9bΔiνJ5e֍7ή wάqGιk³.]ά— g^:TΊΛ]ozt ν’8υ•w€MΝΤ’e+yο«οΙvίKξΈGgiS4lΤH>πΖ‡έŸBχ?—i"qŸoΕhHkn”ξςλ§?.Χ[}™λεάε DμΊ±©‘vΪsoΩ‘Σ.ς€Ÿ 6…Ϋ?C'L–ΫοΆ§lά΄™ Ÿ³¬9BΊύγξ±ύm\Ωώ{φE^wΦΛΖή%mœΊΛχ<θPiηΙ]žΆΕ"}Θ\έε§MΚ|―ŒܐΉώ2ΊΛ‹Υ D’š2Λ¦PΫvη]e‘[Tκ;"6nήA B B ’‘@dνεΕII B RŒ"• €›w”=q>|Έμ₯‹΄ΟΏύφYSS#Ǎ'Γ}³0@vνΪUΊΛ]wΪi'yέuΧJ_›uιβΈ,P8λa]ξjo+θΩ˘}m}Ξ\ύ©lήbΩ{Ψ5¦Ϊο¨ceοΛGH›Θ·¬…ξ.‹ DΊ{Ί΄—ϋΪ„{ό’‘\m{9}Mλ6]nή½d₯,τϋμρέΛΌΟz΅t—Ϋλ§2W ’KΫ›κ)ΧKΝ‹Υ‚χeβφΉ΅;Ή%r―ƒ—αu¬ΛΈϋŸ―?SfΦ—@Δ3 BμόϋΪ&!@΅AΒ$…›wˆˆˆ”@‘β$ $)N€ΊE8 nή‘Z ²zυ*Y[[+—,yQ~υΥ—rρβE²S§N²OŸή]Oώύ₯΅[΅j₯\°ΰiSeε LΜΗŸ-7Ϊh#ωα‡H_ΫuιβΈŠ ΊίSξwτqrόœ%rκ²·εΠρ“ε1§)έώϋ~Œ΄—v_ΐlٚίH Nωω/€Ϋί,w 2ϊΙ ΜΏ{dŽτ΅ χψΕΥ{iύ¨Ωσ€6₯•Ύu„΅)Γϊ]}ƒ΄ΰΛΧ6λρgυ–φςg›βΗ^&_³ιf2W b…ΰKoš νeυv7ίΊƒ΄ύqϋλδ—VΙυΦ[O^~ϋTiSSœφˆ΄λ7W wγφ?θΈδž]““½.Η>³XΆίnyΖEƒ€Ϋί¦T³`θ’GK›ΪΝ§³^.έώI[mΘOϊ^$·έe7iΧ₯Ϋ.ͺ6~ν~κk“ Ϊ‡ a’ΒΝ;DDDD~Π?n P¬""ΕI P·‡ a’ΒΝ;R DlΚ«‰;w–Mš4‘νΫ·—ύϊυ“kΦ¬‘ξzΎψbμΥ«—lΦ¬©΄ dȐΑνηzβ‰'ΚSN9EϊΪDΡΕ-p(Xα³ϋ9ηK+¬7iΎ±άηˆcδMΝ•n³]!ν₯Νφξ;ζ/—V0Όrβ}νo»mΆΨRΪvrΩtγ·Ž°všoR#­Ώ-nϋΈΗ/ˆœxώr‹ΫIΫΎ6Vhχ­#με·M‘›ΆΫBΪχ·οηΆΏνω—εŽ{v‘φς| ΊyžΜˆLxn©΄ύ΄σ”ή+«υŸώζ‡νΧμ‹ΰ³Z!Ωέ;οφo·άύΫΕoΘƒΊυ”6…”έΟξ#ο_ριφ7-Ϊaχ½€½\~»]v—7ΜxBϊϊΖ±Ν₯™ρ›±Αω™λl69.έώu5±σaύσ™λϊs%πAΒ$…›wόββΎ’@ΔΣ&Š.n«Ψ@@dmν8ˆˆd%!ρI P·‡ a’ΒΝ;R Dκ«.Ύ"VŸˆ\ψλ›₯― "bX€j#‚„H 7ο ‰©‹―Θ…Υ'"*@΅AΒ$…›wˆΔΤΕWδΒκ“@  Ϊ‡ a’ΒΝ;Dbκβ+raυI ‚ˆ… Pm„C°Iαζ"1uρΉ°ϊ¬Φ@Δχβι(n΅CGι['b΅PίYΆl™4Β!HX€€pσ‘˜ΊψŠ\X}ˆ&"ΤD mάΌƒ@$¦.Ύ"""b>κ;"6nήA S_‘ 1ŸυH7ο ‰©‹―Θ…ˆˆˆˆΉ…κ€@ΖΝ;Dbκβ{ΘGDDDΔάBu@ iγζ"1uρ=δ#"""bn‘: €΄qσ‘˜Ίψς1·Pˆ@ΪΈyHL]|ωψΩυ<―Ώ<κ”^ΧΧί`Ω Aƒ΅Όgι[Χ§.χ~PξϋI‘Ϋ/χώb<{NȜΏŒGΚœΏŒΎ6_¨D mάΌƒ@$¦.Ύ‡|€ ˆXˆ"λΆάχ“B·_ξύΕxˆ€#T"6nήA SίC>"b1ή>οI ²ΆεΚ½}Δϊ(T'α$,@RΈyHL]|ωˆˆΕH β·άDΉ·X…κ$‚„H 7οH=YΈpμΦν8ΩΌysΩ‘Γ6ςΪkGJ_ί¬_|±FφκΥK6kΦLΆnέZ^vΩιλ›uεΚ•ςΨc•oΌ±΄ώgŸ}–\³ζ·Ž°.Ύ‡|,ήᓐ­Ϊn.}m09ΗΟ}IZΎΛ‘GJ·έΠ “eӍ[HwyRVϋω'ρ[ξ@’άۏ*χΟκ½ίϊΔ m7hΤν²Q“¦]~Υ]ΣεΞ{ο'­έf[n-Οt…tϋΕͺ“p )άΌƒ@„@€’₯ —"•%ˆίrεή~TΉV—"P ‡ a’ΒΝ;RDjkkεμΩ³€σζΝ“-[Ά”“&M”nώύϋˎ;ΚU«VΚωσηɚš9nά8ιφ?μ°Γ€2ό‘΄υμ²Λ.ςβ‹/–nWίC>/½tu j7‘£Ÿ\ ­H:ˆψ-w QξνG•ϋgu™T ²ΟαΗΘ«'ϐӖΏ+GN{D6iΦ\^ψλ›₯ΫΏX‘: ‡ ˆˆˆˆˆˆ…7ο !©h)θ₯+HeI β·άDΉ·UξŸΥ%ΤEΒ3ˆˆˆˆˆˆ…7οH=ΙgέeίΎ}₯}ών·ίH <Ǝ+Γ}³^pΑ²kΧ]ή¦MyΗ·Kwω/~q‰<ϊθ£₯»άΥΕ}ΐίϋπ£ε'.wΩχΩp£€.¬@aύ¬qόY½eλΝΫΙζ›ΤΘΓO–o½΅ZξΆΫnrτθΡνοκβ>ΰ[Ag£Ζ₯\ο}ν}ιΆ7­ΰΆλ~I+Pήυβ› eGŸZ+­ί!=N’½."ΓλτyP·žς¬—Kwy±ϋοj…·¨A³Ψ)_Š=~Iϋλfɝ~ΆlΡ²•άλΰΓεE׏’χ½φ{ι[GšΊ΅λ§?.7i)§Όό–Μˆœςσ_ΘΑ·ή!νϋyz‘΄ΐαό_]+έώfΪSώΨυ]ΣΊœό*Ωq―½₯]7­ 5’w-~CΪz¬p^W‘Έηώ—Άίv>­ λ~·\“ή~‘χΏ“ϋ],;vήGNZτΊœΈπ5yκ!G=>_ϊΦ‘Υφ·Ψρ“ΤύΏXΛ½}³η„ΜωΛXh ²ω rΤ’ΜyΚ8qyζΎ‘q«Λ:Κ³&“Ύuc©‘ϋ_@Z0—λώV¬P„f 1*nήA B B B ς½""Y DD²&u/Φroί$ $R~˜ADDDDD,Δ¨ΈyGΩ‘aΓ†J{p7 (έφ+VΌ&­έςε―H 6$§LΉG6jΤHΊλωτΣOδ ΓΫΞzϊι§K jάώ.ξΎtŽ9ν,ι.w΅‚³νΟMΝ•n»ί>τŒt }‡ZΪvνσέ%νσΊˆ{ώ~ϋπ³–ηšΪΘ^οήβφk©Ά_θύΟξΫ65–έG:tΪEžτ³¦0ς­#kάρ“ΤύΏXΛ½}³Ψ@€ο™ρŸΡ]~Ϊ€ΜψΟxΐ ™ρŸΡ]^¬ξύ;©)³l ·mwήUΠεͺDDDDDLΚ¨ΈyHF‘@· f&!!ω·…nŸ@€8Λ½}“@„@’ƒ@“2*nήQφ@Δuψπα²K—.>φΫodMM7nœ χΝ:`ΐΩ΅kWiŸ―\ΉRZ‘ΰε——Κpί¬wί}—lΦ¬™t—»ΊΈψVΠq ©Ή΄‚§ν§½ΌΩΧΦηΜ՟Κζ-6‘½‡]#m –ύŽ:VφΎ|„t Ώ…ξ.‹ DΊ{Ί΄—ΈϊΪ„{ό’φΊϋgI›jΔ‚*+$_|Γ­^Zν[GšΊ5ϋ·-·BΏ½Œή D¬»aΓ†ς’λo‘φΉ΅;Ή%^.oŸ»zώγZt 2σIiŸοqΠ!ςΌ‘WKϋά<ΆΧOeΎ@δξ%+eZΧsάσgϋgϋ[θ”SqϋΗ΅TΫ/φώηjΧΓ6;ν,-hυ΅Νwό$u/Φroί¬Φ@ΔΖΉ!vύωΪ&!T"ˆˆˆˆˆ˜”Qqσ‘Pί¬"k›TAŠ@„@$JAέ5nA·P DDJ±}‘β,χφMHDDDDDLΚ¨ΈyGjΘκΥ«dmm­\²δEωΥW_ΚΕ‹ΙN:Ι>}zKw=ύϋχ—ΦnΥͺ•rΑ‚€M•ε&ώσŸ€*6eΦηŸ&ί=iSfνΏ~2ΌmŸ.ξ~±Ηχ”ϋ}œ?g‰œΊμm9tόdyΜigJ·>‡#[Άi+―`ΆμΝo€ΘNωω/€ΫίLͺ UlApτ“ δl(χΘιk6ξρ+•χ―ψƒόί—ŒΨΛΨ}}Τ-¨ΩΏmωΐ›'ȍ7–n 2ω₯Ur½υΦ“—ί>UΪΤ>#§="νϊΛˆ{ώ]mΚ »ž}m²&ˆVoi/Ά)fμeώ5›n&σ"¦νΏ«o|ϊΪΖ1©σ·σήϋΙ#N:]Nyω-iz›ͺ/Χύ nΈ&½ύBοVˆΎτ¦ Άoχ1»ξμzπ­#kάρ“ΤύΏXΛ½}³Ϊ‘Ÿτ½Hn»Λnξ n»¨F½Bu@ ‚XΈΛ—/“/ΌπΌ|κ©Η₯oμΤ'ν{ΪχΆγΰ;FˆiΛΈd\bt/Œ—R7ο !!!ω^· fΆε""""iYξν›"""ˆ…K!‰BVžŒKΖ%F—ρΒx)₯QqσŽΤ›ςjβΔ;eηΝe“&Mdϋφν₯kΦ¬‘ξzΎψbμΥ«—lΦ¬©΄ dȐΑνgΝ;WtΠA¦Ζ² €{χγε›oΎ)}λλβ>ΰ[Π±—|ΫΛ³7mΧ^6iΎ±άηˆcδMΝ•n³]!mЦ™«>‘wΜ_.­`rεΔϋ€Ϋί,vΫl±₯΄νδ-¨ηŽCσMj€υ·B£Ϋ>ξρ«Vέ‚šύΫ–O_ω‘l½y;™λόe_$žΥ aV@ΆΊ·\uΧBΟΏkΤ‚\RΘmΟΏ,wά³‹tΏΏ½”;j rωmSδ¦νΆφύνΈψϊΔ1ξω›πάRΉϋΛF›H ŽόΙι2W@·\γn?ξύΟΆoΑ΅«iέFΪυ3ύΝ₯Ϋί΅ΨρSμύ?)Λ΅ύ6—fΞ_ΖηgŽΣ:l: s^2Ίύλj b½υΟgρουώ ՁbαZ!eαΒδG}$έηφϊζΗ$ν{ϟΌτ#Δ΄e\2.1ΊŒΖK)Š{~DDDDΎΧ-¨ΩΏm9HΦ|η/n ·\γnŸ@$Λ΅}‘ >sΧ¨χ_¨D —B…$¬<—ŒKŒ.γ…ρRJ£βžŸΤ‘ϊͺ‹ο!s ΥI8 λ{ΨA¬Vmʍ>ϊPΪ”ΟΥ’}o;Ύc„˜ΆŒKΖ%F—ρΒx)₯QqσΛADŠΤΕχˆˆˆˆΉ…κ$‚„υ=μ V«’($aεΙΈd\bt/Œ—R7ο ‰©‹ο!s ΥI8 λ{ΨA¬Vm\ψŠ,Υ$χ¬$—ŒKŒ"γ%ρR£βζ"1uρ=δ#"""bn‘:±ηWίΓb΅jγΒW\©&Ή?`%ΙΈ d\b/Œ—7ο ‰©‹ο!1 }/>ŽβV;t”ΎuΦ%}ί-Šυεϋ—[ί±"Η³BubΟΎ‡ΔjΥΖΕgŸ}ZΥrΐJ’qΘΈΔ(2^/₯1*nήA SίC>"bϊŠΝQ¬/iίw‹"ωdτΫ(rό1+T'φόΰκ{ΨA¬Vm\ψŠ+Υ$χ¬$—ŒKŒ"γ%ρR£βζ"1uρ=δ#"""bn‘:±ηWίΓb΅jγΒW\©&Ή?`%ΙΈ d\b/Œ—7ο ‰©‹ο!s Υ‰=?Έϊv«UΎβJ5Ιύ+IΖe γ£Θx dΌ”Ζ¨ΈyHL]|ωˆQ¨μωΑΥχ°ƒX­ΪΈψτΣOͺZξXI2.—EΖK γ₯4FΕΝ;Dbκβ+r#F Z°ηWίΓb΅jγΒW\©&Ή?`%ΙΈ d\b/Œ—7ο ‰©‹―ȍU€ϊΚ²eΛ€aΟΎ‡ΔjΥΖ…―ΈRMrΐJ’qΘΈΔ(2^/₯1*nήA S_‘1ͺυΔΒ΅qα+T“ά°’d\2.1ŠŒ—@ΖKiŒŠ›wˆΔΤΕWδFŒ*@}…@±pm\|ςΙΗU-χ¬$—ŒKŒ"γ%ρR£βζ"1uρΉ£ P_!A,\ΎβJ5Ιύ+IΖe γ£Θx dΌ”Ζ¨ΈyHL]|EnΔ¨ΤWD ΧΖ…―ΈRMrΐJ’qΘΈΔ(2^/₯1*nήA S_‘1ͺυΔΒ΅qα+T“ά°’d\2.1ŠŒ—@ΖKiŒŠ›w€ˆ,\Έ@vλvœlήΌΉμΠayν΅#₯―oΦ/ΎX#{υκ%›5k&[·n-/»lˆτυΝϊΚ+Λδa‡&­f›m&‡ύ₯τυυιβ+rcρŸτ€lΥvsιkSŸ¨―ˆ ‹?ώ¨ͺεώ€•$γ2q‰QdΌ2^JcTάΌƒ@„@€’%¨ˆ  _q₯šδώ€•$γ2q‰QdΌ2^JcTάΌ#υ@€ΆΆVΞ=KYσG9oή<Ω²eK9iDιφοίΏΏμΨ±£\΅j₯œ?ž¬©©‘γƍ“ΦοΫoΏ‘Φ―OŸήςσΟ?“ΤX02~όxήΆO_‘‹—@ ~@ ‚XΈ6.|Ε•j’ϋV’ŒΛ@Ζey5fŒόΝM7Λ'ž|RϊΪ–SΖK γ₯4FΕΝ;DD*Z€ϊbαΪΈπWͺIξXI2.—ε•@€nΙx)QqσŽΤ‘|φθΡ]φνΫWΪηhXΰ1vμXξ›υ‚ .]»v•φω[o­– 4+W”αΎY/Ήδyδ‘GJwΉ«‹Ά'/]-χ?¦›lΦ’…l΅Y[Yϋ‹ΛδΜUŸHλ7ϊΙrƒ 6”w.xUΪrσΆη_–λo°?χ%y٘Ir‹m·—[ξ°Sΰφ;Κs_!›oR#?ρ4iλΫߜΆό]yόY½eλΝΫΙχ;UN]φΆ΄~7ΟzNΪyΚgΟσϊΛπΆΓξ}ψΡςˆ“N—»μ{€lΈΡFΦ3hΤν2ξρwΫ*@΅`ΟΎ‡JtόνwH+D˜3fΞ”Ύ>Yο{ΰ~ιφ»σ»€―V―6.>ϊθΓͺΆέJνίwΪIff#ωŸ»ο&}λΒΒe\2.ΧΦύ»`Κ΄iΧ6 λZ ⻆ͺIΖKiŒŠ›wˆ„ϊf%!!(=φόΰκ{Ψ©D D0 m\ψŠ+Υd]»?”Z‘ςΚΈ d\-ˆ_ΖK γ₯4FΕΝ;Κˆ|ύυ_δœ9ΟJ›2kΪ΄©Ϊ½χή» Ψ6ΕVx]Y-(iΥͺ•΄Οέ@Δ¦Ϊ χΝjΘV[m%έε.VΨ>ΉίΕ²cη}δ€E―Λ‰ _“§^πrΤγσeΈ(ž΅S—}εY/—ξς3.$w?ΰ`iŸ[ QΣΊœό*Ωq―½₯4­ 5’w-~CΖνoϋqpχεϋ$'<·Tήυβ›Φsτ©΅ϊΉΖ2Λ‘7–φύξ}ν}ιλ“΅ΨγW€jΑž\};•h@δζ[GΛeΛ–JkKKδοn%έ~"θΣΖΕ‡~PWΌΎB.ZΌh-ί\ω¦τυ)…uνώPjέ@δΟΗw“ΎΆ˜ΌŒΛ@ΖεΪˆψeΌ2^JcTάΌƒ@$Τ7+HV€bΟΎ‡J”@ΣΠΖ…―Έ’†’*S‘ςΚΈ d\-ˆ_ΖK ¦ZMςIDATγ₯4FΕΝ;Κˆ 6TZ@a4PΊνW¬xMZ»εΛ_‘έ»/$§LΉG6jΤHZ›rk§Μ YΟ?|ιΎT½}ϋφ Trιb…νS\*wέχ@iSh…‹ίλrΐu7Λ-:l'νσ™«?•m·ΪF^rγhiΛ­ΰoAŒ}~Τ)½€ςνσ6[l)oztŒΫΚΛoI;O7=–ω<£΅7ϋΠ3²ιΖ-€»άL*9ζ΄³€―Οb\ͺ{~pυ=μT’nαγΦ±c₯ύϋαG‘Φ~Ζƒ3eφΉ‘₯K_’̘.njŸ oΊe”7α6ωΘ£J·ΏωθcΙ±™ΆY-˜3~ΌΌχώδ‹/.–Iχw—ωΫ›o‘ΆήG{TΊύΝΕ‹Ι‰wέ-oΎυV9ώφΫεc³fIw;ση?/m=•r\σiγΒW\IΓ_]u•ά·λ!r}φ“έzž(}}Ja]»?”Ϊ€‘nέJΪz֜}–όvŸ½εΏš6•^}•,΄ύλσž—_τ:Cώs«­δΏ5’άzkΉζ§ηΘΧΎ γξη'ƒΚn³΄νύWϋφςΛSN‘o>ω„t·—OΖe γrmέίΉ\ˆύώά?ύiΏ?φϋ16σΏ³NŸ9CΊ…ι"Φ~bζo‰¬7ΊUΪοΩ³Ο>#έυπ;ζο—΄Œ—7ο !!ρH PZμωΑΥχ°S‰Ί…‘bŽK>m\ψŠ+iH!©2%!a\VžξοH γ%ρR£βζe DL›2kΡ’…²cǎrĈΪŝ2Λ΄½t½Y³¦rηw–^*·έΆƒtϋ»ΊXaϋήWί“65ΦN{ξ-;tΪEžτ³ςώΧ?α’xΈ“fΝεΘ©Λ«'ϐMšo,έ©Ÿ,Π° Ζ>ΡιgΛ³.&νσΝ·ξ o|π)·Ώ#vž’:υ•w€­ΧL*9σ‘ΧΖg±Η?Υ‚=?Έϊv*Q·πρΐŒ £ΖŒ•/½τ’΄©΄άƒυw‘εΛ—I+τ[; V^~ω%9υή{₯-Ώ€­gώ σ₯-ŸΩη¬ΦΕ%‹εμΗgI[Rύσi‡ll;O?σ΄΄vv<¬`cνl{φœwΟΤi–›ˆTΚqͺ‹>ψCYόςΛ/ε/―ψ•άkΏδ!G-}}Ja]»?”ΪR"¬ž1]Ϋώ΅₯Kδ?Άί^ZϋΟvΎ|}Α|ωε§K[ώ·έw—―Ύςr`Ϋ}λήiΪύ½cGωϊ σδ›O=!?Ύ|¨\sήΉϊG•qΘΈ\Ϋ|Θ+™k:λψΫ2Ώ?­έΜ”φϋaA‰-ΏνΞ‰~Ώl}n ’ Q²Zpράσs₯ύ‡ΦnΑ‚$ΏcŒ—ϊ`TάΌƒ@„@„@Δc±Η?Υ‚=?Έϊv*Q‘d &"λΦΖ…―Έ’†’*SΖeεI β—ρΘx)Qqσ޲"Γ‡—]Ίt‘φΉMyUSS#Ǎ'Γ}³0@Zΰα.ΟgώύεO~ςιkΦΕWδ{χ’•r›v–ηκZιk›Υ^:~ΔI§ΛΓ~|Š<ζ΄3₯ΫΎθ@cζ“2n{–Ύ%-θ°—―[ϋB½κξι²Υfm₯―ΝΊ΄@Δέο¨zόγ P-Ψσƒ«οa§u 3zP>όΘΓςϋΓwHϋχ¬Ω³₯Ψνs7yζΩg₯-·‚†T¬έόζI·M±1χΉΉ–ί2z΄΄©₯¬`b[―·TοŸ>]Ϊv,°εsŸ›#mΉιnΧ-π˜ˆTΚqͺ _q₯”ώώχοΛ_ $8δ09νΎϋ$…€ςκ"ω΄)¦άυΈAΓ§ΏΈDΊνΜ¨νίΏεfiνώo½υδŠΕ ₯΅³)«ΎoχοLš(­]ΤνΎ{ϋmΪύO‹ςγΛ†ΘwοΌ]Z γφ*γ2qΉΆω‘gž}FΪrΣ~W¬n»ηŸ^Z;7q§κ4m -kgΏ·όŽ1^κƒQqσG‘°"₯Αž\};•(HΗΕΖ…―ΈRJ)$UΆ""ŒΛΚ“@Δ/γ%ρR£βζ©"«W―’΅΅΅rΙ’εW_})ν*έ©S'Ω§OoιΗ k·jΥJi—/›*+W`bSj=ύτSς³Ο>•wήy‡΄)΄ζΜyVΊύ]]¬°}rKδ₯7Mφ²ρρs–H ϊ]}ƒ ΕΓ^w,Ω¨IΣΐΖM€}ξΆ/w bŸw=Ύ§άοθγ€}ο©Λή–CΗO–ω‚…ΡO.l°‘όέ#s€―­ΟΈH‘Η?—6ε—폯MV€ϊΚ²eΛ€aΟΎ‡J4W b…{Ω·-·)΄¬πž/ylφ,iΛ uΑΒΦ—k*)Σ ώΉ¦ΔˆΫαG‘γn»MΪΛ^}λΚjλ?ϋ‰Η₯-·—Ÿ‡·‘Υž3ΓλΚjH₯Χ|ΪΈψΓ~ŸŠοΏžΌdΰ i€—^~YΎ—Y–υΡY³€o₯°έJ­ˆ$5eΦ#GH_Ϋ¬QΫόΛΛ€΅ϋŸfΝ€ΫΞ¦Φ²vζΧ]+­]ΤνΎ–Ή·fύσqΗI bΒλΞϊΏl γN™ε»VK!γ²n˜/qμw0ΌŽ¬φw‚΅3Ÿ|κIiνά@δρΜodΦπΊ²ΊΏS“§L‘Ή–»ς;–ŒŒ—7ο !Y+Π YΫB. D Ϊ!!!‘T¬uνώPj DD—•'ˆ_ΖK γ₯4FΕΝ;R DlΚ«‰;w–Mš4‘νΫ·—ύϊυ“kΦ¬‘ξzΎψbμΥ«—΄Γ‚!CK·Ÿωξ»οΘ#]¬°=αΉ₯‚¦·5­ΫΘngž'§Ώω‘ Ε}nΉΓNr‹ΫI_›¬•ˆΨK»ŸsΎά΄]{i/#ίηˆcδMΝ•Φ/—Άžζ›ΤH›’«ηyύ₯―OΦΈˆυψη’@ͺj DlΉ½dέ–?τπΓ–η Dά©5~wΛ(ιΎT΅P-°yξωη€8l;¦΅‹ΫίύVZ°πiλ½οϋ₯΅»sRζxd΄εΉ¦Μr§Ι?eVeΧ\ΪΈUJaΎ§Ÿ~"?όπiυίΊJa]»?”ΪJDbO™5ρNiν έOΣ^¦nλ³$Ό­¬…N‘ΕΈ d\mΎ@Δύύ1£N™eΏ/ΦΞ D 2ΛmΗοXieΌ”Ζ¨Ψω6 DDD"H ‘¬"ώγšKα’J)€T·$!a\Vž"~/Œ—;ίfjH}ΥΕWδNB (jγ—ΧKgZΗ ΎRmH>σ"V ΫmΪMŸ9CZεΕ%‹₯M₯αN…a/·—ˆZ``SrXαΓΦoS}Ωφγφϊ™§δΏ—–‹/”6Υ¨Ρc€΅s[ίΨ ·IkχΰΓI+ΠδšϊΓ[OΉ«­'Ÿ6.με°₯rφγΛƒ?RZι“O>–Ύ>iZΧξ₯Ά› λΫn+­ύη?;_Zρε§K[ώŸ»ν*_͌!ωέϊ’nχνiSδW'ž(ίΊwš\‘ΛYί½γviλωW³¦ς΅Μ½#«»Ύ\2.—k›/±ί‡q™ί°¬Φn惙Ώ2ΪοΨύΣ3d΄ε·ίy§t?ά@dμψ •ηη='mΚ+sAfμeεw,]/₯1*nήA S_‘; DΚ+@<DΦ–@„@$Š6.|Ε•$₯T·$!a\Vž"~/Œ—7ο ‰©‹―ΘΗ+'ή'7lΨPήρΒ«Χ“7νγP_!YΫ|ˆΉtιKrϊŒ›κiΜψρ ξTT¦φο˜4QZaΓŠ;'M’VIͺΏN˜1]ή2zt`¦OΦ»οΉGZαθϋγα"ζβΕ‹€/›‚Λ^ΦώΘcJ[i…[O₯Χ|ΪΈπW’Τ F\³FVJΙ¬kχ‡Rλ"ωόοM6‘ξz’ f‘νίx~΄ΰγΏΆl/΅ΡFςŸ[n)ל}–΄)άυDέ½Tέ^Κώ·Ξ{I >ώgγείΊt–ΈλΙ'γ2qΉΆωsι%‚ϋ½qlκM JάυΈˆύžέ1q’΄ί#ϋ}{ϊ™§₯»~Η‘ρR£βζ"1uρΉγH R^ D’@dm DD’hγΒW\IR IuK‘JqΉΆ"~/Œ—7ο ‰©‹―Θ]Œ[νΠQΦlΊ™μwυ Χ“·\Η ΎRί¬L­`c"›"dιΛ/I_ŸJΦΖΕ{ο½›ŠVΈρ-+§ά°’d\2.ΧvμwSVΩΆΥ$γ%ρR£βζ"1uρΉ‹‘@€Όˆ$ ¦!H<)$!ζ—qΘΈ\[ΏŒ—@ΖKiŒŠ›wˆΔΤΕWδFŒ*@΅`ΟΎ‡Dσ‘G•6Ε‡M}eSiΩ”VΊχώϋ€o]uAοΎϋNUΛύ+IΖe`΅K›ςΩ9ΟJϋέ1ηΜ}VϊϊV“Œ—ΐj/₯2*nήA S_‘1ͺΥ‚=?ΈϊvM‘κ”ϋV’ŒΛΐj—"ΡdΌVϋx)•Qqσ‘˜ΊψŠάˆˆˆˆˆΥξάΎ”φo{~pυ=μ š/½΄DΪΛΞG+νε―·έq‡œύψ,i+ίΊκ‚6.ήyηνͺ–ϋV’ŒΛΐj—οΊ[ή2z΄ΌνΞ‰ς©§Ÿ”Ύ>Υ(γ%°ΪΗK©ŒŠ›wˆΔΤ%όΠ‡ˆˆˆˆˆ"˜„"Υ)χ¬$—Υ>. D’Ιx ¬φρR*£βζ"1u ?τ!""""b bαΪΈxϋν·ͺZξXI2.—EΖK γ₯4FΕΝ;Dbκ~θCDDDDΔ@ΔΒ΅qα+T“ά°’d\2.1ŠŒ—@ΖKiŒŠ›wˆΔΤ%όΠWIŽŸϋ’άaχ½δϊl wέχ@ιλΆηyύεQ§τ’Ύ6ΥΰΗφώϊfιkS¬ΆσΙυ‹ˆX˜'œΫWžqρ`ιkƒΙkŸ5hΠ`-οYϊ–τυ©Kˆ ‹·ήZUΥrΐJ’qΘΈΔ(2^/₯1*nήA S—πC_%I ’Œ"uS_DΔΒ$)"Ύ‡ΔjΥΖ…―ΈRMrΐJ’qΘΈΔ(2^/₯1*nήA S—πC_%i…ΰcΟ8GN_ω‘τ΅ΕzγƒOΙMΫ΅—uύψ "⺜Έπ5ΩΌΕ&ςξ%+₯―-&ονσ^‘"ˆhγbυκ•U-χ¬$—ŒKŒ"γ%ρR£βζ"1u ?τU’"ρ$ADΔj’@€Όˆψx«QΎβJ5Ιύ+IΖe γ£Θx dΌ”Ζ¨ΈyGκΘΒ… d·nΗΙζΝ›ΛΆ‘Χ^;Rϊϊf½α†λ₯= šl°τυ ϋΕkd―^½d³fΝdλΦ­εe— ‘ΎΎ>]Β}•δφ»ξ!ίz‡τ΅Αάyςς€Ÿ Ύ6uIDΔΚ¦Ά΄Ώkn}βιΆ4κvΩ¨ISι.Ώκιrη½χ“Φn³-·–gΊBΊύrΩε°£δyC―–Ύ6˜Όυ5±ΐΔώmΟΎ‡ΔjΥΖΕΚ•oV΅ά°’d\2.1ŠŒ—@ΖKiŒŠ›wˆˆ` D±”ˆ`Xb5jγΒW\©&Ή?`%ΙΈ d\b/Œ—7οhםL-©­­•³gΟ’kΦόQΞ›7OΆlΩRNš4QϊΦvƌ2j ΏΩ±cGΉjΥJ9ώr£Ζε"'/]-έώqΏRŽ~r΄οŸo{—™$·Ψv{Ήε;nΏ£/Υχ/Φb›βΙ>·γζ6[l)oz4σ=3Ϊ6εΕΘ©KkoώμΚλδ6;ν,νs+ΈΨρϋΜbξ›Υ QΟg‘Ϊω/6(φϊΙeΤλΧ=ώΧήϋ¨tΫ•jΚ¬J»ώ1=έ@$Ÿ…"φwˆMέ9}εGΧ6¬ρΆέB‘JστΜ½7«ίξr 4μ>ν.2z’lΩ¦­t—Ηνoˆ ΈξfΉE‡ν€}>sυ§²νVΫΘKn-Γ}γυο{©ΊύύcΟΎ‡Δjυ©§—Λ—/“+VΌZU._ώ²΄γΰ;FˆiΛΈd\bt/Œ—R7ο !‰$H!˜Ε^?Ή$AΔJ—@$ DDλš’($aεΙΈd\bt/Œ—R7ο([ bΪ”Y‹-”;v”#FŒΎ>a£"εž2λΜK‡JwΉ«Ζm?£:υ•w€oYΛˆZ.Υχ/Φμ J³Ϊv¬`νk›Υ ξΛκtϊٝβΙΞ‹ά@cά³/Jko^6φ.Ω’e+iŸφαg₯υΟ55[·3Ο“QΟg‘{ώΝΈύ]£^ΏQ©ό‡L:©΄λΣΣ D’š2λδ~ΛmwήUN^ΊZϊΪϊŒϋRυ΄΅ΏsΆίmOΩΈi3Ύgfν|ΘνoFkn”ξςλ§?.Χ[}9sΥ'–Ηνoˆάϋκ{²I³ζώÊ«'ϐφrχ|S·jΤΏζ~π₯΄ΏΒ!HXίΓb΅ϊΒ ΟΛΩ³‘K–Ό(_{my½ΦΎ§}οωσŸ—Ύc„˜ΆŒKΖ%F—ρΒx)₯Qqσ§ˆ_‘`;"Ρ,φό›qϋ»ˆ b₯K ’Œ""ˆυM I’°ςd\2.1ΊŒΖK)Š›w΄kΧN–-q>|Έμ₯‹τ΅ 5ωφΫodMM7nœtΫ 0@vνΪUΊΛ]]Β‡Y­`κΒsiΌφl/‘φ΅-D{π¬τ@€TίΏXmЉζ›ΤΘkξ™)}m³ˆΜ|RZ‘©θ)³Ύ;^vόΚ5e–½ ώΌ‘WKwω±½~*έσo{ύδ2κυkSΘ¬ŸΉ—dΝ5e–­'W Rμχ―΄λΣ3ι@δδώ—H Bξ^²RϊΪΛ>WŒ”v_φ΅©-Ψ°aCyΡυ·HϋάΪΩqΩλΰΓexY-Π°ίwΉύΞg_žΥ]·Ώiη«Ψίƒ£O­•GœtΊ<μΗ§ΘcN;SϊϊΔΡΎbςΎςΚΛς‘‡fΘργo•£FύΆ^;~όhωΠCΣ₯ί1BL[Ζ%γ£ΛxaΌ”¨Έy‡ε "ίI β—@„@€ DD±0 DβI ²Ά"ˆυG I’°ςd\2.1ΊŒΖK)Š›w€ˆ¬^½JΦΦΦJϋΏ}υΥ—rρβE²S§N²OŸή·°Q³ώΆ³jΥJΉ`Α ¦ΚΚ˜ΈΊ„³ˆ˜]ο)χ;ϊ89~Ξ9uΩΫrθψΙ2κƒ­=xVz b&ύύγj/ΡΆ—yϋΪdZ°ΟνΌX bŸtά rΟ‡ΙI‹^—p΄ίnyFŽ—ŽοΌχ~ !6ΥΧχ/‰oΤHF=Ÿ…zόY½₯½ΌΧ¦h±—ΧlΊ™Μuώγ^?…^Ώvένsψ1 SΧ?0[6kΡBζ Dβ~J»ώ±τ&ˆό€οErΫ]v““_Z%έvQ΅©₯ΞύεUΧf]vθ΄‹άqΟ.Χ& ν{·ήzςςΫ§Κϋ_@ΪΤ_­6k+σ"›Άk/G͞'-°ί' Ά“ξοΪͺνζ²ίΥ7Hϋ5|mΓ^w,iΧI£ΖM€}ξλGDDDDDLΫ¨ΈyH$ DD ‘@„@ “@$ž"kK ‚ˆˆˆˆˆυέ¨ΈyGjˆMY5q❲sηΞ²I“&²}ϋφ²_Ώ~r͚5]ΟΓ?$­`Λ-ZH·_¬‘½zυ’Νš5•„ 2XΊύrι~8ΜZl b/Iξ~Ξω¬νe˜ϋqŒΌι±Ή·Ž°φΰ5i³Ε–wlΓ6έΈ…tϋΫ±ν€Ώ\ν₯η›ΆΫBΪΤJn»€‘»Ώ!κΦS6o±‰lΩ¦­μ~vyŠ?HλgNxn©άύ€ƒ₯B,(9ς'§ΛR"·=²΄˜0V€²—Ίη:q―ŸΈΧ―lόΪKywΨ}/iϋoΛέώqΏ₯]ˆXzγ"φ{ΎΗ­K»…ΧφΞ―J €-φ΅]—νΆΩVΪ}ΛΧ&IνwΓ‚χώkyοoΖ‰η_ ·θ°΄ϋ―Φφ$έίυςΫ¦HϋϋΓΟύ>ψϊ„έr‡€ν‡―Mˆ "Λۈ˜°Ύ±†ˆ˜5*nήA B β•@dm D “@„@ “@$νwƒ@$@1]}Ε\DŒ§o¬!"fŠ›w€ˆΤW]Β‡X΄©¬\w³τ΅Αϊo―K†Θ\"b]χ„sϋΚ3rL͘ϻ^|SΪVΧά3SϊΪV’h\ψλ›₯―ΝΊŒΫ?i- ¨ύ_J_›4΅@ΔώAΒϊvλ‚Ύb."ΖΣ7Φ³FΕΝ;Dbκ~θΓϊ'f%AΔϊ.H)$AΔϊ―˜‹ˆρτ5DΔ¬Qqσ‘˜Ί„ϊ±~J ‚ˆΈn‡Œž(;vήGϊΪT’υ%Ήrβ}rΓ† ε/Ό*}mΣΤ¦ ΅‡CDΔϊ ―˜‹ˆρτ5DΔ¬Qqσ‘˜Ί„ϊ±~J ‚ˆΈn DD|ˆ b}ΧWΜEΔxϊΖ"bΦ¨ΈyHL]Β}ˆuΝπ w q«:Jί:λ£υ5ρΫ(&uώ}λŽ"ΫgϋυaϋXΦυ@ΔǚM7“ύΎAϊΪ–Γ¨Τo }ΞˆC8λΘJ S—πCb]ΣWμ‹b΅ DΦ6©σο[wΩ>Ϋ―ΫΗʐ@€΄ˆ@–BŸ3βΞ:²ˆΔΤ%όΠ‡ˆˆˆˆˆ"₯ΠηL€8„³Ž¬"1u ?τ!""""b d)τ9 α¬#+HL]Β}Υ(€eΛ–I#‚„…ϊM‘Ο™qgY Dbκβ ͺI"₯ΠηL€8„³Ž¬"1uρ…Υ$€ΘRθs&@ΒYGV‘˜ΊψB‚jΐd)τ9 α¬#+HL]|!A%:fƒ7εψ-VJ_›bˆB8 υ›BŸ3βΞ:²ˆΔΤΕT’"PNΒ!HX¨ίϊœ ‡pΦ‘•@$¦.Ύ %€rAΒBύ¦ΠηL€8„³Ž¬"1uρ…•(”“pκ7…>gΔ!œudM=YΈpμΦν8ΩΌysΩ‘Γ6ςΪkGJ_ί¬7άp½lΠ ΑZn°ΑΧ'lάώ. LαSyη‘oΙ±ί”γZN:ύ]ωΰŠLϋ¬‘P! D œ„C°εβξ)SεψΫοoΏϋ„d)τ9 α¬#+Hύ]], ΘM8 [.D‘ΠηL€8„³Ž¬©"΅΅΅rφμYr͚?ΚyσζΙ–-[ΚI“&Jί:ΒΘ1ChΔνοbΑΐν{­–c›Ό)οδc9mΜrLƒ7δ€Ϊwe8THC('α$l±LπAiΖœηž—Q!I‡BŸ3]άσœΟyT@uΞ:²ˆˆˆ@κ„C°ΕB R7(τ9Σ…@ !œudmם¬˜—ͺχθΡ]φνΫWϊΪ„­΄@δώΗ>’xάyΤΫ Ζo΅JΪTZ3_LΪςισ>‘wώ(Σ?γΈ–oΆ^)'v[ΞXπ‰ ―;λ½γ?”ΆY)έ©ΊD œ„C°Ε7t(τ9Σ…σ …Ξ:²ZB B ’ˆQ‡ a‹…Byέ ΠηLΞ3B8λΘZφ@δλ―"ηΜyVΪ”YΣ¦M•Ύ>a+-™zγ€"wσtƒƒΫχKZ; R|σS9a‡Ur\«•ς'>|ώXΪχ™tχδΐΙχΘηηΏ s]―I]χ+ήxCΪρ³ώSο»_Ξ_°P~ϋ·ΏI—ΈύέλΟΌνΞ‰ΦϋڊΧe.ώϊΝ7rΦγOH;Μ|PΎώΖ›έΞΧ¬‘FRΗ >Ξ:²ˆˆˆ@Ι! ¨φf‘Ο™.qΟ³αžΟ|AC‘νν<ˆ$uέˆˆJ8λΘZΆ@dΨ°‘²Aƒk9hΠ@ιλ㳑)Γ/-pΈϋόw₯άyθΫΪέ7ν#yοέJϋ|R―w₯ΫbΟw€΅›ώδΗrΪΨ€}~wοχ€υ›ΎθiΛ D κ[ rίΣ₯Nίyχ=iΛ'άq§όϋί.υ―I+xZ; VώλΏώK>7ož΄ε .’…²ό΅Χ€­§X_~ε™…>gΊΔ=Ο†{>­ ώ§?YΊDmύyώ.H°φK3Χ~V;Ο eΞkF[ώΠ#J·`]θ~FΕ Df<ψόϋ?ώ!έύ3­ΠoΧυ]χL‘ΆόΜ˜Ιj$uέωε—–Ϋώώ3Σ7λί2c0λΚU«δ’—2λΟhΔνŸ 8,€°νόώ† N¬ 8žϋœ΄ε¦"IW€j œud%!!€’C B ’₯ΠηL‘¬…"Αςbο'u™pΦ‘΅lˆiSf-Z΄PvμΨQŽ1Bϊϊ„­΄@€θ)³ωXN½6Σ?£}Υ{οόPNΉζ>Ώgπϋςϋm― ΄ε"υ-±Β°a…L[nώρkδ~(νs›bηΏϋΏ₯ρΕ_J·])•ςQl0’tbϊœιβžη|ΪS.ξω|uΕ ™‹¨νέσlΊηΩ‚4·έηŸ.Bχ3*n bSIoΏσŽ΄εζόΟHγαG“Άά‚#©λώ“O?“Άά¦κzγΝ•ςΣΟ>“ΈΔν•…‹_”ΆΉΟΟ“Ζǟ|"mΉιnΧ pL D’:Υ@8λΘJ B B %‡@„@$K‘Ο™.""Y DD’Ξ:²–=q>|Έμ₯‹τ΅ [iˆ½έ‡;z[ΊΑΑψ­VΙ1Ύ)gΎϊ©Όw‡ϊίΥη=ιφΟ%Sf@%RίwωϋOΪrΣ άo¬\)έεQ;ERΤ`€TAˆQθs¦Kάσlδ;Ÿ.QΫ»ηΩ^ΆοbSY;Σ¦^3 έΟ¨Έˆ»ήwί{OΪς‰wO–.n b/g7’Ίξm*±\SI™Vπw§ΌŠΫίXώjfeΌΖ i/Cχ­+λc³—Ζκ·ή–Άά^~ξς·όO^WV D’:Υ@8λΘΪ§”‘,…>gΊˆ¬{?£B RXƒ@ ξΞ:²ΆkΧN–<Y½z•¬­­•K–Ό(ΏϊκKΉxρ"Ω©S'Ω§Ooι[WΨJ D,ΈmΟ·δΨ&oJ›kژ€wσΆ΄~3_Ών*9nΣ•ςώΙ™―}*ο›ώ‘ΌσG™ώ­Œ₯ŸΚ±M3ΫΝhΗŒωŸΘ»/x_F DxβciνΗnθk›ΐG΅"ξ7V΅ΒxZδ FJ„…>gΊTz βžgӝΚ(Χ”YŸe•¬F‘ϋ•΄‘R]χφ2t;^`ΨvΜ\S`Ϊίύ„ΈΑΒ Jkχθ¬ΩΘ5e–έ?ŒB§Μ*Χύ .`š–ƒˆˆx%€$ !ΙRθs¦ ΘΊχ3*""Υ‚ύύi¦ˆ|ϋν7rβΔ;eηΝe“&MdϋφνeΏ~ύδšΜ|Vw=?όlΠ Α:mΡ’…LΊΏ«‹Σ_ψTήqΔ[rlγ7₯ γZ―”3~"Γ‘‚ϊ?χ‰œΨύm9~³7εΨf·οσ–ΌχŽ₯Ϋί¦Ξ²©ΉΖ΅xSN:ν]9fƒΜΎd$€rAΒK₯"V¨|`ΖLiΛ½ΈDΪKŽφ·ΏΙw2λΞϊΤ3ΟΚ€yyΩ+k™…>gΊTz bηωώι3€΅·—[}Α’E–?ψπ#¦v2 έΟ¨€ˆ$uέΫΛΑŸŸ‚΄ΐΐ‚&{)Ί­ί Ϋ~άώοώχ–Ϋρψϊλ―₯#wί3EZ;7±υέϋΐtiν,΄ &ΧΤ^ˆΨz*ε~PΙ„³Ž¬"9$ $€RAΒ HaˆˆˆˆTα¬#kjH}ΥΕ„ό‹χ₯ “/~OϊΪΦE’AΒ‹[(Ο§„|…η|Λσ"Ζ?ωOΉxΙi…Q›ςfκ}χΛηηΝ—Vh­/ϊœιχ<ωΞ§K‘νρH >¦eΞiΦΫ'N’Σξ@Ϊu`…p—B·;.ΉΦ›T bΔ½ξ-(²—Ξ?όΨ,iΑΕ€ΜΎe}$σYV 8Œ€ϊ/Zό’œ4ωiΗρ©gž‘ΠΩρpγ―ύ«|μρΗ₯퇽¬ύ΅―K[iΑŽQνχ€(„³Ž¬"1uρ…a DDͺ΅€Yθs¦ ΘΊ·;.ΉΦK B P_gY Dbκβ ΦrU ½Lύώ?’ήΆuP€(„C°PΏ)τ9 ±—½[2αŽ;ε?ώρO Ρ gY Dbκβ Φ’@`­$,Τo }Ξ¨FD’#œud%‰©‹/$¨&’AΒBύ¦ΠηL€ϊȊΧ_—6…—M}eSiΩ”^ˆΜ{a€Β gY Dbκβ ͺI€(„C°PΏ)τ9 >B α¬#+HL]|!A5 …pκ7…>gΤGώώχΏΛηηΏ 'O*³/Ο:㑇εΚU«δΏώυ/ …Ξ:²ˆΔΤΕT“Q‡ a‘~Sθs&@}„@ =ΒYGV‘˜@~–-[&pκ7…>gΔ!œud%‰)δ‡@²ϊœ ‡pΦ‘•@$¦ΘRθs&@ΒYGV‘˜@~D K‘Ο™qgY Db ω!,…>gΔ!œud%‰)δ‡@²ϊœ ‡pΦ‘•@$¦ΘRθs&@ΒYGV‘˜@~D K‘Ο™qgYSD.\ »u;N6oή\v谍ΌφΪ‘Χ7λ 7\/4h°–l°τυ ;{φ,yΰΚf͚JΫώˆ#€――Oȁd)τ9 α¬#+@Ι!,…>gΔ!œudM=©­­•L¬YσG9oή<Ω²eK9iDι[GΨ3fΘ¨ˆ1O<ρΈ΄ν?ϋμ3š &Hί:Β@α„C°ξσ"""""’kTά~""©AΒΊΟ#ˆˆˆˆˆˆQqϋ₯ˆδ³Gξ²oίΎΧ&l‘H>=φXyΞ9gK_›°P8α$,@RΈyˆ#@ι ‡ a’ΒΝ;Ϊ΅k'Λˆ|ύυ_δœ9ΟJ›2kΪ΄©Χ'lRΘŸώτ•΄rΛ-·H_Ϋ°P8α$,@RΈy‡ε ""©AΒ$…›w”-6l¨lΠ ΑZ4PϊϊψL*ιέϋ<Ω΅kWiA―mX(œp )άΌƒ@δ; D#‚„H 7ο([ bZπ°hΡBΩ±cG9bΔιλ6n 2xπ ΉΗ{ΘO>ωXϊΪϊ€Β ‡ a’ΒΝ;DDR'‚„H 7ο({ β:|ψpΩ₯KιkΆΨ@dȐΑ‚>ϊPϊΪKΘΟ²eΛ€AΒ$…›wˆˆ”H7οH-Y½z•¬­­•K–Ό(ΏϊκKΉxρ"Ω©S'Ω§Ooι[WΨB{iϋž{ξ)?ώψ#ιkEȁ@υρωηŸΛ Θ/ΏόRBe²ώϋΛ;ξΈCΊδ[P‰Έy@Ι!¨>Dκ"PqσŽΤ‘oΏύFNœx§μάΉ³l€‰lίΎ½μΧ―Ÿ\³ftΧσπΓIϋƒ*—-Z΄ΦΟ‚_[ŸG}΄ oΫ'δ‡@ ϊ ©[ˆ@₯Βύ§:IκΌ»yH D’ƒ@ ϊ ©[δ+<%U˜(ξ?ΥIRηέΝ;R D꫐(†c=V^rΙ%’±χή{Λ»ξΊK–‹ΈH±ηΏRΎ]#_α)©ΒT‘TΚω<μ°Γ€Mέ~ί}χΙ£Ž:JΊΤ•λ0­ύ,τψΕ%ννεγ₯—^’={φ”­[·–φŠοΎϋξςϊλ―—ϋίe]‘άΏΧΕ^ΗψΗ?€ύNͺ½Β‘\€5~λ:nήA SȁCΉ ,u•J)ˆΤ-DΦM‘φΊr¦΅Ÿiio/"₯₯Ψλ˜@€:pσ‘˜@~D Κ]`©«TJ„@€nA ²n -°Χ•λ0­ύL; (Υφώυ―Ι9sζȟώτ§‚ —'Ÿ|R6jΤH8PΎύφΫς?σ?εoΌ!‡*xΰYW(χοu©γ“O>YφιΣGViίΊŽ›wˆΔςC ΕPξK]₯R $"u ‘uSh½\‡iνg©Š\”j{"~Κύ{]ͺλ˜@€~ΰζ"1€Β ‡ aΒδ+°μΉηžςŠ+Gq„άxγεN;ν$Ÿ~ϊiY(qΧν·ίΚ‹/ΎXn½υΦr“M6‘έ»w—|πt5j”μΠ‘ƒlΪ΄©<ψΰƒε+―Ό"ΣO?]Zαjm#ξώ}φΩgΪΩqΩyηε˜1c€mΏΤH‘ίίφΫ–―·ήzŽχˆ#δώοJ—Ώώυ―ŽŸυ«©©‘}ϋφ•ϋΫίdTŠ]oάοcΗ§Ψ@€Πλ5…žΟ5kΦΘ^½zΙ6mΪΘΝ6ΫLžsΞ9ςOϊ“,”¨φ΄―ΓφνΫΛgŸ}VΊ|όρΗΦ—ΏόE¦}|KPδ"©ν½ωζ›ς²Λ.“[nΉ₯΄σ3lΨ0ωϋί^vΎ¬έΟώsY,qΉοΧqOνztο?…^Η…’/©–ρ›‹™3gJ;.vΎmΏή}i,Y²DΆhΡBώχ·4μ{δ:οQqσ‘˜@α„C°aJ]`ΙGάυˆˆˆˆΈΊϋχΌˆψIj{"Ρ(υο΅]ξύ§ΠλΈPDΦ Θw0ΎΠ > …AΒ„‰Z`±BΎ½΄Φ¦ 9r€΄ώ\‰\Δ]I'$»uλ&­`fo›:₯sηΞ¦b±©T6l(.\(νε―/Ύψ’4ht‰:…F±ϋgrΘ! FVpyο½χδ>ϋμ#­Rκ@Δ(v ‘ωŸ‘Λ—/—;μ°ƒœ6mšt±—#[ΑεΚ• V·έv›œ5k–ŒJRλ-τϋδ*<Ή–Η½^συ|Zόψ㏗Ÿ~ϊ©ό裏€`my‘Z`Oλ:,Ά j€u| =~q)t{όγεΝ7ί,νΎΧͺU+Ω―_?ωΒ /Θ|Ώ'6nνΈΫ8(ϋ>Εrί―γώžζ»?;ήςaΗ+W βR_Ηo.ώόη?ΛυΧ__~ψα‡8ΰ€δŽ;ξ(νχΛ°σnΏ{.ωΞ{TάΌƒ@$¦P8α$,@˜RXςwύ""Q‚ —€Φ[θχΙWxΚ΅œ@„@$Κρ-τψΕ₯Πνˆˆψ°γE β‡@δ»_hPŸuΉεΟ· -@΅AΒ„‰Z`ωέο~']μAέ Ÿ|ς‰ŒJ±λw Vxp±€Α¦ŠxύυΧ₯͚5“φyTςHβξŸΠ¬ΏΦ\μ₯ΓΦ›ʝšΓ >φ½ή}χ]—R­ΧΘυ}Œ|…§\Λγ^―ωΘw>m ;nψΓ€‹½΄ΪΪΩB₯’ΤΧ‘Qκ‚j₯ί€±—£ΫώŸ{ξΉ¦,”yσζI[Ÿž %ξρ―”ϋuάίλ|χ§€Ζ›K‘ˆK΅Œ_ Τ&Nœ(ν?¬°)8νσSN9E‡~ΈΌυΦ[₯KΎσ7ο ‰©‹―ȍU€j!‚„SκK>Š]Ώ[ΐ  Ϊˆ¬?ωΞgZΏB)υuhˆ$ˆ‘hˆxBƒϊ¬‹―ȍU€j!‚„΅ΐ2eΚιbSφΨ~‘ζbΧoSͺΨηQ}μ±Η€aΆγ`…σΞ;OΎφΪk%_$ξώY‘Ο ΰΉ°Β‹υ―΄@dϊτι¦Ζ±οώΞY»vν*ωσηΛ 6Ψ@ζ›:'*qΧ[μχ1ςžς-/φzΝGΎσiΧγ†n(sαŽW›²§TδΫo#ξy+uA΅Roόρ»)³nΊι&ΉΧ^{I›2«ώrΑ‚2ίψLjΚ¬ΈΗίϊΫu•‹Rί―γώ^η»Do…’/aόός—Ώ”φφGyDwάqςσΟ?—6ž,hlΤ¨‘\΅j•tΙwή£βζ"1uρΉ£ P-„C°aJ]`ΙG±λ' ) ?ωΞgZΏBΙ·ίFάσF ’ "">D’A β κ³.Ύ"wΨIt—¦^ }m°ώxηU§ΛΫo:GϊΪ„¨Β!HX€0₯.°δ£ΨυΫΤGφ’Ρ―ΎϊJΖΕ¦°²ύ±©¬μ₯΄ΖΎϋξ+sHβξ_Τ)XζΝ+­]ZHΎοo…O ~ψaωΝ7ίH+tΪΛ•­ cΨρ³οUθu•‹bΧχϋφyΒSΎε.Q―Χ|δ;Ÿξ”0v]βN S(₯Ύ {i³R.―ΌςŠ΄ονTλκρM ϋ^C† ‘VΐξΠ‘ƒΌόςΛ₯ †?k7`ΐY(q₯ά―γώ^η»δ»Ž‹%W Βψ]›r­mΫΆwwŠ΄έvΫMŽ1Bn±Ε2ωΞ{TάΌƒ@$¦.Ύ"wX‘κ’@ΐO8 ¦Τ–|»~+8ˆˆB±λMͺ0gŸη*<ε[ξB RΪλΠ )-φ½DΦM©―σές]ΗΕB  OhPŸuρΉ³ŽY|ΉœrΔ~rΤ—7K_[¬?ήϊήurκώε¨?\/}m³ΤW–-[&p L© ,ωˆ»ώO•χέw―΄%«nΌρΧ·MΨ€HΟwq ά—ή{²όΎξΌ_L+Θ_1ε ω?ω«‡ΛΈω΄œρΡς†>[ΙΛ.}mΣtΖΗΣε%Ž‘ί/™5λιΫ&‰iΕώ“Œ]τΖΉmP―ˆΤ&"PΟΈyHIˆˆ”@mB υŒ›wtμΨQV<;vŒ΄/š9zτ(ιΫΖgΉHZŸοβΈΛ D’κmADVU/ζΥ§ξ#―Ϊ_ZPαk›†WΗVΠ‚σΚs‡Jί6i˜φψΟ|vœ΄ώˆ@£AΒ€…›wXB Rζη»Έn‘dˆΤ'α$,@ZΈyGΥΣ–¬š3ηΉα†ΚργΗKί6aΛ DΜ€ŸοβΈέ‡ͺ_τξymεχω{FI_›,΅‡‹Ϋ’Q3ή™"}m³Π‚—™.5`[yωΕ‡Kί6ištόy¨:@sΒ!HX€΄pσ‘Xˆˆ€I8 nήQυ@Δυ¬³Ξ’›oΎΉτ΅ ›4q-υσ]άχ…ŸL—φπKξ?EώO»Υ*ώ}ςΦdιk[I―Έπ0yέή}€―M-yω?•ΧνίOϊΪhΒ!HX€΄pσG‘ζˆ€#@sΒ!HX€΄pσŽŠ"/½τ’:t¨|μ±GεβΕΛΉsηΘnέΊΙaΔΎ}…ˆdυω.Ύ"wΑ«O,―œx τ΅©%ν‘εΏΪ«Όθν)Χ6Ž7τέJ^σΣ]₯―MΑ‹^š ―΅—œωδ™ςΗ3?C^Ώ[/y՘}€o_΅δ΅Gμ"/Ώl˜τ΅)Π(„C°ycλ­·–W^y₯€ΩtΣMε 7ά ‘‰ώσŸςΠC•mΫΆ•?ϊя$4η_ϊ—<βˆ#€ΧK,ΡΜε—_^Bcΰζ""^ D•@ 9α$,@ή Hˆ‘ nήQ±@δΛ/ΏW_}•μή½»lΥͺ•μΤ©“1b„\Έp‘tχ3kΦνΘνΪ΅“Ά]ZŸοκβ+rœ9χ4yύφ[I{HΈ―mUύ.x°‡ΐGyνα;KοΎBΖ Dl‰±Λ~{ΌόΥή}ε―»o"m?W1DΞψΰ|ιέW xΡk“δ―{l&£–hΒ!HX€ΌQ끁 dIZσ«Q‘¨ρ³|£6’Ÿ}φ™?³fΝ’ΕΖλΙ'Ÿ”"…›w F B –@$U Dό„C°y#­‚pVΤz ί€5ΏDD€@|ΈyGǎeΝ\ΪίI.γǏ—;w–Ο<σŒόΰƒδ€δφΫo/]N<ρDiAΝάΉseΦΈyHB]|EnΔΈΤ+"P"D²!n!½Ϊδ₯ŸΥ"ξψˆψ!) nήA ’P_‘1υ ”CZΘ /Ό O9εΉΦZkΙ.]ΊΘ±cΗΚ7ί|SΊ|ώωηrδΘ‘Ά[i₯•€ώώχΏKcαΒ…ςΐ”«―ΎΊ\c5䑇*?ωδιb†έwί]ΈβŠ;sζLΉΔKH+p”J΅ŽΟ  6ώvΎΫΆm+ν|ωε—ϊ·φΪkΛφνΫKŸ·ί~[–Šυc̘1r»νΆ“6ήέ»w—<ςˆt‰ D:uκ$ο½χ^ιςή{οI;Ÿ~ϊ©4,X ­ΠδΞƒ‹.ΊH›Qύ³γ?ύτΣeΏ~ύ€}Ξl τ§?I—3fH›7ΆtŠγSO=%γ²ώϋK;W;ΓΞΏ½Ώδ’KJλπώϋίJ—rΟO©ύLϊ}9χάsεΊλ+]нoO;.vή­ίoΌρ†4{μ1Ω];ω―ύKvœξό*u|’ΞΓrIϊύLΪοbγηΞkW[JΛ¨ΤυΨΪύ⿐φ=oΣ¦΄λ’Ν›σΟ?_Ϊ8Ϋ<:ꨣd±Β{©Δ―¨@ΔέO©Χ“€Χλr―§6ήΆ4V±ΏgŠρΟώSξ±Ης’K.‘.vν8\^|ρEiΗχςΛ/KΓώ³’C‡r½υΦ“γƍ“ξu()nήaŸO R¦.Ύ"7b\κ(+Θˆ4hάΒ Hœ[TμψΛ-θˆ4οŸιφ3ιχ…@„@$,HsβŽˆ§A\μΖΤ³.Ύ"7b\κ(+ΘΔ D>ϊξ!žΣ§O—VΘ^e•U€-‘ρΠCΙb —AƒI+HΨV»όςΛε]wέ% λn»ν&ί}ωξ»οJ+œΩϋ.½{χ–ϋ쳏΄‚—=,uΛ-·”Ε +q©ΦρYaΝ "sζΜ‘φΠVcπΰΑ LVθ± gΤ¨QΞw©6λΗΚ+―,ς—ΏHΫΏ-₯f…ΌE‹I£XAΣ°RΉΧ^½zΙ8@Ϊη[Α¨G²Ψ<ˆκŸΏM?ώΈόκ«―δ„ €Vν{σΚ+―Θe—]VZ`τΝ7ίΘG}TΪΓwK%ξRK.6ž~ϊii…ΆoΌQΊ$=?qϋ™τϋRn ς·ΏύM.΅ΤRςwή‘FϞ=εϊλ―/νϋnΨω·λ„KΤόŠ;>εΞΓ€$=Iϋ5~Ηwœ,Ά”Q©λ±΅³‚½ύ}gΑυG!-°ΰΓ‚˜W_}UΪηάrΛ-2-’Ζ+*q)υzRξυ:ιυΤώ.rƒ7ϋ=³@¦U«V‚3›6.~ψ‘\gu€±xρbiύΆώΓ‚œ›oΎYΓΖχό£<δC€Νϋ»ΔKξχ/.nήA ’P_‘1υ ”ƒxDDDDβbσ‡@€ ‘–Izώ“φ;jόDJƒ@„@Δ‡›wˆ$ΤΕWδFDŒ#@=C •ΐŽn7μ‡~Έ΄BM©XαΠφχΪk―Ι(¬πaΫ½υΦ[εωηŸ—ΦΞ–Θ²ΐΓ^· ΔΕ oνάBxΥ:>Γ kV0tq ‘Vΰs±Δ‹ηž{NΖΕϊaKfΓ JnΑ8ͺ YnΑΥΞ‡½^μόήύ²X»¨ώΩρ_pΑΕ κΆ[Ζ‚)[*§Τq"n!= [‚Ζ–prIZκgZί—€X€zυΥWK όlι9{}ί}χ•†=ΉΨ9Qσ+ξy,w&%ιωOΪο¨ρ‹*πWκzlX»iΣ¦I+ΐΫRSξR‹ΖA$O=υT™i".Ε'I―Χε^O-x³@Ξ°%°,ˆ³ΰΙͺnΓ2Λ,#m\ ΌΎψβ iύ³~ΫXΕ°‡Ί›ΧQΨΈΨ^φΉξRqqqσ‘„ΊψŠœˆˆq¨gD ˆψ 0Ε iΒϊA B RNA<ͺŸi}_’B β'ιωOΪο¨ρ#) ‘&Dšγζ" uρ9γΠH„C°Iψθ»%³¬P³Ωf›I[2λ裏–?ό°ŒZrεΑ”K/½΄Œjo̞=[Z‘‘Ά†έθΫR+Ά½FŠa…/Ϋή 7άpƒ΄Χ]­ W­γ3¬°vύυΧK[Ϊ,άχ8ήyη2.֏¨Β=lχŒ3ΐFTA³ά‚«³=ΤΈΕζΥ?;~›7.ξy΄ΒŸaγ½Λ.»H+€Ϋ9Ο<σŒ,•Έ…t+τΩ’iφ½±ώšΆ”K‚xT?ΣϊΎ$Ε ΟΆTΞwά!wέuWiKεΨυ‚d++€FΝ―Έη1ι<,—€η?iΏ£Ζ/ͺΐŸΦό²γ(v=6’ŽΧ–RŠϊύ6l˜<α„dZ$ DΚ½žΨyHz½.υzjaƒ-}gX€±ΦZkΙblΈα†ΖΕ,{(Ώώυ/™υ’YΆΤ—=όί–Μ²qΎμ²Λ€ϋύ‹‹›wˆ$ΤΕWδDDŒ#@#AΒ$@„@€ ”βbύ(V4DšφοtK-ΰΕΕφUH'‰ˆŸ€η?iΏ£Ζ@€4Dš iŽ›wˆ$ΤΕWδ,Η―φ]QώcΟ€― bΉφ;ξ\ΩσΰIΧ¦š.΅τΩr‰%š{ξ[Σ₯o›z ‘‡ a²ΐ– 9ωδ“₯ΐlI[‚Α †¬·η.abϋq)Ά„Iά%³’–JŠ’ZΗgDΦlΏφ0h+Θ€υcμΨ±²ε.™eα΅B—ΛSO=%mœ¬ΰcηΓ^/v~£ζAT’ΞCTAΧΕ–0³ύΩRfΆ΄K\ΆΪj+Y¬ώΡw¨z³fΝ’ΆΔ‹|Σ§O—6.εž#ͺŸi}_’bKμ­Ήζš ΗξRO?ώρεψργ₯-}SŒ¨ω5>FΪσ0.IΟ~G_TΏRΧc#ͺ]^‘€Χ;―6Ύε^―]’§¦ύ=cόίύŸ\m΅Υδο~χ;iσΡ]2Λώ·-f/ΉΨίOΕ–Π³ΰԎοε—_–Ζόωσε/~ρ iΧ·οαΩgŸ-m^§…›wˆ$ΤΕWδ,GΜR‘Ϊ ‘‡ a²ΐ A"Ν©ΦρQ…5Ϋ/HΛη7jDυ/κϋL^qΕ FŸ>}€mo¨wί}WφλΧO0@ΊΨRC† ‘‹-’V(θΡ£‡Œ[X)F΅Ž/nn―½φ’φ9―ΌςŠ΄BΠOϋ¬4¬>hοΫυ±Qσ+ξψ”;“’τό'νwΤψEψJ]£Ϊε5IλzRξυ:ιυΤΞΏυΫ°Ώsli¬•VZIZvΫm7iKŒώς—Ώ”φw’‹₯;w–Ά„—-Ήgσ«oίΎεΔO”Ά„ιœ9sdΦΈy‡]ηDΚΤΕWδ,GΜR‘Ϊ ‘‡ a*Hsͺu|q p""ΎB:HsDΚ#ιωOΪο¨ρ#) nήaΧΉŠ"<ς°0`Wi›ιε‡rβΔ ·mΑ)S&K›8¦ύ“&ί6-ωΙ'‹εϊλ―/ν‚οkλΣε/ΏΩG~»Σ%yΫΓΗK+Œˆ`–ˆΤ¦D8 P‹X0pμ±ΗJ+Xέ /φ0RΓ Vx°₯+μa₯|°t ΨΖ‚ €¬ oK7͜9SΪ}q±ύDQ­γ‹[€³`bτθΡ²kΧ nV˜²‡D»Dή­φΠi ’¬^a…"{Θ»‹}~±‚¦Β,p²‡ΝΪD—^z©΄σθ\­ iΏΆyΠ­[7imωηŸK#ͺQη‘XAΧ–d™2eŠ΄%O¬ΰnϋ΅₯g\’ΞΛ#<"ν8mi;ΓŽί–‚ZnΉε€=dΨκ]ξvFσ·ŸIΏ/Ic§v’k¬±†΄₯€Œ»οΎ[ΪρF=dێ³ΨόŠ;>εΞΓ€$=Iϋ5~q‘J]£Ϊε51’^OΚ½^'½žZoίϋϋ!mμ!θ£F’«Ίͺ΄~ξΉηžς£ο– «άΌΓΞ#6"΅)@#AΒΤ"""""vόξω‰ΫΟ€ί‘‚Ε¨Τυ8ͺˆΗ‘C‡Κίώ.ΉpαGNάΚ+―,―ΉζjιΫGΨ[o½U–ˆŒu’΄‰œ4q œ}V³ΒJ±B΄LT―Φ±ΆΥS 6Ιϊz}ΥUWΙόΰoK‚Yπςϊλ―K["ΛκβΆe½αζ""Ψ€ˆΤ¦D8 ρ!I¨"ΥΑΝ;*ˆD9pΰξrψπαΧ&lΉˆ-έΥ½{wyέuΧΚZ DώΉΗςςΥ36“|zθκς¦'O”ξφW½~Ά|ντMεΧϋ΄‘_νΫVΎrΦζςΚ7Ο‘ξφWΎ1NΎl[π›½ΫΘ/χo/ŸΊΌδƒ)έώW/Œ‘vάτςέ_¬/ν8μύ»ώ4LΪφεφξU»ΙμΥZ.:ͺ“όzŸΆςΥ3»Λ Ζ΄ΰϋ?λ*/^xΎ΄ύ”λ°¦Κ5Φ;GvΨpΌ\sƒsδ qSdλ•ΗΙN’ξ~&Ύ>]nΎχ$iνΫw8GnΜΉςό/”ξφgόuš\ΏχΉ\λ³ε:[—›ο3QfˆtήlΌμ3β\iǿŠγ€}ώδw¦Kί> –ˆΨqΉ`Štίίυ”ΙrΣ=&JχύIoN—› œ([΅'mόw?mŠœΎψBιnοΪΎc{ΉρΞK_›‚υΜΌyσ€AΒ@|D‘Φ‘ίώφ·ςΆΫn“Ά„˜=ΜΦ–φ9ζ˜c$T‡ZΉ^?όσς°Γ“k­΅–΄%ΐliL{¨Ί-ΕUμaκyΗΝ;:vμψmΗνφ'!iΎ=Hyˆ4I \€, IH‘ΪΔΝ;φίʁΘgŸ}*ο»ο^idθΖ-}Ϋ„-5ωτΣΏΙM6ΩDήύςΧΏΎAΦZ bΫύΏϋ†ΛΫg-νυ7ΖόXΪv-Ί@.>’ƒ΄ ΐŠλŸoŽŽ[G^ψΙt9γ;_KZ;Ϋώφ‘ίξΌ€|iά2άχ‚Φήϊi>τ«Aς²w'Ι;!χΰ±2i-±Οϋυ3§HΫΟ‡Ηv‘wώi˜΄v·΄ΟΫκ€I‚„cg/—Yώl™u ²Ξ‘§ΜΉ@žσς4iύλ3ό\ιΫGΑj";8YΣc‚œŒ}Aλ.'M–c›&έν] DD²€@$j=YΌx±άύ₯ΥM¬ΐ5rδHωυΧ_K€Fΐ–²λ_\­@ ΅E½œOΧ΅‰›wˆˆˆˆ4ί>©"Ν% Θ‘t Θ"υd‰›wT-;vŒt'ςθΡ£€oŸ₯"§vš<ςΘ#€½^«ΘΏw[VΪλ—Ύ?YΪώ>:Ί³΄χχΠqήvj/iο›/³₯΄vΏš?VώφρŸK{ύωΙΫJw{ ¬έ₯L‘φΎˆΨ’Yα}ψLΪ7±%½,`±%Έn|ϊ$iνά%»ΚΥ+€Ϋλ< 8u²΄ΧWι|Ž<ωα 䴏/”K-sΆyχΪ›ϋN";n|Ž΄Χ­`oΒιOM“αm Z0“u bΑƒϋώ‘ΧO•νΦ'έχΝj"»œn―[ίφ·pDgiοί{ϋήλ¬Ώ-οΎϋ0i―?vω.φoΎ~Ϊ&Ϊ]ά©ήw‘·NήX†χα3iΛ DξΎηιλS)Z b…t{}ΫΓ'ɁgN–φϊjλœ#G=pt3žž&­½9μΧΑηΆYuœ΄ΧOzπi۟χώtήΆ`ο£Ξ•Y"ϋMŸ"έχOΌοΉδRgΛb'―V rή‚&mi¬.[N~<^φ?α\Yμ‘φε PΟˆ@₯qσ‘οή'!!IO‘ς¨gD ΈyGΥΧ³Ξ:KnΎωζΧ&lά@δͺ«”ξ]Q>τΠƒ·Ο‚.n³Θχ=ξύyν νύ(³Z2λΝS6–α}ψLΪά"χ_ “.™e_·‘V—Μ²q²‡Ο»ο›_Ÿ.νxμψ|mΓΪΓθOœ"έχ{9I DŠiύ±qίgΚιk[Žυ T7ο ‰@„@€ Dš$)O€z†@*›wT,yι₯εΠ‘Cεc=*/ώXΝ;GvλΦMv€τν+lά@$ΚzY2λβ…ηKϋœ―†΄“7=y’œωΡyς·Α_ΠΫ~ΖβirΡQδΧϋ΄‘φΠςί=x¬όοΞKΚ—Ηm!m{³ά@$iσˆΨλ›ν9QvλΧδ„W¦ΛΣηM“k?^Ίi7»φœ { $'Ώ}‘<ξŽσε²Λ“Y"+―uŽ<υΡ €Ά€•Ύ}„mίqœάoΪyrϊ'J_Ϋ‚}†Ÿ+Χέv‚΄‡’ž}l·Ζ9²X ²Σ¨sεaWO•6~gόuš\­kpή­?ξφν;Ά—οΌ±τ΅)ΠH„C°aώωΟΚC=TΆmΫVώθG?’yα_ϊ—<βˆ#€‡ϋδ-Ώός*G£ώN0@Z}½^qσ‘ο$iڞ@δϋTŠ"Mˆ4—@ΰ ‡ aΒˆ@Φˆˆ43.vγ ~ωεςκ«―’έ»w—­Z΅’φ°σ#FΘ… Jw?³fέ.έ ιZj°Q/ˆyυ+gΚWΞΪ\ώ}ΏφςφX^.ψYW9λέώͺΧΟ–―Ύ‰όfpkωχ!ΑΨ>w^/ι.•e–ˆ˜εφΏ^‘ ―N—έχš$[―4NΆ[³Ι>#Ξ•S?œ.m;σΜg§ΙυϋLΛ΅'-(Ωϊ I2λ@€ΘΙrυuΟ‘+¬8Nv“ycΦ¬Y²Ψq<ωδ“’@ ;Άήzkyε•WJ£Q§zθ!ΉΑΘώχΏ²ήpσ‘ο$iΎ=Hyˆ4I \€%‚„C iA Ε !if\μΖΤ³.Ύ"'b£iΘΠ™ηI_ό_‰p Μi§&?όp™WΞ8γ Yμ8D ?ώΈ4h\uΥU₯ύ‡¦?ωΙOδδΙ“εΧ_-σΒ.»μ"O8αYiΆΨb yν΅ΧΚΈ|σΝ7χλΖΡ–€―εwΪΤJ?’ΘK?‘4ύwΊK—.ςΟώ³¬7άΌƒ@$‘.Ύ"'b£I RžD8 †@ΰ‡@$[Κ-tˆ€C­τ#ŠΌτJƒ@€±‘Ž;J‘2uρ9M‘ςh$Β!HX€0ΗΌ΄₯•σJΤqˆ€Λ‰'ž(9ζ9wξ\Y+όη?‘χέwŸ<μ°Γ€.χάs΄ω1jΤ(ωΚ+―Θ―ΎϊJ>όσr̘1ςζ›o–y!―Hϋ쳏6l˜¬5j₯ΐ_+ύˆ"/ύΜ+ΥΊ~7ϊοτπαΓεΡG-λ 7ο°„@€L]|ENΔF“@€<‰p LT"/4z‘₯ˆˆ”CV…n‘xΤJ?’ΘK?σ Hu qΔΕn`|‘A=λβ+r"ζE{Xy©vθvŽ΄ύˆ”'@#AΒΨ}χέ₯oy™‚Ά”–Ρ©S'yο½χJ—χή{OΪφŸ~ϊ©46έtSyϊι§Λ~ύϊΙW\QΪΓFτ§?ΙΈΔ=ލB‹»Ÿ%—\RΪγǏ—Ε†Ί`Α9`ΐiΗe½θ’‹€νγ?–ΖŒ3€}^λΦ­εvΫm'Ÿzκ)Y+ΌπΒ κ:tλ­·ž7nœ|γ7dΦXN9εΉΦZkIΟ±cΗΚ7ί|Sv>­ΛeαΒ…ςΐ”«―ΎΊ\c5䑇*?ωδιςΑH›ξ<š9s¦,6’ˆ D’~O‹=T}ύχ—ΦoWΫ\’‘€ίοr―₯wωSŒRϋΡθγEλύ—_~)GŽ)Χ^{mΩΎ}{iγφΫoK—€ίΣJ_ΏέωδΪ(ΏΣ—]v™άl³Νd½αζ6ΏDΚΤΕWδDΜ‹Ύ°#Ž"ιΠH„C°β(Œr \FN1βHΊTΊ …υ‡@€eDš>―Τοwή ό₯φ£ΡΗ+Š€Χ{‘ζ6Κο4ˆΣ .vγ κY_‘1ŽυΜΌyσ€AΒ„9ξΈγd±%,Œr \†p¬πc―Ά₯ˆ&L˜ ­U¬ QŒ¨γˆ*΄Έόϋί–O?ύ΄΄Bэ7ή(]zυκ%8ΰΉhΡ"i₯=zH·ΠbK2-»μ²ς‘G‘φιG}TŽ=Z–Š-eŸ[ͺV¨ŠΒΖλό£<δC€œ¬`tωε—Kw~Δ壏>’Σ§O—έ»w—«¬²Š΄σΠCΙ¨y4ώ|iΗkγ].}ϋφ•»νΆ›|ύχε»οΎ+­piο»τξέ[Zί Ύ―ΏώΊάrΛ-₯υΧ-ΨE7)χ{jk71²Z )*q)υϋτϊχΈ“ΞŸ(ΚF―b”{½7,­0oAνηŸ.mΙ>»ΎΩ€FΪΏ§v~³Ύ~7ϊοτν·ί.νΌΤnήA ’P_‘1Žυ ”CTΒHZΰJ»€γθ…–bˆˆ„!i’Τοw½ψΛF―b”{½7DD ΦnήA ’P_‘£€ϊ†@Κ!ͺ@a$-pYη‚ ..ϋΫί€moK[Δ%νB‹‹-•aKΊ―½φš΄~»…/γώϋο—n;+„΅iΣF>χάs²^°γάc=€ά ΕΕ x?όpiKΠ”ΚμΩ³₯νΟ ©₯b5ΫΟ[o½%]μ‘μΦΞ–Θ²ΐΓ^· ΔΕoνl|γ7)χ{š—@Δ₯ΨχΫΘΊΐŸtώΔ%­ρo”ρrIz½wΫ @Ϊ΅k'έί…¬O λwZΧοF&qΔΕn`|‘A=λβ+ς!"b΄Pίˆ@9D(Œ€¬ 8^h©Uμ8 Dš(V %IH<F/—€Χ{χΈ DšC ’oάΌƒ@$‘.Ύ"""F υ ”CTΒHZΰ²Ξ 7ά ]lι Ϋή qIZhΉε–[€-Qb…λiKnVPoΫΆ­,†μl?nAζΞ;ο”V°Ά‚ΰG!ŸyζY«Ψ%φ_{˜±-Ήbγf•uηG\>ϊnΙ¬iΣ¦I{8­-™uτΡGΛ‡~XF-“Φ’Y6–YfY wžΫR7Ά½Ν»bDΝ£(β"ε~Ok5)χϋmd]ΰO:βwό/?φΉε^οm)?{=φϋ`€ύ{Z©λw£NΫψρPυοŒ‹έΐψBƒzΦΕWδCDΔh Ύ!rˆ*PI \ip\½ΠRmD’hm{›wňšGQΨό"!iiό/?φΉε^ο DD ˆ|g\μΖΤ³.Ύ"_=xζgΚ΅Ο^[.5|)Ήή€υ€o›q—Μ*uΉT;Ωj«­dTAΎTŠ"IΏίFλ_Τq'?q‰κγΥ2I―χΦΟ₯–ZJ.^ΌX–Jοi΅ίώ;=|ψpYμψσŽ›wˆ$ΤΕWδ« Dš$Ι‡"ωκ(‡¨…‘΄ΐ•΄€E£ZŠA B †@„@€₯~0^-“τzoύ$!ρήqσ‘„ΊψŠ|υ`ΟΛ{Κ^Wυ’ΣO“ΎΆυδΩoΪΐr€ΫcyˆδS¨oD ’ ΖΎϋξ+,­€υφΫoΛwάQZ!Α-p%-ΰDQn‘Ε δK.Ή€|ΰδ?ώρ9wξ\ΉφΪkΛbΐmΆΩFpΐrΡ’E J=zτv|VhωσŸ,nj#νΈνσ―»ξ:Ήμ²ΛΚrž6'žx’΄%ͺζΜ™#k+TΩ’=ΆΜδΙ“₯Λ=χά#WXayΚ)§ΘW_}UZλ…^cǎ•7ί|³4ϊτι#(­kkοΧ―Ÿ0`€t±₯^† "γΞ#ÁώύϋK—j"ƒ ’VˆύΧΏώ%]’ŽΓ₯X ’Φχ;ιυ/ξq'?QγՏF―r)χzoμ΅Χ^ϊύΚ+―H»Ξ<ρΔΪΩψIΏ§ΥΊ~7ϊοτ:λ¬#mi2—sΟ=W»ξΊ2oΈyHB]|EΎz@$ΈΰˆδF‘| υ ”CTΒHZΰJZΐ‰’Ρ -•†@„@€ ϋ=΅οHu όQγՏF―r)χzoˆˆˆΖΕn`|‘AΨGyX°«΄‡ΖtιςC9qβιΫΆΰ”)“₯MΣώi’o›°ξ.έν]_yεeιΫGX_‘―μ|vgyΔCGH_›z”@$Ÿˆ€γ±³Ž•ν;Ά—Ύ6i E8 »α;πΐεj«­ΦΜύφΫO.X°@ΊΨC:G-m»Φ­[K»Ρθ»₯’°%¬bχύλ_%”GTΒ°‚Aοή½₯ΗψΗςK/•v^άWNεZŒ©S§Κ5Χ\S.·άr²gϞξη‹Z¬·λΑίɁφ0ΪnέΊIΫΏίηŸ.οώON™2EΪ’%­Z΅’6nΆDd‹=ty=φφ°v;?ωΙO€――ΏώZ~ψ‘΄‚›]χV_}uyπΑK·@jΨυΤ Έ66Ϊh#9sζLiσΘέOTAΌΪΘ#<"ν{aΕvΏWQΗαR,1’~Ώ“^βwω5nqϋΡ(γU.ε^ο [κΙώ>κΪ΅«΄‡„ΫqήqΗ%ιχ΄Z4κοτΓ?,Χ_}i½‹TφφΌαζv>D DšK Μ ‘άH ’Ž"%α$l\μš@€Ύ‰*PI \Yp΅ΠιB B —ΤΈΕνG£ŒWΉ”{½7DDDγb70ΎΠ μΠ‘Cεο—\Έπ#9{φlΉςΚ+ΛkΉZϊφφΦ[o•₯"gœq†τ΅)E_‘―\νΤΰΒxԜ£€―M=J ’O D‘@²$‚„‹-©pϋν·K+XΨCAwΫm7ΉέvΫI—ργΗΛΝ;ΛgžyFΪ’VπΫ~ϋνeΣ¦M“VΠ³VΘwί}·΄ϋq€r°°].τ@rΈή瓬Λύ½|Λ-·ΘbXπmgη 7ο ρ΄)E_‘―$!Ι“"ιH YAΒΖ…@ =(AˆΤ>\οσIVη@€BH”X >\ϊΪ„%ΙΖu&¬#­_Μυ&­'έν'Ύ7Qn~ρζ²υΘΦ²ύ‰νεφΏ n,Ο_tΎt·77Ύ`cΩγ²rέIλΚeŽ^FZ?Žxπi۝ωΖ™²ϋΕέe«Ÿ΅’mήVΪηG=>―Θ:[η/pǟο(ΧιόοΐeWXVnΠw9ιΝI·rvΓ0ΉΖzkΘvkn°¦4nl½r0{œΧ@ίΎ’X,™ϊΑTΩm‡nr‹![Θi‹‚yήGX *°$=g>ΜΐωΨͺ}0ΫΜΐν ζഏƒγ΄νN™sŠ΄˜(ϋΧO†?;‰ΠX„C°iaA‰=„Ψ₯S§Nς’‹.’./Ύψ’΄ί½—_~YΊΨλφ0Jw;¨~ϋΫίΚΫn»MΪ’(ΪR1ΗsŒ(€κΓυ>Ÿpή²ΕΝ;DαΌe‹›wT=ωμ³Oε}χέ+νŸώάxγ―₯o›°ε"νΫ·—φ0{H=΄έ·­O_‘―\ν”Υdά%³Ί_Τ]n0y9ώέρς΄WO“kŒYCΈe€τν£ "Λ½¬φΠ0yήΒσ€o›‚;ί΄³΄‡ΐO]4UΊŸΏΟ]ϋHί> ζ=Y­kpήΗ<6FŽ%8ΊuΟ(}ϋ(G DV\}E9ιI²ΛV]δ&7‘֏e—Ξkΰ„W'Hί>ΛΡ D&Ώ3Yvέ&ψžφ:’—œΎxΊτν#l΅‘rΟίΞ£ƒωxΔ―‚ωhAΠiOσ?Π«}¦σ?ΠέήdΙ,Θ»pMΚϋοΏ/ $χίi,^ΌXZΑξΡG•Ε°‡­ή|σΝ°‡²ΫΓ1νa•nA@j›χφ}°ϋξ΅ΦZKŽ9RΊα(€ςyλ­·€}βzΨa‡Iƒλ}>αΌe‹›wˆˆΔ’@$ψ‘!‰”@$ D °ϋΧ€ˆό/Z ˆ”HcΓyΛ7ο¨Z 2vμι~‘G%}Ϋψ,5q]΄h‘Όι¦›€έπ\~ωe·MX_‘―ŒˆΨTK _JŽ|*ψΒΊνφ½{_ΩρτŽ}ί΄@dΫ+·•Ύ6εΈλΝ»ΚMgl*}m ζ=pκιΎί„ώrΛύΆ”ξϋεjˆ-ρd―χ<Έ§tϋ³JηUδΙŸ,νυ€Z bύθά½³ά|οΝ₯o›Z2λσgγ³ι `ώϊΪ$€, ‡ aKεΪk―•ξ}Ε&›l",X 7ί|SZ;[βͺ?ψΑδ•W^) &H»q5Dj7ο !‰%H0? D"%IGhΒ!HΨR!€bΈyGΥΣ–Μš3ηΉα†ΚργΗKί6a“"Γ†)wί}7ιkΦΕWδ«γ"ηΌsŽ΄ΰŒΧΐn»a“mNh#έχM Dή6PϊΪψ΄~vΧY.μςϊen4u#ιΫGΑΌ"C."έχΏ/ˆο±©tί/W DΦ롞΄Χ·=|[ι.ρ΄Ϊ:ΑΌ υΐ(i―'ΥŽΟ Vψo³j0ίΗΝ'}ΫΦ‚IΟίQ7σ?Π‚ εΫσ?ΠΖΓά¨0ένMH“yσζI#‚„-—ώχΏςƒ>ΗόŽώπ‡?”_}υ•΄% μχ°Τ%³ζϟ/ν‘μ‹-’@νΰζ"Ž"~ DšΪˆ΄,H:ˆ@=B •ΖΝ;:vμ(«ˆΈžuΦYrσΝ7—Ύ6aΣD~ϊΣaΎξkΦΕWδ«γ"Y-™5πw₯―MΨσ>:O.}t0‡ώy¨΄Χ­έN7ν$»ΧM†χvβ{₯φpx_[ŸI·/Χά"χ’φzRνψΊυ Ξo ½ΎυA[Λu·]WNϋ8˜―αmkΑrΟίy ‚yΈτrΑόzI0νuk·Σ¨`ώvΫ!Ÿ@{έυΈ;Ž“ν;΄—Ύ6i υMցˆ‹-•eΑΔ³Ο>+ 4.Ίθ"ιbKiΩφ/Ώό²Όα†€½ΧQ£‚Ώw rΈy‡ε "ίI β—@$Έ‘%‰”@$ D !!¨4nήQ±@δ₯—^”C‡•=φ¨\Όψc9wξΩ­[7iKWωφ6n ςζ›oΘC9X>υΤσΜ3–Ό0 ψ;5°oίΎ2.,™ξίό±€Κγζ""±$ijO ²"ιH υ4 ξί"ΥΓΝ;*ˆ|ω傆ξέ»ΛV­ZIϋ'λ#FŒ .”ξ~fΝΊ]Ϊ₯˜νΪ΅“ξφφOβνανφωφΏ/ΌπBιnWL_‘―,5±€ϋEΑylύ³Φ²έ/‚σΨηΊ>rκ’©·‚₯"ζ?7ȁD,{τ²~Χχ“q‘αs‡Λ•F―$m ¬ΎΧ7ȁΎmΒ&έΎT Dόˆyƒ'ΙeWζE =<άmgζ%1m;λχ²ΛΗhHΏγ‚ωˆ˜}ζi`땃οq ]gm?ΎmΒΎξκςG»ώHϊΪ€ϊ&­@ΔΈσΞ;eϞ=₯ύ]oI΄ΐδ₯—^’.¬ΨRV«Ίͺ΄ύμΉηžς£>’q!(ΞΦ[o-―ΌςJ P―ˆ@~ͺ‹›wˆ|χω"-K B G‘t$€z„@(@£@ aψύ«.nήQ±@€^uρωΡ‰―M”Ά„Χρw/}m @}“v -YfK%ίtΣM²ώ²<ώψγrΠ A ~ς“ŸΘΙ“'Λ―ΏώZζ…]vΩEžpΒ ²l±ΕςΪk―•q±%σ¬πXͺΆw΅(χΈΣ¦VϊE^ϊ Ν©΅λyΦ$ Dψύ«,όώU‡J]ΟέΌƒ@$‘.Ύ""b#J aD (U BΥ‘R‘(j₯Qδ₯ŸΠœZ»žg Ώ₯PξuίΏxΈyHB]|E>DΔFτΘ돔λτXGϊΪ„€Ζ"‚„“UAθ?ωΌοΎϋδa‡&­γrΟ=χΘε—_^ΪRk―ΌςŠόκ«―δσΟ?/nj#oΎωf™ςZŠbŸ}φ‘Γ† “΅F₯ BQΤJ?’ΘK?σΚ‰'ž(9ζ9wξ\™”Z+πgM­"όώωαχ―:Tκzξζ" uρωQh‰p ‘ΚBA¨:Tͺ E­τ#ŠΌτ3―ˆ€Ώ₯ΥuίΏ&άΌƒ@$‘.Ύ"""F E8 &­‚Π /Ό O9εΉΦZkΙ.]ΊΘ±cΗΚ7ί|Sύο₯΅³aΉ,\ΈPxΰrυΥW—k¬±†<τΠCε'Ÿ|"]>ψΰΉϋξ»ΛW\Qn΄ΡFrζΜ™²ά\TAhΣM7•§Ÿ~ΊμΧ―Ÿ΄~l°ΑςOϊ“t)φPΩύχί_ZΏ]m»r‰*ΩxΪηΩ’―vήǏ/m>ΈtκΤIή{ο½ε½χή“ΆO?ύT–zάIηO1JνG£W , ξχτ’‹.’Φoχ{ϊε—_Κ‘#GΚ΅Χ^[Άoί^ΪψΏύφΫ%ιχΤ—V'μΠ‘ƒ\o½υδΈqγδoΌ!γ’v?ιϊθ#9}ϊtΩ½{wΉΚ*«Θ#FΘ‡zH»Α7ζϟ/νύΡG•εbΗ³Ϋn»Ιχί_Ύϋξ» ,φΎKοή½₯8¬@πϊλ―Λ-·άRZ³*YΦ²kK¦L˜0AZΛ_+pΈ!£V– ωχΏ-Ÿ~ϊii…ΰoΌQΊ”[2βwωEΉγί¨γUŒ^½zΙ8@.Z΄HZ€Π£GiΗη~O,-P±BυηŸ.mΙ"»ΎΩHFο©‹ί?ώρςC‘Vήn»νδε—_.έσeΨωHZΰ/F©σ0ι8e}=.uΌψύγχΟ‡W½ώώΕΕΝ;Dκβ+ς!"b΄ΠX„C°aμ˜‚P„Κ£ή BqηOεŽ£ŽW1DDΈ—:^όώρϋηΓΖ‹@€yήA ’P_‘±ΡύΝηΏ‘φΏΓ!HX€$ΨΓaνΖϋπΓ—ΆM©Μž=[Ϊώ¬pS*V΅ύΌυΦ[ΕJkνl‰+ψΨλVr±‡δZ»¬ B\ptωΫίώ&νσmι #/!—3fH[βΓ%λ‚Pω—΄ΖΏQΖΛε΅Χ^“ΆΏbίΏϋοΏ_Ίνάγ.Vπ³€]»vςΉηž“Fοi\¬ί{챇΄ύvΪi²ΪDΝΓrΗ©RΧγRαχί?ςϋ…›wˆ$Τ%|Σ‡ˆˆˆˆˆMˆ@%  DAȁH<F/‘¦ύˆ4‘τz\*όώρϋηƒ@€ 7ο I¨Kψ¦›$JπΡwK†L›6MnΆΩf– 9ϊθ£εΓ?,+΅dˆ––YfYŒoΎωFΪηΩ’Ά}›6md1¬P`ΫgUΊα†€‹Ϋ+΅ZΊε–[€-1cγlΗaΪRH.Y„’ΞŸΈΔΖˏ}nΫΆme1Š}Om)#{=wήy§4’~O]l {X΄=όΪ–Μ²σ|Ωe—Iχ|eEyXξ8ΩyΆΟ+Fλq©πϋΗFωύ‹ΒΝ;DκΎιCDDDDΔ& D P’ δƒ@$qǟρςcŸK B R ιυΈTψύγχρHnήA ’P—πM_=Ίι ΰ8tζPιkƒιΉύ1ΫΛcH_›F΄ίqύdΟƒ{J_›$ξzΚrγ7–Ύ6(ίtdώb5ΝΛόγχΟoή―£%ν‡C°Y`Kqœ|ςΙnΰ»tι"m‰+¨V0²vΗwœ,wΙ‡wήyGΊ$]2€ΨRόsiΨ’5£G–]»v•φ°c;Ξ;ξΈCΊ$ύžζ…€σ0ι8%½η ~ψύ χΓ¨φυ<.nήaΗE B ’D«+‘ζζ½ ”7ωώ§+σ«iήζΏΝΝϋυƒ@κ B„Βύ0ςRΰ·Έύh”ρ*‘ʐt&§€ΧγΌΑοΏα~ΥΎžΗΕΝ;μΈ*ˆ :TώώχwΙ… ?’³gΟ–+―Ό²Όζš«₯oao½υV7™<ω\iΊηž?ΘE‹Κ«ΊRή}χο₯oa]Β7}υΰτO¦ΛΦ+:πψ;—ΎΆ΅l{ΘΌTφ>woΩ΅gπ‡P ―M#™χ‚P^¬—ο­Ωhσ7οΧίz3oσίΏζζύϊA =V0°ΒC±ΒT»οΎ[Zύ ’Γο΄„›wˆˆ΄(HmHA¨Ήy/εE‘ll΄ωK R[ζmώρϋΧάΌ_?D²‡‚@νC >όώAKΈyGΕ‘(ά]>\ϊΪ„-5Yk­΅δ΅Χ^#}mJΡ%|ΣWŽ}b¬΄ Κδw&K_Ϋ°λl½Žάρη;Κuz;pΩ–•τέ@Nzs’τν#M+UvΓ0ΉΖzkΘvkn°¦4n΄³υΛ·―°#0R.³ό2rΪΗΣ€―mΣκΏ=όvσ½7—ΦΎ}‡φrϋcΆ—ηxΎt·?γ―gΘυ{―/—k½œ΄y΅ω>Α~+]šϊΑTΩm‡nr‹![Θz}ΘxήΎΜί&kmώΪ8ηυϊWζ_“iΟ?~κλϊA =„ͺΟoϋ[yΫm·I[λ™gž‘Ά”Μ1Η# 9όώAKΈyˆ§M)Ί„oϊκA‘L« βJAˆ@€ˆ0ΣΠΖ™@„ωWΞόγχ@Jƒ‚@υ!¨<όώAKΈyGΥ‘Ο>ϋTήwί½ώΙΰ7ώZϊΆ 7yλ­7₯}1μ‘κ;v”νΫ7ͺƒ–oΏύ–τν+¬Kψ¦―<ξŽγ€"|m|ڍϋj]W“c#ΗΏ2^vθΦA'°Νͺm€½~ƒ'IΫώΌχΟ“αm φ>ͺ·ΜΊ dύΨtP0O­Ώγ揓ΎmλΙΌ}™ΏMΦΪόΝϋυ7ΜΏ&Ӟόώ5ί>οΧ¨4nήA β΄#i.Hi&-¨Ψλ„šoŸχ‚P^$aώ¦!σ/Ιόγχ―ωφyΏ~ˆ@₯qσŽͺ"gu–ά|σΝ₯―MΨΈΘ—_~!W\qEω›ίά(έvΧ^{\sΝ5₯ϋΎ«Kψ¦―œώΙtΩzεΦςψ;—ΎΆa DJ,¨ά?JΪλ{Oή[ΪΈϊΪ€aώ[‘ͺά%Cμα³Vˆ©φ’!έϊu“φϊΦm-Χέv]™vaΞζ§\ΣZrΘ5oίζo“ΥšΏΕΜϋυ7ΜΏ&Ӟόώ5ί>οΧ¨4nήA β΄#i.Hi&-¨Ψλ„šoŸχ‚P1m~ΪρΗ•@€Iζo“ΥšΏΕ$aώ,wώρϋΧ|ϋΌ_?D ΈyGΕ‘—^zQ:T>φΨ£rρβεάΉsd·nΑ Xΰ°aGJίΎΒΖ DΜΓ?Lφ豕,φPυƒ:HϊφΦ%|ΣWOڍ°= ΩΧ&l΅ ’ΕΜ{An£ώΙ½&ξ%}m0­ώoΆηf *^™ OŸwΊ\sύ5₯ϋZ³kΟ²ΗΠΰΌΪRMφοe—_Vf]Ϊxη₯½~ή‚σδλ­!w½³ o[ζεϋΟόm²Φζ/σ―`ΉσίΏ|ŸΏφΫKہ䉭·ώώ ΌςΚ+₯KΤϋQόσŸ”‡z¨lΫΆ­όя~$+EγHΚ‡~(-ώψγ%@ZΈyH, Dβ™VAΕ•‚H5%aώ&‘@„ωW°άωΗο@΅ˆ ’ "Mˆ@ΦΈyGΕ[²κκ«―’έ»w—­Z΅’:u’#FŒ .”ξ~fΝΊ]ΪLΕlםt·πΓδ~ϋν'νΟ•W^YΪλο½χt·wu ίΦ“φΠΠ•:­$§-š&}m ΦZ R)Σ*¨˜ηΌtŽlΥ>ψžN|}’tΫ₯eZύŸπκΩ}―ΰ{Ψz₯ֲݚΑχ2°Οˆ>rκ‡S₯mgžωμ™rύ>λΛεZ-'­PdϊJ„L{ψν²+,+³Z²ͺVΜΛχŸωΫd£Ξί΄ΞΉ2šLkώρϋWΧ7±ί{?‚„¨’‚‚€A‚ύ‡}m΄‘όμ³ΟdΪd}I!€¬qσ‘Xζ₯ ZmΣ*¨˜„((Χ‚yωώ3›lΤω›Φω/Wζ_“iΝ?~DͺMΦAH"5nήQ±@€^u ίΦ£Άā(}m0=·?f{Yli ΔJΚχ+%Ώυ)䉬ƒ„ΣN;M~ψα²Z$=Ž€ˆ@ΦΈyHB]Β7}υ(ΡΚJAkIΎˆX)ωύ«O D ODIƒ‘&D kάΌƒ@$‘.α›>DDDDDl’@ςDTP4H8ώψγ₯-]-’GRD kάΌƒ@$‘.α›>DDDDDl’@ςDTP4H i‚@²ΖΝ;DκΎιCDDDDΔ& D >όs9rδHΩ₯KΉJ+ΙαΓ‡ΛΏύοΨ}χέ₯Ϊ—\rIiۏ?^ώχΏ•.QAAΉA‚Ϋ/W[JΛ¨φq|ωε—Ζν΅Χ–νΫ·—ΦΏ·ί~[Ί|πΑΪ­ΈβŠ&?sζLiΗG iγζ" u ίτ!""""b“"P""Ipσ‘„Ί„oϊ±I(‡AƒΙνΆΫNΟ?_~ϊι§ςςΛ/—wέu—,ΖΏύoωτΣOΛυΦ[Oήxγ%iΕqΗ'K]2«Η1xπ`9`ΐωζ›oJ ͺF ΎΧέ»w—ωΟ€Ρ»woΉΟ>ϋΘ… ΚΧ_]nΉε–’@²ΒΝ;DκΎιCDDDDΔ& D DšC PnήA ’P—πMV^Θα$,@wήyGZ‘ό΅Χ^“i1cΖ ΉώϋK—€ABε".YΗ{ο½'mόί}ιbH»vνδsΟ='-π°ν-qΉοΎϋ€΅#€΄qσ‘„ΊψŠτX9 „C°DβA Π2nήA ’P_‘+'δƒp ΐƒ>(—^ziYμ‘αΕΈε–[€-εΤ¦Mi…w³W―^₯ά !.q‘jΗC=$έΟ‰ςΞ;ο”³gΟ–ΦίbΌυΦ[Ά'€΄qσ‘„ΊψŠτX9 „C°Dš H†›wˆ$ΤΕW€Η ΏqΡ-ςβNOΚ™K=ΧdηΰτmSސΒ!HX€ε.™υΡGI Rf͚%Ώψβ iΑΚτιΣ₯.Ε‚#κύ(’‘j‡RK-%/^,γwΙ¬ϋοΏ_Z;H7ο I¨‹―H"Мp @ΈyHB]|Eϊ†φΓ‹δΜVΟΚ‹7xL^ΈpF“Ύmω ‚„3pΰ@Ω»woωβ‹/ΚΟ>ϋL^qΕς»ξ’ΆΣ’K.)xΰωόCΝ;W½φΪ—bAυ~QH­Η^{ν%ν<ΌςΚ+ς«―Ύ’O<ρ„΄vΦ?Γ–ς2dˆ\΄h‘|γ7d=d±@dΨ°a²ώ TάΌƒ@$‘.Ύ"}CK Β!HX€0"""7ο¨x ςΘ#Λv•mΫΆ•]ΊόPNœ8AϊΆ-8eΚdi0™φO‰}Ϋœ?Ύt·+ζζ›o.}ϋ λb…ω™Λ?ΫδΟ7Ήd“·ϋk“}”3ξΏF†‹ϊυ䌧/—6νϊ€τ΅MCΘα$,@ >Ž=φXΩΉsgΉΚ*«H ώώχΏKcκΤ©rΝ5Χ”Λ-·œμΩ³§΄ϋ_ \’‚‚¨χ£ˆ DŒj‡-Ρ5zτhΩ΅kWiK·νοΈγι²`Α9`ΐΉβŠ+ʍ6ΪHΜ9SΪ}8€›wΨίO"Ž"ιH >Β!HX€0"""7ο°ΏŸ*ˆ :TώώχwΙ… ?’³gΟ–+―Ό²Όζš«₯oao½υVˆΔuΛ-·“&M”Ύ6a]¬0} ²ϊSςΒΕ3δŒ–3[?#/^sžΌπƒ‹š χλΑs”ˆ\ΌΫ_€―m@m2oή\ϊΪ„M+±₯Ό–_~yωΞ;oK_Ϋ°.V˜Ÿ@$T΄/xρ³₯”|ίζρ+δχAmς»₯Άlι­ο·ΏαFωύφ/ώR^4θ>9s•§εΕηΙ‹†έ#/|οβ&m»”Ά·vΦΏ’v~RΊΫ—+Τ&"PiάΌƒ@δ; DΎΫ.₯ν­υ―¨" T7ο¨z ςΩgŸΚϋξ»WΪ’Y7ήψkιΫ&lZΘa‡*‡ "}m|ΊXa>2ιχ ΄` *ωΎέ9·Λ ίΈDΞΈε†&gύJΪ\o:WZaϋ›qϋυς~ѐ{εχŸ›t{G–Μ€"PiάΌƒ@δ; DΎϋ\Θ¨4nήQ΅@dμΨ1r‰%–hζθΡ£€oŸI‘χί_ [·n-οΉηΧΦ§‹ζ'ω$x½ΰμ«εΜ6ΟΘ’U.€ψ>HψnΙ¬οί/βŒ?_#Ώίξ°?I·έΕ[Ξ‘ΦnΖ»3›LΈ½ΫŽ@ ˆ@₯qσI YB •ΖΝ;ͺˆ˜Άd֜9Θ 7άPŽ?^ϊΆ ›49οΌ)rύυΧ—Ύ6-ιb…ωο‘ο‚€ο]ρ―ςβήΙχ_#ΓE}ι";Ν–ΣΞqΖ5Ώ‘ΆέE'ί)έv|@Z» ½R&έήmG D Έyˆ$€,!€JγζUD\Ο:λ,Ήωζ›K_›°I‘ 6Ψ@Nš4QϊΪ΄€‹ζΏDlΙ¬PΡ>–N rΡΞ‘ήΆ!Y2 ς@8 nήA B " D ’„C°iαζ D^zιE9tθPωΨcΚΕ‹?–sηΞ‘έΊu“Γ†)}ϋ [n rχέΏ—Λ-·œ|睷₯―mKΊXaΎZΘ…7yρOζ6ΉκSrΖW49λWrζRΟΙ‹χ½O¦Ά½cβ@ΔWoΫ@Θα$,€Ο?ωOy葇ʢmΫΚύθG²Rl½υΦςΚ+―”q`ώ6ρα‡Κ%–XB~όρΗZΖΝ;DDD β„C°>”!Ο0› (7οθΨ±£Μ<ωςΛ/δΥW_%»wο.[΅j%;uκ$GŒ!.\(έύ̚u»΄€bΆkΧNΊΫ›{ν΅—άwί}₯―M]¬0_΅@Δ|α—ς’=ξ—3W~Z^ΌζΌ&ψ£,ΆΤUβνΏ“@|„C°υL΅ ͺφn΄ΡFς³Ο>“iu|Υ:~Θ7Μί&DΚΓΝ;,!ρ΄‰£‹ζ Dš$α$,@=S­‚*eΘ3Μί&DΚΓΝ;*ˆΤ«.Ύ"=VNΘα$,46ί|σ Ηn₯hK)Wš-ΆΨB^{ν΅²Φ8ν΄Σδα‡.«E΅ Κ΅B­Ο£VϊΙόm‚@ <άΌƒ@$‘.Ύ"=VNΘα$,46"Ω@AΉΆ¨υωbΤJ?™ΏMˆ”‡›wˆ$ΤΕW€ΗΚ ω ‚„h‰}φΩG6LΦ ΅^ΰ>ώψγ₯-Q]-Dš¨υωbΤJ?™ΏMˆ”‡›wˆ$ΤΕW€ΗΚ ω ‚„h ‘ς  \[Τϊ|1j₯ŸΜί&DΚΓΝ;Dκβ+cε€ΪdήΌy‡ aZ"*Ω}χέ₯ —\rIΩ₯K9~όxωίώWΊ|ώωηrδΘ‘Ά[i₯•δπαΓείώwΉώϋKϋψΰiνV\qEi“Ÿ9s¦΄γ#ˆ‡›wˆ$ΤΕW€ΗΚ ΅ €ˆI B 7ο I¨‹―H•jHƒ¨@Δείώ·|ϊι§εzλ­'oΌρFι2hΠ ΉέvΫΙωσηK+_~ωες»ξ’Fά₯…’ ͺε~~Ηwœ,uΙ‘RΗ/κψ’ήO+ιΠ‘ƒœ3gŽ΄γ0,  ί|σMiΤ¨Q£dχξέεώσi”ˆε.EUκωH:žqϋiΑΣn»ν&ί}ωξ»οΚ~ύϊI{ΏTς2“Ξ«ή½{K»ΞYΠτϊλ―Λ-·άRΪω"ˆ‡›wˆ$ΤΕW€ΗΚ ΅ €H\J―€σ—@ 6qσ‘„ΊψŠτˆˆˆY Pλˆ@”ˆΈΜ˜1CΪ’@Ζ;οΌ#­ΠψΪk―ΙΈΔ-+¨&ύό(Κ-(»?#ͺ`υ~ZΘ„ €‹»½ξ]¬Pέ];ωάsΟΙ΄ˆ;_’ˆ:Y"oΌρ†΄νίzλ-ιςόσΟKkgKCΕ₯Φηoye‡moAˆΛ}χέ'­@<άΌƒ@$‘.Ύ"""bΦΤ:""εA DΒuZĝ/QD‘ζd5“Ξ+€lqσ‘„ΊψŠTˆˆˆY Pλˆ@D"·άr‹΄%iΪ΄i#­€hφκΥK>ψ \zι₯e±‡.#n»XA5ιηG· \ξψŎψz?­@δϊλ―—.=τ KοΌσN™qηKσ‘u 2{φlΉΜ2ΛΘb|σΝ7>ηρΗ—q©υω›t^Ω8Z‹a“mO 7ο I¨‹―H…ˆˆ˜΅΅€Hyˆ4A ‘ζ”; Dj7ο I¨‹―HU°ίqύdΟƒ{J_ΔZσά·Ξ•α?Ϊ φ8°‡τmγs‹!ΑƒΞ$}mΒξzΚrγ7–Ύ6qμΌYgiύnί±½τ΅­EΣLf©σΧ¬τό¨uD Š"}τ‘΄@aΦ¬Yς‹/Ύ0LŸ>]ZaΣHΊdΥV[m%£ άΕ ͺΥ^2+ιψŎψzίz],€xκ©§€S±@δ†n.6ΞK-΅”\Όx±¬4Qσ%­σ‘t<£ϊι.™eγλ’υ’Y՞ΏIηUά%³ξΏ~iνDβαζ" uρ© ˆ`%©"΅!@:ˆ@ˆ”H6Ξ"Mˆ4Η^/uώ&W"Ωβζ" uρ©σͺ[?ϋ…³₯―mKV+1Gάόα˜χ@€άρΗd–ˆ˜•šy#‚„h‰bˆ-%³δ’KΚx@ώγsηΞ•k―½Ά΄Β¦Λΐeοή½ε‹/Ύ(?ϋμ3yΕWΘ»ξΊKƒ'ώ⿐ϊΧΏ€K±‚ͺQξηGUPNkό’Ž/κύ}χέWΒήzλ­2n ·o_iΜ{ο½+_|qΎάxγεΘ‘#₯oa]|Eͺjšχ‚(VW‘κJ B RŠy#‚„H 7ο !A,*Hu%!)E€ΌAΒ€…›wT<‰rΰΐέεπαΓ₯―MΨRϋ'›W^y…tίωΟOφp1χ}W+L 9TZ!ΣμypO.bω\gλuδŽ?ϊΈNΰ.»Β²rƒΎΘIoN’Άέ)sN‘ξη³ίqύdψ³ΓZAΊΗΠrέmΧ•Λ,ΏŒ΄ύqέΆ›ψϊDΉωή›ΛΦ+·–ν;΄—Ϋ³½<Γσeψ3 Ϊqm2pΩͺ}+iΫο~Ϊξrϊβιέ>©εŽR‡έ0L±ή²Γ†δš¬)$m<{œ—@ίΎ°Φ‘©L•έvθ&mΏΣM“α}„MZΆνάώdm©γŸΦχΜgΟ”έw—φύk»Z[iίίiγθnoߟ! ‘ξϋv~7έcSi―§Υ€ΧΧRη―+€Ÿp -άΌƒ@ΔyŸ@€ΉV&!)H B B B α$,@ZΈyGΥ‘Ο>ϋTήwί½–ΜΊρΖ_Kί6aK D~ϊΣarχέw“ Ό'_~ω%i»ψβ‹₯oa]|Eͺ‚VΈ+5Y­λjrΜccδψWΖΛέ:ȁg”Ύ}LΊδŒ€-°‚ύyοŸ'}ΫμΎWwiΑυϋ΄'O“Vπ0f€t·ίιĝ€^™ ΟyωΉΛI»Hwϋ€¦5ώ₯jγ»βκ+ΚIoL’]Άκ"- ²~,»|p^'ΌŒO oŸI¬•@dς;“eΧmΊΚ^Gτ’q±F D\ΛύώοK DށμΩ³§t?ύχ—ΤψφΦΕW€*Xn 2ΰΤ}Ώ ύε–ϋm)έχΝr Ц€·=l[ιkΦ–ΠYj™₯δΘ»GJ·έΎSχ•7ξ(έχw9yΉ^―υdΪKSE™Φψ—ͺ"Ωλ6oάώ¬yyςΓ'K{=-«ˆΨ8tξήYΪHΎmZ²Rι΄­V εχΖ M₯ϋΎ}*ˆ€uύq%H‡yσζI#‚„H 7ο q>Ÿ@€Ή"""Υ“@„@€j¨4nήQ΅@Δ΄ΰaΜGδ†n(Ǐ/}Ϋ„ˆ|ρΕηrΣM7•#FŒ|πΎ|ύυΧδ.»μ"χΫo?ιΫWX_‘ͺ`ΉH₯ Šˆ Χ ο6_ΖΝ'}Ϋϊ$)νΈΊι(iAΤςm–—Φs£ώIwϋj]ΏΊώΈˆ€T7ο !iQ‘κI B RŠ΅T7ο¨z βzΦYgΙΝ7ί\ϊΪ„ˆΜŸ?_Z‘μΙ'Ÿn»λ»VΆiΣFΊο»ΊψŠT«ˆwΗq²}‡φΧ¦%ΏDœB|1³Z²ΖœψϊDiΫ{¨sRΣR-;Ή”΄ΧӲځH·~έ€½ΎυA[Λu·]WΪ| oλ³Q‘RΏD.½\p= zΙPi―[»Fν$»νœŸΐπ> ΪΓΜO,έχ{ΩK¦}ύΚκϊC "PiάΌƒ@ΔiG \‘κI B RŠ΅T7ο¨X ςK/Κ‘C‡ΚΗ{T.^ό±œ;wŽμΦ­›6μHιΫWΨΈΘίώφ‰\i₯•€-™υα‡Θ7ήx]ξςέ’Y[oέCϊφΦΕW€*X­@dμc₯Ozθ$ιkλ³Τ@ΔάlΟΝ€΄'Ό2Až>οtΉζϊkΚb-·‚λaW&'Ώ=YžρΧ3δj]W“ϋMΫOΊΫ'•@€Ιj"6μu+Μ―±ήrηΡ;ΛπΆ>“€m©ΆnρCιk“…IΗΏΤο€7&Ι%—\RŽΈ%·@[šnδFJ (Š"}†χ‘\Mz3ΨoΰθΩ£e»5ΪΙ¬_I―?ΥDl;χϋΰ Pλˆ@₯q󑡁HσχγŽ©ˆ4iγλ€ DDβ\ΏDj¨4nήQ±@δΛ/ΏW_}•μή½»lΥͺ•μΤ©“΄ bαΒ…έΟ¬Y·K+³]»vέώώϋο—Ϋn»­΄₯±,(Ω}χέδ /Ό έν]]¬0΅JηU€―oaWh·‚ ΅ ¦]ο{t_ΩzεΦ>ί‚ί6­Wj 2αΥ ²ϋ^Αyl½RπΉνΦ ΞK`Ÿ}δΤ§Jwϋ3Ÿ=Svlhγ΄βκ+Κν~ΊΌ`αέ>©"MΦZ bžτΰIrΩ–•φπm·™΄ ½ϊΊ«Λνϊ#ιk“…i©ί›χ6^Λ.Œs  Ά]±@δ¬ηΞ’ ΉΫΫχ7«λWλ+@:ˆ@₯qσoAΡ΄HσχKΈˆ4iγ[¬L βo_ΜRΏ6οmΌDD€@*›wtμΨQfˆΤ«.Ύ"b^u ςf{Hί6>“”Λ΅σf₯υ»Τ‚τΔΧ&J[Bκψ;—ΎΆY˜Φψc2˝ΏIη_©δp -άΌcΨw9H™ΊψŠTˆy•@„@ D²"‚„H 7ο°„@€L]|E*ΔF·ZHRΌώHΉNu€― ΦΏy™Ώy#‚„H 7ο I¨‹―H…Ψθˆ`ž%Θ†p -άΌƒ@$‘.Ύ"""bΦδp -άΌƒ@$‘.Ύ"""bΦδp -άΌƒ@$‘.Ύ"""bΦδp -άΌƒ@$‘.Ύ"""bΦδp -άΌƒ@$‘.Ύ"""""ΦPΒ!HX€΄pσŽa"Ιtρέd#"""bν Υ!‚„H 7οθΨ±£$)SίM6""""ΦPζΝ›'p -άΌΓr‘2uρέd#"""bν •@*›wˆ$ΤΕw“υ㦃6•Cg•Ύ6X}w=eWΉρΞK_ΜήνΩ^3@ϊΪΤ²ηΎu\b‰%šΩγΐ·MϋΧOφ<Έ§τ΅ [jϋz³ΪΗίθγŸΤ-†l!3HϊΪψμΌYgiί»φΫK_Ϋ4„Κ@ •ΖΝ;Dκβ»ΙΖϊ‘@$ˆΤ†"~K-°7zAΎΪΗίθγŸTC •ΖΝ;Dκβ»ΙΖό;κQrε΅V–ΣM“ΎΆX} DjΓs^>GΆ^©΅œψϊDιk[‹ΊΘΩ/œ-}mK‘;6’ε"ζˆ[GH‘ϊ€@*›wˆ$ΤΕw“ω—@$_ˆΤ†"~ D°‘$0"PiάΌ£βΘ#<, ΨUΆmΫVvιςC9qβιΫΆΰ”)“₯¨Μ₯—^ZϊΆ ϋΤSσdίΎ}e›6mδk¬!nj9UϊΆυιβ»ΙΖς=vΦ±2λBH”[΄΅μBιkSπΜgΞ”6/Η<>FΊνŽΈξΉ\λε€ϋώΰ‰ƒexŽ\jι₯€ΫΎΦ<ύ©ΣεόXΆ^Ή΅\ι+Ιώ#ƒq œςξιΫG D’yήϋηΙ­φίJ.ίfyΩfΥΰzΈσθ₯o[Ÿοœ‡@›ΧΎ6΅(ζΩZωύ$0"PiάΌƒ@„@€¦%i>Ο DβI ’L‘& D0Οˆ”&T¨4nήQρ@dθΠ‘ςχΏΏK.\ψ‘œ={Ά\yε•ε5Χ\-}ϋ{λ­·Κ¨@δΛ/ΏnΈ‘6μHωα‡H j,ωε/)}ϋ λβ»ΙΖς­vAgϊ'Σ₯τΏσxιk[0­@Δυ¨›Ž’y D:tλ ·9t9αΥ –PΪgΚ>ς _$}ϋH"H2ϋ ο#Χά`Myζ³ΑΌ<ρώ₯-uΰΕJί>Βξ}ξή²kΟΧ¦%ΑLn΄γF‚Άύ¦ο'7ίgsyτοŽ–ΕΎ§iϋ}ψ]ΰqΐEH·]ί£ϋJϋ>»ο»ŽόΓHiίϋbΧ½bVjώΊ–ˆœρΧ3δϊ½Χ—φ=_gλu€ίbΘΠ™C₯}7@Izύ7mώύp‹ΚεΫ./;oΦYžpOπ{θΫΆ ―ΈΧΫάγvΓ0ΉΖzkΘvμ 7HΪοXƒ~ΊϋI:ώvžwόωŽrΑ\v…eε}7vžάνΛύϋ!­ίΟ΄~Mh‰p -άΌƒ@ΔiG $H“"₯I ²"""""ώvΕ$©oΒ!HX€΄pσŽͺ"Ÿ}φ©ΌοΎ{₯-™u㍿–ΎmΒ–ˆΌψβ|ιΆ³@€sηΞ}ίΥΕn¬ν‘ΓGόκi…ΨӞιυί–F[zΉΰw5pθ%C₯}NyδiΑŠ»½iη«άλΏχψm+Ύ’œτΖ$iηΓ~·ΖΏ2^.»|Π―ΐ¨ωXκψ[ ²ZΧΥ€³}-)8π́έ>ιίfΉΏŸiύώ›"Πvΰ nήA β΄#i2­‚H‚XΉ΄$)M‘ζˆ4iΧ=Ϋ/H\ Dκ»pH 7ο¨Z 2vμi…&sτθQ·ΟΈˆ=T}ƒ 6?ύιO₯ϋPυN:ΙUVYEϊφΦΕw“νΣ Ά›ΪTΊοοrς.r½^λΙbKk³άν'Ώ=YΪω°Β—ΫnτμΡr…v+Hχ}Σ bΫΆ­τ΅iΙr :i™4‰²RH₯΅šΫ­ΩNΪ’+6¬ΐζΫGνϋeαΞέ;ΛΝχή\ϊΆIC[ϊΚ –hXΐa…iίΆ-yϊS§ΛcH[Θφo…RίΆ₯hϋ±ωiΑˏόXZ‘ύπk—qΏξ~K Dͺe©ˆΦήΞ›Ϋξϋ‚rΜ{©ω€ΏVθήbί-€―M“^ΝΈΗoˆ}ονuΫnΐ©Αχ'Π^_₯sπ;xςΓ'K{έ΅Τρ·@Δύ<³ ύε–ϋm)έχ£ŒϊϋΑ,υχ3νί“@Z"‚„H 7ο !i&Hs DΚ“@„@$¬»_‘RŒ{ό"Ν%)M¨α$,@ZΈyGΥΣ–Μš3ηΉα†ΚργΗKί6aγ"ζO<.{υκ%Ϋ΄i-7Ϊh#9jΤ‰ruΊHί>º؍΅°­»|›ε₯̍ϊŸΎ)/xή‚σ€-meΛ.²Σ;I+¨œαω2­ν­0δφ3Κ)οN‘α>΄‚Ψΐ3Jχύ(«ˆόΟCΥΏ+ωΪt+(»ν*½dV­xϊΌΣ₯Νϋw ζG ―m­`hηΑ ‡ΆdΥΈωγ€oΫ$χŽ“ˆΨχΞ–Ά)79γι3δncw“ˆ¬½ωΪίΆ₯˜Υ’YIͺ^-K DNzπ$iν‹- Υϋ¨ή2n½Τ‚|ߏ ·~‡ν{δΎΧ€Χ3ξρ[ bA½nKΦΉKT­ΆΞjrΤ£€½ξZκψ[ 2δ‚!}ίΖuΣ=‚λR ϋ~ΏΜR?Σώύ7 D %Β!HX€΄pσ‘fΫˆ4—@$] DDDDJ5ξρˆ4—@€4‘:„C°iαζUD\Ο:λ,Ήωζ›K_›°₯"Q}τΡrο½χ–Ύ6a]¬ε>ŒΦ^·οFν$ναΚα›ς–΄‡.wάΈ£΄B«―­Ο¨νέ =6ΌRόΎ ζ’βjKV΅οΠ^ϊΪd©=ά–z²%‘|m ˆΔӎ'nA½T­ΰΨ­_πύ ΄Χ·>hkΉξΆλΚ¬ σ?Sp] ΄%ƒ,±BζAΏ³°Οπ>²Γ†€7[ZΘ‚¬b‰«η^χ’Ύ6-iK=ΩCδ}m²°Τ@ΔμΪ³«μ1΄‡΄λ―¨—]~Y·ΐ^jA>ιυί–J³ΒόΑ—,mi€S=UξqΦέή΄ο_ΉΧ3ξρη=Iλο³άίΟ΄~Νj"q 2Μ›7Oα$,@Ώ³:F D²?€J5™ηΝqσοφ"Ν%)MΏ"""₯χψ DšK dάί?¨ "P "•-tˆδ‡¨yΜΠ–lς΅mΙΥΧ]]ΪuΗΧ& Λ Dμϊ»~Ÿυεr­‚ρ ΄ ΔΦbφU:―"ΓίuŸΕΎI―¦δΧξΎΆ΄ορZ›%OΌDιΫΆ }J½ώ—{όi"IΗΏά@ΔLϊχƒk©ΏŸiύώ›"†@ [ŽώΩHΉΙ–=šΉΥΆΫΙƒφ’cN?SΎπβ‹²V!©lΏ³D8δPyΗ]wI¨m8_΅M^―oΥΒΝ;DDΌΫˆ4—@€4 Dς-H“""-ι~ΎI \C -"ΝΙkΑ°Zύ&0œ―Ϊ&―Χ·jαζ DκUίM6֏›νΉ™Œ»Tb#»ύ1ΫΛ§Ύ6-9ρ΅‰–²₯Ε|m³Π DΜφΎm±Ήε"7λ,ν{Wn W¨ "ΩbΘ”σ/Ζ?ωOωΦΫoΛ .œ!»o½Ό/‘΅TΞWm“Χλ[΅pσ‘„Ίψn²±~$AŒ/"ˆ@€l!iN^ †Υκ7„α|Υ6y½ΎU 7ο I¨‹ο&KχΘ돔λτXGϊΪ bm[n Ri‘2ˆdK±@€gž3^ξ8`wωίώWŸ|ς7yΚi§ΛΎ;ν"·ίΉΙΣΞ:[~φωηΕφϋθγK—.”Ά΄Χ_|! +ΠϘy‰<μ§GΙmϊl/χ;θωΧgž‘.QΓ―ΎϊZNΖͺΰ.Ιm·ίAχσ_Θ>ψP–Κίώwiϋίu=e―~ύε9'Ι―ΏώZQύŽzΏάΟ-ˆ|σΝ7r䉣δq'ό\ΊΫγ€1§Ιπ2naνxŒ€σ.ЍρKkήN6]ΪΌέΊw_ΉΧύδsΟΏ uΓ―₯}ξ6}ϋΙq&Ιόη?Ε>§άοG1jν|%ύžΪ8]tΙ₯ςΘαG˞}ϊΚ{ώτg·]γϋ9QDΝγ¨χ­3y™vτ1ζΟ{ο+η>ϊ˜tΙϊϊ™6nήA ’PίM6""–.bώ%0"ΩB œ¨‚`Φ=‘&DD’œ―€ίS§¨"n»€Ηχs’ˆšΗQο[?DDΚΕw“ˆˆˆˆ΅+T€l)5yό‰'₯:ί|λ-iX‘Ξ ΰ‹},?όθ#i4{ί%­Βςv;τ—OΞ{JZΑκλ~%­€ό·ΏύMQΑŸ>Y;ςηrΑϋοKΫωΐVX.V˜.†V¨~γΝ7₯η­·Ο’>τ°4’ϊυ~ΉŸkγmΘΗ‹Λ9LŽ?w²,uŒΈK0%wQD_ZσΦ‚¨ω/Ύ$­€|ζΈs€ž-ψ°ϊ;οΎ+wΨe€όΣ½χIϋœrΏQΤΚωJϊ=΅q²ρόλ³ΟΚrΫ%=ήΈŸEΤ<ŽzίϊaAΖσ/Ό -½βκk€=n`žυυ3mάΌƒ@$‘.Ύ›lDDDD¬]‘2ˆd H‘–‰?‘&DDDb`70ΎΠ žuρέd#"""bν Υ!‚„€ς(5±Β«vmiχ,φϊϋ| ]^{ύuiν>ώψci€UXžρέ’@Ε°%ˆ¬Πo+ΊŸkM+ΰYAωΥΧ^—Q|πα‡φΞ»οΙΈD2‹½Ÿτsέρ0h/i…υ€DΨӚwQDoZσφϊ#],ΈΨt«­e±₯ΗƜ~¦Ό08]άσUŒbߏ(ͺ}ΎϊžΪ8YΏQν:ήΈύ‰"jG½oύΈώΧ7J—Ο?BΪq,\΄H¦u^*›wˆ$ΤΕw“ˆˆˆˆ΅+T‡pΚƒ@„@„@$š¨ρ%i‚@€9ioάώD5£ή·~ˆˆ”₯‹ο&³ςI8 εQj β.™υΦΫoΛ'ŸzJvίzYŒόίIΫή–\1*,+θφπή™—].bΑ§žώ«΄Ολμ‡’QΜ{ϊiΉYž]j&ЍBf±χ“~wΏw•ƒχ;@ΪROI‰*°§5ί΄ζ­-=ζςμsΟK{Θz1Ξ?Aϋ>Ϋη;£Ψχ#ŠjŸ―΄Ύ§6NwέύYŒ¨vioάώD5£ή·~›§ξqXΐšυυ3+ܼ㨣Ž’"eκβ»IGDDDΔμ„|AΒ@yˆˆˆD5Ύ"Mˆ4'­γΫŸ(’ζqΤϋΦ‘²tρέ€#"""bvB> ‡ a _ΆΏ€ίΣ¨σaD΅Kλxγφ'Ѝyυ~T?Š"i—JγζΓ‡—"eκβ»IGDDDΔμ„|AΒ@yˆˆ$ω\o+€ˆˆˆό€uΌqϋEΤ<Žz?ͺ"1±_hPΟΊψnρΒoϋΧOφ<Έ§τ΅i7΄©:s¨τ΅‰c©γΙψ§+γ٘¦υύΝΪ]OΩUnΌσΖΧ&ŽΫ³½0f€τ΅©gύψσ&δ“pΚ£X ς―ύKΪ’XΣf\$mι—ϋςιrΔQ#δρΏ8QZaοÏ>’ΓŽ>F;ςηeΤ)§ΚŸ>YZαψƒ>”Ï=^ZΑ­XaΉχ;J[²ζο_}%―»αΧr›>ΫΛΏύνoˆ*ώ|τIŽονwή‘ί|σ|aώ|iνώοώOΖΕφ{ψQΓεoΎ%ΏόςKyΫ¬YςΑ‡–FTΏ£ή/χsέ©=ωμ ₯½Ι'“₯2ςΔQrκ΄ιςίώ·tI:Ώ΄ζm±BsځHΉί(jε|%ύžF#n»€Ηχs’ˆšΗQοGυ£X b$=/•ΖΝ;Dκβ»IG Θ&H}Θx6¦"ώvυ*HΎ„|AΒ@yˆˆ(χsέ)Θ’τxγ~NQσ8κύ¨~ˆΔΔn`|‘A=λβ»IGυΐ(ΉςZ+Λi‹¦I_Ϋ8R―Œc™φχ7kΣ DΞyωΩz₯Φrβλ₯―m=Ϊθǟ7!Ÿ„C°PˆXΛάrΫνδ{μ)ǜ~¦|αΕe1>^ΌXΪI}vάYφέi9挳䧟~*]l‰+Μχ؏ά{εΝ·ή&­ŸΕ ΛΞΌD:μ(Ω³O_9dθΑςλU΄Βρΐ»ν9XZ‘ΪΆ`φƒ²T,€˜8ω<Ήσξ{H+`Ÿ3ι\ωυΧ_K#ͺίQο—ϋΉQR+ŒΪgˆ΄‡‹Ηε―Ο<#χάw?iœ‘tήE5~iΝΫbγ˜v Rξχ#ŠZ9_IΏ§QηÈΫ.ιρΖύœ(μΈ‹Νγ¨χ£ϊˆd}ύL7ο I¨‹ο&‘@€ΎdόK‘ΪςI8 εA œ¨‚`Φ=‘ζˆ4A RIΏ§QηÈΫ.ιρΖύœ(μΈ‹Νγ¨χ£ϊA »ρ…ayδa9`ΐ²mΫΆ²K—Κ‰'HίΆϋ»δ6Ϋl#Ϋ΄i-mϋργΗKίΆ-Z(<π@Ω¦MΉκͺ«ΚSN9YϊΆυιβ»IΗς=vΦ±²}ΗφΧ&n}ΠΦ² ύ₯―M)R―ŒcYκχχτ§N—?πcΩzεΦr₯¬$ϋ φ8εέ)·$¦ˆ˜ομ'pπΔΑΧ& Ο|ζLΉΔKΘ1‘n»#;B.Χz9ιΎoύ΄ύ˜K-½”tΫGY©γOΫjύ~¦=ώq…|0oήύΧgd^!ˆ›wˆˆΤ΄"~)ΘWWΖΏ1$i’@„@$‰"†@ͺ@γβζD’8pwiσ΅iΙ]vΩEzθ!^ςΛ/€—\r‰ o[πΨc•½zυ’ξϋ.ξ Ί€z ν!Χέv]ΉΜςΛH+όXΗΆ›ςήΩgxiK­Xan«Ά’“ί™,m»•:ν­b―s―‰{Ιb…³rϋ?tζPiο›QδSζœ"ένŠi…iw?εŽ_ڎ}b¬΄ώΖύΌ3ώz†\Ώχϊ λl½Žά|ŸΝe±ρ,wόO~ψdΉμ ΛΚbKϊŒώΛhΉ\« _6ήn»RvΓ0ΉΖzkΘvkn°¦4n΄σΨγΐ`^Ίϋ±‡oΎw0NΦΎ}‡φrϋcΆ—ηxΎt·O:ώiYξχ/ιόοΌYgΩgD°}  + νψγΞηR΅qήρη;Κuz;Πζε}7“ήœ$}ϋHΓRΏΏ6﬽mοk›₯Ε‘©L•έvθ&·²…ŒzHόΘ?Œ”6ο¦}΄τ΅Mb­"•:~σΜgƒqμ>Έ»lΥΎ•l»Z[iΧ/·iύ~¦-„!€JcΑ‡=lόŒ³Ο‘y‡@ >nήA ΪΆ HσχΛν?H“₯TM‘‚ε~’Ξ‘&Kύώˆ$“@€I‘ς„|@ •†@άΌ£κΘgŸ}*ο»ο^iKfέxγ―₯oŸŸ|²XvμΨQ^xapƒhοΏώϊk ΆDWx-(Ye•U€ϋΎ«‹{ƒn)+δYΑχΌχΟ“n{Σ Žλm·ž΄ΙΔΧ&ΚMn"{SΪv[μ»…άmμn2ΌOŸέχκ.χ8kιΎ_n]­πRjΩ‚R—ό(wόφΈ;Ž“VHσ΅ρΩe«. ΧηΎu΄ρ°ύΕΟRΗΏγΖΑχ(π K’ξϋΆ?›oξϋεjσkΕΥW”“ή˜$m<켍eΌ\vω`^Ϊ’DΆ›ΧV8·φ§=yš΄ΐeΐ˜2ά‡‚iΉVϊϊaZ bAŠZmΙ' \άν“jΘj]W“c#ν<Ϊ’TΟ(}ϋHΓRΏΏΆΔΦͺ]V•vN{ͺ΄χ}Ϋ¦©ˆXΣu›²Χ½δτΕA}ϋkίϋύtΏoiY«H₯ŽίάyτΞςˆ_ΗhA–υΓ_ΆτšoνzΕ’YPKˆ@₯qσ‘Π> ˆ4Ώάώ»–Z7Λ-θ”;~iK Rš6ΏDš¬τυΓ$i’@€Iϋήdˆ4I RžD ΈyGꁈ?όP‹žvΪXΉΕ[4σΒ §Λ―ΏώJΖέ߈#δ‘G)m‰,ΫΟ«―Ύ"-0±ΐe»νzI[bλœsΞ‘?όα₯m_Μχί_Ϊ ή¨F5ΣΒΊΛQ»Θί|ώ›4o’΄ΒΛaW&έύž|ΧΙr›>ΫHΫώ”N‘CŽ"Οι|ΉφζkΛ­φΫJΪ~Ϊ­ΡNžxΫ‰2ά—‚ΆŸ#Ξ:BΪώΒ}ρiνl?#¦η'ππ3—φzΤώ†œ|~ΰϊ?Y_ΪvΕL:~Qύ3­»ύ”ΩSdmzΘ¨ύύ»£₯ΝΣK_ΊTΊϋ=ΰηȝ‡ν,}ϋ »Η {Hwό]­VθΆΒ·νηΔϋƒyhηcβ½₯o_£ŽΧ΄vηά|χ84θo νΗϊ½Ο˜}€mΧnΝ`ώzΥ‘ςΔϋ‚ώvZ«“œϊΘTξSΑ“―ΞΰOzύDΪώlόmώ ϋυ0iύ³νmόέρ΄vΆΏbΊϋ+f―Α½€Ύ}΄ύ]χΑu§=s‘΄ύY»C8D.Χf9ιξo³Ύ›ΙŸ]τ3ξSΑqw“λύh=ιnοjŸλξΗΥΪύΰΗ?ΫΎ­tχ·η‰{ΚCN Ž#Π·―‚Ά?w{Wkηn_κχΧΒ럫΅Ϋφ°`άπ£`ΧάpMiKe•ΊΏ#―~Wν{qμνΗΚrϋ>Ά°Gύζ(iΧΏπί>Χ^'ψ] τν+μ±Χύ άj«ΰχ/ΠΧ·‚ΕϊηψGƒσθΫGΨ¨γ5­oa­ί ϊl ‹νoς_&ΛΎ»τ•Εφηnοjνάν]‹νoπ€Αr©₯–’Iχηjν’p^+¦΅‹‚ύωΪί‹/Ύ(­]8 nήA B B B ς½Φ?kG B RΠέή΅ΨώDΨ_¨4nή‘z β[Vͺ%mΙ¬9s‘nΈ‘?~Ότmφ€“FΛM6ΩD.XπžtΫY°bJ/™5πŒ}ίΥjmύŒ«=όΪ–Άi³jyή‚σδΪέΧnς»`Δ–Ύ±%‡.ψθιφ§Τώ³Τ%›ΜR—όH:~Ύ}&ρΚόφdιk[π€O’ΦΎΨH½κ-γŽg©γφ gΛ₯—[ZNxe‚<ξ'ΫήVF=ŒΉTmI¨υz­'νu+Œ»K$­ΆΞj c6―mόΞxϊ iνM :μ{b―g5ώεZιλ‡νΗ–ΜΪoϊ~2ό-xZr©%eά₯—βjKf Ή`ˆtί·%‘6έcS龟–₯~£<}ήιr£ώɍw Ξo ―mm|¬ί› Ζ)ΠζϋΈωγ€o[Ÿτ΅­eσΦΌυ7kκꎿιk›₯Ύ>τ΅­†yι—ιk›Δ¬χŸ΅yο½jηƒ@$cΓ“Ώ ―M-λφίτ΅MbΦϋk­τ£Vd"‘u·άςΫ-ϋ όŸ"ρ Oώ‚Ύ6΅¬ΫΣΧ6‰Yο?΅Z‘ρhYw|L_Ϋrτν» ―m5¬Υ~₯m£g£›χσμφίτ΅m}cQΠΧΆVΊ_ξη™ΎΆˆIυ¦ž—ͺ’―ύ οPΠΧ6K}}(θk[Λζ­yλoΦ2ΥΥΣΧ6K}}(θk[ σ/ΣΧ6‰Yο?kσήzΥΞGt ²ξΊίtˆΔ3<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;‘HαyδώΣ€@$žαΙ_ΠΧ¦–uϋoϊΪ&1λύΗ΅VϊQ+2-뎏ιk[ŽΎ}τ΅­†΅Ϊ―΄m”γltσ~žέώ›ΎΆ o, ϊΪVΓJχΛύ<ΣΧ1©ή"ΠσRUτυΉτ] ϊΪf©―}mkΩΌυ?oύΝZΖ£ΊΊγoϊΪf©―}m«a^ϊeϊΪ&1λύgmήϋ_―ΪωˆˆtˆΔ3<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;"žό}mjY·¦―m³ή\k₯΅"γΡ²ξψ˜ΎΆεθΫwA_ΫjX«ύJΫF9ΞF7οηΩνΏιkΫϊΖ’ ―m5¬tΏάΟ3}m“κM!=/UE_ŸAί5  ―m–ϊϊPΠΧΆ–Ν[σΦί¬e<ͺ«;ώ¦―m–ϊϊPΠΧΆζ₯_¦―m³ήΦζ½υͺ‘Œ Oώ‚Ύ6΅¬ΫΣΧ6‰Yο?΅Z‘ρhYw|L_Ϋrτν» ―m5¬Υ~₯m£g£›χσμφίτ΅m}cQΠΧΆVΊ_ξη™ΎΆˆIυ¦ž—ͺ’―ύ οPΠΧ6K}}(θk[Λζ­yλoΦ2ΥΥΣΧ6K}}(θk[ σ/ΣΧ6‰Yο?kσήzΥ΁HΖ†'A_›ZΦνΏιk›Δ¬χΧZιG­Θx΄¬;>¦―m9ϊφ]ΠΧΆΦjΏΆQ޳ΡΝϋyvϋoϊΪ6‚Ύ±(θk[ +έ/χσL_[Δ€zSˆ@ΟKUΡΧηFΠw (θk›₯Ύ>τ΅­eσΦΌυ7kκꎿιk›₯Ύ>τ΅­†yι—ιk›Δ¬χŸ΅yο½jηƒ@$cΓ“Ώ ―M-λφίτ΅MbΦϋk­τ£Vd7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;‘Θ–[nων–"ežό}mjY·¦―m³ή\k₯΅"γΡ²ξψ˜ΎΆεθΫwA_ΫjX«ύJΫF9ΞF7οηΩνΏιkΫϊΖ’ ―m5¬tΏάΟ3}m“κM!=/UE_ŸAί5  ―m–ϊϊPΠΧΆ–Ν[σΦί¬e<ͺ«;ώ¦―m–ϊϊPΠΧΆζ₯_¦―m³ήΦζ½υͺΘ@€πŽΈε4 ‰gxςτ΅©eέώ›ΎΆIΜzq­•~ԊŒGΛΊγcϊΪ–£oί}m«a­φ+mε8έΌŸg·¦―m#θ‹‚ΎΆΥ°ύr?Οτ΅ELͺ7…τΌT}}n}Χ€‚ΎΆYκλCA_ΫZ6oύΟ[³–ρ¨ξψ›ΎΆYκλCA_Ϋj˜—~™ΎΆIΜzY›χώΧ«v>D26<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;"žό}mjY·¦―m³ή\k₯΅"γΡ²ξψ˜ΎΆεθΫwA_ΫjX«ύJΫF9ΞF7οηΩνΏιkΫϊΖ’ ―m5¬tΏάΟ3}m“κM!=/UE_ŸAί5  ―m–ϊϊPΠΧΆ–Ν[σΦί¬e<ͺ«;ώ¦―m–ϊϊPΠΧΆζ₯_¦―m³ήΦζ½υͺ‘Œ Oώ‚Ύ6΅¬ΫΣΧ6‰Yο?΅Z‘ρhYw|L_Ϋrτν» ―m5¬Υ~₯m£g£›χσμφίτ΅m}cQΠΧΆVΊ_ξη™ΎΆˆIυ¦ž—ͺ’―ύ οPΠΧ6K}}(θk[Λζ­yλoΦ2ΥΥΣΧ6K}}(θk[ σ/ΣΧ6‰Yο?kσήzΥΞGŒ@δΘoφγ‘κεžό}mjY·¦―m³ή\k₯΅"γΡ²ξψ˜ΎΆεθΫwA_ΫjX«ύJΫF9ΞF7οηΩνΏιkΫϊΖ’ ―m5¬tΏάΟ3}m“κM!=/UE_ŸAί5  ―m–ϊϊPΠΧΆ–Ν[σΦί¬e<ͺ«;ώ¦―m–ϊϊPΠΧΆζ₯_¦―m³ήΦζ½υͺΘ@dέuΧύΆ Ϋ€@$žαΙ_ΠΧ¦–uϋoϊΪ&1λύΗ΅VϊQ+2-뎏ιk[ŽΎ}τ΅­†΅Ϊ―΄m”γltσ~žέώ›ΎΆ o, ϊΪVΓJχΛύ<ΣΧ1©ή"ΠσRUτυΉτ] ϊΪf©―}mkΩΌυ?oύΝZΖ£ΊΊγoϊΪf©―}m«a^ϊeϊΪ&1λύgmήϋ_―Ϊωˆ DΆά²ί·χ?ςˆΔ3<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;‘ˆύ?n‘x†'A_›ZΦνΏιk›Δ¬χΧZιG­Θx΄¬;>¦―m9ϊφ]ΠΧΆΦjΏΆQ޳ΡΝϋyvϋoϊΪ6‚Ύ±(θk[ +έ/χσL_[Δ€zSˆ@ΟKUΡΧηFΠw (θk›₯Ύ>τ΅­eσΦΌυ7kκꎿιk›₯Ύ>τ΅­†yι—ιk›Δ¬χŸ΅yο½jηƒ@$cΓ“Ώ ―M-λφίτ΅MbΦϋk­τ£VdD26<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;"žό}mjY·¦―m³ή\k₯΅"γΡ²ξψ˜ΎΆεθΫwA_ΫjX«ύJΫF9ΞF7οηΩνΏιkΫϊΖ’ ―m5¬tΏάΟ3}m“κM!=/UE_ŸAί5  ―m–ϊϊPΠΧΆ–Ν[σΦί¬e<ͺ«;ώ¦―m–ϊϊPΠΧΆζ₯_¦―m³ήΦζ½υͺ‘Œ Oώ‚Ύ6΅¬ΫΣΧ6‰Yο?΅Z‘ρhYw|L_Ϋrτν» ―m5¬Υ~₯m£g£›χσμφίτ΅m}cQΠΧΆVΊ_ξη™ΎΆˆIυ¦ž—ͺ’―ύ οPΠΧ6K}}(θk[Λζ­yλoΦ2ΥΥΣΧ6K}}(θk[ σ/ΣΧ6‰Yο?kσήzΥ΁HΖ†'A_›ZΦνΏιk›Δ¬χΧZιG­Θx΄¬;>¦―m9ϊφ]ΠΧΆΦjΏΆQ޳ΡΝϋyvϋoϊΪ6‚Ύ±(θk[ +έ/χσL_[Δ€zSˆ@ΟKUΡΧηFΠw (θk›₯Ύ>τ΅­eσΦΌυ7kκꎿιk›₯Ύ>τ΅­†yι—ιk›Δ¬χŸ΅yο½jηƒ@$cΓ“Ώ ―M-λφίτ΅MbΦϋk­τ£VdD26<ω ϊΪΤ²nM_Ϋ$f½ΈΦJ?jEΖ£eέρ1}mΛΡ·ο‚ΎΆΥ°Vϋ•ΆrœnήΟ³ΫΣΧΆτEA_ΫjXι~ΉŸgϊΪ"&Υ›Bz^ͺŠΎ>7‚Ύk@A_Ϋ,υυ‘ ―m-›·ώη­ΏYΛxTWwόM_Ϋ,υυ‘ ―m5ΜKΏL_Ϋ$f½¬Ν{λU;‰DDDDDDDDDDDΔΌθζ"ˆˆˆˆˆˆˆˆˆˆˆXwΊyΗχΘα‡ώmA·"""""""""""bή΅„@λΦο‘bKf!"""""""""""ζέο—Μ"ADDDDDDDDDDΔz•@λ^DDDDDDDDDDD¬{ D±ξ%ADDDDDDDDDDΔΊ—@λή}χέWˆ """"""""""bέJ ‚ˆˆˆˆˆˆˆˆˆˆˆuοπαΓ%"""""""""""Φ­"ˆˆˆˆˆˆˆˆˆˆˆXχˆ """"""""""bέK ‚ˆˆˆˆˆˆˆˆˆˆˆu/"""""""""""Φ½"ˆˆˆˆˆˆˆˆˆˆˆXχˆ """"""""""bέK ‚ˆˆˆˆˆˆˆˆˆˆˆu/"""""""""""Φ½ί"#FŒψvθΠ‘ήFˆˆˆˆˆˆˆˆˆˆˆˆyφϋ@dϋν·ΆoίΎήFˆˆˆˆˆˆˆˆˆˆˆˆyvΗƒΎ D a"""""""""""Φ£"ˆˆˆˆˆˆˆˆˆˆˆXχ~ΏdVώύΏ=πΐ½σμχΘ±ΗϋνρΗοm„ˆˆˆˆˆˆˆˆˆˆˆ˜gΏD a"""""""""""Φ£{Y Rψ?"ˆˆˆˆˆˆˆˆˆˆˆX~ˆμΈγŽϊ|0Ή/Ύτ’άdΛςΥW_‘ΎΆˆˆˆˆˆˆυμΰ!ϋΛoΊIϊΪ`ύωώϋ δI§Ž‘[χξ#χΨ{_iνnύέν²»I»~葇exŸˆˆˆˆ₯ψ} ·oίo ‘ˆ―&—@±I‘Ζ”@«νχΘ!CΎ-θk„Ι%ADDDΔzpΏƒ–ΧώκWΧ1J‘Ζτw³ξο-ίxγuiο/Xπžάn‡εέχά#Γϋ@DDDLβχUΟVDDDD¬ D0 DSDDD¬Ά5ˆ9b„΄ΐΐάrΫνδžϋ‘7ώφ··Z–@kIϋϋϋ¬sΖK_,έ§ž~Zž0j΄΄ΒyόΟO”/̟/έν?ψΰ}9~$iΫmΥ«·<ζg?“/½ό’t·7ο½>yΰ‘‡IχΎκϊ“τmΗzPŽ8ξxΉ]Ώώύœ3gΚwί}GΪφ"MώωΎ{₯}{φΩ^φΫeWyΪYgΙ7ί|CΊΫŸ~ΦΩ2|]p³=₯ΫΎ\οΰyΔπα²gοΎrΛmzΙ½χ?@ώϊ77Iί> NΉΰ9ϊ”1}―ΟόUZ?όπιΆ«–ϋp ΌώΖ_K_›J8ζŒ3€{ή]/½ό ιnΏMί~·ΟζΏ mϋ€Χ©€ύGDΔζ¦υχc\ ΪK>0ϋ/Χ&μWG!Ώ]b‰ζ.½΄τm“₯"’@kIϋϋ›@$] DDJ‘@€ωϋ"ρ$ADΔ°iύύW‘”,vCφΞ;oΛΛ―ΌRΪF=ώ˜ ο£–%ADDDΔZ²ΨίߘΜq'Κί͚%_ύuωάσΟɟ}ŒzΨaέώ‚ gH{˜τœGηΚ_œ/‡8F|Δ‘έώώΏ< {lΧG^}νuϊρτ_Ÿ–VHw·ς»ο–[lΣKžάtœχΤSξίμ~m”σδ-·έ*m?"MώΣα–†²ΰγρ'—φ°ρQ§œ"}ϋϋξΌSΪ}³―M)ήωϋίK;ίS§M“6Ÿ_}νUyÍΏ‘Vh?ϊ…έίg“Vwίψ‘G€}žϋ~΅­΅@€άοq”§yΆ<θ°#€ϋ~λTΦύGDl4“^—γ:ο©y²w€1ΎΆ-ωι ΧKDDDDĊI ’""₯H ό}‘xf(ˆ "ζΛ€ΧεΈˆ€lΤ ™ °ύawΣΝ7K{­·ή’gΫάqΐξώ ϋι1ΗΚηž ώp ο» ½oΕ¦[m-wΪm ΄‰UμŸμΪ³ύΨ?!Ά‡Ε]qυΥ DΊζZ9hŸ!έ―ωΤΣOI;ώbǁˆˆˆˆΗr‘¨‡ͺ[‘{ΚωηΛCŽ&νογέφάKήύ‡{€»}Ώλg\|±άu=₯ϋ~΅΅ Δ–rίίa—]₯ύaξϋO<ω€΄ϋ »1΅χνFχŒqηΘπΆI΄ϋ »?²₯œ|mγ˜tžΨ<°q(υώΝ>άσ¦ΚƒΖ-pλή}δooΉEV{>ύςŠ+δΞ»ο!}mΒ¦ˆΈη;nαΪξ[o#ν{ꞯR΅ο…}ΞeΑ˜΄ώΩ’ 4>2gŽ χ­`ΉΧ—Ÿύb”τυ­ ]­}Φσ&«@αν·ί’ΆtΫo~ϋ[ιΆKz"ADLΧ€ΧεΈ^|ι/e±₯/γJ ς""ˆˆˆˆX9 Dͺ#H“Iη‰Ν‘& DD’H ‚ˆ˜O“^—γZwΘ±Η›‹%³μ+ ¬έ1?)νŸ=σμ3ώΙ±ύSn{Ψ›,Ά½«½oH ΄§,φΑΠΓ—ǝp‚|ωε—₯ύ“τ}*mβY bΩφ°:wΦa#Ž–ξϋˆˆˆˆˆ₯˜u b…F{ψΆύ]?mΖE²ΟŽ;I·`τοϊj°‹9ώ|i!·«½oKΩύΒ_fΟ–α}„΅°-E΅`Α{ξ—lΙ"[rΙΪο{ΰAζνΫ·Ο'ž|BΖν_”Iη‰k©χoφωΫο΄‹΄₯Ζjm>ΩχΑτ΅ ›V βžοΩ>(}mΓΪψmήs[ι^'¬nρπΆzδaYlΙ,[šΝφoχΟοΎχ΄yi•u··q,χϊwΙ¬¬ηŸˆ6^ΆTŠσoΌ.}ϋπyMp ΪΓxί Ζ΄ ½Ÿτ:e―gΥDΔF3­λr\m)Ε[w»τ΅‰c΅‘B’@dΗwόvθΠ‘ήF•@„@+'He%inyβZκύ›}>ˆ_DΔΪ7­λr\λ.ιΫ·ο·}*‘ݐ٠t΅?xξΌλ.iΫ½0iνμF#Όο‚φ‡Œ>φ˜tΫΣώI{γb‡}Ύ!αm ήσ§?Jkgˆ½o?ψΏ8ιdi―Ϋ Ϋυλ/o»ύviο#""""–cցΘ%ΏΌLΊοΫΓ½νοβ‚Ώέ›¬Μίυ• ¦v<ζ^Cφ“vάΦή ³ΦΞ–6ο3lΏ]v•vμώΒΆίa—Rύζ[oJ li(wίg„΅Εφό ΟK_Ϋ8–;OάvΕ,vfΪηΫxΈοW[ϋ{mΏƒ΄ϋN_Ϋ°i"ξωŽ;OL Ί¦_t‘΄ΧνΎΧ βαm F"φ=ι±]χϋoύ·γ)χϊ7©΄οΏΏ@Ϊχ}π~Αό΄Φ·O;Ύρ“Ξ•ξϋI―SΎ6Σκ?"b£™ΥuΩΥώ.³@Εώτ΅#Θwˆˆ """bε$ΙV‘–-wžΈνŠI B ΦϊoΗSξυ…@„@±–ΜκΊμj—ˆ€l±²W^yYΪRTφOΌν•ϋξΏ_Ϊ‰λwώ?iŸsΛm·Iϋ§±φ–»έ‡&m;ϋCΡΪΫλΟ>χ¬΄ύΈˆύ“d{Έ’ύ“'{(]ίw–φOαΓϋFDDDD,Υ¬ϋ;Φ}ί–Ά±Ώ‹Ÿzϊi™Φίυ΅¦-υτβ‹σεigž-wάmwiKD%]ςΰέwί‘φpρ©Σ¦IίΆmIœnότ΅ λ.‘ΥΏ(˝'φ~Ήχo¦}ώ―s“tί―–„τξΏ“΄%ΐ|m}¦ˆΈη»V–Μ2ν{oΧ1+δŸtκ9ηΡΉΪ§u}±Ο©΅@ΔΥκv=ˆ*\ΩΈ[{χϋf&½NωΪψ,΅ˆˆj₯ΛΆιΓ‡K_›R¬™@€πφίo£JXμ†Œ@„@Σ·ΨίίQˆ”&ˆίr牽O β—@„@€`©"b>­ΤuΉn‘γ?ώΫ‚ΎF•0κ†ΜώiŽύ“α«―ϋ•|ξωη€ύΑgΑέΎ˜/½ό’΄ν7λi?ΈvsιεWH»΄νγ.™υΗ?ύIZ;71>όH9σ_Jϋ~βδ)mˆˆˆˆXŽQ3«@$ιίυyΡ–~²γŸϋθ£ήίa—]₯ΖΓΫ΄₯lϋyOΝ“φώξ{ν-‹"vcKς;OΆέN» ”VΨφ΅cΉσ$ιύ›υω•φΒ‹/–φχǟx\ϊΪΆdZˆ£wqΟ·§}ώsΟίλ@{ίφ“4q΅ Ζ>ί–Ό²ΐ1­λ‹ύšυˆœ4f¬<ό§Γ₯―MΨ€Χ©( DK3λλςΘGΙΛ―ΊJϊΪ”"Θwˆ4I ‚ˆˆˆˆ•@€:ˆ4Yξ΄a{h¦=€ψ­·ή’φρm·ο'm)/w?ΕΌλξ»₯-υkαΦSO?%νλBd”V@Άϋˆ-·έNnΏσ“'η=)έν-X9'8φ‚Ά΄•νηθγ&mι(w{ΣnŒνs­ΰyΰ!‡I |ΫΖρΑ‡”Ï=^ΪΖΦΟ=χ"/Ίδi}·ν“Ξ“€χoQŸof5ŸμΎΦŽ/Κb}}Ϋψ,vε½χί'mI₯­{χ‘Φ/+`G-%•4±ϋe›Wν)mήΩy΅₯Τάν“^_ξΰiKΣuίzιΞ³¬―Cwήu—΄ωnίo[βμΜsΖK[zά·‚Άτ‰ΥŠ—Τ=‡nYfΚ{7fόSʜ28»k©qLm;΅Φ―ΩΞ-ΖΟϋޏή!B[ίΨύaΜO­©sΦσΠώpr¬±»ΎŽλϋωk%ΉN&ΤΣg_Χ·ϋώ”Ή>tκοΧτgσ?xWΣ=§ΠIENDB`‚rocq-9.2.0/doc/sphinx/_static/coqdoc.css000066400000000000000000000141161516144147600201700ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* div.version { color: #dedede !important; } .std-term, .btn-info:hover, a:hover, a.wy-text-info:hover { color: var(--refman-custom-primary-blue-2) !important } .wy-menu-vertical header, .wy-menu-vertical p.caption, .rst-content .wy-alert-neutral.admonition-todo a, .rst-content .wy-alert-neutral.admonition a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.seealso a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .wy-alert.wy-alert-neutral a, a, .wy-text-info, .btn-link, .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-nav .wy-menu-vertical header, .rst-versions a, .rst-content a code, .rst-content a tt, html.writer-html4 .rst-content dl:not(.docutils)>dt, html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt, html.writer-html4 .rst-content dl:not(.docutils)>dt:before, html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:before { color: var(--refman-custom-primary-blue) !important } .rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title { background: var(--refman-custom-primary-blue) !important } html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt { background: var(--refman-custom-secondary-orange-2) !important; color: var(--refman-custom-primary-blue) !important; border-top: 3px solid var(--refman-custom-secondary-orange) !important; } .wy-tray-container li.wy-tray-item-info, .btn-info, .wy-menu-vertical a:active, .wy-dropdown-menu>dd>a:hover, .wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover, .wy-side-nav-search img, .wy-nav .wy-menu-vertical a:hover, .wy-nav-top, .wy-nav-top img { background-color: var(--refman-custom-secondary-orange) !important } .wy-side-nav-search input[type=text] { border-color: var(--refman-custom-primary-blue-2) !important } .rst-versions, .wy-nav-side { background: #dedede !important; } .rst-content .admonition-title a{ color: var(--refman-custom-secondary-orange-2) !important; } .wy-menu-vertical a:hover { background-color: #494949 !important; color: #dedede !important; } .notation .hole, .std-token .pre { color: var(--refman-custom-secondary-orange) !important } rocq-9.2.0/doc/sphinx/_static/css/000077500000000000000000000000001516144147600167735ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/_static/css/custom.css000066400000000000000000000004141516144147600210160ustar00rootroot00000000000000html.writer-html5 .rst-content dl.field-list, html.writer-html5 .rst-content dl.footnote { display: grid; grid-template-columns: 30% 70%; justify-content: start; justify-items: start; align-items: start; } dt.field-even, dd.field-odd { max-width: 100%; } rocq-9.2.0/doc/sphinx/_static/debugger.png000066400000000000000000002417431516144147600205100ustar00rootroot00000000000000‰PNG  IHDRDπ₯²,sRGBΞιgAMA± όa pHYs‡‡ερe₯IDATx^μέœTυ½sS4&7&ω%χjŒ‰F»¨A± τ"{Q@AQ*ˆt”’ ¨(X+ˆτ^₯(½,KUSώχζ¦νΜ{φ³ξ~ύ;;3;;ευz<ž{έ=ηΜΜ™ΩΩ=ηΜτΐδ™βφ&UŠΈόκK$Ϊ―ΗΚw_d§F‰ο{”΅ϋοΏ_|ίσiΩ¦}^‹4Ί―ΎΗPX¦=žte/uμΨ2‚ύ~υ}―,4hΠ@bύοTSάύ-ξΏSMqχ·ΈŽUͺ½NΛ dwPΑ@@²1€2;φ}Ο§u»ή“υ©(t_}‘°L{<銁€L“j'š‹;‘^ά§šβξoqjŠ»ΏΕύw¬RνuZV "DDDDDDDDDDDD™"""""""""""ΚψˆQΖΗ@„ˆˆˆˆˆˆˆˆˆˆˆ2>"DDDDDDDDDDD”ρ1!""""""""""’Œe| Dˆˆˆˆˆˆˆˆˆˆˆ(γc BDDDDDDDDDDD"""""""""""ΚψˆQΖΗ@„ˆˆˆˆˆˆˆˆˆˆˆ2>"DDDDDDDDDDD”ρ5jΤHˆQΖ–‘ΓŸ-ΘϋΛ‘ύyόη?σΏBDDDDDDDDDDD”Έl’τΘž/孞Π>oΕ³mς–mU`Υδξyχ—ΏQό•Ι@dχ'SςVŽk›·tLK―3fδύλ_Κ_šˆˆˆˆˆˆˆˆˆˆˆ(ΎΚd ²fbο δ-ςrssσ—&"""""""""""Š―2ˆ„.“ε„|cΙ’%ωKQ6uI'%ίϊυςͺV½5ο«―ΎΞJΙ ­ΪFh[©X"ώχΏσ–mε‚φή{οε―ADDDDDDDDDDΩ”o¨*ΎΠ γϋ'Ÿ’wε5ΧΔ4 ­Z7΄ΠΆR±€DBΉŸ²yώΔΐ„ΌOG΅Φ2²UήςεΛσ—&"""""""""’l*Qƒ "ΡWx Q‘H<λ&³2ˆόυ―Ν[6ΆUήΖwž ΔΌ>~Ύή³gΟΌcǎε/MDDDDDDDDDDΩ‘²)–ΑFΊ CB•Ι@$TαAˆ9rdή3cFζ}πΑΊ΄–ϊ wbڞ·}ξΘΌΦεΛόP„•Ο+ίzdήάνω‹•IsσZλΎ΄ώΏΒmΟYΎπ}-ͺ|πXZϋπΔχύΔېΦEo•ˆˆˆˆˆˆˆˆˆ(™ΩΉΚxKΤv²©’ 8iͺΜ"«V­Κ{ο΅gŠ DƎ›wδΘ‘ΌώσŸy9[?-ς=³}γ}?žΆΟmW>!¬Ό† ε  ʏΜ+»™HέίBμ~η uόχΫ0 Dˆˆˆˆˆˆˆˆˆ¨ ³σœρ–¨νd[Ρ :mͺΜ"ϋίσώρv„"‘rΆ|Rδλ™3gΖό/FΆ΄ϊΧs½CƒνΫη桎8PHFΕ DΚητήΉΠΏziW0Ψ)οΚΆαϋQΩ—¨AF’Ά“hΰ‘ŽΓPe6±ŽΚ)tŒ5JƒŽΒΓŸ…oŽΞϋςΛ/σ·P‚ζΆΞh]Ζ—Δ*X"V‘ς­νΑ@„ˆˆˆˆˆˆˆˆˆR»D 2΅lΝ7ψHΧaH¨2ˆ€<ύτΣy:Ό³Θπ#’ 6δo!ΪlΘPά0!Šw *γe BDDDDDDDDD©‘ΤΙ€€λ0$T™DBِ£ώE†'2ώόό΅£ΜώuH\Ÿ±=oξΘB—€’ΠgnσAζΫηζl,W°Nθ3>B—λŠ4œHΔ@$τσo«ΘΒ Dˆˆˆˆˆˆˆˆˆbι›s‚‰A‘KΤ>b_'¦ΒC‘t†„*σΘŽ― 9xΌΘΠγDJ:±α@Μσν# 4Κη΅nέZŠ|Ν·νΒλ•·υς?Η€|π—β@Δ?b BDDDDDDDDKασ€‰C‘KΤ>b_'&" Κ7μ(Μ—‡–π’Y%$|+P„*ίή@θƒΜΓ?X‘Ύυμ>h½8"6ŒρD"‰u%&;_o‰ΪN6WxϊΏ…tŠ”Ω@δ˜­ήaG4:uκ”wτθΡό-ES|*bϋΘόΡq‚^bΛΎ<•οkE*ψΧ#e4)_>―ό·΄f BDDDDDDDDDešΞ_β-QΫΙΦάaHθΏ}_K—Κd βrψτκΥΛϋυΑƒηύσŸΜίZ4•pΰΎάV1λΪπ‘όΘΰΦΒΏ^€AM2"± ‡ˆˆˆˆˆˆˆˆˆˆJ;"eί‰ι:Iϊ@dgy‡>3fΜψΦΧνρ`ή₯Kσ·}Q 5ΌE;@Θb D’Y―”"ω—ςβCΥ‰ˆˆˆˆˆˆˆˆ(b RΆE3πHΗ‘H"ϊΧΏςΎχς·>?^τCΦG>ωhήsΟ=—χχΏ=kΡWμε«"–ΎΙ3!""""""""’Τ.QƒŒDm'›*Ι #έ†"Iˆ„ EΎψβ‹ΌUοO,2π(μ“™#ς6ΝϋζΏ;vμ˜7sζΜΌϋΏΛίJ ‹ψyΕεβ[—§Šf½Hƒ Dμƒή ]Β+"""""""""Jνˆ”M± 8i(R&λψGήςEώKh=ωδ“y³fΝΚλΫ·oήΤ©SσφνΫ—χο;ΝΨ²1ρν!Α‰‹υCΥνφ"ώ«Z$z R0όρ-Η@„ˆˆˆˆˆˆˆˆˆR»πyS"Ι,žΑFΊ EΚt *4δp‡!=τPήΡ£Gυ―AB—ΗŠwςM6 ”o7rͺ°}ξΘΌΦ­ Ml@αnl4Ψ8Ρ`bϋ7ΫLΨ@dϋφΌΉ­ΛηίfθRYή…ˆQJ>oš8T|U«ήΧ@£πP$΄­T¬Μ"‘Ά,xΎΘ@dΪ΄iωί)Άηl/>ς•/_>_‘χ_‘ 7B‚e[·Ξk(ό5ߐ’ΰ_—„”―Σ:vʏœa8Qά@$΄-»Οa·‘ο΅>ΑΏ ‰Όo0,!""""""""’²«ΘωΞ β[Ώ~ƒρόλŽΠΊ‘m„Ά•Š₯Δ@€π0$δwήΙNι΅}ϋ\ FΎh„…­GΞ-: ±œ!'Z>?ύ‹“"Γ–`ύλHZ#ŠΘ·χ«uδυςM'Ϊ†a BDDDDDDDDDD™U™DάaHΘσŸΙϋη?™ΏD&i BDDDDDDDDDDD‰¬L"ΗφnπDBΆlΩ’ΏT&Η@„ˆˆˆˆˆˆˆˆˆˆ(•ν@dίFο0$dαΒ…ωKer Dˆˆˆˆˆˆˆˆˆˆˆ’Q™DΎ<°Ω; ™?~ώR™""""""""""’dT¦‘ϋίy;vμΘΫΌyσ·?~<©LށQ2*Ӂ1!""""""""""JF Dˆˆˆˆˆˆˆˆˆˆˆ(γc BDDDDDDDDDDD"""""""""""ΚψˆQΖΗ@„ˆˆˆˆˆˆˆˆˆˆˆ2>"DDDDDDDDDDD”ρ1!""""""""""’Œe| Dˆˆˆˆˆˆˆˆˆˆˆ(γc BDDDDDDDDDDD"""""""""""ΚψˆQΖΗ@„ˆˆˆˆˆˆˆˆˆˆˆ2>"DDDDDDDDDDD”ρ1!""""""""""’Œο[‘C‡r2 ρˆ€ŒΗ@d<" γ1Θx D@Ζc 2ρˆ€ŒΗ@dΌ΄ˆΤmΤX^xρEρ-ƒΘΆlέ"—^u|ρΕηβ[~οˆοˆ―“δΊ§N=™ώΚ+β[ΰΌAvγ}@Ά` ’%ψΓPόή+ή? ^'ΙΕ@ΡΰΌAvγ}@ΆH™HqoΌΌ1Η§Έ?lΨΏE±?’)―^ψ―”^w™η!Ε½x$‘τPΦ? D²οΛ²‘,Α@€dΨΙ”Χ―gΔ‚Χ Κ―»Μΐσˆβ^ΌN’‹Hz(λŸ "ٍχeΩ’Τ"ΝΫ΄ϋE‰-ηΫFa™ώΖνώ2sίO|Ϋς‰χ›ZυΘKΣ§‰o™²Τ¦CGιϊπΓβ[Ζ§q³ζςXŸ'Δ· ’美gΟ™+ΎeCμu5ζΩqβ[‘₯ϊΟeͺΪ·ŸΨλ΄€.Ώζ:ρm;“”φο]^ΏΡ™7Ύ4kέZ»©’\uύ ro½ϊ2uϊtρmι'έί§2ύοφO~*φχ獕«ΘUεo”»kΧ‘QcΗΚΎ}{Ε·­l–ι―“HΗwφώ}k;εΑξΙΒΕ‹Δ·­D` ›q'J΅;οί2!γƒeBμyžσή{β.gοW―wηΜwΉ²Β@$Ήμ}’OΏώβ[¦0{ί:|Έψ–‰G¦Ώ/€a ’"’έ_†HQ DRƒϋ:f RΊRύη2U1‰Niήευ"Ω‰Hjc ’™ώ:‰t|Η@$½0a Ršμ}‚$W©D’}c/N¦Ώ1'zΉ2} ςΞμΩb’;vμί²!kΦ‘ΛΎV–.[&Ύe={Ϋ‰;!pπ`ŽΈΛΫ늁HlRύη2]uθE~΄—ψ–Ι₯ύ{—Χο‰Ωο5;abΎ7m”/Ά!S§Ώ,ΧW¬,O &Ύm"s€ϊϋT¦ώέώξœ9b?—ύ ’ΥkΦΘή½{dωŠε2hΘSςΪΜΧΕ·Νl–©―ιψξΐύ²zΝjιΌ†BΚ]{½ΜzσM)Ό­D` ›+WˆGoάόΈΛ΅νΨIξΌ·Ά 6ψΩΉωΆjb?={=&‘Žv;vBΞnǞ»Τ’]’Ι]ΏΈΧM²^Ώρξo»„…έ―«oΈIl,^²Dάυʊν/»ΏΡ^ΡNpEz?³Χˆ)ΌnΘg›?{άaA’^χO>5T7m.ΧήTA^}ν5)ξu—m―‡HŠ{ŸŠχ}=ήυ‹{Σύη²WŸ>β[6ρξ_ϋyJχί#Ε}?ޟχ²V㻇yTμy²Χ}?ήύοσiχ+Φί#ρώέ\Φ*έZM^œ:UμλφσSΎRey}Φ,©]Ώ‘ήFΘΐ`ί‡4ΌΏ©Έί/ξηžΗXξŽχΌA¬ο_₯}œΏίKϊ>a―H‘xί'’}ύΕϊ>©‚HŠ(ιώr1a ’ μuΜ@$Ί»X_I.‹{‰:1c―_"'ώ}cϋ‹Θ·_»!v»Ά|Όϋ;έOΌ2)Ίl{=DΒ@$ΉάŸK"‰ω=Rάχγύy/k%=Ύc Β@$€ΈŸ {cύ»›HΡΫ-k%}Ÿ°ΧˆOΖ DΪuκ,φ–θά΅k§Ψ Z{ƒŽτ‡Y)ιώrΩTv€l¨¬]·Vμ²HΨ·νΔuͺ_Ϊd؈‘b—jrΏoDέώp‹τxJλυfvΒΚ.}bΫ­Χψ>©~WM™4εE±ο5ZμC<νλ©Β^Ηƒ‡•—_}U*έr›ΨhΆ|q—νGϋƒΆϊ]w‹έŽ-gϋΩ.i±dιR)Ό­»΄L“-Εύ~q―ƒMξ—Ξ]»ΙηŸoϋΎNΓΖιηΞνγ3Ρώ\χ8μΔdΛΆνdsp°²ι³MbZφ}w}ϋΓΨώΰΆ›΅K‡ΨλΦ”άόTSά‰ΖxίΨώ²ΆE‹‹ύ|<Τσ± ;ae–vΙ?ϋΉzmζL)| ߎ ψΡGbχΣ>μΧ,νυkλχΊq•Φλ7Φύm—°±KR؁™}Xυ' ˆ Θ}·]VZ)φΎa'|ΛfΫ―ϋΌΕ{"+Q―{{έΞϋ$x>ξrΕ½ξ²νυIqοSρΎ―Η»~€η1S~.ν~ϊ–FΌϋΧ~žύχHqߏχ}§¬•τψξύ>{­Z½JμϋρξxŸΟx$ϊοζd³Ώ Ÿ}έώξ­Qσ^±γMۏξ~¨έ ‘ >Bμλ¦ΈŸ {cύ»;ήσ±ΎΩ~HτqpΊ~/ιϋ„½>" Dβ}Ÿˆφυλϋ€ "ΞvΚJIχ—‹H‘²e―c" DJr`–jμ}”Θ‰_7zύΖΊΏ3εΔ+‘oξcHΆ½")ξ}*ήχυx׏τΦ–³joί·?ŒŸ7^ ―b@ΆΎ]2Α].UD:ј¨Ÿ‚ύ5~‚^7Δ,μT{φμw9;0·K/Έί·Ϋ±ξ~ίΨ%άΟH―›hΕϋϊwΫ ]BΖ}RΥ‡Οΐ·νί²>v‚dδ˜1b_υD–ϋυx_χvB£πΊ…EzέΕ{?υυI€χ©xίΧυ{!σ˜)?—vβΟ·μ‰$jΪΟSΊ‰τύD½ο”5ϋ»8ڝ6¨²Ηm'v΅?β}>cύ=’¬Ώ›K›ύ½bƒDϋΊύΎνΥϋ ±―·hΣVfΎρ†μάΉCl `Ο―-oŠϋΉ±η1τ7wˆϋ}ΫοΆνοξxΟ$κύ+ΡΗΑιώϋέή'lEΛˆ$κ}"ΪΧ_¬ο#*ˆ8Λ••’ώ"΄?LˆeΟ?‘²a―c"a DΒ"˜ΉΛ₯ "α―GzέD+ήΧoΌϋ;SNΌΪ~π-λΓ@$³^‘0I." Dba3a Β@δ›Χ+‘’μ}ΒφW΄ˆ@|J} ν€Ε½ρFϊώΗσζIα_Ρx띷₯πm”₯’ξ/chφ€o™ϋƒΕΏϋfqϋ?Ϊ―©’mΗNbNh_·K#=ή·Ÿ^§°~½Ω§}έo½%φ‡σ–­[δ†J7‹]Α.΅rΥ*±ν₯ {Ϋ@ΔΎώρΌωbng˜Ϋλ*@Δ.α`€Χ^ηξώ΅‚οξœ9rcε*b„έώΠ·?ΌχνΫ+ξϊ‘^φsg\xΒŠϋΉ‹χρEϋsYάγ°bαu ³rnχΗώiΎ}ίώ0Άu.Όnˆ»Ύ»Λ₯ŠH'υσ_άώ²Ϊo―χϋΖξ_€ίv;ξσξ²Wt–‘^7¦΄_Ώ‰Ϊίφίφώd·k—”Y²l©Ύν²”¨KfΉϋ5ΦY‰~έO{ω)|Ϋ…Ezέeλλ!’HοSρΎ―'κχBqοιφ<$κ’Y‰ΪΏφσ”ξΏG"}?Q?οeΝ^ί‘φ―Λ¬^³Z΅?β}>cύ=b―ϋxn.k6΅ϋgο M[ΆϋΠp[~τ3ψ JμxΟφƒ—Ύβ~nμyŒτσοΎΨίέφ<χΎιy°υγ}*­γ`{½§ΛοSχ {}Έ‘D½ODϋϊ‹τ}ι}R‘B·Q–JΊΏLΌΨΨχ‹ΫφE€W©†HΩ°Χ1‘°β~ξJϋ„²)ξq”φ‰w}"'ή_ιr"«΄_Ώ‰Ϊίφίφώd·›.'^ˆ„Ώž­―‡Hˆ$—ϋsiοΣΎeO$QϋΧ~žύχH€ο'κ罬Ωλ;ώu19ρίΝeHbήΏˆUχ {}0€ψ€ύ@Δ>ŒΛώιιΫΏΒ릃’ξ/ν?}uΐvΐ,nΫ‡ΏE:q•jޝ3[μ>ϋ_»t€ύS^ίΊ!₯ύz³ς«ή*υyBάϊ|W­:2lδ(©„„ήV*±Χ±;1ν;w‘n=zŠύ‘κDΆnΫ*ΆŸνz»vο»δΥ³&Š=_…o+ΔNΪœύ“υzXyόqqΧ3‘^v`ιηΙDϊΉKΤγ‹φη2γpι»½Ύ ―Rά?}υΐΜ].UD:ј¨ŸβφW’Od=ωΤPqΏo"ύ“φH―›d½~΅Ώ]φΎ`ϋί.ιŠΙfϋΟ>,Ω~?ψ–-̏ Dμ„‚}ί>δή=π5φ{~NνDV²^χ&λ.[_‘DzŸŠχ}=QΏ"=‘dκΟ₯+Qϋ·ΈŸ§T=RάχmΏ$ϊη=ΩJz|gC›o«.φΊKΤώˆχωŒυχHΌ7»Λ•΅Ϋο)cž}VμηΜ}^.^$·ί}Ψ ΟNήfaΕύάΨσιη?ίέρž7HΤϋW²ŽƒΣεχ{Iί'μυαDυ>νλ/ΦχH DRDIχ—a βΗ@€lΨ똁HX€Ÿ»dP6‘G²NΜ0)ͺΈύΕ@$,QϋΫ•κΘΆˆ”Ξο_WͺΏ"a ’\±ώ\Ί΅‹ϋyb ’Jz|Η@„HHq?7φa―"Ÿκ7^œwΖg€ο@Δ΄λΤIZ΅ο «Χ¬ϋ…·pΡB±εφ$„ΈΫ)+%έ_.»$IΗ”Ο?ί&φ‡‹}¨΅ύaβώYάώmΣ‘£τ0@rrˆ»\ͺ°?€μC³o­q§4Έ/ΨOί:…•φλΝώϋͺς7ŠύΆtΩ2±εžθί_μϋέzτϋ~ͺ±Χq€ˆύAnδΩώ)΄;±ͺm¬>όPlΏΝ_π‰Ψ‡ΫσUψΆ ³}kά΄ΉΨ₯»άΒν*ξuPΏqιά΅›Dϋs—¨ΗνΟeq£ΡύΝΔ^Οvΰb—Έ―y iΡ¦ΈλΗz`ζ.—*"h4ρώό·Ώ}"Λ~ΞμR6Έ°Ÿ»λnͺ(φϊ΅υ#½n’ύϊuΟyο=±Ÿ{έΩχ§NŸ.6@°K2Έ·_Vή~η±ϋgΎφsΉ}Ηv±KPΩ%퍻=ϋpv:KΑΐccp°K~ΨΟ©}ί֏υy°υ‹{έ›H―;λύHχΧƒ«Έχ©xίΧγ]?σ˜ξΟƒ]Šσͺΰo˜ƒ‡ˆ}Ά½W¬\!vΒθ΅™―‹m'ήύ[άΟSͺ‰φϋ±ώΌ»Ϋ)+‘ŽομRIvI¬ώƒž»Ρ¬7ί”ΒΫ ‰wΔϋ|Ζϋ{$ΦΏ›mύTΡ«O±WΏ§n°_ξrv©βŒ‹oΜ«Χ"…ˆ‰χΏ¬•tΉˆΕ@€lΨ똁‘Βˆύω/n1)Ί\¬ϋ;ݐˆ$φχoΊΏ\ DΚ"%ιψށ" DL€χ‰HμυΑ@βΣ"’φ{ξ?hάvΗ]bΆΎ}h—»~Y³ύexǽĈ}H΅ύαaΏ€μŸ*Nœ4Il}χ›βφοΌωσ₯FΝ{Εώ`·υάεSΕπQ£Ε·ύAδ[Ά°βφG’^oΝZ΅– Uoϋ§ρφύwfΟ»vβ«π6R‰½Ž# DŒύkΛώpr—³―Ϋ?©Ά?dλ5ΎOl;ΆΏέυ¨°Ϋ»σήΪβ[Ά0Ϋn€ΧύαϊΐϋΉ³Ÿ»v»»vν[?ήΗνΟ₯ύw€Ηa—Φ±Τo*7UΉEμcξϋ†‰χΐ,Υw’1ޟβφW’OdΩ‡WΪ°}˜§ΐΫ‡0ΊλχΊIΦλ7Φύm'œμCMνRvnϋΗ.ωeλ₯šζ},v’ɞ?ϋy²Α”{ΒΥe':ήίTl0l—€xnd±νΊ'²Jϋuol;‘^wΩώz0Ε½OΕϋΎοϊ‘žΗLyμPΡΊ}G±Cφ8ξ]GμqξΫ·Wlύxχ―ν§t=Rάχγ}ί)k‘Žομd—`{°ϋCb—Xςm+$ήύοσοο‘xnNv ^»Ÿ}ί²!φ?±ε—-_.ΎeCμyŒτsaΟc€ŸβώξŽχΌAΌο_&QΗΑιώ{Εή'"½»μυi οϋ„}ΏΈΧ_¬ο#*lΒ@€ŒΩώ²_ψΕa "Ιe―c" D c Rtύβφ‘’ΛΗΊΏ3εΔ+‘’ίΟφΧƒa RΆˆ0‰F€γ;" Dˆ01φ>ι}Ψe―"ŸRˆ@Ά³?δνŸΚϋ–J‹°D:`Fz³KΨ@ΚL}Λ@,ψ=‚dβοf υρ{@¦` ₯„;”%X2₯ί#H&ώnRΏd "£―Ώ&―ΟzCμŸ(/YΆTμφα‹Ύm₯…–μπΞ»οΚεΧ\'φ!χΎe $ψ=‚Dβοf ύρ{@¦` 1βΐ©Œ–μΐ@@iαχ‰Ώ›τΗο™‚Δθ‹ν_H§»‰ύ›o«.½ϋυχΓTdΰ€~ ‘ψ»Hό^)ˆ@Œ8°C*γ€~ ‘ψ»Hό^)ΞΈ±ΩlΒ@d," γ1Θx D@Ζc 2ρΎ5Ω°a=@Fa 2ή·"ΎFΞˆ€ŒΗ@d<" γ1Θx D@Ζc 2ρˆ€ŒΗ@d<" γ1Θx D@Ζc 2ρˆ€Œ—΄Θž=»eΑ‚2gΞ™={ΆΌύφΫςΖoΘλ―Ώ.―ΎϊͺLŸ>]^zι%yα…δωηŸ—‰'ΚΈqγδΩgŸυ?~ΌΜ˜1CvμΨ.Ύϋ Θ|sηΞϋ½`ή}χ]ΙΝ=(Ύu>ˆ0€¬Ζ@ ;$m 2oή»Dl=ێٸq£¬[·Nή{ο=±A‹ο># ά/Ϋ¦>!kΊ)¬{Ωφb9”,βΫFΫώζYϋpEY“oϋ›£Ε·N:ΫΏ~‘l;x|-mS{Λφwž•œ[Δ·¬d?Gω?/kΊήφΰ ²uJIχŸ£7Θ+―Ό"ϊӟŠxν΅ΧdέΊ΅Β`$ίΞνr`ϊ$ΩΣρ>ΩuOΩYρβ"μλ{:5‘/Oێχ6RО%oΛϊ޷ʚWžΨƒW„=ΆΊ‹)Φ9_§’VuΌ<¬CQk{ά,{Ύ%ΎϋNŒ‘ΜΒ@δ„ˆ0‰ "'Β@„iͺΤ"ΉsηΚ]»dΫΆmb—&YΉr₯|ώωηRο©sεΐΧςM,Fx9[oΩ²e2ώ|ω裏dΓ† bƒ»ΤΦΎ}ϋΔχ>ΆMν+[Ÿ¬.Η>xDŽηΫ:0ψzΘ”'Δ·L’{0GΆN~TΆͺ+_~:HŽΟλ'[ή.›Ηu—άƒΔ·ΝTvpΟvΩ2ΎSΨ€ͺ²oJΙ™ή2_ Ω=ŽlμSYΆM{Brsφ‰ο6²ΑΆƒύΨχ9φn79ϊNΨ–'‚―ΆNξ#Ύm€²O?ύTμ’X›7oϋ½dlPo—vόδ“Oķ͌Άoμύ”l»υjΩΧΉ±¦όεΝρς?σ¦‡Ν³―ΫrΆήη·^#»Η »ο}Hλϋά*_.|RώΊ~|QλΖ΅φYωΛσLΨκ±E­#^5:leΎ£ς”άΧ:ΘΪξ•ΔwΣс­keγΰΖ²ΊΣΥ²ρΙΰΏΆίΊ™ΰΐΆΰρ"?ώπώρ­ (9" D2 ‘’ˆ0‰"E0"₯ƒH¦RˆμΪ΅S>ώψcΩ½{·Ψ‰¨;vˆ $Œ 6φυŒl=Τϊ„l9[oΛ–-²fΝ±q·ΘϊυλεΕ_”Ο?ί&ΎΗPl€Τ AYΈπSρ-[φ<Ψvηϟ'ΎeΣњC—υΉ1οθœξr읎aoΆ—£ο<(«:^/Ύmd„όK}6¦£μžΠLώ²z‚|ωα#ς՜aŸτ•mƒο’M#ΪKΊ\)gϋfΩ8Έ‘μSSΏΡ!μυ–rθΥ¦rψΥfa―·’#ot”cOΥ—ƒ{vˆο63Ωκ.εεπ[]δhθg'dV9<3Ψ§Uν―ί6R‘½οΏωζ›bƒ˜―X±’ϋΊύ>yλ­·dνڡ⻍L’³y“l©SMv΅¬+_½0\ώ45μλρΛW£ƒχ’‹ΚΊ-gλ}59lWΛ:²₯nu±Ϋυέ§²΄ξ±[δπ»ΚWσΊΛ—u ϋπΑ°χ»Θρχ:‡Νι(Ηή ~…ΌΣ.μ­ΆrτΝΦa³ZΙ‘™-Β^k.‡gοY½γkɚΕwΣ‰½ΏλUCrf< _/~JφΏΨF6 l$Ύmd‚ O6–ΣΫΛΧK†JΞ«eέ£·KΆώ>€Dc Β@„H&b Β@$ Dˆ„0)ЁHbΩϋ+"L₯>ΩΆm«Ψ%JφμΩ#K–,‘œœ9rδˆ|ύυΧRoθΉ²«Ρβ‚fΛΩ@Δ.u²iΣ&Y°`Ψ‡«Ϋ‰1»d—}hο1$Σ«―Ύ"5’~ύϋIύϊυΕΎuOδƒή„τξΣ[μΏνDŸoέt²²υ%ςε=ΕN(™ΡLŽΟξ&+š]$Ύm€³ά}»eΣΠf²{rkωλͺρrtn7ωfΏ4•£―·’/?|T>ϊYί―‘€κ‰˜άœ²eΚ`Ω1™μ›άXφO/_ C wzc9δ8ςΚύao΄—½γλΚƁ΅Δ.=ζ»™hE‹‹εψœΰη%pψ•ϋΔφΧΡ·:Λς&Šo©δ­·ή”—^zIμ’‰φ{Ι.±8}ϊτ"–/_. .ϋ½aΫyγ7$Σ>lέn-/{»Ά‘/Ÿ"Gk+‡^#½‚χ‘ΐΡ>ΝεΨ-а―ΫrλεoΗΆ»χΑVb·›jƒ‘=‹ή’΅=«Θͺφ—Υ._ΫKeΗΈFςυΒΑβ>޽ΧCΆ ΉKμη@σ|ωΏ―Φt©(»Ό)Ύϋ˜rƒχΐ¦a­dί”Άς§`…›σ|½` ¬l]NΌΫΚ«Ϊ^)_=δψϋΙW ΘήI-dγS-ΕφŸo[€β1a Β@$ƒ0a ’vB–"ί` ’ DŠ` ΙUꑍ7ˆ @μ#vιͺC‡‰ DrssΕϋΎ)Ύ!HaΆœ;±K’Ψ 0w b—NYΊt‰ψC2Lš4Iš4i"£ΗŒ’Q£Gʈ‘Γ₯aΓ†2gΞlρm«°χίOlπ1lΔΣ2fμh9j€4Ύ―±Lžd’εM/’cοt‘C/―‘@ξ”zrtf;YΦθρm#•<όσbyϋύ`—Ύ²‡ύ~2φu»τ’}ΨΊ]ϊΡή/srˆοΆΣIξΎ=²ξžΫeg‡ζrxΐ£’Σ²NXλΪ’Ϋ!x=u ^!]ΙαξΑΟR!φu[ΞΦ³νΨvνvvΆo&λξ­.ΉϋχŠο>§„œ}ςΩΘΆ²{|ωΛͺρr|n7qΡ‡CοA/?μ%_ ½W6<Ω\rχΟGΐ{›iμ󗇄5δλ%ΓδΠ+Α{qΰˏϊȁZΚϊΎ Δ·­L°Ύ_πψ^j-_}Τ[ŽΌΌV_}:XΆ Ί;ljπ|ۏ"€‘Db Β@„H 0)"E1€δ*υΘͺU«Δ>€Φ>D}Χ]b’n' μ$υžϊμ::T6h~BΆ\€ˆmίˆΜž=[>ϊθCρ=†4xπ`iή’ΉŒ3RžθΧGμφ€ Τ_ž6Tl0bw»οΎϋŽΨ dθΣOΙ 'Šm·o'Δ#͚5“ργΗ‹»έT—i'r‹“σΕ&YΫσvΙyνAωσŠ1rdfΫ°ό+Ή/6€ΨώΙ™TWμΏMͺ'φaγ»FΧ•U]n•œΟ7Šο>%ΣΏߖ=³†Θξi=dΟ”v²oj«°›Λ–·ΘηOאï΅‘CΣBC³ϋςr_¨φR°Ÿ9“ΓVά‰ψξC&Z~ίεΨ¬φrpR°ηjΙαW[Ιϊη‹o©dβΔ‰bƒ lΨο)S¦Θ7Ώ/Β^xα±~¦DΆ{J6ΦΎKυ{Tφ6¬™οNΩέθ.Yxο-²³iM±ΗΑ6Αk₯ϋϊ`™[owh[ωΫ”FΑmμv7ΦΎCΆŽxZ|χΉ,ά»SμCΏwNl*Y=NŽΝyPl}04„φ’ο“£οv“ΟŸΎWΦυ'©zΙΒ’Ϊ5¦¬{¨‚|υι92³ƒ}£³~ϋaYέξ:ΩΏi₯ψΆ™ |ΆRV5δπ›έεΨ›εPθwTΰˏϋΛΪ—]Ώ.Ύm"c Β@„Hc Β@€40a Β@€x DJ†ˆHRˆ,^ΌHμ$6ΩφωiπτωR{πΩEά7ό|Ωz°Ώ¬άΥψ„l9[ΟݞέΞκ΅«ΔN„}τΡGRV*ή½{7iΧ­<«§ty°³— J† "6±cγY aςΤ`±Α‡o›!=ι)M›6»TŒο>§²L;‘ΙώΝ«euΧΚ’ϋζ#ς§e#δΘ«-δΛΩ]εΠ«mεπŒΦ’;ΉœT[M]6ͺiށŽΛ„δŒΏGOo!»FΦ–Um*ΚώM«Δw“aίͺOeο{ΟΛξΧ„Mλ.ϋ^ι*›ϊΥ’νoŽ–­Οw“Mί(‡_n&'―“@ΞĚrθΕΖ²²ιΕ²oέRρέ—L²¬αrdF+Ι™쏐qwΛ‘©χΛ:ί6RΙΛ/O—qγΖ‰}XΊ @,X vιBcΊnΛΩ€ίΖΣ¦MχCΥ?όπC™1cFφυΒχ-ά±]ίp­μνρ μnRWvΥͺ.»λά.Kή#ΗΦ―•%νšΚφϊwΘΎΖwa__άϊ>9Άa,i\[l»v;»ξ«#{{v•Ε7\#9;vˆο1$“]:pέγχΘξηZȟW=#Gίκ,ƒθό«;ˆ>ψB}ɝ0μ…zrtVGΩ1¬–¬yθ.9Έs›ψξS*;°i₯¬ιrƒ}―OΨ[Θ‘ο“cο>*kΫ_+;?˜!Ύmf’]σfʚΆΧΘΡ·»Λ‘Ј!pτυφrδν²ΊΥ΅²o}π{)ΰΫ&ΰΫˆ0"酁H‘Α@„‘Θˆ” ‘θ0€δ(υˆ²KU}ώωηbˆW?~Fڎ½Roν*λχ<–―—,άZη„l9[oΙΆξξΩ«δ…wŸ’>ψ@μCΦν]/Ώό²ψCiΪΏŸ<τπCrί}₯S—Ž'ΤλρGεΙΑOJγƍΕ$ƒ”ή}ί6B:tj/υΤ;Ρη»―ι ΣNδFb2»{bωϊΣ!rxΪύrτ­NrpzYΩτ9쓐œ‰χ„φMΰΠ΄¦²’ρeίΈrpjSΩ?²ΊδNn(;žΌ]Φ<:YWΛ{“αΰρ;²wφ8Ω=£Ÿ|1ρα°YΟJΑΊ‘“ׁ•­―–}ΟΦ–γο {‡Ψ mγƒΧΙΆ©Γ€π}ΘD60<<½©Ψώ80ζv9ψBCYRλ<ρm#­Z΅Rlΰ»iΣ&ΩΎ}»Ψ₯]βΡ–³Θ₯KΔώ›7&ζΘ+―Ό"ώσŸ‹°―ΫrΆžmηΐύβ»ο₯iλK/Κͺ»ο’½ΫΙwά"ΫοΎUvήSMώΏλΕϊΫ—ΗeaΛϋdk­j²­VuY|-Δ–³ώl#ΔΆk·c·kχcε]wΙΆ©/Šο1$ΣΖ!-dοσΝεO+ΖΚ‘Χ;Θ—ο> Ή3ΪIΔAtώϋξΑ)Ν€ΰχΦΈΠ﬚ƒθνOΥ”uOά/Ύϋ”Šμ’b«»ή&9―> Ηf?,6p?ϊv7ωμ‘ͺ²υ…'Ε·Νl°uJπψΊU”#³:Λώ1wΚ‘™δΐδV²ͺΓΝ’³k»ψΆ ψ" D‘0"₯ƒ"‘1‰‘Ψ0€Uκ‘wί}Wμ“ύ·]zdηΝςκΗcΔŸlκ(σ75”Χί}Bσ75Ÿu’Ž•Ι³‹ d/^,v©¬eΛ–‰]"Εχ’Α>”χ‘GzJ£Ζ€CΗφ±S―G –Ψ‡₯8@νυˆψΦ iί‘½Τ―__FŒ!Ύϋ–N2υDkE‹rrxf'9ςZΛ°Yδΐ -Δ.©aϋεΠτfrΰ™;ΓΖ֐ƒS‰ν—χΫμ~·œμ·ΐ1‘}yGήώgjΙΪ‰ο>&Sξξν²gΡ\Ωωξ‹²kώ;’όl…Έλm}ΎŸl{Ό²δŒ»Gφ¬z¬Ο―(·w;™fiίKnπš±ύ±oψ­’σ\Y\σ\ρm#•}όρΗbΆnƒρ­[·±tιRyξΉηΔό³gΟ–ωσηΛ¬Y³dζΜ™bΛ}υΥWEΨΧm9[ΟΆcΫMφ`di“&²©aCΩ^―Άl«v³|~{U)T΄m.8~L¬Ώ}υ₯|Ϊβ>YΠ΄‘όο±cbύγλ―doΗΦbΫ΅Ϋ±Ϋέ^?ΈMκΛ&χ‹ο1$Eώ uU›ΛελƒδΘΜva―·‘άde³Λ€ΨAτ}ΚώηJξKχΙώQΥεp°LȊF—ˆέο}Lωχoγ“-eηΨFr|Ξ#²oL 9ψBπ{'πΕΐ;e}ίfr(7'Μ·νlΏ6 l)ŸχΎUL¨#{‡?ƒ”|1θnYΧ»‰dύώ€b0a Β@$ 1)ЁHb1a Β@Δ#D5‘bδί?"1Κί D t”Ϊ@Δ>dΦNψ|φΩgb' μ%ή{R:ŒΏJ>XίRζΎGήYY­ˆ9«kΚGλ[K—‰ΧΙψ·„lΨ°AμRYvι“•+WŠ]*Κ.eβ{LΙ`·Δ}€aΓC[iί±ΧΓ=*Β·LˆmΗ.­eχCΣU¦ŸΘ5λϋ6–/ή.‡_λ {ΖΤ“Umo½kIΑ~y±±μ에·IΞσuΕφΛήΥ eE“kδσΗ*ˁ1χΘζ.Χɚ‡κŠο>¦ƒ]ŸΌ#λΫ_%žΉ[φ ­6μΩΡ―Š¬yπnρm+“,Ήχ<Ιy.x]lμ}κf±ύ΄ψΞί‰oιΐ~Œ9Rμχ„yζ™gΔψŸ~Ί@ζΝ›'Ǐ—ύϋχaƒώΥ«Wa_w—·νΨvνv|χΉ4|pcEΩΦ¬™l©v‹lRQΆάRYΆήv³l«VEv·n&ψςΈXχυWEXψςKΩέ¦ΉΨvl»v;·›?μ~}X‘²ψC2­ξz«z­­}ϋA9ψr[YΣξZ)ι zeγΛeϘZ’;%xΏμWWV΄ΎY|χ)•l›>L6χΊUŽΝyDŒ {Θ³χʎΥee»Κrpχvρm3ΩώXΡ¦²|Ρ§ͺΌ~ϋŸΎUŽΎήY6uΊAΆN"Ύmˆ0a ’–ˆ$?" DˆDΖ@δΔˆ$(₯6Ω½{—ΌσΞ;b'„f̘!φακ/ΎψBFΏρ°t•Ό»ς~™΅€zΎj2{ε}eβΥ2jV7q!λΧ―—΅k׊]Ε.‰2yςdΩ±c»ψS2Ω`€oΏΎ aiΣ΅΄mί&& 5”Ύ}ƒν2eb²εDnΞηe}οF²όΎr²ΆW}ΩΩ±εΏ΅_ž*{Cϋ&pΰٚβξ—ύ›V˚ξudΙ½ɚξuεΐΦ bΛ§*»d–έίάƒΑφm\)«š\,ϋGέ!{Ÿ¬(ϋU’έͺΚς&ε₯`»ωΫ9°%Ψn 7gΏΎνTiΨχί}xφ±ύ±o`Ιy‡,Ίύl)Ψnšξ»dβ°aΓdψπα2aΒ±χΙM›6ŠύΫ»w―δδδΘ‚ dΜ9b—h4sηΞ|ΨzΆΫέŽοΎ–†7/ΎR>oΦL6VΈI6εϋ¬RΩ|sΕ0XT­$[›5‘Ώ}ω₯ΈύίW_ΙΦζχ‹­gΫ±νΪνΨνΪύ°ϋυΦ%WŠο1$ΣήσdMNJ²ρduϋJ²gωΗRAτž₯ΑzΝo”ΥM/—•Νn=K>ί}J%Λ›^-‡¦΅’ύΑ}OΏCFά-ΛΏ·ϋ7,ίΆό^μŸΐς—ΛΎΑΥeί›$wθνackΛΊ—‹o[" Dˆ€%"%Γ@€("E1a R DNŒHb1€Δ*΅ΘΆm[eξά9b—Μzγ7dσζΝβ~ˆνΆmΫΔώ{θŒNeβ52sQ°ΕuεΑη•Α―΄–β!+V¬)S¦ΘςεΑAfΰε—§K²ODgώ}¨Q#iήΌ™΄iΫ:*mΫ΅‘vνΫI½zυdοή=β»ΝT’³mƒ¬}¬,kt™¬}€žΈ'ώc=‘k'ώW?XKίυGYύ`m9°e½Ψςι¦`ΏŒ φK`ο“•dί `ίrFέ)ξ~Iw{–},«Z——uν―•U-+ȏfΙڐΓͺΙΎ~7ΚώΎωά,Kλ]){$Λ^#«κ\ +\%»}(ΎϋT–Ύ΅?:\'«Zϋ#°giπΈ‹ξ8GŒΎC φΗ7ΘΑ‘·ΙΒΫ~+ϋ£Q°?+λόQ–ΧΏZRuDbLΫΧνΏ_yε±K`ΩΐcΙ’%²eΛ)< ±―ΫrΖΆcΫuo·΄½~Ρ•²ΉA#Yw}πΪ¬Ο·α†dγM7Κ¦ a«oΊA>ͺSKώvόΈΈύν«―δ£:΅ΕΦ³νΨvνvμvέ―Χ/ξgΐχΚBΑ`1ψβcD{°Ύϋ~ͺ[~ίUrπΉΖ²Xυ°'ƒχΡΐήΑΥeyƒΛΔNψϋΆ…o"Λκ]*{ϋ―‘@Nολε`J’34ψ=XRλ2ρm ΐ@„ˆη6S ‘Δ` Β@$„Htˆ0‰?"‰Ε@«Τ"λΧ―“χί_l b'€l`aƒΈ>Ϋ¬θ7ν~ιϊά5EτzŸlΨl/$Β Δ>μ—€νί6‘}ρΎ‘wΙ‘—ΫΚα™Ιͺϋ’%ΑΎ ΙyκΩίϋϊ°Η“œ~•daσeɝΘ‡ΚΛΑώ7ΛΎ^Α> ,mx£ψξSY*Ψ£jΚ‘W:ΘαY=du“kdQυ³εΰΣΥΔέU•O«ώF–ήqμιq“XUφυͺ ©Ί?’υΦ[o‰]ZqφμΩb—zότΣOΕ~oΩ`γƒή/βε—_[ΞΦ³KEΪvνvμv}χ)‘ήΈŠ¬½£fΨυ7†]umΨ5ΧΙΊkΓV\s­Ό_σωί£GΕϊΗW_aύο±cbλΩvl»v;·›?ΦάqΌQώfρ=†T”­ƒθ­S†Κϊ6WΙα‰ ε@Ώ ’3$xŸ lοYA–7ΛΩ΅]|ΫΜFΆ?–έ“|ήνzΙν[Aψ Ψ%²žθΫG:tl/-Z6/»„Vο>KΫvm₯cǎ²gΟnρέ§²΄€ΞE’3±μ]CŽΝκ&‡^ ^³ε”’žΘ]rο…²«ΗMr°o₯°žΧʁΗn”Oo9W|χ1»_ž φKΐφ‹oi%χ ,­υΙ{\EŽΎΠLΟθ*‹οω£PYXNr{XXυ±ϋ὏ΙδξgkɁ!UεΘ‹ΝδπkέeIΝΰη"pπΙ*β}+JΑ`±η rθρ›ΔφΗ‘Η*HΚνzώωηeίΎ}EΨ~υκΥςΙ'ŸΘϋοΏ'ξvή{oΨrΆžύ^t·o·λn'ΡζΤk. n¬"kΚW”U—]%«Λε»βjω°Ζ]ς?GŽˆυχγ_Κ–ϊ esνΊςχ£GΕϊίγΗεγšχŠmΧnΗnΧξΗ‚«Κάϊ-ΔχRQΆ’νη|}οf²΅{94Ί¦x,τ»5ψ›{gK‡kdMΖr(7'Μ·νlΏΦ=ΪDΆ΄ φO ·OΙyθ 94πΩάζ*YΣ­‘dύώ€b0a Β@„HΑ‰)" Dˆ|"±` Β@$&ωϋ”ŽRˆ|όρΗ2oή<±G.»TΘ‘C‡δΨ±cbƒ;1΄{χnΩ±cG6H±ο8p@Ž9"ΉΉ‘ΘΝ-ψ0[w²rεJ±K•ίc*M»wο’ΪKσΝε‘^=₯M»Φ¬ES―ΖMεk,ΎeBZΆn!=ν!mΪΫ ΄oί^μ~ψξcYXέυ^ΩϊHeΙ}Ά–μλ_QŽΎ^Ώϊ€,½χ)ξDξ’[+»ΎAυΉQ>PN=|-°ωώ‹eE«;ΔwӁp³Pϋ₯ηΥbϋεΣ›Οί6Ρڞδ³WIξΘ;$'xCŽNj&‡&·‘ƒ‘αF §ϋaέΚΙΑ―½^'Ή^/9.“Γ]-›_$«:Χί}*KΆ?6wξkΰΠθ»%§Ο rtrs9όB[9Ψ;؁oνΧΙΎΧΛ‘GΛ‹νC_+›??Tέњ8q’μΩ³§ΰΫή~ί͝;GάνΨΧm9δΫvάνΫνΊΫI΄Υ“§ΚWW–Υ7U‘ε–“‡­Όδ ωzΕ*±ώ~μΈ|voYuωUEΨΧm9ΛΆcΫ΅Ϋ±Ϋ΅ϋρΖΥ•dΥδiβ{ ©(λюƒ{vΚςf•dg―›εΰ [ΒzΏ{‡‡Τ5 .’ΝΟφί6³ΑζgϊΚΪϋ.‘ΓͺΚΑ/—άΗo’^/K„qΙ1ˆ" Dˆ0a Β@δˆ0‰"±` ₯«Τ"οΌσΆΨ‡ΖΎϊκ«²fΝ±HΖN Ω Γ"_}υ•όε/‘Ώώυ―bύ§?ύIŽ?.ϋχο—mΫΆΙͺU«Δ„,^ΌXήxγ ±K˜Ψύτ=¦°sgh¨³#―uλΦ¬y3ιώP7iΩͺ…4mvΏW£F ₯vνΪR·n]iΤΈ‘ψΦ iή’™tνφ ΄lΥRμ~ΨύςέηdΪΏa•,k|­l{Έ’Ψ‰ν}ΚΛΡ)-εΘ”vRά‰ά½]ΓμDξΑΞ—Ι‘žΧΚ–¦Ιβ»ΚΙΎu+ΔwӁpΛνWIΎ΅_ φA`AΕ3Ε·t”³}«¬hu«|Φ’œr›δ>n―‰G―—ύ”“ƒ―‡Ξ—ʁv—HnΗ|ν/–C]―’Mυ.₯*KΞΑν|χ©,}k΄ φGΰπΠκ’ΫλzΙ {N°?φ·ΏD?3!ΉΑr¨[°?›κQReΨο™qγΖΙόωσΕ]ξΣOΘ΄iΣdΫΆ­ςϊλ―ΛψργΕ~oΨο»δΥΪ΅kεΕ_”9sfΛμΩοŠ}έ–³υ쎢]»»]χ~&ΪΎν;δω ΚΛ§ΧW‘₯]φ‡KeΩω—Ικn–?-_)ξΌWl‰-gλΩvl»v;v» «"Ορ±ϋι{ ©([Ρύλ–Λ{.‘ύ½o–ƒο»!έƒ}Θν[UΧ8WΆΏ=M|ΫΜD;ζ̐ewž'φQ χΛεpπήrΰαΰοžΐ’ΘήU‹Ε·Mΐ·1Ι?Ε@„" Dˆ0a ’( DΒˆD‡$G© Df̘!Λ–-“%K–ˆ²ΑH΄l`b'ŒmΟv ,wβ²ε-Z$6 ™2eŠψSihΥͺ•4iD:uξ(͚7•&χίηΥ a}©S§Ž,Y²XV\!υκΥ“† ˆo!χ7m";uϋοΏ_l0β»ΟeαΐΦ ²όώ ²ΉέΥrhΘm’Σγκ°bNδhv¨SΨΑΛαξWΛζϊΘβΪΧˁΝΑν|χ)|ZωΧ’Ϋ«ΌΈϋ%χαkδ“%Ύm€³ƒ»wΘΚφwΙϊ†Κ‘>$·λr°Σ%’Σφ’°ΦJn[G—ΛeνέηΚςζ·KΊ\²δΫϋγ"9ά·’ φEHqϋγPπ5 ~ΦBΦΥ²Ϋ3φu[~λΦ­bΫ±νΪν~ ΙπΙΐ‘ςEε“+n–yΏΏJζŸWNœwΉ,ό}Ψ’ί_&‹‹aΛΩzΆΫݎέξKW’CF‹ο>§²lDG²}φ«²€ΖΩ’σX°O‡ΊοάξWɁ‡‚ί½Ε·Ώ‹ϋΦ.ί63=ΎΕ·Qφwώ† ~°œδvΈ$μαkeΙ-Ώ•νοΌ"Ύm"c Β@„" Dˆ0a ’` DŠb βΗ@’«Τ"&L”H'ŒR ^F-ΎΗT&Mz^4h 7”Ζχ5ςͺ_ΏžΨ%²lβnΧ#v ­ϊ ‚υΎm†ΨνΪς&Œw»e-gΗ6YΡς6Ωx₯r(t7`:ϊ­Ή­.”oNj_$‡('λο>W–5"9ΫƒΫ ψξC:ZPαL±ΑGn‡‹ΓΪϋ!`'΄?Ήώ ρm#δΨ'kΊ7 «yžκy½Ψ%±΅ώcX«σσ](‡;\&«ͺύFV΄«-Ήϋφˆο6SΩ·φΗ½Ώ—Cή ‡;^*ξώΘmυG9Τ1xέVέφ[IΥύ±xqh轨`ΰm—Ί²Έ]2qΧ]bύ₯K—ŠmgέΊ΅ςάsΟ‰ύ~³ΑΖ_|!Ά»c_·KCΊΫέNαǐ 9ϋφΙ€kΚ΄?V”ΉU’ΩΏ»Fζžs΅Όχ»«δύ|όξΚ²εl=ΫNΑvσogκeςMχΘΑύϋΔwŸSYΆ’#ωlτ²ΊζοεPΰύ7DCΦΐWΘM.‘ε-kˆo[™`E«;e{σKΔΏ½ο~πJYYύΩ4²ψΆ(‘| Dˆ0a Β@„H"‰ΐ@ďHQ D ΉJm R₯Κ-b—^²K;ύς—Ώ”‹.ΊH*W,΅jΥ’ζΝ›‹έŸG}Tϊυλ'O>ω€ 2€ˆAƒIίΎ}ε±Η“GyDzτθ!έ»w—]»J—.]Δ.]U­Zuρ=¦τκ«―ˆ :l€Ρ°Q©W―Ψ~Z΄h‘ψΆU˜]ΜΦ―›ΟΆk·cΟΟ‹/NίΆRΙΑ½»du§Z²φωrθ‘Δ.1Qά‰ά5·ώV–7―!ιrΙ£’ϊδΖ3ε›-„εο—C‘ΜΏφtρm#“Ψ `mΟζ²’ΪΩ’ΫΉœjμ“ΐαζa‡Z_(++Ÿ%«»5ێο6RɎΉ―Ιβš—Λ‚›Ξ;ϋɍg„έΆ’z°?―—V‘ΧΚy‡[„εΆΉPVήμΐΌ«ώ«¨+‹ZxΛE²ύWΕw“Α.e—Δzν΅ΧδΝ7ί»t’]RΛ]½χζŠ}ΨΉ;Pw/‰e–nμ뢜­gΫ±νΪνΈ·_ΪΨ/›W’ηW’ηΞ­(3ΟΏ9μœΒ~s½ΜϊνuςF1l9[―`;ωΫ}>ΈT–-+W‹έ/ί}Ne *ώZ=|Έƒθά‚χ›Π Ί|π3πm#εΜ‘UλΙΖ:ηΛ‘N—‡5ƒξpΉ|rΓYβΫV&ψδ¦ίΘαΞWˆ=ώ£ν/‘Mχœ'«:ΤΫΎmŠgs" Dˆ0a Β@„" Β@ďHQ D ΉlξπH:u₯nέzbςύ«_ύJ.Ήδ©T©’Ψ‰ώ¦M›J§NΔO<ρ„ 8Pl02`ΐιέ»·τμΩS܁Gǎ₯]»v¦MiΡ’…ΤͺU[ξΏΏ©ψSi²ѝ5k¦Ψ`€vνZωΒm'Κ6mΪ(6¬χΪΈqƒ|φΩ&ωψγΔ.‰U§Nm±ύξ~xpΊΘ=°_Vwo"«n?[Ύ9ρˆnω)8‘[ε,YΥ₯±€Λ‰νX}zλωr ΥERpΒΏΩοε@Σ°•Γ|ΫΘHΉeΓ€²¬β―ε@γσ$§ρΉ²΄Β―dνcν%έNH-Ύϋ29Ποn9ώΜύEm6ζΎ°Q Δ ‡›žvΉr΄υΕςεπE=mκΛWCλɁf—Λ§7Q|χ1μ’TσηΟ—Y³fad»΄–»ώώύϋdκΤ©bο›&L(bϊτι²iΣ¦"μλξςΆΫݎ{ϋ‰fΏwφξέ#_|ρΉlήό™,Ÿχ‰ŒΊςqv™όΫΚ2Υό¦bΨY7…ύϊΖ’μλΆ\ώz“{³ Ά2κͺ;ΕnΧξ‡έ/»ŸvΏ})•,¬φG9Π>xύμ’PΉmBCŠޏ?­ςρm#“εμόBΧΌFΆΦ>Oμ…›kž#ΛξΏ]|ΫΘΛ›έ.[ο=W·ΉXΆΥ:WέuΨώςm=" DΔNΘωξ[*c "0a Β@„H)a rb DΒˆ@r•Ϊ@€}ϋR½ϊνb'βνVv‰«ώύϋ‹ >zθ!±6vι¬^½z‰ύ· @Ίuλ&:t»– Krš] ξƒΨ‰νΥ·”άœύβΫf&Ω0°›¬ΊωΧr Ιο%§Ρy²Ίβ™²Ύ_Wρm#l~ζIYPιa/Ÿ$ΎuΑβ;.‘½m―’C-ώΦόχβ<7ω]XγsδH£| Ο«Ϋ°zΏ‘£uΟ «ύλ°Zg†έϋ+ΩsΫΛ‚Šˆο>–&{|ρΕΕ>ά|Ω²eb—:tθΨϋν7_/Ί=XΜ™3[Φ]#φ~9bΔ±K7φu[ΞΦ³ν$kbμ~Ψϋ½;Y·n,~§„Ότ@oιΦ 2ψ7dΔιacΟ¨$Οώκζ"μλΓOΏIl=ΫΞ΄}ΔnΗn7έ"ž ήw«nϋδ΄όcXσΰχR`U•3eύ€ΰ}7ΰΫF6Ψ·~•,kRMζ_s¦,m\Mφ­_-Ύu3=Ύˆ]°Ύu%Η@$0ΐ@„H&c " Dˆ0I"Ρa Β@’©Τ"φa΅Χ_ƒ\}υ΅)­B…J2oή<ρ=¦“s@μD $l0b—Ύ²g«V­”•+Wˆ :ΜςεΛΔύΊ-oλΫ '»€ΦηŸo“;wˆ˜ΛΝ=(ΎϋžΚ2υΔv¬μbλϋ=( *œ'Ÿάt¬{βΙτK‡e«οΐEΥ.‘H~>οŠ_†• ϋψς_„]ζΈτΙG—δ»8ίE?χ²AΘφ·^ί},MΣ¦M“O>ωDfΜ)/Όπ‚Ψ Δ!«W―–·ί~[|Ϋ<‘—^zI† V„}έ·N*°/ί½{—Ψ ΒζvIΖ Ι¬AcdTΥΖ2ΰχ·Θγ§__Δ€?_ŒΊ₯‰Μzr¬Ψvl»v;v»v?υCΥ ήwσ *ο»!Γμύ˜χ]’‡H>" D2‘μΖ@„H4ˆ$RO© DŒ] ΚNΘ/Y²8₯Ψύ²ϋι{ eΙ. b'„lP±gΟnΩ΅k§Ψ Γ‡ύ·P²εm}Ϋ^Ί\zbe'ΨνΓΛ,X ξrK—†.CΈ4οΝ7ί[Ο].[Ωο ϋ=bƒόHΏŒ}έ–³υl;όΙΒ@„'’d4"‰aΏ/μχnJ} PΦˆ€ŒΗ@d<" γ1Θx D@Ζc 2ρˆ€ŒΗ@d<" γ1Θx D@Ζc 2ρˆ€ŒΗ@d<" γ1ΘxΕDΦ­[Vάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάyqάy‘FΌΦNΊ=WY^š;DV―]!Ύu@jpη D"` @ϊrη DsL—~Σο’ΝFΚ„χšJΟΙ·ΙΒεŠo lΉσ""€?wήΑ@$ίΪu«₯χKwΛ/ϊɞγOJΞΧεΉ›Ι+οίΆ|-ϊT.½κš"fΚ)Ύu@lάy‘| DΘξΌƒHΎΧ?/CgΥ•}_–νGΊΛ֜aυΉJ²|ΥBρmΛ‡ΙγΞ;ˆδc @ζpηY?Y½v…Ψ‡₯―ΪΥWΆyXφ~9TΖΝm$SfίΆN„ΙγΞ;ˆ0 γΈσެˆΌ4η)3»l?<@6|@Vξx\ΊOΊYV­Y&ξv>ψπ}©ίΈ‰\{γMR£ζ=2tΨΣRά@dρβEςPϞrΛν5δͺς7J΅;ο’'‡ ‘΅kWKαϋRΎbe±Ϋy¬O©Σ ‘ΨφͺίUS^š:UΊυθ!ΧU¨$ΧW λψΐƒιφχ9ΔΦ·ϋ}ευ7Θ-·ί!={υ’eΛ–ˆ»Αw0a Β@qάyGΦDV¬^,ݟ«$+v<"λφΆ•-{ΛΰΧο–>#ξvV―^)·ΦΈSlρψOΘ’%‹€m‡Žbί76±νΤ¨YSμϋ>ώΈ,]ΊXΪwξ,φύ=$ξύr"wή[K.\ έ~XμϋΖ- >] ε+έ,φύgƏ»U«Vˆ VlΉΗ‚ΗbχΫ½½{κΦ“5kVIαϋ@Όάy"E0dwή‘1‘•«—ΚSkKΟͺΙ‹f‰»ό„·{Ι³sκΚΊ=]eΥΞΦ2wm{ytJ Y»n΅ΈΫ™:}ΊΨ‰~³tΩR±εήzϋ-q—³Θ S¦ˆ}½ά΅ΧΛΚ•ΛΕΆσΖ[oˆ-wω5Χ‰{ *w 2xθP±ο}φ±ο_vυ΅βή^­ϊ Δ–³A}ς”ΔέΞςεKΕ–ϋxήΗbΛ™―½&Ά‰ΰΞ;ˆ0"€LβΞ;2f 2tF+;»–Ό½²…t{‚ΜψpŒ,^1O|’,Ϊ9lk#YΉύι3΅ΊΌ=%ρέfΘ¨1cΔNπΫ‡•»Λ}ςΙ|)< ±ΘΠαΓΕύ~΄ήύΨνΉ‘gΖ=+φύρ'ˆ}Ϊ›*Š}ίΈϋpvϋΎ{Ώ―Ή±‚ήFˆ]ZΛ–3ώ/ξςΔÝw0a " D™Δw€ύ@䍏'Iοi·ΙΒ-νdΑζ¦ςώΪλ₯[€Ηδj2α½Ϊςι–¦ςΙζϋdϊ‚ϊoZ]ρέfa‰Ίd–{ι©+―ΏAμΓΦ ίf4’5‰χ’Y―Θ!Ά‰ΰΞ;ˆ0"€LβΞ;~ ςή§―Jχη*ΚKλΛGλΘϋkkΙ‡λšΘ˜wkΘ‡kƒΌ·ζnωh}ι>©’|Έh–ψn³0Xάr{ ±ύφαγK–,’Ά:Jαa@ˆ Dl;·ί]Sμϋ?ϊ¨Ψ‡¦Ο›±<3~œ4kΥZάϋ•¬ˆ] «ΪwIΑrΑcYΊt±t{ψa±οΧ¬SWΦ¬Y%…o€xΉσ" D„ “ΈσŽ΄ˆ˜w?yIΊN¬(“>ΈSζ¬ͺ-o―¨!sWΧ‘wWޝ―¦Ψ δ©W[Šο6Nδύή“zΛ57ή$ΥξΌ[†<ύ΄Ψ@ΐΨ@ΔΆ³xρ"ιρθ£rk;Ε.‘U₯Ϊν±K™=η])|_B’51‹}*6ψ¨ZύvΉςΊςR΅z ± ŠάνξΌƒa Θ$ξΌ#c"fΑΉbžώτ·ΘKkΘk‹«ζ«’οy`όMςι²χΕ·mάy"dwή‘q³lΥ"ι7΅<1­’L›_E^^6πΥJ2φnβΫH/ξΌƒ2Ž;οΘ؁ˆY³v₯ŒšΩYžTAF½}½<0α&YΆrψΆ‹;ο` Β@€ŒγΞ;2~ βš:χiι<ώ™φήpρ- “;ο` Β@€ŒγΞ;²n 2Ÿ;ο` 2Ž;ο` 2Ž;οhΥͺ•0Ýw0ǝw΄nέZˆ€ŒαΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;ˆ€ŒγΞ;J} rϋΘρ2η{m2—;ο` ‚¬ΰ{m2—;ο` ‚¬ΰ{m2—;ο` ‚¬ΰ{m2—;ο8ηœs$β@dξάwγβ;9 $›ο΅ Θ\ξΌ£Q«Vy­ DΡ|―M@ζrη‘aΘ "ιvνΪΒ@d," γ5iDˆ€ŒΕ@dΌŽ; ±ˆ€ŒΗ@d<" γ1/a‘Ήsί(UΎE4ˆ€΄α›QD#α‘Ώώυ/iΕmδ—#€€ΙΦ ΜFDDDDD);nπΝ(’Α@ΔΙw ”–l͎\DDDDDD‘²γߌ" Dœ|©@iΙΦμψΑEDDDDD);nπΝ(’Α@ΔΙw ”–l͎\DDDDDD‘²γߌ" Dœ|©@ΪΨ?Fƞ΄)μβeβ]I7Ή} ?­½ψ–Aό¦Τ$^l+ΎeNdϊ%‡]xa£φ=%Ύu2Ι”z•eόδΦβ[&=ί―ΎLzψ^ρ-x_Θ Ο?QO&o"Ύe ΛΦμψΑ•©}χ»ί•“N:©ˆ―ΎϊJˆˆˆˆˆ¨ψμΈΑ7£ˆ'ίA*6ˆ€4"ΙΑ@$> DβΓ@! D’ˎ\™""""’ψ³γߌ" Dœ|©@Ϊ` ’’Ζ.ν%S+_#£ŽŽί²ˆ_’NHώ| 0ρ/—ˆ Fο$Σ-'£vί²!ٚ?Έ2½ύϋχ """"’’gΗ ΎE4ˆ8ωR΄Α@$%1I."ρa "a ]vόΰΚτˆŞ7ψfΡH»Θ!ƒΕ Œύtί:'βf¦£–<'c*}*csŒ9s•ŒnυžŒάρLX‘ƒΪDύθΫb'ΈG!ΎeitΛΉb·;κ•iβ[φDΚκώ—•QλΗ‹=ή§lΛPŒ4KFΦ ρl+& DR€‡ξ‘η6ί2'2α™fςμ{έΔ· ΎΑ@$μΩ’©―ί2> DβΓ@$³ΔϋώϋB‹j2a\ ρ-’­Ωρƒ+RϊΧΏdΐ€rφΩgΛ©§ž*•+W–Ν›7KͺΖ@„ˆˆˆˆ(φμΈΑ7£ˆ';0e Β@$ DΰΓ@$Ήˆ„1ρc ‚’` RΊΩρƒ+R DˆˆˆˆˆΘŽ|3Šh€έ@Δυϊλ―KΒ"GƒΣ€ >Ζόn…ŒΪ<.lΟΨ°a―‡Ω‰mΟΑm"0I/ξ@dΜ ‹Δ^7£»Ώ#ϋ£λ»βΫVLˆ€–γ#dκuεδ™y=Δ»l!“»Υ”q³»JΑ ΉΉέdΒ mdβΣχ‰oٌH?"8‘DΏN˜ΠR¦ΤΏY|Λ„dkvόΰŠT·nέ䬳Β ȟόg±ξΧ―Ÿ€j Dˆˆˆˆˆbώ|3Šh0qb Ζ@$6 DP‘2Α@$Œˆœ‘δfΗH1!""""";nπΝ(’Α@ΔiΤκ‰b'”Η\½XJ|i£ΟΖɘ;η…ύΏ5aΏΜwοΗ2jλ8±υlπPpB»8₯tΒ;ցH’ξ¨ΕΟΛθjσeμΟΧ†Ί^ΖTόTF™ζ¬ol3ζΒe2φGΑϊ1ΧΟk`Τ‡“Ε·n," D –96Jμu`gdξθ0[.ΖΧΟ·"Ώ]%cn$μΗλΒ.[*#>fληϋέ`ݐ³‚υφυo=ΎŠ ₯πΊZn^°_c. φ{ˆέnυωa? ώ@ΑγwΦΟcΦ?!'Τχ?%Ύe uπiynp#yιΆλεΕ»o’ Ο·’‘G‡‡yΆQ9CεωήuΕN¨Ϋ`gR·šιρΨ υη5”)uƒL+w©ΌΠδ΅wˆΈλή_&wΊS¦]sΉL½αJyώ‰zιρΫ ιη6”—nΏA¦]l'0Ή} ‰tϋ&ցHΌϋ/VcVχ»ΏΕ±Α€»xŸΏ²zόfτgύdJγͺ2νŠΰ~μqMκ|gX„HΌχ?ήןέΟH©ηžΎO&· ΆpΏ?zλyαΎͺ2=xΞBμ„ό€ο‹πψγ]?QΟδ–ΥdRχ`ωΐ”†UdΪε—ˆ½ŽΗ½ΡE|ۈE’ίŸYΠSμ~GZ/[³γ—ΫργΗε?ψΌϊκ«RŽ;&υλΧ—Ÿόης«_ύJ|πAωΫίώ&n{φμ‘zυκΙOϊSωε/)Άώ?ωO‰T’"gžy¦Τ¨QCˆˆˆˆˆ²!;nπΝ(’Α@Δ‰H‘Ψ0Ι_ށˆ0a Ο α’b Ζ@„H<ˆ$7;~pΉ1ρΗ@„ˆˆˆˆ²1;nπΝ(’Α@Δ©ΰ„rώ‰σ‚Ώε–Θθη^•‘‡G…9΄φυ1,“±ΏX+#WL”Q˟;Αo'ζ# \²υ’Yc:Ο–Q/M—‚―Ο??φδ bzο?jό«Rp»΅>ΫΞ¨UΑs°KXΉλΗͺ؁HΎ1εƒ―l9Εύϊq"Άύ‰―„}:Il=ΉΈ―Ώ˜"‡FΛΨ_­δΨΰjtŸ7₯ΰΎeψ@δُ–‚aže|μ„άΔ!δ['δ&΅–hOΘ•”0ž¨ŠΨ€bτΑςB»ς|{Ε]ίNθΎtλu2vέ2zη“ςbdβθ¦βάSeά›]dTn°?c6τ•—ͺ•— Ο΅w};!=΅ΒΥ2vUo±Ϋ/8±›aχξϊ&ցHΌϋ/Qβ½dV¬Ο_Y?~ΰœxΟήlΨΟc€ϊρήx_ΆcˆΨΰΐŠ6x±KφΩ`+γwύD=6±ΫχΦ22x/Ο:‰θχ_{ί²χ{ΈΛekvόΰr{ύχΕ‡–’V·n]©Z΅ͺ:tH>όs9όσ%%·{μ1™9s¦όΟό|ρΕbλ3F"Ε@„ˆˆˆˆ(φμΈΑ7£ˆ'"a DbΓ@„Ha DˆΔsB8^ Dˆ0)9"Ι͎\n Dό1!"""’l̎|3Šh0q²ΣQoΎ(φ‘κ'pΝ―W‰]¨`½·^[ntσχΔΎoΖΤύHlΉQ+'Š»\ΆDŠ3ζΛeμ7Θ·ΎΥ)Έξ₯₯JIΤ‘ͺ €ΰώ͝ολΗˆΨ@Ε]ΏJpϋ‚υΧNϋ~¬‘Q³ƒΗ(ψώύˆ}δΑΡR°}"^Ε}¨―(Mτ‡ͺήχ”Ψ‰;;‘λ.7vωc25t«€ϋ};‘ϋά°&β~Ή Δ.½γ~Ώ8φΈνCξχν„΄ΠtΏ?ξέ`Ώ"έSH’φ_’Δ;)ισW֏τŽAb·?fS?q—³ςξ ύDέx_ΆK:±ν?D|αuC&·»]Ύυψγ]?ΑΟΏ D&υ¬%ΎeJC’ίΗϋ0Δφ‹νgwΉl͎\n3fΜ όλ_«M›6bί7ψΗ?Δ.aυ½ο}O.\(nΟ<σŒ\rΙ%Ržxβ ©]»ΆD*Q""""’l̎|3Šh„†!šΦf bف)"±` Β@€0" Dβ9!/" Dˆ”‘δfΗ.7"DDDDDdΩqƒoF΅Λη]tΖ D,χΥ>{τ«ΣΔ.UpΒχάbˏσšΨχ£5jζT)rΫ‘νeΫ@$M£{Ό#cΟYf—xΚߎΛ.ΥdΫσί«eμχ6J‘Ϋ(EQD"\2+ξ׏;±Kb9·?Ίώ‡R°Ύσας1DžEμϋ£žΗ€}ߌύιΊ° ˆΈͺn' }˞HΑ ΉχΊ‰o™D°˜v£5κΐP±νΔzBΧ<;»«LΉ·‚L»ς2qoχ…f·‰»Ύ.ψπcηϋc—=&ΆQ‡†‰»\I"‰Ϊ‰ο@€€Ο_Y?ώ±+Ϋn€K+=xqOθ'κώΗϋϊ‹yGϋψσ?μό[?ήυόόΫ@d⨦β~?Yβ}εCΥOœ?Έά/^,6@8zτ¨Έ-[ΆLl9ˆδζζŠ}}ηΝβφΦ[oΙ/~ρ q{χέwεͺ«’ψΗbΫ5ΥͺU“H1!""""Š=;nπΝ(’qΖgδ]t[S"–{€Κ@$ώ1‰ "…1a H'„γΕ@$Β }" DJ€HιfΗ.7"DDDDDdΩqƒoF3.Ί-―i‡ D,χυ[rG˘―;q<ςhπ½ΐ¨7^’‚f‹w[Qέλm)Ψ^Ί DJxG͘*ΆΌ  Fm'60sφJ±εμy±ν€μ%³ςlc~ΉF ωΈ_?ξ@$ΦKfε’ΖœΉJμλφaτΆή·"oΏ(ίΟςKf<>B¦^WNμC‰½Λ¦;αo'*#]Ϊ₯8±žΠ΅3žvΩΕ2nz{±―Ϋrv)’šή*φuc'€#]²Θ.φΌΈί7£v–hχG’φ_’Ψ%ΫμΓ½}ΛψΔόό•ργ·Ϋ³Ϋ/ι%³uγ}ύ½Πδ™0…ΈίΎWmqχΏϋψνRM…Χ ‰φ’Y%]?ΡΟΑ@$Β‡χ§‹ [Šύ\ω– ΙΦμψΑεφε—_Κ©§ž*³fΝ·H‘x/™υΧΏώU~πƒΘ”)SΔΎnυκΥKn»ν6‰Τ±cΗΔξ§}Έ;Ÿ7ψfΡύλ>T½PΎƒΤ"ˆ”" DˆΈίg ’ Dˆ0){ DNœ?Έάˆ‘eΗ ΎE4ˆ8Ω‰α1wΟ“QοΏ v’yΤΑΖώ`ƒΨ‰χ‚ƒZ˜œ·BΖώΧ)ψπυœΰϋQΫ ŒΉ3Έ@αƒβΒFz]μsΑ ςόλΎu!a‘ή»[~̍ eδŽgdΤδ—ΕΎo܁ˆ ^μϋφ!δ#wΫ ŒZϊΌDΊ€S¬" DFν+£»·°ο~ ؁‚mΔϋϊq"ωμRV£;0φ”ΰυςϋΰ66h²νŒύυͺ°οo”‘λΖΛθ>oŠmΧˆ zR{Ε]?Φκ£χ ‘ι]$φ!ΖvI!»τŒΰ/n b—гΊ·Œή9X¦4¬"Ο?RKάυ]Ά /΄tω– ‰w%Š]²mΪ%ɘ•‹oΩΒb}ώLY?ώ)υo–IέkŠ]ͺΞDΣ/ΏTάϊ&ήϋολΟ.IeˍΪ;D >ŒόΖ«$ώ·υμqΨϊΟΜ{X¦]q©DzόρoλΕϋόgΚ@Δ.ν7a| ρ-’­Ωρƒ+R<ςˆœsΞ9²dΙωŸω™~" DR ‘gΗH1)""""ΚΖμΈΑ7£ˆFΪ Dή|σ ±H~ς“Ÿˆo…ΉΩ‰αΡ^»dΣΨn»ΤQΑ‰θόΕί:Έέ|-0ζޏeμι«Ε.΅5ζϊE2κυ©ς­υΝή±2¦Β§bχ£ΰ„ςΕΛΔ»n܁HqFM.ίΪVIοΏνvsdΜ φuΘO‚}μσϋ°oێ;1£FΌ&c.X&v~ΜΥ‹eΤ'“Δ]/Vξ@€@ώ‡ΒΉ(ΈΡސˆƒ­X_?ξ@δ·Α> ŒΉνϋ£ΰρ‡δοχHΤ€W€`°ρσ΅bƒBΫώ·"Ά~ώ qΜ—‹έέ{>νρΈλ»} 2vi/y©Υ2κθρ-› μCŽŸ’žL­|L»ϊr™άͺšΨ‡(»λΗ{BέΦ³ΚvΫ Οχ«/Ε DžΠ@^¬^^¦]u™Lξx§Ψ‰rw}Χ³sΊŠ=vI Ϋ?ξςρξΏD+Έω—h*ΈωϋΡ]>ήη―¬θ-ύε…ϋͺΚτrΑλ'P0(ΙPF:‘ούχυ7zλ±ν|λυXm‰΄mύo=~tt­)“­-‰^?QΟΊDFo$Σ wΐ.Αη[6$[³γW€μW}ϊτ‘³Ξ:KN9εΉτKe€IβvδΘ©[·όμg?“3Ξ8C:wξ,ϋΏ+nγƍDΨνΪ€[·nν@dΜ9bΓŽcΊtι"ΕΕ@„ˆˆˆˆ²1;nπΝ(’Α@Δ‰H‘Ψ0Ι_ŸH DŠ~ŸHι\χƒ"IΓ@$ΊμψΑ)"Ec BDDDD٘7ψfΡHϋKfΕΛΝw Aς^’sWˆwΩ 4ΉΓ2~j;ρ-₯iRη;εΉχ‹o™‰wύla‘η†5ί2…ekvόΰ""""""Š”7ψfΡ` βδ;H Dˆ(S D’ƒHtΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο @Ɍξύ¦ŒzϋE±Ky~z¦Ψ%·μlΎmJn܌ŽaΣΫ‹]šλ™O‘©Χ\.cΧτ‘D―Ψdkvόΰ""""""Š”7ψfΡ CˆΚw  dˆ@Ω` ’ž²5;~pEʎ|3Šh0qς€(‘eL•aωž>Φ>Ύρ2rχΨ0ί6%6jίS2Ή[M±Ζ‹·]/6ππ­οϊˆMΆfΗ."""""’HΩqƒoF "NΎƒT%Δ@Κ‘τ”­Ωρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο (-ٚ?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ωR€’­Ωρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒ%=;~pEʎ|3Šh0!""""’€gΗ."""""’HΩqƒoF "DDDDD”τμψΑEDDDDD);nπΝ(’Α@„ˆˆˆˆˆ’ž?Έˆˆˆˆˆˆ"eΗ ΎE4ˆQ³γQ€μΈΑ7£ˆ"""""Jzvόΰ""""""Š”7ψfΡ` BDDDDDIώ\DDDDDD‘²γߌ" Dˆˆˆˆˆ(ιΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QD#ν"³gΏ+Χ_½όθG§ΚΩgVϊχο/Ύu}ˆˆˆˆˆ(ωΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒ%=;~pEʎ|3Šh€έ@€zυj2wξ9|ψ|τΡ‡ςγXƏ/ΎmFDDDDDΙώ\DDDDDD‘²γߌ"Mš4"DDDDD”΄μψΑEDDDDD);nπΝ(’‘v‘βάvΫm€Ι}β[¦0"""""J~vόΰ""""""Š”7ψfΡH»Kf‡QκgΗ."""""’HΩqƒoFŒˆ?~LΞ8γ 9r€ψ–-Œˆˆˆˆˆ’Ÿ?Έˆˆˆˆˆˆ"eΗ ΎE4ˆQ³γQ€μΈΑ7£ˆFΖ Dš7o&7άpƒ|ύυWβ[Ά0"""""J~vόΰ""""""Š”7ψfΡ` BDDDDDIώ\DDDDDD‘²γߌ"i?yθ‘ξrι₯—ʁϋΕ·¬%?;~pEʎ|3Šh0!""""’€gΗ."""""’HΩqƒoF΄ˆ<όπCbƒ}ϋφŠoΩ!""""’δgΗ."""""’HΩqƒoF "DDDDD”τμψΑEDDDDD);nπΝ(’‘v‘ξέ»Ιe—]&ϋχοί²Ρ """"’δgΗ."""""’HΩqƒoF "DDDDD”τμψΑEDDDDD);nπΝ(’‘6‘cǎΚI'•ͺU«Šo[…Qς³γQ€μΈΑ7£ˆ"""""Jzvόΰ""""""Š”7ψfΡH›Hi!""""’δgΗ."""""’HΩqƒoF "DDDDD”τμψΑEDDDDD);nπΝ(’Α@„ˆˆˆˆˆ’ž?Έˆˆˆˆˆˆ"eΗ ΎE4ˆQ³γQ€μΈΑ7£ˆ"""""Jzvόΰ""""""Š”7ψfΡ` BDDDDDIώ\DDDDDD‘²γߌ" Dˆˆˆˆˆ(ιΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒ%=;~pEʎ|3Šh0qωεHYŠˆˆˆ’—?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ωN’ΘDDD”ΌμψΑEDDDDD);nπΝ(’Α@ΔΙw’@v ""’δeΗ."""""’HΩqƒoF "NΎ“€²%/;~pEʎ|3Šh0qς$ˆˆˆ(yΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο$)€μ@DDDΙˎ\DDDDDD‘²γߌ" Dœ|'Id"""J^vόΰ""""""Š”7ψfΡ` βδ;I ;Qς²γQ€μΈΑ7£ˆFΪ D/^$Υ«W“ψΗrφΩΏ•ˆo]7;1Ίώι%ο–“δν[Iα“§ΡXϊόνbΫωπ†β[©§ύ›OΛigτί2ΘDDD”ΌμψΑEDDDDD);nπΝ(’Α@ΔΙNŒ2A‘μBDDDΙˎ\DDDDDD‘²γߌ"i7iΨ°‘̞ύ>|H,X ?ϋΩΟdςδIβΫFanvb”Bˆd"""J^vόΰ""""""Š”7ψfΡ` βd'Fˆ „Hv!""’δeΗ."""""’HΩqƒoF΄ˆηŽ;jHλΦ­Ε·Lanvb4ցˆ-gληhΛ3ΕέΞ΄υ=dgΟ‹δού‘όύŽΘސΆ<&ξϊΖ0G[œ!Ώσd9ΨαyuΕβ[7-¦•:―Ÿœ~~ωο?τ“»ϊ‘SΦWi0HlύGW—ψήoλ)|!}6—ψn°\ χϊαβ.WR=– ““Nz"*•;<)ξvzoξO ά=凧υ•"¬R»'eψΡ‘βoΪΞ*Ώ½²Ώœόγ'δ¬ΛϋK—χ†‰oέDh;«­όφΚίΚΙ?>YΞΊό,ις^ρ­›H§qš\xλ…β[&ˆˆˆ(yΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“e "a D‹QζeΗ."""""’HΩqƒoF΄ˆ|ύυWςρΗ‰]2kϊτiβ[§07;1λ@Δλ%³V©"οΎί\Ζο(ΣΦ=$Όύϋ²·λωβώۍΕnwΫWˆmηΕΝ½dΕΈ[Ε]?V6ωΟ_φ•A;GΘΩWχ—Kο(ύ?!ί?Ή― ψb„ΨvΞΉΆΏάΩgˆΎκ=Λο+ χϋ‰λ%³nν>Xš½8T†)½V Υ2Dάυ»Ξ&ίύΑπ™§dπήcρp©ΡkˆΈλΗ«λΌςέ|W>ΣPο,=χ½jˆo‰ν@䞁χΘI'T"νίl/DDD”ΌμψΑ•j1B|CœΘG}$¬Οϊ¬ΟϊΎeN„υY?Φ'"JΥμΈΑ7£ˆ';±Κ@$6 DΒˆ$""’Μˎ\©VYŸb}Φg}Φχ-s"¬Οϊ‰XŸˆ(U³γߌ"i;yτΡGΔ}γξή½›ψΦρq³«e=)Ξ±ζgΘ?jό@άοηΆ?[μvŸΫΥOάεΝ"η\3@μλΧ5$6Θ°―ό¬~ςπ’ab_o0ζ)ωεΉύΔΎ>βxΨ;»Ÿ4”Ψχ-ցHqͺυ,—έ5Pάο_w_°ΏWΦsΏ_Ϊ»ο:Ή²φ•β[&Qς²γQ€μΈΑ7£ˆ';1Κ@$6 D’Γ@$5Qς²γQ€μΈΑ7£ˆFΪDŒ]2kΙ’ΕrώωηKώύΕ·Nanvb΄Μ"ΗGΘς‰Υδλϋ~!v‰,ێkΜ‘abΫωkŸΘΏͺύ‡ΉRd‘σn φυςMΙ½‹}ύητ“nσ‡‰}ύ©aφ!βη “o?-§όg_y*g„Ψz‰λ@€Υ+Cε¬rύεδυχCΩXe ΈλŸ_i€ΨΰΔύ~i;ΏRπs¨Φ£šψ–ΙDDDD”ΌμψΑEDDDDD);nπΝ(’Α@ΔΙNŒ2‰ ‘0"ι‰ˆˆˆ’—?Έˆˆˆˆˆˆ"eΗ ΎE4~ βκΣ§\qΕβ[¦07;1šΈH ±ν7yk^k±ε΅ύ<Ώ£―ΨΐδλΖOlΉ1‡‡Šm§¬/™UβΘΌab_7vι¨k†]]/μϊ&aξς‰Φα­§ε΄Σϋ‰o™Βlγ~Ί}έ–»₯Ϋ“rΑΝ€π6BΈdVlψPu""’τɎ\©VY¨-λ³>λ³Ύo™a}ΦOΔϊDD©š7ψfΡ` βd'VˆΔ†‘²Δ@„ˆˆ(}²γWͺUΦ'€XŸυYŸυ}˜λ³~"Φ'"JΥμΈΑ7£ˆFΪ DΆnέ" 6”εΛ—Ι±cGeι%rΑH‹ΝΕ·­ΒάμΔj’"Ο¬/ΆΥ£o–QΗGˆ»ΌέŽ-Ώσdόށ2gΞύbί7ξ@Δ/φύ­ύ’ρϋΙԍ=eω„Ϋ€π}ˆG’"|0L~pκa?μ+φuwωD{tεpωο=!-&ΎeCν!ίωΞζ΅§ειά‘yξΣb–H‘¬Ψ‡ΗΩ7Rz.&wφ"ξϊρκϊqWωξΎ+Η7–!ϋ†HΟe=εΞ>wŠo‰tΪ§Ι…·^(Ύeˆˆˆ’—?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8Ω‰Q"±a Β@€40!""ΚΌμψΑEDDDDD);nπΝ(’‘6‘ΏόεΟ2iσR\9ωα(gžy¦΄iΣF>,Ύmζf'F݁Hqήύ …>ΉςlΞ`Ωχΰοε5~ ΆήΡ–gJΑ:‘!I`νˆJς?΅~$»ϋΩώΨ₯ςη†?ێ;1Ώ^WŽ5;]ώ~Ηδ`‡³εε5έΕ]/V‰ˆ˜ΣΟο/Ώ<·Ÿψ–)MΫ>)§ώ¬―Ψ‡’Wξπ€ΈΛΧ6DμΓΨΏr˜ @l½Hc•ί”λ/φαμΏΎ¬Ώt φYˆoέDhσZπσψMΉίΘΙ?:Y~}Ω―₯λΌβ[7‘ˆe^vόΰ""""""Š”7ψfΡ` βd'FˆΔ†H‘Δb BDD”yΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QD#m"₯ΕΝw’eΟ,5,Ύe€xQς²γQ€μΈΑ7£ˆ'ίIR”="H"""J^vόΰ""""""Š”7ψfΡ` βδ;IвΣvΦP±ο»eΈψ–βEDDDΙˎ\DDDDDD‘²γߌ" Dœ|'IQvˆ ™ˆˆˆ(yΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο$)’οτ ϊΙOώ+¬ξπ§Δ·laφaη%e·ηΫ&²%/;~pEʎ|3Šh0qς$Eς1AY ""’δeΗ."""""’HΩqƒoF "NΎ“€²%/;~pEʎ|3Šh0qς$ˆˆˆ(yΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο$)Jegvόΰ""""""Š”7ψfΡ` βδ;H@ι‘μ̎\DDDDDD‘²γߌ" Dœ|ι(=”Ωρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο ₯‡²3;~pEʎ|3Šh0qς€—…hύrRΛ“Šx2ηIρ­₯ι²».“†cŠoŸή;{ΛožψΨϋΫyƒΞί:ι,ήχοxΧOwΏ½ς·RT}ρ-ƒΜCΩ™?Έˆˆˆˆˆˆ"eΗ ΎE4*T¨ Dςσ€—…l?! υ0‰NΌοίρŸξˆd'ΚΞμψΑEDDDDD);nπΝ(’as"ωωΛ»Ÿl;! ut›ίM~φλŸΙπ#ΓΕ·¬Οu“žΏA† Φψ–Ν$ρΎgλϋ?‘μDΩ™?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ωΛRΆž:ˆΔ&ήχοl}g ’(;³γQ€μΈΑ7£ˆFΪDŽ?&Ώύοε'?ω‰ψ–υqσ€—₯²>!Φ~e{9­λiβ[€_ϋ7ƒŸŸΐig??ί2ιΰΪFΧJ•.UΔ·Μ‰œυΔYla3ρ-“‰β}.λχ²Β@$5$ϋύ‹²3;~peZ5jԐ“N ήΟK GBDDDDDίdΗ ΎE4ˆ8ωΛRYŸc ρH‘ΨήΏΛϊύΏ¬0I D(Ωρƒ+Σb BDDDD”ΈμΈΑ7£ˆFΪDΊuλ*Χ^{­0I,"@μ} 2βψ9υg§JΗw:ŠoΩωEΟ_H«%­Δ·L&Šχύ»¬ίΛ ‘Τΐ@„’‘?Έ²₯Ϋn»MΊtι"DDDDDT|vάΰ›QDƒˆ“ο ½,•υ 1"@μˆ„1a R DRJFvόΰΚ–ˆ•<;nπΝ(’‘Ά‘Ε‹IΉrεdΚ”„HؐCC€Β δ§έ~*§v>Uw΅ >8Xl½[zˆέ^q*ΏTY ίv"΅ΥVμΩΙ?>YΞΊό,ις^ppΧΈc \qοb'tO;ύ4©Τ’<ϋ΄ΈλŸsν9RυͺrΞ5ΑΎΚχε ƒv wύD³Rήz‘ψ–IEιϊόΩΧ/½γRωαi?»ύ½jȈc#ΔΦλ±$ψω ψ.{αSΉCπσ(|Ϋ…Ωσ}MΓkδάςηΚχNώžΨvšMi&Ύm„Δϊϊytε£b·3xoπ~π-[Ψ9‚ύπ½gvή σΔ]ΰώΰω\1&xώφΎeƒΩJ/Οΰι#ΑσpΧ7 oΰšρΑώ œ;(Ψο΅ φ_ΐξG³Oƒύ°υzομ-εΖΏ_?μ<?πc±Ϋ/ξΓαγhΔ»~¬zo ά=ΑγΨλΗΏΐ~ώ† ΐ·xΨϋE•ΞUδτσO—SώσΉμΛ$Οo’%ϋύ7ήχ―XŸΏDΏ•egvόΰΚ–bˆΨ%Έš6m**οN>9ψ;+`?§―ΏώΊX7άpƒŒ7Nάϊτι#΅jΥ·Ώόε/©S'ωυ―-?ωΟ₯I“&ς§?ύIˆˆˆˆˆJ#;nπΝ(’Α@ΔΙw^–b=!Ζ@„H*` rb DˆœHΌλNJHQΙ~χύ‹₯SvόΰΚ–ˆ•<;nπΝ(’‘v‘―ΎϊR.½τR™7ožL›6Uˆ„]1φ 9οΙσΔNπΩ‰ΖKGϋ/pέΔλΔ·²ΊdVΧy]ε»?ψ4|¦‘Ψ Ω‹{ˆ˜vΧ/W³œΨ‰£ώŸχ—^«zɝχ_Rύ‘κβo'€~ρ»_Θ#ΛΫΞιœ.wτΎCάυ-Ϊrχ ΌG Ÿ΄Š†]Ε·ΝX€ϋσwKΧ[ΔNDψ|€τΫΦOn{θ6±νΊλ›x/9cΟ·m1΅…<•σ”ψΦρ‰φυγκπV±Œo™hό’Gπ<’½dVΉΡΑσψΓΰΰωτί D(Ωρƒ+[Šw Ίuk‰ΆX"_ύ΅ΨfγƍβΆvνZ9ν΄ΰ}#@DDDDTΩqƒoF "NΎƒτ²Tb Dˆ€"a DΒˆ0) " D({²γWΆΔ@„ˆˆˆˆ¨δΩqƒoF΄ˆ¬]»FΞ<σL9p`ΏΨχˆ„=Όωa±ε£5$wˆΈΫ+«Θω•Ξ;qγ[Ζ't9£;`{|νγβ.ΧbZ ωΡϋ‘Έί·Ru†Υχϋ'”ξΌLάοg»tώž:π”Ψ₯±ΞΎκl9σβΰύ'`'$#}¨»IΤ@δŽΗοί2₯ι[ͺΎg°ψ–=‘h"ύφΟΐή—ί<wΉ‹‚η?π£.ΑσpΏol rΗΜ`|ΛψΨύ<«οYrrϋ“₯π{fΘ‡ώQ|Ϋ‰w οϊ±jυJπψg• ΰδ?`―σΗ*ΑγψΆˆΨΰΣύ~χOΊ‹έβ~ΣMΌο_‰zώˆP2²γWΆο@dΠ Am±D6lΨ ξϋHqώόη? Q"³γߌ" Dœ|ιe©€'Δˆ0I DΒˆ„1 /_FΌλNJHيχύ‹₯SvόΰΚ–ˆ•<;nπΝ(’‘6‘ηŸN|lŸΘΒ…ŸŠo›!nΎƒτ²d‚n'ΔμΓ…}Λ†Ψ ³h—/N‡•$Ω‘TΉδR¬'€ΚJͺ|¨z¦>w?»έβ>”Ψ.9uZώ‡Cϋ–9‘‚H„O.m#ŽSvͺt|§£ψ–=‘h"₯uΙ¬;fϋ/ΰ[¦°§=%ίmϋ]iψaC±―Ϋr·Όr‹\πΤRx…•τύΫοϊ%eƒΐοώ xό†Ο?`_·εμRVά<ώ@αm$‚ D"^2+„Ώ½.έο§»XίΏύόΕϋώUR”Ωρƒ+[Šw ςδ“Αίύh«Z΅ͺŒό~Έ΅kΧN܁ΘW_}%φwγ‘C‡„ˆˆˆˆ¨,²γߌ" Dœ|ιe©€'Δˆ0a Β@$Qˆ0a ’|±Ύ%ϊω‹χύ«€(;³γWΆΔ@„ˆˆˆˆ¨δΩqƒoF΄ˆ'S/™el Qwn]±•ΎeCʍ)'—ŒΌDίρΈΨ‡·ZάJŸx½ψΆςθ珊 |資ķl"uύΈ«Ψ‰Ζγː}C€η²žrgŸ;Ε]ς»/— *_ > ­~Lώϋχ-‘>΄Ά΄N¨ΗΚ.Yb'Θ}Λ€’tώμ„αύ“ξ»TΤγλ‚Ÿ£ΐ/~χ ©;<ψy Έλ»δ” xZόό|Λϊ$j οληΪF׊]*Μ·Μ‰D;1—ž€ μ žΐc_ΟΰΏ ž@υΑσπm#€€‘AΙwZ}GΪ,k#OyZ:―ν,φ~\ά@Δ”τύΫοϊΡ΄3xόο|'xό6―?`—€κ<7xό;A^Ϊ‘Ÿώκ§cI±χs˟+ε›–ί6)ΩοΏ±Ύ%ϊω‹χύΛΨ₯νyυ-BΩ™?Έ²₯dD:uκ$*T/ΏόRμΓΠO?ύtq"V½zυ€f͚²kΧ.ωӟώ$οΌσŽ΄jόΎ•Fvάΰ›QDƒˆ“ο =”τ„"e‰H‘0"%{vΕ»~΄ˆψ%ϋύ7Φχ/"”ŽΩρƒ+[b BDDDDTςμΈΑ7£ˆ'ίAz*h½΄΅ό΄ϋOΕ.‘RqJEq—·I·ο¬ϋΟδ”Ž§ΘEΓ/’[zˆ»ΎΛΆsjηSΕnΏςK•Ε·N"Ψ ί”ϋΨ‡Γώϊ²_KΧy]Ε]oΐ€\ΝrrκOƒϋψΙ―@…6Α``hξPq׏χ„z’%ϋ„\’€λσΧ{Co)wOpϋS~όάώσ—)7ΆΌQ†&ξϊŠmƒŸŸ€]βΗ.9QΉCπσπ­bΟwYDΊΝο&?=3x ?2\|Λϊ”t br£ƒύ8΅S°ί?y0xώ¦Ο`θ‘ΰωψΆRˆ©37xέlρύΆί€Ψϋ^΄‘’Ύ»β]Ώ€μηΖ^7ί?9xό;n―ΫβN¨ΗΚNœίάιfωο?ό·œόγΰύ#`ο 6¨τm#‘βύω)©xίΏύόΕϊώe~yξ/ε’jΑίί2!”Ωρƒ+[Jφ@dοή½rν΅ΧΚ)§ίμ~tθΠA" DμCνώώζ7Αίw;ώΊσΞ;eγƍBDDDDTΩqƒoF "NΎƒτTPb Dˆ€"a DˆΔ3Јwύ’²Ÿ{έ0IξϋoΌο_‰~ώˆPifΗl‰QΙ³γߌ"3‰•›ο πΝ₯ΜŒi Ύe dΰφb—πκψNGρ-BΩ™?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ω DDE“?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ω½ζ/5—s9G|ΛFΩ™?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ω="Mvόΰ""""""Š”7ψfΡ` βδ;H@ι‘μ̎\DDDDDD‘²γߌ" Dœ|ι(=”Ωρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο ₯‡²3;~pEʎ|3Šh0qς€ τPvfΗ."""""’HΩqƒoF "NΎƒt€TF”ŽΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο$@*#JΗμψΑEDDDDD);nπΝ(’Ρ±cGa ’Ÿο$@*#JΗμψΑEDDDDD);nπΝ(’ΡΆm[a ’Ÿο$@*#JΗμψΑEDDDDD);nπΝ(’Α@ΔΙw’ίΈμΛ€αΨ†β[#σ~{εo₯ώ¨ϊβ[&•ΪU’κTί22K’ή?²]ͺΌV~©²\7α:ρ-“Dι˜?Έˆˆˆˆˆˆ"eΗ ΎE4ˆ8ωN2ΰ D’Γ@@¬ˆ$’Τώ\DDDDDD‘²γߌ" Dœ|'02―Ϋόnς³_L†.Ύe‘ΈšύΆυ“Szͺ ά1P|ΛΘ D#Ϋή?‰1;~pEʎ|3Šh0qςd‘’b  V DƒQκgΗ."""""’HΩqƒoF΄ˆάqG 9逓NθσΟ·‰o…ΉωN2`dή΅•*]ͺˆo|#Ρ'4/ΌεBΉgΰ=β[¦4έΥο.iσzρ-ƒΜΕσŸ\©6IχηΏ¬ί?“…(³γQ€μΈΑ7£ˆ'ίI0))"Θ$<ΙΕ@$±ˆ₯nvόΰ""""""Š”7ψfΡHہΘγ?.ΎeJΒΝw’!›8>BNύΩ©ρŽβ[6•]ΣΰIΦ ±DŸΠΌχΙ{εwΧύN|Λ$’ν―Φ―Ά–‚’―΅‘ΊΓλJ΅ΥΔ· €/ž’l€λϋGIeΪσŸμχΟ²B”ŽΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆ“ο$C6c "Hg*v)²Α{‹oΩΒzoθ-εξ)'?<ν‡ςγ_όX*΅«$Ïί6©¬NhVι\EN?t9ε?O‘ΛξΊLν$ΎmΦyngωήΙί“ήoOxJnιz‹όςά_Κ™—œ)΅‡Φ–Ύmg΅۟'ψd9λς³€Λ{]Δ·n:+λŸž’ύύ£€2νωOφϋgΓΚI-ƒί›…\7α:ρ­SΨ9Ξ‘ͺΣ«Κ9ύƒ|Ώνχεƒ ƒr‚η?`λ₯cvόΰ""""""Š”7ψfΡhΦ¬Y^ΫΆmˆX…OJ€H¬}B“" Dˆ0a B™–?Έˆˆˆˆˆˆ"eΗ ΎE4ξΉηžΌV­Z₯ί@δ΄ΣN““O>Y~χ»ίɐ!ƒΕ·[α“™Χα­b'’|ΛψάΪύViφb3zp¨τZΥKώλΌ’ZCj‰o‰TV'4O;=x^τ°τΌΏΨ₯[μΓκ}Ϋ(Μφ› ¦|1@|Λ&BΑ Ρn·ˆ{B΄ΞΣu€΄N,vΧUΎϋƒοJΓgŠ δz,ξ!5zΥί6ba―ΫΟΡjf{ρm3eύσ“­Ο$ιώώQR™φό'ϋύΣUω₯ΚRΘ/zώBΩφˆτί<Σ{.wΜΊCl=’t̎\DDDDDD‘²γߌ"·ήv[ήύM›2± Ÿ”‘X1‰OY·Χ‡νηh1ρo'VeυόGΒ@„H<ˆEΎ\DDDDDD‘²γߌ"Uo½5―I“&ι3q9rX^yε9υΤSeΒ„ρβ[§0·Β'%ϋ@€8φaΌvιί2±H•ΪvBΣN(Ίίoυr+9ε'§ˆϋ}W²OθΩ ΰHͺ\gX)­UΎξΎλδΚΪWŠo™lVZ??&[ŸL}(©L{ώΣu R}FuqΏ_eZΉκΩ«ΔΎN”ŽΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDγΆjΥςš¦ΣΏq1)] DbΓ@$>euB<]”ΦϏΙΦ矁HX¦= DˆR7;~pEʎ|3ŠhΤͺU+―uλΦι;q΅hΡ\jΤΈ]|ΛζVψ€<ͺΎg°ψ–-¬Υ+­δ¬rgΙΙ?:Yl;ζUώ(Ύm$’ΰ³žΎeΙNhΪ‡»ίοώIw±ύπtξΣβ.g’ύ‘ΐ‚’―·ί2‰t~₯σ₯΄NΈ¦ΊTϋωΙφη?έί?β•ξΟYΏΖ:©3·ŽΈί―6#Ψ/ΛF^&φu’t̎\DDDDDD‘²γߌ"-[ΆΘkΫΆ-«πI0‰‘ψ€Ϊ ρdc Β@„"” Ωρƒ‹ˆˆˆˆˆ(Rvάΰ›QD#4 Ι¨HhΒbΎξ[¦0·Β'02oΔρrκΟN•Žοtί²!φaΌξ‡αΪΧm9»Μ7_ …·QΚκ„fΔKήδŸπΆύκ~ίuοΰ{εœkΟί2™$[/™”ͺ??ΙVVΟ$ιώώ‘nύό—υϋ'’ΘΩρƒ‹ˆˆˆˆˆ(Rvάΰ›QDƒˆSα“` +"ρ)«βφϊπ =N„Hb•Υσ ‘δJτσΟ@„(u³γQ€μΈΑ7£ˆFΪ DvνΪ)χέΧXΦ¬Y-φ‘κ3gΞ”ύθT™4ιyρm«0·Β'πk]+UΊTί2!ƒv’ο|η;bΒk—t±K—œvϊi’ι‘Ÿώκ§cIπω9·όΉRΎiyρm£0»4Ŕ5Ε·L&ιϊqW±Α@γρeΘΎ!sYOΉ³ΟβΫF:J՟ŸdK΅η?έί?M’Ÿ²~d B9;~pEʎ|3Šh0q*|ί` R2 Dβ“j'Δ“…HXͺ= D’+ΡΟ?’Τ͎\DDDDDD‘²γߌ"i31£G–σΟ?_~ψΓŠύχΘ‘#Ε·[α“ψF·ωέδ§gώT†.ΎeCκ «#§qš|δΐ­ά‘²dκ ];‘ys§›εΏπίrςO–r5ΛIqRίok?ωαiΑλ<0pΗ@ρ-›‰l π›rΏϋpρ__φkι:―«ψΦMgΩώσc²υωOΤϋGΊ‹χω/«χϟ?τs9©εI'tJΗSΔ]ŸeSvόΰ""""""Š”7ψfΡ` βTψ€ΎΑ@€dˆ$FΆžg –­Ο?‘°xŸ"D©Ÿ?Έˆˆˆˆˆθgο>ΐ,+«Δ_γΥeœ`nj£Ž"A²ˆ"&’ HNJΑHN‚ˆ(ΩQ”$"ΙA‘œsjrΞ"oχͺYώ»ΏωΆ΅«ϊΤξSuήχ>ΏηΉΣ΅ΟιͺΣ΅λ_k/Ω‡&97Τvmw ‘^Wšϊ’ƒώoύιŽVΩk•¨vŒzΧβ-}|«G΅c$I·Aϋω γQΞeMrn¨ν(Ϊ΄ζškF"«v‘A/ ‘n³‘€Ρe!ύ/η‡2€&97Τvmϊϋ!²ΦZkύmJ΅ƒΪ”ŸHmιΠΟ•j$I’ϊ9r~(h’sCmGΡ& ‘Bν"ƒ$IR?γQΞeMrn¨ν(Ϊd!R¨]d$Iκη`<Κω‘  IΞ ΅E›,D ΅‹ ’$IύŒG9?”4ΙΉ‘Ά£h“…H‘v‘A’$©Ÿƒρ(η‡2€&97Τvm²)Τ.2H’$υs0εόPΠ$η†ΪŽ’M"…ΪEIνΊρσkNWoYαΧΰjίS ƒ(η‡2€&97Τvm²)Τ.RHjWmΙ1’jΙ58ΥΎ§€A QΞeMrn¨ν(Ϊd!R¨]€ΤΪ’c$Υ.’kpͺ}OIƒ ’œʚδάPΫQ΄ΙB€P»H!©]΅%ΗHͺ]$ΧΰTϋž’%D9?”4ΙΉ‘Ά£h“…H‘v‘’ϊΘ—?-°ΪQν˜‘Τλ瓦T[rLι‘γNŒ;ύ¬¨vΜ”jΙkνwΜ΅Ρa§έՎΡψ«φ=Υωω«.‚A”σC@“œj;Š6Yˆj)ϊ!δ4ͺ-9¦d!’6ΥΎ§ϊ!?ΥE0ˆr~(h’sCmGΡ& ‘Bν"ΕDΜ9E΅%ΗHͺ]$―e!21«}OMΔόόU-D9?”4ΙΉ‘Ά£h“…H‘v‘b"ζ‚œΖ’Ϊ’c$Υ.’Χ²™˜ΥΎ§&b~ώͺ ’œʚδάPΫQ΄iά.DvΨa‡θΝo~S4묳F_όβκΡάΥ;u₯ΪEЉXΫ r_ϊέ—’9_;gT;f"χθ[Ž<ζΘθŒ]ψnώΔΝQν1SχΣΫ=?ΛσΡΓo{8ͺ[kzώ«-9FRν"y­Ά ‘ΥΆ;=Ίη‘ΏF΅c&r·έϋD΄ΚΦ§F[οQτ‡ ξˆj™“O?•~όιθ˜s'Eσ¬ύΫ¨φSιί_ϋžšˆωωΫιύωwόΑΗGόΧQώΎ½χGGwDT{μ”Ίώω ƒ(η‡2€&97Τvm²)Τ.RLΔ\kΧτ^³Yες¦,DΪe!ŸωωΫιύωg!ύ/η‡2€&97Τvmw ‘]vΩ9zύλ_xβ ΡύχίνΏ~ΡρΗ՞cκJ΅‹1δΪ5½ΔNΨ„θ‘w>=7λsΡ/τΛ¨φ˜©λϊ‚άτV[rŒ€ςyS"νšή…Θ¦»1Κ?Ÿoέ£’?^qotμo‹¦~μΤYˆΤσσ·]£ύωwμ/ςηνΙ?=9ϊιm?ςηοeλ]՞cJ]ό…A”σC@“œj;Š6Yˆj)&b.Θ΅kz/ˆYˆŒ¬ςyS"ν²ιΟόόmΧhώYˆΐψ‘σC@“œj;Š6»…Θήπ†θ ƒŒjnj€Rν"Ōh՟¬Ν4ΣLΣ4ά΄μ»—~7zϋ"ofžmζθ-σΏ%ϊΰςŒΚηΫς[FείΫT^Ψ›ϊοžχ.^τΟ~ zωœ/ζxΝΡβ-νφΐnQωψlΓίNώά›ηys4Λ³Doόο7F›ΈYT{l/šή b7|κ†θΒ―\Mϊθ€θΌ­Ξ‹j™Ί^]Λ ͺs/=wT;¦εbγΎ}φJ~V4υdκςΒψ’_:&ϊΣ•χFyώ’k9gRT.D>φΥγ£Άr±’ΟήθχQ^πμ/ΟD=φttΐ±ΧEo[ι7Qωψμ‹ΫŸ]zΓƒΡ_ώϊltεΝE+|用φΨ^Τλ…HΆΓΑ—D·άύxT~<λΥB€«οίΜΟί‘ΖλΟίΌ%Φp ακΥΟίΆΑ Κω‘  IΞ ΅E›,D ΅‹3"䆲ιΝ9 ‘: ‘ϊγ,Dόό’…Ho~ώΆ QΞeMrn¨ν(Ϊ4n"·ήzK”‚ςMΥ_ϋΪΧFsΞ9gτΩΟ~6š4ιΦ¨φ\SWͺ]€θ‡ςΒWΫ r1οDσ~~ήhη[wŽς,/›εeΡpΟ7Ϊ[Ά,ύυ₯£΅~1ωϋjr?ΈϋΡ·/όvτ―oϋΧhω]—ΚΗυ΄―F/ω₯Ρͺ{―νrΫ.Ρ–ηn-ϋνe£ςρ½j΄Δ~rχO’gg{6ΚǟΉΣ™QΎΙoν±SΧ« r]]P-9¦τΘq'Fm"_@τΫ3o‰ήΏΖ‘Qήλ™g_ˆΚ…HΩho™΅Χ‘WEύπœθέ«}d“c£›οz,Κ όεγ?½ΥIΡ³Ο½}ύ'ηEο]ύˆh™―žύπΧ—Gεγ{U―" ¬χ»θΒk<γ–hκΗNέx]ˆ”ωω;>~ώξ}ΗήΡί^2ω1ŸάqΏ8.*k[―~ώΆ QΞeMrn¨ν(Ϊd!R¨]€θ‡\³Ιί_–~"υγΚ,D,D¦ΞΟ_ ‘ιωωΫ6D9?”4ΙΉ‘Ά£hΣΈYˆ\~ωeQ.DZh‘θϊλ―‹nΊιΖhˆVZi₯¨φ\SWͺ]€θ‡Ϊ^ΫξΊν’|Ύsρw’ςΈχ}ς}ΡX]eΆ\&z§ή•_`υɟΧδζYaž¨όxΏ—oκϋμμΟF{έ»Wτ‹σύm¦Ιίl“;θβƒ’ΪsŒΗjKŽ)΅]ˆδ›v§ΕΎ|LT^8?ιό;’±Zˆ Χ‡]pήνQωρCO½)ϊύ9“’ςγύ^.Dš\;ι‘hώυ~՞c4ΥΎ§ϊ!?§ύxΏΆί5ϋEωσυˆγŽˆjΗφc0ˆr~(h’sCmGΡ& ‘Bν"E?δ‚ά΄οχ,D¦ΝBdڏχ{"Σζηο΄οΧ,D`όΙω‘  IΞ ΅E›ΖΝBδΖoˆςBΣ!‡ό**;ψΰƒ’ω—‰Κ—•j)ϊ‘ΆδΆ8k‹(_§οίυύ¨^«-9¦Τv!²μΧOŒά_8,*/œβΔλ£±Zˆ¬³σYΡ7==ωΤsQιΜKοŽΚǟsω=Ρ‡_•οχr!Rή2λkνμ΅Ρw>½}εC£©Ÿc4ΥΎ§ϊ!?§ύxΏΆη{F/Όμ…hzo™Υu0ˆr~(h’sCmGΡ& ‘Bν"E?δ‚ά΄οχ,D¦ΝBdڏχ{"Σζηο΄οΧ,D`όΙω‘  IΞ ΅E›ΖΝBδ‰'^ρŠWDΏώυ!QyάAύΫΏύ[T~Ό¬T»HΡ΅½ ·ύυΫGyΑkzoΩςε£ΏΝωοsF΅c¦ξϋw~?*ߌ7<[κkKEοZβ]ΡΤΟ1₯ρzΛ–ίχγθι9ŸŽςΦ-Mέ3Ο=QνΉΖc΅%Η”Ϊ.Dζ]η¨(Mο-³Vέζ΄θή‡Վ™Ίχ|απ¨|3τόσ<ξ'Ώ½*:뻣©ŸcJε–YεB$[x£ίGiι͏ΚγFZν{ͺςσwڏχ{χ~ΰήθ²υ.‹jΗτc0ˆr~(h’sCmGΡ& ‘Bν"E?δ‚ά΄οΧ,Dκ‹ ‘i?ήοYˆL›ŸΏΣ~Όί³ρ#η‡2€&97Τvm7 ‘lΝ5׈ζ›oή¨ιMΥΏπ…/D΅η˜ΊRν"E?Τφ‚\φŸ όg4ίͺσE»LΪ%Κ l4Λ?EΓ=ί·.ψVτ½μ‹Ά8{‹¨vμ”vΊy§θ%/yI΄ΑαD?Όη‡Ρ¦'lεΎ¦ r_=υ«Q^Ψ[νg«E»ήΎk΄Υy[EΛm½\T>~Fυ»#~½ψ£}―ί7*;κwGE{ΙδoΊΙνΥώQy\―zύ½>zσ ·ωθ¦ΗEΟ?bτ‰―ŸՎRήκΕ­΅γΡ;W94Zρ;§DΉ`iZˆ|f«“£\¬lώγ?E΅ϊΡ_9>ΪυW—EεγgtM ‘όwΘ[ύυιη£όΊ¦~ŽΡTϋžšRWίΏMωω;>~ώfGvtτό,ΟG'τδhŸIϋDΏ:ϋWΡ₯^՞£—ε-Οζ^zξ¨vΜ”`εόPΠ$η†ΪŽ’M"…ΪEŠ~Θ9 ‘ιΙBΔBd$YˆL›ŸΏ"Σ“…4Λω‘  IΞ ΅E›ΖέBδž{ξŽVZi₯hŽ9ζˆ^ύκWGωηwάq{T{Ž©+Υ.R̈ζzγ\Qήz₯©Y_9kT>ώ{—/zϋ’of~ωΜQ^¨› σGm/π-ΆαbΡl―ž-ΚΏ?/–Η―ψ££Ό”σ\>ι‚\–τήτ7Eωζΐox’―žφΥ¨φΨΡ•«_έΆΨmQν˜)νωΰžΡ_ών/Ρ™;ŸՎνEςΦ‰ή³Μ{’Ϊ1½(Ο=π`4œžόkT.Dς–LΊςή(/Ό}QrϊΝΡp ‘μΐγ―‹yβ™(νwΜ΅Qyόwφ½ Κ7cΟL.@ςqM ‘,*—ίψP”oΞ~εΝGŸήꀨφΨY.DJ?ωltΡδƒ)}aΫΣ’ΪsŒ¦ΪχΤ”ΊϊώΝόόjΌύό-;qΏ£ζ~ ΚΙ5ωžάΗΥΫΛςίΑBώ―œʚδάPΫQ΄ΙB€P»H1#rAn( ‘ήd!b!2’,Dόό’…HoΚ ψΏr~(h’sCmGΡ¦q·ιu₯ΪE iΌΆγ;Fy Ω8ͺΫ‹r±1ΪjΙ58•ίO]J32D9?”4ΙΉ‘Ά£h“…H‘v‘B―YˆhϊΫR3U;φδu’Ϊc5γ³EΞeMrn¨ν(Ϊd!R¨]€OYˆŒο,D€A‘σC@“œj;Š6Yˆj©Ηsοω‘ΘBd|d! ŠœʚδάPΫQ΄iε•WŠ,DώWν"υxΞBd|e! ŠœʚδάPΫQ΄iΓ 7ŒΖΝB䬳Ό>όαG³Ο>[4ηœsFΛ.ϋ‰θϊλ―‹jΟ1u₯ςυΏY!zx‹žψK£Χ~mtΔΉGεγϊ₯"s/=w4ΣL3¨nφΡ¨φœƒ”…0(r~(h’sCmGΡ& ‘ByΪBddYˆL_"ΐ Θω‘  IΞ ΅E›ΖέBδνo{τρζθΦ[o‰.ΊθΒh–Yf‰–_~ω¨φSWΚ ΣηΌ\”‹„+wωpτσI;FΏΈϊ[Q.¦Ύ¨έOu½iκ]KΌ+ZlΓΕ’Ϊ1²GΞeMrn¨ν(Ϊd!RΘ Σ"½ΝB€]"ΐ Θω‘  IΞ ΅E›ΖέBdώωη‹ήόζ7EM ‘uΧ]7ͺ=ΗΤ•~όΐnΡӟ™-zfΉY’Ÿάϋύ¨v»Φ~7oέπχGO}nφ艕ηŒ.ΑΒΡήwΥe[F7oυž(μ'gŽnϋκ;’ƒωNT>>ο ‘ΌΧ|«Ξ½uΑ·F/›εeQήrk­ƒΧŠςqo™-ъ?Z1šϊ9§΄Μ–ΛDο_ξύQωρ]οΨ5ZtύE£W½ξUΡl―ž-šχσσF»άΆKT>~΄Yˆƒ"η‡2€&97ΤvmZyε•" ‘e!26Yˆ΄ΛB9?”4ΙΉ‘Ά£hΣf›m›…Θ5Χ\½α oˆς‚xφ| ΊοΎϋ’ΪsL]ι——oεαξ/GT»x]kΟ‡vξ[ Q.2~qΥ7££ΞΪ(ϊΫ/‰έvž¨|ž‹φϊhtμIkG?»mΗθW—n=‰Šnϋκ;£ςρΩDYˆόΣ¬­σΛu’οίυύ¨φ˜)MοBδƒΛ0zΫΒo‹Ύwωχ’oά1zί'ί-°ϊQωψΡf! ŠœʚδάPΫQ΄)χ "ΛBdl²i—…0(r~(h’sCmGΡ¦q·Yd‘E’ΧΎφ΅Ρ•W^ύα'G/{ΩΛ’ 6Ψ ͺ=ΗΤ•ϋσfQ.nύΖάQ^°Ύs³·Eωρ,)‡ž•(όΚ]Œ¦Ύθ=₯{ΎτQχΣ»wΚγšzpνΧFΟ-;sT;fJe!²ΰ F΅cjv!²Λ€]’\°myξ–ΡԏΧΟόz4λ+gΚ6 `PδόPΠ$η†ΪŽ’M" ‘±ΙB€]"ΐ Θω‘  IΞ ΅E›ΖΝB$o••ͺΏτ₯/Eεq /Όp4ϋμ³GεΗΛJ\½(wmό–¨Όp}ŒςΈ\ˆόQώωŸώ±¨|όMί~_”ΗύΟ[E{<΄{τη}—‰]ύ5Qή"+/ΫλώEεί3Q"Ÿόξ'£Ϊ1΅F»ωΖ9߈ςϋ¬m»ήΎk4υί1š,D€A‘σC@“œj;Š6Yˆ,DΖ& ‘vYˆƒ"η‡2€&97Τvm7 ‘nΈ>Κ ΠM ‘…Z(zΥ«^•/+ε›’?ΉΒ+’g–›%ΪλΎDyαΊi!2½·Μ:ϊ΄υ£όσ{7|S΄MΫFΉ0yt΅ŽςΈςσΛΞϋω2QwΒq_ŒΚγΖΊι^ˆ|ο“Qν˜ZοXμΡgwόlT~|‘΅'ŸL\ˆμ|λΞQ~ŸmύφΡԏΛ,D€A‘σC@“œj;Š6Yˆ,DΖ& ‘vYˆƒ"η‡2€&97Τvm7 ‘μΏώλΏ’ςMΥO:ιΔ(ίT}ε•WŽjΟ1u₯Ό0}ϊ‘+DΉHΈl·E£}ξΨ9*oE• ‘=ά-Ί½ΧG]~φθW+ϊνY_Š^\ϊ%ΡuΫΞείϋϋSΧ‹ςyοψΚΫ’ŸέΆcTή’+kZˆwβZQwυNσG?ΎGQyόXΥυBdΡυήΊΰ[£nΩ)Κ7CεΏΎ2*"Ω>ϋθ½ΛΎ7ϊξ₯ߍvΉm—h½_―}ψ‹ŽΚΗ—ΝωΪ9£όzjΗLΙB9?”4ΙΉ‘Ά£h“…H!/L[ˆτ6  €©εόPΠ$η†ΪŽ’Mγn!rωε—EK/½tτΚWΎ2zΝk^­ΊκͺΡwά՞cκJεκ3υΩθ‘Υ_½πρ—FyK­ΏσΎθη“vŒςqϋί΄M”κ³³EYρ•Ρί_(Κ[eύύοόί[b]²ϋβQ.Tžώτ¬Q>ίγ«Ξ ·ΙΝU;Ξ=ύ™—GωΈ|ήςq½λ…ΘΦWl½yž7G4Λ?Eωy,ΌξΒQΣB$ί$=?ίWΏαΥΡ¬―˜5zΟ2ο‰Άπ°hϋχ¨vΜDl›ƒή=Ο|Ρ,/Ÿ-ϊΧ7Ό)Zύλί‰jžh'η‡2€&97Τvm²)Τ–#©v‘|Ff!b!Џr~(h’sCmGΡ¦q³yβ‰Η£wΎσΡ:λ¬έsΟέΡΉηžεbdŸ}φ‰jΟ5u₯Ϊ’c$Υ.’ΟΘu!ς‘Ε—ŠΆύΕΡ!—άνpΘΡΡΛgŸ#Ϊxηέ£ΪsŒ&ΪΙω‘  IΞ ΅E›,D ΅%ΗHͺ]$Ÿ‘YˆXˆτ£œʚδάPΫQ΄iά,D»ξΪh¦™fŠΎϊκ¨>ϋήΏ‰ήώώFΉˆxλ{ήνψλίG΅ΗŽe\μ£ΡΛ>ͺ3šh'η‡2€&97Τvm²)Xˆ e!2Ίh'η‡2€&97Τvm· ‘kΉ:*Λ…ΘίψΖ¨όxY)"Ο?ϊXtΛΊ_ŽžΊαΖθ/\έ²Α¦Ρ‹Ο>έ²ώ&Q^ΧηVϋΪ·£©/šOισ›|=zο GεΗ{Υho™΅ΒF_‰Άψρ~Ρo.»%ϊΙΙŒ^χ–·Fλ~wΗ¨|όGœ½μŸώ)Ϊd—=’_]t}΄Ϋ1§E«~eΛ¨|όXuθ“’Ήώυί’υ·Ω%ͺ;šh'η‡2€&97Τvm²)Xˆ e!2Ίh'η‡2€&97Τvm7 ‘|SυwΌγΡΊλ•oͺώϊΧΏ>škΉ’ΪsM])"O]c”·Βzμτ³’‡Žψ]”ώάF·}γ»Q^ςN»G―ϋŒςϏΌφθίήψζh³οοεΗ{έh"Γ΅ςΖ_‹>ό±OFεΗ—\qΥh‘O~6*?>£Zj₯Υ’Ήη] :όκΫ£Ϊ±£ €vr~(h’sCmGΡ& ‘‚…H»,DκΠNΞeMrn¨ν(Ϊ4n"Ωœ-΄ΠBΡμ³Ο½ϋέφ΅―FoyΛD΅η˜ΊR.DώzΝuQ.>=υŒθΑίεŸ?{ο}Ρνίά&Κ γΏΎτ¦(ίD|‡_ύ.ΪφGD/ŸγΡ―/»9šϊ’z/νBδ›?ϋEτΦz4λl³GyΛ²μ‹|$*ώVΪψkQωρ[~ƒM£·Όϋ=Ρ/.Έ6ͺ;=ΠNΞeMrn¨ν(Ϊd!R°ΚBdtΠNΞeMrn¨ν(Ϊ4ξ"Γ΅α†FŸϋάη’Ϊ1SWυBδ[ΫDεςΌuΤG>»r΄Ψ§Wˆ–Zι Qy|―ΫζΰΓ£|ρΪ1S—‹œςΝΠσΟσΈε7ά,ϊ¦~Ž)υΛ-³ςσΜEΘΑΎ:ͺΫ‹h'η‡2€&97Τvm²)XˆXˆLO΄“σC@“œj;Š6»…Θή{ο|ςIΡέwίνΏ~QήBλΤSO‰jΟ1u₯^/Dv:τΨh–—Ο6Τ¬/ςΟΛγ{έ^'ž½τ₯/‹~tτ©QνΨ)ύβόk’—Όδ%Ρ·χύUtθ“’9:ΚKΣBd—Ϗr±’o«‹oˆφ<ξΜh΅―};*?½}nύM’·Μύ_Q~]΅cΫ”·›gρ%£Ϊ1S œʚδάPΫQ΄ΙB€`!b!RΛB ·r~(h’sCmGΡ¦q·ΉρΖ’%–X"šuΦY£χΌη=Ρ‘‡Υ[«Τλ…Hφ†·½#zέόgT;f,[φ‹λFsΜωͺ(ίύSkm•Η―ΏΝ.Q.ώi–Y’\€δγš"Y.TήφގςΝΩsξχF»qBT{μh:τς[£©ίψύ5άηŸYˆτVΞeMrn¨ν(Ϊd!R°ΚBdΪ,Dz+η‡2€&97Τvmw ‘^WΚEΗh«]$Ÿ{ζύp΄κζ[E΅c4ώ œʚδάPΫQ΄ΙB€P[rŒ€ΪEς)Yˆ F΄“σC@“œj;Š6YˆjKŽ‘T^ ήΏ‰ςΝΕχ;ϋ¨η‹σe,ΚΉ‘Ά£h“…ΠΉœΚjC4¨ΉδB’ϊ/η₯σRνsΎ8_Ζ’œj;Š6YˆΛω‘¬6τHƒZήrγˆξ»οήθž{ξžΠεΧωΰƒDω:Τ^#©λœ—ΞK΅Οωβ|‹rn¨ν(Ϊd!t.燲ΪΠ# j.$Ή€ώΛyιΌTϋœ/Ξ—±(η†ΪŽ’M"@ηr~(« = –ηΕ \@*Λ―ΫΟυSΞKη₯Ϊη|qΎŒEωzΦvm²:—σCYmθ‘΅¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyQ»Έ2Hωω ~Κy9”σRmrΎ ε|ιmωzΦvm²:—σCYmθ‘΅¨Ÿr^弜±YˆŒ―œ/½-_Οڎ’M"@ηr~(« =ύΨ'?σΉθ}šošΎωέοF΅ΗLi³―}-*χωΥΎΥ£Α-Ο‹ΫoΏm o?ΖΊ}φέ/Κ ‘Γ΅οώϋG΅ηΘs^弜ΆςΌόε!‡D΅c{Ρx[ˆΤΎ‡)ηKoΛΧ³Ά£h“…ΠΉœΚjCO?f!’.Κσ’vqeo?Ζ: ‘›σr(ηε΄YˆΤsΎ ε|ιmωzΦvm²:—σCYmθιǚ"σ/²XtήyŒςψ3Ο:3šg£ςq"ͺ•ηΕm·Mš!]~ΕεΡτΗiΊκκ«’ΪcΖ’ρφσa¬λϊΒ«¦Νy9”σrΪ,Dκ9_†rΎτΆ|=k;Š6YˆΛω‘¬6ττc"κ’΄ΰΒΡ2Λ}*ΪyΧ]£K.Ή(*Ÿg—ό ZzΩε’y>ΌPτΡe>mφ΅―G§žvjΤλΗ7->0‡£|ήό:ΚΗg'αδh•Υ׈ζ_x‘hΩΟ|&ϊώ•Ο‘Ώ=2Κηι—ΧuΈςΌ¨]\ι’οn³M4οB‹Dωz~όSŸ‰j‹ΖΫΟ‡±W^Λ ͺ‡qD΄F»νωγθψNˆFzόœzψaΡOφωYτ£=φŒφžό?₯Ï<"Ίθ’ ’ιύ<Μ1Ρή?ϋy”ίOφΩ'ϊυ‘‡Eηχ§¨όϋ†Λy9”σrΪڞ—cu^δρtP”ηΕO'ŸS:ε”?Dεσ8_κλuΞ—ή–―gmGΡ&  s9?”Υ†ž~ΜBΔBdJΣϋΊ Wž΅‹+]δBRf!b!βΌμΏ,Dκ9_†rΎτΆ|=k;Š6YˆΛω‘¬6ττcεώo|λ[Ρ"K|τ[2:λ¬3£Ό•Φ’D”ΚσρεB$/€δ…ώ<.+ϊΣΉΡ—6έ4ʏu‹-’|žί}t”δg—ώψΗs’ΣN?5Ϊmέ£|ώ^=Ύ©\0δ‚#ωχμwΐώQŸ―G.ςΈόϋrΑ±ώ—ΎεΗ³\ˆτΛλΪΆΚϋG»οεφόσr!rΠΑGωρΌ΅Τό9ΚγŽ:ϊ¨(ΛA?ίΤύΧΏωM”πb‹Gίя’ίφ›(ωΌΩτ>Ύm_ίrΛ(ž6Ω4ʏκΧΏŠςγYωχ–‹Š,"ύςΊΆ-Ο‹ΪΕ•±μ–[nŽΎςυ―G ,²XtΘδ―yJ.$ΝΨΚ ―Γ•·˜*Ÿ§Ό zτο•ΗemΓ)ˆςΈ,’y\^Έ-;γŒ3’<νί{Ϊι§Eyά{νsμ±Q^ Ξ ΎεγΫζΌΚy9mΓ-DΖϊΌΘχ/?žε-΄ςΈC?(ʏΟσα…’ςΦ#-6‡vX”κσοɚnυ4Η—_G.BςMZs±·΄ΘγVZu΅(ή¦[fε­EςΈαn™Υ――kSy^Τ.τ²α. έuםΡm·MŠς:@νΉΖ’ρφσa¬λχ…Θτήθτ3NςΈ‘~žYήκ'Ÿ//θNύwMi€·r^弜ΆαΞΛ±>/FzΛ¬ς8ηΛΨζ|ιmωzζΏγH³:—σCYmθιΗ,D,D¦nz_Χ¦ςΌ¨]\ιe.$―,D,Dœ—ύ—…H=ηΛPΞ—ή–―gώ;Ž4  s9?”Υ†ž~lΈ…Θp ·Ι $Ÿψτg’<.-ωζή§~j΄χΟφ‰ΦZoύ(Ÿ'ί|γ―lε“|ρίzh”ΟŸ·ϊΚΏzΏοώϋEψ"‹E'|b”· Zθ#ςΈr!’Ο·τ²ΛEyάΦΫmεB"oa•Οr!’Ο3£_Χ|žαΚσ"ίv¬:ξψγ£_"Κ HwήyGT{L—·Ÿc]Ώ/Dς–??ύΩΟ£<ώΘίώ6Κ ͺ‡~X”ίwύ£\”ζσ΅ύ{Ο:ϋΜ(ί4ω¬³ΟŠςσΙ ½ω<»ψΗQωχ —σr(ηε΄ w^Žυy±χ>?‹r‘rΖ™§GyΛ«μœsΊœ/έζ|ιmωzΦvm²:—σCYmθιΗ,D,D¦ηuΙηO– Œ|žύΊΆ-Ο‹ΪΕ•^–Œξ½οΎ¨_. eγνηΓXW^x=~ΌWT>OΫEC6γsA˜x²Ο>яφΨ3Κϋ°#Žˆς‚pω<#ύ{σΝ§χ;π€(/δξ>ω5˜ώείΪsό£œ—C9/§mΈ…H6VηΕᓏ~εχύή?ϋytςNŽΚηqΎt“σ₯·ελYΫQ΄ΙBθ\Ξe΅‘§³±™žΧ₯my^Τ.τ2’ΖW""ύσrΪ,Dκ9_†rΎτΆ|=k;Š6YˆΛω‘¬6τHm›ς†ζSΚEΘΟ·@tΞΉgG΅Ητsy^άtӍ”nj›‘ωω ~Κy9”σrΪ¦άjJΉ Θ…GνΨAΚω2”σ₯·ελYΫQ΄ΙBθ\Ξe΅‘Gj›…ΘτεB’4|ΞΛ‘œ—Σf!RΟω2”σ₯·ελYΫQ΄ΙBθ\Ξe΅‘GΚvήuΧ(oU•·ΎΚ[iε­«r!²ιζ_jΟ5ΚσβΖoθό|P?εΌjΠΟΛΌuβ)§žε"$;υ΄S’Ϊc)ηΛPƒ~ΎτΊ|=k;Š6YˆΛω‘¬6τH™…Θ`ζηƒϊ)ηεPƒ~^Zˆ΄Λω2Τ Ÿ/½._Οڎ’M"@ηr~(« =RvζYgFeσh‘%–Œζ_d±θSΛ/νΆΗξQΎ©{νΉΖCy^άpΓυŸ꧜—C ϊyyΐAG{μ΅WτσύˆN:ωΔ¨φ˜AΜω2Τ Ÿ/½._Οڎ’M"@ηr~(« =Rf!2˜ωω ~Κy9Τ Ÿ—"νrΎ 5θηK―ΛΧ³Ά£h“…ΠΉœΚjC4¨εyqύυΧ t~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqέuΧ t~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqν΅Wt~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqυΥW t~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqΥUWt~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqε•—t~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨εyqΕ— t~>¨Ÿr^εΌT›œ/C9_z[Ύž΅E›,D€ΞεόPVz€A-Ο‹ΪΕ•AΚΟυSΞΛ‘œ—j“σe(ηKoΛΧ³Ά£h“…ΠΉœΚjC4¨tρΡ%—\]~ω₯Υ%—\ελP{€s^:/Υ>η‹σe,ΚΉ‘Ά£h“…ΠΉœΚjC4¨ΉδB’ϊ/η₯σRνsΎ8_Ζ’œj;Š6YˆΛω‘¬6τHƒΪΩgŸwάΡџ|^tΩe—LθςλΜ―ϋ¬³Ξˆj―‘ΤuΞKη₯Ϊη|qΎŒE97Τvm²:—σCYmθ‘5’\HRεΌt^ͺ}ΞηΛX”sCmGΡ&  s9?”Υ†iP»ψβ ££Ž:"ΪgŸG{ξωΓ έ>ϋμuΤαQΎ΅ΧHκ:η₯σRνsΎ8_Ζ’œj;Š6YˆΛω‘¬6τHƒš I.$©r^:/Υ>η‹σe,ΚΉ‘Ά£h“…ΠΉœΚjC$I’$M)η†ΪŽ’M"@ηr~(« =’$I’4₯œj;Š6YˆΛω‘¬6τŒ€Oμq½$ͺΪΟI’Τ_εάPΫQ΄ΙBθ\Ξe΅‘g$Υ.rJR›j?S$IR•sCmGΡ&  s9?”Υ†ž‘T»Θ)ImͺύL‘$IύUΞ ΅E›,D€ΞεόPVzFRν"§$΅©φ3E’$υW97Τvm²:—σC―«]䔀6Υ~¦H’€ώ¬Ά£h“…ΠΉ©‡™^V»Θ)ImͺύL‘$IύYmGΡ&  sS3SΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄i“M6‰,D€ΞδόPΠ$η†ΪŽ’M+―ΌRd!t&η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›Φ\sΘBθLΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”Q7~σGϋ]Ό_Đ_!:θƒ’±ΆωI›G۝΅]@·rn¨ν(Ϊd!t.η‡2κ,Dκ,DKΞ ΅E›,D€ΞεόPF…Θ΄.Ίϋ’θM»Ώ)zξ…η’±vΟχD―ήεΥΡƒ}0 97Τvm²:—σCu"Σ²L97Τvm²:—σCYiΩC–fΪf¦΅ε)[FΣλΦGnΚηΕN―ˆ=hΡθ€›NŠΖŠ…Θ΄ΦώύΪQΫη'Ÿ}2Zύ¨Υ£9vš#zΝχ_}ητοDm}βOD»Ÿ·{@7rn¨ν(Ϊd!t.燲’…Θ ‘iYˆ ¦œj;Š6YˆΛω‘¬­ύςcΡf'n•r!rΝΧDw=~WτγσΝ²ύ,Ρ)7Ÿυš…Ȑχ›kΧΉ’3n=#Ξ&'l½ϋ'οŽ&=:)Ίΰ ’ΌΦ— gΟ?ο-|ΰΒέΘΉ‘Ά£h“…ΠΉœΚΪ²L"ƒ-η†ΪŽ’M"@ηr~(kk΄ ‘“o:9ΚCήϊjžŸΟ{ϋΉQ*"Χ>pmTZχ˜u£%gΙ¨τΔ3ODyaώ »½!Κ ϋ_όέ£Ηž~,*εηϋSΎΝ½χάΡ+w~e΄Βα+D?υpTZθ€…’}.ά'*m}ΖΦΡς‡-•n{τΆh‰_,ΝΆγlQ.V;j΅hί―•λΌ.ʏ¦Χ+ε%ϋ_²TΚο£ΌΪpΞΉνœ(aΟΏψ|Τk?ΏθηΡ*Gεχο /Ύ šœj;Š6YˆΛω‘¬-    `πδάPΫQ΄ΙBθ\Ξemt!’·Fšyϋ™£ƒ/;8Κ κWάwE΄ΓΩ;D©νBdί‹χζάyΞ¨”΄?xρ(oΩτΐ“DŸ=τ³Q.VJΉyݏ^]~οεΡ½Ή7ΚΕΔZG―•¦w!’‹‚•X9ΚΕKή²κε;Ό<λ…Θi·œε"b8w?qw”~ηίy~TΚEΙ?οϊΟΡpnxθ†(Ÿχώ'οzνΑΏ>ε­Ωςϋ j[ΊUΤτ} 0ΡδάPΫQ΄ΙBθ\ΞemYˆXˆXˆXˆƒ'η†ΪŽ’M"@ηr~(kk€ ‘\4¬ϊΫU£ΆΪ.D½κΠθ%ΫΌ$Κ[5=ϊτ£Q>>/₯KξΉ$jZ¨δ…πoŸφν¨tΜυΗDMνB$.ωωη" τΉΓ>υΫB€\\δΏί§~σ©θ[§}+:όκΓ£ΆΟ{ύƒΧGωΌc΅irΣΓ7E۝΅]”oŸί'MNγ]Ξ ΅E›,D€ΞεόPΦ–…Θ΄,DκςσΝΟίB`|ΛΉ‘Ά£h“…ΠΉœΚΪιBd©Y*Κ m΅]ˆμwρ~QΎΙyΚ[[εγΫφψ3G)/tο}ΑήQιβ»/ŽςρO?t”F»ΉτžK£|ή'Ÿ}2*ε›ΕυB€|Sυ\85«[fuυ¦κMn~ψζhϋ³Άr!2ί~σE"ΐD•sCmGΡ&  s9?”΅e!2- ‘: €‰%η†ΪŽ’M"@ηr~(kk€ ‘±ΎeΦzΗ¬-ω?KFι‘§‰ςρy ͺ‘Κ…HΣ-³Ž½ώΨh]ηŠJωyν~ήξQi£γ6ŠΚ…HyΛ¬ΌUT©«[fε­ΘςλΜ7uo’ΗΏz—WG\r@TϊΚI“ηαΙε›Η'ίδ<Mc%ίT}―σχŠΨ(ίT}ΛSΆŒyΰš`’ΛΉ‘Ά£h“…ΠΉœΚΪ²™–…H]o!01δάPΫQ΄i•U>YˆΙω‘¬­‘.DςVI3o?sτΛΛε­©Ύκh—sw‰RΣB$oΕ”·°šu‡Y£?άό‡¨΄ς+GŸ9τ3Ρ-ά=φτcQΎ)z.VJΉΙ αWήwetί_ξ‹ςBώΗn•ς–VyάΓO=ε›Ήϋ=*")—_G>ώΜIgF³ο8{4Φ ‘΄φο׎r!0œόϊηή{ξh£“’‹ξΎ(Κ[e5-LJΛόj™h·σv‹ΖΚΟ.ϊYτω#?tΣIΡ /Ύ šœj;Š6mΈα†‘…Π™œΚΪ²±±±OΞ ΅E›rb!t&燲ΆFΊI'άxB4οΎσFsμ4GτΑŸ0Ίΰ ’T.D²|ά".xγ‰Q“\Όδηϋ¦έίε›°/χλε’+ξ»"*εBd‹?lε›hΏb§WD+±RΤτ&γ·=z[”Ο“ œ|Ώ|ό—£¦…H>~‰_,ΝΆγlQ.JV?jυhΓγ6ŒΖZ.2ήΈΫ£η^x.j’oŸŸg.prt+²R.Β^΅Λ«’Ό₯έΘΉ‘Ά£h“…ΠΉœΚΪ²±±<97Τvm²:—σCγΣ*GνpφQWV<|ΕθΐKŒΖΪζ'mm{ζΆέΚΉ‘Ά£h“…ΠΉœΚŸ,DθBΞ ΅E›,D€ΞεόPF:δŠC’ƒ/;8Κ[s{ϋΉΡœ;Ο]uUŒ…œj;Š6YˆΛω‘Œώd!@?ΘΉ‘Ά£h“…ΠΉœΚθO<υH΄Ζοֈrς޽ήεΒΖRΞ ΅E›,D€ΞεόPF² δάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σCΩpόρh–Yf‰ήωΞwFΐΔ—sCmGΡ&  s9?” ΗBWΞ ΅E›,D€ΞεόP6œίόζ7ΡάsΟ½όε/Ίκͺ˜Έrn¨ν(Ϊd!t.燲αXˆΐΰΚΉ‘Ά£h“…ΠΉœΚ†³Β +D[m΅U΄Μ2ΛDΫn»mL\97Τvm²:—σCΩp,D`pεάPΫQ΄ΙBθ\ΞeMώϊΧΏF³Ο>{tΖgD{μ±GτώχΏ?&œj;Š6YˆΛω‘¬‰…sCmGΡ&  s9?”5ωέο~Ν1ΗΡ3Ο<]{ν΅ΡL3ΝέtΣM0ρδάPΫQ΄ΙBθ\ΞeM,D€œj;Š6YˆΛω‘¬Ιj«­}ς“ŸŒJρνΊλ0ρδάPΫQ΄ΙBθ\ΞeM,D€œj;Š6YˆΛω‘¬τμ³ΟF―zΥ«’Ό5VSσΟ?L<97Τvm²:—σCYΙBH97Τvm²:—σCYιΔOŒ^ϊ—Fχή{oT:ε”S’—Όδ%ΡwάGΞ ΅E›,D€ΞεόPV²RΞ ΅E›,D€ΞεόPVZwέu£%—\2jςΒ /D―}νk£=χά3&Žœj;Š6YˆΛω‘¬d!€œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2κζίoώhΏ‹χ‹²Βα+D]zP4Φ6?iσh»³Ά‹θVΞ ΅E›,D€ΞεόPF…H…ΐ`ΙΉ‘Ά£h“…ΠΉœΚ¨³™ΦEw_½iχ7EΟ½π\4ΦξyβžθΥ»Ό:zπ―Ft#η†ΪŽ’M"@ηr~(£ΞBdZ"ƒ)η†ΪŽ’M"@ηr~(+-{Θ²ΡLΫΜ4’ΆwΨη’~[ˆ”‹‹όχϋΤo>}λ΄oE‡_}xΤφy―πϊ(Ÿw¬"Mnzψ¦h»³Ά‹ςΝβσϋ€ιί `ΌΛΉ‘Ά£h“…ΠΉœΚΪ²™–…H]~Ύωω[ˆŒo97Τvm²:—σCY[#]ˆ,υ?KEyαΏ­Ά ‘ύ.ή/Κ79Oyk«||Ϋζρ(ε…ξ½/Ψ;*]|χΕQ>ώι矎h"—ήsi”Οϋδ³OF₯|³ψ±^ˆ”oͺž §&cuΛ¬ήT½ΙΝίmΦφQ.DζΫoΎΘB˜¨rn¨ν(Ϊd!t.燲Ά,D¦e!Rg!0±δάPΫQ΄ΙBθ\Ξemt!2Φ·ΜZο˜υ’%gΙ(=ςΤ#Q>>oA5RΉiΊeΦ±ΧΝ΅λ\Q)?―έΟΫ=*mtάFQΉ)o™•·Š*uuΛ¬ΌY~ω¦ξMςψWοςκθ€KˆJ_9iς<<Ή|σψαδ›œη’i¬δ›ͺοuώ^Ρϋ/ε›ͺoyΚ–Ρ5\Lt97Τvm²:—σCY["Σ²©Λγ-D&†œj;Š6YˆΛω‘¬­‘.DςVI3o?sτΛΛε­©Ύκh—sw‰RΣB$oΕ”·°šu‡Y£?άό‡¨΄ς+GŸ9τ3Ρ-ά=φτcQΎ)z.VJΉΙ αWήwetί_ξ‹ςBώΗn•ς–VyάΓO=ε›Ήϋ=*")—_G>ώΜIgF³ο8{4Φ ‘΄φο׎r!0œόϊηή{ξh£“’‹ξΎ(Κ[e5-LJΛόj™h·σv‹ΖΚΟ.ϊYτω#?tΣIΡ /Ύ šœj;Š6YˆΛω‘¬-    `πδάPΫQ΄ΙBθ\Ξemt!’NΈρ„hή}ηζΨiŽθƒ?`tΑ]D©\ˆdωΈE\$:ρΖ£&ΉxΙΟχM»Ώ)Κ7a_ξΧΛEWάwETΚ…ΘΨ"Κ7Ρ~ΕN―ˆV:b₯¨ιMΖo{τΆ(Ÿ'8ω:~ωψ/GM ‘|όΏX"šmΗΩ’\”¬~ΤκΡ†Ηm΅\dΌq·7FΟ½π\Τ$ί >?Ο\ΰδ"€ιVd₯\„½j—WEyK+Ί‘sCmGΡ&  s9?”΅e!b!b!0xrn¨ν(Ϊd!t.η‡2Ζ§UŽ\%Ϊαμ’¬xψŠΡ—΅ΝOΪ<ΪφΜm#Ί•sCmGΡ&  s9?”1>YˆΠ…œj;Š6YˆΛω‘ŒώtΘ‡D_vp”·ζ:χφs£9wž3Ίκώ«" 97Τvm²:—σCύΙB€~sCmGΡ&  s9?”ΡŸyκ‘hί­εδ{½#Κ… Œ₯œj;Š6­ΌςJ‘…Π™œΚθO"τƒœj;Š6mΈα†‘…Π™œʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›V^y₯ΘBθLΞeMrn¨ν(ΪδΏ:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊτε/9²:“σC@“œj;Š6εΔBθLΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97Τvm²:—σC@“œj;Š6YˆΛω‘  IΞ ΅E›,D€ΞεόPΠ$η†ΪŽ’M"@ηr~(h’sCmGΡ&  s9?”4ΙΉ‘Ά£h“…ΠΉœʚδάPΫQ΄ΙBθ\ΞeMrn¨ν(Ϊd!t.η‡2€&97ΤvmκωBD’$I’$I’$i¬ͺν(Ϊd!"I’$I’$I’ΖM΅E›zΆ‘$I’$I’$IκΧ,D$I’$I’$I„ΟBD’$I’$I’$Mψ,D$I’$I’$I„ΟBD’$I’$I’$Mψ,D$I’$I’$I„ΟBD’$I’$I’$Mψ,D$I’$I’$I„ΟBD’$I’$I’$Mψ,D$I’$I’$I„oΨ…Θ '+I’$I’$I’4*χ"’$I’$I’$iΒUξ;†]ˆάsΟέΡΕ_rΚIQνΙ'Rωuζם―CωϊH’$IhΛω£φ1I’$I½ΝB€! I’$Ic]Ξ΅I’$IκmΓ.Dr!π§?=φΨcΡ³Ο>;‘Λ―3Ώξ‹/Ύ(*_I’$Im"’$IRwYˆ4d!"I’$i¬³‘$I’ΊkΨ…Hή:κˆξ»οή(o!5QΛ―σΑˆςu(_I’$Im"’$IRwYˆ4d!"I’$i¬³‘$I’ΊkΨ…Hώ‚>(‹²όΊ *’$I’z9C’$Iκ. ‘a²‘$I’4V™3$I’€ξj½Ήϋξ»:ƒŠ$I’€^gΐ$I’ΊΛB€eI’$I½Ξœ!I’$u—…HΛ&Κ ²V‹ϊΕ/’‘~|ΠϋμŠ+G‡όζ7QνI’$©meΘΡMοοιζ I’€ΑΘB€eePξ}ƒΐ?ΞBD’$I½l’Μ3: I’$΅©υBδ»ξθ&Κ 2ά/ϊœ…ˆ$I’zΩD™3†k¬η I’$΅ΙB€eePξ}ƒΐ?ΞBD’$I½l’ΜΓ5Φs†…ˆ$I’Ϊd!²^ *g}V΄Α—7ŽώΘG£-ΈpτιVŒφόΙO’ΫoΏ-ͺ=Χhξύι.Ίψβh£M6‰ωθRΡ‚‹$Zgƒ £SO;-*ΏόηW‰ώη_EεΗgt"’$Iκe£3ržψκ7ΎՎ©΅ΪZkGίΩz›¨vΜxΜBD’$Im²iΩh•2  I’$)νœa!2m"’$IjSλ…ȝwή1ЍvPɎ=ώψhž/m·ΣNQ.n»mRτησν΄λχ£Γ<"ͺ=ηhξύι–YξΣΡζ[|#Ίκκ«’[n½%:ώΔ£u7ά(*o!"I’€Aj΄sΖ1Ηε°κ¦›nŠjΗNιβK.Žή?οόџΞ;/ͺ;³‘$IR›,DZ6ΪA%³±‘$I’ΚF;gXˆL›…ˆ$I’Ϊd!²Ρ*χάsw΄Τ'>}{λ­£Ϊ±mZw£/EοϋΠ|Q4ωό?ΪcΟ(ήςρΓύ’?ΪAΰΪλςσϊγŸώՎ­΅Ιζ_‹ςρeωyερΣϋ:άrΛΝΡχΆΫ>ΚΗε­½ΎωοD“&έεγš­\hε­ rαS>^’$IšΊΡΞwί}W΄δΗ—~Ύί~QνΨ)mΏΣNΡηWϋb”>½ΏWηοΗ;ΡjkΝΏΘ’Ρ‘‡ 7gτκσΘaΩͺk¬-°ΘbΡηVώ|tΪι§Gεγ‡ϋόn½υΦ(η‡|έ?ΌΨG’όό―ΈβЍ|όΟφέ7Κ―gή…‰ςσ<χŒΚΗI’$©·Yˆ΄l΄ƒJώžΏψZˆΤ³‘$I 6Ϊ9ΓBdΪΗηηa!"I’€Tλ…Θwά>ЍvPΉΰΒ ’όΕώŒ3όjǎ¦„ςθκΣΡ―=4*ξύα>ήT&Τg’|SυόzoŸόN©φΨ©ν-³Fϊ:δβ"όwΚ[ pπ/’ίsL”ΛA+"Χ\{M΄ΒηWΎυ½οEωωLύwJ’$Ie£3²νΎGτιVŒΚηΐk‘. χ{φH―Ξߏ_κcΡigœ•ΏtΞνη‘§?œrJ”C¨=ς“hEΏώΊ(?άη·Ρ&›Fλl°QtΩε—EωόyKδ\Όδ矷Hώΰ FΉΙω(η₯\X•―$I’z›…HΛF;¨XˆXˆH’$IMvΞΘ,D†ΚΟΓBD’$I¨Ύ[ˆά~ϋmQνcSΧφΈ^5ΪAε§NώE|rΉΉςͺ+£Ϊ±½(SμΌUωρα~ΡξγΓuΥΥWGίΩz›(—ς?Ρ?ς¨£’ςρ£]ˆ”5½W\yE”_rI4υcQ9hεŠΏτ²ΛE9`Υ#I’$55Ϊ9#»zςοήSϊΐόŽΞ<λ¬(?~Ψ‡GΉ(Θ[½Nύ¨αζ‹όύx·=•Ο¦wΞhϋyδοιεΗ³O~φsQώ ςΟ›>Ώ«Ύ*Κω!_οόx– \Έœχη?GΉ8™oαE£όσςρ’$Iκ& ‘–vP±±‘$I’šνœ‘Yˆ Uώž^~<³‘$IμZ/Dr1Vεj|ψα‡E—^zITwΩe—F‡vXtΓ 7Dεq½n΄ƒJ―o™uψ‘GFωŸbη/ΦωόΩ*_\#*?ά 2άΗG[ώϋξ{ΐΡΟ·@”){Χv!2ΪΧα”ΣNςοΟ[}Mύά¨΄[rιhΉΟ­ε›,Φ#I’$55Ϊ9£lÍ7‰Άψζ·’όσ/³nτέm·‹¦~Μ”¦wΎΘߏυλίDεΗ³αζŒ^}ΓΝ1ωζη»ώθGQώyΣηwκi§Eεη1\Gσϋ(Ÿ'ο΅7Ψ ΚΉg‹­ΎύρΌ?EyΌ$I’Ζ& ‘–vP±ΚBD’$IϊΏvΞ(³±‘$Iπ΅^ˆδZέλnΈαϊθg?Ϋ'ΪtΣM£ώπΡW\]sΝΥΡn»ύ(ΚγφάsΟθΖoˆjG/ν ’ά—ϊΔ'£Ό•TνΨΤ΅Χ]ε…όίώξθθ–[o‰ςοωιΟχςϊςyš~Ρoϋρ^υ±O~**ΣϊVωBΤ΄™ήΧ‘W·ΜΚΟoΣ―~-Zy΅Υ£|SφΪc%I’€²ΡΞeΗ\”‹„|3ςχΟ;τησερ½š/ςχγC~σ›¨όx–/ηŒ^;Qωρl€·ΜΚω!?Ώ&ϜSʏΆΌΕVΎny«­œ?k‘$Iτg!²Ρ*ω Ό…Θ΄YˆH’$I"½ώ<,D$I’τša ‘I“n=τΠhγMΎm³ν6Ρίψz΄ύφΫG;οΌsτ΅―-Ϊv»m’7Ω8ϊνoΥώ^4½ƒΚ±Η}θΓ E;ξ²ktρ%GωχœΑωQώ"ψ‘GD—_qy”ΝΙψC”oϊ~ϊ™gDK~|Ω¨iPhϊEΏνΗ›Κ7S_οK_ŽN<ω€(7ί<Τε@qΒI'Fω<|yγhΫvˆξΊλΞ(?ή«Χ!?ΟUΧX3ΊΰΒ £ό<œό΅OιχΗεγʁ/™-Ώύ(?~έuΧES’$IRΩτΞYώ^Ίδ'&<Ή₯—].Zeυ5’ςψ^ύ^]ώ~\~<ΛΗ—sF―?…_"ϊΓ©§DΉXΩλ§ϋD ,²XtύυΧEωψ¦Ο/Ϋh“M’œ#.Ίψβ(ηΈ³Ο9;Κγςσ?ώΔ£|³χόdεΗyΘ!ΡX0r+^I’€±ΝB€eΣ;¨XˆXˆH’$IeΣ;gd""’$IΎΦ ‘\`τΊλ―Ώ>ΪηgϋDλo°^΄Ε_ΎϊΥΝ£Ν6Ϋ4ϊΖ–[Dλ·n΄Ο>“7Ή['’;₯ΪίΡ‹z5¨œuφYΡϊ_Ϊ8Κ_Ψ?΄ΰΒΡ§WX1ϊρή{Gω¦ξωψόE>ίΤ;qΞ[6m³ύφQΣ 0ά/ϊΓ}|ΈŽ9φΨh­υ֏\ό#Qώ'ΰω恿<δΧQωψΣN?=Zφ3Ÿ‹>0‡£όΌςΈι}rρρνοm}t™ODωορΝο~7Κ|άp_.r>ριΟFW]}UT'I’$M©WsF–·€Ν[ΔζχΪ±Sšήί«‡ϋύ8ΛΗ7Ν½ϊΏ\¬lΏΣNQή8oQ–?κθ££|ܝwήε|χρO}:Κω/?οΌUΨΤ§$I’zŸ…HΛz5¨XˆXˆH’$IY―ζŒΜBΔBD’$IΝΝπ…Θν·ίMš4ε6Z“ώφƒ|?Z{ν΅’―|e³θ«_Ϋδœτ^Ήο°iYΎ΅‹΄γ9  ‘ρΐD“sΠ{εΎ£υBδΚ+/θςuΨΰϋgG7ίυXtÏF7ήωX”·`zδ‰g’#ΟΈ%Κ ΊέτΈθωη_Œζ_οwΡΤ}§΄Π†GGΟΏ0ωΈΙ-²Ρο£ςΈ‘φ±―΅•ΦΛηYxςη2₯cx[τΨ_ž‰zμιθ€c―‹ήΆo’ςρΩ·?=Ίτ†£ΏόυΩθΚ›ŠVψΞ)Qν±S— Σ/Ύ+ͺ3uw?ψd΄ιŒjΗτs‹~ι˜θOWή=ωτsΡEΧήsΞ€¨i!ςžΥ>αϊ(Cω}ϋΫ3o‰ή»ϊQ>nzΏ³υΫθ˜s'ž“Λγο}ψ―Q~Όs•C£|ΐD“sΠ{εΎΓB€eω:Xˆ e!2c³˜rΞz―άw΄^ˆ\qΕe]ΎyAψGŸŠ>°ζ‘ΡΕΧ?tώΡΌλε›tΟ³φo£Ό°›wύΥeQώyΆϋ‘WDyΑ»όx―ν-³φ:ςͺh£ž囏d“c£Ό`ΎυώEεγ?½ΥIΡ³Ο½}ύ'ηEy~™―žύπΧ—GεγΛΪ.D>4ωίdJ)/ΰη…ψ\μ§Ϋ’ςί­_Κο·\\Ό#£όχ|ζΩ’¦…H.LΞ»κΎ(\Ή¨ΘογCO½)ΚΗυκϋΈ?ޝ{ω=QΏΔδο)εχΟn“ρ)εγ&šœ3ŸN=υΤhα…ŽfŸ}φθ-oyK΄λ»FΜεΎΓB€eω:Xˆ e!2cΛο7 €ρ-η Ζ' €ώVξ;V^y₯¨q!rΚ)'E—\rQtωε—T—\ra”―C^ΎψΊ’ΌP›žs‘‘~ηύ‰>ώ΅’όσ-φώstΛݏGωηΉβP·έϋD”oξοu£]ˆ Χ‡]pήνQωρΌΠώϋs&EεΗΗͺ\Ψ€σ―Ύ/ϊπGGy ³\Xuύω Χ|λ₯ΕΎ|LT—‹‰r!ςΎ/₯\£Zφλ'F©ιϋγ'^• ‘\LŒΤ­~D4½ίm:λοzvτπγOGωηΝDYˆœ|ςΙΡόσΟε"`žyζ‰Ξ=χάhΠ|βŸˆΦ^{ν€n•ϋ ‘†,Dώq"3& €‰ΕBdb³˜±Κ}Η° ‘»ξΊ3:ωδ£}χέ;ΪsΟNθφέχ§Ρώpb”―Γh/jΛ“’όσ,ouΔ7GGukτ›SnŠΚγ{].`ςMΕkΗL].rΚ7CΟ?Ογ~ςΫ«’³.½;šϊ9¦4£n™•·$Λ…Σ†?8'*Ϋt?Fχ?ςTT~|F•o>žš M·ΜΚ7_Oω|S?φ5½ίn™0­ρΎΉΰ‚ ’™gž9:ψΰƒ£Η{,ΊβŠ+’vΨ!κ•έwί=ši¦™FΤ)§œ΅§Ÿ~:zέλ^ν³Ο>έ*χ" YˆΤ³™±YˆL,"£c!@εΎcΨ…Θ=χάε­³ςΝΕσχ‰Z~ωuηλΠλ…ΘςίϊCτδΣΟE}ϊω(Ό<ΎΧ}tΣγ’Ό@ύ‰―ŸՎΦ<2zρΕΏEkνxFτΞUVόΞ)Q.Xš"ŸΩκδ(+ωζρyk¦₯Ώr|TΎžMε-ΏNΏψ¨vΜΤεBζ’λˆšήTύΘ3n‰jΟ1uΧάϊHtι F΅czΩ…“?·)ε"-ί,=\O?ϋ|T.D²cx[tςωwD‹~ι˜θ½“_ϋ)­»ΛYQΉ˜λΥχρΊ-:ϋ²{’­sT΄ψΖΗF7έωXTΎI;ΐD“σΗx΅ξΊλF«ΊjĐυΧ_?ZtΡE£ηž{. [εΎΓB€! ‘ϊρ"υ,D,DF#ηρΚB€ΞB ?”ϋŽa"Ήψӟ΍ς?}~φΩg'tωuζΧ=½oͺή΄ΙnΈγΡθ–»jnje]τΘΟDiΏcΚγΏ³οQ."ς|.@ςqM ‘,*—ίψP”oΞ~εΝGŸήꀨφΨ©ιB$/όη-»ςΝνσλΟ?ΟPν9¦ξΦΙfS:υΒ;£Ϊ1½lα~ύιΚ{£\€ύ}QrϊΝQΣB$Oωο~ΧOFy+±ό:–ωκ Q>Wίσ¬ύΫθΈ?ή=ϊ—g’ϋώktΠρΧGοZε°(0ьχ…ΘRK-m½υΦΡ ϋΦ·ΎύχwτπΓGΜεΎΓB€! ‘!"""cΗBdb±θ/εΎcΨ…Hή:κΑˆξΏΎ¨ελf{]^`ώΑ―/jΗ¨ϊΰZΏςb«l}jT;VΣΐD3ή"3κ–Yύφ¦κίώφ·£\„δ ΐŒU^χ·iΘBDm²ι6€‰ΖBdt,Dh£Όξ?μB$AΏοΎ{£|sρA)Ώξ|ji§§/nz”o.ΎΐzΏ‹jΗͺΪπϋgG_χ@T;F½ `’Ι9cΌ:όσ£™gž9ϊε/=ώψγΡΥW_ν²Λ.ΡDσΝo~3ϊΐ>=τΠCύ‘άwXˆ “…ˆώQ"έ0Ρδœ1^YˆXˆτ³rίΡz!R[ Rω:Τ.ަn4Ί‘§’oό‚¨vμԍVώ}΅η”ΖKMΞγέ 'œΝ;οΌΡsΜ}πƒŒ.Έΰ‚h’xκ©§’ΪmΉj}μc‹θVΉο°iYΎ΅‹΄£ΙBDyMΞ㝅Θ?ΞB`Ζ(χ"-ΛΧ‘v‘VR7L49g½Wξ;,DZ–―Cν"­€n˜hrΞz―άwXˆ΄Μ τš9ΖNΉοψΔ'V‹,D†Ι τš9ΖNΉοXwέu’ΎΉςͺ+£χ}hΎiϊπb‰ΦΩ`£θΌ?Ÿ՞c,3¨½fΞ€±Sξ;6άpΓΘBd˜ *@―™3`μ”ϋŽΦ ‘»οΎkL»κκ«’ΥΧ^7zζ™g’{ξΉ7:ΰΰƒ£}ςSΡ€I·F΅η‹ *#σ΅―}-Zgu"ΰ2gΐΨ)χ"-3¨ŒŒ… Ϝc§άwτέBd΅΅ΦŽςΟσσxψᇣ6Ω$:ρ€“’©Ÿc,3¨ŒŒ… Ϝcgκ]Η”,DZfP ž9ΖΞΤ»Ž)υύB€lϋw‰ωΝ‘Q혱¨ΧƒΚ5Χ\-±ΔΡsΜύΫΏύ[τ½ο}/―,D`x½ž3€§άwXˆ΄¬ΧƒŠ…Πλ9ψΚ}ΗΈ[ˆlπ卣SO;-ͺ3υjPyρΕ£wΏϋέΡl=φΨcΡΕ_εbδΐŒΖ ^―ζ ΰ*χ"-λΥ b!€^ΝΐUξ;ϊ~!rν΅ΧD?ΫwίθγŸϊttΧ]wFS?ΗX6ά ςϊΧΏ>ZvΩe£&·ί~{4ΣL3E·ήzkTϊϊΧΏ-΅ΤRQΏΉε–[’|δ#Ρμ³Ο-΄ΠBΡ*«¬5-Džxβ‰h“M6‰ήπ†7DsΝ5WτΕ/~1ΚEQϊέο~½σοŒζž{ξ(Lίώχ£|ž5ΦX#*=ψΰƒΡη?ω(έλ^mΎωζΡΣO?ΐXnΞF―άwXˆ΄lΈAΕBΔBFjΈ9½rίΡz!’ ˆ±κΚ«Œήχ‘ω¦iEΦέπKΡ•W]ε’’φ\cΡpƒΚh"“&MŠJΉyΣ›ήυ›ψΓQ..yδ‘θ”SN‰f™e–¨i!’ “Ε_<ΚΧαˆ>ϋΩΟFλ»n”r!’·{葇’ό|ςqχή{o4묳Fχί”VZi₯hΙ%—Œςψλ―Ώ>Κ…ΛvΫmΐXnΞF―άwXˆ΄lΈAΕBΔBFjΈ9½rίΡ7 ‘{ξΉ;zζ™g¦)oY”·XΊοΎ{£ΪsŒe½TςMΥίυwEm΄Q”·†Κ7UΟ[Hύσ?sΤ/ξΉηž(:7έtSTΚΕDΉyτΡG£|όW\•.Ήδ’hΞ9ηŒR.D\pΑ(εί³νΆΫFιΝo~stωε—GΟ?|τ²—½,:ϋμ³£ή{ο½χ½ο`,τjΞώ―rίa!²^ *""z5gWΉοθ›…HΏΧλAεΚ+―Œ]tΡ(ί”ό=οyO΄ΥV[EωŸυ‹K/½4Κ…Ζ“O>•6ήxγ¨\ˆδb"ίΆΗ<Κ…Θb‹-₯ 6Ψ Ϊy督τΦ·Ύ5Ίθ’‹’r‘sσΝ7G₯£>:zΝk^ΐXθυœό?εΎΓB€e½T,D¦]x —…Q―η ΰ)χ"-λzPΩd“M’|σο~‘o>ž …‘ή2+ί|=ŸΟΧΦh"^xaδ–Yτ“η $εΎΓB€e]*"u"L$]Ο0HΚ}‡…HΛ†T^ϊΧGΛ.»l4œύχί?:묳’|³ρ_ώς—QήBλάsύ†σώχΏ?šώω£±ΆπΒ GkΉf”Ÿi§Ν:λ¬QΉI+―Όrτ™Ο|&Ίε–[’|sωcŽ9&Zo½υ’4½ ‘΄βŠ+FK/½ttί}χE7ήxc”oz_ΎI;τps0zεΎΓB€eΓ *""0RΓΝΐθ•ϋŽΦ ‘;οΌc nPιBδ»ξŠ–Zj©(y‹¦|SοΆήώφ·GΛ-·\4Φ&Mš-±ΔΡl³Νε’d­΅ΦŠš"ω&ι›mΆYτ¦7½)zε+_εΧqΕWD©W ‘ϋοΏ?Κ[’½ϊΥ―Ž^ϋΪΧF›nΊiτΤSOE0†›3€Ρ+χ"-nP±±€‘nΞF―άwό}!’·&*Θ_ΠkK‚^vΩε—EοϋΠ|°[n½%ͺ=ΗXΦ―ƒΚ<½δ%/‰Ξ8γŒθύ:gΐDPξ;,DZΦ―ƒŠ…Œ_ύ:gΐDPξ;ώΎYύυ6₯ς€ό½Ά$θeW\yE΄ϊΪλFΟ<σL΅|“σΪsŒeύ:¨uΤQΡ‚ .γGΏΞ0”ϋ ‘–υλ b!γWΏΞ0”ϋŽΎ[ˆ|aΝ΅£Ϊ132ƒ Πk#3.ΌπΒθ'?ωIOΚη›^'Ÿ|r4όσG―xΕ+’yζ™':χάs£ƒ>}ώσŸζškθu―{]΄ωζ›GO?ύtTZh‘…’­ΆΪ*Κ‘ΨΛ_ώςhΙ%—Œ~ψα€ΑRξ;,DZ6A`8#3,D¦e!ΐ?Rξ;ϊn!R{#υ)}dιe’Ϊc»h€ƒ ΐpF:gΌπΒ ΡψΓhΉε–U;οΌsτόσΟG£uΑD3Ο¦]>ω—δ)­Ύφ:Ρ3Ο<=Mύλ_£Ϊc»h€ƒ ΐpF;gŒv1«EHZwέu£UW]5j+ώ—½μeΡΩgŸ•φή{οθ½ο}oTΚ…ΘΆΫn•ΆάrΛh΅ΥV‹,εΎΓB€e£TšŒvΞ°b!ΐ?Rξ;ϊn!’oͺ^;fF6ΪA ΙτΞm#½^„€₯–Z*Ϊzλ­£ΆξΉηž(o%uσΝ7G₯£>:zΝk^•r!²Ο>ϋD₯όΌ–_~ω€ΑRξ;,DZ6½ƒ @izη  š•ϋŽ•W^)κ›…Hν Υ§ξΛ.jΟ1–Mο Pκ՜Ѵ«EHκ—[fu½ρ¦κγCΉοXsΝ5" ‘aκΥ z5gXˆXˆπ•ϋŽΎYˆάuΧ]ΡΤo€^+«=ΗXΦ«A υzΞΘEΓ1Ηε=VΞ?όhζ™gŽ~ωΛ_F?ώxtυΥWG»μ²KTZqΕ£₯—^:ΊοΎϋ’oΌ1zΧ»ή5½iϊŒZˆ0>”ϋŽΎΉe–…0hz=gXˆLΛB`°•ϋŽΕ[μoσΌηέΓ/DnΏύΆΧƒ ΐD™3N8α„hήyηζ˜cŽθƒό`tΑD₯ϋοΏ?Zi₯•’WΏϊΥΡk_ϋΪhΣM7žzꩨd!ΐ?Rξ;6ήxγΘBd˜&Κ τ‰2gXˆΠΚ}Ηί"λ­·ήί¦TΏ Χ–ƒΤDT€ώaΞ€±Sξ;,DZfPz͜c§άwό}!²ζškώmJεω zmI0HT€^3gΐΨ)χΉ±&ƒ Πkζ ;εΎγο ‘όOEΚςτΪ’`2¨½fΞ€±Sξ;ώ~Λ, ‘œAθ5sŒrί1Γ"7έ|SτΎΝΧͺνvά)ͺ=ΧXfPz͜c§άwXˆ΄Μ τš9ΖNΉοh½ΉνΆIcR.ž~ϊιiΪhΣΝ’+Ό2Κ?葇’Ϊse ΧΜ0vΚ}‡…HΛ *@―™3`μ”ϋŽΎijƒ7‰Ξ9χœ¨vL—T€^3gΐΨ)χ"-3¨½fΞ€±Sξ;,DZfPz͜c§άwXˆ΄Μ τš9ΖNΉο°i™Aθ5sŒrίa!2ƒ Πkζ ;εΎΓB€e ΧΜ0vΚ}‡…HΛ *@―™3`μ”ϋŽΦ ‘I“nν΄\ˆœ}Ξ9Qν˜.3¨½fΞ€±Sξ;,DZfPz͜c§άwτνBδ±ΗξΌσΞ¨vL—T€^3gΐΨ)χ"-3¨½fΞ€±Sξ;ϊv!oT€^3gΐΨ)χ"-3¨½fΞ€±Sξ;,DZfPz͜эVX!:θ ƒ’Άn½υΦhήyη^ϊ—F‹-ΆX4ΡδΧ7ΣL3MΣ#< gz?ήΝ?όΡ~ϋν3^Ήο°i™Aθ5sF7,DΪ™ή…Ζτ>~Ό³€ώSξ;,DZfPz͜1Ά.Ίθ’θMozSτάsΟEm­³Ξ:Ρ†nτργΥw܍v‘1½―,D ”ϋ ‘–T€^3gŒ- ‘Ρ± θ?εΎ£υBδΦ[oθ *@―™3ΖΦΪk―mΉε–ΡHΝ3Ο<Ρ‘G ‘Ρ±ι§œrJτϊΧΏ>`°•ϋ ‘–T€^3gŒ- ‘Ρ± ‘ώ`!ΐΤΚ}Gί.DΎΎε7£UV_#ͺΣe ΧΜcγΕ_ŒζškθŒ3ΈFκmo{[tμ±ΗFƒΒBdt,Dϊƒ…S+χ"-3¨½fΞ"ΣΗBdt,Dϊƒ…S+χ}·ΉρΖ’κ3ъ«~!ΊΰΒ ’ΪcΊΘ τš9cl\wέuQ^μ±Η’α,΄ΠBQ>©Ε[,*=ψΰƒΡη?ω(2―{έλ’Ν7ίΝ1ΗQ~^Ω2Λ,5― ‘^}ύ£• ‘\|•.Ύψβ(?αή\ΌΙ…Θ>ϋμ•Άήzλhω嗏J½ϊχ³`jεΎΓB€e ΧΜcΓBΔBdzΎώΡ²± ”ϋŽΎYˆμwΐΡϋ>4ί?lΫvŒjΟ1–T€^3gŒ_|1škΉ’3Ξ8#©Ά ‘±ΊeVΣ›O—ώς—ΏD3ΟΎ­±ϊϊG*"oxΓ’+―Ό2ΚοƒE]4Ϊ`ƒ ’±–―~?΅Ρ.Dzύο—·ΜΛεe—]Τϋίώ(]ŸΚ}‡…HΛ *@―™3Ζ–…ˆ…Θτ|ύ#e!b!@)χ­"7ί|Ә–orwΧ]wFεΗo»mRτ—Ώ<•λ *@―™3ΖΦE]½ρoŒž{ξΉ¨­‘.DξΏώh₯•VŠ^ύκWG―}νk£M7έ4Κα_“‘.DR^ˆΞ α³Ξ:k”Ώφ΅―EΓ]PNΗ|”―_ήk³Ν6‹†3½©^ύ#•Ξ·Ψb‹θέο~wτŠWΌ"Κο‹ΡΎΙHελΠο ‘ΤλΏό>Λ[”εχ_>Οpήώφ·GΛ-·\ΐψTξ;,DZfPz͜1Ά,D,D¦ηλ)  ϊOΉοθ›…HΏgPz͜эΌ•Ձ4yΰ’Ό…Χgœ0>•ϋ ‘–T€^3gtΓBhΛB`b)χ­"ω&ζƒšAθ5s@9ꨣ’\0`|+χ"-3¨½fΞθ/"KΉο°i™Aθ5sŒrίa!2ƒ Πkζ ;εΎγο ‘Ο­ψ…ΏM©< AΏρΖ:ƒ Πkζ ;εΎΓB€e ΧΜ0vΚ}Gί-DN9υ΄h•Υ׈ζ_xΡθSΛ―sμ±Qν±c™A€Ώ½; ’€ <_ΤE‘#vπΨπƒa(οκ.―ˆr:ΓΘ‘8€:\/ˆ€2rΙ}©»ˆάΒ Θα*‚ˆˆ\# ‡Κ%2ΜΓ! r¨‹ŠαΫύŒΣ“dMUueVggώΏ/SYΥέ•UΩ™ωLgIUη8C’$Iͺ―βΌΓ@€GT$I’$Uγ I’$©ΎŠσŽž"?όP­-Ί?l6}«pΕ•? οΉηΒ½χέŽ9α„Pφur "I’$©κgH’$IυUœwμΆΫnΑ@€ *’$I’ͺΞq†$I’T_ΕyΗΛ‘<π₯QΕr½lHP₯ /ώv8β˜cΓSOύ&δ%«ό±πϋί.”=F¨H’$Iͺ:Η“£Y³f…‹.Ί(¨ΌυΦ[/œώωaΌΝ™3'œpΒ ARϋ«jϋ1Υ³ύ”^Yqήρς%³ DVρŠ$I’€ͺsœ192ι-IγΝ@€šl?₯WVœwτ1Y^«ΣΞ<3œω³CΩ2ɁŠ$I’€ͺsœΡμ,XήρŽw„^x!¨ΌͺNh>ϋμ³αΝo~sxξΉη‚€φf RMΆŸ++Ξ; Dzδ@E’$IRΥ9Ξhv"ύe "iΌˆT“ν§τʊσŽž"=΄ΌV—\zY8τˆ#BΩ2ɁŠ$I’€ͺsœΡμφΨcpΨa‡­ΎͺOhΜ93œvΪia؝|ςΙaήΌy‘ξnΊι¦°α††ΧΏώυαο|g8逓‚†“υ?ܚ6™μλ’·ŸR“*Ξ; Dzδ@E’$IRΥ9Ξhv"ύe 2XSύ„xΣ²ώ‡›ˆˆTWΕyG‘k•^ΎΕV \tQΈΡ}αΖω7†#Ž9&”=F¨H’$Iͺ:ΗΝμΕ_ k­΅VΈυΦ[ΓdkφμΩaX'Δͺ>‘yΖg„""d―8οθy ²|ωƒ΅ΚΘ½χίv™½{XoÍΓv³v 7έ|K(ήΏnT$I’$UγŒfΆ|ωςπͺW½*όωΟέzβ‰'ΒN;νΦ\sΝπ–·Ό%Μ™3'όλ_ u7Q'4=τΠπήχΎ7Όρo ³fΝ όγC·ςDΰk_ϋΪPχσφΧΏώ5qΔα]οzWxίϋήΞ>ϋμ0¬υW,/“—rk[ύώ±ώWm²o?ϊ­mλΨΫO©Ιη"=r "I’$©κg43‘ρe RoΓ>!>μ DVί°ΧΏˆˆΤ–ŠσŽ>" Εc=ώτ§?†ά =όŸΒγ?Κξ['*’$I’ͺΞqF3»ωζ›CžHκ΅£Ž:*\qΕαο{xψα‡Γ»ίύξpΦYg…Ί›¨šk―½vX΄hQψνoς-»οΎ{θV>o9˜ϊύοκ*Ο?yδ‘‘xBτœsΞ Γ>±ψΟώ3δσ:wξάPUωϊΘηΉWσηΟU5ΡΊώ;5Ω·ύΦΆυ?μν§ΤδŠσ‘9P‘$I’TuŽ3š™Θψ2©§ΊOˆηλ#Ÿη^ˆ §ΊΧ§ D D€ΆTœwτ<yπΑ¦4*’$I’ͺΞqF3ο@€[ωaΌyι—ͺjΚ ν<‘™'‹]}υΥαMozSθΦC=ςϋ­ϋ„^žξτ‘Κy"²UξΤή{ο6ήxγπΒ /„©V]οŸlͺΆn?ϊ­mλΨΫO©Ιη"=r "I’$©κg43‘ρe ROuŸŸ,ΥυώΙ¦κϊ7YQΫΦΏˆ΄²βΌ£Θ²)́Š$I’€ͺsœΡ̊ͺώόσΟ‡n]sΝ5aέuΧ oxΓB>Nš1cF¨»<Α—'<λ.Ohζ‡[ΈpaΘη!/Σ©‰ώPΰ=ΤέDΠμtΙ›<αΟk·Ξ<σΜ°Α„©R>y"τΉηž u•―±C‡^TuΙ€¦Ύ&ͺa―NMφνΗd­ͺυ?U·ŸRYΕyΗ*‘QΕr½lH0•8P‘$I’TuŽ3š™Θψ2©¦|ώ†uB<_eCΥ1©§a―NˆLLU­ieΕyG‘₯SšI’$IUη8£Ων±Ηα°Γ ϊΓώ^ύκW‡όήΌ€K^Ίdν΅ΧmˆΌνmo K–, ΏϋέοB~(π>ϋμΊ•—F:υΤSCΫ;όπΓΓϋίώ―«ΆΧΤχΟ°kΪϊŸμۏΙVΥλͺm?₯ΥUœwˆτȁŠ$I’€ͺsœΡμ DϊΛ@d°švB|X5υύ3욢ώ D†[Υλί@DZYqήΡσ@dΩ²₯΅Ίνφ‘_p#f}j—PΆΜ¨MΆόH(»­NT$I’$UγŒf·`Α‚πφ·Ώ=ΌπΒ ‘SsηΞ o}λ[Γλ^χΊ'p:θ ΠΦΊyBσC οyΟ{Βk¬vάqΗΠνCκŸyζ™°ζšk†‰ΊdΠ°ϊΗ?ώΚ.KU¦­―Ÿ©ϊώ±ώWTΥφc²UυϊŸjΫO©—ŠσŽ—"£¨n ™I’$IUη8£Ωˆτ—ΘψrB|E"ε뻨m?f RΎΎ‹Ί­ι•η/D<πΐ—F‡"Εr}Ω²%΅Ίσ;ΒΞ³weˌΪ|ΖΜPv[¨H’$Iͺ:Η“£vΨ!\xα…Aυ6gΜpόρΗIRoΩ~J―¬8οXe 2ͺΈ@ξ — ͺd "I’$iͺε8crd 2άœΠ“€ρeϋ)½²βΌ£ηΘ₯Kjuǝw„ˆ”-3*"e·ΥɁŠ$I’€ͺsœ!I’$ΥWqήa #*’$I’ͺΞq†$I’T_ΕyG‘šʁΘ¬ϋΥZ9)œΊ8P‘$I’TuŽ3$I’€ϊ*Ξ; Dzδ@E’$IRΥ9ΐ$I’κ«8οθy ²dΙβZέ~ΗaΧέχ ϋΫίJε@€μ1κδ@E’$IRΥ9ΐ$I’κ«8ο0ι‘I’$IUη8C’$Iͺ―βΌ£Θ’Zέ~Ην!?T½l™Q+"ε·Χي$I’€ͺsœ!I’$ΥWqήa #*’$I’ͺΞq†$I’T_Εy‡H¨H’$Iͺ:Η’$IR}η"=r "I’$©κgH’$IυUœwτ<YΌψώZ=πΐπ‡?<Κ–υη??Κn«“I’$IUη8C’$Iͺ―βΌΓ@€GT$I’$Uγ I’$©ΎŠσŽΖ DšΞŠ$I’€ͺsœ!I’$ΥWqήa #*’$I’ͺΞq†$I’T_ΕyGΟ‘E‹ξ›¨H’$Iͺ:Η’$IR}η"=r "I’$©κgH’$IυUœwˆτȁŠ$I’€ͺsœ!I’$ΥWqήa #*’$I’ͺΞq†$I’T_ΕyGΟ‘ϋοΏwJs "I’$©κgH’$IυUœwˆτȁŠ$I’€ͺsœ!I’$ΥWqήΡu 2ώOΒΒ…χ„²aA›εϝσ$I’$U•ˆ$I’T_Εy‡H"’$I’κΚ@D’$Iͺ―βΌ£λ@$Χ\sUΈλ;Γ}χ-l΅ό9ση^ΈpA$I’€ͺ2‘$I’κ«8ο0ιΐ@D’$IRέˆH’$IυUœwtˆ<ύτSα†ζ…σΞ;;œqΖΧ[νΌσΞ 7ή8/δσ I’$IUe "I’$ΥWqήa ˆ$I’€Ί3‘$I’κ«8οθ:Ιt€Ι’8ο0Z§8οθy rϊO€ χͺW½ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ ˆΠ e'Ώ <˜,Šσ uŠσŽ€ΙΞ@h= υ D€Φ3ZΟ@h= υ D€Φ3ZΟ@h= υ D€Φ3ZΟ@h= υ D€Φ3ZΟ@h= υ D€Φ3ZΟ@h= υ D€Φ›6mZ0Z+"λ¬c ΄Χ΄iλΌ4}·ύ D€φ2ZΟ@dHxππλ~ <όπC‘lY`j™θνΓΗwΨ)\rι₯‘l€a²25=ύτSα/ΦΫhγ°Νφ³B.χƒ^6Ÿ13δ~τΟoΏ-Œ}L€± D†Δ@θΔ@`UφO¦& n"Cb ;ξ²kΈθΫίeΛΐ°ˆΐJφΧedjϊᏠ[|ϋπ«_=ςφ§žϊMΨp³-Βuσζ…±°:Σ¦M "53iΨ4‘¬dQφO¦& n1Yg‰ˆμ±Ο>!O¦u?΄aΨnΦα’Λ. eΡd"Ta‹™ ίόΦ·BΩ2c}x‹'š­νΓ'>ω©π/ωn([f”Τ!χο=αΔPΆ Γ·|ωςπ…ƒybωƒ}8μ2{χ0θ₯‡~φσŸ…}φΫ?lΈιζ‘x|wΖ7Ύž|ςΧ!οod…£Ž=.δ~bzί>Κξ3Φ χοΥΝ·άvί{§uΧί lΏΣ'ΓwΏwi({ŒQ'rJ8ψ°ΓCρφϋξΏ/δχμ³Ο„βr₯Χύο‰6θλbΠνȍ7Νω{βƒo6>#yμ±α±Η~Šχ`UΟ<σt8ρ«_ Ή]ώΟ 6 ϋp@xpωƒ‘μ1ϊ±ΥΆ ·ότΦPΆΜXΓώώΊiΜ%³ςaρ²¬d N"΄Qξίˆ4‹Θδ2θ‰λAοί+‘ D D&‚H7)0ύϊΧO„ož~Θ_ΠΏΈϋaμc4™U0i'Ϊ¨Σώ=kη„O}fvXΌdqȏGBΨx‹-Cΐ–=V™k».ό―υ7'ŒτŽZ°paΘγ»<žϋκI_ —_ρƒc€ά―Ύ:τzβΊhΠϋ]}ν΅!ΧχΙ§žςuυπ#‡ο\ς½°ώ‡7 _?ντP|Ό£;>~τΡ‘xϋm·ίςλoŸh“e RΤολbΠνΘn{νς’gyΏ»ywΘΡ?θ°ΓΒΨ― ΐ+rϊaσ3Γwέx`YΨsŸ}Γ»οΚ£ .mΎeθu?qXί_― D†Δ@„*ˆ΄“md L"“Ϋ Aο_d ²*€‰` ŸΖDR>Αω ϊο?δν?ώx8fδΎ£ΆΨκ£!wΈφΪχsaρβ‘_Τ#Ζ>φ¨Ό=OHώ\/l9sλ+ӟδζ ΜΗΙ?Νƒ;ο‚ Bρ„η·.Ό(lϋ‰BρqΣΒ{†όω;ύγ•y@²σμΩ!ŽόηόSθNχί_;9μΊΫΘ xΔzm.»όςPόΣΪ|εŽRξπ<ςθ#!?ίqδλŒϋ΅ΗΊΡύ!Ÿ§E‹…Ό½Ϋ‡tζΟqΧΏ>½Ηž!Ÿ‡™Ϋ},\wύȎۈβύ—.[ςœχΛΧAφŠ―ƒβγtRυ@dПwΠϋϊΎΛ―ό—Ώςuϋ 7ωΌτg? ί8gnΨlϊŒšύ₯# 6δƒn_Ζ»}(>N―˜sPΘΗ+ΚχA.?θzΦz`rο@€ξύ΅A―ŸqΦYaΖ6Ϋ…βνM7s»‡ά(ή~Ο‚{Bξ7,]Ά4—+Κύ΅άΛKή”-Ϋ‹AΧsΗό9Ζ»Ÿ9zl3ͺΣρΝ°_ƒ4½*οΌSΩ²cε€λύλ­ς}V\_ύΚύΚό:ηžw^Θο//Ι‘ϋ©·ίqGϋ½οφ‘ίύο¦mGϊ}]Τ΅IsGΦέ¨|t›PΆ +εοΑ<οXΌύ—χάr»œƒβrݜuΞάΠ閝 λϋ땁ȿενωΔχ»Γl ΫƒˆΘXƒΎοςλˆ¬Κ@€&0i&‘ώφ3GmFˆ¬ͺΈΎ D DΖ2ό=XχΐΑ@€b˜Š—ΜΚ§δrϋπω'’σΔxώιeώ©vžΨοvΒ-oΟ₯­Άέ.|ο²ΛBqωgοφϋΒBžψΏχΎ{Γ¬OξrΕζ ΟάαΚ‚ωύοΉΟgCρφAε‡6Ω4ά8~Θη/?μ0ΏΟ‡ZŠχίdΛιαζ[G~ŽΕη9$φϊμΎaΩ²eaΙ%!tςφΌί£>ςO£οΈσΐ·§―rJψ̞{…βν½`ηŽo~dΎO=γ̐œβTώΙπηΏxPΘη)?όo‡w ΕΧΑΨοauκˆŒχητώEύΎοςληNώ }Ύ―ωα!œσ„{άr;’―ΫΛ―Έ"ΏΞ Ϋ—ρnΖ~γΡο%³}Τ½˜\κˆŒχχΦ ΏΧ›v"³_y‚?χOςDeώόΉΎ>υι‘ύΪΕη―“_ήσːϋ3·ώτ§‘lΩ^ Ίž‹r=φ»Ÿ™ϋ'Žo†ύzt 1θύSq}η|)[v¬|ώώη?Šοσ¬tΊdV~Hw§Kfε₯ΩςρσψϊΙί<ςu™κZΌ Ϋ‡^χΏ›ΆιχuQΧv$εzHeΛπμΛ—¦μu+ƒ@ρR₯½Ϊeφξα?Ό2”-3Φ°ΏΏ^M›6ν₯iλ¬c R”·χΊΓœ;"""Γ?P5)g ΐD2i&‘AξŸ D D D&žΘψΔ@dDc"ωεΝΥΧ\ς~ω‹7—Λμc{Tξ¨δ ύ»~ρ‹P\“ό“ΫόSΨόχ<‘™_?Ot޽ο¨y7ό$δrΕžΉγ7ηCCώϋoFvΪFmΈιζαŠ+― y{Ur‡?/™UΆΜ¨ΌτΝ;δΏηύσΐdμ}Fε@ ώβ₯¬R~Έb.——ΚΫχ?π‹!„9=w°r`pΙΘAΝ¨Ό=υz€}φάsCρφΜδχ——ΘZxο½!½Σ νŸάpCθΆ\'u DϊύyσφAοίM§χ]zωλŸϋΝPΌ={y‰„'žx<—›sπ!α+#―ύQωοƒn_ͺΪ>ŒWΏ‘ρΗΊΧ“Sέ‘~o λΈ‘ις?,ΜήσΏB>)χ7σ„wΩc”Ήρ¦‘ίχ#ςqς?<•-Ϋ‹ρηβrτΊŸΩιψf’ :Πτώ©ΈΎσύUΆl™tvζ™!=‹Η;ΙF^Ί΅ΧχoUΫ‡^χΏ›¦ίΧE]Ϋ‘ό°l²YΘγ©²eXω{/·Ώyι©²eGm:}F负έIξwεΐβ±Η eˎ5¬ο―_ϋοΏ0ι’ΣsU'Nρ„gξ(¬;²S7*€(?t.Ol?υΤoΒΨΗBξπw{Αε‡ΘtΚ)!=οέο]ΖήgT>OyΙ³βν)”9Ÿ§όΣψΌύšλ 9 Κη#O(η‡έ=ωδ―ΓΨΗΥλv>οΕΫ‹ί_BςηΛY,ή/u{t“Ϊ?zyTΩ2cε%ΠΎsΙχBρφρώΌyϋ χοϋ.uϋϊω§xέޟ‡qd(nέΎδλ’ΫΧτuΡIΏ‘ρΗΊΧ“Sέ‘~oUuά0Ωεσϋ…ƒωςgξgζ~d§ΓEy<“Ο[ώώ/[Άγ]Οy{Uϋ™Žo&Κ Aλ»)—ΜJωΎΝνPξη₯\οΈλΐΛW΅}θu»iϊ}]T½ΙAΘF›oςveΛ°°.I•—έ}ο½CΩ2e†υύυΛ@δί_gΌ;ΜUπΜJ‘Ul DVe ²κγwϋϊΉ‘νφώ4©χu0θz`rκ΄ίM]ϋkU7Lvωόˆ¬Πm?Σ@€\q}ˆ¬xœ^χΏ›¦ίΧEΥΫ€ρΦΐΑ@€&έ˜ςOsςO'σ’M‹—,ω‹;Ÿθβύ;ypωƒ!οΓ]ςOςRLη|󼐿ψσώ½^§ΧK%ε‡Ž㜹!wΠΏςN Εε«’;όωαheˌκvΙ¬N,ΕKfεz+.Χν’YΉ½Ωτ!/!–—λ΄γœrύU}€ςί;­ίA/™•ž#=6”-3*7ΏΞM7ίŠΛχηΝΫΗ{Aίw©ΫΧΟ νxOΔΊ}©zϋΠ― ˆ0ΊνίwRΧώΪ ΏΧ'»βώα-?½5”-;*H{ύΠΜάΫrζΦ!Ol—-Ϋ‹ρηaνgN”Aƒή?εσ˜—Fκu}ησ™_ρβ‘χ刼=gЁHQGζΧΟK^ε‡τW΅}θu»iz}]T½9ύ¬³Β&[NwςξP\€ΥΛσ€9`.ޞ—ͺΚνχ‚… BqΉN>ΕƒB―—π/ͺϋϋ뗁Ȁ;Μ"+ώ½ΫƒΘ ƒžψ6Yυρ»}}&ށH³χ D DΖs”Ο£Θͺ DVe 0u DjλSώΒΜaΛK&ν{ΐαΏ>·_X°paΘœŸίφσΛ凕η₯jςΓ~oΈρƐ·η/ψόzv˜sp±sB^κ+;μΌkΘ›;ΕΗΙ? Ϊx‹-C~_Ήƒ_\>1ςœŒš±Νv‘l™ΥΙώ8ε₯~ςΐα¬sζ†nτα?_ρώΉƒ9φ±ΗΪeφξ!ΧS<ςC?½ΗžaΟ}φ e1*?ό=HΉ£UΌΔVQΏͺ°σφOξϊ™ŠρΎ:ΙΧG^šλG?ώqΘ©ΞηqΏ/ΆΩ~VΘχIρρύyΗ{ͺήwέΎ~U'βΗ»}ΙϋW΅}θΧ>ϋνŽς—ΓΣO?ŠΛw=ζνΓZL.Mˆδνƒώ^tΏ{’εΐbΞΑ‡„ δώd~Ψx^¨ψόu“—ΈΝKημZxοΟsžψ̐•ϋΉω8γ]ΟΓΪΟLΓ~= :ΠτώEyΙ¨|½œ|κ©!Kyτ‘—ΛKν”SBρρˆ\7o^ΘγΕ|]δϊΞ%—„ό~σOyA·½ξ7m;ολbΠνHΎοσ}˜Ϋ‡±_€ήrϊaσ3C^ςyž5Ο£–=F™ό=–—@Μύ¬²eW§οoΌ D*Ϊa6ιν€Α@Δ@dTUο»n_ί@Δ@€‰c L""ƒάΏΘ@dΥ탁ˆΐD0ιΟ€ˆδΛ†›m.Έθβ'ξOόκWΓτ­· y.wt―ΌκͺP|ά<αŸ^žΏΈwΪυΣαΈO v˜—.[rζΰ /1uή„άaοtΒ3O\矌~fΟ½BqΉ’#Ž9&δ‡Δ•-³:ΉΓ•‘ΖQy7OΌ|Η‘ΫGδ‡ΝuΊ·†|‘ηΐ Χc~xZ^ϊͺΫ αάaΚη3Oό—-;VΏΊ°sΗΟ}>ςuπяmςu–χμ±_…±_£Ή#ŸίoΎΞ7ωȌΟoώιwΩcŒτητώƒΎοΊ}ύͺNΔΊ}©jϋΠ―›oΉ%δλούλ­ŠΟη λqXλ€Ι%χοσχG7yιΤό=UΧώΪ ΏΧ›v"³_ω<ηώjΰζϟ έιηοUώG₯½?·Θx΅ξ‡6 ΫΝΪ!œyφΩαΙ'ςώƒηΊχ3Sέ―‡|δΟΩMq?rΠϋχjώΝ7…έφΪ;δqd.ςΓν»]JjЁHOηλj«m· ωΊΛυš—R+ήΠνC―ϋί½τu1ήνHžΟ)ϋe:­gV•—†ˆΌMrβCΥaςΙAΘ²eKCΩ6‰c @£ˆ”ŸxšΗ@€Ω^1hͺY³f…<‘Π/ ρ D€ΑμΣ¬«ΞϊΑIENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-coqtop-compacted.png000066400000000000000000000066021516144147600232500ustar00rootroot00000000000000‰PNG  IHDRτ™EzsRGBΞιgAMA± όa pHYs‡‡ερe IDATx^νέ=’›J`ο‡x μΐΉjΰdb’WγdBΧ$TM8εΔ΅οΐΉ·Ροήώ4 !ΡqΥgK·ωkΤGδ‘ζ“ό1Dt7`‘ˆς‹;*M}jLU Ά=θώNζδ5U–!ΊςWQ˜²ͺMsͺM9^ΰΒθNY3Πtη r]W 4Ρ}π7Šju υΙ i/gS—‘mΪήΆ}[Y™Ίρ—ΑuιΧsΛvυFΦ‹ΆSΚώΩOνmχ'ΗbΫΒ±ΰΰ2ΠτόΥΞ΄…)¦ΪFv!ΆΛΫΆ°¬oσ‘³! m½εΖχ‹ΒoOΙz'Πš€Ώ±:АF‚#3e%—μ!hV*ΠQ›<T2³Ϊ ‚-«mM=iΈυΪYZfv‡¦‡δol΄γίP ‘΄΅υΆΑάh]Nn‡ύOτ…¦ΰo¬ ΄Ύ3.Βύ’’ΩΊ}-μ‚hΓΦΜq »πιe΅Ξς6΄φ4€Ϊ¦Oξ  k>I„ϋΡώμ± Ÿšξž b{™Ϊi/e§ /q P›paτυ2~²ΠπΥ¦jίPon…Ί\Κχfsm›zS,ή^UΪΩ{jš,ήLΟϊ6άγ™–ˆ&ΑβΘeΆ}£MgW!³{;;Ρ°HDy‚E"Κ,¦ύwPΏˆς‹i( ΉAύ"Κ,¦‘€–ϋκκuPGύ"Κ,¦ΕΑ8<š,¦…ό¨LύΫύ7Sσ^τ3ηΥύTΨι£Δν#σϋ+~Τ¦ρυΈ­όθjΪ”ΊκQή`1ΝLΒρ»2₯Ξ|¨6(Kl ττώŠΧaΩΡ±p†¦‡‹iÐ؀τj‰ύI ΓΜέ›…ΡΊκQή`1νPΦΆ“©Γ%ψθXhz°˜vn νςk/Ήηݘϊ‡k+ήρ%who‘~ε ΣhβφΣVο₯©μεwΧ^ΎΗŸ*σuΤ/’ΌΑbšJΦPΏˆς‹Iέl—/Τ/’ΜΑbšρrƒϊE”7XLCΙ κQή`‘ˆς‹D”'X$’<Α"ε ‰(O°˜4υ}ήϊ½ΧlcΫ£΅‘Œά,Qž`1ιHώlcΫ­ΫPFn‰(O°HDy‚E"Κ,Qž`‘ˆς‹D”'XLϋBD‹ όμΣόΑ~~ύeώšξΟ/ύΞ―Έ3σΥόςϋΠ?~^ΨFtc(?ϋΕ4{°€Ώζϋn!ΖΎώ™ν\[ήό—$>‘6:4”Ÿύΐbš=X τ/σu؁1Π””ŸύΐbχώϊΆχGfλoΠKρΝ―?ώίvχOίδί°?_ΫΞΫKψhΫ(œ— tρ˜ζ₯2΅ώώ«·ήΧ―žρς#Oώ«ˆe]Ψ>βCωμχ©?6ψR΄νΕsmšθwq…Άς­«ujSΆΫέbώX’΄ο•)PpφΉ^ι"νŠώ͞OŸΑbšνΔΔ ύν»D; wοΎ#‘ϋ§‘φm’@KΠ?‡νHΈεUωhϋ— τιC‚ρ€†{ά@X8°7Z–—RκL+ŽƒYΘq΄hΠvωzώX’6zΛΉvAt‰-ZοάΗvu 'Ξ'ΚΟ~`1Νvb"ΠΔί»`~ωlgt7Kλ:QΨ‡β™ΫώΩ7ΠξΦÝόUϊjΊŸ(”φ ! ‘Ύh†ή?Π3Η2‘κ_gIΐy·ξokfΟ'ΚΟ~`1Νvbk Α:–ΆΙr!vf”@kΫΙΤaί£€ Φ=Ϋά±, Λ―œ‘·œk]fKΐΞ~lWφoφ|’όμΣl'&Β™Όδž tχzϋσΟύ/ΉΟ~Πu€­} =θΖΤώ5^ρ‚/ΉCϋˆ½Δ“'„Ε―IηŽe•ώμs½E[:’zSlΈΌ§!v―-λόόκί|λ/ŸΦ}GΏŸλ₯τ—]{)ΗΦΝR]έb {.ςΨ>^ ιHΚ·h@Ρq όμΣЁΣνΘ έ,ΎR «BωΩ,¦‘'’1”Ÿύΐb:p"CωΩ,Qž`‘ˆς‹D”'X$’<Α"ε ‰(O°HDy‚E"Κ,Qž`‘ˆς‹D”'X$’<Α"ε ‰(O°HDy‚Ε ψοp*PΫR—ΨΖ₯ι1LS (i8¨ S5GδȚ0N-{Δ@oq/ύ  ` σM­Ή@ϋΆ²2uγΎ>Ά»œkϋdв6―ΗmEΥΘmΏN]Ϊϋφw•ΡώλξλjY&lσSν« β²ξŽ‘S›ΆOχ!}œK¦¬δXS—Π7χΎNέΫΟτq¦ϋ'· ωΧ―§}i·k£ΖΤr.νΏΡ> 9ζξxϊmS.wΞθ ~°LZœ¦’A!χeτΛT›<Έ2ˆ ;n³r㙬―Σ „n€†Ϋv28ά`κ–·Ϋ—ΑέτŽ{Ž‹–ξCκ8Σ\υλ*:IzώQ §Οuͺν‡άΧ'hϋ­Σ»?ܞτ½έζ΄σΟ]ΐψΑΝΠ½= €Ή6½/νaV°\[χλϊ¨―γΨΆΕƒ™ZvPϊ0œρ6†Ά9˜ τΜΉ^ΪΏ˜žOy‚θŽ―Ώί^%iό“H»ά΄νηŒ.hψ λΛά@J΅Ιΰδβ ψυΠ%=qA{―/I:Τl_€Ύ$”ΫΟ]{ Ϋ“ƒ₯} ηRΊ- }=Άl†φ― Γ₯₯έ–\Άιm»ύ0ΰt ωΧg£AŒτgXG}8p^ϊ’{κ\wνΈρr»α6ύύBŽ]„e΅ί½Χή’ηΜ?†KΆE›Ι_r’ΫΛc™»Μ €ωAΦ½©β΄R u• Š θθM1χ†ŒkλmSί ŠχŸΰžΒ6Σ}HΞΕ\°“oŠ΅Άzύεzd–†oŠ _.…ΧΰΓυθC€ΕŒθΰ‰_ΟΜ`&ΊO°HDy‚E"Κ,Qž`‘ˆς‹;Όc»»ώ›fλί₯&ʊό₯οhKθο _;Нώ•έ!ύΏέΊh’ϋΰo€VH™ώDΞ ΄½mϋΆψ“CρΘ²]½‘υ’νLύ „˜ϊtWŒ¦ΰo¬τp¦?‘“ ΄ ±]ήΆ…e}› ihλ-7Ύ?υι.{ίc ιψ«­q?O=ώDN*ΠQ›QG΄Q£e΅mξΓŸξrΛ: 4=cC †Z₯­­΄ ζζ@λrr;μ’/ 4=cm g?‘γ‚hΓΦΜq »πιe΅Ξς6΄φ4€Ϊ¦Oξ  k>I„ϋΡώμ± Ÿšξž b{™Ϊi/e§$>‘Σ~ϊGλφΫEβ@λ§τυ± ήά uύ:›8ΔΪ6υ¦XΌ½θΣ]q¨hz°x3E<λΫpgZ"š‹7"—Ωρg‘{ŸΝ&’`‘ˆς‹D”'XLϋ2γΏ ύ:WDΧ‹ih0(ηBϋ9"tˆΣΠ`P Ο…φsSξΎ«§A+’λΕ΄x‘@ž νη¦h:$XL ϊΉ2υ‡ϋo¦ζ₯pƒrβ½1Ν»lο·lχνOŠύφ84SžάOšήJά>2ΣQ<Χ¦ρυΈ­|λjΪ”Ί:WDΧ‹i6 2?*Sκ,%ƒΏΤ ¬KΨ–mΌΊm7ο…y²Y›=ΡQ<Ι“JXvΠΖš Σ†Ϊ†ιό@Ϋπώ§Ϋ–mΕ΅843Σ{_Ϊ£š¦ ΐbΪέZΫN¦—ΰΓ°3ΠtL°˜Ά$Π?τ2UB‘―CmΖفΆΗ°φ’{.Ѝ©Ÿ][ρ‚/ΉC{ +’λΕ΄»΄ qϋ —Tφς»k/_βOͺω::WDΧ‹i~PCQHΛ ΜkΏΆ ΪΟ‘sEt=°˜†³ΧΝZ—ƒφsHθ\],¦‘Α φ\h?G„ΞΡυΐbΜ δΉΠ~Ž+’λE"Κ,Qž`‘ˆς‹D”'X$’<ΑbΤχyλχ^³mΦ†2r#°HDy‚Ε€#=;²m·nCΉX$’<Α"ε ‰(O°HDy‚E"Κ,Qž`1 }tφΞ?‹ihΰΡ>Πω'Β`1 <Ϊ:D,¦‘Gϋ@ηŸƒΕ΄πΈΏ*IΏ2χ£κ~ΥLBρΘφύΎήJ{ίώή«αχb_ΘΩϋ[ΩΏΩσ‰Ξ?‹ivΚΐ›ψ½PI}ϊνλ―§ρƒέ…nώIΔΡ$Άh½ ϋkm τΔωDηŸƒΕ΄Δ—ΤOq_V?Ά$`nέ―ΫΟͺ€­΄u[ϋ7{>Ρω'Β`1mc [fθ-ΣeΆlλώZ›fhšΞ‹i™z+š2‹i τ<šnΣzƒ‘v…Ξ?‹ihΰΡ>Πω'Β`1 <Ϊ:D,¦‘Gϋ@ηŸƒE"Κ,Qž`‘ˆς‹D”'X$’<Α"ε ‰(O°HDy‚E"Κ,Qž`‘ˆς‹D”Oζ吖tΎ§IENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-coqtop-multigoal.png000066400000000000000000000107711516144147600233100ustar00rootroot00000000000000‰PNG  IHDRκQohssRGBΞιgAMA± όa pHYs‡‡ερeŽIDATx^νέΫ•›Κ…aηS©Α αόΜ›Cπ ο‘CγΤͺΠδ&€ξΥΫγσn- θš*@-ψα›˜'‹l‘EΆΘβ›tΣπ1N½SΣή!΄χ1}dcοΔ<ΐ7Πυγ4–Ξ<SχΦ}vPέ@Pρu]7ΉψΐΕΞό1t3½ Až΄FUλσΤIη;·WΗcΫωX3,†hικ .‘ »·aD‹aŒ α ΣBxh·L[‡Ώ<Ϊ‹Λ²|ς°ž»λ‚³μ2zgN&­w5W뀐εz·Q‡©ŸOβ΄#y:.ΝuΏ;ڌΎaΪΦΙ€ϊυϊ.ŽΆλ°>ucdρKΈz„‹‘mΓόΓdρ ψ]ΡxrgαζΡ€,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[dqWΌXuΉZ`%\7—iLϋΧ¦©ŒΌ,°EwYz7cΣΎzšΚΘΘ"[d€-²ΐY`‹,°EΨ"‹ϋώχͺ…,ξSA»K΅ Ε} ·ψ_}πϋ§{ ŸςΣMέο|7ρΊΪPΘβΎΤ*h?{ΌqκζΗœθπ§'¨ΐu²ΈoΤ<ΒΏΚγ1ΨΈ@χ­‚FʏuπφTΰ*Yά·>Fύ;ξφ6*p•,ξ{Ψυ½ˆ WΙβ>‚ |6YάχdPέoύΎxJ΅ Ε}"„·©v²ΈOν.Υ€Bχ© έ₯ΪPΘβ>΄»T; Y`‹,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²x \3iœz§¦½C{y±wbžwHν~^{ΐ&Y<πΩA]tΓ΅ΰtύ8%δγ0u_°Μΐ ΘβοT7u]7Ής³ξΗΠ­ζΎΧ‡6•έΚqΊ2qF—―Ε[OλϊiΣsΗ:~ή₯F΄κu:ίήθΫςηφ~L.N+Λ’yuD­9?Ί~Œ}ΛrΤΛlo³¬<Ÿ7ΌJ;2Ίͺ5…3Ξ§•y󴦾2­™ορ±seτσόσβύlΚγμω ¦εzΥ.7υώ£}Ξj»4Ϋ,#¨x΅ΞxqTθϋΥρΫQPΫΞ:t ΠCΐͺyΓ΄fD[Α΅ŒΔΙ«‚^7Œ|WŸ§‚–ak›oώρΗoaw„-Φ5v觃ζσ?—φ›φΧƒΪ»§§θ –iΫ x“Ξ-,ΓΝ»k)`±“Ξ#]Τ%Taχ6Œ01Œy·/^‘3§Ρg™Άy\΅—eψδjPοΣΚ ϊν΅½ΝΚ‚jΘvPσFοϊiΧ»A{Σ~L¦1Χλi.Œ}~ŽοˆαρG|ͺύaΉLηXwVW΅5 §:Dμπω΅~΄ŠΣ·Χαx9Ος‘λύ²^κμ©ύ±ΟΑΝόϊΗχB€o{₯ύςσς/λ^¦7Ϋ:{jY†ly½£mΫΪΏͺίΨΎΓΔέ0ΎΆ“oMσΔ•Ρ‘–: ΩO/Η8)©3΄ΓΟγƒ’:Γ2|ύΨΑκεήž«ζέ^‡£ε<––qθ«mqJj³At9¨λυφλΠLσλή„ΒγψڏΫh{D ύD,γζΆΖmϋA­¦Ε_f γή΄πΨOΟ£TύΞΊtφπ|U«Ÿ“Δi«7‚kbkήU½Z‡ύε¬_cνN@ߞίώCwΤΞ9]ά; Λ’ίŒζiλm’‚·^?‚jΘγ/¬b»#OσΏΔς >€όΌ‡_ΎχO5½IΚυΏ%/SΔυ6ΡΑ#¨†4³ΞΗFΫωΜ΄ςK ΗIηFΤΤ1ζ]ΡψZ~w-ό_ΏtŒΠρς1γ©Ρ.ΟΊΦαω Χ»Š,oƒΣ»ΎΞ/ƒW‡ε_žΦky3 ηΤφ|6¨uοκςcΕoΐy7Տ¦Λ/k»#οO "t𚩣†_jkίͺ“IιHξLυk†@uϋR°Λk―Γύ )°Η'“B;eω²ω 3»ΪΡΧ‡ΝG>iέ‡‘ή¦Υs³λAέΪΦήΥεǚ,~’ƒΟͺN‚•Τ³ot0AρŸFPΏ!Y`‹,°EΨ"‹oςΩΗFνΙ¦λgm#ghΉ37ΟΌΓםΔ8όœ0Ν-δlύωέKTΰIεw©3~3£„Qύ‘Dύ•ϊp?οRύσͺΧρ#ώΔ.|HΏϊS»­oλΤΤΊm―`Nϊ+“šs£ιzd\3c/¨U;qZ™7OΛaŠα+Ӛωo}['>ΞƒΊ·€9ε‡4’žύ―ΣίΜxjŽωoVΝ¦5»δ«?aΫψΆNš7Q#κφ:ζT6F£mωΟKΨbνzPcΰžj˜Ο\ΪoΪ[lοΦ«uŒqσ7,ςˆzζdα73ςρή<ΥA]BΥ|k#,„/L αI£έ2mώςΈj/.‹~³yκξ:Ζ€έΏΌΛΨ|ΓbΗξ73|(Κ7(B=^‘jψM9‰ΣžΐIΗ₯Ή.…R‡3LΫ:™TΏ^υm:¬Aέ_ΐYόΛθ^BΫ† ψ‡Ιβ»ήνθ>¦d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹»βΕͺΛΥ+αΊΉLcΪΏ6Meδ d€-²ΈΛ»ӘφΥΣTFή@Ψ"‹l‘EΆΘ"[d€-²ΐY`‹,°E„[ό―>ψ:1ŸΰάΤΕ[ωs7qΰY<‚ZΝυ>xγαθ0τΈN¬‚šGΨ‘«ηΩƒMP dρ@Τ0R~\ A’Ε«cΤq8άνmTΰ*Y<°ήυ½ˆ WΙβ‚ |2Y<π\P·ΎΣwϊ$πο’EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘EΆΘ"[d€-²x \3ιψΚψ―Σ^žt의ηR»ŸΧ°I|vPέp-8]?Nc ω8Lέ,3π²xΰ»ΥM]ΧMόμŸϋqφfV€%αvσˆγΓ·\ΊsΖζZΌyZΧO؞ΫάΝΝΟ»ΤÈV½NηΫ};Cώu©P§•eсΌ:’ΦβεJΗ>wG\Χe9Φ—3έήfYy>o x•vdtU'> j gœ?N+σζi9L1|eZ3ίγcηΚθηωη©ϋΩ<Τ΄\Χ!μ¦ήΏq΄ΟYm—f›e―Φω/Ž }Ώ:~; jΫYC‡ŽzX5o˜ΦŒh« ψ –‘8yUPΓ놑οκσTPΓ2lm3ΰmΒ?ωζΒ%l±v=¨±C?Τ0ŸΉ΄ί΄·ΈΤΠ†Ψ==E΅L{άfΐ›tnιdρnή]K‹tικ .‘ »·a„‰aΜ»}iτ 9>Λ΄uψΛγͺ½Έ,λΐ'Wƒzη˜V5ά1}s›•y6`Χ/Σμj>ΎH!ΛυαB¨†©ŸOͺ΄#V:.ΝuΏ{،ΎaΪΦΙ€ϊυϊ.†dΦkΑKo(Λ΄wζdL΅Όi•Χk·Yš‡ βεdρW81΄mΨ\&‹7„Ο+σHœGœy4π,Y`‹,°E§{Υ€3dQν.Υ€3dΡλρ£ρOχ>‘ϋ]}cεο0u?σ4Υ€3dΡ+}VΪ•ώΜœPB·ΙMέ―nrεη?>¬%ΰͺgΘ’Φ*¨y„~•Ηη8?Ί~όνSpU;ΐE²6¨ξwώ“ΎόψœUΈU;ΐΕ9dσ1ͺ?Φ<ήν­ωη}HέRSν8CSΠ. …›ϊU]΅ΰ YτΑz>¨αψ»I Υ€3dΡλΩ v™γn3'“€›dQπT;ΐE΄»T;ΐE΄»T;ΐE΄»T;ΐEΆΘβpf·ΊΫ΅g’?οͺ©]2dρΐguqυͺ‚ι ‰9δ\ί—,ψ>A —χ,WŒΧrΊtBΐˆηή3α’k'Ÿ[.χ™5— υΈχ >];2ώο=“Νƒ_–χ4u₯όΥviΆYFPρjΖ½g‚4’^  jή…–Ϋ x›ποΔaw„-Φ5v觃ζσ?—φ›φΟΥΫ₯·ι –iά{ŸζΏ~ο™εͺύyD½}K :›Ϋ¬Μ“Ά»Ύx™½ϋ¨|{Ο”έΤπ:žΊOΜ.Τς¦΅σš―'‹·pοΰεdρ†°‹ΩŽbσh ΰY²ΐY`‹,κ―©έ₯Ϊp†,κ έ₯Ϊp†,ϊ`₯ΟJη“BήΩ{ΟΈ_α3ΠόΌϊzΐͺgΘ’Vϊ¬tΎ αι{Οx?]Ύχ̏©ϋ3rBΰ>Yτ![5°Χξ=γΪkόͺvœ!‹>XmP―έ{ΖMύίewΉŒ²gΘ’Φκυς½g‚4’rΫEΰ6YτΑZοϊ>)žXΚ―£Ϊp†,ϊ=Tχ3“–•“Iΐ]²θCφ|Pγ™ήj—Ήγγΰ.Y|ίK¨vœ!‹:hw©vœ!‹:hw©vœ!‹:hw©vœ!‹l‘EΆΘ"[d€-²ΐY`‹,°EΨ"‹l‘Efό˜ώ„ŽaΞ††3IENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-coqtop-on.png000066400000000000000000000155761516144147600217370ustar00rootroot00000000000000‰PNG  IHDR‰ΚPfΌΛsRGBΞιgAMA± όa pHYs‡‡ερeIDATx^νέΙ’άΖ΅€α~Όwα;ΩRY“醨Α¦M* j²$s›3 ‰€Hω^. GT—ά8€eoύz=nžD&HœΔP…κκϊρ»2Μs0T£nύο·εΑΑ]·ώN’$$I7ώH/Ψ+‹²8:*œež)σ€e‹’\Λ }ΎυυΥs½6ΰ8UΗκd‘ΤaYζ™VΆ«ζhSί:61Ζvΰ8΄’D–—Ε²Ω GΛΌ\„3o¬Μ‹ePΟωvς’˜zπέAήXbΠυΥsz°ύζ&;œ&›£MγΦ1ίہγpσ;—$άΩp±hžeY™ω·†I’ΘŠES·Μό<ΣN^-IǞLIϋfξ`²Αi²9Ϊ4n{•$nΉ+ Ό½–$bΞΨ‹Βύž9·[–RΎR£³r‘e1΄γΝΆŽϊ‚rO=νm‘ΰJIkοψƒο’•[W#h{².1LLr«―άLσλ^·žΣ:°λ€‹ζ*rό²}ΪW{KΧΎ,7Σ‚ΆŠqυΏž™νoΑΙΖ$zϋδjΌ:ΩrσΙη₯λ―Μ/ί–”ϊ4εM‘ύγ—i4c ΅\Ώ(8Ω>'}2œgͺMυ₯Αέ‰=έ6₯Ζ_0Ÿ=.~*mˆϊ«Πϋl’OτΪΔq˜Ω­οΪδ^[²sٝοTYΩ\TχηƒyUΙA–3`΅ Sλ­§YV8όΌ¦žZ²™`…΄Ώ»ž1ϋ¬ξ R΄iέzNkCU{kQκ’ΨήTν:˜m˜Wυ―x%φ_Η&κ9­ο…ν3lέδXΛ‰DΠjΥ F{ΌIϋΒyγ«ψΈ<5}μΥ³\uR’OjΏNΦ9ύΩ1-ΛE†ϋp΅=?_f{=ΖΗ_\ζλιΦiΖ£έρzmŒυφ‰€¦.σ‡™έώξύAvL²Ar°[•:y§#D i΅ΪJφͺ―žvώκΐ5±Ϋ§X!νUBo]φњυœΦ†¨.­³*YgXŠ―SXΏή€ί²j=«ύήͺKg šΐjθΨΎΨί>αŸ~΄$!ϋE–‘:Έ ”υυ™ώεRͺυfΩρ}eΘͺΗhE}±gΚψkΥ3ήΟΥrρ>κŽ1YΏOθͺνΝ{fζ“„H©ΑΪ·Γ;eρNNYρ,Σ1‚6Ψ1ΜΟώ@$:π΄+d½Κ@¬‹²Œ΅~=§΅!:^³ lΧ†(ΦκmΘ>ΣWΔ&κι­–$’ν3κ³cuL…}‘[fΗ…)oΓ¨ύ©εRάϊμ2sνΗՎΡΚWXlpό₯κοgύX₯’D_ŸΠΉνΝzfvϋΙ7Υv‡KΓƒAβ\۝οTχΉU&΅:«ivς©Ι’:hόYS}ΐϊκι†?ˆrw£WƒuIuˆυλ9{’p}cʐ:„ΗHŽ[ψε[ΗΒ¬wΤU„QΟΙV―8γΗΙΤIB˜ ΅ns„PlΗ7;V{ lš,#:ΚhΥ€|pm™A< ²—Ϊώ[Y#λ)AΑ&›¨kΏŸ΄71’uιYΖX·žΣΪ/Ϋ)£ΊΩΞ;%Xˆžc$&―sD='’ύ<594Rν3υ Οm;γρ % YΞ―ΛǞSA?ΫƈεtνύYΝGΛnΑ1+ς°9ά~rόϋRφ—}–αλ)m(ͺ3ϋz½Νrυςκθσͺγ° IβξwA’˜EΤQp*Θ}oŽιώαΈγΰICδŒμ$Οdp28ξχΎϋZ/ΰώ’ ‘ IRN.Iχ³ ٞΦΑΤo0ΐž*‡_υίίμΧΦ*'χ€{ϊΧ\`OίVWφ;γEN’4ξ?*ΪVψ˜ζZό/ψ²(΄ΦνΚRo[4σ6Σ—fΉ`==Ώ$S½^ΑΧEO$ iύ$_ΈWyhe$Q%†ξ«?\™ δ6πϋ²Φ|έΟ›yΣ+μ©9$o‘JA™{U ޝΰΜ+eς^œΊ,zΕAόš’¬ξήΓϋν +$‰Š{θν½6=IΨ`Ώr’ωΜΟ~ϋ‰Ά$`€{ΦL½o‘¬‚» ΰυ~˜$š€ήzΫ’­ƒ~)[ρ펢.q²©$`$Ÿ$ͺ·†·i*υmœ”·PϊΆΕκ9„›ž»c뭐³½ιφΤέψJbKdαΥ‰Mέ+ΐ†έypO/8Q™{.W†Ή ©―"Ηηφ7ۘ$[αφΧ$ @β^ΐϋ$ @Βu’ …$HΊ~ŸΧ€„Γ{$ @Βα=n7Ύ"IRή½£p…$HΉ|—ΫM€’ ι’ $H"I’H€€Λ·I€„Λ\IRάα—ι Wn―—$²|Yu,σŒ2ΚφL#ΐN»zϋΆ^ΐWk&‰m:‹£Œ²“.ΣΖ°Σq%H!I’I€”λ$ @ W€€ΓΫ·τέZσJβ`'h1|Θ\Iβ₯ώPώT6~ψgS6―sεnςο§½4² XΕ’,δw žgJΩq‘:,Λό©V†Νšcίχ­£κ_υοΪΜΟzΆ§Επ!kΦn\‚σO响%έ9“•R‰ ―l·0ΆίάΗh—ŽωiλŸs΄gά:/Ά4I|ukΝgvγ’$~(ΟΕΪ0’ΆΣάΗh—ŽωiλŸs΄gά:Ά6I\]3I<ωΩέΫiύ3W0εR)Ή υσOε?Ήλ« —Xώaώχλψι\έ{ϋ*X·πηKn§>ΛΛβΗ.ϋžζεR._,τςŽώνeϊr馇e‰ό΄FQ.κυ*+σΝ«&–Ωs3-jΣΈŽΌζώTdΟ‹²xΎ(3₯l˜ή>܊gn>ωό£ΫŸώ˜:υ<ŽΤ§)_ΦεCΗ(΅\ΏhΠΫώaΦ96pνtœΏ/ 2ϋ«ήΦ Σο:ϋή73έώ_ΏθΩ}ξΫ΄A9ϊΨJτέ^=ύE‰αƒΦMU₯WxbE0ZŸeΘ–DαΚΒ$a’ΗK~=&a”ΚϊηMζ ό˜W;μΤI{₯A˜ή^φ4†ΊD`νΞiΦo:rΥωe[ρΆΗμ—ώφ­&+6ΐš91Y€ΫgΨΊΙώ4ƒΡ ϊξ~•ιq’φ…σfQ}βςΤτxΉ”fΉ*@ηΣ’εNχΟώΊ€ΨY.2œ`ͺνωω2Ψ₯ΟΩφΨύ΄­υ9jw'ITήξ·x=Ž–$zϋnRS—NΡbψ& ξ??i‚ύ£—μ•Gu5!Λ $^aΨ›N©Ό Ϋ3ƒΠŸqTŽaF|Η ;©ve‘[uVΉU—N@4Υvό±Ι’Ώ}Β”x€V΄$!ϋE–‘:Έΰ”υ£ώεRͺυfY½Žs8~Ηή?WιK+κKzRΦκaίθ«gΌOͺεβcΩM²\ΈŸ+Γ} ΪžΪ_΄>δd“„²Œ%ef>δνΘΎ$‰ͺcώΰvκ-»6·½ΤΩI½}ιΨc·»ΙύΉZ’θ;ϋͺΟ:Υ¨' _f―n:~θ₯–Kqλ³Λl²_z}ΗΟνΟcνŸΣϋΚWǘ$β>•J}}WηΆ§υ-†Ήr’·›ϊ’Dσόβ₯Ην¦ι±fηOΝp‡ςCξak6Ωql'ŸΦ±€sΦ—σvš ΔυΟσΎ0λ₯}«ZοvS²}6ᘁ/gΗκ~SτSSΓξ^a%ŽΡΰr)ΑώτA,8>ƒvΊφΥeάΎͺκ'}Ίς³Ϋ·eq]όη έυ•VΈΟΜ:]“œz~»F7I M]°Οβώ’Επ!MbθΑu<Ώ#‰ΑΔyσΟ,σ―sξy{ώΣ™$ͺgΧ'ΞD Rα@¬:LkO·&BaaπpΜnχYΠY·``Λ>™š©φ™z†gZκΰΥ’„,ηΧe(‘Υc4b9]{VgΙc—5vΊφΧeZ퓇ΝαφMύυΧA»εΈΪgΎž†’:³―ΧΫ,W/―$‰Α±©κι/Z rωζM½`¬NqδΎwέ©-Cθ;zΑXZΆl-†Ή|ƒόΐ^Πbψ+7nθ\Ήq¨pω&Ipωζu½€‹k~pŠ]ΌΉζW`§ΧΕ\I\η+°€„k7xp HΈzxM/ΰΚΊoœ^Ÿ~Ε3 @Β{Ÿ]Ρ xﳫzŸ\γ—ι Wξ=Τ v†ϋ{™V6Φλ˜›Τι¨\ζ™RΗ$ΏδO"”Y™/·-pj¦ψԼۘ$V±λνϊΗr±(꼎Ε?Ήδ>Δ†$±{v½§ε8§Θ™όKχ! a’pe‹Ό,–Υ^s€―μ ΜEΉtΣΓ²,_šŸέ2ΕΒ~>²λ Ά_Θ4·œ™Η―σ ΆU£Λ’hκΠπg©ι6 Χs¬¬\δ¦C·LΫ–A‹ΦvυnŸω93»ε€-υzν1Z–…Ω—φ`›™©sSŸvYZŸHsΛ‘$€νqζΒίά‡x€ΖIΒ φenωl‚J;₯ΚL1)s?‡e6Ψ.]ΰrA€ ΘMΠk‹™Η›*@5σΫυ›@΄XdYmήt†κ9¬JRΗ"φΕ ΩZ’Hολ‘φ-m;ΜgID>IΨ€,Σϊ―Ο΄½^gŸ‘z¦€κΰΔΌσ—Οέ‡n@θ\Iψ2Hό ο+“Ο¦άŸ½ZUYheymZΈLΕ–ŒšΤΌΡτ  ύυ Χ[59x©$Ρ³―ΗΆ/$ϋΣσ¦~νν.μ՜΄ΑόzΎ>CυL‘ε”cΞ ΰXόαγ‹ξCH$Xψέ7θ‡ΚLΐρ}tπuΛi·6H‰}­”·¦‡σ’„ŸfΫb¦ ΪCυLIΥΐ‰yο/ŸΉUp¨ƒ€ μ:xτ ϊα2pδώφΈ+ wέί°λΚΚL~ΆλχAL‚—{F0*°΄λOΧΪ°z’πζΎέ”ΪΧMΉήΎpΎ€]GΌNχ93u7όΌξΦ³Œ€‘z¦DΛΕμzLΏU³xοϛfΦ·†ΜUD3Xϋ}@h|VARŸ$Š|0ψš <ΈšVe­uΚΓΡpϋͺ€βΧ9ά†υ“„W%‹ΑΧ΅U’D_ϋΪ󡘫 υΑu|«Π?ӈ—ο§N– Άη4υ‘υ˜i$ ΰψΌ{.Χ vŽ`*c γwοώA/ΰΝyW/ΰά'ώ+°D^}λ½€xυ ½`γ’oΐl\ϋΑφτo'ΐϊΟWίl>ΘχβνΧKγΫ@ǝ$νW~’~υ›ίΫδwŠ"'I―Ÿ‰Ύ;ϊŸι7…F‰ ΅nWΎ)4ό%)3o3}i– Φ“ϊε/#υΦΩIFzϋά…φ„ΙI"Ύ"ί:”$ͺΔ`η·e~^WζΉ όΎ¬5_χsκ­³φ³C’€‘Ξύν«φ„ΙIB‚nυώ€ξ›B‡’DPζ^Caƒw'ΈσJYί ιo­ζ­$`€/ίhOX!ITάCoθν΄ιIΒϋ•“„Μg~φΫO΄…$#½ύ‘ ¬35IτΎ)΄ ξ6€Χgψa’hΊάR’«›l$πK™$ŸκJ₯)‹lΟΦ%N6’Œτκϋην6ΈΧ·hυmœ”7…Φo%•ιφ―Θ…IBή+ΟdYε΄Ÿ.>4L R–zp/xλl˜(H0[η?Ρ NX^Ψ„Ρ½"lΨ[ηƒΏ'±52χ0\ŒΦίΆ›ίύ‹^ΐξŒ^ΐkξΑυʝZ»εΑŸΎΈ¦Œ₯έ]£΅ Pœωψ’^0–t·Vυ{ωΣhΊΦ.@yπΖΩθέMS…Αvλ‘$`’3‘Œεο³Ό,~¬Ύ²Ί|ž΅ƒpŸ§ΥoW½XθεύΫ˞εMΛ/ši’\ΘrZ»εΑ‡WλcΩ mξyΉ3t€λΰ;ΖJI"½½μι’ΜόΌΊp%“|πω%½`¬8πΪ ?!IL6°=“$όFλjA[ΦΣΪ(Ύ,ιcmU’²£²π·Ÿ:u!Iΐ$_~}ΒIΒΞ?υvS_’X–Ε³ͺ,{ίnςε5­]€ςΰσϋτ‚±Ά*IT‰‘~ μσE™Ϋ[OMωβyψΆ[7]k`Ž$q hν”ΏωV/©9+ί]Z»ΖωΛ‡zΑXΪ™ωΡΪ(>ΎyW/K Ί»Fk <Έώδ©^0–tO­Ν°/.έ_χ+°§œΦfΨΏΣš™Ξ~%5~<α+°ΫNk3μ‹{εM½`¬ψχN­Ν°/~ρλίκc­›$&2ΘΚόEσKqK·l&Ώ(­Gήώ:όVZΧνΝ²Z›`_ΌωΑΊΎτψ“D;π›ν›ΐ^½jCκήκŠ?§Θ|¦Ϊ›e΅6ΐΎxυσ?“>s_Gw{α6Γ’]Yθd‰W}hm€}ρΞ§3Ώ*|γͺ$ΡyIŸWψ¬Μ[/’¨ώ|ι¦^0ΦΊIbΕΫMυ­!;-+³`ϋφjβE1a$ Pε‡χτ‚±ά™}|ϋ'y¦[!IΔν_Ÿ·Έμ3… u I€ξγ…^0V+؞BZ›`_\XσJ’9›?΄6ΐή8ϋε5½`,νμϋ4ΡΪ ϋβύO―θciυ4ΡΪ ϋβύΏ^Υ ψπκ½€Ώή]οΟ—N±/ο“$ ο?Τ Έtοk½`€,σΉ±Μ3Κ(Ϋ»2mŒ;νϊƒ5|)ΰτΊπΕ_υ‚‘Άι,Ž2ΚNΊL#ΐN{ύ—υ^{εzoΌόοz―ύς?τΏό/½€—_αΑ5 α7οœΡ Ζz@M#ΐ.ΛvY/K(“T#{ω8Sʎ‹ϋΧieΨ¬9φ}ί:ͺώU.Γ,ύ¬g{ΪvΩΩO?Χ ΖŠΙ±˜;¨Ο½ΎMΪ₯ΊŽ1G{Ζ­cρ=I˜μέστ‚±βAr,ζ”»xw©cΜўqλ I+8α3½`,;8²2ΎyUΑςϋE5ύ£Ό\šΟΕ‘›O>Ώ(ΚEPζ—©ηq²ΗEPΎ¬Λe ϋen=Λυ‹ύ‘Y‡ΤslΰςmρνδΆw˜—Ε‹ͺaπΚμφ}š²‘Ά―¦Ώ.aφW½­ο eί›γf¦Ϋλγ#»Ο}Ϋ•6(ΗBO‰ΎΫ«§ΏhcΨeΌG½`,3HΪƒΟ 3PλΑmλό#3Ν οž}Ιτ8IDƒΠΜ“ΥeZyjzΌ\J³\ σ‘Λ9+% 3ΏΩŽ ,v‰ξ£E³ύ¨,έφUυΧ%%{œxΡ`‚©ΆηηΛL`_ϊφΨύ΄­υ9jw'ITήξ·x=Ž–$zϋnRS—NΡΖ°ΛήώΝoυ‚±άν > θDK2xes&ωΨ― ¬0ύΛ₯Tλ+Μ²zηΥΏπδ³)wgΔ•M'‰žΊΜ­/ιIY+A‡}£―žρ>©–λOB– χseΈTΫSϋ‹6F€]φϋΧ­ŒεZίΩW}Φ©žiλIΒ—-δφQgΐΗA!–Z.Ε­Ο.³ΑY‹κ―œΎή =Τφ©ϊκ’Άς•Δ1&‰ξ‰‡ž$ϊϊΞmOλ/Ϊvٟί[/Λ |υν ;X²2σ?ϋΛq9;V€2 ?2AήπŸm@j%˜jvΦ5Έ\Jd|«Ϋ2‚ XfLΊέΤπ|Ϋδ‹T“ΝΦJΰλ«ΛΈ}UΥO’yuεg·oΛβΊψΟA»λ+­pŸ™uΊ ·€κuϊν©ΫMΙΎ›μ³ΈΏhcΨeŸεgυ‚±μ 1>xψgoχΚ`”ΑuπjIΒGyˆ\?ΫƈεtΑ 7Ÿ«³δ±Λ.πΝ“$ͺΔ`Χ'ϋρρΒξŸ0Q¨mχΆ=I­φΙΓζpϋ¦ώϊƒλ έr\ν³ _OiCQΩΧλm–«—W’DΊο†σΔzϊ‹6F€]φΦΏ Ζκ œ4y.S]/mŒ»μΥuž„6PprδL|τ f§`—½sζ ½`,m ϋJ#ΐ.ϋδσσzΑXΪ@φ•6F€]vΡm½€χX/ΰκΧτήΟ?Ρ xευΧτ^&IR>ΌxU/ΰ£›χυώ|ρP/ΰό—_ι\ψ‚g€„³ηs½€³ϊ@/ΰ›‡ΌΰπθΫ»zN„ό Mm:œˆ‡;%αώήp¦•5Η:ΰzψθ–ϋΚ¬Μ—»8§ψΤΌΫ“$Έ’°UΎ}|Η} Il[ΰ˜»’pe‹Ό,–Gφlw™gνεΤ²ƒ2[εMΛ²|i~vΛ ϋωΘ'Ψ~!ΣάrfΏΞƒ,ΨVQŒ π‹’©C£(Ά<έ†αzŽ••‹άΤ5Ψ7ΩΆ6NΔΈ+ )3Ar™— ωl;ΐ¦ΚLΝL`u?‡e6Ψ.ΝΟ¦\–— \δ*ˆJPo’™ΗιΒζf~»~Ψ—#’DE–ΥζM·a¨žΓͺδ u,ς`_ΐ.˜t%αΛΜ™ό2> WΛδ³)wgηαΩ{heymZΈLΕ–EI¨[ο>©y£ιAϊλ#ΆZrvjΣΰD3Asά•„{†ΰoΨuee&?Ϋυϋ"Ψ=#¨ηλΣO<}ή$αMK\IΨ*žΏLg‚c}kΘ\E47DϋΛͺΔ A]ΉIID’(ςΑΰΫ~pm—_Te­uΚΓζpϋͺ€βΧ9ά†υ“„W%‹‘Χ°U<>-Ώq-AάX“΄ΆΤW›'βAύν&"ίΣ p"Έ’°UΎα€”―OΝ3 ΐμH€€ožπL@’θΚ―ώӐ…IENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-coqtop-on3.png000066400000000000000000000041151516144147600220050ustar00rootroot00000000000000‰PNG  IHDR P ž€οsRGBΞιgAMA± όa pHYs‡‡ερeβIDATx^νέKr€ΊΰޏΆΒξoΑc&'<κ‘Γ"<τ°‡΅4nκ‘Bˆ*)ΧώρΕιJρ(Λέ俁ˆh )$"R0xcΝНϊ‘u¨νόώNΓ)ι[–!’ιΞ MΫ ύ©šι7pο"1j: ’ώ NŠCΧ΅,D„\»ΉHψΣη©|?tΆU…`²νΤΦ΄CΧ§G€IλΕeΗx/λΫid½μ§KΟϋ“c mz,Έ°HmV|Ψ\$κάRΫ¬HΔΒ–mΊljK‰_Ϋ&ΛΝ?;—ΆηΙz'Π ’͊›‹„OΊ^’Qξθ­n¬‰~θ>c›ϋƏڞ‘~Q mžͺHĐ τ»Ϊπθ1Ά7ίεo»¦8κ•`Π&%ίKCύ"’ šŒwεΧ…ϊED0hƒξΜ―υ‹ˆJ0hƒ’ξΥ ~Q mPν κ3Ρρΐ  J¬=A}&:΄ ?’¬_nψθ³C}&:΄©Ώ·°7¨ΟDΗƒ6Ώ-›ΏLεΉ‘ύΏΥ§u’T΅۟η+5υύf)κ3Ρρΐ ΝŠΔ4ρe’Ψρ«ΦώXΚGϊσΏœϊΝRΤg’γAM°Βω;χoΜχWξ³, hfωm.|Υυ™θx`Π¦N°›‹EbφKZ*'Έ<’ό³‹Ρ0hσΫ"qαγF~417Έba6ρ# ζm²Hƒ6ιΞ^Oοτ΅ ŠDύβ2όΖηgρˆή)l8 ’s`Πf’l;„ϊLt<0h2ήΝχ υ™θ€`Πέ}χυ™θx`Π%֞ > )$"R0HD€`ˆHΑ ‘‚AΧ–ί|υ­cΫΧ†rd'`ˆHΑ Ι3UqΆ±νΡm(Gv‰ˆ )$"R0HD€`ˆHΑ ‘‚A›Q†rd`Н¨Mβί‘Ω8Πv/ιοΈ|Cmt[Χ8χkۈγ+—α*γle(Gφmκ“tΧNκkoο–^ιX-ΡΫ6š/‰_€A›ϊ$έΕ΅ε•ο•ŽΥβύ±mƒEβW`Π&œ7΄_γWUϋ―&Ζίβ_—ί½§εόηŸnhŠ6]'/“Έhοs»ΏΠΊΞ(mse½uΥE—mψγ΄\ν‹φϋ¬΄ΏχvθόΏ!"λ–ƒΧ…ύkΖΆs}ΏΜϊ±ά„œ―Ό――œ{ΉnΟΧ―ΊFαœkίAΐ΅ΐEbaμZ/(Gφmδ$MOΎœ@ΉPωβΚ τΙΪΎΕ+c^}}Ό.ΥEe\nCνKρz½%γz1A[γzΙEEB–—ύ„ΞQQθޚqUΫrί/΅~,KάΗΒο/œ-0qΊœ“Δξ΅?α<}›|ϊ=+1ΑΓy«·“ "±:vΗ2/(GφmZ,: πBEΒ_<ΏŽάI>ΰ-Ϊf¦°Ύή’Έ½NΦΕΗxmΥρOΌ,νιŽέΊH¬Λ΅­=ί6)ΠεΨX;ΞϊœΔυΦ ‚ηΧ+Οst~ ΔύΑρ‚rd`Π&θ΅κ›ο:πN‹‹„Ά5ώρavΑλAQ[ZoIΪ^Xη† ’UΗχ,iΟυ}«΅cYvρLβŽEb~γΑEbmμbihΌ Ω΄‘γO~ž†“%Σ|ύ³NΗόέ^pAεΡ€ϊ9 ΘI‰iΆ­³λ-)™βάƒ0`εlzάXπΪ7Ž%ΥβΐΗΏeΰ―Λ €sΟσ8σ ϋmυ±θη’ίy¦Už3Ωf*ώ oSχ+–7Ηξ’βœΥγεΘ>ΐ M8i’θΕ˟0έχΓ_ΜbΐΑ‹‡Š„‚ΌDŒƒK—Iϋ0¬‡]>Η»€u]‘ώuŠD, a{ώ<~4αό”…φ]={‘“ώω—εώεψρ‹Λ’ίώΊ†wzœΎ]Ό³ηνŽλευA‘X»ε2΅•ρ‚rd`ΠfvιΡό{™œtt_(GφmΠ‰’ΗρwbσŒ†εΘ>ΐ  :QDG…rd`Н(’£B9²0HD€`ˆHΑ ‘‚A""ƒDD ‰ˆ )$"†„?’B‘τIENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-error-message.png000066400000000000000000000127471516144147600225700ustar00rootroot00000000000000‰PNG  IHDR΄GoE²EsRGBΞιgAMA± όa pHYs††]’|IDATx^νLUgšΗΏΠ²«£‰mՎ»ι0‚-n΄ΦJΣ°E­!@՘"Ϋ¬vΗ”Β¬‘`&ΊΦ?ΤνfW(QΑ‘4Μ΄lΊ6Τ„°A­Φl”A[g-0"ΘLvΩΥΆcRgܑʏ}žsήsοΉ—ϋγξΉάλυω$/χœσž_οy<Οχ}_ΞqMŒ L@AξsΤ― ‚ ά׈AAβ1h‚ B\ΰ1h%©@² 5Ώ£PΰYΟώ@νΪωιœƒjέ{ΌοαA…ŸU°τ—˜ς†Ÿi‡Ϊ.‚πγ=)„Κ·š€Εjgɘ g^Uλa’Mηo0Ÿ?lLq(}\_w’l2šg¨•ϋAr.ΆάίiAˆΦ» ΕVbRQlΜtPc›mR5d}0νΓΗSlΎ ²5ΞO‘Δ†rdCΐΗ\ψΨs</uCͺΘ¬~μ(Sγωη3―‘΄,=?Sœ?…ΖηΜ CfNƒqFϊΜ*ΨΈ¦ [!Ζ±nΠJIYU>τΠr)„ ύή oΞjR`*n„φοΫξc0Ύώ‰~Œ}Φ‘ΪπiΤƒρn')γόήJ±nΤ“Κδc2·xŽη£β™μΊB5βθόVρ| jιψΊ–₯ηGƊ·›Οc†ΟΩCΟ+“‚q†zζτρυ*IΩ Έ”–9½N)lA„Ζώ€]Τθ ζ†%jA1ψ(₯8pγν5Τ ΤΈΗ/~ΨLΊ•1 V >κ*ƒ &G'ΰσg”xξαϋΛhσ('φόΒ%η5ΰψϋj…θ εΝ΄Mα ΈAR V8«7ώ»NyΤΓζJc*,&΅dV&ξ cI§ηO?šκ£ΐj8㐂 1ˆ·AK§πiά« T+°ρΛ$Ε‘ͺPO;ώ…Ύμ†Φ·ΣvCρhϋΠ1ζnΏ€(΅δo\Ξ€έcLŽ‡Θ³Oκ=™š‡――1κHώ˟{Υ΅Έϋά"}eΡ"Œώ΅Ύθ…•ϊgΑΎžAγ7ήΡ¬)5~ίDq ‹[1ΎF­„πΰYΉ–ΐσ (uFα§―«ΨΰLW>ώl7\ύK0~=t ­%@© fΝ:ŒΧ¨cΩΓοίbΉΐΰ‘ΧqŽξχέ…[qΒΈw ΎκςύΞ~μ.ΣγN,θΓ;&Γ~ψtΚκ9φܚTTQ£Ξ οόM<>»?+ œ)Ε'σΛέκϋ—O₯㼊cΒ=Ώ_ϊ|Lb •Ϋ‹-φΗ P?*J‘W£Κ…ΎWGΈςK©AhsǏSΌ»Ρ,’νϋMυͺ’φ9fRβ*ήΥOύHοσ4¨μ=σ9ŸέκΉ>―ϋήcΒ‹6γ{ςμG—Η]φπUΈϋœŠ$¬ηΐ™Ÿ―Ζ=ίψ`υΟ²} ŒM…φ"΄wςE΄fxων=Ώέ9Vb’„  »ηǘΨH…ΒͺQκDB©Ιϋ‘Βε4―½R…άGτε\jΠݐΒϋδΧ&eΚ‘z ήuΏ— {mm€γ#Εϋ Fjv9žΊ²Ε}ŽΏ#ρt’P9,œίk1ΑΫAS²V6 αz{•§œX-_~λΗ)*o©2+̡Ԉ΅ιέ’t}—o%Η§Ϋ3ΞεUžϊ‘ηtω™zύ3<~_ΰ7Ό} uγ΅-$aηŸδKωΓα'GΠ{ΙjέC°ϊgΡΎaj]Žq ΨΜ*P]οgγ4Ž=’ЧΜΚΤΘ€©]’Š#χ·?7XY~ω4°ώ˜ς`9ΏŸŠ’Ξžž(Y+δYOμ7•‹^²ΓγχU~Γώυ/Vc5*„Dς/,Œη*FŠ)oςώ#>Ϋ§‹Θ4–•Q΄Zj ݍΪuΈZ­XφšŸM'Ky`<žΦ­/Ϋ’ΧΎΥ—ΞπxWΉΕq ΅Ψ° YglŒΫM+αίία#πό£¬8~ξŸ0uΑΦΆ—λ;NΕέ}䩚=ιιΖoύ`o~§‹‰"'+_)j'ϊͺΌ 6Η“jπJ‹‘~.Ώ€DμΣηΉ†6ήb£Λ>œϊηf Γϊ’‹g4ζTΒ₯―Fɝ@ω3Œ‡J0…ψ~Η*πλ§\Ν%~Ζ@#["€ΠXV6N’²o¨€';»qΎs•κZςLl8Μ΄I!{<έNMv8zPy©žnΓόZLԐ„·{p$Ώ3U7D4…ζ*4ϊ†&om:>©VιΌΒγ]UZ—0OκΰtΏ‘š(Βd>jԞƒ1A&· »Ώς€ @₯Ÿ ’•γC’’½Ί\ΜΧ!v\PCε―φΩ―JέΗ?IY»{Ηΰ?Ώ8Q«§‹σpIΝδΚͺ9.>Μ΄γΏ~ ² ύ₯ξϋO,­z Œ4L΄Φ‘6M:(ΐx«iŒy5n-*_«ϊ1Ύ«–ΟZ#Μ“ή¦­P5ΐ§ΛέεΐάHO”§Γ₯κ@"ωγ,֍0κŸb΄0 ?Ρ»©’?§υ_Th#“xHug™»ˎ«Ψi@ς'pώ Ÿ§6σ+$šΊ‚“λΎŽρ"Βυ/rοrδ iΛΓX₯―‡9ψzP£ϊ΄ΑdΤςb ›) υ#„Sδ]Ž‘'&ςΗ§ώέ?οr\S…q_ AxZjΒΕn$°χbCu<1 ο@τ3Νυ#Hύ‹mb"¦‘ώΙΫφAˆ:’ΠbyΫΎ ‚ L#ςΕjA!.…&‚ ΔbΠA„Έ@ š ‚LΝ •€ΪώN ŒοΫt¨uAApη'…dοΞx©$΅΄& G­ ‚ ‚CxZ6©'ί/„²γmΩθλΖEύ}Itφαν>φμΓΑW‘]Sϋq`γ'‚ ΰ1h d\Ά7₯¦/„ΦΠΆg(ξU}=‡”Χm«€mΎh―ϋ§ΈΜ-ϊ―|ΥXmλQqύφ».AΑƒΖ©§S_f΅¦©226=yϊχiœ’…Œ’qΎ κ3Ϋ‚ ‚&ή“BX1 ς·kH­e΄‘zϊŒ~εMΏ‚ BμγmΠX1½K*mσj}ω8΅ ΎλE΅XΓcn2N&‚ Doƒ–š 4AΚ}Θy ΈΐΫτ(€”›1™£β kΥΊΑΪE†0Cνǟ*κQ3y†#·‘ΆσDž`²ρcύ<2Ž&‚ „‰ΌΛQAˆ Όš ‚ ά§ˆAAβ1h‚ B\ΰΨΪΧ3η©%A{\ϊΓͺ₯©±β₯–„H©ό™χ–ZrΗšΣ7&‚ v.GA!.ƒ&‚ Δφ šρΆύ’³ϊ?JσrΐŠ>‰9 σ0§]­Ί9‰Š’yΘoRλΎ αtCΠ>FΌoμ1ΤNχήpR­ ‘~ŸJΟ€ΈidpΙ‡κ0η…Μ/vώ>΄΄ωtR™{aζSΉΣΒ eH6ήZΓ΄—ΡvΪ¦V£K ϊ]’E¦lXeφΡδξθRkΎ #mΕΟΝΦBν7[Ε<(Δtώ\ΖcGcωΊϋ„ͺΆμ‹μ4~““ώ# M½X8Ντv~I‡oΓέ\΅ΑΝK¨¬Ώ…Φά|…]KqŒφΉ©Bΐ}c‘ιVKfRP΄χŽ­R«Qa³Άΐœ²fΜ8οοΓ'%·C˯耓ΣW€δ§›pkόΎΏ„ΫOˆ9[됀φ@n>Fπ!f ΟAJ.&cf£Έ~D—€ΎΘ” «όΰjZς…ŒΩΊWŠΥ8χέ΄χnτώ ˏ«xλ8‘Ρ"¦σηυW°lΧg˜ύ«ϋ„ͺ6μK ¦ΦεθΎΘ3¦Wc™9‰?/λΖXυίS<χΰ•Š9ϊ!-ˆBcΏ’2œΦwΜ`V^ωMπΠCΐޏq›ÐθΚ³“‚ ιπ¨΅}e¨Ώ‘637θFœŠ?­βέΟ‘.πρAIΑΰ†ΎwŠΤ&»Ή?Kά¨σ>žƒωω„{~b,}1F΅₯Œlά¦-yx W½‰e‡£¬όΧΝ(“n*ƒσr0Λ]†½γΉ|κε›Άežj­Αv―{Ěg―ΕΧyφ₯ϊα9·RŒυ΄X_ΰ9ήJΓοHύλΒrR]Λψ#όΜ­Β<žώSCIEδεΝψ£ΆΎ»)³›ΟO£J“ό œ?‹p­“Z ¨―MΖbύ i_cΟ -f₯€.’YS²’ώ>-ΣήJ7Ό#/{+«ΰΌbnΎΙΠ6“B«Ζ}‡ΐ,.ΖοΗ›΄Ζ!Ήμ*ξ6rΓ} · z1'Ν\ΰ‚3Ί£ƒΞ£ΛώΘ•έ˜kΩ›Χ•§–ΆUMκή)lI6θjŠτΈ +{ρv}w‚ϋό½$³7\rΛρ…{s4£ΕΟN;7―φρ:>„ΈΏΠ±Ϊ»}+γ/QzV’c7`)ύN1ϊς&Œ‘Γ43š]}~λ7z+0λΚ&₯0)΄r]θFb?ΗsƒFρΨιV w°›Κ77ˆΊ³r[9*#uζγuΈlkρυT~φ\βΉ~Μr+Ψ—p›Άiϋ5ιΗs¨σ)Ώώp€ώ­Β—€Ό.scψκ?SΓȍ#…CFc‘ΗΉN­vVbω.RKRΈH#ω<¬΄ώY΅/A°©Π^€άh/’}ΠS½xΨ‡€ώ^ϊ»cN~GΝ"#­ΥQΧέQ‡;Οw#ωSkM~R;y2†χΒ…σΌŠp’U;Q΄P_Lyl)9žW΅}θΛf\€ί=ΊΒ­P2›Ή{‘ύ杏_¦7„ζγ#εϋ Θb,ω ΰb³~|ώΎb΄ύp'.μ-¦κξΔω-²8χθgFΏΝ§¦υ+/ΧΗKΆ;ζ·~ v ωόJάi,V “ΠΊhVbŒ{_4#Έ ·©s+Π:n€l璝Έ£ΊπG—Pω9ΥF/DhΒ©V™MΖ,kσ§˜ύ\)ΞYmPΓΝ?ΙgZ¬Ω—`L­Λ1!Y>77ξ)οHσ°žWqΣ†Y™zBε2uΒΉ?]_x³ ϋ7mCϊ"2^ΝΘάgV˜1œώάjU.&{Ι·#6Ζ^yξ˜ ίOJ`cΖ*α\§ΡύhˆδŸδO¬ƒ¦yθE’εώYηHΞχτ '΅&•5ΉλΣ/ύW‘H κΨM/ ιΠaςΘτ(;€όp%ύ5ΊΡN’~_Ž₯Yš)Λ7αY;l8ιnΰ‡.—!Ÿ”JΕe΅!Š„}ά₯X”ƒΞ…/‘ˆ—ΚνΈ@†ΝP˜N₯?±oPy΄CHnαρX0ƒ~ξiωό֏Ε9!oyΦΑ“&œ»Ήrπ0w{«υ9ΕF<₯―8ΘΔ’Α“˜uΐOϊC0š—_ν|γϊ™rύSόα‰ ϊϋ_ϊΈΨυ.€­#¦MόΖc;hy₯γiΚlzΊ’?σΗ"aΧΏίQ"R)ψΞfdš–Ήώ€¬οΔ σψˆ7iRˆ—š‘κ'0s«ή•0λk=(jdoυbV[ŒΉxχH‘%–­°6πͺHΙέ‰ΏލLΎχ½Ρ²hjrS΄IFΊ5G΅;­œΖ…ΕhέΧDΗ’jQiΟόχ^`Υ;(!…b>^›HΑΒt|h<Σ^]./XœψβώάωGΑ{bŒ9»ρφ^}νψn`>5Fςό‘HΑΖ&Œ\)ΐ<­+iζ\Ω†Ϋζ.""ιΣfΝq‰κμBΏυƒΗYxάε Ί= ΙOoΒw;Ές“ΈΦdŠΧΗsn_«¦sιh]\”~νΨ­­+ΰ1jd)“εxςΛ3OΘΧΛΗe`tΗNmμX»F5Θξλ[cΚυOρΗ7·βFo ²xΒΑςF,\Ί_ΎIrΎσ–}ΐ³ηz°pσ+~&%DΙ&`ώh³Pυ<ρš8²ξΈΧ€πλίoΥ―ύšω}Žb€lLcύˆ4Τ?V αΐcaBb%όΤΏϋΘ  ‚ XCZlσΐ½m_A’‰£ MA’…(4A!.ƒ&‚ ΔbΠA„Έ@ š ‚ˆAAβ1h‚ Bό?ή ₯-Ιa”IENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-rocqide-compacted.png000066400000000000000000000032731516144147600233720ustar00rootroot00000000000000‰PNG  IHDR[EδdE²sRGBΞιgAMA± όa pHYs‡‡ερePIDATx^νάΏjΫZΐq=N‘[pŠ“7(τΌ„šςYŠΑ₯`ˆ_ΐs tΙoŽYB'Oκ t)άνNχάsŽώψw€cΙ–%5Ηωp,Ι’eξχώ*9‰ΤΏΏ _Δ@l`ΔΰΔ6Y/Υj>QηγHΟŸœϋΆΊŠT¨ΕΪΏ|} ζ8†Ž›²ΥΡω±YŒrl3Ιό„ΨθTΗ±}R‹«“Νt¨Ÿoμ20σ\ό›N²ξicϋp£b=YΫΧOΤΚ‰ο]¦§pχ5JϋΧϋ^Ϋjς΅υΟ—›e±Π΅Nc›Fj©’όgσΟς,Άως<ΆVi? B½~’vmβͺ£Z,71ΞΦ_λ°–.wT&c»½~½όgγβ΅5|ηx2Δ@Χ:žlΕδi'Kw2mŽmυ2B±Νϊ¦˜’ r{³όͺ:©τ€[Ό¦^Η=>b `ύ]³Υ“gbώ™ΏΧdΫglυΜ Έ|2Φ*Η#ž'ΆΊΤilM,c3σ:"€2bΙƒŽ£™.ΨΊ—μ:εΛΕ”Ίηeλ‰σΪfΚ%Ά†ΰΔ6Ώiε(O“5:f±ΈAUΉΑeγ'–‰\ΕWΏ²{·χά s£XƒΜD΄Xv₯—ΩŸεδ›½Άc{hΛ?ΩΒΔ’ @‚‹­½ΤMf:έ|Σ^― '[±€±ύύߟZ«~τʷϐȓ eΔΆ#ς€@±νˆ<©PFl;"O*”Ϋ==ߞͺ(Ύ―yΤΌέΗχOϊ΅ί«ψηυε³ήμ7υQλγχώckΤ½ΏςΊω~F·ιΊ9&[mTc+Cςx©γt©ξτco@χacϋI}яml?ΣΟ·‰m{uοΟόόό8S£|κΝ[] ΆylZ},ΩΤΛd  K­b»όϊΎ§|ΎVg±=π2ΒΆΨfΣkΈ/κωφΖ·[{ι!Ώ–›άλc9΅λΘ“ eΥd† R6ιٟuΨd87±1­#o}ΈV±Ω^?~χυΪΖΦ\Λ•A«wΰ 2ΓσώΜkέΕω:& 3u‘_Rp&ΩϋΝσf½,Ός€@™3ΩΦΩΔΣL£ι.'¨ςν3$ς€@ΩΞ±M'ΉώψφyR ¬ΕdΫί>C"O*”ΫŽΘ“ eElύ!Ά0b  Άΰ‘ΜOΤωόΙ»¬ b ΰ(-Ζ'j±ήόœ¬—j5Ÿ¨σq΄CD—*Ž&*Ο5nΏΎΡΛnœm$b ΰψGgώυšeύΐ'Ζ Œ ΖΫls{]egΉ«ΥχlΧΈώ~6«0ηyφϋ5}ύC<^ί»ψξ·ΫτkήX'Œw·ηyέŽ7ΕρΗ…οΛOγJωAc΄M1?Œ·ΩοΥy]]ζ}uω½Έ.œ[?–―-+αfZ„ργχl}Y^;»ΌΞ6pΎk^Λ«ψζ{΄ζΟηήΖζβχΞ«πuτ‡'ΦΖύίΰX=aœNXW«tXυΩWΦϋΦΖ.ό³? «p}Ζ…όz3ŒσyσΧοφόΒ7έΓυΦΥλ_ΛΟΩ σ8Ό‹ρq«e[Ώw.όAh|žJ_}?€c WΖ!μBε—¬ϋD•kσVe;Ζέ6ΕaΜλχnΧ<6ωw8Όgώšζη›Ζcίΰ£mŠdN•‡ω.΄’ρŸΖy†„ϋΚ:Χω<ΡωtGίΰ0aΈ>„ΥΆμλΞhU4Ηη‘Β2‡άξ1ΟP]6Β8Ÿ/·}+‘xM»Mq¨rgΆ)Š0ΏnΌw¨rη„ρΨχ8F·2Z‡†ηA3giΫο<μΦΡψΞ Έ"£kΡ ΈΓΆ*€“γ7πš‘ΩϊόyΗ7πBΘ­ςkΕq\9Wοέ1ω~GoS,άG/½xeοWzωP ΐ{ωλ+c€S Œ@,€0Xa °Β Η€'q߈0NVϋ‰άέλ]ω XλΙέ΄πΨukιμΘ~οΥ– Η,·ΖΐizΌξίΚ‘΅'NJͺ*.ΟΥο™zθ¬o'Θ1Β8Iαα°ήP γTUά•|ψΘκX'¨ ΣΖKΔFΒxΈW\nPVΆ)R•w˜»΅aΩΒ8=‘:ͺlΓx$Θχφ{¬Κ{cΰτόƒ0ž΅‚’jI΄Ο c€Β±mŠνΰΈζ~ζ}ϋ½kS€ͺΣrΟτ–¨²­Š§μχξ@$―~ηόJQycn~EΫfi@Λ[„λ,GVŁ0X€:Œ‹»­^ ΐ_aΒR΄…S,€0Xa °Β`:aΌί£vž­§>˜›·_(A’2n?FX>q2{­ήΘHΤ&„qωˆΰμ'J„1ΐdΣ*γcžbΖ“υ„q«g|Ψ₯ha 0Ω€6ΕQ„1ΐdΒ`:aά\Ϊ6ΏW<Ά_(]‰Κ€&Œ@,€0Xa °Β`„1ΐc€a“΄zxM'«»ΙΩ]Ά><Ψ6ΆW{ω4rσgχ·ε~νΥmW«ΦΟςϋ©~€–ΗλμluΧ8Βω°ρΩkΉ#eίφΐ©ͺΈ2ήOυ΄<^gg«»ΖΉ²­Οm*ίTUh·ΕΝΆζMΎν`U<>>Π¦8HV§Uk‘Ψg½κωΖΥσhU<2Ύ|x΅ΔΆaαΖάόŠΆΝ6€–·ΧYެŠa °uwΛ>ΐίeΒR΄…kTΖ© αίR<15a °Β`„1ΐ4Γxχ3»θ4ΖΏd7Ώ^’αš΄{ΘnΎFγΏ~Λξ«kρΔΤ•q¦yˆήr{ΫΫ3B@οzαuw}–W“ϊίη7v™ 6σάςή­λ*ίΈβ΄!|£–Ί·ϋ8ΏTλ(”Wρ2]΅Ηϋ(_{m«Ι}λͺ{y»Κ— „0€!<„]x­Τ6<6oο}‡ε!„­ΒqξL@κυ·!x7&tuΨfΛMHϋυ7:p Σ&₯JΪn―χλΞφ­™‚θ|>U‹7ŸJΟΛ €)8Ι~χfA8 QΫ | βΝ[΅|ξΏρό•ZώŠΓ¬Ω·ύσ·j•\žΦζψf'ζyο‰^7?Ζ'υR,Λψ@–SPͺ„mΉxͺ–ίΏd‘Χ5Lw a£Ϋρέqž|tλTŽE:„e€}₯Cρ•zχ¬ιψ«οoΥ“P%{„0€cu\!όK°έ—ΎJ¦pμz α=§#ͺŽον房¨ΥΗW6”‹!l§0Β\ρ―Oϊ\žΪuδ…ΐ€oΜ&}εiw Τ=oΜΥέ›°Ž Φ·κe˜šˆ*ίOωσf=ΘςΒ` J•π)“S…°«O—Όp˜*a! #šU7‘ C „Ω00BX C „Ω00Βξ ‰v ω΅ε1ϊVͺ„Ηώνˆ1Ι†€!T‡°ύΚ°ωIΙa;ΒόΦCώ•c³}lσ[ς+ΜΪΛοϊ9{nωsΙύ ΩΧ’+~―X6 !ΒY°ιξόƒξƎ!\ϊ•΄œα<ό~E₯nΟ·Γqάυ₯―X6 ‘Ήή)„wύ€O­|Νz²2ΟB;ίG“μϊΒsb²a`ΝsΒώΏ κt»r!ά4υαͺaσΣ”²ŠM―[F˜’žBxΏιsό°έJ‡d©ΪsΑΕίnB˜ΒuQ(„Ήόχ€συά CsΥ‹¦;LΛ›}ϊ\·…Ζ€Ύ•*α9“ CˆB8«gJ6 JX C „Ω00„(„Γ"„`D„0Œˆ€ ΫΫ3uqϋ\v(„0€“uw~¦ξ6ωγνf₯Φ·—κβ|Ρ"\WjΉΈŒΎΔΥΈύζF/»ιτΕ/BΐiΊΏT‹λU岦­‚kΆ__/ΤςΎό|BΐIΊΣΥje6†pΉ ŽΤmί±&„œ ’λδ2­!„η‚k·7ǎ§AκΒN©Fw­d›άhρΪ*Ό€pzφαVŸˆ „ ΞΣΝU°ΡXI3`ζRΥ¨ωδBιΟo²εMUpΣφ7ζ@ΣΥjεGΤ’JŸ+ήQο‘Ϊ _Φ€γ’‡°½›˜˜ο€Ιkq3m’’JψΟ0901„00r`b>a`"δΐΔ|ΒΐDȁ‰ωθ)„Ώ©«ΕB=ϋό3±¬Ωγη?Τbω-ΉlvΏfΕυ˜X~,ϊjŸΙωρΪίty­Ύ¦–w±ύ žω›8W?Λ½¬nγ¦ώ'&ζc’•πΧεα@`Β‘‡pŸν396ˆΒ–+κB8諍λϊŸ˜˜rouG}‘;`¨^θ°uDV ¦Κ->.“μΔΊ"‰φ­ηI΄,Zή΄}³|όTού~Ϊ Κ˜ίΆc˜gm³όΫ΄ο{ίΎaP±ΟτΊω1Z΄Οڜ_ο ύοΩ sN2„uΫ/σ>fΪΗυΟόοiΪΓ†¨_'ίή΅ŸΫ§_Vq}•!\3>Ϊ¨λr`b>βφoΩ~δΣn`ώ‘wΤπΆ.λθb™ξΔ~dΣ?υz‘SζλUW!νΆ―ΑW8»M™μΒFΦfΎσA™Zί§xŽΥν³ΏnηsΫVhuΎ…Ώ― <»}’f_ξ|Μί_.O΄MTI‹ύω>ϋh——ϋp²ΫŒuύOLΜGΒC™NZU‹ΊγΊj­Ίσ%;q/ΏOS‘\}*—ήΦh·}yW;π~κCΒ„‚θβνuΒ5ηΧ§dΰΛγ'ΟΕkθŸυη―λ΄‘k=>jΤυ?901‰np²#;oP?Ύ©χŸ_««πΆ²0πšB¦iϋ:ξάυ[~tϊZ[V0‡R₯Jk€JΈκόΨm}Ώ(iqΎφo3x§Ϋ3υ\ΫρQ§Ι‰ωHNG˜Ξ‚y»ζ‚ΑwΫ©]P„0NU©NμφWϏ:L‹Ϋξ7Μ…κ·€οuΕkƒ¨εφuςͺκφo%s~ΫαΤ†„·;ΣΎν‹!\Ω>Εu:΄KPb=+ΎΩk3£p|?υO?%Ξ/:ͺνυίMNGϋTi?A›ρѠɁ‰ωhqcNp?ΰmΗτΟ›AοΊ.λ°Ύ£gDXJޑ琿ύφiΩω†π΄φΥ%hv αR{Ιλρϋr‘bž3Α*nBFPΡ>B2D4_j›ƒΣΗΜΝόm틬yμϋ‘ Φ¬t?ΤηΏ›mcnšeΫη–a:Ν¬£χ›½σ(φέ@φaΩφšω9€5υΏcύνμ§Β8&LDpΰ(ȁ‰ω „O‘y‹ά± ΖψδΐΔ|ΒΐDȁ‰ω „‰σ…0`X„0Œˆ€Β0"BFDΐˆa! £ω­ώ―ΏΎfΖ‘‘ͺIENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-rocqide-removed.png000066400000000000000000000101331516144147600230650ustar00rootroot00000000000000‰PNG  IHDRΊiL*ζ°sRGBΞιgAMA± όa pHYs‡‡ερeπIDATx^νέOoΤHΗρ~9h†‚QΒ;ΑKf,-pβΚ͈Aή@ΟmΘh†C"voα0šŠ„”y£•VΪΛj«υΦS²Ÿ²Λ:v]ύ=|έώWΆληΗν$³μ?d€Š $ $-ΊΣ“EvτςNv}k–]ω1˜qjGχgΩlv%Ϋ?‰O?οξ˜6H;ΞӈWtfΐΏˆ~낃Ξ9}y… €DŒt³ύϋWΚͺΘόϊΦS;MΒCή›ΏΛηΝ+Έ°r²Aχξi67₯]Η֝μ(ΎE8ΝTŸα:*Ϋ7Ϋ>*–5τΊMυ8Ή(§)€cΤ Λb‘ϊΧr+НŸξƒΞͺlg_BΘΜκΓνD‚ΝZ1]‚ΠΝbB­r‹΅VΪεΝϊόk„ΕΊ Ϋ =AιΉ’S—­¨ΒЬ;θκ·.‹eNžΥaA//ΣοΧ+΄#Sαλ4σ„ν#θ uΣ}Gg*SΉ΅8¨’›2θLΛΓ.Ύ"4jνQοt†QƒN‚jƒDΦ£ΒGΘι;LRUAήΊ΄σTo]ΥΩΐ[—6(ολ–κŽ €΄Aη T«¨ϋ&HζκaΪΓ$6xΤ4υ0Iργ.£ΛGF ©ύa °bΪ}3ΝΎΦŸ[w  Zΐϊ‰WtkB‚ŠΚ Πfν‚ΞήήtΥ–Teε•Τ­uE@‚΄"θŽώυ·€ιl‚4‚4‚΄δ‚nρΓΧΩμξ‹Ϊϋz§›#Ή {vwFΠ EΠΩJH~ϋξ£lώϋ‘μoneσίΓΐθφSΎό7²Etz\ŸνΛ<—δ}η’™·άΖ‹μ†šVp‘§w°9‚ŠΞVC³―³ω۟Š`X˝Άύ|;—~Θηυ¨θZ=θtHΌ½e‚ηVφΜΏžXΧφoe—|΅ηt€6λtΏ›3ΑvΓU{Tt€>&Ί3ήΊlΪΎϋώέOΩβ‡[6ψͺAgowϊοξ~aΪς΅Gο4`sΤF6‚²―…ΦFiΩώ³»~ ―GΩ 3¨ΰ^”οΛ|.ττN6GPΡ₯Lο4`sA—W@ι; ΨTt€€t€€mLΠuѝHAηθN€ƒ st§AΠ9ΊSιpAχ1!οΘcωηω+ΐ.R΅ci*Ί‹ώ]—Iw ρ ³Ώ~Kώ\ΞωώKωέ”ε―ο’u˜mΛοΆΤΏΜΈρΦΌgΫVΎ]ŸRόб†Ώw§;ŽzΠαa‚nπ]K]ν―ψpςνpλU§mο€νδϋ{wΊSιh―θ– ΊεΏΤΉΒVp2Ÿ0‹`,ΧΡ₯Ψ?žZŸξ@:ΪΏ£“Ώ00L–•]ΧmΌͺ“?»£«±ψΌulž ‚ξl·.eϋ~Ή… ’ZΥ¦Ύ›«ώ-Ί.ltm?^pNA'j£”Oœ/ίξκ/ά•°ΣΈ˜ΆžV:† ’ΫdΊSι(‚¨v6”ξ@:¨θέ)€ttŽξ@:Š  E i iDœΎΌ’]ω1: λ… €ύ­+ΩώIωϊτd‘½Ό“]ߚυ°E6Ÿέ ~‘Dης'OΝ΄§ός‰DΠHΟ»;Ωμώ’qZWΠ΅Vs-Λݟeσwυχq±:ΙΩ7UWcΰt]½š ΄-OU·’:‰Ιƒκ(:ΝθΊΞοζZ——m‡·Lqρ:i‘ͺjي¬+$EGPΆV“Έ€΄œ!θz=iIΠ­‚@b–½uω±»š!·.W A 9±ͺJžˆ¬ύε’­§Ετjky‹‡QVA =¦κjόρ‚¨΅Ÿ»[?^°š:I#Έ‘š[Y iyΠΩ§”"χŸ`ευx€­¨θώύΧΏΙϊ’t(M ΓFˆ\Vƒ₯)tΨ±“ ΐjΠ‘4‚!vrX :”¦ ΊΓg—³Ω_fΞεμή"4&³Έ]lwkΝπι@ƒΨΙ5•χ;³l{χStΪE’vΝfΧ²WΗριX%?gδA›«Ο#Σ†λυΩ|[<ΰ3ΕρΫΦJS¨έ―³­'·³Οj8oŸχ/·YΧτ”ν}u;;ŒΌ=Σ7ζ’μα^dΪϊTt―~›½Ό?–WWΧ;θ¦ξŸΥbΒn€ }?ϋ/»Χ&»Pkjƒ₯)AwψΜ$«˜ O«γMΆ§ͺ½-3MΊ~y ‘ΓύΫΩ–]^ Μ‹ΗΩ½'n½R)ξΗ₯)‚ξσCΣns₯²uΣ΄Λ]΅Μ– 7Ω=»ό°e{mΧτΟWnΪ¬2hh.@όrΚ½]΅όYύΈ§Ά/m}\\πήTο?4}Ώkͺkχzφ•>FβΖλvŸmήΞφvΓγ£zbEΛΐβΪflο<ΟΎӞgΫξύζuqυ«NάΞ+βOΩ«kε<ζΫ~ SλΧμΆϊ,ί“hd0+ΆcΦQμg§Oy₯18~{Ϋ;ί–ϋY ­ƒηͺ―ev.§υκŸευj_‹ ?+z‡Fpό™ύ?¨]εσ7Σ|ϋόφ}δΥSΈmϋΩλ>–ύ‹„ެ+ΪζΆσ£§¦γoκ²o¨θβΧή“ΛΩή―κ½_Νΐhζ ͺ?{{ΡΡ³½μ³Μkζ±ΪιoΤσ`Œέͺ’³ƒ­ ?ζ―ošυΘ ]™―έrA'Ί·oϊΗMΛ§ΧƒlʊnΟ„PπYJπ™°σ―₯ύA{MΨm݌_¬ΔŒΣύ>”Ά™cΣm+vU½2ƒ\pβΚ‰mNζς΅ Ά2Uώ―—1šŠόύŸ‹m|‘`¬U[Εgω.~ yΏkτ†έrA'μΰ¦Άω^‚:θ§OΩΥ¬«ύ;eEΧέΎ)IˆθΟγ“έΎώ|kՐ ž2l€ύA™γ# ΊΆΛΧϋ3?Ξκϋέy~τΠtόιPšBtΎJ[[ώꈨžp5 Cm@7'w>_eΠQšŠ|0+Χ šφΌ{ω.2ΨmΛ:vΚΐ³`Ί!aθΓφΧ‚¨-γή‹Ά%²oC/xšŽ?JSθ_ΡΙϋ¦J«Ύ/Už©θβΥ–©L₯··(§Ievή]P!IE2QEΣΎ}Σ?3Σ?κ–[m~cΊŠNn[φ»iΫ4°šηΩΓ+Ίόκ8>­d«(rΫfΠxpΐ’EΥ±©^ΜU퐊.Π°|hΘνΉ £Iϋ@lϊ_.TŸΖαU Ί3[υ λy~ti:ώt(Ma’[—ΡςΉΈε?»ολΦ/θΞvλ²qϋςœ 1?0ηί5Εn]šΟΐΟ#ƒΉiGΠfφJk`‰όVbΧry κvτuAw–οθς[UυΑΔ“ Ό΅•WW±0>PδG Νκΰ₯# ²msΕμ―|ϋ,ί₯XΏ,»ThœνΦeγ@lu³―~ίέwIυ kξΛ¬ΣϋE΄Άorr<ωcK,wλ·WϊO*0έώκ­K;Oδh:~»Ξ>šŽ?JS‚n―xPD ͺΈΆ‡Q€b«,kθ “€ςοo=3ΛΪΧ><γΛΟώβ₯kz;d}Ήm[Ζ°ΑΦ΄Γ.7,θϊl_Ο#ΥΘ‘}Κg 7ώΎΛΛBΉ76μ|f&Μ€j ‚Τ°ν\’šσλ=[7γ©K7ΈΈvΝΜI)A"‰œόώ};ϊΥΘ©Hάrςd–jδA°~=°εlx5Lο³|ύx·XA Μύ~–ϋΥGw…σΘƒονλppoλΡφ{›>ν›œ .·ofμΓ(ς"μšF©-/}#ΏΜgΪ_τ‹ ΐbž’ŸΊίΆσ£hC‹ΆγO‡κ֘Ή1UΰΨUR b'Rc‚ ‘ΚΖjΣ‘4‚.%φG†ίRέ±“ ‰±L «4±t(M ΓFˆ\Vƒ₯)tΨ±“ ΐjΠ‘4…"θώόί?\}RA¬}RA¬}RA¬}RΧAχKΆ3›eW_™Φνψυ΅l6%:ν,μzε·ΏΟŽ#ΣΧΕTύ³r>|η~ τ»μ 6}ˆΣﳫξ‡Sw>D¦;Ε1"FξγγOŸ”Ζ΅rέΑ|όAΖ³ƒΝšέ”ύ³rl؍tV~ΦtήT}άvόι“ΐΈΒ ;5ƒΑΆ9ΙύUνΆdNσQ_νJ΅V}]':P˜+λ`ύΑ|ω@L ¦w-ί­h~Λvέzϊ |!·μΐΐ,ϊfώ}±mιί]ΧΏ~_yˆ«fήr=ϊη ϊ΄or•γοκΆ΄IιϋyyŒIδΗgωyJΨ rσ”Ληύ—―ΣMkΨΏΖ k9?ϊh;ώτI `\eΠΉΫ;;Κ[Žωΰw­ ό- b0QΣ”ψ@αšβ–ζof>β—σ5_Mχ[Ύhά ΎάνΥε‚N}ζϊΈψbσηΫ©Ά±ΉΞnXϋBω² z΅·ςωJ¨ΨεΓ ’uεν‘Ο_OτMPͺυΉcφΨN―ΓΡ>ξs~th;ώτI `\EΠε'­ uAΥc‡Όκh>Α£…·NΉ²ήyν­R|YΡoω6zw– Ή³iˆeΰ5ƒ©ΪG»Ÿηt-ν›R4Tυφ£mΙΓΛŸννηΝυΏ˜θ}~΄h;ώτI `\• λΤτΙZ ΌΆΑψψΓ/Ωξλο² ͺ2Έu δ]Λ·ΙΫ~Ν…‰ΩמWβciˆkΓUtMνλ`—uΗEMφΪΟζάƒ.ޟ±χϊžmڎ?}RWνΦ₯œΰ~°‘[;ωΰλNH;p䃱ΌΨΥll ΘΧVΗ&°ͺƒ‡]―nκΤ„š©άμ`ίsω6ε`κ«Γώ·JnΩλ΅Δξy{€σΎ―]cTηΠ/^{PL¬τvίδ3ςΫw·‹γΣέΊVν Ϊί΄Όωάτ­Λκ1U[ΧηόθΠvόι“ΐΈ:F1ƒ¨TνΙοή—5Lέ{Ε ΰ“‚Dό@‘EΠm(·ίωΈ’½> μ ξΧ5d0_.θjύ₯χΗ­+Έε= /υΰM0θ6τ¨;t΅/ΆΜθΜ6‹}“ΟΦ^ΘΘkwIx}dŽCΣ°*W}#ŠΛ—vζώΦ»ΜcΦ[TΠΥcΧΣΗ°ξ{Ce⺎Ώ#uRWtH€ ΨjpΖZΠ'%€qt©‘Ϋi«9\<}RA¬}RA¬}RWt€ˆ $ $ $ $ $ $ $ $ $μμΡ5ΈάoKIENDB`‚rocq-9.2.0/doc/sphinx/_static/diffs-show-proof.png000066400000000000000000000325111516144147600221070ustar00rootroot00000000000000‰PNG  IHDRftΆO˜2sRGBΞιgAMA± όa pHYs‡‡ερe4ήIDATx^ν}gXUIΆφό™οήϋέωžιh眧§»ΆΝ9+fE `Ξ9+ζ,(*9 (ˆ"’³DED1c ˜ζΠΆ»{}υ.{‡ Η>ϋ`•Οϋ΅Χ]aΥ[k­ͺ½ωύ–nέΊIIIρ:””vE&™d’I¦ί3Ib–I&™dX’Δ,“L2Ι€±T)1ηδdαΓ‡$$$$$~gTJΜ–$f ‘RbNNN ΤΤ$ ‰ίUƳTcΟ•σή½ΩtμΨ ‰ί’˜%$$$4IΜ ΈO‡ όό<:p`Ώ&ŸδQAA>=zX΅ή–Ζ¦ ΰ <ύQKKuAP7kΣIΜtδHνίΏ²³3(3sed€i¨Οή½YΌhHrΦ0&XΤχνΛ‘¬¬t1fZŸ=\'Τ u΄&ύ‘Δό‚ʚ›»—‰Ή¨θ,έΏ?~¬ Δό‚C!ζ3gNΣ΅kW5‹άά©“„BΜ/^P7-u“Δ,aUΔ,QHb~>Δό‚γ1ŸβσžZ…$fmβ1ŸW7-u“Δ,aUPˆωτim3Ύu uR{PˆωΒν3κ&‰Ή†Ψ—»—Βw„SPH0SΔΚΘL/'““E‘Q‘|ίΉCΘd”“‘0 ’˜Ν‹C‡ς)3+“φ€οdV™BoΘS½Χ!‰ΩΌΘu·Yœ˜w’νΪ£ύ­qSϊφ‡FΤ»Ϊ°i£ξ}ψί?0€μαλ@·ή}ΙέΣ³BY5Η3b.€+W.›ΨΏxΈ@ΕΟ8ΰ―&WX 1ƒ”½|ύΘΥm#­ίΈ‘6nv§ΝBWψRrJ²κ½Φ]ZZ ?Nuάj θΚSύΊ#€Ÿk«?¨κh ΔŸ@ξ^ήΪ#ζF-Zј ιΰΑ<&εΌΌύ΄pΙjΤΌ₯$ζη…˜O:Ι ΆΐD:%¬ο‚Γ”0Ÿ9LgϞΡM0SaΔμH ‰‰”ŸΘ?ΕAτ‰θs΅{­ϊΔ¬6n5Κ9Yx’:Θϊsμψ1*.)V•5’˜M€>17jΡ’ ξm;€ƒΆˆΑΙ§­‘ΫΘqΔHϊΎI3jͺ5}Χ°q9byCαCΆ†ΠβeΛhΒ”)4rμ8š2cΉmΪ$Ϊ’Xξy‘Q»iΥΪ΅Bn*3–&NJΛW­βπšΚαγ&N’‘#Fp=FŽ’ “§Πͺ5k)rw€N8ŸG»Dήό…‹Δβ3&OŸNk]\ΘeΓzΎΨΘ$„Οqξέ›C^ήή4ΟΩ™Ÿ{f͝K>~Ύ”•©+ξ3ϊiα’₯,7jάxš:s&­uu₯Ψψ8‘ΰ•ξΠάČI΄%8˜¦ΝœEC‡ α’ο-]Ζ§>Τ䍾,gmΔ°e ₯¦₯ͺΚψ>πŽˆ²mEDξ’81VψkX% ½‰‹γʈKˆ§¨θhΪΎcEμΪΕΟ9$Θ !“έQQΊ};—³=<œbΕ}9’――@^ˆΠάŸ˜ΐϊ{’cc(=#RRSD]"ψΩΫπŒΔ€$AfyB+ΐό3b.U·šβPΑ!ΪδαN£ΗO !Γ†³‘ζ!ζ€š¬±@έ$1ΧϊΔά£o?κ£'΅λά•Ι ±–ω Rמ½8――=΄>1#&γΆi# =šΒΔ4Οy‘Τaδ0Τ‘­ν¨θ(VœœlΎΦΧn ΩJΞ‹Σ’εΛ™ΠΧ»ΉΡ.1)Œ•Sκ²m« α5‚|–ς³fΟ›Oύν¨OβηyBα“™ό0IΆο§ΙΣ¦S§nέi€Γ &ά%’Μα£Η輁UkΧPO”dZΆrΩ Lƒœ˜Δ§ΟšMφC‡r»\Φ―g—““dά«_. υPκ»ΩΣƒ―+υ5„>1Γͺ­-π]ή”΄4š>{.΅οbΓ m?1nΗOW•7u‘˜ρ}`o??yxzϋθˆ2:ζ)YξδθΆy³ΈΎI*A‚΄#ωZ‚ Φ¬μ,AδρΌu+_ Ϋ.τ2’ΗsAΐ mεY‘ΫΓhƒ0"6yxP° p<Κ‚n œΐ `Q&vύn1g’b’™°«Z؟s2»ΪΈΥ…§ …ρ²›œF¦ζmΪQΣVm„.ΝQ•5¨κ(‰ΉΠ'fΚ¨qγΘ¦Wo1©»’‡—Ω ’λά½' 5ŠΖMšL ›΅Π3,ΕΈψXκek+ Λΐr±‚ΰ:uλΑ$‚‚ #Ρv 5Ž•8AX!IΙ‰B·“―Ώ…‰AT1brT'§ΦXΉ°Tf BnΫΉ ·υ„EŸ»Χ£YλΆlω―Φxrrm“dΤΨρεˆ“ΟiΣ©χΛLa%ο,ͺΩσηsΈ§·m1™½aν₯ VβΦ:1)cβ&$Ζ‹E#„Ό}}ΨZR«/ s‘pΥ”Ί¦€ΫxπΠ!±¨¬’ΑΒβιΡ§υμkΛ.©šΌ±°FbφΓCίόƒ~ΐ„¬>1{ˆΙ"> tE±t‘‡ 1#6&­xSΎώώ΄A\ƒΘQ.ΖήΛΧ—6Ί{= η…ε)Č|XΦ{…ήεΐ‹‹‰εϊzˆΕ!Iθ$tυLΫ“JI)Βj2ϊmΤ‡Ή‰E'#3SxΌ3…QδΘ†Ϊδi3Te…$f OΜA,[Ή’­ΚοΕο δΖ-[ ΒΝ.?¬h°BΜΩΒjΨ,­iλ6TΏQ&DX ιPDl$"τ—Š rΓ&"B&=ϋΩrhΒΗί—-ꬬ ž(‚¨π{urJύ±8°"‹Εα…,11W Φ뎝ΨΚΕυ˜Ψh;q"“o«φ…΅›Δ m@ΘAŸ˜QwηE‹ωw΄k“»»˜x{xqπτρνmΛν‚7λz‹°˜Ϊtμ,ϊͺ“αΡW[‚·09c«ϊ“:ζ$fLΔ1}Ψ±Χ8x(x-f΅Ν?%d «OΜ€ OCΏ,…˜X±J l‚XΌQΆΛ7Š&tI λΑϊEΎŸ σμμlΎ¦3HδqGYU€˜Aπxκ‡Pˆ~^.λŽ~HΔψΉDuάj‚ββ"~6Œ!5λE"μ/TMήX n’˜kCbFlΩΣΫ‹ 9ΓΊ\Ό|[†Δ ^Ύj55δ ƒ% š·mΟaδ#·q.~ρ<ŽY‹ϋš΅iΛς ?a@  e¬Nu‡lpβ©3™ˆ:Ϊtc«uFέ›·mG£Ηη#aΒMEόD ?S<ΚΐdΫ,άK}bθΤ™³tyXxπμ–ν;0)Χ€Œόι³fq`A@,Ό•xφ͚‹η·ΡYЁμŒΨYΟυρŒ˜OθvΒMŽ$e‹ΕiζάyΤ‘«X@|)_XΞ jΈ¦˜tjχ 裡³Ϊζ,X%dυ‰9xλΆ G@Ÿ³»πzβt–+Βwy Φ4BΚ=(ˆΩGθ)¬l}bφρσ§”ΤT1ξOλFXdKp“σ†M›™πςπτραX4Z)ί 1—––¨Ž›±€ώΰYc'N’={‹6ΕΡcΗDf‰ΉϋτΝBSΊIb! ‰94,T P$o5hڜμ‡:2YÍ7$fX§PjΔ‘@xXi!«œwV€˜0”J˜š–ΒΟΨμαΞδ‹M†V:rˆaΤ©±ΡΉGO>~BLJJͺ‘Θε3† »GŸΎ4nβDš6c&ox!V6iκtΆH X,[7δαφO²ˆ+ΔΌΦΥ…7Ω*aΘc1ΒfhϋA[ήΆ εb‚‡lέJΣgΟ Δ@κ,κkΣ«9ŽΑ'7@τSƒ9ˆιϊuόŸ§ψRM¦Ά°b†W’t–ώ¦Ÿ‹ƒ§Yx@8ꆉˆM7C„YXΖ8Slxl FH3Θ§*|8,€Ν;Œ­"‹σxv  lXΗΠ]ετ{0ΫΒBΩ°@l„’iΓUd Q[b 3Π萹IΔl \8šWV•ˍΏ” 9Τ Κ€\‘Biρ1uL Θδˆρ;δτ•εΓbAY€ρ3M_‘•Cω H\Η³aΑ#άπτ>ΤaŸΞjΑ°Pφώ&χ“Φ0HaœΊ€ yΤΟγςEΩ|(ε£ΓrΡ?(“λ+δρτ‹~ϋ ‘σ‰ΗΨ­48"§Lό¬&S[`<Ρ§jmΠΠΧπ¦Ποϊ›~:ˆ|E0n gδιo *€AΗπ³2ή†2{Θ(² RΓ² Ο|]Θ^CΉͺεόV§£GŸΙB!fsS7cπΌυu³b†g΄Yx*'ζ x 18$„ίξaσ›}Ύ>δΰθH š4γΣ#π 'Ξσ&$ˆωψρ£μVš e¨]3¬…˜_4(ČΧξΥΖΝXφ&$1Ž€«ˆΠβΤψφŽΰMš67(ρV!άG΅ϋž'žσU₯Φ rrž†° λ/aY(Čo‘¨›€Ίi™˜q2&:6–?Ω€MWΌπ#‰ω‡B̈#β%­qs©“ΪƒBΜψž·ΪΈi¨›–‰Y ’˜_p<#ζΓTTtF³Δ¬M€μRSAΜ…ͺγ¦ n¨£$f «BΜΨp<{φ΄f‘!uRƒxJΜOΏN¨6nZκ†:Jb–°(ČρY΅ IΜΪ„BΜx₯_mά΄ΤM³„UA!ζ‚‚C‹Σ*πU?©“ΪƒBΜxAImά΄ΤM³„Uα1._‘f!‰Y›PˆŸuU7-u“Δ,aUPˆGωΰςiYYιR'5…˜ρ‚’ΪΈi¨›$f «Β3b>ΐ.ŸV!‰Y›Pˆ?«›€ΊIb–°*9b~ϊGπ½ -ˆΕD­ –C~ώΣsΜ8Υ£6vZκ†:’jmΠ"$1Ώΰ€fd€1ι!œ<5εΆ@ΘψcδRf&ΎΌ·Bύ%, Ό­šžžΚcο ―φ«₯%€Ί N¨κh‰7kM…$ζx±$77‡RRhΟL0|Ή_³<`Εγky‰‰±LΜΦ4±^`Σ―Λ?£tώ"£ΪXZ¨ κ„Ί‘ލ«Z΄IΜlU$''RXXωϋ{‘··»&ΰλλA[ΆψΡξέ;Ω’=ΏΊ'a°°cΑŒ‹‹¦@ςσσTKKu ΩB±±Q\GΤU­ Z„$f VXX§{χf±e ·O @ˆ±e|Wϋπaλ±v^4`Α„uŠ—€0fjci  .x•?/oŸΥ-κ΅&樬γδ](!‘i@OΥτWBB‹¨51Cιm6KHhΠS5ύ•Π"*%f|˜±ΗκΰuRu"HHh ΠS5ύ•Π"*%ζδδ>”]–†PZτTM%$΄ˆJ‰gH‘w«¬ŒΚJΟQYI‰*ΞΊDyGoΤ\₯}1΄wwΎUm@[TΫψβŒΠS5ύ­ 7Μ₯«{²ιjJ†uC΄mQk£)ύR G‚+™3Ν€J‰’…Σ/ΏΠΟwξΡΟ·ξΌψΟ΅2ϊGζ~ϊ{jŽUm@[ΤΪ(Q=€¨CφK% 4W2‰˜qνΝΚ¦βόCtά…rΧ,^/£›gŠ(9bέ8uFU¦*X‹βνΫμK‘ΛVSδΥΏz=ݎI‘')ΩΊλ΅QΌΊ<ΎΖΒzPέψ sP]μ—²Σg©pί~*=t˜υΛ°Ν ͺ”³41ϋζmžŽ’Λet"g_ω ZΞ_€μΨxϊφλ―)uW€ͺLU°΄β‹!Ί[―ΎJώӟθW^‘cώΫθQb†ξΊ©’ΗW(`]_cai=¨n|…©zPκbΏ€οަyS§Ρ²yσιnι9ϊ˜†νVΞΔό@XP™Ρ1Τ°ώί(.t;=ΉzύYε4tΦ“+ΧθΊX<~«ΙTK+ž±Έ™@'CiέΨ‰f%ζ§γΗΧXXZͺ_caͺT†ΊΨ/·‹J(ΨΓ“κσ Ι;ΐ£a»υεώφν·ε,MΜgδΣΒ3…EeO{2*]]¬Šβ=ˆίCYnž΄lψhΤ‘3υoӞζ8 ‘4ΧΝεnTo0ΉM˜JC;ΫPίVmiBo[Ϊ±h]‰ˆ-§ ζΖΝθ$ς1Χ¬Δ\ΧΗWH}_B­\ΰLCΨΡΐ>}iώ΄ι”ΗNΡ­Ž―‚GI”Ύήζ: ₯~’nvν:ΠΪ1θO_―©Τ•~ΙΩδMσ;‘M“fŒξM›sDΉί/Όq“£’©}λָٝž*•³$1]Έ΅»ΆΣ‡ο½O)‘tοάωgΣΓ£‹—ι\Α^ewμδUζτώτπΒ% ‚η—Ž άΔdJΪ!ΚΫE‡φ€s|SίJC°½ =ƒ7£[LίΑε‚4°‚)rxζΡΜlŠΩʈ «Υζί―Š]ιŠ_•HηΆοJΨ‘z5oE[η/¦'bp‘K„rbEžΤ·ΏP’­t;&™N‡„SZ7Ϊ#,E~LΚ€ΠHΚΪθΕεbγbΏ‡?]ήC?ιm^ ·YMΞ’Δ\v¦ˆάΧ¬£·ήxCΈΌUw01™0V/\D­š6£/>ύ”š6lH‹gΝ¦cz+Μ΅ΒΣδνΊž:·kO_~ϊ}σΥWdΧ»ν ΨΒ<ŠάΜ‰ΙΆg/1xuhΣ†>ωθ#jό}ΪΈj5έ:[¬“Q`u³^=zυε—ιό#O^εΊ±PˆYp'gΡέ 4ͺ{/ή|ΐπO".[η†MΘmΚ ₯!. ρ˜2“:ύИΎxοϊϊ£ΙΆM{ s^F·’“ur%B‰=§Ξ“­}.@Θb’… ρ^\ZΉ2ΝMΜΚψ’λκψͺα_’MwKΞΡG'α€ψuε:]NΤμψ“39|η€•|ŸιsΘΆu[Ά MΡΦΪ/ϊ0–˜ο—RμΆ0ζΆθmτο²[εϊB_.fkhE9KσωΓGi•σBϊΰέχθΚ‰“ε*¬ ΄ΰ0Ν?Z6iJ~άθxΞ^:’F‘>~΄+(X'·yυžSFa—–Υ Ϋώ׊ Ωͺ“ΓΔmπέwΌjη&%3)@f¨έ@VE„ώŒ°άΆϋϊΣλ―½fbc՞iη@]7ε˜ZYT―π<¨ΙW_ΣdαΚ]ˆΣέ£† β>L"Έš‡ΌƒX‘νΫuβψυΞΕ+uraΞKiγΔi½|-[?9›|Xn„MJX³Ύ\™ζ&fe|ίηέ:;Ύ†ΐΔΒ‚4{dκΦ±ΧΟyrρ eΊϋhv|Γ γΘ©K7q}«ξZ̊u‚˜Ϋ‘C‡N&³eϋ%άδ~1„±Δ o/;.κ½φ:mσφ‘/])ΧϊrYΒ³« gIbΖ€\Ή`}(\έΚδpw†Ω;ΠΤ1γΔδ.δ]}Έ‘ΗοΑ cά€pswς.;d|ΦoyύΙyΖL]y˜Έ½ΊΪΠ†ε+ΈS°9αΊl9[XkΧιδΰά-άπ7„eebFœnΩ°ΡBΙ;Σ–9ΞtvλNžχγχP΄˜ίώo >JL§»±©δ7s9 WnβΣ°ΆJΙbKΫ‘}'vΣ°±xGΘΒB@ήΌΑŽΊη•†Eς3EΖ³ˆ2]ΖM’αBAέ„β*r€Ή‰Yίή}·ΞŽ―!J<έθuEl‹κXΤ%fν͎/¬eΈώmκO£{τfςZ:|4ωΜKAsςfuŸ–­M&fkνCKΜΠϜψDAΈ―Qˆ—7ίϊrO ά@Ξ’ΔŒ‰·^Lšwί~›]K ”~₯X\NbRz»¬―p @|°k‡4Ζi˜ ƒ#ΊkˆU:ΩΫΣπAƒty˜Έψ=2(D—E+ξ]³h±.OAm'ξa¬™0…72€‘έz7B_ψ1 λΪƒwz‘˜ή€ΆνωLeΛoλsώ »AΤτλoθΟϋ'ϊΓώ@Ÿ Λsή Gά³ϊΒ₯Η$RΚΨ#}χΙgτΓ_ιςΤΠ[L°ŸImΦ \ώLρΌΝZПώηhlΟ>όεΪ€Ά¨΅±2(γϋΞ[oΥΩρ5Dnbun׎ζN™J§χηιβίwŠJhD―>š_όŒSΎω— ωΛχ?υϋ+uk\θλGτ…¨“)zXkΏ‚7š΅€ϋ_ΝσUΙ7μxΠ+„ΚnΓ~‹rMKήΉ«’œ%‰“"ΘέCLά·ι`κz|ωjΉJΛζΞγ‰°qS…k&;βVˆ=Ž>‚.=»†ΝXcŽΒUς0qΗ89ρ¦’*\ˆ±"+Ί’§ ΆŠ7Ψ¦;―όU‘kγf7{γεWθαΦ@1•k­Ώϋ½ϋz=ͺχΛώ χ^½7¨•PfEŠ Ήή|“lDyˆΫΥroΎς*5ϊς/ό;ς‘ĐϋτέχtχΈ^ΣΟιΏώψGjρΝw|jDΉ†6άΦ‹Ρe|ί“½Ž―!GΈ%igŸSUςΡw;uΡμψ2Δ½o½ϊ£ΡWΡεÐ@ή'oΏc’Vέ/zhί ‘(ηSϊ?BΟUς ϋΙM|ώΙ'Όω©ΏA­ΘmυR‘³$1X-ώ"άΈ΄xEQΙWΰ㺁'ή9σθ'1±1Q±‰€ŸΘ ―_ž<ΑAψ1Ĉΐ-[œ:vœΌί{β†2$μαδ;±)μž)ω8ΗyKΈT°T° ‚έfΈTΨi>βBC;Ω°bΒ-Γ}}ZΆa·.ΧݏC!Eώφ…Λh°Θ›άo—χΝFX;MX³ξΖ₯q,ΫsκL²¬εωΒ)!σ³B㌦ώ&‰©.,Ζχ«Ο>―³γk„YpR.)Ϊ‘δϋκ Ί-Ζ^«γ  ΜAΊπβ]KW‰zdr7ŒŸΒυFy¦κEϋ%Άvύ’cCΕ „Ρ1Ÿ==μ‡(ω†x*7―’œ₯‰G›† ΐηρφ‹bΏαxvκΘ›C˜8·Δj{αθ1žxx“L‘[:g.ΗΟšΓ› ηγϋϊχκΕV›"gibΖ %M„{θ=m6ίΎ[—@©°γŒdlfδ{ς±‘D‘\=›·)(δ9gχΛyΘ0ή΄)ΪA#lzςƈ¬ω¬Ψ8–Χ©acvυ°ωοδyπΔk V{CEΉq«\θ3aQ¬“±$t—ΘzΙΤ YΧΗΧ™1±Τ¬Q#ςwΫ€‹‘θ»'Ήš_Θ‡u‰PA±Έ~Ψ7ˆz·hEΆmΪ1™ͺΦή/ Œ%ζόΤ46&͚MEωuω†€œmO9K36y‚6{πKY1qLώG/ρΉUμάcWΎM7,&:Ύ»€s¬ŠvκW:;Sοnέ¨O·ξΤ·{Π»7ys)χbƒ₯‰9~•+}ςΞ;δ:nςo P~ΰ1Όic3 ¨`pΗ.δ.”JΉC>[ψ-BvΗYhΌ«cΣ€ιT΄-Bw.;ӈ…AΉ!3JL8(wQ¦‘‚…AΫYι‘؝¦ΨΪρPS'$Ζ7Xg]_CΐCψμγΙmΕ*ΊxμYΨEΡ­Ž―ώυ5£Η39£LΈυύZ·εΝ1‘©z`νύr*8œV‹~1 e +GŽ-Χ/Ωα€^΅Ζ>tLi―>ΉοΏύ’œ₯‰.Ξɜ}ό6Π–J^_DL Τ½\\y³hΣͺΥάύXΚΑ›D[ ΰLμΊ%Ki‡€°ςι_ΒυUδπ‘Xbϊ«Σρ콜—―ΛSπ48ΑqΈ°νWEρ”Ζ©Œυγ'‹•ά›nF%ις@Ο„μ ˆ%+Ε™ΐοAβψϊξUδeα?s-1†VOΫ,αχώυC$…AaμκAy ΠΨνFYxΥ5yέFœμrψρWxΛkΪ,>˜oκ„δρέ›[gΗΧ%‡ ψ-ΗΌδΤrMΡ­Ž―rύΗδL:μ,¬Βω΄tΨ(Z!žΎh9ΧΧMΥkο— αQάϊΐ"ΗκΌ΄\ΏξΛε“@ϋφ₯ΛΗO– έθC‘³οΫ―’œ₯‰ΐ;Ξ5"fXrθpΉk–ΖυS§yWΑy¬ϊj2UAQ<}%°F˜:!Δλκψ ©ꨋύ‚π]ΰ&wΪΌUuΓ[NNXΝδ΄@ΜZΔύsηιZα)ήωΗn2Nΰ…5Ωͺ '€6aρ5RΤ!ϋ₯HbVΎ€…oτβ;Ν7¦ͺ§ ͺƒTΎϋBΰα£›T\΄ŸΞœΞΕgφΡ½Στ τ¬&ρπB ύψθΆj΅€‡oΣΉϋET|ο΄&Qzη έ;―ή·¦ΊQΣ₯犳ϋ¨ψN‘jMΉϋεΡΉ"ϊΧΉ‹τοs—~WόηΒϊεΗΗτΛOOΜ‚_ŸόdɜiŽT-1"ώέωυ!έϊυώ kΏά’=?ξ§€GΩU2U+C’zΫΟ–‚ΉΗWλν5ζξp 8F¦ςΙ$b.ϋω.•>ΈD~ΌJΧώ₯-rΊωσ=Ίς2:UVDWώ^¦*SŒ@΅QΠΊάΖΒD΅σR<…ο¦mE‘VMρχ2(ια³λζ& ­·ΧXθχ τδάΓΛtρρUΊωΛ½ mVP•œ$fυd1ƒT&̜Dk<ΦQNa^Ήk–ΖωGW(6'Ύώξ―΄+-ZU¦*;j3q΅ί‰&χŸ±°4QuΤ…^}ϋ5zεΝWιγo>₯ΐcaOΙκ·λ΅_5h½½ΖBΏ_’³βhξŠ΄ή׍IΧ°Ν ͺ’“Δ¬žjLΜ_£”ƒιΤ¬MsςίΉ…Jξ_,ΧΡ–Ζυί¦3·J)"u·°ϊŠUeͺ‚±ΘΤ‰[ΧϋΟXXš¨6fωΠΌΰΕΤk\?zωWΘ―`+ΕίMΧ]7u|+ƒΦΫk,τϋεθε“δ⽁ΪvjG珱ξΆ»:9IΜκ©ΖΔ|ψβqZξΆ’ΊυνAIyiUΊ0Φe­Ip£±k'Ρ ΉNε0Υc6yδšων€%.ΛΘyυbrρ’μ“ϋΕΔΌσŒ¨fQpαZΌs^5’‰nΣΙ5Νƒ"―&ͺ’ƒΉy-‘¦yΝ5 1[{{ΔίΟ οό šα;ŸœDέ†/CΞ‘Λ)θd8_Χο—«ΌI;’#©q‹&΅Ξή>W‘_ͺ““Δ¬žjLΜΙω{Θ¦O7Z°r!:wT—_W L ΩΞΤΥ©;}έδzι΅—θΝή’o[Φ'Ϋ)φ΄:nC'‚Ίή Ž].$ίπ5y υΆλC{t‘Ά]Ϊ3iΎp\ΧΟΑ§vŠΕn΅·οLM»΅`tpθJcΔ’θΉ?°q˜ζ$fko―„8FO»6£F›RΓΞM¨UίΆβΎ9~>¦BΏdΝ!ϋaƒhόŒ‰ba:POτQ™œ$fυT#bΖ¦Uhόϊΰγi[μv*Ύ{^ΧΑϊΈ!,Έμp‰ oœ₯Σ7K8v©οΒΐRΌτδ:½sNΘρfSρ½ 6œ°iP"ςK…Λ―”wζV ]όιZ9kΟ„Μ‰kg'Μ±ω·a'5θЈzνG>ƒuω5Έΐ‹Π b²Θs«―°”v ©T,BΗ¨gήΤ΅— ω…΅ŸoQΪ£}4~ύTjΨ± ΅±ν@›²|iΧ•a±Σό₯΄(|₯Ώ…₯}3•v\Œ£°’( +’ˆΛρ{;­ά&VΒƒLŠ.Kr±OεtrΏΙ(0'1[{{Œ[7™uiJέFτ’Σδ™·…šuoΙδΌ$bu…~Α’³Δe95oΣ‚βφ&–λ}T&'‰Y=Ո˜‹ο^ υ~鍷ހ½…yμΎ)¬ΓO[€;΅ν܎>κsj²-\³„θdp"!pW0υΠ›ΎψϊKϊkύoΘqμ0ŠL.G@s—/ aγGΠ„Y“¨}׎τΙηŸpΉžΫ|˜Ό9Δ°‘φζΫo2ή~χ³lώ™“˜_„ώSpυ7™ό―όύ/H8}β4nυ±οGAtυ?7)φz*΅θ՚ZφiCΛ"ΧRܝtJ|Ε„RŠΉ•ͺλοέ7’iώΦ₯ΤͺO[ϊΰˏθ“o?£nΓ{*α½θob f.€½ΫΠ{Ÿ@ώε#κ:¬­‰wγ²9ΐœΔlνν°΄wθL-EYX$ξgPœ+ΘΔμ0Χ©BΏ ,Έ+„ήy=6:* ΝU&'‰Y=Ո˜α-Ω;οΏKGΕΟjƒKkρΊeΤ΅w7š·ΒYΈwδζGnώ›)<1B'‡XάΠ1N4d΄#ωl ΝΑ^ΤoP;mΕdΕλδ&Ξ̱©ώCμΘWΘy‡ϊ K€ Ÿ8Š­E$“u|['s–Ν§—^~‰BγΒu׍Εσ$fkιΏΉΛMο?C”ύ|OXμi§ uλΧ“c―GΔΒsιΧΙ'7˜ώΪμ[κ1Ί[gJίͺanΠb&œN=hΞ–E4Γg΅ЁϊLθOk“6ιδVDΉΠΔ ΣiŠϋ,ZΆB'7`šo€ι—iNbV`­ν‰Gλ‘ œΰπΘ Π][΄}%sη‘6ϊžάξŒXzύz¬;•yY•ΙIbVO5"fXU V-€χ>|ŸN^?[γlδ1hΔ²sr œΒύ<αα²ο;u€­DΘ€†OI½φ%/A°ώŠ„ ¬Β~Ά΄hνR]y μζΞZ<—W]ΘΞY6γU +ENΑΉ‡—("5Šκ½YOsΔl-ύ·+Ντώ3­>4p˜Χ+­ “-ϊ Oژτωχ_’έŒAl-Ζχ{eΜz½z"o΄Βa ³ΦύΪΡlgΪ}=™v^Š£αKΗ0 X>V7.^ΒυޘιΓ±άΈ;{Ψ­Ό`˜ •n4ΥsŽNxΔl­νMΈŸI[Ομ’ϊm°Μ]RάωΗΚW³ .°τ ϋΗίβφ&Ρkυ^'//L•ΙIbVO΅°˜OͺZ|K\—1©¬v_Wα€{. w―cχΞ4t΄S9χΕίΝ ˜›iχ„ι4T7 Žƒ»ŠόžΊ<Δl1N8U³lΧZ>ύΠo²»ηŽ Gκδ€ηAΜΦΪή„ϋ"Θ½~λο9ΎŒΓiρ(–ŸΰL­mΫQ‹ή­+τ [Βιϊ–π έ5}T&'‰Y=™cΞ9ΉŸΑθw>0sρl²>ˆc˜†ΧΔί`Ή΅VάΘI£ΩΒP%ξOa±<@—bq;ΌœοζΟΔλSΙS ebΆ–ώ3'1ΗοK昢Χ6_ή€Tςυ]ϋΎ“°E¨τ­ίαmlρ¨‡έq!–ΎoאzŽιK‘Ε‘:Ήυbl: Ά‘vvψwΔHWΗ»QορΆτΕ_Ρ[ΎM―Ύυύι₯Gοω!9ΜuΤέ D^K’ιήO‰ΚχPΗS•k¦³΅Ά›ˆ8uΡ }CYΰΊr ρp,νvͺΠ/•ΕŽ Q™œ$fυT#b6ζTΑŠ«ΙΞў–mXYα€Ήώ―ΫΤΉGWz›-I”YΫρ΅Φφ*p\4’šΨ4ηpΛφhAφΫΩ‚YΟ \X‘_p>y “›>‘ΪsΜjr’˜ΥS‰;ΜOί\λNI*ΎΉVtη<Ή{±εW{ϊΒY|Jb­§+ΉΘτA.“…Ϋݟ¦;Ο€©σ§S_{[>ή•yl―NΞRΔ¬ΌωKζνίβ_¨ϋΘή΅~σΟϊϜļ3e7}όΩΗμ Ζδ+ύŒέΘ₯οΔ‚L†R―1ύΨ²`8/υ€¬ΪθHφ³‡’έΜΑ,3ΤyΘ,FXΨDC~―qΆ4xή0޳βwΈθ†D`σ ±άΆv©ο$;šΌymήλgςψZk{•λn™ήό¬f=[‘νδ&Α ΗΐγΫΛυ Bqπ5oLA»ρFί³…HUΙIbVO5&fμ¦ς·ZWώ­‡“ΧΟPHLš2†O8ŽΖΗ΄τγ‘—„«·[ΛSBιG†ΨρΡ"”—ΉΝAžLJ{ ²ty8ζ΅ΦΛ•Ο‡*y π LΔq60Ό^” €ΌωΧS΅}σΟϊ ›©ύgˆΚ,H₯ŸAD ,‚Ί0 tqμΞ–’ώ‘-X–θw»‚ ©!0lΙh>‘ wsŽX1މξ7N@ŒwB£VMΰ1Uδ`σ ΗΟzŒκƬVD»˜<ΎΦΪ^εzό½trIuηΕV<ž=jεxέ[‰ϊύrδIZ硞Ϊtl[αϊ¨JN³zͺ11˜ΌgMβ“ΨΔΏfiΰΨXHt½αϋb•~f%‹+.£]ηγ9VW Y΅2ͺƒΦϋo«XLν?cal?[ ΅_5h½½ΖBΏ_ψ«qΒCsυ1βλr•ΘIbVO&36±@.8«₯ο #,WT@ӜgM–{ΒXœΊYL_~χ±*@¦°μΩ{MP—ϋΟX οŒιgK‘6γ«­·ΧXθχ‹όσσK&³ακλFύΫQ».¨]Χ΄rΣ:*\(5Ωͺ€σ¦λb7Ρβ«ͺd «V†5’\ ˜ΪΖΒΨ~ΆΜ=ΎZo―±0wΏHbVOu†˜±Ή€&ζ―pζ³Βω%‡ιςυΓξUA‰*1·Κ`j R«Πο?W_ΣϋΟXΫΟ–‚ΉΗWλν5ζξIΜκΙbώ•ύϊ=όυρ »Ώ<€c?C‡ŸV Θ@V­ ‰κal?[ ζ_­·ΧX˜»_ΐ-ΰ™Κ§j‰Y&™d’I¦ί7Ib–I&™dX’Δ,“L2Ι€±$‰Y&™d’IcI³L2Ι$“Ζ’$f™d’I&%IΜ2Ι$“LK’˜e’I&™4–$1Λ$“L2i,Ib–I&™dX’Δ,“L2Ι€±$‰Y&™d’IcI³L2Ι$“Ζ’$f™d’I&%IΜ2Ι$“LšJDs?i_A5IENDB`‚rocq-9.2.0/doc/sphinx/_static/notations.css000066400000000000000000000144001516144147600207320ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* span, .rocqtop dl { margin: 12px; /* Copied from RTD theme */ } .rocqdoc > span { display: block; } .rocqtop dt, .rocqtop dd { border: none !important; display: block !important; } .rocqtop.rocqtop-hidden, dd.rocqtop-hidden, dt.rocqtop-hidden { /* Overqualifying for precedence */ display: none !important; } /* FIXME: Specific to the RTD theme */ .rocqdoc > span, .rocqtop dt, .rocqtop dd, pre { /* pre added because of production lists */ font-family: Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace !important; /* Copied from RTD theme */ font-size: 12px !important; /* Copied from RTD theme */ line-height: 1.5 !important; /* Copied from RTD theme */ white-space: pre; } /*************/ /* Overrides */ /*************/ .prodn-table { display: table; margin: 1.5em 0px; vertical-align: baseline; font-weight: bold; } .prodn-column-group { display: table-column-group; } .prodn-column { display: table-column; } .prodn-row-group { display: table-row-group; } .prodn-row { display: table-row; } .prodn-cell-nonterminal, .prodn-cell-op, .prodn-cell-production, .prodn-cell-tag { display: table-cell; } .prodn-cell-nonterminal { padding-right: 0.49em; } .prodn-cell-op { padding-right: 0.90em; font-weight: normal; } .prodn-cell-production { width: 99%; } .prodn-cell-tag { text-align: right; font-weight: normal; font-size: 75%; font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif; } .prodn-table .notation > .repeat-wrapper { margin-top: 0.28em; } .prodn-table .notation > .repeat-wrapper-with-sub { margin-top: 0.28em; margin-bottom: 0.28em; } .term-defn { font-style: italic; } .std-term { color: #2980B9; /* override if :visited */ } /* We can't display nested blocks otherwise */ code, .rst-content tt, .rst-content code { background: transparent !important; border: none !important; font-size: inherit !important; } code { padding: 0 !important; /* This padding doesn't make sense without a border */ } dt > .property { margin-right: 0.25em; } .icon-home:visited { color: #FFFFFF; } /* Pygments for Rocq is confused by β€˜β€¦β€™ */ code span.error { background: inherit !important; line-height: inherit !important; margin-bottom: 0 !important; padding: 0 !important; } /* Red is too aggressive */ .rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { color: inherit !important; } .rocqdoc-comment { color: #808080 !important } /* make the error message index readable */ .indextable code { white-space: inherit; /* break long lines */ } .indextable tr td + td { padding-left: 2em; /* indent 2nd & subsequent lines */ text-indent: -2em; } .rst-content dl:not(.docutils) dt { padding: 6px; display: table; } rocq-9.2.0/doc/sphinx/_static/notations.js000066400000000000000000000031701516144147600205600ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* sup") .attr("data-hint", function() { return annotateSup($(this).text()); }).addClass("hint--top hint--rounded"); $(".repeat-wrapper > sub") .attr("data-hint", function() { return annotateSub($(this).text()); }).addClass("hint--bottom hint--rounded"); //.text(function(i, text) { return translatePunctuation(text); }); } $(annotateNotations); rocq-9.2.0/doc/sphinx/_static/pre-text.css000066400000000000000000000017671516144147600205000ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* Σήν4r%»šζ] ‘‘›FLτQΦnXΝ²΄ϋπ±ΏνdK‹9ܟ)νκα 28Kq„§Ϊ‘Ϊκδ–|½%I’tƒάΤt2cⰘ²0:Ψaη녍»λ-Χ•“”LFΤƒn©ŽΔϋΛ΄ΗMnΊNΛΞA;Ε£‘Ψtβ0ΩώžX»U χJ ΖΨΛ΄―Ϋ€ίŽΔP3ΈΤd ς­† 4 3 Όι , ‰a y―Š/ƒ@‚—Mόm΄•sΆ$ιΆι˜ žb'ΘLŒΰΠe3Ξ^Υ¨[³-γC‚°ύθXTqh??άοw#ηD™IΉΨ4i«G6YαdΔ₯`ΙΦQl° ΑΉZTE#;.―ζžΨ*`>Ά‚ž³6sΕΪ Χvυ°ΥH9u³²€H'ν―}·Ρn‘²f_\›8‘sς<Ω©Ήkl«Υΐ₯zΤ«/]Λ$λμ9L±Ι˜³-`΄ΓΚ3—ώX©ωλKj ΉηΟ’™Hn¦ŒΦ]±»―:Žς±5’Tž².\Β5#‡χžxŽf!5Ψ{ξ ŸlXΛετ μ}Λ\WN|"6 ),ξ?]θŒωj!i99Ψx{”©ΌYΧ83ua‰ΫΤ7ΈΔœ''9…uςn>τkύ}L'=ΔΟώβ– Kˆ—šlH<΅§[‰ν)τh•~kΞ:8p8WΗ¨xΒΡ€—!/©2( u~KKΗθ$‡%ιφθhβΪοχ,’ο†84Νƒ—ίψ„WƒιζƜίRxe*†Ωnbΐτ£΄κχ½k:³ω‹—xυO:uθΟΠ!‘Τ¬bEΦ•HΆlω†)ϋ.ν•OΑΜh„0ΦΖΑEC‰Ϋτ΄έMVF<\\ΩX̍ΘΪ‘ΖΛn΅έλΚΪoeΔgηxxΨh vŐΝ–?–ρφαDD}WTK*ϋ’hχP^TŸ:nφ•ΐΙ“Ώρξ†3DΧv {Νγlμ~:œΰͺέL3z: d§}„ο·όΙW—έ±u—Ι–$•sZ.ιΩόπΚΫΈΨ_;χw¬ί˜ζΥkeΖ{d€¦•)/ΘMLΖ6ώ K‡ΎJmί–y…Ύ_LΗ€€΅Gι=[QϊσΦ-B”œσΈ8ςΛΡύτoσΥ½|Y>d,Ο}> Ee/½Fˆ— ωεθ~D­ͺ₯ζOΦτh•}ΌΐJQρ³·&ΤΪP΄2ƒ¬Œ4¬―Ο”$©¬ χhε:B±Ζ6w3[,θy»-j•VΜx£Ξj2g’ŽrτŠ>3‘9χ»BvΗ"Σ©β_“½'bœH―fΌkUΑœ•ƒp΄C€E³ϋB —“,œΔΓΟ~tσ²§Aɏν–Ϋ-\ΦΉ 3^m‹))’πxkΒόBxΌη/Œeβ₯Ϊcbhί{ ³›Ή’š―p2*Υ-ΆY\ΜΡΘ:M»žSnήΦαp°λΔά>ν PLœzΖ,ΊVrΞ£*dϋΉΣsήΗ¬ϊ*΅ύωaΜD|\\9Γ³_L'Ϋίƒͺ@)Η“‚D+· =Z ΠΡΞH=+† ―֟KJE³±*S]’$GηΪή£βΫ|+BtΌόͺQέΩ€Θ:ΑΊƒΙθ†όxΕ« +ι:{#'­¬18΄gMSWTΛi&Ώ. β5¬{ρΓΫ½ {πanέΘ?›¦’`žΜ†nΑhgΧ1pΑ²\PΪ0€Δ²?±_­r›ν.kEΦΡ9<Ί`‰Β›—ίϊ„Χͺ:Σ0ΔΔb1Άap“*ΔEΟzƒχ/(‹†ƒ{ ζ zTλ’γάό-‡jΨγ €H?ΖΌ³ω6IΓΞΙ‡ΐj¨ήŠyϋωλ«—±ηνι΄©JNz:V₯μsY1q,0†Ϊ~œŒ‹‘Ž_ @ΑοŸχN―%³°s.Ήgμκ|s³γtƒ"λw.XWκ1ΐɞT_Wz}>•u#ίΰ>o?Ξ&\€ΧηS1ω»ct²G+γ±€ΜC‡#]lιδPtךSQt©„ͺςkμeτͺ₯ή½(IΝθ\λωV°χΈ–ξ:ΉYɜ<Ί―~όž―έιWηXΨ³}3'ƒ ZG‘‚©iPP”ΪLœς  WνβE9μuΉn⦋/8¦ Έ”‘lAl·Ρn‘²‡&ιΎΊ(WNpζ’QΥ k+#"'Υ?ˆϋT=ν›’ e5TU'KSΰΚ9 Ύ₯΄₯Ψ{α7ζkΘ›υξη“Ισyρθ_,ύu«ΣrΡΌ¬A~›«$• MΏΆ3™5-―GIδύ^x›r ‹ΩBVn{#Γιχε,NNž@y±βΕ1dζζ`±XJ­GzΑίΧo[Ίb_[n.6F#vΦ׎™vVΦ؍€ζζ"ʜλ(y‰–₯ w~˜Žuf{Έ|M™9ΉΜ;x†..„€2Œ‘J’T½P ±q"֜Εb΄η*ˆjAΰ”ƒ•Ώ‰dη˜ΖΌy†όύRδ&r4β"ι…wEνIΞΆθΒT΄I!ΚVΦΙ‘~›ν^WΦ”™ƒnP(EΤQθf4]dε@™^£#z |ωε«l nCφθΥ  †΅αα%o1$Έζ#ηhIRyφ6l;s‚NυσI―ώŒύv1 ?3€mα'φΆ₯ζJUz/ω4―Ξμœ‚ε—ΣSιτωG (XUυ-΅-?Π„ΈaΫ’Φ]Ο’”‚OJ6λF½…Ώ«;§/ΕPΛǟu/ΏΙ³'sIΧ1ΊW)±ž<†²χhΕ*09ΣΜ•d½άΩzφ_₯g2ϋ@8oOk+Ω›%IwDΏvη]>T‹άjφ…6Ρ1\·kXm1DG΅’‘’Μί~Μ§±„Š0ΰββJRMoΔ₯s7΄iΆ+CΩ(ΗΕν΅{“²Χκ„Α νςEbΤq ₯}ΰWό³ο$BΣρς­F†£9q₯΄UΝΕ¬S3gΟlβγ²ΎΗ'¬νΐƒMkγΈ2ŠD―’ο’$©ŒΌάxgύΧ΄¬^“Gλ7ζxύΖ«R23xgύ*πv+=Ηp°Γš7+{ﱂΕ]Η6ΉNιΟϋΌš@Yt½`¨°ΈmJŒΗ’ᘐΒ7£&θζΑιK±<1g2 ?Όό&΅|όωζ₯Χθόι˜œμΑxύωzω‰V™ϋ …δό+ΚCιYΔϋx\Κ~,IΊsΕνGeΩ·„;9ΪίΜΫυ(σ[Υ`μ[sy<κIΒoοl|LλΝ™dYέfΩM©δrγσbξ¨μυ ¬œΙIΫΞͺΣ]x―Ž?ΗΞ€EΤ%ΜNΤΤδ©O6qΨΆ”Ά6œΗ2˜3p%ξ1&Ώ  B#ζβ%Lφ6ςX%IεD©βD„)Φ½Ι”}y¨v=„όuζ8o―šh+ΡΕρΦφ9[k6<‚λ`wkϋλΥmSζ~]β6%Υ©%§Ρ5¬)΅|ό9})–s&sΕ3oώs>δΗόdλρ°&|wCξ†4–ύ%€ŸΡΐ€*y_&έ!Π“υI&»Φ%IRE3’Χρβ—οίcP|O†Άl@X΅:TΧ³Έ{ˆοO¦cqu€ŒΫ-kiε]φ:Š5Z]ΑEBΧ§ιΧ¨&΅ξ«ENz,;:Ν%wgτ CΙmΉ9‘§γ׈` ͺNsAfJ4ύσ3S6₯‘UΗηŽήeI’Š2ϊ{Ÿf’ί· Yy.Wμl1ψx`¬βtΛυYUυη©Ε3QP° ς»ες.#Ÿ»ε2…©Ξ¬;Ό€ο#ΥΫƒk^’•t™ύ]ÚςΓ‘½¨ΥΚφŒ0₯Ε’©βœ’[¦kY˜do B'1#‹—γSΛ”ΝI’TV:ꉣX]ˆ šE‡ ―™χΑ© Χ ΓμYθ!Α"5ζ"†ψtΤl  "œΠ«ϊcq·ΚωΣXGeG09‘e/{'ν[V ž:ŠUΌ^τ΅šM"/bH2‘˜XΩ’ϋϊc vΚ»-­­ŒDŒgP3rQ4ΐΖέΓ K57Di½ό’$ύη‰œ\tSŠ-κuIzV"+ΥΑΕ¦τωž!ΒϊΦ-=Νωγ ͺ“=δ‘K’$I’$ιz!ΒϊΦ†!―[M’$I’$I*έυ79I’$I’$IεD&Z’$I’$IΔΩkμݎC’$I’$ι_ε‘οζΚ-I’$I’€ŠRd2ΌΡJζ]’t'ΆnΩJλΦmοv’$IR%!3+I’$I’€ "-I’$I’€ "-I’$I’€ rΛ,-o_.ZΘoΏύŠΩl&ΡΏo™Κ覣(*=žzŠWΗΎZΑJ’$I’$ݞ»žhmάΈ‡~UU±«}™ΚDyδλΡMKή 5θ;kiώ—· z“O γxΏ³J…Ζ,I’$•‡»žhi Ί‘ͺy§ //―ΆQ;£¨ͺ‚λhšv‡­gπϋ€^|Ό³θ °Jη)|;Άύη.Ο;Αέi3’„JpοYLν]5ΥΚΆL; b0δύ"28r(K“Š‹R’$I*_w?Ρ4tMGUςN? %nˆͺͺθBΗb) H₯Ϊ3Ÿ2γ™ΰO€WOp’tΗTk;ΉώS₯'νaω¬ωl8’ލθΪλΎk·kgX2μuβ,€Ν±ΜΪ™JΎ§ylŽ‘Z0«W Jf8|Ζwœ!YΈR½eO† νFG%―όΘy؍θ‡ωΫ9¬?ͺπΨ‡ \·π/H>ΈŠΟVnβΔωK€Ό λ<œΧϊ5ΕU?Γ’‘³1τλNϊΪ%όžŠ]Υxfδ(ž¨ι€’•²YgωuΑ"S4|κΠnΰxF΄υ–C=D<ΏΜ˜Β―Κ3Lϊ’#~Ω§ψα³œξ£]‘ Ήθ»<{~4ϊŒw:Έa°ΆGΙό={+Ί2nζ$B ΨΊπcޝfΗάwΕ@eΓμ•4ι=ΟΗϊΰθtύn―`οθKύξcι[Λ›ψ_˜φώV7[ĐZ€Εϊ₯»0zKΌ³9ώέΗLϋΰ ό>K3ΫRΦΫ§²sή;|›ϋ 潍gϊ^M™Βtχy|π˜7Jimί»†Θ’bdν‚ντ3…/ƒΞύψ “g/§ΑβWhj•ΜΆ9o³,₯3γ¦M XMδ\²3žJi1J’$έΎ―Χʚ<έn’ i4‹†’(δδδ ͺ†λ~Τ"?yΫ¨θzyυhέ"‘ΚŽ9“Xez„·ζΕ{a·ιC¦ώ,'Ώaϊ:3ίYΘͺ ˜<€= \εΑϊ?O#κ»WθΥσIzτ|’={1ykβςΆχ€σΐž„ωΈβά’η{·ΐα†ς F;;¬ k°³RWΆ³q ~–&nΈϊ†ρδK½ :όΖθyEE&Ζ¦ƒήΎ^.ΨsyeSγažhJ§ή‘hœBLl"}@ϋΎt©λƒ«{0­_θOkΛ?l9’SPώfλEςv~ήεKΑSΗۏϋΪΣη1_ŽmέM’(CΫΕΔ^r¬/Π½?~4ξΡ™ΠΜsœ»¬#’Ά±a·3]‡>GΣ@<όkΣΌž†2Δ(I’t»J:μί―?ΐM{Άξ$Ι‚Ό­«=S}ϋχ)X ‘ ωΏ BL†Ώσ9Z‘ίŒ¦ϋΪ«©-ΖδΝΦΕo-’·ργ_z~Ω•Ίž ψt o§yiΛ.’:u£Š¦‘)F\έqσ΄ΒΝ3 b”ξ}*'ςώ“AW76.hg/o ¦zΐ΅ώTkͺψΛT«v1†85˜'ό―]3)nΥ¨ζΗωX ό¬¨^»Φ7­ΕBΒΎΥ,[³•c1Idδ˜1g›©H~’†_οkWeΆΑ„ψζςO|J~rsσυ§σΔdηψ°ξ,Ν_-,9X|›’¦ƒ‡‘΄Ά―½΄νψωΔ’ΨΪb‹‹΄δ Δ‚ιζ_tπV‹+9ΖS;.υA’$©°Βίy[¦9ZύϋυΗΖΪ†…_.Όaω$Y7GKΣσ¦ΊuλP0Ρ]³hyk4]ΗdΚ"=5”΄TtMΗb)‘C•€o3Ή{`Α-Ϋ*7Ώ^»wP>φb7η/–,~ΝHΥΑ#΄7Γ۾ˌ!/πΫCέθέλqξ΄—=Zy FGwΌΌ½‹ Q[„TΤΒU½aWIς.EnlοZ•j‰_―G―eςδqκ5œΧ_ ΑΝ6…?>šΐ©ΒۈΒ-θˆλΌιz!ΐΊCf i‘v£n†²΄]4φ²lo0άδ΅ ύ&ΛKŽ1D~IΈ$I·`ϋφ’gež Μ3Ο$[ε‘dX,yC‡žžž<Πκμ±±ΆΑΪΚ³9³ΩLfV&+V,'2*’j!!€¦€”»3 Vξxϋψ\7GλfΫ „Ms†Ν½ξ l刻ΐ“V#ζ¨Ϋ^~Yύ3†HγΧfρϊƒ2Ω’n`πςΕΛrœ¨K:-σ->Ž„b?*ͺ BΏ–0όͺ¨$"F£UυΌO°HŠ "Ν—¦eKΧ2Ïεў©O·‘¦°€“k*œ”Xˆ‹‰C§ZήΕHV$gγlπρ­‚Bj‰λΎψŠƒ\ΞrΗ;ΰΖΓMF©mίj¬7gπφΗΫς‘q:_KΖ ₯Δ(I’t'n鞚gžy†~ύϊό”‡Β=Z¦ ͺKρ±Œ=šaΓ_"ϊΒy"’ΒΡ4τŒ UAU:–r™ k Ύψι±ΔgyΰγγSπγνξX(kU°hΞS―Μ`f_7ΆoΨΙ9Χγ?N ηfa2eaΚ Γd"3WCρjΙƒ΅γψyρOHαJΜ^V}»”βͺPœπt7Ήw;IWHJΛEqmK·6YlXψ5ϋ.\!ωβQΦΝ_MthΪ”mχΆuχΔ1ω8{N\")ώ /_Ζ_WŠΖύΫ2~8v‘δ€sό΅x9;mΪΠ.Μ¦ΤυŠ{Ί4Oη§y ψ;β2©i—‰>Ί…?]F”©ν[υζΟΦ<Ϊ8‰Ÿ~ΛΑΨdR“Ξsxί)RάJŽQ’$ιNάςεΫΥ9[ε₯p–)Γ„[[;DώΨC9—άά\t‘“‘‘ͺ((Š‚ιεΤ£ukΆtmρ3gAυ1½iδ ©ηrJ«O‡Fžθηώ⧘*„Υ ΒΝp™#αIΨΊ»c/»³ώγt’ΎC―οώϋΪK»Œ}ƒΛŸΞηνΑ_‚gΊzΆη·S‡=͞@Γi_ρΪ€₯Tο)SŸͺΚύΓ?`π’y|6φ[,ΞT»Ώ;οΌο2~ζŒaΟ2ς±Oψβ½A|£xΣΈϋ†wJdCA¨Ξ΄ξڐ³ ^ai” ϋΰV œ8˜Ζvδυό–΄Wڎώ€ΜΕ Y>qΣΑΑ· ¬_ΆΆo5Φ’(ž΄σ.iση3cτ ’Μφψ·ΖMj—£$IPZ,™*6υ Pβ<ŽŠR/4”ΦmZa0qrvdθΠ!((Lœ8 €a#^BΣ,ψzϋσΑ i!!!\Ίt‰ΛΎ"+;λZΟΰχIΟ°¦Ζl>οRΒγΞy2ΌΘ η—… X½ν8qιΰθW‡φ/Nΰ₯VθλxογUŒN&ΧθJΥƝ<ͺΝ<δyώ ΆnΩZdδ=/9^ Ύγυ–Ε|+Biλ%I’ώcΆo»ΰ<πΘwsοώKgΚɸqγhΤΈ!ͺͺ`PU +ή}χ²²³ΘΚΞΖΙΡ…ΌaF{{{lllΘΙΞΑpΗu€γύLΗβVj1hρω(ό;(φ5θΉuω•!0 Œ9β©$ݞΒW7’$IΛ]O΄Ϊ>Ψ–³eΪvεŠ F’$I’$©œTŠDK’€JΚP“ ΦέώzI’€89C[’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚ά3ΟΡΪ±c»χμ@’άόΫrŸκΡ‹  ͺΓΘ$©|DFF²eΛf22LeΪήΙΙ‘‡nGpppΕ&I’$έΆ{&ΡΪ½gγ_›@NN666Λ5Mΐl6ceeΕτ™ŸΘdKΊ'?~Œ§žκQβ…DaBΆmΫ.-I’€JμžI΄2™LμΞ‘Z.!ςœ;ΑΕ„Xš7kΙ«―Œ—Ι–tO²³³Γέέkkλ2mŸ››‹]GUΑ΄p–yŸ+ύ2¦©νݎζβχΌ6|/νH§*eK€%I’ »ηζh !8ύ‹Ί]P-€ΙΙΙ8Ψ;ŸΟσ}ϊ³φϋΥw'@-œ₯Γϊ0cOφέi_Ίg)ŠRζ$ ΐΪΪΊ˜ή― ώ|· vκΐ£:ςXΧτ~q .ΫBT–(ί€Λƒ‘}g-et%L²$I’ΚΓ=Χ£%τΌ“Ef£Տκb€£ƒ3ί―_Mff&&SΩζΈ@ΏOκΕΗ;sAQ0ΪUΑ―Ζύ<>`0=κUαΆ_ 5θ?w9 ·S:Ÿΰς˜eϏ»έ^˜JpοYLν]rΈΎ›ŸWΞζΥƒ˜όQ_jW²œFΉ£}E’$©r»ηz΄t‘ό^£Ω("ώD:5¦jP5„5ⱎ]n‘F•jΟ|ΚΊuίσυηοσ|HΛ'Mε·ΔΫΏϊW †;KŽDGžΑ|'uHχœ²ΞΝ*½Œ‚jm‡ƒƒ#Ξn~ΤΌΏ;―Ly“Ά©ί1ηtύ<«F=ΑΈΈφ)ΟaΟΜ§yfϊ.²΄3,φ2ΛwώΙΌΧϋρT·.<υβ,Ϊ“”Ώ½ ωΰΧL~u}zv‘λΣykΩ>’_vΩφ_™υΚs<Ω­}_ΝΦΨ‹μ^ς/>ύ8]{φη­I½Ίύξ|΄3οΣ.Lαlœσ*Ÿ~œO=͐~γβΥ]^\aγ[Oπςw1δ-8³d {ΌΛζτόW’΅)½²θ΄†Θ gΓ¬Wθί« Oτ|žW¦―ηdFώvΪ– Ν7Ηφ³b <υδž° 'νa送τκφ8½†LbΕΡτ’·ΗΙ“Ε΄c.εύΙς›˜χΪσ<Ω­+ώšΒgLTΒώHI’ΚΰžK΄ ‘“•ό 5š"κΟͺΨΩΪαι鉍 UͺTΉ…Tk{qχ―Λ#CςΥavΛν4‹ΏΜΧGχ±lB?ΊuιΟΗ-ˆΜ3ό<}4}Ίw’σ“}υΙ:N\=ΐj§Y4°ώ“βΘ<Λ†£ισdgΊτz‘IΛχ‘t-WD˜ΒωyΦXϊυθL§'z3hςχό4mΣIe¬^΄o(#ΎΉz@—€Ϋ£86¦ΛCޜۡ—ΛJ ­[ΎcΧΉ'Ψ}P§ρaΨh‘¬]°Ÿη¦πε…ΌΩ&› ³—³?@ΑήΡ—ϊέΗ2εσ|9ιr7ΜaυIK^]Z$λ–’ΦK3Y²p2]ι—)] IDAT¬·2λΥq¬ΆtfgΛω|\s’Φ~ΖϊsZΡ E2ΫζΌΝ²Ψ† ŸΆ”%³ίγΕΗλγyυ(₯T‘n¨?Nœ"Cz,gγj’'r°œ;Ξic]κ§±mφ$V$4eΤΜ,›3žΆ¦ΥΌ;νw._}Νz,f―$ιΑ |Ύd}j$ρˌ)ό*e+ψόΝΘψ™SΧ…ykqnl§¦U)ο_λ—ξ&hΰ4–,žΓˆ:Ρ,ωΰ φ•΅£^’€JεžM΄:B2―l€F³QœίŒ›«;~Ύώέ~ŠŠͺ*¨j~OΛΟ3Vτπ[,\9›Ύ5ΣωkζD–Ζ7γ•Ω+YωΩx4}Η€O~»v/6•s&±Κτo͊₯φΒnΣ‡Lύ5>οκT$σχ¬‰,‰mΘΛ³–³βσχ΅9FΌΗσ΅mi0l)λΧΟ΄§ξ½(ι–•_Vq ψψΒεK$h*ώ­ΪP5|{δ}h-gv²ίά„V μσ·ψwxξ όquυ£qΞ„fžγάεΌ”ί¦ΖΓ<Ρ:” O7ΌC;Π*8…˜Ψ¬‚―ΐφ}x΄–7^υθΪ>] ₯ϋσ­¨κξF@³.<˜ΐω˜ά"Š€mlΨνLΧ‘ΟΡ4ΠΪ4―ηWh~ƒJ@½PΟη¬DA$Φ§σC;x :ρ'OV3ŒšιΫΩΈΗ…Η?K“7\}Γxς₯ήώ?cς/[D&Ζ¦ƒήΎ^.Ψ%ο`ΛqO:μI˜+Α-yΎw nx/ΛG-«Ϋ±7–φώA@ϋΎt©λƒ«{0­_θOkΛ?l9’SΖkI’*“{ξό-τΌƒ€ABlb‘dλNθ™ΩΏκ+ώ֚Σ&,"cσΑŒμ˜0NέΖ†]Uxβ₯ηhθŽ›_zŒxšͺΧσ{tΡ~'‘Όwψσ₯ΤυqΕ³Fϊvςεθ–]$ ‰σΣNΊ λC³ <όλpXΆvφX 68::`g%giIwJ k:Υ·5mͺžbΗήd{φ‘Ω°ζYρς-8@(ΆΆΨbΑb°°oSίJ>=yͺΧ`Ÿ0£λzAY?―‚²Φ66¨n>x_η―Ψ`m ‹Vd8L»t8C0!ώ7Ÿ³eΌ/ŒΪζSœŒ΅vdQ!θΨ,qτη-™œ>CPύzΨ_Š!N &ΔΪ!Nq«F5η8ΞΗ^ν’²’zν\ KKΈHΌ1˜κΧΪ·φ―ŠO1α”5'εΖvJ ψψz_;8Ϋβ›K||Š>”€{Π=7^Ώ:tˆ†‚άά\.DΖ@^²Ύ9Ύ·2»I#ς›Ρt_£““­αX½-Ο½χ2VQ@°’zέBγΈβ Α<PτβΗω ͺωΒyb²sμΕn,Ξ_&,9Xόš‘ͺC•‹y'–ξr2°TΡ=ZΞ_ο–xŏV­ƒYυΟnRΪΧbχΎ4=ט‚< ƒ‘ψλ0=z-“'ˆS―αΌώRnΆ)όρΡN•TVUKŸ·(Κ0@nW‡°j—Ψuκ2ΑGNΤx$ξ5¨›Ό†CλQ…Πή^¨ςώr=₯P*F«Bq ¨¨…UUŠέ;Λ7΄Sϊϋwν8—/„Μ°$ιžuΟ%ZW ]Ώ6ŒE’­+¬€χΛX“J@Χ·™ά#;Η*Tq°Ίξ„ be,z’˜ΈPΈρL"6Ν6wM­-U¬q7θΩY%ύˆ+ΫX·5…ΊΟ6ΓUPπy -ΑίξfD4€Η΅ξ¬e†#Κ£=SŸnCM`I'Χtη³ ήώx[~#2Nηΰ›tΆ+n„†z³κψo8γE“gζσœ‹½ώ$₯ (Χ†I%ιΦτά,L¦tR’8Ίu%Ό>“ΓUϋ3΄£wΑg\ρnE›ΰΣό½z/—κ·’±}ΩNγΆξž8&gΟ‰K$şαοεΛψλʝG­xΆζΡΖIό΄π[Ζ&“štžΓϋNεݍWΐ@`ύΊ¨‡~g·‘!MόUPœ kX•ˆ?6W#ŒΪΦ ΈΆ₯[›,6,όš}|ρ(λζ―&:΄ νŠ?μ)^-y°v?/ώγ )\‰ΩΛͺo·‘RμΦe‹£8₯Ώ‚θί–ρΓ±‹$'γ―ΕΛΩiΣ†va6ΕW(IR₯vΟ&ZΊn!!: Ξ8xv#ζτqμ={aλϊgχΝ‘F³Qμ]UΆ+τ[‘Έ>HχΆYό4+φΖ\!9ξk?ϋŽσυΊΠ.°θΫ©x΄₯k‹ ~œύ[Ο^&5υ2ΡG6σϋΑΛ@ρjC§&‰ό0Δ&“’xžC{N‘Œ3žF"wo#"ι IiΉΕ#ύ«8;;c6—}Ψ;77gg—bΦθD}7†^½ž’ϐ±|²ϊNNbΞ{=¨Vψδ―xρ@+νŒ τ¦8”±»Δφ,#3πη{ƒθ?ς#ώ΄νΙπNΎw~0Q<;πUζn‰εϊOΏU0j™’ A3B  β’’Š½ΠΌyQŠχ€ΑAGψll?ϊŽ˜ΒΫξΌ3Ύ3ή7{Š/]ΖΎA»άx{pΏ·νρhλT|2ΕQŒRί?Ε™Φ]rvΑ+Ό0`4σΟTcΰΔΑ4ΎΗΏ@’ώ«”K¦ŠM½G―PΙ̜5ρ―M 66–σ›A1δͩȟ£RδΛ¦ΛAΠμΩΜ›ΤšΑο“žaMΩ|ή/δΖΉΪi Oό 5ΌΩͺΠΨ_NΏ/˜ΓΚΝ'IМ iΡƒa#zQίEΉ‘ŒΘ η—… X½ν8qιΰθW‡φ/Nΰ₯V(€H;ΖΪyσω~ΧYΝφ΄Ξ‡―·Η5ς>ωψ+vGgS}ΐfφzοfΕ![·l₯uλΆE–mίώχ ˊ'ˆˆˆΐdΊΩη΅({ͺW―N1cΦe¦YΔΠ·bxnΡ;΄s–Swv†%Γ^'aΐwΌήͺτν%Iͺt σωnξ½7GΛίίŸ>f ₯τ’ιΝΊ_€»BΞ}—€{&Ρ β“iSniϋ»C  …ΫΈLϊΣ4Mϋ_<+ΙBVΊ‰τθίYΈΑDΫq-‘Y’$IγžI΄zφμ}·C(…Ffj*Yρ‡8™μN=O9Π'URZ4ίOΕΧέhψΤkτo 'H’$U”{&ΡͺτD;g δ“]ͺ=:šχΙgcI•”!„>s¦ΟݎCΊ‘‘&¬»ΫQH’TŽd’U^yg=άν8$I’$Iͺ4δψ–$I’$IR‘‰–$I’$IR)2t8L9x·β€…§οv’$IR₯R$Ρϊω«Mw+IϊWxΪ·ιέA’$IͺDδΠ‘$I’$IR‘wJR%{ρ"›ο#%;«LΫ»ΨΪΎA3ό}}+82I’$ιvUŠD+,G₯]¦ŠjΆάt›l+Ύu0“T)"–€ς·ιπ>kD2mζ\›oΧ ŽL’$IΊ]•"myΨ€πbίπpχΌφΕΠΧωγ?πŒŒΰ[ν §mβΎHW’*£”μ,ΌάέΘΙΝ.Σφήξeξύ Ύ°8~ΐwΌρΏϊΒβΒm6bω˜χΉ!cšΪώoΪ―wγ}”$ιžU)-ƒEΓΓέ“Μ,šfA‘λy ]Χ±··γζ-pόn>ΆKWνfΓ§£‡kmύΏ Τ’—ƒβοŽͺšΡ/^AΈza°“IŸT>2LXΫάό3ΑάΉŸ3}ϊ'ddd³… γτO,X΄–§Θ48βFη!γxͺFΕΕ]&†τ΅JωBxI’€“J3ώjO–’¨¨Š‚’ζ­¨¨ͺΚ•δ+ΈšγqZ΅VΓ_‘Ήk0Ο­ωφ[ΥΡβ°DΕϊ‰Γ’TόϋͺŽ-X?vΟΩjγNdZυό“bzZΊv‡ρHu’„?η"τβP<Θ’%KˆΛ›vπΩϋΛΈX$3–|Ν’OίγΕGκαWεxARΕ`ψΧτE[^‡$I«Rτh]₯( gΟFx9ρ†u1§Ά£Ÿ2ώΑΐ˜μbN’T6ΊΘϋΩρΟhυ@ΑςΘΘ( BΰνλCΗΠ‹ω ιΟžY‡^O6%ΠI7WΌλζ­ΤΕρ[˜7~›N]AυͺO§!γΨά™αl\πίύs†dαJυ–=2΄u’Ω8ρ~i0O{’’qfΙ`ΖόΔkΛή‘“Yۘ ^·A΅Šι΅*2ŒΙ’‘s0τλFϊϊεl>•žυι\8–¬³όΊ`«Ά…“jνG£.CυlάΏ<ΤΞ”\—eӟŸύΔ₯ «—·―‹”_˜8πwš~6ƒξžα,9΅O’Χ.gλ9Nχ=Β ±½°ϋ}. =LΌζNX·1ŒΎ.ŠββŸ|:v["±«ΪŠgFΎΜ5J];Γ’‘σ°Ρσ·sXTα±2Έn₯:K’TN*M€ͺ¨ΤͺU“Z΅€EΛϋΉΏEsšέί”jή9IΛfM©V=ŽΜδ=ΔΔEσ͐'Λ‘USVΆf‘kζΊf.­χGη%YZ6z|<–σqXb“Πs Ω„Λ…XΜ™"1ƒϋύ°ΚHΐ‡–š?©_7£'&b‰ŽΓ–hΚΛΛςΛλq—Ρ³sςۈ/ZΏτί$+W¬dΒxσ·Bp.2’Αƒ#ς“¬™Σ¦βΖΟ‹κLΥ)ώΪIVq'‘ΕwΰσόΗ,ZΆ m²Ω0{9ϋs‘ΜΆΩ“X‘Π”Q3W°lΞxښVσξ΄ίΉLκ†ϊsαΔ)2 Ηrΰp6φ'9p"ΛΉγœ6Φ₯~΅2 j‘¬]°Ÿη¦πε…ΌY$–TvΞ{‡oMν˜0o‹ήο‰έζ)L=Ύψ ™’κ*c,λ–’ΦK3Y²p2]¬·2λΥq¬ΆtfgΛω|\s’Φ~Ζϊsω½ΦΒΔ΍yqKΟeTX,Λ&Α>ScΧcΩ0{%INΰσ%³θSS&Y’τoU©-EU9s&œμdΧΞέμή΅‡mΏαψ―Σiή€ ξΉ'9ut7αΥ²ˆΦ‡} ΚγαMΛ%=7‡΄όŸ M4”loΖwγ?ζЁŒu3R08¨ψςΖΐ˜WΥ™N]^az-μτ>qoNcc / θnGŸvΓΩ=φ"ΗNδΗφ h˜ž™w°U|y£0FΪω0ΆηN›ΐΫώrξʝTƒ;ώωg;―½6Ž!ƒ†$Y3¦MΓΫίMΧ‹M8ηΆ Υ†δ•#0z2Λώ cA’εγ烦iΫήΘ€wλΡΜ©ί™~ϋ™ŸVŒgύχ/Σ² €@ί‚+,ΕΦ[,XΜ %Η§σ„΅λ/Ε­՜γ8«alFmσלŒ΅P=bQ!­ΧΜ‘ίΰΌ₯ηOΔTΏNežΌdΔ?θf±œ'&ϋ8Η‡ugιΥχΖ’ƒΕ·)i:xάpMrσΊΚ‹ŸWAykT7Ό―NmSl°Ά‹EΛOpψψy_»R΅ €ͺo.Ϋ/₯`q,%φΌT―]ƒΚ1sN’€ŠT©-EU9uμ8 d'Gb‰ψžΝšβ‘…sθΠ~φM¦Σ«Ώβ ”W’e φ£8qΥ³–ΖΦ½‹['XωΗ>veθ@3Ÿ‘ηƒΧ•˜-ΉdλMΛλ€jU‹>ΥM¬ψc7§ ΐΔβύ»θΠ₯%=Ÿgn.€ – Ϋyϋά%ŠŸ~/ύΧθ²sΝ 1‚Σ§OsβΤ) 3¦MΓΛΧ³¦Ωφf .5hΫϋΪt}œ―ί|•ωkΪΡμEk@Ε`ΌyGΆ(vн’7ρΫaΥ.±λΤe‚œ&¨ρHάk:Q7y ‡.Φ#.’ ‘½½n‘›\Ε`ΈΙΦB€u3†ΜAΣB=dŠΡ·b;~K¨«8š™’Oν+¦Όͺ–8αύϊχ© ρ--v-―=£U₯P$©‚TͺDKUTBλ…RW«ΓOŸL‘Εύ-ρμΫΏγ²θϊζf\ƒ(ίϋ}tΞ[Η€¨΄όaAAvN.ͺ£+z<ΗӝΨr.­_Ÿhέδ΅8{¬'°,ύΪαXΟJΰTΦƒΤtQα2€Ζ±Λρ2Ι’ ΙKu2s³™=goMœΘ]ΗΣΧ‹~ύ]­₯ΟιSμͺΡ¨+k“RΠρ*q[ƒ_UυƒDΔh΄ͺž—Νˆ€"|i`ōΠPoVgΌhςŒ'ͺ­-kΞδοΝϋI1ΧεωjεsH1ψβ+r9Λο€;­Σˆ•ΡLN‘Νr!šΈ;ΊIΨΒ؋θη%–ΉΡD]΄ΖΫ§ Ζr]’€{]₯Ί€R…ΗO°α›OqvqΕ[eΗέŠ2αΣaΙ&₯ά#δζfkJε‚)• ¦4- *ŠΠΠ _φš5Šv½rcξgTQA‘[5 ΓՍυ"=[š9y"ΩY|8y2š4Α’ιΛ―ώθΜEΣt-j?ώuπ˜x’Σ’ˆ>°–U›¨ί€6₯MR\Ϋ­M~ΝΎ WHΎx”uσWΪ…v*` °~]ΤCΏ³ΫА&ώ*(Ξ„5¬JΔ›‰«Fνr SάΫΠ₯y:?Ν[ΐί—IM»LτΡ-όqθς­ίΥk€zP»ώ™S—SIŠήΕW«ώ&ωw½θ?–ργρ‹$'G³sΕrΆ[΅βα0›ς]’€{^₯ΊάR…°°0VΟOu§Λ,;…½[Uzίzl<ΠυΌ˜–;!@/T―’’ggk¬EM=“ίu[‘‹bεL@±‰ž‚ ˜sσ’)EE3₯‘4 T1ρ«ΩEΡΐβJ¨] [3er%έHApδτΦͺ…Θ\JJJρΫ Α‘Σ§oΌR9°ϊ –_H$ΓbΔΩ·6-{½Ο φ(ϊ•Rpβώα0xΡ<>ϋ- gͺέߝw^ιŒwώ΅U0j™6rΊe3B yQ{4hˆΛ—'°ͺz σ³J‘Έvτd.^Θς‰Έ˜Ύuxd`ύΫ¨Λ“φC^βΔΜΌ1p!Fοϊtμ7€vqά~|Vυιχb#Ξ|ρ K’2°―ڊ~o₯©=@9Ζ.I=Oi±dͺΨΤ{$ΥVΟΈ+AŒM€ΧΗ½ @Nf*}{<@³°Zžϊ!3J )+z΄Ζ°ψωτΨy©ΰŽBaηDV^xΈ#LΏ1δ·}DΫT£ίc½αΗΔu?ςΩƒρ>MΐΟuΩHη–CψPόΚ3‘θθH’-νοοΛT›½ΌΌqΗuoztμΓhΫέtώλDας2ρϊ·XαΫ”Φ­ΫYΆ}ϋί7,+Ξ鈳,ή³•K–²}Ρ–Ν€Vυ»ύΘwI’$ιͺΒΗόGΎ›[Ήz΄ςΎώa/F{t]G‚ͺλT0‚(ώv«Ϋ ’Ϊ¨Τn9Š-―΅Ÿ±–f»£XΉ{#~ΝbΕΠΐΓ²ƒπ“[M`1’X©(6 Λζ“ΫΩΡ²λGtβΔα―ιu2‰?χ―crΓv|ψΒCψ+YœŒ;ΐ‹;rAJας’΅ͺίΗΗΥο»ΫaH’$Iε¨R$ZΊ•‘ΤΤT\\\°±―R°\UσF \»ΝHA•D4£n2cͺμrXσΧ,Φάl΅)‚·DπaαeŽζr‰žS°8;εΓ9T΄Ό%‘5ϋΎcΝΎbκEΛK’$I’τοS)­Νφ:,ωΥ\ΆΔI·2²ΕA·I’$I’TΉUŠD눍Ξ›[Iœξ΄'K’$I’$©βUͺΗ;H’$I’$ύ›ΘDK’$I’$©‚ΘDK’$I’$©‚ΘDK’$I’$©‚™ σάkw+IϊWΨΊeλέA’$IͺDd–$I’$IR©w$ b/^dΣα}€dg•i{[[Ϊ7h†Ώ―oG&I’$έ.™hIR%±ιπ>kD2mζ\›oΧ ŽL’$IΊ]•"ΡJKO#βάL¦ ₯δΡL!tœ ©³“σ(BIͺx)ΩYxΉ»‘“[Ά/•φφp/sοΧ ΄p–yŸ+ύ2¦©m)۞aΙ°Χ‰πo΄΄*y}σ¨ς«χΏΰvί;I’ξw=ΡJKOγLψIκ‡6ΐΡΑ E)ωK–…d˜9zό05kΤ‘Ι–τ―’aΚΐΪΖϊ¦λ#""˜;χs¦O„ŒŒŒβjΰΟwŸcmYΜνRθ[BΝμ™ρ,σήeΡΠz 5θ;k) ΕΤqΚ΅^AβOoς©aοwvγήόϊυ[x υ"I]uΧ'ß;NƒzptpBΧu4M+ρGΧσz΄ΤkΔΉsαw;|I*W’„?η"τβP<Θ’%Kˆ;jK1*$y)·zEG…ίΫ_Έu‹―‘’ώO$IΊ{ξzV†){{Μf3_―ZΙ‘Γ Φ}ςΡtΖΏρjΑ²† ρά³Οcoο@†©Έ+zIΊwι"οgΗ?;x ΥΛ##£ŸπΩk²5­Pύ"‹]?ξΐηωY΄l!Ϊd³aφrφηVP½fgξϊ.ΟΦ΄%lθbΦYΓΗO=`‰dΆΝy›e± >m)KfΏΗ‹ΧΗ³,G5=– ³W’τΰ>_2‹>5Ε/―abηΌwψΦԎ σV°θύžΨmžΒτίγ―υ'j‘¬]°Ÿη¦πε…Όy+―‘$7«7©₯Η%IR₯pΧ-!DΑ΅5ͺͺ2ρ XΫXY>ρ ¨ͺZdΉ(―Ιζ-‰T±Ϊϟ»ΣδJΊk  Ψ98πΟ?Ϋyν΅q 4δΩ»οπ(ͺΆΓΏΩΩτ›Άι$tz“!Hο*%τ& ’θ«ςΒkC€ƒDEŠ Hό‘.*Ho %@B)„4²eΎ?!=Hπά^{ɞ9sζ™Νξμ3ηœ™ΝN²f͜‰ΦΝƒΡXΔϋΤ@δϊρτκΩ•ξُ^ΜΨ“Rΰ:JόόvNC{αο¬ΑΑ;€A}°Ι™kΫAtσwE£q₯aχ |Σp%ΞXψΎ|7{ξ4ζΝ1|χΫ!ZwΐώΑρΠΖ‘sƒ{Ό~)»Βο`αΥ’~oΏMΧZVHΕ- ?œz IDAT”΄KμX<5ϋ/’dβJΓN#yηΝΖΨ«­aώΚί8q“dYK½Nc˜<¨ vΖ0–ŽœΕΈθΦΜeΣ)‰ /Ώ£χ½υEԟ‹<¨+w7­ΰ·σρHŽ~tύC›έnH½ΘφE¬ί8½5Ν3ύύφ8g£π΄( το&)ΙwΩ΄y39Š,«³“,gWg Cvέ‚©pϊi]=sœIι8ωέ8VPΫpσ:1rΊΊ>¬mβ扳|3G-5n.ΩνIζ昣G―+|_ΚͺݜνGΛ^tq{œΙγ&T«]ƒό—δ.7D_%*γ,gGucωύ2E½Kc’ΰπ`<oŠVx»†Δbβσι‘ά(2Ρ8` @±ΙΦγ&YiιiY_9“+€δδ;ΨΪVΚ·Μh4–žφXΫΜ-“3Ών#­ρ[΄ ΌΞ΅»8p«=]΅9Ξ< ‘lZϊ'C&Μb…s:gΦ~Ξ—Ÿ,Ζν»wij^ΜrΛ;ό1ο#ΦfφcκβOpΌϋ7!ΣΗW‹ψ,H‹„„₯΅ ώέίe`WLcvπεΗsYί4”‘΅γ ~ž΅ŠΖύ¦2Ωkδ+EΤ7D°aρ½ϋ‘UΰΚO_0mΦ κ―œ@ΣDφΟώΠ€ŽL™ύήr—γmq”Š‹QxZŒ ddκ=f aaaœ»pY–™5s&N.Ξθ Ζ\u &‘ΆΆΗI«ΝuΥae‹B²ζ‚26YΞΣέ­BV?bΦ]Vνf·_xoZ>]ž ι*Τ&m7OΉ’€i†ΟCγw ΤVΨΙ€!kY.‹3’"Ϊ-..AʍbΕ%QO’d€§g`0HHLΘχΘΤιΘΤι \f0HO/Ωύ†Šΰ8ΏΤΣό₯XΊπb΅‹μή{ƒΌ‡pWΠΙΧ;{o‡ ’•ώ »Oή+vΉ’x€­ΈΠsd'|œ58Φx…ώ\8½ηΟμ.~³šmθXOG;œύΪΰDΤυτ¬a% uΣaŒmχpˆ£Θϊ(ΈΏLϊnΨiάhΤ«#~†nοgΫαJtυM<pp«C37δΔ(<-YW¦ef0wή<š5kΖ΄O?ΑΡE‹ήhΘu"₯4Θ-k]Ρ’ˆŒyψ7܊¦ˆQΑ§Τ • cΑ+ΘZ7΄ϊ«DDη]ΖD­γήÏ'ϊλ׈6GKΉΓαίώβΞνtήλ΄ύA!Š”ΐξπΧ©ZϋαΛcΜ5NcD1’λͺΗΒ—+(fM5?OΏ‰5φ2―ώΘ΄O·`Σg Œ©†½Y";gLα|vM&9†VJR_]θ0†₯ΐ#pΡ1 O‡„Β©°pκΧͺ…rΝ•””Tp]EαTXXι\Ν"iι0~ ±³ρρ°eΰT ž―Rϋ\ψ3nΧ’&}‚©?s5ƒ—SmΰΎκQεα>KŽ΄}η’/fΦΫ«ˆΧYβ0ŠιjΣvψHΞ}³Š)ƒCPkύh7 ˜6Ρ»c4Ύ=΄e!¬ό0˜˜»`εR‡—ϋ•Ξ><'ŽK„§ε‘z™ϋφνΛ½Μ¬3θH² «G ΜΜΜ155EQŒ <’ί/ΓΜ,λg(LMMψζ`ň©©iVΉΔχh)ρΩuBCǏfΣΥσώ‘OΉΛσ¦²cχYΥGVή‘'ϊZ4FΌ³ιWΈxΓ  wŠ\vρΐΥxŒΨtœ=ςΏά)αgˆp|…Y―RKτwΙL-|˜!νλη$kέpΦνδΚ #-½κεbbžŽž _`Ωί{ω!ςL‰κ;«ΝάτΕ<₯Φ΄ύd+mσΥ6‘ι„iϊΰ©\“ΰ%{‰UΝ<½ƒο?Wb71ρώ°WήΊYΝ2uSΰύ'9——f»`ζέ™t.τ5l}ι1y=ς.π bœ &ε, μP`ŒΩ А,kΠaμ—t[@OΊra―]ρν— εΖ#«>˜ _Z230Œ¨Υ&ψΤ©ΛΊ kξ'TfΩ^»ώ{|κΤE­6A―Χ‘ρDs΄nξΫΕ9χWP /ΥΓrϋΞMΨΈψ7N ©G“¬²«ΚOυGΡΪ%S«Wπ‡y+>©g–½NaΛ%‹@:5_Ν7sΏ₯Ϊ;½iΰwžζ‚ΑW8bξΰˆMΒώ:{§;œΩΆœ½ρΰQHԏZ?'Ι©­fΙβuψŽλ@U³d"―€S₯qΡ1Šaˆ§£V΅κ|Q­ϊ³€Μ¨HbL+£1/έΏ~Y΅+‚P^=σξ‹Κ Χ―Gαν]?_?κωΥΛW§GΧ^Ω~π3=Χ―GQY£yό ―±gχj·ŸJ•\ύψΆΝƒhυνημ:šJ“€dK`—\Zτ6Λ"R±ςnΙЏGΠΘ’¬«ŽŠZކ'Μ -d +¦ δ³»`νZ‡ΆCύyPΧ{qA_°θ?Α¬‘΄4κρc;Ζρs!a?jύ\$G^™ψ)Ι 3sτJnλ,q͚Τ.2Fαy—Ξ©m?rΣ½%υΌμQ'`mθ^”ΖSπy’ίz.«vA*©yθWΚξήY}Ο_ξ\Ά"##XΆl)―Ώώή^UQ«‹Ξύτz=‘WX»v5ΑΑCπςz² »Ε2„±tΨ{Δέΐ/πνPάrα_eζ*;xpΎ²ς%“σ?ώ—ωΫΞŸŠΑ܁jM»1|dκΪ>IΟSY΅+‚P~ε<ζΏΌ~ώ³οΡςςςfΠ `Φ]ΓυΧ‹½Ϋ»$IxΈ{0p`pΩ'YΩ”b€/nΉ ”g¦Τιω_τ¬(ν ‚ TΟ<Ρ¨Z΅S§~τ¬ΓAA(UβVAAΚHΉθΡ*ΧδZ YΆερ— ‚ ‚π―%z΄AAʈH΄AAʈH΄AAʈ˜£%εDDD{φόNJJj‰κΫΨXΣΊuΌΌΌΚ60A᱉DKΚ‰³gΟΠ£Gw$©d7σT…ŠDK‘C‡‚PNXXX`oo³³s‰φφφXXX”|†pB‡wγσΓΊ²Ϋ‰Ηr‘•oυgφΡό^iyŠϋq<ΚΎ ‚πά©=Zqq·Ψ·QQQ΄ž‡‡/ΆΖΡΡ©Œ"„#I¦¦¦%ojjZ@ο—BJΨ6–,έΘα°[€ΙΦ8{ω4|=j”nΌODAΩΛA–K‘1…ΫΫ>`Ž<‰iAvεοGΠKu_A¨h*D’΅o|}λςzίώ΄ήΙΣΗΩ·={τ)£Θ‘|QR`α΄Δ΅ŸΒ¬)Υ1Kας©0¨\ςξi‘J+ρPR8uβ"ϊF₯Σ\Y(΅}‘Β©‰VTT―χνOΔΥ‹θT’’„„„$IΌ;i*ξnnΌσφ(PdYM=Ώόίύς¬Γ„)ιά¬’Φ1Ζ„s1­½Ί6ΖΓF; N>Y €€†Ψ=,˜ΌŠέP9ωΡaψ$7΅G”΄‹μX²υ‡ΒIT4TkΡ“α#ΊPΗ*‘β—z ˜ΣΫΒC‡ρΞ6O&ψ˜66€ು‘8ύ7„!΅ξ'†pBΗ.ΐbΜt?Μcσi‰φ aX­+„ŽzΨΰυLia‚’ψ«f/`Ϋ‰[ ­O§!άžΏ—:σfΠΑ¦ˆΈ›¨ωcφ[Μ>|‡{τ‘ύ<5΅/av/‡σ" α„Ž‡κŽ$n\Ιή+©ΨT™!zaρλ|Bώο$±{ό»ΌΓδ7PIRH<Ύ–…ίοζάΥ›$ΛZόƒF3q@c4Ζ‚χg¨ΛΙ"βΏψp_›F:vς€.άέΌ’ί/Δƒ£A9ώ‚ <_*Τ-£bDVΙ¨T2²J,ΛΘ*™ˆΘkDΗάΌ\J%c4ŸuΈ‚πΤ©œΌπ4ΉΐΎέ€τCηJ:nύη7Ώ`ιŠήo•ΑφΉ+ω'P90χ#VέjΜΈoV±bήdS7πΙΜ_‰£2>Ύn\?w0ήΰΨΙ 4–η9v.ύ•³„©}πσΞΣ{cΌΑφΉίβϋ, Ν5σœί)·Ω5η3v^ε£oW±θύφdl aorŽ(,n-ΝF|BΏšζψXΖΖδ‹ξωl†~Zy‚Z#Ώ!4dMχ2ϋέIlΠρΡΒ•,šΤ”ψ Ω|ΕHXZ»ΰΧmŸ-ZΕw½Lζφyl8―/xj$žX6.9ˆσλŸρές>Θω7αΉS‘-•JΞJ¦du IμΩ{€ιŸΝdοΎCP’sΓ~ύ¨/·}9Η£-=fAΔΡ*Δm™Βԟ(δp+Ή”F–dΘπq­Hό~,ΑoΟ`ΕoηˆΟυfVpm;ˆnώh44μ„oΪΔQ²γοJΌ6¬άνΠΈψΣudot‡{{ΡvΆšΪCΏc^_ŠΥ…(ψ{?ϊΉ›¬uEkˆ"2ζa„†[Ρ”|$M…JJ)ΝΛL»x†H‡Ά θΣ /7œd2S oϋΙγαyV‘ΎϋSRR˜τή‡ΌυΞdή›ϊ1ύ}${ŽVμ­[lέφ [Άνΰv|͚5)aˆuoΣ­Kg:wιLη.=ψίΎt”ψl³2GΎNc{μ\λΡ}LͺίΜ―ΧAά_ ¦G}7μ4n4κΥΏμy#–YσFΜ¬°Ά.lވ ”.CδΆξ;ΞΕ¨X“γΉvl#kχ§βΧ¨6y§Nε%iι*ν!k8z=Δ˜Σό΄xΧ|;Ζ]Θxψω :ρ+Ιυiδ¦ΙϊUΈΌλw’kψSϋ1ξ"!9Ύ@kŸΆ-ΫΔ™Ψ$’ώfݚ½Δ—τΪΤ:w³ήύYτs!7.h›”«š1xz3ίΔnbβύ!Α’Δmζέ™t.q &²9 GδB―·ΠkZ ύŠCsBs*Έ?%ΏAž+*Ρ:~ς4G9Ξδ‰γ±ΣhθΧ?˜τŒ{Θ²EQLΩΝϊ·τdύφ²{<”γ\Ίf  zV ¦άΎΜ₯dWšΊ—δ.Ο’TzσF„ηŸ,Λψϊϊ’R•¬[ΘhTΠιt Οί{,3*’ΣΚhΜ+ζ{E_„S‘Ίcn݊ΓΑΑ[φ<Θ΅¨(d•κώ€ψϋ·|Έ%’τ„χX–4/-0m‹Ws$*ΔθSl\Έž«u;Ζ£/›d‹£ƒšˆΏ”ΚΌαωg0ΙΘΈGZZF‰χž“$+SΫVρλρ+Δ&ή!>b!‘{Q·Δ§d£¨ΟXE_„²T‘z΄^nύ"aΒ>ϊ-κϋϋΡ―w/,-,QI* ’BΞ›”ͺžtHO²‘ω[3±dσΖ­γ–Α–ͺΝ»3νݎ8—(‡³€YΏ`κ±šwή ₯Zπ<ΎιύψσFαω%cr/œ-³b~|*sͺ5ΐΤα-°B=~AΚ’Τ<τ+ewο±EίλζΪΈiυλΥ§NmίGZο|Ψ9Nœ8Nξ½Κ(2AΘmδžosπΰώ|e‚ Βσ)η1ευσ+FV`«Ω`[·my€υ<=«ΨκΕ2ŠJA‘h"Ρrtt½R‚ ‚ T8εs¬PAα9 -AA„2"-AA„2"-AA„2R!&Γ ΒΏΑ˜vŸ ϊ,_™]%+Ύz§= ͺ<π‘Τ(χ+Θ•+W2t( KC—Σ½[—όλ§ώΑΒi+ˆk?…YSͺc–ΓεSaPΉπδMA(;"Ρϊ;8˜Z `γε•«<θνοOΓΖus•_‹IdΚΌ\6όι)₯ΐ¨d=ώ8τ/΄|!»<""’aC²’,­‹3ν^ycω˜1&œ‹iuθΥ΅16ΨipςπΙZh$5ΔξaΑδU쾐€ΚɏΓ'1Έ©= €]dΗ’…¬?N’’‘Z‹ž Ρ…:V‰μψpΏΤ[ΐœή¨0:ŒwΆy2qΕΗ΄±‘ ύŸ ΕιΏ! ©%gmSΉΓ©υsωvΫQ"ο°Φα₯AΥβΛΗΞEЍ»CΩuρU^ οΨqti…„Bβρ΅,ό~7ηή$YΦβ4š‰£‘@I½Θ/ΛσγΑ0βτVΈ4Μ§“_Εωή%ώoΙΦΈΘSWtΑΈ~°SK€ρΫΟ‚ ”• ‘heάΎ—·—-ΛU~XT}%Χ\εMkΨ—PΠ°Š ”sŠΒχ«Ύ'dI-[0γ³ιDDF2|Θp”ϋIΦ73gβμζBόνΫωVW9yαi²}»#hΥ₯*y3%?·ώAwΎ`©\Ωϊ%3ζ€ή²ρ46Iδΐ܏X•ά‰Iί|DUω:{CΎΰ“™Μψ||έ9wΕ[εΗNf ±<Ο±s™΄if†ώΚYΒΤ>Όμ-goNa³·fι£%Όδ #φiβ΅$ξ€!’ΝΛ"ψν™„j38»ώ fNΧEhb%aiν‚_· τ―ε‚Yμ/̜6 M–2ΌΞ]Μϋ+’‚˜4σ}ΌT·Ή’h‹£t‡Γ >ζ‡ΜΎΌΏΰ?8ή=ΒΟ>γkϋLo―ΕPh,‚ e§BO†7Υhψ`Hk΅φ¦ScW,LεβW*M†0–ξΒ‰ΙΕBιP•,caeΕ‘C™8qR$kΦΜ™hέ\00JΆ ׊ΔοΗόφ VόvŽx}ξ-ΈΆD7W4WvΒ7ν WβŒ( Ωρw%^֏Fξvh\όι:²7ž'·π[ΈΧυΕϊY.ιA‰?Ξ±Ϋ~½€αΜρpτ‰=ŽδšώΤ2Ι±9ƒƒ€Ζͺ²wj7ο@Kο‡Γ˜ξmϋΣΡǍ½ƒ ?ĞSχ0«ΡšΞΎx:Ϊ‘υ}…–^IDέHΗ€νΩiΔλ4φpΐΑ­6MλΊ"'δη?]θ>μ5κh58ToΛν]8³χ/β•βcA( ’G«0u&Nδvκz’V¬ΕΚo­λŽeΗ±˜Gn'3ϊO6¬ϊ_„sσΣΚnΤ|αu&Όυ2n:*Eώύί$%ω.›6oζŸ#G‘euv’εμκŒΑ`Θ›ŸŒ6ΰmζωqhηΟl[5™Ν›Ϊ1ωΏoΡ’2€7—μ3,Ιάsτθu`HŒ"ZεEηozΙΞoΫhή0 ηOmέΞίΠSνςQ"«ΆdRk~]rŒ«zož‹ΒΣ―.69ΊˆΤ>½0Ωc‚ΩΨ…ž=:Τές~/’Œ³‹φαٞΉU]29›„‚=qG7°βΗ½œ‰Š'εž]†Ώ—n^'Zφ’‹[ξ+CτU’2ΞrvT7–?x=υχΠ»4&ΩEΖ"‚P6*t’UΩΧ—„γΓπο5—“Ζ‘m41{™J₯Β`0"ΛEgJϊ¨­όgΒbλdΤηοQΛA&ωκ)ŽάrΓA$YΒSfT #SΗθ1c γά… Θ²Μ¬™3qrqFg0ζͺ[ΉR {§U§ΧXσΑ»,ώ± M†š*duαoμ‚§βKYɈEό½oςη…8ΌN…αΩp,φ5mπIό‘1u‰Ύ\ίήNΉ»ΙUŽΌ0r.υ;aηΖ5Μ·γg1ι…ϋskΖμδΡxm#3flΕ¦ΧhήY;σ$v}ώ>#R0mΒπΩchœ£WMR[a'K+‘l ‚Pf*L’C֜¬œœU*0κ1±q£žΈ[·i[Γ/sd•DZ†+³ΒUΩ²Œ°šcXό~΄χΏ!4•_ζΑυŠJZ8Ϋ-`νΑp;ͺΏΠ“‘£Ίβc“Π\d]CKGΞΗbά@tkζ²ι”DΠ—Kα“ΒΙusX΄ε(I¬œλΠfπdΖŠ ΊNY©NZfsηΝcκ‡ΉΣk8ΊhΡ ωκG²π¦†ρIq*²μZγq.GhY-«·H‰ΏΜεd»Λ Ωαλ«eνٝ w’Q_GTζζ4¬ω ϋ‡$oztH‘°tkJ·qhζφ.£ω“Δ5=ΡQΡρΞJΞ#Έm†³Ke/ž!‘-_υiEMΠί%35+Α’΅nhυ;‰ˆ6ς‚ΧΓ΄NvρΐE9N\Ί=ZχΒmΔπvβΓ&B©}6^ΛΑaHΦ½–Cυ5^:σ¦υξ‡―ΐΝ$#κν­0nmAόχυινq°θ$ υO˜Π²K›μ$+%‘}ί|ΘςΨ&ŒŸϋ=ί/œΜ‹£c€– IDAT©λωθ˝ΔεύŽ+I]γ ~ž΅ŠψΦS ω~.ύk©ΡŸ_ΗΧ?ιhχqkW-aΖπΆΤwt’uχ0’ (Y3)ιόoΖ 4j„ή`Μ.π0’¬»—« CδΆξ;ΞΕ¨X“γΉvl#kχ§βΧ¨6&…lχIH—VιlYΓΡλ $Ɯζ§ΕΈζΫ‘6ξ*@ΖΓΟΥ‰_ωKO#7HΆψΧ―Βε]Ώ]ßΪy¦<"φ³u)"n&r'ξ §.Ζcng’ΎΒ΅+Ψr&†Δψ+μ[Ά’Γf­hγo†Ή½#Φ‰gωϋάMβcΓΩΏrϋξΗιΐ« γΩςΗo$r'ώ*'^ Ι›ήeΫ‚%μΏǝδ8ήΓq(ΕΖ"‚P6*L–‹ΨUΚϊ·…ΣD’ž!βΘLn&Q ιθ ƒΧ³ω‹ŽΌ8r%)‹{qδs/œ›ΐγ₯χ lΣΝMƒ+~žOˆUβ°ύΟΚtžσ:=T€=έΗταΠΰΝόz­oΈ?b]% uΣaŒmW‹[Τ?˜ «±ΗΞΡ;Gχό  §ΒΒ©_«Š”υνŸ””Tp]EαTXXώ3%ΓmŽmψ–•Χo“’WcλR›½¦1€­’1‘˜lh6z:Γ–.`α„Έ₯·Ε»Y7>„φ~2bRßZ©;kΡ„ͺrVΤυκSι»s˜Τυ%_G―’ΐ±u Y•ˆN]ΟALΦ .dK@§ϊ\Z2žε‘©Xz΅dπ‡Γhh’?ΖΆ’o?Β:IKΓncέα6Ϋ$GΪΎσ Ι‹3λνUΔλ,q ΕτF΅ |{:iΛBXωa01wΑΚ₯/φ+&A„²Sa­œds_’šMύ7—sυ›~(ϊ¬³z΅Ή *Ω”ψ#-Νητ†±…&ZvBkˆŽ"Zφ’«{ξΙΑU+EsυΊά΅ Υ|j3­Sϋφftΰ'Μ>ˆ/u‘w―Χhζ!&θώυlψΛώήΛ‘gJTίYmΞΰ¦/ζ*“«uγ“ωέ ^AIπ’Ÿr—™2uSΰΓηf^΄ύmG²Q«Φ|΄©uξf½ϋ³θηώo²jW>YΨ5 άCrλΘ€Ή]™”wΉΚ‘CΏ’ΕМ…!4πO[_zLžGΌλYΦ ΓΨ/ι0φbA(C2Ρ’P‘υ˜XΪ`Έ—Œ_‹ΧΠ'_§nΣvθ.’uρΐΔBCQσX$-R ΧλΐΉ^-₯€ΙΑŠT`vV|]&y'"«i9f> Ία— «™5z+ 'Ξζ½Εέ›ZΥͺσE΅κΟ:Œ§ͺψYf‚ […˜£•—‚‚€’QŒF|bεΥΟΊ/a¦m€§οKXz·Ε½ͺoαW'έ'YΧ§i4ύr„Žψ²{<”.]{8 YΉ}™KΙxΉΛ]·€H°toJρ³ψ¦Ώ·.0AA*– ‘h™Z:‘‰™f0fšΑ¨ΤN˜ΫjΙΌ{ΟΊνH>»%3…»η@Ρ₯‘|zv5PŒzŠΨEΙ‰vƒΊγπχ¦ΞήΖ±Θ8’’β‰Ύr’ΓgcQ4/-0m‹Ws$*ΔθSl\Έž«u;Ζ#w»#ΤΝΙpe›χδΚΝD’β.gMΠ΅·ΗRtg ‚ B…W!†½›…rωπtΏΰ\Ӎo[nό³†*-G‘‹GŸ(`4 υ˜ΩΥ %φ •<›ΩΆ…o0_~ιΘς[ψ|ά|Α\γŠOχχhβ«₯ω[3±dσΖ­γ–Α–ͺΝ»3νݎ8ηM„$›’ΧΝIIΰΨκ,½–H¦ZC•†AΌ7’Ή˜ +<ί š/&‚π’š‡~₯μξ5sTmR!:Έ²(FΒ~Ί»Έ5μƒyeΟ¬ή+Ε(€ΖžηΚώωΤΈsχ³ŽVψ—Ψ»g/ΉΚܟ―LAx>ε<ζΏΌ~~ΕθΡ*€’VŸUά:΅ŽˆC!€ΖžΛ±LΒ5z­I– ‚ ΟLΕM΄$ §zύpͺΧοYG"‚ ‚O+AA¨XD’%‚ ‚PFD’%‚ ‚PF*φ-AxŽDDD°gΟο€€€–¨Ύ5­[·ΑΛΛ«lA›H΄‘œ8{φ =ztG’Jv·ZEQ8pΰ H΄AΚ1‘h B9aaa½½=¦¦ξf^™™™XX<Β­m α„ŽzΨΰυLiaς˜Q ωˆΧU„"ˆDKΚ I’Jœd˜ššΠϋ₯Ά%K7r8μi²5Ξ^ώ ŸD₯― ‚P<‘h ΒsDIύƒ…ΣVΧ~ ³¦TΗ,5†Λ§Β rΙ8αρˆŸ'‘ "ъέω+@FbbΎe}–―Μ’_½Σž€UžFx‚P*J:7«¨uŒ1α\L«C―ρ°‘ΐNƒ“‡OΦB ©!v &―bχ…TN~t>‰ΑMν‘%ν";–,dύ‘p ΥZτdψˆ.Τ±JdΗ‡ƒψ₯ήζτφ@…πΠaΌ³Ν“‰+>¦ιψl`(N aH-ωώ6Γ ;y@7ξn eΧΕ;XTyΎcΗΡΉ¦’!œΠ± °3έσΨ|Z’ύBκQpΦYϋ«$ώΓͺΩ ΨvβhλΣiH ·ηο₯ΞΌt°ΉXp›ή‘όί’¬=p‘;¦4θ8‚qύa§”;œZ?—o·%ςŽ+m^4‘Q-Ν9]Py€6wb%™ ΔόƜ «Ψsω.UZwμ[YϋˆBβρ΅,ό~7ηή$YΦβ4š‰£1ΌΓ|*Δ‘Y„¨ŸζΏƒƒ©Υ 6y&ύΖ½ύύiΨΈnςk1‰L™·“ƒΛ†?½ ‘P9yαi²}»#hΥ₯*ωFΣωsλτη –zΐ•­_2cξJκ-Oc“DΜύˆUɝ˜τΝGT•―³7δ >™iΑό_ΑΗ׍sHQ<°UnpμdΛσ;—I›ff诜%LνΓΛήrξm"ΩΌό/‚ίžI¨6ƒ³λΏ`ζτoq]4&ζ€ρΫη~O£ήο³h‚3ΦΦw9πuaqΌŠ#·Ω5η3vzρΡ·νpM?Λ¦EsΨ›\:Ά™―ΝTΟω˜2ϋςώ‚ΰxχK?ϋŒ―ν0½½Γ…uΜޚI§–π’ƒŽΨK§‰Χj0\-°<_J¬€rxΗ1†N˜Εν=.ό4“―f|‹λΒ 4±’°΄vΑ―ΫϊΧrΑ,φfN›Η†&K^«€Xm*ΔaY„ͺχΡΚΈ}//n/[–λqyΩ2ΦzŠΏ/&δzxΊhˆKHyΦa Β#)-Ι6αγZ‘ψύX‚ίžΑŠίΞ―ΟYCΑ΅ν Ίω»’ΡΈ°{ΎiWΈgDI8ȎΏ+ρΪ°~4r·CγβOΧ‘½ρ<Ή…ί’ΐ½/Φ—ΞrIJόqŽέφ#θ% gއ£ΗHμωs$Χτ§VσΑέΫφ§£3{/ $@ˆ=§ξέ) uγ!Œn[ 'M%,’‹ŠΓˆΏt ΣΠ^ψ;kpπ`Pίlrνfž6οδη?]θ>μ5κh58ToΛν]8³χ/βΐ`ΐ ©±ͺl‡ΖΑΪΝ;ΠΫ΄πςxΎς`«Πbΐυ‡Ψs:kΝj΄¦s€/žŽvh}_‘₯WQ7Q ˆΥRδY‚π\©‰VaL5>šA­½ιΤΨ SΉψ•αΉ&£ x›yKη0:ΐ’3«&3tά\Η+χ—«qσpΙώΰKζ昣G―CLΡ*/ͺΊ=<,HvήxΫFsυ†uujλ.pώ†žδSG‰¬Ϊ€vM|QNγͺ>°sQxϊΥΕ&_Ύ(γμ’}x°1χ’ͺK&±±IY‰&T«]ƒιKqqn^'F‚·λΓε&nž8ηϊψηi3ϊ*QgY:ͺέ{v₯{ΟξΌ΅ϊϊ;‰$AνΣ‹·ωnL0“ζlΰ―λi(^žŸgΧϋhβA—Lbo&‘ ηΦΡ΅|5eίθI^ΓXvN‡Ρh,0VAž/ϊά©ΞΔ‰άN]OŠ΅Xω ‘uέ±μ8S²• a,φkς/“μxνσ΅ŒoT‘_‘‚)­δJ5μ=žV^cΝο²ψΗ64j ¨Υ…Ÿ_)($RΦP™Eό½oςη…8ΌN…αΩp,φ5mπIό‘1u‰Ύ\ίήNž½•œ­Ιυj“άk‡R@ͺ#ΛyΆ›§MEΣ& Ÿ=†Ζ9zά$΅v2€#/ŒœKύNGΨΉq ³Ηm£ΑψYLjUXΉCΎαΓΌQ=Σxm#3flΕ¦ΧhήY;σ$v}ώ>ŠΨAžϊΣ]ΩΧΥεUψχ˜EϊΙoΡV6Ο^¦R©0Œ…―,Χ όŸΨ²y [6~Ng+^|Η¬η›W0ΊΎH²„ŠO²π¦†»‰Iρi@v­‚‡1‚ΛQO>”ψΛ\NvΑΣ]Ι__-gwr,ά‰F Q™Χ₯aΝ(Nόώα:ό½ ϊάθ‰ŽŠ~Έύτ.E›αμRΉΐ+υŠ‹CΦΊ’5Dσp ·’‰+κγξ⁋M\Ί=Z­6ϋαdoγlSΒ­)έΖ}ΝΧoΨρΗ/’¨Už{c’bξcζ5"cLΡ:W&ύβ"Ϊ2 O+|ΌάpvΙL-ξ―!Βσ’Β$Z1ΐ…<I₯£0ꉻu›Ά5,πw1GVI€eθŠhQ…©₯ΦΦΦX[Y`"I¨Ν­³Ÿ§\Νί ¦O—tθ>ˆ)‘GHΈpUώaωΤ`Ίu ’[πT–ήΙΜ~SΨ‘€€’ΔΙ΅Ÿ2²o'^mDχAο2l!Γ ‚PΊ ‘ΨΊο8£bILŽηΪ±¬έŸŠ_£Ϊw+MIH—VιlYΓΡλ $Ɯζ§ΕΈζΫ‘6ξ*@ΖΓΟΥ‰_ωKO#7HΆψΧ―Βε]Ώ]ßΪŽ)\ΫΉ‚-gbHŒΏΒΎe+9l֊6ώf‡δψ­}bΨΆlgb“Hˆϊ›ukφ_Δ‡L²oEΗ¦wΩΆ` ϋ/Ηq'9Žk§χ°λD `ˆΨΟΦύ§ˆΈ™ΘΈ+œΊΉ=¦‘—η»ΘΈΆk[ΟƐ˜xΓ«VrΠ€%­ύΝ0·wΔ:ρ,Ÿ»I|l8ϋW`_B1 Až’ΫΖk98ΤC`Φs΅©w0΅QΑ@›IF\Ά·Β˜–AΌ•9½=š`cυφcn1λ*!ξο2°Ž+¦1;ψςγΉ¬oΚHŸ$~ύfΫ }ψdi;\ΣΞ°qώl~ΏS@~_€£λ§!Όδ 'φβi❠ΈJIς°΅΅E§ΣabR²»‹gffbk[)w‘α6Η6|ΛΚλ·IΡ«±u©M‹^ΣΦΙXΜ·»dC³ΡΣΆt 'όΐ-½-ήΝΊρρψ ΄χίΐ&5ό©•Ίƒ°M¨*H8Τ«O₯οΞaRΧ·€ωY€dK@§ϊ\Z2žε‘©Xz΅dπ‡ΓhhAΦ-'9-ΖO!vφ">Ά œκΤσUjŸ /bί4Ύ=΄e!¬ό0˜˜»`εR‡—ϋe-W8Άn!Λ’Ρ©+γΩ ˆ‰ΓšaqgkΑεyΫ7ρcΐΠ„;žΠΘ,«΄dΐ#hl ’?ΖΆ’o?Β:IKΓncέα6Ϋ‹ώk‚πœš‡~₯μξ= άΞ8²ΖŒϊ― ζ^β2,œf}4œ˜#Gτν :Ύ³ŽΝ_χ‘λ{ΫΩόEGΊLάΘΑΕ½°±ΆΐΉω<^zΏθ θΟ°(x*‰#δƒ–|Ι)·Ψτξώyu mψ;“‚wPή"ϊ{g½^™|CΔ2pυg΄‹ZΘΐιq ˜3•WΕΟqόΫμέ³—€€ΐ\eξΟWV0…Λ—/“ššV’mYYYR­Z5Κυ­2ο<Ν­ΰυΌW†?O£Δnbβ¨h·|:―Ϊ–γΧC„η^ΞcώΛληWŒ­Όds_’šMύ7—sυ›~(ϊ¬K¨ΥζYx«dSβSŒ΄4ŸΣΖŸhε£ηΦ‘υ„ίΓ©«ρ€fκΘLΧαŠCLΦOέέr^ρTUlV Ύ½ψ ³†bηK]θέλ5šyX–η―B‘œe___Tͺ’½[ŒFNWτ\Δr’¬‡Ξ3£"‰1­ŒΖ\|A(_*d’%‘B1κ1±΄ΐp/Ώ―‘OΎNέ¦νΠ%\Dλ⁉…†Η9Δ―ώΘ΄O·`Σg Œ©†½Y";gLα Ία— «™5z+ 'Ξζ½σ_₯$9 F †{Ο:Œ SΫ~δ¦{KκyΩ£N:ΑΪΠ½(§ΰ#:‘A(g*d’₯  ©d£ί†Xy΅ΖӐ™ΆžΎ‘Xz·Ε½κ― <ή™~Zψ"_aΦλΤ’ύέμ«„d­+Zύ"’΄τΚκΥ2܊ζVΉ&–ξMι1ΎΝέΖ3bϋa†vΒ^dZ‚P dLξ…³eφȌOΕ`ξ@΅¦˜:ΌΦβ3&B9S!-SK2’#1Χ @₯vΒάVKζέxΦmGςΩuH*™»η@1θI>½ ;Χ(F=H>οΜάΑ›„3όuφ&Nw8³m9{γΑœZςrέ¬ ΩH½·^Α53œν«φ―TΐpeΫ’*γ_Λ;9.λ*%{{,Ε€πo$Χ$xΙO₯ά¨)uzώ—=KΉYA„2P!-οf‘\><]Ζο8Χ4AγΫ–¬‘JΛQθβΓΡ§Η  (F=fv5H‰=C%Ο¦Ό=u½Χτ‹ώΜIK£o1Άc?HZ‚ή}Ÿ›_/δ£ΰ₯ΰTŸŽ}ΪSηΑOJΗV/`ι΅D2Υͺ4 β½Νσ_₯$‚ Βs―B$ZΆ.ν¨ίύfξBΕHΨΈ²gn ϋ`ιQ'«χJ1 ©±η‰<B[Šί€Ί.£V娧rδ…3yaDΞJKiq_’cs†~ޜ‘BΉΉ‘w$«ucΪ’n½―‚ ‚ «Έuj‡BH=—c™„₯]5jτZΉΖ»ΜCɌŠ ΖDƒ¦ » ‚ ‚π―Uq-IΒ©^?œκυ{ŠMηδ– άτ ž·=&‰ΗYύέ^hϊ>ΎβŠ'AAr¨Ψ‰Φ3‘uΕΣ¦―71ηvΦOΥ› δ?£^(ψΨ‚ ‚ όk‰Dλ‘™βΣ{:ίφ~Φq‚ ‚Pή•ΟίάAAxˆDKA‘ŒˆDKA‘ŒˆDKA‘ŒˆDKA‘ŒˆDKA‘ŒˆDKA‘Œˆϋh ΒSpπΰώg‚ ‚π ˆDKΚX@@ΰ³AAxFΚΝΠα©3LjΌvEQJT^ζ a,ά…=έν ‚ ‚πά(7‰VςdLΤ&όsόoRSSŠ-/ w/laζ„tλψ*―vκΑΐqΣΨp>£”·“{›q[¦0υηžγ’[3—M§$‚Ύ˜…ο½ΝΧ‡ξpο`/ΪΞVS{θwΜλ끔z‘ν!‹XΏqzk\› fϊ$ ίχ›‹εΗ+γŸυ§R’vπ~4Yς)ΪΥcσ·ΥΗ†Σλζ°hΛQ"’ X9Χ‘ΝΰɌ Τςδ©© ‚ ’ά$Z©i©H’„Z–Ή—yšΥk‘–eφΨ›―\VΙμέ»›NΊ=Ρ6UZ/ͺ˜lgΟ―WhΥ½–y3%?6bΠ»_²άότΣf­ ώΚ 41Mdί7²όNg¦ΜύUελμωφs>ϊ‚ΕΣΪγ`ΌΑΟ³VΡΈίTB&;cmc‹iΥOyσκ8ŽΎ΄˜O_΅Cmf‰JIdίμ MκΘ”Ωΰ-Ηq9ήGΥυΒƒ—li>:[ΖσίςυO:Ί~ΒKzb/ž&ήY#’,AAxΚM’•––†$©07·ΐŠ3gOqώΒYξέ»—«ότ™Sœ?–Φ­_~βmJΆ/2bόI>ž5†»[±k:·ρΑ>ϋUQpk7ˆξυάPš^ρϋiWβŒ46?ΐφ?+ΣyΞλ4φPφtΣ‡Cƒ7σλ΅vΌα(i¨›cl»ZdFΚ–˜Κ²™ΦΦVY=cqϋΩvΈ]ζΎAOpΐΑ Π‘h!‘ΆΘί–ή`ΐ ©±Ψcηh‚£ϋΏN‚ ‚ <žr3>-5 Sd• λ7¬αΝ;tιάƒ΄΄εj~XΏ†δδ;tνڍƢ*γ8ž…+ζρV §WLdΠθ9Ίύ`jΉ7ΧμI2·ΐL‘Σƒ!:ŠhΩ‹jξ_BΙΞ›ͺ•’ΉzέpΏΔ„j>5(nΖ—!ζϊύΆδ'ή#΅ooFΖ±dψ &ΜZϟQib’Ό ‚ <#ε&ΡJMMεŸcGY³v­_jK³f-P©TΛΧ¬’Mλ‡ε₯ITƒϋNΰλΩτ6ΫΕΒ gΡ B­.|[Š’δOb‰‡γt*LŠX!#JIΗφτΊϋ±BεHΛ1σY΅πmZJ‡˜5z8_μ»-’­ DΉΉ‰w»ΏΟ/I .²ς­ώΜ>Z†WΒΒ ލΟ?ζ­LžtύBΫ} ϋ.‚PΖΚΝΠ‘£“–„ΔΛ•H999ŸΟΰΑΓK=ΑΚK²¬JC_ β1βTd]Ω½ Κq.]3P=«'JΉ}™KΙ4-²gJB’@1Ά₯uΓY·“+7Œ΄τΞΉ&¨Υ™dd>,Ρ_ΏΖ Cαm=(·toJρhξ6žΫ3,°φb’Φ3’ΒoŸτα«Ώrό!‘¨Τώ¬y»qΡBΉύg/Ynoϋ€9ς$¦Ω=σξrν» BΕTn­Αƒ†\\pyi0Dμg[€5>Υέp΄Usχβ.ΦμKΕPLˆ/r]Iσ"έΧςΥβΥψΎύΥελμ^Όž«uίdЇ ςζ>Ω+Ϊβθ &β―\nω"kμZΡ‘Ρj–,^‡οΈT5K&ςJ:U{P½J:«Άnγ|•Φ8₯]`σκ}$έ m«ςνΓl‹ͺŒ-Oμδ8N]ŒΗάή>Dα)SαΥ{6_υrΏYBeb^’ τ ΡPR8uβ"ϊFeay|‹H"Ι‘‚+7‰Φ3aΈΝ±³<κ6)z5•\kΣ’Οt†·s@2h!ΩΠό­ŒX2yγΦqΛ`KΥζέ™φnGœ‹όΖ²€YΏ`κ±šwή ₯Zπ<Ύι]…W&~Jς‚ΕΜ½’Ϋ:KάGσΏ&΅i7jηfdR%¨΅~΄<˜ΆΧwΪΦΜF [½€₯ΧΙTk¨0ˆχF4Η’”^2αqI¨L-°²²&oκ`Œ›•³³ύΤ-Π6 S―κΗτ α„ŽzΨΰZύ9Ω‡οpο>΄Ÿ§¦Φΰ%Μξ偔v‘K²ώP8‰Š†j-z2|DκXKYλ]€Ε˜θ~˜ΗζΣνΒ0Ÿ<}Ι%ζ7ζLXŞΛw±¨’Ύcί’sΝϋl€_β–,`큋ά1u₯AΗŒλΧ»μ ŒY·BY0y»/$ rς£ΓπI nj„Bβρ΅,ό~7ηή$YΦβ4š‰oΪσμέy|LΧϋΐρϝ™D[6“Ιb'Tν»„.B+±4JK‹ΪΥRJiiKΥ—κ’’Ϊͺ”XΪ*­ZK[[JμZ΅υ‡ˆ-"{Θ63χχG ΩDΟ;―y‘›{Ο}Ξ™dζ™sΞ=wΛθ·9᳄™ΎŽι‰ήφ}ρ ¬'±txYΎώ7¬abk Τ’¨§BόǞθW!mΝξL[Ψ=—z0hι†μΫ,Ϊ1ec–ϋΦ•©JΗ·Ύ€γ[<>γ°κݘόM·μΛ?MIσθqοΞΥ|yoΎ/οeέφŒOeUaΪ’‡[φBό‡Τl5“ί”^Lώ¦#.I§Ω°`§M5y>ێεi9l*½/αοgπQ{΄–iKƒμž3™•q]˜0{2Υ΅WZόSύ­™χΡ ™ΛŒό:η;šΎ2‰―Η9SΆ\φκmφoω›ΑγfΡOŸΜιuώ|1γ\Œ£ΉM,ϋηΔκ”^Lš?§ψΓ,™9“/ζ3ύΕτυΩΤDlάGί·?c‰;œίψ93ζ¬ α±4³T°)k Ύί8ϊz(sc+ώΣζςSσΕtτtαηύ‡ˆφρΑ^³ο¨%­ή{K.f‰/š=EQO!„ψ•šΙπB<ήL\\3–ž=^’{—θή£'3‚P#φ±λ”>{ΠΐΩΗͺ­ισJ+lο;^AgmΆœ‡₯-ΆΆΆX[(¨QΑl9TΞCzΣΤΝ;C^zσ*Ϋΐφ°τρkυΊfƒανA%» Ψδ’TξΠί§œ±s¨Bλ~ύhgάΛΙ¨ΡΑl>` ϋΞΤΥΫαXΣ›Χ_4p2θ ‘™WY¨ΈxχΗ― vv.4ιξC½;η9‘C™ZΟΡΥ«•μΡΧλ€gΥΒ&γήΖ —Σ{9“VPςΙ`ώ²lEΫΊΩ―Υ-Κz !ΔI^ŠόγŸ6 IDAT„ψOhpσωi/UΞόtS¦‚-¦sαάΠe_ΪΓ΅ ΞΪ[*ΥΖ5MUΊΊf_f€Zωk\ΊjW jΤΙo™Ξ.ϊ»ŸΌ,ά©bH!ψz Ζ²—K:Ε©α~,K±jLΖhhFœӏwu7dY Ε +ŒSŒά<ςΛβdX$ Ι©€&₯RΏ½Me/Ό\~fο_qtτΆβΔΎΏ±lωOY’vw†‡¬gpπξ΅£B%/―»£_’h ρŸPΠ•u ’^ŸmŽ–QU š¬σϊ4šϋζqεE%‡eFP²LnΧ ³ΘΏσϊή2T5Λ,›34`$Ν,²œAg‹½–τ„Hƒ6—₯LΜ—Χ2cΖFΚυΑ{oVΗή*†mŸNβ4€ΖΟ6.¬έw„ΈΆvμϋ[Gλ υ°Θ‘œΒΤ3닝Bόξύ€'C‡B” m%•Œ—Ήxύξeͺ¦ΧΈiΚio Ν=KƒΈTΑέ|Π°»¨‘‘„Ζ¨ό@ ΰ  Ώ{±lΚe.†[’wˆΞΰŽA½FD’z½>σQΙ‘l>©έ 9ΙEGoϊ½Ϊ–§ͺΊβμ¨%εvΖ™4Έyza8΅#Gχσ·5^uξ/΅θκ)„-I΄„ψO¨˜SΉ};„Ϋ $ܾ͝J₯Φ&~#ΡιΏfμ q₯g%–/‹£Ϋ0œ_””rESO!„ψ)­ΏPwΌ2  @σ8„Ή ΪtίΌ ΰΰέ2WH!žY_σΫ―™'C‡B!„ΕE-!„Bˆb"‰–B!D1yd&ΓΟπΟόΨ·Η—`$B!„σHτh©ͺΚ•+W:xW\EU rQΉB!DΙz$-__>™ρ)+ΪσɌOρυυΙ !„BˆVͺ‡gψsεΚU~Y»ŽνΫΆqΰΰ~Z΅lΝ/kΧρΞψ±ΈΉΉ>ΩȦ3,ς.7ύΜϋž9έ΄D!„%©ΤχhM›:rεΚ±ΰ>ώχΏμ?ΈrεΚ1mκ΄"(=?&w’½wϋ,o^žucžΗ©Dl˜Θ›£ ΄2ΆB!žL₯ΊG `ΚΤ)ΜψίLZ·lΓδΙΠΊeβγγ™2u nnEp Υz}Ε¬^UΣ³N…Uή £&pόθYR›Αι…BρΨ*Υ‰VΖ° O'Φ­[ΟK/ω‘p;?Ώ—Ψ²ekEAciƒmΩ²ά½5­Jτξ _ 0bα$ΪUTP0όsbϊ}†χ±)|Ή7–δΰžxθ¨3ψ[ζφrGΉsŽ- ηςΓξb,\hεMήξΣ  iΓ|oΞΓzτ€ώ0‡_Ž+ψ|Ύ„auBYςζ΄ύ_"ώ—εlΏH§ϊψŽxΑ-PP‰ώϋζ­ΨΞΙ Χ‰ΣκiΨe$οφoŽ}Φj¨1ϋρ+Ύήp„ 1&lλςόΐwΩNά‘D!„(₯jθpv€ζ#Cί~―cο`ΗϋL$&&Šχ?˜ˆ½ƒ}ϋ½^Œ‘(Ψ΅Ζ :GYΌό/n«ΙόϋΓB‚]ί`xϋj΄ρ1}κXΡpψ2Φ―—έΠ¨±μ›;™U·ΫσΑΒοYφIO¬w|ΒΏέΈ;ΌhΎΚζY+‰|ξ7‡Ύιyι?-άƒsίΟόώ[>|&‰M³–s$9-›²t‡/Ύύžΐ©ή€lœΓš³nοGΎ\—JǏ³jε"f υ¦‘›$YB!D *5=ZK8L›:)S§ ͺ*}ϋ½Ξϋ?ΐΑΑž~όžEί~ƒ››+οŽ—ΘΘ(ϊτ}οVώπg6qαΗ1ψ­ΝHI,h>f9“ŸwΔϋΝώ졐eΥ[σοοθΠ gΦ6Xj΄el)[ΦP£φ°qŸίvα)'œ;Π·ΣFήάu€ΘNέpPο k1„Q=°Ό{z@Εν…ΌάΘ `ΧΣ—ϊλ6q>ΒLs7 ej?O·Ϊιϋ;vΔ«ΪjώΊ’ˆZ'k5L˜ΆvΨ;Y`οδφν"ώkWΓΓΩqμ1I‰ΪΏ‚•ή ›γj0sdB! «Τ$ZΎΎ>¬[·ž²Άe3—ppp΄ΗήޞJ•œ?ξ]RSXXθ0M¨*(JQτΧhpλ2…~ξ™s΄¬*Ϊ¦ύΟΉ£^ΫΑ›sΦβή./Ήks-ΕtεaI§89ΈKΣ·©ΖdŒ.Ν‰5“–haA§jέM²2ιp­μ’Ω½¨XYSFI%Υ`δζα5ΩΕρK‘άNI%%1•LΩK¨χ #ΪMeΦΠώόώl7^ιΩ™–ξ6£υΩqμΟ5hL­κΥ ΄Ωσ‘μ8v„~†.Ε™BˆΒ*ρD+―%>˜<‰U«Ώη±οςΓͺοΩόλf:ϋv¦w―Χ9zτ/6jT(XΨ: wvζώ4*…θ[±˜΄KŠ Ί\3΅L †ΟI³,+-(eqΠ’ήs₯ΑB—Σh­6ηQ\σ₯Ÿ™φρΚ½:’χGΦΐ‘L4ΏΟ˜ΘέW„ž#ηΡΈΫaΆώτ=³Fl€Ιψή{ΖQ’­GDLR"•μINI*ΠώzG‡χ~ύ§L!¬x{Qo,ζνfV|ΈzύƏ8ŒχOθT±όφ>d}„OΆR1G+Ώ%ŒF#›6obΕςοΨ΄yF£''=οŒ-ή5΄RΞόΘάί+0`ΖάwΟcΕɌ75EΥlΞάWkpΗΕ|•‰Ž8;;g>τe*›½sφ$œ:Π΅vԫꊳ“Ž”Ϋζ\φV°qkΑΛcg1»―=ΑΏξ'J֟x€$άNΐl6ηϊ a̘qFς(ΙΜ•Ÿή’s―OΩ{ϋA£PΉ΅i“·rωm-ϊ,cL©HJ΄.9μ_ͺκ#„xΤ”ŠDkΚΤ)ΔΗΗηΈ„€N§£Kη.τ{£]:wA§Σqƒ/gϋηSrA¨˜Sξp;!„„ns'ΩΖσόŸρυ”ό θiϊς[Œς`σ½;ͺQόύύ|–\Ž&EgG•&>Ό7¬Φqnρί3«i}{χΡΖ³Mζφ .2dΠ0PUτg:vθ€9μΙ²ƒ Ψ¦ΌΦ-œΐ{‰~Άφ™‚ρ_φ™ƒΝ‡ΛώtΪK€³•ώA³ωQιΗΡμ%yί«Ό8W‡ΗΐEτtGΉΒ–E X³χ,Ρͺ5Zχ`θ°nΤ-{O b:KΰπχΈ1` [\ pΤ\΄ύΊΏ~;OG‚S}|†N`` ΐyˆ ωυψMΠ7¦KϚΩ>ͺ‰ηψmΡ|Vν !Φ…ΖΎΓέ»)φšτsεV~sϋήΚ‘.nΔ]Ε‚οvπο₯΄%SψŒ`|ίZόϋUϋwOdyF}Z[ ζΥyΕ“^_!Δ“₯Δ­ [Άlερc3―:ά²e+}ϊΎFTTŠύggΧ―‡Σ€q’’’ŠΰζeιψΏ­tΜρg-Yί#Λ·Ίτ™Ώž>ίWοΖδoΊe?Δ¦>cΎΐgLΕi=΄tCΑΆ[΄cΚΖvιί8Ρf˜?m†eέa ­¨˜εX?¦-ςΛ±&β’ͺ|·ς;/ZŒ§§3fNηΒΕ‹ 45=ɚν«Θ[·r)$…S;$±ι[<ηu…«wρ"]+ΰm^)OΛaSι}i ?»€:Ψ£΅΄A£F³{ΞdVΖuaΒμΙTΧ^!hρgLυ·fήG/ΰ”WΡ¦ ¬]LΏ·gςme…σ?gƜ4\:–f7Ψ:k&Ώ)½˜όMG\’N³aΑ,N›jς<€Λώω±:₯“ζOΑ)ώ0KfΞδK‡ωL1}Έ\Λ;ηΊ€/™Rίo}= ”Ή±isω©ω· Μq,ΟO4{ςj‡όκ{•0BˆΗ\©:Μΰζ暹„ΐw+`ζgŸπΞ„w8}φ 5ζτΩ3Ό3αf~φ +W|_Β Q΄T@£ΥbmkΛή½ΑŒ?![’5Λί½«“Ωœϋp`β?μΨg’E»FΨ8{αU=„^%·™}Ω)θ¬­Σ–/±΄ΕΦΦk 5*˜-‡*ΠyHošΊΩcghΐKoΎBεcΨ–_Ι*ϊγΧΠ;;štχ‘ޝσœ0£FμcΧ)'|φ ³ŽU[Ση•VΨfΜζΊιL]½Ž5½yύE'ƒ©ζWΎšc]ΚΤzŽ^υ¨μdΎ^<«Ζv5 m.ϋgž©@ν{}…OžRΣ£δxƒθ{“©±cΖύWαρŸSUθΫ· qρό²~=>‚V«ΛL²œ]œ1™L™ϋζP m瀦“κ—₯ž^΅Xώϋ..½ά—j…όhe 㚦*]]ο ΨW£Zωk\Ίj‚Κy¬Γ΅²!Λς%VXaĘ ¦θpnθͺRΓνξ5Ώ–UpΦ¦υΦ™₯-›rjΈΛ2jhLΖhhF\ζ²)Ή—Ÿ3#7όΔςŸƒ8IBr*©I©ΤoŸ"”o;Έ&!Δγ¬T%ZB<ιΜ*$₯€2bδHΜ9ΓΏ§O£Υj™εοO%ƒ3©&sΆ}ο£ΖqpηAβn%ςΎί–Œ¨J;Cz3Θ#—?ySjΎΖΥ§ί+˜w€A›Λς%iΩ’MΦB4š»K­¨*X6ghΐ=Λ¦θl±Ο²lJεηΐ|y-3fl€\ΟΌχfuμ­bΨφι$NπψόΫαΑβB<ή$Ρ’TI{Ώ“’ΔœΉsωΰΓιΪ₯3N=F³ιΎ}ο;:jΫ±ΓηύΩtuΛx³g‚ωmΧΏτσh€:,t©$'ί=Ξxε2Χ2‹Χ Ρά³|‰KάΝG 3αY#- R#C 3ΠΜ-χ…|σ£­d ’ρ―›iνž―ιΖ5n¦Η’5ΈcP‘θ€ή­0/WχΧεNΘI.:zσΕ«m©­ŒρY–LΉlρS;!_ς±KˆR".53*ͺšΦ‘“”Θ'3fΠΈiSŒ&sζφŒ‡•ΈΤ,Ω*Χχμΰά:­MuͺV­šώxίΞΝH ήΞ±$@λNΚ‰άΌ™Σ±D^>ΐχ«v‘[(εprΠrαpπέεKμΪΡ­m"Ώ.ώ#W’ˆ?ΑΊ…?qΉž/Ο»ώeD©Τšgκ\cσ œΊCTΨaV­ήCLΖΟΪβΫ"žMσ±;4‚ΨΈ.ŸΨΕΆ ΈlJu±rp’lτ)ύ{ΘgΩ½b9FεΎΆβŠ©„/ye’”PP9~ζ,±ΡΡΔΔΔCXψ5nήΊ•ω}Ζ#6:šγgΞd6_&hηy<:zί3eJ‘| <5ΨρχmPœπϊ&M’V3qΰk ›ΆžŸ± '½Ώ.š½υ’–νβQŸ²έͺ#:eΜ©Κ‘ξΩβ-¦vB<Ά”V_¨;^€ΞBς.!FΠ ΌΌΪeΫΌϋΎm99zŽ₯‡‚Έn,Ψ-xœuV lρ 5j*V!„E/λk~ϋ5σdŽ–₯…Gš|V£fI‡!„’I–B!D1‘DK!„’˜H’%„BQLJ|ŽΦνΫ· ή»›³gΟ`4ζ·dbNGνΪxyΆΓΦΦ6„B!J@‰'ZΑ{wc_ў‘ƒ‡£ΣεNΖM€F#ΗO#xοn^θΨιΏS!„⁕ψΠαΩ³ghΠ ƒ† ΰ}3 ™ψψψl€€$ΤoΘΩ³gώΫ`M!,ώ:³μς{!„B<ΩJ<Ρ2™=Yk~ό™5?ώ €’(xϋtΖΫ§3Š’ ( ;w₯cη¨ͺŠN§+πPcξψcr'Ϊw|yΗοΏγ«ωβχΌωb{^xk5WΜ€ΆoΜ[ΑΨVy^!„B< J<Ρ‚΄€ `ΫΞ­lΫΉ5s›΅56ΦΦ(ŠΒΘ·†γQÏξΌ5fdž]ƒ££‰½;“œm»‰σAAΔΨ;’υfŠV[€›θ !„B”‚9ZY-^΄$σ;» ΐέD,£·λ•^=2·=<-ΥZ·δΖޝMlJ+λτΝΖ3μάm€U›μΘ‘4aɐwΉ1θgήos›c?~ΕΧŽp!Ζ„­s]žψ.#ΫιαvΏ.ώš5»Oa,‹KˁLŸτ"†R‘Φ !„βΏRj­―ηΓθqc˜Υμ*fO΄2z»Š– UΫξΔgμόλ­ΌlHύw'{,Ϊ1ΆzΫs˜ fόΏωr]*/}Ό˜gά9A€³Š͟γΛΔ€χ©¦ 4²‰­1κƒœΒ†O†πJ·Ntλ?‹}· QFΣY‡ϊριώϋ/0βIT*­ŒΔΚΖΖλΜο³NŽΏχηϋΛ3μ…Ή…’rkΣ$&o‰’hJKˆΆ}–1¦ΩΓ\m\šΫD%rΧΟy0jήJΟθK#%ΫΟKoμB”~₯bθ0cy‡A†’(Jf•u¨PUUφ‚ͺͺ(Š’οβ¦LΡΣφΉš¬Ψω+›­NPγΉ8)›χAΨΈ΅ΰε±Miε:–aΏξgπ8WœSηόU3žΥJE+!jϊWNΟ?Ο ΑΓ@UYΈŒξ~έξΩCΑΙϋCΎ΅œΖ«ίΉ1cΞ@j—DΗͺšΐρB06-sEϋ YͺΫΔLDψMtu»ΡΪέ‹{\ΘΨεσ¦iJE’•’’‚½½=ΝέΔ$cΘ0'&“‰ψψψ"ŽBΑΡσyžZΐ mKƏ·Οσ…ΒtώO6…U€Ge졉ΔΚΑ[}-:5ύžE €ήθNT/ΗΕσ‰Ti^;yεω0«i}{χΡΖ³Mζφ .2dPZ’₯78Σ±CΜν^0%pΤ\΄ύΊΏ~;OG‚S}|†N`` 5–γkζπΝ¦#\Œ5a«―Λ³ύΗ3άK‰ηψmΡ|Vν !Φ…ΖΎΓέ»)φšŒrηc=²©«η²ώ„Β‹3όyꏱμ%yί«Ό8W‡ΗΐEτΜ2 ŸΫωZΗ²lΤ΄ύόˆ_ΘΆX¬«΄‘Χ¨Ρt­m‹‚JτΡU,ψn^ΊNœVOŸŒοΧ ;ΤΫ!l]ΊŸƒΟa΄ΕΠ| ΏϋΞΙyΤ!Ί+YΫoψ{ά°†‰-.’-‡Ρππ΄ΫDΙ«}σ©―9ς+ςλρ› oL—ž5s’Pο„°eΡΦμ=K΄jGΦ=:¬umc9°h2_mΉB|Κ:οΤΡpΔ >λβ”V5–½oε»±ΉΕ X †oη«q+ُuOzz+νy,H› ρ)ρDK§ΣqηΞ\Ή‚ΡhDUUΜfsζπ`NΧj΅8;;y―–bΧ†ηΝΏΊφ΄,―@^εj?Ÿ%—£IΡΩQ₯‰ο k…΅’‘Γψ‰›Ώ+Έ•jƒ[»|ΌN‘Ζ*SͺΚw+Ώcρ’Εxzz1cζt.\ΌΘΠACQΣ“¬Ωώώ8»ˆΌu«ΰεš.°vQ0ύޞɷ•ΞoόœsVΠpιX…ώHΐΖΊL^Δ³Ž©ά8w‚H½ŠΛΎω±:₯“ζOΑ)ώ0KfΞδK‡ωL1ύMΡ|•_η|GΣW&ρυ8gΚ–+e΅©τΎ4†ΏŸ]ΐGμΡZΪdKŒ§s9±`ΊΘϊe0Ɵ@}§Φ|†τopωzΝmlΚ¨ο7ŽΎΚά؊΄ΉόΤ| CλΖ³gξ–Ηψ0ΑU5·8]'%–ύyΤΑ”k,EΩ–ξ΄l’C›δΫΎyΥ7’­³fς›‹ΙίtΔ%ι4Μβ΄©&Οίχ;͞9“YΧ… ³'S]{… ΕŸ1Υߚyu€iΏιL0ffό@l†U›»υWΚΣrXNΟg±yκmφoω›ΑγfΡOŸΜιuώ|1γ\Œ£ρεB΄Ή°O΄jΧφΰΚ•0 —Μm‰UΦΉXYUU•+WΓ¨]Ϋγ!Ο^–ŽΫDnjo• xΌο̟+Tμτ)›3o§θΑ ₯οΗ΄E~9–ͺ”š“ζΡγ!£OΠh΅XΫΪ²wo0γΗOΰΨΡc™IΦ,τLfσΞ—QqνΠΏ†h€&έ}¨·aη#Μ4ΚΈ‚Ά’=vŽΨ9¦_A΅Ν tΊ3uΠ{σϊ‹›tΘΊβ ήAΧl#Ό=°Μ8•ΦK­‚Φ[[Ϋϋί@s9¦΄άΌϋβϋ”3ΐ«Ψσ»Ž€yλ2”©υ]k₯—γΨΟͺkψλj"ζJ{ψυ`yΊΜzfξw―φU£~Ν³s‹₯ˆΫυώ6Q£‚σn_…άλ븏]§œπ™ΥƒΞZ 5}^iŢݟ|«QΑl9TΞ_φ¦©›°η₯7_aί° lλ@οΚΆX[((:+lmmο:TΠYηό|ζ›šώ²\ΉΓέη±uΏ~΄Ϋυ)»NŒ€qΩΒ΄ΉO΄Ό<ΫΌw7;ƒΆψ–::ŽΪ΅=πςlWΜΡ ρίRUθΫ· qρό²~=>‚V«ΛL²œ]œ1™L™ϋœΧΚ†Μž%ΕΚ +ŒSAχTO†yM#`δΆ΅λF—}iαfƒιΪ%Β’NqjΈΛ2β3&c44#ΞLZ’…5κΤΊ›d$’\Ξ—φΕΩ ΏΫfU•κ†φވAو#?±όη N†E’œJjR*υΫ›1]O»Ϊ·›kφΉTωΦ!ΟXŠ-s*/ίΨ΄FnζVί›αάΠeΏΊΩ΅ ΞΪϋ-SxΧ4Uικz·_Q±―F΅ςΧΈtΥ• Σ—”{lmδμ’εy΄p§Š!…ΰλ1h»¦Ν…xt•x’ekkΛ ;ρBΗNωο,ΔcΞ¬BRJ*#FŽδΜ™3ό{ϊ4Z­–YώώT28“j2gΫ·ΰ4h΅ΉΜΰΡ8ΡζΝ94κr˜ίΧώ@ΐθM4;‹±U°lΞΠ€‘4ΛΝ‘θl±Χ’ή₯Agρ€}δrΎ m2κ•΅bζΜ„|y-3fl€\ΟΌχfuμ­bΨφι$N¨fr€ζSr‰₯­coόή–Ό<ΆΌλ«4YƒΤhΘmΚ~Ξ—X(…NnςŒ-σœχб!·6Κ³Ν…xtΙeqB”*io‰wR’˜3w.-[ΆdΪΗSq2θ1šM™W%¦½mεΕφ 6-πύ%_ΎnΟΎ­ˆsvΗ ^#"Ρ½^Ÿω¨δP6ŸOh4PΝΉ$?Ήœ/Z0r-μ™G&^ΰά΅28*’r’‹Žήτ{΅-OUuΕΩQKΚν΄=΅zWτΖK\Έ–ύœZCAκ[,…•Syχ·I~±έΙ«Ύ• T2^ζβυ»ε™n\γ¦ιώh΄.Up7_ 4μξΥΘPBγ T.ΠzχǞWliŒ„‡…ί}S.s1ά½sΕτdͺ¨Ϋ\ˆK-!J‰ΈΤdΜ¨¨jΪ§„€D>™1ƒΖM›b4™3·g<Μ¨Δ₯&η_p>LœSΉΗ IDATv³qχq.\&6β|Ϊ΄φΨ8ΆΕ·E<›ζ/bwh±q\>±‹mDδβ)εprΠrαp0‘‘QDΖ₯θ|Φi—Ήqωχεl8Ntδyώ\Ί‚ύeΪς|ƒ2X98Q6ϊ‡ώ½N䍳μ^±œ?£OιδΕ M"Ω΄x5G―Fy‰cGNcŸwςŽ₯θΪZs›(yΗ–g}+΅ζ™:ΧΨΌt§nΖv˜U«χ“ΣΣa׎nmωuρΉEtψ Φ-ό‰Λυ|yή­o9<ŸyΕ–αςΆεl<Ntτeφ―\A°…'Ο5(Sδm.DiWβC‡Bˆ4 *ΗϜ₯‘‡jϊύ=cbrzλEU9~ζΜ=Ÿ”T"v|Κ„―χ‘tGΛ”±Z&Οzƒzω½©Qόύγ–†E“ͺ«HεΖ>ŒkEC»1ΣΉ³t1+>@x<Ψκ~`ύ| ΄‘ω«hδ=γ,£Ζ_ρΕΛU²,οΛω8JyΌΊ4βά’±,»x›ͺž όpM¬AiΠ›Q/~Ξ7βGEOΏ‘Œθt‹_'ΌίžJάΒ…Μ³’ΘT\½†3½iΌλk,…”kyšΫ$―ΨtyΦΧ€οΈ‰D|΅)CΎ§†tԟv—φά“RŽ–#¦3dΙ|Œ[ΝMcyͺ΅τγ£±>θ ”άδπ|ϊε€E}ϊ nΜΩoΖx1›*žτ{Νlΐ\Τm.D)§΄ όBέρΚ(€Ÿk!„Θ&hW^^Ω/ή}ίΆœœ =ΗCA\7μV/Ξ:+Άx΅ςίωQΎ^ΥΝkx―υ}Λf !Δ#!λk~ϋ5σ€GKˆΒ£FM>«Q³€Γ(q2UGρ8‘.,!„Bˆb"‰–B!D1‘‘C!Dι ­Ν€EλJ: !„(R£%„BQL$ΡB!„(&’h !„BI΄„B!Љ$ZB!„ΕD-!„Bˆb"Λ;QJ\ gΗ±#Δ$%h VVx7lŽ«ΑPΜ‘ !„(,I΄„(%v;Βs S«zυνφ|(;Ž‘Ÿ‘K1G&„’°dθPˆR"&)‘Jφ$§$θ‘wt(pοΧ3…°β­Ύ)Ψ J½ώ οtŸΔ֘Ό£‘ι,Cύψtj.?Έx³ΕULu/5ςkΛ|ΜΫGˆ"&‰–₯HΒνΜfsƌ‡Ρh$!!αώΜWXσvW&n‰ΊηζΜ©μύ΄ƒΟ`*H ΪZτ XƘfVER―bW”ρ>ju/V*·6MbrΦί'i!ˆ$ZB”"j_‘ηC4xGeIΰ2T°Wθ)Z-J±žαΑεOQΖ[λ^"ΤŽ‚ρžΝ>BœΜΡ’1«i}{χΡΖ³Mζφ .2dΠ0PUτg:vθ€ωaς,ΣYGΝEΫ―ρλW°σt$8ΥΗgθΆp@1%pψ{ά°†‰­-Po‡°uιB~>C„ΡCσ|όξ 8'…°eΡΦμ=K΄jGΦ=:¬uΛ¦½ ›#±"`!ΏΏ ϊΖtιY3Ϋ§;5ρΏ-šΟͺ=!ΔZΊΠΨw£{7Ε>§€ŠjψvΎ·’]‘ρXWρ€Χ¨·θZΫ6{Ό-.δ]·όβzΐ²ΤθΏX0ŸMά}#Ί jΗ­yAԝ;ƒN³§#…jΗτηJσΊ/ΡkWtώ6εjΆgΠΈžX1ΕΏγ†Ιέήζέ>©`>Kΰ¨9hϋωΏ6m!±XWiC―Q£ΣΪκžfΝυ9PbΩπϋcIήχ*/ΞΥα1pέYžυwγNώ±ηΥ~B<ξ€GKˆDUωnεwLš8‰χ'~€ͺͺœΏp!ƒ† ¦'Y³ύύq―μκCφh™.°vQ0Ξ―ΝδΫe‹yΏmΏΞYΑ_)χΖ͞ΉSX~΅#ό—8ηcw“͞9“Yy³£g―dωάwiwϋ'¦ϊA„ ¨7Ψ:k&Ώ©/0ω›•|ύΎ©Ϋ6s:cμReόX}ϋy&Ν_Ι’i=°ή9“/Έ‘s_z›ύ[ώ¦ϊΰY.ΗθWY>γŽά~ΐΊεΧ•u‹m_Νd‹)½¬I/’΄v1Aq9Τ °ν˜ΓΊΰρζlΟΐΧ2ˆ€w&π“Ρ‡Ι Vπυ„D]ΐϊσι•0]dύ²ƒTθO์¬{™ΐι9΄U^ρRž–Γ¦»Ά †-eνΟ?σΩKnΩί4Τ‚Ε^ ί3!S’h QЍ€F«ΕΪΦ–½{ƒ?~C ΝL²fωϋ£w5`2›‹`ΰPΕ΅CόΊbgηB“ξ>Τ»sžσζμ{EξαΧƒει2μ5šΉ;βθZ‡O»  fΛ‘ t›¦nφΨπ›―PωΨΆ‡™Q#φ±λ”>{ΠΐΩΗͺ­ισJ+l3ʍfσέ‡t¦ήǚ޼ώ’“A‰Μ₯r•;τΕχ)gμͺΠΊ_?Ϊχ²λDςΥ-ΏΈ¨¬Θ}l?ζH—Α=ΣΚͺζE^^”Λ©”BΆcF ξޯ󂇻JOΣΕ»fS=όϊxRΕΑ·ζΎ<γ~“Kaw³7ͺŠW7π2ξeΧρμm•χs  ³ΆΖR« ΅΄ΕΦΦk‹{zθ {A~Ο„x\ΙΠ‘₯ˆͺBίΎ}Hˆ‹η—υλωλπ΄Z]f’εμβŒΙdΚάχαθp­lΘό΄₯XYa…γ=£™_ᚢ*έ\΅Ω·‡‡qMS•w?―)φΥ¨Vώ—š0• η†*5άξgιZgν­΄γ―]",駆ϋ±,£ώΖdŒ†fΔ™Α1ϋιΞ.ϊ»Ÿ-ά©bH!ψzLIgξu3EηΧƒ΄“)ϊ αΪ*Όδr· ,\+㬽~_)…mG\3κ^)3Λ2eΠΨ;£·Μ8  ––`4šΫB‹³!K[YU₯Ί!…½7²·UΎΟA>Ε {A~Ο„x\I’%D)bV!)%•#GrζΜώ=}­VΛ,*œI5™³ν{E‹V ͺωήή3&3(š¬οœ΄Ϊtj«Ήχ<¨9NΙWζή¨* A“΅D£!3ΝPU°lΞΠ€‘4³Θr΄Ξϋϋ’¬Œσέσ}ΙfuΛ/.λZmΞC…mΗάbΠhςœγdΞ›9ηΆΚο9(@2_¨Ψ…x‚ΘoΏ₯JΪΫ֝”$ζ̝KΛ–-™φρTœ zŒfSΆ«s|Tμ0θ-Ήvρ2Ω¦ΐ/sώ28*=π½VοŠήx‰ Χ²' Z—*Έ›/vwr“JhœΚnZ΄• T2^ζβυ»Η™n\γfϊξZƒ;υ‰θυϊΜG%‡²Ή|4Nfi)—Ήn‰ήΉβMͺΞ/‘Υ» 7…q1ωΔυ`mΣ†ηž gΣ_8y#†¨°CόψCPŽsΜ ΫŽ…£rωχεl8Ntδyώ\Ί‚ύeΪςό=m•οs ”ΓΙAΛ…ΓΑ„FF—}»bW± ρx‘‘C!J •γgΞΘΓUIK‡bbr~ϋWT•γgΞδψIΙκιAόoB0“Ρ "IΆ°£rƒφŒžΡ–ε qA½β„χΫS‰[ΈYcV™jƒ«Χp¦7­CΛΣ²d> ƭ榱<ΥZϊρΡXτ €ίq‰ψj!S†| N ι2¨?ν.νI/׎vc¦sgιbV|8€πx°5Τ₯ύΐϊ9ΗaQŸ~ƒsφ›±^Lΐ¦Š'ύήF3(Ψ*¬υΙ'j=ΖNδFΐΧ|4d)TjˆO¨σοΩφ-l;‚R―.8·h,Λ.ήΖ¦ͺ'?Bk²·UΎΟ Ν_@#ο?`5ήψŠ/^Κz|Ή’]ˆΗŒ*π uΗ+£ΠYΘ'!FΠ ΌΌΪeΫΌϋΎm99zŽ₯‡‚Έn,Ψ­MœuV lρ 5j*VQ<ΤΏ0~ψ_t\6Κ—@Ά‘ΎΨΝkx―΅Eώϋ !ŠTΦΧόφkζI–₯…Gš|V£fI‡!RJΨEΒ-+bgU²]:Ε{ί!DAI’%„…–ΘρM?sέΝ“†UΠΕόΓͺΐ ΤfyJ:“„H’%„A‹EςY6¬c^δmLVŽΤhя†Ά¦¬ΜQB ‰–B<Kκφψσ{”tYhk3`ΡΊ’ŽB‘NfΏ !„BI΄„B!Љ$ZB!„ΕD-!„Bˆb"‰–B!D1‘DK!„’˜ΘςB”WΓΓΩqμ1I‰ΪΏ‚•ή ›γj0sdB! K-!J‰ǎπ\ƒΖΤͺ^½@ϋŸ=ʎcGθgθRΜ‘ !„(,:’”ˆIJ€’ƒ=Ι)Izθ άϋυD2%p¨ŸξO-δρ!¬x«/G v“o!„Θ‰$ZB”" ·0›ΝΉ>BBB3fF£‘„„„”Aƒ‡qτθQ–.CΝ+ 2]dWΠ-*莰σPάƒ%LjΗ Αψ°•y”δRgE«EnY(„x2GKˆRΔ¬¦=φνέGΟ6™Ϋ/\ΈΘAΓ@UΡœιΨ‘ζ<²'cΘ‚b›ςZ·pwξ%ϊΩNΨgd ΖC|Ωg6.cψΣi/jΜV>ψΝζD₯G°?–δ}―ςβ\ΠΣεN[-`Νή³D«vΤhέƒ‘ΓΊQ7‡»'«·CΨΊt!?Ÿ!Βh‹‘ω@>~χœ“ς(Γt–ΐQsΡΌξKτڝΏMΉšν4'ΦΜcρoΗΈar A··y·Oc*˜Ο8jΪ~~Δ― d[H,ΦUΪΠkΤhΊΦΆ½/ARΟρΫ’ω¬ΪB¬₯ }‡1ΊwSμ•XφΌu»'²|ψ{ά°†‰­-PσͺzμΪ~݈_Ώ‚§#Α©>>C'0°…ƒ$kB<Α€GKˆDUωnεwLš8‰χ'~€ͺͺœΏp!ƒ† ¦'Y³ύύq―μjn™V §vώIbΣΆ<ηΥ†*·ƒΰˆφi)εi9l*½k[Ρ`ΨRΦώό3Ÿ½δ†FfϜɬΌΩŒΡ³W²|ξ»΄»ύSύΰΎ’Υhφ̝Βς«ῌΐ93Έs}œ””aΊΐΊΰρζlΟΐΧ2ˆ€w&π“Ρ‡Ι Vπυ„D]ΐϊσ¦τύ/²~ΩA*τ'pι\FΦ½Lΰτo8rοp©Λώω±ϊφσLšΏ’%Σz`½s&_ώq5·:ί[§ΔΎvQ0Ξ―ΝδΫe‹yΏmΏΞYΑ_)kz!ΔγI-!JΠh΅XΫΪ²wo0γΗO`θ ‘™IΦ,τLfsξÁ‰°cŸ‰νaγμ…Wυvώys"PΠY[c©UΠZΪbkk‹΅…‚Μ–Cθ<€7Mέμ±34ΰ₯7_‘ς± lΛ^²Ή‡_–§Λ°ΧhζkZ<ν‚Ά@e¨Έ{ΏΞ zμ*=Mοz˜MυπλγI{ܚϋςŒϋM.…έΝ^άΌϋβϋ”3vUρκ^Ζ½μ:žœ=¦θ`60Π}Hgκκνp¬ιΝλ/8tH5η:g;Ύ€±»vθ_CWμμ\hέ‡zwΞs>’`-/„xοΟ¦«[Ζ›~<ϋ|Θo»ώ₯ŸG,Πa‘K%9ΛθšρΚee―A£Υ|7aΊTΑέ|”Π0ž5zͺΤΘPBγ 4sΛήs₯Υ»’7ώΞ…kfΪTΥͺŒ‚3r-μfͺ₯υ$%^ΰά΅28*’{χάw κQ"Π»ετ²w³Υ©XbB< δγ—₯D\j2f†U’ωdΖ 7mŠΡdΞܞρ0£—šu.’Κυ=;ψ?·ŽtkSͺU«¦?žΖ·s3ƒ·s, ΠΊS£r"7oζtD,‘—πύͺέDgδJ9œ΄\8Lhd‘q)(vνθΦ6‘_ΐ‘+QD‡Ÿ`έŸΈ\Ο—ηέ²ΏŒ(N^ΌΠ$’M‹Wsτj4±‘—8vδ41 ^FΑ©\ώ}9N†yž?—`™Ά<ί Lφ˜ΪβΫ"žMσ±;4‚ΨΈ.ŸΨΕΆ"Υκœνψ¨ΏBd%=ZB” *ΗϜ₯‘‡ͺ’6 “σΎͺΚρ3g²R2_&hηy<:N’rΆ(”oαƒη·Ÿ±γοΫ4kγ„χΠ7ωwφJ&\ŒN_ŸŽύπό΅mιϋΫΠόΥ4ςžρ–Q㍯ψβε*΄1!Kζ³`άjnΛS­₯υA︞β„χΫS‰[ΈYcV™jƒ«Χp¦7­Sπ2 άhερκˆs‹Ζ²μβmlͺz2πΓ!4±²v*v΄3;K³βΓ„Ηƒ­‘.νΦΟ½Ξ/e=Ύ\ΡΗ.„x"(­ΏPwΌ2 …|2βaν ΒΛ«]ΆmΑΑ»οΫ–“3‘ηXz(ˆλΖ‚έςΕYgΕΐΟΰQ£V‘b}δ™Ξ8ό=nXΓ{­-ςί_!ώY_σΫ―™'=ZB”5jςYš%Ζ#ηΙΉMβQ$]XB!„ΕD-!„Bˆb"C‡BˆG“Ά6­+ι(„"O£%„BQL$ΡB!„(&’h !„B™£%„(uΒ„ρηξ?IHH(ιP ν©:uQsΎσχBQ”;Ώ₯ej׍ƒƒC‰œ_ˆD-!D©sκίS<άsXZ<š ‘ž?žgŸ}ΆΔΞΏ}ΗvΌΫ{—Ψω“’’Ψ»w?­[·.±„(-$ΡB”:εΚ•ΓΩY₯₯eI‡R(ρ ρ%Φ#—Ρ“URη·°° %%9…xH’%„(•Υ$+«’:,Ισ›Νζόwβ !‰–B΅„n”‘`•ΤωM&Sώ; ρ„DK!ŠKI߈±„ΞoV₯GKˆ ’h !D1)©‘»Μ­ΊBH’%„Ε¦€†ξJΛω…’h ρh3%pψ{ά°†‰­Ν₯ /…π«Yϊύo Δ\Ύ-Ί`tΟϊTPŒψ’ώ7έΠΊρκWKZG €υ+fΝgΓΡk€”―NΫΧΖςVηZΨ(Ea‰υh=δω»vλ ΐΖ ‹("!ž\’h Q"Ψ>υUΎ8˜((Ί2”ΧΧ QΫnΌφΚ³T΅.’wϊΒH α»ρ3ΈΡ{.γZ•γα#Q‰?ΰϘ ΌEjQ>¨Ζ`ω²θ_Μ7 I:³ŽYŸ…nΌΧΖΤ;ΔĘh6ζ{>|lΪAŠKkmz‘l ψ„ί,ϊ1}‰Β#ΰ“i|뢈э­‹(Θ’)¦ΔΞ_ρ ρ[πQb4T}%€Ÿ~ώ…5ΛΏaϊg°:2‡w&}Ηι€’ŠI%bG uιΥ’(’,…r-^ΓW»e;"Šμ½[©Πމ_ΞΰηκΰlοHΥΦ―Σ­ώmΜΎŠ @!:Φ'ƒ#eΛ–M{ΨΪ`™ώͺ§Ζdη?.ψ ξΚSΞΈ6ξΕΰtm=̝"ŠQ-©―,Wζ«(βB€‘-!JŒ‚Ζ[Ϋ²hmΛRΎ₯cλΉ‘}k 7?Λ¬ξh5ρΏ-šΟͺ=!ΔZΊΠΨw£{7ΕώΎI*ΡGW±ΰ»ό{ι:qZ= |F0ΎΏ}‹Ώ½Ώεσ•“§dΝξΗ,σXίiEf9Œ[ώΪΎγqѐ649j.šΧ}‰^»‚ σ·)W³=ƒΖυΔϊy,ών7L4θφ6οφiLb9Ύfίl:ΒΕXΆϊΊ<Ϋ<Γ½\xC-ΎίΊƒ+{αn:Ξ·£fπ?η‹—«ώ_ΦLP#&NΑΞΑ.­E₯d<»ŸΏR›βΩΠ&Ϋρ©ΟrΉb-jΨeλ*Βέϋu^πΠcWιiΊxΧΓlͺ‡_Oͺ8ΨγΦά—gάor),L&LŠۊφΨ9ΊQ§U'<«₯­πΨΧ’f…Λ„\H]=ϊ,gFWχ"y2έΨΕμΟwSυΝQx;άν‘²«Ω˜†΅+γκVƒ†/ ηΞί±›*¨ͺ9η.₯ηΗΊ’τ-!J³Ι ::ΐtνaI§85܏e{“1šgΗlΗΉyδ'–ΔΙ°H’SIMJ₯~{3ƒm«¬bίαh|^¬@θ‘#άi4€Ζ6ΩΟwσ©Ž΅qΚ6l¦ΓΩ₯RfBdY¦ {gτwΘQΚ`i F£ νS=ζ5€‘ΨΦ=^φ₯…›MZ“Φ½S η#βPq,’ω_ F`ξ_ισ?f΄―”Gβ¦ΑΰβŒζΟxΜΰPΎ"εβˆΟ’“˜βcΉm[‰ςρU‡{ώάS ύ"nE<Πy {ώΆΟ΄Νq{AΟ/„ΈK-!JW.]}kτZ@UΑ²9CF,ΛΥzŠΞ{-εN'ζΛk™1c#εzŽΰ½7«coΓΆO'q@γ‚§WUVν=HŒ·ΔΡψ΅&dοΟRINNK+ΚdΫA«½'}ΡhrN”4N΄ysΊζχ΅?0zΗΞbB[G¬(c ΙIΙ¨P$‰–w”ΕΞ&Τs2Ÿτς οkΝ\»ަR5 ­R›j‰›Ή‘ΨUL\:sͺ΅Α½ζgAΑ›7‹ζ„E|ώβŠKˆ'‰$ZB”"jΤΦΕπTοζΨ)€Αƒz”ˆDτnyΉή 9ΙEGoΎx΅-΅΅€1ž”Ϋ·BQpnӎͺ«ςWhG5’{φξ,@ωφξ;<Šκkΰψwv7½‘%€H“ήI₯(UE”jEDQμΨλ+ˆ(E)‚’…ŸJοE‰τ’ή“-3σώ±IH HΨEΞηyφ!μΜήΉ3gfημ½wοΪΘΩbΖ|M{‘ΰޚΎcZΠ&όyF­έIrTo0cΆ€‹«kω$YY±πΨUηiήιW%3ƒ @1Έΰξι†!v3ίnΦ¨ί’.UώΘΤ3θτb;|P|ΫΡ£έl¦}΅’FOFQιό:ΎZ›I»±-JIΨ ŽκΒ+―ί:”.H!$ZB8ŒŽfΙ&33-3‘3mεΗo–r¨Ζ0ώοΞ܁ξθΥϊ>Ÿ6“ZOχ§I0€ž:Μ?κmtm\(aq Ζ;ωOvK`HώšMIP-wΉI‡ˆel^–Al£^4ΏlVNί @Œ‰HT!δ*ήΤ›Ys¦n­F€1?’qΔClρΔ%˜ φE±ύΙόqσOηχxχ*ΗieοXΒ’ΓIXΏΝΥφΒΏ-~Žξdώώ{Ž„LίͺMθ2ϊC†·ΙΆBρ‘ύ“―svςgΌ>|YΥiΣužlW^ΣZΰψy¨d-!N-!FγδgιΏLΑδκM@x=Zάυ:SξiEh^7‘βOΗgή#kΞ,ζNL:xUO—acR IDAT.+ΝΤx £»̌·G²D ₯yί§Υ#όD ‘}d8sf£ΥΈ–x‘MΈΦ¬C΅δ]D§θΤΊŠtCOb’ιΜ9“ŒΥT‰κΝz2ξΡ6xzςΏD§T§m„+θVsfλΥίΙ=»ΌΓΪ.%¬P©#?hΕΘVQ|oγ7fρΐUΧ’d7κΜπyc³b/Δ–S„ΈyI’%„CxΣυ­Υt-ڊgzŒώ˜£‹XhΌ•α3σΎrL»G&Πξ‘‚+Μ’νΕ’¬WŸOo"[xΩj£„Ά Uε…μٟBŸ;ύQ •oη5ž£ Ύ¨2χςχp/oM/<%€NΚώέ«’§B04bδί–Ύσ78Gw½]νφc.Δ”sM„ΈyΙτBά44ΞμέKZ“Ž΄τ)¦΅ΚA·žυψgύ/ΔhE―ru›>Η/λ‘nnΤΈ‰ήut]wΘ£ΰ{–³ηΞ;Ί*WmβΔO»ύ·}š5kξ°ν αL$ΡB8wwΦo€ΑpγχσΉ±[γ…ΡhΔΧΧΧΡΥΒ)H’%„p:ͺͺ‘ͺŽιφ*/aaaŽ‚Β ΘτB!„D-!„Bˆ "]‡B8‰'NπΫoΏ’‘‘Y¦υ}|ΌΉγŽΞDDDTlΕ„B\5I΄„pώy˜ϋοΏE)Ϋp]ΧΩ²e«$ZBαΔ€λP'αααA`` aaaezβαQΚ,ο7υ(sλΗ„]Φr.³/ν(¦L5šωO?Μδ½9WUΌ»œηο{…΅)ϊ5—%ŠVθ qI‹–NBQ\]]ΛΌΎ««k­_όο­˜°ΛR°dόΊΐ’gZ:Α―r|α(^=0³_lʎΌΊ* &χJTӚ^Cεή†~ωΏ‰¨₯αηo—°fΗ!N%d’ΊψΡ€;z–ΑΝύΫ‰Ζ:<­ΡkΩ³Μϋε.ήνμδυ7§xοBPζ±Y₯ΏFΑΰꁗ—7…nΩκQ掞‚ap/’ΏŸΟΖγ™ψά…‘ΟυΗcύTf­;Θ5Ζχ<Λ‹5ΓOΡI>°˜ι α―S±€CiάsㆴΔ_=3š΅sΎδ»­oσ’r«ΌύB[βΏϋœ+χr2UΕ+΄>·Η“Q‘(€-z#[²ΪπdS £@]}1zωyδ0my›]ζpgΫζLcWθ>{σ^ͺζ½[U €Z½2-~#Ώ8σΐ‰ŒΏ³ †μY7s‹·D“κZ…f½gΜAόόάΣμοϊί’{c5³ϋΣ!LΖ2χΩP\ΠcώΗgΟ-ΰ·cιxԈδΑΡOsχ­^(κQζ>ω†/εεΦ'˜;z Ζ!χώγ|~=’ΑθωΨ Œhˆh‰»™?ωKV‘ΝθΣ–‹c8°,=y &OcεοqΪ”>#;’0u#υ§ΌOΏ4ώXZ|,μθ Ώ¬ω›[{£Šα’ν·³7ηθ)k?b=-§O’oXΑσ«œbvΕη%θYΡ¬™9₯ێ’¬ϋS»]?{όκ{Ϋχ¬Δc θE[` UΈ£[ΎYϋ gο|j2ΐF\#9…„Έ™¨'ψaώοΤ}βSζΞzŸ^™όό ,³υδυισωβ…Φ$~?«€‚§weυ}ŽΏXΐW―wΑ²z ΛώΆžΜ–)oπυΉ¦Œš8ΉŸΏΝ#½αt “WXθ:~& η~Ι;t¦IΈξέΖ‘M[±ΆΉƒΖnΕΤO1bPϋŒπYϋΨΈ"οοqρ†}%²πΝΣ9ΫιUΖu«‚QOeΗ΄7ω6³3―L[ΐμwϊαρλ‡|ς?W"£ͺ½}' yCx,±λ€FσφρΠ3Ω±f?΅™Δά9SΣψ_Ώ?ƒ½E}AT=Αχ3·6θCΎš7‹W;δ°ϊσωμ³ϊΦNϊuϊ]Ό>c_ΌΪλ†UQ‹Wρe%°α³Y£ζ–υJwrΎŸΕΖ4ϋN؎” ;=~{ΞΦ¦us«oΉ)˜]Ιy©'³εσΧYΧ’1Ÿ.ΰλ)/1soM\OΌNιΗΈΈσ`ύμGNΑΏykjŸΩΝΎΣ%$ZB8‰ςkΡR9Ήt,ύϋέΛ}ύξεΎ~ύycFξ2j]sWέPόCn£OΧ†hjCϊ>IΐͺΆκE§jqœ:cγεVηξŽjHυΰBv#2"…3η²Ρ·°z—/}DΛjA…Χ£υmU0©*ͺbΒ«RώAU©ΧΆ‘5sǝY³i'΄οԐ’F’iΩ1μ_ϊ [΅VDέζ†–σΆͺԞ·ΆΓ³αώάύzΰύ_H/κ>¨€’Η³qς{¬~œΧΎ /τδ­¬ΪY™ϋνMύP‚nιΚΰξ•9Όqξν;P#z;»“r“”£;ΨgmAdΟόb«w{˜^ Βπ¬A»!CθhΫΖo‡Šš½^'ΌΫ0ϊ6 ΗίΏ ΝολIΓ¬γΧΠγ·σ۟ΑτяΖaώE΄γ‘mρ*6Β%”•Έ ’Ο#ύνeՌbΨƒQψδŸ%Δ"—υδQNWͺCm«K³Κ-fWp^κI[Y³Ϋή€EΥό+7ζή'PύΰOόοLιΗΈψσ`‰ΉuSκp‹ίi’O”γ—*ΔMKΊ…ψΟ1P΅ηxήΉ·zώ')7ΏΌΫŒ‰°*!ωΟ»ΊΉa#4οΎ¨Έακ 6›ŠŽψ½Λψϊ»>“H†ΩŠ5ΗJ£.jμYΞ#Έ'Όπx"Sƒώ<υ“ŸΞ†ŽχΠοώ^΄κ‰˜od§)ŠWλaœ›.Χ0η¨xΧκΐƒ―¦c%=@AΙ8h’ξ€ω’·•³+ίδνSV΄"χίHάϊ‰LΩʐ Ν­’zώgrώδΟ'ϋ2/wMέfΖVΉ%‘]ιPc1Ϋχ$Σ³»Ηvο%«ιpšyjήq ½ψΙΤ₯5*[Ψ›Βεyƒ‰πκ•σΧUάέqΗ†Ν jr LΤzρΈΉ†Χ ̘Pδž”\ΦYbŒ5Έ·ΚΕΟΛ.αΥ 3Ζ–‹ά½'-.kΠ­_Ρ°°ŠˆYΩΟK[ΜΞ"Έ;όβ~+5©ι{žSηTTŸ’qIηAšAFΐDh°…γρiθΙ8-qM$ΡΒI”η-“w !‘‘—ŒΡ0`4^m0y#ΡNΟϋο―ΐ§(^z’ξ)lψθŽθEί.1Σώ‰ΟiΪg?ΏˆΙcVlμ$^θΰΕΑM»πˆz‡[ ½λδ&…}#pχͺD%/—‹u #ΔpžSgmdOΞ\|‚ ρΡΘρv)ώζ§§q4Ύκμδ»…;ΉύΉvψ)€ƒk+›ό- δzŠΙ‹/<’"XΌm)]λ²koΝ5Η³`±—n¦Ψ^₯"Žq‘(τ[ΩΕη9₯•u £ρb2Xl,ς³Ω ξΧ“ €jΕvIΚ=fWp^Ϊk‘ΰ*φυK;Ζ%ω+Ήγζ ζ3:%BˆHΧ‘’HYΡ‡9Τ•!t AD8aAF,™φΛN¨ν'Ξ•p)x†·¦ο˜OψdpΫΧξ$9s?χϊΡ‘c­K’Šά€0$―Β7bΕ»)mf±mυζό.²ρ"ς‘±Œ;Œπ]S™±Γήκd¬\Κϊyβ³ Ν„zcB!¬}G"Žξbί±=μOjJd³‚i–˜31[c,§9γJhX₯+Ί C*b;ΝΙΨ‹ΗM½pžΈβΖh•TVhBΥ3œŒ)PVάyβ …€ˆXθ—ΉΊΊ‚ΕLαP‹ωb—™s–˜Bυ«ˆ˜•±J ͺi'8vζb₯τΔcK«LυͺΖRqΙηA3f ΈΈΊJ’%™$ZBόηθh–l233ΘΘΜ #3“,Λ•ίΙέƒρNώ“έΕ’xα(›ηΝ¦$ϋ2%8Š»š'²rΦ·8—Ljβ)ξ=BΒρΝ¬Ψό'b“I?ΞΡ‰Έ ΨΘώ Ntͺq}TJ]†¦ΪΑΟyeΒ2vDǐœ–NJάq’ΟeΣu‘‘J/ž~Έ*»Ώό’mΙ:J`z΅Ngε΄™l>OjZ<§ύΖ†ίγν­‘‘tˆψ‡ΝΛφΫ(’ζž…o±§7|͊?cHN>͎σΩκΙŎκ/f—BΪΡ©ήyVΝω‰?γRH:³‡Είn!εŠJΙ-+Έ=w4ˆaεœεΎB™έ,Y΄1?ΑQO‹@<ςwKΑ7(c⠝Vϋ‘Cqι€ΖμηΫΕ›Iш»Ž­΄διcV¦ύφοΘ=²Y=k{Ο&‘sˆΎ\Ζ醽θ\ΥPκ1.ν<°ΌxβLϋJ’%™t α$|}}±Z­ΈΈ”m–D‹Ε‚――_K4N.}–ώKσώŸ;aιhί+ͺ©ρ@Fw˜od‰JσΎO1ͺG«”`Ί>ϋi_~Ι€ghυ$<κIήΎ/ύK¦3ηL2VS%ͺ7λΙΈGphΖ$Β: £κ~΄s­Υw&σν‚εΜxm2lά}ͺr Qέ"p/ρ.h$Όη†lš/fl‘αKιψΜ{dΝ™ΕόρΓ‰I―Κυι2’Qξa ‘}d8sf£ΥΈ–x,Ϋ₯CiΖΡc™{2Ο‘ yυqZζα*#₯2½ž{™ψΟΎδGΏ‚ΰ&τ9ŒŽ§Ά\فPBι1φe.Lώ‚7!MθΩο.κύuΤΎ\OΊ<Ά‘ΰo ΈΦ¬C΅δ]D§θΤΚέaΕ“ΚΖL|b)žuθ2ru(„p ΡΡΡDFΆΓέέέΡUΉ©εδδ°mΫΪ΅kWθy‰sψ8·’β#‰–Β)X,fE!##ΓΡUΉ©ΉΈΈΩ*"ρqηVT|$ΡB8 MΣΠuέ‘uψ;f'Ÿώ:o·J jω-#Ί;΄>Χ›¦?„ΔβSšο7ύΝ—?ξΓ¦i λθ:θΨλά΅em^ΪΑΑ5Ό67z|ώ늊$ZB§‘ͺjώMΡ,Ά>ωu8ύΊŒΐ¨YΆηζοΟΈn ¨ζ_ΟaυΊžTU-q™#γS›ͺ1uωή}¬ ^ξn¨Ί‚MM‡΄,ΞYΛψ‘QŽζ5Ή‘γs3(*>’h !œFIŸΦ―‡οφO a­fT Ί…S™{y΄ΗxΦ^Ȋ?¦πTΗi­Ϋυ’ι%·˜8›cη“©V ƒAAΧμI†Ÿ—;›~?ES0Ϋΐ¬*tiZ ]‡=qT|ψi变Ν9—-swwηξήχTaΫΏQI΄„NΓ‘έ1©ΗΨpδk^~p ‡Σאl9M-―φΔΗΗΡ)β.ι’Α±ρ)Κ惧ωpαVΦNt±nΊŽ¦ƒU‹MΗͺ‚Υ9+EqΊ}(O΅oII‰¬Z³‚ŽQ¨Y³ΦeΛOœ8ΞͺΥ+θέλn‹(αζ&‰–Βi8²ΫγΛ-ΟΠ§Γ@R΄3€ZΟRέ³Ηγ‘žžAηzc΅X―o…Τ™?fK²Ε„o•Ί΄ν1ˆA=κα§dςλ{Γω閏™τ`Fυ<λ?|₯nCωΰΉΫ 1^ΧCP¬ςŽORR"kΦ¬"²}$^ΡΗ8τΨγ΄«Zo“ «ΥŠΝj%5;›ƒΓFΠxφWDΆ‹dυš•τμΡ»ΘdΛ»‡—,η·ύLjΝPqσ«LνΦύύx'*_οιΣ―γυ%‰–Βy8ΰ>žmΝ`φŽy’οxNfο"ήrŒvΓΨtψ{ZΧμI¨gνβ «§Ψ²-‰J.qlή›NΫ>(εU1½ΐΏŽΟoμ\σ ιΌ4γ7κίR­λβζbΟp:?³°Πzc?]€Ρ¨Π­U^~Έ3 ©ΉΣΨ‡œρΦΫλρθ=Š·žmIuo3±‡60oΪ[Όϋ k„§’`2)Œ†άX€spξG|“}χƝ„©΄h|V­^A‡Θx?Α<ΌPYκΩ΅|8~qΝ†1zβ›46‘zb;Ο‡€”έKu―/I΄„NΓέ:‹χΎG«Ϋ:βγεΟίI«q»ƒΥν‡~eΦΓ‡±θ&Ή”νίΝlNmŐϋb˜Ήi'ΙQ]ρΟΛ΄ΤYπά—υ!ύΗ…όv, χj­ιχΔ“τͺγ‰RΪrrίυ3,}ώe~ο<•χzη&rfφMyœΟυ§˜1¦ΧkŠJGv»ν?Λ»_o£{‡fΤ―FtLM"ό˜φςL0\ΰζbΔΝdΐΓΝoO7S³PUΝ>`>oτx~]΄‚ΤNoπɈ¦­64έDx‹F6£ž›ΟΪnq_Υ‹ϋ¬cατšO˜| !/|ڏp-‡βΟŽλ―Όγ“““C͚΅XΧ¦=Νπ4±Z­θš†–ϋΠ5 ƒšf3ϋ‡ ₯{\,~ΩPΈ.z ›,$Ίήf½ά‹Uƒ€:QάSWΓl±’|π;f-ΩΘί§βH7s[χG3¨ώZήu‹Œ•KΨx4 %¨wx†‡[Ψ―“¬c¬z?n&Aυ$¬ΕΓΌ6Ά ‘ζγl˜3‹eۏ‘ζFγξΓ5 ώ†Όγ•wΤ*φΌ–ί:B8ΌOΙεωHʌαΥ]:―«‰¦_ό4~2ρOvZΑMr,s ijΝύϊ³|ΛW•£g“9z&‘ΏNΖ›˜N|rœΊ€ƒ’;^Χu΄τΓψΗ‡ΘΞ Ρ³ΝXm*ͺͺb΅da οH§π“μ;–y4› wEΑf΅b³XμZ­¨6ͺͺ’©*nΉλY—Μ?Ψ}Θ…w·Η#+‹MEΥTlV3Ωf+š^~Ui>ΰe>·”…οuG[7ƒΨς―“Ÿζξ’κ°‰|σνΧΌ}‡•uΣ—pΐ¬£kΙlϋβ}]hΑ³S±xζŒκΫ„RΩ5γ–›οδ­ΩKωζγψlžΔη‹C+°z·<’h !œFyΏαeYxw]_noΡƒΧ†|ΑψUΌ»ξ^’3cΡt[ΗpονCI²ΰ\Ξ!ϊtηΘω=(ͺ+­«χ)ΤErΩ#ϋ›wͺ΄νPC@:άς/›ΆGΝ_ΗΎOΥοJχO“?-‡§“Ί‹-‡sΚΌ4‚Ϊv""z7ϋ“μυ±FοeΏ΅%νσo7⍼,wηocέΎs Όϋv¬Έp2>P ƒPΠQΠtϋΰwUΣ±i:ͺͺΫΫ*t0 ˜­6<έLωεjI $FεΫeΗPΣ*¦—˜Oσ±εL˜ό+¦ξΓθ`Ζ¬^cq½γSP^’e΅Zνγ³lΆόD+/Ω*.jΒβ΄pͺ…hΒS­ŽτhA%Wχš·U+•˜Ψ¬άnYj=FrO]_Ε‹[ονEγμSœNPΡw°~?}G=@ΓJ&L>UiT'=y'?ο gΐwRΝLax¨W8mΫK’vρϊ„Št !ώ³¦l~œζ ΪP7’)±ζΏqηkμˆ^ΝK?ήNΛκ½πτv£ax[v₯,Δdp£Ί[+&lΓGχoΐl.ιΗyu2lb·1’WλΠ΅J΄ιP—9kΆrΊΟ"ς?š ρΑb³ί„ΜT¦fΈ…- iΉ₯-ΟέZ`k:Φ\Θύ)tνκΛ‰Θn1‚†.ΊΓΗMU4ϋΨ( °ͺ:UΓ€Π-*©™6tLwwCώίΊ¦ƒάέ\ˆML§f•€‹ (θhEΏΣΠ4μ_cΜύωCρτι՚m?Mgy›·Έ»ͺ“Œ€ΏNlV+Š’δ}΅37!ΥΠT5?α*–Α~AΨη9+j£JܞoXόγ6ώ:›D¦Ε†%ΗJ“ΫσNnαU*aΆΪ·‘ι.Έ**š Z\,±ΖTχ7cQ4,*h±η8—s˜τcVώf,Ψͺ4#Cƒλω½HI΄„N£€OλWCΣ­έ Ί‰l5…#™λiT³5uš°nοξοψ8Η³wh=N'ΨπϋbΊ6x_SXΙ7==[φ’ŸΝ+ύWζ=‰Δ³υίϋ¨QΗhŸƒέ>[·ž7(ĊUŐ7ŸSiΛ±ίΤ΄@Ϊt¬Ε7»χ“r{-φοK§ΕC 1iϊuΝ³Κ;>e1aԝΜ[{oWn’O—ΆTτδd\&™f+nFr“+›ά‡ŽΝͺTMΓΣδ‚Ÿ—_,ίM·Φu.ξC`!J,gcmθ—ά ΥΞΕBhΣ`] Dάχ,O €uΪ(ޟφήΎŸη˜u#_EΕΗ`2‘n6γa4ζΤuέ>V+·E+'w½"λB0η9}ފxωAΣΞώΔΔ λ¨τΐ^{ Αξ)¬{w‡σΛ1`P΄ΧIή€ :Ί(:ͺ¦£θ£ΣάΪ2zΖZηoRA10tt΅ΐυUΑη΅t !œFy7α?ΣeΏάΛΟϋQΗ£3ž†Žεl%Σ%†Ύ‡’œηdφnͺΈ7"'Ϋʁ#;ΈΏι‹ΨlΆΛΥ’v²ω`wΏ5‡ΉsζΪ³§πH£$ΆmύKώ›·sg t'fŸΰΨ97*‡ϊε&b₯-{Χ†J₯–©ytΏ;ΘΑδf΄kX1έ†Χ³kͺ,”Τwmΐ›#nη‡Ÿ·ŸH½ͺ> ]š„Ρ©Q(‘ BiS/„uBhR;„ΑάR-ˆ¬‹εΎΩ‚Ÿ·½ΫΥΎΈn·Ρ²~&»6$γ’±Vζ·±-Άm›ωΫoΔ((Z6ι™?:Ž;3~`Ϊς1;ΰx\ΟψΈ»{pβΔqšΟš&f³½ΫΠbΙ«•—dστ€Εβo8qβ8…λλv­d±sΓN’‹Χ–u¬κIDATό(§ƒ»3¬_ ͺxαζšMf†^8 *τšό=F 'ΜvŠηΤBe*aΥ¨’αL¬W7Χά‡ .&ε’δͺβγ#-ZB§‘—sϋŒ‡!€©ƒχςΕΖg™ϊΣΛ ΉkΎξaΙόΗ2·aΦ3°ifšxίÌΥοπl·X-₯ύ^œΞ…[8Rν.F5υΗ/ΥJtνέ†₯_lεπΐ45Ωχητ†%¬7„¨Πώό~ ;έ;ρfCcξ·ΚK[žwTtT–t¨υ-;WdΫ€7·™Κϋh•ξϊoΡ.#+ƒΖ5ύ™7ώ~žšΈ’€Τκ΄oz š/LϊΘΧ( ϊyR-€έΥ”¨ΖΥHNM.°†·λΟΟ/OηcŸ‘ κ|•=-ΔέΚwσ~ΖtΟ{ܬ嬏=αR1S—α/τα™W¦³΄Ι{ {½ΎσYΊςŽΟΐ±τ»%΄o۞&sfspΔHΒ³² }Λ5/Ιj2g6΅j²}Ηv0θ’ΊψΡihΦ½<“ff2ΈGsjψΘN‰εlv0MBBπI:Θ–‘ά”Ξ?λ—°)Q§zn)E};0οϊ!°-έ[,bζό¨=²3nœ>•CΥfνθέ~ŸΞœCψc}h€zζoώUλΣ©QΰΕoυ^‡oJ’%„pεό~§ΪTR3x’γgμ9΅†O—βώ;†Ρ’κƒμL™GŠε-}δΰ©-Tr £~pT)c³νΫ·œ ~ ²Ψ }½ί₯Ι]t4ώ[ˆ¦-όθΤ·gΎ~Ρ§²πŒˆβρ·FPίhΓj+Γr½ΐCυ£uTUΎšώ/m^l„C†g9p<˜ΩlΖΧΝΔβwπΒ”ŸYυΫ>ξνά€_?]δk4MCΥT233INIΎd©Š^ύA>žΒΌ―Ύγ“—¦’b6αή€Θ&πJχͺh™—LT«Ί[Δ`^꿟ηΏXBΣ†Π£άfO»6ε£ΙΔ€~ζ'[MΏžΛΎƒ/›ΎωW³Θ¬S›ν;·3 ƒM¦K¦EQ‘Ζ@>žΜά―ΎgΚk³IΙQpσ«L½»Ÿ¦yίyΆχD¦ώί3|§„Π¬ο3<Ση VδνSΑ—ό«ϊΠaμ{d|1…/_ZF’Υƒ*‘#y­Ι­΄~ϊ#FΝ™Ξ’χžα³ π «Kη!·]^fŸΧJΫΉτ_ŒΨ­!D)6mΪH³ζM+¬|w7w²Iβ͟ϊR΅JUξiση-‡1Τγ£%OριΫ0ΩΌΛP’ ―€@άrHΚΊd—β†o Jz<©Y'ωξ₯·IΊ€—:ωγnRΠm9d€§‘eΥA=Uςr\π τǘOŠ9χNpn9ΟΏq–A_>C —Š»;Ψ;:έ^蹊ŽOY)Š‚Ÿ_%¦/ίΓ/ϋOr>.™οί[hΉ’( ϋΰνR\<ρφςΔΝՈQΝf%';Œ,+φ‘@<*γeM$!3/yPpρ ΐΝBrR:–λœ€^Οψ˜L&4Ueι²%΄oΧΎΨί:άΎs;ϊ=ˆΑh,vξ9ƒ‹'ήޞΈ»˜0(:Ί¦bΝJ%)SΓΝΗ_ ΊŠ%+,ƒ/žΆ$’³—_Š;•‚½°%%’a xωψΰιfˆŽΝœNrj6ͺ₇^n.˜ φΨfg€’nV)ςϊ*'γΣeιTiΡB8ŠlΒΟ6g£(žLκΏ•9Ϋ^αΣοŸηήΞCXόϋDz7z-Ϋ•-'Fw³6.Κj%#)–Œ"w ‡Τ„œό½έ–EJRQ?αSΪr i‰ ό_γΜξέ€6@cW"†‚T8Gu‚½uΚf³a³ΩHIMa@ΗΒܘ΄t‰I‰ωsdεΕΜh4b00™LωΛc ͺ5“Τ”ΜΆ¬’•KV‘ηt, Δy8NEΔΗj³b2™ΠA–,]Δ†_6\ΆŽ»»„b4`΅› ͺ5“ΤδLR‹X–“žHNzΑgβ±_Iκ%Χ g“—}ρš™ŒTσεΧ€n!+-ρ’ΨεΉτϊͺ8’h !œFI}―–ύ+θφ.$MΣHOO§ίm―R7¨=_­~žZMhWe ©©©ω7iƒb@1(ω7k£ΑˆΡd,S ΙŝΉψG‘ϋUΪς|6r2²H?»‰…?gqΗ‹ΝpΡt΄^QQ*">ea³Ωςηn²ΩlΨ¬6222¨ζΒΫ·"-5 MΣς,£Ιˆ‹‹ &£ “ΛΕDΛΥΥ£ρΏ;-CEΕΗj΅βbrα駞-ςΠu„Δ¬ΦλόΓλ7I΄„NCΧτ+KfΚTθΕ‡ιθšNzz:΅}[σyίύX,RRSςΧUPΐxq}”άητ¦σwY—ηQΟ³ϊ½ΧψώBΝx…Α·‚Vάo\—ƒΏΥVρ)ƒbOvuEG7δ>4Υ¦μkΐbq±C{’e0bTrΝύΫΕδ‚Ρ`ΌαηsT|¬V+1±1Rφ‰|λPαΤTM-χΕ `2š0κφŸΣΡ4{[¦id›³Ρ5ooΓΕ±=»σή<―¨kΖX›‘sWcL%9§ˆΧ•Ά<½Z υ?F›TΜ)$g˜+4WP‹žΑ3™#Z„ƒ‚«›+..ω1Τu›Ν†¦ζώζz~λ£ΑhoΩΊt¬–£ZδΚ“3ΖG\TT|$ΡB8ΌξŸςVπ›wγ-톔χšΌΔμΚ™I; ΛσXH‹?GΪUΦβJ•΄ΏŸ²(ΓΌΨ™L¦ΛZp W–Ή§n4ΞaWT|$ΡB8…ψψΒ’’ρυσutUnj©©©ΔΗ'\φΌΔΗ9H|œ[Qρ‘DKαjΧΝΆ­ΫΙΙΙ)}eQa<<ΞMβγΌdԜB!D‘DK!„’‚H’%„BQA KN3,„Bq“ΙΛ­€Άs'όwfsB!„p;‡Ώ ό?mκΒ^€^IENDB`‚rocq-9.2.0/doc/sphinx/_static/rocqide-preferences-shortcuts.png000066400000000000000000001547441516144147600247110ustar00rootroot00000000000000‰PNG  IHDRͺnΙ)wsBIT|dˆ IDATxœμέw|ΥΪΐρίΜ–τήI!‘7)RA”"RD±Α+Š" (–«^°]E€‚€’ˆ]PAE”*Mz $ή³›έ9ο›„ВِΰωϊΑ$³SΞ<{fζ…ω(8ο3Ώ.+‰5^αΈωϋΊΎ΄’$IΧ=Ÿ¬»H9™‰ΝͺW‘7Ά%ΨWžΔ‘$I’-“ ΐ™th θΊVζω(€ΐθιC†ΥŽ]ΟΗj΅ θeχH’$Υ,ΉNRbρε¦ ŠΙŒΙ/ί†  sηŠR=Ÿ¬MΗiίe$O?YŸ/…Ό΄=ΌΡ<~ŒmE€L<$I’€j@³bΛΚΑδλƒΡΣύ¬ΟVμ9Ή˜ύ}1Έ»•9QΤaaΚ½—`…w­½ά bwόqΦεZ1ΤυΖWhδι`½ά5’$Iͺ6tς7―₯ݝŸ±±σ̌6k'OμβΫe_σIN=‚λx^v⑝<€;„‰]›α%ς8r4 IΔg{ ΊλΨΚ>#I’$USΆμ\ N&αΘ·`τςΐ#"· €KžWaz&yΗπŽΊ€y€­ίZ‘ρ‚ol}ΡΟ4k!ΪΑcάΦ΄+χξΐ‚9Π[FΖΔTΊ7iΑ―{ώΑΠ ΆάΔŠ’Žς.­ΠΜΝ3πR$8š·δ5‘&Ÿ¦ζσ—Ρ]ήγ!IR ¦c/yS‘  ν0ΫSνψ†ΖΡ€Agž―ƒϋ[cNzΔφ­δ9jtC …{SnΓ­u'‚­Xβ“—”…Γͺ£Έϋΰ[ί8TEڔIh»ά°οώ”»§ώA†9”€ΝpΧrΘΪ±i‘KΟ[.cΉ₯¦΅GΠΪ‡Β}Η±fΫf/άγκγWΧ΅xΥ΅,‡ŽŸ˜‰έ꣦hόZDbR‹>/kY8°?DξΡ4l0š1ϊΰQ―.ήΑςqμ’$]{, § Θ+δ΅;ξ§ml>rIΛΎ%57θˆ Ο«09 ·”,ζ….tžZ4—œΒBάΒ‚+4½]Χ88yn™γ4xnX™νΒΜ,ϊ6iΙ«`p§n<4η]r‹Šς<•Α'₯Nh8š,K;Ž9$°Με)”τt”jΝςςb‡MΗ¨ΈΓΫ@¨Α™`….F_sr1ϊΘΛ­$Iͺ©t4qζχS›ζρΠ²$4-˜'_˜Δ3±ΡτhΘτ_³xzόbžp_ΙΓοξ’γΰ·Ψΐ—?>Ξ3λBθuλ¬) όMX2޲jΥLά’€54πϊØ=`Όξ ώ™χ8I+Gη5'°δ­Λ…¦MΔήΚ Λϊž|ρR—{Ξ΄ž«ωΑΊ<1†ž±ςN°κ·OxyGβΊTG6y[ιzΛ<ϊΘu4τK ϋφύΚ«Λr’‘Φ­ι/ηυΑθβ‰­έŸη΅₯eˆŠ5›'vςέͺίY”„{L<$IΊvΨsςπΛ΅²τι—ρσ<Σξqέυ΄«Ϋ€>S^#/;§Bmd[Z&ξΙ|όψ34ŠˆΰγǞζ‘ί%_spω=Qώ{ΎB”έώχσζη][rS7κ†F°π±±ά?λ>ώ,uBΓ9œrŠŸwmE4¬]n.a¦€§£βύω&E₯–§™¦fΓΩ33°δε`>ηš/I’€š£tOG‘#3ξE»<»Γξάu’ϊwdΚ ]ρU39xl»2ΌΈmΠ8¦ίΦvΝΕ?²ΎHγ8ξΩ`'¬‘?vK!ΒΫ‘s‚Ώ²HMw@f:]ξ{λβΣ₯¨l—ΌάΣϊήΔ”g:“Ÿ~”ψd3ΝkΥαφ»Ÿ"7a,γN7Βxς$έNdZΫT{ϋŽF Œ¦Ύ»…S…–'θzχΔ‹/kGώlIΒΠ("ŠOΛ}³ί!_c9qr%1cΎΰη'¦,ΐ‘ke·Uk­ ξžω6‹†F΅’YϊΤ8Βύ؟t’ϋ>|kd0Urφλ%I‡­= ΠΓΓH3“CLθyŸIΟFs3Uh^’$IΥ“Ξ™=˜JD»Gψ΄ŽNh­8κϊ–½|O&Ί‘¨›\ρΔ”π}§-gŸΙŒΑ«;ί΄ @u`Βλ―2'YΓ}K_Hσ›»ΠrυrΦ­œLŠ}ΛϊΕ’ϊž‘sΆaςCυΊ‰ΗʜφGΆͺώ—ΉάӚ°μšΞms6‘&ΒxςΏ“xΆΆ/-λΓΆDΖ›ΦΪƒ8Εό©/πz‚‚phxEc―γ@?Φ©μrώρ%Ϋλ{β₯€ΘέΝΜ9Σψ2]ΓΓ'―θ8Τ0E'$IΊ¦Xsσθά°/|³Μpηώφ?_Β¦—ίε¦M)ΜΝΕTΞΎΟr2‰~ŠF΅’Ω—t’Ζ΅’J~Ÿ5dχ,˜Š‡oΩ=&ΕχjΫuŸZœυYξί;J>+w_μγIvDχ̚Μχ£^ ^X-₯œβžY“ɏ Βθγ‰VΑ}z…/―εηN/―³oωf1ϊ4ˆΑCUω%1½NνrŸ‚%I’T}ιœι•Vπ G‡ ›%“}»Ά°θ‡οψ<0‘[|¬ƒMk`_l Tσ1TC, ŠˆqΏ`\ιYϋ…E!›ύΞΉΩΞ/Ό³Pό*0mIΩ.cΉ₯¦έ±sιυš dμεΰi;’Ά ³Ιˆ(ΜDŒ‘žͺ ημfε1/θ‡ͺκX42Ž`ˆ(gYͺΝ Ώ2}wK^jv“&ΜζΡ]ςρ/Λψ:Η†j†ς{ώ%I’j M?³S³kš³§A8/=Nyνm‡έΕVΘζ£ρ ώh*ϋ&Μ`ΐΜ·ψτΡ§(°βp8ʝ.τ’ŸηŽ[Φg\7› 7£σ™c—‡ΙŒ›ΡHΆΝ†¨p»_q&Ž <½κσ΄\ΜΊϋ‘έ,ξ¦CA‘™dƒŸ! Χ‘I’$UOz©±ΖαεγΈυ›C8ŒfπυGΔΕ€O!Κ±’Q„ΐZhGΧΗŠφΒ–ΖΓ§Θ-½;ΤHχuGωg/RˆŠMλγ†Θ½Μεž3m~A!ΊAA œu°DˆRθŠ@Σu@€₯*΄ŽήθΡπΡGΟ°*φ&†tοΕ=-ϊπfσ›θ²ΰΏ<–dD —χtH’tνžn¬9Έ—^Χ]Ο€{†0φΛω((Ό=h(kβχ"<έΛmo+΅ΓΈΰ}η<­…%ΓSs³ι5λ-PL΅#ʝVΤΧ„8oά²>;—#=‹π,+ߏώ/‘A8@ΓπHΎς%ξ˜6ΣΊŽ1ΘΏΜω8*ήΣ‘¨ΐ„;™ωάθΝκC ,Κ-`ΪΆxa!(f“με$©†ΣΟ<Α©ˆˆiˆ-Ξ³Τ(:†sΖΡu ‡·;†LjΧ:RΙδ·/ίζύDBEπσ ½Aβτ‘σ–iχ¨ΐ΄υPφˆΛ[ξE¦=χp# &΄ΤSœΠΨ§)έ£±nΛ>„¦Gž·‰Β€r–€bΧi€CWςʞίY2`ίφŽβζ6πώμi‘e?εD’$©F δ•%ŸΣ‘nn»ξzφ\w}ΙGYyΌ²d1„–ίήφςΐΠΤyί‡uσξ’Α]Η½hΈNωοΦ+N&Ί^r9Υ…Ζ)³< ο”,Ύ=Žθΐ`œNδŽιPPXϊδK4 δ‹αΟϋύ7ΘχργΉGΖs%ξ›P2‹ΞrmΟ΅RrVLφoH’t-ΈΠΎ¬"ϋ7αD‘φ37ήΖμŽυϋίά~,tαNXXξΫή¦ΣXL—9νΚllœτ+šφά&_ sΦ²ψ@^kΙΠ±οΡώΨiμ>Q4ΠηI+Ωα^Ξ²–ΗPgΛίkAFR'σjΕDb'O&ίΣM/$IΊ¦(ώ>ΞO‘Σ[/1qΐCά¨Bώ<Έ‡——|Ξ “ΐθη}iϋ>w3+χνDΧuπΈ΄ύfρΈY3>/sœ²ζ©eζΠ·y†Grΰt"}§O #ΔyϋΣίδ‡’Δγφζ­Y”tCžͺe¬ψ*@-£‡ύ=Έ5:„%ιω(εΏ D’$ιΪgDoΚΟί½Ζ#Ιwσx‡4kL]έΒ©Δν|·/G€δ]ξ΄&Θ©μiΟ‘˜Ρš>žχ&τ½—Α­Π°^C sΩπηNω’ΗΚ^V zφn~9ΛΝ1ui)(Θ:ΑŸλ~bβΚ,Γ―(Κ’$IΥ‘12”δœ|9aqΎ2[ρpΗŒΡίη’ηgͺΙ]σίCAΑSλ’§χu%OSšκλΕχ;6πÎ-d‡ωap&ι@ŸioΠ·y–ξ܌W±w(νLG[…Fnh60ήΣ B'-ΟΒ“ΙΩΚl$I’juο.L©ΣΰμK«Š‰Œ[b(PΠ›4ΗRκ₯¨Β†zς†δ\T«P^>θ΅#q™rόζcŽ₯°i@Ε§½’ε^pZΊ¦dύμu΅ηc8z Cz>Š]€Ι="G¬σΜXyΛΚKΓx(5Ο†’nξθΑ‘8βευΐK’$IΥ‚(΄‘η[P<άQΟιdΠ-…‹ΥΛΕ­όϋτκσ₯%zN>]+¦ϊx‚AA$I’$I’$IΊ°:Β|i—W³»E’$I’$I’$©’Ξ}P‹$I’$I’$IR₯’I‡$I’$I’$I.e8zΟΨ«]I’$I’$I’AέΎš!{:$I’$I’$Ir­³n$7šd"•oυͺΥtκΤωjC’$I’$Iͺ!d–!I’$I’$I’KΙ€C’$I’$I’$—’I‡$I’$I’$I.uΙ/¬lΝ›Λ―Ώώ‚έn'-ς‘ M£o{EQpΧ]<3φ—P’$I’$I’€+qΥ“ŽεΛ—Ρ₯K7TUΕ£Ρ šζXpO,V+_~ρ…L:$I’$I’$©š»κI‡έnGUV­ZΕΡO“ŸŸWζψ^^ήt}g3­ZΆΔf³UQ)₯J‘dΑ!ωα―x‘έΡ3Ώw0]΅"‰ΣίρμˆΝtŸ&½ό•«·lŸC,|κu2†Με©6ξ`gι”I,ϊ;Β€ξ<ύˆ‘?χα…Cid¨bJ’$I’$]±«žt8Ί(ͺ‚’@fff™γ{{{£ͺ BθΨνvΧL‹ηγQ―’ρπ<ΖΆ>ΞΌaΟ“όΘ7ΌΤρκ5k„―Η0όΫH^œχ½vyjC}šϊ1 € }Υ<jΘΨi€ ΌkqӍŠσcI’$I’€ζͺ'šΓk¨ͺσ,shhθyγ(ηœ€VU]ΧΡ4ν —žΗŠρχπφ†=& ώ½'ςεΨΆ ™±ΠΩΌΕό›hΗX΅: ?γ)ώؔÍ]|©ΪώƒšK)Ι(tRO₯`l܏ΡΑ”€Ή2α$I’$©†ΊϊI‡¦‘k:ͺβ|VJJJ™γGGG£ͺ*ΊΠq8*#P‰τ>SΕ=ΚKA5Ή;#O+_2GόJVg·ζώ~§XπΗ:2oιE`²QΟς9πΥΊƒdŠκvΈ›ΗοGc―L–ϋ?~n1“χF£’qpΑ0žϊ1†g?y…> XΦ0qΘB7—‘1GωeΞL―‰'Ϋ\‹V}gτ}­ ,zN›žΎ‰…Sg³lg „΅’ο=υ.ό7ν FMG} ™ί.dυ‘||κuγ‘±χΰ±bsΩA²Dσ~Oρόƒ­πSΚXo₯όe—\z6‡[vΎΞϋΛΘ΅½Μνi1b!oD,dπ^ŒŸ3œ¦F–C_Oν FΝΔcδ`μ_NgΙ.…žoΞeXγ|v~5άΒ±l ―°ΖάςΟςD§0™J’$I’δRe&Ÿ,ό„… VhFCaπΰΑ—\ηεUzIOGdd­sΖ8Ώ9€* Ί¦‘iŽK^ήωT³'^ήήgŸHΦœΉ€ͺύΩSˆ‚C,Ÿ=ΟŠ'ΛT‹λϋη©Ϋ€"‹_ΌΟ¬₯[8š₯αޘCŸgdηCΓΞƞ?ώΔϊIΊtJΰ/W²6΅'w„–³ζ"“5ΣΖσiN_ž{oFϋΏ`κ6ϊŽŸΓ-Αv’ν"=,ΰ_P/%I’$IΊΪΚ|OGE‰ΛM84́ζΠP…ΒΒBTΥpΞ?υ¬ΞqTt½²z:.‘Θfύτρ,ΞοΖg/βγ7οΑcε›Lώ%8φ}Α»ίΫιρΚ\:‡ u§eΤΏ€agΩΞΚυν:·Δ3ΌκΔσǟ‰θεL&2Φ²|“·»ΦQD4ηΞα‰Ω±”ίOBT³¦xΪΓ!ˆτΨ–v½o `χ?q “Όo/9 šΣ o-?mŒ`ΐ°Ϋi@p½ξ<Π3‚έ«&]€H]Οͺ=!τz7ΝΓŽνΐƒΫsρΫNΡέΰΆ†a„6£oχ¦θZSϊ?Ψ‘ΪAD΅νΓΝΡ)?i+gτKXΆ‚ΙΓ “‚btΗΛΛ wγΩ΅Gd–½žΞ‘ 0Άy„έΰ‡§Π44ň— ΑQ4jί‹ŽqζKϋŽ%I’$I’.CΉ—W <ΰ’=W’p€³§£ΈΗβ‘!” Χ…@Π‚’ί!Jn$Ώς{:4Ž~1†ώί7μL΄ϋ/uΊπΨ"s ?¬ΰξϊ$Dπ[y¨Χ _΅‘τ^ύπ/nΨb"0$ͺΚXςΆώΞF΅=/^ηJ(;Υη“_Wqό‡ˆ+#½ΥN$IεŽΘ3#)qΔω&qhΠ €’Δ£2‡Γyy@HH7vΌ/OoάΜn˜MnΨν6μv;–>ύt!G%N²³²K¦»2 &― ΒΒΓΟΉ§γbγ „[;ž˜qNƒΟδM „Ž#gΠͺίf~ώzSFόΐυΟNε?7_Σ ;‘±†ί·Πϋ₯χΈ#ͺΈ±›Λ†ΖρΛͺ½ n؜‹=lΨP«6Ρϊ?>©Ρ±σ[ι‡9œA›((4mΖβ=Ώ²ν`(­… Ί»s}ƒχψ돭dΩ›π`œCn4βR-A„E_΅Eh‘Ž=;­Σ!ΪYF-9‰”J¨Fε­ƒΑ\yΛ6D”½žeSπŒlGΡ­Ή!ςFόΌ‘ΜN·WθfI’$I’€ΛUζ=η4hƒ.ωWJχtδεηaP œNNd̘1<1b8'ŽsψX<𦑛—‡’*¨Š‚@ΗQ)7’_CD4΅τD’-Α„‡‡—ό ς.•Α)xF΅γ§§πήC¬]ΆŒσO_C§Χ¬d_TϊέX‡ΨΨΨ’Νθs{,kg‡υβS+ιw“…es?gKB™§vρύμ―9Ρ΄]£Tΐ@τuMP·―ΰoCKZGͺ ψΌemφIυ›ΣΘ JΠMτi—ˏ3ηπΧαT²sR9±kΏmOEJhnn”ΔOσ—²'%‹Œ“›Yόε²*!ε­Ce.»ΌυΌνθ_όπΧNŽžΞ$;υ;γΣq ΒC&’$I’$ΉΨ%?2·ψΚRΊ§#?/!ξξαl>Ωμ6l6ΊΠΙΛΛCUEAΧτJκιΈ4JpgϊΆ_Δ{Σ>€ξSiΩΗw±_»Ž[[… ω“OϊΣΌa †TgΓ.(ΟkΉa§Ÿ`υGhΨγEbΞJc|Ϋυ¦γGo³r[>mnΈΘτŠ7ŒxƒaσfςΑΨ/IqψwC^yΊ7aEq3ΥoNΓόεθΠ–:ηΌƒ[΄Δο£½˜š5ΕG σ˜7(˜?—…γζT.xE4¦ΫΠλŠ–AŸ±/ϊώl^φ„΄ ο#Gηγk<εC%.[)g=/Fd°ν‹˜2»ΡŸ˜V½yvΨ x\ΖκJ’$I’$] ₯ύ‚ΙbεΐQη_^š5mJ§›:b0ρρυζρΗCAaάΈρ<1r8šζ ",’7ήxMΣ¨S§§OŸζΣOa±Z`ιy¬?ˆoκOcΦΰ:e<2χΘYo$ρόuqa$I’$I’$IͺTΧ΍’$I’$I’$UK2ι$I’$I’$Ι₯d!I’$I’$I’KΙ€C’$I’$I’$—’I‡$I’$I’$I.U-ž^%]›ΆnέΒϋ3¦‘––v΅‹R-„„„0zΤ“ q© β˜Υމ%>>›­πj©F2›έhΠ ǎύΧΦ=Y—\£Έn !d\+‘Œ«kΘΈΊFq\ƒ‚‚ΚO&’ΛΜϊp6;tΰπ‘Š=ωZW·N]fψ!B— *ŽΩΠJǎpwwΏΪEͺ‘¬V+λΦm`ή‚yΪΊ'λ’kΧ-@Ζ΅ΙΈΊ†Œ«kΗ΅C‡eŽ'“Ιe,V GEUεU|G₯ΐRPς»ŒKωŠcf³’( yyyW»H5’ΙdΒf+όWo“².ΉFqέd\+‘Œ«kΘΈΊFιΈ–₯Ζ$λΧ―ηοMλB (ΚEΗ»kΐ=ΔΔΤΒ’IcP e~WFΥ γr Šc¦λ:Bˆ«\ššIΧu@n“².UΎβΊUό»Œkεqu WΧ(ײԘ€γοMλyώΩ),,ΔΝΝ­dΈ¦iΨνvL&οΎ7I&Υ„ΙdϊWžQ-‹ΙdqΉΕ1Σ4 <@\ŽβύδΏ}›”u©ςΧ­βίe\+‡Œ«kΘΈΊFιΈ–₯Ζ$ΕςσσΩϊ•7 {FύwδΠaN₯$mžyϊy™xTf³ω_έΐΉ³Ω Θ€γRΗ¬’gR€σιΒ»ϋ6)λRε+[ γZ™d\]CΖΥ5JΗ΅,5.ι(ξ ;πs8υz&ΔΥ‰cοέxyz‘œ’Μƒ α³EŸπτSΟV}΅x>υ*Οcl»χ J5ζ¬ͺ°pϊΐlMˆρsν₯'W½§£Όu’γco@”― Ί…΄“'IΞ.D˜ˆn…Ÿ‘j‹\3Ω ~εϊ6Y…ΫΪ…ΘΊδZ2!γκ2U―ζ%Ί³’Τo;šψ_jQχΦ“ΐΫΛ—ο–|MAAωωωœ[+ΖίΓΫl (=ό©UnxšωsY‡DC}†ΜX†+i™ R—ΎΘTΓσΌq{ΰε•£0›Ν(ΚΥkΰΨӎ ΔTN5WcΈλύπσd–―Xαε*>ΣzΥβRήΊκσΐΤρψό>ƒ%ρ6μ΄ρχ΅ΐœ»/?ψ‘έ ‡+ΧJR3Ω ~εφ6ynύ«π6ZI₯Ί$’—ςΒ“Ϋθ6χUz\…ξBd\]CΖϋγIω IDATΥ5d\«^K:JwαΤo;šψί’‰ν~œV­ηΔ‰γ˜Νf|}όψeΕ² ΞQ%nΠϋLƒ=;νKf2mόdΌζΎAΟΰΛϋ•+J8‘ΗΞbose³ΉΪLfͺκͺ@@™ι˜ŽΉΓsϋκ7ΆΛDχ©M›ΎπψMρ­ΒŠwΝΕΥ–ΒΦσέΚ-Δ'ηƒWoΉŸαƒ;Q…­§k.₯WGδ²uΦ³LXۈ>yšv¦*,Σ5W[¦ α+sΟ΄y ‘ x{WΏŠ/QΈˆ—tW!t¬YΏ:ίkS»λ1BBB°Z­ψϋϋ_ΒT³'^ήΎΌ›Πν±‘μόσώήm₯ηM'˜7|£‡`|ίνTθ=iΕaΩ¬™,^{LH½οfψwΔGνσ†=Oς#ίπRG’ΰΛgOησΏβΙ2ΥβϊΎΓyκΑ6lωρ,›;‹―ώΪOͺΓ›Z7 βNσwΜZ—MαΪ{θ>ΥH£G?bϊ θχϊx³Ι׏ ;ω)$g¨„Φ‹ΐ[4 ιI‰€d`*n~a©κυͺƒςΟAvξΘΒ£V#κ‡jœήŸ€HN 5‚κ5’–·‚(ͺŠ’wšψ4•πό=•ήό1›\tOΗyqq—œ@bjV¨fOjΕP΄Z6I‡ΘΘ·£˜½ ŠŠ‘–― D§φΖV«ώΉ'poŒΆοΎYΉ·¨„XS‰ιyv\λy€q¨ b沓RBG(jε7uE{wF΄V+VvW•£”ͺΪ&ΉΙ$œΚ ίjÁο(b"|0)ΕۚNnb1½d]Ίόeω)²·πΕβ}Dήχ:#[…bέ “&NfA­ΣΞ³κΚuΝΕυ»N…ΡηΉ™΄υΖzτWfL˜Ζα x½WŠŒλ%,«ΤOqf`ښY|΄ί`ƒcρg2—°¬R?u ΉΉ:mΗ~ΝkέΌΓξp ιU\‹¨±IΒω¨³‚ŒεΞΔγXjw=@ddδε/@QQΥRgυD~šς)mξϋ/sŸΗΫ;—?'γγμ;xaΪΛΤ1$°κΓ·?ΙƒΩ―χ$δ¬Βf³~ϊxΫξγΏ³_%$wsίx“ΙΑ³˜Ψ; EdςΧΤq,ΘκΓ S_"ΐΚαtZΤkAξ‰ΡlΉe6―έˆΡΝ³Ζ%P|ύx%ΝL8ΘΟHζtšBξƒΪΥ“­ŸύΖΝAv 4{ΰξΊ!ƒ•΄ύ±EtΰΆΎ˜Ϊ/ΰϋ'4WΞfώAɏ’9{Ό†ΎHz [?›ΕΚΔβPΑ|Γpήi’ΖO‹Ώα―cBΒC+΅ρc29βκΈΞ΅β{ΣHΖτiN-/kΖ1ΆύΆŒΥGTαΐξΦ„‡^Ο 1>θϋX1ΦΊαcŒ‘»―ΰΏbG?AŸΦ΅π6½ΔΧ7kύω#6‡‡ώ-ώλ'ιwWIΜ*½+\ΛdͺοωκwAΏ7‘…rˆOΗΞFΤ“Μ%Ÿ³ζh>unaΘθ;q_9‡Wμ"E’ινOπτ ψ) ,Gψmώ\Ύ^˜S8Ν{>̈­P²Ω8σy¦mΘΖΆώ!ϊM7Pπt& ¨EΎo˜ϋΕjφO!ΧB³žΓ}+Ό7}ΐώπ₯ίΐ~tͺλ‹+ΞKUΝ6 ώϋ2`dκEβ©§³χ—ω|ΊΩ†›WρΆζGϋ‘c λ™ΊTp˜σ?βۍ‡ΘώΤΉ‘C‡φ‘‘·sνυτ­|>sΏμNƒΠζτΎ«ΞΓ”Ώ›yiND‘«CΗ«ε½άΩβ;>;œ„£]]τ*¨[Ξ’\cq Ή™'ž7 Ϊ°k·ϊ½ΈνΊ…|”–‰F°ŒλeΖ΅xm΄€εΜX\Θ]#naΕδ„’G]Ζυςβ*²ΙΚρ $Јέa/΅’UΧ²ΤΌ€£θiBh )Iι„r~βq9τ‚Sόσν"ώΪρdσ’ΗςŠŒν†1ͺGCΜ€HϋeύΉγύϋi­A y/λ†.aΕ‰<Uͺ¬™kψa}wΤ—&! „ίΚC½~`ψͺ€χκGPΪ_όΈΑ~Σ mŒ&8§0 n^x{{U‹Λ2.‡ΡdBθWxDΡYΤΣιΞ†ΝK½Zΰ•τλ–­ε˜’8tβξϋ#vςγΒε€θΎ„y[9ž| ασ(υwΞαΗΓVt» PΓΉυρ{9±ιζό’…ΥzζŠ’’Η―ζ'Cn5‰~›ωρΛoψσ¨±?F“s3wu\ Ρ·ρhOΎ˜Γ1«Ώπ|ς¬ ψ€βAΫ>7ςΧΟ‹™΅BΫτbΐc}HœΎ–Œ’XX9ϊΧ—|myžΏ1gΝ)μvΊq1ΏψžWM―’˜UVWΈ–ŁΥίσεΝXυζτ₯₯AΰΠTŒœ`ιη»yβ…YŒ Nα§·_dζ‹[©Ϋ}o,ιΰBΖΏ6eν¦p_\>ψ&ίιπκΌ.„εlΰƒW§0-π]ΖίJ‡Q’4’-]η1‘Wh6lšŽ—_Χ|ΗšFα~κGήχ!KŸΑΓ7η%γ>ύίvβύθTΗ§RO8TΙ6©€B’·ύΜί‰™8ό―£η]Cι–0‡ΝΉΕυ«ΓΏΛΊt¦.ε²nΦ,ΞΏ“Ξš@=Γ ~›17ίw睻L ΏN—ߍ2α“ήDμδΛ©ο²ΟQŸ[½ΌœR/ζr€–­Ψ2ELUP·ΰŒ«VH~ρ»γD!©|Ηw»jqΛγP…ΐ γzyq€ν0ίL[Nΰ°)τό‰Ÿ+ŠΘϊzΩϋ\²²ςX7}8¬VTΏΪ΄ΊνχjˆRuq-KK:τβΛ«ΠB`³ΩH8šDT©Δ#ς!{9s)MγθcθN‘UΓ»ngξνInφW@0Q·I}ΜΕc'$Ι˝QgΎ&%0Ž:~IOΠ T‘%η€u»νΗό’aΒQˆ£V[²uπ?•@’!–ώQΥγZ»ΚfPUτ+<“ 1ΧοΓΣΟΆΖ3q;ωΗs@ΡεPžΝθ& Ÿlΰh†δs$ P„ήπγnΎΣΟg ώΛ―vτxβ*ηΐP%Ϋ$kό*Ύ;AžΥŽ&βΥζFZ‡Έ£ζ—_².•Τ%ΏόΆ%;ίΏ‡FΎ64κrϋΘϋXχΘ2VŸΌ…ξ›Y·/Œ;¦έAšηυs=½kγΒ©­¬Šοϐw§rλζ|Ν Φ&6ΠƒΤ΄lΥ#6lˆΙθ\3±ΐΩm{n 9'PE1»2ΪΎ%LχaύŸζΙ»Zf°wξ–l$<Τ›Cttƒ CPώš hƒ4]C;H’u7>z7sKbΓQ«y:©g.Ά=³―HΩΌˆΕKΦ±7!ƒ|››ΥN‹[œ3;lδΪ|›χcXH8‹ί{g©υφ½Τ«„sU±M KΉΎyxhgGψαn2`4©μί­žSΏd]*©KΙ§8m¨ML€» cu$Ξ5tοRŒqΤ²aΧlθΑΡD¨©η—-u-³fl Ξˆ©tςEγ»ΎnU†jWcsΆ€ΑΦNο[ΙΒŸδεŒ‰Œ»-UΖυ2β*ΘΪ4yG»1ξΝϊ`ΏΠIbΧΛ«―:ξαυ¨‹Ž.|o~ŒηΣw3|νnνMˆrυγZs“‘£λ:Q±¨(*&³μk©ίv4l~¨Θ{:L^A„……Tθϊ6CTm’Ε?:‘Ρ©θi‡9”S‹vητX"’©₯o#ΩLxτω‘a‘„ΫεH’NΗΈCηY\/Ήβƒ|Β*>š»F-ofΤΫχ`=Έž?-gΓ!/βκ‡βεnB6»‚j*tœ9£ZREAAGΣΞ)WQCTΛ)·Q»co†θ@c"»Ά,fv|*VΤJ»ήΥqρPς8τΗgΜΩΗum;ςΔΫ]Ω66kςŠb —ŠKQO’ͺ% AgPρΞ³t Ϗ«Θ―š˜]ιY)΅εH>ύΌ«Ώ]Μ€QbnΦ•^=»Ρ6ΆθΪV!UΡ’Τqt]8OŸp‘(ΰ֞QŽ.υΔEU1¨’δδ„(•tθ Kygς/ψί;šρOΧ#Δ=‹_ώχ,»‹—εΘβπ¦•όόΛjˆ¦άvο4ΎκžS€£’puέsσλȈ‘έ›W³lm yv•Ϊέ$ϊΌϊ%λRI]R„hΊ@―£¦!„‚jΐYΧš(9Qε\gυtˆΜ-̝°€μΫ'2‘ƒΆΒRǐ*¨[Χf\ f7<έB©ίiΟηοεα_7’ΤύN"Ud\/5z.ΫVαΨ?x΄οά³ΚωϊΐΥ΄σ1/tφq½ΜϊͺΩm”\@λ°γ†ZP@&ͺ$e©±I‡;H9qŒϊνF£έΩΏξ-šu}•έ«ΗQΏνh6/φ€ν}•Ί\%ΰfϊw^ΜδΩ‹h:ζvκX9ϋ+Ž7{’Υ³N"*ΑιΫ~οMϋΊO €UdίΕ~ν:nm‚z½Z/bΞμ/h:Ίuάr8vΔBνΆ1„9ϊχwΌ™“7AΎζ‹ͺ«Œwˆ‚φ­_ΖΎM>D6nIΧ''qoφzΎωaYd›βoOγ˜ˆ§κΐbΡqχχΕ €°ζau0*L&Pœ η=LΚ™αΖΨΎΌ:Ά-ζ€έl]σ%žΞ/Ϊ€Ο™ζrΧE/΅qΙΘΛ ΥjΒΗΟί?νcΛ‘ϋΣ₯9;JζΌ”Ί§EQJΗH…Fq~ Ο‹«[Ε슻ΒmΉd«atΈ%Ί>˜ΕίΎα«Ο²Πž‘΅)YΠ™§δΏΈRκ©+Jx4΅τ8yΪPrΒω‘ξ< U‘i%σ+8r!=yκξΦDitΗ)ςσœσwΔΛ«SVΰh|w˜Α‹ ½qX °fη_aίΔΩ\]χςk7 :}=3ߍΕθ /έLd_g}(]Ώd]* %"–±„C'΄Š->™u„C9‘΄«₯’˜Β uμαψi–‘ΞοΟ‘|Šd’ω‰ά]|:ρCNάτoυΗnqœΉaχΠwΌRuλZŒ+4Ν%‡ΓFΆΕͺUρ2—WΌΉι©y΄)ΥΒΥ~ΰΥ·NΣ½ΗiηγŽ#ώ[ΧΛ―₯ι$œLB mGRuυ΅,53ι'v}nšξ„ΚξUγ‹>‡ψΝΣ₯ςΕ‡φONΰρ9Σ™>ϊ R4_κ΄ΐλΟτ!όάƒ’ΐΝc'P0wŸΌ0„‰Ήΰ]«1έmΞ­J·>ϋ93gσΈ…€Ω=‰κ<‚7Ϋ6β†ϋ¦εΫ‹xκΑΤ}x:ο ¬]#Ÿ`U©ηΤσ9΅g?μΩ„_Dš’’δγΐρŽάvοš»‚#…~ΤmR·BŽBAνf±XΧnΔMΈ[Ρ}εœ3¦Κ™αŠγkΏ\ΐ©\Gρ Tjά‹^Ž‹1’)m΄γlίwœD=Œ·αpθhκb *ΞΖ rζμ³σsσ/΅TyϏkDΕ¬Rž4’Ϋ±dcQŒΔvy˜Χz=LΪΎC¨‘Ÿ9 J .4πλΐν7~Ξ{sζωX_ VΘ>ΉCZcnΎ.Eρ&8ΨΘΡ-9Ϊͺ=~&/όBCρΙΨΑš:%8—+ΎΰΟtA %¨=#§‘I€NAA9YΩ.y’£«λžΠμΤ'Ξπ++iΥo ’Ξ­_ЬK%|Ϊsη-_0ω“o¨7¬±jk.αΔuρl8@;Ί4ω”E‹–ΣΰαN„ΩŽπΫwkΙutΛAΎ™τ>Ϋ?Νw““–…(ͺ 73jΥ­k+:y»~αηΤZ5Š!Ψ[}h ‹–₯ξ€ΡD¨MΖυ²κ«ΑΛ—ο±ΣσΌ1<ρσχΕCuΰq½Όύ@ΚF–nΠ¨ί’΅ό2φόΜόσιςŸvx*½ŠβZ–—tDFFώ€C9/ΰ›τΞDž~ͺΌΛ«ΌιρΏŸθq± ydώσ‡»ΕγΙwιρdωεU<λΣ{ΜdzΉΘηΎΝΈϋΕά}ξuϊ1ώΓ~ε/ š«τw ‘›œζl$“ΟΎίΒ³Λ͌˜ΨoƒΜψ?ωώΧ}œΨΆΔžx}Ζ@RΦ}ΙWρu7ΰγc@M)]HΟ’αJJ*Ι.+·‹’Ž3s/‰‹Α3’Ά=οd@€F½€τ»XρΗq4Cθω10ψΰ­Ίcρ0 Z=K}.πτsΓδδšQΗωqέZ51«Τ½£Π°[ςΘ²(ΈEGaΆ;Π‹Ο:•>ϋTϊηΉΓuwΪ=ω#ζΐηoŒαύ<π oHΧΑ͊Ζsγϊ{εϊIŸ0~δηΔέ7‘Χϋβ©ΫίaΖΫcψF ₯U1Œι;‹%(†h‘KFΆk{$mcΥήΫθςό»ά!r9Ύmξ  Ή― ΥPΊ~ΙΊTς·n¦ωπ·ρΡ{Μi ©š/qνοaΒΘψiV4Έυ™q€N™Ξ[£?ƒζτ}μΊž\ ¬[–ςύΎLlϋ^摟ΞMρΏ•q³§EΥ­k+ &oΙ_Ν獏RΘӌψ„Φ₯έ€ <ή7 έꨲmφڊ+‡£θA.NΊζ\€ξp «n_x­Εoϋ2siΰٜξc&1Έ™‰B›^uq-ƒ~Αd±rΰ(Œ¦κ{.ύ›oΎβdΒ‰ Γέwta‰.BΫΟάG_ mΨΧΌxcΎZ³ ­^΅šN:Ÿ5lνΪΏΞφξ{οβζvmΖΰr:oš“q©ΈΒB;moM«λ[ΊxI&|‚0δ₯’Uθά)+nώ„z;ΘHΟΓωΝπ ΖlI%Σ’ƒbΒΓΗ/7Ft‡K^6Ή…Ξ‹‚£'~~ήΈμyιdά|όπυ0‘ [Aͺ/žŽ ηό\θŸmΫΩ²mλΏΊξUοΊdΔΓΫowͺ’γ(, 77[q΅0Έαγ닇IέFAƒ―;ΆτL¬ζBύάΞ–‰^@fZ….ncό³m;ΐ΅Wƒ'~>^˜TE kv -yδζΫͺδr”k5ηνκŒήΘKΛvy]…k8Έαγ덻ΙXti― K~.yVG₯ζWσΟΆνά|σ-g +έ6μφՌšΣΣqUˆK’Q%y;ϋ2ƒhR}ΈͺT׏_‹d\.]₯ΏΘι<6r“Ο^fa&§ Kq—qΊΤ6 rΉΨœΒ‘OfzώYΓ¬ΉιXsKIΕz₯ΎT²ξUΧΊd§ 7‚³κF)š•œL+9₯‡₯ΥYε·ί~cΩ²e΄»‘ 4”oΥ•$I’$I’€’Z$V«…ΰ  ,ωhš]„; ]Χρττ MλΆμωβC̏:Qt]Ά£§ΧΥ.Ύ$I’$I’$Ie¨6έΕ=Š’’* ŠZτSQQU•ŒΜ μΙΈ/ϊ‘G<―βΕΪ§¬2ŠΣί2¦ο ,Ο Εσρ0e“|ς$I’$I’$•₯ZτtS…C‡“vgύžάΏ}ί>šχaVlƒ‰€n>Ό’%ζ±bό=Ό½ΑVΊψχžΘ—cΫ–C}†ΜX H]ϊ"S ΟσΖνόϋž #I’$I’$IW­’UQiΨ° ΤGΧu„θB'νΨ?XΩΗ mΫ,Nr"sII‰΄όlVe,•ΈAο3ePlQ·‚jr―P`”βl‰Ε»λ²)\{έ§iτθGLRpe³f²xνA2E υnΌ›αOάIΕ9ύπxŒ‚ύσi|·S‘χ€y<ή΄Z}%’$I’$I’tΕͺU WU7nL£F ΡuAΪ‰lίώνΫ΄&Ψq€={v°q*ΖΙΌ/~pmaΔi–Mžΐrε~^ΧƒHλ>Ύ›φ.ϋυι^z<Ε—φ#^γΑγ£ΩrΛl^»-£›'ͺΘdυ{γψ8ϋ^˜φ2u ¬ϊπ-ΖOς`φλ= ΠωiΚ§΄ΉοΏΜ}>oŸjυuH’$I’$IR₯¨V­\EUΩΏ{)))X3β8όνΫΆ!X‹gϋφ­l9”I―g~!8Ί)PYI‡ΖΡ/ΖΠΫβ. mΗ|ΒΈ¦λωcw·O»›αΰF† ZϊΧΞ½ίDΑθα‰Ω `pσΒΫΫ ikXΆΡŸ;ήΏŸ6Ρ*Δ€‘χ²nθVœθΑQ€(ΐΨn£z4Δ\Ik#I’$I’$IΥM΅J:TE₯i³¦4Ρσ〉΄Ώ‘‘β0[ΆnaO‚…Ύ/ύW@ Tκ­Ϊ*Q}_fBθ’{:άύ½Πž"ΩG½θ3]™£j‘ž“ϋ…hI'I2ΔrgΤ™„)qΤρKβx‚Q&κ6©/I’$I’$ιšV­’EQΨ»{/GΆŠ―_aj"λΧΝήD+Ρ½¦™―βTιKΕδDXxψYχt8Eα¬wͺκyχ}”E8o R*gR1«ΝS‹%I’$I’$Ι%ͺU‹WQš7oΞ֍+IH8Ζ'_H’şΫH—Ϋξ 66΅ŠήDn Τ~’γ§τ’aZrΙϊ…Ζv&'B?σ‘!ͺ6Ρβ(‡Nh%ΓDΪaεΤ"6κRRI’$I’$IͺΩͺUPXΝ#'I΅ιυμ/άυϊίxω…½$PqA!Πmδηε‘——G^^>Οή}‡WQ| ξή’HHHB „P₯·€ˆH *ΥF΅χξ«?QPš€ ‚bEš‚J E@zBzOξ½»ϋώ‘B!‘$$‘σρΉ0»wφμfς0ggf73GCρλΘ͍O±ψ‹_Ψ›LBτVΎYΈžδ †.Ε_3Q―ηHB" ©6― ΟbΙτo؝Hιέόψω"Ž7ιKχΰJwΩ…B!„(7•jzU.ƒ‹·bvr=χT]Η@sξ΄₯²£η.$6οη^ΨοΩ9;i―Œ˜5›sΗΧfϋ\ IDATΓΓι΅˜:\i7x-ή†'˜K½Sψx`mڏ‡GgNaΚ„o9«yR·ύ]Όυt_όενB!„β:R)’WRRR¨V­NΥ ΚU5wDΐTh%…a$$ΖγμμZGv§η­ ηΕ6Χμΐ#οuΰ‘Βeϊδύ‘!£ζ,.(vͺ۟Wgτ/ϊ}§PzŽˆžγ‹©ΫTτϋB!„BόWUŠ€£K—pζ=—ΜΜΜKΪίΥΥ•πππrŽJ!„BQ*EΦΈ a›TtB!„Bˆr +š…B!„εJ’!„B!DΉ’€C!„BQ$ιB!„B”+I:„B!„εJ’!„B!DΉ’€C!„BQ$ιB!„B”«JρrΐΤ΄TŽ=DFF:ŠRrd:ξnΤ­[OΟk‘B!„βJUx‘š–Κ‘Θ4 kŽ»›Š’”ΈΏa€g€±gί.Τo$‰‡B!„•\…O―:z4’ζMZβξζλhšVβGΧsG:š7iΙΡ£‘ΎB!„’>‘ž‘Ž««v» ΏfηΫ&ΎχΟ½πtAY‹ζ-2ψ\]έHΟHΏζρ !„B!.O…t(Jξ”)MΣΨ`“>ό„Ι“¦`΅Z F7¬V+“'Ma‡Ÿ°ΐ>4MΓ0 J™‰ut’ΏK―»GDFYΥ)„B!„€Jt†Qπ±:YQU•W^«“΅Hω+―ΏˆͺͺEΚ Γ(› ΄(ώZOuΛ?όρw*eT«B!„‚R¦WΝ›?ωση_REΓ†cθΠ‘—@VfVΑ¨…ΥκΔ[!ΥκΔ³O=W°ΟΛ/ΌΚ“&lΛΙΚΜΊμγΗqθOV§΄ζ;cψ⏠$ήά›ω£(ΪAf?φ ¦w“Ίh6«₯ΰΪ‰Α?Ν έPJΫ™‡Y>} ΦE’l©ΕMύγ‰ZSC0HΪΎ€©σ`oΤRM~4ο7–η†·Α[?ΘμΗ¦β2aφŸςΣn…>Ώ``Ξ’φΣπ;IϋiH@ρmJί1ΟσP»Ή±dD²lΦ4­ϋ—8‡;΅Ϊδν{αŸ]RŒB!„B\Ή“ŽaC‡”šx\i™•‰kE €ΤΤ<=«]°MΧ52³2―θ˜EΩΨϋΗZ2[§{ψIV-\Εϊ³½ΈΣ―Πά-ν?ΝήΜ¨§&1Ο?‹½ ίcβΣ όβiΪ:—²έ5…S^e‘m0/Oί΄-Μzϋ|ΰ3wϋψ‘ ΰκ@³»žfX£ZXc–3ρυOYΤv.έθ§X:ι+Z~™YΟωγξaΑt΄„ύ΅(ΎŸΎžαOΏΟάΪpτηχykξΉvπG„ƒφέZβΠ™υ"ωsΝ)τσv Ύu(ύΒόρQ‡πQΓιβˆΰΟ]9₯n7’ΦσλΖξy¬ύ½π­+φ`ΟκΝ$δΝγrjНώαMρυΖΏiO:ΧI&ϊdVξ4/#sΫ‡Χ³!5½ͺαj.e ‚nΑέ-ρφ €Υ½}išy”£q:Fό:–lͺFΡχΣ&ΔŸΐF΄kˆιbB!„βJ]Σ«† †“Υ‰Y_ΜΊ όj€ΜΜL4MΓΰ—%?”ίΩojώJρbΆišFfζՎt€o]Ε&΅/7uŏNαυ™³β/Žέ;”Ί)™ @ΏsšsκΪX“”ΧΡΏψv‡ϋq’³χ±χ‘ώΜΙ?ͺ#G­6€θΰcrpvλ"ζ.ZΝξγ dΨμΨ²μ4»UΛΫΫB½Ζυ±Δ\ΪώfCjΔ’8»ΰ€Ψ±;@K<ΙiS(‚LE‚v²΄―ς2 !„BˆλΪ%?2χΎϋξ(H<Κ"α€ά5Ίc6›±Z­<<ς1fΝ™Ξςί—qGίώόΊlq‘mf³]Χ―~M‡‘Β¦?ώ&%>‹ηϋ-Λ/ΔPωσΠκήxξςθzα[ώ:†N‘§g]|»αΤ–ΡSΗΪrnΕβN θΗΰ­7γ1h,/­G §$~ημ©b1ŸΊ”ύΝ¦‹ `ιΕΞ•*9F!„B!Ζe½§γΎϋξ#Η–;₯¨,Θι@''g¬V+†‘σπΘǘχυœœœ°Z­ {`$†‘c΅ZsΛz€ΓHˆ`ΥN/ϊΎ:™;Cς:κF§ΌΜς?χ1όΖζδφΑœ>q:Ή#YG‰<εD@€ )%n7SKίNl–ώΑ^ξτC{‰ς½•ICΒihiΨ2ΟάUθz]ζώ…™όρ·ΞΡS:κœKLL₯Δ(„B!ΔΥΈμg :¬`yYΘΞΚFΧtΜf 5αΫο°pΡΧyΙ…NNNX­V.ϊšoΏ_@γFM0›-θšNφU­ι08³vϋƒnc@ηzΤ ­“ϋ©Σ”~w΄!kύμΜ>·ορίζςσž㏲fΦ<6:wα–ζN₯nW|ΒιΧ>_?ΑšΓq€€Δqbχ_¬ά‡8ϋψβ‘Έ—Ώχ!αΜAΦΞύ’5 ϊrχ/L©Ω…ή­βY<ύ[ΆŸJ"9ώ8;·όKr’cB!„βjTψmνκ^^œ<M:uiΦ”ζM›_°Οέwή[πg]ΧΡ4“'£©ξεuεΦO°ϊΟ£άΨλejI½<Ϋχ‘ˌχX΅-ƒ6Ε“πώ-9<νqζDeΰV§½ώ(­\­”νxΡυ©wȜ5“y/ γέ4p―Ո5γVΐά|ϊΌΟ΄ΧF°@ρ£ΥέγΧ7Ž₯ ϋrχ/BρεΦgή$υ³ι|8f>ρvW‚ΒΗπΏ67–£B!„WCi?χγργ0[ύKŽ‹bΜ٠r?uBλb6—œ9’ŽeαΒo1b‘‘uΚ7@ν ³~žΨ‡Ύη₯Ž–Λίώ΄fυ:w/R±ξ‚2!„Bq}*ά7ΌeΡԊι ­Γπα#XΈp'O,υ-㊒Μ°a#Κ?α(`Pς<£Ά !„Bqύͺπ€ nέzΌός«†B!„’\ϋωTB!„BˆλJ₯ι¨ΤL 5gρ•oB!„β:'#B!„Bˆr%I‡B!„’\I!„B!„(W’t!„B!Κ•$B!„Bˆr%I‡B!„’\U‰GζΖŝeνΊΥDGG_Φχ‚ƒƒι~3ΎΎ5Λ)2!„B!DiͺD±vέjΒš0δΎ/λ{»φμ`νΊΥάsχ rŠL!„BQš*‘tDGG3δΎ‰:‰CΧPEQxϊΩ— δ‰ΗGc`€a`2™iή΄%ΏύΆ’’ΓB!„βΊV%’Ž|Ί‘cRM(Š‚’¨( ((D;ͺš0™L†ŽλB!„‚*–t¨ͺ UUσŽάQ%£’°zΝz"6ώM§νθήιjLgε«χςώ&[‘2…κ}ήε»§Ϊ\εΕ1ˆ[ό"“MΟρφνήηβB!„β:S₯’“jBQUTEEQΟM―ˆŠŠβ·ί&ϊ911gxιΉη/‘V•:χ}Β€ϋBσε₯ Zœ―ώΒιμήq{λ«­H!„Bˆͺ­J%ͺͺζv(EF;, ψΊsΧΐΨόχΦK¬UA΅ΊβζξŽιΌ-Fζ!–MϋŒ…‡H2ΌΉ‘γ=<6ϊN{( dφcŸb~'i?Ν㏠(ΎMι;ζyjkbΓGγψhC 9χc²™ϊ‚)χΛ3Š…B!Δu§Jυσ§Wε―ί0™L˜ΤάTΑΣΓ«ΥŠ““ξn$&&aΖ•ΜHbνΗ―πelžότkΎώό9Ίf,βΥ‰Ώ—_­ΕχΣΧγΰϋΜύζ ^ιšΝ’IσΨf«Fϋ1oςΐΞ4ύ%ΏόςήT΅.ΆB!„e€Jt€§§σοLΔfwΰξαΖέwφ£S‡Ğ=Λ―KV :ρ ‰τΈεζ‚Q’iD}ϋ8~ΜίΧBϋ§ΎζΕ°υ,Ϋ\;>Bλ`¨Α]c±aδ/¬<Ρ“ϋƒ ‚nΑέ-Q―{ϋτη%3hθŠΥ€`rrΓέέMΦt!„BˆλV•J:άάάxην7πps#-=ƒ§Ÿ‘πΞ] bνΊυμΨ΅›Ν›rίΐ{.±V• ~―ρΞ€ΰ‚5Ξ՝ΡEsΪʝAηΖ'ο:Τ­všγ'50R«`CqvΑI±cw”Υ !„BQυU©€Γj΅²|ΕJvξΪCZz±gΞr&6–k@ΧυΌ†¦k—X«‚Ε­~ώώEΦt8Γ0Έ`‚–‘pnΨBΕl’ISB!„B”€Jυ˜wμΪΓΆvπΤγω䣨^½:YΩ9˜LζάuE©{u§f ͺM°Εαη’#ώ‡Sktώ’σβ(( ςΎ!„Bq«RIΗΩ³qψψΤΐΣΓƒuœˆŽΖ€ͺy Κσ£[πώŽ«[E‘xue@xK¦ΓΦθD’NοζΗΟqΌI_Ί_ΒeS<ρυ1υχzŽ$$’j+ύ;B!„BόU©€γ–›»β°ΫydΜxvξάΝΰχβκβŠͺ¨ (šχ„z΅Σžڏ‡GkοbΚ„όΨψΛω.ήz±/ώ—”ΟΈnπZΔ/䉆σΦo1Ș‡B!„ΈU‰5!!΅9πο>έΖ½ρF±ϋ˜MfΜ&3ΰTPvΰΰ~BBj—P³;=o)=/ΆΩ)”žγ?’ηψbΆ™2jΞβ’e–p^ϋ5όάΧλφηΥύK8ΎB!„}U"ιο•uλΧςλ’Ε₯ο\HHHmΒ»t-§¨„B!„—’J$ΎΎ5Ήϋ{+: !„B!Δ¨Rk:„B!„U$B!„Bˆr%I‡B!„’\I!„B!„(W’t!„B!Κ•$B!„Bˆr%I‡B!„’\I!„B!„(WUβε€±Ώ―dΛΠ‘d'%]°ν•>ο^Pζ]͍žθEη–΅―ExB!„BˆT‰€cˈ4lُΠΠ"ε1ΐΐfΝΈ©u“"ε'b’xaΚοDΜyδΪ)„B!„(V•H:²γγρ %~Μ"εG€E}κγ¨V«HyΫϊήΔ%¦_Γ…B!„S₯ΧtX½ΌxiΤΝ ΏΉύZΧΒΕjΊΆh™=²?Ϋ`ΏΆΗB!„’ ©#Σθ™gˆΟXDςΌ…Έ5ΕΝMΖ±|{ΜeΧc;½™οΏϊŽ•[q&MΓZ=‡πΤψ[¬i™B!„―J'ΥΓΒHάρ0Νξύ”]ίOΐ―Υ3ΫTUEΣtL¦’³Gτ―ΌφΤLb[ cτ{ΟΣΠΗDκρέl=ˆ$B!„B\΅*“tĐ»†£0U݁Ε#tqgγιQί…ΠgLͺBfΆ7§‹Wj$±zΦ6Λτ{γ——dxUΏ…όη^™‡X6ν3F"Ιπζ†ŽχπΨθ;iμ‘\X]Iϋj™ύΨT\& ΓΎΰS~Ϊ­ΠgβlmœΞo?aΪβmD%kΈω7’ϋΘηξΗ…GB!„’κ©IGθ—ΰS΄πάΏ›­^5{ «‡ [Ξ$λ,λ‚ž™M‚›3ƒΫΰαφxΙgl'b§…N―t/H8Š0’Xϋρ+|™r/|ϊuM'Y=γ=^θΒτ·zα{Ήϋκ§X:ι+Z~™YΟωγξaΖqΰ[>ϊΩΝoΞ’›ƒΨΘ=$ψ{IΒ!„B!ώ3ͺΜ’€PhΤ:χΣ¬Η3dŸΨΛΑ/Gq&YΗΠ²°k7XDrΊF‹ηΣΩm[ί %zΝ…ορȧǝζŒV‹Πk±Ϋ„υ,Ϋ\;BλΰxΧjΞ]cQ{Η/¬<‘_ώΎF&ζΆ3gCjzUΓΥ hšbΖΝ«ήΎA4κΨ›Ξu‹G!„Bˆͺ¨Κ$…™œΓ8ύχrš™ƒ]309˜=PMVušά3•˜M3J­οb£ ΪιhN›B©tξ2)ήu¨[ν4ΗOjW°―…zλS8₯0‡ dLx3ΞS“±9:£Τˆ…B!„¨:ͺd‘ bθ,5ΠrRiΪαv©'iΆ'φΔHό‚±ΈxA ]xΕΗ%†'/ώΘ[Γ0.¬ΑPŠΝTJίWΕb>ο’«Ύt;•―>œNΚ&y„χΧΖKβ!„B!ώ3ͺda` ¨& ]'μ¦pάBo&€I7œόZΦ Χ:=ͺ†^b=Š{ Ϊ6ΚdÊ‹ιε›‚jlDqψΔΉQ #ώ‡SkdΊβ}‹‰Χ Άάύδ$>~Π›ˆe›ŠG!„Bˆͺ¨J,$·Ίϊz g―‘¨ζš8{ϊaK;EH“ž€ξϋE5‘vΰ; ΝAꞯπUCw€RB^₯Τ€ηπ»XρΒ'Ό<9ƒ‡΄§nu•ΜΔ“Ος§]γ _ΘΣΏ!μρΫΉΑt’?§/βx“x!X…B9βuιϋ¦]Λ’θκ4k‚·)Žέ‘ 8Χ¨k\I±’CB!„•P•H:κ΄›Λ‘MC±g€ ^a=8υΟjw=αެΐ]ΓΠ8yΧ'=v/ΥBΪ–X·KΨ&NτεΛy‹yoΒT³ΐΩ«οzž6a~΄ΞœΒ” ίrVσ€nϋ»xλιΎψŸŸ(—ΎoaF"ΫΏωŒΩ'’°™½¨}Sž΄=.WuŽΝΓ+:!„BQI)νη~`ό9pfKšmeθόn(ΨΣΌiΞΥCrG5 0Ȉ=ΐΡuSi4l1Ξ^u*:Ϊ”5«ΧH’!„B!.Ι-‹¦V‘Žb)* }ΕΩέί΅a±ϋ mSpυGύ{ηIΒ!„B!D«ΊI€’P³ω`j6\Ρ‘!„B!.’ Ν§B!„BTE’t!„B!Κ•$B!„Bˆr%I‡B!„’\I!ͺ γΜO<}Χ‹¬H6@‹dώψ™Ό-;wcv$‹χ0ϋχ¦πX³ώ†žΓΏZΙu–‰"ǞΔƌψλδΟΏφUΪ!ζ>2€χ6Ω+:!„’Κ«ΪO―•H:Ό1ˆΆzΡ½ΉŒij)²U?Ύ€ργζr¬ήC̘4ˆ «MwMυypς—`2 «g3χpCžšϊ.7ͺξ΅jΠ₯£’»Ή\sμͺψ:ωΛqή΅_ςŸ˜žε­>ήόΗΟΌ ΙuBq}‘‘Q†T||t6­ΩMN‘r£λΦ’μνCYζŠΙ”ΧYΣ‰‹9‹ΉQ':ϋP3ΠWEΕdΊ]ΉβŽ} [Α ½‘Ξ8*: ͺF›BˆλŒŒtˆ2d"΄];b7fΧC­hλ’Wμ8ĚυΪ΅―Λ_ΟνmdF²|ζη,Ϊpˆ$Γ‹zξα‘GϋΣΘ=/•HΨΒόΙΣYΆϋ,ψ΅€ί½7œΛ’΅CΜύ<±#fmχ[|²ό$iΆΧΈύ/3ΝΗΜην€ω ύ܍Wg>F˜Œ¬Γό6σ3$ΕZ‹–}eΒΰVx«yuϋ —±C±7…_φ(τϊί,n”ΑξEŸ2cΙ6Ž₯hΈω5’ΫπgέΩ/―ÝΜζ™―^pμχϋωBIηv±γ5.τλ¨bξΈ)¨χχ%ιΗω¬9šΗ ·0κ©{qY9•YΏν"V«A³ώOπά-©¦\Κ9NΑ4΄?iΏΜη―ΐ·)}y–‘mk 8ΆπΡŸβϊΚ—Œn’‡‘Ό‚WF€υη“்mτσϘE—ΝO1yS 9ΡkŠ™†#g2ωή`”KˆεrΞ­P«!iΗB>ϊOφ?Cͺɏf}ΖπΜΠΦx)`dD²bΞt~ˆ8HœΓ€6#yσΉΫπΟΊHyN qžηςΫΠLξΙωώΒX¬ΟώOΖέ€έ”ΦN…BˆJ J$±Ώ―dΛΠ‘d'%]°ν•>ο^Pζ]͍žθEη–΅―Ex’€΅;ΣeοDVοΘ€mGWμώ"Β…ΗλDžK:Œ$Φϊ*_₯φγُ_₯ι$kf½ΟΊ0υυΫπ%–“ήε7ε>^Ρ“ZΩ²ψσIό«έ@χ"Η¬F«‘oσ¬>wΣF2klkœ\Qw+…MŸ½ΞwΆϋxρ³ΧπMΫΚμwίε£Ÿρv―ΌŽ™~ŠeŸ~M«/2ν)ά=Μ8ώύ–ΙΏΪθχκLΊωΨ‰=Ό‡?―s9₯ψc+FλJ<·βw-ŠŸηοδΡ§?f˜WΏό“ŸήΒ ·ŒζΥϟΖtx!oΏϋ9ΏtœΞ°Ίι₯Ÿ£ŏ3#ϊΔ»|’pτΧ‰Όσι|šΟy’ΦW4ζιI»Gί`πρΗΩήνs^ΏΥ“ΥΥHaγ%ΔrΙηV―πψ˜‚«{M<Εƒ pŠ]Α‡oMαϋ6³y€Qλ§ΌΖΌδ><ϋα‹„ͺρMςΔWIΊHω%΄‹«jCLQΕΕϊ#‹½nWΦnJm§B!D%P%’Ž-#FΠ°eK`ΔZ|yβ²Kˆ3ο'q…mˆbcΝΖΤ¨˜λv…ν¦τv*„BTΌ*‘tdΗΗγJόœ9Eʏ‹ϊΤΗQ­V‘ςΆυ½‰KLΏ†ŠsLwιF­ŸW³%΅+·X·³z«έήFέsn/-&šΣj(wž»ΕxΧ‘ŽηiŽŸΠ›ΙΊ#q€€ΖqbΟjVνŒ+ζς9ZΤ:~]·›¨3I€ΔewdΞή5p)₯#WΪΉ•‡+=Η¦`κ…dρχ₯ό—BΒ‰Ν|³pI%ό εΨί&’ΆFp$!‘„TΫΥΗRηΎΈ'νcΛώ3$Δbέόy¬MΜ Ε·3·έ”ΐ’Yί±γT) ΗΩ΅ν_’}.Rξ}ιq^Ι9•k±Χν ΫΝ•ΆS!„βZͺ2=λrΧpζ―ͺ ;°x€ξ ξl<=κ»ΰŒIUΘΜΆγαζt‘U¬nΉs£.X³³;ξξΐ iϋ7Lœ{£ruΩΌίXžήoŒΔ˜χΡTοŒ…š-ιH8ρŸ¦ρ΄wιS-…]ί~Β΄ΕۈJΦpσoDχ‘Ο16όϊz|₯ΡΑπ± IDATR½ݚOη€₯;ν<8Ώk¦xΠnΜΫ<<ϋ3>κ;Ξ:<©Σn―?Ω? €ΎO½@ά'Σyνα/ΐ·9ύF 'όψϊ+Ζ‹πΗί&sΞ,ζΏ2‚˜4p hΔ-#›–ό=#‘νί~Μθ$μζκ„΄μΓ3·Γ₯δo]ΒΉ•ƒ+=Η‚οϋγ‘ΗΨρWΌ0rfΏ¦τ:‚ξ§W•ςEWΪ A‹Ώα™_RoΨ'|pwν«‹₯ζfƒΧk"3ήΕ·Š7 ˘ήρ,Λ?‡'ή uϊt&=ώ vW;ζνV7^΄ό’γΌ‚λ[b¬ΉnWΤn΄ !„א~ξƟΗ\Βσбu~υG™»άlυ"¨ΩKX=qΰ‹i=κg–~ԟ€€ffSΝΝ™ί΢ᡏΏΏ΄8φ2mΔΛ$=φ/uʝ°sθ/~;S“–jaYΞΔΧ§ΑΫsy¬q2ΏΏφ_ΨρΚ=©•Ή—§NζΧλ3nΑ»τ<=ƒ‘oœδΞ7ΗΡΝΗAlδόo‘sέ’— W%kV―)²0rην_&„B!O…ϋ†·,šZu¦W„B£ΦΉŸf=ž!ϋΔ^~9Š3Ι:†–…]3ΈiΔ"’Σ5Z<8ŸΞnλΨϊ^(Ρk.|Η₯pjНώαMρυΖΏiO:ΧI&ϊdzόVξπεŽGο₯ΉΏΎu»0ςώΞxδί‰Μ|₯W Ό}ƒhΤ±χ*αB!„βrU™€£0“s§^Nσ!s°k†#wυ«ΩΩΥd%!]§Ι=S‰Ω4㠎ΰΰμΦΌμΓά?π.ξ0Š/φΩΡt -ζ$1¦ΪΤ-τXKK`mςώjȘπ8f>2œ§&-bstζUΟcB!„’*«’I‡‚Š‘;°ΈΦ@ΛI₯i‡Ϋq€ž€I۞Ψ#ρ ΖββΕk .~όήzs1ΙΝδ₯‰S˜>ν]ΥΟ_ώbpΑβ “ιά£]U_:ΚWŸ?N'e“Ζ<Βϋkγ%ρB!„Χ­*™t(ͺ CΧ »)·Π› i 'Ώ–„„uΓ΅N‚κ†]όωό₯Θ<΄—(ί[>$œ°Π@ό}Ν…ΛY ?Η ’NŸ«[;{ώ£\\ƒΪrχ““ψψAo"–m"Q²!„BqͺO―²Ίϊz g―‘¨ζš8{ϊaK;EH“ž€ξϋE5‘vΰ; ΝAꞯπUCw€rωy•³/‰{ω{ί|j¦°wΙ—¬I€`@©Ω‰[šΜcώ¬i>ώVjΩ±μ«Υ$uЎeItuš5 ΑΫ—ϋψΚ5p½ž]%„B!D!U"ι¨Σn.G6 Şύώ ,x…υΰΤ? ¨έi4φ„C8²t Cwΰδ]ŸτΨ½T i{ΩΗ37Β„>ο3ν΅,PόhuχxΖυc)€βGŸ§_δΜGŸσκˆΩP³}υ’ΡώCΉ_6ΩώΝgΜ>‘„ΝμEν›ϊπό£νερ•B!„βΊU%’Ο€ž΄ΈλLΡBCηΰwC9Ίz7 Β5ΈQ‘±8Άa†-.ύζ&ŒώͺΠ~ͺ/ύŽήi6ςώ€ψΆη‘χΪσP~(g~δ LυπΦΜW|B!„BόΧT‰€£XŠJΓA_qvχ·Dm˜EFμώBΫ\½λQήy8{Υ)χPlΡQΔXΌπ’W !„Bqͺ›t( 5›¦fσΑΧπ YμZό=g‚;ΣΌN ,I;ψζ‹5ΠφEΒ,Χ0 ρŸρΟ?Ϋψdκ§ΔΗΗWt(•ž――/ƍ§vH(‘‘‘Ψl9R₯`΅:Ρ AŽ‹ΊnΫR~ΫhuSλŠE!D1ͺvQ!LXrρΣG?ρI|š³7΄Ζk£;ž{A —aڌιtκЁ#GTt(•^½Ίυ˜>c#‡€S§8;;WtH•Bvv66lbφάΩΧm[Κo³fH!„•‘$—ΝJγo3c`EΗ!ώ+²²³ˆ:…ͺVΙ'X_SQΗ’ΘΜΚΔfΛAQΣΣ+:€JΑb±`³ε\Χm)Ώm!„¨œ$ι’‚™TŠ"Γd—Κ€šΠuÐΰ@ξ΅iKωmC!Dε#I‡Μb±\—w¦―”Ε’»xJΣ4 $ι€άk–ςΫ†BˆΚ§H1ZΩQQqˆ*dPEπc΅Z―λŽβε²Z­ΐΉ»ϋt#χZ\οm)Ώm!„¨|Š$KΏω³’βUΘ Y¨Y–*τξ΄‘Ε™ƒG±4&€Z1ΣrŒ,b#cχo@§ zρΡΡΔ¦δ`XΌnD΅k<£%nΆL­ΊP…t”ΦžΚ™Œt!Dεuύή’’°Z­(ŠZ1Swς cš_$s}ξŸόγ[»’(*ŽLZω˜―ϊ™οΏG;wŽ„cKΤ―YΜωw³ͺπŸΙΌ±ƒψ`³­άUαm©˜φTQmC!Dε#k:DΕΡ"™Δ[$›Ε­―ίGŸZ¬T΅Όξ @ uη/:V”‹ΔÚYŸ€£ͺ n­ς@½Sό:ν[N Yvk‡gyΖ²‚_ώΝΚλϊ–rΜ«d±VτH‡Aός7ω\}œW{y•|¦†‚YU0›Œko…Ά%8―=Φ6„BT>’tˆς‘GρΝψ'Ψέϋ ή»έ·P7Γ vρΣ<²ς&&Oy€' ¦λϋ‰3VK9ΜΓ7μd$ž%6Q₯ζ Έ+cOr*.•l¨VWΌj…δ₯ Š–Βι#'IΜ°£Xέ©B-O ™Δ8‚­ΦTO;s ΄σψαΟ­85ΐ7;ސ^uQvbχd\jέΘ .ρŽWρυχ₯Ί«ΉΜ»˜VKήέμςκΓ:†’^’k-Zφ}” χΥaσkΓYΡό3>ŒŠΖ‘ΉσΔ’ž™χ:έ=ΘZΟ»ΓζRσυ ŸΎΛžωΰξΪUfΑ’ΩbΑΠ΅««$οnτ™„άβK½›γvz–EpLW1ίΖC½,lϊv&Η²MTσΑ#=P\hΣ·#λV,dΪb¨ΩΊ7w=—SS"HΜ›.£(ΩD­ϋŽο³` λ*fΑn·‘›ς›ηCΤί=“%G²Ρν64} KM­ι8n"ύ·²δ»Xe.³¦Ω’Ϋ]/³ιJZ2ΧόΜw‹·’ucξΎ-L=™ ΣήaAΪνΌ4υMκ™ΞyΦʍuۣŌe[χΩΌΣ»h6lΆ#˜‰αχΟΏ§υΧψςΥ,ΪΉIE–Žρ’ωΎšώ,?zwζξύι\Χ£LΫι΅hKŠvrˆέΎ‚ΏO%α¨ή”^wδ–“3ٚ–ί^r8ςGΕ΅ !„•O₯I:^ρ«ΟΑœ ~JŽA+tσbεe&'-)#GE‹ΥΫ Υ)€F>AΠφiLˆ+γGs¦% Q“GόY–u•15¨ƒ²~sύ‚Aμ¦υιΒγAηMM1RΨτΩλ|g»?{ ί΄­Μ~χ]>ͺ1…‡Β™΅_`<Slί•—λΆο·Ρ½Ž£ϋ8hnΜ-u,όλβŒs»ΫiRUτ«lΫFfΦϊ}yς™VΈžΪΙίί}ΑρTŠͺ’Ί{`UœΩ½φκψΕ'PΝΩ„ͺͺ((œύg=Ϋ’“1€c[·Ω¦5ΥM$gζέΉV ‡ »f`hvl6;: 8μ8tΝaΓf³ ͺ’CάΑ ,>Έ―z-h?ς-nKΨΘO?o!^ρΔω*{–ωΣ‡:ιΠ’9΄v1‹–ξ‚ζύxΰƒ1΄π6ΘΚΚΖ¦ ›XΉΥ‹Ÿ"¬ΊA4­f`³Η’¨ *rlΩ(δ†’‰₯ύ#ŒνˆΓcθωεΊ]₯f»ϋy₯λ`Ξόύ3_Ο}™_άΪΰtS6ΙΗ΅hK Ω‘«ωιL"ιΩv4γn­;ΚΧ5£p{©ΈΆ!„’ς©4IΗ 7nkΨ‚GπρΩ#DΫ³J,/z6Ό~_7n󫆻‘MtΒqΎΩΎŠ™Iew˜’ ό η=σ*FFg_mχ  λ*j»ΤζΫ ‰λw'5‰eΣ†Γ„t~’@(tCΦHŠ`ιζξšv;|πλΑύ½–0vΝV\‡αΎ|‡·2yΫγ›§ΫqVν8„£]±φ“ΪΰvΊ„ΡvςΌ ;έ+•ΫQΊΊΔVm|cοiLβΪ―˜ύύ&bL^Ττυ‘Zώέγ˜X9€aMζΦ­+ωω‡•Ξ©M¨·‚’8ˆ‹OAQsηγγ°a3ΜXΜΉ‹Λ…άNΆ ͺBΡEηωsψΟ_ˆnΨΙLŠeΧo{Ψ½· χ=|?χeαΌb2‡/«Ž₯vΰ&Ο^‡ί€'w+όLY€€Ÿϋ-Ϟጩ6!^9Ψ4=χΖΉ…E 74 žγΈΘÖIšMΑ³YφυgαΗ3γ33΅ήΔ epίΰZ΄%#+ž4ΟNŒN£€j8[L˜-*ξUΟk/U·m!„({•&ιΘ±εP;0ΏΎψοrε»Ψc,͈#;'» άo§ ߝ=Ξ²ŒΈ2υPΤzόߝ½ŒZΑ]Η’e©Nc?°;Ξν€g‘IΞ 1;‘zWGuΙλθvτΔτL`BquGυvCQɝž“ ޞ’Œž ͺΏJZ&νZa9zΗ±tπͺ‰©š9·€τ  ‚‹'&ύd ψΦΔ” PΛD;•‰RΛ%9£˜ΊTŒ”d΄ΤΠ 0[Qͺ{ar«ˆ‘•Z»Ίp=›βϊs‡Ύ‘ˆ#‘ty"π‚»ΊΪιγDgοcίθ|™Wf8rp΄&³n3n΄/ΰΐ)υŽlγXέN<ΫƝ•3·sάQ‡γϋ£ iڏ*< ξͺ;K'WσΕ¬άΨ’+γήΏ—μCYΉt9›»Q§~M\”tυ53wΦ‘i›NŒ~Ώ;ΫηLg}Ί‚‚ަ+ηbPΥΌΕΐjAΗTT5wΠΎΚΉ;Ϋ#1<<¦uΝ§Ψ³m!Σ#γΘF-³5W;‘ΆΛW ϊ²ζΗ…L7k“ξτξu mBsΧ[  hΊQ8f#w5‰Q8ι0 @Ε€hθ†Rdί‚ο8’9²εOVόΆ†ƒF· ϊ”EΠS3q”Ρ]ƒςnKNΥ:1fμ-[Χ°,β,ιv•Ϊ= ψ‚φRqmC!DεSi’ŽΜŒLlΆ’S“θΠΊ5ϋΣb²2³ Κ;ΆιˆίρZμΫΑΜΜ3œΡνWuLSυ`š9gΪΆCv²@V&§ROΪCΓ07δ!=ΈΗΧ-ν(_ρ3sΐPtHsαώξχ3A-j’ΑήΓ«ycνnvVsEQxaΨ`ψλ­£y8ώυΫκ=ΚGυάpnψ§{λμάρ%wˆGKwfHΧΑŒiH-5‡γΡλ±%•ργo#cΝήHΞν‘(Ξ-YπTSΦ,]Ξ©N\XΧΞ³΄j<„7Ϊ4ΰFg…΄΄S,ήρ;oœN»ΚϋŸWF­Υ™.uΎ!bs,mυŽΤ ηιZΕτ, ¬mxdςXZzκ₯bvΓΫ=‹fuΞ°ωί8Bw$δ¦qΤhΰAγ€ΨΣ„ΣGͺ6°f•YΓQEΉϊθΜ³ΨΈŒ[<lΤ‚ξγ'2(e#?όΊ‡ΔτDβ²-xΨ"ω{ιΆΜγ77cχX@ΙMςϋΚλ8TE)΄έΘέ€(ΉΫ3&Œμt²&̊ §Π~ΌρT¬§χςΟϊοX{&#oP«Π1ζ< ϊρWΩK·₯‘’ϊΡaΘKt ™=«~`ΡΤg˜_ύž{‘/!Ύψ;~'κ”FːB?CAUΐΠ΄σ’Ξ%狁#ςG^Ÿ΄G£ΫΈgΜT^lθŽ#+“μ”Œ2ύέ,οΆ”Q»Α ω쏽d™€'X 짐ϋσ-ά^*m!„¨|*M‘‘™’(˜M&rl9„5hŒ³ΕΚΊυk.(w2[±m\Γ{Δ_Υ1΅¬dλ-ιbaιŽD2=έQέ¬…#οΔm­›ρΡΆθšάΖ΄^7³ι—u¬ΣUϊvΙ³ΥvσΔΚeΠ½ιί²_φ°Σ{ΣqΘΥ—{υdέΑετܚBŠ-›œ”ŸψΔυΊDΝγ‘ΣΩ864‡JŸπ‘<'WύΖΏ†]²8mΈ—}6nΏ°.Ε· ΄23oν—,Ι1δ„_fV…$(tμT‡Ι_₯^ηg (¦sa &ΐΨA\V ό‚Ξo–.„…ω±pίοl?T“Vχω’:;sSƒYχΧ?$Ϋσ@JΣ”―H™N Ρ3ˆΩ·_χm‘Z€š’b£΅vœŽsJχ£Γm5p8t΄όQ ₯Π]fUΙν<*ηξVηn7Θύ›Z(^ŽƒΪMBɎ،Ν7˜G ίΝ%&Ν‘rešjZnk.“§Wιv²2SΘRΜ„ή<‚7{ ώΐa2Uj΄§W«̜3υFu'Τ)Η³ j‚™¨m›‰jٞj7Ό]Ο=₯κόΈςΛ•ν;e½t233IMN)—)‘εέ– ΝNŽW}κ˜~geΌ7-ϋ€³·ΒισΫ‹RqmC!DεSingff’(*ΞΞ.ΈΊΈ±cΟ­ωτσΚ·οήΑ’ΥΏρ…–pΥΗ4rρ[γΫεI6Μ³AξψœMΖ(Xk pμπζΔ&—Μϊ;Ψbυ§±«‚jiΘύυ2ψjΗί¬KΝ .=š9lζPhξqΝΎŽ“Όvτ §²³HΧ μΩΊ¦εjΛ!C7Pς`ύLζoί̚ΤtΞ€ΕπΧΩdΕ‡}±uαμ„Yqr<Š3ΡΡlΪΝoΙ%ΧTΎό;†S'ς~¬KηώΕ>‘F©Ρ…ΎmΣXςΩLΦ‰#%5Ž{V³jg&‚›6FέΉ’ΏM-h¨‚βI³΅9²κ/NΧoƍVΐ±ωO γε_£+.ΙΊBͺͺ–ΓG#-6žLEΕδH›{筏§3ύγηΉέλ+7G3ΉβιlΒΓΓtξ{&άUg<]L¨EΆ›p­ζ„ΕΓSΑ1œΨΎ‰S΅ξβ­©“xͺG-LιqΔfθεtN…GΚπ£kΨ³INΚΐ)8ˆκš]ž|›!5ώaϊσ£yxμkΜή‹Γpβ¦AqSΒOΌ:v―>‹~ ΗPj„lN#1%l»ž{WΎ,?Χ¨-§·³zΏ37?χSί›@§έ¬έ—†‹§εΌφRmC!D₯Singfdb΅X°Ϋ-|υν|–eΔ³ΩΕ`|¦‘WnfώΒω,ΟΜ-ΧΛdώΎΞΙ«Έ=v7½κ5ghΧьj³• KΧς‡ @γhrrΑzgΓa# 3¨ž>„κg™—VhαiΦYώΝκJƒj*Δε~o\,9₯D‘zδΦυeΪΥw•qπΦΙ;xΤσ :΄‘i6ς§Ν΅BΦtδRό:Ρ9t6³ιB'Ώ‹όΰ/Β›Μ9³˜Κbΐ- ·Œl €₯~3f,η`‡6Τ5(ψ4oA΅/φci–»žΓΠ±ηd“c―zs,Κο-yv±δ›]—³lόjZΡŒΓ,ŸvΈ˜νρ%3T₯ΰŽ…žΈ› vΤY° ½œ•ΟΎ ΆόίCYJ0}Ÿ›Ζ½NfL8rHJΙB―Ωƒgέ‰“IΑžž@b¦ΒˆΉΛ0₯Η‘œS8¨W¨ά†­">_Ή·%‰Šψ‘¨ˆΒe_q PΙ.ž*ͺm!„¨|*M‘‘‘Αζm[ψ5β/–VWItU‹–―“₯^¦‚ς²δΘ‰eιώ•,‹άΙγ]ρf‹C¬9 γΠ/±1ηΞqΗoω4ΐΐ0ε³ͺcΏ`Έ_α‚uM&CΗ(\WώΎEξb*ZαZ1uiόώΟ6 εΎFνωpD{Φ­ό’§Sτ œbεǝ—qηωε¦Œ˜ωσΉέ\λΣ{άDz+¦·›yυ§›‹~½ΞƒL[ϊΰΉKSFMϋΜΒΎ–Κbώυ¦Μ_X=‡τ”Ο/wd”Q€(5!Ά˜ l)/?–„BTF•&ι8©jΌ³α7vωΊΕ8©κΌ±‚έ5έΚht£[Ί]E±šQTΠ³Ž³6:‡½«a"₯Δ―jΙQš¦dπ›έEΡΐαE˜K2k2Kκή+(v[n’’¨θΩ©D›s#όnwAQu ›Žβvέ‚³- ΓaE1l¨ήΤQ/^Žlt»Jšγ_l<ΜʘA¬lֈwΧογlY]7QζdjΘε+Ÿ‘ŽͺOΪ’BˆΚ¨$+‚=‹--€ψς²`φjΘS2ΫNΗ“©Q=°»πχžXμ8—ψ]#+’/£ΫσA·NlYΎž}ΊwυμFƒΈΏy"­„ΐ‘MŒΝ Qh]ξΫIΌ»;ρ™GXӁ»Άgۊμ³»qc°/G²’9κΔγ͚Πό·νœv©ΗˆN-πUβ.ZW²χ QγΩ|ς ±ΊνkV#ӞMΖΕ#•€t/Ÿ‘yOK…0iKB!*£J“tT«]ΫχβYw½z±lΕ ’’’+:”JΟΓΓƒ>½{s66Ž ΙΞΞθ*ZΆΌ _ίΧm[ΚoB!*'I:„¨`!!΅™0nό5xΏBΥ§λv»ŸΎ‘iZι_Ί˜L&<==quuΉnΫR~ې·’ !Dε$I‡,6φ,‘‘‘Ψl₯½FRX­N4hΠΓ08|ψ°\³<ωΧeοή=|2υSβγγ+:€kΞΧΧ— γΖΣκ¦ΦŠBˆbH!D‹ŒŒ€S§8;—ό˜fΩΩΩlΨ° @Y!ωΧeφάΩtκЁ#GTtHΧ\½Ίυ˜>c³fH!„•‘$BT0›-EQHOΏΰ½ΧΟήyΗGU|}ψΉwKzH%…Π› tŠ(%bD)" €A (}”.M@@ͺ )J•&B€€”žΆΩέ{οϋΗf“ „β/™‡Ο’έ[fΞ|w“=gfΌΰ& CΞθ†Π,».™¦L’.F=«zE]Œ"#3£€ΝΑmΘt\~iTIΩ!ΈΨωλΞ’6α?‡ͺͺb‡ν{ΐqiX‘Y.v]t²ξ^2W'?x«v Αύ‚ιJŠ’ !θ»α˜8.4ΛΕ‹Α`x G9μ †’6A ·AA)ΐ±_p{T-οH‡ΐ†]£Ρψ@F£±€MΑmA‡@P Σ„ώ=B³[)ρ‘-“λg.`ͺM…2Ε?ΝKŒtAιεΎι›$…Μ€h.ž%C²SΣγψηάNŸ<Α‰“gˆŠIG‘edYB$Y%υκ5|jTAJ>Λρc'8g΄λœ»CŠIE*l;e£AŒtAi₯TηtLž2‰+WςÚ΅όΌ};Ώ±ŸfMCωaΝZή5’rŒ|ύ^ζW9ΓόoΣ5cZ”Φ> cΪ>ζΞίG½7[PΨΣΌ%]!,‘©₯qόΟH¬Š μ{5!7](IόύλZVύ¬ώiκιR8Ήf6 ΆεR²Šk@ ZυΞ€¦ a€ΨέΜyoΏžMBη0OχNοΖ>HΚ9–Œψ€ΨήΣhuςψϊ§+ά0₯Σv=u^ύ’° Ÿ3m ζ}½ Ÿ£ϊΛΣ_n£wxή-œ–U=)*‹\3=hηΩΆhλφE―ΈΨ¨ YpS›'„g²τyΈ zΛκΉl<O<ƒWͺΫγ σ―y§ˆu±εtRaš•τΔΗKTiϋ"ύΪΈrψ»ν\Pΐ«V'žhL΅ \ΥώϊqKšqr“±ύŠ—‘YΔž―ΩBΦQΈϊΛl%taRνx6-_Νξ‹:όΛβεͺ§°ώ, χE?š@ <”κ `άGγπππ`ϋψτ“Οxμž{3γ>Ηάoζ°τ4ΆνΚϋΝΗ$Ό:~ΞΚ7šάAΈυ£™’{›OŸρ)΄/Μ&κ?FΒΖY,hU—ΧυΘG/€£Λωϊ»_ψλunθ¨Ϋq(£zω²eψλœθ8ŸΟΓό²οΛ`ίΔ>|ν2šCάY:δbϊβέPZa–L™ΙΖ?c! >ϊ·"~ΖNjMO/ς―£wuώšϊSφ§΅―;ν§λ©Ωo.SžΟd‘cΩ‘l™ϋ5«φž%Iσ¦jh^N-w ”³,6έΛα€[̎ΏΐΏ_}‹~ϊ"YŽσΝ°ρœ~z_¨˜οπb‘MT’9³s-+Χ$σ‘Žτ|§υuYg~`ζη?YΔS’>Κu/oΠlšn<ΘΛoMfY‰σίΚ_―ΰ‘YCh “Ρλ$τ:/šτŸΘ{†Ζέx•%#›’W³°*γIΈΑ‘6σίΑ3i0cτλX2ϋ-Φψ΄δ…nᴬβQθΓͺE­™UMfο¬ρ,K}†13>¦ͺ.–ΘX#Ui†·ΝfσyτDσΣΧίΣψ₯ψvl44Εr€‘yΡλ’7ΠΤ‚ š…τΔX'Ψ‚1καvν({7οα’*#I`!‹˜#[ωγjV―:΄‘O^™ΛΑTΫo©$eqώηεόθ9€κΗη²ρΌ ΥbFQw²IטζΓ&žx+W³+J_hΑ‡ή φι‚J©:>ψθΖς9‘M›3vμ{„6mNjj*|τ!!ε ‘™Κ/Nε«+eωKΘη; £₯qόθY, ‘ϊ<Zωp†„νgτμ…΄~ψ5ΊέμZHΈΊQ§στ„SΜV&›ΞχMζρt‹`Vο?@RǎψH@ζqφ5μG0rΡ‘šxΆOύœ-JWΖΞyšΰΜSό0k*;oT£Φλψ†~ƒ>’Η₯yόk>|ʝљH‡²“ψmΪX–άθΔ[“ΗREw…σΎΰ£I.Μψ°ώJkζξαεΧ?η› 6L`ό΄ΕΤ[0’Ζ²£‹3Ξwθ…-°­$svΧzVm:υ:ΡkβPκϋhdfš0+ΆάMγdԁޙrυŸ€Ό’…Ωl{BΪχ#ΌΊ;j<Fέ6πOΌBύ²φ T[²„$k˜Ν&[>*’,!c%ΛlBBCΣdΚ6νΙϋ­{pύ΅|·π=ΦΉ=Jx·giYΉπœμ"Χ,a?ΫzΣyZwφ²`%„:e4Μ–˜|Ϊ ‘Ω«D΄.‡Υ’’©φγͺ₯θuΡΙ2jG€΄Œ,ŒΥΓ9ͺW䏕ίpι†I–‘Π0EώΚΧI3YP΄³Έ5nN#gδτμ‘IB³Z°ͺŠΥŒΩl$d)‹Έ3{Yζ ήUλΣ¬ί8Ϊ%μ㇡ˆ—X–Mγ‡γ'ΜgΠCη™?xΊWž#υ‡Eό|:ΙΏaCίa@S_$4’Ž,cΖβŸ9eλ‘―Χ)‚·_i‚c3΄dŽ­˜Κ¬υ‡ˆJVp ¬E›~oΡ* „Gb4¬V=χLΫ=2sI+¦ΟΝ3―ͺ?Α³Υ³_ψ=E‹J«8|5‹ςΝ[όΓ^&w ·DΦΙ=66γέZyKΠφρσ1?:MξJέ@hΙ+/fΧΗΧοR‡ ]-Œ: Ρ 777›^ΕZβΆ(Γ3_φ Qˆ ψπάΰnμ΄žŸ/?ErΆv–{κ:Χ+‡ 4|Ύ#―ίΘ…8•Ζεζε)‹ O|PN―cΚόέtΙk/4"@—IJZσ©«έ…ˆΦŸ0qΔ~jсπgΫΡ¨œKφgCOΉ /²,ΆF«š£€ps‡Ή¦εΊ³š–=Ή)Η«vLςΦ°š3H5KxΦ g  Λ'OfΞL=Α_t§Z)錾›fjμuλ*RΑ; ³ Ϊ~ζΫfΥj†`Ι²ήΖν/z]lNwΑφ/‘k?OD—Ϊ$ξZΒόοχ­σ¦¬Ώe²G"΄ΜxR=[Π·_+j•ΑΩ CoωϋdvN‡„-(³ηwH ζš…Œ€Žύx‚γ'γŁ=όš?Λν!Ί€[―ˆ C J/₯*θp\Χpτ~Ή'>ΎήŒyο]Ζ}4Ž>ϊ_ozΏά“%‹—‘%ޏ ’Ž!Μ[t˜FΓλpqΩlφ”λΓΜ'+γΧβcz]Ξ‘Ηgσq;τNΘZ {§eΉΉοΝώΤΜϋτ3&ϊΝβσŽΩŽΏz•M_-‘qχ˜χv ξΩς+Q|?ϋ7^yσ V„ kΏ`άW‹¨Ώψ š8Ωzθλ>&}jcŒήΒ„§±κΡ… ~(Χbλι|ΉΦΒsΟγq?+1‘'Hτ.SΏ4M·Ζτιί’!“fπέcΣι‹Ν9±a%φΠχ,Z½““—HΛ²`1Y¨σ€Š\‘%-ƒW³χπ žnλΜ‰}G06}‡ΪFςΚυ+Dλ*ς\pΣa(W@έυ»Φq7”θΛ\“+ρlΉά²%ŸΚTφΌΖ₯« ”ΠSBPNo΅δμŒ3V¬–‘QλG°dY;Χ,gΒ°9iC‡φO€Rvξ€Υ―~ΝςΞΩΌ|1³ήϊ‘:γήTddYEΣ²­ΟΩ€ΟΑ©ΦςφΪ;Ά<ζ›pk2ηόΒΦwrF{˜vέ§±ͺEκ ¬…4+ͺ¨5Σ$@PT ΝΡ—Ν―ΝšMG€ jRžksξΡ΄bΡ₯ΐŽχ•_ωfήiͺߚa_tΕtvΫ6ma97*W/‹S™ xνΰN6ο‰%Ν"S±m/Κ;$’Ϋ>SΉ£v›΄τhΞ\2S±EG ₯Šώ*'-gvd&δΒΛGA©£Τšf[ΧXhšFο—{2ζέχπυυaي₯Μύf!!εx{ΤΫ$$$«χK|·dYkVˆZ1‚ΞkμŽ‚&#1ΆmΏΒŽa³ωΆJ(ύT†S:(KΰβjλwrΓέέΦ3%ώΖ†}Atω¦΅ύ%|Šή60ψΧίIθŽ€–ώс {ΊfnOΏ //Τ·υ’{w £ΞZ[/y“§m―‘}½ίΣ΄¬Ό’ΓW2Ρrl†‚"ιqσφΕΗί€Hu)l$ΌZ€ο/ƒ™>s9‘}t9>υŸ5ŒΏCygp|œ“Ωώ£ω@.O‹ζΑ¬Ωwˆy³οˆžΠ·ζ–΄ωόP.'Έcχ€–oΪ²δΤΙθt»ΗTΰ©BζTRδB_C›^ɜؾšU3F±ΨλYή~7ŒŠ:SZ’{mž1…G—C$5©n7ΐΑΞ±*Οθ…¦Ωev :$d 4EΙΉV9χ~΅ k­vt:ƒΡ5έ±ff`JI/`|^ŠZ³ ώε΄ώDΤU…ήΫ|Ϊ|Kp‘k€ύ ΦΘ5Ε’‹$άsΧ2b9½o3§xPV}ΪΌ6ξ)ϋX½αιkP>a3>I¦ήJZ‚‘r$@F’$@IF’τθ$ΠLi˜¬:τ’§Jψθ&―δπo+Ωu==»ο@vθ„(€έ…ΌΆ€@  Rt„…udνΪuΈ»Ήη,‹λλ烏eΛ2ꍷ±X¬ z¬VM#ϋ  Θ„tϊ€ρΛηδt8{ΉΩžv`ΨKΏ0xΪΚΏ2ηΚί~ώƒrε—M§89 œΩΗ4kΦΰ&€¨Ψ‚ T­]ύ–©EΆ^ς`‡^rœ$ +€•Ψƒ«XΈκWŽ_J έlΑœi‘ξSyηΎθξΖΠVρΥ«―πΣγαtλϊ MΛ»–Š‘Ž$ΪμΕφασ™Ή‘&H^dDžδ’_[&vŒ:ΐšŠ9έξ†Ι„΄hIΠΪ}:κΓ}(£Ίυc« &@9ΕΕh•ζmJ*±ΧˆΛ.ζnuΘ2hjώŸ.Έ"εΥ£œΏ¬Π’ͺν3 %œηό ‡Ξ\‘BY‰I΅™‘B¦€§}ωΈC_βOŸ#CΦ°^ΪΟΆ«e¨]-o9‘Γ%ΰβWW)wu%G4‡#ΉηW€ΝΎZrΗΟOOΤ‘ί‰jЌ27Ό}›1½΅½U222Έ‘œRΨλL9XT@ξ ΎΝhίhs―₯j6TrJγŸK&BκWΈ₯Ν>ωλh;bϋ_*&] uŠ‘šNτ©½l8u€2Aή(’Œ¦XΘςNeέOl‹χ‘Ax7ZϊH\“rG7$IF–¬X³4*>R Ӟί1ϋ—'Θ͞• ‰N΅Ϊ-ΤDzE)ΜπM …I‰wZχ½±£YΎr)oŽ|›eΛ—²iσ&ž {†/φδθΡΓΤ«_Ώ,0Έω˜Ο–f’βSPt–˜‚Yύm½x ΝιQ†Μˆ ±C7ΌdpΗWGφˆ†ŒAŸίW¬Œώ6½δκ₯Ռϋx=έ#Q_§$~.§o)Ÿ3h~­ί/ε«‘h8j ο΄φ+U‡\C»ξ`ΔβγX+ΦΐΩΧχ€Sψλ:Ύeopjσ"v%Bωœ{ZςXΠ:Φ.wEΧlωΔHώΝy’φbΎ[πu‡Ά%Ψ|–-Λv’ UΎ{’ώΎ:’ξα|h+Ό ξψΊ9”ν݊πΗ–σΥΌeΤFUέU~ϋ=<ά“·Cδ»O‘·žbρ¨ œiσ)Ÿ<[>'«0½OMΑ’™Fr¦„SωŒ+)S?,dΩ•dΜϊ2Thπ,£_m„“v.=% οqΗσyμu’aχ4œ°ˆ±Λ¨άγs>~ε΅TSŠΈΫΉˆ5Sω)i³¦3ϋοI°Έά’?οΥ«~k›;r{²’o…bΡ₯hςRcβA’αΪ~ύ«OΌύ%Οj©\:ς+»NySΧΣ€¬sΕΣY‡‡‡9ΦΚ?Gφs΅ύσŒ›ΡΨ½+Yu8Ž˜"³Q@Pš)ρ ξΎ,Υje㦍,YΌ”ή/χ€k—ξψϋπf‡°"΅Λ|fΣ*Cίρωσf°ψρ™ γΩωŽ=γΊ ς«GˆΙτ#°|αɚqφ$QώOρΥK­¨yKύΝHΈ†<Κ #Ρ¬άHmήΟΐVπ-MQz*wBψ7Yc?R·ΓΪO`ΞΗύY!Π°sC;Δ³Ω~‹\Žζ-Κ²θΫ„ͺ™‡V  ΓΘw‰™2‹.€²υθΨ₯ύuφκp₯IχΎΤŸ΄”Q}Ώ₯jŸ©L|Ξ±lšύ”σgςυ+‰΅zRΉig>Ω‘€{ΡVS±d™Θ²άήΩ,΄ε_σ–ŠΥlϋ¬Θ•žεΣω/aΤΙH¨Ά„ζid©Uι»p3Ί΄8’³²mΠ7gμ–§°&&fΝ{Ύζ€οX/έ ξFVN>eΫ2zήs8ι$,i $f˜1ίΞ€Βl]kV2₯ς„½=‹NzthX³RIJΙD½₯Ν­:Ȏϊ.y’Ά‹„4’φ¬!jγ±%\dLμ[2+Η5ρ8[—ΟΉJ’₯RΥ "‚β£Tw[W―ΧΣι™NΌά§žι„^―'..†/'ObΤo°v ՜AzZZž%s]u—X=cΊΞ“θά¨2‘=vπڌe΄žΦŸZNžψϋι‰ϊγ7Ξ·hmλχkE§fK™›§xΗ²qͺDΫ‘i;4Ÿfήd†VΌχC«μuθ?ke>7ζRθέ݌5Δ„τ|N˜Ή‘s“1™$Εfζ{ޜΛMW£YΣIΚ·μ’₯Θ5P³HKΙ"νζγω΄ω|υ-b #§C ‚Β¦ΔƒŽ;-‹λληΓ[oΎ’(ΌΤΓ6ΒaΟιhΠ ΛV,/ T["ω ϋk ―Žγ™Ta9«2;ςYΧj聐g#xα—7™ώ}k¦φͺFΣ}©ΕR^ͺ}§3Ή[EZΏ1žŒysYτn>OχΰZ΄P—§ `ΎήK οψ³>θΛ2)€F/ΌΖ°°86έ|‘–Θ‘₯3™Of½7vδAΝp)@έχ;ζΛ‰6zα]ΠΕ‹’ι΅o#4Λ±l¬@ J#%tΨΩ²e+oŽ™³zΥ–-[ιΥϋ%‘$8rτA\ΏMΓ ILL,§Γ§?ΩΚΣωžkΚΊ./υUι5s½μ―«„3vNxή[\«ΣqΔD:ŽΘ§8]Mϊ/XoΗ ­ψ`ƒ½—άŸζƒ&Ρ|γσ ΐΛαήΌ›Ϋ9ί–<dr|γj‡΄ ^%_τΙ²|αN΄ΖοRϋ–₯JšͺΒmη…fΉ8κ"‚@ ”FJMΠR.gY\€ο–,£χΛ=Ρ4FΣΎ}G¦LΫΙeK‘$©χιάθ0deύ”΅ΜHHGqφ£κ£/σή«‘Έί~©’*θt₯dΧΌRŒβ°c‘Π,G]DΠ!‚H© :μS­Ή9°9ββ2Gp_a€V—O˜ΩεξW–FTUΞβ= :,ή 4ΛΕQ1ϊ#‚H© :‚‘ΈΈx“π,γY¦”zRRRˆ‹‹š9`ΧΕΣΣUΣΠ?€#@V«‚§§ψ<AiEA S΅jUφξΩ‡Ιd*iSJ=...4hΠMΣ„fΨuρχχeσΦ­$%%—΄IŎ‡‡;t(i3@pDΠ!”0΅kΧ&$$EQξ~ρŽN§ΛιΝšεbΧΕΥΥ…αΓ^+†½:Jͺͺa±Xā@PJA‡@Pœμ5Πš9`Χ₯b…JDFFb6g•΄IŎΡθD5πυυ-iS@"θJ˜YsfΣ"4”σΞ—΄)₯žͺUͺ2{Ξ4Mš9`Χ₯ί+ύhΡ"ggη’6©Ψ1™Lμέ»ŸΠΠΠ’6E ω ‚ „Ι4eu1J¬ΔtD]Œ"#3#ηΉΠΜ†]³9 I’HK»eυ<ƒαα‚ϋt%ŒNΦ‰eN:ΩΆ2“Π,/v]TU} wkw\6X ₯t%ŒΑ`=φƒΑΆΕΌΠ,/v]EAγΑ :Δ’@PΊA‡@PFα@ ŒF# ‚Ž›±λς φψ«ΪƒΩn@ Έ_(ρ #==={wsφμ¬Vλ=έ£Χλ©Q£&-[΄ΒΝΝ­ˆ-Š–ιΠ2Ή~ζζ ΪT(“Οt%-“˜ΘKXkβ)ƒšIόεΛΔ€d‘Ό)_#„2ΕΌέ}5q7} ».βΤ*@ ”~J<θΨ³w7>^>Ό:`zύΝ±™Z­VŽŸ8ƞ½»iχ΄Ψ Jpc4‘€r ε Ό0υΌ·Ndσ₯|¦§θͺΣsΚX<~žΑΊH3– L&AS°ς덜Όrž+R*ϋϟ{~‰iXβ/ά[›ο¦o!bΧ₯D§V)ηX<ό}b{/aT3CΙΩ!‚RG‰gϞαΥCθ?°ožγ3§ΟΚyn6μ?%I’nzΜ›?»xƒ%’o‡}DbίωΌρθƒ·$ε}‹r–…Cή!¦ο*ή -}ސΑh(ΒΝά4ΰeΫ“±%ι66D³sήTPUdYΒ­Q7zU½Κ†Y+ΈͺIdZTŒ‘o1Κ°•ugf»»w©³€Œφ‘ŽŒόΪ|ςθΛ]Κ-v]Jt€C“ΠΛz†¦©Δoω˜―εŒmο]„-Αύ@‰V«5g„cՊΥt{± ’$ρd‡0~ή² €§Β:°mΣτzύ=OΗΊ=ilΫ•/ώπ‘σ€oV7―Cͺ^\ΚΠΑ ˆͺώ*σ§v'DW>3ƒ˜η“܏(gY8d8+.ηΣ»+ωΠρΣ₯ŒhXβΏ›Πˆί8†©Ί·Χѧ؜$£‘r:4 鉱Δ$Κ”­„»d%-ζ Wγn`²‚ltΕ;Έ!ή ))\;…Δt ’Ρߐ {@Λ ϊτyΜΑα•ϊΞυύPN/bυ/q ©Ώ)Ž ν« =ΛρcΙΈ?D5—xΞΕΛψϊγεͺ/t†"ΚιΈE3@Ι$αΪUb“20k2Neπ•3©Φ!o›«—UΈώχδςAh1WˆKίj잭―,#₯]'²t)²ME“δ;Ϋ­9όTΣψλΔy΄F²Γρ{(C IJ…Χg_ϊrϋŽ­yŽΉΊΈδ<:l05«–ΰ΅|»`q!Υ.γη§°wΗqΦm„SΞq… ;w’μγ‡cˆ!‰€γήΠU£ηΤ5tU5°ώΝ·#>%₯ΟBFΑΞ“Πaγιs-‚Cmζ3Ύƒ/(f,`ΖθΧ±dφ[¬ρiΙ έΒiYΕ㎿@ ψoPj‚ŽY3η0ό‘Μœ: o―ΌA‡γHHα‘A₯Ηhuβ vΞ YKW,νΰ7C+FV‰δη3·ήe=½‚/ΧZxξγy<ξg%&ς ήHZ»¦ΌΟΒδ0ޝ2†ΚΊ8Ξ'xβ/ΎUsΡRΨ?σCVš_dτΜπO=ΘόΟ?ηKί™|Ϊ>ΐζ|)Q¬]ό'ƒήœLο8~šόSή<@΅'‡0φλ7ѝ[Ξ§ŸΝΊζ³ιS P.²ξΫ?θ;b LœZυ“>Cπ¬7h’'ύFΒΥ=ˆ:ί wΝ œbΆ2i K IDATάtΎoς ύ}DK#8ςψΧ|ψ”:£+²–ΒΎ;Ψͺό½‚)Μt;—Ηύ,Ĝ;AB€7’ΡΕgΓέίx,£°wZΛΘΒX=Œ‘£αzυOώXω —nΨ¦J²ŒμξQΆrύψ!ώ΄xŸ@g²,#!{ψ7]NF.<@d“Ζ”σ‘œ‘έS/IhV3ECS,˜ΝT$°Z°ͺŠΥŒΩl$d)‹Έ3{Yζ ήUλΣ¬ί8Ϊ%μ㇡ˆ—(ΡNΦςΆ-Ώ6K6/_‰E•₯\ηYrΤO*&] †rzSζο& σH^{‘ΊLR…ΨƒKYΎn/]I$έlΕl²Pορ›‚-7ΑCsxn5gj–π¬Ξ@@–OžΜœ™z‚ΏθN51ίJ ώ³”š CΣ΄œ‘ ϋ”γtͺ―gΜfڌ) :ΌkΧQαρΗ ^³ƒίo΄ζ)Γavπη‰I呏η‡ώαn mυ_½ϊ ?=N·ΟΠ΄Ό+Jτι*Ρ9D|{ήεΪ%.›NqjHgΎΝ>¦Y³°5ζ†JvΠ‘'0ΈlŽσftrBφ $ ;WΙ £¬V%»Ώ[G`P@³η\‰*AfφΖ$ίΤn%φΠχ,Z½““—HΛ²`1Y¨σdώί]m­έ•A-Η1%’/Ϋ[…Σε…0 qύΧSe μ0^ω•oζζ‘ϊ­φEWLgχ±mΣφŸs£rυ²ΈHiœΫρs¬L&-ςEŽ,˜Νoi*Š*εڐέ;/Ι²-θ°D–νJ:\+εŽ„δτ΄§Gsζ’™Š-:2ph(UτW9qh9³#γ0!Z.FQkζζl@Μ ΩΰtάΪf[ ’’(7Ω%εκ'e.ιλG°dY;Χ,gΒ°9iC‡φO€’-C½²žIΔ«ϋpƎ¬†Ώs2?~2Š“ŽukΆ@CΓ–c’Η&k2ηόΒΦwrF{˜vέ§±ͺEκ ¬b‹@ ψΟR*‚ϋ’««KžΧ7O§r<_ΨΛBΚΑ­y’ vμK€©λ/iCί`nt ϋΣ"b Β²υϋ₯|5t GMαMoM,Νrg4 ŒMxuJ “τnψθ@F§»Ι “οΌκšη3‘’ίGDύg γΗoΐ£λPή\ηdΆίhώώ_mΕŸζƒ§QΏΣA~Z³Œ)Γ7`δWΌυ˜ίΏ < cΟ -#–Σϋ6sϊ€εjΥ§Νk螲ΥN˜–HœΙ€‡9’?6ζΠΉŒx’.Η7Ε’Ν‘Ά쐇`›Ϊh?―ΩNI’νœMth¦4LVzI‡S₯N|τFŒΧNrψ·•μΊžn{Kq¨£ νΤμf­fΙ€jβe‰η’ꃫl%3SΕΩΛσ–6 Ž:9TࠟΎ˜t)πίFs*)r‘/‘M―dNl_Νͺ£Xμυ,oΏ†ί…³όγߞ׻4"D±’Z£IOΣrl+Π4 YMQrŽ+η~ΰΓ―Άa­ΥŽ.Cg0Ί¦;ΦΜ L)ι·Ai§Tφ%sϋχ}I’rΎ §SišFΏW’i’$έu#ΑΐcOTcρŽΝlr>AΥ'†β/AʝoΒ5δQ^وfεF2hσ~ΌQŽ@ΛO\Έͺ’²˜‘œΊ ςiG‰Λτ% €°ήG+Χ._C₯²m΄#3Šsל ςBrx3"OrΡ―-»?F `MŜnwwl½Νššλώά›­ε₯σπF4-χ&C·ώNRΛgπωŽd‘.ͺ¦}j/N L7Š$£z˜ΖΚ%ώ<}‰«j‘ν|±ZUϋ¨†δΠΣ.KΆ`CΚΝI°Χ°½’μ΅bΝ¨ψH%L{~Ημ_ž k4{V.$:Υjo\‘ΞΥW5»Ψ’ΥLJΏΘ™K-hΧ½9ηζmγBVͺֈSΦ­mtΚGGΘ‘$©˜t)”Υ«T ™)dJz*=Ρ—;τ%ώτ92d §²eρH<ΖoG[π„_*gΆ­`W‚Fμ#ΩVHξψωι‰:τ;Q šQΖΰ†·o3"¦χ‘Ά·JFF7’SJr+C@ #₯"θ0›Νψψψδq"μS«ςCQRSS Ω Ώm¨=o ‹uM5κΞϋ4(v±ρ²ukVΐGΗρΘœ}}q ¨N‡FK™;{ο@§\ΌIΕ&α-F@|#μΡ₯L›9—*―u₯ž?€\:ΙεΪΦχWρΡψη§E¬―;ˆΗƒ29Ύ|1ϋcl]§ηγη*Q^K%1E„@π QβA‡^―'##ƒ+W`΅ZΡ4 UUs¦Pεχ\§ΣXθ£’wsΪ4˜Ε_ϊ'iκ)qΗoo-‘#Kg2Ÿ$Μzo*6μΘ;ƒšα"Ι<5κcǹ̜‘‹‰·Έj(Ÿ5y¨Pm½―‘Όi5βS2Μcρϋ}‰N· Z<Ω―NΚτ€e§ϊœ›;’o/¦γZ©ύήHC²§kΩΠΧνΑ°φ˜σqVH4μΑΠρlΐ•&έϋRRFυύ–ͺ}¦2ρ…ŠwΆUKδȊ―Yp9 ‹ή‹ :2j`S\΄SX²LdYξΝΉ*Ίέ΅³I8ΖΖ₯Ηn­—Xφ-™•Χν[fΛη<Δμω–9ΙjβqΆ.˝‡˜“^ΔΉfζhŽώ΄‚£ŽΗ$ nn3άͺ#@~ϊ1E³#Ή†ΥœΤX\¨σΚ$–1 k ζŒdΘ xԚHR¦}nF—Gr– eΫ2zήs8ι$,i $f˜1u@ (ύHΝNΤ~ι6 ύ=,οYΨό΄m+!Αε Ξ9f2s7jšFτυkΔΕΗξιΕnσƒΞΞ_w²e«<ΗφμΩ}Λ±bC9ΛΒ!οΫwο„ξ~})γΛΙ_βμμtχ ˜LYB³›0™²hά°υΦ+iSJŒ?£uλΗKΪ @ Χ7|rՌ’ιhΩ’{φξfΗΟ±Z­χt^―§Fš΄lQBN Tr?OΨ(ͺ)7e„fωS4#@ Œ:άάάhχt1b!x τΏGh–?šͺεl¨ϊ !‚-@ (έ”xΠ!„ύΏ 4ΛEUΠιΌ}‚UΉϋE@ (1DΠ!ΈΡΥ οά΅%mEx{¦ ŠΠ,TU} 2U;}AiFA γιι‰ͺiθΐήι‹Υͺΰιι 4sΐK\\<‰Ix–ρ,i“Š””βββKΪ @ άt%LΗφνΩΌu+IIΙ%mJ©ΗΓΓƒŽ:€¦ Ν°λΗή=ϋ0™L%mR±γββBƒ KΪ @ άt%L… >μ΅bΫΗα~FU5, €ΠΜ».~Ύώ„„„ (^~ƒN§ΛAιCA sΰΐ¦Ξ˜F|Ό˜r7όύύ>μ5Πš9`Χ₯b…Jœ;w³9«€M*vŒF'jΤ¨““ΨΏE J#"θJ˜YsfΣ"4”σΞ—΄)₯žͺUͺ2{Ξ4Mš9`Χ₯ί+ύhΡ"ggη’6©Ψ1™Lμέ»ŸΠΠΠ’6E ω ‚ „Ι4eu1κ\qθίu1ŠŒΜŒœηB3v]Μζ,$I"--­€M*v Γ9Β#χ "θJ¬ΛΏώ t²mΕ*‘Y^μΊ¨ͺϊ@n”'–Μ‚:‚Ζ`0ˆϋΑ`Δζ€7cΧEQ4Ό γALž‚ϋ t%ŒΡhτΏΐh4"θΈ».jΏͺ=˜ν‚ϋt%L‰Žth™\?ssPm*”ΙgΊ’–ILδ%,5ρ”AΝ$ώςebR²Π ή”―B™bޟοΎιΈ›Ύ…ˆ]—qj•@ J?χΑ·Ά@πίΖh4"IrΙ’ZςVή﷍Ζ_Eη@ -σ?ΝΙςί"I1Σ lΓ{4ΒG”³,6—ˆ—±¬œΞΊν?›ΗΐšX8δbϊβέPÝΛΠR8Ύjs6βbŠ‚[@-eCšΖ0ΨxN?=‰/T,’$(½Α€¦pΉΟμ^ϊλ 6ΗyL‡zΈ];ΚήΝ{Έ¨ΚθΚ·c@{ϋWΜε’IG™ΐ x€™@ςΙ…&aΝΩ½u9³ΦCΩΖxώΥ0NίCbφτ I2΅{%ίgφ’›λvζώΕbFΥ/ηGΟT?>—ηM¨3ŠΊ“MΊΖ46πΔƒl\Ήš]QϊBs²υ›«ZԚIV•Κ/½ΛKAΗΩΈx ±ͺ'ξ&.Ε\DσΘΫf$/yjPwώ9°Ή?&c2εξ%"I2jd1ιRXΣ«”dΞμ\ΛΚυΙ|¨#=ίιD}†U·2!4μφ.―>‚sτF>{λΞΰ•κφ vž„OŸkj3Ÿρ|A1c‘3FΏŽ%³ίbOK^θNΛ*"ΉP DΠ!(2΄Τ?9ψ·‘/6Ξ 8μ8UoΓcλψγP]ŸΉ[A)μŸω!+Ν/2zζψ§dώηŸσ₯οL>m`sΦΤ«lžφΊfցΈ{θUΚί+˜²ΑL§±syάΟBΜΉ$x#Iρ]œq6[€“eΤφNkY«‡1rT#\―ώΙ+Ώα +`›Ϊ#»{`”­\?~ˆ?-^Δ'PΖY‡,ΛHHΔώC—“Ρ€‹Ω€1εΌt$gdχΤKšΥŒEΡΠ f³ ¬¬ͺ†b5c6[ YΚ"ξΜ^֟9ˆwΥϊ4λ7Žv ϋψaνβ%Oœ θ]Ϋ§U΅f’λ#<Ρ8ύ‹φ•¨ι\H$Χ[Ϋ,ΛHΈ žέΕφ“Χ±•"g$ΉΨt)pΠ‘$svΧzVm:υ:ΡkβPκϋhdfš0+Ά²υUZΡAV±X¨ό8-«,ηΰυ ΤjφB4UE’%d¬d™MHhhšLΩ¦=yΏu±–οΎΗ:·G οφ,-+‹ΰC ώˈ CPdh‰±Δi4Μg….€r°ύz,wλ―Φ’φ°ιχ žŸυ ΅ό%hKΟφ‰Ψω νžΕ@Λ@ίΈ?CΫΦΔhΏQΉχ2ΌEγζεƒ·ŸoΏμ;ζε)‹ *Ε±9‹Ϋc@ύ<]j“Έk σΏίO΄Ξ›²ώ~”±χ GζΧΘΞτωr OάΖΪΥΫ8—U‘J>’d%.>IΆε`5cΦττΆδrIΒζ<Κ KδM:—²snNDΧ,d$ΕpμΗ?ω/μΙΰΧόYΎhΡάN!7—£h5“|P’9œ¬εm[~m–l:^Ύ‹*KΉΞ³δ¨ŸTLΊ ετ:¦ΜίM@η‘ΌφB#t™€€92 ±—²|έ^ώΊ’HΊΩŠΩd‘ήγ7;Zn‚‡ζπάjΞ Υ,αY7œώ,Ÿ<™93υѝjbΎ•@ όgA‡ HΉkι=τξ*Χ.qΩtŠSC:σ­ύVkΦ ΖάP±¨ϊPυά€γί–Q»+ƒZŽcJD_Ά· §Λ a<βZl ―v―όΚ7σNσPύΦ ϋ’+¦³ϋΨΆi ϋΟΉQΉzY\€4ΞνψŽΉV¦N“ ω’ GΜζ·4 E•rmΘdΩtΨ"ΛvΗΡαZ)w$$§§==š3—ΜTlΡ‘CC©’ΏΚ‰CΛ™‡ ΉΠr1ŠZ37g’¦`ΆHΘΗ γΦ6ΫEΉΙ.)W?)³xt)θH‡\?‚%ΛΒΨΉf9†ΝΑψH:΄’&•l9κ•υLšψ#^έ‡3vd5ό“ωρ“Qœt¬[³ΩKψ:ΪdMζό_ΨϊγNΞhΣϋ4V΅B½‘U¬z+YDΠ!(2$ίόελ\½@ΐM5%š«1PΆ~Yt\ΊυfΕ’=E[©± ―N‰ ±Α‘|½>:²G4dτwšu·2π§ωΰiΤοtŸΦ,cΚπ4ωo=ζW,‡$άγΤ2b9½o3§xPV}ΪΌ6ξ)ϋX½α‰i‰Δ™ x˜#ωcΣiλΑˆ'κr|S Ωi{Cςl9 φσšν”$ΩΞHzth¦4LVzI‡S₯N|τFŒΧNrψ·•μΊžž=θδPGAΪ©ΩΝ,ZΝ’32H1ΤΔΛΟEΥWΩJf¦Š³—η-m6ur¨ΐA?}1ιRΰιUζTRδB_C›^ɜؾšU3F±ΨλYή~7 Ώ gωΗΏ=―wiDˆbE΅F“ž¦εΩV i²š’δWΞύΐ‡_mΓZ«]†Ξ`tMw¬™˜R 8n%‚Ž:E†δ^Ζ5ΣYΉγ0―Τmš'―#+r'ΏEW¦m#$bΠ[ΘΚΚ=o½ςΧ²§Gι‚Κ€%.Σ—€ν#{oeHΈ–{”ΞΓΡ΄ά› έϊ;I-ŸΑ§’ŽB]ώUM'ϊΤ^6œ:@™ oIFτ0•KόyϊWΥBΫωb΅ͺ(φQ Ι‘§]–lΑ†”›“`;―a{%;ΨkŚ₯Qρ‘J˜φόŽΩΏŽ”qόsβWΆwΟΛέΚP’v³aχq’'‘wγ‘ 8ϋψ⒜bρλ}xoΓε"퉕eΉ ©1ρdH2:Χr4ι:‚q“g3{ς;<γ}–mϋ/‘θ\ρtΦαα‘Λ½O灻쌧‹9Οyeœ0xΈ£Λ©ΓΚ?Gφs5ψyΖΝψŠ7Ϊ£K‹#&]-’6ΙΕ¦™,₯sϊηM‘š3τσ™ΜžϊΪTΑ=Ÿ6λσΣQ–σθ'“.9ža OΏά—6ΧΆΫ ‘Όi5βS2Μcρϋ}‰N· Z<Ω―Ξ½r·2΄Dެψš—“°θ½¨Π #£6ΕE;…%ΛD–₯h=š’Ϋ];›„cl\zμΦz‰eί’YymΠΞ±eΦΉ|ΞC̞o™ΰ,­&gλ²γ9eζ$€1E€9š£?­ΰ¨γ1I‚›Ϋ ·κŸΎELΡμHa5g‡έκΌ2‰εC Ț‚9γς΅&’”ιEί…›Ρ₯Ε‘œ₯BΩΆŒžχN: KZ‰fΜE`@ J?R³…΅_Ί Έσœx ›Ώξ€eΛVyŽνΩ³ϋ–cωa½Ί±o,Fλ1‰qΟUΊmβχƒΔ—“ΏΔΩΩ©€ΝΈo0™lσπ„fy1™²hά°υΦ+iSJŒ?Ώ½ϋŽ’Ξ?ώš[r“@ ‘&EDA€Jo"*¨ΨEΐ‚βξΪΕ^VΧ՟}εϋ]+l(,**’μκREPŠς΅Ρ#©—΄[¦όώΈΙ%@(™ά‹<ηάCrgξάΟΜ;sψΌf>3³b΅’θf΄kίπΔιOq¦uΛΧ|€nΎκ+M˜xŸž9ό Mθέ°Ξξ•Μjυϊ„CΫ¬fξœιΰ·!t Žj<ψݝ₯UΫ7(Οκ‘&ά›ŸτmV3ΗvβOB?”Ά Ή:PχŒϊ:ζ€Ρ:&ΡνH"t =ΆYΝ,Ϋ’Χ{θ%yΛήίcF‰Dθ’ΐ‘xdϊ·b›ΥΜΆνC2Ω6Oϊ€dFθ,33SΆγΘwώ΅LΣRff¦$±Νͺ©Ϊ.yyωjZX€Μ¬ΜD7©ΞƒAεεε'Ί€½ t vκπαšύα‡***NtS’^FF†N1BrΆY5UΫeϋ/yZΌh‰B‘P’›TηΤ­[χD7°„ ΑZ΅:BΧ_{]=Ηα`fێ’Ρ¨$±Νͺ©Ϊ.³sΤ’E YΦ‘w}ƒΧ덟$B`–eΛ²Β‰nΖA‡mΆ§@  œœœD7€=zW¨S„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘ayόθSIDAT€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BW:ΈŠΠΐU„"tp‘€«\Eθΰ*BWωέό~,Z΄ ΡM@"t V 0(ΡM@’bxWνr¦ΓŒΪ‰j"œΥχδηηkνΪ΅ŠDΒ‰nΚ!-%% £Ž:JΩΩΩ»ΌO}’υIn5Υ‡αU$‘΅kΧͺΎJMMMtSi‘PH‹¦Ύ}ϋξς>υIΤ'ΉΥTBI$ Λ0 •––&Ί)‡4Ώί_γΡrꓨOr«©>„’ŒmΫr'‘mψφη₯šψΙxΥ4Π؞χ¨gλα mO]³ν½9O†ϊμΟ;σΏΥsο})ΣΆ%Η‘γHŽbmΦ³ώ2n`‚[ψΫμυω½«©>„’ŒeYρb"D̐ώώΙe:οΔρς^½΅όA½ΆμnέrλjΩπθ„΅«.Y–΅Οi‰¬Οώ˜–­§f,Χύ:QυR²C¦-َ΄£άΤC“?Τέγ$Ί™ΏΙΑ\ŸCAMυ!tdφu·.Ό½β1ujΫM-©Me_θ#ξΦΗk¦hζWOκšAO'΄muΕvφ}$=Ω¬ίV€6MΘγ1δΨ±wV½TΝ_΅YΫPΨ”Β–‘»Ά”γH{ŸŸzL}CύϋυΧ¬93uΪ©#ŽΰQ‡ϋ‘€$“¨£ΠŸ­_c‡Ί1Tˊ¦(κDΤ&­ž˜u“ξ=γ}EΒ‘½|ΦΦwnΣυο7Σ-Οέ€Ύι΅Ψ(ǐΟcΘηu’ζθ|2΄£"lκΎW*bΊρ’uΛΔwγνr*»έΆ K*) )ňͺSλΦ±yvYG%k?ΦΤ©s΄τΫ-*Šψ”Ω¬ƒϊŒ«±#ŽV–!IeϊδΛτώ‘κ‰Ρ­ε•$k›>~θ.MŒΣƒ7 Qon‚½ͺνϊhΜYκί―Ώκ­]――t…ϊΆh‘ϊ>Ÿ’Ρ¨ΜhTΑŠ ­ΎtΌŽ{ιEυοΫ_³η| SGœ^cπˆδ.Χ{ΣfθΣλ•[j)uΈΪυ:_Χ^1X‡Χυc»λp"tlΠ§­ˆ–κ₯ΟnΣ•gί­+>W^d½ϊ6ΊTσΧΌ£^mNΥaινφ~ρ΅I ͺ»|Q’>3dΤVÜj&Ύ―“ΰvlΛ/Ρν“>Υ1GΆΤ°^πΗzϋC'LΩeΎ'Ξ”$y½†N:Ύ½ξΈx¨ςƒ•·’­Ά‘οίΤ½χ}¬΄Σ―Φ½7τT«ϊaε~=O―<}―ώ’{—Ύ΄³ C>Ÿ!ΧSY‹­~ωa½QqŽΉηd5΅"²§υ™5{¦φ¨ϊ6κ«?όQ]³²Tίη‹ί%Λq₯{½joϊκς?θΈžWΎύυΑ¬™wρe»,ΛΪς‘Ίϋmοv©}ό―κ˜γSpγ—ZΊ­‰΅ίφύͺΓύ‹Π@’IΔΠ—©_< γ€Œz υmα,5 )O4 %_’.^#³ΪP’έ™λhAπx]rΞΟz~ώR ¦†U©ΓZ§ΧozNή±#Uςή}Ί~‡R[φyW^₯ΣΪ§ΛΨίtUφ…œŸ4ύζ;΄jθSzജΚPΦ—O^‘8ΧhυΗ«—Θ‘I+~ΘΥύ―.ΦπέtLΫ¦Zϋs©Ί΄ΞΣwŒ’Ο#ωΌ†RΌRΐοUΐηQZΐ―ϊι†T,—eΩ±‹Ν«ΦΑΙΣ'oΞTpπ=ϊϋψςFMَOΝ{\ »ο©ΠΥ7½¦OzXη΄ΨΉΞŽ"Ϊ<ηοϊŸ•tλΔσΤάiοu―Άλ …Τ¦M[ΝνέOέ5RΊΧ«h4*ΗΆeWΎΫVšΗ£6α°V\2NΓ·ηjήΏηνΪ§Xσ_Ÿ’΅G_―ξͺŒHD–-5j?@gv°ŽDU΄ϊm½0ν?ϊvΣv•xstμπ?κϊ±έΤΠΪONSιΣτŸ e4ξ¨SΖOΠΕ=Εφ“ςυϊψΥΙzoΙZε[ιjΪγbέuγ‰:,ΌAσ&Ώ ·–¬ΧS7ό2]=ͺ›zͺΆWΥVsχοΊOβ€ύ¨:zZ›―Β²Ÿυη™Γ4ξ•#4{Νs²Gi,ψ?}Ύi¦Nξ:FλΛj‡΅]έ³Ξ׌…/κͺ!ε˜ή},;¬o,Rθψκί§ŸΪ|;_ŸεΩΥ¦{δΣfΝzc…Ϊ]υM}s’nςšώΙ·zhΚR:u€šΦXλΆ•ΚΆ}³9¨ο·υΓ– Φn-ΦΊmAύ°₯H?όT o~ΜUnA‰ςŠJυύ¦_δ8’Qy!Ήγ8²KΦhεχκ?΄“œŠ°’¦%Λ²”+Ϊ|7Q_Ξ“ί–Š–?―‡gψtΡύΧͺkJ…’vbΆG]Υ§ŠmšJ5 ™Ρ¨ΜH$φo4*Λ4eY–lΛR rΎΫRφ•–}νΧΐ3ϊ)­ΌBΣ’e[2£aU„£²©^V uu‡&Ύ2]S.{ξ$½χίOήωs΅Έτq½ρΟWuί QΝ}fšV†9v‘?ϋ7½ωKέπΤ›šϊόƒΊϊμ.j’ >Ÿτ f„OΦ½/M׏ŽQΖ‚'τm—]mύ·[BI¦Άσ/μΠύsΟ֐#tΧ%Οjeή,έ?χ,•εΚvlMZt½Ξ2N…ζFm }­NΓυέΆε2¬υj5r—a${Ό*ΎΦ‚₯–ϊ ‘oψ₯Φ(¬°UχΫ’λS]UΰˆF£±λ9L3:ͺ‚ΗήΪbε’νvs΅lbWΫ?v}ωΪˆγ[«AŠ‘Τ6C4 mP?η–W]sΤrΔε:³C¦ £žŽ:λ4W±I›σ-ΩŸιγε uφΥ¨SŸ|-ΤΉ}Žœ’₯ϊhysΊςd΅L•|Mκ’Ӛλ›Ε_¨ΐήΉJξΧ‡αUόΞ=Ήΰ uοΨ[ZwUnψ[?ω.}ΆvΆnoˆzΆ:MιυκΤΌ>/ž"Ÿ' VγυΨ‚λυπΉσ‡χ±dGe+ηk™·ΏώάΑ#Ηn ή;hςœEΪη]9&[½v\­Ώ=ύ:ίwZ'ǝŒγάͺΗηSI8¬4―7~­‘γ8±k;*Οt„*η«±-ΩM”£mΪΌ-*'{ύfoy_?6W .Έ^ΉρHε€kξύ·hM|9y »Ϊ~Rυ>GŽ!Ιpdَœjγ˜Ð}tν€λΥ+ώ•† G^#ΗͺΆΉόwΝπ*’Lms˜pβ$­Zύ…>Zρ¦Ϊ§ UΊ§‘Φ‡©Μ³Ξ4N%Ζ6ύX±LΝR;+TΥΚο>ΣΉ]o“išϋ\]ΈT V7χNΦΛ“_޽^zRθ\¨Ε‹ΎU$ή‘1΅υ§jC*6jύΦ€?,«2”μoΊώa©AΟAjσΓ—Z΅~΅VuSίNξ ­ͺΛα;ς*λΒaυΧρCτξG‹”›W £[dΘλ1tb—¦άω0υοx˜zέD=Ϊ7Q—vMΤ±uŽŽlΩXε!S_­ΟΥ#o,TVύ4ή·έΞu «žΗ”ισ«UΊΫ΅αu‹΅8·­ϊtkλ”ʐaW¨€Μ£γώx‹N.}WOΟX§pΆG]Φ'55M7nPχΧ^ΥFŸO₯αplhU$ΏΆ£*plMOW©ohγΖ JKKΫ΅½cu|Ηr-·TE5\SΎαmΞKΟλ‘Vκ)R‘²RgΧ@°Λgβk,#§Ήšš›΄q«΅Λ2¦-ΥΜώI?εz•H©|ωεχ» χλΓ™’ŒSΛΗνΣ<τΤ…_θΩά §ήΏC—œr‹2S›κ»²i}Ωb…R™vX]꟩I³Ÿn8i’’k?νpτΛ…ϊε)ΊΊkCeΕgm a§χΦτgi͘Žκκ‹­ΟζyΣ4ϋθK4ఐώοiZš:Xνδ­ΌSηώ¦WmGVÞΨφŸZ:³LΉ]NΧ±ΎΪήZϋWχίSZ^ͺγΪ4Τ+wŸ«k@…ΑVκΧυHَtλoΧψв³Υ²I]tJW 8₯Š‚EΥζȐKΟΧGw<£G3ΖiμΠcuxzDy?,Ϋ―|$ί™θ”»rH*Γ‡₯°:θ²[GjΟhz—ta‡ΊΊwΨώΥv}Ζ\0VΣߞ¦~}ϊ©Λδ—΄zόεj^^ΎΛέͺG—Ι/©΄m-ωl‰F»[[²4xάωš{Ησzπω2]8’»ŽΘς¨’8W[*rΤ₯IeΦΒ•ύuBγ}ρ4Ν/pΤͺr)5έeͺjQv ορ¦žν]΅»|¨ZJ΅ySH-ΊυΥιύήΤΔη'«ωŸFͺscCΑŸΎΥ:λ σξpupχ*BΙ¦–ο·LK;‚₯ΊrΠjω¦9šψΦΥ:χ„KΥ£Εh--~EΕ‘­κ™9Z«7-Tƒ@S“3`?ΧrH²·jɍ:fΔmj1wΉeͺΏΛ)δ}D‹V]€=$)KƒΟ>^?½ϊ]»©\ι­θŠ{Ηλ―©¨yӝj/+K½΄Π‹Ο¬SοΫ:+!—s$πϊ‘p8¬Μ€OSο₯[ŸόH³>ύRg ν.IZωκu5~ΖΆmYΆ₯²²2ν6Υ’Σj΄}’‰^yρmύύφ§Tφ)³yGυΏΰ1έ9Ό…μ²έ ιHr"2[_¨ΫΟ_‘›Ÿ¦ŽS§΄Z{:ΛoSΛυρϊ|uήθxπθϊκΛϊrΜ…{<‘Όϋ‹/¨¬};-YΊD£Ξ-―Ο·Ϋ­¦-ιˆ1zτ‰½όβ;zς—T2Θ:\GŸqΊŸ=Z7œώΈžzd‚ή6š¨ΫΩ4a䳚Y΅NΥ_Ϊν_+Co|@₯Ο>©ηnKΡ45λΉξκr”z]χ°žόŒή|`‚ώ·TͺΧ΄ƒ†^rμžΛtωοΪθσςcΞΏG]λξ·€2ώΤ­{WΧ–ŸHU… υΧχΟV‹f-tfο?i[δk5ρ­‡§]£‰,–Ο¬Kς©^£lBω*,ίνΊ# Μμ,%y –¨·oΏOωγ^Χνƒ*ΥgΘ1C*-Ω‘ς¨#Y›φ=]~ed7”·4OΕαΚ^ΡΦΊωž-ϋάυπ»ΧSZΉb•²Λ{nΧη@†‘¬¬zfΖrύ{ŏڢ½H3vΦ.Σ ΓΗγ‰]ψΌΊκΧKW Ε+―!ΩfT‘Š•–G»rΐ£΄9ͺ-P~YUGڐΏ~#5 DTTX’H‡±Ί¬Οη“mYšώΦ4υλΫOmΪ΄έcž7ΔΗy£ερzχϊl?]υλ§+Υο“ΗpδΨ–’εA–Ω dd)3Ν/c)RΎCεžL₯›…*ͺπξΉ©jSOfaJMIžΥΛΘPzΐ'―™α+d~₯ed¨^ΐ/Ÿ'Vۊ JΒ–jάΏjIυϊœ8ύ)ΞtlάζPa€λ‰σiςβ;5ρ›uΦΠK4uΥγ:½σU²+R²CρNkUΗΥγΩύ2Π¨J sUZγ „ΜΕΧFrδ˜ε*.ŒΤ4σ~¦G΄£ΰ—jΏΫϊiΩ2»Žq)Άj:ξΊD ―’bg-LΣ”iš*kΤ Φjή( '¦/WAaAόU5σz½ςx<ςω|ρמ΅”¬h™‚ΕeϋψfKεΕΉ*ίε=G‘|εΦψG8nΤ'jFεσω4κόњ6ύMΝϋχΌ=ζIMMӘ ΖΚπz5£{]–-S°¨LΑ¦…J *©ώNžb{’΅Ϋ~ Ι©PΡφŠΏΫa•Γ{ξ“NDε; v«]•έχ/χ:H2ϋΊHφΏ»­gl˜mΫ*))ΡyΗώYχΣ‹³oVΫμ.κΫlŒ‚Α`ΌΓκ1<2*Χ ·u“ίvdογnq£>Β4Νψ³!LΣ”5UZZͺMύΊοβγ΅#ΈCΆmΗΓ†Χη•ίο—Ολ“ΟΏ3t€€€ΘλύύήκΦ­ϊD£Qω}~]wΝ 5ξŽγ(Ώ _ΡθήΗ‘ŒΠ@’qlηΧuμh‘;_ŽνΘ±•””¨]f/ύγμŠD"*Ηη5dHޝσΛ¨|οΧφ眽ό| Σ«XΫ4ϋ»τΞ/Τν‚;uαQ’]Σ‰‘Z²Ο»#ΉQŸΰ1bΑΟ19žΚ—νΘ2-εdz‰ψcΫΠP,txΌς•Vώμχωευxϊηš$ͺ>ΡhT?ηώμΚ²OΈ{ΛΆjύH΄α1δσϊδuΌrœΨ̀ؐŠp…ΫQύŒϊ2dΘπμΌ ϊ«ͺŽΔ―Ύβm§q/Ο–·$WE‘>·ΏιρωΪjά ΅>Kαb•†]ν7[5?-/>-g ‘”@Šό)ώx Η‘iš²-;φ»œψY)7vΖcχk;u¦¦6%c}°SMυ!tdͺ†ΘΤΆκΝͺNθώ:gUŸ© )Ώ^XΑνΫ~Γτ*νΘΫͺe+~­}­―[υ9ΥkXU;ŸΟ·Η‘ύκσΘ³-6ΙZΔΤTBI$//_M ‹”™•™θ¦‚Α ςςςχxŸϊ$κ“άjͺ‘€$];-^΄D‘Ph3Γ5iiiκΦ­ϋοSŸδ@}’[Mυ!tD:vμ¨-ZΘ²φ>fξσz½ΚΜάσh9υIΤ'ΉΥTBI$('''ΡΝΐ^PŸδF}’WΩp‘€«\ε‘€HΔΕGz8$Uε C’ϊΌόΨοηi1’ΖΛn5ώ?Θ Gώ₯IENDB`‚rocq-9.2.0/doc/sphinx/_static/rocqide-queries.png000066400000000000000000002344441516144147600220250ustar00rootroot00000000000000‰PNG  IHDRύqΌ ŽsBIT|dˆ IDATxœμέw|UΪΐρίά–^IO =”ΠAAš’‚AQ׎uΥέuw­k{-kΧ΅a]*6DšJ BH―€η&Ήefή?n’JŠϋ|?ζ#ɝ;σΜ™sζΜ3sfF‘‘³–=₯7ώ›B!„B!N[ΎG©{έ/g-{J7šΝψϋωαηΩrς£B!„B!D»8T‡¦RZ]EIi)ͺΓQ—ό+ΰJψ½½½ Δ (-ΟM!„B!„§%MΧΙ-.’’’‚-Wί£˜,f3~~84­Ε/t [Υe“°B!„B!Ϊ.ΠΟ›Ν€rΦ²§t__Ό½ΌZό’Ÿ³ŠK3wγc«DAg­G»ΊΗŒ B!„B!N+εΦ *ΚΚ1(ΥΩβF¦αc³’ΰzΞίΰ’l6z…αζοΫυΡ !„B!„’͌f3€+ιWΠ4΅Ε/XQ“§EΥš•κκ*­εB!ΔiΙQFιΑΓ”fa«r‚Ω ³_ ή1= ŒςΖΠαθTοΫHϊA+u―ΕQ<?‘ ςί~";«φΆ:Εlq-ΏG4Ρ˜κ©¦­eΐgτ"’ŒŽT!„§΅Ϊ†½€ ³―&OχŸ9+«q”•cρχΕθξΦβ|τš#Πκ½ό?z‡3Β˝ €nμ=”Ζ¦ςjŒ½ΌρΥU*4¨>Ρ5B!N6k:ωΫμL; ]3€ώh•Ε€g&²ζ·υΌŸβιΝ‰ίΐ¦cΫ!Ccν_"\-€VΐΫOέΓ“ϋUΞ›[FΊΞΐλΊ†£Ί”τŒ¬ώυ[ήZ›‹αœΎx5¬[aτμcΣγΰΫΧεΟιc ‰”Δ_!Δ™Η^ZNeF6Nk&/<ΒCpλΠξyΩ ‹©HΝΐ;&κ„ζΡQGέή¦ι‚ΖŽhφ3΅Ϊ†š”Κ…‡±f.ͺ#ƒ±ϊ`/*Α”Uΐ”Cψa_ΖΎ1­&ώP“τ·6΄@Eη #χ@¦SαhόPς7bΤQuχ ¬l0ΉΛ=ώB!NoΆŠwxςχ»Ιβ3Ί­˜€΄#¨>ατއ~p%/ζ{θ(§:ω0™Ε8ͺ5w/ά"{ΰΣ;SmŽ]UHٞd* «Π->xτ‰Ζ˜±—ςo|FD‘ξώœ7{Μ皁!˜υB6―ωŒ•Ž(LΖ΄šθT=ΜΞ|n~αΔυ9››ϊŒα=ο°θέDŠΞŽΑQ7L vΪͺšσφN’>άUlͺŽBq&©ΚΜ% ΒΖC³2ͺg_Ά¦$ρ«>£ Όξαmž—-ο(nω%Ό}ΥR4]γŽί ΜfΓ-4¨«Βo’CSIzꍧι{Οu-ζίΆβfΚƒsΰΚsΞcρλΟP^3*ί3§ˆw―Ώ‹ž!a¨ΊΞͺ£iX‚[\žBέ•ώ–‡φ8€d//vΩ5L#³Ό„] ΎQQ˜lψ‘¬“ χBqΊR±'¦1rΖ\aFΝ[Η-OΏΕN7 φjΌύzΰg”β-ΉŒŸ°ˆ[ώ4˜83Υ%όΊe%O­;HαΘޘΩ”οσαΆ…ryάΚσΥW_‘3σCώ“Κ<Α;^9<ύmfΌPΫ>ήόl+‡ΖΑ°―6ιΧΘωύ-―ΚEWlψ„ΟδΥΫ0vπbž<ϋ―Μ?\Ž[]>_;mЧ P0χˆg€ή¦~\!„8]8Κ*π+―fεχγηy,Ό`πpFχκΛτg’’΄¬MΉ₯ύh1ξyEΌsßιΐ;ΧίΙβ<ƒUKΠΙ»βοΤ[? οΤ[ι·ύΌωnΟv½BΒyοϊ»XψκΣ( Ό{γέτ γp~ίνَή/ΊΥc uWϊΫ~°`V DxZhi8”Πb4RUQ†₯Ρ=B!ΔiC-’ͺ¨—Œ Β¨ΫωyΥG¬‚wŒΠQ­V2-n¨{“™tι£ΌrV Šν(ϋŽδβΩ“i3ξbTψ‹Μ\‘F‘ΣΙ’[ΰ–ήτκ£μ-23aΑ„Φυ:ͺ»;Τ?™opG3¨4Ύ0―„υΖ£―'Ά=ίςθΊρ¬œΕΰ1cˆέτGu«zU9Ž*ΐΰ‡Α]oW.„Bœ*Σ³xbΞUψyzρΣΎ<πΕG( <2g“γβΉoζ|–~ρ>^q½Zœ³€ μ£Όγέu ?@π(ήΏώ..νi¬ ˜NΓη5 x»nςστg—αΤΤ–ϋnƒBuD7ζΎό$Λoψ3ύ#Ί³ςŽζ@bv—ηͺ#ƒ0hε8 .ι··α \ΰabΩˆ±GΘqŸ§–’Ί™Ϋ4/!„┨²‚wozz( η±'Γ α†c}—‡Tf£*γΈaT F=“WŸΎ'ς4ŒΎSω1μRϋžQ/fNO7-“<ϋ7ΟV±„ΜελΜ‘MR―jz£κ85•ΖΧt]ΕιμΕ‘΄tμzAτ°Uq¨ξV=#½.zœ”‹j~uξγώΏύ› ΐ(ηΫ…BœAͺΛ+˜Πoύτ=ŠΓ\χ¬εΏοςϋύΟ0Ύο@lεε˜[Ι-«2²yηκ;θѝΩΔEt¨ϋχ«WέΜΌeΟαα{rF£Χ>+Ο‘iψŒΰ³ςίvΥ}ΦjΞμγIixσ^}Š/–ώ•ή‘$ηη0οΥ§°FvΓδγ‰ΪΖά»ΝΓϋ—ϊΉ3Ν«αC>MLezίx |ŸU€Φ3ΊΥ·!„§Œ¦‘(JΝϊt4T]EΧκ=¦’cX4} Zι6δψ Œ EέΆ—Mω#"CeΑh §»ZΩ~6dω Œξ†}λ^Ά•]BŸΪωkθJϊgύ:š«/Φt,ƒλ;Ί†VcνT ξιWΣΙρτDE₯ ΟγB!Nκ±Ξ ‡ͺΦυŽzW­U­υΫל'Uv[βΚ7Ÿγΐ£/0ηε'xOwPi·αt:OΪmpšΥύΏρ2[ϊ¬)ͺݎ›Ι„‡εXξaΆΰf2Qj·£·yWοlΓΡΒGGΛ±TV19ΘCΝΓϊά4¨΄Ωy9!‰Ν~~uΪpƒBqJ˜Ν(εdΫu†ΉΣ/(qβτ¬’―9Αc¬ν_PΠQ5 ₯^χVΫΥΉ’sW―κ:ŠξzΈm-Ucƒ¬ί5―γ/υk85'δV2μά, ¨ωYqsCΓZ3‘λžώEίδΰτ0‚β> ;˜4€_!ΔDχtcc~¦ ΞΝ»Š»>~…'\ΐΖCϋΡ=έ[ΝS•θ0ζ/{ή5Οj[έί ΚK™φκ (˜£ΓΫ”οVmέΣβη£·:ΪcU׏[fKŸ5ζ,,!¬€š/nϋ;‘έ8˜›@Ώ°HΎΈυ>f½π(Ήš†©›«1±νWϊ³x΄AQ±•yή¬KΞδΓςJ^Ψqgh0ŠΕ,Wω…Bœή/ XXΙEΓ<9wΪ%œυΜr~ΝqՁβπ ΄§'ωΩGHTΗ3g"ήη—me˜ύ.b\ˆ΄\dΩQ΅\2uθη۟ αelΪZ‚9πb†ωΦfω:š­ κ’ΣͺΡμΗο'/ rDτ½Œ&…bΤmόΆω7Žω’–5šXGC½ ½ά‰κ/oΝBq† δ/?βμ^}Ήpπpφ ^χQIe|ΉB[ΟS½<0tέχ_½uoݟš†{Νί5hSžκΤ4J^ϊ¨ΙΟό—.lSΞ\›Μ;5­n8SΣ΄8/§Šw~ +nϋέƒ8˜›Ε¬EAaε­χΡ/,’7ήΝEΟ «'Η^)Ԝš€ΏΝΧζ…βš«ό;Λ«Θ {EŸ\ίBqϊ3‘ΖΈσυŸ2Ώο•Œν1“ž8›ΔΜ£ΨάόιDΚηw0/λ^Ϊ4•7'DrύέΟ2.­Ÿ¨^D›‘pηJ>,€ZέΜ—i³Έ7Ά;7όωYΖf”αޝp5Wή5|•aάp~<–8œ5’άmGΨYΧi}-ΔΪρθNP,8ΘΨώ6ύͺ‡Έ‘”5š6ζΨ+ϋ~ϋιUž.‰–Δ_!ΔEρχα°5ŸsžΈΗη,fRAθΊΞϊ€}άεG€›uL~ήνΛ1έ-¬9°MΣΐΓ­έωiKΣλ­|ήx͝ηέIοασY:,άΥΩƒ™4υ2Rφό™έ%΅Α(xυβμ@'֊BμωΥ›ΎgY’Β!aθJύg(xυflέ+‡”n¨ΖP‘£"IΏBˆ3‹)2„Ό2+W~ό:zU5Ї;Ζ° Lώ>힟9:’Kίώ7 ζ'“ί…'τ½Ξœ‡ΑΧ‹/vύΐW»ΆQκ‡1ΐ•τΣ_ψ3γG²rχV ±αmš§rΦ²§τΕή¦‰ϋYŒόΣΣΊΖъ*nΝ+mΣ™!„β΄SY‚)­Cq%ŠC£ έΛ5ΆͺΏt;†ŒŒΉeͺU°Έ£‡βŒ @―IW]‚))c©,n`:‹wž½…s•džxΰQ^ΤsŽέcˆbA2§ŸŽaΜ5χτ)0›Ρ½½QΓ‚Qƒ=κͺ5œΆŽmΐ`Α„BρΗ‘ΫμhΦ*w .²kU6τͺj ^(n–VηΥS·΄οJA»ΚΒ£G©}Lpν!„βŒγι3…ΰ(΄Ρh=Z˜‡»?ΞxœΞ",»~¬GΕaλΫΤUxmΐlM|rΖG·ζšΧ–£hNvƒ 'eό@K1<~Ε Œ `μw,fUηθΧχρΌρΎ(₯£aiGψπΦ;Ψ=νMž˜\o~:y+Μυ?ηΉ―¬·όŽ.°3ΈΚςιδqάχβߘp,jηΆgXτVΎt½Œ'8ϋεέ‘8›ΨV6οR“XvΣm¬Θh"%‹ώυ!·ocsλ°ΆΆΓNϋ¦Sžτο°’Mϋ3(Ά™ρ‹Œγμι‹ΉjΖ@όΊ2ΐS]Ί΄ώœΌύ²=g Ÿ}ψ ?m?DnΉŠΕ?’>g]Ξ7ŸKΔΙWV{ž²~IA1ΉαΪ‹‘γ/fαόIΔx΄΅ŸΜ˜ΫI/α‡ϋ―βΣ^OρΪ’ΎΈΊ;۞_Μύ;&πΔ[·_SU΅΄ΈυŽ\ψϊ3k_υϋοΣ^?=ΈΟϊ<ΗKWτδX·ιΰχg/ηe―yλ†Am8ψ:λ€Bˆ3N" =―x…ΖΦtb ( h8Z†x"1΅¦^Μz{vBΩIG†&NŠδΣM›9:}Α΅³ΥσΩΌιέ'έI¬αT•Ys\ei±nζυ·eΘ]γŽ%XŠ‘-eΪ’NZί&·ΥiR–ΖΎ,ymW‘ƒs?―ίp?%ϊˆ{ΟΆΈͺ₯r²ώvθμΊίAΥ‰οqίίWα>γΊmέ½νδνύ‰e/έΗ_ςαΩkγρμ²POq=:λO#Ό―yθ/o?τj–>u?qΑFJSΨ’NΠIO\N~ [ Ω‰Ώςε²ωσΞL}|1ύέΫ>―Σ£e6’ψ1dx4―lήΟQ½/‘ ΰLfηkΫSTβϋΔ}dEeH7§Γyͺ#?Ij“υ㷞ΑŠQ²x!„'_;Ž$ F3F£Ή&ΑΦ]©I,»ι/δ]ύ έπzU2ίΏώ2Λ7’ΤΑ°ι7pΫε#μ΄>―™˜­πwή{ξ5VνΞ‡Πa̜ίχΨU‚Ί˜ί`ό–»ψχ―₯Ψ6Νgκσ&ϊ]σ:ΟΝλށ$W!jά$Ί―ΨΘ–‚™Μ q-TΟ•M‡’™tGT½εΒ_Ο67]N bΩrΎς2ΟΟοŽ•€eΧqΗΧ=Έϋέ8ΧGͺ<~Υ2ByƒkϋθeψZ&FΜ™ΕΡΟ_γνρρά1Ϊ§‰Nβ„εΌςΑφ§εRf %ώ’›Ή{Q7Ύ½νφ\τOͺω^%Ώ>u―xό·oςζΓϊλ[ΌχŸ{™―wζCθPf^;£/­#ξΕG™ζOΣΛXά‡ύΟίzόΆšSΕ»υη]yˆo_…O6%Q¬ΠλμΉ\ΓΕΔy+r_ϊ"Ζ+/¦όΛχψ9±‚sΡυχpΝθn>ΐVŒF ( ›0Œ& F£ΠΡ*“ωΉΆP—αŠιφλR¬ψτ>kοš‡Η/ρΖχ»ΘS»ρά»h~ZΛ–Ύ€ρΚK(l«•β=–KocV_―FλΡΜ6k<ηuGi©έκ₯μώδώσυ6RKUΌB㘴δnn:'΄cε§η³ϊ½Ο)™x?o_77UCbΖ,δnVnΈλMVM}ŽyaΫxfΡ xώγnδΪ}ι%ίρk~dδ+ΟrI˜ς~GMbΩ—ρΈεJΏΘ—{¦>φΧυKi½Mvq΄X¬‡XΥ\½†–λ}ƒrξͺνWΜϊeΛHκwoώ}*ͺЦƒη€Ι\:PΗιΤΪΤ6;­ œ.ύ’g0±#/αξA=0έπO^ϋfΟΞuυ/­ΗaFΟω‰ηοzŸ΅‡ΛρˆΗ‚₯·ΊΦΟω{λν Εύl‡j*Αƒβ ϊh‰•³ υ-3Ά±L³„„Lκ;Iϋ’π΄€ξzΛ―έGZέ·ΨΣB}χ*ζΫ΄±ί|ψiFνzΉσΫB;΄Ή.ͺνΩη !„ΗkηaŽŽΧώΈ’λf‡ ι₯l~ω>Ί€ίϊ„ž\€χΪΗyφΗ<:χΌ&bσψξΩΗω^™ΞΏήϋ„eΝB]ύϋλ.4ΤΖμΗΨ[εͺ8w†-ύoW}ΓσJψkDŒcBχƒlό­ f]uςΆlδPΜΖE(4(³ζΚi΅ΑC’ΘJ|δBœ«^δΏ£˜81’€-[)ύZΥn6οtγœΙρX¬οQVΏπ8ίι5ΫζΑΨ?{ƒueJΝA]3ΛHτjf[՟w1_ό'οŒαžW?α“7ώΞΉUεΑg~€@wΝΫ α³76Ήδ>ψδ]šlcΥ ο±έήΔκΆΏλκ‘λךz©΅Φ\q}ρώ.άώ2+>xŠΩξλyώΟχπ©6‹Gήώ„wώ~6ş½Κ—)jΝτi|ωξοτΌι–/wΞ`ΩΏώΓ6k·YsεΩJ»u&~Μs_9™φΘ»|ΆbOή|#ΊwόΦ½|Ϋx3nΚ0,N­¦MkͺbΞebΔ~Ϋ^€Ž‚QQhpMQP¨ω[«ϋƒžΕ·/|@ρy°μγWYίD›Ϊd—Aσυ§•zέj½?¦Λb―άΙ―»ΜŒŸ= ‡U«έ~*N§ΦζΆΩymΰτι—4UΕaŒ)a€όΆ΅f›΅%Ž 6­J ο-/±bωά=,›w=Ά~-·ƒΦφ³cŒΒ σφ$;‚];Θ‹Ν%£³c‡k)μ= 1pHŸ†ϋιΦφΓ­υί-Υ%ΪάoΖ;>횢ΠVνͺ‹νΩη !„ΗkG~«’²βζ͜͝Ή³™3wOl¬jvj½x«ΆDrΩMΣινο…wτy,žΑžυΏSΨiGWΗΗτθΊ τ‚Ν¬ΫΒΕΧΟ%Ξί ŸΘ1\΅p/z(&3FCν•c'uψœ31†C›6Χΰε±yS21ΖήhΚζΛi+nγsh‡ &°£ žYηucοΞ$œhδ%ξ§΄_<};iδ―Σa ίεK™ͺ}ΟΛοο’²‰i,½ΟeΦΨώ„ωzαΧο|Ζχ,!+»šΘqˆ8π Ϋj΄dΫ»‰ν–±Œοί08½p3kv†0ϋ†ym5Ž?]9_₯΅eTA+ΫJ/ΪΔ·Ώ0ϋζ… ρΖ#p ³o]HμΞ•ό”Q;ΤW§ϋ΄kΉtPžξΑΔ_:ƒψΚ#€tέPΰΆ΅˜ ―djΟ@<|ϋ3σΒΑ¨Ϊ`ζ/K€·AΓg29:τL{έτ=.Όšι}ΊαιΙΩΧ\Γ$η&Φν±·όφ”g«±κšΑ„‡—7ή!τ5•±±ζN(£| #2D9ώ€W &" ςσςiνvΰΆ•u%¦³nδΆ)½πsχΐbhη<Ί¨ š]§VκuΫκ}νΜΊ&vνh6ΉZΡΖ&“ηΆΆΝjuqœ”~©©+GD δQ Ά=Ž˜iK˜ή§^ጾκ&«›XΏ·ωυ«[\φ³bκϐ~•μί—Ž¦—±+α}F !hΘhϊΩΖΞύθφυah·¦"lv?άZέr]‰ΤΖ~ΣΠ•νΈρ±‰λψδ‘5uν£ύu±ύυ]!„¨ΥŽtΡ@χ‹ζ‰K£λ†›=›Ώ9QΝN#£z/―];‹7jώ¦;m8#GQAPg\œn2&oΤƒ9δ™z3LGΣ]G λAΈ‘ΰψYΤλ\uNJϊΒΖM$φƒl.˜Ε,νW6%χdβέaΗMΩR9Yc㉳ΐ,'=o'΅Οxώ:‡o_K ΝKϊtb† Δ«“δt]GsΖΥ7NdΣc/ραψYΰΎR'ωΏ/ηέOΧ±7£ ›G΅ƒ!ηι9ž‰‘³i{ηOqgΟ–νXΖώ8#ΤΟΤΤάLrŒΡΔ„j5ΫFEλAΈ!·υe΄²­Τœ rŒ1\ͺ‘j:ͺw4±~Ωdd« `"2*U­ƒarΓMq’vαν¦­Ά\q……wCs ³c·pΊ‘Φ”“³TU­)αuΣƒjθAl€y%’φ•g«±ΈŒ₯ΰ©›–πύ„‹™{ιtFGyvB»qΥ3½Ιs/«ίŠϊ9ΚΆ•΅™>ύ{‚Sk2A=ueΠΜ:΅R―UοΆΤ{SnΏΊ{«N`jΫfΧ΄zqœ”~©):ͺͺΙŒ©-qΤ¬_XXΠ±υS"ˆŽ°³1·ωυ«Υϊ~Άƒo‰α…­ϋ)τ'α`#nπΗΰ7”‘έίdΫ+cΥ=€Ea ΏΗ΅λζχΓjqΛύwkuΙ0¬mύ¦οΐα]؎›8HxνFή©ω­mu a™5_ίOή- B!ΞLνΊ§ίμι‡Ώΐ±NLΧΡ[Ίτζ6†₯―έΞθΪ“η (FwΌ;νΐͺι˜ŠπT1ΠeΗsM 9‡‰=ίcΣoyŒΦ6‘άk"χ†4Σ-7WNž• ιΓ― ˆή“Hτˆ[ρολΛ ’Ω•3ˆœC ^άΉ½γuφυ\7ςO<ϋςrΞΊΪXWI΄τΟxτΡ―π[p;χίΡ‹nn%|ȟΩ@γ&DρΙ–m”`Λ63γώΧδPEi”ά)†Ίaͺ-/£ŠΊŽVήΊ((u…dΐTLlmικ#¦–Ϊ‚κŠΛX/.WΨ-=Θ«&‰¨γJŒηΕ'Tž-ΆΫ@Ζάό ΛgoeΥΗοράm_3μΞgΉg|P‡ŠP #DΙ!3G…F»%5‡¬\Œ‘΄γΏ¬:ŽhCY›ZΫœ‚2hVkυΊMυΎVn?rHΟt@ˆ₯ύλtU8N—χKMQΙLM‡°±„Υ.§Υzκ:{LMά\4j-νg;N!hPŽ>!ψκTW;Z‹;žˆ½›Ω–°…mζqLθ{ό–6†EκL'5§αΆΙΧΪΆŒ–Ά•12†ξz Ιυ^{¦&Ή4’˜¨cεt²ίτάΦΆΠΎΈœd₯g»€V•Br–αα XΫ[ž­Ηͺ£ΪƒGpɝ/πς’nόϊύ–cΟr8AŠΧF°²yνv*ΝΛvh²c9kD0 fL&;Άz#Z™id©mŸš΅hή©*ƒfγi₯^·΅ήΣ…±ΧnΏM?ljr^]Σ6ΫΦΔq²ϊ₯Fτ’|±Ά„ηŒΔ_ikN²3rŽ­Ÿ=Τl7ΒΒκ(žω IDATZo­μg;ƒ1:žΑ¦C¬ϋi†‘Γ‰V τ>χğω9ΙΑ ψήΝ–ksΫΊ΅ώ»υΊΤΦ~³‹Ϋqγc“cBr­G»λbϋλ»BQ«ΛŽs”ΐρΜ[ΞW/ύ‡υΙω””ζ“Άϋg~LΘοΔ€KG΅Wa΅VPa­ Βj₯’eς€,ΎZΆ’}ω%eleωΗšξΜ_‚ƒL€όώ ‡ ‹(,λŒ'ΊΉ=‘^I_°2©7Ξnrš–ΛΙ@ΤΰVσ›y8#"PΌ<<†δΥkΘκ;„ώ]ς&/-dK/οIvΒ.jowχ Ζ§pΏξΚ’ η λί}‡΅υo> ΟĈ=|Ήb¦qθΣDνR‚Ζ2ep6_½ύ9{σJ(ΚψΛΧr΄-Λhe[)ώ˜3©Šoήψˆm™Eημα‹ΧώKjόL΍:u—CΊ¦-θ€ύπ.+χζP\˜Βϊ·ίc“ΫD¦Δ7ΌΚΪήςl-VυΘΎΪ°›”œB ³ٚXˆG·ΰNx•^η_=ŸΐΟςπ;k9UDiIΙ›—σψ“_£ΜΌŽ »Σ;ΊŠ-ί|CbA)…ι[ψpωzŠjW©ΚϊΤ•A3ρ΄R―ΫSο»rϋMΉzΑ[_ΰŸ/~CBj%%…δΩΝ–ύyθ]6ΫΦκ;ΉύR9%ω©μYχϊΛΏΩs-·\8~x—―φεP\œΞζχίcƒy<ηΖ[Zo­μg;…©?ρύ ΨΆ½„ψαύκhzŽbhΕolΞκΓΠΈζ·EsZλΏ[―οmλ7Ov;>n=Ϋ]Ϋ_ί…BˆZ]ψςg?ΞΉλIͺήx…χώq59εΰΗωŠοΔehYq;σVΤώΰ7υ1>Ί}Σού'OΏΔύΧ½ !C˜}ύ΅œ›ΆΎ‰yx0zαŸώψ{ά}υ2z]υ9Ί’-ψ1ι’€Όq'ο±β;žΎ‘n Υ{>A»Λσ˜Vb-aηΗ―°,½»)€θ3ωۍchσ«Η›₯cκs%O=Μ²·?ζ_·ύ…UN°tgΒ΅OςοΩpW5t%ˆσoΊ•O½Ν_―ySθ`¦]{dPW./λΦζΡUeМΦκu{κ}Χm?sί%<σl0o½ύwΧΛWƒ»ζάΛΘa]Π6ΫΦη€υK+˜,ήt‹ŠcΤτGx}Ξ4gΝ•Ϊ6ΔaŸnΙ‘άΙ²Τ ή“AAΧTvN­ρzΆ²Νšͺϋ-ΕZ3½Α ΈΚWUq؝tJ“ƒ³Ωšω9χήΌ mΡΣ<43šΊ΄Β`Δbq½Λ^?mŸ@YΣΈΜZ™G—A“υ§ΕzέΪηυΦM?yΫOQέUηl­ν1vz8•ύ’Žι¨ͺ‡£ΡɍVλ© *ŠΩΤΔϊΡ¦vΠό~Ά“YkΆΰa{UΝ2kέάpSԚ~Zάo4ά·ΨΧ”sKν‘-ύf—΅γ揗Œ–šγΪ˜ΪΊ―²j₯Ύ !„Ν;ο“—Ϊz₯_Ηi«¦ι‹'Žj[¦¦³Ά7σ½Žj)&Χ²6›λ‘~΅ͺj0Ε©©Ψͺ[{Ψ ΖXέTŒν(']ΕVΥ(6ΝIueg–jse©α¨W†:ͺΓNUƒB΅5xސξ°SΩΰσΪω4\ίϊΫΖ–z„K ξJλΛ8n[ι ηήBkM”o‡iΨ«-§ΕΆΠD\ͺƒ†a5K:Ί¦b―Άqό )υηΧήςl%Φ.k+΅‹V±Ϋjζ4ƒ{oίΙMO>ΘΛ!Οrϋ˜š{W5{΅Ϊp½λV{ΛΊ©ΏŸΒ2h²ώ΄X―[ϋΌώΊΔνwό§§¨ œFύRƒI[«§5k₯ͺM¬mjΝοg;GΣϋ{PmΆF―|ma{ΈΎΡp?άb ­Ά‡Άτ›]Ωο7ST»/:nΧΎͺ₯ϊ.„B΄¬ ‡χ Ρ”*vύ)ΉQγΣ SΙN–/[‹>ϊ Ϊ(κΣ5όΞΉ‹Gί°ύh κBNκ+8„8SΙ~V!„ΗHχ/N2#ξŽdV>/΅’ΊΡϋ¬kxθ¦1x)-ΏBόοΡ5zŸ·€~h8§ςΉ BœId?+„BˆcΪxOΏΗ`Ά`1)jί·¬ͺΨNyQ›5w_Ί+€ ΄Fφ³$Rί…BœΈvάΣ/DηΡvͺ›ΈT΄Usχ₯ ρΏBΪ@kd?ϋG"υ]!DǜΊ—— !„B!„’KI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόA™Nu])­xοl»w“sγJ―n#NuHg€κκ*Ž€%“_K·ΐ`zΕφΕΓΓσ”Εc΅V°sΧV† …·—χ)‹γd++/%-ύ0₯e%hš†ͺjhš†Ήώ―ij£ίx{ω0φμ vλ²8«mΥ€₯¦ΰh>έ»έw.[^}W_»]Χ>|$KΊ†wή}›;Ά‘( Λήz€Δ „B!Διδ‘τλΊΞΑCϋ(,*hπχofζψΕlΜzΧάΜ¬Π‡0™L躎λ„…Χ0Š’œ’ΘΟ )©Ι„‡†1lΘ²²3I:”Ȑψα§$«΅œ_·l ~πP6nϊ™sΖNΒΗΫχ”ΔR]]MZF2ωݏKnΣ3RθΧ7oŸžGfV&Ώnω…]ά‰‘5”šv˜ΠP† FvNΙ‡2xΰΠ.[^­%Χ,βΎΏώnέΩ‘°ƒ΄΄βϊχγŠΛ/§°°ˆ%Χ,❷?θς8κΣu€δύ-ΜoqΊΰPzχŒ;­χEΦJ+“\λFΏ~qws?eρΨl6% +;ƒ°ΠHzυκϋ?uP!„’­N(ιί±ξc6}σͺΣq쏺€ΕΓ‡) ώBί‘“;%ΐΦθΊNb^Ό}Ό7£Α€’((ŠΒKogΣ;d()–οΨtp7#†!00]ΧQUΜμ4φμΫΙΰCOλƒνS-7/‹αCGPUU‰Ÿ―Ώεl>%I…΅œMΏgΚΉΰγγKP·`V}χ5“&NΑΧΗο€Η“š~˜Π0† NvN‡'?hX—-Οαtb΅ZΡ5ν„ηQZRŒΙdμp,v»#©ΙδζeFLžxzzŸŸΓΠψaX­εX,frr2λ’ώςς2vμάFNNQQ=>lž4jDQ cΖτ™8NFŽ‰Σ©’λœτ6λ:‡οΗΝ͍)“§άβu]gβ>ήOŸ^NΛ}‘λdΫF&M8³ΩΒΑ€ύ$&ξe萑§,¦ΔƒϋˆŒˆ`ΤΘ1””σΓκοNΩΎ@!„βtvBI–οή$nμtň¦©UCΣTœΆ ~Zώ8!QEτιμxsπΠ>ΊŽΣα@5(  †c+¨=„ΆZ+πςςp Φu"Γ»c2˜Ψ½7!ƒ;'‰-++ευ7^γHj*gŸu6³/žƒ·wΣWŸ*++ωό‹OΩ²e3=’{pέ΅7Π)qt¦Π0’’ πδ`R"αa'=† k9ΏlZΗωη]ˆ§§₯₯Εx{ϋrΡΤ¬όϊ Ξ?o*ΎΎώ]²μj[5™G(,* ΐΏΡέ{βξξA^~6Cγ‡QUU‰――9ΫΆti? ί@vμΪFYYi£aϋz³Γω„††1φ¬s:Λα”$ΒBÈ<”ςς2Φo\ΛΩcΞΑΫΫ—ΰΰvοέIP· S  ΄¬„οψ†‹g^B@@ ιμΨ±•sΖMμp<Γ† '!a;Σ§Οβ£ε²vέZ&OšΜε !a;Γ†ΌU„‹qύ`΅Vΰ¬’΄“ΙD\ΏHΪΗ‘ΓθΣλτΊβ_a-gΣζ œξxxxRYYAΟΨ^|ϋΓ·§4ιΟΞΝdτ¨1TWWαλλΗτi3ως«Ο»t_ „Bq&:‘€ίa·αΤt’l=ξ3_nψuηΓ§―­»ϊ ώ‰ΙβΞΈιΧ3lβΌY|Gσ ₯¬Ό£Ρ„ΙhΒh2ajbՌF#ŠΑ€’i¨šŠ΅²OOrr³:-ινυW0›Œ\xαω€€€π―Ηδχ=x\βo΅Zyμρ‡ιԍ /Ό€Γ‡“ωΟ―πΧ{ή)qt¦~}βΨw`/»wο$2"ŠAŸΤεWT”±ρ—΅\pώ4<=½¨¨(Γ`0RQQ†··/ΟΌ„O?„iΞΐΟ―σOšdd¦ΚΰCΘΝΛ&%5™ύJrrώώώ$%$¬‹O†xxx3yΒω 'žjš†έξDλΐh€άόl†Iuu>>Ύœ7ω|ΎϋqΖM¦Oοώ$&ξcΛο[ˆ$ JΛJψφϋ―™7g>^^mΐ‘䃝–τ_wν ύόγ.Ϋ!„Bœ‰Nθιύš•Φ²&?++)Δ©™ ξ;™n½'Ψsώ1γπ‹>ίξ£ρމΙ?– _½‘ΐλbΡ4ά,ξ€g€“–v„”#Ι$''qπЁγ¦=’šBJJ2)G“šz„΄΄TLFS‡ ϊ²³²ˆνKQa!½{χ&ΊG{β***ꦱZ­<φΔΓ„‡‡Χ?Žβ’"bc{’Υiqt&³ΩΡ#Οbώά…œ5fΛΙy(ΈώυΏόά α7™Μ¨ͺ“ΙLEE^^ή\:g>_}³’’’’N!Ώ —А0ͺͺ*ρρφ%7Ο΅ϊφιOqI~YΑ`d@ά N_v}š¦Q]m£²²ΊΙŸάΌ|>ςSrs󚝦ΊΪή)υ½[`EE…θΊkyxx2υ‚ιόΌn5•ΦjF ΝάKζ3fΤYTZ«XυνWu YYŠbΰpJ2½{uήh Χ^•‚‚ΎTVVαtͺšτ1‚#GR  !''›˜ΨXztοΞγO>‚ΥjΕj΅ςψAŸΎ}ΘΞΙ&8(„#©GNκπγφ¨¨¨`γ/λxΓe¬[3εεε'eΉεe¬ΫψSΟΏ¨AŸ››ΓŠO–““sμ`ίΫΛ›σπεWŸQ\άΉϋΑAΑ€€$SYieοώ=„‡`6Ή1rΔζΞΉŒqƒIHΨΞg_,gσ– Nςœ ee₯¬Yϋ=Γ‡η‡ΥίRZZά₯Λ‹λ7u~&??·nxzx2γ’YόΈfωTVV“ŸŸΟ7ίdώάΛπττ’€ζ™ιι¬ί°žΓGuZL»wοdΨ°¨ͺΚΒΛ―ΰ•—^cαεW ͺ*SΞ›‚›ΕBTT=ccπττδ’Ω³ΉόΚ+ΩΏ?7όi Χέ|3ΉΉyŠαpJ"f³kΈΎΥZΑ‘7ί"ωˆEQΠT½ζφ"]Χq3ιo4Φ$ώ―PQQΖ€ώ1ŒμΩ·£s ζTT”±α—ŸΉ`ΚT<=&ό›6odϊ΄YΈ»{²ψάέ<Ήhκ 6ώ²α€ν „B!ΞD'4Ό_Υ4JK‹pͺNrŠ|τΑrŒΖ–g§ͺN.Ίœ O3Z']Ε4 Ε`ΐιtb4šPP@§ΙDΎ¬Ό £Ι€ΓιΐαpPYU‰ͺv|¨s} .»‚‡ΎŸ4·4bcbΙΝΝ‘g―ž(ŠΒc?Œ’(DFEΡ§Oo²²2‰ŠŠ"%%…£GΉε¦Ϋ:-ŽΞ΄gί.b’£™0~2)©‡IΨ΅ρ4$»9εe¬]ΏšιSg6HψsrsΨπΛzΟr!?―]ΓΔ “ˆ ΄΄__.XΔ»οΏΓ₯sζΠ9―₯λΫ‡ƒ‡Ω—Έ‡πΠϊχ\Wum6ΰ`{Βvb’{0aό€“VF΅ΚΚJXύσχ\2kλJgP0+>YΞESgΰοΨ%Λ΄X<8oςω|Ώϊ[F<‹ΠΠΊ!Φ³g]Κ?ϋ˜³ΗœΓ/›ΦsΩόxzzQ\\ˆΕb!=#Υ?ύΘ—/ΖΛΛ§ΣhλΊNQQŠ;vFςαd&œ3žί·mCΣ4***κΔχ_―€ΌΌœέ{χ αaΨνvΎαzΎ[Ής„cΘ+ΘeΚδ©„ν·Iϊηύ σρΑ ¨N'Ί^οω ΊŽi˜…^ΐ‘FU5boΌžΑγωόΛ?θδΏf΄Ό’ŒυΧ0υ‚ιǝlΫψλfMŸ§‡švjG"躎‡‡³fΜζ³/>m°/πσσηςΛΰ½ήνΤ}B!Δ™θ„’~MƒJk΅£Φu£ΡDqqa‹ί θ†λ5WΧOdΙMΕ’aP\Ifω>ήΪ~'žf_&Ζ^~ά΄Ϋ Ύΰχƒ+π13)τ: •έpvro±ΈρΰπΰCDΧ‘OοήδζζΠ»Oo,nn λΔΔD“MDD$‡";;›x³ΩrΚ†τVWW±oΩƒΈώρρq½ /==…I&QUUIp·`~Zσc]B[RRΜ/›6–žJ―^}8gά„Ώ6«ΒZΑΟλ~dΖ΄‹\eΜΙΝaύΖu̞5o/_ζΜΎ”O>]Α€ “‰ˆˆ °°€ΐΐ /ΊŠ·—½Ιε—-"  γI―ΙδΖ°!#9|4ͺͺb·;ΫN-•QW*++αΗ5ί1ηβyΈ»»Χ<ΰΠ‡Λζ]Ξ‡ΛίcζτK:₯ ΣuwwO.œrί|·’±cΖFYY >>~̝3wή{›«_ƒ§§G σλnΓωiΝj-ΌΏNM?Yρ)—]>]Χ5j4nξ^<υο—xα•7P…?x‡ΓΑΧ«Ύ"??Ÿΰ†·—7‡"##‹»οΌ½Γq( 8φάq#‚‚0+ ͺΣu‚T―Iτ5MCS]£ŒtMΓ’λΔ:όϋ?Ώj1>ήΎΨM?ψ―+•W”±nΓj¦]8―F †MλΉxΖ%hlά΄Ž΄΄T’"»3lθ(|||(+/cλΦΝ$§$˘Ργπσ=ρ'ιWUU’th?Ω9Ω„†Έ^θει…΅Κž½;ΙΘL#2"Š‘ρÏΫ=Z@·nA,Zx%Λή}‹Λζ/€[`P'–”B!Δ™γ‡χ»χڟZΫ~oρ§–+ιοΌ+ύƒ‡ΓΙςέpαΨ9\tΞ|ΦeΏuά΄Ιʏ\5ν.FŒʚΜΧ)//Γ :5ιΧu³ΩΒƒΜ»t?­YMzF:&³™ΌόlΌ½½Y΄p1λ7¬νp,pμŠ~ee56›£ΙνΤ\u₯²Ύ_½Š9ΟΕέݍ’’B@§°θ(ξξn,\°˜/W~JQ+'γN”¦ιxxx2}Ϊ,Φ²žΜ¬, #EExyz±τ¦Ϋρςτ"??³ΩBzz:?ώ+Ί ᨬ¬ζγεε“ŸrΧwσΝ·ίσδ£σΒ³Η+Ο?K…ΥΚ7ί~Σι$&:_v$lΗZiΕξp²οΐ.œr~‡γ¨­ΊcΦuT§§Σ‰Zϋ£ͺ¨ͺZ—τΧώ˜j†ό;UUΣpœδ€ΏΌ’œ΅λV3ν‚xyz78ΩΆnγ:fΝΈOOoΆ'l#&:–k–\GϞ½ΨΊύ7~}3½{χαφ₯w·O?~ύuc‡βILΪODD—\<—¨¨ξμΫΏ€={ˆιΝβ…KˆιΓΆ[›άδζeγλλΓ’+―ζÏޣ°°kځB!Διξ„’~U§¦βT]?΅FέβO-§ͺ’vρ~έ•~‡§ζ ΐ–L»X8α^ΖΗO―›ξœψ©,YΪ’Λ7£k:U•U˜ΝζNMϊαXβΐύ“CZz:δδSPΏii©deeρΐύŸς„ =#•˜˜Xͺͺ¬ψϋϋsιμΉ¬όζKJJŠ>l$ωωy|Ύς3ƒΡ£Ο’¨θ(+>ω%W^C€Ώ?™ψϊϊ±ožN‰%ΐ?ΠuRΖ` +;‹uΦqΙΕ—’i:λΦ―αέχίdΝΟ?’ι: .»‚W@Fz:‹ωωyψp$υp'”LΫ4UF]©΄¬„ο\ΕάKζγζζNaa&“»έΩl!/?ww7]qύt9…EG»$MΣρτπββ™—°nΓZ2³2jξύΞ‘ΊΊŠœά,,73X½ζG/Z‚o$ό΅jXh³ΩΩςϋο8|½½‰ŒŒdηDEE^zν-*+mτμΩ‹Ττ#τξΥ“Όόl6{‡cp αw­Ÿͺͺu Ώ³ήOSΙΏ^³RU'šͺβ°w<–φΨόΫFzφμ…§§ee% F #?¬ώމηLΒΛΣMΣIM=L―ž½©ͺͺ$$8„δΓ8”|~}ϋSUUIxX8‰χw(žμ¬ ΊGυ ͺͺ’ΐ€@3RHMO%&¦§kTMpGŽFΣtΌ½}˜2εΎXω9n7,f72³ρφρa@\Ÿ~ώqG‹H!„βŒΤ+ύΗ`k΅ύJΏ³Σ―τWWW§_ΜO`WΚ&ΆY?`LΏ κ¦ μaf[ΕϋμNω•δ„\’Κ'£λ`6[:=ιׁΏέξΊ*¬@ݐ^U=φΰΐϊӜja‘ဦ¦ΰp8ΘΟΟΕΣΣ“Λζ-ΰ‹―>£ZΕ”s/ΰ–oγ‚)S©΄VρъXrΥΥxy{“š–‚Ρhΰ@β~ββv8–θξ18°UUIOOeέ†΅Μ™})^^>lέφ±±=ΉαΊ›ιΥ«7›·lΒΗΗ—Ε‹–πÏߓx0MSωα‡oιΧ·'”LΣ*«*ωeΣz–½χλ6όŒ­Ϊή Œͺ«μ¬όκsžρV}χu§>Ψ―΄΄˜οΎšΉ—ΜΗbq£ ΐu%=#+“eοΎEffnnξdegΰζζΖΥKώĊPXXΠi1Τ§i:^žή\zΙ<ΦmXηZΎΕΌό\άάάIOOcυκΥ\Ω… ΥΧ.fΙ5‹xα₯η(+/γ…—žΓέbβ=ΞυKο@Qΐf·ΊOΏ`έκx EΗέέMS9’‹xύΝγG ΅‡k¨škΏX{uίιp4y΅ΏφίZ½ύ‚λdͺσ€οŸxΞd&r8%£ΡHUU%f³‰+\ɚŸWSXδΊRÎ„ν”––°~ΓZzΕφ w―>όφϋŠ‹‹ωρ§θΫΑφΑώ{)//γχ­[θιzE`ξ=Ψ΅;²²R6nΪ@LŒkTΝΡ£¬ϊv·άx+f‹…²ςR<ά=Ω΅;»v²pΑŠG!„βLu‚―μk8Ό_Χu***ˆŽŠ₯{Dt³?999TWΫ\Γϋ;ρA~N§“Q#G2mτB–}ŸβC&v&μbKι2¬Ÿp΄ϊ ;wQ”dώφξ;ΌŠ2mΰπoNOο€@Ίt€Q@EρuΡ IDATWAAPD±a]ύμu­«ko« ’(vQͺ@Š‚€Τ$΄@zBz;}ζϋ#…Π$=Ÿ›‹+ΙΜ™yŸ™3Ι™ηmΓΥα―2τόρŒ1²IZϊ‘bΖϋη^xšΘ¨H"£’ΘΝΛ%8(˜ ΐ ςςr‰ŠŠ&**Šη^xΊΩgz?•~}ϊ³jΥ/ddT΄Μfd¦αειΙ”ΙSωϊΫ/ΘΜΜ’ΌάFFf&Ÿ/œΟΜoΒΫΛ›C‡φγιιEΚ‘#¬‰gΨΠα Ž₯ηω½ΙΚΞβ›οΏβHj “&NΖΛΛUΥ8tθ;œ‡ΥZNXhϋχ'‘ͺΎ>~ΜΊi6yΉω̝7·[εΒQ οͺ}:[ΆόFTt³oΊ•ή={ρεWŸwŽ|6—#FπΰΣ½[·FjPTTPρΌϋ‰“1›Mdgg`2™IKO#>~Έb"Ώ¬^Ijj ORR“1›Μά<λζ/˜GnnN£Δq"UΥπφςaςΥΧΏ6ž”ΤT|}|II=ΒͺUΏpγ 3πυmš„Ζ™ΧσπƒπκΛ―₯s'Ž9D—ΝXψι'|πΦλΨl6ςσσ Βl6qλΝ3=φξžs+z½??\NΌλvόηέ,ψba½c©¨ΠTqW{:eίι<–τWώWOHψαXEAswο·X*žΎ°~γ―€e€a0ΘΞΞΔΛΛ“IΧ\Λ·ίEAAϊ$+;“…‹’θt <€‘C†‘‘‘ΞΗσώ‡‚Β¨£On½ΘΝΛeιŠ%θτzzχͺ˜Τ°_ŸώδδδπΝw_£St\ΠωωΉ•‘7βννΝαΓρππ"ωH2K—,eφ¬Ϋπυυoπ9B!„8)ηΎ¬­š4§N=>σμ¦P b"Ώ”b/?ύ I›Q˜ΆΥUϋn©Š’Υu$ƒ&>^§ͺό°ψ+.7žνΫ·²aΓΣqγ (ς7t±΄ο LHΗ}0Kr/τiίΎ=ŽE―ή}XψεgL<½^εŸJii)Ο½ψ 1QΡ΄mWQΩEZZš11Ρdd€Nrr2©©©<ςΠx{7lΌ†P…ςςΎόz!C%4,Œ’bb’ΪRZZΚǟ|ΔEŽeωŠ%ά4cή>>8°?__RΣRYΆb9wά:?Ώΐχ\P£Ρ€^―ΓνVq:MœΏv%!ΑmˆŒˆδχΝ›ΠιτŒΉψ3nΧΨζ͐[gίA^~.Ύ>Ύ””–2χΔsδνMZz*žžΌΏxθGTfqq1?ύό“'MΑd2‘™•ާ§™¬]»†©ΧNΓΧן’βζΝϋˆQ£.¬œΝΌvνβ°ΫνΌρζ™9c6AAM3©™N§PRRΔ' ζמ}ϋφ1sϊMψϊϊ7Y—ώ7Mγε—^!44 ƒAΣιΒh4ΰrΉΙΞΞβšλη‘ϋο#.™thί?Ώ;)ιGτ =3‹€Δ$<=½ΨςΗ6^~α₯zΕ²rυΖ]|)GssXݎŽz=fέρu«Uλ«ωθ>¬(τά½0ζ}ς1snΏ·‘§§Nt:…²ςRΎώfƒ &,,Œ²²R"Β£()-eώ§sΉfβΒΓΓΠλυΗMl©( &“α€ευuΊύΈ<#3‹… η3³ςwξPςΚ §–/_Ξm·ήΏ`‹?m@!„’%Œ^τVέfοίόσΫΨφ3νΓ-@QυςA°α› Ž»€φή‹ΑθTά`»ηΣ*–h•ίU.ΟNήJiIf½’’UΝ…¦¨\0hT―™\ρ₯ς1Ν#Γ€0`Θ±mͺ㴏χ«―Rž}ώ)’££‰ŽŽ&55…θθ:HzZŠ’ΰpΨ‰‹#--Ά11hšΖ³Ο?Εc<Υb‰Ώ¦ixyω0iβ΅|ΎpC† %,,ŒCΙˆmמo˜ΑλoΌΖ]wή‹··ϋφοΕΟן#)GXΎb9wά~W£έXW {8•A ζΧ λˆ_»Šσ:v:gΑ_mΧΨ"Β#IHΨƒ€?“χΧΓ ηΘ›}πυυgoβΊwmψ°‡»Άsε•1M€₯§ΰεεMZz:kΧΕsύ”πρρΕνvγλγǍΣgςΑGο3zΤh"""8p0‰ΈΈσ˜=ϋV~ϊωg›2­ΞΒΙTUΓΗǏ§ΝδΛ―Ύΰ¦oΖΗΗ·Iή½ϋ°}ϋV.»μ >_ψρkβ5rS½Žyσ?A―3PX˜NמΘΘH²s²ΘΚΙΔΓΣ“ΰΐ`ΚΛΛyψ±§1Œ””–ςο矫w,N§§Σ‰’(΄αY?ύ,Ρv;ζ―©™θWq© =€’ΣcwΨ›½₯j ՘p _,ϊœ!ƒ‡T ύII&&Ί]'cL;©β¨ζ#,ΓιφWsy^~.Ÿ}>Ÿ›fΜΒΛΫ›ύ•‘GŽaΩʊŠHIψ…BρwW§€Οζety#^~!ΥΛͺgͺVU¬Φ2²c³–V.׎›ΙΊκ«FE€²όΖψΟΦϋTUΕεv“ŸŸOŸ^}ρφρΑh0b4š*Ώp:8]Ί›r—“’ΆύΉ§ΣΩ¨IβŸ~ <,Œ¨¨(RRΓ‘ΓGHKOγαCU5^ϊχs¨ͺF\l;RΣR‰‰ŽΑaw0˜sGΓV_“aω2εΪλψdΑ<† Fxx8ϋ$Ρ±}'ž|ό\.' I»ρχ«JψWpηwΠL7ΦތΏτ ώqωUšX_C† γ“Oη2lθ0ΒΓΒΩ·?‰Žjž£=ψϋω“š’Bόš5ά=ηž—yπΰ~.}1iι)xxx’žžΑΪuρL»n:ͺK–.fίώ$ΪΗu`Ψ°‘άG΄Υ†ι4ΫT%ό!άKπΥ±Y»š=Ξ―w Q5TγΪk¦°ΰσω 2”π°pΪOϋΨ̘~όο=¦O»‰ΐΐ ‰   €ŸΝ㦙³ρςφnŠH!„Bˆ³Y’ώΠΈ>”—RTP@iq V'υ5'§«ψ UIΏV³Υ_«ώ‰τ[±xΥ΅ή‰wΕδx.ŠŠŠ±ΫνΨνv’“qπΠA:΄οH»vνj,λP=ρSQQ1N—Υέ8IΏ¦iόΎy£FŽ"''‡ΘΘ(Ž9BJj*wΟΉ§³bμξ=w“Wσ2ͺΫMl\,GssˆkߞeΛ–RPP€ΕbΑΓΓ£Qbͺ«ͺ–Ϊ»‘η}Θ°aΓ‰ !i1ΡνH>|ˆŽ©xόΪ]sξmΆ„ °°€_Χ―!1)ŽΞcΔπ ρχh–²kςφς­Σ9ςυ hpεD‡Hά—@€Ÿ?‡$³aΣFnΈώF||όψiɏtιΤ™+1={wΏŠ«œΘ­·άΞoΏΞΠΑCiێοO·nέ|όωμ;°—Όό\άnUu£ΊUάjΕχΛ*žEοVOψή­βVέψωϊ3ζ’K kP,ο}π.έ»vΑ`0pωψΛyε?ζςρ—c0ΈεΖιΌσΡ\¦NšΘWί|Ρ`€€¬ “ΡΐΤΙ()-EQ 1θ θtL¦Σ₯ηgΦ―Οlϊm=Ώmω>½ϊfς$άn7©ΟΏH΄νXβ_u%8‹… {ο"ΰκ«1›=X³&Ώ.;§Σuš’šVUΰuS¦1wώ\†­¨LΪ—ΐy;sΕWςΛκ•LΊϊΪ‰`ΣοΈώΊπφς"!q7ώ€€€°lΕςf­ˆB!„hνκ”τ·λ6” Λ?'"Ά[iew}­ϊφT q­ύ•έϊ+r•œτύLΉγ…΅΄WMδWTtlΈΑΑC‡˜rνυ|φω§μά΅³zω€k&σνwίΤHϊ‹p:Φ_^^NΧ.]9pπΪw ωΠ!RRSΉρ†™X­64MΑd2αp8ΉiζΝ|πα{8œN:v¨xmxX8EEEΥODhΙΔίΧ׏7ΞβύίeδπDDD°@AA!IIaΕΚάsη½4ουΊ_ΧΠ΅kWž8‰]»w±*ώ&^uM³•_EΣN>GαUη(0„””T–―\ή¨ηh@ΏAlΨΈŽ₯‰ Δ΄mˌfVOp˜””ΐ„+'b΅–Ε’―ΎδWLΐί?{ﺏ•Ώ¬δγ>¦wο>ŒwiƒβpΉ\$ξΫC―ž½ρσυ;εž3―‘Έ—e+–pέ”0κτ§¨š¦iμάω'Σ»·ΫΝΤ)ΧqΝΥ“«Ητ5Š~ϊ…_}Η„+ΖΣεΌσ°Z­όϋ΅7ΘΜΚ‘ Ώ›έA`` ΎΎ~xxx ΧΧ/‡ΓΕ CY·~ ›~ΫHΏΎύžt5nΥΝ‘§Ÿ­˜EQ¨::Ž »ο pDΜf3kΦΖΰΘψΛώΡb •cC5nδΐˆα# #i^Ό½|9ΨΔ=FΞdοή]LΈr{wγηλWρ;·bY³WD !„B΄v΅Ύ»Υ4˜NύωvήΛ χ$$,t:E‡’SΠ):Ptθt:ͺ&ψSՊ–m΅²υO­lεS57©ώΔ;0†¨.Υ“3ΥGΥcπŠ‹Š«—uξΤ…ΰ nΎιμv[υς’γόβ’βFνή―ͺnƎΉ„Ε?ύΐΚ_V۞ΙΧLΑ`0a0°X,X,EAQfέ4›Ε?ΐς+ α²K.«žύ»₯©ͺ†Ÿ―?³gέΚ;οΎΑΘ£ˆγΐΑ¬XΉ’ϋ€€ fΏ±ή›°‡kž„ΥZNtT ΏXΠ"I?492›-Œs)—^2Ύz’B«ΥF^^a‘αlΨ΄žvmΫ²fΝ"#"ΙΘΘ ((oo?&]s-SΪΰ 5MΓf³RRZBaav›UΣ*ž3―©¨ͺVωU­\V±NΥT4UCΥΤκΧfdfΰrΉ°Ω¬xyyΧλo@Uωωω( lέΆ•ΠΠ0²³³θΫ§/ωωωτzΎϋβs¬V+V« §ΣEpHK–―’G·.άΟέΔΔΔΰεε…ΩliPK?T$ώΓ‡Žduό/¬ίπ+ϊ_@ΠΥπΉb<švlςΎͺz½ƒΡTΡΒοΘ?˜Πβ ?TTξRZZAΓY²l)Γ‡ %.=;vώITT4ΉΉΉψϋϋΧ»¦!qEEΕ°ξΧ΅DFFpΰΰAV¬\Αε—^AAA!N§»ΩγB!„h­κ”τkθι;fkΏ{‡€T°Ι» /½ §Σ‰ΙdΧ NNͺͺ’Χλkι/-+eΕΚe$$ξΕf;–τλυzΪΆm[ύsQQQΕ3²U•œœΪ΄iΣ cςππΐΟϟkžŒΓ᨜ˆKΑl6γλ닏/ŠRρΊτz=“―™ŠΫνFΣTE‡ΩlΑΛΛ ‹Ε XƒΥj£ΌΜʘ‹/ε»Ύ‘K—.μή΅‹‰&a΅Ϊ±Xl˜Νζ3ο¨ΨνvςςςˆˆˆδΧυ눍mΗͺU«‰ŠŒ©Nn›+–ššσj’Β²²2ΚΚʈŠŒaσζΝότσb‚ƒιΡ½'eeeX,Μfs£MpX•Δ„°ιχM8μΆ“»οŸ’+ΏZσϋΚ^^ήτξΥ§:q―oξΫοsϋœ[Ρ4Π°0:wμBβώ>_ψ9Š’pλμΫ0™,X,žψωUT8,Zπ)Š’TOΕ,#:]E₯e}+ k*+³·OΦ¬[ΕΊυkxΑ ΜfΛq šVQaιrΉX½j5ήή>ŒΉh,εεΦκΉHZRYYεεεc·;θή₯;lΩΚςε+ˆŒˆb@ (//Ηh4βηηΧμqulί‰ί7oβϋRρρρ₯o―~8nŠ‹‹ΡιτΝ—B!DkUλGφiš†Σι ¨¨ˆC‡’——Χ ‚ύύύιΠ‘#ώώώ¦zέh'$μeΧξmΨμv6oήΒχί€Υj₯¬¬μ€ΦLEΡαεεYέmώεW^‘Gξ˜Mf.0„.]Ί6θ˜*ΚPpΉ\8@ΓP9™ ’Τ|’Α±Χ9Nάn:½ή€ΡhD§ShΰποF‘ŸŸO^^ydff°εΝτλ;€ˆˆ‚ "00°YcΙΜΜ`ηνdegJ―σϋΩ¬±œ*–:GŠ’ΰv»°Ωμ8vάn7z½£ΡŒΕbF―74κD‡œ”••6xhŒ’θ0™LxyyWώŽΤύo€Ϋν¦ΌΌœb²³³ΙΛΛ£ΌάЧ§AAA„††βλλ‡ΩlA―ΧWCUQšΖqε6NΒ_‘”Z­V[ΆώNjjJu…IUň¦jΈU7šͺΝ…£.Βdͺ˜ΟΓΣΣ/―ϊO(Ψͺ*Ev» ‡ΓŽͺj˜LFL&Sεί6Sυλš;.§ΣQω·Φ^ύΔ“Ι\έ[£ΉγB!„hF/z«φI?λJοr9œ”*  Fτz}吀ΊΛΝ=J^^.οΌχΦq­ύ΅αηηΗν·V{PP0ΑΑ!gΨ’iœX!ΠZT%”V« »έZέk6{ΰαaiτ„²6±4Wr[ΧΈZϊUδͺ5V­Ι©ͺnιU-τυ₯(JuΛz}“mMΣpΉœΨl6ΚΚΚ±ZΛqΉά z<<<ρςςΔb±`0Τ―R‘Ύͺ*#l6+.— ·»’"°ζπN‡ΑP1q ^o¨T‘πWUP΄§:w­!‘n­q !„B΄uNϊαΨ UCξΛr#^3Y0›λ~SμyΟ§~vΆ¨Πœ εΩKM­5Ώ‹šηψJ΄Φs­ž|ΐΙρΙu#„B!ΟθEoΥmφ~hœξ―ϋiψ>j&κV«½α;§Tυ†Φ 5ΕRSkλο’ζωo-Iσ‰Χ„\#B!„’%Τ―_½B!„B!Z=Iϊ…B!„Bˆs”$ύB!„B!Δ9J’~!„B!„β%IΏB!„BqŽ’€_!„B!„8GI/„B!„Bœ£$ιB!„B!ΞQ’τ !„B!„η(Iϊ…B!„Bˆs”‘ζGf£ΣιPEQͺΏξή½›ήύz7„3ΫΨNχξέ[: !„B!„gMΣͺΏjš†ͺͺ„„„V―?.ι7 θυϊκ€Ώ*αΝΛh4ΆtB!„B!ΞU Ώ¦iΈέξγ֝2ιΧιtθt=k&ώZ3„+L&SK‡ „B!„β,PΥ―ͺ*ͺͺžΤx\―ΧλOjν?~oM¬¨`0Ξό"!„B!„NΫΚ'$ύ:ξΈ–~ιήί2τz}K‡ „B!„β,Q5–¨ώZε€€_QIϊ[XΥΠ !„B!„βLjNζwb>yR?ς'ρkŠΔξf>ϋσ,F&t{σ‚6zg3©lB!„BQš¦ύεdόΗUœψ‚Φιίά?ξεβ & „eςυξηmΏηΒ?!„B!„’ΆΞ”Η·H?ς£ε)Δχ$,:ˆδόν-‚B!„BqΞ«Ϋ4ρMΥ- άB!„B!D£;Kž WΖΪfρζΞΛ|/z”nλΥ B#oιs| ŸΓCcό‘ωB!„B!Zƒ–Ο—kEΑhΠwέλΌ15}ε2ΝmΕκt·|G­ŒΔ=ΙΠWfέB!„BΡzΤ)ιoΘDs©E{ωί–9˜ ^'­{hω@ΌMALκρ8ƒ/8ΝΕIΉ½Ό2ι?6υfMfΥΌωvS2ΕΖPzŒ½ΩWχ$@Έςωγqσ$œί|Δ’½0ϊΙטΦα0Ÿ?π?t“.¦π‡ElH.Η;nΧΟΉΛκψτ—=䨁t»t6wN’Q΄σ;>ώr‰)9”θCθ6fw\ΗΎwανߊplšΙ5oιιpύxξͺˆ–™0A!„B!„¨Τlyι‚ν1nΘ.>…N1½ͺ—wΐucξ’W―,N|ν {QQ΅ͺšh%lωπe~pŒε©ρωΏ§ΰχλΌ»κhe…Ωόςή·”\τ$sΏx—;λ+–k©,ω"wΏΓ— ^ζ*ΟMΌθΣ,VδΩΉ‹˜χθ`Šό„₯‡έ€‚—_ }'=ΔkσΎβ³gΗ‘­ψˆχ{3ψΞη™ήΕBο9Ÿ±δηŸyύšhIψ…B!„B΄ΈΊε¦Zύ»UΩΆ€«0aΠmTΝήΧΎ{G\8P² —Ϋyϊ}ΰ&yΡ#̜6ιΣ¦3}Ϊ,^ίhC+ΨΜ/D2ω–‹‰4»PΪ αΊΛ"IΨτ'jΥΆεήΒ#Β0hnΤͺεŠFΫqΣiΔeŠf̘¨ZO&M냿΍gΧqŒj{”ŒΜŠΈŒqCΧ?_ƒCΫ +&;«Ό"n‚‚ƒr[)V—»ώηJ!„B!„h$Ν6¦r'ygΣΝ„΄υ /6™ S;rνI;”C^ͺƒ{‡Όϋ{Π}Ε3ΌxuΫΚξύ Σ+Έ’2Θ°νζύ›'ρaΥKέ\½(S!#Ξ ΗnsžW ρΖζrn\:#ϊ 6ψ9mΈt€[EgΥ­’α&wΛη|ργFς)sΈqڜτšVΉΧΚ2‘ŸB!„BˆΦ Y’ώΔ„έόΊ~/Y›Ί’Χ{7yέ‰νT@rbGχΘ]ΓMo>Δ+/=E½O±ƒΕŒΑl¨Nϊ5Υ Šζ ˜σώέ 0{­’S@§@‡^q£tΈ:tŠΚqΠͺk΄κejΪb^{u~“οβ‰{;l)dωΏξgwƒΟŽB!„BΡ4še"Ώΰ δaξ·έ¦i˜Œ&τzN—gG'Ξqw9p8μάΉύεT.ΡάΈάγΦ*αΡD¨’’ƒ:θkl’‘ͺZ}i'μχδε§ZR΅¬<ω)!cyυκήDΊ]Έ]”–jΥ―Q”ŠJˆ†Lv(„B!„B4¦f™onΗΞ’ŸŸGξΡ£ FEΑd4c·Ω9tθ v›:²²²λ΄oΕo γ—ςσσX ‡ΒΒRv­cυŽ£¨x mΪΰ“Ώ“_·§‘ΔϊŸ³.―ͺ'€ΑΑ’ψΓω…”8±d!„B!„’~š₯{Jj .—UU)(, 1)‘„Δ½Ψl6ŒF#GŒΐd2‘]·€ΝB»^δφίfα³χπF)x…ubΤτξz ϊn“Ήgό«Όυ½|£΄‘ΧUwqχεορfϊLžEŸΒ“w,$vκsτπ Kuxψ΅ΑΛ•GnΩ)ZΡ#žή>x™Mt ΊXK )Ά»#>θΛr(΄ΧμzςrΕ@¨—‹Όό*JΡγ‚ΩšCΎMΑβ폯‡nεΕ”+ΎxΊσΘ·ͺ(Oό|}°θœeΉδ•»κ~’€]ξbΤ¨QυΪV!„B!Δߏ¦i¨ͺŠΫνΖεra4š½θ­ζiιΟΞΞζ–[onΐT¬EYXO·ZsR^’OyΙ©V:)Ι?U—kφ²μ5—Έ)+Θ’¬ς'[iΆšλb«ΪΦUNa~ω™D!„B!„h6Ν2‘ί«―½V§ΧΛdxB!„B!DΓΙ°s!„B!„β%IΏB!„BqŽ’€_!„B!„8GΥm"?j/„B!„Bœ5ŽKϊ5νψ¬^Σ΄γΫ'μ !„B!„­Η©ςψšNjιΧ4­ϊΏ’(Υ˜Νf6&‹© Γύ{sΨ˜Νζ“ή$!„B!„βtjζρ':.ιOKKC―ΧW·ξΧlεχσσ#ω`2.—«‰Γύϋ2 ’œœά‘!„B!„8KT%ϋš¦αv»‰‹λP½ξΈ€ΏS§NΝ™B!„B!•Σιώ^fοB!„B!ΞQ’τ !„B!„η(Iϊ…B!„Bˆs”$ύB!„B!Δ9κ€Gφ(>>Ύ9βB!„B!D5κ/ן1ι9jdcΔrZο–ΎΫ€ϋBΡ4nσΎ­₯C8k¬‰_Sύ}S !„βο‘ζύΕιHχ~!„B!„β%IΏB!„BqŽ’€_!„B!„8G]IΏšCΟžΰφ›^eΰχί―|!„’9Ή“ψhζF_4šΡζβι°ΧΥA !„’.š(ιΧ(9Έ’χΈ–K―}νgΊAp%2zφ½ά=ωžγ_έ‹΄»΅γ™W†±ΌΟr΅iB+ ,_·χ[fNyq[ώΖwLZ9‡_XΚΪΕ₯hg~υߊ–‘Dόν;Θ;e}’FιΟλXϊάaΚrβάe€Ο]ΗςΧ²/³n;ϊλψš^S–―₯'±ζΖe¬ϋ(³τΧ³₯ίΡuόΜlNϊŽL{λ;~ψώΎ~p(ζ–ŽG!„uV«ΩϋλF%ε‡GψηG©΄νΥo₯›Ι½~ΠΚ’ψρέ·Y΄ώΊ`:˜Β7£½§h”μώ†w>ώ‰ΝI™”κόh7`"sξžD_Ή„BˆsA“TΫλC;Ρpe»h”^Š:o2`߁ΪμMΖίQs₯‚­οx6 H`μοΫ°|ωΎK8?MΕΡik/ FΫhvbηύ¨r"½‰HN’Ϋ?’ύŸ)2gοε|ΠMytιΊl"_Ζε9°θ_c9ͺ«ς+ivβζύ˜ΰ²’|?”J—Ήίέγv9μθMώ”zΕ³@£¬mGrύ0DQVΫ;r§›ψθ˜ψΆόUv<^Ξ‚9:ξΖL’ρη}e,Ο3qύ/ž„«n6ώ³œPΈ#A± …‡U4t€m'QodΔUzς©xΕιπP4ΏPΖηρόΤ‡N‘ Ο–ρΙ:ώω₯‰@“‘Ι;ύ“δΰ‹Kν¬ΈO£ηSή<Ϊ^£ΤPλ”ydν6zΉίρ •wέoŽ`Υ[;Hι;ˆRΨ±°”Θ;œ9α―’°oΎ…n· {ˆ“¬yΩώώAB_μ„O­?t&zUWχ„ο ε|< Χ—N½1ΉJ8ςαοlω"±7‡ ‹λΔΠ7;βή²•εŸ™ψJwυ€ABΒ¦ΰΫ'Σ,rνm‰΄Τ5H E§œt|Άu;Ω±Χ‡~Ο_@°·‹²}ωΈΪT”œ)>C}?O—΄Γl}ψ ο:‰Ίaγ"Ψυή(Ÿ1*Η²ώƒBΒoLοσ-h9yΈΜ(΅)Ώ6ju}((:ΠΤϊvΗiνΧO=γ/>Β¦;$ΗyΒˍmθυζ ¨νο¨8­}fjGYφκσ,e*Oo4αeۘςλ$ΈFU/`νηΣ’+xψ­'i§β§ΎΘ£oϊπή Ε_Qππ £σεχqνCΡψ8SXρΦ³Ό8Ώ3σζτ€ϊΤ !„’‘5m_=U«ΣΈm₯<‰ωˆž•wœjpOΦOοG‘ΏΓε°–GŸ'Ÿg؁7τeίυ—Ρyχ—΄ύι0ζb2Ε°ρ¦aδλ©ΌρΥ ΝPΏx馣τ}ς%†ξίC‡GΜ8 wϋΛψζ™‹ΘWŽηΙ—Ά=F³ΊΗΚ―ΪΏW/V>wϋ½ θύΤs OJ'4Ε͎Ύ£Xςπ0bί}‚+ΦΊI»ϊf–υ―ϋ©o;ΓBίσu(θό˜‰ίG:ٝffΈήΑΖε Γ±Π©=€Ž1Ο™Ωq©Oι§£ψ7—]γ·glόnԈo‘τJ@Ίk?… =θί·’¬›Ω2ΠΑή,C#@η‘ΤE‡—¦R:Φ‹KΖT$uˆ_Λ* ΠιG§Ά'gα¦>=θΥwΫ>>€CΫGqΏΎτλ]‡.֚ŠΟθnΔuφBbΖF°χω"JάΤ>ιWLDΜKDνK­uωΊ¨HΪGU½ΨB‡‹CHϊ±«‚—^ΡSή’E‡Αˈρ4ٚ.Ζ?w6…™‘±υh…;ε/€†ζRΡ=¦ fo0_P#“«E|ŠΩŒWŒ&lΨϊ ‘k?t€'ΐ‰ΙβIœdύ’#qώˆ€ŠίΧ€¨cΉdΞΟ鏻39 ŸzΕοIοW‚qŸxν(zΜ>υ(Gœ^?3΄άό²#”+ޚΘωα:`4³'o`έ»UλΧ±ψ· &Ό5•ΎQ: ˆλoΏœ_οωu7 αŠ`CΜPώS΅ΗΊ¬'_|½Ÿ<­'u$„BˆV¨u ΠsζΎ5ΏϊG52”?4(ͺΕ¦ZΘΦMόƒkη #G'^ΝΆ˜šwΎ φΘ²’Υήm_Ύ9Εxi™xh ΕέΞ£PDF—@Τ}y¦£τ¬Υ˜Ϋ‰4o? Β-hI 5!“’ΨφX œ.FO°ήA^*¨¨δyθ‰Š=φrέyzΒυ²“α‚X†―U 4ιξv“|HEIQš¬C;β »Ψ͞‰El¨qƒη΄λh— Ηe:±ƒκΪ‚XAΛ³bχφΔγT3A)&ΒoθI›ϋ6±SiΗΰ„aͺΛΝ¦bΔ'³ϊό(f=zU₯Ω¦{•LS"ύVκ£;«[Aj†‚ Έ27²ΰ£/Y»'« ΥeΓΫWs\_B!„hr­κNNσΔχοœbL­Έ1–Ω*“ƒΝ‰¨9‘΅’ͺΗξ_΄Κ4^«qOsͺΜΎ.Ν.fœ•;Σ”ΖΎSPέΗύXA9yΡq?h k«# [εΘF7Ά~fϊX­όΆIΕ?K‘M;ΐ ŒωΑ“>5φ‘€%τ„00i‚ΣqΈp›L§Mμ΄r6‡‚‚ ›UŸ:eύθZτjώ‹ςΥbφ½Ό™”ΠnτόΏP|ότh»vΏ²>εθΠUμgl=?ž–±5χμΖΪ³'Cτ;ω>ή3σCΤΞΓ$-ΪIόdΊ=1˜Ž±uLΓ†Ϊ ;p«hUQ4Λδ–΅Ή>όκOΧXuc&=ήAΗΠζΚxšλϊ©ιήίΚi'Wnκ θ«/݊α<Η>Tτ(ΠΤdύλV‡Oηφ'ϊ`FΫώw.iκΈ…BΡ\ZUίϊ”΅ŒZœŽΞ?†,CaΛΏ‘ߐ{ΨW5"QΓpp?α֞€šσ =T‚’˜)υ₯Τ†MIΖwο>όέ1δ+yD$δ£SΌΙφm€œDΑm0 αΐ³  π«ΫζšΖΡύ*Ϊ…­ύκa7GU±Ρ 3θ²:H;];WΌ\Mr“α14tώzΛ$ύ}•Ψ2=ίΕ;Ρ¬z:E‚Ξ©'Τμ ?_!°W&9F=:§ϋΤ­οj)Ιοο‘|ψ@²‹mο¦Νc±Τ§±ΉΥ)/ /ݟv <€βφΫΊΥΑICΗP\gκΰΖνΠc¨γδςJh;όΛLΒ[;Ψ±2”a—κι z<ΟoOοQ<·Œ„ψBΪΗQcΘ{-β;:·½ͺΩPÚV‚Sσ­\νW09R‚Šωτ½κ]~mi”Εο$αh(}ŸιLDp+Ήψυϊ©ιήίͺιC#sν"9CeH»ŠίgVΉjΕ }D4᎟ٟ¦rAεzwΚ~’έα\‡²ύμIλΐ•ONd`hΕυuΤQΜ©¦B!ΔΩιμxΎSi—.cψ{ίΠ5M5—Ξ 1μϋDεiΰΞ¦ηΗ+ s˜I½z:Kξ‚έ•AοΉλͺΡ:do`όƒ―3α±w΄ί…x>ϋΊqwΜXϊƒK™ψπ;\υΘ[ ήοΖ;˜]] g.ΏVtδΗFΰΒEτ‚2ει·Ήζαωt«υφ2ΧΖ;UJS]¬ΞA^#έ"A 31tœΖ―ΫH<¨R|ΐΙςΗμX/1Σ30ιqsh§Žv}<ϋθρΪκ";LGπ50μz…­ZY·ΦMΡQ•£ΫlxΗInσ§Z5άΈ¬uw  z`)-§ά~βΫΩ“Eο©DLιEDϊnΆRΦ<ΐΥaΨIc9ΛίΚΐј›-xx–‘ύ{ε…VŠώHdΫ'›ζƒgI6G6c+ΆQ–Q^Ρ½Ά&[9ε₯<뚐κMxuŠ‘ύ3IΕ'”­QςϋARχS^μΐ–žGAކ%Π|\Εΐ™βΣμnTMΓνPίΏήίH;™+R)Κ·SΎ0»WΫ·b"ldξΥ;Ω΅‘ς"eGrIίUzά~ju~D£ho>ζ ΪΣΙ«σœΧO}βW XBΌπjsΒ †VR/ςw¦΄ΒθξΩόψΑWμΘ( οπz>^°žβΚχP Ξƒ ωώνΟψ#-ŸόΤ-|ϊξO”Ύ‚αΑ X‚φLgΫΖDr Ž’όΫgΌώu)*4\.4χΙNB!„h՚€₯ί΅ηCn}l19.ε6Η&Βθ?–'?Ίƒήυ(Q—΅AŸ" :΅πηoμ؊Ox?JŠΎa@’wτElD γΨωS"ύχ―dΔʞό P6πbvk tέU†+’ΏΟΎ‚ΓQlΉ&Ϊό%tίyˆ(·'yύΗ²αΖ‹9j8SωΘ¬ΥΨ_…X}d7&8© [Xoœ΅M,τ:ϊΟΠ³χŽΏ&{ΣLbίηΗ‹²Η­|}±"M!ϊrf=k¬θ!―Χ­Qt@OΫpΠibμ66wΥh¨Ψ>ξq/nτΆ²τR~Μs¨Žv-tS@M²σφ₯V’ ©ΈΩ›PΔ&OCψ2aD-γ”pότ©Q‰ιr¬ΎIΛNfϋη₯Dάsm<Bι>+œUolηpΟ!ΔΆiΜBC΅»pιΤΖ­l0Ά‘σΝQlώhΛζλπκKχλc)ύωψ—)Ρθ3­˜mŸ¬fΙλΖΞ]ώL'όj\#καŠL~ΔΦ³ΫΉ’WŽ m©©$ύsχ²5ρfφ$``OϊŒ;Ύ7ΐιβσΝΨΗΪ‡w“W¦VμϊΙοI6{χπXzυԁ·φ³Ί’φNVίΌ cL¦vΖϊqyυΎΝCϊ0Έh';η―cyώγήγΨ–ΪœŸ†4Ptυ½ήZυΣ"ρ‹3jΠg¦Κ₯χ?BφήαΙYγφλΜ…c†½¬j½?Γξy–βχήζυ;’§qΨLώuλpΐΨ›©sFπβ»Η΄υ„)7ΝΌ”το«‚ΫΝGw>Γβ”BJn4 ξΉμGΌΊ0υ…—™Χd3q!„’‘(ηΎ¬­š4γ)šΆβγγ9jd“ρnι»MΊύΞEΜ|~Ί7σΏΫΊ7Ξ¬ΰpρeΟrτψrυ°–¦4;G^\NRΫα\<Υ_ζ‡ͺ3‚+YŸΩ…±χGΧm’ΓΚν ?_Ιڌn\~δYΝ§9©€Ώ²˜„θ‘Œž|ŠyΔ)έζ}[K‡pΦXΏ¦ϊϋ¦ό\u'~ΐ¬§ΛΉσΣ{θsΞ βB!Δ©¬‰_Γ¨Q£NZξtVd½£½%χύ’)f"ΖFβZw˜ά“Ίψ‹3²επ―n’Ζ„Χ#αP0y >Jn±΄εžH+Μ!',ΑIψΕYL£,5•|ίόδBB!g˘~qΞ0φξBΧΆY$*•.Δu’QϊK"Ωq]ι|~ύ›ξ<†u£Kh&f­eΆΌU΄Œ$ΦΜώœΆέι>τTΟ”’•rbιΗ_°fw ΉE…d%,γέΟ·2pm₯η½B!8‡fο+ξσ'ρα“Z:  xξαq΄kι8Ξ: ήγ‡3n|wγH§Η/‘c™Υ"Ν€U”Πφ ™Χ“§ΤƒŠ³ŒΞηN>}ρ+2ςJq{FΠ}Τ½<1υΌΏΗΌB!ΞHξ Ξ&“|[:ŠΣ’1½g!yΆΊη₯ Coyž‘·΄t B!„h­€YK!„B!„8GI/„B!„Bœ£$ιB!„B!ΞQ’τ7w"_ώλ νw·t$gΰ ρϋgyμ½5d«uΨμ¬9>!„B!„55A―Qœ΄„·Ε€+ΖqΙUΧsολ+8r<—]Ν]Νλ/Oς9›Ϋ*xψΰρ·ŸϋΗ/„B!v”εO\Η?ΏMηψv%’ƒ+yοkΉτΪΧΩξϊ‹}Ψ·ςΪu3ψ ‘ζ‹Ξ΄½JΖχpέγK‘' qzŸτkωόρύR²:έΐ³|Ζ'/Ν jΧ<Ώθ­=—Τ σ(¨K ψYΗHΫ oεžΙύέ\ήX‡#Δ9§ρΩ§qαƒoraΥΟa£˜tΡ·άΆ#‰-&x4ΈkΧ|žίζIΗό?ΩaoΟ%£ƒΩΎτWrƒ/fφ싉1h”^ΛwΛ6’š‡Uρ&Όσp&LΈ8O5u9oΞ_KZ‰§ͺρϊΓk0φ˜ΞσΣzcΐNζΆ%,^ϋ'–‚g8]FOaΪ HτŠ­`;ίΎ·„Ν)₯˜Γz2n5 3Υβ²ΩzK"^·ESΊ(‘΄d;ϊΘΊάΩ—νΟπiεlžχ ΫΊ=Ζ-Ό©yz­Ϋ>διν=xlFφ~ς hθ£.γζ\Lhε_εZCŽO!„Bœ›΄~[²Λ¨—θaΉBGδΐ<38–ŽΉσ˜υŒυ/χ±eΥ‚GΎJœΎŽΫ›»3n”7χΌžYΖ4I!ΔΩρ“ώ“¨”• χτΔάdΏ„₯ϋΈy6c—ΏΙΛ»1ω¦iYπ#ΫΣ/$¦­³g mNfτ΅mπtg³εϋω,XΡ–Gμ€!ςBnωηpœ _ςά2onΌλ2Ϊκ@1˜*~ς„oωΰϋ4Ί^yvτCΝ?LŠΫχXm¦feηΪ팼κv .eϋwσέ·ιxΫH‚ksάjϋζ[θvϋΊ‡8ɚ·‘νο$τΕNψόU ΕLP…yh˜HίΎŽD]WFτ #?·― `FNͺƒ8γρ7Βρ !„BˆsŽšq€ƒΞ8:ΕώE[’ͺqϊ!χωV±+ξB†‡Ÿ¦₯μ/·ClGβ\Ι̐S!N₯i[ϊ]ι,}εMΆΆΞ#όON6‘β鍧’  xx{a@^―βvW RwηοfΕΥόy$‡»Υνΐ‰ͺΑS ΙΝS λ~ϊ¦XEQ,˜έ塟Η@1βιYŠbΦ£WUΞ<Δ^Α;0Γφ< ²28μέƒξκ’sσQ τυρiœσήΠγB!„η57›|Ÿ6›ΟόΪSrX·j/z€ϊή΄šBhγ[ΐΡ\ ΪΧsBœΓš.ιWsΩπΖc|5ŒG_ΎœΘϋϋ42E―«μR€ 7œpXj&«|ΚΆ KΈςϊΞ„z›Π|Ο7Χvο•΅‹Κ_ύ%c04$½VΠΥσέΠ†PœΗ‘C9Ψb.€σ+~KΞΐΏ8€6AΥ™£‘Η'„B!Ξ5šέŽΓδWοaΌjΖVξΞ•ƒλίP₯˜0:e !N₯iΊχkl~η!^ήݝ^Έƒώ-=£†=•ΓG£vιΊΕ„€ΡUŽσΔΧ) Šϋc†?ύr²²kΡςήόtώ!: H:œKtl;bΫ…‘y(G!ώux‹OwόB!„Bœ‚b4at:pΤ+ίV9OfŸ‹Έΐ·ω‚fΗf7anΊ Δ„8«5Α#ϋŠΨώα#<·1šΩΝ’§₯œRJΛΚ±·T_p£~–\’φ€PPZHfΒJΎZ—rΨ ]PΛΩ²3“β²bςŽbΧΕ“}Ίβψγ{~ά‘FAi1ωYΩy0·uT φΙβPFνb,xF·Γ+εΩΎ!Υ–―:±9\hn6‡ZϋγB!„β”ΰг9j―ΗΖξ¬^“O ϋρ‘~Ι–CNi‘!M>]™g₯Fοή―mΰΛοφQκάΗ«³ΧρjΥ %ρ/.δήΎΝπΐ€:rΡ?zρΩβwxv‰žΐΈAŒ7ˆά ΗΏLΧf8“.ΝbΡ’ςτ" ΆcΉ}φh"οσ―aVΩό°τž/r’χπ'jθutkάόΗs"%ˆ€ŠrzΡΦWAG;b\KΩB pΰϋ|Θ―Ήܚμη΅'AoŽfΜ-χ06²βδiΏEN!„B΄VϊˆΔV±ο°‹ΡݎΏΟwνω[[LŽΛAΉM㱉«0ϊεɏ\‰«Y[>ˆ»ϋxžrίgΪΎϊu‡φqΘΗeα’τ q*ΚΐΉ/k«&Νΐhώ£Qœ΄”OηΛΪ]i”θƒι<ςξΉu mΝ-›hlί―9Θ>\Hδψψοό/ωμΫιtπC^ψ<±ι[,κλΩ»οψ(κόγ―Ω’Mο=$!‘χŽ UΑώ=Ϋ©(’ˆ‚ηYπΤ³χΓv€b?»' bQDDͺτ–$”τžέί 4²›„άϋωxδρHfwζϋ™οΜfη3ί2f»^ω‘΅»cιφδ™œυtβχ­cρ+»¨j]LΜ:ΕaRτεBζή³Ž‚€μή KDDΌΓΜgw‘“φ/’wd,±‘mhμσ”°βοFx@8a~Ηϋv¨ιu9ΈχδϋΗdo`&?|Κͺ.W2dηL>ίήW‹nvόχfΖΏ»ύOž[ο+aRcήΊ^ϋˆiz§G³™Η/³f“Σζ*yω]ή|ςšύ:™Η¦ΧC/3©wήOϊΊ_>«†v$9*œ¨ζ§rz―hςvηRνυΒΌ$'[ΫHݞ„δόγh7Ίφ%[Ι.hθΰw)[υ«ζεSuBίF!½:rκδ3θ?2»ξ Šˆ4 ξΌ7ΉβΑ4»½+wm+eώϋ©ψίθΐqσ¦μ?πί,…ίD›Ϋ"ˆΈ£gΌ//H IDAT«+^ς9ΏbμΔ7:πΏεRήΙ|+Ž'τζx†|½&y['sν³hvK0ΑoΞ)―>ΝΒϊΉ’5‹—ςμU#ωΗ9/RMrΎψŽz–₯Ε5Ηΰ\3«.{†₯•‡-,ϋG/Ό‚ΦxΨΙς_Μ°aCzΨΟ™χΟ£ά“pώΒ3—έΚϋ?}Ξ€ —rξ™gqαυ3kS™'kΞ,δ»Η.αβ‡η‘_›ͺ―±|“β53yςΦ«Ήπμα ?χbΖ>όΏ(Δ΅αmnΎμ8χΞΟΨ»k&qpZ@ε—κωnΥρψΰήΙWŸηΠο.α "ψfϊJ<­#oŸTχσ““zλόω‚Ζ½ξ]|όΠDžŸ³‰’Ήώφv|ξ"6Νyž‰}Μ.oܝ2’rηΎκ4ZΗGΫz0K%{έF<ύψΚΙΓΗcϊέ”fΞcΦ’*zυοDcν)βΞΘ£ΐEtκοΩ°Ρ,ŠHGyυpΟ·h;‹G}Β'—υ3j1Ϋ‹K0iW·Β±rίN\ΚζΥe΅ΎmΔDm·»ξb‹ˆΘρX".εΕ‰ΛXσΠwά—Θΐ‹~%ηι\rŸό”±‘0χπαϋρhώp^Έs=λo{–Ήδ‚>e― Ψ†σΒ#YlόΗ£ 4ζρχgΠό‚οXϋΟYLκή+!A©τπ_ί·­wΏΕ_*ώΝθ/~πJW#€'cnκΗΞ7_ΰλ½&ζή―yαΝlϊCϐšο@ΫΪf@ΐO,Xω{ Q΅ξVτ‘_Oϊ©ΫθrΓ|2λ>™υ ³ή}€3γCιΨ­­ηΧ$M|πκJZίπo½=™1©λyyΚgμ¨Υ—©›Γ‡ZίwΣς Bγi{ξ­<σŸςώ‹χ0Έl&OΌ΅šjΐΪκbžxυή»σ4‚βΟη‰ΤΓΜ;ϋ{嚬Η jΝ§Μ΅η¬–v’…^›¦3;»•λ•γsbκ~~6μώ›…syΰ’σ8οό£~.z€Ή…žd}u|5κγoIβμλ/"rωΣά4ώIfΨ[ϋL―ΔWΝή3yrόM<½<’‹?›$‹7ŽίΡάc Δ‘Β&ΗG#»œ,Ÿ:šηξ₯άA+ώΙέƒ£jEWOͺσ+p…Fy‚όC\Ίπω½‘$Ί=λθΟ§aΕrΰWk\ώV«ύ@WϊίΎŽάωρς― ŒŸ8‘‘±V ž».ΊŽYOOγ£σΟelΈ«_ ΝΣ‰"—½>⾎m°Ι·a?Ÿβ+0–›ϊδιy+ΩmžFsŸ1„τΎŽρ½Ηρμ‹QlN'£Ο­άΡ3Δ³k[+ŸΖέ –SvJ?q²ω—ΨNΉ•φŽ6°: rf1K_{…ŸRΗ0εΌ$ΟΏΩM'ΙΓGs^‡x ΰτsϊςζ}[ΙrA²§1BθwΫ›τσ΄ΜZ”oKιΟω)Ώ½9‚ ΞξΒgnfΏΩ…x«ƒΐ v†a' (˜`―^ωΥρψšEόψΙšŸ=•8ptbδ9vœsnιI€GΫ¨Γρqΰωkδ«7¦³‚Js<7έΐ>œϋ_»‰n5ΥU]ΟΟή#t{Ύ3•Η\: υμŸC>_ }ό=ΰHθΝewχΰΜ syχΥ;χρ F]w1ύ“=<ΗλŸIَ…LεM”uγ’›§p{ΫπCs½xγψQZαbf-(₯ϋu]π―υΪΨω(ι·Ρρͺ§yιΒr w¬ΰΣΧ`bΕCη‰OžαΓm›ΨSQΛUFybWͺM¨—»ρF(§\w#έox€-ΓyxZo`nNΏχ`Cu9>Ά\ωΤK\θr³ϋσ‡xΡ=†ϋΟKΒj $Β£+亝Ÿ ΎFq₯Φ58±ΟWƒο?@υ"žΌόIUόΫ―wΎw'ύŽ8€VΒێ`ΤMVΚ™Μs―$ΠφΑαΔxržΧ%>s?Ός3³ϋrσ?GqzZπ‘i―?ΐ™Ν짦°,u“†7Ϊ†Z9q>›ΓΥ/4†ψPˆOHαfs}zΏ^ٞžpΦX{ΈkqΕ‘wΚΜJ*Šmψ‡ΧΓDJEΫY&]w:mBqoœΘΐE>Œω8Μ<ς«,XΘ'― υ|]KΚ ōωK‹ιΧjΛ‹{reΏΪ•_π#Σ¦,₯͍ΟszlmΏ8mΨτΪεOΚwg0ύαΗω6a7ήΧ‹δζŠ™πe½xΒΗΧHΌˆgώsΤΒΐ^άϊŸ^΅(½.ΗǏИ8BqSlΗξŠ&>>ΎVύ;λr~6τώ›…syπΪ©,?ζϊ³;γ_»Ÿ3<œFD?_ ½VοΙΨ©/3κ·§†Q7|\lšΟ‡ο}ΐόά†šΒ›φx7λŸΓπί€υσΞΏn`Fά`.ΉόB·>ΠΪο­γ‡{‹&“—spΟ€sIͺ9d₯ήΥΟטۍι’ΡΞi€E^±•}Y&qι> ζΞύδU†Σ²Ή»φCΝέϋΝ ²_ψžΥΫΒi~Ρ) λͺd_Dδ€5Ί iΥ―³b―‹ Ĝ9+XγJclŒWfΛω)·+7^7ž³"-€›μκ|*κs€—{_L~ƒά!χs?―πΜ”Ωtδ,c>οVμ’ΛΉ]j1TΠdίό©Ό°Ά3γžκ„­΄„ΐ°: 8IυN”YΘχOέΜkΖυL½­_-†7Τΐ?Šθΐl–Έώƒ’)έψ―Ν܈;ό”#ήfML&Ύp.sΏΟ ΉGUΕ.Β’b<‡“u/ζοs:πΰϋwΗγ φΖρm ,$_:™©'΄n]ΞΟVηξαδσε3~4?χ!^iΩμ°ΟJ1‚hή ξξ7’[φγu?~f!+^Ή›GLfμ#cθβ_FI `X°ϋβh€y›œο'ύ†gΦ¦|ψovΉ°‡'Ρα΄yτΪ>ήϋ’σ6ΓAυ§Rώς –έΎJ߈SΫsκ˜όCΜ†u{>²{Γ―Μ{deNΞJψρͺ,,α©τ™άΥKAŠˆˆΧ1\pωGδ}x;ώυ/v›ρtοφ^8’X\»Ÿeψ3χσcYεήb“£xΝ―9׍]Ν³mύΐ6ˆ;/ΎΡ3Ο’ύ,;©-―αασaΛ‚ƒΫw-βή]Ξ+Ήϋ(¨vbš0τ–— ιΝΔρ³Ή-~ɟΏžτη—ξέ_0ωτ»σΊτ`τ}7i2³»?ΚY6Ρύœφ ΟnμΗύχΤbŠ)s7σg-b_“‡―όζΠb[»λyνί—Π¬:σΰΖYQN…΅Ϊ»OΠ±wγςρybΪD|ΕJ|η³ΈvτYdΟ:ςm–Τ‘ά2&“η^žΐεn‚ۏb€KHν’ή,'{Η>ό:χ€}-FNxλψžμNψό<Ω5šΟ—A$· jθ(Žd¬U W6e.⃏7QR½‰§―ž§•Ι9OΌΟί{4Β1ΩrŒ>™dΞ»x<vϋ±·tζϟϠΑƒ|Δ΄’i^Ϊ’IьωόBO%΄ άa¬γ‚Η5t""Mή‚ω ύξλοΥ¦ΗMΖΫγΈcΗΌuχΌsΙ+‡8Χπβθ{Ι½ϊMξ’λ§ΪΣω)" gΑό <ψ˜εΥΥם>ΥΧΟ’©#χ.~ώ9Ÿ{(‘ς3+[*{1τ%ό'D秈4rκ·!"""“«‚’’vύπ³Šς^J©|Αˆ9Ÿ§>8Ώ‘Γ8ωθό‘“„’~i”ά9ŸsοΨWΨή™‘·ύΞ΅{RŸˆOιό‘“EKϊ B2„! ΖIΖ{s*Θ‰Πœ ""ΗgIΊˆg?Ώ¨‘Γ9.Ÿ"r²Π˜~‘&JIΏˆˆˆˆˆˆH₯€_DDDDDD€‰jbIΏIьoωvFfC‡$™~0Oυ+"""""r’πνD~ζ~ζή?†Iλπψϋ·³1Oθ*eΧϋ«X;oΕ%ΰBĐNτΊ8?=΄φΏ?μζiΊM ‹*GDDDDD€±ςi^Άς]ήέ`%΄Ρη…&₯s~αηοόθxϋ0’ ͺvη“W€½QΔnbšFƒΕREΦSσΨXMŒ£‚rs?/ήΛ^ΏV »7FQG""""""r4ί%ύΞ f½Ύ„–gbημ*Ÿγ&…› ±u;…τΑX€€Θ Β<\Ϋ½x _-π#&w'ΩεΡ΄K0;ίήJIbϊ?؎ˆΊ>·Υ]ΚΦI+(νΩ‘vƒ#π«ν Œ’–ίΎ”²‘CθwF&₯sρνǁτžΤΈΰš6`'ρΪώ„dε²ρω”:HΫƒ6ΝC=λαΜeΩΨυŽiFΡλΩ΅Λ$ }]Ζw$!ϊΰΚςΩϊΪJ6ύT@…%€Θ~mι:ͺ9aώUlt6Y§Œ`ΐιŽ#6[½`_~ŸΘˆ{ΣpΈΛΨύΑJΦ|³‡’RΑ]ΣιrC;b# pζπΛθEd™ΰH’Χ#ρδLω•μέyω ^ʟξFλ―¦σCDDDDDΔW|4¦ίdό7ψΜ~WυΐΩθ€ΕP½.›=y'¬IŊ|Ηφ§]L«ί-%νώή$d±c›»ζΥ‹Ά³xΤ'|rωQ?£³½°“vu++—ρνΔ₯l^]†[ύ]p<―K€ψύUdν71χg±κύ’λθAΒ``‹ΒΊ=›‚6]ιΪΉ„œ,!q~žŸ@|6Ν,$αζaœ9΅­vπσδm”š€YΑΞi?²~_<έ'Ι™w%fη―,z)›JlΕϋQž[†‰“‚ο7°aa!.LJw•α—Œέp‘χή"–.  υ?N?Έύ,–LΙ€ΜlρτxεΞ|Ί±fλ§ν θͺΑŒψw?Ίœόη ΏWκ―Žη‡ˆˆˆˆˆΘ ςMKωJή{woΏ›$γ­Ϊ%¨ Β μΌtΨ²„Ε7}EΜ°V΄9?˜hΟρ$΅ΓΥ*{x3š₯E⎫do+‡$Ρν©h\Gίo0¬8Bόj‹§νmq€mΞdύ[?πΝΝθpe’šyvύΊw’ky,} Uζ&Šzφ g·ZtAp—±£•”‘©4·U±ϋΏϋ)q†V‹3(rxRύšNζm;Ψ΅7––lΆ.υ§ε€ΆΔ%@<νM'ϋ­μΌ2„„@*Φ—β&γνudZ+‰ξΫ‘ΚέΆ Β(ΫΝζ―έ€έΣ…ΤΦ ˆΤ+Z²}|»σšΣ"Κΐp8J  *zφ£}Ο,@ ‡±Χ΅ώκt~ˆˆˆˆˆˆœ $ύ.2?yΕ-―β…ŒΎ™€ΐHZσ š­Ξ`㌍,œ°•δ›ϊΡ£PΝ-Α€βΐΟbPi·bs`Αΐb1q{ΝΑ°αγΙ‘0p΄jN‡1œO­`ωΫADώ£9θGΒU]ˆ½u1«ζœϊL|ν&(΄“vGƒ΄αΤ;k±ξΑςƒβ~O’Ψ‚-Ϋ(έkbRL©_α Ώd$…jΩNq€%aωΎ”¬Bφ‡&’ΰΞc2Ψc4ΨφQTZΚ?cΫ‘-˜Έͺ‰Κ’ΓAtϋΠΪwq©cύΥιό9A^OϊΝΌωΌρ©•‘OžFΈ.oΰSV;·€[η洘΅ˆωΩHJŸξΔzRKVγΠΝ‹½–)eΡvOXΙžκ£–Ϋcι:₯/©‘&•[v°ωÍμΨJκeƒΡ7¬V šeTTTPQnBH}ΞΐgbΊϊϋ°Ώώ,#6˜ΐόRςΧ”ΰlӚ”ͺεd¬+ /8ͺ[$νξErΘα+Z°G΅eΓ†Νχ .υW—σCDDDDDδy=ιw]ΜΟ{Χ°θΪαΌ˜yξ:{>ƒξύˆ{ϊΫ½]€ΨnγΏ₯T:ρυƒ kξήoVύΒχ¬ήNσ‹NaXŸΠΪ?Uΐ]BΖKk);­}ψ•ε/eϋΟ4‚κ+ο7«(Ξΐμˆ˜9Ε”˜DΗ–‚ͺ2ΘίeŸr sG…ξ ZΔAΑVμ#wC αύ£ˆ*cεͺ¨ ".Ϊΐp…bΟ ¬ΘAP ¬†?‘ΰυ ΙΦσF^~}Τ‘qόm3ΈwJ)4šήρΎΞžOYFΞWΉΈS# χΗV^HΦ‡;¨hΡ†GΝ«ΧYMέϋM+‘#ϊ2,=δ!hR2wks›qΚ‰ΔšVrnϋ™ίΔοtΟ†/xCώœ΅d΅οH|H;ήΝ ΄M’ š‘ήk+_έ@δ i„™l{}Υ½Ί‘i€;ˆΰπ"²ΆΡκ~‘8fdR™B pΔΣrΨ:Ύ²ŒΠ±νHJ΅γά[ΐžunβΞM"ψ`ΓΊYιΒmšΈͺܘXj±ί£ώDDDDDDjΛλYΈE³δίQ»JC°[ b’›ΥHs~0peο`έGk(Λ―Ζeχ'¬ssNΉ₯Α!£3μ„΄8ρfn+ή+!ρ–Sˆ ˆ£γ˜ζM^Af—~€ΕΦΓNZIFΞδoXžν& }:½Ζ§l)wΠl\?ͺήXɊ‰(7ύ‰θہSG7Γί,AΗVRžέŒ¨(Ì"’zΫSC²؈Ύ²?}V³nκ|Vη»±E„uZ{ 0wlβ»»Φ°ΏΤiχΟ"ΓDϊ]ΓιΪ₯ζφ’ώDDDDDDN€Ρη?“Μyΐn·σ†ωση3hπ Ÿ1­dš—ΆdR4c>ΏΠ“Α©αΩλRœΉ,»n–[GΠ­“Ζ³m\πΈ†ADκΑ‚ω ύξλοUωί°`ώ|Μςκκ³λ >΅φ“˜‹ˆˆˆˆˆˆΘΙAIΏˆˆˆˆˆˆH₯€_DDDDDD€‰j΄S띃п aH=—ͺ1Ω˜ΡΠˆˆˆˆˆˆόοQKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ι­3yΰ‘ΨΰjθHDDDDDDDNŒ&ς3ΩϋΙν\1e%ΞCΛμτ™8ƒGΞΑπ~"""""""r>HϊέζvΖƒΌ|cΧƒΨό•π‹ˆˆˆˆˆˆΤ#Ÿ΄τδ•ΤŒΠΰΰϊ?ΰΚgνΌψςηMμ)χ#Ίu.y­C pmΰƒ'Ύ!jdwφΞ›ΛΚ]₯Ψc:2ό/—2 ™γΐκy«ωό£Οω9#wxkυ ΔԞh(""""""S|ΥVQXP̎Ÿξ沏+1ΒRιqΦhΩ‘pŸ5υW‘9χήΫ”Ζ]5‘6‘e¬ŸσoNεΆΡ}‰pοΰΫ/C9λ’ œ^ΑΊ/^cζ¬…΄Ήq(±μeαο²Τ6”Q?…θ²5|ςώ,Šά=}°ˆˆˆˆˆˆˆΟω ιδΤλ#(/ΔHyΏ~Β‹/έΓ#ΦψΧ%ω¦εΏb=ίύμ’Ο5#ι•b’θ=bKŸZΞΊ’>τL±½Ξ’_jΠσ”Μ~sΉnˆ)ZΛʝQτ?ŒΦΡ /ητYΚΪο|¬ˆˆˆˆˆˆHύπIυ€δτI>π{JςΝLά·žρ_-`Ηy%ΥYΏ;7ΉϋXϋκ=,ϊ})ΥΞš› bc"Ν+`ψωawγάyXγIŒω-8 ‘qqψk9‰ΥΓ u+͚'cωͺ€B7Ύ{H ₯9g\9έƒΟΤ­ψ‡Zύnϋ“½5 Λ‘‘Y­X1½§ˆˆˆˆˆˆH=©‡€ίdoΞΜ¨ΆD[}S‚%"ž8ΫOδ•…ΩΜοΨ7ΈjZ?ŠpW&Ήωn:ΖX“’}{)3£}―ˆˆˆˆˆˆH}π~»»k+σ¦Νς­»Ι+ΨΓ–…oςάΜ]t;{ Ύκ.οߞ½ύYφΙω~s…%…μέ±–Eί―fŸ»ζՍπŽtKΩΓ_.$#Ώ˜‚?σωΫ}£YIφδ―ψjr6•κ """"""œχ[ϊ ?œΫ?γΉ™“Ω[δΒ?-ύ―x”λψΑwCδύH1–«Ÿ2{ζΏω΄Θ…#4–ζ]GΠΑ€{ιQτ»ψJ fΞβ•IŸAd[† L³ΩEG½ΡΔ]ιΔ‰[EDDDDD€Ρσ~oIfψ“ξυ ΧΐA»a£h7μx―΅ε’{:b‘%ω\ξyδ°ΏΓ;pξ˜œ{Ψ{†u?j;†?ΙwœM²·bρ!_M«'""""""" LIΏˆˆˆˆˆˆH₯€_DDDDDD€‰ͺ‡GφΥl\πΈ†ADDDDDD€ΙQKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ιi’|4‘ŸIΙ¦Ωόη?³pmyUώτ½νM<=Γ7ŠˆˆˆˆˆˆΘQ|’τWoύ€{ώω5±ΓΓZθΖe QΒ/""""""RΌŸτ›…όπξΗX/y†».Lψ‘βύ€ΏςW~Z@η~ ylΒg¬Ξ5‰ξ0‚knΊœ^ΡV―'"""""""Ηηυ†xχΎd—nηλ9»ι~νΓ<υΔ­ 5ηπΘc³Θv{»4ω#^OϊΝ²RʌΞ0³Ί¦‘’ήƒ‘γ/¦ΥζοYΌΗτvq"""""""ςΌžτ~ώ8l1ΔΗόή•ί‹%Ϊ^BQ±šϊEDDDDDDκ‹Χ“~K|sRμ›ωu}ε‘efA.{œ‘ΔDjZ?‘ϊβύ,άΏ;g±ρΝ SωzS.{wδγηg°½Λ0ϊDκ‘}"""""""υΕϋ³χ@—1πχW§πζ?ζ©Κ`šŸrχέr1ΚωEDDDDDDꍒ~ΐ‘›&1δ&Ÿl]DDDDDDD< Aφ"""""""M”’~‘&JIΏˆˆˆˆˆˆHε›1ύ΅4­dZC‡ " d\πΈ†ADDDD€ΙRKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ι― W –Ώ ΐΦ’–eM±κ Bηv¦Ε–¦Έo""""""{ΌžέΉ6ΌΜ¨αC:쨟αWσΚΧρWz£ΆΘ‘Ψ’a}ίοΐ²Ο:b‹Œυ?Ο _Τ[Μ ¬_œΰnΥ΄Ύi…]6(r@ρ‰qΒ\ќ2πFΝα‡cϊΉά8€‘P'¬Ό=&dθc-0½ΌνϊˆίΜ22ŸΝwŸ•ΰν*hΪLJΎψžΩfR¦Ši4Ό>{Ώ΅υΥLϋθrά‡]ψ;7½Ιߞ(€]³?IΖ +ΖμHΈ4ηΔ ίξ[Υ£υmΕΈΏY„»Ψ±u)θXΚ(© 4Ζ…Σ]Fetε^ΎeψYg’ϊ/aγ―έι΄a+?·σβ>ΦCόήΰ\΅υΫθykπSR°cŽ}Έ6Β ±aΌΥΛ›Q[`:1OΙΕύθVΜ6šΧ Α2°–υγ·γ^°w;Σ³ψ΄Εφ—8Μ'ΦbώΠΛ7RŠyΟ:\W”xV―F%eρΕ”E›˜2ŠcΛ©ϊ­: R:t8!7—OFabϊζω\:₯ˆ―Ύω–ναlίA»„²υ‰9¬^Η…S›³jκ6*=Ι|«RΪ½…Oo"β©^΄\€³ε6~ž2U]«jŽίSf%;Ÿύ†UN ½=ogεf»ηξΔ:`ΡŽΓ–;sY6v=cšQτΑzvν2 hŸF—ρIˆ>DY>[_[Ι¦Ÿ ¨°Ω―-]G5'ΜΏŠνΞ&λ” 8έqDqΥ ρεχ‰ŒΈ7 ‡»Œέ¬dΝ7{()΅ά5.7΄#6Βg<ΖBά IDATΏŒ^Df‘ Ž$z=OΞ”_Ιή ‘—bΰ‘~ƒ’$‡ε·/₯lδϊ„IιάE|ϋq ½'u'.Έ†zqζ²lμ‚Ζ%S2};3*±&%nBZΆ8μ_ˆ#šζμ|?w•=Rqθ‰ˆˆˆˆHƒσ~³p_, b؝pόι °^ŠΖ²ΠΚ=Ώ«ƒ±ό΅ –εh_€i Δψ,λpΝΞΐ¬΄‚£3"#Η„Nω˜Ρ&ψƒ0ܐ‘γΒμ™EAσ“±ŽrαϊakΝλ[ͺ0GξΖ\‹Β0*ŽŠ½¦ψLΖ]1šaΆ©ΒX‚1±5–+p'{ΪΕΆ©3Ψΐb¦O=μ₯πν,zb+—NHΫΣ?gmψx8[ŸŸνYΒX—t¦cŸvrQΪf9™Οχ₯ΓΆ –·π°―Ά3Žž–ργs3Y”μ νήstG'²ζ,#ίZCό3°ψΩ°Ί-G&ΉEΫYγγ€ί$wώ¬HΑu-­5ΌΥέφaFΔcΜ‡Σ{mq–VθΆΧμLLK –³NΑ², cρv́YΈfμΔίλϋΜ;Vα:ϋπιnΜ»ΖyΏϋΐ0·?–σϋbYŽ‘k`v―iύJΜΫΦγr`9»Ζς£b―)ΎίήΎΧΧk0#ό±œΫΛO!k π(ιsΓρέι—1δžψ›έ‰>―‡TzΆ²ιO‹W›³ΤY]¬ΌΖΕωΟ'σλ3YKςώϊ#Ώφ.ΒΦ_½Sˆ!ΙΑ€ί ?Η'ρθε!It{*ΧΡΥhXq„xΎy3'Ÿ‚κ0Ϊ€άAδπ€€ϋ€5ΜΫv°ko:--Ωl]κOΛIm‰K4€xΪ]›Nφ][Ωye T¬/Ε]]MΖΫλΘ΄Vέ·#•»+l„QΆ›Ν_»I»§ ©­-@©W΄dϋψ,vη5§E”αp”„TτμGϋž!X€@χΝ―{'Ίφ˜ΗςΧ·Pen’¨gzv«Ε|¦›‘Ho„€ Odέc…»8,ιKJ8a\ v›$₯©©_DDDD€‘ω6ιwmγ«ΩΫθxΑ=$Φxύo€ξAN¬σb0N;μ₯uΑΰ61δaΪΚ1O­€₯ώό`ΰΡMοG³bΜh…εΉŒνvpώΦMί€ͺέΉΓβ)Ύ6ίΪ930ͺ0Σ]π“Ο2jOΒ¨ γοΨ1θXΦρΩόL*<ΜΉŒΜvt^»Ÿ^ψ­MŠ.[Ξ‘=hŸ΅ƒU)ά”0ͺΘouΨδwNœ.Kύ<Β°αSχSΩά_Nep Ηλ’bψχ{’lΔ†lΩFι^“bJύΒOψ½Β€pB-Ϋ)΁΄„ ,ί—RšUΘώΠDάyμίU{ ‚ϋÞ"ŠJKΩυΰg{B˜Έͺ‰Κ’ΓAtϋΠΪΧ«αGΒU]ˆ½u1«ζœϊL<~΅ΙΙ ;!I‡z+V·ϋΨ)0WPžg‚’~‘ηΣ€ΏςΧ/˜›ί›q’<œΝ‰yf>̊ΒXUxh©ρ[&yΌάΣ“FςMΙXnKΒpWcφΚƒ~‰ΒΘχ(¨y_°‹CaρώηFQnάF A%DzV†™Ά‚™KŽZΌyKΆΧ’t7ξZ4{•ΧΊχ;qωωqόŽ &¦ϋ¨ΏϋλΟΞo#6˜ΐόRςΧ”ΰlӚ”ͺεd¬+ /8γΐ[$νξEςα= φˆ£ΆlΨ°`·y³¬‚Š*ƒ *ΚM©U֏ţ¬v7•ήΊ™%"""""u⻀ί,fΙίΑiχ+¨띢Σ?ΛwA‡2)³m)XΒ1FbTaZ0ϋƒ₯³έaMυv0 ΧΦ΅}KF΅ —―Ε5e?Taqœ€Φσ­9Ύϊx„™+ŒŽwτ!τ’/ω’ώ ½£Yο―9Π]Ώ©σRχ~μV,Υγ?ΐΑ¬’8»³ΫΦn3§˜3θXΓBPUω»LβSœ΄ζŽ έA΄ˆ70‚‚ ¬ΨGξ†ΒϋGUΖΚU9PD\΄α %ĞAY‘ƒ >ϊHΊKΘxi-e§υ‘Ώ²ό₯Lb™FΧγ]Έͺ¬ΨκˆˆˆˆˆΑg)‘Ήο;>9‚ΣGΤ0ίΡ"σ0ϋΊt™-‰;5wg7¬HΗ:΄Φaέ±,΅@ημο=P"fΧbΐ‚q_O¬ηvΗ:΄#–lš•cZ ψ¨-Φ »bνΫ˚c"ώγυσC0^JΓς·6 p`άΧΛ³IΩ†‡ρω’AΨ[ƒι»} ξΪΖΆ,`λ–Ύ ~·†YέO6f%Ω“Ώβ«©»¨:’™έ†LA±GύΔψc«E‘ψ—”Qφχ{ςη¬%k[9•{χ³υέ JΫ$“m`D6#½W%[_έ@ξ *²sXϊ6ͺ{΅ ){ΑαEμΫDT+~­#qlΪGQd0A6 0ž–Γμd½²Œ-«Š(/(§xσnΆ~’MΙa§YιΒmšΈͺά΅ΌdR2wks›ΡνςD/λJbφV|SκύϋQe”•ψ}œŠνψMΞ¦²>n„‰ˆˆˆˆˆ―’~7Y_Ιϊ΄œΡ’–³ΈΥΈΟ<Ψ΅·ΔΐQŒϋΥΈΟ+†¬pŒΝ`ž½ Χ;™˜‡ZMΈtΡω˜?ŒŸC1Jݘv:νΔ}K¦ΝcE ŒΨ€λŽβ£ ώ“υ3β°ά›Žεέ(Œά6Œy‰XieΉαa|Ύcdvdπcαl}|1Y‘@X?>–AδΓƒιΥ”~w₯gem“^Ο α„Y‹Θί~œ5–@RG„‘3ωΎΌq![*’ι5>ύ@KΉα ΩΈ~΄ΟeΕΔΩ̞Έ‚= 8u\³΄[IΉ%‚¨(#1Šˆκ2*bC²؈Ύ²?}šdMΟμ1s˜―΅δX 0wlbΑρΡ•KΩUYΚΦϋgρρ₯³YΉΚ³Jfn+ή+!qLb 8:ŽI ψνdξρnMΊ3σ)τ #<ξxηoŸˆˆˆˆˆΛθσŸIζΌ‹Η`·› ΟŸ?ŸAƒω4ˆi%Σ|Ί}˜•lβ+6¦žΖι—‡ήKΒ™Λ²λ–aΉuέ:ύ/Œ—8Q&ωο|ΝΒέν~{²ΗŽ ηΫ°D‰σϊέΧί«"""ςΏaΑό <ψ˜εΥΥ.†NŸZ?“«‹œ ‰Γ“p~ŸΙ>O§tίUμ%σΝΞH¨έ“DDDDDΔg”τ‹Ζή­νSsΨ0―D]ΠkΕ€δ› δ¦·§mgί> TDDDDD<§«s‘Á4ΏkΝ:Ž“ŽAπ9§1βœ†ŽCDDDDDΧ(’~ι•FoFC """""R{κή/""""""D)ιi’”τ‹ˆˆˆˆˆˆ4QJϊEDDDDDDš(ŸLδg―ε£η_䣟Ά°ίNΛΎ2nό…tΡΓ»EDDDDDDκ‹Zϊ+ψ啇x/―·M}‡wŸΏήϋίγαΧ–SιύΒDDDDDDDδx?ι7‹Ω•]Jϊ€tkETrΐFιέ”˜^/MDDDDDDDώ€χ“~#’.½Ψϊε,έλΔΉw ΜΞ€EοΞD¨wΏˆˆˆˆˆˆH½ρΑ˜~+Ν/~€‰{ξ䁫‚Γj₯ε₯ςΠ…)š5PDDDDDD€ω 7)Zύ)]jeΰΥΧσΧAρμψjίn-χ~Q"""""""ς‡Όί_½†·Ÿ™Cμυ/3q@§ΣΞCάόΔ{΄{ρZΪψδy"""""""r4―·τ›%ΫٞO›V‘Βo#sgβs·°­T3ω‰ˆˆˆˆˆˆΤ―'ύFHkΪΖmcΞ Ψ²·‚œuΜyϋs2R;Ρ6D3ω‰ˆˆˆˆˆˆΤοwΆ·΅ζ―χέBωσoqηΥOPj yόσΎKHΣL~"""""""υΖ'#μ)CΉιΙ‘ά䋍‹ˆˆˆˆˆˆˆGΤφ.""""""D)ιi’”τ‹ˆˆˆˆˆˆ4Q>Σ_[ΣJ¦5t€ΖkθDDDDDDš$΅τ‹ˆˆˆˆˆˆ4QJϊEDDDDDDš(%ύ"""""""MΤI‘τ[WOηΊKoaό³+Η$"""""""'ŸδΠΞάΕΌ9υ5ζ¬ΨI™#ΓFρ·1ƒH²οέU€ΌzχuΖ1―”ž>Ž·zϋ"ΚFΔ4ωρ’B¦Ο?r±₯΅?_θOr#ΉΣαήZΙ”KݜχciΗ=–""""""˜x?te0ύα'ω1νFy­Q₯kψθίΟq›±Ϊ½ψ }~ά…_P"›/ΉœoΕγ(Ι€Λ»ŸΣui!U Ϊχfρθ³Ψkΐ(ΨLχwΏ€Σςl‚]μοr*‹FNV€cŒΌωCš9NΜϋG{ޞC«ΜͺŽα±νpώαφ!εΥ9ok7–€n€ΗON2FdοΒιτΩΞ/wOΰηt«Gugψ„ΗsQνfνSε|ωΆ“=…=ΔΑOϋΣ:¨ͺζύ₯,ΩF€Λ?³³~|9«3 ε`nH«δ‰ ZeU±ͺΨΖ™·[XρPϋ\?˟”ύTΙǏV²~Ή›r‹…„aF>ν =άΛ+˜rU%;sMͺ]ποΈJμηρΨvΜ= ƒΈΰ|+LJΎuρ―`†';ωδ7}gyo+V(Αi!υš@Ζ/ γώοιVRΙ;O:q–ΞΖώΚ}/ΨρOqpΓ¦0Ογαi΅Hψ0°ψΩ°:,ΗΚ!""""""ήζυ–~kRΪ:>γΛΟ6ΣύΒV–eρύ±ΊΊ’τŠΊtΞ7!΄s»Œm…tyθ­ίI\– £j9V—γj½η4 ­U$ΎύΞ^F›Μaδ—/’σΦj\-ΞζΓ‡†‘gμ₯ϋύO2`σ":­Κ·βΨ6bΉKh»-3ν\fά;„Όƒ΅cd/ώ“νf€5•_n=ΐ=G/gwζίMŸΏΝ$’¨ΤγύΫωd1w?ϋϋ’ΰKƒΈλ Φb'ί½ }ή W―υΎΧΑ>U¬Λρ£"X ’ΪY2έ” βΜ3¬XΐΉŒ6:χ΄RΥΝΐ?Ə­ΈRLΆΌ'amm§λίJΆqΪU6ζMsQθΆe3π[ aG˜Aΐ‰Œι7όH?œΔXUDDDDDDjΟϋ#Ζύ{2ϊφ³xτι›Ήπu«_ύ.οK[Ϋ ukίu§Ά`W F…qΜυU؜`ΙΙ%άmb[ϋW_ώΡο+Bς\ξέM€iPΤ‘5V€(v΅‹Δ½i?‘;‹0:E6W€…=}»‘XΝόωφφ^0lΈό,`€i·γ²X01±Έ<νέ`06ˆΡΧόή n 6°ξν.r‹\¬½°E‡Uau₯…ζΉpDm±Φχ@ΒΔΦ# -ΰvΔΨ « \Υ&`ΰΚ¬fξΓ•¬όΩEq Έ«MͺΫΰnΊ“(ˆˆˆˆˆˆ4y>˜&Ξ ’η΅<υή•η—b„„γΏι%±'’SΗΡώ~8&½¦qXφk±`bΰŒK#+9θ°Plμ 30φόϋx μ1Λ ͺG.aϋήb ·‘b9ώ˜ ›3> €{δ‘βwΤϋ π ‹L^rhOψσν[Iψή7ϋυKŠ•8Gyy‘]}0ΎΨEζf+ήpΠ!ωΐ’‚―Mͺ Uΰτ~""""""β>IϊΝ²ύμ©°b/ίΕͺΩ―3ν».š4ˆpΝήfFχ`Ω€ο8gώ·\xσjφ¦FQUUHTΆ?Λ›ΐςv§ςkΪRϊlΝ…wmbŸ%—€LΞ΄Sω΅ΏνΛιφν―€.-ΖΐEΒηο2,»5‡ŸΖŽ(£†νίΘ>ίμΦοBm ΈΒΰ₯;Λ‰ΚA—φU;]lZ mΖΪ‰>Ψ—ί]nβ2ΑYnbbx>Y^€…°7ΏtΡi€AΕς*>Α…uδΐ}Kš…ΘύU,ύďΈAΥ…œnΑγQf%ΩS°Ζ‰Α7%β§ΩόDDDDDD|Κ'IΏkγ{όύξΟΘ³‡Σ¬}zςΞn}tŸr/2‚ΘΈφ&>ώœ^ίm$f}f`ϋ;υ 7Ψ{3–ή>σ­/ιΈzΝ\μο5œEWŸΞ^„ύϊ=½ζd–;2‘}vDYkάΎgδ«Σ’~oW—3ϋζ>ΝGœ…ζϊΣΑχΖJž?«œŒŒΑYΘβ@ ύή eδ@6ο°1μI;οήSΒ#@δ©~œσO?φ½|δΫ,m\|Ώ›ιχ—πΰ>θεύ³$z|™Έ+8-ξ{WˆˆˆˆˆˆHέ}ώ3ɜwρxμφcΣΧωση3hπ Ÿ1­dšO·/ΫΈΰq ‚ˆˆΟ-˜ΏΰΠοΎώ^‘ ζ/`πΰΑΗ,―>πlω‘Σ§Ξ89ω)ιi’”τ‹ˆˆˆˆˆˆ4QΎ{dŸˆ‡4§ƒˆ4Ν)""""MZϊEDDDDDDš(%ύ"""""""M”’~‘&κnLuξfΞόŠΥΩTΩΒhwΦMŒξνΫ»ξ|ώΜ³|³Η €%z7ίvΝ­Ύ.β“_ΆQ˜FbΙx?Oρ‹ˆˆˆˆxΫ &ύ&Ε[Ώαέ_γΣ}yτΏΡνπ-Uf0ϋωgykΑ& ¬1΄<Š[nFŠŸWb!΄22ŸψŽνpΪΉΑGΌXΑšΉ³X4‚±wt'Κ(£Κιϋξ–$†OxŒ‘nηΊχyd^-_—“‚Ήk# © σ”.D5Δ ›Κ½lzy;[9ˆΊ½£ζUΕ/ΗeR΅9“uέΒΞuΕT[ˆθߞξ£S υϋύ=%_όΐ+SxwsUχ""""‡œ@Ύλ&λ“»ύχ7ΨKπ1WU¬}σ!^ΚθΘΝSήζ'."dα3<ςώfœήˆΈΞUXΏ=φgπf)…ΕnβΫv#5"„π8’‚κ£EΞ‚έαO@@~ΗΛkz]NζΎ2Κέ W~εO[ΩΫ±Ι»6±m‡ιƒLŠ?šΟ·3ŠπΕΦ}Ώo5\ό&fc¬.ΣτΞybVϋE&e­ΪΡοίg1όΑ„¬[ΑΟΆ}ƒΰaνHΨΉŽuΛͺ½QͺˆˆˆH“q-ύ’ϊ\ΓC§¦ΡjίŒy¨όΘ—λ˜· Šaw^CίT;Ώξ"«Μ$χλΉ¬ϋk+:ϋr@YΕξΉ;±@΄γ°ΕKxλ•Ωl..₯¬‰;σ>ώώ`Mη‚;&00ΐ¬ΘbΡ§3m6ΕF)‡qΑΩ½IrΰZΟϋΌΜ’RΓή…ΛohΛϊ韱z?€œ1ρƒβ©ΘόŽηόΘϊϋ)7‚Ih{#G!½>šœJrX~ϋRΚF‘ίA˜”Ξ]Δ·{Rwβ‚|uχϊUΜ}ΪI·η{χ[½•g³dμjόοN—v5έq³ηΕ/ωaNΕωΦSzsξ])5ŸdΞ\–έ@ΠΈdJ¦o`gF%Φ€DΪMθAΛ΅8aΜJv>ϋ «\z{ ώžV½εW­ίΜͺwΆ‘³₯”jΓAh–t½‘ Ρ!`n^Η‚'ΆP_…Λ σ/ά|`OνΓy›QηΫ8ž_w1™sJIs ι™ω|?k7-'$b7<Ϋ?_ςθόjΔρ{t~7dόξRΆNZAiώ΄_mοcz;>wωσΧ³ζ— ΊέΡ’ΰΊήW5HΎe0ΙΏύ›LλA[˜·&*3μχŽhš°σύά]TφHUO ‘ƒNθŠΣΧ†v€3ΧyLλ½Ή₯-9§•œ|τς|βF]Mσχ—°eΏIη8^‰Uν'gΈsÎhε7Βzpι„ΞΈέy,|ύίlμr;£{†`ό˜Ε¬όθ5Ύ*νΗγ―!ΑΜζǏί問Έύ’Ξ[ΫqΙέsFξώ;νζ~TN—³ώΖ=1ε”Xb±`ΰŒ$΅Ο% ½4–@W.Kg½Ε;sSΉϋZϊ~β„ΰx:^—ΘΌ©«ΘκΡ—²Xυ~ IzטπXZ'“δΏ˜Ώ:‰λy ZΧΖ\φ$Π»₯'WμbFηΌ+όe–νaυ?—QΦ9ςΩ»οψ(ͺ΅γΏ™-ι½’Fθ½χ&PP@¬(’^+ Ψυzνz½ϊbμbE½(W±J€χŽt$’ή³»3ο!!„”MΩlž―Ÿ|$3³ηœΩs6{ž9gΞΨπjiϊΚ•NS‡9ΘΒ™/Φ³γ££„ΌΦ/»ƒΥlΔ ©Ος¨eώF/wόGχ’]{OΜΦ,N|²‰-υgΤέA¨-Ϋ1xvl[ΆρΗ7.τ£3ώΐh¨}ΐvΥ―m1N˜’ΤRΕ-²-‘?ο%φt3Ϊ†)vŸ#ΩΣΎZώΜlx`'Ie€MΑtŸ=€ζήUžA•νΫ©οΏκI‹ΫΫpxή6ώ\βC«Ϋ:Ρͺ«{υ¦qΥIω4rweίWGΙhMηΫ[ό΅~Λ)Μ(Dq3aΈΰƒΰέ3σ’3œ-hNΈkuΣB!„hšjjOίΤ²3ΙvυΑΗ¬“΄τr-―kΟ’_–“‘₯Aˆγ¦―λgH·ψΠy™^ͺbΔΕΥΊ+&UA5M₯/ξ/κι»X·7—=0’vA*ΰΝγ±λύ΅μΊ² ƒ|T“'‘xθ™dwΈ‹+;„`όΞ₯aξΚΰΰβ ½Έ¬_kV¬Ž'CoM@=Œ8™{v‘{―lμ…ϊ!2{χ’w;Q0ψ9ΠΜΪ΅IX{‡aD#}Gj―^˜μKB1›0™½Δ―χp&’ 1W–s‹EEt ―hΩήˆΖί―feΓώ C16}aφζYόՈpZEμJλΛƒ8ψK:yz&wW£‡ S7σJλW/$aρi|އ˜h=JeέΟI΄Ό?€θC^›χךΔΞ7r"]G·Z±ρ'Ώό€ ψ6§¬ξWυW€ͺφεθς{…Σγ@leX)\Όͺxmρ‘•΅oG—ί†PΪ?B‹ΓΗΩΥ–/Š Σδv„GΨω'Ύ–ε³ΖŸβΰΧϋˆΟ ¦ν½1τnγrώ³_ο2Ost­…Ϋƒ.ϊS£|ρ±%’~Z'Ό… υ !„B€#VοΧtt]GΟXΟηߜ&ζ©ηha<‚AUQάΣSς(πtΗΝ₯κcKΣR“H1…xΎw«‡ΣLέBbŠ>₯"8Ε“-š]4‚kKέΛ%²σDY64[!–Πp4ͺ?μ\Š™f·u#ψ‘ μV’ψV(f»σUπΫsq$ζ†ξ’Eβ.;ͺΏΘaαΆ=μΨμC—Χ£©Φr Š ―pχ’·Jq1`Π4κνω*ςΧ8πυ!βd‘Ÿ§‘ΫlΨ’|Dύκ‰'8v"”Ž3Š/ς(x oKΐγ9‘L+ͺΟ―RΖ:Ύ4’6šNΞοΩ­u¦Už¨ͺ »ώ‚TήΎ^~ňkPέό©+―};Όό–Άά½…„ΒsΏ›ΓθσIΒ.Έ(§ΰ&šNw©XίΨΑφ―=π*7{ΪgmΚ§ηυv'4£ΗcˆjnΊπ#Q‡ο?Άlbgο 1ͺ#1ΛωCοβŽ›g>y©:HΠ/„B8 θW}|ρΞίΟΊ/?eWΧ»ψ ³+f–νA¨£ηZ±™Ν5žR­WψK)ŠsΩtν4ΞϋšνWrν­ν ρ4£YΘ;›kXsσΙ/TPΘ'?O/ϋ;½JD .™ IDAT!«ˆΫ^HX«DsBθΨ‘šοdF»>NΔοΓ‰ ͺn‡[Auκ$+Ι_ΛδΠΜ͜ ιD·'Bπς1 οΩΝΚeυZΐ λW mΓΠ9ev ₯לВ[‘vο―s ;ft4OΥζ†G°G΅uTΦΎ^ώΊš^^AϋvόϋCθ:s$‹.)F\/HO§ΰH‡wΈ$ošίΓθ>Ek Ψ₯εS܈~j4~s`ΦrGnb"[Ÿν―«χ_Λ#αΓuμIŠ οK­π,χΟ“ŠΑ€Q kω !„B”¨σ0KρoM+οχωiMoωh > Xνγ°[KΖψ;xδΕd@΅Ψͺ=:¬„`Ω@όYŽ!E&΄€8΄Ψq‘’ ŽγΙ ™<”N~  “nΝ₯^ϋZ6±ν#χ²ώτgΫ?:Nπ3-ЦΫCυ$b°‡7$’•H~·6Vη‹z>ρŸξδlηξ θZ/ƒίυ&7”SΎ΄~²5Ν‚Šκ7o[aΡ(i (VΝN¨mύ:[mΫWmΤΕτrg·oΕ€KεNbσ9υώjvσ%ϊΊ~Œμο]`ΏΚgΒg`Gϊ hCζΖ#ψΰO΄μΚeSΓq­£χΜά΅lέHο»κSс6l…ŒυΥΆ„B!Ίz7vΰς‘ΡΈ4Γ'?•”ψόΓίQ‡ £ƒGr7\³sΙ-¨ζλΌ»1Έck~^ƁδL2“χσΗ―λΙλ8ˆnήη{Ϛ₯›a΅Ψ.œ`ςΑΗυ,χ$-;Σϋ—ρΓκ“εLΠ±Ω4Π΅‹F»φWD'{ιφ%FΠcRa7w'μΤ^v,Ο©Ζ#³άDβs0Ž[rκX:ykw²λ@ o DΝ΅`Ι±`ΙΧςh·Š‹Qΐ©Yπǜ λ2cWάάsHά”Fnz[°ύη΄‹ΞM υΒ=+‘λ2ΙΟΜ''!λi€~ω;?NήΒιBͺ‘.κ·.(xMˆaψυή5zkΣΎjI1βδGp™Ÿ WŒvHiί2ΰ=z#ίθK‡NψKSLxθ@ί7F2`΄wQΧφύΧ Hϊr›6{ε±ΞΉZ‹ή\ 6[™cσsΙΝvΕ=°œ„‹>Μ:EAΓ¨8!„BˆzQ£0άΊοξ{ζW’¬…δζλ<3q&ίQ)›<«†ΓμgΦακٜ‘˜Κˆΰγ•οoVωΉθ‰±μψ6›°‡ϊμB绚±bΦŽwD‹`ϋ’% œˆ¨=l?Ξ€NΥyT^qΏ%—¬±ιή“%›ΥΆ]ΈΌV‡/U΄+V΅Žƒ1S0νοŽ`σάΥόώ•ŠGΗtΎ΅Ω‹.@½Šύφ:„ς» ”GO‘w’iB!„B!ύΦ}Ÿpί3Ώ’d-$7_癉+0ωŽβωΉΣθa¬zυ((E’~βs~Σ߁¨|ΠŸ* ϊ]²Πζ톡D]ι‹b΅ 9†φΪρs· T΅ίN-ΠΫF SΠ£%ΰB!„BΡ°Υ(θ7vΊ›OΊ»Ζϋ/bNE;ψ'叹λθΣΆbVEa)hŸ§T†ϋ:ΔbKŒ­xΏw*ΪΪΏ*OC!„B!„h šΐ=ύB!„B!„(ύB!„B!D%AΏB!„BΡDΩuONv–C ρκ/9MίΡ^εJχΈϊήz*‰B!„BqžŒτ !„B!„M”ύB!„B!D%AΏB!„BΡDΩuOΏ¨‚Κ“c&1έ»θŠ-k ύΕvΝΙεB!„BqI«αH>§6ύ—O½‰kΖίΖ¬νΦRϋt2όΞG/>ΐδ›&2α¦;xπίσΨ”h­05Ε΅ σnzŒύΓΊ’œ+˜{ΎΏώ:nv΅ΏT―>ό8.†>υ=AOδ?ή£Σ‚ΩτΨp˜όzΞ^!„B!„(OυΓck,ΏΎτ3^ϋ/›ςΡΛμΦ3ΦπΑΏ?bρTCAμ―΄e₯r₯3ΧErδtf•Τ¬,²KŽpγͺώ“x’5ŒίxˆT»O9•™nάΪͺίeΖ’αޚ'Z‘—τ›Tƒ½i !„Έ€`41 %Aqΐ/D]1™κ~D4,ƒAκYT›΄›ΖΙh4–Τ[qΐ―λ:6›Ν™ƒ5ϊ5RΆύΔΧί?7ύήFά¦ŸωnϋI†υ%,5ž„\t I·Tς:–>VŠΖι+§a^όeŒjYœεIζl;Δ;=―gMwΈ€έΌΎk-Κ\€²elη靁ΌΪύ6υ‡τ³˜΄b3ϋυβ#LF¨Υ{lžΚΧΫΦΡ£ί0~Ήf$™Gω`χfB{zνWΓyςŠ«™μν†·QEώwc7²ςO3gεΥΙI!Δ% 8θWUυάΪ1ψ‹Ίd6›]α`ƒAκYT›΄›ΖΙh4b6›KFϊ5MCΣ4»ϋJΟgκ+n˜€ΙtρψτΚ•+ιΣ§Wέ•ΈνωΘ‘ι;ہ«οuv„B8Ω–-ΫJώέ³gΟ‹Fϋ‹­[·Žξ½»;£ˆ’‰ΨΉu'ƒ rv1„ƒνή½›]»:»’‘‘vΣ8;vŒ–-‹FΔKς[­VΆoίNLLΜE―±XІθG|?Η‘«χ !„’<ͺͺ^0Ρ•z½όΧ a/ƒAn4lκ ƒΤ³¨6i7Sρ@Pr/?Pς*_ο°’ !„’\Ł~…AΏ¨)))=r”ΒΒΒͺv³ΩLλΦ­ρπ―σ΄Uyδp‰δδd>μΤznΫΆ-ušnιΫƒDέ“vΣ8] υVz1?{λR‚~!„Β Κ.β'ύ;zδ(#†ΐΝΥΝ)ωηεη±βΟτ θ[ηiK{:οΘ‘#τοίWWW§δŸŸŸΟ¦M› ͺΣtUƒ\0t$i7SS―7]Χk΄°]AΏ‡§W hΈI94}!„’!)ϋEέ”;` Yaa!ͺ’’]υΑ`2™œ6u))((@Q§Φ³=«kW—A•)ڎ$ν¦qjκυVψ³· #ύB!„ΈdišvAͺΎσυ£)Φ³\,tηN^\šLžΝ^·>ΓΣ1v\νB!„cˆ0€Δ΅λΩ;Ή+=]ΟmΆe̓Z±|ω£υΌXV|ρ?nˆ%ΣB—Q·qΟuέπS=“}?}ΒWKvq2CΓ-€ ƒ'MεŽώ.ό]ήφdξώ‰Οζ―ζΐΙ$² AtΊβ¦έά_ττέ|ώgό±'‚:3κΆ€~ΌŽΆ3Ÿf„R³² ͺ΄Qσi :ͺΙ—‚=όφΣFΞvφb@χΛρ½$:; ŠΑ€ͺ.μ kgX3οOΜ#bΫ΄‚mρΠυΊ;šTώφΐdv­ϊ“ΝGΙΡ=nΥ‹˜a=iζZIZaωΔm^ΞͺΗ9›«cφiF‡A£‰iλνΈz6š1ΫN³{η1²Γ\hΡ·¦V—Tƒ£BŸπ<7Ζs¦°'>. §žδ€₯5]ZηΔΙ4‡ `ατ©D\#ϊα―@ξɍ¬XΏŸS)δ+ήDvΞθΡxθ•΅‹¨{ΏcŸΞAρ §λΠ+₯τΤο–Ι• θ9'XΏl;Of‚wέ/kKφŠƒ„έ2‘.ξΉnΞq\»©@abşs ώ7KΏ[ρδ|L­ι7b$=C]©·bŠκΜ Ώ’d;ίφ&MΜ##nΏΜ}'ς_β;:ΚhΏBαdzT†zΏΑ†έyτμ[ԝ±XΟFσë<Δ²β _ΟbΛ'3ωYŸΔ s‡šΉžχ_˜Ε~―ρΟΛƒΠύΜΗK`όΛ_ryˆ…ΣvpΪ7νΠ7εnWPππ‰’Χ OqoηHάNΒΏŸ™Λ/½ήαΆΆόυỬPnζ•/―"”Α-3I<“‡–²5{‚Ο8’]­¨½Έ}ςex+΅,‹οGͺ(k_½0›—ΏΘσγ»ΰQ³N•ƒκΨ±4’7Λ{οΝfφ{³™ύήϋόz ΰάΎB -‡1²c0ξfΖ’7εΒν†άCμŽu§ηπ~Dy»`φ §ηπ~ΖνΰοT½β΄4Π³«+f7o‚[v‘M οQ.H`γ’•€vΌ–«»‡γηα`fž·1”Θf…œJHE'ΈΙ„FGαΥ‚Π³±Δ偞•ΐ©œ’ŠΖ!θΡ¦ΎξfC’‘9ΎyΪς±„ΡLM¨UY1"€gνeή«‘0ϊežHe,/<€‘]ΰΌΗκ•‚χρ\ί; δB‡Α₯xu!a(έzαv=#t%žή:EU £»δ–NJΊ~ε§₯†χax»…όώΥ\φ΄λNοήέhεg¦*5ω+8Ν–₯λΘμ2žqν]Θ³tf܈sυ\ύΤκœcWaw!<2ε± δΈqβŒ?ΡΓάQά£ˆφ_Γ±Έ|Zλρ€ψEα™±›X·υρ)ΩXmX-6’:ΏS΅ ?Ÿ’ϊΡU#FlhεΎΑ«g¦‘‘Xž4πρΗWM/z₯΄›υΉzΏ}Ÿs―’χZΓ—@_+3sQZI½sξ=ύε±μgΙ' κΣ‰ζAžΨ’ΆσΓΧk1υšŽ vIW!„βR’£ωχcXτw¬ίšNw·uμŠΞνΒ΍’€K?¦4ƒΎ% ύ+EΣCUlξt»η=ΎΏ•ίΎϋ’žXJ—i/1}@PΉΫ§Fζν7—βsγƒ<χpk]ΣωγεΗΨ[œ—’cΣ(™‡¨£PΟ©qYόλτήO=k/ίόηcNz™ηFŸgAΗBFV΅’iδ .nxxœŸέ λ:EGE-wϊpΫKΏύΊ(œ―°ς^γIλα·q_ΟXvm^Ηy;i>κflλY·χψœfΛ²υdwΟΈφfr`=;v±4οπ<7%pΚΜ)χζτρπ‘y΄'[OΖ“`HΔ%Ό7~€ž²•_݁[ΏΛΉzd0ž¦\φό2Ÿ„’τ*kφ–ΙŽcKW³’”jnŠ9e‘½J?η/Ό§λPT{RoŜ2½ίΊοξ5ώυ+‰gσΜΔ«ΉvΚ{μ°Š λΙί™ύΤ=άrύόγ_σˆλ0•OλO]?ΙC!„5€ωΠ7¦ Χ­`ωšΏiΣΟ2Γj³HΒ΄xβΞ(]Œη~ ŒΕiωΩ©δzv`μŒwxοŽ Ά¬ΨNΊ^ώφ3±G84ŠΫ―λI„ΏfsΩΩE358ŒPk'Μ/„–tš$­Άe©όmΠ«ωŸ-7‡ ρ―πμhςσ,hΥNαΒ-½¨c]όS]ͺ_ ώz2‰©ηλ[ΟN"1Ο—@ΏΚΊ§:šΝ†κݜ^WάΒδΑžΩs”ά*‹[ΝzΆXπι9ž±Lδ4Πzvτˆ­I„!‘ύϋN‘FE¨(6ΖtϊŸ±Œ&%pΦ«3CϊΆ!ΤΟOwkAύ΅oΕΫo-…³ησΤ3ΣΙ,ωUΪM±ϊι·οs‘žš~ώlm)$§ρρυ@‘z+α”‘~c§»ωτ§»+ΨۚqO½ΝΈZJ!„Έ”9ͺΣp>e}bθτΙ;ό`ΐ£3\±‘•䬣ƒOΖόŽ·>ώœ°{ΖΡ92γpΔ֞˺ Ψΐ²S>thŽŸšΒφΏΟβŒΛΙυ,)g»_p0^©»Y³c 1YXϊ=«St’Π! /Γ»|Ν—σ~£Ν—ZxŒε?¬!Ek΅(‹»Rρ»©£WϋxC³ΛΈ6ΚJ^΅NjΙ‘DΗΡΡm…”Œ)ζκΔξνθΥ~#‹ΪHΨΘnȚώ IDAT+iμk )ƒγ§PΡ|Z-ω »ά‰ ΐCΝβψιLž^T9ᷚo±κέ†nVrꨞA18x4ΝJdhKO˜h7&δ|]· *!["V4νΖθε…kNΌ#~ΦDvm<@ΆH»)Ναν¦4;?η){Χ³#b(ν}­œήΊŽC†Ά\iz+₯ή/„Bˆ†NsλΙ°ž.όmF7Χr`έ•>ΎΖΤΟήγ»WbV6x„Ά#fJη’ύjψ%ίΕ§Shτ!ͺηΥόσž^Έ$-.w»‡G;ϋ&s^˜)Αt 3Ζ}ΘϚ71?C[³˜9γΏθΉκζ«θxpνΚBa₯ΈjR[σΘΉδ&ΦIήτ-οm*ώ]Α½ΛDξQ[™i1όz†―^ʊο6“©Ήάͺ7GvΑ»Λ yœά΄’5©9XUw›wglL+LUtΥ›b=;~A6Β#ΡNΊ^*d04£E€Κή΄HΒΟ=vΝџ+Ί-fΕϟ³Qρ&Ίχ\ή=‹.αy^t=ŽŒί—³πσ5ΰE·~] K8}nΏ΄›bυΉŸ]ŸsC$C†E“Έκ;֜-ΐ%° —]C΄lRo%j»Ÿσ™ϊЦ`2]άV\Ι°˜a΅ΚD!„ΈΤ­ZΉͺδίύϊυΓh4b0PUυ‚i{+W€K.*…Š›O0nI€ζέ<οζŒ7ι$gζ£ͺ«?Α…œMΟΖ  ˜pχπΒΓŌQΝf!/'Μ=πσςΐΕh@Ρ5,…ΉdegQ V°]3ΰκι‹·« …Ή™δͺήΈ[SŠΚ£Ίΰε卻ΙZ!9±?πΔ;ρώ£ ςTjV–JV`Z»f-ƒ vΠ{mŸ΅λΦ2xHέ–aώ=ΔΔΔΤiš₯©=κ[³b±ΑhΝR΄6C ₯ΒνͺΑ€ͺ*(θθš†ΝV<Ϋ€‚Χ(*ƒŠzξ3£k6ΝFe}ό•+W₯›£>SφΩ³«ξλ$77wwχ:M³,E5b4θΨ,Ά &_¨Ε†ΥzΎΎ.¨K› M1 κV¬ZΕυρvƒIE·ZΡτϋ«:P”’Ώ©ŠΊŽ-m ί~K—L “»΄›bm7z:[ϋ'ΊάΕΔΞΕyTυ97 Ϋ4”βϊΡ5l6ΫΉ:•z+VXXˆΩ\4ΗAΧu4­θ}²Z­lΪ΄©άό,–’eτG|?GFϊ…BˆK‡F^ΖςJžYϊwΠςS9“_jƒn!7;•άμr’³ζ––SN6lΗF~v ω€•LIvZYΙ―Tp"–Σf?|έ”š—₯ ΅yžσ₯J³YΠ*x$“Νj)g«^αvΝf­ ­ ^£kΨ¬Z΅ŸΥλΉ>dΣ5+–r.œi6K™;0Κ«KλΉc*‹·kΨJ2,½Ώͺc) τ­Φ’ΆaIM&έ聻 i7₯8¦έθθΊ‚-=–γiξΈ^°―ςΟωΉ!φςκGκ­DΓ[½_!„΅Στϊ+vΘgίοΏ’Φ—NΝύ1¦οεΗ―Χ@ί'i«β°χDΧtη¬fM©Žι%Yίυ«AΤssΦω4Lβvn!ΓΏ ‘žrN²qΝh1–°ZD;nμ”Ώ…s—sάb$¨ϋϊ4«ΏΕΛ#υv1 ϊ…BΡqΧNςϋGKψ4%Ν%€VξδΕ»{ΰ‚γž“lΣl Ξy¦°­’αrQηšb=Χva―¦EΑhKbΗν,Ο.@7yάj0γcZγR‹ΏnμδΪ…kξmƒUuΓέD©ιϋΞΡλ­gΪA‚~!„’i|«ΉΧ#m―{…O'›1TΠmX rΘΜΞ¦ΠQ? iZ½>Βͺlήp©Φwύjυ\Χ$θ/ΝHXŸ‰άΡO₯h@΄μ½γ5#νΖ^:ͺΡ3Φp-³IΦ›Œτ !„’ρΣ)ΜM%Ήͺ0Χ‘””RΣπφρΏLKΙΘΘ %%Ε)y_JΞ=KPjSλωμΩ³užŠs§P74ΊfΓZ‡£¬nͺ«a\Όlͺυ¦Τr¨_‚~!„B\’’££YΆbωNΙίΥΝ•]»:%οKI«V­ΨΈa#ωωωUμnnnτμΩΣ)y‹š“vΣ8I½•O‚~!„B\’ΪwhOXxšΝχTB5¨x{;g4κR©S'"""°Ωœ3οΨ`0ΰγγSηιΚB~Ž%ν¦qjͺυV[τ !„β’d6› tv1„ƒΉΈΈμμbΤΉ¦Ό9›΄›ΖIκ­|τ !„ MΓΈ5RѐΙ-ύ’&€έ4N²zΏBΡ΄ΘjξBˆ*iH'ͺOΪMγ€S«ΐ_ͺ\!„¨gΊWϊ»BTΕY$›΄›Ζ©xzMϋ2/„B8λ%?Š’”|q»ΈΈP˜_ˆΩΥμδŠΖ¨0ΏΉ$„MTιώƒ½$θB!κY||<ƒ‘δΚ}ιz|||ˆ=‹ΥjuVρD#f4ρχχ'66ΦΩEBαΕΑΎλv?₯@‚~!„’ž΅mΧΦΩEB!DPε1rS‡B!„BΡDIΠ/„B!„B4Qτ !„B!„M”άΣ/„Bˆš±dξέπνΙ’…„Τπywξ=t”ή…BΡ`ΘHΏBα$zϊbžΊr$γž^BΚΉ'οθΙ yδκ§Xœn£x΄Sσ™qϋμ­ο m˜<η'~^ψ3 žŒK=g/„BˆͺIΠ/„B8“k žG±4N«qZkώςZP1»{ΰι鉧« ο !„ ‘|C !„Ξ€΅fθ3,]ό7ΧέΧΉΜ³NΦήρώgΏ±ωΰi²U’ϋNdϊŒθβ­`;π5Ώψ?§dS¨ιΜ½σeΟ²πΉaUŽΌ[ΦΌΒνΛΌι‘ψ«sΊ2εΦ0V}Ί„ˆIΌϊ·ΠNYΝKζ:σ3ξioΐΊνm&½σΔ·Π[zB!Dƒ'_ΧB!„3ιV"†ζΐ+‹Ψ<Ή3/Ψ©ΰζJϋqpΣS‘xYN²tΞ+ΌφU{Ύ˜ή S›xνΣρl|‹)Ÿϋςμ{wΑŠΙΥΞ©φ:iΫτϊ«Lώόa>ό¬?Ύφ4ϋ_ώ˜•‡o€][Gœp©ά3–ςβ?ζ°έRf‡©'Ση>Ο>Šc „B\$θB!œͺ[ΰpΖΆ]ΐ’Υ)το}α^cΤ`‰*ώ͏ρcΊρί‡IΡ»jpΑέΓ“«E1αζα‰g5ΏΩ ὑωνρπΖΠV°†f°+Νώ5jJρŒχΊRP6+Εo ψ…BˆΊ AΏBαdΊβΗΰ±}ωόΛ₯ΔυpΏ`Ÿυτzζ͝Ο_ϋβIΛ³’Yσ)hΡ«ΤA\¬xϋβ₯*ΨLf<}}0aΐ`Π°Zλa‘Ε Ώ7Ηη#„B\Β$θB!ΧξcώΡX|h†βZ,ίΏόώl6…©Ου!Ο}Η‡<°ΈξςUŒ†s£ΩTυ ¬¬uΤ}ιύB!„γIΠ/„B4Ζ6\u₯¬ΨK³βm9‡ΩߚkŸŸHΠI.Μ€°μkΕj‘ξŸΨgΐ¨PP2^'9.ž\=ΊNR—ιύB!„γΙ#ϋ„BˆA!tΔΪ½‘ύΆs›\t?ΕφυHJK&vγ7Ό»ΰ e'ήΒ" ΝΨΚΥ±€d€r:>™ά΄žΑκ™S˜2s5ΥΉUίI‹ˆ 6.ϊ“£)ι$XΜg‹Ž”sW^t;€nC«NϊŠ~!‘„†–ω ρΓMb~!„’NHΠ/„B4ŠΟ Ζς¦δvzS&MJΞ‚'˜|ΛέΌ°0—+Π2ίήjσ ζo«³ %„Bˆ$θB!œ.‡ _}ΐ&ŸλψΟσωο§―3mHh©/i€f„…ϊβ’8±˜eΪ0yΞOόΌπg<9—Ϊ€₯'σΗs·π菧hHΧ5νΤ|fάώ{Λ½ ’‘°πqnyv ‰z-2±žfυ‡3εϊGXpͺz Ω’ή"ζ…ΗYo«Eώ΅ΰΘό΅ΈωΜΈώ6{/ι­ΚۏβR AΏBαlzgSmDχJ‡?ό‚£υ)ύm¦Γ€Χ™ύΔHBRЏŠΩέOOO<]΅J)oΫ<Ύ:ޟΙcΒ₯sR†–t†Δ ―„¨„]y+N~ΙΧ›sk˜ƒNΖ_ςΦ_L|ω_Œ «^#³₯ηdm.8Τ’#σW#ε…ά„ΟΪ·ωduN<Ν«Όύ!.ς½*„B8‰žτ;/ίq―½“χε³ύέ9r#FΟΰgtΠ3YϊΜUŒΌΌhϊό¨©ί^0½_ΟΪΒΫ·Mΰ©EgΞ#:g=ΕΔ)o³%«κπΔ²ζnynoά;‘«o}‘ύώ \7†‰}ΓΑBΐ²š—ΖMαγη‡P­Ϋήζ†ήbk]ŽκYl\ΌטQt)=]ΐΊ•·n~„ο6ώΖΜnbά•W1ρž—YxΘΎΰΆΚσ³»|όυκάπς ͺυUY~¬½ xύ‘Ϋ™8f£Ζέΐ½/ΟgOfQ&Ά_σΰΝΧ2ξΙ_INXΐŒΡEνΰΚ—VQP:—ΞŒŽρdν’΅€Χ(*ΥHŽ;…­γpF΅ΐ΅tΜoω›―Ύ»œŽϋβ9#”V―^ΓŽdήρ3μιP‚fL|ς,bpΑeͺ >Ÿ, ΐϊχ>α†ΛT\Ί‰yΗη2ωεPΌ eψ²}Ψ¬?2ιαΞ<}ό|c*ά?ζOMeyΙ¦lφmzŒkώMΰƒ^ό³“VοΖbOώU±§}).ψ΅ΙΠ6ΞΦ,θoθνΗQεB4΅»,/„BˆS‚Fπ؜ΑΨ΄3όςτ ΆϋGω‘(\έPΌΉβ•E ΟΝ ξ·—˜ΎͺΜλ½zsΧ΄Aάζϋ,λϋ"—³ŒχΏ<ΕΰΗEo/{FkuΆ&θυW™όωΓ|ψY}νiφΏό1+ίH»ΆŽ8λrξeσ.zMh‰‘μ>Ϋ!ζκΟΏΓ]!Ωlόθ9fΟώ•^οήHd•CUœ_'{»A*FW\m&ͺ=Ρ’ς+Έy‡~ά#άτT$^–“,σ ―}՞/¦wΓΤζ^ϋt<ίbΚηΎ<ϋޝt0€br-s+…θ>½ρϊe {ς―`ˆ[u Ίƒͺ” IΪςiΟ§|Ν@χbo&ΗίcΤ#όςμ4ςχL₯σ―A|σδ‹τ1€bπΐ ΐ8Šχ_9Ι?Ο|Ι½oΎΟΎKgΒψΏΨœF’‘-VU*φ>Κ5σwpΥM ˜Υ>λΩ lΣB1jUωΫΓφ₯ ¨ Ί¦Χp€Ώ‘·Ÿš•_ΟXΚ‹˜ΓvK™ΓM=™>χyπiPΣ’„Έ€IΠ/„B8‹bΒΝΓΊfƒ‚Α₯hͺό…]e£»~^ζr―Ύw3½ούΌύαdιίΫονewpaο͐­Θoˆ‡ί0†Άκ€54ƒ]υ8€§%α¨₯%7Ά(§[’[‰u'Ww E.;€/Ÿ;ΚIvύut~Šƒύ’AφΏΒξς£sMTρΑ~ŒӍ.8LŠήPƒ ξ.˜\(Š 7O<+θΉ[΄‘₯u+Gl iuΡ₯{ Š’”m5:V›MqΕΟ;„ … n­ΞοVέπvsΓΕΕ„’˜ρpσΕ·LΦsΡa- ‘δ.?ς\ηv˜€H€*g‹dπΗϊŸ οχΌή·wQ ο=’Ψ‘Υ§m_ϋR¨iΘίΪOMΚ―xaΖ{])(ϋΆ(.ψxKΐ/DC"AΏBј)ήτ»{*=ο{ΥQΌόA_μδ/yΉ/^ͺ‚ΝdΖΣΧ  «΅ώnΦΞ&’κL`yϊ;‘QΑ%1\΄4μ]³ΝιηWEω­§Χ3oξ|ώΪOZž͚OA‹6Xu¨Φ°°9ˆ`ο4’ΟκΠͺκΓKΣσN°}o*a=ΒΛΜ΄PiΦη%žέs ^ZØ‘OπxΜ΅tv«Αέ‘J[uΔTΧhρ=k₯CηNΈV?G;ΛeOϋRiьδέ[9‘Ϋ’–ξυΠΦWϋ©QΩάπ ©Α΄!D½“ _!„hδτœT UTHΝΌν­b4œλ (Νv„dV Φ:ξ>θš}*x2S-²«φωΥΉJΚ―ΕςύΛαΟfS˜ϊ\"ύ\Πw|Θ‹kbΖl²n©ήh΄ί;—€žχσκ -.ZμIqνΓCSw1αΰ—ΌΉδ †ω”η§ύΘƒΥ Γ=p·ηΡΆB¬%—ŠΖΦ‡F―φ΄/­n|‚)‡ώΕΤλ7rΟ§o1‘Y}ώυΤ~j@¦χ ΡxHΠ/„B4fZ‹f}AβπηyžOxkφzΎr‘uί6`T ((™Ώ«“O]‰—PLfL–B /΅EΒr³/Ύ5Χ>?‘ώ!  “\˜ΙEk * ŠΥRωlx½€ό3.Υ|¦£:š§fϊπΝ›πήβ>ΜΌ6¬œۍ¨vχρnΫ‰τϊ°―nάΞύΧ ™ά²εΘO");€ jvνŒ^4λ8‚q|9όwl™ΐΠΖΑ]1π~β³SHLάΘΆ+!ΎΑt Am‰ΞYΖΌνϋ8“HlRόο“΅0—BlX /<7΅ƒΟ²xέٝ‘LάρΟy~νσνKρgtίΡδlx’§·ν .+‘ kψωΠΡ ¦ίW•νY9Ίη ~ƒfxΗP<«½n@#h?5)Ώβ†_H(‘‘e~Bόp“˜_ˆE‚~!„’‘²ξβΓΫΗ1zτXn{'GΏeϊ5£}υTΎ>bC;½ˆY_Δ3hΪτπPP<{qηΤœ˜;‹%gκ ΊP#7νvZϋι·LbΪΫΫiwϋΝ΄/ž'hέΛάϋoΰΪ1£χκjςπИ+ΉζΖG˜Μή»ξΑ֚–ΖX―λ±ΘΊ’aΝΟ#ΏΠrQ@U+¦Lš>”œO0ω–»yaa.Wάy‘ezgjσ pn,ZmΛέΧ?O·ψ§ςL[}»’ήγ§O©UσƒzΞαγ:±γη+ιόt[zΟΊχŽ½ *ΚΏ.iΊŽͺΦ΄ΫάπۏSΚ/„¨7JΟgκ+n˜€Ιtρ₯Λ•+W2,fX=K!„hZV­\Uςoω^-CΟ`ΩσS˜ίb&έΡζβΗφ‰*Ψ88χnώ™p_>3¬Z 9ΏώΘηχςπ©)όψ̐κ-ΆwI°°ϊ• |Σ|LΎxέ!„p¦U+WsΡv‹₯θβϋˆοηΘί-!„B8™βΓ ±ƒΙYω;{κ†,¬*`θ˜ώ5ψTό‚όяνbO†Œε–eKΫɎ£δηπρ…Β$θB!„ΣΉχΉΫ£·πέο 2…ΈZ4N-ωŽ-­¦0©GMl§ΰ?όv&7Ϋΐ3“fΑιKmEŊiρσyθΦ—Ψήβ.ξŒρ• _Ρ(ΙκύB!„p>%˜Q/}Ε(g—£ΡQ ?“―ΗΧ.Ε½#7ώ{²³±Κ*l%Τfγxυϋ‰xz%ΰB4Zτ !„B@Αδι%χτ—fpΗΛΓΩ…BˆΪ‘ιύB!„B!D%AΏB!„BΡDIΠ/„B!„B4Qτ !„’f¬Λ™ϊTs¦ν/tvIͺΓςω‰x{ͺσh€Fs~B!DΕ$θB!.qΆ€·ˆyαqΦۜ]G1ΰνΣ‚VΈ—³{Σ?!„—2Y½_!„ΈΔَsRwqv1Θ•Ύ£ρW{›ώω !„Έ”ΙHΏBΡHμ˜LΫgpο«?{³Χ‹‘Oϊρζkl΅θ€Ε?ήξBΔCžx>MΏOίdmŽ€υψΏφt(A³?&>y1Έΰ2ΥŸOW’K6ϋ6=Ζ5Ž&πA/ώُI«wc)ή­ΡSππ[m šαOτλ`nB}'`έΚ[7?Βwcζ71ξΚ«˜xΟΛ,]ξ\΄†ΐυΏ<{€Γ·Mΐ'ΰ>~ϋΏDίLδδ”kp@'mο£\35Ν/_ΐΆW±ωξ'Ή6,Cqτt~^Ύ€Π1KΨϋόbυ^Ζcί}Κ±²‘xEl‡˜ιNΪήχ_}=‹»šοηγΩΏWΥ½χŠΡAœ:{9μά2“™Ϋφ‡•Ιqψ·ΒW `ςύ©dΎΟφρ—a.“DΥη_η'„B8™LοB!1Cπε\Ϋ’ΉΝΓρφΊŽ‰ύ( LaMfQΤl ½†ϋB‹fΪΰ‘ΌΉb'§υˈVέπvsΓΕΕ„’˜ρpσΕΧP:υŒoοΞγ’ͺώ?ŽΏοΜ°²‰(δΉ€ζŠ»εΎ•Ω/Ν4K­\Ϋμ›νVZY¦©εnξišZje fΉ₯f™š») *ξ ΜΜύύαš(‹’Θψz><0˝Ϲg†9ο9ηήΡχ+ηKΥζθύjUΟaίTμ?€ͺHυwυB©b²ͺ˜zΦo­'lΠ‡tWVF¦]MΊ©uΉP’ξkYSS^ί₯})"Γ© «’‚Šθΰ½J΅ŸΠδ…oλsk’jU€C‰q*zWΤω&,rχ,¨`oO₯;œ?Σφη@ϋΘeΌ]‡YΌƒ`²Ϋ­ΤΉV«χΙrΔ¦¨κΑ9΄œρΫ@.cy?y˜a΅Ινάor³]±€έΉYOμͺΩj«!έΠo׊Ν•?³°‘©sŸ dt7Ή[³ΌΑ«°Ιν:§ lΕUδΨ­έ±RΗ£Σ9 ;7jΟΡ"*Q0§ζ5n΄}δ.B?κμZPIΟ΄λ­ζ‘eT,0B^iΙ:{ερθ†E†=υΙω.^^HEύ mΫ–ώΊΫ€5 ˜Š€μӏ»v©rρκͺqW9mΪρ½bS#Uά?έ:ύk»Vϋp„~\•{!ςά©ŸώZ§Ψγ΄ιοχΥη§uι–ΞΫ‚J*ςΤšώΗf<™ =‰ϋuΒ”d¨i΅¦:΅κ% \ΏA±'΄7ξW-άΎ+ Λοo[€ŠωnъΨ(ՈτU@duνY WΤeύ¦σ΄Ž§€Θι<₯γ©φtgϋΏfϋp„~\•­Ύ^κπ ŽΤ\e_«ͺ[vB[?’WΌϋ[C{idΫ*ϊ{~]Ή΄κLŸ­MI2Ty”ζ΅*§ ›ιξ%Uυ“§4zχ!evrύ[ˆTρ€DΕYͺ¨Z‹¬Α5TΕ«„€ηΪθXo”oŸ@•ύςήΎκ<Ÿ_ωŸ«­Α±φ‹›ΉvϋΘϋŒ“‡š?uθ-IrsKΏ.&&FυΤΏΕeΰZ–Ε,»ψ;ο« ',‹Y¦ €»<-νܚΌFsF1Σ€«"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?yžS{gτVο{εΜνRΐmΕ–Ϋ€\”²GߎώXS—mΧQkΚ4θ’ώO5Vχά.μΌΫ½>nsΜτpΗJΥζ)ƒ4vΟέκ;rš>―½ς6LοΜΪ!{Žlί”iήΞυΰϊύά©μ[τΣ²T5~ςqΥ,$ΏΤ8ν;mjK΅%'R΅3Nσ ΠY‚G" IDATθοΆλψυwp³λΰΐς~ξPζαέΪsͺΈZ–p“μ{τΥΈ…tιͺΘYk΄σ°© !FΖχ?ΆTo=1J€]q…[eυžψ†ξχ W‹νυΥδΤλλ»Τ¦{7΅Ή'Hn·¨>@θΰŽε»ΫSJ=¦δ“ή ͟ωΌ@ζΛϋ Iέ£y3g+&‘ˆšt©)u’δ“…Π~£υB?w,# ΈŠω~ͺωΏVΥsckΙϐμ»7kGΎ»Τ" σTžις~3YΏ~όΌΖμ,f_ΡΨΪ‘ςΞΖ ύΦύάΉlet_γH-ω-L~gθπήνϊjΜw²ΤWe³2B0ςΙ?$ί΅―7έΩjΖ/,―λΙθ7Z τp粩δ#―ͺίΡaϊ΄O'2ύUͺ~O½ΦΉL–Ο°Ÿ!Γ[%ΌoίϊΈϊΈ“yΥύύGθώώΉ]Θ5άξυp›γ,8Έ(B?.ŠΠ€‹β˜~ς<‹Šv₯QΉ]Έν0Σ€‹"τΰ’ύΈ(B?yžS{gτVο{εΜνRsΫ4±ΫύjΤΈ‘5n€ϋΊŒΣ{nΘk8‘w2ϋA­œ:ZŸ·A{OΚ_°°JέίC{τε7r»Έ;œ΅„:š―‡¦V UηιΉ] /"τpΗ2upΡς£―Ί½:VuΓ-:v`›ώ9$οΫ"π›2MCFΧβTμύυΎγy}©θ-\&i‘»—·ά%₯y2d\ήAΈcΩ΅{ΫnyT}U­*„Λ&)00Lweωξλ4¬σt?SW{¦ΝΠͺύ,ί\OΏπ„jYoΌnrsThhhΆŽΜφγΫΣdΟΡαΩυχt£ϋp; τ€σ<QΎ€ LΣΡ4em”`žΤώΨΓ2«†ΘδŒί§Ξ• Ι|@¦ΛϋΝdύϊρσ³³Έšu|EckGή&ί*S¬²YR”rq˜JŠέ―ΣfdΞ=Δ τΐ5ϊΈS™ ϊ}Ρ:Ω£Κ(²P€^ϋ: λψ‘l§«o%ζn;τΈΌe1ΛΤ Aƒt—§₯ϋ*ήFsFέΊqΈ΅ύΈ(B?.ŠΌΘσ,*ΪiTΟ]>3ΆͺznΞ·ϊQ‘Uτ@Μτΰ²ύΈ(B?.ŠΠ.JέήOΕ^~F?Ϊs»ύΈ(B?.ŠΠ@^ζˆΥ’EνuοΛεΧ?BUΖΎ«Ÿ;Ο]gQΟ Ό_C―SΑΎTψέGυΩΎοžvx‘^Y^αύόςf; έsRΦ\j Θy„~ς¬ΣZ³¨žό»ϊχ\§m―/P_™κT§ΘH…TQη6½TvΧl-9v~Ά_i*Uσ-υΈ+RΑ*ͺSt &lΤV§δ<²X_ν‹RΟ_TΓΰ0‰|RoGWΘΥ&€œeΛνΐυ±Ϊ¬­gvkρΘš`\ΌT§Σ"Tγ˜Sς‘€ό*Zψβ§ό†»—ς9e—δHώW±Φ²ͺ|a8`U‘Beδ{‹ΫnB?y™΅†φŸ ήΖ₯Λ 7ωϊ^x‹·ΙύZι† Γ*λew•ΥM69―qΧϊΘ£leUΚ6Yž RΡ"ήιo`ΟψώV»TΔώ…Άq¨e°U’S‡wθ¨Šέ”zΐ­Η1ύδUωšκιZΎš=ηi}ΊυŏΣ޽K4φ§Ϊ•…ΙzK@ ΅ΪOηΥͺΓ‰ΪΏoš^ύe­8ƒΠ@žε­θ6ίhF5‡fN―――–S½ρƒτύI›<Μο-#Jέ;OΦΓ©£ΥnP έϋω7*Σ€Ÿ*3:ΐe°Ό€ΌΜ‘&Νg¨Iσ«\gk¬OίΫϋί‹"kΣΗ—ύΠBƒϋ΄ΠΰΛnσb΅›R)Θ|–€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠnkΞ³Υ―λgΪdΟνJnΪΈ™ύΰΆζL<¨ηΝΨ²)ΣΌΫΝΪΈ™lΉ]ΈΝ™Ητːνθ‘±―6’Ώ‘ΕϋΩΧiXη™ λΧPϋgLΧςΗεQS_x^mKzI2ubΣ<}:i‘~ί―“?EV{P½ϋuPy_CŽ­Στμ[σ΄γπI₯:Mυk:W’δ^χ5-x½ΎίP•nυœ†MώB³ΖΌ’§η꽩•&ΙZ’ƒή›0]3_ͺ+οΠ6zoήB-\°Ps_ŠΞ™ΐh W‹νπΗGκΥϋ}Νݐ€4Ϊ—wΪΘB?Ș‘_΅ŸŸ’©κͺ@vSΏiWD“nj].Tώ‹λΎ–5ε»o—φ9Ξ]m+­6 *¨h°ΏΒ+ͺ]‹Š:΅s‡›’¬ςςφ‘§M†α¦|ή>ςρρ‘·GΞ-Tτ«¦G~ͺ‘}+(aΖ‹zϊυΟυkμieyU<νΛΥφ2Η]pσ^Š(|q…€αα!g²ΞgFΩγWjϊΔΩϊeσ~%Ÿ±Λi?«”¨²›Rφ—\EΪ ½ίρ}­H=·{m½4σ%Υv»όFV(έT]zYuζO4||˜JΏΥDAYy|ΪwsΫΈa„~pΩδv­Ρ†sζΌ=D?‡uΡ3―ί«™Ζ¨Ο’œ|ψͺκ9jœΊ\˜Ϊ6<εŸz:Ί=FσfΞVLB5ι2RSκDΙ'ˁ•φέΤφn‘δŽS;΄yq΅}γAΥ1$™JJ=Τ+og2μiΊo|3D^ec΄&-·‹ΈB?ΉΝy@³ϋ4Q“ώsoζv19Οy`ΆϊuύL›μ9»]σθύ―Yc΅ψ­Ÿίof=ΧϊZr4λ;ςfΥ—)[¨^YΡ_ ‰Ο*vRIε»‘m™IϊώυNzώ«rζT}YβTά‚Υι΅o•πŸ]nΧΎoίU·vΝΥΊΛ@ΝΪ|J¦L%-¨.¬ΠΙ|žηZ@Aθ —™‰k΄ϊ€|φš$ΧKύΞΔƒJΈYIΤ³ |v-ΦΨλ€›Z_† yζχPžςσΆήΠ–Ξ¬Ÿ©ΦPηα·xpgQ‘fͺζΎ)šφϋιKΫ7κ«iύΞd|ΘͺωΣbt$u›.<ͺΖνkΘΗΘΉ r― o°εvάΩLZ»J{JΆΥŽyZ΅φˆΪ΄”!IφίυαΓυν1S†G] ψ¨ͺ~pΌ~; •κϊ±>~8JΖ‘΅ϊό£ΡϊϊΟ)ψ^=ΤΉ„ΦŽOR§iΟ©ͺΉ\ƒ˜¨Π‘“Τ£τΉPi_±:ΎojΐΜηTqΥ;κϊƒ―ξIψEΛOUP—G iΩ„Š+άQƒ?θ€Rξ’μ‰Z=}”&}»A±'=^΅žιχ¨*’}†už©°~ ΅Ζt-ίy\ξ5Υω…ηΥΆ€—[§ιΩ·ζiΗα“JušκΧt$Ι½ξkZπz}yHRΚΏϊώ³O4cωV%€ΈΛΏpY΅μυͺ­ΰ•΅έη,zujι’-jΤέW lLΨ4OŸNZ€ί·Ελ€ΕO‘ΥTο~TήΧΘZ}H™ΏPε§{ͺΑή­šΡ“EΡΈ‘ί(Φ)YKtΠ{¦kζKuεΪFοΝ[¨… jξKΡη™©δŸΗjΤίEΤγγiš=m΄ήx¬‘Κ†fc‘»iWα†Mε·|±~?u商ςω†ͺt«η4lςš5ζ58=WοMέ¨4e₯ΎΜχ_ *<’ƒέ₯—ή8ͺn‹Z«mΒίϊrΓ-œzNέ€ίςV•{οRΊυτOζ2{~\`Uδ½U•ΣZύ}φόEΆςjΩVšΥ­₯ΪΩ’ΚΝ#΄zώ^E?TWώ—ηΩ λ»ωύ—ρσΟΤ‰5£5pδ_ ιπΆΖϘ©±otRΘ€sϋΩLΦ/Γ_Σ΄ΔjznΤ4MΡGχMΠ+#WθβΡ%φνϊrζΥ0F3& Φƒ^1zοƒE:hJYz}@ τ‹Μγλ΅ςŸBΊ·J¨ U©ͺΠ-+΅ώΔ₯ΏΕ£€B£ ΙΧ<"χ=Υ₯z‡—U©P›ΜC+υγ_!jέύAU PPρFκρpΥ,žs¬αUU§L1•+UPήκ«^±2*zL‡“MιτΝϋΦf}{ιΎ2‘ .₯&O΄S䦟΅ϊΠ…ƒθνŠhM­Λ…ΚΏ`qέΧ²¦|χν>‡$«‡ΌΌ}δγi“aΈ)Ÿ·|||δνqi>ήa·Λ4<”? @ΒU¦v#UΞΞ,gͺͺeΙ ZΌόpΊγΩmE’Υ¦A φW@xE΅kQQ§vξ8w€,Τ—ιώ+₯ΆΥCT³ͺ―|£ΛθΑ αͺuFρ‰·.΅9γvjWΪ]*u•Ί3κŸ,Θπωq[T έeί£]q6쩏 ΣsΏΠμ/'«·χ/ϊΙ§­Ϊ–qΛV}7»2~ώοί.—?₯§—Rh@ ΒΛΦUƒ ώ2$™‡–λ›Υz WGU)¨ΐˆ{υθ3­δσΫB-?|i”nυΈ’hY΅κΦJα[b΄"!‹―/Θ,ο ט:Ήa₯6ωWΡ£…-²˜UUΕoΎVn8₯Fυ|ώ{SΓOεΚGώηΫΏ_mEUθΒgψ†Ό""d9šε ίΚo1δps—O?ΉΙ*«Υ)»έ)Gόν;§U/= EsΈC)©Α*—μ”ό%^Š(¬ Wςp&+k™P`£'ΤeυΫzυρΏT³mG=ΆŽ’²yΐ·iψ+Ίe5Mž²T±χόwΩΊ=~₯¦Oœ­_6οWς»œφ³J‰*!»))VP[½`‘μVφ’‡a‘›Ν©ΤΤ[7Σο<” #ωƒUπjŸφάPdόόψχ ϋ&+ι)»t±Ν«€όΜƒš?w³ΚΥΌK{uΤ_g£ΤΌοuΎ;σϊnneςόs&).ή‘’Υ£t΅#1ρ±ŠwΏKΕΓ/Ν‘Y#Š+Κ²T±q©€$ΓG‘‘ΎK΅„D(ΜϊβrœΚδυtcηy€ ύδš3ϊsεΨ·\Ο4™uώ2CΎ+ιz΅υŸψjx*Ÿη•χ7ӟ©έj“5£0dO“ύ²·Γf=—!›»[ϊΫ[Λͺσ‡/©οε΅Ψδx!Ψδv£ Γ«΄zw’κnψN³§¦>_/RΧ!ο¨}±μπξY©₯Ž’%Ϋ[]Zβξά£9oΡΟa]τΜλχ*ΒίCζ†1κ³δϊλMWΏ›Un†$rσΘBHKsʞà -Ν”₯ΊϋΙγͺύ~ƒύ“Ωσγβ έεξ–¦£iιg¨SώώJ‹κ¨Α¦ΩZ_σe½ώƒ6_΅>Ή;γϊnEeτό3M™’ γZ/(γ܌坿Ο₯˜r:{ύ…ϋIΚΒλ nΛϋΘ-g7jΥ7Υ{~¬&L˜  &θ³ώudΩ°R§d~wkH!…ΪχjOά₯T‘v0N‡.ώi•Ν’’”” ΔTRμ~ΞβΚakh€ŠΈΗλΰρ ½τRPω³$ C†=MΧ>Υ€‡Bξi£Ύ~¦>%·jΑνάφl%ΤΌ™Ώ~ύiΣ₯YμS;΄yq΅νρ j”)ͺπΠy€WjΆλ»^ΉYν:}ρ€φ¦l;’9ΌrΫps—[ZͺRssEΈ™’³)ξςΈς“σ°~™ϋ»Jp†(,Ěs―/Θ‘€\’²i•Φ«ͺ7(¨Θ(EEF©dΓFͺβX§•›.EΗΩ³²›N₯¦Ϊ3«hΧV£»τυΈ/υW\²ϋ›&MMΗ/άΘ‘¨ΒΗ΄zρΟΪuψ¨·.Ρ€Ε;³Ύ*Ϊ»ΊΪ6σΟ£>ό?φκPς!νίΆZ_ΟύU²±zέZ(B‘ΗΦiις=:|μˆβχ'ΰΑ©}+ΎΦΟχ*ιΨqΩΏYΫ:δθC‘Z¨τ–Υϊηβaε*θu@¬άͺΔδ$νY=C#ζnK·:βΪυgΣς‘]ΤeθςK'YΜ [ ξ.qZK&nΦΖψӊ]ϋ—ή˜pΥύŸ–ζ”œN]Ήj>+Œ‚Aς?ž €,|PtӜMTβΙ@…ύ·ημ;ΏΡW‡¨}­…žΠΦΏvλΐΖMŠ QPfœSύwM™<ŒόͺΦΈΊΞ~™Ζύ²C‰GθΰžϊνΟrJ2λͺuΝ£Z0z†Φν?’#±k5ν³E:Y«΅κΌΠΛ¦Ά}σΉ~Ψ™€£ [΄pς"Ε—­―ZΑF޽Ύ 3|Ž@HΣΦΥke―K/_Άοu’+§iΜͺ”Rp›ώΧ’6L“Σ”4 ₯{†ͺΥ[Ÿ«we›d„¨ω •0μS½ρδ$9όJ«αύъψξόΆ,jΥ««ώ6F½; —OњzΈλ#:4&)‹5zͺ|·χτZΎ±šςQ_=œ¦|ETΑcͺ™γ©-EP'Υπq}Τρ¨S>e»hθΠ‡u—UρMš7vŠ>N:!»g°JF?£ώ­ο»ζ ΏΪjY{Ό~ϋώόnχ¨cοzzο³κ<ήͺΠ ΝυD·ζ:° υI’œ²Ÿ=£3²§?œ"#Φ@uVGΏ?υ“κ^~e‹λ…·j*ξ…γηOΫ―Χ’ηkόΆΣ:zΖ)Σ”ψC~Α…4`Ρ#zΎ|Φφ‚΅PqέeϋIΫ΅«QΉάΪΩwoΧnχ»Τ"첚ΝZ9w™BΪ S1›Štξ€_ί~Q=Ž…ιώg©€u―g΄ΡλΏ dψό3T ^½}t¬ΖNxQ]’RdΛ€νώ§•Βe1 ¨Nwt|Μhθ3K‡Ν•¨ΣMo?uΩ7XBt_«(­ωΰ) MS`ω–zι…– 5€œz}@fŒ“‡š?uθ-IrsKί1&&FυΤΏΕeΰZ–Ε,»ψϋΝ|_ul§'ί:­>Σϊ«2νίΜcϊα.š5Tc/‘ώkϋn:‡ΆMμ—γΣ”Wλ+?υϋ: λψ‘l§«o%^ŒnŽe1ΛΤ Aƒt—§₯[φΦhΞ(fϊp¦NΕΖκˆoqωΌξ†Ÿj·ŒΦ€QίιοŽ%T);ί٘Ξώ₯ο—₯¨ή³5nŸΐŸΆBοw|_+ΰ<χΪziζKͺΑΉ ΐUϊΘ«»υν”ί•―Z-έα+{ά*M™ΉAAu;«('Ύ£xέϋ˜ΊFΎ YίΕ©B›B·π€MNψv–Φλ’aχ€ϋz‰άc«ͺž£Ζ©Λ΅Žν7<εΟ(ΐ‚wδUεOΫ¨iο}©ΈΓ'επ*€»<«Χ;–δ ώNc«Ι ©jrΛΨ’πvC5­έ-ΰŒ*šΫUΐm1y•¬θžƒέ3· Ž­ͺž›σEnW|eŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύš4ΘoIDATΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τp yxxδv ΐEde\aΛΚ†–Ε,»ΡZ€€₯KkΥΚUJIIΙνR@ζαα‘₯Kgz»LCƒ r€ pN­Z΅r»p‡`y?.ŠΠ€‹"τΰ’ύΈ¨œΘ/&&&·κ9 :ΊξΕίϊ9S?y[Zšγβο,οΐEϊpQ„~\‘EθΐEϊpQ„~\‘EθΐEϊpQ„~\‘EθΐEϊpQ„~\‘EθΐEϊpQ„~\”νς?ΉUΘaΜτΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.ŠΠ€‹"τΰ’ύΈ(B?.*O…~σΰWzώ—υνQ3·KΙΗMνΣYΓםΝνJΐμN“8ΆkrvzoUZnWrsœέ‘…ƒ»«C›fjΣu˜Vž2u|γt½ϊd;΅lΥV='ύ-m9€l°έΨέOκΗ7ΦΠ5©’aΘκξ«ΰbUΤ챞κP1@FΞԘwYK¨σπΟ%«5‡7|Ω~ΏΘ_ΣΑšΩ―κvj0u蛁a}Qƒšσ<ΰΦ8©ίμ¨y%†kT§»τŸΡΗM“\?gςŸšρή»ϊΦUSήi!‹†TΕ―™£)³ΎΣΪ=GδΘ©jmŸV―ΛΛοƒŠΤψ՚7cŽ~\ΏCO8δ^ \%j<’ώ= ίͺζdκμžο5nμ,ύϊO‚R<ΓTΆ~'=Σ­‘Šx\νΦ¦NlVΣ¦/Ԋ-±JNq“_xΥlΡY]Z–;ΏLŽ™¨Ι;KιΉQCTΪbΚΗc―ŒŸ­δoj|»B2 ·λͺ6§Ζr™υeVϊΪ©£›κσiίhΥΆxp«Ν»Υσξάρ—3“ΧkϊˆΟτΝ†8₯ϊή₯ΪΧO½›—PΎkΎ€Ϊ=ύ Œλ¬‰’ε}CΫΚXΌZ,Šμ0\C;•σΤAmώφ3x{¨ς:XΝƒ‰{ΖM{s½΄ίΟ-Χ0dqσΌ Ώ$σ€6ώΉCφ*Ή]ΈΰζI²ΛΤ™έ‹5lπ:\ΐGΖƒσΨjM›ΆIΑ½ͺΡε *eΗ π/yM £^•ς]ύ>ŽέZώΫ1U}ΌΚum+9 YάσΙΫΫGVοβͺέ©³ώψαu­η¬šη“yf§Ύ7Z³~έ‘cξ…tO‹žκϋHX$ΙTς†YϊtϊOΪ²χ Ž[CT‘ω3zα±ͺς7$ηαί5uψ-ޘ(…ά£V?χOΡΉW³ϊφՍ'θƒΦΑη?}LΡο?¦aΞg5ωωΊκξplΧδޟΘϊX;˜7Y?μ8¦|EkιzχUλ’ή2Ϋ5Ήχhελυ˜fΤ‚Ώ 5<^OFξΡ’qŸjΊνJ6ύU¬f{υθΩFeΌώՌ>ύυwσ‰’ΰω:NkεΠ.ϊ4ί˚τ΄f<ύ’Ÿ£UΫ£Ι½GΚϊXX0U?o=,•Wσ/ͺ[΅@:χ‰Ξ΄α£υ͟‰RH%΅z’Z¦2#ίU³W~€rΩ~Ώβš χω5ΪΨ½ΤnMξ=R–N-”₯όΕι‰ηRΎ₯£4ώ»Ώ”ΰT…6ύ5ΰΡ{δg\£ο:—Π–}4|Υ1₯¬|XMGΪTͺΫ8 ("oK€+qlΧδμŒI2K€mΤ„ήοκŸϋ?ΠΠΣΦΜ₯jίοΛο±χυΔ‰zjε―5όκjΐΘΊΊ8½\½£Z•_¨YΫβδ¨QβΏγ3YΏLž¬ν%žΦθΝ|ΎTδ|»eΨ€„0M?m="Kpy5»ΨΦ Ζ’ΞkŒ™JlΙ~ϋΣβ΄p„괨­bA)¨šWŸ©7φ”CWlΓLΤSΎRrτΛσD ωœίj>’—ύO©χ&hρύo©Θ·ohΔ’ύ:‘ϊΊZώlSωΆτΧ<-?q\φη›iž{]½ϊe_ωΝDcΏY§9δRFυ»Ύ §£C€kυ±qL+†_e,Χ6Y“²ΩξLϋ2³λΝ$ύ<γ'…t₯>X=ŠΫ—ytbώ W›‘­T&ĐBV·ϋ~«ί―S·JušMν;–ιΧΣΥυτAώzΆ•™›’Γ ÐΕbHζ1­ύ†fŸj¨—GOΣΔAν•οη!ϊhi‚Ξ•oΘΛ'LεΫ=§!ŸMΣ„Χ)uρH}ω]2τν°!ϊΞl’ΧΖNΣg›+ν‡EΪκd‰PttνXΉZ‡.ޟΊEk68UΉV…Œw„γ_-ψ|ŠtϋP“'T―2ϋ4ω±ZwκόυΞZόΙtχ²>›<\JœΠ―ŸΌ¦i‰UΥχγiš2r€κžϊRo~ΈTIFQΥ]HΫVύδ uœΩ¨•άU£ΞέrOχΨ{4oάo ν8D>―uΞjρ'S΅>U’yH?Œ’%Žσν}Ή©ΞΞ―eΗ³yώ‚LχωUΪXv±ΎωST©§>Φδροͺ…ϋ2 ώE}ioΧ>ͺΟ^¬¦Γσ>Υ‚έŽkχέV/Uοω¦)ι© ='iήάΉzΏma?·“ Η$™Œ% «άσyΚΣνzίέ=Tκ^VοΊ…ds^cœsyΊ3λΨqCώ'NoЊ?έT«UΓ‹?σŒV½R‘Ύ―‰SΖλεΛۚΡXTΊϊ˜ιzΪοYF•K'jωχuΤ)9“ΠOλT₯zιt3pζ‰?΅v«·j6¬z1π_ΰQ’‘κ„νњ?RUω±wτbΣ0ω6xU³ηΞΥΫ]TίΑ½UΫ;\ν†ΜΥΌ™tο/4όλT5~uœ¦O£AO6TΕpυ±α{υ±άυφ{f}™Αυζ‰ Z³³˜ΚΈ- ήκ}\Ο_€§σΘω½pΗpΔξ>οβ*~q₯»UEK—sΧΕ:v»Άώς›ͺ7P…+ρΙώΆ2—³YΜq\ΫΝΥ GUΥΎΫCfςoZ΄:Lto©2!ώ*XΌ±:5 Σ¦ektψόkΥ£D΅Ž.§"A )wŸjGUμ3r&­TΜζ 5οΦ^BύU0²¦νPγό‹ΒkΧQΡ+υϋ‘s²o_₯υiUT»’W¦enάY-Κ†Κ?0RΡ]»(ΪΎB1SΞ]iž–­κz¦q)ϋϋ)ίρί΄δw?΅μώˆͺX΅}ͺƒŠό΅P?ΖJEjE«ΠΦZ{ώδ‚)›~ΣzχͺS&]δ—d*όΎjW1\ώώ…Tωζ*wz·v'9e^©*¨VO>t½QΡκϊΡΚ흭η<«‡Ϊ·ΥνΫκφι½_ΟdiŸ_ΩF―‹ο6¦"wR“R!ςΎ[­—“ΣQNν­­’*|o Υ‹HΤήΨΤ ϊωςΙέjΘκξ-oooεsγsYn/ŒI2KΨΚι±αSτnλ[³ŠοΜζ…Zwξ―U0έL―3)N…T΄πΥΖ]˜*ΤΈ«ΪU(”­΅Η’¦tυ1Συ΄ίSΛ/«κ?oλΙ§zλ©>γtϊΑwΥ/Ϊ/]›Μ#‰J2CU(τ*KΨ­! •&Ι’οάΛ°yžoyx(Ÿw>Ω ‹άςωΘΗΫC6‡CΓ&ος/XX₯k4Sν(χLϊؐνjcΉθχŒϊςjΧ;φ+>e³ΎΡ½ίΥ―=¦b»'hΠ€ :s57ƒyκ„N{ϋ*eOlk~?y<ͺ«Ξα¦n/«₯ZυΚ₯›(ΞφΆ² –χŸŸσ%GΚYχι™wžV=CŽM{{v³6?έNŸŸΏ΅iO‘=¬ͺŽ;₯‚V»Χ}©)s—iSμaLISΪΩ4•oδ”#1^ ΆH+|ιž{xQ…ZI’,aΡͺSt–VMVσ¦~Ϊυϋ:τΈξΙ4σ[rιŸ•g€ξ KՊ„£ηgΒέT¬t‰‹;ί«8K€Z‡_ϊχfD)Κ7N{8d©­θBs΅bύqέίΨS―όCξΥ_RYwIι>‰±)ΌHΨΕΗ6<=ε)»μi’#yΏβ­EΥΆΠ₯Ηq /’PλΑk΄Γ’ΒΝ_Υ ΆE.nΟΣΟSŽ™μσ«΄ρςϊB _ܞ»‡‡,‘ ΉpCΓCξξ’έξ)»’Ρwΰv—Ρ˜$³ρΫ­«‘£ύͺΘξΓΤ0πΪ“F†σ 6…G\½­΅Η’η\kΜ”])Ϊ»ϊ{­;]Z͚W–cΓbύςυΧZ{χΣͺš~8žas²1θ·•}H=£ix―ΗυCέ6j` U+μ%G\&}|>ΝΙ¬/―v½yϊ”N%Υ±ίγͺhH*ͺ'Ϋ _GΠv{eUΌ-NfH¦ΣΜΞKS)›–i΅-ZK§?Υfv·•9r"Ώsα3B'V}’WΏvWΑ―s¬LSrΏW=†χRΥΛΪcΨΌ`•œϋζιέwΏVώ‡žΡKOέ₯Ο£ϊα½—΅υΒ}e‘ες Λ₯γΈ,…T;:R³V¬ΡΡΖ₯΄fέqέΣ±²2Ÿη—œζε»Ρ©ό)‹lW,[2u΅oœk£%B΅kΌ•λtΌŽΏVώaSΝΛ]γL©Y­Χψ/j^₯k­Φ >I5dσ TpHΘŽm³g²ΟΟ}‘ΎΧ¬ΟbΉκO†}ns™ŒI2Kά"ζ‘ΥύΖXn:Hƒ_uLd†¨ ―}ti–βJYmWokζγ™k™²ΗΉχ+}4υ”ZςΆš΄Hm›«ΑŒzeΔ•άZ!— ΆŒΐYκΐA‡rΕPέ― Rp₯ΰtηtΊ*Kj=υ‰*΅Z«οηΝΤπΎίθžg‡ιΩ™τq'ŽΜϊςšΧ»ΉΛΝ#PAΎ—v-  όNΠ)Vψγ6bρυ“Ο©γ:qΩσqβ˜NϋΛ7]˜:£Ώ~Y£|ΡƒTς*i<{ΫΚb}Χw·Λ]Ÿ‘*Ω²§Ϊϋ¬1³Άθ¬$kX„ΒΜ8% THHΘşΰ@Ω$ή±Il¬Η£²‘α -hUκ©sŸ¬ZƒΓlί§^š9v$Δ)ΡqιqCkΥUδφ5ZΏk­ώ8RI΅3Ÿζ—dW\lœ.nυΜνŒσPhX«†[k‘’ŠpξΡΛ 0ογa*RΨ*Ι’Β΅£Άy₯ΦmX₯?l5]:ϋŸ₯XC )Δ«γ/kobœ’²9qžΩ>Ο)υd‘Ε"™NfύΘknΥX"#ζρ?5ρΝΪ]γ½Ρ‘δ5ΟΧdψTΤ½₯NkΥw+._)2Οδǁ=Šσ/©’†ήωU©¬ΌφοQά+C ŸŠͺZκ”VΌ^'―hSʎeϊυ`”ͺW ΚΖIν y…WS»Ύι£NZωνjΝ¬sn,—Y_ft½5uŠ~9rnSFpMΥ+§E“jsβQ‰]«Y³ΥΡΛΞ©­:‘Ϋ΄όΛ΅:XΎΆ*{’c§¦<ΥR}ζΔκκ¦Lνϋ~ŠnŠWςαέϊeT­ς¨£†WžAαΒcψΧU›:g΄xόL­ΫDΙρkώ˜/΅―\ 5,|nχYΒ£U'l“ζΟZ'kΊΊŽΜ/#¨–”Χ7“Ύ¦„£:ϋ»Ύ˜ΉμqψYέN&ϋ<§dΤw2ς+(Πͺ=kΣΓGtψxj>2Έ6S©Ηjl¬bΟμ?|&[c€LΗφ͚ڿ‹^ωϊZc­lΑι4sΠύ^ό x0J:}R'OΤ©Σ)鏜4‚Υψ±v \χ‰^ΉHώMΡ£‡Ώg£VoIΘ΄Ύ Η3Χrν·F–VdόRΝ\ς·β“ιHμz}9k™N—Ό[‘Wβ`έΧεω6Lƒ>Ρ?ŽθΨΡν\5KCή_$k‹ξjž΅!ΌcΟr}½|£φLΦ±€έΪΈγ°<εU0“>ΎΪXξ:ڝY_fv½α[K­λžΥ7ŸNͺ½IJά£ρΣV+ ^=η[ϋp1ςΧP“‰Z8y‘Ά&Qό_s4ιϋSͺΡ°κt™:ωΗ2ύQ°žκ½ϊ“8λΫΚΊΐΦ£Τ©{½e2f‘κΎΧ^uϋ½£Σ“Ζk꫏+ώ„δVFΊ•?χΰQο¦hμ[Oθ #D•Ϋυ3Νi±$ajρά”4bŒ^ο>A ͺ¨VOtUέ½Ώ^z0#X΅j‡kΨ]Ίχ…ͺς6tξ+Qω«\Ω°«’aψ*ΊU%νχ¬>χ”Ό"k«Ϋ«έU9Ÿr Ύ$#Ώͺ?σŽΊO­OŸ›­D»―’ͺ·ΣΟ6Ώ΄ΛZ΅ƒ5εσγjΣ³ΤυνT#D͞ύŸ†¦7ΊO’‚+ͺyϋ&*½e{6·γŸα>Ο)φΌtοÏ«‡3τΒ㟫X—Χω•> {œΪυκρυ…Ώ yΦ{]s_ Ξϊ&2K˜N₯₯œUJΪΝY_}vΝϊbσ₯n€ΗΏ½Ό¬ζzwκ³ͺrΕ@+_Ω2$HS§}­ž­δ³’gB*ΣξEU-•ρθ#γρΜ5\Gϋ-…ZλŏjΜτΑzfl²R= ͺx΅υZΟ†ςΏΚ”½gιΗ4xH¦MϋBοτύ@Ι©nς /«ZνήΥ³­ΚΙ+«ΣόζύρΕ§š›¬4[Ή§Ή^θ^]ω K&γΕ«ŒεZgΏέ™υeΩLϋΪGU{RΟ #5φ…ΗuΨ TΩϋϊ镇Kά²U'@–ωU³Η+Ϊ?r€ήμρ©Nη+’{xE=kψόwUŽyBkΩ Π:]UψZž²Ί­μ”WcςPσ§½―σξΉΟ±}’zΎ«ŽίPC_CŽέSΤϋνγκ9Ά*]yhΧωο¨M||Ž^ͺyυ£ξo'fΒWzαιυΊσwΤδzΰά‘Ν•Χ'_Š]·NΗ+ΦUΥσίipζί=J«VWε28Νj^9οGj쿊w/ O? ϋςθΚ»Ξœ8₯ϋ–jόβSͺϋbΝ‹g2τiψ¦&4ΜέκΟmόf­Š‘²ύS³&/“Yυ*{ϋ/Jά†ςfθwμΣW/χΥΜψUzπu©x½§4ΈXε–²] ‡ΟΧ¨Γ§δπ,¨bΥΣ+=jΚ‡‰~ΐuΘσΗτ€τΝ•GgϊάΡΦ­_§α#>V‘CΉ] \HPPϊχν§ͺUξΝνRr ‘@žσΙ¨OT±R%mΩ΄)·K )ww9=JS&MΙνRr ‘@žsςδIνΫϋ―|ύ|s»Έ½{χκΔ‰Ή]FŽ"τΘs|σϋΚέέ#·Λ€ ʟ?n—£ύς››MnnΔδ<›Ν΅žWΥw ›Ν-·Kn{„~yŽΏΏΏœN‡<<Ρ5B!N6k:ωΫμL; ]3€ώh•Ε€g&²ζ·υΌŸβιΝ‰ίΐ¦cΫ!Ccν_"\-€VΐΫOέΓ“ϋUΞ›[FΊΞΐλΊ†£Ί”τŒ¬ώυ[ήZ›‹αœΎx5¬[aτμcΣγΰΫΧεΟιc ‰”Δ_!Δ™Η^ZNeF6Nk&/<ΒCpλΠξyΩ ‹©HΝΐ;&κ„ζΡQGέή¦ι‚ΖŽhφ3΅Ϊ†š”Κ…‡±f.ͺ#ƒ±ϊ`/*Α”Uΐ”Cψa_ΖΎ1­&ώP“τ·6΄@Eη #χ@¦SαhόPς7bΤQuχ ¬l0ΉΛ=ώB!NoΆŠwxςχ»Ιβ3Ί­˜€΄#¨>ατއ~p%/ζ{θ(§:ω0™Ε8ͺ5w/ά"{ΰΣ;SmŽ]UHٞd* «Π->xτ‰Ζ˜±—ςo|FD‘ξώœ7{Μ皁!˜υB6―ωŒ•Ž(LΖ΄šθT=ΜΞ|n~αΔυ9››ϊŒα=ο°θέDŠΞŽΑQ7L vΪͺšσφN’>άUlͺŽBq&©ΚΜ% ΒΖC³2ͺg_Ά¦$ρ«>£ Όξαmž—-ο(nω%Ό}ΥR4]γŽί ΜfΓ-4¨«Βo’CSIzꍧι{Οu-ζίΆβfΚƒsΰΚsΞcρλΟP^3*ί3§ˆw―Ώ‹ž!a¨ΊΞͺ£iX‚[\žBέ•ώ–‡φ8€d//vΩ5L#³Ό„] ΎQQ˜lψ‘¬“ χBqΊR±'¦1rΖ\aFΝ[Η-OΏΕN7 φjΌύzΰg”β-ΉŒŸ°ˆ[ώ4˜83Υ%όΊe%O­;HαΘޘΩ”οσαΆ…ryάΚσΥW_‘3σCώ“Κ<Α;^9<ύmfΌPΫ>ήόl+‡ΖΑ°―6ιΧΘωύ-―ΚEWlψ„ΟδΥΫ0vπbž<ϋ―Μ?\Ž[]>_;mЧ P0χˆg€ή¦~\!„8]8Κ*π+―fεχγηy,Ό`πpFχκΛτg’’΄¬MΉ₯ύh1ξyEΌsßιΐ;ΧίΙβ<ƒUKΠΙ»βοΤ[? οΤ[ι·ύΌωnΟv½BΒyοϊ»XψκΣ( Ό{γέτ γp~ίνَή/ΊΥc uWϊΫ~°`V DxZhi8”Πb4RUQ†₯Ρ=B!ΔiC-’ͺ¨—Œ Β¨ΫωyΥG¬‚wŒΠQ­V2-n¨{“™tι£ΌrV Šν(ϋŽδβΩ“i3ξbTψ‹Μ\‘F‘ΣΙ’[ΰ–ήτκ£μ-23aΑ„Φυ:ͺ»;Τ?™opG3¨4Ύ0―„υΖ£―'Ά=ίςθΊρ¬œΕΰ1cˆέτGu«zU9Ž*ΐΰ‡Α]oW.„Bœ*Σ³xbΞUψyzρΣΎ<πΕG( <2g“γβΉoζ|–~ρ>^q½Zœ³€ μ£Όγέu ?@π(ήΏώ..νi¬ ˜NΓη5 x»nςστg—αΤΤ–ϋnƒBuD7ζΎό$Λoψ3ύ#Ί³ςŽζ@bv—ηͺ#ƒ0hε8 .ι··α \ΰabΩˆ±GΘqŸ§–’Ί™Ϋ4/!„┨²‚wozz( η±'Γ α†c}—‡Tf£*γΈaT F=“WŸΎ'ς4ŒΎSω1μRϋžQ/fNO7-“<ϋ7ΟV±„ΜελΜ‘MR―jz£κ85•ΖΧt]ΕιμΕ‘΄tμzAτ°Uq¨ξV=#½.zœ”‹j~uξγώΏύ› ΐ(ηΫ…BœAͺΛ+˜Πoύτ=ŠΓ\χ¬εΏοςϋύΟ0Ύο@lεε˜[Ι-«2²yηκ;θѝΩΔEt¨ϋχ«WέΜΌeΟαα{rF£Χ>+Ο‘iψŒΰ³ςίvΥ}ΦjΞμγIixσ^}Š/–ώ•ή‘$ηη0οΥ§°FvΓδγ‰ΪΖά»ΝΓϋ—ϊΉ3Ν«αC>MLezίx |ŸU€Φ3ΊΥ·!„§Œ¦‘(JΝϊt4T]EΧκ=¦’cX4} Zι6δψ Œ EέΆ—Mω#"CeΑh §»ZΩ~6dω Œξ†}λ^Ά•]BŸΪωkθJϊgύ:š«/Φt,ƒλ;Ί†VcνT ξιWΣΙρτDE₯ ΟγB!Nκ±Ξ ‡ͺΦυŽzW­U­υΫל'Uv[βΚ7Ÿγΐ£/0ηε'xOwPi·αt:OΪmpšΥύΏρ2[ϊ¬)ͺݎ›Ι„‡εXξaΆΰf2Qj·£·yWοlΓΡΒGGΛ±TV19ΘCΝΓϊά4¨΄Ωy9!‰Ν~~uΪpƒBqJ˜Ν(εdΫu†ΉΣ/(qβτ¬’―9Αc¬ν_PΠQ5 ₯^χVΫΥΉ’sW―κ:ŠξzΈm-Ucƒ¬ί5―γ/υk85'δV2μά, ¨ωYqsCΓZ3‘λžώEίδΰτ0‚β> ;˜4€_!ΔDχtcc~¦ ΞΝ»Š»>~…'\ΐΖCϋΡ=έ[ΝS•θ0ζ/{ή5Οj[έί ΚK™φκ (˜£ΓΫ”οVmέΣβη£·:ΪcU׏[fKŸ5ζ,,!¬€š/nϋ;‘έ8˜›@Ώ°HΎΈυ>f½π(Ήš†©›«1±νWϊ³x΄AQ±•yή¬KΞδΓςJ^Ψqgh0ŠΕ,Wω…Bœή/ XXΙEΓ<9wΪ%œυΜr~ΝqՁβπ ΄§'ωΩGHTΗ3g"ήη—me˜ύ.b\ˆ΄\dΩQ΅\2uθη۟ αelΪZ‚9πb†ωΦfω:š­ κ’ΣͺΡμΗο'/ rDτ½Œ&…bΤmόΆω7Žω’–5šXGC½ ½ά‰κ/oΝBq† δ/?βμ^}Ήpπpφ ^χQIe|ΉB[ΟS½<0tέχ_½uoݟš†{Νί5hSžκΤ4J^ϊ¨ΙΟό—.lSΞ\›Μ;5­n8SΣ΄8/§Šw~ +nϋέƒ8˜›Ε¬EAaε­χΡ/,’7ήΝEΟ «'Η^)Ԝš€ΏΝΧζ…βš«ό;Λ«Θ {EŸ\ίBqϊ3‘ΖΈσυŸ2Ώο•Œν1“ž8›ΔΜ£ΨάόιDΚηw0/λ^Ϊ4•7'DrύέΟ2.­Ÿ¨^D›‘pηJ>,€ZέΜ—i³Έ7Ά;7όωYΖf”αޝp5Wή5|•aάp~<–8œ5’άmGΨYΧi}-ΔΪρθNP,8ΘΨώ6ύͺ‡Έ‘”5š6ζΨ+ϋ~ϋιUž.‰–Δ_!ΔEρχα°5ŸsžΈΗη,fRAθΊΞϊ€}άεG€›uL~ήνΛ1έ-¬9°MΣΐΓ­έωiKΣλ­|ήx͝ηέIοασY:,άΥΩƒ™4υ2Rφό™έ%΅Α(xυβμ@'֊BμωΥ›ΎgY’Β!aθJύg(xυflέ+‡”n¨ΖP‘£"IΏBˆ3‹)2„Ό2+W~ό:zU5Ї;Ζ° Lώ>힟9:’Kίώ7 ζ'“ί…'τ½Ξœ‡ΑΧ‹/vύΐW»ΆQκ‡1ΐ•τΣ_ψ3γG²rχV ±αmš§rΦ²§τΕή¦‰ϋYŒόΣΣΊΖъ*nΝ+mΣ™!„β΄SY‚)­Cq%ŠC£ έΛ5ΆͺΏt;†ŒŒΉeͺU°Έ£‡βŒ @―IW]‚))c©,n`:‹wž½…s•džxΰQ^ΤsŽέcˆbA2§ŸŽaΜ5χτ)0›Ρ½½QΓ‚Qƒ=κͺ5œΆŽmΐ`Α„BρΗ‘ΫμhΦ*w .²kU6τͺj ^(n–VηΥS·΄οJA»ΚΒ£G©}Lpν!„βŒγι3…ΰ(΄Ρh=Z˜‡»?ΞxœΞ",»~¬GΕaλΫΤUxmΐlM|rΖG·ζšΧ–£hNvƒ 'eό@K1<~Ε Œ `μw,fUηθΧχρΌρΎ(₯£aiGψπΦ;Ψ=νMž˜\o~:y+Μυ?ηΉ―¬·όŽ.°3ΈΚςιδqάχβߘp,jηΆgXτVΎt½Œ'8ϋεέ‘8›ΨV6οR“XvΣm¬Θh"%‹ώυ!·ocsλ°ΆΆΓNϋ¦Sžτο°’Mϋ3(Ά™ρ‹Œγμι‹ΉjΖ@όΊ2ΐS]Ί΄ώœΌύ²=g Ÿ}ψ ?m?DnΉŠΕ?’>g]Ξ7ŸKΔΙWV{ž²~IA1ΉαΪ‹‘γ/fαόIΔx΄΅ŸΜ˜ΫI/α‡ϋ―βΣ^OρΪ’ΎΈΊ;۞_Μύ;&πΔ[·_SU΅΄ΈυŽ\ψϊ3k_υϋοΣ^?=ΈΟϊ<ΗKWτδX·ιΰχg/ηe―yλ†Am8ψ:λ€Bˆ3N" =―x…ΖΦtb ( h8Z†x"1΅¦^Μz{vBΩIG†&NŠδΣM›9:}Α΅³ΥσΩΌιέ'έI¬αT•Ys\ei±nζυ·eΘ]γŽ%XŠ‘-eΪ’NZί&·ΥiR–ΖΎ,ymW‘ƒs?―ίp?%ϊˆ{ΟΆΈͺ₯r²ώvθμΊίAΥ‰οqίίWα>γΊmέ½νδνύ‰e/έΗ_ςαΩkγρμ²POq=:λO#Ό―yθ/o?τj–>u?qΑFJSΨ’NΠIO\N~ [ Ω‰Ώςε²ωσΞL}|1ύέΫ>―Σ£e6’ψ1dx4―lήΟQ½/‘ ΰLfηkΫSTβϋΔ}dEeH7§Γyͺ#?Ij“υ㷞ΑŠQ²x!„'_;Ž$ F3F£Ή&ΑΦ]©I,»ι/δ]ύ έπzU2ίΏώ2Λ7’ΤΑ°ι7pΫε#μ΄>―™˜­πwή{ξ5VνΞ‡Πa̜ίχΨU‚Ί˜ί`ό–»ψχ―₯Ψ6Νgκσ&ϊ]σ:ΟΝλށ$W!jά$Ί―ΨΘ–‚™Μ q-TΟ•M‡’™tGT½εΒ_Ο67]N bΩrΎς2ΟΟοŽ•€eΧqΗΧ=Έϋέ8ΧGͺ<~Υ2ByƒkϋθeψZ&FΜ™ΕΡΟ_γνρρά1Ϊ§‰Nβ„εΌςΑφ§εRf %ώ’›Ή{Q7Ύ½νφ\τOͺω^%Ώ>u―xό·oςζΓϊλ[ΌχŸ{™―wζCθPf^;£/­#ξΕG™ζOΣΛXά‡ύΟίzόΆšSΕ»υη]yˆo_…O6%Q¬ΠλμΉ\ΓΕΔy+r_ϊ"Ζ+/¦όΛχψ9±‚sΡυχpΝθn>ΐVŒF ( ›0Œ& F£ΠΡ*“ωΉΆP—αŠιφλR¬ψτ>kοš‡Η/ρΖχ»ΘS»ρά»h~ZΛ–Ύ€ρΚK(l«•β=–KocV_―FλΡΜ6k<ηuGi©έκ₯μώδώσυ6RKUΌB㘴δnn:'΄cε§η³ϊ½Ο)™x?o_77UCbΖ,δnVnΈλMVM}ŽyaΫxfΡ xώγnδΪ}ι%ίρk~dδ+ΟrI˜ς~GMbΩ—ρΈεJΏΘ—{¦>φΧυKi½Mvq΄X¬‡XΥ\½†–λ}ƒrξͺνWΜϊeΛHκwoώ}*ͺЦƒη€Ι\:PΗιΤΪΤ6;­ œ.ύ’g0±#/αξA=0έπO^ϋfΟΞuυ/­ΗaFΟω‰ηοzŸ΅‡ΛρˆΗ‚₯·ΊΦΟω{λν Εύl‡j*Αƒβ ϊh‰•³ υ-3Ά±L³„„Lκ;Iϋ’π΄€ξzΛ―έGZέ·ΨΣB}χ*ζΫ΄±ί|ψiFνzΉσΫB;΄Ή.ͺνΩη !„ΗkηaŽŽΧώΈ’λf‡ ι₯l~ω>Ί€ίϊ„ž\€χΪΗyφΗ<:χΌ&bσψξΩΗω^™ΞΏήϋ„eΝB]ύϋλ.4ΤΖμΗΨ[εͺ8w†-ύoW}ΓσJψkDŒcBχƒlό­ f]uςΆlδPΜΖE(4(³ζΚi΅ΑC’ΘJ|δBœ«^δΏ£˜81’€-[)ύZΥn6οtγœΙρX¬οQVΏπ8ίι5ΫζΑΨ?{ƒueJΝA]3ΛHτjf[՟w1_ό'οŒαžW?α“7ώΞΉUεΑg~€@wΝΫ α³76Ήδ>ψδ]šlcΥ ο±έήΔκΆΏλκ‘λךz©΅Φ\q}ρώ.άώ2+>xŠΩξλyώΟχπ©6‹Gήώ„wώ~6ş½Κ—)jΝτi|ωξοτΌι–/wΞ`ΩΏώΓ6k·YsεΩJ»u&~Μs_9™φΘ»|ΆbOή|#ΊwόΦ½|Ϋx3nΚ0,N­¦MkͺbΞebΔ~Ϋ^€Ž‚QQhpMQP¨ω[«ϋƒžΕ·/|@ρy°μγWYίD›Ϊd—Aσυ§•zέj½?¦Λb―άΙ―»ΜŒŸ= ‡U«έ~*N§ΦζΆΩymΰτι—4UΕaŒ)a€όΆ΅f›΅%Ž 6­J ο-/±bωά=,›w=Ά~-·ƒΦφ³cŒΒ σφ$;‚];Θ‹Ν%£³c‡k)μ= 1pHŸ†ϋιΦφΓ­υί-Υ%ΪάoΖ;>횢ΠVνͺ‹νΩη !„ΗkG~«’²βζ͜͝Ή³™3wOl¬jvj½x«ΆDrΩMΣινο…wτy,žΑžυΏSΨiGWΗΗτθΊ τ‚Ν¬ΫΒΕΧΟ%Ξί ŸΘ1\΅p/z(&3FCν•c'uψœ31†C›6Χΰε±yS21ΖήhΚζΛi+nγsh‡ &°£ žYηucοΞ$œhδ%ξ§΄_<};iδ―Σa ίεK™ͺ}ΟΛοο’²‰i,½ΟeΦΨώ„ωzαΧο|Ζχ,!+»šΘqˆ8π Ϋj΄dΫ»‰ν–±Œοί08½p3kv†0ϋ†ym5Ž?]9_₯΅eTA+ΫJ/ΪΔ·Ώ0ϋζ… ρΖ#p ³o]HμΞ•ό”Q;ΤW§ϋ΄kΉtPžξΑΔ_:ƒψΚ#€tέPΰΆ΅˜ ―djΟ@<|ϋ3σΒΑ¨Ϊ`ζ/K€·AΓg29:τL{έτ=.Όšι}ΊαιΙΩΧ\Γ$η&Φν±·όφ”g«±κšΑ„‡—7ή!τ5•±±ζN(£| #2D9ώ€W &" ςσςiνvΰΆ•u%¦³nδΆ)½πsχΐbhη<Ί¨ š]§VκuΫκ}νΜΊ&vνh6ΉZΡΖ&“ηΆΆΝjuqœ”~©©+GD δQ Ά=Ž˜iK˜ή§^ጾκ&«›XΏ·ωυ«[\φ³bκϐ~•μί—Ž¦—±+α}F !hΘhϊΩΖΞύθφυah·¦"lv?άZέr]‰ΤΖ~ΣΠ•νΈρ±‰λψδ‘5uν£ύu±ύυ]!„¨ΥŽtΡ@χ‹ζ‰K£λ†›=›Ώ9QΝN#£z/―];‹7jώ¦;m8#GQAPg\œn2&oΤƒ9δ™z3LGΣ]G λAΈ‘ΰψYΤλ\uNJϊΒΖM$φƒl.˜Ε,νW6%χdβέaΗMΩR9Yc㉳ΐ,'=o'΅Οxώ:‡o_K ΝKϊtb† Δ«“δt]GsΖΥ7NdΣc/ραψYΰΎR'ωΏ/ηέOΧ±7£ ›G΅ƒ!ηι9ž‰‘³i{ηOqgΟ–νXΖώ8#ΤΟΤΤάLrŒΡΔ„j5ΫFEλAΈ!·υe΄²­Τœ rŒ1\ͺ‘j:ͺw4±~Ωdd« `"2*U­ƒarΓMq’vαν¦­Ά\q……wCs ³c·pΊ‘Φ”“³TU­)αuΣƒjθAl€y%’φ•g«±ΈŒ₯ΰ©›–πύ„‹™{ιtFGyvB»qΥ3½Ιs/«ίŠϊ9ΚΆ•΅™>ύ{‚Sk2A=ueΠΜ:΅R―UοΆΤ{SnΏΊ{«N`jΫfΧ΄zqœ”~©):ͺͺΙŒ©-qΤ¬_XXΠ±υS"ˆŽ°³1·ωυ«Υϊ~Άƒo‰α…­ϋ)τ'α`#nπΗΰ7”‘έίdΫ+cΥ=€Ea ΏΗ΅λζχΓjqΛύwkuΙ0¬mύ¦οΐα]؎›8HxνFή©ω­mu a™5_ίOή- B!ΞLνΊ§ίμι‡Ώΐ±NLΧΡ[Ίτζ6†₯―έΞθΪ“η (FwΌ;νΐͺι˜ŠπT1ΠeΗsM 9‡‰=ίcΣoyŒΦ6‘άk"χ†4Σ-7WNž• ιΓ― ˆή“Hτˆ[ρολΛ ’Ω•3ˆœC ^άΉ½γuφυ\7ςO<ϋςrΞΊΪXWI΄τΟxτΡ―π[p;χίΡ‹nn%|ȟΩ@γ&DρΙ–m”`Λ63γώΧδPEi”ά)†Ίaͺ-/£ŠΊŽVήΊ((u…dΐTLlmικ#¦–Ϊ‚κŠΛX/.WΨ-=Θ«&‰¨γJŒηΕ'Tž-ΆΫ@Ζάό ΛgoeΥΗοράm_3μΞgΉg|P‡ŠP #DΙ!3G…F»%5‡¬\Œ‘΄γΏ¬:ŽhCY›ZΫœ‚2hVkυΊMυΎVn?rHΟt@ˆ₯ύλtU8N—χKMQΙLM‡°±„Υ.§Υzκ:{LMά\4j-νg;N!hPŽ>!ψκTW;Z‹;žˆ½›Ω–°…mζqLθ{ό–6†EκL'5§αΆΙΧΪΆŒ–Ά•12†ξz Ιυ^{¦&Ή4’˜¨cεt²ίτάΦΆΠΎΈœd₯g»€V•Br–αα XΫ[ž­Ηͺ£ΪƒGpɝ/πς’nόϊύ–cΟr8AŠΧF°²yνv*ΝΛvh²c9kD0 fL&;Άz#Z™id©mŸš΅hή©*ƒfγi₯^·΅ήΣ…±ΧnΏM?ljr^]Σ6ΫΦΔq²ϊ₯Fτ’|±Ά„ηŒΔ_ikN²3rŽ­Ÿ=Τl7ΒΒκ(žω IDATZo­μg;ƒ1:žΑ¦C¬ϋi†‘Γ‰V τ>χğω9ΙΑ ψήΝ–ksΫΊ΅ώ»υΊΤΦ~³‹Ϋqγc“cBr­G»λbϋλ»BQ«ΛŽs”ΐρΜ[ΞW/ύ‡υΙω””ζ“Άϋg~LΘοΔ€KG΅Wa΅VPa­ Βj₯’eς€,ΎZΆ’}ω%eleωΗšξΜ_‚ƒL€όώ ‡ ‹(,λŒ'ΊΉ=‘^I_°2©7Ξnrš–ΛΙ@ΤΰVσ›y8#"PΌ<<†δΥkΘκ;„ώ]ς&/-dK/οIvΒ.jowχ Ζ§pΏξΚ’ η λί}‡΅υo> ΟĈ=|Ήb¦qθΣDνR‚Ζ2ep6_½ύ9{σJ(ΚψΛΧr΄-Λhe[)ώ˜3©Šoήψˆm™Eημα‹ΧώKjόL΍:u—CΊ¦-θ€ύπ.+χζP\˜Βϊ·ίc“ΫD¦Δ7ΌΚΪήςl-VυΘΎΪ°›”œB ³ٚXˆG·ΰNx•^η_=ŸΐΟςπ;k9UDiIΙ›—σψ“_£ΜΌŽ »Σ;ΊŠ-ί|CbA)…ι[ψpωzŠjW©ΚϊΤ•A3ρ΄R―ΫSο»rϋMΉzΑ[_ΰŸ/~CBj%%…δΩΝ–ύyθ]6ΫΦκ;ΉύR9%ω©μYχϊΛΏΩs-·\8~x—―φεP\œΞζχίcƒy<ηΖ[Zo­μg;…©?ρύ ΨΆ½„ψαύκhzŽbhΕolΞκΓΠΈζ·EsZλΏ[―οmλ7Ov;>n=Ϋ]Ϋ_ί…BˆZ]ψςg?ΞΉλIͺήx…χώq59εΰΗωŠοΔehYq;σVΤώΰ7υ1>Ί}Σού'OΏΔύΧ½ !C˜}ύ΅œ›ΆΎ‰yx0zαŸώψ{ά}υ2z]υ9Ί’-ψ1ι’€Όq'ο±β;žΎ‘n Υ{>A»Λσ˜Vb-aηΗ―°,½»)€θ3ωۍchσ«Η›₯cκs%O=Μ²·?ζ_·ύ…UN°tgΒ΅OςοΩpW5t%ˆσoΊ•O½Ν_―ySθ`¦]{dPW./λΦζΡUeМΦκu{κ}Χm?sί%<σl0o½ύwΧΛWƒ»ζάΛΘa]Π6ΫΦη€υK+˜,ήt‹ŠcΤτGx}Ξ4gΝ•Ϊ6ΔaŸnΙ‘άΙ²Τ ή“AAΧTvN­ρzΆ²Νšͺϋ-ΕZ3½Α ΈΚWUq؝tJ“ƒ³Ωšω9χήΌ mΡΣ<43šΊ΄Β`Δbq½Λ^?mŸ@YΣΈΜZ™G—A“υ§ΕzέΪηυΦM?yΫOQέUηl­ν1vz8•ύ’Žι¨ͺ‡£ΡɍVλ© *ŠΩΤΔϊΡ¦vΠό~Ά“YkΆΰa{UΝ2kέάpSԚ~Zάo4ά·ΨΧ”sKν‘-ύf—΅γ揗Œ–šγΪ˜ΪΊ―²j₯Ύ !„Ν;ο“—Ϊz₯_Ηi«¦ι‹'Žj[¦¦³Ά7σ½Žj)&Χ²6›λ‘~΅ͺj0Ε©©Ψͺ[{Ψ ΖXέTŒν(']ΕVΥ(6ΝIueg–jse©α¨W†:ͺΓNUƒB΅5xސξ°SΩΰσΪω4\ίϊΫΖ–z„K ξJλΛ8n[ι ηήBkM”o‡iΨ«-§ΕΆΠD\ͺƒ†a5K:Ί¦b―Άqό )υηΧήςl%Φ.k+΅‹V±Ϋjζ4ƒ{oίΙMO>ΘΛ!Οrϋ˜š{W5{΅Ϊp½λV{ΛΊ©ΏŸΒ2h²ώ΄X―[ϋΌώΊΔνwό§§¨ œFύRƒI[«§5k₯ͺM¬mjΝοg;GΣϋ{PmΆF―|ma{ΈΎΡp?άb ­Ά‡Άτ›]Ωο7ST»/:nΧΎͺ₯ϊ.„B΄¬ ‡χ Ρ”*vύ)ΉQγΣ SΙN–/[‹>ϊ Ϊ(κΣ5όΞΉ‹Gί°ύh κBNκ+8„8SΙ~V!„ΗHχ/N2#ξŽdV>/΅’ΊΡϋ¬kxθ¦1x)-ΏBόοΡ5zŸ·€~h8§ςΉ BœId?+„BˆcΪxOΏΗ`Ά`1)jί·¬ͺΨNyQ›5w_Ί+€ ΄Fφ³$Rί…BœΈvάΣ/DηΡvͺ›ΈT΄Usχ₯ ρΏBΪ@kd?ϋG"υ]!DǜΊ—— !„B!„’KI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόAI/„B!„BόA™Nu])­xοl»w“sγJ―n#NuHg€κκ*Ž€%“_K·ΐ`zΕφΕΓΓσ”Εc΅V°sΧV† …·—χ)‹γd++/%-ύ0₯e%hš†ͺjhš†Ήώ―ij£ίx{ω0φμ vλ²8«mΥ€₯¦ΰh>έ»έw.[^}W_»]Χ>|$KΊ†wή}›;Ά‘( Λήz€Δ „B!Διδ‘τλΊΞΑCϋ(,*hπχofζψΕlΜzΧάΜ¬Π‡0™L躎λ„…Χ0Š’œ’ΘΟ )©Ι„‡†1lΘ²²3I:”Ȑψα§$«΅œ_·l ~πP6nϊ™sΖNΒΗΫχ”ΔR]]MZF2ωݏKnΣ3RθΧ7oŸžGfV&Ώnω…]ά‰‘5”šv˜ΠP† FvNΙ‡2xΰΠ.[^­%Χ,βΎΏώnέΩ‘°ƒ΄΄βϊχγŠΛ/§°°ˆ%Χ,❷?θς8κΣu€δύ-ΜoqΊΰPzχŒ;­χEΦJ+“\λFΏ~qws?eρΨl6% +;ƒ°ΠHzυκϋ?uP!„’­N(ιί±ξc6}σͺΣq쏺€ΕΓ‡) ώBί‘“;%ΐΦθΊNb^Ό}Ό7£Α€’((ŠΒKogΣ;d()–οΨtp7#†!00]ΧQUΜμ4φμΫΙΰCOλƒνS-7/‹αCGPUU‰Ÿ―Ώεl>%I…΅œMΏgΚΉΰγγKP·`V}χ5“&NΑΧΗο€Η“š~˜Π0† NvN‡'?hX—-Οαtb΅ZΡ5ν„ηQZRŒΙdμp,v»#©ΙδζeFLžxzzŸŸΓΠψaX­εX,frr2λ’ώςς2vμάFNNQQ=>lž4jDQ cΖτ™8NFŽ‰Σ©’λœτ6λ:‡οΗΝ͍)“§άβu]gβ>ήOŸ^NΛ}‘λdΫF&M8³ΩΒΑ€ύ$&ξe萑§,¦ΔƒϋˆŒˆ`ΤΘ1””σΓκοNΩΎ@!„βtvBI–οή$nμtň¦©UCΣTœΆ ~Zώ8!QEτιμxsπΠ>ΊŽΣα@5(  †c+¨=„ΆZ+πςςp Φu"Γ»c2˜Ψ½7!ƒ;'‰-++ευ7^γHj*gŸu6³/žƒ·wΣWŸ*++ωό‹OΩ²e3=’{pέ΅7Π)qt¦Π0’’ πδ`R"αa'=† k9ΏlZΗωη]ˆ§§₯₯Εx{ϋrΡΤ¬όϊ Ξ?o*ΎΎώ]²μj[5™G(,* ΐΏΡέ{βξξA^~6Cγ‡QUU‰――9ΫΆti? ί@vμΪFYYi£aϋz³Γω„††1φ¬s:Λα”$ΒBÈ<”ςς2Φo\ΛΩcΞΑΫΫ—ΰΰvοέIP· S  ΄¬„οψ†‹g^B@@ ιμΨ±•sΖMμp<Γ† '!a;Σ§Οβ£ε²vέZ&OšΜε !a;Γ†ΌU„‹qύ`΅Vΰ¬’΄“ΙD\ΏHΪΗ‘ΓθΣλτΊβ_a-gΣζ œξxxxRYYAΟΨ^|ϋΓ·§4ιΟΞΝdτ¨1TWWαλλΗτi3ως«Ο»t_ „Bq&:‘€ίa·αΤt’l=ξ3_nψuηΓ§―­»ϊ ώ‰ΙβΞΈιΧ3lβΌY|Gσ ₯¬Ό£Ρ„ΙhΒh2ajbՌF#ŠΑ€’i¨šŠ΅²OOrr³:-ινυW0›Œ\xαω€€€π―Ηδχ=x\βo΅Zyμρ‡ιԍ /Ό€Γ‡“ωΟ―πΧ{ή)qt¦~}βΨw`/»wο$2"ŠAŸΤεWT”±ρ—΅\pώ4<=½¨¨(Γ`0RQQ†··/ΟΌ„O?„iΞΐΟ―σOšdd¦ΚΰCΘΝΛ&%5™ύJrrώώώ$%$¬‹O†xxx3yΒω 'žjš†έξDλΐh€άόl†Iuu>>Ύœ7ω|ΎϋqΖM¦Oοώ$&ξcΛο[ˆ$ JΛJψφϋ―™7g>^^mΐ‘䃝–τ_wν ύόγ.Ϋ!„Bœ‰Nθιύš•Φ²&?++)Δ©™ ξ;™n½'Ψsώ1γπ‹>ίξ£ρމΙ?– _½‘ΐλbΡ4ά,ξ€g€“–v„”#Ι$''qπЁγ¦=’šBJJ2)G“šz„΄΄TLFS‡ ϊ²³²ˆνKQa!½{χ&ΊG{β***ꦱZ­<φΔΓ„‡‡Χ?Žβ’"bc{’Υiqt&³ΩΡ#Οbώά…œ5fΛΙy(ΈώυΏόά α7™Μ¨ͺ“ΙLEE^^ή\:g>_}³’’’’N!Ώ —А0ͺͺ*ρρφ%7Ο΅ϊφιOqI~YΑ`d@ά N_v}š¦Q]m£²²ΊΙŸάΌ|>ςSrs󚝦ΊΪή)υ½[`EE…θΊkyxx2υ‚ιόΌn5•ΦjF ΝάKζ3fΤYTZ«XυνWu YYŠbΰpJ2½{uήh Χ^•‚‚ΎTVVαtͺšτ1‚#GR  !''›˜ΨXztοΞγO>‚ΥjΕj΅ςψAŸΎ}ΘΞΙ&8(„#©GNκπγφ¨¨¨`γ/λxΓe¬[3εεε'eΉεe¬ΫψSΟΏ¨AŸ››ΓŠO–““sμ`ίΫΛ›σπεWŸQ\άΉϋΑAΑ€€$SYieοώ=„‡`6Ή1rΔζΞΉŒqƒIHΨΞg_,gσ– Nςœ ee₯¬Yϋ=Γ‡η‡ΥίRZZά₯Λ‹λ7u~&??·nxzx2γ’YόΈfωTVV“ŸŸΟ7ίdώάΛπττ’€ζ™ιι¬ί°žΓGuZL»wοdΨ°¨ͺΚΒΛ―ΰ•—^cαεW ͺ*SΞ›‚›ΕBTT=ccπττδ’Ω³ΉόΚ+ΩΏ?7όi Χέ|3ΉΉyŠαpJ"f³kΈΎΥZΑ‘7ί"ωˆEQΠT½ζφ"]Χq3ιo4Φ$ώ―PQQΖ€ώ1ŒμΩ·£s ζTT”±α—ŸΉ`ΚT<=&ό›6odϊ΄YΈ»{²ψάέ<Ήhκ 6ώ²α€ν „B!ΞD'4Ό_Υ4JK‹pͺNrŠ|τΑrŒΖ–g§ͺN.Ίœ O3Z']Ε4 Ε`ΐιtb4šPP@§ΙDΎ¬Ό £Ι€ΓιΐαpPYU‰ͺv|¨s} .»‚‡ΎŸ4·4bcbΙΝΝ‘g―ž(ŠΒc?Œ’(DFEΡ§Oo²²2‰ŠŠ"%%…£GΉε¦Ϋ:-ŽΞ΄gί.b’£™0~2)©‡IΨ΅ρ4$»9εe¬]ΏšιSg6HψsrsΨπΛzΟr!?―]ΓΔ “ˆ ΄΄__.XΔ»οΏΓ₯sζΠ9―₯λΫ‡ƒ‡Ω—Έ‡πΠϊχ\Wum6ΰ`{Βvb’{0aό€“VF΅ΚΚJXύσχ\2kλJgP0+>YΞESgΰοΨ%Λ΄X<8oςω|Ώϊ[F<‹ΠΠΊ!Φ³g]Κ?ϋ˜³ΗœΓ/›ΦsΩόxzzQ\\ˆΕb!=#Υ?ύΘ—/ΖΛΛ§ΣhλΊNQQŠ;vFςαd&œ3žί·mCΣ4***κΔχ_―€ΌΌœέ{χ αaΨνvΎαzΎ[Ής„cΘ+ΘeΚδ©„ν·Iϊηύ σρΑ ¨N'Ί^οω ΊŽi˜…^ΐ‘FU5boΌžΑγωόΛ?θδΏf΄Ό’ŒυΧ0υ‚ιǝlΫψλfMŸ§‡švjG"躎‡‡³fΜζ³/>m°/πσσηςΛΰ½ήνΤ}B!Δ™θ„’~MƒJk΅£Φu£ΡDqqa‹ί θ†λ5WΧOdΙMΕ’aP\Ifω>ήΪ~'žf_&Ζ^~ά΄Ϋ Ύΰχƒ+π13)τ: •έpvro±ΈρΰπΰCDΧ‘OοήδζζΠ»Oo,nn λΔΔD“MDD$‡";;›x³ΩrΚ†τVWW±oΩƒΈώρρq½ /==…I&QUUIp·`~Zσc]B[RRΜ/›6–žJ―^}8gά„Ώ6«ΒZΑΟλ~dΖ΄‹\eΜΙΝaύΖu̞5o/_ζΜΎ”O>]Α€ “‰ˆˆ °°€ΐΐ /ΊŠ·—½Ιε—-"  γI―ΙδΖ°!#9|4ͺͺb·;ΫN-•QW*++αΗ5ί1ηβyΈ»»Χ<ΰΠ‡Λζ]Ξ‡ΛίcζτK:₯ ΣuwwO.œrί|·’±cΖFYY >>~̝3wή{›«_ƒ§§G σλnΓωiΝj-ΌΏNM?Yρ)—]>]Χ5j4nξ^<υο—xα•7P…?x‡ΓΑΧ«Ύ"??Ÿΰ†·—7‡"##‹»οΌ½Γq( 8φάq#‚‚0+ ͺΣu‚T―Iτ5MCS]£ŒtMΓ’λΔ:όϋ?Ώj1>ήΎΨM?ψ―+•W”±nΓj¦]8―F †MλΉxΖ%hlά΄Ž΄΄T’"»3lθ(|||(+/cλΦΝ$§$˘Ργπσ=ρ'ιWUU’th?Ω9Ω„†Έ^θει…΅Κž½;ΙΘL#2"Š‘ρÏΫ=Z@·nA,Zx%Λή}‹Λζ/€[`P'–”B!Δ™γ‡χ»χڟZΫ~oρ§–+ιοΌ+ύƒ‡ΓΙςέpαΨ9\tΞ|ΦeΏuά΄Ιʏ\5ν.FŒʚΜΧ)//Γ :5ιΧu³ΩΒƒΜ»t?­YMzF:&³™ΌόlΌ½½Y΄p1λ7¬νp,pμŠ~ee56›£ΙνΤ\u₯²Ύ_½Š9ΟΕέݍ’’B@§°θ(ξξn,\°˜/W~JQ+'γN”¦ιxxx2}Ϊ,Φ²žΜ¬, #EExyz±τ¦Ϋρςτ"??³ΩBzz:?ώ+Ί ᨬ¬ζγεε“ŸrΧwσΝ·ίσδ£σΒ³Η+Ο?K…ΥΚ7ί~Σι$&:_v$lΗZiΕξp²οΐ.œr~‡γ¨­ΊcΦuT§§Σ‰Zϋ£ͺ¨ͺZ—τΧώ˜j†ό;UUΣpœδ€ΏΌ’œ΅λV3ν‚xyz78ΩΆnγ:fΝΈOOoΆ'l#&:–k–\GϞ½ΨΊύ7~}3½{χαφ₯w·O?~ύuc‡βILΪODD—\<—¨¨ξμΫΏ€={ˆιΝβ…KˆιΓΆ[›άδζeγλλΓ’+―ζÏޣ°°kځB!Διξ„’~U§¦βT]?΅FέβO-§ͺ’vρ~έ•~‡§ζ ΐ–L»X8α^ΖΗO―›ξœψ©,YΪ’Λ7£k:U•U˜ΝζNMϊαXβΐύ“CZz:δδSPΏii©deeρΐύŸς„ =#•˜˜Xͺͺ¬ψϋϋsιμΉ¬όζKJJŠ>l$ωωy|Ύς3ƒΡ£Ο’¨θ(+>ω%W^C€Ώ?™ψϊϊ±ožN‰%ΐ?ΠuRΖ` +;‹uΦqΙΕ—’i:λΦ―αέχίdΝΟ?’ι: .»‚W@Fz:‹ωωyψp$υp'”LΫ4UF]©΄¬„ο\ΕάKζγζζNaa&“»έΩl!/?ww7]qύt9…EG»$MΣρτπββ™—°nΓZ2³2jξύΞ‘ΊΊŠœά,,73X½ζG/Z‚o$ό΅jXh³ΩΩςϋο8|½½‰ŒŒdηDEE^zν-*+mτμΩ‹Ττ#τξΥ“Όόl6{‡cp αw­Ÿͺͺu Ώ³ήOSΙΏ^³RU'šͺβ°w<–φΨόΫFzφμ…§§ee% F #?¬ώމηLΒΛΣMΣIM=L―ž½©ͺͺ$$8„δΓ8”|~}ϋSUUIxX8‰χw(žμ¬ ΊGυ ͺͺ’ΐ€@3RHMO%&¦§kTMpGŽFΣtΌ½}˜2εΎXω9n7,f72³ρφρa@\Ÿ~ώqG‹H!„βŒΤ+ύΗ`k΅ύJΏ³Σ―τWWW§_ΜO`WΚ&ΆY?`LΏ κ¦ μaf[ΕϋμNω•δ„\’Κ'£λ`6[:=ιׁΏέξΊ*¬@ݐ^U=φΰΐϊӜja‘ဦ¦ΰp8ΘΟΟΕΣΣ“Λζ-ΰ‹―>£ZΕ”s/ΰ–oγ‚)S©΄VρъXrΥΥxy{“š–‚Ρhΰ@β~ββv8–θξ18°UUIOOeέ†΅Μ™})^^>lέφ±±=ΉαΊ›ιΥ«7›·lΒΗΗ—Ε‹–πÏߓx0MSωα‡oιΧ·'”LΣ*«*ωeΣz–½χλ6όŒ­Ϊή Œͺ«μ¬όκsžρV}χu§>Ψ―΄΄˜οΎšΉ—ΜΗbq£ ΐu%=#+“eοΎEffnnξdegΰζζΖΥKώĊPXXΠi1Τ§i:^žή\zΙ<ΦmXηZΎΕΌό\άάάIOOcυκΥ\Ω… ΥΧ.fΙ5‹xα₯η(+/γ…—žΓέbβ=ΞυKο@Qΐf·ΊOΏ`έκx EΗέέMS9’‹xύΝγG ΅‡k¨škΏX{uίιp4y΅ΏφίZ½ύ‚λdͺσ€οŸxΞd&r8%£ΡHUU%f³‰+\ɚŸWSXδΊRÎ„ν”––°~ΓZzΕφ w―>όφϋŠ‹‹ωρ§θΫΑφΑώ{)//γχ­[θιzE`ξ=Ψ΅;²²R6nΪ@LŒkTΝΡ£¬ϊv·άx+f‹…²ςR<ά=Ω΅;»v²pΑŠG!„βLu‚―μk8Ό_Χu***ˆŽŠ₯{Dt³?999TWΫ\Γϋ;ρA~N§“Q#G2mτB–}ŸβC&v&μbKι2¬Ÿp΄ϊ ;wQ”dώφξ;ΌŠ2mΰπoNOο€@Ίt€Q@EρuΡ IDATWAAPD±a]ύμu­«ko« ’(vQͺ@Š‚€Τ$΄@zBz;}ζϋ#…Π$=Ÿ›‹+ΙΜ™yŸ™3Ι™ηmΓΥα―2τόρŒ1²IZϊ‘bΖϋη^xšΘ¨H"£’ΘΝΛ%8(˜ ΐ ςςr‰ŠŠ&**Šη^xΊΩgz?•~}ϊ³jΥ/ddT΄Μfd¦αειΙ”ΙSωϊΫ/ΘΜΜ’ΌάFFf&Ÿ/œΟΜoΒΫΛ›C‡φγιιEΚ‘#¬‰gΨΠα Ž₯ηω½ΙΚΞβ›οΏβHj “&NΖΛΛUΥ8tθ;œ‡ΥZNXhϋχ'‘ͺΎ>~ΜΊi6yΉω̝7·[εΒQ οͺ}:[ΆόFTt³oΊ•ή={ρεWŸwŽ|6—#FπΰΣ½[·FjPTTPρΌϋ‰“1›Mdgg`2™IKO#>~Έb"Ώ¬^Ijj ORR“1›Μά<λζ/˜GnnN£Δq"UΥπφςaςΥΧΏ6ž”ΤT|}|II=ΒͺUΏpγ 3πυmš„Ζ™ΧσπƒπκΛ―₯s'Ž9D—ΝXψι'|πΦλΨl6ςσσ Βl6qλΝ3=φξžs+z½??\NΌλvόηέ,ψba½c©¨ΠTqW{:eίι<–τWώWOHψαXEAswο·X*žΎ°~γ―€e€a0ΘΞΞΔΛΛ“IΧ\Λ·ίEAAϊ$+;“…‹’θt <€‘C†‘‘‘ΞΗσώ‡‚Β¨£On½ΘΝΛeιŠ%θτzzχͺ˜Τ°_ŸώδδδπΝw_£St\ΠωωΉ•‘7βννΝαΓρππ"ωH2K—,eφ¬Ϋπυυoπ9B!„8)ηΎ¬­š4§N=>σμ¦P b"Ώ”b/?ύ I›Q˜ΆΥUϋn©Š’Υu$ƒ&>^§ͺό°ψ+.7žνΫ·²aΓΣqγ (ς7t±΄ο LHΗ}0Kr/τiίΎ=ŽE―ή}XψεgL<½^εŸJii)Ο½ψ 1QΡ΄mWQΩEZZš11Ρdd€Nrr2©©©<ςΠx{7lΌ†P…ςςΎόz!C%4,Œ’bb’ΪRZZΚǟ|ΔEŽeωŠ%ά4cή>>8°?__RΣRYΆb9wά:?Ώΐχ\P£Ρ€^―ΓνVq:MœΏv%!ΑmˆŒˆδχΝ›ΠιτŒΉψ3nΧΨζ͐[gίA^~.Ύ>Ύ””–2χΔsδνMZz*žžΌΏxθGTfqq1?ύό“'MΑd2‘™•ާ§™¬]»†©ΧNΓΧן’βζΝϋˆQ£.¬œΝΌvνβ°ΫνΌρζ™9c6AAM3©™N§PRRΔ' ζמ}ϋφ1sϊMψϊϊ7Y—ώ7Mγε—^!44 ƒAΣιΒh4ΰrΉΙΞΞβšλη‘ϋο#.™thί?Ώ;)ιGτ =3‹€Δ$<=½ΨςΗ6^~α₯zΕ²rυΖ]|)GssXݎŽz=fέρu«Uλ«ωθ>¬(τά½0ζ}ς1snΏ·‘§§Nt:…²ςRΎώfƒ &,,Œ²²R"Β£()-eώ§sΉfβΒΓΓΠλυΗMl©( &“α€ευuΊύΈ<#3‹… η3³ςwξPςΚ §–/_Ξm·ήΏ`‹?m@!„’%Œ^τVέfοίόσΫΨφ3νΓ-@QυςA°α› Ž»€φή‹ΑθTά`»ηΣ*–h•ίU.ΟNήJiIf½’’UΝ…¦¨\0hT―™\ρ₯ς1Ν#Γ€0`Θ±mͺ㴏χ«―Rž}ώ)’££‰ŽŽ&55…θθ:HzZŠ’ΰpΨ‰‹#--Ά11hšΖ³Ο?Εc<Υb‰Ώ¦ixyω0iβ΅|ΎpC† %,,ŒCΙˆmמo˜ΑλoΌΖ]wή‹··ϋφοΕΟן#)GXΎb9wά~W£έXW {8•A ζΧ λˆ_»Šσ:v:gΑ_mΧΨ"Β#IHΨƒ€?“χΧΓ ηΘ›}πυυgoβΊwmψ°‡»Άsε•1M€₯§ΰεεMZz:kΧΕsύ”πρρΕνvγλγǍΣgςΑGο3zΤh"""8p0‰ΈΈσ˜=ϋV~ϊωg›2­ΞΒΙTUΓΗǏ§ΝδΛ―Ύΰ¦oΖΗΗ·Iή½ϋ°}ϋV.»μ >_ψρkβ5rS½Žyσ?A―3PX˜NמΘΘH²s²ΘΚΙΔΓΣ“ΰΐ`ΚΛΛyψ±§1Œ””–ςο矫w,N§§Σ‰’(΄αY?ύ,Ρv;ζ―©™θWq© =€’ΣcwΨ›½₯j ՘p _,ϊœ!ƒ‡T ύII&&Ί]'cL;©β¨ζ#,ΓιφWsy^~.Ÿ}>Ÿ›fΜΒΛΫ›ύ•‘GŽaΩʊŠHIψ…BρwW§€Οζety#^~!ΥΛͺgͺVU¬Φ2²c³–V.׎›ΙΊκ«FE€²όΖψΟΦϋTUΕεv“ŸŸOŸ^}ρφρΑh0b4š*Ώp:8]Ί›r—“’ΆύΉ§ΣΩ¨IβŸ~ <,Œ¨¨(RRΓ‘ΓGHKOγαCU5^ϊχs¨ͺF\l;RΣR‰‰ŽΑaw0˜sGΓV_“aω2εΪλψdΑ<† Fxx8ϋ$Ρ±}'ž|ό\.' I»ρχ«JψWpηwΠL7ΦތΏτ ώqωUšX_C† γ“Oη2lθ0ΒΓΒΩ·?‰Žjž£=ψϋω“š’Bόš5ά=ηž—yπΰ~.}1iι)xxx’žžΑΪuρL»n:ͺK–.fίώ$ΪΗu`Ψ°‘άG΄Υ†ι4ΫT%ό!άKπΥ±Y»š=Ξ―w Q5TγΪk¦°ΰσω 2”π°pΪOϋΨ̘~όο=¦O»‰ΐΐ ‰   €ŸΝ㦙³ρςφnŠH!„Bˆ³Y’ώΠΈ>”—RTP@iq V'υ5'§«ψ UIΏV³Υ_«ώ‰τ[±xΥ΅ή‰wΕδx.ŠŠŠ±ΫνΨνv’“qπΠA:΄οH»vνj,λP=ρSQQ1N—Υέ8IΏ¦iόΎy£FŽ"''‡ΘΘ(Ž9BJj*wΟΉ§³bμξ=w“Wσ2ͺΫMl\,GssˆkߞeΛ–RPP€ΕbΑΓΓ£Qbͺ«ͺ–Ϊ»‘η}Θ°aΓ‰ !i1ΡνH>|ˆŽ©xόΪ]sξmΆ„ °°€_Χ―!1)ŽΞcΔπ ρχh–²kςφς­Σ9ςυ hpεD‡Hά—@€Ÿ?‡$³aΣFnΈώF||όψiɏtιΤ™+1={wΏŠ«œΘ­·άΞoΏΞΠΑCiێοO·nέ|όωμ;°—Όό\άnUu£ΊUάjΕχΛ*žEοVOψή­βVέψωϊ3ζ’K kP,ο}π.έ»vΑ`0pωψΛyε?ζςρ—c0ΈεΖιΌσΡ\¦NšΘWί|Ρ`€€¬ “ΡΐΤΙ()-EQ 1θ θtL¦Σ₯ηgΦ―Οlϊm=Ώmω>½ϊfς$άn7©ΟΏH΄νXβ_u%8‹… {ο"ΰκ«1›=X³&Ώ.;§Σuš’šVUΰuS¦1wώ\†­¨LΪ—ΐy;sΕWςΛκ•LΊϊΪ‰`ΣοΈώΊπφς"!q7ώ€€€°lΕςf­ˆB!„hνκ”τ·λ6” Λ?'"Ά[iew}­ϊφT q­ύ•έϊ+r•œτύLΉγ…΅΄WMδWTtlΈΑΑC‡˜rνυ|φω§μά΅³zω€k&σνwίΤHϊ‹p:Φ_^^NΧ.]9pπΪw ωΠ!RRSΉρ†™X­64MΑd2αp8ΉiζΝ|πα{8œN:v¨xmxX8EEEΥODhΙΔίΧ׏7ΞβύίeδπDDD°@AA!IIaΕΚάsη½4ουΊ_ΧΠ΅kWž8‰]»w±*ώ&^uM³•_EΣN>GαUη(0„””T–―\ή¨ηh@ΏAlΨΈŽ₯‰ Δ΄mˌfVOp˜””ΐ„+'b΅–Ε’―ΎδWLΐί?{ﺏ•Ώ¬δγ>¦wο>ŒwiƒβpΉ\$ξΫC―ž½ρσυ;εž3―‘Έ—e+–pέ”0κτ§¨š¦iμάω'Σ»·ΫΝΤ)ΧqΝΥ“«Ητ5Š~ϊ…_}Η„+ΖΣεΌσ°Z­όϋ΅7ΘΜΚ‘ Ώ›έA`` ΎΎ~xxx ΧΧ/‡ΓΕ CY·~ ›~ΫHΏΎύžt5nΥΝ‘§Ÿ­˜EQ¨::Ž »ο pDΜf3kΦΖΰΘψΛώΡb •cC5nδΐˆα# #i^Ό½|9ΨΔ=FΞdοή]LΈr{wγηλWρ;·bY³WD !„B΄v΅Ύ»Υ4˜NύωvήΛ χ$$,t:E‡’SΠ):Ptθt:ͺ&ψSՊ–m΅²υO­lεS57©ώΔ;0†¨.Υ“3ΥGΥcπŠ‹Š«—uξΤ…ΰ nΎιμv[υς’γόβ’βFνή―ͺnƎΉ„Ε?ύΐΚ_V۞ΙΧLΑ`0a0°X,X,EAQfέ4›Ε?ΐς+ α²K.«žύ»₯©ͺ†Ÿ―?³gέΚ;οΎΑΘ£ˆγΐΑ¬XΉ’ϋ€€ fΏ±ή›°‡kž„ΥZNtT ΏXΠ"I?492›-Œs)—^2Ύz’B«ΥF^^a‘αlΨ΄žvmΫ²fΝ"#"ΙΘΘ ((oo?&]s-SΪΰ 5MΓf³RRZBaav›UΣ*ž3―©¨ͺVωU­\V±NΥT4UCΥΤκΧfdfΰrΉ°Ω¬xyyΧλo@Uωωω( lέΆ•ΠΠ0²³³θΫ§/ωωωτzΎϋβs¬V+V« §ΣEpHK–―’G·.άΟέΔΔΔΰεε…ΩliPK?T$ώΓ‡Žduό/¬ίπ+ϊ_@ΠΥπΉb<švlςΎͺz½ƒΡTΡΒοΘ?˜Πβ ?TTξRZZAΓY²l)Γ‡ %.=;vώITT4ΉΉΉψϋϋΧ»¦!qEEΕ°ξΧ΅DFFpΰΰAV¬\Αε—^AAA!N§»ΩγB!„h­κ”τkθι;fkΏ{‡€T°Ι» /½ §Σ‰ΙdΧ NNͺͺ’Χλkι/-+eΕΚe$$ξΕf;–τλυzΪΆm[ύsQQQΕ3²U•œœΪ΄iΣ cςππΐΟϟkžŒΓ᨜ˆKΑl6γλ닏/ŠRρΊτz=“―™ŠΫνFΣTE‡ΩlΑΛΛ ‹Ε XƒΥj£ΌΜʘ‹/ε»Ύ‘K—.μή΅‹‰&a΅Ϊ±Xl˜Νζ3ο¨ΨνvςςςˆˆˆδΧυ눍mΗͺU«‰ŠŒ©Nn›+–ššσj’Β²²2ΚΚʈŠŒaσζΝότσb‚ƒιΡ½'eeeX,Μfs£MpX•Δ„°ιχM8μΆ“»οŸ’+ΏZσϋΚ^^ήτξΥ§:q―oξΫοsϋœ[Ρ4Π°0:wμBβώ>_ψ9Š’pλμΫ0™,X,žψωUT8,Zπ)Š’TOΕ,#:]E₯e}+ k*+³·OΦ¬[ΕΊυkxΑ ΜfΛq šVQaιrΉX½j5ήή>ŒΉh,εεΦκΉHZRYYεεεc·;θή₯;lΩΚςε+ˆŒˆb@ (//Ηh4βηηΧμqulί‰ί7oβϋRρρρ₯o―~8nŠ‹‹ΡιτΝ—B!DkUλGφiš†Σι ¨¨ˆC‡’——Χ ‚ύύύιΠ‘#ώώώ¦zέh'$μeΧξmΨμv6oήΒχί€Υj₯¬¬μ€ΦLEΡαεεYέmώεW^‘Gξ˜Mf.0„.]Ί6θ˜*ΚPpΉ\8@ΓP9™ ’Τ|’Α±Χ9Nάn:½ή€ΡhD§ShΰποF‘ŸŸO^^ydff°εΝτλ;€ˆˆ‚ "00°YcΙΜΜ`ηνdegJ―σϋΩ¬±œ*–:GŠ’ΰv»°Ωμ8vάn7z½£ΡŒΕbF―74κD‡œ”••6xhŒ’θ0™LxyyWώŽΤύo€Ϋν¦ΌΌœb²³³ΙΛΛ£ΌάЧ§AAA„††βλλ‡ΩlA―ΧWCUQšΖqε6NΒ_‘”Z­V[ΆώNjjJu…IUň¦jΈU7šͺΝ…£.Βdͺ˜ΟΓΣΣ/―ϊO(Ψͺ*Ev» ‡ΓŽͺj˜LFL&Sεί6Sυλš;.§ΣQω·Φ^ύΔ“Ι\έ[£ΉγB!„hF/z«φI?λJοr9œ”*  Fτz}吀ΊΛΝ=J^^.οΌχΦq­ύ΅αηηΗν·V{PP0ΑΑ!gΨ’iœX!ΠZT%”V« »έZέk6{ΰαaiτ„²6±4Wr[ΧΈZϊUδͺ5V­Ι©ͺnιU-τυ₯(JuΛz}“mMΣpΉœΨl6ΚΚΚ±ZΛqΉά z<<<ρςςΔb±`0Τ―R‘Ύͺ*#l6+.— ·»’"°ζπN‡ΑP1q ^o¨T‘πWUP΄§:w­!‘n­q !„B΄uNϊαΨ UCξΛr#^3Y0›λ~SμyΟ§~vΆ¨Πœ εΩKM­5Ώ‹šηψJ΄Φs­ž|ΐΙρΙu#„B!ΟθEoΥmφ~hœξ―ϋiψ>j&κV«½α;§Tυ†Φ 5ΕRSkλο’ζωo-Iσ‰Χ„\#B!„’%Τ―_½B!„B!Z=Iϊ…B!„Bˆs”$ύB!„B!Δ9J’~!„B!„β%IΏB!„BqŽ’€_!„B!„8GI/„B!„Bœ£$ιB!„B!ΞQ’τ !„B!„η(Iϊ…B!„Bˆs”‘ζGf£ΣιPEQͺΏξή½›ήύz7„3ΫΨNχξέ[: !„B!„gMΣͺΏjš†ͺͺ„„„V―?.ι7 θυϊκ€Ώ*αΝΛh4ΆtB!„B!ΞU Ώ¦iΈέξγ֝2ιΧιtθt=k&ώZ3„+L&SK‡ „B!„β,PΥ―ͺ*ͺͺžΤx\―ΧλOjν?~oM¬¨`0Ξό"!„B!„NΫΚ'$ύ:ξΈ–~ιήί2τz}K‡ „B!„β,Q5–¨ώZε€€_QIϊ[XΥΠ !„B!„βLjNζwb>yR?ς'ρkŠΔξf>ϋσ,F&t{σ‚6zg3©lB!„BQš¦ύεdόΗUœψ‚Φιίά?ξεβ & „eςυξηmΏηΒ?!„B!„’ΆΞ”Η·H?ς£ε)Δχ$,:ˆδόν-‚B!„BqΞ«Ϋ4ρMΥ- άB!„B!D£;Kž WΖΪfρζΞΛ|/z”nλΥ B#oιs| ŸΓCcό‘ωB!„B!Zƒ–Ο—kEΑhΠwέλΌ15}ε2ΝmΕκt·|G­ŒΔ=ΙΠWfέB!„BΡzΤ)ιoΘDs©E{ωί–9˜ ^'­{hω@ΌMALκρ8ƒ/8ΝΕIΉ½Ό2ι?6υfMfΥΌωvS2ΕΖPzŒ½ΩWχ$@Έςωγqσ$œί|Δ’½0ϊΙטΦα0Ÿ?π?t“.¦π‡ElH.Η;nΧΟΉΛκψτ—=䨁t»t6wN’Q΄σ;>ώr‰)9”θCθ6fw\ΗΎwανߊplšΙ5oιιpύxξͺˆ–™0A!„B!„¨Τlyι‚ν1nΘ.>…N1½ͺ—wΐucξ’W―,N|ν {QQ΅ͺšh%lωπe~pŒε©ρωΏ§ΰχλΌ»κhe…Ωόςή·”\τ$sΏx—;λ+–k©,ω"wΏΓ— ^ζ*ΟMΌθΣ,VδΩΉ‹˜χθ`Šό„₯‡έ€‚—_ }'=ΔkσΎβ³gΗ‘­ψˆχ{3ψΞη™ήΕBο9Ÿ±δηŸyύšhIψ…B!„B΄ΈΊε¦Zύ»UΩΆ€«0aΠmTΝήΧΎ{G\8P² —Ϋyϊ}ΰ&yΡ#̜6ιΣ¦3}Ϊ,^ίhC+ΨΜ/D2ω–‹‰4»PΪ αΊΛ"IΨτ'jΥΆεήΒ#Β0hnΤͺεŠFΫqΣiΔeŠf̘¨ZO&M냿΍gΧqŒj{”ŒΜŠΈŒqCΧ?_ƒCΫ +&;«Ό"n‚‚ƒr[)V—»ώηJ!„B!„h$Ν6¦r'ygΣΝ„΄υ /6™ S;rνI;”C^ͺƒ{‡Όϋ{Π}Ε3ΌxuΫΚξύ Σ+Έ’2Θ°νζύ›'ρaΥKέ\½(S!#Ξ ΗnsžW ρΖζrn\:#ϊ 6ψ9mΈt€[EgΥ­’α&wΛη|ργFς)sΈqڜτšVΉΧΚ2‘ŸB!„BˆΦ Y’ώΔ„έόΊ~/Y›Ί’Χ{7yέ‰νT@rbGχΘ]ΓMo>Δ+/=E½O±ƒΕŒΑl¨Nϊ5Υ Šζ ˜σώέ 0{­’S@§@‡^q£tΈ:tŠΚqΠͺk΄κejΪb^{u~“οβ‰{;l)dωΏξgwƒΟŽB!„BΡ4še"Ώΰ δaξ·έ¦i˜Œ&τzN—gG'Ξqw9p8μάΉύεT.ΡάΈάγΦ*αΡD¨’’ƒ:θkl’‘ͺZ}i'μχδε§ZR΅¬<ω)!cyυκήDΊ]Έ]”–jΥ―Q”ŠJˆ†Lv(„B!„B4¦f™onΗΞ’ŸŸGξΡ£ FEΑd4c·Ω9tθ v›:²²²λ΄oΕo γ—ςσσX ‡ΒΒRv­cυŽ£¨x mΪΰ“Ώ“_·§‘ΔϊŸ³.―ͺ'€ΑΑ’ψΓω…”8±d!„B!„’~š₯{Jj .—UU)(, 1)‘„Δ½Ψl6ŒF#GŒΐd2‘]·€ΝB»^δφίfα³χπF)x…ubΤτξz ϊn“Ήgό«Όυ½|£΄‘ΧUwqχεορfϊLžEŸΒ“w,$vκsτπ Kuxψ΅ΑΛ•GnΩ)ZΡ#žή>x™Mt ΊXK )Ά»#>θΛr(΄ΧμzςrΕ@¨—‹Όό*JΡγ‚ΩšCΎMΑβ폯‡nεΕ”+ΎxΊσΘ·ͺ(Oό|}°θœeΉδ•»κ~’€]ξbΤ¨QυΪV!„B!Δߏ¦i¨ͺŠΫνΖεra4š½θ­ζiιΟΞΞζ–[onΐT¬EYXO·ZsR^’OyΙ©V:)Ι?U—kφ²μ5—Έ)+Θ’¬ς'[iΆšλb«ΪΦUNa~ω™D!„B!„h6Ν2‘ί«―½V§ΧΛdxB!„B!DΓΙ°s!„B!„β%IΏB!„BqŽ’€_!„B!„8GΥm"?j/„B!„Bœ5ŽKϊ5νψ¬^Σ΄γΫ'μ !„B!„­Η©ςψšNjιΧ4­ϊΏ’(Υ˜Νf6&‹© Γύ{sΨ˜Νζ“ή$!„B!„βtjζρ':.ιOKKC―ΧW·ξΧlεχσσ#ω`2.—«‰Γύϋ2 ’œœά‘!„B!„8KT%ϋš¦αv»‰‹λP½ξΈ€ΏS§NΝ™B!„B!•Σιώ^fοB!„B!ΞQ’τ !„B!„η(Iϊ…B!„Bˆs”$ύB!„B!Δ9κ€Gφ(>>Ύ9βB!„B!D5κ/ן1ι9jdcΔrZο–ΎΫ€ϋBΡ4nσΎ­₯C8k¬‰_Sύ}S !„βο‘ζύΕιHχ~!„B!„β%IΏB!„BqŽ’€_!„B!„8G]IΏšCΟžΰφ›^eΰχί―|!„’9Ή“ψhζF_4šΡζβι°ΧΥA !„’.š(ιΧ(9Έ’χΈ–K―}νgΊAp%2zφ½ά=ωžγ_έ‹΄»΅γ™W†±ΌΟr΅iB+ ,_·χ[fNyq[ώΖwLZ9‡_XΚΪΕ₯hg~υߊ–‘Dόν;Θ;e}’FιΟλXϊάaΚrβάe€Ο]ΗςΧ²/³n;ϊλψš^S–―₯'±ζΖe¬ϋ(³τΧ³₯ίΡuόΜlNϊŽL{λ;~ψώΎ~p(ζ–ŽG!„uV«ΩϋλF%ε‡GψηG©΄νΥo₯›Ι½~ΠΚ’ψρέ·Y΄ώΊ`:˜Β7£½§h”μώ†w>ώ‰ΝI™”κόh7`"sξžD_Ή„BˆsA“TΫλC;Ρpe»h”^Š:o2`߁ΪμMΖίQs₯‚­οx6 H`μοΫ°|ωΎK8?MΕΡik/ FΫhvbηύ¨r"½‰HN’Ϋ?’ύŸ)2gοε|ΠMytιΊl"_Ζε9°θ_c9ͺ«ς+ivβζύ˜ΰ²’|?”J—Ήίέγv9μθMώ”zΕ³@£¬mGrύ0DQVΫ;r§›ψθ˜ψΆόUv<^Ξ‚9:ξΖL’ρη}e,Ο3qύ/ž„«n6ώ³œPΈ#A± …‡U4t€m'QodΔUzς©xΕιπP4ΏPΖηρόΤ‡N‘ Ο–ρΙ:ώω₯‰@“‘Ι;ύ“δΰ‹Kν¬ΈO£ηSή<Ϊ^£ΤPλ”ydν6zΉίρ •wέoŽ`Υ[;Hι;ˆRΨ±°”Θ;œ9α―’°oΎ…n· {ˆ“¬yΩώώAB_μ„O­?t&zUWχ„ο ε|< Χ—N½1ΉJ8ςαοlω"±7‡ ‹λΔΠ7;βή²•εŸ™ψJwυ€ABΒ¦ΰΫ'Σ,rνm‰΄Τ5H E§œt|Άu;Ω±Χ‡~Ο_@°·‹²}ωΈΪT”œ)>C}?O—΄Γl}ψ ο:‰Ίaγ"Ψυή(Ÿ1*Η²ώƒBΒoLοσ-h9yΈΜ(΅)Ώ6ju}((:ΠΤϊvΗiνΧO=γ/>Β¦;$ΗyΒˍmθυζ ¨νο¨8­}fjGYφκσ,e*Oo4αeۘςλ$ΈFU/`νηΣ’+xψ­'i§β§ΎΘ£oϊπή Ε_Qππ £σεχqνCΡψ8SXρΦ³Ό8Ώ3σζτ€ϊΤ !„’‘5m_=U«ΣΈm₯<‰ωˆž•wœjpOΦOοG‘ΏΓε°–GŸ'Ÿg؁7τeίυ—Ρyχ—΄ύι0ζb2Ε°ρ¦aδλ©ΌρΥ ΝPΏx馣τ}ς%†ξίC‡GΜ8 wϋΛψζ™‹ΘWŽηΙ—Ά=F³ΊΗΚ―ΪΏW/V>wϋ½ θύΤs OJ'4Ε͎Ύ£Xςπ0bί}‚+ΦΊI»ϊf–υ―ϋ©o;ΓBίσu(θό˜‰ίG:ٝffΈήΑΖε Γ±Π©=€Ž1Ο™Ωq©Oι§£ψ7—]γ·glόnԈo‘τJ@Ίk?… =θί·’¬›Ω2ΠΑή,C#@η‘ΤE‡—¦R:Φ‹KΖT$uˆ_Λ* ΠιG§Ά'gα¦>=θΥwΫ>>€CΫGqΏΎτλ]‡.֚ŠΟθnΔuφBbΖF°χω"JάΤ>ιWLDΜKDνK­uωΊ¨HΪGU½ΨB‡‹CHϊ±«‚—^ΡSή’E‡Αˈρ4ٚ.Ζ?w6…™‘±υh…;ε/€†ζRΡ=¦ fo0_P#“«E|ŠΩŒWŒ&lΨϊ ‘k?t€'ΐ‰ΙβIœdύ’#qώˆ€ŠίΧ€¨cΉdΞΟ鏻39 ŸzΕοIοW‚qŸxν(zΜ>υ(Gœ^?3΄άό²#”+ޚΘωα:`4³'o`έ»UλΧ±ψ· &Ό5•ΎQ: ˆλoΏœ_οωu7 αŠ`CΜPώS΅ΗΊ¬'_|½Ÿ<­'u$„BˆV¨u ΠsζΎ5ΏϊG52”?4(ͺΕ¦ZΘΦMόƒkη #G'^ΝΆ˜šwΎ φΘ²’Υήm_Ύ9Εxi™xh ΕέΞ£PDF—@Τ}y¦£τ¬Υ˜Ϋ‰4o? Β-hI 5!“’ΨφX œ.FO°ήA^*¨¨δyθ‰Š=φrέyzΒυ²“α‚X†―U 4ιξv“|HEIQš¬C;β »Ψ͞‰El¨qƒη΄λh— Ηe:±ƒκΪ‚XAΛ³bχφΔγT3A)&ΒoθI›ϋ6±SiΗΰ„aͺΛΝ¦bΔ'³ϊό(f=zU₯Ω¦{•LS"ύVκ£;«[Aj†‚ Έ27²ΰ£/Y»'« ΥeΓΫWs\_B!„hr­κNNσΔχοœbL­Έ1–Ω*“ƒΝ‰¨9‘΅’ͺΗξ_΄Κ4^«qOsͺΜΎ.Ν.fœ•;Σ”ΖΎSPέΗύXA9yΡq?h k«# [εΘF7Ά~fϊX­όΆIΕ?K‘M;ΐ ŒωΑ“>5φ‘€%τ„00i‚ΣqΈp›L§Mμ΄r6‡‚‚ ›UŸ:eύθZτjώ‹ςΥbφ½Ό™”ΠnτόΏP|ότh»vΏ²>εθΠUμgl=?ž–±5χμΖΪ³'Cτ;ω>ή3σCΤΞΓ$-ΪIόdΊ=1˜Ž±uLΓ†Ϊ ;p«hUQ4Λδ–΅Ή>όκOΧXuc&=ήAΗΠζΚxšλϊ©ιήίΚi'Wnκ θ«/݊α<Η>Tτ(ΠΤdύλV‡Oηφ'ϊ`FΫώw.iκΈ…BΡ\ZUίϊ”΅ŒZœŽΞ?†,CaΛΏ‘ߐ{ΨW5"QΓpp?α֞€šσ =T‚’˜)υ₯Τ†MIΖwο>όέ1δ+yD$δ£SΌΙφm€œDΑm0 αΐ³  π«ΫζšΖΡύ*Ϊ…­ύκa7GU±Ρ 3θ²:H;];WΌ\Mr“α14tώzΛ$ύ}•Ψ2=ίΕ;Ρ¬z:E‚Ξ©'Τμ ?_!°W&9F=:§ϋΤ­οj)Ιοο‘|ψ@²‹mο¦Νc±Τ§±ΉΥ)/ /ݟv <€βφΫΊΥΑICΗP\gκΰΖνΠc¨γδςJh;όΛLΒ[;Ψ±2”a—κι z<ΟoOοQ<·Œ„ψBΪΗQcΘ{-β;:·½ͺΩPÚV‚Sσ­\νW09R‚Šωτ½κ]~mi”Εο$αh(}ŸιLDp+Ήψυϊ©ιήίͺιC#sν"9CeH»ŠίgVΉjΕ }D4᎟ٟ¦rAεzwΚ~’έα\‡²ύμIλΐ•ONd`hΕυuΤQΜ©¦B!ΔΩιμxΎSi—.cψ{ίΠ5M5—Ξ 1μϋDεiΰΞ¦ηΗ+ s˜I½z:Kξ‚έ•AοΉλͺΡ:do`όƒ―3α±w΄ί…x>ϋΊqwΜXϊƒK™ψπ;\υΘ[ ήοΖ;˜]] g.ΏVtδΗFΰΒEτ‚2ει·Ήζαωt«υφ2ΧΖ;UJS]¬ΞA^#έ"A 31tœΖ―ΫH<¨R|ΐΙςΗμX/1Σ30ιqsh§Žv}<ϋθρΪκ";LGπ50μz…­ZY·ΦMΡQ•£ΫlxΗInσ§Z5άΈ¬uw  z`)-§ά~βΫΩ“Eο©DLιEDϊnΆRΦ<ΐΥaΨIc9ΛίΚΐј›-xx–‘ύ{ε…VŠώHdΫ'›ζƒgI6G6c+ΆQ–Q^Ρ½Ά&[9ε₯<뚐κMxuŠ‘ύ3IΕ'”­QςϋARχS^μΐ–žGAކ%Π|\Εΐ™βΣμnTMΓνPίΏήίH;™+R)Κ·SΎ0»WΫ·b"ldξΥ;Ω΅‘ς"eGrIίUzά~ju~D£ho>ζ ΪΣΙ«σœΧO}βW XBΌπjsΒ †VR/ςw¦΄ΒθξΩόψΑWμΘ( οπz>^°žβΚχP Ξƒ ωώνΟψ#-ŸόΤ-|ϊξO”Ύ‚αΑ X‚φLgΫΖDr Ž’όΫgΌώu)*4\.4χΙNB!„h՚€₯ί΅ηCn}l19.ε6Η&Βθ?–'?Ίƒήυ(Q—΅AŸ" :΅πηoμ؊Ox?JŠΎa@’wτElD γΨωS"ύχ―dΔʞό P6πbvk tέU†+’ΏΟΎ‚ΓQlΉ&Ϊό%tίyˆ(·'yύΗ²αΖ‹9j8SωΘ¬ΥΨ_…X}d7&8© [Xoœ΅M,τ:ϊΟΠ³χŽΏ&{ΣLbίηΗ‹²Η­|}±"M!ϊrf=k¬θ!―Χ­Qt@OΫpΠibμ66wΥh¨Ψ>ξq/nτΆ²τR~Μs¨Žv-tS@M²σφ₯V’ ©ΈΩ›PΔ&OCψ2aD-γ”pότ©Q‰ιr¬ΎIΛNfϋη₯Dάsm<Bι>+œUolηpΟ!ΔΆiΜBC΅»pιΤΖ­l0Ά‘σΝQlώhΛζλπκKχλc)ύωψ—)Ρθ3­˜mŸ¬fΙλΖΞ]ώL'όj\#καŠL~ΔΦ³ΫΉ’WŽ m©©$ύsχ²5ρfφ$``OϊŒ;Ύ7ΐιβσΝΨΗΪ‡w“W¦VμϊΙοI6{χπXzυԁ·φ³Ί’φNVίΌ cL¦vΖϊqyυΎΝCϊ0Έh';η―cyώγήγΨ–ΪœŸ†4Ptυ½ήZυΣ"ρ‹3jΠg¦Κ₯χ?BφήαΙYγφλΜ…c†½¬j½?Γξy–βχήζυ;’§qΨLώuλpΐΨ›©sFπβ»Η΄υ„)7ΝΌ”το«‚ΫΝGw>Γβ”BJn4 ξΉμGΌΊ0υ…—™Χd3q!„’‘(ηΎ¬­š4γ)šΆβγγ9jd“ρnι»MΊύΞEΜ|~Ί7σΏΫΊ7Ξ¬ΰpρeΟrτψrυ°–¦4;G^\NRΫα\<Υ_ζ‡ͺ3‚+YŸΩ…±χGΧm’ΓΚν ?_Ιڌn\~δYΝ§9©€Ώ²˜„θ‘Œž|ŠyΔ)έζ}[K‡pΦXΏ¦ϊϋ¦ό\u'~ΐ¬§ΛΉσΣ{θsΞ βB!Δ©¬‰_Γ¨Q£NZξtVd½£½%χύ’)f"ΖFβZw˜ά“Ίψ‹3²επ―n’Ζ„Χ#αP0y >Jn±΄εžH+Μ!',ΑIψΕYL£,5•|ίόδBB!g˘~qΞ0φξBΧΆY$*•.Δu’QϊK"Ωq]ι|~ύ›ξ<†u£Kh&f­eΆΌU΄Œ$ΦΜώœΆέι>τTΟ”’•rbιΗ_°fw ΉE…d%,γέΟ·2pm₯η½B!8‡fο+ξσ'ρα“Z:  xξαq΄kι8Ξ: ήγ‡3n|wγH§Η/‘c™Υ"Ν€U”Πφ ™Χ“§ΤƒŠ³ŒΞηN>}ρ+2ςJq{FΠ}Τ½<1υΌΏΗΌB!ΞHξ Ξ&“|[:ŠΣ’1½g!yΆΊη₯ Coyž‘·΄t B!„h­€YK!„B!„8GI/„B!„Bœ£$ιB!„B!ΞQ’τ7w"_ώλ νw·t$gΰ ρϋgyμ½5d«uΨμ¬9>!„B!„55A―Qœ΄„·Ε€+ΖqΙUΧsολ+8r<—]Ν]Νλ/Oς9›Ϋ*xψΰρ·ŸϋΗ/„B!v”εO\Η?ΏMηψv%’ƒ+yοkΉτΪΧΩξϊ‹}Ψ·ςΪu3ψ ‘ζ‹Ξ΄½JΖχpέγK‘' qzŸτkωόρύR²:έΐ³|Ζ'/Ν jΧ<Ώθ­=—Τ σ(¨K ψYΗHΫ oεžΙύέ\ήX‡#Δ9§ρΩ§qαƒoraΥΟa£˜tΡ·άΆ#‰-&x4ΈkΧ|žίζIΗό?ΩaoΟ%£ƒΩΎτWrƒ/fφ싉1h”^ΛwΛ6’š‡Uρ&Όσp&LΈ8O5u9oΞ_KZ‰§ͺρϊΓk0φ˜ΞσΣzcΐNζΆ%,^ϋ'–‚g8]FOaΪ HτŠ­`;ίΎ·„Ν)₯˜Γz2n5 3Υβ²ΩzK"^·ESΊ(‘΄d;ϊΘΊάΩ—νΟπiεlžχ ΫΊ=Ζ-Ό©yz­Ϋ>διν=xlFφ~ς hθ£.γζ\Lhε_εZCŽO!„Bœ›΄~[²Λ¨—θaΉBGδΐ<38–ŽΉσ˜υŒυ/χ±eΥ‚GΎJœΎŽΫ›»3n”7χΌžYΖ4I!ΔΩρ“ώ“¨”• χτΔάdΏ„₯ϋΈy6c—ΏΙΛ»1ω¦iYπ#ΫΣ/$¦­³g mNfτ΅mπtg³εϋω,XΡ–Gμ€!ςBnωηpœ _ςά2onΌλ2Ϊκ@1˜*~ς„oωΰϋ4Ί^yvτCΝ?LŠΫχXm¦feηΪ팼κv .eϋwσέ·ιxΫH‚ksάjϋζ[θvϋΊ‡8ɚ·‘νο$τΕNψόU ΕLP…yh˜HίΎŽD]WFτ #?·― `FNͺƒ8γρ7Βρ !„BˆsŽšq€ƒΞ8:ΕώE[’ͺqϊ!χωV±+ξB†‡Ÿ¦₯μ/·ClGβ\Ι̐S!N₯i[ϊ]ι,}εMΆΆΞ#όON6‘β鍧’  xx{a@^―βvW RwηοfΕΥόy$‡»Υνΐ‰ͺΑS ΙΝS λ~ϊ¦XEQ,˜έ塟Η@1βιYŠbΦ£WUΞ<Δ^Α;0Γφ< ²28μέƒξκ’sσQ τυρiœσήΠγB!„η57›|Ÿ6›ΟόΪSrX·j/z€ϊή΄šBhγ[ΐΡ\ ΪΧsBœΓš.ιWsΩπΖc|5ŒG_ΎœΘϋϋ42E―«μR€ 7œpXj&«|ΚΆ KΈςϊΞ„z›Π|Ο7Χvο•΅‹Κ_ύ%c04$½VΠΥσέΠ†PœΗ‘C9Ψb.€σ+~KΞΐΏ8€6AΥ™£‘Η'„B!Ξ5šέŽΓδWοaΌjΖVξΞ•ƒλίP₯˜0:e !N₯iΊχkl~η!^ήݝ^Έƒώ-=£†=•ΓG£vιΊΕ„€ΡUŽσΔΧ) Šϋc†?ύr²²kΡςήόtώ!: H:œKtl;bΫ…‘y(G!ώux‹OwόB!„Bœ‚b4at:pΤ+ίV9OfŸ‹Έΐ·ω‚fΗf7anΊ Δ„8«5Α#ϋŠΨώα#<·1šΩΝ’§₯œRJΛΚ±·T_p£~–\’φ€PPZHfΒJΎZ—rΨ ]PΛΩ²3“β²bςŽbΧΕ“}Ίβψγ{~ά‘FAi1ωYΩy0·uT φΙβPFνb,xF·Γ+εΩΎ!Υ–―:±9\hn6‡ZϋγB!„β”ΰг9j―ΗΖξ¬^“O ϋρ‘~Ι–CNi‘!M>]™g₯Fοή―mΰΛοφQκάΗ«³ΧρjΥ %ρ/.δήΎΝπΐ€:rΡ?zρΩβwxv‰žΐΈAŒ7ˆά ΗΏLΧf8“.ΝbΡ’ςτ" ΆcΉ}φh"οσ―aVΩό°τž/r’χπ'jθutkάόΗs"%ˆ€ŠrzΡΦWAG;b\KΩB pΰϋ|Θ―Ήܚμη΅'AoŽfΜ-χ06²βδiΏEN!„B΄VϊˆΔV±ο°‹ΡݎΏΟwνω[[LŽΛAΉM㱉«0ϊεɏ\‰«Y[>ˆ»ϋxžrίgΪΎϊu‡φqΘΗeα’τ q*ΚΐΉ/k«&Νΐhώ£Qœ΄”OηΛΪ]i”θƒι<ςξΉu mΝ-›hlί―9Θ>\Hδψψοό/ωμΫιtπC^ψ<±ι[,κλΩ»οψ(κόγ―Ω’Mο=$!‘χŽ UΑώ=Ϋ©(’ˆ‚ηYπΤ³χΓv€b?»' bQDDͺτ–$”τžέί 4²›„άϋωxδρHfwζϋ™οΜfη3ί2f»^ω‘΅»cιφδ™œυtβχ­cρ+»¨j]LΜ:ΕaRτεBζή³Ž‚€μή KDDΌΓΜgw‘“φ/’wd,±‘mhμσ”°βοFx@8a~Ηϋv¨ιu9ΈχδϋΗdo`&?|Κͺ.W2dηL>ίήW‹nvόχfΖΏ»ύOž[ο+aRcήΊ^ϋˆiz§G³™Η/³f“Σζ*yω]ή|ςšύ:™Η¦ΧC/3©wήOϊΊ_>«†v$9*œ¨ζ§rz―hςvηRνυΒΌ$'[ΫHݞ„δόγh7Ίφ%[Ι.hθΰw)[υ«ζεSuBίF!½:rκδ3θ?2»ξ Šˆ4 ξΌ7ΉβΑ4»½+wm+eώϋ©ψίθΐqσ¦μ?πί,…ίD›Ϋ"ˆΈ£gΌ//H IDAT«+^ς9ΏbμΔ7:πΏεRήΙ|+Ž'τζx†|½&y['sν³hvK0ΑoΞ)―>ΝΒϊΉ’5‹—ςμU#ωΗ9/RMrΎψŽz–₯Ε5Ηΰ\3«.{†₯•‡-,ϋG/Ό‚ΦxΨΙς_Μ°aCzΨΟ™χΟ£ά“pώΒ3—έΚϋ?}Ξ€ —rξ™gqαυ3kS™'kΞ,δ»Η.αβ‡η‘_›ͺ―±|“β53yςΦ«Ήπμα ?χbΖ>όΏ(Δ΅αmnΎμ8χΞΟΨ»k&qpZ@ε—κωnΥρψΰήΙWŸηΠο.α "ψfϊJ<­#oŸTχσ““zλόω‚Ζ½ξ]|όΠDžŸ³‰’Ήώφv|ξ"6Νyž‰}Μ.oܝ2’rηΎκ4ZΗGΫz0K%{έF<ύψΚΙΓΗcϊέ”fΞcΦ’*zυοDcν)βΞΘ£ΐEtκοΩ°Ρ,ŠHGyυpΟ·h;‹G}Β'—υ3j1Ϋ‹K0iW·Β±rίN\ΚζΥe΅ΎmΔDm·»ξb‹ˆΘρX".εΕ‰ΛXσΠwά—Θΐ‹~%ηι\rŸό”±‘0χπαϋρhώp^Έs=λo{–Ήδ‚>e― Ψ†σΒ#YlόΗ£ 4ζρχgΠό‚οXϋΟYLκή+!A©τπ_ί·­wΏΕ_*ώΝθ/~πJW#€'cnκΗΞ7_ΰλ½&ζή―yαΝlϊCϐšο@ΫΪf@ΐO,Xω{ Q΅ξVτ‘_Oϊ©ΫθrΓ|2λ>™υ ³ή}€3γCιΨ­­ηΧ$M|πκJZίπo½=™1©λyyΚgμ¨Υ—©›Γ‡ZίwΣς Bγi{ξ­<σŸςώ‹χ0Έl&OΌ΅šjΐΪκbžxυή»σ4‚βΟη‰ΤΓΜ;ϋ{嚬Η jΝ§Μ΅η¬–v’…^›¦3;»•λ•γsbκ~~6μώ›…syΰ’σ8οό£~.z€Ή…žd}u|5κγoIβμλ/"rωΣά4ώIfΨ[ϋL―ΔWΝή3yrόM<½<’‹?›$‹7ŽίΡάc Δ‘Β&ΗG#»œ,Ÿ:šηξ₯άA+ώΙέƒ£jEWOͺσ+p…Fy‚όC\Ίπω½‘$Ί=λθΟ§aΕrΰWk\ώV«ύ@WϊίΎŽάωρς― ŒŸ8‘‘±V ž».ΊŽYOOγ£σΟelΈ«_ ΝΣ‰"—½>⾎m°Ι·a?Ÿβ+0–›ϊδιy+ΩmžFsŸ1„τΎŽρ½Ηρμ‹QlN'£Ο­άΡ3Δ³k[+ŸΖέ –SvJ?q²ω—ΨNΉ•φŽ6°: rf1K_{…ŸRΗ0εΌ$ΟΏΩM'ΙΓGs^‡x ΰτsϊςζ}[ΙrA²§1BθwΫ›τσ΄ΜZ”oKιΟω)Ώ½9‚ ΞξΒgnfΏΩ…x«ƒΐ v†a' (˜`―^ωΥρψšEόψΙšŸ=•8ptbδ9vœsnιI€GΫ¨Γρqΰωkδ«7¦³‚Js<7έΐ>œϋ_»‰n5ΥU]ΟΟή#t{Ύ3•Η\: υμŸC>_ }ό=ΰHθΝewχΰΜ syχΥ;χρ F]w1ύ“=<ΗλŸIَ…LεM”uγ’›§p{ΫπCs½xγψQZαbf-(₯ϋu]π―υΪΨω(ι·Ρρͺ§yιΒr w¬ΰΣΧ`bΕCη‰OžαΓm›ΨSQΛUFybWͺM¨—»ρF(§\w#έox€-ΓyxZo`nNΏχ`Cu9>Ά\ωΤK\θr³ϋσ‡xΡ=†ϋΟKΒj $Β£+亝Ÿ ΎFq₯Φ58±ΟWƒο?@υ"žΌόIUόΫ―wΎw'ύŽ8€VΒێ`ΤMVΚ™Μs―$ΠφΑαΔxržΧ%>s?Ός3³ϋrσ?GqzZπ‘i―?ΐ™Ν짦°,u“†7Ϊ†Z9q>›ΓΥ/4†ψPˆOHαfs}zΏ^ٞžpΦX{ΈkqΕ‘wΚΜJ*Šmψ‡ΧΓDJEΫY&]w:mBqoœΘΐE>Œω8Μ<ς«,XΘ'― υ|]KΚ ōωK‹ιΧjΛ‹{reΏΪ•_π#Σ¦,₯͍ΟszlmΏ8mΨτΪεOΚwg0ύαΗω6a7ήΧ‹δζŠ™πe½xΒΗΧHΌˆgώsΤΒΐ^άϊŸ^΅(½.ΗǏИ8BqSlΗξŠ&>>ΎVύ;λr~6τώ›…syπΪ©,?ζϊ³;γ_»Ÿ3<œFD?_ ½VοΙΨ©/3κ·§†Q7|\lšΟ‡ο}ΐόά†šΒ›φx7λŸΓπί€υσΞΏn`Fά`.ΉόB·>ΠΪο­γ‡{‹&“—spΟ€sIͺ9d₯ήΥΟטۍι’ΡΞi€E^±•}Y&qι> ζΞύδU†Σ²Ή»φCΝέϋΝ ²_ψžΥΫΒi~Ρ) λͺd_Dδ€5Ί iΥ―³b―‹ Ĝ9+XγJclŒWfΛω)·+7^7ž³"-€›μκ|*κs€—{_L~ƒά!χs?―πΜ”Ωtδ,c>οVμ’ΛΉ]j1TΠdίό©Ό°Ά3γžκ„­΄„ΐ°: 8IυN”YΘχOέΜkΖυL½­_-†7Τΐ?Šθΐl–Έώƒ’)έψ―Ν܈;ό”#ήfML&Ύp.sΏΟ ΉGUΕ.Β’b<‡“u/ζοs:πΰϋwΗγ φΖρm ,$_:™©'΄n]ΞΟVηξαδσε3~4?χ!^iΩμ°ΟJ1‚hή ξξ7’[φγu?~f!+^Ή›GLfμ#cθβ_FI `X°ϋβh€y›œο'ύ†gΦ¦|ψovΉ°‡'Ρα΄yτΪ>ήϋ’σ6ΓAυ§Rώς –έΎJ߈SΫsκ˜όCΜ†u{>²{Γ―Μ{deNΞJψρͺ,,α©τ™άΥKAŠˆˆΧ1\pωGδ}x;ώυ/v›ρtοφ^8’X\»Ÿeψ3χσcYεήb“£xΝ―9׍]Ν³mύΐ6ˆ;/ΎΡ3Ο’ύ,;©-―αασaΛ‚ƒΫw-βή]Ξ+Ήϋ(¨vbš0τ–— ιΝΔρ³Ή-~ɟΏžτη—ξέ_0ωτ»σΊτ`τ}7i2³»?ΚY6Ρύœφ ΟnμΗύχΤbŠ)s7σg-b_“‡―όζΠb[»λyνί—Π¬:σΰΖYQN…΅Ϊ»OΠ±wγςρybΪD|ΕJ|η³ΈvτYdΟ:ςm–Τ‘ά2&“η^žΐεn‚ۏb€KHν’ή,'{Η>ό:χ€}-FNxλψžμNψό<Ω5šΟ—A$· jθ(Žd¬U W6e.⃏7QR½‰§―ž§•Ι9OΌΟί{4Β1ΩrŒ>™dΞ»x<vϋ±·tζϟϠΑƒ|Δ΄’i^Ϊ’IьωόBO%΄ άa¬γ‚Η5t""Mή‚ω ύξλοΥ¦ΗMΖΫγΈcΗΌuχΌsΙ+‡8Χπβθ{Ι½ϊMξ’λ§ΪΣω)" gΑό <ψ˜εΥΥם>ΥΧΟ’©#χ.~ώ9Ÿ{(‘ς3+[*{1τ%ό'D秈4rκ·!"""“«‚’’vύπ³Šς^J©|Αˆ9Ÿ§>8Ώ‘Γ8ωθό‘“„’~i”ά9ŸsοΨWΨή™‘·ύΞ΅{RŸˆOιό‘“EKϊ B2„! ΖIΖ{s*Θ‰Πœ ""ΗgIΊˆg?Ώ¨‘Γ9.Ÿ"r²Π˜~‘&JIΏˆˆˆˆˆˆH₯€_DDDDDD€‰jbIΏIьoωvFfC‡$™~0Oυ+"""""r’πνD~ζ~ζή?†Iλπψϋ·³1Oθ*eΧϋ«X;oΕ%ΰBĐNτΊ8?=΄φΏ?μζiΊM ‹*GDDDDD€±ςi^Άς]ήέ`%΄Ρη…&₯s~αηοόθxϋ0’ ͺvη“W€½QΔnbšFƒΕREΦSσΨXMŒ£‚rs?/ήΛ^ΏV »7FQG""""""r4ί%ύΞ f½Ύ„–gbημ*Ÿγ&…› ±u;…τΑX€€Θ Β<\Ϋ½x _-π#&w'ΩεΡ΄K0;ίήJIbϊ?؎ˆΊ>·Υ]ΚΦI+(νΩ‘vƒ#π«ν Œ’–ίΎ”²‘CθwF&₯sρνǁτžΤΈΰš6`'ρΪώ„dε²ρω”:HΫƒ6ΝC=λαΜeΩΨυŽiFΡλΩ΅Λ$ }]Ζw$!ϊΰΚςΩϊΪJ6ύT@…%€Θ~mι:ͺ9aώUlt6Y§Œ`ΐιŽ#6[½`_~ŸΘˆ{ΣpΈΛΨύΑJΦ|³‡’RΑ]ΣιrC;b# pζπΛθEd™ΰH’Χ#ρδLω•μέyω ^ʟξFλ―¦σCDDDDDΔW|4¦ίdό7ψΜ~WυΐΩθ€ΕP½.›=y'¬IŊ|Ηφ§]L«ί-%νώή$d±c›»ζΥ‹Ά³xΤ'|rωQ?£³½°“vu++—ρνΔ₯l^]†[ύ]p<―K€ψύUdν71χg±κύ’λθAΒ``‹ΒΊ=›‚6]ιΪΉ„œ,!q~žŸ@|6Ν,$αζaœ9΅­vπσδm”š€YΑΞi?²~_<έ'Ι™w%fη―,z)›JlΕϋQž[†‰“‚ο7°aa!.LJw•α—Œέp‘χή"–.  υ?N?Έύ,–LΙ€ΜlρτxεΞ|Ί±fλ§ν θͺΑŒψw?Ίœόη ΏWκ―Žη‡ˆˆˆˆˆΘ ςMKωJή{woΏ›$γ­Ϊ%¨ Β μΌtΨ²„Ε7}EΜ°V΄9?˜hΟρ$΅ΓΥ*{x3š₯E⎫do+‡$Ρν©h\Gίo0¬8Bόj‹§νmq€mΞdύ[?πΝΝθpe’šyvύΊw’ky,} Uζ&Šzφ g·ZtAp—±£•”‘©4·U±ϋΏϋ)q†V‹3(rxRύšNζm;Ψ΅7––lΆ.υ§ε€ΆΔ%@<νM'ϋ­μΌ2„„@*Φ—β&γνudZ+‰ξΫ‘ΚέΆ Β(ΫΝζ―έ€έΣ…ΤΦ ˆΤ+Z²}|»σšΣ"Κΐp8J  *zφ£}Ο,@ ‡±Χ΅ώκt~ˆˆˆˆˆˆœ $ύ.2?yΕ-―β…ŒΎ™€ΐHZσ š­Ξ`㌍,œ°•δ›ϊΡ£PΝ-Α€βΐΟbPi·bs`Αΐb1q{ΝΑ°αγΙ‘0p΄jN‡1œO­`ωΫADώ£9θGΒU]ˆ½u1«ζœϊL|ν&(΄“vGƒ΄αΤ;k±ξΑςƒβ~O’Ψ‚-Ϋ(έkbRL©_α Ώd$…jΩNq€%aωΎ”¬Bφ‡&’ΰΞc2Ψc4ΨφQTZΚ?cΫ‘-˜Έͺ‰Κ’ΓAtϋΠΪwq©cύΥιό9A^OϊΝΌωΌρ©•‘OžFΈ.oΰSV;·€[η洘΅ˆωΩHJŸξΔzRKVγΠΝ‹½–)eΡvOXΙžκ£–Ϋcι:₯/©‘&•[v°ωÍμΨJκeƒΡ7¬V šeTTTPQnBH}ΞΐgbΊϊϋ°Ώώ,#6˜ΐόRςΧ”ΰlӚ”ͺεd¬+ /8ͺ[$νξErΘα+Z°G΅eΓ†Νχ .υW—σCDDDDDδy=ιw]ΜΟ{Χ°θΪαΌ˜yξ:{>ƒξύˆ{ϊΫ½]€ΨnγΏ₯T:ρυƒ kξήoVύΒχ¬ήNσ‹NaXŸΠΪ?Uΐ]BΖKk);­}ψ•ε/eϋΟ4‚κ+ο7«(Ξΐμˆ˜9Ε”˜DΗ–‚ͺ2ΘίeŸr sG…ξ ZΔAΑVμ#wC αύ£ˆ*cεͺ¨ ".Ϊΐp…bΟ ¬ΘAP ¬†?‘ΰυ ΙΦσF^~}Τ‘qόm3ΈwJ)4šήρΎΞžOYFΞWΉΈS# χΗV^HΦ‡;¨hΡ†GΝ«ΧYMέϋM+‘#ϊ2,=δ!hR2wks›qΚ‰ΔšVrnϋ™ίΔοtΟ†/xCώœ΅d΅οH|H;ήΝ ΄M’ š‘ήk+_έ@δ i„™l{}Υ½Ί‘i€;ˆΰπ"²ΆΡκ~‘8fdR™B pΔΣrΨ:Ύ²ŒΠ±νHJ΅γά[ΐžunβΞM"ψ`ΓΊYιΒmšΈͺܘXj±ί£ώDDDDDDjΛλYΈE³δίQ»JC°[ b’›ΥHs~0peο`έGk(Λ―Ζeχ'¬ssNΉ₯Α!£3μ„΄8ρfn+ή+!ρ–Sˆ ˆ£γ˜ζM^Af—~€ΕΦΓNZIFΞδoXžν& }:½Ζ§l)wΠl\?ͺήXɊ‰(7ύ‰θہSG7Γί,AΗVRžέŒ¨(Ì"’zΫSC²؈Ύ²?}V³nκ|Vη»±E„uZ{ 0wlβ»»Φ°ΏΤiχΟ"ΓDϊ]ΓιΪ₯ζφ’ώDDDDDDN€Ρη?“Μyΐn·σ†ωση3hπ Ÿ1­dš—ΆdR4c>ΏΠ“Α©αΩλRœΉ,»n–[GΠ­“Ζ³m\πΈ†ADκΑ‚ω ύξλοUωί°`ώ|Μςκκ³λ >΅φ“˜‹ˆˆˆˆˆˆΘΙAIΏˆˆˆˆˆˆH₯€_DDDDDD€‰j΄S띃п aH=—ͺ1Ω˜ΡΠˆˆˆˆˆˆόοQKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ι­3yΰ‘ΨΰjθHDDDDDDDNŒ&ς3ΩϋΙν\1e%ΞCΛμτ™8ƒGΞΑπ~"""""""r>HϊέζvΖƒΌ|cΧƒΨό•π‹ˆˆˆˆˆˆΤ#Ÿ΄τδ•ΤŒΠΰΰϊ?ΰΚgνΌψςηMμ)χ#Ίu.y­C pmΰƒ'Ύ!jdwφΞ›ΛΚ]₯Ψc:2ό/—2 ™γΐκy«ωό£Οω9#wxkυ ΔԞh(""""""S|ΥVQXP̎Ÿξ沏+1ΒRιqΦhΩ‘pŸ5υW‘9χήΫ”Ζ]5‘6‘e¬ŸσoNεΆΡ}‰pοΰΫ/C9λ’ œ^ΑΊ/^cζ¬…΄Ήq(±μeαο²Τ6”Q?…θ²5|ςώ,Šά=}°ˆˆˆˆˆˆˆΟω ιδΤλ#(/ΔHyΏ~Β‹/έΓ#ΦψΧ%ω¦εΏb=ίύμ’Ο5#ι•b’θ=bKŸZΞΊ’>τL±½Ξ’_jΠσ”Μ~sΉnˆ)ZΛʝQτ?ŒΦΡ /ητYΚΪο|¬ˆˆˆˆˆˆHύπIυ€δτI>π{JςΝLά·žρ_-`Ηy%ΥYΏ;7ΉϋXϋκ=,ϊ})ΥΞš› bc"Ν+`ψωawγάyXγIŒω-8 ‘qqψk9‰ΥΓ u+͚'cωͺ€B7Ύ{H ₯9g\9έƒΟΤ­ψ‡Zύnϋ“½5 Λ‘‘Y­X1½§ˆˆˆˆˆˆH=©‡€ίdoΞΜ¨ΆD[}S‚%"ž8ΫOδ•…ΩΜοΨ7ΈjZ?ŠpW&Ήωn:ΖX“’}{)3£}―ˆˆˆˆˆˆH}π~»»k+σ¦Νς­»Ι+ΨΓ–…oςάΜ]t;{ Ύκ.οߞ½ύYφΙω~s…%…μέ±–Eί―fŸ»ζՍπŽtKΩΓ_.$#Ώ˜‚?σωΫ}£YIφδ―ψjr6•κ """"""œχ[ϊ ?œΫ?γΉ™“Ω[δΒ?-ύ―x”λψΑwCδύH1–«Ÿ2{ζΏω΄Θ…#4–ζ]GΠΑ€{ιQτ»ψJ fΞβ•IŸAd[† L³ΩEG½ΡΔ]ιΔ‰[EDDDDD€Ρσ~oIfψ“ξυ ΧΐA»a£h7μx―΅ε’{:b‘%ω\ξyδ°ΏΓ;pξ˜œ{Ψ{†u?j;†?ΙwœM²·bρ!_M«'""""""" LIΏˆˆˆˆˆˆH₯€_DDDDDD€‰ͺ‡GφΥl\πΈ†ADDDDDD€ΙQKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ιi’|4‘ŸIΙ¦Ωόη?³pmyUώτ½νM<=Γ7ŠˆˆˆˆˆˆΘQ|’τWoύ€{ώω5±ΓΓZθΖe QΒ/""""""RΌŸτ›…όπξΗX/y†».Lψ‘βύ€ΏςW~Z@η~ ylΒg¬Ξ5‰ξ0‚knΊœ^ΡV―'"""""""Ηηυ†xχΎd—nηλ9»ι~νΓ<υΔ­ 5ηπΘc³Θv{»4ω#^OϊΝ²RʌΞ0³Ί¦‘’ήƒ‘γ/¦ΥζοYΌΗτvq"""""""ςΌžτ~ώ8l1ΔΗόή•ί‹%Ϊ^BQ±šϊEDDDDDDκ‹Χ“~K|sRμ›ωu}ε‘efA.{œ‘ΔDjZ?‘ϊβύ,άΏ;g±ρΝ SωzS.{wδγηg°½Λ0ϊDκ‘}"""""""υΕϋ³χ@—1πχW§πζ?ζ©Κ`šŸrχέr1ΚωEDDDDDDꍒ~ΐ‘›&1δ&Ÿl]DDDDDDD< Aφ"""""""M”’~‘&JIΏˆˆˆˆˆˆHε›1ύ΅4­dZC‡ " d\πΈ†ADDDD€ΙRKΏˆˆˆˆˆˆH₯€_DDDDDD€‰R/""""""D)ι― W –Ώ ΐΦ’–eM±κ Bηv¦Ε–¦Έo""""""{ΌžέΉ6ΌΜ¨αC:쨟αWσΚΧρWz£ΆΘ‘Ψ’a}ίοΐ²Ο:b‹Œυ?Ο _Τ[Μ ¬_œΰnΥ΄Ύi…]6(r@ρ‰qΒ\ќ2πFΝα‡cϊΉά8€‘P'¬Ό=&dθc-0½ΌνϊˆίΜ22ŸΝwŸ•ΰν*hΪLJΎψžΩfR¦Ši4Ό>{Ώ΅υΥLϋθrά‡]ψ;7½Ιߞ(€]³?IΖ +ΖμHΈ4ηΔ ίξ[Υ£υmΕΈΏY„»Ψ±u)θXΚ(© 4Ζ…Σ]Fetε^ΎeψYg’ϊ/aγ―έι΄a+?·σβ>ΦCόήΰ\΅υΫθykπSR°cŽ}Έ6Β ±aΌΥΛ›Q[`:1OΙΕύθVΜ6šΧ Α2°–υγ·γ^°w;Σ³ψ΄Εφ—8Μ'ΦbώΠΛ7RŠyΟ:\W”xV―F%eρΕ”E›˜2ŠcΛ©ϊ­: R:t8!7—OFabϊζω\:₯ˆ―Ύω–ναlίA»„²υ‰9¬^Η…S›³jκ6*=Ι|«RΪ½…Oo"β©^΄\€³ε6~ž2U]«jŽίSf%;Ÿύ†UN ½=ogεf»ηξΔ:`ΡŽΓ–;sY6v=cšQτΑzvν2 hŸF—ρIˆ>DY>[_[Ι¦Ÿ ¨°Ω―-]G5'ΜΏŠνΞ&λ” 8έqDqΥ ρεχ‰ŒΈ7 ‡»Œέ¬dΝ7{()΅ά5.7΄#6Βg<ΖBά IDATΏŒ^Df‘ Ž$z=OΞ”_Ιή ‘—bΰ‘~ƒ’$‡ε·/₯lδϊ„IιάE|ϋq ½'u'.Έ†zqζ²lμ‚Ζ%S2};3*±&%nBZΆ8μ_ˆ#šζμ|?w•=Rqθ‰ˆˆˆˆHƒσ~³p_, b؝pόι °^ŠΖ²ΠΚ=Ώ«ƒ±ό΅ –εh_€i Δψ,λpΝΞΐ¬΄‚£3"#Η„Nω˜Ρ&ψƒ0ܐ‘γΒμ™EAσ“±ŽrαϊakΝλ[ͺ0GξΖ\‹Β0*ŽŠ½¦ψLΖ]1šaΆ©ΒX‚1±5–+p'{ΪΕΆ©3Ψΐb¦O=μ₯πν,zb+—NHΫΣ?gmψx8[ŸŸνYΒX—t¦cŸvrQΪf9™Οχ₯ΓΆ –·π°―Ά3Žž–ργs3Y”μ νήstG'²ζ,#ίZCό3°ψΩ°Ί-G&ΉEΫYγγ€ί$wώ¬HΑu-­5ΌΥέφaFΔcΜ‡Σ{mq–VθΆΧμLLK –³NΑ², cρv́YΈfμΔίλϋΜ;Vα:ϋπιnΜ»ΖyΏϋΐ0·?–σϋbYŽ‘k`v―iύJΜΫΦγr`9»Ζς£b―)ΎίήΎΧΧk0#ό±œΫΛO!k π(ιsΓρέι—1δžψ›έ‰>―‡TzΆ²ιO‹W›³ΤY]¬ΌΖΕωΟ'σλ3YKςώϊ#Ώφ.ΒΦ_½Sˆ!ΙΑ€ί ?Η'ρθε!It{*ΧΡΥhXq„xΎy3'Ÿ‚κ0Ϊ€άAδπ€€ϋ€5ΜΫv°ko:--Ωl]κOΛIm‰K4€xΪ]›Nφ][Ωye T¬/Ε]]MΖΫλΘ΄Vέ·#•»+l„QΆ›Ν_»I»§ ©­-@©W΄dϋψ,vη5§E”αp”„TτμGϋž!X€@χΝ―{'Ίφ˜ΗςΧ·Pen’¨gzv«Ε|¦›‘Ho„€ Odέc…»8,ιKJ8a\ v›$₯©©_DDDD€‘ω6ιwmγ«ΩΫθxΑ=$Φxύo€ξAN¬σb0N;μ₯uΑΰ61δaΪΚ1O­€₯ώό`ΰΡMοG³bΜh…εΉŒνvpώΦMί€ͺέΉΓβ)Ύ6ίΪ930ͺ0Σ]π“Ο2jOΒ¨ γοΨ1θXΦρΩόL*<ΜΉŒΜvt^»Ÿ^ψ­MŠ.[Ξ‘=hŸ΅ƒU)ά”0ͺΘouΨδwNœ.Kύ<Β°αSχSΩά_Nep Ηλ’bψχ{’lΔ†lΩFι^“bJύΒOψ½Β€pB-Ϋ)΁΄„ ,ί—RšUΘώΠDάyμίU{ ‚ϋÞ"ŠJKΩυΰg{B˜Έͺ‰Κ’ΓAtϋΠΪΧ«αGΒU]ˆ½u1«ζœϊL<~΅ΙΙ ;!I‡z+V·ϋΨ)0WPžg‚’~‘ηΣ€ΏςΧ/˜›ί›q’<œΝ‰yf>̊ΒXUxh©ρ[&yΌάΣ“FςMΙXnKΒpWcφΚƒ~‰ΒΘχ(¨y_°‹CaρώηFQnάF A%DzV†™Ά‚™KŽZΌyKΆΧ’t7ξZ4{•ΧΊχ;qωωqόŽ &¦ϋ¨ΏϋλΟΞo#6˜ΐόRςΧ”ΰlӚ”ͺεd¬+ /8γΐ[$νξEςα= φˆ£ΆlΨ°`·y³¬‚Š*ƒ *ΚM©U֏ţ¬v7•ήΊ™%"""""u⻀ί,fΙίΑiχ+¨띢Σ?ΛwA‡2)³m)XΒ1FbTaZ0ϋƒ₯³έaMυv0 ΧΦ΅}KF΅ —―Ε5e?Taqœ€Φσ­9Ύϊx„™+ŒŽwτ!τ’/ω’ώ ½£Yο―9Π]Ώ©σRχ~μV,Υγ?ΐΑ¬’8»³ΫΦn3§˜3θXΓBPUω»LβSœ΄ζŽ έA΄ˆ70‚‚ ¬ΨGξ†ΒϋGUΖΚU9PD\΄α %ĞAY‘ƒ >ϊHΊKΘxi-e§υ‘Ώ²ό₯Lb™FΧγ]Έͺ¬ΨκˆˆˆˆˆΑg)‘Ήο;>9‚ΣGΤ0ίΡ"σ0ϋΊt™-‰;5wg7¬HΗ:΄Φaέ±,΅@ημο=P"fΧbΐ‚q_O¬ηvΗ:΄#–lš•cZ ψ¨-Φ »bνΫ˚c"ώγυσC0^JΓς·6 p`άΧΛ³IΩ†‡ρω’AΨ[ƒι»} ξΪΖΆ,`λ–Ύ ~·†YέO6f%Ω“Ώβ«©»¨:’™έ†LA±GύΔψc«E‘ψ—”Qφχ{ςη¬%k[9•{χ³υέ JΫ$“m`D6#½W%[_έ@ξ *²sXϊ6ͺ{΅ ){ΑαEμΫDT+~­#qlΪGQd0A6 0ž–Γμd½²Œ-«Š(/(§xσnΆ~’MΙa§YιΒmšΈͺά΅ΌdR2wks›ΡνςD/λJbφV|SκύϋQe”•ψ}œŠνψMΞ¦²>n„‰ˆˆˆˆˆ―’~7Y_Ιϊ΄œΡ’–³ΈΥΈΟ<Ψ΅·ΔΐQŒϋΥΈΟ+†¬pŒΝ`ž½ Χ;™˜‡ZMΈtΡω˜?ŒŸC1Jݘv:νΔ}K¦ΝcE ŒΨ€λŽβ£ ώ“υ3β°ά›Žεέ(Œά6Œy‰XieΉαa|Ύcdvdπcαl}|1Y‘@X?>–AδΓƒιΥ”~w₯gem“^Ο α„Y‹Θί~œ5–@RG„‘3ωΎΌq![*’ι5>ύ@KΉα ΩΈ~΄ΟeΕΔΩ̞Έ‚= 8u\³΄[IΉ%‚¨(#1Šˆκ2*bC²؈Ύ²?}šdMΟμ1s˜―΅δX 0wlbΑρΡ•KΩUYΚΦϋgρρ₯³YΉΚ³Jfn+ή+!qLb 8:ŽI ψνdξρnMΊ3σ)τ #<ξxηoŸˆˆˆˆˆΛθσŸIζΌ‹Η`·› ΟŸ?ŸAƒω4ˆi%Σ|Ί}˜•lβ+6¦žΖι—‡ήKΒ™Λ²λ–aΉuέ:ύ/Œ—8Q&ωο|ΝΒέν~{²ΗŽ ηΫ°D‰σϊέΧί«"""ςΏaΑό <ψ˜εΥΥ.†NŸZ?“«‹œ ‰Γ“p~ŸΙ>O§tίUμ%σΝΞH¨έ“DDDDDΔg”τ‹Ζή­νSsΨ0―D]ΠkΕ€δ› δ¦·§mgί> TDDDDD<§«s‘Á4ΏkΝ:Ž“ŽAπ9§1βœ†ŽCDDDDDΧ(’~ι•FoFC """""R{κή/""""""D)ιi’”τ‹ˆˆˆˆˆˆ4QJϊEDDDDDDš(ŸLδg―ε£η_䣟Ά°ίNΛΎ2nό…tΡΓ»EDDDDDDκ‹Zϊ+ψ啇x/―·M}‡wŸΏήϋίγαΧ–SιύΒDDDDDDDδx?ι7‹Ω•]Jϊ€tkETrΐFιέ”˜^/MDDDDDDDώ€χ“~#’.½Ψϊε,έλΔΉw ΜΞ€EοΞD¨wΏˆˆˆˆˆˆH½ρΑ˜~+Ν/~€‰{ξ䁫‚Γj₯ε₯ςΠ…)š5PDDDDDD€ω 7)Zύ)]jeΰΥΧσΧAρμψjίn-χ~Q"""""""ς‡Όί_½†·Ÿ™Cμυ/3q@§ΣΞCάόΔ{΄{ρZΪψδy"""""""r4―·τ›%ΫٞO›V‘Βo#sgβs·°­T3ω‰ˆˆˆˆˆˆΤ―'ύFHkΪΖmcΞ Ψ²·‚œuΜyϋs2R;Ρ6D3ω‰ˆˆˆˆˆˆΤοwΆ·΅ζ―χέBωσoqηΥOPj yόσΎKHΣL~"""""""υΖ'#μ)CΉιΙ‘ά䋍‹ˆˆˆˆˆˆˆGΤφ.""""""D)ιi’”τ‹ˆˆˆˆˆˆ4Q>Σ_[ΣJ¦5t€ΖkθDDDDDDš$΅τ‹ˆˆˆˆˆˆ4QJϊEDDDDDDš(%ύ"""""""MΤI‘τ[WOηΊKoaό³+Η$"""""""'ŸδΠΞάΕΌ9υ5ζ¬ΨI™#ΓFρ·1ƒH²οέU€ΌzχuΖ1―”ž>Ž·zϋ"ΚFΔ4ωρ’B¦Ο?r±₯΅?_θOr#ΉΣαήZΙ”KݜχciΗ=–""""""˜x?te0ύα'ω1νFy­Q₯kψθίΟq›±Ϊ½ψ }~ά…_P"›/ΉœoΕγ(Ι€Λ»ŸΣui!U Ϊχfρθ³Ψkΐ(ΨLχwΏ€Σςl‚]μοr*‹FNV€cŒΌωCš9NΜϋG{ޞC«ΜͺŽα±νpώαφ!εΥ9ok7–€n€ΗON2FdοΒιτΩΞ/wOΰηt«Gugψ„ΗsQνfνSε|ωΆ“=…=ΔΑOϋΣ:¨ͺζύ₯,ΩF€Λ?³³~|9«3 ε`nH«δ‰ ZeU±ͺΨΖ™·[XρPϋ\?˟”ύTΙǏV²~Ή›r‹…„aF>ν =άΛ+˜rU%;sMͺ]ποΈJμηρΨvΜ= ƒΈΰ|+LJΎuρ―`†';ωδ7}gyo+V(Αi!υš@Ζ/ γώοιVRΙ;O:q–ΞΖώΚ}/ΨρOqpΓ¦0Ογαi΅Hψ0°ψΩ°:,ΗΚ!""""""ήζυ–~kRΪ:>γΛΟ6ΣύΒV–eρύ±ΊΊ’τŠΊtΞ7!΄s»Œm…tyθ­ίI\– £j9V—γj½η4 ­U$ΎύΞ^F›Μaδ—/’σΦj\-ΞζΓ‡†‘gμ₯ϋύO2`σ":­Κ·βΨ6bΉKh»-3ν\fά;„Όƒ΅cd/ώ“νf€5•_n=ΐ=G/gwζίMŸΏΝ$’¨ΤγύΫωd1w?ϋϋ’ΰKƒΈλ Φb'ί½ }ή W―υΎΧΑ>U¬Λρ£"X ’ΪY2έ” βΜ3¬XΐΉŒ6:χ΄RΥΝΐ?Ə­ΈRLΆΌ'amm§λίJΆqΪU6ζMsQθΆe3π[ aG˜Aΐ‰Œι7όH?œΔXUDDDDDDjΟϋ#Ζύ{2ϊφ³xτι›Ήπu«_ύ.οK[Ϋ ukίu§Ά`W F…qΜυU؜`ΙΙ%άmb[ϋW_ώΡο+Bς\ξέM€iPΤ‘5V€(v΅‹Δ½i?‘;‹0:E6W€…=}»‘XΝόωφφ^0lΈό,`€i·γ²X01±Έ<νέ`06ˆΡΧόή n 6°ξν.r‹\¬½°E‡Uau₯…ζΉpDm±Φχ@ΒΔΦ# -ΰvΔΨ « \Υ&`ΰΚ¬fξΓ•¬όΩEq Έ«MͺΫΰnΊ“(ˆˆˆˆˆˆ4y>˜&Ξ ’η΅<υή•η—b„„γΏι%±'’SΗΡώ~8&½¦qXφk±`bΰŒK#+9θ°Plμ 30φόϋx μ1Λ ͺG.aϋήb ·‘b9ώ˜ ›3> €{δ‘βwΤϋ π ‹L^rhOψσν[Iψή7ϋυKŠ•8Gyy‘]}0ΎΨEζf+ήpΠ!ωΐ’‚―Mͺ Uΰτ~""""""β>IϊΝ²ύμ©°b/ίΕͺΩ―3ν».š4ˆpΝήfFχ`Ω€ο8gώ·\xσjφ¦FQUUHTΆ?Λ›ΐςv§ςkΪRϊlΝ…wmbŸ%—€LΞ΄Sω΅ΏνΛιφν―€.-ΖΐEΒηο2,»5‡ŸΖŽ(£†νίΘ>ίμΦοBm ΈΒΰ₯;Λ‰ΚA—φU;]lZ mΖΪ‰>Ψ—ί]nβ2ΑYnbbx>Y^€…°7ΏtΡi€AΕς*>Α…uδΐ}Kš…ΘύU,ύďΈAΥ…œnΑγQf%ΩS°Ζ‰Α7%β§ΩόDDDDDD|Κ'IΏkγ{όύξΟΘ³‡Σ¬}zςΞn}tŸr/2‚ΘΈφ&>ώœ^ίm$f}f`ϋ;υ 7Ψ{3–ή>σ­/ιΈzΝ\μο5œEWŸΞ^„ύϊ=½ζd–;2‘}vDYkάΎgδ«Σ’~oW—3ϋζ>ΝGœ…ζϊΣΑχΖJž?«œŒŒΑYΘβ@ ύή eδ@6ο°1μI;οήSΒ#@δ©~œσO?φ½|δΫ,m\|Ώ›ιχ—πΰ>θεύ³$z|™Έ+8-ξ{WˆˆˆˆˆˆHέ}ώ3ɜwρxμφcΣΧωση3hπ Ÿ1­dšO·/ΫΈΰq ‚ˆˆΟ-˜ΏΰΠοΎώ^‘ ζ/`πΰΑΗ,―>πlω‘Σ§Ξ89ω)ιi’”τ‹ˆˆˆˆˆˆ4QΎ{dŸˆ‡4§ƒˆ4Ν)""""MZϊEDDDDDDš(%ύ"""""""M”’~‘&κnLuξfΞόŠΥΩTΩΒhwΦMŒξνΫ»ξ|ώΜ³|³Η €%z7ίvΝ­Ύ.β“_ΆQ˜FbΙx?Oρ‹ˆˆˆˆxΫ &ύ&Ε[Ώαέ_γΣ}yτΏΡνπ-Uf0ϋωgykΑ& ¬1΄<Š[nFŠŸWb!΄22ŸψŽνpΪΉΑGΌXΑšΉ³X4‚±wt'Κ(£Κιϋξ–$†OxŒ‘nηΊχyd^-_—“‚Ήk# © σ”.D5Δ ›Κ½lzy;[9ˆΊ½£ζUΕ/ΗeR΅9“uέΒΞuΕT[ˆθߞξ£S υϋύ=%_όΐ+SxwsUχ""""‡œ@Ύλ&λ“»ύχ7ΨKπ1WU¬}σ!^ΚθΘΝSήζ'."dα3<ςώfœήˆΈΞUXΏ=φgπf)…ΕnβΫv#5"„π8’‚κ£EΞ‚έαO@@~ΗΛkz]NζΎ2Κέ W~εO[ΩΫ±Ι»6±m‡ιƒLŠ?šΟ·3ŠπΕΦ}Ώo5\ό&fc¬.ΣτΞybVϋE&e­ΪΡοίg1όΑ„¬[ΑΟΆ}ƒΰaνHΨΉŽuΛͺ½QͺˆˆˆH“q-ύ’ϊ\ΓC§¦ΡjίŒy¨όΘ—λ˜· Šaw^CίT;Ώξ"«Μ$χλΉ¬ϋk+:ϋr@YΕξΉ;±@΄γ°ΕKxλ•Ωl..₯¬‰;σ>ώώ`Mη‚;&00ΐ¬ΘbΡ§3m6ΕF)‡qΑΩ½IrΰZΟϋΌΜ’RΓή…ΛohΛϊ韱z?€œ1ρƒβ©ΘόŽηόΘϊϋ)7‚Ih{#G!½>šœJrX~ϋRΚF‘ίA˜”Ξ]Δ·{Rwβ‚|uχϊUΜ}ΪI·η{χ[½•g³dμjόοN—v5έq³ηΕ/ωaNΕωΦSzsξ])5ŸdΞ\–έ@ΠΈdJ¦o`gF%Φ€DΪMθAΛ΅8aΜJv>ϋ «\z{ ώžV½εW­ίΜͺwΆ‘³₯”jΓAh–t½‘ Ρ!`n^Η‚'ΆP_…Λ σ/ά|`OνΓy›QηΫ8ž_w1™sJIs ι™ω|?k7-'$b7<Ϋ?_ςθόjΔρ{t~7dόξRΆNZAiώ΄_mοcz;>wωσΧ³ζ— ΊέΡ’ΰΊήW5HΎe0ΙΏύ›LλA[˜·&*3μχŽhš°σύά]TφHUO ‘ƒNθŠΣΧ†v€3ΧyLλ½Ή₯-9§•œ|τς|βF]Mσχ—°eΏIη8^‰Uν'gΈsÎhε7Βzpι„ΞΈέy,|ύίlμr;£{†`ό˜Ε¬όθ5Ύ*νΗγ―!ΑΜζǏί問Έύ’Ξ[ΫqΙέsFξώ;νζ~TN—³ώΖ=1ε”Xb±`ΰŒ$΅Ο% ½4–@W.Kg½Ε;sSΉϋZϊ~β„ΰx:^—ΘΌ©«ΘκΡ—²Xυ~ IzטπXZ'“δΏ˜Ώ:‰λy ZΧΖ\φ$Π»₯'WμbFηΌ+όe–νaυ?—QΦ9ςΩ»σψ¨ͺϋγ―{οΜd# ΩI ϋ²Θ*²¨ΈΧ­ώ\κZ—Vmmkmmλ·­Ά΅‹ΦΊ·ΈU­mw+ (‹ Κ"‹ ϋ’@XBΘ63χώώH’Μ$“Ι$Γϋι#Ι½3ηœ{Ξ™›ϋ™sξΉΑΌφ>Φ½K[Ne@†—]Ο/`Ω“θτ§ή$4˜–m?Λ#Δό]‰ρ€ž9Œή}:ΰρdσΣ‹XόZ*SnΜΐμΦ›qφΔΏψsώχΟF=0€T pY‘όTϋϊWΓfw>c»™ΔuιEΦ›+ΩΈ³3½² Ž/œ‚ι_a-Ιf>ύΑ;μΞdΘ££ιšπφοˆΦΏΩ‚k{ςυ˟σΡϋΙtΏΊ?έΕ7mW‹”Ο¦lωV½ΈσpmAuΐrύΛ‘κ@Fœλ¨ΊAΠNxήίŞΚδΔ65]‘θZύo0ρ=°Œ₯/%zW>qΑτΟPΚη”³ν₯₯|½£3'ύ΄?y]έG$Z°ώρ—²ρΡeζυcβ˜zNτ1ρΔu¨ |― ϊEDDD€0ύfr I«™Β3|9θώ> ͺ°―4¬pΟ#ςαχxš=₯Ϊiπ—: žcΠν|τςK,M;‹ ΎΣ‡N<8λ§σΠgΝ¬Έ| IDAT,H39eTTTPQξ@bπ½Fn.Ήζ°uiΩέ )<Τ‰~}›X“vπεS…tόξ$ς2šzΑm`Fτ’δo—°ξώΟΨ©?ƒΦ‰Δd gΕrfΟhΥ6ΨΎFVON}μ˜Ηe1챬κϋ ΄ϊ΅π€ΗγΑΑξ`bϊγHΘLhwυ―°—Ώ₯¦—7ΠΏΓ_€«ƒξ?~΅η%ΓEμQι9TίΚΧ]ΛΦ’$Ί^>‘3G'W―)”ΚgΔ‘Χ™tότkΦ<2“u™]θ}qOΊτ¨νo©ϊ·ΛΩρω¬(Κεδ{»Σ‘ήΣ“‰εΆ©ΤZ~""""‡΅x˜e€φ {L›;œŸ<9†d|ί¬βλΈnœ“ζ‘·…ιυ7ytΨLλDšχSΆν±ιΧ©ϊ‹ »h+;μ4Ζ₯ρEEεV6νΞε”«N₯GpΨο+£U―;νR6>ΉŠ²ρ£Ε –>Ή‰Μ» ͺ§Γμ@ξΈDΎώ΄ƒ₯…T ξIzS±θT°ν™/Ψ3`“ΖΔΆΚΰw«)ΫGρφzόΌ3ͺΫ·όσͺκQώΊ 0|ašjϋFZ¨ύ+-1½<ύΫ°ˆΙH ήILN۟ψ„εί€ΙHN•Τ„`Ώ₯Κη&yL?FŽξIΙΒυ¬ωϋG¬ι6ˆρ·δΫBυΏλΩy,YΞπ{“•άΠ ύψ«,\­Υ·DDDDځ–zwυετΣς‰IλLrΕ^Š7ΚΤ|€9a2ύΒ<’k€Ζ[ZFYeί—4˜qύ2χΝ¬Ω]BΙξΥόον”χΛΰ€#WΟΆ· ΏcγσϊžΰN&9vkWma_ι~vžΑΏ?ΩRΟdΏίΗ>>` jCJ?\ΖͺΒ\NΊ"›μΛ‡½}%ΛfjΒ#³ βGw!yνVΦ,>DΖ¨τ&̘p(Ÿχ_IgΐKΗ,σβ=δΕ[a‡εΡn £’νό=Άƒͺ–Μ8&–ΈψC.ΪGΩώr,YΓ7χwlFV"ρ Ω<Ώ„Š’ ν(ΓwΤ‹lφΎπo\΅˜U4AK΄oK0HΌh"“ΎΤŒ 7”ώ"ΓElF ™ΗόdΔβ κ@ΪHnE™£9큓ι;:]†›€Ρ}9ωΣ}fRu‡ZN%E/ΜgΡgψΣdΔϊͺλΏΜ‹ίΜk+Κ(+%>½ž„kϏl§²m4œˆˆˆH«hVξ[υ4ί»ϋmŠ|U”U8ά}ρ,ά)SψΝ³·r’ΛE―ΛοζφύςΔdΣ‘ήnζκKkΒ5›Ρ9…dk+ϋ6Ϋδ|Μ\έ7v`ΠE7rθέ7ψΟc39@]žΓ η&Ρ»π#ϋ{l,χUγOœOέ©Œ½ζ—\ΤΣWONϋΦώωφόώ=‹Τn£9χΜΡμ™_“Ύήyμy•Rξ³qxτξωΔvθΚiί½…Ι™›ίίΉρcq 7²μ•R²4’Μx€N Έ‘3³YΖ¦Αc)Θ . 0rΘΝ[Αυ9Œξί”Gεbλ;;(ίm³θζ-‡7›½rz+¬_§ Ψ•>|f cξLϊܘΛgΟ~Β/š$τ+`ΐw (}χθ—]z0τͺ–Ύπο=μΰξӏρχφ>²$„γγΰΆr¬ώ‚^ Z}#­Ωύ+ΪLn€α&±{ΈΟMΤ’e*ΩΑΪwχαυξγσmησΓyΔν7g3tΘ‘°7νγ€'™‚zŸSs~ ­|Y#""":ŒQSοwf]zξz–Ÿ={6&Nk!ώ^ϊχ–IΘ©dσŸώΗΪγ9ύŠ”θšbή*όks·χeΚOrΒώ%Ν Η_Μς[ηsθΚ3}Κ‰8XύKΒΙaίΛ3˜·³/S~Ϊ%θ…LΏίαϋα-VsfΟ9όοp]‘ÜΩs˜8qβqΫ½ήκ)‘“_, Σϋ#Ɉ!{JΎO6±§‰Sό°KΩ΅΄’Μ±™ ΘΒΐΩΏŸύUYδ ;~ΤΏ$Ό*v³iŸά3:7αΙ%""""Ρ/Ί‚~ΐ}R_ϊuέŚY₯šΒ,ΏoI9ϋf¬dCI')$ #­;γŸ;™œψH—€•©IΨ9”Ξ\Ca·~τԎniΡwudΔ“‹3ɏt9Ϊ§h#σΌ‚ύIιτΌm('θ@΄„‡ϊ—„ŸA‡sΗsζΉ‘.‡ˆˆˆHΫ}A΄ζ=‘aΡny'…¨₯ώ%""""1Q7½_DDDDDDDͺ)θ‰R ϊEDDDDDD’”‚ώ£oχΔ:ω\&βκ=λoI‘.”ˆˆˆˆˆˆH³43θw8ΈaΈσ2ΞΎμa–ωšΊU©˜½'αJ\ύ“5ΧΨ!˜ΣZωΩf%˜?κ‚±Αύχγτ©ΒιYΦΊei!ΝX½ίfΛ›ΏδŽg·uH&Œ¦ξoDLΞΔƒP‡ρiζχ@ΟΕΨœ¦³9vΕC©ύ7βp#Žžm """"""νX3FϊMrF]Η½ΟNεO—ΰψ±ψ@ϋ‘TŒύόrόΣγΏ© ͺ0Δΐφ\¬¬šY]a.ΘΑœ<W§IΈnO«~oQGΜοΗκ>Wή8¬k 0vΦωΖ‘±ύϋ;b^= λά °²Vζd\†c~Σ”o-DDDDDDDڎfe[zΣπϊ¨oζ~ ύPQσ}„ˁΤ}Ψχ~ƒω―<Œ/0ΏΉ%8£Λq&•€·敃1—šΠo?Žρv7¬­ΰ#Ž`ΏίΓ ύΚa^€–βŒ,« '‘Y """"""q‘M`·xh±J0― ϋ0ΗBά~œS« η¦MΨ›³±–ΕΒΰ―ρOί‚γ©yί'έ0—YpόοoΒ1γ1Ο‰ωyΖ§›qŒœΖχŸZŒύB1¬.ΐšΠ £χό/nΥ2‡""""""΅­°Ά2γƒtŒenX„ύό*μξΗ~m`γ\Pt$ΰΗ€―:TΑpΚ^7`•γŒ©Ϋ±ΖxΏˆˆˆˆˆˆHj[KΥelΗΏbM€Ύ‰Gί4`Τ~/Pί΄'π~‘hΤΆFϊ›ΕΑιsLc^*†πΗa| ¦§oUΐύA+OΒΌz8ΦυΉ•α:‘–ΡΆFϊ²²ζKοyγρώ˜λφβάΈ 'ہ1Ϋ±uΖ\Φ krG+cΉ ƒ·γŒΆΑ °?Xλ20>HΖΐΒΈc;NM‘Ά«YAΏoΥΣ|οξ·)ςUQVαpχΕ³p§Lα7ΟήΚIΐϋ›ΖΐψΈ ζΣΙG6}•ŽΉ&{άφκ ?ζ φΛΛαWέ0g§`ψΌ8η|ƒύ§M5· Ϊ€‚}8½r1\Ε8ω ψEDDDDD€mkVΠοκ#ΟL»±ΩϋγΩ‹½φ#κswpn]‚οΦidcO-n  φτ݈ΏpcΓϋ“φbΟϋΈρ4DDDDDDDڈ(Έ§_DDDDDDDκ£ _DDDDDD$J)θ‰RmbυώΫΏι"„hE€ ’ͺA#] τ‹ˆˆˆˆˆˆD)ύ"""""""QJAΏˆˆˆˆˆˆH”Šή ɟαΜ?€·53-‡Ώ\7½vkζ+""""""rΌfύ7Μΰw^ΖΩ—=Μ2ίΡϋJΦΎΗγΏΊKΟ?“³.ό?~ψC6W6–žž½F Γ‡Γπ0z<»yΕ —-/ΒE‚―‘XžΩ)­Y*‘z5cυ~›-oώ’;žέJΧ!™t0ŽΩνμeΙτχΩΥϋj~ƒώ€”|ΑKωχ½ήƒ'κ†Uoš|χΈΎξύΈο…_Œ‚cӎ΄Β`{y¬ΥŠ#""""""˜fŒτ›δŒΊŽ{ŸΚŸ.@ό±»4&ύόQ~wυxze₯‘Ωk"—žΦ•ν_­ε  iΓΰrπ{ΒΩ7Γά7ΰΪs`ΜXΈό—°ΊμΘkvΜ†Ϋ.†±cΰ’ΓΚ:ϋͺfΑψ‹`•ΘΆEχΑ”ΊΣΛΰ½ας³`Μh8λJψwΝLƒUOΓΩ“ΰΦΒΆW`Τπκ ?ŸQ½ί9? #jΆ_υάρΣϋKΏ‚{―‡‰γ`ςEπΗ· Μ ώψγ_Γ_ξ}Œ—ΏZΐώ-S~v'η?πέΦθτ ‰r͚ήouκMί ψ} Οt?ΜζΰƒXρρΔ„2rο_ .Ÿ< Σ§BΑ ψσͺƒk{ όζ7`Ÿ ―Ύ χŽ…ι3›p_½σ€?/«ώ oΏΎΊ§Wοξs5Όώ&ά3²Ώ 3fΓμΩpΟΔκύF2όm.|<~8΄žδχΒ}wΐ±πΒtxφ§°ιQψΣ¨ύ"€±γ ͺ~ΆςΚ;λισ­πκ―~Δ͝6σχΞc‹Φ9a5czΆC Α{ηΐ§LŸsˆ‘7&6”Όœ ΚώύβSΰŽuΥχΧοž «s`ꡐgΑEοΒΛΑ&^ o~gίgχ«ή”6ωΘn+:Δ@œ 7$&ΦSs&Δ§@r=GY4ζ₯ΓσΧAž €ΓΓ †έ§BΗΗΧΨ‡ωιzςΩ|+? ˜2Ί?Ο=·ƒΝvM–""fΜ™='E‘DxΓAίvήΰQ>οz 7œšΪ-ϊF<δw:ς{l,Ψ5σ w€«t­]1ΐ„Α― `Βv?τιJ Ά}3Δτ„.uͺ;Ώ7˜[a[ΝP|cΗ”Ίdv<ά †ΗCŒγΗίθ{DDDDDD$š…/θ·χ0‘»yjΧ)άuΧyδΤΏ‚_ΈΐέΠ>Μc2p˜Δΰ«σ,?§fΎ‚•λIΧ9vŽDcΗ whσ6DD€ 4ˆ˜˜˜HCDDDΪΉ˜˜πuα }|φΔ]άΏrwώεVF€„yώ¬π€]΅sΩmΨ²œάšX`VBEm mΓ¦Νΰt―ώΥΜ„N¬ί i8ΣoSFίkδζCε4ΨjC·šοY6δjξ½ˆΘ‰dνΪ΅δηηcš&†a`Τ|α\ϋ•+Wrπ“"YDiη–-YΖ€"] ³΅kΧ»wοHCΪυ›φiΛ–-δεεαΤ ;Žƒγ8آ͚5k3fL£οoω ί9ΐ²§ΙtαζίίΐΰΨ2JKΓΔOL£#ώNΝΒ|M\}.k< xω7όδt80^_ Τύ|ΘΫΣ>€Ό±P4ήXΤύFœ5ώψ7ψ –{7Γώ ήεH>Ή]a;0sŒLƒ>θιΘ@ΎΏΚͺͺ_šƒΝ˜§<<w]ΞZxπ d˜±bΛpρρkρ$ηςχΛ“άΦ‰("r¨¬¬ΔεraYΦα ίΫL39QΉέ!M”vΐ²,΅³4™ϊMϋδrΉ·[mΐο8~ΏŸΚΚΐOlkVΠο[υ4ί»ϋmŠ|U”U8ά}ρ,ά)SψΝ³·2€t>šΆŽRο:ώzΣ'ό΅φMF*ηώιU~<¬Ύ,ύπΒχΰ™Pαnw;Β Γ5=Θ́ίά Ώ.y²GΓυWΒcΕ5ϋ»ΒOΏW½Ό?A·ρπύkαΑΒΪΒΑιΏ€ύΑc·@a$eΑeχτ\?؏\{mtόύjp–Β₯?‚mε`;ΐ˜π<Δχ§¦BοTψεƒπΠ_αΪ©ΰ€Γ€[ΰΗ“ƒ_w EΨx½U”£{ύED"©6θ7MΣ¬žρ₯ΐ_Z’ΗΤ*ΐŽY–₯v–&SΏiŸ\.ηπHΏmΫΨΆτ΅ƒ1jκύΞ¬Koΐν>~~φμΩL˜8‘Ε \ΟςaM_W5h`€‹ "υκΨ?tθΠγFϋk͟?Ÿ!ΓΉΥL$€/–|ΑΨ±c#] ³εΛ—3hΠ HCΪυ›φι›oΎ‘[·nGςϋ|>–.]ΚΔ‰{Χ[=Μ;ωυΗΒtOS ι΄mK–DΊ""‚Lөݎ§ _DD€q΄’_«p¨^ύ8Rυ]›·Ϊ;ό"έΞα ΕΨΒOύ¦}ŠΖv uύ"""rŠδh»νh€Ώ΅Dc;Gσblm…ϊMϋ€v;ž‚~‘ΆFΏ­Γ!bS@λ–Aν~oη08‚·HSΏiŸΤnΗkfΠ_ΑφEΣyώ…ι|ΆΣΓδ{Ž­IΚ)cλ’wωο»σXΉiϋύθ2ψ Ύρۜ”ύLDDDΪM­?1Dc;ŸΑ[€©ί΄OΡΨn­OΏo#oίw/,ΫM•ž£χ;ψς½iΜ^GAοώtΪ»ŽU _γ/tζɟ')ϊ׎‘v"G„δxΡΨΞQΌΩ…Με-½–3 ά)‚ϊM˜Ω»˜ϋβΏ)w ητhΉ΅ΤnΗkzΠou’s*Δζc„g) Φ[’ΜυΓ?2Π“KΧ$ §d&χ|χqΎ,*䀃‚~‘ˆ9ΔΗΌG—vδμί>ΜυύΎΆ·ώ—»ξx•ΝέΎΓίμ6tm6Ρwmf•¬šώwήΖWg›Aόΐ‹Ήωτ|ΪμaQΨΞα[­ŒӞaIΖ₯\3.‹κΣ€M3žζM½ωφυ“θR“΅SΌ—_ΩΜ€k/ε€ΔΎΘ7³8εκ›Α±±#Υ~κ7Mγ`ΙΏžη›>Χσν!‰ξ5Ο›oιΏ5QΨn­τρ »αažςΈYρπ5Ηύ€•ή•€γ-aσ’εlσ›d @Φ‰pρ ""’πMM4p»,22–,ψŠ+ϋβΘ|=?›,δ`zn—+*'H-΄•σŠ–½Ηάo*ˆ+Η”‘šτΆΗΥϋMΓ cΤU\9*½ζ’ΎϊΒ½-_ζ…Ξ·­bÞκ/9άiέιΫ%±Mkψ½G—Όt>Ϊ°ƒƒNΙ`±y›Wεf6νΆιRsQ_Ύs;ϋRςθ!eq°#νΧ–@ύ¦9ιGϊ±€j·γ5λž~#6žxΌ¬ŒXΕΌΏ|‡Ώ,¨#ŽΌ‰·πσ+ϊ™‰9"""r„EώθΡΞ[ΐΚ«14Άf³Ÿ~j3zlwf>ςj§|#³žŽ7>έH‰»§\ΝM— ¦£ 8%¬šφ4/Ύ%[ΨΔuκΙΈ+nαΊQ1|UίφΡι”,ŸΖsϊ„5[Š8heЌλΈυς!€ΰμ_ΞλO<ΗVμ†ŒLΉz4{ŸšO―ϋΙδd£yeΡθhSσ§:˜ξb*WπΞ΄…μΘθ!§“rBΜh40, Σ΄ŽΎΆw1χεπLƒΡ,>ίƒ.ΉŽS³ŠκߞΎ›/η|Δgλ 9δ$Ω}' ₯sl#ieW°υ³™Μωb{Κ<ɝι;φL&φJ _;»@…‘D—Α“8sL> Ncύbζ˜“¨X6Ÿ―vΒHΜaΠ©gqJ·u§~wΫέψkηΠf̘Ε[J )!γ{Q:k-ΩW^Μΐψ2υ›αλ7 ¨*lψs€ϋΏβΓW°fwξ΄Œœ|C³b΅[-Ì@Π˜IZΟœ\q€=›Ώf㜩ό-9ƒ{DKΟό‘¦qςFqj|ΊΌœ‘'W_ΞxΧ,`‘g<·wYnjڠί9Θβ§οηMη ~ϋμ$²JπΔoαοΔ/NΟΐ^χ&O½ώξNοδeηšeμLIΓ^χΟz·$$η1μ»Έy@βvΎΕξ~–·†=ΔΥ½πρ?f–q9Ώαlr-㕇bώΑτ7›_–@—‘άϋ™Φ-‡/O#χŒSˆΩma8νmΜ>υ¨αμγΛ )u>7œ›‚Ϋe6°½‚΅οOcAΕPΞ½κ":™Ε¬ϊθ¦}ΰαͺo ±΄μŸρα2›aή@Ώ$?vm‘$1!¬νœ–BΩg_Π±/άΫN;‡4švzΉΦjΆϊιgR²u3:ζ[U¬ZΎ™’i$;{ΨΎΓ!ϋ”N˜€'Ά#y#Ξb|v*ξ_πΞ3Y\p=²λ»Yςρ׌;λ2nN7(Zς6Σf. οϊ3Θ7λNύπZ«”U3ήaΉ3’‹nDΗΚ­,šρ?V—w"ΤoκgΏ9^kg4φ9¨δλ/73ρμ+™βgΗgοπφ;sθxΥΊξU»Υ u€?L_υΈθ{αάύλίσΠ£w29ωޝΞΒ’ΆPe"""mœΖΐΆ³3!ƒeσ–QjN%_Ν_Lς©cΙͺ}Ζ°ξϘΉ$‡wσιδΔψ02Ηrε99¬ώτ φΩ€aβ.Μτa\{UΝΐ‘”%ˆϊhV\Α‹Ώ}”Ν§ίΓo.HnZBσ.ͺΒΤΖαe³ϋ³WxόρGyτρGyτρ'x{MeΝΎ*¬n8­_&ρ7Γ•rτv«lΛ7Ζ3tHς’bπtΘa耑€o]ΖW{†Σ²Α1L<±±xβ’Θμ6žιaΌGΉr ߝΝή~pώ:&ΔqŸr밌0·+‹.«ΨΎc/εlέΌ›¬ό<σ ΘΪ³‘­εΰάΑφCΘΛCtuκΛI=;“ο!!«½2ΚΨ·Ώͺ&Α†ϊ€<…α9Ix<‰t1„.U{Ψ}°ώŽάΠkυ|΅5‰‘Fΰ!.΅'γΗτ>2B«~sXXϋΝ1œ`>η>pƒ³ρΔ¦Πmά)τ±Χ³f›WνV‡βΒ-?ο/eY)‰Υ βΨ^Ό68ŽŸΏΕs‘¦r cΜr³€eGsŠ{ >ΟdΒ·Σq–y™]Έƒ+yςΖKyΊv£Ώ _φِΪηn=υχά£πα˜)œwώι ͎Γj`»Ÿέ‹_α΅·°zΫ^UωρVx|*Ψ»wQhu%7₯œ*?@ώ΄l:›;B*K8F„œƒ+yωΎ'ΩqζοψΝ”t*½ηςΫΩ”–VFnΑ±Ve:δBΎ=<νπVLνꝲΣ1μcGǎήξΨΗ~#‘IΥMΰΰΔ§“·Ÿβύ6t¬?-3g“zOηƒŸeEο! >˜ξy’T=š5ςWΉ“ΕΞ§dΰ…œΧ'†rοΞ›\ΣΞMO­Ε…wφrΊ€3sγUΖ±yW*ωβ1βσΘOΛ7[+θαl£Έcrγ ΐ¦dγ"ζ/YΓΆβR*}~|^?yύjkͺ‘~a15ωpϋ8¦ ~κΏƒΈαΧ:%ϋ8`¦‘~Έ?ِœJŠΉΏϊκ7‡΅ζκύΑ}ΞM’“Χ΅M ι)>Φ–”atW»ΥŠΐ=ύΏώ„‹7°rƒ°YϋΏ—xuk?Ɲ5’άͺΟxδΖgٚS@nG%›Χ°ώΔ8™Α'ƍn"""mœƒ:’ ω―²`Ι~†ΔΝηΛ.“Έ&Υ>ϊβΖ0 f$·=y;'^˜Η¨žj:ΰgπMσκ…KxηΥxςg2πΦ{ΉmtF½Ϋoις ϋλ‡$Ώςλχ =v?ϋέOYY›—αΰ·9<ΡΑΰπuN³Λ’Ϊ’χ~:WςΟ?>ΕΞ)ΏγΧS¨(χβΰεΐΑ&%ΣΞX1q$$™έΰ8՝ΗΔ¬wϊpΫλVΏγG¬Ύχt Η€«ωήЍ|ωΩ|>|ω ΊNΉœ³zuhΩ{|+w²xΖJ\Θy}<”΅ΑvοbiI9ΉtX΄ƒΫ=lοʈd€dΊζw`Ι–mμ° ‰ΙNGΐ)^ΒΫo/#nδιœZ&άe¬xλ_μ8œ^cύ"Ψ2ρΪΊΝluϊ„ϊM­ˆ,²Χθηόψ…χͺ[OνV+ΣϋmŠ?ŸΖK―ΏΕ’~§Š­‹ήδΥ—?`uΉƒαΙcψ˜ξΔΨΜͺ/V²΅*ώ“―γξ<ηΔxτˆˆH{`'sςЬ?‹™sΏ’ΗΔt8f8Γμά…l{Έb\5?–«φbΪOEι^Κ:τεάΫβρλ2Xξkψj—œ.™@UΡφ$ΰ”“{’Υ1‰ρΎΚΦλίFRΊ jϋ IDATG’μbφ8’§S²Ÿ#w«ίΤjΝ‘ώΰ>η6ϋχξ?r΄ώbvοw‘œ’€‘v;,#ύω—=Δ΄ΛΪίƒ³x/g‡R*‘XΈ.Ž€μΰΰ'aΔDϊ?ύΆFsΗν±ψ±ημΰ@ς(Ξσ*>5•μ›Ξc@:”l]ΓzΖLΓήό)3Ά'Σ·GΝb–~΅‡ΈτLbΆ,ΰύzΆwΜΜ$qοrζ.ΓΔτƒ¬ωπu>)vΘÁ΄“™4π%^xωz^?ž¬ͺo˜ωοΉΫBY⍆kΣΑiς=πVηρ\η£ΌΜΧ"­Ξ‹ΔπqpόUTVV=2,7ž¦Δρ½Φg!ο}ΌμΣ“iμcυΗ‹)ΞΛ9 šOkο^Λ—ϋβΙν”F‚yM;αξHΐ ΏM¬b3©'ƒΣ|j‘vΓ σˆ­•E—¬ƒ|ΈΩMοs:iλΜς*¦σ•7—ΙΩΥΣn\‰‰ΔΪΖϊmϋˆK*gϋ—σY]κήf$φ ξ<ζΝύœœIύθθ+δΛ…k(u2υ›ΊΒήoκ ςs^ΌrΛrO₯OŠKζ³ΞκΕω],΅[mtυ~iλμΈ‘LΓWξ Ž­'vbρΓ?qΛsσκοΔ#₯Υ›‰Χ ¨ήoβ«7^ΰΥmϋ©r%“7τ|~qΣ0bŠή«w{BBo~tξ_yμΟ?ζΏF&C.ό!·Ÿχή°“˜ψγ»)zπξΏύ5œτœ}ωΩτ[»:΄²PΥθE\“G©}ες5ν-ΡΗaχ’Wx|Qνορ/ζζΙMy°•‡‚Iίf'2λΥΟ(±γΘμ>œ‹OHR£_ƒ”³eΡlζξ=„ΟŒ'½λΝΨw€Kυhlηπ/ΘCNn:φ–xςsκ„ Vg Ί˜¬άΧ…œšΗYΉ£8cπ{Μzs* $ς‡ŸΑιC²,Μ%<"‘gžΗf2}κ\HΚcπΘAdοΨY³_ύ¦Vk.δΤηάκΒ)ς)œσ*sχT“ή“ρߚHΎ όj·ΓB]ΘΟ5υ~gΦ₯·ΰvί fϞ͈ΓBΚ$σ/Έ€·¦Ok"""‘΄xρη‡=rδH\.–eašζQΣφfϞΝΐ“†©&qΙ™ΔU±·’ϊζωΈ€L’ΨΟξ’ lΐŒM%3ΆŠ=ϋKρnβIˆρΰ2Αφ{)?΄Ÿ’J?Έ蘘@ŒΛΒplΌUe,=H₯ΩΐvΫ"ΆC I±nLόT••Pf&ο+.Cbbρn μ*mό7?ϋΑ2&?qc;Ν+K#+0Ν›;qcΗ…©ƒ3oώ<Ɲ²eX±l'NlΡ4λ2-7Η=κΫφαυƒεrν­^›α0£Αν¦eašŽmγχΧΞ6iΰ=†‰e™˜5ŸΗΆρΫ~»ΖŸ={6‡λ3œ_Ά|›”••ί’iΛ0]Έ,ΏΧΤδ Σrc~|Ύ#νuT[ϊύΨ†…ιψπΩ ·ρΫM,·‰γσa;uχz-`ΥηTΓΗΑΏo1―Ό°‘ί½ˆώρκ7΅ΒΪoœύ,yνE6Ό‹ΤζθsnαψmŒΪφqlό~M›ͺέjUUUαρTΟqpΫ'ŸΟΗ’E‹κΝΟλ­^Eςλi€_DDδΔaS~`εu/©ϋ;Ψ{ΩUQgƒγ₯¬t/e₯υ$η;ΔΎ}‡κΙ¦νψ©(-¦β¨΄vs8;»’ƒvS»vRεζμτt$%Ξh~YεyΞ'*ΫοΕnΰ‰L~Ÿ·ž­NƒΫmΏ―΄xcγχΩ4υPΡΨΞ­± ›cϋπΦσΕ™νχsF}mι«yMΓνόvα λξτZͺ}ŸοpίπξέΝ~WρnΤoκOΏqpώlΪOFZμQϋœΧ ±ΧΧ>j·ΓZεžώ„‰!eΘ¬™³ΒšΎˆˆH»}Χ+A¨`Υo³;ϋdϊwMΕ΅%oΌ4Nώ9½LΒV'ŽνDf5kκ\˜žνέΊΪD;·°HOΫδeλ‹9Ϊ“.ι°maαά5Pp.Ω! qͺί©bӟΙ&―‹Œ!η0’sdWoW»O#ύ"""Έˆ··πΑ“οσLqvLέG_Ο=7žD α{N²ίφcY­yλΡyKλˆΖvua―θbΰς±μΓ₯Μ,­Δq'’Ω}NμALgυ› Εδ[7χΔgΖο¦ΞτύȈΖvkτ…APΠ/""Ζ΄ΏΥά[‚‹^—όžgςΰ²Lpόx+QRZJUΈ"~ΐΆνV}„Υ±yΓ‰Ϊή­«-΄sKSΠ_—‹μsέH“κΡcοoυ›`9˜X<ΨψΪΐw™QΩnι‘φΟ‘ͺl/»=€Ή³oο>’’“Z/Σ:8@qqqDς>‘μΩ³‡Œ½mη={φ΄xΊ&‘BέΦ8Ά_ ޲ͺί4UΫψς2ZΫΝq¨_AΏˆˆˆœςσσ™1k••Ι?6.–AƒE$οIχξέYψιB***Ώ8 βββ:thDς–ζSΏiŸΤnυSΠ/"""'€>}ϋ“νγύ0-“€€ΘŒFHϊχοOnn.~dζ[–Errr‹§«…όΒKύ¦}ŠΦv •‚~9!y<ΣΣ#] ³˜˜233#]ŒνΑ[€©ί΄Oj·ϊ)θikΪΖ­‘"–ι–~iυ›φI«χ‹ˆˆD­ζ."Ω(€“¦SΏiŸB όΥδ"""­ΜqœF $R$“φMύ¦}ͺήίάλτ‹ˆˆD€γ8‡ Γ8ό‡;&&†ͺŠ*<±ž—PΪ£ͺŠ*bbbτE’ˆH”ͺ{ύ,ύ"""­lΫΆmX–uψ›ϋΊ τ$''³qΓF|>_€Š'ν˜Λε"55•7FΊ(""΅ΑΎγ8A?₯@AΏˆˆH+λΥ»W€‹ """Q`ǎ_£›:DDDDDDD’”‚~‘(₯ _DDDDDD$J)θi«ͺfβΚλŠkfU€KΨW/ΰίObžτΈžώ&%jŸζ܎»λ-˜­Ϊδ‡0oο‡ϋ΄G0‚[JZZ[ωό4«E¨΄§σ£4BηŸΦ  _DD$"Œ§ΟΒ㉩η' ΧΤέ‘.`ΐΌχgi·γ]΅ο²wρ_Ψ5…j>ŒϋΖαIˆ«i·X<2qίχe€ v΄υβξ'†·‘X8  k: ½F°~i0χŸλχΧζλ/ΚΟ?m€ώ΅zΏˆˆHD8Χό‡ͺo{/ζΓ±x ού§$$A{yΤΊ½c—ηŠKpς2ΜH—¨•Έp~9ͺ_ΒΌ±7VΜσx;­ν]Έnέώ˜F^‹sΧ»΄Ω˜ ­ XΏ΄ϋΟO˜ϋO¨υ{’kσυεηŸ6Rι‰O€€@J2ĘSηwwMδhΈ`Λ°&χΒ“”Š{τw1W–IΓ»σžKpwMΗ“χ%ΐάe—Υpe׌R§\†ΉψY\C²π$fα~`Uΰτ·Ύ€k@wܝ†`}zσΆΥiu˜„΅ΙόώPσ―š‰«ΰ ¬wŸΖ5;žΔάΓΎƒ΅τ`ƒ,ΕψηOq ΛΗ“˜ˆ§λH\Xή2υWΛpƒΛ·ηθ€?˜ςmz뜁x’“ρτΏλ³#ϋ*ίΐ•:k±οΘΆ™·βΞ«;ύΊ‘γ[όάYxΞ~ γ›Gp'ΤΜ$Ήμ?ΥϋbΜ SπΔΤlυηγ§ΧX‚yγά™ρtξλΆη1:M¨8{1/Θΐυ\=3Zώyžσ¦‚γΐόGp6OJ<©ωΈ/+FqoΓΚΏΒΌυtܝSπ$gαώ-¬ΉAδlω;ώ@υH0ŸŸΖςΤ?Bνκ?‘τ~Γy~ύ|¬η·pŸBퟑζɏqη\ƒYR'½βWpeφΕZPD ’~B9?M» χΕ·γž‹§ΧeXΟ wn*ž Β¨hγo‰ϊoA ϊEDDΪ2g?惁_½wΥ{ΨY3pύΰ   㞠q½—ίK𘎿Γ+ΈnœZ³?Ο|λ·ΰ]ψlη3¬[sίΗx—MΗwI―ΐιη\†oώηxΧ~ŒD<φ+¨**€jϋ[ψσΜΐο5ηXΏϊϋώYΥεθ»λ‡OΥ\<:πήΈnξψή―ΧαύΧΟ±ϋgΥΌ9Δϊ Fcεσ―ΗΊώzLϋ |Ÿ―Α;υLŒηώΫ„ΌίI?ΑϋΕΌΟ]]Ώ‡o{auϋ<χ­κύFφ΄½TνΩ†χγλIΎσΦK°ΆMΑ?5ή9ΓY{7ΎudJ£υί#§[ΖΖ-ΐ!ŒΧξΗϊχ ΐ‡±~+Nχξ`Φϋ¦'πψοβ±KΖυ»Ή‡ίxν.\σϊΰh Ukζγϋυe8ω ΑV`γεtόκ7@ŸŸ`κ?”γ ΅κ?ς$˜ϊ ηω1ΰω#€@η·pŸBퟑζ?ςBμψ٘sIrΞ»˜iηaχξ?κ'δσ“1sΞΓΣρwύλ7ρΏσίΒξSϋžLόί=λα/0μρ8¦^/˜±8:Aͺs~χ¦έΣXωw8ώμ`κ·f€ΟΟΆω§…x|!χ?h΄ΚΏΡώApύ7¬ηǟ―`4v~ ΄?Τσ_Lˆύ3Πω1`ώ#qΎΕ|gœs:PŠωΞ'8罎γ©Ν$@i¬~}>ŸzœŽ=r0 ΟΑΚΌ{ΠH((Ζ,²[ΰψC¬¦ _DD€-3qw;ς{rψφV{Σ*Œί`ž“‹uxZΉ*Ίΐ.š΄ši8cϋ½-Ττ›ςώζδŸAuύτΞ=ςžψxπUΫΏ c£ημώ‘—―Ή+ίΦMΰξ‡Σ³φrΜΒιί7ψ5_¨ΎY‹7»{θ¬χλeŒ ~H§ργk”‰Σ­η΅M«V`dœ‡ν_ŒΉ~ lvΑ•5χ΅o|λξ1?]‡QκoτRsΕnβ\v/ώχΔ=h.φχ†Φ pRšΠn•?Πρg‡yΒl όƒ ϊΓΩ‚ΡμώΡ„τΓu~lΙΟW}η·@ϋC=…*δόc°/8 λΖw0+OΗΆ`ΞNΒ~uXΣΛR_ύ΄Δω)-Lbbq2ΣΑ°ΐε‡*δλΏ…)θiΣάΰiδ*ά= ‡Ο`§ΥyαΖΙjβŸx#'‘ž|BM?Ψχ7;xŽP}O8TO΅|ΝΦHω Lλθ ΛνΖ‘‘ΉΗή*ŒΪα’`Ž/υ₯[›η‘ι _ =`ηFŒOΦΑȟ`—ί†9o9μΘΓιζ*¬+Ε,ψ5ώΧNΗɌ‡Ω?Γύ\4’FΰŸώ%φG/`ύρgΈŸz[oΰάΐΘαq΄Ο±Ž;ώ0jNώuϋΠβύ―ΙBθA γω±9Ÿ―γκΏ6ΟΞoφ‡rώk ‘ζ?ϊBΎ±Έ |οbğƒX3 \_ύ΄ΔωΙνͺιΔΤσΒHΧ RΠ/""^uν‡3cOΞΠ&άΗάZι‡ϋύΟmeγt10W₯zΨ§…ΛͺΌnPυΖ?τ΄cύΧNχšΈΐ*‡²Ϊ+XcνΧΰԌx:ΎZ¦ UU41Vνή§ό9Œυ~θW3šΆf†―ΰθΡ΅ζΚνŽS6sΑœKGβ”φǘω?œς|œ\ J–b¬‚ύ―Ϋ°σLΐΖ¨ΨWΟAΔαLϊΎ‰c^Τλε₯ψ ½|Αsλ7δότ@φΏ6’Ήυκη;ΰη+Δϊ$Τσ_­pΥ_0ωǎΒ>Λ‡υΞ"L8χ™:SϋCξσS€λΏ…i!?‘φ*ωLόΧ%aώψϋX³VcξΐXςζCΣƒ[(«VY8~(?ζ*&Ττƒ}Ές7Rq8^ό9Φ–ab¬œ‹9gCΛ€˜ ~ΐίΔ.η`ŸΌσObl.ΒXϊΦ‹μwυΖιΉσΩΧ0vξΖX<λ™/ƒ?ΎZέzαΟΐόο*Œέ…_o;ϊκΣW†QZ ΎCp¨ΞJδ/Β>§σ'ΖόΊcέ‡Xw>ηތΣSΫcςq2ΏΒψ’gDΈ‘πΩ'{TρِΈγ­%…Ϋ1ήύ3ΦCKκ$ΰΗxλIΜOVcμ.ΖX·c“:·Π#ο‚=ώ@υόυ@υΏ`5ΤZJsλ7άη`λΏ‘σ[ ύ-u~ŠTύ‹}Α™πΞ}˜οšΨΦ3΅?Pi¨~Β}~j­ϊwφ`ή0χ ΣΒϊ­€‚~‘v+ηwoγ»άyσάέϋγΎμ^Μ=.‚Ί/wυίpg%αΙϊ.fΩf¬³π€φΑšU{qbϊήφό œKΓχΫώ˜Ώ: wA/άg}sαžJί‡qdάΣq½X„ρΤ™x:ζβΎE0o³3S±ΛΗ=°'ξkήΖωων8‡o±ξ…Αίΰ,Ώ w^Έn™sϝGφ<Ύ}oΕχ‡awΗίΧχώU}Ρκύ«:žiΈοψ–wF"žτ±X_ψΐΘΐ~ό ό³°ΖυΖ=ξ‡˜έ‹ο±‹pZβŽ+§k†5 ;Ϋ„ž£p*·bδυ¬>Ƙ ψΎγ‘³qχŽλ‰ƒΨΏ»ξθΰŠ?ΕΊιtάέςpΏσδϋρέΤ£ GπΗίPύ†;€ύ#€@ύ/@ύ§₯4»~Γ|ώTΞoa?EΊώjŒΉ§t¦}vέ©ύϊO ϊ χω©Υκί†²R(«jΡε4ŽeŒšzΏ3λΫp»Ÿ 1{φl&LœΖ"ˆˆˆDΏ9³ηώ·ώŠˆˆHK˜3{'N%Qδœ/αPϊ/5ηύEZΉ#^©™UT=Έ±Zwξ­Ύ]BUέΘϋš”ε3·§‘žœ<^,yΊΤgΣ?RjψhMο$‡|T₯L•–W/—₯£kηkΦά―΄~1Ω«ΥSΛξCτθ]Mσζΰt­l\A©υώ„·΅dσey]­Θ{ΧΠN δ^δχͺ]ϋήDΟι­ΟDΙγ/UΌrΘ‡Υ»;Foά]WΉ ΪώεۚπŸ7Tmκ+κδΗO£qΩ~Ήžίοy—k²Tq»Ώ$ΗImέ²[97Vt!ΰœΛΧ“”–C§χ-Υ[―ΜSJ OšGΪοΪο«ΫKΟ†xθΜΑο5ύ751°‘Ζwρ»$€ζΔ/ΡΛΟNWb³>4φY]λkQϊ‘­ZŸ$ί+ζšΦβη\Π™³υό KεΪq°žάBΑU³”Όs…>xηy=›8Fo>Ψ\F’&ΙΦΈ›ZΧ™ξ³χιH’šG4W ο_θ Λ©—sœX£9sΆΙ―Χ(MiZS™»?SΜΗjzH¬žχpΊΦr²=pΕpΣw“Ζλ›*}τς»Qͺžπ•&Ύ6V±ΑΣτh χΒ·±οӏ?ŸPX/ όeΛ‰rȈ†,.ξςππ”Υ£Ύ"θ­MΛώ­ΏQ'?w9NοΡWοNΡܟvλ„KοIr(uσ\M};ν8˜ 4«ΏšuzDOχ “·!妬Σμ˜iZΊ5IςΏ^]{ΥΟ ΈΉ5wΨ0mjž^Ώγά›¦Φύ―ήΚΈ§ΒUθξ°οRάΠ‰²φι‘τ…qZΆϋ„άλFθή‘ΓtΗ΅2μ»7tŠάν£μ&ι³_ uxeΊͺ·__Ό;UσWξRͺΓ[Χ΄ξ©Aƒ»©qΥϊΰ±'τk§ίΉζΩ:NiΥ}5Υ}€b‡xκƒ!Ο*±|=ΧrΏβ†N’΅O7₯6[ίοL‘j5U§A#4 ₯― εΡ™3EKΆ$Iώ-ΤυΑhύ9y…O§Ž5 ώŠ»`ΏψL±ϋΌˆ9lΈOqC'Ις@g₯.œ­ϋ2T­ώ-zπΙ^rf²¦υ‹νΎjΦν =σ―λUέ(bνz7Ў )fυ eΊG&ΩΤpΐ»ŠιU»rέK€™Ψw)4=Iq½DφV½7tœ~»νu½qWέ2ό~Ο‘uΏͺzŸΧτ`ϊ=ΌκβΟΎΡτTτω¨ΡU·†Ύ―Ψ„ΩεwqσκHΥqqΪΥ`ˆ¦<ΣQ~g‹ρq‹κœ· ›”Έ\Sž™£οv“Ε―©:ζΟ΅˜^4·ˆž©ΑŽ2ΜΏψ9_Δ‘€e³>QjΤHM{0\žg[ΐ­οΣHο }ξ=-½νeΥως%Mψβ°³ώ­.ίΫΤ΄{oΥϊe‘~LOSΞS΅Π%Z£>¦κŸNΤ;K6θΐ »<όλϊ=­!QώRQklœΠʘBzΉξ©Š-弍κΡzfR΄ςΤ΄Ί_]›.άߏΘή@Vgkνlϋν{ΰςs_«εΏ«Ϋ€jμoHώχhΐ­ίiΤΧ4 E›B³iΞξϊιT+ )δΛ2–3—%‡†!‹Ε'΄zΚKϊ(£FN™£czΚύϋρzσ›Dεέ•o¨ͺg šφxRγߞ£χ^ΌEYK'ιγίr$G’Ύ|kΌΎrάί™£·Ÿο€μeŸk§]’₯Ά’’κhχͺ5ϊσάνύY;΄vsnˆhVόްΠg3ΧͺΞ€*.v’m|HqcίΡ†Œ³ŸΟύCK'Ύ―”Ά#υv\ŒhŸ&Ύ¨9IaφΏ9š5ιEg|¬ΡύFΙF]EFιχΥλ”zŽΣ[΅j³‹ΒΫ\'—K^{ΏΎϋ³ξ―χfNΧσmΞhιΔΩژ%Ιρ§–M―/μgη;²ƒΞ,œi₯|~Σ}^Θ―΅εΧχιμ-jψπ7}œ:»¬PΜS#τqN'½8uΆήΡR) §κ³}φ’ΧngU΅gGϊ­ίι‘ΦνΒςώ( Ϊ©Mΰ~­έ”₯ϊŒΥˆςΊy”>Z°@ιw—†½2T‘Ακ1~~ψŒnΪ;O1‹³Τ~Τ»z?nšΖ<ΤNΝƒ½e·Ζ†Wα½\YΧύΒ98t"͐·OK{Γ’ΦΊ€ΫΘΏW‡<κ«~ώ•ξVΥmT_Ή{w+ή^Ψ9ΪωΓΟΚnu³šΉώΥ±œ+ߟ{šv}Ύ@+νaŠΌΞUŽΤŸυωš@έ9°‹ϋ{«fύφz C Ά­X«”³οw nΦQ‘ͺSΛGώ‘·*²ήqΕqZΉΙ«΄|{-uΠSΝΌU³^kύλξπ³—>XΩFuw―ΊcyεμZ­Ω7*²yU§e†΄ο­ΞMδν[OQύϊ**g₯–oΝΜϋ€γ”laκ‘φ εη]]ξi?λ‹uΥΥeΰ}Ί1ΔGށΝΤύα»Uη—Eϊ6^ͺ₯ +΅ώμΓ3·ύ¬.αjΣψ’Θ/Ι‘ΰ[ϋ©Gσ`y{ι†;;)τΤ>νKΞ•#e•Ύύ₯¦Ί>Τ+oΎWE©ί½QͺVτΞցωΓΥ«gwέΩ³»ξμΩK―ώtΊDϋΌΰ«ζΏ«:T»ύΊ½‘ΏΌύSΧφ‘Κ΅‡ͺΗΏ"UΧΧG!7uVΫΪI:ŸUΜڝ‘Υέ].VCVyxxΘ½ ·ype)¦'qΦKΨBΥ'f–Ζέq―βΛΩ¨)ύ{¨{χ;ΤχΥΥ κ‚ξoβzΙ—ε&QBnκ†ΦwŸkPϋ~κΡ,θ’ΉJEχ’©πžι2Οίq,IɎrΫκ―ΰ))!YχΌΛ°Ήευ[rχp—Ν°¨Š»§<=\e³Ϋe7lς¨α#οš!jήQ‘WΉ8YcCΆΒzΉr˜χιν‹τΕ‘λu[DΝσYΎ„k]δφΐΐ‘‘S^ͺvΑ7¦΅ZuU=y\…žΓΝΪ¦ΦHmC/9Q\κ±J .ο?>?•μ™gdΤΎUŒ’Άή†μΫ*ώΜvmC3Ο~΅#'S9aJΛ•jZs”΄αcΝZ°BΫβSt23[Ωg²Υτ–\Ω“Ž*ΡVOΧ„œΓs «λŸ’$K`”Ϊԝ«UλSΥ©Cuν]·A§ZτΧυN3ΏUώηί¬άκικΐ,­L<~φLx]Σ¨AώΞ·ΧK=έ|ώνΝπΉJWyΡΑ?체ŠRTΠ­ά˜¦ΫΪ»ιΧU›δκY5q‘tΙ‘›‚λζΏΆαζ&7ε('[²§ΦQk]u::U‚λ(ΐšPΔ<, ι4JcΊΧΙΟ­Ί›μ{œμσBζxa}A~ωγΉΈΊΚβ s_hΈΚΕEΚΙ±Λ‘%±vΰJW\Oβ¬ϋ;Κ»N½_Ÿ¦;Ο€)αχτQά“zωΜύ§sP‘Σ(6Ϊ\»πΉJEχ’yŠκ™.―b§SЦίΦ€—GQΜ£ύ΅,Ί›zήΥY-CͺΚ~ΔΙ_†£φ€εšπζOͺ7π-΅σ½`†%\λ"·Ž\Gi~4•Ήm…ΦΨ’τ|£K΅YΪ±J’\δ—>k+}υDZ쒚ώUσή¬Ιε& ŠyTaΜΗ°yΘΗ*εZ¨qγ«Z―GτμΓWΛΗνΈ–½:R;Οm+‹,ώL[,ηοέ±)2ͺžζ\«γνjν†4] r~ž_Κu\ΈsuΡ‡²ΘVΰ²%‡ ΫρFή-΅€…«6(­·Vm²©υˆΠ"ž”j‘ΥZΔ»¨£₯΅Z‹9’jΘζι+?‹ξgΚq²ΟσD\:Η"λ³X ύΕSμΪ€+œ“ž€Έ^βoα*―Zώς’ΏkΧWpΖ όζGύΡρ^ΥΎ lΓΧ_5£:τGΆΞŸ₯(Θ"«­πΉ:οgŠκ™.ΓΧ_΅, ϊ#Α.ωhΥνGυG’δΧΒ―dχ³[j)βα‰jΡu½Ύ^ψ‘b†-ΡυΓίπNΦΈœ‡γΨMyι₯t£17ϋθo―uρΫΟβU]žiJΏΰgǞ~B§<ύδuI˜:­_~X+χ¨1ΊΆ4^Ί±JX_Ω6»ΠΉπ k» VOοο5md ¬­@Η%Ÿφ•ΏΏώ?_OΩ$Ϊ½MjΆWŸ{Ϊ¨I½`Τ΄*+#οΘͺΥ/P~9‡t αό™c{β%ΩΟΏn@D΄κνZ«{ΧkΣ±Št~š_RŽŽΔQώ¨§χkΟWΦ(4άZƒκͺvξ~ν½ΰ GΚ^νM T«$‹B"£Έ}•6l^­MΆΦŠjTϊc)V ωΫγuΰθσM:’δRž8wΆΟΛKqk'Yd±HŽ\ΞϊPΩό]½DiΨνΉrΖ%½šαΩ\75<₯Υ_­<|₯R(ΎŸ©†gs…5ΜКο7κd9eξ^‘ŸR«°Z₯ΈΌέPΥΰ–κ1μM½ω€V}ΉFiΞΦΈόz9GΪΝ=AϋΒ_ΠKw_λτ!dΧΊ΄ΫΑZχZ]ujφ$ϋ‘΅λΠ½rΤ½F!ΠΪ€ͺ«MτΥ…Ό+ΥX%TΎΚluΥm`ι‹)Z°7[†oun™%SήՏ{“u"-Y‡~]e[’εδζ[Kž©Ϋ΅nG‚RwιΗΩ³τΓ±Ό‘ ΏΦjΫθˆ>]€νIΗu,~½ζ~τ“Ž_πr†€ΪΤϋ]?~Ό^ M#uCUC²οΡ¬‡»θ±ωρ*όmΚ‘C_Ο’mG•š²O?ΔΞΦjΧ6jWπ η^Γ;ZέڜΦιjΓαcJ=ϊ«>φ±…vV»Όέg ŽR›ΐmϊtξYΓ£U†Μ/£V„nnrTKb?ΡΆΔγ:ΏNσ>\qώ>ό’ŽγdŸ——βΦNF5Υς΅jϊŸ΅7ε˜R²Κρ•@ΡΚJKΠαψxşύs8εt©z§½DΞvΝ~’―^X\T―υΧκ?ωΛgϊΰ›υΪu8YΗO$kϊ4υΣύΊ:2\A;WΓOνϋτο†‰zqηΪ| YǏ§θθώ­Z³#Ρi}Εφ3EΉ¬σ—dψιΦΎwΚϋη·4fζrύφΗ18ž¨=«ηjόkŸΛΪy Ί—¬…·οQ‹άͺύ ©:‘ΌO[w§ΘΝΗWUk:YγΒzΉ2ΜΫqκ7}8fΌΦΥDΟάu•tκ€NfœTΖ©LΩK°ΦΕo\9ŒjαΊ=ΧΞ€c:ϊΛ|Ε~‘πvaT9trΣ mͺΩVmλžΰK>VΙ•ϋ[Χ†χj`Ϋ?m‘’_ν©θΗΗκTμtΝΥ_GΣ%ΐΖΊe@ΣΌovŸ†vx]οΌό ζώΊ‘Η£z€γŸZ*IF :?ωœ’'LΣΏΎ'ΥjφSτΑŸΞΏ˜α§ˆΘ`ΕΎ³W7=&CRφώΣ[‘M ?’ax)ͺk νywΈfΘPΥz‘0j npW!χΰK2ͺ©Υ#c5pΖM}ς#%εxιͺV=τπNς?w¬ˆH?͚™¦nƒ–m§ώκ8ό9%ΖΌ­—ΖJ~ΝΥ©ηνj΄cW)Ηρ.vŸ——bΧNUuΣ=ύΥβΏθιώ3uMί eό/}@ιδκπβ—4hρΉ Ή΅ύ·Œπ+ωΞz G²3Ο(3»Όο:Ν«ΧκζPόΧ“υΩ”D₯Ϋmςς――°;Fλ‰"z χ&ύ4~|-͞³X―?9E©g$·Ajάc„Βί}ίΟα²Ξ?[£>ze|-Ν™3Oc‡½Τ¬*ς n’ˆγ4Όk¨ͺ–τ4Ώγ˜6Ν›ͺΨψTeΫj¨ΞυττΐVr7,NϊΕBzΉ;J?ο3kηiήφcΚΪ>FύΏ<ο†w'›=\Mœ¬υi'ΫίXQ—žΥΤzΠ :jqΧΣκΫά Ορ΄ͺJζ.-ŠωT“S2dw«©kZφΡ ƒZΛ“ύ€2¨τχτ€Kέ2r%=ΣΰmΓΖ Š™π?%ωgE—©U«–žφΈΒnΌ©’K)7„~•ΞΔΙΥΌE νΨΆ­’K‰„^ͺIS&kV쬊.₯άϊT:'OžΤ‘ƒδUέ«’K‰>Ύzhΐ€Š.£\ϊT:Mš„jς„I²XŒŠ.&’›λPvvΆμφ܊.₯άϊT:v{μφ̊.ΈβY*ΊpyX$)++«’λεδ\Ξ7$)<ξ G…VΚ՚ώ#Œ½Ξwδ€PIENDB`‚rocq-9.2.0/doc/sphinx/_static/rocqnotations.sty000066400000000000000000000064501516144147600216540ustar00rootroot00000000000000% The LaTeX generator wraps all custom spans in \DUrole{class}{contents}. That % command then checks for another command called \DUroleclass. % Most of our CSS class names have dashes, so we need β€˜\csname … \endcsname’ % % \def\newcssclass#1#2{\expandafter\def\csname DUrole#1\endcsname ##1{#2}} % \RequirePackage{adjustbox} \RequirePackage{xcolor} \RequirePackage{amsmath} \definecolor{nbordercolor}{HTML}{AAAAAA} \definecolor{nbgcolor}{HTML}{EAEAEA} \definecolor{nholecolor}{HTML}{4E9A06} \newlength{\nscriptsize} \setlength{\nscriptsize}{0.8em} \newlength{\nboxsep} \setlength{\nboxsep}{2pt} \newcommand*{\scriptsmallsquarebox}[1]{% % Force width \makebox[\nscriptsize]{% % Force height and center vertically \raisebox{\dimexpr .5\nscriptsize - .5\height \relax}[\nscriptsize][0pt]{% % Cancel depth \raisebox{\depth}{#1}}}} \newcommand*{\nscriptdecoratedbox}[2][]{\adjustbox{cfbox=nbordercolor 0.5pt 0pt,bgcolor=nbgcolor}{#2}} \newcommand*{\nscriptbox}[1]{\nscriptdecoratedbox{\scriptsmallsquarebox{\textbf{#1}}}} \newcommand*{\nscript}[2]{\text{\hspace{-.5\nscriptsize}\raisebox{-#1\nscriptsize}{\nscriptbox{\small#2}}}} \newcommand*{\nsup}[1]{^{\nscript{0.15}{#1}}} \newcommand*{\nsub}[1]{_{\nscript{0.35}{#1}}} \newcommand*{\nnotation}[1]{#1} \newcommand*{\nbox}[1]{\adjustbox{cfbox=nbordercolor 0.5pt \nboxsep,bgcolor=nbgcolor}{#1}} \newcommand*{\nrepeat}[1]{\text{\nbox{#1\hspace{.5\nscriptsize}}}} \newcommand*{\nwrapper}[1]{\ensuremath{\displaystyle#1}} % https://tex.stackexchange.com/questions/310877/ \newcommand*{\nhole}[1]{\textit{\color{nholecolor}#1}} % % Make it easier to define new commands matching CSS classes \newcommand{\newcssclass}[2]{% \expandafter\def\csname DUrole#1\endcsname##1{#2} } % % https://tex.stackexchange.com/questions/490262/ \def\naltsep{} \newsavebox{\nsavedalt} \newlength{\naltvruleht} \newlength{\naltvruledp} \def\naltvrule{\smash{\vrule height\naltvruleht depth\naltvruledp}} \newcommand{\nalternative}[2]{% % First measure the contents of the box without the bar \bgroup% \def\naltsep{}% \savebox{\nsavedalt}{#1}% \setlength{\naltvruleht}{\ht\nsavedalt}% \setlength{\naltvruledp}{\dp\nsavedalt}% \addtolength{\naltvruleht}{#2}% \addtolength{\naltvruledp}{#2}% % Then redraw it with the bar \def\naltsep{\naltvrule}% #1\egroup} \newcssclass{notation-sup}{\nsup{#1}} \newcssclass{notation-sub}{\nsub{#1}} \newcssclass{notation}{\nnotation{\textbf{#1}}} \newcssclass{repeat}{\nrepeat{#1}} \newcssclass{repeat-wrapper}{\nwrapper{#1}} \newcssclass{repeat-wrapper-with-sub}{\nwrapper{#1}} \newcssclass{hole}{\nhole{#1}} \newcssclass{alternative}{\nalternative{\nbox{#1}}{0pt}} \newcssclass{alternative-block}{#1} \newcssclass{repeated-alternative}{\nalternative{#1}{\nboxsep}} \newcssclass{alternative-separator}{\quad\naltsep{}\quad} \newcssclass{prodn-table}{% \begin{savenotes} \sphinxattablestart \begin{tabulary}{\linewidth}[t]{lLLL} #1 \end{tabulary} \par \sphinxattableend \end{savenotes}} % latex puts targets 1 line below where they should be; prodn-target corrects for this \newcssclass{prodn-target}{\raisebox{\dimexpr \nscriptsize \relax}{#1}} \newcssclass{prodn-cell-nonterminal}{#1 &} \newcssclass{prodn-cell-op}{#1 &} \newcssclass{prodn-cell-production}{#1 &} \newcssclass{prodn-cell-tag}{#1\\} rocq-9.2.0/doc/sphinx/_templates/000077500000000000000000000000001516144147600167125ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/_templates/versions.html000066400000000000000000000036101516144147600214500ustar00rootroot00000000000000{# Forked from versions.html in sphinx_rtd_theme 0.4.3 #} {# The MIT License (MIT) Copyright (c) 2013-2018 Dave Snider, Read the Docs, Inc. & contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #} {% if not READTHEDOCS %}
Other versions v: {{ version }}
{{ _('Versions') }}
{% for slug, url in versions %}
{{ slug }}
{% endfor %}
{{ _('Downloads') }}
{% for type, url in downloads %}
{{ type }}
{% endfor %}
{% endif %} rocq-9.2.0/doc/sphinx/addendum/000077500000000000000000000000001516144147600163365ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/addendum/canonical-structures.rst000066400000000000000000000001561516144147600232420ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/addendum/extended-pattern-matching.rst000066400000000000000000000001521516144147600241310ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/addendum/extraction.rst000066400000000000000000000775661516144147600212750ustar00rootroot00000000000000.. _extraction: Program extraction ================== :Authors: Jean-Christophe FilliΓ’tre and Pierre Letouzey We present here the Rocq extraction commands, used to build certified and relatively efficient functional programs, extracting them from either Rocq functions or Rocq proofs of specifications. The functional languages available as output are currently OCaml, Haskell and Scheme. In the following, "ML" will be used (abusively) to refer to any of the three. .. versionchanged:: 8.11 Before using any of the commands or options described in this chapter, the extraction framework should first be loaded explicitly via ``From Corelib Require Extraction``. .. rocqtop:: in From Corelib Require Extraction. Generating ML Code ------------------- .. note:: In the following, a qualified identifier :token:`qualid` can be used to refer to any kind of global "object" : :term:`constant`, inductive type, inductive constructor or module name. .. cmd:: Extraction @qualid Recursive Extraction {+ @qualid } Extraction @string {+ @qualid } The first two forms display the extracted term(s) as a convenient preview: - the first form extracts :n:`@qualid` and displays the resulting term; - the second form extracts the listed :n:`@qualid`\s and all their dependencies, and displays the resulting terms. The third form produces a single extraction file named :n:`@string` for all the specified objects and all of their dependencies. Global and local identifiers are renamed as needed to fulfill the syntactic requirements of the target language, keeping original names as much as possible. The following commands also generate file(s). The generated file(s) are produced in the current working directory. It is possible to inspect what is the current directory with the command :cmd:`Pwd` and to change it with the command :cmd:`Cd`. .. cmd:: Extraction Library @ident Extraction of the whole Rocq library :n:`@ident.v` to an ML module :n:`@ident.ml`. In case of name clash, identifiers are here renamed using prefixes ``coq_`` or ``Coq_`` to ensure a session-independent renaming. .. cmd:: Recursive Extraction Library @ident Extraction of the Rocq library :n:`@ident.v` and all other modules :n:`@ident.v` depends on. .. cmd:: Separate Extraction {+ @qualid } Recursive extraction of all the mentioned objects and all their dependencies, just as :n:`Extraction @string {+ @qualid }`, but instead of producing one monolithic file, this command splits the produced code in separate ML files, one per corresponding ``.v`` file. This command is hence quite similar to :cmd:`Recursive Extraction Library`, except that only the needed parts of Rocq libraries are extracted instead of the whole. The naming convention in case of name clash is the same one as :cmd:`Extraction Library`: identifiers are here renamed using prefixes ``coq_`` or ``Coq_``. The following command is meant to help automatic testing of the extraction, see for instance the ``test-suite`` directory in the Rocq sources. .. cmd:: Extraction TestCompile {+ @qualid } All the mentioned objects and all their dependencies are extracted to a temporary OCaml file, just as in ``Extraction "file"``. Then this temporary file and its signature are compiled with the same OCaml compiler used to built Rocq. This command succeeds only if the extraction and the OCaml compilation succeed. It fails if the current target language of the extraction is not OCaml. .. cmd:: Show Extraction :undocumented: .. cmd:: Pwd This command displays the current working directory (where the extracted files are produced). .. cmd:: Cd {? @string } .. deprecated:: 8.20 Use the command line option :n:`-output-directory` instead (see :ref:`command-line-options`), or the :opt:`Extraction Output Directory` option. If :n:`@string` is specified, changes the current directory according to :token:`string` which can be any valid path. Otherwise, it displays the current directory as :cmd:`Pwd` does. Extraction Options ------------------- Setting the target language ~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Extraction Language @language .. insertprodn language language .. prodn:: language ::= OCaml | Haskell | Scheme | JSON The ability to fix target language is the first and most important of the extraction options. Default is ``OCaml``. The JSON output is mostly for development or debugging: it contains the raw ML term produced as an intermediary target. Inlining and optimizations ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Since OCaml is a strict language, the extracted code has to be optimized in order to be efficient (for instance, when using induction principles we do not want to compute all the recursive calls but only the needed ones). So the extraction mechanism provides an automatic optimization routine that will be called each time the user wants to generate an OCaml program. The optimizations can be split in two groups: the type-preserving ones (essentially constant inlining and reductions) and the non-type-preserving ones (some function abstractions of dummy types are removed when it is deemed safe in order to have more elegant types). Therefore some :term:`constants ` may not appear in the resulting monolithic OCaml program. In the case of modular extraction, even if some inlining is done, the inlined constants are nevertheless printed, to ensure session-independent programs. Concerning Haskell, type-preserving optimizations are less useful because of laziness. We still make some optimizations, for example in order to produce more readable code. The type-preserving optimizations are controlled by the following flags and commands: .. flag:: Extraction Optimize Default is on. This :term:`flag` controls all type-preserving optimizations made on the ML terms (mostly reduction of dummy beta/iota redexes, but also simplifications on Cases, etc). Turn this flag off if you want a ML term as close as possible to the Rocq term. .. flag:: Extraction Conservative Types Default is off. This :term:`flag` controls the non-type-preserving optimizations made on ML terms (which try to avoid function abstraction of dummy types). Turn this flag on to make sure that ``e:t`` implies that ``e':t'`` where ``e'`` and ``t'`` are the extracted code of ``e`` and ``t`` respectively. .. flag:: Extraction KeepSingleton Default is off. Normally, when the extraction of an inductive type produces a singleton type (i.e. a type with only one constructor, and only one argument to this constructor), the inductive structure is removed and this type is seen as an alias to the inner type. The typical example is ``sig``. This :term:`flag` allows disabling this optimization when one wishes to preserve the inductive structure of types. .. flag:: Extraction AutoInline Default is off. When enabled, the extraction mechanism inlines the :term:`bodies ` of some defined :term:`constants `, according to some heuristics like size of bodies, uselessness of some arguments, etc. Even when this flag is off, recursors (`_rect` and `_rec` schemes, such as `nat_rect`), projections, and a few specific constants such as `andb` and `orb` (for the lazy behaviour) and well founded recursion combinators are still automatically inlined. .. cmd:: Extraction Inline {+ @qualid } In addition to the automatic inline feature, the :term:`constants ` mentioned by this command will always be inlined during extraction. .. cmd:: Extraction NoInline {+ @qualid } Conversely, the constants mentioned by this command will never be inlined during extraction. .. cmd:: Print Extraction Inline Prints the current state of the table recording the custom inlinings declared by the two previous commands. .. cmd:: Reset Extraction Inline Empties the table recording the custom inlinings (see the previous commands). **Inlining and printing of a constant declaration:** The user can explicitly ask for a :term:`constant` to be extracted by two means: * by mentioning it on the extraction command line * by extracting the whole Rocq module of this :term:`constant`. In both cases, the declaration of this :term:`constant` will be present in the produced file. But this same :term:`constant` may or may not be inlined in the following terms, depending on the automatic/custom inlining mechanism. For the :term:`constants ` non-explicitly required but needed for dependency reasons, there are two cases: * If an inlining decision is taken, whether automatically or not, all occurrences of this :term:`constant` are replaced by its extracted :term:`body`, and this :term:`constant` is not declared in the generated file. * If no inlining decision is taken, the :term:`constant` is normally declared in the produced file. Extra elimination of useless arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following command provides some extra manual control on the code elimination performed during extraction, in a way which is independent but complementary to the main elimination principles of extraction (logical parts and types). .. cmd:: Extraction Implicit @qualid [ {* {| @ident | @integer } } ] Declares some arguments of :token:`qualid` as implicit, meaning that they are useless in extracted code. The extracted code will omit these arguments. Here :token:`qualid` can be any function or inductive constructor, and the :token:`ident`\s are the names of the useless arguments. Arguments can also be identified positionally by :token:`integer`\s starting from 1. When an actual extraction takes place, an error is normally raised if the :cmd:`Extraction Implicit` declarations cannot be honored, that is if any of the implicit arguments still occurs in the final code. This behavior can be relaxed via the following flag: .. flag:: Extraction SafeImplicits Default is on. When this :term:`flag` is off, a warning is emitted instead of an error if some implicit arguments still occur in the final code of an extraction. This way, the extracted code may be obtained nonetheless and reviewed manually to locate the source of the issue (in the code, some comments mark the location of these remaining implicit arguments). Note that this extracted code might not compile or run properly, depending of the use of these remaining implicit arguments. Accessing opaque proofs ~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Extraction AccessOpaque By default extraction will treat opaque proofs (concluded with :cmd:`Qed`) as though they were transparent. Turning this :term:`flag` off will instead treat them as axioms. Realizing axioms ~~~~~~~~~~~~~~~~ Extraction will fail if it encounters an informative axiom not realized. A warning will be issued if it encounters a logical axiom, to remind the user that inconsistent logical axioms may lead to incorrect or non-terminating extracted terms. It is possible to assume some axioms while developing a proof. Since these axioms can be any kind of proposition or object or type, they may perfectly well have some computational content. But a program must be a closed term, and of course the system cannot guess the program which realizes an axiom. Therefore, it is possible to tell the system what ML term corresponds to a given axiom. .. cmd:: Extract Constant @qualid {* @string__tv } => {| @ident | @string } Give an ML extraction for the given :term:`constant`. :n:`@string__tv` If the type scheme axiom is an arity (a sequence of products followed by a sort), then some type variables have to be given (as quoted strings). The number of type variables is checked by the system. For example: .. rocqtop:: in Axiom Y : Set -> Set -> Set. Extract Constant Y "'a" "'b" => " 'a * 'b ". .. note:: The extraction recognizes whether the realized axiom should become a ML type constant or a ML object declaration. For example: .. rocqtop:: in Axiom X:Set. Axiom x:X. Extract Constant X => "int". Extract Constant x => "0". .. caution:: It is the responsibility of the user to ensure that the ML terms given to realize the axioms do have the expected types. In fact, the strings containing realizing code are just copied to the extracted files. .. cmd:: Extract Inlined Constant @qualid => {| @ident | @string } Same as the previous one, except that the given ML terms will be inlined everywhere instead of being declared via a ``let``. .. note:: This command is sugar for an :cmd:`Extract Constant` followed by a :cmd:`Extraction Inline`. Hence a :cmd:`Reset Extraction Inline` will have an effect on the realized and inlined axiom. .. exn:: The term @qualid is already defined as foreign custom constant. The :n:`@qualid` was previously used in a :cmd:`Extract Foreign Constant` command. Using :cmd:`Extract Inlined Constant` for :n:`@qualid` would override this command. Realizing an axiom via :cmd:`Extract Constant` is only useful in the case of an informative axiom (of sort ``Type`` or ``Set``). A logical axiom has no computational content and hence will not appear in extracted terms. But a warning is nonetheless issued if extraction encounters a logical axiom. This warning reminds user that inconsistent logical axioms may lead to incorrect or non-terminating extracted terms. If an informative axiom has not been realized before an extraction, a warning is also issued and the definition of the axiom is filled with an exception labeled ``AXIOM TO BE REALIZED``. The user must then search these exceptions inside the extracted file and replace them by real code. Realizing inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~ The system also provides a mechanism to specify ML terms for inductive types and constructors. For instance, the user may want to use the ML native boolean type instead of the Rocq one. The syntax is the following: .. cmd:: Extract Inductive @qualid => {| @ident | @string } [ {* {| @ident | @string } } ] {? @string__match } Give an ML extraction for the given inductive type. You must specify extractions for the type itself (the initial :n:`{| @ident | @string }`) and all its constructors (the :n:`[ {* {| @ident | @string } } ]`). In this form, the ML extraction must be an ML inductive datatype, and the native pattern matching of the language will be used. When the initial :n:`{| @ident | @string }` matches the name of the type of characters or strings (``char`` and ``string`` for OCaml, ``Prelude.Char`` and ``Prelude.String`` for Haskell), extraction of literals is handled in a specialized way, so as to generate literals in the target language. This feature requires the type designated by :n:`@qualid` to be registered as the standard char or string type, using the :cmd:`Register` command. :n:`@string__match` Indicates how to perform pattern matching over this inductive type. In this form, the ML extraction could be an arbitrary type. For an inductive type with :math:`k` constructors, the function used to emulate the pattern matching should expect :math:`k+1` arguments, first the :math:`k` branches in functional form, and then the inductive element to destruct. For instance, the match branch ``| S n => foo`` gives the functional form ``(fun n -> foo)``. Note that a constructor with no arguments is considered to have one unit argument, in order to block early evaluation of the branch: ``| O => bar`` leads to the functional form ``(fun () -> bar)``. For instance, when extracting :g:`nat` into OCaml ``int``, the code to be provided has type: ``(unit->'a)->(int->'a)->int->'a``. .. caution:: As for :cmd:`Extract Constant`, this command should be used with care: * The ML code provided by the user is currently **not** checked at all by extraction, even for syntax errors. * Extracting an inductive type to a pre-existing ML inductive type is quite sound. But extracting to a general type (by providing an ad-hoc pattern matching) will often **not** be fully rigorously correct. For instance, when extracting ``nat`` to OCaml ``int``, it is theoretically possible to build ``nat`` values that are larger than OCaml ``max_int``. It is the user's responsibility to be sure that no overflow or other bad events occur in practice. * Translating an inductive type to an arbitrary ML type does **not** magically improve the asymptotic complexity of functions, even if the ML type is an efficient representation. For instance, when extracting ``nat`` to OCaml ``int``, the function ``Nat.mul`` stays quadratic. It might be interesting to associate this translation with some specific :cmd:`Extract Constant` when primitive counterparts exist. Typical examples are the following: .. rocqtop:: in Extract Inductive unit => "unit" [ "()" ]. Extract Inductive bool => "bool" [ "true" "false" ]. Extract Inductive sumbool => "bool" [ "true" "false" ]. .. note:: When extracting to OCaml, if an inductive constructor or type has arity 2 and the corresponding string is enclosed by parentheses, and the string meets OCaml's lexical criteria for an infix symbol, then the rest of the string is used as an infix constructor or type. .. rocqtop:: in Extract Inductive list => "list" [ "[]" "(::)" ]. Extract Inductive prod => "(*)" [ "(,)" ]. As an example of translation to a non-inductive datatype, let's turn ``nat`` into OCaml ``int`` (see caveat above): .. rocqtop:: in Extract Inductive nat => int [ "0" "succ" ] "(fun fO fS n -> if n=0 then fO () else fS (n-1))". Generating FFI Code ~~~~~~~~~~~~~~~~~~~ The plugin provides mechanisms to generate only OCaml code to interface the generated OCaml code with C programs. In order to link compiled OCaml code with C code, the linker needs to know * which C functions will be called by the ML code (external) * which ML functions shall be accessible by the C code (callbacks) .. cmd:: Extract Foreign Constant @qualid => @string Like :cmd:`Extract Constant`, except that the referenced ML terms will be declared in the form ``external`` :n:`@qualid` ``: ML type =`` ":n:`@string`". For example: .. rocqtop:: in From Corelib Require Extraction. Extract Inductive nat => int [ "0" "Stdlib.Int.succ" ]. Axiom f : nat -> nat -> nat. Extract Foreign Constant f => "f_impl". Here, the extracted external definition will be: ``external f : int -> int -> int = "f_impl"`` .. caution:: * The external function name :n:`@string` is not checked in any way. * The user must ensure that the C functions given to realize the axioms have the expected or compatible types. In fact, the strings containing realizing code are just copied to the extracted files. .. exn:: Extract Foreign Constant is supported only for OCaml extraction. Foreign function calls are only supported for OCaml. .. exn:: Extract Foreign Constant is supported only for functions. This error is thrown if :n:`@qualid` is of sort ``Type`` as external functions only work for functions. .. exn:: The term @qualid is already defined as inline custom constant. The :n:`@qualid` was previously used in a :cmd:`Extract Inlined Constant` command. Using :cmd:`Extract Foreign Constant` for :n:`@qualid` would override this command. .. cmd:: Extract Callback {? @string } @qualid This command makes sure that after extracting the :term:`constants ` specified by :n:`@qualid`, a constant ML function will be generated that registers :n:`@qualid` as callback, callable by :n:`@string`. This is done by declaring a function ``let _ = Callback.register`` ":n:`@string`" :n:`@qualid`. This expression signals OCaml that the given ML function :n:`@qualid` shall be accessible via the alias :n:`@string`, when calling from C/C++. If no alias is specified, it is set to the string representation of :n:`@qualid`. .. caution:: * The optional alias :n:`@string` is currently **not** checked in any way. * The user must ensure that the callback aliases are unique, i.e. when multiple modules expose a callback, the user should make sure that no two :n:`@qualid` share the same alias. .. note:: Using Extract Callback has no impact on the rest of the synthesised code since it is an additional declaration. Thus, there is no impact on the correctness and type safety of the generated code. .. exn:: Extract Callback is supported only for OCaml extraction. The callback registration mechanism ``Callback.register`` is specific to OCaml. Thus, the command is only usable when extracting OCaml code. .. cmd:: Print Extraction Foreign Prints the current set of custom foreign functions declared by the command :cmd:`Extract Foreign Constant` together with its associated foreign ML function name. .. .. cmd:: Reset Extraction Foreign .. Resets the set of custom externals .. declared by the command :cmd:`Extract Foreign Constant`. .. cmd:: Print Extraction Callback Prints the map of callbacks declared by the command :cmd:`Extract Callback`, showing the :token:`qualid` and callback alias :token:`string` (if specified) for each callback. .. cmd:: Reset Extraction Callback Resets the the map recording the callbacks declared by the command :cmd:`Extract Callback`. Avoiding conflicts with existing filenames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When using :cmd:`Extraction Library`, the names of the extracted files directly depend on the names of the Rocq files. It may happen that these filenames conflict with already existing files, either in the standard library of the target language or in other code that is meant to be linked with the extracted code. For instance the module ``List`` exists both in Rocq and in OCaml. It is possible to instruct the extraction not to use particular filenames. .. cmd:: Extraction Blacklist {+ @ident } Instruct the extraction to avoid using these names as filenames for extracted code. .. cmd:: Print Extraction Blacklist Show the current list of filenames the extraction should avoid. .. cmd:: Reset Extraction Blacklist Allow the extraction to use any filename. For OCaml, a typical use of these commands is ``Extraction Blacklist String List``. Additional settings ~~~~~~~~~~~~~~~~~~~ .. opt:: Extraction File Comment @string This :term:`option` provides a comment that is included at the beginning of the output files. .. opt:: Extraction Flag @natural This :term:`option` controls which optimizations are used during extraction, providing a finer-grained control than :flag:`Extraction Optimize`. The bits of :token:`natural` are used as a bit mask. Keeping an option off keeps the extracted ML more similar to the Rocq term. Values are: +-----+-------+----------------------------------------------------------------+ | Bit | Value | Optimization (default is on unless noted otherwise) | +-----+-------+----------------------------------------------------------------+ | 0 | 1 | Remove local dummy variables | +-----+-------+----------------------------------------------------------------+ | 1 | 2 | Use special treatment for fixpoints | +-----+-------+----------------------------------------------------------------+ | 2 | 4 | Simplify case with iota-redux | +-----+-------+----------------------------------------------------------------+ | 3 | 8 | Factor case branches as functions | +-----+-------+----------------------------------------------------------------+ | 4 | 16 | (not available, default false) | +-----+-------+----------------------------------------------------------------+ | 5 | 32 | Simplify case as function of one argument | +-----+-------+----------------------------------------------------------------+ | 6 | 64 | Simplify case by swapping case and lambda | +-----+-------+----------------------------------------------------------------+ | 7 | 128 | Some case optimization | +-----+-------+----------------------------------------------------------------+ | 8 | 256 | Push arguments inside a letin | +-----+-------+----------------------------------------------------------------+ | 9 | 512 | Use linear let reduction (default false) | +-----+-------+----------------------------------------------------------------+ | 10 | 1024 | Use linear beta reduction (default false) | +-----+-------+----------------------------------------------------------------+ .. flag:: Extraction TypeExpand If this :term:`flag` is set, fully expand Rocq types in ML. See the Rocq source code to learn more. .. opt:: Extraction Output Directory @string Sets the directory where extracted files will be written. If not set, files will be written to the directory specified by the command line option :n:`-output-directory`, if set (see :ref:`command-line-options`) and otherwise, the current directory. Use :cmd:`Pwd` to display the current directory. Differences between Rocq and ML type systems ---------------------------------------------- Due to differences between Rocq and ML type systems, some extracted programs are not directly typable in ML. We now solve this problem (at least in OCaml) by adding when needed some unsafe casting ``Obj.magic``, which give a generic type ``'a`` to any term. First, if some part of the program is *very* polymorphic, there may be no ML type for it. In that case the extraction to ML works alright but the generated code may be refused by the ML type checker. A very well known example is the ``distr-pair`` function: .. rocqtop:: in Definition dp {A B:Type}(x:A)(y:B)(f:forall C:Type, C->C) := (f A x, f B y). In OCaml, for instance, the direct extracted term would be:: let dp x y f = Pair((f () x),(f () y)) and would have type:: dp : 'a -> 'a -> (unit -> 'a -> 'b) -> ('b,'b) prod which is not its original type, but a restriction. We now produce the following correct version:: let dp x y f = Pair ((Obj.magic f () x), (Obj.magic f () y)) Secondly, some Rocq definitions may have no counterpart in ML. This happens when there is a quantification over types inside the type of a constructor; for example: .. rocqtop:: in Inductive anything : Type := dummy : forall A:Set, A -> anything. which corresponds to the definition of an ML dynamic type. In OCaml, we must cast any argument of the constructor dummy (no GADT are produced yet by the extraction). Even with those unsafe castings, you should never get error like ``segmentation fault``. In fact even if your program may seem ill-typed to the OCaml type checker, it can't go wrong: it comes from a Rocq well-typed terms, so for example inductive types will always have the correct number of arguments, etc. Of course, when launching manually some extracted function, you should apply it to arguments of the right shape (from the Rocq point-of-view). More details about the correctness of the extracted programs can be found in :cite:`Let02`. We have to say, though, that in most "realistic" programs, these problems do not occur. For example all the programs of the Rocq Stdlib are accepted by the OCaml type checker without any ``Obj.magic`` (see examples below). Some examples ------------- We present here two examples of extraction, taken from the Rocq Stdlib. We choose OCaml as the target language, but everything, with slight modifications, can also be done in the other languages supported by extraction. We then indicate where to find other examples and tests of extraction. A detailed example: Euclidean division ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This example requires the Stdlib library. Its file ``Euclid`` contains the proof of Euclidean division. The natural numbers used here are unary, represented by the type ``nat``, which is defined by two constructors ``O`` and ``S``. This module contains a theorem ``eucl_dev``, whose type is:: forall b:nat, b > 0 -> forall a:nat, diveucl a b where ``diveucl`` is a type for the pair of the quotient and the modulo, plus some logical assertions that disappear during extraction. We can now extract this program to OCaml: .. rocqtop:: reset all extra-stdlib From Corelib Require Extraction. From Stdlib Require Import Euclid Wf_nat. Extraction Inline gt_wf_rec lt_wf_rec induction_ltof2. Recursive Extraction eucl_dev. The inlining of ``gt_wf_rec`` and others is not mandatory. It only enhances readability of extracted code. You can then copy-paste the output to a file ``euclid.ml`` or let Rocq do it for you with the following command:: Extraction "euclid" eucl_dev. Let us play the resulting program (in an OCaml toplevel):: #use "euclid.ml";; type nat = O | S of nat type sumbool = Left | Right val sub : nat -> nat -> nat = val le_lt_dec : nat -> nat -> sumbool = val le_gt_dec : nat -> nat -> sumbool = type diveucl = Divex of nat * nat val eucl_dev : nat -> nat -> diveucl = # eucl_dev (S (S O)) (S (S (S (S (S O)))));; - : diveucl = Divex (S (S O), S O) It is easier to test on OCaml integers:: # let rec nat_of_int = function 0 -> O | n -> S (nat_of_int (n-1));; val nat_of_int : int -> nat = # let rec int_of_nat = function O -> 0 | S p -> 1+(int_of_nat p);; val int_of_nat : nat -> int = # let div a b = let Divex (q,r) = eucl_dev (nat_of_int b) (nat_of_int a) in (int_of_nat q, int_of_nat r);; val div : int -> int -> int * int = # div 173 15;; - : int * int = (11, 8) Note that these ``nat_of_int`` and ``int_of_nat`` are now available via a mere ``From Stdlib Require Import ExtrOcamlIntConv`` and then adding these functions to the list of functions to extract. This file ``ExtrOcamlIntConv.v`` and some others in ``plugins/extraction/`` are meant to help build concrete programs via extraction. Extraction's horror museum ~~~~~~~~~~~~~~~~~~~~~~~~~~ Some pathological examples of extraction are grouped in the file ``test-suite/success/extraction_*.v`` of the sources of Rocq. Users' Contributions ~~~~~~~~~~~~~~~~~~~~ Several user contributions use extraction to produce certified programs. In particular the following ones have an automatic extraction test: * ``additions-chains`` : https://github.com/coq-community/hydra-battles * ``bdds`` : https://github.com/coq-contribs/bdds * ``canon-bdds`` : https://github.com/coq-contribs/canon-bdds * ``chinese`` : https://github.com/coq-contribs/chinese * ``continuations`` : https://github.com/coq-contribs/continuations * ``coq-in-coq`` : https://github.com/coq-contribs/coq-in-coq * ``exceptions`` : https://github.com/coq-contribs/exceptions * ``firing-squad`` : https://github.com/coq-contribs/firing-squad * ``founify`` : https://github.com/coq-contribs/founify * ``graphs`` : https://github.com/coq-contribs/graphs * ``higman-cf`` : https://github.com/coq-contribs/higman-cf * ``higman-nw`` : https://github.com/coq-contribs/higman-nw * ``hardware`` : https://github.com/coq-contribs/hardware * ``multiplier`` : https://github.com/coq-contribs/multiplier * ``search-trees`` : https://github.com/coq-contribs/search-trees * ``stalmarck`` : https://github.com/coq-community/stalmarck Note that ``continuations`` and ``multiplier`` are a bit particular. They are examples of developments where ``Obj.magic`` is needed. This is probably due to a heavy use of impredicativity. After compilation, those two examples run nonetheless, thanks to the correction of the extraction :cite:`Let02`. rocq-9.2.0/doc/sphinx/addendum/generalized-rewriting.rst000066400000000000000000001407061516144147600234010ustar00rootroot00000000000000.. _generalizedrewriting: Generalized rewriting ===================== :Author: Matthieu Sozeau This chapter presents the extension of several equality related tactics to work over user-defined structures (called setoids) that are equipped with ad-hoc equivalence relations meant to behave as equalities. Actually, the tactics have also been generalized to relations weaker than equivalences (e.g. rewriting systems). The toolbox also extends the automatic rewriting capabilities of the system, allowing the specification of custom strategies for rewriting. This documentation is adapted from the previous setoid documentation by Claudio Sacerdoti Coen (based on previous work by ClΓ©ment Renard). The new implementation is a drop-in replacement for the old one [#tabareau]_, hence most of the documentation still applies. The work is a complete rewrite of the previous implementation, based on the typeclass infrastructure. It also improves on and generalizes the previous implementation in several ways: + User-extensible algorithm. The algorithm is separated into two parts: generation of the rewriting constraints (written in ML) and solving these constraints using typeclass resolution. As typeclass resolution is extensible using tactics, this allows users to define general ways to solve morphism constraints. + Subrelations. An example extension to the base algorithm is the ability to define one relation as a subrelation of another so that morphism declarations on one relation can be used automatically for the other. This is done purely using tactics and typeclass search. + Rewriting under binders. It is possible to rewrite under binders in the new implementation, if one provides the proper morphisms. Again, most of the work is handled in the tactics. + First-class morphisms and signatures. Signatures and morphisms are ordinary Rocq terms, hence they can be manipulated inside Rocq, put inside structures and lemmas about them can be proved inside the system. Higher-order morphisms are also allowed. + Performance. The implementation is based on a depth-first search for the first solution to a set of constraints which can be as fast as linear in the size of the term, and the size of the proof term is linear in the size of the original term. Besides, the extensibility allows the user to customize the proof search if necessary. .. [#tabareau] Nicolas Tabareau helped with the gluing. Introduction to generalized rewriting ------------------------------------- Relations and morphisms ~~~~~~~~~~~~~~~~~~~~~~~ A parametric *relation* ``R`` is any term of type ``forall (x1 : T1) ... (xn : Tn), relation A``. The expression ``A``, which depends on ``x1 ... xn`` , is called the *carrier* of the relation and ``R`` is said to be a relation over ``A``; the list ``x1,...,xn`` is the (possibly empty) list of parameters of the relation. .. example:: Parametric relation It is possible to implement finite sets of elements of type ``A`` as unordered lists of elements of type ``A``. The function ``set_eq: forall (A : Type), relation (list A)`` satisfied by two lists with the same elements is a parametric relation over ``(list A)`` with one parameter ``A``. The type of ``set_eq`` is convertible with ``forall (A : Type), list A -> list A -> Prop.`` An *instance* of a parametric relation ``R`` with n parameters is any term ``(R t1 ... tn)``. Let ``R`` be a relation over ``A`` with ``n`` parameters. A term is a parametric proof of reflexivity for ``R`` if it has type ``forall (x1 : T1) ... (xn : Tn), reflexive (R x1 ... xn)``. Similar definitions are given for parametric proofs of symmetry and transitivity. .. example:: Parametric relation (continued) The ``set_eq`` relation of the previous example can be proved to be reflexive, symmetric and transitive. A parametric unary function ``f`` of type ``forall (x1 : T1) ... (xn : Tn), A1 -> A2`` covariantly respects two parametric relation instances ``R1`` and ``R2`` if, whenever ``x``, ``y`` satisfy ``R1 x y``, their images (``f x``) and (``f y``) satisfy ``R2 (f x) (f y)``. An ``f`` that respects its input and output relations will be called a unary covariant *morphism*. We can also say that ``f`` is a monotone function with respect to ``R1`` and ``R2`` . The sequence ``x1 ... xn`` represents the parameters of the morphism. Let ``R1`` and ``R2`` be two parametric relations. The *signature* of a parametric morphism of type ``forall (x1 : T1) ... (xn : Tn), A1 -> A2`` that covariantly respects two instances :math:`I_{R_1}` and :math:`I_{R_2}` of ``R1`` and ``R2`` is written :math:`I_{R_1} ++> I_{R_2}`. Notice that the special arrow ++>, which reminds the reader of covariance, is placed between the two relation instances, not between the two carriers. The signature relation instances and morphism will be typed in a context introducing variables for the parameters. The previous definitions are extended straightforwardly to n-ary morphisms, that are required to be simultaneously monotone on every argument. Morphisms can also be contravariant in one or more of their arguments. A morphism is contravariant on an argument associated with the relation instance :math:`R` if it is covariant on the same argument when the inverse relation :math:`R^{βˆ’1}` (``inverse R`` in Rocq) is considered. The special arrow ``-->`` is used in signatures for contravariant morphisms. Functions having arguments related by symmetric relations instances are both covariant and contravariant in those arguments. The special arrow ``==>`` is used in signatures for morphisms that are both covariant and contravariant. An instance of a parametric morphism :math:`f` with :math:`n` parameters is any term :math:`f \, t_1 \ldots t_n`. .. example:: Morphisms Continuing the previous example, let ``union: forall (A : Type), list A -> list A -> list A`` perform the union of two sets by appending one list to the other. ``union`` is a binary morphism parametric over ``A`` that respects the relation instance ``(set_eq A)``. The latter condition is proved by showing: .. rocqdoc:: forall (A: Type) (S1 S1' S2 S2': list A), set_eq A S1 S1' -> set_eq A S2 S2' -> set_eq A (union A S1 S2) (union A S1' S2'). The signature of the function ``union A`` is ``set_eq A ==> set_eq A ==> set_eq A`` for all ``A``. .. example:: Contravariant morphisms The subtraction function ``Nat.sub : nat -> nat -> nat`` is a morphism of signature ``le ++> le --> le`` where ``le`` is the usual order relation over natural numbers. Notice that subtraction is covariant in its first argument and contravariant in its second argument. Leibniz equality is a relation and every function is a morphism that respects Leibniz equality. Unfortunately, Leibniz equality is not always the intended equality for a given structure. In the next section we will describe the commands to register terms as parametric relations and morphisms. Several tactics that deal with equality in Rocq can also work with the registered relations. The exact list of tactics will be given :ref:`in this section `. For instance, the tactic reflexivity can be used to solve a goal ``R n n`` whenever ``R`` is an instance of a registered reflexive relation. However, the tactics that replace in a context ``C[]`` one term with another one related by ``R`` must verify that ``C[]`` is a morphism that respects the intended relation. Currently the verification consists of checking whether ``C[]`` is a syntactic composition of morphism instances that respects some obvious compatibility constraints. .. example:: Rewriting Continuing the previous examples, suppose that the user must prove ``set_eq int (union int (union int S1 S2) S2) (f S1 S2)`` under the hypothesis ``H : set_eq int S2 (@nil int)``. It is possible to use the ``rewrite`` tactic to replace the first two occurrences of ``S2`` with ``@nil int`` in the goal since the context ``set_eq int (union int (union int S1 nil) nil) (f S1 S2)``, being a composition of morphisms instances, is a morphism. However the tactic will fail replacing the third occurrence of ``S2`` unless ``f`` has also been declared as a morphism. Adding new relations and morphisms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These commands support the :attr:`local` and :attr:`global` locality attributes. The default is :attr:`local` if the command is used inside a section, :attr:`global` otherwise. They also support the :attr:`universes(polymorphic)` attributes. .. cmd:: Add Parametric Relation {* @binder } : @one_term__A @one_term__Aeq {? reflexivity proved by @one_term } {? symmetry proved by @one_term } {? transitivity proved by @one_term } as @ident Declares a parametric relation of :n:`@one_term__A`, which is a `Type`, say `T`, with :n:`@one_term__Aeq`, which is a relation on `T`, i.e. of type `(T -> T -> Prop)`. Thus, if :n:`@one_term__A` is :n:`A: forall Ξ±__1 … Ξ±__n, Type` then :n:`@one_term__Aeq` is :n:`Aeq: forall Ξ±__1 … Ξ±__n, (A Ξ±__1 … Ξ±__n) -> (A Ξ±__1 … Ξ±__n) -> Prop`, or equivalently, :n:`Aeq: forall Ξ±__1 … Ξ±__n, relation (A Ξ±__1 … Ξ±__n)`. :n:`@one_term__A` and :n:`@one_term__Aeq` must be typeable under the context :token:`binder`\s. In practice, the :token:`binder`\s usually correspond to the :n:`Ξ±`\s The final :token:`ident` gives a unique name to the morphism and it is used by the command to generate fresh names for automatically provided lemmas used internally. Notice that the carrier and relation parameters may refer to the context of variables introduced at the beginning of the declaration, but the instances need not be made only of variables. Also notice that ``A`` is *not* required to be a term having the same parameters as ``Aeq``, although that is often the case in practice (this departs from the previous implementation). To use this command, you need to first import the module ``Setoid`` using the command ``Require Import Setoid``. .. cmd:: Add Relation @one_term @one_term {? reflexivity proved by @one_term } {? symmetry proved by @one_term } {? transitivity proved by @one_term } as @ident If the carrier and relations are not parametric, use this command instead, whose syntax is the same except there is no local context. The proofs of reflexivity, symmetry and transitivity can be omitted if the relation is not an equivalence relation. The proofs must be instances of the corresponding relation definitions: e.g. the proof of reflexivity must have a type convertible to :g:`reflexive (A t1 … tn) (Aeq tβ€²1 … tβ€²m)`. Each proof may refer to the introduced variables as well. .. example:: Parametric relation For Leibniz equality, we may declare: .. rocqtop:: in From Corelib Require Import Setoid. Add Parametric Relation (A : Type) : A (@eq A) reflexivity proved by (@eq_refl A) symmetry proved by (@eq_sym A) transitivity proved by (@eq_trans A) as eq_rel. Some tactics (:tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`transitivity`) work only on relations that respect the expected properties. The remaining tactics (:tacn:`replace`, :tacn:`rewrite` and derived tactics such as :tacn:`autorewrite`) do not require any properties over the relation. However, they are able to replace terms with related ones only in contexts that are syntactic compositions of parametric morphism instances declared with the following command. .. cmd:: Add Parametric Morphism {* @binder } : @one_term with signature @term as @ident Declares a parametric morphism :n:`@one_term` of signature :n:`@term`. The final identifier :token:`ident` gives a unique name to the morphism and it is used as the base name of the typeclass instance definition and as the name of the lemma that proves the well-definedness of the morphism. The parameters of the morphism as well as the signature may refer to the context of variables. The command asks the user to prove interactively that the function denoted by the first :token:`ident` respects the relations identified from the signature. .. example:: We start the example by assuming a small theory over homogeneous sets and we declare set equality as a parametric equivalence relation and union of two sets as a parametric morphism. .. rocqtop:: in Require Export Setoid. Require Export Relation_Definitions. Set Implicit Arguments. Parameter set : Type -> Type. Parameter empty : forall A, set A. Parameter eq_set : forall A, set A -> set A -> Prop. Parameter union : forall A, set A -> set A -> set A. Axiom eq_set_refl : forall A, reflexive _ (eq_set (A:=A)). Axiom eq_set_sym : forall A, symmetric _ (eq_set (A:=A)). Axiom eq_set_trans : forall A, transitive _ (eq_set (A:=A)). Axiom empty_neutral : forall A (S : set A), eq_set (union S (empty A)) S. Axiom union_compat : forall (A : Type), forall x x' : set A, eq_set x x' -> forall y y' : set A, eq_set y y' -> eq_set (union x y) (union x' y'). Add Parametric Relation A : (set A) (@eq_set A) reflexivity proved by (eq_set_refl (A:=A)) symmetry proved by (eq_set_sym (A:=A)) transitivity proved by (eq_set_trans (A:=A)) as eq_set_rel. Add Parametric Morphism A : (@union A) with signature (@eq_set A) ==> (@eq_set A) ==> (@eq_set A) as union_mor. Proof. exact (@union_compat A). Qed. It is possible to reduce the burden of specifying parameters using (maximally inserted) implicit arguments. If ``A`` is always set as maximally implicit in the previous example, one can write: .. rocqdoc:: Add Parametric Relation A : (set A) eq_set reflexivity proved by eq_set_refl symmetry proved by eq_set_sym transitivity proved by eq_set_trans as eq_set_rel. Add Parametric Morphism A : (@union A) with signature eq_set ==> eq_set ==> eq_set as union_mor. Proof. exact (@union_compat A). Qed. We proceed now by proving a simple lemma performing a rewrite step and then applying reflexivity, as we would do working with Leibniz equality. Both tactic applications are accepted since the required properties over ``eq_set`` and ``union`` can be established from the two declarations above. .. rocqtop:: in Goal forall (S : set nat), eq_set (union (union S (empty nat)) S) (union S S). .. rocqtop:: in Proof. intros. rewrite empty_neutral. reflexivity. Qed. The tables of relations and morphisms are managed by the typeclass instance mechanism. The behavior on section close is to generalize the instances by the variables of the section (and possibly hypotheses used in the proofs of instance declarations) but not to export them in the rest of the development for proof search. One can use the :cmd:`Existing Instance` command to do so outside the section, using the name of the declared morphism suffixed by ``_Morphism``, or use the ``Global`` modifier for the corresponding class instance declaration (see :ref:`First Class Setoids and Morphisms `) at definition time. When loading a compiled file or importing a module, all the declarations of this module will be loaded. Rewriting and nonreflexive relations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To replace only one argument of an n-ary morphism it is necessary to prove that all the other arguments are related to themselves by the respective relation instances. .. example:: To replace ``(union S empty)`` with ``S`` in ``eq_set (union (union S empty) S) (union S S)`` the rewrite tactic must exploit the monotony of ``union``. Since only the first argument is being replaced, it is necessary to prove that the second argument relates to itself. .. rocqtop:: in Goal forall (S : set nat), eq_set (union (union S (empty nat)) S) (union S S). Proof. .. rocqtop:: all abort intros; apply union_compat; [apply empty_neutral|]. When the relations associated with some arguments are not reflexive, the tactic cannot automatically prove the reflexivity goals, that are left to the user. Setoids whose relations are partial equivalence relations (PER) are useful for dealing with partial functions. Let ``R`` be a PER. We say that an element ``x`` is defined if ``R x x``. A partial function whose domain comprises all the defined elements is declared as a morphism that respects ``R``. Every time a rewriting step is performed the user must prove that the argument of the morphism is defined. .. example:: Let ``eqO`` be ``fun x y => x = y /\ x <> 0`` (the smallest PER over nonzero elements). Division can be declared as a morphism of signature ``eq ==> eq0 ==> eq``. Replacing ``x`` with ``y`` in ``div x n = div y n`` opens an additional goal ``eq0 n n`` which is equivalent to ``n = n /\ n <> 0``. Rewriting and nonsymmetric relations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When the user works up to relations that are not symmetric, it is no longer the case that any covariant morphism argument is also contravariant. As a result it is no longer possible to replace a term with a related one in every context, since the obtained goal implies the previous one if and only if the replacement has been performed in a contravariant position. In a similar way, replacement in an hypothesis can be performed only if the replaced term occurs in a covariant position. .. example:: Covariance and contravariance Suppose that subtraction over integers has been defined as a morphism of signature ``Z.sub : Z.lt ++> Z.lt --> Z.lt`` (i.e. ``Z.sub`` is increasing in its first argument, but decreasing on the second one). Let ``<`` denote ``Z.lt``. Under the hypothesis ``H : x < y`` we have ``k < x - y -> k < x - x``, but not ``k < y - x -> k < x - x``. Dually, under the same hypothesis ``k < x - y -> k < y - y`` holds, but ``k < y - x -> k < y - y`` does not. Thus, if the current goal is ``k < x - x``, it is possible to replace only the second occurrence of ``x`` (in contravariant position) with ``y`` since the obtained goal must imply the current one. On the contrary, if ``k < x - x`` is an hypothesis, it is possible to replace only the first occurrence of ``x`` (in covariant position) with ``y`` since the current hypothesis must imply the obtained one. Contrary to the previous implementation, no specific error message will be raised when trying to replace a term that occurs in the wrong position. It will only fail because the rewriting constraints are not satisfiable. However it is possible to use the at modifier to specify which occurrences should be rewritten. As expected, composing morphisms together propagates the variance annotations by switching the variance every time a contravariant position is traversed. .. example:: Let us continue the previous example and let us consider the goal ``x - (x - x) < k``. The first and third occurrences of ``x`` are in a contravariant position, while the second one is in covariant position. More in detail, the second occurrence of ``x`` occurs covariantly in ``(x - x)`` (since subtraction is covariant in its first argument), and thus contravariantly in ``x - (x - x)`` (since subtraction is contravariant in its second argument), and finally covariantly in ``x - (x - x) < k`` (since ``<``, as every transitive relation, is contravariant in its first argument with respect to the relation itself). Rewriting in ambiguous setoid contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One function can respect several different relations and thus it can be declared as a morphism having multiple signatures. .. example:: Union over homogeneous lists can be given all the following signatures: ``eq ==> eq ==> eq`` (``eq`` being the equality over ordered lists) ``set_eq ==> set_eq ==> set_eq`` (``set_eq`` being the equality over unordered lists up to duplicates), ``multiset_eq ==> multiset_eq ==> multiset_eq`` (``multiset_eq`` being the equality over unordered lists). To declare multiple signatures for a morphism, repeat the :cmd:`Add Morphism` command. When morphisms have multiple signatures it can be the case that a rewrite request is ambiguous, since it is unclear what relations should be used to perform the rewriting. Contrary to the previous implementation, the tactic will always choose the first possible solution to the set of constraints generated by a rewrite and will not try to find *all* the possible solutions to warn the user about them. Rewriting with ``Type`` valued relations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Definitions in ``Classes.Relations``, ``Classes.Morphisms`` and ``Classes.Equivalence`` are based on ``Prop``. Analogous definitions with the same names based on ``Type`` are in ``Classes.CRelations``, ``Classes.CMorphisms`` and ``Classes.CEquivalence``. The ``C`` identifies the "computational" versions. Importing these modules allows for generalized rewriting with relations of the form ``R : A -> A -> Type`` together with support for universe polymorphism. Declaring rewrite relations --------------------------- The ``RewriteRelation A R`` typeclass, indexed by a type and relation, registers relations that generalized rewriting handles. The default instances of this class are the ``iff``, ``impl`` and ``flip impl`` relations on ``Prop``, any declared ``Equivalence`` on a type ``A`` (including :term:`Leibniz equality`), and pointwise extensions of declared relations for function types. Users can simply add new instances of this class to register relations with the generalized rewriting machinery. It is used in two cases: + Inference of morphisms: In some cases, generalized rewriting might face constraints of the shape ``Proper (S ==> ?R) f`` for a function ``f`` with no matching ``Proper`` instance. In this situation, the ``RewriteRelation`` instances are used to instantiate the relation ``?R``. If the instantiated relation is reflexive, then the ``Proper`` constraint can be automatically discharged. + Compatibility with ssreflect's rewrite: The :tacn:`rewrite (ssreflect)` tactic uses generalized rewriting when possible, by checking that a ``RewriteRelation R`` instance exists when rewriting with a term of type ``R t u``. Commands and tactics -------------------- .. _first-class-setoids-and-morphisms: First class setoids and morphisms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The implementation is based on a first-class representation of properties of relations and morphisms as typeclasses. That is, the various combinations of properties on relations and morphisms are represented as records and instances of these classes are put in a hint database. For example, the declaration: .. rocqdoc:: Add Parametric Relation (x1 : T1) ... (xn : Tn) : (A t1 ... tn) (Aeq tβ€²1 ... tβ€²m) reflexivity proved by refl symmetry proved by sym transitivity proved by trans as id. is equivalent to an instance declaration: .. rocqdoc:: Instance id (x1 : T1) ... (xn : Tn) : @Equivalence (A t1 ... tn) (Aeq tβ€²1 ... tβ€²m) := { Equivalence_Reflexive := refl; Equivalence_Symmetric := sym; Equivalence_Transitive := trans }. The declaration itself amounts to the definition of an object of the record type ``Stdlib.Classes.RelationClasses.Equivalence`` and a hint added to the typeclass instances database. See the documentation on :ref:`typeclasses` and the theories files in ``Stdlib.Classes`` for further explanations. One can inform the rewrite tactic about morphisms and relations just by using the typeclass mechanism to declare them using the :cmd:`Instance` and :cmd:`Context` commands. Any object of type ``Proper`` (the type of morphism declarations) in the local context will also be automatically used by the rewriting tactic to solve constraints. .. example:: Instance declaration for Proper The `union` morphism from the example above can also be declared succinctly using: .. rocqtop:: in Require Import Relation_Definitions RelationClasses Morphisms. Instance Proper_union A : Proper (@eq_set A ==> @eq_set A ==> @eq_set A) (@union A). Proof. exact (@union_compat A). Qed. Other representations of first class setoids and morphisms can also be handled by encoding them as records. In the following example, the projections of the setoid relation and of the morphism function can be registered as parametric relations and morphisms. .. example:: First class setoids .. rocqtop:: in reset Require Import Relation_Definitions Setoid. Record Setoid : Type := { car: Type; eq: car -> car -> Prop; refl: reflexive _ eq; sym: symmetric _ eq; trans: transitive _ eq }. Add Parametric Relation (s : Setoid) : (@car s) (@eq s) reflexivity proved by (refl s) symmetry proved by (sym s) transitivity proved by (trans s) as eq_rel. Record Morphism (S1 S2 : Setoid) : Type := { f: car S1 -> car S2; compat: forall (x1 x2 : car S1), eq S1 x1 x2 -> eq S2 (f x1) (f x2) }. Add Parametric Morphism (S1 S2 : Setoid) (M : Morphism S1 S2) : (@f S1 S2 M) with signature (@eq S1 ==> @eq S2) as apply_mor. Proof. apply (compat S1 S2 M). Qed. Lemma test : forall (S1 S2 : Setoid) (m : Morphism S1 S2) (x y : car S1), eq S1 x y -> eq S2 (f _ _ m x) (f _ _ m y). Proof. intros. rewrite H. reflexivity. Qed. .. _tactics-enabled-on-user-provided-relations: Tactics enabled on user provided relations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following tactics, all prefixed by ``setoid_``, deal with arbitrary registered relations and morphisms. Moreover, all the corresponding unprefixed tactics (i.e. :tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`transitivity`, :tacn:`replace`, :tacn:`rewrite`) have been extended to fall back to their prefixed counterparts when the relation involved is not Leibniz equality. Notice, however, that using the prefixed tactics it is possible to pass additional arguments such as ``using relation``. .. tacn:: setoid_reflexivity setoid_symmetry {? in @ident } setoid_transitivity @one_term setoid_etransitivity setoid_rewrite {? {| -> | <- } } @one_term_with_bindings {? at @rewrite_occs } {? in @ident } setoid_rewrite {? {| -> | <- } } @one_term_with_bindings in @ident at @rewrite_occs setoid_replace @one_term with @one_term {? using relation @one_term } {? in @ident } {? at {+ @int_or_var } } {? by @ltac_expr3 } :name: setoid_reflexivity; setoid_symmetry; setoid_transitivity; setoid_etransitivity; setoid_rewrite; _; setoid_replace .. todo: move rewrite_occs to rewrite chapter when that chapter is revised .. insertprodn rewrite_occs rewrite_occs .. prodn:: rewrite_occs ::= {+ @integer } | @ident The ``using relation`` arguments cannot be passed to the unprefixed form. The latter argument tells the tactic what parametric relation should be used to replace the first tactic argument with the second one. If omitted, it defaults to the ``DefaultRelation`` instance on the type of the objects. By default, it means the most recent ``Equivalence`` instance in the global environment, but it can be customized by declaring new ``DefaultRelation`` instances. As Leibniz equality is a declared equivalence, it will fall back to it if no other relation is declared on a given type. Every derived tactic that is based on the unprefixed forms of the tactics considered above will also work up to user defined relations. For instance, it is possible to register hints for :tacn:`autorewrite` that are not proofs of Leibniz equalities. In particular it is possible to exploit :tacn:`autorewrite` to simulate normalization in a term rewriting system up to user defined equalities. Printing relations and morphisms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the :cmd:`Print Instances` command with the class names ``Reflexive``, ``Symmetric`` or ``Transitive`` to print registered reflexive, symmetric or transitive relations and with the class name ``Proper`` to print morphisms. When rewriting tactics refuse to replace a term in a context because the latter is not a composition of morphisms, this command can be useful to understand what additional morphisms should be registered. .. _debugging_resolution_issues: Understanding and fixing failed resolutions ------------------------------------------- .. flag:: Rewrite Output Constraints Generalized rewriting relies on proof-search to find the congruence lemmas necessary to prove that a rewriting is valid. Oftentimes, one forgets to add a ``Proper`` declaration and is faced with a whole resolution failure involving many constraints. To help with understanding the failed search, one can use the :flag:`Rewrite Output Constraints` flag. This flag changes the behavior of :tacn:`setoid_rewrite` to produce the set of unsatisfied typeclass constraints when they cannot be resolved automatically, instead of failing with an error. A typical workflow for fixing a failing resolution will hence go like this: .. example:: Understanding a resolution failure .. rocqtop:: in reset Require Import Relation_Definitions RelationClasses Morphisms. Parameter A : Type. Fixpoint In (a : A) (s : list A) {struct s} : Prop := match s with | nil => False | cons b s' => a = b \/ In a s' end. Definition same (s t : list A) : Prop := forall a : A, In a s <-> In a t. Parameter same_equiv : Equivalence same. #[local] Existing Instance same_equiv. We suppose we are in a context with some relations over which we want to perform generalized rewriting, here the notion `same` on lists which we assume is an equivalence. We want to prove a goal involving `In` and `same`: .. rocqtop:: all Goal forall (x : A) xs xs', same xs xs' -> In x xs -> In x xs'. Proof. intros x xs xs' hin. .. rocqtop:: all Fail rewrite hin. The proof-search involves three instances, to find out which is missing, lets switch to debug mode. .. rocqtop:: all Set Rewrite Output Constraints. rewrite hin. This produces new subgoals corresponding to the constraints to solve. Beware that the exact order of the produced goals is unspecified, so one should not rely on it. There are dependent subgoals `?r` and `?r0` for relations to infer. We can use :tacn:`shelve_unifiable` so that these dependent existential variables for unknown relations are not considered as goals: typeclass resolution should infer them during resolution of the `Proper` constraints instead. .. rocqtop:: all 2-6: shelve_unifiable. Note, we could have just `;`-chained the :tacn:`shelve_unifiable` tactic with the `rewrite hin` tactic to obtain the same result. We can now debug the proof search. The :tacn:`setoid_rewrite` tactic is internally calling typeclass resolution on all the constraint subgoals together, which fails. :tacn:`typeclasses eauto` is a multigoal tactic, so when launched on all goals it still fails. .. rocqtop:: all Fail 2-4: typeclasses eauto. We can however also try to launch *independent* typeclass resolutions on each constraint to see which constraint has no solution. The :tacn:`try` tactical is focusing on each goal in sequence, hence the :tacn:`typeclasses eauto` calls are now performed more independently on the three goals. The later calls are still affected by instantiations of existential variables by successful resolutions in previous goals. .. rocqtop:: all 2-4:try typeclasses eauto. Here it shows that no instance can be found for the `In` constant, but the last two goals have been solved, instantiating all the existential variables. The full search would be solvable if we had an instance for `Proper (same ==> Basics.impl) (In x)`. Adding the required instance indeed results in a successful rewrite. Let's rollback before the `Goal` and declare it: .. rocqtop:: none Abort. .. rocqtop:: in Instance Proper_In_same : Proper (eq ==> same ==> Basics.impl) In. Proof. intros x y -> l l' sll' inyl. now apply sll' in inyl. Qed. Goal forall (x : A) xs xs', same xs xs' -> In x xs -> In x xs'. Proof. intros x xs xs' hin. .. rocqtop:: all rewrite hin. Beware that typeclass resolution is backtracking, so in more complex situations, a more complex combination of instance declarations might be necessary to solve the constraints (if they are satisfiable at all). The proof-search strategy of first solving each constraint independently to find a failing branch is incomplete as the search might need to backtrack on the first constraint's solutions to find a successful resolution for subsequent constraints. .. _deprecated_syntax_for_generalized_rewriting: Deprecated syntax and backward incompatibilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Add Setoid @one_term__carrier @one_term__congruence @one_term__proofs as @ident This command for declaring setoids and morphisms is also accepted due to backward compatibility reasons. Here :n:`@one_term__congruence` is a congruence relation without parameters, :n:`@one_term__carrier` is its carrier and :n:`@one_term__proofs` is an object of type (:n:`Setoid_Theory @one_term__carrier @one_term__congruence`) (i.e. a record packing together the reflexivity, symmetry and transitivity lemmas). Notice that the syntax is not completely backward compatible since the identifier was not required. .. cmd:: Add Parametric Setoid {* @binder } : @one_term @one_term @one_term as @ident :undocumented: .. cmd:: Add Morphism @one_term : @ident Add Morphism @one_term with signature @term as @ident :name: Add Morphism; _ This command is restricted to the declaration of morphisms without parameters. It is not fully backward compatible since the property the user is asked to prove is slightly different: for n-ary morphisms the hypotheses of the property are permuted; moreover, when the morphism returns a proposition, the property is now stated using a bi-implication in place of a simple implication. In practice, porting an old development to the new semantics is usually quite simple. .. cmd:: Declare Morphism @one_term : @ident Declares a parameter in a module type that is a morphism. Notice that several limitations of the old implementation have been lifted. In particular, it is now possible to declare several relations with the same carrier and several signatures for the same morphism. Moreover, it is now also possible to declare several morphisms having the same signature. Finally, the :tacn:`replace` and :tacn:`rewrite` tactics can be used to replace terms in contexts that were refused by the old implementation. As discussed in the next section, the semantics of the new :tacn:`setoid_rewrite` tactic differs slightly from the old one and :tacn:`rewrite`. Extensions ---------- Rewriting under binders ~~~~~~~~~~~~~~~~~~~~~~~ .. warning:: Due to compatibility issues, this feature is enabled only when calling the :tacn:`setoid_rewrite` tactic directly and not :tacn:`rewrite`. To be able to rewrite under binding constructs, one must declare morphisms with respect to pointwise (setoid) equivalence of functions. Example of such morphisms are the standard ``all`` and ``ex`` combinators for universal and existential quantification respectively. They are declared as morphisms in the ``Classes.Morphisms_Prop`` module. For example, to declare that universal quantification is a morphism for logical equivalence: .. rocqtop:: reset none Require Import Morphisms. .. rocqtop:: in Instance all_iff_morphism (A : Type) : Proper (pointwise_relation A iff ==> iff) (@all A). .. rocqtop:: all abort Proof. simpl_relation. One then has to show that if two predicates are equivalent at every point, their universal quantifications are equivalent. Once we have declared such a morphism, it will be used by the setoid rewriting tactic each time we try to rewrite under an ``all`` application (products in ``Prop`` are implicitly translated to such applications). Indeed, when rewriting under a lambda, binding variable ``x``, say from ``P x`` to ``Q x`` using the relation iff, the tactic will generate a proof of ``pointwise_relation A iff (fun x => P x) (fun x => Q x)`` from the proof of ``iff (P x) (Q x)`` and a constraint of the form ``Proper (pointwise_relation A iff ==> ?) m`` will be generated for the surrounding morphism ``m``. Hence, one can add higher-order combinators as morphisms by providing signatures using pointwise extension for the relations on the functional arguments (or whatever subrelation of the pointwise extension). For example, one could declare the ``map`` combinator on lists as a morphism: .. rocqdoc:: Instance map_morphism `{Equivalence A eqA, Equivalence B eqB} : Proper ((eqA ==> eqB) ==> list_equiv eqA ==> list_equiv eqB) (@map A B). where ``list_equiv`` implements an equivalence on lists parameterized by an equivalence on the elements. Note that when one does rewriting with a lemma under a binder using :tacn:`setoid_rewrite`, the application of the lemma may capture the bound variable, as the semantics are different from rewrite where the lemma is first matched on the whole term. With the new :tacn:`setoid_rewrite`, matching is done on each subterm separately and in its local context, and all matches are rewritten *simultaneously* by default. The semantics of the previous :tacn:`setoid_rewrite` implementation can almost be recovered using the ``at 1`` modifier. Subrelations ~~~~~~~~~~~~~ Subrelations can be used to specify that one relation is included in another, so that morphism signatures for one can be used for the other. If a signature mentions a relation ``R`` on the left of an arrow ``==>``, then the signature also applies for any relation ``S`` that is smaller than ``R``, and the inverse applies on the right of an arrow. One can then declare only a few morphisms instances that generate the complete set of signatures for a particular :term:`constant`. By default, the only declared subrelation is ``iff``, which is a subrelation of ``impl`` and ``flip impl`` (the dual of implication). That’s why we can declare only two morphisms for conjunction: ``Proper (impl ==> impl ==> impl) and`` and ``Proper (iff ==> iff ==> iff) and``. This is sufficient to satisfy any rewriting constraints arising from a rewrite using ``iff``, ``impl`` or ``inverse impl`` through ``and``. Subrelations are implemented in ``Classes.Morphisms`` and are a prime example of a mostly user-space extension of the algorithm. Constant unfolding during rewriting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, :tacn:`setoid_rewrite` and :tacn:`rewrite_strat` unfold global definitions during rewrite rule matching, but do not unfold local definitions. Unfolding definitions may slow down matching, whereas keeping definitions opaque may cause matches to be missed. This behavior is configurable using transparency hints in the hint database ``rewrite``: :n:`Hint {| Variables | Constants } {| Opaque | Transparent } : rewrite.` :n:`Hint {| Opaque | Transparent } {+ @qualid } : rewrite.` The effect of these commands on rewriting is similar to that of :cmd:`Hint Transparent` and :cmd:`Hint Variables` on unification used by :tacn:`eauto` and related tactics. Note that the transparency information from database `rewrite` is used even when rewriting with individual lemmas. .. example:: .. rocqtop:: reset in Require Setoid. Definition f x y := 2*x + y. Definition g x y := 2*x + y. Goal forall (double_f : forall x y, 2*f x y = f (2*x) y + y), 2 * g 1 8 = 20. Proof. .. rocqtop:: all intros. (* By default, this rewrite succeeds by unifying f with g. *) assert_succeeds (setoid_rewrite double_f). assert_succeeds (rewrite_strat bottomup double_f). set (x := g _). (* Hide left-hand side behind local definition. *) assert_fails (setoid_rewrite double_f). assert_fails (rewrite_strat bottomup double_f). Hint Variables Transparent : rewrite. (* Now rewriting unfolds x. *) assert_succeeds (setoid_rewrite double_f). assert_succeeds (rewrite_strat bottomup double_f). Hint Constants Opaque : rewrite. (* Disallow unfolding f and g. *) assert_fails (setoid_rewrite double_f). assert_fails (rewrite_strat bottomup double_f). subst x. (* With x substituted, f and g are still distinct. *) assert_fails (setoid_rewrite double_f). assert_fails (rewrite_strat bottomup double_f). Hint Transparent f g : rewrite. (* Allow unfolding f and g only. *) assert_succeeds (setoid_rewrite double_f). assert_succeeds (rewrite_strat bottomup double_f). .. rocqtop:: none exact eq_refl. Qed. Constant unfolding during ``Proper``-instance search ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``Proper`` instances are resolved using typeclass search. By default, all constants are treated as transparent. This may slow down the resolution because :tacn:`typeclasses eauto` will do a lot of unifications (all the declared ``Proper`` instances are tried at each node of the proof search tree). To speed up the search, declare your non-abbreviation definitions as opaque in the hint database ``typeclass_instances``. :n:`Hint {| Opaque | Transparent } {+ @qualid } : typeclass_instances.` For more information, see :cmd:`Typeclasses Opaque` and :tacn:`typeclasses eauto`. .. _strategies4rewriting: Strategies for rewriting ------------------------ Usage ~~~~~ .. tacn:: rewrite_strat @rewstrategy {? in @ident } :name: rewrite_strat Rewrite using :n:`@rewstrategy` in the conclusion or in the hypothesis :n:`@ident`. .. exn:: Nothing to rewrite. The strategy didn't find any matches. .. exn:: No progress made. If the strategy succeeded but made no progress. .. exn:: Unable to satisfy the rewriting constraints. If the strategy succeeded and made progress but the corresponding rewriting constraints are not satisfied. :tacn:`setoid_rewrite` :n:`@one_term` is basically equivalent to :n:`rewrite_strat outermost @one_term`. .. tacn:: rewrite_db @ident__1 {? in @ident__2 } Equivalent to :tacn:`rewrite_strat` :n:`(topdown (hints @ident__1)) {? in @ident__2 }` Definitions ~~~~~~~~~~~ The generalized rewriting tactic is based on a set of strategies that can be combined to create custom rewriting procedures. Its set of strategies is based on the programmable rewriting strategies with generic traversals by Visser et al. :cite:`Luttik97specificationof` :cite:`Visser98`, which formed the core of the Stratego transformation language :cite:`Visser01`. Rewriting strategies are applied using the :tacn:`rewrite_strat` tactic. .. insertprodn rewstrategy rewstrategy0 .. prodn:: rewstrategy ::= fix @ident := @rewstrategy1 | {+; @rewstrategy1 } rewstrategy1 ::= <- @one_term | progress @rewstrategy1 | try @rewstrategy1 | choice {+ @rewstrategy0 } | repeat @rewstrategy1 | any @rewstrategy1 | subterm @rewstrategy1 | subterms @rewstrategy1 | innermost @rewstrategy1 | outermost @rewstrategy1 | bottomup @rewstrategy1 | topdown @rewstrategy1 | hints @ident | terms {* @one_term } | eval @red_expr | fold @one_term | @rewstrategy0 | old_hints @ident rewstrategy0 ::= @one_term | fail | id | refl | ( @rewstrategy ) :n:`@one_term` lemma, left to right :n:`fail` failure :n:`id` identity :n:`refl` reflexivity :n:`<- @one_term` lemma, right to left :n:`progress @rewstrategy1` progress :n:`try @rewstrategy1` try catch :n:`@rewstrategy ; @rewstrategy1` composition :n:`choice {+ @rewstrategy0 }` first successful strategy :n:`repeat @rewstrategy1` one or more :n:`any @rewstrategy1` zero or more :n:`subterm @rewstrategy1` one subterm :n:`subterms @rewstrategy1` all subterms :n:`innermost @rewstrategy1` Innermost first. When there are multiple nested matches in a subterm, the innermost subterm is rewritten. For :ref:`example `, rewriting :n:`(a && b) && c` with `andbC` gives :n:`(b && a) && c`. :n:`outermost @rewstrategy1` Outermost first. When there are multiple nested matches in a subterm, the outermost subterm is rewritten. For :ref:`example `, rewriting :n:`(a && b) && c` with `andbC` gives :n:`c && (a && b)`. :n:`bottomup @rewstrategy1` bottom-up :n:`topdown @rewstrategy1` top-down :n:`hints @ident` apply hints from hint database :n:`terms {* @one_term }` any of the terms :n:`eval @red_expr` apply reduction :n:`fold @term` unify :n:`fix @ident := @rewstrategy1` fixpoint operator, where :math:`\texttt{fix }f := v` evaluates to :math:`\subst{v}{f}{(\texttt{fix }f := v)}` :n:`( @rewstrategy )` to be documented :n:`old_hints @ident` to be documented Conceptually, a few of these are defined in terms of the others: - :n:`try @rewstrategy1 := choice (@rewstrategy1) id` - :n:`any @rewstrategy1 := fix @ident := try (@rewstrategy1 ; @ident)` - :n:`repeat @rewstrategy1 := @rewstrategy1; any @rewstrategy1` - :n:`bottomup @rewstrategy1 := fix @ident := (choice (progress subterms @ident) (@rewstrategy1) ; try @ident)` - :n:`topdown @rewstrategy1 := fix @ident := (choice (@rewstrategy1) (progress subterms @ident) ; try @ident)` - :n:`innermost @rewstrategy1 := fix @ident := choice (subterm @ident) (@rewstrategy1)` - :n:`outermost @rewstrategy1 := fix @ident := choice (@rewstrategy1) (subterm @ident)` The basic control strategy semantics are straightforward: strategies are applied to subterms of the term to rewrite, starting from the root of the term. The lemma strategies unify the left-hand-side of the lemma with the current subterm and on success rewrite it to the right-hand-side. Composition can be used to continue rewriting on the current subterm. The ``fail`` strategy always fails while the identity strategy succeeds without making progress. The reflexivity strategy succeeds, making progress using a reflexivity proof of rewriting. ``progress`` tests progress of the argument :n:`@rewstrategy1` and fails if no progress was made, while ``try`` always succeeds, catching failures. ``choice`` uses the first successful strategy in the list of :n:`@rewstrategy0`\s. One can iterate a strategy at least 1 time using ``repeat`` and at least 0 times using ``any``. The ``subterm`` and ``subterms`` strategies apply their argument :n:`@rewstrategy1` to respectively one or all subterms of the current term under consideration, left-to-right. ``subterm`` stops at the first subterm for which :n:`@rewstrategy1` made progress. The composite strategies ``innermost`` and ``outermost`` perform a single innermost or outermost rewrite using their argument :n:`@rewstrategy1`. Their counterparts ``bottomup`` and ``topdown`` perform as many rewritings as possible, starting from the bottom or the top of the term. Hint databases created for :tacn:`autorewrite` can also be used by :tacn:`rewrite_strat` using the ``hints`` strategy that applies any of the lemmas at the current subterm. The ``terms`` strategy takes the lemma names directly as arguments. The ``eval`` strategy expects a reduction expression (see :ref:`applyingconversionrules`) and succeeds if it reduces the subterm under consideration. The ``fold`` strategy takes a :token:`term` and tries to *unify* it to the current subterm, converting it to :token:`term` on success. It is stronger than the tactic ``fold``. .. note:: The symbol ';' is used to separate sequences of tactics as well as sequences of rewriting strategies. `rewrite_strat s; fail` is interpreted as `rewrite_strat (s; fail)`, in which `fail` is a rewriting strategy. Use `(rewrite_strat s); fail` to make `fail` a tactic. `rewrite_strat s; apply I` gives a syntax error (`apply` is not a valid rewrite strategy). .. _rewrite_strat_innermost_outermost: .. example:: :n:`innermost` and :n:`outermost` The type of `andbC` is `forall a b : bool, a && b = b && a`. .. rocqtop:: all Require Import ssrbool. Set Printing Parentheses. Local Open Scope bool_scope. Goal forall a b c : bool, a && b && c = true. rewrite_strat innermost andbC. .. rocqtop:: none Abort. Goal forall a b c : bool, a && b && c = true. Using :n:`outermost` instead gives this result: .. rocqtop:: all rewrite_strat outermost andbC. .. rocqtop:: none Abort. rocq-9.2.0/doc/sphinx/addendum/implicit-coercions.rst000066400000000000000000000441441516144147600226730ustar00rootroot00000000000000.. _coercions: Implicit Coercions ==================== :Author: Amokrane SaΓ―bi General Presentation --------------------- This section describes one inheritance mechanism of the Rocq Prover. With inheritance, we are not interested in adding any expressive power to our theory, but only convenience. Given a term, possibly not typable, we are interested in the problem of determining if it can be well typed modulo insertion of appropriate coercions. We allow to write: * :g:`f a` where :g:`f:(forall x:A,B)` and :g:`a:A'` when ``A'`` can be seen in some sense as a subtype of ``A``. * :g:`x:A` when ``A`` is not a type, but can be seen in a certain sense as a type: set, group, category etc. * :g:`f a` when ``f`` is not a function, but can be seen in a certain sense as a function: bijection, functor, any structure morphism etc. .. _classes-implicit-coercions: Coercion Classes ---------------- A class with :math:`n` parameters is any defined name with a type :n:`forall (@ident__1 : @type__1)..(@ident__n:@type__n), @sort`. Thus a class with parameters is considered as a single class and not as a family of classes. An object of a coercion class is any term of type :n:`@coercion_class @term__1 .. @term__n`. In addition to these user-defined classes, we have two built-in classes: * ``Sortclass``, the class of sorts; its objects are the terms whose type is a sort (e.g. :g:`Prop` or :g:`Type`). * ``Funclass``, the class of functions; its objects are all the terms with a functional type, i.e. of form :g:`forall x:A,B`. Formally, the syntax of classes is defined as: .. insertprodn coercion_class coercion_class .. prodn:: coercion_class ::= Funclass | Sortclass | @reference .. note:: Don't confuse coercion classes with typeclasses, which are records with special properties defined with the :cmd:`Class` command. Coercions --------- A name ``f`` can be declared as a coercion between a source user-defined class ``C`` with :math:`n` parameters and a target class ``D`` if one of these conditions holds: * ``D`` is a user-defined class, then the type of ``f`` must have the form :g:`forall (x₁:A₁)..(xβ‚–:Aβ‚–)(y:C v₁..vβ‚™), D u₁..uβ‚˜` where :math:`m` is the number of parameters of ``D``. * ``D`` is ``Funclass``, then the type of ``f`` must have the form :g:`forall (x₁:A₁)..(xβ‚–:Aβ‚–)(y:C v₁..vβ‚™)(x:A), B`. * ``D`` is ``Sortclass``, then the type of ``f`` must have the form :g:`forall (x₁:A₁)..(xβ‚–:Aβ‚–)(y:C v₁..vβ‚™), s` with ``s`` a sort. We then write :g:`f : C >-> D`. .. _ambiguous-paths: When you declare a new coercion (e.g. with :cmd:`Coercion`), new coercion paths with the same classes as existing ones are ignored. Rocq will generate a warning when the two paths may be non convertible. When the :g:`x₁..xβ‚–` are exactly the :g:`v₁..vβ‚™` (in the same order), the coercion is said to satisfy the :gdef:`uniform inheritance condition`. When possible, we recommend using coercions that satisfy this condition. This guarantees that no spurious warning will be generated. .. note:: The built-in class ``Sortclass`` can be used as a source class, but the built-in class ``Funclass`` cannot. To coerce an object :g:`t:C t₁..tβ‚™` of ``C`` towards ``D``, we have to apply the coercion ``f`` to it; the obtained term :g:`f _.._ t` is then an object of ``D``. Reversible Coercions -------------------- When a term cannot be coerced (directly) to its expected type, Rocq tries to use a :gdef:`reversible coercion` (see the :attr:`reversible` attribute). Intuitively, Rocq synthesizes a new term of the right type that can be coerced to the original one. The new term is obtained by reversing the coercion, that is guessing its input given the output. More precisely, in order to coerce a term :g:`a : A` to type :g:`B`, Rocq finds a reversible coercion :g:`f : B >-> A`, then synthesizes some :g:`?x : B` such that :g:`f ?x = a` (typically through :ref:`canonicalstructures` or :ref:`typeclasses`) and finally replaces :g:`a` with the value of :g:`?x`. If Rocq doesn't find a reversible coercion :g:`f : B >-> A`, then it looks for a coercion class :g:`C` equipped with an incoming reversible coercion :g:`g : B >-> C` and a coercion :g:`h : A >-> C` (not necessarily reversible), then synthesizes some :g:`?x : B` such that :g:`g ?x = h a`, and finally replaces :g:`a` with the value of :g:`?x`. If there's another class :g:`D` with a coercion from :g:`C` to :g:`D` and incoming coercions from :g:`A` and :g:`B`, Rocq tries :g:`C` before :g:`D`. This ordering is well defined only if the coercion graph happens to be a semi lattice. The intuition behind this ordering is that since coercions forget information, :g:`D` has less information than :g:`C`, and hence inferring :g:`?x : B` from :g:`h a : D` would be harder. See the :ref:`example below `. Identity Coercions ------------------- To make coercions work for both a named class and for ``Sortclass`` or ``Funclass``, use the :cmd:`Identity Coercion` command. There is an example :ref:`here `. Inheritance Graph ------------------ Coercions form an inheritance graph with classes as nodes. We call *coercion path* an ordered list of coercions between two nodes of the graph. A class ``C`` is said to be a subclass of ``D`` if there is a coercion path in the graph from ``C`` to ``D``; we also say that ``C`` inherits from ``D``. Our mechanism supports multiple inheritance since a class may inherit from several classes, contrary to simple inheritance where a class inherits from at most one class. However there must be at most one path between two classes. If this is not the case, only the *oldest* one is valid and the others are ignored. So the order of declaration of coercions is important. We extend notations for coercions to coercion paths. For instance :g:`[f₁;..;fβ‚–] : C >-> D` is the coercion path composed by the coercions ``f₁..fβ‚–``. The application of a coercion path to a term consists of the successive application of its coercions. Coercion Classes ---------------- .. cmd:: Coercion @reference {? : @coercion_class >-> @coercion_class } Coercion @ident_decl @def_body The first form declares the construction denoted by :token:`reference` as a coercion between the two given classes. The second form defines :token:`ident_decl` just like :cmd:`Definition` :n:`@ident_decl @def_body` and then declares :token:`ident_decl` as a coercion between its source and its target. Both forms support the :attr:`local` attribute, which makes the coercion local to the current section. :n:`{? : @coercion_class >-> @coercion_class }` The source and target classes of the coercion. If unspecified, :n:`@reference` must already be a coercion, which enables modifying the :attr:`reversible` attribute of :n:`@reference`. See the :ref:`example ` below. .. attr:: reversible{? = {| yes | no } } :name: reversible This :term:`attribute` allows the coercion to be used as a :term:`reversible coercion`. By default coercions are not reversible except for :cmd:`Record` fields specified using :g:`:>`. .. attr:: nonuniform Silence the non uniform inheritance warning. .. deprecated:: 8.18 Use the :attr:`warnings` attribute instead with "-uniform-inheritance". .. exn:: @qualid not declared. :token:`qualid` is not defined globally. .. exn:: @qualid is already a coercion. :token:`qualid` is already registered as a coercion. .. exn:: Funclass cannot be a source class. Funclass as a source class is currently not supported. This may change in the future. .. exn:: @qualid is not a function. :token:`qualid` is not a function, so it cannot be used as a coercion. .. exn:: Cannot find the source class of @qualid. Rocq can not infer a valid source class. .. exn:: Cannot recognize @coercion_class as a source class of @qualid. The inferred source class of the coercion differs from the one specified. .. exn:: Cannot find the target class The target class of the coercion is not specified and cannot be inferred. Make sure that the target is not a variable. .. exn:: Found target class @coercion_class instead of @coercion_class The inferred target class of the coercion differs from the one specified. .. warn:: @qualid does not respect the uniform inheritance condition. The :ref:`test for ambiguous coercion paths ` may yield false positives involving the coercion :token:`qualid`. Use the :attr:`warnings` attribute with "-uniform-inheritance" to silence this warning. .. warn:: New coercion path ... is ambiguous with existing ... The check for :ref:`ambiguous paths ` failed. The paths for which this check fails are displayed by a warning in the form :g:`[f₁;..;fβ‚™] : C >-> D`. The convertibility checking procedure for coercion paths is complete for paths consisting of coercions satisfying the :term:`uniform inheritance condition`, but some coercion paths could be reported as ambiguous even if they are convertible with existing ones when they have coercions that don't satisfy this condition. .. warn:: ... is not definitionally an identity function. If a coercion path has the same source and target class, that is said to be circular. When a new circular coercion path is not convertible with the identity function, it will be reported as ambiguous. Some objects can be declared as coercions when they are defined. This applies to :ref:`assumptions` and constructors of :ref:`inductive types and record fields`. Use :n:`:>` instead of :n:`:` before the type of the assumption to do so. See :n:`@of_type`. .. cmd:: Identity Coercion @ident : @coercion_class__src >-> @coercion_class__dest Checks that :n:`@coercion_class__src` is a :term:`constant` with a :term:`body` of the form :n:`fun (x₁:T₁)..(xβ‚™:Tβ‚™) => @coercion_class__dest t₁..tβ‚˜` where `m` is the number of parameters of :n:`@coercion_class__dest`. Then we define an identity function with type :g:`forall (x₁:T₁)..(xβ‚™:Tβ‚™)(y:C x₁..xβ‚™),D t₁..tβ‚˜`, and we declare it as an identity coercion between ``C`` and ``D``. See below for an :ref:`example `. This command supports the :attr:`local` attribute, which makes the coercion local to the current section. .. exn:: @coercion_class must be a transparent constant. :undocumented: .. cmd:: SubClass @ident_decl @def_body If :n:`@type` is a coercion class :n:`@ident'` applied to some arguments then :n:`@ident` is defined and an identity coercion of name :n:`Id_@ident_@ident'` is declared. In other words, this is an abbreviation for :n:`Definition @ident := @type.` :n:`Identity Coercion Id_@ident_@ident' : @ident >-> @ident'`. This command supports the :attr:`local` attribute, which makes the coercion local to the current section. Displaying Available Coercions ------------------------------- .. cmd:: Print Classes Print the list of declared coercion classes in the current context. .. cmd:: Print Coercions Print the list of declared coercions in the current context. .. cmd:: Print Graph Print the list of valid coercion paths in the current context. .. cmd:: Print Coercion Paths @coercion_class @coercion_class Print the list of valid coercion paths between the two given classes. Activating the Printing of Coercions ------------------------------------- .. flag:: Printing Coercions When on, this :term:`flag` forces all the coercions to be printed. By default, coercions are not printed. .. table:: Printing Coercion @qualid This :term:`table` specifies a set of qualids for which coercions are always displayed. Use the :cmd:`Add` and :cmd:`Remove` commands to update the set of qualids. .. _coercions-classes-as-records: Classes as Records ------------------ .. index:: :> (coercion) *Structures with Inheritance* may be defined using the :cmd:`Record` command. Use `>` before the record name to declare the constructor name as a coercion from the class of the last field type to the record name. See :token:`record_definition`. Use `:>` in the field type to declare the field as a coercion from the record name to the class of the field type. For these coercions, the :attr:`reversible` attribute defaults to :g:`yes`. See :token:`of_type`. Coercions and Sections ---------------------- The inheritance mechanism is compatible with the section mechanism. The global classes and coercions defined inside a section are redefined after its closing, using their new value and new type. The classes and coercions which are local to the section are simply forgotten. Coercions with a local source class or a local target class are also forgotten. Coercions and Modules --------------------- The coercions present in a module are activated only when the module is explicitly imported. Examples -------- There are three situations: .. example:: Coercion at function application :g:`f a` is ill-typed where :g:`f:forall x:A,B` and :g:`a:A'`. If there is a coercion path between ``A'`` and ``A``, then :g:`f a` is transformed into :g:`f a'` where ``a'`` is the result of the application of this coercion path to ``a``. We first give an example of coercion between atomic inductive types .. rocqtop:: all Definition bool_in_nat (b:bool) := if b then 0 else 1. Coercion bool_in_nat : bool >-> nat. Check (0 = true). Set Printing Coercions. Check (0 = true). Unset Printing Coercions. .. warning:: Note that ``Check (true = O)`` would fail. This is "normal" behavior of coercions. To validate ``true=O``, the coercion is searched from ``nat`` to ``bool``. There is none. We give an example of coercion between classes with parameters. .. rocqtop:: all Parameters (C : nat -> Set) (D : nat -> bool -> Set) (E : bool -> Set). Parameter f : forall n:nat, C n -> D (S n) true. Coercion f : C >-> D. Parameter g : forall (n:nat) (b:bool), D n b -> E b. Coercion g : D >-> E. Parameter c : C 0. Parameter T : E true -> nat. Check (T c). Set Printing Coercions. Check (T c). Unset Printing Coercions. In the case of functional arguments, we use the monotonic rule of sub-typing. To coerce :g:`t : forall x : A, B` towards :g:`forall x : A', B'`, we have to coerce ``A'`` towards ``A`` and ``B`` towards ``B'``. An example is given below: .. rocqtop:: all Parameters (A B : Set) (h : A -> B). Coercion h : A >-> B. Parameter U : (A -> E true) -> nat. Parameter t : B -> C 0. Check (U t). Set Printing Coercions. Check (U t). Unset Printing Coercions. Remark the changes in the result following the modification of the previous example. .. rocqtop:: all Parameter U' : (C 0 -> B) -> nat. Parameter t' : E true -> A. Check (U' t'). Set Printing Coercions. Check (U' t'). Unset Printing Coercions. .. example:: Coercion to a type An assumption ``x:A`` when ``A`` is not a type, is ill-typed. It is replaced by ``x:A'`` where ``A'`` is the result of the application to ``A`` of the coercion path between the class of ``A`` and ``Sortclass`` if it exists. This case occurs in the abstraction :g:`fun x:A => t`, universal quantification :g:`forall x:A,B`, global variables and parameters of (co)inductive definitions and functions. In :g:`forall x:A,B`, such a coercion path may also be applied to ``B`` if necessary. .. rocqtop:: all Parameter Graph : Type. Parameter Node : Graph -> Type. Coercion Node : Graph >-> Sortclass. Parameter G : Graph. Parameter Arrows : G -> G -> Type. Check Arrows. Parameter fg : G -> G. Check fg. Set Printing Coercions. Check fg. Unset Printing Coercions. .. example:: Coercion to a function ``f a`` is ill-typed because ``f:A`` is not a function. The term ``f`` is replaced by the term obtained by applying to ``f`` the coercion path between ``A`` and ``Funclass`` if it exists. .. rocqtop:: all Parameter bij : Set -> Set -> Set. Parameter ap : forall A B:Set, bij A B -> A -> B. Coercion ap : bij >-> Funclass. Parameter b : bij nat nat. Check (b 0). Set Printing Coercions. Check (b 0). Unset Printing Coercions. .. _example-reversible-coercion: .. example:: Reversible coercions Notice the :n:`:>` on `ssort` making it a :term:`reversible coercion`. .. rocqtop:: in Structure S := { ssort :> Type; sstuff : ssort; }. Definition test (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. .. rocqtop:: all Check test (nat : Type). .. _example-reversible-coercion-attribute: .. example:: Reversible coercions using the :attr:`reversible` attribute Notice there is no `:>` on `ssort'` and the added :cmd:`Coercion` compared to the previous example. .. rocqtop:: in Structure S' := { ssort' : Type; sstuff' : ssort'; }. Coercion ssort' : S' >-> Sortclass. Definition test' (s : S') := sstuff' s. Canonical Structure S_nat' := {| ssort' := nat; sstuff' := 0; |}. Since there's no `:>` on the definition of `ssort'`, the :attr:`reversible` attribute is not set: .. rocqtop:: all Fail Check test' (nat : Type). The attribute can be set after declaring the coercion: .. rocqtop:: all #[reversible] Coercion ssort'. Check test' (nat : Type). .. _example-identity-coercion: .. example:: Identity coercions. .. rocqtop:: in Definition fct := nat -> nat. Parameter incr_fct : Set. Parameter fct_of_incr_fct : incr_fct -> fct. .. rocqtop:: all Fail Coercion fct_of_incr_fct : incr_fct >-> Funclass. .. rocqtop:: in Coercion fct_of_incr_fct : incr_fct >-> fct. Parameter f' : incr_fct. .. rocqtop:: all Check f' : fct. Fail Check f' 0. Identity Coercion Id_fct_Funclass : fct >-> Funclass. Check f' 0. .. example:: Inheritance Graph Let us see the resulting graph after all these examples. .. rocqtop:: all Print Graph. rocq-9.2.0/doc/sphinx/addendum/micromega.rst000066400000000000000000000503261516144147600210410ustar00rootroot00000000000000.. _micromega: Micromega: solvers for arithmetic goals over ordered rings ================================================================== :Authors: FrΓ©dΓ©ric Besson and Evgeny Makarov .. note:: The tactics described in this chapter require the Stdlib library. Short description of the tactics -------------------------------- The Psatz module (``Require Import Psatz``) gives access to several tactics for solving arithmetic goals over :math:`\mathbb{Q}`, :math:`\mathbb{R}`, and :math:`\mathbb{Z}` but also :g:`nat` and :g:`N`. It is also possible to get only the tactics for integers by ``Require Import Lia``, only for rationals by ``Require Import Lqa`` or only for reals by ``Require Import Lra``. + :tacn:`lia` is a decision procedure for linear integer arithmetic; + :tacn:`nia` is an incomplete proof procedure for integer non-linear arithmetic; + :tacn:`lra` is a decision procedure for linear (real or rational) arithmetic; + :tacn:`nra` is an incomplete proof procedure for non-linear (real or rational) arithmetic; + :tacn:`psatz` ``D n`` is an incomplete proof procedure for non-linear arithmetic. ``D`` is :math:`\mathbb{Z}` or :math:`\mathbb{Q}` or :math:`\mathbb{R}` and ``n`` is an optional integer limiting the proof search depth. It is based on John Harrison’s HOL Light driver to the external prover CSDP [#csdp]_. Note that the CSDP driver generates a *proof cache* which makes it possible to rerun scripts even without CSDP. .. flag:: Info Micromega When set, instructs the tactics :tacn:`lia`, :tacn:`nia`, :tacn:`lra`, :tacn:`nra` and :tacn:`psatz` to print the list of hypotheses needed by the proof. The default is unset. .. opt:: Dump Arith This :term:`option` (unset by default) may be set to a file path where debug info will be written. .. cmd:: Show Lia Profile This command prints some statistics about the amount of pivoting operations needed by :tacn:`lia` and may be useful to detect inefficiencies. .. flag:: Lia Cache This :term:`flag` (set by default) instructs :tacn:`lia` to cache its results in the file `.lia.cache` .. flag:: Nia Cache This :term:`flag` (set by default) instructs :tacn:`nia` to cache its results in the file `.nia.cache` .. flag:: Nra Cache This :term:`flag` (set by default) instructs :tacn:`nra` to cache its results in the file `.nra.cache` .. flag:: Lia Depth :undocumented: 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 for formulas is: .. note the following is not an insertprodn .. prodn:: F ::= {| @A | P | True | False | @F /\ @F | @F \/ @F | @F <-> @F | @F -> @F | ~ @F | @F = @F } A ::= {| @p = @p | @p > @p | @p < @p | @p >= @p | @p <= @p } p ::= {| c | x | βˆ’@p | @p βˆ’ @p | @p + @p | @p * @p | @p ^ n } where - :token:`F` is interpreted over either `Prop` or `bool` - :n:`P` is an arbitrary proposition - :n:`c` is a numeric constant of :math:`D` - :n:`x` :math:`\in D` is a numeric variable - :n:`βˆ’`, :n:`+` and :n:`*` are respectively subtraction, addition and product - :n:`p ^ n` is exponentiation by a natural integer constant :math:`n` When :math:`F` is interpreted over `bool`, the boolean operators are `&&`, `||`, `Bool.eqb`, `Bool.implb`, `Bool.negb` and the comparisons in :math:`A` are also interpreted over the booleans (e.g., for :math:`\mathbb{Z}`, we have `Z.eqb`, `Z.gtb`, `Z.ltb`, `Z.geb`, `Z.leb`). For :math:`\mathbb{Q}`, the equality of rationals ``==`` is used rather than Leibniz equality ``=``. For :math:`\mathbb{Z}` (resp. :math:`\mathbb{Q}`), :n:`c` ranges over integer constants (resp. rational constants). For :math:`\mathbb{R}`, the tactic recognizes as real constants the following expressions: :: c ::= R0 | R1 | Rmult c c | Rplus c c | Rminus c c | IZR z | Q2R q | Rdiv c c | Rinv c where `z` is a constant in :math:`\mathbb{Z}` and `q` is a constant in :math:`\mathbb{Q}`. This includes :n:`@number` written using the decimal notation, *i.e.*, ``c%R``. *Positivstellensatz* refutations -------------------------------- The name `psatz` is an abbreviation for *positivstellensatz* – literally "positivity theorem" – which generalizes Hilbert’s *nullstellensatz*. It relies on the notion of Cone. Given a (finite) set of polynomials :math:`S`, :math:`\mathit{Cone}(S)` is inductively defined as the smallest set of polynomials closed under the following rules: .. math:: \begin{array}{l} \dfrac{p \in S}{p \in \mathit{Cone}(S)} \quad \dfrac{}{p^2 \in \mathit{Cone}(S)} \quad \dfrac{p_1 \in \mathit{Cone}(S) \quad p_2 \in \mathit{Cone}(S) \quad \Join \in \{+,*\}} {p_1 \Join p_2 \in \mathit{Cone}(S)}\\ \end{array} The following theorem provides a proof principle for checking that a set of polynomial inequalities does not have solutions [#fnpsatz]_. .. _psatz_thm: .. thm:: Psatz Let :math:`S` be a set of polynomials. If :math:`-1` belongs to :math:`\mathit{Cone}(S)`, then the conjunction :math:`\bigwedge_{p \in S} p\ge 0` is unsatisfiable. *Proof:* Let's assume that :math:`\bigwedge_{p \in S} p\ge 0` is satisfiable, meaning there exists :math:`x` such that for all :math:`p \in S` , we have :math:`p(x) \ge 0`. Since the cone building rules preserve non negativity, any polynomial in :math:`\mathit{Cone}(S)` is non negative in :math:`x`. Thus :math:`-1 \in \mathit{Cone}(S)` is non negative, which is absurd. :math:`\square` A proof based on this theorem is called a *positivstellensatz* refutation. The tactics work as follows. Formulas are normalized into conjunctive normal form :math:`\bigwedge_i C_i` where :math:`C_i` has the general form :math:`(\bigwedge_{j\in S_i} p_j \Join 0) \to \mathit{False}` and :math:`\Join \in \{>,\ge,=\}` for :math:`D\in \{\mathbb{Q},\mathbb{R}\}` and :math:`\Join \in \{\ge, =\}` for :math:`\mathbb{Z}`. For each conjunct :math:`C_i`, the tactic calls an oracle which searches for :math:`-1` within the cone. Upon success, the oracle returns a :gdef:`cone expression` that is normalized by the :tacn:`ring` tactic (see :ref:`theringandfieldtacticfamilies`) and checked to be :math:`-1`. `lra`: a decision procedure for linear real and rational arithmetic ------------------------------------------------------------------- .. tacn:: lra This tactic is searching for *linear* refutations. As a result, this tactic explores a subset of the *Cone* defined as .. math:: \mathit{LinCone}(S) =\left\{ \left. \sum_{p \in S} \alpha_p \times p~\right|~\alpha_p \mbox{ are positive constants} \right\} The deductive power of :tacn:`lra` overlaps with the one of :tacn:`field` tactic *e.g.*, :math:`x = 10 * x / 10` is solved by :tacn:`lra`. .. tacn:: xlra_Q @ltac_expr xlra_R @ltac_expr For internal use only (it may change without notice). .. tacn:: wlra_Q @ident @one_term For advanced users interested in deriving tactics for specific needs. See the :ref:`example below ` and comments in `plugin/micromega/coq_micromega.mli`. `lia`: a tactic for linear integer arithmetic --------------------------------------------- .. tacn:: lia This tactic solves linear goals over :g:`Z` by searching for *linear* refutations and cutting planes. :tacn:`lia` provides support for :g:`Z`, :g:`nat`, :g:`positive` and :g:`N` by pre-processing via the :tacn:`zify` tactic. High level view of `lia` ~~~~~~~~~~~~~~~~~~~~~~~~ Over :math:`\mathbb{R}`, *positivstellensatz* refutations are a complete proof principle [#mayfail]_. However, this is not the case over :math:`\mathbb{Z}`. Actually, *positivstellensatz* refutations are not even sufficient to decide linear *integer* arithmetic. The canonical example is :math:`2 * x = 1 \to \mathtt{False}` which is a theorem of :math:`\mathbb{Z}` but not a theorem of :math:`{\mathbb{R}}`. To remedy this weakness, the :tacn:`lia` tactic is using recursively a combination of: + linear *positivstellensatz* refutations; + cutting plane proofs; + case split. Cutting plane proofs ~~~~~~~~~~~~~~~~~~~~~~ are a way to take into account the discreteness of :math:`\mathbb{Z}` by rounding (rational) constants to integers. .. _ceil_thm: .. thm:: Bound on the ceiling function Let :math:`p` be an integer and :math:`c` a rational constant. Then :math:`p \ge c \rightarrow p \ge \lceil{c}\rceil`. .. example:: Cutting plane For instance, from :math:`2 x = 1` we can deduce + :math:`x \ge 1/2` whose cut plane is :math:`x \ge \lceil{1/2}\rceil = 1`; + :math:`x \le 1/2` whose cut plane is :math:`x \le \lfloor{1/2}\rfloor = 0`. By combining these two facts (in normal form) :math:`x βˆ’ 1 \ge 0` and :math:`-x \ge 0`, we conclude by exhibiting a *positivstellensatz* refutation: :math:`βˆ’1 \equiv xβˆ’1 + βˆ’x \in \mathit{Cone}({xβˆ’1,x})`. Cutting plane proofs and linear *positivstellensatz* refutations are a complete proof principle for integer linear arithmetic. Case split ~~~~~~~~~~~ enumerates over the possible values of an expression. .. _casesplit_thm: .. thm:: Case split Let :math:`p` be an integer and :math:`c_1` and :math:`c_2` integer constants. Then: .. math:: c_1 \le p \le c_2 \Rightarrow \bigvee_{x \in [c_1,c_2]} p = x Our current oracle tries to find an expression :math:`e` with a small range :math:`[c_1,c_2]`. We generate :math:`c_2 βˆ’ c_1` subgoals whose contexts are enriched with an equation :math:`e = i` for :math:`i \in [c_1,c_2]` and recursively search for a proof. .. tacn:: xlia @ltac_expr For internal use only (it may change without notice). .. tacn:: wlia @ident @one_term For advanced users interested in deriving tactics for specific needs. See the :ref:`example below ` and comments in `plugin/micromega/coq_micromega.mli`. `nra`: a proof procedure for non-linear arithmetic -------------------------------------------------- .. tacn:: nra This tactic is an *experimental* proof procedure for non-linear arithmetic. The tactic performs a limited amount of non-linear reasoning before running the linear prover of :tacn:`lra`. This pre-processing does the following: + If the context contains an arithmetic expression of the form :math:`e[x^2]` where :math:`x` is a monomial, the context is enriched with :math:`x^2 \ge 0`; + For all pairs of hypotheses :math:`e_1 \ge 0`, :math:`e_2 \ge 0`, the context is enriched with :math:`e_1 \times e_2 \ge 0`. After this pre-processing, the linear prover of :tacn:`lra` searches for a proof by abstracting monomials by variables. .. tacn:: xnra_Q @ltac_expr xnra_R @ltac_expr For internal use only (it may change without notice). .. tacn:: wnra_Q @ident @one_term For advanced users interested in deriving tactics for specific needs. See the :ref:`example below ` and comments in `plugin/micromega/coq_micromega.mli`. `nia`: a proof procedure for non-linear integer arithmetic ---------------------------------------------------------- .. tacn:: nia This tactic is a proof procedure for non-linear integer arithmetic. It performs a pre-processing similar to :tacn:`nra`. The obtained goal is solved using the linear integer prover :tacn:`lia`. .. tacn:: xnia @ltac_expr For internal use only (it may change without notice). .. tacn:: wnia @ident @one_term For advanced users interested in deriving tactics for specific needs. See the :ref:`example below ` and comments in `plugin/micromega/coq_micromega.mli`. `psatz`: a proof procedure for non-linear arithmetic ---------------------------------------------------- .. tacn:: psatz @one_term {? @nat_or_var } This tactic explores the *Cone* by increasing degrees – hence the depth parameter :token:`nat_or_var`. In theory, such a proof search is complete – if the goal is provable the search eventually stops. Unfortunately, the external oracle is using numeric (approximate) optimization techniques that might miss a refutation. To illustrate the working of the tactic, consider we wish to prove the following goal: .. needs csdp .. rocqdoc:: Require Import ZArith Psatz. Open Scope Z_scope. Goal forall x, -x^2 >= 0 -> x - 1 >= 0 -> False. intro x. psatz Z 2. Qed. As shown, such a goal is solved by ``intro x. psatz Z 2``. The oracle returns the :term:`cone expression` :math:`2 \times p_2 + p_2^2 + p_1` with :math:`p_1 := -x^2` and :math:`p_2 := x - 1`. By construction, this expression belongs to :math:`\mathit{Cone}({p_1, p_2})`. Moreover, by running :tacn:`ring` we obtain :math:`-1`. Thus, by Theorem :ref:`Psatz `, the goal is valid. .. tacn:: xsos_Q @ltac_expr xsos_R @ltac_expr xsos_Z @ltac_expr xpsatz_Q @nat_or_var @ltac_expr xpsatz_R @nat_or_var @ltac_expr xpsatz_Z @nat_or_var @ltac_expr For internal use only (it may change without notice). .. tacn:: wsos_Q @ident @one_term wsos_Z @ident @one_term wpsatz_Q @nat_or_var @ident @one_term wpsatz_Z @nat_or_var @ident @one_term For advanced users interested in deriving tactics for specific needs. See the :ref:`example below ` and comments in `plugin/micromega/coq_micromega.mli`. `zify`: pre-processing of arithmetic goals ------------------------------------------ .. tacn:: zify This tactic is internally called by :tacn:`lia` to support additional types, e.g., :g:`nat`, :g:`positive` and :g:`N`. Additional support is provided by the following modules: + For boolean operators (e.g., :g:`Nat.leb`), require the module :g:`ZifyBool`. + For comparison operators (e.g., :g:`Z.compare`), require the module :g:`ZifyComparison`. + For native unsigned 63 bit integers, require the module :g:`ZifyUint63`. + For native signed 63 bit integers, require the module :g:`ZifySint63`. + For operators :g:`Nat.div`, :g:`Nat.mod`, and :g:`Nat.pow`, require the module :g:`ZifyNat`. + For operators :g:`N.div`, :g:`N.mod`, and :g:`N.pow`, require the module :g:`ZifyN`. :tacn:`zify` can also be extended by rebinding the tactics `Zify.zify_pre_hook` and `Zify.zify_post_hook` that are respectively run in the first and the last steps of :tacn:`zify`. + To support :g:`Z.divide`: ``Ltac Zify.zify_post_hook ::= Z.divide_to_equations``. + To support :g:`Z.div` and :g:`Z.modulo`: ``Ltac Zify.zify_post_hook ::= Z.div_mod_to_equations``. + To support :g:`Z.quot` and :g:`Z.rem`: ``Ltac Zify.zify_post_hook ::= Z.quot_rem_to_equations``. + To support :g:`Z.divide`, :g:`Z.div`, :g:`Z.modulo`, :g:`Z.quot` and :g:`Z.rem`: either ``Ltac Zify.zify_post_hook ::= Z.to_euclidean_division_equations`` or ``Ltac Zify.zify_convert_to_euclidean_division_equations_flag ::= constr:(true)``. The :g:`Z.to_euclidean_division_equations` tactic consists of the following passes: - :g:`Z.divide_to_equations'`, posing characteristic equations using factors from :g:`Z.divide` - :g:`Z.div_mod_to_equations'`, posing characteristic equations for and generalizing over :g:`Z.div` and :g:`Z.modulo` - :g:`Z.quot_rem_to_equations'`, posing characteristic equations for and generalizing over :g:`Z.quot` and :g:`Z.rem` - :g:`Z.euclidean_division_equations_cleanup`, removing impossible hypotheses introduced by the above passes, such as those presupposing :g:`x <> x` - :g:`Z.euclidean_division_equations_find_duplicate_quotients`, which heuristically adds equations of the form :g:`q1 = q2 \/ q1 <> q2` when it seems that two quotients might be equal, allowing :g:`nia` to prove more goals, including those relating :g:`Z.quot` and :g:`Z.modulo` to :g:`Z.quot` and :g:`Z.rem`. The :tacn:`zify` tactic can be extended with new types and operators by declaring and registering new typeclass instances using the following commands. The typeclass declarations can be found in the module ``ZifyClasses`` and the default instances can be found in the module ``ZifyInst``. .. cmd:: Add Zify @add_zify @qualid .. insertprodn add_zify add_zify .. prodn:: add_zify ::= {| InjTyp | BinOp | UnOp | CstOp | BinRel | UnOpSpec | BinOpSpec } | {| PropOp | PropBinOp | PropUOp | Saturate } Registers an instance of the specified typeclass. The typeclass type (e.g. :g:`BinOp Z.mul` or :g:`BinRel (@eq Z)`) has the additional constraint that the non-implicit argument (here, :g:`Z.mul` or :g:`(@eq Z)`) is either a :n:`@reference` (here, :g:`Z.mul`) or the application of a :n:`@reference` (here, :g:`@eq`) to a sequence of :n:`@one_term`. This command supports attributes :attr:`local`, :attr:`export` and :attr:`global`. In sections only :attr:`local` is supported, outside sections the default is :attr:`global`. .. cmd:: Show Zify @show_zify .. insertprodn show_zify show_zify .. prodn:: show_zify ::= {| InjTyp | BinOp | UnOp | CstOp | BinRel | UnOpSpec | BinOpSpec | Spec } Prints instances for the specified typeclass. For instance, :cmd:`Show Zify` ``InjTyp`` prints the list of types that supported by :tacn:`zify` i.e., :g:`Z`, :g:`nat`, :g:`positive` and :g:`N`. .. tacn:: zify_elim_let zify_iter_let @ltac_expr zify_iter_specs zify_op zify_saturate For internal use only (it may change without notice). .. _lra_example: .. example:: Lra The :tacn:`lra` tactic automatically proves the following goal. .. rocqtop:: in extra-stdlib From Stdlib Require Import QArith Lqa. #[local] Open Scope Q_scope. Lemma example_lra x y : x + 2 * y <= 4 -> 2 * x + y <= 4 -> x + y < 3. Proof. lra. Qed. Although understanding what's going on under the hood is not required to use the tactic, here are the details for curious users or advanced users interested in deriving their own tactics for arithmetic types other than ``Q`` or ``R`` from the standard library. Mathematically speaking, one needs to prove that :math:`p_2 \ge 0 \land p_1 \ge 0 \land p_0 \ge 0` is unsatisfiable with :math:`p_2 := 4 - x - 2y` and :math:`p_1 := 4 - 2x - y` and :math:`p_0 := x + y - 3`. This is done thanks to the :term:`cone expression` :math:`p_2 + p_1 + 3 \times p_0 \equiv -1`. .. rocqtop:: all extra-stdlib From Stdlib.micromega Require Import RingMicromega QMicromega EnvRing Tauto. Print example_lra. Here, ``__ff`` is a reified representation of the goal and ``__varmap`` is a variable map giving the interpretation of each variable (here that ``PEX 1`` in ``__ff`` stands for ``__x1`` and ``PEX 2`` for ``__x2``). Finally, ``__wit`` is the :term:`cone expression` also called *witness*. This proof could also be obtained by the following tactics where :n:`wlra_Q wit ff` calls the oracle on the goal ``ff`` and puts the resulting :term:`cone expression` in ``wit``. ``QTautoChecker_sound`` is a theorem stating that, when the function call ``QTautoChecker ff wit`` returns ``true``, then the goal represented by ``ff`` is valid. .. rocqtop:: in extra-stdlib Lemma example_lra' x y : x + 2 * y <= 4 -> 2 * x + y <= 4 -> x + y < 3. Proof. pose (ff := IMPL (A isProp {| Flhs := PEadd (PEX 1) (PEmul (PEc 2) (PEX 2)); Fop := OpLe; Frhs := PEc 4 |} tt) None (IMPL (A isProp {| Flhs := PEadd (PEmul (PEc 2) (PEX 1)) (PEX 2); Fop := OpLe; Frhs := PEc 4 |} tt) None (A isProp {| Flhs := PEadd (PEX 1) (PEX 2); Fop := OpLt; Frhs := PEc 3 |} tt)) : BFormula (Formula Q) isProp). .. rocqtop:: all extra-stdlib pose (varmap := VarMap.Branch (VarMap.Elt y) x VarMap.Empty). let ff' := eval unfold ff in ff in wlra_Q wit ff'. change (eval_bf (Qeval_formula (@VarMap.find Q 0 varmap)) ff). apply (QTautoChecker_sound ff wit). .. rocqtop:: in extra-stdlib vm_compute. reflexivity. Qed. .. [#csdp] Sources and binaries can be found at ``_ .. [#fnpsatz] Variants deal with equalities and strict inequalities. .. [#mayfail] In practice, the oracle might fail to produce such a refutation. .. comment in original TeX: .. %% \paragraph{The {\tt sos} tactic} -- where {\tt sos} stands for \emph{sum of squares} -- tries to prove that a .. %% single polynomial $p$ is positive by expressing it as a sum of squares \emph{i.e.,} $\sum_{i\in S} p_i^2$. .. %% This amounts to searching for $p$ in the cone without generators \emph{i.e.}, $Cone(\{\})$. rocq-9.2.0/doc/sphinx/addendum/miscellaneous-extensions.rst000066400000000000000000000041751516144147600241370ustar00rootroot00000000000000Program derivation ================== Rocq comes with an extension called ``Derive``, which supports program derivation. Typically in the style of Bird and Meertens formalism or derivations of program refinements. To use the Derive extension it must first be required with ``From Corelib Require Derive``. When the extension is loaded, it provides the following command: .. cmd:: Derive @open_binders in @type as @ident Derive @open_binders SuchThat @type As @ident where :n:`@open_binders` is a list of the form :n:`@ident__i : @type__i` which can appear in :n:`@type`. This command opens a new proof presenting the user with a goal for :n:`@type` in which each name :n:`@ident__i` is bound to an existential variable of same name :g:`?ident__i` (these existential variables are shelved goals, as described in :tacn:`shelve`). When the proof is complete, Rocq defines :term:`constants ` for each :n:`@ident__i` and for :n:`@ident`: + The first ones, named :n:`@ident__i`, are defined as the proof of the shelved goals (which are also the value of :n:`?ident__i`). They are always transparent. + The final one is named :n:`@ident`. It has type :n:`@type`, and its :term:`body` is the proof of the initially visible goal. It is opaque if the proof ends with :cmd:`Qed`, and transparent if the proof ends with :cmd:`Defined`. .. example:: .. rocqtop:: none Module Nat. Axiom mul_add_distr_l : forall n m p : nat, n * (m + p) = n * m + n * p. End Nat. .. rocqtop:: all From Corelib Require Derive. Section P. Variables (n m k:nat). Derive j p in ((k*n)+(k*m) = j*p) as h. Proof. rewrite <- Nat.mul_add_distr_l. subst j p. reflexivity. Qed. End P. Print j. Print p. Check h. Any property can be used as `type`, not only an equation. In particular, it could be an order relation specifying some form of program refinement or a non-executable property from which deriving a program is convenient. .. note:: The syntax :n:`Derive @open_binders SuchThat @type As @ident` is obsolete and to be avoided. rocq-9.2.0/doc/sphinx/addendum/nsatz.rst000066400000000000000000000154261516144147600202370ustar00rootroot00000000000000.. _nsatz_chapter: Nsatz: a solver for equalities in integral domains =========================================================== :Author: LoΓ―c Pottier, Laurent Thery and Lionel Blatter .. note:: The tactics described in this chapter require the Stdlib library. This chapter presents the tactics dedicated to deal with equalities in integral domains. What does this tactics do? ------------------------------ On a commutative ring :math:`A` with no zero divisors, if a polynomial :math:`P` in :math:`A[X_1,\ldots,X_n]` verifies .. math:: c P^r = \sum_{i=1}^{s} S_i P_i, with :math:`c \in A`, :math:`c \not = 0`, :math:`r` a positive integer, and the :math:`S_i` s in :math:`A[X_1,\ldots,X_n ]`, then :math:`P` is zero whenever polynomials :math:`P_1,\ldots,P_s` are zero (the converse is also true when :math:`A` is an algebraically closed field: the method is complete). In the same setting, if a polynomial :math:`P` in :math:`A[X_1,\ldots,X_n]` verifies .. math:: c P = \sum_{i=1}^{s} S_i P_i, with :math:`c \in A`, :math:`c = 1` or :math:`c = -1`, then :math:`\exists Y_1, \dots, Y_m, P = \sum_{i=1}^{m} Y_i P_i` The :tacn:`nsatz` and :tacn:`ensatz` tactics finds :math:`S_1, \ldots, S_s`, :math:`c` and :math:`r` by the computation of a GrΓΆbner basis of the ideal generated by :math:`P_1,...,P_s`. This is done using an adapted version of the Buchberger algorithm. The witnesses returned by the Buchberger algorithm are checked to be correct solutions to the inital problem. This computation is done after a step of *reification*. Concrete usage --------------------- To use the tactic :tacn:`nsatz` described in this section, load the ``Nsatz`` module with the command ``Require Import Nsatz``. Alternatively, if you prefer not to transitively depend on the files that declare the axioms used to define the real numbers, you can ``Require Import NsatzTactic`` instead; this will still allow :tacn:`nsatz` to solve goals defined about :math:`\mathbb{Z}`, :math:`\mathbb{Q}` and any user-registered rings. To use the tactic :tacn:`ensatz` described in this section, use in addition the command ``Require Import ENsatzTactic``. .. tacn:: nsatz {? with radicalmax := @one_term strategy := @one_term parameters := @one_term variables := @one_term } This tactic is for solving goals of the form .. math:: P(\bar{X}) = Q(\bar{X}), given the premises :math:`P_i(\bar{X}) = Q_i(\bar{X})`, which may be part of the goal or already in the hypotheses or a mix of both, :math:`A` an integral domain, i.e. a commutative ring with no zero divisors, :math:`\bar{X} \in A^n`, and all :math:`P` and :math:`Q` are polynomials. For example, :math:`A` can be :math:`\mathbb{R}`, :math:`\mathbb{Z}`, or :math:`\mathbb{Q}`. Note that the equality :math:`=` used in these goals can be any setoid equality (see :ref:`tactics-enabled-on-user-provided-relations`) , not only Leibniz equality. `radicalmax` bound when searching for r such that :math:`c (Pβˆ’Q)^r = \sum_{i=1..s} S_i (P_i βˆ’ Q_i)`. This argument must be of type `N` (natural numbers). `strategy` gives the order on variables :math:`X_1,\ldots,X_n` and the strategy used in Buchberger algorithm (see :cite:`sugar` for details): * `strategy := 0%Z`: reverse lexicographic order and newest s-polynomial. * `strategy := 1%Z`: reverse lexicographic order and sugar strategy. * `strategy := 2%Z`: pure lexicographic order and newest s-polynomial. * `strategy := 3%Z`: pure lexicographic order and sugar strategy. `parameters` a list of parameters of type `R`, containing the variables :math:`X_{i_1},\ldots,X_{i_k}` among :math:`X_1,\ldots,X_n`. Computation will be performed with rational fractions in these parameters, i.e. polynomials have coefficients in :math:`R(X_{i_1},\ldots,X_{i_k})`. In this case, the coefficient :math:`c` can be a nonconstant polynomial in :math:`X_{i_1},\ldots,X_{i_k}`, and the tactic produces a goal which states that :math:`c` is not zero. `variables` a list of variables of type `R` in the decreasing order in which they will be used in the Buchberger algorithm. If the list is empty, then `lvar` is replaced by all the variables which are not in `parameters`. .. example:: .. rocqtop:: in extra-stdlib From Stdlib Require Import Znumtheory. From Stdlib Require Import ZArith. From Stdlib Require Import ZNsatz. Goal forall (x y z : Z), ( x + y + z = 0 -> x * y + x * z + y * z = 0 -> x * y * z = 0 -> x * x * x = 0)%Z. Proof. nsatz. Qed. See the file `Nsatz.v `_ for examples, especially in geometry. .. tacn:: ensatz {? with strategy := @one_term } Solves goals of the form .. math:: \exists Y_1, \ldots, Y_m \in A, P(\bar{X}) = Q(\bar{X}) + \sum_{i=1}^{m} Y_i * I_i(\bar{X}) given the premises :math:`P_i(\bar{X}) = Q_i(\bar{X})`, which may be part of the goal or already in the hypotheses or a mix of both, :math:`A` an integral domain, i.e. a commutative ring with no zero divisors, :math:`\bar{X} \in A^n`, and all :math:`P`, :math:`Q` and :math:`I` are polynomials. For example, :math:`A` can be :math:`\mathbb{R}`, :math:`\mathbb{Z}`, or :math:`\mathbb{Q}`. Note that the equality :math:`=` used in these goals can be any setoid equality (see :ref:`tactics-enabled-on-user-provided-relations`), not only Leibniz equality. For the `strategy` parameter, see the desciption for the `nsatz` tactic. .. example:: .. rocqtop:: in extra-stdlib From Stdlib Require Import Znumtheory. From Stdlib Require Import ZArith. From Stdlib Require Import ZNsatz. From Stdlib Require Import ENsatzTactic. Goal forall a b n j x y z : Z, a - j = x * n -> b - y = z * n -> exists k : Z, a * b - j * y = k * n. Proof. ensatz. Qed. The tactic can also solve goals with existential variables. .. example:: .. rocqtop:: in extra-stdlib From Stdlib Require Import Znumtheory. From Stdlib Require Import ZArith. From Stdlib Require Import ZNsatz. From Stdlib Require Import ENsatzTactic. Goal forall a b n j x y z : Z, a - j = x * n -> b - y = z * n -> exists k : Z, a * b - j * y = k * n. Proof. intros. eexists. ensatz. Qed. See the file `ENsatz.v `_ and `EENsatz.v `_ for examples. .. tacn:: nsatz_compute @one_term :undocumented: rocq-9.2.0/doc/sphinx/addendum/parallel-proof-processing.rst000066400000000000000000000207441516144147600241700ustar00rootroot00000000000000.. _asynchronousandparallelproofprocessing: Asynchronous and Parallel Proof Processing ========================================== :Author: Enrico Tassi This chapter explains how proofs can be asynchronously processed by Rocq. This feature improves the reactivity of the system when used in interactive mode via RocqIDE. In addition, it allows Rocq to take advantage of parallel hardware when used as a batch compiler by decoupling the checking of statements and definitions from the construction and checking of proofs objects. This feature is designed to help dealing with huge libraries of theorems characterized by long proofs. In the current state, it may not be beneficial on small sets of short files. This feature has some technical limitations that may make it unsuitable for some use cases. For example, in interactive mode, some errors coming from the kernel of Rocq are signaled late. The type of errors belonging to this category are universe inconsistencies. At the time of writing, only opaque proofs (ending with :cmd:`Qed` or :cmd:`Admitted`) can be processed asynchronously. Finally, asynchronous processing is disabled when running RocqIDE in Windows. The current implementation of the feature is not stable on Windows. It can be enabled, as described below at :ref:`interactive-mode`, though doing so is not recommended. .. _proof-annotations: Proof annotations ---------------------- To process a proof asynchronously Rocq needs to know the precise statement of the theorem without looking at the proof. This requires some annotations if the theorem is proved inside a Section (see Section :ref:`section-mechanism`). When a :ref:`section ` ends, Rocq looks at the proof object to decide which section variables are actually used and hence have to be quantified in the statement of the theorem. To avoid making the construction of proofs mandatory when ending a section, one can start each proof with the :cmd:`Proof using` command (Section :ref:`proof-editing-mode`) that declares which section variables the theorem uses. The presence of :cmd:`Proof using` is needed to process proofs asynchronously 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 :cmd:`Proof using`, the system records in an auxiliary file, produced along with the ``.vo`` file, the list of section variables used. If a theorem has an incorrect annotation that omits a needed variable, you may see a message like this: .. code-block:: File "./Pff.v", line 2372, characters 0-4: Error: The following section variable is used but not declared: precisionNotZero. You can either update your proof to not depend on precisionNotZero, or you can update your Proof line from Proof using FtoRradix b pGivesBound precision radix radixMoreThanOne radixMoreThanZERO to Proof using FtoRradix b pGivesBound precision precisionNotZero radix radixMoreThanOne radixMoreThanZERO In this case the minimal annotation suggested by the :flag:`Suggest Proof Using` flag is `Print Using pGivesBound precisionNotZero radixMoreThanOne.` The other variables in the suggestion are unnecessary because they will be transitively included from the minimal annotation. Alternatively, if the :cmd:`Proof using` included unneeded variables, they become extra parameters of the theorem, which may generate errors. This :ref:`example ` shows an example of an unneeded variable. One possible error is `(in proof ) Attempt to save an incomplete proof`, which may indicate that the named theorem refers to an earlier theorem that has an incorrect annotation. Automatic suggestion of proof annotations ````````````````````````````````````````` The :flag:`Suggest Proof Using` flag makes Rocq suggest, when a :cmd:`Qed` command is processed, a correct proof annotation. It is up to the user to modify the proof script accordingly. Proof blocks and error resilience -------------------------------------- In interactive mode Rocq is able to completely check a document containing errors instead of bailing out at the first failure. Two kind of errors are handled: errors occurring in commands and errors occurring in proofs. To properly recover from a failing tactic, Rocq needs to recognize the structure of the proof in order to confine the error to a sub proof. Proof block detection is performed by looking at the syntax of the proof script (i.e. also looking at indentation). Rocq comes with four kind of proof blocks, and an ML API to add new ones. :curly: blocks are delimited by { and }, see Chapter :ref:`proofhandling` :par: blocks are atomic, i.e. just one tactic introduced by the `par:` goal selector :indent: blocks end with a tactic indented less than the previous one :bullet: blocks are delimited by two equal bullet signs at the same indentation level Caveats ```````` When a command fails the subsequent error messages may be bogus, i.e. caused by the first error. Error resilience for commands can be switched off by passing ``-async-proofs-command-error-resilience off`` to RocqIDE. An incorrect proof block detection can result into an incorrect error recovery and hence in bogus errors. Proof block detection cannot be precise for bullets or any other non-well parenthesized proof structure. Error resilience can be turned off or selectively activated for any set of block kind passing to RocqIDE one of the following options: - ``-async-proofs-tactic-error-resilience off`` - ``-async-proofs-tactic-error-resilience all`` - ``-async-proofs-tactic-error-resilience`` :n:`{*, blocktype}` Valid proof block types are: β€œcurly”, β€œpar”, β€œindent”, and β€œbullet”. .. _interactive-mode: Interactive mode --------------------- .. todo: How about PG and coqtail? RocqIDE and VsCoq support asynchronous proof processing. When RocqIDE is started and async mode is enabled, two or more Rocq processes are created. The master one follows the user, giving feedback as soon as possible by skipping proofs, which are delegated to the worker processes. The worker processes asynchronously processes the proofs. The *Jobs panel* in the main RocqIDE window shows the status of each worker process. If a proof contains an error, it's reported in red in the label of the very same button, that can also be used to see the list of errors and jump to the corresponding line. If a proof is processed asynchronously the corresponding :cmd:`Qed` command is colored using a lighter color than usual. This signals that the proof has been delegated to a worker process (or will be processed lazily if the ``-async-proofs lazy`` option is used). Once finished, the worker process will provide the proof object, but this will not be automatically checked by the kernel of the main process. To force the kernel to check all the proof objects, one has to click the button with the gears (Fully check the document) on the top bar. Only then all the universe constraints are checked. 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 `rocq workmgr` 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). `rocq workmgr` automatically starts in the background and prints an environment variable assignment like `ROCQWORKMGR\_SOCKET=localhost:45634`. The user must set this variable in all the shells from which Rocq processes will be started. If one uses just one terminal running the bash shell, then `export $(rocq workmgr -j 4)` will do the job. After that, all Coq processes, e.g. `rocqide` and `rocq compile`, will honor the limit, globally. Caveats ``````` The number of worker processes can be increased by passing RocqIDE the ``-async-proofs-j n`` flag. Note that the memory consumption increases too, since each worker requires the same amount of memory as the master process. Also note that increasing the number of workers may reduce the reactivity of the master process to user commands. To disable this feature, one can pass the ``-async-proofs off`` flag to RocqIDE. Conversely, on Windows, where the feature is disabled by default, pass the ``-async-proofs on`` flag to enable it. Proofs that are known to take little time to process are not delegated to a worker process. The threshold can be configured with ``-async-proofs-delegation-threshold``. Default is 0.03 seconds. rocq-9.2.0/doc/sphinx/addendum/program.rst000066400000000000000000000335271516144147600205510ustar00rootroot00000000000000.. this should be just "_program", but refs to it don't work .. _programs: Program ======== :Author: Matthieu Sozeau We present here the |Program| tactic commands, used to build certified Rocq programs, elaborating them from their algorithmic skeleton and a rich specification :cite:`sozeau06`. It can be thought of as a dual of :ref:`Extraction `. The goal of |Program| is to program as in a regular functional programming language whilst using as rich a specification as desired and proving that the code meets the specification using the whole Rocq proof apparatus. This is done using a technique originating from the β€œPredicate subtyping” mechanism of PVS :cite:`Rushby98`, which generates type checking conditions while typing a term constrained to a particular type. Here we insert existential variables in the term, which must be filled with proofs to get a complete Rocq term. |Program| replaces the |Program| tactic by Catherine Parent :cite:`Parent95b` which had a similar goal but is no longer maintained. The languages available as input is Rocq's term language. We use the same syntax as Rocq and permit to use implicit arguments and the existing coercion mechanism. Input terms and types are typed in an extended system (Russell) and elaborated into Rocq terms. The elaboration process may produce some proof obligations which need to be resolved to create the final term. .. _elaborating-programs: Elaborating programs -------------------- The main difference from plain Rocq is that an object in a type :g:`T : Set` can be considered as an object of type :g:`{x : T | P}` for any well-formed :g:`P : Prop`. If we go from :g:`T` to the subset of :g:`T` verifying property :g:`P`, we must prove that the object under consideration verifies it. Russell will generate an obligation for every such coercion. In the other direction, Russell will automatically insert a projection. Another distinction is the treatment of pattern matching. Apart from the following differences, it is equivalent to the standard match operation (see :ref:`extendedpatternmatching`). + Generation of equalities. A match expression is always generalized by the corresponding equality. As an example, the expression: :: match x with | 0 => t | S n => u end. will be first rewritten to: :: (match x as y return (x = y -> _) with | 0 => fun H : x = 0 -> t | S n => fun H : x = S n -> u end) (eq_refl x). This permits to get the proper equalities in the context of proof obligations inside clauses, without which reasoning is very limited. + Generation of disequalities. If a pattern intersects with a previous one, a disequality is added in the context of the second branch. See for example the definition of div2 below, where the second branch is typed in a context where :g:`βˆ€ p, _ <> S (S p)`. + Coercion. If the object being matched is coercible to an inductive type, the corresponding coercion will be automatically inserted. This also works with the previous mechanism. There are flags to control the generation of equalities and coercions. .. flag:: Program Cases This :term:`flag` controls the special treatment of pattern matching generating equalities and disequalities when using |Program| (it is on by default). All pattern-matches and let-patterns are handled using the standard algorithm of Rocq (see :ref:`extendedpatternmatching`) when this flag is deactivated. .. flag:: Program Generalized Coercion This :term:`flag` controls the coercion of general inductive types when using |Program| (the flag is on by default). Coercion of subset types and pairs is still active in this case. .. flag:: Program Mode This :term:`flag` enables the program mode, in which 1) typechecking allows subset coercions and 2) the elaboration of pattern matching of :cmd:`Fixpoint` and :cmd:`Definition` acts as if the :attr:`program` attribute has been used, generating obligations if there are unresolved holes after typechecking. .. attr:: program{? = {| yes | no } } :name: program; Program This :term:`boolean attribute` allows using or disabling the Program mode on a specific definition. An alternative and commonly used syntax is to use the legacy ``Program`` prefix (cf. :n:`@legacy_attr`) as it is elsewhere in this chapter. .. _syntactic_control: Syntactic control over equalities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To give more control over the generation of equalities, the type checker will fall back directly to Coq’s usual typing of dependent pattern matching if a ``return`` or ``in`` clause is specified. Likewise, the if construct is not treated specially by |Program| so boolean tests in the code are not automatically reflected in the obligations. One can use the :g:`dec` combinator to get the correct hypotheses as in: .. rocqtop:: in From Corelib.Program Require Import Basics Tactics. .. rocqtop:: all Program Definition id (n : nat) : { x : nat | x = n } := if sumbool_of_bool (Nat.leb n 0) then 0 else S (pred n). The :g:`let` tupling construct :g:`let (x1, ..., xn) := t in b` does not produce an equality, contrary to the let pattern construct :g:`let '(x1,..., xn) := t in b`. The next two commands are similar to their standard counterparts :cmd:`Definition` and :cmd:`Fixpoint` in that they define :term:`constants `. However, they may require the user to prove some goals to construct the final definitions. .. _program_definition: Program Definition ~~~~~~~~~~~~~~~~~~ A :cmd:`Definition` command with the :attr:`program` attribute types the value term in Russell and generates proof obligations. Once solved using the commands shown below, it binds the final Rocq term to the name :n:`@ident` in the global environment. :n:`Program Definition @ident_decl : @type := @term` Interprets the type :n:`@type`, potentially generating proof obligations to be resolved. Once done with them, we have a Rocq type :n:`@type__0`. It then elaborates the preterm :n:`@term` into a Rocq term :n:`@term__0`, checking that the type of :n:`@term__0` is coercible to :n:`@type__0`, and registers :n:`@ident` as being of type :n:`@type__0` once the set of obligations generated during the interpretation of :n:`@term__0` and the aforementioned coercion derivation are solved. .. exn:: Non extensible universe declaration not supported with monomorphic Program Definition. The absence of additional universes or constraints cannot be properly enforced even without Program. .. seealso:: Sections :ref:`controlling-the-reduction-strategies`, :tacn:`unfold` .. _program_fixpoint: Program Fixpoint ~~~~~~~~~~~~~~~~ A :cmd:`Fixpoint` command with the :attr:`program` attribute may also generate obligations. It works with mutually recursive definitions too. For example: .. rocqtop:: reset in From Corelib.Program Require Import Basics Tactics. .. rocqtop:: all Program Fixpoint div2 (n : nat) : { x : nat | n = 2 * x \/ n = 2 * x + 1 } := match n with | S (S p) => S (div2 p) | _ => O end. The :cmd:`Fixpoint` command may include an optional :n:`@fixannot` annotation, which can be: + :g:`measure f R` where :g:`f` is a value of type :g:`X` computed on any subset of the arguments and the optional term :g:`R` is a relation on :g:`X`. :g:`X` defaults to :g:`nat` and :g:`R` to :g:`lt`. + :g:`wf R x` which is equivalent to :g:`measure x R`. .. todo see https://github.com/rocq-prover/rocq/pull/12936#discussion_r492747830 Here we have one obligation for each branch (branches for :g:`0` and ``(S 0)`` are automatically generated by the pattern matching compilation algorithm). .. rocqtop:: all Obligation 1. .. rocqtop:: reset none From Corelib.Program Require Import Basics Tactics Wf. One can use a well-founded order or a measure as termination orders using the syntax: .. rocqtop:: in Program Fixpoint div2 (n : nat) {measure n} : { x : nat | n = 2 * x \/ n = 2 * x + 1 } := match n with | S (S p) => S (div2 p) | _ => O end. .. note:: The :g:`measure f R` and :g:`wf R x` annotations add an implicit argument to the functions being defined. When the function name is prefixed with :g:`@` (see :ref:`deactivation-of-implicit-arguments`), the position of the extra argument needs to be taken into account, e.g. by providing :g:`_` or an explicit value. .. caution:: When defining structurally recursive functions, the generated obligations should have the prototype of the currently defined functional in their context. In this case, the obligations should be transparent (e.g. defined using :g:`Defined`) so that the guardedness condition on recursive calls can be checked by the kernel’s type- checker. There is an optimization in the generation of obligations which gets rid of the hypothesis corresponding to the functional when it is not necessary, so that the obligation can be declared opaque (e.g. using :g:`Qed`). However, as soon as it appears in the context, the proof of the obligation is *required* to be declared transparent. No such problems arise when using measures or well-founded recursion. .. _program_lemma: Program Lemma ~~~~~~~~~~~~~ A :cmd:`Lemma` command with the :attr:`program` attribute uses the Russell language to type statements of logical properties. It generates obligations, tries to solve them automatically and fails if some unsolved obligations remain. In this case, one can first define the lemma’s statement using :cmd:`Definition` and use it as the goal afterwards. Otherwise the proof will be started with the elaborated version as a goal. The :attr:`program` attribute can similarly be used with :cmd:`Variable`, :cmd:`Hypothesis`, :cmd:`Axiom` etc. .. _solving_obligations: Solving obligations ------------------- The following commands are available to manipulate obligations. The optional identifier is used when multiple functions have unsolved obligations (e.g. when defining mutually recursive blocks). The optional tactic is replaced by the default one if not specified. .. cmd:: Obligation Tactic := @generic_tactic Sets the default obligation solving tactic applied to all obligations automatically, whether to solve them or when starting to prove one, e.g. using :cmd:`Next Obligation`. This command supports the :attr:`local`, :attr:`export` and :attr:`global` attributes. :attr:`local` makes the setting last only for the current module. :attr:`local` is the default inside sections while :attr:`global` otherwise. :attr:`export` and :attr:`global` may be used together. When :attr:`global` is used without :attr:`export` and when no explicit locality is used outside sections, the meaning is different from the usual meaning of :attr:`global`: the command's effect persists after the current module is closed (as with the usual :attr:`global`), but it is also reapplied when the module or any of its parents is imported. This will change in a future version. .. cmd:: Show Obligation Tactic Displays the current default tactic. .. cmd:: Obligations {? of @ident } Displays all remaining obligations. .. cmd:: Obligation @natural {? of @ident } {? with @generic_tactic } Start the proof of obligation :token:`natural`. .. cmd:: Next Obligation {? of @ident } {? with @generic_tactic } Start the proof of the next unsolved obligation. .. cmd:: Final Obligation {? of @ident } {? with @generic_tactic } Like :cmd:`Next Obligation`, starts the proof of the next unsolved obligation. Additionally, at :cmd:`Qed` time, after the automatic solver has run on any remaining obligations, Rocq checks that no obligations remain for the given :token:`ident` when provided and otherwise in the current module. .. cmd:: Solve Obligations {? of @ident } {? with @ltac_expr } Tries to solve each obligation of :token:`ident` using the given :token:`ltac_expr` or the default one. .. cmd:: Solve All Obligations {? with @ltac_expr } Tries to solve each obligation of every program using the given tactic or the default one (useful for mutually recursive definitions). .. cmd:: Admit Obligations {? of @ident } Admits all obligations (of :token:`ident`). .. note:: Does not work with structurally recursive programs. .. cmd:: Preterm {? of @ident } Shows the term that will be fed to the kernel once the obligations are solved. Useful for debugging. .. flag:: Transparent Obligations This :term:`flag` controls whether all obligations should be declared as transparent (the default), or if the system should infer which obligations can be declared opaque. The module :g:`Corelib.Program.Tactics` defines the default tactic for solving obligations called :g:`program_simpl`. Importing :g:`Stdlib.Program.Program` also adds some useful notations, as documented in the file itself. .. _program-faq: Frequently Asked Questions --------------------------- .. exn:: Ill-formed recursive definition. This error can happen when one tries to define a function by structural recursion on a subset object, which means the Rocq function looks like: :: Program Fixpoint f (x : A | P) := match x with A b => f b end. Supposing ``b : A``, the argument at the recursive call to ``f`` is not a direct subterm of ``x`` as ``b`` is wrapped inside an ``exist`` constructor to build an object of type ``{x : A | P}``. Hence the definition is rejected by the guardedness condition checker. However one can use wellfounded recursion on subset objects like this: :: Program Fixpoint f (x : A | P) { measure (size x) } := match x with A b => f b end. One will then just have to prove that the measure decreases at each recursive call. There are three drawbacks though: #. A measure function has to be defined; #. The reduction is a little more involved, although it works well using lazy evaluation; #. Mutual recursion on the underlying inductive type isn’t possible anymore, but nested mutual recursion is always possible. rocq-9.2.0/doc/sphinx/addendum/rewrite-rules.rst000066400000000000000000000172741516144147600217140ustar00rootroot00000000000000:ROCQTOP_ARGS: -allow-rewrite-rules .. _rewrite_rules: User-defined rewrite rules ========================== .. warning:: Rewrite rules are highly experimental. In particular, ill-typed rewrite rules will lead to mistyped expressions, and manipulating these will most often result in inconsistencies and anomalies. This section describes the extension of Rocq's reduction mechanisms with user-defined rewrite rules, as a means to extend definitional equality. It should not be confused with the :ref:`rewrite tactic ` or :ref:`setoid rewriting ` which operate on propositional equality and other relations which are defined in Rocq. Rewrite rules need to be enabled by passing the option ``-allow-rewrite-rules`` to the Rocq program. .. exn:: Rewrite rule declaration requires passing the flag "-allow-rewrite-rules". :undocumented: Symbols ----------------- Rewrite rules operate on symbols, which are their own kind of constants. They stand in-between defined constants and axioms, in that they don't always reduce as defined constants do, but they may still reduce using the provided rules, unlike axioms. .. cmd:: {| Symbol | Symbols } {| @assumpt | {+ ( @assumpt ) } } :name: Symbol; Symbols Binds an :n:`@ident` to a :n:`@type` as a symbol. .. rocqtop:: in Symbol pplus : nat -> nat -> nat. Notation "a ++ b" := (pplus a b). Rewrite rules --------------- .. cmd:: Rewrite {| Rule | Rules } @ident := {? %| } {+| @rewrite_rule } :name: Rewrite Rule; Rewrite Rules .. insertprodn rewrite_rule rewrite_rule .. prodn:: rewrite_rule ::= {? @univ_decl %|- } @rw_pattern => @term Declares a named block of rewrite rules. The name is declared in the same namespace as constants and inductives. Rewrite rules have two parts named pattern (left-hand side) and replacement (right-hand side). Patterns are a subclass of :n:`@term`\s described :ref:`below`, while replacements are regular :n:`@term`\s, which can also refer to the pattern variables matched by the pattern with the :n:`?@name` syntax. When a rule is applied, the term is matched against the pattern, subterms aligned with pattern variables are collected and then substituted into the replacement, which is returned. .. rocqtop:: all Rewrite Rule pplus_rewrite := | ?n ++ 0 => ?n | ?n ++ S ?m => S (?n ++ ?m) | 0 ++ ?n => ?n | S ?n ++ ?m => S (?n ++ ?m). .. _Pattern syntax: Pattern syntax -------------- Patterns are a subclass of :n:`@term`\s which are rigid enough to be matched against. Informally, they are terms with pattern variables (:n:`?@name`), where those may not appear on the left of applications or as the discriminee of a match or a primitive projection; furthermore a pattern may not have let-bindings, (co-)fixpoints or non-symbol constants. As a formal grammar, it is easier to understand them with the separation between head-pattern (:n:`@rw_head_pattern`) and eliminations (non-base-case constructions for :n:`@rw_pattern`): .. prodn:: rw_pattern ::= @rw_head_pattern | @rw_pattern {+ @rw_pattern_arg } | @rw_pattern .( @qualid {? @univ_annot } ) | match @rw_pattern {? as @name } {? in @pattern } {? return @rw_pattern_arg } with {? | } {*| @pattern => @rw_pattern_arg } end rw_head_pattern ::= @ident | @qualid {? @univ_annot } | fun {+ ({+ @name } {? : @rw_pattern_arg}) } => @rw_pattern_arg | forall {+ ({+ @name } {? : @rw_pattern_arg}) }, @rw_pattern_arg rw_pattern_arg ::= ?@name | _ | @rw_pattern where :n:`@qualid {? @univ_annot }` (in the second line for :n:`@rw_head_pattern`) can refer to symbols, sorts, inductives and constructors, but not arbitrary constants. The projections must be primitive to be allowed. Finally, a valid pattern needs its head head-pattern to be a symbol. Higher-order pattern holes -------------------------- Patterns with lambdas (:n:`fun`), products (:n:`forall`) and :n:`match`\es introduce new variables in the context which need to be substituted in the replacement. To this end, the user can add what to substitute each new variable with, using the syntax :n:`?@name@%{{+; @name := @term }%}`. Note that if in the replacement, the context was extended with a variable bearing the same name, this explicit substitution is inferred automatically (like for existential variable instantiations). .. rocqtop:: all warn Symbol raise : forall (A : Type), A. Rewrite Rule raise_nat := match raise nat as n return ?P with 0 => _ | S _ => _ end => raise ?P@{n := raise nat}. Symbol id : forall (A : Type), A -> A. Rewrite Rule id_rew := id (forall (x : ?A), ?P) ?f => fun (x : ?A) => id ?P (?f x). Universe polymorphic rules -------------------------- Rewrite rules support universe and sort quality polymorphism. Universe levels and sort quality variables must be declared with the notation :n:`@{q1 q2;u1 u2+|+}` (the same notation as universe instance declarations); each variable must appear exactly once in the pattern. If any universe level isn't bound in the rule, as is often the case with the level of a pattern variable when it is a type, you need to make the universe instance extensible (with the final +). Universe level constraints, as inferred from the pattern, must imply those given, which in turn must imply the constraints needed for the replacement. You can make the declared constraints extensible so all inferred constraints from the left-hand side are used for the replacement. .. rocqtop:: reset all warn #[universes(polymorphic)] Symbol raise@{q;u} : forall (A : Type@{q;u}), A. Rewrite Rule raise_nat := @{q;u+|+} |- raise@{q;u} (forall (x : ?A), ?P) => fun (x : ?A) => raise@{q;u} ?P. Rewrite rules, type preservation, confluence and termination ------------------------------------------------------------ Currently, rewrite rules do not ensure that types must be preserved. There is a superficial check that the replacement needs to be typed against the type inferred for the pattern (for an unclear definition of type of a pattern), but it is known to be incomplete and only emits a warning if failed. This then means that reductions using rewrite rules have no reason to preserve well-typedness at all. The responsibility of ensuring type preservation falls on the user entirely. Similarly, neither confluence nor termination are checked by the compiler. There are future plans to add a check on confluence using the triangle criterion :cite:`TotR21` and a more complete check on type preservation. Compatibility with the eta laws ------------------------------- Currently, pattern matching against rewrite rules pattern cannot do eta-expansion or contraction, which means that it cannot properly match against terms of functional types or primitive records. As with type preservation, a check is done to test whether this may happen, but it is not complete (false positives) and thus only emits a warning if failed. Level of support ---------------- Rewrite rules have been integrated into the kernel and the most used parts of the upper layers. Notably, reduction machines simpl, cbn and cbv can reduce on rewrite rules, with some limitations (e.g. simpl cannot reduce on rules which contain a match). Also, regular unification can work with rewrite rules, as well as apply's unification mechanism in a limited manner (only if the pattern contains no match or projections). On the other hand, some operations are not supported, such as declaring rules in sections and some interactions with modules. Since rewrite rules may introduce untyped terms, which the VM and native reduction machines don't support (risk of segfault or code injection), they are turned off when rewrite rules are enabled. rocq-9.2.0/doc/sphinx/addendum/ring.rst000066400000000000000000000747231516144147600200440ustar00rootroot00000000000000.. |bdi| replace:: βδι .. |ra| replace:: :math:`\rightarrow_{\beta\delta\iota}` .. |la| replace:: :math:`\leftarrow_{\beta\delta\iota}` .. |eq| replace:: `=`:sub:`(by the main correctness theorem)` .. |re| replace:: ``(PEeval`` `v` `ap`\ ``)`` .. |le| replace:: ``(Pphi_dev`` `v` ``(norm`` `ap`\ ``))`` .. |N| replace:: ``N`` .. |nat| replace:: ``nat`` .. |Z| replace:: ``Z`` .. _theringandfieldtacticfamilies: ring and field: solvers for polynomial and rational equations ============================================================= :Author: Bruno Barras, Benjamin GrΓ©goire, Assia Mahboubi, Laurent ThΓ©ry [#f1]_ .. note:: The tactics described in this chapter require the Stdlib library. This chapter presents the tactics dedicated to dealing with ring and field equations. What does this tactic do? ------------------------------ ``ring`` does associative-commutative rewriting in ring and semiring structures. Assume you have two binary functions :math:`\oplus` and :math:`\otimes` that are associative and commutative, with :math:`\oplus` distributive on :math:`\otimes`, and two constants 0 and 1 that are unities for :math:`\oplus` and :math:`\otimes`. A polynomial is an expression built on variables :math:`V_0`, :math:`V_1`, :math:`\dots` and constants by application of :math:`\oplus` and :math:`\otimes`. Let an ordered product be a product of variables :math:`V_{i_1} \otimes \dots \otimes V_{i_n}` verifying :math:`i_1 ≀ i_2 ≀ \dots ≀ i_n` . Let a monomial be the product of a constant and an ordered product. We can order the monomials by the lexicographic order on products of variables. Let a canonical sum be an ordered sum of monomials that are all different, i.e. each monomial in the sum is strictly less than the following monomial according to the lexicographic order. It is an easy theorem to show that every polynomial is equivalent (modulo the ring properties) to exactly one canonical sum. This canonical sum is called the normal form of the polynomial. In fact, the actual representation shares monomials with same prefixes. So what does the ``ring`` tactic do? It normalizes polynomials over any ring or semiring structure. The basic use of ``ring`` is to simplify ring expressions, so that the user does not have to deal manually with the theorems of associativity and commutativity. .. example:: In the ring of integers, the normal form of :math:`x (3 + yx + 25(1 βˆ’ z)) + zx` is :math:`28x + (βˆ’24)xz + xxy`. ``ring`` is also able to compute a normal form modulo monomial equalities. For example, under the hypothesis that :math:`2x^2 = yz+1`, the normal form of :math:`2(x + 1)x βˆ’ x βˆ’ zy` is :math:`x+1`. The variables map ---------------------- It is frequent to have an expression built with :math:`+` and :math:`\times`, but rarely on variables only. Let us associate a number to each subterm of a ring expression in the Gallina language. For example, consider this expression in the semiring ``nat``: :: (plus (mult (plus (f (5)) x) x) (mult (if b then (4) else (f (3))) (2))) As a ring expression, it has 3 subterms. Give each subterm a number in an arbitrary order: ===== =============== ========================= 0 :math:`\mapsto` if b then (4) else (f (3)) 1 :math:`\mapsto` (f (5)) 2 :math:`\mapsto` x ===== =============== ========================= Then normalize the β€œabstract” polynomial :math:`((V_1 \oplus V_2 ) \otimes V_2) \oplus (V_0 \otimes 2)` In our example the normal form is: :math:`(2 \otimes V_0 ) \oplus (V_1 \otimes V_2) \oplus (V_2 \otimes V_2 )`. Then substitute the variables by their values in the variables map to get the concrete normal polynomial: :: (plus (mult (2) (if b then (4) else (f (3)))) (plus (mult (f (5)) x) (mult x x))) Is it automatic? --------------------- Yes, building the variables map and doing the substitution after normalizing is automatically done by the tactic. So you can just forget this paragraph and use the tactic according to your intuition. Concrete usage -------------------------- .. tacn:: ring {? [ {+ @one_term } ] } Solves polynomical equations of a ring (or semiring) structure. It proceeds by normalizing both sides of the equation (w.r.t. associativity, commutativity and distributivity, constant propagation, rewriting of monomials) and syntactically comparing the results. :n:`[ {+ @one_term } ]` If specified, the tactic decides the equality of two terms modulo ring operations and the equalities defined by the :token:`one_term`\s. Each :token:`one_term` has to be a proof of some equality :g:`m = p`, where :g:`m` is a monomial (after β€œabstraction”), :g:`p` a polynomial and :g:`=` is the corresponding equality of the ring structure. .. tacn:: ring_simplify {? [ {+ @one_term } ] } {+ @one_term } {? in @ident } Applies the normalization procedure described above to the given :token:`one_term`\s. The tactic then replaces all occurrences of the :token:`one_term`\s given in the conclusion of the goal by their normal forms. If no :token:`one_term` is given, then the conclusion should be an equation and both sides are normalized. The tactic can also be applied in a hypothesis. :n:`in @ident` If specified, the tactic performs the simplification in the hypothesis named :token:`ident`. .. note:: :n:`ring_simplify @one_term__1; ring_simplify @one_term__2` is not equivalent to :n:`ring_simplify @one_term__1 @one_term__2`. In the latter case the variables map is shared between the two :token:`one_term`\s, and common subterm :g:`t` of :n:`@one_term__1` and :n:`@one_term__2` will have the same associated variable number. So the first alternative should be avoided for :token:`one_term`\s belonging to the same ring theory. The tactic must be loaded by ``Require Import Ring``. The ring structures must be declared with the ``Add Ring`` command (see below). The ring of booleans is predefined; if one wants to use the tactic on |nat| one must first require the module ``ArithRing`` exported by ``Arith``); for |Z|, do ``Require Import ZArithRing`` or simply ``Require Import ZArith``; for |N|, do ``Require Import NArithRing`` or ``Require Import NArith``. All declared field structures can be printed with the :cmd:`Print Rings` command. .. cmd:: Print Rings :undocumented: .. example:: .. rocqtop:: all extra-stdlib From Stdlib Require Import ZArith. Open Scope Z_scope. Goal forall a b c:Z, (a + b + c) ^ 2 = a * a + b ^ 2 + c * c + 2 * a * b + 2 * a * c + 2 * b * c. intros; ring. Abort. Goal forall a b:Z, 2 * a * b = 30 -> (a + b) ^ 2 = a ^ 2 + b ^ 2 + 30. intros a b H; ring [H]. Abort. Error messages: .. exn:: Not a valid ring equation. The conclusion of the goal is not provable in the corresponding ring theory. .. exn:: Arguments of ring_simplify do not have all the same type. :tacn:`ring_simplify` cannot simplify terms of several rings at the same time. Invoke the tactic once per ring structure. .. exn:: Cannot find a declared ring structure over @term. No ring has been declared for the type of the terms to be simplified. Use :cmd:`Add Ring` first. .. exn:: Cannot find a declared ring structure for equality @term. Same as above in the case of the :tacn:`ring` tactic. .. tacn:: ring_lookup @ltac_expr0 [ {* @one_term } ] {+ @one_term } protect_fv @string {? in @ident } For internal use only. Adding a ring structure ---------------------------- Declaring a new ring consists in proving that a ring signature (a carrier set, an equality, and ring operations: ``Ring_theory.ring_theory`` and ``Ring_theory.semi_ring_theory``) satisfies the ring axioms. Semi- rings (rings without + inverse) are also supported. The equality can be either Leibniz equality, or any relation declared as a setoid (see :ref:`tactics-enabled-on-user-provided-relations`). The definitions of ring and semiring (see module ``Ring_theory``) are: .. rocqdoc:: Record ring_theory : Prop := mk_rt { Radd_0_l : forall x, 0 + x == x; Radd_sym : forall x y, x + y == y + x; Radd_assoc : forall x y z, x + (y + z) == (x + y) + z; Rmul_1_l : forall x, 1 * x == x; Rmul_sym : forall x y, x * y == y * x; Rmul_assoc : forall x y z, x * (y * z) == (x * y) * z; Rdistr_l : forall x y z, (x + y) * z == (x * z) + (y * z); Rsub_def : forall x y, x - y == x + -y; Ropp_def : forall x, x + (- x) == 0 }. Record semi_ring_theory : Prop := mk_srt { SRadd_0_l : forall n, 0 + n == n; SRadd_sym : forall n m, n + m == m + n ; SRadd_assoc : forall n m p, n + (m + p) == (n + m) + p; SRmul_1_l : forall n, 1*n == n; SRmul_0_l : forall n, 0*n == 0; SRmul_sym : forall n m, n*m == m*n; SRmul_assoc : forall n m p, n*(m*p) == (n*m)*p; SRdistr_l : forall n m p, (n + m)*p == n*p + m*p }. This implementation of ``ring`` also features a notion of constant that can be parameterized. This can be used to improve the handling of closed expressions when operations are effective. It consists in introducing a type of *coefficients* and an implementation of the ring operations, and a morphism from the coefficient type to the ring carrier type. The morphism needs not be injective, nor surjective. As an example, one can consider the real numbers. The set of coefficients could be the rational numbers, upon which the ring operations can be implemented. The fact that there exists a morphism is defined by the following properties: .. rocqdoc:: Record ring_morph : Prop := mkmorph { morph0 : [cO] == 0; morph1 : [cI] == 1; morph_add : forall x y, [x +! y] == [x]+[y]; morph_sub : forall x y, [x -! y] == [x]-[y]; morph_mul : forall x y, [x *! y] == [x]*[y]; morph_opp : forall x, [-!x] == -[x]; morph_eq : forall x y, x?=!y = true -> [x] == [y] }. Record semi_morph : Prop := mkRmorph { Smorph0 : [cO] == 0; Smorph1 : [cI] == 1; Smorph_add : forall x y, [x +! y] == [x]+[y]; Smorph_mul : forall x y, [x *! y] == [x]*[y]; Smorph_eq : forall x y, x?=!y = true -> [x] == [y] }. where ``c0`` and ``cI`` denote the 0 and 1 of the coefficient set, ``+!``, ``*!``, ``-!`` are the implementations of the ring operations, ``==`` is the equality of the coefficients, ``?+!`` is an implementation of this equality, and ``[x]`` is a notation for the image of ``x`` by the ring morphism. Since |Z| is an initial ring (and |N| is an initial semiring), it can always be considered as a set of coefficients. There are basically three kinds of (semi-)rings: abstract rings to be used when operations are not effective. The set of coefficients is |Z| (or |N| for semirings). computational rings to be used when operations are effective. The set of coefficients is the ring itself. The user only has to provide an implementation for the equality. customized ring for other cases. The user has to provide the coefficient set and the morphism. This implementation of ring can also recognize simple power expressions as ring expressions. A power function is specified by the following property: .. rocqtop:: in extra-stdlib From Stdlib Require Import Reals. Section POWER. Variable Cpow : Set. Variable Cp_phi : N -> Cpow. Variable rpow : R -> Cpow -> R. Record power_theory : Prop := mkpow_th { rpow_pow_N : forall r n, rpow r (Cp_phi n) = pow_N 1%R Rmult r n }. End POWER. The syntax for adding a new ring is .. cmd:: Add Ring @ident : @one_term {? ( {+, @ring_mod } ) } .. insertprodn ring_mod ring_mod .. prodn:: ring_mod ::= decidable @one_term | abstract | morphism @one_term | constants [ @ltac_expr ] | preprocess [ @ltac_expr ] | postprocess [ @ltac_expr ] | setoid @one_term @one_term | sign @one_term | power @one_term [ {+ @qualid } ] | power_tac @one_term [ @ltac_expr ] | div @one_term | closed [ {+ @qualid } ] The :n:`@ident` is used only for error messages. The :n:`@one_term` is a proof that the ring signature satisfies the (semi-)ring axioms. The optional list of modifiers is used to tailor the behavior of the tactic. Here are their effects: :n:`abstract` declares the ring as abstract. This is the default. :n:`decidable @one_term` declares the ring as computational. The expression :n:`@one_term` is the correctness proof of an equality test ``?=!`` (which should be evaluable). Its type should be of the form ``forall x y, x ?=! y = true β†’ x == y``. :n:`morphism @one_term` declares the ring as a customized one. The expression :n:`@one_term` is a proof that there exists a morphism between a set of coefficient and the ring carrier (see ``Ring_theory.ring_morph`` and ``Ring_theory.semi_morph``). :n:`setoid @one_term @one_term` forces the use of given setoid. The first :n:`@one_term` is a proof that the equality is indeed a setoid (see ``Setoid.Setoid_Theory``), and the second a proof that the ring operations are morphisms (see ``Ring_theory.ring_eq_ext`` and ``Ring_theory.sring_eq_ext``). This modifier needs not be used if the setoid and morphisms have been declared. :n:`constants [ @ltac_expr ]` specifies a tactic expression :n:`@ltac_expr` that, given a term, returns either an object of the coefficient set that is mapped to the expression via the morphism, or returns ``InitialRing.NotConstant``. The default behavior is to map only 0 and 1 to their counterpart in the coefficient set. This is generally not desirable for nontrivial computational rings. :n:`preprocess [ @ltac_expr ]` specifies a tactic :n:`@ltac_expr` that is applied as a preliminary step for :tacn:`ring` and :tacn:`ring_simplify`. It can be used to transform a goal so that it is better recognized. For instance, ``S n`` can be changed to ``plus 1 n``. For :tacn:`ring_simplify`, the terms given as arguments are also modified by this tactic. :n:`postprocess [ @ltac_expr ]` specifies a tactic :n:`@ltac_expr` that is applied as a final step for :tacn:`ring_simplify`. For instance, it can be used to undo modifications of the preprocessor. :n:`power @one_term [ {+ @qualid } ]` to be documented :n:`power_tac @one_term @ltac_expr ]` allows :tacn:`ring` and :tacn:`ring_simplify` to recognize power expressions with a constant positive integer exponent (example: :math:`x^2` ). The term :n:`@one_term` is a proof that a given power function satisfies the specification of a power function (term has to be a proof of ``Ring_theory.power_theory``) and :n:`@tactic` specifies a tactic expression that, given a term, β€œabstracts” it into an object of type |N| whose interpretation via ``Cp_phi`` (the evaluation function of power coefficient) is the original term, or returns ``InitialRing.NotConstant`` if not a constant coefficient (i.e. |Ltac| is the inverse function of ``Cp_phi``). See files ``plugins/ring/ZArithRing.v`` and ``plugins/ring/RealField.v`` for examples. By default the tactic does not recognize power expressions as ring expressions. :n:`sign @one_term` allows :tacn:`ring_simplify` to use a minus operation when outputting its normal form, i.e writing ``x βˆ’ y`` instead of ``x + (βˆ’ y)``. The term :token:`term` is a proof that a given sign function indicates expressions that are signed (:token:`term` has to be a proof of ``Ring_theory.get_sign``). See ``plugins/ring/InitialRing.v`` for examples of sign function. :n:`div @one_term` allows :tacn:`ring` and :tacn:`ring_simplify` to use monomials with coefficients other than 1 in the rewriting. The term :n:`@one_term` is a proof that a given division function satisfies the specification of an euclidean division function (:n:`@one_term` has to be a proof of ``Ring_theory.div_theory``). For example, this function is called when trying to rewrite :math:`7x` by :math:`2x = z` to tell that :math:`7 = 3 \times 2 + 1`. See ``plugins/ring/InitialRing.v`` for examples of div function. :n:`closed [ {+ @qualid } ]` to be documented Error messages: .. exn:: Bad ring structure. The proof of the ring structure provided is not of the expected type. .. exn:: Bad lemma for decidability of equality. The equality function provided in the case of a computational ring has not the expected type. .. exn:: Ring operation should be declared as a morphism. A setoid associated with the carrier of the ring structure has been found, but the ring operation should be declared as morphism. See :ref:`tactics-enabled-on-user-provided-relations`. How does it work? ---------------------- The code of ``ring`` is a good example of a tactic written using *reflection*. What is reflection? Basically, using it means that a part of a tactic is written in Gallina, Rocq's language of terms, rather than |Ltac| or OCaml. From the philosophical point of view, reflection is using the ability of the Calculus of Constructions to speak and reason about itself. For the ``ring`` tactic we used Rocq as a programming language and also as a proof environment to build a tactic and to prove its correctness. The interested reader is strongly advised to have a look at the file ``Ring_polynom.v``. Here a type for polynomials is defined: .. rocqdoc:: Inductive PExpr : Type := | PEc : C -> PExpr | PEX : positive -> PExpr | PEadd : PExpr -> PExpr -> PExpr | PEsub : PExpr -> PExpr -> PExpr | PEmul : PExpr -> PExpr -> PExpr | PEopp : PExpr -> PExpr | PEpow : PExpr -> N -> PExpr. Polynomials in normal form are defined as: .. rocqdoc:: Inductive Pol : Type := | Pc : C -> Pol | Pinj : positive -> Pol -> Pol | PX : Pol -> positive -> Pol -> Pol. where ``Pinj n P`` denotes ``P`` in which :math:`V_i` is replaced by :math:`V_{i+n}` , and ``PX P n Q`` denotes :math:`P \otimes V_1^n \oplus Q'`, `Q'` being `Q` where :math:`V_i` is replaced by :math:`V_{i+1}`. Variable maps are represented by lists of ring elements, and two interpretation functions, one that maps a variables map and a polynomial to an element of the concrete ring, and the second one that does the same for normal forms: .. rocqdoc:: Definition PEeval : list R -> PExpr -> R := [...]. Definition Pphi_dev : list R -> Pol -> R := [...]. A function to normalize polynomials is defined, and the big theorem is its correctness w.r.t interpretation, that is: .. rocqdoc:: Definition norm : PExpr -> Pol := [...]. Lemma Pphi_dev_ok : forall l pe npe, norm pe = npe -> PEeval l pe == Pphi_dev l npe. So now, what is the scheme for a normalization proof? Let p be the polynomial expression that the user wants to normalize. First a little piece of ML code guesses the type of `p`, the ring theory `T` to use, an abstract polynomial `ap` and a variables map `v` such that `p` is |bdi|- equivalent to `(PEeval v ap)`. Then we replace it by `(Pphi_dev v (norm ap))`, using the main correctness theorem and we reduce it to a concrete expression `p’`, which is the concrete normal form of `p`. This is summarized in this diagram: ========= ====== ==== `p` |ra| |re| \ |eq| \ `p’` |la| |le| ========= ====== ==== The user does not see the right part of the diagram. From outside, the tactic behaves like a |bdi| simplification extended with rewriting rules for associativity and commutativity. Basically, the proof is only the application of the main correctness theorem to well-chosen arguments. Dealing with fields ------------------------ .. tacn:: field {? [ {+ @one_term } ] } An extension of the :tacn:`ring` tactic that deals with rational expressions. Given a rational expression :math:`F = 0`. It first reduces the expression `F` to a common denominator :math:`N/D = 0` where `N` and `D` are two ring expressions. For example, if we take :math:`F = (1 βˆ’ 1/x) x βˆ’ x + 1`, this gives :math:`N = (x βˆ’ 1) x βˆ’ x^2 + x` and :math:`D = x`. It then calls ring to solve :math:`N = 0`. :n:`[ {+ @one_term } ]` If specified, the tactic decides the equality of two terms modulo field operations and the equalities defined by the :token:`one_term`\s. Each :token:`one_term` has to be a proof of some equality :g:`m = p`, where :g:`m` is a monomial (after β€œabstraction”), :g:`p` a polynomial and :g:`=` the corresponding equality of the field structure. .. note:: Rewriting works with the equality :g:`m = p` only if :g:`p` is a polynomial since rewriting is handled by the underlying ring tactic. Note that :n:`field` also generates nonzero conditions for all the denominators it encounters in the reduction. In our example, it generates the condition :math:`x \neq 0`. These conditions appear as one subgoal which is a conjunction if there are several denominators. Nonzero conditions are always polynomial expressions. For example when reducing the expression :math:`1/(1 + 1/x)`, two side conditions are generated: :math:`x \neq 0` and :math:`x + 1 \neq 0`. Factorized expressions are broken since a field is an integral domain, and when the equality test on coefficients is complete w.r.t. the equality of the target field, constants can be proven different from zero automatically. The tactic must be loaded by ``Require Import Field``. New field structures can be declared to the system with the ``Add Field`` command (see below). The field of real numbers is defined in module ``RealField`` (in ``plugins/ring``). It is exported by module ``Rbase``, so that requiring ``Rbase`` or ``Reals`` is enough to use the field tactics on real numbers. Rational numbers in canonical form are also declared as a field in the module ``Qcanon``. .. example:: .. rocqtop:: all extra-stdlib From Stdlib Require Import Reals. Open Scope R_scope. Goal forall x, x <> 0 -> (1 - 1 / x) * x - x + 1 = 0. intros; field; auto. Abort. Goal forall x y, y <> 0 -> y = x -> x / y = 1. intros x y H H1; field [H1]; auto. Abort. .. example:: :tacn:`field` that generates side goals .. rocqtop:: reset all extra-stdlib From Stdlib Require Import Reals. Goal forall x y:R, (x * y > 0)%R -> (x * (1 / x + x / (x + y)))%R = ((- 1 / y) * y * (- x * (x / (x + y)) - 1))%R. intros; field. .. tacn:: field_simplify {? [ {+ @one_term__eq } ] } {+ @one_term } {? in @ident } Performs the simplification in the conclusion of the goal, :math:`F_1 = F_2` becomes :math:`N_1 / D_1 = N_2 / D_2`. A normalization step (the same as the one for rings) is then applied to :math:`N_1`, :math:`D_1`, :math:`N_2` and :math:`D_2`. This way, polynomials remain in factorized form during fraction simplification. This yields smaller expressions when reducing to the same denominator since common factors can be canceled. :n:`[ {+ @one_term__eq } ]` Do simplification in the conclusion of the goal using the equalities defined by these :token:`one_term`\s. :n:`{+ @one_term }` Terms to simplify in the conclusion. :n:`in @ident` If specified, substitute in the hypothesis :n:`@ident` instead of the conclusion. .. tacn:: field_simplify_eq {? [ {+ @one_term } ] } {? in @ident } Performs the simplification in the conclusion of the goal, removing the denominator. :math:`F_1 = F_2` becomes :math:`N_1 D_2 = N_2 D_1`. :n:`[ {+ @one_term } ]` Do simplification in the conclusion of the goal using the equalities defined by these :token:`one_term`\s. :n:`in @ident` If specified, simplify in the hypothesis :n:`@ident` instead of the conclusion. .. tacn:: field_lookup @ltac_expr [ {* @one_term } ] {+ @one_term } For internal use only. Adding a new field structure --------------------------------- Declaring a new field consists in proving that a field signature (a carrier set, an equality, and field operations: ``Field_theory.field_theory`` and ``Field_theory.semi_field_theory``) satisfies the field axioms. Semi-fields (fields without + inverse) are also supported. The equality can be either Leibniz equality, or any relation declared as a setoid (see :ref:`tactics-enabled-on-user-provided-relations`). The definition of fields and semifields is: .. rocqdoc:: Record field_theory : Prop := mk_field { F_R : ring_theory rO rI radd rmul rsub ropp req; F_1_neq_0 : ~ 1 == 0; Fdiv_def : forall p q, p / q == p * / q; Finv_l : forall p, ~ p == 0 -> / p * p == 1 }. Record semi_field_theory : Prop := mk_sfield { SF_SR : semi_ring_theory rO rI radd rmul req; SF_1_neq_0 : ~ 1 == 0; SFdiv_def : forall p q, p / q == p * / q; SFinv_l : forall p, ~ p == 0 -> / p * p == 1 }. The result of the normalization process is a fraction represented by the following type: .. rocqdoc:: Record linear : Type := mk_linear { num : PExpr C; denum : PExpr C; condition : list (PExpr C) }. where ``num`` and ``denum`` are the numerator and denominator; ``condition`` is a list of expressions that have appeared as a denominator during the normalization process. These expressions must be proven different from zero for the correctness of the algorithm. The syntax for adding a new field is .. cmd:: Add Field @ident : @one_term {? ( {+, @field_mod } ) } .. insertprodn field_mod field_mod .. prodn:: field_mod ::= @ring_mod | completeness @one_term The :n:`@ident` is used only for error messages. :n:`@one_term` is a proof that the field signature satisfies the (semi-)field axioms. The optional list of modifiers is used to tailor the behavior of the tactic. Since field tactics are built upon ``ring`` tactics, all modifiers of :cmd:`Add Ring` apply. There is only one specific modifier: completeness :n:`@one_term` allows the field tactic to prove automatically that the image of nonzero coefficients are mapped to nonzero elements of the field. :n:`@one_term` is a proof of :g:`forall x y, [x] == [y] -> x ?=! y = true`, which is the completeness of equality on coefficients w.r.t. the field equality. When :cmd:`Add Field` is called, a call to :cmd:`Add Ring` is performed with all modifiers of the form :n:`@ring_mod`. As a result, any previous ring declaration for the type is replaced by the one that uses the same modifiers as the :cmd:`Add Field` command. In the case where it is desired to have different modifiers for the field and the ring structure, a new call to :cmd:`Add Ring` can be performed after this command, to set different values of certain modifiers. .. cmd:: Print Fields :undocumented: History of ring -------------------- First Samuel Boutin designed the tactic ``ACDSimpl``. This tactic did lot of rewriting. But the proofs terms generated by rewriting were too big for Coq’s type checker. Let us see why: .. rocqtop:: reset all extra-stdlib From Stdlib Require Import ZArith. Open Scope Z_scope. Goal forall x y z : Z, x + 3 + y + y * z = x + 3 + y + z * y. intros; rewrite (Zmult_comm y z); reflexivity. Save foo. Print foo. At each step of rewriting, the whole context is duplicated in the proof term. Then, a tactic that does hundreds of rewriting generates huge proof terms. Since ``ACDSimpl`` was too slow, Samuel Boutin rewrote it using reflection (see :cite:`Bou97`). Later, it was rewritten by Patrick Loiseleur: the new tactic does not any more require ``ACDSimpl`` to compile and it makes use of |bdi|-reduction not only to replace the rewriting steps, but also to achieve the interleaving of computation and reasoning (see :ref:`discussion_reflection`). He also wrote some ML code for the ``Add Ring`` command that allows registering new rings dynamically. Proofs terms generated by ring are quite small, they are linear in the number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type checking those terms requires some time because it makes a large use of the conversion rule, but memory requirements are much smaller. .. _discussion_reflection: Discussion ---------------- Efficiency is not the only motivation to use reflection here. ``ring`` also deals with constants, it rewrites for example the expression ``34 + 2 * x βˆ’ x + 12`` to the expected result ``x + 46``. For the tactic ``ACDSimpl``, the only constants were 0 and 1. So the expression ``34 + 2 * (x βˆ’ 1) + 12`` is interpreted as :math:`V_0 \oplus V_1 \otimes (V_2 \ominus 1) \oplus V_3`\ , with the variables mapping :math:`\{V_0 \mapsto 34; V_1 \mapsto 2; V_2 \mapsto x; V_3 \mapsto 12\}`\ . Then it is rewritten to ``34 βˆ’ x + 2 * x + 12``, very far from the expected result. Here rewriting is not sufficient: you have to do some kind of reduction (some kind of computation) to achieve the normalization. The tactic ``ring`` is not only faster than the old one: by using reflection, we get for free the integration of computation and reasoning that would be very difficult to implement without it. Is it the ultimate way to write tactics? The answer is: yes and no. The ``ring`` tactic intensively uses the conversion rules of the Calculus of Inductive Constructions, i.e. it replaces proofs by computations as much as possible. It can be useful in all situations where a classical tactic generates huge proof terms, like symbolic processing and tautologies. But there are also tactics like ``auto`` or ``linear`` that do many complex computations, using side-effects and backtracking, and generate a small proof term. Clearly, it would be significantly less efficient to replace them by tactics using reflection. Another idea suggested by Benjamin Werner: reflection could be used to couple an external tool (a rewriting program or a model checker) with Rocq. We define (in Rocq) a type of terms, a type of *traces*, and prove a correctness theorem that states that *replaying traces* is safe with respect to some interpretation. Then we let the external tool do every computation (using side-effects, backtracking, exception, or others features that are not available in pure lambda calculus) to produce the trace. Now we can check in Rocq that the trace has the expected semantics by applying the correctness theorem. .. rubric:: Footnotes .. [#f1] based on previous work from Patrick Loiseleur and Samuel Boutin rocq-9.2.0/doc/sphinx/addendum/sprop.rst000066400000000000000000000206511516144147600202370ustar00rootroot00000000000000.. _sprop: SProp (proof irrelevant propositions) ===================================== .. warning:: The status of strict propositions is experimental. In particular, conversion checking through bytecode or native code compilation currently does not understand proof irrelevance. This section describes the extension of Rocq with definitionally proof irrelevant propositions (types in the sort :math:`\SProp`, also known as strict propositions) as described in :cite:`Gilbert:POPL2019`. Use of |SProp| may be disabled by passing ``-disallow-sprop`` to the Rocq program or by turning the :flag:`Allow StrictProp` flag off. .. flag:: Allow StrictProp This :term:`flag` enables or disables the use of |SProp|. It is enabled by default. The command-line flag ``-disallow-sprop`` disables |SProp| at startup. .. exn:: SProp is disallowed because the "Allow StrictProp" flag is off. :undocumented: Some of the definitions described in this document are available through ``Stdlib.Logic.StrictProp``. Basic constructs ---------------- The purpose of :math:`\SProp` is to provide types where all elements are convertible: .. rocqtop:: all Theorem irrelevance (A : SProp) (P : A -> Prop) : forall x : A, P x -> forall y : A, P y. Proof. intros * Hx *. exact Hx. Qed. Since we have definitional :ref:`eta-expansion-sect` for functions, the property of being a type of definitionally irrelevant values is impredicative, and so is :math:`\SProp`: .. rocqtop:: all Check fun (A:Type) (B:A -> SProp) => (forall x:A, B x) : SProp. In order to keep conversion tractable, cumulativity for :math:`\SProp` is forbidden. .. rocqtop:: all Fail Check (fun (A:SProp) => A : Type). We can explicitly lift strict propositions into the relevant world by using a wrapping inductive type. The inductive stops definitional proof irrelevance from escaping. .. rocqtop:: in Inductive Box (A:SProp) : Prop := box : A -> Box A. Arguments box {_} _. .. rocqtop:: all Fail Check fun (A:SProp) (x y : Box A) => eq_refl : x = y. .. doesn't get merged with the above if coqdoc .. rocqtop:: in Definition box_irrelevant (A:SProp) (x y : Box A) : x = y := match x, y with box x, box y => eq_refl end. In the other direction, we can use impredicativity to "squash" a relevant type, making an irrelevant approximation. .. rocqdoc:: Definition iSquash (A:Type) : SProp := forall P : SProp, (A -> P) -> P. Definition isquash A : A -> iSquash A := fun a P f => f a. Definition iSquash_sind A (P : iSquash A -> SProp) (H : forall x : A, P (isquash A x)) : forall x : iSquash A, P x := fun x => x (P x) (H : A -> P x). Or more conveniently (but equivalently) .. rocqdoc:: Inductive Squash (A:Type) : SProp := squash : A -> Squash A. Most inductives types defined in :math:`\SProp` are squashed types, i.e. they can only be eliminated to construct proofs of other strict propositions. Empty types are the only exception. .. rocqtop:: in Inductive sEmpty : SProp := . .. rocqtop:: all Check sEmpty_rect. .. note:: Eliminators to strict propositions are called ``foo_sind``, in the same way that eliminators to propositions are called ``foo_ind``. Primitive records in :math:`\SProp` are allowed when fields are strict propositions, for instance: .. rocqtop:: in Set Primitive Projections. Record sProd (A B : SProp) : SProp := { sfst : A; ssnd : B }. Primitive records in relevant sorts with fields that are only strict propositions are allowed but do not have Ξ·-conversion. This is in order to avoid having definitionally irrelevant types in non-:math:`\SProp` sorts (through record Ξ·-extensionality). .. rocqtop:: all Record rBox (A : SProp) : Prop := rbox { runbox : A }. Goal forall (A : SProp) (r : rBox A), r = {| runbox := r.(runbox A) |}. Proof. intros A r. Fail reflexivity. Abort. In contrast, primitive records in relevant sorts with at least one relevant field are allowed and have Ξ·-conversion. .. rocqdoc:: Record ssig (A : Type) (P : A -> SProp) : Type := { spr1 : A; spr2 : P spr1 }. Goal forall (A : Type) (P : A -> SProp) (s : ssig A P), s = {| spr1 := s.(spr1 A P); spr2 := s.(spr2 A P) |}. Proof. intros A P s. reflexivity. Qed. Encodings for strict propositions --------------------------------- The elimination for unit types can be encoded by a trivial function thanks to proof irrelevance: .. rocqdoc:: Inductive sUnit : SProp := stt. Definition sUnit_rect (P:sUnit->Type) (v:P stt) (x:sUnit) : P x := v. By using empty and unit types as base values, we can encode other strict propositions. For instance: .. rocqdoc:: Definition is_true (b:bool) : SProp := if b then sUnit else sEmpty. Definition is_true_eq_true b : is_true b -> true = b := match b with | true => fun _ => eq_refl | false => sEmpty_ind _ end. Definition eq_true_is_true b (H:true=b) : is_true b := match H in _ = x return is_true x with eq_refl => stt end. Definitional UIP ---------------- .. flag:: Definitional UIP This :term:`flag`, off by default, allows the declaration of non-squashed inductive types in |SProp| with 1 constructor which takes no non-parameter arguments. Since this includes equality types, it provides definitional uniqueness of identity proofs. Because squashing is a universe restriction, unsetting :flag:`Universe Checking` is stronger than setting :flag:`Definitional UIP`. Definitional UIP involves a special reduction rule through which reduction depends on conversion. Consider the following code: .. rocqtop:: in Set Definitional UIP. Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. Axiom e : seq 0 0. Definition hidden_arrow := match e return Set with srefl _ => nat -> nat end. Check (fun (f : hidden_arrow) (x:nat) => (f : nat -> nat) x). By the usual reduction rules :g:`hidden_arrow` is a stuck match, but by proof irrelevance :g:`e` is convertible to :g:`srefl 0` and then by congruence :g:`hidden_arrow` is convertible to `nat -> nat`. The special reduction reduces any match on a type which uses definitional UIP when the indices are convertible to those of the constructor. For `seq`, this means a match on a value of type `seq x y` reduces if and only if `x` and `y` are convertible. Such matches are indicated in the printed representation by inserting a cast around the discriminee: .. rocqtop:: out Print hidden_arrow. Non Termination with UIP ++++++++++++++++++++++++ The special reduction rule of UIP combined with an impredicative sort breaks termination of reduction :cite:`abel19:failur_normal_impred_type_theor`: .. rocqtop:: all Axiom all_eq : forall (P Q:Prop), P -> Q -> seq P Q. Definition transport (P Q:Prop) (x:P) (y:Q) : Q := match all_eq P Q x y with srefl _ => x end. Definition top : Prop := forall P : Prop, P -> P. Definition c : top := fun P p => transport (top -> top) P (fun x : top => x (top -> top) (fun x => x) x) p. Fail Timeout 1 Eval lazy in c (top -> top) (fun x => x) c. The term :g:`c (top -> top) (fun x => x) c` infinitely reduces to itself. Debugging |SProp| issues ------------------------ Every binder in a term (such as `fun x` or `forall x`) caches information called the :gdef:`relevance mark` indicating whether its type is in |SProp| or not. This is used to efficiently implement proof irrelevance. The user should usually not be concerned with relevance marks, so by default they are not displayed. However code outside the kernel may generate incorrect marks resulting in bugs. Typically this means a conversion will incorrectly fail as a variable was incorrectly marked proof relevant. .. warn:: Bad relevance This is a developer warning, which is treated as an error by default. It is emitted by the kernel when it is passed a term with incorrect relevance marks. This is always caused by a bug in Rocq (or a plugin), which should thus be reported and fixed. In order to allow the user to work around such bugs, we leave the ability to unset the ``bad-relevance`` warning for the time being, so that the kernel will silently repair the proof term instead of failing. .. flag:: Printing Relevance Marks This :term:`flag` enables debug printing of relevance marks. It is off by default. Note that :flag:`Printing All` does not affect printing of relevance marks. .. rocqtop:: all Set Printing Relevance Marks. Check fun x : nat => x. Check fun (P:SProp) (p:P) => p. rocq-9.2.0/doc/sphinx/addendum/type-classes.rst000066400000000000000000000642761516144147600215230ustar00rootroot00000000000000.. _typeclasses: Typeclasses =========== Typeclasses are types whose values Rocq can automatically infer by using user declared instances. It allows for a form of programmatic proof or term search. This chapter presents a quick reference of the commands related to typeclasses. Additional helpful information can be found in the paper introducing typeclasses to Coq :cite:`sozeau08` and the literature on type classes in Haskell. Typeclass and instance declarations ----------------------------------- The syntax for typeclasses and instance declarations is the same as the record syntax: .. rocqdoc:: Class classname (p1 : t1) β‹― (pn : tn) [: sort] := { f1 : u1 ; β‹― ; fm : um }. Instance instancename q1 β‹― qm : classname p1 β‹― pn := { f1 := e1 ; β‹― ; fm := em }. The ``pi : ti`` variables are called the *parameters* of the typeclass and the ``fi : ui`` are called the *methods*. Each typeclass definition gives rise to a corresponding record declaration and each instance is a regular definition whose name is given by `instancename` and type is an instantiation of the record type. We’ll use the following example typeclass in the rest of the chapter: .. rocqtop:: in Class EqDec (A : Type) := { eqb : A -> A -> bool ; eqb_leibniz : forall x y, eqb x y = true -> x = y }. This typeclass implements a boolean equality test which is compatible with Leibniz equality on some type. An example implementation is: .. rocqtop:: in Instance unit_EqDec : EqDec unit := { eqb x y := true ; eqb_leibniz x y H := match x, y return x = y with | tt, tt => eq_refl tt end }. Using the :attr:`refine` attribute, if the term is not sufficient to finish the definition (e.g. due to a missing field or non-inferable hole) it must be finished in proof mode. If it is sufficient a trivial proof mode with no open goals is started. .. rocqtop:: in #[refine] Instance unit_EqDec' : EqDec unit := { eqb x y := true }. Proof. intros [] [];reflexivity. Defined. Note that if you finish the proof with :cmd:`Qed` the entire instance will be opaque, including the fields given in the initial term. Alternatively, in :flag:`Program Mode` if one does not give all the members in the Instance declaration, Rocq generates obligations for the remaining fields, e.g.: .. rocqtop:: in Require Import Program.Tactics. Program Instance eq_bool : EqDec bool := { eqb x y := if x then y else negb y }. .. rocqtop:: all Next Obligation. destruct x ; destruct y ; (discriminate || reflexivity). Defined. One has to take care that the transparency of every field is determined by the transparency of the :cmd:`Instance` proof. One can use alternatively the :attr:`program` attribute to get richer facilities for dealing with obligations. Binding typeclasses ------------------- Once a typeclass is declared, one can use it in typeclass binders: .. rocqtop:: all Definition neqb {A} {eqa : EqDec A} (x y : A) := negb (eqb x y). When one calls a typeclass method, a constraint is generated that is satisfied only in contexts where the appropriate instances can be found. In the example above, a constraint ``EqDec A`` is generated and satisfied by ``eqa : EqDec A``. In case no satisfying constraint can be found, an error is raised: .. rocqtop:: all Fail Definition neqb' (A : Type) (x y : A) := negb (eqb x y). The algorithm used to solve constraints is a variant of the :tacn:`eauto` tactic that does proof search with a set of lemmas (the instances). It will use local hypotheses as well as declared lemmas in the ``typeclass_instances`` database. Hence the example can also be written: .. rocqtop:: all Definition neqb' A (eqa : EqDec A) (x y : A) := negb (eqb x y). However, the generalizing binders should be used instead as they have particular support for typeclasses: + They automatically set the maximally implicit status for typeclass arguments, making derived functions as easy to use as typeclass methods. In the example above, ``A`` and ``eqa`` should be set maximally implicit. + They support implicit quantification on partially applied typeclasses (:ref:`implicit-generalization`). Any argument not given as part of a typeclass binder will be automatically generalized. + They also support implicit quantification on :ref:`superclasses`. Following the previous example, one can write: .. rocqtop:: all Generalizable Variables A B C. Definition neqb_implicit `{eqa : EqDec A} (x y : A) := negb (eqb x y). Here ``A`` is implicitly generalized, and the resulting function is equivalent to the one above. Parameterized instances ----------------------- One can declare parameterized instances as in Haskell simply by giving the constraints as a binding context before the instance, e.g.: .. rocqtop:: in Program Instance prod_eqb `(EA : EqDec A, EB : EqDec B) : EqDec (A * B) := { eqb x y := match x, y with | (la, lb), (ra, rb) => andb (eqb la ra) (eqb lb rb) end }. .. rocqtop:: none Admit Obligations. These instances are used just as well as lemmas in the instance hint database. .. _contexts: Sections and contexts --------------------- To ease developments parameterized by many instances, one can use the :cmd:`Context` command to introduce the parameters into the :term:`local context`, which works similarly to the command :cmd:`Variable`, except it accepts any binding context as an argument, so variables can be implicit, and :ref:`implicit-generalization` can be used. For example: .. rocqtop:: all Section EqDec_defs. Context `{EA : EqDec A}. .. rocqtop:: in #[ global, program ] Instance option_eqb : EqDec (option A) := { eqb x y := match x, y with | Some x, Some y => eqb x y | None, None => true | _, _ => false end }. Admit Obligations. .. rocqtop:: all End EqDec_defs. About option_eqb. Here the :attr:`global` attribute redeclares the instance at the end of the section, once it has been generalized by the context variables it uses. .. seealso:: Section :ref:`section-mechanism` Building hierarchies -------------------- .. _superclasses: Superclasses ~~~~~~~~~~~~ One can also parameterize typeclasses by other typeclasses, generating a hierarchy of typeclasses and superclasses. In the same way, we give the superclasses as a binding context: .. rocqtop:: all Class Ord `(E : EqDec A) := { le : A -> A -> bool }. Contrary to Haskell, we have no special syntax for superclasses, but this declaration is equivalent to: .. rocqdoc:: Class `(E : EqDec A) => Ord A := { le : A -> A -> bool }. This declaration means that any instance of the ``Ord`` typeclass must have an instance of ``EqDec``. The parameters of the subclass contain at least all the parameters of its superclasses in their order of appearance (here A is the only one). As we have seen, ``Ord`` is encoded as a record type with two parameters: a type ``A`` and an ``E`` of type ``EqDec A``. However, one can still use it as if it had a single parameter inside generalizing binders: the generalization of superclasses will be done automatically. .. rocqtop:: all Definition le_eqb `{Ord A} (x y : A) := andb (le x y) (le y x). To specify sharing of structures, you may want to explicitly specify the superclasses. You can do this directly in regular binders, and with the ``!`` modifier before typeclass binders. For example: .. rocqtop:: all Definition lt `{eqa : EqDec A, !Ord eqa} (x y : A) := andb (le x y) (neqb x y). The ``!`` modifier switches how Rocq interprets a binder. In particular, it uses the implicit arguments mechanism if available, as shown in the example. Substructures ~~~~~~~~~~~~~ .. index:: :: (substructure) Substructures are components of a typeclass which are themselves instances of a typeclass. They often arise when using typeclasses for logical properties, e.g.: .. rocqtop:: none Require Import Relation_Definitions. .. rocqtop:: in Class Reflexive (A : Type) (R : relation A) := reflexivity : forall x, R x x. Class Transitive (A : Type) (R : relation A) := transitivity : forall x y z, R x y -> R y z -> R x z. This declares singleton typeclasses for reflexive and transitive relations, (see the :ref:`singleton class ` variant for an explanation). These may be used as parts of other typeclasses: .. rocqtop:: all Class PreOrder (A : Type) (R : relation A) := { PreOrder_Reflexive :: Reflexive A R ; PreOrder_Transitive :: Transitive A R }. The syntax ``::`` indicates that each ``PreOrder`` can be seen as a ``Reflexive`` relation. So each time a reflexive relation is needed, a preorder can be used instead. This is very similar to the coercion mechanism of ``Structure`` declarations. The implementation simply declares each projection as an instance. One can also declare existing objects or structure projections using the :cmd:`Existing Instance` command to achieve the same effect. Command summary --------------- .. cmd:: Class @record_definition Class @ident_decl {* @binder } {? : @sort } := @constructor The first form declares a record and makes the record a typeclass with parameters :n:`{* @binder }` and the listed record fields. .. _singleton-class: The second form declares a *singleton* typeclass with a single projection. This singleton typeclass is a so-called *definitional typeclass*, represented simply as a definition ``ident binders := term`` and whose instances are themselves objects of this type. Definitional typeclasses are not wrapped inside records, and the trivial projection of an instance of such a typeclass is convertible to the instance itself. This can be useful to make instances of existing objects easily and to reduce proof size by not inserting useless trivial projections. The typeclass :term:`constant` itself is declared rigid during resolution so that the typeclass abstraction is maintained. Like any command declaring a record, this command supports the :attr:`universes(polymorphic)`, :attr:`universes(template)`, :attr:`universes(cumulative)` and :attr:`private(matching)` attributes. It also supports the :attr:`mode` attribute for setting a hint mode declaration for the class. .. note:: Don't confuse typeclasses with "coercion classes", described in :ref:`implicit coercions`. When record syntax is used, this command also supports the :attr:`projections(primitive)` :term:`attribute`. .. attr:: mode = @string :name: mode Sets the mode of resolution for queries on the class. The syntax to use in the quoted string is explained in :cmd:`Hint Mode`. .. cmd:: Existing Class @qualid Declares a typeclass from a previously declared :term:`constant` or inductive definition. No methods or instances are defined. .. warn:: @ident is already declared as a typeclass This command has no effect when used on a typeclass. .. warn:: Ignored instance declaration for β€œ@ident”: β€œ@term” is not a class Using the ``::`` syntax in the :n:`@record_definition` or :n:`@constructor` with a right-hand-side that is not itself a Class has no effect (apart from emitting this warning). .. cmd:: Instance {? @ident_decl {* @binder } } : @type {? @hint_info } {? {| := %{ {* @field_val } %} | := @term } } Declares a typeclass instance named :token:`ident_decl` of the typeclass :n:`@type` with the specified parameters and with fields defined by :token:`field_val`, where each field must be a declared field of the typeclass. Adds one or more :token:`binder`\s to declare a parameterized instance. :token:`hint_info` may be used to specify the hint priority. If the priority is not specified, the default is the number of non-dependent binders of the instance. If :token:`one_pattern` is given, terms matching that pattern will trigger use of the instance. Otherwise, use is triggered based on the conclusion of the type. This command supports the :attr:`local`, :attr:`global` and :attr:`export` locality attributes. .. versionchanged:: 8.18 The default value for instance locality outside sections is now :attr:`export`. It used to be :attr:`global`. Like :cmd:`Definition`, it also supports the :attr:`program` attribute to switch the type checking to `Program` (chapter :ref:`programs`) and to use the obligation mechanism to manage missing fields. Finally, it supports the lighter :attr:`refine` attribute: .. attr:: refine This :term:`attribute` can be used to leave holes or not provide all fields in the definition of an instance and open the tactic mode to fill them. It works exactly as if no :term:`body` had been given and the :tacn:`refine` tactic has been used first. .. cmd:: Declare Instance @ident_decl {* @binder } : @term {? @hint_info } In a :cmd:`Module Type`, declares that a corresponding concrete instance should exist in any implementation of this :cmd:`Module Type`. This is similar to the distinction between :cmd:`Parameter` vs. :cmd:`Definition`, or between :cmd:`Declare Module` and :cmd:`Module`. .. cmd:: Existing Instance @qualid {? @hint_info } Existing Instances {+ @qualid } {? %| @natural } Adds a :term:`constant` whose type ends with an applied typeclass to the instance database with an optional priority :token:`natural`. It can be used for redeclaring instances at the end of sections, or declaring structure projections as instances. This is equivalent to ``Hint Resolve ident : typeclass_instances``, except it registers instances for :cmd:`Print Instances`. .. cmd:: Print Instances @reference Shows the list of instances associated with the typeclass :token:`reference`. .. cmd:: Print Typeclasses Shows the list of declared typeclasses. .. tacn:: typeclasses eauto {? {| bfs | dfs | best_effort } } {? @nat_or_var } {? with {+ @ident } } This proof search tactic uses the resolution engine that is run implicitly during type checking, known as *typeclass search*. This tactic uses a different resolution engine than :tacn:`eauto` and :tacn:`auto`. The main differences are the following: + Unlike :tacn:`eauto` and :tacn:`auto`, the resolution is done entirely in the proof engine, meaning that backtracking is available among dependent subgoals, and shelving goals is supported. ``typeclasses eauto`` is a multi-goal tactic. It analyses the dependencies between subgoals to avoid backtracking on subgoals that are entirely independent. + The transparency information of databases is used consistently for all hints declared in them. It is always used when calling the unifier. When considering local hypotheses, we use the transparent state of the first hint database given. Using an empty database (created with :cmd:`Create HintDb` for example) with unfoldable variables and :term:`constants ` as the first argument of ``typeclasses eauto`` hence makes resolution with the local hypotheses use full conversion during unification. + The mode hints (see :cmd:`Hint Mode`) associated with a typeclass are taken into account by :tacn:`typeclasses eauto`. When a goal does not match any of the declared modes for its head (if any), instead of failing like :tacn:`eauto`, the goal is suspended and resolution proceeds on the remaining goals. If after one run of resolution, there remain suspended goals, resolution is launched again on them, until it reaches a fixed point when the set of remaining suspended goals does not change. Using `solve [typeclasses eauto]` can be used to ensure that no suspended goals remain. + When considering local hypotheses, we use the union of all the modes declared in the given databases. + The tactic may produce more than one success when used in backtracking tactics such as `typeclasses eauto; ...`. See :tacn:`ltac-seq`. + Use the :cmd:`Typeclasses eauto` command to customize the behavior of this tactic. :n:`{| bfs | dfs}` Specifies whether to use breadth-first search or depth-first search. The default is depth-first search, which can be changed with the :flag:`Typeclasses Iterative Deepening` flag. .. _TypeclassesEautoBestEffort: :n:`best_effort` If the `best_effort` option is given and resolution fails, `typeclasses eauto` returns the first partial solution in which all remaining subgoals fall into one of these categories: - Stuck goals: the head of the goal has at least one associated declared mode and the constraint does not match any mode declared for its head. These goals are shelved. - Mode failures: the head of the constraint has at least one matching declared mode, but the constraint couldn't be solved. These goals are left as subgoals of :n:`typeclasses eauto best_effort`. During type inference, typeclass resolution always uses the `best_effort` option: in case of failure, it constructs a partial solution for the goals and gives a more informative error message. It can be used the same way in interactive proofs to check which instances/hints are missing for a typeclass resolution to succeed. :n:`@nat_or_var` Specifies the maximum depth of the search. .. warning:: The semantics for the limit :n:`@nat_or_var` are different than for :tacn:`auto`. By default, if no limit is given, the search is unbounded. Unlike :tacn:`auto`, introduction steps count against the limit, which might result in larger limits being necessary when searching with :tacn:`typeclasses eauto` than with :tacn:`auto`. :n:`with {+ @ident }` Runs resolution with the specified hint databases. It treats typeclass subgoals the same as other subgoals (no shelving of non-typeclass goals in particular), while allowing shelved goals to remain at any point during search. When :n:`with` is not specified, :tacn:`typeclasses eauto` uses the ``typeclass_instances`` database by default. (If `with` is provided, you must explicitly specify `typeclass_instances` to use it.) Unlike :tacn:`auto` and :tacn:`eauto`, `core` is not automatically included. Dependent subgoals are automatically shelved, and shelved goals can remain after resolution ends (following the behavior of Coq 8.5). .. comment if `with` given then typeclases_eauto must be explicit: Tac2tactics.typeclasses_eauto (read code) and Class_tactics.e_my_find_search (with debugger) core not automatically included: test-suite/success/tceauto_nocore.v .. note:: ``all:once (typeclasses eauto)`` faithfully mimics what happens during typeclass resolution when it is called during refinement/type inference, except that *only* declared typeclass subgoals are considered at the start of resolution during type inference, while ``all`` can select non-typeclass subgoals as well. It might move to ``all:typeclasses eauto`` in future versions when the refinement engine will be able to backtrack. .. tacn:: autoapply @one_term with @ident The tactic ``autoapply`` applies :token:`one_term` using the transparency information of the hint database :token:`ident`, and does *no* typeclass resolution. This can be used in :cmd:`Hint Extern`\s for typeclass instances (in the hint database `typeclass_instances`) to allow backtracking on the typeclass subgoals created by the lemma application, rather than doing typeclass resolution locally at hint application time. .. _TypeclassesTransparent: Typeclasses Transparent, Typeclasses Opaque ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Typeclasses Transparent {+ @qualid } Makes :token:`qualid` transparent during typeclass resolution. A shortcut for :cmd:`Hint Transparent` :n:`{+ @qualid } : typeclass_instances` .. cmd:: Typeclasses Opaque {+ @qualid } Make :token:`qualid` opaque for typeclass search. A shortcut for :cmd:`Hint Opaque` :n:`{+ @qualid } : typeclass_instances`. It is useful when some :term:`constants ` prevent some unifications and make resolution fail. It is also useful to declare constants which should never be unfolded during proof search, like fixpoints or anything which does not look like an abbreviation. This can additionally speed up proof search as the typeclass map can be indexed by such rigid constants (see :ref:`hintdatabases`). By default, all :term:`constants ` and local variables are considered transparent. One should take care not to make opaque any constant that is used to abbreviate a type, like: .. rocqdoc:: Definition relation A := A -> A -> Prop. .. versionadded:: 8.15 :cmd:`Typeclasses Transparent` and :cmd:`Typeclasses Opaque` support locality attributes like :cmd:`Hint ` commands. .. deprecated:: 8.15 The default value for typeclass transparency hints will change in a future release. Hints added outside of sections without an explicit locality are now deprecated. We recommend using :attr:`export` where possible. Settings ~~~~~~~~ .. _TypeclassesDefaultMode: .. opt:: Typeclasses Default Mode {| "+" | "-" | "!" }. Sets the default mode declaration associated with a :cmd:`Class` or :cmd:`Existing Class` declaration. It is set by default to "-", i.e. doing no mode filtering by default. Each class declaration uses this default mode for *all* its parameters, unless a :attr:`mode` attribute is used to set the mode explicitly. .. _class-declaration-default-mode: .. warn:: Using inferred default mode: β€œmode” for β€œ@ident” Indicates that the :attr:`mode` for a :cmd:`Class` declaration has been assigned automatically using the default mode. This warning is named ``class-declaration-default-mode``. It is disabled by default. Enable it to find (and fix) any typeclasses that don't have explicit mode declarations. .. flag:: Typeclasses Dependency Order This :term:`flag` (off by default) respects the dependency order between subgoals, meaning that subgoals on which other subgoals depend come first, while the non-dependent subgoals were put before the dependent ones previously (Coq 8.5 and below). This can result in quite different performance behaviors of proof search. .. flag:: Typeclasses Limit Intros This :term:`flag` (on by default) controls the ability to apply hints while avoiding (functional) eta-expansions in the generated proof term. It does so by allowing hints that conclude in a product to apply to a goal with a matching product directly, avoiding an introduction. .. warning:: This can be expensive as it requires rebuilding hint clauses dynamically, and does not benefit from the invertibility status of the product introduction rule, resulting in potentially more expensive proof search (i.e. more useless backtracking). .. flag:: Typeclass Resolution For Conversion This :term:`flag` (on by default) controls the use of typeclass resolution when a unification problem cannot be solved during elaboration/type inference. With this flag on, when a unification fails, typeclass resolution is tried before launching unification once again. .. flag:: Typeclasses Strict Resolution Typeclass declarations introduced when this :term:`flag` is set have a stricter resolution behavior (the flag is off by default). When looking for unifications of a goal with an instance of this typeclass, we β€œfreeze” all the existentials appearing in the goals, meaning that they are considered rigid during unification and cannot be instantiated. .. flag:: Typeclasses Unique Solutions When a typeclass resolution is launched we ensure that it has a single solution or fail. This :term:`flag` ensures that the resolution is canonical, but can make proof search much more expensive. .. flag:: Typeclasses Unique Instances Typeclass declarations introduced when this :term:`flag` is set have a more efficient resolution behavior (the flag is off by default). When a solution to the typeclass goal of this typeclass is found, we never backtrack on it, assuming that it is canonical. .. flag:: Typeclasses Iterative Deepening When this :term:`flag` is set, the proof search strategy is breadth-first search. Otherwise, the search strategy is depth-first search. The default is off. :cmd:`Typeclasses eauto` is another way to set this flag. .. opt:: Typeclasses Depth @natural This :term:`option` sets the maximum proof search depth. The default is unbounded. :cmd:`Typeclasses eauto` is another way to set this option. .. flag:: Typeclasses Debug Controls whether typeclass resolution steps are shown during search. Setting this :term:`flag` also sets :opt:`Typeclasses Debug Verbosity` to 1. :cmd:`Typeclasses eauto` is another way to set this flag. .. opt:: Typeclasses Debug Verbosity @natural Determines how much information is shown for typeclass resolution steps during search. 1 is the default level. 2 shows additional information such as tried tactics and shelving of goals. Setting this :term:`option` to 1 or 2 turns on the :flag:`Typeclasses Debug` flag; setting this option to 0 turns that flag off. Note that the tactics shown when :n:`@natural > 0`(after removing tactics that were backtracked) may not always work as a replacement for the proof search tactic. See :ref:`here `. Typeclasses eauto ~~~~~~~~~~~~~~~~~ .. cmd:: Typeclasses eauto := {? debug } {? ( {| bfs | dfs } ) } {? @natural } Allows more global customization of the :tacn:`typeclasses eauto` tactic. The options are: ``debug`` Sets debug mode. In debug mode, a trace of successfully applied tactics is printed. Debug mode can also be set with :flag:`Typeclasses Debug`. :n:`{| bfs | dfs }` Specifies whether to use breadth-first search or depth-first search. The default is depth-first search, which can be changed with the :flag:`Typeclasses Iterative Deepening` flag. :token:`natural` Sets the depth limit for the search. The limit can also be set with :opt:`Typeclasses Depth`. rocq-9.2.0/doc/sphinx/addendum/universe-polymorphism.rst000066400000000000000000001316521516144147600235000ustar00rootroot00000000000000.. _polymorphicuniverses: Polymorphic Universes ====================== :Author: Matthieu Sozeau General Presentation --------------------- .. warning:: The status of Universe Polymorphism is experimental. This section describes the universe polymorphic extension of Rocq. Universe polymorphism makes it possible to write generic definitions making use of universes and reuse them at different and sometimes incompatible universe levels. A standard example of the difference between universe *polymorphic* and *monomorphic* definitions is given by the identity function: .. rocqtop:: in Definition identity {A : Type} (a : A) := a. By default, :term:`constant` declarations are monomorphic, hence the identity function declares a global universe (automatically named ``identity.u0``) for its domain. Subsequently, if we try to self-apply the identity, we will get an error: .. rocqtop:: all Fail Definition selfid := identity (@identity). Indeed, the global level ``identity.u0`` would have to be strictly smaller than itself for this self-application to type check, as the type of :g:`(@identity)` is :g:`forall (A : Type@{identity.u0}), A -> A` whose type is itself :g:`Type@{identity.u0+1}`. A universe polymorphic identity function binds its domain universe level at the definition level instead of making it global. .. rocqtop:: in Polymorphic Definition pidentity {A : Type} (a : A) := a. .. rocqtop:: all About pidentity. It is then possible to reuse the constant at different levels, like so: .. rocqtop:: in Polymorphic Definition selfpid := pidentity (@pidentity). Of course, the two instances of :g:`pidentity` in this definition are different. This can be seen when the :flag:`Printing Universes` flag is on: .. rocqtop:: all Set Printing Universes. Print selfpid. Now :g:`pidentity` is used at two different levels: at the head of the application it is instantiated at ``u`` while in the argument position it is instantiated at ``u0``. This definition is only valid as long as ``u0`` is strictly smaller than ``u``, as shown by the constraints. Note that if we made ``selfpid`` universe monomorphic, the two universes (in this case ``u`` and ``u0``) would be declared in the global universe graph with names ``selfpid.u0`` and ``selfpid.u1``. Since the constraints would be global, ``Print selfpid.`` will not show them, however they will be shown by :cmd:`Print Universes`. When printing :g:`pidentity`, we can see the universes it binds in the annotation :g:`@{u}`. Additionally, when :flag:`Printing Universes` is on we print the "universe context" of :g:`pidentity` consisting of the bound universes and the constraints they must verify (for :g:`pidentity` there are no constraints). Inductive types can also be declared universe polymorphic on universes appearing in their parameters or fields. A typical example is given by monoids. We first put ourselves in a mode where every declaration is universe-polymorphic: .. rocqtop:: in Set Universe Polymorphism. .. rocqtop:: in Record Monoid := { mon_car :> Type; mon_unit : mon_car; mon_op : mon_car -> mon_car -> mon_car }. A monoid is here defined by a carrier type, a unit in this type and a binary operation. .. rocqtop:: all Print Monoid. The Monoid's carrier universe is polymorphic, hence it is possible to instantiate it for example with :g:`Monoid` itself. First we build the trivial unit monoid in any universe :g:`i >= Set`: .. rocqtop:: in Definition unit_monoid@{i} : Monoid@{i} := {| mon_car := unit; mon_unit := tt; mon_op x y := tt |}. Here we are using the fact that :g:`unit : Set` and by cumulativity, any polymorphic universe is greater or equal to `Set`. From this we can build a definition for the monoid of monoids, where multiplication is given by the product of monoids. To do so, we first need to define a universe-polymorphic variant of pairs: .. rocqtop:: in Record pprod@{i j} (A : Type@{i}) (B : Type@{j}) : Type@{max(i,j)} := ppair { pfst : A; psnd : B }. Arguments ppair {A} {B}. Infix "**" := pprod (at level 40, left associativity) : type_scope. Notation "( x ; y ; .. ; z )" := (ppair .. (ppair x y) .. z) (at level 0) : core_scope. The monoid of monoids uses the cartesian product of monoids as its operation: .. rocqtop:: in Definition monoid_op@{i} (m m' : Monoid@{i}) (x y : mon_car m ** mon_car m') : mon_car m ** mon_car m' := let (l, r) := x in let (l', r') := y in (mon_op m l l'; mon_op m' r r'). Definition prod_monoid@{i} (m m' : Monoid@{i}): Monoid@{i} := {| mon_car := (m ** m')%type; mon_unit := (mon_unit m; mon_unit m'); mon_op := (monoid_op m m') |}. Definition monoids_monoid@{i j | i < j} : Monoid@{j} := {| mon_car := Monoid@{i}; mon_unit := unit_monoid@{i}; mon_op := prod_monoid@{i} |}. .. rocqtop:: all Print monoids_monoid. As one can see from the constraints, this monoid is β€œlarge”, it lives in a universe strictly higher than its objects, monoids in the universes :g:`i`. Polymorphic, Monomorphic ------------------------- .. attr:: universes(polymorphic{? = {| yes | no } }) :name: universes(polymorphic); Polymorphic; Monomorphic This :term:`boolean attribute` can be used to control whether universe polymorphism is enabled in the definition of an inductive type. There is also a legacy syntax using the ``Polymorphic`` prefix (see :n:`@legacy_attr`) which, as shown in the examples, is more commonly used. When ``universes(polymorphic=no)`` is used, global universe constraints are produced, even when the :flag:`Universe Polymorphism` flag is on. There is also a legacy syntax using the ``Monomorphic`` prefix (see :n:`@legacy_attr`). .. flag:: Universe Polymorphism This :term:`flag` is off by default. When it is on, new declarations are polymorphic unless the :attr:`universes(polymorphic=no) ` attribute is used to override the default. Many other commands can be used to declare universe polymorphic or monomorphic :term:`constants ` depending on whether the :flag:`Universe Polymorphism` flag is on or the :attr:`universes(polymorphic)` attribute is used: - :cmd:`Lemma`, :cmd:`Axiom`, etc. can be used to declare universe polymorphic constants. - Using the :attr:`universes(polymorphic)` attribute with the :cmd:`Section` command will locally set the polymorphism flag inside the section. - :cmd:`Variable`, :cmd:`Context`, :cmd:`Universe` and :cmd:`Constraint` in a section support polymorphism. See :ref:`universe-polymorphism-in-sections` for more details. - Using the :attr:`universes(polymorphic)` attribute with the :cmd:`Hint Resolve` or :cmd:`Hint Rewrite` commands will make :tacn:`auto` / :tacn:`rewrite` use the hint polymorphically, not at a single instance. .. _cumulative: Cumulative, NonCumulative ------------------------- .. attr:: universes(cumulative{? = {| yes | no } }) :name: universes(cumulative); Cumulative; NonCumulative Polymorphic inductive types, coinductive types, variants and records can be declared cumulative using this :term:`boolean attribute` or the legacy ``Cumulative`` prefix (see :n:`@legacy_attr`) which, as shown in the examples, is more commonly used. This means that two instances of the same inductive type (family) are convertible based on the universe variances; they do not need to be equal. When the attribtue is off, the inductive type is non-cumulative even if the :flag:`Polymorphic Inductive Cumulativity` flag is on. There is also a legacy syntax using the ``NonCumulative`` prefix (see :n:`@legacy_attr`). This means that two instances of the same inductive type (family) are convertible only if all the universes are equal. .. exn:: The cumulative attribute can only be used in a polymorphic context. Using this attribute requires being in a polymorphic context, i.e. either having the :flag:`Universe Polymorphism` flag on, or having used the :attr:`universes(polymorphic)` attribute as well. .. note:: :n:`#[ universes(polymorphic{? = yes }), universes(cumulative{? = {| yes | no } }) ]` can be abbreviated into :n:`#[ universes(polymorphic{? = yes }, cumulative{? = {| yes | no } }) ]`. .. flag:: Polymorphic Inductive Cumulativity When this :term:`flag` is on (it is off by default), it makes all subsequent *polymorphic* inductive definitions cumulative, unless the :attr:`universes(cumulative=no) ` attribute is used to override the default. It has no effect on *monomorphic* inductive definitions. Consider the examples below. .. rocqtop:: in reset Polymorphic Cumulative Inductive list {A : Type} := | nil : list | cons : A -> list -> list. .. rocqtop:: all Set Printing Universes. Print list. When printing :g:`list`, the universe context indicates the subtyping constraints by prefixing the level names with symbols. Because inductive subtypings are only produced by comparing inductives to themselves with universes changed, they amount to variance information: each universe is either invariant, covariant or irrelevant (there are no contravariant subtypings in Rocq), respectively represented by the symbols `=`, `+` and `*`. Here we see that :g:`list` binds an irrelevant universe, so any two instances of :g:`list` are convertible: :math:`E[Ξ“] ⊒ \mathsf{list}@\{i\}~A =_{βδι΢η} \mathsf{list}@\{j\}~B` whenever :math:`E[Ξ“] ⊒ A =_{βδι΢η} B` and this applies also to their corresponding constructors, when they are comparable at the same type. See :ref:`Conversion-rules` for more details on convertibility and subtyping. The following is an example of a record with non-trivial subtyping relation: .. rocqtop:: all Polymorphic Cumulative Record packType := {pk : Type}. About packType. :g:`packType` binds a covariant universe, i.e. .. math:: E[Ξ“] ⊒ \mathsf{packType}@\{i\} ≀_{βδι΢η} \mathsf{packType}@\{j\}~\mbox{ whenever }~i ≀ j Looking back at the example of monoids, we can see that they are naturally covariant for cumulativity: .. rocqtop:: in Set Universe Polymorphism. Cumulative Record Monoid := { mon_car :> Type; mon_unit : mon_car; mon_op : mon_car -> mon_car -> mon_car }. .. rocqtop:: all Set Printing Universes. Print Monoid. This means that a monoid in a lower universe (like the unit monoid in set), can be seen as a monoid in any higher universe, without introducing explicit lifting. .. rocqtop:: in Definition unit_monoid : Monoid@{Set} := {| mon_car := unit; mon_unit := tt; mon_op x y := tt |}. .. rocqtop:: all Monomorphic Universe i. Check unit_monoid : Monoid@{i}. Finally, invariant universes appear when there is no possible subtyping relation between different instances of the inductive. Consider: .. rocqtop:: in Polymorphic Cumulative Record monad@{i} := { m : Type@{i} -> Type@{i}; unit : forall (A : Type@{i}), A -> m A }. .. rocqtop:: all Set Printing Universes. Print monad. The universe of :g:`monad` is invariant due to its use on the left side of an arrow in the :g:`m` field: one cannot lift or lower the level of the type constructor to build a monad in a higher or lower universe. Specifying cumulativity ~~~~~~~~~~~~~~~~~~~~~~~ The variance of the universe parameters for a cumulative inductive may be specified by the user. For the following type, universe ``a`` has its variance automatically inferred (it is irrelevant), ``b`` is required to be irrelevant, ``c`` is covariant and ``d`` is invariant. With these annotations ``c`` and ``d`` have less general variances than would be inferred. .. rocqtop:: all Polymorphic Cumulative Inductive Dummy@{a *b +c =d} : Prop := dummy. About Dummy. Insufficiently restrictive variance annotations lead to errors: .. rocqtop:: all Fail Polymorphic Cumulative Record bad@{*a} := {p : Type@{a}}. .. example:: Demonstration of universe variances .. rocqtop:: in Set Printing Universes. Set Universe Polymorphism. Set Polymorphic Inductive Cumulativity. Inductive Invariant @{=u} : Type@{u}. Inductive Covariant @{+u} : Type@{u}. Inductive Irrelevant@{*u} : Type@{u}. Section Universes. Universe low high. Constraint low < high. (* An invariant universe blocks cumulativity from upper or lower levels. *) Axiom inv_low : Invariant@{low}. Axiom inv_high : Invariant@{high}. .. rocqtop:: all Fail Check (inv_low : Invariant@{high}). Fail Check (inv_high : Invariant@{low}). .. rocqtop:: in (* A covariant universe allows cumulativity from a lower level. *) Axiom co_low : Covariant@{low}. Axiom co_high : Covariant@{high}. .. rocqtop:: all Check (co_low : Covariant@{high}). Fail Check (co_high : Covariant@{low}). .. rocqtop:: in (* An irrelevant universe allows cumulativity from any level *) Axiom irr_low : Irrelevant@{low}. Axiom irr_high : Irrelevant@{high}. .. rocqtop:: all Check (irr_low : Irrelevant@{high}). Check (irr_high : Irrelevant@{low}). .. rocqtop:: in End Universes. .. example:: A proof using cumulativity .. rocqtop:: in reset Set Universe Polymorphism. Set Polymorphic Inductive Cumulativity. Set Printing Universes. Inductive eq@{i} {A : Type@{i}} (x : A) : A -> Type@{i} := eq_refl : eq x x. .. rocqtop:: all Print eq. The universe of :g:`eq` is irrelevant here, hence proofs of equalities can inhabit any universe. The universe must be big enough to fit `A`. .. rocqtop:: in Definition funext_type@{a b e} (A : Type@{a}) (B : A -> Type@{b}) := forall f g : (forall a, B a), (forall x, eq@{e} (f x) (g x)) -> eq@{e} f g. Section down. Universes a b e e'. Constraint e' < e. Lemma funext_down {A B} (H : @funext_type@{a b e} A B) : @funext_type@{a b e'} A B. Proof. exact H. Defined. End down. Cumulativity Weak Constraints ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Cumulativity Weak Constraints When set, which is the default, this :term:`flag` causes "weak" constraints to be produced when comparing universes in an irrelevant position. Processing weak constraints is delayed until minimization time. A weak constraint between `u` and `v` when neither is smaller than the other and one is flexible causes them to be unified. Otherwise the constraint is silently discarded. This heuristic is experimental and may change in future versions. Disabling weak constraints is more predictable but may produce arbitrary numbers of universes. Global and local universes --------------------------- Each universe is declared in a global or local context before it can be used. To ensure compatibility, every *global* universe is set to be strictly greater than :g:`Set` when it is introduced, while every *local* (i.e. polymorphically quantified) universe is introduced as greater or equal to :g:`Set`. Conversion and unification --------------------------- The semantics of conversion and unification have to be modified a little to account for the new universe instance arguments to polymorphic references. The semantics respect the fact that definitions are transparent, so indistinguishable from their :term:`bodies ` during conversion. This is accomplished by changing one rule of unification, the first- order approximation rule, which applies when two applicative terms with the same head are compared. It tries to short-cut unfolding by comparing the arguments directly. In case the :term:`constant` is universe polymorphic, we allow this rule to fire only when unifying the universes results in instantiating a so-called flexible universe variables (not given by the user). Similarly for conversion, if such an equation of applicative terms fail due to a universe comparison not being satisfied, the terms are unfolded. This change implies that conversion and unification can have different unfolding behaviors on the same development with universe polymorphism switched on or off. Minimization ------------- Universe polymorphism with cumulativity tends to generate many useless inclusion constraints in general. Typically at each application of a polymorphic :term:`constant` :g:`f`, if an argument has expected type :g:`Type@{i}` and is given a term of type :g:`Type@{j}`, a :math:`j ≀ i` constraint will be generated. It is however often the case that an equation :math:`j = i` would be more appropriate, when :g:`f`\'s universes are fresh for example. Consider the following example: .. rocqtop:: none Polymorphic Definition pidentity {A : Type} (a : A) := a. .. rocqtop:: in Definition id0 := @pidentity nat 0. .. rocqtop:: all Set Printing Universes. Print id0. This definition is elaborated by minimizing the universe of :g:`id0` to level :g:`Set` while the more general definition would keep the fresh level :g:`i` generated at the application of :g:`id` and a constraint that :g:`Set` :math:`≀ i`. This minimization process is applied only to fresh universe variables. It simply adds an equation between the variable and its lower bound if it is an atomic universe (i.e. not an algebraic max() universe). .. flag:: Universe Minimization ToSet Turning this :term:`flag` off (it is on by default) disallows minimization to the sort :g:`Set` and only collapses floating universes between themselves. .. _explicit-universes: Explicit Universes ------------------- .. insertprodn universe_name sort_constraint .. prodn:: universe_name ::= @qualid | Set | Prop univ_annot ::= @%{ {* @univ_level_or_quality } {? {| %| | ; } {* @univ_level_or_quality } } %} univ_level_or_quality ::= 0 | Set | SProp | Prop | Type | _ | @qualid sort_quality_var ::= Prop | SProp | Type | @qualid univ_decl ::= @%{ {? {* @ident } {| %| | ; } } {* @ident } {? + } {? %| {*, @sort_constraint } {? + } } %} cumul_univ_decl ::= @%{ {? {* @ident } {| %| | ; } } {* {? {| + | = | * } } @ident } {? + } {? %| {*, @sort_constraint } {? + } } %} sort_constraint ::= @universe_name {| < | = | <= } @universe_name | @sort_quality_var -> @sort_quality_var The syntax has been extended to allow users to explicitly bind names to universes and explicitly instantiate polymorphic definitions. .. cmd:: Universe {+ @ident } Universes {+ @ident } In the monomorphic case, declares new global universes with the given names. Global universe names live in a separate namespace. The command supports the :attr:`universes(polymorphic)` attribute (or the ``Polymorphic`` legacy attribute) only in sections, meaning the universe quantification will be discharged for each section definition independently. .. exn:: Polymorphic universes can only be declared inside sections, use Monomorphic Universe instead. :undocumented: .. cmd:: Constraint {+, @sort_constraint } Declares new constraints between named universes. If consistent, the constraints are then enforced in the global environment. Like :cmd:`Universe`, it can be used with the :attr:`universes(polymorphic)` attribute (or the ``Polymorphic`` legacy attribute) in sections only to declare constraints discharged at section closing time. One cannot declare a global constraint on polymorphic universes. .. exn:: Undeclared universe @ident. :undocumented: .. exn:: Universe inconsistency. :undocumented: .. exn:: Polymorphic universe constraints can only be declared inside sections, use Monomorphic Constraint instead :undocumented: .. _printing-universes: Printing universes ~~~~~~~~~~~~~~~~~~ .. flag:: Printing Universes Turn this :term:`flag` on to activate the display of the actual level of each occurrence of :g:`Type`. See :ref:`Sorts` for details. This wizard flag, in combination with :flag:`Printing All` can help to diagnose failures to unify terms apparently identical but internally different in the Calculus of Inductive Constructions. .. cmd:: Print {? Sorted } Universes {? Subgraph ( {* @debug_univ_name } ) } {? {| With | Without } Constraint Sources } {? @string } :name: Print Universes .. insertprodn debug_univ_name debug_univ_name .. prodn:: debug_univ_name ::= @qualid | @string This command can be used to print the constraints on the internal level of the occurrences of :math:`\Type` (see :ref:`Sorts`). The :n:`Subgraph` clause limits the printed graph to the requested names (adjusting constraints to preserve the implied transitive constraints between kept universes). :n:`@debug_univ_name` is :n:`@qualid` for named universes (e.g. `eq.u0`), and :n:`@string` for raw universe expressions (e.g. `"Stdlib.Init.Logic.1"`). By default when printing a subgraph `Print Universes` attempts to find and print the source of the constraints. This can be controlled by providing `With Constraint Sources` or `Without Constraint Sources`. .. rocqtop:: in Monomorphic Universes a b c. Monomorphic Definition make_a_le_b (F:Type@{b} -> Prop) (X:Type@{a}) := F X. Monomorphic Definition make_b_le_c (F:Type@{c} -> Prop) (X:Type@{b}) := F X. Monomorphic Definition make_c_le_a (F:Type@{a} -> Prop) (X:Type@{c}) := F X. .. rocqtop:: all Print Universes Subgraph (a c). .. coqrst gets confused if we use a < c as it thinks there's a prompt this isn't a problem with a = c (for some reason it's also not a problem with the implicit Set < a) .. note:: The integer in raw universe expressions is extremely unstable, so raw universe expressions should not be used outside debugging sessions. The :n:`Sorted` clause makes each universe equivalent to a numbered label reflecting its level (with a linear ordering) in the universe hierarchy. :n:`@string` is an optional output filename. If :n:`@string` ends in ``.dot`` or ``.gv``, the constraints are printed in the DOT language, and can be processed by Graphviz tools. The format is unspecified if `string` doesn’t end in ``.dot`` or ``.gv``. If :n:`@string` is a relative filename, it refers to the directory specified by the command line option `-output-directory`, if set (see :ref:`command-line-options`) and otherwise, the current directory. Use :cmd:`Pwd` to display the current directory. Polymorphic definitions ~~~~~~~~~~~~~~~~~~~~~~~ For polymorphic definitions, the declaration of (all) universe levels introduced by a definition uses the following syntax: .. rocqtop:: in Polymorphic Definition le@{i j} (A : Type@{i}) : Type@{j} := A. .. rocqtop:: all Print le. During refinement we find that :g:`j` must be larger or equal than :g:`i`, as we are using :g:`A : Type@{i} <= Type@{j}`, hence the generated constraint. At the end of a definition or proof, we check that the only remaining universes are the ones declared. In the term and in general in proof mode, introduced universe names can be referred to in terms. Note that local universe names shadow global universe names. During a proof, one can use :cmd:`Show Universes` to display the current context of universes. It is possible to provide only some universe levels and let Rocq infer the others by adding a :g:`+` in the list of bound universe levels: .. rocqtop:: all Fail Definition foobar@{u} : Type@{u} := Type. Definition foobar@{u +} : Type@{u} := Type. Set Printing Universes. Print foobar. This can be used to find which universes need to be explicitly bound in a given definition. Definitions can also be instantiated explicitly, giving their full instance: .. rocqtop:: all Check (pidentity@{Set}). Monomorphic Universes k l. Check (le@{k l}). User-named universes and the anonymous universe implicitly attached to an explicit :g:`Type` are considered rigid for unification and are never minimized. Flexible anonymous universes can be produced with an underscore or by omitting the annotation to a polymorphic definition. .. rocqtop:: all Check (fun x => x) : Type -> Type. Check (fun x => x) : Type -> Type@{_}. Check le@{k _}. Check le. .. flag:: Strict Universe Declaration Turning this :term:`flag` off allows one to freely use identifiers for universes without declaring them first, with the semantics that the first use declares it. This is meant mainly for debugging purposes. .. flag:: Private Polymorphic Universes This :term:`flag`, on by default, removes universes which appear only in the :term:`body` of an opaque polymorphic definition from the definition's universe arguments. As such, no value needs to be provided for these universes when instantiating the definition. Universe constraints are automatically adjusted. Consider the following definition: .. rocqtop:: in Lemma foo@{i} : Type@{i}. Proof. exact Type. Qed. .. rocqtop:: all Print foo. The universe :g:`Top.xxx` for the :g:`Type` in the :term:`body` cannot be accessed, we only care that one exists for any instantiation of the universes appearing in the type of :g:`foo`. This is guaranteed when the transitive constraint ``Set <= Top.xxx < i`` is verified. Then when using the :term:`constant` we don't need to put a value for the inner universe: .. rocqtop:: all Check foo@{_}. and when not looking at the :term:`body` we don't mention the private universe: .. rocqtop:: all About foo. To recover the same behavior with regard to universes as :g:`Defined`, the :flag:`Private Polymorphic Universes` flag may be unset: .. rocqtop:: in Unset Private Polymorphic Universes. Lemma bar : Type. Proof. exact Type. Qed. .. rocqtop:: all About bar. Fail Check bar@{_}. Check bar@{_ _}. Note that named universes are always public. .. rocqtop:: in Set Private Polymorphic Universes. Unset Strict Universe Declaration. Lemma baz : Type@{outer}. Proof. exact Type@{inner}. Qed. .. rocqtop:: all About baz. .. _sort-polymorphism: Sort polymorphism ----------------- Quantifying over universes does not allow instantiation with `Prop` or `SProp`. For instance .. rocqtop:: in reset Polymorphic Definition type@{u} := Type@{u}. .. rocqtop:: all Fail Check type@{Prop}. To be able to instantiate a sort with `Prop` or `SProp`, we must quantify over :gdef:`sort qualities`. Definitions which quantify over sort qualities are called :gdef:`sort polymorphic`. All sort quality variables must be explicitly bound. .. rocqtop:: all Polymorphic Definition sort@{s ; u} := Type@{s;u}. .. note:: The following deprecated syntax is equivalent: .. rocqtop:: all warn Polymorphic Definition sort'@{s | u |} := Type@{s|u}. To help the parser, both `|` in the :n:`@univ_decl` are required. Sort quality variables of a sort polymorphic definition may be instantiated by the concrete values `SProp`, `Prop` and `Type` or by a bound variable. Instantiating `s` in `Type@{s;u}` with the impredicative `Prop` or `SProp` produces `Prop` or `SProp` respectively regardless of the instantiation of `u`. .. rocqtop:: all Eval cbv in sort@{Prop;Set}. Eval cbv in sort@{Type;Set}. When no explicit instantiation is provided or `_` is used, a temporary variable is generated. Temporary sort variables are instantiated with `Type` if not unified with another quality when universe minimization runs (typically at the end of a definition). :cmd:`Check` and :cmd:`Eval` run minimization so we cannot use them to witness these temporary variables. .. rocqtop:: in Goal True. Set Printing Universes. .. rocqtop:: all abort let c := constr:(sort) in idtac c. .. note:: We recommend you do not name explicitly quantified sort variables `Ξ±` followed by a number as printing will not distinguish between your bound variables and temporary variables. Sort polymorphic inductives may be declared when every instantiation is valid. .. _elim-constraints: Elimination of Sort-Polymorphic Inductives ------------------------------------------ Sort-polymorphic inductives follow rules for their elimination, both when the target sort is polymorphic or not. We illustrate the first case on the following example: .. rocqtop:: all reset Set Universe Polymorphism. Inductive Squash@{s;u} (A:Type@{s;u}) : Prop := squash (_:A). Here, elimination to `Prop` and `SProp` is always allowed, so `Squash_ind` and `Squash_sind` are automatically defined. Elimination to `Type` is not allowed with variable `s`, because the instantiation `s := Type` does not allow elimination to `Type`. However elimination to `Type` or to a polymorphic sort with `s := Prop` is allowed: .. rocqtop:: all Definition Squash_Prop_rect A (P:Squash@{Prop;_} A -> Type) (H:forall x, P (squash _ x)) : forall s, P s := fun s => match s with squash _ x => H x end. Definition Squash_Prop_srect@{s;u +} A (P:Squash@{Prop;_} A -> Type@{s;u}) (H:forall x, P (squash _ x)) : forall s, P s := fun s => match s with squash _ x => H x end. In fact, for a given universe instance, elimination is allowed if: - it is allowed for every ground instantiation of the sort variables in the instance, or - the output sort at the given universe instance is sort polymorphic and the return type of the elimination is at the same quality. For instance, for the following inductive, elimination is not allowed unless the target sort of the inductive matches the sort it is eliminated to. .. rocqtop:: all Inductive sum@{sl sr s;ul ur} (A:Type@{sl;ul}) (B:Type@{sr;ur}) : Type@{s;max(ul,ur)} := | inl (_:A) | inr (_:B). .. rocqtop:: none Arguments inl {_ _} _. Arguments inr {_ _} _. .. rocqtop:: all Fail Definition sum_elim@{sl sr s s';ul ur u'|} (A:Type@{sl;ul}) (B:Type@{sr;ur}) (P:sum@{sl sr s;ul ur} A B -> Type@{s';u'}) (fl : forall (x : A), P (inl x)) (fr : forall (y : B), P (inr y)) (v : sum@{sl sr s;ul ur} A B) : P v := match v with | inl x => fl x | inr y => fr y end. As this greatly inhibits the possibilities of sort polymorphism, we have introduced *elimination constraints* to manage these cases. Here, the annotation `s -> s'` can be added to tell Rocq that the definition is allowed for *every* sorts `s`, `s'` such that `s` eliminates into `s'`. .. rocqtop:: all Definition sum_elim@{sl sr s s';ul ur u'|s -> s'} (A:Type@{sl;ul}) (B:Type@{sr;ur}) (P:sum@{sl sr s;ul ur} A B -> Type@{s';u'}) (fl : forall (x : A), P (inl x)) (fr : forall (y : B), P (inr y)) (v : sum@{sl sr s;ul ur} A B) : P v := match v with | inl x => fl x | inr y => fr y end. It means that `s` and `s'` can respectively be instantiated to e.g., `Type` and `Prop` or `Prop` and `SProp`, but cannot be instantiated to e.g., `Prop` and `Type` or `SProp` and `Prop`. .. rocqtop:: all Check sum_elim@{_ _ Type Prop;_ _ _}. Check sum_elim@{_ _ Prop SProp;_ _ _}. Fail Check sum_elim@{_ _ Prop Type;_ _ _}. Fail Check sum_elim@{_ _ SProp Prop;_ _ _}. .. note:: As with universe level constraints, elimination constraints can be elaborated automatically if the constraints are denoted extensible with `+` **or** if they are totally omitted. For instance, the two following definitions are legal. .. rocqtop:: all Definition sum_elim_ext@{sl sr s s';ul ur u'|+} (A:Type@{sl;ul}) (B:Type@{sr;ur}) (P:sum@{sl sr s;ul ur} A B -> Type@{s';u'}) (fl : forall (x : A), P (inl x)) (fr : forall (y : B), P (inr y)) (v : sum@{sl sr s;ul ur} A B) : P v := match v with | inl x => fl x | inr y => fr y end. Definition sum_elim_elab@{sl sr s s';ul ur u'} (A:Type@{sl;ul}) (B:Type@{sr;ur}) (P:sum@{sl sr s;ul ur} A B -> Type@{s';u'}) (fl : forall (x : A), P (inl x)) (fr : forall (y : B), P (inr y)) (v : sum@{sl sr s;ul ur} A B) : P v := match v with | inl x => fl x | inr y => fr y end. .. note:: These restrictions ignore :flag:`Definitional UIP`. .. flag:: Printing Sort Qualities By default when :flag:`Printing Universes` is on, sorts at floating sort qualities will print their quality. Turning this :term:`flag` off will instead print them as though the quality was `Type` (which it will become at the end of the definition unless it is unified with another rigid quality). Explicit Sorts --------------- Similar to universes, fresh global sorts can be declared with the :cmd:`Sort`, and elimination constraint on global sorts can be declared with the :cmd:`Constraint`. .. cmd:: Sort {+ @ident } Sorts {+ @ident } In the monomorphic case, declares new global sort qualities with the given names. Global quality names live in their own namespace. Inside sections, the command respects the `Universe Polymorphism` flag, either set globally or locally through the :attr:`universes(polymorphic)` attribute (or the ``Polymorphic`` legacy attribute), meaning the sort quantification will be discharged for each section definition independently. Polymorphic sort qualities are forbidden outside sections. .. exn:: Polymorphic sorts can only be declared inside sections, use #[universe(polymorphic=no)] Sort in order to declare a global sort. Generated when a :cmd:`Sort` command is issued outside a section with universe polymorphism set. Either scope the :cmd:`Sort` with an enclosing :cmd:`Section` or be explicit about creating a global sort by turning universe polymorphism off. .. exn:: Cannot declare global sort qualities inside module types. The :cmd:`Sort` command is not supported inside module types. .. cmd:: Print Sorts Print the list of global named sorts in the current global environment. Use :cmd:`Show Universes` to print sort variables local to a proof context. .. rocqtop:: all Set Universe Polymorphism. (* A global sort named g. *) #[universes(polymorphic=no)] Sort g. Print Sorts. (* Universe of g-sorted type. *) Definition G@{l|} : Type@{l+1} := Type@{g;l}. Section LocalSorts. Sort u v w. Definition arr2@{l|} (A : Type@{u;l}) (B : Type@{v;l}) (C : Type@{w;l}) : Type@{w;l} := A -> B -> C. Print Sorts. Sort x y. Definition arr1@{l|} (X : Type@{x;l}) (Y : Type@{y;l}) : Type@{y;l} := X -> Y. Print Sorts. End LocalSorts. (* The sorts u, v, w, x and y are no longer present. *) Print Sorts. (* Equivalent definition of arr2 outside the section LocalSorts. *) Definition arr2'@{u v w ; l |} (A : Type@{u;l}) (B : Type@{v;l}) (C : Type@{w;l}) : Type@{w;l} := A -> B -> C. (* All sort declarations of the section are bound, even the unused one. *) About arr1. .. _Template-polymorphism: Template polymorphism --------------------- Template polymorphism is a variant of universe polymorphism for inductive types (and inductive families) whose shape allows inferring the universe instance from the parameters. Template polymorphic inductives appear in terms without an explicit universe instance (for instance if `prod` is template polymorphic then `prod nat nat` is a fully explicit term, if it is universe polymorphic it would be `prod@{Set Set} nat nat`). Additionally template polymorphism implements sort polymorphism restricted to the sorts `Prop` and `Type` (for instance `prod True True : Prop`). Template polymorphic inductive declarations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A template polymorphic inductive is polymorphic over some specific universe levels and sort variables which are introduced by the inductive's declaration. These levels are called "template (polymorphic) levels" and sorts. A type of the shape `Type@{s;u}` or `forall ..., Type@{s;u}` (i.e. a type of types or type families) is called an "arity". `Type@{s;u}` is the "conclusion" of the arity. The type of an inductive is always an arity, and for short we say "the inductive's conclusion" instead of "the inductive's type's conclusion". Template polymorphism also involves parameters of the inductive whose types are arities. An inductive may be template polymorphic when - it is the only inductive of its block (the combination of template polymorphism and mutual inductives is not supported). - the template levels appear linearly in the conclusions of parameters which are arities. Such conclusions must have only that level as its universe (i.e. `Type@{s;u}` where `u` is a template level, not `Type@{s;max(u,v)}` or `Type@{u+1}`). Each template level is said to be "bound" by the parameter in whose type it appears. - the template levels may also appear in the inductive's conclusion, and appear nowhere else (not in non-arity parameters, not in the domains of arity parameters, not in the indices, and not in the constructor arguments and return types). - template levels which appear in the inductive's conclusion do not appear with an increment (i.e. if `u` is a template level it does not appear as `u+1`). This restriction prevents generating increments higher than 1 by applying template inductives to themselves, i.e. if `I : Type@{u} -> Type@{u + 1}` was template polymorphic and `X:Type@{i}` then `I (I X) : Type@{i + 2}`. It is necessary as the current universe checking cannot handle such increments properly, but this restriction may be removed in the future. - the template sorts appear in the conclusions of parameters (not necessarily linearly), may appear in the inductive's conclusion, and appear nowhere else. - for each template universe `u`, there are no constraints of the form `v <= u` ("no constraints from below"). These requirements are more than sufficient to ensure that if the inductive was declared universe polymorphic and cumulative then all template levels would be irrelevant. The "no constraints from below" requirement is needed for subject reduction (preservation of typing by reduction) in terms involving partially applied template polymorphic inductives. Linearity of template universes and not supporting mutual inductives make implementation of template polymorphism easier. .. warning:: The restriction that universes are introduced by the inductive declaration prevents inductive types declared in sections from being template-polymorphic on universes introduced previously in the section: they cannot parameterize over the universes introduced with section variables that become parameters at section closing time, as these may be shared with other definitions from the same section which can impose constraints on them. .. note:: Currently user syntax does not support explicit sort polymorphism annotations (`@{s;...}`) in template polymorphic declarations. The sorts must be left implicit and will be automatically inferred. .. example:: .. rocqtop:: in reset Inductive option (A:Type) : Type := | None : option A | Some : A -> option A. Inductive prod A B := pair : A -> B -> prod A B. .. rocqtop:: all Set Printing Universes. About option. About prod. Since the sort polymorphism of template inductives cannot be specified in the user syntax, it is instead described by the "can/cannot be instantiated to `Prop`" mention in :cmd:`About`'s output. Since `option` has 2 constructors, it cannot be instantiated to `Prop` i.e. it is not sort polymorphic. Using template polymorphic inductives ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each template universe `u` bound by parameter `A` of an inductive `I`, when `I` is applied such that `A` is instantiated with a term of type `forall ..., Type@{q;i}` (where `i` may be an algebraic universe), `u` is instantiated by `i` in the inductive's conclusion and in the constraints (which must be of the form `u <= x` where `x` is a global universe due to the "no constraints from below" requirement). Each template sort `s` is instantiated by the supremum of the `q` appearing in the conclusions of the types of arguments provided for parameters binding `s`. This is well-defined because template sorts may only be instantiated by `Prop` and `Type` and variable sorts restricted to these 2 ground sorts. If the inductive is partially applied, leftover parameters act as though they were given an argument at a default global universe and at sort `Type`. .. warning:: Partially applied template polymorphic inductives lead to constraints between global universes, which can cause complex universe inconsistencies. .. example:: As mentioned previously, `option` is not sort polymorphic: .. rocqtop:: all Check fun A:Prop => option A. but it is universe polymorphic: .. rocqtop:: all Check fun A:Set => option A. Check option Set. .. example:: `prod` is sort polymorphic, but restricted to `Prop` and `Type`: .. rocqtop:: all Check fun A:Prop => prod A A. Fail Check fun A:SProp => prod A A. When only one of the arguments is `Prop`, the supremum of the sorts is `Type`: .. rocqtop:: all Check prod True nat. This is also the case when partially applied to a `Prop`, and we can see the use of the default universe `prod.u1` for the second parameter: .. rocqtop:: all Check prod True. Controlling template polymorphism ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Auto Template Polymorphism This :term:`flag`, enabled by default, makes every inductive type declared at level `Type` (without an explicit universe instance or hiding it behind a definition) template polymorphic if possible. This can be prevented using the :attr:`universes(template=no) ` attribute. Template polymorphism and full universe polymorphism (see Chapter :ref:`polymorphicuniverses`) are incompatible, so if the latter is enabled (through the :flag:`Universe Polymorphism` flag or the :attr:`universes(polymorphic)` attribute) it will prevail over automatic template polymorphism. .. warn:: Automatically declaring @ident as template polymorphic. Warning ``auto-template`` can be used (it is off by default) to find which types are implicitly declared template polymorphic by :flag:`Auto Template Polymorphism`. An inductive type can be forced to be template polymorphic using the :attr:`universes(template)` attribute: in this case, the warning is not emitted. .. attr:: universes(template{? = {| yes | no } }) :name: universes(template) This :term:`boolean attribute` can be used to explicitly declare an inductive type as template polymorphic, whether the :flag:`Auto Template Polymorphism` flag is on or off. .. exn:: Template-polymorphism and universe polymorphism are not compatible This attribute cannot be used in a full universe polymorphic context, i.e. if the :flag:`Universe Polymorphism` flag is on or if the :attr:`universes(polymorphic)` attribute is used. .. warn:: This inductive type has no template universes :name: no-template-universe The attribute was used but the inductive definition does not satisfy the criterion to be template polymorphic. When ``universes(template=no)`` is used, it will prevent an inductive type from being template polymorphic, even if the :flag:`Auto Template Polymorphism` flag is on. .. _universe-polymorphism-in-sections: Universe polymorphism and sections ---------------------------------- :cmd:`Variables`, :cmd:`Context`, :cmd:`Universe` and :cmd:`Constraint` in a section support polymorphism. This means that the universe variables and their associated constraints are discharged polymorphically over definitions that use them. In other words, two definitions in the section sharing a common variable will both get parameterized by the universes produced by the variable declaration. This is in contrast to a β€œmononorphic” variable which introduces global universes and constraints, making the two definitions depend on the *same* global universes associated with the variable. It is possible to mix universe polymorphism and monomorphism in sections, except in the following ways: - no monomorphic constraint may refer to a polymorphic universe: .. rocqtop:: all reset Section Foo. Polymorphic Universe i. Fail Constraint i = i. This includes constraints implicitly declared by commands such as :cmd:`Variable`, which may need to be used with universe polymorphism activated (locally by attribute or globally by option): .. rocqtop:: all Fail Variable A : (Type@{i} : Type). Polymorphic Variable A : (Type@{i} : Type). (in the above example the anonymous :g:`Type` constrains polymorphic universe :g:`i` to be strictly smaller.) - no monomorphic :term:`constant` or inductive may be declared if polymorphic universes or universe constraints are present. These restrictions are required in order to produce a sensible result when closing the section (the requirement on :term:`constants ` and inductive types is stricter than the one on constraints, because constants and inductives are abstracted by *all* the section's polymorphic universes and constraints). rocq-9.2.0/doc/sphinx/appendix/000077500000000000000000000000001516144147600163655ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/appendix/history-and-changes/000077500000000000000000000000001516144147600222345ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/appendix/history-and-changes/index.rst000066400000000000000000000013371516144147600241010ustar00rootroot00000000000000.. _history-and-changes: ========================== History and recent changes ========================== This chapter is divided in two parts. The first one is about the :ref:`early history of Coq ` and is presented in chronological order. The second one provides :ref:`release notes about recent versions of the Rocq Prover ` and is presented in reverse chronological order. When updating your version of Rocq (especially to a new major version), it is strongly recommended that you read the corresponding release notes. They may contain advice that will help you understand the differences with the previous version and upgrade your projects. .. toctree:: :maxdepth: 1 ../../history ../../changes rocq-9.2.0/doc/sphinx/appendix/indexes/000077500000000000000000000000001516144147600200245ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/appendix/indexes/index.rst000066400000000000000000000010501516144147600216610ustar00rootroot00000000000000:orphan: .. _indexes: ======== Indexes ======== We provide various specialized indexes that are helpful to quickly find what you are looking for. .. toctree:: ../../std-glossindex ../../rocq-cmdindex ../../rocq-tacindex ../../rocq-attrindex ../../rocq-optindex ../../rocq-exnindex ../../genindex For reference, here are direct links to the documentation of: - :ref:`attributes` - :ref:`flags-options-tables`; - controlling the display of warning messages with the :opt:`Warnings` option or the :attr:`warnings` attribute; rocq-9.2.0/doc/sphinx/biblio.bib000066400000000000000000000576521516144147600165120ustar00rootroot00000000000000@String{jfp = "Journal of Functional Programming"} @String{lncs = "Lecture Notes in Computer Science"} @String{lnai = "Lecture Notes in Artificial Intelligence"} @String{SV = "{Springer-Verlag}"} @InCollection{Asp00, Title = {Proof General: A Generic Tool for Proof Development}, Author = {Aspinall, David}, Booktitle = {Tools and Algorithms for the Construction and Analysis of Systems, {TACAS} 2000}, Publisher = {Springer Berlin Heidelberg}, Year = {2000}, Editor = {Graf, Susanne and Schwartzbach, Michael}, Pages = {38--43}, Series = {Lecture Notes in Computer Science}, Volume = {1785}, Doi = {10.1007/3-540-46419-0_3}, ISBN = {978-3-540-67282-1}, } @Book{Bar81, author = {H.P. Barendregt}, publisher = {North-Holland}, title = {The Lambda Calculus its Syntax and Semantics}, year = {1981} } @InProceedings{Bou97, title = {Using reflection to build efficient and certified decision procedure s}, author = {S. Boutin}, booktitle = {TACS'97}, editor = {Martin Abadi and Takahashi Ito}, publisher = SV, series = lncs, volume = 1281, year = {1997} } @Article{Bru72, author = {N.J. de Bruijn}, journal = {Indag. Math.}, title = {{Lambda-Calculus Notation with Nameless Dummies, a Tool for Automatic Formula Manipulation, with Application to the Church-Rosser Theorem}}, volume = {34}, year = {1972} } @inproceedings{CH85, title={Constructions: a higher order proof system for mechanizing mathematics}, author={Coquand, Thierry and Huet, GΓ©rard}, booktitle={European Conference on Computer Algebra}, pages={151--184}, year={1985}, issn = {1611-3349}, doi = {10.1007/3-540-15983-5_13}, url = {http://dx.doi.org/10.1007/3-540-15983-5_13}, isbn = 9783540396840, publisher = {Springer Berlin Heidelberg} } @techreport{CH88 TITLE = {{The calculus of constructions}}, AUTHOR = {Coquand, T. and Huet, G{\'e}rard}, URL = {https://hal.inria.fr/inria-00076024}, NUMBER = {RR-0530}, INSTITUTION = {{INRIA}}, YEAR = {1986}, MONTH = May, PDF = {https://hal.inria.fr/inria-00076024/file/RR-0530.pdf}, HAL_ID = {inria-00076024}, HAL_VERSION = {v1}, } @techreport{CH87, TITLE = {{Concepts mathematiques et informatiques formalises dans le calcul des constructions}}, AUTHOR = {Coquand, T. and Huet, G{\'e}rard}, URL = {https://hal.inria.fr/inria-00076039}, NUMBER = {RR-0515}, INSTITUTION = {{INRIA}}, YEAR = {1986}, MONTH = Apr, PDF = {https://hal.inria.fr/inria-00076039/file/RR-0515.pdf}, HAL_ID = {inria-00076039}, HAL_VERSION = {v1}, } @techreport{C90, TITLE = {{Metamathematical investigations of a calculus of constructions}}, AUTHOR = {Coquand, T.}, URL = {https://hal.inria.fr/inria-00075471}, NUMBER = {RR-1088}, INSTITUTION = {{INRIA}}, YEAR = {1989}, MONTH = Sep, PDF = {https://hal.inria.fr/inria-00075471/file/RR-1088.pdf}, HAL_ID = {inria-00075471}, HAL_VERSION = {v1}, } @PhDThesis{Coq85, author = {Th. Coquand}, month = jan, school = {Universit\'e Paris~7}, title = {Une Th\'eorie des Constructions}, year = {1985} } @InProceedings{Coq86, author = {Th. Coquand}, address = {Cambridge, MA}, booktitle = {Symposium on Logic in Computer Science}, publisher = {IEEE Computer Society Press}, title = {{An Analysis of Girard's Paradox}}, year = {1986} } @InProceedings{Coq92, author = {Th. Coquand}, title = {{Pattern Matching with Dependent Types}}, year = {1992}, booktitle = {Proceedings of the 1992 Workshop on Types for Proofs and Programs} } @InProceedings{DBLP:conf/types/CornesT95, author = {Cristina Cornes and Delphine Terrasse}, title = {Automating Inversion of Inductive Predicates in Coq}, booktitle = {TYPES}, year = {1995}, pages = {85-104}, crossref = {DBLP:conf/types/1995}, bibsource = {DBLP, http://dblp.uni-trier.de} } @inproceedings{CP90, title={Inductively defined types}, author={Coquand, Thierry and Paulin, Christine}, booktitle={COLOG-88}, pages={50--66}, year={1990}, issn = {1611-3349}, doi = {10.1007/3-540-52335-9_47}, url = {http://dx.doi.org/10.1007/3-540-52335-9_47}, isbn = 9783540469636, publisher = {Springer Berlin Heidelberg} } @Book{Cur58, author = {Haskell B. Curry and Robert Feys and William Craig}, title = {Combinatory Logic}, volume = 1, publisher = "North-Holland", year = 1958, note = {{\S{9E}}}, } @Article{CSlessadhoc, author = {Gonthier, Georges and Ziliani, Beta and Nanevski, Aleksandar and Dreyer, Derek}, title = {How to Make Ad Hoc Proof Automation Less Ad Hoc}, journal = {SIGPLAN Not.}, issue_date = {September 2011}, volume = {46}, number = {9}, month = sep, year = {2011}, issn = {0362-1340}, pages = {163--175}, numpages = {13}, url = {http://doi.acm.org/10.1145/2034574.2034798}, doi = {10.1145/2034574.2034798}, acmid = {2034798}, publisher = {ACM}, address = {New York, NY, USA}, keywords = {canonical structures, coq, custom proof automation, hoare type theory, interactive theorem proving, tactics, type classes}, } @InProceedings{CSwcu, hal_id = {hal-00816703}, url = {http://hal.inria.fr/hal-00816703}, title = {{Canonical Structures for the working Coq user}}, author = {Mahboubi, Assia and Tassi, Enrico}, booktitle = {{ITP 2013, 4th Conference on Interactive Theorem Proving}}, publisher = {Springer}, pages = {19-34}, address = {Rennes, France}, volume = {7998}, editor = {Sandrine Blazy and Christine Paulin and David Pichardie }, series = {LNCS }, doi = {10.1007/978-3-642-39634-2_5}, year = {2013}, } @InProceedings{Del00, author = {Delahaye, D.}, title = {A {T}actic {L}anguage for the {S}ystem {Coq}}, booktitle = {Proceedings of Logic for Programming and Automated Reasoning (LPAR), Reunion Island}, publisher = SV, series = LNCS, volume = {1955}, pages = {85--95}, month = {November}, year = {2000}, url = {http://www.lirmm.fr/%7Edelahaye/papers/ltac%20(LPAR%2700).pdf} } @Article{Dyc92, author = {Roy Dyckhoff}, journal = {The Journal of Symbolic Logic}, month = sep, number = {3}, title = {Contraction-free sequent calculi for intuitionistic logic}, volume = {57}, year = {1992} } @Book{Fourier, author = {Jean-Baptiste-Joseph Fourier}, publisher = {Gauthier-Villars}, title = {Fourier's method to solve linear inequations/equations systems.}, year = {1890} } @article{Gilbert:POPL2019, author = {Gilbert, Ga\"{e}tan and Cockx, Jesper and Sozeau, Matthieu and Tabareau, Nicolas}, title = {{Definitional Proof Irrelevance Without K}}, journal = {Proc. ACM Program. Lang.}, issue_date = {January 2019}, volume = {3}, number = {POPL}, year = {2019}, issn = {2475-1421}, pages = {3:1--3:28}, articleno = {3}, numpages = {28}, url = {http://doi.acm.org/10.1145/3290316}, acmid = {3290316}, publisher = {ACM}, address = {New York, NY, USA}, keywords = {proof assistants, proof irrelevance, type theory}, } @InProceedings{Gim94, author = {E. Gim\'enez}, booktitle = {Types'94 : Types for Proofs and Programs}, note = {Extended version in LIP research report 95-07, ENS Lyon}, publisher = SV, series = LNCS, title = {Codifying guarded definitions with recursive schemes}, volume = {996}, year = {1994} } @TechReport{Gim98, author = {E. Gim\'enez}, title = {A Tutorial on Recursive Types in Coq}, institution = {INRIA}, year = 1998, month = mar } @Unpublished{GimCas05, author = {E. Gim\'enez and P. Cast\'eran}, title = {A Tutorial on [Co-]Inductive Types in Coq}, institution = {INRIA}, year = 2005, month = jan, note = {available at \url{http://coq.inria.fr/doc}} } @InProceedings{Gimenez95b, author = {E. Gim\'enez}, booktitle = {Workshop on Types for Proofs and Programs}, series = LNCS, number = {1158}, pages = {135-152}, title = {An application of co-Inductive types in Coq: verification of the Alternating Bit Protocol}, editorS = {S. Berardi and M. Coppo}, publisher = SV, year = {1995} } @Book{Gir89, author = {J.-Y. Girard and Y. Lafont and P. Taylor}, publisher = {Cambridge University Press}, series = {Cambridge Tracts in Theoretical Computer Science 7}, title = {Proofs and Types}, year = {1989} } @InCollection{How80, author = {W.A. Howard}, booktitle = {to H.B. Curry : Essays on Combinatory Logic, Lambda Calculus and Formalism.}, editor = {J.P. Seldin and J.R. Hindley}, note = {Unpublished 1969 Manuscript}, publisher = {Academic Press}, title = {The Formulae-as-Types Notion of Constructions}, year = {1980} } @inproceedings{H88, title={Induction principles formalized in the Calculus of Constructions}, author={Huet, G{\'e}rard}, booktitle={Programming of Future Generation Computers. Elsevier Science}, year={1988}, issn = {1611-3349}, doi = {10.1007/3-540-17660-8_62}, url = {http://dx.doi.org/10.1007/3-540-17660-8_62}, isbn = 9783540477464, publisher = {Springer Berlin Heidelberg} } @InProceedings{H89, author = {G. Huet}, booktitle = {A perspective in Theoretical Computer Science. Commemorative Volume for Gift Siromoney}, editor = {R. Narasimhan}, publisher = {World Scientific Publishing}, title = {{The Constructive Engine}}, year = {1989} } @Article{LeeWerner11, author = {Gyesik Lee and Benjamin Werner}, title = {Proof-irrelevant model of {CC} with predicative induction and judgmental equality}, journal = {Logical Methods in Computer Science}, volume = {7}, number = {4}, year = {2011}, ee = {http://dx.doi.org/10.2168/LMCS-7(4:5)2011}, bibsource = {DBLP, http://dblp.uni-trier.de} } @TechReport{Leroy90, author = {X. Leroy}, title = {The {ZINC} experiment: an economical implementation of the {ML} language}, institution = {INRIA}, number = {117}, year = {1990} } @InProceedings{Let02, author = {P. Letouzey}, title = {A New Extraction for Coq}, booktitle = {TYPES}, year = 2002, crossref = {DBLP:conf/types/2002}, url = {http://www.irif.fr/~letouzey/download/extraction2002.pdf} } @InProceedings{Luttik97specificationof, author = {Sebastiaan P. Luttik and Eelco Visser}, booktitle = {2nd International Workshop on the Theory and Practice of Algebraic Specifications (ASF+SDF'97), Electronic Workshops in Computing}, publisher = SV, title = {Specification of Rewriting Strategies}, year = {1997} } @inproceedings{Visser98, author = {Eelco Visser and Zine{-}El{-}Abidine Benaissa and Andrew P. Tolmach}, title = {Building Program Optimizers with Rewriting Strategies}, booktitle = {ICFP}, pages = {13--26}, year = {1998}, } @inproceedings{Visser01, author = {Eelco Visser}, title = {Stratego: {A} Language for Program Transformation Based on Rewriting Strategies}, booktitle = {RTA}, pages = {357--362}, year = {2001}, series = {LNCS}, volume = {2051}, } @InProceedings{DBLP:conf/types/McBride00, author = {Conor McBride}, title = {Elimination with a Motive}, booktitle = {TYPES}, year = {2000}, pages = {197-216}, ee = {http://link.springer.de/link/service/series/0558/bibs/2277/22770197.htm}, crossref = {DBLP:conf/types/2000}, bibsource = {DBLP, http://dblp.uni-trier.de} } @InProceedings{Moh93, author = {C. Paulin-Mohring}, booktitle = {Proceedings of the conference Typed Lambda Calculi and Applications}, editor = {M. Bezem and J.-F. Groote}, note = {Also LIP research report 92-49, ENS Lyon}, number = {664}, publisher = SV, series = {LNCS}, title = {{Inductive Definitions in the System Coq - Rules and Properties}}, year = {1993} } @MastersThesis{Mun94, author = {C. MuΓ±oz}, month = sep, school = {DEA d'Informatique Fondamentale, Universit\'e Paris 7}, title = {D\'emonstration automatique dans la logique propositionnelle intuitionniste}, year = {1994} } @Article{Myers, author = {Eugene Myers}, title = {An {O(ND)} difference algorithm and its variations}, journal = {Algorithmica}, volume = {1}, number = {2}, year = {1986}, bibsource = {https://link.springer.com/article/10.1007\%2FBF01840446}, url = {http://www.xmailserver.org/diff2.pdf} } @inproceedings{P86, title={Algorithm development in the calculus of constructions}, author={Mohring, Christine}, booktitle={LICS}, pages={84--91}, year={1986} } @inproceedings{P89, title={Extracting $\Omega$'s programs from proofs in the calculus of constructions}, author={Paulin-Mohring, Christine}, booktitle={Proceedings of the 16th ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, pages={89--104}, year={1989}, doi = {10.1145/75277.75285}, url = {http://dx.doi.org/10.1145/75277.75285}, isbn = 0897912942, organization = {ACM Press} } @inproceedings{P93, title={Inductive definitions in the system coq rules and properties}, author={Paulin-Mohring, Christine}, booktitle={International Conference on Typed Lambda Calculi and Applications}, pages={328--345}, year={1993}, doi = {10.1007/bfb0037116}, url = {http://dx.doi.org/10.1007/bfb0037116}, isbn = 3540565175, organization = {Springer-Verlag} } @inproceedings{PP90, title={Inductively defined types in the Calculus of Constructions}, author={Pfenning, Frank and Paulin-Mohring, Christine}, booktitle={International Conference on Mathematical Foundations of Programming Semantics}, pages={209--228}, year={1989}, doi = {10.1007/bfb0040259}, url = {http://dx.doi.org/10.1007/bfb0040259}, isbn = 0387973753, organization = {Springer-Verlag} } @InProceedings{Parent95b, author = {C. Parent}, booktitle = {{Mathematics of Program Construction'95}}, publisher = SV, series = {LNCS}, title = {{Synthesizing proofs from programs in the Calculus of Inductive Constructions}}, volume = {947}, year = {1995} } @InProceedings{Pit16, Title = {Company-Coq: Taking Proof General one step closer to a real IDE}, Author = {Pit-Claudel, ClΓ©ment and Courtieu, Pierre}, Booktitle = {CoqPL'16: The Second International Workshop on Coq for PL}, Year = {2016}, Month = jan, Doi = {10.5281/zenodo.44331}, } @Book{RC95, author = {di~Cosmo, R.}, title = {Isomorphisms of Types: from $\lambda$-calculus to information retrieval and language design}, series = {Progress in Theoretical Computer Science}, publisher = {Birkhauser}, year = {1995}, note = {ISBN-0-8176-3763-X} } @Article{Rushby98, title = {Subtypes for Specifications: Predicate Subtyping in {PVS}}, author = {John Rushby and Sam Owre and N. Shankar}, journal = {IEEE Transactions on Software Engineering}, pages = {709--720}, volume = 24, number = 9, month = sep, year = 1998 } @InProceedings{sozeau06, author = {Matthieu Sozeau}, title = {Subset Coercions in {C}oq}, year = {2007}, booktitle = {TYPES'06}, pages = {237-252}, volume = {4502}, publisher = "Springer", series = {LNCS} } @InProceedings{sozeau08, Author = {Matthieu Sozeau and Nicolas Oury}, booktitle = {TPHOLs'08}, Pdf = {http://www.lri.fr/~sozeau/research/publications/drafts/classes.pdf}, Title = {{F}irst-{C}lass {T}ype {C}lasses}, Year = {2008}, url = {https://doi.org/10.1007/978-3-540-71067-7_23}, } @InProceedings{sugar, author = {Alessandro Giovini and Teo Mora and Gianfranco Niesi and Lorenzo Robbiano and Carlo Traverso}, title = {"One sugar cube, please" or Selection strategies in the Buchberger algorithm}, booktitle = { Proceedings of the ISSAC'91, ACM Press}, year = {1991}, pages = {5--4}, publisher = {} } @PhDThesis{Wer94, author = {B. Werner}, school = {Universit\'e Paris 7}, title = {Une th\'eorie des constructions inductives}, type = {Th\`ese de Doctorat}, year = {1994} } @InProceedings{CompiledStrongReduction, author = {Benjamin Gr{\'{e}}goire and Xavier Leroy}, editor = {Mitchell Wand and Simon L. Peyton Jones}, title = {A compiled implementation of strong reduction}, booktitle = {Proceedings of the Seventh {ACM} {SIGPLAN} International Conference on Functional Programming {(ICFP} '02), Pittsburgh, Pennsylvania, USA, October 4-6, 2002.}, pages = {235--246}, publisher = {{ACM}}, year = {2002}, url = {http://doi.acm.org/10.1145/581478.581501}, doi = {10.1145/581478.581501}, timestamp = {Tue, 11 Jun 2013 13:49:16 +0200}, biburl = {http://dblp.uni-trier.de/rec/bib/conf/icfp/GregoireL02}, bibsource = {dblp computer science bibliography, http://dblp.org} } @InProceedings{FullReduction, author = {Mathieu Boespflug and Maxime D{\'{e}}n{\`{e}}s and Benjamin Gr{\'{e}}goire}, editor = {Jean{-}Pierre Jouannaud and Zhong Shao}, title = {Full Reduction at Full Throttle}, booktitle = {Certified Programs and Proofs - First International Conference, {CPP} 2011, Kenting, Taiwan, December 7-9, 2011. Proceedings}, series = {Lecture Notes in Computer Science}, volume = {7086}, pages = {362--377}, publisher = {Springer}, year = {2011}, url = {http://dx.doi.org/10.1007/978-3-642-25379-9_26}, doi = {10.1007/978-3-642-25379-9_26}, timestamp = {Thu, 17 Nov 2011 13:33:48 +0100}, biburl = {http://dblp.uni-trier.de/rec/bib/conf/cpp/BoespflugDG11}, bibsource = {dblp computer science bibliography, http://dblp.org} } @inproceedings{MilnerPrincipalTypeSchemes, author = {Damas, Luis and Milner, Robin}, title = {Principal Type-schemes for Functional Programs}, booktitle = {Proceedings of the 9th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, series = {POPL '82}, year = {1982}, isbn = {0-89791-065-6}, location = {Albuquerque, New Mexico}, pages = {207--212}, numpages = {6}, url = {http://doi.acm.org/10.1145/582153.582176}, doi = {10.1145/582153.582176}, acmid = {582176}, publisher = {ACM}, address = {New York, NY, USA}, } @techreport{abel19:failur_normal_impred_type_theor, author = {Andreas Abel AND Thierry Coquand}, title = {{Failure of Normalization in Impredicative Type Theory with Proof-Irrelevant Propositional Equality}}, year = 2019, institution = {Chalmers and Gothenburg University}, } @inproceedings{ConchonFilliatre07wml, author = {Sylvain Conchon and Jean-Christophe FilliΓ’tre}, title = {A Persistent Union-Find Data Structure}, booktitle = {ACM SIGPLAN Workshop on ML}, publisher = {ACM Press}, pages = {37--45}, year = 2007, address = {Freiburg, Germany}, month = {October}, topics = {team, lri}, type_publi = {icolcomlec}, type_digiteo = {conf_isbn}, x-pdf = {https://www.lri.fr/~filliatr/ftp/publis/puf-wml07.pdf}, url = {https://www.lri.fr/~filliatr/ftp/publis/puf-wml07.pdf}, abstract = { The problem of disjoint sets, also known as union-find, consists in maintaining a partition of a finite set within a data structure. This structure provides two operations: a function find returning the class of an element and a function union merging two classes. An optimal and imperative solution is known since 1975. However, the imperative nature of this data structure may be a drawback when it is used in a backtracking algorithm. This paper details the implementation of a persistent union-find data structure as efficient as its imperative counterpart. To achieve this result, our solution makes heavy use of imperative features and thus it is a significant example of a data structure whose side effects are safely hidden behind a persistent interface. To strengthen this last claim, we also detail a formalization using the Coq proof assistant which shows both the correctness of our solution and its observational persistence. }, x-equipes = {demons PROVAL}, x-type = {article}, x-support = {actes_aux}, x-cle-support = {ML} } @phdthesis{Zimmermann19, author = {Th{\'{e}}o Zimmermann}, title = {Challenges in the collaborative evolution of a proof language and its ecosystem.}, school = {UniversitΓ© de Paris, France}, year = {2019}, url = {https://tel.archives-ouvertes.fr/tel-02451322}, timestamp = {Tue, 21 Jul 2020 00:40:54 +0200}, biburl = {https://dblp.org/rec/phd/hal/Zimmermann19.bib}, bibsource = {dblp computer science bibliography, https://dblp.org} } @article{TotR21, author = {Cockx, Jesper and Tabareau, Nicolas and Winterhalter, Th\'{e}o}, title = {The Taming of the Rew: A Type Theory with Computational Assumptions}, year = {2021}, issue_date = {January 2021}, publisher = {Association for Computing Machinery}, address = {New York, NY, USA}, volume = {5}, number = {POPL}, url = {https://doi.org/10.1145/3434341}, doi = {10.1145/3434341}, abstract = {Dependently typed programming languages and proof assistants such as Agda and Coq rely on computation to automatically simplify expressions during type checking. To overcome the lack of certain programming primitives or logical principles in those systems, it is common to appeal to axioms to postulate their existence. However, one can only postulate the bare existence of an axiom, not its computational behaviour. Instead, users are forced to postulate equality proofs and appeal to them explicitly to simplify expressions, making axioms dramatically more complicated to work with than built-in primitives. On the other hand, the equality reflection rule from extensional type theory solves these problems by collapsing computation and equality, at the cost of having no practical type checking algorithm. This paper introduces Rewriting Type Theory (RTT), a type theory where it is possible to add computational assumptions in the form of rewrite rules. Rewrite rules go beyond the computational capabilities of intensional type theory, but in contrast to extensional type theory, they are applied automatically so type checking does not require input from the user. To ensure type soundness of RTTβ€”as well as effective type checkingβ€”we provide a framework where confluence of user-defined rewrite rules can be checked modularly and automatically, and where adding new rewrite rules is guaranteed to preserve subject reduction. The properties of RTT have been formally verified using the MetaCoq framework and an implementation of rewrite rules is already available in the Agda proof assistant.}, journal = {Proc. ACM Program. Lang.}, month = {jan}, articleno = {60}, numpages = {29}, keywords = {termination, dependent types, rewriting theory, confluence, type theory} } @unpublished{NestedInductiveTypes, TITLE = {{Nested Inductive Types}}, AUTHOR = {Lamiaux, Thomas and Forster, Yannick and Sozeau, Matthieu and Tabareau, Nicolas}, URL = {https://hal.science/hal-05366368}, NOTE = {working paper or preprint}, YEAR = {2025}, KEYWORDS = {Type Theory ; Proof Assistant ; Rocq prover ; Lean}, PDF = {https://hal.science/hal-05366368v1/file/main.pdf}, HAL_ID = {hal-05366368}, HAL_VERSION = {v1}, } rocq-9.2.0/doc/sphinx/changes.rst000066400000000000000000026550321516144147600167340ustar00rootroot00000000000000.. _changes: -------------- Recent changes -------------- .. ifconfig:: not is_a_released_version .. include:: ../unreleased.rst Version 9.2 ----------- .. contents:: :local: :depth: 1 Summary of changes ~~~~~~~~~~~~~~~~~~ We highlight some of the most impactful changes here: - :ref:`Reenable support for `native_compute`<92native>` when compiled with OCaml 5. As it relies on some architecture-specific code, only some x86 setups are supported for now - Records in `Type` and `Prop`, with only fields in `SProp`, can now have :ref:`primitive projections but without eta conversion<92etarecord>`. - Implicit elaboration of :ref:`elimination constraints <92elimconstraints>` - :ref:`Parsing of elimination constraints<92elimparsing>` in prenex polymorphic definitions as well as in constraints declaration :g:`Constraint s1 -> s2.` - :ref:`Induction hypotheses are now generated for nested arguments<92nested>` provided an `All` predicate, and a theorem to prove it, have been registered with the keys `All` and `AllForall`. - Add a `Scheme All` command to :ref:`generate the All predicate<92nestedscheme>` and its theorem for inductive types used for the eliminators of nested inductive types - Tactics such as :tacn:`induction` find eliminators (like `nat_rect`) through the :cmd:`Register Scheme` table (which is automatically populated by :cmd:`Scheme` and automatic scheme declarations) instead of by name (the lookup by name remains for now for backward compatibility) - attribute :attr:`schemes` to :ref:`control automatic scheme declaration<92scheme>`. - :ref:`Goal names can be automatically generated<92goalnames>` for :tacn:`induction`, :tacn:`destruct` and :tacn:`eapply` by using the :flag:`Generate Goal Names` flag - congruence tactics now :ref:`handle primitive ints, floats and strings<92congruence>` - :cmd:`Ltac2 Custom Entry` making it possible to define :ref:`more complex<92ltac2>` :cmd:`Ltac2 Notation`\s and many other additions to Ltac2 (see below for details). - :flag:`Printing Fully Qualified` to :ref:`print all names<92printfully>` (global references, modules, module types, universes, etc) using fully qualified paths - :ref:`Generalized universe polymorphism flag<92mlapi>` structure (ML API change) See the `Changes in 9.2.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Rocq's `reference manual for 9.2 `_, documentation of the 9.2 `corelib `__ and `developer documentation of the 9.2 ML API `_ are also available. ThΓ©o Zimmermann, with help from Jason Gross and GaΓ«tan Gilbert, maintained `coqbot `__ used to run Rocq's CI and other pull request management tasks. Jason Gross maintained the `bug minimizer `_ and its `automatic use through coqbot `_. Ali Caglayan, Emilio JesΓΊs Gallego Arias, Rudi Grinberg and Rodolphe Lepigre maintained the `Dune build system for OCaml and Coq/Rocq `_ used to build the Rocq Prover itself and many Rocq projects. The `opam repository `_ for Rocq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. The up-to-date list of packages is `available on the Rocq website `_. Erik Martin-Dorel maintained the `Rocq Docker images `_ and the `docker-keeper `_ compiler used to build and keep those images up to date (note that the tool is not Rocq specific). Erik Martin-Dorel and ThΓ©o Zimmermann maintained the `docker-coq-action `_ container action (which is applicable to any opam project hosted on GitHub). Cyril Cohen, Vincent Laporte, Pierre Roux and ThΓ©o Zimmermann maintained the `Nix toolbox `_. The docker-coq-action and the Nix toolbox are used by many Rocq projects for continuous integration. Rocq 9.2 was made possible thanks to the following 35 reviewers: Eric Bistal, Dan Christensen, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Julien Cretin, TomΓ‘s DΓ­az, Andres Erbsen, Jian Fang, Jim Fehrle, GaΓ«tan Gilbert, Jason Gross, Hugo Herbelin, Emilio JesΓΊs Gallego Arias, Ralf Jung, Jan-Oliver Kaiser, Thomas Lamiaux, Olivier Laurent, Rodolphe Lepigre, Yann Leray, Kenji Maillard, Guillaume Melquiond, Guillaume Munch-Maccagnoni, Karl Palmskog, ClΓ©ment Pit-Claudel, Pierre-Marie PΓ©drot, Pierre Rousselin, Pierre Roux, RadosΕ‚aw Rowicki, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi, Li-yao Xia, ThΓ©o Zimmermann. See the `Rocq Team `_ page for more details on Rocq's development teams. The 43 contributors to the 9.2 version are: Charles C Norton, Ilan, Jean Caspar, quarkcool, Lionel Blatter, Mathis Bouverot, Jeffrey Chang, Owen Conoly, Quentin Corradi, Julien Cretin, TomΓ‘s DΓ­az, Andres Erbsen, Jim Fehrle, GaΓ«tan Gilbert, Jason Gross, Dario Halilovic, Hugo Herbelin, Emilio JesΓΊs Gallego Arias, Jan-Oliver Kaiser, Thomas Lamiaux, Rodolphe Lepigre, Yann Leray, Gregory Malecha, Bruno Martinez, Guillaume Melquiond, Jan Midtgaard, Patrick Nicodemus, Charles Norton, ClΓ©ment Pit-Claudel, Pierre-Marie PΓ©drot, Johann Rosain, Dan Rostovtsev, Pierre Rousselin, Pierre Roux, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi, Laurent Thery, Quentin Vermande, ThΓ©o Winterhalter, ThΓ©o Zimmermann. The Rocq community at large helped improve this new version via the GitHub issue and pull request system, the `Discourse forum `__ and the `Rocq Zulip chat `_. Nicolas Tabareau is the release manager of Rocq 9.2. This release is the result of 486 merged PRs, closing 80 issues. | Nantes, March 2026 | Nicolas Tabareau for the Rocq development team Changes in 9.2.0 ~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ .. _92etarecord: - **Changed:** Records in `Type` and `Prop`, with only fields in `SProp`, can now have primitive projections but without eta conversion. (`#21438 `_, by Tomas Diaz). - **Changed:** Error messages for module signature mismatches and "with Definition" constraint failures are now more detailed (`#21465 `_, fixes `#21464 `_, by Jason Gross). .. _92native: - **Changed:** Reenable support for `native_compute` when compiled with OCaml 5. As it relies on some architecture-specific code, only some x86 setups are supported for now (`#21540 `_, fixes `#13940 `_, by Guillaume Melquiond). - **Removed:** the ability to define monomorphic sorts within sections (`#21451 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Fix the detection and treatment of uniform arguments of nested fixpoints (`#21684 `_, fixes `#21682 `_ and `#21683 `_ and `#21701 `_, by Yann Leray). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Added:** when a reference is not found in the current environment, the error suggests similar names (`#20662 `_, by GaΓ«tan Gilbert). .. _92elimconstraints: - **Added:** implicit elaboration of elimination constraints (`#21417 `_, by Tomas Diaz). Notations ^^^^^^^^^ - **Changed:** :cmd:`Abbreviation` no longer adds a printing rule when a surrounding module is imported (i.e. when it would need to print a qualified name). :attr:`global` can be used to retrieve the previous behavior (`#20816 `_, fixes `#20668 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`custom entry ` names are now qualified. A compatibility layer provides deprecated access with unqualified names without needing to import their module, as long as it is unambiguous (`#20857 `_, by GaΓ«tan Gilbert). - **Changed:** the ``notation-incompatible-prefix`` no longer warns about common prefixes followed by terminal symbols. For instance ``"x #0`` and ``"x #0 #1"`` are not incompatible since our parser isn't exactly LL1, considering successive terminal symbols as a single token. Note that this change has an impact on the default levels of such notations (`#21159 `_, by Pierre Roux). - **Deprecated:** use of "Notation" keyword for :cmd:`abbreviations `, use "Abbreviation" instead (`#20855 `_, by Pierre Roux). - **Added:** a warning for non closed notations at level 0 (`#21107 `_, by Pierre Roux). Tactics ^^^^^^^ - **Changed:** tactics such as :tacn:`induction` find eliminators (like `nat_rect`) through the :cmd:`Register Scheme` table (which is automatically populated by :cmd:`Scheme` and automatic scheme declarations) instead of by name (the lookup by name remains for now for backward compatibility) (`#20614 `_, by GaΓ«tan Gilbert). - **Changed:** type class hints without hypotheses used via functor applications are applied with their type from the module type rather than the module instance (`#21193 `_, by Pierre-Marie PΓ©drot). - **Removed:** the implicit call to `auto with *` in intuition solver, that was deprecated since 8.17 (`#21129 `_, fixes `#4949 `_, by Pierre-Marie PΓ©drot). - **Removed:** the `destauto` tactic, which was deprecated in 8.20 (`#21172 `_, fixes `#11537 `__, by Pierre-Marie PΓ©drot). - **Deprecated:** tactics such as :tacn:`induction` finding eliminators (like `nat_rect`) by name instead of through the :cmd:`Register Scheme` table (which is automatically populated by :cmd:`Scheme` and automatic scheme declarations) (`#20614 `_, by GaΓ«tan Gilbert). - **Deprecated:** dynamically generating schemes when needed in tactics. This was mostly used for rewriting and equality schemes of the registered equality type (`eq` when using the Corelib) for tactics such as :tacn:`discriminate`. These schemes are now explicitly declared for `eq` in the Corelib (`#21245 `_, by GaΓ«tan Gilbert). .. _92congruence: - **Added:** congruence tactics now handle primitive ints, floats and strings (`#20810 `_, fixes `#20011 `_, by Pierre-Marie PΓ©drot). .. _92nested: - **Added:** Induction hypotheses are now generated for nested arguments provided an `All` predicate, and a theorem to prove it, have been registered with the keys `All` and `AllForall`. (`#21356 `_, by Thomas Lamiaux). .. _92nestedscheme: - **Added:** Add a `Scheme All` command to generate the `All` predicate and its theorem for inductive types used for the eliminators of nested inductive types (`#21429 `_, by Thomas Lamiaux). - **Fixed:** ``setoid_rewrite`` now correctly picks up ``Params`` instances when rewriting in ``Type`` (`#20045 `_, fixes `#20044 `_, by quarkcool). - **Fixed:** a sequence `Import M. Remove Hints h. Import M.` where `M` exports hints `h` would not re-add `h` after its removal (`#20698 `_, by GaΓ«tan Gilbert). - **Fixed:** Canonical structure resolution in tactic unification in presence of universe polymorphism (`#20780 `_, fixes `#20779 `_, by Matthieu Sozeau). - **Fixed:** rewrite hints are controlled by the `hints` import category (`#21108 `_, fixes `#21106 `_, by GaΓ«tan Gilbert). - **Changed:** The unification algorithm (evarconv) may need to unfold its two input terms to succeed. Now, when one of the terms is an evar, it instantiates it with the folded version of the other term. In other words, tactics now unfold less than before, which may change the behavior of subsequent tactics. (`#19987 `_, by Quentin Vermande). - **Changed:** Hypotheses of generated induction schemes use the constructor name instead of `f`, `f0`, etc (`#20813 `_, by Dario Halilovic). .. _92goalnames: - **Added:** Goal names can be automatically generated for :tacn:`induction`, :tacn:`destruct` and :tacn:`eapply` by using the :flag:`Generate Goal Names` flag (`#20809 `_, by Dario Halilovic). - **Fixed:** :n:`autorewrite*` was failing if any of the possible rewritings failed to solve its generated side-conditions (`#21803 `_, fixes `#7672 `_ and `#4976 `_, by Matthieu Sozeau). Ltac2 language ^^^^^^^^^^^^^^ - **Changed:** :cmd:`Ltac2 Notation` without an explicit level puts the notation at level `1` instead of `5` when it starts with a string which is an identifier. Various notations have consequently changed level (e.g. `apply`). (`#20759 `_, fixes `#20616 `_, by GaΓ«tan Gilbert). - **Changed:** well parenthesized notations (`match!`, `lazy_match!`, etc) are now at level `0` instead of `5`, and `now` is at level `1` instead of `6` (its argument is still at level `6`) (`#20759 `_, by GaΓ«tan Gilbert). - **Deprecated:** use of "Notation" keyword for :cmd:`abbreviations `, use "Abbreviation" instead (`#20855 `_, by Pierre Roux). - **Deprecated:** syntactic classes parsing terms (`constr`, `lconstr`, etc.) taking more than one :n:`@scope_key` argument without qualifying it with `delimiters` (e.g. `constr(type, function)` should be `constr(delimiters(type, function))` but a single argument like `constr(type)` is not deprecated). See :n:`@ltac2_constr_synclass_arg` (`#21285 `_, by GaΓ«tan Gilbert). .. _92ltac2: - **Added:** :cmd:`Ltac2 Custom Entry` making it possible to define more complex :cmd:`Ltac2 Notation`\s (`#20561 `_, by GaΓ«tan Gilbert). - **Added:** ``Ltac2.Reference.equal`` (`#20794 `_, by Pierre Rousselin). - **Added:** :cmd:`Ltac2 Set` supports :attr:`local` and :attr:`export` (the default behaviour of `local` in sections and `export` outside sections has not changed) (`#20882 `_, fixes `#20879 `_, by GaΓ«tan Gilbert). - **Added:** ``Ltac2.Option.filter`` (`#21023 `_, by Jason Gross). - **Added:** :ref:`syntactic class ` `lpreterm` parsing terms at precedence level 200 and interpreting them as preterms (`#21094 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Message.of_lconstr` to print terms without surrounding parentheses (`#21096 `_, by GaΓ«tan Gilbert). - **Added:** module `Ltac2.Constr.Relevance` for APIs about proof relevance annotations (`#21162 `_, by GaΓ«tan Gilbert). - **Added:** APIs for module introspection in `Ltac2.Module` (`#21178 `_, by GaΓ«tan Gilbert). - **Added:** :ref:`syntactic_classes` parsing terms support parsing at a specific level and parsing :ref:`custom-entries` (`#21215 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Unification.solve_constraints` (cf :tacn:`solve_constraints`) (`#21222 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Constant.print`, `Ltac2.Ind.print`, `Ltac2.Constructor.print`, `Ltac2.Proj.print`, `Ltac2.Ident.print`, `Ltac2.Message.of_preterm` (`#21239 `_, by GaΓ«tan Gilbert). - **Added:** APIs `Control.print_err` and `Control.print_exn` which may be used to customize printing of Ltac2 errors (`#21252 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Ltac2 Set` supports attribute :attr:`global` (`#21264 `_, by GaΓ«tan Gilbert). - **Added:** :flag:`Ltac2 Backtrace Compact` to reduce the output of :flag:`Ltac2 Backtrace` (`#21299 `_, by GaΓ«tan Gilbert). - **Added:** `Message.of_exninfo` and `Control.current_exninfo` (`#21334 `_, fixes `#21312 `_, by GaΓ«tan Gilbert). - **Fixed:** associativity of `::` in Ltac2 `match` patterns (:n:`@tac2pat2`) (`#21054 `_, fixes `#21045 `_, by GaΓ«tan Gilbert). SSReflect ^^^^^^^^^ - **Changed:** rewrite pattern selection algorithm made more robust in face of changes to implicit arguments shape. This changes can result in a different pattern selection in some corner cases. The option `Set SsrMatching LegacyFoUnif` can be used to obtain the previous behavior when repairing scripts (`#20707 `_, fixes `#16763 `_, by Enrico Tassi with help from Georges Gonthier, Pierre Roux and Quentin Vermande). - **Changed:** level of notation ``'Under[ _ ]`` in `ssrunder.v` from 8 to 0 (`#21107 `_, by Pierre Roux). - **Changed:** level of ``tactic => intro_pattern`` notation to a left-associative notation level with higher priority than level 3, rather than being repeated in levels 3 (right-associative) and 4 (left-associative) (`#21244 `_, by Pierre Roux). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** Default patterns displayed by :cmd:`Print HintDb` now show pattern holes using the name from the original theorem (e.g. :n:`?n` instead of :n:`?M3135`) (`#20827 `_, by Jim Fehrle). - **Changed:** :cmd:`Show` and :n:`Show goalnum` now show diffs (if enabled) in rocqtop. Added :cmd:`Show Diffs` :n:`goalname` to show diffs for a named goal. For emacs support; still no diffs shown for these commands in other IDEs (`#21103 `_, fixes `#20793 `_, by Jim Fehrle). - **Changed:** `_rec` schemes are not defined using `_rect` schemes anymore. In particular `eq_rec` is not defined using `eq_rect` (`#21241 `_, by GaΓ«tan Gilbert). - **Changed:** Generalize :cmd:`Register Scheme` from constants to constants, or inductive types, or constructors (`#21326 `_, by Thomas Lamiaux). - **Changed:** :cmd:`Derive` names the existential variables it generates according using the name of the constant they will define (e.g. `Derive X in X as x` binds `X` to an evar named `?X` instead of an anonymous evar (which would print as `?Goal`)) (`#21332 `_, by GaΓ«tan Gilbert). .. _92mlapi: - **Changed:** Generalized universe polymorphism flag structure (ML API change) (`#21419 `_, by Matthieu Sozeau). - **Changed:** :cmd:`Print Assumptions` now recurses into the types of axioms (`#21437 `_, fixes `#21436 `_, by Jason Gross). - **Changed:** :cmd:`Print Assumptions`, :cmd:`Print Opaque Dependencies`, :cmd:`Print Transparent Dependencies`, and :cmd:`Print All Dependencies` now accept lists of globals instead of single references (`#21477 `_, by Jason Gross). - **Removed:** flag `Loose Hint Behavior` which appears to have behaved as `Strict` regardless of how it was set for the last few versions (`#20698 `_, by GaΓ«tan Gilbert). - **Deprecated:** implicitly creating hint databases when declaring hints. (`#21114 `_, fixes `#4117 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** creating implicitly rewrite hint databases through the :cmd:`Hint Rewrite` command. One must now do it explicitly through :cmd:`Create Rewrite HintDb` (`#21206 `_, by Pierre-Marie PΓ©drot). - **Added:** Additional documentation of Create HintDb (discriminated), proof search tactic performance, matching process and hint transparency (`#19761 `_, by Jim Fehrle). .. _92scheme: - **Added:** attribute :attr:`schemes` to control automatic scheme declaration (`#21163 `_, fixes `#19480 `_, by GaΓ«tan Gilbert). .. _92elimparsing: - **Added:** Parsing of elimination constraints in prenex polymorphic definitions as well as in constraints declaration :g:`Constraint s1 -> s2.` (`#21195 `_, by Johann Rosain). - **Added:** a :cmd:`Create Rewrite HintDb` command to explicitly declare rewrite hint databases (`#21203 `_, by Pierre-Marie PΓ©drot). - **Added:** :cmd:`Scheme Rewriting` to explicitly declare rewriting schemes for a given inductive (`#21248 `_, by GaΓ«tan Gilbert). .. _92printfully: - **Added:** :flag:`Printing Fully Qualified` to print all names (global references, modules, module types, universes, etc) using fully qualified paths (`#21443 `_, fixes `#11852 `_, by Jason Gross). - **Fixed:** Properly test for duplicate names in mutual blocks (`#21082 `_, fixes `#20766 `_, by Yann Leray). - **Fixed:** Fix Derive command to handle dependent types correctly (`#21313 `_, fixes `#21292 `_, by Jason Gross). - **Fixed:** fallback printing of inductives using ```` should be rarer (it should in any case only happen rarely from module errors) (`#21473 `_, by Jason Gross). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** in ``-emacs`` mode, goals are no longer spontaneously printed (`#21038 `_, fixes `#21035 `_, by Pierre Roux). - **Changed:** `rocq compile` does not create empty `.vos` and `.vok` files anymore, their creation is left to the makefile generated by `rocq makefile`. Other build system may choose to create these empty files at their discretion (`#21548 `_, by GaΓ«tan Gilbert). - **Added:** :ref:`rocq doc ` replaces `@@TITLE@@` with the page title in custom HTML headers (`#20907 `_, fixes `#2511 `_, by GaΓ«tan Gilbert). - **Fixed:** ``rocq dep`` now handles non .vo dependencies from the ``ROCQPATH`` environment variable (`#20878 `_, fixes `#20835 `_, by GaΓ«tan Gilbert). Corelib ^^^^^^^ - **Changed:** Level of ``_~0`` and ``_~1`` reserved notations (used for positive numbers) from level 7 to level 1 (`#17876 `_, by Pierre Roux). - **Changed:** level of postfix notations in `PrimArray` to level 1 (`#21211 `_, by Pierre Roux). - **Changed:** rewriting schemes for `eq` and `eq_true` are explicitly declared in `Init.Logic` instead of dynamically when a tactic needs them. For instance `EqdepFacts.internal_eq_rew_dep` does not exist anymore and instead `Logic.eq_rew_dep` is available (`#21248 `_, by GaΓ«tan Gilbert). - **Added:** a slightly more general variant of Fix_eq which is sometimes more convenient (`#20018 `_, by Owen Conoly). - **Fixed:** primitive array axioms (in `ArrayAxioms`) are universe polymorphic (they were inadvertently turned monomorphic in the stdlib split) (`#21744 `_, by GaΓ«tan Gilbert). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Extraction ^^^^^^^^^^ - **Fixed:** Added "effect" as a recognized keyword for ocaml extraction (`#21350 `_, fixes `#21176 `_, by Dan Rostovtsev). Miscellaneous ^^^^^^^^^^^^^ - **Changed:** use `Gc.ramp_up` while executing :cmd:`Require` on OCaml 5.4 and later. This should partially mitigate the performance lost since OCaml 4.14 (`#21306 `_, by GaΓ«tan Gilbert). Version 9.1 ----------- .. contents:: :local: :depth: 1 Summary of changes ~~~~~~~~~~~~~~~~~~ We highlight some of the most impactful changes here: - fixed incorrect guard checking leading to inconsistencies (multiple PRs) - sort polymorphic universe instances :ref:`should now be written <91sortpolysyntax>` as `@{s ; u}` instead of `@{s | u}` - :ref:`fixed <91ltac2notationfix>` handling of notation variables for ltac2 in notations (i.e. `Notation "'foo' x" := ltac2:(...)`) - :ref:`Support <91refinedef>` for :attr:`refine` attribute in :cmd:`Definition` - Rocq can be compile-time configured to be :ref:`relocatable <91relocatable>` - extraction :ref:`handles <91extractsortpoly>` sort polymorphic definitions See the `Changes in 9.1.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Rocq's `reference manual for 9.1 `_, documentation of the 9.1 `corelib `__ and `developer documentation of the 9.1 ML API `_ are also available. ThΓ©o Zimmermann, with help from Jason Gross and GaΓ«tan Gilbert, maintained `coqbot `__ used to run Rocq's CI and other pull request management tasks. Jason Gross maintained the `bug minimizer `_ and its `automatic use through coqbot `_. Ali Caglayan, Emilio JesΓΊs Gallego Arias, Rudi Grinberg and Rodolphe Lepigre maintained the `Dune build system for OCaml and Coq/Rocq `_ used to build the Rocq Prover itself and many Rocq projects. The `opam repository `_ for Rocq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. The up-to-date list of packages is `available on the Rocq website `_. Erik Martin-Dorel maintained the `Rocq Docker images `_ and the `docker-keeper `_ compiler used to build and keep those images up to date (note that the tool is not Rocq specific). Erik Martin-Dorel and ThΓ©o Zimmermann maintained the `docker-coq-action `_ container action (which is applicable to any opam project hosted on GitHub). Cyril Cohen, Vincent Laporte, Pierre Roux and ThΓ©o Zimmermann maintained the `Nix toolbox `_. The docker-coq-action and the Nix toolbox are used by many Rocq projects for continuous integration. Rocq 9.1 was made possible thanks to the following 24 reviewers: Florian Angeletti, Ali Caglayan, Cyril Cohen, Pierre Courtieu, Jim Fehrle, GaΓ«tan Gilbert, Jason Gross, Emilio JesΓΊs Gallego Arias, Jan-Oliver Kaiser, Thomas Lamiaux, Rodolphe Lepigre, Erik Martin-Dorel, Guillaume Melquiond, Patrick Nicodemus, Pierre-Marie PΓ©drot, Pierre Rousselin, Pierre Roux, Gabriel Scherer, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi, ThΓ©o Winterhalter and ThΓ©o Zimmermann. See the `Rocq Team `_ page for more details on Rocq's development teams. The 45 contributors to the 9.1 version are: Soudant, ypopovitch, Reynald Affeldt, Wassim Ait-Moussa, David Allsopp, Christian Benedict Smit, FrΓ©dΓ©ric Besson, Mathis Bouverot, Ali Caglayan, Jean Caspar, Benedict Christian Smit, Cyril Cohen, Pierre Courtieu, Julien Cretin, Jian Fang, Jim Fehrle, GaΓ«tan Gilbert, Jason Gross, Dario Halilovic, Hugo Herbelin, Elyes Jemel, Emilio JesΓΊs Gallego Arias, Jan-Oliver Kaiser, Kacper Korban, Lucie Lahaye, Thomas Lamiaux, Rodolphe Lepigre, Yann Leray, Kenji Maillard, Erik Martin-Dorel, Patrick Nicodemus, Charles Norton, Pim Otte, Pierre-Marie PΓ©drot, Josselin Poiret, Johann Rosain, Pierre Rousselin, Pierre Roux, RadosΕ‚aw Rowicki, Benedict Smit, Bastien Sozeau, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi and ThΓ©o Zimmermann. The Rocq community at large helped improve this new version via the GitHub issue and pull request system, the `Discourse forum `__ and the `Rocq Zulip chat `_. GaΓ«tan Gilbert and Pierre-Marie PΓ©drot are the release managers of Rocq 9.1. This release is the result of 397 merged PRs, closing 66 issues. | Nantes, September 2025 | GaΓ«tan Gilbert and Pierre-Marie PΓ©drot for the Rocq development team Changes in 9.1.0 ~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** Guard checking forgot to check non principal arguments of a fixpoint for unguarded uses of the fixpoint leading to an inconsistency (`#20415 `_, fixes `#20413 `_, by GaΓ«tan Gilbert). - **Fixed:** inconsistency from incomplete guard checking with nested matches (`#20457 `_, fixes `#20455 `_, by GaΓ«tan Gilbert). - **Fixed:** inconsistency from incorrect reduction across a fixpoint during guard checking (`#20648 `_, fixes `#20555 `_, by Yann Leray). - **Fixed:** Wrong context management during rewrite rule reduction (`#20729 `_, fixes `#20728 `_, by Yann Leray). - **Fixed:** Fix guard checker making propositional extensionality inconsistent (`#21050 `_, fixes `#21053 `_, by Yann Leray). - **Fixed:** substitution of functor delta-resolvers when strengthening. The previous code was only substituting the inner delta resolvers and ignoring the codomain of functors. In particular this was generating ill-formed constants whose canonical component was pointing to a bound name that did not exist in the global environment, leading to an inconsistency (`#21057 `_, fixes `#21051 `_, by Pierre-Marie PΓ©drot). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _91sortpolysyntax: - **Deprecated:** in :ref:`sort polymorphic ` instances, separating sorts from universes using `|` instead of `;` (the later being possible since this version) (`#20635 `_, by GaΓ«tan Gilbert). - **Added:** in :ref:`sort polymorphic ` instances, sorts can be separated from universes using `;` instead of `|`. This is less ambiguous as `|` is also used to separate universes and constraints when declaring sort polymorphic objects, and in such declarations when constraints are unspecified it allows omitting the `|` (`Definition foo@{s;u} := ...` instead of `Definition foo@{s|u|+} := ...`) (`#20635 `_, by GaΓ«tan Gilbert). - **Fixed:** Anomaly `List.chop` in the presence of projections with not enough argument scopes (`#20945 `_, fixes `#20940 `_, by Hugo Herbelin). - **Fixed:** Anomaly `List.chop` with too many projection parameters in an abbreviation (`#20946 `_, fixes `#15815 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Changed:** The `Specif` notations (`exists x : A, P`, `{ x : A | P }`, `{ x : A & P }`, etc) locally opens `type_scope` for the second component (`P`). This makes eg `{ x & type_1 * type_2 }` work even when `nat_scope` is opened instead of interpreting `*` as peano multiplication (`#20294 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Enable Notation` and :cmd:`Disable Notation` do not take effect in deep imports (i.e. when a parent of their origin module is imported) (`#20484 `_, by GaΓ«tan Gilbert). Tactics ^^^^^^^ - **Changed:** the :tacn:`abstract` tactic now only registers a name for the sublemma after the whole tactic block has run, i.e. after a dot. In particular, the sublemma cannot be accessed by its name while the tactic call has not returned (`#14937 `_, by Pierre-Marie PΓ©drot). - **Changed:** the congruence tactic now can handle some dependently typed constructor fields. The field's type has to be composed of terms occuring globally or projectable from parameters or indices of the inductive type (`#19700 `_, by Benedict Christian Smit). - **Changed:** setoid rewriting now rewrites under primitive projections. In rare cases (see for instance `#20575 `_), some rewrite that used to accidentally work will now correctly fail (`#19811 `_, by Josselin Poiret and Pierre-Marie PΓ©drot). - **Changed:** output of :cmd:`Print Instances` better matches the actual behaviour when an instance is declared multiple times with different priorities (`#20486 `_, by GaΓ«tan Gilbert). - **Added:** a new :flag:`Rewrite Output Constraints` flag and :ref:`documented ` its use for debugging typeclass resolution failures in setoid rewriting (`#20476 `_, by Matthieu Sozeau). Ltac language ^^^^^^^^^^^^^ - **Changed:** :cmd:`Ltac` redefinitions (`Ltac ::=`) understand :attr:`export`. Previously :attr:`global` and the default locality meant the redefinition would take effect at Require time and when importing any surrounding module. Now :attr:`global` means it takes affect at Require time, :attr:`export` when the current module (but not its parents) is imported, and the default is equivalent to the combination of :attr:`global` and :attr:`export` (`#20054 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Ltac` redefinitions (`Ltac foo ::= ...`) are not undone by importing the module containing the original definition. To get the previous behaviour, add `Ltac foo ::= orig_def.` after the original definition `Ltac foo := orig_def.` (`#20391 `_, by GaΓ«tan Gilbert). - **Changed:** Named goals can now appear in any goal selector list (`#20511 `_, fixes `#12838 `_, by Dario Halilovic). Ltac2 language ^^^^^^^^^^^^^^ - **Changed:** Ltac2 does not depend on the prelude (i.e. it is compiled with `-noinit`). It still depends on `Corelib.Init.Ltac` due to the interoperation with Ltac1 (`#20387 `_, by GaΓ«tan Gilbert). - **Changed:** the documentation and error messages do not use the term "scope" to describe Ltac2 :ref:`syntactic_classes` (`#20504 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Ltac2 Set` only takes effect with shallow imports, i.e. `Import Foo` will not run a mutation from (non exported) inner module `Foo.Bar` (`#20516 `_, by GaΓ«tan Gilbert). - **Added:** A file `Ltac1CompatNotations` for Ltac2 Notations reproducing Ltac1 parsing of tactics, that can be harmful to parsing, and produce bad error messages. (`#20569 `_, by Thomas Lamiaux). - **Added:** `rename` (in `Ltac1CompatNotations`), `eassumption`, `cycle`, and `exfalso` Ltac2 notations (`#20197 `_, by Josselin Poiret). - **Added:** ``Ltac2.Constr.is_string``, ``Ltac2.Constr.is_sort`` (`#20088 `_, by Jason Gross). - **Added:** ``Ltac2.Constr.decompose_app_list``, ``Ltac2.Constr.decompose_app`` (`#20089 `_, by Jason Gross). - **Added:** ``Ltac2.Option.is_some``, ``Ltac2.Option.is_none``, ``Ltac2.Option.compare``, ``Ltac2.Option.join``, ``Ltac2.Option.iter`` (`#20184 `_, by Jason Gross). - **Added:** `empty` and `add` in `Ltac2.Fresh.Free`, `next` in `Ltac2.Fresh`. `Ltac2.Fresh` operations should also be faster (`#20220 `_, by GaΓ«tan Gilbert). - **Added:** Enable use of (open\_)lconstr inside Ltac2 Notation command (`#20430 `_, by Pim Otte). - **Added:** API functions for inductive types - `Ind.nparams`, `Ind.nparams_uniform`, `Ind.constructor_nargs`, `Ind.constructor_ndecls`, `Constr.Case.inductive` (`#20475 `_, fixes `#10940 `_, by Patrick Nicodemus). - **Added:** format specifiers `%A` to use unthunked printers and `%m` for already-formatted messages. Typically, instead of `printf "foo: %a" (fun () v => print_thing v) v` we can now write `printf "foo: %A" print_thing v` or `printf "foo: %m" (print_thing v)` (`#20498 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 type for reduction expressions (`#20543 `_, by RadosΕ‚aw Rowicki, with review of Pierre-Marie PΓ©drot and GaΓ«tan Gilbert and Jason Gross). - **Added:** Ported `rewrite_strat` to Ltac2 and added the `Rewrite.Strategy` module for describing rewrite strategies (`#20544 `_, fixes `#20482 `_, by RadosΕ‚aw Rowicki with review of Jason Gross and Pierre-Marie PΓ©drot and GaΓ«tan Gilbert). - **Added:** ``Ltac2.Message.empty`` (`#20547 `_, by Elyes Jemel). - **Added:** conversion tests to Unification - `Unification.conv`, `Unification.conv_current`, `Unification.conv_full` (`#20649 `_, fixes `#20579 `_, by Thomas Lamiaux). - **Added:** antiquotation `$hyp:id` in terms for dynamically named hypotheses, i.e. `let x := @y in constr:($hyp:x)` is equivalent to `constr:(&y)` (`#20656 `_, by GaΓ«tan Gilbert). .. _91ltac2notationfix: - **Fixed:** Ltac2 in terms in notations is more aware of the notation variables it uses, providing early failure when the variable is instantiated with an invalid term, preventing a spurious warning when a variable that cannot be instantiated is unused, and preventing exponential blowups from copying unused data (`#20313 `_, fixes `#17833 `_ and `#20188 `_ and `#20305 `_, by GaΓ«tan Gilbert). SSReflect ^^^^^^^^^ - **Changed:** `%FUN` now delimits scope `function_scope` rather than `fun_scope` in `ssrfun.v` (`#20478 `_, by Pierre Roux). - **Removed:** scope `fun_scope` from `ssrfun.v` that was deprecated since 8.20, use `function_scope` instead (`#20478 `_, by Pierre Roux). - **Deprecated:** `idempotent` in `ssrfun.v`, use `idempotent_op` instead (`#20478 `_, by Pierre Roux). - **Added:** definitions `injective2`, `idempotent_op` and `idempotent_fun` and lemmas `omap_id`, `eq_omap`, `inj_omap`, `omapK`, `inr_inj` and `inl_inj` in `ssrfun.v` (`#20478 `_, by Pierre Roux). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** commands taking a tactic argument (e.g. :cmd:`Hint Extern`) now follow :opt:`Default Proof Mode` instead of hardcoding Ltac1 (`#19690 `_, fixes `#13784 `_, by GaΓ«tan Gilbert). - **Changed:** :opt:`Printing Depth` completely skips subterms beyond the given depth. In general the formatter depth is higher than the term depth, so there is no visible change, but some notations print subterms without increasing the formatting depth in which case you may need to increase the printing depth to avoid `...` (`#20275 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Search` ignores lemmas declared with :attr:`local` unless new flag :flag:`Search Blacklist Locals` is unset (`#20349 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Search` now accepts open modules, including the current file with the `in`, `inside` and `outside` filters. (`#20733 `_, fixes `#14010 `_, by Pierre Rousselin, with a lot of help by GaΓ«tan Gilbert). - **Removed:** flag `Lia Enum`, which did nothing (`#20640 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Sort` to declare global or section-scoped sort qualities (`#18615 `_, by Kenji Maillard). - **Added:** :cmd:`Number Notation` and :cmd:`String Notation` understand parsers which may produce error messages (`#20107 `_, fixes `#20042 `_, by GaΓ«tan Gilbert). .. _91refinedef: - **Added:** support for the :attr:`refine` attribute to definitions and (co)fixpoints (`#20355 `_, fixes `#20302 `_, by Yann Leray). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** `rocq timelog2html` now needs package `rocq-devtools` to be installed (`#20169 `_, by GaΓ«tan Gilbert). - **Added:** error on ambiguous :cmd:`Require`. Rocq used to silently select a file when ambiguous :cmd:`Require`\s came from different loadpaths, for instance different fields of the ``ROCQPATH`` environment variable (`#20601 `_, fixes `#20587 `_, by GaΓ«tan Gilbert). - **Fixed:** `rocq dep` implicitly adds `-I $rocq-runtime/..` after the explicit `-I` instead of before (where `$rocq-runtime` is the expected location of the rocq-runtime package). This means that if a local plugin (whose META is in an explicit `-I` path) is installed next to rocq-runtime, `rocq dep` will emit a dependency on the local version instead of the installed version (`#20393 `_, by GaΓ«tan Gilbert). RocqIDE ^^^^^^^ - **Changed:** default character encoding is UTF8 (it was locale dependent on non-windows OSes), and when the configured encoding is not UTF8 RocqIDE will attempt to convert input files even if they are already valid UTF8 (`#20256 `_, fixes `#11526 `_, by GaΓ«tan Gilbert). - **Added:** an option to control the maximum length of the message view in RocqIDE (`#20597 `_, fixes `#20420 `_, by Pierre-Marie PΓ©drot). Corelib ^^^^^^^ - **Added:** type `result` in `Corelib.Datatypes`, equivalent to `sum` but with a name fitting possibly-failing computations (`#20107 `_, by GaΓ«tan Gilbert). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** minimum supported OCaml version is now 4.14.0 (instead of 4.09.0), and minimum supported OCamlfind version is now 1.9.1 (instead of 1.8.1) (`#20576 `_, by GaΓ«tan Gilbert). .. _91relocatable: - **Added:** Rocq can be compile-time configured to be relocatable, using `./configure -relocatable` instead of e.g. `./configure -prefix /some/path`. See :ref:`system_config` for an explanation of how Rocq uses its configured installation paths (`#19901 `_, by GaΓ«tan Gilbert). - **Added:** Experimental support for native Windows builds. Rocq can now build and run under a native Windows environment using the new native Windows support in Opam 2.3. This setup is tested in CI, running a large part of the test suite. Beware this support is still experimental, and some problem may arise on Unix-specific tools. Note that RocqIDE is still not supported (c.f. `#20631 `_) (`#20464 `_, by Emilio Jesus Gallego Arias, GaΓ«tan Gilbert, David Allsopp, Ali Caglayan, Jason Gross, the Opam team, the @setup-ocaml team, the OCaml team). - **Fixed:** Bad interaction between dune, `rocq dep`, and local opam directory switches (`#20437 `_, fixes `#20422 `_, by Rodolphe Lepigre). Extraction ^^^^^^^^^^ .. _91extractsortpoly: - **Fixed:** extraction handles sort polymorphic definitions (`#20655 `_, by Pierre-Marie PΓ©drot). Miscellaneous ^^^^^^^^^^^^^ - **Added:** plugin tutorial for extending Ltac2 (`#20670 `_, by GaΓ«tan Gilbert). Changes in 9.1.1 ~~~~~~~~~~~~~~~~ .. contents:: :local: Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** anomaly when defining a sort polymorphic inductive without enabling :flag:`Universe Polymorphism` (`#21479 `_, fixes `#21476 `_, by Yann Leray) Miscellaneous ^^^^^^^^^^^^^ - **Fixed:** compatibility with OCaml 5.4 with warnings as errors (`#21261 `_, by Yann Leray) - **Fixed:** compatibility with OCaml 5.5 with warnings as errors (`#21584 `_, by Yann Leray and Kate Deplaix) - **Changed:** various documentation updates Version 9.0 ----------- .. contents:: :local: :depth: 1 Summary of changes ~~~~~~~~~~~~~~~~~~ The Rocq Prover version 9.0 is the first Rocq Prover release after the renaming from The Coq Proof Assistant. The Rocq Prover 9.0 command line interface is backwards compatible with Coq 8.20, providing compatibility shims so that developments depending on Coq can be easily ported, see `Porting to The Rocq Prover`_ for details. The 9.0 version is based on a new single binary `rocq` that dispatches commands to previously separate binaries, a split and renaming of the standard library to `Stdlib` and improvements to the handling of template-polymorphism, bringing it closer to a complete subsumption by sort polymorphism. We highlight some of the most impactful changes here: - "The Rocq Prover" is the new official name of the project. We leave to users the choice of renaming their projects to reflect this change, see `Renaming Advice`_. The Rocq Prover comes with a new visual identity and website, see `The Rocq Prover Website`_. - A single `rocq` binary dispatches commands for compilation, read-eval-print-loop, documentation building, dependency computation, etc. See :ref:`therocqcommands`. It corresponds to the `rocq-runtime` `opam package `_. This is a bare-bones package that does not provide any Gallina code. - The `Coq` standard library has been :ref:`split <90stdlib>` into two libraries: - A `Corelib` library (the `rocq-core` opam package). This is an extended prelude, which is enough to run Rocq tactics and contains the `Ltac2` library and bindings for primitive types (integers, floats, arrays and strings). - An `Stdlib` library (the `rocq-stdlib` opam package). The `Stdlib` is now maintained out of the main `rocq` repository. We welcome maintainers and contributors to the `new repository `_. A specific call for contributions will be sent soon. Notable breaking changes: - The legacy loading mode for plugins has been :ref:`removed `. See the `Changes in 9.0.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Rocq's `reference manual for 9.0 `_, documentation of the 9.0 `core `_ and `standard `_ libraries, `reference manual of the 9.0 standard library `_ and `developer documentation of the 9.0 ML API `_ are also available. ThΓ©o Zimmermann, with help from Jason Gross and GaΓ«tan Gilbert, maintained `coqbot `_ used to run Coq's CI and other pull request management tasks. Jason Gross maintained the `bug minimizer `_ and its `automatic use through coqbot `_. Ali Caglayan, Emilio JesΓΊs Gallego Arias, Rudi Grinberg and Rodolphe Lepigre maintained the `Dune build system for OCaml and Coq/Rocq `_ used to build the Rocq Prover itself and many Rocq projects. The `opam repository `_ for Rocq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. The up-to-date list of packages is `available on the Rocq website `_. Erik Martin-Dorel and Jaime Arias maintained the `Rocq Docker images `_. Erik Martin-Dorel maintained the `docker-keeper `_ compiler used to build and keep those images up to date (note that the tool is not Rocq specific). Erik Martin-Dorel and ThΓ©o Zimmermann maintained the `docker-coq-action `_ container action (which is applicable to any opam project hosted on GitHub). Cyril Cohen, Vincent Laporte, Pierre Roux and ThΓ©o Zimmermann maintained the `Nix toolbox `_. The docker-coq-action and the Nix toolbox are used by many Rocq projects for continuous integration. Rocq 9.0 was made possible thanks to the following 27 reviewers: Yves Bertot, Ali Caglayan, Tej Chajed, Andres Erbsen, Jim Fehrle, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Jason Gross, Samuel Gruetter, Hugo Herbelin, Thomas Lamiaux, Olivier Laurent, Rodolphe Lepigre, Erik Martin-Dorel, Guillaume Melquiond, Guillaume Munch-Maccagnoni, Karl Palmskog, Pierre-Marie PΓ©drot, Pierre Rousselin, Pierre Roux, Marcello Seri, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Romain Tetley, Oliver Turner and ThΓ©o Zimmermann. See the `Rocq Team `_ page for more details on Rocq's development teams. The 48 contributors to the 9.0 version are: Jean Abou Samra, Tanaka Akira, David Allsopp, FrΓ©dΓ©ric Besson, Mathis Bouverot, Sylvain Chiron, Cyril Cohen, Lucas Donati, Andrej Dudenhefner, Arya Elfren, Andres Erbsen, Siegmentation Fault, Jim Fehrle, GaΓ«tan Gilbert, Tomaz Gomes Mascarenhas, Jason Gross, Hugo Herbelin, Florent Hivert, Daniil Iaitskov, Emilio JesΓΊs Gallego Arias, Jan-Oliver Kaiser, Rodolphe Lepigre, Yann Leray, Felix Loyau-Kahn, Erik Martin-Dorel, Guillaume Melquiond, Guillaume Munch-Maccagnoni, Aleksandar Nanevski, Charles Norton, Karl Palmskog, Pierre-Marie PΓ©drot, Pierre Rousselin, Pierre Roux, Kazuhiko Sakaguchi, Gabriel Scherer, Marcello Seri, Benny Smit, Michael Soegtrop, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi, Oliver Turner, Quentin Vermande, Daneel Yaitskov, Remzi Yang, Tan Yee Jian and ThΓ©o Zimmermann. The Coq/Rocq community at large helped improve this new version via the GitHub issue and pull request system, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 9.0's development spanned 7 months from the release of Coq 8.20.0. Pierre-Marie PΓ©drot and Matthieu Sozeau are the release managers of Rocq 9.0. This release is the result of 491 merged PRs, closing 68 issues. | Nantes, March 2025 | Pierre-Marie PΓ©drot and Matthieu Sozeau for the Rocq development team Porting to The Rocq Prover ~~~~~~~~~~~~~~~~~~~~~~~~~~ The Rocq Prover version 9.0 includes compatibility shims that make it possible to invoke it through legacy Coq commands: `coq-tex`, `coq_makefile`, `coqchk`, `coqdoc`, `coqpp`, `coqtop`, `coqwc`, `coqc`, `coqdep`, `coqnative`, `coqtimelog2html`, `coqtop.byte`, `coqworkmgr`. When using `opam`, this compatibility layer is provided by the packages `coq-core`, `coq-stdlib` and `coq`. In this setting, nothing needs to be changed to the build systems of existing projects to compile with Rocq 9.0 (aliased as "Coq 9.0"). You should expect warnings that the standard library previously under namespace `Coq` has been renamed to `Stdlib`. See `this entry `_ from the Standard Library's changelog for the suggested workflow to port theories. There are important changes to consider for building plugins and libraries: - To be future-proof, projects based on `coq_makefile` can be ported to not rely on the compatibility layer anymore. To do so, one must replace uses of `coq_makefile` with :ref:`rocq makefile `, which will directly call the new `rocq` binary without relying on the compatibility shims. - If using `dune` to :ref:`build ` a Rocq project, you will still need the compatibility shim for `coq-core` so that `dune`'s Coq language extension functions correctly. Regarding packaging: - Opam packages that depend on the compatibility shims should remain named as `coq-*`, whereas ported packages should be named `rocq-*`, with the `coq` dependency being replaced by a `rocq-core` and `rocq-stdlib` dependency (unless your package does not depend on the stdlib), but **not** `rocq-prover` which is only a user-oriented metapackage. - Similarly, Nix packages that use the compatibility shims can be kept in `coqPackages` (and can keep depending on `coq`), whereas ported packages can be added in `rocqPackages`, depending on `rocq-core`. In both cases, when a `rocq` port is done, a `coq` metapackage can be kept, simply depending on the new `rocq` package and `coq`. Renaming Advice ~~~~~~~~~~~~~~~ We have applied the `renaming `_ from the Coq Proof Assistant to The Rocq Prover in this version, and officialy supported projects in the `Rocq organization `_ will be renamed in the future. The Rocq Development Team's official position on renaming of projects *it does not officially maintain* is to let their authors do as they wish. We just note that the new identity is quite compatible with existing Rooster references. However, we encourage existing and forthcoming projects to adopt the new logo, its colors and fonts, see the `identity guidelines `_ for more information. The Rocq Prover Website ~~~~~~~~~~~~~~~~~~~~~~~ The Rocq Prover comes with a new `website `_ which was developped by Matthieu Sozeau, Nicolas Tabareau and ThΓ©o Zimmermann in collaboration with Bastien Sozeau of the `Noir Blanc Rouge `_ type foundry. The new website is a fork of the `OCaml.org `_ website developed by `Tarides `_. The Rocq development team is thankful for their help and for open-sourcing their website. It includes full support for the `Rocq package archive `_, a responsive design and easy contributions through markdown files. The new identity, customized fonts and logo were designed by Bastien Sozeau, consulting for the Rocq development team. The logo is released under the UNLICENSE open-source `license `_ and customized 3rd-party fonts are released under open-source `licences `_. The website is deployed automatically using a custom `deployer `_ developed by Matthieu Sozeau. The deployer keeps the website up-to-date with the GitHub repositories of the `website `__ and `documentation `_. Its code is accessible on `GitHub `_. Changes in 9.0.0 ~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Changed:** large performance improvements in kernel checking of terms with repeated subterms (`#19160 `_, by GaΓ«tan Gilbert) - **Changed:** the criteria for a parameter to be considered template in a template inductive type. For a level to be template, it must now appear only once in the context of parameters, and only as the return sort of the arity of some parameter. Furthermore, it may appear neither in the indices of the inductive type nor in the type of its constructors. Finally, a template level appearing in the return sort of the inductive type must have a zero increment (`#19250 `_, `#19254 `_, `#19263 `_, by Pierre-Marie PΓ©drot). - **Changed:** the kernel typing rules for template polymorphic inductive types do not require anymore adding global constraints when applied enough. Rather, template polymorphic inductive types are now a special kind of universe polymorphic inductive types that do not need explicit instances and can handle some amount of algebraic universe levels. The new rules are strictly more general than the previous ones and thus backwards compatible (`#19262 `_, by Pierre-Marie PΓ©drot). - **Removed:** the kernel always produces an error when given terms with bad relevances instead of emitting the default-error `bad-relevance` warning (which is now only used by the higher layers) (`#19164 `_, by GaΓ«tan Gilbert). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Typeclasses queries of classes that are declared with the options `Typeclasses Strict Resolution` and `Typeclasses Unique Instances` enabled are resolved independently of other queries, allowing them to succeed even when the remaining queries fail (`#18762 `_, by Jan-Oliver Kaiser). - **Changed:** More systematic early check of `@{univs}`-like universe declarations at the time of declaring the statement of an interactive definition/theorem (`#18960 `_, by Hugo Herbelin). - **Changed:** The syntax :n:`Derive x SuchThat type As name` is deprecated and replaced by :n:`Derive x in type as name` which itself is generalized into :n:`Derive open_binders in type as name`, so that several names, and possibly types to these names, can be given (`#19295 `_, by Hugo Herbelin). - **Changed:** `match` elaboration can unify sort quality variables to make an elimination valid (`#19329 `_, fixes `#19327 `_, by GaΓ«tan Gilbert). - **Changed:** ``:>`` in :token:`of_type_inst` now always declares coercions. The previous behavior, deprecated since 8.18, was to declare typeclass instances instead, when used in records declared with the :cmd:`Class` keyword. Look at the :ref:`previous changelog entries <819_changes_spec_language>` about former warnings `future-coercion-class-constructor` and `future-coercion-class-field` for advice on how to update your code (`#19519 `_, by Pierre Roux). - **Changed:** The unification algorithm does not solve unification problems of the form `proj _ ~ _` using canonical structures when the LHS reduces or is ground (`#19611 `_, by Quentin Vermande). - **Changed:** When unification fails to instantiate an evar because of a problem that occurs under a beta-redex, we reduce this beta-redex and try again (`#19833 `_, by Quentin Vermande). - **Added:** Ability to hide the quantification over the decreasing argument of a fixpoint under a definition, with application to declaring fixpoints as instance of a class (`#19296 `_, fixes `#7913 `_, by Hugo Herbelin). - **Fixed:** :cmd:`Derive` now supports :cmd:`Admitted` (`#19092 `_, fixes `#18951 `_, by Hugo Herbelin). - **Fixed:** Mishandling of let binders in `Program Fixpoint` (`#19257 `_, fixes `#16906 `_, by Hugo Herbelin). - **Fixed:** Pattern-matching in :attr:`Program` mode now supports inductive types using :ref:`local definitions ` in their declaration (`#19773 `_, fixes `#10407 `_, by Hugo Herbelin). - **Fixed:** Anomaly in :cmd:`Function` when a well-founded relation had not the expected type (`#19775 `_, fixes `#12417 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Fixed:** Recognized all Unicode non-spacing marks as valid identifier characters (`#19693 `_, fixes `#19512 `_, by Guillaume Melquiond). Tactics ^^^^^^^ - **Changed:** The reduction tactic :tacn:`hnf` becomes insensitive to the :g:`simpl never` status of constants, as prescribed in the reference manual; this can exceptionally impact the behavior of :tacn:`intros` on goals defining an implicative or universally quantified statement by recursion (`#18580 `_, by Hugo Herbelin). - **Changed:** `Ncring_tac.extra_reify` is expected to return `tt` on failure and the reification result on success, instead of `(false, anything)` on failure and `(true, result)` on success (this only matters to users overriding it to extend the Ncring reification) (`#19501 `_, by GaΓ«tan Gilbert). - **Removed:** the deprecated `gintuition` tactic (`#19704 `_, by Pierre-Marie PΓ©drot). - **Removed:** `dfs eauto` tactic, which was deprecated in 8.16 (`#19817 `_, by Jim Fehrle). - **Added:** The :flag:`Info Micromega` flag (unset by default) makes :tacn:`lia`, :tacn:`lra`, :tacn:`nia` and :tacn:`nra` print the names of hypotheses used by the proof (`#19703 `_, by FrΓ©dΓ©ric Besson). - **Fixed:** Refolding of constants marked as :g:`simpl never` in position of argument of a destructor in :tacn:`simpl`; note that this may occasionally cause some calls to :tacn:`simpl` to satisfy more scrupulously :g:`simpl never` and to stop reducing further in subterms that are *not* in position of argument of a destructor, as specified by :g:`simpl never` (`#18591 `_, fixes `#16040 `_, by Hugo Herbelin). - **Fixed:** `Set Typeclasses Strict Resolution` is no longer ignored in `typeclasses eauto with ` (`#19436 `_, fixes `#15432 `_, by Jan-Oliver Kaiser). - **Fixed:** Unbound variables were sometimes generated when a metavariable of a theorem given to :tacn:`apply` occurred in the type of the theorem under a :n:`fun` (`#19769 `_, fixes `#17314 `_, by Hugo Herbelin). - **Fixed:** `cbn` now considers primitive literals (integers, floats, arrays, strings) "constructors", i.e. they now satisfy the `!` modifier in `Arguments` (`#20004 `_, fixes `#20003 `_, by Jan-Oliver Kaiser). Ltac2 language ^^^^^^^^^^^^^^ - **Deprecated:** `Ltac2.Constr.occur_between` and `occurn` whose return values are the opposite of that implied by their names (`#19614 `_, by GaΓ«tan Gilbert). - **Added:** Added Ltac2 bindings for congruence and simpl congruence, it fixes #14289 not entirely but provides Ltac2 bindings for one of the tactics listed there (`#19032 `_, fixes `#14289 `_, by Benny Smit, reviewed by Jason Gross, Pierre-Marie PΓ©drot, GaΓ«tan Gilbert). - **Added:** APIs `compare` `of_int` and `print` in `Ltac2.Uint63` (`#19197 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Ltac2 Type` supports deprecation of the declared constructors (`#19575 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Constr.noccur_between` and `noccurn` to test for non-occurrence of local variables in terms (`#19614 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Control.hyp_value` to get the value (`v` in `H := v`) of an hypothesis (`#19630 `_, by GaΓ«tan Gilbert). - **Fixed:** resolution of :ref:`abbreviations ` in :n:`reference` in :token:`ltac2_quotations`, for instance in eval tactic delta-reduction flags :token:`ltac2_delta_reductions` (`#19589 `_, fixes `#19590 `_, by Pierre Roux). - **Fixed:** `Ltac2 Eval` does not require to be focused in a goal anymore (`#19961 `_, by Daniil Iaitskov). SSReflect ^^^^^^^^^ - **Changed:** The :tacn:`done` tactic now tries to apply `sym_equal` with four arguments instead of trying first with zero to three arguments (`#19372 `_, by Quentin Vermande). - **Changed:** `done` uses `simple refine` instead of `apply` to apply `sym_equal` (`#19399 `_, by Quentin Vermande). - **Removed:** no longer used lemma ``not_locked_false_eq_true`` and its call in the :tacn:`done` tactic (`#19382 `_, by Pierre Roux). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** :cmd:`Variables` and its aliases do not share the type of combined binders anymore. This makes for instance `Variables a b : T` strictly equivalent to `Variables (a: T) (b : T).` (when `a` is not bound in `T`). The difference matters when interpreting `T` generates fresh universes or existential variables: they will be distinct in the types of `a` and `b`. This was already the case for binders in terms (eg `fun (a b : T) => ...`), :cmd:`Context`, and when :flag:`Universe Polymorphism` is enabled (`#19277 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Guarded` and :cmd:`Validate Proof` are now internally classified as "queries" instead of "proof steps". This means they should not be counted anymore when stepping back with :cmd:`Undo`. (`#19383 `_, by GaΓ«tan Gilbert). - **Changed:** template polymorphism can bind universes which do not appear in the inductive's conclusion. For instance `eq` and `ex` are now template polymorphic. (`#19528 `_, by GaΓ«tan Gilbert). - **Changed:** The order of hints shown in the "For any goal" category in :cmd:`Print HintDb` now matches the order in which they will be tried. Previously the entries were misordered on their priority (`#19624 `_, by Jim Fehrle). - **Changed:** The :cmd:`Hint Rewrite` command now requires a *non-empty* list of hintDbs after the colon to be consistent with other Hint commands. If your script has an empty list of hintDbs, fix it by removing the colon (`#19730 `_, by Jim Fehrle). - **Changed:** :cmd:`Create HintDb` no longer erases pre-existing hint databases (`#19808 `_, by GaΓ«tan Gilbert). .. _LegacyLoadingRemoval: - **Removed:** "legacy" (non-findlib) loading mode for plugins in :cmd:`Declare ML Module` (`#18385 `_, by Emilio JesΓΊs Gallego Arias and GaΓ«tan Gilbert). - **Removed:** :n:`: @type` annotation in :cmd:`Obligation` which was ignored when executing the command (`#19678 `_, by GaΓ«tan Gilbert). - **Removed:** flag `Automatic Proposition Inductives` (using its effect was deprecated since 8.20) (`#19872 `_, by GaΓ«tan Gilbert). - **Added:** New :cmd:`Arguments`' modifier `clear simpl` to reset `simpl` reduction flags (`#19216 `_, by Hugo Herbelin). - **Added:** The ``use`` field of the :attr:`deprecated` attribute lets one specify a replacement for a ``Theorem``, ``Definition`` or ``Notation`` that is printed as part of the deprecation warning message and also used to suggest a quick fix in LSP based user interfaces (`#19300 `_, by Enrico Tassi). - **Added:** :cmd:`Register`, :cmd:`Register Scheme` and :cmd:`Add Zify` now support attributes :attr:`local`, :attr:`export` and :attr:`global` (`#19362 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Add` and :cmd:`Remove` now support attributes :attr:`local`, :attr:`export` and :attr:`global` (`#19390 `_, by GaΓ«tan Gilbert). - **Added:** Default hint mode option for typeclasses, mode attribute on Class declarations overriding the default and class-declaration-default-mode warning to check for uses of the default mode (`#19473 `_, by Matthieu Sozeau). - **Added:** :cmd:`Profile` command modifier to get profiling information for a given command (`#19517 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Print Universes` `Subgraph` accepts raw universe names (which end in an integer instead of an identifier) for debugging purposes, eg `Print Universes Subgraph ("foo.1" "foo.2")`. The integer in raw universe expressions is extremely unstable, so raw universe expressions should not be used outside debugging sessions (`#19640 `_, by GaΓ«tan Gilbert). - **Fixed:** the effect of :cmd:`Export` survives sections (the previous behaviour was identical to :cmd:`Import` in sections) (`#19361 `_, fixes `#19360 `_, by GaΓ«tan Gilbert). - **Fixed:** Anomaly when printing a module functor with :cmd:`Strategy` or :cmd:`Transparent` in one of its parameters (`#19768 `_, fixes `#19767 `_, by Hugo Herbelin). - **Fixed:** :opt:`Debug` and :opt:`Warnings` are classified as Synterp. This changes the scheduling during :cmd:`Import` such that putting `#[export] Set Warnings` around a specific command may change behaviour. (`#19981 `_, by GaΓ«tan Gilbert). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** The ``-compat`` :ref:`command line option ` now raises a warning rather than an error when the compatibility file doesn't exist. This enables easier use of the compat mechanism with versions where the compatibility file doesn't exist yet (`#19370 `_, by Pierre Roux). - **Changed:** `coq_makefile` generated makefiles only install plugin `.cmxs` files in findlib locations and stop putting a copy in `user-contrib` (the copy should be useless after the removal of plugin legacy loading) (`#19841 `_, by GaΓ«tan Gilbert). - **Removed:** `coqdep` flag `-m` (it was used through `coq_makefile`) (`#19863 `_, by GaΓ«tan Gilbert). - **Added:** :ref:`command line option ` ``-compat-from`` to enable writing compatibility files for libraries similarly to the ``-compat`` option for Rocq (`#19370 `_, by Pierre Roux). - **Added:** The ``-compat`` :ref:`command line option ` now silences deprecation warnings that were introduced since the given version (`#19370 `_, by Pierre Roux). RocqIDE ^^^^^^^ - **Changed:** Improved Preferences dialog: larger margins, tree of categories, sections in the categories, spin buttons for numbers, preservation of the last selected category, and more (`#19417 `_, by Sylvain Chiron). - **Fixed:** All preferences are now applied after clicking Apply or OK rather than immediately (`#19417 `_, by Sylvain Chiron). - **Fixed:** Changing the allowed modifiers in the Shortcuts panel of the Preferences dialog now immediately updates the available modifiers for the listed items (`#19417 `_, by Sylvain Chiron). - **Added:** Preference setting for unjustified conclusions background color (`#19417 `_, by Sylvain Chiron). - **Changed:** CoqIDE is renamed to RocqIDE (the auxiliary binary `coqidetop` is not renamed) (`#20036 `_, by GaΓ«tan Gilbert). - **Added:** Warnings are now included in the Errors panel (`#19188 `_, by Jim Fehrle). - **Fixed:** Changing the position of buffer names (top, left, bottom or right) no longer needs a restart (`#19166 `_, by Sylvain Chiron). - **Added:** Document tabs are now reorderable (`#19166 `_, by Sylvain Chiron). Standard library ^^^^^^^^^^^^^^^^ .. _90stdlib: - **Changed:** Stdlib moved to its own repository, look for `Stdlib own changelog `_ for other changes there (`#19975 `_, by Pierre Roux). - **Added:** a new `rocq-core` package for users who don't want to depend on Stdlib. This provides `Corelib `_ a tiny subset of Stdlib (`#19530 `_, starting to implement `CEP#83 `_ by Pierre Roux). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** when building Coq, the makefile's `world` target and `dune build`'s default target do not build rocqide anymore. Use `make world rocqide` or `dune build @default rocqide.install` to build what they respectively used to build (`#19378 `_, by GaΓ«tan Gilbert). - **Changed:** `coq_makefile` generates profiling info for `coqc` in `foo.vo.prof.json.gz` instead of `foo.v.prof.json.gz` (`#19428 `_, by GaΓ«tan Gilbert). - **Added:** `coq_makefile` generates profiling info for `coqchk` in `validate.prof.json.gz` (`#19428 `_, by GaΓ«tan Gilbert). - **Changed:** minimal Dune version required to build Coq bumped to 3.8.3 (`#19621 `_, by Pierre Roux). Miscellaneous ^^^^^^^^^^^^^ - **Changed:** the current working directory is not implicitly added to the ML search path (`#19834 `_, by GaΓ«tan Gilbert). - **Changed:** the `user-contrib`, XDG and `COQPATH` directories are not implicitly added to the ML loadpath (`#19842 `_, by GaΓ«tan Gilbert). Changes in 9.0.1 ~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** Guard checking forgot to check non principal arguments of a fixpoint for unguarded uses of the fixpoint leading to an inconsistency (`#20415 `_, fixes `#20413 `_, by GaΓ«tan Gilbert). - **Fixed:** inconsistency from incomplete guard checking with nested matches (`#20457 `_, fixes `#20455 `_, by GaΓ«tan Gilbert). - **Fixed:** inconsistency from incorrect reduction across a fixpoint during guard checking (`#20648 `_, fixes `#20555 `_, by Yann Leray). - **Fixed:** Fix guard checker making propositional extensionality inconsistent (`#21050 `_, fixes `#21053 `_, by Yann Leray). - **Fixed:** substitution of functor delta-resolvers when strengthening. The previous code was only substituting the inner delta resolvers and ignoring the codomain of functors. In particular this was generating ill-formed constants whose canonical component was pointing to a bound name that did not exist in the global environment, leading to an inconsistency (`#21057 `_, fixes `#21051 `_, by Pierre-Marie PΓ©drot). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Fixed:** `rocq dep` implicitly adds `-I $rocq-runtime/..` after the explicit `-I` instead of before (where `$rocq-runtime` is the expected location of the rocq-runtime package). This means that if a local plugin (whose META is in an explicit `-I` path) is installed next to rocq-runtime, `rocq dep` will emit a dependency on the local version instead of the installed version (`#20393 `_, by GaΓ«tan Gilbert). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** Bad interaction between dune, `rocq dep`, and local opam directory switches (`#20437 `_, fixes `#20422 `_, by Rodolphe Lepigre). Version 8.20 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.20 adds a new rewrite rule mechanism along with a few new features, a host of improvements to the virtual machine, the notation system, Ltac2 and the standard library. We highlight some of the most impactful changes here: - :ref:`rewrite_rules` - `primitive strings `_ - A lot of work went into reducing the size of the bytecode segment, which in turn means that .vo files might now be considerably smaller. - A new version of the `docker-keeper `_ compiler to build and maintain Docker images of Coq. Notable breaking changes: - Syntactic global references passed through the `using` clauses of :tacn:`auto`-like tactics are now handled as plain references rather than interpreted terms. In particular, their typeclass arguments will not be inferred. In general, the previous behaviour can be emulated by replacing `auto using foo` with `pose proof foo; auto`. - Argument order for the Ltac2 combinators `List.fold_left2` and `List.fold_right2` changed to be the same as in OCaml. - :cmd:`Import`\ing a module containing a mutable Ltac2 definition does not undo its mutations. Replace `Ltac2 mutable foo := some_expr.` with `Ltac2 mutable foo := some_expr. Ltac2 Set foo := some_expr.` to recover the previous behaviour. - Some :ref:`renaming <820_renaming_stdlib>` in the standard library. Deprecations are provided for a smooth transition. See the `Changes in 8.20.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual for 8.20 `_, `documentation of the 8.20 standard library `_ and `developer documentation of the 8.20 ML API `_ are also available. ThΓ©o Zimmermann with help from Ali Caglayan and Jason Gross maintained `coqbot `_ used to run Coq's CI and other pull request management tasks. Jason Gross maintained the `bug minimizer `_ and its `automatic use through coqbot `_. Erik Martin-Dorel maintained the `Coq Docker images `_ and the `docker-keeper `_ compiler used to build and keep those images up to date (note that the tool is not Coq specific). Cyril Cohen, Vincent Laporte, Pierre Roux and ThΓ©o Zimmermann maintained the `Nix toolbox `_ used by many Coq projects for continuous integration. Ali Caglayan, Emilio JesΓΊs Gallego Arias, Rudi Grinberg and Rodolphe Lepigre maintained the `Dune build system for OCaml and Coq `_ used to build Coq itself and many Coq projects. The opam repository for Coq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Karl Palmskog and Enrico Tassi with contributions from many users. A list of packages is `available on the Coq website `_. Coq 8.20 was made possible thanks to the following reviewers: FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, Ali Caglayan, Cyril Cohen, Andrej Dudenhefner, Andres Erbsen, Jim Fehrle, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Jason Gross, Hugo Herbelin, Ralf Jung, Jan-Oliver Kaiser, Chantal Keller, Olivier Laurent, Rodolphe Lepigre, Yishuai Li, Ralph Matthes, Guillaume Melquiond, Pierre-Marie PΓ©drot, Karl Palmskog, ClΓ©ment Pit-Claudel, Pierre Rousselin, Pierre Roux, Michael Soegtrop, soukouki, Matthieu Sozeau, Nicolas Tabareau, Enrico Tassi, Niels van der Weide, Nickolai Zeldovich and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details on Coq's development team. The 59 contributors to the 8.20 version are: Timur Aminev, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, BjΓΆrn Brandenburg, Ali Caglayan, Nikolaos Chatzikonstantinou, Sylvain Chiron, chluebi, Cyril Cohen, Anton Danilkin, Louise Dubois de Prisque, Andrej Dudenhefner, Maxime DΓ©nΓ¨s, Andres Erbsen, Jim Fehrle, Davide Fissore, Andreas Florath, Yannick Forster, Mario Frank, GaΓ«tan Gilbert, Georges Gonthier, Jason Gross, Stefan Haan, Hugo Herbelin, Lennart Jablonka, Emilio JesΓΊs Gallego Arias, Ralf Jung, Jan-Oliver Kaiser, Evgenii Kosogorov, Rodolphe Lepigre, Yann Leray, David M. Cooke, Erik Martin-Dorel, Guillaume Melquiond, Guillaume Munch-Maccagnoni, Karl Palmskog, Julien Puydt, Pierre-Marie PΓ©drot, Ramkumar Ramachandra, Pierre Rousselin, Pierre Roux, Kazuhiko Sakaguchi, Bernhard Schommer, Remy Seassau, Matthieu Sozeau, Enrico Tassi, Romain Tetley, Laurent ThΓ©ry, Alexey Trilis, Oliver Turner, Quentin Vermande, Li-yao Xia and ThΓ©o Zimmermann, The Coq community at large helped improve this new version via the GitHub issue and pull request system, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.20's development spanned 7 months from the release of Coq 8.19.0 (9 months since the branch for 8.19.0). Pierre Roux and Guillaume Melquiond are the release managers of Coq 8.20. This release is the result of 470 merged PRs, closing 113 issues. | Toulouse, September 2024 | Pierre Roux and Guillaume Melquiond for the Coq development team Changes in 8.20.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Changed:** The guard checker now recognizes uniform parameters of a fixpoint and treats their instances as constant over the recursive call (`#17986 `_, grants `#16040 `_, by Hugo Herbelin). - **Added:** A mechanism to add user-defined rewrite rules to Coq's reduction mechanisms; see chapter :ref:`rewrite_rules` (`#18038 `_, by Yann Leray). - **Added:** Support for primitive strings in terms (`#18973 `_, by Rodolphe Lepigre). .. _819_changes_spec_language: Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** warnings `future-coercion-class-constructor` and `future-coercion-class-field` about ``:>`` in :cmd:`Class` as errors by default. This offers a last opportunity to replace ``:>`` with ``::`` (available since Coq 8.18) to declare typeclass instances before making ``:>`` consistently declare coercions in all records in next version. To adapt huge codebases, you can try `this script `_ or the one below. But beware that both are incomplete. .. code-block:: sh #!/bin/awk -f BEGIN { startclass = 0; inclass = 0; indefclass = 0; # definitionalclasses (single field, without { ... }) } { if ($0 ~ "[ ]*Class") { startclass = 1; } if (startclass == 1 && $0 ~ ":=") { inclass = 1; indefclass = 1; } if (startclass == 1 && $0 ~ ":=.*{") { indefclass = 0; } if (inclass == 1) startclass = 0; if (inclass == 1 && $0 ~ ":>") { if ($0 ~ "{ .*:>") { # first field on a single line sub("{ ", "{ #[global] "); } else if ($0 ~ ":=.*:>") { # definitional classes on a single line sub(":= ", ":= #[global] "); } else if ($0 ~ "^ ") { sub(" ", " #[global] "); } else { $0 = "#[global] " $0; } sub(":>", "::") } print $0; if ($0 ~ ".*}[.]" || indefclass == 1 && $0 ~ "[.]$") inclass = 0; } (`#18590 `_, by Pierre Roux). - **Changed:** Mutually-proved theorems with statements in different coinductive types now supported (`#18743 `_, by Hugo Herbelin). - **Added:** :cmd:`CoFixpoint` supports attributes `bypass_guard`, `clearbody`, `deprecated` and `warn` (`#18754 `_, by Hugo Herbelin). - **Added:** `Program Fixpoint` with `measure` or `wf` (see :ref:`program_fixpoint`) now supports the `where` clause for notations, the `local` and `clearbody` attributes, as well as non-atomic conclusions (`#18834 `_, by Hugo Herbelin, fixes in particular `#13812 `_ and `#14841 `_). - **Fixed:** Anomaly on the absence of remaining obligations of some name now an error (`#18873 `_, fixes `#3889 `_, by Hugo Herbelin). - **Fixed:** Universe polymorphic `Program`'s obligations are now generalized only over the universe variables that effectively occur in the obligation (`#18915 `_, fixes `#11766 `_ and `#11988 `_, by Hugo Herbelin). - **Fixed:** Anomaly `assertion failed` in pattern-matching compilation, with :flag:`Program Mode` or with let-ins in the arity of an inductive type (`#18921 `_, fixes `#5777 `_ and `#11030 `_ and `#11586 `_, by Hugo Herbelin). - **Fixed:** Support for `Program`-style pattern-matching on more than one argument in an inductive family (`#18929 `_, fixes `#1956 `_ and `#5777 `_, by Hugo Herbelin). - **Fixed:** anomaly with obligations in the binders of a `measure`- or `wf`-based `Program Fixpoint` (`#18958 `_, fixes `#18920 `_, by Hugo Herbelin). - **Fixed:** Incorrect registration of universe names attached to a primitive polymorphic constant (`#19100 `_, fixes `#19099 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Changed:** an :g:`only printing` interpretation of a notation with a specific format does no longer change the printing rule of other interpretations of the notation; to globally change the default printing rule of all interpretations of a notation, use :g:`Reserved Notation` instead (`#16329 `_, fixes `#16262 `_, by Hugo Herbelin). - **Changed:** levels of :cmd:`Reserved Notation` now default to levels of previous notations with longest common prefix, if any. This helps to :ref:`factorize notations ` with common prefixes (`#19149 `_, by Pierre Roux). - **Added:** :warn:`closed-notation-not-level-0` and :warn:`postfix-notation-not-level-1` warnings about closed and postfix notations at unusual levels (`#18588 `_, by Pierre Roux). - **Added:** :warn:`notation-incompatible-prefix` warning when two notation definitions have incompatible prefixes (`#19049 `_, by Pierre Roux). - **Fixed:** Notations for applied constants equipped with multiple signatures of implicit arguments were not correctly inserting as many maximal implicit arguments as they should have (`#18445 `_, by Hugo Herbelin). - **Fixed:** Add support for printing notations applied to extra arguments in custom entries, thus eliminating an anomaly (`#18447 `_, fixes `#18342 `_, by Hugo Herbelin). Tactics ^^^^^^^ - **Changed:** When using :g:`Z.to_euclidean_division_equations`, :tacn:`nia` can now relate :g:`Z.div`/:g:`Z.modulo` to :g:`Z.quot`/:g:`Z.rem` a bit better, by virtue of being noticing when there are two equations of the form ``x = y * q₁ + _`` and ``x = y * qβ‚‚ + _`` (or minor variations thereof), suggesting that ``q₁ = qβ‚‚``. Users can replace :g:`Z.to_euclidean_division_equations` with :g:`let flags := Z.euclidean_division_equations_flags.default_with Z.euclidean_division_equations_flags.find_duplicate_quotients false in Z.to_euclidean_division_equations_with flags` or, using :g:`Import Z.euclidean_division_equations_flags.`, with :g:`Z.to_euclidean_division_equations_with ltac:(default_with find_duplicate_quotients false)` (`#17934 `_, by Jason Gross). - **Changed:** The opacity/transparency of primitive projections is now attached to the projections themselves, not the compatibility constants, and compatibility constants are always considered transparent (`#18327 `_, fixes `#18281 `_, by Jan-Oliver Kaiser and Rodolphe Lepigre). - **Changed:** Tactic :g:`intro z` on an existential variable goal forces the resolution of the existential variable into a goal :g:`forall z:?T, ?P`, which becomes :g:`?P` in context :g:`z:?T` after introduction. The existential variable :n:`?P` itself is now defined in a context where the variable of type `?T` is also named :g:`z`, as specified by :tacn:`intro` instead of :g:`x` as it was conventionally the case before (`#18395 `_, by Hugo Herbelin). - **Changed:** syntactic global references passed through the `using` clauses of :tacn:`auto`-like tactics are now handled as plain references rather than interpreted terms. In particular, their typeclass arguments will not be inferred. In general, the previous behaviour can be emulated by replacing `auto using foo` with `pose proof foo; auto` (`#18909 `_, by Pierre-Marie PΓ©drot). - **Changed:** Use Coqlib's :cmd:`Register` mechanism for the generalized rewriting tactic and make the (C)RelationClasses/(C)Morphisms independent of the `rewrite` tactic to ease maintainance. (`#19115 `_, by Matthieu Sozeau). - **Removed:** the `clear` modifier which was deprecated since 8.17 (`#18887 `_, by Pierre-Marie PΓ©drot). - **Removed:** the `cutrewrite` tactic, which was deprecated since Coq 8.5 (`#19027 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** non-reference hints in `using` clauses of :tacn:`auto`-like tactics (`#19006 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** the `gintuition` tactic, which used to be undocumented until Coq 8.16 (`#19129 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** `destauto`, see `#11537 `_ (`#19179 `_, by Jim Fehrle). - **Added:** When using :g:`Z.to_euclidean_division_equations`, you can now pose equations of the form ``x = y * q`` using :g:`Z.divide` (`#17927 `_, by Evgenii Kosogorov). - **Added:** support for :g:`Nat.double` and :g:`Nat.div2` to :g:`zify` and :g:`lia` (`#18729 `_, by Andres Erbsen). - **Added:** the :tacn:`replace` tactic now accepts `->` and `<-` to specify the direction of the replacement when used with a `with` clause (`#19060 `_, fixes `#13480 `_, by Pierre-Marie PΓ©drot). - **Fixed:** The name of a cofixpoint globally defined with a name is now systematically reused by :tacn:`simpl` after reduction, even when the named cofixpoint is mutually defined or defined in a section (`#18576 `_, fixes `#4056 `_, by Hugo Herbelin). - **Fixed:** The reduction of primitive projections of cofixpoints by :tacn:`simpl` is now implemented (`#18577 `_, fixes `#7982 `_, by Hugo Herbelin). - **Fixed:** Support for refolding reduced global mutual fixpoints/cofixpoints with parameters in :tacn:`cbn` (`#18601 `_, fixes part of `#4056 `_, by Hugo Herbelin). - **Fixed:** :tacn:`cbn` was leaving behind unnamable constants when refolding mutual fixpoints/cofixpoints from aliased modules (`#18616 `_, fixes `#17897 `_, by Hugo Herbelin). - **Fixed:** :tacn:`cbv` of primitive projections applied to a tuple now ignores `beta` like it does for :tacn:`cbn`, :tacn:`lazy` and :tacn:`simpl` (`#18618 `_, fixes `#9086 `_, by Hugo Herbelin). Ltac language ^^^^^^^^^^^^^ - **Added:** In :tacn:`rewrite_strat`, :n:`@rewstrategy` now supports the fixpoint operator :n:`fix @ident := @rewstrategy1` (`#18094 `_, fixes `#13702 `_, by Jason Gross and GaΓ«tan Gilbert). - **Fixed:** :tacn:`rewrite_strat` now works inside module functors (`#18094 `_, fixes `#18463 `_, by Jason Gross). Ltac2 language ^^^^^^^^^^^^^^ - **Changed:** recursive `let` and non mutable projections of syntactic values are considered syntactic values (`#18411 `_, by GaΓ«tan Gilbert). - **Changed:** Ltac2 notations are typechecked at declaration time by default. This should produce better errors when a notation argument does not have the expected type (e.g. wrong branch type in `match! goal`). In the previous behaviour of typechecking, only the expansion result can be recovered using :flag:`Ltac2 Typed Notations`. We believe there are no real use cases for this, please report if you have any (`#18432 `_, fixes `#17477 `_, by GaΓ«tan Gilbert). - **Changed:** argument order for the Ltac2 combinators `List.fold_left2` and `List.fold_right2` changed to be the same as in OCaml (`#18706 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Import`\ing a module containing a mutable Ltac2 definition does not undo its mutations. Replace `Ltac2 mutable foo := some_expr.` with `Ltac2 mutable foo := some_expr. Ltac2 Set foo := some_expr.` to recover the previous behaviour (`#18713 `_, by GaΓ«tan Gilbert). - **Changed:** the `using` clause argument of :tacn:`auto`-like tactics in Ltac2 now take a global `reference` rather than arbitrary `constr` (`#18940 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** `Ltac2.Constr.Pretype.Flags.open_constr_flags` whose name is misleading as it runs typeclass inference unlike `open_constr:()` (`#18765 `_, by GaΓ«tan Gilbert). - **Added:** `fst` and `snd` in `Ltac2.Init` (`#18370 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Ltac1.of_preterm` and `to_preterm` (`#18551 `_, by GaΓ«tan Gilbert). - **Added:** `of_intro_pattern` and `to_intro_pattern` in `Ltac2.Ltac1` (`#18558 `_, by GaΓ«tan Gilbert). - **Added:** basic APIs in `Ltac2.Ltac1` to produce slightly more informative errors when failing to convert a Ltac1 value to some Ltac2 type (`#18558 `_, by GaΓ«tan Gilbert). - **Added:** APIs `Ltac2.Control.unshelve` and `Ltac2.Notations.unshelve` (`#18604 `_, by GaΓ«tan Gilbert). - **Added:** warning on unused Ltac2 variables (except when starting with `_`) (`#18641 `_, by GaΓ«tan Gilbert). - **Added:** `Ltac2.Control.numgoals` (`#18690 `_, by GaΓ«tan Gilbert). - **Added:** `intropattern` and `intropatterns` notation scopes support views (`foo%bar`) (`#18757 `_, by GaΓ«tan Gilbert). - **Added:** open recursion combinators in `Ltac2.Constr.Unsafe` (`#18764 `_, by GaΓ«tan Gilbert). - **Added:** APIs in `Ltac2.Constr.Pretype.Flags` to customize pretyping flags. (`#18765 `_, by GaΓ«tan Gilbert). - **Added:** :attr:`abstract` attribute for :cmd:`Ltac2 Type` to turn types abstract at the end of the current module (`#18766 `_, fixes `#18656 `_, by GaΓ«tan Gilbert). - **Added:** APIs in `Ltac2.Message` to interact with the boxing system of the pretty printer (`#18988 `_, by GaΓ«tan Gilbert). - **Added:** flag `Automatic Proposition Inductives`, :flag:`Dependent Proposition Eliminators` and warning `automatic-prop-lowering` (`#18989 `_, by GaΓ«tan Gilbert). - **Added:** `String.sub` (`#19204 `_, by Rodolphe Lepigre). - **Fixed:** `Ltac2.Control.new_goal` removes the new goal from the shelf and future goals (`#19141 `_, fixes `#19138 `_, by GaΓ«tan Gilbert). SSReflect ^^^^^^^^^ - **Changed:** ssreflect no longer relies on the recovery mechanism of the parsing engine, this can slightly change the parsing priorities in rare occurences, for instance when combining :tacn:`unshelve` and ``=>`` (`#18224 `_, by Pierre Roux). - **Changed:** notations ``_.1`` and ``_.2`` are now defined in the prelude at level 1 rather than in ``ssrfun`` at level 2 (`#18224 `_, by Pierre Roux). - **Changed:** The :tacn:`have` tactic generates a proof term containing an opaque constant, as it did up to PR `#15121 `_ included in Coq 8.16.0. See the variant `have @H` to generate a (transparent) let-in instead (:ref:`generating_let_ssr`). (`#18449 `_, fixes `#18017 `_, by Enrico Tassi). - **Deprecated:** The ``fun_scope`` notation scope declared in `ssrfun.v` is deprecated. Use ``function_scope`` instead (`#18374 `_, by Kazuhiko Sakaguchi). - **Fixed:** handling of primitive projections in ssrewrite (`#19213 `_, fixes `#19229 `_, by Pierre Roux, Kazuhiko Sakaguchi, Enrico Tassi and Quentin Vermande). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** the default reversibility status of most coercions. The refman states that By default coercions are not reversible except for Record fields specified using ``:>``. The previous code was making way too many coercion reversible by default. The new behavior should be closer from the spec in the doc (`#18705 `_, by Pierre Roux). - **Changed:** focus commands such as `1:{` and goal selection for query commands such as `1: Check` do not need `Classic` (Ltac1) proof mode to function. In particular they function in Ltac2 mode (`#18707 `_, fixes `#18351 `_, by GaΓ«tan Gilbert). - **Changed:** inductives declared with `: Type` or no annotation and automatically put in `Prop` are not declared template polymorphic (`#18867 `_, by GaΓ«tan Gilbert). - **Changed:** Clarify the warning about use of :cmd:`Let`, :cmd:`Variable`, :cmd:`Hypothesis` and :cmd:`Context` outside sections and make it an error by default (`#18880 `_, by Pierre Roux). - **Changed:** The "fragile-hint-constr" warning is now an error by default, as the corresponding feature will be removed in a later version (`#18895 `_, by Pierre-Marie PΓ©drot). - **Changed:** :cmd:`Scheme` automatically registers the resulting schemes in the :cmd:`Register Scheme` database (`#19016 `_, fixes `#3132 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Typeclasses Transparent` and :cmd:`Typeclasses Opaque` default locality outside section is now :attr:`export` (`#19069 `_, by GaΓ«tan Gilbert). - **Deprecated:** The :cmd:`Cd` command. Instead use the command line option `-output-directory` (see :ref:`command-line-options`) or, for extraction, :opt:`Extraction Output Directory` (`#17403 `_, by Ali Caglayan and Hugo Herbelin). - **Added:** :attr:`warn` attribute generalizing the deprecation machinery to other forms of comments (`#18248 `_, by Hugo Herbelin and Pierre Roux). - **Added:** :cmd:`Register Scheme` to add entries to the scheme database used by some tactics (`#18299 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Print` :n:`@reference` now shows the implicit arguments of a :n:`@reference` directly on the type of :n:`@reference`, using `{...}` and `[...]` markers for respectively maximally-inserted and non-maximally-inserted implicit arguments, as :cmd:`About` does (`#18444 `_, by Hugo Herbelin). - **Added:** :n:`@import_categories` supports category `options` controlling :ref:`flags-options-tables` (`#18536 `_, by GaΓ«tan Gilbert). - **Added:** When a name is a projection, :cmd:`About` and :cmd:`Print` now indicate it (`#18725 `_, by Hugo Herbelin). - **Added:** :cmd:`Hint Projections` command that sets the transparency flag for projections for the specified hint databases (`#18785 `_, by Jan-Oliver Kaiser and Rodolphe Lepigre). - **Added:** :cmd:`Search` now admits the `is:Fixpoint` and `is:CoFixpoint` logical kinds to search for constants defined with the `Fixpoint` and `CoFixpoint` keywords (`#18983 `_, by Pierre Rousselin). - **Added:** The :cmd:`Include` command can now include module types with a `with` clause (:n:`@with_declaration`) to instantiate some parameters (`#19144 `_, by Pierre Rousselin). - **Fixed:** Fixes missing implicit arguments coming after a :g:`->` in the main type printed by :cmd:`Print` and :cmd:`About` (`#18442 `_, fixes `#15020 `_, by Hugo Herbelin). - **Fixed:** :flag:`Cumulativity Weak Constraints` can unify universes to `Set` when :flag:`Universe Minimization ToSet` is enabled (`#18458 `_, by GaΓ«tan Gilbert). - **Fixed:** :cmd:`Search` with modifier `is:Scheme` restricted the search to inductive types which have schemes instead of the schemes themselves. For instance `Search nat is:Scheme` with just the prelude loaded would return `le` i.e. the only inductive type whose type mentions `nat` (`#18537 `_, fixes `#18298 `_, by GaΓ«tan Gilbert). - **Fixed:** :cmd:`Search` now searches also in included module types (`#18662 `_, fixes `#18657 `_, by Hugo Herbelin). - **Fixed:** :cmd:`Eval` and :cmd:`Definition` with `:= Eval` work without needing to load the Ltac plugin (`#18852 `_, fixes `#12948 `_, by GaΓ«tan Gilbert). - **Fixed:** :cmd:`Scheme` declares non-recursive schemes for :n:`@scheme_type` `Case` and `Elimination` (`#19017 `_, fixes `#10816 `_, by GaΓ«tan Gilbert). - **Fixed:** :flag:`Cumulativity Weak Constraints` had its meaning flipped since 8.12 (`#19201 `_, by GaΓ«tan Gilbert). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** signal `SIGINT` interrupts the process with " "user interrupt" error instead of aborting. This is intended to produce better messages when interrupting Coq (`#18716 `_, by GaΓ«tan Gilbert). - **Added:** Command line option :n:`-output-directory dir` to set the default output directory for extraction, :cmd:`Redirect` and :cmd:`Print Universes` (`#17392 `_, fixes `#8649 `_, by Hugo Herbelin). - **Fixed:** coqdoc links to section variables introduced with :cmd:`Context` (`#18527 `_, fixes `#18516 `_, by Pierre Roux). CoqIDE ^^^^^^ - **Changed:** Find/replace UI was improved: margins, icons for found/not found (`#18523 `_, fixes `#11024 `_, by Sylvain Chiron). - **Changed:** The default key binding modifier for the Navigation menu was changed to Alt on non-macOS systems. The previous default, Ctrl, hid some conventional cursor movement bindings such as Ctrl-Left, Ctrl-Right, Ctrl-Home and Ctrl-End. The new default generally has no effect if you've previously installed Coq on your system. See :ref:`Shortcuts` to change the default. The Edit/Undo key binding was changed from Ctrl-U to Ctrl-Z to be more consistent with common conventions. `View/Previous Tab` and `View/Next Tab` were changed from `Alt-Left/Right` to `Ctrl-PgUp/PgDn` (`Cmd-PgUp/PgDn` on macOS). To change key bindings on your system (e.g. back to Ctrl-U), see :ref:`key_bindings` (`#18717 `_, by Sylvain Chiron). - **Changed:** Changing modifiers for the View menu only applies to toggleable items; View/Show Proof was changed to Shift-F2 (`#18717 `_, by Sylvain Chiron). - **Added:** Edit/Select All and Navigation/Fully Check menu items (`#18717 `_, fixes `#16141 `_, by Sylvain Chiron). - **Fixed:** Opening a file with drag and drop now works correctly (fixed regression) (`#18524 `_, fixes `#3977 `_, by Sylvain Chiron). - **Fixed:** Incorrect highlight locations and line numbers for errors and warnings, especially in the presence of unicode characters. This updates the XML protocol (`#19040 `_, fixes `#18682 `_, by Hugo Herbelin). - **Fixed:** Show tooltips for syntax errors (`#19153 `_, fixes `#19152 `_, by Jim Fehrle). .. _820_renaming_stdlib: Standard library ^^^^^^^^^^^^^^^^ - **Changed:** names of "push" lemmas for :g:`List.length` to follow the same convention as push lemmas for other operations. For example, :g:`app_length` became :g:`length_app`. The standard library was migrated using the following script: .. code-block:: sh find theories -name '*.v' | xargs sed -i -E ' s/\/length_app/g; s/\/length_rev/g; s/\/length_map/g; s/\/fold_left_S_O/g; s/\/length_fst_split/g; s/\/length_snd_split/g; s/\/length_combine/g; s/\/length_prod/g; s/\/length_firstn/g; s/\/length_skipn/g; s/\/length_seq/g; s/\/length_concat/g; s/\/length_flat_map/g; s/\/length_list_power/g; ' (`#18564 `_, by Andres Erbsen). - **Changed:** ``Coq.CRelationClasses.arrow``, ``Coq.CRelationClasses.iffT`` and ``Coq.CRelationClasses.flip`` are now :cmd:`Typeclasses Opaque` (`#18910 `_, by Pierre-Marie PΓ©drot). - **Removed:** The library files ``Coq.NArith.Ndigits``, ``Coq.NArith.Ndist``, and ``Coq.Strings.ByteVector`` which were deprecated since 8.19 (`#18936 `_, by Andres Erbsen). - **Deprecated:** The library files * ``Coq.Numbers.Integer.Binary.ZBinary`` * ``Coq.Numbers.Integer.NatPairs.ZNatPairs`` * ``Coq.Numbers.Natural.Binary.NBinary`` have been deprecated. Users should require ``Coq.Arith.PeanoNat`` or ``Coq.Arith.NArith.BinNat`` if they want implementations of natural numbers and ``Coq.Arith.ZArith.BinInt`` if they want an implementation of integers (`#18500 `_, by Pierre Rousselin). - **Deprecated:** The library file ``Coq.Numbers.NatInt.NZProperties`` is deprecated. Users can require ``Coq.Numbers.NatInt.NZMulOrder`` instead and replace the module ``NZProperties.NZProp`` with ``NZMulOrder.NZMulOrderProp`` (`#18501 `_, by Pierre Rousselin). - **Deprecated:** The library file ``Coq.Arith.Bool_nat`` has been deprecated (`#18538 `_, by Pierre Rousselin). - **Deprecated:** The library file ``Coq.Numbers.NatInt.NZDomain`` is deprecated (`#18539 `_, by Pierre Rousselin). - **Deprecated:** The library files ``Coq.Numbers.Integers.Abstract.ZDivEucl`` and ``Coq.ZArith.Zeuclid`` are deprecated (`#18544 `_, by Pierre Rousselin). - **Deprecated:** The library files ``Coq.Numbers.Natural.Abstract.NIso`` and ``Coq.Numbers.Natural.Abstract.NDefOps`` are deprecated (`#18668 `_, by Pierre Rousselin). - **Deprecated:** ``Bool.Bvector``. Users are encouraged to consider ``list bool`` instead. Please open an issue if you would like to keep using ``Bvector``. (`#18947 `_, by Andres Erbsen). - **Added:** A warning on :g:`Vector.t` to make its new users aware that using this dependently typed representation of fixed-length lists is more technically difficult, compared to bundling lists with a proof of their length. This is not a deprecation and there is no intent to remove it from the standard library. Use option `-w -stdlib-vector` to silence the warning (`#18032 `_, by Pierre Roux, reviewed by Andres Erbsen, Jim Fehrle, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Hugo Herbelin, Olivier Laurent, Yishuai Li, Pierre-Marie PΓ©drot and Michael Soegtrop). - **Added:** lemmas :g:`NoDup_app`, :g:`NoDup_iff_ForallOrdPairs`, :g:`NoDup_map_NoDup_ForallPairs` and :g:`NoDup_concat` (`#18172 `_, by Stefan Haani and Andrej Dudenhefner). - **Added:** lemmas :g:`In_iff_nth_error` :g:`nth_error_app`, :g:`nth_error_cons_0`, :g:`nth_error_cons_succ`, :g:`nth_error_rev`, :g:`nth_error_firstn`, :g:`nth_error_skipn`, :g:`hd_error_skipn`, :g:`nth_error_seq` (`#18563 `_, by Andres Erbsen) - **Added:** to :g:`N` and :g:`Nat` lemmas :g:`strong_induction_le`, :g:`binary_induction`, :g:`strong_induction_le`, :g:`even_even`, :g:`odd_even`, :g:`odd_odd`, :g:`even_odd`, :g:`b2n_le_1`, :g:`testbit_odd_succ'`, :g:`testbit_even_succ'`, :g:`testbit_div2`, :g:`div2_0`, :g:`div2_1`, :g:`div2_le_mono`, :g:`div2_even`, :g:`div2_odd'`, :g:`le_div2_diag_l`, :g:`div2_le_upper_bound`, :g:`div2_le_lower_bound`, :g:`lt_div2_diag_l`, :g:`le_div2`, :g:`lt_div2`, :g:`div2_decr`, :g:`land_even_l`, :g:`land_even_r`, :g:`land_odd_l`, :g:`land_odd_r`, :g:`land_even_even`, :g:`land_odd_even`, :g:`land_even_odd`, :g:`land_odd_odd`, :g:`land_le_l`, :g:`land_le_r`, :g:`ldiff_even_l`, :g:`ldiff_odd_l`, :g:`ldiff_even_r`, :g:`ldiff_odd_r`, :g:`ldiff_even_even`, :g:`ldiff_odd_even`, :g:`ldiff_even_odd`, :g:`ldiff_odd_odd`, :g:`ldiff_le_l`, :g:`shiftl_lower_bound`, :g:`shiftr_upper_bound`, :g:`ones_0`, :g:`ones_succ`, :g:`pow_lower_bound` (`#18628 `_, by Pierre Rousselin). - **Fixed:** :g:`Z.euclidean_division_equations_cleanup` has been reordered so that :tacn:`zify` (and :tacn:`lia`, :tacn:`nia`, etc) are no longer as slow when the context contains many assumptions of the form :g:`0 <= ... < ...` (`#18818 `_, fixes `#18770 `_, by Jason Gross). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Bump minimal Dune version required to build Coq to 3.6.1 (`#18359 `_, by Emilio Jesus Gallego Arias). - **Removed:** Support for ``.vio`` files and for ``.vio2vo`` transformation has been removed, compilation to ``.vos`` is the supported method for quick compilation now (`#18424 `_, fixes `#4007 `_ and `#4013 `_ and `#4123 `_ and `#5308 `_ and `#5223 `_ and `#6720 `_ and `#8402 `_ and `#9637 `_ and `#11471 `_ and `#18380 `_, by Emilio Jesus Gallego Arias). - **Added:** The `coq-doc` opam / Dune package will now build and install Coq's documentation (`#17808 `_, by Emilio Jesus Gallego Arias). - **Added:** Coq is now compatible with `memprof-limits` interruption methods. This means that Coq will be recompiled when the library is installed / removed from an OPAM switch. (`#18906 `_, fixes `#17760 `_, by Emilio Jesus Gallego Arias). - **Added:** ability to exit from `Drop.` in Coq toplevel by a simple `Ctrl + D`, without leaving the OCaml toplevel on the stack. Also add a custom OCaml toplevel directory `#go` which does the same action as `go ()`, but with a more native syntax (`#18771 `_, by Anton Danilkin). Extraction ^^^^^^^^^^ - **Added:** Extension for OCaml extraction: Commands to extract foreign function calls to C (external) and ML function exposition (Callback.register) for calling being able to call them by C functions (`#18270 `_, fixes `#18212 `_, by Mario Frank). - **Fixed:** Wrongly self-referencing extraction of primitive projections to OCaml in functors (`#17321 `_, fixes `#16288 `_, by Hugo Herbelin). Note that OCaml wrappers assuming that the applicative syntax of projections is provided may have to use the dot notation instead. Changes in 8.20.1 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** Possible guard checker anomaly on fixpoints containing an inner fixpoint that is reducible (because of its main argument reducing to a constructor). This is a regression in 8.20 (`#19671 `_, fixes `#19661 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Fixed:** spurious warning about incompatible prefixes in presence of ``as pattern`` :n:`@syntax_modifier` (`#19653 `_, fixes `#19541 `_, by Pierre Roux). - **Fixed:** spurious warning about incompatible prefixes in presence of recursive notations (`#19673 `_, fixes `#19658 `_, by Pierre Roux). Tactics ^^^^^^^ - **Fixed:** a regression in `Hint Extern` matching primitive projections (`#19675 `_, fixes `#19668 `_, by Jan-Oliver Kaiser). Version 8.19 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.19 extends the kernel universe polymorphism to polymorphism over sorts (e.g. `Prop`, `SProp`) along with a few new features, a host of improvements to the notation system, the Ltac2 standard library, and the removal of some standard library files after a long deprecation period. We highlight some of the most impactful changes here: - :ref:`sort-polymorphism` makes it possible to share common constructs over `Type` `Prop` and `SProp`. - The notation :g:`term%_scope` to set a scope only temporarily (in addition to :g:`term%scope` for opening a scope applying to all subterms). - :tacn:`lazy`, :tacn:`simpl`, :tacn:`cbn` and :tacn:`cbv` and the associated :cmd:`Eval` and :tacn:`eval` reductions learned to do head reduction when given flag `head`. - :ref:`New Ltac2 APIs <819Ltac2>`, improved Ltac2 `exact` and dynamic building of Ltac2 term patterns. - New performance evaluation facilities: :cmd:`Instructions` to count CPU instructions used by a command (Linux only) and :ref:`profiling` system to produce trace files. - New command :cmd:`Attributes` to assign attributes such as :attr:`deprecated` to a library file. Notable breaking changes: - :tacn:`replace` with `by tac` does not automatically attempt to solve the generated equality subgoal using the hypotheses. Use `by first [assumption | symmetry;assumption | tac]` if you need the previous behaviour. - :ref:`Removed old deprecated files <819Stdlib>` from the standard library. See the `Changes in 8.19.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual for 8.19 `_, `documentation of the 8.19 standard library `_ and `developer documentation of the 8.19 ML API `_ are also available. Maxime DΓ©nΓ¨s and Thierry Martinez with support from Erik Martin-Dorel and ThΓ©o Zimmermann moved the CI away from `gitlab.com `_ to use Inria supported runner machines through `gitlab.inria.fr `_. ThΓ©o Zimmermann with help from Ali Caglayan and Jason Gross maintained `coqbot `_ used to run Coq's CI and other pull request management tasks. Jason Gross maintained the `bug minimizer `_ and its `automatic use through coqbot `_. Jaime Arias and Erik Martin-Dorel maintained the `Coq Docker images `_ and Cyril Cohen, Vincent Laporte, Pierre Roux and ThΓ©o Zimmermann maintained the `Nix toolbox `_ used by many Coq projects for continuous integration. Ali Caglayan, Emilio JesΓΊs Gallego Arias, Rudi Grinberg and Rodolphe Lepigre maintained the `Dune build system for OCaml and Coq `_ used to build Coq itself and many Coq projects. The opam repository for Coq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Karl Palmskog and Enrico Tassi with contributions from many users. A list of packages is `available on the Coq website `_. Our current maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Ana Borges, Ali Caglayan, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Andres Erbsen, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details. The 40 contributors to the 8.19 version are: quarkcool, Khalid Abdullah, Tanaka Akira, Isaac van Bakel, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, Ana Borges, Ali Caglayan, Nikolaos Chatzikonstantinou, Maxime DΓ©nΓ¨s, Andrej Dudenhefner, Andres Erbsen, Jim Fehrle, GaΓ«tan Gilbert, Jason Gross, Stefan Haan, Hugo Herbelin, Emilio JesΓΊs Gallego Arias, Pierre Jouvelot, Ralf Jung, Jan-Oliver Kaiser, Robbert Krebbers, Jean-Christophe LΓ©chenet, Rodolphe Lepigre, Yann Leray, Yishuai Li, Guillaume Melquiond, Guillaume Munch-Maccagnoni, Sotaro Okada, Karl Palmskog, Pierre-Marie PΓ©drot, Jim Portegies, Pierre Rousselin, Pierre Roux, Michael Soegtrop, David Swasey, Enrico Tassi, Shengyi Wang and ThΓ©o Zimmermann. The Coq community at large helped improve this new version via the GitHub issue and pull request system, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.19's development spanned 4 months from the release of Coq 8.18.0 (6 months since the branch for 8.18.0). GaΓ«tan Gilbert and Matthieu Sozeau are the release managers of Coq 8.19. This release is the result of 285 merged PRs, closing 70 issues. | Nantes, January 2024 | GaΓ«tan Gilbert for the Coq development team Changes in 8.19.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Added:** :ref:`sort-polymorphism` makes it possible to share common constructs over `Type` `Prop` and `SProp` (`#17836 `_, `#18331 `_, by GaΓ«tan Gilbert). - **Fixed:** Primitives being incorrectly considered convertible to anything by module subtyping (`#18507 `_, fixes `#18503 `_, by GaΓ«tan Gilbert). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** :token:`term_forall_or_fun`, :token:`term_let`, :token:`term_fix`, :token:`term_cofix` and :token:`term_if` from :token:`term` at level 200 to :token:`term10` at level 10. This is a first step towards getting rid of the recovery mechanism of camlp5/coqpp. The impact will mostly be limited to rare cases of additional parentheses around the above (`#18014 `_, by Hugo Herbelin). - **Changed:** Declarations of the form :g:`(id := body)` in :cmd:`Context` outside a section in a :cmd:`Module Type` do not any more try to declare a class instance. Assumptions whose type is a class and declared using :cmd:`Context` outside a section in a :cmd:`Module Type` are now declared as global, instead of local (`#18254 `_, by Hugo Herbelin). - **Fixed:** Anomaly in the presence of duplicate variables within a disjunctive pattern (`#17857 `_ and `#18005 `_, fixes `#17854 `_ and `#18004 `_, by Hugo Herbelin). - **Fixed:** Printing of constructors and of :g:`in` clause of :g:`match` now respects the :flag:`Printing Implicit` and :flag:`Printing All` flags (`#18176 `_, fixes `#18163 `_, by Hugo Herbelin). - **Fixed:** Wrong shift of argument names when using :cmd:`Arguments` in nested sections (`#18393 `_, fixes `#12755 `_ and `#18392 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Changed:** More informative message when a notation cannot be intepreted as a reference (`#18104 `_, addresses `#18096 `_, by Hugo Herbelin). - **Changed:** In casts like :g:`term : t` where :g:`t` is bound to some scope :g:`t_scope`, via :cmd:`Bind Scope`, the :g:`term` is now interpreted in scope :g:`t_scope`. In particular when :g:`t` is :g:`Type` the :g:`term` is interpreted in :g:`type_scope` and when :g:`t` is a product the :g:`term` is interpreted in :g:`fun_scope` (`#6134 `_, fixes `#14959 `_, by Hugo Herbelin, reviewed by Maxime DΓ©nΓ¨s, Jim Fehrle, Emilio Gallego, GaΓ«tan Gilbert, Jason Gross, Pierre-Marie PΓ©drot, Pierre Roux, Bas Spitters and ThΓ©o Zimmermann). - **Added:** the notation :g:`term%_scope` to set a scope only temporarily (in addition to :g:`term%scope` for opening a scope applying to all subterms) (`#14928 `_, fixes `#11486 `_ and `#12157 `_ and `#14305 `_, by Hugo Herbelin, reviewed by Pierre Roux). - **Removed** the ability to declare scopes whose name starts with `_` (would be ambiguous with the new :g:`%_scope` notation) (`#14928 `_, by Pierre Roux, reviewed by Hugo Herbelin). - **Deprecated** the notation :n:`term%scope` in :cmd:`Arguments` command. In a few version, we'll make it an error and in next version give it the same semantics as in terms (i.e., deep scope opening for all subterms rather than just temporary opening) (`#14928 `_, fixes `#11486 `_ and `#12157 `_ and `#14305 `_, by Hugo Herbelin, reviewed by Pierre Roux). - **Added:** Quoted strings can be used as tokens in notations; double quotes can be used in symbols in :g:`only printing` notations; see :ref:`Basic notations ` for details (`#17123 `_, by Hugo Herbelin). - **Added:** Parsing support for notations with recursive binders involving not only variables bound by :n:`fun` or :n:`forall` but also by :n:`let` or :n:`match` (`#17856 `_, fixes `#17845 `_, by Hugo Herbelin). - **Added:** Declaring more than once the level of a notation variable is now an error (`#17988 `_, fixes `#17985 `_, by Hugo Herbelin). - **Fixed:** Various bugs and limitations to using custom binders in non-recursive and recursive notations (`#17115 `_, fixes parts of `#17094 `_, by Hugo Herbelin). - **Fixed:** An invalid case of eta-expansion in notation pretty-printer (`#17841 `_, fixes `#15221 `_, by Hugo Herbelin). - **Fixed:** :flag:`Printing Parentheses` now works also when an explicit level is set for the right-hand side of a right-open notation (`#17844 `_, fixes `#15322 `_, by Hugo Herbelin). - **Fixed:** anomaly when a notation variable denoting a binder occurs nested more than once in a recursive pattern (`#17861 `_, fixes `#17860 `_, by Hugo Herbelin). - **Fixed:** Anomaly when trying to disable a non-existent custom notation (`#17891 `_, fixes `#17782 `_, by Hugo Herbelin). - **Fixed:** appropriate error instead of anomaly in the presence of notations with constructors applied to too many arguments in pattern-matching (`#17892 `_, fixes `#17071 `_, by Hugo Herbelin). - **Fixed:** support constructors with parameters in number or string notations for patterns (`#17902 `_, fixes `#11237 `_, by Hugo Herbelin). - **Fixed:** Chains of entry coercions possibly printed in the wrong order depending on the order in which they were declared (`#18230 `_, fixes `#18223 `_, by Hugo Herbelin). Tactics ^^^^^^^ - **Changed:** `open_constr` in Ltac1 and Ltac2 does not perform evar normalization. Normalization may be recovered using `let c := open_constr:(...) in constr:(c)` if necessary for performance (`#17704 `_, by GaΓ«tan Gilbert). - **Changed:** :tacn:`abstract` now supports existential variables (`#17745 `_, by GaΓ«tan Gilbert). - **Changed:** instances declared with :flag:`Typeclasses Unique Instances` do not allow backtracking even when the goal contains evars (`#17789 `_, fixes `#6714 `_, by Jan-Oliver Kaiser). - **Changed:** In :tacn:`rewrite_strat`, the syntax for the :g:`choice` strategy has changed slightly. You may need to add parentheses around its arguments (one such case found in our continuous integration tests) (`#17832 `_, by Hugo Herbelin, Jim Fehrle and Jason Gross). - **Changed:** :tacn:`replace` with `by tac` does not automatically attempt to solve the generated equality subgoal using the hypotheses. Use `by first [assumption | symmetry;assumption | tac]` if you need the previous behaviour (`#17964 `_, fixes `#17959 `_, by GaΓ«tan Gilbert). - **Changed:** ``Z.euclidean_division_equations_cleanup`` now breaks up hypotheses of the form `0 <= _ < _` for better cleanup in ``zify`` (`#17984 `_, by Jason Gross). - **Changed:** :tacn:`simpl` now refolds applied constants unfolding to reducible fixpoints into the original constant even when this constant would become partially applied (`#17991 `_, by Hugo Herbelin). - **Added:** Ltac2 tactic `Std.resolve_tc` to resolve typeclass evars appearing in a given term (`#13071 `_, by GaΓ«tan Gilbert and Maxime DΓ©nΓ¨s). - **Added:** :tacn:`lazy`, :tacn:`simpl`, :tacn:`cbn` and :tacn:`cbv` and the associated :cmd:`Eval` and :tacn:`eval` reductions learned to do head reduction when given flag `head` (eg `Eval lazy head in (fun x => Some ((fun y => y) x)) 0` produces `Some ((fun y => y) 0)`) (`#17503 `_, by GaΓ«tan Gilbert; :tacn:`cbv` case added in `#18190 `_, by Hugo Herbelin). - **Fixed:** ensure that opaque primitive projections are correctly handled by "Evarconv" unification (`#17788 `_, fixes `#17774 `_, by Rodolphe Lepigre). - **Fixed:** Useless duplications with :cmd:`Hint Cut` and :cmd:`Hint Mode` (`#17887 `_, fixes `#17417 `_, by Hugo Herbelin). - **Fixed:** `zify` / `Z.euclidean_division_equations_cleanup` now no longer instantiates dependent hypotheses. This will by necessity make `Z.to_euclidean_division_equations` a bit weaker, but the previous behavior was overly sensitive to hypothesis ordering. See `#17935 `_ for a recipe to recapture the power of the previous behavior in a more robust albeit slower way (`#17935 `_, fixes `#17936 `_, by Jason Gross). - **Fixed:** :tacn:`simpl` now working on reducible named mutual fixpoints with parameters (`#17993 `_, fixes `#12521 `_ and part of `#3488 `_, by Hugo Herbelin). - **Fixed:** support for reasoning up to polymorphic universe variables in :tacn:`congruence` and :tacn:`f_equal` (`#18106 `_, fixes `#5481 `_ and `#9979 `_, by Hugo Herbelin). - **Fixed:** Only run zify saturation on existing hypotheses of the goal (`#18152 `_, fixes `#18151 `_, by FrΓ©dΓ©ric Besson and Rodolphe Lepigre). - **Fixed:** A stack overflow due to a non-tail recursive function in `lia` (`#18159 `_, fixes `#18158 `_, by Jan-Oliver Kaiser and Rodolphe Lepigre). - **Fixed:** Apply substitution in Case stack node for cbv reify (`#18195 `_, fixes `#18194 `_, by Yann Leray). - **Fixed:** Anomaly of :tacn:`simpl` on partially applied named mutual fixpoints (`#18243 `_, fixes `#18239 `_, by Hugo Herbelin). - **Changed:** :tacn:`simpl` tries to reduce named mutual fixpoints also when they return functions (`#18243 `_, by Hugo Herbelin). Ltac language ^^^^^^^^^^^^^ - **Fixed:** Fix broken "r " and "r " commands in the coqtop Ltac debugger, which also affected the Proof General Ltac debugger (`#18068 `_, fixes `#18067 `_, by Jim Fehrle). .. _819Ltac2: Ltac2 language ^^^^^^^^^^^^^^ - **Changed:** `Array.empty`, `Message.Format.stop` and `Pattern.empty_context` are not thunked (`#17534 `_, by GaΓ«tan Gilbert). - **Changed:** Ltac2 `exact` and `eexact` elaborate their argument using the type of the goal as expected type, instead of elaborating with no expected type then unifying the resulting type with the goal (`#18157 `_, fixes `#12827 `_, by GaΓ«tan Gilbert). - **Changed:** argument order for the Ltac2 combinators `List.fold_left` `List.fold_right` and `Array.fold_right` changed to be the same as in OCaml (`#18197 `_, fixes `#16485 `_, by GaΓ«tan Gilbert). - **Changed:** `Ltac2.Std.red_flags` added field `rStrength` to support head-only reduction (`#18273 `_, fixes `#18209 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 supports pattern quotations when building `pattern` values. This allows building dynamic patterns, eg `Ltac2 eq_pattern a b := pattern:($pattern:a = $pattern:b)` (`#17667 `_, by GaΓ«tan Gilbert). - **Added:** new standard library modules `Ltac2.Unification` and `Ltac2.TransparentState` providing access to "Evarconv" unification, including the configuration of the transparency state (`#17777 `_, by Rodolphe Lepigre). - **Added:** ``Ltac2.Constr.is_float``, ``Ltac2.Constr.is_uint63``, ``Ltac2.Constr.is_array`` (`#17894 `_, by Jason Gross). - **Added:** new Ltac2 standard library modules `Ltac2.Ref`, `Ltac2.Lazy` and `Ltac2.RedFlags` - **Added:** new Ltac2 standard library functions to `Ltac2.Control`, `Ltac2.Array`, and `Ltac2.List` (`#18095 `_, fixes `#10112 `_, by Rodolphe Lepigre). - **Added:** Support for the ``setoid_rewrite`` tactic (`#18102 `_, by quarkcool). - **Added:** :cmd:`Ltac2 Globalize` and :cmd:`Ltac2 Check` useful to investigate the expansion of Ltac2 notations (`#18139 `_, by GaΓ«tan Gilbert). - **Added:** A new flag :flag:`Ltac2 In Ltac1 Profiling` (unset by default) to control whether Ltac2 stack frames are included in Ltac profiles (`#18293 `_, by Rodolphe Lepigre). - **Added:** `Ltac2.Message.Format.ikfprintf` useful to implement conditional printing efficiently (i.e. without building an unused message when not printing) (`#18311 `_, fixes `#18292 `_, by GaΓ«tan Gilbert). - **Fixed:** Ltac2 mutable references are not considered values anymore (`#18082 `_, by GaΓ«tan Gilbert). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** :cmd:`Let` with :cmd:`Qed` produces an opaque side definition instead of being treated as a transparent `let` after the section is closed. The previous behaviour can be recovered using :attr:`clearbody` and :cmd:`Defined` (`#17576 `_, by GaΓ«tan Gilbert). - **Changed:** automatic lowering of record types to `Prop` now matches the behavior for inductives: no lowering when universe polymorphism is on, more lowering with recursive records (`#17795 `_, fixes `#17801 `_ and `#17796 `_ and `#17801 `_ and `#17805 `_, by GaΓ«tan Gilbert). - **Added:** :opt:`Extraction Output Directory` option for specifying the directory in which extracted files are written (`#16126 `_, fixes `#9148 `_, by Ali Caglayan). - **Added:** `-profile` command line argument and `PROFILE` variable in `coq_makefile` to control a new :ref:`profiling` system (`#17702 `_, by GaΓ«tan Gilbert). - **Added:** new command modifier :cmd:`Instructions` that executes the given command and displays the number of CPU instructions it took to execute it. This command is currently only supported on Linux systems, but it does not fail on other systems, where it simply shows an error message instead of the count. (`#17744 `_, by Rodolphe Lepigre). - **Added:** support for instruction counts to the `-profile` option. (`#17744 `_, by Rodolphe Lepigre). - **Added:** New command :cmd:`Attributes` to assign attributes such as :attr:`deprecated` to a library file (`#18193 `_, fixes `#8032 `_, by Hugo Herbelin). - **Fixed:** Anomaly with :cmd:`Search` in the context of a goal (`#17987 `_, fixes `#17963 `_, by Hugo Herbelin). - **Fixed:** The printer for :cmd:`Guarded` was possibly raising an anomaly in the presence of existential variables (`#18008 `_, fixes `#18006 `_, by Hugo Herbelin). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** Add a `coqdep` option `-w` to adjust warnings and allow turning then into errors like the corresponding `coqc` option (`#17946 `_, fixes `#10156 `_, by David Swasey and Rodolphe Lepigre). - **Fixed:** properly delayed variable expansion when `coq_makefile` uses the combined rule for `.vo` and `.glob` targets, i.e. on GNU Make 4.4 and later. (`#18077 `_, fixes `#18076 `_, by GaΓ«tan Gilbert). - **Fixed:** Spurious `coqdep` warnings due to missing path normalization for plugins (`#18165 `_, by Rodolphe Lepigre). - **Fixed:** Regression in option :g:`--external` of `coqdoc`, whose two arguments were inadvertently swapped (`#18448 `_, fixes `#18434 `_, by Hugo Herbelin). .. _819Stdlib: Standard library ^^^^^^^^^^^^^^^^ - **Changed:** reimplemented `Ncring_tac` reification (used by :tacn:`nsatz`, `cring`, but not :tacn:`ring`) in Ltac instead of typeclasses (`#18325 `_, by GaΓ«tan Gilbert). - **Removed:** :g:`Numbers.Cyclic.ZModulo` from the standard library. This file was deprecated in 8.17 and has no known use cases. It is retained in the test suite to ensure consistency of :g:`CyclicAxioms` (`#17258 `_, by Andres Erbsen). - **Removed:** :g:`ZArith.Zdigits` in favor of :g:`Z.testbit` (`#18025 `_, by Andres Erbsen). - **Removed:** long deprecated files in `Arith`: `Div2.v`, `Even.v`, `Gt.v`, `Le.v`, `Lt.v`, `Max.v`, `Minus.v`, `Min.v`, `Mult.v`, `Plus.v`, `Arith_prebase.v` (`#18164 `_, by Pierre Rousselin). - **Deprecated:** :g:`NArith.Ndigits` and :g:`NArith.Ndist` due to disuse. For most uses of `Ndigits`, `N.testbit` and similar functions seem more desirable. If you would like to continue using these files, please consider volunteering to maintain them, within stdlib or otherwise (`#17732 `_, by Andres Erbsen). - **Deprecated:** :g:`Strings.ByteVector` in favor of :g:`Init.Byte` (`#18022 `_, by Andres Erbsen). - **Deprecated:** :g:`Numbers.NaryFunctions` due to disuse. If you are interested in continuting to use this module, please consider volunteering to maintain it, in stdlib or otherwise (`#18026 `_, by Andres Erbsen). - **Added:** Lemma `cardinal_Add_In` says that inserting an existing key with a new value doesn't change the size of a map, lemma `Add_transpose_neqkey` says that unequal keys can be inserted into a map in any order (`#12096 `_, by Isaac van Bakel and Jean-Christophe LΓ©chenet). - **Added:** lemmas :g:`app_eq_cons`, :g:`app_inj_pivot` and :g:`rev_inj` (`#17787 `_, by Stefan Haan, with help of Olivier Laurent). - **Added:** ``unfold_nth_error``, ``nth_error_nil``, ``nth_error_cons``, ``nth_error_O``, ``nth_error_S`` to ``Coq.Lists.List`` (`#17998 `_, by Jason Gross). - **Added:** ``Reflexive``, ``Symmetric``, ``Transitive``, ``Antisymmetric``, ``Asymmetric`` instances for ``Rle``, ``Rge``, ``Rlt``, ``Rgt`` (`#18059 `_, by Jason Gross). Extraction ^^^^^^^^^^ - **Fixed:** In the error message about extraction of sort-polymorphic singleton inductive types, do not specifically refer to OCaml as other languages are also concerned (`#17889 `_, fixes `#17817 `_, by Hugo Herbelin). Changes in 8.19.1 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** incorrect abstraction of sort variables for opaque constants leading to an inconsistency (`#18596 `_ and `#18630 `_, fixes `#18594 `_, by GaΓ«tan Gilbert). - **Fixed:** memory corruption with :tacn:`vm_compute` (rare but more likely with OCaml 5.1) (`#18599 `_, by Guillaume Melquiond). Notations ^^^^^^^^^ - **Changed:** :warn:`Found no matching notation to enable or disable` is a warning instead of an error (`#18670 `_, by Pierre Roux). Tactics ^^^^^^^ - **Fixed:** undeclared universe with multiple uses of :tacn:`abstract` (`#18640 `_, fixes `#18636 `_, by GaΓ«tan Gilbert). Ltac2 language ^^^^^^^^^^^^^^ - **Fixed:** incorrect printing of constructor values with multiple arguments, and over-parenthesizing of constructor printing (`#18560 `_, fixes `#18556 `_, by GaΓ«tan Gilbert). - **Fixed:** incorrect declared type for `Ltac2.FMap.fold` (`#18649 `_, fixes `#18635 `_, by GaΓ«tan Gilbert). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** missing `conf-` dependencies of the opam packages: `coq-core` depends on `conf-linux-libc-dev` when compiled on linux, and `coq` depends on `conf-python-3` and `conf-time` to run the test suite (`#18565 `_, by GaΓ«tan Gilbert). - **Fixed:** avoid comitting symlinks to git which caused build failures on some Windows setups (`#18550 `_, fixes `#18548 `_, by GaΓ«tan Gilbert). Changes in 8.19.2 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** Regression from Coq 8.18 in the presence of a defined field in a primitive :n:`Record` (`#19088 `_, fixes `#19082 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Fixed:** Printer sometimes failing to use a prefix or infix custom notation whose right-hand side refers to a different custom entry (`#18089 `_, fixes `#18914 `_, by Hugo Herbelin). Tactics ^^^^^^^ - **Fixed:** :tacn:`abstract` failing in the presence of admitted goals in the surrounding proof (`#18945 `_, fixes `#18942 `_, by GaΓ«tan Gilbert). Ltac2 language ^^^^^^^^^^^^^^ - **Fixed:** anomalies when using Ltac2 in VsCoq due to incorrect state handling of Ltac2 notations (`#19096 `_, fixes `coq-community/vscoq#772 `_, by GaΓ«tan Gilbert) Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Fixed:** anomaly when using :cmd:`Include` on a module containing a record declared with :flag:`Primitive Projections` (`#18772 `_, fixes `#18769 `_, by Jan-Oliver Kaiser) - **Fixed:** anomaly from :cmd:`Fixpoint` with no arguments (`#18741 `_, by Hugo Herbelin) CoqIDE ^^^^^^ - **Fixed:** Position error/warning tooltips correctly when multibyte UTF-8 characters are present (`#19137 `_, fixes `#19136 `_, by Jim Fehrle). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** compatibility with OCaml versions where `effect` is a keyword (`#18863 `_, by Remy Seassau) - **Added:** Coq is now compatible with `memprof-limits` interruption methods. This means that Coq will be recompiled when the library is installed / removed from an OPAM switch. (`#18906 `_, fixes `#17760 `_, by Emilio Jesus Gallego Arias). Version 8.18 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.18 integrates two soundness fixes to the Coq kernel along with a host of improvements. We highlight a few impactful changes: - the default :ref:`locality <818HintLocality>` of `Hint` and :cmd:`Instance` commands was switched to :attr:`export`. - the universe unification algorithm can now delay the commitment to a sort (the algorithm used to pick `Type`). Thanks to this feature many `Prop` and `SProp` annotations can be now omitted. - Ltac2 supports array literals, maps and sets of primitive datatypes such as names (of constants, inductive types, etc) and fine-grained control over profiling. - The warning system offers new categories, enabling finer (de)activation of specific warnings. This should be particularly useful to handle deprecations. - Many new lemmas useful for teaching analysis with Coq are now part of the standard library about real numbers. - The `#[deprecated]` attribute can now be applied to definitions. The 41 contributors to the 8.18 version are: Reynald Affeldt, Tanaka Akira, Matthieu Baty, Yves Bertot, Lasse Blaauwbroek, Ana Borges, Kate Deplaix, Ali Caglayan, Cyril Cohen, Maxime DΓ©nΓ¨s, Andrej Dudenhefner, Andres Erbsen, Jim Fehrle, Yannick Forster, Paolo G. Giarrusso, GaΓ«tan Gilbert, Jason Gross, Samuel Gruetter, Stefan Haan, Hugo Herbelin, Yoshihiro Imai, Emilio JesΓΊs Gallego Arias, Olivier Laurent, Meven Lennon-Bertrand, Rodolphe Lepigre, Yishuai Li, Guillaume Melquiond, Karl Palmskog, Pierre-Marie PΓ©drot, Stefan Radziuk, Ramkumar Ramachandra, Pierre Rousselin, Pierre Roux, Julin Shaji, Kazuhiko Sakaguchi, Weng Shiwei, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Hao Yang, ThΓ©o Zimmermann. We are very grateful to the Coq community for their help in creating 8.18 in the 6 months since the release of Coq 8.17.0. Maxime DΓ©nΓ¨s and Enrico Tassi were the release managers. | Sophia-Antipolis, September 2023, | Enrico Tassi for the Coq development team Changes in 8.18.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Changed:** the `bad-relevance` warning is now an error by default (`#17172 `_, by Pierre-Marie PΓ©drot). - **Fixed:** the kernel now checks that case elimination of private inductive types (cf :attr:`private(matching)`) is not used outside their defining module. Previously this was only checked in elaboration and the check could be avoided through some tactics, breaking consistency in the presence of axioms which rely on the elimination restriction to be consistent (`#17452 `_, fixes `#9608 `_, by GaΓ«tan Gilbert). - **Fixed:** a bug enabling :tacn:`native_compute` to yield arbitrary floating-point values (`#17872 `_, fixes `#17871 `_, by Guillaume Melquiond and Pierre Roux, bug found by Jason Gross). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** enhance the universe unification algorithm, which is now able to delay the definition of a sort. This allows omitting some explicit `Prop` and `SProp` annotations when writing terms. Some minor backwards compatibility issues can arise in rare cases, which can be solved with more explicit sort annotations (`#16903 `_, by Pierre-Marie PΓ©drot). - **Changed:** match compilation for primitive record avoids producing an encoding overhead for matches that are equivalent to a primitive projection (`#17008 `_, by GaΓ«tan Gilbert). - **Added:** volatile casts :n:`@term :> @type` which do not leave a trace in the elaborated term. They are used by :flag:`Printing Match All Subterms` to display otherwise hidden subterms of match constructs (`#16992 `_, fixes `#16918 `_, by GaΓ«tan Gilbert). - **Added:** when printing uninterpreted terms (for instance through :cmd:`Print Ltac` on `Ltac foo := exact some_term`), extensions to the term language (for instance :ref:`tactics-in-terms`) are now printed correctly instead of as holes (`_`) (`#17221 `_, by GaΓ«tan Gilbert). - **Added:** Support for the :attr:`local`, :attr:`global` and :attr:`export` locality attributes for the single "field" of :ref:`definitional typeclasses ` when using the ``:>`` and ``::`` syntaxes for coercion and substructures (`#17754 `_, fixes `#17451 `_, by Pierre Roux). - **Added:** a hook in the coercion mechanism to enable programming coercions in external metalanguages such as Ltac, Ltac2, Elpi or OCaml plugins (`#17794 `_, by Pierre Roux). - **Fixed:** canonical instance matching `match` terms (`#17206 `_, fixes `#17079 `_, by GaΓ«tan Gilbert). - **Fixed:** universe constraint inference in module subtyping can trigger constant unfoldings (`#17305 `_, fixes `#17303 `_, by GaΓ«tan Gilbert). Notations ^^^^^^^^^ - **Removed:** The `\'[=\'` keyword. `\'[=\'` tokens in notation definitions should be replaced with the pair of tokens `\'[\' \'=\'`. If compatibility with Coq < 8.18 is needed, replace `[=` in uses of the notation with an added space (`[ =`) (`#16788 `_, fixes `#16785 `_, by Pierre Roux). - **Added:** Support for :flag:`Printing Parentheses` in custom notations (`#17117 `_, by Hugo Herbelin). - **Added:** Improve printing of reverse coercions. When a term :g:`x` is elaborated to :g:`x'` through a reverse coercion, return the term :g:`reverse_coercion x' x` that is convertible to :g:`x'` but displayed :g:`x` thanks to the coercion :g:`reverse_coercion` (`#17484 `_, by Pierre Roux). - **Fixed:** Add support to parse a recursive pattern as a sequence of terms in a recursive notation even when this recursive pattern is used in position of binders; it was formerly raising an anomaly (`#16937 `_, fixes `#12467 `_, by Hugo Herbelin). - **Fixed:** Improved ability to print notations involving anonymous binders (`#17050 `_, by Hugo Herbelin). - **Fixed:** anomaly with notations abbreviating a local variable or record field name (`#17217 `_, fixes `#14975 `_, by Hugo Herbelin). - **Fixed:** Ensure in all cases that a parsing rule is declared when the :n:`only parsing` flag is given (`#17318 `_, fixes `#17316 `_, by Hugo Herbelin). - **Fixed:** In :cmd:`Number Notation`, "abstract after N" was applied when number >= N. Now it is applied when number > N (`#17478 `_, by Jim Fehrle). Tactics ^^^^^^^ - **Changed:** in the fringe case where the ``with`` clause of a call to :tacn:`specialize` depends on a variable bound in the type, the tactic will now fail instead of silently producing a shelved evar (`#17322 `_, by Pierre-Marie PΓ©drot). - **Changed:** extensions to the term syntax through generic arguments (typically `ltac:()`, `ltac2:()` or ltac2's `$`) produce errors when used in term patterns (for instance patterns used to filter hints) instead of being treated as holes (`_`) (`#17352 `_, by GaΓ«tan Gilbert). - **Changed:** the :tacn:`case` tactic and its variants always generate a pattern-matching node, regardless of their argument. In particular, they are now guaranteed to generate as many goals as there are constructors in the inductive type. Previously, they used to reduce to the corresponding branch when the argument Ξ²ΞΉ-normalized to a constructor, resulting in a single goal (`#17541 `_, by Pierre-Marie PΓ©drot). - **Changed:** :tacn:`injection` continues working using sigma types when `Eqdep_dec` has not been required even if an equality scheme was found, instead of failing (`#17670 `_, by GaΓ«tan Gilbert). - **Changed:** the unification heuristics for implicit arguments of the :tacn:`case` tactic. We unconditionally recommend using :tacn:`destruct` instead, and even more so in case of incompatibility (`#17564 `_, by Pierre-Marie PΓ©drot). - **Removed:** the no-argument form of the :tacn:`instantiate` tactic, deprecated since 8.16 (`#16910 `_, by Pierre-Marie PΓ©drot). - **Removed:** undocumented tactics `hresolve_core` and `hget_evar` (`#17035 `_, by GaΓ«tan Gilbert). - **Deprecated:** the `elimtype` and `casetype` tactics (`#16904 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** `revert dependent`, which is a misleadingly named alias of :tacn:`generalize dependent` (`#17669 `_, by GaΓ«tan Gilbert). - **Fixed:** The :tacn:`simpl` tactic now respects the :n:`simpl never` flag even when the subject function is referred to through another definition (`#13448 `_, fixes `#13428 `_, by Yves Bertot). - **Fixed:** unification is less sensitive to whether a subterm is an indirection through a defined existential variable or a direct term node. This results in less constant unfoldings in rare cases (`#16960 `_, by GaΓ«tan Gilbert). - **Fixed:** untypable proof states generated by setoid_rewrite, which may cause some backwards-incompatibilities (`#17304 `_, fixes `#17295 `_, by Lasse Blaauwbroek). - **Fixed:** intropatterns destructing a term whose type is a product cannot silently create shelved evars anymore. Instead, it fails with an unsolvable variable. This can be fixed in a backwards compatible way by using the e-variant of the parent tactic (`#17564 `_, by Pierre-Marie PΓ©drot). - **Fixed:** the :tacn:`field_simplify` tactic, so that it no longer introduces side-conditions when working on a hypothesis (`#17591 `_, by Guillaume Melquiond). - **Fixed:** the :tacn:`tauto` tactic and its variants now try to match types up to universe unification. This makes them compatible with universe-polymorphic code (`#8905 `_, fixes `#4721 `_ and `#5351 `_, by Pierre-Marie PΓ©drot). Ltac2 language ^^^^^^^^^^^^^^ - **Added:** Support for parsing Ltac2 array literals ``[| ... |]`` (`#16859 `_, fixes `#13976 `_, by Samuel Gruetter). - **Added:** Finite set and map APIs for identifier, string, int, constant, inductive and constructor keys (`#17347 `_, c.f. `#16409 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 preterm antiquotation `$preterm:` (`#17359 `_, fixes `#13977 `_, by GaΓ«tan Gilbert). - **Added:** :flag:`Ltac Profiling` also profiles Ltac2 tactics. Ltac2 also provides tactics `start_profiling` `stop_profiling` and `show_profile` for finer grained control (`#17371 `_, fixes `#10111 `_, by GaΓ«tan Gilbert). - **Added:** primitives to build and compare values in `Ltac2.Init.cast` (`#17468 `_, by GaΓ«tan Gilbert). - **Added:** It is possible to define 0-argument externals (`#17475 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 quotations :ref:`ltac2val:(ltac2 tactic) ` in Ltac1 which produce Ltac1 values (as opposed to `ltac2:()` quotations which are only useful for their side effects) (`#17575 `_, by GaΓ«tan Gilbert). - **Fixed:** nested notations involving :ref:`term-antiquotations` (`#17232 `_, fixes `#15864 `_, by GaΓ«tan Gilbert). - **Fixed:** Parsing level of :g:`by` clause of Ltac2's :g:`assert` (`#17508 `_, fixes `#17491 `_, by Samuel Gruetter). - **Fixed:** `multi_match!`, `multi_match! goal` and the underlying `Ltac2.Pattern.multi_match0` and `Ltac2.Pattern.multi_goal_match0` now preserve exceptions from backtracking after a branch succeeded instead of replacing them with `Match_failure` (e.g. `multi_match! constr:(tt) with tt => () end; Control.zero Not_found` now fails with `Not_found` instead of `Match_failure`) (`#17597 `_, fixes `#17594 `_, by GaΓ«tan Gilbert). Commands and options ^^^^^^^^^^^^^^^^^^^^ .. _818HintLocality: - **Changed:** the default locality of `Hint` and :cmd:`Instance` commands was switched to :attr:`export` (`#16258 `_, by Pierre-Marie PΓ©drot). - **Changed:** warning `non-primitive-record` is now in category `records` instead of `record`. This was the only use of `record` but the plural version is also used by `cannot-define-projection` `future-coercion-class-constructor` and `future-coercion-class-field`. (`#16989 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Eval` prints information about existential variables like :cmd:`Check` (`#17274 `_, by GaΓ«tan Gilbert). - **Changed:** The names of deprecation warnings now depend on the version in which they were introduced, using their "since" field. This enables deprecation warnings to be selectively enabled, disabled, or treated as an error, according to the version number provided in the :attr:`deprecated` attribute (`#17489 `_, fixes `#16287 `_, by Pierre Roux, reviewed by Ali Caglayan, ThΓ©o Zimmermann and GaΓ«tan Gilbert). - **Changed:** warnings can now have multiple categories allowing for finer user control on which warning to enable, disable or treat as an error (`#17585 `_, by GaΓ«tan Gilbert). - **Changed:** :attr:`Template polymorphic ` inductive types are not implicitly added to the :table:`Keep Equalities` table anymore when defined. This may change the behavior of equality-related tactics on such types (`#17718 `_, by Pierre-Marie PΓ©drot). - **Changed:** :opt:`Warnings` and :attr:`warnings` now emit a warning when trying to enable an unknown warning (there is still no warning when disabling an unknown warning as this behavior is useful for compatibility, or when enabling an unknown warning through the command line `-w` as the warning may be in a yet to be loaded plugin) (`#17747 `_, by GaΓ«tan Gilbert). - **Removed:** the flag `Apply With Renaming` which was deprecated since 8.15 (`#16909 `_, by Pierre-Marie PΓ©drot). - **Removed:** the `Typeclasses Filtered Unification` flag, deprecated since 8.16 (`#16911 `_, by Pierre-Marie PΓ©drot). - **Removed:** :attr:`program` attribute is not accepted anymore with commands :cmd:`Add Relation`, :cmd:`Add Parametric Relation`, :cmd:`Add Setoid`, :cmd:`Add Parametric Setoid`, :cmd:`Add Morphism`, :cmd:`Add Parametric Morphism`, :cmd:`Declare Morphism`. Previously, it was accepted but ignored (`#17042 `_, by ThΓ©o Zimmermann). - **Removed:** the `Elaboration StrictProp Cumulativity` and `Cumulative SProp` flags. These flags became counterproductive after the introduction of sort variables in unification (`#17114 `_, fixes `#17108 `_, by Pierre-Marie PΓ©drot). - **Removed:** The ``Add LoadPath``, ``Add Rec LoadPath``, ``Add ML Path``, and ``Remove LoadPath`` commands have been removed following deprecation. Users are encouraged to use the existing mechanisms in ``coq_makefile`` or ``dune`` to configure workspaces of Coq theories (`#17394 `_, by Emilio Jesus Gallego Arias). - **Deprecated:** `Export` modifier for :cmd:`Set`. Use attribute :attr:`export` instead (`#17333 `_, by GaΓ«tan Gilbert). - **Deprecated:** the :attr:`nonuniform` attribute, now subsumed by :attr:`warnings` with "-uniform-inheritance" (`#17716 `_, by Pierre Roux). - **Deprecated:** Using :cmd:`Qed` with :cmd:`Let`. End the proof with :cmd:`Defined` and use :attr:`clearbody` instead to get the same behavior (`#17544 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`About` now prints information when a constant or inductive is syntactically equal to another through module aliasing (`#16796 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Final Obligation` command (`#16817 `_, by GaΓ«tan Gilbert). - **Added:** The :attr:`deprecated` attribute is now supported for definition-like constructions (`#16890 `_, fixes `#12266 `_, by Maxime DΓ©nΓ¨s and GaΓ«tan Gilbert). - **Added:** attributes :attr:`warnings` and alias :attr:`warning` to set warnings locally for a command (`#16902 `_, fixes `#15893 `_, by GaΓ«tan Gilbert). - **Added:** flag :flag:`Printing Unfolded Projection As Match` (off by default) to be able to distinguish unfolded and folded primitive projections (`#16994 `_, by GaΓ«tan Gilbert). - **Added:** option `-time-file`, like `time` but outputting to a file (`#17430 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Validate Proof` runs the type checker on the current proof, complementary with :cmd:`Guarded` which runs the guard checker (`#17467 `_, by GaΓ«tan Gilbert). - **Added:** :attr:`clearbody` for :cmd:`Let` to clear the body of a let-in in an interactive proof without kernel enforcement. (This is the behavior that was previously provided by using :cmd:`Qed`, which is now deprecated for `Let`\s.) (`#17544 `_, by GaΓ«tan Gilbert). - **Added:** option `-time-file`, like `time` but outputting to a file (`#17430 `_, by GaΓ«tan Gilbert). - **Fixed:** universe monomorphic inductives and records do not ignore :flag:`Universe Minimization ToSet` (`#17285 `_, fixes `#13927 `_, by GaΓ«tan Gilbert). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** Do not pass the ``-rectypes`` flag by default in ``coq_makefile`` when compiling OCaml code, since it is no longer required by Coq. To re-enable passing the flag, put ``CAMLFLAGS+=-rectypes`` in the local makefile, e.g., ``CoqMakefile.local`` (see :ref:`rocqmakefilelocal`) (`#17038 `_, by Karl Palmskog with help from GaΓ«tan Gilbert). - **Changed:** disable inclusion of variable binders in coqdoc indexes by default, and provide a new coqdoc option `--binder-index` for including them (`#17045 `_, fixes `#13155 `_, by Karl Palmskog). - **Added:** `coqdoc` handles multiple links to the same source. For example when declaring an inductive type `t` all occurences of `t` itself and its elimination principles like `t_ind` point to its declaration (`#17118 `_, by Enrico Tassi). - **Added:** Command line options :n:`-require lib` (replacing :n:`-load-vernac-object lib`) and :n:`-require-from root lib` respectively equivalent to vernacular commands :n:`Require lib` and :n:`From root Require lib` (`#17364 `_, by Hugo Herbelin). - **Added:** `coqtimelog2html` command-line tool used to render the timing files produced with `-time` (which is passed by `coq_makefile` when environment variable `TIMING` is defined) (`#17411 `_, by GaΓ«tan Gilbert). - **Fixed:** `coq_makefile` avoids generating a command containing all files to install in a make rule, which could surpass the maximum single argument size in some developments (`#17697 `_, fixes `#17721 `_, by GaΓ«tan Gilbert). CoqIDE ^^^^^^ - **Changed:** XML Protocol now sends (and expects) full Coq locations, including line and column information. This makes some IDE operations (such as UTF-8 decoding) more efficient. Clients of the XML protocol can just ignore the new fields if they are not useful for them (`#17382 `_, fixes `#17023 `_, by Emilio Jesus Gallego Arias). Standard library ^^^^^^^^^^^^^^^^ - **Changed:** implementation of :g:`Vector.nth` to follow OCaml and compute strict subterms (`#16731 `_, fixes `#16738 `_, by Andrej Dudenhefner). - **Changed:** drop the unnecessary second assumption :g:`NoDup l'` from :g:`set_diff_nodup` in ``ListSet.v``, with `-compat 8.17` providing the old version of :g:`set_diff_nodup` for compatibility (`#16926 `_, by Karl Palmskog with help from Traian Florin ŞerbΔƒnuΕ£Δƒ and Andres Erbsen). - **Changed:** Moved instances from :g:`DecidableClass` to files that prove the relevant decidability facts: :g:`Bool`, :g:`PeanoNat`, and :g:`BinInt` (`#17021 `_, by Andres Erbsen). - **Changed:** `Hint Extern` `btauto.Algebra.bool` locality from :attr:`global` to :attr:`export` (`#17281 `_, by Andres Erbsen). - **Changed:** :g:`xorb` to a simpler definition (`#17427 `_, by Guillaume Melquiond). - **Changed** lemmas in `Reals/RIneq.v` - :g:`completeness_weak` renamed as :g:`upper_bound_thm`, - :g:`le_epsilon` renamed as :g:`Rle_epsilon`, - :g:`Rplus_eq_R0` renamed as :g:`Rplus_eq_0`, - :g:`Req_EM_T` renamed as :g:`Req_dec_T`, - :g:`Rinv_r_simpl_m` renamed as :g:`Rmult_inv_r_id_m`, - :g:`Rinv_r_simpl_l` renamed as :g:`Rmult_inv_r_id_l`, - :g:`Rinv_r_simpl_r` renamed as :g:`Rmult_inv_m_id_r`, - :g:`tech_Rgt_minus` renamed as :g:`Rgt_minus_pos`, - :g:`tech_Rplus` renamed as :g:`Rplus_le_lt_0_neq_0`, - :g:`IZR_POS_xI` modified with `2` instead of `1 + 1`, - :g:`IZR_POS_xO` modified with `2` instead of `1 + 1`, - :g:`Rge_refl` modified with `>=` instead of `<=` (`#17036 `_, by Pierre Rousselin, reviewer Laurent ThΓ©ry). - **Removed:** :g:`Datatypes.prod_curry`, :g:`Datatypes.prod_uncurry`, :g:`Datatypes.prodT_curry`, :g:`Datatypes.prodT_uncurry`, :g:`Combinators.prod_curry_uncurry`, :g:`Combinators.prod_uncurry_curry`, :g:`Bool.leb`, :g:`Bool.leb_implb`, :g:`List.skipn_none`, :g:`Zdiv.Z_div_mod_eq`, :g:`Zdiv.div_Zdiv`, :g:`Zdiv.mod_Zmod`, :g:`FloatOps.frexp`, :g:`FloatOps.ldexp`, :g:`FloatLemmas.frexp_spec`, :g:`FloatLemmas.ldexp_spec`, :g:`RList.Rlist`, :g:`Rlist.cons`, :g:`Rlist.nil`, :g:`RList.Rlength`, :g:`Rtrigo_calc.cos3PI4`, :g:`Rtrigo_calc.sin3PI4`, :g:`MSetRBT.filter_app` after deprecation for at least two Coq versions (`#16920 `_, by Olivier Laurent). - **Deprecated:** :g:`List.app_nil_end`, :g:`List.app_assoc_reverse`, :g:`List.ass_app`, :g:`List.app_ass` (`#16920 `_, by Olivier Laurent). - **Deprecated:** `Coq.Lists.List.Forall2_refl` (`Coq.Lists.List.Forall2_nil` has the same type) (`#17646 `_, by GaΓ«tan Gilbert). - **Deprecated:** :g:`ZArith.Zdigits` in favor of :g:`Z.testbit`. If you are aware of a use case of this module and would be interested in a drop-in replacement, please comment on the PR with information about the context that would benefit from such functinality (`#17733 `_, by Andres Erbsen). - **Deprecated:** Deprecation warnings are now generated for :g:`Numbers.Cyclic.Int31.Cyclic31`, :g:`NNumbers.Cyclic.Int31.Int31`, and :g:`NNumbers.Cyclic.Int31.Ring31`. These modules have been deprecated since Coq 8.10. The modules under :g:`Numbers.Cyclic.Int63` remain available (`#17734 `_, by Andres Erbsen). - **Deprecated** lemmas in `Reals/RIneq.v` :g:`inser_trans_R`, :g:`IZR_neq`, :g:`double`, :g:`double_var`, :g:`Rinv_mult_simpl`, :g:`Rle_Rinv`, :g:`Rlt_Rminus`, :g:`Rminus_eq_0`, :g:`Rminus_gt_0_lt`, :g:`Ropp_div`, :g:`Ropp_minus_distr'`, :g:`Rplus_sqr_eq_0_l`, :g:`sum_inequa_Rle_lt_depr`, :g:`S_O_plus_INR_depr`, :g:`single_z_r_R1_depr`, :g:`tech_single_z_r_R1_depr`, (`#17036 `_, by Pierre Rousselin, reviewer Laurent ThΓ©ry). - **Added:** lemmas :g:`L_inj`, :g:`R_inj`, :g:`L_R_neq`, :g:`case_L_R`, :g:`case_L_R'` to ``Fin.v``, and :g:`nil_spec`, :g:`nth_append_L`, :g:`nth_append_R`, :g:`In_nth`, :g:`nth_replace_eq`, :g:`nth_replace_neq`, :g:`replace_append_L`, :g:`replace_append_R`, :g:`append_const`, :g:`map_append`, :g:`map2_ext`, :g:`append_inj`, :g:`In_cons_iff`, :g:`Forall_cons_iff`, :g:`Forall_map`, :g:`Forall_append`, :g:`Forall_nth`, :g:`Forall2_nth`, :g:`Forall2_append`, :g:`map_shiftin`, :g:`fold_right_shiftin`, :g:`In_shiftin`, :g:`Forall_shiftin`, :g:`rev_nil`, :g:`rev_cons`, :g:`rev_shiftin`, :g:`rev_rev`, :g:`map_rev`, :g:`fold_left_rev_right`, :g:`In_rev`, :g:`Forall_rev` to ``VectorSpec.v`` (`#16765 `_, closes `#6459 `_, by Andrej Dudenhefner). - **Added:** lemmas :g:`iter_swap_gen`, :g:`iter_swap`, :g:`iter_succ`, :g:`iter_succ_r`, :g:`iter_add`, :g:`iter_ind`, :g:`iter_rect`, :g:`iter_invariant` for `Nat.iter` (`#17013 `_, by Stefan Haan with help from Jason Gross). - **Added:** module :g:`Zbitwise` with basic relationships between bitwise and arithmetic operations on integers (`#17022 `_, by Andres Erbsen). - **Added:** lemmas :g:`forallb_filter`, :g:`forallb_filter_id`, :g:`partition_as_filter`, :g:`filter_length`, :g:`filter_length_le` and :g:`filter_length_forallb` (`#17027 `_, by Stefan Haan with help from Olivier Laurent and Andres Erbsen). - **Added:** lemmas in `Reals/RIneq.v`: :g:`eq_IZR_contrapositive`, :g:`INR_0`, :g:`INR_1`, :g:`INR_archimed`, :g:`INR_unbounded`, :g:`IPR_2_xH`, :g:`IPR_2_xI`, :g:`IPR_2_xO`, :g:`IPR_eq`, :g:`IPR_ge_1`, :g:`IPR_gt_0`, :g:`IPR_IPR_2`, :g:`IPR_le`, :g:`IPR_lt`, :g:`IPR_not_1`, :g:`IPR_xH`, :g:`IPR_xI`, :g:`IPR_xO`, :g:`le_IPR`, :g:`lt_1_IPR`, :g:`lt_IPR`, :g:`minus_IPR`, :g:`mult_IPR`, :g:`not_1_IPR`, :g:`not_IPR`, :g:`plus_IPR`, :g:`pow_IPR`, :g:`Rdiv_0_l`, :g:`Rdiv_0_r`, :g:`Rdiv_1_l`, :g:`Rdiv_1_r`, :g:`Rdiv_def`, :g:`Rdiv_diag_eq`, :g:`Rdiv_diag`, :g:`Rdiv_diag_uniq`, :g:`Rdiv_eq_compat_l`, :g:`Rdiv_eq_compat_r`, :g:`Rdiv_eq_reg_l`, :g:`Rdiv_eq_reg_r`, :g:`Rdiv_mult_distr`, :g:`Rdiv_mult_l_l`, :g:`Rdiv_mult_l_r`, :g:`Rdiv_mult_r_l`, :g:`Rdiv_mult_r_r`, :g:`Rdiv_neg_neg`, :g:`Rdiv_neg_pos`, :g:`Rdiv_opp_l`, :g:`Rdiv_pos_cases`, :g:`Rdiv_pos_neg`, :g:`Rdiv_pos_pos`, :g:`Rexists_between`, :g:`Rge_gt_or_eq_dec`, :g:`Rge_gt_or_eq`, :g:`Rge_lt_dec`, :g:`Rge_lt_dec`, :g:`Rgt_le_dec`, :g:`Rgt_minus_pos`, :g:`Rgt_or_le`, :g:`Rgt_or_not_gt`, :g:`Rinv_0_lt_contravar`, :g:`Rinv_eq_compat`, :g:`Rinv_eq_reg`, :g:`Rinv_lt_0_contravar`, :g:`Rinv_neg`, :g:`Rinv_pos`, :g:`Rle_gt_dec`, :g:`Rle_half_plus`, :g:`Rle_lt_or_eq`, :g:`Rle_or_gt`, :g:`Rle_or_not_le`, :g:`Rlt_0_2`, :g:`Rlt_0_minus`, :g:`Rlt_ge_dec`, :g:`Rlt_half_plus`, :g:`Rlt_minus_0`, :g:`Rlt_or_ge`, :g:`Rlt_or_not_lt`, :g:`Rminus_def`, :g:`Rminus_diag`, :g:`Rminus_eq_compat_l`, :g:`Rminus_eq_compat_r`, :g:`Rminus_plus_distr`, :g:`Rminus_plus_l_l`, :g:`Rminus_plus_l_r`, :g:`Rminus_plus_r_l`, :g:`Rminus_plus_r_r`, :g:`Rmult_div_assoc`, :g:`Rmult_div_l`, :g:`Rmult_div_r`, :g:`Rmult_div_swap`, :g:`Rmult_gt_reg_r`, :g:`Rmult_inv_l`, :g:`Rmult_inv_m_id_r`, :g:`Rmult_inv_r`, :g:`Rmult_inv_r_id_l`, :g:`Rmult_inv_r_id_m`, :g:`Rmult_inv_r_uniq`, :g:`Rmult_neg_cases`, :g:`Rmult_neg_neg`, :g:`Rmult_neg_pos`, :g:`Rmult_pos_cases`, :g:`Rmult_pos_neg`, :g:`Rmult_pos_pos`, :g:`Ropp_div_distr_l`, :g:`Ropp_eq_reg`, :g:`Ropp_neg`, :g:`Ropp_pos`, :g:`Rplus_0_l_uniq`, :g:`Rplus_eq_0`, :g:`Rplus_ge_reg_r`, :g:`Rplus_gt_reg_r`, :g:`Rplus_minus_assoc`, :g:`Rplus_minus_l`, :g:`Rplus_minus_r`, :g:`Rplus_minus_swap`, :g:`Rplus_neg_lt`, :g:`Rplus_neg_neg`, :g:`Rplus_neg_npos`, :g:`Rplus_nneg_ge`, :g:`Rplus_nneg_nneg`, :g:`Rplus_nneg_pos`, :g:`Rplus_npos_le`, :g:`Rplus_npos_neg`, :g:`Rplus_npos_npos`, :g:`Rplus_pos_gt`, :g:`Rplus_pos_nneg`, :g:`Rplus_pos_pos`, :g:`Rsqr_def` lemmas in `Reals/R_Ifp.v`: :g:`Int_part_spec`, :g:`Rplus_Int_part_frac_part`, :g:`Int_part_frac_part_spec` (`#17036 `_, by Pierre Rousselin, reviewer Laurent ThΓ©ry). - **Added:** lemmas :g:`concat_length`, :g:`flat_map_length`, :g:`flat_map_constant_length`, :g:`list_power_length` to `Lists.List` (`#17082 `_, by Stefan Haan with help from Olivier Laurent). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Sphinx 4.5.0 or above is now required to build the reference manual, so now / can be used as a quick search shortcut and Esc as a shortcut to remove search highlighting (`#17772 `_, fixes `#15778 `_, by Ana Borges). Extraction ^^^^^^^^^^ - **Fixed:** Anomaly when extracting within a module or module type (`#17344 `_, fixes `#10739 `_, by Hugo Herbelin). Version 8.17 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.17 integrates a soundness fix to the Coq kernel along with a few new features and a host of improvements to the Ltac2 language and libraries. We highlight some of the most impactful changes here: - :ref:`Fixed <817VmCompute>` a logical inconsistency due to :tacn:`vm_compute` in presence of side-effects in the enviroment (e.g. using `Back` or `Fail`). - It is now possible to dynamically :ref:`enable or disable <817Notations>` notations. - Support :ref:`multiple scopes <817Scopes>` in :cmd:`Arguments` and :cmd:`Bind Scope`. - The tactics chapter of the manual has :ref:`many improvements <817TacticsRefman>` in presentation and wording. The documented grammar is semi-automatically checked for consistency with the implementation. - :ref:`Fixes <817Eauto>` to the :tacn:`auto` and :tacn:`eauto` tactics, to respect hint priorities and the documented use of :tacn:`simple apply`. This is a potentially breaking change. - :ref:`New Ltac2 <817Ltac2>` APIs, deep pattern-matching with ``as`` clauses and handling of literals, support for record types and preterms. - :ref:`Move <817ClassFieldSyntax>` from :g:`:>` to :g:`::` syntax for declaring typeclass fields as instances, fixing a confusion with declaration of coercions. - :ref:`Standard library <817Stdlib>` improvements. - While Coq supports OCaml 5, users are likely to experience slowdowns ranging from +10% to +50% compared to OCaml 4. Moreover, the :tacn:`native_compute` machinery is not available when Coq is compiled with OCaml 5. Therefore, OCaml 5 support should still be considered experimental and not production-ready. See the `Changes in 8.17.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual for 8.17 `_, `documentation of the 8.17 standard library `_ and `developer documentation of the 8.17 ML API `_ are also available. Ali Caglayan, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. Maxime DΓ©nΓ¨s, Paolo G. Giarrusso, Huα»³nh TrαΊ§n Khanh, and Laurent ThΓ©ry have maintained the VsCoq extension for VS Code. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The `Coq Platform `_ has been maintained by Michael Soegtrop, with help from Karl Palmskog, Pierre Roux, Enrico Tassi and ThΓ©o Zimmermann. Our current maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Ana Borges, Ali Caglayan, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Andres Erbsen, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details. The 45 contributors to the 8.17 version are: Reynald Affeldt, Tanaka Akira, Lasse Blaauwbroek, Stephan Boyer, Ali Caglayan, Cyril Cohen, Maxime DΓ©nΓ¨s, Andrej Dudenhefner, Andres Erbsen, FrantiΕ‘ek Farka, Jim Fehrle, Paolo G. Giarrusso, GaΓ«tan Gilbert, Jason Gross, Alban Gruin, Stefan Haan, Hugo Herbelin, Wolf Honore, Bodo Igler, Jerry James, Emilio JesΓΊs Gallego Arias, Ralf Jung, Jan-Oliver Kaiser, Wojciech Karpiel, Chantal Keller, Thomas Klausner, Olivier Laurent, Yishuai Li, Guillaume Melquiond, Karl Palmskog, Sudha Parimala, Pierre-Marie PΓ©drot, Valentin Robert, Pierre Roux, Julin S, Dmitry Shachnev, Michael Soegtrop, Matthieu Sozeau, Naveen Srinivasan, Sergei Stepanenko, Karolina Surma, Enrico Tassi, Li-yao Xia and ThΓ©o Zimmermann. The Coq community at large helped improve this new version via the GitHub issue and pull request system, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.17's development spanned 5 months from the release of Coq 8.16.0. ThΓ©o Zimmermann is the release manager of Coq 8.17. This release is the result of 414 merged PRs, closing 105 issues. | Nantes, February 2023, | Matthieu Sozeau for the Coq development team Changes in 8.17.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ .. _817VmCompute: - **Fixed:** inconsistency linked to :tacn:`vm_compute`. The fix removes a vulnerable cache, thus it may result in slowdowns when :tacn:`vm_compute` is used repeatedly, if you encounter such slowdowns please report your use case (`#16958 `_, fixes `#16957 `_, by GaΓ«tan Gilbert). - **Fixed:** Unexpected anomaly when checking termination of fixpoints containing :g:`match` expressions with inaccessible branches (`#17116 `_, fixes `#17073 `_, by Hugo Herbelin). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** :warn:`Unused variable ` warning triggers even when catching a single case. This warning used to be triggered only when the unused variable was catching at least two cases (`#16135 `_, by Pierre Roux). - **Fixed:** Pattern-matching clauses were possibly lost when matching over a constructor from a singleton inductive type in the presence of implicit coercions (`#17138 `_, fixes `#17137 `_, by Hugo Herbelin). - **Fixed:** Possible anomaly when using syntax :g:`term.(proj)` with projections defined in sections (`#17174 `_, fixes `#17173 `_, by Hugo Herbelin). Notations ^^^^^^^^^ - **Changed:** When multiple tokens match the beginning of a sequence of characters, the longest matching token not cutting a subsequence of contiguous letters in the middle is used. Previously, this was only the longest matching token. See :ref:`lexical conventions ` for details and examples (`#16322 `_, fixes `#4712 `_, by Hugo Herbelin). .. _817Notations: - **Added:** :cmd:`Enable Notation` and :cmd:`Disable Notation` commands to enable or disable previously defined notations (`#12324 `_ and `#16945 `_, by Hugo Herbelin and Pierre Roux, extending previous work by Lionel Rieg, review by Jim Fehrle). .. _817Scopes: - **Added:** Support for multiple scopes in the :cmd:`Arguments` command (`#16472 `_, by Pierre Roux, review by Jim Fehrle, Hugo Herbelin and Enrico Tassi). - **Added:** Attributes :attr:`add_top` and :attr:`add_bottom` to bind multiple scopes through the :cmd:`Bind Scope` command (`#16472 `_, by Pierre Roux, review by Jim Fehrle, Hugo Herbelin and Enrico Tassi). Tactics ^^^^^^^ .. _817TacticsRefman: - **Changed:** Documentation in the tactics chapter to give the current correct syntax, consolidate tactic variants for each tactic into a single, unified description for each tactic and many wording improvements. With this change, following similar changes to other chapters in previous releases, the correctness of documented syntax is assured by semi-automated tooling in all chapters except SSReflect (`#15015 `_, `#16498 `_, and `#16659 `_, by Jim Fehrle, reviewed by ThΓ©o Zimmermann, with help from many others). .. _817Eauto: - **Changed:** :tacn:`eauto` respects priorities of :cmd:`Extern ` hints (`#16289 `_, fixes `#5163 `_ and `#16282 `_, by Andrej Dudenhefner). .. warning:: Code that relies on eager evaluation of :cmd:`Extern ` hints with high assigned cost by :tacn:`eauto` will change its performance profile or potentially break. To approximate prior behavior, set to zero the cost of :cmd:`Extern ` hints, which may solve the goal in one step. - **Changed:** less discrepancies between :tacn:`auto` hint evaluation and :tacn:`simple apply`, :tacn:`exact` tactics (`#16293 `_, fixes `#16062 `_ and `#16323 `_, by Andrej Dudenhefner). .. warning:: :tacn:`auto` may solve more goals. As a result, non-monotone use of :tacn:`auto` such as :g:`tac1; auto. tac2.` may break. For backwards compatibility use explicit goal management. - **Removed:** `absurd_hyp` tactic, that was marked as obsolete 15 years ago. Use :tacn:`contradict` instead (`#16670 `_, by ThΓ©o Zimmermann). - **Removed:** the undocumented `progress_evars` tactical (`#16843 `_, by ThΓ©o Zimmermann). - **Deprecated:** the default ``intuition_solver`` (see :tacn:`intuition`) now outputs warning ``intuition-auto-with-star`` if it solves a goal with ``auto with *`` that was not solved with just :tacn:`auto`. In a future version it will be changed to just :tacn:`auto`. Use ``intuition tac`` locally or ``Ltac Tauto.intuition_solver ::= tac`` globally to silence the warning in a forward-compatible way with your choice of tactic ``tac`` (``auto``, ``auto with *``, ``auto with`` your prefered databases, or any other tactic) (`#16026 `_, by GaΓ«tan Gilbert). - **Deprecated:** `>` clear modifier that could be used in some tactics like :tacn:`apply` and :tacn:`rewrite` but was never documented. Open an issue if you actually depend on this feature (`#16407 `_, by ThΓ©o Zimmermann). - **Fixed:** :tacn:`auto` now properly updates local hypotheses after hint application (`#16302 `_, fixes `#15814 `_ and `#6332 `_, by Andrej Dudenhefner). - **Fixed:** Make the behavior of :tacn:`destruct ... using ... ` more powerful and more similar to :tacn:`destruct ... ` (`#16605 `_, by Lasse Blaauwbroek). - **Fixed:** typeclass inference sometimes caused remaining holes to fail to be detected (`#16743 `_, fixes `#5239 `_, by GaΓ«tan Gilbert). Ltac language ^^^^^^^^^^^^^ - **Changed:** :cmd:`Ltac` redefinitions (with ``::=``) now respect :attr:`local` (`#16106 `_, by GaΓ«tan Gilbert). - **Changed:** In :tacn:`match goal`, ``match goal with hyp := body : typ |- _`` is syntax sugar for ``match goal with hyp := [ body ] : typ |- _`` i.e. it matches ``typ`` with the type of the hypothesis rather than matching the body as a cast term. This transformation used to be done with any kind of cast (e.g. VM cast ``<:``) and is now done only for default casts ``:`` (`#16764 `_, by GaΓ«tan Gilbert). .. _817Ltac2: Ltac2 language ^^^^^^^^^^^^^^ - **Changed:** ``Ltac2.Bool`` notations are now in a module ``Ltac2.Bool.BoolNotations`` (exported by default), so that these notations can be imported separately (`#16536 `_, by Jason Gross). - **Changed:** ``Constr.in_context`` enforces that the ``constr`` passed to it is a type (`#16547 `_, fixes `#16540 `_, by GaΓ«tan Gilbert). - **Changed:** goal matching functions from ``Ltac2.Pattern`` (``matches_goal``, ``lazy_goal_match0``, ``multi_goal_match0`` and ``one_goal_match0``) have changed types to support matching hypothesis bodies (`#16655 `_, by GaΓ«tan Gilbert). - **Added:** Deep :ref:`pattern matching ` for Ltac2 (`#16023 `_, by GaΓ«tan Gilbert). - **Added:** patterns for Ltac2 matches: ``as``, records and literal integers and strings (`#16179 `_, by GaΓ«tan Gilbert). - **Added:** APIs for working with strings: `Message.to_string`, `String.concat`, `cat`, `equal`, `compare`, `is_empty` (`#16217 `_, by GaΓ«tan Gilbert). - **Added:** ``Ltac2.Constr.Unsafe.liftn`` (`#16413 `_, by Jason Gross). - **Added:** ``Ltac2.Constr.Unsafe.closedn``, ``Ltac2.Constr.Unsafe.is_closed``, ``Ltac2.Constr.Unsafe.occur_between``, ``Ltac2.Constr.Unsafe.occurn`` (`#16414 `_, by Jason Gross). - **Added:** `Ltac2.List.equal` (`#16429 `_, by Jason Gross). - **Added:** :cmd:`Print Ltac2`, :cmd:`Print Ltac2 Signatures` and :cmd:`Locate` can now find Ltac2 definitions (`#16466 `_, fixes `#16418 `_ and `#16415 `_, by GaΓ«tan Gilbert). - **Added:** ``Ltac2.Array.for_all2`` and ``Ltac2.Array.equal`` (`#16535 `_, by Jason Gross). - **Added:** ``Ltac2.Constant.equal``, ``Ltac2.Constant.t``, ``Ltac2.Constructor.equal``, ``Ltac2.Constructor.t``, ``Ltac2.Evar.equal``, ``Ltac2.Evar.t``, ``Ltac2.Float.equal``, ``Ltac2.Float.t``, ``Ltac2.Meta.equal``, ``Ltac2.Meta.t``, ``Ltac2.Proj.equal``, ``Ltac2.Proj.t``, ``Ltac2.Uint63.equal``, ``Ltac2.Uint63.t``, ``Ltac2.Char.equal``, ``Ltac2.Char.compare``, ``Ltac2.Constr.Unsafe.Case.equal`` (`#16537 `_, by Jason Gross). - **Added:** ``Ltac2.Option.equal`` (`#16539 `_, by Jason Gross). - **Added:** syntax for Ltac2 record update ``{ foo with field := bar }`` (`#16552 `_, fixes `#10117 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 record expressions support punning, i.e. ``{ foo; M.bar }`` is equivalent to ``{ foo := foo; M.bar := bar }`` (`#16556 `_, by GaΓ«tan Gilbert). - **Added:** :tacn:`match! goal` support for matching hypothesis bodies (`#16655 `_, fixes `#12803 `_, by GaΓ«tan Gilbert). - **Added:** quotation and syntax class for :ref:`preterms ` (`#16740 `_, by GaΓ«tan Gilbert). SSReflect ^^^^^^^^^ - **Added:** port the additions made to `ssrfun.v` and `ssrbool.v` in math-comp `PR #872 `_ and `PR #874 `_, namely definitions `olift` and `pred_oapp` as well as lemmas `all_sig2_cond`, `compA`, `obindEapp`, `omapEbind`, `omapEapp`, `omap_comp`, `oapp_comp`, `olift_comp`, `ocan_comp`, `eqbLR`, `eqbRL`, `can_in_pcan`, `pcan_in_inj`, `in_inj_comp`, `can_in_comp`, `pcan_in_comp` and `ocan_in_comp` (`#16158 `_, by Pierre Roux). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** commands which set tactic options (currently :opt:`Firstorder Solver` and :cmd:`Obligation Tactic`, as well as any defined by third party plugins) now support :attr:`export` locality. Note that such commands using :attr:`global` without :attr:`export` or using no explicit locality outside sections apply their effects when any module containing it (recursively) is imported. This will change in a future version. (`#15274 `_, fixes `#15072 `_, by GaΓ«tan Gilbert). - **Changed:** `Hint` and :cmd:`Instance` commands with no locality attribute are deprecated. Previous versions generated a warning, but this version generates an error by default. This includes all `Hint` commands described in :ref:`creating_hints`, :cmd:`Hint Rewrite`, and :cmd:`Instance`. As mentioned in the error, please add an explicit locality to the hint command. The default was #[:attr:`global`], but we recommend using #[:attr:`export`] where possible (`#16004 `_, fixes `#13394 `_, by Ali Caglayan). - **Changed:** Transparent obligations generated by :attr:`Program ` do not produce an implicit :cmd:`Hint Unfold` anymore (`#16340 `_, by Pierre-Marie PΓ©drot). - **Changed:** :cmd:`Print Typeclasses` replaces the undocumented `Print TypeClasses` command which displays the list of typeclasses (`#16690 `_, fixes `#16686 `_, by Ali Caglayan). - **Changed:** The -async-proofs-tac-j command line option now accepts the argument 0, which makes `par` block interpreted without spawning any new process (`#16837 `_, by Pierre-Marie PΓ©drot). - **Removed:** the ``Program Naming`` flag, which was introduced as an immediately deprecated option in Coq 8.16 (`#16519 `_, by Pierre-Marie PΓ©drot). - **Removed:** undocumented and broken `Solve Obligation` command (the :cmd:`Solve Obligations` command is untouched) (`#16842 `_, by ThΓ©o Zimmermann). .. _817ClassFieldSyntax: - **Deprecated** :g:`:>` syntax, to declare fields of :ref:`typeclasses` as instances, since it is now replaced by :g:`::` (see :n:`@of_type_inst`). This will allow, in a future release, making :g:`:>` declare :ref:`coercions` as it does in :ref:`record ` definitions (`#16230 `_, fixes `#16224 `_, by Pierre Roux, reviewed by Ali Caglayan, Jim Fehrle, GaΓ«tan Gilbert and Pierre-Marie PΓ©drot). - **Added:** An improved description of :cmd:`Proof using` and section variables (`#16168 `_, by Jim Fehrle). - **Added:** :g:`::` syntax (see :n:`@of_type_inst`) to declare fields of records as :ref:`typeclass ` instances (`#16230 `_, fixes `#16224 `_, by Pierre Roux, reviewed by Ali Caglayan, Jim Fehrle, GaΓ«tan Gilbert and Pierre-Marie PΓ©drot). - **Added:** The :cmd:`Print Keywords` command, which prints all the currently-defined parser keywords and tokens (`#16438 `_, fixes `#16375 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Print Grammar` can print arbitrary nonterminals or the whole grammar instead of a small adhoc list of nonterminals (`#16440 `_, by GaΓ«tan Gilbert). - **Fixed:** :flag:`Fast Name Printing` flag no longer causes variable name capture when displaying a goal (`#16395 `_, fixes `#14141 `_, by Wojciech Karpiel). - **Fixed:** :tacn:`vm_compute` ignored the ``bytecode-compiler`` command line flag (`#16931 `_, fixes `#16929 `_, by GaΓ«tan Gilbert). - **Fixed:** The :cmd:`Proof Mode` command now gives an error if the specified proof mode doesn't exist. The command was not previously documented (`#16981 `_, fixes `#16602 `_, by Jim Fehrle). - **Fixed:** Backtracking over grammar modifications from plugins (such as added commands) (`#17069 `_, fixes `#12575 `_, by GaΓ«tan Gilbert). - **Fixed:** Anomaly instead of regular error on unsupported applied :g:`fix` in :cmd:`Function` (`#17113 `_, fixes `#17110 `_, by Hugo Herbelin). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Added:** New documentation section :ref:`configuration_basics` covering use cases such as setting up Coq with opam, where/how to set up source code for your projects and use of _CoqProject (`#15888 `_, by Jim Fehrle). - **Added:** In _CoqProject files, expand paths that are directories to include appropriate files in (sub)directories (`#16308 `_, by Jim Fehrle). - **Fixed:** issues when using ``coq_makefile`` to build targets requiring both ``.vo`` and ``.glob`` files (typically documentation targets), where ``make`` would run multiple ``coqc`` processes on the same source file with racy behaviour (only fixed when using a ``make`` supporting "grouped targets" such as GNU Make 4.3) (`#16757 `_, by GaΓ«tan Gilbert). - **Fixed:** Properly process legacy attributes such as ``Global`` and ``Polymorphic`` in coqdoc to avoid omissions when using the ``-g`` (Gallina only) option (`#17090 `_, fixes `#15933 `_, by Karl Palmskog). .. _817Stdlib: Standard library ^^^^^^^^^^^^^^^^ - **Changed:** Class :g:`Saturate` in ``ZifyCLasses.v``, :g:`PRes` now also takes operands (`#16355 `_, by FrantiΕ‘ek Farka on behalf of BedRock Systems, Inc.). - **Changed:** For uniformity of naming and ease of remembering, `R_dist` and theorems mentioning `R_dist` in their name become available with spelling `Rdist` (`#16874 `_, by Hugo Herbelin). - **Removed:** from :g:`Nat` and :g:`N` superfluous lemmas :g:`rs_rs'`, :g:`rs'_rs''`, :g:`rbase`, :g:`A'A_right`, :g:`ls_ls'`, :g:`ls'_ls''`, :g:`rs'_rs''`, :g:`lbase`, :g:`A'A_left`, and also redundant non-negativity assumptions in :g:`gcd_unique`, :g:`gcd_unique_alt`, :g:`divide_gcd_iff`, and :g:`gcd_mul_diag_l` (`#16203 `_, by Andrej Dudenhefner). - **Deprecated:** notation ``_ ~= _`` for ``JMeq`` in ``Coq.Program.Equality`` (`#16436 `_, by GaΓ«tan Gilbert). - **Deprecated:** lemma :g:`Finite_alt` in ``FinFun.v``, which is a weaker version of the newly added lemma :g:`Finite_dec` (`#16489 `_, fixes `#16479 `_, by Bodo Igler, with help from Olivier Laurent). - **Deprecated:** :g:`Zmod`, :g:`Zdiv_eucl_POS`, :g:`Zmod_POS_bound`, :g:`Zmod_pos_bound`, and :g:`Zmod_neg_bound` in `ZArith.Zdiv` (`#16892 `_, by Andres Erbsen). - **Deprecated:** :g:`Cyclic.ZModulo.ZModulo` because there have been no known use cases for this module and because it does not implement `Z/nZ` for arbitrary `n` as one might expect based on the name. The same construction will remain a part of the Coq test suite to ensure consistency of `CyclicAxioms` (`#16914 `_, by Andres Erbsen). - **Added:** lemmas :g:`Permutation_incl_cons_inv_r`, :g:`Permutation_pigeonhole`, :g:`Permutation_pigeonhole_rel` to ``Permutation.v``, and :g:`Forall2_cons_iff`, :g:`Forall2_length`, :g:`Forall2_impl`, :g:`Forall2_flip`, :g:`Forall_Exists_exists_Forall2` to ``List.v`` (`#15986 `_, by Andrej Dudenhefner, with help from Dominique Larchey-Wendling and Olivier Laurent). - **Added:** modules :g:`Nat.Div0` and :g:`Nat.Lcm0` in :g:`PeanoNat`, and :g:`N.Div0` and :g:`N.Lcm0` in :g:`BinNat` containing lemmas regarding :g:`div` and :g:`mod`, which take into account `n div 0 = 0` and `n mod 0 = n`. Strictly weaker lemmas are deprecated, and will be removed in the future. After the weaker lemmas are removed, the modules :g:`Div0` and :g:`Lcm0` will be deprecated, and their contents included directly into :g:`Nat` and :g:`N`. Locally, you can use :g:`Module Nat := Nat.Div0.` or :g:`Module Nat := Nat.Lcm0.` to approximate this inclusion (`#16203 `_, fixes `#16186 `_, by Andrej Dudenhefner). - **Added:** lemma :g:`measure_induction` in :g:`Nat` and :g:`N` analogous to :g:`Wf_nat.induction_ltof1`, which is compatible with the `using` clause for the :tacn:`induction` tactic (`#16203 `_, by Andrej Dudenhefner). - **Added:** three lemmata related to finiteness and decidability of equality: :g:`Listing_decidable_eq`, :g:`Finite_dec` to ``FinFun.v`` and lemma :g:`NoDup_list_decidable` to ``ListDec.v`` (`#16489 `_, fixes `#16479 `_, by Bodo Igler, with help from Olivier Laurent and Andrej Dudenhefner). - **Added:** lemma :g:`not_NoDup` to ``ListDec.v`` and :g:`NoDup_app_remove_l`, :g:`NoDup_app_remove_r` to ``List.v`` (`#16588 `_, by Stefan Haan with a lot of help from Olivier Laurent and Ali Caglayan). - **Added:** the `skipn_skipn` lemma in `Lists/List.v` (`#16632 `_, by Stephan Boyer). - **Added:** lemmas :g:`nth_error_ext`, :g:`map_repeat`, :g:`rev_repeat` to ``List.v``, and :g:`to_list_nil_iff`, :g:`to_list_inj` to ``VectorSpec.v`` (`#16756 `_, by Stefan Haan). - **Added:** transparent :g:`extgcd` to replace opaque :g:`euclid`, :g:`euclid_rec`, :g:`Euclid`, and :g:`Euclid_intro` in :g:`Znumtheory`. Deprecated compatibility wrappers are provided (`#16915 `_, by Andres Erbsen). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Coq is now built entirely using the Dune build system. Packagers and users that build Coq manually must use the new build instructions in the documentation (`#15560 `_, by Ali Caglayan, Emilio Jesus Gallego Arias, and Rudi Grinberg). - **Changed:** Coq is not compiled with OCaml's ``-rectypes`` option anymore. This means plugins which do not exploit it can also stop passing it to OCaml (`#16007 `_, by GaΓ«tan Gilbert). - **Changed:** Building Coq now requires Dune >= 2.9 (`#16118 `_, by Emilio Jesus Gallego Arias). - **Changed:** Coq Makefile targets `pretty-timed`, `make-pretty-timed`, `make-pretty-timed-before`, `make-pretty-timed-after`, `print-pretty-timed`, `print-pretty-timed-diff`, `print-pretty-single-time-diff` now generate more readable timing tables when absolute paths are used in `_CoqProject` / the arguments to `coq_makefile`, by stripping off the absolute prefix (`#16268 `_, by Jason Gross). - **Changed:** Coq's configure script now defaults to `-native-compiler no`. Previously, the default was `-native-compiler ondemand`, except on Windows. The behavior for users installing through opam does not change, i.e., it is `-native-compiler no` if the `coq-native` package is not installed, and `-native-compiler yes` otherwise (`#16997 `_, by ThΓ©o Zimmermann). - **Removed:** the ``-coqide`` switch to ``configure`` in Coq's build infrastructure (it stopped controlling what got compiled in the move to dune) (`#16512 `_, by GaΓ«tan Gilbert). - **Removed:** the ``-nomacintegration`` configure flag for CoqIDE. Now CoqIDE will always build with the proper platform-specific integration if available (`#16531 `_, by Emilio Jesus Gallego Arias). - **Added:** Coq now supports OCaml 5; note that OCaml 5 is not compatible with Coq's native reduction machine (`#15494 `_, `#16925 `_, `#16947 `_, `#16959 `_, `#16988 `_, `#16991 `_, `#16996 `_, `#16997 `_, `#16999 `_, `#17010 `_, and `#17015 `_ by Emilio Jesus Gallego Arias, GaΓ«tan Gilbert, Guillaume Melquiond, Pierre-Marie PΓ©drot, and others). - **Added:** OCaml 4.14 is now officially supported (`#15867 `_, by GaΓ«tan Gilbert). Miscellaneous ^^^^^^^^^^^^^ - **Changed:** Module names are now added to the loadpath in alphabetical order for each (sub-)directory. Previously they were added in the order of the directory entries (as shown by "ls -U") (`#16725 `_, by Jim Fehrle). Changes in 8.17.1 ~~~~~~~~~~~~~~~~~ A variety of bug fixes and improvements to error messages, including: - **Fixed:** in some cases, coqdep emitted incorrect paths for META files which prevented dune builds for plugins from working correctly (`#17270 `_, fixes `#16571 `_, by Rodolphe Lepigre). - **Fixed:** Shadowing of record fields in extraction to OCaml (`#17324 `_, fixes `#12813 `_ and `#14843 `_ and `#16677 `_, by Hugo Herbelin). - **Fixed:** an impossible to turn off debug message "backtracking and redoing byextend on ..." (`#17495 `_, fixes `#17488 `_, by GaΓ«tan Gilbert). - **Fixed:** major memory regression affecting MathComp 2 (`#17743 `_, by Enrico Tassi and Pierre Roux). Version 8.16 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.16 integrates changes to the Coq kernel and performance improvements along with a few new features. We highlight some of the most impactful changes here: - The guard checker (see :cmd:`Guarded`) now ensures strong :ref:`normalization <816Normalization>` under any reduction strategy. - Irrelevant terms (in the ``SProp`` sort) are now squashed to a dummy value during :ref:`conversion <816SPropConversion>`, fixing a subject reduction issue and making proof conversion faster. - Introduction of :ref:`reversible coercions <816ReversibleCoercions>`, which allow coercions relying on meta-level resolution such as type-classes or canonical structures. Also :ref:`allow coercions <816UniformInh>` that do not fullfill the :term:`uniform inheritance condition`. - :ref:`Generalized rewriting <816GeneralizeRew>` support for rewriting with ``Type``-valued relations and in ``Type`` contexts, using the ``Classes.CMorphisms`` library. - Added the :ref:`boolean equality <816BooleanEquality>` scheme command for decidable inductive types. - Added a :ref:`Print Notation <816PrintNotation>` command. - Incompatibilities in :ref:`name generation <816ProgramObls>` for Program obligations, :tacn:`eauto` treatment of :ref:`tactic failure levels <816EautoLevels>`, use of ``ident`` :ref:`in notations <816IdentNotations>`, parsing of :ref:`module expressions <816ModuleExprs>`. - Standard library :ref:`reorganization and deprecations <816Stdlib>`. - Improve the treatment of standard library numbers by :cmd:`Extraction`. See the `Changes in 8.16.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual for 8.16 `_, `documentation of the 8.16 standard library `_ and `developer documentation of the 8.16 ML API `_ are also available. Ali Caglayan, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The `Coq Platform `_ has been maintained by Michael Soegtrop, with help from Karl Palmskog, Enrico Tassi and ThΓ©o Zimmermann. Our current maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Ana Borges, Ali Caglayan, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details. The 57 contributors to the 8.16 versions are Tanaka Akira, FrΓ©dΓ©ric Besson, Martin Bodin, Ana Borges, Ali Caglayan, Minki Cho, Cyril Cohen, Juan Conejero, "stop-cran", Adrian Dapprich, Maxime DΓ©nΓ¨s, StΓ©phane Desarzens, Christian Doczkal, Andrej Dudenhefner, Andres Erbsen, Jim Fehrle, Emilio JesΓΊs Gallego Arias, Attila GΓ‘spΓ‘r, Paolo G. Giarrusso, GaΓ«tan Gilbert, Rudi Grinberg, Jason Gross, Hugo Herbelin, Wolf Honore, Jasper Hugunin, Bart Jacobs, Pierre Jouvelot, Ralf Jung, Grant Jurgensen, Jan-Oliver Kaiser, Wojciech Karpiel, Thomas Klausner, Ethan Kuefner, Fabian Kunze, Olivier Laurent, Yishuai Li, Erik Martin-Dorel, Guillaume Melquiond, Jean-Francois Monin, Pierre-Marie PΓ©drot, Rudy Peterson, ClΓ©ment Pit-Claudel, Seth Poulsen, Ramkumar Ramachandra, Pierre Roux, Takafumi Saikawa, Kazuhiko Sakaguchi, Gabriel Scherer, Vincent Semeria, Kartik Singhal, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. The Coq community at large helped improve this new version via the GitHub issue and pull request system, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.16's development spanned 6 months from the release of Coq 8.15.0. Pierre-Marie PΓ©drot is the release manager of Coq 8.16. This release is the result of 356 merged PRs, closing 99 issues. | Nantes, June 2022, | Matthieu Sozeau for the Coq development team Changes in 8.16.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ .. _816Normalization: - **Changed:** Fixpoints are now expected to be guarded even in subterms erasable by reduction, thus getting rid of an artificial obstacle preventing to lift the assumption of weak normalization of Coq to an assumption of strong normalization; for instance (barring implementation bugs) termination of the type-checking algorithm of Coq is now restored (of course, as usual, up to the assumption of the consistency of set theory and type theory, i.e., equivalently, up to the weak normalization of type theory, a "physical" assumption, which has not been contradicted for decades and which specialists commonly believe to be a truth) (`#15434 `_, incidentally fixes the complexity issue `#5702 `_, by Hugo Herbelin). - **Changed:** Flag :n:`Unset Guard Checking` nevertheless requires fixpoints to have an argument marked as decreasing in a type which is inductive (`#15668 `_, fixes `#15621 `_, by Hugo Herbelin). - **Removed:** :ref:`Template-polymorphism` is now forbidden for mutual inductive types (`#15965 `_, by GaΓ«tan Gilbert). - **Fixed:** Inlining of non-logical objects (notations, hints, ...) was missing when applying a functor returning one of its arguments as e.g. in :n:`Module F (E:T) := E` (`#15412 `_, fixes `#15403 `_, by Hugo Herbelin). .. _816SPropConversion: - **Fixed:** We introduce a new irrelevant term in the reduction machine. It is used to shortcut computation of terms living in a strict proposition, and behaves as an exception. This restores subject reduction, and also makes conversion of large terms in SProp cheap (`#15575 `_, fixes `#14015 `_, by Pierre-Marie PΓ©drot). - **Fixed:** performance blowups while inferring variance information for :ref:`cumulative` inductive types (`#15662 `_, fixes `#11741 `_, by GaΓ«tan Gilbert). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Added:** New clause :n:`as @ident` to the :cmd:`Record` command to specify the name of the main argument to use by default in the type of projections (`#14563 `_, by Hugo Herbelin). .. _816ReversibleCoercions: - **Added:** :term:`Reversible coercions ` are coercions which cannot be represented by a regular coercion (a Gallina function) but rather a meta procedure, such as type class inference or canonical structure resolution (`#15693 `_, by Cyril Cohen, Pierre Roux, Enrico Tassi, reviewed by Ali Caglayan, Jim Fehrle and GaΓ«tan Gilbert). .. _816UniformInh: - **Added:** support for coercions not fulfilling the uniform inheritance condition, allowing more freedom for the parameters that are now inferred using unification, canonical structures or typeclasses (`#15789 `_, fixes `#2828 `_, `#4593 `_, `#3115 `_, `#5222 `_, `#9696 `_ and `#8540 `_, by Pierre Roux, reviewed by Ali Caglayan, Enrico Tassi, Kazuhiko Sakaguchi and Jim Fehrle). - **Fixed:** interpretation of `{struct}` fixpoint annotations when the principal argument comes from an implicit generalization (`#15581 `_, fixes `#13157 `_, by GaΓ«tan Gilbert). Notations ^^^^^^^^^ .. _816IdentNotations: - **Removed:** ``_`` in ``ident`` entries in notations, which was deprecated in favor of ``name`` in 8.13. When you see messages like .. code:: Error: Notation "[ rel _ _ : _ | _ ]" is already defined at level 0 with arguments name, name, constr, constr while it is now required to be at level 0 with arguments ident, ident, constr, constr. replace ``ident`` with ``name`` in the :cmd:`Notation` command. To ease the change, you can fix the ``deprecated-ident-entry`` warnings in Coq 8.15 (or 8.14 or 8.13). The warning can be turned into an error with ``-arg -w -arg +deprecated-ident-entry`` in the ``_CoqProject`` file (`#15754 `_, by Pierre Roux). - **Added:** When defining a recursive notation referring to another recursive notation, expressions of the form :n:`x .. y` can be used where a sequence of binders is expected (`#15291 `_, grants `#7911 `_, by Hugo Herbelin). - **Fixed:** Coercions are disabled when typechecking parsers and printers of :cmd:`Number Notation` (`#15884 `_, fixes `#15843 `_, by Pierre Roux). Tactics ^^^^^^^ - **Changed:** The ``RewriteRelation`` type class is now used to declare relations inferable by the :tacn:`setoid_rewrite` tactic to construct ``Proper`` instances. This can break developments that relied on existing ``Reflexive`` instances to infer relations. The fix is to simply add a (backwards compatible) ``RewriteRelation`` declaration for the relation. This change allows to set stricter modes on the relation type classes ``Reflexive``, ``Symmetric``, etc. (`#13969 `_, fixes `#7916 `_, by Matthieu Sozeau). - **Changed:** The :tacn:`setoid_rewrite` tactic can now properly recognize homogeneous relations applied to types in different universes (`#14138 `_, fixes `#13618 `_, by Matthieu Sozeau). .. _816EautoLevels: - **Changed:** The :tacn:`eauto` tactic does not propagate internal Ltac failures with level > 0 anymore. Any failure caused by a hint now behaves as if it were a level 0 error (`#15215 `_, fixes `#15214 `_, by Pierre-Marie PΓ©drot). - **Changed:** :tacn:`rewrite` when used to rewrite in multiple hypotheses (eg `rewrite foo in H,H'`) requires that the term (`foo`) does not depend on the hypotheses it rewrites. When using `rewrite in *`, this means we only rewrite in hypotheses which do not appear in the term (`#15426 `_, fixes `#3051 `_ and `#15448 `_, by GaΓ«tan Gilbert). - **Changed:** When it fails, :tacn:`assert_succeeds` fails with the argument tactic's original error instead of ``Tactic failure: fails.`` (`#15728 `_, fixes `#10970 `_, by GaΓ«tan Gilbert). - **Deprecated:** the :tacn:`instantiate` tactic without arguments. Since the move to the monadic tactic engine in 8.5, it was behaving as the identity (`#15277 `_, by Pierre-Marie PΓ©drot). .. _816GeneralizeRew: - **Added:** generalized rewriting now supports rewriting with (possibly polymorphic) relations valued in ``Type``. Use ``Classes.CMorphisms`` instead of ``Classes.Morphisms`` to declare ``Proper`` instances for :tacn:`rewrite` (or :tacn:`setoid_rewrite`) to use when rewriting with ``Type`` valued relations (`#14137 `_, fixes `#4632 `_, `#5384 `_, `#5521 `_, `#6278 `_, `#7675 `_, `#8739 `_, `#11011 `_, `#12240 `_, and `#15279 `_, by Matthieu Sozeau helped by Ali Caglayan). - **Added:** Tactics to obtain a micromega :term:`cone expression` (aka witness) from an already reified goal. Using those tactics, the user can develop their own micromega tactics for their own types, using their own parsers (`#15921 `_, by Pierre Roux, reviewed by FrΓ©dΓ©ric Besson and Jim Fehrle). - **Fixed:** :tacn:`typeclasses eauto` used with multiple hint databases respects priority differences for hints from separate databases (`#15289 `_, fixes `#5304 `_, by GaΓ«tan Gilbert). - **Fixed:** :tacn:`cbn` has better support for combining `simpl nomatch`, `!` and `/` specifiers (c.f. :cmd:`Arguments`) (`#15657 `_, fixes `#3989 `_ and `#15206 `_, by GaΓ«tan Gilbert). Tactic language ^^^^^^^^^^^^^^^ - **Changed:** Ltac `match` does not fail when the term to match contains an unfolded primitive projection (`#15559 `_, fixes `#15554 `_, by GaΓ«tan Gilbert). - **Added:** ``Ltac2`` understands :token:`toplevel_selector` and obeys :opt:`Default Goal Selector`. Note that ``par:`` is buggy when combined with :tacn:`abstract`. Unlike ``Ltac1`` even ``par: abstract tac`` is not properly treated (`#15378 `_, by GaΓ«tan Gilbert). - **Added:** Ltac2 `Int` functions `div`, `mod`, `asr`, `lsl`, `lsr`, `land`, `lor` , `lxor` and `lnot` (`#15637 `_, by Michael Soegtrop). - **Fixed:** Ltac2 `apply` and `eapply` not unifying with implicit arguments; unification inconsistent with `exact` and `eexact` (`#15741 `_, by Ramkumar Ramachandra). SSReflect ^^^^^^^^^ - **Fixed:** :tacn:`have`, :tacn:`suff` and :tacn:`wlog` support goals in `SProp` (`#15121 `_, by Enrico Tassi). Commands and options ^^^^^^^^^^^^^^^^^^^^ .. _816ModuleExprs: - **Changed:** :cmd:`Module` now only allows parentheses around module arguments. For instance, ``Module M := (F X).`` is now a parsing error (`#15355 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Fail` no longer catches anomalies, which it has done since Coq version 8.11. Now it only catches user errors (`#15366 `_, by Hugo Herbelin). - **Changed:** :ref:`program_definition` in universe monomorphic mode does not accept non-extensible universe declarations (`#15424 `_, fixes `#15410 `_, by GaΓ«tan Gilbert). .. _816ProgramObls: - **Changed:** The algorithm for name generation of anonymous variables for ``Program`` subproofs is now the same as the one used in the general case. This can create incompatibilities in scripts relying on such autogenerated names. The old scheme can be reactivated using the deprecated flag ``Program Naming`` (`#15442 `_, by Pierre-Marie PΓ©drot). - **Removed:** `Universal Lemma Under Conjunction` flag, that was deprecated in 8.15 (`#15268 `_, by ThΓ©o Zimmermann). - **Removed:** :cmd:`Abort` no longer takes an :n:`@ident` as an argument (it has been ignored since 8.5) (`#15669 `_, by GaΓ«tan Gilbert). - **Removed:** `Simplex` flag, that was deprecated in 8.14. :tacn:`lia` and :tacn:`lra` will always use the simplex solver (that was already the default behaviour) (`#15690 `_, by FrΓ©dΓ©ric Besson). - **Deprecated:** ``Add LoadPath`` and ``Add Rec LoadPath``. If this command is an important feature for you, please open an issue on `GitHub ` and explain your workflow (`#15652 `_, by GaΓ«tan Gilbert). - **Deprecated:** the `Typeclasses Filtered Unification` flag. Due to a buggy implementation, it is unlikely this is used in the wild (`#15752 `_, by Pierre-Marie PΓ©drot). .. _816BooleanEquality: - **Added:** :cmd:`Scheme Boolean Equality` command to generate the boolean equality for an inductive type whose equality is decidable. It is useful when Coq is able to generate the boolean equality but isn't powerful enough to prove the decidability of equality (unlike :cmd:`Scheme Equality`, which tries to prove the decidability of the type) (`#15526 `_, by Hugo Herbelin). - **Added:** New more extensive algorithm based on the "parametricity" translation for canonically generating Boolean equalities associated to a decidable inductive type (`#15527 `_, by Hugo Herbelin). - **Added:** :cmd:`From … Dependency` command to declare a dependency of a ``.v`` file on an external file. The ``coqdep`` tool generates build dependencies accordingly (`#15650 `_, fixes `#15600 `_, by Enrico Tassi). .. _816PrintNotation: - **Added:** :cmd:`Print Notation` command that prints the level and associativity of a given notation definition string (`#15683 `_, fixes `#14907 `_ and `#4436 `_ and `#7730 `_, by Ali Caglayan and Ana Borges, with help from Emilio Jesus Gallego Arias). - **Added:** a warning when trying to deprecate a definition (`#15760 `_, by Pierre Roux). - **Added:** A deprecation warning that the :g:`Class >` syntax, which currently does nothing, will in the future declare :ref:`coercions ` as it does when used in :cmd:`Record` commands (`#15802 `_, by Pierre Roux, reviewed by GaΓ«tan Gilbert, Ali Caglayan, Jason Gross, Jim Fehrle and ThΓ©o Zimmermann). - **Added:** the :attr:`nonuniform` boolean attribute that silences the non-uniform-inheritance warning when user needs to declare such a coercion on purpose (`#15853 `_, by Pierre Roux, reviewed by GaΓ«tan Gilbert and Jim Fehrle). - **Added:** All commands which can import modules (e.g. ``Module Import M.``, ``Module F (Import X : T).``, ``Require Import M.``, etc) now support :token:`import_categories`. :cmd:`Require Import` and :cmd:`Require Export` also support :token:`filtered_import` (`#15945 `_, fixes `#14872 `_, by GaΓ«tan Gilbert). - **Fixed:** Make `Require Import M.` equivalent to `Require M. Import M.` (`#15347 `_, fixes `#3556 `_, by Maxime DΓ©nΓ¨s). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Added:** coq_makefile variable `COQPLUGININSTALL` to configure the installation of ML plugins (`#15788 `_, by Cyril Cohen and Enrico Tassi). - **Added:** Added :n:`-bytecode-compiler {| yes | no }` flag for ``coqchk`` enabling :tacn:`vm_compute` during checks, which is off by default (`#15886 `_, by Ali Caglayan). - **Fixed:** ``coqdoc`` confused by the presence of command :cmd:`Load` in a file (`#15511 `_, fixes `#15497 `_, by Hugo Herbelin). CoqIDE ^^^^^^ - **Added:** Documentation of editing failed async mode proofs, how to configure key bindings and various previously undocumented details (`#16070 `_, by Jim Fehrle). Standard library ^^^^^^^^^^^^^^^^ .. _816Stdlib: - **Changed:** the ``signature`` scope of ``Classes.CMorphisms`` into ``signatureT`` (`#15446 `_, by Olivier Laurent). - **Changed:** the locality of typeclass instances `Permutation_app'` and `Permutation_cons` from :attr:`global` to :attr:`export` (`#15597 `_, fixes `#15596 `_, by GaΓ«tan Gilbert). - **Removed:** ``Int63``, which was deprecated in favor of ``Uint63`` in 8.14 (`#15754 `_, by Pierre Roux). - **Deprecated:** some obsolete files from the ``Arith`` part of the standard library (``Div2``, ``Even``, ``Gt``, ``Le``, ``Lt``, ``Max``, ``Min``, ``Minus``, ``Mult``, ``NPeano``, ``Plus``). Import ``Arith_base`` instead of these files. References to items in the deprecated files should be replaced with references to ``PeanoNat.Nat`` as suggested by the warning messages. Concerning the definitions of parity properties (even and odd), it is recommended to use ``Nat.Even`` and ``Nat.Odd``. If an inductive definition of parity is required, the mutually inductive ``Nat.Even_alt`` and ``Nat.Odd_alt`` can be used. However, induction principles for ``Nat.Odd`` and ``Nat.Even`` are available as ``Nat.Even_Odd_ind`` and ``Nat.Odd_Even_ind``. The equivalence between the non-inductive and mutually inductive definitions of parity can be found in ``Nat.Even_alt_Even`` and ``Nat.Odd_alt_Odd``. All ``Hint`` declarations in the ``arith`` database have been moved to ``Arith_prebase`` and ``Arith_base``. To use the results about Peano arithmetic, we recommend importing ``PeanoNat`` (or ``Arith_base`` to base it on the ``arith`` hint database) and using the ``Nat`` module. ``Arith_prebase`` has been introduced temporarily to ensure compatibility, but it will be removed at the end of the deprecation phase, e.g. in 8.18. Its use is thus discouraged (`#14736 `_, `#15411 `_, by Olivier Laurent, with help of Karl Palmskog). - **Deprecated:** `identity` inductive (replaced by the equivalent `eq`). `Init.Logic_Type` is removed (the only remaining definition `notT` is moved to `Init.Logic`) (`#15256 `_, by Olivier Laurent). - **Deprecated:** `P_Rmin`: use more general `Rmin_case` instead (`#15388 `_, fixes `#15382 `_, by Olivier Laurent). - **Added:** lemma `count_occ_rev` (`#15397 `_, by Olivier Laurent). - **Added:** ``Nat.EvenT`` and ``Nat.OddT`` (almost the same as ``Nat.Even`` and ``Nat.Odd`` but with output in ``Type``. Decidability of parity (with output ``Type``) is provided ``EvenT_OddT_dec`` as well as induction principles ``Nat.EvenT_OddT_rect`` and ``Nat.OddT_EvenT_rect`` (with output ``Type``) (`#15427 `_, by Olivier Laurent). - **Added:** Added a proof of ``sin x < x`` for positive ``x`` and ``x < sin x`` for negative ``x`` (`#15599 `_, by stop-cran). - **Added:** decidability typeclass instances for Z.le, Z.lt, Z.ge and Z.gt, added lemmas Z.geb_ge and Z.gtb_gt (`#15620 `_, by Michael Soegtrop). - **Added:** lemmas ``Rinv_inv``, ``Rinv_mult``, ``Rinv_opp``, ``Rinv_div``, ``Rdiv_opp_r``, ``Rsqr_div'``, ``Rsqr_inv'``, ``sqrt_inv``, ``Rabs_inv``, ``pow_inv``, ``powerRZ_inv'``, ``powerRZ_neg'``, ``powerRZ_mult``, ``cv_infty_cv_0``, which are variants of existing lemmas, but without any hypothesis (`#15644 `_, by Guillaume Melquiond). - **Added:** a Leibniz equality test for primitive floats (`#15719 `_, by Pierre Roux, reviewed by Guillaume Melquiond). - **Added:** support for primitive floats in Scheme Boolean Equality (`#15719 `_, by Pierre Roux, reviewed by Hugo Herbelin). - **Added:** lemma :g:`le_add_l` to ``NAddOrder.v``. Use :g:`Nat.le_add_l` as replacement for the deprecated :g:`Plus.le_plus_r` (`#16184 `_, by Andrej Dudenhefner). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Bumped lablgtk3 lower bound to 3.1.2 (`#15947 `_, by Pierre-Marie PΓ©drot). - **Changed:** Load plugins using `findlib `_. This requires projects built with ``coq_makefile`` to either provide a hand written ``META`` file or use the ``-generate-meta-for-package`` option when applicable. As a consequence :cmd:`Declare ML Module` now uses plugin names according to ``findlib``, e.g. `coq-aac-tactics.plugin`. ``coqdep`` accepts ``-m META`` and uses the file to resolve plugin names to actual file names (`#15220 `_, fixes `#7698 `_, by Enrico Tassi). - **Changed:** Minimum supported zarith version is now 1.11 (`#15483 `_ and `#16005 `_ and `#16030 `_, closes `#15496 `_, by GaΓ«tan Gilbert and ThΓ©o Zimmermann and Jason Gross). - **Changed:** Bump the minimum OCaml version to 4.09.0. As a consequence the minimum supported ocamlfind version is now 1.8.1 (`#15947 `_ and `#16046 `_, fixes `#14260 `_ and `#16015 `_, by Pierre-Marie PΓ©drot and ThΓ©o Zimmermann). Extraction ^^^^^^^^^^ .. _816Extraction: - **Changed:** `ExtrOCamlInt63` no longer extracts `comparison` to `int` in OCaml; the extraction of `Uint63.compare` and `Sint63.compare` was also adapted accordingly (`#15294 `_, fixes `#15280 `_, by Li-yao Xia). - **Changed:** Extraction from :g:`nat` to OCaml :g:`int` uses Stdlib instead of Pervasives (`#15333 `_, by Rudy Nicolo Peterson). - **Changed:** The empty inductive type is now extracted to OCaml empty type available since OCaml 4.07 (`#15967 `_, by Pierre Roux). - **Added:** More extraction definitions for division and comparison of Z and N (`#15098 `_, by Li-yao Xia). - **Fixed:** Type :n:`int` in files :n:`Number.v`, :n:`Decimal.v` and :n:`Hexadecimal.v` have been renamed to :n:`signed_int` (together with a compatibility alias :n:`int`) so that they can be used in extraction without conflicting with OCaml's :n:`int` type (`#13460 `_, fixes `#7017 `_ and `#13288 `_, by Hugo Herbelin). Changes in 8.16.1 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** conversion of Prod values in the native compiler (`#16651 `_, fixes `#16645 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Coq 8.16.0 missed `SProp` check for opaque names in conversion (`#16768 `_, fixes `#16752 `_, by Hugo Herbelin). - **Fixed:** Pass the correct environment to compute Ξ·-expansion of cofixpoints in VM and native compilation (`#16845 `_, fixes `#16831 `_, by Pierre-Marie PΓ©drot). - **Fixed:** inconsistency with conversion of primitive arrays, and associated incomplete strong normalization of primitive arrays with ``lazy`` (`#16850 `_, fixes `#16829 `_, by GaΓ«tan Gilbert, reported by Maxime Buyse and Andres Erbsen). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Fixed:** :cmd:`Print Assumptions` treats opaque definitions with missing proofs (as found in ``.vos`` files, see :ref:`compiled-interfaces`) as axioms instead of ignoring them (`#16434 `_, fixes `#16411 `_, by GaΓ«tan Gilbert). CoqIDE ^^^^^^ - **Fixed:** "Interrupt computations" now works correctly on Windowsβ€”except if you start CoqIDE as a background process, e.g. with `coqide &` in `bash`, in which case it won't work at all (`#16142 `_, fixes `#13550 `_, by Jim Fehrle). Version 8.15 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.15 integrates many bug fixes, deprecations and cleanups as well as a few new features. We highlight some of the most impactful changes here: - The :tacn:`apply with ` tactic :ref:`no longer renames arguments <815ApplyWith>` unless compatibility flag `Apply With Renaming` is set. - :ref:`Improvements <815Auto>` to the :tacn:`auto` tactic family, fixing the :cmd:`Hint Unfold` behavior, and generalizing the use of discrimination nets. - The :tacn:`typeclasses eauto` tactic has a new :ref:`best_effort <815BestEffort>` option allowing it to return *partial* solutions to a proof search problem, depending on the mode declarations associated to each constraint. This mode is used by typeclass resolution during type inference to provide more precise error messages. - Many :ref:`commands and options <815Commands>` were deprecated or removed after deprecation and more consistently support locality attributes. - The :cmd:`Import` command is extended with :token:`import_categories` to :ref:`select the components <815Import>` of a module to import or not, including features such as hints, coercions, and notations. - A :ref:`visual Ltac debugger <815LtacDebugger>` is now available in CoqIDE. See the `Changes in 8.15.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual for 8.15 `_, `documentation of the 8.15 standard library `_ and `developer documentation of the 8.15 ML API `_ are also available. Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The `Coq Platform `_ has been maintained by Michael Soegtrop and Enrico Tassi. Our current maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Ali Caglayan, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details. The 41 contributors to this version are Tanaka Akira, FrΓ©dΓ©ric Besson, Juan Conejero, Ali Caglayan, Cyril Cohen, Adrian Dapprich, Maxime DΓ©nΓ¨s, StΓ©phane Desarzens, Christian Doczkal, Andrej Dudenhefner, Jim Fehrle, Emilio JesΓΊs Gallego Arias, Attila GΓ‘spΓ‘r, GaΓ«tan Gilbert, Jason Gross, Hugo Herbelin, Jasper Hugunin, Bart Jacobs, Ralf Jung, Grant Jurgensen, Jan-Oliver Kaiser, Wojciech Karpiel, Fabian Kunze, Olivier Laurent, Yishuai Li, Erik Martin-Dorel, Guillaume Melquiond, Jean-Francois Monin, Pierre-Marie PΓ©drot, Rudy Peterson, ClΓ©ment Pit-Claudel, Seth Poulsen, Pierre Roux, Takafumi Saikawa, Kazuhiko Sakaguchi, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov and ThΓ©o Zimmerman. The Coq community at large helped improve the design of this new version via the GitHub issue and pull request system, the Coq development mailing list coqdev@inria.fr, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.15's development spanned 3 months from the release of Coq 8.14.0. GaΓ«tan Gilbert is the release manager of Coq 8.15. This release is the result of 384 merged PRs, closing 143 issues. | Nantes, January 2022, | Matthieu Sozeau for the Coq development team Changes in 8.15.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** Name clash in a computation of the type of parameters of functorial module types; this computation was provided for the purpose of clients using the algebraic form of module types such as :cmd:`Print Module Type` (`#15385 `_, fixes `#9555 `_, by Hugo Herbelin). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** :cmd:`Instance` warns about the default locality immediately rather than waiting until the instance is ready to be defined. This changes which command warns when the instance has a separate proof: the :cmd:`Instance` command itself warns instead of the proof closing command (such as :cmd:`Defined`) (`#14705 `_, by GaΓ«tan Gilbert). - **Removed:** Arguments of section variables may no longer be renamed with :cmd:`Arguments` (this was previously applied inconsistently) (`#14573 `_, by GaΓ«tan Gilbert). - **Added:** Non-dependent implicit arguments can be provided explicitly using the syntax :n:`(@natural := @term)` where :token:`natural` is the index of the implicit argument among all non-dependent arguments of the function, starting from 1 (`#11099 `_, by Hugo Herbelin). - **Added:** :cmd:`Succeed`, a :n:`@control_command` that verifies that the given :n:`@sentence` succeeds without changing the proof state (`#14750 `_, by GaΓ«tan Gilbert). - **Fixed:** The :n:`@term.(@qualid {* @arg })` syntax now takes into account the position of the main argument :n:`@term` when computing the implicit arguments of :n:`@qualid` (`#14606 `_, fixes `#4167 `_, by Hugo Herbelin). - **Fixed:** Source and target of coercions preserved by module instantiation (`#14668 `_, fixes `#3527 `_, by Hugo Herbelin). - **Fixed:** Made reference manual consistent with the implementation regarding the role of recursively non-uniform parameters of inductive types in the nested positivity condition (`#14967 `_, fixes `#14938 `_, by Hugo Herbelin) Notations ^^^^^^^^^ - **Changed:** Terms printed in error messages may be more verbose if syntactic sugar would make it appear that the obtained and expected terms only differ in existential variables (`#14672 `_, by GaΓ«tan Gilbert). - **Removed:** the ``Numeral Notation`` command that was renamed to :cmd:`Number Notation` in 8.13 (`#14819 `_, by Pierre Roux). - **Removed:** primitive float notations ``<``, ``<=`` and ``==`` that were replaced by ```_, by Pierre Roux). - **Removed:** primitive integer notations ``\%``, ``<``, ``<=`` and ``==`` that were replaced by ``mod``, ```_, by Pierre Roux). - **Added:** Include floats in the number notation mechanism (`#14525 `_, by Pierre Roux). - **Added:** Coercion entries and :n:`ident`/:n:`global` entries in custom notations now respect the :n:`only parsing` modifier (`#15340 `_, fixes `#15335 `_, by Hugo Herbelin). - **Fixed:** :cmd:`Reserved Infix` now accept further parameters in the infix notation (`#14379 `_, fixes `#11402 `_, by Hugo Herbelin). - **Fixed:** Useless self reference when printing abbreviations declared in nested modules (`#14493 `_, fixes one part of `#12777 `_ and `#14486 `_, by Hugo Herbelin). - **Fixed:** anomalies with notation applied in `match` patterns when the notation have a notation variable at head (`#14713 `_, fixes `#14708 `_, by Hugo Herbelin). - **Fixed:** Regression in parsing error reporting in case of empty custom entry (`#15338 `_, fixes `#15334 `_, by Hugo Herbelin). Tactics ^^^^^^^ .. _815ApplyWith: - **Changed:** ``apply with`` does not rename arguments unless using compatibility flag `Apply With Renaming` (`#13837 `_, fixes `#13759 `_, by GaΓ«tan Gilbert). Porting hint: if the renaming is because of a goal variable (eg ``intros x; apply foo with (x0 := bar)`` where ``About foo.`` says the argument is called ``x``) it is probably caused by an interaction with implicit arguments and ``apply @foo with (x := bar)`` will usually be a backwards compatible fix. .. _815Auto: - **Changed:** :cmd:`Hint Unfold` in discriminated databases now respects its specification, namely that a constant may be unfolded only when it is the head of the goal. The previous behavior was to perform unfolding on any goal, without any limitation. An unexpected side-effect of this was that a database that contained ``Unfold`` hints would sometimes trigger silent strong Ξ²ΞΉ-normalization of the goal. Indeed, :tacn:`unfold` performs such a normalization regardless of the presence of its argument in the goal. This does introduce a bit of backwards incompatibility, but it occurs in very specific situations and is easily circumvented. Since by default hint bases are not discriminated, it means that incompatibilities are typically observed when adding unfold hints to the typeclass database. In order to recover the previous behavior, it is enough to replace instances of ``Hint Unfold foo.`` with ``Hint Extern 4 => progress (unfold foo).``. A less compatible but finer-grained change can be achieved by only adding the missing normalization phase with ``Hint Extern 4 => progress (lazy beta iota).`` (`#14679 `_, fixes `#14874 `_, by Pierre-Marie PΓ©drot). - **Changed:** Correctly consider variables without a body to be rigid for the pattern recognition algorithm of discriminated hints (`#14722 `_, by Pierre-Marie PΓ©drot). - **Changed:** Use discrimination nets for goals containing evars in all :tacn:`auto` tactics. It essentially makes the behavior of undiscriminated databases to be the one of discriminated databases where all constants are considered transparent. This may be incompatible with previous behavior in very rare cases (`#14848 `_, by Pierre-Marie PΓ©drot). - **Changed:** The ``choice`` strategy for :tacn:`rewrite_strat` is now of arbitrary arity (`#14989 `_, fixes `#6109 `_, by GaΓ«tan Gilbert). - **Changed:** The :tacn:`exact` tactic now takes a :g:`uconstr` as argument instead of an ad-hoc one. In very rare cases, this can change the order of resolution of dependent evars when used over several goals at once (`#15171 `_, by Pierre-Marie PΓ©drot). - **Changed:** :tacn:`cbn` interprets the combination of the ``!`` and ``/`` modifiers (from :cmd:`Arguments`) to mean "unfold as soon as all arguments before the ``/`` are provided and all arguments marked with ``!`` reduce to a constructor". This makes it unfold more often than without the ``/`` when all arguments are provided. Previously adding ``/`` would only prevent unfolding when insufficient arguments are provided without adding new unfoldings. Note that this change only takes effect in default mode (as opposed to when ``simpl nomatch`` was used) (`#15204 `_, fixes `#4555 `_ and `#7674 `_, by GaΓ«tan Gilbert). - **Removed:** the deprecated new auto tactic (`#14527 `_, by Pierre-Marie PΓ©drot). - **Removed:** deprecated syntax for :tacn:`instantiate` using capitalized ``Value`` or ``Type`` (`#15193 `_, by GaΓ«tan Gilbert). - **Removed:** deprecated ``autoapply ... using`` syntax for :tacn:`autoapply` (`#15194 `_, by GaΓ«tan Gilbert). - **Deprecated:** the `bfs eauto` tactic. Since its introduction it has behaved exactly like the :tacn:`eauto` tactic. Use :tacn:`typeclasses eauto` with the `bfs` flag instead (`#15314 `_, fixes `#15300 `_, by Pierre-Marie PΓ©drot). - **Added:** The :tacn:`zify` tactic can now recognize `Pos.Nsucc_double`, `Pos.Ndouble`, `N.succ_double`, `N.double`, `N.succ_pos`, `N.div2`, `N.pow`, `N.square`, and `Z.to_pos`. Moreover, importing module `ZifyBool` lets it recognize `Pos.eqb`, `Pos.leb`, `Pos.ltb`, `N.eqb`, `N.leb`, and `N.ltb` (`#10998 `_, by Kazuhiko Sakaguchi). .. _815BestEffort: - **Added:** :ref:`best_effort ` option to :tacn:`typeclasses eauto`, to return a *partial* solution to its initial proof-search problem. The goals that can remain unsolved are determined according to the modes declared for their head (see :cmd:`Hint Mode`). This is used by typeclass resolution during type inference to provide more informative error messages (`#13952 `_, fixes `#13942 `_ and `#14125 `_, by Matthieu Sozeau). - **Added:** A new :table:`Keep Equalities` table to selectively control the preservation of subterm equalities for the :tacn:`injection` tactic. It allows a finer control than the boolean flag :flag:`Keep Proof Equalities` that acts globally (`#14439 `_, by Pierre-Marie PΓ©drot). - **Added:** :tacn:`simple congruence` tactic which works like :tacn:`congruence` but does not unfold definitions (`#14657 `_, fixes `#13778 `_ and `#5394 `_ and `#13189 `_, by Andrej Dudenhefner). - **Added:** Small enhancement of unification in the presence of local definitions (`#14673 `_, fixes `#4415 `_, by Hugo Herbelin). - **Added:** `dfs` option in :tacn:`typeclasses eauto` to use depth-first search (`#14693 `_, fixes `#13859 `_, by Ali Caglayan). - **Fixed:** More flexible hypothesis specialization in :tacn:`congruence` (`#14650 `_, fixes `#14651 `_ and `#14662 `_, by Andrej Dudenhefner). - **Fixed:** Added caching to congruence initialization to avoid quadratic runtime (`#14683 `_, fixes `#5548 `_, by Andrej Dudenhefner). - **Fixed:** Correctly handle matching up to Ξ·-expansion in discriminated hints (`#14732 `_, fixes `#14731 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Old unification understands some inductive cumulativity (`#14758 `_, fixes `#14734 `_ and `#6976 `_, by GaΓ«tan Gilbert). - **Fixed:** The :tacn:`clear dependent ` tactic now does not backtrack internally, preventing an exponential blowup (`#14984 `_, fixes `#11689 `_, by Pierre-Marie PΓ©drot). - **Fixed:** :tacn:`setoid_rewrite` now works when the rewriting lemma has non dependent arguments and rewriting under binders (`#14986 `_, fixes `#5369 `_, by GaΓ«tan Gilbert). - **Fixed:** Regression in 8.14.0 and 8.14.1 with action pattern :n:`%` in :n:`as` clause of tactic :tacn:`specialize` (`#15245 `_, fixes `#15244 `_, by Hugo Herbelin). Tactic language ^^^^^^^^^^^^^^^ - **Fixed:** the parsing level of the Ltac2 tactic :tacn:`now` was set to level 6 in order to behave as it did before 8.14 (`#15250 `_, fixes `#15122 `_, by Pierre-Marie PΓ©drot). SSReflect ^^^^^^^^^ - **Changed:** rewrite generates subgoals in the expected order (side conditions first, by default) also when rewriting with a setoid relation (`#14314 `_, fixes `#5706 `_, by Enrico Tassi). - **Removed:** The ssrsearch plugin and the ssr Search command (`#13760 `_, by Jim Fehrle). - **Added:** port the additions made to `ssrbool.v` in math-comp `PR #757 `_, namely `reflect` combinators `negPP`, `orPP`, `andPP` and `implyPP` (`#15059 `_, by Christian Doczkal). - **Fixed:** SSR patterns now work with primitive values such as ints, floats or arrays (`#14660 `_, fixes `#12770 `_, by Juan Conejero). - **Fixed:** A bug where :tacn:`suff` would fail due to use of :tacn:`apply` under the hood (`#14687 `_, fixes `#14678 `_, by Ali Caglayan helped by Enrico Tassi). Commands and options ^^^^^^^^^^^^^^^^^^^^ .. _815Commands: - **Changed:** :cmd:`About` and :cmd:`Print` now display all known argument names (`#14596 `_, grants `#13830 `_, by Hugo Herbelin). - **Changed:** :cmd:`Typeclasses Transparent` and :cmd:`Typeclasses Opaque` support ``#[local]``, ``#[export]`` and ``#[global]`` attributes (`#14685 `_, fixes `#14513 `_, by GaΓ«tan Gilbert). - **Changed:** In extraction to OCaml, empty types in :n:`Type` (such as :n:`Empty_set`) are now extracted to an abstract type (empty by construction) rather than to the OCaml's :n:`unit` type (`#14802 `_, fixes a remark at `#14801 `_, by Hugo Herbelin). - **Changed:** Closed modules now live in a separate namespace from open modules and sections (`#15078 `_, fixes `#14529 `_, by GaΓ«tan Gilbert). - **Removed:** boolean attributes ``monomorphic``, ``noncumulative`` and ``notemplate`` that were replaced by ``polymorphic=no``, ``cumulative=no`` and ``template=no`` in 8.13 (`#14819 `_, by Pierre Roux). - **Removed:** command ``Grab Existential Variables`` that was deprecated in 8.13. Use :cmd:`Unshelve` that is mostly equivalent, up to the reverse order of the resulting subgoals (`#14819 `_, by Pierre Roux). - **Removed:** command ``Existential`` that was deprecated in 8.13. Use :cmd:`Unshelve` and :tacn:`exact` (`#14819 `_, by Pierre Roux). - **Removed:** the `-outputstate` command line argument and the corresponding vernacular commands `Write State` and `Restore State` (`#14940 `_, by Pierre-Marie PΓ©drot) - **Deprecated:** ambiguous :cmd:`Proof using` and :cmd:`Collection` usage (`#15056 `_, fixes `#13296 `_, by Wojciech Karpiel). - **Deprecated:** `Universal Lemma Under Conjunction` flag that was introduced for compatibility with Coq versions prior to 8.4 (`#15272 `_, by ThΓ©o Zimmermann). - **Deprecated:** using :cmd:`Hint Cut`, :cmd:`Hint Mode`, :cmd:`Hint Transparent`, :cmd:`Hint Opaque`, :cmd:`Typeclasses Transparent` or :cmd:`Typeclasses Opaque` without an explicit locality outside sections. (`#14697 `_, by Pierre-Marie PΓ©drot, and `#14685 `_, by GaΓ«tan Gilbert) - **Added:** The :flag:`Mangle Names Light` flag, which changes the behavior of :flag:`Mangle Names`. For example, the name `foo` becomes `_0` with :flag:`Mangle Names`, but with :flag:`Mangle Names Light` set, it will become `_foo` (`#14695 `_, fixes `#14548 `_, by Ali Caglayan). - **Added:** The :cmd:`Hint Cut`, :cmd:`Hint Mode`, :cmd:`Hint Transparent`, :cmd:`Hint Opaque`, :cmd:`Typeclasses Transparent` and :cmd:`Typeclasses Opaque` commands now accept the :attr:`local`, :attr:`export` and :attr:`global` locality attributes inside sections. With either attribute, the commands will trigger the `non-local-section-hint` warning if the arguments refer to local section variables (`#14697 `_, by Pierre-Marie PΓ©drot, and `#14685 `_, fixes `#14513 `_, by GaΓ«tan Gilbert). - **Added:** :attr:`projections(primitive)` attribute to make a record use primitive projections (`#14699 `_, fixes `#13150 `_, by Ali Caglayan). .. _815Import: - **Added:** Syntax for :token:`import_categories` providing selective import of module components (eg ``Import(notations) M`` (`#14892 `_, by GaΓ«tan Gilbert). - **Added:** :cmd:`Search` understands modifier ``in`` as an alias of ``inside`` (`#15139 `_, fixes `#14930 `_, by GaΓ«tan Gilbert). This is intended to ease transition for ssreflect Search users. - **Fixed:** interaction of Program's obligation state and modules and sections: obligations started in a parent module or section are not available to be solved until the submodules and subsections are closed (`#14780 `_, fixes `#14446 `_, by GaΓ«tan Gilbert). - **Fixed:** :cmd:`Eval` and :cmd:`Compute` now beta-iota-simplify the type of the result, like :cmd:`Check` does (`#14901 `_, fixes `#14899 `_, by Hugo Herbelin) Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** Coqdoc options ``--coqlib`` and ``--coqlib_path`` have been renamed to ``--coqlib_url`` and ``--coqlib`` to make them more consistent with flags used by other Coq executables (`#14059 `_, by Emilio Jesus Gallego Arias). - **Changed:** Syntax of `_CoqProject` files: `-arg` is now handled by :ref:`coq_makefile ` and not by `make`. Unquoted `#` now start line comments (`#14558 `_, by StΓ©phane Desarzens, with help from Jim Fehrle and Enrico Tassi). - **Changed:** :cmd:`Require` now selects files whose logical name exactly matches the required name, making it possible to unambiguously select a given file: if several :n:`-Q` or :n:`-R` options bind the same logical name to a different file, the option appearing last on the command line takes precedence. Moreover, it is now an error to require a file using a partial logical name which does not resolve to a non-ambiguous path (`#14718 `_, by Hugo Herbelin). - **Changed:** ``coq_makefile`` now declares variable ``COQBIN`` to avoid warnings in ``make --warn`` mode (`#14787 `_, by ClΓ©ment Pit-Claudel). - **Changed:** ``coqchk`` respects the :flag:`Kernel Term Sharing` flag instead of forcing it on (`#14957 `_, by GaΓ«tan Gilbert) - **Removed:** These options of :ref:`coq_makefile `: `-extra`, `-extra-phony`, `-custom`, `-no-install`, `-install`, `-no-opt`, `-byte`. Support for subdirectories is also removed (`#14558 `_, by StΓ©phane Desarzens, with help from Jim Fehrle and Enrico Tassi). - **Added:** :ref:`coq_makefile ` now takes the `-docroot` option as alternative to the `INSTALLCOQDOCROOT` variable (`#14558 `_, by StΓ©phane Desarzens, with help from Jim Fehrle and Enrico Tassi). - **Fixed:** Various `coqdep` issues with the `From` clause of :cmd:`Require` and a few inconsistencies between `coqdep` and `coqc` disambiguation of :cmd:`Require` (`#14718 `_, fixes `#11631 `_ and `#14539 `_, by Hugo Herbelin). - **Fixed:** ``coq_makefile`` has improved logic when dealing with incorrect ``_CoqProject`` files (`#13541 `_, fixes `#9319 `_, by Fabian Kunze). - **Fixed:** ``coqdep`` was confusing periods occurring in comments with periods ending Coq sentences (`#14996 `_, fixes `#7393 `_, by Hugo Herbelin). CoqIDE ^^^^^^ - **Changed:** CoqIDE unicode keys for brackets (e.g. `\langle`) now bind to unicode mathematical symbols rather than unicode CJK brackets (`#14452 `_, by Bart Jacobs). - **Changed:** All occurrences of the name `CoqIde` to `CoqIDE`. This may cause issues with installing and uninstalling desktop icons, causing apparent duplicates (`#14696 `_, fixes `#14310 `_, by Ali Caglayan). .. _815LtacDebugger: - **Added:** Initial version of a visual debugger in CoqIDE. Supports setting breakpoints visually and jumping to the stopping point plus continue, step over, step in and step out operations. Displays the call stack and variable values for each stack frame. Currently only for Ltac. See the documentation :ref:`here ` (`#14644 `_, fixes `#13967 `_, by Jim Fehrle) - **Fixed:** It is now possible to deactivate the unicode completion mechanism in CoqIDE (`#14863 `_, by Pierre-Marie PΓ©drot). Standard library ^^^^^^^^^^^^^^^^ - **Changed:** Permutation-related Proper instances are now at default priority instead of priority ``10`` (`#14574 `_, fixes `#14571 `_, by GaΓ«tan Gilbert). - **Changed:** The new type of `epsilon_smallest` is `(exists n : nat, P n) -> { n : nat | P n /\ forall k, P k -> n <= k }`. Here the minimality of `n` is expressed by `forall k, P k -> n <= k` corresponding to the intuitive meaning of minimality "the others are greater", whereas the previous version used the negative equivalent formulation `forall k, k < n -> ~P k`. Scripts using `epsilon_smallest` can easily be adapted using lemmas `le_not_lt` and `lt_not_le` from the standard library (`#14601 `_, by Jean-Francois Monin). - **Changed:** ``ltb`` and ``leb`` functions for ``ascii``, into comparison-based definition (`#14234 `_, by Yishuai Li). - **Removed:** the file ``Numeral.v`` that was replaced by ``Number.v`` in 8.13 (`#14819 `_, by Pierre Roux). - **Removed:** some ``*_invol`` functions that were renamed ``*_involutive`` for consistency with the remaining of the stdlib in 8.13 (`#14819 `_, by Pierre Roux). - **Deprecated:** ``frexp`` and ``ldexp`` in `FloatOps.v`, renamed ``Z.frexp`` and ``Z.ldexp`` (`#15085 `_, by Pierre Roux). - **Added:** A proof that incoherent equivalences can be adjusted to adjoint equivalences in ``Logic.Adjointification`` (`#13408 `_, by Jasper Hugunin). - **Added:** ``ltb`` and ``leb`` functions for ``string``, and some lemmas about them; - **Added:** simple non dependent product ``slexprod`` in ``Relations/Relation_Operators.v`` and its proof of well-foundness ``wf_slexprod`` in ``Wellfounded/Lexicographic_Product.v`` (`#14809 `_, by Laurent Thery). - **Added:** The notations ``(x; y)``, ``x.1``, ``x.2`` for sigT are now exported and available after ``Import SigTNotations.`` (`#14813 `_, by Laurent ThΓ©ry). - **Added:** The function ``sigT_of_prod`` turns a pair ``A * B`` into ``{_ : A & B}``. Its inverse function is ``prod_of_sigT``. This is shown by theorems ``sigT_prod_sigT`` and ``prod_sigT_prod`` (`#14813 `_, by Laurent ThΓ©ry). - **Fixed:** ``split_combine`` lemma for lists, making it usable (`#14458 `_, by Yishuai Li). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Coq's continuous integration now provides a more accessible Windows installer artifact in the "Checks" GitHub tab, both for pull requests and the `master` branch. This facilitates testing Coq's bleeding edge builds on Windows, and should be more reliable than the previous setup (`#12425 `_, by Emilio Jesus Gallego Arias). - **Changed:** Coq's ``./configure`` script has gone through a major cleanup. In particular, the following options have been removed: - ``-force-caml-version``, ``-force-findlib-version``: Coq won't compile with OCaml or findlib lower than the required versions; - ``-vmbyteflags``, ``-custom``, ``-no-custom``: linking options for toplevels are now controlled in ``topbin/dune``; - ``-ocamlfind``: Coq will now use the toolchain specified in the Dune configuration; this can be controlled using the workspaces feature; - ``-nodebug``: Coq will now follow the standard, which is to always pass ``-g`` to OCaml; this can be modified using a custom Dune workspace; - ``-flambda-opts``: compilation options are now set in Coq's root ``dune`` file, can be updated using a custom Dune workspace; - ``-local``, ``-bindir``, ``-coqdocdir``, ``-annotate``, ``-camldir``, ``-profiling``: these flags were deprecated in 8.14, and are now removed. Moreover, the ``-annot`` and ``-bin-annot`` flags only take effect to set ``coq-makefile``'s defaults (`#14189 `_, by Emilio Jesus Gallego Arias). - **Changed:** Configure will now detect the Dune version, and will correctly pass ``-etcdir`` and ``-docdir`` to the install procedure if Dune >= 2.9 is available. Note that the ``-docdir`` configure option now refers to root path for documentation. If you would like to install Coq documentation in ``foo/coq``, use ``-docdir foo`` (`#14844 `_, by Emilio Jesus Gallego Arias). - **Changed:** OCaml 4.13 is now officially supported (`#14879 `_, by Emilio Jesus Gallego Arias) - **Changed:** Sphinx 3.0.2 or above is now required to build the reference manual (`#14963 `_, by ThΓ©o Zimmermann) Extraction ^^^^^^^^^^ - **Changed:** replaced ``Big`` module with ``Big_int_Z`` functions from ``zarith``. OCaml code extracted with the following modules should be linked to the `Zarith `_ library. + ``ExtrOcamlNatBigInt`` + ``ExtrOcamlZBigInt`` Removed ``ExtrOcamlBigIntConv`` module. (`#8252 `_, by Yishuai Li). - **Fixed:** compilation errors in ExtrOcamlString and ExtrOcamlNativeString (`#15075 `_, fixes `#15076 `_, by Yishuai Li). Changes in 8.15.1 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** cases of incompletenesses in the guard condition for fixpoints in the presence of cofixpoints or primitive projections (`#15498 `_, fixes `#15451 `_, by Hugo Herbelin). - **Fixed:** inconsistency when using module subtyping with squashed inductives (`#15839 `_, fixes `#15838 `_ (reported by Pierre-Marie PΓ©drot), by GaΓ«tan Gilbert). Notations ^^^^^^^^^ - **Fixed:** Check for prior declaration of a custom entry was missing for notations in only printing mode (`#15628 `_, fixes `#15619 `_, by Hugo Herbelin). Tactics ^^^^^^^ - **Fixed:** :tacn:`rewrite_strat` regression in 8.15.0 related to `Transitive` instances (`#15577 `_, fixes `#15568 `_, by GaΓ«tan Gilbert). - **Fixed:** When :tacn:`setoid_rewrite` succeeds in rewriting at some occurrence but the resulting equality is the identity, it now tries rewriting in subterms of that occurrence instead of giving up (`#15612 `_, fixes `#8080 `_, by GaΓ«tan Gilbert). - **Fixed:** Ill-typed goals created by :tacn:`clearbody` in the presence of transitive dependencies in the body of a hypothesis (`#15634 `_, fixes `#15606 `_, by Hugo Herbelin). - **Fixed:** :tacn:`cbn` knows to refold fixpoints when :cmd:`Arguments` with ``/`` and ``!`` was used (`#15653 `_, fixes `#15567 `_, by GaΓ«tan Gilbert). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Fixed:** a bug where :n:`coqc -vok` was not creating an empty '.vok' file (`#15745 `_, by Ramkumar Ramachandra). CoqIDE ^^^^^^ - **Fixed:** Line numbers shown in the Errors panel were incorrect; they didn't match the error locations in the script panel (`#15532 `_, fixes `#15531 `_, by Jim Fehrle). - **Fixed:** anomaly when using proof diffs with no focused goal (`#15633 `_, fixes `#15578 `_, by Jim Fehrle). - **Fixed:** Attempted edits to the processed part of a buffer while Coq is busy processing a request are now ignored to ensure "processed" highlighting is accurate (`#15714 `_, fixes `#15733 `_ and `#15675 `_ and `#15725 `_, by Jim Fehrle). Miscellaneous ^^^^^^^^^^^^^ - **Fixed:** Ensure that the names of arguments of inductive schemes are distinct so that the new Coq 8.15 preservation of argument names in the ``with`` clause of tactics in `#13837 `_ works as in Coq 8.14 for these schemes (`#15537 `_, fixes `#15420 `_, by Hugo Herbelin). Changes in 8.15.2 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Tactics ^^^^^^^ - **Added:** :tacn:`intuition` and :tacn:`dintuition` use ``Tauto.intuition_solver`` (defined as ``auto with *``) instead of hardcoding ``auto with *``. This makes it possible to change the default solver with ``Ltac Tauto.intuition_solver ::= ...`` (`#15866 `_, fixes `#7725 `_, by GaΓ«tan Gilbert). - **Fixed:** uncaught exception ``UnableToUnify`` with bidirectionality hints (`#16066 `_, fixes `#16063 `_, by GaΓ«tan Gilbert). CoqIDE ^^^^^^ - **Fixed:** multiple CoqIDE bugs (`#15938 `_, fixes `#15861 `_, `#15939 `_, fixes `#15882 `_, `#15964 `_, fixes `#15799 `_, `#15984 `_, partially fixes `#15873 `_, `#15996 `_, `#15912 `_, fixes `#15903 `_, all by Jim Fehrle). Standard library ^^^^^^^^^^^^^^^^ - **Fixed:** an incorrect implementation of SFClassify, allowing for a proof of False since 8.11.0, due to Axioms present in Float.Axioms (`#16101 `_, fixes `#16096 `_, by Ali Caglayan). Version 8.14 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.14 integrates many usability improvements, as well as an important change in the core language. The main changes include: - The :ref:`internal representation <814CaseRepresentation>` of `match` has changed to a more space-efficient and cleaner structure, allowing the fix of a completeness issue with cumulative inductive types in the type-checker. The internal representation is now closer to the user-level view of `match`, where the argument context of branches and the inductive binders `in` and `as` do not carry type annotations. - A :ref:`new <814CoqNative>` `coqnative` binary performs separate native compilation of libraries, starting from a `.vo` file. It is supported by `coq_makefile`. - :ref:`Improvements <814TCCanon>` to typeclasses and canonical structure resolution, allowing more terms to be considered as classes or keys. - More control over :ref:`notations <814Notations>` declarations and support for primitive types in string and number notations. - :ref:`Removal <814Tactics>` of deprecated tactics, notably `omega`, which has been replaced by a greatly improved `lia`, along with many bug fixes. - New :ref:`Ltac2 <814Ltac2>` APIs for interaction with Ltac1, manipulation of inductive types and printing. - Many :ref:`changes and additions <814Stdlib>` to the standard library in the numbers, vectors and lists libraries. A new signed primitive integers library `Sint63` is available in addition to the unsigned `Uint63` library. See the `Changes in 8.14.0`_ section below for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's `reference manual `_, `documentation of the standard library `_ and `developer documentation of the ML API `_ are also available. Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The `Coq Platform `_ has been maintained by Michael Soegtrop and Enrico Tassi. Our current maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Ali Caglayan, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. See the `Coq Team face book `_ page for more details. The 54 contributors to this version are Reynald Affeldt, Arthur Azevedo de Amorim, Yves Bertot, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, Ana Borges, Ali Caglayan, Cyril Cohen, Pierre Courtieu, Maxime DΓ©nΓ¨s, StΓ©phane Desarzens, Andrej Dudenhefner, Jim Fehrle, Yannick Forster, Simon Friis Vindum, GaΓ«tan Gilbert, Jason Gross, Samuel Gruetter, Stefan Haan, Hugo Herbelin, Jasper Hugunin, Emilio JesΓΊs Gallego Arias, Jacques-Henri Jourdan, Ralf Jung, Jan-Oliver Kaiser, Fabian Kunze, Vincent Laporte, Olivier Laurent, Yishuai Li, Barry M. Trager, Kenji Maillard, Erik Martin-Dorel, Guillaume Melquiond, Isaac Oscar Gariano, Pierre-Marie PΓ©drot, Rudy Peterson, ClΓ©ment Pit-Claudel, Pierre Roux, Takafumi Saikawa, Kazuhiko Sakaguchi, Gabriel Scherer, Vincent Semeria, shenlebantongying, Avi Shinnar, slrnsc, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Hendrik Tews, Anton Trunov, Karolin Varner, Li-yao Xia, Beta Ziliani and ThΓ©o Zimmermann. The Coq community at large helped improve the design of this new version via the GitHub issue and pull request system, the Coq development mailing list coqdev@inria.fr, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.14's development spanned 9 months from the release of Coq 8.13.0. Guillaume Melquiond is the release manager of Coq 8.14. This release is the result of 522 merged PRs, closing ~150 issues. | Nantes, September 2021, | Matthieu Sozeau for the Coq development team Changes in 8.14.0 ~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ .. _814CaseRepresentation: - **Changed:** The term representation of pattern-matchings now uses a compact form that provides a few static guarantees such as eta-expansion of branches and return clauses and is usually more efficient. The most visible user change is that for the time being, the :tacn:`destruct` tactic and its variants generate dummy cuts (Ξ² redexes) in the branches of the generated proof. This can also generate very uncommon backwards incompatibilities, such as a change of occurrence numbering for subterms, or breakage of unification in complex situations involving pattern-matchings whose underlying inductive type declares let-bindings in parameters, arity or constructor types. For ML plugin developers, an in-depth description of the new representation, as well as porting tips, can be found in dev/doc/case-repr.md (`#13563 `_, fixes `#3166 `_, by Pierre-Marie PΓ©drot). - **Changed:** Linking of native-code libraries used by :tacn:`native_compute` is now delayed until an actual call to the :tacn:`native_compute` machinery is performed. This should make Coq more responsive on some systems (`#13853 `_, fixes `#13849 `_, by Guillaume Melquiond). - **Removed:** The ability to change typing flags inside sections to prevent exploiting a weakness in :cmd:`Print Assumptions` (`#14395 `_, fixes `#14317 `_, by GaΓ«tan Gilbert). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _814TCCanon: - **Changed:** The hints mode ``!`` matches a term iff the applicative head is not an existential variable. It now also matches projections applied to any term or a `match` on any term (`#14392 `_, by Matthieu Sozeau). - **Removed:** The little used `:>` type cast, which was only interpreted in Program-mode (`#13911 `_, by Jim Fehrle and ThΓ©o Zimmermann). - **Added:** Enable canonical `fun _ => _` projections, see :ref:`canonicalstructures` for details (`#14041 `_, by Jan-Oliver Kaiser and Pierre Roux, reviewed by Cyril Cohen and Enrico Tassi). - **Added:** :cmd:`Canonical Structure` declarations now accept dependent function types `forall _, _` as keys (`#14386 `_, by Jan-Oliver Kaiser and Kazuhiko Sakaguchi). - **Added:** Ability to declare primitive projections as class, for dependent typeclass resolutions (`#9711 `_, fixes `#12975 `_, by Matthieu Sozeau). - **Fixed:** Multiple printing of same warning about unused variables catching several cases (`#14261 `_, fixes `#14207 `_, by Hugo Herbelin). - **Fixed:** Constants :g:`id` and :g:`not` were unduly set opaque in some parts of the unification algorithm (`#14371 `_, fixes `#14374 `_, by Hugo Herbelin). Notations ^^^^^^^^^ .. _814Notations: - **Changed:** Flag :flag:`Printing Notations` no longer controls whether strings and numbers are printed raw (`#13840 `_, by Enrico Tassi). - **Changed:** The error ``Argument X was previously inferred to be in scope XXX_scope but is here used in YYY_scope.`` is now the warning ``[inconsistent-scopes,syntax]`` and can be silenced by specifying the scope of the argument (`#13965 `_, by Enrico Tassi). - **Removed:** Decimal-only number notations which were deprecated in 8.12 (`#13842 `_, by Pierre Roux). - **Added:** :cmd:`Number Notation` and :cmd:`String Notation` now support parsing and printing of primitive floats, primitive arrays and type constants of primitive types (`#13519 `_, fixes `#13484 `_ and `#13517 `_, by Fabian Kunze, with help of Jason Gross) - **Added:** Flag :flag:`Printing Raw Literals` to control whether strings and numbers are printed raw (`#13840 `_, by Enrico Tassi). - **Added:** Let the user specify a scope for abbreviation arguments, e.g. ``Notation abbr X := t (X in scope my_scope)`` (`#13965 `_, by Enrico Tassi). - **Added:** Look-ahead of tokens is changed from sequential to tree-based, allowing more automatic rule factorizations in notations (`#14070 `_, by Hugo Herbelin). - **Fixed:** Non-local custom entries survive module closing and are declared when a file is Required (`#14183 `_, fixes `#13654 `_, by GaΓ«tan Gilbert). - **Fixed:** :g:`ident` modifier in custom entry notations gave fatal errors at printing time (`#14257 `_, fixes `#14211 `_, by Hugo Herbelin). - **Fixed:** Anomaly when overriding a notation with different applicability in :g:`match` patterns (`#14377 `_, fixes `#13966 `_, by Hugo Herbelin). Tactics ^^^^^^^ .. _814Tactics: - **Changed:** More systematic checks that occurrences of an :n:`at` clause are valid in tactics such as :tacn:`rewrite` or :tacn:`pattern` (`#13568 `_, fixes `#13566 `_, by Hugo Herbelin). - **Removed:** :tacn:`fail` and :tacn:`gfail`, which formerly accepted negative values as a parameter, now give syntax errors for negative values (`#13469 `_, by Jim Fehrle). - **Removed:** Deprecated flag ``Bracketing Last Introduction Pattern`` affecting the behavior of trailing disjunctive introduction patterns is definitively removed (`#13509 `_, by Hugo Herbelin). - **Removed:** The `omega` tactic (deprecated in 8.12) and four `* Omega *` flags. Use `lia` instead (`#13741 `_, by Jim Fehrle, who addressed the final details, building on much work by FrΓ©dΓ©ric Besson, who greatly improved :tacn:`lia`, Maxime DΓ©nΓ¨s, Vincent Laporte and with the help of many package maintainers, among others). - **Removed:** convert_concl_no_check. Use :tacn:`change_no_check` instead (`#13761 `_, by Jim Fehrle). - **Removed:** double induction tactic. Replace :n:`double induction @ident @ident` with :n:`induction @ident; induction @ident` (or :n:`induction @ident ; destruct @ident` depending on the exact needs). Replace :n:`double induction @natural__1 @natural__2` with :n:`induction @natural__1; induction natural__3` where :n:`natural__3` is the result of :n:`natural__2 - natural__1` (`#13762 `_, by Jim Fehrle). - **Deprecated:** In :tacn:`change` and :tacn:`change_no_check`, the `at ... with ...` form is deprecated. Use `with ... at ...` instead. For `at ... with ... in H |-`, use `with ... in H at ... |-` (`#13696 `_, by Jim Fehrle). - **Deprecated:** The micromega option `Simplex`, which is currently set by default (`#13781 `_, by FrΓ©dΓ©ric Besson). - **Deprecated:** the undocumented `new auto` tactic (`#14528 `_, by Pierre-Marie PΓ©drot). - **Added:** :tacn:`lia` supports the boolean operator `Bool.implb` (`#13715 `_, by FrΓ©dΓ©ric Besson). - **Added:** ``zify`` (``lia``/``nia``) support for :g:`div`, :g:`mod`, :g:`pow` for :g:`Nat` (via ``ZifyNat`` module) and :g:`N` (via ``ZifyN`` module). The signature of :g:`Z_div_mod_eq_full` has no assumptions (`#14037 `_, fixes `#11447 `_, by Andrej Dudenhefner, Jason Gross, and FrΓ©dΓ©ric Besson). - **Added:** Ltac2 now has a `unify` tactic (`#14089 `_, fixes `#14083 `_, by Samuel Gruetter). - **Added:** :tacn:`inversion_sigma` can now be applied to a specified hypothesis and additionally supports intropatterns, so it can be used much like :tacn:`induction` and :tacn:`inversion`. Additionally, :tacn:`inversion_sigma` now supports the types :n:`ex` (:n:`exists x : A, P x`) and :n:`ex2` (:n:`exists2 x : A, P x & Q x`) in cases where the first argument :n:`A` is a :n:`Prop` (`#14174 `_, by Jason Gross). - **Added:** ``zify`` (``lia``/``nia``) support for ``Sint63`` (`#14408 `_, by Ana Borges, with help from FrΓ©dΓ©ric Besson). - **Fixed:** Possible collision between a user-level name and an internal name when using the :n:`%` introduction pattern (`#13512 `_, fixes `#13413 `_, by Hugo Herbelin). - **Fixed:** :tacn:`simpl` and :tacn:`hnf` now reduce primitive functions on primitive integers, floats and arrays (`#13699 `_, fixes `#13579 `_, by Pierre Roux). - **Fixed:** Setoid rewriting now remembers the (invisible) binder names of non-dependent product types. SSReflect's rewrite tactic expects these names to be retained when using ``rewrite foo in H``. This also fixes SSR ``rewrite foo in H *`` erroneously reverting ``H`` (`#13882 `_, fixes `#12011 `_, by GaΓ«tan Gilbert). - **Fixed:** Properly expand projection parameters in hint discrimination nets. (`#14033 `_, fixes `#9000 `_, `#14009 `_, by Pierre-Marie PΓ©drot). - **Fixed:** anomalies caused by empty strings in Ltac notations are now errors (`#14378 `_, fixes `#14124 `_, by Hugo Herbelin). - **Fixed:** Print a message instead of a Diff_Failure anomaly when old and new goals can't be matched; show the goal without diff highlights (`#14457 `_, fixes `#14425 `_, by Jim Fehrle). - **Fixed:** Anomaly of :tacn:`destruct` on terms with dependent variables unused in goal (`#15099 `_, fixes `#11504 `_ and `#14090 `_, by Lasse Blaauwbroek and Hugo Herbelin). - **Fixed:** Correct convertibility of multiple terms selected by patterns in tactics such as :tacn:`set` when these terms have subterms in `SProp` (`#14610 `_, fixes `#14609 `_, by Hugo Herbelin). Tactic language ^^^^^^^^^^^^^^^ .. _814Ltac2: - **Changed:** Renamed Ltac2 ``Bool.eq`` into ``Bool.equal`` for uniformity. The old function is now a deprecated alias (`#14128 `_, by Pierre-Marie PΓ©drot). - **Added:** A ``printf`` macro to Ltac2. It can be made accessible by importing the ``Ltac2.Printf`` module. See the documentation there for more information (`#13236 `_, fixes `#10108 `_, by Pierre-Marie PΓ©drot). - **Added:** A function ``Ltac1.lambda`` allowing to embed Ltac2 functions into Ltac1 runtime values (`#13442 `_, fixes `#12871 `_, by Pierre-Marie PΓ©drot). - **Added:** Ltac2 commands defining terms now accept the :attr:`deprecated` attribute (`#13774 `_, fixes `#12317 `_, by Pierre-Marie PΓ©drot). - **Added:** Allow the presence of type casts for function return values, let bindings and global definitions in Ltac2 (`#13914 `_, by Pierre-Marie PΓ©drot). - **Added:** The Ltac2 API `Ltac2.Ind` for manipulating inductive types (`#13920 `_, fixes `#10095 `_, by Pierre-Marie PΓ©drot). - **Added:** Allow scope delimiters in Ltac2 ``open_constr:(...)`` quotation (`#13939 `_, fixes `#12806 `_, by Pierre-Marie PΓ©drot). - **Added:** A FFI to convert between Ltac1 and Ltac2 identifiers (`#13997 `_, fixes `#13996 `_, by Pierre-Marie PΓ©drot). - **Added:** Lazy evaluating boolean operators ``lazy_and``, ``lazy_or``, ``lazy_impl`` and infix notations ``&&`` and ``||`` to the Ltac2 `Bool.v` library l (`#14081 `_, fixes `#13964 `_, by Michael Soegtrop). - **Fixed:** Ltac2 notations now correctly take into account their assigned level (`#14094 `_, fixes `#11866 `_, by Pierre-Marie PΓ©drot). SSReflect ^^^^^^^^^ - **Added:** A test that the notations `{in _, _}` and `{pred _}` from `ssrbool.v` are displayed correctly (`#13473 `_, by Cyril Cohen). - **Added:** Lemmas about interaction between :n:`{in _, _}`, :n:`{on _, _}`, and :n:`sig` have been backported from Mathematical Components 1.12.0 (`#13490 `_, by Kazuhiko Sakaguchi). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** :cmd:`Hint Rewrite` now supports locality attributes (including :attr:`export`) like other :ref:`Hint ` commands (`#13725 `_, fixes `#13724 `_, by GaΓ«tan Gilbert). - **Changed:** In :cmd:`Record`, alpha-rename the variable associated with the record to avoid alpha-renaming parameters of projections (`#13852 `_, fixes `#13727 `_, by Li-yao Xia). - **Changed:** Improve the :cmd:`Coercion` command to reduce the number of ambiguous paths to report. A pair of multiple inheritance paths that can be reduced to smaller adjoining pairs will not be reported as ambiguous paths anymore (`#13909 `_, by Kazuhiko Sakaguchi). - **Changed:** The printing order of :cmd:`Print Classes` and :cmd:`Print Graph`, due to the changes for the internal tables of coercion classes and coercion paths (`#13912 `_, by Kazuhiko Sakaguchi). - **Removed:** The Hide Obligations flag, deprecated in 8.12 (`#13758 `_, by Jim Fehrle). - **Removed:** SearchHead command. Use the `headconcl:` clause of :cmd:`Search` instead (`#13763 `_, by Jim Fehrle). - **Removed:** `Show Zify Spec`, `Add InjTyp` and 11 similar `Add *` commands. For `Show Zify Spec`, use `Show Zify UnOpSpec` or `Show Zify BinOpSpec` instead. For `Add *`, `Use Add Zify *` intead of `Add *` (`#13764 `_, by Jim Fehrle). - **Deprecated:** Like hints, typeclass instances added outside of sections without an explicit locality now generate a deprecation warning. See :ref:`Hint ` (`#14208 `_, fixes `#13562 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** the `Regular Subst Tactic` flag (`#14336 `_, by Pierre-Marie PΓ©drot). - **Added:** :opt:`Debug` to control debug messages, functioning similarly to the warning system (`#13202 `_, by Maxime DΓ©nΓ¨s and GaΓ«tan Gilbert). The following flags have been converted (such that ``Set Flag`` becomes ``Set Debug "flag"``): - ``Debug Unification`` to ``unification`` - ``Debug HO Unification`` to ``ho-unification`` - ``Debug Tactic Unification`` to ``tactic-unification`` - ``Congruence Verbose`` to ``congruence`` - ``Debug Cbv`` to ``cbv`` - ``Debug RAKAM`` to ``RAKAM`` - ``Debug Ssreflect`` to ``ssreflect`` - **Added:** The Ltac2 grammar can now be printed using the Print Grammar ltac2 command (`#14093 `_, fixes `#14092 `_, by Pierre-Marie PΓ©drot). - **Added:** :cmd:`Instance` now accepts the :attr:`export` locality attribute (`#14148 `_, by Pierre-Marie PΓ©drot). - **Fixed:** extraction failure of a parameterized type in :g:`Prop` exported in an module interface as an assumption in :g:`Type` (`#14102 `_, fixes `#14100 `_, by Hugo Herbelin). - **Fixed:** Print Assumptions now treats delayed opaque proofs generated by vos compilation as if they were axioms (`#14382 `_, fixes `#13589 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Incorrect de Bruijn index handling in vernac class declaration, preventing users from marking existing instances of existing classes which are primitive projections (`#14664 `_, fixes `#14652 `_, by Ali Caglayan and Hugo Herbelin). Command-line tools ^^^^^^^^^^^^^^^^^^ - **Changed:** `coqc` now enforces that at most a single `.v` file can be passed in the command line. Support for multiple `.v` files in the form of `coqc f1.v f2.v` didn't properly work in 8.13, tho it was accepted (`#13876 `_, by Emilio Jesus Gallego Arias). - **Changed:** ``coqdep`` now reports an error if files specified on the command line don't exist or if it encounters unreadable files. Unknown options now generate a warning. Previously these conditions were ignored (`#14024 `_, fixes `#14023 `_, by Hendrik Tews). - **Changed:** Makefiles produced by ``coq_makefile`` now use ``.DELETE_ON_ERROR`` (`#14238 `_, by GaΓ«tan Gilbert). - **Removed:** Previously deprecated command line options ``-sprop-cumulative`` and ``-input-state`` and its alias ``-is`` (`#13822 `_, by GaΓ«tan Gilbert). - **Added:** ``coq_makefile``\-made ``Makefile``\s now support inclusion of a ``.local-late`` file at the end, allowing the user to access more variables (`#12411 `_, fixes `#10912 `_, by Jason Gross). - **Fixed:** Failure of extraction in the presence of inductive types with local definitions in parameters (`#13624 `_, fixes `#13581 `_, by Hugo Herbelin). - **Fixed:** File name was missing in coqdoc error position reporting (`#14285 `_, fixes `#14283 `_, by Arthur CharguΓ©raud and Hugo Herbelin). Native Compilation ^^^^^^^^^^^^^^^^^^ .. _814CoqNative: - **Changed:** `coq_makefile` now uses the `coqnative` binary to generate native compilation files. Project files also understand directly the `-native-compiler` flag without having to wrap it with `-arg` (`#14265 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** the `-native-compiler` option for coqc. It is now recommended to use the :ref:`rocqnative` binary instead to generate native compilation files ahead of time (`#14309 `_, by Pierre-Marie PΓ©drot). - **Added:** A standalone `coqnative` binary that performs native compilation out of `vo` files, allowing to split library compilation from native compilation. See :ref:`rocqnative`. The hybrid build system was adapted to perform a split compilation on the stdlib (`#13287 `_, by Pierre-Marie PΓ©drot). CoqIDE ^^^^^^ .. _814CoqIDE: - **Added:** Ltac debugger support in CoqIDE (see :flag:`Ltac Debug`). Debugger output and prompts appear in the Messages panel (`#13783 `_, by Jim Fehrle and Emilio J. Gallego Arias). - **Added:** Shift-return in the Find dialog now searches backwards (`#13810 `_, by slrnsc). Standard library ^^^^^^^^^^^^^^^^ .. _814Stdlib: - **Changed:** Minor Changes to ``Rpower``: Generalizes ``exp_ineq1`` to hold for all non-zero numbers. Adds ``exp_ineq1_le``, which holds for all reals (but is a ``<=`` instead of a ``<``) (`#13582 `_, by Avi Shinnar and Barry Trager, with help from Laurent ThΓ©ry). - **Changed:** set :g:`n mod 0 = n` uniformly for :g:`nat`, :g:`N`, :g:`Z`, :g:`int63`, :g:`sint63`, :g:`int31` such that :g:`m = (m / n) * n + (m mod n)` holds (also for :g:`n = 0`) .. warning:: code that relies on :g:`n mod 0 = 0` will break; for compatibility with both :g:`n mod 0 = n` and :g:`n mod 0 = 0` you can use :g:`n mod 0 = ltac:(match eval hnf in (1 mod 0) with |0 => exact 0 |_ => exact n end)` (`#14086 `_, by Andrej Dudenhefner with help of Guillaume Melquiond, Jason Gross, and Kazuhiko Sakaguchi). - **Changed:** The standard library now contains a more complete theory of equality on types of the form :g:`exists x : A, P x` and :g:`exists2 x : A, P x & Q x` when we have :g:`A : Prop`. To bring this theory more in line with the existing theory about sigma types, :g:`eq_ex_uncurried`, :g:`eq_ex2_uncurried`, :g:`eq_ex`, :g:`eq_ex2`, :g:`eq_ex_hprop`, :g:`eq_ex2_hprop` have been renamed into :g:`eq_ex_intro_uncurried`, :g:`eq_ex_intro2_uncurried`, :g:`eq_ex_intro`, :g:`eq_ex_intro2`, :g:`eq_ex_intro_hprop`, :g:`eq_ex_intro2_hprop` respectively and the implicit status of these lemmas has changed slightly (`#14174 `_, by Jason Gross). - **Changed** Moved 39 lemmas and notations about the rationals `Q` from the constructive reals private file `theories/Reals/Cauchy/QExtra.v` to appropriate files in `theories/QArith`. The now public lemmas are mostly about compatibility of multiplication and power with relational operators and simple convenience lemmas e.g. for reduction of `Q` values. The following moved lemmas have been renamed: `Q_factorDenom` to `Qmult_frac_l`, `Q_reduce_fl` to `Qreduce_num_l`, `Qle_neq` to `Qlt_leneq`, `Qmult_lt_le_compat_nonneg` to `Qmult_le_lt_compat_pos`, `Qpower_pos_lt` to `Qpower_0_lt`, `Qpower_lt_1_increasing` to `Qpower_1_lt_pos`, `Qpower_lt_1_increasing'` to `Qpower_1_lt`, `Qpower_le_1_increasing` to `Qpower_1_le_pos`, `Qpower_le_1_increasing'` to `Qpower_1_le`, `Qzero_eq` to `Qreduce_zero`, `Qpower_lt_compat` to `Qpower_lt_compat_l`, `Qpower_le_compat` to `Qpower_le_compat_l`, `Qpower_lt_compat_inv` to `Qpower_lt_compat_l_inv`, `Qpower_le_compat_inv` to `Qpower_le_compat_l_inv`, `Qpower_decomp'` to `Qpower_decomp_pos` and `QarchimedeanExp2_Pos` to `Qarchimedean_power2_pos`. The following lemmas have been renamed and the sides of the equality swapped: `Qinv_swap_pos` to `Qinv_pos`, `Qinv_swap_neg` to `Qinv_neg` and. The following lemmas have been deleted: `Q_factorNum_l` and `Q_factorNum`. The lemma `Qopp_lt_compat` has been moved from `theories/QArith/Qround.v` to `theories/QArith/QArith_base.v`. About 10 additional lemmas have been added for similar cases as the moved lemmas. Compatibility notations are not provided because QExtra is considered internal (excluded from the library documentation) (`#14293 `_, by Michael Soegtrop). - **Changed:** Importing `ZArith` no longer has the side-effect of closing `Z_scope` (`#14343 `_, fixes `#13307 `_, by Ralf Jung). - **Removed:** ``IF_then_else`` definition and corresponding ``IF P then Q else R`` notation (`#13871 `_, by Yishuai Li). - **Removed:** from ``List.v`` deprecated/unexpected dependencies ``Setoid``, ``Le``, ``Gt``, ``Minus``, ``Lt`` (`#13986 `_, by Andrej Dudenhefner). - **Deprecated:** Unsigned primitive integers are now named ``uint63`` instead of ``int63``. The ``Int63`` module is replaced by ``Uint63``. The full list of changes is described in the PR (`#13895 `_, by Ana Borges). - **Added:** ``leb`` and ``ltb`` functions for ``ascii`` (`#13080 `_, by Yishuai Li). - **Added:** Library for signed primitive integers, Sint63. The following operations were added to the kernel: division, remainder, comparison functions, and arithmetic shift right. Everything else works the same for signed and unsigned ints (`#13559 `_, fixes `#12109 `_, by Ana Borges, Guillaume Melquiond and Pierre Roux). - **Added:** Lemmas about vectors related with ``to_list``: ``length_to_list``, ``of_list_to_list_opp``, ``to_list_nil``, ``to_list_cons``, ``to_list_hd``, ``to_list_last``, ``to_list_const``, ``to_list_nth_order``, ``to_list_tl``, ``to_list_append``, ``to_list_rev_append_tail``, ``to_list_rev_append``, ``to_list_rev``, ``to_list_map``, ``to_list_fold_left``, ``to_list_fold_right``, ``to_list_Forall``, ``to_list_Exists``, ``to_list_In``, ``to_list_Forall2`` (`#13671 `_, by Olivier Laurent). - **Added:** Lemmas about ``count_occ``: ``count_occ_app``, ``count_occ_elt_eq``, ``count_occ_elt_neq``, ``count_occ_bound``, ``count_occ_repeat_eq``, ``count_occ_repeat_neq``, ``count_occ_unique``, ``count_occ_repeat_excl``, ``count_occ_sgt``, ``Permutation_count_occ`` (`#13804 `_, by Olivier Laurent with help of Jean-Christophe LΓ©chenet). - **Added:** Lemmas to ``List``: ``Exists_map``, ``Exists_concat``, ``Exists_flat_map``, ``Forall_map``, ``Forall_concat``, ``Forall_flat_map``, ``nth_error_map``, ``nth_repeat``, ``nth_error_repeat`` (`#13955 `_, by Andrej Dudenhefner, with help from Olivier Laurent). - **Added:** ``Cantor.v`` containing the Cantor pairing function and its inverse. ``Cantor.to_nat : nat * nat -> nat`` and ``Cantor.of_nat : nat -> nat * nat`` are the respective bijections between ``nat * nat`` and ``nat`` (`#14008 `_, by Andrej Dudenhefner). - **Added:** Lemmas to ``Q``: ``Qeq_from_parts``, ``Qden_cancel``, ``Qnum_cancel``, ``Qreduce_l``, ``Qreduce_r``, ``Qmult_inject_Z_l``, ``Qmult_inject_Z_r`` QArith_base Reduction of rationals; establishing equality for Qden/Qnum separately (`#14087 `_, by Karolin Varner). - **Added:** ``Coq.Structures.OrdersEx.String_as_OT`` and ``Coq.Structures.OrdersEx.Ascii_as_OT`` to make strings and ascii ordered types (using lexical order). (`#14096 `_, by Jason Gross). - **Added:** Lemmas :g:`app_eq_app`, :g:`Forall_nil_iff`, :g:`Forall_cons_iff` to ``List.v`` (`#14153 `_, closes `#1803 `_, by Andrej Dudenhefner, with help from Olivier Laurent). - **Added:** ``Z``, ``positive`` and ``N`` constants can now be printed in hexadecimal by opening ``hex_Z_scope``, ``hex_positive_scope``, and ``hex_N_scope`` respectively (`#14263 `_, by Jason Gross). - **Added:** Absolute value function for Sint63 (`#14384 `_, by Ana Borges). - **Added:** Lemmas showing :g:`firstn` and :g:`skipn` commute with :g:`map` (`#14406 `_, by Rudy Peterson). - **Fixed:** Haskell extraction is now compatible with GHC versions >= 9.0. Some ``#if`` statements have been added to extract ``unsafeCoerce`` to its new location in newer versions of GHC. (`#14345 `_, fixes `#14256 `_, by Jason Gross). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _814Dune: - **Changed:** Coq's configure script now requires absolute paths for the `-prefix` option (`#12567 `_, by Emilio Jesus Gallego Arias). - **Changed:** The regular Coq package has been split in two: coq-core, with OCaml-based libraries and tools; and coq-stdlib, which contains the Gallina-based standard library. The package Coq now depends on both for compatiblity (`#12567 `_, by Emilio Jesus Gallego Arias, review by Vincent Laporte, Guillaume Melquiond, Enrico Tassi, and ThΓ©o Zimmerman). - **Changed:** Coq's OCaml parts and tools [``coq-core``] are now built using Dune. The main user-facing change is that Dune >= 2.5 is now required to build Coq. This was a large and complex change. If you are packager you may find some minor differences if you were using a lot of custom optimizations. Note that, in particular, the configure option ``-datadir`` is not customizable anymore, and ``-bindir`` has been removed in favor of ``$prefix/bin``. Moreover, the install procedure will ignore ``-docdir`` and ``-etcdir``, unless you patch the makefile and use Dune >= 2.9. We usually recommended using a recent Dune version, if possible. For developers and plugin authors, see the entry in `dev/doc/changes.md`. For packagers and users, see `dev/doc/INSTALL.make.md` (`#13617 `_, by Emilio JesΓΊs Gallego Arias, Rudi Grinberg, and ThΓ©o Zimmerman; review and testing by GaΓ«tan Gilbert, Guillaume Melquiond, and Enrico Tassi) - **Changed:** Undocumented variables ``OLDROOT`` and ``COQPREFIXINSTALL`` which added a prefix path to ``make install`` have been removed. Now, ``make install`` does support the more standard ``DESTDIR`` variable, akin to what ``coq_makefile`` does (`#14258 `_, by Emilio Jesus Gallego Arias). - **Added:** Support OCaml 4.12 (`#13885 `_, by Emilio Jesus Gallego Arias, review by GaΓ«tan Gilbert and ThΓ©o Zimmerman). Miscellaneous ^^^^^^^^^^^^^ - **Changed:** The representation of micromega caches was slightly altered for efficiency purposes. As a consequence all stale caches must be cleaned up (`#13405 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Fix the timeout facility on Unix to allow for nested timeouts. Previous behavior on nested timeouts was that an "inner" timeout would replace an "outer" timeout, so that the outer timeout would no longer fire. With the new behavior, Unix and Windows implementations should be (approximately) equivalent (`#13586 `_, by Lasse Blaauwbroek). Changes in 8.14.1 ~~~~~~~~~~~~~~~~~ Kernel ^^^^^^ - **Fixed:** Fix the implementation of persistent arrays used by the VM and native compute so that it uses a uniform representation. Previously, storing primitive floats inside primitive arrays could cause memory corruption (`#15081 `_, closes `#15070 `_, by Pierre-Marie PΓ©drot). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Fixed:** Missing registration of universe constraints in :cmd:`Module Type` elaboration (`#14666 `_, fixes `#14505 `_, by Hugo Herbelin). Tactics ^^^^^^^ - **Fixed:** :tacn:`abstract` more robust with respect to Ltac `constr` bindings containing existential variables (`#14671 `_, fixes `#10796 `_, by Hugo Herbelin). - **Fixed:** correct support of trailing :n:`let` by tactic :tacn:`specialize` (`#15046 `_, fixes `#15043 `_, by Hugo Herbelin). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Fixed:** anomaly with :flag:`Extraction Conservative Types` when extracting pattern-matching on singleton types (`#14669 `_, fixes `#3527 `_, by Hugo Herbelin). - **Fixed:** a regular error instead of an anomaly when calling :cmd:`Separate Extraction` in a module (`#14670 `_, fixes `#10796 `_, by Hugo Herbelin). Version 8.13 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.13 integrates many usability improvements, as well as extensions of the core language. The main changes include: - :ref:`Introduction <813PrimArrays>` of :ref:`primitive persistent arrays` in the core language, implemented using imperative persistent arrays. - Introduction of :ref:`definitional proof irrelevance <813UIP>` for the equality type defined in the SProp sort. - Cumulative record and inductive type declarations can now :ref:`specify <813VarianceDecl>` the variance of their universes. - Various bugfixes and uniformization of behavior with respect to the use of implicit arguments and the handling of existential variables in declarations, unification and tactics. - New warning for :ref:`unused variables <813UnusedVar>` in catch-all match branches that match multiple distinct patterns. - New :ref:`warning <813HintWarning>` for `Hint` commands outside sections without a locality attribute, whose goal is to eventually remove the fragile default behavior of importing hints only when using `Require`. The recommended fix is to declare hints as `export`, instead of the current default `global`, meaning that they are imported through `Require Import` only, not `Require`. See the following `rationale and guidelines `_ for details. - General support for :ref:`boolean attributes <813BooleanAttrs>`. - Many improvements to the handling of :ref:`notations <813Notations>`, including number notations, recursive notations and notations with bindings. A new algorithm chooses the most precise notation available to print an expression, which might introduce changes in printing behavior. - Tactic :ref:`improvements <813Tactics>` in :tacn:`lia` and its :tacn:`zify` preprocessing step, now supporting reasoning on boolean operators such as :g:`Z.leb` and supporting primitive integers :g:`Int63`. - Typing flags can now be specified :ref:`per-constant / inductive <813TypingFlags>`. - Improvements to the reference manual including updated syntax descriptions that match Coq's grammar in several chapters, and splitting parts of the tactics chapter to independent sections. See the `Changes in 8.13+beta1`_ section and following sections for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's documentation is available at https://coq.github.io/doc/v8.13/refman (reference manual), and https://coq.github.io/doc/v8.13/stdlib (documentation of the standard library). Developer documentation of the ML API is available at https://coq.github.io/doc/v8.13/api. Maxime DΓ©nΓ¨s, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. Our current 32 maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Olivier Laurent, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia and ThΓ©o Zimmermann. The 51 contributors to this version are Reynald Affeldt, Tanaka Akira, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, ClΓ©ment Blaudeau, Martin Bodin, Ali Caglayan, Tej Chajed, Cyril Cohen, Julien Coolen, Matthew Dempsky, Maxime DΓ©nΓ¨s, Andres Erbsen, Jim Fehrle, Emilio JesΓΊs Gallego Arias, Attila GΓ‘spΓ‘r, Paolo G. Giarrusso, GaΓ«tan Gilbert, Jason Gross, Benjamin GrΓ©goire, Hugo Herbelin, Wolf Honore, Jasper Hugunin, Ignat Insarov, Ralf Jung, Fabian Kunze, Vincent Laporte, Olivier Laurent, Larry D. Lee Jr, Thomas Letan, Yishuai Li, James Lottes, Jean-Christophe LΓ©chenet, Kenji Maillard, Erik Martin-Dorel, Yusuke Matsushita, Guillaume Melquiond, Carl Patenaude-Poulin, ClΓ©ment Pit-Claudel, Pierre-Marie PΓ©drot, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Anton Trunov, Edward Wang, Li-yao Xia, Beta Ziliani and ThΓ©o Zimmermann. The Coq community at large helped improve the design of this new version via the GitHub issue and pull request system, the Coq development mailing list coqdev@inria.fr, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the `Coq Zulip chat `_. Version 8.13's development spanned 5 months from the release of Coq 8.12.0. Enrico Tassi and Maxime DΓ©nΓ¨s are the release managers of Coq 8.13. This release is the result of 400 merged PRs, closing ~100 issues. | Nantes, November 2020, | Matthieu Sozeau for the Coq development team | Changes in 8.13+beta1 ~~~~~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ .. _813UIP: - **Added:** Definitional UIP, only when :flag:`Definitional UIP` is enabled. This models definitional uniqueness of identity proofs for the equality type in SProp. It is deactivated by default as it can lead to non-termination in combination with impredicativity. Use of this flag is also printed by :cmd:`Print Assumptions`. See documentation of the flag for details (`#10390 `_, by GaΓ«tan Gilbert). .. _813PrimArrays: - **Added:** Built-in support for persistent arrays, which expose a functional interface but are implemented using an imperative data structure, for better performance (`#11604 `_, by Maxime DΓ©nΓ¨s and Benjamin GrΓ©goire, with help from GaΓ«tan Gilbert). Primitive arrays are irrelevant in their single polymorphic universe (same as a polymorphic cumulative list inductive would be) (`#13356 `_, fixes `#13354 `_, by GaΓ«tan Gilbert). - **Fixed:** A loss of definitional equality for declarations obtained through :cmd:`Include` when entering the scope of a :cmd:`Module` or :cmd:`Module Type` was causing :cmd:`Search` not to see the included declarations (`#12537 `_, fixes `#12525 `_ and `#12647 `_, by Hugo Herbelin). - **Fixed:** Fix an incompleteness in the typechecking of `match` for cumulative inductive types. This could result in breaking subject reduction (`#13501 `_, fixes `#13495 `_, by Matthieu Sozeau). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _813BooleanAttrs: - **Changed:** :term:`Boolean attributes ` are now specified using key/value pairs, that is to say :n:`@ident__attr{? = {| yes | no } }`. If the value is missing, the default is :n:`yes`. The old syntax is still supported, but produces the ``deprecated-attribute-syntax`` warning. Deprecated attributes are ``universes(monomorphic)``, ``universes(notemplate)`` and ``universes(noncumulative)``, which are respectively replaced by :attr:`universes(polymorphic=no) `, :attr:`universes(template=no) ` and :attr:`universes(cumulative=no) `. Attributes :attr:`program` and :attr:`canonical` are also affected, with the syntax :n:`@ident__attr(false)` being deprecated in favor of :n:`@ident__attr=no` (`#13312 `_, by Emilio Jesus Gallego Arias). - **Changed:** Heuristics for universe minimization to :g:`Set`: also use constraints ``Prop <= i`` (`#10331 `_, by GaΓ«tan Gilbert with help from Maxime DΓ©nΓ¨s and Matthieu Sozeau, fixes `#12414 `_). - **Changed:** The type given to :cmd:`Instance` is no longer automatically generalized over unbound and :ref:`generalizable ` variables. Use ``Instance : `{type}`` instead of :n:`Instance : @type` to get the old behavior, or enable the compatibility flag ``Instance Generalized Output`` (`#13188 `_, fixes `#6042 `_, by GaΓ«tan Gilbert). - **Changed:** Tweaked the algorithm giving default names to arguments. Should reduce the frequency that argument names get an unexpected suffix. Also makes :flag:`Mangle Names` not mess up argument names (`#12756 `_, fixes `#12001 `_ and `#6785 `_, by Jasper Hugunin). - **Removed:** Undocumented and experimental forward class hint feature ``:>>``. Use ``:>`` (see :n:`@of_type`) instead (`#13106 `_, by Pierre-Marie PΓ©drot). .. _813VarianceDecl: - **Added:** Commands :cmd:`Inductive`, :cmd:`Record` and synonyms now support syntax `Inductive foo@{=i +j *k l}` to specify variance information for their universes (in :ref:`Cumulative ` mode) (`#12653 `_, by GaΓ«tan Gilbert). .. _813UnusedVar: - **Added:** Warning on unused variables in pattern-matching branches of :n:`match` serving as catch-all branches for at least two distinct patterns (`#12768 `_, fixes `#12762 `_, by Hugo Herbelin). - **Added:** Definition and (Co)Fixpoint now support the :attr:`using` attribute. It has the same effect as :cmd:`Proof using`, which is only available in interactive mode (`#13183 `_, by Enrico Tassi). .. _813TypingFlags: - **Added:** Typing flags can now be specified per-constant / inductive, this allows to fine-grain specify them from plugins or attributes. See :ref:`controlling-typing-flags` for details on attribute syntax (`#12586 `_, by Emilio Jesus Gallego Arias). - **Added:** Inference of return predicate of a :g:`match` by inversion takes sort elimination constraints into account (`#13290 `_, grants `#13278 `_, by Hugo Herbelin). - **Fixed:** Implicit arguments taken into account in defined fields of a record type declaration (`#13166 `_, fixes `#13165 `_, by Hugo Herbelin). - **Fixed:** Allow use of typeclass inference for the return predicate of a :n:`match` (was deactivated in versions 8.10 to 8.12, `#13217 `_, fixes `#13216 `_, by Hugo Herbelin). - **Fixed:** A case of unification raising an anomaly IllTypedInstance (`#13376 `_, fixes `#13266 `_, by Hugo Herbelin). - **Fixed:** Using :n:`{wf ...}` in local fixpoints is an error, not an anomaly (`#13383 `_, fixes `#11816 `_, by Hugo Herbelin). - **Fixed:** Issue when two expressions involving different projections and one is primitive need to be unified (`#13386 `_, fixes `#9971 `_, by Hugo Herbelin). - **Fixed:** A bug producing ill-typed instances of existential variables when let-ins interleaved with assumptions (`#13387 `_, fixes `#12348 `_, by Hugo Herbelin). .. _813Notations: Notations ^^^^^^^^^ - **Changed:** In notations (except in custom entries), the misleading :n:`@syntax_modifier` :n:`@ident ident` (which accepted either an identifier or a :g:`_`) is deprecated and should be replaced by :n:`@ident name`. If the intent was really to only parse identifiers, this will eventually become possible, but only as of Coq 8.15. In custom entries, the meaning of :n:`@ident ident` is silently changed from parsing identifiers or :g:`_` to parsing only identifiers without warning, but this presumably affects only rare, recent and relatively experimental code (`#11841 `_, fixes `#9514 `_, by Hugo Herbelin). - **Changed:** Improved support for notations/abbreviations with mixed terms and patterns (such as the forcing modality) (`#12099 `_, by Hugo Herbelin). - **Changed** Rational and real constants are parsed differently. The exponent is now encoded separately from the fractional part using ``Z.pow_pos``. This way, parsing large exponents can no longer blow up and constants are printed in a form closer to the one in which they were parsed (i.e., ``102e-2`` is reprinted as such and not ``1.02``) (`#12218 `_, by Pierre Roux). - **Changed:** Scope information is propagated in indirect applications to a reference prefixed with :g:`@`; this covers for instance the case :g:`r.(@p) t` where scope information from :g:`p` is now taken into account for interpreting :g:`t` (`#12685 `_, by Hugo Herbelin). - **Changed:** New model for ``only parsing`` and ``only printing`` notations with support for at most one parsing-and-printing or only-parsing notation per notation and scope, but an arbitrary number of only-printing notations (`#12950 `_, fixes `#4738 `_ and `#9682 `_ and part 2 of `#12908 `_, by Hugo Herbelin). - **Changed:** Redeclaring a notation also reactivates its printing rule; in particular a second :cmd:`Import` of the same module reactivates the printing rules declared in this module. In theory, this leads to changes in behavior for printing. However, this is mitigated in general by the adoption in `#12986 `_ of a priority given to notations which match a larger part of the term to print (`#12984 `_, fixes `#7443 `_ and `#10824 `_, by Hugo Herbelin). - **Changed:** Use of notations for printing now gives preference to notations which match a larger part of the term to abbreviate (`#12986 `_, by Hugo Herbelin). - **Removed** OCaml parser and printer for real constants have been removed. Real constants are now handled with proven Coq code (`#12218 `_, by Pierre Roux). - **Deprecated** ``Numeral.v`` is deprecated, please use ``Number.v`` instead (`#12218 `_, by Pierre Roux). - **Deprecated:** `Numeral Notation`, please use :cmd:`Number Notation` instead (`#12979 `_, by Pierre Roux). - **Added:** ``Printing Float`` flag to print primitive floats as hexadecimal instead of decimal values. This is included in the :flag:`Printing All` flag (`#11986 `_, by Pierre Roux). - **Added:** :ref:`Number Notation ` and :ref:`String Notation ` commands now support parameterized inductive and non-inductive types (`#12218 `_, fixes `#12035 `_, by Pierre Roux, review by Jason Gross and Jim Fehrle for the reference manual). - **Added:** Added support for encoding notations of the form :g:`x βͺ― y βͺ― .. βͺ― z βͺ― t`. This feature is considered experimental (`#12765 `_, by Hugo Herbelin). - **Added:** The :n:`@binder` entry of :cmd:`Notation` can now be used in notations expecting a single (non-recursive) binder (`#13265 `_, by Hugo Herbelin, see section :ref:`notations-and-binders` of the reference manual). - **Fixed:** Issues in the presence of notations recursively referring to another applicative notations, such as missing scope propagation, or failure to use a notation for printing (`#12960 `_, fixes `#9403 `_ and `#10803 `_, by Hugo Herbelin). - **Fixed:** Capture the names of global references by binders in the presence of notations for binders (`#12965 `_, fixes `#9569 `_, by Hugo Herbelin). - **Fixed:** Preventing notations for constructors to involve binders (`#13092 `_, fixes `#13078 `_, by Hugo Herbelin). - **Fixed:** Notations understand universe names without getting confused by different imported modules between declaration and use locations (`#13415 `_, fixes `#13303 `_, by GaΓ«tan Gilbert). .. _813Tactics: Tactics ^^^^^^^ - **Changed:** In :tacn:`refine`, new existential variables unified with existing ones are no longer considered as fresh. The behavior of :tacn:`simple refine ` no longer depends on the orientation of evar-evar unification problems, and new existential variables are always turned into (unshelved) goals. This can break compatibility in some cases (`#7825 `_, by Matthieu Sozeau, with help from Maxime DΓ©nΓ¨s, review by Pierre-Marie PΓ©drot and Enrico Tassi, fixes `#4095 `_ and `#4413 `_). - **Changed:** Giving an empty list of occurrences after :n:`in` in tactics is no longer permitted. Omitting the :n:`in` gives the same behavior (`#13237 `_, fixes `#13235 `_, by Hugo Herbelin). - **Removed:** :n:`at @occs_nums` clauses in tactics such as :tacn:`unfold` no longer allow negative values. A "-" before the list (for set complement) is still supported. Ex: "at -1 -2" is no longer supported but "at -1 2" is (`#13403 `_, by Jim Fehrle). - **Removed:** A number of tactics that formerly accepted negative numbers as parameters now give syntax errors for negative values. These include {e}constructor, do, timeout, 9 {e}auto tactics and psatz* (`#13417 `_, by Jim Fehrle). - **Removed:** The deprecated and undocumented `prolog` tactic was removed (`#12399 `_, by Pierre-Marie PΓ©drot). - **Removed:** `info` tactic that was deprecated in 8.5 (`#12423 `_, by Jim Fehrle). - **Deprecated:** Undocumented :n:`eauto @nat_or_var @nat_or_var` syntax in favor of new `bfs eauto`. Also deprecated 2-integer syntax for :tacn:`debug eauto` and :tacn:`info_eauto` (Use `bfs eauto` with the :flag:`Info Eauto` or :flag:`Debug Eauto` flags instead.) (`#13381 `_, by Jim Fehrle). - **Added:** :tacn:`lia` is extended to deal with boolean operators e.g. `andb` or `Z.leb` (as `lia` gets more powerful, this may break proof scripts relying on `lia` failure, `#11906 `_, by FrΓ©dΓ©ric Besson). - **Added:** :tacn:`apply … in ` supports several hypotheses (`#12246 `_, by Hugo Herbelin; grants `#9816 `_). - **Added:** The :tacn:`zify` tactic can now be extended by redefining the `zify_pre_hook` tactic. (`#12552 `_, by Kazuhiko Sakaguchi). - **Added:** The :tacn:`zify` tactic provides support for primitive integers (module :g:`ZifyInt63`) (`#12648 `_, by FrΓ©dΓ©ric Besson). - **Fixed:** Avoid exposing an internal name of the form :n:`_tmp` when applying the :n:`_` introduction pattern which would break a dependency (`#13337 `_, fixes `#13336 `_, by Hugo Herbelin). - **Fixed:** The case of tactics, such as :tacn:`eapply`, producing existential variables under binders with an ill-formed instance (`#13373 `_, fixes `#13363 `_, by Hugo Herbelin). Tactic language ^^^^^^^^^^^^^^^ - **Added:** An if-then-else syntax to Ltac2 (`#13232 `_, fixes `#10110 `_, by Pierre-Marie PΓ©drot). - **Fixed:** Printing of the quotation qualifiers when printing :g:`Ltac` functions (`#13028 `_, fixes `#9716 `_ and `#13004 `_, by Hugo Herbelin). SSReflect ^^^^^^^^^ - **Added:** SSReflect intro pattern ltac views ``/[dup]``, ``/[swap]`` and ``/[apply]`` (`#13317 `_, by Cyril Cohen). - **Fixed:** Working around a bug of interaction between + and /(ltac:(...)) cf `#13458 `_ (`#13459 `_, by Cyril Cohen). Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** Drop prefixes from grammar non-terminal names, e.g. "constr:global" -> "global", "Prim.name" -> "name". Visible in the output of :cmd:`Print Grammar` and :cmd:`Print Custom Grammar` (`#13096 `_, by Jim Fehrle). - **Changed:** When declaring arbitrary terms as hints, unsolved evars are not abstracted implicitly anymore and instead raise an error (`#13139 `_, by Pierre-Marie PΓ©drot). - **Removed:** In the :cmd:`Extraction Language` command, remove `Ocaml` as a valid value. Use `OCaml` instead. This was deprecated in Coq 8.8, `#6261 `_ (`#13016 `_, by Jim Fehrle). .. _813HintWarning: - **Deprecated:** Hint locality currently defaults to :attr:`local` in a section and :attr:`global` otherwise, but this will change in a future release. Hints added outside of sections without an explicit locality now generate a deprecation warning. We recommend using :attr:`export` where possible (`#13384 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** ``Grab Existential Variables`` and ``Existential`` commands (`#12516 `_, by Maxime DΓ©nΓ¨s). - **Added:** The :attr:`export` locality can now be used for all Hint commands, including :cmd:`Hint Cut`, :cmd:`Hint Mode`, :cmd:`Hint Transparent` / :cmd:`Opaque ` and :cmd:`Remove Hints` (`#13388 `_, by Pierre-Marie PΓ©drot). - **Added:** Support for automatic insertion of coercions in :cmd:`Search` patterns. Additionally, head patterns are now automatically interpreted as types (`#13255 `_, fixes `#13244 `_, by Hugo Herbelin). - **Added:** The :cmd:`Proof using` command can now be used without loading the Ltac plugin (`-noinit` mode) (`#13339 `_, by ThΓ©o Zimmermann). - **Added:** Clarify in the documentation that ``Add ML Path`` is not exported to compiled files (`#13345 `_, fixes `#13344 `_, by Hugo Herbelin). Tools ^^^^^ - **Changed:** Option `-native-compiler` of the configure script now impacts the default value of the `-native-compiler` option of coqc. The `-native-compiler` option of the configure script supports a new `ondemand` value, which becomes the default, thus preserving the previous default behavior. The stdlib is still precompiled when configuring with `-native-compiler yes`. It is not precompiled otherwise. This an implementation of point 2 of `CEP #48 `_ (`#13352 `_, by Pierre Roux). - **Changed:** Added the ability for coq_makefile to directly set the installation folders, through the `COQLIBINSTALL` and `COQDOCINSTALL` variables. See :ref:`rocqmakefilelocal` (`#12389 `_, by Martin Bodin, review of Enrico Tassi). - **Removed:** The option ``-I`` of coqchk was removed (it was deprecated in Coq 8.8) (`#12613 `_, by GaΓ«tan Gilbert). - **Fixed:** ``coqchk`` no longer reports names from inner modules of opaque modules as axioms (`#12862 `_, fixes `#12845 `_, by Jason Gross). CoqIDE ^^^^^^ - **Added:** Support showing diffs for :cmd:`Show Proof` in CoqIDE from the :n:`View` menu. See :ref:`showing_proof_diffs` (`#12874 `_, by Jim Fehrle and Enrico Tassi) - **Added:** Support for flag :flag:`Printing Goal Names` in View menu (`#13145 `_, by Hugo Herbelin). Standard library ^^^^^^^^^^^^^^^^ - **Changed:** In the reals theory changed the epsilon in the definition of the modulus of convergence for CReal from 1/n (n in positive) to 2^z (z in Z) so that a precision coarser than one is possible. Also added an upper bound to CReal to enable more efficient computations (`#12186 `_, by Michael Soegtrop). - **Changed:** Int63 notations now match up with the rest of the standard library: :g:`a \% m`, :g:`m == n`, :g:`m < n`, :g:`m <= n`, and :g:`m ≀ n` have been replaced with :g:`a mod m`, :g:`m =? n`, :g:`m `_, fixes `#12454 `_, by Jason Gross). - **Changed:** PrimFloat notations now match up with the rest of the standard library: :g:`m == n`, :g:`m < n`, and :g:`m <= n` have been replaced with :g:`m =? n`, :g:`m `_, fixes `#12454 `_, by Jason Gross). - **Changed:** the sort of cyclic numbers from Type to Set. For backward compatibility, a dynamic sort was defined in the 3 packages bignums, coqprime and color. See for example commit 6f62bda in bignums (`#12801 `_, by Vincent Semeria). - **Changed:** ``Require Import Coq.nsatz.NsatzTactic`` now allows using :tacn:`nsatz` with `Z` and `Q` without having to supply instances or using ``Require Import Coq.nsatz.Nsatz``, which transitively requires unneeded files declaring axioms used in the reals (`#12861 `_, fixes `#12860 `_, by Jason Gross). - **Deprecated:** ``prod_curry`` and ``prod_uncurry``, in favor of ``uncurry`` and ``curry`` (`#12716 `_, by Yishuai Li). - **Added:** New lemmas about ``repeat`` in ``List`` and ``Permutation``: ``repeat_app``, ``repeat_eq_app``, ``repeat_eq_cons``, ``repeat_eq_elt``, ``Forall_eq_repeat``, ``Permutation_repeat`` (`#12799 `_, by Olivier Laurent). - **Added:** Extend some list lemmas to both directions: `app_inj_tail_iff`, `app_inv_head_iff`, `app_inv_tail_iff` (`#12094 `_, fixes `#12093 `_, by Edward Wang). - **Added:** ``Decidable`` instance for negation (`#12420 `_, by Yishuai Li). - **Fixed:** `Coq.Program.Wf.Fix_F_inv` and `Coq.Program.Wf.Fix_eq` are now axiom-free, and no longer assuming proof irrelevance (`#13365 `_, by Li-yao Xia). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** When compiled with OCaml >= 4.10.0, Coq will use the new best-fit GC policy, which should provide some performance benefits. Coq's policy is optimized for speed, but could increase memory consumption in some cases. You are welcome to tune it using the ``OCAMLRUNPARAM`` variable and report back on good settings so we can improve the defaults (`#13040 `_, fixes `#11277 `_, by Emilio Jesus Gallego Arias). - **Changed:** Coq now uses the `zarith `_ library, based on GNU's gmp instead of ``num`` which is deprecated upstream. The custom ``bigint`` module is no longer provided (`#11742 `_, `#13007 `_, by Emilio Jesus Gallego Arias and Vicent Laporte, with help from FrΓ©dΓ©ric Besson). Changes in 8.13.0 ~~~~~~~~~~~~~~~~~ Commands and options ^^^^^^^^^^^^^^^^^^^^ - **Changed:** The warning `custom-entry-overriden` has been renamed to `custom-entry-overridden` (with two d's) (`#13556 `_, by Simon Friis Vindum). Changes in 8.13.1 ~~~~~~~~~~~~~~~~~ Kernel ^^^^^^ - **Fixed:** Fix arities of VM opcodes for some floating-point operations that could cause memory corruption (`#13867 `_, by Guillaume Melquiond). CoqIDE ^^^^^^ - **Added:** Option ``-v`` and ``--version`` to CoqIDE (`#13870 `_, by Guillaume Melquiond). Changes in 8.13.2 ~~~~~~~~~~~~~~~~~ Kernel ^^^^^^ - **Fixed:** Crash when using :tacn:`vm_compute` on an irreducible ``PArray.set`` (`#14005 `_, fixes `#13998 `_, by Guillaume Melquiond). - **Fixed:** Never store persistent arrays as VM / native structured values. This could be used to make vo marshalling crash, and probably breaking some other invariants of the kernel (`#14007 `_, fixes `#14006 `_, by Pierre-Marie PΓ©drot). Tactic language ^^^^^^^^^^^^^^^^ - **Fixed:** Ltac2 ``Array.init`` no longer incurs exponential overhead when used recursively (`#14012 `_, fixes `#14011 `_, by Jason Gross). Version 8.12 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.12 integrates many usability improvements, in particular with respect to notations, scopes and implicit arguments, along with many bug fixes and major improvements to the reference manual. The main changes include: - New :ref:`binder notation<812Implicit>` for non-maximal implicit arguments using :g:`[ ]` allowing to set and see the implicit status of arguments immediately. - New notation :g:`Inductive I A | x : s := ...` to distinguish the :ref:`uniform<812Uniform>` from the non-uniform parameters in inductive definitions. - More robust and expressive treatment of :ref:`implicit inductive<812ImplicitInductive>` parameters in inductive declarations. - Improvements in the treatment of implicit arguments and partially applied constants in :ref:`notations<812Notations>`, parsing of hexadecimal number notation and better handling of scopes and coercions for printing. - A correct and efficient :ref:`coercion coherence<812Coercions>` checking algorithm, avoiding spurious or duplicate warnings. - An improved :cmd:`Search` :ref:`command<812Search>` which accepts complex queries. Note that this takes precedence over the now deprecated :ref:`ssreflect search<812SSRSearch>`. - Many additions and improvements of the :ref:`standard library<812Stdlib>`. - Improvements to the :ref:`reference manual<812Refman>` include a more logical organization of chapters along with updated syntax descriptions that match Coq's grammar in most but not all chapters. Additionally, the `omega` tactic is deprecated in this version of Coq, and we recommend users to switch to :tacn:`lia` in new proof scripts. See the `Changes in 8.12+beta1`_ section and following sections for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's documentation is available at https://coq.github.io/doc/v8.12/refman (reference manual), and https://coq.github.io/doc/v8.12/stdlib (documentation of the standard library). Developer documentation of the ML API is available at https://coq.github.io/doc/v8.12/api. Maxime DΓ©nΓ¨s, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Erik Martin-Dorel has maintained the `Coq Docker images `_ that are used in many Coq projects for continuous integration. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. Previously, most components of Coq had a single principal maintainer. This was changed in 8.12 (`#11295 `_) so that every component now has a team of maintainers, who are in charge of reviewing and merging incoming pull requests. This gave us a chance to significantly expand the pool of maintainters and provide faster feedback to contributors. Special thanks to all our maintainers! Our current 31 maintainers are Yves Bertot, FrΓ©dΓ©ric Besson, Tej Chajed, Cyril Cohen, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Georges Gonthier, Benjamin GrΓ©goire, Jason Gross, Hugo Herbelin, Vincent Laporte, Assia Mahboubi, Kenji Maillard, Guillaume Melquiond, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Arnaud Spiwack, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, Li-yao Xia, ThΓ©o Zimmermann The 59 contributors to this version are Abhishek Anand, Yves Bertot, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, Simon Boulier, Quentin Carbonneaux, Tej Chajed, Arthur CharguΓ©raud, Cyril Cohen, Pierre Courtieu, Matthew Dempsky, Maxime DΓ©nΓ¨s, Andres Erbsen, Erika (@rrika), Nikita Eshkeev, Jim Fehrle, @formalize, Emilio JesΓΊs Gallego Arias, Paolo G. Giarrusso, GaΓ«tan Gilbert, Jason Gross, Samuel Gruetter, Attila GΓ‘spΓ‘r, Hugo Herbelin, Jan-Oliver Kaiser, Robbert Krebbers, Vincent Laporte, Olivier Laurent, Xavier Leroy, Thomas Letan, Yishuai Li, Kenji Maillard, Erik Martin-Dorel, Guillaume Melquiond, Ike Mulder, Guillaume Munch-Maccagnoni, Antonio Nikishaev, Karl Palmskog, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Ramkumar Ramachandra, Lars Rasmusson, Daniel de Rauglaudre, Talia Ringer, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, @scinart, Kartik Singhal, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Ralf Treinen, Anton Trunov, Bernhard M. Wiedemann, Li-yao Xia, Nickolai Zeldovich and ThΓ©o Zimmermann. Many power users helped to improve the design of this new version via the GitHub issue and pull request system, the Coq development mailing list coqdev@inria.fr, the coq-club@inria.fr mailing list, the `Discourse forum `_ and the new `Coq Zulip chat `_ (thanks to Cyril Cohen for organizing the move from Gitter). Version 8.12's development spanned 6 months from the release of Coq 8.11.0. Emilio Jesus Gallego Arias and ThΓ©o Zimmermann are the release managers of Coq 8.12. This release is the result of ~500 PRs merged, closing ~100 issues. | Nantes, June 2020, | Matthieu Sozeau for the Coq development team | Changes in 8.12+beta1 ~~~~~~~~~~~~~~~~~~~~~ .. contents:: :local: Kernel ^^^^^^ - **Fixed:** Specification of :n:`PrimFloat.leb` which made :n:`(x <= y)%float` true for any non-NaN :n:`x` and :n:`y` (`#12484 `_, fixes `#12483 `_, by Pierre Roux). Specification language, type inference ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** The deprecation warning raised since Coq 8.10 when a trailing implicit is declared to be non-maximally inserted (with the command :cmd:`Arguments`) has been turned into an error (`#11368 `_, by SimonBoulier). - **Changed:** Typeclass resolution, accessible through :tacn:`typeclasses eauto`, now suspends constraints according to their modes instead of failing. If a typeclass constraint does not match any of the declared modes for its class, the constraint is postponed, and the proof search continues on other goals. Proof search does a fixed point computation to try to solve them at a later stage of resolution. It does not fail if there remain only stuck constraints at the end of resolution. This makes typeclasses with declared modes more robust with respect to the order of resolution (`#10858 `_, fixes `#9058 `_, by Matthieu Sozeau). - **Added:** Warn when manual implicit arguments are used in unexpected positions of a term (e.g. in `Check id (forall {x}, x)`) or when an implicit argument name is shadowed (e.g. in `Check fun f : forall {x:nat} {x}, nat => f`) (`#10202 `_, by Hugo Herbelin). - **Added:** :cmd:`Arguments` now supports setting implicit an anonymous argument, as e.g. in `Arguments id {A} {_}` (`#11098 `_, by Hugo Herbelin, fixes `#4696 `_, `#5173 `_, `#9098 `_). .. _812Implicit: - **Added:** Syntax for non-maximal implicit arguments in definitions and terms using square brackets. The syntax is ``[x : A]``, ``[x]``, ```[A]`` to be consistent with the command :cmd:`Arguments` (`#11235 `_, by Simon Boulier). - **Added:** :cmd:`Implicit Types` are now taken into account for printing. To inhibit it, unset the :flag:`Printing Use Implicit Types` flag (`#11261 `_, by Hugo Herbelin, granting `#10366 `_). .. _812Uniform: - **Added:** New syntax :cmd:`Inductive` :n:`@ident {* @binder } | {* @binder } := ...` to specify which parameters of an inductive type are uniform. See :ref:`parametrized-inductive-types` (`#11600 `_, by GaΓ«tan Gilbert). - **Added:** Warn when using :cmd:`Fixpoint` or :cmd:`CoFixpoint` for definitions which are not recursive (`#12121 `_, by Hugo Herbelin). .. _812ImplicitInductive: - **Fixed:** More robust and expressive treatment of implicit inductive parameters in inductive declarations (`#11579 `_, by Maxime DΓ©nΓ¨s, GaΓ«tan Gilbert and Jasper Hugunin; fixes `#7253 `_ and `#11585 `_). - **Fixed:** Anomaly which could be raised when printing binders with implicit types (`#12323 `_, by Hugo Herbelin; fixes `#12322 `_). - **Fixed:** Case of an anomaly in trying to infer the return clause of an ill-typed :g:`match` (`#12422 `_, fixes `#12418 `_, by Hugo Herbelin). .. _812Notations: Notations ^^^^^^^^^ - **Changed:** Notation scopes are now always inherited in notations binding a partially applied constant, including for notations binding an expression of the form :n:`@@qualid`. The latter was not the case beforehand (part of `#11120 `_). - **Changed:** The printing algorithm now interleaves search for notations and removal of coercions (`#11172 `_, by Hugo Herbelin). - **Changed:** Nicer printing for decimal constants in R and Q. 1.5 is now printed 1.5 rather than 15e-1 (`#11848 `_, by Pierre Roux). - **Removed:** deprecated ``compat`` modifier of :cmd:`Notation` and :cmd:`Infix` commands. Use the :attr:`deprecated` attribute instead (`#11113 `_, by ThΓ©o Zimmermann, with help from Jason Gross). - **Deprecated:** Numeral Notation on ``Decimal.uint``, ``Decimal.int`` and ``Decimal.decimal`` are replaced respectively by numeral notations on ``Numeral.uint``, ``Numeral.int`` and ``Numeral.numeral`` (`#11948 `_, by Pierre Roux). - **Added:** Notations declared with the ``where`` clause in the declaration of inductive types, coinductive types, record fields, fixpoints and cofixpoints now support the ``only parsing`` modifier (`#11602 `_, by Hugo Herbelin). - **Added:** :flag:`Printing Parentheses` flag to print parentheses even when implied by associativity or precedence (`#11650 `_, by Hugo Herbelin and Abhishek Anand). - **Added:** Numeral notations now parse hexadecimal constants such as ``0x2a`` or ``0xb.2ap-2``. Parsers added for :g:`nat`, :g:`positive`, :g:`Z`, :g:`N`, :g:`Q`, :g:`R`, primitive integers and primitive floats (`#11948 `_, by Pierre Roux). - **Added:** Abbreviations support arguments occurring both in term and binder position (`#8808 `_, by Hugo Herbelin). - **Fixed:** Different interpretations in different scopes of the same notation string can now be associated with different printing formats (`#10832 `_, by Hugo Herbelin, fixes `#6092 `_ and `#7766 `_). - **Fixed:** Parsing and printing consistently handle inheritance of implicit arguments in notations. With the exception of notations of the form :n:`Notation @string := @@qualid` and :n:`Notation @ident := @@qualid` which inhibit implicit arguments, all notations binding a partially applied constant, as e.g. in :n:`Notation @string := (@qualid {+ @arg })`, or :n:`Notation @string := (@@qualid {+ @arg })`, or :n:`Notation @ident := (@qualid {+ @arg })`, or :n:`Notation @ident := (@@qualid {+ @arg })`, inherit the remaining implicit arguments (`#11120 `_, by Hugo Herbelin, fixing `#4690 `_ and `#11091 `_). - **Fixed:** Notations in ``only printing`` mode do not uselessly reserve parsing keywords (`#11590 `_, by Hugo Herbelin, fixes `#9741 `_). - **Fixed:** Numeral Notations now play better with multiple scopes for the same inductive type. Previously, when multiple numeral notations were defined for the same inductive, only the last one was considered for printing. Now, among the notations that are usable for printing and either have a scope delimiter or are open, the selection is made according to the order of open scopes, or according to the last defined notation if no appropriate scope is open (`#12163 `_, fixes `#12159 `_, by Pierre Roux, review by Hugo Herbelin and Jason Gross). Tactics ^^^^^^^ - **Changed:** The :tacn:`rapply` tactic in :g:`Coq.Program.Tactics` now handles arbitrary numbers of underscores and takes in a :g:`uconstr`. In rare cases where users were relying on :tacn:`rapply` inserting exactly 15 underscores and no more, due to the lemma having a completely unspecified codomain (and thus allowing for any number of underscores), the tactic will now loop instead (`#10760 `_, by Jason Gross). - **Changed:** The :g:`auto with zarith` tactic and variations (including :tacn:`intuition`) may now call :tacn:`lia` instead of `omega` (when the `Omega` module is loaded); more goals may be automatically solved, fewer section variables will be captured spuriously (`#11018 `_, by Vincent Laporte). - **Changed:** The new :flag:`NativeCompute Timing` flag causes calls to :tacn:`native_compute` (as well as kernel calls to the native compiler) to emit separate timing information about conversion to native code, compilation, execution, and reification. It replaces the timing information previously emitted when the `-debug` command-line flag was set, and allows more fine-grained timing of the native compiler (`#11025 `_, by Jason Gross). Additionally, the timing information now uses real time rather than user time (fixes `#11962 `_, `#11963 `_, by Jason Gross) - **Changed:** Improve the efficiency of `PreOmega.elim_let` using an iterator implemented in OCaml (`#11370 `_, by FrΓ©dΓ©ric Besson). - **Changed:** Improve the efficiency of :tacn:`zify` by rewriting the remaining Ltac code in OCaml (`#11429 `_, by FrΓ©dΓ©ric Besson). - **Changed:** Backtrace information for tactics has been improved (`#11755 `_, by Emilio Jesus Gallego Arias). - **Changed:** The default tactic used by :g:`firstorder` is :g:`auto with core` instead of :g:`auto with *`; see :ref:`decisionprocedures` for details; old behavior can be reset by using the `-compat 8.12` command-line flag; to ease the migration of legacy code, the default solver can be set to `debug auto with *` with `Set Firstorder Solver debug auto with *` (`#11760 `_, by Vincent Laporte). - **Changed:** :tacn:`autounfold` no longer fails when the :cmd:`Opaque` command is used on constants in the hint databases (`#11883 `_, by Attila GΓ‘spΓ‘r). - **Changed:** Tactics with qualified name of the form ``Coq.Init.Notations`` are now qualified with prefix ``Coq.Init.Ltac``; users of the ``-noinit`` option should now import ``Coq.Init.Ltac`` if they want to use Ltac (`#12023 `_, by Hugo Herbelin; minor source of incompatibilities). - **Changed:** Tactic :tacn:`subst` :n:`@ident` now fails over a section variable which is indirectly dependent in the goal; the incompatibility can generally be fixed by first clearing the hypotheses causing an indirect dependency, as reported by the error message, or by using :tacn:`rewrite` :n:`... in *` instead; similarly, :tacn:`subst` has no more effect on such variables (`#12146 `_, by Hugo Herbelin; fixes `#10812 `_ and `#12139 `_). - **Changed:** The check that :tacn:`unfold` arguments were indeed unfoldable has been moved to runtime (`#12256 `_, by Pierre-Marie PΓ©drot; fixes `#5764 `_, `#5159 `_, `#4925 `_ and `#11727 `_). - **Changed** When the tactic :tacn:`functional induction` :n:`c__1 c__2 ... c__n` is used with no parenthesis around :n:`c__1 c__2 ... c__n`, :n:`c__1 c__2 ... c__n` is now read as one single applicative term. In particular implicit arguments should be omitted. Rare source of incompatibility (`#12326 `_, by Pierre Courtieu). - **Changed:** When using :tacn:`exists` or :tacn:`eexists` with multiple arguments, the evaluation of arguments and applications of constructors are now interleaved. This improves unification in some cases (`#12366 `_, fixes `#12365 `_, by Attila GΓ‘spΓ‘r). - **Removed:** Undocumented ``omega with``. Using :tacn:`lia` is the recommended replacement, although the old semantics of ``omega with *`` can also be recovered with ``zify; omega`` (`#11288 `_, by Emilio Jesus Gallego Arias). - **Removed:** Deprecated syntax `_eqn` for :tacn:`destruct` and :tacn:`remember`. Use `eqn:` syntax instead (`#11877 `_, by Hugo Herbelin). - **Removed:** `at` clauses can no longer be used with :tacn:`autounfold`. Since they had no effect, it is safe to remove them (`#11883 `_, by Attila GΓ‘spΓ‘r). - **Deprecated:** The `omega` tactic is deprecated; use :tacn:`lia` from the :ref:`Micromega ` plugin instead (`#11976 `_, by Vincent Laporte). - **Added:** The :tacn:`zify` tactic is now aware of `Pos.pred_double`, `Pos.pred_N`, `Pos.of_nat`, `Pos.add_carry`, `Pos.pow`, `Pos.square`, `Z.pow`, `Z.double`, `Z.pred_double`, `Z.succ_double`, `Z.square`, `Z.div2`, and `Z.quot2`. Injections for internal definitions in module `ZifyBool` (`isZero` and `isLeZero`) are also added to help users to declare new :tacn:`zify` class instances using Micromega tactics (`#10998 `_, by Kazuhiko Sakaguchi). - **Added:** :cmd:`Show Lia Profile` prints some statistics about :tacn:`lia` calls (`#11474 `_, by FrΓ©dΓ©ric Besson). - **Added:** Syntax :tacn:`pose proof` :n:`(@ident:=@term)` as an alternative to :tacn:`pose proof` :n:`@term as @ident`, following the model of :tacn:`pose` :n:`(@ident:=@term)` (`#11522 `_, by Hugo Herbelin). - **Added:** New tactical :tacn:`with_strategy` which behaves like the command :cmd:`Strategy`, with effects local to the given tactic (`#12129 `_, by Jason Gross). - **Added:** The :tacn:`zify` tactic is now aware of `Nat.le`, `Nat.lt` and `Nat.eq` (`#12213 `_, by FrΓ©dΓ©ric Besson; fixes `#12210 `_). - **Fixed:** :tacn:`zify` now handles :g:`Z.pow_pos` by default. In Coq 8.11, this was the case only when loading module :g:`ZifyPow` because this triggered a regression of :tacn:`lia`. The regression is now fixed, and the module kept only for compatibility (`#11362 `_, fixes `#11191 `_, by FrΓ©dΓ©ric Besson). - **Fixed:** Efficiency regression of :tacn:`lia` (`#11474 `_, fixes `#11436 `_, by FrΓ©dΓ©ric Besson). - **Fixed:** The behavior of :tacn:`autounfold` no longer depends on the names of terms and modules (`#11883 `_, fixes `#7812 `_, by Attila GΓ‘spΓ‘r). - **Fixed:** Wrong type error in tactic :tacn:`functional induction` (`#12326 `_, by Pierre Courtieu, fixes `#11761 `_, reported by Lasse Blaauwbroek). Tactic language ^^^^^^^^^^^^^^^ - **Changed:** The "reference" tactic generic argument now accepts arbitrary variables of the goal context (`#12254 `_, by Pierre-Marie PΓ©drot). - **Added:** An array library for Ltac2 (as compatible as possible with OCaml standard library) (`#10343 `_, by Michael Soegtrop). - **Added:** The Ltac2 rebinding command :cmd:`Ltac2 Set` has been extended with the ability to give a name to the old value so as to be able to reuse it inside the new one (`#11503 `_, by Pierre-Marie PΓ©drot). - **Added:** Ltac2 notations for :tacn:`enough` and :tacn:`eenough` (`#11740 `_, by Michael Soegtrop). - **Added:** New Ltac2 function ``Fresh.Free.of_goal`` to return the list of names of declarations of the current goal; new Ltac2 function ``Fresh.in_goal`` to return a variable fresh in the current goal (`#11882 `_, by Hugo Herbelin). - **Added:** Ltac2 notations for reductions in terms: :n:`eval @red_expr in @term` (`#11981 `_, by Michael Soegtrop). - **Fixed:** The :flag:`Ltac Profiling` machinery now correctly handles backtracking into multi-success tactics. The call-counts of some tactics are unfortunately inflated by 1, as some tactics are implicitly implemented as :g:`tac + fail`, which has two entry-points rather than one (fixes `#12196 `_, `#12197 `_, by Jason Gross). SSReflect ^^^^^^^^^ .. _812SSRSearch: - **Changed:** The `Search (ssreflect)` command that used to be available when loading the `ssreflect` plugin has been moved to a separate plugin that needs to be loaded separately: `ssrsearch` (part of `#8855 `_, fixes `#12253 `_, by ThΓ©o Zimmermann). - **Deprecated:** `Search (ssreflect)` (available through `Require ssrsearch.`) in favor of the `headconcl:` clause of :cmd:`Search` (part of `#8855 `_, by ThΓ©o Zimmermann). Flags, options and attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** :term:`Legacy attributes ` can now be passed in any order (`#11665 `_, by ThΓ©o Zimmermann). - **Removed:** ``Typeclasses Axioms Are Instances`` flag, deprecated since 8.10. Use :cmd:`Declare Instance` for axioms which should be instances (`#11185 `_, by ThΓ©o Zimmermann). - **Removed:** Deprecated unsound compatibility ``Template Check`` flag that was introduced in 8.10 to help users gradually move their template polymorphic inductive type definitions outside sections (`#11546 `_, by Pierre-Marie PΓ©drot). - **Removed:** Deprecated ``Shrink Obligations`` flag (`#11828 `_, by Emilio Jesus Gallego Arias). - **Removed:** Unqualified ``polymorphic``, ``monomorphic``, ``template``, ``notemplate`` attributes (they were deprecated since Coq 8.10). Use :attr:`universes(polymorphic)`, ``universes(monomorphic)``, :attr:`universes(template)` and ``universes(notemplate)`` instead (`#11663 `_, by ThΓ©o Zimmermann). - **Deprecated:** `Hide Obligations` flag (`#11828 `_, by Emilio Jesus Gallego Arias). - **Added:** Handle the :attr:`local` attribute in :cmd:`Canonical Structure` declarations (`#11162 `_, by Enrico Tassi). - **Added:** New attributes supported when defining an inductive type :attr:`universes(cumulative)`, ``universes(noncumulative)`` and :attr:`private(matching)`, which correspond to legacy attributes ``Cumulative``, ``NonCumulative``, and the previously undocumented ``Private`` (`#11665 `_, by ThΓ©o Zimmermann). - **Added:** The :ref:`Hint ` commands now accept the :attr:`export` locality as an attribute, allowing to make import-scoped hints (`#11812 `_, by Pierre-Marie PΓ©drot). - **Added:** `Cumulative StrictProp` to control cumulativity of |SProp| (`#12034 `_, by GaΓ«tan Gilbert). Commands ^^^^^^^^ .. _812Coercions: - **Changed:** The :cmd:`Coercion` command has been improved to check the coherence of the inheritance graph. It checks whether a circular inheritance path of `C >-> C` is convertible with the identity function or not, then report it as an ambiguous path if it is not. The new mechanism does not report ambiguous paths that are redundant with others. For example, checking the ambiguity of `[f; g]` and `[f'; g]` is redundant with that of `[f]` and `[f']` thus will not be reported (`#11258 `_, by Kazuhiko Sakaguchi). - **Changed:** Several commands (:cmd:`Search`, :cmd:`About`, ...) now print the implicit arguments in brackets when printing types (`#11795 `_, by Simon Boulier). - **Changed:** The warning when using :cmd:`Require` inside a section moved from the ``deprecated`` category to the ``fragile`` category, because there is no plan to remove the functionality at this time (`#11972 `_, by GaΓ«tan Gilbert). - **Changed:** :cmd:`Redirect` now obeys the :opt:`Printing Width` and :opt:`Printing Depth` options (`#12358 `_, by Emilio Jesus Gallego Arias). - **Removed:** Recursive OCaml loadpaths are not supported anymore; the command ``Add Rec ML Path`` has been removed; ``Add ML Path`` is now the preferred one. We have also dropped support for the non-qualified version of the ``Add LoadPath`` command, that is to say, the ``Add LoadPath dir`` version; now, you must always specify a prefix now using ``Add Loadpath dir as Prefix`` (`#11618 `_, by Emilio Jesus Gallego Arias). - **Removed:** undocumented ``Chapter`` command. Use :cmd:`Section` instead (`#11746 `_, by ThΓ©o Zimmermann). - **Removed:** ``SearchAbout`` command that was deprecated since 8.5. Use :cmd:`Search` instead (`#11944 `_, by Jim Fehrle). - **Deprecated:** Declaration of arbitrary terms as hints. Global references are now preferred (`#7791 `_, by Pierre-Marie PΓ©drot). - **Deprecated:** `SearchHead` in favor of the new `headconcl:` clause of :cmd:`Search` (part of `#8855 `_, by ThΓ©o Zimmermann). - **Added:** :cmd:`Print Canonical Projections` can now take constants as arguments and prints only the unification rules that involve or are synthesized from the given constants (`#10747 `_, by Kazuhiko Sakaguchi). - **Added:** A section variable introduced with :cmd:`Let` can be declared as a :cmd:`Canonical Structure` (`#11164 `_, by Enrico Tassi). - **Added:** Support for universe bindings and universe contrainsts in :cmd:`Let` definitions (`#11534 `_, by ThΓ©o Zimmermann). .. _812Search: - **Added:** Support for new clauses `hyp:`, `headhyp:`, `concl:`, `headconcl:`, `head:` and `is:` in :cmd:`Search`. Support for complex search queries combining disjunctions, conjunctions and negations (`#8855 `_, by Hugo Herbelin, with ideas from Cyril Cohen and help from ThΓ©o Zimmermann). - **Fixed:** A printing bug in the presence of elimination principles with local definitions (`#12295 `_, by Hugo Herbelin; fixes `#12233 `_). - **Fixed:** Anomalies with :cmd:`Show Proof` (`#12296 `_, by Hugo Herbelin; fixes `#12234 `_). Tools ^^^^^ - **Changed:** Internal options and behavior of ``coqdep``. ``coqdep`` no longer works as a replacement for ``ocamldep``, thus ``.ml`` files are not supported as input. Also, several deprecated options have been removed: ``-w``, ``-D``, ``-mldep``, ``-prefix``, ``-slash``, and ``-dumpbox``. Passing ``-boot`` to ``coqdep`` will not load any path by default now, ``-R/-Q`` should be used instead (`#11523 `_ and `#11589 `_, by Emilio Jesus Gallego Arias). - **Changed:** The order in which the require flags `-ri`, `-re`, `-rfrom`, etc. and the option flags `-set`, `-unset` are given now matters. In particular, it is now possible to interleave the loading of plugins and the setting of options by choosing the right order for these flags. The load flags `-l` and `-lv` are still processed afterward for now (`#11851 `_ and `#12097 `_, by Lasse Blaauwbroek). - **Changed:** The ``cleanall`` target of a makefile generated by ``coq_makefile`` now erases ``.lia.cache`` and ``.nia.cache`` (`#12006 `_, by Olivier Laurent). - **Changed:** The output of ``make TIMED=1`` (and therefore the timing targets such as ``print-pretty-timed`` and ``print-pretty-timed-diff``) now displays the full name of the output file being built, rather than the stem of the rule (which was usually the filename without the extension, but in general could be anything for user-defined rules involving ``%``) (`#12126 `_, by Jason Gross). - **Changed:** When passing ``TIMED=1`` to ``make`` with either Coq's own makefile or a ``coq_makefile``\-made makefile, timing information is now printed for OCaml files as well (`#12211 `_, by Jason Gross). - **Changed:** The pretty-timed scripts and targets now print a newline at the end of their tables, rather than creating text with no trailing newline (`#12368 `_, by Jason Gross). - **Removed:** The `-load-ml-source` and `-load-ml-object` command-line options have been removed; their use was very limited, you can achieve the same adding additional object files in the linking step or using a plugin (`#11409 `_, by Emilio Jesus Gallego Arias). - **Removed:** The confusingly-named `-require` command-line option, which was deprecated since 8.11. Use the equivalent `-require-import` / `-ri` options instead (`#12005 `_, by ThΓ©o Zimmermann). - **Deprecated:** ``-cumulative-sprop`` command-line flag in favor of the new `Cumulative StrictProp` flag (`#12034 `_, by GaΓ«tan Gilbert). - **Added:** A new documentation environment ``details`` to make certain portion of a Coq document foldable. See :ref:`rocqdoc-hide-show` (`#10592 `_, by Thomas Letan). - **Added:** The ``make-both-single-timing-files.py`` script now accepts a ``--fuzz=N`` parameter on the command line which determines how many characters two lines may be offset in the "before" and "after" timing logs while still being considered the same line. When invoking this script via the ``print-pretty-single-time-diff`` target in a ``Makefile`` made by ``coq_makefile``, you can set this argument by passing ``TIMING_FUZZ=N`` to ``make`` (`#11302 `_, by Jason Gross). - **Added:** The ``make-one-time-file.py`` and ``make-both-time-files.py`` scripts now accept a ``--real`` parameter on the command line to print real times rather than user times in the tables. The ``make-both-single-timing-files.py`` script accepts a ``--user`` parameter to use user times. When invoking these scripts via the ``print-pretty-timed`` or ``print-pretty-timed-diff`` or ``print-pretty-single-time-diff`` targets in a ``Makefile`` made by ``coq_makefile``, you can set this argument by passing ``TIMING_REAL=1`` (to pass ``--real``) or ``TIMING_REAL=0`` (to pass ``--user``) to ``make`` (`#11302 `_, by Jason Gross). - **Added:** Coq's build system now supports both ``TIMING_FUZZ``, ``TIMING_SORT_BY``, and ``TIMING_REAL`` just like a ``Makefile`` made by ``coq_makefile`` (`#11302 `_, by Jason Gross). - **Added:** The ``make-one-time-file.py`` and ``make-both-time-files.py`` scripts now include peak memory usage information in the tables (can be turned off by the ``--no-include-mem`` command-line parameter), and a ``--sort-by-mem`` parameter to sort the tables by memory rather than time. When invoking these scripts via the ``print-pretty-timed`` or ``print-pretty-timed-diff`` targets in a ``Makefile`` made by ``coq_makefile``, you can set this argument by passing ``TIMING_INCLUDE_MEM=0`` (to pass ``--no-include-mem``) and ``TIMING_SORT_BY_MEM=1`` (to pass ``--sort-by-mem``) to ``make`` (`#11606 `_, by Jason Gross). - **Added:** Coq's build system now supports both ``TIMING_INCLUDE_MEM`` and ``TIMING_SORT_BY_MEM`` just like a ``Makefile`` made by ``coq_makefile`` (`#11606 `_, by Jason Gross). - **Added:** New ``coqc`` / ``coqtop`` option ``-boot`` that will not bind the `Coq` library prefix by default (`#11617 `_, by Emilio Jesus Gallego Arias). - **Added:** Definitions in coqdoc link to themselves, giving access in html to their own url (`#12026 `_, by Hugo Herbelin; granting `#7093 `_). - **Added:** Hyperlinks on bound variables in coqdoc (`#12033 `_, by Hugo Herbelin; it incidentally fixes `#7697 `_). - **Added:** Highlighting of link targets in coqdoc (`#12091 `_, by Hugo Herbelin). - **Fixed:** The various timing targets for Coq's standard library now correctly display and label the "before" and "after" columns, rather than mixing them up (`#11302 `_ fixes `#11301 `_, by Jason Gross). - **Fixed:** The sorting order of the timing script ``make-both-time-files.py`` and the target ``print-pretty-timed-diff`` is now deterministic even when the sorting order is ``absolute`` or ``diff``; previously the relative ordering of two files with identical times was non-deterministic (`#11606 `_, by Jason Gross). - **Fixed:** Fields of a record tuple now link in coqdoc to their definition (`#12027 `_, fixes `#3415 `_, by Hugo Herbelin). - **Fixed:** ``coqdoc`` now reports the location of a mismatched opening ``[[`` instead of throwing an uninformative exception (`#12037 `_, fixes `#9670 `_, by Xia Li-yao). - **Fixed:** coqchk incorrectly reporting names from opaque modules as axioms (`#12076 `_, by Pierre Roux; fixes `#5030 `_). - **Fixed:** coq_makefile-generated ``Makefile``\s ``pretty-timed-diff`` target no longer raises Python exceptions in the rare corner case where the log of times contains no files (`#12388 `_, fixes `#12387 `_, by Jason Gross). CoqIDE ^^^^^^^^ - **Removed:** "Tactic" menu from CoqIDE which had been unmaintained for a number of years (`#11414 `_, by Pierre-Marie PΓ©drot). - **Removed:** "Revert all buffers" command from CoqIDE which had been broken for a long time (`#11415 `_, by Pierre-Marie PΓ©drot). .. _812Stdlib: Standard library ^^^^^^^^^^^^^^^^ - **Changed:** Notations :n:`[|@term|]` and :n:`[||@term||]` for morphisms from 63-bit integers to :g:`Z` and :g:`zn2z int` have been removed in favor of :n:`Ο†(@term)` and :n:`Ξ¦(@term)` respectively. These notations were breaking Ltac parsing (`#11686 `_, by Maxime DΓ©nΓ¨s). - **Changed:** The names of ``Sorted_sort`` and ``LocallySorted_sort`` in ``Coq.Sorting.MergeSort`` have been swapped to appropriately reflect their meanings (`#11885 `_, by Lysxia). - **Changed:** Notations :g:`<=?` and :g:``_, `#11891 `_, by Jason Gross). - **Changed:** The level of :g:`≑` in ``Coq.Numbers.Cyclic.Int63.Int63`` is now 70, no associativity, in line with :g:`=`. Note that this is a minor incompatibility with developments that declare their own :g:`≑` notation and import ``Int63`` (fixes `#11905 `_, `#11909 `_, by Jason Gross). - **Changed:** No longer re-export ``ListNotations`` from ``Program`` (``Program.Syntax``) (`#11992 `_, by Antonio Nikishaev). - **Changed:** It is now possible to import the :g:`nsatz` machinery without transitively depending on the axioms of the real numbers nor of classical logic by loading ``Coq.nsatz.NsatzTactic`` rather than ``Coq.nsatz.Nsatz``. Note that some constants have changed kernel names, living in ``Coq.nsatz.NsatzTactic`` rather than ``Coq.nsatz.Nsatz``; this might cause minor incompatibilities that can be fixed by actually running :g:`Import Nsatz` rather than relying on absolute names (`#12073 `_, by Jason Gross; fixes `#5445 `_). - **Changed:** new lemma ``NoDup_incl_NoDup`` in ``List.v`` to remove useless hypothesis `NoDup l'` in ``Sorting.Permutation.NoDup_Permutation_bis`` (`#12120 `_, by Olivier Laurent). - **Changed:** :cmd:`Fixpoints ` of the standard library without a recursive call turned into ordinary :cmd:`Definitions ` (`#12121 `_, by Hugo Herbelin; fixes `#11903 `_). - **Deprecated:** ``Bool.leb`` in favor of ``Bool.le``. The definition of ``Bool.le`` is made local to avoid conflicts with ``Nat.le``. As a consequence, previous calls to ``leb`` based on importing ``Bool`` should now be qualified into ``Bool.le`` even if ``Bool`` is imported (`#12162 `_, by Olivier Laurent). - **Added:** Theorem :g:`bezout_comm` for natural numbers (`#11127 `_, by Daniel de Rauglaudre). - **Added** :g:`rew dependent` notations for the dependent version of :g:`rew` in :g:`Coq.Init.Logic.EqNotations` to improve the display and parsing of :g:`match` statements on :g:`Logic.eq` (`#11240 `_, by Jason Gross). - **Added:** Lemmas about lists: - properties of ``In``: ``in_elt``, ``in_elt_inv`` - properties of ``nth``: ``app_nth2_plus``, ``nth_middle``, ``nth_ext`` - properties of ``last``: ``last_last``, ``removelast_last`` - properties of ``remove``: ``remove_cons``, ``remove_app``, ``notin_remove``, ``in_remove``, ``in_in_remove``, ``remove_remove_comm``, ``remove_remove_eq``, ``remove_length_le``, ``remove_length_lt`` - properties of ``concat``: ``in_concat``, ``remove_concat`` - properties of ``map`` and ``flat_map``: ``map_last``, ``map_eq_cons``, ``map_eq_app``, ``flat_map_app``, ``flat_map_ext``, ``nth_nth_nth_map`` - properties of ``incl``: ``incl_nil_l``, ``incl_l_nil``, ``incl_cons_inv``, ``incl_app_app``, ``incl_app_inv``, ``remove_incl``, ``incl_map``, ``incl_filter``, ``incl_Forall_in_iff`` - properties of ``NoDup`` and ``nodup``: ``NoDup_rev``, ``NoDup_filter``, ``nodup_incl`` - properties of ``Exists`` and ``Forall``: ``Exists_nth``, ``Exists_app``, ``Exists_rev``, ``Exists_fold_right``, ``incl_Exists``, ``Forall_nth``, ``Forall_app``, ``Forall_elt``, ``Forall_rev``, ``Forall_fold_right``, ``incl_Forall``, ``map_ext_Forall``, ``Exists_or``, ``Exists_or_inv``, ``Forall_and``, ``Forall_and_inv``, ``exists_Forall``, ``Forall_image``, ``concat_nil_Forall``, ``in_flat_map_Exists``, ``notin_flat_map_Forall`` - properties of ``repeat``: ``repeat_cons``, ``repeat_to_concat`` - definitions and properties of ``list_sum`` and ``list_max``: ``list_sum_app``, ``list_max_app``, ``list_max_le``, ``list_max_lt`` - misc: ``elt_eq_unit``, ``last_length``, ``rev_eq_app``, ``removelast_firstn_len``, ``cons_seq``, ``seq_S`` (`#11249 `_, `#12237 `_, by Olivier Laurent). - **Added:** Well-founded induction principles for `nat`: ``lt_wf_rect1``, ``lt_wf_rect``, ``gt_wf_rect``, ``lt_wf_double_rect`` (`#11335 `_, by Olivier Laurent). - **Added:** ``remove'`` and ``count_occ'`` over lists, alternatives to ``remove`` and ``count_occ`` based on ``filter`` (`#11350 `_, by Yishuai Li). - **Added:** Facts about ``N.iter`` and ``Pos.iter``: - ``N.iter_swap_gen``, ``N.iter_swap``, ``N.iter_succ``, ``N.iter_succ_r``, ``N.iter_add``, ``N.iter_ind``, ``N.iter_invariant`` - ``Pos.iter_succ_r``, ``Pos.iter_ind`` (`#11880 `_, by Lysxia). - **Added:** Facts about ``Permutation``: - structure: ``Permutation_refl'``, ``Permutation_morph_transp`` - compatibilities: ``Permutation_app_rot``, ``Permutation_app_swap_app``, ``Permutation_app_middle``, ``Permutation_middle2``, ``Permutation_elt``, ``Permutation_Forall``, ``Permutation_Exists``, ``Permutation_Forall2``, ``Permutation_flat_map``, ``Permutation_list_sum``, ``Permutation_list_max`` - inversions: ``Permutation_app_inv_m``, ``Permutation_vs_elt_inv``, ``Permutation_vs_cons_inv``, ``Permutation_vs_cons_cons_inv``, ``Permutation_map_inv``, ``Permutation_image``, ``Permutation_elt_map_inv`` - length-preserving definition by means of transpositions ``Permutation_transp`` with associated properties: ``Permutation_transp_sym``, ``Permutation_transp_equiv``, ``Permutation_transp_cons``, ``Permutation_Permutation_transp``, ``Permutation_ind_transp`` (`#11946 `_, by Olivier Laurent). - **Added:** Notations for sigma types: ``{ x & P & Q }``, ``{ ' pat & P }``, ``{ ' pat & P & Q }`` (`#11957 `_, by Olivier Laurent). - **Added:** Order relations ``lt`` and ``compare`` added in ``Bool.Bool``. Order properties for ``bool`` added in ``Bool.BoolOrder`` as well as two modules ``Bool_as_OT`` and ``Bool_as_DT`` in ``Structures.OrdersEx`` (`#12008 `_, by Olivier Laurent). - **Added:** Properties of some operations on vectors: - ``nth_order``: ``nth_order_hd``, ``nth_order_tl``, ``nth_order_ext`` - ``replace``: ``nth_order_replace_eq``, ``nth_order_replace_neq``, ``replace_id``, ``replace_replace_eq``, ``replace_replace_neq`` - ``map``: ``map_id``, ``map_map``, ``map_ext_in``, ``map_ext`` - ``Forall`` and ``Forall2``: ``Forall_impl``, ``Forall_forall``, ``Forall_nth_order``, ``Forall2_nth_order`` (`#12014 `_, by Olivier Laurent). - **Added:** Lemmas :g:`orb_negb_l`, :g:`andb_negb_l`, :g:`implb_true_iff`, :g:`implb_false_iff`, :g:`implb_true_r`, :g:`implb_false_r`, :g:`implb_true_l`, :g:`implb_false_l`, :g:`implb_same`, :g:`implb_contrapositive`, :g:`implb_negb`, :g:`implb_curry`, :g:`implb_andb_distrib_r`, :g:`implb_orb_distrib_r`, :g:`implb_orb_distrib_l` in library :g:`Bool` (`#12018 `_, by Hugo Herbelin). - **Added:** Definition and properties of cyclic permutations / circular shifts: ``CPermutation`` (`#12031 `_, by Olivier Laurent). - **Added:** ``Structures.OrderedTypeEx.Ascii_as_OT`` (`#12044 `_, by formalize.eth (formalize@protonmail.com)). - **Fixed:** Rewrote ``Structures.OrderedTypeEx.String_as_OT.compare`` to avoid huge proof terms (`#12044 `_, by formalize.eth (formalize@protonmail.com); fixes `#12015 `_). Reals library ^^^^^^^^^^^^^ - **Changed:** Cleanup of names in the Reals theory: replaced `tan_is_inj` with `tan_inj` and replaced `atan_right_inv` with `tan_atan` - compatibility notations are provided. Moved various auxiliary lemmas from `Ratan.v` to more appropriate places (`#9803 `_, by Laurent ThΓ©ry and Michael Soegtrop). - **Changed:** Replace `CRzero` and `CRone` by `CR_of_Q 0` and `CR_of_Q 1` in `ConstructiveReals`. Use implicit arguments for `ConstructiveReals`. Move `ConstructiveReals` into new directory `Abstract`. Remove imports of implementations inside those `Abstract` files. Move implementation by means of Cauchy sequences in new directory `Cauchy`. Split files `ConstructiveMinMax` and `ConstructivePower`. .. warning:: The constructive reals modules are marked as experimental. (`#11725 `_, `#12287 `_ and `#12288 `_, by Vincent Semeria). - **Removed:** Type `RList` has been removed. All uses have been replaced by `list R`. Functions from `RList` named `In`, `Rlength`, `cons_Rlist`, `app_Rlist` have also been removed as they are essentially the same as `In`, `length`, `app`, and `map` from `List`, modulo the following changes: - `RList.In x (RList.cons a l)` used to be convertible to `(x = a) \\/ RList.In x l`, but `List.In x (a :: l)` is convertible to `(a = x) \\/ List.In l`. The equality is reversed. - `app_Rlist` and `List.map` take arguments in different order. (`#11404 `_, by Yves Bertot). - **Added:** inverse trigonometric functions `asin` and `acos` with lemmas for the derivatives, bounds and special values of these functions; an extensive set of identities between trigonometric functions and their inverse functions; lemmas for the injectivity of sine and cosine; lemmas on the derivative of the inverse of decreasing functions and on the derivative of horizontally mirrored functions; various generic auxiliary lemmas and definitions for `Rsqr`, `sqrt`, `posreal` and others (`#9803 `_, by Laurent ThΓ©ry and Michael Soegtrop). Extraction ^^^^^^^^^^ - **Added:** Support for better extraction of strings in OCaml and Haskell: `ExtOcamlNativeString` provides bindings from the Coq `String` type to the OCaml `string` type, and string literals can be extracted to literals, both in OCaml and Haskell (`#10486 `_, by Xavier Leroy, with help from Maxime DΓ©nΓ¨s, review by Hugo Herbelin). - **Fixed:** In Haskell extraction with ``ExtrHaskellString``, equality comparisons on strings and characters are now guaranteed to be uniquely well-typed, even in very polymorphic contexts under ``unsafeCoerce``; this is achieved by adding type annotations to the extracted code, and by making ``ExtrHaskellString`` export ``ExtrHaskellBasic`` (`#12263 `_, by Jason Gross, fixes `#12257 `_ and `#12258 `_). .. _812Refman: Reference manual ^^^^^^^^^^^^^^^^ - **Changed:** The reference manual has been restructured to get a more logical organization. In the new version, there are fewer top-level chapters, and, in the HTML format, chapters are split into smaller pages. This is still a work in progress and further restructuring is expected in the next versions of Coq (`CEP#43 `_, implemented in `#11601 `_, `#11871 `_, `#11914 `_, `#12148 `_, `#12172 `_, `#12239 `_ and `#12330 `_, effort inspired by Matthieu Sozeau, led by ThΓ©o Zimmermann, with help and reviews of Jim Fehrle, ClΓ©ment Pit-Claudel and others). - **Changed:** Most of the grammar is now presented using the notation mechanism that has been used to present commands and tactics since Coq 8.8 and which is documented in :ref:`syntax-conventions` (`#11183 `_, `#11314 `_, `#11423 `_, `#11705 `_, `#11718 `_, `#11720 `_, `#11961 `_ and `#12103 `_, by Jim Fehrle, reviewed by ThΓ©o Zimmermann). - **Added:** A glossary of terms and an index of attributes (`#11869 `_, `#12150 `_ and `#12224 `_, by Jim Fehrle and ThΓ©o Zimmermann, reviewed by ClΓ©ment Pit-Claudel) - **Added:** A selector that allows switching between versions of the reference manual (`#12286 `_, by ClΓ©ment Pit-Claudel). - **Fixed:** Most of the documented syntax has been thoroughly updated to make it accurate and easily understood. This was done using a semi-automated `doc_grammar` tool introduced for this purpose and through significant revisions to the text (`#9884 `_, `#10614 `_, `#11314 `_, `#11423 `_, `#11705 `_, `#11718 `_, `#11720 `_ `#11797 `_, `#11913 `_, `#11958 `_, `#11960 `_, `#11961 `_ and `#12103 `_, by Jim Fehrle, reviewed by ThΓ©o Zimmermann and Jason Gross). Infrastructure and dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - **Changed:** Minimal versions of dependencies for building the reference manual: now requires Sphinx >= 2.3.1 & < 3.0.0, sphinx_rtd_theme 0.4.3+ and sphinxcontrib-bibtex 0.4.2+. .. warning:: The reference manual is known not to build properly with Sphinx 3. (`#12224 `_, by Jim Fehrle and ThΓ©o Zimmermann). - **Removed:** Python 2 is no longer required in any part of the codebase (`#11245 `_, by Emilio Jesus Gallego Arias). Changes in 8.12.0 ~~~~~~~~~~~~~~~~~~~~~ **Notations** - **Added:** Simultaneous definition of terms and notations now support custom entries (`#12523 `_, fixes `#11121 `_ by Maxime DΓ©nΓ¨s). - **Fixed:** Printing bug with notations for n-ary applications used with applied references (`#12683 `_, fixes `#12682 `_, by Hugo Herbelin). **Tactics** - **Fixed:** :tacn:`typeclasses eauto` (and discriminated hint bases) now correctly classify local variables as being unfoldable (`#12572 `_, fixes `#12571 `_, by Pierre-Marie PΓ©drot). **Tactic language** - **Fixed:** Excluding occurrences was causing an anomaly in tactics (e.g., :g:`pattern _ at L` where :g:`L` is :g:`-2`) (`#12541 `_, fixes `#12228 `_, by Pierre Roux). - **Fixed:** Parsing of multi-parameters Ltac2 types (`#12594 `_, fixes `#12595 `_, by Pierre-Marie PΓ©drot). **SSReflect** - **Fixed:** Do not store the full environment inside ssr ast_closure_term (`#12708 `_, fixes `#12707 `_, by Pierre-Marie PΓ©drot). **Commands and options** - **Fixed:** Properly report the mismatched magic number of vo files (`#12677 `_, fixes `#12513 `_, by Pierre-Marie PΓ©drot). - **Changed:** Arbitrary hints have been undeprecated, and their definition now triggers a standard warning instead (`#12678 `_, fixes `#11970 `_, by Pierre-Marie PΓ©drot). **CoqIDE** - **Fixed:** CoqIDE no longer exits when trying to open a file whose name is not a valid identifier (`#12562 `_, fixes `#10988 `_, by Vincent Laporte). **Infrastructure and dependencies** - **Fixed:** Running ``make`` in ``test-suite/`` twice (or more) in a row will no longer rebuild the ``modules/`` tests on subsequent runs, if they have not been modified in the meantime (`#12583 `_, fixes `#12582 `_, by Jason Gross). Changes in 8.12.1 ~~~~~~~~~~~~~~~~~~~~~ **Kernel** - **Fixed:** Incompleteness of conversion checking on problems involving :ref:`eta-expansion-sect` and :ref:`cumulative universe polymorphic inductive types ` (`#12738 `_, fixes `#7015 `_, by GaΓ«tan Gilbert). - **Fixed:** Polymorphic side-effects inside monomorphic definitions were incorrectly handled as not inlined. This allowed deriving an inconsistency (`#13331 `_, fixes `#13330 `_, by Pierre-Marie PΓ©drot). **Notations** - **Fixed:** Undetected collision between a lonely notation and a notation in scope at printing time (`#12946 `_, fixes the first part of `#12908 `_, by Hugo Herbelin). - **Fixed:** Printing of notations in custom entries with variables not mentioning an explicit level (`#13026 `_, fixes `#12775 `_ and `#13018 `_, by Hugo Herbelin). **Tactics** - **Added:** :tacn:`replace` and :tacn:`inversion` support registration of a :g:`core.identity`\-like equality in :g:`Type`, such as HoTT's :g:`path` (`#12847 `_, partially fixes `#12846 `_, by Hugo Herbelin). - **Fixed:** Anomaly with :tacn:`injection` involving artificial dependencies disappearing by reduction (`#12816 `_, fixes `#12787 `_, by Hugo Herbelin). **Tactic language** - **Fixed:** Miscellaneous issues with locating tactic errors (`#13247 `_, fixes `#12773 `_ and `#12992 `_, by Hugo Herbelin). **SSReflect** - **Fixed:** Regression in error reporting after :tacn:`case `. A generic error message "Could not fill dependent hole in apply" was reported for any error following :tacn:`case ` or :tacn:`elim ` (`#12857 `_, fixes `#12837 `_, by Enrico Tassi). **Commands and options** - **Fixed:** Failures of :cmd:`Search` in the presence of primitive projections (`#13301 `_, fixes `#13298 `_, by Hugo Herbelin). - **Fixed:** :cmd:`Search` supports filtering on parts of identifiers which are not proper identifiers themselves, such as :n:`"1"` (`#13351 `_, fixes `#13349 `_, by Hugo Herbelin). **Tools** - **Fixed:** Special symbols now escaped in the index produced by coqdoc, avoiding collision with the syntax of the output format (`#12754 `_, fixes `#12752 `_, by Hugo Herbelin). - **Fixed:** The `details` environment added in the 8.12 release can now be used as advertised in the reference manual (`#12772 `_, by Thomas Letan). - **Fixed:** Targets such as ``print-pretty-timed`` in ``coq_makefile``\-made ``Makefile``\s no longer error in rare cases where ``--output-sync`` is not passed to make and the timing output gets interleaved in just the wrong way (`#13063 `_, fixes `#13062 `_, by Jason Gross). **CoqIDE** - **Fixed:** View menu "Display parentheses" (`#12794 `_ and `#13067 `_, fixes `#12793 `_, by Jean-Christophe LΓ©chenet and Hugo Herbelin). **Infrastructure and dependencies** - **Added:** Coq is now tested against OCaml 4.11.1 (`#12972 `_, by Emilio Jesus Gallego Arias). - **Fixed:** The reference manual can now build with Sphinx 3 (`#13011 `_, fixes `#12332 `_, by ThΓ©o Zimmermann and Jim Fehrle). Changes in 8.12.2 ~~~~~~~~~~~~~~~~~ **Notations** - **Fixed:** 8.12 regression causing notations mentioning a coercion to be ignored (`#13436 `_, fixes `#13432 `_, by Hugo Herbelin). **Tactics** - **Fixed:** 8.12 regression: incomplete inference of implicit arguments in :tacn:`exists` (`#13468 `_, fixes `#13456 `_, by Hugo Herbelin). Version 8.11 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ The main changes brought by Coq version 8.11 are: - :ref:`Ltac2<811Ltac2>`, a new tactic language for writing more robust larger scale tactics, with built-in support for datatypes and the multi-goal tactic monad. - :ref:`Primitive floats<811PrimitiveFloats>` are integrated in terms and follow the binary64 format of the IEEE 754 standard, as specified in the `Coq.Float.Floats` library. - :ref:`Cleanups<811Sections>` of the section mechanism, delayed proofs and further restrictions of template polymorphism to fix soundness issues related to universes. - New :ref:`unsafe flags<811UnsafeFlags>` to disable locally guard, positivity and universe checking. Reliance on these flags is always printed by :g:`Print Assumptions`. - :ref:`Fixed bugs<811ExportBug>` of :g:`Export` and :g:`Import` that can have a significant impact on user developments (**common source of incompatibility!**). - New interactive development method based on `vos` :ref:`interface files<811vos>`, allowing to work on a file without recompiling the proof parts of their dependencies. - New :g:`Arguments` annotation for :ref:`bidirectional type inference<811BidirArguments>` configuration for reference (e.g. constants, inductive) applications. - New :ref:`refine attribute<811RefineInstance>` for :cmd:`Instance` can be used instead of the removed ``Refine Instance Mode``. - Generalization of the :g:`under` and :g:`over` :ref:`tactics<811SSRUnderOver>` of SSReflect to arbitrary relations. - :ref:`Revision<811Reals>` of the :g:`Coq.Reals` library, its axiomatisation and instances of the constructive and classical real numbers. Additionally, while the `omega` tactic is not yet deprecated in this version of Coq, it should soon be the case and we already recommend users to switch to :tacn:`lia` in new proof scripts. The ``dev/doc/critical-bugs`` file documents the known critical bugs of Coq and affected releases. See the `Changes in 8.11+beta1`_ section and following sections for the detailed list of changes, including potentially breaking changes marked with **Changed**. Coq's documentation is available at https://coq.github.io/doc/v8.11/api (documentation of the ML API), https://coq.github.io/doc/v8.11/refman (reference manual), and https://coq.github.io/doc/v8.11/stdlib (documentation of the standard library). Maxime DΓ©nΓ¨s, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop and ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. The opam repository for Coq packages has been maintained by Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The 61 contributors to this version are Michael D. Adams, Guillaume Allais, Helge Bahmann, Langston Barrett, Guillaume Bertholon, FrΓ©dΓ©ric Besson, Simon Boulier, Michele Caci, Tej Chajed, Arthur CharguΓ©raud, Cyril Cohen, FrΓ©dΓ©ric Dabrowski, Arthur Azevedo de Amorim, Maxime DΓ©nΓ¨s, Nikita Eshkeev, Jim Fehrle, Emilio JesΓΊs Gallego Arias, Paolo G. Giarrusso, GaΓ«tan Gilbert, Georges Gonthier, Jason Gross, Samuel Gruetter, ArmaΓ«l GuΓ©neau, Hugo Herbelin, Florent Hivert, Jasper Hugunin, Shachar Itzhaky, Jan-Oliver Kaiser, Robbert Krebbers, Vincent Laporte, Olivier Laurent, Samuel LeliΓ¨vre, Nicholas Lewycky, Yishuai Li, Jose Fernando Lopez Fernandez, Andreas Lynge, Kenji Maillard, Erik Martin-Dorel, Guillaume Melquiond, Alexandre Moine, Oliver Nash, Wojciech Nawrocki, Antonio Nikishaev, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Lars Rasmusson, Robert Rand, Talia Ringer, JP Rodi, Pierre Roux, Kazuhiko Sakaguchi, Vincent Semeria, Michael Soegtrop, Matthieu Sozeau, spanjel, Claude Stolze, Enrico Tassi, Laurent ThΓ©ry, James R. Wilcox, Xia Li-yao, ThΓ©o Zimmermann Many power users helped to improve the design of the new features via the issue and pull request system, the Coq development mailing list, the coq-club@inria.fr mailing list or the `Discourse forum `_. It would be impossible to mention exhaustively the names of everybody who to some extent influenced the development. Version 8.11 is the sixth release of Coq developed on a time-based development cycle. Its development spanned 3 months from the release of Coq 8.10. Pierre-Marie PΓ©drot is the release manager and maintainer of this release, assisted by Matthieu Sozeau. This release is the result of 2000+ commits and 300+ PRs merged, closing 75+ issues. | Paris, November 2019, | Matthieu Sozeau for the Coq development team | Changes in 8.11+beta1 ~~~~~~~~~~~~~~~~~~~~~ **Kernel** .. _811PrimitiveFloats: - **Added:** A built-in support of floating-point arithmetic, allowing one to devise efficient reflection tactics involving numerical computation. Primitive floats are added in the language of terms, following the binary64 format of the IEEE 754 standard, and the related operations are implemented for the different reduction engines of Coq by using the corresponding processor operators in rounding-to-nearest-even. The properties of these operators are axiomatized in the theory :g:`Coq.Floats.FloatAxioms` which is part of the library :g:`Coq.Floats.Floats`. See Section :ref:`primitive-floats` (`#9867 `_, closes `#8276 `_, by Guillaume Bertholon, Erik Martin-Dorel, Pierre Roux). - **Changed:** Internal definitions generated by :tacn:`abstract`\-like tactics are now inlined inside universe :cmd:`Qed`\-terminated polymorphic definitions, similarly to what happens for their monomorphic counterparts, (`#10439 `_, by Pierre-Marie PΓ©drot). .. _811Sections: - **Fixed:** Section data is now part of the kernel. Solves a soundness issue in interactive mode where global monomorphic universe constraints would be dropped when forcing a delayed opaque proof inside a polymorphic section. Also relaxes the nesting criterion for sections, as polymorphic sections can now appear inside a monomorphic one (`#10664 `_, by Pierre-Marie PΓ©drot). - **Changed:** Using ``SProp`` is now allowed by default, without needing to pass ``-allow-sprop`` or use :flag:`Allow StrictProp` (`#10811 `_, by GaΓ«tan Gilbert). **Specification language, type inference** .. _811BidirArguments: - **Added:** Annotation in `Arguments` for bidirectionality hints: it is now possible to tell type inference to use type information from the context once the `n` first arguments of an application are known. The syntax is: `Arguments foo x y & z`. See :ref:`bidirectionality_hints` (`#10049 `_, by Maxime DΓ©nΓ¨s with help from Enrico Tassi). - **Added:** Record fields can be annotated to prevent them from being used as canonical projections; see :ref:`canonicalstructures` for details (`#10076 `_, by Vincent Laporte). - **Changed:** Require parentheses around nested disjunctive patterns, so that pattern and term syntax are consistent; match branch patterns no longer require parentheses for notation at level 100 or more. .. warning:: Incompatibilities + In :g:`match p with (_, (0|1)) => ...` parentheses may no longer be omitted around :n:`0|1`. + Notation :g:`(p | q)` now potentially clashes with core pattern syntax, and should be avoided. ``-w disj-pattern-notation`` flags such :cmd:`Notation`. See :ref:`extendedpatternmatching` for details (`#10167 `_, by Georges Gonthier). - **Changed:** :cmd:`Function` always opens a proof when used with a ``measure`` or ``wf`` annotation, see :ref:`advanced-recursive-functions` for the updated documentation (`#10215 `_, by Enrico Tassi). - **Changed:** The legacy command :cmd:`Add Morphism` always opens a proof and cannot be used inside a module type. In order to declare a module type parameter that happens to be a morphism, use :cmd:`Declare Morphism`. See :ref:`deprecated_syntax_for_generalized_rewriting` for the updated documentation (`#10215 `_, by Enrico Tassi). - **Changed:** The universe polymorphism setting now applies from the opening of a section. In particular, it is not possible anymore to mix polymorphic and monomorphic definitions in a section when there are no variables nor universe constraints defined in this section. This makes the behavior consistent with the documentation. (`#10441 `_, by Pierre-Marie PΓ©drot) - **Added:** The :cmd:`Section` command now accepts the "universes" attribute. In addition to setting the section universe polymorphism, it also locally sets the universe polymorphic option inside the section (`#10441 `_, by Pierre-Marie PΓ©drot) - **Fixed:** ``Program Fixpoint`` now uses ``ex`` and ``sig`` to make telescopes involving ``Prop`` types (`#10758 `_, by GaΓ«tan Gilbert, fixing `#10757 `_ reported by Xavier Leroy). - **Changed:** Output of the :cmd:`Print` and :cmd:`About` commands. Arguments meta-data is now displayed as the corresponding :cmd:`Arguments` command instead of the human-targeted prose used in previous Coq versions. (`#10985 `_, by GaΓ«tan Gilbert). .. _811RefineInstance: - **Added:** :attr:`refine` attribute for :cmd:`Instance`, a more predictable version of the old ``Refine Instance Mode`` which unconditionally opens a proof (`#10996 `_, by GaΓ«tan Gilbert). - **Changed:** The unsupported attribute error is now an error-by-default warning, meaning it can be disabled (`#10997 `_, by GaΓ«tan Gilbert). - **Fixed:** Bugs sometimes preventing to define valid (co)fixpoints with implicit arguments in the presence of local definitions, see `#3282 `_ (`#11132 `_, by Hugo Herbelin). .. example:: The following features an implicit argument after a local definition. It was wrongly rejected. .. rocqtop:: in Definition f := fix f (o := true) {n : nat} m {struct m} := match m with 0 => 0 | S m' => f (n:=n+1) m' end. **Notations** - **Added:** Numeral Notations now support sorts in the input to printing functions (e.g., numeral notations can be defined for terms containing things like `@cons Set nat nil`). (`#9883 `_, by Jason Gross). - **Added:** The :cmd:`Notation` and :cmd:`Infix` commands now support the `deprecated` attribute (`#10180 `_, by Maxime DΓ©nΓ¨s). - **Deprecated:** The former `compat` annotation for notations is deprecated, and its semantics changed. It is now made equivalent to using a `deprecated` attribute, and is no longer connected with the `-compat` command-line flag (`#10180 `_, by Maxime DΓ©nΓ¨s). - **Changed:** A simplification of parsing rules could cause a slight change of parsing precedences for the very rare users who defined notations with `constr` at level strictly between 100 and 200 and used these notations on the right-hand side of a cast operator (`:`, `<:`, `<<:`) (`#10963 `_, by ThΓ©o Zimmermann, simplification initially noticed by Jim Fehrle). **Tactics** - **Added:** Syntax :n:`injection @term as [= {+ @intropattern} ]` as an alternative to :n:`injection @term as {+ @simple_intropattern}` using the standard injection intropattern syntax (`#9288 `_, by Hugo Herbelin). - **Changed:** Reimplementation of the :tacn:`zify` tactic. The tactic is more efficient and copes with dependent hypotheses. It can also be extended by redefining the tactic ``zify_post_hook`` (`#9856 `_, fixes `#8898 `_, `#7886 `_, `#9848 `_ and `#5155 `_, by FrΓ©dΓ©ric Besson). - **Changed:** The goal selector tactical ``only`` now checks that the goal range it is given is valid instead of ignoring goals out of the focus range (`#10318 `_, by GaΓ«tan Gilbert). - **Added:** Flags :flag:`Lia Cache`, :flag:`Nia Cache` and :flag:`Nra Cache` (`#10765 `_, by FrΓ©dΓ©ric Besson, see `#10772 `_ for use case). - **Added:** The :tacn:`zify` tactic is now aware of `Z.to_N` (`#10774 `_, grants `#9162 `_, by Kazuhiko Sakaguchi). - **Changed:** The :tacn:`assert_succeeds` and :tacn:`assert_fails` tactics now only run their tactic argument once, even if it has multiple successes. This prevents blow-up and looping from using multisuccess tactics with :tacn:`assert_succeeds`. (`#10966 `_ fixes `#10965 `_, by Jason Gross). - **Fixed:** The :tacn:`assert_succeeds` and :tacn:`assert_fails` tactics now behave correctly when their tactic fully solves the goal. (`#10966 `_ fixes `#9114 `_, by Jason Gross). **Tactic language** .. _811Ltac2: - **Added:** Ltac2, a new version of the tactic language Ltac, that doesn't preserve backward compatibility, has been integrated in the main Coq distribution. It is still experimental, but we already recommend users of advanced Ltac to start using it and report bugs or request enhancements. See its documentation in the :ref:`dedicated chapter ` (`#10002 `_, plugin authored by Pierre-Marie PΓ©drot, with contributions by various users, integration by Maxime DΓ©nΓ¨s, help on integrating / improving the documentation by ThΓ©o Zimmermann and Jim Fehrle). - **Added:** Ltac2 tactic notations with β€œconstr” arguments can specify the notation scope for these arguments; see :ref:`ltac2_notations` for details (`#10289 `_, by Vincent Laporte). - **Changed:** White spaces are forbidden in the :n:`&@ident` syntax for ltac2 references that are described in :ref:`ltac2_built-in-quotations` (`#10324 `_, fixes `#10088 `_, authored by Pierre-Marie PΓ©drot). **SSReflect** .. _811SSRUnderOver: - **Added:** Generalize tactics :tacn:`under` and :tacn:`over` for any registered relation. More precisely, assume the given context lemma has type `forall f1 f2, .. -> (forall i, R1 (f1 i) (f2 i)) -> R2 f1 f2`. The first step performed by :tacn:`under` (since Coq 8.10) amounts to calling the tactic :tacn:`rewrite `, which itself relies on :tacn:`setoid_rewrite` if need be. So this step was already compatible with a double implication or setoid equality for the conclusion head symbol `R2`. But a further step consists in tagging the generated subgoal `R1 (f1 i) (?f2 i)` to protect it from unwanted evar instantiation, and get `Under_rel _ R1 (f1 i) (?f2 i)` that is displayed as ``'Under[ f1 i ]``. In Coq 8.10, this second (convenience) step was only performed when `R1` was Leibniz' `eq` or `iff`. Now, it is also performed for any relation `R1` which has a ``RewriteRelation`` instance (a `RelationClasses.Reflexive` instance being also needed so :tacn:`over` can discharge the ``'Under[ _ ]`` goal by instantiating the hidden evar.) This feature generalizing support for setoid-like relations is enabled as soon as we do both ``Require Import ssreflect.`` and ``Require Setoid.`` Finally, a rewrite rule ``UnderE`` has been added if one wants to "unprotect" the evar, and instantiate it manually with another rule than reflexivity (i.e., without using the :tacn:`over` tactic nor the ``over`` rewrite rule). See also Section :ref:`under_ssr` (`#10022 `_, by Erik Martin-Dorel, with suggestions and review by Enrico Tassi and Cyril Cohen). - **Added:** A :g:`void` notation for the standard library empty type (:g:`Empty_set`) (`#10932 `_, by Arthur Azevedo de Amorim). - **Added:** Lemma :g:`inj_compr` to :g:`ssr.ssrfun` (`#11136 `_, by Cyril Cohen). **Commands and options** - **Removed:** Deprecated flag `Refine Instance Mode` (`#9530 `_, fixes `#3632 `_, `#3890 `_ and `#4638 `_ by Maxime DΓ©nΓ¨s, review by GaΓ«tan Gilbert). - **Changed:** :cmd:`Fail` does not catch critical errors (including "stack overflow") anymore (`#10173 `_, by GaΓ«tan Gilbert). - **Removed:** Undocumented :n:`Instance : !@type` syntax (`#10185 `_, by GaΓ«tan Gilbert). - **Removed:** Deprecated ``Show Script`` command (`#10277 `_, by GaΓ«tan Gilbert). .. _811UnsafeFlags: - **Added:** Unsafe commands to enable/disable guard checking, positivity checking and universes checking (providing a local `-type-in-type`). See :ref:`controlling-typing-flags` (`#10291 `_ by Simon Boulier). .. _811ExportBug: - **Fixed:** Two bugs in :cmd:`Export`. This can have an impact on the behavior of the :cmd:`Import` command on libraries. `Import A` when `A` imports `B` which exports `C` was importing `C`, whereas :cmd:`Import` is not transitive. Also, after `Import A B`, the import of `B` was sometimes incomplete (`#10476 `_, by Maxime DΓ©nΓ¨s). .. warning:: This is a common source of incompatibilities in projects migrating to Coq 8.11. - **Changed:** Output generated by :flag:`Printing Dependent Evars Line` flag used by the Prooftree tool in Proof General (`#10489 `_, closes `#4504 `_, `#10399 `_ and `#10400 `_, by Jim Fehrle). - **Added:** Optionally highlight the differences between successive proof steps in the :cmd:`Show Proof` command. Experimental; only available in coqtop and Proof General for now, may be supported in other IDEs in the future (`#10494 `_, by Jim Fehrle). - **Removed:** Legacy commands ``AddPath``, ``AddRecPath``, and ``DelPath`` which were undocumented, broken variants of ``Add LoadPath``, ``Add Rec LoadPath``, and ``Remove LoadPath`` (`#11187 `_, by Maxime DΓ©nΓ¨s and ThΓ©o Zimmermann). **Tools** .. _811vos: - **Added:** `coqc` now provides the ability to generate compiled interfaces. Use `coqc -vos foo.v` to skip all opaque proofs during the compilation of `foo.v`, and output a file called `foo.vos`. This feature is experimental. It enables working on a Coq file without the need to first compile the proofs contained in its dependencies (`#8642 `_ by Arthur CharguΓ©raud, review by Maxime DΓ©nΓ¨s and Emilio Gallego). - **Added:** Command-line options `-require-import`, `-require-export`, `-require-import-from` and `-require-export-from`, as well as their shorthand, `-ri`, `-re`, `-refrom` and -`rifrom`. Deprecate confusing command line option `-require` (`#10245 `_ by Hugo Herbelin, review by Emilio Gallego). - **Changed:** Renamed `VDFILE` from `.coqdeps.d` to `..d` in the `coq_makefile` utility, where `` is the name of the output file given by the `-o` option. In this way two generated makefiles can coexist in the same directory (`#10947 `_, by Kazuhiko Sakaguchi). - **Fixed:** ``coq_makefile`` now supports environment variable ``COQBIN`` with no ending ``/`` character (`#11068 `_, by GaΓ«tan Gilbert). **Standard library** - **Changed:** Moved the :tacn:`auto` hints of the `OrderedType` module into a new `ordered_type` database (`#9772 `_, by Vincent Laporte). - **Removed:** Deprecated modules `Coq.ZArith.Zlogarithm` and `Coq.ZArith.Zsqrt_compat` (`#9811 `_, by Vincent Laporte). .. _811Reals: - **Added:** Module `Reals.Cauchy.ConstructiveCauchyReals` defines constructive real numbers by Cauchy sequences of rational numbers (`#10445 `_, by Vincent Semeria, with the help and review of Guillaume Melquiond and Bas Spitters). This module is not meant to be imported directly, please import `Reals.Abstract.ConstructiveReals` instead. - **Added:** New module `Reals.ClassicalDedekindReals` defines Dedekind real numbers as boolean-valued functions along with 3 logical axioms: limited principle of omniscience, excluded middle of negations, and functional extensionality. The exposed type :g:`R` in module :g:`Reals.Rdefinitions` now corresponds to these Dedekind reals, hidden behind an opaque module, which significantly reduces the number of axioms needed (see `Reals.Rdefinitions` and `Reals.Raxioms`), while preserving backward compatibility. Classical Dedekind reals are a quotient of constructive reals, which allows to transport many constructive proofs to the classical case (`#10827 `_, by Vincent Semeria, based on discussions with Guillaume Melquiond, Bas Spitters and Hugo Herbelin, code review by Hugo Herbelin). - **Added:** New lemmas on :g:`combine`, :g:`filter`, :g:`nodup`, :g:`nth`, and :g:`nth_error` functions on lists (`#10651 `_, and `#10731 `_, by Oliver Nash). - **Changed:** The lemma :g:`filter_app` was moved to the :g:`List` module (`#10651 `_, by Oliver Nash). - **Added:** Standard equivalence between weak excluded-middle and the classical instance of De Morgan's law, in module :g:`ClassicalFacts` (`#10895 `_, by Hugo Herbelin). **Infrastructure and dependencies** - **Changed:** Coq now officially supports OCaml 4.08. See `INSTALL` file for details (`#10471 `_, by Emilio JesΓΊs Gallego Arias). Changes in 8.11.0 ~~~~~~~~~~~~~~~~~ **Kernel** - **Changed:** the native compilation (:tacn:`native_compute`) now creates a directory to contain temporary files instead of putting them in the root of the system temporary directory (`#11081 `_, by GaΓ«tan Gilbert). - **Fixed:** `#11360 `_. Broken section closing when a template polymorphic inductive type depends on a section variable through its parameters (`#11361 `_, by GaΓ«tan Gilbert). - **Fixed:** The type of :g:`Set+1` would be computed to be itself, leading to a proof of False (`#11422 `_, by GaΓ«tan Gilbert). **Specification language, type inference** - **Changed:** Heuristics for universe minimization to :g:`Set`: only minimize flexible universes (`#10657 `_, by GaΓ«tan Gilbert with help from Maxime DΓ©nΓ¨s and Matthieu Sozeau). - **Fixed:** A dependency was missing when looking for default clauses in the algorithm for printing pattern matching clauses (`#11233 `_, by Hugo Herbelin, fixing `#11231 `_, reported by Barry Jay). **Notations** - **Fixed:** :cmd:`Print Visibility` was failing in the presence of only-printing notations (`#11276 `_, by Hugo Herbelin, fixing `#10750 `_). - **Fixed:** Recursive notations with custom entries were incorrectly parsing `constr` instead of custom grammars (`#11311 `_ by Maxime DΓ©nΓ¨s, fixes `#9532 `_, `#9490 `_). **Tactics** - **Changed:** The tactics :tacn:`eapply`, :tacn:`refine` and variants no longer allow shelved goals to be solved by typeclass resolution (`#10762 `_, by Matthieu Sozeau). - **Fixed:** The optional string argument to :tacn:`time` is now properly quoted under :cmd:`Print Ltac` (`#11203 `_, fixes `#10971 `_, by Jason Gross) - **Fixed:** Efficiency regression of :tacn:`lia` introduced in 8.10 by PR `#9725 `_ (`#11263 `_, fixes `#11063 `_, and `#11242 `_, and `#11270 `_, by FrΓ©dΓ©ric Besson). - **Deprecated:** The undocumented ``omega with`` tactic variant has been deprecated. Using :tacn:`lia` is the recommended replacement, though the old semantics of ``omega with *`` can be recovered with ``zify; omega`` (`#11337 `_, by Emilio Jesus Gallego Arias). - **Fixed** For compatibility reasons, in 8.11, :tacn:`zify` does not support :g:`Z.pow_pos` by default. It can be enabled by explicitly loading the module :g:`ZifyPow` (`#11430 `_ by FrΓ©dΓ©ric Besson fixes `#11191 `_). **Tactic language** - **Fixed:** Syntax of tactic `cofix ... with ...` was broken since Coq 8.10 (`#11241 `_, by Hugo Herbelin). **Commands and options** - **Deprecated:** The `-load-ml-source` and `-load-ml-object` command line options have been deprecated; their use was very limited, you can achieve the same by adding object files in the linking step or by using a plugin (`#11428 `_, by Emilio Jesus Gallego Arias). **Tools** - **Fixed:** ``coqtop --version`` was broken when called in the middle of an installation process (`#11255 `_, by Hugo Herbelin, fixing `#11254 `_). - **Deprecated:** The ``-quick`` command is renamed to ``-vio``, for consistency with the new ``-vos`` and ``-vok`` flags. Usage of ``-quick`` is now deprecated (`#11280 `_, by Arthur CharguΓ©raud). - **Fixed:** ``coq_makefile`` does not break when using the ``CAMLPKGS`` variable together with an unpacked (``mllib``) plugin (`#11357 `_, by GaΓ«tan Gilbert). - **Fixed:** ``coqdoc`` with option ``-g`` (Gallina only) now correctly prints commands with attributes (`#11394 `_, fixes `#11353 `_, by Karl Palmskog). **CoqIDE** - **Changed:** CoqIDE now uses the GtkSourceView native implementation of the autocomplete mechanism (`#11400 `_, by Pierre-Marie PΓ©drot). **Standard library** - **Removed:** Export of module :g:`RList` in :g:`Ranalysis` and :g:`Ranalysis_reg`. Module :g:`RList` is still there but must be imported explicitly where required (`#11396 `_, by Michael Soegtrop). **Infrastructure and dependencies** - **Added:** Build date can now be overridden by setting the `SOURCE_DATE_EPOCH` environment variable (`#11227 `_, by Bernhard M. Wiedemann). Changes in 8.11.1 ~~~~~~~~~~~~~~~~~ **Kernel** - **Fixed:** Allow more inductive types in `Unset Positivity Checking` mode (`#11811 `_, by SimonBoulier). **Notations** - **Fixed:** Bugs in dealing with precedences of notations in custom entries (`#11530 `_, by Hugo Herbelin, fixing in particular `#9517 `_, `#9519 `_, `#9521 `_, `#11331 `_). - **Added:** In primitive floats, print a warning when parsing a decimal value that is not exactly a binary64 floating-point number. For instance, parsing 0.1 will print a warning whereas parsing 0.5 won't (`#11859 `_, by Pierre Roux). **CoqIDE** - **Fixed:** Compiling file paths containing spaces (`#10008 `_, by snyke7, fixing `#11595 `_). **Infrastructure and dependencies** - **Added:** Bump official OCaml support and CI testing to 4.10.0 (`#11131 `_, `#11123 `_, `#11102 `_, by Emilio Jesus Gallego Arias, Jacques-Henri Jourdan, Guillaume Melquiond, and Guillaume Munch-Maccagnoni). **Miscellaneous** - **Fixed:** :cmd:`Extraction Implicit` on the constructor of a record was leading to an anomaly (`#11329 `_, by Hugo Herbelin, fixes `#11114 `_). Changes in 8.11.2 ~~~~~~~~~~~~~~~~~ **Kernel** - **Fixed:** Using :cmd:`Require` inside a section caused an anomaly when closing the section. (`#11972 `_, by GaΓ«tan Gilbert, fixing `#11783 `_, reported by Attila Boros). **Tactics** - **Fixed:** Anomaly with induction schemes whose conclusion is not normalized (`#12116 `_, by Hugo Herbelin; fixes `#12045 `_) - **Fixed:** Loss of location of some tactic errors (`#12223 `_, by Hugo Herbelin; fixes `#12152 `_ and `#12255 `_). **Commands and options** - **Changed:** Ignore -native-compiler option when built without native compute support (`#12070 `_, by Pierre Roux). **CoqIDE** - **Changed:** CoqIDE now uses native window frames by default on Windows. The GTK window frames can be restored by setting the `GTK_CSD` environment variable to `1` (`#12060 `_, fixes `#11080 `_, by Attila GΓ‘spΓ‘r). - **Fixed:** New patch presumably fixing the random Coq 8.11 segfault issue with CoqIDE completion (`#12068 `_, by Hugo Herbelin, presumably fixing `#11943 `_). - **Fixed:** Highlighting style consistently applied to all three buffers of CoqIDE (`#12106 `_, by Hugo Herbelin; fixes `#11506 `_). Version 8.10 ------------ Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.10 contains two major new features: support for a native fixed-precision integer type and a new sort :math:`\SProp` of strict propositions. It is also the result of refinements and stabilization of previous features, deprecations or removals of deprecated features, cleanups of the internals of the system and API, and many documentation improvements. This release includes many user-visible changes, including deprecations that are documented in the next subsection, and new features that are documented in the reference manual. Here are the most important user-visible changes: - Kernel: - A notion of primitive object was added to the calculus. Its first instance is primitive cyclic unsigned integers, axiomatized in module :g:`UInt63`. See Section :ref:`primitive-integers`. The `Coq.Numbers.Cyclic.Int31` library is deprecated (`#6914 `_, by Maxime DΓ©nΓ¨s, Benjamin GrΓ©goire and Vincent Laporte, with help and reviews from many others). - The :math:`\SProp` sort of definitionally proof-irrelevant propositions was introduced. :math:`\SProp` allows to mark proof terms as irrelevant for conversion, and is treated like :math:`\Prop` during extraction. It is enabled using the `-allow-sprop` command-line flag or the :flag:`Allow StrictProp` flag. See Chapter :ref:`sprop` (`#8817 `_, by GaΓ«tan Gilbert). - The unfolding heuristic in termination checking was made more complete, allowing more constants to be unfolded to discover valid recursive calls. Performance regression may occur in Fixpoint declarations without an explicit ``{struct}`` annotation, since guessing the decreasing argument can now be more expensive (`#9602 `_, by Enrico Tassi). - Universes: - Added Subgraph variant to :cmd:`Print Universes`. Try for instance :g:`Print Universes Subgraph(sigT2.u1 sigT_of_sigT2.u1 projT3_eq.u1).` (`#8451 `_, by GaΓ«tan Gilbert). - Added private universes for opaque polymorphic constants, see the documentation for the :flag:`Private Polymorphic Universes` flag, and unset it to get the previous behavior (`#8850 `_, by GaΓ«tan Gilbert). - Notations: - New command :cmd:`String Notation` to register string syntax for custom inductive types (`#8965 `_, by Jason Gross). - Experimental: :ref:`Number Notations ` now parse decimal constants such as ``1.02e+01`` or ``10.2``. Parsers added for :g:`Q` and :g:`R`. In the rare case when such numeral notations were used in a development along with :g:`Q` or :g:`R`, they may have to be removed or disambiguated through explicit scope annotations (`#8764 `_, by Pierre Roux). - Ltac backtraces can be turned on using the :flag:`Ltac Backtrace` flag, which is off by default (`#9142 `_, fixes `#7769 `_ and `#7385 `_, by Pierre-Marie PΓ©drot). - The tactics :tacn:`lia`, :tacn:`nia`, :tacn:`lra`, :tacn:`nra` are now using a novel Simplex-based proof engine. In case of regression, unset `Simplex` to get the venerable Fourier-based engine (`#8457 `_, by FrΓ©deric Besson). - SSReflect: - New intro patterns: - temporary introduction: `=> +` - block introduction: `=> [^ prefix ] [^~ suffix ]` - fast introduction: `=> >` - tactics as views: `=> /ltac:mytac` - replace hypothesis: `=> {}H` See Section :ref:`introduction_ssr` (`#6705 `_, by Enrico Tassi, with help from Maxime DΓ©nΓ¨s, ideas coming from various users). - New tactic :tacn:`under` to rewrite under binders, given an extensionality lemma: - interactive mode: :n:`under @term`, associated terminator: :tacn:`over` - one-liner mode: :n:`under @term do [@tactic | ...]` It can take occurrence switches, contextual patterns, and intro patterns: :g:`under {2}[in RHS]eq_big => [i|i ?]` (`#9651 `_, by Erik Martin-Dorel and Enrico Tassi). - :cmd:`Combined Scheme` now works when inductive schemes are generated in sort :math:`\Type`. It used to be limited to sort `Prop` (`#7634 `_, by ThΓ©o Winterhalter). - A new registration mechanism for reference from ML code to Coq constructs has been added (`#186 `_, by Emilio JesΓΊs Gallego Arias, Maxime DΓ©nΓ¨s and Vincent Laporte). - CoqIDE: - CoqIDE now depends on gtk+3 and lablgtk3 instead of gtk+2 and lablgtk2. The INSTALL file available in the Coq sources has been updated to list the new dependencies (`#9279 `_, by Hugo Herbelin, with help from Jacques Garrigue, Emilio JesΓΊs Gallego Arias, Michael Sogetrop and Vincent Laporte). - Smart input for Unicode characters. For example, typing ``\alpha`` then ``Shift+Space`` will insert the greek letter alpha. A larger number of default bindings are provided, following the latex naming convention. Bindings can be customized, either globally, or on a per-project basis. See Section :ref:`rocqide-unicode` for details (`#8560 `_, by Arthur CharguΓ©raud). - Infrastructure and dependencies: - Coq 8.10 requires OCaml >= 4.05.0, bumped from 4.02.3 See the `INSTALL` file for more information on dependencies (`#7522 `_, by Emilio JesΓΊs Gallego ArΓ­as). - Coq 8.10 doesn't need Camlp5 to build anymore. It now includes a fork of the core parsing library that Coq uses, which is a small subset of the whole Camlp5 distribution. In particular, this subset doesn't depend on the OCaml AST, allowing easier compilation and testing on experimental OCaml versions. Coq also ships a new parser `coqpp` that plugin authors must switch to (`#7902 `_, `#7979 `_, `#8161 `_, `#8667 `_, and `#8945 `_, by Pierre-Marie PΓ©drot and Emilio JesΓΊs Gallego Arias). The Coq developers would like to thank Daniel de Rauglaudre for many years of continued support. - Coq now supports building with Dune, in addition to the traditional Makefile which is scheduled for deprecation (`#6857 `_, by Emilio JesΓΊs Gallego Arias, with help from Rudi Grinberg). Experimental support for building Coq projects has been integrated in Dune at the same time, providing an `improved experience `_ for plugin developers. We thank the Dune team for their work supporting Coq. Version 8.10 also comes with a bunch of smaller-scale changes and improvements regarding the different components of the system, including many additions to the standard library (see the next subsection for details). On the implementation side, the ``dev/doc/changes.md`` file documents the numerous changes to the implementation and improvements of interfaces. The file provides guidelines on porting a plugin to the new version and a plugin development tutorial originally made by Yves Bertot is now in `doc/plugin_tutorial`. The ``dev/doc/critical-bugs`` file documents the known critical bugs of Coq and affected releases. The efficiency of the whole system has seen improvements thanks to contributions from GaΓ«tan Gilbert, Pierre-Marie PΓ©drot, and Maxime DΓ©nΓ¨s. Maxime DΓ©nΓ¨s, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop, ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system and package building infrastructure. Coq is now continuously tested against the OCaml trunk, in addition to the oldest supported and latest OCaml releases. Coq's documentation for the development branch is now deployed continuously at https://coq.github.io/doc/master/api (documentation of the ML API), https://coq.github.io/doc/master/refman (reference manual), and https://coq.github.io/doc/master/stdlib (documentation of the standard library). Similar links exist for the `v8.10` branch. The opam repository for Coq packages has been maintained by Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi (who migrated it to opam 2) with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The 61 contributors to this version are Tanaka Akira, Benjamin Barenblat, Yves Bertot, FrΓ©dΓ©ric Besson, Lasse Blaauwbroek, Martin Bodin, Joachim Breitner, Tej Chajed, FrΓ©dΓ©ric Chapoton, Arthur CharguΓ©raud, Cyril Cohen, Lukasz Czajka, David A. Dalrymple, Christian Doczkal, Maxime DΓ©nΓ¨s, Andres Erbsen, Jim Fehrle, Emilio Jesus Gallego Arias, GaΓ«tan Gilbert, MatΔ›j GrabovskΓ½, Simon Gregersen, Jason Gross, Samuel Gruetter, Hugo Herbelin, Jasper Hugunin, Mirai Ikebuchi, Chantal Keller, Matej KoΕ‘Γ­k, Sam Pablo Kuper, Vincent Laporte, Olivier Laurent, Larry Darryl Lee Jr, Nick Lewycky, Yao Li, Yishuai Li, Assia Mahboubi, Simon Marechal, Erik Martin-Dorel, Thierry Martinez, Guillaume Melquiond, Kayla Ngan, Karl Palmskog, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Pierre Roux, Kazuhiko Sakaguchi, Ryan Scott, Vincent Semeria, Gan Shen, Michael Soegtrop, Matthieu Sozeau, Enrico Tassi, Laurent ThΓ©ry, Kamil TrzciΕ„ski, whitequark, ThΓ©o Winterhalter, Xia Li-yao, Beta Ziliani and ThΓ©o Zimmermann. Many power users helped to improve the design of the new features via the issue and pull request system, the Coq development mailing list, the coq-club@inria.fr mailing list or the new Discourse forum. It would be impossible to mention exhaustively the names of everybody who to some extent influenced the development. Version 8.10 is the fifth release of Coq developed on a time-based development cycle. Its development spanned 6 months from the release of Coq 8.9. Vincent Laporte is the release manager and maintainer of this release. This release is the result of ~2500 commits and ~650 PRs merged, closing 150+ issues. | Santiago de Chile, April 2019, | Matthieu Sozeau for the Coq development team | Other changes in 8.10+beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Command-line tools and options: - 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 (`#9095 `_, by Emilio JesΓΊs Gallego Arias). - 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 ``-topfile foolib/bar.v`` will set the module name to ``Foo.Bar``. CoqIDE now properly sets the module name for a given file based on its path (`#8991 `_, closes `#8989 `_, by GaΓ«tan Gilbert). - Experimental: Coq flags and options can now be set on the command-line, e.g. ``-set "Universe Polymorphism=true"`` (`#9876 `_, by GaΓ«tan Gilbert). - The `-native-compiler` flag of `coqc` and `coqtop` now takes an argument which can have three values: - `no` disables native_compute - `yes` enables native_compute and precompiles `.v` files to native code - `ondemand` enables native_compute but compiles code only when `native_compute` is called The default value is `ondemand`. Note that this flag now has priority over the configure flag of the same name. A new `-bytecode-compiler` flag for `coqc` and `coqtop` controls whether conversion can use the VM. The default value is `yes`. (`#8870 `_, by Maxime DΓ©nΓ¨s) - The pretty timing diff scripts (flag `TIMING=1` to a `coq_makefile`\-made `Makefile`, also `tools/make-both-single-timing-files.py`, `tools/make-both-time-files.py`, and `tools/make-one-time-file.py`) now correctly support non-UTF-8 characters in the output of `coqc` / `make` as well as printing to stdout, on both python2 and python3 (`#9872 `_, closes `#9767 `_ and `#9705 `_, by Jason Gross) - coq_makefile's install target now errors if any file to install is missing (`#9906 `_, by GaΓ«tan Gilbert). - Preferences from ``coqide.keys`` are no longer overridden by modifiers preferences in ``coqiderc`` (`#10014 `_, by Hugo Herbelin). - Specification language, type inference: - Fixing a missing check in interpreting instances of existential variables that are bound to local definitions. Might exceptionally induce an overhead if the cost of checking the conversion of the corresponding definitions is additionally high (`#8217 `_, closes `#8215 `_, by Hugo Herbelin). - A few improvements in inference of the return clause of `match` that can exceptionally introduce incompatibilities. This can be solved by writing an explicit `return` clause, sometimes even simply an explicit `return _` clause (`#262 `_, by Hugo Herbelin). - Using non-projection values with the projection syntax is not allowed. For instance :g:`0.(S)` is not a valid way to write :g:`S 0`. Projections from non-primitive (emulated) records are allowed with warning "nonprimitive-projection-syntax" (`#8829 `_, by GaΓ«tan Gilbert). - An option and attributes to control the automatic decision to declare an inductive type as template polymorphic were added. Warning "auto-template" (off by default) can trigger when an inductive is automatically declared template polymorphic without the attribute. Inductive types declared by Funind will never be template polymorphic. (`#8488 `_, by GaΓ«tan Gilbert) - Notations: - New command :cmd:`Declare Scope` to explicitly declare a scope name before any use of it. Implicit declaration of a scope at the time of :cmd:`Bind Scope`, :cmd:`Delimit Scope`, :cmd:`Undelimit Scope`, or :cmd:`Notation` is deprecated (`#7135 `_, by Hugo Herbelin). - Various bugs have been fixed (e.g. `#9214 `_ on removing spurious parentheses on abbreviations shortening a strict prefix of an application, by Hugo Herbelin). - :cmd:`Number Notation` now support inductive types in the input to printing functions (e.g., numeral notations can be defined for terms containing things like :g:`@cons nat O O`), and parsing functions now fully normalize terms including parameters of constructors (so that, e.g., a numeral notation whose parsing function outputs a proof of :g:`Nat.gcd x y = 1` will no longer fail to parse due to containing the constant :g:`Nat.gcd` in the parameter-argument of :g:`eq_refl`) (`#9874 `_, closes `#9840 `_ and `#9844 `_, by Jason Gross). - Deprecated compatibility notations have actually been removed. Uses of these notations are generally easy to fix thanks to the hint contained in the deprecation warning emitted by Coq 8.8 and 8.9. For projects that require more than a handful of such fixes, there is `a script `_ that will do it automatically, using the output of ``coqc`` (`#8638 `_, by Jason Gross). - Allow inspecting custom grammar entries by :cmd:`Print Custom Grammar` (`#10061 `_, fixes `#9681 `_, by Jasper Hugunin, review by Pierre-Marie PΓ©drot and Hugo Herbelin). - The `quote plugin `_ was removed. If some users are interested in maintaining this plugin externally, the Coq development team can provide assistance for extracting the plugin and setting up a new repository (`#7894 `_, by Maxime DΓ©nΓ¨s). - Ltac: - Tactic names are no longer allowed to clash, even if they are not defined in the same section. For example, the following is no longer accepted: :g:`Ltac foo := idtac. Section S. Ltac foo := fail. End S.` (`#8555 `_, by Maxime DΓ©nΓ¨s). - Names of existential variables occurring in Ltac functions (e.g. :g:`?[n]` or :g:`?n` in terms - not in patterns) are now interpreted the same way as other variable names occurring in Ltac functions (`#7309 `_, by Hugo Herbelin). - Tactics: - Removed the deprecated `romega` tactic (`#8419 `_, by Maxime DΓ©nΓ¨s and Vincent Laporte). - Hint declaration and removal should now specify a database (e.g. `Hint Resolve foo : database`). When the database name is omitted, the hint is added to the `core` database (as previously), but a deprecation warning is emitted (`#8987 `_, by Maxime DΓ©nΓ¨s). - 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 :tacn:`lia`, :tacn:`nia`, 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 (`#8062 `_, by Jason Gross). - The syntax of the :tacn:`autoapply` tactic was fixed to conform with preexisting documentation: it now takes a `with` clause instead of a `using` clause (`#9524 `_, closes `#7632 `_, by ThΓ©o Zimmermann). - Modes are now taken into account by :tacn:`typeclasses eauto` for local hypotheses (`#9996 `_, fixes `#5752 `_, by Maxime DΓ©nΓ¨s, review by Pierre-Marie PΓ©drot). - New variant :tacn:`change_no_check` of :tacn:`change`, usable as a documented replacement of `convert_concl_no_check` (`#10012 `_, `#10017 `_, `#10053 `_, and `#10059 `_, by Hugo Herbelin and Paolo G. Giarrusso). - The simplified value returned by :tacn:`field_simplify` is not always a fraction anymore. When the denominator is :g:`1`, it returns :g:`x` while previously it was returning :g:`x/1`. This change could break codes that were post-processing application of :tacn:`field_simplify` to get rid of these :g:`x/1` (`#9854 `_, by Laurent ThΓ©ry, with help from Michael Soegtrop, Maxime DΓ©nΓ¨s, and Vincent Laporte). - SSReflect: - 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}` (`#9341 `_, by Enrico Tassi). - `inE` now expands `y \in r x` when `r` is a `simpl_rel`. New `{pred T}` notation for a `pred T` alias in the `pred_sort` coercion class, simplified `predType` interface: `pred_class` and `mkPredType` deprecated, `{pred T}` and `PredType` should be used instead. `if c return t then ...` now expects `c` to be a variable bound in `t`. New `nonPropType` interface matching types that do _not_ have sort `Prop`. New `relpre R f` definition for the preimage of a relation R under f (`#9995 `_, by Georges Gonthier). - Commands: - Binders for an :cmd:`Instance` now act more like binders for a :cmd:`Theorem`. Names may not be repeated, and may not overlap with section variable names (`#8820 `_, closes `#8791 `_, by Jasper Hugunin). - Removed the deprecated `Implicit Tactic` family of commands (`#8779 `_, by Pierre-Marie PΓ©drot). - The `Automatic Introduction` option has been removed and is now the default (`#9001 `_, by Emilio JesΓΊs Gallego Arias). - `Arguments` now accepts names for arguments provided with `extra_scopes` (`#9117 `_, by Maxime DΓ©nΓ¨s). - The naming scheme for anonymous binders in a `Theorem` has changed to avoid conflicts with explicitly named binders (`#9160 `_, closes `#8819 `_, by Jasper Hugunin). - Computation of implicit arguments now properly handles local definitions in the binders for an `Instance`, and can be mixed with implicit binders `{x : T}` (`#9307 `_, closes `#9300 `_, by Jasper Hugunin). - :cmd:`Declare Instance` now requires an instance name. The flag `Refine Instance Mode` has been turned off by default, meaning that :cmd:`Instance` no longer opens a proof when a body is provided. The flag has been deprecated and will be removed in the next version. (`#9270 `_, and `#9825 `_, by Maxime DΓ©nΓ¨s) - Command :cmd:`Instance`, when no body is provided, now always opens a proof. This is a breaking change, as instance of :n:`Instance @ident__1 : @ident__2.` where :n:`@ident__2` is a trivial class will have to be changed into :n:`Instance @ident__1 : @ident__2 := %{%}.` or :n:`Instance @ident__1 : @ident__2. Proof. Qed.` (`#9274 `_, by Maxime DΓ©nΓ¨s). - The flag :flag:`Program Mode` now means that the `Program` attribute is enabled for all commands that support it. In particular, it does not have any effect on tactics anymore. May cause some incompatibilities (`#9410 `_, by Maxime DΓ©nΓ¨s). - The algorithm computing implicit arguments now behaves uniformly for primitive projection and application nodes (`#9509 `_, closes `#9508 `_, by Pierre-Marie PΓ©drot). - :cmd:`Hypotheses` and :cmd:`Variables` can now take implicit binders inside sections (`#9364 `_, closes `#9363 `_, by Jasper Hugunin). - Removed deprecated option `Automatic Coercions Import` (`#8094 `_, by Maxime DΓ©nΓ¨s). - The ``Show Script`` command has been deprecated (`#9829 `_, by Vincent Laporte). - :cmd:`Coercion` does not warn ambiguous paths which are obviously convertible with existing ones. The ambiguous paths messages have been turned to warnings, thus now they could appear in the output of ``coqc``. The convertibility checking procedure for coercion paths is complete for paths consisting of coercions satisfying the uniform inheritance condition, but some coercion paths could be reported as ambiguous even if they are convertible with existing ones when they have coercions that don't satisfy the uniform inheritance condition (`#9743 `_, closes `#3219 `_, by Kazuhiko Sakaguchi). - A new flag :flag:`Fast Name Printing` has been introduced. It changes the algorithm used for allocating bound variable names for a faster but less clever one (`#9078 `_, by Pierre-Marie PΓ©drot). - Option ``Typeclasses Axioms Are Instances`` (compatibility option introduced in the previous version) is deprecated. Use :cmd:`Declare Instance` for axioms which should be instances (`#8920 `_, by GaΓ«tan Gilbert). - Removed option `Printing Primitive Projection Compatibility` (`#9306 `_, by GaΓ«tan Gilbert). - Standard Library: - Added `Bvector.BVeq` that decides whether two `Bvector`\s are equal. Added notations for `BVxor`, `BVand`, `BVor`, `BVeq` and `BVneg` (`#8171 `_, by Yishuai Li). - Added `ByteVector` type that can convert to and from `string` (`#8365 `_, by Yishuai Li). - Added lemmas about monotonicity of `N.double` and `N.succ_double`, and about the upper bound of number represented by a vector. Allowed implicit vector length argument in `Ndigits.Bv2N` (`#8815 `_, by Yishuai Li). - The prelude used to be automatically Exported and is now only Imported. This should be relevant only when importing files which don't use `-noinit` into files which do (`#9013 `_, by GaΓ«tan Gilbert). - Added `Coq.Structures.OrderedTypeEx.String_as_OT` to make strings an ordered type, using lexical order (`#7221 `_, by Li Yao). - Added lemmas about `Z.testbit`, `Z.ones`, and `Z.modulo` (`#9425 `_, by Andres Erbsen). - Moved the `auto` hints of the `FSet` library into a new `fset` database (`#9725 `_, by FrΓ©dΓ©ric Besson). - Added :g:`Coq.Structures.EqualitiesFacts.PairUsualDecidableTypeFull` (`#9984 `_, by Jean-Christophe LΓ©chenet and Oliver Nash). - Some error messages that show problems with a pair of non-matching values will now highlight the differences (`#8669 `_, by Jim Fehrle). - Changelog has been moved from a specific file `CHANGES.md` to the reference manual; former Credits chapter of the reference manual has been split in two parts: a History chapter which was enriched with additional historical information about Coq versions 1 to 5, and a Changes chapter which was enriched with the content formerly in `CHANGES.md` and `COMPATIBILITY` (`#9133 `_, `#9668 `_, `#9939 `_, `#9964 `_, and `#10085 `_, by ThΓ©o Zimmermann, with help and ideas from Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, ClΓ©ment Pit-Claudel, Matthieu Sozeau, and Enrico Tassi). Changes in 8.10+beta2 ~~~~~~~~~~~~~~~~~~~~~ Many bug fixes and documentation improvements, in particular: **Tactics** - Make the :tacn:`discriminate` tactic work together with :flag:`Universe Polymorphism` and equality in :g:`Type`. This, in particular, makes :tacn:`discriminate` compatible with the HoTT library https://github.com/HoTT/HoTT (`#10205 `_, by Andreas Lynge, review by Pierre-Marie PΓ©drot and Matthieu Sozeau). **SSReflect** - Make the ``case E: t`` tactic work together with :flag:`Universe Polymorphism` and equality in :g:`Type`. This makes :tacn:`case ` compatible with the HoTT library https://github.com/HoTT/HoTT (`#10302 `_, fixes `#10301 `_, by Andreas Lynge, review by Enrico Tassi) - Make the ``rewrite /t`` tactic work together with :flag:`Universe Polymorphism`. This makes :tacn:`rewrite ` compatible with the HoTT library https://github.com/HoTT/HoTT (`#10305 `_, fixes `#9336 `_, by Andreas Lynge, review by Enrico Tassi) **CoqIDE** - Fix CoqIDE instability on Windows after the update to gtk3 (`#10360 `_, by Michael Soegtrop, closes `#9885 `_). **Miscellaneous** - Proof General can now display Coq-generated diffs between proof steps in color (`#10019 `_ and (in Proof General) `#421 `_, by Jim Fehrle). Changes in 8.10+beta3 ~~~~~~~~~~~~~~~~~~~~~ **Kernel** - Fix soundness issue with template polymorphism (`#9294 `_). Declarations of template-polymorphic inductive types ignored the provenance of the universes they were abstracting on and did not detect if they should be greater or equal to :math:`\Set` in general. Previous universes and universes introduced by the inductive definition could have constraints that prevented their instantiation with e.g. :math:`\Prop`, resulting in unsound instantiations later. The implemented fix only allows abstraction over universes introduced by the inductive declaration, and properly records all their constraints by making them by default only :math:`>= \Prop`. It is also checked that a template polymorphic inductive actually is polymorphic on at least one universe. This prevents inductive declarations in sections to be universe polymorphic over section parameters. For a backward compatible fix, simply hoist the inductive definition out of the section. An alternative is to declare the inductive as universe-polymorphic and cumulative in a universe-polymorphic section: all universes and constraints will be properly gathered in this case. See :ref:`Template-polymorphism` for a detailed exposition of the rules governing template-polymorphic types. To help users incrementally fix this issue, a command line option `-no-template-check` and a global flag ``Template Check`` are available to selectively disable the new check. Use at your own risk. (`#9918 `_, by Matthieu Sozeau and Maxime DΓ©nΓ¨s). **User messages** - Improve the ambiguous paths warning to indicate which path is ambiguous with new one (`#10336 `_, closes `#3219 `_, by Kazuhiko Sakaguchi). **Extraction** - Fix extraction to OCaml of primitive machine integers; see :ref:`primitive-integers` (`#10430 `_, fixes `#10361 `_, by Vincent Laporte). - Fix a printing bug of OCaml extraction on dependent record projections, which produced improper `assert false`. This change makes the OCaml extractor internally inline record projections by default; thus the monolithic OCaml extraction (:cmd:`Extraction` and :cmd:`Recursive Extraction`) does not produce record projection constants anymore except for record projections explicitly instructed to extract, and records declared in opaque modules (`#10577 `_, fixes `#7348 `_, by Kazuhiko Sakaguchi). **Standard library** - Added ``splitat`` function and lemmas about ``splitat`` and ``uncons`` (`#9379 `_, by Yishuai Li, with help of Konstantinos Kallas, follow-up of `#8365 `_, which added ``uncons`` in 8.10+beta1). Changes in 8.10.0 ~~~~~~~~~~~~~~~~~ - Micromega tactics (:tacn:`lia`, :tacn:`nia`, etc) are no longer confused by primitive projections (`#10806 `_, fixes `#9512 `_ by Vincent Laporte). Changes in 8.10.1 ~~~~~~~~~~~~~~~~~ A few bug fixes and documentation improvements, in particular: **Kernel** - Fix proof of False when using |SProp| (incorrect De Bruijn handling when inferring the relevance mark of a function) (`#10904 `_, by Pierre-Marie PΓ©drot). **Tactics** - Fix an anomaly when unsolved evar in :cmd:`Add Ring` (`#10891 `_, fixes `#9851 `_, by GaΓ«tan Gilbert). **Tactic language** - Fix Ltac regression in binding free names in uconstr (`#10899 `_, fixes `#10894 `_, by Hugo Herbelin). **CoqIDE** - Fix handling of unicode input before space (`#10852 `_, fixes `#10842 `_, by Arthur CharguΓ©raud). **Extraction** - Fix custom extraction of inductives to JSON (`#10897 `_, fixes `#4741 `_, by Helge Bahmann). Changes in 8.10.2 ~~~~~~~~~~~~~~~~~ **Kernel** - Fixed a critical bug of template polymorphism and nonlinear universes (`#11128 `_, fixes `#11039 `_, by GaΓ«tan Gilbert). - Fixed an anomaly β€œUncaught exception Constr.DestKO” on :g:`Inductive` (`#11052 `_, fixes `#11048 `_, by GaΓ«tan Gilbert). - Fixed an anomaly β€œnot enough abstractions in fix body” (`#11014 `_, fixes `#8459 `_, by GaΓ«tan Gilbert). **Notations** - Fixed an 8.10 regression related to the printing of coercions associated with notations (`#11090 `_, fixes `#11033 `_, by Hugo Herbelin). **CoqIDE** - Fixed uneven dimensions of CoqIDE panels when window has been resized (`#11070 `_, fixes 8.10-regression `#10956 `_, by Guillaume Melquiond). - Do not include final stops in queries (`#11069 `_, fixes 8.10-regression `#11058 `_, by Guillaume Melquiond). **Infrastructure and dependencies** - Enable building of executables when they are running (`#11000 `_, fixes 8.9-regression `#10728 `_, by GaΓ«tan Gilbert). Version 8.9 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.9 contains the result of refinements and stabilization of features and deprecations or removals of deprecated features, cleanups of the internals of the system and API along with a few new features. This release includes many user-visible changes, including deprecations that are documented in the next subsection and new features that are documented in the reference manual. Here are the most important changes: - Kernel: mutually recursive records are now supported, by Pierre-Marie PΓ©drot. - Notations: - Support for autonomous grammars of terms called β€œcustom entries”, by Hugo Herbelin (see Section :ref:`custom-entries` of the reference manual). - Deprecated notations of the standard library will be removed in the next version of Coq, see the next subsection for a script to ease porting, by Jason Gross and Jean-Christophe LΓ©chenet. - Added the :cmd:`Number Notation` command for registering decimal numeral notations for custom types, by Daniel de Rauglaudre, Pierre Letouzey and Jason Gross. - Tactics: Introduction tactics :tacn:`intro`/:tacn:`intros` on a goal that is an existential variable now force a refinement of the goal into a dependent product rather than failing, by Hugo Herbelin. - Decision procedures: deprecation of tactic ``romega`` in favor of :tacn:`lia` and removal of ``fourier``, replaced by :tacn:`lra` which subsumes it, by FrΓ©dΓ©ric Besson, Maxime DΓ©nΓ¨s, Vincent Laporte and Laurent ThΓ©ry. - Proof language: focusing bracket ``{`` now supports named :ref:`goals `, e.g. ``[x]:{`` will focus on a goal (existential variable) named ``x``, by ThΓ©o Zimmermann. - SSReflect: the implementation of delayed clear was simplified by Enrico Tassi: the variables are always renamed using inaccessible names when the clear switch is processed and finally cleared at the end of the intro pattern. In addition to that, the use-and-discard flag ``{}`` typical of rewrite rules can now be also applied to views, e.g. ``=> {}/v`` applies ``v`` and then clears ``v``. See Section :ref:`introduction_ssr`. - Vernacular: - Experimental support for :term:`attributes ` on commands, by Vincent Laporte, as in ``#[local] Lemma foo : bar.`` Tactics and tactic notations now support the ``deprecated`` attribute. - Removed deprecated commands ``Arguments Scope`` and ``Implicit Arguments`` in favor of :cmd:`Arguments`, with the help of Jasper Hugunin. - New flag :flag:`Uniform Inductive Parameters` by Jasper Hugunin to avoid repeating uniform parameters in constructor declarations. - New commands :cmd:`Hint Variables` and :cmd:`Hint Constants`, by Matthieu Sozeau, for controlling the opacity status of variables and constants in hint databases. It is recommended to always use these commands after creating a hint database with :cmd:`Create HintDb`. - Multiple sections with the same name are now allowed, by Jasper Hugunin. - Library: additions and changes in the ``VectorDef``, ``Ascii``, and ``String`` libraries. Syntax notations are now available only when using ``Import`` of libraries and not merely ``Require``, by various contributors (source of incompatibility, see the next subsection for details). - Toplevels: ``coqtop`` and ``coqide`` can now display diffs between proof steps in color, using the :opt:`Diffs` option, by Jim Fehrle. - Documentation: we integrated a large number of fixes to the new Sphinx documentation by various contributors, coordinated by ClΓ©ment Pit-Claudel and ThΓ©o Zimmermann. - Tools: removed the ``gallina`` utility and the homebrewed ``Emacs`` mode. - Packaging: as in Coq 8.8.2, the Windows installer now includes many more external packages that can be individually selected for installation, by Michael Soegtrop. Version 8.9 also comes with a bunch of smaller-scale changes and improvements regarding the different components of the system. Most important ones are documented in the next subsection file. On the implementation side, the ``dev/doc/changes.md`` file documents the numerous changes to the implementation and improvements of interfaces. The file provides guidelines on porting a plugin to the new version and a plugin development tutorial kept in sync with Coq was introduced by Yves Bertot http://github.com/ybertot/plugin_tutorials. The new ``dev/doc/critical-bugs`` file documents the known critical bugs of Coq and affected releases. The efficiency of the whole system has seen improvements thanks to contributions from GaΓ«tan Gilbert, Pierre-Marie PΓ©drot, and Maxime DΓ©nΓ¨s. Maxime DΓ©nΓ¨s, Emilio JesΓΊs Gallego Arias, GaΓ«tan Gilbert, Michael Soegtrop, ThΓ©o Zimmermann worked on maintaining and improving the continuous integration system. The opam repository for Coq packages has been maintained by Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The 54 contributors for this version are LΓ©o AndrΓ¨s, Rin Arakaki, Benjamin Barenblat, Langston Barrett, Siddharth Bhat, Martin Bodin, Simon Boulier, Timothy Bourke, Joachim Breitner, Tej Chajed, Arthur CharguΓ©raud, Pierre Courtieu, Maxime DΓ©nΓ¨s, Andres Erbsen, Jim Fehrle, Julien Forest, Emilio Jesus Gallego Arias, GaΓ«tan Gilbert, MatΔ›j GrabovskΓ½, Jason Gross, Samuel Gruetter, ArmaΓ«l GuΓ©neau, Hugo Herbelin, Jasper Hugunin, Ralf Jung, Sam Pablo Kuper, Ambroise Lafont, Leonidas Lampropoulos, Vincent Laporte, Peter LeFanu Lumsdaine, Pierre Letouzey, Jean-Christophe LΓ©chenet, Nick Lewycky, Yishuai Li, Sven M. Hallberg, Assia Mahboubi, Cyprien Mangin, Guillaume Melquiond, Perry E. Metzger, ClΓ©ment Pit-Claudel, Pierre-Marie PΓ©drot, Daniel R. Grayson, Kazuhiko Sakaguchi, Michael Soegtrop, Matthieu Sozeau, Paul Steckler, Enrico Tassi, Laurent ThΓ©ry, Anton Trunov, whitequark, ThΓ©o Winterhalter, Zeimer, Beta Ziliani, ThΓ©o Zimmermann. Many power users helped to improve the design of the new features via the issue and pull request system, the Coq development mailing list or the coq-club@inria.fr mailing list. It would be impossible to mention exhaustively the names of everybody who to some extent influenced the development. Version 8.9 is the fourth release of Coq developed on a time-based development cycle. Its development spanned 7 months from the release of Coq 8.8. The development moved to a decentralized merging process during this cycle. Guillaume Melquiond was in charge of the release process and is the maintainer of this release. This release is the result of ~2,000 commits and ~500 PRs merged, closing 75+ issues. The Coq development team welcomed Vincent Laporte, a new Coq engineer working with Maxime DΓ©nΓ¨s in the Coq consortium. | Paris, November 2018, | Matthieu Sozeau for the Coq development team | Details of changes in 8.9+beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kernel - Mutually defined records are now supported. Notations - New support for autonomous grammars of terms, called "custom entries" (see chapter "Syntax extensions" of the reference manual). - Deprecated compatibility notations will actually be removed in the next version of Coq. Uses of these notations are generally easy to fix thanks to the hint contained in the deprecation warnings. For projects that require more than a handful of such fixes, there is `a script `_ that will do it automatically, using the output of ``coqc``. The script contains documentation on its usage in a comment at the top. Tactics - Added toplevel goal selector `!` which expects a single focused goal. Use with `Set Default Goal Selector` to force focusing before tactics are called. - The undocumented "nameless" forms `fix N`, `cofix` that were deprecated in 8.8 have been removed from Ltac's syntax; please use `fix ident N/cofix ident` to explicitly name the (co)fixpoint hypothesis to be introduced. - Introduction tactics `intro`/`intros` on a goal that is an existential variable now force a refinement of the goal into a dependent product rather than failing. - Support for `fix`/`cofix` added in Ltac `match` and `lazymatch`. - Ltac backtraces now include trace information about tactics called by OCaml-defined tactics. - Option `Ltac Debug` now applies also to terms built using Ltac functions. - Deprecated the `Implicit Tactic` family of commands. - The default program obligation tactic uses a bounded proof search instead of an unbounded and potentially non-terminating one now (source of incompatibility). - The `simple apply` tactic now respects the `Opaque` flag when called from Ltac (`auto` still does not respect it). - Tactic `constr_eq` now adds universe constraints needed for the identity to the context (it used to ignore them). New tactic `constr_eq_strict` checks that the required constraints already hold without adding new ones. Preexisting tactic `constr_eq_nounivs` can still be used if you really want to ignore universe constraints. - Tactics and tactic notations now understand the `deprecated` attribute. - The `fourier` tactic has been removed. Please now use `lra` instead. You may need to add `Require Import Lra` to your developments. For compatibility, we now define `fourier` as a deprecated alias of `lra`. - The `romega` tactics have been deprecated; please use `lia` instead. Focusing - Focusing bracket `{` now supports named goal selectors, e.g. `[x]: {` will focus on a goal (existential variable) named `x`. As usual, unfocus with `}` once the subgoal is fully solved. Specification language - A fix to unification (which was sensitive to the ascii name of variables) may occasionally change type inference in incompatible ways, especially regarding the inference of the return clause of `match`. Standard Library - Added `Ascii.eqb` and `String.eqb` and the `=?` notation for them, and proved some lemmas about them. Note that this might cause incompatibilities if you have, e.g., `string_scope` and `Z_scope` both open with `string_scope` on top, and expect `=?` to refer to `Z.eqb`. Solution: wrap `_ =? _` in `(_ =? _)%Z` (or whichever scope you want). - Added `Ndigits.N2Bv_sized`, and proved some lemmas about it. Deprecated `Ndigits.N2Bv_gen`. - The scopes `int_scope` and `uint_scope` have been renamed to `dec_int_scope` and `dec_uint_scope`, to clash less with ssreflect and other packages. They are still delimited by `%int` and `%uint`. - Syntax notations for `string`, `ascii`, `Z`, `positive`, `N`, `R`, and `int31` are no longer available merely by :cmd:`Require`\ing the files that define the inductives. You must :cmd:`Import` `Coq.Strings.String.StringSyntax` (after `Require` `Coq.Strings.String`), `Coq.Strings.Ascii.AsciiSyntax` (after `Require` `Coq.Strings.Ascii`), `Coq.ZArith.BinIntDef`, `Coq.PArith.BinPosDef`, `Coq.NArith.BinNatDef`, `Coq.Reals.Rdefinitions`, and `Coq.Numbers.Cyclic.Int31.Int31`, respectively, to be able to use these notations. Note that passing `-compat 8.8` or issuing `Require Import Coq.Compat.Coq88` will make these notations available. Users wishing to port their developments automatically may download `fix.py` from https://gist.github.com/JasonGross/5d4558edf8f5c2c548a3d96c17820169 and run a command like `while true; do make -Okj 2>&1 | /path/to/fix.py; done` and get a cup of coffee. (This command must be manually interrupted once the build finishes all the way though. Note also that this method is not fail-proof; you may have to adjust some scopes if you were relying on string notations not being available even when `string_scope` was open.) - Numeral syntax for `nat` is no longer available without loading the entire prelude (`Require Import Coq.Init.Prelude`). This only impacts users running Coq without the init library (`-nois` or `-noinit`) and also issuing `Require Import Coq.Init.Datatypes`. Tools - Coq_makefile lets one override or extend the following variables from the command line: `COQFLAGS`, `COQCHKFLAGS`, `COQDOCFLAGS`. `COQFLAGS` is now entirely separate from `COQLIBS`, so in custom Makefiles `$(COQFLAGS)` should be replaced by `$(COQFLAGS) $(COQLIBS)`. - Removed the `gallina` utility (extracts specification from Coq vernacular files). If you would like to maintain this tool externally, please contact us. - Removed the Emacs modes distributed with Coq. You are advised to use `Proof-General `_ (and optionally `Company-Coq `_) instead. If your use case is not covered by these alternative Emacs modes, please open an issue. We can help set up external maintenance as part of Proof-General, or independently as part of coq-community. Commands - Removed deprecated commands `Arguments Scope` and `Implicit Arguments` (not the option). Use the `Arguments` command instead. - Nested proofs may be enabled through the option `Nested Proofs Allowed`. By default, they are disabled and produce an error. The deprecation warning which used to occur when using nested proofs has been removed. - Added option `Uniform Inductive Parameters` which abstracts over parameters before typechecking constructors, allowing to write for example `Inductive list (A : Type) := nil : list | cons : A -> list -> list.` - New `Set Hint Variables/Constants Opaque/Transparent` commands for setting globally the opacity flag of variables and constants in hint databases, overriding the opacity setting of the hint database. - Added generic syntax for "attributes", as in: `#[local] Lemma foo : bar.` - Added the `Numeral Notation` command for registering decimal numeral notations for custom types - The `Set SsrHave NoTCResolution` command no longer has special global scope. If you want the previous behavior, use `Global Set SsrHave NoTCResolution`. - Multiple sections with the same name are allowed. Coq binaries and process model - Before 8.9, Coq distributed a single `coqtop` binary and a set of dynamically loadable plugins that used to take over the main loop for tasks such as IDE language server or parallel proof checking. These plugins have been turned into full-fledged binaries so each different process has associated a particular binary now, in particular `coqidetop` is the CoqIDE language server, and `coq{proof,tactic,query}worker` are in charge of task-specific and parallel proof checking. SSReflect - The implementation of delayed clear switches in intro patterns is now simpler to explain: 1. The immediate effect of a clear switch like `{x}` is to rename the variable `x` to `_x_` (i.e. a reserved identifier that cannot be mentioned explicitly) 2. The delayed effect of `{x}` is that `_x_` is cleared at the end of the intro pattern 3. A clear switch immediately before a view application like `{x}/v` is translated to `/v{x}`. In particular, the third rule lets one write `{x}/v` even if `v` uses the variable `x`: indeed the view is executed before the renaming. - An empty clear switch is now accepted in intro patterns before a view application whenever the view is a variable. One can now write `{}/v` to mean `{v}/v`. Remark that `{}/x` is very similar to the idiom `{}e` for the rewrite tactic (the equation `e` is used for rewriting and then discarded). Standard Library - There are now conversions between `string` and `positive`, `Z`, `nat`, and `N` in binary, octal, and hex. Display diffs between proof steps - `coqtop` and `coqide` can now highlight the differences between proof steps in color. This can be enabled from the command line or the `Set Diffs "on"/"off"/"removed"` command. Please see the documentation for details. Showing diffs in Proof General requires small changes to PG (under discussion). Notations - Added `++` infix for `VectorDef.append`. Note that this might cause incompatibilities if you have, e.g., `list_scope` and `vector_scope` both open with `vector_scope` on top, and expect `++` to refer to `app`. Solution: wrap `_ ++ _` in `(_ ++ _)%list` (or whichever scope you want). Changes in 8.8.0 ~~~~~~~~~~~~~~~~ Various bug fixes. Changes in 8.8.1 ~~~~~~~~~~~~~~~~ - Some quality-of-life fixes. - Numerous improvements to the documentation. - Fix a critical bug related to primitive projections and :tacn:`native_compute`. - Ship several additional Coq libraries with the Windows installer. Version 8.8 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.8 contains the result of refinements and stabilization of features and deprecations, cleanups of the internals of the system along with a few new features. The main user visible changes are: - Kernel: fix a subject reduction failure due to allowing fixpoints on non-recursive values, by Matthieu Sozeau. Handling of evars in the VM (the kernel still does not accept evars) by Pierre-Marie PΓ©drot. - Notations: many improvements on recursive notations and support for destructuring patterns in the syntax of notations by Hugo Herbelin. - Proof language: tacticals for profiling, timing and checking success or failure of tactics by Jason Gross. The focusing bracket ``{`` supports single-numbered goal selectors, e.g. ``2:{``, by ThΓ©o Zimmermann. - Vernacular: deprecation of commands and more uniform handling of the ``Local`` flag, by Vincent Laporte and Maxime DΓ©nΓ¨s, part of a larger attribute system overhaul. Experimental ``Show Extraction`` command by Pierre Letouzey. Coercion now accepts ``Prop`` or ``Type`` as a source by Arthur CharguΓ©raud. ``Export`` modifier for options allowing to export the option to modules that ``Import`` and not only ``Require`` a module, by Pierre-Marie PΓ©drot. - Universes: many user-level and API level enhancements: qualified naming and printing, variance annotations for cumulative inductive types, more general constraints and enhancements of the minimization heuristics, interaction with modules by GaΓ«tan Gilbert, Pierre-Marie PΓ©drot and Matthieu Sozeau. - Library: Decimal Numbers library by Pierre Letouzey and various small improvements. - Documentation: a large community effort resulted in the migration of the reference manual to the Sphinx documentation tool. The result is this manual. The new documentation infrastructure (based on Sphinx) is by ClΓ©ment Pit-Claudel. The migration was coordinated by Maxime DΓ©nΓ¨s and Paul Steckler, with some help of ThΓ©o Zimmermann during the final integration phase. The 14 people who ported the manual are Calvin Beck, Heiko Becker, Yves Bertot, Maxime DΓ©nΓ¨s, Richard Ford, Pierre Letouzey, Assia Mahboubi, ClΓ©ment Pit-Claudel, Laurence Rideau, Matthieu Sozeau, Paul Steckler, Enrico Tassi, Laurent ThΓ©ry, Nikita Zyuzin. - Tools: experimental ``-mangle-names`` option to ``coqtop``/``coqc`` for linting proof scripts, by Jasper Hugunin. On the implementation side, the ``dev/doc/changes.md`` file documents the numerous changes to the implementation and improvements of interfaces. The file provides guidelines on porting a plugin to the new version. Version 8.8 also comes with a bunch of smaller-scale changes and improvements regarding the different components of the system. Most important ones are documented in the next subsection file. The efficiency of the whole system has seen improvements thanks to contributions from GaΓ«tan Gilbert, Pierre-Marie PΓ©drot, Maxime DΓ©nΓ¨s and Matthieu Sozeau and performance issue tracking by Jason Gross and Paul Steckler. The official wiki and the bugtracker of Coq migrated to the GitHub platform, thanks to the work of Pierre Letouzey and ThΓ©o Zimmermann. GaΓ«tan Gilbert, Emilio JesΓΊs Gallego Arias worked on maintaining and improving the continuous integration system. The opam repository for Coq packages has been maintained by Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. The 44 contributors for this version are Yves Bertot, Joachim Breitner, Tej Chajed, Arthur CharguΓ©raud, Jacques-Pascal Deplaix, Maxime DΓ©nΓ¨s, Jim Fehrle, Julien Forest, Yannick Forster, GaΓ«tan Gilbert, Jason Gross, Samuel Gruetter, Thomas Hebb, Hugo Herbelin, Jasper Hugunin, Emilio Jesus Gallego Arias, Ralf Jung, Johannes Kloos, Matej KoΕ‘Γ­k, Robbert Krebbers, Tony Beta Lambda, Vincent Laporte, Peter LeFanu Lumsdaine, Pierre Letouzey, Farzon Lotfi, Cyprien Mangin, Guillaume Melquiond, RaphaΓ«l Monat, Carl Patenaude Poulin, Pierre-Marie PΓ©drot, ClΓ©ment Pit-Claudel, Matthew Ryan, Matt Quinn, Sigurd Schneider, Bernhard Schommer, Michael Soegtrop, Matthieu Sozeau, Arnaud Spiwack, Paul Steckler, Enrico Tassi, Anton Trunov, Martin Vassor, Vadim Zaliva and ThΓ©o Zimmermann. Version 8.8 is the third release of Coq developed on a time-based development cycle. Its development spanned 6 months from the release of Coq 8.7 and was based on a public roadmap. The development process was coordinated by Matthieu Sozeau. Maxime DΓ©nΓ¨s was in charge of the release process. ThΓ©o Zimmermann is the maintainer of this release. Many power users helped to improve the design of the new features via the bug tracker, the pull request system, the Coq development mailing list or the coq-club@inria.fr mailing list. Special thanks to the users who contributed patches and intensive brain-storming and code reviews, starting with Jason Gross, Ralf Jung, Robbert Krebbers and Amin Timany. It would however be impossible to mention exhaustively the names of everybody who to some extent influenced the development. The Coq consortium, an organization directed towards users and supporters of the system, is now running and employs Maxime DΓ©nΓ¨s. The contacts of the Coq Consortium are Yves Bertot and Maxime DΓ©nΓ¨s. | Santiago de Chile, March 2018, | Matthieu Sozeau for the Coq development team | Details of changes in 8.8+beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kernel - Support for template polymorphism for definitions was removed. May trigger more "universe inconsistency" errors in rare occasions. - Fixpoints are no longer allowed on non-recursive inductive types. Notations - Recursive notations with the recursive pattern repeating on the right (e.g. "( x ; .. ; y ; z )") now supported. - Notations with a specific level for the leftmost nonterminal, when printing-only, are supported. - Notations can now refer to the syntactic category of patterns (as in "fun 'pat =>" or "match p with pat => ... end"). Two variants are available, depending on whether a single variable is considered as a pattern or not. - Recursive notations now support ".." patterns with several occurrences of the recursive term or binder, possibly mixing terms and binders, possibly in reverse left-to-right order. - "Locate" now working also on notations of the form "x + y" (rather than "_ + _"). Specification language - When printing clauses of a "match", clauses with same right-hand side are factorized and the last most factorized clause with no variables, if it exists, is turned into a default clause. Use "Unset Printing Allow Default Clause" do deactivate printing of a default clause. Use "Unset Printing Factorizable Match Patterns" to deactivate factorization of clauses with same right-hand side. Tactics - On Linux, "native_compute" calls can be profiled using the "perf" utility. The command "Set NativeCompute Profiling" enables profiling, and "Set NativeCompute Profile Filename" customizes the profile filename. - The tactic "omega" is now aware of the bodies of context variables such as "x := 5 : Z" (see #1362). This could be disabled via Unset Omega UseLocalDefs. - The tactic "romega" is also aware now of the bodies of context variables. - The tactic "zify" resp. "omega with N" is now aware of N.pred. - Tactic "decide equality" now able to manage constructors which contain proofs. - Added tactics reset ltac profile, show ltac profile (and variants) - Added tactics restart_timer, finish_timing, and time_constr as an experimental way of timing Ltac's evaluation phase - Added tactic optimize_heap, analogous to the Vernacular Optimize Heap, which performs a major garbage collection and heap compaction in the OCaml run-time system. - The tactics "dtauto", "dintuition", "firstorder" now handle inductive types with let bindings in the parameters. - The tactic ``dtauto`` now handles some inductives such as ``@sigT A (fun _ => B)`` as non-dependent conjunctions. - A bug fixed in ``rewrite H in *`` and ``rewrite H in * |-`` may cause a few rare incompatibilities (it was unintendedly recursively rewriting in the side conditions generated by H). - Added tactics "assert_succeeds tac" and "assert_fails tac" to ensure properties of the execution of a tactic without keeping the effect of the execution. - `vm_compute` now supports existential variables. - Calls to `shelve` and `give_up` within calls to tactic `refine` now working. - Deprecated tactic `appcontext` was removed. Focusing - Focusing bracket `{` now supports single-numbered goal selector, e.g. `2: {` will focus on the second subgoal. As usual, unfocus with `}` once the subgoal is fully solved. The `Focus` and `Unfocus` commands are now deprecated. Commands - Proofs ending in "Qed exporting ident, .., ident" are not supported anymore. Constants generated during `abstract` are kept private to the local environment. - The deprecated Coercion Local, Open Local Scope, Notation Local syntax was removed. Use Local as a prefix instead. - For the Extraction Language command, "OCaml" is spelled correctly. The older "Ocaml" is still accepted, but deprecated. - Using β€œRequire” inside a section is deprecated. - An experimental command "Show Extraction" allows to extract the content of the current ongoing proof (grant wish #4129). - Coercion now accepts the type of its argument to be "Prop" or "Type". - The "Export" modifier can now be used when setting and unsetting options, and will result in performing the same change when the module corresponding the command is imported. - The `Axiom` command does not automatically declare axioms as instances when their type is a class. Previous behavior can be restored using `Set Typeclasses Axioms Are Instances`. Universes - Qualified naming of global universes now works like other namespaced objects (e.g. constants), with a separate namespace, inside and across module and library boundaries. Global universe names introduced in an inductive / constant / Let declaration get qualified with the name of the declaration. - Universe cumulativity for inductive types is now specified as a variance for each polymorphic universe. See the reference manual for more information. - Inference of universe constraints with cumulative inductive types produces more general constraints. Unsetting new option Cumulativity Weak Constraints produces even more general constraints (but may produce too many universes to be practical). - Fix #5726: Notations that start with `Type` now support universe instances with `@{u}`. - `with Definition` now understands universe declarations (like `@{u| Set < u}`). Tools - Coq can now be run with the option -mangle-names to change the auto-generated name scheme. This is intended to function as a linter for developments that want to be robust to changes in auto-generated names. This feature is experimental, and may change or disappear without warning. - GeoProof support was removed. Checker - The checker now accepts filenames in addition to logical paths. CoqIDE - Find and Replace All report the number of occurrences found; Find indicates when it wraps. coqdep - Learned to read -I, -Q, -R and filenames from _CoqProject files. This is used by coq_makefile when generating dependencies for .v files (but not other files). Documentation - The Coq FAQ, formerly located at https://coq.inria.fr/faq, has been moved to the GitHub wiki section of this repository; the main entry page is https://github.com/rocq-prover/rocq/wiki/The-Coq-FAQ. - Documentation: a large community effort resulted in the migration of the reference manual to the Sphinx documentation tool. The result is partially integrated in this version. Standard Library - New libraries Coq.Init.Decimal, Coq.Numbers.DecimalFacts, Coq.Numbers.DecimalNat, Coq.Numbers.DecimalPos, Coq.Numbers.DecimalN, Coq.Numbers.DecimalZ, Coq.Numbers.DecimalString providing a type of decimal numbers, some facts about them, and conversions between decimal numbers and nat, positive, N, Z, and string. - Added [Coq.Strings.String.concat] to concatenate a list of strings inserting a separator between each item - Notation `'` for Zpos in QArith was removed. - Some deprecated aliases are now emitting warnings when used. Compatibility support - Support for compatibility with versions before 8.6 was dropped. Options - The following deprecated options have been removed: + `Refolding Reduction` + `Standard Proposition Elimination` + `Dependent Propositions Elimination` + `Discriminate Introduction` + `Shrink Abstract` + `Tactic Pattern Unification` + `Intuition Iff Unfolding` + `Injection L2R Pattern Order` + `Record Elimination Schemes` + `Match Strict` + `Tactic Compat Context` + `Typeclasses Legacy Resolution` + `Typeclasses Module Eta` + `Typeclass Resolution After Apply` Details of changes in 8.8.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tools - Asynchronous proof delegation policy was fixed. Since version 8.7 Coq was ignoring previous runs and the `-async-proofs-delegation-threshold` option did not have the expected behavior. Tactic language - The undocumented "nameless" forms `fix N`, `cofix` have been deprecated; please use `fix ident N /cofix ident` to explicitly name the (co)fixpoint hypothesis to be introduced. Documentation - The reference manual is now fully ported to Sphinx. Other small deprecations and bug fixes. Details of changes in 8.8.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kernel - Fix a critical bug with cofixpoints and `vm_compute`/`native_compute` (#7333). - Fix a critical bug with modules and algebraic universes (#7695) - Fix a critical bug with inlining of polymorphic constants (#7615). - Fix a critical bug with universe polymorphism and `vm_compute` (#7723). Was present since 8.5. Notations - Fixed unexpected collision between only-parsing and only-printing notations (issue #7462). Windows installer - The Windows installer now includes external packages Ltac2 and Equations (it included the Bignums package since 8.8+beta1). Many other bug fixes, documentation improvements (including fixes of regressions due to the Sphinx migration), and user message improvements (for details, see the 8.8.1 milestone at https://github.com/rocq-prover/rocq/milestone/13?closed=1). Details of changes in 8.8.2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Documentation - A PDF version of the reference manual is available once again. Tools - The coq-makefile targets `print-pretty-timed`, `print-pretty-timed-diff`, and `print-pretty-single-time-diff` now correctly label the "before" and "after" columns, rather than swapping them. Kernel - The kernel does not tolerate capture of global universes by polymorphic universe binders, fixing a soundness break (triggered only through custom plugins) Windows installer - The Windows installer now includes many more external packages that can be individually selected for installation. Many other bug fixes and lots of documentation improvements (for details, see the 8.8.2 milestone at https://github.com/rocq-prover/rocq/milestone/15?closed=1). Version 8.7 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.7 contains the result of refinements, stabilization of features and cleanups of the internals of the system along with a few new features. The main user visible changes are: - New tactics: variants of tactics supporting existential variables :tacn:`eassert`, :tacn:`eenough`, etc... by Hugo Herbelin. Tactics ``extensionality in H`` and :tacn:`inversion_sigma` by Jason Gross, ``specialize with ...`` accepting partial bindings by Pierre Courtieu. - ``Cumulative Polymorphic Inductive`` types, allowing cumulativity of universes to go through applied inductive types, by Amin Timany and Matthieu Sozeau. - Integration of the SSReflect plugin and its documentation in the reference manual, by Enrico Tassi, Assia Mahboubi and Maxime DΓ©nΓ¨s. - The ``coq_makefile`` tool was completely redesigned to improve its maintainability and the extensibility of generated Makefiles, and to make ``_CoqProject`` files more palatable to IDEs by Enrico Tassi. Coq 8.7 involved a large amount of work on cleaning and speeding up the code base, notably the work of Pierre-Marie PΓ©drot on making the tactic-level system insensitive to existential variable expansion, providing a safer API to plugin writers and making the code more robust. The ``dev/doc/changes.txt`` file documents the numerous changes to the implementation and improvements of interfaces. An effort to provide an official, streamlined API to plugin writers is in progress, thanks to the work of Matej KoΕ‘Γ­k. Version 8.7 also comes with a bunch of smaller-scale changes and improvements regarding the different components of the system. We shall only list a few of them. The efficiency of the whole system has been significantly improved thanks to contributions from Pierre-Marie PΓ©drot, Maxime DΓ©nΓ¨s and Matthieu Sozeau and performance issue tracking by Jason Gross and Paul Steckler. Thomas Sibut-Pinote and Hugo Herbelin added support for side effect hooks in cbv, cbn and simpl. The side effects are provided via a plugin available at https://github.com/herbelin/reduction-effects/. The BigN, BigZ, BigQ libraries are no longer part of the Coq standard library, they are now provided by a separate repository https://github.com/coq/bignums, maintained by Pierre Letouzey. In the Reals library, ``IZR`` has been changed to produce a compact representation of integers and real constants are now represented using ``IZR`` (work by Guillaume Melquiond). Standard library additions and improvements by Jason Gross, Pierre Letouzey and others, documented in the next subsection file. The mathematical proof language/declarative mode plugin was removed from the archive. The opam repository for Coq packages has been maintained by Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi with contributions from many users. A list of packages is available at https://coq.inria.fr/opam/www/. Packaging tools and software development kits were prepared by Michael Soegtrop with the help of Maxime DΓ©nΓ¨s and Enrico Tassi for Windows, and Maxime DΓ©nΓ¨s for MacOS X. Packages are regularly built on the Travis continuous integration server. The contributors for this version are Abhishek Anand, C.J. Bell, Yves Bertot, FrΓ©dΓ©ric Besson, Tej Chajed, Pierre Courtieu, Maxime DΓ©nΓ¨s, Julien Forest, GaΓ«tan Gilbert, Jason Gross, Hugo Herbelin, Emilio JesΓΊs Gallego Arias, Ralf Jung, Matej KoΕ‘Γ­k, Xavier Leroy, Pierre Letouzey, Assia Mahboubi, Cyprien Mangin, Erik Martin-Dorel, Olivier Marty, Guillaume Melquiond, Sam Pablo Kuper, Benjamin Pierce, Pierre-Marie PΓ©drot, Lars Rasmusson, Lionel Rieg, Valentin Robert, Yann RΓ©gis-Gianas, Thomas Sibut-Pinote, Michael Soegtrop, Matthieu Sozeau, Arnaud Spiwack, Paul Steckler, George Stelle, Pierre-Yves Strub, Enrico Tassi, Hendrik Tews, Amin Timany, Laurent ThΓ©ry, Vadim Zaliva and ThΓ©o Zimmermann. The development process was coordinated by Matthieu Sozeau with the help of Maxime DΓ©nΓ¨s, who was also in charge of the release process. ThΓ©o Zimmermann is the maintainer of this release. Many power users helped to improve the design of the new features via the bug tracker, the pull request system, the Coq development mailing list or the Coq-Club mailing list. Special thanks to the users who contributed patches and intensive brain-storming and code reviews, starting with Jason Gross, Ralf Jung, Robbert Krebbers, Xavier Leroy, ClΓ©ment Pit–Claudel and Gabriel Scherer. It would however be impossible to mention exhaustively the names of everybody who to some extent influenced the development. Version 8.7 is the second release of Coq developed on a time-based development cycle. Its development spanned 9 months from the release of Coq 8.6 and was based on a public road-map. It attracted many external contributions. Code reviews and continuous integration testing were systematically used before integration of new features, with an important focus given to compatibility and performance issues, resulting in a hopefully more robust release than Coq 8.6 while maintaining compatibility. Coq Enhancement Proposals (CEPs for short) and open pull request discussions were used to discuss publicly the new features. The Coq consortium, an organization directed towards users and supporters of the system, is now upcoming and will rely on Inria’s newly created Foundation. | Paris, August 2017, | Matthieu Sozeau and the Coq development team | Potential compatibility issues ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Extra superfluous names in introduction patterns may now raise an error rather than a warning when the superfluous name is already in use. The easy fix is to remove the superfluous name. Details of changes in 8.7+beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tactics - New tactic "extensionality in H" which applies (possibly dependent) functional extensionality in H supposed to be a quantified equality until giving a bare equality. - New tactic ``inversion_sigma`` which turns equalities of dependent pairs (e.g., ``existT P x p = existT P y q``, frequently left over by ``inversion`` on a dependent type family) into pairs of equalities (e.g., a hypothesis ``H : x = y`` and a hypothesis of type ``rew H in p = q``); these hypotheses can subsequently be simplified using ``subst``, without ever invoking any kind of axiom asserting uniqueness of identity proofs. If you want to explicitly specify the hypothesis to be inverted, or name the generated hypotheses, you can invoke ``induction H as [H1 H2] using eq_sigT_rect``. The tactic also works for ``sig``, ``sigT2``, and ``sig2``, and there are similar ``eq_sig*_rect`` induction lemmas. - Tactic "specialize with ..." now accepts any partial bindings. Missing bindings are either solved by unification or left quantified in the hypothesis. - New representation of terms that statically ensure stability by evar-expansion. This has several consequences. * In terms of performance, this adds a cost to every term destructuration, but at the same time most eager evar normalizations were removed, which couterbalances this drawback and even sometimes outperforms the old implementation. For instance, many operations that would require O(n) normalization of the term are now O(1) in tactics. YMMV. * This triggers small changes in unification, which was not evar-insensitive. Most notably, the new implementation recognizes Miller patterns that were missed before because of a missing normalization step. Hopefully this should be fairly uncommon. - Tactic "auto with real" can now discharge comparisons of literals. - The types of variables in patterns of "match" are now beta-iota-reduced after type checking. This has an impact on the type of the variables that the tactic "refine" introduces in the context, producing types that should be closer to the expectations. - In "Tactic Notation" or "TACTIC EXTEND", entry "constr_with_bindings" now uses type classes and rejects terms with unresolved holes, like entry "constr" does. To get the former behavior use "open_constr_with_bindings" (possible source of incompatibility). - New e-variants eassert, eenough, epose proof, eset, eremember, epose which behave like the corresponding variants with no "e" but turn unresolved implicit arguments into existential variables, on the shelf, rather than failing. - Tactic injection has become more powerful (closes bug #4890) and its documentation has been updated. - New variants of the `first` and `solve` tacticals that do not rely on parsing rules, meant to define tactic notations. - Added support for side effects hooks in `cbv`, `cbn` and `simpl`. The side effects are provided via a plugin: https://github.com/herbelin/reduction-effects/ - It is now possible to take hint database names as parameters in a Ltac definition or a Tactic Notation. - New option `Set Ltac Batch Debug` on top of `Set Ltac Debug` for non-interactive Ltac debug output. Gallina - Now supporting all kinds of binders, including 'pat, in syntax of record fields. Commands - Goals context can be printed in a more compact way when `Set Printing Compact Contexts` is activated. - Unfocused goals can be printed with the `Set Printing Unfocused` option. - `Print` now shows the types of let-bindings. - The compatibility options for printing primitive projections (`Set Printing Primitive Projection Parameters` and `Set Printing Primitive Projection Compatibility`) are now off by default. - Possibility to unset the printing of notations in a more fine grained fashion than `Unset Printing Notations` is provided without any user-syntax. The goal is that someone creates a plugin to experiment such a user-syntax, to be later integrated in Coq when stabilized. - `About` now tells if a reference is a coercion. - The deprecated `Save` vernacular and its form `Save Theorem id` to close proofs have been removed from the syntax. Please use `Qed`. - `Search` now sorts results by relevance (the relevance metric is a weighted sum of number of distinct symbols and size of the term). Standard Library - New file PropExtensionality.v to explicitly work in the axiomatic context of propositional extensionality. - New file SetoidChoice.v axiomatically providing choice over setoids, and, consequently, choice of representatives in equivalence classes. Various proof-theoretic characterizations of choice over setoids in file ChoiceFacts.v. - New lemmas about iff and about orders on positive and Z. - New lemmas on powerRZ. - Strengthened statement of JMeq_eq_dep (closes bug #4912). - The BigN, BigZ, BigZ libraries are no longer part of the Coq standard library, they are now provided by a separate repository https://github.com/coq/bignums The split has been done just after the Int31 library. - IZR (Reals) has been changed to produce a compact representation of integers. As a consequence, IZR is no longer convertible to INR and lemmas such as INR_IZR_INZ should be used instead. - Real constants are now represented using IZR rather than R0 and R1; this might cause rewriting rules to fail to apply to constants. - Added new notation {x & P} for sigT (without a type for x) Plugins - The Ssreflect plugin is now distributed with Coq. Its documentation has been integrated as a chapter of the reference manual. This chapter is work in progress so feedback is welcome. - The mathematical proof language (also known as declarative mode) was removed. - A new command Extraction TestCompile has been introduced, not meant for the general user but instead for Coq's test-suite. - The extraction plugin is no longer loaded by default. It must be explicitly loaded with [Require Extraction], which is backwards compatible. - The functional induction plugin (which provides the [Function] vernacular) is no longer loaded by default. It must be explicitly loaded with [Require FunInd], which is backwards compatible. Dependencies - Support for camlp4 has been removed. Tools - coq_makefile was completely redesigned to improve its maintainability and the extensibility of generated Makefiles, and to make _CoqProject files more palatable to IDEs. Overview: * _CoqProject files contain only Coq specific data (i.e. the list of files, -R options, ...) * coq_makefile translates _CoqProject to Makefile.conf and copies in the desired location a standard Makefile (that reads Makefile.conf) * Makefile extensions can be implemented in a Makefile.local file (read by the main Makefile) by installing a hook in the extension points provided by the standard Makefile The current version contains code for retro compatibility that prints warnings when a deprecated feature is used. Please upgrade your _CoqProject accordingly. * Additionally, coq_makefile-made Makefiles now support experimental timing targets `pretty-timed`, `pretty-timed-before`, `pretty-timed-after`, `print-pretty-timed-diff`, `print-pretty-single-time-diff`, `all.timing.diff`, and the variable `TIMING=1` (or `TIMING=before` or `TIMING=after`); see the documentation for more details. Build Infrastructure - Note that 'make world' does not build the bytecode binaries anymore. For that, you can use 'make byte' (and 'make install-byte' afterwards). Warning: native and byte compilations should *not* be mixed in the same instance of 'make -j', otherwise both ocamlc and ocamlopt might race for access to the same .cmi files. In short, use "make -j && make -j byte" instead of "make -j world byte". Universes - Cumulative inductive types. see prefixes "Cumulative", "NonCumulative" for inductive definitions and the option "Set Polymorphic Inductive Cumulativity" in the reference manual. - New syntax `foo@{_}` to instantiate a polymorphic definition with anonymous universes (can also be used with `Type`). XML Protocol and internal changes See dev/doc/changes.txt Many bugfixes including #1859, #2884, #3613, #3943, #3994, #4250, #4709, #4720, #4824, #4844, #4911, #5026, #5233, #5275, #5315, #5336, #5360, #5390, #5414, #5417, #5420, #5439, #5449, #5475, #5476, #5482, #5501, #5507, #5520, #5523, #5524, #5553, #5577, #5578, #5589, #5597, #5598, #5607, #5618, #5619, #5620, #5641, #5648, #5651, #5671. Many bugfixes on OS X and Windows (now the test-suite passes on these platforms too). Many optimizations. Many documentation improvements. Details of changes in 8.7+beta2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tools - In CoqIDE, the "Compile Buffer" command takes account of flags in _CoqProject or other project file. Improvements around some error messages. Many bug fixes including two important ones: - Bug #5730: CoqIDE becomes unresponsive on file open. - coq_makefile: make sure compile flags for Coq and coq_makefile are in sync (in particular, make sure the `-safe-string` option is used to compile plugins). Details of changes in 8.7.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ OCaml - Users can pass specific flags to the OCaml optimizing compiler by -using the flambda-opts configure-time option. Beware that compiling Coq with a flambda-enabled compiler is experimental and may require large amounts of RAM and CPU, see INSTALL for more details. Details of changes in 8.7.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Compatibility with OCaml 4.06.0. Many bug fixes, documentation improvements, and user message improvements (for details see the 8.7.1 milestone at https://github.com/rocq-prover/rocq/milestone/10?closed=1). Details of changes in 8.7.2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fixed a critical bug in the VM handling of universes (#6677). This bug affected all releases since 8.5. Improved support for building with OCaml 4.06.0 and external num package. Many other bug fixes, documentation improvements, and user message improvements (for details, see the 8.7.2 milestone at https://github.com/rocq-prover/rocq/milestone/11?closed=1). Version 8.6 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.6 contains the result of refinements, stabilization of 8.5’s features and cleanups of the internals of the system. Over the year of (now time-based) development, about 450 bugs were resolved and over 100 contributions integrated. The main user visible changes are: - A new, faster state-of-the-art universe constraint checker, by Jacques-Henri Jourdan. - In CoqIDE and other asynchronous interfaces, more fine-grained asynchronous processing and error reporting by Enrico Tassi, making Coq capable of recovering from errors and continue processing the document. - More access to the proof engine features from Ltac: goal management primitives, range selectors and a :tacn:`typeclasses eauto` engine handling multiple goals and multiple successes, by Cyprien Mangin, Matthieu Sozeau and Arnaud Spiwack. - Tactic behavior uniformization and specification, generalization of intro-patterns by Hugo Herbelin and others. - A brand new warning system allowing to control warnings, turn them into errors or ignore them selectively by Maxime DΓ©nΓ¨s, Guillaume Melquiond, Pierre-Marie PΓ©drot and others. - Irrefutable patterns in abstractions, by Daniel de Rauglaudre. - The ssreflect subterm selection algorithm by Georges Gonthier and Enrico Tassi is now accessible to tactic writers through the ssrmatching plugin. - Integration of LtacProf, a profiler for Ltac by Jason Gross, Paul Steckler, Enrico Tassi and Tobias Tebbi. Coq 8.6 also comes with a bunch of smaller-scale changes and improvements regarding the different components of the system. We shall only list a few of them. The iota reduction flag is now a shorthand for match, fix and cofix flags controlling the corresponding reduction rules (by Hugo Herbelin and Maxime DΓ©nΓ¨s). Maxime DΓ©nΓ¨s maintained the native compilation machinery. Pierre-Marie PΓ©drot separated the Ltac code from general purpose tactics, and generalized and rationalized the handling of generic arguments, allowing to create new versions of Ltac more easily in the future. In patterns and terms, @, abbreviations and notations are now interpreted the same way, by Hugo Herbelin. Name handling for universes has been improved by Pierre-Marie PΓ©drot and Matthieu Sozeau. The minimization algorithm has been improved by Matthieu Sozeau. The unifier has been improved by Hugo Herbelin and Matthieu Sozeau, fixing some incompatibilities introduced in Coq 8.5. Unification constraints can now be left floating around and be seen by the user thanks to a new option. The Keyed Unification mode has been improved by Matthieu Sozeau. The typeclass resolution engine and associated proof search tactic have been reimplemented on top of the proof-engine monad, providing better integration in tactics, and new options have been introduced to control it, by Matthieu Sozeau with help from ThΓ©o Zimmermann. The efficiency of the whole system has been significantly improved thanks to contributions from Pierre-Marie PΓ©drot, Maxime DΓ©nΓ¨s and Matthieu Sozeau and performance issue tracking by Jason Gross and Paul Steckler. Standard library improvements by Jason Gross, SΓ©bastien Hinderer, Pierre Letouzey and others. Emilio JesΓΊs Gallego Arias contributed many cleanups and refactorings of the pretty-printing and user interface communication components. FrΓ©dΓ©ric Besson maintained the micromega tactic. The opam repository for Coq packages has been maintained by Guillaume Claret, Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi and others. A list of packages is now available at https://coq.inria.fr/opam/www/. Packaging tools and software development kits were prepared by Michael Soegtrop with the help of Maxime DΓ©nΓ¨s and Enrico Tassi for Windows, and Maxime DΓ©nΓ¨s and Matthieu Sozeau for MacOS X. Packages are now regularly built on the continuous integration server. Coq now comes with a META file usable with ocamlfind, contributed by Emilio JesΓΊs Gallego Arias, Gregory Malecha, and Matthieu Sozeau. Matej KoΕ‘Γ­k maintained and greatly improved the continuous integration setup and the testing of Coq contributions. He also contributed many API improvements and code cleanups throughout the system. The contributors for this version are Bruno Barras, C.J. Bell, Yves Bertot, FrΓ©dΓ©ric Besson, Pierre Boutillier, Tej Chajed, Guillaume Claret, Xavier Clerc, Pierre Corbineau, Pierre Courtieu, Maxime DΓ©nΓ¨s, Ricky Elrod, Emilio JesΓΊs Gallego Arias, Jason Gross, Hugo Herbelin, SΓ©bastien Hinderer, Jacques-Henri Jourdan, Matej KoΕ‘Γ­k, Xavier Leroy, Pierre Letouzey, Gregory Malecha, Cyprien Mangin, Erik Martin-Dorel, Guillaume Melquiond, ClΓ©ment Pit–Claudel, Pierre-Marie PΓ©drot, Daniel de Rauglaudre, Lionel Rieg, Gabriel Scherer, Thomas Sibut-Pinote, Matthieu Sozeau, Arnaud Spiwack, Paul Steckler, Enrico Tassi, Laurent ThΓ©ry, Nickolai Zeldovich and ThΓ©o Zimmermann. The development process was coordinated by Hugo Herbelin and Matthieu Sozeau with the help of Maxime DΓ©nΓ¨s, who was also in charge of the release process. Many power users helped to improve the design of the new features via the bug tracker, the pull request system, the Coq development mailing list or the Coq-Club mailing list. Special thanks to the users who contributed patches and intensive brain-storming and code reviews, starting with Cyril Cohen, Jason Gross, Robbert Krebbers, Jonathan Leivent, Xavier Leroy, Gregory Malecha, ClΓ©ment Pit–Claudel, Gabriel Scherer and Beta Ziliani. It would however be impossible to mention exhaustively the names of everybody who to some extent influenced the development. Version 8.6 is the first release of Coq developed on a time-based development cycle. Its development spanned 10 months from the release of Coq 8.5 and was based on a public roadmap. To date, it contains more external contributions than any previous Coq system. Code reviews were systematically done before integration of new features, with an important focus given to compatibility and performance issues, resulting in a hopefully more robust release than Coq 8.5. Coq Enhancement Proposals (CEPs for short) were introduced by Enrico Tassi to provide more visibility and a discussion period on new features, they are publicly available https://github.com/coq/ceps. Started during this period, an effort is led by Yves Bertot and Maxime DΓ©nΓ¨s to put together a Coq consortium. | Paris, November 2016, | Matthieu Sozeau and the Coq development team | Potential sources of incompatibilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Symptom: An obligation generated by Program or an abstracted subproof has different arguments. Cause: Set Shrink Abstract and Set Shrink Obligations are on by default and the subproof does not use the argument. Remedy: + Adapt the script. + Write an explicit lemma to prove the obligation/subproof and use it instead (compatible with 8.4). + Unset the option for the program/proof the obligation/subproof originates from. - Symptom: In a goal, order of hypotheses, or absence of an equality of the form "x = t" or "t = x", or no unfolding of a local definition. Cause: This might be connected to a number of fixes in the tactic "subst". The former behavior can be reactivated by issuing "Unset Regular Subst Tactic". Details of changes in 8.6beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kernel - A new, faster state-of-the-art universe constraint checker. Specification language - Giving implicit arguments explicitly to a constant with multiple choices of implicit arguments does not break any more insertion of further maximal implicit arguments. - Ability to put any pattern in binders, prefixed by quote, e.g. "fun '(a,b) => ...", "Ξ» '(a,(b,c)), ...", "Definition foo '(x,y) := ...". It expands into a "let 'pattern := ..." Tactics - Flag "Bracketing Last Introduction Pattern" is now on by default. - Flag "Regular Subst Tactic" is now on by default: it respects the initial order of hypothesis, it contracts cycles, it unfolds no local definitions (common source of incompatibilities, fixable by "Unset Regular Subst Tactic"). - New flag "Refolding Reduction", now disabled by default, which turns on refolding of constants/fixpoints (as in cbn) during the reductions done during type inference and tactic retyping. Can be extremely expensive. When set off, this recovers the 8.4 behavior of unification and type inference. Potential source of incompatibility with 8.5 developments (the option is set on in Compat/Coq85.v). - New flag "Shrink Abstract" that minimalizes proofs generated by the abstract tactical w.r.t. variables appearing in the body of the proof. On by default and deprecated. Minor source of incompatibility for code relying on the precise arguments of abstracted proofs. - Serious bugs are fixed in tactic "double induction" (source of incompatibilities as soon as the inductive types have dependencies in the type of their constructors; "double induction" remains however deprecated). - In introduction patterns of the form (pat1,...,patn), n should match the exact number of hypotheses introduced (except for local definitions for which pattern can be omitted, as in regular pattern-matching). - Tactic scopes in Ltac like constr: and ltac: now require parentheses around their argument. - Every generic argument type declares a tactic scope of the form "name:(...)" where name is the name of the argument. This generalizes the constr: and ltac: instances. - When in strict mode (i.e. in a Ltac definition), if the "intro" tactic is given a free identifier, it is not bound in subsequent tactics anymore. In order to introduce a binding, use e.g. the "fresh" primitive instead (potential source of incompatibilities). - New tactics is_ind, is_const, is_proj, is_constructor for use in Ltac. - New goal selectors. Sets of goals can be selected by listing integers ranges. Example: "1,4-7,24: tac" focuses "tac" on goals 1,4,5,6,7,24. - For uniformity with "destruct"/"induction" and for a more natural behavior, "injection" can now work in place by activating option "Structural Injection". In this case, hypotheses are also put in the context in the natural left-to-right order and the hypothesis on which injection applies is cleared. - Tactic "contradiction" (hence "easy") now also solve goals with hypotheses of the form "~True" or "t<>t" (possible source of incompatibilities because of more successes in automation, but generally a more intuitive strategy). - Option "Injection On Proofs" was renamed "Keep Proof Equalities". When enabled, injection and inversion do not drop equalities between objects in Prop. Still disabled by default. - New tactics "notypeclasses refine" and "simple notypeclasses refine" that disallow typeclass resolution when typechecking their argument, for use in typeclass hints. - Integration of LtacProf, a profiler for Ltac. - Reduction tactics now accept more fine-grained flags: iota is now a shorthand for the new flags match, fix and cofix. - The ssreflect subterm selection algorithm is now accessible to tactic writers through the ssrmatching plugin. - When used as an argument of an ltac function, "auto" without "with" nor "using" clause now correctly uses only the core hint database by default. Hints - Revised the syntax of [Hint Cut] to follow standard notation for regexps. - Hint Mode now accepts "!" which means that the mode matches only if the argument's head is not an evar (it goes under applications, casts, and scrutinees of matches and projections). - Hints can now take an optional user-given pattern, used only by [typeclasses eauto] with the [Filtered Unification] option on. Typeclasses - Many new options and new engine based on the proof monad. The [typeclasses eauto] tactic is now a multi-goal, multi-success tactic. See reference manual for more information. It is planned to replace auto and eauto in the following version. The 8.5 resolution engine is still available to help solve compatibility issues. Program - The "Shrink Obligations" flag now applies to all obligations, not only those solved by the automatic tactic. - "Shrink Obligations" is on by default and deprecated. Minor source of incompatibility for code relying on the precise arguments of obligations. Notations - "Bind Scope" can once again bind "Funclass" and "Sortclass". General infrastructure - New configurable warning system which can be controlled with the vernacular command "Set Warnings", or, under coqc/coqtop, with the flag "-w". In particular, the default is now that warnings are printed by coqc. - In asynchronous mode, Coq is now capable of recovering from errors and continue processing the document. Tools - coqc accepts a -o option to specify the output file name - coqtop accepts --print-version to print Coq and OCaml versions in easy to parse format - Setting [Printing Dependent Evars Line] can be unset to disable the computation associated with printing the "dependent evars: " line in -emacs mode - Removed the -verbose-compat-notations flag and the corresponding Set Verbose Compat vernacular, since these warnings can now be silenced or turned into errors using "-w". XML protocol - message format has changed, see dev/doc/changes.txt for more details. Many bug fixes, minor changes and documentation improvements are not mentioned here. Details of changes in 8.6 ~~~~~~~~~~~~~~~~~~~~~~~~~ Kernel - Fixed critical bug #5248 in VM long multiplication on 32-bit architectures. Was there only since 8.6beta1, so no stable release impacted. Other bug fixes in universes, type class shelving,... Details of changes in 8.6.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Fix #5380: Default colors for CoqIDE are actually applied. - Fix plugin warnings - Document named evars (including Show ident) - Fix Bug #5574, document function scope - Adding a test case as requested in bug 5205. - Fix Bug #5568, no dup notation warnings on repeated module imports - Fix documentation of Typeclasses eauto := - Refactor documentation of records. - Protecting from warnings while compiling 8.6 - Fixing an inconsistency between configure and configure.ml - Add test-suite checks for coqchk with constraints - Fix bug #5019 (looping zify on dependent types) - Fix bug 5550: "typeclasses eauto with" does not work with section variables. - Bug 5546, qualify datatype constructors when needed in Show Match - Bug #5535, test for Show with -emacs - Fix bug #5486, don't reverse ids in tuples - Fixing #5522 (anomaly with free vars of pat) - Fix bug #5526, don't check for nonlinearity in notation if printing only - Fix bug #5255 - Fix bug #3659: -time should understand multibyte encodings. - FIx bug #5300: Anomaly: Uncaught exception Not_found" in "Print Assumptions". - Fix outdated description in RefMan. - Repairing `Set Rewriting Schemes` - Fixing #5487 (v8.5 regression on ltac-matching expressions with evars). - Fix description of command-line arguments for Add (Rec) LoadPath - Fix bug #5377: @? patterns broken. - add XML protocol doc - Fix anomaly when doing [all:Check _.] during a proof. - Correction of bug #4306 - Fix #5435: [Eval native_compute in] raises anomaly. - Instances should obey universe binders even when defined by tactics. - Intern names bound in match patterns - funind: Ignore missing info for current function - Do not typecheck twice the type of opaque constants. - show unused intro pattern warning - [future] Be eager when "chaining" already resolved future values. - Opaque side effects - Fix #5132: coq_makefile generates incorrect install goal - Run non-tactic comands without resilient_command - Univs: fix bug #5365, generation of u+k <= v constraints - make ``emit`` tail recursive - Don't require printing-only notation to be productive - Fix the way setoid_rewrite handles bindings. - Fix for bug 5244 - set printing width ignored when given enough space - Fix bug 4969, autoapply was not tagging shelved subgoals correctly Version 8.5 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.5 contains the result of five specific long-term projects: - A new asynchronous evaluation and compilation mode by Enrico Tassi with help from Bruno Barras and Carst Tankink. - Full integration of the new proof engine by Arnaud Spiwack helped by Pierre-Marie PΓ©drot, - Addition of conversion and reduction based on native compilation by Maxime DΓ©nΓ¨s and Benjamin GrΓ©goire. - Full universe polymorphism for definitions and inductive types by Matthieu Sozeau. - An implementation of primitive projections with Ξ·-conversion bringing significant performance improvements when using records by Matthieu Sozeau. The full integration of the proof engine, by Arnaud Spiwack and Pierre-Marie PΓ©drot, brings to primitive tactics and the user level Ltac language dependent subgoals, deep backtracking and multiple goal handling, along with miscellaneous features and an improved potential for future modifications. Dependent subgoals allow statements in a goal to mention the proof of another. Proofs of unsolved subgoals appear as existential variables. Primitive backtracking makes it possible to write a tactic with several possible outcomes which are tried successively when subsequent tactics fail. Primitives are also available to control the backtracking behavior of tactics. Multiple goal handling paves the way for smarter automation tactics. It is currently used for simple goal manipulation such as goal reordering. The way Coq processes a document in batch and interactive mode has been redesigned by Enrico Tassi with help from Bruno Barras. Opaque proofs, the text between Proof and Qed, can be processed asynchronously, decoupling the checking of definitions and statements from the checking of proofs. It improves the responsiveness of interactive development, since proofs can be processed in the background. Similarly, compilation of a file can be split into two phases: the first one checking only definitions and statements and the second one checking proofs. A file resulting from the first phase – with the .vio extension – can be already Required. All .vio files can be turned into complete .vo files in parallel. The same infrastructure also allows terminating tactics to be run in parallel on a set of goals via the ``par:`` goal selector. CoqIDE was modified to cope with asynchronous checking of the document. Its source code was also made separate from that of Coq, so that CoqIDE no longer has a special status among user interfaces, paving the way for decoupling its release cycle from that of Coq in the future. Carst Tankink developed a Coq back-end for user interfaces built on Makarius Wenzel’s Prover IDE framework (PIDE), like PIDE/jEdit (with help from Makarius Wenzel) or PIDE/Coqoon (with help from Alexander Faithfull and Jesper Bengtson). The development of such features was funded by the Paral-ITP French ANR project. The full universe polymorphism extension was designed by Matthieu Sozeau. It conservatively extends the universes system and core calculus with definitions and inductive declarations parameterized by universes and constraints. It is based on a modification of the kernel architecture to handle constraint checking only, leaving the generation of constraints to the refinement/type inference engine. Accordingly, tactics are now fully universe aware, resulting in more localized error messages in case of inconsistencies and allowing higher-level algorithms like unification to be entirely type safe. The internal representation of universes has been modified but this is invisible to the user. The underlying logic has been extended with Ξ·-conversion for records defined with primitive projections by Matthieu Sozeau. This additional form of Ξ·-conversion is justified using the same principle than the previously added Ξ·-conversion for function types, based on formulations of the Calculus of Inductive Constructions with typed equality. Primitive projections, which do not carry the parameters of the record and are rigid names (not defined as a pattern matching construct), make working with nested records more manageable in terms of time and space consumption. This extension and universe polymorphism were carried out partly while Matthieu Sozeau was working at the IAS in Princeton. The guard condition has been made compliant with extensional equality principles such as propositional extensionality and univalence, thanks to Maxime DΓ©nΓ¨s and Bruno Barras. To ensure compatibility with the univalence axiom, a new flag ``-indices-matter`` has been implemented, taking into account the universe levels of indices when computing the levels of inductive types. This supports using Coq as a tool to explore the relations between homotopy theory and type theory. Maxime DΓ©nΓ¨s and Benjamin GrΓ©goire developed an implementation of conversion test and normal form computation using the OCaml native compiler. It complements the virtual machine conversion offering much faster computation for expensive functions. Coq 8.5 also comes with a bunch of many various smaller-scale changes and improvements regarding the different components of the system. We shall only list a few of them. Pierre Boutillier developed an improved tactic for simplification of expressions called :tacn:`cbn`. Maxime DΓ©nΓ¨s maintained the bytecode-based reduction machine. Pierre Letouzey maintained the extraction mechanism. Pierre-Marie PΓ©drot has extended the syntax of terms to, experimentally, allow holes in terms to be solved by a locally specified tactic. Existential variables are referred to by identifiers rather than mere numbers, thanks to Hugo Herbelin who also improved the tactic language here and there. Error messages for universe inconsistencies have been improved by Matthieu Sozeau. Error messages for unification and type inference failures have been improved by Hugo Herbelin, Pierre-Marie PΓ©drot and Arnaud Spiwack. Pierre Courtieu contributed new features for using Coq through Proof General and for better interactive experience (bullets, Search, etc). The efficiency of the whole system has been significantly improved thanks to contributions from Pierre-Marie PΓ©drot. A distribution channel for Coq packages using the opam tool has been initiated by Thomas Braibant and developed by Guillaume Claret, with contributions by Enrico Tassi and feedback from Hugo Herbelin. Packaging tools were provided by Pierre Letouzey and Enrico Tassi (Windows), Pierre Boutillier, Matthieu Sozeau and Maxime DΓ©nΓ¨s (MacOS X). Maxime DΓ©nΓ¨s improved significantly the testing and benchmarking support. Many power users helped to improve the design of the new features via the bug tracker, the coq development mailing list or the Coq-Club mailing list. Special thanks are going to the users who contributed patches and intensive brain-storming, starting with Jason Gross, Jonathan Leivent, Greg Malecha, ClΓ©ment Pit-Claudel, Marc Lasson, Lionel Rieg. It would however be impossible to mention with precision all names of people who to some extent influenced the development. Version 8.5 is one of the most important releases of Coq. Its development spanned over about 3 years and a half with about one year of beta-testing. General maintenance during part or whole of this period has been done by Pierre Boutillier, Pierre Courtieu, Maxime DΓ©nΓ¨s, Hugo Herbelin, Pierre Letouzey, Guillaume Melquiond, Pierre-Marie PΓ©drot, Matthieu Sozeau, Arnaud Spiwack, Enrico Tassi as well as Bruno Barras, Yves Bertot, FrΓ©dΓ©ric Besson, Xavier Clerc, Pierre Corbineau, Jean-Christophe FilliΓ’tre, Julien Forest, SΓ©bastien Hinderer, Assia Mahboubi, Jean-Marc Notin, Yann RΓ©gis-Gianas, FranΓ§ois Ripault, Carst Tankink. Maxime DΓ©nΓ¨s coordinated the release process. | Paris, January 2015, revised December 2015, | Hugo Herbelin, Matthieu Sozeau and the Coq development team | Potential sources of incompatibilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ List of typical changes to be done to adapt files from Coq 8.4 to Coq 8.5 when not using compatibility option ``-compat 8.4``. - Symptom: "The reference omega was not found in the current environment". Cause: "Require Omega" does not import the tactic "omega" any more Possible solutions: + use "Require Import OmegaTactic" (not compatible with 8.4) + use "Require Import Omega" (compatible with 8.4) + add definition "Ltac omega := Coq.omega.Omega.omega." - Symptom: "intuition" cannot solve a goal (not working anymore on nonstandard connective) Cause: "intuition" had an accidental non-uniform behavior fixed on nonstandard connectives Possible solutions: + use "dintuition" instead; it is stronger than "intuition" and works uniformly on nonstandard connectives, such as n-ary conjunctions or disjunctions (not compatible with 8.4) + do the script differently - Symptom: The constructor foo (in type bar) expects n arguments. Cause: parameters must now be given in patterns Possible solutions: + use option "Set Asymmetric Patterns" (compatible with 8.4) + add "_" for the parameters (not compatible with 8.4) + turn the parameters into implicit arguments (compatible with 8.4) - Symptom: "NPeano.Nat.foo" not existing anymore\ Possible solutions: + use "Nat.foo" instead Symptom: typing problems with proj1_sig or similar Cause: coercion from sig to sigT and similar coercions have been removed so as to make the initial state easier to understand for beginners Solution: change proj1_sig into projT1 and similarly (compatible with 8.4) Other detailed changes - options for *coq* compilation (see below for ocaml). + [-I foo] is now deprecated and will not add directory foo to the coq load path (only for ocaml, see below). Just replace [-I foo] by [-Q foo ""] in your project file and re-generate makefile. Or perform the same operation directly in your makefile if you edit it by hand. + Option -R Foo bar is the same in v8.5 than in v8.4 concerning coq load path. + Option [-I foo -as bar] is unchanged but discouraged unless you compile ocaml code. Use -Q foo bar instead. for more details: see section "Customization at launch time" of the reference manual. - Command line options for ocaml Compilation of ocaml code (plugins) + [-I foo] is *not* deprecated to add foo to the ocaml load path. + [-I foo -as bar] adds foo to the ocaml load path *and* adds foo to the coq load path with logical name bar (shortcut for -I foo -Q foo bar). for more details: section "Customization at launch time" of the reference manual. - Universe Polymorphism. - Refinement, unification and tactics are now aware of universes, resulting in more localized errors. Universe inconsistencies should no more get raised at Qed time but during the proof. Unification *always* produces well-typed substitutions, hence some rare cases of unifications that succeeded while producing ill-typed terms before will now fail. - The [change p with c] tactic semantics changed, now typechecking [c] at each matching occurrence [t] of the pattern [p], and converting [t] with [c]. - Template polymorphic inductive types: the partial application of a template polymorphic type (e.g. list) is not polymorphic. An explicit parameter application (e.g [fun A => list A]) or [apply (list _)] will result in a polymorphic instance. - The type inference algorithm now takes opacity of constants into account. This may have effects on tactics using type inference (e.g. induction). Extra "Transparent" might have to be added to revert opacity of constants. Type classes. - When writing an ``Instance foo : Class A := {| proj := t |}`` (note the vertical bars), support for typechecking the projections using the type information and switching to proof mode is no longer available. Use ``{ }`` (without the vertical bars) instead. Tactic abstract. - Auxiliary lemmas generated by the abstract tactic are removed from the global environment and inlined in the proof term when a proof is ended with Qed. The behavior of 8.4 can be obtained by ending proofs with "Qed exporting" or "Qed exporting ident, .., ident". Details of changes in 8.5beta1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logic - Primitive projections for records allow for a compact representation of projections, without parameters and avoid the behavior of defined projections that can unfold to a case expression. To turn the use of native projections on, use [Set Primitive Projections]. Record, Class and Structure types defined while this option is set will be defined with primitive projections instead of the usual encoding as a case expression. For compatibility, when p is a primitive projection, @p can be used to refer to the projection with explicit parameters, i.e. [@p] is definitionally equal to [Ξ» params r. r.(p)]. Records with primitive projections have eta-conversion, the canonical form being [mkR pars (p1 t) ... (pn t)]. - New universe polymorphism (see reference manual) - New option -type-in-type to collapse the universe hierarchy (this makes the logic inconsistent). - The guard condition for fixpoints is now a bit stricter. Propagation of subterm value through pattern matching is restricted according to the return predicate. Restores compatibility of Coq's logic with the propositional extensionality axiom. May create incompatibilities in recursive programs heavily using dependent types. - Trivial inductive types are no longer defined in Type but in Prop, which leads to a non-dependent induction principle being generated in place of the dependent one. To recover the old behavior, explicitly define your inductive types in Set. Commands - A command "Variant" allows to define non-recursive variant types. - The command "Record foo ..." does not generate induction principles (foo_rect, foo_rec, foo_ind) anymore by default (feature wish #2693). The command "Variant foo ..." does not either. A flag "Set/Unset Nonrecursive Elimination Schemes" allows changing this. The tactic "induction" on a "Record" or a "Variant" is now actually doing "destruct". - The "Open Scope" command can now be given also a delimiter (e.g. Z). - The "Definition" command now allows the "Local" modifier, allowing for non-importable definitions. The same goes for "Axiom" and "Parameter". - Section-specific commands such as "Let" (resp. "Variable", "Hypothesis") used out of a section now behave like the corresponding "Local" command, i.e. "Local Definition" (resp. "Local Parameter", "Local Axiom"). (potential source of rare incompatibilities). - The "Let" command can now define local (co)fixpoints. - Command "Search" has been renamed into "SearchHead". The command name "Search" now behaves like former "SearchAbout". The latter name is deprecated. - "Search", "About", "SearchHead", "SearchRewrite" and "SearchPattern" now search for hypothesis (of the current goal by default) first. They now also support the goal selector prefix to specify another goal to search: e.g. "n:Search id". This is also true for SearchAbout although it is deprecated. - The coq/user-contrib directory and the XDG directories are no longer recursively added to the load path, so files from installed libraries now need to be fully qualified for the "Require" command to find them. The tools/update-require script can be used to convert a development. - A new Print Strategies command allows visualizing the opacity status of the whole engine. - The "Locate" command now searches through all sorts of qualified namespaces of Coq: terms, modules, tactics, etc. The old behavior of the command can be retrieved using the "Locate Term" command. - New "Derive" command to help writing program by derivation. - New "Refine Instance Mode" option that allows to deactivate the generation of obligations in incomplete typeclass instances, raising an error instead. - "Collection" command to name sets of section hypotheses. Named collections can be used in the syntax of "Proof using" to assert which section variables are used in a proof. - The "Optimize Proof" command can be placed in the middle of a proof to force the compaction of the data structure used to represent the ongoing proof (evar map). This may result in a lower memory footprint and speed up the execution of the following tactics. - "Optimize Heap" command to tell the OCaml runtime to perform a major garbage collection step and heap compaction. - ``Instance`` no longer treats the ``{|...|}`` syntax specially; it handles it in the same way as other commands, e.g. "Definition". Use the ``{...}`` syntax (no pipe symbols) to recover the old behavior. Specification Language - Slight changes in unification error messages. - Added a syntax $(...)$ that allows putting tactics in terms (may break user notations using "$(", fixable by inserting a space or rewriting the notation). - Constructors in pattern-matching patterns now respect the same rules regarding implicit arguments as in applicative position. The old behavior can be recovered by the command "Set Asymmetric Patterns". As a side effect, notations for constructors explicitly mentioning non-implicit parameters can now be used in patterns. Considering that the pattern language is already rich enough, binding local definitions is however now forbidden in patterns (source of incompatibilities for local definitions that delta-reduce to a constructor). - Type inference algorithm now granting opacity of constants. This might also affect behavior of tactics (source of incompatibilities, solvable by re-declaring transparent constants which were set opaque). - Existential variables are now referred to by an identifier and the relevant part of their instance is displayed by default. They can be reparsed. The naming policy is yet unstable and subject to changes in future releases. Tactics - New tactic engine allowing dependent subgoals, fully backtracking (also known as multiple success) tactics, as well as tactics which can consider multiple goals together. In the new tactic engine, instantiation information of existential variables is always propagated to tactics, removing the need to manually use the "instantiate" tactics to mark propagation points. * New tactical (a+b) inserts a backtracking point. When (a+b);c fails during the execution of c, it can backtrack and try b instead of a. * New tactical (once a) removes all the backtracking points from a (i.e. it selects the first success of a). * Tactic "constructor" is now fully backtracking. In case of incompatibilities (e.g. combinatoric explosion), the former behavior of "constructor" can be retrieved by using instead "[> once constructor ..]". Thanks to backtracking, undocumented "constructor " syntax is now equivalent to "[> once (constructor; tac) ..]". * New "multimatch" variant of "match" tactic which backtracks to new branches in case of a later failure. The "match" tactic is equivalent to "once multimatch". * New selector "all:" such that "all:tac" applies tactic "tac" to all the focused goals, instead of just the first one as is the default. * A corresponding new option Set Default Goal Selector "all" makes the tactics in scripts be applied to all the focused goal by default * New selector "par:" such that "par:tac" applies the (terminating) tactic "tac" to all the focused goal in parallel. The number of worker can be selected with -async-proofs-tac-j and also limited using the coqworkmgr utility. * New tactics "revgoals", "cycle" and "swap" to reorder goals. * The semantics of recursive tactics (introduced with "Ltac t := ..." or "let rec t := ... in ...") changed slightly as t is now applied to every goal, not each goal independently. In particular it may be applied when no goals are left. This may cause tactics such as "let rec t := constructor;t" to loop indefinitely. The simple fix is to rewrite the recursive calls as follows: "let rec t := constructor;[t..]" which recovers the earlier behavior (source of rare incompatibilities). * New tactic language feature "numgoals" to count number of goals. It is accompanied by a "guard" tactic which fails if a Boolean test over integers does not pass. * New tactical "[> ... ]" to apply tactics to individual goals. * New tactic "gfail" which works like "fail" except it will also fail if every goal has been solved. * The refine tactic is changed not to use an ad hoc typing algorithm to generate subgoals. It also uses the dependent subgoal feature to generate goals to materialize every existential variable which is introduced by the refinement (source of incompatibilities). * A tactic shelve is introduced to manage the subgoals which may be solved by unification: shelve removes every goal it is applied to from focus. These goals can later be called back into focus by the Unshelve command. * A variant shelve_unifiable only removes those goals which appear as existential variables in other goals. To emulate the old refine, use "refine c;shelve_unifiable". This can still cause incompatibilities in rare occasions. * New "give_up" tactic to skip over a goal. A proof containing given up goals cannot be closed with "Qed", but only with "Admitted". - The implementation of the admit tactic has changed: no axiom is generated for the admitted sub proof. "admit" is now an alias for "give_up". Code relying on this specific behavior of "admit" can be made to work by: * Adding an "Axiom" for each admitted subproof. * Adding a single "Axiom proof_admitted : False." and the Ltac definition "Ltac admit := case proof_admitted.". - Matching using "lazymatch" was fundamentally modified. It now behaves like "match" (immediate execution of the matching branch) but without the backtracking mechanism in case of failure. - New "tryif t then u else v" tactical which executes "u" in case of success of "t" and "v" in case of failure. - New conversion tactic "native_compute": evaluates the goal (or an hypothesis) with a call-by-value strategy, using the OCaml native compiler. Useful on very intensive computations. - New "cbn" tactic, a well-behaved simpl. - Repeated identical calls to omega should now produce identical proof terms. - Tactics btauto, a reflexive Boolean tautology solver. - Tactic "tauto" was exceptionally able to destruct other connectives than the binary connectives "and", "or", "prod", "sum", "iff". This non-uniform behavior has been fixed (bug #2680) and tauto is slightly weaker (possible source of incompatibilities). On the opposite side, new tactic "dtauto" is able to destruct any record-like inductive types, superseding the old version of "tauto". - Similarly, "intuition" has been made more uniform and, where it now fails, "dintuition" can be used (possible source of incompatibilities). - New option "Unset Intuition Negation Unfolding" for deactivating automatic unfolding of "not" in intuition. - Tactic notations can now be defined locally to a module (use "Local" prefix). - Tactic "red" now reduces head beta-iota redexes (potential source of rare incompatibilities). - Tactic "hnf" now reduces inner beta-iota redexes (potential source of rare incompatibilities). - Tactic "intro H" now reduces beta-iota redexes if these hide a product (potential source of rare incompatibilities). - In Ltac matching on patterns of the form "_ pat1 ... patn" now behaves like if matching on "?X pat1 ... patn", i.e. accepting "_" to be instantiated by an applicative term (experimental at this stage, potential source of incompatibilities). - In Ltac matching on goal, types of hypotheses are now interpreted in the %type scope (possible source of incompatibilities). - "change ... in ..." and "simpl ... in ..." now properly consider nested occurrences (possible source of incompatibilities since this alters the numbering of occurrences), but do not support nested occurrences. - Tactics simpl, vm_compute and native_compute can be given a notation string to a constant as argument. - When given a reference as argument, simpl, vm_compute and native_compute now strictly interpret it as the head of a pattern starting with this reference. - The "change p with c" tactic semantics changed, now type checking "c" at each matching occurrence "t" of the pattern "p", and converting "t" with "c". - Now "appcontext" and "context" behave the same. The old buggy behavior of "context" can be retrieved at parse time by setting the "Tactic Compat Context" flag (possible source of incompatibilities). - New introduction pattern p/c which applies lemma c on the fly on the hypothesis under consideration before continuing with introduction pattern p. - New introduction pattern [= x1 .. xn] applies "injection as [x1 .. xn]" on the fly if injection is applicable to the hypothesis under consideration (idea borrowed from Georges Gonthier). Introduction pattern [=] applies "discriminate" if a discriminable equality. - New introduction patterns * and ** to respectively introduce all forthcoming dependent variables and all variables/hypotheses dependent or not. - Tactic "injection c as ipats" now clears c if c refers to an hypothesis and moves the resulting equations in the hypotheses independently of the number of ipats, which has itself to be less than the number of new hypotheses (possible source of incompatibilities; former behavior obtainable by "Unset Injection L2R Pattern Order"). - Tactic "injection" now automatically simplifies subgoals "existT n p = existT n p'" into "p = p'" when "n" is in an inductive type for which a decidable equality scheme has been generated with "Scheme Equality" (possible source of incompatibilities). - New tactic "rewrite_strat" for generalized rewriting with user-defined strategies, subsuming autorewrite. - Injection can now also deduce equality of arguments of sort Prop, by using the option "Set Injection On Proofs" (disabled by default). Also improved the error messages. - Tactic "subst id" now supports id occurring in dependent local definitions. - Bugs fixed about intro-pattern "*" might lead to some rare incompatibilities. - New tactical "time" to display time spent executing its argument. - Tactics referring or using a constant dependent in a section variable which has been cleared or renamed in the current goal context now fail (possible source of incompatibilities solvable by avoiding clearing the relevant hypotheses). - New construct "uconstr:c" and "type_term c" to build untyped terms. - Binders in terms defined in Ltac (either "constr" or "uconstr") can now take their names from identifiers defined in Ltac. As a consequence, a name cannot be used in a binder "constr:(fun x => ...)" if an Ltac variable of that name already exists and does not contain an identifier. Source of occasional incompatibilities. - The "refine" tactic now accepts untyped terms built with "uconstr" so that terms with holes can be constructed piecewise in Ltac. - New bullets --, ++, **, ---, +++, ***, ... made available. - More informative messages when wrong bullet is used. - Bullet suggestion when a subgoal is solved. - New tactic "enough", symmetric to "assert", but with subgoals swapped, as a more friendly replacement of "cut". - In destruct/induction, experimental modifier "!" prefixing the hypothesis name to tell not erasing the hypothesis. - Bug fixes in "inversion as" may occasionally lead to incompatibilities. - Behavior of introduction patterns -> and <- made more uniform (hypothesis is cleared, rewrite in hypotheses and conclusion and erasing the variable when rewriting a variable). - New experimental option "Set Standard Proposition Elimination Names" so that case analysis or induction on schemes in Type containing propositions now produces "H"-based names. - Tactics from plugins are now active only when the corresponding module is imported (source of incompatibilities, solvable by adding an "Import"; in the particular case of Omega, use "Require Import OmegaTactic"). - Semantics of destruct/induction has been made more regular in some edge cases, possibly leading to incompatibilities: + new goals are now opened when the term does not match a subterm of the goal and has unresolved holes, while in 8.4 these holes were turned into existential variables + when no "at" option is given, the historical semantics which selects all subterms syntactically identical to the first subterm matching the given pattern is used + non-dependent destruct/induction on an hypothesis with premises in an inductive type with indices is fixed + residual local definitions are now correctly removed. - The rename tactic may now replace variables in parallel. - A new "Info" command replaces the "info" tactical discontinued in v8.4. It still gives informative results in many cases. - The "info_auto" tactic is known to be broken and does not print a trace anymore. Use "Info 1 auto" instead. The same goes for "info_trivial". On the other hand "info_eauto" still works fine, while "Info 1 eauto" prints a trivial trace. - When using a lemma of the prototypical form "forall A, {a:A & P a}", "apply" and "apply in" do not instantiate anymore "A" with the current goal and use "a" as the proof, as they were sometimes doing, now considering that it is a too powerful decision. Program - "Solve Obligations using" changed to "Solve Obligations with", consistent with "Proof with". - Program Lemma, Definition now respect automatic introduction. - Program Lemma, Definition, etc.. now interpret "->" like Lemma and Definition as a non-dependent arrow (potential source of incompatibility). - Add/document "Set Hide Obligations" (to hide obligations in the final term inside an implicit argument) and "Set Shrink Obligations" (to minimize dependencies of obligations defined by tactics). Notations - The syntax "x -> y" is now declared at level 99. In particular, it has now a lower priority than "<->": "A -> B <-> C" is now "A -> (B <-> C)" (possible source of incompatibilities) - Notations accept term-providing tactics using the $(...)$ syntax. - "Bind Scope" can no longer bind "Funclass" and "Sortclass". - A notation can be given a (compat "8.x") annotation, making it behave like a "only parsing" notation, but the annotation may lead to eventually issue warnings or errors in further versions when this notation is used. - More systematic insertion of spaces as a default for printing notations ("format" still available to override the default). - In notations, a level modifier referring to a non-existent variable is now considered an error rather than silently ignored. Tools - Option -I now only adds directories to the ml path. - Option -Q behaves as -R, except that the logical path of any loaded file has to be fully qualified. - Option -R no longer adds recursively to the ml path; only the root directory is added. (Behavior with respect to the load path is unchanged.) - Option -nois prevents coq/theories and coq/plugins to be recursively added to the load path. (Same behavior as with coq/user-contrib.) - coqdep accepts a -dumpgraph option generating a dot file. - Makefiles generated through coq_makefile have three new targets "quick" "checkproofs" and "vio2vo", allowing respectively to asynchronously compile the files without playing the proof scripts, asynchronously checking that the quickly generated proofs are correct and generating the object files from the quickly generated proofs. - The XML plugin was discontinued and removed from the source. - A new utility called coqworkmgr can be used to limit the number of concurrent workers started by independent processes, like make and CoqIDE. This is of interest for users of the par: goal selector. Interfaces - CoqIDE supports asynchronous edition of the document, ongoing tasks and errors are reported in the bottom right window. The number of workers taking care of processing proofs can be selected with -async-proofs-j. - CoqIDE highlights in yellow "unsafe" commands such as axiom declarations, and tactics like "give_up". - CoqIDE supports Proof General like key bindings; to activate the PG mode go to Edit -> Preferences -> Editor. For the documentation see Help -> Help for PG mode. - CoqIDE automatically retracts the locked area when one edits the locked text. - CoqIDE search and replace got regular expressions power. See the documentation of OCaml's Str module for the supported syntax. - Many CoqIDE windows, including the query one, are now detachable to improve usability on multi screen work stations. - Coqtop/coqc outputs highlighted syntax. Colors can be configured thanks to the COQ_COLORS environment variable, and their current state can be displayed with the -list-tags command line option. - Third party user interfaces can install their main loop in $ROCQLIB/toploop and call coqtop with the -toploop flag to select it. Internal Infrastructure - Many reorganizations in the ocaml source files. For instance, many internal a.s.t. of Coq are now placed in mli files in a new directory intf/, for instance constrexpr.mli or glob_term.mli. More details in dev/doc/changes. - The file states/initial.coq does not exist anymore. Instead, coqtop initially does a "Require" of Prelude.vo (or nothing when given the options -noinit or -nois). - The format of vo files has slightly changed: cf final comments in checker/cic.mli. - The build system does not produce anymore programs named coqtop.opt and a symbolic link to coqtop. Instead, coqtop is now directly an executable compiled with the best OCaml compiler available. The bytecode program coqtop.byte is still produced. Same for other utilities. - Some options of the ./configure script slightly changed: * The -coqrunbyteflags and its blank-separated argument is replaced by option -vmbyteflags which expects a comma-separated argument. * The -coqtoolsbyteflags option is discontinued, see -no-custom instead. Miscellaneous - ML plugins now require a "DECLARE PLUGIN \"foo\"" statement. The "foo" name must be exactly the name of the ML module that will be loaded through a "Declare ML \"foo\"" command. Details of changes in 8.5beta2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logic - The VM now supports inductive types with up to 8388851 non-constant constructors and up to 8388607 constant ones. Specification language - Syntax "$(tactic)$" changed to "ltac: tactic". Tactics - A script using the admit tactic can no longer be concluded by either Qed or Defined. In the first case, Admitted can be used instead. In the second case, a subproof should be used. - The easy tactic and the now tactical now have a more predictable behavior, but they might now discharge some previously unsolved goals. Extraction - Definitions extracted to Haskell GHC should no longer randomly segfault when some Coq types cannot be represented by Haskell types. - Definitions can now be extracted to Json for post-processing. Tools - Option -I -as has been removed, and option -R -as has been deprecated. In both cases, option -R can be used instead. - coq_makefile now generates double-colon rules for rules such as clean. API - The interface of [change] has changed to take a [change_arg], which can be built from a [constr] using [make_change_arg]. Details of changes in 8.5beta3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Commands - New command "Redirect" to redirect the output of a command to a file. - New command "Undelimit Scope" to remove the delimiter of a scope. - New option "Strict Universe Declaration", set by default. It enforces the declaration of all polymorphic universes appearing in a definition when introducing it. - New command "Show id" to show goal named id. - Option "Virtual Machine" removed. Tactics - New flag "Regular Subst Tactic" which fixes "subst" in situations where it failed to substitute all substitutable equations or failed to simplify cycles, or accidentally unfolded local definitions (flag is off by default). - New flag "Loose Hint Behavior" to handle hints loaded but not imported in a special way. It accepts three distinct flags: * "Lax", which is the default one, sets the old behavior, i.e. a non-imported hint behaves the same as an imported one. * "Warn" outputs a warning when a non-imported hint is used. Note that this is an over-approximation, because a hint may be triggered by an eauto run that will eventually fail and backtrack. * "Strict" changes the behavior of an unloaded hint to the one of the fail tactic, allowing to emulate the hopefully future import-scoped hint mechanism. - New compatibility flag "Universal Lemma Under Conjunction" which let tactics working under conjunctions apply sublemmas of the form "forall A, ... -> A". - New compatibility flag "Bracketing Last Introduction Pattern" which can be set so that the last disjunctive-conjunctive introduction pattern given to "intros" automatically complete the introduction of its subcomponents, as the the disjunctive-conjunctive introduction patterns in non-terminal position already do. - New flag "Shrink Abstract" that minimalizes proofs generated by the abstract tactical w.r.t. variables appearing in the body of the proof. Program - The "Shrink Obligations" flag now applies to all obligations, not only those solved by the automatic tactic. - Importing Program no longer overrides the "exists" tactic (potential source of incompatibilities). - Hints costs are now correctly taken into account (potential source of incompatibilities). - Documented the Hint Cut command that allows control of the proof search during typeclass resolution (see reference manual). API - Some functions from pretyping/typing.ml and their derivatives were potential source of evarmap leaks, as they dropped their resulting evarmap. The situation was clarified by renaming them according to a ``unsafe_*`` scheme. Their sound variant is likewise renamed to their old name. The following renamings were made. * ``Typing.type_of`` -> ``unsafe_type_of`` * ``Typing.e_type_of`` -> ``type_of`` * A new ``e_type_of`` function that matches the ``e_`` prefix policy * ``Tacmach.pf_type_of`` -> ``pf_unsafe_type_of`` * A new safe ``pf_type_of`` function. All uses of ``unsafe_*`` functions should be eventually eliminated. Tools - Added an option -w to control the output of coqtop warnings. - Configure now takes an optional -native-compiler (yes|no) flag replacing -no-native-compiler. The new flag is set to no by default under Windows. - Flag -no-native-compiler was removed and became the default for coqc. If precompilation of files for native conversion test is desired, use -native-compiler. - The -compile command-line option now takes the full path of the considered file, including the ".v" extension, and outputs a warning if such an extension is lacking. - The -require and -load-vernac-object command-line options now take a logical path of a given library rather than a physical path, thus they behave like Require [Import] path. - The -vm command-line option has been removed. Standard Library - There is now a Coq.Compat.Coq84 library, which sets the various compatibility options and does a few redefinitions to make Coq behave more like Coq v8.4. The standard way of putting Coq in v8.4 compatibility mode is to pass the command line flags "-require Coq.Compat.Coq84 -compat 8.4". Details of changes in 8.5 ~~~~~~~~~~~~~~~~~~~~~~~~~ Tools - Flag "-compat 8.4" now loads Coq.Compat.Coq84. The standard way of putting Coq in v8.4 compatibility mode is to pass the command line flag "-compat 8.4". It can be followed by "-require Coq.Compat.AdmitAxiom" if the 8.4 behavior of admit is needed, in which case it uses an axiom. Specification language - Syntax "$(tactic)$" changed to "ltac:(tactic)". Tactics - Syntax "destruct !hyp" changed to "destruct (hyp)", and similarly for induction (rare source of incompatibilities easily solvable by removing parentheses around "hyp" when not for the purpose of keeping the hypothesis). - Syntax "p/c" for on-the-fly application of a lemma c before introducing along pattern p changed to p%c1..%cn. The feature and syntax are in experimental stage. - "Proof using" does not clear unused section variables. - Tactic "refine" has been changed back to the 8.4 behavior of shelving subgoals that occur in other subgoals. The "refine" tactic of 8.5beta3 has been renamed "simple refine"; it does not shelve any subgoal. - New tactical "unshelve tac" which grab existential variables put on the tactic shelve by the execution of "tac". Details of changes in 8.5pl1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Critical bugfix - The subterm relation for the guard condition was incorrectly defined on primitive projections (#4588) Plugin development tools - add a .merlin target to the makefile Various performance improvements (time, space used by .vo files) Other bugfixes - Fix order of arguments to Big.compare_case in ExtrOcamlZBigInt.v - Added compatibility coercions from Specif.v which were present in Coq 8.4. - Fixing a source of inefficiency and an artificial dependency in the printer in the congruence tactic. - Allow to unset the refinement mode of Instance in ML - Fixing an incorrect use of prod_appvect on a term which was not a product in setoid_rewrite. - Add -compat 8.4 econstructor tactics, and tests - Add compatibility Nonrecursive Elimination Schemes - Fixing the "No applicable tactic" uninformative error message regression on apply. - Univs: fix get_current_context (bug #4603, part I) - Fix a bug in Program coercion code - Fix handling of arity of definitional classes. - #4630: Some tactics are 20x slower in 8.5 than 8.4. - #4627: records with no declared arity can be template polymorphic. - #4623: set tactic too weak with universes (regression) - Fix incorrect behavior of CS resolution - #4591: Uncaught exception in directory browsing. - CoqIDE is more resilient to initialization errors. - #4614: "Fully check the document" is uninterruptible. - Try eta-expansion of records only on non-recursive ones - Fix bug when a sort is ascribed to a Record - Primitive projections: protect kernel from erroneous definitions. - Fixed bug #4533 with previous Keyed Unification commit - Win: kill unreliable hence do not waitpid after kill -9 (Close #4369) - Fix strategy of Keyed Unification - #4608: Anomaly "output_value: abstract value (outside heap)". - #4607: do not read native code files if native compiler was disabled. - #4105: poor escaping in the protocol between CoqIDE and coqtop. - #4596: [rewrite] broke in the past few weeks. - #4533 (partial): respect declared global transparency of projections in unification.ml - #4544: Backtrack on using full betaiota reduction during keyed unification. - #4540: CoqIDE bottom progress bar does not update. - Fix regression from 8.4 in reflexivity - #4580: [Set Refine Instance Mode] also used for Program Instance. - #4582: cannot override notation [ x ]. MAY CREATE INCOMPATIBILITIES, see #4683. - STM: Print/Extraction have to be skipped if -quick - #4542: CoqIDE: STOP button also stops workers - STM: classify some variants of Instance as regular `` `Fork `` nodes. - #4574: Anomaly: Uncaught exception Invalid_argument("splay_arity"). - Do not give a name to anonymous evars anymore. See bug #4547. - STM: always stock in vio files the first node (state) of a proof - STM: not delegate proofs that contain Vernac(Module|Require|Import), #4530 - Don't fail fatally if PATH is not set. - #4537: Coq 8.5 is slower in typeclass resolution. - #4522: Incorrect "Warning..." on windows. - #4373: coqdep does not know about .vio files. - #3826: "Incompatible module types" is uninformative. - #4495: Failed assertion in metasyntax.ml. - #4511: evar tactic can create non-typed evars. - #4503: mixing universe polymorphic and monomorphic variables and definitions in sections is unsupported. - #4519: oops, global shadowed local universe level bindings. - #4506: Anomaly: File "pretyping/indrec.ml", line 169, characters 14-20: Assertion failed. - #4548: CoqIDE crashes when going back one command Details of changes in 8.5pl2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Critical bugfix - Checksums of .vo files dependencies were not correctly checked. - Unicode-to-ASCII translation was not injective, leading in a soundness bug in the native compiler. Other bugfixes - #4097: more efficient occur-check in presence of primitive projections - #4398: type_scope used consistently in "match goal". - #4450: eauto does not work with polymorphic lemmas - #4677: fix alpha-conversion in notations needing eta-expansion. - Fully preserve initial order of hypotheses in "Regular Subst Tactic" mode. - #4644: a regression in unification. - #4725: Function (Error: Conversion test raised an anomaly) and Program (Error: Cannot infer this placeholder of type) - #4747: Problem building Coq 8.5pl1 with OCaml 4.03.0: Fatal warnings - #4752: CoqIDE crash on files not ended by ".v". - #4777: printing inefficiency with implicit arguments - #4818: "Admitted" fails due to undefined universe anomaly after calling "destruct" - #4823: remote counter: avoid thread race on sockets - #4841: -verbose flag changed semantics in 8.5, is much harder to use - #4851: [nsatz] cannot handle duplicated hypotheses - #4858: Anomaly: Uncaught exception Failure("hd"). Please report. in variant of nsatz - #4880: [nsatz_compute] generates invalid certificates if given redundant hypotheses - #4881: synchronizing "Declare Implicit Tactic" with backtrack. - #4882: anomaly with Declare Implicit Tactic on hole of type with evars - Fix use of "Declare Implicit Tactic" in refine. triggered by CoqIDE - #4069, #4718: congruence fails when universes are involved. Universes - Disallow silently dropping universe instances applied to variables (forward compatible) - Allow explicit universe instances on notations, when they can apply to the head reference of their expansion. Build infrastructure - New update on how to find camlp5 binary and library at configure time. Details of changes in 8.5pl3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Critical bugfix - #4876: Guard checker incompleteness when using primitive projections Other bugfixes - #4780: Induction with universe polymorphism on was creating ill-typed terms. - #4673: regression in setoid_rewrite, unfolding let-ins for type unification. - #4754: Regression in setoid_rewrite, allow postponed unification problems to remain. - #4769: Anomaly with universe polymorphic schemes defined inside sections. - #3886: Program: duplicate obligations of mutual fixpoints. - #4994: Documentation typo. - #5008: Use the "md5" command on OpenBSD. - #5007: Do not assume the "TERM" environment variable is always set. - #4606: Output a break before a list only if there was an empty line. - #5001: metas not cleaned properly in clenv_refine_in. - #2336: incorrect glob data for module symbols (bug #2336). - #4832: Remove extraneous dot in error message. - Anomaly in printing a unification error message. - #4947: Options which take string arguments are not backwards compatible. - #4156: micromega cache files are now hidden files. - #4871: interrupting par:abstract kills coqtop. - #5043: [Admitted] lemmas pick up section variables. - Fix name of internal refine ("simple refine"). - #5062: probably a typo in Strict Proofs mode. - #5065: Anomaly: Not a proof by induction. - Restore native compiler optimizations, they were disabled since 8.5! - #5077: failure on typing a fixpoint with evars in its type. - Fix recursive notation bug. - #5095: irrelevant too strict test in let-in abstraction. - Ensuring that the evar name is preserved by "rename". - #4887: confusion between using and with in documentation of firstorder. - Bug in subst with let-ins. - #4762: eauto weaker than auto. - Remove if_then_else (was buggy). Use tryif instead. - #4970: confusion between special "{" and non-special "{{" in notations. - #4529: primitive projections unfolding. - #4416: Incorrect "Error: Incorrect number of goals". - #4863: abstract in typeclass hint fails. - #5123: unshelve can impact typeclass resolution - Fix a collision about the meta-variable ".." in recursive notations. - Fix printing of info_auto. - #3209: Not_found due to an occur-check cycle. - #5097: status of evars refined by "clear" in ltac: closed wrt evars. - #5150: Missing dependency of the test-suite subsystems in prerequisite. - Fix a bug in error printing of unif constraints - #3941: Do not stop propagation of signals when Coq is busy. - #4822: Incorrect assertion in cbn. - #3479 parsing of "{" and "}" when a keyword starts with "{" or "}". - #5127: Memory corruption with the VM. - #5102: bullets parsing broken by calls to parse_entry. Various documentation improvements Version 8.4 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.4 contains the result of three long-term projects: a new modular library of arithmetic by Pierre Letouzey, a new proof engine by Arnaud Spiwack and a new communication protocol for CoqIDE by Vincent Gross. The new modular library of arithmetic extends, generalizes and unifies the existing libraries on Peano arithmetic (types nat, N and BigN), positive arithmetic (type positive), integer arithmetic (Z and BigZ) and machine word arithmetic (type Int31). It provides with unified notations (e.g. systematic use of add and mul for denoting the addition and multiplication operators), systematic and generic development of operators and properties of these operators for all the types mentioned above, including gcd, pcm, power, square root, base 2 logarithm, division, modulo, bitwise operations, logical shifts, comparisons, iterators, ... The most visible feature of the new proof engine is the support for structured scripts (bullets and proof brackets) but, even if yet not user-available, the new engine also provides the basis for refining existential variables using tactics, for applying tactics to several goals simultaneously, for reordering goals, all features which are planned for the next release. The new proof engine forced Pierre Letouzey to reimplement info and Show Script differently. Before version 8.4, CoqIDE was linked to Coq with the graphical interface living in a separate thread. From version 8.4, CoqIDE is a separate process communicating with Coq through a textual channel. This allows for a more robust interfacing, the ability to interrupt Coq without interrupting the interface, and the ability to manage several sessions in parallel. Relying on the infrastructure work made by Vincent Gross, Pierre Letouzey, Pierre Boutillier and Pierre-Marie PΓ©drot contributed many various refinements of CoqIDE. Coq 8.4 also comes with a bunch of various smaller-scale changes and improvements regarding the different components of the system. The underlying logic has been extended with Ξ·-conversion thanks to Hugo Herbelin, StΓ©phane Glondu and Benjamin GrΓ©goire. The addition of Ξ·-conversion is justified by the confidence that the formulation of the Calculus of Inductive Constructions based on typed equality (such as the one considered in Lee and Werner to build a set-theoretic model of CICΒ :cite:`LeeWerner11`) is applicable to the concrete implementation of Coq. The underlying logic benefited also from a refinement of the guard condition for fixpoints by Pierre Boutillier, the point being that it is safe to propagate the information about structurally smaller arguments through Ξ²-redexes that are blocked by the β€œmatch” construction (blocked commutative cuts). Relying on the added permissiveness of the guard condition, Hugo Herbelin could extend the pattern matching compilation algorithm so that matching over a sequence of terms involving dependencies of a term or of the indices of the type of a term in the type of other terms is systematically supported. Regarding the high-level specification language, Pierre Boutillier introduced the ability to give implicit arguments to anonymous functions, Hugo Herbelin introduced the ability to define notations with several binders (e.g. ``exists x y z, P``), Matthieu Sozeau made the typeclass inference mechanism more robust and predictable, Enrico Tassi introduced a command Arguments that generalizes Implicit Arguments and Arguments Scope for assigning various properties to arguments of constants. Various improvements in the type inference algorithm were provided by Matthieu Sozeau and Hugo Herbelin with contributions from Enrico Tassi. Regarding tactics, Hugo Herbelin introduced support for referring to expressions occurring in the goal by pattern in tactics such as set or destruct. Hugo Herbelin also relied on ideas from Chung-Kil Hur’s Heq plugin to introduce automatic computation of occurrences to generalize when using destruct and induction on types with indices. StΓ©phane Glondu introduced new tactics :tacn:`constr_eq`, :tacn:`is_evar`, and :tacn:`has_evar`, to be used when writing complex tactics. Enrico Tassi added support to fine-tuning the behavior of :tacn:`simpl`. Enrico Tassi added the ability to specify over which variables of a section a lemma has to be exactly generalized. Pierre Letouzey added a tactic timeout and the interruptibility of :tacn:`vm_compute`. Bug fixes and miscellaneous improvements of the tactic language came from Hugo Herbelin, Pierre Letouzey and Matthieu Sozeau. Regarding decision tactics, LoΓ―c Pottier maintained nsatz, moving in particular to a typeclass based reification of goals while FrΓ©dΓ©ric Besson maintained Micromega, adding in particular support for division. Regarding commands, StΓ©phane Glondu provided new commands to analyze the structure of type universes. Regarding libraries, a new library about lists of a given length (called vectors) has been provided by Pierre Boutillier. A new instance of finite sets based on Red-Black trees and provided by Andrew Appel has been adapted for the standard library by Pierre Letouzey. In the library of real analysis, Yves Bertot changed the definition of :math:`\pi` and provided a proof of the long-standing fact yet remaining unproved in this library, namely that :math:`sin \frac{\pi}{2} = 1`. Pierre Corbineau maintained the Mathematical Proof Language (C-zar). Bruno Barras and Benjamin GrΓ©goire maintained the call-by-value reduction machines. The extraction mechanism benefited from several improvements provided by Pierre Letouzey. Pierre Letouzey maintained the module system, with contributions from Γ‰lie Soubiran. Julien Forest maintained the Function command. Matthieu Sozeau maintained the setoid rewriting mechanism. Coq related tools have been upgraded too. In particular, coq\_makefile has been largely revised by Pierre Boutillier. Also, patches from Adam Chlipala for coqdoc have been integrated by Pierre Boutillier. Bruno Barras and Pierre Letouzey maintained the `coqchk` checker. Pierre Courtieu and Arnaud Spiwack contributed new features for using Coq through Proof General. The Dp plugin has been removed. Use the plugin provided with Why 3 instead (http://why3.lri.fr/). Under the hood, the Coq architecture benefited from improvements in terms of efficiency and robustness, especially regarding universes management and existential variables management, thanks to Pierre Letouzey and Yann RΓ©gis-Gianas with contributions from StΓ©phane Glondu and Matthias Puech. The build system is maintained by Pierre Letouzey with contributions from StΓ©phane Glondu and Pierre Boutillier. A new backtracking mechanism simplifying the task of external interfaces has been designed by Pierre Letouzey. The general maintenance was done by Pierre Letouzey, Hugo Herbelin, Pierre Boutillier, Matthieu Sozeau and StΓ©phane Glondu with also specific contributions from Guillaume Melquiond, Julien Narboux and Pierre-Marie PΓ©drot. Packaging tools were provided by Pierre Letouzey (Windows), Pierre Boutillier (MacOS), StΓ©phane Glondu (Debian). Releasing, testing and benchmarking support was provided by Jean-Marc Notin. Many suggestions for improvements were motivated by feedback from users, on either the bug tracker or the Coq-Club mailing list. Special thanks are going to the users who contributed patches, starting with Tom Prince. Other patch contributors include CΓ©dric Auger, David Baelde, Dan Grayson, Paolo Herms, Robbert Krebbers, Marc Lasson, Hendrik Tews and Eelis van der Weegen. | Paris, December 2011 | Hugo Herbelin | Potential sources of incompatibilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main known incompatibilities between 8.3 and 8.4 are consequences of the following changes: - The reorganization of the library of numbers: Several definitions have new names or are defined in modules of different names, but a special care has been taken to have this renaming transparent for the user thanks to compatibility notations. However some definitions have changed, what might require some adaptations. The most noticeable examples are: + The "?=" notation which now bind to Pos.compare rather than former Pcompare (now Pos.compare_cont). + Changes in names may induce different automatically generated names in proof scripts (e.g. when issuing "destruct Z_le_gt_dec"). + Z.add has a new definition, hence, applying "simpl" on subterms of its body might give different results than before. + BigN.shiftl and BigN.shiftr have reversed arguments order, the power function in BigN now takes two BigN. - Other changes in libraries: + The definition of functions over "vectors" (list of fixed length) have changed. + TheoryList.v has been removed. - Slight changes in tactics: + Less unfolding of fixpoints when applying destruct or inversion on a fixpoint hiding an inductive type (add an extra call to simpl to preserve compatibility). + Less unexpected local definitions when applying "destruct" (incompatibilities solvable by adapting name hypotheses). + Tactic "apply" might succeed more often, e.g. by now solving pattern-matching of the form ?f x y = g(x,y) (compatibility ensured by using "Unset Tactic Pattern Unification"), but also because it supports (full) betaiota (using "simple apply" might then help). + Tactic autorewrite does no longer instantiate pre-existing existential variables. + Tactic "info" is now available only for auto, eauto and trivial. - Miscellaneous changes: + The command "Load" is now atomic for backtracking (use "Unset Atomic Load" for compatibility). Details of changes in 8.4beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logic - Standard eta-conversion now supported (dependent product only). - Guard condition improvement: subterm property is propagated through beta-redex blocked by pattern-matching, as in "(match v with C .. => fun x => u end) x"; this allows for instance to use "rewrite ... in ..." without breaking the guard condition. Specification language and notations - Maximal implicit arguments can now be set locally by { }. The registration traverses fixpoints and lambdas. Because there is conversion in types, maximal implicit arguments are not taken into account in partial applications (use eta expanded form with explicit { } instead). - Added support for recursive notations with binders (allows for instance to write "exists x y z, P"). - Structure/Record printing can be disable by "Unset Printing Records". In addition, it can be controlled on type by type basis using "Add Printing Record" or "Add Printing Constructor". - Pattern-matching compilation algorithm: in "match x, y with ... end", possible dependencies of x (or of the indices of its type) in the type of y are now taken into account. Tactics - New proof engine. - Scripts can now be structured thanks to bullets - * + and to subgoal delimitation via { }. Note: for use with Proof General, a cvs version of Proof General no older than mid-July 2011 is currently required. - Support for tactical "info" is suspended. - Support for command "Show Script" is suspended. - New tactics constr_eq, is_evar and has_evar for use in Ltac (DOC TODO). - Removed the two-argument variant of "decide equality". - New experimental tactical "timeout ". Since is a time in second for the moment, this feature should rather be avoided in scripts meant to be machine-independent. - Fix in "destruct": removal of unexpected local definitions in context might result in some rare incompatibilities (solvable by adapting name hypotheses). - Introduction pattern "_" made more robust. - Tactic (and Eval command) vm_compute can now be interrupted via Ctrl-C. - Unification in "apply" supports unification of patterns of the form ?f x y = g(x,y) (compatibility ensured by using "Unset Tactic Pattern Unification"). It also supports (full) betaiota. - Tactic autorewrite does no longer instantiate pre-existing existential variables (theoretical source of possible incompatibilities). - Tactic "dependent rewrite" now supports equality in "sig". - Tactic omega now understands Zpred (wish #1912) and can prove any goal from a context containing an arithmetical contradiction (wish #2236). - Using "auto with nocore" disables the use of the "core" database (wish #2188). This pseudo-database "nocore" can also be used with trivial and eauto. - Tactics "set", "destruct" and "induction" accepts incomplete terms and use the goal to complete the pattern assuming it is unambiguous. - When used on arguments with a dependent type, tactics such as "destruct", "induction", "case", "elim", etc. now try to abstract automatically the dependencies over the arguments of the types (based on initial ideas from Chung-Kil Hur, extension to nested dependencies suggested by Dan Grayson) - Tactic "injection" now failing on an equality showing no constructors while it was formerly generalizing again the goal over the given equality. - In Ltac, the "context [...]" syntax has now a variant "appcontext [...]" allowing to match partial applications in larger applications. - When applying destruct or inversion on a fixpoint hiding an inductive type, recursive calls to the fixpoint now remain folded by default (rare source of incompatibility generally solvable by adding a call to simpl). - In an ltac pattern containing a "match", a final "| _ => _" branch could be used now instead of enumerating all remaining constructors. Moreover, the pattern "match _ with _ => _ end" now allows to match any "match". A "in" annotation can also be added to restrict to a precise inductive type. - The behavior of "simpl" can be tuned using the "Arguments" vernacular. In particular constants can be marked so that they are always/never unfolded by "simpl", or unfolded only when a set of arguments evaluates to a constructor. Last one can mark a constant so that it is unfolded only if the simplified term does not expose a match in head position. Commands - It is now mandatory to have a space (or tabulation or newline or end-of-file) after a "." ending a sentence. - In SearchAbout, the [ ] delimiters are now optional. - New command "Add/Remove Search Blacklist ...": a Search or SearchAbout or similar query will never mention lemmas whose qualified names contain any of the declared substrings. The default blacklisted substrings are ``_subproof``, ``Private_``. - When the output file of "Print Universes" ends in ".dot" or ".gv", the universe graph is printed in the DOT language, and can be processed by Graphviz tools. - New command "Print Sorted Universes". - The undocumented and obsolete option "Set/Unset Boxed Definitions" has been removed, as well as syntaxes like "Boxed Fixpoint foo". - A new option "Set Default Timeout n / Unset Default Timeout". - Qed now uses information from the reduction tactics used in proof script to avoid conversion at Qed time to go into a very long computation. - New command "Show Goal ident" to display the statement of a goal, even a closed one (available from Proof General). - Command "Proof" accept a new modifier "using" to force generalization over a given list of section variables at section ending (DOC TODO). - New command "Arguments" generalizing "Implicit Arguments" and "Arguments Scope" and that also allows to rename the parameters of a definition and to tune the behavior of the tactic "simpl". Module System - During subtyping checks, an opaque constant in a module type could now be implemented by anything of the right type, even if bodies differ. Said otherwise, with respect to subtyping, an opaque constant behaves just as a parameter. Coqchk was already implementing this, but not coqtop. - The inlining done during application of functors can now be controlled more precisely, by the annotations (no inline) or (inline at level XX). With the latter annotation, only functor parameters whose levels are lower or equal than XX will be inlined. The level of a parameter can be fixed by "Parameter Inline(30) foo". When levels aren't given, the default value is 100. One can also use the flag "Set Inline Level ..." to set a level (DOC TODO). - Print Assumptions should now handle correctly opaque modules (#2168). - Print Module (Type) now tries to print more details, such as types and bodies of the module elements. Note that Print Module Type could be used on a module to display only its interface. The option "Set Short Module Printing" could be used to switch back to the earlier behavior were only field names were displayed. Libraries - Extension of the abstract part of Numbers, which now provide axiomatizations and results about many more integer functions, such as pow, gcd, lcm, sqrt, log2 and bitwise functions. These functions are implemented for nat, N, BigN, Z, BigZ. See in particular file NPeano for new functions about nat. - The definition of types positive, N, Z is now in file BinNums.v - Major reorganization of ZArith. The initial file ZArith/BinInt.v now contains an internal module Z implementing the Numbers interface for integers. This module Z regroups: * all functions over type Z : Z.add, Z.mul, ... * the minimal proofs of specifications for these functions : Z.add_0_l, ... * an instantiation of all derived properties proved generically in Numbers : Z.add_comm, Z.add_assoc, ... A large part of ZArith is now simply compatibility notations, for instance Zplus_comm is an alias for Z.add_comm. The direct use of module Z is now recommended instead of relying on these compatibility notations. - Similar major reorganization of NArith, via a module N in NArith/BinNat.v - Concerning the positive datatype, BinPos.v is now in a specific directory PArith, and contains an internal submodule Pos. We regroup there functions such as Pos.add Pos.mul etc as well as many results about them. These results are here proved directly (no Number interface for strictly positive numbers). - Note that in spite of the compatibility layers, all these reorganizations may induce some marginal incompatibilies in scripts. In particular: * the "?=" notation for positive now refers to a binary function Pos.compare, instead of the infamous ternary Pcompare (now Pos.compare_cont). * some hypothesis names generated by the system may changed (typically for a "destruct Z_le_gt_dec") since naming is done after the short name of the head predicate (here now "le" in module Z instead of "Zle", etc). * the internals of Z.add has changed, now relying of Z.pos_sub. - Also note these new notations: * "= XP SP1. - The communication between CoqIDE and coqtop is now done via a dialect of XML (DOC TODO). - The backtrack engine of CoqIDE has been reworked, it now uses the "Backtrack" command similarly to Proof General. - The CoqIDE parsing of sentences has be reworked and now supports tactic delimitation via { }. - CoqIDE now accepts the Abort command (wish #2357). - CoqIDE can read coq_makefile files as "project file" and use it to set automatically options to send to coqtop. - Preference files have moved to $XDG_CONFIG_HOME/coq and accelerators are not stored as a list anymore. Tools - Coq now searches directories specified in COQPATH, $XDG_DATA_HOME/coq, $XDG_DATA_DIRS/coq, and user-contribs before the standard library. - Coq rc file has moved to $XDG_CONFIG_HOME/coq. - Major changes to coq_makefile: * mli/mlpack/mllib taken into account, ml not preproccessed anymore, ml4 work; * mlihtml generates doc of mli, install-doc install the html doc in DOCDIR with the same policy as vo in COQLIB; * More variables are given by coqtop -config, others are defined only if the users doesn't have defined them elsewhere. Consequently, generated makefile should work directly on any architecture; * Packagers can take advantage of $(DSTROOT) introduction. Installation can be made in $XDG_DATA_HOME/coq; * -arg option allows to send option as argument to coqc. Details of changes in 8.4beta2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Commands - Commands "Back" and "BackTo" are now handling the proof states. They may perform some extra steps of backtrack to avoid states where the proof state is unavailable (typically a closed proof). - The commands "Suspend" and "Resume" have been removed. - A basic Show Script has been reintroduced (no indentation). - New command "Set Parsing Explicit" for deactivating parsing (and printing) of implicit arguments (useful for teaching). - New command "Grab Existential Variables" to transform the unresolved evars at the end of a proof into goals. Tactics - Still no general "info" tactical, but new specific tactics info_auto, info_eauto, info_trivial which provides information on the proofs found by auto/eauto/trivial. Display of these details could also be activated by "Set Info Auto"/"Set Info Eauto"/"Set Info Trivial". - Details on everything tried by auto/eauto/trivial during a proof search could be obtained by "debug auto", "debug eauto", "debug trivial" or by a global "Set Debug Auto"/"Set Debug Eauto"/"Set Debug Trivial". - New command "r string" in Ltac debugger that interprets "idtac string" in Ltac code as a breakpoint and jumps to its next use. - Tactics from the Dp plugin (simplify, ergo, yices, cvc3, z3, cvcl, harvey, zenon, gwhy) have been removed, since Why2 has not been maintained for the last few years. The Why3 plugin should be a suitable replacement in most cases. Libraries - MSetRBT: a new implementation of MSets via Red-Black trees (initial contribution by Andrew Appel). - MSetAVL: for maximal sharing with the new MSetRBT, the argument order of Node has changed (this should be transparent to regular MSets users). Module System - The names of modules (and module types) are now in a fully separated namespace from ordinary definitions: "Definition E:=0. Module E. End E." is now accepted. CoqIDE - CoqIDE now supports the "Restart" command, and "Undo" (with a warning). Better support for "Abort". Details of changes in 8.4 ~~~~~~~~~~~~~~~~~~~~~~~~~ Commands - The "Reset" command is now supported again in files given to coqc or Load. - "Show Script" now indents again the displayed scripts. It can also work correctly across Load'ed files if the option "Unset Atomic Load" is used. - "Open Scope" can now be given the delimiter (e.g. Z) instead of the full scope name (e.g. Z_scope). Notations - Most compatibility notations of the standard library are now tagged as (compat xyz), where xyz is a former Coq version, for instance "8.3". These notations behave as (only parsing) notations, except that they may triggers warnings (or errors) when used while Coq is not in a corresponding -compat mode. - To activate these compatibility warnings, use "Set Verbose Compat Notations" or the command-line flag -verbose-compat-notations. - For a strict mode without these compatibility notations, use "Unset Compat Notations" or the command-line flag -no-compat-notations. Tactics - An annotation "eqn:H" or "eqn:?" can be added to a "destruct" or "induction" to make it generate equations in the spirit of "case_eq". The former syntax "_eqn" is discontinued. - The name of the hypothesis introduced by tactic "remember" can be set via the new syntax "remember t as x eqn:H" (wish #2489). Libraries - Reals: changed definition of PI, no more axiom about sin(PI/2). - SetoidPermutation: a notion of permutation for lists modulo a setoid equality. - BigN: fixed the ocaml code doing the parsing/printing of big numbers. - List: a couple of lemmas added especially about no-duplication, partitions. - Init: Removal of the coercions between variants of sigma-types and subset types (possible source of incompatibility). Version 8.3 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.3 is before all a transition version with refinements or extensions of the existing features and libraries and a new tactic nsatz based on Hilbert’s Nullstellensatz for deciding systems of equations over rings. With respect to libraries, the main evolutions are due to Pierre Letouzey with a rewriting of the library of finite sets FSets and a new round of evolutions in the modular development of arithmetic (library Numbers). The reason for making FSets evolve is that the computational and logical contents were quite intertwined in the original implementation, leading in some cases to longer computations than expected and this problem is solved in the new MSets implementation. As for the modular arithmetic library, it was only dealing with the basic arithmetic operators in the former version and its current extension adds the standard theory of the division, min and max functions, all made available for free to any implementation of :math:`\mathbb{N}`, :math:`\mathbb{Z}` or :math:`\mathbb{Z}/n\mathbb{Z}`. The main other evolutions of the library are due to Hugo Herbelin who made a revision of the sorting library (including a certified merge-sort) and to Guillaume Melquiond who slightly revised and cleaned up the library of reals. The module system evolved significantly. Besides the resolution of some efficiency issues and a more flexible construction of module types, Γ‰lie Soubiran brought a new model of name equivalence, the :math:`\Delta`-equivalence, which respects as much as possible the names given by the users. He also designed with Pierre Letouzey a new, convenient operator ``<+`` for nesting functor application that provides a light notation for inheriting the properties of cascading modules. The new tactic nsatz is due to LoΓ―c Pottier. It works by computing GrΓΆbner bases. Regarding the existing tactics, various improvements have been done by Matthieu Sozeau, Hugo Herbelin and Pierre Letouzey. Matthieu Sozeau extended and refined the typeclasses and Program features (the Russell language). Pierre Letouzey maintained and improved the extraction mechanism. Bruno Barras and Γ‰lie Soubiran maintained the Coq checker, Julien Forest maintained the Function mechanism for reasoning over recursively defined functions. Matthieu Sozeau, Hugo Herbelin and Jean-Marc Notin maintained coqdoc. FrΓ©dΓ©ric Besson maintained the Micromega platform for deciding systems of inequalities. Pierre Courtieu maintained the support for the Proof General Emacs interface. Claude MarchΓ© maintained the plugin for calling external provers (dp). Yves Bertot made some improvements to the libraries of lists and integers. Matthias Puech improved the search functions. Guillaume Melquiond usefully contributed here and there. Yann RΓ©gis-Gianas grounded the support for Unicode on a more standard and more robust basis. Though invisible from outside, Arnaud Spiwack improved the general process of management of existential variables. Pierre Letouzey and StΓ©phane Glondu improved the compilation scheme of the Coq archive. Vincent Gross provided support to CoqIDE. Jean-Marc Notin provided support for benchmarking and archiving. Many users helped by reporting problems, providing patches, suggesting improvements or making useful comments, either on the bug tracker or on the Coq-Club mailing list. This includes but not exhaustively CΓ©dric Auger, Arthur CharguΓ©raud, FranΓ§ois Garillot, Georges Gonthier, Robin Green, StΓ©phane Lescuyer, Eelis van der Weegen,Β ... Though not directly related to the implementation, special thanks are going to Yves Bertot, Pierre CastΓ©ran, Adam Chlipala, and Benjamin Pierce for the excellent teaching materials they provided. | Paris, April 2010 | Hugo Herbelin | Details of changes ~~~~~~~~~~~~~~~~~~ Rewriting tactics - Tactic "rewrite" now supports rewriting on ad hoc equalities such as eq_true. - "Hint Rewrite" now checks that the lemma looks like an equation. - New tactic "etransitivity". - Support for heterogeneous equality (JMeq) in "injection" and "discriminate". - Tactic "subst" now supports heterogeneous equality and equality proofs that are dependent (use "simple subst" for preserving compatibility). - Added support for Leibniz-rewriting of dependent hypotheses. - Renamed "Morphism" into "Proper" and "respect" into "proper_prf" (possible source of incompatibility). A partial fix is to define "Notation Morphism R f := (Proper (R%signature) f)." - New tactic variants "rewrite* by" and "autorewrite*" that rewrite respectively the first and all matches whose side-conditions are solved. - "Require Import Setoid" does not export all of "Morphisms" and "RelationClasses" anymore (possible source of incompatibility, fixed by importing "Morphisms" too). - Support added for using Chung-Kil Hur's Heq library for rewriting over heterogeneous equality (courtesy of the library's author). - Tactic "replace" supports matching terms with holes. Automation tactics - Tactic ``intuition`` now preserves inner ``iff`` and ``not`` (exceptional source of incompatibilities solvable by redefining ``intuition`` as ``unfold iff, not in *; intuition``, or, for iff only, by using ``Set Intuition Iff Unfolding``.) - Tactic ``tauto`` now proves classical tautologies as soon as classical logic (i.e. library ``Classical_Prop`` or ``Classical``) is loaded. - Tactic ``gappa`` has been removed from the Dp plugin. - Tactic ``firstorder`` now supports the combination of its ``using`` and ``with`` options. - New ``Hint Resolve ->`` (or ``<-``) for declaring iff's as oriented hints (wish #2104). - An inductive type as argument of the ``using`` option of ``auto`` / ``eauto`` / ``firstorder`` is interpreted as using the collection of its constructors. - New decision tactic "nsatz" to prove polynomial equations by computation of Groebner bases. Other tactics - Tactic "discriminate" now performs intros before trying to discriminate an hypothesis of the goal (previously it applied intro only if the goal had the form t1<>t2) (exceptional source of incompatibilities - former behavior can be obtained by "Unset Discriminate Introduction"). - Tactic "quote" now supports quotation of arbitrary terms (not just the goal). - Tactic "idtac" now displays its "list" arguments. - New introduction patterns "*" for introducing the next block of dependent variables and "**" for introducing all quantified variables and hypotheses. - Pattern Unification for existential variables activated in tactics and new option "Unset Tactic Evars Pattern Unification" to deactivate it. - Resolution of canonical structure is now part of the tactic's unification algorithm. - New tactic "decide lemma with hyp" for rewriting decidability lemmas when one knows which side is true. - Improved support of dependent goals over objects in dependent types for "destruct" (rare source of incompatibility that can be avoided by unsetting option "Dependent Propositions Elimination"). - Tactic "exists", "eexists", "destruct" and "edestruct" supports iteration using comma-separated arguments. - Tactic names "case" and "elim" now support clauses "as" and "in" and become then synonymous of "destruct" and "induction" respectively. - A new tactic name "exfalso" for the use of 'ex-falso quodlibet' principle. This tactic is simply a shortcut for "elimtype False". - Made quantified hypotheses get the name they would have if introduced in the context (possible but rare source of incompatibilities). - When applying a component of a conjunctive lemma, "apply in" (and sequences of "apply in") now leave the side conditions of the lemmas uniformly after the main goal (possible source of rare incompatibilities). - In "simpl c" and "change c with d", c can be a pattern. - Tactic "revert" now preserves let-in's making it the exact inverse of "intro". - New tactics "clear dependent H" and "revert dependent H" that clears (resp. reverts) H and all the hypotheses that depend on H. - Ltac's pattern-matching now supports matching metavariables that depend on variables bound upwards in the pattern. Tactic definitions - Ltac definitions support Local option for non-export outside modules. - Support for parsing non-empty lists with separators in tactic notations. - New command "Locate Ltac" to get the full name of an Ltac definition. Notations - Record syntax ``{|x=...; y=...|}`` now works inside patterns too. - Abbreviations from non-imported module now invisible at printing time. - Abbreviations now use implicit arguments and arguments scopes for printing. - Abbreviations to pure names now strictly behave like the name they refer to (make redirections of qualified names easier). - Abbreviations for applied constant now propagate the implicit arguments and arguments scope of the underlying reference (possible source of incompatibilities generally solvable by changing such abbreviations from e.g. ``Notation foo' := (foo x)`` to ``Notation foo' y := (foo x (y:=y))``). - The "where" clause now supports multiple notations per defined object. - Recursive notations automatically expand one step on the left for better factorization; recursion notations inner separators now ensured being tokens. - Added "Reserved Infix" as a specific shortcut of the corresponding "Reserved Notation". - Open/Close Scope command supports Global option in sections. Specification language - New support for local binders in the syntax of Record/Structure fields. - Fixpoint/CoFixpoint now support building part or all of bodies using tactics. - Binders given before ":" in lemmas and in definitions built by tactics are now automatically introduced (possible source of incompatibility that can be resolved by invoking "Unset Automatic Introduction"). - New support for multiple implicit arguments signatures per reference. Module system - Include Type is now deprecated since Include now accepts both modules and module types. - Declare ML Module supports Local option. - The sharing between non-logical object and the management of the name-space has been improved by the new "Delta-equivalence" on qualified name. - The include operator has been extended to high-order structures - Sequences of Include can be abbreviated via new syntax "<+". - A module (or module type) can be given several "<:" signatures. - Interactive proofs are now permitted in module type. Functors can hence be declared as Module Type and be used later to type themselves. - A functor application can be prefixed by a "!" to make it ignore any "Inline" annotation in the type of its argument(s) (for examples of use of the new features, see libraries Structures and Numbers). - Coercions are now active only when modules are imported (use "Set Automatic Coercions Import" to get the behavior of the previous versions of Coq). Extraction - When using (Recursive) Extraction Library, the filenames are directly the Coq ones with new appropriate extensions : we do not force anymore uncapital first letters for Ocaml and capital ones for Haskell. - The extraction now tries harder to avoid code transformations that can be dangerous for the complexity. In particular many eta-expansions at the top of functions body are now avoided, clever partial applications will likely be preserved, let-ins are almost always kept, etc. - In the same spirit, auto-inlining is now disabled by default, except for induction principles, since this feature was producing more frequently weird code than clear gain. The previous behavior can be restored via "Set Extraction AutoInline". - Unicode characters in identifiers are now transformed into ascii strings that are legal in Ocaml and other languages. - Harsh support of module extraction to Haskell and Scheme: module hierarchy is flattened, module abbreviations and functor applications are expanded, module types and unapplied functors are discarded. - Less unsupported situations when extracting modules to Ocaml. In particular module parameters might be alpha-renamed if a name clash is detected. - Extract Inductive is now possible toward non-inductive types (e.g. nat => int) - Extraction Implicit: this new experimental command allows to mark some arguments of a function or constructor for removed during extraction, even if these arguments don't fit the usual elimination principles of extraction, for instance the length n of a vector. - Files ExtrOcaml*.v in plugins/extraction try to provide a library of common extraction commands: mapping of basics types toward Ocaml's counterparts, conversions from/to int and big_int, or even complete mapping of nat,Z,N to int or big_int, or mapping of ascii to char and string to char list (in this case recognition of ascii constants is hard-wired in the extraction). Program - Streamlined definitions using well-founded recursion and measures so that they can work on any subset of the arguments directly (uses currying). - Try to automatically clear structural fixpoint prototypes in obligations to avoid issues with opacity. - Use return type clause inference in pattern-matching as in the standard typing algorithm. - Support [Local Obligation Tactic] and [Next Obligation with tactic]. - Use [Show Obligation Tactic] to print the current default tactic. - [fst] and [snd] have maximal implicit arguments in Program now (possible source of incompatibility). Type classes - Declaring axiomatic type class instances in Module Type should be now done via new command "Declare Instance", while the syntax "Instance" now always provides a concrete instance, both in and out of Module Type. - Use [Existing Class foo] to declare a preexisting object [foo] as a class. [foo] can be an inductive type or a constant definition. No projections or instances are defined. - Various bug fixes and improvements: support for defined fields, anonymous instances, declarations giving terms, better handling of sections and [Context]. Commands - New command "Timeout ." interprets a command and a timeout interrupts the execution after seconds. - New command "Compute ." is a shortcut for "Eval vm_compute in ". - New command "Fail ." interprets a command and is successful iff the command fails on an error (but not an anomaly). Handy for tests and illustration of wrong commands. - Most commands referring to constant (e.g. Print or About) now support referring to the constant by a notation string. - New option "Boolean Equality Schemes" to make generation of boolean equality automatic for datatypes (together with option "Decidable Equality Schemes", this replaces deprecated option "Equality Scheme"). - Made support for automatic generation of case analysis schemes available to user (governed by option "Set Case Analysis Schemes"). - New command :n:`{? Global } Generalizable {| All | No } {| Variable | Variables } {* @ident}` to declare which identifiers are generalizable in `` `{} `` and `` `() `` binders. - New command "Print Opaque Dependencies" to display opaque constants in addition to all variables, parameters or axioms a theorem or definition relies on. - New command "Declare Reduction := ", allowing to write later "Eval in ...". This command accepts a Local variant. - Syntax of Implicit Type now supports more than one block of variables of a given type. - Command "Canonical Structure" now warns when it has no effects. - Commands of the form "Set X" or "Unset X" now support "Local" and "Global" prefixes. Library - Use "standard" Coq names for the properties of eq and identity (e.g. refl_equal is now eq_refl). Support for compatibility is provided. - The function Compare_dec.nat_compare is now defined directly, instead of relying on lt_eq_lt_dec. The earlier version is still available under the name nat_compare_alt. - Lemmas in library Relations and Reals have been homogenized a bit. - The implicit argument of Logic.eq is now maximally inserted, allowing to simply write "eq" instead of "@eq _" in morphism signatures. - Wrongly named lemmas (Zlt_gt_succ and Zlt_succ_gt) fixed (potential source of incompatibilities) - List library: + Definitions of list, length and app are now in Init/Datatypes. Support for compatibility is provided. + Definition of Permutation is now in Sorting/Permtation.v + Some other light revisions and extensions (possible source of incompatibilities solvable by qualifying names accordingly). - In ListSet, set_map has been fixed (source of incompatibilities if used). - Sorting library: + new mergesort of worst-case complexity O(n*ln(n)) made available in Mergesort.v; + former notion of permutation up to setoid from Permutation.v is deprecated and moved to PermutSetoid.v; + heapsort from Heap.v of worst-case complexity O(n*n) is deprecated; + new file Sorted.v for some definitions of being sorted. - Structure library. This new library is meant to contain generic structures such as types with equalities or orders, either in Module version (for now) or Type Classes (still to do): + DecidableType.v and OrderedType.v: initial notions for FSets/FMaps, left for compatibility but considered as deprecated. + Equalities.v and Orders.v: evolutions of the previous files, with fine-grain Module architecture, many variants, use of Equivalence and other relevant Type Classes notions. + OrdersTac.v: a generic tactic for solving chains of (in)equalities over variables. See {Nat,N,Z,P}OrderedType.v for concrete instances. + GenericMinMax.v: any ordered type can be equipped with min and max. We derived here all the generic properties of these functions. - MSets library: an important evolution of the FSets library. "MSets" stands for Modular (Finite) Sets, by contrast with a forthcoming library of Class (Finite) Sets contributed by S. Lescuyer which will be integrated with the next release of Coq. The main features of MSets are: + The use of Equivalence, Proper and other Type Classes features easing the handling of setoid equalities. + The interfaces are now stated in iff-style. Old specifications are now derived properties. + The compare functions are now pure, and return a "comparison" value. Thanks to the CompSpec inductive type, reasoning on them remains easy. + Sets structures requiring invariants (i.e. sorted lists) are built first as "Raw" sets (pure objects and separate proofs) and attached with their proofs thanks to a generic functor. "Raw" sets have now a proper interface and can be manipulated directly. Note: No Maps yet in MSets. The FSets library is still provided for compatibility, but will probably be considered as deprecated in the next release of Coq. - Numbers library: + The abstract layer (NatInt, Natural/Abstract, Integer/Abstract) has been simplified and enhance thanks to new features of the module system such as Include (see above). It has been extended to Euclidean division (three flavors for integers: Trunc, Floor and Math). + The arbitrary-large efficient numbers (BigN, BigZ, BigQ) has also been reworked. They benefit from the abstract layer improvements (especially for div and mod). Note that some specifications have slightly changed (compare, div, mod, shift{r,l}). Ring/Field should work better (true recognition of constants). Tools - Option -R now supports binding Coq root read-only. - New coqtop/coqc option -beautify to reformat .v files (usable e.g. to globally update notations). - New tool beautify-archive to beautify a full archive of developments. - New coqtop/coqc option -compat X.Y to simulate the general behavior of previous versions of Coq (provides e.g. support for 8.2 compatibility). Coqdoc - List have been revamped. List depth and scope is now determined by an "offside" whitespace rule. - Text may be italicized by placing it in _underscores_. - The "--index " flag changes the filename of the index. - The "--toc-depth " flag limits the depth of headers which are included in the table of contents. - The "--lib-name " flag prints " Foo" instead of "Library Foo" where library titles are called for. The "--no-lib-name" flag eliminates the extra title. - New option "--parse-comments" to allow parsing of regular ``(* *)`` comments. - New option "--plain-comments" to disable interpretation inside comments. - New option "--interpolate" to try and typeset identifiers in Coq escapings using the available globalization information. - New option "--external url root" to refer to external libraries. - Links to section variables and notations now supported. Internal infrastructure - To avoid confusion with the repository of user's contributions, the subdirectory "contrib" has been renamed into "plugins". On platforms supporting ocaml native dynlink, code located there is built as loadable plugins for coqtop. - An experimental build mechanism via ocamlbuild is provided. From the top of the archive, run ./configure as usual, and then ./build. Feedback about this build mechanism is most welcome. Compiling Coq on platforms such as Windows might be simpler this way, but this remains to be tested. - The Makefile system has been simplified and factorized with the ocamlbuild system. In particular "make" takes advantage of .mllib files for building .cma/.cmxa. The .vo files to compile are now listed in several vo.itarget files. Version 8.2 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.2 adds new features, new libraries and improves on many various aspects. Regarding the language of Coq, the main novelty is the introduction by Matthieu Sozeau of a package of commands providing Haskell-style typeclasses. Typeclasses, which come with a few convenient features such as type-based resolution of implicit arguments, play a new landmark role in the architecture of Coq with respect to automation. For instance, thanks to typeclass support, Matthieu Sozeau could implement a new resolution-based version of the tactics dedicated to rewriting on arbitrary transitive relations. Another major improvement of Coq 8.2 is the evolution of the arithmetic libraries and of the tools associated with them. Benjamin GrΓ©goire and Laurent ThΓ©ry contributed a modular library for building arbitrarily large integers from bounded integers while Evgeny Makarov contributed a modular library of abstract natural and integer arithmetic together with a few convenient tactics. On his side, Pierre Letouzey made numerous extensions to the arithmetic libraries on :math:`\mathbb{Z}` and :math:`\mathbb{Q}`, including extra support for automation in presence of various number-theory concepts. FrΓ©dΓ©ric Besson contributed a reflective tactic based on Krivine-Stengle Positivstellensatz (the easy way) for validating provability of systems of inequalities. The platform is flexible enough to support the validation of any algorithm able to produce a β€œcertificate” for the Positivstellensatz and this covers the case of Fourier-Motzkin (for linear systems in :math:`\mathbb{Q}` and :math:`\mathbb{R}`), Fourier-Motzkin with cutting planes (for linear systems in :math:`\mathbb{Z}`) and sum-of-squares (for non-linear systems). Evgeny Makarov made the platform generic over arbitrary ordered rings. Arnaud Spiwack developed a library of 31-bits machine integers and, relying on Benjamin GrΓ©goire and Laurent ThΓ©ry’s library, delivered a library of unbounded integers in base :math:`2^{31}`. As importantly, he developed a notion of β€œretro-knowledge” so as to safely extend the kernel-located bytecode-based efficient evaluation algorithm of Coq version 8.1 to use 31-bits machine arithmetic for efficiently computing with the library of integers he developed. Beside the libraries, various improvements were contributed to provide a more comfortable end-user language and more expressive tactic language. Hugo Herbelin and Matthieu Sozeau improved the pattern matching compilation algorithm (detection of impossible clauses in pattern matching, automatic inference of the return type). Hugo Herbelin, Pierre Letouzey and Matthieu Sozeau contributed various new convenient syntactic constructs and new tactics or tactic features: more inference of redundant information, better unification, better support for proof or definition by fixpoint, more expressive rewriting tactics, better support for meta-variables, more convenient notations... Γ‰lie Soubiran improved the module system, adding new features (such as an β€œinclude” command) and making it more flexible and more general. He and Pierre Letouzey improved the support for modules in the extraction mechanism. Matthieu Sozeau extended the Russell language, ending in an convenient way to write programs of given specifications, Pierre Corbineau extended the Mathematical Proof Language and the automation tools that accompany it, Pierre Letouzey supervised and extended various parts of the standard library, StΓ©phane Glondu contributed a few tactics and improvements, Jean-Marc Notin provided help in debugging, general maintenance and coqdoc support, Vincent Siles contributed extensions of the Scheme command and of injection. Bruno Barras implemented the ``coqchk`` tool: this is a stand-alone type checker that can be used to certify .vo files. Especially, as this verifier runs in a separate process, it is granted not to be β€œhijacked” by virtually malicious extensions added to Coq. Yves Bertot, Jean-Christophe FilliΓ’tre, Pierre Courtieu and Julien Forest acted as maintainers of features they implemented in previous versions of Coq. Julien Narboux contributed to CoqIDE. Nicolas Tabareau made the adaptation of the interface of the old β€œsetoid rewrite” tactic to the new version. Lionel Mamane worked on the interaction between Coq and its external interfaces. With Samuel Mimram, he also helped making Coq compatible with recent software tools. Russell O’Connor, Cezary Kaliszyk, Milad Niqui contributed to improve the libraries of integers, rational, and real numbers. We also thank many users and partners for suggestions and feedback, in particular Pierre CastΓ©ran and Arthur CharguΓ©raud, the INRIA Marelle team, Georges Gonthier and the INRIA-Microsoft Mathematical Components team, the Foundations group at Radboud university in Nijmegen, reporters of bugs and participants to the Coq-Club mailing list. | Palaiseau, June 2008 | Hugo Herbelin | Details of changes ~~~~~~~~~~~~~~~~~~ Language - If a fixpoint is not written with an explicit { struct ... }, then all arguments are tried successively (from left to right) until one is found that satisfies the structural decreasing condition. - New experimental typeclass system giving ad-hoc polymorphism and overloading based on dependent records and implicit arguments. - New syntax "let 'pat := b in c" for let-binding using irrefutable patterns. - New syntax "forall {A}, T" for specifying maximally inserted implicit arguments in terms. - Sort of Record/Structure, Inductive and CoInductive defaults to Type if omitted. - (Co)Inductive types can be defined as records (e.g. "CoInductive stream := { hd : nat; tl : stream }.") - New syntax "Theorem id1:t1 ... with idn:tn" for proving mutually dependent statements. - Support for sort-polymorphism on constants denoting inductive types. - Several evolutions of the module system (handling of module aliases, functorial module types, an Include feature, etc). - Prop now a subtype of Set (predicative and impredicative forms). - Recursive inductive types in Prop with a single constructor of which all arguments are in Prop is now considered to be a singleton type. It consequently supports all eliminations to Prop, Set and Type. As a consequence, Acc_rect has now a more direct proof [possible source of easily fixed incompatibility in case of manual definition of a recursor in a recursive singleton inductive type]. Commands - Added option Global to "Arguments Scope" for section surviving. - Added option "Unset Elimination Schemes" to deactivate the automatic generation of elimination schemes. - Modification of the Scheme command so you can ask for the name to be automatically computed (e.g. Scheme Induction for nat Sort Set). - New command "Combined Scheme" to build combined mutual induction principles from existing mutual induction principles. - New command "Scheme Equality" to build a decidable (boolean) equality for simple inductive datatypes and a decision property over this equality (e.g. Scheme Equality for nat). - Added option "Set Equality Scheme" to make automatic the declaration of the boolean equality when possible. - Source of universe inconsistencies now printed when option "Set Printing Universes" is activated. - New option "Set Printing Existential Instances" for making the display of existential variable instances explicit. - Support for option "[id1 ... idn]", and "-[id1 ... idn]", for the "compute"/"cbv" reduction strategy, respectively meaning reduce only, or everything but, the constants id1 ... idn. "lazy" alone or followed by "[id1 ... idn]", and "-[id1 ... idn]" also supported, meaning apply all of beta-iota-zeta-delta, possibly restricting delta. - New command "Strategy" to control the expansion of constants during conversion tests. It generalizes commands Opaque and Transparent by introducing a range of levels. Lower levels are assigned to constants that should be expanded first. - New options Global and Local to Opaque and Transparent. - New command "Print Assumptions" to display all variables, parameters or axioms a theorem or definition relies on. - "Add Rec LoadPath" now provides references to libraries using partially qualified names (this holds also for coqtop/coqc option -R). - SearchAbout supports negated search criteria, reference to logical objects by their notation, and more generally search of subterms. - "Declare ML Module" now allows to import .cmxs files when Coq is compiled in native code with a version of OCaml that supports native Dynlink (>= 3.11). - Specific sort constraints on Record now taken into account. - "Print LoadPath" supports a path argument to filter the display. Libraries - Several parts of the libraries are now in Type, in particular FSets, SetoidList, ListSet, Sorting, Zmisc. This may induce a few incompatibilities. In case of trouble while fixing existing development, it may help to simply declare Set as an alias for Type (see file SetIsType). - New arithmetical library in theories/Numbers. It contains: * an abstract modular development of natural and integer arithmetics in Numbers/Natural/Abstract and Numbers/Integer/Abstract * an implementation of efficient computational bounded and unbounded integers that can be mapped to processor native arithmetics. See Numbers/Cyclic/Int31 for 31-bit integers and Numbers/Natural/BigN for unbounded natural numbers and Numbers/Integer/BigZ for unbounded integers. * some proofs that both older libraries Arith, ZArith and NArith and newer BigN and BigZ implement the abstract modular development. This allows in particular BigN and BigZ to already come with a large database of basic lemmas and some generic tactics (ring), This library has still an experimental status, as well as the processor-acceleration mechanism, but both its abstract and its concrete parts are already quite usable and could challenge the use of nat, N and Z in actual developments. Moreover, an extension of this framework to rational numbers is ongoing, and an efficient Q structure is already provided (see Numbers/Rational/BigQ), but this part is currently incomplete (no abstract layer and generic lemmas). - Many changes in FSets/FMaps. In practice, compatibility with earlier version should be fairly good, but some adaptations may be required. * Interfaces of unordered ("weak") and ordered sets have been factorized thanks to new features of Coq modules (in particular Include), see FSetInterface. Same for maps. Hints in these interfaces have been reworked (they are now placed in a "set" database). * To allow full subtyping between weak and ordered sets, a field "eq_dec" has been added to OrderedType. The old version of OrderedType is now called MiniOrderedType and functor MOT_to_OT allow to convert to the new version. The interfaces and implementations of sets now contain also such a "eq_dec" field. * FSetDecide, contributed by Aaron Bohannon, contains a decision procedure allowing to solve basic set-related goals (for instance, is a point in a particular set ?). See FSetProperties for examples. * Functors of properties have been improved, especially the ones about maps, that now propose some induction principles. Some properties of fold need less hypothesis. * More uniformity in implementations of sets and maps: they all use implicit arguments, and no longer export unnecessary scopes (see bug #1347) * Internal parts of the implementations based on AVL have evolved a lot. The main files FSetAVL and FMapAVL are now much more lightweight now. In particular, minor changes in some functions has allowed to fully separate the proofs of operational correctness from the proofs of well-balancing: well-balancing is critical for efficiency, but not anymore for proving that these trees implement our interfaces, hence we have moved these proofs into appendix files FSetFullAVL and FMapFullAVL. Moreover, a few functions like union and compare have been modified in order to be structural yet efficient. The appendix files also contains alternative versions of these few functions, much closer to the initial Ocaml code and written via the Function framework. - Library IntMap, subsumed by FSets/FMaps, has been removed from Coq Standard Library and moved into a user contribution Cachan/IntMap - Better computational behavior of some constants (eq_nat_dec and le_lt_dec more efficient, Z_lt_le_dec and Positive_as_OT.compare transparent, ...) (exceptional source of incompatibilities). - Boolean operators moved from module Bool to module Datatypes (may need to rename qualified references in script and force notations || and && to be at levels 50 and 40 respectively). - The constructors xI and xO of type positive now have postfix notations "~1" and "~0", allowing to write numbers in binary form easily, for instance 6 is 1~1~0 and 4*p is p~0~0 (see BinPos.v). - Improvements to NArith (Nminus, Nmin, Nmax), and to QArith (in particular a better power function). - Changes in ZArith: several additional lemmas (used in theories/Numbers), especially in Zdiv, Znumtheory, Zpower. Moreover, many results in Zdiv have been generalized: the divisor may simply be non-null instead of strictly positive (see lemmas with name ending by "_full"). An alternative file ZOdiv proposes a different behavior (the one of Ocaml) when dividing by negative numbers. - Changes in Arith: EqNat and Wf_nat now exported from Arith, some constructions on nat that were outside Arith are now in (e.g. iter_nat). - In SetoidList, eqlistA now expresses that two lists have similar elements at the same position, while the predicate previously called eqlistA is now equivlistA (this one only states that the lists contain the same elements, nothing more). - Changes in Reals: * Most statement in "sigT" (including the completeness axiom) are now in "sig" (in case of incompatibility, use proj1_sig instead of projT1, sig instead of sigT, etc). * More uniform naming scheme (identifiers in French moved to English, consistent use of 0 -- zero -- instead of O -- letter O --, etc). * Lemma on prod_f_SO is now on prod_f_R0. * Useless hypothesis of ln_exists1 dropped. * New Rlogic.v states a few logical properties about R axioms. * RIneq.v extended and made cleaner. - Slight restructuration of the Logic library regarding choice and classical logic. Addition of files providing intuitionistic axiomatizations of descriptions: Epsilon.v, Description.v and IndefiniteDescription.v. - Definition of pred and minus made compatible with the structural decreasing criterion for use in fixpoints. - Files Relations/Rstar.v and Relations/Newman.v moved out to the user contribution repository (contribution CoC_History). New lemmas about transitive closure added and some bound variables renamed (exceptional risk of incompatibilities). - Syntax for binders in terms (e.g. for "exists") supports anonymous names. Notations, coercions, implicit arguments and type inference - More automation in the inference of the return clause of dependent pattern-matching problems. - Experimental allowance for omission of the clauses easily detectable as impossible in pattern-matching problems. - Improved inference of implicit arguments. - New options "Set Maximal Implicit Insertion", "Set Reversible Pattern Implicit", "Set Strongly Strict Implicit" and "Set Printing Implicit Defensive" for controlling inference and use of implicit arguments. - New modifier in "Implicit Arguments" to force an implicit argument to be maximally inserted. - New modifier of "Implicit Arguments" to enrich the set of implicit arguments. - New options Global and Local to "Implicit Arguments" for section surviving or non-export outside module. - Level "constr" moved from 9 to 8. - Structure/Record now printed as Record (unless option Printing All is set). - Support for parametric notations defining constants. - Insertion of coercions below product types refrains to unfold constants (possible source of incompatibility). - New support for fix/cofix in notations. Tactic Language - Second-order pattern-matching now working in Ltac "match" clauses (syntax for second-order unification variable is "@?X"). - Support for matching on let bindings in match context using syntax "H := body" or "H := body : type". - Ltac accepts integer arguments (syntax is "ltac:nnn" for nnn an integer). - The general sequence tactical "expr_0 ; [ expr_1 | ... | expr_n ]" is extended so that at most one expr_i may have the form "expr .." or just "..". Also, n can be different from the number of subgoals generated by expr_0. In this case, the value of expr (or idtac in case of just "..") is applied to the intermediate subgoals to make the number of tactics equal to the number of subgoals. - A name used as the name of the parameter of a lemma (like f in "apply f_equal with (f:=t)") is now interpreted as a ltac variable if such a variable exists (this is a possible source of incompatibility and it can be fixed by renaming the variables of a ltac function into names that do not clash with the lemmas parameter names used in the tactic). - New syntax "Ltac tac ::= ..." to rebind a tactic to a new expression. - "let rec ... in ... " now supported for expressions without explicit parameters; interpretation is lazy to the contrary of "let ... in ..."; hence, the "rec" keyword can be used to turn the argument of a "let ... in ..." into a lazy one. - Patterns for hypotheses types in "match goal" are now interpreted in type_scope. - A bound variable whose name is not used elsewhere now serves as metavariable in "match" and it gets instantiated by an identifier (allow e.g. to extract the name of a statement like "exists x, P x"). - New printing of Ltac call trace for better debugging. Tactics - New tactics "apply -> term", "apply <- term", "apply -> term in ident", "apply <- term in ident" for applying equivalences (iff). - Slight improvement of the hnf and simpl tactics when applied on expressions with explicit occurrences of match or fix. - New tactics "eapply in", "erewrite", "erewrite in". - New tactics "ediscriminate", "einjection", "esimplify_eq". - Tactics "discriminate", "injection", "simplify_eq" now support any term as argument. Clause "with" is also supported. - Unfoldable references can be given by notation's string rather than by name in unfold. - The "with" arguments are now typed using informations from the current goal: allows support for coercions and more inference of implicit arguments. - Application of "f_equal"-style lemmas works better. - Tactics elim, case, destruct and induction now support variants eelim, ecase, edestruct and einduction. - Tactics destruct and induction now support the "with" option and the "in" clause option. If the option "in" is used, an equality is added to remember the term to which the induction or case analysis applied (possible source of parsing incompatibilities when destruct or induction is part of a let-in expression in Ltac; extra parentheses are then required). - New support for "as" clause in tactics "apply in" and "eapply in". - Some new intro patterns: * intro pattern "?A" genererates a fresh name based on A. Caveat about a slight loss of compatibility: Some intro patterns don't need space between them. In particular intros ?a?b used to be legal and equivalent to intros ? a ? b. Now it is still legal but equivalent to intros ?a ?b. * intro pattern "(A & ... & Y & Z)" synonym to "(A,....,(Y,Z)))))" for right-associative constructs like /\ or exists. - Several syntax extensions concerning "rewrite": * "rewrite A,B,C" can be used to rewrite A, then B, then C. These rewrites occur only on the first subgoal: in particular, side-conditions of the "rewrite A" are not concerned by the "rewrite B,C". * "rewrite A by tac" allows to apply tac on all side-conditions generated by the "rewrite A". * "rewrite A at n" allows to select occurrences to rewrite: rewrite only happen at the n-th exact occurrence of the first successful matching of A in the goal. * "rewrite 3 A" or "rewrite 3!A" is equivalent to "rewrite A,A,A". * "rewrite !A" means rewriting A as long as possible (and at least once). * "rewrite 3?A" means rewriting A at most three times. * "rewrite ?A" means rewriting A as long as possible (possibly never). * many of the above extensions can be combined with each other. - Introduction patterns better respect the structure of context in presence of missing or extra names in nested disjunction-conjunction patterns [possible source of rare incompatibilities]. - New syntax "rename a into b, c into d" for "rename a into b; rename c into d" - New tactics "dependent induction/destruction H [ generalizing id_1 .. id_n ]" to do induction-inversion on instantiated inductive families Γ  la BasicElim. - Tactics "apply" and "apply in" now able to reason modulo unfolding of constants (possible source of incompatibility in situations where apply may fail, e.g. as argument of a try or a repeat and in a ltac function); versions that do not unfold are renamed into "simple apply" and "simple apply in" (usable for compatibility or for automation). - Tactics "apply" and "apply in" now able to traverse conjunctions and to select the first matching lemma among the components of the conjunction; tactic "apply" also able to apply lemmas of conclusion an empty type. - Tactic "apply" now supports application of several lemmas in a row. - Tactics "set" and "pose" can set functions using notation "(f x1..xn := c)". - New tactic "instantiate" (without argument). - Tactic firstorder "with" and "using" options have their meaning swapped for consistency with auto/eauto (source of incompatibility). - Tactic "generalize" now supports "at" options to specify occurrences and "as" options to name the quantified hypotheses. - New tactic "specialize H with a" or "specialize (H a)" allows to transform in-place a universally-quantified hypothesis (H : forall x, T x) into its instantiated form (H : T a). Nota: "specialize" was in fact there in earlier versions of Coq, but was undocumented, and had a slightly different behavior. - New tactic "contradict H" can be used to solve any kind of goal as long as the user can provide afterwards a proof of the negation of the hypothesis H. If H is already a negation, say ~T, then a proof of T is asked. If the current goal is a negation, say ~U, then U is saved in H afterwards, hence this new tactic "contradict" extends earlier tactic "swap", which is now obsolete. - Tactics f_equal is now done in ML instead of Ltac: it now works on any equality of functions, regardless of the arity of the function. - New options "before id", "at top", "at bottom" for tactics "move"/"intro". - Some more debug of reflexive omega (``romega``), and internal clarifications. Moreover, romega now has a variant ``romega with *`` that can be also used on non-Z goals (nat, N, positive) via a call to a translation tactic named zify (its purpose is to Z-ify your goal...). This zify may also be used independently of romega. - Tactic "remember" now supports an "in" clause to remember only selected occurrences of a term. - Tactic "pose proof" supports name overriding in case of specialization of an hypothesis. - Semi-decision tactic "jp" for first-order intuitionistic logic moved to user contributions (subsumed by "firstorder"). Program - Moved useful tactics in theories/Program and documented them. - Add Program.Basics which contains standard definitions for functional programming (id, apply, flip...) - More robust obligation handling, dependent pattern-matching and well-founded definitions. - New syntax " dest term as pat in term " for destructing objects using an irrefutable pattern while keeping equalities (use this instead of "let" in Programs). - Program CoFixpoint is accepted, Program Fixpoint uses the new way to infer which argument decreases structurally. - Program Lemma, Axiom etc... now permit to have obligations in the statement iff they can be automatically solved by the default tactic. - Renamed "Obligations Tactic" command to "Obligation Tactic". - New command "Preterm [ of id ]" to see the actual term fed to Coq for debugging purposes. - New option "Transparent Obligations" to control the declaration of obligations as transparent or opaque. All obligations are now transparent by default, otherwise the system declares them opaque if possible. - Changed the notations "left" and "right" to "in_left" and "in_right" to hide the proofs in standard disjunctions, to avoid breaking existing scripts when importing Program. Also, put them in program_scope. Type Classes - New "Class", "Instance" and "Program Instance" commands to define classes and instances documented in the reference manual. - New binding construct " [ Class_1 param_1 .. param_n, Class_2 ... ] " for binding type classes, usable everywhere. - New command " Print Classes " and " Print Instances some_class " to print tables for typeclasses. - New default eauto hint database "typeclass_instances" used by the default typeclass instance search tactic. - New theories directory "theories/Classes" for standard typeclasses declarations. Module Classes.RelationClasses is a typeclass port of Relation_Definitions plus a generic development of algebra on n-ary heterogeneous predicates. Setoid rewriting - Complete (and still experimental) rewrite of the tactic based on typeclasses. The old interface and semantics are almost entirely respected, except: + Import Setoid is now mandatory to be able to call setoid_replace and declare morphisms. + "-->", "++>" and "==>" are now right associative notations declared at level 55 in scope signature_scope. Their introduction may break existing scripts that defined them as notations with different levels. + One needs to use [Typeclasses unfold [cst]] if [cst] is used as an abbreviation hiding products in types of morphisms, e.g. if ones redefines [relation] and declares morphisms whose type mentions [relation]. + The [setoid_rewrite]'s semantics change when rewriting with a lemma: it can rewrite two different instantiations of the lemma at once. Use [setoid_rewrite H at 1] for (almost) the usual semantics. [setoid_rewrite] will also try to rewrite under binders now, and can succeed on different terms than before. In particular, it will unify under let-bound variables. When called through [rewrite], the semantics are unchanged though. + [Add Morphism term : id] has different semantics when used with parametric morphism: it will try to find a relation on the parameters too. The behavior has also changed with respect to default relations: the most recently declared Setoid/Relation will be used, the documentation explains how to customize this behavior. + Parametric Relation and Morphism are declared differently, using the new [Add Parametric] commands, documented in the manual. + Setoid_Theory is now an alias to Equivalence, scripts building objects of type Setoid_Theory need to unfold (or "red") the definitions of Reflexive, Symmetric and Transitive in order to get the same goals as before. Scripts which introduced variables explicitly will not break. + The order of subgoals when doing [setoid_rewrite] with side-conditions is always the same: first the new goal, then the conditions. - New standard library modules ``Classes.Morphisms`` declares standard morphisms on ``refl`` / ``sym`` / ``trans`` relations. ``Classes.Morphisms_Prop`` declares morphisms on propositional connectives and ``Classes.Morphisms_Relations`` on generalized predicate connectives. ``Classes.Equivalence`` declares notations and tactics related to equivalences and ``Classes.SetoidTactics`` defines the setoid_replace tactics and some support for the ``Add *`` interface, notably the tactic applied automatically before each ``Add Morphism`` proof. - User-defined subrelations are supported, as well as higher-order morphisms and rewriting under binders. The tactic is also extensible entirely in Ltac. The documentation has been updated to cover these features. - [setoid_rewrite] and [rewrite] now support the [at] modifier to select occurrences to rewrite, and both use the [setoid_rewrite] code, even when rewriting with leibniz equality if occurrences are specified. Extraction - Improved behavior of the Caml extraction of modules: name clashes should not happen anymore. - The command Extract Inductive has now a syntax for infix notations. This allows in particular to map Coq lists and pairs onto OCaml ones: + Extract Inductive list => list [ "[]" "(::)" ]. + Extract Inductive prod => "(*)" [ "(,)" ]. - In pattern matchings, a default pattern "| _ -> ..." is now used whenever possible if several branches are identical. For instance, functions corresponding to decidability of equalities are now linear instead of quadratic. - A new instruction Extraction Blacklist id1 .. idn allows to prevent filename conflits with existing code, for instance when extracting module List to Ocaml. CoqIDE - CoqIDE font defaults to monospace so as indentation to be meaningful. - CoqIDE supports nested goals and any other kind of declaration in the middle of a proof. - Undoing non-tactic commands in CoqIDE works faster. - New CoqIDE menu for activating display of various implicit informations. - Added the possibility to choose the location of tabs in coqide: (in Edit->Preferences->Misc) - New Open and Save As dialogs in CoqIDE which filter ``*.v`` files. Tools - New stand-alone .vo files verifier "coqchk". - Extended -I coqtop/coqc option to specify a logical dir: "-I dir -as coqdir". - New coqtop/coqc option -exclude-dir to exclude subdirs for option -R. - The binary "parser" has been renamed to "coq-parser". - Improved coqdoc and dump of globalization information to give more meta-information on identifiers. All categories of Coq definitions are supported, which makes typesetting trivial in the generated documentation. Support for hyperlinking and indexing developments in the tex output has been implemented as well. Miscellaneous - Coq installation provides enough files so that Ocaml's extensions need not the Coq sources to be compiled (this assumes O'Caml 3.10 and Camlp5). - New commands "Set Whelp Server" and "Set Whelp Getter" to customize the Whelp search tool. - Syntax of "Test Printing Let ref" and "Test Printing If ref" changed into "Test Printing Let for ref" and "Test Printing If for ref". - An overhauled build system (new Makefiles); see dev/doc/build-system.txt. - Add -browser option to configure script. - Build a shared library for the C part of Coq, and use it by default on non-(Windows or MacOS) systems. Bytecode executables are now pure. The behavior is configurable with -coqrunbyteflags, -coqtoolsbyteflags and -custom configure options. - Complexity tests can be skipped by setting the environment variable COQTEST_SKIPCOMPLEXITY. Version 8.1 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8.1 adds various new functionalities. Benjamin GrΓ©goire implemented an alternative algorithm to check the convertibility of terms in the Coq type checker. This alternative algorithm works by compilation to an efficient bytecode that is interpreted in an abstract machine similar to Xavier Leroy’s ZINC machine. Convertibility is performed by comparing the normal forms. This alternative algorithm is specifically interesting for proofs by reflection. More generally, it is convenient in case of intensive computations. Christine Paulin implemented an extension of inductive types allowing recursively non-uniform parameters. Hugo Herbelin implemented sort-polymorphism for inductive types (now called template polymorphism). Claudio Sacerdoti Coen improved the tactics for rewriting on arbitrary compatible equivalence relations. He also generalized rewriting to arbitrary transition systems. Claudio Sacerdoti Coen added new features to the module system. Benjamin GrΓ©goire, Assia Mahboubi and Bruno Barras developed a new, more efficient and more general simplification algorithm for rings and semirings. Laurent ThΓ©ry and Bruno Barras developed a new, significantly more efficient simplification algorithm for fields. Hugo Herbelin, Pierre Letouzey, Julien Forest, Julien Narboux and Claudio Sacerdoti Coen added new tactic features. Hugo Herbelin implemented matching on disjunctive patterns. New mechanisms made easier the communication between Coq and external provers. Nicolas Ayache and Jean-Christophe FilliΓ’tre implemented connections with the provers cvcl, Simplify and zenon. Hugo Herbelin implemented an experimental protocol for calling external tools from the tactic language. Matthieu Sozeau developed Russell, an experimental language to specify the behavior of programs with subtypes. A mechanism to automatically use some specific tactic to solve unresolved implicit has been implemented by Hugo Herbelin. Laurent ThΓ©ry’s contribution on strings and Pierre Letouzey and Jean-Christophe FilliΓ’tre’s contribution on finite maps have been integrated to the Coq standard library. Pierre Letouzey developed a library about finite sets β€œΓ  la Objective Caml”. With Jean-Marc Notin, he extended the library on lists. Pierre Letouzey’s contribution on rational numbers has been integrated and extended. Pierre Corbineau extended his tactic for solving first-order statements. He wrote a reflection-based intuitionistic tautology solver. Pierre Courtieu, Julien Forest and Yves Bertot added extra support to reason on the inductive structure of recursively defined functions. Jean-Marc Notin significantly contributed to the general maintenance of the system. He also took care of ``coqdoc``. Pierre CastΓ©ran contributed to the documentation of (co)inductive types and suggested improvements to the libraries. Pierre Corbineau implemented a declarative mathematical proof language, usable in combination with the tactic-based style of proof. Finally, many users suggested improvements of the system through the Coq-Club mailing list and bug-tracker systems, especially user groups from INRIA Rocquencourt, Radboud University, University of Pennsylvania and Yale University. | Palaiseau, July 2006 | Hugo Herbelin | Details of changes in 8.1beta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logic - Added sort-polymorphism on inductive families - Allowance for recursively non-uniform parameters in inductive types Syntax - No more support for version 7 syntax and for translation to version 8 syntax. - In fixpoints, the { struct ... } annotation is not mandatory any more when only one of the arguments has an inductive type - Added disjunctive patterns in match-with patterns - Support for primitive interpretation of string literals - Extended support for Unicode ranges Commands - Added "Print Ltac qualid" to print a user defined tactic. - Added "Print Rewrite HintDb" to print the content of a DB used by autorewrite. - Added "Print Canonical Projections". - Added "Example" as synonym of "Definition". - Added "Proposition" and "Corollary" as extra synonyms of "Lemma". - New command "Whelp" to send requests to the Helm database of proofs formalized in the Calculus of Inductive Constructions. - Command "functional induction" has been re-implemented from the new "Function" command. Ltac and tactic syntactic extensions - New primitive "external" for communication with tool external to Coq - New semantics for "match t with": if a clause returns a tactic, it is now applied to the current goal. If it fails, the next clause or next matching subterm is tried (i.e. it behaves as "match goal with" does). The keyword "lazymatch" can be used to delay the evaluation of tactics occurring in matching clauses. - Hint base names can be parametric in auto and trivial. - Occurrence values can be parametric in unfold, pattern, etc. - Added entry constr_may_eval for tactic extensions. - Low-priority term printer made available in ML-written tactic extensions. - "Tactic Notation" extended to allow notations of tacticals. Tactics - New implementation and generalization of ``setoid_*`` (``setoid_rewrite``, ``setoid_symmetry``, ``setoid_transitivity``, ``setoid_reflexivity`` and ``autorewite``). New syntax for declaring relations and morphisms (old syntax still working with minor modifications, but deprecated). - New implementation (still experimental) of the ring tactic with a built-in notion of coefficients and a better usage of setoids. - New conversion tactic "vm_compute": evaluates the goal (or an hypothesis) with a call-by-value strategy, using the compiled version of terms. - When rewriting H where H is not directly a Coq equality, search first H for a registered setoid equality before starting to reduce in H. This is unlikely to break any script. Should this happen nonetheless, one can insert manually some "unfold ... in H" before rewriting. - Fixed various bugs about (setoid) rewrite ... in ... (in particular bug #5941) - "rewrite ... in" now accepts a clause as place where to rewrite instead of just a simple hypothesis name. For instance: ``rewrite H in H1,H2 |- *`` means ``rewrite H in H1; rewrite H in H2; rewrite H`` ``rewrite H in * |-`` will do try ``rewrite H in Hi`` for all hypothesis Hi <> H. - Added "dependent rewrite term" and "dependent rewrite term in hyp". - Added "autorewrite with ... in hyp [using ...]". - Tactic "replace" now accepts a "by" tactic clause. - Added "clear - id" to clear all hypotheses except the ones depending in id. - The argument of Declare Left Step and Declare Right Step is now a term (it used to be a reference). - Omega now handles arbitrary precision integers. - Several bug fixes in Reflexive Omega (romega). - Idtac can now be left implicit in a [...|...] construct: for instance, [ foo | | bar ] stands for [ foo | idtac | bar ]. - Fixed a "fold" bug (noncritical but possible source of incompatibilities). - Added classical_left and classical_right which transforms ``|- A \/ B`` into ``~B |- A`` and ``~A |- B`` respectively. - Added command "Declare Implicit Tactic" to set up a default tactic to be used to solve unresolved subterms of term arguments of tactics. - Better support for coercions to Sortclass in tactics expecting type arguments. - Tactic "assert" now accepts "as" intro patterns and "by" tactic clauses. - New tactic "pose proof" that generalizes "assert (id:=p)" with intro patterns. - New introduction pattern "?" for letting Coq choose a name. - Introduction patterns now support side hypotheses (e.g. intros [|] on "(nat -> nat) -> nat" works). - New introduction patterns "->" and "<-" for immediate rewriting of introduced hypotheses. - Introduction patterns coming after nontrivial introduction patterns now force full introduction of the first pattern (e.g. ``intros [[|] p]`` on ``nat->nat->nat`` now behaves like ``intros [[|?] p]``) - Added "eassumption". - Added option 'using lemmas' to auto, trivial and eauto. - Tactic "congruence" is now complete for its intended scope (ground equalities and inequalities with constructors). Furthermore, it tries to equates goal and hypotheses. - New tactic "rtauto" solves pure propositional logic and gives a reflective version of the available proof. - Numbering of "pattern", "unfold", "simpl", ... occurrences in "match with" made consistent with the printing of the return clause after the term to match in the "match-with" construct (use "Set Printing All" to see hidden occurrences). - Generalization of induction "induction x1...xn using scheme" where scheme is an induction principle with complex predicates (like the ones generated by function induction). - Some small Ltac tactics has been added to the standard library (file Tactics.v): * f_equal : instead of using the different f_equalX lemmas * case_eq : a "case" without loss of information. An equality stating the current situation is generated in every sub-cases. * swap : for a negated goal ~B and a negated hypothesis H:~A, swap H asks you to prove A from hypothesis B * revert : revert H is generalize H; clear H. Extraction - All type parts should now disappear instead of sometimes producing _ (for instance in Map.empty). - Haskell extraction: types of functions are now printed, better unsafeCoerce mechanism, both for hugs and ghc. - Scheme extraction improved, see http://www.pps.jussieu.fr/~letouzey/scheme. - Many bug fixes. Modules - Added "Locate Module qualid" to get the full path of a module. - Module/Declare Module syntax made more uniform. - Added syntactic sugar "Declare Module Export/Import" and "Module Export/Import". - Added syntactic sugar "Module M(Export/Import X Y: T)" and "Module Type M(Export/Import X Y: T)" (only for interactive definitions) - Construct "with" generalized to module paths: T with (Definition|Module) M1.M2....Mn.l := l'. Notations - Option "format" aware of recursive notations. - Added insertion of spaces by default in recursive notations w/o separators. - No more automatic printing box in case of user-provided printing "format". - New notation "exists! x:A, P" for unique existence. - Notations for specific numerals now compatible with generic notations of numerals (e.g. "1" can be used to denote the unit of a group without hiding 1%nat) Libraries - New library on String and Ascii characters (contributed by L. Thery). - New library FSets+FMaps of finite sets and maps. - New library QArith on rational numbers. - Small extension of Zmin.V, new Zmax.v, new Zminmax.v. - Reworking and extension of the files on classical logic and description principles (possible incompatibilities) - Few other improvements in ZArith potentially exceptionally breaking the compatibility (useless hypothesys of Zgt_square_simpl and Zlt_square_simpl removed; fixed names mentioning letter O instead of digit 0; weaken premises in Z_lt_induction). - Restructuration of Eqdep_dec.v and Eqdep.v: more lemmas in Type. - Znumtheory now contains a gcd function that can compute within Coq. - More lemmas stated on Type in Wf.v, removal of redundant Acc_iter and Acc_iter2. - Change of the internal names of lemmas in OmegaLemmas. - Acc in Wf.v and clos_refl_trans in Relation_Operators.v now rely on the allowance for recursively non-uniform parameters (possible source of incompatibilities: explicit pattern-matching on these types may require to remove the occurrence associated with their recursively non-uniform parameter). - Coq.List.In_dec has been set transparent (this may exceptionally break proof scripts, set it locally opaque for compatibility). - More on permutations of lists in List.v and Permutation.v. - List.v has been much expanded. - New file SetoidList.v now contains results about lists seen with respect to a setoid equality. - Library NArith has been expanded, mostly with results coming from Intmap (for instance a bitwise xor), plus also a bridge between N and Bitvector. - Intmap has been reorganized. In particular its address type "addr" is now N. User contributions known to use Intmap have been adapted accordingly. If you're using this library please contact us. A wrapper FMapIntMap now presents Intmap as a particular implementation of FMaps. New developments are strongly encouraged to use either this wrapper or any other implementations of FMap instead of using directly this obsolete Intmap. Tools - New semantics for coqtop options ("-batch" expects option "-top dir" for loading vernac file that contains definitions). - Tool coq_makefile now removes custom targets that are file names in "make clean" - New environment variable COQREMOTEBROWSER to set the command invoked to start the remote browser both in Coq and CoqIDE. Standard syntax: "%s" is the placeholder for the URL. Details of changes in 8.1gamma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Syntax - changed parsing precedence of let/in and fun constructions of Ltac: let x := t in e1; e2 is now parsed as let x := t in (e1;e2). Language and commands - Added sort-polymorphism for definitions in Type (but finally abandoned). - Support for implicit arguments in the types of parameters in (co)fixpoints and (co)inductive declarations. - Improved type inference: use as much of possible general information. before applying irreversible unification heuristics (allow e.g. to infer the predicate in "(exist _ 0 (refl_equal 0) : {n:nat | n=0 })"). - Support for Miller-Pfenning's patterns unification in type synthesis (e.g. can infer P such that P x y = phi(x,y)). - Support for "where" clause in cofixpoint definitions. - New option "Set Printing Universes" for making Type levels explicit. Tactics - Improved implementation of the ring and field tactics. For compatibility reasons, the previous tactics are renamed as legacy ring and legacy field, but should be considered as deprecated. - New declarative mathematical proof language. - Support for argument lists of arbitrary length in Tactic Notation. - ``rewrite ... in H`` now fails if ``H`` is used either in an hypothesis or in the goal. - The semantics of ``rewrite ... in *`` has been slightly modified (see doc). - Support for ``as`` clause in tactic injection. - New forward-reasoning tactic "apply in". - Ltac fresh operator now builds names from a concatenation of its arguments. - New ltac tactic "remember" to abstract over a subterm and keep an equality - Support for Miller-Pfenning's patterns unification in apply/rewrite/... (may lead to few incompatibilities - generally now useless tactic calls). Bug fixes - Fix for notations involving basic "match" expressions. - Numerous other bugs solved (a few fixes may lead to incompatibilities). Details of changes in 8.1 ~~~~~~~~~~~~~~~~~~~~~~~~~ Bug fixes - Many bugs have been fixed (cf coq-bugs web page) Tactics - New tactics ring, ring_simplify and new tactic field now able to manage power to a positive integer constant. Tactic ring on Z and R, and field on R manage power (may lead to incompatibilities with V8.1gamma). - Tactic field_simplify now applicable in hypotheses. - New field_simplify_eq for simplifying field equations into ring equations. - Tactics ring, ring_simplify, field, field_simplify and field_simplify_eq all able to apply user-given equations to rewrite monoms on the fly (see documentation). Libraries - New file ConstructiveEpsilon.v defining an epsilon operator and proving the axiom of choice constructively for a countable domain and a decidable predicate. Version 8.0 ----------- Summary of changes ~~~~~~~~~~~~~~~~~~ Coq version 8 is a major revision of the Coq proof assistant. First, the underlying logic is slightly different. The so-called *impredicativity* of the sort Set has been dropped. The main reason is that it is inconsistent with the principle of description which is quite a useful principle for formalizing mathematics within classical logic. Moreover, even in an constructive setting, the impredicativity of Set does not add so much in practice and is even subject of criticism from a large part of the intuitionistic mathematician community. Nevertheless, the impredicativity of Set remains optional for users interested in investigating mathematical developments which rely on it. Secondly, the concrete syntax of terms has been completely revised. The main motivations were - a more uniform, purified style: all constructions are now lowercase, with a functional programming perfume (e.g. abstraction is now written fun), and more directly accessible to the novice (e.g. dependent product is now written forall and allows omission of types). Also, parentheses are no longer mandatory for function application. - extensibility: some standard notations (e.g. β€œ<” and β€œ>”) were incompatible with the previous syntax. Now all standard arithmetic notations (=, +, \*, /, <, <=, ... and more) are directly part of the syntax. Together with the revision of the concrete syntax, a new mechanism of *notation scopes* permits to reuse the same symbols (typically +, -, \*, /, <, <=) in various mathematical theories without any ambiguities for Coq, leading to a largely improved readability of Coq scripts. New commands to easily add new symbols are also provided. Coming with the new syntax of terms, a slight reform of the tactic language and of the language of commands has been carried out. The purpose here is a better uniformity making the tactics and commands easier to use and to remember. Thirdly, a restructuring and uniformization of the standard library of Coq has been performed. There is now just one Leibniz equality usable for all the different kinds of Coq objects. Also, the set of real numbers now lies at the same level as the sets of natural and integer numbers. Finally, the names of the standard properties of numbers now follow a standard pattern and the symbolic notations for the standard definitions as well. The fourth point is the release of CoqIDE, a new graphical gtk2-based interface fully integrated with Coq. Close in style to the Proof General Emacs interface, it is faster and its integration with Coq makes interactive developments more friendly. All mathematical Unicode symbols are usable within CoqIDE. Finally, the module system of Coq completes the picture of Coq version 8.0. Though released with an experimental status in the previous version 7.4, it should be considered as a salient feature of the new version. Besides, Coq comes with its load of novelties and improvements: new or improved tactics (including a new tactic for solving first-order statements), new management commands, extended libraries. Bruno Barras and Hugo Herbelin have been the main contributors of the reflection and the implementation of the new syntax. The smart automatic translator from old to new syntax released with Coq is also their work with contributions by Olivier Desmettre. Hugo Herbelin is the main designer and implementer of the notion of notation scopes and of the commands for easily adding new notations. Hugo Herbelin is the main implementer of the restructured standard library. Pierre Corbineau is the main designer and implementer of the new tactic for solving first-order statements in presence of inductive types. He is also the maintainer of the non-domain specific automation tactics. Benjamin Monate is the developer of the CoqIDE graphical interface with contributions by Jean-Christophe FilliΓ’tre, Pierre Letouzey, Claude MarchΓ© and Bruno Barras. Claude MarchΓ© coordinated the edition of the Reference Manual for Coq V8.0. Pierre Letouzey and Jacek ChrzΔ…szcz respectively maintained the extraction tool and module system of Coq. Jean-Christophe FilliΓ’tre, Pierre Letouzey, Hugo Herbelin and other contributors from Sophia-Antipolis and Nijmegen participated in extending the library. Julien Narboux built a NSIS-based automatic Coq installation tool for the Windows platform. Hugo Herbelin and Christine Paulin coordinated the development which was under the responsibility of Christine Paulin. | Palaiseau & Orsay, Apr. 2004 | Hugo Herbelin & Christine Paulin | (updated Apr. 2006) | Details of changes in 8.0beta old syntax ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logic - Set now predicative by default - New option -impredicative-set to set Set impredicative - The standard library doesn't need impredicativity of Set and is compatible with the classical axioms which contradict Set impredicativity Syntax for arithmetic - Notation "=" and "<>" in Z and R are no longer implicitly in Z or R (with possible introduction of a coercion), use ...=... or ...<>... instead - Locate applied to a simple string (e.g. "+") searches for all notations containing this string Commands - "Declare ML Module" now allows to import .cma files. This avoids to use a bunch of "Declare ML Module" statements when using several ML files. - "Set Printing Width n" added, allows to change the size of width printing. - "Implicit Variables Type x,y:t" (new syntax: "Implicit Types x y:t") assigns default types for binding variables. - Declarations of Hints and Notation now accept a "Local" flag not to be exported outside the current file even if not in section - "Print Scopes" prints all notations - New command "About name" for light printing of type, implicit arguments, etc. - New command "Admitted" to declare incompletely proven statement as axioms - New keyword "Conjecture" to declare an axiom intended to be provable - SearchAbout can now search for lemmas referring to more than one constant and on substrings of the name of the lemma - "Print Implicit" displays the implicit arguments of a constant - Locate now searches for all names having a given suffix - New command "Functional Scheme" for building an induction principle from a function defined by case analysis and fix. Commands - new coqtop/coqc option -dont-load-proofs not to load opaque proofs in memory Implicit arguments - Inductive in sections declared with implicits now "discharged" with implicits (like constants and variables) - Implicit Arguments flags are now synchronous with reset - New switch "Unset/Set Printing Implicits" (new syntax: "Unset/Set Printing Implicit") to globally control printing of implicits Grammar extensions - Many newly supported UTF-8 encoded unicode blocks - Greek letters (0380-03FF), Hebrew letters (U05D0-05EF), letter-like symbols (2100-214F, that includes double N,Z,Q,R), prime signs (from 2080-2089) and characters from many written languages are valid in identifiers - mathematical operators (2200-22FF), supplemental mathematical operators (2A00-2AFF), miscellaneous technical (2300-23FF that includes sqrt symbol), miscellaneous symbols (2600-26FF), arrows (2190-21FF and 2900-297F), invisible mathematical operators (from 2080-2089), ... are valid symbols Library - New file about the factorial function in Arith - An additional elimination Acc_iter for Acc, simpler than Acc_rect. This new elimination principle is used for definition well_founded_induction. - New library NArith on binary natural numbers - R is now of type Set - Restructuration in ZArith library + "true_sub" used in Zplus now a definition, not a local one (source of incompatibilities in proof referring to true_sub, may need extra Unfold) + Some lemmas about minus moved from fast_integer to Arith/Minus.v (le_minus, lt_mult_left) (theoretical source of incompatibilities) + Several lemmas moved from auxiliary.v and zarith_aux.v to fast_integer.v (theoretical source of incompatibilities) + Variables names of iff_trans changed (source of incompatibilities) + ZArith lemmas named ``OMEGA`` something or ``fast_`` something, and lemma ``new_var`` are now out of ZArith (except ``OMEGA2``) + Redundant ZArith lemmas have been renamed: for the following pairs, use the second name (Zle_Zmult_right2, Zle_mult_simpl), (OMEGA2, Zle_0_plus), (Zplus_assoc_l, Zplus_assoc), (Zmult_one, Zmult_1_n), (Zmult_assoc_l, Zmult_assoc), (Zmult_minus_distr, Zmult_Zminus_distr_l) (add_un_double_moins_un_xO, is_double_moins_un), (Rlt_monotony_rev,Rlt_monotony_contra) (source of incompatibilities) - Few minor changes (no more implicit arguments in Zmult_Zminus_distr_l and Zmult_Zminus_distr_r, lemmas moved from Zcomplements to other files) (rare source of incompatibilities) - New lemmas provided by users added Tactic language - Fail tactic now accepts a failure message - Idtac tactic now accepts a message - New primitive tactic "FreshId" (new syntax: "fresh") to generate new names - Debugger prints levels of calls Tactics - Replace can now replace proofs also - Fail levels are now decremented at "Match Context" blocks only and if the right-hand-side of "Match term With" are tactics, these tactics are never evaluated immediately and do not induce backtracking (in contrast with "Match Context") - Quantified names now avoid global names of the current module (like Intro names did) [source of rare incompatibilities: 2 changes in the set of user contribs] - NewDestruct/NewInduction accepts intro patterns as introduction names - NewDestruct/NewInduction now work for non-inductive type using option "using" - A NewInduction naming bug for inductive types with functional arguments (e.g. the accessibility predicate) has been fixed (source of incompatibilities) - Symmetry now applies to hypotheses too - Inversion now accept option "as [ ... ]" to name the hypotheses - Contradiction now looks also for contradictory hypotheses stating ~A and A (source of incompatibility) - "Contradiction c" try to find an hypothesis in context which contradicts the type of c - Ring applies to new library NArith (require file NArithRing) - Field now works on types in Set - Auto with reals now try to replace le by ge (Rge_le is no longer an immediate hint), resulting in shorter proofs - Instantiate now works in hyps (syntax : Instantiate in ...) - Some new tactics : EConstructor, ELeft, Eright, ESplit, EExists - New tactic "functional induction" to perform case analysis and induction following the definition of a function. - Clear now fails when trying to remove a local definition used by a constant appearing in the current goal Extraction (See details in plugins/extraction/CHANGES) - The old commands: (Recursive) Extraction Module M. are now: (Recursive) Extraction Library M. To use these commands, M should come from a library M.v - The other syntax Extraction & Recursive Extraction now accept module names as arguments. Bugs - see coq-bugs server for the complete list of fixed bugs Miscellaneous - Implicit parameters of inductive types definition now taken into account for inferring other implicit arguments Incompatibilities - Persistence of true_sub (4 incompatibilities in Coq user contributions) - Variable names of some constants changed for a better uniformity (2 changes in Coq user contributions) - Naming of quantified names in goal now avoid global names (2 occurrences) - NewInduction naming for inductive types with functional arguments (no incompatibility in Coq user contributions) - Contradiction now solve more goals (source of 2 incompatibilities) - Merge of eq and eqT may exceptionally result in subgoals now solved automatically - Redundant pairs of ZArith lemmas may have different names: it may cause "Apply/Rewrite with" to fail if using the first name of a pair of redundant lemmas (this is solved by renaming the variables bound by "with"; 3 incompatibilities in Coq user contribs) - ML programs referring to constants from fast_integer.v must use "Coqlib.gen_constant_modules Coqlib.zarith_base_modules" instead Details of changes in 8.0beta new syntax ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ New concrete syntax - A completely new syntax for terms - A more uniform syntax for tactics and the tactic language - A few syntactic changes for commands - A smart automatic translator translating V8.0 files in old syntax to files valid for V8.0 Syntax extensions - "Grammar" for terms disappears - "Grammar" for tactics becomes "Tactic Notation" - "Syntax" disappears - Introduction of a notion of notation scope allowing to use the same notations in various contexts without using specific delimiters (e.g the same expression "4<=3+x" is interpreted either in "nat", "positive", "N" (previously "entier"), "Z", "R", depending on which Notation scope is currently open) [see documentation for details] - Notation now requires a precedence and associativity (default was to set precedence to 1 and associativity to none) Revision of the standard library - Many lemmas and definitions names have been made more uniform mostly in Arith, NArith, ZArith and Reals (e.g : "times" -> "Pmult", "times_sym" -> "Pmult_comm", "Zle_Zmult_pos_right" -> "Zmult_le_compat_r", "SUPERIEUR" -> "Gt", "ZERO" -> "Z0") - Order and names of arguments of basic lemmas on nat, Z, positive and R have been made uniform. - Notions of Coq initial state are declared with (strict) implicit arguments - eq merged with eqT: old eq disappear, new eq (written =) is old eqT and new eqT is syntactic sugar for new eq (notation == is an alias for = and is written as it, exceptional source of incompatibilities) - Similarly, ex, ex2, all, identity are merged with exT, exT2, allT, identityT - Arithmetical notations for nat, positive, N, Z, R, without needing any backquote or double-backquotes delimiters. - In Lists: new concrete notations; argument of nil is now implicit - All changes in the library are taken in charge by the translator Semantical changes during translation - Recursive keyword set by default (and no longer needed) in Tactic Definition - Set Implicit Arguments is strict by default in new syntax - reductions in hypotheses of the form "... in H" now apply to the type also if H is a local definition - etc Gallina - New syntax of the form "Inductive bool : Set := true, false : bool." for enumerated types - Experimental syntax of the form p.(fst) for record projections (activable with option "Set Printing Projections" which is recognized by the translator) Known problems of the automatic translation - iso-latin-1 characters are no longer supported: move your files to 7-bits ASCII or unicode before translation (switch to unicode is automatically done if a file is loaded and saved again by coqide) - Renaming in ZArith: incompatibilities in Coq user contribs due to merging names INZ, from Reals, and inject_nat. - Renaming and new lemmas in ZArith: may clash with names used by users - Restructuration of ZArith: replace requirement of specific modules in ZArith by "Require Import ZArith_base" or "Require Import ZArith" - Some implicit arguments must be made explicit before translation: typically for "length nil", the implicit argument of length must be made explicit - Grammar rules, Infix notations and V7.4 Notations must be updated wrt the new scheme for syntactic extensions (see translator documentation) - Unsafe for annotation Cases when constructors coercions are used or when annotations are eta-reduced predicates Details of changes in 8.0 ~~~~~~~~~~~~~~~~~~~~~~~~~ Commands - New option "Set Printing All" to deactivate all high-level forms of printing (implicit arguments, coercions, destructing let, if-then-else, notations, projections) - "Functional Scheme" and "Functional Induction" extended to polymorphic types and dependent types - Notation now allows recursive patterns, hence recovering parts of the functionalities of pre-V8 Grammar/Syntax commands - Command "Print." discontinued. - Redundant syntax "Implicit Arguments On/Off" discontinued New syntax - Semantics change of the if-then-else construction in new syntax: "if c then t1 else t2" now stands for "match c with c1 _ ... _ => t1 | c2 _ ... _ => t2 end" with no dependency of t1 and t2 in the arguments of the constructors; this may cause incompatibilities for files translated using coq 8.0beta Notation scopes - Delimiting key %bool for bool_scope added - Import no more needed to activate argument scopes from a module Tactics and the tactic Language - Semantics of "assert" is now consistent with the reference manual - New tactics stepl and stepr for chaining transitivity steps - Tactic "replace ... with ... in" added - Intro patterns now supported in Ltac (parsed with prefix "ipattern:") Executables and tools - Added option -top to change the name of the toplevel module "Top" - Coqdoc updated to new syntax and now part of Coq sources - XML exportation tool now exports the structure of vernacular files (cf chapter 13 in the reference manual) User contributions - User contributions have been updated to the new syntax Bug fixes - Many bugs have been fixed (cf coq-bugs web page) rocq-9.2.0/doc/sphinx/conf.py000066400000000000000000000416061516144147600160630ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## v documentation" by default. #html_title = 'Coq 8.5 v8.5pl1' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] html_css_files = [ 'css/custom.css', ] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not None, a 'Last updated on:' timestamp is inserted at every page # bottom, using the given strftime format. # The empty string is equivalent to '%b %d, %Y'. #html_last_updated_fmt = None # FIXME: this could be re-enabled after ensuring that smart quotes are locally # disabled for all relevant directives smartquotes = False # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' #html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # 'ja' uses this config value. # 'zh' user can custom change `jieba` dictionary path. #html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. #html_search_scorer = 'scorer.js' # -- Options for LaTeX output --------------------------------------------- ########################### # Set things up for XeTeX # ########################### latex_elements = { 'babel': '', 'fontenc': '', 'inputenc': '', 'utf8extra': '', 'cmappkg': '', 'papersize': 'letterpaper', 'classoptions': ',openany', # No blank pages 'polyglossia': '\\usepackage{polyglossia}', 'sphinxsetup': 'verbatimwithframe=false', 'preamble': r""" \usepackage{unicode-math} \usepackage{microtype} % Macro definitions \usepackage{refman-preamble} % Style definitions for notations \usepackage{rocqnotations} % Style tweaks \newcssclass{sigannot}{\textrm{#1:}} % Silence 'LaTeX Warning: Command \nobreakspace invalid in math mode' \everymath{\def\nobreakspace{\ }} % deeper table of contents than default \setcounter{tocdepth}{4} """ } latex_engine = "xelatex" # Cf. https://github.com/sphinx-doc/sphinx/issues/7015 latex_use_xindy = False ######## # done # ######## latex_additional_files = [ "refman-preamble.sty", "_static/rocqnotations.sty" ] latex_documents = [('index', f'rocq-{version}-reference-manual.tex', 'The Rocq Prover Reference Manual', author, 'manual')] # The name of an image file (relative to this directory) to place at the top of # the title page. latex_logo = "../../ide/rocqide/coq.png" # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. latex_show_urls = 'footnote' # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). #man_pages = [ # (master_doc, 'rocq', 'Rocq Documentation', # [author], 1) #] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) #texinfo_documents = [ # (master_doc, 'Rocq', 'Rocq Documentation', # author, 'Rocq', 'One line description of project.', # 'Miscellaneous'), #] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. #epub_title = project #epub_author = author #epub_publisher = author #epub_copyright = copyright # The basename for the epub file. It defaults to the project name. #epub_basename = project # The HTML theme for the epub output. Since the default themes are not # optimized for small screen space, using the same theme for HTML and epub # output is usually not wise. This defaults to 'epub', a theme designed to save # visual space. #epub_theme = 'epub' # The language of the text. It defaults to the language option # or 'en' if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # A tuple containing the cover image and cover page html template filenames. #epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. #epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True # Choose between 'default' and 'includehidden'. #epub_tocscope = 'default' # Fix unsupported image types using the Pillow. #epub_fix_images = False # Scale large images. #epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. #epub_show_urls = 'inline' # If false, no index is generated. #epub_use_index = True # navtree options navtree_shift = True # since sphinxcontrib-bibtex version 2 we need this bibtex_bibfiles = [ "biblio.bib" ] rocq-9.2.0/doc/sphinx/coq-attrindex.rst000066400000000000000000000001341516144147600200670ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/coq-cmdindex.rst000066400000000000000000000001331516144147600176570ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/coq-exnindex.rst000066400000000000000000000001331516144147600177060ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/coq-optindex.rst000066400000000000000000000001331516144147600177160ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/coq-tacindex.rst000066400000000000000000000001331516144147600176630ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/dune000066400000000000000000000000441516144147600154310ustar00rootroot00000000000000(dirs :standard _static _templates) rocq-9.2.0/doc/sphinx/genindex.rst000066400000000000000000000001211516144147600171020ustar00rootroot00000000000000:orphan: .. hack to get index in TOC ------------- General index ------------- rocq-9.2.0/doc/sphinx/history.rst000066400000000000000000001727731516144147600170310ustar00rootroot00000000000000.. _history: ---------------------- Early history of Coq ---------------------- The Rocq Prover is the successor of Coq, whose history, up to version 7, is presented here. Historical roots ---------------- Coq is a proof assistant for higher-order logic, allowing the development of computer programs consistent with their formal specification. It is the result of about ten years [#years]_ of research of the Coq project. We shall briefly survey here three main aspects: the *logical language* in which we write our axiomatizations and specifications, the *proof assistant* which allows the development of verified mathematical proofs, and the *program extractor* which synthesizes computer programs obeying their formal specifications, written as logical assertions in the language. The logical language used by Coq is a variety of type theory, called the *Calculus of Inductive Constructions*. Without going back to Leibniz and Boole, we can date the creation of what is now called mathematical logic to the work of Frege and Peano at the turn of the century. The discovery of antinomies in the free use of predicates or comprehension principles prompted Russell to restrict predicate calculus with a stratification of *types*. This effort culminated with *Principia Mathematica*, the first systematic attempt at a formal foundation of mathematics. A simplification of this system along the lines of simply typed Ξ»-calculus occurred with Church’s *Simple Theory of Types*. The Ξ»-calculus notation, originally used for expressing functionality, could also be used as an encoding of natural deduction proofs. This Curry-Howard isomorphism was used by N. de Bruijn in the *Automath* project, the first full-scale attempt to develop and mechanically verify mathematical proofs. This effort culminated with Jutting’s verification of Landau’s *Grundlagen* in the 1970’s. Exploiting this Curry-Howard isomorphism, notable achievements in proof theory saw the emergence of two type-theoretic frameworks; the first one, Martin-LΓΆf’s *Intuitionistic Theory of Types*, attempts a new foundation of mathematics on constructive principles. The second one, Girard’s polymorphic Ξ»-calculus :math:`F_\omega`, is a very strong functional system in which we may represent higher-order logic proof structures. Combining both systems in a higher-order extension of the Automath language, T. Coquand presented in 1985 the first version of the *Calculus of Constructions*, CoC. This strong logical system allowed powerful axiomatizations, but direct inductive definitions were not possible, and inductive notions had to be defined indirectly through functional encodings, which introduced inefficiencies and awkwardness. The formalism was extended in 1989 by T. Coquand and C. Paulin with primitive inductive definitions, leading to the current *Calculus of Inductive Constructions*. This extended formalism is not rigorously defined here. Rather, numerous concrete examples are discussed. We refer the interested reader to relevant research papers for more information about the formalism, its meta-theoretic properties, and semantics. However, it should not be necessary to understand this theoretical material in order to write specifications. It is possible to understand the Calculus of Inductive Constructions at a higher level, as a mixture of predicate calculus, inductive predicate definitions presented as typed PROLOG, and recursive function definitions close to the language ML. Automated theorem-proving was pioneered in the 1960’s by Davis and Putnam in propositional calculus. A complete mechanization (in the sense of a semidecision procedure) of classical first-order logic was proposed in 1965 by J.A. Robinson, with a single uniform inference rule called *resolution*. Resolution relies on solving equations in free algebras (i.e. term structures), using the *unification algorithm*. Many refinements of resolution were studied in the 1970’s, but few convincing implementations were realized, except of course that PROLOG is in some sense issued from this effort. A less ambitious approach to proof development is computer-aided proof-checking. The most notable proof-checkers developed in the 1970’s were LCF, designed by R. Milner and his colleagues at U. Edinburgh, specialized in proving properties about denotational semantics recursion equations, and the Boyer and Moore theorem-prover, an automation of primitive recursion over inductive data types. While the Boyer-Moore theorem-prover attempted to synthesize proofs by a combination of automated methods, LCF constructed its proofs through the programming of *tactics*, written in a high-level functional meta-language, ML. The salient feature which clearly distinguishes our proof assistant from say LCF or Boyer and Moore’s, is its possibility to extract programs from the constructive contents of proofs. This computational interpretation of proof objects, in the tradition of Bishop’s constructive mathematics, is based on a realizability interpretation, in the sense of Kleene, due to C. Paulin. The user must just mark his intention by separating in the logical statements the assertions stating the existence of a computational object from the logical assertions which specify its properties, but which may be considered as just comments in the corresponding program. Given this information, the system automatically extracts a functional term from a consistency proof of its specifications. This functional term may be in turn compiled into an actual computer program. This methodology of extracting programs from proofs is a revolutionary paradigm for software engineering. Program synthesis has long been a theme of research in artificial intelligence, pioneered by R. Waldinger. The Tablog system of Z. Manna and R. Waldinger allows the deductive synthesis of functional programs from proofs in tableau form of their specifications, written in a variety of first-order logic. Development of a systematic *programming logic*, based on extensions of Martin-LΓΆf’s type theory, was undertaken at Cornell U. by the Nuprl team, headed by R. Constable. The first actual program extractor, PX, was designed and implemented around 1985 by S. Hayashi from Kyoto University. It allows the extraction of a LISP program from a proof in a logical system inspired by the logical formalisms of S. Feferman. Interest in this methodology is growing in the theoretical computer science community. We can foresee the day when actual computer systems used in applications will contain certified modules, automatically generated from a consistency proof of their formal specifications. We are however still far from being able to use this methodology in a smooth interaction with the standard tools from software engineering, i.e. compilers, linkers, run-time systems taking advantage of special hardware, debuggers, and the like. We hope that Coq can be of use to researchers interested in experimenting with this new methodology. .. [#years] At the time of writing, i.e. 1995. Versions 1 to 5 --------------- .. note:: This summary was written in 1995 together with the previous section and formed the initial version of the Credits chapter. A more comprehensive description of these early versions is available in the following subsections, which come from a document written in September 2015 by GΓ©rard Huet, Thierry Coquand and Christine Paulin. A first implementation of CoC was started in 1984 by G. Huet and T. Coquand. Its implementation language was CAML, a functional programming language from the ML family designed at INRIA in Rocquencourt. The core of this system was a proof-checker for CoC seen as a typed Ξ»-calculus, called the *Constructive Engine*. This engine was operated through a high-level notation permitting the declaration of axioms and parameters, the definition of mathematical types and objects, and the explicit construction of proof objects encoded as Ξ»-terms. A section mechanism, designed and implemented by G. Dowek, allowed hierarchical developments of mathematical theories. This high-level language was called the *Mathematical Vernacular*. Furthermore, an interactive *Theorem Prover* permitted the incremental construction of proof trees in a top-down manner, subgoaling recursively and backtracking from dead-ends. The theorem prover executed tactics written in CAML, in the LCF fashion. A basic set of tactics was predefined, which the user could extend by his own specific tactics. This system (Version 4.10) was released in 1989. Then, the system was extended to deal with the new calculus with inductive types by C. Paulin, with corresponding new tactics for proofs by induction. A new standard set of tactics was streamlined, and the vernacular extended for tactics execution. A package to compile programs extracted from proofs to actual computer programs in CAML or some other functional language was designed and implemented by B. Werner. A new user-interface, relying on a CAML-X interface by D. de Rauglaudre, was designed and implemented by A. Felty. It allowed operation of the theorem-prover through the manipulation of windows, menus, mouse-sensitive buttons, and other widgets. This system (Version 5.6) was released in 1991. Coq was ported to the new implementation Caml-light of X. Leroy and D. Doligez by D. de Rauglaudre (Version 5.7) in 1992. A new version of Coq was then coordinated by C. Murthy, with new tools designed by C. Parent to prove properties of ML programs (this methodology is dual to program extraction) and a new user-interaction loop. This system (Version 5.8) was released in May 1993. A Centaur interface CTCoq was then developed by Y. Bertot from the Croap project from INRIA-Sophia-Antipolis. In parallel, G. Dowek and H. Herbelin developed a new proof engine, allowing the general manipulation of existential variables consistently with dependent types in an experimental version of Coq (V5.9). The version V5.10 of Coq is based on a generic system for manipulating terms with binding operators due to Chet Murthy. A new proof engine allows the parallel development of partial proofs for independent subgoals. The structure of these proof trees is a mixed representation of derivation trees for the Calculus of Inductive Constructions with abstract syntax trees for the tactics scripts, allowing the navigation in a proof at various levels of details. The proof engine allows generic environment items managed in an object-oriented way. This new architecture, due to C. Murthy, supports several new facilities which make the system easier to extend and to scale up: - User-programmable tactics are allowed - It is possible to separately verify development modules, and to load their compiled images without verifying them again - a quick relocation process allows their fast loading - A generic parsing scheme allows user-definable notations, with a symmetric table-driven pretty-printer - Syntactic definitions allow convenient abbreviations - A limited facility of meta-variables allows the automatic synthesis of certain type expressions, allowing generic notations for e.g. equality, pairing, and existential quantification. In the Fall of 1994, C. Paulin-Mohring replaced the structure of inductively defined types and families by a new structure, allowing the mutually recursive definitions. P. Manoury implemented a translation of recursive definitions into the primitive recursive style imposed by the internal recursion operators, in the style of the ProPre system. C. MuΓ±oz implemented a decision procedure for intuitionistic propositional logic, based on results of R. Dyckhoff. J.C. FilliΓ’tre implemented a decision procedure for first-order logic without contraction, based on results of J. Ketonen and R. Weyhrauch. Finally C. Murthy implemented a library of inversion tactics, relieving the user from tedious definitions of β€œinversion predicates”. | Rocquencourt, Feb. 1st 1995 | GΓ©rard Huet | Version 1 ~~~~~~~~~ This software is a prototype type checker for a higher-order logical formalism known as the Theory of Constructions, presented in his PhD thesis by Thierry Coquand, with influences from Girard's system F and de Bruijn's Automath. The metamathematical analysis of the system is the PhD work of Thierry Coquand. The software is mostly the work of GΓ©rard Huet. Most of the mathematical examples verified with the software are due to Thierry Coquand. The programming language of the CONSTR software (as it was called at the time) was a version of ML adapted from the Edinburgh LCF system and running on a LISP backend. The main improvements from the original LCF ML were that ML was compiled rather than interpreted (GΓ©rard Huet building on the original translator by Lockwood Morris), and that it was enriched by recursively defined types (work of Guy Cousineau). This ancestor of CAML was used and improved by Larry Paulson for his implementation of Cambridge LCF. Software developments of this prototype occurred from late 1983 to early 1985. Version 1.10 was frozen on December 22nd 1984. It is the version used for the examples in Thierry Coquand's thesis, defended on January 31st 1985. There was a unique binding operator, used both for universal quantification (dependent product) at the level of types and functional abstraction (Ξ») at the level of terms/proofs, in the manner of Automath. Substitution (Ξ»-reduction) was implemented using de Bruijn's indexes. Version 1.11 was frozen on February 19th, 1985. It is the version used for the examples in the paper: T. Coquand, G. Huet. *Constructions: A Higher Order Proof System for Mechanizing Mathematics*Β :cite:`CH85`. Christine Paulin joined the team at this point, for her DEA research internship. In her DEA memoir (August 1985) she presents developments for the *lambo* function – :math:`\text{lambo}(f)(n)` computes the minimal :math:`m` such that :math:`f(m)` is greater than :math:`n`, for :math:`f` an increasing integer function, a challenge for constructive mathematics. She also encoded the majority voting algorithm of Boyer and Moore. Version 2 ~~~~~~~~~ The formal system, now renamed as the *Calculus of Constructions*, was presented with a proof of consistency and comparisons with proof systems of Per Martin LΓΆf, Girard, and the Automath family of N. de Bruijn, in the paper: T. Coquand and G. Huet. *The Calculus of Constructions*Β :cite:`CH88`. An abstraction of the software design, in the form of an abstract machine for proof checking, and a fuller sequence of mathematical developments was presented in: T. Coquand, G. Huet. *Concepts MathΓ©matiques et Informatiques FormalisΓ©s dans le Calcul des Constructions*Β :cite:`CH87`. Version 2.8 was frozen on December 16th, 1985, and served for developing the examples in the above papers. This calculus was then enriched in version 2.9 with a cumulative hierarchy of universes. Universe levels were initially explicit natural numbers. Another improvement was the possibility of automatic synthesis of implicit type arguments, relieving the user of tedious redundant declarations. Christine Paulin wrote an article *Algorithm development in the Calculus of Constructions*Β :cite:`P86`. Besides *lambo* and *majority*, she presents *quicksort* and a text formatting algorithm. Version 2.13 of the Calculus of Constructions with universes was frozen on June 25th, 1986. A synthetic presentation of type theory along constructive lines with ML algorithms was given by GΓ©rard Huet in his May 1986 CMU course notes *Formal Structures for Computation and Deduction*. Its chapter *Induction and Recursion in the Theory of Constructions* was presented as an invited paper at the Joint Conference on Theory and Practice of Software Development TAPSOFT’87 in Pisa in March 1987, and published as *Induction Principles Formalized in the Calculus of Constructions*Β :cite:`H88`. Version 3 ~~~~~~~~~ This version saw the beginning of proof automation, with a search algorithm inspired from PROLOG and the applicative logic programming programs of the course notes *Formal structures for computation and deduction*. The search algorithm was implemented in ML by Thierry Coquand. The proof system could thus be used in two modes: proof verification and proof synthesis, with tactics such as ``AUTO``. The implementation language was now called CAML, for Categorical Abstract Machine Language. It used as backend the LLM3 virtual machine of Le Lisp by JΓ©rΓ΄me Chailloux. The main developers of CAML were Michel Mauny, Ascander Suarez and Pierre Weis. V3.1 was started in the summer of 1986, V3.2 was frozen at the end of November 1986. V3.4 was developed in the first half of 1987. Thierry Coquand held a post-doctoral position in Cambridge University in 1986-87, where he developed a variant implementation in SML, with which he wrote some developments on fixpoints in Scott's domains. Version 4 ~~~~~~~~~ This version saw the beginning of program extraction from proofs, with two varieties of the type ``Prop`` of propositions, indicating constructive intent. The proof extraction algorithms were implemented by Christine Paulin-Mohring. V4.1 was frozen on July 24th, 1987. It had a first identified library of mathematical developments (directory ``exemples``), with libraries ``Logic`` (containing impredicative encodings of intuitionistic logic and algebraic primitives for booleans, natural numbers and list), ``Peano`` developing second-order Peano arithmetic, ``Arith`` defining addition, multiplication, euclidean division and factorial. Typical developments were the Knaster-Tarski theorem and Newman's lemma from rewriting theory. V4.2 was a joint development of a team consisting of Thierry Coquand, GΓ©rard Huet and Christine Paulin-Mohring. A file V4.2.log records the log of changes. It was frozen on September 1987 as the last version implemented in CAML 2.3, and V4.3 followed on CAML 2.5, a more stable development system. V4.3 saw the first top-level of the system. Instead of evaluating explicit quotations, the user could develop his mathematics in a high-level language called the mathematical vernacular (following Automath terminology). The user could develop files in the vernacular notation (with ``.v`` extension) which were now separate from the ``ml`` sources of the implementation. Gilles Dowek joined the team to develop the vernacular language as his DEA internship research. A notion of sticky constant was introduced, in order to keep names of lemmas when local hypotheses of proofs were discharged. This gave a notion of global mathematical environment with local sections. Another significant practical change was that the system, originally developed on the VAX central computer of our lab, was transferred on SUN personal workstations, allowing a level of distributed development. The extraction algorithm was modified, with three annotations ``Pos``, ``Null`` and ``Typ`` decorating the sorts ``Prop`` and ``Type``. Version 4.3 was frozen at the end of November 1987, and was distributed to an early community of users (among those were Hugo Herbelin and Loic Colson). V4.4 saw the first version of (encoded) inductive types. Now natural numbers could be defined as:: [source, coq] Inductive NAT : Prop = O : NAT | Succ : NAT->NAT. These inductive types were encoded impredicatively in the calculus, using a subsystem *rec* due to Christine Paulin. V4.4 was frozen on March 6th 1988. Version 4.5 was the first one to support inductive types and program extraction. Its banner was *Calcul des Constructions avec RΓ©alisations et SynthΓ¨se*. The vernacular language was enriched to accommodate extraction commands. The verification engine design was presented as: G. Huet. *The Constructive Engine*. Version 4.5. Invited Conference, 2nd European Symposium on Programming, Nancy, March 88. The final paper, describing the V4.9 implementation, appeared in: A perspective in Theoretical Computer Science, Commemorative Volume in memory of Gift Siromoney, Ed. R. Narasimhan, World Scientific Publishing, 1989. Version 4.5 was demonstrated in June 1988 at the YoP Institute on Logical Foundations of Functional Programming organized by GΓ©rard Huet at Austin, Texas. Version 4.6 was started during the summer of 1988. Its main improvement was the complete rehaul of the proof synthesis engine by Thierry Coquand, with a tree structure of goals. Its source code was communicated to Randy Pollack on September 2nd 1988. It evolved progressively into LEGO, proof system for Luo's formalism of Extended Calculus of Constructions. The discharge tactic was modified by GΓ©rard Huet to allow for inter-dependencies in discharged lemmas. Christine Paulin improved the inductive definition scheme in order to accommodate predicates of any arity. Version 4.7 was started on September 6th, 1988. This version starts exploiting the CAML notion of module in order to improve the modularity of the implementation. Now the term verifier is identified as a proper module Machine, which the structure of its internal data structures being hidden and thus accessible only through the legitimate operations. This machine (the constructive engine) was the trusted core of the implementation. The proof synthesis mechanism was a separate proof term generator. Once a complete proof term was synthesized with the help of tactics, it was entirely re-checked by the engine. Thus there was no need to certify the tactics, and the system took advantage of this fact by having tactics ignore the universe levels, universe consistency check being relegated to the final type checking pass. This induced a certain puzzlement in early users who saw, after a successful proof search, their ``QED`` followed by silence, followed by a failure message due to a universe inconsistency… The set of examples comprise set theory experiments by Hugo Herbelin, and notably the Schroeder-Bernstein theorem. Version 4.8, started on October 8th, 1988, saw a major re-implementation of the abstract syntax type ``constr``, separating variables of the formalism and metavariables denoting incomplete terms managed by the search mechanism. A notion of level (with three values ``TYPE``, ``OBJECT`` and ``PROOF``) is made explicit and a type judgement clarifies the constructions, whose implementation is now fully explicit. Structural equality is speeded up by using pointer equality, yielding spectacular improvements. Thierry Coquand adapts the proof synthesis to the new representation, and simplifies pattern matching to first-order predicate calculus matching, with important performance gain. A new representation of the universe hierarchy is then defined by GΓ©rard Huet. Universe levels are now implemented implicitly, through a hidden graph of abstract levels constrained with an order relation. Checking acyclicity of the graph insures well-foundedness of the ordering, and thus consistency. This was documented in a memo *Adding Type:Type to the Calculus of Constructions* which was never published. The development version is released as a stable 4.8 at the end of 1988. Version 4.9 is released on March 1st 1989, with the new "elastic" universe hierarchy. The spring of 1989 saw the first attempt at documenting the system usage, with a number of papers describing the formalism: - *Metamathematical Investigations of a Calculus of Constructions*, by Thierry CoquandΒ :cite:`C90`, - *Inductive definitions in the Calculus of Constructions*, by Christine Paulin-Mohrin, - *Extracting FΟ‰'s programs from proofs in the Calculus of Constructions*, by Christine Paulin-Mohring*Β :cite:`P89`, - *The Constructive Engine*, by GΓ©rard HuetΒ :cite:`H89`, as well as a number of user guides: - *A short user's guide for the Constructions*, Version 4.10, by GΓ©rard Huet - *A Vernacular Syllabus*, by Gilles Dowek. - *The Tactics Theorem Prover, User's guide*, Version 4.10, by Thierry Coquand. Stable V4.10, released on May 1st, 1989, was then a mature system, distributed with CAML V2.6. In the mean time, Thierry Coquand and Christine Paulin-Mohring had been investigating how to add native inductive types to the Calculus of Constructions, in the manner of Per Martin-LΓΆf's Intuitionistic Type Theory. The impredicative encoding had already been presented in: F. Pfenning and C. Paulin-Mohring. *Inductively defined types in the Calculus of Constructions*Β :cite:`PP90`. An extension of the calculus with primitive inductive types appeared in: T. Coquand and C. Paulin-Mohring. *Inductively defined types*Β :cite:`CP90`. This led to the Calculus of Inductive Constructions, logical formalism implemented in Versions 5 upward of the system, and documented in: C. Paulin-Mohring. *Inductive Definitions in the System Coq - Rules and Properties*Β :cite:`P93`. The last version of CONSTR is Version 4.11, which was last distributed in the spring of 1990. It was demonstrated at the first workshop of the European Basic Research Action Logical Frameworks In Sophia Antipolis in May 1990. Version 5 ~~~~~~~~~ At the end of 1989, Version 5.1 was started, and renamed as the system Coq for the Calculus of Inductive Constructions. It was then ported to the new stand-alone implementation of ML called Caml-light. In 1990 many changes occurred. Thierry Coquand left for Chalmers University in GΓΆteborg. Christine Paulin-Mohring took a CNRS researcher position at the LIP laboratory of Γ‰cole Normale SupΓ©rieure de Lyon. Project Formel was terminated, and gave rise to two teams: Cristal at INRIA-Roquencourt, that continued developments in functional programming with Caml-light then OCaml, and Coq, continuing the type theory research, with a joint team headed by GΓ©rard Huet at INRIA-Rocquencourt and Christine Paulin-Mohring at the LIP laboratory of CNRS-ENS Lyon. Chetan Murthy joined the team in 1991 and became the main software architect of Version 5. He completely rehauled the implementation for efficiency. Versions 5.6 and 5.8 were major distributed versions, with complete documentation and a library of users' developments. The use of the RCS revision control system, and systematic ChangeLog files, allow a more precise tracking of the software developments. | September 2015 + | Thierry Coquand, GΓ©rard Huet and Christine Paulin-Mohring. | Versions 6 ---------- Version 6.1 ~~~~~~~~~~~ The present version 6.1 of Coq is based on the V5.10 architecture. It was ported to the new language Objective Caml by Bruno Barras. The underlying framework has slightly changed and allows more conversions between sorts. The new version provides powerful tools for easier developments. Cristina Cornes designed an extension of the Coq syntax to allow definition of terms using a powerful pattern matching analysis in the style of ML programs. Amokrane SaΓ―bi wrote a mechanism to simulate inheritance between types families extending a proposal by Peter Aczel. He also developed a mechanism to automatically compute which arguments of a constant may be inferred by the system and consequently do not need to be explicitly written. Yann Coscoy designed a command which explains a proof term using natural language. Pierre CrΓ©gut built a new tactic which solves problems in quantifier-free Presburger Arithmetic. Both functionalities have been integrated to the Coq system by Hugo Herbelin. Samuel Boutin designed a tactic for simplification of commutative rings using a canonical set of rewriting rules and equality modulo associativity and commutativity. Finally the organisation of the Coq distribution has been supervised by Jean-Christophe FilliΓ’tre with the help of JudicaΓ«l Courant and Bruno Barras. | Lyon, Nov. 18th 1996 | Christine Paulin | Version 6.2 ~~~~~~~~~~~ In version 6.2 of Coq, the parsing is done using camlp4, a preprocessor and pretty-printer for CAML designed by Daniel de Rauglaudre at INRIA. Daniel de Rauglaudre made the first adaptation of Coq for camlp4, this work was continued by Bruno Barras who also changed the structure of Coq abstract syntax trees and the primitives to manipulate them. The result of these changes is a faster parsing procedure with greatly improved syntax-error messages. The user-interface to introduce grammar or pretty-printing rules has also changed. Eduardo GimΓ©nez redesigned the internal tactic libraries, giving uniform names to Caml functions corresponding to Coq tactic names. Bruno Barras wrote new, more efficient reduction functions. Hugo Herbelin introduced more uniform notations in the Coq specification language: the definitions by fixpoints and pattern matching have a more readable syntax. Patrick Loiseleur introduced user-friendly notations for arithmetic expressions. New tactics were introduced: Eduardo GimΓ©nez improved the mechanism to introduce macros for tactics, and designed special tactics for (co)inductive definitions; Patrick Loiseleur designed a tactic to simplify polynomial expressions in an arbitrary commutative ring which generalizes the previous tactic implemented by Samuel Boutin. Jean-Christophe FilliΓ’tre introduced a tactic for refining a goal, using a proof term with holes as a proof scheme. David Delahaye designed the tool to search an object in the library given its type (up to isomorphism). Henri LaulhΓ¨re produced the Coq distribution for the Windows environment. Finally, Hugo Herbelin was the main coordinator of the Coq documentation with principal contributions by Bruno Barras, David Delahaye, Jean-Christophe FilliΓ’tre, Eduardo GimΓ©nez, Hugo Herbelin and Patrick Loiseleur. | Orsay, May 4th 1998 | Christine Paulin | Version 6.3 ~~~~~~~~~~~ The main changes in version V6.3 were the introduction of a few new tactics and the extension of the guard condition for fixpoint definitions. B. Barras extended the unification algorithm to complete partial terms and fixed various tricky bugs related to universes. D. Delahaye developed the ``AutoRewrite`` tactic. He also designed the new behavior of ``Intro`` and provided the tacticals ``First`` and ``Solve``. J.-C. FilliΓ’tre developed the ``Correctness`` tactic. \E. GimΓ©nez extended the guard condition in fixpoints. H. Herbelin designed the new syntax for definitions and extended the ``Induction`` tactic. P. Loiseleur developed the ``Quote`` tactic and the new design of the ``Auto`` tactic, he also introduced the index of errors in the documentation. C. Paulin wrote the ``Focus`` command and introduced the reduction functions in definitions, this last feature was proposed by J.-F. Monin from CNET Lannion. | Orsay, Dec. 1999 | Christine Paulin | Versions 7 ---------- Summary of changes ~~~~~~~~~~~~~~~~~~ The version V7 is a new implementation started in September 1999 by Jean-Christophe FilliΓ’tre. This is a major revision with respect to the internal architecture of the system. The Coq version 7.0 was distributed in March 2001, version 7.1 in September 2001, version 7.2 in January 2002, version 7.3 in May 2002 and version 7.4 in February 2003. Jean-Christophe FilliΓ’tre designed the architecture of the new system. He introduced a new representation for environments and wrote a new kernel for type checking terms. His approach was to use functional data-structures in order to get more sharing, to prepare the addition of modules and also to get closer to a certified kernel. Hugo Herbelin introduced a new structure of terms with local definitions. He introduced β€œqualified” names, wrote a new pattern matching compilation algorithm and designed a more compact algorithm for checking the logical consistency of universes. He contributed to the simplification of Coq internal structures and the optimisation of the system. He added basic tactics for forward reasoning and coercions in patterns. David Delahaye introduced a new language for tactics. General tactics using pattern matching on goals and context can directly be written from the Coq toplevel. He also provided primitives for the design of user-defined tactics in Caml. Micaela Mayero contributed the library on real numbers. Olivier Desmettre extended this library with axiomatic trigonometric functions, square, square roots, finite sums, Chasles property and basic plane geometry. Jean-Christophe FilliΓ’tre and Pierre Letouzey redesigned a new extraction procedure from Coq terms to Caml or Haskell programs. This new extraction procedure, unlike the one implemented in previous version of Coq is able to handle all terms in the Calculus of Inductive Constructions, even involving universes and strong elimination. P. Letouzey adapted user contributions to extract ML programs when it was sensible. Jean-Christophe FilliΓ’tre wrote ``coqdoc`` (now ``rocq doc``), a documentation tool for Coq libraries usable from version 7.2. Bruno Barras improved the efficiency of the reduction algorithm and the confidence level in the correctness of Coq critical type checking algorithm. Yves Bertot designed the ``SearchPattern`` and ``SearchRewrite`` tools and the support for the pcoq interface (http://www-sop.inria.fr/lemme/pcoq/). Micaela Mayero and David Delahaye introduced Field, a decision tactic for commutative fields. Christine Paulin changed the elimination rules for empty and singleton propositional inductive types. LoΓ―c Pottier developed Fourier, a tactic solving linear inequalities on real numbers. Pierre CrΓ©gut developed a new, reflection-based version of the Omega decision procedure. Claudio Sacerdoti Coen designed an XML output for the Coq modules to be used in the Hypertextual Electronic Library of Mathematics (HELM cf http://www.cs.unibo.it/helm). A library for efficient representation of finite maps using binary trees contributed by Jean Goubault was integrated in the basic theories. Pierre Courtieu developed a command and a tactic to reason on the inductive structure of recursively defined functions. Jacek ChrzΔ…szcz designed and implemented the module system of Coq whose foundations are in JudicaΓ«l Courant’s PhD thesis. The development was coordinated by C. Paulin. Many discussions within the DΓ©mons team and the LogiCal project influenced significantly the design of Coq especially with J. Courant, J. Duprat, J. Goubault, A. Miquel, C. MarchΓ©, B. Monate and B. Werner. Intensive users suggested improvements of the system : Y. Bertot, L. Pottier, L. ThΓ©ry, P. Zimmerman from INRIA, C. Alvarado, P. CrΓ©gut, J.-F. Monin from France Telecom R & D. | Orsay, May. 2002 | Hugo Herbelin & Christine Paulin | Details of changes in 7.0 and 7.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Notes: - items followed by (**) are important sources of incompatibilities - items followed by (*) may exceptionally be sources of incompatibilities - items followed by (+) have been introduced in version 7.0 Main novelties ^^^^^^^^^^^^^^ References are to Coq 7.1 reference manual - New primitive let-in construct (see sections 1.2.8 and ) - Long names (see sections 2.6 and 2.7) - New high-level tactic language (see chapter 10) - Improved search facilities (see section 5.2) - New extraction algorithm managing the Type level (see chapter 17) - New rewriting tactic for arbitrary equalities (see chapter 19) - New tactic Field to decide equalities on commutative fields (see 7.11) - New tactic Fourier to solve linear inequalities on reals numbers (see 7.11) - New tactics for induction/case analysis in "natural" style (see 7.7) - Deep restructuration of the code (safer, simpler and more efficient) - Export of theories to XML for publishing and rendering purposes (see http://www.cs.unibo.it/helm) Details of changes ^^^^^^^^^^^^^^^^^^ Language: new "let-in" construction *********************************** - New construction for local definitions (let-in) with syntax [x:=u]t (*)(+) - Local definitions allowed in Record (a.k.a. record Γ  la Randy Pollack) Language: long names ******************** - Each construction has a unique absolute names built from a base name, the name of the module in which they are defined (Top if in coqtop), and possibly an arbitrary long sequence of directory (e.g. "Coq.Lists.PolyList.flat_map" where "Coq" means that "flat_map" is part of Coq standard library, "Lists" means it is defined in the Lists library and "PolyList" means it is in the file Polylist) (+) - Constructions can be referred by their base name, or, in case of conflict, by a "qualified" name, where the base name is prefixed by the module name (and possibly by a directory name, and so on). A fully qualified name is an absolute name which always refer to the construction it denotes (to preserve the visibility of all constructions, no conflict is allowed for an absolute name) (+) - Long names are available for modules with the possibility of using the directory name as a component of the module full name (with option -R to coqtop and coqc, or command Add LoadPath) (+) - Improved conflict resolution strategy (the Unix PATH model), allowing more constructions to be referred just by their base name Language: miscellaneous *********************** - The names of variables for Record projections _and_ for induction principles (e.g. sum_ind) is now based on the first letter of their type (main source of incompatibility) (**)(+) - Most typing errors have now a precise location in the source (+) - Slightly different mechanism to solve "?" (*)(+) - More arguments may be considered implicit at section closing (*)(+) - Bug with identifiers ended by a number greater than 2^30 fixed (+) - New visibility discipline for Remark, Fact and Local: Remark's and Fact's now survive at the end of section, but are only accessible using a qualified names as soon as their strength expires; Local's disappear and are moved into local definitions for each construction persistent at section closing Language: Cases *************** - Cases no longer considers aliases inferable from dependencies in types (*)(+) - A redundant clause in Cases is now an error (*) Reduction ********* - New reduction flags "Zeta" and "Evar" in Eval Compute, for inlining of local definitions and instantiation of existential variables - Delta reduction flag does not perform Zeta and Evar reduction any more (*) - Constants declared as opaque (using Qed) can no longer become transparent (a constant intended to be alternatively opaque and transparent must be declared as transparent (using Defined)); a risk exists (until next Coq version) that Simpl and Hnf reduces opaque constants (*) New tactics *********** - New set of tactics to deal with types equipped with specific equalities (a.k.a. Setoids, e.g. nat equipped with eq_nat) [by C. Renard] - New tactic Assert, similar to Cut but expected to be more user-friendly - New tactic NewDestruct and NewInduction intended to replace Elim and Induction, Case and Destruct in a more user-friendly way (see restrictions in the reference manual) - New tactic ROmega: an experimental alternative (based on reflexion) to Omega [by P. CrΓ©gut] - New tactic language Ltac (see reference manual) (+) - New versions of Tauto and Intuition, fully rewritten in the new Ltac language; they run faster and produce more compact proofs; Tauto is fully compatible but, in exchange of a better uniformity, Intuition is slightly weaker (then use Tauto instead) (**)(+) - New tactic Field to decide equalities on commutative fields (as a special case, it works on real numbers) (+) - New tactic Fourier to solve linear inequalities on reals numbers [by L. Pottier] (+) - New tactics dedicated to real numbers: DiscrR, SplitRmult, SplitAbsolu (+) Changes in existing tactics *************************** - Reduction tactics in local definitions apply only to the body - New syntax of the form "Compute in Type of H." to require a reduction on the types of local definitions - Inversion, Injection, Discriminate, ... apply also on the quantified premises of a goal (using the "Intros until" syntax) - Decompose has been fixed but hypotheses may get different names (*)(+) - Tauto now manages uniformly hypotheses and conclusions of the form ``t=t`` which all are considered equivalent to ``True``. Especially, Tauto now solves goals of the form ``H : ~ t = t |- A``. - The "Let" tactic has been renamed "LetTac" and is now based on the primitive "let-in" (+) - Elim can no longer be used with an elimination schema different from the one defined at definition time of the inductive type. To overload an elimination schema, use "Elim using " (*)(+) - Simpl no longer unfolds the recursive calls of a mutually defined fixpoint (*)(+) - Intro now fails if the hypothesis name already exists (*)(+) - "Require Prolog" is no longer needed (i.e. it is available by default) (*)(+) - Unfold now fails on a non-unfoldable identifier (*)(+) - Unfold also applies on definitions of the local context - AutoRewrite now deals only with the main goal and it is the purpose of Hint Rewrite to deal with generated subgoals (+) - Redundant or incompatible instantiations in Apply ... with ... are now correctly managed (+) Efficiency ********** - Excessive memory uses specific to V7.0 fixed - Sizes of .vo files vary a lot compared to V6.3 (from -30% to +300% depending on the developments) - An improved reduction strategy for lazy evaluation - A more economical mechanism to ensure logical consistency at the Type level; warning: this is experimental and may produce "universes" anomalies (please report) Concrete syntax of constructions ******************************** - Only identifiers starting with "_" or a letter, and followed by letters, digits, "_" or "'" are allowed (e.g. "$" and "@" are no longer allowed) (*) - A multiple binder like (a:A)(a,b:(P a))(Q a) is no longer parsed as (a:A)(a0:(P a))(b:(P a))(Q a0) but as (a:A)(a0:(P a))(b:(P a0))(Q a0) (*)(+) - A dedicated syntax has been introduced for Reals (e.g ``3+1/x``) (+) - Pretty-printing of Infix notations fixed. (+) Parsing and grammar extension ***************************** - More constraints when writing ast - "{...}" and the macros $LIST, $VAR, etc. now expect a metavariable (an identifier starting with $) (*) - identifiers should starts with a letter or "_" and be followed by letters, digits, "_" or "'" (other characters are still supported but it is not advised to use them) (*)(+) - Entry "command" in "Grammar" and quotations (<<...>> stuff) is renamed "constr" as in "Syntax" (+) - New syntax "[" sentence_1 ... sentence_n"]." to group sentences (useful for Time and to write grammar rules abbreviating several commands) (+) - The default parser for actions in the grammar rules (and for patterns in the pretty-printing rules) is now the one associated with the grammar (i.e. vernac, tactic or constr); no need then for quotations as in <:vernac:<...>>; to return an "ast", the grammar must be explicitly typed with tag ": ast" or ": ast list", or if a syntax rule, by using <<...>> in the patterns (expression inside these angle brackets are parsed as "ast"); for grammars other than vernac, tactic or constr, you may explicitly type the action with tags ": constr", ": tactic", or ":vernac" (**)(+) - Interpretation of names in Grammar rule is now based on long names, which allows to avoid problems (or sometimes tricks;) related to overloaded names (+) New commands ************ - New commands "Print XML All", "Show XML Proof", ... to show or export theories to XML to be used with Helm's publishing and rendering tools (see http://www.cs.unibo.it/helm) (by Claudio Sacerdoti Coen) (+) - New commands to manually set implicit arguments (+) - "Implicits ident." to activate the implicit arguments mode just for ident - "Implicits ident [num1 num2 ...]." to explicitly give which arguments have to be considered as implicit - New SearchPattern/SearchRewrite (by Yves Bertot) (+) - New commands "Debug on"/"Debug off" to activate/deactivate the tactic language debugger (+) - New commands to map physical paths to logical paths (+) - Add LoadPath physical_dir as logical_dir - Add Rec LoadPath physical_dir as logical_dir Changes in existing commands **************************** - Generalization of the usage of qualified identifiers in tactics and commands about globals, e.g. Decompose, Eval Delta; Hints Unfold, Transparent, Require - Require synchronous with Reset; Require's scope stops at Section ending (*) - For a module indirectly loaded by a "Require" but not exported, the command "Import module" turns the constructions defined in the module accessible by their short name, and activates the Grammar, Syntax, Hint, ... declared in the module (+) - The scope of the "Search" command can be restricted to some modules (+) - Final dot in command (full stop/period) must be followed by a blank (newline, tabulation or whitespace) (+) - Slight restriction of the syntax for Cbv Delta: if present, option [-myconst] must immediately follow the Delta keyword (*)(+) - SearchIsos currently not supported - Add ML Path is now implied by Add LoadPath (+) - New names for the following commands (+) AddPath -> Add LoadPath Print LoadPath -> Print LoadPath DelPath -> Remove LoadPath AddRecPath -> Add Rec LoadPath Print Path -> Print Coercion Paths Implicit Arguments On -> Set Implicit Arguments Implicit Arguments Off -> Unset Implicit Arguments Begin Silent -> Set Silent End Silent -> Unset Silent. Tools ***** - coqtop (+) - Two executables: coqtop.byte and coqtop.opt (if supported by the platform) - coqtop is a link to the more efficient executable (coqtop.opt if present) - option -full is obsolete (+) - do_Makefile renamed into coq_makefile (+) - New option -R to coqtop and coqc to map a physical directory to a logical one (+) - coqc no longer needs to create a temporary file - No more warning if no initialization file .coqrc exists Extraction ********** - New algorithm for extraction able to deal with "Type" (+) (by J.-C. FilliΓ’tre and P. Letouzey) Standard library **************** - New library on maps on integers (IntMap, contributed by Jean Goubault) - New lemmas about integer numbers [ZArith] - New lemmas and a "natural" syntax for reals [Reals] (+) - Exc/Error/Value renamed into Option/Some/None (*) New user contributions ********************** - Constructive complex analysis and the Fundamental Theorem of Algebra [FTA] (Herman Geuvers, Freek Wiedijk, Jan Zwanenburg, Randy Pollack, Henk Barendregt, Nijmegen) - A new axiomatization of ZFC set theory [Functions_in_ZFC] (C. Simpson, Sophia-Antipolis) - Basic notions of graph theory [GRAPHS-BASICS] (Jean Duprat, Lyon) - A library for floating-point numbers [Float] (Laurent ThΓ©ry, Sylvie Boldo, Sophia-Antipolis) - Formalisation of CTL and TCTL temporal logic [CtlTctl] (Carlos Daniel Luna,Montevideo) - Specification and verification of the Railroad Crossing Problem in CTL and TCTL [RailroadCrossing] (Carlos Daniel Luna,Montevideo) - P-automaton and the ABR algorithm [PAutomata] (Christine Paulin, Emmanuel Freund, Orsay) - Semantics of a subset of the C language [MiniC] (Eduardo GimΓ©nez, Emmanuel Ledinot, Suresnes) - Correctness proofs of the following imperative algorithms: Bresenham line drawing algorithm [Bresenham], MarchΓ©'s minimal edition distance algorithm [Diff] (Jean-Christophe FilliΓ’tre, Orsay) - Correctness proofs of Buchberger's algorithm [Buchberger] and RSA cryptographic algorithm [Rsa] (Laurent ThΓ©ry, Sophia-Antipolis) - Correctness proof of Stalmarck tautology checker algorithm [Stalmarck] (Laurent ThΓ©ry, Pierre Letouzey, Sophia-Antipolis) Details of changes in 7.2 ~~~~~~~~~~~~~~~~~~~~~~~~~ Language - Automatic insertion of patterns for local definitions in the type of the constructors of an inductive types (for compatibility with V6.3 let-in style) - Coercions allowed in Cases patterns - New declaration "Canonical Structure id = t : I" to help resolution of equations of the form (proj ?)=a; if proj(e)=a then a is canonically equipped with the remaining fields in e, i.e. ? is instantiated by e Tactics - New tactic "ClearBody H" to clear the body of definitions in local context - New tactic "Assert H := c" for forward reasoning - Slight improvement in naming strategy for NewInduction/NewDestruct - Intuition/Tauto do not perform useless unfolding and work up to conversion Extraction (details in plugins/extraction/CHANGES or documentation) - Syntax changes: there are no more options inside the extraction commands. New commands for customization and options have been introduced instead. - More optimizations on extracted code. - Extraction tests are now embedded in 14 user contributions. Standard library - In [Relations], Rstar.v and Newman.v now axiom-free. - In [Sets], Integers.v now based on nat - In [Arith], more lemmas in Min.v, new file Max.v, tail-recursive plus and mult added to Plus.v and Mult.v respectively - New directory [Sorting] with a proof of heapsort (dragged from 6.3.1 lib) - In [Reals], more lemmas in Rbase.v, new lemmas on square, square root and trigonometric functions (R_sqr.v - Rtrigo.v); a complementary approach and new theorems about continuity and derivability in Ranalysis.v; some properties in plane geometry such as translation, rotation or similarity in Rgeom.v; finite sums and Chasles property in Rsigma.v Bugs - Confusion between implicit args of locals and globals of same base name fixed - Various incompatibilities wrt inference of "?" in V6.3.1 fixed - Implicits in infix section variables bug fixed - Known coercions bugs fixed - Apply "universe anomaly" bug fixed - NatRing now working - "Discriminate 1", "Injection 1", "Simplify_eq 1" now working - NewInduction bugs with let-in and recursively dependent hypotheses fixed - Syntax [x:=t:T]u now allowed as mentioned in documentation - Bug with recursive inductive types involving let-in fixed - Known pattern-matching bugs fixed - Known Cases elimination predicate bugs fixed - Improved errors messages for pattern-matching and projections - Better error messages for ill-typed Cases expressions Incompatibilities - New naming strategy for NewInduction/NewDestruct may affect 7.1 compatibility - Extra parentheses may exceptionally be needed in tactic definitions. - Coq extensions written in OCaml need to be updated (see dev/changements.txt for a description of the main changes in the interface files of V7.2) - New behavior of Intuition/Tauto may exceptionally lead to incompatibilities Details of changes in 7.3 ~~~~~~~~~~~~~~~~~~~~~~~~~ Language - Slightly improved compilation of pattern-matching (slight source of incompatibilities) - Record's now accept anonymous fields "_" which does not build projections - Changes in the allowed elimination sorts for certain class of inductive definitions : an inductive definition without constructors of Sort Prop can be eliminated on sorts Set and Type A "singleton" inductive definition (one constructor with arguments in the sort Prop like conjunction of two propositions or equality) can be eliminated directly on sort Type (In V7.2, only the sorts Prop and Set were allowed) Tactics - New tactic "Rename x into y" for renaming hypotheses - New tactics "Pose x:=u" and "Pose u" to add definitions to local context - Pattern now working on partially applied subterms - Ring no longer applies irreversible congruence laws of mult but better applies congruence laws of plus (slight source of incompatibilities). - Field now accepts terms to be simplified as arguments (as for Ring). This extension has been also implemented using the toplevel tactic language. - Intuition does no longer unfold constants except "<->" and "~". It can be parameterized by a tactic. It also can introduce dependent product if needed (source of incompatibilities) - "Match Context" now matching more recent hypotheses first and failing only on user errors and Fail tactic (possible source of incompatibilities) - Tactic Definition's without arguments now allowed in Coq states - Better simplification and discrimination made by Inversion (source of incompatibilities) Bugs - "Intros H" now working like "Intro H" trying first to reduce if not a product - Forward dependencies in Cases now taken into account - Known bugs related to Inversion and let-in's fixed - Bug unexpected Delta with let-in now fixed Extraction (details in plugins/extraction/CHANGES or documentation) - Signatures of extracted terms are now mostly expunged from dummy arguments. - Haskell extraction is now operational (tested & debugged). Standard library - Some additions in [ZArith]: three files (Zcomplements.v, Zpower.v and Zlogarithms.v) moved from plugins/omega in order to be more visible, one Zsgn function, more induction principles (Wf_Z.v and tail of Zcomplements.v), one more general Euclid theorem - Peano_dec.v and Compare_dec.v now part of Arith.v Tools - new option -dump-glob to coqtop to dump globalizations (to be used by the new documentation tool coqdoc; see http://www.lri.fr/~filliatr/coqdoc) User Contributions - CongruenceClosure (congruence closure decision procedure) [Pierre Corbineau, ENS Cachan] - MapleMode (an interface to embed Maple simplification procedures over rational fractions in Coq) [David Delahaye, Micaela Mayero, Chalmers University] - Presburger: A formalization of Presburger's algorithm [Laurent Thery, INRIA Sophia Antipolis] - Chinese has been rewritten using Z from ZArith as datatype ZChinese is the new version, Chinese the obsolete one [Pierre Letouzey, LRI Orsay] Incompatibilities - Ring: exceptional incompatibilities (1 above 650 in submitted user contribs, leading to a simplification) - Intuition: does not unfold any definition except "<->" and "~" - Cases: removal of some extra Cases in configurations of the form "Cases ... of C _ => ... | _ D => ..." (effects on 2 definitions of submitted user contributions necessitating the removal of now superfluous proof steps in 3 different proofs) - Match Context, in case of incompatibilities because of a now non trapped error (e.g. Not_found or Failure), use instead tactic Fail to force Match Context trying the next clause - Inversion: better simplification and discrimination may occasionally lead to less subgoals and/or hypotheses and different naming of hypotheses - Unification done by Apply/Elim has been changed and may exceptionally lead to incompatible instantiations - Peano_dec.v and Compare_dec.v parts of Arith.v make Auto more powerful if these files were not already required (1 occurrence of this in submitted user contribs) Changes in 7.3.1 ^^^^^^^^^^^^^^^^ Bug fixes - Corrupted Field tactic and Match Context tactic construction fixed - Checking of names already existing in Assert added (#1386) - Invalid argument bug in Exact tactic solved (#1387) - Colliding bound names bug fixed (#1412) - Wrong non-recursivity test for Record fixed (#1394) - Out of memory/seg fault bug related to parametric inductive fixed (#1404) - Setoid_replace/Setoid_rewrite bug wrt "==" fixed Misc - Ocaml version >= 3.06 is needed to compile Coq from sources - Simplification of fresh names creation strategy for Assert, Pose and LetTac (#1402) Details of changes in 7.4 ~~~~~~~~~~~~~~~~~~~~~~~~~ Symbolic notations - Introduction of a notion of scope gathering notations in a consistent set; a notation sets has been developed for nat, Z and R (undocumented) - New command "Notation" for declaring notations simultaneously for parsing and printing (see chap 10 of the reference manual) - Declarations with only implicit arguments now handled (e.g. the argument of nil can be set implicit; use !nil to refer to nil without arguments) - "Print Scope sc" and "Locate ntn" allows to know to what expression a notation is bound - New defensive strategy for printing or not implicit arguments to ensure re-type-checkability of the printed term - In Grammar command, the only predefined non-terminal entries are ident, global, constr and pattern (e.g. nvar, numarg disappears); the only allowed grammar types are constr and pattern; ast and ast list are no longer supported; some incompatibilities in Grammar: when a syntax is a initial segment of an other one, Grammar does not work, use Notation Library - Lemmas in Set from Compare_dec.v (le_lt_dec, ...) and Wf_nat.v (lt_wf_rec, ...) are now transparent. This may be source of incompatibilities. - Syntactic Definitions Fst, Snd, Ex, All, Ex2, AllT, ExT, ExT2, ProjS1, ProjS2, Error, Value and Except are turned to notations. They now must be applied (incompatibilities only in unrealistic cases). - More efficient versions of Zmult and times (30% faster) - Reals: the library is now divided in 6 parts (Rbase, Rfunctions, SeqSeries, Rtrigo, Ranalysis, Integration). New tactics: Sup and RCompute. See Reals.v for details. Modules - Beta version, see doc chap 2.5 for commands and chap 5 for theory Language - Inductive definitions now accept ">" in constructor types to declare the corresponding constructor as a coercion. - Idem for assumptions declarations and constants when the type is mentioned. - The "Coercion" and "Canonical Structure" keywords now accept the same syntax as "Definition", i.e. "hyps :=c (:t)?" or "hyps :t". - Theorem-like declaration now accepts the syntax "Theorem thm [x:t;...] : u". - Remark's and Fact's now definitively behave as Theorem and Lemma: when sections are closed, the full name of a Remark or a Fact has no longer a section part (source of incompatibilities) - Opaque Local's (i.e. built by tactics and ended by Qed), do not survive section closing any longer; as a side-effect, Opaque Local's now appear in the local context of proofs; their body is hidden though (source of incompatibilities); use one of Remark/Fact/Lemma/Theorem instead to simulate the old behavior of Local (the section part of the name is not kept though) ML tactics and commands - "Grammar tactic" and "Grammar vernac" of type "ast" are no longer supported (only "Grammar tactic simple_tactic" of type "tactic" remains available). - Concrete syntax for ML written commands and tactics is now declared at ML level using camlp4 macros TACTIC EXTEND et VERNAC COMMAND EXTEND. - "Check n c" now "n:Check c", "Eval n ..." now "n:Eval ..." - ``Proof with T`` (no documentation) - SearchAbout id - prints all theorems which contain id in their type Tactic definitions - Static globalisation of identifiers and global references (source of incompatibilities, especially, Recursive keyword is required for mutually recursive definitions). - New evaluation semantics: no more partial evaluation at definition time; evaluation of all Tactic/Meta Definition, even producing terms, expect a proof context to be evaluated (especially "()" is no longer needed). - Debugger now shows the nesting level and the reasons of failure Tactics - Equality tactics (Rewrite, Reflexivity, Symmetry, Transitivity) now understand JM equality - Simpl and Change now apply to subterms also - "Simpl f" reduces subterms whose :term:`head constant` is f - Double Induction now referring to hypotheses like "Intros until" - "Inversion" now applies also on quantified hypotheses (naming as for Intros until) - NewDestruct now accepts terms with missing hypotheses - NewDestruct and NewInduction now accept user-provided elimination scheme - NewDestruct and NewInduction now accept user-provided introduction names - Omega could solve goals such as ``~x=y`` but failed when the hypothesis was unfolded to ``x < y -> False``. This is fixed. In addition, it can also recognize 'False' in the hypothesis and use it to solve the goal. - Coercions now handled in "with" bindings - "Subst x" replaces all occurrences of x by t in the goal and hypotheses when an hypothesis x=t or x:=t or t=x exists - Fresh names for Assert and Pose now based on collision-avoiding Intro naming strategy (exceptional source of incompatibilities) - LinearIntuition (no documentation) - Unfold expects a correct evaluable argument - Clear expects existing hypotheses Extraction (See details in plugins/extraction/CHANGES and README): - An experimental Scheme extraction is provided. - Concerning OCaml, extracted code is now ensured to always type check, thanks to automatic inserting of Obj.magic. - Experimental extraction of Coq new modules to Ocaml modules. Proof rendering in natural language - Export of theories to XML for publishing and rendering purposes now includes proof-trees (see http://www.cs.unibo.it/helm) Miscellaneous - Printing Coercion now used through the standard keywords Set/Add, Test, Print - "Print Term id" is an alias for "Print id" - New switch "Unset/Set Printing Symbols" to control printing of symbolic notations - Two new variants of implicit arguments are available + ``Unset``/``Set Contextual Implicits`` tells to consider implicit also the arguments inferable from the context (e.g. for nil or refl_eq) + ``Unset``/``Set Strict Implicits`` tells to consider implicit only the arguments that are inferable in any case (i.e. arguments that occurs as argument of rigid constants in the type of the remaining arguments; e.g. the witness of an existential is not strict since it can vanish when applied to a predicate which does not use its argument) Incompatibilities - "Grammar tactic ... : ast" and "Grammar vernac ... : ast" are no longer supported, use TACTIC EXTEND and VERNAC COMMAND EXTEND on the ML-side instead - Transparency of le_lt_dec and co (leads to some simplification in proofs; in some cases, incompatibilites is solved by declaring locally opaque the relevant constant) - Opaque Local do not now survive section closing (rename them into Remark/Lemma/... to get them still surviving the sections; this renaming allows also to solve incompatibilites related to now forbidden calls to the tactic Clear) - Remark and Fact have no longer (very) long names (use Local instead in case of name conflict) Bugs - Improved localisation of errors in Syntactic Definitions - Induction principle creation failure in presence of let-in fixed (#1459) - Inversion bugs fixed (#1427 and #1437) - Omega bug related to Set fixed (#1384) - Type-checking inefficiency of nested destructuring let-in fixed (#1435) - Improved handling of let-in during holes resolution phase (#1460) Efficiency - Implementation of a memory sharing strategy reducing memory requirements by an average ratio of 3. rocq-9.2.0/doc/sphinx/index.html.rst000066400000000000000000000013551516144147600173650ustar00rootroot00000000000000========================== Introduction and Contents ========================== .. include:: introduction.rst Contents -------- .. toctree:: self .. toctree:: :caption: Specification language language/core/index language/extensions/index .. toctree:: :caption: Proofs proofs/writing-proofs/proof-mode proofs/writing-proofs/index proof-engine/ssreflect-proof-language proofs/automatic-tactics/index proofs/creating-tactics/index .. toctree:: :caption: Using the Rocq Prover using/libraries/index using/tools/index .. toctree:: :caption: Appendix appendix/history-and-changes/index appendix/indexes/index zebibliography .. No entries yet * :index:`thmindex` .. include:: license.rst rocq-9.2.0/doc/sphinx/index.latex.rst000066400000000000000000000014111516144147600175270ustar00rootroot00000000000000================================== The Rocq Prover Reference Manual ================================== ------------ Introduction ------------ .. include:: introduction.rst .. include:: license.rst ---------------------- Specification language ---------------------- .. toctree:: language/core/index language/extensions/index ------ Proofs ------ .. toctree:: proofs/writing-proofs/proof-mode proofs/writing-proofs/index proof-engine/ssreflect-proof-language proofs/automatic-tactics/index proofs/creating-tactics/index --------------------- Using the Rocq Prover --------------------- .. toctree:: using/libraries/index using/tools/index -------- Appendix -------- .. toctree:: appendix/history-and-changes/index zebibliography rocq-9.2.0/doc/sphinx/introduction.rst000066400000000000000000000072211516144147600200320ustar00rootroot00000000000000This is the reference manual of the Rocq Prover. Rocq is a proof assistant or interactive theorem prover. It lets you formalize mathematical concepts and then helps you interactively generate machine-checked proofs of theorems. Machine checking gives users much more confidence that the proofs are correct compared to human-generated and -checked proofs. Rocq has been used in a number of flagship verification projects, including the `CompCert verified C compiler `_, and has served to verify the proof of the `four color theorem `_ (among many other mathematical formalizations). Users generate proofs by entering a series of tactics that constitute steps in the proof. There are many built-in tactics, some of which are elementary, while others implement complex decision procedures (such as :tacn:`lia`, a decision procedure for linear integer arithmetic). :ref:`Ltac ` and its planned replacement, :ref:`Ltac2 `, provide languages to define new tactics by combining existing tactics with looping and conditional constructs. These permit automation of large parts of proofs and sometimes entire proofs. Furthermore, users can add novel tactics or functionality by creating Rocq plugins using OCaml. The Rocq kernel, a small part of the Rocq Prover, does the final verification that the tactic-generated proof is valid. Usually the tactic-generated proof is indeed correct, but delegating proof verification to the kernel means that even if a tactic is buggy, it won't be able to introduce an incorrect proof into the system. Finally, Rocq also supports extraction of verified programs to programming languages such as OCaml and Haskell. This provides a way of executing Rocq code efficiently and can be used to create verified software libraries. To learn Rocq, beginners are advised to first start with a tutorial / book. Several such tutorials / books are listed at https://rocq-prover.org/docs. This manual is organized in three main parts, plus an appendix: - **The first part presents the specification language of the Rocq Prover**, that allows to define programs and state mathematical theorems. :ref:`core-language` presents the language that the kernel of Rocq understands. :ref:`extensions` presents the richer language, with notations, implicits, etc. that a user can use and which is translated down to the language of the kernel by means of an "elaboration process". - **The second part presents proof mode**, the central feature of the Rocq Prover. :ref:`proofhandling` introduces this interactive mode, then :ref:`tactics` introduces the standard Rocq tactics and :ref:`thessreflectprooflanguage` presents the alternative SSReflect tactics. :ref:`automatic-tactics` presents some more advanced tactics, while :ref:`writing-tactics` is about the languages that allow a user to combine tactics together and develop new ones. - **The third part shows how to use the Rocq Prover in practice.** :ref:`libraries` presents some of the essential reusable blocks from the ecosystem and some particularly important extensions such as the program extraction mechanism. :ref:`tools` documents important tools that a user needs to build a Rocq project. - In the appendix, :ref:`history-and-changes` presents the history of Rocq and changes in recent releases. This is an important reference if you upgrade the version of Rocq that you use. The various :ref:`indexes ` are very useful to **quickly browse the manual and find what you are looking for.** They are often the main entry point to the manual. .. only:: html The full table of contents is presented below: rocq-9.2.0/doc/sphinx/language/000077500000000000000000000000001516144147600163405ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/language/cic.rst000066400000000000000000000411401516144147600176300ustar00rootroot00000000000000Typing rules ==================================== The underlying formal language of the Rocq Prover is a :gdef:`Calculus of Inductive Constructions` (|Cic|) whose inference rules are presented in this chapter. The history of this formalism as well as pointers to related work are provided in a separate chapter; see :ref:`history`. .. _The-terms: The terms ------------- The expressions of the |Cic| are *terms* and all terms have a *type*. There are types for functions (or programs), there are atomic types (especially datatypes)... but also types for proofs and types for the types themselves. Especially, any object handled in the formalism must belong to a type. For instance, universal quantification is relative to a type and takes the form β€œ*for all x of type* :math:`T`, :math:`P`”. The expression β€œ:math:`x` *of type* :math:`T`” is written β€œ:math:`x:T`”. Informally, β€œ:math:`x:T`” can be thought as β€œ:math:`x` *belongs to* :math:`T`”. Terms are built from sorts, variables, constants, abstractions, applications, local definitions, and products. From a syntactic point of view, types cannot be distinguished from terms, except that they cannot start by an abstraction or a constructor. More precisely the language of the *Calculus of Inductive Constructions* is built from the following rules. #. the sorts :math:`\SProp`, :math:`\Prop`, :math:`\Set`, :math:`\Type(i)` are terms. #. 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 Rocq 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 a *dependent product*. If :math:`x` does not occur in :math:`U` then :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` in Rocq concrete syntax) is a term. This is a notation for the Ξ»-abstraction of Ξ»-calculus :cite:`Bar81`. The term :math:`Ξ» x:T .~u` is a function which maps elements of :math:`T` to the expression :math:`u`. #. if :math:`t` and :math:`u` are terms then :math:`(t~u)` is a term (:g:`t u` in Rocq concrete syntax). The term :math:`(t~u)` reads as β€œ:math:`t` applied to :math:`u`”. #. if :math:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are terms then :math:`\letin{x}{t:T}{u}` is 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. .. _Free-variables: **Free variables.** The notion of free variables is defined as usual. In the expressions :math:`Ξ»x:T.~U` and :math:`βˆ€ x:T,~U` the occurrences of :math:`x` in :math:`U` are bound. .. _Substitution: **Substitution.** The notion of substituting a term :math:`t` to free occurrences of a variable :math:`x` in a term :math:`u` is defined as usual. The resulting term is written :math:`\subst{u}{x}{t}`. .. _The-logical-vs-programming-readings: **The logical vs programming readings.** The constructions of the |Cic| can be used to express both logical and programming notions, according to the Curry-Howard correspondence between proofs and programs, and between propositions and types :cite:`Cur58,How80,Bru72`. For instance, let us assume that :math:`\nat` is the type of natural numbers with zero element written :math:`0` and that :g:`True` is the always true proposition. Then :math:`β†’` is used both to denote :math:`\natβ†’\nat` which is the type of functions from :math:`\nat` to :math:`\nat`, to denote Trueβ†’True which is an 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 :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 Rocq notation) but may build also predicates over the natural numbers. For instance :math:`Ξ» x:\nat.~(\kw{eqnat}~x~0)` (i.e. :g:`fun x:nat => eqnat x 0` in Rocq notation) will represent the predicate of one variable :math:`x` which asserts the equality of :math:`x` with :math:`0`. This predicate has type :math:`\nat β†’ \Prop` and it can be applied to any expression of type :math:`\nat`, say :math:`t`, to give an 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 with 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)`”. .. _Typing-rules: Typing rules ---------------- As objects of type theory, terms are subjected to *type discipline*. The well typing of a term depends on a local context and a global environment. .. _Local-context: **Local context.** A :term:`local context` is an ordered list of declarations of *variables*. The declaration of a variable :math:`x` is either an *assumption*, written :math:`x:T` (where :math:`T` is a type) or a *definition*, written :math:`x:=t:T`. Local contexts are written in brackets, for example :math:`[x:T;~y:=u:U;~z:V]`. The variables declared in a local context must be distinct. If :math:`Ξ“` is a local context that declares :math:`x`, we write :math:`x ∈ Ξ“`. Writing :math:`(x:T) ∈ Ξ“` means there is an assumption or a definition giving the type :math:`T` to :math:`x` in :math:`Ξ“`. If :math:`Ξ“` defines :math:`x:=t:T`, we also write :math:`(x:=t:T) ∈ Ξ“`. For the rest of the chapter, :math:`Ξ“::(y:T)` denotes the local context :math:`Ξ“` enriched with the local assumption :math:`y:T`. Similarly, :math:`Ξ“::(y:=t:T)` denotes the local context :math:`Ξ“` enriched with the :term:`local definition ` :math:`(y:=t:T)`. The notation :math:`[]` denotes the empty local context. Writing :math:`Ξ“_1 ; Ξ“_2` means concatenation of the local context :math:`Ξ“_1` and the local context :math:`Ξ“_2`. .. _Global-environment: **Global environment.** A :term:`global environment` is an ordered list of *declarations*. Global declarations are either *assumptions*, *definitions* or declarations of inductive objects. Inductive objects declare both constructors and inductive or coinductive types (see Section :ref:`inductive-definitions`). In the global environment, *assumptions* are written as :math:`(c:T)`, indicating that :math:`c` is of the type :math:`T`. *Definitions* are written as :math:`c:=t:T`, indicating that :math:`c` has the value :math:`t` and type :math:`T`. We shall call such names :term:`constants `. For the rest of the chapter, the :math:`E;~c:T` denotes the global environment :math:`E` enriched with the assumption :math:`c:T`. Similarly, :math:`E;~c:=t:T` denotes the global environment :math:`E` enriched with the definition :math:`(c:=t:T)`. The rules for inductive definitions (see Section :ref:`inductive-definitions`) have to be considered as assumption rules in which the following definitions apply: if the name :math:`c` is declared in :math:`E`, we write :math:`c ∈ E` and if :math:`c:T` or :math:`c:=t:T` is declared in :math:`E`, we write :math:`(c : T) ∈ E`. .. _Typing-rules2: **Typing rules.** In the following, we define simultaneously two judgments. The first one :math:`\WTEG{t}{T}` means the term :math:`t` is well-typed and has type :math:`T` in the global environment :math:`E` and local context :math:`Ξ“`. The second judgment :math:`\WFE{Ξ“}` means that the global environment :math:`E` is well-formed and the local context :math:`Ξ“` is a valid local context in this global environment. A term :math:`t` is well typed in a global environment :math:`E` iff there exists a local context :math:`\Gamma` and a term :math:`T` such that the judgment :math:`\WTEG{t}{T}` can be derived from the following rules. .. inference:: W-Empty --------- \WF{[]}{} .. inference:: W-Local-Assum \WTEG{T}{s} s \in \Sort x \not\in \Gamma % \cup E ------------------------- \WFE{\Gamma::(x:T)} .. inference:: W-Local-Def \WTEG{t}{T} x \not\in \Gamma % \cup E ------------------------- \WFE{\Gamma::(x:=t:T)} .. inference:: W-Global-Assum \WTE{}{T}{s} s \in \Sort c \notin E ------------ \WF{E;~c:T}{} .. inference:: W-Global-Def \WTE{}{t}{T} c \notin E --------------- \WF{E;~c:=t:T}{} .. inference:: Ax-SProp \WFE{\Gamma} ---------------------- \WTEG{\SProp}{\Type(1)} .. inference:: Ax-Prop \WFE{\Gamma} ---------------------- \WTEG{\Prop}{\Type(1)} .. inference:: Ax-Set \WFE{\Gamma} --------------------- \WTEG{\Set}{\Type(1)} .. inference:: Ax-Type \WFE{\Gamma} --------------------------- \WTEG{\Type(i)}{\Type(i+1)} .. inference:: Var \WFE{\Gamma} (x:T) \in \Gamma~~\mbox{or}~~(x:=t:T) \in \Gamma~\mbox{for some $t$} -------------------------------------------------------------------- \WTEG{x}{T} .. inference:: Const \WFE{\Gamma} (c:T) \in E~~\mbox{or}~~(c:=t:T) \in E~\mbox{for some $t$} ---------------------------------------------------------- \WTEG{c}{T} .. inference:: Prod-SProp \WTEG{T}{s} s \in {\Sort} \WTE{\Gamma::(x:T)}{U}{\SProp} ----------------------------- \WTEG{\forall~x:T,U}{\SProp} .. inference:: Prod-Prop \WTEG{T}{s} s \in \Sort \WTE{\Gamma::(x:T)}{U}{\Prop} ----------------------------- \WTEG{βˆ€ x:T,~U}{\Prop} .. inference:: Prod-Set \WTEG{T}{s} s \in \{\SProp, \Prop, \Set\} \WTE{\Gamma::(x:T)}{U}{\Set} ---------------------------- \WTEG{βˆ€ x:T,~U}{\Set} .. inference:: Prod-Type \WTEG{T}{s} s \in \{\SProp, \Type(i)\} \WTE{\Gamma::(x:T)}{U}{\Type(i)} -------------------------------- \WTEG{βˆ€ x:T,~U}{\Type(i)} .. inference:: Lam \WTEG{βˆ€ x:T,~U}{s} \WTE{\Gamma::(x:T)}{t}{U} ------------------------------------ \WTEG{Ξ» x:T\mto t}{βˆ€ x:T,~U} .. _app_rule: .. inference:: App \WTEG{t}{βˆ€ x:U,~T} \WTEG{u}{U} ------------------------------ \WTEG{(t\ u)}{\subst{T}{x}{u}} .. inference:: Let \WTEG{t}{T} \WTE{\Gamma::(x:=t:T)}{u}{U} ----------------------------------------- \WTEG{\letin{x}{t:T}{u}}{\subst{U}{x}{t}} .. note:: **Prod-Prop** and **Prod-Set** typing-rules make sense if we consider the semantic difference between :math:`\Prop` and :math:`\Set`: + All values of a type that has a sort :math:`\Set` are extractable. + No values of a type that has a sort :math:`\Prop` are extractable. .. 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:`t`). This is because the value :math:`t` associated with :math:`x` may be used in a conversion rule (see Section :ref:`Conversion-rules`). For example :g:`let A := True in (fun a : A => 42) I` is well-typed and reduces to :g:`42`, while :g:`(fun A => (fun a : A => 42) I) True` is ill-typed. .. _subtyping-rules: 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 :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: #. if :math:`E[Ξ“] ⊒ t =_{βδι΢η} u` then :math:`E[Ξ“] ⊒ t ≀_{βδι΢η} u`, #. if :math:`i ≀ j` then :math:`E[Ξ“] ⊒ \Type(i) ≀_{βδι΢η} \Type(j)`, #. for any :math:`i`, :math:`E[Ξ“] ⊒ \Set ≀_{βδι΢η} \Type(i)`, #. :math:`E[Ξ“] ⊒ \Prop ≀_{βδι΢η} \Set`, hence, by transitivity, :math:`E[Ξ“] ⊒ \Prop ≀_{βδι΢η} \Type(i)`, for any :math:`i` (note: :math:`\SProp` is not related by cumulativity to any other term) #. if :math:`E[Ξ“] ⊒ T =_{βδι΢η} U` and :math:`E[Ξ“::(x:T)] ⊒ T' ≀_{βδι΢η} U'` then :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)}, S)βˆˆΞ“_I` and :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_{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_{k,1}' … v_{k,m}' ] respectively then .. math:: E[Ξ“] ⊒ t~w_1 … w_m ≀_{βδι΢η} t'~w_1' … w_m' (notice that :math:`t` and :math:`t'` are both fully applied, i.e., they have a sort as a type) if .. math:: E[Ξ“] ⊒ w_i =_{βδι΢η} w_i' for :math:`1 ≀ i ≀ m` and we have .. math:: E[Ξ“] ⊒ T_{i,j} ≀_{βδι΢η} T_{i,j}' and .. 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']`. The conversion rule up to subtyping is now exactly: .. inference:: Conv E[Ξ“] ⊒ U : s E[Ξ“] ⊒ t : T E[Ξ“] ⊒ T ≀_{βδι΢η} U -------------- E[Ξ“] ⊒ t : U .. _Normal-form: **Normal form**. A term which cannot be any more reduced is said to be in *normal 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 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: .. 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 ) 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 ) 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` can be reducible. Similar notions of head-normal forms involving Ξ΄, ΞΉ and ΞΆ reductions or any combination of those can also be defined. .. _The-Calculus-of-Inductive-Construction-with-impredicative-Set: The Calculus of Inductive Constructions with impredicative Set ----------------------------------------------------------------- The Rocq Prover can be used as a type checker for the Calculus of Inductive Constructions with an impredicative sort :math:`\Set` by using the compiler option ``-impredicative-set``. For example, using the ordinary `rocq repl` command, the following is rejected, .. example:: .. rocqtop:: all Fail Definition id: Set := forall X:Set,X->X. while it will type check, if one uses instead the ``-impredicative-set`` command-line flag. The major change in the theory concerns the rule for product formation 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 --------------------- 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 inductive definitions* like the example of second-order existential quantifier (:g:`exSet`). There should be restrictions on the eliminations which can be performed on such definitions. The elimination rules in the impredicative system for sort :math:`\Set` become: .. inference:: Set1 s ∈ \{\Prop, \Set\} ----------------- [I:\Set|Iβ†’ s] .. inference:: Set2 I~\kw{is a small inductive definition} s ∈ \{\Type(i)\} ---------------- [I:\Set|Iβ†’ s] rocq-9.2.0/doc/sphinx/language/coq-library.rst000066400000000000000000000521551516144147600213260ustar00rootroot00000000000000.. _thecoqlibrary: The Coq libraries ================= .. index:: single: Theories The :gdef:`core library` contains definitions and theorems for the most commonly used elementary logical notions and data types, as well as :ref:`primitive objects `, support for tactics such as :tacn:`setoid_rewrite` or commands such as :ref:`Program `, the proof language :ref:`ssreflect `, the tactic language :ref:`Ltac2 ` and some compatibilty helpers for previous versions of Rocq. The content of the corelib can be browsed at ``_. Rocq automatically loads many of these files when it starts. This set of preloaded files is called the :gdef:`prelude`. Its content can be browsed at ``_. Other libraries like the :gdef:`standard library` are general-purpose libraries with definitions and theorems for sets, lists, sorting, arithmetic, etc. To use these files, users must load them explicitly with the ``From Stdlib Require`` command (see :ref:`compiled-files`). The content of the standard library can be browsed at ``_. There are many other libraries provided by the Rocq users' community. Many such libraries and developments are packaged in Nix or Opam. The Rocq Opam repository can be browsed at ``_ (see :ref:`userscontributions`). This chapter briefly reviews the prelude. The prelude ----------- This section lists the basic notions and results which are directly available in the standard Coq system. Most of these constructions are defined in the ``Prelude`` module in directory ``theories/Init`` in the Coq root directory; this includes the modules ``Notations``, ``Logic``, ``Datatypes``, ``Specif``, ``Peano``, ``Wf`` and ``Tactics``. .. _init-notations: Notations ~~~~~~~~~ This module defines the parsing and pretty-printing of many symbols (infixes, prefixes, etc.). However, it does not assign a meaning to these notations. The purpose of this is to define and fix once for all the precedence and associativity of very common notations. The main notations fixed in the initial state are : ================ ============ =============== Notation Precedence Associativity ================ ============ =============== ``_ -> _`` 99 right ``_ <-> _`` 95 no ``_ \/ _`` 85 right ``_ /\ _`` 80 right ``~ _`` 75 right ``_ = _`` 70 no ``_ = _ = _`` 70 no ``_ = _ :> _`` 70 no ``_ <> _`` 70 no ``_ <> _ :> _`` 70 no ``_ < _`` 70 no ``_ > _`` 70 no ``_ <= _`` 70 no ``_ >= _`` 70 no ``_ < _ < _`` 70 no ``_ < _ <= _`` 70 no ``_ <= _ < _`` 70 no ``_ <= _ <= _`` 70 no ``_ + _`` 50 left ``_ || _`` 50 left ``_ - _`` 50 left ``_ * _`` 40 left ``_ && _`` 40 left ``_ / _`` 40 left ``- _`` 35 right ``/ _`` 35 right ``_ ^ _`` 30 right ================ ============ =============== .. _coq-library-logic: Logic ~~~~~ `Logic.v` in the basic library of Coq has the definitions of standard (intuitionistic) logical connectives defined as inductive constructions. They are equipped with an appealing syntax enriching the subclass :token:`form` of the syntactic class :token:`term`. The constructs for :production:`form` are: ============================================== ======= True True False False :n:`~ @form` not :n:`@form /\ @form` and :n:`@form \/ @form` or :n:`@form -> @form` primitive implication :n:`@form <-> @form` iff :n:`forall @ident : @type, @form` primitive for all :n:`exists @ident {? @specif}, @form` ex :n:`exists2 @ident {? @specif}, @form & @form` ex2 :n:`@term = @term` eq :n:`@term = @term :> @specif` eq ============================================== ======= .. note:: Implication is not defined but primitive (it is a non-dependent product of a proposition over another proposition). There is also a primitive universal quantification (it is a dependent product over a proposition). The primitive universal quantification allows both first-order and higher-order quantification. Propositional Connectives +++++++++++++++++++++++++ .. index:: single: Connectives single: True (term) single: I (term) single: False (term) single: not (term) single: and (term) single: conj (term) single: proj1 (term) single: proj2 (term) single: or (term) single: or_introl (term) single: or_intror (term) single: iff (term) First, we find propositional calculus connectives. At times, it's helpful to know exactly what these notations represent. .. rocqdoc:: Inductive True : Prop := I. Inductive False : Prop := . Definition not (A: Prop) := A -> False. Inductive and (A B:Prop) : Prop := conj (_:A) (_:B). Section Projections. Variables A B : Prop. Theorem proj1 : A /\ B -> A. Theorem proj2 : A /\ B -> B. End Projections. Inductive or (A B:Prop) : Prop := | or_introl (_:A) | or_intror (_:B). Definition iff (P Q:Prop) := (P -> Q) /\ (Q -> P). We also have the `Type` level negation: .. index:: single: notT (term) .. rocqtop:: in Definition notT (A:Type) := A -> False. Quantifiers +++++++++++ .. index:: single: Quantifiers single: all (term) single: ex (term) single: exists (term) single: ex_intro (term) single: ex2 (term) single: exists2 (term) single: ex_intro2 (term) Then we find first-order quantifiers: .. rocqtop:: in Definition all (A:Set) (P:A -> Prop) := forall x:A, P x. Inductive ex (A: Set) (P:A -> Prop) : Prop := ex_intro (x:A) (_:P x). Inductive ex2 (A:Set) (P Q:A -> Prop) : Prop := ex_intro2 (x:A) (_:P x) (_:Q x). The following abbreviations are allowed: ====================== ======================================= ``exists x:A, P`` ``ex A (fun x:A => P)`` ``exists x, P`` ``ex _ (fun x => P)`` ``exists2 x:A, P & Q`` ``ex2 A (fun x:A => P) (fun x:A => Q)`` ``exists2 x, P & Q`` ``ex2 _ (fun x => P) (fun x => Q)`` ====================== ======================================= The type annotation ``:A`` can be omitted when ``A`` can be synthesized by the system. .. _coq-equality: Equality ++++++++ .. index:: single: Equality single: eq (term) single: eq_refl (term) Then, we find equality, defined as an inductive relation. That is, given a type ``A`` and an ``x`` of type ``A``, the predicate :g:`(eq A x)` is the smallest one which contains ``x``. This definition, due to Christine Paulin-Mohring, is equivalent to define ``eq`` as the smallest reflexive relation, and it is also equivalent to Leibniz' equality. .. rocqtop:: in Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. Lemmas ++++++ Finally, a few easy lemmas are provided. .. index:: single: absurd (term) single: eq_sym (term) single: eq_trans (term) single: f_equal (term) single: sym_not_eq (term) single: eq_ind_r (term) single: eq_rec_r (term) single: eq_rect (term) single: eq_rect_r (term) .. rocqdoc:: Theorem absurd : forall A C:Prop, A -> ~ A -> C. Section equality. Variables A B : Type. Variable f : A -> B. Variables x y z : A. Theorem eq_sym : x = y -> y = x. Theorem eq_trans : x = y -> y = z -> x = z. Theorem f_equal : x = y -> f x = f y. Theorem not_eq_sym : x <> y -> y <> x. End equality. Definition eq_ind_r : forall (A:Type) (x:A) (P:A->Prop), P x -> forall y:A, y = x -> P y. Definition eq_rec_r : forall (A:Type) (x:A) (P:A->Set), P x -> forall y:A, y = x -> P y. Definition eq_rect_r : forall (A:Type) (x:A) (P:A->Type), P x -> forall y:A, y = x -> P y. Hint Immediate eq_sym not_eq_sym : core. .. index:: single: f_equal2 ... f_equal5 (term) The theorem ``f_equal`` is extended to functions with two to five arguments. The theorem are names ``f_equal2``, ``f_equal3``, ``f_equal4`` and ``f_equal5``. For instance ``f_equal3`` is defined the following way. .. rocqtop:: in abort Theorem f_equal3 : forall (A1 A2 A3 B:Type) (f:A1 -> A2 -> A3 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3), x1 = y1 -> x2 = y2 -> x3 = y3 -> f x1 x2 x3 = f y1 y2 y3. .. _datatypes: Datatypes ~~~~~~~~~ .. index:: single: Datatypes In the basic library, we find in ``Datatypes.v`` the definition of the basic data-types of programming, defined as inductive constructions over the sort ``Set``. Some of them come with a special syntax shown below (this syntax table is common with the next section :ref:`specification`). The constructs for :production:`specif` are: ============================================= ======= :n:`@specif * @specif` prod :n:`@specif + @specif` sum :n:`@specif + { @specif }` sumor :n:`{ @specif } + { @specif }` sumbool :n:`{ @ident : @specif | @form }` sig :n:`{ @ident : @specif | @form & @form }` sig2 :n:`{ @ident : @specif & @specif }` sigT :n:`{ @ident : @specif & @specif & @specif }` sigT2 ============================================= ======= The notation for pairs (elements of type prod) is: :n:`(@term, @term)` Programming +++++++++++ .. index:: single: Programming single: unit (term) single: tt (term) single: bool (term) single: true (term) single: false (term) single: nat (term) single: O (term) single: S (term) single: option (term) single: Some (term) single: None (term) single: identity (term) single: refl_identity (term) .. rocqtop:: in Inductive unit : Set := tt. Inductive bool : Set := true | false. Inductive nat : Set := O | S (n:nat). Inductive option (A:Set) : Set := Some (_:A) | None. Note that zero is the letter ``O``, and *not* the numeral ``0``. We then define the disjoint sum of ``A+B`` of two sets ``A`` and ``B``, and their product ``A*B``. .. index:: single: sum (term) single: A+B (term) single: + (term) single: inl (term) single: inr (term) single: prod (term) single: A*B (term) single: * (term) single: pair (term) single: fst (term) single: snd (term) .. rocqtop:: in Inductive sum (A B:Set) : Set := inl (_:A) | inr (_:B). Inductive prod (A B:Set) : Set := pair (_:A) (_:B). Section projections. Variables A B : Set. Definition fst (H: prod A B) := match H with | pair _ _ x y => x end. Definition snd (H: prod A B) := match H with | pair _ _ x y => y end. End projections. Some operations on ``bool`` are also provided: ``andb`` (with infix notation ``&&``), ``orb`` (with infix notation ``||``), ``xorb``, ``implb`` and ``negb``. .. _specification: Specification ~~~~~~~~~~~~~ The following notions defined in module ``Specif.v`` allow to build new data-types and specifications. They are available with the syntax shown in the previous section :ref:`datatypes`. For instance, given :g:`A:Type` and :g:`P:A->Prop`, the construct :g:`{x:A | P x}` (in abstract syntax :g:`(sig A P)`) is a ``Type``. We may build elements of this set as :g:`(exist x p)` whenever we have a witness :g:`x:A` with its justification :g:`p:P x`. From such a :g:`(exist x p)` we may in turn extract its witness :g:`x:A` (using an elimination construct such as ``match``) but *not* its justification, which stays hidden, like in an abstract data-type. In technical terms, one says that ``sig`` is a *weak (dependent) sum*. A variant ``sig2`` with two predicates is also provided. .. index:: single: {x:A | P x} (term) single: sig (term) single: exist (term) single: sig2 (term) single: exist2 (term) .. rocqtop:: in Inductive sig (A:Set) (P:A -> Prop) : Set := exist (x:A) (_:P x). Inductive sig2 (A:Set) (P Q:A -> Prop) : Set := exist2 (x:A) (_:P x) (_:Q x). A *strong (dependent) sum* :g:`{x:A & P x}` may be also defined, when the predicate ``P`` is now defined as a constructor of types in ``Type``. .. index:: single: {x:A & P x} (term) single: sigT (term) single: existT (term) single: sigT2 (term) single: existT2 (term) single: projT1 (term) single: projT2 (term) .. rocqtop:: in Inductive sigT (A:Type) (P:A -> Type) : Type := existT (x:A) (_:P x). Section Projections2. Variable A : Type. Variable P : A -> Type. Definition projT1 (H:sigT A P) := let (x, h) := H in x. Definition projT2 (H:sigT A P) := match H return P (projT1 H) with existT _ _ x h => h end. End Projections2. Inductive sigT2 (A: Type) (P Q:A -> Type) : Type := existT2 (x:A) (_:P x) (_:Q x). A related non-dependent construct is the constructive sum :g:`{A}+{B}` of two propositions ``A`` and ``B``. .. index:: single: sumbool (term) single: left (term) single: right (term) single: {A}+{B} (term) .. rocqtop:: in Inductive sumbool (A B:Prop) : Set := left (_:A) | right (_:B). This ``sumbool`` construct may be used as a kind of indexed boolean data-type. An intermediate between ``sumbool`` and ``sum`` is the mixed ``sumor`` which combines :g:`A:Set` and :g:`B:Prop` in the construction :g:`A+{B}` in ``Set``. .. index:: single: sumor (term) single: inleft (term) single: inright (term) single: A+{B} (term) .. rocqtop:: in Inductive sumor (A:Set) (B:Prop) : Set := | inleft (_:A) | inright (_:B). We may define variants of the axiom of choice, like in Martin-LΓΆf's Intuitionistic Type Theory. .. index:: single: Choice (term) single: Choice2 (term) single: bool_choice (term) .. rocqdoc:: Lemma Choice : forall (S S':Set) (R:S -> S' -> Prop), (forall x:S, {y : S' | R x y}) -> {f : S -> S' | forall z:S, R z (f z)}. Lemma Choice2 : forall (S S':Set) (R:S -> S' -> Set), (forall x:S, {y : S' & R x y}) -> {f : S -> S' & forall z:S, R z (f z)}. Lemma bool_choice : forall (S:Set) (R1 R2:S -> Prop), (forall x:S, {R1 x} + {R2 x}) -> {f : S -> bool | forall x:S, f x = true /\ R1 x \/ f x = false /\ R2 x}. The next construct builds a sum between a data-type :g:`A:Type` and an exceptional value encoding errors: .. index:: single: Exc (term) single: value (term) single: error (term) .. rocqtop:: in Definition Exc := option. Definition value := Some. Definition error := None. This module ends with theorems, relating the sorts ``Set`` or ``Type`` and ``Prop`` in a way which is consistent with the realizability interpretation. .. index:: single: False_rect (term) single: False_rec (term) single: eq_rect (term) single: absurd_set (term) single: and_rect (term) .. rocqdoc:: Definition except := False_rec. Theorem absurd_set : forall (A:Prop) (C:Set), A -> ~ A -> C. Theorem and_rect2 : forall (A B:Prop) (P:Type), (A -> B -> P) -> A /\ B -> P. Basic Arithmetic ~~~~~~~~~~~~~~~~ The basic library includes a few elementary properties of natural numbers, together with the definitions of predecessor, addition and multiplication, in module ``Peano.v``. It also provides a scope ``nat_scope`` gathering standard notations for common operations (``+``, ``*``) and a decimal notation for numbers, allowing, for instance, writing ``3`` for :g:`S (S (S O))`. This also works on the left hand side of a ``match`` expression (see for example section :tacn:`refine`). This scope is opened by default. .. example:: The following example is not part of the standard library, but it shows the usage of the notations: .. rocqtop:: in reset Fixpoint even (n:nat) : bool := match n with | 0 => true | 1 => false | S (S n) => even n end. .. index:: single: eq_S (term) single: pred (term) single: pred_Sn (term) single: eq_add_S (term) single: not_eq_S (term) single: IsSucc (term) single: O_S (term) single: n_Sn (term) single: plus (term) single: plus_n_O (term) single: plus_n_Sm (term) single: mult (term) single: mult_n_O (term) single: mult_n_Sm (term) Now comes the content of module ``Peano``: .. rocqdoc:: Theorem eq_S : forall x y:nat, x = y -> S x = S y. Definition pred (n:nat) : nat := match n with | 0 => 0 | S u => u end. Theorem pred_Sn : forall m:nat, m = pred (S m). Theorem eq_add_S : forall n m:nat, S n = S m -> n = m. Hint Immediate eq_add_S : core. Theorem not_eq_S : forall n m:nat, n <> m -> S n <> S m. Definition IsSucc (n:nat) : Prop := match n with | 0 => False | S p => True end. Theorem O_S : forall n:nat, 0 <> S n. Theorem n_Sn : forall n:nat, n <> S n. Fixpoint plus (n m:nat) {struct n} : nat := match n with | 0 => m | S p => S (p + m) end where "n + m" := (plus n m) : nat_scope. Lemma plus_n_O : forall n:nat, n = n + 0. Lemma plus_n_Sm : forall n m:nat, S (n + m) = n + S m. Fixpoint mult (n m:nat) {struct n} : nat := match n with | 0 => 0 | S p => m + p * m end where "n * m" := (mult n m) : nat_scope. Lemma mult_n_O : forall n:nat, 0 = n * 0. Lemma mult_n_Sm : forall n m:nat, n * m + n = n * (S m). Finally, it gives the definition of the usual orderings ``le``, ``lt``, ``ge`` and ``gt``. .. index:: single: le (term) single: le_n (term) single: le_S (term) single: lt (term) single: ge (term) single: gt (term) .. This emits a notation already used warning but it won't be shown to the user. .. rocqtop:: in warn Inductive le (n:nat) : nat -> Prop := | le_n : le n n | le_S : forall m:nat, n <= m -> n <= (S m) where "n <= m" := (le n m) : nat_scope. Definition lt (n m:nat) := S n <= m. Definition ge (n m:nat) := m <= n. Definition gt (n m:nat) := m < n. Properties of these relations are not initially known, but may be required by the user from modules ``Le`` and ``Lt``. Finally, ``Peano`` gives some lemmas allowing pattern matching, and a double induction principle. .. index:: single: nat_case (term) single: nat_double_ind (term) .. rocqdoc:: Theorem nat_case : forall (n:nat) (P:nat -> Prop), P 0 -> (forall m:nat, P (S m)) -> P n. Theorem nat_double_ind : forall R:nat -> nat -> Prop, (forall n:nat, R 0 n) -> (forall n:nat, R (S n) 0) -> (forall n m:nat, R n m -> R (S n) (S m)) -> forall n m:nat, R n m. Well-founded recursion ~~~~~~~~~~~~~~~~~~~~~~ The basic library contains the basics of well-founded recursion and well-founded induction, in module ``Wf.v``. .. index:: single: Well foundedness single: Recursion single: Well founded induction single: Acc (term) single: Acc_inv (term) single: Acc_rect (term) single: well_founded (term) .. rocqdoc:: Section Well_founded. Variable A : Type. Variable R : A -> A -> Prop. Inductive Acc (x:A) : Prop := Acc_intro : (forall y:A, R y x -> Acc y) -> Acc x. Lemma Acc_inv x : Acc x -> forall y:A, R y x -> Acc y. Definition well_founded := forall a:A, Acc a. Hypothesis Rwf : well_founded. Theorem well_founded_induction : forall P:A -> Set, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. Theorem well_founded_ind : forall P:A -> Prop, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. The automatically generated scheme ``Acc_rect`` can be used to define functions by fixpoints using well-founded relations to justify termination. Assuming extensionality of the functional used for the recursive call, the fixpoint equation can be proved. .. index:: single: Fix_F (term) single: Fix_eq (term) single: Fix_F_inv (term) single: Fix_F_eq (term) .. rocqdoc:: Section FixPoint. Variable P : A -> Type. Variable F : forall x:A, (forall y:A, R y x -> P y) -> P x. Fixpoint Fix_F (x:A) (r:Acc x) {struct r} : P x := F x (fun (y:A) (p:R y x) => Fix_F y (Acc_inv x r y p)). Definition Fix (x:A) := Fix_F x (Rwf x). Hypothesis F_ext : forall (x:A) (f g:forall y:A, R y x -> P y), (forall (y:A) (p:R y x), f y p = g y p) -> F x f = F x g. Lemma Fix_F_eq : forall (x:A) (r:Acc x), F x (fun (y:A) (p:R y x) => Fix_F y (Acc_inv x r y p)) = Fix_F x r. Lemma Fix_F_inv : forall (x:A) (r s:Acc x), Fix_F x r = Fix_F x s. Lemma Fix_eq : forall x:A, Fix x = F x (fun (y:A) (p:R y x) => Fix y). End FixPoint. End Well_founded. Tactics ~~~~~~~ A few tactics defined at the user level are provided in the initial state, in module ``Tactics`` of ``Corelib`` (`documentation `_). .. _userscontributions: Opam repository --------------- Numerous users' contributions have been packaged and are available at URL https://rocq-prover.org/packages/. On this web page, you can browse all contributions with informations (author, institution, quick description, etc.) and the possibility to download their sources or install them with their dependencies through the Opam package manager. You will also find informations on how to submit a new package. rocq-9.2.0/doc/sphinx/language/core/000077500000000000000000000000001516144147600172705ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/language/core/assumptions.rst000066400000000000000000000224421516144147600224130ustar00rootroot00000000000000Functions and assumptions ========================= .. _binders: Binders ------- .. insertprodn open_binders binder .. prodn:: open_binders ::= {+ @name } : @type | {+ @binder } name ::= _ | @ident binder ::= @name | ( {+ @name } : @type ) | ( @name {? : @type } := @term ) | @implicit_binders | @generalizing_binder | ( @name : @type %| @term ) | ' @pattern0 Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` *bind* variables. A binding is represented by an identifier. If the binding variable is not used in the expression, the identifier can be replaced by the symbol :g:`_`. When the type of a bound variable cannot be synthesized by the system, it can be specified with the notation :n:`(@identΒ :Β @type)`. There is also a notation for a sequence of binding variables sharing the same type: :n:`({+ @ident}Β :Β @type)`. A binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. Some constructions allow the binding of a variable to value. This is called a β€œlet-binder”. The entry :n:`@binder` of the grammar accepts either an assumption binder as defined above or a let-binder. The notation in the latter case is :n:`(@identΒ :=Β @term)`. In a let-binder, only one variable can be introduced at the same time. It is also possible to give the type of the variable as follows: :n:`(@identΒ :Β @typeΒ :=Β @term)`. `(x : T | P)` is syntactic sugar for `(x : @Stdlib.Init.Specif.sig _ (fun x : T => P))`, which would more typically be written `(x : {x : T | P})`. Since `(x : T | P)` uses `sig` directly, changing the notation `{x : T | P}` will not change the meaning of `(x : T | P)`. Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, it is intended that at least one binder of the list is an assumption otherwise fun and forall gets identical. Moreover, parentheses can be omitted in the case of a single sequence of bindings sharing the same type (e.g.: :g:`funΒ (xΒ yΒ zΒ :Β A)Β =>Β t` can be shortened in :g:`funΒ xΒ yΒ zΒ :Β AΒ =>Β t`). .. index:: fun .. index:: forall Functions (fun) and function types (forall) ------------------------------------------- .. insertprodn term_forall_or_fun term_forall_or_fun .. prodn:: term_forall_or_fun ::= forall @open_binders , @type | fun @open_binders => @term The expression :n:`fun @ident : @type => @term` defines the *abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term :n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity function on type :g:`A`). The keyword :g:`fun` can be followed by several binders as given in SectionΒ :ref:`binders`. Functions over several variables are equivalent to an iteration of one-variable functions. For instance the expression :n:`fun {+ @ident__i } : @type => @term` denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If a let-binder occurs in the list of binders, it is expanded to a let-in definition (see SectionΒ :ref:`let-in`). The expression :n:`forallΒ @identΒ :Β @type__1,Β @type__2` denotes the :gdef:`product type ` (or *product*) of the variable :n:`@ident` of type :n:`@type__1` over the type :n:`@type__2`. If :n:`@ident` is used in :n:`@type__2`, then we say the expression is a :gdef:`dependent product`, and otherwise a :gdef:`non-dependent product`. The intention behind a dependent product :g:`forallΒ xΒ :Β A,Β B` is twofold. It denotes either the universal quantification of the variable :g:`x` of type :g:`A` in the proposition :g:`B` or the functional dependent product from :g:`A` to :g:`B` (a construction usually written :math:`\Pi_{x:A}.B` in set theory). Non-dependent product types have a special notation: :g:`A -> B` stands for :g:`forall _ : A,Β B`. *Non-dependent product* is used to denote both propositional implication and function types. These terms are also useful: * `n : nat` is a :gdef:`dependent premise` of `forall n:nat, n + 0 = n` because `n` appears both in the binder of the `forall` and in the quantified statement `n + 0 = n`. Note that if `n` isn't used in the statement, Rocq considers it a non-dependent premise. Similarly, :n:`let n := ... in @term` is a dependent premise only if `n` is used in :n:`@term`. * `A` and `B` are :gdef:`non-dependent premises ` (or, often, just ":gdef:`premises `") of `A -> B -> C` because they don't appear in a `forall` binder. `C` is the *conclusion* of the type, which is a second meaning for the term :term:`conclusion`. (As noted, `A -> B` is notation for the term `forall _ : A, B`; the wildcard `_` can't be referred to in the quantified statement.) As for abstractions, :g:`forall` is followed by a binder list, and products over several variables are equivalent to an iteration of one-variable products. .. _function_application: Function application -------------------- .. insertprodn term_application arg .. prodn:: term_application ::= @term10 {+ @arg } | @ @qualid_annotated {+ @term1 } arg ::= ( @ident := @term ) | ( @natural := @term ) | @term1 :n:`@term1__fun @term1` denotes applying the function :n:`@term1__fun` to :token:`term1`. .. todo: What is the relevant definition of a function here? See https://github.com/rocq-prover/rocq/pull/16659#discussion_r1039540851 :n:`@term1__fun {+ @term1__i }` denotes applying :n:`@term1__fun` to the arguments :n:`@term1__i`. It is equivalent to :n:`( … ( @term1__fun @term1__1 ) … ) @term1__n`: associativity is to the left. The :n:`@ @qualid_annotated {+ @term1 }` form requires specifying all arguments, including implicit ones. Otherwise, implicit arguments need not be given. See :ref:`ImplicitArguments`. The notations :n:`(@identΒ :=Β @term)` and :n:`(@natural := @term)` for arguments are used for making explicit the value of implicit arguments. See :ref:`explicit-applications`. .. _gallina-assumptions: Assumptions ----------- Assumptions extend the global environment with axioms, parameters, hypotheses or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted by Rocq only if :n:`@type` is a correct type in the global environment before the declaration and if :n:`@ident` was not previously defined in the same module. This :n:`@type` is considered to be the type (or specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` has type :n:`@type`. .. _Axiom: .. cmd:: @assumption_token {? Inline {? ( @natural ) } } {| @assumpt | {+ ( @assumpt ) } } :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables .. insertprodn assumption_token of_type .. prodn:: assumption_token ::= {| Axiom | Axioms } | {| Conjecture | Conjectures } | {| Parameter | Parameters } | {| Hypothesis | Hypotheses } | {| Variable | Variables } assumpt ::= {+ @ident_decl } @of_type ident_decl ::= @ident {? @univ_decl } of_type ::= {| : | :> } @type These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in the global environment. The fact asserted by :n:`@type` (or, equivalently, the existence of an object of this type) is accepted as a postulate. They accept the :attr:`program`, :attr:`deprecated` and :attr:`warn` attributes. :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms are equivalent. They can take the :attr:`local` :term:`attribute`, which makes the declared :n:`@ident` accessible only through their fully qualified names, even if :cmd:`Import` or its variants has been used on the current module. Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. They should only be used inside :ref:`section-mechanism`. The :n:`@ident`\s defined are only accessible within the section. When the current section is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. :n:`:>` If specified, :token:`ident_decl` is automatically declared as a coercion to the class of its type. See :ref:`coercions`. The :n:`Inline` clause is only relevant inside module types used for functor arguments. See :cmd:`Module`. .. example:: Simple assumptions .. rocqtop:: reset in Parameter X Y : Set. Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). Axiom R_S_inv : forall x y, R x y <-> S y x. .. exn:: @ident already exists. :name: β€˜ident’ already exists. (Axiom) :undocumented: .. warn:: Use of "Variable" or "Hypothesis" outside sections behaves as "#[local] Parameter" or "#[local] Axiom". Warning generated when using :cmd:`Variable` or its equivalent instead of :n:`Local Parameter` or its equivalent. This message is an error by default, it may be convenient to disable it while debuging. .. note:: We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases (corresponding to the declaration of an abstract object of the given type). rocq-9.2.0/doc/sphinx/language/core/basic.rst000066400000000000000000000613151516144147600211110ustar00rootroot00000000000000============================= Basic notions and conventions ============================= This section provides some essential notions and conventions for reading the manual. We start by explaining the syntax and lexical conventions used in the manual. Then, we present the essential vocabulary necessary to read the rest of the manual. Other terms are defined throughout the manual. The reader may refer to the :ref:`glossary index ` for a complete list of defined terms. Finally, we describe the various types of settings that Rocq provides. Syntax and lexical conventions ------------------------------ .. _syntax-conventions: Syntax conventions ~~~~~~~~~~~~~~~~~~ The syntax described in this documentation is equivalent to that accepted by the Rocq parser, but the grammar has been edited to improve readability and presentation. In the grammar presented in this manual, the terminal symbols are black (e.g. :n:`forall`), whereas the nonterminals are orange, italic and hyperlinked (e.g. :n:`@term`). Some syntax is represented graphically using the following kinds of blocks: :n:`{? item }` An optional item. :n:`{+ item }` A list of one or more items. :n:`{* item }` An optional list of items. :n:`{+s item}` A list of one or more items separated by "s" (e.g. :n:`item__1 s item__2 s item__3`). :n:`{*s item}` An optional list of items separated by "s". :n:`{| item__1 | item__2 | ... }` Alternatives (either :n:`item__1` or :n:`item__2` or ...). `Precedence levels `_ that are implemented in the Rocq parser are shown in the documentation by appending the level to the nonterminal name (as in :n:`@term100` or :n:`@ltac_expr3`). .. note:: Rocq uses an extensible parser. Plugins and the :ref:`notation system ` can extend the syntax at run time. Some notations are defined in the :term:`prelude`, which is loaded by default. The documented grammar doesn't include these notations. Precedence levels not used by the base grammar are omitted from the documentation, even though they could still be populated by notations or plugins. Furthermore, some parsing rules are only activated in certain contexts (:ref:`proof mode `, :ref:`custom entries `...). .. warning:: Given the complexity of these parsing rules, it would be extremely difficult to create an external program that can properly parse a Rocq document. Therefore, tool writers are advised to delegate parsing to Rocq, by communicating with it, for instance through `coq-lsp `_. .. seealso:: :cmd:`Print Grammar` .. _lexical-conventions: Lexical conventions ~~~~~~~~~~~~~~~~~~~ Blanks Space, newline and horizontal tab are considered blanks. Blanks are ignored but they separate tokens. Comments Comments are enclosed between ``(*`` and ``*)``. They can be nested. They can contain any character. However, embedded :n:`@string` literals must be correctly closed. Comments are treated as blanks. Identifiers Identifiers, written :n:`@ident`, are sequences of letters, digits, ``_`` and ``'``, that do not start with a digit or ``'``. That is, they are recognized by the following grammar (except that the string ``_`` is reserved; it is not a valid identifier): .. insertprodn ident subsequent_letter .. prodn:: ident ::= @first_letter {* @subsequent_letter } first_letter ::= {| a .. z | A .. Z | _ | @unicode_letter } subsequent_letter ::= {| @first_letter | @digit | ' | @unicode_id_part } All characters are meaningful. In particular, identifiers are case-sensitive. :production:`unicode_letter` non-exhaustively includes Latin, Greek, Gothic, Cyrillic, Arabic, Hebrew, Georgian, Hangul, Hiragana and Katakana characters, CJK ideographs, mathematical letter-like symbols and non-breaking space. :production:`unicode_id_part` non-exhaustively includes symbols for prime letters and subscripts. Numbers Numbers are sequences of digits with an optional fractional part and exponent, optionally preceded by a minus sign. Hexadecimal numbers start with ``0x`` or ``0X``. :n:`@integer`\s are signed numbers without fraction or exponent parts. :n:`@natural`\s are non-negative integers. Underscores embedded in the digits are ignored, for example ``1_000_000`` is the same as ``1000000``. .. insertprodn number hexdigit .. prodn:: number ::= {? - } @decnat {? . {+ {| @digit | _ } } } {? {| e | E } {? {| + | - } } @decnat } | {? - } @hexnat {? . {+ {| @hexdigit | _ } } } {? {| p | P } {? {| + | - } } @decnat } integer ::= @bigint bigint ::= {? - } @bignat natural ::= @bignat bignat ::= {| @decnat | @hexnat } decnat ::= @digit {* {| @digit | _ } } digit ::= 0 .. 9 hexnat ::= {| 0x | 0X } @hexdigit {* {| @hexdigit | _ } } hexdigit ::= {| 0 .. 9 | a .. f | A .. F } :n:`number`, :n:`@bigint` and :n:`@bignat`, which are used in :token:`term`\s, generally have no range limitation. :n:`@integer` and :n:`@natural`, which are used as arguments in tactics and commands, are limited to the range that fits into an OCaml integer (63-bit integers on most architectures). The :ref:`standard library ` provides a few :ref:`interpretations ` for :n:`@number`. Some of these interpretations support exponential notation for decimal numbers, for example ``5.02e-6`` means 5.02Γ—10\ :sup:`-6`; and base 2 exponential notation for hexadecimal numbers denoted by ``p`` or ``P``, for example ``0xAp12`` means 10Γ—2\ :sup:`12`. The :cmd:`Number Notation` mechanism lets the user define custom parsers and printers for :n:`@number`. By default, numbers are interpreted as :n:`nat`\s, which is a unary representation. For example, :n:`3` is represented as `S (S (S O))`. While this is a convenient representation for doing proofs, computing with large :n:`nat`\s can lead to stack overflows or running out of memory. You can explicitly specify a different interpretation to avoid this problem. For example, the Stdlib library enables to write :n:`1000000%Z` for a more efficient binary representation of that number as an integer. See :ref:`Scopes` and :n:`@term_scope` for the ``%`` notation. .. example:: Stack overflow with :n:`nat` .. rocqtop:: all reset Fail Eval compute in 100000 + 100000. (* gives a stack overflow (not shown) *) .. rocqtop:: in extra-stdlib From Stdlib Require Import ZArith. (* for definition of Z *) .. rocqtop:: all extra-stdlib Eval compute in (1000000000000000000000000000000000 + 1)%Z. Strings Strings begin and end with ``"`` (double quote). Use ``""`` to represent a double quote character within a string. In the grammar, strings are identified with :production:`string`. The :cmd:`String Notation` mechanism offers the user a way to define custom parsers and printers for :token:`string`. .. _keywords: Keywords The following character sequences are keywords defined in the main Rocq grammar that cannot be used as identifiers (even when starting Rocq with the `-noinit` command-line flag):: _ Axiom CoFixpoint Definition Fixpoint Hypothesis Parameter Prop SProp Set Theorem Type Variable as at cofix else end fix for forall fun if in let match return then where with The following are keywords defined in notations or plugins loaded in the :term:`prelude`:: by exists exists2 using Note that loading additional modules or plugins may expand the set of reserved keywords. :cmd:`Print Keywords` can be used to print the current keywords and tokens. Other tokens The following character sequences are tokens defined in the main Rocq grammar (even when starting Rocq with the `-noinit` command-line flag):: ! # #[ % %_ & ' ( () ) * + , - -> . .( .. / : :: ::> := :> ; < <+ <- <: <<: <= = => > >-> ? @ @{ [ ] _ `( `[ `{ { {| | |- } The following character sequences are tokens defined in notations or plugins loaded in the :term:`prelude`:: && ** ++ ... .1 .2 ::= <-> <> >= /\ \/ || ^ ~ Note that loading additional modules or plugins may expand the set of defined tokens. .. _lexing-unseparated-keywords: When multiple tokens match the beginning of a sequence of characters, the longest matching token not cutting a subsequence of contiguous letters in the middle is used. Occasionally you may need to insert spaces to separate tokens. For example, if ``~`` and ``~~`` are both defined as tokens, the inputs ``~ ~`` and ``~~`` generate different tokens, whereas if ``~~`` is not defined, then the two inputs are equivalent. Also, if ``~`` and ``~_h`` are both defined as tokens, the input ``~_ho`` is interpreted as ``~ _ho`` rather than ``~_h o`` so as not to cut the identifier-like subsequence ``ho``. Contrastingly, if only ``~_h`` is defined as a token, then ``~_ho`` is an error because no token can be found that includes the whole subsequence ``ho`` without cutting it in the middle. Finally, if all of ``~``, ``~_h`` and ``~_ho`` are defined as tokens, the input ``~_ho`` is interpreted using the longest match rule, i.e. as the token ``~_ho``. Essential vocabulary -------------------- This section presents the most essential notions to understand the rest of the Rocq Prover manual: :term:`terms ` and :term:`types ` on the one hand, :term:`commands ` and :term:`tactics ` on the other hand. .. glossary:: term Terms are the basic expressions of Rocq. Terms can represent mathematical expressions, propositions and proofs, but also executable programs and program types. Here is the top-level syntax of terms. Each of the listed constructs is presented in a dedicated section. Some of these constructs (like :n:`@term_forall_or_fun`) are part of the core language that the kernel of Rocq understands and are therefore described in :ref:`this chapter `, while others (like :n:`@term_if`) are language extensions that are presented in :ref:`the next chapter `. .. insertprodn term qualid_annotated .. prodn:: term ::= @term100 term100 ::= @term_cast | @term99 term99 ::= @term10 term10 ::= @term_application | @term_forall_or_fun | @term_let | @term_fix | @term_cofix | @term_if | @one_term one_term ::= @term_explicit | @term1 term1 ::= @term_projection | @term_scope | @term0 term0 ::= @qualid_annotated | @sort | @number_or_string | @term_evar | @term_match | @term_record | @term_generalizing | [| {*; @term } %| @term {? : @type } |] {? @univ_annot } | @term_ltac | ( @term ) qualid_annotated ::= @qualid {? @univ_annot } .. note:: Many :term:`commands ` and :term:`tactics ` use :n:`@one_term` (in the syntax of their arguments) rather than :n:`@term`. The former need to be enclosed in parentheses unless they're very simple, such as a single identifier. This avoids confusing a space-separated list of terms or identifiers with a :n:`@term_application`. type To be valid and accepted by the Rocq kernel, a term needs an associated type. We express this relationship by β€œ:math:`x` *of type* :math:`T`”, which we write as β€œ:math:`x:T`”. Informally, β€œ:math:`x:T`” can be thought as β€œ:math:`x` *belongs to* :math:`T`”. The Rocq kernel is a type checker: it verifies that a term has the expected type by applying a set of typing rules (see :ref:`Typing-rules`). If that's indeed the case, we say that the term is :gdef:`well-typed`. A special feature of the Rocq language is that types can depend on terms (we say that the language is `dependently-typed `_). Because of this, types and terms share a common syntax. All types are :term:`terms `, but not all terms are types. The syntactic aliases :n:`@type` and :n:`@one_type` are used to make clear when the provided :term:`term` must semantically be a type: .. insertprodn type one_type .. prodn:: type ::= @term one_type ::= @one_term Intuitively, types may be viewed as sets containing terms. We say that a type is :gdef:`inhabited` if it contains at least one term (i.e. if we can find a term which is associated with this type). We call such terms :gdef:`inhabitants `. Note that deciding whether a type is inhabited is `undecidable `_. Formally, types can be used to construct logical foundations for mathematics alternative to the standard `"set theory" `_: we call such logical foundations `"type theories" `_. The Rocq Prover is based on the Calculus of Inductive Constructions, which is a particular instance of type theory. sentence Rocq documents are made of a series of sentences that contain :term:`commands ` or :term:`tactics `, generally terminated with a period and optionally decorated with :term:`attributes `. .. insertprodn document sentence .. prodn:: document ::= {* @sentence } sentence ::= {? @attributes } @command . | {? @attributes } {? @natural : } @query_command . | {? @attributes } {? @toplevel_selector : } @ltac_expr {| . | ... } | @control_command :n:`@ltac_expr` syntax supports both simple and compound :term:`tactics `. For example: ``split`` is a simple tactic while ``split; auto`` combines two simple tactics. For more information, see :ref:`compil-steps`. command A :production:`command` can be used to modify the state of a Rocq document, for instance by declaring a new object, or to get information about the current state. By convention, command names begin with uppercase letters. Commands appear in the HTML documentation in blue or gray boxes after the label "Command". In the pdf, they appear after the boldface label "Command:". Commands are listed in the :ref:`command_index`. Example: .. cmd:: Comments {* {| @one_term | @string | @natural } } Prints "Comments ok" and does not change the state of the document. tactic A :production:`tactic` specifies how to transform the current proof state as a step in creating a proof. They are syntactically valid only when Rocq is in :term:`proof mode`, such as after a :cmd:`Theorem` command and before any subsequent proof-terminating command such as :cmd:`Qed`. See :ref:`proofhandling` for more on proof mode. By convention, tactic names begin with lowercase letters. Tactic appear in the HTML documentation in blue or gray boxes after the label "Tactic". In the pdf, they appear after the boldface label "Tactic:". Tactics are listed in the :ref:`tactic_index`. Settings -------- There are several mechanisms for changing the behavior of Rocq. The :term:`attribute` mechanism is used to modify the default behavior of a :term:`sentence` or to attach information to Rocq objects. The :term:`flag`, :term:`option` and :term:`table` mechanisms are used to modify the behavior of Rocq more globally in a document or project. .. _attributes: Attributes ~~~~~~~~~~ An :gdef:`attribute` is used to modify the default behavior of a sentence or to attach information to a Rocq object. Syntactically, most commands and tactics can be decorated with attributes (cf. :n:`@sentence`), but attributes not supported by the command or tactic will trigger :warn:`This command does not support this attribute`. There is also a command :cmd:`Attributes` to assign attributes to a whole document. .. insertprodn attributes legacy_attr .. prodn:: attributes ::= {* #[ {*, @attribute } ] } {* @legacy_attr } attribute ::= @ident {? @attr_value } attr_value ::= = @string | = @qualid | ( {+, @attribute } ) legacy_attr ::= {| Local | Global } | {| Polymorphic | Monomorphic } | {| Cumulative | NonCumulative } | Private | Program The order of top-level attributes doesn't affect their meaning. ``#[foo,bar]``, ``#[bar,foo]``, ``#[foo]#[bar]`` and ``#[bar]#[foo]`` are equivalent. :gdef:`Boolean attributes ` take the form :n:`@ident__attr{? = {| yes | no } }`. When the :n:`{| yes | no }` value is omitted, the default is :n:`yes`. The legacy attributes (:n:`@legacy_attr`) provide an older, alternate syntax for certain attributes. They are equivalent to new attributes as follows: ============================= ================================ Legacy attribute New attribute ============================= ================================ `Local` :attr:`local` `Global` :attr:`global` `Polymorphic`, `Monomorphic` :attr:`universes(polymorphic)` `Cumulative`, `NonCumulative` :attr:`universes(cumulative)` `Private` :attr:`private(matching)` `Program` :attr:`program` ============================= ================================ Attributes appear in the HTML documentation in blue or gray boxes after the label "Attribute". In the pdf, they appear after the boldface label "Attribute:". Attributes are listed in the :ref:`attribute_index`. .. warn:: This command does not support this attribute: @ident. :name: This command does not support this attribute This warning is configured to behave as an error by default. You may turn it into a normal warning by using the :opt:`Warnings` option: .. rocqtop:: none Set Silent. .. rocqtop:: all warn Set Warnings "unsupported-attributes". #[ foo ] Comments. Generic attributes ^^^^^^^^^^^^^^^^^^ The following attribute is supported by every command: .. attr:: warnings = @string :name: warnings Sets the given warning string locally for the command. After the command finishes the warning state is reset to what it was before the command. For instance if the current warning state is `some-warnings,-other-warning`, .. rocqdoc:: #[warnings="+other-warning"] Command. is equivalent to .. rocqdoc:: Set Warnings "+other-warning". Command. Set Warnings "some-warnings,-other-warning". and `other-warning` is an error while executing the command. Consequently, using this attribute around an :cmd:`Import` command will prevent it from changing the warning state. See also :opt:`Warnings` for the concrete syntax to use inside the quoted string. .. attr:: warning = @string :name: warning Alias of :attr:`warnings`. Document-level attributes ^^^^^^^^^^^^^^^^^^^^^^^^^ .. cmd:: Attributes {+, @attribute } :name: Attributes Associates attributes with the document. When compiled with ``rocq compile`` (see Section :ref:`therocqcommands`), the attributes are associated with the compiled file and may have an effect when the file is loaded with :cmd:`Require`. Supported attributes include :attr:`deprecated` and :attr:`warn`. .. _flags-options-tables: Flags, Options and Tables ~~~~~~~~~~~~~~~~~~~~~~~~~ The following types of settings can be used to change the behavior of Rocq in subsequent commands and tactics (see :ref:`set_unset_scope_qualifiers` for a more precise description of the scope of these settings): * A :gdef:`flag` has a boolean value, such as :flag:`Universe Polymorphism`. * An :gdef:`option` generally has a numeric or string value, such as :opt:`Firstorder Depth`. * A :gdef:`table` contains a set of :token:`string`\s or :token:`qualid`\s. * In addition, some commands provide settings, such as :cmd:`Extraction Language`. .. FIXME Convert "Extraction Language" to an option. .. insertprodn setting_name setting_name .. prodn:: setting_name ::= {+ @ident } .. Flags, options and tables are identified by a series of identifiers. By convention, each of the identifiers start with an initial capital letter. Flags, options and tables appear in the HTML documentation in blue or gray boxes after the labels "Flag", "Option" and "Table". In the pdf, they appear after a boldface label. They are listed in the :ref:`options_index`. .. cmd:: Set @setting_name {? {| @integer | @string } } If :n:`@setting_name` is a flag, no value may be provided; the flag is set to on. If :n:`@setting_name` is an option, a value of the appropriate type must be provided; the option is set to the specified value. This command supports the :attr:`local`, :attr:`global` and :attr:`export` attributes. They are described :ref:`here `. .. warn:: There is no flag or option with this name: "@setting_name". This warning message can be raised by :cmd:`Set` and :cmd:`Unset` when :n:`@setting_name` is unknown. It is a warning rather than an error because this helps library authors produce Rocq code that is compatible with several Rocq versions. To preserve the same behavior, they may need to set some compatibility flags or options that did not exist in previous Rocq versions. .. cmd:: Unset @setting_name If :n:`@setting_name` is a flag, it is set to off. If :n:`@setting_name` is an option, it is set to its default value. This command supports the :attr:`local`, :attr:`global` and :attr:`export` attributes. They are described :ref:`here `. .. cmd:: Add @setting_name {+ {| @qualid | @string } } Adds the specified values to the table :n:`@setting_name`. This command supports the :attr:`local`, :attr:`global` and :attr:`export` attributes. The default is `export` outside sections and `local` inside sections. Depending on the table some values may only allow `local`, typically section variables cannot be added with `export` or `global`. .. cmd:: Remove @setting_name {+ {| @qualid | @string } } Removes the specified value from the table :n:`@setting_name`. This command supports the same attributes as :cmd:`Add`. .. cmd:: Test @setting_name {? for {+ {| @qualid | @string } } } If :n:`@setting_name` is a flag or option, prints its current value. If :n:`@setting_name` is a table: if the `for` clause is specified, reports whether the table contains each specified value, otherwise this is equivalent to :cmd:`Print Table`. The `for` clause is not valid for flags and options. .. exn:: There is no flag, option or table with this name: "@setting_name". This error message is raised when calling the :cmd:`Test` command (without the `for` clause), or the :cmd:`Print Table` command, for an unknown :n:`@setting_name`. .. exn:: There is no qualid-valued table with this name: "@setting_name". There is no string-valued table with this name: "@setting_name". These error messages are raised when calling the :cmd:`Add` or :cmd:`Remove` commands, or the :cmd:`Test` command with the `for` clause, if :n:`@setting_name` is unknown or does not have the right type. .. cmd:: Print Options Prints the current value of all flags and options, and the names of all tables. .. cmd:: Print Table @setting_name Prints the values in the table :n:`@setting_name`. .. cmd:: Print Tables A synonym for :cmd:`Print Options`. .. _set_unset_scope_qualifiers: Locality attributes supported by :cmd:`Set` and :cmd:`Unset` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :cmd:`Set` and :cmd:`Unset` commands support the mutually exclusive :attr:`local`, :attr:`export` and :attr:`global` locality attributes. * If no attribute is specified, the original value of the flag or option is restored at the end of the current module but it is *not* restored at the end of the current section. * The :attr:`local` attribute makes the setting local to the current :cmd:`Section` (if applicable) or :cmd:`Module`. * The :attr:`export` attribute makes the setting local to the current :cmd:`Module`, unless :cmd:`Import` (or one of its variants) is used on the :cmd:`Module`. * The :attr:`global` attribute makes the setting persist outside the current :cmd:`Module` in the current file, or whenever :cmd:`Require` is used on the current file. .. note:: We discourage using the :attr:`global` locality attribute with the :cmd:`Set` and :cmd:`Unset` commands. If your goal is to define project-wide settings, you should rather use the command-line arguments ``-set`` and ``-unset`` for setting flags and options (see :ref:`command-line-options`). rocq-9.2.0/doc/sphinx/language/core/coinductive.rst000066400000000000000000000173541516144147600223500ustar00rootroot00000000000000Coinductive types and corecursive functions ============================================= .. _coinductive-types: Coinductive types ------------------ The objects of an inductive type are well-founded with respect to the constructors of the type. In other words, such objects contain only a *finite* number of constructors. Coinductive types arise from relaxing this condition, and admitting types whose objects contain an infinity of constructors. Infinite objects are introduced by a non-ending (but effective) process of construction, defined in terms of the constructors of the type. More information on coinductive definitions can be found in :cite:`Gimenez95b,Gim98,GimCas05`. .. cmd:: CoInductive @inductive_definition {* with @inductive_definition } CoInductive @record_definition {* with @record_definition } This command introduces a coinductive type. The syntax of the command is the same as the command :cmd:`Inductive`. No principle of induction is derived from the definition of a coinductive type, since such principles only make sense for inductive types. For coinductive types, the only elimination principle is case analysis. This command supports the :attr:`universes(polymorphic)`, :attr:`universes(template)`, :attr:`universes(cumulative)`, :attr:`private(matching)`, :attr:`bypass_check(universes)`, :attr:`bypass_check(positivity)` and :attr:`using` attributes. When record syntax is used, this command also supports the :attr:`projections(primitive)` :term:`attribute`. .. example:: The type of infinite sequences of natural numbers, usually called streams, is an example of a coinductive type. .. rocqtop:: in CoInductive Stream : Set := Seq : nat -> Stream -> Stream. The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` can be defined as follows: .. rocqtop:: in Definition hd (x:Stream) := let (a,s) := x in a. Definition tl (x:Stream) := let (a,s) := x in s. Definitions of coinductive predicates and blocks of mutually coinductive definitions are also allowed. .. example:: The extensional equality on streams is an example of a coinductive type: .. rocqtop:: in CoInductive EqSt : Stream -> Stream -> Prop := eqst : forall s1 s2:Stream, hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` we have to construct an infinite proof of equality, that is, an infinite object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite objects in Section :ref:`cofixpoint`. Caveat ~~~~~~ The ability to define coinductive types by constructors, hereafter called *positive coinductive types*, is known to break subject reduction. The story is a bit long: this is due to dependent pattern-matching which implies propositional Ξ·-equality, which itself would require full Ξ·-conversion for subject reduction to hold, but full Ξ·-conversion is not acceptable as it would make type checking undecidable. Since the introduction of primitive records in Coq 8.5, an alternative presentation is available, called *negative coinductive types*. This consists in defining a coinductive type as a primitive record type through its projections. Such a technique is akin to the *copattern* style that can be found in e.g. Agda, and preserves subject reduction. The above example can be rewritten in the following way. .. rocqtop:: none Reset Stream. .. rocqtop:: all Set Primitive Projections. CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. CoInductive EqSt (s1 s2: Stream) : Prop := eqst { eqst_hd : hd s1 = hd s2; eqst_tl : EqSt (tl s1) (tl s2); }. Some properties that hold over positive streams are lost when going to the negative presentation, typically when they imply equality over streams. For instance, propositional Ξ·-equality is lost when going to the negative presentation. It is nonetheless logically consistent to recover it through an axiom. .. rocqtop:: all Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). More generally, as in the case of positive coinductive types, it is consistent to further identify extensional equality of coinductive types with propositional equality: .. rocqtop:: all Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. As of Coq 8.9, it is now advised to use negative coinductive types rather than their positive counterparts. .. seealso:: :ref:`primitive_projections` for more information about negative records and primitive projections. .. index:: single: cofix Co-recursive functions: cofix ----------------------------- .. insertprodn term_cofix cofix_body .. prodn:: term_cofix ::= let cofix @cofix_body in @term | cofix @cofix_body {? {+ with @cofix_body } for @ident } cofix_body ::= @ident {* @binder } {? : @type } := @term The expression ":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" denotes the :math:`i`-th component of a block of terms defined by a mutual guarded corecursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When :math:`n=1`, the ":n:`for @ident__i`" clause is omitted. .. _cofixpoint: Top-level definitions of corecursive functions ----------------------------------------------- .. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } .. insertprodn cofix_definition cofix_definition .. prodn:: cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } This command introduces a method for constructing an infinite object of a coinductive type. For example, the stream containing all natural numbers can be introduced by applying the following method to the number :g:`O` (see Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` and :g:`tl`): .. rocqtop:: all CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). Unlike recursive definitions, there is no decreasing argument in a corecursive definition. To be admissible, a method of construction must provide at least one extra constructor of the infinite object for each iteration. A syntactical guard condition is imposed on corecursive definitions in order to ensure this: each recursive call in the definition must be protected by at least one constructor, and only by constructors. That is the case in the former definition, where the single recursive call of :g:`from` is guarded by an application of :g:`Seq`. On the contrary, the following recursive function does not satisfy the guard condition: .. rocqtop:: all Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). The elimination of corecursive definition is done lazily, i.e. the definition is expanded only when it occurs at the head of an application which is the argument of a case analysis expression. In any other context, it is considered as a canonical expression which is completely evaluated. We can test this using the command :cmd:`Eval`, which computes the normal forms of a term: .. rocqtop:: all Eval compute in (from 0). Eval compute in (hd (from 0)). Eval compute in (tl (from 0)). As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously defining several mutual cofixpoints. If :n:`@term` is omitted, :n:`@type` is required and Rocq enters proof mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a :term:`constant` for which the computational behavior is relevant. See :ref:`proof-editing-mode`. rocq-9.2.0/doc/sphinx/language/core/conversion.rst000066400000000000000000000237471516144147600222240ustar00rootroot00000000000000.. _Conversion-rules: Conversion rules ---------------- The Rocq Prover has conversion rules that can be used to determine if two terms are equal by definition in |CiC|, or :term:`convertible`. Conversion rules consist of reduction rules and expansion rules. Equality is determined by converting both terms to a normal form, then verifying they are syntactically equal (ignoring differences in the names of bound variables by :term:`alpha-conversion `). .. seealso:: :ref:`applyingconversionrules`, which describes tactics that apply these conversion rules. :gdef:`Reductions ` convert terms to something that is incrementally closer to its normal form. For example, :term:`zeta-reduction` removes :n:`let @ident := @term__1 in @term__2` constructs from a term by replacing :n:`@ident` with :n:`@term__1` wherever :n:`@ident` appears in :n:`@term__2`. The resulting term may be longer or shorter than the original. .. rocqtop:: all Eval cbv zeta in let i := 1 in i + i. :gdef:`Expansions ` are reductions applied in the opposite direction, for example expanding `2 + 2` to `let i := 2 in i + i`. While applying reductions gives a unique result, the associated expansion may not be unique. For example, `2 + 2` could also be expanded to `let i := 2 in i + 2`. Reductions that have a unique inverse expansion are also referred to as :gdef:`contractions `. The normal form is defined as the result of applying a particular set of conversion rules (beta-, delta-, iota- and zeta-reduction and eta-expansion) repeatedly until it's no longer possible to apply any of them. Sometimes the result of a reduction tactic will be a simple value, for example reducing `2*3+4` with `cbv beta delta iota` to `10`, which requires applying several reduction rules repeatedly. In other cases, it may yield an expression containing variables, axioms or opaque contants that can't be reduced. The useful conversion rules are shown below. All of them except for eta-expansion can be applied with conversion tactics such as :tacn:`cbv`: .. list-table:: :header-rows: 1 * - Conversion name - Description * - beta-reduction - eliminates `fun` * - delta-reduction - replaces a defined variable or constant with its definition * - zeta-reduction - eliminates `let` * - eta-expansion - replaces a term `f` of type `forall a : A, B` with `fun x : A => f x` * - match-reduction - eliminates `match` * - fix-reduction - replaces a `fix` with a :term:`beta-redex`; recursive calls to the symbol are replaced with the `fix` term * - cofix-reduction - replaces a `cofix` with a :term:`beta-redex`; recursive calls to the symbol are replaced with the `cofix` term * - iota-reduction - match-, fix- and cofix-reduction together :ref:`applyingconversionrules` describes tactics that only apply conversion rules. (Other tactics may use conversion rules in addition to other changes to the proof state.) .. _alpha-conversion-sect: Ξ±-conversion ~~~~~~~~~~~~ Two terms are :gdef:`Ξ±-convertible ` if they are syntactically equal ignoring differences in the names of variables bound within the expression. For example `forall x, x + 0 = x` is Ξ±-convertible with `forall y, y + 0 = y`. (Internally, Rocq represents these two terms using de Bruijn indices, so explicit Ξ±-conversion is not necessary.) .. _beta-reduction-sect: Ξ²-reduction ~~~~~~~~~~~ :gdef:`Ξ²-reduction ` reduces a :gdef:`beta-redex`, which is a term in the form `(fun x => t) u`. (Beta-redex is short for "beta-reducible expression", a term from lambda calculus. See `Beta reduction `_ for more background.) Formally, in any :term:`global environment` :math:`E` and :term:`local context` :math:`Ξ“`, the beta-reduction rule is: .. inference:: Beta -------------- 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 *Ξ²-expansion* of :math:`\subst{t}{x}{u}`. .. todo: :term:`Calculus of Inductive Constructions` fails to build in CI for some reason :-() Terms of the *Calculus of Inductive Constructions* enjoy some fundamental properties such as confluence, strong normalization, subject reduction. These results are theoretically of great importance but we will not detail them here and refer the interested reader to :cite:`Coq85`. .. _delta-reduction-sect: Ξ΄-reduction ~~~~~~~~~~~ :gdef:`Ξ΄-reduction ` replaces variables defined in :term:`local contexts ` or :term:`constants ` defined in the :term:`global environment` with their values. :gdef:`Unfolding ` means to replace a constant by its definition. Formally, this is: .. inference:: Delta-Local \WFE{\Gamma} (x:=t:T) ∈ Ξ“ -------------- E[Ξ“] ⊒ x~\triangleright_Ξ΄~t .. inference:: Delta-Global \WFE{\Gamma} (c:=t:T) ∈ E -------------- E[Ξ“] ⊒ c~\triangleright_Ξ΄~t :term:`Delta-reduction ` unfolds constants when permitted by their :term:`opaqueness ` settings. .. _iota-reduction-sect: ΞΉ-reduction ~~~~~~~~~~~ A specific conversion rule is associated with the inductive objects in the global environment. We shall give later on (see Section :ref:`Well-formed-inductive-definitions`) the precise rules but it just says that a destructor applied to an object built from a constructor behaves as expected. This reduction is called :gdef:`ΞΉ-reduction ` and is more precisely studied in :cite:`Moh93,Wer94`. .. _zeta-reduction-sect: ΞΆ-reduction ~~~~~~~~~~~ :gdef:`ΞΆ-reduction ` removes :ref:`let-in definitions ` in terms by replacing the defined variable by its value. One way this reduction differs from Ξ΄-reduction is that the declaration is removed from the term entirely. Formally, this is: .. inference:: Zeta \WFE{\Gamma} \WTEG{u}{U} \WTE{\Gamma::(x:=u:U)}{t}{T} -------------- E[Ξ“] ⊒ \letin{x}{u:U}{t}~\triangleright_ΞΆ~\subst{t}{x}{u} .. _eta-expansion-sect: Ξ·-expansion ~~~~~~~~~~~ Another important concept is :gdef:`Ξ·-expansion `. It is legal to identify any term :math:`t` of functional type :math:`βˆ€ x:T,~U` with its so-called Ξ·-expansion .. math:: Ξ»x:T.~(t~x) for :math:`x` an arbitrary variable name fresh in :math:`t`. .. note:: We deliberately do not define Ξ·-reduction: .. math:: Ξ» x:T.~(t~x)~\not\triangleright_Ξ·~t This is because, in general, the type of :math:`t` need not be convertible 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) then .. math:: Ξ» x:\Type(1).~(f~x) ~:~ βˆ€ x:\Type(1),~\Type(1) We could not allow .. math:: Ξ» 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)`. Examples ~~~~~~~~ .. example:: Simple delta, fix, beta and match reductions ``+`` is a :ref:`notation ` for ``Nat.add``, which is defined with a :cmd:`Fixpoint`. .. rocqtop:: all abort Print Nat.add. Goal 1 + 1 = 2. cbv delta. cbv fix. cbv beta. cbv match. The term can be fully reduced with `cbv`: .. rocqtop:: all abort Goal 1 + 1 = 2. cbv. .. _proof-irrelevance: Proof Irrelevance ~~~~~~~~~~~~~~~~~ It is legal to identify any two terms whose common type is a strict proposition :math:`A : \SProp`. Terms in a strict propositions are therefore called *irrelevant*. .. _convertibility: Convertibility ~~~~~~~~~~~~~~ Let us write :math:`E[Ξ“] ⊒ t \triangleright u` for the contextual closure of the relation :math:`t` reduces to :math:`u` in the global environment :math:`E` and local context :math:`Ξ“` with one of the previous reductions Ξ², Ξ΄, ΞΉ or ΞΆ. We say that two terms :math:`t_1` and :math:`t_2` are *βδι΢η-convertible*, or simply :gdef:`convertible`, or :term:`definitionally equal `, in the 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 up to irrelevant subterms, or they are convertible up to Ξ·-expansion, 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 :math:`u_2'`. We then write :math:`E[Ξ“] ⊒ t_1 =_{βδι΢η} t_2`. Apart from this we consider two instances of polymorphic and cumulative (see Chapter :ref:`polymorphicuniverses`) inductive types (see below) convertible .. math:: E[Ξ“] ⊒ t~w_1 … w_m =_{βδι΢η} t~w_1' … w_m' if we have subtypings (see below) in both directions, i.e., .. math:: E[Ξ“] ⊒ t~w_1 … w_m ≀_{βδι΢η} t~w_1' … w_m' and .. math:: E[Ξ“] ⊒ t~w_1' … w_m' ≀_{βδι΢η} t~w_1 … w_m. Furthermore, we consider .. math:: E[Ξ“] ⊒ c~v_1 … v_m =_{βδι΢η} c'~v_1' … v_m' convertible if .. math:: E[Ξ“] ⊒ v_i =_{βδι΢η} v_i' and we have that :math:`c` and :math:`c'` are the same constructors of different instances of the same inductive types (differing only in universe levels) such that .. math:: E[Ξ“] ⊒ c~v_1 … v_m : t~w_1 … w_m and .. math:: E[Ξ“] ⊒ c'~v_1' … v_m' : t~ w_1' … w_m ' and we have .. math:: E[Ξ“] ⊒ t~w_1 … w_m =_{βδι΢η} t~w_1' … w_m'. The convertibility relation allows introducing a new typing rule which says that two convertible well-formed types have the same inhabitants. rocq-9.2.0/doc/sphinx/language/core/definitions.rst000066400000000000000000000225161516144147600223430ustar00rootroot00000000000000Definitions =========== .. index:: let ... := ... (term) .. _let-in: Let-in definitions ------------------ .. insertprodn term_let term_let .. prodn:: term_let ::= let @name {? : @type } := @term in @term | let @name {+ @binder } {? : @type } := @term in @term | @destructuring_let :n:`let @ident := @term__1 in @term__2` represents the local binding of the variable :n:`@ident` to the value :n:`@term__1` in :n:`@term__2`. :n:`let @ident {+ @binder} := @term__1 in @term__2` is an abbreviation for :n:`let @ident := fun {+ @binder} => @term__1 in @term__2`. .. seealso:: Extensions of the `let ... in ...` syntax are described in :ref:`irrefutable-patterns`. .. index:: single: ... : ... (type cast) single: ... <: ... (VM type cast) single: ... <<: ... (native compute type cast) single: ... :> ... (volatile type cast) .. _type-cast: Type cast --------- .. insertprodn term_cast term_cast .. prodn:: term_cast ::= @term99 <: @type | @term99 <<: @type | @term99 :> @type | @term99 : @type The expression :n:`@term99Β :Β @type` is a type cast expression. It enforces the type of :n:`@term99` to be :n:`@type`. :n:`@term99Β <:Β @type` specifies that the virtual machine will be used to type check that :n:`@term99` has type :n:`@type` (see :tacn:`vm_compute`). :n:`@term99Β <<:Β @type` specifies that compilation to OCaml will be used to type check that :n:`@term99` has type :n:`@type` (see :tacn:`native_compute`). :n:`@term99Β :>Β @type` enforces the type of :n:`@term99` to be :n:`@type` without leaving a trace in the produced value. This is a :gdef:`volatile cast`. If a scope is :ref:`bound ` to :n:`@type` then :n:`@term99` is interpreted in that scope. .. _gallina-definitions: Top-level definitions --------------------- Definitions extend the global environment by associating names to terms. A definition can be seen as a way to give a meaning to a name or as a way to abbreviate a term. In any case, the name can later be replaced at any time by its definition. The operation of unfolding a name into its definition is called :term:`delta-reduction`. A definition is accepted by the system if and only if the defined term is well-typed in the current context of the definition and if the name is not already used. The name defined by the definition is called a :gdef:`constant` and the term it refers to is its :gdef:`body`. A definition has a type, which is the type of its :term:`body`. A formal presentation of constants and environments is given in Section :ref:`typing-rules`. .. cmd:: {| Definition | Example } @ident_decl @def_body :name: Definition; Example .. insertprodn def_body reduce .. prodn:: def_body ::= {* @binder } {? : @type } := {? @reduce } @term | {* @binder } : @type reduce ::= Eval @red_expr in These commands bind :n:`@term` to the name :n:`@ident` in the global environment, provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, which makes the defined :n:`@ident` accessible only through their fully qualified names, even if :cmd:`Import` or its variants has been used on the current :cmd:`Module`. If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified computation on :n:`@term`. These commands also support the :attr:`universes(polymorphic)`, :attr:`refine`, :attr:`program` (see :ref:`program_definition`), :attr:`canonical`, :attr:`bypass_check(universes)`, :attr:`bypass_check(guard)`, :attr:`deprecated`, :attr:`warn` and :attr:`using` attributes. If :n:`@term` is omitted, :n:`@type` is required and Rocq enters proof mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a :term:`constant` for which the computational behavior is relevant. See :ref:`proof-editing-mode`. The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type :n:`@type`, and bound to value :n:`@term`. The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to :n:`Definition @identΒ :Β forall {* @binder }, @typeΒ :=Β fun {* @binder }Β =>Β @term`. With attribute :attr:`refine`, the user can leave out parts of the definition (writing `_` instead) and Rocq enters proof mode to fill in the holes. :attr:`refine` is not compatible with :n:`@reduce`. .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. .. exn:: @ident already exists. :name: β€˜ident’ already exists. (Definition) :undocumented: .. exn:: The term @term has type @type while it is expected to have type @type'. :undocumented: .. _Assertions: Assertions and proofs --------------------- An assertion states a proposition (or a type) for which the proof (or an inhabitant of the type) is interactively built using :term:`tactics `. Assertions cause Rocq to enter :term:`proof mode` (see :ref:`proofhandling`). Common tactics are described in the :ref:`tactics` chapter. The basic assertion command is: .. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property .. insertprodn thm_token thm_token .. prodn:: thm_token ::= Theorem | Lemma | Fact | Remark | Corollary | Proposition | Property After the statement is asserted, Rocq needs a proof. Once a proof of :n:`@type` under the assumptions represented by :n:`@binder`\s is given and validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and the theorem is bound to the name :n:`@ident` in the global environment. These commands accept the :attr:`program` attribute. See :ref:`program_lemma`. Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction over a mutually inductive assumption, or that assert mutually dependent statements in some mutual coinductive type. It is equivalent to :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of the statements (or the :term:`body` of the specification, depending on the point of view). The inductive or coinductive types on which the induction or coinduction has to be done is assumed to be unambiguous and is guessed by the system. Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that recursive proof arguments are correct is done only at the time of registering the lemma in the global environment. To know if the use of induction hypotheses is correct at some time of the interactive development of a proof, use the command :cmd:`Guarded`. This command accepts the :attr:`bypass_check(universes)`, :attr:`bypass_check(guard)`, :attr:`deprecated`, :attr:`warn`, and :attr:`using` attributes. .. exn:: The term @term has type @type which should be Set, Prop or Type. :undocumented: .. exn:: @ident already exists. :name: β€˜ident’ already exists. (Theorem) The name you provided is already defined. You have then to choose another name. .. exn:: Nested proofs are discouraged and not allowed by default. This error probably means that you forgot to close the last "Proof." with "Qed." or "Defined.". \ If you really intended to use nested proofs, you can do so by turning the "Nested Proofs Allowed" flag on. :name: Nested proofs are discouraged and not allowed by default You are asserting a new statement when you're already in proof mode. This feature, called nested proofs, is disabled by default. To activate it, turn the :flag:`Nested Proofs Allowed` flag on. Proofs start with the keyword :cmd:`Proof`. Then Rocq enters the proof mode until the proof is completed. In proof mode, the user primarily enters tactics (see :ref:`tactics`). The user may also enter commands to manage the proof mode (see :ref:`proofhandling`). When the proof is complete, use the :cmd:`Qed` command so the kernel verifies the proof and adds it to the global environment. .. note:: #. Several statements can be simultaneously asserted provided the :flag:`Nested Proofs Allowed` flag was turned on. #. Not only other assertions but any command can be given while in the process of proving a given assertion. In this case, the command is understood as if it would have been given before the statements still to be proved. Nonetheless, this practice is discouraged and may stop working in future versions. #. Proofs ended by :cmd:`Qed` are declared :term:`opaque`. Their content cannot be unfolded (see :ref:`applyingconversionrules`), thus realizing some form of *proof-irrelevance*. Proofs that end with :cmd:`Defined` can be unfolded. #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the current asserted statement into an axiom and exit proof mode. rocq-9.2.0/doc/sphinx/language/core/index.rst000066400000000000000000000034501516144147600211330ustar00rootroot00000000000000.. _core-language: ============= Core language ============= At the heart of the Rocq Prover is the Rocq kernel. While users have access to a language with many convenient features such as :ref:`notations `, :ref:`implicit arguments `, etc. (presented in the :ref:`next chapter `), those features are translated into the core language (the Calculus of Inductive Constructions) that the kernel understands, which we present here. Furthermore, while users can build proofs interactively using tactics (see Chapter :ref:`tactics`), the role of these tactics is to incrementally build a "proof term" which the kernel will verify. More precisely, a proof term is a :term:`term` of the Calculus of Inductive Constructions whose :term:`type` corresponds to a theorem statement. The kernel is a type checker which verifies that terms have their expected types. This separation between the kernel on one hand and the :ref:`elaboration engine ` and :ref:`tactics ` on the other follows what is known as the :gdef:`de Bruijn criterion` (keeping a small and well delimited trusted code base within a proof assistant which can be much more complex). This separation makes it necessary to trust only a smaller, critical component (the kernel) instead of the entire system. In particular, users may rely on external plugins that provide advanced and complex tactics without fear of these tactics being buggy, because the kernel will have to check their output. .. toctree:: :maxdepth: 1 basic sorts assumptions definitions conversion ../cic variants inductive coinductive records sections modules primitive ../../addendum/universe-polymorphism ../../addendum/sprop ../../addendum/rewrite-rules rocq-9.2.0/doc/sphinx/language/core/inductive.rst000066400000000000000000001630731516144147600220260ustar00rootroot00000000000000.. _inductive: Inductive types and recursive functions ======================================= The :cmd:`Inductive` command allows defining types by cases on the form of the :term:`inhabitants ` of the type. These constructors can recursively have arguments in the type being defined. In contrast, in types defined by the :cmd:`Variant` command, such recursive references are not permitted. Inductive types include natural numbers, lists and well-founded trees. Inhabitants of inductive types can recursively nest only a finite number of constructors. So, they are well-founded. This distinguishes them from :cmd:`CoInductive` types, such as streams, whose constructors can be infinitely nested. In Rocq, :cmd:`Variant` types thus correspond to the common subset of inductive and coinductive types that are non-recursive. Due to the recursive structure of inductive types, functions on inductive types generally must be defined recursively using the :n:`fix` expression (see :n:`@term_fix`) or the :cmd:`Fixpoint` command. .. _gallina-inductive-definitions: Inductive types --------------- .. cmd:: Inductive @inductive_definition {* with @inductive_definition } Inductive @record_definition {* with @record_definition } .. insertprodn inductive_definition constructor .. prodn:: inductive_definition ::= @ident {? @cumul_univ_decl } {* @binder } {? %| {* @binder } } {? : @type } := {? {? %| } {+| @constructor } } {? @decl_notations } constructor ::= {* #[ {+, @attribute } ] } @ident {* @binder } {? @of_type_inst } Defines one or more inductive types and its constructors. Rocq generates :gdef:`induction principles ` depending on the universe that the inductive type belongs to. The induction principles are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which respectively correspond to on :g:`Type`, :g:`Prop`, :g:`Set` and :g:`SProp`. Their types expresses structural induction/recursion principles over objects of type :n:`@ident`. These :term:`constants ` are generated when possible (for instance :n:`@ident`\ ``_rect`` may be impossible to derive when :n:`@ident` is a proposition). This commands supports :attr:`schemes` to control the automatic generation of inductive principles. .. flag:: Dependent Proposition Eliminators The inductive principles express dependent elimination when the inductive type allows it (always true when not using :flag:`Primitive Projections`), except by default when the inductive is explicitly declared in `Prop`. The dependent elimination corresponds to the "Induction" :n:`@scheme_type`, and non-dependent elimination to "Minimality". Explicitly `Prop` inductive types declared when this flag is enabled also automatically declare dependent inductive principles. Name generation may also change when using tactics such as :tacn:`destruct` on such inductives. Note that explicit declarations through :cmd:`Scheme` are not affected by this flag. :n:`{? %| {* @binder } }` The :n:`|` separates uniform and non uniform parameters. See :flag:`Uniform Inductive Parameters`. The :cmd:`Inductive` command supports the :attr:`universes(polymorphic)`, :attr:`universes(template)`, :attr:`universes(cumulative)`, :attr:`bypass_check(positivity)`, :attr:`bypass_check(universes)` and :attr:`private(matching)` attributes. When record syntax is used, this command also supports the :attr:`projections(primitive)` :term:`attribute`. Also, in the record syntax, if given, the :n:`as @ident` part specifies the name to use for inhabitants of the record in the type of projections. Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. The :n:`@ident`\s are simultaneously added to the global environment before the types of constructors are checked. Each :n:`@ident` can be used independently thereafter. However, the induction principles currently generated for such types are not useful. Use the :cmd:`Scheme` command to generate useful induction principles. See :ref:`mutually_inductive_types`. If the entire inductive definition is parameterized with :n:`@binder`\s, those :gdef:`inductive parameters ` correspond to a local context in which the entire set of inductive declarations is interpreted. For this reason, the parameters must be strictly the same for each inductive type. See :ref:`parametrized-inductive-types`. Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case the actual type of the constructor is :n:`forall {* @binder }, @type`. .. exn:: Non strictly positive occurrence of @ident in @type. The types of the constructors have to satisfy a *positivity condition* (see Section :ref:`positivity`). This condition ensures the soundness of the inductive definition. Positivity checking can be disabled using the :flag:`Positivity Checking` flag or the :attr:`bypass_check(positivity)` attribute (see :ref:`controlling-typing-flags`). .. exn:: The conclusion of @type is not valid; it must be built from @ident. The conclusion of the type of the constructors must be the inductive type :n:`@ident` being defined (or :n:`@ident` applied to arguments in the case of indexed inductive types β€” cf. next section). The following subsections show examples of simple inductive types, simple indexed inductive types, simple parametric inductive types, mutually inductive types and private (matching) inductive types. .. _simple-inductive-types: Simple inductive types ~~~~~~~~~~~~~~~~~~~~~~ A simple inductive type belongs to a universe that is a simple :n:`@sort`. .. example:: The set of natural numbers is defined as: .. rocqtop:: reset all Inductive nat : Set := | O : nat | S : nat -> nat. The type nat is defined as the least :g:`Set` containing :g:`O` and closed by the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the global environment. This definition generates four :term:`induction principles `: :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: .. rocqtop:: all Check nat_ind. This is the well known structural induction principle over natural numbers, i.e. the second-order form of Peano’s induction principle. It allows proving universal properties of natural numbers (:g:`forall n:nat, P n`) by induction on :g:`n`. The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to primitive induction principles (allowing dependent types) respectively over sorts ``Type``, ``Set`` and ``SProp``. In the case where inductive types don't have indices (the next section gives an example of indices), a constructor can be defined by giving the type of its arguments alone. .. example:: .. rocqtop:: reset none Reset nat. .. rocqtop:: in Inductive nat : Set := O | S (_:nat). Automatic Prop lowering +++++++++++++++++++++++ When an inductive is declared without an explicit sort, it is put in the smallest sort which permits large elimination (excluding `SProp`). For :ref:`empty and singleton ` types this means they are declared in `Prop`. Simple indexed inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In indexed inductive types, the universe where the inductive type is defined is no longer a simple :n:`@sort`, but what is called an arity, which is a type whose conclusion is a :n:`@sort`. .. example:: As an example of indexed inductive types, let us define the :g:`even` predicate: .. rocqtop:: all Inductive even : nat -> Prop := | even_0 : even O | even_SS : forall n:nat, even n -> even (S (S n)). The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively defined) over natural numbers. The type of its two constructors are the defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: .. rocqtop:: all Check even_ind. From a mathematical point of view, this asserts that the natural numbers satisfying the predicate :g:`even` are exactly in the smallest set of naturals satisfying the clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` and to prove that if any natural number :g:`n` satisfies :g:`P` its double successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the structural induction principle we got for :g:`nat`. .. _parametrized-inductive-types: Parameterized inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the previous example, each constructor introduces a different instance of the predicate :g:`even`. In some cases, all the constructors introduce the same generic instance of the inductive definition, in which case, instead of an index, we use a context of parameters which are :n:`@binder`\s shared by all the constructors of the definition. Parameters differ from inductive type indices in that the conclusion of each type of constructor invokes the inductive type with the same parameter values of its specification. .. example:: A typical example is the definition of polymorphic lists: .. rocqtop:: all Inductive list (A:Set) : Set := | nil : list A | cons : A -> list A -> list A. In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: .. rocqtop:: all Check nil. Check cons. Observe that the induction principles are also quantified with :g:`(A:Set)`, for example: .. rocqtop:: all Check list_ind. Once again, the names of the constructor arguments and the type of the conclusion can be omitted: .. rocqtop:: none Reset list. .. rocqtop:: in Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). .. note:: + The constructor type can recursively invoke the inductive definition on an argument which is not the parameter itself. One can define : .. rocqtop:: all Inductive list2 (A:Set) : Set := | nil2 : list2 A | cons2 : A -> list2 (A*A) -> list2 A. that can also be written by specifying only the type of the arguments: .. rocqtop:: all reset Inductive list2 (A:Set) : Set := | nil2 | cons2 (_:A) (_:list2 (A*A)). But the following definition will give an error: .. rocqtop:: all Fail Inductive listw (A:Set) : Set := | nilw : listw (A*A) | consw : A -> listw (A*A) -> listw (A*A). because the conclusion of the type of constructors should be :g:`listw A` in both cases. + A parameterized inductive definition can be defined using indices instead of parameters but it will sometimes give a different (bigger) sort for the inductive definition and will produce a less convenient rule for case elimination. .. flag:: Uniform Inductive Parameters When this :term:`flag` is set (it is off by default), inductive definitions are abstracted over their parameters before type checking constructors, allowing to write: .. rocqtop:: all Set Uniform Inductive Parameters. Inductive list3 (A:Set) : Set := | nil3 : list3 | cons3 : A -> list3 -> list3. This behavior is essentially equivalent to starting a new section and using :cmd:`Context` to give the uniform parameters, like so (cf. :ref:`section-mechanism`): .. rocqtop:: all reset Section list3. Context (A:Set). Inductive list3 : Set := | nil3 : list3 | cons3 : A -> list3 -> list3. End list3. For finer control, you can use a ``|`` between the uniform and the non-uniform parameters: .. rocqtop:: in reset Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop := Acc_in : (forall y, R y x -> Acc y) -> Acc x. The flag can then be seen as deciding whether the ``|`` is at the beginning (when the flag is unset) or at the end (when it is set) of the parameters when not explicitly given. .. seealso:: Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. .. _mutually_inductive_types: Mutually defined inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. todo: combine with the very similar tree/forest example in reasoning-inductives.rst The induction principles currently generated for mutually defined types are not useful. Use the :cmd:`Scheme` command to generate a useful induction principle. .. example:: Mutually defined inductive types A typical example of mutually inductive data types is trees and forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can be declared like this: .. rocqtop:: in Parameters A B : Set. Inductive tree : Set := node : A -> forest -> tree with forest : Set := | leaf : B -> forest | cons : tree -> forest -> forest. This declaration automatically generates eight induction principles. They are not the most general principles, but they correspond to each inductive part seen as a single inductive definition. To illustrate this point on our example, here are the types of :g:`tree_rec` and :g:`forest_rec`. .. rocqtop:: all Check tree_rec. Check forest_rec. Assume we want to parameterize our mutual inductive definitions with the two type variables :g:`A` and :g:`B`, the declaration should be done as follows: .. rocqdoc:: Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B with forest (A B:Set) : Set := | leaf : B -> forest A B | cons : tree A B -> forest A B -> forest A B. Assume we define an inductive definition inside a section (cf. :ref:`section-mechanism`). When the section is closed, the variables declared in the section and occurring free in the declaration are added as parameters to the inductive definition. .. seealso:: A generic command :cmd:`Scheme` is useful to build automatically various mutual induction principles. .. index:: single: fix Recursive functions: fix ------------------------ .. insertprodn term_fix fixannot .. prodn:: term_fix ::= let fix @fix_decl in @term | fix @fix_decl {? {+ with @fix_decl } for @ident } fix_decl ::= @ident {* @binder } {? @fixannot } {? : @type } := @term fixannot ::= %{ struct @ident %} | %{ wf @one_term @ident %} | %{ measure @one_term {? @ident } {? @one_term } %} The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the :math:`i`-th component of a block of functions defined by mutual structural recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When :math:`n=1`, the ":n:`for @ident__i`" clause is omitted. The association of a single fixpoint and a local definition have a special syntax: :n:`let fix @ident {* @binder } := @term in` stands for :n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for cofixpoints. Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in commands such as :cmd:`Fixpoint` (with the :attr:`program` attribute) and :cmd:`Function`. .. todo explanation of struct: see text above at the Fixpoint command, also see https://github.com/rocq-prover/rocq/pull/12936#discussion_r510716268 and above. Consider whether to move the grammar for fixannot elsewhere .. _Fixpoint: Top-level recursive functions ----------------------------- This section describes the primitive form of definition by recursion over inductive objects. See the :cmd:`Function` command for more advanced constructions. .. cmd:: Fixpoint @fix_definition {* with @fix_definition } .. insertprodn fix_definition fix_definition .. prodn:: fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } Allows defining functions by pattern matching over inductive objects using a fixed point construction. The meaning of this declaration is to define :n:`@ident` as a recursive function with arguments specified by the :n:`@binder`\s such that :n:`@ident` applied to arguments corresponding to these :n:`@binder`\s has type :n:`@type`, and is equivalent to the expression :n:`@term`. The type of :n:`@ident` is consequently :n:`forall {* @binder }, @type` and its value is equivalent to :n:`fun {* @binder } => @term`. This command accepts the :attr:`program`, :attr:`bypass_check(universes)`, and :attr:`bypass_check(guard)` attributes. To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical constraints on a special argument called the decreasing argument. They are needed to ensure that the :cmd:`Fixpoint` definition always terminates. The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to let the user tell the system which argument decreases along the recursive calls. The :n:`{struct @ident}` annotation may be left implicit, in which case the system successively tries arguments from left to right until it finds one that satisfies the decreasing condition. :cmd:`Fixpoint` without the :attr:`program` attribute does not support the :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. See :ref:`program_fixpoint`. The :n:`with` clause allows simultaneously defining several mutual fixpoints. It is especially useful when defining functions over mutually defined inductive types. Example: :ref:`Mutual Fixpoints`. If :n:`@term` is omitted, :n:`@type` is required and Rocq enters proof mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. In this case, the proof should be terminated with :cmd:`Defined` in order to define a :term:`constant` for which the computational behavior is relevant. See :ref:`proof-editing-mode`. This command accepts the :attr:`using` attribute. .. note:: + Some fixpoints may have several arguments that fit as decreasing arguments, and this choice influences the reduction of the fixpoint. Hence an explicit annotation must be used if the leftmost decreasing argument is not the desired one. Writing explicit annotations can also speed up type checking of large mutual fixpoints. + In order to keep the strong normalization property, the fixed point reduction will only be performed when the argument in position of the decreasing argument (which type should be in an inductive definition) starts with a constructor. .. example:: One can define the addition function as : .. rocqtop:: all Fixpoint add (n m:nat) {struct n} : nat := match n with | O => m | S p => S (add p m) end. The match operator matches a value (here :g:`n`) with the various constructors of its (inductive) type. The remaining arguments give the respective values to be returned, as functions of the parameters of the corresponding constructor. Thus here when :g:`n` equals :g:`O` we return :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. The match operator is formally described in Section :ref:`match-construction`. The system recognizes that in the inductive call :g:`(add p m)` the first argument actually decreases because it is a *pattern variable* coming from :g:`match n with`. .. example:: The following definition is not correct and generates an error message: .. rocqtop:: all Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := match m with | O => n | S p => S (wrongplus n p) end. because the declared decreasing argument :g:`n` does not actually decrease in the recursive call. .. _reversed_add_example: The function computing the addition over the second argument should rather be written: .. rocqtop:: all Fixpoint plus (n m:nat) {struct m} : nat := match m with | O => n | S p => S (plus n p) end. **Aside**: Observe that `plus n 0` is reducible but `plus 0 n` is not, the reverse of `Nat.add`, for which `0 + n` is reducible and `n + 0` is not. .. rocqtop:: all Goal forall n:nat, plus n 0 = plus 0 n. intros; simpl. (* plus 0 n not reducible *) .. rocqtop:: none Abort. .. rocqtop:: all Goal forall n:nat, n + 0 = 0 + n. intros; simpl. (* n + 0 not reducible *) .. rocqtop:: none Abort. .. example:: The recursive call may not only be on direct subterms of the recursive variable :g:`n` but also on a deeper subterm and we can directly write the function :g:`mod2` which gives the remainder modulo 2 of a natural number. .. rocqtop:: all Fixpoint mod2 (n:nat) : nat := match n with | O => O | S p => match p with | O => S O | S q => mod2 q end end. .. _example_mutual_fixpoints: .. example:: Mutual fixpoints The size of trees and forests can be defined the following way: .. rocqtop:: all Fixpoint tree_size (t:tree) : nat := match t with | node a f => S (forest_size f) end with forest_size (f:forest) : nat := match f with | leaf b => 1 | cons t f' => (tree_size t + forest_size f') end. .. extracted from CIC chapter .. _inductive-definitions: Theory of inductive definitions ------------------------------- Formally, we can represent any *inductive definition* as :math:`\ind{p}{Ξ“_I}{Ξ“_C}` where: + :math:`Ξ“_I` determines the names and types of inductive types; + :math:`Ξ“_C` determines the names and types of constructors of these inductive types; + :math:`p` determines the number of parameters of these inductive types. 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 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 :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:: The declaration for parameterized lists is: .. math:: \ind{1}{[\List:\Setβ†’\Set]}{\left[\begin{array}{rcl} \Nil & : & βˆ€ A:\Set,~\List~A \\ \cons & : & βˆ€ A:\Set,~Aβ†’ \List~Aβ†’ \List~A \end{array} \right]} which corresponds to the result of the Rocq declaration: .. rocqtop:: in reset Inductive list (A:Set) : Set := | nil : list A | cons : A -> list A -> list A. .. example:: The declaration for a mutual inductive definition of tree and forest is: .. math:: \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]} {\left[\begin{array}{rcl} \node &:& \forest β†’ \tree\\ \emptyf &:& \forest\\ \consf &:& \tree β†’ \forest β†’ \forest\\ \end{array}\right]} which corresponds to the result of the Rocq declaration: .. rocqtop:: in Inductive tree : Set := | node : forest -> tree with forest : Set := | emptyf : forest | consf : tree -> forest -> forest. .. example:: The declaration for a mutual inductive definition of even and odd is: .. math:: \ind{0}{\left[\begin{array}{rcl}\even&:&\nat β†’ \Prop \\ \odd&:&\nat β†’ \Prop \end{array}\right]} {\left[\begin{array}{rcl} \evenO &:& \even~0\\ \evenS &:& βˆ€ n,~\odd~n β†’ \even~(\nS~n)\\ \oddS &:& βˆ€ n,~\even~n β†’ \odd~(\nS~n) \end{array}\right]} which corresponds to the result of the Rocq declaration: .. rocqtop:: in Inductive even : nat -> Prop := | even_O : even 0 | even_S : forall n, odd n -> even (S n) with odd : nat -> Prop := | odd_S : forall n, even n -> odd (S n). .. _Types-of-inductive-objects: Types of inductive objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We have to give the type of constants in a global environment :math:`E` which contains an inductive definition. .. inference:: Ind \WFE{Ξ“} \ind{p}{Ξ“_I}{Ξ“_C} ∈ E (a:A)βˆˆΞ“_I --------------------- E[Ξ“] ⊒ a : A .. inference:: Constr \WFE{Ξ“} \ind{p}{Ξ“_I}{Ξ“_C} ∈ E (c:C)βˆˆΞ“_C --------------------- E[Ξ“] ⊒ c : C .. example:: Provided that our global environment :math:`E` contains inductive definitions we showed before, these two inference rules above enable us to conclude that: .. math:: \begin{array}{l} E[Ξ“] ⊒ \even : \natβ†’\Prop\\ E[Ξ“] ⊒ \odd : \natβ†’\Prop\\ E[Ξ“] ⊒ \evenO : \even~\nO\\ E[Ξ“] ⊒ \evenS : βˆ€ n:\nat,~\odd~n β†’ \even~(\nS~n)\\ E[Ξ“] ⊒ \oddS : βˆ€ n:\nat,~\even~n β†’ \odd~(\nS~n) \end{array} .. _Well-formed-inductive-definitions: Well-formed inductive definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We cannot accept any inductive definition because some of them lead to inconsistent systems. We restrict ourselves to definitions which satisfy a syntactic criterion of positivity. Before giving the formal rules, we need a few definitions: 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`. .. example:: :math:`Aβ†’\Set` is an arity of sort :math:`\Set`. :math:`βˆ€ A:\Prop,~Aβ†’ \Prop` is an arity of sort :math:`\Prop`. Arity +++++ A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of sort :math:`s`. .. example:: :math:`Aβ†’ \Set` and :math:`βˆ€ A:\Prop,~Aβ†’ \Prop` are arities. .. Convention in describing inductive types: k is the number of inductive types (I_i : forall params, A_i) n is the number of constructors in the whole block (c_i : forall params, C_i) r is the number of parameters l is the size of the context of parameters (p_i : P_i) m is the number of recursively non-uniform parameters among parameters s is the number of indices q = r+s is the number of parameters and indices 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_q )` + :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`. .. _positivity: Positivity Condition ++++++++++++++++++++ The type of constructor :math:`T` will be said to *satisfy the positivity condition* for a set of constants :math:`X_1 … X_k` in the following cases: + :math:`T=(X_j~t_1 … t_q )` for some :math:`j` and no :math:`X_1 … X_k` occur free in any :math:`t_i` + :math:`T=βˆ€ x:U,~V` and :math:`X_1 … X_k` occur only strictly positively in :math:`U` and the type :math:`V` satisfies the positivity condition for :math:`X_1 … X_k`. Strict positivity +++++++++++++++++ The constants :math:`X_1 … X_k` *occur strictly positively* in :math:`T` in the following cases: + no :math:`X_1 … X_k` occur in :math:`T` + :math:`T` converts to :math:`(X_j~t_1 … t_q )` for some :math:`j` and no :math:`X_1 … X_k` occur in any of :math:`t_i` + :math:`T` converts to :math:`βˆ€ x:U,~V` and :math:`X_1 … X_k` occur strictly positively in type :math:`V` but none of them occur in :math:`U` + :math:`T` converts to :math:`(I~a_1 … a_r~t_1 … t_s )` where :math:`I` is the name of an inductive definition of the form .. math:: \ind{r}{I:A}{c_1 :βˆ€ p_1 :P_1 ,… βˆ€p_r :P_r ,~C_1 ;~…;~c_n :βˆ€ p_1 :P_1 ,… βˆ€p_r :P_r ,~C_n} (in particular, it is not mutually defined and it has :math:`r` parameters) and no :math:`X_1 … X_k` occur in any of the :math:`t_i` nor in any of the :math:`a_j` for :math:`m < j ≀ r` where :math:`m ≀ r` is the number of recursively uniform parameters, and the (instantiated) types of constructor :math:`\subst{C_i}{p_j}{a_j}_{j=1… m}` of :math:`I` satisfy the nested positivity condition for :math:`X_1 … X_k` Nested Positivity +++++++++++++++++ If :math:`I` is a non-mutual inductive type with :math:`r` parameters, then, the type of constructor :math:`T` of :math:`I` *satisfies the nested positivity condition* for a set of constants :math:`X_1 … X_k` in the following cases: + :math:`T=(I~b_1 … b_r~u_1 … u_s)` and no :math:`X_1 … X_k` occur in any :math:`u_i` nor in any of the :math:`b_j` for :math:`m < j ≀ r` where :math:`m ≀ r` is the number of recursively uniform parameters + :math:`T=βˆ€ x:U,~V` and :math:`X_1 … X_k` occur only strictly positively in :math:`U` and the type :math:`V` satisfies the nested positivity condition for :math:`X_1 … X_k` .. example:: For instance, if one considers the following variant of a tree type branching over the natural numbers: .. rocqtop:: in Inductive nattree (A:Type) : Type := | leaf : nattree A | natnode : A -> (nat -> nattree A) -> nattree A. Then every instantiated constructor of ``nattree A`` satisfies the nested positivity condition for ``nattree``: + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for ``nattree`` because ``nattree`` does not appear in any (real) arguments of the type of that constructor (primarily because ``nattree`` does not have any (real) arguments) ... (bullet 1) + Type ``A β†’ (nat β†’ nattree A) β†’ nattree A`` of constructor ``natnode`` satisfies the positivity condition for ``nattree`` because: - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1) - ``nattree`` occurs only strictly positively in ``nat β†’ nattree A`` ... (bullet 3 + 2) - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1) .. _Correctness-rules: Correctness rules +++++++++++++++++ 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 .. inference:: W-Ind \WFE{Ξ“_P} (E[Ξ“_I ;Ξ“_P ] ⊒ C_i : s_{q_i} )_{i=1… n} ------------------------------------------ \WF{E;~\ind{l}{Ξ“_I}{Ξ“_C}}{} provided that the following side conditions hold: + :math:`k>0` and all of :math:`I_j` and :math:`c_i` are distinct names for :math:`j=1… k` and :math:`i=1… n`, + :math:`l` is the size of :math:`Ξ“_P` which is called the context of parameters, + for :math:`j=1… k` we have that :math:`A_j` is an arity of sort :math:`s_j` and :math:`I_j βˆ‰ E`, + for :math:`i=1… n` we have that :math:`C_i` is a type of constructor of :math:`I_{q_i}` which satisfies the positivity condition for :math:`I_1 … I_k` and :math:`c_i βˆ‰ E`. Additionally, for :math:`j=1… k` the following universe constraints must be satisfied, or :math:`s_j` must be an impredicative sort (`SProp`, `Prop`, or if `-impredicative-set` was used `Set`) and the `j`\th inductive may not be eliminated to larger sorts: - for each (non parameter) constructor argument, the universe of its type must be smaller than :math:`s_j` - if `-indices-matter` was used, for each index the universe of its type must be smaller than :math:`s_j` - if there are 2 or more constructors, `Set` must be smaller than :math:`s_j` - unless the inductive is a primitive record, and unless :flag:`Definitional UIP` was used, if there is 1 constructor, `Prop` must be smaller than :math:`s_j` (essentially this means :math:`s_j` must not be `SProp`) .. 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)`. .. rocqtop:: in Inductive exProp (P:Prop->Prop) : Prop := | exP_intro : forall X:Prop, P X -> exProp P. The same definition on :math:`\Set` is not allowed and fails: .. rocqtop:: all Fail Inductive exSet (P:Set->Prop) : Set := exS_intro : forall X:Set, P X -> exSet P. It is possible to declare the same inductive definition in the universe :math:`\Type`. The :g:`exType` inductive definition has type :math:`(\Type(i)β†’\Prop)β†’\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}` has type :math:`\Type(k)` with :math:`kProp) : Type := exT_intro : forall X:Type, P X -> exType P. .. example:: Negative occurrence (first example) The following inductive definition is rejected because it does not satisfy the positivity condition: .. rocqtop:: all Fail Inductive I : Prop := not_I_I (not_I : I -> False) : I. If we were to accept such definition, we could derive a contradiction from it (we can test this by disabling the :flag:`Positivity Checking` flag): .. rocqtop:: in #[bypass_check(positivity)] Inductive I : Prop := not_I_I (not_I : I -> False) : I. .. rocqtop:: all Definition I_not_I : I -> ~ I := fun i => match i with not_I_I not_I => not_I end. .. rocqtop:: in Lemma contradiction : False. Proof. enough (I /\ ~ I) as [] by contradiction. split. - apply not_I_I. intro. now apply I_not_I. - intro. now apply I_not_I. Qed. .. example:: Negative occurrence (second example) Here is another example of an inductive definition which is rejected because it does not satify the positivity condition: .. rocqtop:: all Fail Inductive Lam := lam (_ : Lam -> Lam). Again, if we were to accept it, we could derive a contradiction (this time through a non-terminating recursive function): .. rocqtop:: in #[bypass_check(positivity)] Inductive Lam := lam (_ : Lam -> Lam). .. rocqtop:: all Fixpoint infinite_loop l : False := match l with lam x => infinite_loop (x l) end. Check infinite_loop (lam (@id Lam)) : False. .. example:: Non strictly positive occurrence It is less obvious why inductive type definitions with occurences that are positive but not strictly positive are harmful. We will see that in presence of an impredicative type they are unsound: .. rocqtop:: all Fail Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. If we were to accept this definition we could derive a contradiction by creating an injective function from :math:`A β†’ \Prop` to :math:`A`. This function is defined by composing the injective constructor of the type :math:`A` with the function :math:`Ξ»x. Ξ»z. z = x` injecting any type :math:`T` into :math:`T β†’ \Prop`. .. rocqtop:: in #[bypass_check(positivity)] Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. .. rocqtop:: all Definition f (x: A -> Prop): A := introA (fun z => z = x). .. rocqtop:: in Lemma f_inj: forall x y, f x = f y -> x = y. Proof. unfold f; intros ? ? H; injection H. set (F := fun z => z = y); intro HF. symmetry; replace (y = x) with (F y). + unfold F; reflexivity. + rewrite <- HF; reflexivity. Qed. The type :math:`A β†’ \Prop` can be understood as the powerset of the type :math:`A`. To derive a contradiction from the injective function :math:`f` we use Cantor's classic diagonal argument. .. rocqtop:: all Definition d: A -> Prop := fun x => exists s, x = f s /\ ~s x. Definition fd: A := f d. .. rocqtop:: in Lemma cantor: (d fd) <-> ~(d fd). Proof. split. + intros [s [H1 H2]]; unfold fd in H1. replace d with s. * assumption. * apply f_inj; congruence. + intro; exists d; tauto. Qed. Lemma bad: False. Proof. pose cantor; tauto. Qed. This derivation was first presented by Thierry Coquand and Christine Paulin in :cite:`CP90`. .. _Destructors: Destructors ~~~~~~~~~~~~~~~~~ The specification of inductive definitions with arities and constructors is quite natural. But we still have to say how to use an object in an inductive type. This problem is rather delicate. There are actually several different ways to do that. Some of them are logically equivalent but not always equivalent from the computational point of view or from the user point of view. From the computational point of view, we want to be able to define a function whose domain is an inductively defined type by using a combination of case analysis over the possible constructors of the object and recursion. Because we need to keep a consistent theory and also we prefer to keep 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 :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 a set of constructors. We want to capture the fact that we do not have any other way to build an object in this type. So when trying to prove a property about an object :math:`m` in an inductive type it is enough to enumerate all the cases where :math:`m` starts with a different constructor. 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 :math:`βˆ€ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove: + :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 :math:`\length` is the same as proving: + :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 proposed by Martin-LΓΆf in his Intuitionistic Type Theory, is to introduce for each inductive definition an elimination operator. At the logical level it is a proof of the usual induction principle and at the computational level it implements a generic operator for doing primitive recursion over the structure. But this operator is rather tedious to implement and use. We choose to factorize the operator for primitive recursion into two more primitive operations as was first suggested by Th. Coquand in :cite:`Coq92`. One is the definition by pattern matching. The second one is a definition by guarded fixpoints. .. _match-construction: The match ... with ... end construction +++++++++++++++++++++++++++++++++++++++ The basic idea of this operator is that we have an object :math:`m` in an inductive type :math:`I` and we want to prove a property which possibly depends on :math:`m`. For this, it is enough to prove the property for :math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`. The Rocq 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 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 and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the :math:`u_1 … u_{p_i}` according to the ΞΉ-reduction. Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need 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`. Rocq can sometimes infer this predicate but sometimes not. The concrete syntax for describing this predicate uses the :math:`\as…\In…\return` construction. For instance, let us assume that :math:`I` is an unary predicate with one parameter and one argument. The predicate is made explicit using the syntax: .. math:: \Match~m~\as~x~\In~I~\_~a~\return~P~\with~ (c_1~x_{11} ... x_{1p_1} ) β‡’ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) β‡’ f_n~\kwend The :math:`\as` part can be omitted if either the result type does not depend on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m` can occur in :math:`P` where it is considered a bound variable). The :math:`\In` part can be omitted if the result type does not depend on the arguments of :math:`I`. Note that the arguments of :math:`I` corresponding to parameters *must* be :math:`\_`, because the result type is not generalized to all possible values of the parameters. The other arguments of :math:`I` (sometimes called indices in the literature) have to be variables (:math:`a` above) and these variables can occur in :math:`P`. The expression after :math:`\In` must be seen as an *inductive type pattern*. Notice that expansion of implicit arguments and notations apply to this pattern. For the purpose of presenting the inference rules, we use a more compact notation: .. math:: \case(m,(Ξ» a x . P), Ξ» x_{11} ... x_{1p_1} . f_1~| … |~Ξ» x_{n1} ...x_{np_n} . f_n ) .. _Allowed-elimination-sorts: **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. .. _cic_notations: **Notations.** The :math:`[I:A|B]` is defined as the smallest relation satisfying the following rules: We write :math:`[I|B]` for :math:`[I:A|B]` where :math:`A` is the type of :math:`I`. The case of inductive types in sorts :math:`\Set` or :math:`\Type` is simple. There is no restriction on the sort of the predicate to be eliminated. .. inference:: Prod [(I~x):Aβ€²|Bβ€²] ----------------------- [I:βˆ€ x:A,~Aβ€²|βˆ€ x:A,~Bβ€²] .. inference:: Set & Type s_1 ∈ \{\Set,\Type(j)\} s_2 ∈ \Sort ---------------- [I:s_1 |Iβ†’ s_2 ] The case of Inductive definitions of sort :math:`\Prop` is a bit more complicated, because of our interpretation of this sort. The only harmless allowed eliminations, are the ones when predicate :math:`P` is also of sort :math:`\Prop` or is of the morally smaller sort :math:`\SProp`. .. inference:: Prop s ∈ \{\SProp,\Prop\} -------------------- [I:\Prop|Iβ†’s] :math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in :math:`\Prop` could not be used for computation and are consequently ignored by the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, and the logical disjunction :math:`A ∨ B` is defined inductively by: .. example:: .. rocqtop:: in Inductive or (A B:Prop) : Prop := or_introl : A -> or A B | or_intror : B -> or A B. The following definition which computes a boolean value by case over the proof of :g:`or A B` is not accepted: .. example:: .. rocqtop:: all Fail Definition choice (A B: Prop) (x:or A B) := match x with or_introl _ _ a => true | or_intror _ _ b => false end. 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 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 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 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: .. example:: .. rocqtop:: all Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. The elimination of an inductive type of sort :math:`\Prop` on a predicate :math:`P` of type :math:`Iβ†’ \Type` leads to a paradox when applied to impredicative inductive definition like the second-order existential quantifier :g:`exProp` defined above, because it gives access to the two projections on this type. .. _Empty-and-singleton-elimination: **Empty and singleton elimination.** There are special inductive definitions in :math:`\Prop` for which more eliminations are allowed. .. inference:: Prop-extended I~\kw{is an empty or singleton definition} s ∈ \Sort ------------------------------------- [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 canonical way to interpret the informative extraction on an object in that type, such that the elimination on any sort :math:`s` is legal. Typical examples are the conjunction of non-informative propositions and the equality. If there is a hypothesis :math:`h:a=b` in the local context, it can be used for rewriting not only in logical propositions but also in any type. .. example:: .. rocqtop:: all Print eq_rec. Require Extraction. Extraction eq_rec. An empty definition has no constructors, in that case also, elimination on any sort is allowed. .. _Eliminaton-for-SProp: Inductive types in :math:`\SProp` must have no constructors (i.e. be empty) to be eliminated to produce relevant values. Note that thanks to proof irrelevance elimination functions can be produced for other types, for instance the elimination for a unit type is the identity. .. _Type-of-branches: **Type of branches.** Let :math:`c` be a term of type :math:`C`, we assume :math:`C` is a type of constructor for an inductive type :math:`I`. Let :math:`P` be a term that represents the property to be proved. We assume :math:`r` is the number of parameters and :math:`s` is the number of arguments. We define a new type :math:`\{c:C\}^P` which represents the type of the branch corresponding to the :math:`c:C` constructor. .. math:: \begin{array}{ll} \{c:(I~q_1\ldots q_r\ t_1 \ldots t_s)\}^P &\equiv (P~t_1\ldots ~t_s~c) \\ \{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`. .. example:: The following term in concrete syntax:: match t as l return P' with | nil _ => t1 | cons _ hd tl => t2 end can be represented in abstract syntax as .. math:: \case(t,P,f_1 | f_2 ) where .. math:: :nowrap: \begin{eqnarray*} P & = & Ξ» l.~P^\prime\\ f_1 & = & t_1\\ f_2 & = & Ξ» (hd:\nat).~Ξ» (tl:\List~\nat).~t_2 \end{eqnarray*} According to the definition: .. math:: \{(\Nil~\nat)\}^P ≑ \{(\Nil~\nat) : (\List~\nat)\}^P ≑ (P~(\Nil~\nat)) .. math:: \begin{array}{rl} \{(\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:`\{(\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: **Typing rule.** Our very general destructor for inductive definitions has the following typing rule .. inference:: match \begin{array}{l} E[Ξ“] ⊒ c : (I~q_1 … q_r~t_1 … t_s ) \\ E[Ξ“] ⊒ P : B \\ [(I~q_1 … q_r)|B] \\ (E[Ξ“] ⊒ f_i : \{(c_{p_i}~q_1 … q_r)\}^P)_{i=1… l} \end{array} ------------------------------------------------ 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 :math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`. .. example:: Below is a typing rule for the term shown in the previous example: .. inference:: list example \begin{array}{l} E[Ξ“] ⊒ t : (\List ~\nat) \\ E[Ξ“] ⊒ P : B \\ [(\List ~\nat)|B] \\ E[Ξ“] ⊒ f_1 : \{(\Nil ~\nat)\}^P \\ E[Ξ“] ⊒ f_2 : \{(\cons ~\nat)\}^P \end{array} ------------------------------------------------ E[Ξ“] ⊒ \case(t,P,f_1 |f_2 ) : (P~t) .. _Definition-of-ΞΉ-reduction: **Definition of ΞΉ-reduction.** We still have to define the ΞΉ-reduction in the general case. An ΞΉ-redex is a term of the following form: .. math:: \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) with :math:`c_{p_i}` the :math:`i`-th constructor of the inductive type :math:`I` with :math:`r` parameters. 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_l ) \triangleright_ΞΉ (f_i~a_1 … a_m ) .. _Fixpoint-definitions: Fixpoint definitions ~~~~~~~~~~~~~~~~~~~~ The second operator for elimination is fixpoint definition. This fixpoint may involve several mutually recursive definitions. The basic 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 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 In the inference rules, we represent such a term by .. math:: \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 :math:`Ξ“_i`, namely :math:`t_i'=Ξ» Ξ“_i . t_i` and :math:`A_i'=βˆ€ Ξ“_i , A_i`. Typing rule +++++++++++ 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[Ξ“] ⊒ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i Any fixpoint definition cannot be accepted because non-normalizing terms allow proofs of absurdity. The basic scheme of recursion that should be allowed is the one needed for defining primitive recursive functionals. In that case the fixpoint enjoys a special syntactic restriction, namely one of the arguments belongs to an inductive type, the function starts with a case analysis and recursive calls are done on variables coming from patterns and representing subterms. For instance in the case of natural numbers, a proof of the induction principle of type .. math:: βˆ€ 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~\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 check that the definition is β€œguarded”. A precise analysis of this notion can be found in :cite:`Gim94`. The first stage is to precise on which argument the fixpoint will be decreasing. The type of this argument should be an inductive type. For doing this, the syntax of fixpoints is extended and becomes .. math:: \Fix~f_i\{f_1/k_1 :A_1:=t_1 … f_n/k_n :A_n:=t_n\} 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. 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 syntactically recognized as structurally smaller than :math:`y_{k_i}`. 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_m :T_m,~(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:`(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 type :math:`I_p` part of the inductive definition 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_m :B_m ,~(I_p~p_1 … p_r~t_1 … t_s )` and can consequently be written :math:`Ξ» y_1 :B_1' .~… Ξ» y_m :B_m'.~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 :math:`y`. The following definitions are correct, we enter them using the :cmd:`Fixpoint` command and show the internal representation. .. example:: .. rocqtop:: all Fixpoint plus (n m:nat) {struct n} : nat := match n with | O => m | S p => S (plus p m) end. Print plus. Fixpoint lgth (A:Set) (l:list A) {struct l} : nat := match l with | nil _ => O | cons _ a l' => S (lgth A l') end. Print lgth. Fixpoint sizet (t:tree) : nat := let (f) := t in S (sizef f) with sizef (f:forest) : nat := match f with | emptyf => O | consf t f => plus (sizet t) (sizef f) end. Print sizet. .. _Reduction-rule: Reduction rule ++++++++++++++ Let :math:`F` be the set of declarations: :math:`f_1 /k_1 :A_1 :=t_1 …f_n /k_n :A_n:=t_n`. 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} when the structural argument :math:`a_{k_i}` starts with a constructor. This last restriction is needed in order to keep strong normalization and corresponds to the reduction for primitive recursive operators. The following reductions are now possible: .. math:: :nowrap: \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: **Mutual induction** The principles of mutual induction can be automatically generated using the Scheme command described in Section :ref:`proofschemes-induction-principles`. rocq-9.2.0/doc/sphinx/language/core/modules.rst000066400000000000000000001073041516144147600214770ustar00rootroot00000000000000.. _themodulesystem: The Module System ================= The module system extends the Calculus of Inductive Constructions providing a convenient way to structure large developments as well as a means of massive abstraction. Modules and module types ---------------------------- **Access path.** An access path is denoted by :math:`p` and can be either a module variable :math:`X` or, if :math:`pβ€²` is an access path and :math:`id` an identifier, then :math:`pβ€².id` is an access path. **Structure element.** A structure element is denoted by :math:`e` and is either a definition of a :term:`constant`, an assumption, a definition of an inductive, a definition of a module, an alias of a module or a module type abbreviation. **Structure expression.** A structure expression is denoted by :math:`S` and can be: + an access path :math:`p` + a plain structure :math:`\Struct~e ; … ; e~\End` + a functor :math:`\Functor(X:S)~Sβ€²`, where :math:`X` is a module variable, :math:`S` and :math:`Sβ€²` are structure expressions + an application :math:`S~p`, where :math:`S` is a structure expression and :math:`p` an access path + a refined structure :math:`S~\with~p := pβ€²` or :math:`S~\with~p := t:T` where :math:`S` is a structure expression, :math:`p` and :math:`pβ€²` are access paths, :math:`t` is a term and :math:`T` is the type of :math:`t`. **Module definition.** A module definition is written :math:`\Mod{X}{S}{S'}` and consists of a module variable :math:`X`, a module type :math:`S` which can be any structure expression and optionally a module implementation :math:`Sβ€²` which can be any structure expression except a refined structure. **Module alias.** A module alias is written :math:`\ModA{X}{p}` and consists of a module variable :math:`X` and a module path :math:`p`. **Module type abbreviation.** A module type abbreviation is written :math:`\ModType{Y}{S}`, where :math:`Y` is an identifier and :math:`S` is any structure expression . .. extracted from Gallina extensions chapter Using modules ------------- The module system provides a way of packaging related elements together, as well as a means of massive abstraction. .. cmd:: Module {? {| Import | Export } {? @import_categories } } @ident {* @module_binder } {? @of_module_type } {? := {+<+ @module_expr_inl } } .. insertprodn module_binder module_expr_inl .. prodn:: module_binder ::= ( {? {| Import | Export } {? @import_categories } } {+ @ident } : @module_type_inl ) module_type_inl ::= ! @module_type | @module_type {? @functor_app_annot } functor_app_annot ::= [ inline at level @natural ] | [ no inline ] module_type ::= @qualid | ( @module_type ) | @module_type @module_expr_atom | @module_type with @with_declaration with_declaration ::= Definition @qualid {? @univ_decl } := @term | Module @qualid := @qualid module_expr_atom ::= @qualid | ( @module_expr_atom ) of_module_type ::= : @module_type_inl | {* <: @module_type_inl } module_expr_inl ::= ! {+ @module_expr_atom } | {+ @module_expr_atom } {? @functor_app_annot } Defines a module named :token:`ident`. See the examples :ref:`here`. The :n:`Import` and :n:`Export` flags specify whether the module should be automatically imported or exported. Specifying :n:`{* @module_binder }` starts a functor with parameters given by the :n:`@module_binder`\s. (A *functor* is a function from modules to modules.) :n:`@of_module_type` specifies the module type. :n:`{+ <: @module_type_inl }` starts a module that satisfies each :n:`@module_type_inl`. .. todo: would like to find a better term than "interactive", not very descriptive :n:`:= {+<+ @module_expr_inl }` specifies the body of a module or functor definition. If it's not specified, then the module is defined *interactively*, meaning that the module is defined as a series of commands terminated with :cmd:`End` instead of in a single :cmd:`Module` command. Interactively defining the :n:`@module_expr_inl`\s in a series of :cmd:`Include` commands is equivalent to giving them all in a single non-interactive :cmd:`Module` command. .. opt:: Inline Level Controls inlining of parameters (declared by e.g. :cmd:`Axiom`) in functor application. The default is 100. A functor application with `[inline at level A]` will inline all parameters declared with `Inline(B)` with `B <= A`. :cmd:`Parameter` declaration with `Inline` uses the value of this option unless an explicit level is provided (with `Inline(level)`). Functor application implicitly uses `[inline at level n]` where `n` is the value of this option, unless `[inline at level]` or `[no inline]` (or the prefix `!` which is equivalent to the suffix `[no inline]`) is explicitly provided. .. cmd:: Module Type @ident {* @module_binder } {* <: @module_type_inl } {? := {+<+ @module_type_inl } } Defines a module type named :n:`@ident`. See the example :ref:`here`. Specifying :n:`{* @module_binder }` starts a functor type with parameters given by the :n:`@module_binder`\s. :n:`:= {+<+ @module_type_inl }` specifies the body of a module or functor type definition. If it's not specified, then the module type is defined *interactively*, meaning that the module type is defined as a series of commands terminated with :cmd:`End` instead of in a single :cmd:`Module Type` command. Interactively defining the :n:`@module_type_inl`\s in a series of :cmd:`Include` commands is equivalent to giving them all in a single non-interactive :cmd:`Module Type` command. .. _terminating_module: **Terminating an interactive module or module type definition** Interactive modules are terminated with the :cmd:`End` command, which is also used to terminate :ref:`Sections`. :n:`End @ident` closes the interactive module or module type :token:`ident`. If the module type was given, the command verifies that the content of the module matches the module type. If the module is not a functor, its components (:term:`constants `, inductive types, submodules etc.) are now available through the dot notation. .. exn:: Signature components for field @ident do not match. :undocumented: .. exn:: The field @ident is missing in @qualid. :undocumented: .. |br| raw:: html
.. note:: #. Interactive modules and module types can be nested. #. Interactive modules and module types can't be defined inside of :ref:`sections`. Sections can be defined inside of interactive modules and module types. #. Hints and notations (the :ref:`Hint ` and :cmd:`Notation` commands) can also appear inside interactive modules and module types. Note that with module definitions like: :n:`Module @ident__1 : @module_type := @ident__2.` or :n:`Module @ident__1 : @module_type.` |br| :n:`Include @ident__2.` |br| :n:`End @ident__1.` hints and the like valid for :n:`@ident__1` are the ones defined in :n:`@module_type` rather then those defined in :n:`@ident__2` (or the module body). #. Within an interactive module type definition, the :cmd:`Parameter` command declares a :term:`constant` instead of definining a new axiom (which it does when not in a module type definition). #. Assumptions such as :cmd:`Axiom` that include the :n:`Inline` clause will be automatically expanded when the functor is applied, except when the function application is prefixed by ``!``. .. cmd:: Include @module_type_inl {* <+ @module_type_inl } Includes the content of module(s) in the current interactive module. Here :n:`@module_type_inl` can be a module expression or a module type expression. If it is a high-order module or module type expression then the system tries to instantiate :n:`@module_type_inl` with the current interactive module. Including multiple modules in a single :cmd:`Include` is equivalent to including each module in a separate :cmd:`Include` command. .. cmd:: Include Type {+<+ @module_type_inl } .. deprecated:: 8.3 Use :cmd:`Include` instead. .. cmd:: Declare Module {? {| Import | Export } {? @import_categories } } @ident {* @module_binder } : @module_type_inl Declares a module :token:`ident` of type :token:`module_type_inl`. If :n:`@module_binder`\s are specified, declares a functor with parameters given by the list of :token:`module_binder`\s. .. cmd:: Import {? @import_categories } {+ @filtered_import } For each module name :n:`@qualid` in :n:`@filtered_import`, if :n:`@qualid` denotes a valid basic module (i.e. its module type is a signature), makes its components available by their short names. When used inside a section, the effect is local to the section. .. example:: .. rocqtop:: reset in Module Mod. Definition T:=nat. Check T. End Mod. Check Mod.T. .. rocqtop:: all Fail Check T. Import Mod. Check T. Some features defined in modules are activated only when a module is imported. This is for instance the case of notations (see :ref:`Notations`). Declarations made with the :attr:`local` attribute are never imported by the :cmd:`Import` command. Such declarations are only accessible through their fully qualified name. .. example:: .. rocqtop:: in Module A. Module B. Local Definition T := nat. End B. End A. Import A. .. rocqtop:: all fail Check B.T. .. insertprodn filtered_import filtered_import .. prodn:: filtered_import ::= @qualid {? ( {+, @qualid {? ( .. ) } } ) } Appending a module name with a parenthesized list of names will make only those names available with short names, not other names defined in the module nor will it activate other features. The names to import may be :term:`constants `, inductive types and constructors, and notation aliases (for instance, Ltac definitions cannot be selectively imported). If they are from an inner module to the one being imported, they must be prefixed by the inner path. The name of an inductive type may also be followed by ``(..)`` to import it, its constructors and its eliminators if they exist. For this purpose "eliminator" means a :term:`constant` in the same module whose name is the inductive type's name suffixed by one of ``_sind``, ``_ind``, ``_rec`` or ``_rect``. .. example:: .. rocqtop:: reset in Module A. Module B. Inductive T := C. Definition U := nat. End B. Definition Z := Prop. End A. Import A(B.T(..), Z). .. rocqtop:: all Check B.T. Check B.C. Check Z. Fail Check B.U. Check A.B.U. .. warn:: Cannot import local constant, it will be ignored. This warning is printed when a name in the list of names to import was declared as a local constant, and the name is not imported. .. insertprodn import_categories import_categories .. prodn:: import_categories ::= {? - } ( {+, @qualid } ) Putting a list of :n:`@import_categories` after ``Import`` will restrict activation of features according to those categories. Currently supported categories are: - ``coercions`` corresponding to :cmd:`Coercion`. - ``hints`` corresponding to the `Hint` commands (e.g. :cmd:`Hint Resolve` or :cmd:`Hint Rewrite`) and :ref:`typeclass ` instances. - ``canonicals`` corresponding to :cmd:`Canonical Structure`. - ``notations`` corresponding to :cmd:`Notation` (including :cmd:`Reserved Notation`), scope controls (:cmd:`Delimit Scope`, :cmd:`Bind Scope`, :cmd:`Open Scope`) but not :ref:`Abbreviations`. - ``options`` for :ref:`flags-options-tables` - ``ltac.notations`` corresponding to :cmd:`Tactic Notation`. - ``ltac2.notations`` corresponding to :cmd:`Ltac2 Notation` (including Ltac2 abbreviations). Plugins may define their own categories. .. cmd:: Export {? @import_categories } {+ @filtered_import } Similar to :cmd:`Import`, except that when the module containing this command is imported, the :n:`{+ @qualid }` are imported as well. When used in a section, the effect is not local to the section. The selective import syntax also works with Export. .. exn:: @qualid is not a module. :undocumented: .. warn:: Trying to mask the absolute name @qualid! :undocumented: .. cmd:: Print Module @qualid Prints the module type and (optionally) the body of the module :n:`@qualid`. .. cmd:: Print Module Type @qualid Prints the module type corresponding to :n:`@qualid`. .. flag:: Short Module Printing This :term:`flag` (off by default) disables the printing of the types of fields, leaving only their names, for the commands :cmd:`Print Module` and :cmd:`Print Module Type`. .. cmd:: Print Namespace @dirpath Prints the names and types of all loaded constants whose fully qualified names start with :n:`@dirpath`. For example, the command ``Print Namespace Stdlib.`` displays the names and types of all loaded constants in the standard library. The command ``Print Namespace Stdlib.Init`` only shows constants defined in one of the files in the ``Init`` directory. The command ``Print Namespace Stdlib.Init.Nat`` shows what is in the ``Nat`` library file inside the ``Init`` directory. Module names may appear in :n:`@dirpath`. .. example:: .. rocqtop:: reset in Module A. Definition foo := 0. Module B. Definition bar := 1. End B. End A. .. rocqtop:: all Print Namespace Top. Print Namespace Top.A. Print Namespace Top.A.B. .. _module_examples: Examples ~~~~~~~~ .. example:: Defining a simple module interactively .. rocqtop:: in Module M. Definition T := nat. Definition x := 0. .. rocqtop:: all Definition y : bool. exact true. .. rocqtop:: in Defined. End M. Inside a module one can define :term:`constants `, prove theorems and do anything else that can be done in the toplevel. Components of a closed module can be accessed using the dot notation: .. rocqtop:: all Print M.x. .. _example_def_simple_module_type: .. example:: Defining a simple module type interactively .. rocqtop:: in Module Type SIG. Parameter T : Set. Parameter x : T. End SIG. .. _example_filter_module: .. example:: Creating a new module that omits some items from an existing module Since :n:`SIG`, the type of the new module :n:`N`, doesn't define :n:`y` or give the body of :n:`x`, which are not included in :n:`N`. .. rocqtop:: all Module N : SIG with Definition T := nat := M. Print N.T. Print N.x. Fail Print N.y. .. reset to remove N (undo in last coqtop block doesn't seem to do that), invisibly redefine M, SIG .. rocqtop:: none reset Module M. Definition T := nat. Definition x := 0. Definition y : bool. exact true. Defined. End M. Module Type SIG. Parameter T : Set. Parameter x : T. End SIG. The definition of :g:`N` using the module type expression :g:`SIG` with :g:`Definition T := nat` is equivalent to the following one: .. rocqtop:: in Module Type SIG'. Definition T : Set := nat. Parameter x : T. End SIG'. Module N : SIG' := M. .. exn:: No field named @ident in @qualid. Raised when the final :n:`@ident` in the left-hand side :n:`@qualid` of a :n:`@with_declaration` is applied to a module type :n:`@qualid` that has no field named this :n:`@ident`. If we just want to be sure that our implementation satisfies a given module type without restricting the interface, we can use a transparent constraint .. rocqtop:: in Module P <: SIG := M. .. rocqtop:: all Print P.y. .. example:: Creating a functor (a module with parameters) .. rocqtop:: in Module Two (X Y: SIG). Definition T := (X.T * Y.T)%type. Definition x := (X.x, Y.x). End Two. and apply it to our modules and do some computations: .. rocqtop:: in Module Q := Two M N. .. rocqtop:: all Eval compute in (fst Q.x + snd Q.x). .. example:: A module type with two sub-modules, sharing some fields .. rocqtop:: in Module Type SIG2. Declare Module M1 : SIG. Module M2 <: SIG. Definition T := M1.T. Parameter x : T. End M2. End SIG2. .. rocqtop:: in Module Mod <: SIG2. Module M1. Definition T := nat. Definition x := 1. End M1. Module M2 := M. End Mod. Notice that ``M`` is a correct body for the component ``M2`` since its ``T`` component is ``nat`` as specified for ``M1.T``. .. extracted from Gallina extensions chapter .. _qualified-names: Qualified names --------------- Qualified names (:token:`qualid`\s) are hierarchical names that are used to identify items such as definitions, theorems and parameters that may be defined inside modules (see :cmd:`Module`). In addition, they are used to identify compiled files. Syntactically, they have this form: .. insertprodn qualid qualid .. prodn:: qualid ::= @ident {* .@ident } *Fully qualified* or *absolute* qualified names uniquely identify files (as in the `Require` command) and items within files, such as a single :cmd:`Variable` definition. It's usually possible to use a suffix of the fully qualified name (a *short name*) that uniquely identifies an item. The first part of a fully qualified name identifies a file, which may be followed by a second part that identifies a specific item within that file. Qualified names that identify files don't have a second part. While qualified names always consist of a series of dot-separated :n:`@ident`\s, *the following few paragraphs omit the dots for the sake of simplicity.* **File part.** Files are identified by :gdef:`logical paths `, which are prefixes in the form :n:`{* @ident__logical } {+ @ident__file }`, such as :n:`Stdlib.Init.Logic`, in which: - :n:`{* @ident__logical }`, the :gdef:`logical name`, maps to one or more directories (or :gdef:`physical paths `) in the user's file system. The logical name is used so that Rocq scripts don't depend on where files are installed. For example, the directory associated with :n:`Stdlib` contains Rocq's standard library. The logical name is generally a single :n:`@ident`. - :n:`{+ @ident__file }` corresponds to the file system path of the file relative to the directory that contains it. For example, :n:`Init.Logic` corresponds to the file system path :n:`Init/Logic.v` on Linux) When Rocq is processing a script that hasn't been saved in a file, such as a new buffer in RocqIDE or anything in `rocq repl`, definitions in the script are associated with the logical name :n:`Top` and there is no associated file system path. **Item part.** Items are further qualified by a suffix in the form :n:`{* @ident__module } @ident__base` in which: - :n:`{* @ident__module }` gives the names of the nested modules, if any, that syntactically contain the definition of the item. (See :cmd:`Module`.) - :n:`@ident__base` is the base name used in the command defining the item. For example, :n:`eq` in the :cmd:`Inductive` command defining it in `Stdlib.Init.Logic` is the base name for `Stdlib.Init.Logic.eq`, the standard library definition of :term:`Leibniz equality`. If :n:`@qualid` is the fully qualified name of an item, Rocq always interprets :n:`@qualid` as a reference to that item. If :n:`@qualid` is also a partially qualified name for another item, then you must provide a more-qualified name to uniquely identify that other item. For example, if there are two fully qualified items named `Foo.Bar` and `Stdlib.X.Foo.Bar`, then `Foo.Bar` refers to the first item and `X.Foo.Bar` is the shortest name for referring to the second item. Definitions with the :attr:`local` attribute are only accessible with their fully qualified name (see :ref:`gallina-definitions`). .. example:: .. rocqtop:: all Check 0. Definition nat := bool. Check 0. Check Datatypes.nat. Locate nat. .. seealso:: Commands :cmd:`Locate`. :ref:`logical-paths-load-path` describes how :term:`logical paths ` become associated with specific files. .. _controlling-locality-of-commands: Controlling the scope of commands with locality attributes ---------------------------------------------------------- Many commands have effects that apply only within a specific scope, typically the section or the module in which the command was called. Locality :term:`attributes ` can alter the scope of the effect. Below, we give the semantics of each locality attribute while noting a few exceptional commands for which :attr:`local` and :attr:`global` attributes are interpreted differently. .. attr:: local This :term:`attribute` limits the effect of the command to the current scope (section or module). The ``Local`` prefix is an alternative syntax for the :attr:`local` attribute (see :n:`@legacy_attr`). .. note:: - For some commands, this is the only locality supported within sections (e.g., for :cmd:`Notation`, :cmd:`Ltac` and :ref:`Hint ` commands). - For some commands, this is the default locality within sections even though other locality attributes are supported as well (e.g., for the :cmd:`Arguments` command). .. warning:: **Exception:** when :attr:`local` is applied to :cmd:`Definition`, :cmd:`Theorem` or their variants, its semantics are different: it makes the defined objects available only through their fully qualified names rather than their unqualified names after an :cmd:`Import`. .. attr:: export This :term:`attribute` makes the effect of the command persist when the section is closed and applies the effect when the module containing the command is imported. Commands supporting this attribute include :cmd:`Set`, :cmd:`Unset` and the :ref:`Hint ` commands, although the latter don't support it within sections. .. attr:: global This :term:`attribute` makes the effect of the command persist even when the current section or module is closed. Loading the file containing the command (possibly transitively) applies the effect of the command. The ``Global`` prefix is an alternative syntax for the :attr:`global` attribute (see :n:`@legacy_attr`). .. warning:: **Exception:** for a few commands (like :cmd:`Notation` and :cmd:`Ltac`), this attribute behaves like :attr:`export`. .. warning:: We strongly discourage using the :attr:`global` locality attribute because the transitive nature of file loading gives the user little control. We recommend using the :attr:`export` locality attribute where it is supported. .. _visibility-attributes-modules: Summary of locality attributes in a module ------------------------------------------ This table sums up the effect of locality attributes on the scope of vernacular commands in a module, when outside the module where they were entered. In the following table: * a cross (❌) marks an unsupported attribute (compilation error); * β€œnot available” means that the command has no effect outside the :cmd:`Module` it was entered; * β€œwhen imported” means that the command has effect outside the :cmd:`Module` if, and only if, the :cmd:`Module` (or the command, via :n:`@filtered_import`) is imported (with :cmd:`Import` or :cmd:`Export`). * β€œshort name when imported” means that the command has effects outside the :cmd:`Module`; if the :cmd:`Module` (or command, via :n:`@filtered_import`) is not imported, the associated identifiers must be qualified; * β€œqualified name” means that the command has effects outside the :cmd:`Module`, but the corresponding identifier may only be referred to with a qualified name; * β€œalways” means that the command always has effects outside the :cmd:`Module` (even if it is not imported). A similar table for :cmd:`Section` can be found :ref:`here`. .. list-table:: :header-rows: 1 * - ``Command`` - no attribute - :attr:`local` - :attr:`export` - :attr:`global` * - :cmd:`Definition`, :cmd:`Lemma`, :cmd:`Axiom`, ... - :attr:`global` - qualified name - ❌ - short name when imported * - :cmd:`Ltac` - :attr:`global` - not available - ❌ - short name when imported * - :cmd:`Ltac2` - :attr:`global` - not available - ❌ - short name when imported * - :cmd:`Abbreviation` - :attr:`global` - not available - ❌ - short name when imported * - :cmd:`Notation` - :attr:`global` - not available - ❌ - when imported * - :cmd:`Tactic Notation` - :attr:`global` - not available - ❌ - when imported * - :cmd:`Ltac2 Notation` - :attr:`global` - not available - ❌ - when imported * - :cmd:`Coercion` - :attr:`global` - not available - ❌ - when imported * - :cmd:`Canonical Structure` - :attr:`global` - when imported - ❌ - when imported * - ``Hints`` (and :cmd:`Instance`) - :attr:`export` - not available - when imported - always * - :cmd:`Set` or :cmd:`Unset` a flag - :attr:`local` - not available - when imported - always Typing Modules ------------------ In order to introduce the typing system we first slightly extend the syntactic class of terms and environments given in section :ref:`The-terms`. The environments, apart from definitions of :term:`constants ` and inductive types now also hold any other structure elements. Terms, apart from variables, :term:`constants ` and complex terms, also include access paths. We also need additional typing judgments: + :math:`\WFT{E}{S}`, denoting that a structure :math:`S` is well-formed, + :math:`\WTM{E}{p}{S}`, denoting that the module pointed by :math:`p` has type :math:`S` in the global environment :math:`E`. + :math:`\WEV{E}{S}{\ovl{S}}`, denoting that a structure :math:`S` is evaluated to a structure :math:`\ovl{S}` in weak head normal form. + :math:`\WS{E}{S_1}{S_2}` , denoting that a structure :math:`S_1` is a subtype of a structure :math:`S_2`. + :math:`\WS{E}{e_1}{e_2}` , denoting that a structure element :math:`e_1` is more precise than a structure element :math:`e_2`. The rules for forming structures are the following: .. inference:: WF-STR \WF{E;Eβ€²}{} ------------------------ \WFT{E}{ \Struct~Eβ€² ~\End} .. inference:: WF-FUN \WFT{E; \ModS{X}{S}}{ \ovl{Sβ€²} } -------------------------- \WFT{E}{ \Functor(X:S)~Sβ€²} Evaluation of structures to weak head normal form: .. inference:: WEVAL-APP \begin{array}{c} \WEV{E}{S}{\Functor(X:S_1 )~S_2}~~~~~\WEV{E}{S_1}{\ovl{S_1}} \\ \WTM{E}{p}{S_3}~~~~~ \WS{E}{S_3}{\ovl{S_1}} \end{array} -------------------------- \WEV{E}{S~p}{\subst{S_2}{X}{p}} .. inference:: WEVAL-WITH-MOD \begin{array}{c} E[] ⊒ S \lra \Struct~e_1 ;…;e_i ; \ModS{X}{S_1 };e_{i+2} ;… ;e_n ~\End \\ E;e_1 ;…;e_i [] ⊒ S_1 \lra \ovl{S_1} ~~~~~~ E[] ⊒ p : S_2 \\ E;e_1 ;…;e_i [] ⊒ S_2 <: \ovl{S_1} \end{array} ---------------------------------- \begin{array}{c} \WEV{E}{S~\with~X := p}{}\\ \Struct~e_1 ;…;e_i ; \ModA{X}{p};\subst{e_{i+2}}{X}{p} ;…;\subst{e_n}{X}{p} ~\End \end{array} .. inference:: WEVAL-WITH-MOD-REC \begin{array}{c} \WEV{E}{S}{\Struct~e_1 ;…;e_i ; \ModS{X_1}{S_1 };e_{i+2} ;… ;e_n ~\End} \\ \WEV{E;e_1 ;…;e_i }{S_1~\with~p := p_1}{\ovl{S_2}} \end{array} -------------------------- \begin{array}{c} \WEV{E}{S~\with~X_1.p := p_1}{} \\ \Struct~e_1 ;…;e_i ; \ModS{X}{\ovl{S_2}};\subst{e_{i+2}}{X_1.p}{p_1} ;…;\subst{e_n}{X_1.p}{p_1} ~\End \end{array} .. inference:: WEVAL-WITH-DEF \begin{array}{c} \WEV{E}{S}{\Struct~e_1 ;…;e_i ;(c:T_1);e_{i+2} ;… ;e_n ~\End} \\ \WS{E;e_1 ;…;e_i }{(c:=t:T)}{(c:T_1)} \end{array} -------------------------- \begin{array}{c} \WEV{E}{S~\with~c := t:T}{} \\ \Struct~e_1 ;…;e_i ;(c:=t:T);e_{i+2} ;… ;e_n ~\End \end{array} .. inference:: WEVAL-WITH-DEF-REC \begin{array}{c} \WEV{E}{S}{\Struct~e_1 ;…;e_i ; \ModS{X_1 }{S_1 };e_{i+2} ;… ;e_n ~\End} \\ \WEV{E;e_1 ;…;e_i }{S_1~\with~p := p_1}{\ovl{S_2}} \end{array} -------------------------- \begin{array}{c} \WEV{E}{S~\with~X_1.p := t:T}{} \\ \Struct~e_1 ;…;e_i ; \ModS{X}{\ovl{S_2} };e_{i+2} ;… ;e_n ~\End \end{array} .. inference:: WEVAL-PATH-MOD1 \begin{array}{c} \WEV{E}{p}{\Struct~e_1 ;…;e_i ; \Mod{X}{S}{S_1};e_{i+2} ;… ;e_n ~\End} \\ \WEV{E;e_1 ;…;e_i }{S}{\ovl{S}} \end{array} -------------------------- E[] ⊒ p.X \lra \ovl{S} .. inference:: WEVAL-PATH-MOD2 \WF{E}{} \Mod{X}{S}{S_1}∈ E \WEV{E}{S}{\ovl{S}} -------------------------- \WEV{E}{X}{\ovl{S}} .. inference:: WEVAL-PATH-ALIAS1 \begin{array}{c} \WEV{E}{p}{~\Struct~e_1 ;…;e_i ; \ModA{X}{p_1};e_{i+2} ;… ;e_n ~\End} \\ \WEV{E;e_1 ;…;e_i }{p_1}{\ovl{S}} \end{array} -------------------------- \WEV{E}{p.X}{\ovl{S}} .. inference:: WEVAL-PATH-ALIAS2 \WF{E}{} \ModA{X}{p_1 }∈ E \WEV{E}{p_1}{\ovl{S}} -------------------------- \WEV{E}{X}{\ovl{S}} .. inference:: WEVAL-PATH-TYPE1 \begin{array}{c} \WEV{E}{p}{~\Struct~e_1 ;…;e_i ; \ModType{Y}{S};e_{i+2} ;… ;e_n ~\End} \\ \WEV{E;e_1 ;…;e_i }{S}{\ovl{S}} \end{array} -------------------------- \WEV{E}{p.Y}{\ovl{S}} .. inference:: WEVAL-PATH-TYPE2 \WF{E}{} \ModType{Y}{S}∈ E \WEV{E}{S}{\ovl{S}} -------------------------- \WEV{E}{Y}{\ovl{S}} Rules for typing module: .. inference:: MT-EVAL \WEV{E}{p}{\ovl{S}} -------------------------- E[] ⊒ p : \ovl{S} .. inference:: MT-STR E[] ⊒ p : S -------------------------- E[] ⊒ p : S/p The last rule, called strengthening is used to make all module fields manifestly equal to themselves. The notation :math:`S/p` has the following meaning: + if :math:`S\lra~\Struct~e_1 ;…;e_n ~\End` then :math:`S/p=~\Struct~e_1 /p;…;e_n /p ~\End` where :math:`e/p` is defined as follows (note that opaque definitions are processed as assumptions): + :math:`(c:=t:T)/p = (c:=t:T)` + :math:`(c:U)/p = (c:=p.c:U)` + :math:`\ModS{X}{S}/p = \ModA{X}{p.X}` + :math:`\ModA{X}{pβ€²}/p = \ModA{X}{pβ€²}` + :math:`\ind{r}{Ξ“_I}{Ξ“_C}/p = \Indp{r}{Ξ“_I}{Ξ“_C}{p}` + :math:`\Indpstr{r}{Ξ“_I}{Ξ“_C}{p'}{p} = \Indp{r}{Ξ“_I}{Ξ“_C}{p'}` + if :math:`S \lra \Functor(X:Sβ€²)~Sβ€³` then :math:`S/p=S` The notation :math:`\Indp{r}{Ξ“_I}{Ξ“_C}{p}` denotes an inductive definition that is definitionally equal to the inductive definition in the module denoted by the path :math:`p`. All rules which have :math:`\ind{r}{Ξ“_I}{Ξ“_C}` as premises are also valid for :math:`\Indp{r}{Ξ“_I}{Ξ“_C}{p}`. We give the formation rule for :math:`\Indp{r}{Ξ“_I}{Ξ“_C}{p}` below as well as the equality rules on inductive types and constructors. The module subtyping rules: .. inference:: MSUB-STR \begin{array}{c} \WS{E;e_1 ;…;e_n }{e_{Οƒ(i)}}{e'_i ~\for~ i=1..m} \\ Οƒ : \{1… m\} β†’ \{1… n\} ~\injective \end{array} -------------------------- \WS{E}{\Struct~e_1 ;…;e_n ~\End}{~\Struct~e'_1 ;…;e'_m ~\End} .. inference:: MSUB-FUN \WS{E}{\ovl{S_1'}}{\ovl{S_1}} \WS{E; \ModS{X}{S_1'}}{\ovl{S_2}}{\ovl{S_2'}} -------------------------- E[] ⊒ \Functor(X:S_1 ) S_2 <: \Functor(X:S_1') S_2' Structure element subtyping rules: .. inference:: ASSUM-ASSUM E[] ⊒ T_1 ≀_{βδι΢η} T_2 -------------------------- \WS{E}{(c:T_1)}{(c:T_2)} .. inference:: DEF-ASSUM E[] ⊒ T_1 ≀_{βδι΢η} T_2 -------------------------- \WS{E}{(c:=t:T_1)}{(c:T_2)} .. inference:: ASSUM-DEF E[] ⊒ T_1 ≀_{βδι΢η} T_2 E[] ⊒ c =_{βδι΢η} t_2 -------------------------- \WS{E}{(c:T_1)}{(c:=t_2:T_2)} .. inference:: DEF-DEF E[] ⊒ T_1 ≀_{βδι΢η} T_2 E[] ⊒ t_1 =_{βδι΢η} t_2 -------------------------- \WS{E}{(c:=t_1:T_1)}{(c:=t_2:T_2)} .. inference:: IND-IND E[] ⊒ Ξ“_I =_{βδι΢η} Ξ“_I' E[Ξ“_I] ⊒ Ξ“_C =_{βδι΢η} Ξ“_C' -------------------------- \WS{E}{\ind{r}{Ξ“_I}{Ξ“_C}}{\ind{r}{Ξ“_I'}{Ξ“_C'}} .. inference:: INDP-IND E[] ⊒ Ξ“_I =_{βδι΢η} Ξ“_I' E[Ξ“_I] ⊒ Ξ“_C =_{βδι΢η} Ξ“_C' -------------------------- \WS{E}{\Indp{r}{Ξ“_I}{Ξ“_C}{p}}{\ind{r}{Ξ“_I'}{Ξ“_C'}} .. inference:: INDP-INDP E[] ⊒ Ξ“_I =_{βδι΢η} Ξ“_I' E[Ξ“_I] ⊒ Ξ“_C =_{βδι΢η} Ξ“_C' E[] ⊒ p =_{βδι΢η} p' -------------------------- \WS{E}{\Indp{r}{Ξ“_I}{Ξ“_C}{p}}{\Indp{r}{Ξ“_I'}{Ξ“_C'}{p'}} .. inference:: MOD-MOD \WS{E}{S_1}{S_2} -------------------------- \WS{E}{\ModS{X}{S_1 }}{\ModS{X}{S_2 }} .. inference:: ALIAS-MOD E[] ⊒ p : S_1 \WS{E}{S_1}{S_2} -------------------------- \WS{E}{\ModA{X}{p}}{\ModS{X}{S_2 }} .. inference:: MOD-ALIAS E[] ⊒ p : S_2 \WS{E}{S_1}{S_2} E[] ⊒ X =_{βδι΢η} p -------------------------- \WS{E}{\ModS{X}{S_1 }}{\ModA{X}{p}} .. inference:: ALIAS-ALIAS E[] ⊒ p_1 =_{βδι΢η} p_2 -------------------------- \WS{E}{\ModA{X}{p_1 }}{\ModA{X}{p_2 }} .. inference:: MODTYPE-MODTYPE \WS{E}{S_1}{S_2} \WS{E}{S_2}{S_1} -------------------------- \WS{E}{\ModType{Y}{S_1 }}{\ModType{Y}{S_2 }} New environment formation rules .. inference:: WF-MOD1 \WF{E}{} \WFT{E}{S} -------------------------- \WF{E; \ModS{X}{S}}{} .. inference:: WF-MOD2 \WS{E}{S_2}{S_1} \WF{E}{} \WFT{E}{S_1} \WFT{E}{S_2} -------------------------- \WF{E; \ModImp{X}{S_1}{S_2}}{} .. inference:: WF-ALIAS \WF{E}{} E[] ⊒ p : S -------------------------- \WF{E; \ModA{X}{p}}{} .. inference:: WF-MODTYPE \WF{E}{} \WFT{E}{S} -------------------------- \WF{E; \ModType{Y}{S}}{} .. inference:: WF-IND \begin{array}{c} \WF{E;\ind{r}{Ξ“_I}{Ξ“_C}}{} \\ E[] ⊒ p:~\Struct~e_1 ;…;e_n ;\ind{r}{Ξ“_I'}{Ξ“_C'};… ~\End \\ E[] ⊒ \ind{r}{Ξ“_I'}{Ξ“_C'} <: \ind{r}{Ξ“_I}{Ξ“_C} \end{array} -------------------------- \WF{E; \Indp{r}{Ξ“_I}{Ξ“_C}{p} }{} Component access rules .. inference:: ACC-TYPE1 E[Ξ“] ⊒ p :~\Struct~e_1 ;…;e_i ;(c:T);… ~\End -------------------------- E[Ξ“] ⊒ p.c : T .. inference:: ACC-TYPE2 E[Ξ“] ⊒ p :~\Struct~e_1 ;…;e_i ;(c:=t:T);… ~\End -------------------------- E[Ξ“] ⊒ p.c : T Notice that the following rule extends the delta rule defined in section :ref:`Conversion-rules` .. inference:: ACC-DELTA E[Ξ“] ⊒ p :~\Struct~e_1 ;…;e_i ;(c:=t:U);… ~\End -------------------------- E[Ξ“] ⊒ p.c \triangleright_Ξ΄ t In the rules below we assume :math:`Ξ“_P` is :math:`[p_1{:}P_1 ; …; p_r {:}P_r ]`, :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 ]`. .. inference:: ACC-IND1 E[Ξ“] ⊒ p :~\Struct~e_1 ;…;e_i ;\ind{r}{Ξ“_I}{Ξ“_C};… ~\End -------------------------- E[Ξ“] ⊒ p.I_j : βˆ€ Ξ“_P, A_j .. inference:: ACC-IND2 E[Ξ“] ⊒ p :~\Struct~e_1 ;…;e_i ;\ind{r}{Ξ“_I}{Ξ“_C};… ~\End -------------------------- E[Ξ“] ⊒ p.c_m : βˆ€ Ξ“_P, C_m .. inference:: ACC-INDP1 E[] ⊒ p :~\Struct~e_1 ;…;e_i ; \Indp{r}{Ξ“_I}{Ξ“_C}{p'} ;… ~\End -------------------------- E[] ⊒ p.I_i \triangleright_Ξ΄ p'.I_i .. inference:: ACC-INDP2 E[] ⊒ p :~\Struct~e_1 ;…;e_i ; \Indp{r}{Ξ“_I}{Ξ“_C}{p'} ;… ~\End -------------------------- E[] ⊒ p.c_i \triangleright_Ξ΄ p'.c_i rocq-9.2.0/doc/sphinx/language/core/primitive.rst000066400000000000000000000222711516144147600220360ustar00rootroot00000000000000.. _primitive-objects: Primitive objects ================= .. _primitive-integers: Primitive Integers ------------------ The language of terms features 63-bit machine integers as values. The type of such a value is *axiomatized*; it is declared through the following sentence (excerpt from the :g:`PrimInt63` module): .. rocqdoc:: Primitive int := #int63_type. This type can be understood as representing either unsigned or signed integers, depending on which module is imported or, more generally, which scope is open. :g:`Uint63` and :g:`uint63_scope` refer to the unsigned version, while :g:`Sint63` and :g:`sint63_scope` refer to the signed one. The :g:`PrimInt63` module declares the available operators for this type. For instance, equality of two unsigned primitive integers can be determined using the :g:`Uint63.eqb` function, declared and specified as follows: .. rocqdoc:: Primitive eqb := #int63_eq. Notation "m '==' n" := (eqb m n) (at level 70, no associativity) : uint63_scope. Axiom eqb_correct : forall i j, (i == j)%uint63 = true -> i = j. The complete set of such operators can be found in the :g:`PrimInt63` module. The specifications and notations are in the :g:`Uint63` and :g:`Sint63` modules. These primitive declarations are regular axioms. As such, they must be trusted and are listed by the :g:`Print Assumptions` command, as in the following example. .. rocqtop:: in reset From Corelib Require Import PrimInt63 Uint63Axioms. Lemma one_minus_one_is_zero : (sub 1 1 = 0)%uint63. Proof. apply eqb_correct; vm_compute; reflexivity. Qed. .. rocqtop:: all Print Assumptions one_minus_one_is_zero. The reduction machines implement dedicated, efficient rules to reduce the applications of these primitive operations. The extraction of these primitives can be customized similarly to the extraction of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlInt63` module can be used when extracting to OCaml: it maps the Rocq primitives to types and functions of a :g:`Uint63` module (including signed functions for :g:`Sint63` despite the name). That OCaml module is not produced by extraction. Instead, it has to be provided by the user (if they want to compile or execute the extracted code). For instance, an implementation of this module can be taken from the kernel of Rocq. Literal values (at type :g:`Uint63.int`) are extracted to literal OCaml values wrapped into the :g:`Uint63.of_int` (resp.Β :g:`Uint63.of_int64`) constructor on 64-bit (resp.Β 32-bit) platforms. Currently, this cannot be customized (see the function :g:`Uint63.compile` from the kernel). .. _primitive-floats: Primitive Floats ---------------- The language of terms features Binary64 floating-point numbers as values. The type of such a value is *axiomatized*; it is declared through the following sentence (excerpt from the :g:`PrimFloat` module): .. rocqdoc:: Primitive float := #float64_type. This type is equipped with a few operators, that must be similarly declared. For instance, the product of two primitive floats can be computed using the :g:`PrimFloat.mul` function, declared and specified as follows: .. rocqdoc:: Primitive mul := #float64_mul. Notation "x * y" := (mul x y) : float_scope. Axiom mul_spec : forall x y, Prim2SF (x * y)%float = SF64mul (Prim2SF x) (Prim2SF y). where :g:`Prim2SF` is defined in the :g:`FloatOps` module. These primitive declarations are regular axioms. As such, they must be trusted, and are listed by the :g:`Print Assumptions` command. The reduction machines (:tacn:`vm_compute`, :tacn:`native_compute`) implement dedicated, efficient rules to reduce the applications of these primitive operations, using the floating-point processor operators that are assumed to comply with the IEEE 754 standard for floating-point arithmetic. The extraction of these primitives can be customized similarly to the extraction of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlFloats` module can be used when extracting to OCaml: it maps the Rocq primitives to types and functions of a :g:`Float64` module. Said OCaml module is not produced by extraction. Instead, it has to be provided by the user (if they want to compile or execute the extracted code). For instance, an implementation of this module can be taken from the kernel of Rocq. Literal values (of type :g:`Float64.t`) are extracted to literal OCaml values (of type :g:`float`) written in hexadecimal notation and wrapped into the :g:`Float64.of_float` constructor, e.g.: :g:`Float64.of_float (0x1p+0)`. .. flag:: Printing Float When off, primitive floats use a low level hexadecimal representation. On by default. .. _primitive-arrays: Primitive Arrays ---------------- The language of terms features persistent arrays as values. The type of such a value is *axiomatized*; it is declared through the following sentence (excerpt from the :g:`PArray` module): .. rocqdoc:: Primitive array := #array_type. This type is equipped with a few operators, that must be similarly declared. For instance, elements in an array can be accessed and updated using the :g:`PArray.get` and :g:`PArray.set` functions, declared and specified as follows: .. rocqdoc:: Primitive get := #array_get. Primitive set := #array_set. Notation "t .[ i ]" := (get t i). Notation "t .[ i <- a ]" := (set t i a). Axiom get_set_same : forall A t i (a:A), (i < length t) = true -> t.[i<-a].[i] = a. Axiom get_set_other : forall A t i j (a:A), i <> j -> t.[i<-a].[j] = t.[j]. The rest of these operators can be found in the :g:`PArray` module. These primitive declarations are regular axioms. As such, they must be trusted and are listed by the :g:`Print Assumptions` command. The reduction machines (:tacn:`vm_compute`, :tacn:`native_compute`) implement dedicated, efficient rules to reduce the applications of these primitive operations. The extraction of these primitives can be customized similarly to the extraction of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlPArray` module can be used when extracting to OCaml: it maps the Rocq primitives to types and functions of a :g:`Parray` module. Said OCaml module is not produced by extraction. Instead, it has to be provided by the user (if they want to compile or execute the extracted code). For instance, an implementation of this module can be taken from the kernel of Rocq (see ``kernel/parray.ml``). Rocq's primitive arrays are persistent data structures. Semantically, a set operation ``t.[i <- a]`` represents a new array that has the same values as ``t``, except at position ``i`` where its value is ``a``. The array ``t`` still exists, can still be used and its values were not modified. Operationally, the implementation of Rocq's primitive arrays is optimized so that the new array ``t.[i <- a]`` does not copy all of ``t``. The details are in section 2.3 of :cite:`ConchonFilliatre07wml`. In short, the implementation keeps one version of ``t`` as an OCaml native array and other versions as lists of modifications to ``t``. Accesses to the native array version are constant time operations. However, accesses to versions where all the cells of the array are modified have O(n) access time, the same as a list. The version that is kept as the native array changes dynamically upon each get and set call: the current list of modifications is applied to the native array and the lists of modifications of the other versions are updated so that they still represent the same values. .. _primitive-string: Primitive (Byte-Based) Strings ------------------------------ The language of terms supports immutable strings as values. Primitive strings are *axiomatized*. The type is declared through the following sentence (excerpt from the :g:`PrimString` module): .. rocqdoc:: Primitive string := #string_type. This type is equipped with functions that must be similarly declared. For example, the length of a string can be computed with :g:`PrimString.length`, and the character (i.e., byte) at a given position can be obtained with :g:`PrimString.get`. These functions are defined as follows: .. rocqdoc:: Definition char63 := int. Primitive length : string -> int := #string_length. Primitive get : string -> int -> char63 := #string_get. The remaining primitives can be found in the :g:`PrimString` module. These primitive declarations are regular axioms. As such, they must be trusted and are listed by the :g:`Print Assumptions` command. The reduction machines (:tacn:`vm_compute`, :tacn:`native_compute`) implement dedicated, efficient rules to reduce the applications of these primitive operations. The extraction of these primitives can be customized similarly to the extraction of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlPString` module can be used when extracting to OCaml: it maps the Rocq primitives to types and functions of a :g:`Pstring` module. Said OCaml module is not produced by extraction. Instead, it has to be provided by the user (if they want to compile or execute the extracted code). For instance, an implementation of this module can be taken from the kernel of Rocq (see ``kernel/pstring.ml``). Literal values (of type :g:`Pstring.t`, or equivalently :g:`string`) are extracted to literal OCaml values (of type :g:`string`). rocq-9.2.0/doc/sphinx/language/core/records.rst000066400000000000000000000471701516144147600214740ustar00rootroot00000000000000.. _record-types: Record types ------------ The :cmd:`Record` command defines types similar to :gdef:`records` in programming languages. Those types describe tuples whose components, called :gdef:`fields `, can be accessed with :gdef:`projections `. Records can also be used to describe mathematical structures, such as groups or rings, hence the synonym :cmd:`Structure`. Defining record types ~~~~~~~~~~~~~~~~~~~~~ .. _record_grammar: .. cmd:: {| Record | Structure } @record_definition :name: Record; Structure .. insertprodn record_definition of_type_inst .. prodn:: record_definition ::= {? > } @ident_decl {* @binder } {? : @sort } {? := {? @ident } %{ {? {+; @record_field } {? ; } } %} {? as @ident } } record_field ::= {* #[ {+, @attribute } ] } @name {? @field_spec } {? %| @natural } {? @decl_notations } field_spec ::= {* @binder } @of_type_inst | {* @binder } := @term | {* @binder } @of_type_inst := @term of_type_inst ::= {| : | :> | :: | ::> } @type Defines a non-recursive record type, creating projections for each field that has a name other than `_`. The field body and type can depend on previous fields, so the order of fields in the definition may matter. Use the :cmd:`Inductive` and :cmd:`CoInductive` commands to define recursive (inductive or coinductive) records. These commands also permit defining mutually recursive records provided that all of the types in the block are records. These commands automatically generate induction schemes. Enable the :flag:`Nonrecursive Elimination Schemes` flag to enable automatic generation of elimination schemes for :cmd:`Record`. See :ref:`proofschemes-induction-principles`. The :cmd:`Class` command can be used to define records that are also :ref:`typeclasses`, which permit Rocq to automatically infer the inhabitants of the record. :n:`{? > }` If specified, the constructor is declared as a coercion from the class of the last field type to the record name. See :ref:`coercions`. :n:`@ident_decl` The :n:`@ident` within is the record name. :n:`{* @binder }` :n:`@binder`\s may be used to declare the :term:`inductive parameters ` of the record. :n:`: @sort` The sort the record belongs to. The default is :n:`Type`. :n:`:= {? @ident }` :n:`@ident` is the name of the record constructor. If omitted, the name defaults to :n:`Build_@ident` where :n:`@ident` is the record name. :n:`as {? @ident}` Specifies the name used to refer to the argument corresponding to the record in the type of projections. If not specified, the name is the first letter of the record name converted to lowercase (see :ref:`example `). In constrast, :cmd:`Class` command uses the record name as the default (see :ref:`example `). In :n:`@record_field`: :n:`@attribute`, if specified, can only be :attr:`canonical`. :n:`@name` is the field name. Since field names define projections, you can't reuse the same field name in two different records in the same module. This :ref:`example ` shows how to reuse the same field name in multiple records. :n:`@field_spec` can be omitted only when the type of the field can be inferred from other fields. For example: the type of :n:`n` can be inferred from :n:`npos` in :n:`Record positive := { n; npos : 0 < n }`. :n:`| @natural` Specifies the priority of the field. It is only allowed in :cmd:`Class` commands. :n:`{? @decl_notations }` Defines notations that are active in subsequent fields, not in the field itself, until the end of the :cmd:`Record` (see :ref:`example `). Note that :g:`where` clauses cannot be added at the record level. - :n:`{+ @binder } : @of_type_inst` is equivalent to :n:`: forall {+ @binder } , @of_type_inst` - :n:`{+ @binder } := @term` is equivalent to :n:`:= fun {+ @binder } => @term` - :n:`{+ @binder } @of_type_inst := @term` is equivalent to :n:`: forall {+ @binder } , @of_type_inst := fun {+ @binder } => @term` :n:`:= @term`, if present, gives the value of the field, which may depend on the fields that appear before it. Since their values are already defined, such fields cannot be specified when constructing a record. :n:`:` Specifies the type of the field. :n:`:>` If specified, the field is declared as a coercion from the record name to the class of the field type. See :ref:`coercions`. :n:`::` If specified, the field is declared a typeclass instance of the class of the field type. See :ref:`typeclasses`. :n:`::>` Acts as a combination of :n:`::` and :n:`:>`. The :cmd:`Record` command supports the :attr:`universes(polymorphic)`, :attr:`universes(template)`, :attr:`universes(cumulative)`, :attr:`private(matching)` and :attr:`projections(primitive)` attributes. .. example:: Defining a record The set of rational numbers may be defined as: .. rocqtop:: reset all Record Rat : Set := mkRat { negative : bool ; top : nat ; bottom : nat ; Rat_bottom_nonzero : 0 <> bottom ; Rat_irreducible : forall x y z:nat, (x * y) = top /\ (x * z) = bottom -> x = 1 }. The :n:`Rat_*` fields depend on :n:`top` and :n:`bottom`. :n:`Rat_bottom_nonzero` is a proof that :n:`bottom` (the denominator) is not zero. :n:`Rat_irreducible` is a proof that the fraction is in lowest terms. .. _reuse_field_name: .. example:: Reusing a field name in multiple records .. rocqtop:: in Module A. Record R := { f : nat }. End A. Module B. Record S := { f : nat }. End B. .. rocqtop:: all Check {| A.f := 0 |}. Check {| B.f := 0 |}. .. _record_as_clause: .. example:: Using the "as" clause in a record definition .. rocqtop:: all Record MyRecord := { myfield : nat } as VarName. About myfield. (* observe the MyRecord variable is named "VarName" *) (* make "VarName" implicit without having to rename the variable, which would be necessary without the "as" clause *) Arguments myfield {VarName}. (* make "VarName" an implicit parameter *) Check myfield. Check (myfield (VarName:={| myfield := 0 |})). .. _class_arg_name: .. example:: Argument name for a record type created using :cmd:`Class` Compare to :cmd:`Record` in the previous example: .. rocqtop:: all Class MyClass := { myfield2 : nat }. About myfield2. (* Argument name defaults to the class name and is marked implicit *) .. _record_where_clause: .. example:: Using a :g:`where` clause in a record field .. rocqtop:: all Reserved Notation "a & b" (at level 40, left associativity). Record nat_comoid := { op : nat -> nat -> nat where "a & b" := (op a b); identity : nat; identity_cond : forall n, identity & n = n; comm: forall a b, a & b = b & a; assoc: forall a b c, a & (b & c) = a & b & c }. .. exn:: Error: "where" clause not supported for records. :g:`where` clauses are only supported for :n:`@record_field`\s, not for the overall record definition. .. exn:: Records declared with the keyword Record or Structure cannot be recursive. The record name :token:`ident` appears in the type of its fields, but uses the :cmd:`Record` command. Use the :cmd:`Inductive` or :cmd:`CoInductive` command instead. .. exn:: @ident already exists The fieldname :n:`@ident` is already defined as a global. .. warn:: @ident__1 cannot be defined because the projection @ident__2 was not defined The type of the projection :n:`@ident__1` depends on previous projections which themselves could not be defined. .. warn:: @ident cannot be defined. The projection cannot be defined. This message is followed by an explanation of why it's not possible, such as: #. The :term:`body` of :token:`ident` uses an incorrect elimination for :token:`ident` (see :cmd:`Fixpoint` and :ref:`Destructors`). .. warn:: @ident__field cannot be defined because it is informative and @ident__record is not The projection for the named field :n:`@ident__field` can't be defined. For example, :n:`Record R:Prop := { f:nat }` generates the message "f cannot be defined ... and R is not". Records of sort :n:`Prop` must be non-informative (i.e. indistinguishable). Since :n:`nat` has multiple inhabitants, such as :n:`%{%| f := 0 %|%}` and :n:`%{%| f := 1 %|%}`, the record would be informative and therefore the projection can't be defined. .. seealso:: Coercions and records in section :ref:`coercions-classes-as-records`. .. todo below: Need a better description for Variant and primitive projections. Hugo says "the model to think about primitive projections is not fully stabilized". .. note:: Records exist in two flavors. In the first, a record :n:`@ident` with parameters :n:`{* @binder }`, constructor :n:`@ident__0`, and fields :n:`{* @name @field_spec }` is represented as a variant type with a single constructor: :n:`Variant @ident {* @binder } : @sort := @ident__0 {* ( @name @field_spec ) }` and projections are defined by case analysis. In the second implementation, records have primitive projections: see :ref:`primitive_projections`. During the definition of the one-constructor inductive definition, all the errors of inductive definitions, as described in Section :ref:`gallina-inductive-definitions`, may also occur. Constructing records ~~~~~~~~~~~~~~~~~~~~ .. insertprodn term_record field_val .. prodn:: term_record ::= %{%| {? {+; @field_val } {? ; } } %|%} field_val ::= @qualid {* @binder } := @term Instances of record types can be constructed using either *record form* (:n:`@term_record`, shown here) or *application form* (see :n:`@term_application`) using the constructor. The associated record definition is selected using the provided field names or constructor name, both of which are global. In the record form, the fields can be given in any order. Fields that can be inferred by unification or by using obligations (see :ref:`programs`) may be omitted. In application form, all fields of the record must be passed, in order, as arguments to the constructor. .. example:: Constructing 1/2 as a record Constructing the rational :math:`1/2` using either the record or application syntax: .. rocqtop:: in Theorem one_two_irred : forall x y z:nat, x * y = 1 /\ x * z = 2 -> x = 1. Admitted. (* Record form: top and bottom can be inferred from other fields *) Definition half := {| negative := false; Rat_bottom_nonzero := O_S 1; Rat_irreducible := one_two_irred |}. (* Application form: use the constructor and provide values for all the fields in order. "mkRat" is defined by the Record command *) Definition half' := mkRat true 1 2 (O_S 1) one_two_irred. Accessing fields (projections) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. insertprodn term_projection term_projection .. prodn:: term_projection ::= @term1 .( @qualid {? @univ_annot } {* @arg } ) | @term1 .( @ @qualid {? @univ_annot } {* @term1 } ) The value of a field can be accessed using *projection form* (:n:`@term_projection`, shown here) or with *application form* (see :n:`@term_application`) using the projection function associated with the field. Don't forget the parentheses for the projection form. Glossing over some syntactic details, the two forms are: - :n:`@qualid__record.( {? @ } @qualid__field {* @arg })`Β Β Β (projection) and - :n:`{? @ } @qualid__field {* @arg } @qualid__record`Β Β Β (application) where the :n:`@arg`\s are the parameters of the inductive type. If :n:`@` is specified, all implicit arguments must be provided. In projection form, since the projected object is part of the notation, it is always considered an explicit argument of :token:`qualid`, even if it is formally declared as implicit (see :ref:`ImplicitArguments`). .. example:: Accessing record fields .. rocqtop:: all (* projection form *) Eval compute in half.(top). (* application form *) Eval compute in top half. .. example:: Matching on records .. rocqtop:: all Eval compute in ( match half with | {| negative := false; top := n |} => n | _ => 0 end). .. example:: Accessing anonymous record fields with match .. rocqtop:: in Record T := const { _ : nat }. Definition gett x := match x with const n => n end. Definition inst := const 3. .. rocqtop:: all Eval compute in gett inst. Settings for printing records ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following settings let you control the display format for record types: .. flag:: Printing Records When this :term:`flag` is on (this is the default), use the record syntax (shown above) as the default display format. You can override the display format for specified record types by adding entries to these tables: .. table:: Printing Record @qualid This :term:`table` specifies a set of qualids which are displayed as records. Use the :cmd:`Add` and :cmd:`Remove` commands to update the set of qualids. .. table:: Printing Constructor @qualid This :term:`table` specifies a set of qualids which are displayed as constructors. Use the :cmd:`Add` and :cmd:`Remove` commands to update the set of qualids. .. flag:: Printing Projections Activates the projection form (dot notation) for printing projections (off by default). .. example:: .. rocqtop:: all Check top half. (* off: application form *) Set Printing Projections. Check top half. (* on: projection form *) .. _primitive_projections: Primitive Projections ~~~~~~~~~~~~~~~~~~~~~ Note: the design of primitive projections is still evolving. When the :flag:`Primitive Projections` flag is on or the :attr:`projections(primitive)` attribute is supplied for a :cmd:`Record` definition, its :g:`match` construct is disabled. To eliminate the record type, one must use its defined primitive projections. For compatibility, the parameters still appear when printing terms even though they are absent in the actual AST manipulated by the kernel. This can be changed by unsetting the :flag:`Printing Primitive Projection Parameters` flag. There are currently two ways to introduce primitive records types: #. Through the :cmd:`Record` command, in which case the type has to be non-recursive. The defined type enjoys eta-conversion definitionally, that is the generalized form of surjective pairing for records: `r` ``= Build_``\ `R` ``(``\ `r`\ ``.(``\ |p_1|\ ``) …`` `r`\ ``.(``\ |p_n|\ ``))``. Eta-conversion allows to define dependent elimination for these types as well. #. Through the :cmd:`Inductive` and :cmd:`CoInductive` commands, when the :term:`body` of the definition is a record declaration of the form ``Build_``\ `R` ``{`` |p_1| ``:`` |t_1|\ ``; … ;`` |p_n| ``:`` |t_n| ``}``. In this case the types can be recursive and eta-conversion is disallowed. Dependent elimination is not available for such types; you must use non-dependent case analysis for these. For both cases the :flag:`Primitive Projections` :term:`flag` must be set or the :attr:`projections(primitive)` :term:`attribute` must be supplied. .. flag:: Primitive Projections This :term:`flag` turns on the use of primitive projections when defining subsequent records (even through the :cmd:`Inductive` and :cmd:`CoInductive` commands). Primitive projections extend 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 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 for the usual defined ones, although there are a few notable differences. .. attr:: projections(primitive{? = {| yes | no } }) :name: projections(primitive) This :term:`boolean attribute` can be used to override the value of the :flag:`Primitive Projections` :term:`flag` for the record type being defined. .. flag:: Printing Primitive Projection Parameters This compatibility :term:`flag` (off by default) reconstructs internally omitted parameters at printing time (even though they are absent in the actual AST manipulated by the kernel). Reduction +++++++++ The basic reduction rule of a primitive projection is |p_i| ``(Build_``\ `R` |t_1| … |t_n|\ ``)`` :math:`{\rightarrow_{\iota}}` |t_i|. However, to take the Ξ΄ flag into account, projections can be in two states: folded or unfolded. An unfolded primitive projection application obeys the rule above, while the folded version delta-reduces to the unfolded version. This allows to precisely mimic the usual unfolding rules of :term:`constants `. Projections obey the usual ``simpl`` flags of the :cmd:`Arguments` command in particular. Unfolded primitive projections can be built using the compatibility match syntax for primitive records, or by reducing the compatibility constant. User-written :g:`match` constructs on primitive records are desugared using the unfolded primitive projections and `let` bindings. .. example:: .. rocqtop:: reset all #[projections(primitive)] Record Sigma A B := sigma { p1 : A; p2 : B p1 }. Arguments sigma {_ _} _ _. Check fun x : Sigma nat (fun _ => nat) => match x with sigma v _ => v + v end. Check fun x : Sigma nat (fun x => x = 0) => match x return exists y, y = 0 with sigma v e => ex_intro _ v e end. Matches which are equivalent to just a projection have adhoc handling to avoid generating useless ``let``: .. rocqtop:: all Arguments p1 {_ _} _. Check fun x : Sigma nat (fun x => x = 0) => match x return x.(p1) = 0 with sigma v e => e end. .. flag:: Printing Unfolded Projection As Match By default this flag is off and unfolded primitive projections are printed the same as folded primitive projections. By setting this flag, unfolded primitive projections are instead printed as let-style matches in the form ``let '{| p := p |} := c in p``. Compatibility Constants for Projections +++++++++++++++++++++++++++++++++++++++ To ease compatibility with ordinary record types, each primitive projection is also defined as an ordinary :term:`constant` taking parameters and an object of the record type as arguments, and whose :term:`body` is an application of the unfolded primitive projection of the same name. These constants are used when elaborating partial applications of the projection. One can distinguish them from applications of the primitive projection if the :flag:`Printing Primitive Projection Parameters` flag is off: For a primitive projection application, parameters are printed as underscores while for the compatibility projections they are printed as usual. They cannot be distinguished if the record has no parameters. rocq-9.2.0/doc/sphinx/language/core/sections.rst000066400000000000000000000265011516144147600216550ustar00rootroot00000000000000.. _section-mechanism: Sections ==================================== Sections are naming scopes that permit creating section-local declarations that can be used by other declarations in the section. Declarations made with :cmd:`Variable`, :cmd:`Hypothesis`, :cmd:`Context` (or the plural variants of the first two) and definitions made with :cmd:`Let`, :cmd:`Let Fixpoint` and :cmd:`Let CoFixpoint` within sections are local to the section. In proofs done within the section, section-local declarations are included in the :term:`local context` of the initial goal of the proof. They are also accessible in definitions made with the :cmd:`Definition` command. Using sections -------------- Sections are opened by the :cmd:`Section` command, and closed by :cmd:`End`. Sections can be nested. When a section is closed, its local declarations are no longer available. Global declarations that refer to them will be adjusted so they're still usable outside the section as shown in this :ref:`example `. .. cmd:: Section @ident Opens the section named :token:`ident`. Section names do not need to be unique. .. cmd:: End @ident Closes the section or module named :token:`ident`. See :ref:`Terminating an interactive module or module type definition ` for a description of its use with modules. After closing the section, the section-local declarations (variables and :gdef:`section-local definitions `, see :cmd:`Variable`) are *discharged*, meaning that they stop being visible and that all global objects defined in the section are generalized with respect to the variables and local definitions they each depended on in the section. .. exn:: There is nothing to end. :undocumented: .. exn:: Last block to end has name @ident. :undocumented: .. note:: Most commands, such as the :ref:`Hint ` commands, :cmd:`Notation` and option management commands that appear inside a section are canceled when the section is closed. In some cases, this behaviour can be tuned with locality attributes. See :ref:`this table`. .. cmd:: Let @ident_decl @def_body Let Fixpoint @fix_definition {* with @fix_definition } Let CoFixpoint @cofix_definition {* with @cofix_definition } :name: Let; Let Fixpoint; Let CoFixpoint These are similar to :cmd:`Definition`, :cmd:`Fixpoint` and :cmd:`CoFixpoint`, except that the declared :term:`constant` is local to the current section. When the section is closed, all persistent definitions and theorems within it that depend on the constant will be wrapped with a :n:`@term_let` with the same declaration. As for :cmd:`Definition`, :cmd:`Fixpoint` and :cmd:`CoFixpoint`, if :n:`@term` is omitted, :n:`@type` is required and Rocq enters proof mode. This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. See :ref:`proof-editing-mode`. .. attr:: clearbody When used with :cmd:`Let` in a section, clears the body of the definition in the proof context of following proofs. The kernel will still use the body when checking. .. note:: Terminating the proof for a :cmd:`Let` with :cmd:`Qed` produces an opaque side definition. `Let foo : T. Proof. tactics. Qed.` is equivalent to .. rocqdoc:: Lemma foo_subproof : T. Proof. tactics. Qed. #[clearbody] Let foo := foo_subproof. .. cmd:: Context {+ @binder } Declare variables in the context of the current section, like :cmd:`Variable`, but also allowing implicit variables, :ref:`implicit-generalization`, and let-binders. .. rocqdoc:: Context {A : Type} (a b : A). Context `{EqDec A}. Context (b' := b). .. seealso:: Section :ref:`binders`. Section :ref:`contexts` in chapter :ref:`typeclasses`. .. _section_local_declarations: .. example:: Section-local declarations .. rocqtop:: all Section s1. .. rocqtop:: all Variables x y : nat. The command :cmd:`Let` introduces section-wide :ref:`let-in`. These definitions won't persist when the section is closed, and all persistent definitions which depend on `y'` will be prefixed with `let y' := y in`. .. rocqtop:: in Let y' := y. Definition x' := S x. Definition x'' := x' + y'. .. rocqtop:: all Print x'. Print x''. End s1. Print x'. Print x''. Notice the difference between the value of :g:`x'` and :g:`x''` inside section :g:`s1` and outside. .. _visibility-attributes-sections: Summary of locality attributes in a section ------------------------------------------- This table sums up the effect of locality attributes on the scope of vernacular commands in a :cmd:`Section`, when outside the :cmd:`Section` where they were entered. In the following table: * a cross (❌) marks an unsupported attribute (compilation error); * β€œnot available” means that the command has no effect outside the :cmd:`Section` it was entered; * β€œavailable” means that the effects of the command persists outside the :cmd:`Section`. * For :cmd:`Definition` (and :cmd:`Lemma`, ...), :cmd:`Canonical Structure`, :cmd:`Coercion` and :cmd:`Set` (and :cmd:`Unset`), some locality attributes will be passed on to the :cmd:`Module` containing the current :cmd:`Section`, see the associated footnotes. A similar table for :cmd:`Module` can be found :ref:`here `. .. list-table:: :header-rows: 1 * - ``Command`` - no attribute - :attr:`local` - :attr:`export` - :attr:`global` * - :cmd:`Definition`, :cmd:`Lemma`, :cmd:`Axiom`, ... - available [#note1]_ - :attr:`local` in module [#note1]_ - ❌ - ❌ * - :cmd:`Ltac` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Ltac2` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Abbreviation` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Notation` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Tactic Notation` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Ltac2 Notation` - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Coercion` - :attr:`global` - not available - ❌ - :attr:`global` in module [#note2]_ * - :cmd:`Canonical Structure` - :attr:`global` - not available - ❌ - :attr:`global` in module [#note2]_ * - ``Hints`` (and :cmd:`Instance`) - :attr:`local` - not available - ❌ - ❌ * - :cmd:`Set` or :cmd:`Unset` a flag - available [#note3]_ - not available - :attr:`export` in module [#note3]_ - :attr:`global` in module [#note3]_ .. [#note1] For :cmd:`Definition`, :cmd:`Lemma`, ... the default visibility is to be available outside the section and available with a short name when the current :cmd:`Module` is imported (with :cmd:`Import` or :cmd:`Export`) outside the current :cmd:`Module`. The :attr:`local` attribute make the corresponding identifiers available in the current :cmd:`Module` but only with a fully qualified name outside the current :cmd:`Module`. .. [#note2] For :cmd:`Coercion` and :cmd:`Canonical Structure`, the :attr:`global` visibility, which is the default, makes them available outside the section, in the current :cmd:`Module`, and outside the current :cmd:`Module` when it is imported (with :cmd:`Import` or :cmd:`Export`). .. [#note3] For :cmd:`Set` and :cmd:`Unset`, the :attr:`export` and :attr:`global` attributes both make the command's effects persist outside the current section, in the current :cmd:`Module`. It will also persist outside the current :cmd:`Module` with the :attr:`global` attribute, or with the :attr:`export` attribute, when the :cmd:`Module` is imported (with :cmd:`Import` or :cmd:`Export`). The default behaviour (no attribute) is to make the setting persist outside the section in the current :cmd:`Module`, but not outside the current :cmd:`Module`. .. _Admissible-rules-for-global-environments: Typing rules used at the end of a section -------------------------------------------- From the original rules of the type system, one can show the admissibility of rules which change the local context of definition of objects in the global environment. We show here the admissible rules that are used in the discharge mechanism at the end of a section. .. _Abstraction: **Abstraction.** One can modify a global declaration by generalizing it over a previously assumed constant :math:`c`. For doing that, we need to modify the 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}]` and :math:`\subst{E}{|Ξ“|}{|Ξ“|c}` to mean the parallel substitution :math:`E\{y_1 /(y_1~c)\}…\{y_n/(y_n~c)\}`. .. _First-abstracting-property: **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)}}} .. 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)}}{\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}}} 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}]`. .. _Second-abstracting-property: **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β€³}{Ξ“}} .. math:: \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β€³}{Ξ“}} .. _Pruning-the-local-context: **Pruning the local context.** If one abstracts or substitutes constants with the above rules then it may happen that some declared or defined constant does not occur any more in the subsequent global environment and in the local context. One can consequently derive the following property. .. _First-pruning-property: .. inference:: First pruning property: \WF{E;~c:U;~Eβ€²}{Ξ“} c~\kw{does not occur in}~Eβ€²~\kw{and}~Ξ“ -------------------------------------- \WF{E;Eβ€²}{Ξ“} .. _Second-pruning-property: .. inference:: Second pruning property: \WF{E;~c:=u:U;~Eβ€²}{Ξ“} c~\kw{does not occur in}~Eβ€²~\kw{and}~Ξ“ -------------------------------------- \WF{E;Eβ€²}{Ξ“} rocq-9.2.0/doc/sphinx/language/core/sorts.rst000066400000000000000000000102601516144147600211730ustar00rootroot00000000000000.. index:: single: Set (sort) single: SProp single: Prop single: Type .. _sorts: Sorts ~~~~~~~~~~~ .. insertprodn sort universe_expr .. prodn:: sort ::= Set | Prop | SProp | Type | Type @%{ _ %} | Type @%{ {? @qualid {| %| | ; } } @universe %} universe ::= max ( {+, @universe_expr } ) | _ | @universe_expr universe_expr ::= @universe_name {? + @natural } | @natural The types of types are called :gdef:`sorts `. All sorts have a type and there is an infinite well-founded typing hierarchy of sorts whose base sorts are :math:`\SProp`, :math:`\Prop` and :math:`\Set`. The sort :math:`\Prop` intends to be the type of logical propositions. If :math:`M` is a logical proposition then it denotes the class of terms representing proofs of :math:`M`. An object :math:`m` belonging to :math:`M` witnesses the fact that :math:`M` is provable. An object of type :math:`\Prop` is called a :gdef:`proposition`. We denote propositions by :n:`@form`. This constitutes a semantic subclass of the syntactic class :n:`@term`. The sort :math:`\SProp` is like :math:`\Prop` but the propositions in :math:`\SProp` are known to have irrelevant proofs (all proofs are equal). Objects of type :math:`\SProp` are called :gdef:`strict propositions `. See :ref:`sprop` for information about using :math:`\SProp`, and :cite:`Gilbert:POPL2019` for meta theoretical considerations. The sort :math:`\Set` intends to be the type of small sets. This includes data types such as booleans and naturals, but also products, subsets, and function types over these data types. We denote specifications (program types) by :n:`@specif`. This constitutes a semantic subclass of the syntactic class :n:`@term`. :math:`\SProp`, :math:`\Prop` and :math:`\Set` themselves can be manipulated as ordinary terms. Consequently they also have a type. Because assuming simply that :math:`\Set` has type :math:`\Set` leads to an inconsistent theory :cite:`Coq86`, the language of |Cic| has infinitely many sorts. There are, in addition to the base sorts, a hierarchy of universes :math:`\Type(i)` for any integer :math:`i β‰₯ 1`. Like :math:`\Set`, all of the sorts :math:`\Type(i)` contain small sets such as booleans, natural numbers, as well as products, subsets and function types over small sets. But, unlike :math:`\Set`, they also contain large sets, namely the sorts :math:`\Set` and :math:`\Type(j)` for :math:`j` of the type. Each inhabitant is specified by a :gdef:`constructor`. For instance, Booleans have two constructors: :g:`true` and :g:`false`. Types can include enumerated types from programming languages, such as Booleans, characters or even the degenerate cases of the unit and empty types. Variant types more generally include enumerated types with arguments or even enumerated types with parametric arguments such as option types and sum types. It also includes predicates or type families defined by cases such as the Boolean reflection or equality predicates. Observing the form of the :term:`inhabitants ` of a variant type is done by case analysis using the `match` expression. When a constructor of a type takes an argument of that same type, the type is a :gdef:`recursive type`, in which case it can be either :cmd:`Inductive` or :cmd:`CoInductive`. The keyword :cmd:`Variant` is reserved for non-recursive types. Natural numbers, lists or streams cannot be defined using :cmd:`Variant`. .. cmd:: Variant @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? {? %| } {+| @constructor } } {? @decl_notations } Defines a variant type named :n:`@ident` (in :n:`@ident_decl`) with the given list of constructors. No induction scheme is generated for this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. :n:`{? %| {* @binder } }` The :n:`|` separates uniform and non uniform parameters. See :flag:`Uniform Inductive Parameters`. This command supports the :attr:`universes(polymorphic)`, :attr:`universes(template)`, :attr:`universes(cumulative)`, and :attr:`private(matching)` attributes. .. exn:: Types declared with the keyword Variant cannot be recursive. Recursive types are defined with the Inductive and CoInductive command. :undocumented: .. exn:: The @natural th argument of @ident must be @ident in @type. :undocumented: .. example:: The Booleans, the unit type and the empty type are respectively defined by: .. rocqtop:: none Module FreshNameSpace. .. rocqtop:: in Variant bool : Set := true : bool | false : bool. Variant unit : Set := tt : unit. Variant Empty_set : Set :=. The option and sum types are defined by: .. rocqtop:: in Variant option (A : Type) : Type := None : option A | Some : A -> option A. Variant sum (A B : Type) : Type := inl : A -> sum A B | inr : B -> sum A B. .. note:: The standard library commonly uses :cmd:`Inductive` in place of :cmd:`Variant` even for non-recursive types in order to automatically derive the schemes :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``. (These schemes are also created for :cmd:`Variant` if the :flag:`Nonrecursive Elimination Schemes` flag is set.) .. example:: :cmd:`Variant` won't define recursive types .. rocqtop:: all Fail Variant my_nat := zero | succ (n : my_nat). :g:`my_nat` is a :term:`recursive type` because its :g:`succ` constructor has an argument of the type :g:`my_nat` itself. Use the :cmd:`Inductive` command instead (see the chapter covering :ref:`inductive types `): .. rocqtop:: in Inductive my_nat := zero | succ (n : my_nat). .. example:: *Boolean reflection* is a relation reflecting under the form of a Boolean value when a given proposition :n:`P` holds. It can be defined as a two-constructor type family over :g:`bool` parameterized by the proposition :n:`P`: .. rocqtop:: in Variant reflect (P : Prop) : bool -> Set := | ReflectT : P -> reflect P true | ReflectF : ~ P -> reflect P false. .. rocqtop:: none End FreshNameSpace. :term:`Leibniz equality` is another example of variant type. Private (matching) inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. attr:: private(matching) :name: private(matching); Private This :term:`attribute` can be used to forbid the use of the :g:`match` construct on objects of this inductive type outside of the module where it is defined. There is also a legacy syntax using the ``Private`` prefix (cf. :n:`@legacy_attr`). The main use case of private (matching) inductive types is to emulate quotient types / higher-order inductive types in projects such as the `HoTT library `_. Reducing definitions from the inductive's module can expose :g:`match` constructs to unification, which may result in invalid proof terms. Errors from such terms are delayed until proof completion (i.e. on the :cmd:`Qed`). Use :cmd:`Validate Proof` to identify which tactic produced the problematic term. .. example:: .. rocqtop:: all Module Foo. #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). End Foo. Import Foo. Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). .. index:: match ... with ... .. _match_term: Definition by cases: match -------------------------- Objects of inductive types can be destructured by a case-analysis construction called *pattern matching* expression. A pattern matching expression is used to analyze the structure of an inductive object and to apply specific treatments accordingly. .. insertprodn term_match pattern0 .. prodn:: term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end case_item ::= @term100 {? as @name } {? in @pattern } eqn ::= {+| {+, @pattern } } => @term pattern ::= @pattern10 : @term | @pattern10 pattern10 ::= @pattern10 as @name | @pattern10 {* @pattern1 } | @ @qualid {* @pattern1 } pattern1 ::= @pattern1 % @scope_key | @pattern1 %_ @scope_key | @pattern0 pattern0 ::= @qualid | %{%| {* @qualid := @pattern } %|%} | _ | ( {+| @pattern } ) | @number | @string Note that the :n:`@pattern ::= @pattern10 : @term` production is not supported in :n:`match` patterns. Trying to use it will give this error: .. exn:: Casts are not supported in this pattern. :undocumented: This paragraph describes the basic form of pattern matching. See Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description of the general form. The basic form of pattern matching is characterized by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a single :n:`@pattern` and :n:`@pattern` restricted to the form :n:`@qualid {* @ident}`. The expression :n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a *pattern matching* over the term :n:`@term` (expected to be of an inductive type :math:`I`). The :n:`@term__i` are the *branches* of the pattern matching expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` where :n:`@qualid` must denote a constructor. There should be exactly one branch for every constructor of :math:`I`. The :n:`return @term100` clause gives the type returned by the whole match expression. There are several cases. In the *non-dependent* case, all branches have the same type, and the :n:`return @term100` specifies that type. In this case, :n:`return @term100` can usually be omitted as it can be inferred from the type of the branches [1]_. In the *dependent* case, there are three subcases. In the first subcase, the type in each branch may depend on the exact value being matched in the branch. In this case, the whole pattern matching itself depends on the term being matched. This dependency of the term being matched in the return type is expressed with an :n:`@ident` clause where :n:`@ident` is dependent in the return type. For instance, in the following example: .. rocqtop:: in Inductive bool : Type := true : bool | false : bool. Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. Inductive or (A:Prop) (B:Prop) : Prop := | or_introl : A -> or A B | or_intror : B -> or A B. Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := match b as x return or (eq bool x true) (eq bool x false) with | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) end. the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" and ":g:`or (eq bool false true) (eq bool false false)`" while the whole pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", the identifier :g:`b` being used to represent the dependency. .. note:: When the term being matched is a variable, the ``as`` clause can be omitted and the term being matched can serve itself as binding name in the return type. For instance, the following alternative definition is accepted and has the same meaning as the previous one. .. rocqtop:: none Reset bool_case. .. rocqtop:: in Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := match b return or (eq bool b true) (eq bool b false) with | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) end. The second subcase is only relevant for indexed inductive types such as the equality predicate (see Section :ref:`coq-equality`), the order predicate on natural numbers or the type of lists of a given length (see Section :ref:`matching-dependent`). In this configuration, the type of each branch can depend on the type dependencies specific to the branch and the whole pattern matching expression has a type determined by the specific dependencies in the type of the term being matched. This dependency of the return type in the indices of the inductive type is expressed with a clause in the form :n:`in @qualid {* _ } {+ @pattern }`, where - :n:`@qualid` is the inductive type of the term being matched; - the holes :n:`_` match the parameters of the inductive type: the return type is not dependent on them. - each :n:`@pattern` matches the indices of the inductive type: the return type is dependent on them - in the basic case which we describe below, each :n:`@pattern` is a name :n:`@ident`; see :ref:`match-in-patterns` for the general case For instance, in the following example: .. rocqtop:: in Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := match H in eq _ _ z return eq A z x with | eq_refl _ _ => eq_refl A x end. the type of the branch is :g:`eq A x x` because the third argument of :g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the type of the whole pattern matching expression has type :g:`eq A y x` because the third argument of eq is y in the type of H. This dependency of the case analysis in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the return type. Finally, the third subcase is a combination of the first and second subcase. In particular, it only applies to pattern matching on terms in a type with indices. For this third subcase, both the clauses ``as`` and ``in`` are available. There are specific notations for case analysis on types with one or two constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). .. [1] Except if the inductive type is empty in which case there is no equation that can be used to infer the return type. rocq-9.2.0/doc/sphinx/language/extensions/000077500000000000000000000000001516144147600205375ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/language/extensions/arguments-command.rst000066400000000000000000000466331516144147600247260ustar00rootroot00000000000000.. _ArgumentsCommand: Setting properties of a function's arguments ++++++++++++++++++++++++++++++++++++++++++++ .. cmd:: Arguments @reference {* @arg_specs } {* , {* @implicits_alt } } {? : {+, @args_modifier } } .. insertprodn arg_specs args_modifier .. prodn:: arg_specs ::= @argument_spec | / | & | ( {+ @argument_spec } ) {* {| % @scope | %_ @scope } } | [ {+ @argument_spec } ] {* {| % @scope | %_ @scope } } | %{ {+ @argument_spec } %} {* {| % @scope | %_ @scope } } argument_spec ::= {? ! } @name {* {| % @scope | %_ @scope } } implicits_alt ::= @name | [ {+ @name } ] | %{ {+ @name } %} args_modifier ::= simpl nomatch | simpl never | clear simpl | default implicits | clear implicits | clear scopes | clear bidirectionality hint | rename | assert | extra scopes | clear scopes and implicits | clear implicits and scopes Specifies properties of the arguments of a function after the function has already been defined. It gives fine-grained control over the elaboration process (i.e. the translation of Gallina language extensions into the core language used by the kernel). The command's effects include: * Making arguments implicit. Afterward, :term:`implicit arguments ` must be omitted in any expression that applies :token:`reference`. * Declaring that some arguments of a given function should be interpreted in a given :term:`notation scope`. * Affecting when the :tacn:`simpl` and :tacn:`cbn` tactics unfold the function. See :ref:`Args_effect_on_unfolding`. * Providing bidirectionality hints. See :ref:`bidirectionality_hints`. This command supports the :attr:`local` and :attr:`global` attributes. Default behavior is to limit the effect to the current section but also to extend their effect outside the current module or library file. Applying :attr:`local` limits the effect of the command to the current module if it's not in a section. Applying :attr:`global` within a section extends the effect outside the current sections and current module in which the command appears. `/` the function will be unfolded only if it's applied to at least the arguments appearing before the `/`. See :ref:`Args_effect_on_unfolding`. .. exn:: The / modifier may only occur once. :undocumented: `&` tells the type checking algorithm to first type check the arguments before the `&` and then to propagate information from that typing context to type check the remaining arguments. See :ref:`bidirectionality_hints`. .. exn:: The & modifier may only occur once. :undocumented: :n:`( {+ @argument_spec } ) {* %_ @scope }` :n:`(@name__1 @name__2 ...){* %@scope }` is shorthand for :n:`@name__1{* %@scope } @name__2{* %@scope } ...` :n:`[ {+ @argument_spec } ] {* %_ @scope }` declares the enclosed names as implicit, non-maximally inserted. :n:`[@name__1 @name__2 ... ]{* %_@scope }` is equivalent to :n:`[@name__1]{* %_@scope } [@name__2]{* %_@scope } ...` :n:`%{ {+ @argument_spec } %} {* %_ @scope }` declares the enclosed names as implicit, maximally inserted. :n:`%{@name__1 @name__2 ... %}{* %_@scope }` is equivalent to :n:`%{@name__1%}{* %_@scope } %{@name__2%}{* %_@scope } ...` `!` the function will be unfolded only if all the arguments marked with `!` evaluate to constructors. See :ref:`Args_effect_on_unfolding`. :n:`@name {* %_ @scope }` a *formal parameter* of the function :n:`@reference` (i.e. the parameter name used in the function definition). Unless `rename` is specified, the list of :n:`@name`\s must be a prefix of the formal parameters, including all implicit arguments. `_` can be used to skip over a formal parameter. This construct declares :n:`@name` as non-implicit if `clear implicits` is specified or any other :n:`@name` in the :cmd:`Arguments` command is declared implicit. :token:`scope` can be either scope names or their delimiting keys. When multiple scopes are present, notations are interpreted in the leftmost scope containing them. See :ref:`binding_to_scope`. .. deprecated:: 8.19 The :n:`% @scope` syntax is deprecated in favor of the currently equivalent :n:`%_ @scope`. It will be reused in future versions with the same semantics as in terms. .. exn:: To rename arguments the 'rename' flag must be specified. :undocumented: .. exn:: Flag 'rename' expected to rename @name into @name. :undocumented: .. exn:: Arguments of section variables such as @name may not be renamed. :undocumented: `clear implicits` makes all implicit arguments into explicit arguments .. exn:: The 'clear implicits' flag must be omitted if implicit annotations are given. :undocumented: `default implicits` automatically determine the implicit arguments of the object. See :ref:`auto_decl_implicit_args`. .. exn:: The 'default implicits' flag is incompatible with implicit annotations. :undocumented: `rename` rename implicit arguments for the object. See the example :ref:`here `. `assert` assert that the object has the expected number of arguments with the expected names. See the example here: :ref:`renaming_implicit_arguments`. .. warn:: This command is just asserting the names of arguments of @qualid. If this is what you want, add ': assert' to silence the warning. If you want to clear implicit arguments, add ': clear implicits'. If you want to clear notation scopes, add ': clear scopes' :undocumented: `clear scopes` clears argument scopes of :n:`@reference` `extra scopes` defines extra argument scopes, to be used in case of coercion to ``Funclass`` (see :ref:`coercions`) or with a computed type. `simpl nomatch` prevents performing a simplification step for :n:`@reference` that would expose a match construct in the head position. See :ref:`Args_effect_on_unfolding`. `simpl never` prevents performing a simplification step for :n:`@reference`. See :ref:`Args_effect_on_unfolding`. `clear simpl` resets the modifications made to the simplification steps, i.e., cancels all previous `simpl never`, `simpl nomatch`, `/` and `!`. `clear bidirectionality hint` removes the bidirectionality hint, the `&` :n:`@implicits_alt` use to specify alternative implicit argument declarations for functions that can only be applied to a fixed number of arguments (excluding, for instance, functions whose type is polymorphic). For parsing, the longest list of implicit arguments matching the function application is used to select which implicit arguments are inserted. For printing, the alternative with the most implicit arguments is used; the implict arguments will be omitted if :flag:`Printing Implicit` is not set. See the example :ref:`here`. .. todo the above feature seems a bit unnatural and doesn't play well with partial application. See https://github.com/rocq-prover/rocq/pull/11718#discussion_r408841762 Use :cmd:`About` to view the current implicit arguments setting for a :token:`reference`. Or use the :cmd:`Print Implicit` command to see the implicit arguments of an object (see :ref:`displaying-implicit-args`). Manual declaration of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. example:: .. rocqtop:: reset all Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. Check (cons nat 3 (nil nat)). Arguments cons [A] _ _. Arguments nil {A}. Check (cons 3 nil). Fixpoint map (A B : Type) (f : A -> B) (l : list A) : list B := match l with nil => nil | cons a t => cons (f a) (map A B f t) end. Fixpoint length (A : Type) (l : list A) : nat := match l with nil => 0 | cons _ m => S (length A m) end. Arguments map [A B] f l. Arguments length {A} l. (* A has to be maximally inserted *) Check (fun l:list (list nat) => map length l). .. _example_more_implicits: .. example:: Multiple alternatives with :n:`@implicits_alt` .. rocqtop:: all Arguments map [A B] f l, [A] B f l, A B f l. Check (fun l => map length l = map (list nat) nat length l). .. _auto_decl_implicit_args: Automatic declaration of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ":n:`default implicits`" :token:`args_modifier` clause tells Rocq to automatically determine the implicit arguments of the object. Auto-detection is governed by flags specifying whether strict, contextual, or reversible-pattern implicit arguments must be considered or not (see :ref:`controlling-strict-implicit-args`, :ref:`controlling-contextual-implicit-args`, :ref:`controlling-rev-pattern-implicit-args` and also :ref:`controlling-insertion-implicit-args`). .. example:: Default implicits .. rocqtop:: reset all Inductive list (A:Set) : Set := | nil : list A | cons : A -> list A -> list A. Arguments cons : default implicits. Print Implicit cons. Arguments nil : default implicits. Print Implicit nil. Set Contextual Implicit. Arguments nil : default implicits. Print Implicit nil. The computation of implicit arguments takes account of the unfolding of :term:`constants `. For instance, the variable ``p`` below has type ``(Transitivity R)`` which is reducible to ``forall x,y:U, R x y -> forall z:U, R y z -> R x z``. As the variables ``x``, ``y`` and ``z`` appear strictly in the :term:`body` of the type, they are implicit. .. rocqtop:: all Parameter X : Type. Definition Relation := X -> X -> Prop. Definition Transitivity (R:Relation) := forall x y:X, R x y -> forall z:X, R y z -> R x z. Parameters (R : Relation) (p : Transitivity R). Arguments p : default implicits. Print p. Print Implicit p. Parameters (a b c : X) (r1 : R a b) (r2 : R b c). Check (p r1 r2). .. _renaming_implicit_arguments: Renaming implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. example:: (continued) Renaming implicit arguments .. rocqtop:: all Arguments p [s t] _ [u] _: rename. Check (p r1 (u:=c)). Check (p (s:=a) (t:=b) r1 (u:=c) r2). Fail Arguments p [s t] _ [w] _ : assert. .. _binding_to_scope: Binding arguments to scopes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following command declares that the first two arguments of :g:`plus_fct` are interpreted in the :token:`scope` delimited by the key ``F`` and the third argument is first interpreted in the scope delimited by the key ``R``, then in ``F`` (when a notation has no interpretation in ``R``). .. rocqdoc:: Arguments plus_fct (f1 f2)%_F x%_R%_F. When interpreting a term, if some of the arguments of :token:`reference` are built from a notation, then this notation is interpreted in the scope stack extended by the scopes bound (if any) to this argument. The effect of these scopes is limited to the argument itself. It does not propagate to subterms but the subterms that, after interpretation of the notation, turn to be themselves arguments of a reference are interpreted according to the argument scopes bound to this reference. .. note:: In notations, the subterms matching the identifiers of the notations are interpreted in the scope in which the identifiers occurred at the time of the declaration of the notation. Here is an example: .. rocqtop:: all Parameter g : bool -> bool. Declare Scope mybool_scope. Notation "@@" := true (only parsing) : bool_scope. Notation "@@" := false (only parsing): mybool_scope. Bind Scope bool_scope with bool. Notation "<< x >>" := (g x). Check << @@ >>. Arguments g _%_mybool_scope. Check << @@ >>. Delimit Scope mybool_scope with mybool. Check << @@%mybool >>. .. _Args_effect_on_unfolding: Effects of :cmd:`Arguments` on unfolding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + `simpl never` indicates that a :term:`constant` should not be unfolded by :tacn:`cbn` or :tacn:`simpl` when in head position. Note that in the case of :tacn:`simpl`, the modifier does not apply to reduction of the main argument of a `match`, `fix`, primitive projection, or of an unfoldable constant hiding a `match`, `fix` or primitive projection. .. example:: .. rocqtop:: all Arguments Nat.sub n m : simpl never. After that command an expression like :g:`(Nat.sub (S x) y)` is left untouched by the tactics :tacn:`cbn` and :tacn:`simpl`. Otherwise, an expression like :g:`(Nat.sub (S x) 0) + 1` reduces to :g:`S (x + 1)` for :tacn:`simpl` because `Nat.sub` is the main argument of `+` in this case. + A :term:`constant` can be marked to be unfolded only if it's applied to at least the arguments appearing before the `/` in a :cmd:`Arguments` command. .. example:: .. rocqtop:: all Definition fcomp A B C f (g : A -> B) (x : A) : C := f (g x). Arguments fcomp {A B C} f g x /. Notation "f \o g" := (fcomp f g) (at level 50). After that command the expression :g:`(f \o g)` is left untouched by :tacn:`simpl` while :g:`((f \o g) t)` is reduced to :g:`(f (g t))`. The same mechanism can be used to make a :term:`constant` volatile, i.e. always unfolded. .. example:: .. rocqtop:: all Definition volatile := fun x : nat => x. Arguments volatile / x. + A :term:`constant` can be marked to be unfolded only if an entire set of arguments evaluates to a constructor. The ``!`` symbol can be used to mark such arguments. .. example:: .. rocqtop:: all Arguments minus !n !m. After that command, the expression :g:`(minus (S x) y)` is left untouched by :tacn:`simpl`, while :g:`(minus (S x) (S y))` is reduced to :g:`(minus x y)`. + `simpl nomatch` indicates that a :term:`constant` should not be unfolded if it would expose a `match` construct in the head position. This affects the :tacn:`cbn`, :tacn:`simpl` and :tacn:`hnf` tactics. .. example:: .. rocqtop:: all Arguments minus n m : simpl nomatch. In this case, :g:`(minus (S (S x)) (S y))` is simplified to :g:`(minus (S x) y)` even if an extra simplification is possible. In detail: the tactic :tacn:`simpl` first applies Ξ²ΞΉ-reduction. Then, it expands transparent :term:`constants ` and tries to reduce further using Ξ²ΞΉ-reduction. But, when no ΞΉ rule is applied after unfolding then Ξ΄-reductions are not applied. For instance trying to use :tacn:`simpl` on :g:`(plus n O) = n` changes nothing. .. _bidirectionality_hints: Bidirectionality hints ~~~~~~~~~~~~~~~~~~~~~~ When type-checking an application, Rocq normally does not use information from the context to infer the types of the arguments. It only checks after the fact that the type inferred for the application is coherent with the expected type. Bidirectionality hints make it possible to specify that after type-checking the first arguments of an application, typing information should be propagated from the context to help inferring the types of the remaining arguments. .. todo the following text is a start on better wording but not quite complete. See https://github.com/rocq-prover/rocq/pull/11718#discussion_r410219992 .. Two common methods to determine the type of a construct are: * *type checking*, which is verifying that a construct matches a known type, and * *type inference*, with is inferring the type of a construct by analyzing the construct. Methods that combine these approaches are known as *bidirectional typing*. Rocq normally uses only the first approach to infer the types of arguments, then later verifies that the inferred type is consistent with the expected type. *Bidirectionality hints* specify to use both methods: after type checking the first arguments of an application (appearing before the `&` in :cmd:`Arguments`), typing information from them is propagated to the remaining arguments to help infer their types. An :cmd:`Arguments` command containing :n:`@arg_specs__1 & @arg_specs__2` provides bidirectionality hints. It tells the typechecking algorithm, when type checking applications of :n:`@qualid`, to first type check the arguments in :n:`@arg_specs__1` and then propagate information from the typing context to type check the remaining arguments (in :n:`@arg_specs__2`). .. example:: Bidirectionality hints, example with coercion In a context where a coercion was declared from ``bool`` to ``nat`` (see section :ref:`coercions`): .. rocqtop:: in reset Definition b2n (b : bool) := if b then 1 else 0. Coercion b2n : bool >-> nat. Rocq cannot automatically coerce existential statements over ``bool`` to statements over ``nat``, because the need for inserting a coercion is known only from the expected type of a subterm: .. rocqtop:: all Fail Check (ex_intro _ true _ : exists n : nat, n > 0). However, a suitable bidirectionality hint makes the example work: .. rocqtop:: all Arguments ex_intro _ _ & _ _. Check (ex_intro _ true _ : exists n : nat, n > 0). .. example:: Bidirectionality hints, example with number comparison Bidirectionality hints can be used without coercions, as shown by the following example. One could provide arguments with simpler types than expected (or even fully implicit), and let Rocq infer the correct one. For instance, consider the following definition: .. rocqtop:: in reset Import Nat. Definition leb_implies_le {n m} (H : (n <=? m) = true) : n <= m. Proof. revert m H; induction n as [| n IH]; intros m; [intros _; exact (le_0_n _) |]. destruct m; intros [= H]; apply le_n_S, IH; exact H. Qed. One could use leb_implies_le to prove ``3 <= 4`` without providing an explicit proof of ``3 <=? 4 = true``, by using ``eq_refl`` in ``H``'s place. Rocq is able to infer that ``n = 3`` and ``m = 4`` by using ``3 <= 4`` from the expected type and ``n <= m`` from the definition of ``leb_implies_le``. But it cannot use these values to infer that H's type should be ``(3 <=? 4) = true`` from ``(?n <=? ?m) = true`` as one could expect. The reason is that Rocq doesn't make types infered for some arguments available for the inference of the remaining arguments: .. rocqtop:: all Fail Check leb_implies_le (eq_refl _) : 3 <= 4. However, by using a bidirectionality hint, values infered for arguments on the left of ``&`` are propagated to those on the right. This makes values ``n = 3`` and ``m = 4`` propagate to ``H``, allowing ``(?n <=? ?m)`` to be reduced to ``true``: .. rocqtop:: all Arguments leb_implies_le n m & H. Check leb_implies_le (eq_refl _) : 3 <= 4. Rocq will attempt to produce a term which uses the arguments you provided, but in some cases involving Program mode the arguments after the bidirectionality starts may be replaced by convertible but syntactically different terms. rocq-9.2.0/doc/sphinx/language/extensions/canonical.rst000066400000000000000000000510421516144147600232220ustar00rootroot00000000000000.. _canonicalstructures: Canonical Structures ====================== :Authors: Assia Mahboubi and Enrico Tassi This chapter explains the basics of canonical structures and how they can be used to overload notations and build a hierarchy of algebraic structures. The examples are taken from :cite:`CSwcu`. We invite the interested reader to refer to this paper for all the details that are omitted here for brevity. The interested reader shall also find in :cite:`CSlessadhoc` a detailed description of another, complementary, use of canonical structures: advanced proof search. This latter papers also presents many techniques one can employ to tune the inference of canonical structures. .. extracted from implicit arguments section .. _canonical-structure-declaration: Declaration of canonical structures ----------------------------------- A canonical structure is an instance of a record/structure type that can be used to solve unification problems involving a projection applied to an unknown structure instance (an implicit argument) and a value. The complete documentation of canonical structures can be found in :ref:`canonicalstructures`; here only a simple example is given. .. cmd:: Canonical {? Structure } @reference Canonical {? Structure } @ident_decl @def_body :name: Canonical Structure; _ The first form of this command declares an existing :n:`@reference` as a canonical instance of a structure (a record). The second form defines a new :term:`constant` as if the :cmd:`Definition` command had been used, then declares it as a canonical instance as if the first form had been used on the defined object. This command supports the :attr:`local` attribute. When used, the structure is canonical only within the :cmd:`Section` containing it. Outside a :cmd:`Section`, the structure is canonical as soon as :cmd:`Import` (or one of its variants) has been used on the :cmd:`Module` in which it is defined, regardless of its locality attribute, if any. :token:`qualid` (in :token:`reference`) denotes an object :n:`(Build_struct c__1 … c__n)` in the structure :g:`struct` for which the fields are :n:`x__1, …, x__n`. Then, each time an equation of the form :n:`(x__i _)` |eq_beta_delta_iota_zeta| :n:`c__i` has to be solved during the type checking process, :token:`qualid` is used as a solution. Otherwise said, :token:`qualid` is canonically used to extend the field :n:`x__i` into a complete structure built on :n:`c__i` when :n:`c__i` unifies with :n:`(x__i _)`. The following kinds of terms are supported for the fields :n:`c__i` of :token:`qualid`: * :term:`Constants ` and section variables of an active section, applied to zero or more arguments. * :token:`sort`\s. * Literal functions: `fun … => …`. * Literal, (possibly dependent) function types: `… -> …` and `forall …, …`. * Variables bound in :token:`qualid`. Only the head symbol of an existing instance's field :n:`c__i` is considered when searching for a canonical extension. We call this head symbol the *key* and we say ":token:`qualid` *keys* the field :n:`x__i` to :n:`k`" when :n:`c__i`'s head symbol is :n:`k`. Keys are the only piece of information that is used for canonical extension. The keys corresponding to the kinds of terms listed above are: * For constants and section variables, potentially applied to arguments: the constant or variable itself, disregarding any arguments. * For sorts: the sort itself. * For literal functions: skip the abstractions and use the key of the body. * For literal function types: a disembodied implication key denoted `forall _, _`, disregarding both its domain and codomain. * For variables bound in :token:`qualid`: a catch-all key denoted `_`. This means that, for example, `(some_constant x1)` and `(some_constant (other_constant y1 y2) x2)` are not distinct keys. Variables bound in :token:`qualid` match any term for the purpose of canonical extension. This has two major consequences for a field :n:`c__i` keyed to a variable of :token:`qualid`: 1. Unless another keyβ€”and, thus, instanceβ€”matches :n:`c__i`, the instance will always be considered by unification. 2. :n:`c__i` will be considered overlapping not distinct from any other canonical instance that keys :n:`x__i` to one of its own variables. A record field :n:`x__i` can only be keyed once to each key. Rocq prints a warning when :token:`qualid` keys :n:`x__i` to a term whose head symbol is already keyed by an existing canonical instance. In this case, Rocq will not register that :token:`qualid` as a canonical extension. (The remaining fields of the instance can still be used for canonical extension.) Canonical structures are particularly useful when mixed with coercions and strict implicit arguments. .. example:: Here is an example. .. rocqtop:: all reset Require Import Relation_Definitions. Set Implicit Arguments. Unset Strict Implicit. Structure Setoid : Type := {Carrier :> Set; Equal : relation Carrier; Prf_equiv : equivalence Carrier Equal}. Definition is_law (A B:Setoid) (f:A -> B) := forall x y:A, Equal x y -> Equal (f x) (f y). Parameter eq_nat : relation nat. Axiom eq_nat_equiv : equivalence nat eq_nat. Definition nat_setoid : Setoid := Build_Setoid eq_nat_equiv. Canonical nat_setoid. Thanks to :g:`nat_setoid` declared as canonical, the implicit arguments :g:`A` and :g:`B` can be synthesized in the next statement. .. rocqtop:: all abort Lemma is_law_S : is_law S. .. note:: If a same field occurs in several canonical structures, then only the structure declared first as canonical is considered. .. attr:: canonical{? = {| yes | no } } :name: canonical This :term:`boolean attribute` can decorate a :cmd:`Definition` or :cmd:`Let` command. It is equivalent to having a :cmd:`Canonical Structure` declaration just after the command. To prevent a field from being involved in the inference of canonical instances, its declaration can be annotated with ``canonical=no`` (cf. the syntax of :n:`@record_field`). .. example:: For instance, when declaring the :g:`Setoid` structure above, the :g:`Prf_equiv` field declaration could be written as follows. .. rocqdoc:: #[canonical=no] Prf_equiv : equivalence Carrier Equal See :ref:`hierarchy_of_structures` for a more realistic example. .. cmd:: Print Canonical Projections {* @reference } This displays the list of global names that are components of some canonical structure. For each of them, the canonical structure of which it is a projection is indicated. If :term:`constants ` are given as its arguments, only the unification rules that involve or are synthesized from simultaneously all given constants will be shown. .. example:: For instance, the above example gives the following output: .. rocqtop:: all Print Canonical Projections. .. rocqtop:: all Print Canonical Projections nat. .. note:: The last line in the first example would not show up if the corresponding projection (namely :g:`Prf_equiv`) were annotated as not canonical, as described above. Notation overloading ------------------------- We build an infix notation == for a comparison predicate. Such notation will be overloaded, and its meaning will depend on the types of the terms that are compared. .. rocqtop:: all reset Module EQ. Record class (T : Type) := Class { cmp : T -> T -> Prop }. Structure type := Pack { obj : Type; class_of : class obj }. Definition op (e : type) : obj e -> obj e -> Prop := let 'Pack _ (Class _ the_cmp) := e in the_cmp. Check op. Arguments op {e} x y : simpl never. Arguments Class {T} cmp. Module theory. Notation "x == y" := (op x y) (at level 70). End theory. End EQ. We use Rocq modules as namespaces. This allows us to follow the same pattern and naming convention for the rest of the chapter. The base namespace contains the definitions of the algebraic structure. To keep the example small, the algebraic structure ``EQ.type`` we are defining is very simplistic, and characterizes terms on which a binary relation is defined, without requiring such relation to validate any property. The inner theory module contains the overloaded notation ``==`` and will eventually contain lemmas holding all the instances of the algebraic structure (in this case there are no lemmas). Note that in practice the user may want to declare ``EQ.obj`` as a coercion, but we will not do that here. The following line tests that, when we assume a type ``e`` that is in the ``EQ`` class, we can relate two of its objects with ``==``. .. rocqtop:: all Import EQ.theory. Check forall (e : EQ.type) (a b : EQ.obj e), a == b. Still, no concrete type is in the ``EQ`` class. .. rocqtop:: all Fail Check 3 == 3. We amend that by equipping ``nat`` with a comparison relation. .. rocqtop:: all Definition nat_eq (x y : nat) := Nat.compare x y = Eq. Definition nat_EQcl : EQ.class nat := EQ.Class nat_eq. Canonical Structure nat_EQty : EQ.type := EQ.Pack nat nat_EQcl. Check 3 == 3. Eval compute in 3 == 4. This last test shows that Rocq is now not only able to type check ``3 == 3``, but also that the infix relation was bound to the ``nat_eq`` relation. This relation is selected whenever ``==`` is used on terms of type nat. This can be read in the line declaring the canonical structure ``nat_EQty``, where the first argument to ``Pack`` is the key and its second argument a group of canonical values associated with the key. In this case we associate with nat only one canonical value (since its class, ``nat_EQcl`` has just one member). The use of the projection ``op`` requires its argument to be in the class ``EQ``, and uses such a member (function) to actually compare its arguments. Similarly, we could equip any other type with a comparison relation, and use the ``==`` notation on terms of this type. Derived Canonical Structures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We know how to use ``==`` on base types, like ``nat``, ``bool``, ``Z``. Here we show how to deal with type constructors, i.e. how to make the following example work: .. rocqtop:: all Fail Check forall (e : EQ.type) (a b : EQ.obj e), (a, b) == (a, b). The error message is telling that Rocq has no idea on how to compare pairs of objects. The following construction is telling Rocq exactly how to do that. .. rocqtop:: all Definition pair_eq (e1 e2 : EQ.type) (x y : EQ.obj e1 * EQ.obj e2) := fst x == fst y /\ snd x == snd y. Definition pair_EQcl e1 e2 := EQ.Class (pair_eq e1 e2). Canonical Structure pair_EQty (e1 e2 : EQ.type) : EQ.type := EQ.Pack (EQ.obj e1 * EQ.obj e2) (pair_EQcl e1 e2). Check forall (e : EQ.type) (a b : EQ.obj e), (a, b) == (a, b). Check forall n m : nat, (3, 4) == (n, m). Thanks to the ``pair_EQty`` declaration, Rocq is able to build a comparison relation for pairs whenever it is able to build a comparison relation for each component of the pair. The declaration associates to the key ``*`` (the type constructor of pairs) the canonical comparison relation ``pair_eq`` whenever the type constructor ``*`` is applied to two types being themselves in the ``EQ`` class. .. _hierarchy_of_structures: Hierarchy of structures ---------------------------- To get to an interesting example we need another base class to be available. We choose the class of types that are equipped with an order relation, to which we associate the infix ``<=`` notation. .. rocqtop:: all Module LE. Record class T := Class { cmp : T -> T -> Prop }. Structure type := Pack { obj : Type; class_of : class obj }. Definition op (e : type) : obj e -> obj e -> Prop := let 'Pack _ (Class _ f) := e in f. Arguments op {_} x y : simpl never. Arguments Class {T} cmp. Module theory. Notation "x <= y" := (op x y) (at level 70). End theory. End LE. As before we register a canonical ``LE`` class for ``nat``. .. rocqtop:: all Import LE.theory. Definition nat_le x y := Nat.compare x y <> Gt. Definition nat_LEcl : LE.class nat := LE.Class nat_le. Canonical Structure nat_LEty : LE.type := LE.Pack nat nat_LEcl. And we enable Rocq to relate pair of terms with ``<=``. .. rocqtop:: all Definition pair_le e1 e2 (x y : LE.obj e1 * LE.obj e2) := fst x <= fst y /\ snd x <= snd y. Definition pair_LEcl e1 e2 := LE.Class (pair_le e1 e2). Canonical Structure pair_LEty (e1 e2 : LE.type) : LE.type := LE.Pack (LE.obj e1 * LE.obj e2) (pair_LEcl e1 e2). Check (3,4,5) <= (3,4,5). At the current stage we can use ``==`` and ``<=`` on concrete types, like tuples of natural numbers, but we can’t develop an algebraic theory over the types that are equipped with both relations. .. rocqtop:: all Check 2 <= 3 /\ 2 == 2. Fail Check forall (e : EQ.type) (x y : EQ.obj e), x <= y -> y <= x -> x == y. Fail Check forall (e : LE.type) (x y : LE.obj e), x <= y -> y <= x -> x == y. We need to define a new class that inherits from both ``EQ`` and ``LE``. .. rocqtop:: all Module LEQ. Record mixin (e : EQ.type) (le : EQ.obj e -> EQ.obj e -> Prop) := Mixin { compat : forall x y : EQ.obj e, le x y /\ le y x <-> x == y }. Record class T := Class { EQ_class : EQ.class T; LE_class : LE.class T; extra : mixin (EQ.Pack T EQ_class) (LE.cmp T LE_class) }. Structure type := _Pack { obj : Type; #[canonical=no] class_of : class obj }. Arguments Mixin {e le} _. Arguments Class {T} _ _ _. The mixin component of the ``LEQ`` class contains all the extra content we are adding to ``EQ`` and ``LE``. In particular it contains the requirement that the two relations we are combining are compatible. The `class_of` projection of the `type` structure is annotated as *not canonical*; it plays no role in the search for instances. Unfortunately there is still an obstacle to developing the algebraic theory of this new class. .. rocqtop:: all Module theory. Fail Check forall (le : type) (n m : obj le), n <= m -> n <= m -> n == m. The problem is that the two classes ``LE`` and ``LEQ`` are not yet related by a subclass relation. In other words Rocq does not see that an object of the ``LEQ`` class is also an object of the ``LE`` class. The following two constructions tell Rocq how to canonically build the ``LE.type`` and ``EQ.type`` structure given an ``LEQ.type`` structure on the same type. .. rocqtop:: all Definition to_EQ (e : type) : EQ.type := EQ.Pack (obj e) (EQ_class _ (class_of e)). Canonical Structure to_EQ. Definition to_LE (e : type) : LE.type := LE.Pack (obj e) (LE_class _ (class_of e)). Canonical Structure to_LE. We can now formulate out first theorem on the objects of the ``LEQ`` structure. .. rocqtop:: all Lemma lele_eq (e : type) (x y : obj e) : x <= y -> y <= x -> x == y. now intros; apply (compat _ _ (extra _ (class_of e)) x y); split. Qed. Arguments lele_eq {e} x y _ _. End theory. End LEQ. Import LEQ.theory. Check lele_eq. Of course one would like to apply results proved in the algebraic setting to any concrete instate of the algebraic structure. .. rocqtop:: all Example test_algebraic (n m : nat) : n <= m -> m <= n -> n == m. Fail apply (lele_eq n m). Abort. Example test_algebraic2 (l1 l2 : LEQ.type) (n m : LEQ.obj l1 * LEQ.obj l2) : n <= m -> m <= n -> n == m. Fail apply (lele_eq n m). Abort. Again one has to tell Rocq that the type ``nat`` is in the ``LEQ`` class, and how the type constructor ``*`` interacts with the ``LEQ`` class. In the following proofs are omitted for brevity. .. rocqtop:: all Lemma nat_LEQ_compat (n m : nat) : n <= m /\ m <= n <-> n == m. Admitted. Definition nat_LEQmx := LEQ.Mixin nat_LEQ_compat. Lemma pair_LEQ_compat (l1 l2 : LEQ.type) (n m : LEQ.obj l1 * LEQ.obj l2) : n <= m /\ m <= n <-> n == m. Admitted. Definition pair_LEQmx l1 l2 := LEQ.Mixin (pair_LEQ_compat l1 l2). The following script registers an ``LEQ`` class for ``nat`` and for the type constructor ``*``. It also tests that they work as expected. Unfortunately, these declarations are very verbose. In the following subsection we show how to make them more compact. .. rocqtop:: all Module Add_instance_attempt. Canonical Structure nat_LEQty : LEQ.type := LEQ._Pack nat (LEQ.Class nat_EQcl nat_LEcl nat_LEQmx). Canonical Structure pair_LEQty (l1 l2 : LEQ.type) : LEQ.type := LEQ._Pack (LEQ.obj l1 * LEQ.obj l2) (LEQ.Class (EQ.class_of (pair_EQty (to_EQ l1) (to_EQ l2))) (LE.class_of (pair_LEty (to_LE l1) (to_LE l2))) (pair_LEQmx l1 l2)). Example test_algebraic (n m : nat) : n <= m -> m <= n -> n == m. now apply (lele_eq n m). Qed. Example test_algebraic2 (n m : nat * nat) : n <= m -> m <= n -> n == m. now apply (lele_eq n m). Qed. End Add_instance_attempt. Note that no direct proof of ``n <= m -> m <= n -> n == m`` is provided by the user for ``n`` and m of type ``nat * nat``. What the user provides is a proof of this statement for ``n`` and ``m`` of type ``nat`` and a proof that the pair constructor preserves this property. The combination of these two facts is a simple form of proof search that Rocq performs automatically while inferring canonical structures. Compact declaration of Canonical Structures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We need some infrastructure for that. .. rocqtop:: all Module infrastructure. Inductive phantom {T : Type} (t : T) := Phantom. Variant err := | Is_not_an_EQ_type | Is_not_an_LE_type | Is_not_the_right_mixin. Definition unify {T1 T2} (t1 : T1) (t2 : T2) (s : option err) := phantom t1 -> phantom t2. Definition id {T} {t : T} (x : phantom t) := x. Notation "[find v | t1 ~ t2 ] p" := (fun v (_ : unify t1 t2 None) => p) (at level 50, v name, p at level 50, only parsing). Notation "[find v | t1 ~ t2 | s ] p" := (fun v (_ : unify t1 t2 (Some s)) => p) (at level 50, v name, p at level 50, only parsing). Notation "'Error : t : s" := (unify _ t (Some s)) (at level 50, format "''Error' : t : s"). End infrastructure. To explain the notation ``[find v | t1 ~ t2]`` let us pick one of its instances: ``[find e | EQ.obj e ~ T | Is_not_an_EQ_type ]``. It should be read as: β€œfind a class e such that its objects have type T or fail with message "T is not an EQ.type"”. The other utilities are used to ask Rocq to solve a specific unification problem, that will in turn require the inference of some canonical structures. They are explained in more details in :cite:`CSwcu`. We now have all we need to create a compact β€œpackager” to declare instances of the ``LEQ`` class. .. rocqtop:: all Import infrastructure. Definition packager T e0 le0 (m0 : LEQ.mixin e0 le0) := [find e | EQ.obj e ~ T | Is_not_an_EQ_type ] [find o | LE.obj o ~ T | Is_not_an_LE_type ] [find ce | EQ.class_of e ~ ce ] [find co | LE.class_of o ~ co ] [find m | m ~ m0 | Is_not_the_right_mixin ] LEQ._Pack T (LEQ.Class ce co m). Abbreviation Pack T m := (packager T _ _ m _ id _ id _ id _ id _ id). The object ``Pack`` takes a type ``T`` (the key) and a mixin ``m``. It infers all the other pieces of the class ``LEQ`` and declares them as canonical values associated with the ``T`` key. All in all, the only new piece of information we add in the ``LEQ`` class is the mixin, all the rest is already canonical for ``T`` and hence can be inferred by Rocq. ``Pack`` is a notation, hence it is not type checked at the time of its declaration. It will be type checked when it is used, and in that case ``T`` is going to be a concrete type. The odd arguments ``_`` and ``id`` we pass to the packager represent respectively the classes to be inferred (like ``e``, ``o``, etc) and a token (``id``) to force their inference. Again, for all the details the reader can refer to :cite:`CSwcu`. The declaration of canonical instances can now be way more compact: .. rocqtop:: all Canonical Structure nat_LEQty := Eval hnf in Pack nat nat_LEQmx. Canonical Structure pair_LEQty (l1 l2 : LEQ.type) := Eval hnf in Pack (LEQ.obj l1 * LEQ.obj l2) (pair_LEQmx l1 l2). Error messages are also quite intelligible (if one skips to the end of the message). .. rocqtop:: all Fail Canonical Structure err := Eval hnf in Pack bool nat_LEQmx. rocq-9.2.0/doc/sphinx/language/extensions/compil-steps.rst000066400000000000000000000155211516144147600237140ustar00rootroot00000000000000.. _compil-steps: ======================== Command level processing ======================== When a command, for instance :g:`Check 1 + 2 * 2.` is fed to Rocq, it goes through several *successive* processing steps: * :term:`lexing` splits the input string into a sequence of tokens ; * :term:`parsing` converts the sequence of tokens into a syntax tree ; * :term:`synterp` does just enough to be able to proceed parsing the file (that is, executes the few commands that can modify the lexer or parser) ; * :term:`interp` executes the bulk of the parsed commands. .. note:: Understanding the distinction between lexing and parsing is sometimes required to make good use of the notation features. The synterp/interp distinction, while important for developers, should be mostly transparent for users. Lexing ~~~~~~ The first step, :gdef:`lexing` splits the input into a sequence of tokens, for instance the string ``"Check 1 + 2 * 2."`` is split into the sequence of seven tokens `'Check' '1' '+' '2' '*' '2' '.'`. A set of :ref:`basic tokens ` are predefined and can be extended, in particular by :ref:`reserving notations `. Parsing ~~~~~~~ During :gdef:`parsing` the sequence of tokens is interpreted as a tree, for instance here: .. code-block:: text :name: after-parsing Check | + / \ 1 * / \ 2 2 The parsed grammar can be modified, for instance by :ref:`reserving notations `. Synterp ~~~~~~~ In addition to the above lexing and parsing, the :gdef:`synterp` phase does just enough to be able to parse the remaining commands. Typically, this means applying the effects of :cmd:`Reserved Notation` commands. Plugins loading, :cmd:`Require` and :cmd:`Import` commands can also have synterp effects. Interp ~~~~~~ The :gdef:`interp` phase performs the specific effect of each command. If the command contains terms, they will be processed in distinct steps as explained below. .. note:: Depending on the Rocq interface used (``rocq compile``, ``rocq top`` or various IDEs), Rocq may run the interp phase for each command immediately after its synterp phase, or it may run the synterp phase for every command in the file before running any interp step, or any other interleaving. ===================== Term level processing ===================== It is in theory possible to write down every term explicitly as described in the :ref:`Core Language ` part of this manual, for instance :n:`Nat.add (S O) (Nat.mul (S (S O)) (S (S O)))`. However, this would be very tedious and error-prone and takes us away from our usual mathematical practice. To circumvent this, Rocq offers multiple preprocessing mechanisms to help fill the gap between what the users would like to input to the system and the fully formal core language expected by the kernel. We give an overview of all these steps below. For instance, the notation mechanisms reflect the eponymous mathematical practice and allows to write :n:`1 + 2 * 2` instead of the above term. Those mechanisms range from simple :ref:`Abbreviations` to full fledged :ref:`Notations` with user defined :ref:`syntaxes `. Multiple interpretations can be given to the same syntax in different contexts thanks to the :ref:`scope ` mechanism. For instance :n:`(1 + 2 * 2)%N` can be the above natural number expression while :n:`(1 + 2 * 2)%Z` can be an expression with integers. In order to take the best part of all these preprocessing mechanisms, one needs a basic understanding of the multiple steps needed to transform an inputted term (possibly with notations) into the valid Gallina term which Rocq will ultimately use internally. Terms given as input to Rocq go through several successive steps: * First, :term:`lexing`, then :term:`parsing`, are performed as part of any command processing, as described above. * During :gdef:`internalization` a number of things are resolved. This includes :ref:`name resolution `, :term:`notation interpretation` and introduction of :term:`holes ` for :ref:`implicit arguments `. :gdef:`Notation interpretation ` translates each syntactic element to a term, for instance :n:`1` can be interpreted as the natural number :n:`S O` then :n:`2` is interpreted as :n:`S (S O)`, then :n:`2 * 2` as :n:`Nat.mul (S (S O)) (S (S O))` and finally our whole term as :n:`Nat.add (S O) (Nat.mul (S (S O)) (S (S O)))`. The same expression can be given multiple interpretations in various contexts thanks to :ref:`Scopes`. * Finally, :gdef:`type inference`, can use the various mechanisms described in this section to fill gaps (for instance with :ref:`canonical structures ` or :ref:`typeclasses`) or fix terms (for instance with :ref:`coercions `) to obtain fully detailed terms in the :ref:`Core Language `. For each term, Rocq performs these steps *successively* and *independently*. Then, the result goes through the type checking phases discussed in :ref:`previous chapter `. None of the steps has any impact on the previous ones. In particular, no typechecking is involved during parsing or internalization. Also note that none of the features resolved during these phases, like unqualified names, implicit arguments or notations, remains during the later type inference and type checking phases. .. note:: The :term:`type inference` phase together with, all or part of, the previous steps is sometimes called elaboration in the literature. .. example:: Simple interleaving of intern and type inference phases The command :g:`Definition foo : T := body.` has a trivial :term:`synterp` phase. Indeed, it doesn't influence any further parsing. Its :term:`interp` phase will internalize :g:`T` and infer types in it, then it will internalize :g:`body` and infer types in it, using :g:`T` as expected type. Note that the result of type inference in :g:`T` matters in internalization of :g:`body`, for instance for selecting notation scopes. Finally, the resulting :g:`foo : T := body` is sent to the kernel. .. example:: Delayed steps :g:`Ltac foo := exact term.` will internalize :g:`term` and save the result. Only when the :g:`foo` tactic will be called, will the type inference on the resulting :n:`term` be run, with the type of the current goal as expected type. If this succeeds, the proof state will be updated to fill the goal, and the kernel will see the result at :cmd:`Qed`. .. example:: Reserved notation The command :g:`Reserved Notation "x + y" (at level 50, left associativity).` has a non trivial synterp phase, as it extends the parser so that :n:`_ + _` can later be parsed. Its interp phase is then trivial, as there is nothing left to do. rocq-9.2.0/doc/sphinx/language/extensions/evars.rst000066400000000000000000000204541516144147600224160ustar00rootroot00000000000000.. extracted from Gallina extensions chapter .. _existential-variables: Existential variables --------------------- :gdef:`Existential variables ` represent as yet unknown values. .. insertprodn term_evar term_evar .. prodn:: term_evar ::= _ | ?[ @ident ] | ?[ ?@ident ] | ?@ident {? @%{ {+; @ident := @term } %} } Rocq terms can include existential variables that represent unknown subterms that are eventually replaced with actual subterms. Existential variables are generated in place of unsolved implicit arguments or β€œ_” placeholders when using commands such as ``Check`` (see Section :ref:`requests-to-the-environment`) or when using tactics such as :tacn:`refine`, as well as in place of unsolved instances when using tactics such that :tacn:`eapply`. An existential variable is defined in a context, which is the context of variables of the placeholder which generated the existential variable, and a type, which is the expected type of the placeholder. As a consequence of typing constraints, existential variables can be duplicated in such a way that they possibly appear in different contexts than their defining context. Thus, any occurrence of a given existential variable comes with an instance of its original context. In the simple case, when an existential variable denotes the placeholder which generated it, or is used in the same context as the one in which it was generated, the context is not displayed and the existential variable is represented by β€œ?” followed by an identifier. .. rocqtop:: all Parameter identity : forall (X:Set), X -> X. Check identity _ _. Check identity _ (fun x => _). In the general case, when an existential variable :n:`?@ident` appears outside its context of definition, its instance, written in the form :n:`{ {*; @ident := @term} }`, is appended to its name, indicating how the variables of its defining context are instantiated. Only the variables that are defined in another context are displayed: this is why an existential variable used in the same context as its context of definition is written with no instance. This behavior may be changed: see :ref:`explicit-display-existentials`. .. rocqtop:: all Check (fun x y => _) 0 1. Existential variables can be named by the user upon creation using the syntax :n:`?[@ident]`. This is useful when the existential variable needs to be explicitly handled later in the script (e.g. with a named-goal selector, see :ref:`goal-selectors`). .. extracted from Gallina chapter .. index:: _ Inferable subterms ~~~~~~~~~~~~~~~~~~ .. todo: This topic deserves considerably more explanation, but this will have to do for now @name allows `_` (used in 43 places in the grammar), but IIUC is semantically restricted. Some of the cases: * match expressions in terms (see :n:`@term_match`) * binders (see :n:`@name`) in let, functions * function parameters * universe levels relation to implicit arguments? also intropatterns and hints paths, which are not terms :n:`@term`\s may use :gdef:`holes `, denoted by :n:`_`, for purposes such as: * Omitting redundant subterms. Redundant subterms that Rocq is able to infer can be replaced with :n:`_`. For example HELP ME HERE. * Indicating where existential variables should be created in e* tactics such as :tacn:`assert`. is it possible to see holes in the context for any of these? Expressions often contain redundant pieces of information. Subterms that can be automatically inferred by Rocq can be replaced by the symbol ``_`` and Rocq will guess the missing piece of information. e* tactics that can create existential variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A number of tactics have companion tactics that create existential variables when the base tactic would fail because of uninstantiated variables. The companion tactic names begin with an :n:`e` followed by the name of the base tactic. For example, :tacn:`eapply` works the same way as :tacn:`apply`, except that it will create new existential variable(s) when :tacn:`apply` would fail. .. example:: apply vs eapply Both tactics unify the goal with :n:`x = z` in the theorem. :n:`y` is unspecified. This makes :tacn:`apply` fail, while :tacn:`eapply` creates a new existential variable :n:`?y`. .. rocqtop:: none reset Goal forall i j : nat, i = j. intros. .. rocqtop:: all (* Theorem eq_trans : forall (A : Type) (x y z : A), x = y -> y = z -> x = z. *) Fail apply eq_trans. eapply eq_trans. The :n:`e*` tactics include: .. list-table:: * - :tacn:`eapply` - :tacn:`eassert` - :tacn:`eassumption` - :tacn:`eauto` * - :tacn:`ecase` - :tacn:`econstructor` - :tacn:`edestruct` - :tacn:`ediscriminate` * - :tacn:`eelim` - :tacn:`eenough` - :tacn:`eexact` - :tacn:`eexists` * - :tacn:`einduction` - :tacn:`einjection` - :tacn:`eintros` - :tacn:`eleft` * - :tacn:`epose` - :tacn:`eremember` - :tacn:`erewrite` - :tacn:`eright` * - :tacn:`eset` - :tacn:`esimplify_eq` - :tacn:`esplit` - :tacn:`etransitivity` Note that :tacn:`eassumption` and :tacn:`eauto` behave differently from the others. Automatic resolution of existential variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Existential variables that are used in other goals are generally resolved automatically as a side effect of other tactics. .. _automatic-evar-resolution: .. example:: Automatic resolution of existential variables :n:`?y` is used in other goals. The :tacn:`exact` shown below determines the value of this variable by unification, which resolves it. .. rocqtop:: reset in Set Printing Goal Names. Goal forall p n m : nat, n = p -> p = m -> n = m. .. rocqtop:: all intros x y z H1 H2. eapply eq_trans. (* creates ?y : nat as a shelved goal *) Unshelve. (* moves the shelved goals into focus--not needed and usually not done *) exact H1. (* resolves the first goal and by side effect ?y *) The :n:`?y` goal asks for proof that :n:`nat` has an :term:`inhabitant`, i.e. it is not an empty type. This can be proved directly by applying a constructor of :n:`nat`, which assigns values for :n:`?y`. However if you choose poorly, you can end up with unprovable goals (in this case :n:`x = 0`). Like this: .. rocqtop:: reset none Set Printing Goal Names. Goal forall p n m : nat, n = p -> p = m -> n = m. intros x y z H1 H2. eapply eq_trans. (* creates ?y : nat as a shelved goal *) .. rocqtop:: out Unshelve. (* moves the shelved goals into focus--not needed and usually not done *) .. rocqtop:: all 3: apply 0. (* assigns value to ?y *) .. extracted from Gallina extensions chapter .. _explicit-display-existentials: Explicit display of existential instances for pretty-printing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Printing Existential Instances Activates the full display of how the context of an existential variable is instantiated at each of the occurrences of the existential variable. Off by default. .. rocqtop:: all Check (fun x y => _) 0 1. Set Printing Existential Instances. Check (fun x y => _) 0 1. .. _tactics-in-terms: Solving existential variables using tactics ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Instead of letting the unification engine try to solve an existential variable by itself, one can also provide an explicit hole together with a tactic to solve it. Using the syntax ``ltac:(``\ `tacexpr`\ ``)``, the user can put a tactic anywhere a term is expected. The order of resolution is not specified and is implementation-dependent. The inner tactic may use any variable defined in its scope, including repeated alternations between variables introduced by term binding as well as those introduced by tactic binding. The expression `tacexpr` can be any tactic expression as described in :ref:`ltac`. .. rocqtop:: all Definition foo (x : nat) : nat := ltac:(exact x). This construction is useful when one wants to define complicated terms using highly automated tactics without resorting to writing the proof-term by means of the interactive proof engine. rocq-9.2.0/doc/sphinx/language/extensions/implicit-arguments.rst000066400000000000000000000531031516144147600251100ustar00rootroot00000000000000.. _ImplicitArguments: Implicit arguments ------------------ An :gdef:`implicit argument` of a function is an argument which can be inferred from contextual knowledge. There are different kinds of implicit arguments that can be considered implicit in different ways. There are also various commands to control the setting or the inference of implicit arguments. The different kinds of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implicit arguments inferable from the knowledge of other arguments of a function ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The first kind of implicit arguments covers the arguments that are inferable from the knowledge of the type of other arguments of the function, or of the type of the surrounding context of the application. Especially, such implicit arguments correspond to parameters dependent in the type of the function. Typical implicit arguments are the type arguments in polymorphic functions. There are several kinds of such implicit arguments. **Strict Implicit Arguments** An implicit argument can be either strict or non-strict. An implicit argument is said to be *strict* if, whatever the other arguments of the function are, it is still inferable from the type of some other argument. Technically, an implicit argument is strict if it corresponds to a parameter which is not applied to a variable which itself is another parameter of the function (since this parameter may erase its arguments), not in the body of a match, and not itself applied or matched against patterns (since the original form of the argument can be lost by reduction). For instance, the first argument of :: cons: forall A:Set, A -> list A -> list A in module ``List.v`` is strict because :g:`list` is an inductive type and :g:`A` will always be inferable from the type :g:`list A` of the third argument of :g:`cons`. Also, the first argument of :g:`cons` is strict with respect to the second one, since the first argument is exactly the type of the second argument. On the contrary, the second argument of a term of type :: forall P:nat->Prop, forall n:nat, P n -> ex nat P is implicit but not strict, since it can only be inferred from the type :g:`P n` of the third argument and if :g:`P` is, e.g., :g:`fun _ => True`, it reduces to an expression where ``n`` does not occur any longer. The first argument :g:`P` is implicit but not strict either because it can only be inferred from :g:`P n` and :g:`P` is not canonically inferable from an arbitrary :g:`n` and the normal form of :g:`P n`. Consider, e.g., that :g:`n` is :math:`0` and the third argument has type :g:`True`, then any :g:`P` of the form :: fun n => match n with 0 => True | _ => anything end would be a solution of the inference problem. **Contextual Implicit Arguments** An implicit argument can be *contextual* or not. An implicit argument is said to be *contextual* if it can be inferred only from the knowledge of the type of the context of the current expression. For instance, the only argument of:: nil : forall A:Set, list A is contextual. Similarly, both arguments of a term of type:: forall P:nat->Prop, forall n:nat, P n \/ n = 0 are contextual (moreover, :g:`n` is strict and :g:`P` is not). **Reversible-Pattern Implicit Arguments** There is another class of implicit arguments that can be reinferred unambiguously if all the types of the remaining arguments are known. This is the class of implicit arguments occurring in the type of another argument in position of reversible pattern, which means it is at the head of an application but applied only to uninstantiated distinct variables. Such an implicit argument is called *reversible- pattern implicit argument*. A typical example is the argument :g:`P` of nat_rec in :: nat_rec : forall P : nat -> Set, P 0 -> (forall n : nat, P n -> P (S n)) -> forall x : nat, P x (:g:`P` is reinferable by abstracting over :g:`n` in the type :g:`P n`). See :ref:`controlling-rev-pattern-implicit-args` for the automatic declaration of reversible-pattern implicit arguments. Implicit arguments inferable by resolution ++++++++++++++++++++++++++++++++++++++++++ This corresponds to a class of non-dependent implicit arguments that are solved based on the structure of their type only. Maximal and non-maximal insertion of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When a function is partially applied and the next argument to apply is an implicit argument, the application can be interpreted in two ways. If the next argument is declared as *maximally inserted*, the partial application will include that argument. Otherwise, the argument is *non-maximally inserted* and the partial application will not include that argument. Each implicit argument can be declared to be inserted maximally or non maximally. In Rocq, maximally inserted implicit arguments are written between curly braces "{ }" and non-maximally inserted implicit arguments are written in square brackets "[ ]". .. seealso:: :flag:`Maximal Implicit Insertion` Trailing Implicit Arguments +++++++++++++++++++++++++++ An implicit argument is considered *trailing* when all following arguments are implicit. Trailing implicit arguments must be declared as maximally inserted; otherwise they would never be inserted. .. exn:: Argument @name is a trailing implicit, so it can't be declared non maximal. Please use %{ %} instead of [ ]. For instance: .. rocqtop:: all fail Fail Definition double [n] := n + n. Casual use of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If an argument of a function application can be inferred from the type of the other arguments, the user can force inference of the argument by replacing it with `_`. .. exn:: Cannot infer a term for this placeholder. :name: Cannot infer a term for this placeholder. (Casual use of implicit arguments) Rocq was not able to deduce an instantiation of a β€œ_”. .. _declare-implicit-args: Declaration of implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implicit arguments can be declared when a function is declared or afterwards, using the :cmd:`Arguments` command. Implicit Argument Binders +++++++++++++++++++++++++ .. insertprodn implicit_binders implicit_binders .. prodn:: implicit_binders ::= %{ {+ @name } {? : @type } %} | [ {+ @name } {? : @type } ] In the context of a function definition, these forms specify that :token:`name` is an implicit argument. The first form, with curly braces, makes :token:`name` a maximally inserted implicit argument. The second form, with square brackets, makes :token:`name` a non-maximally inserted implicit argument. For example: .. rocqtop:: all Definition id {A : Type} (x : A) : A := x. declares the argument `A` of `id` as a maximally inserted implicit argument. `A` may be omitted in applications of `id` but may be specified if needed: .. rocqtop:: all abort Definition compose {A B C} (g : B -> C) (f : A -> B) := fun x => g (f x). Goal forall A, compose id id = id (A:=A). For non-maximally inserted implicit arguments, use square brackets: .. rocqtop:: all Fixpoint map [A B : Type] (f : A -> B) (l : list A) : list B := match l with | nil => nil | cons a t => cons (f a) (map f t) end. Print Implicit map. For (co)inductive datatype declarations, the semantics are the following: an inductive parameter declared as an implicit argument need not be repeated in the inductive definition and will become implicit for the inductive type and the constructors. For example: .. rocqtop:: all Inductive list {A : Type} : Type := | nil : list | cons : A -> list -> list. Print list. One can always specify the parameter if it is not uniform using the usual implicit arguments disambiguation syntax. The syntax is also supported in internal binders. For instance, in the following kinds of expressions, the type of each declaration present in :n:`{* @binder }` can be bracketed to mark the declaration as implicit: * :n:`fun (@ident:forall {* @binder }, @type) => @term`, * :n:`forall (@ident:forall {* @binder }, @type), @type`, * :n:`let @ident {* @binder } := @term in @term`, * :n:`fix @ident {* @binder } := @term in @term` and * :n:`cofix @ident {* @binder } := @term in @term`. Here is an example: .. rocqtop:: all Axiom Ax : forall (f:forall {A} (a:A), A * A), let g {A} (x y:A) := (x,y) in f 0 = g 0 0. .. warn:: Ignoring implicit binder declaration in unexpected position This is triggered when setting an argument implicit in an expression which does not correspond to the type of an assumption or to the :term:`body` of a definition. Here is an example: .. rocqtop:: all warn Definition f := forall {y}, y = 0. .. warn:: Making shadowed name of implicit argument accessible by position This is triggered when two variables of same name are set implicit in the same block of binders, in which case the first occurrence is considered to be unnamed. Here is an example: .. rocqtop:: all warn Check let g {x:nat} (H:x=x) {x} (H:x=x) := x in 0. Mode for automatic declaration of implicit arguments ++++++++++++++++++++++++++++++++++++++++++++++++++++ .. flag:: Implicit Arguments This :term:`flag` (off by default) allows to systematically declare implicit the arguments detectable as such. Auto-detection of implicit arguments is governed by flags controlling whether strict and contextual implicit arguments have to be considered or not. .. _controlling-strict-implicit-args: Controlling strict implicit arguments +++++++++++++++++++++++++++++++++++++ .. flag:: Strict Implicit When the mode for automatic declaration of implicit arguments is on, the default is to automatically set implicit only the strict implicit arguments plus, for historical reasons, a small subset of the non-strict implicit arguments. To relax this constraint and to set implicit all non-strict implicit arguments by default, you can turn this :term:`flag` off. .. flag:: Strongly Strict Implicit Use this :term:`flag` (off by default) to capture exactly the strict implicit arguments and no more than the strict implicit arguments. .. _controlling-contextual-implicit-args: Controlling contextual implicit arguments +++++++++++++++++++++++++++++++++++++++++ .. flag:: Contextual Implicit By default, Rocq does not automatically set implicit the contextual implicit arguments. You can turn this :term:`flag` on to tell Rocq to also infer contextual implicit argument. .. _controlling-rev-pattern-implicit-args: Controlling reversible-pattern implicit arguments +++++++++++++++++++++++++++++++++++++++++++++++++ .. flag:: Reversible Pattern Implicit By default, Rocq does not automatically set implicit the reversible-pattern implicit arguments. You can turn this :term:`flag` on to tell Rocq to also infer reversible-pattern implicit argument. .. _controlling-insertion-implicit-args: Controlling the insertion of implicit arguments not followed by explicit arguments ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. flag:: Maximal Implicit Insertion Assuming the implicit argument mode is on, this :term:`flag` (off by default) declares implicit arguments to be automatically inserted when a function is partially applied and the next argument of the function is an implicit one. Combining manual declaration and automatic declaration ++++++++++++++++++++++++++++++++++++++++++++++++++++++ When some arguments are manually specified implicit with binders in a definition and the automatic declaration mode in on, the manual implicit arguments are added to the automatically declared ones. In that case, and when the flag :flag:`Maximal Implicit Insertion` is set to off, some trailing implicit arguments can be inferred to be non-maximally inserted. In this case, they are converted to maximally inserted ones. .. example:: .. rocqtop:: all Set Implicit Arguments. Axiom eq0_le0 : forall (n : nat) (x : n = 0), n <= 0. Print Implicit eq0_le0. Axiom eq0_le0' : forall (n : nat) {x : n = 0}, n <= 0. Print Implicit eq0_le0'. .. _explicit-applications: Explicit applications ~~~~~~~~~~~~~~~~~~~~~ In presence of non-strict or contextual arguments, or in presence of partial applications, the synthesis of implicit arguments may fail, so one may have to explicitly give certain implicit arguments of an application. To instantiate a dependent implicit argument, use the :n:`(@ident := @term)` form of :token:`arg`, where :token:`ident` is the name of the implicit argument and :token:`term` is its corresponding explicit term. To instantiate a non-dependent implicit argument, use the :n:`(@natural := @term)` form of :token:`arg`, where :token:`natural` is the index of the implicit argument among all non-dependent arguments of the function (implicit or not, and starting from 1) and :token:`term` is its corresponding explicit term. Alternatively, one can deactivate the hiding of implicit arguments for a single function application using the :n:`@@qualid_annotated {+ @term1 }` form of :token:`term_application`. .. example:: Syntax for explicitly giving implicit arguments (continued) .. rocqtop:: all Parameter X : Type. Definition Relation := X -> X -> Prop. Definition Transitivity (R:Relation) := forall x y:X, R x y -> forall z:X, R y z -> R x z. Parameters (R : Relation) (p : Transitivity R). Arguments p : default implicits. Print Implicit p. Parameters (a b c : X) (r1 : R a b) (r2 : R b c). Check (p r1 (z:=c)). Check (p (x:=a) (y:=b) r1 (z:=c) r2). .. exn:: Wrong argument name :undocumented: .. exn:: Wrong argument position :undocumented: .. exn:: Argument at position @natural is mentioned more than once :undocumented: .. exn:: Arguments given by name or position not supported in explicit mode :undocumented: .. exn:: Not enough non implicit arguments to accept the argument bound to @ident :undocumented: .. exn:: Not enough non implicit arguments to accept the argument bound to @natural :undocumented: .. _displaying-implicit-args: Displaying implicit arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Print Implicit @reference Displays the implicit arguments associated with an object, identifying which arguments are applied maximally or not. Displaying implicit arguments when pretty-printing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Printing Implicit By default, the basic pretty-printing rules hide the inferable implicit arguments of an application. Turn this :term:`flag` on to force printing all implicit arguments. .. flag:: Printing Implicit Defensive By default, the basic pretty-printing rules display implicit arguments that are not detected as strict implicit arguments. This β€œdefensive” mode can quickly make the display cumbersome so this can be deactivated by turning this :term:`flag` off. .. seealso:: :flag:`Printing All`. Interaction with subtyping ~~~~~~~~~~~~~~~~~~~~~~~~~~ When an implicit argument can be inferred from the type of more than one of the other arguments, then only the type of the first of these arguments is taken into account, and not an upper type of all of them. As a consequence, the inference of the implicit argument of β€œ=” fails in .. rocqtop:: all Fail Check nat = Prop. but succeeds in .. rocqtop:: all Check Prop = nat. .. _deactivation-of-implicit-arguments: Deactivation of implicit arguments for parsing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. insertprodn term_explicit term_explicit .. prodn:: term_explicit ::= @ @qualid_annotated This syntax can be used to disable implicit arguments for a single function. .. example:: The function `id` has one implicit argument and one explicit argument. .. rocqtop:: all reset Check (id 0). Definition id' := @id. The function `id'` has no implicit argument. .. rocqtop:: all Check (id' nat 0). .. flag:: Parsing Explicit Turning this :term:`flag` on (it is off by default) deactivates the use of implicit arguments. In this case, all arguments of :term:`constants `, inductive types, constructors, etc, including the arguments declared as implicit, have to be given as if no arguments were implicit. By symmetry, this also affects printing. .. example:: We can reproduce the example above using the :flag:`Parsing Explicit` flag: .. rocqtop:: all reset Set Parsing Explicit. Definition id' := id. Unset Parsing Explicit. Check (id 1). Check (id' nat 1). Implicit types of variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is possible to bind variable names to a given type (e.g. in a development using arithmetic, it may be convenient to bind the names :g:`n` or :g:`m` to the type :g:`nat` of natural numbers). .. cmd:: Implicit {| Type | Types } @reserv_list :name: Implicit Type; Implicit Types .. insertprodn reserv_list simple_reserv .. prodn:: reserv_list ::= {+ ( @simple_reserv ) } | @simple_reserv simple_reserv ::= {+ @ident } : @type Sets the type of bound variables starting with :token:`ident` (either :token:`ident` itself or :token:`ident` followed by one or more single quotes, underscore or digits) to :token:`type` (unless the bound variable is already declared with an explicit type, in which case, that type will be used). .. example:: .. rocqtop:: all Require Import ListDef. Implicit Types m n : nat. Lemma cons_inj_nat : forall m n l, n :: l = m :: l -> n = m. Proof. intros m n. Abort. Lemma cons_inj_bool : forall (m n:bool) l, n :: l = m :: l -> n = m. Abort. .. flag:: Printing Use Implicit Types By default, the type of bound variables is not printed when the variable name is associated with an implicit type which matches the actual type of the variable. This feature can be deactivated by turning this :term:`flag` off. .. _implicit-generalization: Implicit generalization ~~~~~~~~~~~~~~~~~~~~~~~ .. index:: `{ } .. index:: `[ ] .. index:: `( ) .. index:: `{! } .. index:: `[! ] .. index:: `(! ) .. insertprodn generalizing_binder term_generalizing .. prodn:: generalizing_binder ::= `( {+, @typeclass_constraint } ) | `%{ {+, @typeclass_constraint } %} | `[ {+, @typeclass_constraint } ] typeclass_constraint ::= {? ! } @term | %{ @name %} : {? ! } @term | @name : {? ! } @term term_generalizing ::= `%{ @term %} | `( @term ) Implicit generalization is an automatic elaboration of a statement with free variables into a closed statement where these variables are quantified explicitly. Use the :cmd:`Generalizable` command to designate which variables should be generalized. It is activated within a binder by prefixing it with \`, and for terms by surrounding it with \`{ }, or \`[ ] or \`( ). Terms surrounded by \`{ } introduce their free variables as maximally inserted implicit arguments, terms surrounded by \`[ ] introduce them as non-maximally inserted implicit arguments and terms surrounded by \`( ) introduce them as explicit arguments. Generalizing binders always introduce their free variables as maximally inserted implicit arguments. The binder itself introduces its argument as usual. In the following statement, ``A`` and ``y`` are automatically generalized, ``A`` is implicit and ``x``, ``y`` and the anonymous equality argument are explicit. .. rocqtop:: all reset Generalizable All Variables. Definition sym `(x:A) : `(x = y -> y = x) := fun _ p => eq_sym p. Print sym. Dually to normal binders, the name is optional but the type is required: .. rocqtop:: all Check (forall `{x = y :> A}, y = x). When generalizing a binder whose type is a typeclass, its own class arguments are omitted from the syntax and are generalized using automatic names, without instance search. Other arguments are also generalized unless provided. This produces a fully general statement. this behavior may be disabled by prefixing the type with a ``!`` or by forcing the typeclass name to be an explicit application using ``@`` (however the later ignores implicit argument information). .. rocqtop:: all Class Op (A:Type) := op : A -> A -> A. Class Commutative (A:Type) `(Op A) := commutative : forall x y, op x y = op y x. Instance nat_op : Op nat := plus. Set Printing Implicit. Check (forall `{Commutative }, True). Check (forall `{Commutative nat}, True). Fail Check (forall `{Commutative nat _}, True). Fail Check (forall `{!Commutative nat}, True). Arguments Commutative _ {_}. Check (forall `{!Commutative nat}, True). Check (forall `{@Commutative nat plus}, True). Multiple binders can be merged using ``,`` as a separator: .. rocqtop:: all Check (forall `{Commutative A, Hnat : !Commutative nat}, True). .. cmd:: Generalizable {| {| Variable | Variables } {+ @ident } | All Variables | No Variables } Controls the set of generalizable identifiers. By default, no variables are generalizable. This command supports the :attr:`global` attribute. The :n:`{| Variable | Variables } {+ @ident }` form allows generalization of only the given :n:`@ident`\s. Using this command multiple times adds to the allowed identifiers. The other forms clear the list of :n:`@ident`\s. The :n:`All Variables` form generalizes all free variables in the context that appear under a generalization delimiter. This may result in confusing errors in case of typos. In such cases, the context will probably contain some unexpected generalized variables. The :n:`No Variables` form disables implicit generalization entirely. This is the default behavior (before any :cmd:`Generalizable` command has been entered). rocq-9.2.0/doc/sphinx/language/extensions/index.rst000066400000000000000000000016571516144147600224110ustar00rootroot00000000000000.. _extensions: =================== Language extensions =================== Syntax extensions and :term:`type inference` extend the language accepted by the Rocq kernel to make it easier to use. For example, this lets the user omit most type annotations because they can be inferred, call functions with implicit arguments which will be inferred as well, extend the syntax with notations, factorize branches when pattern-matching, etc. In this chapter, we present these language extensions and we give some explanations on how this language is translated down to the core language presented in the :ref:`previous chapter `. .. toctree:: :maxdepth: 1 compil-steps evars implicit-arguments match ../../user-extensions/syntax-extensions arguments-command ../../addendum/implicit-coercions ../../addendum/type-classes canonical ../../addendum/program ../../proof-engine/vernacular-commands rocq-9.2.0/doc/sphinx/language/extensions/match.rst000066400000000000000000000750101516144147600223700ustar00rootroot00000000000000.. _extendedpatternmatching: Extended pattern matching ========================= :Authors: Cristina Cornes and Hugo Herbelin This section describes the full form of pattern matching in Rocq terms. .. |rhs| replace:: right hand sides .. extracted from Gallina extensions chapter Variants and extensions of :g:`match` ------------------------------------- .. _mult-match: Multiple and nested pattern matching ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The basic version of :g:`match` allows pattern matching on simple patterns. As an extension, multiple nested patterns or disjunction of patterns are allowed, as in ML-like languages (cf. :ref:`multiple-patterns` and :ref:`nested-patterns`). The extension is expanded during :term:`type inference` into a sequence of match on simple patterns. Printing by default attempts to reconstruct the factorized syntax (see :flag:`Printing Matching`), but is often not successful and prints the expanded form. .. _if-then-else: Pattern-matching on boolean values: the if expression ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. insertprodn term_if term_if .. prodn:: term_if ::= if @term {? {? as @name } return @term100 } then @term else @term For inductive types with exactly two constructors and for pattern matching expressions that do not depend on the arguments of the constructors, it is possible to use a ``if … then … else`` notation. For instance, the definition .. rocqtop:: all Definition not (b:bool) := match b with | true => false | false => true end. can be alternatively written .. rocqtop:: reset all Definition not (b:bool) := if b then false else true. More generally, for an inductive type with constructors :n:`@ident__1` and :n:`@ident__2`, the following terms are equal: :n:`if @term__0 {? {? as @name } return @term } then @term__1 else @term__2` :n:`match @term__0 {? {? as @name } return @term } with | @ident__1 {* _ } => @term__1 | @ident__2 {* _ } => @term__2 end` .. example:: .. rocqtop:: all Check (fun x (H:{x=0}+{x<>0}) => match H with | left _ => true | right _ => false end). Notice that the printing uses the :g:`if` syntax because :g:`sumbool` is declared as such (see :ref:`controlling-match-pp`). .. _irrefutable-patterns: Irrefutable patterns: the destructuring let variants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Pattern-matching where all cases are captured by a single pattern (":gdef:`irrefutable pattern`", typically for inductive types with a single constructor) can be alternatively written using :g:`let … in …` constructions. There are two variants of them. .. insertprodn destructuring_let destructuring_let .. prodn:: destructuring_let ::= let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term | let ' @pattern {? in @pattern } := @term {? return @term100 } in @term .. _let-tuple: Let-tuple syntax ++++++++++++++++ The expression :n:`let ( {*, @ident__i } ) := @term__0 in @term__1` performs case analysis on :n:`@term__0` whose type must be an inductive type with exactly one constructor. The number of variables :n:`@ident__i` must correspond to the number of arguments of this constructor. Then, in :n:`@term__1`, these variables are bound to the arguments of the constructor in :n:`@term__0`. For instance, the definition .. rocqtop:: reset all Definition fst (A B:Set) (H:A * B) := match H with | pair x y => x end. can be alternatively written .. rocqtop:: reset all Definition fst (A B:Set) (p:A * B) := let (x, _) := p in x. Notice that reduction is different from regular :g:`let … in …` construction since it happens only if :n:`@term__0` is in constructor form. Otherwise, the reduction is blocked. The pretty-printing of a definition by matching on a irrefutable pattern can either be done using :g:`match` or the :g:`let` construction (see Section :ref:`controlling-match-pp`). If term inhabits an inductive type with one constructor `C`, we have an equivalence between :n:`let ( {* @name__i } ) {? {? as @name__as } return @term__ret } := @term__0 in @term__1` and :n:`match @term__0 {? {? as @name__as } return @term__ret } with C {* @name__i } => @term__1 end` (if the parameters of `C` are implicit arguments or :flag:`Asymmetric Patterns` is set). In practice type inference may use slightly different heuristics for the different syntaxes. Let-pattern syntax ++++++++++++++++++ Another destructuring let syntax is available by giving an arbitrary pattern (which must be irrefutable) instead of just a tuple for all the arguments. For example, the preceding example can be written: .. rocqtop:: reset all Definition fst (A B:Set) (p:A*B) := let 'pair x _ := p in x. This is useful to match deeper inside tuples and also to use notations for the pattern, as the syntax :g:`let ’p := t in b` allows arbitrary patterns to do the deconstruction. For example: .. rocqtop:: all Definition deep_tuple (A:Set) (x:(A*A)*(A*A)) : A*A*A*A := let '((a,b), (c, d)) := x in (a,b,c,d). Notation " x 'With' p " := (exist _ x p) (at level 20). Definition proj1_sig' (A:Set) (P:A->Prop) (t:{ x:A | P x }) : A := let 'x With p := t in x. We can also match on multiple constructors: .. rocqtop:: all Check fun A (x : A + A) => let '(inl y | inr y) := x in y. When printing definitions which are written using this construct it takes precedence over let printing directives for the datatype under consideration (see Section :ref:`controlling-match-pp`). In general :n:`let ' @pattern {? in @pattern__in } := @term__0 {? return @term__ret } in @term__1` is desugared into :n:`match @term__0 {? as @name__as } {? in @pattern__in } {? return @term__ret } with @pattern => @term__1 end` where if :n:`@pattern` is a name then it is used to provide :n:`@name__as`, otherwise the `as` annotation is left implicit. .. note:: In the "let-tuple" syntax, `let (x, y) := ...` handles any inductive type with a unique constructor and 2 arguments. In the "let-pattern" syntax, `let '(x, y) := ...` handles the inductive type whose constructor is produced by the `(_, _)` notation (by default `prod` whose constructor is `pair`). .. _controlling-match-pp: Controlling pretty-printing of match expressions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following commands give some control over the pretty-printing of :g:`match` expressions. Printing nested patterns +++++++++++++++++++++++++ .. flag:: Printing Matching The Calculus of Inductive Constructions knows pattern matching only over simple patterns. It is however convenient to re-factorize nested pattern matching into a single pattern matching over a nested pattern. When this :term:`flag` is on (default), Coq’s printer tries to do such limited re-factorization. Turning it off tells Rocq to print only simple pattern matching problems in the same way as the Rocq kernel handles them. Factorization of clauses with same right-hand side ++++++++++++++++++++++++++++++++++++++++++++++++++ .. flag:: Printing Factorizable Match Patterns When several patterns share the same right-hand side, it is additionally possible to share the clauses using disjunctive patterns. Assuming that the :flag:`Printing Matching` mode is on, this :term:`flag` (on by default) tells Rocq's printer to try to do this kind of factorization. Use of a default clause +++++++++++++++++++++++ .. flag:: Printing Allow Match Default Clause When several patterns share the same right-hand side which do not depend on the arguments of the patterns, yet an extra factorization is possible: the disjunction of patterns can be replaced with a `_` default clause. Assuming that the printing matching mode and the factorization mode are on, this :term:`flag` (on by default) tells Rocq's printer to use a default clause when relevant. Printing of wildcard patterns ++++++++++++++++++++++++++++++ .. flag:: Printing Wildcard Some variables in a pattern may not occur in the right-hand side of the pattern matching clause. When this :term:`flag` is on (default), the variables having no occurrences in the right-hand side of the pattern matching clause are just printed using the wildcard symbol β€œ_”. Printing of the elimination predicate +++++++++++++++++++++++++++++++++++++ .. flag:: Printing Synth In most of the cases, the type of the result of a matched term is mechanically synthesizable. Especially, if the result type does not depend of the matched term. When this :term:`flag` is on (default), the result type is not printed when Rocq knows that it can re- synthesize it. Printing of hidden subterms +++++++++++++++++++++++++++ .. flag:: Printing Match All Subterms In order to be able to cheaply reconstruct the types of the variables bound by `in` and `as`, `match` terms contain the polymorphic universe instance and the parameters of the inductive which is being matched. When this :term:`flag` is on (it is off by default), this information is displayed as a :term:`volatile cast` around the match discriminee. When the match relies on :flag:`Definitional UIP`, the indices are also subterms of the `match` term and are displayed when this flag is on. Otherwise they are not subterms and are displayed as holes (`_`) when this flag is on. .. example:: .. rocqtop:: in Polymorphic Inductive eqT@{u} {A:Type@{u}} (a:A) : A -> Type@{u} := reflT : eqT a a. Set Definitional UIP. Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. .. rocqtop:: all Print eqT_rect. Print seq_rect. Set Printing Match All Subterms. Set Printing Universes. Print eqT_rect. Print seq_rect. Printing matching on irrefutable patterns ++++++++++++++++++++++++++++++++++++++++++ If an inductive type has just one constructor, pattern matching can be written using the :ref:`let-tuple syntax `. .. table:: Printing Let @qualid This :term:`table` specifies a set of qualids for which pattern matching is displayed using a let expression. Note that this only applies to pattern matching instances entered with :g:`match`. It doesn't affect pattern matching explicitly entered with a destructuring :g:`let`. Use the :cmd:`Add` and :cmd:`Remove` commands to update this set. Printing matching on booleans +++++++++++++++++++++++++++++ If an inductive type is isomorphic to the boolean type, pattern matching can be written using ``if`` … ``then`` … ``else`` …. This table controls which types are written this way: .. table:: Printing If @qualid This :term:`table` specifies a set of qualids for which pattern matching is displayed using ``if`` … ``then`` … ``else`` …. Use the :cmd:`Add` and :cmd:`Remove` commands to update this set. This example emphasizes what the printing settings offer. .. example:: .. rocqtop:: all Definition snd (A B:Set) (H:A * B) := match H with | pair x y => y end. Test Printing Let for prod. Print snd. Remove Printing Let prod. Unset Printing Synth. Unset Printing Wildcard. Print snd. Conventions about unused pattern-matching variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Pattern-matching variables that are not used on the right-hand side of ``=>`` are considered the sign of a potential error. For instance, it could result from an undetected misspelled constant constructor. By default, a warning is issued in such situations. .. warn:: Unused variable @ident might be a misspelled constructor. Use _ or _@ident to silence this warning. :name: Unused variable β€˜ident’ might be a misspelled constructor. Use _ or _β€˜ident’ to silence this warning. This indicates that an unused pattern variable :token:`ident` occurs in a pattern-matching clause. The warning can be deactivated by using a variable name starting with ``_`` or by setting ``Set Warnings "-unused-pattern-matching-variable"``. Here is an example where the warning is activated. .. example:: .. rocqtop:: all warn Definition is_zero (o : option nat) := match o with | Some _ => true | x => false end. Patterns -------- The full syntax of `match` is presented in :ref:`match_term`. Identifiers in patterns are either constructor names or variables. Any identifier that is not the constructor of an inductive or coinductive type is considered to be a variable. A variable name cannot occur more than once in a given pattern. It is recommended to start variable names by a lowercase letter. If a pattern has the form ``c x`` where ``c`` is a constructor symbol and x is a linear vector of (distinct) variables, it is called *simple*: it is the kind of pattern recognized by the basic version of match. On the opposite, if it is a variable ``x`` or has the form ``c p`` with ``p`` not only made of variables, the pattern is called *nested*. A variable pattern matches any value, and the identifier is bound to that value. The pattern β€œ``_``” (called β€œdon't care” or β€œwildcard” symbol) also matches any value, but does not bind anything. It may occur an arbitrary number of times in a pattern. Alias patterns written :n:`(@pattern as @ident)` are also accepted. This pattern matches the same values as :token:`pattern` does and :token:`ident` is bound to the matched value. A pattern of the form :n:`@pattern | @pattern` is called disjunctive. A list of patterns separated with commas is also considered as a pattern and is called *multiple pattern*. However multiple patterns can only occur at the root of pattern matching equations. Disjunctions of *multiple patterns* are allowed though. Since extended ``match`` expressions are compiled into the primitive ones, the expressiveness of the theory remains the same. Once parsing has finished only simple patterns remain. The original nesting of the ``match`` expressions is recovered at printing time. An easy way to see the result of the expansion is to toggle off the nesting performed at printing (use here :flag:`Printing Matching`), then by printing the term with :cmd:`Print` if the term is a :term:`constant`, or using the command :cmd:`Check`. The extended ``match`` still accepts an optional *elimination predicate* given after the keyword ``return``. Given a pattern matching expression, if all the right-hand-sides of ``=>`` have the same type, then this type can be sometimes synthesized, and so we can omit the return part. Otherwise the predicate after return has to be provided, like for the basicmatch. Let us illustrate through examples the different aspects of extended pattern matching. Consider for example the function that computes the maximum of two natural numbers. We can write it in primitive syntax by: .. rocqtop:: in Fixpoint max (n m:nat) {struct m} : nat := match n with | O => m | S n' => match m with | O => S n' | S m' => S (max n' m') end end. .. _multiple-patterns: Multiple patterns ----------------- Using multiple patterns in the definition of ``max`` lets us write: .. rocqtop:: in reset Fixpoint max (n m:nat) {struct m} : nat := match n, m with | O, _ => m | S n', O => S n' | S n', S m' => S (max n' m') end. which will be compiled into the previous form. The pattern matching compilation strategy examines patterns from left to right. A match expression is generated **only** when there is at least one constructor in the column of patterns. E.g. the following example does not build a match expression. .. rocqtop:: all Check (fun x:nat => match x return nat with | y => y end). .. _aliasing-subpatterns: Aliasing subpatterns -------------------- We can also use :n:`as @ident` to associate a name to a sub-pattern: .. rocqtop:: in reset Fixpoint max (n m:nat) {struct n} : nat := match n, m with | O, _ => m | S n' as p, O => p | S n', S m' => S (max n' m') end. .. _nested-patterns: Nested patterns --------------- Here is now an example of nested patterns: .. rocqtop:: in Fixpoint even (n:nat) : bool := match n with | O => true | S O => false | S (S n') => even n' end. This is compiled into: .. rocqtop:: all Unset Printing Matching. Print even. .. rocqtop:: none Set Printing Matching. In the previous examples patterns do not conflict with, but sometimes it is comfortable to write patterns that admit a nontrivial superposition. Consider the boolean function :g:`lef` that given two natural numbers yields :g:`true` if the first one is less or equal than the second one and :g:`false` otherwise. We can write it as follows: .. rocqtop:: in Fixpoint lef (n m:nat) {struct m} : bool := match n, m with | O, _ => true | _, O => false | S n, S m => lef n m end. Note that the first and the second multiple pattern overlap because the couple of values ``O O`` matches both. Thus, what is the result of the function on those values? To eliminate ambiguity we use the *textual priority rule:* we consider patterns to be ordered from top to bottom. A value is matched by the pattern at the ith row if and only if it is not matched by some pattern from a previous row. Thus in the example, ``O O`` is matched by the first pattern, and so :g:`(lef O O)` yields true. Another way to write this function is: .. rocqtop:: in reset Fixpoint lef (n m:nat) {struct m} : bool := match n, m with | O, _ => true | S n, S m => lef n m | _, _ => false end. Here the last pattern superposes with the first two. Because of the priority rule, the last pattern will be used only for values that do not match neither the first nor the second one. Terms with useless patterns are not accepted by the system. Here is an example: .. rocqtop:: all Fail Check (fun x:nat => match x with | O => true | S _ => false | x => true end). Disjunctive patterns -------------------- Multiple patterns that share the same right-hand-side can be factorized using the notation :n:`{+| {+, @pattern } }`. For instance, :g:`max` can be rewritten as follows: .. rocqtop:: in reset Fixpoint max (n m:nat) {struct m} : nat := match n, m with | S n', S m' => S (max n' m') | 0, p | p, 0 => p end. Similarly, factorization of (not necessarily multiple) patterns that share the same variables is possible by using the notation :n:`{+| @pattern}`. Here is an example: .. rocqtop:: in Definition filter_2_4 (n:nat) : nat := match n with | 2 as m | 4 as m => m | _ => 0 end. Nested disjunctive patterns are allowed, inside parentheses, with the notation :n:`({+| @pattern})`, as in: .. rocqtop:: in Definition filter_some_square_corners (p:nat*nat) : nat*nat := match p with | ((2 as m | 4 as m), (3 as n | 5 as n)) => (m,n) | _ => (0,0) end. About patterns of parametric types ---------------------------------- Parameters in patterns ~~~~~~~~~~~~~~~~~~~~~~ When matching objects of a parametric type, parameters do not bind in patterns. They must be substituted by β€œ``_``”. Consider for example the type of polymorphic lists: .. rocqtop:: in Inductive List (A:Set) : Set := | nil : List A | cons : A -> List A -> List A. We can check the function *tail*: .. rocqtop:: all Check (fun l:List nat => match l with | nil _ => nil nat | cons _ _ l' => l' end). When we use parameters in patterns there is an error message: .. rocqtop:: all Fail Check (fun l:List nat => match l with | nil A => nil nat | cons A _ l' => l' end). .. flag:: Asymmetric Patterns This :term:`flag` (off by default) removes parameters from constructors in patterns: .. rocqtop:: all Set Asymmetric Patterns. Check (fun l:List nat => match l with | nil => nil _ | cons _ l' => l' end). Unset Asymmetric Patterns. Implicit arguments in patterns ------------------------------ By default, implicit arguments are omitted in patterns. So we write: .. rocqtop:: all Arguments nil {A}. Arguments cons [A] _ _. Check (fun l:List nat => match l with | nil => nil | cons _ l' => l' end). But the possibility to use all the arguments is given by β€œ``@``” implicit explicitations (as for terms, see :ref:`explicit-applications`). .. rocqtop:: all Check (fun l:List nat => match l with | @nil _ => @nil nat | @cons _ _ l' => l' end). .. _matching-dependent: Matching objects of dependent types ----------------------------------- The previous examples illustrate pattern matching on objects of non- dependent types, but we can also use the expansion strategy to destructure objects of dependent types. Consider the type :g:`listn` of lists of a certain length: .. rocqtop:: in reset Inductive listn : nat -> Set := | niln : listn 0 | consn : forall n:nat, nat -> listn n -> listn (S n). Understanding dependencies in patterns -------------------------------------- We can define the function length over :g:`listn` by: .. rocqdoc:: Definition length (n:nat) (l:listn n) := n. Just for illustrating pattern matching, we can define it by case analysis: .. rocqtop:: in Definition length (n:nat) (l:listn n) := match l with | niln => 0 | consn n _ _ => S n end. We can understand the meaning of this definition using the same notions of usual pattern matching. When the elimination predicate must be provided ----------------------------------------------- Dependent pattern matching ~~~~~~~~~~~~~~~~~~~~~~~~~~ The examples given so far do not need an explicit elimination predicate because all the |rhs| have the same type and Rocq succeeds to synthesize it. Unfortunately when dealing with dependent patterns it often happens that we need to write cases where the types of the |rhs| are different instances of the elimination predicate. The function :g:`concat` for :g:`listn` is an example where the branches have different types and we need to provide the elimination predicate: .. rocqtop:: in Fixpoint concat (n:nat) (l:listn n) (m:nat) (l':listn m) {struct l} : listn (n + m) := match l in listn n return listn (n + m) with | niln => l' | consn n' a y => consn (n' + m) a (concat n' y m l') end. .. rocqtop:: none Reset concat. The elimination predicate is :g:`fun (n:nat) (l:listn n) => listn (n+m)`. In general if :g:`m` has type :g:`(I q1 … qr t1 … ts)` where :g:`q1, …, qr` are parameters, the elimination predicate should be of the form :g:`fun y1 … ys x : (I q1 … qr y1 … ys ) => Q`. In the concrete syntax, it should be written : ``match m as x in (I _ … _ y1 … ys) return Q with … end``. The variables which appear in the ``in`` and ``as`` clause are new and bounded in the property :g:`Q` in the return clause. The parameters of the inductive definitions should not be mentioned and are replaced by ``_``. Multiple dependent pattern matching ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Recall that a list of patterns is also a pattern. So, when we destructure several terms at the same time and the branches have different types we need to provide the elimination predicate for this multiple pattern. It is done using the same scheme: each term may be associated with an ``as`` clause and an ``in`` clause in order to introduce a dependent product. For example, an equivalent definition for :g:`concat` (even though the matching on the second term is trivial) would have been: .. rocqtop:: in Fixpoint concat (n:nat) (l:listn n) (m:nat) (l':listn m) {struct l} : listn (n + m) := match l in listn n, l' return listn (n + m) with | niln, x => x | consn n' a y, x => consn (n' + m) a (concat n' y m x) end. Even without real matching over the second term, this construction can be used to keep types linked. If :g:`a` and :g:`b` are two :g:`listn` of the same length, by writing .. rocqtop:: in Check (fun n (a b: listn n) => match a, b with | niln, b0 => tt | consn n' a y, bS => tt end). we have a copy of :g:`b` in type :g:`listn 0` resp. :g:`listn (S n')`. .. _match-in-patterns: Patterns in ``in`` ~~~~~~~~~~~~~~~~~~ If the type of the matched term is more precise than an inductive applied to variables, arguments of the inductive in the ``in`` branch can be more complicated patterns than a variable. Moreover, constructors whose types do not follow the same pattern will become impossible branches. In an impossible branch, you can answer anything but False_rect unit has the advantage to be subterm of anything. To be concrete: the ``tail`` function can be written: .. rocqtop:: in Definition tail n (v: listn (S n)) := match v in listn (S m) return listn m with | niln => False_rect unit | consn n' a y => y end. and :g:`tail n v` will be subterm of :g:`v`. Using pattern matching to write proofs -------------------------------------- In all the previous examples the elimination predicate does not depend on the object(s) matched. But it may depend and the typical case is when we write a proof by induction or a function that yields an object of a dependent type. An example of a proof written using ``match`` is given in the description of the tactic :tacn:`refine`. For example, we can write the function :g:`buildlist` that given a natural number :g:`n` builds a list of length :g:`n` containing zeros as follows: .. rocqtop:: in Fixpoint buildlist (n:nat) : listn n := match n return listn n with | O => niln | S n => consn n 0 (buildlist n) end. We can also use multiple patterns. Consider the following definition of the predicate less-equal :g:`Le`: .. rocqtop:: in Inductive LE : nat -> nat -> Prop := | LEO : forall n:nat, LE 0 n | LES : forall n m:nat, LE n m -> LE (S n) (S m). We can use multiple patterns to write the proof of the lemma :g:`forall (n m:nat), (LE n m) \/ (LE m n)`: .. rocqtop:: in Fixpoint dec (n m:nat) {struct n} : LE n m \/ LE m n := match n, m return LE n m \/ LE m n with | O, x => or_introl (LE x 0) (LEO x) | x, O => or_intror (LE x 0) (LEO x) | S n as n', S m as m' => match dec n m with | or_introl h => or_introl (LE m' n') (LES n m h) | or_intror h => or_intror (LE n' m') (LES m n h) end end. In the example of :g:`dec`, the first match is dependent while the second is not. The user can also use match in combination with the tactic :tacn:`refine` to build incomplete proofs beginning with a :g:`match` construction. Pattern-matching on inductive objects involving local definitions ----------------------------------------------------------------- If local definitions (`let :=`) occur in the type of a constructor, then there are two ways to match on this constructor. Either the local definitions are skipped and matching is done only on the true arguments of the constructors, or the bindings for local definitions can also be caught in the matching. .. example:: .. rocqtop:: in reset Inductive list : nat -> Set := | nil : list 0 | cons : forall n:nat, let m := (2 * n) in list m -> list (S (S m)). In the next example, the local definition is not caught. .. rocqtop:: in Fixpoint length n (l:list n) {struct l} : nat := match l with | nil => 0 | cons n l0 => S (length (2 * n) l0) end. But in this example, it is. .. rocqtop:: in Fixpoint length' n (l:list n) {struct l} : nat := match l with | nil => 0 | @cons _ m l0 => S (length' m l0) end. .. note:: For a given matching clause, either none of the local definitions or all of them can be caught. .. note:: You can only catch let bindings in mode where you bind all variables and so you have to use ``@`` syntax. .. note:: this feature is incoherent with the fact that parameters cannot be caught and consequently is somehow hidden. For example, there is no mention of it in error messages. Pattern-matching and coercions ------------------------------ If a mismatch occurs between the expected type of a pattern and its actual type, a coercion made from constructors is sought. If such a coercion can be found, it is automatically inserted around the pattern. .. example:: .. rocqtop:: in Inductive I : Set := | C1 : nat -> I | C2 : I -> I. Coercion C1 : nat >-> I. .. rocqtop:: all Check (fun x => match x with | C2 O => 0 | _ => 0 end). When does the expansion strategy fail? -------------------------------------- The strategy works very like in ML languages when treating patterns of non-dependent types. But there are new cases of failure that are due to the presence of dependencies. The error messages of the current implementation may be sometimes confusing. When the tactic fails because patterns are somehow incorrect then error messages refer to the initial expression. But the strategy may succeed to build an expression whose sub-expressions are well typed when the whole expression is not. In this situation the message makes reference to the expanded expression. We encourage users, when they have patterns with the same outer constructor in different equations, to name the variable patterns in the same positions with the same name. E.g. to write ``(cons n O x) => e1`` and ``(cons n _ x) => e2`` instead of ``(cons n O x) => e1`` and ``(cons n' _ x') => e2``. This helps to maintain certain name correspondence between the generated expression and the original. Here is a summary of the error messages corresponding to each situation: .. exn:: The constructor @ident expects @natural arguments. The variable ident is bound several times in pattern term Found a constructor of inductive type term while a constructor of term is expected Patterns are incorrect (because constructors are not applied to the correct number of arguments, because they are not linear or they are wrongly typed). .. exn:: Non exhaustive pattern matching. The pattern matching is not exhaustive. .. exn:: The elimination predicate term should be of arity @natural (for non \ dependent case) or @natural (for dependent case). The elimination predicate provided to match has not the expected arity. .. exn:: Unable to infer a match predicate Either there is a type incompatibility or the problem involves dependencies. There is a type mismatch between the different branches. The user should provide an elimination predicate. rocq-9.2.0/doc/sphinx/language/gallina-extensions.rst000066400000000000000000000001361516144147600226760ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/language/gallina-specification-language.rst000066400000000000000000000001301516144147600250720ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/language/module-system.rst000066400000000000000000000001321516144147600216750ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/license.rst000066400000000000000000000004711516144147600167330ustar00rootroot00000000000000.. note:: **License** This material (the Rocq Reference Manual) may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub). Options A and B are not elected. rocq-9.2.0/doc/sphinx/practical-tools/000077500000000000000000000000001516144147600176555ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/practical-tools/coq-commands.rst000066400000000000000000001027021516144147600227720ustar00rootroot00000000000000.. _therocqcommands: The Rocq Prover commands ======================== There are several Rocq commands: + ``rocqide``: a graphical integrated development environment, described :ref:`here `. In addition, there are several other IDEs such as Proof General, vsCoq and Coqtail that are not included with the Coq installation. + ``rocq``: the main entry point for the Rocq prover + ``rocqchk``: the Rocq checker (validation of compiled libraries) (also available through ``rocq check``) Many of the parameters to start these tools are shared and are described below. Passing the `-help` option on the command line will print a summary of the available command line parameters. There are also man pages for each of these, but they are probably less current than `-help` or this document. .. _interactive-use: Interactive use (rocq repl) --------------------------- The Rocq toplevel (or read-eval-print-loop) is run by the command ``rocq repl`` (equivalently, `rocq top`). There is also a byte-code toplevel `rocq repl-with-drop` based on an OCaml toplevel. You can switch to the OCaml toplevel with the command ``Drop.``, and come back to the Rocq toplevel with the command ``#go;;``. .. flag:: Rocqtop Exit On Error This :term:`flag`, off by default, causes `rocq top` to exit with status code ``1`` if a command produces an error instead of recovering from it. Batch compilation (rocq compile) -------------------------------- The ``rocq compile`` (equivalently, `rocq c`) command compiles a Rocq proof script file with a ".v" suffix to create a compiled file with a ".vo" suffix. (See :ref:`compiled-files`.) The last component of the filename must be a valid Rocq identifier as described in :ref:`lexical-conventions`; it should contain only letters, digits or underscores (_) with a ".v" suffix on the final component. For example ``/bar/foo/toto.v`` is valid, but ``/bar/foo/to-to.v`` is not. We recommend specifying a :term:`logical path` (which is also the module name) with the `-R` or the `-Q` options. Generally we recommend using utilities such as `make` (using `rocq makefile` to generate the `Makefile`) or `dune` to build Rocq projects. See :ref:`rocq_makefile` and :ref:`building_dune`. .. example:: Compiling and loading a single file If `foo.v` is in Rocq's current directory, you can use `rocq c foo.v` to compile it and then `Require foo.` in your script. But this doesn't scale well for larger projects. Generally it's better to define a new module: To compile `foo.v` as part of a module `Mod1` that is rooted at `.` (i.e. the directory containing `foo.v`), run `rocq c -Q . Mod1 foo.v`. To make the module available in `RocqIDE`, include the following line in the `_CoqProject` file (see :ref:`rocq_makefile`) in the directory from which you start `RocqIDE` or give it as an argument to the ``rocqide`` command. ** is the pathname of the directory containing the module, which can be an absolute path or relative to Rocq's current directory. For now, you must close and reload a named script file for `RocqIDE` to pick up the change, or restart `RocqIDE`. The project file name is configurable in `Edit / Preferences / Project`. .. rocqdoc:: -R Mod1 .. _system_config: System configuration -------------------- Running `rocq` (or the `coq` compatibility commands) will fail if it cannot find certain expected files (except for subcommands like `rocq wc` which do not need to find anything). The files are searched according to Rocq's build time configuration, the location of the `rocq` executable and the available command line arguments and environment variables. .. note:: If `configure` is not explicitly called, it is equivalent to `configure -relocatable`. Let `$root` be the parent directory of the directory of the `rocq` executable (typically `rocq` is `$root/bin/rocq`, or `$root\\bin\\rocq.exe` on Windows). Let `$libdirconf` be the value passed to `configure -libdir`, or `coq/lib` if `libdir` was not used. Let `$libdir` be - if the `coqlib` command line argument was used, its value - otherwise, if the `ROCQLIB` environment variable is defined, its value - otherwise, if the deprecated `COQLIB` environment variable is defined, its value - otherwise, if `$libdirconf` is absolute, its value - otherwise, if `$root/$libdirconf/theories/Init/Prelude.vo` exists or Rocq was configured with `-relocatable`, `$root/$libdirconf` - otherwise, if Rocq was configured with `-prefix $prefix`, `$prefix/$libdirconf` (if the user gave a relative `$prefix`, it is turned into an absolute path based on the working directory of the `configure` invocation) .. note:: Rocq must be configured with either `-prefix` or `-relocatable`. If `$libdirconf` is relative, and `-prefix` was used, usually either `$root/$libdirconf/theories/Init/Prelude.vo` does not exist so we use `$prefix/$libdirconf`, or it is the same as `$prefix/$libdirconf`. If `-relocatable` was used we only have `$root/$libdirconf`. .. exn:: The path for Rocq libraries is wrong. Unless `-boot` was passed, Rocq fails with this error if `$libdir/theories/Init/Prelude.vo` does not exist. Unless `-boot` was passed, Rocq acts as though `-R $libdir/theories Corelib -Q $libdir/user-contrib ""` was passed. Let `$runtimelib` be - if the `ROCQRUNTIMELIB` environment variable is defined, its value - otherwise, if the deprecated `COQCORELIB` environment variable is defined, its value - otherwise, `$libdir/../rocq-runtime` .. exn:: The path for Rocq plugins is wrong. Unless `-boot` was passed, Rocq fails with this error if `$runtimelib/plugins` does not exist. If `-boot` was not passed, Rocq will add `$runtimelib/..` to the OCamlfind search path (as though `-I $runtimelib/..` was passed). If `-boot` was not passed and no `-nI` argument was passed, Rocq will also add an implicit `-nI $runtimelib/kernel` for :tacn:`native_compute` (so if you use `-boot` and native compute you must use `-nI`). Then, regardless of `-boot`, Rocq will search for OCamlfind package `rocq-runtime`. .. exn:: Could not find package rocq-runtime. Rocq fails with this error if OCamlfind package `rocq-runtime` could not be found. Customization at launch time --------------------------------- Command parameters ------------------ There are 3 mechanisms for passing parameters to Rocq commands. In order of importance they are: - :ref:`command line options `, - :ref:`environment variables ` and - the `coqrc` start up script `coqrc` start up script ~~~~~~~~~~~~~~~~~~~~~~~ When Rocq is launched, it can implicitly prepend a startup script to any document it reads, whether it is an interactive session or a file to compile. The startup script can come from a configuration directory or it can be specified on the command line. Coq uses the first file found in this list as the startup script: - ``$XDG_CONFIG_HOME/coqrc.`` - ``$XDG_CONFIG_HOME/coqrc`` - ``$HOME/.coqrc.`` - ``$HOME/.coqrc`` where ``$XDG_CONFIG_HOME`` is an environment variable. ``$HOME`` is the user's home directory. ```` is the version of Rocq (as shown by `rocq --version`, for example). ``-init-file file`` on the command line uses the specified file instead of a startup script from a configuration directory. ``-q`` prevents the use of a startup script. .. _customization-by-environment-variables: Environment variables ~~~~~~~~~~~~~~~~~~~~~ ``$ROCQPATH`` can be used to specify the :term:`load path`. It is a list of directories separated by ``:`` (``;`` on Windows). Coq will also honor ``$XDG_DATA_HOME`` and ``$XDG_DATA_DIRS`` (see Section :ref:`logical-paths-load-path`). The added loadpaths are considered installed, see :cmd:`Print LoadPath`. .. TODO PR: Correct ref above? Makefiles generated by `rocq makefile` call other Rocq commands. In this case, they look for the commands in directory specified by ``$COQBIN``. If this variable is not set, they look for the commands in the executable path. .. _ROCQ_COLORS: ``$ROCQ_COLORS`` can be used to specify the set of colors used by ``rocq repl`` to highlight its output. It uses the same syntax as the ``$LS_COLORS`` variable from GNU’s ls, that is, a colon-separated list of assignments of the form :n:`name={*; attr}` where ``name`` is the name of the corresponding highlight tag and each ``attr`` is an ANSI escape code. The list of highlight tags can be retrieved with the ``-list-tags`` command-line option of ``rocq repl``. The string uses ANSI escape codes to represent attributes. For example: ``export ROCQ_COLORS=”diff.added=4;48;2;0;0;240:diff.removed=41”`` sets the highlights for added text in diffs to underlined (the 4) with a background RGB color (0, 0, 240) and for removed text in diffs to a red background. Note that if you specify ``ROCQ_COLORS``, the predefined attributes are ignored. .. _OCAMLRUNPARAM: ``$OCAMLRUNPARAM``, described `here `_, can be used to specify certain runtime and memory usage parameters. In most cases, experimenting with these settings will likely not cause a significant performance difference and should be harmless. If the variable is not set, Rocq uses the `default values `_, except that ``space_overhead`` is set to 120 and ``minor_heap_size`` is set to 32Mwords (256MB with 64-bit executables or 128MB with 32-bit executables). .. todo: Using the same text "here" for both of the links in the last 2 paragraphs generates an incorrect warning: coq-commands.rst:4: WARNING: Duplicate explicit target name: "here". The warning doesn't even have the right line number. :-( .. todo how about ROCQLIB, ROCQRUNTIMELIB, DOCDIR .. _ROCQ_PROFILE_COMPONENTS: Specifies which components produce events when using the :ref:`profiling` system. It is a comma separated list of component names, possibly prefixed by `-` to negate it. If the variable is not set, all components produce events. If it starts with `-`, all components not in the list produce events. Otherwise only components in the list produce events. Component names are internally defined, but `command` which corresponds to the interpretation of one command is particularly notable. .. _command-line-options: Command line options ~~~~~~~~~~~~~~~~~~~~ The following command-line options are recognized by the commands ``rocq compile`` and ``rocq repl``, unless stated otherwise: :-I *directory*, -include *directory*: Add physical path *directory* to the OCaml loadpath, which is needed to load OCaml object code files (``.cmo`` or ``.cmxs``). Subdirectories are not included. See the command :cmd:`Declare ML Module`. Directories added with ``-I`` are searched after the current directory, in the order in which they were given on the command line .. TODO PR: is that right about Declare ML Module? it's not a directory like -I .. seealso:: The :cmd:`Declare ML Module` command. .. _-Q-option: :-Q *directory dirpath*: Makes the `.vo` files in a :term:`package` available for loading with the :cmd:`Require` command by adding new entries to the :term:`load path`. The entries map the :term:`logical path` *dirpath* to the physical path *directory*. Then Rocq recursively adds load path entries for subdirectories. For example, `-Q . Lib` may add the logical path `Lib.SubDir.File`, which maps to the file `./SubDir/File.vo`. Only subdirectories and files that follow the lexical conventions for :n:`@ident`\s are included. Subdirectories named ``CVS`` or ``_darcs`` are excluded. Some operating systems or file systems are more restrictive. For example, Linux’s ext4 file system limits filenames to 255 bytes. The default on NTFS (Windows) and HFS+ (MacOS X) file systems is to disallow two files in the same directory with names that differ only in their case. Loading files from packages made available with `-Q` must include the :term:`logical name` of the package in `From` clause of the :cmd:`Require` command *or* provide a fully qualified name. The added loadpath is considered local, see :cmd:`Print LoadPath`. :-R *directory dirpath*: Similar to ``-Q`` *directory dirpath*, but allows using :cmd:`Require` with a partially qualified name (i.e. without a `From` clause). :-top *dirpath*: Set the logical module name to :n:`@dirpath` for the `rocq repl` interactive session. If no module name is specified, `rocq repl` will default to ``Top``. `rocq compile` does not accept this option because the logical module name is inferred from the name of the input file and the corresponding `-R` / `-Q` options. :-exclude-dir *directory*: Exclude any subdirectory named *directory* while processing options such as -R and -Q. By default, only the conventional version control management directories named ``CVS`` and ``_darcs`` are excluded. :-nois, -noinit: Start from an empty state instead of loading the `Init.Prelude` module. :-init-file *file*: Load *file* as the resource file instead of loading the default resource file from the standard configuration directories. :-q: Do not to load the default resource file. :-l *file*, -load-vernac-source *file*: Load and execute the Rocq script from *file.v*. :-lv *file*, -load-vernac-source-verbose *file*: Load and execute the Rocq script from *file.v*. Write its contents to the standard output as it is executed. :-require *qualid*: Load Rocq compiled library :n:`@qualid`. This is equivalent to running :cmd:`Require` :n:`@qualid` (note: the short form `-r *qualid*` is intentionally not provided to prevent the risk of collision with `-R`). .. _interleave-command-line: .. note:: Note that the relative order of this command-line option and its variants (`-ri`, `-re`, `-rfrom`, `-refrom`, `-rifrom`) and of the `-set` and `-unset` options matters since the various :cmd:`Require`, :cmd:`Require Import`, :cmd:`Require Export`, :cmd:`Set` and :cmd:`Unset` commands will be executed in the order specified on the command-line. :-ri *qualid*, -require-import *qualid*: Load Rocq compiled library :n:`@qualid` and import it. This is equivalent to running :cmd:`Require Import` :n:`@qualid`. See the :ref:`note above ` regarding the order of command-line options. :-re *qualid*, -require-export *qualid*: Load Rocq compiled library :n:`@qualid` and transitively import it. This is equivalent to running :cmd:`Require Export` :n:`@qualid`. See the :ref:`note above ` regarding the order of command-line options. :-rfrom *dirpath qualid*, -require-from *dirpath qualid*: Load Rocq compiled library :n:`@qualid`. This is equivalent to running :cmd:`From ` :n:`@dirpath` :cmd:`Require ` :n:`@qualid`. See the :ref:`note above ` regarding the order of command-line options. :-rifrom *dirpath qualid*, -require-import-from *dirpath qualid*: Load Rocq compiled library :n:`@qualid` and import it. This is equivalent to running :cmd:`From ` :n:`@dirpath` :cmd:`Require Import ` :n:`@qualid`. See the :ref:`note above ` regarding the order of command-line options. :-refrom *dirpath qualid*, -require-export-from *dirpath qualid*: Load Rocq compiled library :n:`@qualid` and transitively import it. This is equivalent to running :cmd:`From ` :n:`@dirpath` :cmd:`Require Export ` :n:`@qualid`. See the :ref:`note above ` regarding the order of command-line options. :-load-vernac-object *qualid*: Obsolete synonym of :n:`-require qualid`. :-batch: Exit just after argument parsing. Available for ``rocq repl`` only. :-verbose: Output the content of the input file as it is compiled. This option is available for ``rocq compile`` only. :-native-compiler (yes|no|ondemand): Enable the :tacn:`native_compute` reduction machine and precompilation to ``.cmxs`` files for future use by :tacn:`native_compute`. Setting ``yes`` enables :tacn:`native_compute`; it also causes Rocq to precompile the native code for future use; all dependencies need to have been precompiled beforehand. Setting ``no`` disables :tacn:`native_compute` which defaults back to :tacn:`vm_compute`; no files are precompiled. Setting ``ondemand`` enables :tacn:`native_compute` but disables precompilation; all missing dependencies will be recompiled every time :tacn:`native_compute` is called. .. _native-compiler-options: .. deprecated:: 8.14 This flag has been deprecated in favor of calling :ref:`rocq native-precompile `. The toolchain has been adapted to transparently rely on the latter, so if you use :ref:`rocq_makefile` there is nothing to do. Otherwise you should substitute calls to `rocq c -native-compiler yes` to calls to `rocq compile` followed by `rocq native-precompile` on the resulting `vo` file. .. versionchanged:: 8.13 The default value is set at configure time, ``-config`` can be used to retrieve it. All this can be summarized in the following table: .. list-table:: :header-rows: 1 * - ``configure`` - ``rocq compile`` - ``native_compute`` - outcome - requirements * - yes - yes (default) - native_compute - ``.cmxs`` - ``.cmxs`` of deps * - yes - no - vm_compute - none - none * - yes - ondemand - native_compute - none - none * - no - yes, no, ondemand - vm_compute - none - none * - ondemand - yes - native_compute - ``.cmxs`` - ``.cmxs`` of deps * - ondemand - no - vm_compute - none - none * - ondemand - ondemand (default) - native_compute - none - none :-native-output-dir *dir*: Set the directory in which to put the aforementioned ``.cmxs`` for :tacn:`native_compute`. Defaults to ``.coq-native``. :-output-directory *dir*, -output-dir *dir*: Sets the output directory for commands that write output to files, such as :ref:`extraction` commands, :cmd:`Redirect` and :cmd:`Print Universes`. :-vos: Indicate Rocq to skip the processing of opaque proofs (i.e., proofs ending with :cmd:`Qed` or :cmd:`Admitted`), output a ``.vos`` files instead of a ``.vo`` file, and to load ``.vos`` files instead of ``.vo`` files when interpreting :cmd:`Require` commands. :-vok: Indicate Rocq to check a file completely, to load ``.vos`` files instead of ``.vo`` files when interpreting :cmd:`Require` commands. No ``.vo`` file is written. :-w (all|none|w₁,…,wβ‚™): Configure the display of warnings. This option expects all, none or a comma-separated list of warning names or categories (see Section :ref:`controlling-display`). :-color (on|off|auto): Enable or disable color output. Default is auto, meaning color is shown only if the output channel supports ANSI escape sequences. :-diffs (on|off|removed): *Rocq repl only*. Controls highlighting of differences between proof steps. ``on`` highlights added tokens, ``removed`` highlights both added and removed tokens. Requires that ``-color`` is enabled. (see Section :ref:`showing_diffs`). :-beautify: Pretty-print each command to *file.beautified* when compiling *file.v*, in order to get old-fashioned syntax/definitions/notations. :-emacs, -ide-slave: Start a special toplevel to communicate with a specific IDE. :-impredicative-set: Change the logical theory of Rocq by declaring the sort :g:`Set` impredicative. .. warning:: This is known to be inconsistent with some standard axioms of classical mathematics such as the functional axiom of choice or the principle of description. :-type-in-type: Collapse the universe hierarchy of Rocq. .. warning:: This makes the logic inconsistent. :-mangle-names *ident*: *Experimental.* Do not depend on this option. Replace Rocq's auto-generated name scheme with names of the form *ident0*, *ident1*, etc. Within Rocq, the :flag:`Mangle Names` flag turns this behavior on, and the :opt:`Mangle Names Prefix` option sets the prefix to use. This feature is intended to be used as a linter for developments that want to be robust to changes in the auto-generated name scheme. The options are provided to facilitate tracking down problems. :-set *string*: Enable flags and set options. *string* should be :n:`@setting_name=value`, the value is interpreted according to the type of the option. For flags :n:`@setting_name` is equivalent to :n:`@setting_name=true`. For instance ``-set "Universe Polymorphism"`` will enable :flag:`Universe Polymorphism`. Note that the quotes are shell syntax, Rocq does not see them. See the :ref:`note above ` regarding the order of command-line options. :-unset *string*: As ``-set`` but used to disable options and flags. *string* must be :n:`"@setting_name"`. See the :ref:`note above ` regarding the order of command-line options. :-compat *version*: same as ``-compat-from Stdlib Rocq`` (or ``Rocq`` when version is ``8.*``) :-compat-from *root* *library*: Loads a file that sets a few options to maintain partial backward-compatibility with a previous version. This is equivalent to ``-require-import-from `` except that a non existing file only produces a warning (so that the option can be uniformly used on older versions that didn't offer the compat file yet). Note that the :ref:`explanations above ` regarding the order of command-line options apply, and this could be relevant if you are resetting some of the compatibility options. :-dump-glob *file*: Dump references for global names in file *file* (to be used by rocq doc, see :ref:`rocqdoc`). 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 ``rocq compile`` to be *file* instead of the standard one. Not of general use. :-bindir *directory*: Set the directory containing Rocq binaries to be used by ``rocq compile``. It is equivalent to doing export COQBIN= *directory* before launching ``rocq compile``. :-where: Print the location of Rocq’s standard library and exit. :-config: Print the locations of Rocq’s binaries, dependencies, and libraries, then exit. :-filteropts: Print the list of command line arguments that `rocq repl` has recognized as options and exit. :-v: Print Rocq’s version and exit. :-list-tags: Print the highlight tags known by Rocq as well as their currently associated color and exit. :-h, --help: Print a short usage and exit. :-time: Output timing information for each command to standard output. :-time-file *file*: Output timing information for each command to the given file. :-profile *file*: Output :ref:`profiling` information to the given file. .. _profiling: Profiling --------- Use the `rocq compile` command line argument `-profile` or the environment variable `PROFILE` in `rocq makefile`, to generate profiling information in `Google trace format `. The output gives the duration and event counts for the execution of components of Rocq (for instance `process` for the whole file, `command` for each command, `pretyping` for elaboration). Environment variable :ref:`ROCQ_PROFILE_COMPONENTS ` can be used to filter which components produce events. This may be needed to reduce the size of the generated file. The generated file can be visualized with (which can directly load the `.gz` compressed file produced by `rocq makefile`) or processed using any JSON-capable system. Events are annotated with additional information in the `args` field (either on the beginning `B` or end `E` event): - `major` and `minor` indicate how many major and minor words were allocated during the event. - `subtimes` indicates how much time was spent in sub-components and how many times each subcomponent was profiled during the event (including subcomponents which do not appear in `ROCQ_PROFILE_COMPONENTS`). - for the `command` event, `cmd` displays the precise location of the command and a compressed representation of it (like the `-time` header), and `line` is the start line of the command. .. _compiled-interfaces: Compiled interfaces (produced using ``-vos``) ---------------------------------------------- Compiled interfaces help saving time while developing Rocq formalizations, by compiling the formal statements exported by a library independently of the proofs that it contains. .. warning:: Compiled interfaces should only be used for development purposes. At the end of the day, one still needs to proof check all files by producing standard ``.vo`` files. (Technically, when using ``-vos``, fewer universe constraints are collected.) Moreover, this feature is still experimental, it may be subject to change without prior notice. **Principle.** The compilation using ``rocq c -vos foo.v`` produces a file called ``foo.vos``, which is similar to ``foo.vo`` except that all opaque proofs are skipped in the compilation process. The compilation using ``rocq c -vok foo.v`` checks that the file ``foo.v`` correctly compiles, including all its opaque proofs. When compiling a file ``bar.v`` that depends on ``foo.v`` (for example via a ``Require Foo.`` command), if the compilation command is ``rocq c -vos bar.v`` or ``rocq c -vok bar.v``, then the file ``foo.vos`` gets loaded (instead of ``foo.vo``). A special case is if file ``foo.vos`` exists and has empty contents, and ``foo.vo`` exists, then ``foo.vo`` is loaded. Empty `.vos` and `.vok` files are created by the `.vo` targets of `rocq makefile`, and an empty `.vok` by the `.vok` targets of `rocq makefile`. Appart from the aforementioned case where ``foo.vo`` can be loaded in place of ``foo.vos``, in general the ``.vos`` and ``.vok`` files live totally independently from the ``.vo`` files. **Dependencies generated by ``rocq makefile``.** The files ``foo.vos`` and ``foo.vok`` both depend on ``foo.v``. Furthermore, if a file ``foo.v`` requires ``bar.v``, then ``foo.vos`` and ``foo.vok`` also depend on ``bar.vos``. Note, however, that ``foo.vok`` does not depend on ``bar.vok``. Hence, as detailed further, parallel compilation of proofs is possible. In addition, ``rocq makefile`` generates for a file ``foo.v`` a target ``foo.required_vos`` which depends on the list of ``.vos`` files that ``foo.vos`` depends upon (excluding ``foo.vos`` itself). As explained next, the purpose of this target is to be able to request the minimal working state for editing interactively the file ``foo.v``. .. warning:: When writing a custom build system, be aware that ``rocq dep`` only produces dependencies related to ``.vos`` and ``.vok`` if the ``-vos`` command line flag is passed. This is to maintain compatibility with dune (see `ocaml/dune#2642 on github `_). **Typical compilation of a set of file using a build system.** Assume a file ``foo.v`` that depends on two files ``f1.v`` and ``f2.v``. The command ``make foo.required_vos`` will compile ``f1.v`` and ``f2.v`` using the option ``-vos`` to skip the proofs, producing ``f1.vos`` and ``f2.vos``. At this point, one is ready to work interactively on the file ``foo.v``, even though it was never needed to compile the proofs involved in the files ``f1.v`` and ``f2.v``. Assume a set of files ``f1.v ... fn.v`` with linear dependencies. The command ``make vos`` enables compiling the statements (i.e. excluding the proofs) in all the files. Next, ``make -j vok`` enables compiling all the proofs in parallel. Thus, calling ``make -j vok`` directly enables taking advantage of a maximal amount of parallelism during the compilation of the set of files. Note that this comes at the cost of parsing and typechecking all definitions twice, once for the ``.vos`` file and once for the ``.vok`` file. However, if files contain nontrivial proofs, or if the files have many linear chains of dependencies, or if one has many cores available, compilation should be faster overall. **Need for Proof using** When a theorem is in a section, typechecking the statement of the theorem may be insufficient to deduce the type of the statement at the end of the section. For example, the proof of the theorem may make use of section variables or section hypotheses that are not mentioned in the statement of the theorem. For this reason, proofs in sections should begin with :cmd:`Proof using` instead of :cmd:`Proof`. The `using` clause should give the names of the section variables that are required for the proof that are not involved in the typechecking of the statement. See :flag:`Suggest Proof Using`. (Note it's fine to use ``Proof using.`` instead of ``Proof.`` for proofs that are not in a section.) When using ``-vos``, proofs in sections with :cmd:`Proof using` are skipped. Proofs in sections without :cmd:`Proof using` are fully processed (much slower). **Interaction with standard compilation** When compiling a file ``foo.v`` using ``rocq compile`` invoked through the makefile generated by `rocq makefile` for a `.vo` target, an empty file ``foo.vos`` and an empty file ``foo.vok`` are created in addition to the regular output file ``foo.vo``. If ``rocq compile`` is subsequently invoked on some other file ``bar.v`` using option ``-vos`` or ``-vok``, and that ``bar.v`` requires ``foo.v``, if Rocq finds an empty file ``foo.vos``, then it will load ``foo.vo`` instead of ``foo.vos``. The purpose of this feature is to allow users to benefit from the ``-vos`` option even if they depend on libraries that were compiled in the traditional manner (i.e., never compiled using the ``-vos`` option). .. _rocqchk: Compiled libraries checker (rocqchk) ---------------------------------------- The ``rocqchk`` command takes a list of library paths as argument, described either by their logical name or by their physical filename, which must end in ``.vo``. The corresponding compiled libraries (``.vo`` files) are searched in the path, recursively processing the libraries they depend on. The content of all these libraries is then type checked. The effect of ``rocqchk`` is only to return with normal exit code in case of success, and with positive exit code if an error has been found. Error messages are not deemed to help the user understand what is wrong. In the current version, it does not modify the compiled libraries to mark them as successfully checked. Note that non-logical information is not checked. By logical information, we mean the type and optional :term:`body` associated with names. It excludes for instance anything related to the concrete syntax of objects (customized syntax rules, association between short and long names), implicit arguments, etc. This tool can be used for several purposes. One is to check that a compiled library provided by a third-party has not been forged and that loading it cannot introduce inconsistencies [#]_. Another point is to get an even higher level of security. Since ``rocq repl`` can be extended with custom tactics, possibly ill-typed code, it cannot be guaranteed that the produced compiled libraries are correct. ``rocqchk`` is a standalone verifier, and thus it cannot be tainted by such malicious code. Command-line options ``-Q``, ``-R``, ``-where`` and ``-impredicative-set`` are supported by ``rocqchk`` and have the same meaning as for ``rocq repl``. As there is no notion of relative paths in object files ``-Q`` and ``-R`` have exactly the same meaning. :-norec *module*: Check *module* but do not check its dependencies. :-admit *module*: Do not check *module* and any of its dependencies, unless explicitly required. :-o: At exit, print a summary about the context. List the names of all assumptions and variables (constants without a :term:`body`). :-silent: Do not write progress information to the standard output. Environment variable ``$ROCQLIB`` can be set to override the location of the standard library. The algorithm for deciding which modules are checked or admitted is the following: assuming that ``rocqchk`` is called with argument ``M``, option ``-norec N``, and ``-admit A``. Let us write :math:`\overline{S}` for the set of reflexive transitive dependencies of set :math:`S`. Then: + Modules :math:`C = \overline{M} \backslash \overline{A} \cup M \cup N` are loaded and type checked before being added to the context. + And :math:`M \cup N \backslash C` is the set of modules that are loaded and added to the context without type checking. Basic integrity checks (checksums) are nonetheless performed. As a rule of thumb, -admit can be used to tell Rocq that some libraries have already been checked. So ``rocqchk A B`` can be split in ``rocqchk A`` && ``rocqchk B -admit A`` without type checking any definition twice. Of course, the latter is slightly slower since it makes more disk access. It is also less secure since an attacker might have replaced the compiled library ``A`` after it has been read by the first command, but before it has been read by the second command. .. [#] Ill-formed non-logical information might for instance bind Corelib.Init.Logic.True to short name False, so apparently False is inhabited, but using fully qualified names, Corelib.Init.Logic.False will always refer to the absurd proposition, what we guarantee is that there is no proof of this latter constant. rocq-9.2.0/doc/sphinx/practical-tools/coqide.rst000066400000000000000000001015241516144147600216560ustar00rootroot00000000000000.. |GtkSourceView| replace:: :smallcaps:`GtkSourceView` .. _coqintegrateddevelopmentenvironment: RocqIDE ========= .. extra =s to avoid being a git conflict marker .. todo: how to say that a number of things are broken? Maybe list them somewhere--doesn't have to be super detailed The Rocq Integrated Development Environment (RocqIDE) is a user-friendly GUI for Coq. Its main purpose is to allow users to edit Coq scripts and step forward and backward through them. Stepping forward executes commands and tactics while stepping backward undoes previously executed commands and tactics, returning to a previous state. To run RocqIDE, enter `rocqide` on the command line. If you include script file names (which end with `.v`) as arguments, each is opened in a separate tab. If you don't, RocqIDE opens a single unnamed buffer (titled `*scratch*`). `rocqide` also accepts many of the options of `rocq top` (see :ref:`therocqcommands`), while ignoring the ones that aren't meaningful for RocqIDE. Use `rocqide --help` to see the list of command line options. .. _rocqide_mainscreen: .. image:: ../_static/rocqide.png :alt: RocqIDE main screen .. Here is the code used in the screenshot: Fixpoint power (x n : nat) {struct n} : nat := match n with | O => 1 | S m => x * power x m end. Notation "x ^ n" := (power x n). Theorem Fermat : (forall x y z n : nat, x^n + y^n = z^n -> n <= 2). Proof. Induction n. The screenshot shows RocqIDE as the user is stepping through the file `Fermat.v`. A menu bar and a tool bar appear at the top of the window. The left-hand panel shows the current *script buffer*. Each script buffer corresponds to a separate Coq process. The upper right panel is the *proof panel*, which shows the goals to be proven. The lower right panel has four tabs: - the *Messages panel* shows messages produced by commands and tactics; - the *Errors panel* shows errors detected when running in :ref:`async mode `; - the *Warnings panel* shows warnings detected when running in async mode; - the *Jobs panel* shows information on the worker processes used by async mode. The contents of the right-hand panels are specific to the currently displayed script. Click the arrow icons to detach these panel into separate windows. The proof panel can be detached with the *Windows/Detach Proof* menu item. The *status bar* is a line of text that appears at the bottom of the window. Managing files and buffers, basic editing ----------------------------------------- The *File* menu lets you open files into buffers, create new buffers, save buffers to files, and print or export them in various formats. Text editing provides the basic operations such as copy, cut, paste, find and replace. Most editing operations are shown in the *Edit* menu. Keystroke equivalents (if defined) for menu items are shown on the right of each item. If you need more complex editor commands, you can launch an external text editor on the current buffer, using the *Edit/External Editor* menu. (Use `Edit/Preferences/Externals/External Editor` to specify the external text editor.) When you're done editing, you currently must reopen the file to see your changes. Also note these key bindings that are not shown in menus: - `Home` and `End` move the cursor to the beginning or end of the current line (`Cmd-Left` and `Cmd-Right` on macOS). - `Ctrl-Home` and `Ctrl-End` move the cursor to the beginning or end of the buffer (`Cmd-Up` and `Cmd-Down` on macOS). - `Ctrl-Left` and `Ctrl-Right` move the cursor to the next beginning or end of a word - `Ctrl-Delete` (`Alt-Backspace` on macOS) and `Ctrl-Backspace` delete characters from the cursor to the next beginning or end of a word. Commenting and uncommenting the current line or selected text is available in the *Tools* menu. If some text is selected, exactly that text is commented out; otherwise the line containing the cursor is commented out. To uncomment, position the cursor between `(*` and `*)` or select any text between them. Files are automatically saved periodically to a recovery file. For example, `foo.v` is saved to `#foo.v#` every 10 seconds by default. You can change the interval in the *Edit / Preferences / Files* dialog. In some cases when RocqIDE exits abruptly, it saves named buffers in ``.crashrocqide`` in the same directory as ````. Unnamed buffers are saved in ``Unnamed_rocqscript_.crashrocqide`` in the directory that RocqIDE was started in. In the *View* menu, you can set several printing options that correspond to options that can appear in the script. For example, *Display notations* on the menu corresponds to the :flag:`Printing Notations` flag. You should use the menu instead of controlling these settings in your script. Running Coq scripts ------------------- Operations for running the script are available in the *Navigation* menu, from the toolbar and from the keyboard. These include: - Forward (`Alt-Down`) to run one command or tactic - Backward (`Alt-Up`) to undo one command or tactic - Run to cursor (`Alt-Right`) to run commands up to the cursor - Reset Coq (`Alt-Home`) to restart the Coq process - Run to end (`Alt-End`) to run commands to the end of the buffer - Interrupt to stop processing commands after the current command completes. (Note: on Windows but not on WSL, Interrupt doesn't work if you start RocqIDE as a background process, e.g. `rocqide &` in bash. See Rocq issue `#16142 `_.) On macOS, use `Cmd-Ctrl` instead of `Alt` for these operations. Tooltips identify the action associated with each toolbar icon. Commands may: - Complete successfully. In this case, the background of the command is marked with the "processed" color (green by default), except for :cmd:`Axiom`\s and :cmd:`Admitted`\s, which are marked in light orange to indicate they are unproven assumptions. - Complete with a warning. In this case, the warning appears in the messages panel in yellow. The background of the command is marked with the "processed" color and the text is shown in blue and underlined. The message text is available as a tooltip on the text of the command. - Fail with an error. If you're stepping through the proof line by line, the error message appears in the message panel in red and the command is shown in red and underlined with a pink background. If you're in async mode, described in more detail below, the message appears in the *errors panel*. Double click on an entry to jump to the point of the error. Execution of commands stops unless you're in async mode. In the previous figure :ref:`RocqIDE main screen `, the running buffer is `Fermat.v`. All commands until the ``Theorem`` have already been executed, then the user tried to go forward executing ``Induction n``. That command failed because no such tactic exists (names of standard tactics are written in lowercase). The failing command has been underlined. If you're not in async mode and you modify the processed part of the buffer, everything after that point is undone. Unlike in `rocq repl`, you should not use :cmd:`Undo` to go backward. The other buttons on the toolbar do the following: - Open a file (folder icon) - Save the current buffer (down arrow icon) - Close the current buffer ("X" icon) - Fully check the document (gears icon) - for async mode - Previous occurrence (left arrow icon) - find the previous occurrence of the current word (the word under cursor) - Next occurrence (right arrow icon) - find the next occurrence of the current word The colored ribbon appearing across the bottom of the RocqIDE window just above the status bar represents the state of processing for the current script schematically. Blue means unprocessed, light green means successfully processed, red mean an error, light orange is used for :cmd:`Axiom` and :cmd:`Admitted` and gray for proofs awaiting their final check. Clicking on the bar moves the script cursor to the corresponding part of the script. (See the next screenshot, in the async mode section.) The left edge of the ribbon corresponds to the first command or tactic in the script and the right edge corresponds to the last command that has been passed to Rocq. Currently, for very long scripts, it may take many seconds for RocqIDE to pass all the commands to the server, causing the display to jump around a lot. Perhaps this will be improved in a future release. The text at the far right hand side of the status bar (e.g. "0 / 1" gives the number of unprocessed proofs that have been sent to Coq and the number of proofs that have errors. .. _asyncmode: Asynchronous mode ----------------- Asynchronous mode uses multiple Coq processes to process proofs in parallel with proof-level granularity. This is described in detail in :ref:`asynchronousandparallelproofprocessing`. While synchronous mode stops processing at the first error it encounters, in async mode, errors only stop processing the proof the error appears in. Therefore async mode can report errors in multiple proofs without manual intervention. In addition, async mode lets the user edit failed proofs without invalidating successful proofs that appear after it in the script. The part of a failed proof between `Proof.` and `Qed.` can then be edited. Quirk: the light blue part after the error and before `Qed.` becomes editable only after you've changed the error-highlighted text or before it. .. image:: ../_static/async-mode.png :alt: Async mode In the screenshot, the proof of the failed theorem can be edited (between `Proof.` and `Qed.`) without invalidating the theorems that follow it. The modified proof can then be reprocessed using the usual navigation operations. The light blue highlight in the script indicates commands that haven't been processed. Async mode defers the final type checking step of proofs, leaving the `Qed.` marked in a slightly different shade of light blue to indicate this. To complete the final checking, click on the "gears" button on the toolbar ("Fully check the document"). Commands and templates ---------------------- The Templates menu allows using shortcuts to insert commands. This is a nice way to proceed if you're not sure of the syntax of the command you want. Moreover, from this menu you can automatically insert templates of complex commands like ``Fixpoint`` that you can conveniently fill in afterwards. Queries ------- .. image:: ../_static/rocqide-queries.png :alt: RocqIDE queries A *query* is any command that does not change the current state, such as :cmd:`About`, :cmd:`Check`, :cmd:`Print`, :cmd:`Search`, etc. The *query pane* lets you run such commands interactively without modifying your script. The query pane is accessible from the *View* menu, or using the shortcut ``F2``. You can also do queries by selecting some text, then choosing an item from the *Queries* menu. The response will appear in the message panel. The image above shows the result after selecting ``Nat.mul`` in the bottom line of the script panel, then choosing *Print* from the *Queries* menu. Compilation ----------- The *Compile* menu offers direct commands to: + compile the current buffer; + run a compilation using `make`; + go to the next compilation error; and + create a `Makefile` using `rocq makefile`. At the moment these are not working well. We recommend you compile from a terminal window for now. We expect to fix them soon. *Compile buffer* saves the current buffer and compiles it with `rocq compile` as specified in the *Externals* section of the *Edit/Preferences* dialog. Output appears in the *Messages* panel. It's mostly useful for single-file projects because it doesn't automatically recompile other files that it depends on that may have changed. *Make* and *Make makefile* run the `make` and `coqmakefile` commands shown in the *Externals* section of the *Edit/Preferences* dialog. Output appears in the *Messages* panel. If you use `_CoqProject` files, you may want to change the settings to `make -f CoqMakefile` and `coq_makefile -f _CoqProject -o CoqMakefile` as suggested in :ref:`here `. Alternatively, you may find it easier to do your `make` and `rocq makefile` commands from the command line. .. _rocqide_make_note: Note that you must explicitly save changed buffers before you run `make`. *File/Save all* is helpful for this. Notice that modified and unmodified buffers show different icons next to the filename on the tab. You may find them helpful. To use the compiled files after compiling a project with the makefile, you must restart the Coq interpreter (using *Navigation/Start* in the menu or `Alt-Home`) for any buffer in which you're stepping through code that relies on the compiled files. To make changes to `_CoqProject` take effect, you must close and reopen buffers associated with files in the project. Note that each buffer is independently associated with a `_CoqProject`. The *Project* section of the *Edit/Preferences* dialog specifies the name to use for the `_CoqProject` file. We recommend not changing this. Remember that these settings are done on a per-installation basis; they currently can't be set differently for each package you're developing. Customizations -------------- Preferences ~~~~~~~~~~~ You may customize your environment with the *Preferences* dialog, which is accessible from *Edit/Preferences* on the menu. There are several sections. .. image:: ../_static/rocqide-preferences-editor.png :alt: RocqIDE preferences dialog, Editor section The *Files* section is devoted to file management: you may configure automatic saving of files, by periodically saving the contents into files named `#f#` for each opened file `f`. You may also activate the *auto reload* feature: in case an opened file is modified on disk by a third party, RocqIDE may read it again for you. Note that in the case you edited that same file, you will be prompted to choose to either discard your changes or not. The File charset encoding choice is described below in :ref:`character-encoding-saved-files`. The *Project* section enables you to change the default name for project files and the way that project file options are used. The *Editor* section (shown in the screenshot above) is for customizing the editor. It includes in particular the ability to activate an Emacs mode named micro-Proof-General (use the Help menu to know more about the available bindings). The *Appearance* section offers controls to set RocqIDE's window default size and the position of tabs. The *Fonts* section is for selecting the text font used for scripts, goal and message panels. The *Colors* and *Tags* sections are for controlling colors and style of the three main buffers. A predefined Coq highlighting style as well as standard |GtkSourceView| styles are available. Other styles can be added e.g. in ``$HOME/.local/share/gtksourceview-3.0/styles/`` (see the general documentation about |GtkSourceView| for the various possibilities). Note that the style of the rest of graphical part of RocqIDE is not under the control of |GtkSourceView| but of GTK+ and governed by files such as ``settings.ini`` and ``gtk.css`` in ``$XDG_CONFIG_HOME/gtk-3.0`` or files in ``$HOME/.themes/NameOfTheme/gtk-3.0``, as well as the environment variable ``GTK_THEME`` (search the internet for the various possibilities). The *Externals* section allows customizing the external commands for compilation, printing, web browsing. In the browser command, you may use `%s` to denote the URL to open, for example: `firefox "%s"`. .. _shortcuts: The *Shortcuts* section lets you change the modifiers (e.g. `Ctrl`, `Alt` and `Shift`) used in all the menu entry key bindings for the selected menu (for the View menu, only the checkbox items will be changed). Current key bindings are shown at the right side of each menu entry. If any of the new key bindings are already assigned, the existing binding will be removed. You can then rebind one of the menu entries as described in the next section. The top of the *Shortcuts* section lets you select the allowed modifiers that can be selected for the listed menus. *Misc* – to be documented .. _user-configuration-directory: Preferences and key bindings are saved in the user configuration directory, which is ``$XDG_CONFIG_HOME/coq`` if the environment variable ``$XDG_CONFIG_HOME`` is set. If the variable isn't set, the directory is ``~/.config/coq`` on Linux and `C:\\Users\\\\AppData\\Local\\coq` on Windows. Preferences are in the file `coqiderc` and key bindings are in the file `coqide.keys`. .. _rocqide_key_bindings: .. _key_bindings: Key bindings ~~~~~~~~~~~~ As explained just above, the *Edit/Preferences/Shortcuts* panel offers buttons to modify in a few clicks the key bindings for a whole menu. Here is a screenshot of the panel: .. image:: ../_static/rocqide-preferences-shortcuts.png :alt: RocqIDE preferences dialog, Shortcuts section Each menu item in the GUI shows its key binding, if one has been defined, on the right-hand side. Typing the key binding is equivalent to selecting the associated item from the menu. On some systems, you can modify the key binding ("accelerator") for a menu entry by going to the corresponding menu item without releasing the mouse button, pressing the keys you want for the new binding and then releasing the mouse button. Alternatively, you can edit the configuration file directly. Key bindings are saved in the file `coqide.keys` in the :ref:`user configuration directory`. Make sure there are no RocqIDE processes running while you edit the file (RocqIDE creates or overwrites the file when it terminates, which may reorder the lines). The file contains lines such as: :: ; (gtk_accel_path "/Queries/About" "a") ; (gtk_accel_path "/Export/Export to" "") (gtk_accel_path "/Edit/Find Next" "F4") The first line corresponds to the menu item for the Queries/About menu item, which was bound by default to `Shift-Ctrl-A`. `` indicates `Cmd` on macOS and otherwise `Ctrl`. The second line is for a menu item that has no key binding. Lines that begin with semicolons are comments created by RocqIDE. RocqIDE uses the default binding for these items. To change a key binding, remove the semicolon and set the third item in the list as desired, such as in the third line. Avoid assigning the same binding to multiple items. If the same menu item name appears on multiple lines in the file, the value from the last line is used. This is convenient for copying a group of changes from elsewhere–just insert the changes at the end of the file. The next time RocqIDE terminates, it will resort the items. The end of `this file `_ gives the names of the keys. Modifiers (e.g. Alt, Ctrl) for some menus can be can be changed as a group from the Edit/Preferences/Shortcuts panel. See :ref:`Shortcuts`. .. todo: list common rebindings? .. todo: microPG mode? Using Unicode symbols --------------------- RocqIDE is based on GTK+ and inherits from it support for Unicode in its text panels. Consequently a large set of symbols is available for notations. Furthermore, RocqIDE conveniently provides a simple way to input Unicode characters. Displaying Unicode symbols ~~~~~~~~~~~~~~~~~~~~~~~~~~ You just need to define suitable notations as described in the chapter :ref:`syntax-extensions-and-notation-scopes`. For example, to use the mathematical symbols βˆ€ and βˆƒ, you may define: .. rocqtop:: in Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity) : type_scope. Notation "βˆƒ x .. y , P" := (exists x, .. (exists y, P) ..) (at level 200, x binder, y binder, right associativity) : type_scope. A small set of such notations are already defined in the Coq library which you can enable with ``Require Import Unicode.Utf8`` inside RocqIDE, or equivalently, by starting RocqIDE with ``rocqide -l utf8``. However, there are some issues when using such Unicode symbols: you of course need to use a character font which supports them. In the Fonts section of the preferences, the Preview line displays some Unicode symbols, so you could figure out if the selected font is OK. Related to this, one thing you may need to do is choosing whether GTK+ should use antialiased fonts or not, by setting the environment variable `GDK_USE_XFT` to 1 or 0 respectively. .. _rocqide-unicode: Bindings for input of Unicode symbols ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RocqIDE supports a builtin mechanism to input non-ASCII symbols. For example, to input ``Ο€``, it suffices to type ``\pi`` then press the combination of key ``Ctrl-Space`` (default key binding). Often, it suffices to type a prefix of the LaTeX token, e.g. typing ``\p`` then ``Ctrl-Space`` suffices to insert a ``Ο€``. For several symbols, ASCII art is also recognized, e.g. ``\->`` for a right arrow, or ``\>=`` for a greater than or equal sign. A larger number of LaTeX tokens are supported by default. The full list is available here: https://github.com/rocq-prover/rocq/blob/master/ide/rocqide/default_bindings_src.ml Custom bindings may be added, as explained further on. The mechanism is active by default, but can be turned off in the Editor section of the preferences. .. note:: It remains possible to input non-ASCII symbols using system-wide approaches independent of RocqIDE. Adding custom bindings ~~~~~~~~~~~~~~~~~~~~~~ To extend the default set of bindings, create a file named ``coqide.bindings`` in the :ref:`user configuration directory`. The file `coqide.bindings` should contain one binding per line, in the form ``\key value``, followed by an optional priority integer. (The key and value should not contain any space character.) .. example:: Here is an example configuration file: :: \par || \pi Ο€ 1 \le ≀ 1 \lambda Ξ» 2 \lambdas Ξ»s Above, the priority number 1 on ``\pi`` indicates that the prefix ``\p`` should resolve to ``\pi``, and not to something else (e.g. ``\par``). Similarly, the above settings ensure than ``\l`` resolves to ``\le``, and that ``\la`` resolves to ``\lambda``. It can be useful to work with per-project binding files. For this purpose RocqIDE accepts a command line argument of the form ``-unicode-bindings file1,file2,...,fileN``. Each of the file tokens provided may consists of one of: - a path to a custom bindings file, - the token ``default``, which resolves to the default bindings file, - the token ``local``, which resolves to the `coqide.bindings` file stored in the :ref:`user configuration directory `. .. warning:: If a filename other than the first one includes a "~" to refer to the home directory, it won't be expanded properly. To work around that issue, one should not use commas but instead repeat the flag, in the form: ``-unicode-bindings file1 .. -unicode-bindings fileN``. .. note:: If two bindings for a same token both have the same priority value (or both have no priority value set), then the binding considered is the one from the file that comes first on the command line. .. _character-encoding-saved-files: Character encoding for saved files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the Files section of the preferences, the encoding option is related to the way files are saved. If you have no need to exchange files with non-UTF-8 aware applications, it is better to choose the UTF-8 encoding, since it guarantees that your files will be read again without problems. (This is because when RocqIDE reads a file, it tries to automatically detect its character encoding.) If you choose something else than UTF-8, then missing characters will be written encoded by `\x{....}` or `\x{........}` where each dot is an hexadecimal digit: the number between braces is the hexadecimal Unicode index for the missing character. .. _rocqide-debugger: Debugger -------- Version 8.15 introduces a visual debugger for |Ltac| tactics within RocqIDE. It supports setting breakpoints visually and automatically displaying the stopping point in the source code with "continue", "step over" "step in" and "step out" operations. The call stack and variable values for each stack frame are shown in a new panel. The debugger is based on the non-visual |Ltac| :ref:`debugger `. We'd like to eventually support other scripting facilities such as Ltac2. Since the visual debugger is new in 8.15, you may encounter bugs or usability issues. The behavior and user interface will evolve as the debugger is refined. There are notes on bugs and potential enhancements at the end of `this page `_. Feel free to suggest changes and improvements by opening an issue on `GitHub `_, or contact `@jfehrle` directly through email, Zulip or Discourse. Breakpoints ~~~~~~~~~~~ This screenshot shows the debugger stopped at a breakpoint in the |Ltac| tactic `my_tac`. Breakpoints are shown with a red background and the stopping point is shown with a dark blue background. `Set Ltac Debug.` enables stopping in the debugger. .. image:: ../_static/debugger.png :alt: RocqIDE Debugger .. created with: Set Ltac Debug. (* enable the debugger *) Ltac my_tac c := let con := constr:(forall a b : nat, (a + b) * c = a * c + b * c) in idtac "A"; idtac "B"; idtac "C". Goal True. my_tac 2. You can control the debugger with function and control keys. Some messages are shown in the Messages panel. You can type :ref:`debugger commands ` in that panel when it shows the debug prompt. The script is not editable while Coq is processing tactics or stopped in the debugger. When Coq is stopped in the debugger (e.g., at a breakpoint), the blue segment in the "in progress" slider at the bottom edge of the window will be stopped at the left hand edge of its range. The function keys are listed, for the moment, with one exception, in the `Debug` menu: Toggle breakpoint (F8) Position the cursor just before the first character of the tactic name in an Ltac construct, then press F8. Press again to remove the breakpoint. F8 is accepted only when all of the coqtop sessions are idle (i.e. at the debug prompt or not processing a tactic or command). Note that :term:`sentences ` containing a single built-in tactic are not Ltac constructs. A breakpoint on :n:`intros.`, for example, is ignored, while breakpoints on either tactic in :n:`intros; idtac.` work. A breakpoint on, say, :n:`my_ltac_tactic.` also works. Breakpoints on Ltac :n:`@value_tactic`\s, which compute values without changing the proof context, such as :tacn:`eval`, are ignored. You must set at least one breakpoint in order to enter the debugger. Continue (F9) Continue processing the proof. If you're not stopped in the debugger, this is equivalent to "Run to end" (Alt-End). Step over (Alt-↓) When stopped in the debugger, execute the next tactic without stopping inside it. If the debugger reaches a breakpoint in the tactic, it will stop. This is the same key combination used for *Forward one command*β€”if you're stopped in the debugger then it does a *Step over* and otherwise it does a *Forward*. Combining the two functions makes it easy to step through a script in a natural way when some breakpoints are set. Step in (F10) When stopped in the debugger, if next tactic is an |Ltac| tactic, stop at the first possible point in the tactic. Otherwise acts as a "step over". Step out (Shift-F10) When stopped in the debugger, continue and then stop at the first possible point after exiting the current |Ltac| tactic. If the debugger reaches a breakpoint in the tactic, it will stop. Break (F11) Stops the debugger at the next possible stopping point, from which you can step or continue. (Not supported in Windows at this time.) Note that the debugger is disabled when RocqIDE is running multiple worker processes, i.e. running in async mode. Going "Forward" a single step at a time doesn't use async mode and will always enter the debugger as expected. In addition, the debugger doesn't work correctly in some cases involving editing failed proofs in asymc mode ( see `#16069 `_.) If you step through `idtac "A"; idtac "B"; idtac "C".`, you'll notice that the steps for `my_tac` are: | `idtac "A"; idtac "B"; idtac "C"` | `idtac "A"; idtac "B"` | `idtac "A"` | `idtac "B"` | `idtac "C"` which reflects the two-phase execution process for the :n:`@tactic ; @tactic` construct. Also keep in mind that |Ltac| backtracking may cause the call stack to revert to a previous state. This may cause confusion. Currently there's no special indication that this has happened. .. unfortunately not working: Note: This `Wiki page `_ describes a way to change RocqIDE key bindings. Call Stack and Variables ~~~~~~~~~~~~~~~~~~~~~~~~ The bottom panel shows the call stack and the variables defined for the selected stack frame. Stack frames normally show the name of tactic being executed, the line number and the last component of the filename without the :n:`.v` suffix. The directory part of the module name is shown when the frame is not in the toplevel script file. For example, :n:`make_rewriter:387, AllTactics (Rewriter.Rewriter)` refers to the file with the module name :n:`Rewriter.Rewriter.AllTactics`. Note: A few stack frames aren't yet displayed in this described format (e.g. those starting with :n:`???`) and may be extraneous. In some cases, the tactic name is not shown. Click on a stack frame or press the Up (↑) or Down (↓) keys to select a stack frame. Coq will jump to the associated code and display the variables for that stack frame. You can select text with the mouse and then copy it to the clipboard with Ctrl-C. Ctrl-A selects the entire stack. The variables panel uses a tree control to show variables defined in the selected stack frame. To see values that don't fit on a single line, click on the triangle. You can select one or more entries from the tree in the usual way by clicking, shift-clicking and control-clicking on an entry. Ctrl-A selects all entries. Ctrl-C copies the selected entries to the clipboard. Note: Some variable are not displayed in a useful form. For example, the value shown for :n:`tac` in a script containing :n:`let tac = ltac:(auto)` appears only as :n:``. We hope to address this soon. The :n:`DETACH` button moves the debugger panel into a separate window, which will make it easier to examine its contents. Supported use cases ~~~~~~~~~~~~~~~~~~~ There are two main use cases for the debugger. They're not very compatible. Instead of showing warning messages or forcing the user to explicitly pick one mode or another, for now it's up to the user to know the limitations and work within them. The *single file* case is running the debugger on a single *primary* script without ever stopping in other *secondary* scripts. In this case, you can edit the primary script while Coq is not running it nor stopped in the debugger. The position of breakpoints will be updated automatically as you edit the file. It's fine to run the debugger in multiple buffers--you will not be confused. The single-file case is preferable when you can use it. The *multi-file* case is when a primary script stops in a secondary script. In this case, breakpoints in the secondary script that move due to script editing may no longer match the locations in the compiled secondary script. The debugger won't stop at these breakpoints as you expect. Also, the code highlighted for stack frames in that script may be incorrect. You will need to re-compile the secondary script and then restart the primary script (Restart, `Alt-Home`) to get back to a consistent state. For multi-file debugging, we suggest detaching the Messages, Proof Context and Debugger panels so they are in separate windows. To do so, click on the arrow icon next to *Messages*, select *Windows / Detach Proof* from the menu and click on *DETACH* in the Debugger panel. Note that the Debugger panel is initially attached to the Script panel of the toplevel script. Also note that, for now, the "in progress" slider is accurate only when the associated toplevel script panel is visible. If a debugger instance is stopped in a secondary script, the debugger function keys are directed to the debugger instance associated with the primary script. The debugger doesn't attempt to support multiple instances stopped in the same secondary script. If you have a need to do this, run each debugger instance in a separate RocqIDE process/window. Note that if you set a breakpoint in a script that may be called by multiple debugger instances, you may inadvertently find you've gotten into unsupported territory. rocq-9.2.0/doc/sphinx/practical-tools/utilities.rst000066400000000000000000001506421516144147600224320ustar00rootroot00000000000000.. _utilities: ------------------------ Building Rocq Projects ------------------------ .. _configuration_basics: Rocq configuration basics ------------------------- Describes the basics of Rocq configuration that affect running and compiling Rocq scripts. It recommends preferred ways to install the Rocq Prover, manage installed packages and structure your project directories for ease of use. Installing the Rocq Prover and Rocq packages with opam ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The easiest way to install the Rocq Prover is with the `Coq Platform `_, which relies on the `opam package manager `_. The Coq platform installation process provides options to automatically install some of the most frequently used packages at the same time. While there's currently no guarantee that user-developed packages will compile on the current version of Rocq, all packages that Coq platform installs should compile without difficulty--this is part of the Coq platform release process. Once you've installed Rocq, you can search for additional user-developed packages from the `package list `_ or other opam repositories. These commands may be helpful: - `opam list "coq-*"` to see the list of available and installed packages - `opam list "coq-*" --installed` to see the list of installed packages - `opam install ` to install a package on your system. - `opam update` as needed to update the list of available packages For example, this command shows the installed packages with the package name, its version and short description:: $ opam list "coq-*" --installed coq-bignums 8.15.0 Bignums, the Coq library of arbitrary large numbers Note that packages marked `released` in the package list web page are more stable than those marked `extra-dev`. To install `extra-dev` packages, first add the `coq-extra-dev` opam repository to your local opam installation with this command:: opam repo add coq-extra-dev https://rocq-prover.org/opam/extra-dev While this is the easiest way to install packages, it is not the only way. You will then need to find the :term:`logical name` used to refer to the package in :cmd:`Require` commands. There are a couple ways to do this: - If you installed with opam, use :n:`opam show --list-files coq-bignums | head -n1` - the last component of the filename is the logical name (`Bignums`). - On Linux, :n:`ls $(rocq c -where)/user-contrib` shows the logical names of all installed user-contributed packages. You should be able to guess which one you need. - Use the :cmd:`Print LoadPath` command when running Rocq, which shows the mapping from :term:`logical path`\s to directories. Again, you should be able to guess. The last two methods work even if you didn't install with opam. Perhaps in the future the package name to logical name mapping will be more readily available. Once you know the logical name of the package, use it to load compiled files from the package with the :cmd:`Require` command. A :gdef:`package` is a group of files in a top directory and its subdirectories that's installed as a unit. Packages are compiled from *projects*. These terms are virtually interchangeable. Setup for working on your own projects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The working and master copies of source code for your own projects should not be in the directory tree where Rocq is installed. In particular, when you upgrade to a new version of Rocq, any directories you created in the old version won't be copied or moved. We encourage you to use a source code control system for any non-trivial project because it makes it easy to track the history of your changes. `git `_ is the system most used by Rocq projects. Typically, each project has its own git repository. For a project that has only a single file, you can create the file wherever you like and then step through it in one of the IDEs for Rocq, such as :ref:`coqintegrateddevelopmentenvironment`, `ProofGeneral `_, `vsCoq `_ and `Coqtail `_. If your project has multiple files in a single directory that depend on each other through :cmd:`Require` commands, they must be compiled in an order that matches their dependencies. Scripts in `.v` files must be compiled to `.vo` files using `rocq compile` before they can be :cmd:`Require`\d in other files. Currently, the `.vo` file is created in the same directory as its `.v` file. For example, if B.v depends on A.v, then you should compile A.v before B.v. You can do this with :n:`rocq c A.v` followed by :n:`rocq c B.v`, but you may find it tedious to manage the dependencies, particularly as the number of files increases. If your project files are in multiple directories, you would also need to pass additional command-line -Q and -R parameters to your IDE. More details to manage and keep track of. Instead, by creating a `_CoqProject` file, you can automatically generate a makefile that applies the correct dependencies when it compiles your project. In addition, the IDEs find and interpret `_CoqProject` files, so project files spread over multiple directories will work seamlessly. If you're editing `dir/foo.v`, the IDEs apply settings from the `_CoqProject` file in `dir` or the closest ancestor directory. The `_CoqProject` file identifies the :term:`logical path` to associate with the directories containing your compiled files. The `_CoqProject` file is normally in the top directory of the project. Occasionally it may be useful to have additional `_CoqProject` files in subdirectories, for example in order to pass different startup parameters to Rocq for particular scripts. .. _building_with_coqproject: Building a project with _CoqProject (overview) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note: building with `dune` is experimental. See :ref:`building_dune`. The `_CoqProject` file contains the information needed to generate a makefile for building your project. Your `_CoqProject` file should be in the top directory of your project's source tree. We recommend using the :term:`logical name` of the project as the name of the top directory. **Note:** Make sure that `_CoqProject` has no file extension. On Windows, some tools such as Notepad invisibly append `.txt` even when you ask to save the file as `_CoqProject`. Also, File Manager doesn't display file extensions. You may be better off using a command line interface and an editor such as `vi` that always show file extensions. For example, here is a minimal `_CoqProject` file for the `MyPackage` project (the logical name of the package), which includes all the ``.v`` files (and other file types) in the `theories` directory and its subdirectories:: -R theories MyPackage theories :n:`-R theories MyPackage` (see :ref:`here <-Q-option>`) declares that `theories` is a top directory of `MyPackage`. :n:`theories` on the second line declares that all `.v` files in `theories` and its subdirectories are indeed included in the project. In addition, you can list individual files, for example the two script files `theories/File1.v` and `theories/SubDir/File2.v` whose logical paths are `MyPackage.File1` and `MyPackage.SubDir.File2`:: -R theories MyPackage theories/File1.v theories/SubDir/File2.v The generated makefile only processes the specified files. You can list multiple directories if you wish. .. I think dotted names are not useful. For example, this doesn't produce usable .vo files because a.v and b.v are not in an `Abc` subdirectory:: -R . Michael.Abc a.v b.v We suggest choosing a logical name that's different from those used for commonly used packages, particularly if you plan to make your package available to others. Or you can easily do a global replace, if necessary, on the package name before it is (widely) used. After that, a name change may begin to impact a large number of users. Alas, there's currently no easy way to discover what :term:`logical name`\s have already been used. The :cmd:`Print LoadPath` command helps a bit; it shows the logical names defined in the Rocq process. Then: - Generate a makefile from `_CoqProject` with :n:`rocq makefile -f _CoqProject -o CoqMakefile` and - Compile your project with :n:`make -f CoqMakefile` as needed. If you add more files to your project that are not in directories listed in `_CoqProject`, update `_CoqProject` and re-run `rocq makefile` and `make`. .. todo we should use a standard name for the makefile so IDEs can find it. Maybe you should be allowed to include "-o MAKEFILENAME" in the `_CoqProject`, maybe default to "makefile"; provide a name only if you want to use a wrapper Then mandate that the file be called simply "makefile" so IDEs can find it. We recommend checking `CoqMakefile` and `CoqMakefile.conf` into your source code control system. Also we recommend updating them with `rocq makefile` when you switch to a new version of Rocq. In RocqIDE, you must explicitly save modified buffers before running `make` and restart the Rocq interpreter in any buffers in which you're running code. More details :ref:`here `. See :ref:`rocq_makefile` for a complete description of `rocq makefile` and the files it generates. .. todo: describe -vos option, a way to do quicker builds with some caveats .. _logical-paths-load-path: Logical paths and the load path ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Commands such as :cmd:`Require` identify files with :term:`logical paths` rather than file system paths so that scripts don't have to be modified to run on different computers. The :cmd:`Print LoadPath` command displays the :gdef:`load path`, which is a list of (logical path, :term:`physical path`) pairs for directories. For example, you may see:: Logical Path / Physical path: Bignums /home/jef/coq/lib/coq/user-contrib/Bignums Bignums.BigZ /home/jef/coq/lib/coq/user-contrib/Bignums/BigZ Ltac2 /home/jef/coq/lib/coq/user-contrib/Ltac2 Stdlib /home/jef/coq/lib/coq/theories Stdlib.Numbers /home/jef/coq/lib/coq/theories/Numbers Stdlib.Numbers.Natural /home/jef/coq/lib/coq/theories/Numbers/Natural Stdlib.Numbers.Natural.Binary /home/jef/coq/lib/coq/theories/Numbers/Natural/Binary Stdlib.Numbers.Integer /home/jef/coq/lib/coq/theories/Numbers/Integer Stdlib.Arith /home/jef/coq/lib/coq/theories/Arith <> /home/jef/myproj The components of each pair share suffixes, e.g. `Bignums.BigZ` and `Bignums/BigZ` or `Stdlib.Numbers.Natural` and `Numbers/Natural`. Physical pathnames should always use `/` rather than `\\`, even when running on Windows. Packages with a physical path containing `user-contrib` were installed with the Rocq binaries (e.g. `Ltac2`), with the Coq Platform or with opam (e.g. `Bignums`) or perhaps by other means. Note that, for these entries, the entire logical path appears in the directory name. Packages that begin with `Stdlib` were installed with the Rocq binaries. Note that the :term:`logical name` `Stdlib` doesn't appear in the physical path. The `<>` in the final entry represents an empty logical pathname, which permits loading files from the associated directory with just the basename of the script file, e.g. specify `Foo` to load `Foo.vo`. This entry corresponds to the current directory when Rocq was started. Note that the :cmd:`Cd` command doesn't change the associated directory--you would need to restart RocqIDE. With some exceptions noted below, the :term:`load path` is generated from files loaded from the following directories and their subdirectories in the order shown. The associated logical path is determined from the filesystem path, relative to the directory, e.g. the file `Foo/Bar/script.vo` becomes `Foo.Bar.script`: - directories specified with :ref:`-R and -Q command line options <-Q-option>`, - the current directory where the Rocq process was launched (without including subdirectories), - the directories listed in the `ROCQPATH` environment variable (separated with colons, or, on Windows, with semicolons) .. not working - the ``coq`` subdirectory for each directory listed in the ``XDG_DATA_DIRS`` environment variable (separated with colons, or, on Windows, with semicolons) - the ``${XDG_DATA_HOME}/coq/`` directory (see `XDG base directory specification `_). However, RocqIDE relies on the default setting; therefore we recommend not setting this variable. - installed packages from the `user-contrib` directory in the Rocq installation, - the Rocq standard library from the `theories` directory in the Rocq installation (with `Stdlib` prepended to the logical path), .. todo: XDG* with example(s) and suggest best practices for their use .. todo: document loadpath for ml files Each directory may contain multiple `.v`/`.vo` files. For example, :n:`Require Import Stdlib.Numbers.Natural.Binary.NBinary` loads the file :n:`NBinary.vo` from the associated directory. Note that a short name is often sufficient in :cmd:`Require` instead of a fully qualified name. In :cmd:`Require` commands referring to the current package (if `_CoqProject` uses `-R`) can be referenced with a short name without a `From` clause provided that the logical path is unambiguous (as if they are available through `-R`). In contrast, :cmd:`Require` commands that load files from other locations such as `user-contrib` must either use an exact logical path or include a `From` clause (as if they are available through `-Q`). This is done to reduce the number of ambiguous logical paths. We encourage using `From` clauses. Note that if you use a `_CoqProject` file, the `ROCQPATH` environment variable is not helpful. If you use `ROCQPATH` without a `_CoqProject`, a file in `MyPackage/theories/SubDir/File.v` will be loaded with the logical name `MyPackage/theories/SubDir.File`, which may not be what you want. If you associate the same logical name with more than one directory, Rocq looks for the `.vo` file in the most recently added path first (i.e., the one that appears earlier in the :cmd:`Print LoadPath` output). Modifying multiple interdependent projects at the same time ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you want to modify multiple interdependent projects simultaneously, good practice recommends that all of them should be uninstalled. Since the IDEs only apply a single `_CoqProject` file for each script, the best way to make them work properly is to temporarily edit the `_CoqProject` for each project so it includes the other uninstalled projects it depends on, then regenerate the makefile. This may make your `_CoqProject` system dependent. Such dependencies shouldn't be present in published packages. For example, if project `A` requires project `B`, add `-Q B` to the `_CoqProject` in `A`. This will override any installed version of `B` only when you're working on scripts in `A`. If you want to build all the related projects at once, you're on your own. There's currently no tooling to identify the internal dependencies between the projects (and thus the order in which to build them). .. todo I thought @herbelin added code to complain about ambiguous short names I made up some stuff below, need to check it: Installed and uninstalled packages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The directory structure of installed packages (i.e., in the `user-contrib` directory of the Rocq installation) differs from that generally used for the project source tree. The installed directory structure omits the paths given in the `-R` and `-Q` parameters that are not part of the logical name of a file. For example, consider the following `_CoqProject` file. -R theories MyPackage theories/File1.v theories/SubDir/File2.v The compiled file `theories/File1.vo` will be installed in the directory `user-contrib/MyPackage` and `theories/SubDir/File2.vo` in `user-contrib/MyPackage/SubDir`. Use :n:`make -f CoqMakefile install` to install a project from a directory. If you try to step through scripts in installed packages (e.g. to understand the proofs therein), you may get unexpected failures for two reasons: * `_CoqProject` files often have at least one `-R` parameter, while installed packages are loaded with the less-permissive `-Q` option described in the :cmd:`Require` command, which may cause a :cmd:`Require` to fail. One workaround is to create a `_CoqProject` file containing the line `-R . ` in `user-contrib/`. In this case, the `_CoqProject` doesn't need to list all the source files. * Sometimes, the `_CoqProject` file specifies options that affect the behavior of Rocq, such as `-impredicative-set`. These can similarly be added in `_CoqProject` files in `user-contrib`. Another way to get around these problems is to download the source tree for the project in a new directory and compile it before stepping through its scripts. Upgrading to a new version of Rocq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `.vo` files are specific to the version of Rocq that compiled them. When you upgrade to a new version of Rocq, you must recompile all the projects that you want to run in the new version. This is necessary to assure that your proofs still work in the new version. Once their projects build on the new version, most users no longer have a need to run on the old version. If, however, you want to overlap working on your project on both the old and new versions, you'll need to create separate source directories for your project for the different Rocq versions. Currently the compiled `.vo` files are kept in the same directory as their corresponding `.v` file. .. todo: Making your packages available with opam .. _rocq_makefile: Building a Rocq project with rocq makefile (details) ---------------------------------------------------- The ``rocq makefile`` tool is included with Rocq and is based on generating a makefile. The majority of Rocq projects are very similar: a collection of ``.v`` files and possibly some ``.ml`` ones (a Rocq plugin). The main piece of metadata needed in order to build the project are the command line options to ``rocq compile`` (e.g. ``-R``, ``-Q``, ``-I``, see :ref:`command line options `). Collecting the list of files and options is the job of the ``_CoqProject`` file. A ``_CoqProject`` file may contain the following kinds of entries in any order, separated by whitespace: * Selected options of `rocq compile`, which are forwarded directly to it. Currently these are ``-Q``, ``-I``, ``-R`` and ``-native-compiler``. * ``-arg`` options for other options of `rocq compile` that don’t fall in the above set. * Options specific to ``rocq makefile``. Currently there are two options: ``-generate-meta-for-package`` (see below for details), and ``-docroot``. * Directory names, which include all appropriate files in the directory and its subdirectories. * Comments, started with an unquoted ``#`` and continuing to the end of the line. A simple example of a ``_CoqProject`` file follows: :: -R theories/ MyCode -arg "-w all" # include everything under "theories", e.g. foo.v and bar.v theories -I src/ # include everything under "src", e.g. baz.mlg bazaux.ml and qux_plugin.mlpack src -generate-meta-for-package my-package Lines in the form ``-arg foo`` pass the argument ``foo`` to ``rocq compile``: in the example, this passes the two-word option ``-w all`` (see :ref:`command line options `). You must specify a ``-R/-Q`` flag for your project so its modules are properly qualified. Omitting it will generate object files that are unusable except by experts. Projects that include plugins (i.e. `.ml` or `.mlg` OCaml source files) must have a ``META`` file, as per `findlib `_. If the project has only a single plugin, the ``META`` file can be generated automatically when the option ``-generate-meta-for-package my-package`` is given. The generated file makes the plugin available to the :cmd:`Declare ML Module` as ``my-package.plugin``. If the generated file doesn't suit your needs (for instance because it depends on some OCaml packages) or your project has multiple plugins, then create a file named ``META.my-package`` and list it in the ``_CoqProject`` file. You can use ``ocamlfind lint META.my-package`` to lint the hand written file. Typically ``my-package`` is the name of the ``OPAM`` package for your project (which conventionally starts with ``coq-``). If the project includes a ``.mlg`` file (to be pre-processed by ``rocq pp-mlg``) that declares a plugin, then the given name must match the ``findlib`` plugin name, e.g. ``DECLARE PLUGIN "my-package.plugin"``. The ``-native-compiler`` option given in the ``_CoqProject`` file overrides the global one passed at configure time. RocqIDE, Proof General, VsCoq and Coqtail all understand ``_CoqProject`` files and can be used to invoke Rocq with the desired options. The ``rocq makefile`` utility can be used to set up a build infrastructure for the Rocq project based on makefiles. We recommend invoking ``rocq makefile`` this way: :: rocq makefile -f _CoqProject -o CoqMakefile This command generates the following files: CoqMakefile is a makefile for ``GNU Make`` with targets to build the project (e.g. generate .vo or .html files from .v or compile .ml* files) and install it in the ``user-contrib`` directory where the Rocq library is installed. CoqMakefile.conf contains make variables assignments that reflect the contents of the ``_CoqProject`` file as well as the path relevant to Rocq. Run ``rocq makefile --help`` for a description of command line options. The recommended approach is to invoke ``CoqMakefile`` from a standard ``Makefile`` in the following form: .. example:: :: # KNOWNTARGETS will not be passed along to CoqMakefile KNOWNTARGETS := CoqMakefile extra-stuff extra-stuff2 # KNOWNFILES will not get implicit targets from the final rule, and so # depending on them won't invoke the submake # Warning: These files get declared as PHONY, so any targets depending # on them always get rebuilt KNOWNFILES := Makefile _CoqProject .DEFAULT_GOAL := invoke-coqmakefile CoqMakefile: Makefile _CoqProject $(COQBIN)rocq makefile -f _CoqProject -o CoqMakefile invoke-coqmakefile: CoqMakefile $(MAKE) --no-print-directory -f CoqMakefile $(filter-out $(KNOWNTARGETS),$(MAKECMDGOALS)) .PHONY: invoke-coqmakefile $(KNOWNFILES) #################################################################### ## Your targets here ## #################################################################### # This should be the last rule, to handle any targets not declared above %: invoke-coqmakefile @true The advantage of a wrapper, compared to directly calling the generated ``Makefile``, is that it provides a target independent of the version of Rocq to regenerate a ``Makefile`` specific to the current version of Rocq. Additionally, the master ``Makefile`` can be extended with targets not specific to Rocq. Including the generated makefile with an include directive is discouraged, since the contents of this file, including variable names and status of rules, may change in the future. Use the optional file ``CoqMakefile.local`` to extend ``CoqMakefile``. In particular, you can declare custom actions to run before or after the build process. Similarly you can customize the install target or even provide new targets. See :ref:`rocqmakefilelocal` for extension-point documentation. Although you can use all variables defined in ``CoqMakefile`` in the *recipes* of rules that you write and in the definitions of any variables that you assign with ``=``, many variables are not available for use if you assign variable values with ``:=`` nor to define the *targets* of rules nor in top-level conditionals such as ``ifeq``. Additionally, you must use `secondary expansion `_ to make use of such variables in the prerequisites of rules. To access variables defined in ``CoqMakefile`` in rule target computation, top-level conditionals, and ``:=`` variable assignment, for example to add new dependencies to compiled outputs, use the optional file ``CoqMakefile.local-late``. See :ref:`rocqmakefilelocallate` for a non-exhaustive list of variables. The extensions of files listed in ``_CoqProject`` determine how they are built. In particular: + Rocq files must use the ``.v`` extension + OCaml files must use the ``.ml`` or ``.mli`` extension + OCaml files that require pre processing for syntax extensions (like ``VERNAC EXTEND``) must use the ``.mlg`` extension + In order to generate a plugin one has to list all OCaml modules (i.e. ``Baz`` for ``baz.ml``) in a ``.mlpack`` file (or ``.mllib`` file). The use of ``.mlpack`` files has to be preferred over ``.mllib`` files, since it results in a β€œpacked” plugin: All auxiliary modules (as ``Baz`` and ``Bazaux``) are hidden inside the plugin’s "namespace" (``Qux_plugin``). This reduces the chances of begin unable to load two distinct plugins because of a clash in their auxiliary module names. .. todo: don't want "Comments" to appear in the TOC, but won't build with "+++++++" Comments ~~~~~~~~ ``#`` outside of double quotes starts a comment that continues to the end of the line. Comments are ignored. Quoting arguments to rocq c +++++++++++++++++++++++++++ Any string in a ``_CoqProject`` file may be enclosed in double quotes to include whitespace characters or ``#``. For example, use ``-arg "-w all"`` to pass the argument ``-w all`` to `rocq compile`. If the argument to `rocq compile` needs some quotes as well, use single-quotes inside the double-quotes. For example ``-arg "-set 'Default Goal Selector=!'"`` gets passed to `rocq compile` as ``-set 'Default Goal Selector=!'``. But note, that single-quotes in a ``_CoqProject`` file are only special characters if they appear in the string following ``-arg``. And on their own they don't quote spaces. For example ``-arg 'foo bar'`` in ``_CoqProject`` is equivalent to ``-arg foo "bar'"`` (in ``_CoqProject`` notation). ``-arg "'foo bar'"`` behaves differently and passes ``'foo bar'`` to `rocq compile`. Forbidden filenames +++++++++++++++++++ The paths of files given in a ``_CoqProject`` file may not contain any of the following characters: ``\n``, ``\t``, space, ``\``, ``'``, ``"``, ``#``, ``$``, ``%``. These characters have special meaning in Makefiles and ``rocq makefile`` doesn't support encoding them correctly. Warning: No common logical root +++++++++++++++++++++++++++++++ When a ``_CoqProject`` file contains something like ``-R theories Foo theories/Bar.v``, the ``install-doc`` target installs the documentation generated by ``rocq doc`` into ``user-contrib/Foo/``, in the folder where Rocq was installed. But if the ``_CoqProject`` file contains something like: :: -R theories/Foo Foo -R theories/Bar Bar theories/Foo/Foo.v theories/Bar/Bar.v the Rocq files of the project don’t have a :term:`logical path` in common and ``rocq makefile`` doesn’t know where to install the documentation. It will give a warning: "No common logical root" and generate a Makefile that installs the documentation in some folder beginning with "orphan", in the above example, it'd be ``user-contrib/orphan_Foo_Bar``. In this case, specify the ``-docroot`` option in _CoqProject to override the automatically selected logical root. .. _rocqmakefilelocal: CoqMakefile.local +++++++++++++++++ The optional file ``CoqMakefile.local`` is included by the generated file ``CoqMakefile``. It can contain two kinds of directives. **Variable assignment** The variable must belong to the variables listed in the ``Parameters`` section of the generated makefile. These include: :CAMLPKGS: can be used to specify third party findlib packages, and is passed to the OCaml compiler on building or linking of modules. Eg: ``-package yojson``. :CAMLFLAGS: can be used to specify additional flags to the OCaml compiler, like ``-bin-annot`` or ``-w``.... :OCAMLWARN: it contains a default of ``-warn-error +a-3``, useful to modify this setting; beware this is not recommended for projects in Rocq's CI. :ROCQ, COQC, COQDEP, COQDOC: can be set in order to use alternative binaries (e.g. wrappers) :COQ_SRC_SUBDIRS: can be extended by including other paths in which ``*.cm*`` files are searched. For example ``COQ_SRC_SUBDIRS+=user-contrib/Unicoq`` lets you build a plugin containing OCaml code that depends on the OCaml code of ``Unicoq`` :COQFLAGS: override the flags passed to ``rocq compile``. By default ``-q``. :COQEXTRAFLAGS: extend the flags passed to ``rocq compile`` :COQCHKFLAGS: override the flags passed to ``rocqchk``. By default ``-silent -o``. :COQCHKEXTRAFLAGS: extend the flags passed to ``rocqchk`` :COQDOCFLAGS: override the flags passed to ``rocq doc``. By default ``-interpolate -utf8``. :COQDOCEXTRAFLAGS: extend the flags passed to ``rocq doc`` :COQLIBINSTALL, COQPLUGININSTALL, COQDOCINSTALL: specify where the Rocq libraries, plugins and documentation will be installed. By default a combination of ``$(DESTDIR)`` (if defined) with ``$(COQLIB)/user-contrib``, ``$(COQCORELIB)/..`` and ``$(DOCDIR)/coq/user-contrib``. Use :ref:`rocqmakefilelocallate` instead to access more variables. **Rule extension** The following makefile rules can be extended. .. example:: :: pre-all:: echo "This line is print before making the all target" install-extra:: cp ThisExtraFile /there/it/goes ``pre-all::`` run before the ``all`` target. One can use this to configure the project, or initialize sub modules or check dependencies are met. ``post-all::`` run after the ``all`` target. One can use this to run a test suite, or compile extracted code. ``install-extra::`` run after ``install``. One can use this to install extra files. ``install-doc::`` One can use this to install extra doc. ``uninstall::`` \ ``uninstall-doc::`` \ ``clean::`` \ ``cleanall::`` \ ``archclean::`` \ ``merlin-hook::`` One can append lines to the generated ``.merlin`` file extending this target. .. _rocqmakefilelocallate: CoqMakefile.local-late ++++++++++++++++++++++ The optional file ``CoqMakefile.local-late`` is included at the end of the generated file ``CoqMakefile``. The following is a partial list of accessible variables: :COQ_VERSION: the version of ``rocq compile`` being used, which can be used to provide different behavior depending on the Rocq version :COQMAKEFILE_VERSION: the version of Rocq used to generate the Makefile, which can be used to detect version mismatches :ALLDFILES: the list of generated dependency files, which can be used, for example, to cause ``make`` to recompute dependencies when files change by writing ``$(ALLDFILES): myfiles`` or to indicate that files must be generated before dependencies can be computed by writing ``$(ALLDFILES): | mygeneratedfiles`` :VOFILES, GLOBFILES, CMOFILES, CMXFILES, OFILES, CMAFILES, CMXAFILES, CMIFILES, CMXSFILES: lists of files that are generated by various invocations of the compilers In addition, the following variables may be useful for deciding what targets to present via ``$(shell ...)``; these variables are already accessible in recipes for rules added in ``CoqMakefile.local``, but are only accessible from top-level ``$(shell ...)`` invocations in ``CoqMakefile.local-late``: :ROCQ, COQC, COQDEP, COQDOC, CAMLC, CAMLOPTC: compiler binaries :COQFLAGS, CAMLFLAGS, COQLIBS, COQDEBUG, OCAMLLIBS: flags passed to the Rocq or OCaml compilers Timing targets and performance testing ++++++++++++++++++++++++++++++++++++++ The generated ``Makefile`` supports the generation of three kinds of timing data: per-file build-times, per-line times for individual files, and profiling data in Google trace format for individual files. The following targets and Makefile variables allow collection of per- file timing data: + ``TIMED=1`` passing this variable will cause ``make`` to emit a line describing the user-space build-time and peak memory usage for each file built. .. note:: On ``Mac OS``, this works best if you’ve installed ``gnu-time``. .. example:: For example, the output of ``make TIMED=1`` may look like this: :: ROCQ DEP VFILES ROCQ C Slow.v Slow.vo (user: 0.34 mem: 395448 ko) ROCQ C Fast.v Fast.vo (user: 0.01 mem: 45184 ko) + ``pretty-timed`` this target stores the output of ``make TIMED=1`` into ``time-of-build.log``, and displays a table of the times and peak memory usages, sorted from slowest to fastest, which is also stored in ``time-of-build-pretty.log``. If you want to construct the ``log`` for targets other than the default one, you can pass them via the variable ``TGTS``, e.g., ``make pretty-timed TGTS="a.vo b.vo"``. .. note:: This target requires ``python`` to build the table. .. note:: This target will *append* to the timing log; if you want a fresh start, you must remove the file ``time-of-build.log`` or ``run make cleanall``. .. note:: By default the table displays user times. If the build log contains real times (which it does by default), passing ``TIMING_REAL=1`` to ``make pretty-timed`` will use real times rather than user times in the table. .. note:: Passing ``TIMING_INCLUDE_MEM=0`` to ``make`` will result in the tables not including peak memory usage information. Passing ``TIMING_SORT_BY_MEM=1`` to ``make`` will result in the tables be sorted by peak memory usage rather than by the time taken. .. example:: For example, the output of ``make pretty-timed`` may look like this: :: ROCQ DEP VFILES ROCQ C Slow.v Slow.vo (real: 0.52, user: 0.39, sys: 0.12, mem: 394648 ko) ROCQ C Fast.v Fast.vo (real: 0.06, user: 0.02, sys: 0.03, mem: 56980 ko) Time | Peak Mem | File Name -------------------------------------------- 0m00.41s | 394648 ko | Total Time / Peak Mem -------------------------------------------- 0m00.39s | 394648 ko | Slow.vo 0m00.02s | 56980 ko | Fast.vo + ``print-pretty-timed-diff`` this target builds a table of timing changes between two compilations; run ``make make-pretty-timed-before`` to build the log of the β€œbefore” times, and run ``make make-pretty-timed-after`` to build the log of the β€œafter” times. The table is printed on the command line, and stored in ``time-of-build-both.log``. This target is most useful for profiling the difference between two commits in a repository. .. note:: This target requires ``python`` to build the table. .. note:: The ``make-pretty-timed-before`` and ``make-pretty-timed-after`` targets will *append* to the timing log; if you want a fresh start, you must remove the files ``time-of-build-before.log`` and ``time-of-build-after.log`` or run ``make cleanall`` *before* building either the β€œbefore” or β€œafter” targets. .. note:: The table will be sorted first by absolute time differences rounded towards zero to a whole-number of seconds, then by times in the β€œafter” column, and finally lexicographically by file name. This will put the biggest changes in either direction first, and will prefer sorting by build-time over subsecond changes in build time (which are frequently noise); lexicographic sorting forces an order on files which take effectively no time to compile. If you prefer a different sorting order, you can pass ``TIMING_SORT_BY=absolute`` to sort by the total time taken, or ``TIMING_SORT_BY=diff`` to sort by the signed difference in time. .. note:: Just like ``pretty-timed``, this table defaults to using user times. Pass ``TIMING_REAL=1`` to ``make`` on the command line to show real times instead. .. note:: Just like ``pretty-timed``, passing ``TIMING_INCLUDE_MEM=0`` to ``make`` will result in the tables not including peak memory usage information. Passing ``TIMING_SORT_BY_MEM=1`` to ``make`` will result in the tables be sorted by peak memory usage rather than by the time taken. .. example:: For example, the output table from ``make print-pretty-timed-diff`` may look like this: :: After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name ----------------------------------------------------------------------------------------------------------------------------- 0m00.43s | 394700 ko | 0m00.41s | 394648 ko || +0m00.01s || 52 ko | +4.87% | +0.01% | Total Time / Peak Mem ----------------------------------------------------------------------------------------------------------------------------- 0m00.39s | 394700 ko | 0m00.02s | 56980 ko || +0m00.37s || 337720 ko | +1850.00% | +592.69% | Fast.vo 0m00.04s | 56772 ko | 0m00.39s | 394648 ko || -0m00.35s || -337876 ko | -89.74% | -85.61% | Slow.vo The following targets and ``Makefile`` variables allow collection of per- line timing data: + ``TIMING=1`` passing this variable will cause ``make`` to use ``rocq c -time-file`` to write to a ``.v.timing`` file for each ``.v`` file compiled, which contains line-by-line timing information. .. example:: For example, running ``make all TIMING=1`` may result in a file like this: :: Chars 0 - 26 [Require~Stdlib.ZArith.BinInt.] 0.157 secs (0.128u,0.028s) Chars 27 - 68 [Declare~Reduction~comp~:=~vm_c...] 0. secs (0.u,0.s) Chars 69 - 162 [Definition~foo0~:=~Eval~comp~i...] 0.153 secs (0.136u,0.019s) Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] 0.239 secs (0.236u,0.s) + ``rocq timelog2html`` :: rocq timelog2html file.v file.v.time1 [file.v.time2 [file.v.time3]] > file.v.html this command produces a HTML file displaying the original `file.v` with highlights for each command indicating how much time the command used according to the given timing files. It supports between 1 and 3 timing files. `rocq timelog2html` requires the `rocq-devtools` package. There is currently no `rocq makefile` target that automatically invokes this tool. + ``print-pretty-single-time-diff`` :: print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing this target will make a sorted table of the per-line timing differences between the timing logs in the ``BEFORE`` and ``AFTER`` files, display it, and save it to the file specified by the ``TIME_OF_PRETTY_BUILD_FILE`` variable, which defaults to ``time-of-build-pretty.log``. To generate the ``.v.before-timing`` or ``.v.after-timing`` files, you should pass ``TIMING=before`` or ``TIMING=after`` rather than ``TIMING=1``. .. note:: The sorting used here is the same as in the ``print-pretty-timed-diff`` target. .. note:: This target requires python to build the table. .. note:: This target follows the same sorting order as the ``print-pretty-timed-diff`` target, and supports the same options for the ``TIMING_SORT_BY`` variable. .. note:: By default, two lines are only considered the same if the character offsets and initial code strings are identical. Passing ``TIMING_FUZZ=N`` relaxes this constraint by allowing the character locations to differ by up to ``N``, as long as the total number of characters and initial code strings continue to match. This is useful when there are small changes to a file, and you want to match later lines that have not changed even though the character offsets have changed. .. note:: By default the table picks up real times, under the assumption that when comparing line-by-line, the real time is a more accurate representation as it includes disk time and time spent in the native compiler. Passing ``TIMING_REAL=0`` to ``make`` will use user times rather than real times in the table. .. example:: For example, running ``print-pretty-single-time-diff`` might give a table like this: :: After | Code | Before || Change | % Change --------------------------------------------------------------------------------------------------- 0m00.50s | Total | 0m04.17s || -0m03.66s | -87.96% --------------------------------------------------------------------------------------------------- 0m00.145s | Chars 069 - 162 [Definition~foo0~:=~Eval~comp~i...] | 0m00.192s || -0m00.04s | -24.47% 0m00.126s | Chars 000 - 026 [Require~Stdlib.ZArith.BinInt.] | 0m00.143s || -0m00.01s | -11.88% N/A | Chars 027 - 068 [Declare~Reduction~comp~:=~nati...] | 0m00.s || +0m00.00s | N/A 0m00.s | Chars 027 - 068 [Declare~Reduction~comp~:=~vm_c...] | N/A || +0m00.00s | N/A 0m00.231s | Chars 163 - 208 [Definition~foo1~:=~Eval~comp~i...] | 0m03.836s || -0m03.60s | -93.97% + ``all.timing.diff``, ``path/to/file.v.timing.diff`` The ``path/to/file.v.timing.diff`` target will make a ``.v.timing.diff`` file for the corresponding ``.v`` file, with a table as would be generated by the ``print-pretty-single-time-diff`` target; it depends on having already made the corresponding ``.v.before-timing`` and ``.v.after-timing`` files, which can be made by passing ``TIMING=before`` and ``TIMING=after``. The ``all.timing.diff`` target will make such timing difference files for all of the ``.v`` files that the ``Makefile`` knows about. It will fail if some ``.v.before-timing`` or ``.v.after-timing`` files don’t exist. .. note:: This target requires python to build the table. + ``PROFILING=1`` passing this variable or setting it in the environment will cause ``make`` to use ``rocq c -profile`` to write to a ``.vo.prof.json`` file for each ``.v`` file compiled, which contains :ref:`profiling` information. The ``.vo.prof.json`` is then compressed by ``gzip`` to a ``.vo.prof.json.gz``. Building a subset of the targets with ``-j`` ++++++++++++++++++++++++++++++++++++++++++++ To build, say, two targets foo.vo and bar.vo in parallel one can use ``make only TGTS="foo.vo bar.vo" -j`` or ``make foo.vo bar.vo``. Precompiling for ``native_compute`` +++++++++++++++++++++++++++++++++++ To compile files for ``native_compute``, one can use the ``-native-compiler yes`` option of Rocq, by putting it in the ``_CoqProject`` file. The generated installation target of ``rocq makefile`` will then take care of installing the extra ``.coq-native`` directories. .. note:: As an alternative to modifying ``_CoqProject``, one can set an environment variable when calling ``make``: :: COQEXTRAFLAGS="-native-compiler yes" make This can be useful when files cannot be modified, for instance when installing via OPAM a package built with ``rocq makefile``: :: COQEXTRAFLAGS="-native-compiler yes" opam install coq-package .. note:: This requires all dependencies to be themselves compiled with ``-native-compiler yes``. The grammar of _CoqProject ++++++++++++++++++++++++++ A ``_CoqProject`` file encodes a list of strings using the following syntax: .. prodn:: CoqProject ::= {* {| @blank | @comment | @quoted_string | @unquoted_string } } blank ::= {| space | horizontal_tab | newline } comment ::= # {* comment_char } newline quoted_string ::= " {* quoted_char } " unquoted_string ::= string_start_char {* unquoted_char } where the following definitions apply: * :n:`space`, :n:`horizontal_tab` and :n:`newline` stand for the corresponding ASCII characters. * :n:`comment_char` is the set of all characters except :n:`newline`. * :n:`quoted_char` is the set of all characters except ``"``. * :n:`string_start_char` is the set of all characters except those that match :n:`@blank`, or are ``"`` or ``#``. * :n:`unquoted_char` is the set of all characters except those that match :n:`@blank` or are ``#``. The parser produces a list of strings in the same order as they were encountered in ``_CoqProject``. Blanks and comments are removed and the double quotes of :n:`@quoted_string` tokens are removed as well. The list is then treated as a list of command-line arguments of ``rocq makefile``. The semantics of ``-arg`` are as follows: the string given as argument is split on whitespace, but single quotes prevent splitting. The resulting list of strings is then passed to `rocq compile`. The current approach has a few limitations: Double quotes in a ``_CoqProject`` file are only special characters at the start of a string. For lack of an escaping mechanism, it is currently impossible to pass the following kinds of strings to ``rocq makefile`` using a ``_CoqProject`` file: * strings starting with ``"`` * strings starting with ``#`` and containing ``"`` * strings containing both whitespace and ``"`` In addition, it is impossible to pass strings containing ``'`` to `rocq compile` via ``-arg``. .. _building_dune: Building a Rocq project with Dune --------------------------------- Dune, the standard OCaml build tool, has supported building Rocq libraries since version 1.9. .. note:: Dune's Rocq support is still experimental; we strongly recommend using Dune 3.2 or later. .. note:: The canonical documentation for the Rocq Dune extension is maintained upstream; please refer to the `Dune manual `_ for up-to-date information. The documentation below is up to date for Dune 3.2 Building a Rocq project with Dune requires setting up a Dune project for your files. This involves adding a ``dune-project`` and ``pkg.opam`` file to the root (``pkg.opam`` can be empty or generated by Dune itself), and then providing ``dune`` files in the directories your ``.v`` files are placed. For the experimental version "0.3" of the Coq Dune language, Rocq library stanzas look like: .. code:: scheme (coq.theory (name ) (package ) (synopsis ) (modules ) (libraries ) (flags )) This stanza will build all `.v` files in the given directory, wrapping the library under ````. If you declare an ````, an ``.install`` file for the library will be generated; the optional ``(modules )`` field allows you to filter the list of modules, and ``(libraries )`` allows the Rocq theory depend on ML plugins. For the moment, Dune relies on Rocq's standard mechanisms (such as ``ROCQPATH``) to locate installed Rocq libraries. By default Dune will skip ``.v`` files present in subdirectories. In order to enable the usual recursive organization of Rocq projects add .. code:: scheme (include_subdirs qualified) to your ``dune`` file. Once your project is set up, `dune build` will generate the `pkg.install` files and all the files necessary for the installation of your project. Note that projects using Dune to build need to use the compatibility syntax for `Declare ML Module`, see example below: .. example:: A typical stanza for a Rocq plugin is split into two parts. An OCaml build directive, which is standard Dune: .. code:: scheme (library (name equations_plugin) (public_name equations.plugin) (flags :standard -warn-error -3-9-27-32-33-50) (libraries coq.plugins.cc coq.plugins.extraction)) (coq.pp (modules g_equations)) And a Rocq-specific part that depends on it via the ``libraries`` field: .. code:: scheme (coq.theory (name Equations) ; -R flag (package equations) (synopsis "Equations Plugin") (libraries coq.plugins.extraction equations.plugin) (modules :standard \ IdDec NoCycle)) ; exclude some modules that don't build (include_subdirs qualified) For now, each ``.v`` file that loads the plugin must use the following special syntax on its `Declare ML Module` command for compatibility with current Dune versions (as of Coq 8.16): .. code:: coq Declare ML Module "equations_plugin:equations.plugin". .. _rocqdep: rocq dep: Computing Module dependencies --------------------------------------- In order to compute module dependencies (to be used by ``make`` or ``dune``), Rocq provides the ``rocq dep`` tool. ``rocq dep`` computes inter-module dependencies for Rocq programs, and prints the dependencies on the standard output in a format readable by make. When a directory is given as argument, it is recursively looked at. Dependencies of Rocq modules are computed by looking at :cmd:`Require` and :cmd:`Declare ML Module` commands. See the man page of ``rocq dep`` for more details and options. Both Dune and ``rocq makefile`` use ``rocq dep`` to compute the dependencies among the files part of a Rocq project. .. _rocqnative: Split compilation of native computation files --------------------------------------------- Rocq features a :tacn:`native_compute` tactic to provide fast computation in the kernel. This process performs compilation of Rocq terms to OCaml programs using the OCaml compiler, which may cause an important overhead. Hence native compilation is an opt-in configure flag. When native compilation is activated, Rocq generates the compiled files upfront, i.e. during the ``rocq compile`` invocation on the corresponding ``.v`` file. This is impractical because it means one must chose in advance whether they will use a native-capable Rocq installation. In particular, activating native compilation forces the recompilation of the whole Rocq installation. See :ref:`command line options ` for more details. A command ``rocq native-precompile`` is available. It allows performing split native compilation by generating the native compute files out of the compiled ``.vo`` file rather than out of the source ``.v`` file. The ``rocq native-precompile`` command takes a name *file.vo* as argument and tries to perform native compilation on it. It assumes that the Rocq libraries on which *file.vo* depends have been first compiled to their native files, and will fail otherwise. It accepts the ``-R``, ``-Q``, ``-I`` and ``-nI`` arguments with the same semantics as if the native compilation process had been performed through ``rocq compile``. In particular, it means that: + ``-R`` and ``-Q`` are equivalent + ``-I`` is a no-op that is accepted only for scripting convenience Using Rocq as a library ------------------------ It is possible to build custom Rocq executables - for example for better debugging or custom static linking. The preferred method is to use ``dune``: :: (executable (name my_toplevel) (libraries rocq-runtime.toplevel)) in a directory with `my_toplevel.ml` containing the main loop entry point `Coqc.main()` or `Coqtop.(start_coq coqtop_toplevel)` (depending on if you want `rocq compile` or `rocq repl` behaviour). For example, to statically link |Ltac|, you can do: :: (executable (name my_toplevel) (libraries rocq-runtime.toplevel rocq-runtime.plugins.ltac)) and similarly for other plugins. Embedded Rocq phrases inside |Latex| documents ----------------------------------------------- When writing documentation about a proof development, one may want to insert Rocq phrases inside a |Latex| document, possibly together with the corresponding answers of the system. We provide a mechanical way to process such Rocq phrases embedded in |Latex| files: the ``rocq tex`` filter. This filter extracts Rocq phrases embedded in |Latex| files, evaluates them, and insert the outcome of the evaluation after each phrase. Starting with a file ``file.tex`` containing Rocq phrases, the ``rocq tex`` filter produces a file named ``file.v.tex`` with the Rocq outcome. There are options to produce the Rocq parts in smaller font, italic, between horizontal rules, etc. See the man page of ``rocq tex`` for more details. Man pages --------- There are man pages for the commands ``rocq dep`` and ``rocq tex``. Man pages are installed at installation time (see installation instructions in file ``INSTALL``, step 6). rocq-9.2.0/doc/sphinx/proof-engine/000077500000000000000000000000001516144147600171455ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/proof-engine/ltac.rst000066400000000000000000002567421516144147600206420ustar00rootroot00000000000000.. _ltac: Ltac ==== .. note:: Writing automation using Ltac is discouraged. Many alternatives are available as part of the Rocq standard library or the `Coq Platform `_, and some demonstration of their respective power is performed in the `metaprogramming Rosetta stone project `_. The official alternative to Ltac is :ref:`ltac2`. While Ltac is not going away anytime soon, we would like to strongly encourage users to use Ltac2 (or other alternatives) instead of Ltac for new projects and new automation code in existing projects. Reports about hindrances in using Ltac2 for writing automation are welcome as issues on the `Rocq bug tracker `_ or as discussions on the `Ltac2 Zulip stream `_. This chapter documents the tactic language |Ltac|. We start by giving the syntax followed by the informal semantics. To learn more about the language and especially about its foundations, please refer to :cite:`Del00`. (Note the examples in the paper won't work as-is; Rocq has evolved since the paper was written.) .. example:: Basic tactic macros Here are some examples of simple tactic macros you can create with |Ltac|: .. rocqdoc:: Ltac reduce_and_try_to_solve := simpl; intros; auto. Ltac destruct_bool_and_rewrite b H1 H2 := destruct b; [ rewrite H1; eauto | rewrite H2; eauto ]. See Section :ref:`ltac-examples` for more advanced examples. .. _ltac_defects: Defects ------- The |Ltac| tactic language is probably one of the ingredients of the success of Rocq, yet it is at the same time its Achilles' heel. Indeed, |Ltac|: - has often unclear semantics - is very non-uniform due to organic growth - lacks expressivity (data structures, combinators, types, ...) - is slow - is error-prone and fragile - has an intricate implementation Following the need of users who are developing huge projects relying critically on Ltac, we believe that we should offer a proper modern language that features at least the following: - at least informal, predictable semantics - a type system - standard programming facilities (e.g., datatypes) This new language, called Ltac2, is described in the :ref:`ltac2` chapter. We encourage users to start testing it, especially wherever an advanced tactic language is needed. .. _ltac-syntax: Syntax ------ The syntax of the tactic language is given below. The main entry of the grammar is :n:`@ltac_expr`, which is used in proof mode as well as to define new tactics with the :cmd:`Ltac` command. The grammar uses multiple :n:`ltac_expr*` nonterminals to express how subexpressions are grouped when they're not fully parenthesized. For example, in many programming languages, `a*b+c` is interpreted as `(a*b)+c` because `*` has higher precedence than `+`. Usually `a/b/c` is given the :gdef:`left associative` interpretation `(a/b)/c` rather than the :gdef:`right associative` interpretation `a/(b/c)`. In Rocq, the expression :n:`try repeat @tactic__1 || @tactic__2; @tactic__3; @tactic__4` is interpreted as :n:`(try (repeat (@tactic__1 || @tactic__2)); @tactic__3); @tactic__4` because `||` is part of :token:`ltac_expr2`, which has higher precedence than :tacn:`try` and :tacn:`repeat` (at the level of :token:`ltac_expr3`), which in turn have higher precedence than `;`, which is part of :token:`ltac_expr4`. (A *lower* number in the nonterminal name means *higher* precedence in this grammar.) .. insertprodn ltac_expr tactic_atom .. prodn:: ltac_expr ::= @ltac_expr4 ltac_expr4 ::= @ltac_expr4 ; @ltac_expr3 | @ltac_expr4 ; [ @for_each_goal ] | @ltac_expr3 ltac_expr3 ::= @l3_tactic | @ltac_expr2 ltac_expr2 ::= @ltac_expr1 + @ltac_expr2 | @ltac_expr1 %|| @ltac_expr2 | @l2_tactic | @ltac_expr1 ltac_expr1 ::= @tactic_value | @qualid {+ @tactic_arg } | @l1_tactic | @ltac_expr0 tactic_value ::= {| @value_tactic | @syn_value } tactic_arg ::= @tactic_value | @term | () ltac_expr0 ::= ( @ltac_expr ) | [> @for_each_goal ] | @tactic_atom tactic_atom ::= @integer | @qualid | () .. todo For the moment, I've left the language constructs like +, || and ; unchanged in the grammar. Not sure what to do with them. If we just make these indirections I think the grammar no longer gives you an overall idea of the concrete grammar without following the hyperlinks for many terms--not so easy (e.g. I have a construct and I want to figure out which productions generate it so I can read about them). We should think about eventually having a cheat sheet for the constructs, perhaps as part of the chapter introduction (use case: I know there's a construct but I can't remember its syntax). They do show up in the index but they're not so easy to find. I had thought a little about putting an ltac expression cheat sheet at the top of the tactics index. Unconventional, but people would see it and remember how to find it. OTOH, as you rightly note, they are not really tactics. Looking for better ideas that we are OK with. .. note:: Tactics described in other chapters of the documentation are :production:`simple_tactic`\s, which only modify the proof state. |Ltac| provides additional constructs that can generally be used wherever a :token:`simple_tactic` can appear, even though they don't modify the proof state and that syntactically they're at varying levels in :token:`ltac_expr`. For simplicity of presentation, the |Ltac| constructs are documented as tactics. Tactics are grouped as follows: - :production:`l3_tactic`\s include |Ltac| tactics: :tacn:`try`, :tacn:`do`, :tacn:`repeat`, :tacn:`timeout`, :tacn:`time`, :tacn:`progress`, :tacn:`once`, :tacn:`exactly_once`, :tacn:`only` and :tacn:`abstract` - :production:`l2_tactic`\s are: :tacn:`tryif` - :production:`l1_tactic`\s are: :tacn:`fun` and :tacn:`let`, the :token:`simple_tactic`\s, :tacn:`first`, :tacn:`solve`, :tacn:`idtac`, :tacn:`fail` and :tacn:`gfail` as well as :tacn:`match`, :tacn:`match goal` and their :n:`lazymatch` and :n:`multimatch` variants. - :production:`value_tactic`\s, which return values rather than change the proof state. They are: :tacn:`eval`, :tacn:`context`, :tacn:`numgoals`, :tacn:`fresh`, :tacn:`type of` and :tacn:`type_term`. The documentation for these |Ltac| constructs mentions which group they belong to. The difference is only relevant in some compound tactics where extra parentheses may be needed. For example, parentheses are required in :n:`idtac + (once idtac)` because :tacn:`once` is an :token:`l3_tactic`, which the production :n:`@ltac_expr2 ::= @ltac_expr1 + @ltac_expr2` doesn't accept after the `+`. .. note:: - The grammar reserves the token ``||``. .. todo For the compound tactics, review all the descriptions of evaluation vs application, backtracking, etc. to get the language consistent and simple (refactoring so the common elements are described in one place) Values ------ An |Ltac| value can be an integer, string, unit (written as "`()`" ), syntactic value or tactic. Syntactic values correspond to certain nonterminal symbols in the grammar, each of which is a distinct type of value. Most commonly, the value of an |Ltac| expression is a tactic that can be executed. While there are a number of constructs that let you combine multiple tactics into compound tactics, there are no operations for combining most other types of values. For example, there's no function to add two integers. Syntactic values are entered with the :token:`syn_value` construct. Values of all types can be assigned to toplevel symbols with the :cmd:`Ltac` command or to local symbols with the :tacn:`let` tactic. |Ltac| :tacn:`functions` can return values of any type. Syntactic values ~~~~~~~~~~~~~~~~ .. insertprodn syn_value syn_value .. prodn:: syn_value ::= @ident : ( @nonterminal ) Provides a way to use the syntax and semantics of a grammar nonterminal as a value in an :token:`ltac_expr`. The table below describes the most useful of these. You can see the others by running ":cmd:`Print Grammar` `tactic`" and examining the part at the end under "Entry tactic:tactic_value". :token:`ident` name of a grammar nonterminal listed in the table :production:`nonterminal` represents syntax described by :token:`nonterminal`. .. list-table:: :header-rows: 1 * - Specified :token:`ident` - Parsed as - Interpreted as - as in tactic * - ``ident`` - :token:`ident` - a user-specified name - :tacn:`intro` * - ``string`` - :token:`string` - a string - * - ``integer`` - :token:`integer` - an integer - * - ``reference`` - :token:`qualid` - a qualified identifier - * - ``uconstr`` - :token:`term` - an untyped term - :tacn:`refine` * - ``open_constr`` - :token:`term` - a term allowing unresolved evars - :tacn:`refine` * - ``constr`` - :token:`term` - a term - :tacn:`exact` * - ``ltac`` - :token:`ltac_expr` - a tactic - :n:`ltac:(@ltac_expr)` can be used to indicate that the parenthesized item should be interpreted as a tactic and not as a term. The constructs can also be used to pass parameters to tactics written in OCaml. (While all of the :token:`syn_value`\s can appear at the beginning of an :token:`ltac_expr`, the others are not useful because they will not evaluate to tactics.) :n:`uconstr:(@term)` can be used to build untyped terms. Terms built in |Ltac| are well-typed by default. Untyped terms built using :n:`uconstr:(…)` can be used as arguments to the :tacn:`refine` tactic, for example. In that case the untyped term is type checked against the conclusion of the goal, and the holes which are not solved by the typing procedure are turned into new subgoals. If instead the term was built with `open_constr` before being passed to `refine`, it would first be type checked without a type constraint, then coerced to the type of the goal. This may lead to different (usually worse) unifications. Building large terms in recursive |Ltac| functions may give very slow behavior because terms built with `constr` (the default for terms passed as arguments to tactics) must be fully traversed at each step, producing performance quadratic in the size of the term. In such cases, using `uconstr` or `open_constr` may avoid most of the repetitive type checking for the term, improving performance. Substitution ~~~~~~~~~~~~ .. todo next paragraph: we need a better discussion of substitution. Looks like that also applies to binder_tactics in some form. See https://github.com/rocq-prover/rocq/pull/12103#discussion_r422105218 :token:`name`\s within |Ltac| expressions are used to represent both terms and |Ltac| variables. If the :token:`name` corresponds to an |Ltac| variable or tactic name, |Ltac| substitutes the value before applying the expression. Generally it's best to choose distinctive names for |Ltac| variables that won't clash with term names. You can use :n:`ltac:(@name)` or :n:`(@name)` to control whether a :token:`name` is interpreted as, respectively, an |Ltac| variable or a term. Note that values from toplevel symbols, unlike locally-defined symbols, are substituted only when they appear at the beginning of an :token:`ltac_expr` or as a :token:`tactic_arg`. Local symbols are also substituted into tactics: .. example:: Substitution of global and local symbols .. rocqtop:: reset none Goal True. .. rocqtop:: all Ltac n := 1. let n2 := n in idtac n2. Fail idtac n. Local definitions: let ~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: let {? rec } @let_clause {* with @let_clause } in @ltac_expr .. insertprodn let_clause let_clause .. prodn:: let_clause ::= @name := @ltac_expr | @ident {+ @name } := @ltac_expr Binds symbols within :token:`ltac_expr`. :tacn:`let` evaluates each :n:`@let_clause`, substitutes the bound variables into :n:`@ltac_expr` and then evaluates :n:`@ltac_expr`. There are no dependencies between the :n:`@let_clause`\s. Use :tacn:`let` `rec` to create recursive or mutually recursive bindings, which causes the definitions to be evaluated lazily. :tacn:`let` is a :token:`l1_tactic`. Function construction and application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A parameterized tactic can be built anonymously (without resorting to local definitions) with: .. tacn:: fun {+ @name } => @ltac_expr Indeed, local definitions of functions are syntactic sugar for binding a :n:`fun` tactic to an identifier. :tacn:`fun` is a :token:`l1_tactic`. Functions can return values of any type. A function application is an expression of the form: .. tacn:: @qualid {+ @tactic_arg } :n:`@qualid` must be bound to a |Ltac| function with at least as many arguments as the provided :n:`@tactic_arg`\s. The :n:`@tactic_arg`\s are evaluated before the function is applied or partially applied. Functions may be defined with the :tacn:`fun` and :tacn:`let` tactics and with the :cmd:`Ltac` command. .. todo above: note "gobble" corner case https://github.com/rocq-prover/rocq/pull/12103#discussion_r436414417 Tactics in terms ~~~~~~~~~~~~~~~~ .. insertprodn term_ltac term_ltac .. prodn:: term_ltac ::= ltac : ( @ltac_expr ) Allows including an :token:`ltac_expr` within a term. Semantically, it's the same as the :token:`syn_value` for `ltac`, but these are distinct in the grammar. .. _goal-selectors: Goal selectors -------------- .. todo: mention this applies to Print commands and the Info command By default, tactic expressions are applied only to the first goal. Goal selectors provide a way to apply a tactic expression to another goal or multiple goals. (The :opt:`Default Goal Selector` option can be used to change the default behavior.) .. tacn:: @toplevel_selector : @ltac_expr :name: … : … (goal selector) .. insertprodn toplevel_selector toplevel_selector .. prodn:: toplevel_selector ::= @goal_selector | all | ! | par Reorders the goals and applies :token:`ltac_expr` to the selected goals. It can only be used at the top level of a tactic expression; it cannot be used within a tactic expression. The selected goals are reordered so they appear after the lowest-numbered selected goal, ordered by goal number. :ref:`Example `. If the selector applies to a single goal or to all goals, the reordering will not be apparent. The order of the goals in the :token:`goal_selector` is irrelevant. (This may not be what you expect; see `#8481 `_.) .. todo why shouldn't "all" and "!" be accepted anywhere a @goal_selector is accepted? It would be simpler to explain. `all` Selects all focused goals. `!` If exactly one goal is in focus, apply :token:`ltac_expr` to it. Otherwise the tactic fails. `par` Applies :n:`@ltac_expr` to all focused goals in parallel. The number of workers can be controlled via the command line option :n:`-async-proofs-tac-j @natural` to specify the desired number of workers. In the special case where :n:`@natural` is 0, this completely prevents Rocq from spawning any new process, and `par` blocks are treated as a variant of `all` that additionally checks that each subgoal is solved. Limitations: ``par:`` only works on goals that don't contain existential variables. :n:`@ltac_expr` must either solve the goal completely or do nothing (i.e. it cannot make some progress). Selectors can also be used nested within a tactic expression with the :tacn:`only` tactic: .. tacn:: only @goal_selector : @ltac_expr3 .. insertprodn goal_selector range_selector .. prodn:: goal_selector ::= {+, @range_selector } range_selector ::= @natural | [ @qualid ] | @natural - @natural Applies :token:`ltac_expr3` to the selected goals. (At the beginning of a sentence, use the form :n:`@goal_selector: @tactic` rather than :n:`only @goal_selector: @tactic`. In the latter, the :opt:`Default Goal Selector` (by default set to :n:`1:`) is applied before :n:`only` is interpreted. This is probably not what you want.) :tacn:`only` is an :token:`l3_tactic`. :n:`{+, @range_selector }` The selected goals are the union of the specified :token:`range_selector`\s. :n:`[ @qualid ]` Limits the application of :token:`ltac_expr3` to the goal named :token:`qualid` (see :ref:`existential-variables`). This works even when the goal is not in focus. :n:`@natural` Selects a single goal. :n:`@natural__1 - @natural__2` Selects the goals :n:`@natural__1` through :n:`@natural__2`, inclusive. .. exn:: No such goal. :name: No such goal. (Goal selector) :undocumented: .. exn:: Cannot simultaneously select shelved and unshelved goals. This error occurs if you try to select both shelved goals and focused goals in the same selector list, e.g. by doing :n:`1, [A]: @tactic` when `A` is shelved. To work around this error, first :cmd:`Unshelve` the desired goals. .. _reordering_goals_ex: .. example:: Selector reordering goals .. rocqtop:: reset in Goal 1=0 /\ 2=0 /\ 3=0. .. rocqtop:: all repeat split. 1,3: idtac. .. TODO change error message index entry Processing multiple goals ------------------------- When presented with multiple focused goals, most |Ltac| constructs process each goal separately. They succeed only if there is a success for each goal. For example: .. example:: Multiple focused goals This tactic fails because there no match for the second goal (`False`). .. rocqtop:: reset none fail Goal True /\ False. .. rocqtop:: out split. .. rocqtop:: all Fail all: let n := numgoals in idtac "numgoals =" n; match goal with | |- True => idtac end. .. _branching_and_backtracking: Branching and backtracking -------------------------- |Ltac| provides several :gdef:`branching` tactics that permit trying multiple alternative tactics for a proof step. For example, :tacn:`first`, which tries several alternatives and selects the first that succeeds, or :tacn:`tryif`, which tests whether a given tactic would succeed or fail if it was applied and then, depending on the result, applies one of two alternative tactics. There are also looping constructs :tacn:`do` and :tacn:`repeat`. The order in which the subparts of these tactics are evaluated is generally similar to structured programming constructs in many languages. The :tacn:`+<+ (backtracking branching)>`, :tacn:`multimatch` and :tacn:`multimatch goal` tactics provide more complex capability. Rather than applying a single successful tactic, these tactics generate a series of successful tactic alternatives that are tried sequentially when subsequent tactics outside these constructs fail. For example: .. example:: Backtracking .. rocqtop:: all Fail multimatch True with | True => idtac "branch 1" | _ => idtac "branch 2" end ; idtac "branch A"; fail. These constructs are evaluated using :gdef:`backtracking`. Each creates a :gdef:`backtracking point`. When a subsequent tactic fails, evaluation continues from the nearest prior backtracking point with the next successful alternative and repeats the tactics after the backtracking point. When a backtracking point has no more successful alternatives, evaluation continues from the next prior backtracking point. If there are no more prior backtracking points, the overall tactic fails. Thus, backtracking tactics can have multiple successes. Non-backtracking constructs that appear after a backtracking point are reprocessed after backtracking, as in the example above, in which the :tacn:`;` construct is reprocessed after backtracking. When a backtracking construct is within a non-backtracking construct, the latter uses the :gdef:`first success`. Backtracking to a point within a non-backtracking construct won't change the branch that was selected by the non-backtracking construct. The :tacn:`once` tactic stops further backtracking to backtracking points within that tactic. Control flow ------------ Sequence: ; ~~~~~~~~~~~ A sequence is an expression of the following form: .. tacn:: @ltac_expr4 ; @ltac_expr3 :name: ltac-seq .. todo: can't use "… ; …" as the name because of the semicolon The expression :n:`@ltac_expr4` is evaluated to :n:`v__1`, which must be a tactic value. The tactic :n:`v__1` is applied to the current goals, possibly producing more goals. Then the right-hand side is evaluated to produce :n:`v__2`, which must be a tactic value. The tactic :n:`v__2` is applied to all the goals produced by the prior application. This construct uses backtracking: if :n:`@ltac_expr3` fails, Rocq will try each alternative success (if any) for :n:`@ltac_expr4`, retrying :n:`@ltac_expr3` for each until both tactics succeed or all alternatives have failed. See :ref:`branching_and_backtracking`. .. todo I don't see the distinction between evaluating an ltac expression and applying it--how are they not the same thing? If different, the "Semantics" section above should explain it. See https://github.com/rocq-prover/rocq/pull/12103#discussion_r422210482 .. note:: - If you want :n:`@tactic__2; @tactic__3` to be fully applied to the first subgoal generated by :n:`@tactic__1` before applying it to the other subgoals, then you should write: - :n:`@tactic__1; [> @tactic__2; @tactic__3 .. ]` rather than - :n:`@tactic__1; (@tactic__2; @tactic__3)`. Do loop ~~~~~~~ .. tacn:: do @nat_or_var @ltac_expr3 The do loop repeats a tactic :token:`nat_or_var` times: :n:`@ltac_expr` is evaluated to ``v``, which must be a tactic value. This tactic value ``v`` is applied :token:`nat_or_var` times. If :token:`nat_or_var` > 1, after the first application of ``v``, ``v`` is applied, at least once, to the generated subgoals and so on. It fails if the application of ``v`` fails before :token:`nat_or_var` applications have been completed. :tacn:`do` is an :token:`l3_tactic`. Repeat loop ~~~~~~~~~~~ .. tacn:: repeat @ltac_expr3 The repeat loop repeats a tactic until it fails or doesn't change the proof context. :n:`@ltac_expr` is evaluated to ``v``. If ``v`` denotes a tactic, this tactic is applied to each focused goal independently. If the application succeeds, the tactic is applied recursively to all the generated subgoals until it eventually fails. The recursion stops in a subgoal when the tactic has failed *to make progress*. The tactic :tacn:`repeat` :n:`@ltac_expr` itself never fails. :tacn:`repeat` is an :token:`l3_tactic`. Catching errors: try ~~~~~~~~~~~~~~~~~~~~ We can catch the tactic errors with: .. tacn:: try @ltac_expr3 :n:`@ltac_expr` is evaluated to ``v`` which must be a tactic value. The tactic value ``v`` is applied to each focused goal independently. If the application of ``v`` fails in a goal, it catches the error and leaves the goal unchanged. If the level of the exception is positive, then the exception is re-raised with its level decremented. :tacn:`try` is an :token:`l3_tactic`. Conditional branching: tryif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: tryif @ltac_expr__test then @ltac_expr__then else @ltac_expr2__else For each focused goal, independently: Evaluate and apply :n:`@ltac_expr__test`. If :n:`@ltac_expr__test` succeeds at least once, evaluate and apply :n:`@ltac_expr__then` to all the subgoals generated by :n:`@ltac_expr__test`. Otherwise, evaluate and apply :n:`@ltac_expr2__else` to all the subgoals generated by :n:`@ltac_expr__test`. :tacn:`tryif` is an :token:`l2_tactic`. .. multigoal example - not sure it adds much Goal True /\ False. split; tryif match goal with | |- True => idtac "True" | |- False => idtac "False" end then idtac "then" else idtac "else". Alternatives ------------ Branching with backtracking: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We can branch with backtracking with the following structure: .. tacn:: @ltac_expr1 + @ltac_expr2 :name: + (backtracking branching) Evaluates and applies :n:`@ltac_expr1` to each focused goal independently. If it fails (i.e. there is no initial success), then evaluates and applies the right-hand side. If the right-hand side fails, the construct fails. If :n:`ltac_expr1` has an initial success and a subsequent tactic (outside the `+` construct) fails, |Ltac| backtracks and selects the next success for :n:`ltac_expr1`. If there are no more successes, then `+` similarly evaluates and applies (and backtracks in) the right-hand side. To prevent evaluation of further alternatives after an initial success for a tactic, use :tacn:`first` instead. In all cases, :n:`(@ltac_expr__1 + @ltac_expr__2); @ltac_expr__3` is equivalent to :n:`(@ltac_expr__1; @ltac_expr__3) + (@ltac_expr__2; @ltac_expr__3)`. Additionally, in most cases, :n:`(@ltac_expr__1 + @ltac_expr__2) + @ltac_expr__3` is equivalent to :n:`@ltac_expr__1 + (@ltac_expr__2 + @ltac_expr__3)`. Here's an example where the behavior differs slightly: .. rocqtop:: reset none Goal True. .. rocqtop:: all Fail (fail 2 + idtac 1) + idtac 2. Fail fail 2 + (idtac 1 + idtac 2). .. example:: Backtracking branching with + In the first tactic, `idtac "2"` is not executed. In the second, the subsequent `fail` causes backtracking and the execution of `idtac "B"`. .. rocqtop:: reset none Goal True. .. rocqtop:: all idtac "1" + idtac "2". assert_fails ((idtac "A" + idtac "B"); fail). Local application of tactics: [> ... ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: [> @for_each_goal ] :name: [> … | … | … ] (dispatch) .. insertprodn for_each_goal goal_tactics .. prodn:: for_each_goal ::= @goal_tactics | {? @goal_tactics %| } {? @ltac_expr } .. {? %| @goal_tactics } goal_tactics ::= {*| {? @ltac_expr } } Applies a different :n:`{? @ltac_expr }` to each of the focused goals. In the first form of :token:`for_each_goal` (without `..`), the construct fails if the number of specified :n:`{? @ltac_expr }` is not the same as the number of focused goals. Omitting an :n:`@ltac_expr` leaves the corresponding goal unchanged. In the second form (with :n:`{? @ltac_expr } ..`), the left and right :token:`goal_tactics` are applied respectively to a prefix or suffix of the list of focused goals. The :n:`{? @ltac_expr }` before the `..` is applied to any focused goals in the middle (possibly none) that are not covered by the :token:`goal_tactics`. The number of :n:`{? @ltac_expr }` in the :token:`goal_tactics` must be no more than the number of focused goals. In particular: :n:`@goal_tactics | .. | @goal_tactics` The goals not covered by the two :token:`goal_tactics` are left unchanged. :n:`[> @ltac_expr .. ]` :n:`@ltac_expr` is applied independently to each of the goals, rather than globally. In particular, if there are no goals, the tactic is not run at all. A tactic which expects multiple goals, such as :tacn:`swap`, would act as if a single goal is focused. Note that :n:`@ltac_expr3 ; [ {*| @ltac_expr} ]` is a convenient idiom to process the goals generated by applying :n:`@ltac_expr3`. .. tacn:: @ltac_expr4 ; [ @for_each_goal ] :name: [ … | … | … ] (dispatch) :n:`@ltac_expr4 ; [ ... ]` is equivalent to :n:`[> @ltac_expr4 ; [> ... ] .. ]`. .. todo see discussion of [ ... ] in https://github.com/rocq-prover/rocq/issues/12283 First tactic to succeed ~~~~~~~~~~~~~~~~~~~~~~~ In some cases backtracking may be too expensive. .. tacn:: first [ {*| @ltac_expr } ] first @ident :name: first; _ In the first form: for each focused goal, independently apply the first tactic (:token:`ltac_expr`) that succeeds. In the second form: :n:`@ident` represents a list of tactics passed to :n:`first` in a :cmd:`Tactic Notation` command (see example :ref:`here `). :tacn:`first` is an :token:`l1_tactic`. .. exn:: No applicable tactic. :undocumented: Failures in tactics won't cause backtracking. (To allow backtracking, use the :tacn:`+<+ (backtracking branching)>` construct above instead.) If the :tacn:`first` contains a tactic that can backtrack, "success" means the first success of that tactic. Consider the following: .. example:: Backtracking inside a non-backtracking construct .. rocqtop:: reset none Goal True. The :tacn:`fail` doesn't trigger the second :tacn:`idtac`: .. rocqtop:: all assert_fails (first [ idtac "1" | idtac "2" ]; fail). This backtracks within `(idtac "1A" + idtac "1B" + fail)` but :tacn:`first` won't consider the `idtac "2"` alternative: .. rocqtop:: all assert_fails (first [ (idtac "1A" + idtac "1B" + fail) | idtac "2" ]; fail). .. _taclist_in_first: .. example:: Referring to a list of tactics in :cmd:`Tactic Notation` This works similarly for the :tacn:`solve` tactic. .. rocqtop:: reset all Tactic Notation "myfirst" "[" tactic_list_sep(tacl,"|") "]" := first tacl. Goal True. myfirst [ auto | apply I ]. Solving ~~~~~~~ .. tacn:: solve [ {*| @ltac_expr__i } ] solve @ident :name: solve; _ In the first form: for each focused goal, independently apply the first tactic (:n:`@ltac_expr`) that solves the goal. In the second form: :n:`@ident` represents a list of tactics passed to :n:`solve` in a :cmd:`Tactic Notation` command (see example :ref:`here `). If any of the goals are not solved, then the overall :tacn:`solve` fails. :tacn:`solve` is an :token:`l1_tactic`. First tactic to make progress: || ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Yet another way of branching without backtracking is the following structure: .. tacn:: @ltac_expr1 %|| @ltac_expr2 :name: || (first tactic making progress) :n:`@ltac_expr1 || @ltac_expr2` is equivalent to :n:`first [ progress @ltac_expr1 | @ltac_expr2 ]`, except that if it fails, it fails like :n:`@ltac_expr2`. Detecting progress ~~~~~~~~~~~~~~~~~~ We can check if a tactic made progress with: .. tacn:: progress @ltac_expr3 :n:`@ltac_expr` is evaluated to ``v`` which must be a tactic value. The tactic value ``v`` is applied to each focused subgoal independently. If the application of ``v`` to one of the focused subgoal produced subgoals equal to the initial goals (up to syntactical equality), then an error of level 0 is raised. :tacn:`progress` is an :token:`l3_tactic`. .. exn:: Failed to progress. :undocumented: Success and failure ------------------- Checking for success: assert_succeeds ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rocq defines an |Ltac| tactic in `Init.Tactics` to check that a tactic has *at least one* success: .. tacn:: assert_succeeds @ltac_expr3 If :n:`@ltac_expr3` has at least one success, the proof state is unchanged and no message is printed. If :n:`@ltac_expr3` fails, the tactic fails with the same error. Checking for failure: assert_fails ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rocq defines an |Ltac| tactic in `Init.Tactics` to check that a tactic *fails*: .. tacn:: assert_fails @ltac_expr3 If :n:`@ltac_expr3` fails, the proof state is unchanged and no message is printed. If :n:`@ltac_expr3` unexpectedly has at least one success, the tactic performs a :tacn:`gfail` :n:`0`, printing the following message: .. exn:: Tactic failure: succeeds. :undocumented: .. note:: :tacn:`assert_fails` and :tacn:`assert_succeeds` work as described when :token:`ltac_expr3` is a :token:`simple_tactic`. In some more complex expressions, they may report an error from within :token:`ltac_expr3` when they shouldn't. This is due to the order in which parts of the :token:`ltac_expr3` are evaluated and executed. For example: .. rocqtop:: reset none Goal True. .. rocqtop:: all fail assert_fails match True with _ => fail end. should not show any message. The issue is that :tacn:`assert_fails` is an |Ltac|-defined tactic. That makes it a function that's processed in the evaluation phase, causing the :tacn:`match` to find its first success earlier. One workaround is to prefix :token:`ltac_expr3` with "`idtac;`". .. rocqtop:: all assert_fails (idtac; match True with _ => fail end). Alternatively, substituting the :tacn:`match` into the definition of :tacn:`assert_fails` works as expected: .. rocqtop:: all tryif (once match True with _ => fail end) then gfail 0 (* tac *) "succeeds" else idtac. Failing ~~~~~~~ .. tacn:: {| fail | gfail } {? @nat_or_var } {* {| @ident | @string | @natural } } :name: fail; gfail :tacn:`fail` is the always-failing tactic: it does not solve any goal. It is useful for defining other tactics since it can be caught by :tacn:`try`, :tacn:`repeat`, :tacn:`match goal`, or the branching tacticals. :tacn:`gfail` fails even when used after :n:`;` and there are no goals left. Similarly, :tacn:`gfail` fails even when used after ``all:`` and there are no goals left. :tacn:`fail` and :tacn:`gfail` are :token:`l1_tactic`\s. See the example for a comparison of the two constructs. Note that if Rocq terms have to be printed as part of the failure, term construction always forces the tactic into the goals, meaning that if there are no goals when it is evaluated, a tactic call like :tacn:`let` :n:`x := H in` :tacn:`fail` `0 x` will succeed. :n:`@nat_or_var` The failure level. If no level is specified, it defaults to 0. The level is used by :tacn:`try`, :tacn:`repeat`, :tacn:`match goal` and the branching tacticals. If 0, it makes :tacn:`match goal` consider the next clause (backtracking). If nonzero, the current :tacn:`match goal` block, :tacn:`try`, :tacn:`repeat`, or branching command is aborted and the level is decremented. In the case of :n:`+`, a nonzero level skips the first backtrack point, even if the call to :tacn:`fail` :n:`@natural` is not enclosed in a :n:`+` construct, respecting the algebraic identity. :n:`{* {| @ident | @string | @natural } }` The given tokens are used for printing the failure message. If :token:`ident` is an |Ltac| variable, its contents are printed; if not, it is an error. .. exn:: Tactic failure. :undocumented: .. exn:: Tactic failure (level @natural). :undocumented: .. exn:: No such goal. :name: No such goal. (fail) :undocumented: .. example:: .. todo the example is too long; could show the Goal True. Proof. once and hide the Aborts to shorten it. And add a line of text before each subexample. Perhaps add some very short explanations/generalizations (e.g. gfail always fails; "tac; fail" succeeds but "fail." alone fails. .. rocqtop:: reset all fail Goal True. Proof. fail. Abort. Goal True. Proof. trivial; fail. Qed. Goal True. Proof. trivial. fail. Abort. Goal True. Proof. trivial. all: fail. Qed. Goal True. Proof. gfail. Abort. Goal True. Proof. trivial; gfail. Abort. Goal True. Proof. trivial. gfail. Abort. Goal True. Proof. trivial. all: gfail. Abort. Soft cut: once ~~~~~~~~~~~~~~ .. todo Would like a different subsection title above. I have trouble distinguishing once and exactly_once. We need to explain backtracking somewhere. See https://github.com/rocq-prover/rocq/pull/12103#discussion_r422360181 Another way of restricting backtracking is to restrict a tactic to a single success: .. tacn:: once @ltac_expr3 :n:`@ltac_expr3` is evaluated to ``v`` which must be a tactic value. The tactic value ``v`` is applied but only its first success is used. If ``v`` fails, :tacn:`once` :n:`@ltac_expr3` fails like ``v``. If ``v`` has at least one success, :tacn:`once` :n:`@ltac_expr3` succeeds once, but cannot produce more successes. :tacn:`once` is an :token:`l3_tactic`. Checking for a single success: exactly_once ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rocq provides an experimental way to check that a tactic has *exactly one* success: .. tacn:: exactly_once @ltac_expr3 :n:`@ltac_expr3` is evaluated to ``v`` which must be a tactic value. The tactic value ``v`` is applied if it has at most one success. If ``v`` fails, :tacn:`exactly_once` :n:`@ltac_expr3` fails like ``v``. If ``v`` has a exactly one success, :tacn:`exactly_once` :n:`@ltac_expr3` succeeds like ``v``. If ``v`` has two or more successes, :tacn:`exactly_once` :n:`@ltac_expr3` fails. :tacn:`exactly_once` is an :token:`l3_tactic`. .. warning:: The experimental status of this tactic pertains to the fact if ``v`` has side effects, they may occur in an unpredictable way. Indeed, normally ``v`` would only be executed up to the first success until backtracking is needed, however :tacn:`exactly_once` needs to look ahead to see whether a second success exists, and may run further effects immediately. .. exn:: This tactic has more than one success. :undocumented: Manipulating values ------------------- Pattern matching on terms: match ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: @match_key @ltac_expr__term with {? %| } {+| @match_pattern => @ltac_expr } end :name: lazymatch; match; multimatch .. insertprodn match_key cpattern .. prodn:: match_key ::= lazymatch | match | multimatch match_pattern ::= @cpattern | context {? @ident } [ @cpattern ] cpattern ::= @term :tacn:`lazymatch`, :tacn:`match` and :tacn:`multimatch` are :token:`ltac_expr1`\s. Evaluates :n:`@ltac_expr__term`, which must yield a term, and matches it sequentially with the :token:`match_pattern`\s, which may have metavariables. When a match is found, metavariable values are substituted into :n:`@ltac_expr`, which is then applied. Matching may continue depending on whether `lazymatch`, `match` or `multimatch` is specified. In the :token:`match_pattern`\s, metavariables have the form :n:`?@ident`, whereas in the :n:`@ltac_expr`\s, the question mark is omitted. Choose your metavariable names with care to avoid name conflicts. For example, if you use the metavariable `S`, then the :token:`ltac_expr` can't use `S` to refer to the constructor of `nat` without qualifying the constructor as `Datatypes.S`. .. todo how does this differ from the 1-2 other unification routines elsewhere in Rocq? Does it use constr_eq or eq_constr_nounivs? Matching is non-linear: if a metavariable occurs more than once, each occurrence must match the same expression. Expressions match if they are syntactically equal or are :term:`Ξ±-convertible `. Matching is first-order except on variables of the form :n:`@?@ident` that occur in the head position of an application. For these variables, matching is second-order and returns a functional term. .. todo 30 May 20: the `@?ident` form is in dangling_pattern_extension_rule, not included in the doc yet maybe belongs with "Applications" `lazymatch` Causes the match to commit to the first matching branch rather than trying a new match if :n:`@ltac_expr` fails. :ref:`Example`. `match` If :n:`@ltac_expr` fails, continue matching with the next branch. Failures in subsequent tactics (after the `match`) will not cause selection of a new branch. Examples :ref:`here` and :ref:`here`. `multimatch` If :n:`@ltac_expr` fails, continue matching with the next branch. When an :n:`@ltac_expr` succeeds for a branch, subsequent failures (after the `multimatch`) causing consumption of all the successes of :n:`@ltac_expr` trigger selection of a new matching branch. :ref:`Example`. :tacn:`match` :n:`…` is, in fact, shorthand for :tacn:`once` :tacn:`multimatch` `…`. :n:`@cpattern` The syntax of :token:`cpattern` is the same as that of :token:`term`\s, but it can contain pattern matching metavariables in the form :n:`?@ident`. :g:`_` can be used to match irrelevant terms. :ref:`Example`. .. todo Didn't understand the following 2 paragraphs well enough to revise see https://github.com/rocq-prover/rocq/pull/12103#discussion_r436297754 for a possible example When a metavariable in the form :n:`?id` occurs under binders, say :n:`x__1, …, x__n` and the expression matches, the metavariable is instantiated by a term which can then be used in any context which also binds the variables :n:`x__1, …, x__n` with same types. This provides with a primitive form of matching under context which does not require manipulating a functional term. There is also a special notation for second-order pattern matching: in an applicative pattern of the form :n:`@?@ident @ident__1 … @ident__n`, the variable :token:`ident` matches any complex expression with (possible) dependencies in the variables :n:`@ident__i` and returns a functional term of the form :n:`fun @ident__1 … @ident__n => @term`. .. _match_term_context: :n:`context {? @ident } [ @cpattern ]` Matches any term with a subterm matching :token:`cpattern`. If there is a match and :n:`@ident` is present, it is assigned the "matched context", i.e. the initial term where the matched subterm is replaced by a hole. Note that `context` (with very similar syntax) appearing after the `=>` is the :tacn:`context` tactic. For :tacn:`match` and :tacn:`multimatch`, if the evaluation of the :token:`ltac_expr` fails, the next matching subterm is tried. If no further subterm matches, the next branch is tried. Matching subterms are considered from top to bottom and from left to right (with respect to the raw printing obtained by setting the :flag:`Printing All` flag). :ref:`Example`. .. todo There's a more realistic example from @JasonGross here: https://github.com/rocq-prover/rocq/pull/12103#discussion_r432996954 :n:`@ltac_expr` The tactic to apply if the construct matches. Metavariable values from the pattern match are substituted into :n:`@ltac_expr` before it's applied. Note that metavariables are not prefixed with the question mark as they are in :token:`cpattern`. If :token:`ltac_expr` evaluates to a tactic, then it is applied. If the tactic succeeds, the result of the match expression is :tacn:`idtac`. If :token:`ltac_expr` does not evaluate to a tactic, that value is the result of the match expression. If :n:`@ltac_expr` is a tactic with backtracking points, then subsequent failures after a :tacn:`lazymatch` or :tacn:`multimatch` (but not :tacn:`match`) can cause backtracking into :n:`@ltac_expr` to select its next success. (:tacn:`match` :n:`…` is equivalent to :tacn:`once` :tacn:`multimatch` `…`. The :tacn:`once` prevents backtracking into the :tacn:`match` after it has succeeded.) .. note:: Each |Ltac| construct is processed in two phases: an evaluation phase and an execution phase. In most cases, tactics that may change the proof state are applied in the second phase. (Tactics that generate integer, string or syntactic values, such as :tacn:`fresh`, are processed during the evaluation phase.) Unlike other tactics, `*match*` tactics get their first success (applying tactics to do so) as part of the evaluation phase. Among other things, this can affect how early failures are processed in :tacn:`assert_fails`. Please see the note in :tacn:`assert_fails`. .. exn:: Expression does not evaluate to a tactic. :n:`@ltac_expr` must evaluate to a tactic. .. exn:: No matching clauses for match. For at least one of the focused goals, there is no branch that matches its pattern *and* gets at least one success for :n:`@ltac_expr`. .. exn:: Argument of match does not evaluate to a term. This happens when :n:`@ltac_expr__term` does not denote a term. .. _match_vs_lazymatch_ex: .. example:: Comparison of lazymatch and match In :tacn:`lazymatch`, if :token:`ltac_expr` fails, the :tacn:`lazymatch` fails; it doesn't look for further matches. In :tacn:`match`, if :token:`ltac_expr` fails in a matching branch, it will try to match on subsequent branches. .. rocqtop:: reset none Goal True. .. rocqtop:: all Fail lazymatch True with | True => idtac "branch 1"; fail | _ => idtac "branch 2" end. .. rocqtop:: all match True with | True => idtac "branch 1"; fail | _ => idtac "branch 2" end. .. _match_vs_multimatch_ex: .. example:: Comparison of match and multimatch :tacn:`match` tactics are only evaluated once, whereas :tacn:`multimatch` tactics may be evaluated more than once if the following constructs trigger backtracking: .. rocqtop:: all Fail match True with | True => idtac "branch 1" | _ => idtac "branch 2" end ; idtac "branch A"; fail. .. rocqtop:: all Fail multimatch True with | True => idtac "branch 1" | _ => idtac "branch 2" end ; idtac "branch A"; fail. .. _match_with_holes_ex: .. example:: Matching a pattern with holes Notice the :tacn:`idtac` prints ``(z + 1)`` while the :tacn:`pose` substitutes ``(x + 1)``. .. rocqtop:: in reset Goal True. .. rocqtop:: all match constr:(fun x => (x + 1) * 3) with | fun z => ?y * 3 => idtac "y =" y; pose (fun z: nat => y * 5) end. .. _match_term_context_ex: .. example:: Multiple matches for a "context" pattern. Internally "x <> y" is represented as "(~ (x = y))", which produces the first match. .. rocqtop:: in reset Ltac f t := match t with | context [ (~ ?t) ] => idtac "?t = " t; fail | _ => idtac end. Goal True. .. rocqtop:: all f ((~ True) <> (~ False)). .. _ltac-match-goal: Pattern matching on goals and hypotheses: match goal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: @match_key {? reverse } goal with {? %| } {+| @goal_pattern => @ltac_expr } end :name: lazymatch goal; match goal; multimatch goal .. insertprodn goal_pattern match_hyp .. prodn:: goal_pattern ::= {*, @match_hyp } %|- @match_pattern | [ {*, @match_hyp } %|- @match_pattern ] | _ match_hyp ::= @name : @match_pattern | @name := @match_pattern | @name := [ @match_pattern ] : @match_pattern :tacn:`lazymatch goal`, :tacn:`match goal` and :tacn:`multimatch goal` are :token:`l1_tactic`\s. Use this form to match hypotheses and/or goals in the local context. These patterns have zero or more subpatterns to match hypotheses followed by a subpattern to match the conclusion. Except for the differences noted below, this works the same as the corresponding :n:`@match_key @ltac_expr` construct (see :tacn:`match`). Each current goal is processed independently. Matching is non-linear: if a metavariable occurs more than once, each occurrence must match the same expression. Within a single term, expressions match if they are syntactically equal or :term:`Ξ±-convertible `. When a metavariable is used across multiple hypotheses or across a hypothesis and the current goal, the expressions match if they are :term:`convertible`. :n:`{*, @match_hyp }` Patterns to match with hypotheses. Each pattern must match a distinct hypothesis in order for the branch to match. Hypotheses have the form :n:`@name {? := @term__binder } : @type`. Patterns bind each of these nonterminals separately: .. list-table:: :widths: 2 1 :header-rows: 1 * - Pattern syntax - Example pattern * - :n:`@name : @match_pattern__type` - `n : ?t` * - :n:`@name := @match_pattern__binder` - `n := ?b` * - :n:`@name := @term__binder : @type` - `n := ?b : ?t` * - :n:`@name := [ @match_pattern__binder ] : @match_pattern__type` - `n := [ ?b ] : ?t` .. :token:`name` can't have a `?`. Note that the last two forms are equivalent except that: - if the `:` in the third form has been bound to something else in a notation, you must use the fourth form. Note that :cmd:`Require Import` `ssreflect` loads a notation that does this. - a :n:`@term__binder` such as `[ ?l ]` (e.g., denoting a singleton list after :cmd:`Import` `ListNotations`) must be parenthesized or, for the fourth form, use double brackets: `[ [ ?l ] ]`. :n:`@term__binder`\s in the form `[?x ; ?y]` for a list are not parsed correctly. The workaround is to add parentheses or to use the underlying term instead of the notation, i.e. `(cons ?x ?y)`. If there are multiple :token:`match_hyp`\s in a branch, there may be multiple ways to match them to hypotheses. For :tacn:`match goal` and :tacn:`multimatch goal`, if the evaluation of the :token:`ltac_expr` fails, matching will continue with the next hypothesis combination. When those are exhausted, the next alternative from any `context` constructs in the :token:`match_pattern`\s is tried and then, when the context alternatives are exhausted, the next branch is tried. :ref:`Example`. `reverse` Hypothesis matching for :token:`match_hyp`\s normally begins by matching them from left to right, to hypotheses, last to first. Specifying `reverse` begins matching in the reverse order, from first to last. :ref:`Normal` and :ref:`reverse` examples. :n:`|- @match_pattern` A pattern to match with the current goal :n:`@goal_pattern with [ ... ]` The square brackets don't affect the semantics. They are permitted for aesthetics. .. exn:: No matching clauses for match goal. No clause succeeds, i.e. all matching patterns, if any, fail at the application of the :token:`ltac_expr`. Examples: .. _match_goal_hyps_ex: .. example:: Matching hypotheses Hypotheses are matched from the last hypothesis (which is by default the newest hypothesis) to the first until the :tacn:`apply` succeeds. .. rocqtop:: reset all Goal forall A B : Prop, A -> B -> (A->B). intros. match goal with | H : _ |- _ => idtac "apply " H; apply H end. .. _match_goal_hyps_rev_ex: .. example:: Matching hypotheses with reverse Hypotheses are matched from the first hypothesis to the last until the :tacn:`apply` succeeds. .. rocqtop:: reset all Goal forall A B : Prop, A -> B -> (A->B). intros. match reverse goal with | H : _ |- _ => idtac "apply " H; apply H end. .. _match_goal_multiple_hyps_ex: .. example:: Multiple ways to match hypotheses Every possible match for the hypotheses is evaluated until the right-hand side succeeds. Note that `H1` and `H2` are never matched to the same hypothesis. Observe that the number of permutations can grow as the factorial of the number of hypotheses and hypothesis patterns. .. rocqtop:: reset all Goal forall A B : Prop, A -> B -> (A->B). intros A B H. match goal with | H1 : _, H2 : _ |- _ => idtac "match " H1 H2; fail | _ => idtac end. .. todo need examples for: match_context_rule ::= [ {*, @match_hyp } |- @match_pattern ] => @ltac_expr match_hyp ::= | @name := {? [ @match_pattern ] : } @match_pattern .. todo The following items (up to numgoals) are part of "value_tactic". I'd like to make this a subsection and explain that they all return values. How do I get a 5th-level section title? Filling a term context ~~~~~~~~~~~~~~~~~~~~~~ The following expression is not a tactic in the sense that it does not produce subgoals but generates a term to be used in tactic expressions: .. tacn:: context @ident [ @term ] Returns the term matched with the `context` pattern (described :ref:`here`) substituting :token:`term` for the hole created by the pattern. :tacn:`context` is a :token:`value_tactic`. .. exn:: Not a context variable. :undocumented: .. exn:: Unbound context identifier @ident. :undocumented: .. example:: Substituting a matched context .. rocqtop:: reset all Goal True /\ True. match goal with | |- context G [True] => let x := context G [False] in idtac x end. Generating fresh hypothesis names ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tactics sometimes need to generate new names for hypothesis. Letting Rocq choose a name with the intro tactic is not so good since it is very awkward to retrieve that name. The following expression returns an identifier: .. tacn:: fresh {* {| @string | @qualid } } .. todo you can't have a :tacn: with the same name as a :gdef: for now, eg `fresh` can't be both Returns a fresh identifier name (i.e. one that is not already used in the local context and not previously returned by :tacn:`fresh` in the current :token:`ltac_expr`). The fresh identifier is formed by concatenating the final :token:`ident` of each :token:`qualid` (dropping any qualified components) and each specified :token:`string`. If the resulting name is already used, a number is appended to make it fresh. If no arguments are given, the name is a fresh derivative of the name ``H``. .. note:: We recommend generating the fresh identifier immediately before adding it to the local context. Using :tacn:`fresh` in a local function may not work as you expect: Successive calls to :tacn:`fresh` give distinct names even if the names haven't yet been added to the local context: .. rocqtop:: reset none Goal True -> True. .. rocqtop:: out intro x. .. rocqtop:: all let a := fresh "x" in let b := fresh "x" in idtac a b. When applying :tacn:`fresh` in a function, the name is chosen based on the tactic context at the point where the function was defined: .. rocqtop:: all let a := fresh "x" in let f := fun _ => fresh "x" in let c := f () in let d := f () in idtac a c d. :tacn:`fresh` is a :token:`value_tactic`. Computing in a term: eval ~~~~~~~~~~~~~~~~~~~~~~~~~ Evaluation of a term can be performed with: :n:`eval @red_expr in @term` See :tacn:`eval`. :tacn:`eval` is a :token:`value_tactic`. Getting the type of a term ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: type of @term This tactic returns the type of :token:`term`. :tacn:`type of` is a :token:`value_tactic`. Manipulating untyped terms: type_term ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :n:`uconstr : ( @term )` construct can be used to build an untyped term. See :token:`syn_value`. .. tacn:: type_term @one_term In |Ltac|, an untyped term can contain references to hypotheses or to |Ltac| variables containing typed or untyped terms. An untyped term can be type checked with :tacn:`type_term` whose argument is parsed as an untyped term and returns a well-typed term which can be used in tactics. :tacn:`type_term` is a :token:`value_tactic`. Counting goals: numgoals ~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: numgoals The number of goals under focus can be recovered using the :n:`numgoals` function. Combined with the :tacn:`guard` tactic below, it can be used to branch over the number of goals produced by previous tactics. :tacn:`numgoals` is a :token:`value_tactic`. .. example:: .. rocqtop:: reset in Ltac pr_numgoals := let n := numgoals in idtac "There are" n "goals". Goal True /\ True /\ True. split;[|split]. .. rocqtop:: all abort all:pr_numgoals. Testing boolean expressions: guard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: guard @int_or_var @comparison @int_or_var .. insertprodn int_or_var comparison .. prodn:: int_or_var ::= {| @integer | @ident } comparison ::= = | < | <= | > | >= Tests a boolean expression. If the expression evaluates to true, it succeeds without affecting the proof. The tactic fails if the expression is false. The accepted tests are simple integer comparisons. .. todo why doesn't it support = and <> as well? .. example:: guard .. rocqtop:: in Goal True /\ True /\ True. split;[|split]. .. rocqtop:: all all:let n:= numgoals in guard n<4. Fail all:let n:= numgoals in guard n=2. .. exn:: Condition not satisfied. :undocumented: Checking properties of terms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Each of the following tactics acts as the identity if the check succeeds, and results in an error otherwise. .. tacn:: constr_eq_strict @one_term @one_term Succeeds if the arguments are equal modulo alpha conversion and ignoring casts. Universes are considered equal when they are equal in the universe graph. .. exn:: Not equal. :undocumented: .. exn:: Not equal (due to universes). :undocumented: .. tacn:: constr_eq @one_term @one_term Like :tacn:`constr_eq_strict`, but may add constraints to make universes equal. .. tacn:: constr_eq_nounivs @one_term @one_term Like :tacn:`constr_eq_strict`, but all universes are considered equal. .. tacn:: convert @one_term @one_term Succeeds if the arguments are convertible, potentially adding universe constraints, and fails otherwise. .. tacn:: unify @one_term @one_term {? with @ident } Succeeds if the arguments are unifiable, potentially instantiating existential variables, and fails otherwise. :n:`@ident`, if specified, is the name of the :ref:`hint database ` that specifies which definitions are transparent. Otherwise, all definitions are considered transparent. Unification only expands transparent definitions while matching the two :n:`@one_term`\s. .. tacn:: is_evar @one_term Succeeds if :n:`@one_term` is an existential variable and otherwise fails. Existential variables are uninstantiated variables generated by :tacn:`eapply` and some other tactics. .. exn:: Not an evar. :undocumented: .. tacn:: not_evar @one_term :undocumented: .. tacn:: has_evar @one_term Succeeds if :n:`@one_term` has an existential variable as a subterm and fails otherwise. Unlike context patterns combined with ``is_evar``, this tactic scans all subterms, including those under binders. .. exn:: No evars. :undocumented: .. tacn:: is_ground @one_term The negation of :n:`has_evar @one_term`. Succeeds if :n:`@one_term` does not have an existential variable as a subterm and fails otherwise. .. exn:: Not ground. :undocumented: .. tacn:: is_var @one_term Succeeds if :n:`@one_term` is a variable or hypothesis in the current local context and fails otherwise. .. exn:: Not a variable or hypothesis. :undocumented: .. tacn:: is_const @one_term Succeeds if :n:`@one_term` is a global constant that is neither a (co)inductive type nor a constructor and fails otherwise. .. exn:: not a constant. :undocumented: .. tacn:: is_fix @one_term Succeeds if :n:`@one_term` is a `fix` construct (see :n:`@term_fix`) and fails otherwise. Fails for `let fix` forms. .. exn:: not a fix definition. :undocumented: .. example:: is_fix .. rocqtop:: reset in Goal True. is_fix (fix f (n : nat) := match n with S n => f n | O => O end). .. tacn:: is_cofix @one_term :undocumented: Succeeds if :n:`@one_term` is a `cofix` construct (see :n:`@term_cofix`) and fails otherwise. Fails for `let cofix` forms. .. exn:: not a cofix definition. :undocumented: .. example:: is_cofix .. rocqtop:: reset in CoInductive Stream (A : Type) : Type := Cons : A -> Stream A -> Stream A. Goal True. let c := constr:(cofix f : Stream unit := Cons _ tt f) in is_cofix c. .. tacn:: is_constructor @one_term Succeeds if :n:`@one_term` is the constructor of a (co)inductive type and fails otherwise. .. exn:: not a constructor. :undocumented: .. tacn:: is_ind @one_term Succeeds if :n:`@one_term` is a (co)inductive type (family) and fails otherwise. Note that `is_ind (list nat)` fails even though `is_ind list` succeeds, because `list nat` is an application. .. exn:: not an (co)inductive datatype. :undocumented: .. tacn:: is_proj @one_term Succeeds if :n:`@one_term` is a primitive projection applied to a record argument and fails otherwise. .. exn:: not a primitive projection. :undocumented: .. example:: is_proj .. rocqtop:: reset in Set Primitive Projections. Record Box {T : Type} := box { unbox : T }. Arguments box {_} _. Goal True. is_proj (unbox (box 0)). Timing ------ Timeout ~~~~~~~ We can force a tactic to stop if it has not finished after a certain amount of time: .. tacn:: timeout @nat_or_var @ltac_expr3 :n:`@ltac_expr3` is evaluated to ``v`` which must be a tactic value. The tactic value ``v`` is applied but only its first success is used (as with :tacn:`once`), and it is interrupted after :n:`@nat_or_var` seconds if it is still running. If it is interrupted the outcome is a failure. :tacn:`timeout` is an :token:`l3_tactic`. .. warning:: For the moment, timeout is based on elapsed time in seconds, which is very machine-dependent: a script that works on a quick machine may fail on a slow one. The converse is even possible if you combine a timeout with some other tacticals. This tactical is hence proposed only for convenience during debugging or other development phases, we strongly advise you to not leave any timeout in final scripts. Timing a tactic ~~~~~~~~~~~~~~~ A tactic execution can be timed: .. tacn:: time {? @string } @ltac_expr3 evaluates :n:`@ltac_expr3` and displays the running time of the tactic expression, whether it fails or succeeds. In case of several successes, the time for each successive run is displayed. Time is in seconds and is machine-dependent. The :n:`@string` argument is optional. When provided, it is used to identify this particular occurrence of :tacn:`time`. :tacn:`time` is an :token:`l3_tactic`. Timing a tactic that evaluates to a term: time_constr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tactic expressions that produce terms can be timed with the experimental tactic .. tacn:: time_constr @ltac_expr which evaluates :n:`@ltac_expr ()` and displays the time the tactic expression evaluated, assuming successful evaluation. Time is in seconds and is machine-dependent. This tactic currently does not support nesting, and will report times based on the innermost execution. This is due to the fact that it is implemented using the following internal tactics: .. tacn:: restart_timer {? @string } Reset a timer .. tacn:: finish_timing {? ( @string ) } {? @string } Display an optionally named timer. The parenthesized string argument is also optional, and determines the label associated with the timer for printing. By copying the definition of :tacn:`time_constr` from the standard library, users can achieve support for a fixed pattern of nesting by passing different :token:`string` parameters to :tacn:`restart_timer` and :tacn:`finish_timing` at each level of nesting. .. example:: .. rocqtop:: all reset abort Ltac time_constr1 tac := let eval_early := match goal with _ => restart_timer "(depth 1)" end in let ret := tac () in let eval_early := match goal with _ => finish_timing ( "Tactic evaluation" ) "(depth 1)" end in ret. Goal True. let v := time_constr ltac:(fun _ => let x := time_constr1 ltac:(fun _ => constr:(10 * 10)) in let y := time_constr1 ltac:(fun _ => eval compute in x) in y) in pose v. Print/identity tactic: idtac ---------------------------- .. tacn:: idtac {* {| @ident | @string | @natural } } Leaves the proof unchanged and prints the given tokens. :token:`String`\s and :token:`natural`\s are printed literally. If :token:`ident` is an |Ltac| variable, its contents are printed; if not, it is an error. :tacn:`idtac` is an :token:`l1_tactic`. Tactic toplevel definitions --------------------------- Defining |Ltac| symbols ~~~~~~~~~~~~~~~~~~~~~~~ |Ltac| toplevel definitions are made as follows: .. index:: ::= .. cmd:: Ltac @tacdef_body {* with @tacdef_body } .. insertprodn tacdef_body tacdef_body .. prodn:: tacdef_body ::= @qualid {* @name } {| := | ::= } @ltac_expr Defines or redefines an |Ltac| symbol. If the :attr:`local` attribute is specified, definitions will not be exported outside the current module and redefinitions only apply for the current module. :token:`qualid` Name of the symbol being defined or redefined. For definitions, :token:`qualid` must be a simple :token:`ident`. :n:`{* @name }` If specified, the symbol defines a function with the given parameter names. If no names are specified, :token:`qualid` is assigned the value of :token:`ltac_expr`. `:=` Defines a user-defined symbol, but gives an error if the symbol has already been defined. .. todo apparent inconsistency: "Ltac intros := idtac" seems like it redefines/hides an existing tactic, but in fact it creates a tactic which can only be called by its qualified name. This is true in general of tactic notations. The only way to override most primitive tactics, and any user-defined tactic notation, is with another tactic notation. .. exn:: There is already an Ltac named @qualid :undocumented: `::=` Redefines an existing user-defined symbol, but gives an error if the symbol doesn't exist. Note that :cmd:`Tactic Notation`\s do not count as user-defined tactics for `::=`. In sections or with :attr:`local`, the redefinition is forgotten at the end of the current module or section. :attr:`global` and :attr:`export` may be used with their standard meanings. Outside sections specifying no locality is equivalent to repeating the command with :attr:`global` and :attr:`export`. Redefinitions are incompatible with :n:`{* with @tacdef_body }`. .. exn:: There is no Ltac named @qualid :undocumented: :n:`{* with @tacdef_body }` Permits definition of mutually recursive tactics. .. note:: The following definitions are equivalent: - :n:`Ltac @qualid {+ @name } := @ltac_expr` - :n:`Ltac @qualid := fun {+ @name } => @ltac_expr` Printing |Ltac| tactics ~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Print Ltac @qualid Defined |Ltac| functions can be displayed using this command. .. cmd:: Print Ltac Signatures This command displays a list of all user-defined tactics, with their arguments. .. _ltac-examples: Examples of using |Ltac| ------------------------- Proof that the natural numbers have at least three elements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. example:: Proof that the natural numbers have at least three elements The first example shows how to use pattern matching over the proof context to prove that natural numbers have at least three elements. This can be done as follows: .. rocqtop:: reset all Lemma card_nat : ~ exists x y : nat, forall z:nat, x = z \/ y = z. Proof. intros (x & y & Hz). destruct (Hz 0), (Hz 1), (Hz 2). At this point, the :tacn:`congruence` tactic would finish the job: .. rocqtop:: all abort all: congruence. But for the purpose of the example, let's craft our own custom tactic to solve this: .. rocqtop:: none Lemma card_nat : ~ exists x y : nat, forall z:nat, x = z \/ y = z. Proof. intros (x & y & Hz). destruct (Hz 0), (Hz 1), (Hz 2). .. rocqtop:: all abort all: match goal with | _ : ?a = ?b, _ : ?a = ?c |- _ => assert (b = c) by now transitivity a end. all: discriminate. Notice that all the (very similar) cases coming from the three eliminations (with three distinct natural numbers) are successfully solved by a ``match goal`` structure and, in particular, with only one pattern (use of non-linear matching). Proving that a list is a permutation of a second list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. example:: Proving that a list is a permutation of a second list Let's first define the permutation predicate: .. rocqtop:: in reset Section Sort. Variable A : Set. Inductive perm : list A -> list A -> Prop := | perm_refl : forall l, perm l l | perm_cons : forall a l0 l1, perm l0 l1 -> perm (a :: l0) (a :: l1) | perm_append : forall a l, perm (a :: l) (l ++ a :: nil) | perm_trans : forall l0 l1 l2, perm l0 l1 -> perm l1 l2 -> perm l0 l2. End Sort. .. rocqtop:: none Require Import ListDef. Next we define an auxiliary tactic :g:`perm_aux` which takes an argument used to control the recursion depth. This tactic works as follows: If the lists are identical (i.e. convertible), it completes the proof. Otherwise, if the lists have identical heads, it looks at their tails. Finally, if the lists have different heads, it rotates the first list by putting its head at the end. Every time we perform a rotation, we decrement :g:`n`. When :g:`n` drops down to :g:`1`, we stop performing rotations and we fail. The idea is to give the length of the list as the initial value of :g:`n`. This way of counting the number of rotations will avoid going back to a head that had been considered before. From Section :ref:`ltac-syntax` we know that Ltac has a primitive notion of integers, but they are only used as arguments for primitive tactics and we cannot make computations with them. Thus, instead, we use Rocq's natural number type :g:`nat`. .. rocqtop:: in Ltac perm_aux n := match goal with | |- (perm _ ?l ?l) => apply perm_refl | |- (perm _ (?a :: ?l1) (?a :: ?l2)) => let newn := eval compute in (length l1) in (apply perm_cons; perm_aux newn) | |- (perm ?A (?a :: ?l1) ?l2) => match eval compute in n with | 1 => fail | _ => let l1' := constr:(l1 ++ a :: nil) in (apply (perm_trans A (a :: l1) l1' l2); [ apply perm_append | compute; perm_aux (pred n) ]) end end. The main tactic is :g:`solve_perm`. It computes the lengths of the two lists and uses them as arguments to call :g:`perm_aux` if the lengths are equal. (If they aren't, the lists cannot be permutations of each other.) .. rocqtop:: in Ltac solve_perm := match goal with | |- (perm _ ?l1 ?l2) => match eval compute in (length l1 = length l2) with | (?n = ?n) => perm_aux n end end. And now, here is how we can use the tactic :g:`solve_perm`: .. rocqtop:: out Goal perm nat (1 :: 2 :: 3 :: nil) (3 :: 2 :: 1 :: nil). .. rocqtop:: all abort solve_perm. .. rocqtop:: out Goal perm nat (0 :: 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: nil) (0 :: 2 :: 4 :: 6 :: 8 :: 9 :: 7 :: 5 :: 3 :: 1 :: nil). .. rocqtop:: all abort solve_perm. Deciding intuitionistic propositional logic ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Pattern matching on goals allows powerful backtracking when returning tactic values. An interesting application is the problem of deciding intuitionistic propositional logic. Considering the contraction-free sequent calculi LJT* of Roy Dyckhoff :cite:`Dyc92`, it is quite natural to code such a tactic using the tactic language as shown below. .. rocqtop:: in reset Ltac basic := match goal with | |- True => trivial | _ : False |- _ => contradiction | _ : ?A |- ?A => assumption end. .. rocqtop:: in Ltac simplify := repeat (intros; match goal with | H : ~ _ |- _ => red in H | H : _ /\ _ |- _ => elim H; do 2 intro; clear H | H : _ \/ _ |- _ => elim H; intro; clear H | H : ?A /\ ?B -> ?C |- _ => cut (A -> B -> C); [ intro; clear H | intros; apply H; split; assumption ] | H: ?A \/ ?B -> ?C |- _ => cut (B -> C); [ cut (A -> C); [ intros; clear H | intro; apply H; left; assumption ] | intro; apply H; right; assumption ] | H0 : ?A -> ?B, H1 : ?A |- _ => cut B; [ intro; clear H0 | apply H0; assumption ] | |- _ /\ _ => split | |- ~ _ => red end). .. rocqtop:: in Ltac my_tauto := simplify; basic || match goal with | H : (?A -> ?B) -> ?C |- _ => cut (B -> C); [ intro; cut (A -> B); [ intro; cut C; [ intro; clear H | apply H; assumption ] | clear H ] | intro; apply H; intro; assumption ]; my_tauto | H : ~ ?A -> ?B |- _ => cut (False -> B); [ intro; cut (A -> False); [ intro; cut B; [ intro; clear H | apply H; assumption ] | clear H ] | intro; apply H; red; intro; assumption ]; my_tauto | |- _ \/ _ => (left; my_tauto) || (right; my_tauto) end. The tactic ``basic`` tries to reason using simple rules involving truth, falsity and available assumptions. The tactic ``simplify`` applies all the reversible rules of Dyckhoff’s system. Finally, the tactic ``my_tauto`` (the main tactic to be called) simplifies with ``simplify``, tries to conclude with ``basic`` and tries several paths using the backtracking rules (one of the four Dyckhoff’s rules for the left implication to get rid of the contraction and the right ``or``). Having defined ``my_tauto``, we can prove tautologies like these: .. rocqtop:: in Lemma my_tauto_ex1 : forall A B : Prop, A /\ B -> A \/ B. Proof. my_tauto. Qed. .. rocqtop:: in Lemma my_tauto_ex2 : forall A B : Prop, (~ ~ B -> B) -> (A -> B) -> ~ ~ A -> B. Proof. my_tauto. Qed. Deciding type isomorphisms ~~~~~~~~~~~~~~~~~~~~~~~~~~ A trickier problem is to decide equalities between types modulo isomorphisms. Here, we choose to use the isomorphisms of the simply typed Ξ»-calculus with Cartesian product and unit type (see, for example, :cite:`RC95`). The axioms of this Ξ»-calculus are given below. .. rocqtop:: in reset Open Scope type_scope. .. rocqtop:: in Section Iso_axioms. .. rocqtop:: in Variables A B C : Set. .. rocqtop:: in Axiom Com : A * B = B * A. Axiom Ass : A * (B * C) = A * B * C. Axiom Cur : (A * B -> C) = (A -> B -> C). Axiom Dis : (A -> B * C) = (A -> B) * (A -> C). Axiom P_unit : A * unit = A. Axiom AR_unit : (A -> unit) = unit. Axiom AL_unit : (unit -> A) = A. .. rocqtop:: in Lemma Cons : B = C -> A * B = A * C. Proof. intro Heq; rewrite Heq; reflexivity. Qed. .. rocqtop:: in End Iso_axioms. .. rocqtop:: in Ltac simplify_type ty := match ty with | ?A * ?B * ?C => rewrite <- (Ass A B C); try simplify_type_eq | ?A * ?B -> ?C => rewrite (Cur A B C); try simplify_type_eq | ?A -> ?B * ?C => rewrite (Dis A B C); try simplify_type_eq | ?A * unit => rewrite (P_unit A); try simplify_type_eq | unit * ?B => rewrite (Com unit B); try simplify_type_eq | ?A -> unit => rewrite (AR_unit A); try simplify_type_eq | unit -> ?B => rewrite (AL_unit B); try simplify_type_eq | ?A * ?B => (simplify_type A; try simplify_type_eq) || (simplify_type B; try simplify_type_eq) | ?A -> ?B => (simplify_type A; try simplify_type_eq) || (simplify_type B; try simplify_type_eq) end with simplify_type_eq := match goal with | |- ?A = ?B => try simplify_type A; try simplify_type B end. .. rocqtop:: in Ltac len trm := match trm with | _ * ?B => let succ := len B in constr:(S succ) | _ => constr:(1) end. .. rocqtop:: in Ltac assoc := repeat rewrite <- Ass. .. rocqtop:: in Ltac solve_type_eq n := match goal with | |- ?A = ?A => reflexivity | |- ?A * ?B = ?A * ?C => apply Cons; let newn := len B in solve_type_eq newn | |- ?A * ?B = ?C => match eval compute in n with | 1 => fail | _ => pattern (A * B) at 1; rewrite Com; assoc; solve_type_eq (pred n) end end. .. rocqtop:: in Ltac compare_structure := match goal with | |- ?A = ?B => let l1 := len A with l2 := len B in match eval compute in (l1 = l2) with | ?n = ?n => solve_type_eq n end end. .. rocqtop:: in Ltac solve_iso := simplify_type_eq; compare_structure. The tactic to judge equalities modulo this axiomatization is shown above. The algorithm is quite simple. First types are simplified using axioms that can be oriented (this is done by ``simplify_type`` and ``simplify_type_eq``). The normal forms are sequences of Cartesian products without a Cartesian product in the left component. These normal forms are then compared modulo permutation of the components by the tactic ``compare_structure``. If they have the same length, the tactic ``solve_type_eq`` attempts to prove that the types are equal. The main tactic that puts all these components together is ``solve_iso``. Here are examples of what can be solved by ``solve_iso``. .. rocqtop:: in Lemma solve_iso_ex1 : forall A B : Set, A * unit * B = B * (unit * A). Proof. intros; solve_iso. Qed. .. rocqtop:: in Lemma solve_iso_ex2 : forall A B C : Set, (A * unit -> B * (C * unit)) = (A * unit -> (C -> unit) * C) * (unit -> A -> B). Proof. intros; solve_iso. Qed. Debugging |Ltac| tactics ------------------------ Backtraces ~~~~~~~~~~ .. flag:: Ltac Backtrace Setting this :term:`flag` displays a backtrace on Ltac failures that can be useful to find out what went wrong. It is disabled by default for performance reasons. Tracing execution ~~~~~~~~~~~~~~~~~ .. cmd:: Info @natural @ltac_expr Applies :token:`ltac_expr` and prints a trace of the tactics that were successfully applied, discarding branches that failed. :tacn:`idtac` tactics appear in the trace as comments containing the output. This command is valid only in proof mode. It accepts :ref:`goal-selectors`. The number :n:`@natural` is the unfolding level of tactics in the trace. At level 0, the trace contains a sequence of tactics in the actual script, at level 1, the trace will be the concatenation of the traces of these tactics, etc… .. example:: .. rocqtop:: in reset Ltac t x := exists x; reflexivity. Goal exists n, n=0. .. rocqtop:: all Info 0 t 1||t 0. .. rocqtop:: in Undo. .. rocqtop:: all Info 1 t 1||t 0. The trace produced by :cmd:`Info` tries its best to be a reparsable |Ltac| script, but this goal is not achievable in all generality. So some of the output traces will contain oddities. As an additional help for debugging, the trace produced by :cmd:`Info` contains (in comments) the messages produced by the :tacn:`idtac` tactical at the right position in the script. In particular, the calls to idtac in branches which failed are not printed. .. opt:: Info Level @natural This :term:`option` is an alternative to the :cmd:`Info` command. This will automatically print the same trace as :n:`Info @natural` at each tactic call. The unfolding level can be overridden by a call to the :cmd:`Info` command. .. _interactive-debugger: Interactive debugger ~~~~~~~~~~~~~~~~~~~~ .. flag:: Ltac Debug This flag, when set, enables the step-by-step debugger in the |Ltac| interpreter. The debugger is supported in `rocq repl` and Proof General by printing information on the console and accepting typed commands. In addition, RocqIDE now supports a :ref:`visual debugger ` with additional capabilities. When the debugger is activated in `rocq repl`, it stops at every step of the evaluation of the current |Ltac| expression and prints information on what it is doing. The debugger stops, prompting for a command which can be one of the following: +-----------------+-----------------------------------------------+ | newline | go to the next step | +-----------------+-----------------------------------------------+ | h | get help | +-----------------+-----------------------------------------------+ | r n | advance n steps further | +-----------------+-----------------------------------------------+ | r string | advance up to the next call to β€œidtac string” | +-----------------+-----------------------------------------------+ | s | continue current evaluation without stopping | +-----------------+-----------------------------------------------+ | x | exit current evaluation | +-----------------+-----------------------------------------------+ .. exn:: Debug mode not available in the IDE :undocumented: A non-interactive mode for the debugger is available via the flag: .. flag:: Ltac Batch Debug This flag has the effect of presenting a newline at every prompt, when the debugger is on in `rocq repl`. (It has no effect when running the RocqIDE debugger.) The debug log thus created, which does not require user input to generate when this flag is set, can then be run through external tools such as diff. .. todo: maybe drop Debug .. cmd:: Debug {| On | Off } Equivalent to :n:`Set Ltac Debug` or :n:`Unset Ltac Debug`. Profiling |Ltac| tactics ~~~~~~~~~~~~~~~~~~~~~~~~ It is possible to measure the time spent in invocations of primitive tactics as well as tactics defined in |Ltac| and their inner invocations. The primary use is the development of complex tactics, which can sometimes be so slow as to impede interactive usage. The reasons for the performance degradation can be intricate, like a slowly performing |Ltac| match or a sub-tactic whose performance only degrades in certain situations. The profiler generates a call tree and indicates the time spent in a tactic depending on its calling context. Thus it allows to locate the part of a tactic definition that contains the performance issue. .. flag:: Ltac Profiling This :term:`flag` enables and disables the profiler. .. opt:: Ltac Profiling Cutoff @string Reading the string as a floating point number, ltac profiles are printed without entries faster than the cutoff (in seconds). `2.0` by default. .. cmd:: Show Ltac Profile {? {| CutOff @integer | @string } } Prints the profile. :n:`CutOff @integer` By default, tactics that account for less than 2% of the total time are not displayed. `CutOff` lets you specify a different percentage. :n:`@string` Limits the profile to all tactics that start with :n:`@string`. Append a period (.) to the string if you only want exactly that name. .. cmd:: Reset Ltac Profile Resets the profile, that is, deletes all accumulated information. .. warning:: Backtracking across a :cmd:`Reset Ltac Profile` will not restore the information. The following example requires the Stdlib library to use the :tacn:`lia` tactic. .. rocqtop:: reset in extra-stdlib From Stdlib Require Import Lia. Ltac mytauto := tauto. Ltac tac := intros; repeat split; lia || mytauto. Abbreviation max x y := (x + (y - x)) (only parsing). Goal forall x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z, max x (max y z) = max (max x y) z /\ max x (max y z) = max (max x y) z /\ (A /\ B /\ C /\ D /\ E /\ F /\ G /\ H /\ I /\ J /\ K /\ L /\ M /\ N /\ O /\ P /\ Q /\ R /\ S /\ T /\ U /\ V /\ W /\ X /\ Y /\ Z -> Z /\ Y /\ X /\ W /\ V /\ U /\ T /\ S /\ R /\ Q /\ P /\ O /\ N /\ M /\ L /\ K /\ J /\ I /\ H /\ G /\ F /\ E /\ D /\ C /\ B /\ A). Proof. .. rocqtop:: all extra-stdlib Set Ltac Profiling. tac. Show Ltac Profile. Show Ltac Profile "lia". .. rocqtop:: in extra-stdlib Abort. Unset Ltac Profiling. .. tacn:: start ltac profiling This tactic behaves like :tacn:`idtac` but enables the profiler. .. tacn:: stop ltac profiling Similarly to :tacn:`start ltac profiling`, this tactic behaves like :tacn:`idtac`. Together, they allow you to exclude parts of a proof script from profiling. .. tacn:: reset ltac profile Equivalent to the :cmd:`Reset Ltac Profile` command, which allows resetting the profile from tactic scripts for benchmarking purposes. .. tacn:: show ltac profile {? {| cutoff @integer | @string } } Equivalent to the :cmd:`Show Ltac Profile` command, which allows displaying the profile from tactic scripts for benchmarking purposes. .. warn:: Ltac Profiler encountered an invalid stack (no \ self node). This can happen if you reset the profile during \ tactic execution Currently, :tacn:`reset ltac profile` is not very well-supported, as it clears all profiling information about all tactics, including ones above the current tactic. As a result, the profiler has trouble understanding where it is in tactic execution. This mixes especially poorly with backtracking into multi-success tactics. In general, non-top-level calls to :tacn:`reset ltac profile` should be avoided. You can also pass the ``-profile-ltac`` command line option to ``rocq compile``, which turns the :flag:`Ltac Profiling` flag on at the beginning of each document, and performs a :cmd:`Show Ltac Profile` at the end. Run-time optimization tactic ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tacn:: optimize_heap This tactic behaves like :tacn:`idtac`, except that running it compacts the heap in the OCaml run-time system. It is analogous to the :cmd:`Optimize Heap` command. .. cmd:: infoH @ltac_expr Used internally by Proof General. See `#12423 `_ for some background. rocq-9.2.0/doc/sphinx/proof-engine/ltac2.rst000066400000000000000000002266531516144147600207220ustar00rootroot00000000000000.. _ltac2: Ltac2 ===== .. _ltac2_design: General design -------------- Ltac2 is a tactics metalanguage for Rocq. It is mostly used to write new tactics using a mix of :cmd:`Ltac2` definitions and :cmd:`Ltac2 Notation`\s. Ltac2 provides an API in the various modules of the Ltac2 library, see `the relevant section of Corelib's documentation <../../corelib/index.html#Ltac2>`_. Ltac2 is designed to be as close as reasonably possible to Ltac1, while fixing its :ref:`defects `. In particular, Ltac2 is: - a member of the ML family of languages, i.e. * a call-by-value functional language * with effects * together with the Hindley-Milner type system - a language featuring meta-programming facilities for the manipulation of Rocq-side terms - a language featuring notation facilities to help write palatable scripts We describe these in more detail in the remainder of this document. ML component ------------ Overview ~~~~~~~~ Ltac2 is a member of the ML family of languages, in the sense that it is an effectful call-by-value functional language, with static typing Γ  la Hindley-Milner (see :cite:`MilnerPrincipalTypeSchemes`). It is commonly accepted that ML constitutes a sweet spot in PL design, as it is relatively expressive while not being either too lax (unlike dynamic typing) nor too strict (unlike, say, dependent types). The main goal of Ltac2 is to serve as a meta-language for Rocq. As such, it naturally fits in the ML lineage, just as the historical ML was designed as the tactic language for the LCF prover. It can also be seen as a general-purpose language, by simply forgetting about the Rocq-specific features. Sticking to a standard ML type system can be considered somewhat weak for a meta-language designed to manipulate Rocq terms. In particular, there is no way to statically guarantee that a Rocq term resulting from an Ltac2 computation will be well-typed. This is actually a design choice, motivated by backward compatibility with Ltac1. Instead, well-typedness is deferred to dynamic checks, allowing many primitive functions to fail whenever they are provided with an ill-typed term. The language is naturally effectful as it manipulates the global state of the proof engine. This allows to think of proof-modifying primitives as effects in a straightforward way. Semantically, proof manipulation lives in a monad, which allows to ensure that Ltac2 satisfies the same equations as a generic ML with unspecified effects would do, e.g. function reduction is substitution by a value. Use the following command to import Ltac2: .. rocqtop:: in From Ltac2 Require Import Ltac2. Type Syntax ~~~~~~~~~~~ At the level of terms, we simply elaborate on Ltac1 syntax, which is quite close to OCaml. Types follow the simply-typed syntax of OCaml. .. insertprodn ltac2_type ltac2_typevar .. prodn:: ltac2_type ::= @ltac2_type2 -> @ltac2_type | @ltac2_type2 ltac2_type2 ::= @ltac2_type1 * {+* @ltac2_type1 } | @ltac2_type1 ltac2_type1 ::= @ltac2_type1 @qualid | @ltac2_type0 ltac2_type0 ::= ( {+, @ltac2_type } ) {? @qualid } | @ltac2_typevar | _ | @qualid ltac2_typevar ::= ' @ident The set of base types can be extended thanks to the usual ML type declarations such as algebraic datatypes and records. Built-in types include: - ``int``, machine integers (size not specified, in practice inherited from OCaml) - ``string``, mutable strings - ``'a array``, mutable arrays - ``exn``, exceptions - ``constr``, kernel-side terms - ``pattern``, term patterns - ``ident``, well-formed identifiers Type declarations ~~~~~~~~~~~~~~~~~ One can define new types with the following commands. .. cmd:: Ltac2 Type {? rec } @tac2typ_def {* with @tac2typ_def } .. insertprodn tac2typ_def tac2rec_field .. prodn:: tac2typ_def ::= {? @tac2typ_prm } @qualid {? {| := | ::= } @tac2typ_knd } tac2typ_prm ::= @ltac2_typevar | ( {+, @ltac2_typevar } ) tac2typ_knd ::= @ltac2_type | [ {? {? %| } {+| @tac2alg_constructor } } ] | [ .. ] | %{ {? {+; @tac2rec_field } {? ; } } %} tac2alg_constructor ::= {* #[ {+, @attribute } ] } @ident | {* #[ {+, @attribute } ] } @ident ( {*, @ltac2_type } ) tac2rec_field ::= {? mutable } @ident : @ltac2_type :n:`:=` Defines a type with an explicit set of constructors :n:`::=` Extends an existing open variant type, a special kind of variant type whose constructors are not statically defined, but can instead be extended dynamically. A typical example is the standard `exn` type for exceptions. Pattern matching on open variants must always include a catch-all clause. They can be extended with this form, in which case :token:`tac2typ_knd` should be in the form :n:`[ {? {? %| } {+| @tac2alg_constructor } } ]`. Without :n:`{| := | ::= }` Defines an abstract type for use representing data from OCaml. Not for end users. :n:`with @tac2typ_def` Permits definition of mutually recursive type definitions. In :n:`@tac2alg_constructor`, :n:`attribute` supports :attr:`deprecated` (without `use`) and :attr:`warn`. Each production of :token:`tac2typ_knd` defines one of four possible kinds of definitions, respectively: alias, variant, open variant and record types. Aliases are names for a given type expression and are transparently unfoldable to that expression. They cannot be recursive. .. The non-terminal :token:`uident` designates identifiers starting with an uppercase. Variants are sum types defined by constructors and eliminated by pattern-matching. They can be recursive, but the `rec` flag must be explicitly set. Pattern matching must be exhaustive. Open variants can be extended with additional constructors using the `::=` form. Records are product types with named fields and eliminated by projection. Likewise they can be recursive if the `rec` flag is set. .. attr:: abstract :name: abstract Types declared with this attribute are made abstract at the end of the current module. This makes it possible to enforce invariants. .. example:: .. rocqtop:: in Module PositiveInt. #[abstract] Ltac2 Type t := int. Ltac2 make (x:int) : t := if Int.le 0 x then x else Control.throw (Invalid_argument None). Ltac2 get (x:t) : int := x. End PositiveInt. .. rocqtop:: all Ltac2 Eval PositiveInt.get (PositiveInt.make 3). Fail Ltac2 Eval PositiveInt.get (PositiveInt.make -1). .. cmd:: Ltac2 Import Type @qualid as @ident Declares :n:`@ident` as an alias of :n:`@qualid` (i.e. `Ltac2 Type @ident := @qualid`), and also makes its constructors or projections to have names accessible from the current module. .. cmd:: Ltac2 @ external @ident : @ltac2_type := @string__plugin @string__function :name: Ltac2 external Declares functions defined in OCaml. :n:`@string__plugin` is the plugin name defining the function. :n:`@string__function` is the internal name of the function. This command supports the :attr:`deprecated` attribute. APIs ~~~~ Ltac2 provides over 150 API functions that provide various capabilities. These are declared with :cmd:`Ltac2 external` in :n:`lib/coq/user-contrib/Ltac2/*.v`. For example, `Message.print` defined in `Message.v` is used to print messages: .. rocqtop:: none Goal True. .. rocqtop:: all abort Message.print (Message.of_string "fully qualified calls"). From Ltac2 Require Import Message. print (of_string "unqualified calls"). Term Syntax ~~~~~~~~~~~ The syntax of the functional fragment is very close to that of Ltac1, except that it adds a true pattern-matching feature, as well as a few standard constructs from ML. In practice, there is some additional syntactic sugar that allows the user to bind a variable and match on it at the same time, in the usual ML style. There is dedicated syntax for list and array literals. .. insertprodn ltac2_expr ltac2_atom .. prodn:: ltac2_expr ::= @ltac2_expr5 ; @ltac2_expr | @ltac2_expr5 ltac2_expr5 ::= fun {+ @tac2pat0 } {? : @ltac2_type } => @ltac2_expr | let {? rec } @ltac2_let_clause {* with @ltac2_let_clause } in @ltac2_expr | @ltac2_expr3 ltac2_let_clause ::= {+ @tac2pat0 } {? : @ltac2_type } := @ltac2_expr ltac2_expr3 ::= {+, @ltac2_expr2 } ltac2_expr2 ::= @ltac2_expr1 :: @ltac2_expr2 | @ltac2_expr1 ltac2_expr1 ::= @ltac2_expr1 {+ @ltac2_expr0 } | @ltac2_expr1 .( @qualid ) | @ltac2_expr1 .( @qualid ) := @ltac2_expr5 | @ltac2_expr0 tac2rec_fieldexpr ::= @qualid {? := @ltac2_expr1 } ltac2_expr0 ::= ( @ltac2_expr ) | ( @ltac2_expr : @ltac2_type ) | () | [ %| {*; @ltac2_expr5 } %| ] | [ {*; @ltac2_expr5 } ] | %{ @ltac2_expr0 with {? {+; @tac2rec_fieldexpr } {? ; } } %} | %{ {? {+; @tac2rec_fieldexpr } {? ; } } %} | @ltac2_atom tac2rec_fieldpats ::= @tac2rec_fieldpat ; {? @tac2rec_fieldpats } | @tac2rec_fieldpat ; | @tac2rec_fieldpat tac2rec_fieldpat ::= @qualid {? := @tac2pat3 } ltac2_atom ::= @integer | @string | @qualid | @ @ident | & @ident | ' @term | @ltac2_quotations The non-terminal :production:`lident` designates identifiers starting with a lowercase letter. :n:`'@term` is equivalent to :n:`open_constr:(@term)`. Use :n:`@ltac2_expr0 .( @qualid )` to access record fields and :n:`@ltac2_expr0 .( @qualid ) := @ltac2_expr5` to modify mutable record fields. Record expressions and patterns support "punning": in :n:`@tac2rec_fieldexpr` and :n:`@tac2rec_fieldpat`, omitting the optional part is equivalent to using :n:`:= @ident` where the identifier is the identifier part of the field name (i.e. the :n:`@qualid`). A record value can be built from another by changing only a subset of its fields with the syntax :n:`%{ @ltac2_expr0 with {? {+; @qualid := @ltac2_expr1 } {? ; } } %}`. Fields that are not explicitly assigned a value take their value from :n:`@ltac2_expr0`. Ltac2 Definitions ~~~~~~~~~~~~~~~~~ .. cmd:: Ltac2 {? mutable } {? rec } @tac2def_body {* with @tac2def_body } .. insertprodn tac2def_body tac2def_body .. prodn:: tac2def_body ::= {| _ | @ident } {* @tac2pat0 } {? : @ltac2_type } := @ltac2_expr This command defines a new global Ltac2 value. If one or more :token:`tac2pat0` are specified, the new value is a function. This is a shortcut for one of the :token:`ltac2_expr5` productions. For example: :n:`Ltac2 foo a b := …` is equivalent to :n:`Ltac2 foo := fun a b => …`. The body of an Ltac2 definition is required to be a syntactical value that is, a function, a constant, a pure constructor recursively applied to values or a (non-recursive) let binding of a value in a value. If ``rec`` is set, the tactic is expanded into a recursive binding. If ``mutable`` is set, the definition can be redefined at a later stage (see below). This command supports the :attr:`deprecated` attribute. .. cmd:: Ltac2 Set @qualid {? as @ident } := @ltac2_expr This command redefines a previous ``mutable`` definition. Mutable definitions act like dynamic binding, i.e. at runtime, the last defined value for this entry is chosen. This is useful for global flags and the like. The previous value of the binding can be optionally accessed using the `as` binding syntax. This command supports :term:`attributes ` :attr:`local`, :attr:`export` and :attr:`global`. By default it is `export` outside sections. Inside sections it is `local` and does not support `export` or `global`. .. example:: Dynamic nature of mutable cells .. rocqtop:: all Ltac2 mutable x := true. Ltac2 y () := x. Ltac2 Eval y (). Ltac2 Set x := false. Ltac2 Eval y (). .. example:: Interaction with recursive calls .. rocqtop:: all Ltac2 mutable rec f b := if b then 0 else f true. Ltac2 Set f := fun b => if b then 1 else f true. Ltac2 Eval (f false). Ltac2 Set f as oldf := fun b => if b then 2 else oldf false. Ltac2 Eval (f false). In the definition, the `f` in the body is resolved statically because the definition is marked recursive. It is equivalent to `Ltac2 mutable f x := let rec g b := if b then 0 else g true in g x` (alpha renaming the internal `f` to `g` to make the behavior clearer). In the first re-definition, the `f` in the body is resolved dynamically. This is witnessed by the second re-definition. Printing Ltac2 tactics ~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Print Ltac2 @qualid :cmd:`Print` can print defined Ltac2 tactics and can avoid printing other objects by using `Print Ltac2`. .. cmd:: Print Ltac2 Type @qualid Prints the definitions of ltac2 types. .. cmd:: Ltac2 Globalize @ltac2_expr Prints the result of resolving notations in the given expression. .. cmd:: Ltac2 Check @ltac2_expr Typechecks the given expression and prints the result. .. cmd:: Print Ltac2 Signatures This command displays a list of all defined tactics in scope with their types. Reduction ~~~~~~~~~ We use the usual ML call-by-value reduction, with an otherwise unspecified evaluation order. This is a design choice making it compatible with OCaml, if ever we implement native compilation. The expected equations are as follows:: (fun x => t) V ≑ t{x := V} (Ξ²v) let x := V in t ≑ t{x := V} (let) match C Vβ‚€ ... Vβ‚™ with ... | C xβ‚€ ... xβ‚™ => t | ... end ≑ t {xα΅’ := Vα΅’} (ΞΉ) (t any term, V values, C constructor) Note that call-by-value reduction is already a departure from Ltac1 which uses heuristics to decide when to evaluate an expression. For instance, the following expressions do not evaluate the same way in Ltac1. :n:`foo (idtac; let x := 0 in bar)` :n:`foo (let x := 0 in bar)` Instead of relying on the :n:`idtac` idiom, we would now require an explicit thunk to not compute the argument, and :n:`foo` would have e.g. type :n:`(unit -> unit) -> unit`. :n:`foo (fun () => let x := 0 in bar)` Typing ~~~~~~ Typing is strict and follows the Hindley-Milner system. Unlike Ltac1, there are no type casts at runtime, and one has to resort to conversion functions. See notations though to make things more palatable. In this setting, all the usual argument-free tactics have type :n:`unit -> unit`, but one can return a value of type :n:`t` thanks to terms of type :n:`unit -> t`, or take additional arguments. Effects ~~~~~~~ Effects in Ltac2 are straightforward, except that instead of using the standard IO monad as the ambient effectful world, Ltac2 has a tactic monad. Note that the order of evaluation of application is *not* specified and is implementation-dependent, as in OCaml. We recall that the `Proofview.tactic` monad is essentially a IO monad together with backtracking state representing the proof state. Intuitively a thunk of type :n:`unit -> 'a` can do the following: - It can perform non-backtracking IO like printing and setting mutable variables - It can fail in a non-recoverable way - It can use first-class backtracking. One way to think about this is that thunks are isomorphic to this type: :n:`(unit -> 'a) ~ (unit -> exn + ('a * (exn -> 'a)))` i.e. thunks can produce a lazy list of results where each tail is waiting for a continuation exception. - It can access a backtracking proof state, consisting among other things of the current evar assignment and the list of goals under focus. We now describe more thoroughly the various effects in Ltac2. Standard IO +++++++++++ The Ltac2 language features non-backtracking IO, notably mutable data and printing operations. Mutable fields of records and built-in types like `string` and `array` feature imperative assignment. See modules `String` and `Array` respectively. A few printing primitives are provided in the `Message` module for displaying information to the user. Fatal errors ++++++++++++ The Ltac2 language provides non-backtracking exceptions, also known as *panics*, through the following primitive in module `Control`:: val throw : exn -> 'a Unlike backtracking exceptions from the next section, this kind of error is never caught by backtracking primitives, that is, throwing an exception destroys the stack. This is codified by the following equation, where `E` is an evaluation context:: E[throw e] ≑ throw e (e value) There is currently no way to catch such an exception, which is a deliberate design choice. Eventually there might be a way to catch it and destroy all backtrack and return values. Backtracking ++++++++++++ Ltac2 models backtracking computations using streams of values: the head of a non-empty stream represent the first path of computation while its tail stands for the alternative paths of computation when backtracking occurs. The empty stream holding no values represent failure and initiates backtracking. Backtracking failures (empty streams) are moreover decorated with exceptions to inform the reason of failure. These exceptions are then passed to the tail of a non-empty backtracking computation. The following Ltac2 type summarizes the model for backtracking computations .. rocqtop:: in Ltac2 Type rec 'a backtracking_stream := [ EmptyStream(exn) (* backtracking failure holding an exception *) | ConsStream('a, (exn -> 'a backtracking_stream)) ] (* backtracking success *). where `ConsStream` is a backtracking success with a value of type `'a` as its head and a backtracking handler parameterized by an exception. When sequenced with additional backtracking computations, a backtracking success may lead to a failure with an exception that will be passed to the handler. In practice, the backtracking aspects of Ltac2's computations can be accessed through the following primitives, defined in the `Control` module:: Ltac2 Type 'a result := [ Val ('a) | Err (exn) ]. val zero : exn -> 'a val plus : (unit -> 'a) -> (exn -> 'a) -> 'a val case : (unit -> 'a) -> ('a * (exn -> 'a)) result Informally, the primitive `zero e` ends the current computation and returns to the last backtracking point with exception `e`. In the stream model, it corresponds to the empty stream. The primitive `plus t handler` installs a backtracking point around `t`, using `handler` to handle any exception raised by a `zero` while evaluating `t`. This corresponds to appending two streams in the stream model. Finally, the primitive `case t` inspects the backtracking structure of a thunked computation `t` and returns `Err e` if `t` yields `zero e`, or returns the first backtracking point as a pair `Val(v,h)` of a value `v` and a handler `h` if there is any. In the particular case where the computation `t ()` yields an immediate value `v`, `case t` returns a trivial backtracking point `Val(v, zero)`. In the stream model, `case` exposes one layer of the stream acting as pattern-matching. Using these three primitives, thunks of type `unit -> 'a` (corresponding to suspended computations of type `'a`) can be seen as `'a backtracking_stream` when considering only the backtracking effect: .. rocqtop:: in Ltac2 rec to_stream (t : unit -> 'a) : 'a backtracking_stream := match Control.case t with | Err e => EmptyStream e | Val (v, h) => ConsStream v (fun e => to_stream (fun () => h e)) end. Ltac2 rec from_stream (s : 'a backtracking_stream) : unit -> 'a := fun () => match s with | EmptyStream e => Control.zero e | ConsStream hd tl => Control.plus (fun () => hd) (fun e => from_stream (tl e) ()) end. The backtracking is first-class, i.e. one can write :n:`plus (fun () => "x") (fun _ => "y") : string` producing a backtracking string. .. example:: Behaviour of first class backtracking .. rocqtop:: all From Ltac2 Require Import Printf. (* `bs` holds a backtracking string *) Ltac2 bs () := Control.plus (fun () => "x") (fun _ => "y"). (* Prints the first branch "x" and terminates successfully. *) Ltac2 Eval (let s := bs () in printf "%s" s). (* Prints both branches and returns the error. *) Ltac2 print_and_fail (s : string) := printf "%s" s ; Control.zero (Tactic_failure None). Ltac2 Eval (Control.case (fun () => let s := bs () in print_and_fail s)). These operations are expected to satisfy a few equations, validated by the stream model, most notably that they form a monoid-like structure (skewed by exceptions) compatible with sequentialization:: plus t zero ≑ t () plus (fun () => zero e) f ≑ f e plus (plus t f) g ≑ plus t (fun e => plus (f e) g) case (fun () => zero e) ≑ Err e case (fun () => plus (fun () => t) f) ≑ Val (t,f) let x := zero e in u ≑ zero e let x := plus t f in u ≑ plus (fun () => let x := t in u) (fun e => let x := f e in u) (t, f, g, e values) The behaviour of `case` on immediate values can be recovered as `case (fun () => v) ≑ case (fun () => (fun () => v) ()) ≑ case (fun () => plus (fun () => v) zero) ≑ Val(v, zero)`. Goals +++++ A goal is given by the data of its conclusion and hypotheses, i.e. it can be represented as `[Ξ“ ⊒ A]`. The tactic monad naturally operates over the whole proofview, which may represent several goals, including none. Thus, there is no such thing as *the current goal*. Goals are naturally ordered, though. It is natural to do the same in Ltac2, but we must provide a way to get access to a given goal. This is the role of the `enter` primitive, which applies a tactic to each currently focused goal in turn:: val enter : (unit -> unit) -> unit It is guaranteed that when evaluating `enter f`, `f` is called with exactly one goal under focus. Note that `f` may be called several times, or never, depending on the number of goals under focus before the call to `enter`. Accessing the goal data is then implicit in the Ltac2 primitives, and may panic if the invariants are not respected. The two essential functions for observing goals are given below.:: val hyp : ident -> constr val goal : unit -> constr The two above functions panic if there is not exactly one goal under focus. In addition, `hyp` may also fail if there is no hypothesis with the corresponding name. Meta-programming ---------------- Overview ~~~~~~~~ One of the major implementation issues of Ltac1 is the fact that it is never clear whether an object refers to the object world or the meta-world. This is an incredible source of slowness, as the interpretation must be aware of bound variables and must use heuristics to decide whether a variable is a proper one or referring to something in the Ltac context. Likewise, in Ltac1, constr parsing is implicit, so that ``foo 0`` is not ``foo`` applied to the Ltac integer expression ``0`` (|Ltac| does have a notion of integers, though it is not first-class), but rather the Rocq term :g:`Datatypes.O`. The implicit parsing is confusing to users and often gives unexpected results. Ltac2 makes these explicit using quoting and unquoting notation, although there are notations to do it in a short and elegant way so as not to be too cumbersome to the user. Quotations ~~~~~~~~~~ .. _ltac2_built-in-quotations: Built-in quotations +++++++++++++++++++ .. insertprodn ltac2_quotations ltac1_expr_in_env .. prodn:: ltac2_quotations ::= ident : ( @ident ) | constr : ( @term ) | open_constr : ( @term ) | preterm : ( @term ) | pat : ( @cpattern ) | reference : ( {| & @ident | @qualid } ) | ltac1 : ( @ltac1_expr_in_env ) | ltac1val : ( @ltac1_expr_in_env ) ltac1_expr_in_env ::= @ltac_expr | {* @ident } %|- @ltac_expr The current implementation recognizes the following built-in quotations: - ``ident``, which parses identifiers (type ``Init.ident``). - ``constr``, which parses Rocq terms and produces an evar-free term at runtime (type ``Init.constr``). - ``open_constr``, which parses Rocq terms and produces a term potentially with holes at runtime (type ``Init.constr`` as well). - ``preterm``, which parses Rocq terms and produces a value which must be typechecked with ``Constr.pretype`` (type ``Init.preterm``). - ``pat``, which parses Rocq patterns and produces a pattern used for term matching (type ``Init.pattern``). - ``reference`` Qualified names are globalized at internalization into the corresponding global reference, while ``&id`` is turned into ``Std.VarRef id``. This produces at runtime a ``Std.reference``. - ``ltac1``, for calling Ltac1 code, described in :ref:`simple_api`. - ``ltac1val``, for manipulating Ltac1 values, described in :ref:`low_level_api`. The following syntactic sugar is provided for two common cases: - ``@id`` is the same as ``ident:(id)`` - :n:`'@term` is the same as :n:`open_constr:(@term)` Strict vs. non-strict mode ++++++++++++++++++++++++++ Depending on the context, quotation-producing terms (i.e. ``constr``, ``open_constr`` or ``preterm``) are not internalized in the same way. There are two possible modes, the *strict* and the *non-strict* mode. - In strict mode, all simple identifiers appearing in a term quotation are required to be resolvable statically. That is, they must be the short name of a declaration which is defined globally, excluding section variables and hypotheses. If this doesn't hold, internalization will fail. To work around this error, one has to specifically use the ``&`` notation. - In non-strict mode, any simple identifier appearing in a term quotation which is not bound in the global environment is turned into a dynamic reference to a hypothesis. That is to say, internalization will succeed, but the evaluation of the term at runtime will fail if there is no such variable in the dynamic context. Strict mode is enforced by default, such as for all Ltac2 definitions. Non-strict mode is only set when evaluating Ltac2 snippets in interactive proof mode. The rationale is that it is cumbersome to explicitly add ``&`` interactively, while it is expected that global tactics enforce more invariants on their code. .. _term-antiquotations: Term Antiquotations ~~~~~~~~~~~~~~~~~~~ Syntax ++++++ One can also insert Ltac2 code into Rocq terms, similar to what is possible in Ltac1. .. prodn:: term += ltac2:( @ltac2_expr ) Antiquoted terms are expected to have type ``unit``, as they are only evaluated for their side-effects. Semantics +++++++++ A quoted Rocq term is interpreted in two phases, internalization and evaluation. - Internalization is part of the static semantics, that is, it is done at Ltac2 typing time. - Evaluation is part of the dynamic semantics, that is, it is done when a term gets effectively computed by Ltac2. Note that typing of Rocq terms is a *dynamic* process occurring at Ltac2 evaluation time, and not at Ltac2 typing time. Static semantics **************** During internalization, Rocq variables are resolved and antiquotations are type checked as Ltac2 terms, effectively producing a ``glob_constr`` in Rocq implementation terminology. Note that although it went through the type checking of **Ltac2**, the resulting term has not been fully computed and is potentially ill-typed as a runtime **Rocq** term. .. example:: The following term is valid (with type `unit -> constr`), but will fail at runtime: .. rocqtop:: in Ltac2 myconstr () := constr:(nat -> 0). Term antiquotations are type checked in the enclosing Ltac2 typing context of the corresponding term expression. .. example:: The following will type check, with type `constr`. .. rocqdoc:: let x := '0 in constr:(1 + ltac2:(exact $x)) Beware that the typing environment of antiquotations is **not** expanded by the Rocq binders from the term. .. example:: The following Ltac2 expression will **not** type check:: `constr:(fun x : nat => ltac2:(exact $x))` `(* Error: Unbound variable 'x' *)` There is a simple reason for that, which is that the following expression would not make sense in general. `constr:(fun x : nat => ltac2:(clear @x; exact x))` Indeed, a hypothesis can suddenly disappear from the runtime context if some other tactic pulls the rug from under you. Rather, the tactic writer has to resort to the **dynamic** goal environment, and must write instead explicitly that she is accessing a hypothesis, typically as follows. `constr:(fun x : nat => ltac2:(exact (hyp @x)))` This pattern is so common that we provide dedicated Ltac2 and Rocq term notations for it. - `&x` as an Ltac2 expression expands to `hyp @x`. - `&x` as a Rocq constr expression expands to `ltac2:(Control.refine (fun () => hyp @x))`. In the special case where Ltac2 antiquotations appear inside a Rocq term notation, the notation variables are systematically bound in the body of the tactic expression with type `Ltac2.Init.preterm`. Such a type represents untyped syntactic Rocq expressions, which can by typed in the current context using the `Ltac2.Constr.pretype` function. .. example:: The following notation is essentially the identity. .. rocqtop:: in Notation "[ x ]" := ltac2:(let x := Ltac2.Constr.pretype x in exact $x) (only parsing). Dynamic semantics ***************** During evaluation, a quoted term is fully evaluated to a kernel term, and is in particular type checked in the current environment. Evaluation of a quoted term goes as follows. - The quoted term is first evaluated by the pretyper. - Antiquotations are then evaluated in a context where there is exactly one goal under focus, with the hypotheses coming from the current environment extended with the bound variables of the term, and the resulting term is fed into the quoted term. Relative orders of evaluation of antiquotations and quoted term are not specified. For instance, in the following example, `tac` will be evaluated in a context with exactly one goal under focus, whose last hypothesis is `H : nat`. The whole expression will thus evaluate to the term :g:`fun H : nat => H`. `let tac () := hyp @H in constr:(fun H : nat => ltac2:(tac ()))` Many standard tactics perform type checking of their argument before going further. It is your duty to ensure that terms are well-typed when calling such tactics. Failure to do so will result in non-recoverable exceptions. **Trivial Term Antiquotations** It is possible to refer to a variable of type `constr` in the Ltac2 environment through a specific syntax consistent with the antiquotations presented in the notation section. .. prodn:: term += $@lident or equivalently .. prodn:: term += $constr:@lident In a Rocq term, writing :g:`$x` is semantically equivalent to :g:`ltac2:(Control.refine (fun () => x))`, up to re-typechecking. It allows to insert in a concise way an Ltac2 variable of type :n:`constr` into a Rocq term. Similarly variables of type `preterm` have an antiquotation .. prodn:: term += $preterm:@lident It is equivalent to pretyping the preterm with the appropriate typing constraint. Variables of type `ident` have an antiquotation .. prodn:: term += $preterm:@lident interpreting the ident as an hypothesis. This is for dynamically-named hypotheses where `&` is for statically-named hypotheses, in other words `let x := @y in constr:($hyp:x)` is equivalent to `constr:(&y)`. Variables of type `pattern` have an antiquotation .. prodn:: term += $pattern:@lident Its use is only allowed when producing a pattern, i.e. `pattern:($pattern:x -> True)` is allowed but `constr:($pattern:x -> True)` is not allowed. Conversely `constr` and `preterm` antiquotations are not allowed when producing a pattern. Match over terms ~~~~~~~~~~~~~~~~ Ltac2 features a construction similar to Ltac1 :tacn:`match` over terms, although in a less hard-wired way. .. tacn:: @ltac2_match_key @ltac2_expr__term with @ltac2_match_list end :name: lazy_match!; match!; multi_match! .. insertprodn ltac2_match_key ltac2_match_pattern .. prodn:: ltac2_match_key ::= lazy_match! | match! | multi_match! ltac2_match_list ::= {? %| } {+| @ltac2_match_rule } ltac2_match_rule ::= @ltac2_match_pattern => @ltac2_expr ltac2_match_pattern ::= @cpattern | context {? @ident } [ @cpattern ] Evaluates :n:`@ltac2_expr__term`, which must yield a term, and matches it sequentially with the :token:`ltac2_match_pattern`\s, which may contain metavariables. When a match is found, metavariable values are substituted into :n:`@ltac2_expr`, which is then applied. Matching may continue depending on whether `lazy_match!`, `match!` or `multi_match!` is specified. In the :token:`ltac2_match_pattern`\s, metavariables have the form :n:`?@ident`, whereas in the :n:`@ltac2_expr`\s, the question mark is omitted. .. todo how does this differ from the 1-2 other unification routines elsewhere in Rocq? Matching is non-linear: if a metavariable occurs more than once, each occurrence must match the same expression. Expressions match if they are syntactically equal or are :term:`Ξ±-convertible `. Matching is first-order except on variables of the form :n:`@?@ident` that occur in the head position of an application. For these variables, matching is second-order and returns a functional term. .. todo the `@?ident` form is in dangling_pattern_extension_rule, not included in the doc yet maybe belongs with "Applications" `lazy_match!` Causes the match to commit to the first matching branch rather than trying a new match if :n:`@ltac2_expr` fails. :ref:`Example`. `match!` If :n:`@ltac2_expr` fails, continue matching with the next branch. Failures in subsequent tactics (after the `match!`) will not cause selection of a new branch. Examples :ref:`here` and :ref:`here`. `multi_match!` If :n:`@ltac2_expr` fails, continue matching with the next branch. When a :n:`@ltac2_expr` succeeds for a branch, subsequent failures (after the `multi_match!`) causing consumption of all the successes of :n:`@ltac2_expr` trigger selection of a new matching branch. :ref:`Example`. :n:`@cpattern` The syntax of :token:`cpattern` is the same as that of :token:`term`\s, but it can contain pattern matching metavariables in the form :n:`?@ident` and :n:`@?@ident`. :g:`_` can be used to match irrelevant terms. .. todo more on @?@ident here: https://github.com/rocq-prover/rocq/pull/12085#discussion_r467504046 .. todo Example is broken :ref:`Example`. .. todo Didn't understand the following 2 paragraphs well enough to revise see https://github.com/rocq-prover/rocq/pull/12103#discussion_r436297754 for a possible example Unlike Ltac1, Ltac2 :n:`?id` metavariables only match closed terms. There is also a special notation for second-order pattern matching: in an applicative pattern of the form :n:`@?@ident @ident__1 … @ident__n`, the variable :token:`ident` matches any complex expression with (possible) dependencies in the variables :n:`@ident__i` and returns a functional term of the form :n:`fun @ident__1 … @ident__n => @term`. :n:`context {? @ident } [ @cpattern ]` Matches any term with a subterm matching :token:`cpattern`. If there is a match and :n:`@ident` is present, it is assigned the "matched context", i.e. the initial term where the matched subterm is replaced by a hole. This hole in the matched context can be filled with the expression :n:`Pattern.instantiate @ident @cpattern`. For :tacn:`match!` and :tacn:`multi_match!`, if the evaluation of the :token:`ltac2_expr` fails, the next matching subterm is tried. If no further subterm matches, the next branch is tried. Matching subterms are considered from top to bottom and from left to right (with respect to the raw printing obtained by setting the :flag:`Printing All` flag). :ref:`Example`. .. todo There's a more realistic example from @JasonGross here: https://github.com/rocq-prover/rocq/pull/12103#discussion_r432996954 :n:`@ltac2_expr` The tactic to apply if the construct matches. Metavariable values from the pattern match are statically bound as Ltac2 variables in :n:`@ltac2_expr` before it is applied. If :n:`@ltac2_expr` is a tactic with backtracking points, then subsequent failures after a :tacn:`lazy_match!` or :tacn:`multi_match!` (but not :tacn:`match!`) can cause backtracking into :n:`@ltac2_expr` to select its next success. Variables from the :n:`@tac2pat1` are statically bound in the body of the branch. Variables from the :n:`@term` pattern have values of type `constr`. Variables from the :n:`@ident` in the `context` construct have values of type `Pattern.context` (defined in `Pattern.v`). Note that unlike Ltac1, only lowercase identifiers are valid as Ltac2 bindings. Ltac2 will report an error if one of the bound variables starts with an uppercase character. The semantics of this construction are otherwise the same as the corresponding one from Ltac1, except that it requires the goal to be focused. .. _ltac2_match_vs_lazymatch_ex: .. example:: Ltac2 Comparison of lazy_match! and match! (Equivalent to this :ref:`Ltac1 example`.) These lines define a `msg` tactic that's used in several examples as a more-succinct alternative to `print (of_string "...")`: .. rocqtop:: in From Ltac2 Require Import Message. Ltac2 msg x := print (of_string x). .. rocqtop:: none Goal True. In :tacn:`lazy_match!`, if :token:`ltac2_expr` fails, the :tacn:`lazy_match!` fails; it doesn't look for further matches. In :tacn:`match!`, if :token:`ltac2_expr` fails in a matching branch, it will try to match on subsequent branches. Note that :n:`'@term` below is equivalent to :n:`open_constr:(@term)`. .. rocqtop:: all Fail lazy_match! 'True with | True => msg "branch 1"; fail | _ => msg "branch 2" end. match! 'True with | True => msg "branch 1"; fail | _ => msg "branch 2" end. .. _ltac2_match_vs_multimatch_ex: .. example:: Ltac2 Comparison of match! and multi_match! (Equivalent to this :ref:`Ltac1 example`.) :tacn:`match!` tactics are only evaluated once, whereas :tacn:`multi_match!` tactics may be evaluated more than once if the following constructs trigger backtracking: .. rocqtop:: all Fail match! 'True with | True => msg "branch 1" | _ => msg "branch 2" end ; msg "branch A"; fail. .. rocqtop:: all Fail multi_match! 'True with | True => msg "branch 1" | _ => msg "branch 2" end ; msg "branch A"; fail. .. _ltac2_match_with_holes_ex: .. todo EXAMPLE DOESN'T WORK: Ltac2 does not (yet?) handle pattern variables matching open terms. Matching a pattern with holes (Equivalent to this :ref:`Ltac1 example`.) Notice the :tacn:`idtac` prints ``(z + 1)`` while the :tacn:`pose` substitutes ``(x + 1)``. .. rocqtop:: all match! constr:(fun x => (x + 1) * 3) with | fun z => ?y * 3 => print (of_constr y); pose (fun z: nat => $y * 5) end. .. _ltac2_match_term_context_ex: .. example:: Ltac2 Multiple matches for a "context" pattern. (Equivalent to this :ref:`Ltac1 example`.) Internally "x <> y" is represented as "(~ (x = y))", which produces the first match. .. rocqtop:: in Ltac2 f2 t := match! t with | context [ (~ ?t) ] => print (of_constr t); fail | _ => () end. .. rocqtop:: all abort f2 constr:((~ True) <> (~ False)). Match over goals ~~~~~~~~~~~~~~~~ .. tacn:: @ltac2_match_key {? reverse } goal with @goal_match_list end :name: lazy_match! goal; match! goal; multi_match! goal .. insertprodn goal_match_list gmatch_hyp_pattern .. prodn:: goal_match_list ::= {? %| } {+| @gmatch_rule } gmatch_rule ::= @gmatch_pattern => @ltac2_expr gmatch_pattern ::= [ {*, @gmatch_hyp_pattern } %|- @ltac2_match_pattern ] gmatch_hyp_pattern ::= @name : @ltac2_match_pattern | @name := [ @ltac2_match_pattern ] : @ltac2_match_pattern | @name := @ltac2_match_pattern Matches over goals, similar to Ltac1 :tacn:`match goal`. Use this form to match hypotheses and/or goals in the local context. These patterns have zero or more subpatterns to match hypotheses followed by a subpattern to match the conclusion. Except for the differences noted below, this works the same as the corresponding :n:`@ltac2_match_key @ltac2_expr` construct (see :tacn:`match!`). Each current goal is processed independently. Matching is non-linear: if a metavariable occurs more than once, each occurrence must match the same expression. Within a single term, expressions match if they are syntactically equal or :term:`Ξ±-convertible `. When a metavariable is used across multiple hypotheses or across a hypothesis and the current goal, the expressions match if they are :term:`convertible`. .. more detail here: https://github.com/rocq-prover/rocq/pull/12085#discussion_r470406466 :n:`{*, @gmatch_hyp_pattern }` Patterns to match with hypotheses. Each pattern must match a distinct hypothesis in order for the branch to match. Hypotheses have the form :n:`@name {? := @term__binder } : @type`. If :n:`@term__binder` is not specified, the pattern matches hypotheses even if they have a body. .. currently only supports the first row :list-table:: :widths: 2 1 :header-rows: 1 * - Pattern syntax - Example pattern * - :n:`@name : @ltac2_match_pattern` - `n : ?t` * - :n:`@name := @match_pattern__binder` - `n := ?b` * - :n:`@name := @term__binder : @type` - `n := ?b : ?t` * - :n:`@name := [ @match_pattern__binder ] : @ltac2_match_pattern` - `n := [ ?b ] : ?t` :token:`name` can't have a `?`. Note that the last two forms are equivalent except that: - if the `:` in the third form has been bound to something else in a notation, you must use the fourth form. Note that cmd:`Require Import` `ssreflect` loads a notation that does this. - a :n:`@term__binder` such as `[ ?l ]` (e.g., denoting a singleton list after :cmd:`Import` `ListNotations`) must be parenthesized or, for the fourth form, use double brackets: `[ [ ?l ] ]`. If there are multiple :token:`gmatch_hyp_pattern`\s in a branch, there may be multiple ways to match them to hypotheses. For :tacn:`match! goal` and :tacn:`multi_match! goal`, if the evaluation of the :token:`ltac2_expr` fails, matching will continue with the next hypothesis combination. When those are exhausted, the next alternative from any `context` construct in the :token:`ltac2_match_pattern`\s is tried and then, when the context alternatives are exhausted, the next branch is tried. :ref:`Example`. `reverse` Hypothesis matching for :token:`gmatch_hyp_pattern`\s normally begins by matching them from left to right, to hypotheses, last to first. Specifying `reverse` begins matching in the reverse order, from first to last. :ref:`Normal` and :ref:`reverse` examples. :n:`|- @ltac2_match_pattern` A pattern to match with the current goal Note that unlike Ltac1, only lowercase identifiers are valid as Ltac2 bindings. Ltac2 will report an error if you try to use a bound variable that starts with an uppercase character. Variables from :n:`@gmatch_hyp_pattern` and :n:`@ltac2_match_pattern` are bound in the body of the branch. Their types are: - ``constr`` for pattern variables appearing in a :n:`@term` - ``Pattern.context`` for variables binding a context - ``ident`` for variables binding a hypothesis name. The same identifier caveat as in the case of matching over constr applies, and this feature has the same semantics as in Ltac1. .. _ltac2_match_goal_hyps_ex: .. example:: Ltac2 Matching hypotheses (Equivalent to this :ref:`Ltac1 example`.) Hypotheses are matched from the last hypothesis (which is by default the newest hypothesis) to the first until the :tacn:`apply` succeeds. .. rocqtop:: all abort Goal forall A B : Prop, A -> B -> (A->B). intros. match! goal with | [ h : _ |- _ ] => let h := Control.hyp h in print (of_constr h); apply $h end. .. _ltac2_match_goal_hyps_rev_ex: .. example:: Matching hypotheses with reverse (Equivalent to this :ref:`Ltac1 example`.) Hypotheses are matched from the first hypothesis to the last until the :tacn:`apply` succeeds. .. rocqtop:: all abort Goal forall A B : Prop, A -> B -> (A->B). intros. match! reverse goal with | [ h : _ |- _ ] => let h := Control.hyp h in print (of_constr h); apply $h end. .. _ltac2_match_goal_multiple_hyps_ex: .. example:: Multiple ways to match a hypotheses (Equivalent to this :ref:`Ltac1 example`.) Every possible match for the hypotheses is evaluated until the right-hand side succeeds. Note that `h1` and `h2` are never matched to the same hypothesis. Observe that the number of permutations can grow as the factorial of the number of hypotheses and hypothesis patterns. .. rocqtop:: all abort Goal forall A B : Prop, A -> B -> (A->B). intros A B H. match! goal with | [ h1 : _, h2 : _ |- _ ] => print (concat (of_string "match ") (concat (of_constr (Control.hyp h1)) (concat (of_string " ") (of_constr (Control.hyp h2))))); fail | [ |- _ ] => () end. .. _ltac2_match_on_values: Match on values ~~~~~~~~~~~~~~~ .. tacn:: match @ltac2_expr5 with {? @ltac2_branches } end :name: match (Ltac2) Matches a value, akin to the OCaml `match` construct. By itself, it doesn't cause backtracking as do the `*match*!` and `*match*! goal` constructs. .. insertprodn ltac2_branches atomic_tac2pat .. prodn:: ltac2_branches ::= {? %| } {+| {? @atomic_tac2pat } => @ltac2_expr } tac2pat3 ::= @tac2pat3 %| {+| @tac2pat2 } | @tac2pat3 as @ident | @tac2pat2 tac2pat2 ::= @tac2pat1 :: @tac2pat2 | @tac2pat1 tac2pat1 ::= @qualid {+ @tac2pat0 } | @qualid | @tac2pat0 tac2pat0 ::= _ | () | @integer | @string | @qualid | ( {? @atomic_tac2pat } ) | %{ {? @tac2rec_fieldpats } %} | [ {*; @tac2pat3 } ] atomic_tac2pat ::= @tac2pat3 : @ltac2_type | @tac2pat3 , {*, @tac2pat3 } | @tac2pat3 .. tacn:: if @ltac2_expr5__test then @ltac2_expr5__then else @ltac2_expr5__else :name: if-then-else (Ltac2) Equivalent to a :tacn:`match ` on a boolean value. If the :n:`@ltac2_expr5__test` evaluates to true, :n:`@ltac2_expr5__then` is evaluated. Otherwise :n:`@ltac2_expr5__else` is evaluated. .. _ltac2_notations: Notations --------- .. cmd:: Ltac2 Notation {+ @ltac2_syntax_class } {? {| : @natural | : @qualid {? ( @natural ) } } } := @ltac2_expr .. todo seems like name maybe should use lident rather than ident, considering: Ltac2 Notation "ex1" X(constr) := print (of_constr X). ex1 1. Unbound constructor X This works fine with lower-case "x" in place of "X" .. todo Ltac2 Notation := permits redefining same symbol (no warning) Also allows defining a symbol beginning with uppercase, which is prohibited in similar constructs. :cmd:`Ltac2 Notation` provides a way to extend the syntax of Ltac2 tactics. The left-hand side (before the `:=`) defines the syntax to recognize and gives formal parameter names for the syntactic values. :n:`@natural` is the level of the notation (:n:`@ident(@natural)` means :cmd:`custom entry ` :n:`@ident` at level :n:`@natural`). For the default entry when the level is not provided, if the notation starts with a string which is an identifier (e.g. `"apply"`) the level is `1`, otherwise it is `5`. Custom entries must have explicit levels. When the notation is used, the values are substituted into the right-hand side. In the following example, `x` is the formal parameter name and `constr` is its :ref:`syntactic class`. `print` and `of_constr` are functions provided by Rocq through `Message.v`. (Also see :cmd:`Ltac2 Abbreviation`.) .. flag:: Ltac2 Typed Notations By default Ltac2 notations are typechecked at declaration time. This assigns an expected type to notation arguments. When a notation is declared with this flag unset, it is not typechecked at declaration time and its expansion is typechecked when it is used. This may allow slightly more flexible use of the notation arguments at the cost of worse error messages when incorrectly using the notation. It is not believed to be useful in practice, please report any real use cases you find. .. todo "print" doesn't seem to pay attention to "Set Printing All" .. example:: Printing a :n:`@term` .. rocqtop:: none Goal True. .. rocqtop:: all From Ltac2 Require Import Message. Ltac2 Notation "ex1" x(constr) := print (of_constr x). ex1 (1 + 2). You can also print terms with a regular Ltac2 definition, but then the :n:`@term` must be in the quotation `constr:( … )`: .. rocqtop:: all Ltac2 ex2 x := print (of_constr x). ex2 constr:(1+2). There are also metasyntactic classes described :ref:`here` that combine other items. For example, `list1(constr, ",")` recognizes a comma-separated list of one or more :token:`term`\s. .. example:: Parsing a list of :n:`@term`\s .. rocqtop:: abort all Ltac2 rec print_list x := match x with | a :: t => print (of_constr a); print_list t | [] => () end. Ltac2 Notation "ex2" x(list1(constr, ",")) := print_list x. ex2 1, 2, 3. An Ltac2 notation adds a parsing rule to the Ltac2 grammar, which is expanded to the provided body where every token from the notation is let-bound to the corresponding generated expression. .. example:: Assume we perform: .. rocqdoc:: Ltac2 Notation "foo" c(thunk(constr)) ids(list0(ident)) := Bar.f c ids. Then the following expression `let y := @X in foo (nat -> nat) x $y` will expand at parsing time to `let y := @X in` `let c := fun () => constr:(nat -> nat) with ids := [@x; y] in Bar.f c ids` Beware that the order of evaluation of multiple let-bindings is not specified, so that you may have to resort to thunking to ensure that side-effects are performed at the right time. This command supports the :attr:`deprecated` attribute. .. exn:: Notation levels must range between 0 and 6. The level of a notation must be an integer between 0 and 6 inclusive. .. cmd:: Ltac2 Custom Entry @ident Define a new grammar entry for Ltac2 expressions (as :cmd:`Declare Custom Entry` does for terms). Parsing rules can be added to the entry with :cmd:`Ltac2 Notation`, and the entry can be used as a :ref:`syntactic class `. Abbreviations ~~~~~~~~~~~~~ .. cmd:: Ltac2 Abbreviation @ident := @ltac2_expr Introduces a special kind of notation, called an abbreviation, that does not add any parsing rules. It is similar in spirit to Rocq abbreviations (see :cmd:`Abbreviation`), insofar as its main purpose is to give an absolute name to a piece of pure syntax, which can be transparently referred to by this name as if it were a proper definition. (See :cmd:`Ltac2 Notation` for the general description of notations.) The abbreviation can then be manipulated just like a normal Ltac2 definition, except that it is expanded at internalization time into the given expression. Furthermore, in order to make this kind of construction useful in practice in an effectful language such as Ltac2, any syntactic argument to an abbreviation is thunked on-the-fly during its expansion. For instance, suppose that we define the following. .. rocqdoc:: Ltac2 Abbreviation foo := fun x => x (). Then we have the following expansion at internalization time. :n:`foo 0 ↦ (fun x => x ()) (fun _ => 0)` Note that abbreviations are not type checked at all, and may result in typing errors after expansion. This command supports the :attr:`deprecated` attribute. .. _defining_tactics: Defining tactics ~~~~~~~~~~~~~~~~ Built-in tactics (those defined in OCaml code in the Rocq executable) and Ltac1 tactics, which are defined in `.v` files, must be defined through notations. Ltac2 tactics can be defined with :cmd:`Ltac2`. Notations for many but not all built-in tactics are defined in `Notations.v`, which is automatically loaded with Ltac2. The Ltac2 syntax for these tactics is often identical or very similar to the tactic syntax described in other chapters of this documentation. These notations rely on tactic functions declared in `Std.v`. Functions corresponding to some built-in tactics may not yet be defined in the Rocq executable or declared in `Std.v`. Adding them may require code changes to Rocq or defining workarounds through Ltac1 (described below). Two examples of syntax differences: - There is no notation defined that's equivalent to :n:`intros until {| @ident | @natural }`. There is, however, already an ``intros_until`` tactic function defined ``Std.v``, so it may be possible for a user to add the necessary notation. - The built-in `simpl` tactic in Ltac1 supports the use of scope keys in delta flags, e.g. :n:`simpl ["+"%nat]` which is not accepted by Ltac2. This is because Ltac2 uses a different definition for :token:`delta_reductions`; compare it to :token:`ltac2_delta_reductions`. This also affects :tacn:`compute`. Ltac1 tactics are not automatically available in Ltac2. (Note that some of the tactics described in the documentation are defined with Ltac1.) You can make them accessible in Ltac2 with commands similar to the following (the example requires the Stdlib library for the :tacn:`lia` tactic): .. rocqtop:: in extra-stdlib From Stdlib Require Import Lia. Local Ltac2 lia_ltac1 () := ltac1:(lia). Ltac2 Notation "lia" := lia_ltac1 (). A similar approach can be used to access missing built-in tactics. See :ref:`simple_api` for an example that passes two parameters to a missing build-in tactic. .. _syntactic_classes: Syntactic classes ~~~~~~~~~~~~~~~~~ The simplest syntactic classes in Ltac2 notations represent individual nonterminals from the Rocq grammar. Only a few selected nonterminals are available as syntactic classes. In addition, there are metasyntactic operations for describing more complex syntax, such as making an item optional or representing a list of items. When parsing, each syntactic class expression returns a value that's bound to a name in the notation definition. Syntactic classes are described with a form of S-expression: .. insertprodn ltac2_syntax_class ltac2_syntax_class .. prodn:: ltac2_syntax_class ::= @string | @integer | @name | @name ( {+, @ltac2_syntax_class } ) .. todo no syn class for ints or strings? parm names are not reserved (e.g the var can be named "list1") Metasyntactic operations that can be applied to other syntactic classes are: :n:`opt(@ltac2_syntax_class)` Parses an optional :token:`ltac2_syntax_class`. The associated value is either :n:`None` or enclosed in :n:`Some`. :n:`list1(@ltac2_syntax_class {? , @string })` Parses a list of one or more :token:`ltac2_syntax_class`\es. If :token:`string` is specified, items must be separated by :token:`string`. :n:`list0(@ltac2_syntax_class {? , @string })` Parses a list of zero or more :token:`ltac2_syntax_class`\es. If :token:`string` is specified, items must be separated by :token:`string`. For zero items, the associated value is an empty list. :n:`seq({+, @ltac2_syntax_class })` Parses the :token:`ltac2_syntax_class`\es in order. The associated value is a tuple, omitting :token:`ltac2_syntax_class`\es that are :token:`string`\s. `self` and `next` are not permitted within `seq`. The following classes represent nonterminals with some special handling. The table further down lists the classes that are handled plainly. .. insertprodn ltac2_constr_delimiters_arg ltac2_constr_synclass_arg .. prodn:: ltac2_constr_delimiters_arg ::= @scope_key | delimiters ( {+, @scope_key } ) ltac2_constr_synclass_arg ::= @ltac2_constr_delimiters_arg | custom ( @qualid ) | level ( @natural ) Syntactic classes parsing terms may specify :token:`scope_key`\s which are used to interpret the term (as described in :ref:`LocalInterpretationRulesForNotations`). The last :token:`scope_key` is the top of the scope stack that's applied to the :token:`term`. When more than one :n:`@scope_key` is specified, it should be qualified using `delimiters`. A :ref:`custom entry ` a parsing level may also be specified (except for the "l" syntactic classes which always parse the main term entry at level 200). If a custom entry is specified without a level, it is parsed at its highest level. :n:`constr {? ( {+, @ltac2_constr_synclass_arg } ) }` Parses a :token:`term`. Typechecking the term runs typeclass resolution, after which no new undefined existential variables may exist. :n:`lconstr {? ( {+, @ltac2_constr_delimiters_arg } ) }` Identical to `constr` but the term is parsed at precedence level 200. :n:`open_constr {? ( {+, @ltac2_constr_synclass_arg } ) }` Parses an open :token:`term`. Typechecking the term may create new undefined existential variables, and does not run typeclass resolution. :n:`open_lconstr {? ( {+, @ltac2_constr_delimiters_arg } ) }` Identical to `open_constr` but the term is parsed at precedence level 200. .. _preterm: :n:`preterm {? ( {+, @ltac2_constr_synclass_arg } ) }` Parses a non-typechecked :token:`term`. Like :n:`constr` above, this class accepts a list of notation scopes with the same effects. :n:`lpreterm {? ( {+, @ltac2_constr_delimiters_arg } ) }` Identical to `preterm` but the term is parsed at precedence level 200. :n:`ident` Parses :token:`ident` or :n:`$@ident`. The first form returns :n:`ident:(@ident)`, while the latter form returns the variable :n:`@ident`. :n:`@string` Accepts the specified string that is not a keyword, returning a value of `()`. :n:`keyword(@string)` Accepts the specified string that is a keyword, returning a value of `()`. :n:`terminal(@string)` Accepts the specified string whether it's a keyword or not, returning a value of `()`. :n:`tactic {? (@integer) }` Parses an :token:`ltac2_expr`. If :token:`integer` is specified, the construct parses a :n:`ltac2_expr@integer`, for example `tactic(5)` parses :token:`ltac2_expr5`. `tactic(6)` parses :token:`ltac2_expr`. :token:`integer` must be in the range `0 .. 6`. You can also use `tactic` to accept an :token:`integer` or a :token:`string`, but there's no syntactic class that accepts *only* an :token:`integer` or a :token:`string`. .. todo this doesn't work as expected: "::" is in ltac2_expr1 Ltac2 Notation "ex4" x(tactic(0)) := x. ex4 auto :: [auto]. .. not sure "self" and "next" do anything special. I get the same error message for both from constructs like Ltac2 Notation "ex5" x(self) := auto. ex5 match. Syntax error: [tactic:tac2expr level 5] expected after 'match' (in [tactic:tac2expr]). :n:`self` parses an Ltac2 expression at the current level and returns it as is. :n:`next` parses an Ltac2 expression at the next level and returns it as is. :n:`thunk(@ltac2_syntax_class)` Used for semantic effect only, parses the same as :token:`ltac2_syntax_class`. If :n:`e` is the parsed expression for :token:`ltac2_syntax_class`, `thunk` returns :n:`fun () => e`. :n:`pattern` parses a :token:`cpattern` A few syntactic classes contain antiquotation features. For the sake of uniformity, all antiquotations are introduced by the syntax :n:`$@lident`. A few other specific syntactic classes exist to handle Ltac1-like syntax, but their use is discouraged and they are thus not documented. New syntactic classes may be declared from the Ltac2 side using :cmd:`Ltac2 Custom Entry`. Other nonterminals that have syntactic classes are listed here. .. list-table:: :header-rows: 1 * - Syntactic class name - Nonterminal - Similar non-Ltac2 syntax * - :n:`intropatterns` - :token:`ltac2_intropatterns` - :n:`{* @intropattern }` * - :n:`intropattern` - :token:`ltac2_simple_intropattern` - :token:`simple_intropattern` * - :n:`ident` - :token:`ident_or_anti` - :token:`ident` * - :n:`destruction_arg` - :token:`ltac2_destruction_arg` - :token:`induction_arg` * - :n:`with_bindings` - :token:`q_with_bindings` - :n:`{? with @bindings }` * - :n:`bindings` - :token:`ltac2_bindings` - :token:`bindings` * - :n:`reductions` - :token:`ltac2_reductions` - :token:`reductions` * - :n:`reference` - :token:`refglobal` - :token:`reference` * - :n:`clause` - :token:`ltac2_clause` - :token:`occurrences` * - :n:`occurrences` - :token:`q_occurrences` - :n:`{? at @occs_nums }` * - :n:`induction_clause` - :token:`ltac2_induction_clause` - :token:`induction_clause` * - :n:`conversion` - :token:`ltac2_conversion` - * - :n:`orient` - :token:`q_orient` - :n:`{? {| -> | <- } }` * - :n:`rewriting` - :token:`ltac2_oriented_rewriter` - :token:`oriented_rewriter` * - :n:`dispatch` - :token:`ltac2_for_each_goal` - :token:`for_each_goal` * - :n:`hintdb` - :token:`hintdb` - :token:`hintbases` * - :n:`move_location` - :token:`move_location` - :token:`where` * - :n:`pose` - :token:`pose` - :token:`alias_definition` * - :n:`assert` - :token:`assertion` - :n:`( @ident := @term )` * - :n:`constr_matching` - :token:`ltac2_match_list` - See :tacn:`match` * - :n:`goal_matching` - :token:`goal_match_list` - See :tacn:`match goal` Here is the syntax for the :n:`q_*` nonterminals: .. insertprodn ltac2_intropatterns nonsimple_intropattern .. prodn:: ltac2_intropatterns ::= {* @nonsimple_intropattern } nonsimple_intropattern ::= * | ** | @ltac2_simple_intropattern .. insertprodn ltac2_simple_intropattern ltac2_equality_intropattern .. prodn:: ltac2_simple_intropattern ::= @ltac2_simple_intropattern_closed {* % @term0 } ltac2_simple_intropattern_closed ::= @ltac2_or_and_intropattern | @ltac2_equality_intropattern | _ | @ltac2_naming_intropattern ltac2_naming_intropattern ::= ?@ident | ?$ @ident | ? | @ident_or_anti ltac2_or_and_intropattern ::= [ {+| @ltac2_intropatterns } ] | () | ( {+, @ltac2_simple_intropattern } ) | ( {+& @ltac2_simple_intropattern } ) ltac2_equality_intropattern ::= -> | <- | [= @ltac2_intropatterns ] .. insertprodn ident_or_anti ident_or_anti .. prodn:: ident_or_anti ::= @ident | $ @ident .. insertprodn ltac2_destruction_arg ltac2_constr_with_bindings .. prodn:: ltac2_destruction_arg ::= @natural | @ident | @ltac2_constr_with_bindings ltac2_constr_with_bindings ::= @term {? with @ltac2_bindings } .. insertprodn q_with_bindings qhyp .. prodn:: q_with_bindings ::= {? with @ltac2_bindings } ltac2_bindings ::= {+ @ltac2_simple_binding } | {+ @term } ltac2_simple_binding ::= ( @qhyp := @term ) qhyp ::= $ @ident | @natural | @ident .. insertprodn ltac2_reductions ltac2_delta_reductions .. prodn:: ltac2_reductions ::= {+ @ltac2_red_flag } | {? @ltac2_delta_reductions } ltac2_red_flag ::= beta | iota | match | fix | cofix | zeta | delta {? @ltac2_delta_reductions } | head ltac2_delta_reductions ::= {? - } [ {+ @refglobal } ] .. insertprodn refglobal refglobal .. prodn:: refglobal ::= & @ident | @qualid | $ @ident .. insertprodn ltac2_clause ltac2_in_clause .. prodn:: ltac2_clause ::= in @ltac2_in_clause | at @ltac2_occs_nums ltac2_in_clause ::= * {? @ltac2_occs } | * %|- {? @ltac2_concl_occ } | {*, @ltac2_hypident_occ } {? %|- {? @ltac2_concl_occ } } .. insertprodn q_occurrences ltac2_hypident .. prodn:: q_occurrences ::= {? @ltac2_occs } ltac2_occs ::= at @ltac2_occs_nums ltac2_occs_nums ::= {? - } {+ {| @natural | $ @ident } } ltac2_concl_occ ::= * {? @ltac2_occs } ltac2_hypident_occ ::= @ltac2_hypident {? @ltac2_occs } ltac2_hypident ::= @ident_or_anti | ( type of @ident_or_anti ) | ( value of @ident_or_anti ) .. insertprodn ltac2_induction_clause ltac2_eqn_ipat .. prodn:: ltac2_induction_clause ::= @ltac2_destruction_arg {? @ltac2_as_or_and_ipat } {? @ltac2_eqn_ipat } {? @ltac2_clause } ltac2_as_or_and_ipat ::= as @ltac2_or_and_intropattern ltac2_eqn_ipat ::= eqn : @ltac2_naming_intropattern .. insertprodn ltac2_conversion ltac2_conversion .. prodn:: ltac2_conversion ::= @term | @term with @term .. insertprodn q_rewriting ltac2_rewriter .. prodn:: q_rewriting ::= @ltac2_oriented_rewriter ltac2_oriented_rewriter ::= {? @q_orient } @ltac2_rewriter q_orient ::= {? {| -> | <- } } ltac2_rewriter ::= {? @natural } {? {| ? | ! } } @ltac2_constr_with_bindings .. insertprodn ltac2_for_each_goal ltac2_goal_tactics .. prodn:: ltac2_for_each_goal ::= @ltac2_goal_tactics | {? @ltac2_goal_tactics %| } {? @ltac2_expr } .. {? %| @ltac2_goal_tactics } ltac2_goal_tactics ::= {*| {? @ltac2_expr } } .. insertprodn hintdb hintdb .. prodn:: hintdb ::= * | {+ @ident_or_anti } .. insertprodn move_location move_location .. prodn:: move_location ::= at top | at bottom | after @ident_or_anti | before @ident_or_anti .. insertprodn pose ltac2_as_name .. prodn:: pose ::= ( @ident_or_anti := @term ) | @term {? @ltac2_as_name } ltac2_as_name ::= as @ident_or_anti .. insertprodn assertion ltac2_by_tactic .. prodn:: assertion ::= ( @ident_or_anti := @term ) | ( @ident_or_anti : @term ) {? @ltac2_by_tactic } | @term {? @ltac2_as_ipat } {? @ltac2_by_tactic } ltac2_as_ipat ::= as @ltac2_simple_intropattern ltac2_by_tactic ::= by @ltac2_expr5 Evaluation ---------- Ltac2 features a toplevel loop that can be used to evaluate expressions. .. cmd:: Ltac2 Eval @ltac2_expr This command evaluates the term in the current proof if there is one, or in the global environment otherwise, and displays the resulting value to the user together with its type. This command is pure in the sense that it does not modify the state of the proof, and in particular all side-effects are discarded. Debug ----- .. flag:: Ltac2 Backtrace When this :term:`flag` is set, toplevel failures will be printed with a backtrace. .. flag:: Ltac2 Backtrace Compact This flag is on by default. When unset, anonymous functions and quotations in the stack trace print their bodies. This flag has no effect when :flag:`Ltac2 Backtrace` is not set. Profiling --------- .. flag:: Ltac2 In Ltac1 Profiling When this :term:`flag` and :flag:`Ltac Profiling` are set, profiling data is gathered for Ltac2 via the Ltac profiler. It is unset by default. Compatibility layer with Ltac1 ------------------------------ .. _ltac2in1: Ltac1 from Ltac2 ~~~~~~~~~~~~~~~~ .. _simple_api: Simple API ++++++++++ One can call Ltac1 code from Ltac2 by using the :n:`ltac1:(@ltac1_expr_in_env)` quotation. See :ref:`ltac2_built-in-quotations`. It parses a Ltac1 expression, and semantics of this quotation is the evaluation of the corresponding code for its side effects. In particular, it cannot return values, and the quotation has type :n:`unit`. Ltac1 **cannot** implicitly access variables from the Ltac2 scope, but this can be done with an explicit annotation on the :n:`ltac1:({* @ident } |- @ltac_expr)` quotation. See :ref:`ltac2_built-in-quotations`. For example: .. rocqtop:: in Local Ltac2 replace_with (lhs: constr) (rhs: constr) := ltac1:(lhs rhs |- replace lhs with rhs) (Ltac1.of_constr lhs) (Ltac1.of_constr rhs). Ltac2 Notation "replace" lhs(constr) "with" rhs(constr) := replace_with lhs rhs. The return type of this expression is a function of the same arity as the number of identifiers, with arguments of type `Ltac2.Ltac1.t` (see below). This syntax will bind the variables in the quoted Ltac1 code as if they had been bound from Ltac1 itself. Similarly, the arguments applied to the quotation will be passed at runtime to the Ltac1 code. .. _low_level_api: Low-level API +++++++++++++ There exists a lower-level FFI into Ltac1 that is not recommended for daily use, which is available in the `Ltac2.Ltac1` module. This API allows to directly manipulate dynamically-typed Ltac1 values, either through the function calls, or using the `ltac1val` quotation. The latter parses the same as `ltac1`, but has type `Ltac2.Ltac1.t` instead of `unit`, and dynamically behaves as an Ltac1 thunk, i.e. `ltac1val:(foo)` corresponds to the tactic closure that Ltac1 would generate from `idtac; foo`. Due to intricate dynamic semantics, understanding when Ltac1 value quotations focus is very hard. This is why some functions return a continuation-passing style value, as it can dispatch dynamically between focused and unfocused behavior. The same mechanism for explicit binding of variables as described in the previous section applies. Ltac2 from Ltac1 ~~~~~~~~~~~~~~~~ Same as above by switching Ltac1 by Ltac2 and using the `ltac2` quotation instead. .. prodn:: ltac_expr += ltac2 : ( @ltac2_expr ) | ltac2 : ( {+ @ident } |- @ltac2_expr ) The typing rules are dual, that is, the optional identifiers are bound with type `Ltac2.Ltac1.t` in the Ltac2 expression, which is expected to have type unit. The value returned by this quotation is an Ltac1 function with the same arity as the number of bound variables. Note that when no variables are bound, the inner tactic expression is evaluated eagerly, if one wants to use it as an argument to a Ltac1 function, one has to resort to the good old :n:`idtac; ltac2:(foo)` trick. For instance, the code below will fail immediately and won't print anything. .. rocqtop:: in From Ltac2 Require Import Ltac2. Set Default Proof Mode "Classic". .. rocqtop:: all Ltac mytac tac := idtac "I am being evaluated"; tac. Goal True. Proof. (* Doesn't print anything *) Fail mytac ltac2:(fail). (* Prints and fails *) Fail mytac ltac:(idtac; ltac2:(fail)). Abort. In any case, the value returned by the fully applied quotation is an unspecified dummy Ltac1 closure and should not be further used. Use the `ltac2val` quotation to return values to Ltac1 from Ltac2. .. prodn:: ltac_expr += ltac2val : ( @ltac2_expr ) | ltac2val : ( {+ @ident } |- @ltac2_expr ) It has the same typing rules as `ltac2:()` except the expression must have type `Ltac2.Ltac1.t`. .. rocqtop:: all Import Constr.Unsafe. Ltac add1 x := let f := ltac2val:(Ltac1.lambda (fun y => let y := Option.get (Ltac1.to_constr y) in let y := make (App constr:(S) [|y|]) in Ltac1.of_constr y)) in f x. Goal True. let z := constr:(0) in let v := add1 z in idtac v. Abort. Switching between Ltac languages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We recommend using the :opt:`Default Proof Mode` option or the :cmd:`Proof Mode` command to switch between tactic languages. The option has proof-level granularity while the command has :term:`sentence`-level granularity. This allows incrementally porting proof scripts. Transition from Ltac1 --------------------- Owing to the use of a lot of notations, the transition should not be too difficult. In particular, it should be possible to do it incrementally. That said, we do *not* guarantee it will be a blissful walk either. Hopefully, owing to the fact Ltac2 is typed, the interactive dialogue with the Rocq Prover will help you. We list the major changes and the transition strategies hereafter. Syntax changes ~~~~~~~~~~~~~~ Due to conflicts, a few syntactic rules have changed. - The dispatch tactical :n:`tac; [foo|bar]` is now written :n:`tac > [foo|bar]`. - Levels of a few operators have been revised. Some tacticals now parse as if they were normal functions. Parentheses are now required around complex arguments, such as abstractions. The tacticals affected are: :n:`try`, :n:`repeat`, :n:`do`, :n:`once`, :n:`progress`, :n:`time`, :n:`abstract`. - :n:`idtac` is no more. Either use :n:`()` if you expect nothing to happen, :n:`(fun () => ())` if you want a thunk (see next section), or use printing primitives from the :n:`Message` module if you want to display something. Tactic delay ~~~~~~~~~~~~ Tactics are not magically delayed anymore, neither as functions nor as arguments. It is your responsibility to thunk them beforehand and apply them at the call site. A typical example of a delayed function: .. rocqdoc:: Ltac foo := blah. becomes .. rocqdoc:: Ltac2 foo () := blah. All subsequent calls to `foo` must be applied to perform the same effect as before. Likewise, for arguments: .. rocqdoc:: Ltac bar tac := tac; tac; tac. becomes .. rocqdoc:: Ltac2 bar tac := tac (); tac (); tac (). We recommend the use of syntactic notations to ease the transition. For instance, the first example can alternatively be written as: .. rocqdoc:: Ltac2 foo0 () := blah. Ltac2 Notation foo := foo0 (). This allows to keep the subsequent calls to the tactic as-is, as the expression `foo` will be implicitly expanded everywhere into `foo0 ()`. Such a trick also works for arguments, as arguments of syntactic notations are implicitly thunked. The second example could thus be written as follows. .. rocqdoc:: Ltac2 bar0 tac := tac (); tac (); tac (). Ltac2 Notation bar := bar0. Variable binding ~~~~~~~~~~~~~~~~ Ltac1 relies on complex dynamic trickery to be able to tell apart bound variables from terms, hypotheses, etc. There is no such thing in Ltac2, as variables are recognized statically and other constructions do not live in the same syntactic world. Due to the abuse of quotations, it can sometimes be complicated to know what a mere identifier represents in a tactic expression. We recommend tracking the context and letting the compiler print typing errors to understand what is going on. We list below the typical changes one has to perform depending on the static errors produced by the typechecker. In Ltac expressions +++++++++++++++++++ .. exn:: Unbound {| value | constructor } X * if `X` is meant to be a term from the current static environment, replace the problematic use by `'X`. * if `X` is meant to be a hypothesis from the local context, replace the problematic use by `&X`. In quotations +++++++++++++ .. exn:: The reference X was not found in the current environment * if `X` is meant to be a tactic expression bound by a Ltac2 let or function, replace the problematic use by `$X`. * if `X` is meant to be a hypothesis from the local context, replace the problematic use by `&X`. Exception catching ~~~~~~~~~~~~~~~~~~ Ltac2 features a proper exception-catching mechanism. For this reason, the Ltac1 mechanism relying on `fail` taking integers, and tacticals decreasing it, has been removed. Now exceptions are preserved by all tacticals, and it is your duty to catch them and re-raise them as needed. rocq-9.2.0/doc/sphinx/proof-engine/proof-handling.rst000066400000000000000000000001611516144147600226040ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/proof-engine/ssreflect-proof-language.rst000066400000000000000000005542721516144147600246140ustar00rootroot00000000000000.. _thessreflectprooflanguage: ------------------------------ The |SSR| proof language ------------------------------ :Authors: Georges Gonthier, Assia Mahboubi, Enrico Tassi Introduction ------------ This chapter describes a set of tactics known as |SSR| originally designed to provide support for the so-called *small scale reflection* proof methodology. Despite the original purpose, this set of tactics is of general interest and is available in Rocq starting from version 8.7. |SSR| was developed independently of the tactics described in :ref:`tactics`. Indeed the scope of the tactics part of |SSR| largely overlaps with the standard set of tactics. Eventually the overlap will be reduced in future releases of Rocq. Proofs written in |SSR| typically look quite different from the ones written using only tactics described in :ref:`tactics`. We try to summarise here the most β€œvisible” ones in order to help the reader already accustomed to the tactics in :ref:`tactics` to read this chapter. The first difference between the tactics described in this chapter and the tactics described in :ref:`tactics` is the way hypotheses are managed (we call this *bookkeeping*). In :ref:`tactics` the most common approach is to avoid moving explicitly hypotheses back and forth between the context and the conclusion of the goal. On the contrary, in |SSR| all bookkeeping is performed on the conclusion of the goal, using for that purpose a couple of syntactic constructions behaving similar to tacticals (and often named as such in this chapter). The ``:`` tactical moves hypotheses from the context to the conclusion, while ``=>`` moves hypotheses from the conclusion to the context, and ``in`` moves back and forth a hypothesis from the context to the conclusion for the time of applying an action to it. While naming hypotheses is commonly done by means of an ``as`` clause in the basic model of :ref:`tactics`, it is here to ``=>`` that this task is devoted. Tactics frequently leave new assumptions in the conclusion, and are often followed by ``=>`` to explicitly name them. While generalizing the goal is normally not explicitly needed in :ref:`tactics`, it is an explicit operation performed by ``:``. .. seealso:: :ref:`bookkeeping_ssr` Besides the difference of bookkeeping model, this chapter includes specific tactics that have no explicit counterpart in :ref:`tactics` such as tactics to mix forward steps and generalizations as :tacn:`generally have` or :tacn:`without loss`. |SSR| adopts the point of view that rewriting, definition expansion and partial evaluation participate all to a same concept of rewriting a goal in a larger sense. As such, all these functionalities are provided by the :tacn:`rewrite ` tactic. |SSR| includes a little language of patterns to select subterms in tactics or tacticals where it matters. Its most notable application is in the :tacn:`rewrite ` tactic, where patterns are used to specify where the rewriting step has to take place. Finally, |SSR| supports so-called reflection steps, typically allowing to switch back and forth between the computational view and logical view of a concept. To conclude, it is worth mentioning that |SSR| tactics can be mixed with non-|SSR| tactics in the same proof, or in the same Ltac expression. The few exceptions to this statement are described in section :ref:`compatibility_issues_ssr`. Acknowledgments ~~~~~~~~~~~~~~~ The authors would like to thank FrΓ©dΓ©ric Blanqui, FranΓ§ois Pottier and Laurence Rideau for their comments and suggestions. Usage ----- Getting started ~~~~~~~~~~~~~~~ To be available, the tactics presented in this manual need the following minimal set of libraries to be loaded: ``ssreflect.v``, ``ssrfun.v`` and ``ssrbool.v``. Moreover, these tactics come with a methodology specific to the authors of |SSR| and which requires a few options to be set in a different way than in their default way. All in all, this corresponds to working in the following context: .. rocqtop:: in From Corelib Require Import ssreflect ssrfun ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. seealso:: :flag:`Implicit Arguments`, :flag:`Strict Implicit`, :flag:`Printing Implicit Defensive` .. _compatibility_issues_ssr: Compatibility issues ~~~~~~~~~~~~~~~~~~~~ Requiring the above modules creates an environment that is mostly compatible with the rest of Rocq, up to a few discrepancies. + New keywords (``is``) might clash with variable, constant, tactic or tactical names, or with quasi-keywords in tactic or notation commands. + New tactic(al)s names (:tacn:`last`, :tacn:`done`, :tacn:`have`, :tacn:`suffices`, :tacn:`suff`, :tacn:`without loss`, :tacn:`wlog`, :tacn:`congr`, :tacn:`unlock`) might clash with user tactic names. + Identifiers with both leading and trailing ``_``, such as ``_x_``, are reserved by |SSR| and cannot appear in scripts. + The extensions to the :tacn:`rewrite` tactic are partly incompatible with those available in current versions of Rocq; in particular, ``rewrite .. in (type of k)`` or ``rewrite .. in *`` or any other variant of :tacn:`rewrite` will not work, and the |SSR| syntax and semantics for occurrence selection and rule chaining are different. Use an explicit rewrite direction (``rewrite <- …`` or ``rewrite -> …``) to access the Rocq rewrite tactic. + New symbols (``//``, ``/=``, ``//=``) might clash with adjacent existing symbols. This can be avoided by inserting white spaces. + New constant and theorem names might clash with the user theory. This can be avoided by not importing all of |SSR|: .. rocqtop:: in From Corelib Require ssreflect. Import ssreflect.SsrSyntax. Note that the full syntax of |SSR|’s rewrite and reserved identifiers are enabled only if the ssreflect module has been required and if ``SsrSyntax`` has been imported. Thus a file that requires (without importing) ``ssreflect`` and imports ``SsrSyntax`` can be required and imported without automatically enabling |SSR|’s extended rewrite syntax and reserved identifiers. + Some user notations (in particular, defining an infix ``;``) might interfere with the "open term", parenthesis-free syntax of tactics such as :tacn:`have`, :tacn:`set (ssreflect)` and :tacn:`pose (ssreflect)`. + The generalization of ``if`` statements to non-Boolean conditions is turned off by |SSR|, because it is mostly subsumed by Coercion to ``bool`` of the ``sumXXX`` types (declared in ``ssrfun.v``) and the :n:`if @term is @pattern then @term else @term` construct (see :ref:`pattern_conditional_ssr`). To use the generalized form, turn off the |SSR| Boolean ``if`` notation using the command: ``Close Scope boolean_if_scope``. + The following flags can be unset to make |SSR| more compatible with parts of Rocq. .. flag:: SsrRewrite Controls whether the incompatible rewrite syntax is enabled (the default). Disabling the :term:`flag` makes the syntax compatible with other parts of Rocq. .. flag:: SsrIdents Controls whether tactics can refer to |SSR|-generated variables that are in the form _xxx_. Scripts with explicit references to such variables are fragile; they are prone to failure if the proof is later modified or if the details of variable name generation change in future releases of Rocq. The default is on, which gives an error message when the user tries to create such identifiers. Disabling the :term:`flag` generates a warning instead, increasing compatibility with other parts of Rocq. Gallina extensions -------------------- Small-scale reflection makes an extensive use of the programming subset of Gallina, Coq’s logical specification language. This subset is quite suited to the description of functions on representations, because it closely follows the well-established design of the ML programming language. The |SSR| extension provides three additions to Gallina, for pattern assignment, pattern testing, and polymorphism; these mitigate minor but annoying discrepancies between Gallina and ML. Pattern assignment ~~~~~~~~~~~~~~~~~~ The |SSR| extension provides the following construct for irrefutable pattern matching, that is, destructuring assignment: .. prodn:: term += let: @pattern := @term in @term__body Note the colon ``:`` after the ``let`` keyword, which avoids any ambiguity with a function definition or Coq’s basic destructuring let. The ``let:`` construct differs from the latter as follows. + The pattern can be nested (deep pattern matching); in particular, this allows expression of the form: .. rocqdoc:: let: exist (x, y) p_xy := Hp in … . + The destructured constructor is explicitly given in the pattern, and is used for type inference. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Definition f u := let: (m, n) := u in m + n. Check f. Using :g:`let:`, Rocq infers a type for :g:`f`, whereas with a usual ``let`` the same term requires an extra type annotation in order to type check. .. rocqtop:: reset all Fail Definition f u := let (m, n) := u in m + n. The ``let:`` construct is just (more legible) notation for the primitive Gallina expression :n:`match @term with @pattern => @term__body end`. The |SSR| destructuring assignment supports all the dependent match annotations; the full syntax is .. prodn:: term += let: @pattern {? as @ident} {? in @pattern__ind} := @term {? return @term__ret} in @term__body This dependent ``let:`` construct is just notation for :n:`match @term {? as @ident } {? in @pattern__ind } {? return @term__ret } with @pattern {? as @ident } => @term__body end`. In particular, :n:`@ident` is used both for dependent pattern matching and for aliasing the pattern (see :ref:`aliasing-subpatterns`). .. _pattern_conditional_ssr: Pattern conditional ~~~~~~~~~~~~~~~~~~~ The following construct can be used for a refutable pattern matching, that is, pattern testing: .. prodn:: term += if @term is @pattern then @term__then else @term__else Although this construct is not strictly ML (it does exist in variants such as the pattern calculus or the ρ-calculus), it turns out to be very convenient for writing functions on representations, because most such functions manipulate simple data types such as Peano integers, options, lists, or binary trees, and the pattern conditional above is almost always the right construct for analyzing such simple types. For example, the null and all list function(al)s can be defined as follows: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variable d: Set. Definition null (s : list d) := if s is nil then true else false. Variable a : d -> bool. Fixpoint all (s : list d) : bool := if s is cons x s' then a x && all s' else true. The pattern conditional also provides a notation for destructuring assignment with a refutable pattern, adapted to the pure functional setting of Gallina, which lacks a ``Match_Failure`` exception. Like ``let:`` above, the ``if…is`` construct is just (more legible) notation for the primitive Gallina expression :n:`match @term with @pattern => @term__then | _ => @term__else end`. Similarly, it will always be displayed as the expansion of this form in terms of primitive match expressions (where the default expression may be replicated). Explicit pattern testing also largely subsumes the generalization of the ``if`` construct to all binary data types; compare :n:`if @term is inl _ then @term else @term` and :n:`if @term then @term else @term`. The latter appears to be marginally shorter, but it is quite ambiguous, and indeed often requires an explicit annotation ``(term : {_} + {_})`` to type check, which evens the character count. Therefore, |SSR| restricts by default the condition of a plain ``if`` construct to the standard ``bool`` type; this avoids spurious type annotations. .. example:: .. rocqtop:: all Definition orb b1 b2 := if b1 then true else b2. As pointed out in Section :ref:`compatibility_issues_ssr`, this restriction can be removed with the command: ``Close Scope boolean_if_scope.`` Like ``let:`` above, the ``if-is-then-else`` construct supports the dependent match annotations: .. prodn:: term += if @term is @pattern as @ident in @pattern__ind return @term__ret then @term__then else @term__else This dependent ``if-is-then-else`` construct is just notation for :n:`match @term as @ident in @pattern__ind return @term__ret with @pattern as @ident => @term__then | _ => @term__else end`. In particular, :n:`@ident` is used both for dependent pattern matching and for aliasing the pattern (see :ref:`aliasing-subpatterns`). Another variant allows to treat the ``else`` case first: .. prodn:: term += if @term isn't @pattern then @term__then else @term__else Note that :token:`pattern` binds variables in :n:`@term__else` and not in :n:`@term__then`. .. _parametric_polymorphism_ssr: Parametric polymorphism ~~~~~~~~~~~~~~~~~~~~~~~ Unlike ML, polymorphism in core Gallina is explicit: the type parameters of polymorphic functions must be declared explicitly, and supplied at each point of use. However, Rocq provides two features to suppress redundant parameters. + Sections are used to provide (possibly implicit) parameters for a set of definitions. + Implicit arguments declarations are used to tell Rocq to use type inference to deduce some parameters from the context at each point of call. The combination of these features provides a fairly good emulation of ML-style polymorphism, but unfortunately this emulation breaks down for higher-order programming. Implicit arguments are indeed not inferred at all points of use, but only at points of call, leading to expressions such as .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Variable T : Type. Variable null : forall T : Type, T -> bool. Variable all : (T -> bool) -> list T -> bool. .. rocqtop:: all Definition all_null (s : list T) := all (@null T) s. Unfortunately, such higher-order expressions are quite frequent in representation functions, especially those that use Rocq's ``Structures`` to emulate Haskell typeclasses. Therefore, |SSR| provides a variant of Rocq's implicit argument declaration, which causes Rocq to fill in some implicit parameters at each point of use; e.g., the above definition can be written: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Variable T : Type. Variable null : forall T : Type, T -> bool. Variable all : (T -> bool) -> list T -> bool. .. rocqtop:: all Prenex Implicits null. Definition all_null (s : list T) := all null s. Better yet, it can be omitted entirely, since :g:`all_null s` isn’t much of an improvement over :g:`all null s`. The syntax of the new declaration is .. cmd:: Prenex Implicits {+ @ident__i} This command checks that each :n:`@ident__i` is the name of a functional constant, whose implicit arguments are prenex, i.e., the first :math:`n_i > 0` arguments of :n:`@ident__i` are implicit; then it assigns ``Maximal Implicit`` status to these arguments. As these prenex implicit arguments are ubiquitous and have often large display strings, it is strongly recommended to change the default display settings of Rocq so that they are not printed (except after a ``Set Printing All`` command). All |SSR| library files thus start with the incantation .. rocqdoc:: Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Anonymous arguments ~~~~~~~~~~~~~~~~~~~ When in a definition, the type of a certain argument is mandatory, but not its name, one usually uses β€œarrow” abstractions for prenex arguments, or the ``(_ : term)`` syntax for inner arguments. In |SSR|, the latter can be replaced by the open syntax ``of term`` or (equivalently) ``& term``, which are both syntactically equivalent to a ``(_ : term)`` expression. This feature almost behaves as the following extension of the binder syntax: .. prodn:: binder += {| & @term | of @term } Caveat: ``& T`` and ``of T`` abbreviations have to appear at the end of a binder list. For instance, the usual two-constructor polymorphic type list, i.e., the one of the standard ``List`` library, can be defined by the following declaration: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Inductive list (A : Type) : Type := nil | cons of A & list A. Wildcards ~~~~~~~~~ The terms passed as arguments to |SSR| tactics can contain *holes*, materialized by wildcards ``_``. Since |SSR| allows a more powerful form of type inference for these arguments, it enhances the possibilities of using such wildcards. These holes are in particular used as a convenient shorthand for abstractions, especially in local definitions or type expressions. Wildcards may be interpreted as abstractions (see for example Sections :ref:`definitions_ssr` and :ref:`structure_ssr`), or their content can be inferred from the whole context of the goal (see for example Section :ref:`abbreviations_ssr`). .. _definitions_ssr: Definitions ~~~~~~~~~~~ .. tacn:: pose :name: pose (ssreflect) This tactic allows to add a defined constant to a proof context. |SSR| generalizes this tactic in several ways. In particular, the |SSR| :tacn:`pose (ssreflect)` tactic supports *open syntax*: the body of the definition does not need surrounding parentheses. For instance: .. rocqdoc:: pose t := x + y. is a valid tactic expression. The :tacn:`pose (ssreflect)` tactic is also improved for the local definition of higher-order terms. Local definitions of functions can use the same syntax as global ones. For example, the tactic :tacn:`pose (ssreflect)` supports parameters: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : True. pose f x y := x + y. The |SSR| :tacn:`pose (ssreflect)` tactic also supports (co)fixpoints, by providing the local counterpart of the ``Fixpoint f := …`` and ``CoFixpoint f := …`` constructs. For instance, the following tactic: .. rocqdoc:: pose fix f (x y : nat) {struct x} : nat := if x is S p then S (f p y) else 0. defines a local fixpoint ``f``, which mimics the standard plus operation on natural numbers. Similarly, local cofixpoints can be defined by a tactic of the form: .. rocqdoc:: pose cofix f (arg : T) := … . The possibility to include wildcards in the body of the definitions offers a smooth way of defining local abstractions. The type of β€œholes” is guessed by type inference, and the holes are abstracted. For instance the tactic: .. rocqdoc:: pose f := _ + 1. is shorthand for: .. rocqdoc:: pose f n := n + 1. When the local definition of a function involves both arguments and holes, hole abstractions appear first. For instance, the tactic: .. rocqdoc:: pose f x := x + _. is shorthand for: .. rocqdoc:: pose f n x := x + n. The interaction of the :tacn:`pose (ssreflect)` tactic with the interpretation of implicit arguments results in a powerful and concise syntax for local definitions involving dependent types. For instance, the tactic: .. rocqdoc:: pose f x y := (x, y). adds to the context the local definition: .. rocqdoc:: pose f (Tx Ty : Type) (x : Tx) (y : Ty) := (x, y). The generalization of wildcards makes the use of the :tacn:`pose (ssreflect)` tactic resemble ML-like definitions of polymorphic functions. .. _abbreviations_ssr: Abbreviations ~~~~~~~~~~~~~ .. tacn:: set @ident {? : @type } := {? @occ_switch } @term :name: set (ssreflect) The |SSR| ``set`` tactic performs abbreviations; it introduces a defined constant for a subterm appearing in the goal and/or in the context. |SSR| extends the :tacn:`set` tactic by supplying: + an open syntax, similarly to the :tacn:`pose (ssreflect)` tactic; + a more aggressive matching algorithm; + an improved interpretation of wildcards, taking advantage of the matching algorithm; + an improved occurrence selection mechanism allowing to abstract only selected occurrences of a term. .. prodn:: occ_switch ::= { {? {| + | - } } {* @natural } } where: + :token:`ident` is a fresh identifier chosen by the user. + :token:`type` is an optional type annotation. If :token:`occ_switch` is present, then :token:`term` must be surrounded by parentheses. + In the occurrence switch :token:`occ_switch`, if the first element of the list is a natural, this element should be a number, and not an Ltac variable. The empty list ``{}`` is not interpreted as a valid occurrence switch; it is rather used as a flag to signal the intent of the user to clear the name following it (see :ref:`ssr_rewrite_occ_switch` and :ref:`introduction_ssr`). .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom f : nat -> nat. .. rocqtop:: all Lemma test x : f x + f x = f x. set t := f _. .. rocqtop:: all restart set t := {2}(f _). The type annotation may contain wildcards, which will be filled with appropriate values by the matching process. The tactic finds the first subterm of the goal that matches :token:`term` (and its type), then selects occurrences of this subterm, replaces them with :token:`ident` and adds a definition :n:`@ident := @term` to the context. :token:`occ_switch` selects which occurrences to replace. If :token:`occ_switch` is not specified, all occurrences are replaced. Matching ```````` The matching algorithm compares a pattern :token:`term` with a subterm of the goal by comparing their heads and then pairwise unifying their arguments (modulo conversion). Head symbols match under the following conditions. + If the head of :token:`term` is a constant, then it should be syntactically equal to the head symbol of the subterm. + If this head is a projection of a canonical structure, then canonical structure equations are used for the matching. + If the head of :token:`term` is *not* a constant, the subterm should have the same structure (Ξ» abstraction, ``let…in`` structure, etc.). + If the head of :token:`term` is a hole, the subterm should have at least as many arguments as :token:`term`. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test (x y z : nat) : x + y = z. set t := _ x. + In the special case where :token:`term` is of the form ``(let f := t0 in f) t1 … tn`` , then the pattern :token:`term` is treated as ``(_ t1 … tn)``. For each subterm in the goal having the form ``(A u1 … um)`` with m β‰₯ n, the matching algorithm successively tries to find the largest partial application ``(A u1 … uj)`` convertible to the head ``t0`` of :token:`term`. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : (let f x y z := x + y + z in f 1) 2 3 = 6. set t := (let g y z := S y + z in g) 2. The notation ``unkeyed`` defined in ``ssreflect.v`` is a shorthand for the degenerate term ``let x := … in x``. Moreover: + Multiple holes in :token:`term` are treated as independent placeholders. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y z : x + y = z. set t := _ + _. + The type of the subterm matched should fit the type (possibly casted by some type annotations) of the pattern :token:`term`. + The replacement of the subterm found by the instantiated pattern should not capture variables. In the example above, ``x`` is bound and should not be captured. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : forall x : nat, x + 1 = 0. Fail set t := _ + 1. + Typeclass inference should fill in any residual hole, but matching should never assign a value to a global existential variable. .. _occurrence_selection_ssr: Occurrence selection ```````````````````` |SSR| provides a generic syntax for the selection of occurrences by their position indexes. These *occurrence switches* are shared by all |SSR| tactics that require control on subterm selection like rewriting, generalization, … An *occurrence switch* can be: + A list of natural numbers ``{+ n1 … nm}`` of occurrences affected by the tactic. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom f : nat -> nat. .. rocqtop:: all Lemma test : f 2 + f 8 = f 2 + f 2. set x := {+1 3}(f 2). Notice that some occurrences of a given term may be hidden to the user, for example because of a notation. Setting the :flag:`Printing All` flag causes these hidden occurrences to be shown when the term is displayed. This setting should be used to find the correct coding of the occurrences to be selected [#1]_. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Notation "a < b":= (le (S a) b). Lemma test x y : x < y -> S x < S y. set t := S x. + A list of natural numbers ``{n1 … nm}``. This is equivalent to the previous ``{+ n1 … nm}``, but the list should start with a number, and not with an Ltac variable. + A list ``{- n1 … nm}`` of occurrences *not* to be affected by the tactic. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom f : nat -> nat. .. rocqtop:: all Lemma test : f 2 + f 8 = f 2 + f 2. set x := {-2}(f 2). Note that, in this goal, it behaves like ``set x := {1 3}(f 2).`` + In particular, the switch ``{+}`` selects *all* the occurrences. This switch is useful to turn off the default behavior of a tactic that automatically clears some assumptions (see Section :ref:`discharge_ssr` for instance). + The switch ``{-}`` imposes that *no* occurrences of the term should be affected by the tactic. The tactic: ``set x := {-}(f 2).`` leaves the goal unchanged and adds the definition ``x := f 2`` to the context. This kind of tactic may be used to take advantage of the power of the matching algorithm in a local definition, instead of copying large terms by hand. It is important to remember that matching *precedes* occurrence selection. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y z : x + y = x + y + z. set a := {2}(_ + _). Hence, in the following goal, the same tactic fails since there is only one occurrence of the selected term. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y z : (x + y) + (z + z) = z + z. Fail set a := {2}(_ + _). .. _basic_localization_ssr: Basic localization ~~~~~~~~~~~~~~~~~~ It is possible to define an abbreviation for a term appearing in the context of a goal thanks to the ``in`` tactical. .. tacv:: set @ident := @term in {+ @ident} This variant of :tacn:`set ` introduces a defined constant called :token:`ident` in the context, and folds it in the context entries mentioned on the right hand side of ``in``. The body of :token:`ident` is the first subterm matching these context entries (taken in the given order). .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. .. rocqtop:: all Lemma test x t (Hx : x = 3) : x + t = 4. set z := 3 in Hx. .. tacv:: set @ident := @term in {+ @ident} * This variant matches :token:`term` and then folds :token:`ident` similarly in all the given context entries but also folds :token:`ident` in the goal. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. .. rocqtop:: all Lemma test x t (Hx : x = 3) : x + t = 4. set z := 3 in Hx * . Indeed, remember that 4 is just a notation for (S 3). The use of the ``in`` tactical is not limited to the localization of abbreviations: for a complete description of the ``in`` tactical, see Section :ref:`bookkeeping_ssr` and :ref:`localization_ssr`. .. _basic_tactics_ssr: Basic tactics ------------- A sizable fraction of proof scripts consists of steps that do not "prove" anything new, but instead perform menial bookkeeping tasks such as selecting the names of constants and assumptions or splitting conjuncts. Although they are logically trivial, bookkeeping steps are extremely important because they define the structure of the data-flow of a proof script. This is especially true for reflection-based proofs, which often involve large numbers of constants and assumptions. Good bookkeeping consists in always explicitly declaring (i.e., naming) all new constants and assumptions in the script, and systematically pruning irrelevant constants and assumptions in the context. This is essential in the context of an interactive development environment (IDE), because it facilitates navigating the proof, allowing to instantly "jump back" to the point at which a questionable assumption was added, and to find relevant assumptions by browsing the pruned context. While novice or casual Rocq users may find the automatic name selection feature convenient, the usage of such a feature severely undermines the readability and maintainability of proof scripts, much like automatic variable declaration in programming languages. The |SSR| tactics are therefore designed to support precise bookkeeping and to eliminate name generation heuristics. The bookkeeping features of |SSR| are implemented as tacticals (or pseudo-tacticals), shared across most |SSR| tactics, and thus form the foundation of the |SSR| proof language. .. _bookkeeping_ssr: Bookkeeping ~~~~~~~~~~~ During the course of a proof, Rocq always presents the user with a *sequent* whose general form is:: ci : Ti … dj := ej : Tj … Fk : Pk … ================= forall (xl : Tl) …, let ym := bm in … in Pn -> … -> C The *goal* to be proved appears below the double line; above the line is the *context* of the sequent, a set of declarations of *constants* ``ci`` , *defined constants* ``dj`` , and *facts* ``Fk`` that can be used to prove the goal (usually, ``Ti`` , ``Tj : Type`` and ``Pk : Prop``). The various kinds of declarations can come in any order. The top part of the context consists of declarations produced by the Section commands ``Variable``, ``Let``, and ``Hypothesis``. This *section context* is never affected by the |SSR| tactics: they only operate on the lower part β€” the *proof context*. As in the figure above, the goal often decomposes into a series of (universally) quantified *variables* ``(xl : Tl)``, local *definitions* ``let ym := bm in``, and *assumptions* ``Pn ->``, and a *conclusion* ``C`` (as in the context, variables, definitions, and assumptions can appear in any order). The conclusion is what actually needs to be proved β€” the rest of the goal can be seen as a part of the proof context that happens to be β€œbelow the line”. However, although they are logically equivalent, there are fundamental differences between constants and facts, on the one hand, and variables and assumptions, on the other. Constants and facts are *unordered*, but *named* explicitly in the proof text; variables and assumptions are *ordered*, but *unnamed*: the display names of variables may change at any time because of Ξ±-conversion. Similarly, basic deductive steps such as ``apply`` can only operate on the goal because the Gallina terms that control their action (e.g., the type of the lemma used by ``apply``) only provide unnamed bound variables. [#2]_ Since the proof script can only refer directly to the context, it must constantly shift declarations from the goal to the context and conversely in between deductive steps. In |SSR|, these moves are performed by two *tacticals*, ``=>`` and ``:``, so that the bookkeeping required by a deductive step can be directly associated with that step, and that tactics in an |SSR| script correspond to actual logical steps in the proof rather than merely shuffle facts. Still, some isolated bookkeeping is unavoidable, such as naming variables and assumptions at the beginning of a proof. |SSR| provides a specific ``move`` tactic for this purpose. Now, ``move`` does essentially nothing: it is mostly a placeholder for ``=>`` and ``:``. The ``=>`` tactical moves variables, local definitions, and assumptions to the context, while the ``:`` tactical moves facts and constants to the goal. .. example:: For example, the proof of [#3]_ .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma subnK : forall m n, n <= m -> m - n + n = m. might start with .. rocqtop:: all move=> m n le_n_m. where ``move`` does nothing, but ``=> m n le_m_n`` changes the variables and assumption of the goal in the constants ``m n : nat`` and the fact ``le_n_m : n <= m``, thus exposing the conclusion ``m - n + n = m``. The ``:`` tactical is the converse of ``=>``; indeed it removes facts and constants from the context by turning them into variables and assumptions. .. rocqtop:: all move: m le_n_m. turns back ``m`` and ``le_m_n`` into a variable and an assumption, removing them from the proof context, and changing the goal to ``forall m, n <= m -> m - n + n = m``, which can be proved by induction on ``n`` using ``elim: n``. Because they are tacticals, ``:`` and ``=>`` can be combined, as in .. rocqdoc:: move: m le_n_m => p le_n_p. which simultaneously renames ``m`` and ``le_m_n`` into ``p`` and ``le_n_p``, respectively, by first turning them into unnamed variables, then turning these variables back into constants and facts. Furthermore, |SSR| redefines the basic Rocq tactics ``case``, ``elim``, and ``apply`` so that they can take better advantage of ``:`` and ``=>``. In these |SSR| variants, these tactics operate on the first variable or constant of the goal and they do not use or change the proof context. The ``:`` tactical is used to operate on an element in the context. .. example:: For instance, the proof of ``subnK`` could continue with ``elim: n``. Instead of ``elim n`` (note, no colon), this has the advantage of removing n from the context. Better yet, this ``elim`` can be combined with previous ``move`` and with the branching version of the ``=>`` tactical (described in :ref:`introduction_ssr`), to encapsulate the inductive step in a single command: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma subnK : forall m n, n <= m -> m - n + n = m. move=> m n le_n_m. elim: n m le_n_m => [|n IHn] m => [_ | lt_n_m]. which breaks down the proof into two subgoals, the second one having in its context ``lt_n_m : S n <= m`` and ``IHn : forall m, n <= m -> m - n + n = m``. The ``:`` and ``=>`` tacticals can be explained very simply if one views the goal as a stack of variables and assumptions piled on a conclusion: + ``tactic : a b c`` pushes the context constants ``a``, ``b``, ``c`` as goal variables *before* performing the tactic; + ``tactic => a b c`` pops the top three goal variables as context constants ``a``, ``b``, ``c``, *after* the tactic has been performed. These pushes and pops do not need to balance out as in the examples above; so ``move: m le_n_m => p`` would rename ``m`` into ``p``, but leave an extra assumption ``n <= p`` in the goal. Basic tactics like ``apply`` and ``elim`` can also be used without the ’:’ tactical: for example, we can directly start a proof of ``subnK`` by induction on the top variable ``m`` with .. rocqdoc:: elim=> [|m IHm] n le_n. The general form of the localization tactical ``in`` is also best explained in terms of the goal stack:: tactic in a H1 H2 *. is basically equivalent to .. rocqdoc:: move: a H1 H2; tactic => a H1 H2. with two differences: the ``in`` tactical will preserve the body of ``a``, if ``a`` is a defined constant, and if the ``*`` is omitted, it will use a temporary abbreviation to hide the statement of the goal from ``tactic``. The general form of the ``in`` tactical can be used directly with the ``move``, ``case`` and ``elim`` tactics, so that one can write .. rocqdoc:: elim: n => [|n IHn] in m le_n_m *. instead of .. rocqdoc:: elim: n m le_n_m => [|n IHn] m le_n_m. This is quite useful for inductive proofs that involve many facts. See Section :ref:`localization_ssr` for the general syntax and presentation of the ``in`` tactical. .. _the_defective_tactics_ssr: The defective tactics ~~~~~~~~~~~~~~~~~~~~~ In this section, we briefly present the three basic tactics performing context manipulations and the main backward chaining tool. The move tactic. ```````````````` .. tacn:: move :name: move (ssreflect) This tactic, in its defective form, behaves like the :tacn:`hnf` tactic. .. example:: .. rocqtop:: reset all Require Import ssreflect. Goal not False. move. More precisely, the :tacn:`move ` tactic inspects the goal and does nothing (:tacn:`idtac`) if an introduction step is possible, i.e., if the goal is a product or a ``let … in``, and performs :tacn:`hnf` otherwise. Of course this tactic is most often used in combination with the bookkeeping tacticals (see Sections :ref:`introduction_ssr` and :ref:`discharge_ssr`). These combinations mostly subsume the :tacn:`intros`, :tacn:`generalize`, :tacn:`revert`, :tacn:`rename`, :tacn:`clear` and :tacn:`pattern` tactics. .. _the_case_tactic_ssr: The case tactic ``````````````` .. tacn:: case :name: case (ssreflect) This tactic performs *primitive case analysis* on (co)inductive types; specifically, it destructs the top variable or assumption of the goal, exposing its constructor(s) and its arguments, as well as setting the value of its type family indices if it belongs to a type family (see Section :ref:`type_families_ssr`). The |SSR| ``case`` tactic has a special behavior on equalities. If the top assumption of the goal is an equality, the ``case`` tactic β€œdestructs” it as a set of equalities between the constructor arguments of its left and right hand sides, as per the tactic injection. For example, ``case`` changes the goal:: (x, y) = (1, 2) -> G. into:: x = 1 -> y = 2 -> G. The :tacn:`case` can generate the following warning: .. warn:: SSReflect: cannot obtain new equations out of ... The tactic was run on an equation that cannot generate simpler equations, for example `x = 1`. The warning can be silenced or made fatal by using the :opt:`Warnings` option and the `spurious-ssr-injection` key. Finally, the :tacn:`case` tactic of |SSR| performs :g:`False` elimination, even if no branch is generated by this case operation. Hence the tactic :tacn:`case` on a goal of the form :g:`False -> G` will succeed and prove the goal. The elim tactic ``````````````` .. tacn:: elim :name: elim (ssreflect) This tactic performs inductive elimination on inductive types. In its defective form, the tactic performs inductive elimination on a goal whose top assumption has an inductive type. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test m : forall n : nat, m <= n. elim. .. _apply_ssr: The apply tactic ```````````````` .. tacn:: apply {? @term } :name: apply (ssreflect) This is the main backward chaining tactic of the proof system. It takes as argument any :token:`term` and applies it to the goal. Assumptions in the type of :token:`term` that don’t directly match the goal may generate one or more subgoals. In its defective form, this tactic is a synonym for:: intro top; first [refine top | refine (top _) | refine (top _ _) | …]; clear top. where :g:`top` is a fresh name, and the sequence of :tacn:`refine` tactics tries to catch the appropriate number of wildcards to be inserted. Note that this use of the :tacn:`refine` tactic implies that the tactic tries to match the goal up to expansion of constants and evaluation of subterms. :tacn:`apply ` has a special behavior on goals containing existential metavariables of sort :g:`Prop`. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom lt_trans : forall a b c, a < b -> b < c -> a < c. .. rocqtop:: all Lemma test : forall y, 1 < y -> y < 2 -> exists x : { n | n < 3 }, 0 < proj1_sig x. move=> y y_gt1 y_lt2; apply: (ex_intro _ (exist _ y _)). by apply: lt_trans y_lt2 _. by move=> y_lt3; apply: lt_trans y_gt1. Note that the last ``_`` of the tactic ``apply: (ex_intro _ (exist _ y _))`` represents a proof that ``y < 3``. Instead of generating the goal:: 0 < proj1_sig (exist (fun n : nat => n < 3) y ?Goal). the system tries to prove ``y < 3`` calling the trivial tactic. If it succeeds, let’s say because the context contains ``H : y < 3``, then the system generates the following goal:: 0 < proj1_sig (exist (fun n => n < 3) y H). Otherwise the missing proof is considered to be irrelevant, and is thus discharged, generating the two goals shown above. Last, the user can replace the trivial tactic by defining an Ltac expression named ``ssrautoprop``. .. _discharge_ssr: Discharge ~~~~~~~~~ The general syntax of the discharging tactical ``:`` is: .. tacn:: @tactic {? @ident } : {+ @d_item } {? @clear_switch } :name: … : … (ssreflect) :undocumented: .. prodn:: d_item ::= {? {| @occ_switch | @clear_switch } } @term .. prodn:: clear_switch ::= { {+ @ident } } with the following requirements. + :token:`tactic` must be one of the four basic tactics described in :ref:`the_defective_tactics_ssr`, i.e., ``move``, ``case``, ``elim`` or ``apply``, the ``exact`` tactic (section :ref:`terminators_ssr`), the ``congr`` tactic (Section :ref:`congruence_ssr`), or the application of the *view* tactical β€˜/’ (Section :ref:`interpreting_assumptions_ssr`) to one of ``move``, ``case``, or ``elim``. + The optional :token:`ident` specifies *equation generation* (Section :ref:`generation_of_equations_ssr`), and is only allowed if :token:`tactic` is ``move``, ``case`` or ``elim``, or the application of the view tactical β€˜/’ (Section :ref:`interpreting_assumptions_ssr`) to ``case`` or ``elim``. + An :token:`occ_switch` selects occurrences of :token:`term`, as in :ref:`abbreviations_ssr`; :token:`occ_switch` is not allowed if :token:`tactic` is ``apply`` or ``exact``. + A clear item :token:`clear_switch` specifies facts and constants to be deleted from the proof context (as per the ``clear`` tactic). The ``:`` tactical first *discharges* all the :token:`d_item`, right to left, and then performs the tactic, i.e., for each :token:`d_item`, starting with the last one : #. The |SSR| matching algorithm described in Section :ref:`abbreviations_ssr` is used to find occurrences of :token:`term` in the goal, after filling any holes β€˜_’ in the term; however if :token:`tactic` is ``apply`` or ``exact``, a different matching algorithm, described below, is used [#4]_. #. These occurrences are replaced by a new variable; in particular, if the term is a fact, this adds an assumption to the goal. #. If the term is *exactly* the name of a constant or fact in the proof context, it is deleted from the context, unless there is an :token:`occ_switch`. Finally, the tactic is performed just after the first :token:`d_item` has been generalized β€” that is, between steps 2 and 3. The names listed in the final :token:`clear_switch` (if it is present) are cleared first, before :token:`d_item` n is discharged. Switches affect the discharging of a :token:`d_item` as follows. + An :token:`occ_switch` restricts generalization (step 2) to a specific subset of the occurrences of the term, as per Section :ref:`abbreviations_ssr`, and prevents clearing (step 3). + All the names specified by a :token:`clear_switch` are deleted from the context in step 3, possibly in addition to the term. For example, the tactic: .. rocqdoc:: move: n {2}n (refl_equal n). + first generalizes ``(refl_equal n : n = n)``; + then generalizes the second occurrence of ``n``. + finally generalizes all the other occurrences of ``n``, and clears ``n`` from the proof context (assuming ``n`` is a proof constant). Therefore, this tactic changes any goal ``G`` into .. rocqdoc:: forall n n0 : nat, n = n0 -> G. where the name ``n0`` is picked by the Rocq display function, and assuming ``n`` appeared only in ``G``. Finally, note that a discharge operation generalizes defined constants as variables, and not as local definitions. To override this behavior, prefix the name of the local definition with a ``@``, like in ``move: @n``. This is in contrast with the behavior of the ``in`` tactical (see Section :ref:`localization_ssr`), which preserves local definitions by default. Clear rules ``````````` The clear step will fail if the term is a proof constant that appears in other facts; in that case, either the facts should be cleared explicitly with a :token:`clear_switch`, or the clear step should be disabled. The latter can be done by adding an :token:`occ_switch` or simply by putting parentheses around term: both ``move: (n).`` and ``move: {+}n.`` generalize ``n`` without clearing ``n`` from the proof context. The clear step will also fail if the :token:`clear_switch` contains a :token:`ident` that is not in the *proof* context. Note that |SSR| never clears a section constant. If the tactic is ``move`` or ``case`` and an equation :token:`ident` is given, then clearing (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 clearing of context items. Matching for apply and exact ```````````````````````````` The matching algorithm for :token:`d_item` of the |SSR| ``apply`` and ``exact`` tactics exploits the type of the first :token:`d_item` to interpret wildcards in the other :token:`d_item` and to determine which occurrences of these should be generalized. Therefore, occur switches are not needed for ``apply`` and ``exact``. Indeed, the |SSR| tactic ``apply: H x`` is equivalent to ``refine (@H _ … _ x); clear H x``, with an appropriate number of wildcards between ``H`` and ``x``. Note that this means that matching for ``apply`` and ``exact`` has much more context to interpret wildcards; in particular, it can accommodate the ``_`` :token:`d_item`, which would always be rejected after ``move:``. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom f : nat -> nat. Axiom g : nat -> nat. .. rocqtop:: all Lemma test (Hfg : forall x, f x = g x) a b : f a = g b. apply: trans_equal (Hfg _) _. This tactic is equivalent (see Section :ref:`bookkeeping_ssr`) to: ``refine (trans_equal (Hfg _) _).`` and this is a common idiom for applying transitivity on the left hand side of an equation. .. _abstract_ssr: The abstract tactic ``````````````````` .. tacn:: abstract: {+ @d_item} :name: abstract (ssreflect) This tactic assigns an abstract constant previously introduced with the :n:`[: @ident ]` intro pattern (see Section :ref:`introduction_ssr`). In a goal like the following:: m : nat abs : n : nat ============= m < 5 + n The tactic :g:`abstract: abs n` first generalizes the goal with respect to :g:`n` (that is not visible to the abstract constant ``abs``) and then assigns abs. The resulting goal is:: m : nat n : nat ============= m < 5 + n Once this subgoal is closed, all other goals having ``abs`` in their context see the type assigned to ``abs``. In this case:: m : nat abs : forall n, m < 5 + n ============= … For a more detailed example, the reader should refer to Section :ref:`structure_ssr`. .. _introduction_ssr: Introduction in the context ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The application of a tactic to a given goal can generate (quantified) variables, assumptions, or definitions, which the user may want to *introduce* as new facts, constants or defined constants, respectively. If the tactic splits the goal into several subgoals, each of them may require the introduction of different constants and facts. Furthermore it is very common to immediately decompose or rewrite with an assumption instead of adding it to the context, as the goal can often be simplified and even proved after this. All these operations are performed by the introduction tactical ``=>``, whose general syntax is .. tacn:: @tactic => {+ @i_item } :name: => :undocumented: .. prodn:: i_item ::= {| @i_pattern | @s_item | @clear_switch | @i_view | @i_block } .. prodn:: s_item ::= {| /= | // | //= } .. prodn:: i_view ::= {? %{%} } {| /@term | /ltac:( @tactic ) } .. prodn:: i_pattern ::= {| @ident | > | _ | ? | * | + | {? @occ_switch } {| -> | <- } | [ {?| @i_item } ] | - | [: {+ @ident } ] } .. prodn:: i_block ::= {| [^ @ident ] | [^~ {| @ident | @natural } ] } The ``=>`` tactical first executes :token:`tactic`, then the :token:`i_item`\s, left to right. An :token:`s_item` specifies a simplification operation; a :token:`clear_switch` specifies context pruning as in :ref:`discharge_ssr`. 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 |SSR| tactic :tacn:`done` described in :ref:`terminators_ssr`, i.e., it executes ``try done``. + ``/=`` simplifies the goal by performing partial evaluation, as per the tactic :tacn:`simpl` [#5]_. + ``//=`` combines both kinds of simplification; it is equivalent to ``/= //``, i.e., ``simpl; try done``. 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 :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. The second entry in the :token:`i_view` grammar rule, ``/ltac:(`` :token:`tactic` ``)``, executes :token:`tactic`. Notations can be used to name tactics, for example .. rocqtop:: none Tactic Notation "my" "ltac" "code" := idtac. .. rocqtop:: in warn Notation "'myop'" := (ltac:(my ltac code)) : ssripat_scope. lets one write just ``/myop`` in the intro pattern. Note the scope annotation: views are interpreted opening the ``ssripat`` scope. We provide the following ltac views: ``/[dup]`` to duplicate the top of the stack, ``/[swap]`` to swap the two first elements and ``/[apply]`` to apply the top of the stack to the next. Intro patterns `````````````` |SSR| supports the following :token:`i_pattern`\s. :token:`ident` pops the top variable, assumption, or local definition into 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. Thus, trying to clear an :token:`ident` `H` with `{H}H` triggers the following warning: .. warn:: Duplicate clear of H. Use %{ %}H instead of %{ H %}H The warning can be silenced or made fatal with the :opt:`Warnings` option with the `duplicate-clear` key. ``>`` pops every variable occurring in the rest of the stack. Type class instances are popped even if they don't occur in the rest of the stack. The tactic ``move=> >`` is equivalent to ``move=> ? ?`` on a goal such as:: forall x y, x < y -> G A typical use if ``move=>> H`` to name ``H`` the first assumption, in the example above ``x < y``. ``?`` pops the top variable into an anonymous constant or fact, whose name is picked by the tactic interpreter. |SSR| only generates names that cannot appear later in the user script [#6]_. ``_`` pops the top variable into an anonymous constant that will be deleted from the proof context of all the subgoals produced by the ``=>`` tactical. They should thus never be displayed, except in an error message if the constant is still actually used in the goal or context after the last :token:`i_item` has been executed (:token:`s_item` can erase goals or terms where the constant appears). ``*`` pops all the remaining apparent variables/assumptions as anonymous constants/facts. Unlike ``?`` and ``move``, the ``*`` :token:`i_item` does not expand definitions in the goal to expose quantifiers, so it may be useful to repeat a ``move=> *`` tactic, e.g., on the goal:: forall a b : bool, a <> b a first ``move=> *`` adds only ``_a_ : bool`` and ``_b_ : bool`` to the context; it takes a second ``move=> *`` to add ``_Hyp_ : _a_ = _b_``. ``+`` temporarily introduces the top variable. It is discharged at the end of the intro pattern. For example ``move=> + y`` on a goal:: forall x y, P is equivalent to ``move=> _x_ y; move: _x_`` that results in the goal:: forall x, P :n:`{? occ_switch } ->` (resp. :token:`occ_switch` ``<-``) pops the top assumption (which should be a rewritable proposition) into an anonymous fact, rewrites (resp. rewrites right to left) the goal with this fact (using the |SSR| ``rewrite`` tactic described in Section :ref:`rewriting_ssr`, and honoring the optional occurrence selector), and finally deletes the anonymous fact from the context. ``[`` :token:`i_item` * ``| … |`` :token:`i_item` * ``]`` when it is the very *first* :token:`i_pattern` after tactic ``=>`` tactical *and* the tactic is not a move, is a *branching* :token:`i_pattern`. It executes the sequence :n:`@i_item__i` on the i-th subgoal produced by the tactic. The execution of the tactic should thus generate exactly m subgoals, unless the ``[…]`` :token:`i_pattern` comes after an initial ``//`` or ``//=`` :token:`s_item` that closes some of the goals produced by the tactic, in which case exactly m subgoals should remain after the :token:`s_item`, or we have the trivial branching :token:`i_pattern` [], which always does nothing, regardless of the number of remaining subgoals. ``[`` :token:`i_item` * ``| … |`` :token:`i_item` * ``]`` when it is *not* the first :token:`i_pattern` or when the tactic is a ``move``, is a *destructing* :token:`i_pattern`. It starts by destructing the top variable, using the |SSR| ``case`` tactic described in :ref:`the_defective_tactics_ssr`. It then behaves as the corresponding branching :token:`i_pattern`, executing the sequence :n:`@i_item__i` in the i-th subgoal generated by the case analysis; unless we have the trivial destructing :token:`i_pattern` ``[]``, the latter should generate exactly m subgoals, i.e., the top variable should have an inductive type with exactly m constructors [#7]_. While it is good style to use the :token:`i_item` i * to pop the variables and assumptions corresponding to each constructor, this is not enforced by |SSR|. ``-`` does nothing, but counts as an intro pattern. It can also be used to force the interpretation of ``[`` :token:`i_item` * ``| … |`` :token:`i_item` * ``]`` as a case analysis like in ``move=> -[H1 H2]``. It can also be used to indicate explicitly the link between a view and a name like in ``move=> /eqP-H1``. Last, it can serve as a separator between views. Section :ref:`views_and_reflection_ssr` [#9]_ explains in which respect the tactic ``move=> /v1/v2`` differs from the tactic ``move=> /v1-/v2``. ``[:`` :token:`ident` ``…]`` introduces in the context an abstract constant for each :token:`ident`. Its type has to be fixed later on by using the ``abstract`` tactic. Before then the type displayed is ````. 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:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y : Nat.leb 0 x = true -> (Nat.leb 0 x) && (Nat.leb y 2) = true. move=> {x} ->. If the cleared names are reused in the same intro pattern, a renaming 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 the tactic is a ``move``, and in most of the remaining cases the tactic is ``case`` or ``elim``, which implies destructuring. The rules above imply that: + ``move=> [a b].`` + ``case=> [a b].`` + ``case=> a b.`` are all equivalent, so which one to use is a matter of style; ``move`` should be used for casual decomposition, such as splitting a pair, and ``case`` should be used for actual decompositions, in particular for type families (see :ref:`type_families_ssr`) and proof by contradiction. The trivial branching :token:`i_pattern` can be used to force the branching interpretation, e.g.: + ``case=> [] [a b] c.`` + ``move=> [[a b] c].`` + ``case; case=> a b c.`` are all equivalent. Block introduction `````````````````` |SSR| supports the following :token:`i_block`\s. :n:`[^ @ident ]` *block destructing* :token:`i_pattern`. It performs a case analysis on the top variable and introduces, in one go, all the variables coming from the case analysis. The names of these variables are obtained by taking the names used in the inductive type declaration and prefixing them with :token:`ident`. If the intro pattern immediately follows a call to ``elim`` with a custom eliminator (see :ref:`custom_elim_ssr`), then the names are taken from the ones used in the type of the eliminator. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Record r := { a : nat; b := (a, 3); _ : bool; }. Lemma test : r -> True. Proof. move => [^ x ]. :n:`[^~ @ident ]` *block destructing* using :token:`ident` as a suffix. :n:`[^~ @natural ]` *block destructing* using :token:`natural` as a suffix. Only a :token:`s_item` is allowed between the elimination tactic and the block destructing. .. _generation_of_equations_ssr: Generation of equations ~~~~~~~~~~~~~~~~~~~~~~~ The generation of named equations option stores the definition of a new constant as an equation. The tactic: .. rocqdoc:: move En: (size l) => n. where ``l`` is a list, replaces ``size l`` by ``n`` in the goal and adds the fact ``En : size l = n`` to the context. This is quite different from: .. rocqdoc:: pose n := (size l). which generates a definition ``n := (size l)``. It is not possible to generalize or rewrite such a definition; on the other hand, it is automatically expanded during computation, whereas expanding the equation ``En`` requires explicit rewriting. The use of this equation name generation option with a ``case`` or an ``elim`` tactic changes the status of the first :token:`i_item`, in order to deal with the possible parameters of the constants introduced. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test (a b :nat) : a <> b. case E : a => [|n]. If the user does not provide a branching :token:`i_item` as first :token:`i_item`, or if the :token:`i_item` does not provide enough names for the arguments of a constructor, then the constants generated are introduced under fresh |SSR| names. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test (a b :nat) : a <> b. case E : a => H. Show 2. Combining the generation of named equations mechanism with the :tacn:`case` tactic strengthens the power of a case analysis. On the other hand, when combined with the :tacn:`elim` tactic, this feature is mostly useful for debug purposes, to trace the values of decomposed parameters and pinpoint failing branches. .. _type_families_ssr: Type families ~~~~~~~~~~~~~ When the top assumption of a goal has an inductive type, two specific operations are possible: the case analysis performed by the :tacn:`case` tactic, and the application of an induction principle, performed by the :tacn:`elim` tactic. When this top assumption has an inductive type, which is moreover an instance of a type family, Rocq may need help from the user to specify which occurrences of the parameters of the type should be substituted. .. tacv:: case: {+ @d_item } / {+ @d_item } elim: {+ @d_item } / {+ @d_item } A specific ``/`` switch indicates the type family parameters of the type of a :token:`d_item` immediately following this ``/`` switch. The :token:`d_item` on the right side of the ``/`` switch are discharged as described in Section :ref:`discharge_ssr`. The case analysis or elimination will be done on the type of the top assumption after these discharge operations. Every :token:`d_item` preceding the ``/`` is interpreted as an argument of this type, which should be an instance of an inductive type family. These terms are not actually generalized, but rather selected for substitution. Occurrence switches can be used to restrict the substitution. If a term is left completely implicit (e.g., writing just ``_``), then a pattern is inferred by looking at the type of the top assumption. This allows for the compact syntax: .. rocqdoc:: case: {2}_ / eqP. where ``_`` is interpreted as ``(_ == _)``, since ``eqP T a b : reflect (a = b) (a == b)`` and ``reflect`` is a type family with one index. Moreover, if the :token:`d_item` list is too short, it is padded with an initial sequence of ``_`` of the right length. .. example:: Here is a small example on lists. We define first a function that adds an element at the end of a given list. .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all From Corelib Require Import ListDef. Section LastCases. Variable A : Type. Implicit Type l : list A. Fixpoint add_last a l : list A := match l with | nil => a :: nil | hd :: tl => hd :: (add_last a tl) end. Then we define an inductive predicate for case analysis on lists according to their last element: .. rocqtop:: all Inductive last_spec : list A -> Type := | LastSeq0 : last_spec nil | LastAdd s x : last_spec (add_last x s). Theorem lastP : forall l : list A, last_spec l. Admitted. We are now ready to use ``lastP`` in conjunction with ``case``. .. rocqtop:: all Lemma test l : (length l) * 2 = length (l ++ l). case: (lastP l). Applied to the same goal, the tactic ``case: l / (lastP l)`` generates the same subgoals, but ``l`` has been cleared from both contexts: .. rocqtop:: all restart case: l / (lastP l). Again applied to the same goal: .. rocqtop:: all restart abort case: {1 3}l / (lastP l). Note that the selected occurrences on the left of the ``/`` switch have been substituted with ``l`` instead of being affected by the case analysis. The equation name generation feature combined with a type family ``/`` switch generates an equation for the *first* dependent :token:`d_item` specified by the user. Again starting with the above goal, the command: .. example:: .. rocqtop:: all Lemma test l : (length l) * 2 = length (l ++ l). case E: {1 3}l / (lastP l) => [|s x]. Show 2. There must be at least one :token:`d_item` to the left of the ``/`` switch; this prevents any confusion with the view feature. However, the :token:`d_item` to the right of the ``/`` are optional, and if they are omitted, the first assumption provides the instance of the type family. The equation always refers to the first :token:`d_item` in the actual tactic call, before any padding with initial ``_``. Thus, if an inductive type has two family parameters, it is possible to have |SSR| generate an equation for the second one by omitting the pattern for the first; note however that this will fail if the type of the second parameter depends on the value of the first parameter. Control flow ------------ .. _indentation_ssr: Indentation and bullets ~~~~~~~~~~~~~~~~~~~~~~~ A linear development of Rocq scripts gives little information on the structure of the proof. In addition, replaying a proof after some changes in the statement to be proved will usually not display information to distinguish between the various branches of case analysis for instance. To help the user in this organization of the proof script at development time, |SSR| provides some bullets to highlight the structure of branching proofs. The available bullets are ``-``, ``+`` and ``*``. Combined with tabulation, this lets us highlight four nested levels of branching; the most we have ever needed is three. Indeed, the use of β€œsimpl and closing” switches, of terminators (see Section :ref:`terminators_ssr`) and selectors (see Section :ref:`selectors_ssr`) is powerful enough to avoid most of the time more than two levels of indentation. Here is a fragment of such a structured script:: case E1: (abezoutn _ _) => [[| k1] [| k2]]. - rewrite !muln0 !gexpn0 mulg1 => H1. move/eqP: (sym_equal F0); rewrite -H1 orderg1 eqn_mul1. by case/andP; move/eqP. - rewrite muln0 gexpn0 mulg1 => H1. have F1: t %| t * S k2.+1 - 1. apply: (@dvdn_trans (orderg x)); first by rewrite F0; exact: dvdn_mull. rewrite orderg_dvd; apply/eqP; apply: (mulgI x). rewrite -{1}(gexpn1 x) mulg1 gexpn_add leq_add_sub //. by move: P1; case t. rewrite dvdn_subr in F1; last by exact: dvdn_mulr. + rewrite H1 F0 -{2}(muln1 (p ^ l)); congr (_ * _). by apply/eqP; rewrite -dvdn1. + by move: P1; case: (t) => [| [| s1]]. - rewrite muln0 gexpn0 mul1g => H1. ... .. _terminators_ssr: Terminators ~~~~~~~~~~~ To further structure scripts, |SSR| supplies *terminating* tacticals to explicitly close off tactics. When replaying scripts, we then have the nice property that an error immediately occurs when a closed tactic fails to prove its subgoal. It is hence recommended practice that the proof of any subgoal should end with a tactic that *fails if it does not solve the current goal*, like :tacn:`discriminate`, :tacn:`contradiction` or :tacn:`assumption`. In fact, |SSR| provides a generic tactical that turns any tactic into a closing one (similar to :tacn:`now`). Its general syntax is: .. tacn:: by @tactic :name: by :undocumented: The Ltac expression :n:`by [@tactic | @tactic | …]` is equivalent to :n:`do [done | by @tactic | by @tactic | …]`, which corresponds to the standard Ltac expression :n:`first [done | @tactic; done | @tactic; done | …]`. In the script provided as example in Section :ref:`indentation_ssr`, the paragraph corresponding to each sub-case ends with a tactic line prefixed with a ``by``, like in: .. rocqdoc:: by apply/eqP; rewrite -dvdn1. .. tacn:: done :name: done The :tacn:`by` tactical is implemented using the user-defined, and extensible, :tacn:`done` tactic. This :tacn:`done` tactic tries to solve the current goal by some trivial means and fails if it doesn’t succeed. Indeed, the tactic expression :n:`by @tactic` is equivalent to :n:`@tactic; done`. Conversely, the tactic ``by [ ]`` is equivalent to :tacn:`done`. The default implementation of the :tacn:`done` tactic, in the ``ssreflect.v`` file, is: .. rocqdoc:: Ltac done := trivial; hnf; intros; solve [ do ![solve [trivial | apply: sym_equal; trivial] | discriminate | contradiction | split] | match goal with H : ~ _ |- _ => solve [case H; trivial] end ]. The iterator tactical ``do`` is presented in Section :ref:`iteration_ssr`. This tactic can be customized by the user, for instance to include an :tacn:`auto` tactic. A natural and common way of closing a goal is to apply a lemma that is the exact one needed for the goal to be solved. The defective form of the tactic: .. rocqdoc:: exact. is equivalent to: .. rocqdoc:: do [done | by move=> top; apply top]. where ``top`` is a fresh name assigned to the top assumption of the goal. This applied form is supported by the ``:`` discharge tactical, and the tactic: .. rocqdoc:: exact: MyLemma. is equivalent to: .. rocqdoc:: by apply: MyLemma. (see Section :ref:`discharge_ssr` for the documentation of the apply: combination). .. warning:: The list of tactics (possibly chained by semicolons) that follows the ``by`` keyword is considered to be a parenthesized block applied to the current goal. Hence for example if the tactic: .. rocqdoc:: by rewrite my_lemma1. succeeds, then the tactic: .. rocqdoc:: by rewrite my_lemma1; apply my_lemma2. usually fails since it is equivalent to: .. rocqdoc:: by (rewrite my_lemma1; apply my_lemma2). .. _selectors_ssr: Selectors ~~~~~~~~~ .. tacn:: last first :name: last; first (ssreflect) When composing tactics, the two tacticals ``first`` and ``last`` let the user restrict the application of a tactic to only one of the subgoals generated by the previous tactic. This covers the frequent cases where a tactic generates two subgoals one of which can be easily disposed of. This is another powerful way of linearization of scripts, since it happens very often that a trivial subgoal can be solved in a less than one line tactic. For instance, :n:`@tactic ; last by @tactic` tries to solve the last subgoal generated by the first tactic using the given second tactic, and fails if it does not succeed. Its analogue :n:`@tactic ; first by @tactic` tries to solve the first subgoal generated by the first tactic using the second given tactic, and fails if it does not succeed. |SSR| also offers an extension of this facility, by supplying tactics to *permute* the subgoals generated by a tactic. .. tacv:: last first first last :name: last first; first last These two equivalent tactics invert the order of the subgoals in focus. .. tacv:: last @natural first If :token:`natural`\'s value is :math:`k`, this tactic rotates the :math:`n` subgoals :math:`G_1` , …, :math:`G_n` in focus. Subgoal :math:`G_{n + 1 βˆ’ k}` becomes the first, and the circular order of subgoals remains unchanged. .. tacn:: first @natural last :name: first (ssreflect) If :token:`natural`\'s value is :math:`k`, this tactic rotates the :math:`n` subgoals :math:`G_1` , …, :math:`G_n` in focus. Subgoal :math:`G_{k + 1 \bmod n}` becomes the first, and the circular order of subgoals remains unchanged. Finally, the tactics ``last`` and ``first`` combine with the branching syntax of Ltac: if the tactic generates n subgoals on a given goal, then the tactic .. rocqdoc:: tactic ; last k [ tactic1 |…| tacticm ] || tacticn. applies ``tactic1`` to the :math:`nβˆ’k+1`\-th goal, … ``tacticm`` to the :math:`nβˆ’k+m`\-th goal and ``tacticn`` to the others. .. example:: Here is a small example on lists. We define first a function that adds an element at the end of a given list. .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Inductive test : nat -> Prop := | C1 n of n = 1 : test n | C2 n of n = 2 : test n | C3 n of n = 3 : test n | C4 n of n = 4 : test n. Lemma example n (t : test n) : True. case: t; last 2 [move=> k| move=> l]; idtac. .. _iteration_ssr: Iteration ~~~~~~~~~ .. tacn:: do {? @mult } {| @tactic | [ {+| @tactic } ] } :name: do (ssreflect) This tactical offers an accurate control on the repetition of tactics. :token:`mult` is a *multiplier*. Brackets can only be omitted if a single tactic is given *and* a multiplier is present. A tactic of the form: .. rocqdoc:: do [ tactic 1 | … | tactic n ]. is equivalent to the standard Ltac expression: .. rocqdoc:: first [ tactic 1 | … | tactic n ]. The optional multiplier :token:`mult` specifies how many times the action of ``tactic`` should be repeated on the current subgoal. There are four kinds of multipliers: .. prodn:: mult ::= {| @natural ! | ! | @natural ? | ? } Their meaning is as follows. + With ``n!``, the step tactic is repeated exactly ``n`` times (where ``n`` is a positive integer argument). + With ``!``, the step tactic is repeated as many times as possible, and done at least once. + With ``?``, the step tactic is repeated as many times as possible, optionally. + Finally, with ``n?``, the step tactic is repeated up to ``n`` times, optionally. For instance, the tactic: .. rocqdoc:: tactic; do 1? rewrite mult_comm. rewrites at most one time the lemma ``mult_comm`` in all the subgoals generated by tactic, whereas the tactic: .. rocqdoc:: tactic; do 2! rewrite mult_comm. rewrites exactly two times the lemma ``mult_comm`` in all the subgoals generated by ``tactic``, and fails if this rewrite is not possible in some subgoal. Note that the combination of multipliers and rewrite is so often used that multipliers are in fact integrated to the syntax of the |SSR| rewrite tactic, see Section :ref:`rewriting_ssr`. .. _localization_ssr: Localization ~~~~~~~~~~~~ In Sections :ref:`basic_localization_ssr` and :ref:`bookkeeping_ssr`, we have already presented the *localization* tactical ``in``, whose general syntax is: .. tacn:: @tactic in {+ @ident} {? * } :name: in :undocumented: where :token:`ident` is a name in the context. On the left side of ``in``, :token:`tactic` can be ``move``, ``case``, ``elim``, ``rewrite``, ``set``, or any tactic formed with the general iteration tactical ``do`` (see Section :ref:`iteration_ssr`). The operation described by the tactic is performed in the facts listed after ``in`` and in the goal if a ``*`` ends the list of names. The ``in`` tactical successively: + generalizes the selected hypotheses, possibly β€œprotecting” the goal if ``*`` is not present; + performs :token:`tactic`, on the obtained goal; + reintroduces the generalized facts, under the same names. This defective form of the ``do`` tactical is useful to avoid clashes between standard Ltac ``in`` and the |SSR| tactical in. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Ltac mytac H := rewrite H. Lemma test x y (H1 : x = y) (H2 : y = 3) : x + y = 6. do [mytac H2] in H1 *. the last tactic rewrites the hypothesis ``H2 : y = 3`` both in ``H1 : x = y`` and in the goal ``x + y = 6``. By default, ``in`` keeps the body of local definitions. To erase the body of a local definition during the generalization phase, the name of the local definition must be written between parentheses, like in ``rewrite H in H1 (def_n) H2.`` .. tacv:: @tactic in {+ {| @clear_switch | {? @}@ident | ( @ident ) | ( {? @}@ident := @c_pattern ) } } {? * } This is the most general form of the ``in`` tactical. In its simplest form, the last option lets one rename hypotheses that can’t be cleared (like section variables). For example, ``(y := x)`` generalizes over ``x`` and reintroduces the generalized variable under the name ``y`` (and does not clear ``x``). For a more precise description of this form of localization, refer to :ref:`advanced_generalization_ssr`. .. _structure_ssr: Structure ~~~~~~~~~ Forward reasoning structures the script by explicitly specifying some assumptions to be added to the proof context. It is closely associated with the declarative style of proof, since an extensive use of these highlighted statements makes the script closer to a (very detailed) textbook proof. Forward chaining tactics allow to state an intermediate lemma and start a piece of script dedicated to the proof of this statement. The use of closing tactics (see Section :ref:`terminators_ssr`) and of indentation makes syntactically explicit the portion of the script building the proof of the intermediate statement. The have tactic. ```````````````` .. tacn:: have : @term :name: have This is the main |SSR| forward reasoning tactic. It can be used in two modes: one starts a new (sub)proof for an intermediate result in the main proof, and the other provides explicitly a proof term for this intermediate step. This tactic supports open syntax for :token:`term`. Applied to a goal ``G``, it generates a first subgoal requiring a proof of :token:`term` in the context of ``G``. The second generated subgoal is of the form :n:`term -> G`, where term becomes the new top assumption, instead of being introduced with a fresh name. At the proof-term level, the ``have`` tactic creates a Ξ² redex, and introduces the lemma under a fresh name, automatically chosen. Like in the case of the :n:`pose (ssreflect)` tactic (see Section :ref:`definitions_ssr`), the types of the holes are abstracted in term. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : True. have: _ * 0 = 0. The invocation of ``have`` is equivalent to: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Lemma test : True. .. rocqtop:: all have: forall n : nat, n * 0 = 0. The ``have`` tactic also enjoys the same abstraction mechanism as the :tacn:`pose (ssreflect)` tactic for the non-inferred implicit arguments. For instance, the tactic: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Lemma test : True. .. rocqtop:: all have: forall x y, (x, y) = (x, y + 0). opens a new subgoal where the type of ``x`` is quantified. The behavior of the defective have tactic makes it possible to generalize it in the following general construction: .. tacn:: have {* @i_item } {? @i_pattern } {? {| @s_item | {+ @ssr_binder } } } {? : @term } {? {| := @term | by @tactic } } :undocumented: Open syntax is supported for both :token:`term`. For the description of :token:`i_item` and :token:`s_item`, see Section :ref:`introduction_ssr`. The first mode of the have tactic, which opens a sub-proof for an intermediate result, uses tactics of the form: .. tacv:: have @clear_switch @i_item : @term by @tactic :undocumented: which behaves like: .. rocqdoc:: have: term ; first by tactic. move=> clear_switch i_item. Note that the :token:`clear_switch` *precedes* the :token:`i_item`, which allows to reuse a name of the context, possibly used by the proof of the assumption, to introduce the new assumption itself. The ``by`` feature is especially convenient when the proof script of the statement is very short, basically when it fits in one line like in: .. rocqdoc:: have H23 : 3 + 2 = 2 + 3 by rewrite addnC. The possibility of using :token:`i_item` supplies a very concise syntax for the further use of the intermediate step. For instance, .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test a : 3 * a - 1 = a. have -> : forall x, x * a = a. Note how the second goal was rewritten using the stated equality. Also note that in this last subgoal, the intermediate result does not appear in the context. Thanks to the deferred execution of clears, the following idiom is also supported (assuming x occurs in the goal only): .. rocqdoc:: have {x} -> : x = y. Another frequent use of the intro patterns combined with ``have`` is the destruction of existential assumptions like in the tactic: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : True. have [x Px]: exists x : nat, x > 0; last first. An alternative use of the ``have`` tactic is to provide the explicit proof term for the intermediate lemma, using tactics of the form: .. tacv:: have {? @ident } := @term This tactic creates a new assumption of type the type of :token:`term`. If the optional :token:`ident` is present, this assumption is introduced under the name :token:`ident`. Note that the body of the constant is lost for the user. Again, non-inferred implicit arguments and explicit holes are abstracted. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test : True. have H := forall x, (x, x) = (x, x). adds to the context ``H : Type -> Prop.`` This is a schematic example, but the feature is specially useful when the proof term to give involves for instance a lemma with some hidden implicit arguments. After the :token:`i_pattern`, a list of binders is allowed. The following example requires the mathcomp and mczify libraries. .. example:: .. rocqtop:: reset none warn extra-mathcomp extra-mczify From mathcomp Require Import ssreflect ssrfun ssrbool ssrnat zify. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all extra-mathcomp extra-mczify Lemma test : True. have H x (y : nat) : 2 * x + y = x + x + y by lia. A proof term provided after ``:=`` can mention these bound variables (that are automatically introduced with the given names). Since the :token:`i_pattern` can be omitted, to avoid ambiguity, bound variables can be surrounded with parentheses even if no type is specified: .. rocqtop:: all restart extra-mathcomp extra-mczify have (x) : 2 * x = x + x by lia. The :token:`i_item` and :token:`s_item` can be used to interpret the asserted hypothesis with views (see Section :ref:`views_and_reflection_ssr`) or simplify the resulting goals. The :tacn:`have` tactic also supports a ``suff`` modifier that allows for asserting that a given statement implies the current goal without copying the goal itself. .. example:: .. rocqtop:: all restart abort extra-mathcomp extra-mczify have suff H : 2 + 2 = 3; last first. Note that H is introduced in the second goal. The ``suff`` modifier is not compatible with the presence of a list of binders. .. _generating_let_ssr: Generating let in context entries with have ``````````````````````````````````````````` Since |SSR| 1.5, the :tacn:`have` tactic supports a β€œtransparent” modifier to generate ``let in`` context entries: the ``@`` symbol in front of the context entry name. .. example:: .. rocqtop:: none Set Printing Depth 15. .. rocqtop:: all abort extra-mathcomp Inductive Ord n := Sub x of x < n. Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n"). Arguments Sub {_} _ _. Lemma test n m (H : m + 1 < n) : True. have @i : 'I_n by apply: (Sub m); lia. Note that the subterm produced by :tacn:`lia` is in general huge and uninteresting, and hence one may want to hide it. For this purpose the ``[: name]`` intro pattern and the tactic ``abstract`` (see :ref:`abstract_ssr`) are provided. .. example:: .. rocqtop:: all abort extra-mathcomp Lemma test n m (H : m + 1 < n) : True. have [:pm] @i : 'I_n by apply: (Sub m); abstract: pm; lia. The type of ``pm`` can be cleaned up by its annotation ``(*1*)`` by just simplifying it. The annotations are there for technical reasons only. When intro patterns for abstract constants are used in conjunction with`` have`` and an explicit term, they must be used as follows: .. example:: .. rocqtop:: all abort extra-mathcomp Lemma test n m (H : m + 1 < n) : True. have [:pm] @i : 'I_n := Sub m pm. by lia. In this case, the abstract constant ``pm`` is assigned by using it in the term that follows ``:=`` and its corresponding goal is left to be solved. Goals corresponding to intro patterns for abstract constants are opened in the order in which the abstract constants are declared (not in the β€œorder” in which they are used in the term). Note that abstract constants do respect scopes. Hence, if a variable is declared after their introduction, it has to be properly generalized (i.e., explicitly passed to the abstract constant when one makes use of it). .. example:: .. rocqtop:: all abort extra-mathcomp Lemma test n m (H : m + 1 < n) : True. have [:pm] @i k : 'I_(n+k) by apply: (Sub m); abstract: pm k; lia. Last, notice that the use of intro patterns for abstract constants is orthogonal to the transparent flag ``@`` for ``have``. The have tactic and typeclass resolution ``````````````````````````````````````````` Since |SSR| 1.5, the ``have`` tactic behaves as follows with respect to typeclass inference. .. rocqtop:: reset none From Corelib Require Import ssreflect. Axiom ty : Type. Axiom t : ty. Goal True. .. rocqtop:: all have foo : ty. Full inference for ``ty``. The first subgoal demands a proof of such instantiated statement. .. A strange bug prevents using the coqtop directive here .. rocqdoc:: have foo : ty := . No inference for ``ty``. Unresolved instances are quantified in ``ty``. The first subgoal demands a proof of such quantified statement. Note that no proof term follows ``:=``; hence two subgoals are generated. .. rocqtop:: all restart have foo : ty := t. No inference for ``ty`` and ``t``. .. rocqtop:: all restart abort have foo := t. No inference for ``t``. Unresolved instances are quantified in the (inferred) type of ``t`` and abstracted in ``t``. .. flag:: SsrHave NoTCResolution This :term:`flag` restores the behavior of |SSR| 1.4 and below (never resolve typeclasses). Variants: the suff and wlog tactics ``````````````````````````````````` As is often the case in mathematical textbooks, forward reasoning may be used in slightly different variants. One of these variants is to show that the intermediate step L easily implies the initial goal G. By easily we mean here that the proof of L β‡’ G is shorter than the one of L itself. This kind of reasoning step usually starts with: β€œIt suffices to show that …”. This is such a frequent way of reasoning that |SSR| has a variant of the ``have`` tactic called ``suffices`` (whose abridged name is ``suff``). The ``have`` and ``suff`` tactics are equivalent and have the same syntax but: + the order of the generated subgoals is inverted; + the optional clear item is still performed in the *second* branch, which means that the tactic: .. rocqdoc:: suff {H} H : forall x : nat, x >= 0. fails if the context of the current goal indeed contains an assumption named ``H``. The rationale of this clearing policy is to make possible β€œtrivial” refinements of an assumption, without changing its name in the main branch of the reasoning. The ``have`` modifier can follow the ``suff`` tactic. .. example:: .. rocqtop:: none Axioms G P : Prop. .. rocqtop:: all abort Lemma test : G. suff have H : P. Note that, in contrast with ``have suff``, the name H has been introduced in the first goal. Another useful construct is reduction, showing that a particular case is in fact general enough to prove a general property. This kind of reasoning step usually starts with: β€œWithout loss of generality, we can suppose that …”. Formally, this corresponds to the proof of a goal ``G`` by introducing a cut: ``wlog_statement -> G``. Hence the user shall provide a proof for both ``(wlog_statement -> G) -> G`` and ``wlog_statement -> G``. However, such cuts are usually rather painful to perform by hand, because the statement ``wlog_statement`` is tedious to write by hand, and sometimes even to read. |SSR| implements this kind of reasoning step through the :tacn:`without loss` tactic, whose short name is :tacn:`wlog`. It offers support to describe the shape of the cut statements, by providing the simplifying hypothesis and by pointing at the elements of the initial goals that should be generalized. The general syntax of without loss is: .. tacn:: wlog {? suff } {? @clear_switch } {? @i_item } : {* @ident } / @term without loss {? suff } {? @clear_switch } {? @i_item } : {* @ident } / @term :name: wlog; without loss :undocumented: where each :token:`ident` is a constant in the context of the goal. Open syntax is supported for :token:`term`. In its defective form: .. tacv:: wlog: / @term without loss: / @term :undocumented: on a goal G, it creates two subgoals: a first one to prove the formula (term -> G) -> G and a second one to prove the formula term -> G. If the optional list of :token:`ident` is present on the left side of ``/``, these constants are generalized in the premise (term -> G) of the first subgoal. By default bodies of local definitions are erased. This behavior can be inhibited by prefixing the name of the local definition with the ``@`` character. In the second subgoal, the tactic: .. rocqdoc:: move=> clear_switch i_item. is performed if at least one of these optional switches is present in the :tacn:`wlog` tactic. The :tacn:`wlog` tactic is specially useful when a symmetry argument simplifies a proof. Here is an example showing the beginning of the proof that quotient and reminder of natural number euclidean division are unique. The following example requires the mathcomp and mczify libraries. .. example:: .. rocqtop:: reset none warn extra-mathcomp From mathcomp Require Import ssreflect ssrfun ssrbool ssrnat. .. rocqtop:: all extra-mathcomp Lemma quo_rem_unicity d q1 q2 r1 r2 : q1*d + r1 = q2*d + r2 -> r1 < d -> r2 < d -> (q1, r1) = (q2, r2). wlog: q1 q2 r1 r2 / q1 <= q2. by case: (leqP q1 q2); last symmetry; eauto. The ``wlog suff`` variant is simpler, since it cuts ``wlog_statement`` instead of ``wlog_statement -> G``. It thus opens the goals ``wlog_statement -> G`` and ``wlog_statement``. In its simplest form, the ``generally have : …`` tactic is equivalent to ``wlog suff : …`` followed by ``last first``. When the ``have`` tactic is used with the ``generally`` (or ``gen``) modifier, it accepts an extra identifier followed by a comma before the usual intro pattern. The identifier will name the new hypothesis in its more general form, while the intro pattern will be used to process its instance. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrfun ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom P : nat -> Prop. Axioms eqn leqn : nat -> nat -> bool. Declare Scope this_scope. Notation "a != b" := (eqn a b) (at level 70) : this_scope. Notation "a <= b" := (leqn a b) (at level 70) : this_scope. Open Scope this_scope. .. rocqtop:: all Lemma simple n (ngt0 : 0 < n ) : P n. gen have ltnV, /andP[nge0 neq0] : n ngt0 / (0 <= n) && (n != 0); last first. .. _advanced_generalization_ssr: Advanced generalization +++++++++++++++++++++++ The complete syntax for the items on the left hand side of the ``/`` separator is the following one: .. tacv:: wlog … : {? {| @clear_switch | {? @}@ident | ( {? @}@ident := @c_pattern) } } / @term :undocumented: Clear operations are intertwined with generalization operations. This helps in particular avoiding dependency issues while generalizing some facts. If an :token:`ident` is prefixed with the ``@`` mark, then a let-in redex is created, which keeps track of its body (if any). The syntax :n:`(@ident := @c_pattern)` allows to generalize an arbitrary term using a given name. Note that its simplest form ``(x := y)`` is just a renaming of ``y`` into ``x``. In particular, this can be useful in order to simulate the generalization of a section variable, otherwise not allowed. Indeed, renaming does not require the original variable to be cleared. The syntax ``(@x := y)`` generates a let-in abstraction but with the following caveat: ``x`` will not bind ``y``, but its body, whenever ``y`` can be unfolded. This covers the case of both local and global definitions, as illustrated in the following example. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Section Test. Variable x : nat. Definition addx z := z + x. Lemma test : x <= addx x. wlog H : (y := x) (@twoy := addx x) / twoy = 2 * y. To avoid unfolding the term captured by the pattern ``add x``, one can use the pattern ``id (addx x)``, which would produce the following first subgoal .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Variable x : nat. Definition addx z := z + x. Lemma test : x <= addx x. .. rocqtop:: all wlog H : (y := x) (@twoy := id (addx x)) / twoy = 2 * y. .. _rewriting_ssr: Rewriting --------- The generalized use of reflection implies that most of the intermediate results handled are properties of effectively computable functions. The most efficient means of establishing such results are computation and simplification of expressions involving such functions, i.e., rewriting. |SSR| therefore includes an extended ``rewrite`` tactic that unifies and combines most of the rewriting functionalities. An extended rewrite tactic ~~~~~~~~~~~~~~~~~~~~~~~~~~ The main features of the rewrite tactic are: + it can perform an entire series of such operations in any subset of the goal and/or context; + it allows to perform rewriting, simplifications, folding/unfolding of definitions, closing of goals; + several rewriting operations can be chained in a single tactic; + control over the occurrence at which rewriting is to be performed is significantly enhanced. The general form of an |SSR| rewrite tactic is: .. tacn:: rewrite {+ @rstep } :name: rewrite (ssreflect) :undocumented: The combination of a rewrite tactic with the ``in`` tactical (see Section :ref:`localization_ssr`) performs rewriting in both the context and the goal. A rewrite step :token:`rstep` has the general form: .. prodn:: rstep ::= {? @r_prefix } @r_item .. prodn:: r_prefix ::= {? - } {? @mult } {? {| @occ_switch | @clear_switch } } {? [ @r_pattern ] } .. prodn:: r_pattern ::= {| @term | in {? @ident in } @term | {| @term in | @term as } @ident in @term } .. prodn:: r_item ::= {| {? / } @term | @s_item } An :token:`r_prefix` contains annotations to qualify where and how the rewrite operation should be performed. + The optional initial ``-`` indicates the direction of the rewriting of :token:`r_item`: if present, the direction is right-to-left and it is left-to-right otherwise. + The multiplier :token:`mult` (see Section :ref:`iteration_ssr`) specifies if and how the rewrite operation should be repeated. + A rewrite operation matches the occurrences of a *rewrite pattern*, and replaces these occurrences by another term, according to the given :token:`r_item`. The optional *redex switch* ``[r_pattern]``, which should always be surrounded by brackets, gives explicitly this rewrite 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 :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 that 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 and 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. A :token:`r_item` can be one of the following. + A *simplification* :token:`r_item`, represented by a :token:`s_item` (see Section :ref:`introduction_ssr`). Simplification operations are intertwined with the possible other rewrite operations specified by the list of :token:`r_item`. + A *folding/unfolding* :token:`r_item`. The tactic ``rewrite /term`` unfolds the :term:`head constant` of ``term`` in every occurrence of the first matching of ``term`` in the goal. In particular, if ``my_def`` is a (local or global) defined constant, the tactic ``rewrite /my_def.`` is analogous to: ``unfold my_def``. Conversely, ``rewrite -/my_def.`` is equivalent to ``fold my_def``. When an unfold :token:`r_item` is combined with a redex pattern, a conversion operation is performed. A tactic of the form ``rewrite -[term1]/term2.`` is equivalent to ``change term1 with term2.`` If ``term2`` is a single constant and ``term1`` head symbol is not ``term2``, then the head symbol of ``term1`` is repeatedly unfolded until ``term2`` appears. + A :token:`term` can be: + a term whose type has the form: ``forall (x1 : A1 )…(xn : An ), eq term1 term2``, where ``eq`` is the Leibniz equality or a registered setoid equality; + a list of terms ``(t1 ,…,tn)``, each ``ti`` having a type as above, and the tactic ``rewrite r_prefix (t1 ,…,tn ).`` is equivalent to ``do [rewrite r_prefix t1 | … | rewrite r_prefix tn ].``; + an anonymous rewrite lemma ``(_ : term)``, where ``term`` has a type as above. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all abort Definition double x := x + x. Definition ddouble x := double (double x). Lemma test x : ddouble x = 4 * x. rewrite [ddouble _]/double. .. warning:: The |SSR| terms containing holes are *not* typed as abstractions in this context. Hence the following script fails. .. rocqtop:: all Definition f := fun x y => x + y. Lemma test x y : x + y = f y x. .. rocqtop:: all fail rewrite -[f y]/(y + _). but the following script succeeds .. rocqtop:: all rewrite -[f y x]/(y + _). .. flag:: SsrOldRewriteGoalsOrder Controls the order in which generated subgoals (side conditions) are added to the proof context. The :term:`flag` is off by default, which puts subgoals generated by conditional rules first, followed by the main goal. When it is on, the main goal appears first. If your proofs are organized to complete proving the main goal before side conditions, turning the flag on will save you from having to add :tacn:`last first` tactics that would be needed to keep the main goal as the currently focused goal. Remarks and examples ~~~~~~~~~~~~~~~~~~~~ Rewrite redex selection ``````````````````````` The general strategy of |SSR| is to grasp as many redexes as possible and to let the user select the ones to be rewritten thanks to the improved syntax for the control of rewriting. This may be a source of incompatibilities between the two rewrite tactics. In a rewrite tactic of the form: .. rocqdoc:: rewrite occ_switch [term1]term2. ``term1`` is the explicit rewrite redex and ``term2`` is the rewrite rule. This execution of this tactic unfolds as follows. + First ``term1`` and ``term2`` are Ξ²ΞΉ normalized. Then ``term2`` is put in head normal form if the Leibniz equality constructor ``eq`` is not the head symbol. This may involve ΞΆ reductions. + Then, the matching algorithm (see Section :ref:`abbreviations_ssr`) determines the first subterm of the goal matching the rewrite pattern. The rewrite pattern is given by ``term1``, if an explicit redex pattern switch is provided, or by the type of ``term2`` otherwise. However, matching skips over matches that would lead to trivial rewrites. All the occurrences of this subterm in the goal are candidates for rewriting. + Then only the occurrences coded by :token:`occ_switch` (see again Section :ref:`abbreviations_ssr`) are finally selected for rewriting. + The left-hand side of ``term2`` is unified with the subterm found by the matching algorithm, and if this succeeds, all the selected occurrences in the goal are replaced by the right-hand side of ``term2``. + Finally the goal is Ξ²ΞΉ normalized. In the case ``term2`` is a list of terms, the first top-down (in the goal) left-to-right (in the list) matching rule gets selected. Chained rewrite steps ````````````````````` The possibility to chain rewrite operations in a single tactic makes scripts more compact and gathers in a single command line a bunch of surgical operations that would be described by a one sentence in a pen and paper proof. Performing rewrite and simplification operations in a single tactic enhances significantly the concision of scripts. For instance the tactic: .. rocqdoc:: rewrite /my_def {2}[f _]/= my_eq //=. unfolds ``my_def`` in the goal, simplifies the second occurrence of the first subterm matching pattern ``[f _]``, rewrites ``my_eq``, simplifies the goals and closes trivial goals. Here are some concrete examples of chained rewrite operations, in the proof of basic results on natural numbers arithmetic. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Axiom addn0 : forall m, m + 0 = m. Axiom addnS : forall m n, m + S n = S (m + n). Axiom addSnnS : forall m n, S m + n = m + S n. Lemma addnCA m n p : m + (n + p) = n + (m + p). by elim: m p => [ | m Hrec] p; rewrite ?addSnnS -?addnS. Qed. Lemma addnC n m : m + n = n + m. by rewrite -{1}[n]addn0 addnCA addn0. Qed. Note the use of the ``?`` switch for parallel rewrite operations in the proof of ``addnCA``. Explicit redex switches are matched first ````````````````````````````````````````` If an :token:`r_prefix` involves a *redex switch*, the first step is to find a subterm matching this redex pattern, independently from the left-hand side of the equality the user wants to rewrite. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test (H : forall t u, t + u = u + t) x y : x + y = y + x. rewrite [y + _]H. Note that if this first pattern matching is not compatible with the :token:`r_item`, the rewrite fails, even if the goal contains a correct redex matching both the redex switch and the left-hand side of the equality. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test (H : forall t u, t + u * 0 = t) x y : x + y * 4 + 2 * 0 = x + 2 * 0. Fail rewrite [x + _]H. Indeed, the left-hand side of ``H`` does not match the redex identified by the pattern ``x + y * 4``. .. _ssr_rewrite_occ_switch: Occurrence switches and redex switches `````````````````````````````````````` .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y : x + y + 0 = x + y + y + 0 + 0 + (x + y + 0). rewrite {2}[_ + y + 0](_: forall z, z + 0 = z). The second subgoal is generated by the use of an anonymous lemma in 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``. Occurrence selection and repetition ``````````````````````````````````` Occurrence selection has priority over repetition switches. This means the repetition of a rewrite tactic specified by a multiplier will perform matching each time an elementary rewrite operation is performed. Repeated rewrite tactics apply to every subgoal generated by the previous tactic, including the previous instances of the repetition. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: all Lemma test x y (z : nat) : x + 1 = x + y + 1. rewrite 2!(_ : _ + 1 = z). This last tactic generates *three* subgoals because the second rewrite operation specified with the ``2!`` multiplier applies to the two subgoals generated by the first rewrite. Multi-rule rewriting ```````````````````` The rewrite tactic can be provided a *tuple* of rewrite rules, or more generally a tree of such rules, since this tuple can feature arbitrary inner parentheses. We call *multirule* such a generalized rewrite rule. This feature is of special interest when it is combined with multiplier switches, which makes the rewrite tactic iterate the rewrite operations prescribed by the rules on the current goal. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all abort Variables (a b c : nat). Hypothesis eqab : a = b. Hypothesis eqac : a = c. Lemma test : a = a. rewrite (eqab, eqac). Indeed, rule ``eqab`` is the first to apply among the ones gathered in the tuple passed to the rewrite tactic. This multirule ``(eqab, eqac)`` is actually a Rocq term and we can name it with a definition: .. rocqtop:: all Definition multi1 := (eqab, eqac). In this case, the tactic ``rewrite multi1`` is a synonym for ``rewrite (eqab, eqac)``. More precisely, a multirule rewrites the first subterm to which one of the rules applies in a left-to-right traversal of the goal, with the first rule from the multirule tree in left-to-right order. Matching is performed according to the algorithm described in Section :ref:`abbreviations_ssr`, but literal matches have priority. .. example:: .. rocqtop:: all abort Definition d := a. Hypotheses eqd0 : d = 0. Definition multi2 := (eqab, eqd0). Lemma test : d = b. rewrite multi2. Indeed, rule ``eqd0`` applies without unfolding the definition of ``d``. For repeated rewrites, the selection process is repeated anew. .. example:: .. rocqtop:: all abort Hypothesis eq_adda_b : forall x, x + a = b. Hypothesis eq_adda_c : forall x, x + a = c. Hypothesis eqb0 : b = 0. Definition multi3 := (eq_adda_b, eq_adda_c, eqb0). Lemma test : 1 + a = 12 + a. rewrite 2!multi3. It uses ``eq_adda_b`` then ``eqb0`` on the left-hand side only. Without the bound ``2``, one would obtain ``0 = 0``. The grouping of rules inside a multirule does not affect the selection strategy, but can make it easier to include one rule set in another or to (universally) quantify over the parameters of a subset of rules (as there is special code that will omit unnecessary quantifiers for rules that can be syntactically extracted). It is also possible to reverse the direction of a rule subset, using a special dedicated syntax: the tactic rewrite ``(=^~ multi1)`` is equivalent to ``rewrite multi1_rev``. .. example:: .. rocqtop:: all Hypothesis eqba : b = a. Hypothesis eqca : c = a. Definition multi1_rev := (eqba, eqca). except that the constants ``eqba``, ``eqab`` and ``mult1_rev`` have not been created. Rewriting with multirules is useful to implement simplification or transformation procedures, to be applied on terms of small to medium size. For instance, the library `ssrnat` (Mathematical Components library) provides two implementations for arithmetic operations on natural numbers: an elementary one and a tail recursive version, less inefficient but also less convenient for reasoning purposes. The library also provides one lemma per such operation, stating that both versions return the same values when applied to the same arguments: .. rocqdoc:: Lemma addE : add =2 addn. Lemma doubleE : double =1 doublen. Lemma add_mulE n m s : add_mul n m s = addn (muln n m) s. Lemma mulE : mul =2 muln. Lemma mul_expE m n p : mul_exp m n p = muln (expn m n) p. Lemma expE : exp =2 expn. Lemma oddE : odd =1 oddn. The operation on the left-hand side of each lemma is the efficient version, and the corresponding naive implementation is on the right-hand side. In order to reason conveniently on expressions involving the efficient operations, we gather all these rules in the definition ``trecE``: .. rocqdoc:: Definition trecE := (addE, (doubleE, oddE), (mulE, add_mulE, (expE, mul_expE))). The tactic ``rewrite !trecE.`` restores the naive version of each operation in a goal involving the efficient ones, e.g., for the purpose of a correctness proof. Wildcards vs abstractions ````````````````````````` The rewrite tactic supports :token:`r_item`\s containing holes. For example, in the tactic ``rewrite (_ : _ * 0 = 0).``, the term ``_ * 0 = 0`` is interpreted as ``forall n : nat, n * 0 = 0.`` Anyway this tactic is *not* equivalent to ``rewrite (_ : forall x, x * 0 = 0).``. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test y z : y * 0 + y * (z * 0) = 0. rewrite (_ : _ * 0 = 0). while the other tactic results in .. rocqtop:: all restart abort rewrite (_ : forall x, x * 0 = 0). The first tactic requires you to prove the instance of the (missing) lemma that was used, while the latter requires you prove the quantified form. When |SSR| rewrite fails on standard Rocq licit rewrite ```````````````````````````````````````````````````````` In a few cases, the |SSR| rewrite tactic fails rewriting some redexes that standard Rocq successfully rewrites. There are two main cases. + |SSR| never accepts to rewrite indeterminate patterns like: .. rocqdoc:: Lemma foo (x : unit) : x = tt. |SSR| will however accept the Ξ·ΞΆ expansion of this rule: .. rocqdoc:: Lemma fubar (x : unit) : (let u := x in u) = tt. + The standard rewrite tactic provided by Rocq uses a different algorithm to find instances of the rewrite rule. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variable g : nat -> nat. Definition f := g. Axiom H : forall x, g x = 0. Lemma test : f 3 + f 3 = f 6. (* we call the standard rewrite tactic here *) rewrite -> H. This rewriting is not possible in |SSR|, because there is no occurrence of the head symbol ``f`` of the rewrite rule in the goal. .. rocqtop:: all restart fail rewrite H. Rewriting with ``H`` first requires unfolding the occurrences of ``f`` where the substitution is to be performed (here there is a single such occurrence), using tactic ``rewrite /f`` (for a global replacement of ``f`` by ``g``) or ``rewrite pattern/f``, for a finer selection. .. rocqtop:: all restart rewrite /f H. Alternatively, one can override the pattern inferred from ``H`` .. rocqtop:: all restart rewrite [f _]H. Existential metavariables and rewriting ``````````````````````````````````````` The rewrite tactic will not instantiate existing existential metavariables when matching a redex pattern. If a rewrite rule generates a goal with new existential metavariables in the ``Prop`` sort, these will be generalized as for ``apply`` (see :ref:`apply_ssr`) and corresponding new goals will be generated. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrfun ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Set Warnings "-notation-overridden". .. rocqtop:: all abort Axiom leq : nat -> nat -> bool. Notation "m <= n" := (leq m n) : nat_scope. Notation "m < n" := (S m <= n) : nat_scope. Inductive Ord n := Sub x of x < n. Notation "'I_ n" := (Ord n) (at level 8, n at level 2, format "''I_' n"). Arguments Sub {_} _ _. Definition val n (i : 'I_n) := let: Sub a _ := i in a. Definition insub n x := if @idP (x < n) is ReflectT _ Px then Some (Sub x Px) else None. Axiom insubT : forall n x Px, insub n x = Some (Sub x Px). Lemma test (x : 'I_2) y : Some x = insub 2 y. rewrite insubT. Since the argument corresponding to ``Px`` is not supplied by the user, the resulting goal should be ``Some x = Some (Sub y ?Goal).`` Instead, |SSR| ``rewrite`` tactic hides the existential variable. As in :ref:`apply_ssr`, the ``ssrautoprop`` tactic is used to try to solve the existential variable. .. rocqtop:: all abort Lemma test (x : 'I_2) y (H : y < 2) : Some x = insub 2 y. rewrite insubT. As a temporary limitation, this behavior is available only if the rewriting rule is stated using Leibniz equality (as opposed to setoid relations). It will be extended to other rewriting relations in the future. .. _under_ssr: Rewriting under binders ~~~~~~~~~~~~~~~~~~~~~~~ Goals involving objects defined with higher-order functions often require "rewriting under binders". While setoid rewriting is a possible approach in this case, it is common to use regular rewriting along with dedicated extensionality lemmas. This may cause some practical issues during the development of the corresponding scripts, notably as we might be forced to provide the rewrite tactic with complete terms, as shown by the simple example below. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. .. rocqtop:: in Axiom subnn : forall n : nat, n - n = 0. Parameter map : (nat -> nat) -> list nat -> list nat. Parameter sumlist : list nat -> nat. Axiom eq_map : forall F1 F2 : nat -> nat, (forall n : nat, F1 n = F2 n) -> forall l : list nat, map F1 l = map F2 l. .. rocqtop:: all Lemma example_map l : sumlist (map (fun m => m - m) l) = 0. In this context, one cannot directly use ``eq_map``: .. rocqtop:: all fail rewrite eq_map. as we need to explicitly provide the non-inferable argument ``F2``, which corresponds here to the term we want to obtain *after* the rewriting step. In order to perform the rewrite step, one has to provide the term by hand as follows: .. rocqtop:: all abort rewrite (@eq_map _ (fun _ : nat => 0)). by move=> m; rewrite subnn. The :tacn:`under` tactic lets one perform the same operation in a more convenient way: .. rocqtop:: all abort Lemma example_map l : sumlist (map (fun m => m - m) l) = 0. under eq_map => m do rewrite subnn. The under tactic ```````````````` The convenience :tacn:`under` tactic supports the following syntax: .. tacn:: under {? @r_prefix } @term {? => {+ @i_item}} {? do {| @tactic | [ {*| @tactic } ] } } :name: under It operates under the context proved to be extensional by lemma :token:`term`. .. exn:: Incorrect number of tactics (expected N tactics, was given M). This error can occur when using the version with a ``do`` clause. The multiplier part of :token:`r_prefix` is not supported. We distinguish two modes: :ref:`interactive mode `, without a ``do`` clause, and :ref:`one-liner mode `, with a ``do`` clause, which are explained in more detail below. .. _under_interactive: Interactive mode ```````````````` Let us redo the running example in interactive mode. .. example:: .. rocqtop:: all abort Lemma example_map l : sumlist (map (fun m => m - m) l) = 0. under eq_map => m. rewrite subnn. over. The execution of the Ltac expression: :n:`under @term => [ @i_item__1 | … | @i_item__n ].` involves the following steps. 1. It performs a :n:`rewrite @term` without failing like in the first example with ``rewrite eq_map.``, but creating evars (see :tacn:`evar`). If :n:`term` is prefixed by a pattern or an occurrence selector, then the modifiers are honoured. 2. As an n-branch intro pattern is provided, :tacn:`under` checks that n+1 subgoals have been created. The last one is the main subgoal, while the other ones correspond to premises of the rewrite rule (such as ``forall n, F1 n = F2 n`` for ``eq_map``). 3. If so, :tacn:`under` puts these n goals in head normal form (using the defective form of the tactic :tacn:`move `), then executes the corresponding intro pattern :n:`@i_pattern__i` in each goal. 4. Then, :tacn:`under` checks that the first n subgoals are (quantified) Leibniz equalities, double implications or registered relations (w.r.t. Class ``RewriteRelation``) between a term and an evar, e.g., ``m - m = ?F2 m`` in the running example. (This support for setoid-like relations is enabled as soon as one does both ``Require Import ssreflect.`` and ``Require Setoid.``) 5. If so :tacn:`under` protects these n goals against an accidental instantiation of the evar. These protected goals are displayed using the ``'Under[ … ]`` notation (e.g. ``'Under[ m - m ]`` in the running example). 6. The expression inside the ``'Under[ … ]`` notation can be proved equivalent to the desired expression by using a regular :tacn:`rewrite` tactic. 7. Interactive editing of the first n goals has to be signalled by using the :tacn:`over` tactic or rewrite rule (see below), which requires that the underlying relation is reflexive. (The running example deals with Leibniz equality, but ``PreOrder`` relations are also supported, for example.) 8. Finally, a post-processing step is performed in the main goal to keep the name(s) for the bound variables chosen by the user in the intro pattern for the first branch. .. _over_ssr: The over tactic +++++++++++++++ Two equivalent facilities (a terminator and a lemma) are provided to close intermediate subgoals generated by :tacn:`under` (i.e., goals displayed as ``'Under[ … ]``): .. tacn:: over :name: over This terminator tactic allows one to close goals of the form ``'Under[ … ]``. .. tacv:: by rewrite over This is a variant of :tacn:`over` in order to close ``'Under[ … ]`` goals, relying on the ``over`` rewrite rule. Note that a rewrite rule ``UnderE`` is available as well, if one wants to "unprotect" the evar, without closing the goal automatically (e.g., to instantiate it manually with another rule than reflexivity). .. _under_one_liner: One-liner mode `````````````` The Ltac expression: :n:`under @term => [ @i_item__1 | … | @i_item__n ] do [ @tactic__1 | … | @tactic__n ].` can be seen as a shorter form for the following expression: :n:`(under @term) => [ @i_item__1 | … | @i_item__n | ]; [ @tactic__1; over | … | @tactic__n; over | cbv beta iota ].` Notes: + The ``beta-iota`` reduction here is useful to get rid of the beta redexes that could be introduced after the substitution of the evars by the :tacn:`under` tactic. + Note that the provided tactics can as well involve other :tacn:`under` tactics. See below for a typical example involving the `bigop` theory from the Mathematical Components library. + If there is only one tactic, the brackets can be omitted, e.g.: :n:`under @term => i do @tactic.` and that shorter form should be preferred. + If the ``do`` clause is provided and the intro pattern is omitted, then the default :token:`i_item` ``*`` is applied to each branch. E.g., the Ltac expression :n:`under @term do [ @tactic__1 | … | @tactic__n ]` is equivalent to :n:`under @term => [ * | … | * ] do [ @tactic__1 | … | @tactic__n ]` (and it can be noted here that the :tacn:`under` tactic performs a ``move.`` before processing the intro patterns ``=> [ * | … | * ]``). .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Coercion is_true : bool >-> Sortclass. Reserved Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" (at level 36, F at level 36, op, idx at level 10, m, i, n at level 50, format "'[' \big [ op / idx ]_ ( m <= i < n | P ) F ']'"). Variant bigbody (R I : Type) : Type := BigBody : forall (_ : I) (_ : forall (_ : R) (_ : R), R) (_ : bool) (_ : R), bigbody R I. Parameter bigop : forall (R I : Type) (_ : R) (_ : list I) (_ : forall _ : I, bigbody R I), R. Axiom eq_bigr_ : forall (R : Type) (idx : R) (op : forall (_ : R) (_ : R), R) (I : Type) (r : list I) (P : I -> bool) (F1 F2 : I -> R), (forall x : I, is_true (P x) -> F1 x = F2 x) -> bigop idx r (fun i : I => BigBody i op (P i) (F1 i)) = bigop idx r (fun i : I => BigBody i op (P i) (F2 i)). Axiom eq_big_ : forall (R : Type) (idx : R) (op : R -> R -> R) (I : Type) (r : list I) (P1 P2 : I -> bool) (F1 F2 : I -> R), (forall x : I, P1 x = P2 x) -> (forall i : I, is_true (P1 i) -> F1 i = F2 i) -> bigop idx r (fun i : I => BigBody i op (P1 i) (F1 i)) = bigop idx r (fun i : I => BigBody i op (P2 i) (F2 i)). Reserved Notation "\sum_ ( m <= i < n | P ) F" (at level 41, F at level 41, i, m, n at level 50, format "'[' \sum_ ( m <= i < n | P ) '/ ' F ']'"). Parameter index_iota : nat -> nat -> list nat. Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" := (bigop idx (index_iota m n) (fun i : nat => BigBody i op P%bool F)). Notation "\sum_ ( m <= i < n | P ) F" := (\big[plus/O]_(m <= i < n | P%bool) F%nat). Abbreviation eq_bigr := (fun n m => eq_bigr_ 0 plus (index_iota n m)). Abbreviation eq_big := (fun n m => eq_big_ 0 plus (index_iota n m)). Parameter odd : nat -> bool. Parameter prime : nat -> bool. .. rocqtop:: in Parameter addnC : forall m n : nat, m + n = n + m. Parameter muln1 : forall n : nat, n * 1 = n. .. rocqtop:: all Check eq_bigr. Check eq_big. Lemma test_big_nested (m n : nat) : \sum_(0 <= a < m | prime a) \sum_(0 <= j < n | odd (j * 1)) (a + j) = \sum_(0 <= i < m | prime i) \sum_(0 <= j < n | odd j) (j + i). under eq_bigr => i prime_i do under eq_big => [ j | j odd_j ] do [ rewrite (muln1 j) | rewrite (addnC i j) ]. Remark how the final goal uses the name ``i`` (the name given in the intro pattern) rather than ``a`` in the binder of the first summation. .. _locking_ssr: Locking, unlocking ~~~~~~~~~~~~~~~~~~ As program proofs tend to generate large goals, it is important to be able to control the partial evaluation performed by the simplification operations that are performed by the tactics. These evaluations can, for example, come from a ``/=`` simplification switch, or from rewrite steps, which may expand large terms while performing conversion. We definitely want to avoid repeating large subterms of the goal in the proof script. We do this by β€œclamping down” selected function symbols in the goal, which prevents them from being considered in simplification or rewriting steps. This clamping is accomplished by using the occurrence switches (see Section :ref:`abbreviations_ssr`) together with β€œterm tagging” operations. |SSR| provides two levels of tagging. The first one uses auxiliary definitions to introduce a provably equal copy of any term ``t``. However this copy is (on purpose) *not convertible* to ``t`` in the Rocq system [#8]_. The job is done by the following construction: .. rocqdoc:: Lemma master_key : unit. Proof. exact tt. Qed. Definition locked A := let: tt := master_key in fun x : A => x. Lemma lock : forall A x, x = locked x :> A. Note that the definition of *master_key* is explicitly opaque. The equation ``t = locked t`` given by the ``lock`` lemma can be used for selective rewriting, blocking on the fly the reduction in the term ``t``. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrfun ssrbool. From Corelib Require Import ListDef. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variable A : Type. Fixpoint has (p : A -> bool) (l : list A) : bool := if l is cons x l then p x || (has p l) else false. Lemma test p x y l (H : p x = true) : has p ( x :: y :: l) = true. rewrite {2}[cons]lock /= -lock. It is sometimes desirable to globally prevent a definition from being expanded by simplification; this is done by adding ``locked`` in the definition. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Definition lid := locked (fun x : nat => x). Lemma test : lid 3 = 3. rewrite /=. unlock lid. .. tacn:: unlock {? @occ_switch } @ident :name: unlock This tactic unfolds such definitions while removing β€œlocks”; i.e., it replaces the occurrence(s) of :token:`ident` coded by the :token:`occ_switch` with the corresponding body. We found that it was usually preferable to prevent the expansion of some functions by the partial evaluation switch ``/=``, unless this allowed the evaluation of a condition. This is possible thanks to another mechanism of term tagging, resting on the following *Notation*: .. rocqdoc:: Notation "'nosimpl' t" := (let: tt := tt in t). The term ``(nosimpl t)`` simplifies to ``t`` *except* in a definition. More precisely, given: .. rocqdoc:: Definition foo := (nosimpl bar). the term ``foo`` (or ``(foo t’)``) will *not* be expanded by the *simpl* tactic unless it is in a forcing context (e.g., in ``match foo t’ with … end``, ``foo t’`` will be reduced if this allows ``match`` to be reduced). Note that ``nosimpl bar`` is simply notation for a term that reduces to ``bar``; hence ``unfold foo`` will replace ``foo`` by ``bar``, and ``fold foo`` will replace ``bar`` by ``foo``. .. warning:: The ``nosimpl`` trick only works if no reduction is apparent in ``t``; in particular, the declaration: .. rocqdoc:: Definition foo x := nosimpl (bar x). will usually not work. Anyway, the common practice is to tag only the function, and to use the following definition, which blocks the reduction as expected: .. rocqdoc:: Definition foo x := nosimpl bar x. A standard example making this technique shine is the case of arithmetic operations. We define for instance: .. rocqdoc:: Definition addn := nosimpl plus. The operation ``addn`` behaves exactly like ``plus``, except that ``(addn (S n) m)`` will not simplify spontaneously to ``(S (addn n m))`` (the two terms, however, are convertible). In addition, the unfolding step ``rewrite /addn`` will replace ``addn`` directly with ``plus``, so the ``nosimpl`` form is essentially invisible. .. _congruence_ssr: Congruence ~~~~~~~~~~ Because of the way matching interferes with parameters of type families, the tactic: .. rocqdoc:: apply: my_congr_property. will generally fail to perform congruence simplification, even on rather simple cases. We therefore provide a more robust alternative in which the function is supplied: .. tacn:: congr {? @natural } @term :name: congr This tactic: + checks that the goal is a Leibniz equality; + matches both sides of this equality with β€œterm applied to some arguments”, inferring the right number of arguments from the goal and the type of ``term`` (this may expand some definitions or fixpoints); + generates the subgoals corresponding to pairwise equalities of the arguments present in the goal. The goal can be a non-dependent product ``P -> Q``. In that case, the system asserts the equation ``P = Q``, uses it to solve the goal, and calls the ``congr`` tactic on the remaining goal ``P = Q``. This can be useful for instance to perform a transitivity step, like in the following situation. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test (x y z : nat) (H : x = y) : x = z. congr (_ = _) : H. Abort. Lemma test (x y z : nat) : x = y -> x = z. congr (_ = _). The optional :token:`natural` forces the number of arguments for which the tactic should generate equality proof obligations. This tactic supports equalities between applications with dependent arguments. Yet dependent arguments should have exactly the same parameters on both sides, and these parameters should appear as first arguments. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Definition f n := if n is 0 then plus else mult. Definition g (n m : nat) := plus. Lemma test x y : f 0 x y = g 1 1 x y. congr plus. This script shows that the ``congr`` tactic matches ``plus`` with ``f 0`` on the left hand side and ``g 1 1`` on the right hand side, and solves the goal. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test n m (Hnm : m <= n) : S m + (S n - S m) = S n. congr S; rewrite -/plus. The tactic ``rewrite -/plus`` folds back the expansion of ``plus``, which was necessary for matching both sides of the equality with an application of ``S``. Like most |SSR| arguments, :token:`term` can contain wildcards. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test x y : x + (y * (y + x - x)) = x * 1 + (y + 0) * y. congr ( _ + (_ * _)). .. _contextual_patterns_ssr: Contextual patterns ------------------- The simple form of patterns used so far, terms possibly containing wild cards, often requires an additional :token:`occ_switch` to be specified. While this may work pretty fine for small goals, the use of polymorphic functions and dependent types may lead to an invisible duplication of function arguments. These copies usually end up in types hidden by the implicit-arguments machinery or by user-defined notations. In these situations, computing the right occurrence numbers is very tedious, because they must be counted on the goal as printed after setting the :flag:`Printing All` flag. Moreover, the resulting script is not really informative for the reader, since it refers to occurrence numbers he cannot easily see. Contextual patterns mitigate these issues by allowing to specify occurrences according to the context they occur in. Syntax ~~~~~~ The following table summarizes the full syntax of :token:`c_pattern` and the corresponding subterm(s) identified by the pattern. In the third column, we use s.m.r. for β€œthe subterms matching the redex” specified in the second column. .. list-table:: :header-rows: 1 * - :token:`c_pattern` - redex - subterms affected * - ``term`` - ``term`` - all occurrences of ``term`` * - ``ident in term`` - subterm of ``term`` selected by ``ident`` - all the subterms identified by ``ident`` in all the occurrences of ``term`` * - ``term1 in ident in term2`` - ``term1`` in all s.m.r. - in all the subterms identified by ``ident`` in all the occurrences of ``term2`` * - ``term1 as ident in term2`` - ``term1`` - in all the subterms identified by ``ident`` in all the occurrences of ``term2[term1 /ident]`` The rewrite tactic supports two more patterns obtained prefixing the first two with ``in``. The intended meaning is that the pattern identifies all subterms of the specified context. The ``rewrite`` tactic will infer a pattern for the redex looking at the rule used for rewriting. .. list-table:: :header-rows: 1 * - :token:`r_pattern` - redex - subterms affected * - ``in term`` - inferred from rule - in all s.m.r. in all occurrences of ``term`` * - ``in ident in term`` - inferred from rule - in all s.m.r. in all the subterms identified by ``ident`` in all the occurrences of ``term`` The first :token:`c_pattern` is the simplest form matching any context but selecting a specific redex and has been described in the previous sections. We have seen so far that the possibility of selecting a redex using a term with holes is already a powerful means of redex selection. Similarly, any terms provided by the user in the more complex forms of :token:`c_pattern`\s presented in the tables above can contain holes. For a quick glance at what can be expressed with the last :token:`r_pattern`, consider the goal ``a = b`` and the tactic .. rocqdoc:: rewrite [in X in _ = X]rule. It rewrites all occurrences of the left hand side of ``rule`` inside ``b`` only (``a``, and the hidden type of the equality, are ignored). Note that the variant ``rewrite [X in _ = X]rule`` would have rewritten ``b`` exactly (i.e., it would only work if ``b`` and the left-hand side of rule can be unified). Matching contextual patterns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :token:`c_pattern` and :token:`r_pattern` involving terms with holes are matched against the goal in order to find a closed instantiation. This matching proceeds as follows: .. list-table:: :header-rows: 1 * - :token:`c_pattern` - instantiation order and place for ``term_i`` and redex * - ``term`` - ``term`` is matched against the goal, redex is unified with the instantiation of ``term`` * - ``ident in term`` - ``term`` is matched against the goal, redex is unified with the subterm of the instantiation of ``term`` identified by ``ident`` * - ``term1 in ident in term2`` - ``term2`` is matched against the goal, ``term1`` is matched against the subterm of the instantiation of ``term1`` identified by ``ident``, redex is unified with the instantiation of ``term1`` * - ``term1 as ident in term2`` - ``term2[term1/ident]`` is matched against the goal, redex is unified with the instantiation of ``term1`` In the following patterns, the redex is intended to be inferred from the rewrite rule. .. list-table:: :header-rows: 1 * - :token:`r_pattern` - instantiation order and place for ``term_i`` and redex * - ``in ident in term`` - ``term`` is matched against the goal, the redex is matched against the subterm of the instantiation of ``term`` identified by ``ident`` * - ``in term`` - ``term`` is matched against the goal, redex is matched against the instantiation of ``term`` Examples ~~~~~~~~ Contextual pattern in set and the : tactical ```````````````````````````````````````````` As already mentioned in Section :ref:`abbreviations_ssr`, the ``set`` tactic takes as an argument a term in open syntax. This term is interpreted as the simplest form of :token:`c_pattern`. To avoid confusion in the grammar, open syntax is supported only for the simplest form of patterns, while parentheses are required around more complex patterns. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test a b : a + b + 1 = b + (a + 1). set t := (X in _ = X). rewrite {}/t. set t := (a + _ in X in _ = X). Since the user may define an infix notation for ``in``, the result of the former tactic may be ambiguous. The disambiguation rule implemented is to prefer patterns over simple terms, but to interpret a pattern with double parentheses as a simple term. For example, the following tactic would capture any occurrence of the term ``a in A``. .. rocqdoc:: set t := ((a in A)). Contextual patterns can also be used as arguments of the ``:`` tactical. For example: .. rocqdoc:: elim: n (n in _ = n) (refl_equal n). Contextual patterns in rewrite `````````````````````````````` .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Notation "n .+1" := (Datatypes.S n) (at level 1, left associativity, format "n .+1") : nat_scope. Axiom addSn : forall m n, m.+1 + n = (m + n).+1. Axiom addn0 : forall m, m + 0 = m. Axiom addnC : forall m n, m + n = n + m. Lemma test x y z f : (x.+1 + y) + f (x.+1 + y) (z + (x + y).+1) = 0. rewrite [in f _ _]addSn. Note: the simplification rule ``addSn`` is applied only under the ``f`` symbol. Then, we simplify also the first addition and expand ``0`` into ``0 + 0``. .. rocqtop:: all rewrite addSn -[X in _ = X]addn0. Note that the right-hand side of ``addn0`` is undetermined, but the rewrite pattern specifies the redex explicitly. The right-hand side of ``addn0`` is unified with the term identified by ``X``, here ``0``. The following pattern does not specify a redex, since it identifies an entire region; hence the rewrite rule has to be instantiated explicitly. Thus the tactic: .. rocqtop:: all rewrite -{2}[in X in _ = X](addn0 0). The following tactic is quite tricky: .. rocqtop:: all rewrite [_.+1 in X in f _ X](addnC x.+1). The explicit redex ``_.+1`` is important, since its :term:`head constant` ``S`` differs from the head constant inferred from ``(addnC x.+1)`` (that is ``+``). Moreover, the pattern ``f _ X`` is important to rule out the first occurrence of ``(x + y).+1``. Last, only the subterms of ``f _ X`` identified by ``X`` are rewritten; thus the first argument of ``f`` is skipped too. Also note that the pattern ``_.+1`` is interpreted in the context identified by ``X``; thus it gets instantiated to ``(y + x).+1`` and not ``(x + y).+1``. The last rewrite pattern allows to specify exactly the shape of the term identified by X, which is thus unified with the left-hand side of the rewrite rule. .. rocqtop:: all rewrite [x.+1 + y as X in f X _]addnC. Patterns for recurrent contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The user can define shortcuts for recurrent contexts corresponding to the ``ident in term`` part. The notation scope identified with ``%pattern`` provides a special notation ``(X in t)`` the user must adopt in order to define context shortcuts. The following example is taken from ``ssreflect.v``, where the ``LHS`` and ``RHS`` shortcuts are defined. .. rocqdoc:: Abbreviation RHS := (X in _ = X)%pattern. Abbreviation LHS := (X in X = _)%pattern. Shortcuts defined this way can be freely used in place of the trailing ``ident in term`` part of any contextual pattern. Some examples follow: .. rocqdoc:: set rhs := RHS. rewrite [in RHS]rule. case: (a + _ in RHS). .. _views_and_reflection_ssr: Views and reflection -------------------- The bookkeeping facilities presented in Section :ref:`basic_tactics_ssr` are crafted to ease simultaneous introductions and generalizations of facts and operations of casing, naming, etc. It is also a common practice to make a stack operation immediately followed by an *interpretation* of the fact being pushed, that is, to apply a lemma to this fact before passing it to a tactic for decomposition, application and so on. |SSR| provides a convenient, unified syntax to combine these interpretation operations with the proof stack operations. This *view mechanism* relies on the combination of the ``/`` view switch with bookkeeping tactics and tacticals. .. _custom_elim_ssr: Interpreting eliminations ~~~~~~~~~~~~~~~~~~~~~~~~~ The view syntax combined with the ``elim`` tactic specifies an elimination scheme to be used instead of the default, generated, one. Hence, the |SSR| tactic: .. rocqdoc:: elim/V. is a synonym for: .. rocqdoc:: intro top; elim top using V; clear top. where top is a fresh name and V any second-order lemma. Since an elimination view supports the two bookkeeping tacticals of discharge and introduction (see Section :ref:`basic_tactics_ssr`), the |SSR| tactic: .. rocqdoc:: elim/V: x => y. is a synonym for: .. rocqdoc:: elim x using V; clear x; intro y. where ``x`` is a variable in the context, ``y`` a fresh name and ``V`` any second order lemma; |SSR| relaxes the syntactic restrictions of the Rocq ``elim``. The first pattern following ``:`` can be a ``_`` wildcard if the conclusion of the view ``V`` specifies a pattern for its last argument (e.g., if ``V`` is a functional induction lemma generated by the ``Function`` command). The elimination view mechanism is compatible with the equation-name generation (see Section :ref:`generation_of_equations_ssr`). .. example:: The following script illustrates a toy example of this feature. Let us define a function adding an element at the end of a list: .. rocqtop:: reset none From Corelib Require Import ssreflect ListDef. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variable d : Type. Fixpoint add_last (s : list d) (z : d) {struct s} : list d := if s is cons x s' then cons x (add_last s' z) else z :: nil. One can define an alternative, reversed, induction principle on inductively defined lists, by proving the following lemma: .. rocqtop:: all Axiom last_ind_list : forall P : list d -> Prop, P nil -> (forall s (x : d), P s -> P (add_last s x)) -> forall s : list d, P s. Then, the combination of elimination views with equation names results in a concise syntax for reasoning inductively using the user-defined elimination scheme. .. rocqtop:: all Lemma test (x : d) (l : list d): l = l. elim/last_ind_list E : l=> [| u v]; last first. User-provided eliminators (potentially generated with Coq’s ``Function`` command) can be combined with the type family switches described in Section :ref:`type_families_ssr`. Consider an eliminator ``foo_ind`` of type: .. rocqdoc:: foo_ind : forall …, forall x : T, P p1 … pm. and consider the tactic: .. rocqdoc:: elim/foo_ind: e1 … / en. The ``elim/`` tactic distinguishes two cases. :truncated eliminator: when ``x`` does not occur in ``P p1 … pm`` and the type of ``en`` unifies with ``T`` and ``en`` is not ``_``. In that case, ``en`` is passed to the eliminator as the last argument (``x`` in ``foo_ind``) and ``enβˆ’1 … e1`` are used as patterns to select in the goal the occurrences that will be bound by the predicate ``P``; thus it must be possible to unify the subterm of the goal matched by ``enβˆ’1`` with ``pm`` , the one matched by ``enβˆ’2`` with ``pmβˆ’1`` and so on. :regular eliminator: in all the other cases. Here it must be possible to unify the term matched by ``en`` with ``pm`` , the one matched by ``enβˆ’1`` with ``pmβˆ’1`` and so on. Note that standard eliminators have the shape ``…forall x, P … x``; thus ``en`` is the pattern identifying the eliminated term, as expected. As explained in Section :ref:`type_families_ssr`, the initial prefix of ``ei`` can be omitted. Here is an example of a regular, but nontrivial, eliminator. .. example:: Here is a toy example illustrating this feature. .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Lemma plus_ind : forall [m : nat] [P : nat -> nat -> Prop], (forall n p : nat, n = S p -> P p (plus m p) -> P (S p) (S (plus m p))) -> (forall n _x : nat, n = _x -> match _x with | 0 => True | S _ => False end -> P _x m) -> forall n : nat, P n (plus m n). Admitted. Section Test. .. rocqtop:: all Fixpoint plus (m n : nat) {struct n} : nat := if n is S p then S (plus m p) else m. About plus_ind. Lemma test x y z : plus (plus x y) z = plus x (plus y z). The following tactics are all valid and perform the same elimination on this goal. .. rocqdoc:: elim/plus_ind: z / (plus _ z). elim/plus_ind: {z}(plus _ z). elim/plus_ind: {z}_. elim/plus_ind: z / _. .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Fixpoint plus (m n : nat) {struct n} : nat := if n is S p then S (plus m p) else m. Axiom plus_ind : forall [m : nat] [P : nat -> nat -> Prop], (forall n p : nat, n = S p -> P p (plus m p) -> P (S p) (S (plus m p))) -> (forall n _x : nat, n = _x -> match _x with | 0 => True | S _ => False end -> P _x m) -> forall n : nat, P n (plus m n). Lemma test x y z : plus (plus x y) z = plus x (plus y z). .. rocqtop:: all elim/plus_ind: z / _. The two latter examples feature a wildcard pattern: in this case, the resulting pattern is inferred from the type of the eliminator. In both of these examples, it is ``(plus _ _)`` that matches the subterm ``plus (plus x y) z``, thus instantiating the last ``_`` with ``z``. Note that the tactic: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Fixpoint plus (m n : nat) {struct n} : nat := if n is S p then S (plus m p) else m. Axiom plus_ind : forall [m : nat] [P : nat -> nat -> Prop], (forall n p : nat, n = S p -> P p (plus m p) -> P (S p) (S (plus m p))) -> (forall n _x : nat, n = _x -> match _x with | 0 => True | S _ => False end -> P _x m) -> forall n : nat, P n (plus m n). Lemma test x y z : plus (plus x y) z = plus x (plus y z). .. rocqtop:: all Fail elim/plus_ind: y / _. triggers an error: in the conclusion of the ``plus_ind`` eliminator, the first argument of the predicate ``P`` should be the same as the second argument of ``plus``, in the second argument of ``P``, but ``y`` and ``z`` do no unify. Here is an example of a truncated eliminator: .. example:: Consider the goal: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqdoc:: Lemma test p n (n_gt0 : 0 < n) (pr_p : prime p) : p %| \prod_(i <- prime_decomp n | i \in prime_decomp n) i.1 ^ i.2 -> exists2 x : nat * nat, x \in prime_decomp n & p = x.1. Proof. elim/big_prop: _ => [| u v IHu IHv | [q e] /=]. where the type of the ``big_prop`` eliminator is .. rocqdoc:: big_prop: forall (R : Type) (Pb : R -> Type) (idx : R) (op1 : R -> R -> R), Pb idx -> (forall x y : R, Pb x -> Pb y -> Pb (op1 x y)) -> forall (I : Type) (r : seq I) (P : pred I) (F : I -> R), (forall i : I, P i -> Pb (F i)) -> Pb (\big[op1/idx]_(i <- r | P i) F i). Since the pattern for the argument of Pb is not specified, the inferred one, ``big[_/_]_(i <- _ | _ i) _ i``, is used instead, and after the introductions, the following goals are generated: .. rocqdoc:: subgoal 1 is: p %| 1 -> exists2 x : nat * nat, x \in prime_decomp n & p = x.1 subgoal 2 is: p %| u * v -> exists2 x : nat * nat, x \in prime_decomp n & p = x.1 subgoal 3 is: (q, e) \in prime_decomp n -> p %| q ^ e -> exists2 x : nat * nat, x \in prime_decomp n & p = x.1. Note that the pattern matching algorithm instantiated all the variables occurring in the pattern. .. _interpreting_assumptions_ssr: Interpreting assumptions ~~~~~~~~~~~~~~~~~~~~~~~~ Interpreting an assumption in the context of a proof consists in applying to it a lemma before generalizing and/or decomposing this assumption. For instance, with the extensive use of boolean reflection (see Section :ref:`views_and_reflection_ssr`), it is quite frequent to need to decompose the logical interpretation of (the boolean expression of) a fact, rather than the fact itself. This can be achieved by a combination of ``move : _ => _`` switches, like in the following example, where ``||`` is a notation for the boolean disjunction. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variables P Q : bool -> Prop. Hypothesis P2Q : forall a b, P (a || b) -> Q a. Lemma test a : P (a || a) -> True. move=> HPa; move: {HPa}(P2Q HPa) => HQa. which transforms the hypothesis ``HPa : P a``, which has been introduced from the initial statement, into ``HQa : Q a``. This operation is so common that the tactic shell has specific syntax for it. The following scripts: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Variables P Q : bool -> Prop. Hypothesis P2Q : forall a b, P (a || b) -> Q a. Lemma test a : P (a || a) -> True. .. rocqtop:: all move=> HPa; move/P2Q: HPa => HQa. or more directly: .. rocqtop:: all restart move/P2Q=> HQa. are equivalent to the former one. The former script shows how to interpret a fact (already in the context), thanks to the discharge tactical (see Section :ref:`discharge_ssr`), and the latter, how to interpret the top assumption of a goal. Note that the number of wildcards to be inserted to find the correct application of the view lemma to the hypothesis has been automatically inferred. The view mechanism is compatible with the ``case`` tactic and with the equation-name generation mechanism (see Section :ref:`generation_of_equations_ssr`): .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variables P Q: bool -> Prop. Hypothesis Q2P : forall a b, Q (a || b) -> P a \/ P b. Lemma test a b : Q (a || b) -> True. case/Q2P=> [HPa | HPb]. This view tactic performs: .. rocqdoc:: move=> HQ; case: {HQ}(Q2P HQ) => [HPa | HPb]. The term on the right of the ``/`` view switch is called a *view lemma*. Any |SSR| term coercing to a product type can be used as a view lemma. The examples we have given so far explicitly provide the direction of the translation to be performed. In fact, view lemmas need not to be oriented. The view mechanism is able to detect which application is relevant for the current goal. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variables P Q: bool -> Prop. Hypothesis PQequiv : forall a b, P (a || b) <-> Q a. Lemma test a b : P (a || b) -> True. move/PQequiv=> HQab. has the same behavior as the first example above. The view mechanism can insert automatically a *view hint* to transform the double implication into the expected simple implication. The last script is in fact equivalent to: .. rocqdoc:: Lemma test a b : P (a || b) -> True. move/(iffLR (PQequiv _ _)). where: .. rocqdoc:: Lemma iffLR P Q : (P <-> Q) -> P -> Q. Specializing assumptions ```````````````````````` The special case when the *head symbol* of the view lemma is a wildcard is used to interpret an assumption by *specializing* it. The view mechanism hence offers the possibility to apply a higher-order assumption to some given arguments. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test z : (forall x y, x + y = z -> z = x) -> z = 0. move/(_ 0 z). Interpreting goals ~~~~~~~~~~~~~~~~~~ In a similar way, it is also often convenient to change a goal by turning it into an equivalent proposition. The view mechanism of |SSR| has a special syntax ``apply/`` for combining in a single tactic simultaneous goal interpretation operations and bookkeeping steps. .. example:: The following example use the ``~~`` prenex notation for boolean negation: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Variables P Q: bool -> Prop. Hypothesis PQequiv : forall a b, P (a || b) <-> Q a. Lemma test a : P ((~~ a) || a). apply/PQequiv. thus in this case, the tactic ``apply/PQequiv`` is equivalent to ``apply: (iffRL (PQequiv _ _))``, where ``iffRL`` is the analogue of ``iffLR`` for the converse implication. Any |SSR| term whose type coerces to a double implication can be used as a view for goal interpretation. Note that the goal interpretation view mechanism supports both ``apply`` and ``exact`` tactics. As expected, a goal interpretation view command ``exact``/term should solve the current goal or it will fail. .. warning:: Goal-interpretation view tactics are *not* compatible with the bookkeeping tactical ``=>``, since this would be redundant with the ``apply: term => _`` construction. Boolean reflection ~~~~~~~~~~~~~~~~~~ In the Calculus of Inductive Constructions, there is an obvious distinction between logical propositions and boolean values. On the one hand, logical propositions are objects of *sort* ``Prop``, which is the carrier of intuitionistic reasoning. Logical connectives in ``Prop`` are *types*, which give precise information on the structure of their proofs; this information is automatically exploited by Rocq tactics. For example, Rocq knows that a proof of ``A \/ B`` is either a proof of ``A`` or a proof of ``B``. The tactics ``left`` and ``right`` change the goal ``A \/ B`` to ``A`` and ``B``, respectively; dually, the tactic ``case`` reduces the goal ``A \/ B => G`` to two subgoals ``A => G`` and ``B => G``. On the other hand, bool is an inductive *datatype* with two constructors: ``true`` and ``false``. Logical connectives on bool are *computable functions*, defined by their truth tables, using case analysis: .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Definition orb (b1 b2 : bool) := if b1 then true else b2. Properties of such connectives are also established using case analysis .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test b : b || ~~ b = true. by case: b. Once ``b`` is replaced by ``true`` in the first goal and by ``false`` in the second one, the goals reduce by computation to the trivial ``true = true``. Thus, ``Prop`` and ``bool`` are truly complementary: the former supports robust natural deduction; the latter allows brute-force evaluation. |SSR| supplies a generic mechanism to have the best of the two worlds and move freely from a propositional version of a decidable predicate to its boolean version. First, booleans are injected into propositions using the coercion mechanism: .. rocqdoc:: Coercion is_true (b : bool) := b = true. This allows any boolean formula ``b`` to be used in a context where Rocq would expect a proposition, e.g., after ``Lemma … :``. It is then interpreted as ``(is_true b)``, i.e., the proposition ``b = true``. Coercions are elided by the pretty-printer; so they are essentially transparent to the user. The reflect predicate ~~~~~~~~~~~~~~~~~~~~~ To get all the benefits of the boolean reflection, it is in fact convenient to introduce the following inductive predicate ``reflect`` to relate propositions and booleans: .. rocqdoc:: Inductive reflect (P: Prop): bool -> Type := | Reflect_true : P -> reflect P true | Reflect_false : ~P -> reflect P false. The statement ``(reflect P b)`` asserts that ``(is_true b)`` and ``P`` are logically equivalent propositions. For instance, the following lemma: .. rocqdoc:: Lemma andP: forall b1 b2, reflect (b1 /\ b2) (b1 && b2). relates the boolean conjunction to the logical one ``/\``. Note that in ``andP``, ``b1`` and ``b2`` are two boolean variables and the proposition ``b1 /\ b2`` hides two coercions. The conjunction of ``b1`` and ``b2`` can then be viewed as ``b1 /\ b2`` or as ``b1 && b2``. Expressing logical equivalences through this family of inductive types makes possible to take benefit from *rewritable equations* associated to the case analysis of Rocq's inductive types. Since the equivalence predicate is defined in Rocq as: .. rocqdoc:: Definition iff (A B:Prop) := (A -> B) /\ (B -> A). where ``/\`` is a notation for ``and``: .. rocqdoc:: Inductive and (A B:Prop) : Prop := conj : A -> B -> and A B. This makes case analysis very different according to the way an equivalence property has been defined. .. rocqdoc:: Lemma andE (b1 b2 : bool) : (b1 /\ b2) <-> (b1 && b2). Let us compare the respective behaviors of ``andE`` and ``andP``. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Axiom andE : forall (b1 b2 : bool), (b1 /\ b2) <-> (b1 && b2). .. rocqtop:: all Lemma test (b1 b2 : bool) : if (b1 && b2) then b1 else ~~(b1||b2). .. rocqtop:: all case: (@andE b1 b2). .. rocqtop:: none Restart. .. rocqtop:: all case: (@andP b1 b2). Expressing reflection relations through the ``reflect`` predicate is hence a very convenient way to deal with classical reasoning, by case analysis. Using the ``reflect`` predicate allows, moreover, to program rich specifications inside its two constructors, which will be automatically taken into account during destruction. This formalisation style gives far more efficient specifications than quantified (double) implications. A naming convention in |SSR| is to postfix the name of view lemmas with ``P``. For example, ``orP`` relates ``||`` and ``\/``; ``negP`` relates ``~~`` and ``~``. The view mechanism is compatible with reflect predicates. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all abort Lemma test (a b : bool) (Ha : a) (Hb : b) : a /\ b. apply/andP. Conversely .. rocqtop:: all Lemma test (a b : bool) : a /\ b -> a. move/andP. The same tactics can also be used to perform the converse operation, changing a boolean conjunction into a logical one. The view mechanism guesses the direction of the transformation to be used, i.e., the constructor of the reflect predicate that should be chosen. General mechanism for interpreting goals and assumptions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Specializing assumptions ```````````````````````` The |SSR| tactic: .. rocqdoc:: move/(_ term1 … termn). is equivalent to the tactic: .. rocqdoc:: intro top; generalize (top term1 … termn); clear top. where ``top`` is a fresh name for introducing the top assumption of the current goal. Interpreting assumptions ```````````````````````` The general form of an assumption view tactic is: .. tacv:: {| move | case } / @term :undocumented: The term, called the *view lemma*, can be: + a (term coercible to a) function; + a (possibly quantified) implication; + a (possibly quantified) double implication; + a (possibly quantified) instance of the reflect predicate (see Section :ref:`views_and_reflection_ssr`). Let ``top`` be the top assumption in the goal. There are three steps in the behavior of an assumption view tactic. + It first introduces ``top``. + If the type of :token:`term` is neither a double implication nor an instance of the reflect predicate, then the tactic automatically generalises a term of the form ``term term1 … termn``, where the terms ``term1 … termn`` instantiate the possible quantified variables of ``term`` , in order for ``(term term1 … termn top)`` to be well typed. + If the type of ``term`` is an equivalence, or an instance of the reflect predicate, it generalises a term of the form ``(termvh (term term1 … termn ))``, where the term ``termvh`` inserted is called an *assumption interpretation view hint*. + It finally clears top. For a ``case/term`` tactic, the generalisation step is replaced by a case analysis step. *View hints* are declared by the user (see Section :ref:`views_and_reflection_ssr`) and stored in the Hint View database. The proof engine automatically detects from the shape of the top assumption ``top`` and of the view lemma ``term`` provided to the tactic the appropriate view hint in the database to be inserted. If ``term`` is a double implication, then the view hint will be one of the defined view hints for implication. These hints are by default the ones present in the file ``ssreflect.v``: .. rocqdoc:: Lemma iffLR : forall P Q, (P <-> Q) -> P -> Q. which transforms a double implication into the left-to-right one, or: .. rocqdoc:: Lemma iffRL : forall P Q, (P <-> Q) -> Q -> P. which produces the converse implication. In both cases, the two first ``Prop`` arguments are implicit. If ``term`` is an instance of the ``reflect`` predicate, then ``A`` will be one of the defined view hints for the ``reflect`` predicate, which are by default the ones present in the file ``ssrbool.v``. These hints are not only used for choosing the appropriate direction of the translation, but they also allow complex transformation, involving negations. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Check introN. .. rocqtop:: all Lemma test (a b : bool) (Ha : a) (Hb : b) : ~~ (a && b). apply/andP. In fact, this last script does not exactly use the hint ``introN``, but the more general hint: .. rocqtop:: all Check introNTF. The lemma ``introN`` is an instantiation of ``introNF`` using ``c := true``. Note that views, being part of :token:`i_pattern`, can be used to interpret assertions too. For example, the following script asserts ``a && b``, but actually uses its propositional interpretation. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test (a b : bool) (pab : b && a) : b. have /andP [pa ->] : (a && b) by rewrite andbC. Interpreting goals `````````````````` A goal interpretation view tactic of the form: .. tacv:: apply/@term :undocumented: applied to a goal ``top`` is interpreted in the following way. + If the type of ``term`` is not an instance of the reflect predicate, nor an equivalence, then the term ``term`` is applied to the current goal ``top``, possibly inserting implicit arguments. + If the type of ``term`` is an instance of the reflect predicate or an equivalence, then a *goal interpretation view hint* can possibly be inserted, which corresponds to the application of a term ``(termvh (term _ … _))`` to the current goal, possibly inserting implicit arguments. Like assumption interpretation view hints, goal interpretation ones are user-defined lemmas stored (see Section :ref:`views_and_reflection_ssr`) in the ``Hint View`` database, bridging the possible gap between the type of ``term`` and the type of the goal. Interpreting equivalences ~~~~~~~~~~~~~~~~~~~~~~~~~ Equivalent boolean propositions are simply *equal* boolean terms. A special construction helps the user to prove boolean equalities by considering them as logical double implications (between their coerced versions), while performing at the same time logical operations on both sides. The syntax of double views is: .. tacv:: apply/@term/@term :undocumented: The first term is the view lemma applied to the left-hand side of the equality, while the second term is the one applied to the right-hand side. In this context, the identity view can be used when no view has to be applied: .. rocqdoc:: Lemma idP : reflect b1 b1. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test (b1 b2 b3 : bool) : ~~ (b1 || b2) = b3. apply/idP/idP. The same goal can be decomposed in several ways, and the user may choose the most convenient interpretation. .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. .. rocqtop:: all Lemma test (b1 b2 b3 : bool) : ~~ (b1 || b2) = b3. apply/norP/idP. .. _declaring_new_hints_ssr: Declaring new Hint Views ~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Hint View for move / @ident {? | @natural } Hint View for apply / @ident {? | @natural } This command can be used to extend the database of hints for the view mechanism. As library ``ssrbool.v`` already declares a corpus of hints, this feature is probably useful only for users who define their own logical connectives. The :token:`ident` is the name of the lemma to be declared as a hint. If ``move`` is used as tactic, the hint is declared for assumption interpretation tactics; ``apply`` declares hints for goal interpretations. Goal interpretation view hints are declared for both simple views and left-hand side views. The optional natural number is the number of implicit arguments to be considered for the declared hint view lemma. .. cmdv:: Hint View for apply//@ident {? | @natural } This variant with a double slash ``//`` declares hint views for right-hand sides of double views. See the files ``ssreflect.v`` and ``ssrbool.v`` for examples. Multiple views ~~~~~~~~~~~~~~ The hypotheses and the goal can be interpreted by applying multiple views in sequence. Both ``move`` and ``apply`` can be followed by an arbitrary number of ``/term``. The main difference between the following two tactics .. rocqdoc:: apply/v1/v2/v3. apply/v1; apply/v2; apply/v3. is that the former applies all the views to the principal goal. Applying a view with hypotheses generates new goals, and the second line would apply the view ``v2`` to all the goals generated by ``apply/v1``. Note that the NO-OP intro pattern ``-`` can be used to separate two views, making the two following examples equivalent: .. rocqdoc:: move=> /v1; move=> /v2. move=> /v1 - /v2. The tactic ``move`` can be used together with the ``in`` tactical to pass a given hypothesis to a lemma. .. example:: .. rocqtop:: reset none From Corelib Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Test. Variables P Q R : Prop. .. rocqtop:: all Variable P2Q : P -> Q. Variable Q2R : Q -> R. Lemma test (p : P) : True. move/P2Q/Q2R in p. If the list of views is of length two, ``Hint Views`` for interpreting equivalences are indeed taken into account; otherwise only single ``Hint Views`` are used. Additional view shortcuts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following intro pattern ltac views are provided: + ``/[apply]`` shortcut for ``=> hyp {}/hyp`` + ``/[swap]`` shortcut for ``=> x y; move: y x`` which swaps and preserves let bindings + ``/[dup]`` shortcut for ``=> x; have copy := x; move: copy x`` which copies and preserves let bindings One can call rewrite from an intro pattern, use with parsimony: + ``/[1! rules]`` shortcut for ``rewrite rules`` + ``/[! rules]`` shortcut for ``rewrite !rules`` Synopsis and Index ------------------ Parameters ~~~~~~~~~~ |SSR| tactics .. prodn:: d_tactic ::= {| elim | case | congr | apply | exact | move } Notation scope .. prodn:: key ::= @ident Module name .. prodn:: modname ::= @qualid Natural number .. prodn:: nat_or_ident ::= {| @natural | @ident } where :token:`ident` is an Ltac variable denoting a standard Rocq number (should not be the name of a tactic that can be followed by a bracket ``[``, such as ``do``, ``have``,…) Items and switches ~~~~~~~~~~~~~~~~~~ .. prodn:: ssr_binder ::= {| @ident | ( @ident {? : @term } ) } binder (see :ref:`abbreviations_ssr`) .. prodn:: clear_switch ::= { {+ @ident } } clear switch (see :ref:`discharge_ssr`) .. prodn:: c_pattern ::= {? {| @term in | @term as } } @ident in @term context pattern (see :ref:`contextual_patterns_ssr`) .. prodn:: d_item ::= {? {| @occ_switch | @clear_switch } } {? {| @term | ( @c_pattern ) } } discharge item (see :ref:`discharge_ssr`) .. prodn:: gen_item ::= {| {? @ } @ident | ( @ident ) | ( {? @ } @ident := @c_pattern ) } generalization item (see :ref:`structure_ssr`) .. prodn:: i_pattern ::= {| @ident | > | _ | ? | * | + | {? @occ_switch } {| -> | <- } | [ {?| @i_item } ] | - | [: {+ @ident } ] } intro pattern (see :ref:`introduction_ssr`) .. prodn:: i_item ::= {| @clear_switch | @s_item | @i_pattern | @i_view | @i_block } view (see :ref:`introduction_ssr`) .. prodn:: i_view ::= {? %{%} } {| /@term | /ltac:( @tactic ) } intro block (see :ref:`introduction_ssr`) .. prodn:: i_block ::= {| [^ @ident ] | [^~ {| @ident | @natural } ] } intro item (see :ref:`introduction_ssr`) .. prodn:: int_mult ::= {? @natural } @mult_mark multiplier (see :ref:`iteration_ssr`) .. prodn:: occ_switch ::= { {? {| + | - } } {* @natural } } occur. switch (see :ref:`occurrence_selection_ssr`) .. prodn:: mult ::= {? @natural } @mult_mark multiplier (see :ref:`iteration_ssr`) .. prodn:: mult_mark ::= {| ? | ! } multiplier mark (see :ref:`iteration_ssr`) .. prodn:: r_item ::= {| {? / } @term | @s_item } rewrite item (see :ref:`rewriting_ssr`) .. prodn:: r_prefix ::= {? - } {? @int_mult } {? {| @occ_switch | @clear_switch } } {? [ @r_pattern ] } rewrite prefix (see :ref:`rewriting_ssr`) .. prodn:: r_pattern ::= {| @term | @c_pattern | in {? @ident in } @term } rewrite pattern (see :ref:`rewriting_ssr`) .. prodn:: r_step ::= {? @r_prefix } @r_item rewrite step (see :ref:`rewriting_ssr`) .. prodn:: s_item ::= {| /= | // | //= } simplify switch (see :ref:`introduction_ssr`) Tactics ~~~~~~~ *Note*: ``without loss`` and ``suffices`` are synonyms for ``wlog`` and ``suff``, respectively. .. tacn:: move :name: move (ssreflect) :tacn:`idtac` or :tacn:`hnf` (see :ref:`bookkeeping_ssr`) .. tacn:: apply exact :name: apply (ssreflect); exact (ssreflect) application (see :ref:`the_defective_tactics_ssr`) .. tacv:: abstract: {+ @d_item} (see :ref:`abstract_ssr` and :ref:`generating_let_ssr`) .. tacv:: elim induction (see :ref:`the_defective_tactics_ssr`) .. tacv:: case case analysis (see :ref:`the_defective_tactics_ssr`) .. tacv:: rewrite {+ @r_step } rewrite (see :ref:`rewriting_ssr`) .. tacn:: under {? @r_prefix } @term {? => {+ @i_item}} {? do {| @tactic | [ {*| @tactic } ] } } under (see :ref:`under_ssr`) .. tacn:: over over (see :ref:`over_ssr`) .. tacn:: have {* @i_item } {? @i_pattern } {? {| @s_item | {+ @ssr_binder } } } {? : @term } := @term have {* @i_item } {? @i_pattern } {? {| @s_item | {+ @ssr_binder } } } : @term {? by @tactic } have suff {? @clear_switch } {? @i_pattern } {? : @term } := @term have suff {? @clear_switch } {? @i_pattern } : @term {? by @tactic } gen have {? @ident , } {? @i_pattern } : {+ @gen_item } / @term {? by @tactic } generally have {? @ident , } {? @i_pattern } : {+ @gen_item } / @term {? by @tactic } :name: _; _; _; _; _; generally have forward chaining (see :ref:`structure_ssr`) .. tacn:: wlog {? suff } {? @i_item } : {* {| @gen_item | @clear_switch } } / @term specializing (see :ref:`structure_ssr`) .. tacn:: suff {* @i_item } {? @i_pattern } {+ @ssr_binder } : @term {? by @tactic } suffices {* @i_item } {? @i_pattern } {+ @ssr_binder } : @term {? by @tactic } suff {? have } {? @clear_switch } {? @i_pattern } : @term {? by @tactic } suffices {? have } {? @clear_switch } {? @i_pattern } : @term {? by @tactic } :name: suff; suffices; _; _ backchaining (see :ref:`structure_ssr`) .. tacv:: pose @ident := @term local definition (see :ref:`definitions_ssr`) .. tacv:: pose @ident {+ @ssr_binder } := @term local function definition .. tacv:: pose fix @fix_decl local fix definition .. tacv:: pose cofix @fix_decl local cofix definition .. tacn:: set @ident {? : @term } := {? @occ_switch } {| @term | ( @c_pattern) } :name: set (ssreflect) abbreviation (see :ref:`abbreviations_ssr`) .. tacn:: unlock {* {? @r_prefix } @ident } unlock (see :ref:`locking_ssr`) .. tacn:: congr {? @natural } @term congruence (see :ref:`congruence_ssr`) Tacticals ~~~~~~~~~ .. prodn:: tactic += @d_tactic {? @ident } : {+ @d_item } {? @clear_switch } discharge (see :ref:`discharge_ssr`) .. prodn:: tactic += @tactic => {+ @i_item } introduction (see :ref:`introduction_ssr`) .. prodn:: tactic += @tactic in {+ {| @gen_item | @clear_switch } } {? * } localization (see :ref:`localization_ssr`) .. prodn:: tactic += do {? @mult } {| @tactic | [ {+| @tactic } ] } iteration (see :ref:`iteration_ssr`) .. prodn:: tactic += @tactic ; {| first | last } {? @natural } {| @tactic | [ {+| @tactic } ] } selector (see :ref:`selectors_ssr`) .. prodn:: tactic += @tactic ; {| first | last } {? @natural } rotation (see :ref:`selectors_ssr`) .. prodn:: tactic += by {| @tactic | [ {*| @tactic } ] } closing (see :ref:`terminators_ssr`) Commands ~~~~~~~~ .. cmd:: Hint View for {| move | apply } / @ident {? | @natural } view hint declaration (see :ref:`declaring_new_hints_ssr`) .. cmd:: Hint View for apply // @ident {? @natural } right hand side double , view hint declaration (see :ref:`declaring_new_hints_ssr`) .. cmd:: Prenex Implicits {+ @ident } prenex implicits declaration (see :ref:`parametric_polymorphism_ssr`) .. rubric:: Footnotes .. [#1] Unfortunately, even after a call to the ``Set Printing All`` command, some occurrences are still not displayed to the user, essentially the ones possibly hidden in the predicate of a dependent match structure. .. [#2] Thus scripts that depend on bound variable names, e.g., via intros or with, are inherently fragile. .. [#3] The name ``subnK`` reads as β€œright cancellation rule for ``nat`` subtraction”. .. [#4] Also, a slightly different variant may be used for the first :token:`d_item` of ``case`` and ``elim``; see Section :ref:`type_families_ssr`. .. [#5] Except that ``/=`` does not expand the local definitions created by the |SSR| ``in`` tactical. .. [#6] |SSR| reserves all identifiers of the form β€œ_x_”, which is used for such generated names. .. [#7] More precisely, it should have a quantified inductive type with a assumptions and m βˆ’ a constructors. .. [#8] This is an implementation feature: there is no such obstruction in the metatheory. .. [#9] The current state of the proof shall be displayed by the ``Show Proof`` command of Rocq 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. rocq-9.2.0/doc/sphinx/proof-engine/tactics.rst000066400000000000000000002056201516144147600213360ustar00rootroot00000000000000========================== Common elements of tactics ========================== Reserved keywords ~~~~~~~~~~~~~~~~~ The tactics described in this chapter reserve the following keywords:: by using Thus, these keywords cannot be used as identifiers. It also declares the following character sequences as tokens:: ** [= |- .. _invocation-of-tactics: Invocation of tactics ~~~~~~~~~~~~~~~~~~~~~ Tactics may be preceded by a goal selector (see Section :ref:`goal-selectors`). If no selector is specified, the default selector is used. .. _tactic_invocation_grammar: .. prodn:: tactic_invocation ::= {? @toplevel_selector : } @tactic. .. todo: fully describe selectors. At the moment, ltac has a fairly complete description .. todo: mention selectors can be applied to some commands, such as Check, Search, SearchPattern, SearchRewrite. .. opt:: Default Goal Selector "@toplevel_selector" :name: Default Goal Selector This :term:`option` controls the default selector, used when no selector is specified when applying a tactic. The initial value is 1, hence the tactics are, by default, applied to the first goal. Using value ``all`` will make it so that tactics are, by default, applied to every goal simultaneously. Then, to apply a tactic tac to the first goal only, you can write ``1:tac``. Using value ``!`` enforces that all tactics are used either on a single focused goal or with a local selector (’’strict focusing mode’’). Although other selectors are available, only ``all``, ``!`` or a single natural number are valid default goal selectors. .. _bindings: Bindings ~~~~~~~~ Tactics that take a term as an argument may also accept :token:`bindings` to specify the values to assign unbound variables in a term. Bindings can be given by position or name. Generally these appear in the form :n:`@one_term_with_bindings` or :n:`with @bindings`, depending on the tactic. .. insertprodn one_term_with_bindings bindings .. prodn:: one_term_with_bindings ::= @one_term {? with @bindings } bindings ::= {+ @one_term } | {+ ( {| @ident | @natural } := @term ) } * :n:`@one_term {? with @bindings }` β€” bindings for variables in :n:`@one_term` are typically determined by unifying :n:`@one_term` with a tactic-dependent part of the context, with any remaining unbound variables provided by the :n:`@bindings`. * :n:`{+ @one_term }` β€” binds free variables in the left-to-right order of their first appearance in the relevant term. For some tactics, bindings for all free variables must be provided, such as for :tacn:`induction`, :tacn:`destruct`, :tacn:`elim` and :tacn:`case`. Other tactics automatically generate some or all of the bindings from the conclusion or a hypothesis, such as :tacn:`apply` and :tacn:`constructor` and its variants. In this case, only instances for the :term:`dependent premises ` that are not bound in the conclusion of the relevant term are required (and permitted). * :n:`{+ ( {| @ident | @natural } := @term ) }` β€” binds variables by name (if :n:`@ident` is given), or by unifying with the ``n``-th :term:`premise` of the relevant term (if :n:`@natural` is given). .. exn:: No such binder. :n:`@natural` is 0 or more than the number of unbound variables. .. exn:: No such bound variable @ident (no bound variables at all in the expression). :undocumented: .. exn:: No such bound variable @ident__1 (possible names are: @ident__2 ...). The specified binder name :n:`@ident__1` is not used in the :n:`@one_term`. :n:`@ident__2 ...` lists all the valid binder names. .. exn:: Not the right number of missing arguments (expected @natural). Generated when the first form of :n:`@bindings` doesn't have the expected number of arguments. .. _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`. .. insertprodn intropattern equality_intropattern .. prodn:: intropattern ::= * | ** | @simple_intropattern simple_intropattern ::= @simple_intropattern_closed {* % @term0 } simple_intropattern_closed ::= @naming_intropattern | _ | @or_and_intropattern | @equality_intropattern naming_intropattern ::= @ident | ? | ?@ident or_and_intropattern ::= [ {*| {* @intropattern } } ] | ( {*, @simple_intropattern } ) | ( {*& @simple_intropattern } ) equality_intropattern ::= -> | <- | [= {* @intropattern } ] 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`, while :tacn:`intros` and :tacn:`eintros` use :n:`{* @intropattern }`. 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 Rocq generate a fresh 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]`, Rocq 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 `. 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 ` * 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 `. 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 `. :ref:`Example ` * :n:`[ {+| {* @intropattern } } ]` β€” splits an inductive type that has :ref:`multiple constructors ` such as :n:`A \/ B` into multiple subgoals. The number of :token:`intropattern`\s 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 ` 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 ` * :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 ` **Other patterns** * :n:`*` β€” introduces one or more :term:`dependent premises ` from the result until there are no more. :ref:`Example ` * :n:`**` β€” introduces one or more :term:`dependent ` or :term:`non-dependent premises ` from the result until there are no more premises. :g:`intros **` is equivalent to :g:`intros`. :ref:`Example ` * :n:`@simple_intropattern_closed {* % @term}` β€” first applies each of the terms with the :tacn:`apply` tactic on the hypothesis to be introduced, then it uses :n:`@simple_intropattern_closed`. :ref:`Example ` .. _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". .. rocqdoc:: 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:: :tacn:`intros` :n:`{+ 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 /\\ .. rocqtop:: reset none Goal forall (A: Prop) (B: Prop), (A /\ B) -> True. .. rocqtop:: out intros. .. rocqtop:: all destruct H as (HA & HB). .. _intropattern_disj_ex: .. example:: intro pattern for \\/ .. rocqtop:: reset none Goal forall (A: Prop) (B: Prop), (A \/ B) -> True. .. rocqtop:: out intros. .. rocqtop:: all destruct H as [HA|HB]. all: swap 1 2. .. _intropattern_rarrow_ex: .. example:: -> intro pattern .. rocqtop:: reset none Goal forall (x:nat) (y:nat) (z:nat), (x = y) -> (y = z) -> (x = z). .. rocqtop:: out intros * H. .. rocqtop:: all intros ->. .. _intropattern_inj_discr_ex: .. example:: [=] intro pattern The first :tacn:`intros` :n:`[=]` 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. .. rocqtop:: reset none Goal forall (n m:nat), (S n) = (S m) -> (S O)=(S (S O)) -> False. .. rocqtop:: out intros *. .. rocqtop:: all intros [= H]. .. rocqtop:: all intros [=]. .. _intropattern_ampersand_ex: .. example:: (A & B & …) intro pattern .. rocqtop:: reset none Parameters (A : Prop) (B: nat -> Prop) (C: Prop). .. rocqtop:: out Goal A /\ (exists x:nat, B x /\ C) -> True. .. rocqtop:: all intros (a & x & b & c). .. _intropattern_star_ex: .. example:: * intro pattern .. rocqtop:: reset out Goal forall (A: Prop) (B: Prop), A -> B. .. rocqtop:: all intros *. .. _intropattern_2stars_ex: .. example:: ** pattern ("intros \**" is equivalent to "intros") .. rocqtop:: reset out Goal forall (A: Prop) (B: Prop), A -> B. .. rocqtop:: all intros **. .. example:: compound intro pattern .. rocqtop:: reset out Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C. .. rocqtop:: all intros * [a | (_,c)] f. all: swap 1 2. .. _intropattern_injection_ex: .. example:: combined intro pattern using [=] -> and % .. rocqtop:: reset none Require Import ListDef. Section IntroPatterns. Variables (A : Type) (xs ys : list A). Axiom length_zero_iff_nil : forall [A] (l : list A), length l = 0 <-> l = nil. .. rocqtop:: out Example ThreeIntroPatternsCombined : S (length ys) = 1 -> xs ++ ys = xs. .. rocqtop:: 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:`->`. .. rocqdoc:: Theorem length_zero_iff_nil (l : list A): length l = 0 <-> l=nil. The example is based on `Tej Chajed's coq-tricks `_ .. _occurrenceclauses: Occurrence clauses ~~~~~~~~~~~~~~~~~~ An :gdef:`occurrence` is a subterm of a goal or hypothesis that matches a pattern provided by a tactic. Occurrence clauses select a subset of the ocurrences in a goal and/or in one or more of its hypotheses. .. insertprodn occurrences concl_occs .. prodn:: occurrences ::= at @occs_nums | in @goal_occurrences simple_occurrences ::= @occurrences occs_nums ::= {? - } {+ @nat_or_var } nat_or_var ::= {| @natural | @ident } goal_occurrences ::= {+, @hyp_occs } {? %|- {? @concl_occs } } | * %|- {? @concl_occs } | %|- {? @concl_occs } | {? @concl_occs } hyp_occs ::= @hypident {? at @occs_nums } hypident ::= @ident | ( type of @ident ) | ( value of @ident ) concl_occs ::= * {? at @occs_nums } :n:`@occurrences` The first form of :token:`occurrences` selects occurrences in the conclusion of the goal. The second form can select occurrences in the goal conclusion and in one or more hypotheses. :n:`@simple_occurrences` A semantically restricted form of :n:`@occurrences` that doesn't allow the `at` clause anywhere within it. :n:`{? - } {+ @nat_or_var }` Selects the specified occurrences within a single goal or hypothesis. Occurrences are numbered starting with 1 following a depth-first traversal of the term's expression, including occurrences in :ref:`implicit arguments ` and :ref:`coercions ` that are not displayed by default. (Set the :flag:`Printing All` flag to show those in the printed term.) For example, when matching the pattern `_ + _` in the term `(a + b) + c`, occurrence 1 is `(…) + c` and occurrence 2 is `(a + b)`. When matching that pattern with term `a + (b + c)`, occurrence 1 is `a + (…)` and occurrence 2 is `b + c`. Specifying `-` includes all occurrences *except* the ones listed. :n:`{*, @hyp_occs } {? %|- {? @concl_occs } }` Selects occurrences in the specified hypotheses and the specified occurrences in the conclusion. :n:`* %|- {? @concl_occs }` Selects all occurrences in all hypotheses and the specified occurrences in the conclusion. :n:`%|- {? @concl_occs }` Selects the specified occurrences in the conclusion. :n:`@goal_occurrences ::= {? @concl_occs }` Selects all occurrences in all hypotheses and in the specified occurrences in the conclusion. :n:`@hypident {? at @occs_nums }` Omiting :token:`occs_nums` selects all occurrences within the hypothesis. :n:`@hypident ::= @ident` Selects the hypothesis named :token:`ident`. :n:`( type of @ident )` Selects the type part of the named hypothesis (e.g. `: nat`). :n:`( value of @ident )` Selects the value part of the named hypothesis (e.g. `:= 1`). :n:`@concl_occs ::= * {? at @occs_nums }` Selects occurrences in the conclusion. '*' by itself selects all occurrences. :n:`@occs_nums` selects the specified occurrences. Use `in *` to select all occurrences in all hypotheses and the conclusion, which is equivalent to `in * |- *`. Use `* |-` to select all occurrences in all hypotheses. When rewriting in multiple hypotheses, they must not appear in the term to rewrite. For instance `rewrite H in H,H'` is an error. If an hypothesis appears only through a hole, it will be removed from that hole's context. With `rewrite term in *`, hypotheses on which the dependency cannot be avoided are skipped, for instance `rewrite H in *` skips rewriting in `H`. This is the case even if only one hypothesis ends up rewritten. If multiple occurrences are given, such as in :tacn:`rewrite` `H at 1 2 3`, the tactic must match at least one occurrence in order to succeed. The tactic will fail if no occurrences match. Occurrence numbers that are out of range (e.g. `at 1 3` when there are only 2 occurrences in the hypothesis or conclusion) are ignored. .. todo: remove last sentence above and add "Invalid occurrence number @natural" exn for 8.14 per #13568. Tactics that use occurrence clauses include :tacn:`set`, :tacn:`remember`, :tacn:`induction` and :tacn:`destruct`. .. exn:: No such hypothesis: @ident. :undocumented: .. seealso:: :ref:`Managingthelocalcontext`, :ref:`caseanalysisandinduction`, :ref:`printing_constructions_full`. Automatic clearing of hypotheses ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Default Clearing Used Hypotheses When this :term:`flag` is on (it is off by default), some tactics will automatically clear their hypothesis arguments. For instance when `H` is an hypothesis, `apply H` will clear `H`. .. _applyingtheorems: ================= Applying theorems ================= .. tacn:: exact @one_term Directly gives the exact proof term for the goal. ``exact p`` succeeds if and only if the goal and the type of ``p`` are unifiable (see :ref:`Conversion-rules`). .. exn:: Not an exact proof. :undocumented: .. tacn:: eexact @one_term Behaves like :tacn:`exact` but can handle terms and goals with existential variables. .. tacn:: assumption This tactic looks in the local context for a hypothesis whose type is convertible to the goal. If it is the case, the subgoal is proved. Otherwise, it fails. .. exn:: No such assumption. :undocumented: .. tacn:: eassumption Behaves like :tacn:`assumption` but is able to process goals and hypotheses with existential variables. It can also resolve existential variables, which :tacn:`assumption` will not. .. tacn:: {? simple } {? notypeclasses } refine @one_term :name: refine Behaves like :tacn:`exact` but allows holes (denoted by ``_`` or :n:`(_ : @type)`) in :n:`@one_term`. :tacn:`refine` generates as many subgoals as there are remaining holes in the elaborated term. Any subgoal that occurs in other subgoals is automatically shelved, as if calling :tacn:`shelve_unifiable`. `simple` If specified, don't shelve any subgoals or perform beta reduction. `notypeclasses` If specified, do checking without resolving typeclasses. The generated subgoals (shelved or not) are *not* candidates for typeclass resolution, even if they have a typeclass type as their conclusion. .. example:: .. rocqtop:: reset all Inductive Option : Set := | Fail : Option | Ok : bool -> Option. Definition get : forall x:Option, x <> Fail -> bool. refine (fun x:Option => match x return x <> Fail -> bool with | Fail => _ | Ok b => fun _ => b end). intros; absurd (Fail = Fail); trivial. Defined. .. exn:: Cannot infer a term for this placeholder. :name: Cannot infer a term for this placeholder. (refine) There is a hole in the term you gave whose type cannot be inferred. Put a cast around it. Setting :opt:`Debug` ``"unification"`` enables printing traces of unification steps used during elaboration/typechecking and the :tacn:`refine` tactic. ``"ho-unification"`` prints information about higher order heuristics. .. tacn:: apply {+, @one_term_with_bindings } {? @in_hyp_as } .. insertprodn in_hyp_as as_ipat .. prodn:: in_hyp_as ::= in {+, @ident {? @as_ipat } } as_ipat ::= as @simple_intropattern Uses unification to match the type of each :n:`@one_term` (in :n:`@one_term_with_bindings`) with the goal (to do :term:`backward reasoning`) or with a hypothesis (to do :term:`forward reasoning`). Specifying multiple :n:`@one_term_with_bindings` is equivalent to giving each one serially, left to right, as separate `apply` tactics. The type of :n:`@one_term` contains zero or more :term:`premises ` followed by a :ref:`conclusion `, i.e. it typically has the form :n:`{? forall @open_binders , } {* @term__premise -> } @term__conclusion`. (The ``forall``\s may also be interleaved with the premises, but common usage is to equivalently gather them at the beginning of the :n:`@one_term`.) Backward reasoning with a :n:`@one_term` whose type is, for example, `A -> B` replaces an as-yet unproven goal `B` with `A`. Forward reasoning with the same :n:`@one_term` changes a hypothesis with type `A` to `B`. (Hypotheses are considered proven propositions within the context that contains them.) Unification creates a map from the variables in the type of :n:`@one_term` to matching subterms of the goal or hypothesis. The matching subterms are then substituted into the type of :n:`@one_term` when generating the updated goal or hypothesis. Unmatched premises become new subgoals with similar substitutions. If no match is found, the tactic fails. Setting :opt:`Debug` ``"tactic-unification"`` enables printing traces of unification steps in tactic unification. Tactic unification is used in tactics such as :tacn:`apply` and :tacn:`rewrite`. The goal and hypothesis cases are described separately for clarity. .. _unused1: .. the dummy ref name is needed to get correct formatting of the next line and "Without..." :n:`@one_term` (inside :n:`@one_term_with_bindings`) If :n:`@one_term` is an :n:`@ident`, it is the name of a theorem, lemma or hypothesis whose type is given in the theorem statement or shown in the context. Otherwise it is a proof term whose type can be displayed with :cmd:`Check` :n:`@one_term`. Without :n:`@in_hyp_as` (the goal case) If the goal matches all of the type of :n:`@one_term` (both premises and the conclusion), the tactic proves the goal. Otherwise, the tactic matches the goal against the conclusion of :n:`@one_term` and, if possible, one or more premises (from right to left). If the match succeeds, the tactic replaces the current goal with a subgoal for each unmatched premise of the type of :n:`@one_term`. This :ref:`example ` matches only the conclusion, while this :ref:`one ` also matches a premise. If the conclusion of the type of :token:`one_term` does not match the goal *and* the conclusion is an inductive type with a single constructor, then each premise in the constructor is recursively matched to the goal in right-to-left order and the first match is used. In this case, the tactic will not match premises that would result in applying a lemma of the form ``forall A, … -> A``. See example :ref:`here `. .. _apply_with_second_order_unification: The goal case uses first-order unification with dependent types unless the conclusion of the type of :token:`term` is of the form :n:`P t__1 … t__n` with :n:`P` to be instantiated. In the latter case, the behavior depends on the form of the target. If the target is of the form :n:`Q u__1 … u__n` and the :n:`t__i` and :n:`u__i` unify, then :n:`P` is instantiated into :n:`Q`. Otherwise, :tacn:`apply` tries to define :n:`P` by abstracting over :n:`t__1 … t__n` in the target. You can use :tacn:`pattern` to transform the target so that it gets the form :n:`(fun x__1 … x__n => Q) u__1 … u__n`. See the example :ref:`here `. :n:`@in_hyp_as` (the hypothesis case) Proceeding from *right to left*, find the first premise of the type of :n:`@one_term` that matches the specified hypothesis. If a match is found, the hypothesis is replaced with the conclusion of the type of :n:`@one_term` (substituting for the unified variables) and the tactic creates a new subgoal for each unmatched premise. See the example :ref:`here `. If specified, :n:`as @simple_intropattern` is applied to the conclusion of the type of :n:`@one_term`. In this case, the selected hypothesis is left unchanged if its name is not reused. If the type of :n:`@one_term` is an inductive type with a single constructor, then each premise in the constructor is recursively matched to the conclusion of the hypothesis in right-to-left order and the first match is used. See example :ref:`here `. For the hypothesis case, matching is done only with first-order unification. :n:`with @bindings` (in :n:`@one_term_with_bindings`) Gives explicit instantiations for variables used in the type of :n:`@one_term`. There are 3 cases: - Bindings for variables can be provided in a list of :n:`@one_term`\s in the left-to-right order of their first appearance in the type of :n:`@one_term`. For the goal case (:ref:`example `), the list should give bindings only for variables that aren't bound by unification. However, in the hypothesis case (:ref:`example `), the list must include bindings for *all* variables. - Bindings for unbound variables can be given by name with the :n:`(@ident := @term)` form. - The form :n:`(@natural := @term)` binds additional variables by unifying the Nth premise of the type of :n:`@one_term` with :n:`@term`. (Use `1` for the first premise.) .. exn:: Unable to unify @one_term with @one_term. The :tacn:`apply` tactic failed to match the conclusion of :token:`one_term`. You can help :tacn:`apply` by transforming your goal with the :tacn:`change` or :tacn:`pattern` tactics. .. exn:: Unable to apply lemma of type "..." on hypothesis of type "...". This happens if the conclusion of :token:`ident` does not match any of the premises of the type of :token:`one_term`. .. exn:: Unable to find an instance for the variables {+ @ident}. This occurs when some instantiations of the premises of :token:`one_term` are not deducible from the unification. This is the case, for instance, when you want to apply a transitivity property. To fix this, add bindings for the :n:`@ident`\s using to :n:`with @bindings` or use :tacn:`eapply`. .. todo: we should be listing things like "Debug tactic-unification" in in the options index. Maybe we should add ":debug:" as a new tag. .. _apply_backward: .. example:: Backward reasoning in the goal with `apply` .. rocqtop:: reset none Goal forall A B C: Prop, (A -> B -> C) -> C. .. rocqtop:: out intros A B C H. .. rocqtop:: all apply H. (* replace goal with new goals for unmatched premises of H *) .. _apply_backward_w_premises: .. example:: Backward reasoning in the goal with `apply` including a premise .. rocqtop:: reset none Goal forall A B C: Prop, (A -> B -> C) -> (B -> C). .. rocqtop:: out intros A B C H. .. rocqtop:: all apply H. (* match on "B -> C", replace goal with "A" *) .. _apply_forward: .. example:: Forward reasoning in hypotheses with `apply` .. rocqtop:: reset none Goal forall A B C: Prop, B -> (A -> B -> C) -> True. .. rocqtop:: out intros A B C H0 H1. .. rocqtop:: all apply H1 in H0. (* change H0, create new goals for unmatched premises of H1 *) .. _apply_with_binding_goal: .. example:: Apply a theorem with a binding in a goal :tacn:`apply` unifies the conclusion `n <= p` of the theorem `le_trans : forall n m p, n <= m -> m <= p -> n <= p` with the goal, assigning `x * x` and `y * y` in the goal to, repectively, `n` and `p` in theorem (backward reasoning). The `with` clause provides the binding for `m`: .. rocqtop:: reset none Axiom le_trans : forall n m p, n <= m -> m <= p -> n <= p. Goal forall (x y : nat), x <= y -> x * x <= y * y. .. rocqtop:: out intros x y H0. .. rocqtop:: all apply le_trans with (y * x). .. _apply_with_binding_hyp: .. example:: Apply a theorem with a binding in a hypothesis When applying a theorem in a hypothesis, :tacn:`apply` unifies the hypothesis with one of the premises of the theorem `le_trans : forall n m p, n <= m -> m <= p -> n <= p`. In this case, it unifies with the first premise (`n <= m`) and assigns `x * x` and `y * y` to, respectively, `n` and `m` in the theorem (forward reasoning). The `with` clause provides the binding for `p`. In addition, :tacn:`apply` in a hypothesis isn't as flexible as :tacn:`apply` in the goal: for hypotheses, the unbound variable can be bound by name (as shown) or values for all the variables can be given positionally, i.e. `apply Nat.le_trans with (x * x) (y * y) (y * x) in H.` .. rocqtop:: reset none Axiom le_trans : forall n m p, n <= m -> m <= p -> n <= p. Goal forall (x y : nat), x * x <= y * y -> x <= y. .. rocqtop:: out intros x y H. .. rocqtop:: all apply le_trans with (p := y * x) in H. .. _apply_with_iff: .. example:: Applying theorems with `<->` .. Note: :n:`/\` and :n:`/\\` don't give the desired output. A bug. :n:`A <-> B` is defined as :n:`(A -> B) /\ (B -> A)`. `/\\` represents an inductive type with a single constructor: :n:`Inductive and (C D:Prop) : Prop := conj : C -> D -> D /\ C`. The premises of :n:`conj` are :n:`C` and :n:`D`. The tactic uses the first matching constructor premise in right-to-left order. Theorems that use :n:`<->` to state a logical equivalence behave consistently when applied to goals and hypotheses. .. rocqtop:: reset none Goal forall (A B: Prop) (H1: A <-> B) (H: A), A. .. rocqtop:: out intros A B H1 H. .. rocqtop:: all apply H1. apply H1 in H. .. _example_apply_pattern: .. example:: Special case of second-order unification in apply Shows the use of the special case second-order unification described :ref:`here ` (after "unless"). Note that we usually use :tacn:`induction` rather than applying ``nat_ind`` directly. .. rocqtop:: reset none Goal forall x y, x + y = y + x. .. rocqtop:: out intros. .. rocqtop:: all Check nat_ind. apply nat_ind. (* Notice the goals are unprovable. *) Show Proof. (* apply has instantiated P with (eq (x + y)) because the goal was (eq (x + y) (y + x)) and n could be unified with (y + x) *) (* However, we can use the pattern tactic to get the instantiation we want: *) Undo. pattern x. apply nat_ind. Show Proof. (* apply has instantiated P with (fun n : nat => n + y = y + n) and the goal can be proven *) .. tacn:: eapply {+, @one_term_with_bindings } {? @in_hyp_as } Behaves like :tacn:`apply`, but creates :ref:`existential variables ` when Rocq is unable to deduce instantiations for variables, rather than failing. .. tacn:: rapply @one_term Behaves like :tacn:`eapply` but uses the proof engine of :tacn:`refine` to handle existential variables, holes and conversion problems. This may result in slightly different behavior regarding which conversion problems are solvable. However, :tacn:`rapply` fails if any holes remain in :n:`@one_term` itself after typechecking and typeclass resolution but before unification with the goal. Note that :tacn:`rapply` tries to instantiate as many hypotheses of :n:`@one_term` as possible. As a result, if it is possible to apply :n:`@one_term` to arbitrarily many arguments without getting a type error, :tacn:`rapply` will loop. .. tacn:: simple apply {+, @one_term_with_bindings } {? @in_hyp_as } Behaves like :tacn:`apply` but it reasons modulo conversion only on subterms that contain no variables to instantiate and does not traverse tuples. For instance, the following example fails because it would require converting ``id ?foo`` and :g:`O`. .. _simple_apply_ex: .. example:: .. rocqtop:: reset all Definition id (x : nat) := x. Parameter H : forall x y, id x = y. Goal O = O. Fail simple apply H. Because it reasons modulo a limited amount of conversion, :tacn:`simple apply` fails faster than :tacn:`apply` and it is thus well-suited for use in user-defined tactics that backtrack often. .. tacn:: simple eapply {+, @one_term_with_bindings } {? @in_hyp_as } :undocumented: .. tacn:: lapply @one_term Splits a :n:`@one_term` in the goal reducible to the form `A -> B`, replacing it with two new subgoals `A` and `B -> G`. ``lapply H`` (where `H` is `A -> B` and `B` does not start with a product) is equivalent to :tacn:`cut` ``B. 2:apply H.``. .. exn:: lapply needs a non-dependent product. :undocumented: .. example:: Assume we have a transitive relation ``R`` on ``nat``: .. rocqtop:: reset in Parameter R : nat -> nat -> Prop. Axiom Rtrans : forall x y z:nat, R x y -> R y z -> R x z. Parameters n m p : nat. Axiom Rnm : R n m. Axiom Rmp : R m p. Consider the goal ``(R n p)`` provable using the transitivity of ``R``: .. rocqtop:: in Goal R n p. The direct application of ``Rtrans`` with ``apply`` fails because no value for ``y`` in ``Rtrans`` is found by ``apply``: .. rocqtop:: all fail apply Rtrans. A solution is to ``apply (Rtrans n m p)`` or ``(Rtrans n m)``. .. rocqtop:: all apply (Rtrans n m p). Note that ``n`` can be inferred from the goal, so the following would work too. .. rocqtop:: in restart apply (Rtrans _ m). More elegantly, ``apply Rtrans with (y:=m)`` allows only mentioning the unknown m: .. rocqtop:: in restart apply Rtrans with (y := m). Another solution is to mention the proof of ``(R x y)`` in ``Rtrans`` .. rocqtop:: all restart apply Rtrans with (1 := Rnm). … or the proof of ``(R y z)``. .. rocqtop:: all restart apply Rtrans with (2 := Rmp). On the opposite, one can use ``eapply`` which postpones the problem of finding ``m``. Then one can apply the hypotheses ``Rnm`` and ``Rmp``. This instantiates the existential variable and completes the proof. .. rocqtop:: all restart abort eapply Rtrans. apply Rnm. apply Rmp. .. todo the following title isn't the greatest. Perhaps more like "trivial tactics" or "simple tactics"??? .. _managingthelocalcontext: ========================== Managing the local context ========================== .. tacn:: intro {? @ident } {? @where } Applies the :tacn:`hnf` tactic until it finds an item that can be introduced in the context by removing certain constructs in the goal. If no item is found, the tactic fails. The name used is :n:`@ident` (if specified) or from the construct, except that if the name from the construct already exists in the :term:`local context`, Rocq uses a fresh name instead. The constructs have these forms: (See examples :ref:`here `.) :n:`forall x : T, @term` `x : T` is a :term:`dependent premise`. Removes `forall x : T,` from the goal and adds `x : T` to the context. :n:`A -> …` `A` is a :term:`non-dependent premise`. Removes `A ->` from the goal and adds `H : A` to the context. :n:`let x := c, @term` Removes `let x := c,` from the goal and adds `x := c : T` to the context. .. _warn_should_give_name_in_intro: We recommend always specifying :n:`@ident` so that the names of hypotheses don't change as the proof is updated, making your proof easier to maintain. For example, if H exists in the context, Rocq will consider using `H0`, `H1`, ... until it finds an unused name. Modifications to a proof can change automatically assigned names that subsequent tactics likely refer to, making the proofs harder to maintain. The :flag:`Mangle Names` flag gives some control over how fresh names are generated (see :ref:`proof-maintenance`). Note that :tacn:`intros` lets you introduce multiple items into the context with a single tactic. :n:`@ident` The name to give to the introduced item. If not given, Rocq uses the variable name from the :n:`forall` or `H` for premises. If a name such as `H` is already in use, Rocq will consider using `H0`, `H1`, ... until it finds a fresh name. .. note:: If a hypothesis name hides the base name of a global constant then the latter can still be referred to by a qualified name (see :ref:`Qualified-names`). :n:`@where` Indicates where to place the introduced hypothesis: at the top or bottom of the context or before or after another specified hypothesis. The default is `at bottom`. .. exn:: @ident is already used. The provided :n:`@ident` is already used in the :term:`local context`. .. exn:: No product even after head-reduction. There is nothing to introduce even after :tacn:`hnf` has been completely applied. .. _intro_examples: .. example:: `intro` and `intros` .. rocqtop:: reset out Goal forall m n, m < n -> (let x := 0 in True). .. rocqtop:: all intro m. intro n. intro H. intro x. This single `intros` tactic is equivalent to the 4 preceding `intro` tactics: .. rocqtop:: reset out Goal forall m n, m < n -> (let x := 0 in True). .. rocqtop:: all intros m n H x. .. tacn:: intros {* @intropattern } intros until {| @ident | @natural } The first form introduces zero or more items into the context from the constructs listed in :tacn:`intro`. If :n:`@intropattern` is not specified, the tactic introduces items until it reaches the :term:`head constant`; it never fails and may leave the context unchanged. If :n:`@intropattern` is specified, the :tacn:`hnf` tactic is applied until it finds an item that can be introduced into the context. The :n:`@intropattern` is often just a list of :n:`@ident`\s, but other forms can also be specified in order to, for example, introduce all :term:`dependent premises ` (`*`); introduce all dependent and :term:`non-dependent premises ` (`**`); split terms such as `A /\\ B` (`[]`) and pick a fresh name with a given prefix (`?X`). See :ref:`intropatterns`. The second form repeats :n:`intro` until it has introduced a :term:`dependent premise` with the name :n:`@ident` or has introduced :n:`@natural` :term:`premises ` (like ``A`` in ``A -> B``). We recommend explicitly naming items with :tacn:`intros` instead of using :n:`intros until @natural`. See the explanation :ref:`here `. .. example:: intros until .. rocqtop:: reset out Goal forall x y : nat, x = y -> y = x. .. rocqtop:: all intros until y. Or: .. rocqtop:: reset out Goal forall x y : nat, x = y -> y = x. .. rocqtop:: all intros until 1. .. exn:: No quantified hypothesis named @ident in current goal even after head-reduction. The :n:`@ident` in the ``until`` clause doesn't appear as a :term:`dependent premise`. .. exn:: No @natural-th non dependent hypothesis in current goal even after head-reduction. There are fewer than :n:`@natural` premises in the goal. .. tacn:: eintros {* @intropattern } Works just like :tacn:`intros` except that it creates existential variables for any unresolved variables rather than failing. Typically this happens when using a ``%`` intropattern (see :n:`@simple_intropattern`). .. tacn:: clear {? {? - } {+ @ident } } Erases *unneeded* hypotheses from the context of the current goal. "Unneeded" means that the unselected hypotheses and the goal don't refer directly or indirectly to the erased hypotheses. That means the hypotheses will no longer appear in the context and therefore can't be used in subsequent proof steps. Note that erasing an uneeded hypothesis may turn a goal that was provable into an unprovable goal. :n:`clear` All unneeded hypotheses are erased. This may leave the context unchanged; this form never fails. :n:`clear {+ @ident }` Erases the named hypotheses if they are unneeded and fails otherwise. .. exn:: @ident is used in the conclusion. :undocumented: .. exn:: @ident is used in the hypothesis @ident. :undocumented: :n:`clear - {+ @ident }` Selects all hypotheses that are not named by the :n:`@ident`\s, then erases those that are unneeded. This may leave the context unchanged; this form never fails as long as the :n:`@ident`\s name hypotheses in the context. .. tacn:: clearbody {+ @ident } This tactic expects :n:`{+ @ident}` to be :term:`local definitions ` and clears their respective bodies. In other words, it turns the given definitions into assumptions. .. exn:: @ident is not a local definition. :undocumented: .. tacn:: clear dependent @ident Clears the hypothesis :token:`ident` and all the hypotheses that depend on it. .. tacn:: revert {+ @ident } Moves the specified hypotheses and :term:`local definitions ` to the goal, if this respects dependencies. This is the inverse of :tacn:`intro`. .. tacn:: revert dependent @ident .. deprecated:: 8.18 An alias for :tacn:`generalize dependent`. .. tacn:: move @ident__from @where .. insertprodn where where .. prodn:: where ::= at top | at bottom | before @ident | after @ident Moves a hypothesis :n:`@ident__from` and hypotheses that directly or indirectly refer to :n:`@ident__from` that appear between :n:`@ident__from` and :n:`@ident`. `at top` and `at bottom` are equivalent to giving the name of the first or last hypotheses in the context. The dependent hypotheses will appear after :n:`@ident__from`, appearing in dependency order. This lets users show and group hypotheses in the order they prefer. It doesn't change the goal or the proof term. .. todo: "at top and at bottom are equivalent to giving the name of the first or last hypotheses in the context." Equivalent to "after first" and "after last"?? .. note:: Perhaps confusingly, "before" and "after" are interpeted with respect to the direction in which the hypotheses are moved rather than in the order of the resulting list of hypotheses. If :n:`@ident__from` is before :n:`@ident` in the context, these notions are the same: for hypotheses `A B C`, `move A after B` gives `B A C`, whereas if :n:`@ident__from` is after :n:`@ident` in the context, they are the opposite: `move C after A` gives `C A B` because the direction of movement is reversed. .. todo This is dreadful behavior .. exn:: Cannot move @ident__from after @ident: it occurs in the type of @ident. :undocumented: .. exn:: Cannot move @ident__from after @ident: it depends on @ident. :undocumented: .. example:: move .. rocqtop:: reset none Goal forall x :nat, x = 0 -> forall y z:nat, y=y-> 0=x. .. rocqtop:: out intros x Hx y z Hy. .. rocqtop:: in (* x Hx y z Hy *) move y after z. (* x Hx z y Hy (z was left of y, intuitive case) *) Undo. move z after y. (* x Hx z y Hy (z was right of y, see Note above) *) Undo. move x after Hy. (* y z Hy x Hx (Hx depends on x, so moved) *) Undo. move x before Hy. (* y z x Hx Hy *) Undo. move Hy after Hx. (* x y Hy Hx z *) Undo. move Hy before Hx. (* x Hx y Hy z *) .. tacn:: rename {+, @ident__1 into @ident__2 } Renames hypothesis :n:`@ident__1` into :n:`@ident__2` for each pair of :n:`@ident`\s. Renaming is done simultaneously, which permits swapping the names of 2 hypotheses. (Note that the renaming is applied in the context and the existential variables, but the proof term doesn't change.) .. tacn:: set @alias_definition {? @occurrences } set @one_term {? @as_name } {? @occurrences } :name: set; _ .. insertprodn alias_definition as_name .. prodn:: alias_definition ::= ( @ident {* @simple_binder } := @term ) simple_binder ::= @name | ( {+ @name } : @term ) as_name ::= as @ident The first form adds a new local definition :n:`@ident := …`. If :n:`@simple_binder` is not specified, the definition body is :n:`@term` and otherwise :n:`fun {* @simple_binder } => @term`. Then the tactic replaces the body expression with the new variable :n:`@ident` in the goal or as specified by :n:`@occurrences`. The tactic may succeed and add the local definition even if no replacements are made. The second form is equivalent to :n:`set (@ident := @one_term) {? @occurrences }` using :n:`@ident`, if present, or an auto-generated name if not provided. If :token:`term` or :token:`one_term` has holes (i.e. subexpressions with the form β€œ`_`”), the tactic first checks that all subterms matching the pattern are compatible before doing the replacement using the leftmost subterm matching the pattern. .. exn:: The variable @ident is already declared. :undocumented: .. example:: set with a :n:`@simple_binder` :n:`set` does a simple syntactic replacement in the goal: .. rocqtop:: reset none Goal forall n, n = 0. .. rocqtop:: out intros. .. rocqtop:: all pattern n. (* without this, "set" won't replace anything in the goal *) set (f x := x = 0). .. tacn:: eset @alias_definition {? @occurrences } eset @one_term {? @as_name } {? @occurrences } :name: eset; _ Similar to :tacn:`set`, but instead of failing because of uninstantiated variables, generates existential variables for them. In practice, this is relevant only when :tacn:`eset` is used as a synonym of :tacn:`epose`, i.e. when the :token:`term` does not occur in the goal. .. tacn:: remember @one_term {? @as_name } {? eqn : @naming_intropattern } {? in @goal_occurrences } Similar to :tacn:`set` :n:`(@ident := @one_term) in *` but creates a hypothesis using :term:`Leibniz equality` to remember the relation between the introduced variable and the term rather than creating a :term:`local definition `. If :n:`@as_name` is not specified a fresh name is used. Use :n:`@naming_intropattern` to name the new equation. .. tacn:: eremember @one_term {? @as_name } {? eqn : @naming_intropattern } {? in @goal_occurrences } Similar to :tacn:`remember`, but instead of failing because of uninstantiated variables, generates existential variables for them. .. tacn:: pose @alias_definition pose @one_term {? @as_name } :name: pose; _ Similar to :tacn:`set`. Adds a :term:`local definition ` to the context but without doing any replacement. .. tacn:: epose @alias_definition epose @one_term {? @as_name } :name: epose; _ Similar to :tacn:`pose`, but instead of failing because of uninstantiated variables, generates existential variables for them. .. todo: the following title seems inappropriate. How about something more like "Introducing new hypotheses", as in adding arbitrary terms rather than transformations of existing terms?? But then I think the tactics in the previous section (set, remember, pose, maybe decompose) should be moved into this section. But maybe hard to make the section seem like an crisp, intuitive grouping. I can do the moving that after we've reviewed all the text. WDYT? See https://github.com/rocq-prover/rocq/pull/16498#discussion_r989928078 .. _controllingtheproofflow: ========================== Controlling the proof flow ========================== .. tacn:: assert ( @ident : @type ) {? by @ltac_expr3 } assert ( @ident := @term ) assert @one_type {? @as_ipat } {? by @ltac_expr3 } :name: assert; _; _ Adds a new hypothesis to the current subgoal and a new subgoal before it to prove the hypothesis. Then, if :n:`@ltac_expr3` is specified, it applies that tactic to fully prove the new subgoal (and otherwise fails). The first form adds a new hypothesis named :n:`@ident` of type :n:`@type`. (This corresponds to the cut rule of sequent calculus.) The second form is equivalent to :n:`assert (@ident : @type) by exact (@term)` where :n:`@type` is the type of :n:`@term`. It is also equivalent to using :tacn:`pose proof`. If the head of :n:`@term` is :n:`@ident`, the tactic is equivalent to :tacn:`specialize`. In the third form, if :n:`@as_ipat` isn't specified, the tactic adds the hypothesis :n:`@one_type` with a fresh name. Otherwise, it transforms the hypothesis as specified by :n:`@as_ipat` and adds the resulting new hypotheses and goals. See :ref:`intropatterns`. .. exn:: The term "@type" has type "@type__1" which should be Set, Prop or Type. Occurs when the argument :n:`@type` (in the first form) or :n:`@one_type` (in the third form) is not of type :g:`Prop`, :g:`Set` nor :g:`Type`. .. exn:: Proof is not complete. :name: Proof is not complete. (assert) :n:`@ltac_expr3` was not able to prove the new hypothesis. .. tacn:: eassert ( @ident : @type ) {? by @ltac_expr3 } eassert ( @ident := @term ) eassert @one_type {? @as_ipat } {? by @ltac_expr3 } :name: eassert; _; _ Unlike :tacn:`assert`, the :n:`@type`, :n:`@term` or :n:`@one_type` in :tacn:`eassert` may contain :gdef:`holes `, denoted by :n:`_`, for which the tactic will create existential variables. This lets you avoid specifying the asserted statement completely before starting to prove it. .. tacn:: enough ( @ident : @type ) {? by @ltac_expr3 } enough @one_type {? @as_ipat } {? by @ltac_expr3 } :name: enough; _ Adds a new hypothesis to the current subgoal and a new subgoal after it to prove the hypothesis. The first form adds a new hypothesis :n:`@ident : @type` and :n:`@type` as the new subgoal. Then, if :n:`@ltac_expr3` is specified, it applies that tactic to prove the current subgoal with the added hypothesis (and otherwise fails). In the second form, if :n:`@as_ipat` isn't specified, the tactic adds a new hypothesis :n:`@one_type` with a name chosen by Rocq. Otherwise, it transforms :n:`@one_type` as specified by :n:`@as_ipat` and adds the resulting new hypotheses. The :n:`@as_ipat` may also expand the current subgoal into multiple subgoals. Then, if :n:`@ltac_expr3` is specified, it is applied to and must succeed on all of them. .. tacn:: eenough ( @ident : @type ) {? by @ltac_expr3 } eenough @one_type {? @as_ipat } {? by @ltac_expr3 } :name: eenough; _ Unlike :tacn:`enough`, the :n:`@type` and :n:`@one_type` in :tacn:`eenough` may contain :term:`holes `, denoted by :n:`_`, for which the tactic will create existential variables. This lets you avoid specifying the asserted statement completely until you start to use the hypothesis or later start to prove the statement. .. tacn:: cut @one_type Implements the non-dependent case of the :ref:`App ` typing rule, the Modus Ponens inference rule. It is equivalent to :n:`enough (@ident: @one_type). revert @ident.` This tactic is generally considered obsolete but it is still widely used in old scripts. .. tacn:: pose proof @term {? @as_ipat } pose proof ( @ident := @term ) :name: pose proof; _ The first form behaves like :n:`assert @one_type {? @as_ipat } by exact @term` where :token:`one_type` is the type of :token:`term`. .. ThΓ©o notes it's odd that the first form uses @term instead of @one_term The second form is equivalent to :n:`assert (@ident := @term)`. .. tacn:: epose proof @term {? @as_ipat } epose proof ( @ident := @term ) :name: epose proof; _ While :tacn:`pose proof` expects that no existential variables are generated by the tactic, :tacn:`epose proof` removes this constraint. .. tacn:: specialize @one_term_with_bindings {? @as_ipat } Specializes a term (typically a hypothesis or a lemma) by applying arguments to it. *First*, the tactic generates a modified term: If the :term:`head constant` of :n:`@one_term` (in :n:`@one_term_with_bindings`) has the type `forall ...`, the tactic replaces one or more of the quantified variables in the type with arguments provided by :n:`@one_term_with_bindings`, either in the form of a :ref:`function application ` (which may be partial), such as `(H 1)`, or with named or numbered binders, such as `H with (n:=1)`. If the :term:`head constant` has a :term:`non-dependent product` type such as `A -> B -> C`, the tactic eliminates one or more of the premises (doing :term:`forward reasoning`). Uninstantiated arguments are inferred by unification, if possible, or otherwise left quantified in the resulting term. *Then*, If the :term:`head constant` is a hypothesis :n:`H`, the resulting term replaces that hypothesis. Specifying :n:`@as_ipat` will leave the original hypothesis unchanged and will introduce new hypotheses as specified by the :token:`simple_intropattern`. If :n:`H` appears in the conclusion or another hypothesis, you must use :n:`@as_ipat` to give a fresh hypothesis name. If the head constant is a lemma or theorem, the resulting term is added as a new premise of the goal so that the behavior is similar to that of :tacn:`generalize`. In this case, you can use :n:`@as_ipat` to immediately introduce the modified term as one or more hypotheses. .. exn:: Cannot change @ident, it is used in hypothesis @ident. :undocumented: .. exn:: Cannot change @ident, it is used in conclusion. :undocumented: .. example:: partial application in :tacn:`specialize` .. rocqtop:: reset none Goal (forall n m: nat, n + m = m + n) -> True. .. rocqtop:: out intros. .. rocqtop:: all specialize (H 1). (* equivalent to: specialize H with (n := 1) *) .. example:: :tacn:`specialize` with a non-dependent product Compare this to a similar :ref:`example ` that uses :tacn:`apply`. :tacn:`specialize` won't introduce new goals as :tacn:`apply` can. .. rocqtop:: reset none Goal forall A B C: Prop, B -> (A -> B -> C) -> True. Proof. .. rocqtop:: out intros A B C H0 H1. .. rocqtop:: all specialize H1 with (2:=H0). .. tacn:: specialize_eqs @ident :undocumented: .. tacn:: generalize {+ @one_term } generalize {+, @pattern_occs {? @as_name } } :name: generalize; _ For each :n:`@one_term` (which may be in the :n:`@pattern_occs`), replaces the goal `G` with `forall (x:T), G'`, where :n:`@one_term` is a subterm of `G` of type `T` and `G'` is obtained by replacing all occurrences of :n:`@one_term` with `x` within `G`. `x` is a fresh variable chosen based on `T`. Specifying multiple :n:`@one_term`\s is equivalent to :n:`generalize @one_term__n; … ; generalize @one_term__1`. (Note they are processed *right to left*.) :n:`@as_name` The name to use for `x` instead of a fresh name. .. example:: .. rocqtop:: reset none Goal forall x y:nat, 0 <= x + y + y. Proof. intros *. .. rocqtop:: out Show. .. rocqtop:: all abort generalize (x + y + y). (* get a simpler goal that can be proven by induction *) .. tacn:: generalize dependent @one_term Generalizes :n:`@one_term` and all hypotheses that depend on :n:`@one_term`. It clears the generalized hypotheses. .. tacn:: dependent generalize_eqs @ident :undocumented: .. tacn:: dependent generalize_eqs_vars @ident :undocumented: .. tacn:: generalize_eqs @ident :undocumented: .. tacn:: generalize_eqs_vars @ident :undocumented: .. tacn:: evar ( @ident : @type ) evar @one_type :name: evar; _ The :n:`evar` tactic creates a new :term:`local definition ` named :n:`@ident` with type :n:`@type` or :n:`@one_type` in the context. The body of this binding is a fresh existential variable. If the second form is used, Rocq chooses the name. .. tacn:: instantiate ( @ident := @term ) instantiate ( @natural := @term ) {? @hloc } :name: instantiate; _ .. insertprodn hloc hloc .. prodn:: hloc ::= in %|- * | in @ident | in ( type of @ident ) | in ( value of @ident ) The first form refines (see :tacn:`refine`) an existential variable :n:`@ident` with the term :n:`@term`. It is equivalent to :n:`only [@ident]: refine @term`. .. note:: To be able to refer to an existential variable by name, the user must have given the name explicitly (see :ref:`Existential-Variables`). .. note:: When you are referring to hypotheses which you did not name explicitly, be aware that Rocq may make a different decision on how to name the variable in the current goal and in the context of the existential variable. This can lead to surprising behaviors. The second form refines an existential variable selected by its position. The :n:`@natural` argument is the position of the existential variable *from right to left* in the goal. (Use the :n:`@hloc` clause to select an existential variable in a hypothesis.) Counting starts at 1 and multiple occurrences of the same existential variable are counted multiple times. Using this form is discouraged because slight changes to the goal may change the needed index, causing a maintenance issue. Advanced users may want to define and use an Ltac tactic to get more consistent behavior, such as: .. rocqdoc:: Ltac instantiate_ltac_variable ev term := let H := fresh in pose ev as H; instantiate (1 := term) in (value of H); clear H. :n:`in @ident` Selects the hypothesis :n:`@ident`. :n:`in %|- *` Selects the goal. This is the default behavior. :n:`in ( type of @ident )` Selects existential variables in the type of the :term:`local definition ` :n:`@ident`. (The body is not included.) :n:`in ( value of @ident )` Selects existential variables in the body of the :term:`local definition ` :n:`@ident`. (The type is not included.) .. tacn:: absurd @one_type :n:`@one_type` is any proposition :g:`P` of type :g:`Prop`. This tactic applies False elimination, that is it deduces the current goal from False, and generates as subgoals :g:`∼P` and :g:`P`. It is very useful in proofs by cases, where some cases are impossible. In most cases, :g:`P` or :g:`∼P` is one of the hypotheses of the local context. .. tacn:: contradiction {? @one_term_with_bindings } Tries to prove the current goal by finding a contradiction. If :n:`@one_term_with_bindings` is not provided (the most common use case), the tactic first does an :tacn:`intros`. The tactic then proves the goal if - the updated context has a pair of hypotheses where one is the negation of the other (e.g. :n:`P` and not :n:`~P`), or - there is a hypothesis with an empty inductive type (e.g. :n:`False`), or - there is a hypothesis :n:`~P` where `P` is a singleton inductive type (e.g. :n:`True` or :n:`x=x`) provable by `Goal P. constructor.` If :n:`@one_term_with_bindings` is provided, its type must be a negation, such as :n:`~P`, or an empty inductive type, such as :n:`False`. If the type is a negation and :n:`P` is a hypothesis in the context, the goal is proven. If the type is a negation and :n:`P` is not in the context, the goal is replaced with :n:`P`. If the type is :n:`False` or another empty inductive type, the goal is proven. Otherwise the tactic fails. (If there is a hypothesis `P` and you want to replace the goal with `~P`, use the :tacn:`contradict` tactic. If there are hypotheses `H1 : P` and `H2 : ~P`, use `contradiction` without arguments or `contradiction H2` since `contradiction H1` won't work.) Use the :tacn:`discriminate` tactic to prove the current goal when there is a hypothesis with an impossible structural equality such as :n:`0 = 1`. .. example:: :tacn:`contradiction` tactic Simple examples. To see more detail, add `intros` after each `Goal`. .. rocqtop:: reset in Inductive F :=. (* Another empty inductive type *) Goal F -> False. contradiction. Qed. Goal forall (A : Prop), A -> ~A -> False. contradiction. Qed. Goal forall (A : Type) (x : A), ~(x = x) -> False. contradiction. Qed. Apply a fact from the standard library: .. rocqtop:: none Axiom lt_irrefl : forall x, ~ (x < x). .. rocqtop:: in Goal forall (A : Prop), 0 < 0 -> A. .. rocqtop:: all intros. contradiction (lt_irrefl 0). Qed. .. tacn:: contradict @ident Transforms the specified hypothesis :n:`@ident` and the goal in order to prove that the hypothesis is false. For :n:`contradict H`, the current goal and context are transformed as shown. (For brevity, `⊒` is used to separate hypotheses from the goal; it is equivalent to the dividing line shown in a context.): + `H: ~A ⊒ B` becomes `⊒ A` + `H: ~A ⊒ ~B` becomes `H: B ⊒ A` + `H: A ⊒ B` becomes `⊒ ~A` + `H: A ⊒ ~B` becomes `H: B ⊒ ~A` .. tacn:: exfalso Implements the β€œex falso quodlibet” logical principle: an elimination of False is performed on the current goal, and the user is then required to prove that False is indeed provable in the current context. ================= Classical tactics ================= In order to ease the proving process, when the ``Classical`` module is loaded, a few more tactics are available. Make sure to load the module using the :cmd:`Require Import` command. .. tacn:: classical_left classical_right These tactics are the analog of :tacn:`left` and :tacn:`right` but using classical logic. They can only be used for disjunctions. Use :tacn:`classical_left` to prove the left part of the disjunction with the assumption that the negation of right part holds. Use :tacn:`classical_right` to prove the right part of the disjunction with the assumption that the negation of left part holds. ==================================== Performance-oriented tactic variants ==================================== .. todo: move the following adjacent to the `exact` tactic? .. tacn:: exact_no_check @one_term For advanced usage. Similar to :tacn:`exact` :n:`@term`, but as an optimization, it skips checking that :n:`@term` has the goal's type, relying on the kernel check instead. See :tacn:`change_no_check` for more explanation. .. example:: .. rocqtop:: all abort Goal False. exact_no_check I. Fail Qed. .. tacn:: vm_cast_no_check @one_term For advanced usage. Similar to :tacn:`exact_no_check` :n:`@term`, but additionally instructs the kernel to use :tacn:`vm_compute` to compare the goal's type with the :n:`@term`'s type. .. example:: .. rocqtop:: all abort Goal False. vm_cast_no_check I. Fail Qed. .. tacn:: native_cast_no_check @one_term for advanced usage. similar to :tacn:`exact_no_check` :n:`@term`, but additionally instructs the kernel to use :tacn:`native_compute` to compare the goal's type with the :n:`@term`'s type. .. example:: .. rocqtop:: all abort Goal False. native_cast_no_check I. Fail Qed. rocq-9.2.0/doc/sphinx/proof-engine/vernacular-commands.rst000066400000000000000000001357071516144147600236550ustar00rootroot00000000000000.. _vernacularcommands: Commands ======== .. _displaying: Displaying ---------- .. _Print: .. cmd:: Print {? Term } @reference {? @univ_name_list } .. insertprodn univ_name_list univ_name_list .. prodn:: univ_name_list ::= @%{ {* @name } %} Displays definitions of terms, including opaque terms, for the object :n:`@reference`. * :n:`Term` - a syntactic marker to allow printing a term that is the same as one of the various :n:`Print` commands. For example, :cmd:`Print All` is a different command, while :n:`Print Term All` shows information on the object whose name is ":n:`All`". * :n:`@univ_name_list` - locally renames the polymorphic universes of :n:`@reference`. The name `_` means the usual name is printed. .. exn:: @qualid not a defined object. :undocumented: .. exn:: Universe instance length is @natural but should be @natural. :undocumented: .. exn:: This object does not support universe names. :undocumented: .. cmd:: Print All This command displays information about the current state of the environment, including sections and modules. .. cmd:: Inspect @natural This command displays the :n:`@natural` last objects of the current environment, including sections and modules. .. cmd:: Print Section @qualid Displays the objects defined since the beginning of the section named :n:`@qualid`. .. todo: "A.B" is permitted but unnecessary for modules/sections. should the command just take an @ident? Query commands -------------- Unlike other commands, :production:`query_command`\s may be prefixed with a goal selector (:n:`@natural:`) to specify which goals it applies to. If no selector is provided, the command applies to the current goal. If no proof is open, then the command only applies to accessible objects. (see Section :ref:`invocation-of-tactics`). :cmd:`Eval` and :cmd:`Compute` are also :token:`query_command`\s, which are described elsewhere .. cmd:: About @reference {? @univ_name_list } Displays information about the :n:`@reference` object, which may be the name of any accessible defined symbol, such as a theorem, constructor, fixpoint or module. If a proof is open, :n:`@reference` may refer to a hypothesis of the selected goal. The information includes: the kind of the object (module, constant, assumption, inductive, constructor, abbreviation, projection, coercion, …), long name, type, opacity/transparency, implicit arguments, argument names and argument scopes (as set in the definition of :token:`reference` or subsequently with the :cmd:`Arguments` command). It does not print the body of definitions or proofs. See :cmd:`Strategy` for details on opacity. .. cmd:: Check @term Displays the type of :n:`@term`. When called in proof mode, the term is checked in the local context of the selected goal (possibly by using :ref:`single numbered goal selectors`). This command tries to resolve existential variables as much as possible. .. cmd:: Type @term Displays the type of :n:`@term`, same as :cmd:`Check`, but will fail if any existential variables are unable to be resolved. .. cmd:: Search {+ @search_query } {? {| inside | in | outside } {+ @qualid } } This command can be used to filter the goal and the global context to retrieve objects whose name or type satisfies a number of conditions. Searched objects can be filtered by patterns, by the constants they contain (identified by their name or a notation), by their names and by their location (e.g. :n:`head`). Library files that were not loaded with :cmd:`Require` are not considered. The :table:`Search Blacklist` table can also be used to exclude some things from all calls to :cmd:`Search`. The output of the command is a list of qualified identifiers and their types. If the :flag:`Search Output Name Only` flag is on, the types are omitted. .. insertprodn search_query search_query .. prodn:: search_query ::= @search_item | - @search_query | [ {+| {+ @search_query } } ] Multiple :n:`@search_item`\s can be combined into a complex :n:`@search_query`: :n:`- @search_query` Excludes the objects that would be filtered by :n:`@search_query`. See :ref:`this example `. :n:`[ {+ @search_query } | ... | {+ @search_query } ]` This is a disjunction of conjunctions of queries. A simple conjunction can be expressed by having a single disjunctive branch. For a conjunction at top-level, the surrounding brackets are not required. .. insertprodn search_item search_item .. prodn:: search_item ::= {? {| head | hyp | concl | headhyp | headconcl } : } @string {? % @scope_key } | {? {| head | hyp | concl | headhyp | headconcl } : } @one_pattern | is : @logical_kind :n:`@one_pattern` Search for objects whose type contains a subterm matching the pattern :n:`@one_pattern`. Holes of the pattern are indicated by `_` or :n:`?@ident`. If the same :n:`?@ident` occurs more than once in the pattern, all occurrences in the subterm must be identical. See :ref:`this example `. :n:`@string {? % @scope_key }` - If :n:`@string` is a substring of a valid identifier and no :n:`% @scope_key` is provided, search for objects whose name contains :n:`@string`. See :ref:`this example `. - Otherwise, search for objects whose type contains the reference that this string, interpreted as a notation, is attached to (as described in :n:`@reference`). See :ref:`this example `. .. note:: To refer to a string used in a notation that is a substring of a valid identifier, put it between single quotes or explicitly provide a scope. See :ref:`this example `. :n:`hyp:` The provided pattern or reference is matched against any subterm of an hypothesis of the type of the objects. See :ref:`this example `. :n:`headhyp:` The provided pattern or reference is matched against the subterms in head position (any partial applicative subterm) of the hypotheses of the type of the objects. See :ref:`the previous example `. :n:`concl:` The provided pattern or reference is matched against any subterm of the conclusion of the type of the objects. See :ref:`this example `. :n:`headconcl:` The provided pattern or reference is matched against the subterms in head position (any partial applicative subterm) of the conclusion of the type of the objects. See :ref:`the previous example `. :n:`head:` This is simply the union between `headconcl:` and `headhyp:`. :n:`is: @logical_kind` .. insertprodn logical_kind logical_kind .. prodn:: logical_kind ::= {| @thm_token | @assumption_token } | {| Definition | Example | Context | Primitive | Symbol } | {| Coercion | Instance | Scheme | Canonical | SubClass } | {| Fixpoint | CoFixpoint | Field | Method } Filters objects by the keyword that was used to define them (`Theorem`, `Lemma`, `Axiom`, `Variable`, `Context`, `Primitive`...) or its status (`Coercion`, `Instance`, `Scheme`, `Canonical`, `SubClass`, `Field` for record fields, `Method` for class fields). Note that `Coercion`\s, `Canonical Structure`\s, `Instance`\s and `Scheme`\s can be defined without using those keywords. See :ref:`this example `. Additional clauses: * :n:`{| inside | in } {+ @qualid }` - limit the search to the specified modules * :n:`outside {+ @qualid }` - exclude the specified modules from the search The specified modules can be the current file or a currently opened module. For instance, when using Rocq interactively in a file `Foo.v`, the command :g:`Search _ in Foo.` displays every (non-blacklisted) constants previously defined in the file `Foo`. Inside a :cmd:`Module` `A`, :g:`Search _ in A` similarly displays every constant defined up to this point in the :cmd:`Module` `A`. See :ref:`this example `. .. exn:: Module/section @qualid not found. There is no constant in the environment named :n:`@qualid`, where :n:`@qualid` is in an `inside` or `outside` clause. .. _search-pattern: .. example:: Searching for a pattern .. rocqtop:: none reset extra-stdlib From Stdlib Require Import PeanoNat. We can repeat meta-variables to narrow down the search. Here, we are looking for commutativity lemmas. The following example requires the Stdlib library. .. rocqtop:: all Search (_ ?n ?m = _ ?m ?n). .. _search-part-ident: .. example:: Searching for part of an identifier .. rocqtop:: all reset Search "_assoc". .. _search-by-notation: .. example:: Searching for a reference by notation .. rocqtop:: all reset Search "+". .. _search-disambiguate-notation: .. example:: Disambiguating between part of identifier and notation The following example requires the Stdlib library. .. rocqtop:: none reset extra-stdlib From Stdlib Require Import PeanoNat. In this example, we show two ways of searching for all the objects whose type contains `Nat.modulo` but which do not contain the substring "mod". .. rocqtop:: all extra-stdlib Search "'mod'" -"mod". Search "mod"%nat -"mod". .. _search-hyp: .. example:: Search in hypotheses The following search shows the objects whose type contains `bool` in an hypothesis as a strict subterm only: .. rocqtop:: none reset Add Search Blacklist "internal_". .. rocqtop:: all Search hyp:bool -headhyp:bool. .. _search-concl: .. example:: Search in conclusion The following search shows the objects whose type contains `bool` in the conclusion as a strict subterm only: .. rocqtop:: all Search concl:bool -headconcl:bool. .. _search-by-keyword: .. example:: Search by keyword or status The following search shows the definitions whose type is a `nat` or a function which returns a `nat` and the lemmas about `+`: .. rocqtop:: all reset Search [ is:Definition headconcl:nat | is:Lemma (_ + _) ]. The following search shows the instances whose type includes the classes `Reflexive` or `Symmetric`: .. rocqtop:: none reset Require Import Morphisms. .. rocqtop:: all Search is:Instance [ Reflexive | Symmetric ]. The following search outputs operations on `nat` defined in the prelude either with the `Definition` or `Fixpoint` keyword: .. rocqtop:: all reset Search (nat -> nat -> nat) -bool [ is:Definition | is:Fixpoint ]. .. _search-current-module: .. example:: Search in current file or :cmd:`Module` The following example shows how to filter `Search` output in an interactive session. Note that with `rocq top`, the current pseudo-file is named `Top`, it can be replaced with the name of the current file (without the trailing `.v`) when using an IDE. .. rocqtop:: all reset Definition b := 42. Search _ in Top. Module A. Definition a := 12. Search _ in A. End A. Search _ in Top. .. cmd:: SearchPattern @one_pattern {? {| inside | in | outside } {+ @qualid } } Displays the name and type of all hypotheses of the selected goal (if any) and theorems of the current context ending with :n:`{? forall {* @binder }, } {* P__i -> } C` that match the pattern :n:`@one_pattern`. See :cmd:`Search` for an explanation of the `inside`/`in`/`outside` clauses. .. example:: :cmd:`SearchPattern` examples The following example requires the Stdlib library. .. rocqtop:: in reset extra-stdlib From Stdlib Require Import Arith. .. rocqtop:: all extra-stdlib SearchPattern (_ + _ = _ + _). SearchPattern (nat -> bool). SearchPattern (forall l : list _, _ l l). .. rocqtop:: all extra-stdlib SearchPattern (?X1 + _ = _ + ?X1). .. cmd:: SearchRewrite @one_pattern {? {| inside | in | outside } {+ @qualid } } Displays the name and type of all hypotheses of the selected goal (if any) and theorems of the current context that have the form :n:`{? forall {* @binder }, } {* P__i -> } LHS = RHS` where :n:`@one_pattern` matches either `LHS` or `RHS`. See :cmd:`Search` for an explanation of the `inside`/`in`/`outside` clauses. .. example:: :cmd:`SearchRewrite` examples The following example requires the Stdlib library. .. rocqtop:: in reset extra-stdlib From Stdlib Require Import Arith. .. rocqtop:: all extra-stdlib SearchRewrite (_ + _ + _). .. flag:: Search Blacklist Locals By default :cmd:`Search` excludes lemmas declared with :attr:`local` from its results (except for those from the current module or its parents). Unsetting this :term:`flag` will include such lemmas in the results. .. table:: Search Blacklist @string This :term:`table` specifies a set of strings used to exclude lemmas from the results of :cmd:`Search`, :cmd:`SearchPattern` and :cmd:`SearchRewrite` queries. A lemma whose fully qualified name contains any of the strings will be excluded from the search results. The default blacklisted substrings are ``_subterm``, ``_subproof`` and ``Private_``. Use the :cmd:`Add` and :cmd:`Remove` commands to update the set of blacklisted strings. .. flag:: Search Output Name Only This :term:`flag` restricts the output of search commands to identifier names; turning it on causes invocations of :cmd:`Search`, :cmd:`SearchPattern`, :cmd:`SearchRewrite` etc. to omit types from their output, printing only identifiers. .. _requests-to-the-environment: Requests to the environment ------------------------------- .. cmd:: Print Assumptions {+ @reference } Displays all the assumptions (axioms, parameters and variables) one or more theorems or definitions depends on. The message "Closed under the global context" indicates that all the theorems and definitions have no dependencies. .. cmd:: Print Opaque Dependencies {+ @reference } Displays the assumptions and opaque constants that :n:`@reference` depends on. .. cmd:: Print Transparent Dependencies {+ @reference } Displays the assumptions and transparent constants that :n:`@reference` depends on. .. cmd:: Print All Dependencies {+ @reference } Displays all the assumptions and constants :n:`@reference` depends on. .. cmd:: Locate @reference .. insertprodn reference reference .. prodn:: reference ::= @qualid | @string {? % @scope_key } Displays the full name of objects from Rocq's various qualified namespaces such as terms, modules and Ltac, thereby showing the module they are defined in. It also displays notation definitions. Note that objects are reported only when the module containing them has been loaded, such as through a :cmd:`Require` command. Notation definitions are reported only when the containing module has been imported (e.g. with :cmd:`Require Import` or :cmd:`Import`). Objects defined with commands such as :cmd:`Definition`, :cmd:`Parameter`, :cmd:`Record`, :cmd:`Theorem` and their numerous variants are shown as `Constant` in the output. :n:`@qualid` refers to object names that end with :n:`@qualid`. :n:`@string {? % @scope_key }` refers to definitions of notations. :n:`@string` can be a single token in the notation such as "`->`" or a pattern that matches the notation. See :ref:`locating-notations`. :n:`% @scope_key`, if present, limits the reference to the scope bound to the delimiting key :n:`@scope_key`, such as, for example, :n:`%nat`. (see Section :ref:`LocalInterpretationRulesForNotations`) .. todo somewhere we should list all the qualified namespaces .. cmd:: Locate Term @reference Like :cmd:`Locate`, but limits the search to terms .. cmd:: Locate Module @qualid Like :cmd:`Locate`, but limits the search to modules .. cmd:: Locate Ltac @qualid Like :cmd:`Locate`, but limits the search to Ltac tactics .. cmd:: Locate Ltac2 @qualid Like :cmd:`Locate`, but limits the search to Ltac2 tactics. .. cmd:: Locate Library @qualid Displays the full name, status and file system path of the module :n:`@qualid`, whether loaded or not. .. cmd:: Locate File @string Displays the file system path of the file ending with :n:`@string`. Typically, :n:`@string` has a suffix such as ``.cmo`` or ``.vo`` or ``.v`` file, such as :n:`Nat.v`. .. todo: also works for directory names such as "Data" (parent of Nat.v) also "Data/Nat.v" works, but not a substring match .. example:: Locate examples .. rocqtop:: all Locate nat. Locate Datatypes.O. Locate Init.Datatypes.O. Locate Stdlib.Init.Datatypes.O. Locate I.Dont.Exist. .. _printing-flags: Printing flags ------------------------------- .. flag:: Fast Name Printing When this :term:`flag` is turned on, Rocq uses an asymptotically faster algorithm for the generation of unambiguous names of bound variables while printing terms. While faster, it is also less clever and results in a typically less elegant display, e.g. it will generate more names rather than reusing certain names across subterms. This flag is not enabled by default, because as Ltac observes bound names, turning it on can break existing proof scripts. .. _loading-files: Loading files ----------------- Rocq offers the possibility of loading different parts of a whole development stored in separate files. Their contents will be loaded as if they were entered from the keyboard. This means that the loaded files are text files containing sequences of commands for Rocq's toplevel. This kind of file is called a *script* for Rocq. The standard (and default) extension of Rocq's script files is .v. .. cmd:: Load {? Verbose } {| @string | @ident } Loads a file. If :n:`@ident` is specified, the command loads a file named :n:`@ident.v`, searching successively in each of the directories specified in the :term:`load path`. (see Section :ref:`logical-paths-load-path`) If :n:`@string` is specified, it must specify a complete filename. `~` and .. abbreviations are allowed as well as shell variables. If no extension is specified, Rocq will use the default extension ``.v``. Files loaded this way can't leave proofs open, nor can :cmd:`Load` be used inside a proof. We discourage the use of :cmd:`Load`; use :cmd:`Require` instead. :cmd:`Require` loads `.vo` files that were previously compiled from `.v` files. :n:`Verbose` displays the Rocq output for each command and tactic in the loaded file, as if the commands and tactics were entered interactively. .. exn:: Can’t find file @ident on loadpath. :undocumented: .. exn:: Load is not supported inside proofs. :undocumented: .. exn:: Files processed by Load cannot leave open proofs. :undocumented: .. _compiled-files: Compiled files ------------------ This section describes the commands used to load compiled files (see Chapter :ref:`therocqcommands` for documentation on how to compile a file). A compiled file is a particular case of a module called a *library file*. .. cmd:: {? From @dirpath } Require {? {| Import | Export } {? @import_categories } } {+ @filtered_import } :name: From … Require; Require; Require Import; Require Export .. insertprodn dirpath dirpath .. prodn:: dirpath ::= {* @ident . } @ident Loads compiled files into the Rocq environment. For the first :n:`@qualid` in each :n:`@filtered_import`, the command looks in the :term:`load path` for a compiled file :n:`@ident.vo` whose :term:`logical name` has the form :n:`@dirpath.{* @ident__implicit. }@qualid` (if :n:`From @dirpath` is given) or :n:`{* @ident__implicit. }@qualid` (if the optional `From` clause is absent). :n:`{* @ident__implicit. }` represents the parts of the fully qualified name that are implicit. For example, `From Stdlib Require Nat` loads `Stdlib.Init.Nat` and `Init` is implicit. :n:`@ident` is the final component of the :n:`@qualid`. If a file is found, its logical name must be the same as the one used to compile the file. Then the file is loaded as well as all the files it depends on (recursively). All the files must have been compiled with the same version of Rocq. * :n:`Import` - additionally does an :cmd:`Import` on the loaded module, making components defined in the module available by their short names * :n:`Export` - additionally does an :cmd:`Export` on the loaded module, making components defined in the module available by their short names *and* marking them to be exported by the current module If the required file has already been loaded, it is not reloaded. If :n:`Import` or :n:`Export` are present, the command also does the equivalent of the :cmd:`Import` or :cmd:`Export` commands. A single file can be loaded with several variations of the `Require` command. For example, the ``-Q path Lib`` command line parameter associates the file ``path/Foo/File.vo`` with the logical name ``Lib.Foo.File``. It allows this file to be loaded through :n:`Require Lib.Foo.File`, :n:`From Lib Require Foo.File`, :n:`From Lib Require File` or :n:`From Lib.Foo Require File`. The `-R path Lib` command line parameter allows loading the file with the additional alternatives :n:`Require Foo.File` and :n:`Require File` In particular, `From` is useful to ensure that the file comes from a particular package or subpackage. Use of `-Q` is better for avoiding ambiguous path names. Exact matches are preferred when looking for a file with the logical name :n:`@dirpath.{* @ident__implicit. }@qualid` or :n:`{* @ident__implicit. }@qualid` (that is, matches where the implicit part is empty). For both exact and other matches, local loadpaths are considered first, then installed ones. Paths considered as installed are typically the `user-contrib` directory and paths provided via the ``ROCQPATH`` environment variable, see :cmd:`Print LoadPath`. In each attempt (exact local, exact installed, local and installed), several matching files are signaled by an error. The difference between the `-R` and the `-Q` option is that non-exact matches are allowed for `-Q` only if `From` is present. Matching is done when the script is compiled or processed rather than when its .vo file is loaded. .vo files use fully-qualified names. We recommend you use `-R` only to refer to files in the same package. Use `-Q` (if necessary) to refer to files in a different package. .. exn:: Cannot load @qualid: no physical path bound to @dirpath. :undocumented: .. exn:: Cannot find library foo in loadpath. The command did not find the file foo.vo. Either foo.v exists but is not compiled or foo.vo is in a directory which is not in your :term:`load path`. .. exn:: Required library @qualid matches several files in path (found file__1.vo, file__2.vo, ...). Either the file to load must be required with a more discriminating suffix (at worst, with its full logical name) or there is an error in the configuration (command line arguments or environment variables). .. exn:: Compiled library @ident.vo makes inconsistent assumptions over library @qualid. The command tried to load library file :n:`@ident`.vo that depends on some specific version of library :n:`@qualid` which is not the one already loaded in the current Rocq session. Probably :n:`@ident.v` was not properly recompiled with the last version of the file containing module :token:`qualid`. .. exn:: Bad magic number. The file :n:`@ident.vo` was found but either it is not a Rocq compiled module, or it was compiled with an incompatible version of Rocq. .. exn:: The file @ident.vo contains library @qualid__1 and not library @qualid__2. The library :n:`@qualid__2` is indirectly required by a :cmd:`Require`. The :term:`load path` maps :n:`@qualid__2` to :n:`@ident.vo`, which was compiled using a load path that bound it to :n:`@qualid__1`. Usually the appropriate solution is to recompile :n:`@ident.v` using the correct :term:`load path`. .. warn:: Require inside a module is deprecated and strongly discouraged. You can Require a module at toplevel and optionally Import it inside another one. Note that the :cmd:`Import` and :cmd:`Export` commands can be used inside modules. .. seealso:: Chapter :ref:`therocqcommands` .. cmd:: Print Libraries This command displays the list of library files loaded in the current Rocq session. .. cmd:: Declare ML Module {+ @string } Loads OCaml plugins and their dependencies dynamically. The :n:`@string` arguments must be valid `findlib `_ plugin names, for example ``rocq-runtime.plugins.ltac``. Effects (such as adding new commands) from the explicitly requested plugin are activated, but effects from implicitly loaded dependencies are not activated. The first component of the plugin name is a package name that has to be in scope of ``findlib``'s' search path. One can see the paths explored by ``findlib`` by running ``ocamlfind printconf`` and get the list of available libraries by running ``ocamlfind list | grep coq`` (Coq libraries are typically named ``coq-something``). This command is reserved for plugin developers, who should provide a ``.v`` file containing the command. Users of the plugin will usually require the resulting ``.vo`` file which will then transitively load the required plugin. If you are writing a plugin, you thus need to generate the right metadata so ``findlib`` can locate your plugin. This usually involves generating some kind of ``META`` file and placing it in a place where ``findlib`` can see it. Different build systems provide different helpers to do this: see :ref:`here for rocq makefile `, and :ref:`here for Dune `. This command supports the :attr:`local` attribute. If present, the listed files are not exported, even if they're outside a section. .. exn:: File not found on loadpath: @string. ``findlib`` is not able to find the plugin name. Possible reasons are: * The plugin does not exist or is misspelled. You can get the list of available libraries by running ``ocamlfind list | grep coq``. * The metadata for ``findlib`` has not been set properly (see above). .. exn:: Dynlink error: execution of module initializers in the shared library failed: Coq Error: @string is not a valid plugin name anymore. Plugins should be loaded using their public name according to findlib, for example package-name.foo and not foo_plugin. The plugin declaration in some ``.mlg`` file does not match the ``findlib`` plugin name. In the example of ``rocq-runtime.plugins.ltac``, one has to write ``DECLARE PLUGIN "rocq-runtime.plugins.ltac"``. .. cmd:: Print ML Modules Print the name of all findlib libraries loaded with :cmd:`Declare ML Module`. Load paths ---------- .. versionchanged:: 8.18 Commands to manage :term:`load paths ` within Rocq have been removed. Load paths can be managed using Rocq command line options or enviroment variables (see :ref:`logical-paths-load-path`). .. cmd:: Print LoadPath {? @dirpath } Displays the current Rocq :term:`load path`. If :n:`@dirpath` is specified, displays only the paths that extend that prefix. In the output, the logical path `<>` represents an empty logical path. Also prints whether a loadpath is considered installed (``i``) or not, see :cmd:`Require`. .. cmd:: Print ML Path Displays the current OCaml loadpath, as provided by the :ref:`command line option ` :n:`-I @string` (cf. :cmd:`Declare ML Module`). .. _extra_dependencies: Extra Dependencies ------------------ Dependencies on external files, i.e. non ``.v`` files, can be declared as follows: .. cmd:: From @dirpath Extra Dependency @string {? as @ident } :name: From … Dependency Adds an additional dependency of the current `.v` file on an external file. This information is included in the ``rocq dep`` tool generated list of dependencies. The file name :n:`@string` must exist relative to one of the top directories associated with :n:`@dirpath`. :n:`@string` can include directory separators (``/``) to select a file in a subdirectory. Path elements in :n:`@string` must be valid Rocq identifiers, e.g. they cannot contain characters such as ``-`` or ``,``. See :ref:`lexical-conventions`. When :n:`@ident` is provided, that name can be used by OCaml code, typically in a plugin, to access the full path of the external file via the API ``ComExtraDeps.query_extra_dep``. .. warn:: File ... found twice in ... The file is found in more than once in the top directories associated with the given :n:`@dirpath`. In this case the first occurrence is selected. .. _backtracking_subsection: Backtracking ------------ The backtracking commands described in this section can only be used interactively, they cannot be part of a Rocq file loaded via ``Load`` or compiled by ``rocq compile``. .. cmd:: Reset @ident This command removes all the objects in the environment since :n:`@ident` was introduced, including :n:`@ident`. :n:`@ident` may be the name of a defined or declared object as well as the name of a section. One cannot reset over the name of a module or of an object inside a module. .. cmd:: Reset Initial Goes back to the initial state, just after the start of the interactive session. .. cmd:: Back {? @natural } Undoes all the effects of the last :n:`@natural @sentence`\s. If :n:`@natural` is not specified, the command undoes one sentence. Sentences read from a `.v` file via a :cmd:`Load` are considered a single sentence. While :cmd:`Back` can undo tactics and commands executed within proof mode, once you exit proof mode, such as with :cmd:`Qed`, all the statements executed within are thereafter considered a single sentence. :cmd:`Back` immediately following :cmd:`Qed` gets you back to the state just after the statement of the proof. .. exn:: Invalid backtrack. The user wants to undo more commands than available in the history. .. cmd:: BackTo @natural This command brings back the system to the state labeled :n:`@natural`, forgetting the effect of all commands executed after this state. The state label is an integer which grows after each successful command. It is displayed in the prompt when in -emacs mode. Just as :cmd:`Back` (see above), the :cmd:`BackTo` command now handles proof states. For that, it may have to undo some extra commands and end on a state :n:`@naturalβ€² ≀ @natural` if necessary. .. _quitting-and-debugging: Quitting and debugging -------------------------- .. cmd:: Quit Causes Rocq to exit. Valid only in `rocq repl-with-drop`. .. cmd:: Drop This command temporarily enters the OCaml toplevel. It is a debug facility used by Rocq's implementers. Valid only in `rocq repl-with-drop`. The OCaml command: :: #use "include";; adds the right loadpaths and loads some toplevel printers for all abstract types of Rocq- section_path, identifiers, terms, judgments, …. You can also use the file base_include instead, that loads only the pretty-printers for section_paths and identifiers. You can return back to Rocq with the command: :: go();; .. cmd:: Time @sentence Executes :n:`@sentence` and displays the time needed to execute it. .. cmd:: Instructions @sentence Executes :n:`@sentence` and displays the number of CPU instructions needed to execute it. This command is currently only supported on Linux systems, but does not fail on unsupported systems, where it instead prints an error message in the place of the instruction count. .. cmd:: Profile {? @string } @sentence Executes :n:`@sentence` and displays profiling information. If :n:`@string` is given, a full trace is written to ":n:`@string`.json". If :n:`@string` is a relative filename, it refers to the directory specified by the :ref:`command line option ` `-output-directory`, if set and otherwise, the current directory. Use :cmd:`Pwd` to display the current directory. .. cmd:: Redirect @string @sentence Executes :n:`@sentence`, redirecting its output to the file ":n:`@string`.out". If :n:`@string` is a relative filename, it refers to the directory specified by the command line option `-output-directory`, if set (see :ref:`command-line-options`) and otherwise, the current directory. Use :cmd:`Pwd` to display the current directory. .. cmd:: Timeout @natural @sentence Executes :n:`@sentence`. If the operation has not terminated after :n:`@natural` seconds, then it is interrupted and an error message is displayed. .. opt:: Default Timeout @natural When this :term:`option` is set, each :n:`@sentence` is treated as if it was prefixed with :cmd:`Timeout` :n:`@natural`, except for :cmd:`Timeout` commands themselves. If unset, no timeout is applied. .. cmd:: Fail @sentence For debugging scripts, sometimes it is desirable to know whether a command or a tactic fails. If :n:`@sentence` fails, then :n:`Fail @sentence` succeeds (except for anomalies or for critical failures such as "stack overflow"), without changing the proof state. In interactive mode, the system prints a message confirming the failure. .. exn:: The command has not failed! If the given :n:`@command` succeeds, then :n:`Fail @sentence` fails with this error message. .. cmd:: Succeed @sentence If :n:`@sentence` succeeds, then :n:`Succeed @sentence` succeeds without changing the proof state. If :n:`@sentence` fails, then :n:`Succeed @sentence` fails showing the error message for :n:`@sentence`. In interactive mode, the system prints the message :n:`The command has succeeded and its effects have been reverted.` confirming the success. This command can be useful for writing tests. .. note:: :cmd:`Time`, :cmd:`Redirect`, :cmd:`Timeout`, :cmd:`Fail` and :cmd:`Succeed` are :production:`control_command`\s. For these commands, attributes and goal selectors, when specified, are part of the :n:`@sentence` argument, and thus come after the control command prefix and before the inner command or tactic. For example: `Time #[ local ] Definition foo := 0.` or `Fail Timeout 10 all: auto.` .. _controlling-display: Controlling display ----------------------- .. flag:: Silent This :term:`flag` controls the normal displaying. .. opt:: Warnings "{+, {? {| - | + } } @ident }" This :term:`option` configures the display of warnings. The :n:`@ident`\s are warning or category names. Adding `-` in front of a warning or category disables it, adding `+` makes it an error. Warning name and categories are printed between brackets when the warning is displayed (the warning name appears first). Warnings can belong to multiple categories. The special category `all` contains all warnings, and the special category `default` contains the warnings enabled by default. Rocq defines a set of core warning categories, which may be extended by plugins, so this list is not exhaustive. The core categories are: `automation`, `bytecode-compiler`, `coercions`, `deprecated`, `extraction`, `filesystem`, `fixpoints`, `fragile`, `funind`, `implicits`, `ltac`, `ltac2`, `native-compiler`, `numbers`, `parsing`, `pedantic`, `records`, `rewrite-rules`, `ssr`, `syntax`, `tactics`, `user-warn`, `vernacular`. .. This list is from lib/cWarnings.ml The flags are interpreted from left to right, so in case of an overlap, the flags on the right have higher priority, meaning that `A,-A` is equivalent to `-A`. See also the :attr:`warnings` attribute, which can be used to configure the display of warnings for a single command. .. opt:: Debug "{+, {? - } @ident }" This :term:`option` configures the display of debug messages. Each :n:`@ident` enables debug messages for that component, while :n:`-@ident` disables messages for the component. ``all`` activates or deactivates all other components. ``backtrace`` controls printing of error backtraces. :cmd:`Test` `Debug` displays the list of components and their enabled/disabled state. .. opt:: Printing Width @natural This :term:`option` sets which left-aligned part of the width of the screen is used for display. At the time of writing this documentation, the default value is 78. .. opt:: Printing Depth @natural This :term:`option` controls the nesting depth of the formatter used for pretty- printing. Beyond this depth, display of subterms is replaced by dots. At the time of writing this documentation, the default value is 50. .. flag:: Printing Compact Contexts This :term:`flag` controls the compact display mode for goals contexts. When on, the printer tries to reduce the vertical size of goals contexts by putting several variables (even if of different types) on the same line provided it does not exceed the printing width (see :opt:`Printing Width`). At the time of writing this documentation, it is off by default. .. flag:: Printing Unfocused This :term:`flag` controls whether unfocused goals are displayed. Such goals are created by focusing other goals with :ref:`bullets ` or :ref:`curly braces `. It is off by default. .. flag:: Printing Dependent Evars Line This :term:`flag` controls the printing of the β€œ(dependent evars: …)” information after each tactic. The information is used by the Prooftree tool in Proof General. (https://askra.de/software/prooftree) .. extracted from Gallina extensions chapter .. _printing_constructions_full: Printing constructions in full ------------------------------ .. flag:: Printing All Coercions, implicit arguments, the type of pattern matching, but also notations (see :ref:`syntax-extensions-and-notation-scopes`) can obfuscate the behavior of some tactics (typically the tactics applying to occurrences of subterms are sensitive to the implicit arguments). Turning this :term:`flag` on deactivates all high-level printing features such as coercions, implicit arguments, returned type of pattern matching, notations and various syntactic sugar for pattern matching or record projections. Otherwise said, :flag:`Printing All` includes the effects of the flags :flag:`Printing Implicit`, :flag:`Printing Coercions`, :flag:`Printing Synth`, :flag:`Printing Projections`, and :flag:`Printing Notations`. To reactivate the high-level printing features, use the command ``Unset Printing All``. .. note:: In some cases, setting :flag:`Printing All` may display terms that are so big they become very hard to read. One technique to work around this is use :cmd:`Undelimit Scope` and/or :cmd:`Close Scope` to turn off the printing of notations bound to particular scope(s). This can be useful when notations in a given scope are getting in the way of understanding a goal, but turning off all notations with :flag:`Printing All` would make the goal unreadable. .. see a contrived example here: https://github.com/rocq-prover/rocq/pull/11718#discussion_r415481854 .. flag:: Printing Fully Qualified When this :term:`flag` is turned on, all names (global references such as constants, inductives, constructors, and section variables, as well as modules, module types, universes, etc) are printed using their fully qualified paths. This is useful when there are multiple objects with the same short name in different modules, and you want to clearly distinguish them. For example, if you have both ``Foo.ax`` and ``Bar.ax`` defined, turning on this flag will ensure they are printed as ``Module.Foo.ax`` and ``Module.Bar.ax`` respectively (where ``Module`` is the top-level module name), rather than potentially ambiguous short names. This flag is off by default. .. _controlling-typing-flags: Controlling Typing Flags ---------------------------- .. flag:: Guard Checking This :term:`flag` can be used to enable/disable the guard checking of fixpoints. Warning: this can break the consistency of the system, use at your own risk. Decreasing argument can still be specified: the decrease is not checked anymore but it still affects the reduction of the term. Unchecked fixpoints are printed by :cmd:`Print Assumptions`. .. attr:: bypass_check(guard{? = {| yes | no } }) :name: bypass_check(guard) This :term:`boolean attribute` is similar to the :flag:`Guard Checking` flag, but on a per-declaration basis. Disable guard checking locally with ``bypass_check(guard)``. .. flag:: Positivity Checking This :term:`flag` can be used to enable/disable the positivity checking of inductive types and the productivity checking of coinductive types. Warning: this can break the consistency of the system, use at your own risk. Unchecked (co)inductive types are printed by :cmd:`Print Assumptions`. .. attr:: bypass_check(positivity{? = {| yes | no } }) :name: bypass_check(positivity) This :term:`boolean attribute` is similar to the :flag:`Positivity Checking` flag, but on a per-declaration basis. Disable positivity checking locally with ``bypass_check(positivity)``. .. flag:: Universe Checking This :term:`flag` can be used to enable/disable the checking of universes, providing a form of "type in type". Warning: this breaks the consistency of the system, use at your own risk. Constants relying on "type in type" are printed by :cmd:`Print Assumptions`. It has the same effect as `-type-in-type` command line argument (see :ref:`command-line-options`). .. attr:: bypass_check(universes{? = {| yes | no } }) :name: bypass_check(universes) This :term:`boolean attribute` is similar to the :flag:`Universe Checking` flag, but on a per-declaration basis. Disable universe checking locally with ``bypass_check(universes)``. .. cmd:: Print Typing Flags Print the status of the three typing flags: guard checking, positivity checking and universe checking. .. example:: .. rocqtop:: all reset Unset Guard Checking. Print Typing Flags. Fixpoint f (n : nat) : False := f n. Fixpoint ackermann (m n : nat) {struct m} : nat := match m with | 0 => S n | S m => match n with | 0 => ackermann m 1 | S n => ackermann m (ackermann (S m) n) end end. Print Assumptions ackermann. Note that the proper way to define the Ackermann function is to use an inner fixpoint: .. rocqtop:: all reset Fixpoint ack m := fix ackm n := match m with | 0 => S n | S m' => match n with | 0 => ack m' 1 | S n' => ack m' (ackm n') end end. Typing flags may not be changed while inside sections. .. _internal-registration-commands: Internal registration commands -------------------------------- Due to their internal nature, the commands that are presented in this section are not for general use. They are meant to appear only in standard libraries and in support libraries of plug-ins. .. _exposing-constants-to-ocaml-libraries: Exposing constants to OCaml libraries ``````````````````````````````````````` .. cmd:: Register @qualid__1 as @qualid__2 Makes the constant :n:`@qualid__1` accessible to OCaml libraries under the name :n:`@qualid__2`. The constant can then be dynamically located in OCaml code by calling :n:`Rocqlib.lib_ref "@qualid__2"`. The OCaml code doesn't need to know where the constant is defined (what file, module, library, etc.). As a special case, when the first segment of :n:`@qualid__2` is :g:`kernel`, the constant is exposed to the kernel. For instance, the `PrimInt63` module features the following declaration: .. rocqdoc:: Register bool as kernel.ind_bool. This makes the kernel aware of the `bool` type, which is used, for example, to define the return type of the :g:`#int63_eq` primitive. This command supports attributes :attr:`local`, :attr:`export` and :attr:`global`. The default is :attr:`global`, even inside sections. .. seealso:: :ref:`primitive-integers` .. cmd:: Print Registered List the currently registered constants. .. cmd:: Register Scheme @qualid__1 as @qualid__2 for @qualid__3 Make the constant :n:`@qualid__1` accessible to the "scheme" mechanism for scheme kind :n:`@qualid__2` and inductive :n:`@qualid__3`. This command supports attributes :attr:`local`, :attr:`export` and :attr:`global`. The default is :attr:`global`, even inside sections. .. cmd:: Print Registered Schemes List the currently registered schemes. This can be useful to find information about the (currently undocumented) scheme kinds. Inlining hints for the fast reduction machines `````````````````````````````````````````````` .. cmd:: Register Inline @qualid Gives a hint to the reduction machines (VM and native) that the body of the constant :n:`@qualid` should be inlined in the generated code. Registering primitive operations ```````````````````````````````` .. cmd:: Primitive @ident_decl {? : @term } := #@ident Makes the primitive type or primitive operator :n:`#@ident` defined in OCaml accessible in Rocq commands and tactics. For internal use by implementors of Rocq's standard library or standard library replacements. No space is allowed after the `#`. Invalid values give a syntax error. For example, the standard library files `PrimInt63.v` and `PrimFloat.v` use :cmd:`Primitive` to support, respectively, the features described in :ref:`primitive-integers` and :ref:`primitive-floats`. The types associated with an operator must be declared to the kernel before declaring operations that use the type. Do this with :cmd:`Primitive` for primitive types and :cmd:`Register` with the :g:`kernel` prefix for other types. For example, in `PrimInt63.v`, `#int63_type` must be declared before the associated operations. .. exn:: The type @ident must be registered before this construction can be typechecked. :undocumented: The type must be defined with :cmd:`Primitive` command before this :cmd:`Primitive` command (declaring an operation using the type) will succeed. rocq-9.2.0/doc/sphinx/proofs/000077500000000000000000000000001516144147600160655ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/proofs/automatic-tactics/000077500000000000000000000000001516144147600215035ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/proofs/automatic-tactics/auto.rst000066400000000000000000001167141516144147600232170ustar00rootroot00000000000000.. _automation: ========================= Programmable proof search ========================= Tactics ------- .. tacn:: auto {? @nat_or_var } {? @auto_using } {? @hintbases } .. insertprodn auto_using hintbases .. prodn:: auto_using ::= using {+, @one_term } hintbases ::= with * | with {+ @ident } Implements a Prolog-like resolution procedure to solve the current goal. It first tries to solve the goal using the :tacn:`assumption` tactic, then it reduces the goal to an atomic one using :tacn:`intros` and introduces the newly generated hypotheses as hints. Then it looks at the list of tactics associated with the head symbol of the goal and tries to apply one of them. This process is recursively applied to the generated subgoals. .. comment "introduces the newly generated hyps as hints": done in Hints.make_local_hint_db, which also adds constructor hints. eauto also calls this, tc eauto uses different code Within each hintbase, lower cost tactics are tried before higher-cost tactics. When multiple hintbases are specified, all hints in the first database are tried before any in the second database (and so forth) regardless of their cost (unlike :tacn:`eauto` and :tacn:`typeclasses eauto`). :n:`@nat_or_var` Specifies the maximum search depth. The default is 5. :n:`using {+, @one_term }` Uses lemmas :n:`{+, @one_term }` in addition to hints. If :n:`@one_term` is an inductive type, the collection of its constructors are added as hints. Note that hints passed through the `using` clause are used in the same way as if they were passed through a hint database. Consequently, they use a weaker version of :tacn:`apply` and :n:`auto using @one_term` may fail where :n:`apply @one_term` succeeds. .. todo Given that this can be seen as counter-intuitive, it could be useful to have an option to use full-blown :tacn:`apply` for lemmas passed through the `using` clause. Contributions welcome! :n:`with *` Use all existing hint databases. Using this variant is highly discouraged in finished scripts since it is both slower and less robust than explicitly selecting the required databases. :n:`with {+ @ident }` Use the hint databases :n:`{+ @ident}` in addition to the database ``core``. Use the fake database `nocore` to omit `core`. If no `with` clause is given, :tacn:`auto` only uses the hypotheses of the current goal and the hints of the database named ``core``. :tacn:`auto` generally either completely solves the goal or leaves it unchanged. Use :tacn:`solve` `[ auto ]` if you want a failure when they don't solve the goal. :tacn:`auto` will fail if :tacn:`fail` or :tacn:`gfail` are invoked directly or indirectly, in which case setting the :flag:`Ltac Debug` may help you debug the failure. .. warning:: :tacn:`auto` uses a weaker version of :tacn:`apply` that is closer to :tacn:`simple apply` so it is expected that sometimes :tacn:`auto` will fail even if applying manually one of the hints would succeed. .. seealso:: :ref:`hintdatabases` for the list of pre-defined databases and the way to create or extend a database. .. tacn:: info_auto {? @nat_or_var } {? @auto_using } {? @hintbases } Behaves like :tacn:`auto` but shows the tactics it uses to solve the goal. This variant is very useful for getting a better understanding of automation, or to know what lemmas/assumptions were used. .. _info_auto_not_exact: The tactics shown in the info or debug output currently don't correspond exactly to the variants that proof search tactics such as :tacn:`auto` use, but they are close. Occasionally the tactics shown (after removing tactics that were backtracked) may not always work as a replacement for the proof search tactic. For example: .. example:: `info_auto` output that isn't a valid proof The output isn't accepted as a proof because the conversion constraints are solved by default after every statement but are not solved internally by :tacn:`auto` as it searches for a proof. .. rocqtop:: in Create HintDb db. Hint Resolve conj : db. Hint Resolve eq_refl : db. Goal forall n, n=1 -> exists x y : nat, x = y /\ x = 0. intros. do 2 eexists; subst. (* Fix 2: replace with "do 2 (eexists; subst)." *) .. rocqtop:: all Succeed info_auto with nocore db. simple apply conj. (* from info_auto output *) Fail simple apply @eq_refl. (* Fix 1: change to "2: simple apply @eq_refl" *) (* simple apply @eq_refl. *) .. rocqtop:: none abort One fix is to apply the tactics to the goals in a non-default order. Another would be to add parentheses to the `do 2`, which gives a different result. The fixes are shown inline in the example. .. tacn:: debug auto {? @nat_or_var } {? @auto_using } {? @hintbases } Behaves like :tacn:`auto` but shows the tactics it tries to solve the goal, including failing paths. .. tacn:: trivial {? @auto_using } {? @hintbases } debug trivial {? @auto_using } {? @hintbases } info_trivial {? @auto_using } {? @hintbases } Like :tacn:`auto`, but is not recursive and only tries hints with zero cost. Typically used to solve goals for which a lemma is already available in the specified :n:`hintbases`. .. flag:: Info Auto Debug Auto Info Trivial Debug Trivial These :term:`flags ` enable printing of informative or debug information for the :tacn:`auto` and :tacn:`trivial` tactics. .. tacn:: eauto {? @nat_or_var } {? @auto_using } {? @hintbases } Generalizes :tacn:`auto`. While :tacn:`auto` does not try resolution hints which would leave existential variables in the goal, :tacn:`eauto` will try them. Also, :tacn:`eauto` internally uses :tacn:`eassumption` instead of :tacn:`assumption` and, when needed, a tactic similar to :tacn:`simple eapply` instead of a tactic similar to :tacn:`simple apply`. As a consequence, :tacn:`eauto` can solve goals such as: .. example:: .. rocqtop:: all Hint Resolve ex_intro : core. Goal forall P:nat -> Prop, P 0 -> exists n, P n. eauto. `ex_intro` is declared as a hint so the proof succeeds. .. seealso:: :ref:`hintdatabases` .. tacn:: info_eauto {? @nat_or_var } {? @auto_using } {? @hintbases } The various options for :tacn:`info_eauto` are the same as for :tacn:`info_auto`. Note that the tactics shown (after removing tactics that were backtracked) may not always work as a replacement for the proof search tactic. See :ref:`here `. :tacn:`eauto` uses the following flags: .. flag:: Info Eauto Debug Eauto :undocumented: .. tacn:: debug eauto {? @nat_or_var } {? @auto_using } {? @hintbases } Behaves like :tacn:`eauto` but shows the tactics it tries to solve the goal, including failing paths. .. tacn:: autounfold {? @hintbases } {? @simple_occurrences } Unfolds constants that were declared through a :cmd:`Hint Unfold` in the given databases. :n:`@simple_occurrences` Performs the unfolding in the specified occurrences. .. tacn:: autounfold_one {? @hintbases } {? in @ident } :undocumented: .. tacn:: autorewrite {? * } with {+ @ident } {? @occurrences } {? using @ltac_expr } `*` If present, rewrite all occurrences whose side conditions are solved. :n:`with {+ @ident }` Specifies the rewriting rule bases to use. :n:`@occurrences` Performs rewriting in the specified occurrences. Note: the `at` clause is currently not supported. .. exn:: The "at" syntax isn't available yet for the autorewrite tactic. Appears when there is an `at` clause on the conclusion. :n:`using @ltac_expr` :token:`ltac_expr` is applied to the main subgoal after each rewriting step. Applies rewritings according to the rewriting rule bases :n:`{+ @ident }`. For each rule base, applies each rewriting to the main subgoal until it fails. Once all the rules have been processed, if the main subgoal has changed then the rules of this base are processed again. If the main subgoal has not changed then the next base is processed. For the bases, the behavior is very similar to the processing of the rewriting rules. The rewriting rule bases are built with the :cmd:`Hint Rewrite` command. .. warning:: This tactic may loop if you build non-terminating rewriting systems. .. seealso:: :cmd:`Hint Rewrite` for feeding the database of lemmas used by :tacn:`autorewrite` and :tacn:`autorewrite` for examples showing the use of this tactic. Also see :ref:`strategies4rewriting`. Here are two examples of ``autorewrite`` use. The first one ( *Ackermann function*) shows actually a quite basic use where there is no conditional rewriting. The second one ( *Mac Carthy function*) involves conditional rewritings and shows how to deal with them using the optional tactic of the ``Hint Rewrite`` command. .. example:: Ackermann function .. rocqtop:: in reset Parameter Ack : nat -> nat -> nat. .. rocqtop:: in Axiom Ack0 : forall m:nat, Ack 0 m = S m. Axiom Ack1 : forall n:nat, Ack (S n) 0 = Ack n 1. Axiom Ack2 : forall n m:nat, Ack (S n) (S m) = Ack n (Ack (S n) m). .. rocqtop:: in Create Rewrite HintDb base0. Global Hint Rewrite Ack0 Ack1 Ack2 : base0. .. rocqtop:: all Lemma ResAck0 : Ack 3 2 = 29. .. rocqtop:: all autorewrite with base0 using try reflexivity. .. example:: MacCarthy function This example requires the Stdlib library. .. rocqtop:: in reset extra-stdlib From Stdlib Require Import Arith Lia. .. rocqtop:: in extra-stdlib Parameter g : nat -> nat -> nat. .. rocqtop:: in extra-stdlib Axiom g0 : forall m:nat, g 0 m = m. Axiom g1 : forall n m:nat, (n > 0) -> (m > 100) -> g n m = g (pred n) (m - 10). Axiom g2 : forall n m:nat, (n > 0) -> (m <= 100) -> g n m = g (S n) (m + 11). .. rocqtop:: in extra-stdlib Create Rewrite HintDb base1. Global Hint Rewrite g0 g1 g2 using lia : base1. .. rocqtop:: in extra-stdlib Lemma Resg0 : g 1 110 = 100. .. rocqtop:: out extra-stdlib Show. .. rocqtop:: all extra-stdlib autorewrite with base1 using reflexivity || simpl. .. rocqtop:: none extra-stdlib Qed. .. rocqtop:: all extra-stdlib Lemma Resg1 : g 1 95 = 91. .. rocqtop:: all extra-stdlib autorewrite with base1 using reflexivity || simpl. .. rocqtop:: none extra-stdlib Qed. .. tacn:: easy This tactic tries to solve the current goal by a number of standard closing steps. In particular, it tries to close the current goal using the closing tactics :tacn:`trivial`, :tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`contradiction` and :tacn:`inversion` of hypothesis. If this fails, it tries introducing variables and splitting and-hypotheses, using the closing tactics afterwards, and splitting the goal using :tacn:`split` and recursing. This tactic solves goals that belong to many common classes; in particular, many cases of unsatisfiable hypotheses, and simple equality goals are usually solved by this tactic. .. tacn:: now @ltac_expr Run :n:`@tactic` followed by :tacn:`easy`. This is a notation for :n:`@tactic; easy`. .. _hintdatabases: Hint databases -------------- Hints used by :tacn:`auto`, :tacn:`eauto` and other tactics are stored in hint databases. Each database maps head symbols to a list of hints. Use the :cmd:`Print Hint` command to view a database. Each hint has a cost and an optional pattern. Hints with lower cost are tried first. (Cost is not used to limit the scope of searches.) :tacn:`auto` tries a hint when the conclusion of the current goal matches its pattern or when the hint has no pattern. Creating hint databases ``````````````````````` Use :cmd:`Create HintDb` command to create hint databases. The new databases have the default setting `Transparent` for `Constants`, `Projections` and `Variables`. We recommend using :cmd:`Hint Constants`, :cmd:`Hint Projections` and :cmd:`Hint Variables` immediately after :cmd:`Create HintDb` to make these settings explicit. Alternatively, adding a hint to an unknown database creates the latter implicitly, but this behavior is deprecated as of Rocq 9.2. Implicitly created databases have the `Opaque` setting for `Constants`, `Projections` and `Variables`. The proof search tactics use unification to choose which tactics to try, for example whether the goal unifies with a theorem given by :cmd:`Hint Resolve`. Use :cmd:`Hint Opaque` and :cmd:`Hint Transparent` to control the opacity of individual items during this initial unification. These settings are distinct from the non-hint :cmd:`Opaque` and :cmd:`Transparent` settings. Hint opacity settings influence which hints the search tactics try, but in some cases they also affect how selected tactics are executed. (In particular, :tacn:`typeclasses eauto` uses the equivalent of :tacn:`autoapply` when applying :cmd:`Hint Resolve` hints, which explicitly use the hint opacity settings. :tacn:`auto` and :tacn:`eauto` don't do this.) .. cmd:: Create HintDb @ident {? discriminated } If there is no hint database named :n:`@ident`, creates a new hint database with that name. Otherwise, does nothing. All constants, variables and projections are set to default to unfoldable (use :cmd:`Hint Constants`, :cmd:`Hint Projections` and :cmd:`Hint Variables` to change this). For better performance, we recommend setting each of these to :n:`Opaque` and then using :cmd:`Hint Transparent` for specific items when necessary. By default, hint databases are undiscriminated. We recommend using `discriminated` because it generally performs better. .. _hint_performance_considerations: Deciding which hints to try ``````````````````````````` The proof search tactics decide which hints to try by first selecting hints whose pattern has the same :term:`head constant` as the goal. Then the selected hints are tried as follows: - For hints other than :cmd:`Hint Extern`: If the database is discriminated, only matching hints are tried. Hints match if all compared items that are opaque in both the goal and the pattern are identical. Marking definitions as Hint Opaque reduces the number of matches, but it may cause some proof searches that previously worked to fail. Otherwise (if not discriminated), all hints will be tried. (Therefore, use `discriminated` databases whenever possible.) - For `Extern` hints: If the hint has a pattern, hints matching the goal will be tried. In this case, matching uses a form of `syntactic unification `_), treating everything as hint opaque. Otherwise (if there is no pattern), all hints will be tried. (Therefore, provide a pattern in `Extern` hints whenever possible.) .. todo Mention that apply will use conversion (after bug is fixed) .. comment: discriminated matches patterns: see test-suite/output/disc_uses_patterns.v discriminated with transparent: see test-suite/output/disc_with_transparent.v non-discriminated ignores patterns: see test-suite/output/nondisc_ignores_pattern.v Extern uses syntactic unification: see test-suite/success/hint_extern_syntactic_unify.v Extern with no pattern: see test-suite/output/extern_no_pattern.v .. comment not sure: Note: currently, proof search tactics won't unfold the head constant even if it is transparent. .. warn:: @ident already exists and is {? not } discriminated :name: mismatched-hint-db `Create HintDb` will not change whether a pre-existing database is discriminated. .. cmd:: Create Rewrite HintDb @ident Like above, but creates a database for :cmd:`Hint Rewrite` declarations instead. Hint databases defined in the Rocq standard library ``````````````````````````````````````````````````` Several hint databases are defined in the Rocq standard library. The database contains the hints declared for it in the currently loaded modules (subject to :ref:`locality attributes`) as well as any added in the current module. Requiring additional modules (:cmd:`Require`) may add more hints. At Rocq startup, only the core database is nonempty and ready to be used immediately. :core: This special database is automatically used by ``auto``, except when pseudo-database ``nocore`` is given to ``auto``. The core database contains only basic lemmas about negation, conjunction, and so on. Most of the hints in this database come from the Init and Logic directories. :arith: all lemmas about Peano’s arithmetic proved in the directories Init and Arith. :zarith: lemmas about binary signed integers from the directories theories/ZArith. The database also contains high-cost hints that call :tacn:`lia` on equations and inequalities in ``nat`` or ``Z``. :bool: lemmas about booleans, mostly from directory theories/Bool. :datatypes: lemmas about lists, streams and so on that are mainly proved in the Lists subdirectory. :sets: lemmas about sets and relations from the directories Sets and Relations. :typeclass_instances: special database containing all typeclass instances declared in the environment, including those used for ``setoid_rewrite``, from the Classes directory. :fset: internal database for the implementation of the ``FSets`` library. :ordered_type: lemmas about ordered types (as defined in the legacy ``OrderedType`` module), mainly used in the ``FSets`` and ``FMaps`` libraries. You are advised not to put your own hints in the core database, but instead to use one or more databases specific to your development. .. _creating_hints: Creating Hints -------------- The various `Hint` commands share these elements: :n:`{? : {+ @ident } }` specifies the hint database(s) to add to. *(Deprecated since version 8.10:* If no :token:`ident`\s are given, the hint is added to the `core` database.) Hints in hint databases are ordered, which is the order in which they're tried, as shown by the :cmd:`Print HintDb` command. Hints with lower costs are tried first. Hints with the same cost are tried in reverse of their order of definition, i.e., last to first. Rewrites with theorems such as :n:`forall n m, n+m=m+n` or :n:`forall n m p, (n+m)+p=n+(m+p)` (eg :n:`Hint Extern ... => rewrite ...`) should be used only in :cmd:`Hint Immediate` to prevent them from wastefully being applied . Outside of sections, these commands support the :attr:`local`, :attr:`export` and :attr:`global` attributes. :attr:`export` is the default. Inside sections, some commands only support the :attr:`local` attribute. These are :cmd:`Hint Immediate`, :cmd:`Hint Resolve`, :cmd:`Hint Constructors`, :cmd:`Hint Unfold`, :cmd:`Hint Extern` and :cmd:`Hint Rewrite`. :attr:`local` is the default for all hint commands inside sections. + :attr:`local` hints are never visible from other modules, even if they :cmd:`Import` or :cmd:`Require` the current module. + :attr:`export` hints are visible from other modules when they :cmd:`Import` the current module, but not when they only :cmd:`Require` it. + :attr:`global` hints are visible from other modules when they :cmd:`Require` the current module (submodules of the current module are considered :cmd:`Require`\d after their :cmd:`End`). .. versionchanged:: 8.18 The default value for hint locality outside sections is now :attr:`export`. It used to be :attr:`global`. .. deprecated:: 9.2 Implicitly creating a unknown database is now deprecated and will become an error. The `Hint` commands are: .. cmd:: Hint Resolve {+ {| @qualid | @one_term } } {? @hint_info } {? : {+ @ident } } Hint Resolve {| -> | <- } {+ @qualid } {? @natural } {? : {+ @ident } } :name: Hint Resolve; _ .. insertprodn hint_info one_pattern .. prodn:: hint_info ::= %| {? @natural } {? @one_pattern } one_pattern ::= @one_term The first form adds each :n:`@qualid` as a hint with the head symbol of the type of :n:`@qualid` to the specified hint databases (:n:`@ident`\s). If specified, :n:`@natural` is the cost of the hint; otherwise the cost of the hint is the number of subgoals generated by :tacn:`simple apply`. The associated pattern is inferred from the conclusion of the type of :n:`@qualid` or, if specified, the given :n:`@one_pattern`. If the inferred type of :n:`@qualid` does not start with a product, the command adds :tacn:`exact` :n:`@qualid` to the hint list. If the type reduces to a type starting with a product, the command also adds :tacn:`simple apply` :n:`@qualid` to the hints list. Note that tactics printed in debug output are similar to but not exactly the same as the ones executed by proof search. Unlike :tacn:`auto` and :tacn:`eauto`, :tacn:`typeclasses eauto` uses a tactic equivalent to :tacn:`autoapply`, which behaves somewhat differently from :tacn:`simple apply`. Nonetheless, that tactic's debug output and the hint database misleadingly show :tacn:`simple apply`. If the inferred type of :n:`@qualid` contains a dependent quantification on a variable which occurs only in the premises of the type and not in its conclusion, no instance could be inferred for the variable by unification with the goal. In this case, the hint is only used by :tacn:`eauto` / :tacn:`typeclasses eauto`, but not by :tacn:`auto`. A typical hint that would only be used by :tacn:`eauto` is a transitivity lemma. :n:`{| -> | <- }` The second form adds the left-to-right (`->`) or right-ot-left implication (`<-`) of a logical equivalence (`<->`) as a hint. If needed, it defines a projection for the specified direction, which the hint applies with a restricted version of :tacn:`apply`. (For example, `Hint Resolve -> and_comm` defines `and_comm_proj_l2r`.) :n:`@one_term` Permits declaring a hint without declaring a new constant first. This is deprecated. .. warn:: Declaring arbitrary terms as hints is fragile and deprecated; it is recommended to declare a toplevel constant instead :undocumented: :n:`@one_pattern` Overrides the default pattern, which may occasionally be useful. For example, if a hint has the default pattern `_ = _`, you could limit the hint being tried only for `bool`\s with the pattern `(@eq bool _ _)`. .. exn:: @qualid cannot be used as a hint The head symbol of the type of :n:`@qualid` is a bound variable such that this tactic cannot be associated with a constant. .. cmd:: Hint Immediate {+ {| @qualid | @one_term } } {? : {+ @ident } } For each specified :n:`@qualid`, adds the tactic :tacn:`simple apply` :n:`@qualid;` :tacn:`solve` :n:`[` :tacn:`trivial` :n:`]` to the hint list associated with the head symbol of the type of :n:`@qualid`. The tactic fails if any of the subgoals generated by :tacn:`simple apply` :n:`@qualid` are not solved immediately by :tacn:`trivial` (which only tries tactics with cost 0). This hint is useful to allow controlled use of theorems such as :n:`n+m=m+n` or :n:`(n+m)+p=n+(m+p)` that otherwise could be applied repeatedly without limit. The cost of this hint (which never generates subgoals) is always 1, so it won't be used by :tacn:`trivial` itself. .. comment I don't see why :n:`n+1=m+1 -> n=m` would be problematic .. cmd:: Hint Constructors {+ @qualid } {? : {+ @ident } } For each :n:`@qualid` that is an inductive type, adds all its constructors as hints of type ``Resolve``. Then, when the conclusion of current goal has the form :n:`(@qualid ...)`, :tacn:`auto` will try to apply each constructor using :tacn:`exact`. .. exn:: @qualid is not an inductive type :undocumented: .. cmd:: Hint Unfold {+ @qualid } {? : {+ @ident } } For each :n:`@qualid`, adds the tactic :tacn:`unfold` :n:`@qualid` to the hint list that will only be used when the :term:`head constant` of the goal is :token:`qualid`. Its cost is 4. .. cmd:: Hint {| Transparent | Opaque } {+ @qualid } {? : {+ @ident } } :name: Hint Transparent; Hint Opaque Adds transparency hints to the database, making each :n:`@qualid` transparent or opaque during resolution. The proof search tactics use unification to determine whether to try most hints, for example checking if the goal unifies with the theorem used in a :cmd:`Hint Resolve` hint. Currently the head constant is always treated as opaque (see :ref:`example `). See :ref:`here ` for a description of how opaque and transparent affect which hints are tried. Note that transparency hints are independent of the non-hint :cmd:`Opaque` and :cmd:`Transparent` settings. .. example:: Transparency with Multiple Hint Databases To use different transparency settings for particular hints, put them in separate hint databases with distinct transparency settings and use :tacn:`typeclasses eauto`. (This doesn't work for :tacn:`auto` or :tacn:`eauto`.): .. rocqtop:: in reset Definition one := 1. Theorem thm : one = 1. reflexivity. Qed. Create HintDb db1. Hint Opaque one : db1. Hint Resolve thm | 1 : db1. Create HintDb db2. Goal 1 = 1. (* "one" is not unfolded because it's opaque in db1, where bar is *) Fail typeclasses eauto with db1 db2 nocore. (* fails with tc eauto *) Succeed eauto with db1 db2 nocore. (* ignores the distinction *) Succeed auto with db1 db2 nocore. (* ignores the distinction *) Hint Resolve thm | 2 : db2. (* "one" is unfolded because it's transparent (by default) in db2 *) Succeed typeclasses eauto with db1 db2 nocore. .. rocqtop:: none Abort. .. example:: Independence of Hint Opaque and Opaque .. rocqtop:: reset in Definition one := 1. Opaque one. (* not relevant to hint selection *) Theorem bar: 1=1. reflexivity. Qed. Create HintDb db. (* constants, etc. transparent by default *) Hint Opaque one : db. (* except for "one" *) Hint Resolve bar : db. (* hint is not tried if one is Hint Opaque *) Set Typeclasses Debug Verbosity 1. Goal one = 1. Fail typeclasses eauto with db nocore. (* fail: no match for (one = 1) *) Hint Transparent one : db. Succeed typeclasses eauto with db nocore. (* success: now bar is tried *) Fail unfold one. (* fail: one is still Opaque *) .. rocqtop:: none Abort. .. _head_const_opaque: .. example:: Head Constants are always opaque Adding :n:`Hint Unfold Tru : db` will make `auto` succeed. (If the goal was :n:`True = Tru`, the head constant is :n:`eq` and :n:`Tru` will be unfolded.) .. rocqtop:: reset in Definition Tru := True. Create HintDb db. Hint Constants Transparent : db. Hint Resolve I : db. Print HintDb db. (* For XXX -> indicates XXX is the head constant *) Goal Tru. .. rocqtop:: all Fail progress auto with db. Hint Unfold Tru : db. (* workaround *) progress info_auto with db. (* works now! *) .. rocqtop:: none Abort. .. exn:: Cannot coerce @qualid to an evaluable reference. :undocumented: .. cmd:: Hint {| Constants | Projections | Variables } {| Transparent | Opaque } {? : {+ @ident } } :name: Hint Constants; Hint Projections; Hint Variables Sets the default transparency for constants (from :cmd:`Definition`\s and :cmd:`Example`\s), projections (from :cmd:`Record`\s and :cmd:`Structure`\s) or variables (from :cmd:`Hypotheses` and :cmd:`Variables`) for the specified hint databases. Existing transparency settings for individual items (e.g., set with :cmd:`Hint Opaque`) are dropped. Making items opaque can make proof search commands run faster (fewer unfoldings) but it can also prevent matching some hints. We recommend setting each of these to :n:`Opaque` and then using :cmd:`Hint Transparent` for specific items as needed. We advise using this command just after a :cmd:`Create HintDb` command. .. cmd:: Hint Extern @natural {? @one_pattern } => @generic_tactic {? : {+ @ident } } Extends :tacn:`auto` with tactics other than :tacn:`apply` and :tacn:`unfold`. :n:`@natural` is the cost, :n:`@one_pattern` is the pattern to match and :n:`@ltac_expr` is the action to apply. We recommend providing a pattern whenever possible. Hints with patterns are tried only if the pattern matches without unfolding transparent constants (i.e., a syntactic match). Hints without patterns are always tried. **Usage tip**: tactics that can succeed even if they don't change the context, such as most of the :ref:`conversion tactics `, should be prefaced with :tacn:`progress` to avoid needless repetition of the tactic. **Usage tip**: Use a :cmd:`Hint Extern` with no pattern to do pattern matching on hypotheses using ``match goal with`` inside the tactic. .. example:: .. rocqtop:: in Hint Extern 4 (~(_ = _)) => discriminate : core. Now, when the head of the goal is an inequality, ``auto`` will try `discriminate` if it does not manage to solve the goal with hints with a cost less than 4. One can even use some sub-patterns of the pattern in the tactic script. A sub-pattern is a question mark followed by an identifier, like ``?X1`` or ``?X2``. Here is an example: .. example:: .. rocqtop:: reset all Require Import ListDef. Create HintDb eqdec. Hint Extern 5 ({?X1 = ?X2} + {?X1 <> ?X2}) => generalize X1, X2; decide equality : eqdec. Goal forall a b:list (nat * nat), {a = b} + {a <> b}. info_auto with eqdec. .. cmd:: Hint Cut [ @hints_regexp ] {? : {+ @ident } } .. DISABLED insertprodn hints_regexp hints_regexp .. prodn:: hints_regexp ::= {+ @qualid } (hintΒ orΒ instanceΒ identifier) | _ (any hint) | @hints_regexp | @hints_regexp (disjunction) | @hints_regexp @hints_regexp (sequence) | @hints_regexp * (Kleene star) | emp (empty) | eps (epsilon) | ( @hints_regexp ) Adds another clause to the cut regular expression in the specfied hint databases. :n:`Hint Cut @hints_regexp` sets the cut expression to :n:`c | @hints_regexp`. The initial cut expression is `emp`. Typeclass proof search and the :tacn:`typeclasses eauto` tactic (but not :tacn:`auto` or :tacn:`eauto`) use the cut expression to conditionally prevent using some hints based on the path of hints that have been successfully applied. The path is an ordered list of hint identifiers. When the path plus the identifier of a candidate hint matches the cut expression, the hint is *not* applied. (It is nothing like a cut in Prolog.) The hint identifier is the :n:`@qualid` that appears in the various `Hint` commands (e.g. as in :cmd:`Hint Resolve` `plus_O_n.`), with the following exceptions: - :cmd:`Hint Extern`\s do not have associated identifiers - For :cmd:`Hint Constructors`, which creates multiple hints, the identifiers are the names of the constructors. - For :cmd:`Hint Resolve` :n:`{| -> | <- } theorem`, the name is `theorem_proj_l2r` or `theorem_proj_r2l` depending on the direction of the arrow. The output of :cmd:`Print HintDb` shows the cut expression. .. warning:: The regexp matches the entire path. Most hints will start with a leading `( _* )` to match the tail of the path. (Note that `(_*)` misparses since `*)` would end a comment.) .. warning:: There is no operator precedence during parsing, one can check with :cmd:`Print HintDb` to verify the current cut expression. .. cmd:: Hint Mode @qualid {+ {| + | ! | - } } {? : {+ @ident } } Sets an optional mode of resolution for the identifier :n:`@qualid`. When proof search has a goal that ends in an application of :n:`@qualid` to arguments :n:`@arg ... @arg`, the mode tells if the hints associated with :n:`@qualid` can be applied or not, depending on a criterion on the arguments. A mode specification is a list of ``+``, ``!`` or ``-`` items that specify if an argument of the identifier is to be treated as an input (``+``), if its head only is an input (``!``) or an output (``-``) of the identifier. Mode ``-`` matches any term, mode ``+`` matches a term if and only if it does not contain existential variables, while mode ``!`` matches a term if and only if the *head* of the term is not an existential variable. The head of a term is understood here as the applicative head, recursively, ignoring casts. For a mode declaration to match a list of arguments, each argument should match its corresponding mode. Only :tacn:`typeclasses eauto` uses these hints. :cmd:`Hint Mode` is especially useful for typeclasses, when one does not want to support default instances and wants to avoid ambiguity in general. Setting a parameter of a class as an input forces proof search to be driven by that index of the class, with ``!`` allowing existentials to appear in the index but not at its head. .. note:: + Multiple modes can be declared for a single identifier. In that case only one mode needs to match the arguments for the hints to be applied. + If you want to add hints such as :cmd:`Hint Transparent`, :cmd:`Hint Cut`, or :cmd:`Hint Mode`, for typeclass resolution, do not forget to put them in the ``typeclass_instances`` hint database. .. warn:: This hint is not local but depends on a section variable. It will disappear when the section is closed. A hint with a non-local attribute was added inside a section, but it refers to a local variable that will go out of scope when closing the section. As a result the hint will not survive either. .. example:: Logic programming with addition on natural numbers This example illustrates the use of modes to control how resolutions can be triggered during proof search. .. rocqtop:: all reset Parameter plus : nat -> nat -> nat -> Prop. Create HintDb plus. Hint Mode plus ! - - : plus. Hint Mode plus - ! - : plus. .. rocqtop:: in Axiom plus0l : forall m : nat, plus 0 m m. Axiom plus0r : forall n : nat, plus n 0 n. Axiom plusSl : forall n m r : nat, plus n m r -> plus (S n) m (S r). Axiom plusSr : forall n m r : nat, plus n m r -> plus m (S m) (S r). Hint Resolve plus0l plus0r plusSl plusSr : plus. The previous commands define the addition predicate and set its mode so it can resolve goals if and only if one of the first two arguments is headed by a constructor or constant. The last argument of the predicate will be the inferred result. .. rocqtop:: all Goal exists x y, plus x y 12. Proof. eexists ?[x], ?[y]. Fail typeclasses eauto with plus. instantiate (y := 1). typeclasses eauto with plus. Defined. In the proof script, the first call to :tacn:`typeclasses eauto` fails as the two arguments are headed by an existential variable, while when we instantiate the second argument with ``1``, typeclass resolution succeeds as the second declared mode is matched, and instantiates ``x`` with ``11``. .. cmd:: Hint Rewrite {? {| -> | <- } } {+ @one_term } {? using @generic_tactic } {? : {+ @ident } } :n:`{? using @generic_tactic }` If specified, :n:`@generic_tactic` is applied to the generated subgoals, except for the main subgoal. :n:`{| -> | <- }` Arrows specify the orientation; left to right (:n:`->`) or right to left (:n:`<-`). If no arrow is given, the default orientation is left to right (:n:`->`). Adds the terms :n:`{+ @one_term }` (their types must be equalities) to the rewriting bases :n:`{* @ident }`. Note that the rewriting bases are distinct from the :tacn:`auto` hint bases and that :tacn:`auto` does not take them into account. .. cmd:: Print Rewrite HintDb @ident This command displays all rewrite hints contained in :n:`@ident`. .. cmd:: Remove Hints {+ @qualid } {? : {+ @ident } } Removes the hints associated with the :n:`{+ @qualid }` in databases :n:`{+ @ident}`. Hints removals within sections are local to the section. Note: hints created with :cmd:`Hint Extern` currently can't be removed because they aren't associated with names. The best workaround for this is to make the hints non-global and carefully select which modules you import. .. cmd:: Print Hint {? {| * | @reference } } :n:`*` Display all declared hints. :n:`@reference` Display all hints associated with the head symbol :n:`@reference`. Displays tactics from the hints list. The default is to show hints that apply to the conclusion of the current goal. The other forms with :n:`*` and :n:`@reference` can be used even if no proof is open. Each hint has a cost that is a nonnegative integer and an optional pattern. The hints with lower cost are tried first. .. cmd:: Print HintDb @ident This command displays all hints from database :n:`@ident`. Hints are grouped by the :term:`head constants ` of their patterns ("For ... ->"). The groups are shown ordered alphabetically on the last component of the head constant name. Within each group, hints are shown in the order in which they will be tried (first to last). Note that hints with the same cost are tried in reverse of the order they're defined in, i.e., last defined is used first. Mode of resolution symbols, :n:`{+ {| + | ! | - } }`, when defined with :cmd:`Hint Mode`, appear after the head constant. .. _tactics-implicit-automation: Setting implicit automation tactics ----------------------------------- .. cmd:: Proof with @generic_tactic {? using @section_var_expr } Starts a proof in which :token:`generic_tactic` is applied to the active goals after each tactic that ends with `...` instead of the usual single period. ":n:`@tactic...`" is equivalent to ":n:`@tactic; @generic_tactic.`". .. seealso:: :cmd:`Proof` in :ref:`proof-editing-mode`. rocq-9.2.0/doc/sphinx/proofs/automatic-tactics/index.rst000066400000000000000000000011271516144147600233450ustar00rootroot00000000000000.. _automatic-tactics: ===================================================== Automatic solvers and programmable tactics ===================================================== Some tactics are largely automated and are able to solve complex goals. This chapter presents both built-in solvers that can be used on specific categories of goals and programmable tactics that the user can instrument to handle complex goals in new domains. .. toctree:: :maxdepth: 1 logic ../../addendum/micromega ../../addendum/ring ../../addendum/nsatz auto ../../addendum/generalized-rewriting rocq-9.2.0/doc/sphinx/proofs/automatic-tactics/logic.rst000066400000000000000000000240271516144147600233370ustar00rootroot00000000000000.. _decisionprocedures: ============================== Solvers for logic and equality ============================== .. tacn:: tauto This tactic implements a decision procedure for intuitionistic propositional calculus based on the contraction-free sequent calculi LJT* of Roy Dyckhoff :cite:`Dyc92`. Note that :tacn:`tauto` succeeds on any instance of an intuitionistic tautological proposition. :tacn:`tauto` unfolds negations and logical equivalence but does not unfold any other definition. .. example:: The following goal can be proved by :tacn:`tauto` whereas :tacn:`auto` would fail: .. rocqtop:: reset all Goal forall (x:nat) (P:nat -> Prop), x = 0 \/ P x -> x <> 0 -> P x. intros. tauto. Moreover, if it has nothing else to do, :tacn:`tauto` performs introductions. Therefore, the use of :tacn:`intros` in the previous proof is unnecessary. :tacn:`tauto` can for instance solve: .. example:: .. rocqtop:: reset all Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) -> forall x:nat, ~ A -> P x. tauto. .. note:: In contrast, :tacn:`tauto` cannot solve the following goal :g:`Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) ->` :g:`forall x:nat, ~ ~ (A \/ P x).` because :g:`(forall x:nat, ~ A -> P x)` cannot be treated as atomic and an instantiation of `x` is necessary. .. tacn:: dtauto While :tacn:`tauto` recognizes inductively defined connectives isomorphic to the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``, ``Empty_set``, ``unit`` and ``True``, :tacn:`dtauto` also recognizes all inductive types with one constructor and no indices, i.e. record-style connectives. .. todo would be nice to explain/discuss the various types of flags that define the differences between these tactics. See Tauto.v/tauto.ml. .. tacn:: intuition {? @ltac_expr } Uses the search tree built by the decision procedure for :tacn:`tauto` to generate a set of subgoals equivalent to the original one (but simpler than it) and applies :n:`@ltac_expr` to them :cite:`Mun94`. If :n:`@ltac_expr` is not specified, it defaults to ``Tauto.intuition_solver``. The initial value of ``intuition_solver`` is equivalent to :n:`auto with *` but prints warning ``intuition-auto-with-star`` when it solves a goal that :tacn:`auto` cannot solve. In a future version it will be changed to just :tacn:`auto`. Use ``intuition tac`` locally or ``Ltac Tauto.intuition_solver ::= tac`` globally to silence the warning in a forward compatible way with your choice of tactic ``tac`` (``auto``, ``auto with *``, ``auto with`` your prefered databases, or any other tactic). If :n:`@ltac_expr` fails on some goals then :tacn:`intuition` fails. In fact, :tacn:`tauto` is simply :g:`intuition fail`. :tacn:`intuition` recognizes inductively defined connectives isomorphic to the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``, ``Empty_set``, ``unit`` and ``True``. .. example:: For instance, the tactic :g:`intuition auto` applied to the goal:: (forall (x:nat), P x) /\ B -> (forall (y:nat), P y) /\ P O \/ B /\ P O internally replaces it by the equivalent one:: (forall (x:nat), P x), B |- P O and then uses :tacn:`auto` which completes the proof. .. tacn:: dintuition {? @ltac_expr } In addition to the inductively defined connectives recognized by :tacn:`intuition`, :tacn:`dintuition` also recognizes all inductive types with one constructor and no indices, i.e. record-style connectives. .. flag:: Intuition Negation Unfolding This :term:`flag` controls whether :tacn:`intuition` unfolds inner negations which do not need to be unfolded. It is on by default. .. tacn:: rtauto Solves propositional tautologies similarly to :tacn:`tauto`, but the proof term is built using a reflection scheme applied to a sequent calculus proof of the goal. The search procedure is also implemented using a different technique. Users should be aware that this difference may result in faster proof search but slower proof checking, and :tacn:`rtauto` might not solve goals that :tacn:`tauto` would be able to solve (e.g. goals involving universal quantifiers). Note that this tactic is only available after a ``Require Import Rtauto``. .. flag:: Rtauto Check Turning this :term:`flag` on checks the produced proof term at tactic time instead of just proof closing (:cmd:`Qed`) time. Mostly useful for debugging failures at proof closing time. Off by default. .. flag:: Rtauto Verbose Make :tacn:`rtauto` print some debug info while running when on. Off by default. .. flag:: Rtauto Pruning :undocumented: .. tacn:: firstorder {? @ltac_expr } {? using {+, @qualid } } {? with {+ @ident } } An experimental extension of :tacn:`tauto` to first-order reasoning. It is not restricted to usual logical connectives but instead can reason about any first-order class inductive definition. :token:`ltac_expr` Tries to solve the goal with :token:`ltac_expr` when no logical rule applies. If unspecified, the tactic uses the default from the :opt:`Firstorder Solver` option. :n:`using {+, @qualid }` Adds the lemmas :n:`{+, @qualid }` to the proof search environment. If :n:`@qualid` refers to an inductive type, its constructors are added to the proof search environment. :n:`with {+ @ident }` Adds lemmas from :tacn:`auto` hint bases :n:`{+ @ident }` to the proof search environment. .. opt:: Firstorder Solver @ltac_expr The default tactic used by :tacn:`firstorder` when no rule applies in :g:`auto with core`. This command supports the same locality attributes as :cmd:`Obligation Tactic`. .. cmd:: Print Firstorder Solver Prints the default tactic used by :tacn:`firstorder` when no rule applies. .. opt:: Firstorder Depth @natural This :term:`option` controls the proof search depth bound. .. tacn:: congruence {? @natural } {? with {+ @one_term } } :token:`natural` Specifies the maximum number of hypotheses stating quantified equalities that may be added to the problem in order to solve it. The default is 1000. :n:`{? with {+ @one_term } }` Adds :n:`{+ @one_term }` to the pool of terms used by :tacn:`congruence`. This helps in case you have partially applied constructors in your goal. Implements the standard Nelson and Oppen congruence closure algorithm, which is a decision procedure for ground equalities with uninterpreted symbols. It also includes constructor theory (see :tacn:`injection` and :tacn:`discriminate`). If the goal is a non-quantified equality, congruence tries to prove it with non-quantified equalities in the context. Otherwise it tries to infer a discriminable equality from those in the context. Alternatively, congruence tries to prove that a hypothesis is equal to the goal or to the negation of another hypothesis. :tacn:`congruence` is also able to take advantage of hypotheses stating quantified equalities, but you have to provide a bound for the number of extra equalities generated that way. Please note that one of the sides of the equality must contain all the quantified variables in order for congruence to match against it. Increasing the maximum number of hypotheses may solve problems that would have failed with a smaller value. It will make failures slower but it won't make successes found with the smaller value any slower. You may want to use :tacn:`assert` to add some lemmas as hypotheses so that :tacn:`congruence` can use them. .. tacn:: simple congruence {? @natural } {? with {+ @one_term } } Behaves like :tacn:`congruence`, but does not unfold definitions. .. example:: .. rocqtop:: reset all Theorem T (A:Type) (f:A -> A) (g: A -> A -> A) a b: a=(f a) -> (g b (f a))=(f (f a)) -> (g a b)=(f (g b a)) -> (g a b)=a. intros. congruence. Qed. Theorem inj (A:Type) (f:A -> A * A) (a c d: A) : f = pair a -> Some (f c) = Some (f d) -> c=d. intros. congruence. Qed. .. exn:: I don’t know how to handle dependent equality. The decision procedure managed to find a proof of the goal or of a discriminable equality but this proof could not be built in Rocq because of dependently-typed functions. .. exn:: Goal is solvable by congruence but some arguments are missing. Try congruence with {+ @term}, replacing metavariables by arbitrary terms. The decision procedure could solve the goal with the provision that additional arguments are supplied for some partially applied constructors. Any term of an appropriate type will allow the tactic to successfully solve the goal. Those additional arguments can be given to congruence by filling in the holes in the terms given in the error message, using the `with` clause. Setting :opt:`Debug` ``"congruence"`` makes :tacn:`congruence` print debug information. .. tacn:: btauto The tactic :tacn:`btauto` implements a reflexive solver for boolean tautologies. It solves goals of the form :g:`t = u` where `t` and `u` are constructed over the following grammar: .. prodn:: btauto_term ::= @ident | true | false | orb @btauto_term @btauto_term | andb @btauto_term @btauto_term | xorb @btauto_term @btauto_term | negb @btauto_term | if @btauto_term then @btauto_term else @btauto_term Whenever the formula supplied is not a tautology, it also provides a counter-example. Internally, it uses a system very similar to the one of the ring tactic. Note that this tactic is only available after a ``Require Import Btauto``. .. exn:: Cannot recognize a boolean equality. The goal is not of the form :g:`t = u`. Especially note that :tacn:`btauto` doesn't introduce variables into the context on its own. rocq-9.2.0/doc/sphinx/proofs/creating-tactics/000077500000000000000000000000001516144147600213115ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/proofs/creating-tactics/index.rst000066400000000000000000000034751516144147600231630ustar00rootroot00000000000000.. _writing-tactics: ==================== Creating new tactics ==================== The languages presented in this chapter allow one to build complex tactics by combining existing ones with constructs such as conditionals and looping. While :ref:`Ltac ` was initially thought of as a language for doing some basic combinations, it has been used successfully to build highly complex tactics as well, but this has also highlighted its limits and fragility. The language :ref:`Ltac2 ` is a typed and more principled variant which is more adapted to building complex tactics. There are other solutions beyond these two tactic languages to write new tactics: - `Mtac2 `_ is an external plugin which provides another typed tactic language. While Ltac2 belongs to the ML language family, Mtac2 reuses the language of Rocq itself as the language to build Rocq tactics. - `Coq-Elpi `_ is an external plugin which provides an extension language based on Ξ»Prolog, a programming language well suited to write code which manipulates syntax trees with binders such as Rocq terms. Elpi provides an extensive set of APIs to create commands (i.e. script the vernacular language) and tactics. - The most traditional way of building new complex tactics is to write a Rocq plugin in OCaml. Beware that this requires much more effort. Furthermore, Rocq's OCaml API can change from release to release without backward compatibility support, which can cause a significant ongoing maintenance burden. A tutorial for writing Rocq plugins is available in the Rocq repository in `doc/plugin_tutorial `_. .. toctree:: :maxdepth: 1 ../../proof-engine/ltac ../../proof-engine/ltac2 rocq-9.2.0/doc/sphinx/proofs/writing-proofs/000077500000000000000000000000001516144147600210565ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/proofs/writing-proofs/equality.rst000066400000000000000000001431141516144147600234510ustar00rootroot00000000000000========================= Reasoning with equalities ========================= There are multiple notions of :gdef:`equality` in Rocq: - :gdef:`Leibniz equality` is the standard way to define equality in Rocq and the Calculus of Inductive Constructions, which is in terms of a binary relation, i.e. a binary function that returns a `Prop`. The standard library defines `eq` similar to this: .. rocqdoc:: Inductive eq {A : Type} (x : A) : A -> Prop := eq_refl : eq x x. The notation `x = y` represents the term `eq x y`. The notation `x = y :> A` gives the type of x and y explicitly. - :gdef:`Setoid equality ` defines equality in terms of an equivalence relation. A :gdef:`setoid` is a set that is equipped with an equivalence relation (see https://en.wikipedia.org/wiki/Setoid). These are needed to form a :gdef:`quotient set` or :gdef:`quotient` (see https://en.wikipedia.org/wiki/Equivalence_class). In Rocq, users generally work with setoids rather than constructing quotients, for which there is no specific support. - :gdef:`Definitional equality ` is equality based on the :ref:`conversion rules `, which Rocq can determine automatically. Two terms are definitionally equal when they reduce to syntactically identical terms using the conversion rules. When two terms are definitionally equal, Rocq knows it can replace one with the other, such as with :tacn:`change` `X with Y`, among many other advantages. ":term:`Convertible `" is another way of saying that two terms are definitionally equal. Among other reductions, the conversion rules can do computation to simplify expressions. The behavior depends on the function associated with an operator, such as `+` (through the :ref:`Notation ` mechanism). `+` refers to different functions depending on the data type of its operands. Using the standard library definitions of `+` for `nat` and `Z`, `1 + 2` will be reduced to `3`. But the conversion rules don't do all the reductions that a person might. For example, for the mentioned definitions, `n + 0` is not reducible due to how the add function is defined (see the aside :ref:`here `). `n + 1 + 2` isn't reducible because it's represented as `(n + 1) + 2` and convertibility doesn't consider associativity. In contrast, for type `R`, `1 + 2` is not reduced at all. Tactics for dealing with equality of inductive types such as :tacn:`injection` and :tacn:`inversion` are described :ref:`here `. Tactics for simple equalities ----------------------------- .. tacn:: reflexivity After doing an :tacn:`intros`, if the resulting goal is in the form `t = u` in which `t` and `u` are :term:`definitionally equal `, the tactic proves the goal (by applying `eq_refl`). If not, it fails. The tactic also works if the resulting goal (after the :tacn:`intros`) has the form `R t u` where `R` is a reflexive relation registered with the `Equivalence` or `Reflexive` typeclasses. See :cmd:`Class` and :cmd:`Instance`. .. exn:: The relation @ident is not a declared reflexive relation. Maybe you need to require the Stdlib.Classes.RelationClasses library :undocumented: .. tacn:: symmetry {? @simple_occurrences } Changes a goal that has the form :n:`{? forall @open_binders , } t = u` into :n:`u = t`. :n:`@simple_occurrences` may be used to apply the change in the selected hypotheses and/or the conclusion. The tactic may also be applied to goals with the form :n:`{? forall @open_binders , } R @term__1 @term__2` where `R` is a symmetric relation registered with the `Equivalence` or `Symmetric` typeclasses. See :cmd:`Class` and :cmd:`Instance`. .. exn:: The relation @ident is not a declared symmetric relation. Maybe you need to require the Stdlib.Classes.RelationClasses library :undocumented: .. tacn:: transitivity @one_term Changes a goal that has the form :n:`{? forall @open_binders , } t = u` into the two subgoals :n:`t = @one_term` and :n:`@one_term = u`. The tactic may also be applied to goals with the form :n:`{? forall @open_binders , } R @term__1 @term__2` where `R` is a transitive relation registered with the `Equivalence` or `Transitivity` typeclasses. See :cmd:`Class` and :cmd:`Instance`. .. tacn:: etransitivity This tactic behaves like :tacn:`transitivity`, using a fresh evar instead of a concrete :token:`one_term`. .. exn:: The relation @ident is not a declared transitive relation. Maybe you need to require the Stdlib.Classes.RelationClasses library :undocumented: .. tacn:: f_equal For a goal with the form :n:`f a__1 ... a__n = g b__1 ... b__n`, creates subgoals :n:`f = g` and :n:`a__i = b__i` for the `n` arguments. Subgoals that can be proven by :tacn:`reflexivity` or :tacn:`congruence` are solved automatically. .. _rewritingexpressions: Rewriting with Leibniz and setoid equality ------------------------------------------ .. tacn:: rewrite {+, @oriented_rewriter } {? @occurrences } {? by @ltac_expr3 } .. insertprodn oriented_rewriter oriented_rewriter .. prodn:: oriented_rewriter ::= {? {| -> | <- } } {? @natural } {? {| ? | ! } } @one_term_with_bindings Replaces subterms with other subterms that have been proven to be equal or logically equivalent. For equal terms, the type of :n:`@one_term` must have the form: :n:`{? forall @open_binders , } EQ @term__1 @term__2` where :g:`EQ` is the :term:`Leibniz equality` `eq` or a registered :term:`setoid equality`. Note that :n:`eq @term__1 @term__2` is typically written with the infix notation :n:`@term__1 = @term__2`. For logically equivalent terms, the type of :n:`@one_term` must have the form: :n:`{? forall @open_binders , } @term__1 <-> @term__2` You must `Require Setoid` to use the tactic with a setoid equality, logical equivalence or with :ref:`setoid rewriting `. :n:`rewrite @one_term` finds subterms matching :n:`@term__1` in the goal, and replaces them with :n:`@term__2` (or the reverse if `<-` is given). Some of the variables :g:`x`\ :sub:`i` are solved by unification, and some of the types :n:`A__1, …, A__n` may become new subgoals. :tacn:`rewrite` won't find occurrences inside `forall` that refer to variables bound by the `forall`; use the more advanced :tacn:`setoid_rewrite` if you want to find such occurrences. :n:`{+, @oriented_rewriter }` The :n:`@oriented_rewriter`\s are applied sequentially to the first goal generated by the previous :n:`@oriented_rewriter`. If any of them fail, the tactic fails. :n:`{? {| -> | <- } }` For `->` (the default), :n:`@term__1` is rewritten into :n:`@term__2`. For `<-`, :n:`@term__2` is rewritten into :n:`@term__1`. :n:`{? @natural } {? {| ? | ! } }` :n:`@natural` is the number of rewrites to perform. If :n:`?` is given, :n:`@natural` is the maximum number of rewrites to perform; otherwise :n:`@natural` is the exact number of rewrites to perform. :n:`?` (without :n:`@natural`) performs the rewrite as many times as possible (possibly zero times). This form never fails. :n:`!` (without :n:`@natural`) performs the rewrite as many times as possible and at least once. The tactic fails if the requested number of rewrites can't be performed. :n:`@natural !` is equivalent to :n:`@natural`. :n:`@occurrences` If :n:`@occurrences` specifies multiple occurrences, the tactic succeeds if any of them can be rewritten. If not specified, only the first occurrence in the conclusion is replaced. .. note:: If :n:`at @occs_nums` is specified, rewriting is always done with :ref:`setoid rewriting `, even for Leibniz equality, which means that you must `Require Setoid` to use that form. However, note that :tacn:`rewrite` (even when using setoid rewriting) and :tacn:`setoid_rewrite` don't behave identically (as is noted above and below). :n:`by @ltac_expr3` If specified, is used to resolve all side conditions generated by the tactic. .. note:: For each selected hypothesis and/or the conclusion, :tacn:`rewrite` finds the first matching subterm in depth-first search order. Only subterms identical to that first matched subterm are rewritten. If the `at` clause is specified, only these subterms are considered when counting occurrences. To select a different set of matching subterms, you can specify how some or all of the free variables are bound by using a `with` clause (see :n:`@one_term_with_bindings`). For instance, if we want to rewrite the right-hand side in the following goal, this will not work: .. rocqtop:: none From Corelib Require Import Setoid. Axiom add_comm : forall n m, n + m = m + n. .. rocqtop:: out Lemma example x y : x + y = y + x. .. rocqtop:: all fail rewrite add_comm at 2. One can explicitly specify how some variables are bound to match a different subterm: .. rocqtop:: all abort rewrite add_comm with (m := x). Note that the more advanced :tacn:`setoid_rewrite` tactic behaves differently, and thus the number of occurrences available to rewrite may differ between the two tactics. .. exn:: Tactic failure: Setoid library not loaded. :undocumented: .. todo You can use Typeclasses Debug to tell whether rewrite used setoid rewriting. Example here: https://github.com/rocq-prover/rocq/pull/13470#discussion_r539230973 .. exn:: Cannot find a relation to rewrite. :undocumented: .. exn:: Tactic generated a subgoal identical to the original goal. :undocumented: .. exn:: Found no subterm matching @term in @ident. Found no subterm matching @term in the current goal. This happens if :n:`@term` does not occur in, respectively, the named hypothesis or the goal. .. tacn:: erewrite {+, @oriented_rewriter } {? @occurrences } {? by @ltac_expr3 } Works like :tacn:`rewrite`, but turns unresolved bindings, if any, into existential variables instead of failing. It has the same parameters as :tacn:`rewrite`. .. flag:: Keyed Unification This :term:`flag` makes higher-order unification used by :tacn:`rewrite` rely on a set of keys to drive unification. The subterms, considered as rewriting candidates, must start with the same key as the left- or right-hand side of the lemma given to rewrite, and the arguments are then unified up to full reduction. .. cmd:: Declare Equivalent Keys @one_term @one_term :undocumented: .. cmd:: Print Equivalent Keys :undocumented: .. tacn:: rewrite * {? {| -> | <- } } @one_term {? in @ident } {? at @rewrite_occs } {? by @ltac_expr3 } rewrite * {? {| -> | <- } } @one_term at @rewrite_occs in @ident {? by @ltac_expr3 } :name: rewrite *; _ :undocumented: .. tacn:: replace {? {| -> | <- } } @one_term__from with @one_term__to {? @occurrences } {? by @ltac_expr3 } replace {? {| -> | <- } } @one_term__from {? @occurrences } :name: replace; _ The first form, when used with `<-` or no arrow, replaces all free occurrences of :n:`@one_term__from` in the current goal with :n:`@one_term__to` and generates an equality :n:`@one_term__to = @one_term__from` as a subgoal. Note that this equality is reversed with respect to the order of the two terms. When used with `->`, it generates instead an equality :n:`@one_term__from = @one_term__to`. When :n:`by @ltac_expr3` is not present, this equality is automatically solved if it occurs among the hypotheses, or if its symmetric form occurs. The second form, with `->` or no arrow, replaces :n:`@one_term__from` with :n:`@term__to` using the first hypothesis whose type has the form :n:`@one_term__from = @term__to`. If `<-` is given, the tactic uses the first hypothesis with the reverse form, i.e. :n:`@term__to = @one_term__from`. :n:`@occurrences` The `type of` and `value of` forms are not supported. Note you must `Require Setoid` to use the `at` clause in :n:`@occurrences`. :n:`by @ltac_expr3` Applies the :n:`@ltac_expr3` to solve the generated equality. .. exn:: Terms do not have convertible types. :undocumented: .. tacn:: substitute {? {| -> | <- } } @one_term_with_bindings :undocumented: .. tacn:: subst {* @ident } For each :n:`@ident`, in order, for which there is a hypothesis in the form :n:`@ident = @term` or :n:`@term = @ident`, replaces :n:`@ident` with :n:`@term` everywhere in the hypotheses and the conclusion and clears :n:`@ident` and the hypothesis from the context. If there are multiple hypotheses that match the :n:`@ident`, the first one is used. If no :n:`@ident` is given, replacement is done for all hypotheses in the appropriate form in top to bottom order. If :n:`@ident` is a :term:`local definition ` of the form :n:`@ident := @term`, it is also unfolded and cleared. If :n:`@ident` is a section variable it must have no indirect occurrences in the goal, i.e. no global declarations implicitly depending on the section variable may be present in the goal. .. note:: If the hypothesis is itself dependent in the goal, it is replaced by the proof of reflexivity of equality. .. exn:: Cannot find any non-recursive equality over @ident. :undocumented: .. exn:: Section variable @ident occurs implicitly in global declaration @qualid present in hypothesis @ident. Section variable @ident occurs implicitly in global declaration @qualid present in the conclusion. Raised when the variable is a section variable with indirect dependencies in the goal. If :n:`@ident` is a section variable, it must not have any indirect occurrences in the goal, i.e. no global declarations implicitly depending on the section variable may be present in the goal. .. tacn:: simple subst :undocumented: .. tacn:: stepl @one_term {? by @ltac_expr } For chaining rewriting steps. It assumes a goal in the form :n:`R @term__1 @term__2` where ``R`` is a binary relation and relies on a database of lemmas of the form :g:`forall x y z, R x y -> eq x z -> R z y` where `eq` is typically a setoid equality. The application of :n:`stepl @one_term` then replaces the goal by :n:`R @one_term @term__2` and adds a new goal stating :n:`eq @one_term @term__1`. If :n:`@ltac_expr` is specified, it is applied to the side condition. .. cmd:: Declare Left Step @one_term Adds :n:`@one_term` to the database used by :tacn:`stepl`. This tactic is especially useful for parametric setoids which are not accepted as regular setoids for :tacn:`rewrite` and :tacn:`setoid_replace` (see :ref:`Generalizedrewriting`). .. tacn:: stepr @one_term {? by @ltac_expr } This behaves like :tacn:`stepl` but on the right hand side of the binary relation. Lemmas are expected to be in the form :g:`forall x y z, R x y -> eq y z -> R x z`. .. cmd:: Declare Right Step @one_term Adds :n:`@term` to the database used by :tacn:`stepr`. Rewriting with definitional equality ------------------------------------ .. tacn:: change {? @one_term__from {? at @occs_nums } with } @one_term__to {? @occurrences } Replaces terms with other :term:`convertible` terms. If :n:`@one_term__from` is not specified, then :n:`@one_term__to` replaces the conclusion and/or the specified hypotheses. If :n:`@one_term__from` is specified, the tactic replaces occurrences of :n:`@one_term__from` within the conclusion and/or the specified hypotheses. :n:`{? @one_term__from {? at @occs_nums } with }` Replaces the occurrences of :n:`@one_term__from` specified by :n:`@occs_nums` with :n:`@one_term__to`, provided that the two :n:`@one_term`\s are convertible. :n:`@one_term__from` may contain pattern variables such as `?x`, whose value will be substituted for `x` in :n:`@one_term__to`, such as in `change (f ?x ?y) with (g (x, y))` or `change (fun x => ?f x) with f`. The `at … with …` form is deprecated in 8.14; use `with … at …` instead. For `at … with … in H |-`, use `with … in H at … |-`. :n:`@occurrences` If `with` is not specified, :n:`@occurrences` must only specify entire hypotheses and/or the goal; it must not include any :n:`at @occs_nums` clauses. .. exn:: Not convertible. :undocumented: .. exn:: Found an "at" clause without "with" clause :name: Found an at clause without with clause :undocumented: .. tacn:: now_show @one_type A synonym for :n:`change @one_type`. It can be used to make some proof steps explicit when refactoring a proof script to make it readable. .. seealso:: :ref:`applyingconversionrules` .. tacn:: change_no_check {? @one_term__from {? at @occs_nums } with } @one_term__to {? @occurrences } For advanced usage. Similar to :tacn:`change`, but as an optimization, it skips checking that :n:`@one_term__to` is convertible with the conclusion, the specified hypotheses, or :n:`@one_term__from`. Recall that the Rocq kernel typechecks proofs again when they are concluded to ensure correctness. Hence, using :tacn:`change` checks convertibility twice overall, while :tacn:`change_no_check` can produce ill-typed terms, but checks convertibility only once. Hence, :tacn:`change_no_check` can be useful to speed up certain proof scripts, especially if one knows by construction that the argument is indeed convertible to the goal. In the following example, :tacn:`change_no_check` replaces :g:`False` with :g:`True`, but :cmd:`Qed` then rejects the proof, ensuring consistency. .. example:: .. rocqtop:: all abort fail Goal False. change_no_check True. exact I. Qed. .. example:: .. rocqtop:: all abort fail Goal True -> False. intro H. change_no_check False in H. exact H. Qed. .. _applyingconversionrules: Applying conversion rules ------------------------- These tactics apply reductions and expansions, replacing :term:`convertible` subterms with others that are equal by definition in |CiC|. They implement different specialized uses of the :tacn:`change` tactic. Other ways to apply these reductions are through the :cmd:`Eval` command, the `Eval` clause in the :cmd:`Definition`/:cmd:`Example` command and the :tacn:`eval` tactic. Tactics described in this section include: - :tacn:`lazy` and :tacn:`cbv`, which allow precise selection of which reduction rules to apply - :tacn:`simpl` and :tacn:`cbn`, which are "clever" tactics meant to give the most readable result - :tacn:`hnf` and :tacn:`red`, which apply reduction rules only to the head of the term - :tacn:`vm_compute` and :tacn:`native_compute`, which are performance-oriented. Except for :tacn:`red`, conversion tactics succeed even if the context is left unchanged. Conversion tactics, with two exceptions, only change the types and contexts of existential variables and leave the proof term unchanged. (The :tacn:`vm_compute` and :tacn:`native_compute` tactics change existential variables in a way similar to other conversions while also adding a single explicit cast to the proof term to tell the kernel which reduction engine to use. See :ref:`type-cast`.) For example: .. rocqtop:: all Goal 3 + 4 = 7. Show Proof. Show Existentials. cbv. Show Proof. Show Existentials. .. rocqtop:: none Abort. .. tacn:: lazy {? @reductions } @simple_occurrences cbv {? @reductions } @simple_occurrences .. insertprodn reductions delta_reductions .. prodn:: reductions ::= {+ @reduction } | {? head } @delta_reductions reduction ::= head | beta | delta {? @delta_reductions } | match | fix | cofix | iota | zeta delta_reductions ::= {? - } [ {+ @reference } ] Normalize the goal as specified by :n:`@reductions`. If no reductions are specified by name, all reductions are applied. If any reductions are specified by name, then only the named reductions are applied. The reductions include: `head` Do only head reduction, without going under binders. Supported by :tacn:`simpl`, :tacn:`cbv`, :tacn:`cbn` and :tacn:`lazy`. If this is the only specified reduction, all other reductions are applied. `beta` :term:`beta-reduction` of functional application :n:`delta {? @delta_reductions }` :term:`delta-reduction`: unfolding of transparent constants, see :ref:`controlling-the-reduction-strategies`. The form in :n:`@reductions` without the keyword `delta` includes `beta`, `iota` and `zeta` reductions in addition to `delta` using the given :n:`@delta_reductions`. :n:`{? - } [ {+ @reference } ]` without the `-`, limits delta unfolding to the listed constants. If the `-` is present, unfolding is applied to all constants that are not listed. Notice that the ``delta`` doesn't apply to variables bound by a let-in construction inside the term itself (use ``zeta`` to inline these). Opaque constants are not unfolded by most tactics (see `#4476 `_ and :ref:`controlling-the-reduction-strategies`). `iota` :term:`iota-reduction` of pattern matching (`match`) over a constructed term and reduction of :g:`fix` and :g:`cofix` expressions. Shorthand for `match fix cofix`. `zeta` :term:`zeta-reduction`: reduction of :ref:`let-in definitions ` Normalization is done by first evaluating the head of the expression into :gdef:`weak-head normal form`, i.e. until the evaluation is blocked by a variable, an opaque constant, an axiom, such as in :n:`x u__1 … u__n`, :g:`match x with … end`, :g:`(fix f x {struct x} := …) x`, a constructed form (a :math:`\lambda`-expression, constructor, cofixpoint, inductive type, product type or sort) or a redex for which flags prevent reduction of the redex. Once a weak-head normal form is obtained, subterms are recursively reduced using the same strategy. There are two strategies for reduction to weak-head normal form: *lazy* (the :tacn:`lazy` tactic), or *call-by-value* (the :tacn:`cbv` tactic). The lazy strategy is a `call by need `_ strategy, with sharing of reductions: the arguments of a function call are weakly evaluated only when necessary, and if an argument is used several times then it is weakly computed only once. This reduction is efficient for reducing expressions with dead code. For instance, the proofs of a proposition :g:`exists x. P(x)` reduce to a pair of a witness :g:`t` and a proof that :g:`t` satisfies the predicate :g:`P`. Most of the time, :g:`t` may be computed without computing the proof of :g:`P(t)`, thanks to the lazy strategy. .. flag:: Kernel Term Sharing Turning this flag off disables the sharing of computations in :tacn:`lazy`, making it a call-by-name reduction. This also affects the reduction procedure used by the kernel when typechecking. By default sharing is activated. The call-by-value strategy is the one used in ML languages: the arguments of a function call are systematically weakly evaluated first. The lazy strategy is similar to how Haskell reduces terms. Although the lazy strategy always does fewer reductions than the call-by-value strategy, the latter is generally more efficient for evaluating purely computational expressions (i.e. with little dead code). .. tacn:: compute {? @delta_reductions } @simple_occurrences A variant form of :tacn:`cbv`. Setting :opt:`Debug` ``"Cbv"`` makes :tacn:`cbv` (and its derivative :tacn:`compute`) print information about the constants it encounters and the unfolding decisions it makes. .. tacn:: simpl {? head } {? @delta_reductions } {? {| @reference_occs | @pattern_occs } } @simple_occurrences .. insertprodn reference_occs pattern_occs .. prodn:: reference_occs ::= @reference {? at @occs_nums } pattern_occs ::= @one_term {? at @occs_nums } Reduces a term to something still readable instead of fully normalizing it. It performs a sort of strong normalization with two key differences: + It unfolds constants only if they lead to an ΞΉ-reduction, i.e. reducing a match or unfolding a fixpoint. + When reducing a constant unfolding to (co)fixpoints, the tactic uses the name of the constant the (co)fixpoint comes from instead of the (co)fixpoint definition in recursive calls. :n:`@occs_nums` Selects which occurrences of :n:`@one_term` to process (counting from left to right on the expression printed using the :flag:`Printing All` flag) :n:`@simple_occurrences` Permits selecting whether to reduce the conclusion and/or one or more hypotheses. While the `at` option of :n:`@occurrences` is not allowed here, :n:`@reference_occs` and :n:`@pattern_occs` have a somewhat less flexible `at` option for selecting specific occurrences. :tacn:`simpl` can unfold transparent constants whose name can be reused in recursive calls as well as those designated by :cmd:`Arguments` :n:`@reference … /` commands. For instance, a constant :g:`plus' := plus` may be unfolded and reused in recursive calls, but a constant such as :g:`succ := plus (S O)` is not unfolded unless it was specifically designated in an :cmd:`Arguments` command such as :n:`Arguments succ /.`. :n:`{| @reference_occs | @pattern_occs }` can limit the application of :tacn:`simpl` to: - applicative subterms whose :term:`head` is the constant :n:`@qualid` or is the constant used in the notation :n:`@string` (see :n:`@reference`) - subterms matching a pattern :n:`@one_term` .. flag:: SimplIsCbn When this :term:`flag` is on, :tacn:`simpl` and `simpl` in :n:`@red_expr` behave as :tacn:`cbn`. Off by default. .. tacn:: cbn {? @reductions } @simple_occurrences :tacn:`cbn` was intended to be a more principled, faster and more predictable replacement for :tacn:`simpl`. The main difference is that :tacn:`cbn` may unfold constants even when they cannot be reused in recursive calls: in the previous example, :g:`succ t` is reduced to :g:`S t`. Modifiers such as `simpl never` are also not treated the same, see :ref:`Args_effect_on_unfolding`. Setting :opt:`Debug` ``"RAKAM"`` makes :tacn:`cbn` print various debugging information. ``RAKAM`` is the Refolding Algebraic Krivine Abstract Machine. .. example:: Here are typical examples comparing :tacn:`cbn` and :tacn:`simpl`: .. rocqtop:: all Definition add1 (n:nat) := n + 1. Eval simpl in add1 0. Eval cbn in add1 0. Definition pred_add n m := pred (n + m). Eval simpl in pred_add 0 0. Eval cbn in pred_add 0 0. Parameter n : nat. Eval simpl in pred_add 0 n. Eval cbn in pred_add 0 n. .. tacn:: hnf @simple_occurrences Replaces the current goal with its weak-head normal form according to the βδι΢-reduction rules, i.e. it reduces the :term:`head` of the goal until it becomes a product or an irreducible term. All inner Ξ²ΞΉ-redexes are also reduced. While :tacn:`hnf` behaves similarly to :tacn:`simpl` and :tacn:`cbn`, unlike them, it does not recurse into subterms. The behavior of :tacn:`hnf` can be tuned using the :cmd:`Arguments` command. Example: The term :g:`fun n : nat => S n + S n` is not reduced by :n:`hnf`. .. note:: The Ξ΄ rule only applies to transparent constants (see :ref:`controlling-the-reduction-strategies` on transparency and opacity). .. tacn:: red @simple_occurrences Ξ²ΞΉΞΆ-reduces the :term:`head constant` of `T`, if possible, in the selected hypotheses and/or the goal which have the form: :n:`{? forall @open_binders , } T` (where `T` does not begin with a `forall`) to :n:`c t__1 … t__n` where :g:`c` is a constant. If :g:`c` is transparent then it replaces :g:`c` with its definition and reduces again until no further reduction is possible. In the term :n:`{? forall @open_binders , } t__1 ... t__n`, where :n:`t__1` is not a :n:`@term_application`, :n:`t__1` is the :gdef:`head` of the term. In a term with the form :n:`{? forall @open_binders , } c t__1 ... t__n`, where :n:`c` is a :term:`constant`, :n:`c` is the :gdef:`head constant`. .. exn:: No head constant to reduce. :undocumented: .. tacn:: unfold {+, @reference_occs } {? @occurrences } Applies :term:`delta-reduction` to the constants specified by each :n:`@reference_occs`. The selected hypotheses and/or goals are then reduced to Ξ²ΞΉΞΆ-normal form. Use the general reduction tactics if you want to only apply the Ξ΄ rule, for example :tacn:`cbv` :n:`delta [ @reference ]`. :n:`@reference_occs` If :n:`@reference` is a :n:`@qualid`, it must be a defined transparent constant or :term:`local definition ` (see :ref:`gallina-definitions` and :ref:`controlling-the-reduction-strategies`). If :n:`@reference` is a :n:`@string {? @scope_key}`, the :n:`@string` is the discriminating symbol of a notation (e.g. "+") or an expression defining a notation (e.g. `"_ + _"`) and the notation is an application whose head symbol is an unfoldable constant, then the tactic unfolds it. :n:`@occurrences` If :n:`@occurrences` is specified, the specified occurrences will be replaced in the selected hypotheses and/or goal. Otherwise every occurrence of the constants in the goal is replaced. If multiple :n:`@reference_occs` are given, any `at` clauses must be in the :n:`@reference_occs` rather than in :n:`@occurrences`. .. exn:: Cannot turn {| inductive | constructor } into an evaluable reference. Occurs when trying to unfold something that is defined as an inductive type (or constructor) and not as a definition. .. example:: .. rocqtop:: abort all fail Goal 0 <= 1. unfold le. .. exn:: @ident is opaque. Raised if you are trying to unfold a definition that has been marked opaque. .. example:: .. rocqtop:: abort all fail Opaque Nat.add. Goal 1 + 0 = 1. unfold Nat.add. .. exn:: Bad occurrence number of @qualid. :undocumented: .. exn:: @qualid does not occur. :undocumented: .. tacn:: fold {+ @one_term } @simple_occurrences First, this tactic reduces each :n:`@one_term` using the :tacn:`red` tactic. Then, every occurrence of the resulting terms in the selected hypotheses and/or goal will be replaced by its associated :n:`@one_term`. This tactic is particularly useful for reversing undesired unfoldings, which may make the goal very hard to read. The undesired unfoldings may be due to the limited capabilities of other reduction tactics. On the other hand, when an unfolded function applied to its argument has been reduced, the :tacn:`fold` tactic doesn't do anything. :tacn:`fold` :n:`@one_term__1 @one_term__2` is equivalent to :n:`fold @one_term__1; fold @one_term__2`. .. example:: :tacn:`fold` doesn't always undo :tacn:`unfold` .. rocqtop:: all Goal ~0=0. unfold not. This :tacn:`fold` doesn't undo the preceeding :tacn:`unfold` (it makes no change): .. rocqtop:: all fold not. However, this :tacn:`pattern` followed by :tacn:`fold` does: .. rocqtop:: all abort pattern (0 = 0). fold not. .. example:: Use :tacn:`fold` to reverse unfolding of `fold_right` .. rocqtop:: none Require Import ListDef. Local Open Scope list_scope. Definition fold_right [A B] (f : B -> A -> A) (a0 : A) := fix fold_right (l : list B) : A := match l with | nil => a0 | b :: t => f b (fold_right t) end. .. rocqtop:: all abort Goal forall x xs, fold_right and True (x::xs). red. fold (fold_right and True). .. tacn:: pattern {+, @pattern_occs } {? @occurrences } Performs beta-expansion (the inverse of :term:`beta-reduction`) for the selected hypotheses and/or goals. The :n:`@one_term`\s in :n:`@pattern_occs` must be free subterms in the selected items. The expansion is done for each selected item :g:`T` for a set of :n:`@one_term`\s in the :n:`@pattern_occs` by: + replacing all selected occurrences of the :n:`@one_term`\s in :g:`T` with fresh variables + abstracting these variables + applying the abstracted goal to the :n:`@one_term`\s For instance, if the current goal :g:`T` is expressible as :n:`Ο†(t__1 … t__n)` where the notation captures all the instances of the :n:`t__i` in Ο†, then :tacn:`pattern` :n:`t__1, …, t__n` generates the equivalent goal :n:`(fun (x__1:A__1 … (x__n:A__n) => Ο†(x__1 … x__n)) t__1 … t__n`. If :n:`t__i` occurs in one of the generated types :n:`A__j` (for `j > i`), occurrences will also be considered and possibly abstracted. This tactic can be used, for instance, when the tactic :tacn:`apply` fails on matching or to better control the behavior of :tacn:`rewrite`. See the example :ref:`here `. Fast reduction tactics: vm_compute and native_compute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :tacn:`vm_compute` is a brute-force but efficient tactic that first normalizes the terms before comparing them. It is based on a bytecode representation of terms similar to the bytecode representation used in the ZINC virtual machine :cite:`Leroy90`. It is especially useful for intensive computation of algebraic values, such as numbers, and for reflection-based tactics. :tacn:`native_compute` is based on converting the Rocq code to OCaml. Note that both these tactics ignore :cmd:`Opaque` markings (see issue `#4776 `_), nor do they apply unfolding strategies such as from :cmd:`Strategy`. :tacn:`native_compute` is typically two to five times faster than :tacn:`vm_compute` at applying conversion rules when Rocq is running native code, but :tacn:`native_compute` requires considerably more overhead. We recommend using :tacn:`native_compute` when all of the following are true (otherwise use :tacn:`vm_compute`): - the running time in :tacn:`vm_compute` at least 5-10 seconds - the size of the input term is small (e.g. hand-generated code rather than automatically-generated code that may have nested destructs on inductives with dozens or hundreds of constructors) - the output is small (e.g. you're returning a boolean, a natural number or an integer rather than a large abstract syntax tree) These tactics change existential variables in a way similar to other conversions while also adding a single explicit cast (see :ref:`type-cast`) to the proof term to tell the kernel which reduction engine to use. .. tacn:: vm_compute {? {| @reference_occs | @pattern_occs } } {? @occurrences } Evaluates the goal using the optimized call-by-value evaluation bytecode-based virtual machine described in :cite:`CompiledStrongReduction`. This algorithm is dramatically more efficient than the algorithm used for the :tacn:`cbv` tactic, but it cannot be fine-tuned. It is especially useful for full evaluation of algebraic objects. This includes the case of reflection-based tactics. .. tacn:: native_compute {? {| @reference_occs | @pattern_occs } } {? @occurrences } Evaluates the goal by compilation to OCaml as described in :cite:`FullReduction`. Depending on the configuration, this tactic can either default to :tacn:`vm_compute`, recompile dependencies or fail due to some missing precompiled dependencies, see :ref:`the native-compiler option ` for details. .. flag:: NativeCompute Timing This :term:`flag` causes all calls to the native compiler to print timing information for the conversion to native code, compilation, execution, and reification phases of native compilation. Timing is printed in units of seconds of wall-clock time. .. flag:: NativeCompute Profiling On Linux, if you have the ``perf`` profiler installed, this :term:`flag` makes it possible to profile :tacn:`native_compute` evaluations. .. opt:: NativeCompute Profile Filename @string This :term:`option` specifies the profile output; the default is ``native_compute_profile.data``. The actual filename used will contain extra characters to avoid overwriting an existing file; that filename is reported to the user. That means you can individually profile multiple uses of :tacn:`native_compute` in a script. From the Linux command line, run ``perf report`` on the profile file to see the results. Consult the ``perf`` documentation for more details. Computing in a term: eval and Eval ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Evaluation of a term can be performed with: .. tacn:: eval @red_expr in @term .. insertprodn red_expr red_expr .. prodn:: red_expr ::= lazy {? @reductions } | cbv {? @reductions } | compute {? @delta_reductions } | vm_compute {? {| @reference_occs | @pattern_occs } } | native_compute {? {| @reference_occs | @pattern_occs } } | red | hnf | simpl {? head } {? @delta_reductions } {? {| @reference_occs | @pattern_occs } } | cbn {? @reductions } | unfold {+, @reference_occs } | fold {+ @one_term } | pattern {+, @pattern_occs } | @ident :tacn:`eval` is a :token:`value_tactic`. It returns the result of applying the conversion rules specified by :n:`@red_expr`. It does not change the proof state. The :n:`@red_expr` alternatives that begin with a keyword correspond to the tactic with the same name, though in several cases with simpler syntax than the tactic. :n:`@ident` is a named reduction expression created with :cmd:`Declare Reduction`. .. seealso:: Section :ref:`applyingconversionrules`. .. cmd:: Eval @red_expr in @term Performs the specified reduction on :n:`@term` and displays the resulting term with its type. If a proof is open, :n:`@term` may reference hypotheses of the selected goal. :cmd:`Eval` is a :token:`query_command`, so it may be prefixed with a goal selector. .. cmd:: Compute @term Evaluates :n:`@term` using the bytecode-based virtual machine. It is a shortcut for :cmd:`Eval` :n:`vm_compute in @term`. :cmd:`Compute` is a :token:`query_command`, so it may be prefixed with a goal selector. .. cmd:: Declare Reduction @ident := @red_expr Declares a short name for the reduction expression :n:`@red_expr`, for instance ``lazy beta delta [foo bar]``. This short name can then be used in :n:`Eval @ident in` or ``eval`` constructs. This command accepts the :attr:`local` attribute, which indicates that the reduction will be discarded at the end of the file or module. The name is not qualified. In particular declaring the same name in several modules or in several functor applications will be rejected if these declarations are not local. The name :n:`@ident` cannot be used directly as an Ltac tactic, but nothing prevents the user from also performing a :n:`Ltac @ident := @red_expr`. .. _controlling-the-reduction-strategies: Controlling reduction strategies and the conversion algorithm ------------------------------------------------------------- The commands to fine-tune the reduction strategies and the lazy conversion algorithm are described in this section. Also see :ref:`Args_effect_on_unfolding`, which supports additional fine-tuning. :gdef:`Opaqueness ` is used to control whether constants can be :term:`unfolded ` with :term:`delta-reduction`. Opaque means not to do unfolding is some cases, while :gdef:`Transparent ` permits unfolding. Rocq has multiple notions of opaque: - **Sealed.** Theorems ending with :cmd:`Qed` are permanently marked `opaque`. These are never unfolded and they can't be made transparent. - **Changeably opaque or transparent.** Theorems ending with :cmd:`Defined` and constants default to `transparent` (unfoldable). "Constants" include items defined by commands such as :cmd:`Definition`, :cmd:`Let` (with an explicit body), :cmd:`Fixpoint`, :cmd:`CoFixpoint` and :cmd:`Function`. Their opacity can be changed at any time with the :cmd:`Opaque` and :cmd:`Transparent` commands. Conversion tactics such as :tacn:`simpl` and :tacn:`unfold` only unfold transparent constants. Tactics that use unification, such as :tacn:`reflexivity` and :tacn:`apply` may unfold changeably opaque constants, as can :tacn:`vm_compute` and :tacn:`native_compute` (see `#4476 `_). - The :cmd:`Strategy` command provides some additional refinements (all changeable). .. cmd:: Opaque {? ! } {+ @reference } Marks the specified constants as changeably opaque. This command accepts the :attr:`global` attribute. By default, the scope of :cmd:`Opaque` is limited to the current section or module. :cmd:`Opaque` also affects Rocq's conversion algorithm, causing it to delay unfolding the specified constants as much as possible when it has to check that two distinct applied constants are convertible. See Section :ref:`conversion-rules`. In the particular case where the constants refer to primitive projections, a :n:`!` can be used to make the compatibility constants opaque, while by default the projection themselves are made opaque and the compatibility constants always remain transparent. This mechanism is only intended for debugging purposes. Use the :cmd:`About` command to see if a symbol is transparent or opaque. .. cmd:: Transparent {? ! } {+ @reference } The opposite of :cmd:`Opaque`, it marks the specified constants as :term:`transparent` so that tactics may unfold them. See :cmd:`Opaque` above. This command accepts the :attr:`global` attribute. By default, the scope of :cmd:`Transparent` is limited to the current section or module. Note that constants defined by proofs ending with :cmd:`Qed` are irreversibly opaque; :cmd:`Transparent` will not make them transparent. This is consistent with the usual mathematical practice of *proof irrelevance*: what matters in a mathematical development is the sequence of lemma statements, not their actual proofs. This distinguishes lemmas from the usual defined constants, whose actual values are of course relevant in general. In the particular case where the constants refer to primitive projections, a :n:`!` can be used to make the compatibility constants transparent (see :cmd:`Opaque` for more details). .. exn:: The reference @qualid was not found in the current environment. There is no constant named :n:`@qualid` in the environment. .. seealso:: :ref:`applyingconversionrules`, :cmd:`Qed` and :cmd:`Defined` .. _vernac-strategy: .. cmd:: Strategy {+ @strategy_level [ {+ @reference } ] } .. insertprodn strategy_level strategy_level .. prodn:: strategy_level ::= opaque | @integer | expand | transparent Generalizes the behavior of the :cmd:`Opaque` and :cmd:`Transparent` commands. It is used to fine-tune the strategy for unfolding constants, both at the tactic level and at the kernel level. This command associates a :n:`@strategy_level` with the qualified names in the :n:`@reference` sequence. Whenever two expressions with two distinct :term:`head constants ` are compared (for example, typechecking `f x` where `f : A -> B` and `x : C` will result in converting `A` and `C`), the one with lower level is expanded first. In case of a tie, the second one (appearing in the cast type) is expanded. This command accepts the :attr:`local` attribute, which limits its effect to the current section or module, in which case the section and module behavior is the same as :cmd:`Opaque` and :cmd:`Transparent` (without :attr:`global`). Levels can be one of the following (higher to lower): + ``opaque`` : level of opaque constants. They cannot be expanded by tactics (behaves like +∞, see next item). + :n:`@integer` : levels indexed by an integer. Level 0 corresponds to the default behavior, which corresponds to transparent constants. This level can also be referred to as ``transparent``. Negative levels correspond to constants to be expanded before normal transparent constants, while positive levels correspond to constants to be expanded after normal transparent constants. + ``expand`` : level of constants that should be expanded first (behaves like βˆ’βˆž) + ``transparent`` : Equivalent to level 0 .. cmd:: Print Strategy @reference This command prints the strategy currently associated with :n:`@reference`. It fails if :n:`@reference` is not an unfoldable reference, that is, neither a variable nor a constant. .. exn:: The reference is not unfoldable. :undocumented: .. cmd:: Print Strategies Print all the currently non-transparent strategies. .. tacn:: with_strategy @strategy_level_or_var [ {+ @reference } ] @ltac_expr3 .. insertprodn strategy_level_or_var strategy_level_or_var .. prodn:: strategy_level_or_var ::= @strategy_level | @ident Executes :token:`ltac_expr3`, applying the alternate unfolding behavior that the :cmd:`Strategy` command controls, but only for :token:`ltac_expr3`. This can be useful for guarding calls to reduction in tactic automation to ensure that certain constants are never unfolded by tactics like :tacn:`simpl` and :tacn:`cbn` or to ensure that unfolding does not fail. .. example:: .. rocqtop:: all reset abort Opaque id. Goal id 10 = 10. Fail unfold id. with_strategy transparent [id] unfold id. .. warning:: Use this tactic with care, as effects do not persist past the end of the proof script. Notably, this fine-tuning of the conversion strategy is not in effect during :cmd:`Qed` nor :cmd:`Defined`, so this tactic is most useful either in combination with :tacn:`abstract`, which will check the proof early while the fine-tuning is still in effect, or to guard calls to conversion in tactic automation to ensure that, e.g., :tacn:`unfold` does not fail just because the user made a constant :cmd:`Opaque`. This can be illustrated with the following example involving the factorial function. .. rocqtop:: in reset Fixpoint fact (n : nat) : nat := match n with | 0 => 1 | S n' => n * fact n' end. Suppose now that, for whatever reason, we want in general to unfold the :g:`id` function very late during conversion: .. rocqtop:: in Strategy 1000 [id]. If we try to prove :g:`id (fact n) = fact n` by :tacn:`reflexivity`, it will now take time proportional to :math:`n!`, because Rocq will keep unfolding :g:`fact` and :g:`*` and :g:`+` before it unfolds :g:`id`, resulting in a full computation of :g:`fact n` (in unary, because we are using :g:`nat`), which takes time :math:`n!`. We can see this cross the relevant threshold at around :math:`n = 9`: .. rocqtop:: all abort Goal True. Time assert (id (fact 8) = fact 8) by reflexivity. Time assert (id (fact 9) = fact 9) by reflexivity. Note that behavior will be the same if you mark :g:`id` as :g:`Opaque` because while most reduction tactics refuse to unfold :g:`Opaque` constants, conversion treats :g:`Opaque` as merely a hint to unfold this constant last. We can get around this issue by using :tacn:`with_strategy`: .. rocqtop:: all Goal True. Fail Timeout 1 assert (id (fact 100) = fact 100) by reflexivity. Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] reflexivity. However, when we go to close the proof, we will run into trouble, because the reduction strategy changes are local to the tactic passed to :tacn:`with_strategy`. .. rocqtop:: all abort fail exact I. Timeout 1 Defined. We can fix this issue by using :tacn:`abstract`: .. rocqtop:: all Goal True. Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] abstract reflexivity. exact I. Time Defined. On small examples this sort of behavior doesn't matter, but because Rocq is a super-linear performance domain in so many places, unless great care is taken, tactic automation using :tacn:`with_strategy` may not be robustly performant when scaling the size of the input. .. warning:: In much the same way this tactic does not play well with :cmd:`Qed` and :cmd:`Defined` without using :tacn:`abstract` as an intermediary, this tactic does not play well with ``rocqchk``, even when used with :tacn:`abstract`, due to the inability of tactics to persist information about conversion hints in the proof term. See `#12200 `_ for more details. rocq-9.2.0/doc/sphinx/proofs/writing-proofs/index.rst000066400000000000000000000047731516144147600227320ustar00rootroot00000000000000.. _tactics: ============= Basic tactics ============= :term:`Tactics ` specify how to transform the :term:`proof state` of an incomplete proof to eventually generate a complete proof. This chapter introduces the basic tactics that are available in Rocq. An alternative set of tactics is provided by the SSReflect proof language, which is described in the :ref:`thessreflectprooflanguage` chapter. Additional tactics are documented in the :ref:`automatic-tactics` chapter. Proofs can be developed in two basic ways: In :gdef:`forward reasoning`, the proof begins by proving simple statements that are then combined to prove the theorem statement as the last step of the proof. With forward reasoning, for example, the proof of `A /\\ B` would begin with proofs of `A` and `B`, which are then used to prove `A /\\ B`. Forward reasoning is probably the most common approach in human-generated proofs. In :gdef:`backward reasoning`, the proof begins with the theorem statement as the goal, which is then gradually transformed until every subgoal generated along the way has been proven. In this case, the proof of `A /\\ B` begins with that formula as the goal. This can be transformed into two subgoals, `A` and `B`, followed by the proofs of `A` and `B`. Rocq and its tactics primarily use backward reasoning. A tactic may fully prove a goal, in which case the goal is removed from the proof state. More commonly, a tactic replaces a goal with one or more :term:`subgoals `. (We say that a tactic reduces a goal to its subgoals.) Most tactics require specific elements or preconditions to reduce a goal; they display error messages if they can't be applied to the goal. A few tactics, such as :tacn:`auto`, don't fail even if the proof state is unchanged. Goals are identified by number (and optionally given names). The current goal is number 1. Tactics are applied to the current goal by default. (The default can be changed with the :opt:`Default Goal Selector` option.) They can be applied to another goal or to multiple goals with a :ref:`goal selector ` such as :n:`2: @tactic`. This chapter describes many of the most common built-in tactics. Built-in tactics can be combined to form tactic expressions, which are described in the :ref:`Ltac` chapter. Since tactic expressions can be used anywhere that a built-in tactic can be used, "tactic" may refer to both built-in tactics and tactic expressions. .. toctree:: :maxdepth: 1 ../../proof-engine/tactics equality reasoning-inductives rocq-9.2.0/doc/sphinx/proofs/writing-proofs/proof-mode.rst000066400000000000000000001470071516144147600236700ustar00rootroot00000000000000.. _proofhandling: ---------- Proof mode ---------- The Rocq Prover is a proof assistant (or interactive theorem prover), which allows users to interactively construct proofs through a dialog with the assistant. The assistant ensures the validity of each step of the proof. :term:`Tactics `, which represent steps in the proof of a theorem, are the building blocks for this dialog. :gdef:`Proof mode ` is used to prove theorems. Rocq enters proof mode when you begin a proof, such as with the :cmd:`Theorem` command. It exits proof mode when you complete a proof, such as with the :cmd:`Qed` command. :term:`Tactics `, which are available only in proof mode, incrementally transform incomplete proofs to eventually generate a complete proof. When you run Rocq interactively, such as through RocqIDE, Proof General or `rocq repl`, Rocq shows the current proof state (the incomplete proof) as you enter tactics. This information isn't shown when you run Rocq in batch mode with `rocq compile`. Proof State ----------- The :gdef:`proof state` consists of one or more unproven goals. Each goal has a :gdef:`conclusion` (the statement that is to be proven) and a :gdef:`local context`, which contains named :term:`hypotheses ` (which are propositions), variables and local definitions that can be used in proving the conclusion. The proof may also use *constants* from the :term:`global environment` such as definitions and proven theorems. .. _conclusion_meaning_2: (Note that *conclusion* is also used to refer to the last part of an implication. For example, in `A -> B -> C`, `A` and `B` are :term:`premises ` and `C` is the conclusion.) The term ":gdef:`goal`" may refer to an entire goal or to the conclusion of a goal, depending on the context. The conclusion appears below a line and the local context appears above the line. The conclusion is a type. Each item in the local context begins with a name and ends, after a colon, with an associated type. :gdef:`Local definitions ` are shown in the form `n := 0 : nat`, for example, in which `nat` is the type of `0`. The local context of a goal contains items specific to the goal as well as section-local variables and hypotheses (see :ref:`gallina-assumptions`) defined in the current :ref:`section `. The latter are included in the initial proof state. Items in the local context are ordered; an item can only refer to items that appear before it. (A more mathematical description of the *local context* is :ref:`here `.) The :gdef:`global environment` has definitions and proven theorems that are global in scope. (A more mathematical description of the *global environment* is :ref:`here `.) When you begin proving a theorem, the proof state shows the statement of the theorem below the line and often nothing in the local context: .. rocqtop:: none Parameter P: nat -> Prop. .. rocqtop:: out Goal forall n m: nat, n > m -> P 1 /\ P 2. After applying the :tacn:`intros` :term:`tactic`, we see hypotheses above the line. The names of variables (`n` and `m`) and hypotheses (`H`) appear before a colon, followed by their type. The type doesn't have to be a provable statement. For example, `0 = 1` and `False` are both valid and useful types. .. rocqtop:: all intros. Some tactics, such as :tacn:`split`, create new goals, which may be referred to as :gdef:`subgoals ` for clarity. Goals are numbered from 1 to N at each step of the proof to permit applying a tactic to specific goals. The local context is only shown for the first goal. .. rocqtop:: all split. :gdef:`"Variables" ` may refer specifically to local context items introduced from :n:`forall` variables for which the type of their type is `Set` or `Type`. :gdef:`"Hypotheses" ` refers to items that are :term:`propositions `, for which the type of their type is `Prop` or `SProp`, but these terms are also used interchangeably. .. rocqtop:: out let t_n := type of n in idtac "type of n :" t_n; let tt_n := type of t_n in idtac "type of" t_n ":" tt_n. let t_H := type of H in idtac "type of H :" t_H; let tt_H := type of t_H in idtac "type of" t_H ":" tt_H. A proof script, consisting of the tactics that are applied to prove a theorem, is often informally referred to as a "proof". The real proof, whether complete or incomplete, is the associated term, the :gdef:`proof term`, which users may occasionally want to examine. (This is based on the *Curry-Howard isomorphism* :cite:`How80,Bar81,Gir89,H89`, which is a correspondence between proofs and terms and between :term:`propositions ` and types of Ξ»-calculus. The isomorphism is also sometimes called the "propositions-as-types correspondence".) The :cmd:`Show Proof` command displays the incomplete proof term before you've completed the proof. For example, here's the proof term after using the :tacn:`split` tactic above: .. rocqtop:: all Show Proof. The incomplete parts, the goals, are represented by :term:`existential variables ` with names that begin with `?Goal`. (Note that some existential variables are not goals.) The :cmd:`Show Existentials` command shows each existential with the hypotheses and conclusion for the associated goal. .. rocqtop:: all Show Existentials. Users can control which goals are displayed in the context by :term:`focusing ` goals. Focusing lets the user (initially) pick a single goal to work on. Focusing operations can be nested. Tactics such as :tacn:`eapply` create existential variables as placeholders for undetermined variables that become :term:`shelved ` goals. Shelved goals are not shown in the context by default, but they can be unshelved to make them visible. Other tactics may automatically resolve these goals (whether shelved or not); the purpose of shelving is to hide goals that the user usually doesn't need to think about. See :ref:`existential-variables` and :ref:`this example `. Rocq's kernel verifies the correctness of proof terms when it exits proof mode by checking that the proof term is :term:`well-typed` and that its type is the same as the theorem statement. After a proof is completed, :cmd:`Print` `` shows the proof term and its type. The type appears after the colon (`forall ...`), as for this theorem from Rocq's standard library: .. rocqtop:: all Print proj1. .. note:: Many tactics accept :n:`@term`\s as arguments and frequently refer to them with wording such as "the type of :token:`term`". When :n:`@term` is the name of a theorem or lemma, this wording refers to the type of the proof term, which is what's given in the :cmd:`Theorem` statement. When :n:`@term` is the name of a hypothesis, the wording refers to the type shown in the context for the hypothesis (i.e., after the colon). For terms that are more complex than just an :token:`ident`, you can use :cmd:`Check` :n:`@term` to display their type. .. _proof-editing-mode: Entering and exiting proof mode ------------------------------- Rocq enters :term:`proof mode` when you begin a proof through commands such as :cmd:`Theorem` or :cmd:`Goal`. Rocq user interfaces usually have a way to indicate that you're in proof mode. :term:`Tactics ` are available only in proof mode (currently they give syntax errors outside of proof mode). Most :term:`commands ` can be used both in and out of proof mode, but some commands only work in or outside of proof mode. When the proof is completed, you can exit proof mode with commands such as :cmd:`Qed`, :cmd:`Defined` and :cmd:`Save`. .. cmd:: Goal @type Asserts an unnamed proposition. This is intended for quick tests that a proposition is provable. If the proof is eventually completed and validated, you can assign a name with the :cmd:`Save` or :cmd:`Defined` commands. If no name is given, the name will be `Unnamed_thm` (or, if that name is already defined, a variant of that). .. cmd:: Qed Passes a completed :term:`proof term` to Rocq's kernel to check that the proof term is :term:`well-typed` and to verify that its type matches the theorem statement. If it's verified, the proof term is added to the global environment as an :term:`opaque` constant using the declared name from the original goal. It's very rare for a proof term to fail verification. Generally this indicates a bug in a tactic you used or that you misused some unsafe tactics. .. exn:: Attempt to save an incomplete proof. :undocumented: .. exn:: No focused proof (No proof-editing in progress). You tried to use a proof mode command such as :cmd:`Qed` outside of proof mode. .. note:: Sometimes an error occurs when building the proof term, because tactics do not enforce completely the term construction constraints. The user should also be aware of the fact that since the proof term is completely rechecked at this point, one may have to wait a while when the proof is large. In some exceptional cases one may even incur a memory overflow. .. cmd:: Save @ident Similar to :cmd:`Qed`, except that the proof term is added to the global context with the name :token:`ident`, which overrides any name provided by the :cmd:`Theorem` command or its variants. .. cmd:: Defined {? @ident } Similar to :cmd:`Qed` and :cmd:`Save`, except the proof is made :term:`transparent`, which means that its content can be explicitly used for type checking and that it can be unfolded in conversion tactics (see :ref:`applyingconversionrules`, :cmd:`Opaque`, :cmd:`Transparent`). If :token:`ident` is specified, the proof is defined with the given name, which overrides any name provided by the :cmd:`Theorem` command or its variants. .. cmd:: Admitted This command is available in proof mode to give up the current proof and declare the initial goal as an axiom. .. cmd:: Abort {? All } Aborts the current proof. If the current proof is a nested proof, the previous proof becomes current. If :n:`All` is given, all nested proofs are aborted. See :flag:`Nested Proofs Allowed`. :n:`All` Aborts all current proofs. .. cmd:: Proof @term :name: Proof `term` This command applies in proof mode. It is equivalent to :n:`exact @term. Qed.` That is, you have to give the full proof in one gulp, as a proof term (see Section :ref:`applyingtheorems`). .. warning:: Use of this command is discouraged. In particular, it doesn't work in Proof General because it must immediately follow the command that opened proof mode, but Proof General inserts :cmd:`Unset` :flag:`Silent` before it (see `Proof General issue #498 `_). .. cmd:: Proof Is a no-op which is useful to delimit the sequence of tactic commands which start a proof, after a :cmd:`Theorem` command. It is a good practice to use :cmd:`Proof` as an opening parenthesis, closed in the script with a closing :cmd:`Qed`. .. seealso:: :cmd:`Proof with` .. cmd:: Proof using @section_var_expr {? with @generic_tactic } .. insertprodn section_var_expr starred_ident_ref .. prodn:: section_var_expr ::= {* @starred_ident_ref } | {? - } @section_var_expr50 section_var_expr50 ::= @section_var_expr0 - @section_var_expr0 | @section_var_expr0 + @section_var_expr0 | @section_var_expr0 section_var_expr0 ::= @starred_ident_ref | () | ( @section_var_expr ) {? * } starred_ident_ref ::= @ident {? * } | Type {? * } | All Opens proof mode, declaring the set of :ref:`section ` variables (see :ref:`gallina-assumptions`) used by the proof. These :ref:`proof annotations ` are useful to enable asynchronous processing of proofs. This :ref:`example ` shows how they work. The :cmd:`Qed` command verifies that the set of section variables used in the proof is a subset of the declared ones. The set of declared variables is closed under type dependency. For example, if ``T`` is a variable and ``a`` is a variable of type ``T``, then the commands ``Proof using a`` and ``Proof using T a`` are equivalent. The set of declared variables always includes the variables used by the statement. In other words ``Proof using e`` is equivalent to ``Proof using Type + e`` for any declaration expression ``e``. :n:`- @section_var_expr50` Use all section variables except those specified by :n:`@section_var_expr50` :n:`@section_var_expr0 + @section_var_expr0` Use section variables from the union of both collections. See :ref:`nameaset` to see how to form a named collection. :n:`@section_var_expr0 - @section_var_expr0` Use section variables which are in the first collection but not in the second one. :n:`{? * }` Use the transitive closure of the specified collection. :n:`Type` Use only section variables occurring in the statement. Specifying :n:`*` uses the forward transitive closure of all the section variables occurring in the statement. For example, if the variable ``H`` has type ``p < 5`` then ``H`` is in ``p*`` since ``p`` occurs in the type of ``H``. :n:`All` Use all section variables. .. warn:: @ident is both name of a Collection and Variable, Collection @ident takes precedence over Variable. If a specified name is ambiguous (it could be either a :cmd:`Collection` or a :cmd:`Variable`), then it is assumed to be a :cmd:`Collection` name. .. warn:: Variable All is shadowed by Collection named All containing all variables. This is variant of the previous warning for the **All** collection. .. seealso:: :ref:`tactics-implicit-automation` .. attr:: using This :term:`attribute` can be applied to the :cmd:`Definition`, :cmd:`Example`, :cmd:`Fixpoint` and :cmd:`CoFixpoint` commands as well as to :cmd:`Lemma` and its variants. It takes a :n:`@section_var_expr`, in quotes, as its value. This is equivalent to specifying the same :n:`@section_var_expr` in :cmd:`Proof using`. .. example:: .. rocqtop:: all reset Section Test. Variable n : nat. Hypothesis Hn : n <> 0. #[using="Hn"] Lemma example : 0 < n. .. rocqtop:: in Abort. End Test. .. _example-print-using: .. example :: Declaring section variables When a :ref:`section ` is closed with :cmd:`End`, section variables declared with :cmd:`Proof using` are added to the theorem as additional variables. You can see the effect on the theorem's statement with commands such as :cmd:`Check`, :cmd:`Print` and :cmd:`About` after the section is closed. The :cmd:`Print` and :cmd:`About` commands also show the section variables associated with a theorem before the section is closed. Adding the unnecessary section variable `radixNotZero` changes how `foo'` can be applied. .. rocqtop:: in Section bar. Variable radix : nat. Hypothesis radixNotZero : 0 < radix. Lemma foo : 0 = 0. Proof. reflexivity. Qed. Lemma foo' : 0 = 0. Proof using radixNotZero. reflexivity. Qed. (* radixNotZero is not needed *) .. rocqtop:: all Print foo'. (* Doesn't show radixNotZero yet *) End bar. Print foo. (* Doesn't change after the End *) Print foo'. (* "End" added type radix (used by radixNotZero) and radixNotZero *) Goal 0 = 0. .. rocqtop:: in Fail apply foo'. (* Fails because of the extra variable *) .. rocqtop:: all apply (foo' 5). (* Can be used if the extra variable is provided explicitly *) .. rocqtop:: abort none Proof using options ``````````````````` The following options modify the behavior of ``Proof using``. .. opt:: Default Proof Using "@section_var_expr" Set this :term:`option` to use :n:`@section_var_expr` as the default ``Proof using`` value. E.g. ``Set Default Proof Using "a b"`` will complete all ``Proof`` commands not followed by a ``using`` part with ``using a b``. Note that :n:`@section_var_expr` isn't validated immediately. An invalid value will generate an error on a subsequent :cmd:`Proof` or :cmd:`Qed` command. .. flag:: Suggest Proof Using When this :term:`flag` is on, :cmd:`Qed` suggests a ``using`` annotation if the user did not provide one. .. flag:: Keep Admitted Variables When on, proofs terminated with :cmd:`Admitted` use the section variables from `Proof using` if one was provided (including through `Default Proof Using`), otherwise the variables used in the partial proof (including any variables visible from the still open goals). When off, only the section variables used in the type are used. On by default. .. _`nameaset`: Name a set of section hypotheses for ``Proof using`` ```````````````````````````````````````````````````` .. cmd:: Collection @ident := @section_var_expr This can be used to name a set of section hypotheses, with the purpose of making ``Proof using`` annotations more compact. .. example:: Define the collection named ``Some`` containing ``x``, ``y`` and ``z``:: Collection Some := x y z. Define the collection named ``Fewer`` containing only ``x`` and ``y``:: Collection Fewer := Some - z Define the collection named ``Many`` containing the set union or set difference of ``Fewer`` and ``Some``:: Collection Many := Fewer + Some Collection Many := Fewer - Some Define the collection named ``Many`` containing the set difference of ``Fewer`` and the unnamed collection ``x y``:: Collection Many := Fewer - (x y) .. deprecated:: 8.15 Redefining a collection, defining a collection with the same name as a variable, and invoking the :cmd:`Proof using` command when collection and variable names overlap are deprecated. See the warnings below and in the :cmd:`Proof using` command. .. exn:: "All" is a predefined collection containing all variables. It can't be redefined. :name: All is a predefined collection containing all variables. It can't be redefined. When issuing a :cmd:`Proof using` command, **All** used as a collection name always means "use all variables". .. warn:: New Collection definition of @ident shadows the previous one. Redefining a :cmd:`Collection` overwrites the previous definition. .. warn:: @ident was already a defined Variable, the name @ident will refer to Collection when executing "Proof using" command. The :cmd:`Proof using` command allows specifying both :cmd:`Collection` and :cmd:`Variable` names. In case of ambiguity, a name is assumed to be Collection name. Proof modes ----------- When entering proof mode through commands such as :cmd:`Goal` and :cmd:`Proof`, Rocq picks by default the |Ltac| mode. Nonetheless, there exist other proof modes shipped in the standard Rocq installation, and furthermore some plugins define their own proof modes. The default proof mode used when opening a proof can be changed using the following option. The default proof mode is also used for tactic arguments to commands through :n:`generic_tactic`. By default, .. insertprodn generic_tactic generic_tactic .. prodn:: generic_tactic ::= @ltac_expr .. opt:: Default Proof Mode @string This :term:`option` selects the proof mode to use when starting a proof. Depending on the proof mode, various syntactic constructs are allowed when writing a proof. All proof modes support commands; the proof mode determines which tactic language and set of tactic definitions are available. The possible option values are: `"Classic"` Activates the |Ltac| language and the tactics with the syntax documented in this manual. Some tactics are not available until the associated plugin is loaded, such as `SSR` or `micromega`. This proof mode is set when the :term:`prelude` is loaded. `"Noedit"` No tactic language is activated at all. This is the default when the :term:`prelude` is not loaded, e.g. through the `-noinit` option for `rocq`. `"Ltac2"` Activates the Ltac2 language and the Ltac2-specific variants of the documented tactics. This value is only available after :cmd:`Requiring ` Ltac2. :cmd:`Importing ` Ltac2 sets this mode. Some external plugins also define their own proof mode, which can be activated with this command. .. cmd:: Proof Mode @string Sets the proof mode within the current proof. Managing goals -------------- .. cmd:: Undo {? {? To } @natural } Cancels the effect of the last :token:`natural` commands or tactics. The :n:`To @natural` form goes back to the specified state number. If :token:`natural` is not specified, the command goes back one command or tactic. .. cmd:: Restart Restores the proof to the original goal. .. exn:: No focused proof to restart. :undocumented: .. _focused_goals: Focusing goals `````````````` :gdef:`Focusing ` lets you limit the context display to (initially) a single goal. If a tactic creates additional goals from a focused goal, the subgoals are also focused. The two focusing constructs are :ref:`curly braces ` (`{` and `}`) and :ref:`bullets ` (e.g. `-`, `+` or `*`). These constructs can be nested. .. _curly-braces: Curly braces ~~~~~~~~~~~~ .. tacn:: {? {| @natural | [ @qualid ] } : } %{ %} :name: {; } .. todo See https://github.com/rocq-prover/rocq/issues/12004 and https://github.com/rocq-prover/rocq/issues/12825. ``{`` (without a terminating period) focuses on the first goal. The subproof can only be unfocused when it has been fully solved (*i.e.*, when there is no focused goal left). Unfocusing is then handled by ``}`` (again, without a terminating period). See also an example in the next section. Note that when a focused goal is proved a message is displayed together with a suggestion about the right bullet or ``}`` to unfocus it or focus the next goal. :n:`@natural:` Focuses on the :token:`natural`\-th goal to prove. .. _focus_shelved_goal: :n:`[ @qualid ]: %{` Focuses on the goal named :token:`qualid` even if the goal is not in focus. Goals are :term:`existential variables `, which don't have names by default, unless you enable the :flag:`Generate Goal Names` flag. You can give a name to a goal by using :n:`refine ?[@ident]`. .. _example-working-with-named-goals: .. example:: Working with named goals .. rocqtop:: in Ltac name_goal name := refine ?[name]. (* for convenience *) .. rocqtop:: all Goal forall n, n + 0 = n. Proof. induction n; [ name_goal base | name_goal step ]. (* focus on the goal named "base" *) [base]: { reflexivity. .. rocqtop:: in } This can also be a way of focusing on a shelved goal, for instance: .. rocqtop:: all reset Goal exists n : nat, n = n. eexists ?[x]. reflexivity. [x]: exact 0. Qed. .. exn:: This proof is focused, but cannot be unfocused this way. You are trying to use ``}`` but the current subproof has not been fully solved. .. exn:: No such goal (@natural). :undocumented: .. exn:: No such goal (@qualid). :undocumented: .. exn:: Brackets do not support multi-goal selectors. Brackets are used to focus on a single goal given either by its position or by its name if it has one. .. seealso:: The error messages for bullets below. .. _bullets: Bullets ~~~~~~~ Alternatively, proofs can be structured with bullets instead of ``{`` and ``}``. The first use of a bullet ``b`` focuses on the first goal ``g``. The same bullet can't be used again until the proof of ``g`` is completed, then the next goal must be focused with another ``b``. Thus, all the goals present just before the first use of the bullet must be focused with the same bullet ``b``. See the example below. Different bullets can be used to nest levels. The scope of each bullet is limited to the enclosing ``{`` and ``}``, so bullets can be reused as further nesting levels provided they are delimited by curly braces. A :production:`bullet` is made from ``-``, ``+`` or ``*`` characters (with no spaces and no period afterward): .. tacn:: {| {+ - } | {+ + } | {+ * } } :undocumented: :name: bullet (- + *) When a focused goal is proved, Rocq displays a message suggesting use of ``}`` or the correct matching bullet to unfocus the goal or focus the next subgoal. .. note:: In Proof General (``Emacs`` interface to Rocq), you must use bullets with the priority ordering shown above to have correct indentation. For example ``-`` must be the outer bullet and ``+`` the inner one in the example below. .. example:: Use of bullets For the sake of brevity, the output for this example is summarized in comments. Note that the tactic following a bullet is frequently put on the same line with the bullet. Observe that this proof still works even if all the bullets in it are omitted. .. rocqtop:: in Goal (1=1 /\ 2=2) /\ 3=3. Proof. split. (* 1 = 1 /\ 2 = 2 and 3 = 3 *) - (* 1 = 1 /\ 2 = 2 *) split. (* 1 = 1 and 2 = 2 *) + (* 1 = 1 *) trivial. (* subproof complete *) + (* 2 = 2 *) trivial. (* subproof complete *) - (* 3 = 3 *) trivial. (* No more subgoals *) Qed. .. exn:: Wrong bullet @bullet__1: Current bullet @bullet__2 is not finished. Before using bullet :n:`@bullet__1` again, you should first finish proving the current focused goal. Note that :n:`@bullet__1` and :n:`@bullet__2` may be the same. .. exn:: Wrong bullet @bullet__1: Bullet @bullet__2 is mandatory here. You must put :n:`@bullet__2` to focus on the next goal. No other bullet is allowed here. .. exn:: No such goal. Focus next goal with bullet @bullet. You tried to apply a tactic but no goals were under focus. Using :n:`@bullet` is mandatory here. .. exn:: No such goal. Try unfocusing with %}. You just finished a goal focused by ``{``, you must unfocus it with ``}``. .. note:: Use :opt:`Default Goal Selector` with the ``!`` selector to force the use of focusing mechanisms (bullets, braces) and goal selectors so that it is always explicit to which goal(s) a tactic is applied. .. opt:: Bullet Behavior {| "None" | "Strict Subproofs" } This :term:`option` controls the bullet behavior and can take two possible values: - "None": this makes bullets inactive. - "Strict Subproofs": this makes bullets active (this is the default behavior). .. _named_goals: Named goals ~~~~~~~~~~~ You can focus on a goal by using its name. Goals do not have a name by default, but a name can be given by using :n:`refine ?[@ident]`, or generated using the :flag:`Generate Goal Names` flag. .. flag:: Generate Goal Names Enables automatic generation of goal names for the :tacn:`induction`, :tacn:`destruct` and :tacn:`eapply` tactics. For :tacn:`induction` and :tacn:`destruct`, the subgoal takes the name of the corresponding constructor. For :tacn:`eapply`, the subgoal takes the name of the corresponding hypothesis. This option makes it possible to write proofs with multiple subgoals that do not depend on the order in which constructors were defined, but instead rely on the constructor names. If you use bullets or numbers, reordering constructors will break the proof. For proofs that use nested :tacn:`induction` or case analysis, qualified names such as `true.false` are used to disambiguate subgoals (see an example :ref:`here `). .. example:: Automatic generation of goal names In the following example, names are generated for both the base case and the induction case (in constrast with the example given :ref:`here ` in which the user explicitly gives names using :tacn:`refine`). .. rocqtop:: in Set Generate Goal Names. Goal forall n, n + 0 = n. .. rocqtop:: all induction n. [O]: { (* O and S are the constructors for nat. *) reflexivity. .. rocqtop:: in abort } If a goal comes from an existential variable that failed to instantiate (e.g. when using :tacn:`eapply` or other `e*` tactics), the goal is named after the variable (below, `R` and `Rwf` are hypotheses of `well_founded_ind`): .. rocqtop:: none Inductive even : nat -> Prop := | even_zero : even 0 | even_succ : forall n, even n -> even (S (S n)). Inductive odd : nat -> Prop := | odd_one : odd 1 | odd_succ : forall n, odd n -> odd (S (S n)). .. rocqtop:: in Goal forall n : nat, even n \/ odd n. .. rocqtop:: all abort eapply well_founded_ind. [R]: exact lt. .. _qualified-goal-names: .. example:: Qualified goal names When doing nested case analysis or induction, qualified names are used to disambiguate subgoals. Subgoal names are prefixed by the names of parent goals. .. rocqtop:: in Set Generate Goal Names. Goal forall n m : nat, n + m = m + n. intros. induction m; simpl. [O]: { induction n. [O.O]: reflexivity. [O.S]: { simpl. congruence. } } [S]: { induction n. [S.O]: { rewrite <- IHm. reflexivity. } [S.S]: { rewrite <- IHm. auto. } } Qed. Other focusing commands ~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Unfocused Succeeds if there are no unfocused goals. Otherwise the command fails. .. cmd:: Focus {? @natural } Focuses the attention on the first goal to prove or, if :token:`natural` is specified, the :token:`natural`\-th. The printing of the other goals is suspended until the focused goal is solved or unfocused. .. deprecated:: 8.8 Prefer the use of bullets or focusing braces with a goal selector (see above). .. cmd:: Unfocus Restores to focus the goals that were suspended by the last :cmd:`Focus` command. .. deprecated:: 8.8 .. _shelved_goals: Shelving goals `````````````` Goals can be :gdef:`shelved` so they are no longer displayed in the proof state. Shelved goals can be unshelved with the :cmd:`Unshelve` command, which makes all shelved goals visible in the proof state. You can use the goal selector :n:`[ @qualid ]: %{` to focus on a single shelved goal (see :ref:`here `). Currently there's no single command or tactic that unshelves goals by name. .. tacn:: shelve Moves the focused goals to the shelf. They will no longer be displayed in the context. The :cmd:`Show Existentials` command will still show these goals, which will be marked "(shelved)". .. tacn:: shelve_unifiable Shelves only the goals under focus that are mentioned in other goals. Goals that appear in the type of other goals can be solved by unification. .. example:: shelve_unifiable .. rocqtop:: all abort Goal exists n, n=0. refine (ex_intro _ _ _). all: shelve_unifiable. reflexivity. .. cmd:: Unshelve This command moves all the goals on the shelf (see :tacn:`shelve`) from the shelf into focus, by appending them to the end of the current list of focused goals. .. tacn:: unshelve @ltac_expr1 Performs :n:`@tactic`, then unshelves existential variables added to the shelf by the execution of :n:`@tactic`, prepending them to the current goal. .. tacn:: admit give_up Allows skipping a subgoal to permit further progress on the rest of the proof. The selected goals are removed from the context. They are not solved and cannot be solved later in the proof. Since the goals are not solved, the proof cannot be closed with :cmd:`Qed` but only with :cmd:`Admitted`. Reordering goals ```````````````` .. tacn:: cycle @int_or_var Reorders the selected goals so that the first :n:`@integer` goals appear after the other selected goals. If :n:`@integer` is negative, it puts the last :n:`@integer` goals at the beginning of the list. The tactic is only useful with a goal selector, most commonly `all:`. Note that other selectors reorder goals; `1,3: cycle 1` is not equivalent to `all: cycle 1`. See :tacn:`… : … (goal selector)`. .. example:: cycle .. rocqtop:: none reset Parameter P : nat -> Prop. .. rocqtop:: in abort Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5. repeat split. (* P 1, P 2, P 3, P 4, P 5 *) all: cycle 2. (* P 3, P 4, P 5, P 1, P 2 *) all: cycle -3. (* P 5, P 1, P 2, P 3, P 4 *) .. tacn:: swap @int_or_var @int_or_var Exchanges the position of the specified goals. Negative values for :n:`@integer` indicate counting goals backward from the end of the list of selected goals. Goals are indexed from 1. The tactic is only useful with a goal selector, most commonly `all:`. Note that other selectors reorder goals; `1,3: swap 1 3` is not equivalent to `all: swap 1 3`. See :tacn:`… : … (goal selector)`. .. example:: swap .. rocqtop:: in abort Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5. repeat split. (* P 1, P 2, P 3, P 4, P 5 *) all: swap 1 3. (* P 3, P 2, P 1, P 4, P 5 *) all: swap 1 -1. (* P 5, P 2, P 1, P 4, P 3 *) .. tacn:: revgoals Reverses the order of the selected goals. The tactic is only useful with a goal selector, most commonly `all :`. Note that other selectors reorder goals; `1,3: revgoals` is not equivalent to `all: revgoals`. See :tacn:`… : … (goal selector)`. .. example:: revgoals .. rocqtop:: in abort Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5. repeat split. (* P 1, P 2, P 3, P 4, P 5 *) all: revgoals. (* P 5, P 4, P 3, P 2, P 1 *) Proving a subgoal as a separate lemma: abstract ----------------------------------------------- .. tacn:: abstract @ltac_expr2 {? using @ident__name } Does a :tacn:`solve` :n:`[ @ltac_expr2 ]` and saves the subproof as an auxiliary lemma. if :n:`@ident__name` is specified, the lemma is saved with that name; otherwise the lemma is saved with the name :n:`@ident`\ `_subproof`\ :n:`{? @natural }` where :token:`ident` is the name of the current goal (e.g. the theorem name) and :token:`natural` is chosen to get a fresh name. If the proof is closed with :cmd:`Qed`, the auxiliary lemma is inlined in the final proof term. This is useful with tactics such as :tacn:`discriminate` that generate huge proof terms with many intermediate goals. It can significantly reduce peak memory use. In most cases it doesn't have a significant impact on run time. One case in which it can reduce run time is when a tactic `foo` is known to always pass type checking when it succeeds, such as in reflective proofs. In this case, the idiom ":tacn:`abstract` :tacn:`exact_no_check` `foo`" will save half the type checking type time compared to ":tacn:`exact` `foo`". :tacn:`abstract` is an :token:`l3_tactic`. .. warning:: The abstract tactic, while very useful, still has some known limitations. See `#9146 `_ for more details. We recommend caution when using it in some "non-standard" contexts. In particular, ``abstract`` doesn't work properly when used inside quotations ``ltac:(...)``. If used as part of typeclass resolution, it may produce incorrect terms when in polymorphic universe mode. .. warning:: There are no guarantees with fresh name generation. In particular, you should not rely on the generated constant being available in your proof script. Even when providing an explicit :n:`@ident__name`, do it at your own risk. Explicitly named and reused subterms don't play well with asynchronous proofs. Furthermore the binding is only made available when exiting the current tactic block, i.e. after a dot. The only guarantee with explicit naming is that the subproof will be accessible with this name after the :cmd:`Defined` command. .. tacn:: transparent_abstract @ltac_expr3 {? using @ident } Like :tacn:`abstract`, but save the subproof in a transparent lemma with a name in the form :n:`@ident`\ :n:`_subterm`\ :n:`{? @natural }`. .. warning:: Use this feature at your own risk; building computationally relevant terms with tactics is fragile, and explicitly named and reused subterms don’t play well with asynchronous proofs. .. exn:: Proof is not complete. :name: Proof is not complete. (abstract) :undocumented: .. _requestinginformation: Requesting information ---------------------- .. cmd:: Show {? {| @qualid | @natural } } Displays the current goals. If enabled, diffs are shown in emacs (via rocqtop) for :n:`Show` and :n:`Show @natural`. Use :cmd:`Show Diffs` in emacs to see diffs for :n:`Show @ident`. Diffs are not currently displayed in other IDEs. :n:`@natural` Display only the :token:`natural`\-th goal. :n:`@qualid` Displays the named goal :token:`qualid`. This is useful in particular to display a shelved goal but only works if the corresponding existential variable has been named by the user (see :ref:`existential-variables`) as in the following example. .. example:: .. rocqtop:: all abort Goal exists n, n = 0. eexists ?[n]. Show n. .. exn:: No focused proof. :undocumented: .. exn:: No such goal. :undocumented: .. cmd:: Show Diffs @ident For use by emacs. If :opt:`Diffs` is enabled, displays :n:`Show @ident` with proof diffs. .. cmd:: Show Proof {? Diffs {? removed } } Displays the proof term generated by the tactics that have been applied so far. If the proof is incomplete, the term will contain holes, which correspond to subterms which are still to be constructed. Each hole is an existential variable, which appears as a question mark followed by an identifier. Specifying β€œDiffs” highlights the difference between the current and previous proof step. By default, the command shows the output once with additions highlighted. Including β€œremoved” shows the output twice: once showing removals and once showing additions. It does not examine the :opt:`Diffs` option. See :ref:`showing_proof_diffs`. .. cmd:: Show Conjectures Prints the names of all the theorems that are currently being proved. As it is possible to start proving a previous lemma during the proof of a theorem, there may be multiple names. .. cmd:: Show Intro If the current goal begins by at least one product, prints the name of the first product as it would be generated by an anonymous :tacn:`intro`. The aim of this command is to ease the writing of more robust scripts. For example, with an appropriate Proof General macro, it is possible to transform any anonymous :tacn:`intro` into a qualified one such as ``intro y13``. In the case of a non-product goal, it prints nothing. .. cmd:: Show Intros Similar to the previous command. Simulates the naming process of :tacn:`intros`. .. cmd:: Show Existentials Displays all open goals / existential variables in the current proof along with the context and type of each variable. .. cmd:: Show Match @qualid Displays a template of the Gallina :token:`match` construct with a branch for each constructor of the type :token:`qualid`. This is used internally by `company-coq `_. .. example:: .. rocqtop:: all Show Match nat. .. exn:: Unknown inductive type. :undocumented: .. cmd:: Show Universes Displays the set of all universe constraints and its normalized form at the current stage of the proof, useful for debugging universe inconsistencies. .. cmd:: Show Goal @natural at @natural Available in `rocq repl`. Displays a goal at a proof state using the goal ID number and the proof state ID number. It is primarily for use by tools such as Prooftree that need to fetch goal history in this way. Prooftree is a tool for visualizing a proof as a tree that runs in Proof General. .. cmd:: Guarded Some tactics (e.g. :tacn:`refine`) allow to build proofs using fixpoint or cofixpoint constructions. Due to the incremental nature of proof construction, the check of the termination (or guardedness) of the recursive calls in the fixpoint or cofixpoint constructions is postponed to the time of the completion of the proof. The command :cmd:`Guarded` allows checking if the guard condition for fixpoint and cofixpoint is violated at some time of the construction of the proof without having to wait the completion of the proof. .. cmd:: Validate Proof Checks that the current partial proof is well-typed. It is useful for finding tactic bugs since without it, such errors will only be detected at :cmd:`Qed` time. It does not check the guard condition. Use :cmd:`Guarded` for that. .. _showing_diffs: Showing differences between proof steps --------------------------------------- Rocq can automatically highlight the differences between successive proof steps and between values in some error messages. Rocq can also highlight differences in the proof term. For example, the following screenshots of RocqIDE and coqtop show the application of the same :tacn:`intros` tactic. The tactic creates two new hypotheses, highlighted in green. The conclusion is entirely in pale green because although it’s changed, no tokens were added to it. The second screenshot uses the "removed" option, so it shows the conclusion a second time with the old text, with deletions marked in red. Also, since the hypotheses are new, no line of old text is shown for them. .. comment screenshot produced with: Inductive ev : nat -> Prop := | ev_0 : ev 0 | ev_SS : forall n : nat, ev n -> ev (S (S n)). Fixpoint double (n:nat) := match n with | O => O | S n' => S (S (double n')) end. Goal forall n, ev n -> exists k, n = double k. intros n E. .. .. image:: ../../_static/diffs-rocqide-on.png :alt: RocqIDE with Set Diffs on .. .. image:: ../../_static/diffs-rocqide-removed.png :alt: RocqIDE with Set Diffs removed .. .. image:: ../../_static/diffs-coqtop-on3.png :alt: coqtop with Set Diffs on This image shows an error message with diff highlighting in RocqIDE: .. .. image:: ../../_static/diffs-error-message.png :alt: RocqIDE error message with diffs How to enable diffs ``````````````````` .. opt:: Diffs {| "on" | "off" | "removed" } This :term:`option` is used to enable diffs. The β€œon” setting highlights added tokens in green, while the β€œremoved” setting additionally reprints items with removed tokens in red. Unchanged tokens in modified items are shown with pale green or red. Diffs in error messages use red and green for the compared values; they appear regardless of the setting. (Colors are user-configurable.) For `rocq repl`, showing diffs can be enabled when starting `rocq repl` with the ``-diffs on|off|removed`` command-line option or by setting the :opt:`Diffs` option within Rocq. You will need to provide the ``-color on|auto`` command-line option when you start `rocq repl` in either case. Colors for `rocq repl` can be configured by setting the ``ROCQ_COLORS`` environment variable. See section :ref:`customization-by-environment-variables`. Diffs use the tags ``diff.added``, ``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg``. In RocqIDE, diffs should be enabled from the ``View`` menu. Don’t use the ``Set Diffs`` command in RocqIDE. You can change the background colors shown for diffs from the ``Edit | Preferences | Tags`` panel by changing the settings for the ``diff.added``, ``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg`` tags. This panel also lets you control other attributes of the highlights, such as the foreground color, bold, italic, underline and strikeout. Proof General, VsCoq and Coqtail can also display Rocq-generated proof diffs automatically. Please see the PG documentation section `"Showing Proof Diffs" `_ and Coqtail's `"Proof Diffs" `_ for details. How diffs are calculated ```````````````````````` Diffs are calculated as follows: 1. Select the old proof state to compare to, which is the proof state before the last tactic that changed the proof. Changes that only affect the view of the proof, such as ``all: swap 1 2``, are ignored. 2. For each goal in the new proof state, determine what old goal to compare it toβ€”the one it is derived from or is the same as. Match the hypotheses by name (order is ignored), handling compacted items specially. 3. For each hypothesis and conclusion (the β€œitems”) in each goal, pass them as strings to the lexer to break them into tokens. Then apply the Myers diff algorithm :cite:`Myers` on the tokens and add appropriate highlighting. Notes: * Aside from the highlights, output for the "on" option should be identical to the undiffed output. * Goals completed in the last proof step will not be shown even with the "removed" setting. .. comment The following screenshots show diffs working with multiple goals and with compacted hypotheses. In the first one, notice that the goal ``P 1`` is not highlighted at all after the split because it has not changed. .. todo: Use this script and remove the screenshots when ROCQ_COLORS works for coqtop in sphinx .. rocqtop:: none Set Diffs "on". Parameter P : nat -> Prop. Goal P 1 /\ P 2 /\ P 3. .. rocqtop:: out split. .. rocqtop:: all abort 2: split. .. .. rocqtop:: none Set Diffs "on". Goal forall n m : nat, n + m = m + n. Set Diffs "on". .. rocqtop:: out intros n. .. rocqtop:: all abort intros m. This screenshot shows the result of applying a :tacn:`split` tactic that replaces one goal with 2 goals. Notice that the goal ``P 1`` is not highlighted at all after the split because it has not changed. .. .. image:: ../../_static/diffs-rocqide-multigoal.png :alt: rocqide with Set Diffs on with multiple goals Diffs may appear like this after applying a :tacn:`intro` tactic that results in a compacted hypotheses: .. .. image:: ../../_static/diffs-rocqide-compacted.png :alt: rocqide with Set Diffs on with compacted hypotheses .. _showing_proof_diffs: "Show Proof" differences ```````````````````````` To show differences in the proof term: - In `rocq repl` and Proof General, use the :cmd:`Show Proof` `Diffs` command. - In RocqIDE, position the cursor on or just after a tactic to compare the proof term after the tactic with the proof term before the tactic, then select `View / Show Proof` from the menu or enter the associated key binding. Differences will be shown applying the current `Show Diffs` setting from the `View` menu. If the current setting is `Don't show diffs`, diffs will not be shown. Output with the "added and removed" option looks like this: .. .. image:: ../../_static/diffs-show-proof.png :alt: rocqide with Set Diffs on with compacted hypotheses Delaying solving unification constraints ---------------------------------------- .. tacn:: solve_constraints :undocumented: .. flag:: Solve Unification Constraints By default, after each tactic application, postponed typechecking unification problems are resolved using heuristics. Unsetting this :term:`flag` disables this behavior, allowing tactics to leave unification constraints unsolved. Use the :tacn:`solve_constraints` tactic at any point to solve the constraints. .. _proof-maintenance: Proof maintenance ----------------- *Experimental.* Many tactics, such as :tacn:`intros`, can automatically generate names, such as "H0" or "H1" for a new hypothesis introduced from a goal. Subsequent proof steps may explicitly refer to these names. However, future versions of Rocq may not assign names exactly the same way, which could cause the proof to fail because the new names don't match the explicit references in the proof. The following :flag:`Mangle Names` settings let users find all the places where proofs rely on automatically generated names, which can then be named explicitly to avoid any incompatibility. These settings cause Rocq to generate different names, producing errors for references to automatically generated names. .. flag:: Mangle Names When this :term:`flag` is set (it is off by default), generated names use the prefix specified in the following option instead of the default prefix. .. opt:: Mangle Names Prefix @string This :term:`option` specifies the prefix to use when generating names. .. flag:: Mangle Names Light When this :term:`flag` is set (it is off by default), the names generated by :flag:`Mangle Names` only add the :opt:`Mangle Names Prefix` to the original name. Controlling proof mode ---------------------- .. opt:: Hyps Limit @natural This :term:`option` controls the maximum number of hypotheses displayed in goals after the application of a tactic. All the hypotheses remain usable in the proof development. When unset, it goes back to the default mode which is to print all available hypotheses. .. flag:: Nested Proofs Allowed When turned on (it is off by default), this :term:`flag` enables support for nested proofs: a new assertion command can be inserted before the current proof is finished, in which case Rocq will temporarily switch to the proof of this *nested lemma*. When the proof of the nested lemma is finished (with :cmd:`Qed` or :cmd:`Defined`), its statement will be made available (as if it had been proved before starting the previous proof) and Rocq will switch back to the proof of the previous assertion. .. flag:: Printing Goal Names When this :term:`flag` is turned on, the name of the goal is printed in proof mode, which can be useful in cases of cross references between goals. .. flag:: Printing Goal Tags Internal flag used to implement Proof General's proof-tree mode. Controlling memory usage ------------------------ .. cmd:: Print Debug GC Prints heap usage statistics, which are values from the `stat` type of the `Gc` module described `here `_ in the OCaml documentation. The `live_words`, `heap_words` and `top_heap_words` values give the basic information. Words are 8 bytes or 4 bytes, respectively, for 64- and 32-bit executables. When experiencing high memory usage the following commands can be used to force Rocq to optimize some of its internal data structures. .. cmd:: Optimize Proof Shrink the data structure used to represent the current proof. .. cmd:: Optimize Heap Perform a heap compaction. This is generally an expensive operation. See: `OCaml Gc.compact `_ There is also an analogous tactic :tacn:`optimize_heap`. Memory usage parameters can be set through the :ref:`OCAMLRUNPARAM ` environment variable. rocq-9.2.0/doc/sphinx/proofs/writing-proofs/reasoning-inductives.rst000066400000000000000000002137361516144147600257640ustar00rootroot00000000000000============================== Reasoning with inductive types ============================== Applying constructors --------------------- The tactics presented here specialize :tacn:`apply` and :tacn:`eapply` to constructors of inductive types. .. tacn:: constructor {? @nat_or_var } {? with @bindings } First does :n:`repeat intro; hnf` on the goal. If the result is an inductive type :g:`I`, then apply the appropriate constructor(s), and otherwise fail. If :n:`@nat_or_var` is specified and has the value `i`, it uses :n:`apply c__i`, where :n:`c__i` is the i-th constructor of :g:`I`. If not specified, the tactic tries all the constructors, which can result in more than one success (e.g. for `\\/`) when using backtracking tactics such as `constructor; ...`. See :tacn:`ltac-seq`. :n:`{? with @bindings }` If specified, the :n:`apply` is done as :n:`apply … with @bindings`. .. warning:: The terms in :token:`bindings` are checked in the context where constructor is executed and not in the context where :tacn:`apply` is executed (the introductions are not taken into account). .. exn:: Not an inductive product. :undocumented: .. exn:: Not enough constructors. :undocumented: .. exn:: The type has no constructors. :undocumented: .. tacn:: split {? with @bindings } Equivalent to :n:`constructor 1 {? with @bindings }` when the conclusion is an inductive type with a single constructor. The :n:`@bindings` specify any parameters required for the constructor. It is typically used to split conjunctions in the conclusion such as `A /\\ B` into two new goals `A` and `B`. To :n:`split` a hypothesis :n:`H` that begins with :n:`and`, use :tacn:`destruct` :n:`H`. See :ref:`example `. .. tacn:: exists {*, @bindings } Equivalent to :n:`constructor 1 with @bindings__i` for each set of bindings (or just :n:`constructor 1` if there are no :n:`@bindings`) when the conclusion is an inductive type with a single constructor. It is typically used on existential quantifications in the form `exists x, P x.` .. exn:: Not an inductive goal with 1 constructor. :undocumented: .. tacn:: left {? with @bindings } right {? with @bindings } These tactics apply only if :g:`I` has two constructors, for instance in the case of a disjunction `A \\/ B`. Then they are respectively equivalent to :n:`constructor 1 {? with @bindings }` and :n:`constructor 2 {? with @bindings }`. .. exn:: Not an inductive goal with 2 constructors. :undocumented: .. tacn:: econstructor {? @nat_or_var {? with @bindings } } eexists {*, @bindings } esplit {? with @bindings } eleft {? with @bindings } eright {? with @bindings } These tactics behave like :tacn:`constructor`, :tacn:`exists`, :tacn:`split`, :tacn:`left` and :tacn:`right`, but they introduce existential variables instead of failing when a variable can't be instantiated (cf. :tacn:`eapply` and :tacn:`apply`). .. example:: :tacn:`constructor`, :tacn:`left` and :tacn:`right` .. rocqtop:: reset all Print or. (* or, represented by \/, has two constructors, or_introl and or_intror *) Goal forall P1 P2 : Prop, P1 -> P1 \/ P2. constructor 1. (* equivalent to "left" *) apply H. (* success *) In contrast, we won't be able to complete the proof if we select constructor 2: .. rocqtop:: reset none Goal forall P1 P2 : Prop, P1 -> P1 \/ P2. .. rocqtop:: all constructor 2. (* equivalent to "right" *) You can also apply a constructor by name: .. rocqtop:: reset none Goal forall P1 P2 : Prop, P1 -> P1 \/ P2. .. rocqtop:: all intros; apply or_introl. (* equivalent to "left" *) .. _CaseAnalysisAndInduction: Case analysis ------------- The tactics in this section implement case analysis on inductive or coinductive objects (see :ref:`variants`). .. comment Notes contrasting the various case analysis tactics: https://github.com/rocq-prover/rocq/pull/14676#discussion_r697904963 .. tacn:: destruct {+, @induction_clause } {? @induction_principle } .. insertprodn induction_clause induction_arg .. prodn:: induction_clause ::= @induction_arg {? as @or_and_intropattern } {? eqn : @naming_intropattern } {? @occurrences } induction_arg ::= @one_term_with_bindings | @natural Performs case analysis by generating a subgoal for each constructor of the inductive or coinductive type selected by :n:`@induction_arg`. The selected subterm, after possibly doing an :tacn:`intros`, must have an inductive or coinductive type. Unlike :tacn:`induction`, :n:`destruct` generates no induction hypothesis (see :n:`induction` :ref:`example `). In each new subgoal, the tactic replaces the selected subterm with the associated constructor applied to its arguments, if any. Applying :n:`destruct` to a hypothesis beginning with :n:`and` such as :n:`A /\ B` or :n:`A <-> B` splits the hypothesis into multiple hypotheses without creating new subgoals. Example :ref:`here `. :n:`{+, @induction_clause }` Giving multiple :n:`@induction_clause`\s is equivalent to applying :n:`destruct` serially on each :n:`@induction_clause`. :n:`@induction_arg` + If :n:`@one_term` (in :n:`@one_term_with_bindings`) is an identifier :n:`@ident`: + If :n:`@ident` denotes a :n:`forall` variable in the goal, then :n:`destruct @ident` behaves like :tacn:`intros` :n:`until @ident; destruct @ident`. + If :n:`@ident` is not referenced directly or indirectly in the goal or unselected hypotheses after application of :n:`destruct`, it is erased (unless it is a section variable). To avoid erasure, parenthesize the argument to make it a :n:`@term` rather than an :n:`@ident`, as in :n:`destruct (@ident)`. + :n:`@one_term` may contain holes that are denoted by β€œ_”. In this case, the tactic selects the first subterm that matches the pattern and performs case analysis using that subterm. + If :n:`@induction_arg` is a :n:`@natural`, then :n:`destruct @natural` behaves like :n:`intros until @natural` followed by :n:`destruct` applied to the last introduced :term:`premise`. :n:`as @or_and_intropattern` Provides names for (or applies further transformations to) the variables and hypotheses introduced in each new subgoal. The :token:`or_and_intropattern` must have one :n:`{* @intropattern }` for each constructor, given in the order in which the constructors are defined. If there are not enough names, Rocq picks fresh names. Inner :n:`intropattern`\s can also split introduced hypotheses into multiple hypotheses or subgoals. :n:`eqn : @naming_intropattern` Generates a new hypothesis in each new subgoal that is an equality between the term being case-analyzed and the associated constructor (applied to its arguments). The name of the new item may be specified in the :n:`@naming_intropattern`. :n:`with @bindings` (in :n:`@one_term_with_bindings`) Provides explicit instances for the :term:`dependent premises ` of the type of :token:`one_term`. :n:`@occurrences` Selects specific subterms of the goal and/or hypotheses to apply the tactic to. See :ref:`Occurrence clauses `. If it occurs in the :n:`@induction_principle`, then there can only be one :n:`@induction_clause`, which can't have its own :n:`@occurrences` clause. :n:`@induction_principle` Makes the tactic equivalent to :tacn:`induction` :n:`{+, @induction_clause } @induction_principle`. .. example:: Using :tacn:`destruct` Creates a subgoal for each constructor, substituting the constructor into the hypotheses and conclusion. .. rocqtop:: reset none Goal forall m n: nat, n = n -> m + n = n + m. .. rocqtop:: out intros. .. rocqtop:: all destruct n. 2: { (* no induction hypothesis created *) .. _example_create_induction_hyp: .. example:: :tacn:`induction` creating an induction hypotheses Like :n:`destruct`, creates a subgoal for each constructor, substituting the constructor into the hypotheses and conclusion. In addition, :n:`induction` creates induction hypotheses in appropriate subgoals (compare to the previous example). .. rocqtop:: reset none Goal forall m n: nat, n = n -> m + n = n + m. .. rocqtop:: out intros. .. rocqtop:: all induction n. 2: { (* IHn is the induction hypothesis *) .. _example_split_hypothesis: .. example:: Using :tacn:`destruct` on a hypothesis beginning with :n:`and` .. rocqtop:: reset none Goal forall A B: Prop, A /\ B -> True. .. rocqtop:: out intros. .. rocqtop:: all destruct H. .. _example_destruct_ind_concl: .. example:: Using :tacn:`destruct` on an argument with premises .. rocqtop:: reset in Parameter A B C D : Prop. .. rocqtop:: all Goal (A -> B \/ C) -> D. intros until 1. destruct H. Show 2. Show 3. The single tactic :n:`destruct 1` is equivalent to the :tacn:`intros` and :tacn:`destruct` used here. .. tacn:: edestruct {+, @induction_clause } {? @induction_principle } If the type of :n:`@one_term` (in :n:`@induction_arg`) has :term:`dependent premises ` whose values can't be inferred from the :n:`with @bindings` clause, :n:`edestruct` turns them into existential variables to be resolved later on. .. tacn:: case {+, @induction_clause } {? @induction_principle } An older, more basic tactic to perform case analysis without recursion. We recommend using :tacn:`destruct` instead where possible. `case` only modifies the goal; it does not modify the :term:`local context`. .. tacn:: ecase {+, @induction_clause } {? @induction_principle } If the type of :n:`@one_term` (in :n:`@induction_arg`) has :term:`dependent premises ` whose values can't be inferred from the :n:`with @bindings` clause, :n:`ecase` turns them into existential variables to be resolved later on. .. tacn:: case_eq @one_term A variant of the :n:`case` tactic that allows performing case analysis on a term without completely forgetting its original form. This is done by generating equalities between the original form of the term and the outcomes of the case analysis. We recommend using the :tacn:`destruct` tactic with an `eqn:` clause instead. .. tacn:: simple destruct {| @ident | @natural } Equivalent to :tacn:`intros` :n:`until {| @ident | @natural }; case @ident` where :n:`@ident` is a :n:`forall` variable in the goal and otherwise fails. .. tacn:: dependent destruction @ident {? generalizing {+ @ident } } {? using @one_term } :undocumented: .. note:: This tactic requires the Stdlib library. There is a long example of :tacn:`dependent destruction` and an explanation of the underlying technique :ref:`here `. .. tacn:: decompose [ {+ @one_term } ] @one_term Recursively decomposes a complex proposition in order to obtain atomic ones. .. example:: .. rocqtop:: reset all Goal forall A B C:Prop, A /\ B /\ C \/ B /\ C \/ C /\ A -> C. intros A B C H; decompose [and or] H. all: assumption. Qed. .. note:: :tacn:`decompose` does not work on right-hand sides of implications or products. .. tacn:: decompose sum @one_term This decomposes sum types (like :g:`or`). .. tacn:: decompose record @one_term This decomposes record types (inductive types with one constructor, like :g:`and` and :g:`exists` and those defined with the :cmd:`Record` command. Induction --------- .. tacn:: induction {+, @induction_clause } {? @induction_principle } .. insertprodn induction_principle induction_principle .. prodn:: induction_principle ::= using @one_term_with_bindings {? @occurrences } Applies an :term:`induction principle` to generate a subgoal for each constructor of an inductive type. If the argument is :term:`dependent ` in the conclusion or some hypotheses of the goal, the argument is replaced by the appropriate constructor in each of the resulting subgoals and induction hypotheses are added to the local context using names whose prefix is **IH**. The tactic is similar to :tacn:`destruct`, except that `destruct` doesn't generate induction hypotheses. :n:`induction` and :tacn:`destruct` are very similar. Aside from the following differences, please refer to the description of :tacn:`destruct` while mentally substituting :n:`induction` for :tacn:`destruct`. :n:`{+, @induction_clause }` If no :n:`@induction_principle` clause is provided, this is equivalent to doing :n:`induction` on the first :n:`@induction_clause` followed by :n:`destruct` on any subsequent clauses. :n:`@induction_principle` :n:`@one_term` specifies which :term:`induction principle` to use. The optional :n:`with @bindings` gives any values that must be substituted into the induction principle. The number of :n:`@bindings` must be the same as the number of parameters of the induction principle. If unspecified, the tactic finds the appropriate :term:`induction principle` using the "scheme" registration. The scheme kind depends on the sort of the goal: `sind` for `SProp`, `ind` for `Prop`, `rec` for `Set` and `rect` for `Type`. It also has a `_dep` or `_nodep` suffix indicating whether it is dependent in the eliminated value (i.e. in :cmd:`Scheme`, `Induction` is `_dep` and `Minimality` is `_nodep`). When both `_dep` and `_nodep` schemes are registered for the eliminated inductive and goal sort, the `_dep` scheme is used unless the inductive type was explicitly declared in `Prop`. Automatically generated schemes and schemes produced by :cmd:`Scheme` are automatically registered. Constants may also be registered using :cmd:`Register Scheme`, e.g. `Register Scheme my_foo_elim as rect_dep for foo` where `my_foo_elim` is a dependent elimination scheme for inductive `foo` at sort `Type`. If no scheme is registered for the eliminated inductive and goal sort, :tacn:`induction` attempts to find a constant from the same module as the inductive whose name is the inductive's name suffixed by `sind` / `ind` / `rec` / `rect`. This name-based lookup is deprecated. .. exn:: Cannot recognize a statement based on @reference. The type of the :n:`@induction_arg` (in an :n:`@induction_clause`) must reduce to the :n:`@reference` which was inferred as the type the induction principle operates on. Note that it is not enough to be convertible, but you can work around that with :tacn:`change`: .. rocqtop:: reset all Definition N := nat. Axiom strong : forall P, (forall n:N, (forall m:N, m < n -> P m) -> P n) -> forall n, P n. Axiom P : N -> Prop. Goal forall n:nat, P n. intros. Fail induction n using strong. change N in n. (* n is now of type N, matching the inferred type that strong operates on *) induction n using strong. .. exn:: Unable to find an instance for the variables @ident … @ident. Use the :n:`with @bindings` clause or the :tacn:`einduction` tactic instead. .. example:: .. rocqtop:: reset all Lemma induction_test : forall n:nat, n = n -> n <= n. intros n H. induction n. exact (le_n 0). .. example:: :n:`induction` with :n:`@occurrences` `induction in` is useful to generalize over other variables: .. rocqtop:: reset all Lemma induction_test2 : forall n m:nat, n = m -> n <= m. intros n m H. induction n in m, H |- *. Show 2. .. tacn:: einduction {+, @induction_clause } {? @induction_principle } Behaves like :tacn:`induction` except that it does not fail if some :term:`dependent premise` of the type of :n:`@one_term` can't be inferred. Instead, the unresolved premises are posed as existential variables to be inferred later, in the same way as :tacn:`eapply` does. .. tacn:: elim @one_term_with_bindings {? using @one_term_with_bindings } An older, more basic induction tactic. Unlike :tacn:`induction`, ``elim`` only modifies the goal; it does not modify the :term:`local context`. We recommend using :tacn:`induction` instead where possible. :n:`with @bindings` (in :n:`@one_term_with_bindings`) Explicitly gives instances to the premises of the type of :n:`@one_term` (see :ref:`bindings`). :n:`{? using @one_term_with_bindings }` Allows explicitly giving an induction principle :n:`@one_term` that is not the standard one for the underlying inductive type of :n:`@one_term`. The :n:`@bindings` clause allows instantiating premises of the type of :n:`@one_term`. .. tacn:: eelim @one_term_with_bindings {? using @one_term_with_bindings } If the type of :n:`@one_term` has dependent premises, this turns them into existential variables to be resolved later on. .. tacn:: simple induction {| @ident | @natural } Behaves like :n:`intros until {| @ident | @natural }; elim @ident` when :n:`@ident` is a :n:`forall` variable in the goal. .. tacn:: dependent induction @ident {? {| generalizing | in } {+ @ident } } {? using @one_term } .. note:: This tactic requires the Stdlib library. The *experimental* tactic :tacn:`dependent induction` performs induction-inversion on an instantiated inductive predicate. One needs to first :cmd:`Require` the `Stdlib.Program.Equality` module to use this tactic. The tactic is based on the BasicElim tactic by Conor McBride :cite:`DBLP:conf/types/McBride00` and the work of Cristina Cornes around inversion :cite:`DBLP:conf/types/CornesT95`. From an instantiated inductive predicate and a goal, it generates an equivalent goal where the hypothesis has been generalized over its indexes which are then constrained by equalities to be the right instances. This permits to state lemmas without resorting to manually adding these equalities and still get enough information in the proofs. :n:`{| generalizing | in } {+ @ident }` First generalizes the goal by the given variables so that they are universally quantified in the goal. This is generally what one wants to do with variables that are inside constructors in the induction hypothesis. The other ones need not be further generalized. There is a long example of :tacn:`dependent induction` and an explanation of the underlying technique :ref:`here `. .. example:: .. rocqtop:: reset all Lemma lt_1_r : forall n:nat, n < 1 -> n = 0. intros n H ; induction H. Here we did not get any information on the indexes to help fulfill this proof. The problem is that, when we use the ``induction`` tactic, we lose information on the hypothesis instance, notably that the second argument is 1 here. Dependent induction solves this problem by adding the corresponding equality to the context. .. rocqtop:: reset all extra-stdlib Require Import Stdlib.Program.Equality. Lemma lt_1_r : forall n:nat, n < 1 -> n = 0. intros n H ; dependent induction H. The subgoal is cleaned up as the tactic tries to automatically simplify the subgoals with respect to the generated equalities. In this enriched context, it becomes possible to solve this subgoal. .. rocqtop:: all extra-stdlib reflexivity. Now we are in a contradictory context and the proof can be solved. .. rocqtop:: all abort extra-stdlib inversion H. This technique works with any inductive predicate. In fact, the :tacn:`dependent induction` tactic is just a wrapper around the :tacn:`induction` tactic. One can make its own variant by just writing a new tactic based on the definition found in ``Stdlib.Program.Equality``. .. seealso:: :tacn:`functional induction` .. tacn:: fix @ident @natural {? with {+ ( @ident {* @simple_binder } {? %{ struct @name %} } : @type ) } } A primitive tactic that starts a proof by induction. Generally, higher-level tactics such as :tacn:`induction` or :tacn:`elim` are easier to use. The :n:`@ident`\s (including the first one before the `with` clause) are the names of the induction hypotheses. :n:`@natural` tells on which premise of the current goal the induction acts, starting from 1, counting both dependent and non-dependent products, but skipping local definitions. The current lemma must be composed of at least :n:`@natural` products. As in a fix expression, induction hypotheses must be used on structurally smaller arguments. The verification that inductive proof arguments are correct is done only when registering the lemma in the global environment. To know if the use of induction hypotheses is correct during the interactive development of a proof, use the command :cmd:`Guarded`. :n:`with {+ ( @ident {* @simple_binder } {? %{ struct @name %} } : @type ) }` Starts a proof by mutual induction. The statements to be proven are :n:`forall @simple_binder__i, @type__i`. The identifiers :n:`@ident` (including the first one before the `with` clause) are the names of the induction hypotheses. The identifiers :n:`@name` (in the `{ struct ... }` clauses) are the respective names of the premises on which the induction is performed in the statements to be proved (if not given, Rocq guesses what they are). .. tacn:: cofix @ident {? with {+ ( @ident {* @simple_binder } : @type ) } } Starts a proof by coinduction. The :n:`@ident`\s (including the first one before the `with` clause) are the names of the coinduction hypotheses. As in a cofix expression, the use of induction hypotheses must be guarded by a constructor. The verification that the use of coinductive hypotheses is correct is done only at the time of registering the lemma in the global environment. To know if the use of coinduction hypotheses is correct at some time of the interactive development of a proof, use the command :cmd:`Guarded`. :n:`with {+ ( @ident {* @simple_binder } : @type ) }` Starts a proof by mutual coinduction. The statements to be proven are :n:`forall @simple_binder__i, @type__i`. The identifiers :n:`@ident` (including the first one before the `with` clause) are the names of the coinduction hypotheses. .. _equality-inductive_types: Equality of inductive types --------------------------- This section describes some special purpose tactics to work with :term:`Leibniz equality` of inductive sets or types. .. tacn:: discriminate {? @induction_arg } Proves goals for which a hypothesis or a :term:`premise` in the goal that is convertible to the form :n:`@term__1 = @term__2` has inconsistent constructors between the two sides of the equality (i.e., a contradiction). The tactic also works for goals in the form :n:`@term__1 <> @term__2` that are inconsistent (:ref:`example `). If :n:`@induction_arg` is provided, only the provided proof term or hypothesis is checked for inconsistency. If :n:`@induction_arg` is not given, the tactic does an :tacn:`intro` for each premise in the goal, then it checks all the resulting hypotheses for impossible equalities. The tactic relies on the fact that constructors of inductive types are injective and disjoint, i.e. if `C1` and `C2` are distinct constructors of an inductive type then :n:`C1 @term__1 = C1 @term__2` implies that :n:`@term__1 = @term__2` (injectivity) and :n:`C1 @term__1 = C2 @term__2` is a contradiction (disjointedness). For example, :g:`S (S O) = S O` is a contradiction: while the outermost constructors are both `S`, the next ones differ (`S` versus `O`). The tactic traverses the normal forms of :n:`@term__1` and :n:`@term__2`, looking for subterms placed in the same positions whose head symbols are different constructors. If such subterms are present, the equality is impossible and the current goal is completed. Otherwise the tactic fails. Note that opaque constants are not expanded by Ξ΄ reductions while computing the head normal form. Note that :n:`discriminate` doesn't handle contradictory equalities such as :g:`n = S n`. In this case you must use :tacn:`induction` (see :ref:`example `). :n:`@ident` (as :n:`@induction_arg`) Checks the hypothesis :n:`@ident` for impossible equalities. If :n:`@ident` is not already in the context, this is equivalent to :n:`intros until @ident; discriminate @ident`. :n:`@natural` (as :n:`@induction_arg`) Equivalent to :tacn:`intros` :n:`until @natural; discriminate @ident`, where :n:`@ident` is the identifier for the last introduced hypothesis. :n:`@one_term with @bindings` (in :n:`@induction_arg`) Equivalent to :n:`discriminate @one_term` but uses the given bindings to instantiate parameters or hypotheses of :n:`@one_term`. :n:`@one_term` must be a proof of :n:`@term__1 = @term__2`. .. exn:: No primitive equality found. :undocumented: .. exn:: Not a discriminable equality. :undocumented: .. tacn:: ediscriminate {? @induction_arg } Works the same as :tacn:`discriminate` but if the type of :token:`one_term`, or the type of the hypothesis referred to by :token:`natural`, has uninstantiated parameters, these parameters are left as existential variables. .. _discriminate_goal_inequality_ex: .. example:: Proving `1 <> 2` .. rocqtop:: reset in Goal 1 <> 2. discriminate. Qed. This works because `1 <> 2` is represented internally as `not (1 = 2)`, which is just `(1 = 2) -> False` from the definition of `not`: .. rocqtop:: all Print not. You can see this better by doing the :n:`intro` explicitly: .. rocqtop:: in Goal 1 <> 2. .. rocqtop:: all intro. (* if omitted, "discriminate" does an intro *) .. rocqtop:: in discriminate. Qed. .. _discriminate_example: .. example:: :n:`discriminate` limitation: proving `n <> S n` .. rocqtop:: reset in Goal forall n:nat, n <> S n. intro n. induction n. .. rocqtop:: all - discriminate. (* works: O and (S O) start with different constructors *) - Fail discriminate. (* fails: discriminate doesn't handle this case *) injection. .. rocqtop:: in assumption. Qed. .. tacn:: injection {? @induction_arg } {? as {* @simple_intropattern } } Exploits the property that constructors of inductive types are injective, i.e. that if :n:`c` is a constructor of an inductive type and :n:`c t__1 = c t__2` then :n:`t__1 = t__2` are equal too. If there is a hypothesis `H` in the form :n:`@term__1 = @term__2`, then :n:`injection H` applies the injectivity of constructors as deep as possible to derive the equality of subterms of :n:`@term__1` and :n:`@term__2` wherever the subterms start to differ. For example, from :g:`(S p, S n) = (q, S (S m))` we may derive :g:`S p = q` and :g:`n = S m`. The terms must have inductive types and the same head constructor, but must not be convertible. If so, the tactic derives the equalities and adds them to the current goal as :term:`premises ` (except if the :n:`as` clause is used). If no :n:`induction_arg` is provided and the current goal is of the form :n:`@term <> @term`, :tacn:`injection` is equivalent to :n:`intro @ident; injection @ident`. :n:`@ident` (in :n:`@induction_arg`) Derives equalities based on constructor injectivity for the hypothesis :n:`@ident`. If :n:`@ident` is not already in the context, this is equivalent to :n:`intros until @ident; injection @ident`. :n:`@natural` (in :n:`@induction_arg`) Equivalent to :tacn:`intros` :n:`until @natural` followed by :n:`injection @ident` where :n:`@ident` is the identifier for the last introduced hypothesis. :n:`@one_term with @bindings` (in :n:`@induction_arg`) Like :n:`injection @one_term` but uses the given bindings to instantiate parameters or hypotheses of :n:`@one_term`. :n:`as [= {* @intropattern } ]` Specifies names to apply after the injection so that all generated equalities become hypotheses, which (unlike :tacn:`intros`) may replace existing hypotheses with same name. The number of provided names must not exceed the number of newly generated equalities. If it is smaller, fresh names are generated for the unspecified items. The original equality is erased if it corresponds to a provided name or if the list of provided names is incomplete. Note that, as a convenience for users, specifying :n:`{+ @simple_intropattern }` is treated as if :n:`[= {+ @simple_intropattern } ]` was specified. .. example:: Consider the following goal: .. rocqtop:: in Inductive list : Set := | nil : list | cons : nat -> list -> list. Parameter P : list -> Prop. Goal forall l n, P nil -> cons n l = cons 0 nil -> P l. .. rocqtop:: all intros. injection H0. .. note:: Beware that injection yields an equality in a sigma type whenever the injected object has a dependent type :g:`P` with its two instances in different types :n:`(P t__1 … t__n)` and :n:`(P u__1 … u__n)`. If :n:`t__1` and :n:`u__1` are the same and have for type an inductive type for which a decidable equality has been declared using :cmd:`Scheme Equality`, the use of a sigma type is avoided. .. exn:: No information can be deduced from this equality and the injectivity of constructors. This may be because the terms are convertible, or due to pattern matching restrictions in the sort Prop. You can try to use option Set Keep Proof Equalities. :undocumented: .. exn:: Not a negated primitive equality When :n:`@induction_arg` is not provided, the goal must be in the form :n:`@term <> @term`. .. exn:: Nothing to inject. Generated when one side of the equality is not a constructor. .. tacn:: einjection {? @induction_arg } {? as {* @simple_intropattern } } Works the same as :n:`injection` but if the type of :n:`@one_term`, or the type of the hypothesis referred to by :n:`@natural` has uninstantiated parameters, these parameters are left as existential variables. .. tacn:: simple injection {? @induction_arg } Similar to :tacn:`injection`, but always adds the derived equalities as new :term:`premises ` in the current goal (instead of as new hypotheses) even if the :flag:`Structural Injection` flag is set. .. flag:: Structural Injection When this :term:`flag` is set, :n:`injection @term` erases the original hypothesis and adds the generated equalities as new hypotheses rather than adding them to the current goal as :term:`premises `, as if giving :n:`injection @term as` (with an empty list of names). This flag is off by default. .. flag:: Keep Proof Equalities By default, :tacn:`injection` only creates new equalities between :n:`@term`\s whose type is in sort :g:`Type` or :g:`Set`, thus implementing a special behavior for objects that are proofs of a statement in :g:`Prop`. This :term:`flag` controls this behavior. .. table:: Keep Equalities @qualid This :term:`table` specifies a set of inductive types for which proof equalities are always kept by :tacn:`injection`. This overrides the :flag:`Keep Proof Equalities` flag for those inductive types. Use the :cmd:`Add` and :cmd:`Remove` commands to update this set manually. .. tacn:: simplify_eq {? @induction_arg } Examines a hypothesis that has the form :n:`@term__1 = @term__2`. If the terms are structurally different, the tactic does a :tacn:`discriminate`. Otherwise, it does an :tacn:`injection` to simplify the equality, if possible. If :n:`induction_arg` is not provided, the tactic examines the goal, which must be in the form :n:`@term__1 <> @term__2`. See the description of :token:`induction_arg` in :tacn:`injection` for an explanation of the parameters. .. tacn:: esimplify_eq {? @induction_arg } Works the same as :tacn:`simplify_eq` but if the type of :n:`@one_term` or the type of the hypothesis referred to by :n:`@natural` has uninstantiated parameters, these parameters are left as existential variables. .. tacn:: inversion {| @ident | @natural } {? as @or_and_intropattern } {? in {+ @ident } } inversion {| @ident | @natural } using @one_term {? in {+ @ident } } :name: inversion; _ .. comment: the other inversion* tactics don't support the using clause, but they should be able to, if desired. It wouldn't make sense for inversion_sigma. See https://github.com/rocq-prover/rocq/pull/14179#discussion_r642193096 For a hypothesis whose type is a (co)inductively defined proposition, the tactic introduces a goal for each constructor of the proposition that isn't self-contradictory. Each such goal includes the hypotheses needed to deduce the proposition. :gdef:`(Co)inductively defined propositions ` are those defined with the :cmd:`Inductive` or :cmd:`CoInductive` commands whose contructors yield a `Prop`, as in this :ref:`example `. :n:`@ident` The name of the hypothesis to invert. If :n:`@ident` does not denote a hypothesis in the local context but refers to a hypothesis quantified in the goal, then the latter is first introduced in the local context using :n:`intros until @ident`. :n:`@natural` Equivalent to :n:`intros until @natural; inversion @ident` where :n:`@ident` is the identifier for the last introduced hypothesis. :n:`{? in {+ @ident } }` When :n:`{+ @ident}` are identifiers in the local context, this does a :tacn:`generalize` :n:`{+ @ident}` as the initial step of `inversion`. :n:`as @or_and_intropattern` Provides names for the variables introduced in each new subgoal. The :token:`or_and_intropattern` must have one :n:`{* @intropattern }` for each constructor of the (co)inductive predicate, given in the order in which the constructors are defined. If there are not enough names, Rocq picks fresh names. If an equation splits into several equations (because ``inversion`` applies ``injection`` on the equalities it generates), the corresponding :n:`@intropattern` should be in the form :n:`[ {* @intropattern } ]` (or the equivalent :n:`{*, ( @simple_intropattern ) }`), with the number of entries equal to the number of subequalities obtained from splitting the original equation. Example :ref:`here `. .. note:: The ``inversion … as`` variant of ``inversion`` generally behaves in a slightly more expected way than ``inversion`` (no artificial duplication of some hypotheses referring to other hypotheses). To take advantage of these improvements, it is enough to use ``inversion … as []``, letting Rocq choose fresh names. .. note:: As ``inversion`` proofs may be large, we recommend creating and using lemmas whenever the same instance needs to be inverted several times. See :ref:`derive-inversion`. .. note:: Part of the behavior of the :tacn:`inversion` tactic is to generate equalities between expressions that appeared in the hypothesis that is being processed. By default, no equalities are generated if they relate two proofs (i.e. equalities between :token:`term`\s whose type is in sort :g:`Prop`). This behavior can be turned off by using the :flag:`Keep Proof Equalities` setting. .. _inversion-intropattern-ex: .. example:: :tacn:`inversion` with :n:`as @or_and_intropattern` .. rocqtop:: reset all Inductive contains0 : list nat -> Prop := | in_hd : forall l, contains0 (0 :: l) | in_tl : forall l b, contains0 l -> contains0 (b :: l). .. rocqtop:: in Goal forall l:list nat, contains0 (1 :: l) -> contains0 l. .. rocqtop:: all intros l H. inversion H as [ | l' p Hl' [Heqp Heql'] ]. .. tacn:: inversion_clear {| @ident | @natural } {? as @or_and_intropattern } {? in {+ @ident } } Does an :tacn:`inversion` and then erases the hypothesis that was used for the inversion. .. tacn:: simple inversion {| @ident | @natural } {? as @or_and_intropattern } {? in {+ @ident } } A very simple inversion tactic that derives all the necessary equalities but does not simplify the constraints as :tacn:`inversion` does. .. tacn:: dependent inversion {| @ident | @natural } {? as @or_and_intropattern } {? with @one_term } For use when the inverted hypothesis appears in the current goal. Does an :tacn:`inversion` and then substitutes the name of the hypothesis where the corresponding term appears in the goal. .. tacn:: dependent inversion_clear {| @ident | @natural } {? as @or_and_intropattern } {? with @one_term } Does a :tacn:`dependent inversion` and then erases the hypothesis that was used for the dependent inversion. .. tacn:: dependent simple inversion {| @ident | @natural } {? as @or_and_intropattern } {? with @one_term } :undocumented: .. tacn:: inversion_sigma {? @ident {? as @simple_intropattern } } .. note:: This tactic requires the Stdlib library. Turns equalities of dependent pairs (e.g., :g:`existT P x p = existT P y q`, frequently left over by :tacn:`inversion` on a dependent type family) into pairs of equalities (e.g., a hypothesis :g:`H : x = y` and a hypothesis of type :g:`rew H in p = q`); these hypotheses can subsequently be simplified using :tacn:`subst`, without ever invoking any kind of axiom asserting uniqueness of identity proofs. If you want to explicitly specify the hypothesis to be inverted, you can pass it as an argument to :tacn:`inversion_sigma`. This tactic also works for :g:`sig`, :g:`sigT2`, :g:`sig2`, :g:`ex`, and :g:`ex2` and there are similar :g:`eq_sig` :g:`***_rect` induction lemmas. .. exn:: Type of @ident is not an equality of recognized Ξ£ types: expected one of sig sig2 sigT sigT2 sigT2 ex or ex2 but got @term When applied to a hypothesis, :tacn:`inversion_sigma` can only handle equalities of the listed sigma types. .. exn:: @ident is not an equality of Ξ£ types When applied to a hypothesis, :tacn:`inversion_sigma` can only be called on hypotheses that are equalities using :g:`Stdlib.Logic.Init.eq`. .. example:: Non-dependent inversion Let us consider the relation :g:`Le` over natural numbers: .. rocqtop:: reset in Inductive Le : nat -> nat -> Set := | LeO : forall n:nat, Le 0 n | LeS : forall n m:nat, Le n m -> Le (S n) (S m). Let us consider the following goal: .. rocqtop:: none Section Section. Variable P : nat -> nat -> Prop. Variable Q : forall n m:nat, Le n m -> Prop. Goal forall n m, Le (S n) m -> P n m. .. rocqtop:: out intros. To prove the goal, we may need to reason by cases on :g:`H` and to derive that :g:`m` is necessarily of the form :g:`(S m0)` for certain :g:`m0` and that :g:`(Le n m0)`. Deriving these conditions corresponds to proving that the only possible constructor of :g:`(Le (S n) m)` is :g:`LeS` and that we can invert the arrow in the type of :g:`LeS`. This inversion is possible because :g:`Le` is the smallest set closed by the constructors :g:`LeO` and :g:`LeS`. .. rocqtop:: all inversion_clear H. Note that :g:`m` has been substituted in the goal for :g:`(S m0)` and that the hypothesis :g:`(Le n m0)` has been added to the context. Sometimes it is interesting to have the equality :g:`m = (S m0)` in the context to use it after. In that case we can use :tacn:`inversion` that does not clear the equalities: .. rocqtop:: none restart intros. .. rocqtop:: all inversion H. .. example:: Dependent inversion Let us consider the following goal: .. rocqtop:: none Abort. Goal forall n m (H:Le (S n) m), Q (S n) m H. .. rocqtop:: out intros. As :g:`H` occurs in the goal, we may want to reason by cases on its structure and so, we would like inversion tactics to substitute :g:`H` by the corresponding term in constructor form. Neither :tacn:`inversion` nor :tacn:`inversion_clear` do such a substitution. To have such a behavior we use the dependent inversion tactics: .. rocqtop:: all dependent inversion_clear H. Note that :g:`H` has been substituted by :g:`(LeS n m0 l)` and :g:`m` by :g:`(S m0)`. .. example:: Using :tacn:`inversion_sigma` Let us consider the following inductive type of length-indexed lists, and a lemma about inverting equality of cons: .. rocqtop:: reset all extra-stdlib Require Import Stdlib.Logic.Eqdep_dec. Inductive vec A : nat -> Type := | nil : vec A O | cons {n} (x : A) (xs : vec A n) : vec A (S n). Lemma invert_cons : forall A n x xs y ys, @cons A n x xs = @cons A n y ys -> xs = ys. Proof. intros A n x xs y ys H. After performing inversion, we are left with an equality of existTs: .. rocqtop:: all extra-stdlib inversion H. We can turn this equality into a usable form with inversion_sigma: .. rocqtop:: all extra-stdlib inversion_sigma. To finish cleaning up the proof, we will need to use the fact that that all proofs of n = n for n a nat are eq_refl: .. rocqtop:: all extra-stdlib let H := match goal with H : n = n |- _ => H end in pose proof (Eqdep_dec.UIP_refl_nat _ H); subst H. simpl in *. Finally, we can finish the proof: .. rocqtop:: all extra-stdlib assumption. Qed. .. seealso:: :tacn:`functional inversion` Helper tactics ~~~~~~~~~~~~~~ .. tacn:: decide @one_term__1 with @one_term__2 Replaces occurrences of :n:`@one_term__1` in the form :g:`{P}+{~P}` in the goal with :g:`(left _)` or :g:`(right _)`, depending on :n:`@one_term__2`. :n:`@one_term__2` must be of type either :g:`P` or :g:`~P`, and :g:`P` must be of type :g:`Prop`. .. example:: Using :tacn:`decide` to rewrite the goal .. rocqtop:: in extra-stdlib Goal forall (P Q : Prop) (Hp : {P} + {~P}) (Hq : {Q} + {~Q}), P -> ~Q -> (if Hp then true else false) = (if Hq then false else true). .. rocqtop:: all extra-stdlib intros P Q Hp Hq p nq. decide Hp with p. decide Hq with nq. .. rocqtop:: in extra-stdlib reflexivity. Qed. .. tacn:: decide equality Solves a goal of the form :n:`{? forall x y : R, } {x = y} + {~ x = y}` or :n:`{? forall x y : R, } (x = y) \/ (~ x = y)`, where :g:`R` is an inductive type whose constructors do not take proofs or functions as arguments, nor objects in dependent types. .. tacn:: compare @one_term__1 @one_term__2 Compares two :n:`@one_term`\s of an inductive datatype. If :g:`G` is the current goal, it leaves the sub-goals :n:`@one_term__1 = @one_term__2 -> G` and :n:`~ @one_term__1 = @one_term__2 -> G`. The type of the :n:`@one_term`\s must satisfy the same restrictions as in the tactic :tacn:`decide equality`. .. tacn:: dependent rewrite {? {| -> | <- } } @one_term {? in @ident } If :n:`@ident` has type :g:`(existT B a b)=(existT B a' b')` in the local context (i.e. each term of the equality has a sigma type :g:`{ a:A & (B a)}`) this tactic rewrites :g:`a` into :g:`a'` and :g:`b` into :g:`b'` in the current goal. This tactic works even if :g:`B` is also a sigma type. This kind of equalities between dependent pairs may be derived by the :tacn:`injection` and :tacn:`inversion` tactics. :n:`{? {| -> | <- } }` By default, the equality is applied from left to right. Specify `<-` to apply the equality from right to left. .. _proofschemes-induction-principles: Generation of induction principles with ``Scheme`` -------------------------------------------------------- .. cmd:: Scheme {? @ident := } @scheme_kind {* with {? @ident := } @scheme_kind } .. insertprodn scheme_kind sort_quality_or_set scheme_type .. prodn:: scheme_kind ::= @scheme_type for @reference Sort @sort_quality_or_set scheme_type ::= Induction | Minimality | Elimination | Case sort_quality_or_set ::= Prop | SProp | Set | Type Generates :term:`induction principles ` with given :n:`scheme_type`\s and :n:`sort_quality_or_set`\s for an inductive type. In the case where the inductive definition is a mutual inductive definition, the :n:`with` clause is used to generate a mutually recursive inductive scheme for each clause of the mutual inductive type. :n:`@ident` The name of the scheme. If not provided, the name will be determined automatically from the :n:`@scheme_type` and :n:`@sort_quality_or_set`. :n:`@scheme_type` Generate induction principles with given properties: =================== =========== =========== :n:`@scheme_type` Recursive Dependent =================== =========== =========== :n:`Induction` Yes Yes :n:`Minimality` Yes No :n:`Elimination` No Yes :n:`Case` No No =================== =========== =========== See :ref:`examples ` of the :n:`@scheme_type`\s. Unless attribute `register=no` is used, the scheme is automatically registered for use by tactics (for instance :tacn:`induction` uses `Induction` schemes). Use :cmd:`Register Scheme` to manually register a scheme. .. example:: Induction scheme for tree and forest Currently the automatically-generated :term:`induction principles ` such as `odd_ind` are not useful for mutually-inductive types such as `odd` and `even`. You can define a mutual induction principle for tree and forest in sort ``Set`` with the :cmd:`Scheme` command: .. rocqtop:: reset none Axiom A : Set. Axiom B : Set. .. rocqtop:: in Inductive tree : Set := | node : A -> forest -> tree with forest : Set := | leaf : B -> forest | cons : tree -> forest -> forest. .. rocqtop:: all Scheme tree_forest_rec := Induction for tree Sort Set with forest_tree_rec := Induction for forest Sort Set. You may now look at the type of tree_forest_rec: .. rocqtop:: all Check tree_forest_rec. This principle involves two different predicates for trees and forests; it also has three premises each one corresponding to a constructor of one of the inductive definitions. The principle `forest_tree_rec` shares exactly the same premises, only the conclusion now refers to the property of forests. .. example:: Predicates odd and even on naturals Let odd and even be inductively defined as: .. rocqtop:: in Inductive odd : nat -> Prop := | oddS : forall n : nat, even n -> odd (S n) with even : nat -> Prop := | evenO : even 0 | evenS : forall n : nat, odd n -> even (S n). The following command generates a powerful elimination principle: .. rocqtop:: all Scheme odd_even := Minimality for odd Sort Prop with even_odd := Minimality for even Sort Prop. The type of odd_even for instance will be: .. rocqtop:: all Check odd_even. The type of `even_odd` shares the same premises but the conclusion is `forall n : nat, even n -> P0 n`. .. _scheme_example: .. example:: `Scheme` commands with various :n:`@scheme_type`\s Let us demonstrate the difference between the Scheme commands. .. rocqtop:: all Unset Elimination Schemes. Inductive Nat := | z : Nat | s : Nat -> Nat. (* dependent, recursive *) Scheme Induction for Nat Sort Set. About Nat_rec. (* non-dependent, recursive *) Scheme Minimality for Nat Sort Set. About Nat_rec_nodep. (* dependent, non-recursive *) Scheme Elimination for Nat Sort Set. About Nat_case. (* non-dependent, non-recursive *) Scheme Case for Nat Sort Set. About Nat_case_nodep. Eliminators for Nested Inductive Types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When generating eliminators for a predicate `P`, if an argument is nested with :n:`@reference`, the `All` predicate and its theorem will be looked up with the key :n:`All` and :n:`AllForall`, and used to enforce `P` holds on the nested argument. .. warn:: @reference is nested using @reference. No Lemma for @reference is registered for @ident. It can be generated using command "Scheme All" e.g. "Scheme All for @ident.". :name: register-all The `All` and `AllForall` predicate need to be defined and registered before the definition of the nested inductive type. They are not generated on the fly if they are not found. If they are not registered, no induction hypothesis is created for the nested argument. .. cmd:: Scheme All for @reference {? over {+, @ident } } :name: Scheme All For an inductive type `ind`, it generates the sort and universe polymorphic inductive predicate `ind_all` and its theorem `ind_all_forall`, and register them with the keys `All` and `AllForall` (see command :cmd:`Register Scheme`). .. opt:: Depth Scheme All @natural The `All` predicate for an inductive type is itself an inductive type. Consequently, generating automatically the `All` predicate at the definition of an inductive type would create an infinite loop. To prevent this, `Depth Scheme All` controls to which depth should the `All` predicate be generated. For instance, at depth `1`, the `All` predicate for `prod` will be generated, `prod_all`, but the `All` predicate for `prod_all` will not be generated. Its default value is `0`. The depth for nested inductive types is `Depth Scheme All -1` as if `X` is nested with `Y`, then `X_all` is nested with `Y_all`, and the eliminator for `X_all` requires `Y_all_all`. The `All` predicate features a predicate `PA : A -> Type@{s;u}` for each strictly positive uniform-parameter `A : Type` (or more generally an arity), and enforces they hold for each subterm of type `A` in the body of `ind`. The theorem `AllForall` then states that if all the predicates `PA` hold, that is `forall a, PA a`, then `ind_all` holds. The definitions must be sort polymorphic to generate eliminators for the different sorts `Prop`, `Type`, etc. The `AllForall` theorem must also be transparent to ensure termination checking. The corresponding theory can found in :cite:`NestedInductiveTypes`. Wen used to generate eliminators, the type `unit` is used to instantiate the predicates if some parameters are not nested on. For instance, if `prod A B` is nested on `A` but not on `B`, then the predicate for `B` is instantiated with `fun _ => unit`. To provide better eliminators, the `over` clause enables to generate partial version of the `All` predicate, with predicates only for strictly positive uniform-parameter specified. The partial versions of `All` and `AllForall` are looked up first, and the implementation fallbacks on the general ones if they are not found. Partial versions can be registered by hand using the key with `All_s` and `AllForall_s` where `s` is a list of `1` and `0` specifying which parameters can be nested or not. For instance, to register a partial version of `All` for `prod A B` with a predicate on `A` but not on `B`, one should use `All_10`. .. example:: Nesting With Prod The inductive type `prod` has two uniform-parameters `A, B : Type` that are strictly positive, and hence nestable. .. rocqtop:: in reset Inductive prod (A B : Type) : Type := | pair : A -> B -> prod A B. The `All` predicate should then be a predicate with additional parameters `PA : A -> Type@{s;u}` and `PB : B -> Type@{s';u'}`, and requires `PA a` and `PB b` for `prod A PA B PB (pair a b)` to hold. Its theorem will then state that if `PA` and `PB` hold, then `prod_all` holds. They can be generated with :cmd:`Scheme All` command. .. rocqtop:: all Scheme All for prod. Print prod_all. About prod_all_forall. When generating eliminators for a predicate `P`, if an argument is nested with `prod`, the `prod_all` predicate and its theorem will be looked up, and used to enforce `P` holds on the argument. The type `unit` is used to instantiate the predicates if some parameters are not nested on. For instance, if `prod` is nested on `A` but not on `B`, then `PB` is instantiated with `fun _ => unit`. .. rocqtop:: all Inductive LeftTree A : Type := | Lleaf (a : A) : LeftTree A | Lnode (p : prod (LeftTree A) nat) : LeftTree A. About LeftTree_ind. To provide better eliminators for partially nesting like `LeftTree`, it is possible to generate partial version of `prod_all` .. rocqtop:: all Scheme All for prod over A. Print prod_all_10. About prod_all_forall_10. This partial verion of the `All` predicate will then be used in priority, falling back on the general version if it is not found. For instance, if we generate an eliminator for `LeftTree` after the generation of `prod_all_10`, `prod_all_10` will be used instead of `prod_all`. .. rocqtop:: all Scheme LeftTree_ind_partial := Induction for LeftTree Sort Prop. About LeftTree_ind_partial. Scheme Equality, and Rewriting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Scheme {? Boolean } Equality for @reference :name: Scheme Equality; Scheme Boolean Equality Tries to generate a Boolean equality for :n:`@reference`. If :n:`Boolean` is not specified, the command also tries to generate a proof of the decidability of propositional equality over :n:`@reference`. If :token:`reference` involves independent constants or other inductive types, we recommend defining their equality first. .. cmd:: Scheme Rewriting for @reference :name: Scheme Rewriting Tries to generate rewriting schemes such as congruence for :n:`@reference`. Equivalent to setting :flag:`Rewriting Schemes` before declaring :n:`@reference`. Automatic declaration of schemes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. attr:: schemes = {| default | none } :name: schemes When this attribute is not provided or provided with value `default`, schemes are automatically declared according to the following flags. When it is provided with value `none`, no schemes are automatically declared. .. flag:: Elimination Schemes This :term:`flag` enables automatic declaration of induction principles when defining a new inductive type. Defaults to on. .. flag:: Nonrecursive Elimination Schemes This :term:`flag` enables automatic declaration of induction principles for types declared with the :cmd:`Variant` and :cmd:`Record` commands. Defaults to off. .. flag:: Case Analysis Schemes This :term:`flag` governs the generation of case analysis lemmas for inductive types, i.e. corresponding to the pattern matching term alone and without fixpoint. .. flag:: Boolean Equality Schemes Decidable Equality Schemes These :term:`flags ` control the automatic declaration of those Boolean equalities (see the second variant of ``Scheme``). .. warning:: You have to be careful with these flags since Rocq may now reject well-defined inductive types because it cannot compute a Boolean equality for them. .. flag:: Rewriting Schemes This :term:`flag` governs generation of equality-related schemes such as congruence. Combined Scheme ~~~~~~~~~~~~~~~ .. cmd:: Combined Scheme @ident__def from {+, @ident } Combines induction principles generated by the :cmd:`Scheme` command. Each :n:`@ident` is a different inductive principle that must belong to the same package of mutual inductive principle definitions. This command generates :n:`@ident__def` as the conjunction of the principles: it is built from the common premises of the principles and concluded by the conjunction of their conclusions. In the case where all the inductive principles used are in sort ``Prop``, the propositional conjunction ``and`` is used, otherwise the simple product ``prod`` is used instead. .. example:: We can define the induction principles for trees and forests using: .. rocqtop:: reset none Axiom A : Set. Axiom B : Set. .. rocqtop:: in Inductive tree : Set := | node : A -> forest -> tree with forest : Set := | leaf : B -> forest | cons : tree -> forest -> forest. .. rocqtop:: all Scheme tree_forest_ind := Induction for tree Sort Prop with forest_tree_ind := Induction for forest Sort Prop. Then we can build the combined induction principle which gives the conjunction of the conclusions of each individual principle: .. rocqtop:: all Combined Scheme tree_forest_mutind from tree_forest_ind,forest_tree_ind. The type of tree_forest_mutind will be: .. rocqtop:: all Check tree_forest_mutind. .. example:: We can also combine schemes at sort ``Type``: .. rocqtop:: all Scheme tree_forest_rect := Induction for tree Sort Type with forest_tree_rect := Induction for forest Sort Type. .. rocqtop:: all Combined Scheme tree_forest_mutrect from tree_forest_rect, forest_tree_rect. .. rocqtop:: all Check tree_forest_mutrect. .. seealso:: :ref:`functional-scheme` .. _derive-inversion: Generation of inversion principles with ``Derive`` ``Inversion`` ----------------------------------------------------------------- .. cmd:: Derive Inversion @ident with @one_term {? Sort @sort_quality_or_set } Generates an inversion lemma for the :tacn:`inversion` tactic. :token:`ident` is the name of the generated lemma. :token:`one_term` should be in the form :token:`qualid` or :n:`(forall {+ @binder }, @qualid {+ @one_term })` where :token:`qualid` is the name of an inductive predicate and :n:`{+ @binder }` binds the variables occurring in :n:`{+ @one_term }`. The lemma is generated for the sort :token:`sort_quality_or_set` corresponding to :token:`one_term`. Applying the lemma is equivalent to inverting the instance with the :tacn:`inversion` tactic. .. cmd:: Derive Inversion_clear @ident with @one_term {? Sort @sort_quality_or_set } When applied, it is equivalent to having inverted the instance with the tactic inversion replaced by the tactic `inversion_clear`. .. cmd:: Derive Dependent Inversion @ident with @one_term Sort @sort_quality_or_set When applied, it is equivalent to having inverted the instance with the tactic `dependent inversion`. .. cmd:: Derive Dependent Inversion_clear @ident with @one_term Sort @sort_quality_or_set When applied, it is equivalent to having inverted the instance with the tactic `dependent inversion_clear`. .. example:: Consider the relation `Le` over natural numbers and the following parameter ``P``: .. rocqtop:: all Inductive Le : nat -> nat -> Set := | LeO : forall n:nat, Le 0 n | LeS : forall n m:nat, Le n m -> Le (S n) (S m). Parameter P : nat -> nat -> Prop. To generate the inversion lemma for the instance :g:`(Le (S n) m)` and the sort :g:`Prop`, we do: .. rocqtop:: all Derive Inversion_clear leminv with (forall n m:nat, Le (S n) m) Sort Prop. Check leminv. Then we can use the proven inversion lemma: .. rocqtop:: none Goal forall (n m : nat) (H : Le (S n) m), P n m. intros. .. rocqtop:: all Show. inversion H using leminv. .. _dependent-induction-examples: Examples of :tacn:`dependent destruction` / :tacn:`dependent induction` ----------------------------------------------------------------------- .. note:: These tactics require the Stdlib library. The tactics :tacn:`dependent induction` and :tacn:`dependent destruction` are another solution for inverting inductive predicate instances and potentially doing induction at the same time. It is based on the ``BasicElim`` tactic of Conor McBride which works by abstracting each argument of an inductive instance by a variable and constraining it by equalities afterwards. This way, the usual induction and destruct tactics can be applied to the abstracted instance and after simplification of the equalities we get the expected goals. The abstracting tactic is called generalize_eqs and it takes as argument a hypothesis to generalize. It uses the JMeq datatype defined in Stdlib.Logic.JMeq, hence we need to require it before. For example, revisiting the first example of the inversion documentation: .. rocqtop:: in reset extra-stdlib Require Import Stdlib.Logic.JMeq. Inductive Le : nat -> nat -> Set := | LeO : forall n:nat, Le 0 n | LeS : forall n m:nat, Le n m -> Le (S n) (S m). Parameter P : nat -> nat -> Prop. Goal forall n m:nat, Le (S n) m -> P n m. intros n m H. .. rocqtop:: all extra-stdlib generalize_eqs H. The index ``S n`` gets abstracted by a variable here, but a corresponding equality is added under the abstract instance so that no information is actually lost. The goal is now almost amenable to do induction or case analysis. One should indeed first move ``n`` into the goal to strengthen it before doing induction, or ``n`` will be fixed in the inductive hypotheses (this does not matter for case analysis). As a rule of thumb, all the variables that appear inside constructors in the indices of the hypothesis should be generalized. This is exactly what the ``generalize_eqs_vars`` variant does: .. rocqtop:: all abort extra-stdlib generalize_eqs_vars H. induction H. As the hypothesis itself did not appear in the goal, we did not need to use an heterogeneous equality to relate the new hypothesis to the old one (which just disappeared here). However, the tactic works just as well in this case, e.g.: .. rocqtop:: none extra-stdlib Require Import Stdlib.Program.Equality. .. rocqtop:: in extra-stdlib Parameter Q : forall (n m : nat), Le n m -> Prop. Goal forall n m (p : Le (S n) m), Q (S n) m p. .. rocqtop:: all extra-stdlib intros n m p. generalize_eqs_vars p. One drawback of this approach is that in the branches one will have to substitute the equalities back into the instance to get the right assumptions. Sometimes injection of constructors will also be needed to recover the needed equalities. Also, some subgoals should be directly solved because of inconsistent contexts arising from the constraints on indexes. The nice thing is that we can make a tactic based on discriminate, injection and variants of substitution to automatically do such simplifications (which may involve the axiom K). This is what the ``simplify_dep_elim`` tactic from ``Stdlib.Program.Equality`` does. For example, we might simplify the previous goals considerably: .. rocqtop:: all abort extra-stdlib induction p ; simplify_dep_elim. The higher-order tactic ``do_depind`` defined in ``Stdlib.Program.Equality`` takes a tactic and combines the building blocks we have seen with it: generalizing by equalities calling the given tactic with the generalized induction hypothesis as argument and cleaning the subgoals with respect to equalities. Its most important instantiations are :tacn:`dependent induction` and :tacn:`dependent destruction` that do induction or simply case analysis on the generalized hypothesis. For example we can redo what we've done manually with dependent destruction: .. rocqtop:: in extra-stdlib Lemma ex : forall n m:nat, Le (S n) m -> P n m. .. rocqtop:: in extra-stdlib intros n m H. .. rocqtop:: all abort extra-stdlib dependent destruction H. This gives essentially the same result as inversion. Now if the destructed hypothesis actually appeared in the goal, the tactic would still be able to invert it, contrary to dependent inversion. Consider the following example on vectors: .. rocqtop:: in extra-stdlib Set Implicit Arguments. .. rocqtop:: in extra-stdlib Parameter A : Set. .. rocqtop:: in extra-stdlib Inductive vector : nat -> Type := | vnil : vector 0 | vcons : A -> forall n, vector n -> vector (S n). .. rocqtop:: in extra-stdlib Goal forall n, forall v : vector (S n), exists v' : vector n, exists a : A, v = vcons a v'. .. rocqtop:: in extra-stdlib intros n v. .. rocqtop:: all extra-stdlib dependent destruction v. In this case, the ``v`` variable can be replaced in the goal by the generalized hypothesis only when it has a type of the form ``vector (S n)``, that is only in the second case of the destruct. The first one is dismissed because ``S n <> 0``. A larger example ~~~~~~~~~~~~~~~~ Let's see how the technique works with induction on inductive predicates on a real example. We will develop an example application to the theory of simply-typed lambda-calculus formalized in a dependently-typed style: .. rocqtop:: in reset Inductive type : Type := | base : type | arrow : type -> type -> type. .. rocqtop:: in Notation " t --> t' " := (arrow t t') (at level 20, right associativity). .. rocqtop:: in Inductive ctx : Type := | empty : ctx | snoc : ctx -> type -> ctx. .. rocqtop:: in Notation " G , tau " := (snoc G tau) (at level 21, left associativity). .. rocqtop:: in Fixpoint conc (G D : ctx) : ctx := match D with | empty => G | snoc D' x => snoc (conc G D') x end. .. rocqtop:: in Notation " G ; D " := (conc G D) (at level 21). .. rocqtop:: in Inductive term : ctx -> type -> Type := | ax : forall G tau, term (G, tau) tau | weak : forall G tau, term G tau -> forall tau', term (G, tau') tau | abs : forall G tau tau', term (G , tau) tau' -> term G (tau --> tau') | app : forall G tau tau', term G (tau --> tau') -> term G tau -> term G tau'. We have defined types and contexts which are snoc-lists of types. We also have a ``conc`` operation that concatenates two contexts. The ``term`` datatype represents in fact the possible typing derivations of the calculus, which are isomorphic to the well-typed terms, hence the name. A term is either an application of: + the axiom rule to type a reference to the first variable in a context + the weakening rule to type an object in a larger context + the abstraction or lambda rule to type a function + the application to type an application of a function to an argument Once we have this datatype we want to do proofs on it, like weakening: .. rocqtop:: in abort Lemma weakening : forall G D tau, term (G ; D) tau -> forall tau', term (G , tau' ; D) tau. The problem here is that we can't just use induction on the typing derivation because it will forget about the ``G ; D`` constraint appearing in the instance. A solution would be to rewrite the goal as: .. rocqtop:: in abort Lemma weakening' : forall G' tau, term G' tau -> forall G D, (G ; D) = G' -> forall tau', term (G, tau' ; D) tau. With this proper separation of the index from the instance and the right induction loading (putting ``G`` and ``D`` after the inducted-on hypothesis), the proof will go through, but it is a very tedious process. One is also forced to make a wrapper lemma to get back the more natural statement. The :tacn:`dependent induction` tactic alleviates this trouble by doing all of this plumbing of generalizing and substituting back automatically. Indeed we can simply write: .. rocqtop:: in extra-stdlib Require Import Stdlib.Program.Tactics. Require Import Stdlib.Program.Equality. .. rocqtop:: in extra-stdlib Lemma weakening : forall G D tau, term (G ; D) tau -> forall tau', term (G , tau' ; D) tau. .. rocqtop:: in extra-stdlib Proof with simpl in * ; simpl_depind ; auto. .. rocqtop:: in extra-stdlib intros G D tau H. dependent induction H generalizing G D ; intros. This call to :tacn:`dependent induction` has an additional arguments which is a list of variables appearing in the instance that should be generalized in the goal, so that they can vary in the induction hypotheses. By default, all variables appearing inside constructors (except in a parameter position) of the instantiated hypothesis will be generalized automatically but one can always give the list explicitly. .. rocqtop:: all extra-stdlib Show. The ``simpl_depind`` tactic includes an automatic tactic that tries to simplify equalities appearing at the beginning of induction hypotheses, generally using trivial applications of ``reflexivity``. In cases where the equality is not between constructor forms though, one must help the automation by giving some arguments, using the ``specialize`` tactic for example. .. rocqtop:: in extra-stdlib destruct D; simpl in * ; simpl_depind ; auto. apply weak; apply ax. apply ax. .. rocqtop:: in extra-stdlib destruct D; simpl in * ; simpl_depind ; auto. .. rocqtop:: all extra-stdlib Show. .. rocqtop:: all extra-stdlib specialize (IHterm G0 empty eq_refl). Once the induction hypothesis has been narrowed to the right equality, it can be used directly. .. rocqtop:: all extra-stdlib apply weak, IHterm. Now concluding this subgoal is easy. .. rocqtop:: in extra-stdlib constructor; apply IHterm; reflexivity. rocq-9.2.0/doc/sphinx/proofs/writing-proofs/rewriting.rst000066400000000000000000000001261516144147600236210ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/refman-preamble.rst000066400000000000000000000022631516144147600203470ustar00rootroot00000000000000.. This file is automatically prepended to all other files using the ``rst_prolog`` option. .. only:: html .. This is included once per page in the HTML build, and a single time (in the document's preamble) in the LaTeX one. .. preamble:: /refman-preamble.sty .. Some handy replacements for common items .. role:: smallcaps .. |c_1| replace:: `c`\ :math:`_{1}` .. |c_i| replace:: `c`\ :math:`_{i}` .. |c_n| replace:: `c`\ :math:`_{n}` .. |Cic| replace:: CIC .. |eq_beta_delta_iota_zeta| replace:: `=`\ :math:`_{βδι΢}` .. |Latex| replace:: :smallcaps:`LaTeX` .. |Ltac| replace:: `L`:sub:`tac` .. |p_1| replace:: `p`\ :math:`_{1}` .. |p_i| replace:: `p`\ :math:`_{i}` .. |p_n| replace:: `p`\ :math:`_{n}` .. |Program| replace:: :strong:`Program` .. |Prop| replace:: :math:`\Prop` .. |SProp| replace:: :math:`\SProp` .. |Set| replace:: :math:`\Set` .. |SSR| replace:: :smallcaps:`SSReflect` .. |Type| replace:: :math:`\Type` .. |t_1| replace:: `t`\ :math:`_{1}` .. |t_i| replace:: `t`\ :math:`_{i}` .. |t_m| replace:: `t`\ :math:`_{m}` .. |t_n| replace:: `t`\ :math:`_{n}` .. |x_1| replace:: `x`\ :math:`_{1}` .. |x_i| replace:: `x`\ :math:`_{i}` .. |x_n| replace:: `x`\ :math:`_{n}` rocq-9.2.0/doc/sphinx/refman-preamble.sty000066400000000000000000000052121516144147600203530ustar00rootroot00000000000000\newcommand{\as}{\kw{as}} \newcommand{\case}{\kw{case}} \newcommand{\cons}{\textsf{cons}} \newcommand{\consf}{\textsf{consf}} \newcommand{\emptyf}{\textsf{emptyf}} \newcommand{\End}{\kw{End}} \newcommand{\kwend}{\kw{end}} \newcommand{\even}{\textsf{even}} \newcommand{\evenO}{\textsf{even}_\textsf{O}} \newcommand{\evenS}{\textsf{even}_\textsf{S}} \newcommand{\Fix}{\kw{Fix}} \newcommand{\fix}{\kw{fix}} \newcommand{\for}{\textsf{for}} \newcommand{\forest}{\textsf{forest}} \newcommand{\Functor}{\kw{Functor}} \newcommand{\In}{\kw{in}} \newcommand{\ind}[3]{\kw{Ind}~[#1]\left(#2\mathrm{~:=~}#3\right)} \newcommand{\Indp}[4]{\kw{Ind}_{#4}[#1](#2:=#3)} \newcommand{\Indpstr}[5]{\kw{Ind}_{#4}[#1](#2:=#3)/{#5}} \newcommand{\injective}{\kw{injective}} \newcommand{\kw}[1]{\textsf{#1}} \newcommand{\length}{\textsf{length}} \newcommand{\letin}[3]{\kw{let}~#1:=#2~\kw{in}~#3} \newcommand{\List}{\textsf{list}} \newcommand{\lra}{\longrightarrow} \newcommand{\Match}{\kw{match}} \newcommand{\Mod}[3]{{\kw{Mod}}({#1}:{#2}\,\zeroone{:={#3}})} \newcommand{\ModImp}[3]{{\kw{Mod}}({#1}:{#2}:={#3})} \newcommand{\ModA}[2]{{\kw{ModA}}({#1}=={#2})} \newcommand{\ModS}[2]{{\kw{Mod}}({#1}:{#2})} \newcommand{\ModType}[2]{{\kw{ModType}}({#1}:={#2})} \newcommand{\mto}{.\;} \newcommand{\nat}{\textsf{nat}} \newcommand{\Nil}{\textsf{nil}} \newcommand{\nilhl}{\textsf{nil\_hl}} \newcommand{\nO}{\textsf{O}} \newcommand{\node}{\textsf{node}} \newcommand{\nS}{\textsf{S}} \newcommand{\odd}{\textsf{odd}} \newcommand{\oddS}{\textsf{odd}_\textsf{S}} \newcommand{\ovl}[1]{\overline{#1}} \newcommand{\Pair}{\textsf{pair}} \newcommand{\plus}{\mathsf{plus}} \newcommand{\SProp}{\textsf{SProp}} \newcommand{\Prop}{\textsf{Prop}} \newcommand{\return}{\kw{return}} \newcommand{\Set}{\textsf{Set}} \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{\Type}{\textsf{Type}} \newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}} \newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}} \newcommand{\WF}[2]{{\mathcal{W\!F}}(#1)[#2]} \newcommand{\WFE}[1]{\WF{E}{#1}} \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}} \newcommand{\WT}[4]{#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{\zeroone}[1]{[{#1}]} rocq-9.2.0/doc/sphinx/rocq-attrindex.rst000066400000000000000000000001551516144147600202540ustar00rootroot00000000000000:orphan: .. hack to get index in TOC .. _attribute_index: --------------- Attribute index --------------- rocq-9.2.0/doc/sphinx/rocq-cmdindex.rst000066400000000000000000000001551516144147600200450ustar00rootroot00000000000000:orphan: .. hack to get index in TOC .. _command_index: ----------------- Command index ----------------- rocq-9.2.0/doc/sphinx/rocq-exnindex.rst000066400000000000000000000001651516144147600200750ustar00rootroot00000000000000:orphan: .. hack to get index in TOC ------------------------- Errors and warnings index ------------------------- rocq-9.2.0/doc/sphinx/rocq-optindex.rst000066400000000000000000000002331516144147600201010ustar00rootroot00000000000000:orphan: .. hack to get index in TOC .. _options_index: ------------------------------- Flags, options and tables index ------------------------------- rocq-9.2.0/doc/sphinx/rocq-tacindex.rst000066400000000000000000000001431516144147600200460ustar00rootroot00000000000000:orphan: .. hack to get index in TOC .. _tactic_index: ------------- Tactic index ------------- rocq-9.2.0/doc/sphinx/std-glossindex.rst000066400000000000000000000001511516144147600202530ustar00rootroot00000000000000:orphan: .. hack to get index in TOC .. _glossary_index: -------------- Glossary index -------------- rocq-9.2.0/doc/sphinx/user-extensions/000077500000000000000000000000001516144147600177305ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/user-extensions/proof-schemes.rst000066400000000000000000000001731516144147600232350ustar00rootroot00000000000000:orphan: .. raw:: html rocq-9.2.0/doc/sphinx/user-extensions/syntax-extensions.rst000066400000000000000000003217271516144147600242210ustar00rootroot00000000000000.. _syntax-extensions-and-notation-scopes: Syntax extensions and notation scopes ===================================== In this chapter, we introduce advanced commands to modify the way Rocq parses and prints objects, i.e. the translations between the concrete and internal representations of terms and commands. The main commands to provide custom symbolic notations for terms are :cmd:`Notation` and :cmd:`Infix`; they will be described in the :ref:`next section `. There is also a variant of :cmd:`Notation` which does not modify the parser; this provides a form of :ref:`abbreviation `. It is sometimes expected that the same symbolic notation has different meanings in different contexts; to achieve this form of overloading, Rocq offers a notion of :ref:`notation scopes `. The main command to provide custom notations for tactics is :cmd:`Tactic Notation`. .. rocqtop:: none Set Printing Depth 50. .. _Notations: Notations --------- .. _BasicNotations: Basic notations ~~~~~~~~~~~~~~~ .. cmd:: Notation @notation_declaration .. insertprodn notation_declaration notation_declaration .. prodn:: notation_declaration ::= @string := @one_term {? ( {+, @syntax_modifier } ) } {? : @scope_name } Defines a *notation*, an alternate syntax for entering or displaying a specific term or term pattern. This command supports the :attr:`local` attribute, which limits its effect to the current module. If the command is inside a section, its effect is limited to the section. Specifying :token:`scope_name` associates the notation with that scope. Otherwise it is a :gdef:`lonely notation`, that is, not associated with a scope. .. todo indentation of this chapter is not consistent with other chapters. Do we have a standard? For example, the following definition permits using the infix expression :g:`A /\ B` to represent :g:`(and A B)`: .. rocqtop:: in Notation "A /\ B" := (and A B). :g:`"A /\ B"` is a *notation*, which tells how to represent the abbreviated term :g:`(and A B)`. Notations must be in double quotes, except when the abbreviation has the form of an ordinary applicative expression; see :ref:`Abbreviations`. The notation consists of *tokens* separated by spaces. Tokens which are identifiers (such as ``A``, ``x0'``, etc.) are the *parameters* of the notation. Each of them must occur at least once in the abbreviated term. The other elements of the string (such as ``/\``) are the *symbols*, which must appear literally when the notation is used. Identifiers enclosed in single quotes are treated as symbols and thus lose their role as parameters. For example: .. rocqtop:: in Notation "'IF' c1 'then' c2 'else' c3" := (c1 /\ c2 \/ ~ c1 /\ c3) (at level 200, right associativity). Symbols that start with a single quote followed by at least 2 characters must be single quoted. For example, the symbol `'ab` is represented by `''ab'` in the notation string. Quoted strings can be used in notations: they must begin and end with two double quotes. Embedded spaces in these strings are part of the string and do not contribute to the separation between notation tokens. To embed double quotes in these strings, use four double quotes (e.g. the notation :g:`"A ""I'm an """"infix"""" string symbol"" B"` defines an infix notation whose infix symbol is the string :g:`"I'm an ""infix"" string symbol"`). Symbols may contain double quotes without being strings themselves (as e.g. in symbol :g:`|"|`) but notations with such symbols can be used only for printing (see :ref:`Use of notations for printing `). In this case, no spaces are allowed in the symbol. Also, if the symbol starts with a double quote, it must be surrounded with single quotes to prevent confusion with the beginning of a string symbol. A notation binds a syntactic expression to a term, called its :gdef:`interpretation`. Unless the parser and pretty-printer of Rocq already know how to deal with the syntactic expression (such as through :cmd:`Reserved Notation` or for notations that contain only literals), explicit precedences and associativity rules have to be given. .. note:: The right-hand side of a notation is interpreted at the time the notation is given. Disambiguation of constants, :ref:`implicit arguments ` and other notations are resolved at the time of the declaration of the notation. The right-hand side is currently typed only at use time but this may change in the future. .. exn:: Unterminated string in notation Occurs when the notation string contains an unterminated quoted string, as e.g. in :g:`Reserved Notation "A ""an unended string B"`, for which the user may instead mean :g:`Reserved Notation "A ""an ended string"" B`. .. exn:: End of quoted string not followed by a space in notation. Occurs when the notation string contains a quoted string which contains a double quote not ending the quoted string, as e.g. in :g:`Reserved Notation "A ""string""! B"` or `Reserved Notation "A ""string""!"" B"`, for which the user may instead mean :g:`Reserved Notation "A ""string"""" ! B`, :g:`Reserved Notation "A ""string""""!"" B`, or :g:`Reserved Notation "A '""string""!' B`. Precedences and associativity ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mixing different symbolic notations in the same text may cause serious parsing ambiguity. To deal with the ambiguity of notations, Rocq uses precedence levels ranging from 0 to 100 (plus one extra level numbered 200) and associativity rules. Consider for example the new notation .. rocqtop:: in Notation "A \/ B" := (or A B). Clearly, an expression such as :g:`forall A:Prop, True /\ A \/ A \/ False` is ambiguous. To tell the Rocq parser how to interpret the expression, a priority between the symbols ``/\`` and ``\/`` has to be given. Assume for instance that we want conjunction to bind more than disjunction. This is expressed by assigning a precedence level to each notation, knowing that a lower level binds more than a higher level. Hence the level for disjunction must be higher than the level for conjunction. Since connectives are not tight articulation points of a text, it is reasonable to choose levels not so far from the highest level which is 100, for example 85 for disjunction and 80 for conjunction [#and_or_levels]_. Similarly, an associativity is needed to decide whether :g:`True /\ False /\ False` defaults to :g:`True /\ (False /\ False)` (right associativity) or to :g:`(True /\ False) /\ False` (left associativity). We may even consider that the expression is not well-formed and that parentheses are mandatory (this is a β€œno associativity”) [#no_associativity]_. We do not know of a special convention for the associativity of disjunction and conjunction, so let us apply right associativity (which is the choice of Rocq). Precedence levels and associativity rules of notations are specified with a list of parenthesized :n:`@syntax_modifier`\s. Here is how the previous examples refine: .. rocqtop:: in Notation "A /\ B" := (and A B) (at level 80, right associativity). Notation "A \/ B" := (or A B) (at level 85, right associativity). By default, a notation is considered nonassociative, but the precedence level is mandatory (except for special cases whose level is canonical). The level is either a number or the phrase ``next level`` whose meaning is obvious. Some :ref:`associativities are predefined ` in the ``Notations`` module. .. TODO I don't find it obvious -- CPC Complex notations ~~~~~~~~~~~~~~~~~ Notations can be made from arbitrarily complex symbols. One can for instance define prefix notations. .. rocqtop:: in Notation "~ x" := (not x) (at level 75, right associativity). One can also define notations for incomplete terms, with the hole expected to be inferred during type checking. .. rocqtop:: in Notation "x = y" := (@eq _ x y) (at level 70, no associativity). One can define *closed* notations whose both sides are symbols. In this case, the default precedence level for the inner sub-expression is 200, and the default level for the notation itself is 0. .. rocqtop:: in Notation "( x , y )" := (@pair _ _ x y). One can also define notations for binders. .. rocqtop:: in Notation "{ x : A | P }" := (sig A (fun x => P)). In the last case though, there is a conflict with the notation for type casts. The notation for type casts, as shown by the command :cmd:`Print Grammar` `constr` is at level 100. To avoid ``x : A`` being parsed as a type cast, it is necessary to put ``x`` at a level below 100, typically 99. Hence, a correct definition is the following: .. rocqtop:: reset all Notation "{ x : A | P }" := (sig A (fun x => P)) (x at level 99). More generally, it is required that notations are explicitly factorized on the left. See the next section for more about factorization. .. _NotationFactorization: Simple factorization rules ~~~~~~~~~~~~~~~~~~~~~~~~~~ Rocq extensible parsing is performed by *Camlp5* which is essentially a LL1 parser: it decides which notation to parse by looking at tokens from left to right. Hence, some care has to be taken not to hide already existing rules by new rules. Indeed notations with a common prefix but different levels can interfere with one another, making some of them unusable. For instance, a notation ``x << y`` with ``x`` and ``y`` at level 69 would be broken by another rule that puts ``y`` at another level, like ``x << y << z`` with ``x`` at level 69 and ``y`` at level 200. To avoid such issues, you should left factorize rules, that is ensure that common prefixes use the same levels. .. rocqtop:: all Reserved Notation "x << y" (at level 70). Fail Reserved Notation "x << y << z" (at level 70, y at level 200). In order to factorize the left part of the rules, the subexpression referred to by ``y`` has to be at the same level in both rules. However the default behavior puts ``y`` at the next level below 70 in the first rule (``no associativity`` is the default). To fix this, we need to force the parsing level of ``y``, as follows. .. rocqtop:: reset all Reserved Notation "x << y" (at level 70). Reserved Notation "x << y << z" (at level 70, y at next level). Or better yet, simply let the defaults ensure the best factorization. .. rocqtop:: reset all Reserved Notation "x << y" (at level 70). Reserved Notation "x << y << z". Print Notation "_ << _ << _". For the sake of factorization with Rocq predefined rules, simple rules have to be observed for notations starting with a symbol, e.g., rules starting with β€œ\ ``{``\ ” or β€œ\ ``(``\ ” should be put at level 0. The list of Rocq predefined notations can be found in the chapter on :ref:`thecoqlibrary`. .. warn:: Closed notations (i.e. starting and ending with a terminal symbol) should usually be at level 0 (default). :name: closed-notation-not-level-0 It is usually better to put closed notations, that is the ones starting and ending with a terminal symbol, at level 0. .. warn:: Notations at level 0 should be closed (first and last symbols should be terminal symbols). :name: level-0-notation-not-closed Notations at level 0 should be closed, since there is no next level for associativity. .. warn:: Postfix notations (i.e. starting with a nonterminal symbol and ending with a terminal symbol) should usually be at level 1 (default).") :name: postfix-notation-not-level-1 It is usually better to put postfix notations, that is the ones ending with a terminal symbol, at level 1. .. _UseOfNotationsForPrinting: Use of notations for printing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The command :cmd:`Notation` has an effect both on the Rocq parser and on the Rocq printer. For example: .. rocqtop:: all Check (and True True). However, printing, especially pretty-printing, also requires some care. We may want specific indentations, line breaks, alignment if on several lines, etc. For pretty-printing, Rocq relies on OCaml formatting library, which provides indentation and automatic line breaks depending on page width by means of *formatting boxes*. The default printing of notations is rudimentary. For printing a notation, a formatting box is opened in such a way that if the notation and its arguments cannot fit on a single line, a line break is inserted before the symbols of the notation and the arguments on the next lines are aligned with the argument on the first line. A first, simple control that a user can have on the printing of a notation is the insertion of spaces at some places of the notation. This is performed by adding extra spaces between the symbols and parameters: each extra space (other than the single space needed to separate the components) is interpreted as a space to be inserted by the printer. Here is an example showing how to add spaces next to the curly braces. .. rocqtop:: in Notation "{{ x : A | P }}" := (sig (fun x : A => P)) (at level 0, x at level 99). .. rocqtop:: all Check (sig (fun x : nat => x=x)). The second, more powerful control on printing is by using :n:`@syntax_modifier`\s. Here is an example .. rocqtop:: in Definition IF_then_else (P Q R:Prop) := P /\ Q \/ ~ P /\ R. .. rocqtop:: all Notation "'If' c1 'then' c2 'else' c3" := (IF_then_else c1 c2 c3) (at level 200, right associativity, format "'[v ' 'If' c1 '/' '[' 'then' c2 ']' '/' '[' 'else' c3 ']' ']'"). .. rocqtop:: all Check (IF_then_else (IF_then_else True False True) (IF_then_else True False True) (IF_then_else True False True)). A *format* tells how to control the indentation and line breaks when printing a notation. It is a string extending the notation with the possible following elements delimited by single quotes: - tokens of the form ``'/ '`` are translated into breaking points. If there is a line break, indents the number of spaces appearing after the β€œ``/``” (no indentation in the example) - tokens of the form ``'//'`` force writing on a new line - well-bracketed pairs of tokens of the form ``'[ '`` and ``']'`` are translated into printing boxes; if there is a line break, an extra indentation of the number of spaces after the β€œ``[``” is applied - well-bracketed pairs of tokens of the form ``'[hv '`` and ``']'`` are translated into horizontal-or-else-vertical printing boxes; if the content of the box does not fit on a single line, then every breaking point forces a new line and an extra indentation of the number of spaces after the β€œ``[hv``” is applied at the beginning of each new line - well-bracketed pairs of tokens of the form ``'[v '`` and ``']'`` are translated into vertical printing boxes; every breaking point forces a new line, even if the line is large enough to display the whole content of the box, and an extra indentation of the number of spaces after the β€œ``[v``” is applied at the beginning of each new line (3 spaces in the example) - extra spaces in other tokens are preserved in the output Notations disappear when a section is closed. No typing of the denoted expression is performed at definition time. Type checking is done only at the time of use of the notation. .. note:: The default for a notation is to be used both for parsing and printing. It is possible to declare a notation only for parsing by adding the option ``only parsing`` to the list of :n:`@syntax_modifier`\s of :cmd:`Notation`. Symmetrically, the ``only printing`` :n:`@syntax_modifier` can be used to declare that a notation should only be used for printing. If a notation to be used both for parsing and printing is overridden, both the parsing and printing are invalided, even if the overriding rule is only parsing. If a given notation string occurs only in ``only printing`` rules, the parser is not modified at all. Notations used for parsing, that is notations not restricted with the ``only printing`` modifier, can have only a single interpretation per scope. On the other side, notations marked with ``only printing`` can have multiple associated interpretations, even in the same scope. .. note:: When several notations can be used to print a given term, the notations which capture the largest subterm of the term are used preferentially. Here is an example: .. rocqtop:: in Notation "x < y" := (lt x y) (at level 70). Notation "x < y < z" := (lt x y /\ lt y z) (at level 70, y at next level). Check (0 < 1 /\ 1 < 2). When several notations match the same subterm, or incomparable subterms of the term to print, the notation declared most recently is selected. Moreover, reimporting a library or module declares the notations of this library or module again. If the notation is in a scope (see :ref:`Scopes`), either the scope has to be opened or a delimiter has to exist in the scope for the notation to be usable. The Infix command ~~~~~~~~~~~~~~~~~~ The :cmd:`Infix` command is a shortcut for declaring notations for infix symbols. .. cmd:: Infix @notation_declaration The command :n:`Infix @string := @one_term {? ( {+, @syntax_modifier } ) } {? : @scope_name }` is equivalent to :n:`Notation "x @string y" := (@one_term x y) {? ( {+, @syntax_modifier } ) } {? : @scope_name }` where ``x`` and ``y`` are fresh names and omitting the quotes around :n:`@string`. Here is an example: .. rocqtop:: in Infix "/\" := and (at level 80, right associativity). .. _ReservingNotations: Reserving notations ~~~~~~~~~~~~~~~~~~~ .. cmd:: Reserved Notation @string {? ( {+, @syntax_modifier } ) } A given notation may be used in different contexts. Rocq expects all uses of the notation to be defined at the same precedence and with the same associativity. To avoid giving the precedence and associativity every time, this command declares a parsing rule (:token:`string`) in advance without giving its interpretation. Here is an example from the initial state of Rocq. .. rocqtop:: in Reserved Notation "x = y" (at level 70, no associativity). Reserving a notation is also useful for simultaneously defining an inductive type or a recursive constant and a notation for it. .. note:: The notations mentioned in the module :ref:`init-notations` are reserved. Hence their precedence and associativity cannot be changed. .. cmd:: Reserved Infix @string {? ( {+, @syntax_modifier } ) } This command declares an infix parsing rule without giving its interpretation. When a format is attached to a reserved notation (with the `format` :token:`syntax_modifier`), it is used by default by all subsequent interpretations of the corresponding notation. Individual interpretations can override the format. .. warn:: Notations "a b" defined at level x and "a c" defined at level y have incompatible prefixes. One of them will likely not work. :name: notation-incompatible-prefix The two notations have a common prefix but different levels. The levels of one of the notations should be adjusted to match the other. See :ref:`factorization ` for details. Simultaneous definition of terms and notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Thanks to reserved notations, inductive and coinductive type declarations, recursive and corecursive definitions can use customized notations. To do this, insert a :token:`decl_notations` clause after the definition of the (co)inductive type or (co)recursive term (or after the definition of each of them in case of mutual definitions). Note that only syntax modifiers that do not require adding or changing a parsing rule are accepted. .. insertprodn decl_notations decl_notations .. prodn:: decl_notations ::= where @notation_declaration {* and @notation_declaration } Here are examples: .. rocqtop:: in Reserved Notation "A & B" (at level 80). .. rocqtop:: in Inductive and' (A B : Prop) : Prop := conj' : A -> B -> A & B where "A & B" := (and' A B). .. without this we get "not a truly recursive fixpoint" .. rocqtop:: none Arguments S _ : clear scopes. .. rocqtop:: in Fixpoint plus (n m : nat) {struct n} : nat := match n with | O => m | S p => S (p + m) end where "n + m" := (plus n m). Enabling and disabling notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: {| Enable | Disable } Notation {? {| @string | @qualid {* @ident__parm } } } {? := @one_term } {? ( {+, @enable_notation_flag } ) } {? {| : @scope_name | : no scope } } :name: Enable Notation; Disable Notation .. insertprodn enable_notation_flag enable_notation_flag .. prodn:: enable_notation_flag ::= all | only parsing | only printing | in custom @qualid | in constr Enables or disables notations previously defined with :cmd:`Notation` or :cmd:`Abbreviation`. Disabling a notation doesn't remove parsing rules or tokens defined by the notation. The command has no effect on notations reserved with :cmd:`Reserved Notation`. At least one of :token:`string`, :token:`qualid`, :token:`one_term` or :token:`scope_name` must be provided. When multiple clauses are provided, the notations enabled or disabled must satisfy all of their constraints. This command supports the :attr:`local` and :attr:`global` attributes. :n:`@string` Notations to enable or disable. :n:`@string` can be a single token in the notation such as "`->`" or a pattern that matches the notation. See :ref:`locating-notations`. If no :n:`{? := @one_term }` is given, the variables of the notation can be replaced by :n:`_`. :n:`@qualid {* @ident__parm }` Enable or disable :ref:`abbreviations ` whose absolute name has :n:`@qualid` as a suffix. The :n:`{* @ident__parm }` are the parameters of the abbreviation. :n:`{? := @one_term }` Enable or disable notations matching :token:`one_term`. :token:`one_term` can be written using notations or not, as well as :n:`_`, just like in the :cmd:`Notation` command. If no :n:`@string` nor :n:`@qualid {* @ident__parm }` is given, the variables of the notation can be replaced by :n:`_`. :n:`all` Enable or disable all notations meeting the given constraints, even if there are multiple ones. Otherwise, there must be a single notation meeting the constraints. :n:`only parsing` The notation is enabled or disabled only for parsing. :n:`only printing` The notation is enabled or disabled only for printing. :n:`in custom @ident` Enable or disable notations in the given :ref:`custom entry `. :n:`in constr` Enable or disable notations in the custom entry for :n:`constr`. See :ref:`custom entries `. :n:`{| : @scope_name | : no scope }` If given, only notations in scope :token:`scope_name` are affected (or :term:`lonely notations ` for :n:`no scope`). .. exn:: Unexpected only printing for an only parsing notation. Cannot enable or disable for printing a notation that was originally defined as only parsing. .. exn:: Unexpected only parsing for an only printing notation. Cannot enable or disable for parsing a notation that was originally defined as only printing. .. warn:: Found no matching notation to enable or disable. :name: Found no matching notation to enable or disable No previously defined notation satisfies the given constraints. .. exn:: More than one interpretation bound to this notation, confirm with the "all" modifier. :name: More than one interpretation bound to this notation, confirm with the all modifier Use :n:`all` to allow enabling or disabling multiple notations in a single command. .. exn:: Unknown custom entry. In :n:`in custom @ident`, :token:`ident` is not a valid custom entry name. .. exn:: No notation provided. At least one of :token:`string`, :token:`qualid`, :token:`one_term` or :token:`scope_name` must be provided. .. warn:: Activation of abbreviations does not expect mentioning a grammar entry. ``in custom`` and ``in constr`` are not compatible with :ref:`abbreviations `. .. warn:: Activation of abbreviations does not expect mentioning a scope. Scopes are not compatible with :ref:`abbreviations `. .. example:: Enabling and disabling notations .. rocqtop:: all Disable Notation "+" (all). Enable Notation "_ + _" (all) : type_scope. Disable Notation "x + y" := (sum x y). Displaying information about notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. flag:: Printing Notations This :term:`flag` controls whether to use notations for printing terms wherever possible. Default is on. .. flag:: Printing Raw Literals This :term:`flag` controls whether to use string and number notations for printing terms wherever possible (see :ref:`string-notations`). Default is off. .. flag:: Printing Parentheses When this :term:`flag` is on, parentheses are printed even if implied by associativity and precedence (applications are still printed without parentheses, i.e. `(f x) y` is printed as `f x y` regardless of this flag). Default is off. .. seealso:: :flag:`Printing All` to disable other elements in addition to notations. .. cmd:: Print Notation @string {? in custom @qualid } Displays information about the previously reserved notation string :token:`string`. :token:`ident`, if specified, is the name of the associated custom entry. See :cmd:`Declare Custom Entry`. .. rocqtop:: all Reserved Notation "x # y" (at level 123, right associativity). Print Notation "_ # _". Variables can be indicated with either `"_"` or names, as long as these can not be confused with notation symbols. When confusion may arise, for example with notation symbols that are entirely made up of letters, use single quotes to delimit those symbols. Using `"_"` is preferred, as it avoids this confusion. Note that there must always be (at least) a space between notation symbols and arguments, even when the notation format does not include those spaces. .. example:: :cmd:`Print Notation` .. rocqtop:: all Reserved Notation "x 'mod' y" (at level 40, no associativity). Print Notation "_ mod _". Print Notation "x 'mod' y". Reserved Notation "# x #" (at level 0, format "# x #"). Fail Print Notation "#x#". Print Notation "# x #". Reserved Notation "( x , y , .. , z )" (at level 0). Print Notation "( _ , _ , .. , _ )". Reserved Notation "x $ y" (at level 50, left associativity). Declare Custom Entry expr. Reserved Notation "x $ y" (in custom expr at level 30, x custom expr, y at level 80, no associativity). Print Notation "_ $ _". Print Notation "_ $ _" in custom expr. .. exn:: @string cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Occurs when :cmd:`Print Notation` can't find a notation associated with :token:`string`. This can happen, for example, when the notation does not exist in the current context, :token:`string` is not specific enough, there are missing spaces between symbols, or some symbols need to be quoted with `"'"`. .. exn:: @string cannot be interpreted as a known notation in @ident entry. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". :undocumented: .. seealso:: :cmd:`Locate` for information on the definitions and scopes associated with a notation. .. cmd:: Print Keywords Prints the current reserved :ref:`keywords ` and parser tokens, one per line. Keywords cannot be used as identifiers. .. cmd:: Print Grammar {* @ident } When no :token:`ident` is provided, shows the whole grammar (to be specific, the grammar reachable from :term:`sentence` parsing and every declared :opt:`proof mode `). `Print Grammar Full` shows the whole grammar known to the parsing engine including unreachable nonterminals. Otherwise shows the grammar for the nonterminal :token:`ident`\s, except for the following, which will include some related nonterminals: - `constr` - for :token:`term`\s - `tactic` - for currently-defined tactic notations, :token:`tactic`\s and tacticals (corresponding to :token:`ltac_expr` in the documentation). - `vernac` - for :token:`command`\s - `ltac2` - for Ltac2 notations (corresponding to :token:`ltac2_expr`) This command can display any nonterminal in the grammar reachable from `vernac_control`. Most of the grammar in the documentation was updated in 8.12 to make it accurate and readable. This was done using a new developer tool that extracts the grammar from the source code, edits it and inserts it into the documentation files. While the edited grammar is equivalent to the original, for readability some nonterminals have been renamed and others have been eliminated by substituting the nonterminal definition where the nonterminal was referenced. This command shows the original grammar, so it won't exactly match the documentation. The Rocq parser is based on Camlp5. The documentation for `Extensible grammars `_ is the most relevant but it assumes considerable knowledge. Here are the essentials: Productions can contain the following elements: - nonterminal names - identifiers in the form `[a-zA-Z0-9_]*` - `"…"` - a literal string that becomes a keyword and cannot be used as an :token:`ident`. The string doesn't have to be a valid identifier; frequently the string will contain only punctuation characters. - `IDENT "…"` - a literal string that has the form of an :token:`ident` - `OPT element` - optionally include `element` (e.g. a nonterminal, IDENT "…" or "…") - `LIST1 element` - a list of one or more `element`\s - `LIST0 element` - an optional list of `element`\s - `LIST1 element SEP sep` - a list of `element`\s separated by `sep` - `LIST0 element SEP sep` - an optional list of `element`\s separated by `sep` - `[ elements1 | elements2 | … ]` - alternatives (either `elements1` or `elements2` or …) Nonterminals can have multiple **levels** to specify precedence and associativity of its productions. This feature of grammars makes it simple to parse input such as `1+2*3` in the usual way as `1+(2*3)`. However, most nonterminals have a single level. For example, this output from `Print Grammar tactic` shows the first 3 levels for `ltac_expr`, designated as "5", "4" and "3". Level 3 is right-associative, which applies to the productions within it, such as the `try` construct:: Entry ltac_expr is [ "5" RIGHTA [ ] | "4" LEFTA [ SELF; ";"; SELF | SELF; ";"; tactic_then_locality; for_each_goal; "]" ] | "3" RIGHTA [ IDENT "try"; SELF : The interpretation of `SELF` depends on its position in the production and the associativity of the level: - At the beginning of a production, `SELF` means the next level. In the fragment shown above, the next level for `try` is "2". (This is defined by the order of appearance in the grammar or output; the levels could just as well be named "foo" and "bar".) - In the middle of a production, `SELF` means the top level ("5" in the fragment) - At the end of a production, `SELF` means the next level within `LEFTA` levels and the current level within `RIGHTA` levels. `NEXT` always means the next level. `nonterminal LEVEL "…"` is a reference to the specified level for `nonterminal`. `Associativity `_ explains `SELF` and `NEXT` in somewhat more detail. The output for `Print Grammar constr` includes :cmd:`Notation` definitions, which are dynamically added to the grammar at run time. For example, in the definition for `term`, the production on the second line shown here is defined by a :cmd:`Reserved Notation` command in `Notations.v`:: | "50" LEFTA [ SELF; "||"; NEXT Similarly, `Print Grammar tactic` includes :cmd:`Tactic Notation`\s, such as :tacn:`dintuition`. The file `doc/tools/docgram/fullGrammar `_ in the source tree extracts the full grammar for Rocq (not including notations and tactic notations defined in `*.v` files nor some optionally-loaded plugins) in a single file with minor changes to handle nonterminals using multiple levels (described in `doc/tools/docgram/README.md `_). This is complete and much easier to read than the grammar source files. `doc/tools/docgram/orderedGrammar `_ has the edited grammar that's used in the documentation. Developer documentation for parsing is in `dev/doc/parsing.md `_. .. _locating-notations: Locating notations ~~~~~~~~~~~~~~~~~~ To know to which notations a given symbol belongs to, use the :cmd:`Locate` command. You can call it on any (composite) symbol surrounded by double quotes. To locate a particular notation, use a string where the variables of the notation are replaced by β€œ``_``” and where possible single quotes inserted around identifiers or tokens starting with a single quote are dropped. .. rocqtop:: all Locate "exists". Locate "exists _ .. _ , _". Inheritance of the properties of arguments of constants bound to a notation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the right-hand side of a notation is a partially applied constant, the notation inherits the implicit arguments (see :ref:`ImplicitArguments`) and notation scopes (see :ref:`Scopes`) of the constant. For instance: .. rocqtop:: in reset Record R := {dom : Type; op : forall {A}, A -> dom}. Notation "# x" := (@op x) (at level 8). .. rocqtop:: all Check fun x:R => # x 3. As an exception, if the right-hand side is just of the form :n:`@@qualid`, this conventionally stops the inheritance of implicit arguments (but not of notation scopes). .. _notations-and-binders: Notations and binders ~~~~~~~~~~~~~~~~~~~~~ Notations can include binders. This section lists different ways to deal with binders. For further examples, see also :ref:`RecursiveNotationsWithBinders`. Binders bound in the notation and parsed as identifiers +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Here is the basic example of a notation using a binder: .. rocqtop:: in Notation "'sigma' x : A , B" := (sigT (fun x : A => B)) (at level 200, x name, A at level 200, right associativity). The binding variables in the right-hand side that occur as a parameter of the notation (here :g:`x`) dynamically bind all the occurrences in their respective binding scope after instantiation of the parameters of the notation. This means that the term bound to :g:`B` can refer to the variable name bound to :g:`x` as shown in the following application of the notation: .. rocqtop:: all Check sigma z : nat, z = 0. Note the :n:`@syntax_modifier x name` in the declaration of the notation. It tells to parse :g:`x` as a single identifier (or as the unnamed variable :g:`_`). Binders bound in the notation and parsed as patterns ++++++++++++++++++++++++++++++++++++++++++++++++++++ In the same way as patterns can be used as binders, as in :g:`fun '(x,y) => x+y` or :g:`fun '(existT _ x _) => x`, notations can be defined so that any :n:`@pattern` can be used in place of the binder. Here is an example: .. rocqtop:: in reset Notation "'subset' ' p , P " := (sig (fun p => P)) (at level 200, p pattern, format "'subset' ' p , P"). .. rocqtop:: all Check subset '(x,y), x+y=0. The :n:`@syntax_modifier p pattern` in the declaration of the notation tells to parse :g:`p` as a pattern. Note that a single variable is both an identifier and a pattern, so, e.g., the following also works: .. rocqtop:: all Check subset 'x, x=0. If one wants to prevent such a notation to be used for printing when the pattern is reduced to a single identifier, one has to use instead the :n:`@syntax_modifier p strict pattern`. For parsing, however, a ``strict pattern`` will continue to include the case of a variable. Here is an example showing the difference: .. rocqtop:: in Notation "'subset_bis' ' p , P" := (sig (fun p => P)) (at level 200, p strict pattern). Notation "'subset_bis' p , P " := (sig (fun p => P)) (at level 200, p name). .. rocqtop:: all Check subset_bis 'x, x=0. The default level for a ``pattern`` is 0. One can use a different level by using ``pattern at level`` :math:`n` where the scale is the same as the one for terms (see :ref:`init-notations`). Binders bound in the notation and parsed as terms +++++++++++++++++++++++++++++++++++++++++++++++++ Sometimes, for the sake of factorization of rules, a binder has to be parsed as a term. This is typically the case for a notation such as the following: .. rocqdoc:: Notation "{ x : A | P }" := (sig (fun x : A => P)) (at level 0, x at level 99 as name). This is so because the grammar also contains rules starting with :g:`{}` and followed by a term, such as the rule for the notation :g:`{ A } + { B }` for the constant :g:`sumbool` (see :ref:`specification`). Then, in the rule, ``x name`` is replaced by ``x at level 99 as name`` meaning that ``x`` is parsed as a term at level 99 (as done in the notation for :g:`sumbool`), but that this term has actually to be a name, i.e. an identifier or :g:`_`. The notation :g:`{ x | P }` is already defined in the standard library with the ``as name`` :n:`@syntax_modifier`. We cannot redefine it but one can define an alternative notation, say :g:`{ p such that P }`, using instead ``as pattern``. .. rocqtop:: in Notation "{ p 'such' 'that' P }" := (sig (fun p => P)) (at level 0, p at level 99 as pattern). Then, the following works: .. rocqtop:: all Check {(x,y) such that x+y=0}. To enforce that the pattern should not be used for printing when it is just a name, one could have said ``p at level 99 as strict pattern``. Note also that in the absence of a ``as name``, ``as strict pattern`` or ``as pattern`` :n:`@syntax_modifier`\s, the default is to consider sub-expressions occurring in binding position and parsed as terms to be ``as name``. Binders bound in the notation and parsed as general binders +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ It is also possible to rely on Rocq's syntax of binders using the `binder` modifier as follows: .. rocqtop:: in Notation "'myforall' p , [ P , Q ] " := (forall p, P -> Q) (p binder). In this case, all of :n:`@ident`, :n:`{@ident}`, :n:`[@ident]`, :n:`@ident:@type`, :n:`{@ident:@type}`, :n:`[@ident:@type]`, :n:`'@pattern` can be used in place of the corresponding notation variable. In particular, the binder can declare implicit arguments: .. rocqtop:: all Check fun (f : myforall {a}, [a=0, Prop]) => f eq_refl. Check myforall '((x,y):nat*nat), [ x = y, True ]. By using instead `closed binder`, the same list of binders is allowed except that :n:`@ident:@type` requires parentheses around. .. _NotationsWithBinders: Binders not bound in the notation +++++++++++++++++++++++++++++++++ We can also have binders in the right-hand side of a notation which are not themselves bound in the notation. In this case, the binders are considered up to renaming of the internal binder. E.g., for the notation .. rocqtop:: in Notation "'exists_different' n" := (exists p:nat, p<>n) (at level 200). the next command fails because p does not bind in the instance of n. .. rocqtop:: all Fail Check (exists_different p). Notations with expressions used both as binder and term +++++++++++++++++++++++++++++++++++++++++++++++++++++++ It is possible to use parameters of the notation both in term and binding position. Here is an example: .. rocqtop:: in Definition force n (P:nat -> Prop) := forall n', n' >= n -> P n'. Notation "β–’_ n P" := (force n (fun n => P)) (at level 2, n name, P at level 9, format "β–’_ n P"). .. rocqtop:: all Check exists p, β–’_p (p >= 1). More generally, the parameter can be a pattern, as in the following variant: .. rocqtop:: in reset Definition force2 q (P:nat*nat -> Prop) := (forall n', n' >= fst q -> forall p', p' >= snd q -> P (n', p')). Notation "β–’_ p P" := (force2 p (fun p => P)) (at level 2, p pattern at level 0, P at level 9, format "β–’_ p P"). .. rocqtop:: all Check exists x y, β–’_(x,y) (x >= 1 /\ y >= 2). This support is experimental. For instance, the notation is used for printing only if the occurrence of the parameter in term position comes in the right-hand side before the occurrence in binding position. .. _RecursiveNotations: Notations with recursive patterns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A mechanism is provided for declaring elementary notations with recursive patterns. The basic example is: .. rocqtop:: all Notation "[ x ; .. ; y ]" := (cons x .. (cons y nil) ..). On the right-hand side, an extra construction of the form ``.. t ..`` can be used. Notice that ``..`` is part of the Rocq syntax and it must not be confused with the three-dots notation β€œ``…``” used in this manual to denote a sequence of arbitrary size. On the left-hand side, the part β€œ``x s .. s y``” of the notation parses any number of times (but at least once) a sequence of expressions separated by the sequence of tokens ``s`` (in the example, ``s`` is just β€œ``;``”). The right-hand side must contain a subterm of the form either ``Ο†(x, .. Ο†(y,t) ..)`` or ``Ο†(y, .. Ο†(x,t) ..)`` where :math:`Ο†([~]_E , [~]_I)`, called the *iterator* of the recursive notation is an arbitrary expression with distinguished placeholders and where :math:`t` is called the *terminating expression* of the recursive notation. In the example, we choose the names :math:`x` and :math:`y` but in practice they can of course be chosen arbitrarily. Note that the placeholder :math:`[~]_I` has to occur only once but :math:`[~]_E` can occur several times. Parsing the notation produces a list of expressions which are used to fill the first placeholder of the iterating pattern which itself is repeatedly nested as many times as the length of the list, the second placeholder being the nesting point. In the innermost occurrence of the nested iterating pattern, the second placeholder is finally filled with the terminating expression. In the example above, the iterator :math:`Ο†([~]_E , [~]_I)` is :math:`cons [~]_E\, [~]_I` and the terminating expression is ``nil``. Here is another example with the pattern associating on the left: .. rocqtop:: in Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) (at level 0). Here is an example with more involved recursive patterns: .. rocqtop:: in Notation "[| t * ( x , y , .. , z ) ; ( a , b , .. , c ) * u |]" := (pair (pair .. (pair (pair t x) (pair t y)) .. (pair t z)) (pair .. (pair (pair a u) (pair b u)) .. (pair c u))) (t at level 39). To give a flavor of the extent and limits of the mechanism, here is an example showing a notation for a chain of equalities. It relies on an artificial expansion of the intended denotation so as to expose a ``Ο†(x, .. Ο†(y,t) ..)`` structure, with the drawback that if ever the beta-redexes are contracted, the notations stops to be used for printing. Support for notations defined in this way should be considered experimental. .. rocqtop:: in Notation "x βͺ― y βͺ― .. βͺ― z βͺ― t" := ((fun b A a => a <= b /\ A b) y .. ((fun b A a => a <= b /\ A b) z (fun b => b <= t)) .. x) (at level 70, y at next level, z at next level, t at next level). Note finally that notations with recursive patterns can be reserved like standard notations, they can also be declared within :ref:`notation scopes `. .. _RecursiveNotationsWithBinders: Notations with recursive patterns involving binders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Recursive notations can also be used with binders. The basic example is: .. rocqtop:: in Notation "'exists' x .. y , p" := (ex (fun x => .. (ex (fun y => p)) ..)) (at level 200, x binder, y binder, right associativity). The principle is the same as in :ref:`RecursiveNotations` except that in the iterator :math:`Ο†([~]_E , [~]_I)`, the placeholder :math:`[~]_E` can also occur in position of the binding variable of a ``fun`` or a ``forall``. To specify that the part β€œ``x .. y``” of the notation parses a sequence of binders, ``x`` and ``y`` must be marked as ``binder`` in the list of :n:`@syntax_modifier`\s of the notation. The binders of the parsed sequence are used to fill the occurrences of the first placeholder of the iterating pattern which is repeatedly nested as many times as the number of binders generated. If ever the generalization operator ``'`` (see :ref:`implicit-generalization`) is used in the binding list, the added binders are taken into account too. There are two flavors of binder parsing. If ``x`` and ``y`` are marked as binder, then a sequence such as :g:`a b c : T` will be accepted and interpreted as the sequence of binders :g:`(a:T) (b:T) (c:T)`. For instance, in the notation above, the syntax :g:`exists a b : nat, a = b` is valid. The variables ``x`` and ``y`` can also be marked as closed binder in which case only well-bracketed binders of the form :g:`(a b c:T)` or :g:`{a b c:T}` etc. are accepted. With closed binders, the recursive sequence in the left-hand side can be of the more general form ``x s .. s y`` where ``s`` is an arbitrary sequence of tokens. With open binders though, ``s`` has to be empty. Here is an example of recursive notation with closed binders: .. rocqtop:: in Notation "'mylet' f x .. y := t 'in' u":= (let f := fun x => .. (fun y => t) .. in u) (at level 200, x closed binder, y closed binder, right associativity). A recursive pattern for binders can be used in position of a recursive pattern for terms. Here is an example: .. rocqtop:: in Notation "'FUNAPP' x .. y , f" := (fun x => .. (fun y => (.. (f x) ..) y ) ..) (at level 200, x binder, y binder, right associativity). If an occurrence of the :math:`[~]_E` is not in position of a binding variable but of a term, it is the name used in the binding which is used. Here is an example: .. rocqtop:: in Notation "'exists_non_null' x .. y , P" := (ex (fun x => x <> 0 /\ .. (ex (fun y => y <> 0 /\ P)) ..)) (at level 200, x binder). Predefined entries ~~~~~~~~~~~~~~~~~~ By default, sub-expressions are parsed as terms and the corresponding grammar entry is called ``constr``. However, one may sometimes want to restrict the syntax of terms in a notation. For instance, the following notation will accept to parse only global reference in position of :g:`x`: .. rocqtop:: in Notation "'apply' f a1 .. an" := (.. (f a1) .. an) (at level 10, f global, a1, an at level 9). In addition to ``global``, one can restrict the syntax of a sub-expression by using the entry names ``ident``, ``name`` or ``pattern`` already seen in :ref:`NotationsWithBinders`, even when the corresponding expression is not used as a binder in the right-hand side. E.g.: .. rocqtop:: in Notation "'apply_id' f a1 .. an" := (.. (f a1) .. an) (at level 10, f ident, a1, an at level 9). .. _custom-entries: Custom entries ~~~~~~~~~~~~~~ .. cmd:: Declare Custom Entry @ident Defines new grammar entries, called *custom entries*, that can later be referred to using the entry name :n:`custom @qualid`. Custom entry names are qualified names based on the module they're declared in: `Declare Custom Entry e` in module `M` produces an entry whose full name is `M.e`, and may be accessed by the short name `e` before `End M` and after `Import M`. This command supports the :attr:`local` attribute, which limits the entry to the current module. Non-local custom entries survive module closing and are declared when a file is Required. .. example:: For instance, we may want to define an ad hoc parser for arithmetical operations and proceed as follows: .. rocqtop:: reset all Inductive Expr := | One : Expr | Mul : Expr -> Expr -> Expr | Add : Expr -> Expr -> Expr. Declare Custom Entry expr. Notation "[ e ]" := e (e custom expr at level 3). Notation "1" := One (in custom expr at level 0). Notation "x y" := (Mul x y) (in custom expr at level 1, left associativity). Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity). Notation "( x )" := x (in custom expr, x at level 3). Notation "{ x }" := x (in custom expr, x constr). Notation "x" := x (in custom expr at level 0, x ident). Axiom f : nat -> Expr. Check fun x y z => [1 + y z + {f x}]. Unset Printing Notations. Check fun x y z => [1 + y z + {f x}]. Set Printing Notations. Check fun e => match e with | [1 + 1] => [1] | [x y + z] => [x + y z] | y => [y + e] end. Custom entries have levels, like the main grammar of terms and grammar of patterns have. The lower level is 0 and this is the level used by default to put rules delimited with tokens on both ends. The level is left to be inferred by Rocq when using :n:`in custom @ident`. The level is otherwise given explicitly by using the syntax :n:`in custom @ident at level @natural`, where :n:`@natural` refers to the level. Levels are cumulative: a notation at level ``n`` of which the left end is a term shall use rules at level less than ``n`` to parse this subterm. More precisely, it shall use rules at level strictly less than ``n`` if the rule is declared with ``right associativity`` and rules at level less or equal than ``n`` if the rule is declared with ``left associativity``. Similarly, a notation at level ``n`` of which the right end is a term shall use by default rules at level strictly less than ``n`` to parse this subterm if the rule is declared left associative and rules at level less or equal than ``n`` if the rule is declared right associative. This is what happens for instance in the rule .. rocqtop:: in Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity). where ``x`` is any expression parsed in entry ``expr`` at level less or equal than ``2`` (including, recursively, the given rule) and ``y`` is any expression parsed in entry ``expr`` at level strictly less than ``2``. Rules associated with an entry can refer different sub-entries. The grammar entry name ``constr`` can be used to refer to the main grammar of term as in the rule .. rocqtop:: in Notation "{ x }" := x (in custom expr at level 0, x constr). which indicates that the subterm ``x`` should be parsed using the main grammar. If not indicated, the level is computed as for notations in ``constr``, e.g. using 200 as default level for inner sub-expressions. The level can otherwise be indicated explicitly by using ``constr at level n`` for some ``n``, or ``constr at next level``. Conversely, custom entries can be used to parse sub-expressions of the main grammar, or from another custom entry as is the case in .. rocqtop:: in Notation "[ e ]" := e (e custom expr at level 3). to indicate that ``e`` has to be parsed at level ``3`` of the grammar associated with the custom entry ``expr``. The level can be omitted, as in .. rocqdoc:: Notation "[ e ]" := e (e custom expr). in which case Rocq infer it. If the sub-expression is at a border of the notation (as e.g. ``x`` and ``y`` in ``x + y``), the level is determined by the associativity. If the sub-expression is not at the border of the notation (as e.g. ``e`` in ``"[ e ]"``), the level is inferred to be the highest level used for the entry. In particular, this level depends on the highest level existing in the entry at the time of use of the notation. In the absence of an explicit entry for parsing or printing a sub-expression of a notation in a custom entry, the default is to consider that this sub-expression is parsed or printed in the same custom entry where the notation is defined. In particular, if ``x at level n`` is used for a sub-expression of a notation defined in custom entry ``foo``, it shall be understood the same as ``x custom foo at level n``. In general, rules are required to be *productive* on the right-hand side, i.e. that they are bound to an expression which is not reduced to a single variable. If the rule is not productive on the right-hand side, as it is the case above for .. rocqtop:: in Notation "( x )" := x (in custom expr at level 0, x at level 3). and .. rocqtop:: in Notation "{ x }" := x (in custom expr at level 0, x constr). it is used as a *grammar coercion* which means that it is used to parse or print an expression which is not available in the current grammar at the current level of parsing or printing for this grammar but which is available in another grammar or in another level of the current grammar. For instance, .. rocqtop:: in Notation "( x )" := x (in custom expr at level 0, x at level 3). tells that parentheses can be inserted to parse or print an expression declared at level ``3`` of ``expr`` whenever this expression is expected to be used as a subterm at level 0 or 1. This allows for instance to parse and print :g:`Add x y` as a subterm of :g:`Mul (Add x y) z` using the syntax ``(x + y) z``. Similarly, .. rocqtop:: in Notation "{ x }" := x (in custom expr at level 0, x constr). gives a way to let any arbitrary expression which is not handled by the custom entry ``expr`` be parsed or printed by the main grammar of term up to the insertion of a pair of curly brackets. Another special situation is when parsing global references or identifiers. To indicate that a custom entry should parse identifiers, use the following form: .. rocqtop:: reset none Declare Custom Entry expr. .. rocqtop:: in Notation "x" := x (in custom expr at level 0, x ident). Similarly, to indicate that a custom entry should parse global references (i.e. qualified or unqualified identifiers), use the following form: .. rocqtop:: reset none Declare Custom Entry expr. .. rocqtop:: in Notation "x" := x (in custom expr at level 0, x global). .. cmd:: Print Custom Grammar @qualid This displays the state of the grammar for terms associated with the custom entry :token:`ident`. .. _NotationSyntax: Syntax ~~~~~~~ Here are the syntax elements used by the various notation commands. .. insertprodn syntax_modifier level .. prodn:: syntax_modifier ::= at level @natural | in custom @qualid {? at level @natural } | {+, @ident } {| at @level | in scope @ident } | @ident at @level {? @binder_interp } | @ident @explicit_subentry | @ident @binder_interp | left associativity | right associativity | no associativity | only parsing | format @string | only printing explicit_subentry ::= ident | name | global | bigint | strict pattern {? at level @natural } | binder | closed binder | constr {? at @level } {? @binder_interp } | custom @qualid {? at @level } {? @binder_interp } | pattern {? at level @natural } binder_interp ::= as ident | as name | as pattern | as strict pattern level ::= level @natural | next level Note that `_` by itself is a valid :n:`@name` but is not a valid :n:`@ident`. .. 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. .. note:: Some examples of Notation may be found in the files composing the initial state of Rocq (see directory :file:`$ROCQLIB/theories/Init`). .. note:: The notation ``"{ x }"`` has a special status in the main grammars of terms and patterns so that complex notations of the form ``"x + { y }"`` or ``"x * { y }"`` can be nested with correct precedences. Especially, every notation involving a pattern of the form ``"{ x }"`` is parsed as a notation where the pattern ``"{ x }"`` has been simply replaced by ``"x"`` and the curly braces are parsed separately. E.g. ``"y + { z }"`` is not parsed as a term of the given form but as a term of the form ``"y + z"`` where ``z`` has been parsed using the rule parsing ``"{ x }"``. Especially, level and precedences for a rule including patterns of the form ``"{ x }"`` are relative not to the textual notation but to the notation where the curly braces have been removed (e.g. the level and the associativity given to some notation, say ``"{ y } & { z }"`` in fact applies to the underlying ``"{ x }"``\-free rule which is ``"y & z"``). .. note:: Notations such as ``"( p | q )"`` (or starting with ``"( x | "``, more generally) are deprecated as they conflict with the syntax for nested disjunctive patterns (see :ref:`extendedpatternmatching`), and are not honored in pattern expressions. .. warn:: Use of @string Notation is deprecated as it is inconsistent with pattern syntax. This warning is disabled by default to avoid spurious diagnostics due to legacy notation in the Rocq standard library. It can be turned on with the ``-w disj-pattern-notation`` flag. .. exn:: Unknown custom entry: @ident. Occurs when :cmd:`Notation` or :cmd:`Print Notation` can't find the custom entry given by the user. .. _Scopes: Notation scopes --------------- A :gdef:`notation scope` is a set of notations for terms with their interpretations. Notation scopes provide a weak, purely syntactic form of notation overloading: a symbol may refer to different definitions depending on which notation scopes are currently open. For instance, the infix symbol ``+`` can be used to refer to distinct definitions of the addition operator, such as for natural numbers, integers or reals. Notation scopes can include an interpretation for numbers and strings with the :cmd:`Number Notation` and :cmd:`String Notation` commands. .. insertprodn scope scope_key .. prodn:: scope ::= @scope_name | @scope_key scope_name ::= @ident scope_key ::= @ident Each notation scope has a single :token:`scope_name`, which by convention ends with the suffix "_scope", as in "nat_scope". One or more :token:`scope_key`\s (delimiting keys) may be associated with a notation scope with the :cmd:`Delimit Scope` command. Most commands use :token:`scope_name`; :token:`scope_key`\s are used within :token:`term`\s. .. cmd:: Declare Scope @scope_name Declares a new notation scope. Note that the initial state of Rocq declares the following notation scopes: ``bool_scope``, ``byte_scope``, ``core_scope``, ``dec_int_scope``, ``dec_uint_scope``, ``function_scope``, ``hex_int_scope``, ``hex_nat_scope``, ``hex_uint_scope``, ``list_scope``, ``nat_scope``, ``type_scope``. Use commands such as :cmd:`Notation` to add notations to the scope. .. exn:: Scope names should not start with an underscore. Scope names starting with an underscore would make the :g:`%_` syntax ambiguous. Global interpretation rules for notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ At any time, the interpretation of a notation for a term is done within a *stack* of notation scopes and :term:`lonely notations `. If a notation is defined in multiple scopes, Rocq uses the interpretation from the most recently opened notation scope or declared lonely notation. Note that "stack" is a misleading name. Each scope or lonely notation can only appear in the stack once. New items are pushed onto the top of the stack, except that adding a item that's already in the stack moves it to the top of the stack instead. Scopes are removed by name (e.g. by :cmd:`Close Scope`) wherever they are in the stack, rather than through "pop" operations. Use the :cmd:`Print Visibility` command to display the current notation scope stack. The initial state of Rocq has the following scopes opened: ``core_scope``, ``function_scope``, ``type_scope`` and ``nat_scope``, ``nat_scope`` being the top of the scopes stack. .. cmd:: Open Scope @scope Adds a scope to the notation scope stack. If the scope is already present, the command moves it to the top of the stack. If the command appears in a section: By default, the scope is only added within the section. Specifying :attr:`global` marks the scope for export as part of the current module. Specifying :attr:`local` behaves like the default. If the command does not appear in a section: By default, the scope marks the scope for export as part of the current module. Specifying :attr:`local` prevents exporting the scope. Specifying :attr:`global` behaves like the default. .. cmd:: Close Scope @scope Removes a scope from the notation scope stack. If the command appears in a section: By default, the scope is only removed within the section. Specifying :attr:`global` marks the scope removal for export as part of the current module. Specifying :attr:`local` behaves like the default. If the command does not appear in a section: By default, the scope marks the scope removal for export as part of the current module. Specifying :attr:`local` prevents exporting the removal. Specifying :attr:`global` behaves like the default. .. todo: Strange notion, exporting something that _removes_ a scope. See https://github.com/rocq-prover/rocq/pull/11718#discussion_r413667817 .. _LocalInterpretationRulesForNotations: Local interpretation rules for notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In addition to the global rules of interpretation of notations, some ways to change the interpretation of subterms are available. Opening a notation scope locally ++++++++++++++++++++++++++++++++ .. insertprodn term_scope term_scope .. prodn:: term_scope ::= @term1 % @scope_key | @term1 %_ @scope_key The notation scope stack can be locally extended within a :token:`term` with the syntax :n:`(@term)%@scope_key` (or simply :n:`@term0%@scope_key` for atomic terms). In this case, :n:`@term` is interpreted in the scope stack extended with the scope bound to :n:`@scope_key`. The term :n:`@term0%_@scope_key` is interpreted similarly to :n:`@term0%@scope_key` except that the scope stack is only temporarily extended for the head of :n:`@term0`, rather than all its subterms. .. cmd:: Delimit Scope @scope_name with @scope_key Binds the delimiting key :token:`scope_key` to a scope. .. cmd:: Undelimit Scope @scope_name Removes the delimiting keys associated with a scope. .. exn:: Scope delimiters should not start with an underscore. Scope delimiters starting with an underscore would make the :g:`%_` syntax ambiguous. The arguments of an :ref:`abbreviation ` can be interpreted in a scope stack locally extended with a given scope by using the modifier :n:`{+, @ident } in scope @scope_name`.s Binding types or coercion classes to notation scopes ++++++++++++++++++++++++++++++++++++++++++++++++++++ .. cmd:: Bind Scope @scope_name with {+ @coercion_class } Binds the notation scope :token:`scope_name` to the type or coercion class :token:`coercion_class`. When bound, arguments of that type for any function will be interpreted in that scope by default. This default can be overridden for individual functions with the :cmd:`Arguments` command. See :ref:`binding_to_scope` for details. The association may be convenient when a notation scope is naturally associated with a :token:`type` (e.g. `nat` and the natural numbers). Whether the argument of a function has some type ``type`` is determined statically. For instance, if ``f`` is a polymorphic function of type :g:`forall X:Type, X -> X` and type :g:`t` is bound to a scope ``scope``, then :g:`a` of type :g:`t` in :g:`f t a` is not recognized as an argument to be interpreted in scope ``scope``. In explicit :ref:`casts ` :n:`@term : @coercion_class`, the :n:`term` is interpreted in the :token:`scope_name` associated with :n:`@coercion_class`. This command supports the :attr:`local`, :attr:`global`, :attr:`add_top` and :attr:`add_bottom` attributes. .. attr:: add_top add_bottom These :ref:`attributes ` allow adding additional bindings at the top or bottom of the stack of already declared bindings. In absence of such attributes, any new binding clears the previous ones. This makes it possible to bind multiple scopes to the same :token:`coercion_class`. .. example:: Binding scopes to a type Let's declare two scopes with a notation in each and an arbitrary function on type ``bool``. .. rocqtop:: in reset Declare Scope T_scope. Declare Scope F_scope. Notation "#" := true (only parsing) : T_scope. Notation "#" := false (only parsing) : F_scope. Parameter f : bool -> bool. By default, the argument of ``f`` is interpreted in the currently opened scopes. .. rocqtop:: all Open Scope T_scope. Check f #. Open Scope F_scope. Check f #. This can be changed by binding scopes to the type ``bool``. .. rocqtop:: all Bind Scope T_scope with bool. Check f #. When multiple scopes are attached to a type, notations are interpreted in the first scope containing them, from the top of the stack. .. rocqtop:: all #[add_top] Bind Scope F_scope with bool. Check f #. Notation "##" := (negb false) (only parsing) : T_scope. Check f ##. Bindings for functions can be displayed with the :cmd:`About` command. .. rocqtop:: all About f. Bindings are also used in casts. .. rocqtop:: all Close Scope F_scope. Check #. Check # : bool. .. note:: Such stacks of scopes can be handy to share notations between multiple types. For instance, the scope ``T_scope`` above could contain many generic notations used for both the ``bool`` and ``nat`` types, while the scope ``F_scope`` could override some of these notations specifically for ``bool`` and another ``F'_scope`` could override them specifically for ``nat``, which could then be bound to ``%F'_scope%T_scope``. .. note:: When active, a bound scope has effect on all defined functions (even if they are defined after the :cmd:`Bind Scope` directive), except if argument scopes were assigned explicitly using the :cmd:`Arguments` command. .. note:: The scopes ``type_scope`` and ``function_scope`` also have a local effect on interpretation. See the next section. The ``type_scope`` notation scope ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. index:: type_scope The scope ``type_scope`` has a special status. It is a primitive interpretation scope which is temporarily activated each time a subterm of an expression is expected to be a type. It is delimited by the key ``type``, and bound to the coercion class ``Sortclass``. It is also used in certain situations where an expression is statically known to be a type, including the conclusion and the type of hypotheses within an Ltac goal match (see :ref:`ltac-match-goal`), the statement of a theorem, the type of a definition, the type of a binder, the domain and codomain of implication, the codomain of products, and more generally any type argument of a declared or defined constant. The ``function_scope`` notation scope ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. index:: function_scope The scope ``function_scope`` also has a special status. It is temporarily activated each time the argument of a global reference is recognized to be a ``Funclass`` instance, i.e., of type :g:`forall x:A, B` or :g:`A -> B`. .. _notation-scopes: Notation scopes used in the standard library of Rocq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We give an overview of the scopes used in the standard library of Rocq. For a complete list of notations in each scope, use the commands :cmd:`Print Scopes` or :cmd:`Print Scope`. ``type_scope`` This scope includes infix * for product types and infix + for sum types. It is delimited by the key ``type``, and bound to the coercion class ``Sortclass``, as described above. ``function_scope`` This scope is delimited by the key ``function``, and bound to the coercion class ``Funclass``, as described above. ``nat_scope`` This scope includes the standard arithmetical operators and relations on type nat. Positive integer numbers in this scope are mapped to their canonical representent built from :g:`O` and :g:`S`. The scope is delimited by the key ``nat``, and bound to the type :g:`nat` (see above). ``N_scope`` This scope includes the standard arithmetical operators and relations on type :g:`N` (binary natural numbers). It is delimited by the key ``N`` and comes with an interpretation for numbers as closed terms of type :g:`N`. ``Z_scope`` This scope includes the standard arithmetical operators and relations on type :g:`Z` (binary integer numbers). It is delimited by the key ``Z`` and comes with an interpretation for numbers as closed terms of type :g:`Z`. ``positive_scope`` This scope includes the standard arithmetical operators and relations on type :g:`positive` (binary strictly positive numbers). It is delimited by key ``positive`` and comes with an interpretation for numbers as closed terms of type :g:`positive`. ``Q_scope`` This scope includes the standard arithmetical operators and relations on type :g:`Q` (rational numbers defined as fractions of an integer and a strictly positive integer modulo the equality of the numerator- denominator cross-product) and comes with an interpretation for numbers as closed terms of type :g:`Q`. ``Qc_scope`` This scope includes the standard arithmetical operators and relations on the type :g:`Qc` of rational numbers defined as the type of irreducible fractions of an integer and a strictly positive integer. ``R_scope`` This scope includes the standard arithmetical operators and relations on type :g:`R` (axiomatic real numbers). It is delimited by the key ``R`` and comes with an interpretation for numbers using the :g:`IZR` morphism from binary integer numbers to :g:`R` and :g:`Z.pow_pos` for potential exponent parts. ``bool_scope`` This scope includes notations for the boolean operators. It is delimited by the key ``bool``, and bound to the type :g:`bool` (see above). ``list_scope`` This scope includes notations for the list operators. It is delimited by the key ``list``, and bound to the type :g:`list` (see above). ``core_scope`` This scope includes the notation for pairs. It is delimited by the key ``core``. ``string_scope`` This scope includes notation for strings as elements of the type string. Special characters and escaping follow Rocq conventions on strings (see :ref:`lexical-conventions`). Especially, there is no convention to visualize non printable characters of a string. The file :file:`String.v` shows an example that contains quotes, a newline and a beep (i.e. the ASCII character of code 7). ``char_scope`` This scope includes interpretation for all strings of the form ``"c"`` where :g:`c` is an ASCII character, or of the form ``"nnn"`` where nnn is a three-digit number (possibly with leading 0s), or of the form ``""""``. Their respective denotations are the ASCII code of :g:`c`, the decimal ASCII code ``nnn``, or the ascii code of the character ``"`` (i.e. the ASCII code 34), all of them being represented in the type :g:`ascii`. Displaying information about scopes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. cmd:: Print Visibility {? @scope_name } Displays the current notation scope stack. The top of the stack is displayed last. Notations in scopes whose interpretation is hidden by the same notation in a more recently opened scope are not displayed. Hence each notation is displayed only once. If :n:`@scope_name` is specified, displays the current notation scope stack as if the scope :n:`@scope_name` is pushed on top of the stack. This is useful to see how a subterm occurring locally in the scope is interpreted. .. cmd:: Print Scopes Displays, for each existing notation scope, all accessible notations (whether or not currently in the notation scope stack), the most-recently defined delimiting key and the class the notation scope is bound to. The display also includes :term:`lonely notations `. .. todo should the command report all delimiting keys? Use the :cmd:`Print Visibility` command to display the current notation scope stack. .. cmd:: Print Scope @scope_name Displays all notations defined in the notation scope :n:`@scope_name`. It also displays the delimiting key and the class to which the scope is bound, if any. .. _Abbreviations: Abbreviations -------------- .. cmd:: Abbreviation @ident {* @ident__parm } := @one_term {? ( {+, @syntax_modifier } ) } .. deprecated .. cmd:: Notation @ident {* @ident__parm } := @one_term {? ( {+, @syntax_modifier } ) } .. todo: for some reason, Sphinx doesn't complain about a duplicate name if :name: is omitted Defines an abbreviation :token:`ident` with the parameters :n:`@ident__parm`. An *abbreviation* is a name, possibly applied to arguments, that denotes a (presumably) more complex expression. Here are examples: .. rocqtop:: none Require Import ListDef. Set Printing Notations. .. rocqtop:: in Abbreviation Nlist := (list nat). .. rocqtop:: all Check 1 :: 2 :: 3 :: nil. .. rocqtop:: in Abbreviation reflexive R := (forall x, R x x). .. rocqtop:: all Check forall A:Prop, A <-> A. Check reflexive iff. .. rocqtop:: in Abbreviation Plus1 B := (Nat.add B 1). .. rocqtop:: all Compute (Plus1 3). This command supports the :attr:`local`, :attr:`export` and :attr:`global` attributes. :attr:`local` limits the notation to the current module or section. With :attr:`export` the abbreviation is only used for printing when it is imported (but it can still be accessed by its qualified name when not imported). With :attr:`global` requiring the module containing the abbreviation is enough to make it used by printing (NB: for "only parsing" abbreviations there is no difference between :attr:`export` and :attr:`global`). The default is :attr:`export` outside sections and :attr:`local` in sections, and :attr:`local` is the only supported locality in sections. An abbreviation expects no precedence nor associativity, since it is parsed as an usual application. Abbreviations are used as much as possible by the Rocq printers unless the modifier ``(only parsing)`` is given. An abbreviation is bound to an absolute name as an ordinary definition is and it also can be referred to by a qualified name. Abbreviations are syntactic in the sense that they are bound to expressions which are not typed at the time of the definition of the abbreviation but at the time they are used. Especially, abbreviations can be bound to terms with holes (i.e. with β€œ``_``”). For example: .. rocqtop:: none reset Set Strict Implicit. Set Printing Depth 50. .. rocqtop:: in Definition explicit_id (A:Set) (a:A) := a. .. rocqtop:: in Abbreviation id := (explicit_id _). .. rocqtop:: all Check (id 0). No typing of the denoted expression is performed at definition time. Type checking is done only at the time of use of the abbreviation. Like for notations, if the right-hand side of an abbreviation is a partially applied constant, the abbreviation inherits the implicit arguments and notation scopes of the constant. As an exception, if the right-hand side is just of the form :n:`@@qualid`, this conventionally stops the inheritance of implicit arguments. Like for notations, it is possible to bind binders in abbreviations. Here is an example: .. rocqtop:: in reset Definition force2 q (P:nat*nat -> Prop) := (forall n', n' >= fst q -> forall p', p' >= snd q -> P (n', p')). Abbreviation F p P := (force2 p (fun p => P)). Check exists x y, F (x,y) (x >= 1 /\ y >= 2). .. extracted from Gallina chapter Numbers and strings ------------------- .. insertprodn number_or_string number_or_string .. prodn:: number_or_string ::= @number | @string Numbers and strings have no predefined semantics in the calculus. They are merely notations that can be bound to objects through the notation mechanism. Initially, numbers are bound to :n:`nat`, Peano’s representation of natural numbers (seeΒ :ref:`datatypes`). .. note:: Negative integers are not at the same level as :n:`@natural`, for this would make precedence unnatural. .. _number-notations: Number notations ~~~~~~~~~~~~~~~~ .. cmd:: Number Notation @qualid__type @qualid__parse @qualid__print {? ( {+, @number_modifier } ) } : @scope_name .. insertprodn number_modifier number_string_via .. prodn:: number_modifier ::= warning after @bignat | abstract after @bignat | @number_string_via number_string_via ::= via @qualid mapping [ {+, {| @qualid => @qualid | [ @qualid ] => @qualid } } ] Customizes the way number literals are parsed and printed within the current :term:`notation scope`. :n:`@qualid__type` the name of an inductive type, while :n:`@qualid__parse` and :n:`@qualid__print` should be the names of the parsing and printing functions, respectively. The parsing function :n:`@qualid__parse` should have one of the following types: * :n:`Number.int -> @qualid__type'` * :n:`Number.uint -> @qualid__type'` * :n:`Z -> @qualid__type'` * :n:`PrimInt63.pos_neg_int63 -> @qualid__type'` * :n:`PrimFloat.float -> @qualid__type'` * :n:`Number.number -> @qualid__type'` where :n:`@qualid__type'` is one of * :n:`@qualid__type` * :n:`option @qualid__type` * :n:`result @qualid__type _` And the printing function :n:`@qualid__print` should have one of the following types: * :n:`@qualid__type' -> Number.int` * :n:`@qualid__type' -> Number.uint` * :n:`@qualid__type' -> Z` * :n:`@qualid__type' -> PrimInt63.pos_neg_int63` * :n:`@qualid__type' -> PrimFloat.float` * :n:`@qualid__type' -> Number.number` When parsing, the application of the parsing function :n:`@qualid__parse` to the number will be fully reduced, and universes of the resulting term will be refreshed. Note that only fully-reduced ground terms (terms containing only function application, constructors, inductive type families, sorts, primitive integers, primitive floats, primitive arrays and type constants for primitive types) will be considered for printing. .. note:: Instead of an inductive type, :n:`@qualid__type` can be :n:`PrimInt63.int` or :n:`PrimFloat.float`, in which case :n:`@qualid__print` takes :n:`PrimInt63.int_wrapper` or :n:`PrimFloat.float_wrapper` as input instead of :n:`PrimInt63.int` or :n:`PrimFloat.float`. See below for an :ref:`example `. .. note:: When :n:`PrimFloat.float` is used as input type of :n:`@qualid__parse`, only numerical values will be parsed this way, (no infinities nor NaN). Similarly, printers :n:`@qualid__print` with output type :n:`PrimFloat.float` or :n:`option PrimFloat.float` are ignored when they return non numerical values. .. _number-string-via: :n:`via @qualid__ind mapping [ {+, @qualid__constant => @qualid__constructor } ]` When using this option, :n:`@qualid__type` no longer needs to be an inductive type and is instead mapped to the inductive type :n:`@qualid__ind` according to the provided list of pairs, whose first component :n:`@qualid__constant` is a constant of type :n:`@qualid__type` (or a function of type :n:`{* _ -> } @qualid__type`) and the second a constructor of type :n:`@qualid__ind`. The type :n:`@qualid__type` is then replaced by :n:`@qualid__ind` in the above parser and printer types. When :n:`@qualid__constant` is surrounded by square brackets, all the implicit arguments of :n:`@qualid__constant` (whether maximally inserted or not) are ignored when translating to :n:`@qualid__constructor` (i.e., before applying :n:`@qualid__print`) and replaced with implicit argument holes :g:`_` when translating from :n:`@qualid__constructor` to :n:`@qualid__constant` (after :n:`@qualid__parse`). See below for an :ref:`example `. .. note:: The implicit status of the arguments is considered only at notation declaration time, any further modification of this status has no impact on the previously declared notations. .. note:: In case of multiple implicit options (for instance :g:`Arguments eq_refl {A}%_type_scope {x}, [_] _`), an argument is considered implicit when it is implicit in any of the options. .. note:: To use a :token:`sort` as the target type :n:`@qualid__type`, use an :ref:`abbreviation ` as in the :ref:`example below `. :n:`warning after @bignat` displays a warning message about a possible stack overflow when calling :n:`@qualid__parse` to parse a literal larger than :n:`@bignat`. .. warn:: Stack overflow or segmentation fault happens when working with large numbers in @type (threshold may vary depending on your system limits and on the command executed). When a :cmd:`Number Notation` is registered in the current scope with :n:`(warning after @bignat)`, this warning is emitted when parsing a number greater than or equal to :token:`bignat`. :n:`abstract after @bignat` returns :n:`(@qualid__parse m)` when parsing a literal :n:`m` that's greater than :n:`@bignat` rather than reducing it to a normal form. Here :g:`m` will be a :g:`Number.int`, :g:`Number.uint`, :g:`Z` or :g:`Number.number`, depending on the type of the parsing function :n:`@qualid__parse`. This allows for a more compact representation of literals in types such as :g:`nat`, and limits parse failures due to stack overflow. Note that a warning will be emitted when an integer larger than :token:`bignat` is parsed. Note that :n:`(abstract after @bignat)` has no effect when :n:`@qualid__parse` lands in an :g:`option` type. .. warn:: To avoid stack overflow, large numbers in @type are interpreted as applications of @qualid__parse. When a :cmd:`Number Notation` is registered in the current scope with :n:`(abstract after @bignat)`, this warning is emitted when parsing a number greater than or equal to :token:`bignat`. Typically, this indicates that the fully computed representation of numbers can be so large that non-tail-recursive OCaml functions run out of stack space when trying to walk them. .. warn:: The 'abstract after' directive has no effect when the parsing function (@qualid__parse) targets an option type. As noted above, the :n:`(abstract after @natural)` directive has no effect when :n:`@qualid__parse` lands in an :g:`option` type. .. exn:: 'via' and 'abstract' cannot be used together. With the :n:`abstract after` option, the parser function :n:`@qualid__parse` does not reduce large numbers to a normal form, which prevents doing the translation given in the :n:`mapping` list. .. exn:: Cannot interpret this number as a value of type @type The number notation registered for :token:`type` does not support the given number. This error is given when the interpretation function returns :g:`None` (when :n:`@qualid__type'` is :n:`option @qualid__type`) or :g:`Error e` (when :n:`@qualid__type'` is :n:`result @qualid__type _`, in which case `e` will be printed and appended to the error message), or if the interpretation is registered only for integers or non-negative integers, and the given number has a fractional or exponent part or is negative. .. exn:: overflow in int63 literal @bigint The constant's absolute value is too big to fit into a 63-bit integer :n:`PrimInt63.int`. .. exn:: @qualid__parse should go from Number.int to @type or (option @type). Instead of Number.int, the types Number.uint or Z or PrimInt63.pos_neg_int63 or PrimFloat.float or Number.number could be used (you may need to require BinNums or Number or PrimInt63 or PrimFloat first). The parsing function given to the :cmd:`Number Notation` command is not of the right type. .. exn:: @qualid__print should go from @type to Number.int or (option Number.int). Instead of Number.int, the types Number.uint or Z or PrimInt63.pos_neg_int63 or Number.number could be used (you may need to require BinNums or Number or PrimInt63 first). The printing function given to the :cmd:`Number Notation` command is not of the right type. .. exn:: Unexpected term @term while parsing a number notation. Parsing functions must always return ground terms, made up of function application, constructors, inductive type families, sorts and primitive integers. Parsing functions may not return terms containing axioms, bare (co)fixpoints, lambdas, etc. .. exn:: Unexpected non-option term @term while parsing a number notation. Parsing functions expected to return an :g:`option` must always return a concrete :g:`Some` or :g:`None` when applied to a concrete number expressed as a (hexa)decimal. They may not return opaque constants. .. exn:: Multiple 'via' options. At most one :g:`via` option can be given. .. exn:: Multiple 'warning after' or 'abstract after' options. At most one :g:`warning after` or :g:`abstract after` option can be given. .. _string-notations: String notations ~~~~~~~~~~~~~~~~ .. cmd:: String Notation @qualid__type @qualid__parse @qualid__print {? ( @number_string_via ) } : @scope_name Allows the user to customize how strings are parsed and printed. :n:`@qualid__type` the name of an inductive type, while :n:`@qualid__parse` and :n:`@qualid__print` should be the names of the parsing and printing functions, respectively. The parsing function :n:`@qualid__parse` should have one of the following types: * :n:`Byte.byte -> @qualid__type'` * :n:`list Byte.byte -> @qualid__type` * :n:`PrimString.string -> @qualid__type` where :n:`@qualid__type'` is one of * :n:`@qualid__type` * :n:`option @qualid__type` * :n:`result @qualid__type _` The printing function :n:`@qualid__print` should have one of the following types: * :n:`@qualid__type' -> Byte.byte` * :n:`@qualid__type -> list Byte.byte` * :n:`@qualid__type -> PrimString.string` When parsing, the application of the parsing function :n:`@qualid__parse` to the string will be fully reduced, and universes of the resulting term will be refreshed. Note that only fully-reduced ground terms (terms containing only function application, constructors, inductive type families, sorts, primitive integers, primitive floats, primitive strings, primitive arrays and type constants for primitive types) will be considered for printing. :n:`via @qualid__ind mapping [ {+, @qualid__constant => @qualid__constructor } ]` works as for :ref:`number notations above `. .. exn:: Cannot interpret this string as a value of type @type The string notation registered for :token:`type` does not support the given string. This error is given when the interpretation function returns :g:`None` or :g:`Error e`. .. exn:: @qualid__parse should go from Byte.byte, (list Byte.byte), or PrimString.string to @type or (option @type). The parsing function given to the :cmd:`String Notation` command is not of the right type. .. exn:: @qualid__print should go from @type to T or (option T), where T is either Byte.byte, (list Byte.byte), or PrimString.string. The printing function given to the :cmd:`String Notation` command is not of the right type. .. exn:: Unexpected term @term while parsing a string notation. Parsing functions must always return ground terms, made up of function application, constructors, inductive type families, sorts, primitive integers and primitive strings. Parsing functions may not return terms containing axioms, bare (co)fixpoints, lambdas, etc. .. exn:: Unexpected non-option term @term while parsing a string notation. Parsing functions expected to return an :g:`option` must always return a concrete :g:`Some` or :g:`None` when applied to a concrete string expressed as a decimal. They may not return opaque constants. .. note:: Number or string notations for parameterized inductive types can be added by declaring an :ref:`abbreviation ` for the inductive which instantiates all parameters. See :ref:`example below `. The following errors apply to both string and number notations: .. exn:: @type is not an inductive type. String and number notations can only be declared for inductive types. Declare string or numeral notations for non-inductive types using :n:`@number_string_via`. .. exn:: @qualid was already mapped to @qualid and cannot be remapped to @qualid Duplicates are not allowed in the :n:`mapping` list. .. exn:: Missing mapping for constructor @qualid A mapping should be provided for :n:`@qualid` in the :n:`mapping` list. .. warn:: @type was already mapped to @type, mapping it also to @type might yield ill typed terms when using the notation. Two pairs in the :n:`mapping` list associate types that might be incompatible. .. warn:: Type of @qualid seems incompatible with the type of @qualid. Expected type is: @type instead of @type. This might yield ill typed terms when using the notation. A mapping given in the :n:`mapping` list associates a constant with a seemingly incompatible constructor. .. exn:: Cannot interpret in @scope_name because @qualid could not be found in the current environment. The inductive type used to register the string or number notation is no longer available in the environment. Most likely, this is because the notation was declared inside a functor for an inductive type inside the functor. This use case is not currently supported. Alternatively, you might be trying to use a primitive token notation from a plugin which forgot to specify which module you must :g:`Require` for access to that notation. .. exn:: Syntax error: [prim:reference] expected after 'Notation' (in [vernac:command]). The type passed to :cmd:`String Notation` or :cmd:`Number Notation` must be a single qualified identifier. .. exn:: Syntax error: [prim:reference] expected after [prim:reference] (in [vernac:command]). Both functions passed to :cmd:`String Notation` or :cmd:`Number Notation` must be single qualified identifiers. .. todo: generally we don't document syntax errors. Is this a good execption? .. exn:: @qualid is bound to a notation that does not denote a reference. Identifiers passed to :cmd:`String Notation` or :cmd:`Number Notation` must be global references, or notations which evaluate to single qualified identifiers. .. todo note on "single qualified identifiers" https://github.com/rocq-prover/rocq/pull/11718#discussion_r415076703 .. example:: Number Notation for radix 3 The following example parses and prints natural numbers whose digits are :g:`0`, :g:`1` or :g:`2` as terms of the following inductive type encoding radix 3 numbers. .. rocqtop:: in reset Inductive radix3 : Set := | x0 : radix3 | x3 : radix3 -> radix3 | x3p1 : radix3 -> radix3 | x3p2 : radix3 -> radix3. We first define a parsing function .. rocqtop:: in Definition of_uint_dec (u : Decimal.uint) : option radix3 := let fix f u := match u with | Decimal.Nil => Some x0 | Decimal.D0 u => match f u with Some u => Some (x3 u) | None => None end | Decimal.D1 u => match f u with Some u => Some (x3p1 u) | None => None end | Decimal.D2 u => match f u with Some u => Some (x3p2 u) | None => None end | _ => None end in f (Decimal.rev u). Definition of_uint (u : Number.uint) : option radix3 := match u with Number.UIntDecimal u => of_uint_dec u | Number.UIntHexadecimal _ => None end. and a printing function .. rocqtop:: in Definition to_uint_dec (x : radix3) : Decimal.uint := let fix f x := match x with | x0 => Decimal.Nil | x3 x => Decimal.D0 (f x) | x3p1 x => Decimal.D1 (f x) | x3p2 x => Decimal.D2 (f x) end in Decimal.rev (f x). Definition to_uint (x : radix3) : Number.uint := Number.UIntDecimal (to_uint_dec x). before declaring the notation .. rocqtop:: in Declare Scope radix3_scope. Open Scope radix3_scope. Number Notation radix3 of_uint to_uint : radix3_scope. We can check the printer .. rocqtop:: all Check x3p2 (x3p1 x0). and the parser .. rocqtop:: all Set Printing All. Check 120. Digits other than :g:`0`, :g:`1` and :g:`2` are rejected. .. rocqtop:: all fail Check 3. .. _example-number-notation-primitive-int: .. example:: Number Notation for primitive integers This shows the use of the primitive integers :n:`PrimInt63.int` as :n:`@qualid__type`. It is the way parsing and printing of primitive integers are actually implemented in `PrimInt63.v`. .. rocqtop:: in reset Require Import PrimInt63. Definition parser (x : pos_neg_int63) : option int := match x with Pos p => Some p | Neg _ => None end. Definition printer (x : int_wrapper) : pos_neg_int63 := Pos (int_wrap x). Number Notation int parser printer : uint63_scope. .. _example-number-notation-non-inductive: .. example:: Number Notation for a non-inductive type The following example encodes the terms in the form :g:`sum unit ( ... (sum unit unit) ... )` as the number of units in the term. For instance :g:`sum unit (sum unit unit)` is encoded as :g:`3` while :g:`unit` is :g:`1` and :g:`0` stands for :g:`Empty_set`. The inductive :g:`I` will be used as :n:`@qualid__ind`. .. rocqtop:: in reset Inductive I := Iempty : I | Iunit : I | Isum : I -> I -> I. We then define :n:`@qualid__parse` and :n:`@qualid__print` .. rocqtop:: in Definition of_uint (x : Number.uint) : I := let fix f n := match n with | O => Iempty | S O => Iunit | S n => Isum Iunit (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with | Iempty => O | Iunit => 1 | Isum i1 i2 => f i1 + f i2 end in Nat.to_num_uint (f x). Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B. the number notation itself .. rocqtop:: in Abbreviation nSet := Set (only parsing). Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum]) : type_scope. and check the printer .. rocqtop:: all Local Open Scope type_scope. Check sum unit (sum unit unit). and the parser .. rocqtop:: all Set Printing All. Check 3. .. _example-number-notation-implicit-args: .. example:: Number Notation with implicit arguments The following example parses and prints natural numbers between :g:`0` and :g:`n-1` as terms of type :g:`Fin.t n`. .. rocqtop:: all reset warn Module Fin. Inductive t : nat -> Set := F1 : forall n, t (S n) | FS : forall n, t n -> t (S n). End Fin. Arguments Fin.F1 {_}. Arguments Fin.FS {_}. Note the implicit arguments of :g:`Fin.F1` and :g:`Fin.FS`, which won't appear in the corresponding inductive type. .. rocqtop:: in Inductive I := I1 : I | IS : I -> I. Definition of_uint (x : Number.uint) : I := let fix f n := match n with O => I1 | S n => IS (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with I1 => O | IS n => S (f n) end in Nat.to_num_uint (f x). Declare Scope fin_scope. Delimit Scope fin_scope with fin. Local Open Scope fin_scope. Number Notation Fin.t of_uint to_uint (via I mapping [[Fin.F1] => I1, [Fin.FS] => IS]) : fin_scope. Now :g:`2` is parsed as :g:`Fin.FS (Fin.FS Fin.F1)`, that is :g:`@Fin.FS _ (@Fin.FS _ (@Fin.F1 _))`. .. rocqtop:: all Check 2. which can be of type :g:`Fin.t 3` (numbers :g:`0`, :g:`1` and :g:`2`) .. rocqtop:: all Check 2 : Fin.t 3. but cannot be of type :g:`Fin.t 2` (only :g:`0` and :g:`1`) .. rocqtop:: all fail Check 2 : Fin.t 2. .. _example-string-notation-parameterized-inductive: .. example:: String Notation with a parameterized inductive type The parameter :g:`Byte.byte` for the parameterized inductive type :g:`list` is given through an :ref:`abbreviation `. .. rocqtop:: in reset Abbreviation string := (list Byte.byte) (only parsing). Definition id_string := @id string. String Notation string id_string id_string : list_scope. .. rocqtop:: all Check "abc"%list. .. _TacticNotation: Tactic Notations ----------------- Tactic notations allow customizing the syntax of tactics. .. todo move to the Ltac chapter .. todo to discuss after moving to the ltac chapter: any words of wisdom on when to use tactic notation vs ltac? can you run into problems if you shadow another tactic or tactic notation? If so, how to avoid ambiguity? .. cmd:: Tactic Notation {? ( at level @natural ) } {+ @ltac_production_item } := @ltac_expr .. insertprodn ltac_production_item ltac_production_item .. prodn:: ltac_production_item ::= @string | @ident {? ( @ident {? , @string } ) } Defines a *tactic notation*, which extends the parsing and pretty-printing of tactics. This command supports the :attr:`local` attribute, which limits the notation to the current module. :token:`natural` The parsing precedence to assign to the notation. This information is particularly relevant for notations for tacticals. Levels can be in the range 0 .. 5 (default is 5). :n:`{+ @ltac_production_item }` The notation syntax. Notations for simple tactics should begin with a :token:`string`. Note that `Tactic Notation foo := idtac` is not valid; it should be `Tactic Notation "foo" := idtac`. .. todo: "Tactic Notation constr := idtac" gives a nice message, would be good to show that message for the "foo" example above. :token:`string` represents a literal value in the notation :n:`@ident` is the name of a grammar nonterminal listed in the table below. In a few cases, to maintain backward compatibility, the name differs from the nonterminal name used elsewhere in the documentation. :n:`( @ident__parm {? , @string__s } )` :n:`@ident__parm` is the parameter name associated with :n:`@ident`. The :n:`@string__s` is the separator string to use when :n:`@ident` specifies a list with separators (i.e. :n:`@ident` ends with `_list_sep`). :n:`@ltac_expr` The tactic expression to substitute for the notation. :n:`@ident__parm` tokens appearing in :n:`@ltac_expr` are substituted with the associated nonterminal value. For example, the following command defines a notation with a single parameter `x`. .. rocqtop:: in Tactic Notation "destruct_with_eqn" constr(x) := destruct x eqn:?. For a complex example, examine the 16 `Tactic Notation "setoid_replace"`\s defined in :file:`$ROCQLIB/theories/Classes/SetoidTactics.v`, which are designed to accept any subset of 4 optional parameters. The nonterminals that can specified in the tactic notation are: .. Some missing entries: "ref", "string", "preident", "int" and "ssrpatternarg". (from reading .v files). Looks like any string passed to "make0" in the code is valid. But do we want to support all these? @JasonGross's opinion here: https://github.com/rocq-prover/rocq/pull/11718#discussion_r415387421 .. list-table:: :header-rows: 1 * - Specified :token:`ident` - Parsed as - Interpreted as - as in tactic * - ``ident`` - :token:`ident` - a user-given name - :tacn:`intro` * - ``simple_intropattern`` - :token:`simple_intropattern` - an introduction pattern - :tacn:`assert` `as` * - ``hyp`` - :token:`ident` - a hypothesis defined in context - :tacn:`clear` * - ``reference`` - :token:`qualid` - a qualified identifier - name of an |Ltac|-defined tactic * - ``smart_global`` - :token:`reference` - a global reference of term - :tacn:`unfold`, :tacn:`with_strategy` * - ``constr`` - :token:`one_term` - a term - :tacn:`exact` * - ``open_constr`` - :token:`one_term` - a term where all `_` which are not resolved by unification become evars; typeclass resolution is not triggered - tacn:`epose`, tacn:`eapply` * - ``uconstr`` - :token:`one_term` - an untyped term - :tacn:`refine` * - ``integer`` - :token:`integer` - an integer - * - ``int_or_var`` - :token:`int_or_var` - an integer - :tacn:`do` * - ``strategy_level`` - :token:`strategy_level` - a strategy level - * - ``strategy_level_or_var`` - :token:`strategy_level_or_var` - a strategy level - :tacn:`with_strategy` * - ``tactic`` - :token:`ltac_expr` - a tactic - * - ``tactic``\ *n* (*n* in 0..5) - :token:`ltac_expr`\ *n* - a tactic at level *n* - * - *entry*\ ``_list`` - :n:`{* entry }` - a list of how *entry* is interpreted - * - ``ne_``\ *entry*\ ``_list`` - :n:`{+ entry }` - a list of how *entry* is interpreted - * - *entry*\ ``_list_sep`` - :n:`{*s entry }` - a list of how *entry* is interpreted - * - ``ne_``\ *entry*\ ``_list_sep`` - :n:`{+s entry }` - a list of how *entry* is interpreted - .. todo: notation doesn't support italics .. note:: In order to be bound in tactic definitions, each syntactic entry for argument type must include the case of a simple |Ltac| identifier as part of what it parses. This is naturally the case for ``ident``, ``simple_intropattern``, ``reference``, ``constr``, ... but not for ``integer`` nor for ``strategy_level``. This is the reason for introducing special entries ``int_or_var`` and ``strategy_level_or_var`` which evaluate to integers or strategy levels only, respectively, but which syntactically includes identifiers in order to be usable in tactic definitions. .. note:: The *entry*\ ``_list*`` and ``ne_``\ *entry*\ ``_list*`` entries can be used in primitive tactics or in other notations at places where a list of the underlying entry can be used: entry is either ``constr``, ``hyp``, ``integer``, ``reference``, ``strategy_level``, ``strategy_level_or_var``, or ``int_or_var``. .. rubric:: Footnotes .. [#and_or_levels] which are the levels effectively chosen in the current implementation of Rocq .. [#no_associativity] Rocq accepts notations declared as nonassociative but the parser on which Rocq is built, namely Camlp5, currently does not implement ``no associativity`` and replaces it with ``left associativity``; hence it is the same for Rocq: ``no associativity`` is in fact ``left associativity`` for the purposes of parsing rocq-9.2.0/doc/sphinx/using/000077500000000000000000000000001516144147600157025ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/using/libraries/000077500000000000000000000000001516144147600176565ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/using/libraries/funind.rst000066400000000000000000000361701516144147600217020ustar00rootroot00000000000000Functional induction ==================== .. note:: The functional induction (FunInd) plugin is legacy functionality. For new code and new projects, we recommend `Equations `_, a more powerful plugin that provides most of FunInd's features. It can be installed through the `Coq Platform `_. Refer to the `Equations documentation `_ to learn more. FunInd is not deprecated and not planned for removal yet because porting code from FunInd to Equations can be difficult (due to differences in the generated induction principles). .. note:: The tactics described in this chapter require the Stdlib library. .. _advanced-recursive-functions: Advanced recursive functions ---------------------------- The following command is available when the ``FunInd`` library has been loaded via ``From Stdlib Require Import FunInd``: .. cmd:: Function @fix_definition {* with @fix_definition } This command is a generalization of :cmd:`Fixpoint`. It is a wrapper for several ways of defining a function *and* other useful related objects, namely: an induction principle that reflects the recursive structure of the function (see :tacn:`functional induction`) and its fixpoint equality. This defines a function similar to those defined by :cmd:`Fixpoint`. As in :cmd:`Fixpoint`, the decreasing argument must be given (unless the function is not recursive), but it might not necessarily be *structurally* decreasing. Use the :n:`@fixannot` clause to name the decreasing argument *and* to describe which kind of decreasing criteria to use to ensure termination of recursive calls. :cmd:`Function` also supports the :n:`with` clause to create mutually recursive definitions, however this feature is limited to structurally recursive functions (i.e. when :n:`@fixannot` is a :n:`struct` clause). See :tacn:`functional induction` and :cmd:`Functional Scheme` for how to use the induction principle to reason easily about the function. The form of the :n:`@fixannot` clause determines which definition mechanism :cmd:`Function` uses. (Note that references to :n:`ident` below refer to the name of the function being defined.): * If :n:`@fixannot` is not specified, :cmd:`Function` defines the nonrecursive function :token:`ident` as if it was declared with :cmd:`Definition`. In addition, the following are defined: + :token:`ident`\ ``_rect``, :token:`ident`\ ``_rec`` and :token:`ident`\ ``_ind``, which reflect the pattern matching structure of :token:`term` (see :cmd:`Inductive`); + The inductive :n:`R_@ident` corresponding to the graph of :token:`ident` (silently); + :token:`ident`\ ``_complete`` and :token:`ident`\ ``_correct`` which are inversion information linking the function and its graph. * If :n:`{ struct ... }` is specified, :cmd:`Function` defines the structural recursive function :token:`ident` as if it was declared with :cmd:`Fixpoint`. In addition, the following are defined: + The same objects as above; + The fixpoint equation of :token:`ident`: :n:`@ident`\ ``_equation``. * If :n:`{ measure ... }` or :n:`{ wf ... }` are specified, :cmd:`Function` defines a recursive function by well-founded recursion. The module ``Recdef`` of the standard library must be loaded for this feature. + :n:`{measure @one_term__1 {? @ident } {? @one_term__2 } }`\: where :n:`@ident` is the decreasing argument and :n:`@one_term__1` is a function from the type of :n:`@ident` to :g:`nat` for which the decreasing argument decreases (for the :g:`lt` order on :g:`nat`) for each recursive call of the function. The parameters of the function are bound in :n:`@one_term__1`. + :n:`{wf @one_term @ident }`\: where :n:`@ident` is the decreasing argument and :n:`@one_term` is an ordering relation on the type of :n:`@ident` (i.e. of type `T`\ :math:`_{\sf ident}` β†’ `T`\ :math:`_{\sf ident}` β†’ ``Prop``) for which the decreasing argument decreases for each recursive call of the function. The order must be well-founded. The parameters of the function are bound in :n:`@one_term`. If the clause is ``measure`` or ``wf``, the user is left with some proof obligations that will be used to define the function. These proofs are: proofs that each recursive call is actually decreasing with respect to the given criteria, and (if the criteria is `wf`) a proof that the ordering relation is well-founded. Once proof obligations are discharged, the following objects are defined: + The same objects as with the ``struct`` clause; + The lemma :n:`@ident`\ ``_tcc`` which collects all proof obligations in one property; + The lemmas :n:`@ident`\ ``_terminate`` and :n:`@ident`\ ``_F`` which will be inlined during extraction of :n:`@ident`. The way this recursive function is defined is the subject of several papers by Yves Bertot and Antonia Balaa on the one hand, and Gilles Barthe, Julien Forest, David Pichardie, and Vlad Rusu on the other hand. .. note:: To obtain the right principle, it is better to put rigid parameters of the function as first arguments. For example it is better to define plus like this: .. rocqtop:: reset none extra-stdlib From Stdlib Require Import FunInd. .. rocqtop:: all extra-stdlib Function plus (m n : nat) {struct n} : nat := match n with | 0 => m | S p => S (plus m p) end. than like this: .. rocqtop:: reset none extra-stdlib From Stdlib Require Import FunInd. .. rocqtop:: all extra-stdlib Function plus (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (plus p m) end. *Limitations* :token:`term` must be built as a *pure pattern matching tree* (:g:`match … with`) with applications only *at the end* of each branch. :cmd:`Function` does not support partial application of the function being defined. Thus, the following example cannot be accepted due to the presence of partial application of :g:`wrong` in the body of :g:`wrong`: .. rocqtop:: none extra-stdlib From Stdlib Require List. Import List.ListNotations. .. rocqtop:: all fail extra-stdlib Function wrong (C:nat) : nat := List.hd 0 (List.map wrong (C::nil)). For now, dependent cases are not treated for non-structurally terminating functions. .. exn:: The recursive argument must be specified. :undocumented: .. exn:: No argument name @ident. :undocumented: .. exn:: Cannot use mutual definition with well-founded recursion or measure. :undocumented: .. warn:: Cannot define graph for @ident. The generation of the graph relation (:n:`R_@ident`) used to compute the induction scheme of ident raised a typing error. Only :token:`ident` is defined; the induction scheme will not be generated. This error happens generally when: - the definition uses pattern matching on dependent types, which :cmd:`Function` cannot deal with yet. - the definition is not a *pattern matching tree* as explained above. .. warn:: Cannot define principle(s) for @ident. The generation of the graph relation (:n:`R_@ident`) succeeded but the induction principle could not be built. Only :token:`ident` is defined. Please report. .. warn:: Cannot build functional inversion principle. :tacn:`functional inversion` will not be available for the function. Tactics ------- .. tacn:: functional induction @term {? using @one_term_with_bindings } {? as @simple_intropattern } Performs case analysis and induction following the definition of a function :token:`qualid`, which must be fully applied to its arguments as part of :token:`term`. It uses a principle generated by :cmd:`Function` or :cmd:`Functional Scheme`. Note that this tactic is only available after a ``From Stdlib Require Import FunInd``. See the :cmd:`Function` command. :n:`using @one_term` Specifies the induction principle (aka elimination scheme). :n:`with @bindings` Specifies the arguments of the induction principle. :n:`as @simple_intropattern` Provides names for the introduced variables. .. example:: .. rocqtop:: reset all extra-stdlib From Stdlib Require Import FunInd. Functional Scheme minus_ind := Induction for minus Sort Prop. Check minus_ind. Lemma le_minus (n m:nat) : n - m <= n. functional induction (minus n m) using minus_ind; simpl; auto. Qed. .. note:: :n:`functional induction (f x1 x2 x3)` is actually a wrapper for :n:`induction x1, x2, x3, (f x1 x2 x3) using @qualid` followed by a cleaning phase, where :n:`@qualid` is the induction principle registered for :g:`f` (by the :cmd:`Function` or :cmd:`Functional Scheme` command) corresponding to the sort of the goal. Therefore :tacn:`functional induction` may fail if the induction scheme :n:`@qualid` is not defined. .. note:: There is a difference between obtaining an induction scheme for a function by using :cmd:`Function` and by using :cmd:`Functional Scheme` after a normal definition using :cmd:`Fixpoint` or :cmd:`Definition`. .. exn:: Cannot find induction information on @qualid. :undocumented: .. exn:: Not the right number of induction arguments. :undocumented: .. tacn:: soft functional induction {+ @one_term } {? using @one_term_with_bindings } {? as @simple_intropattern } :undocumented: .. tacn:: functional inversion {| @ident | @natural } {? @qualid } Performs inversion on hypothesis :n:`@ident` of the form :n:`@qualid {+ @term} = @term` or :n:`@term = @qualid {+ @term}` when :n:`@qualid` is defined using :cmd:`Function`. Note that this tactic is only available after a ``From Stdlib Require Import FunInd``. :n:`@natural` Does the same thing as :n:`intros until @natural` followed by :n:`functional inversion @ident` where :token:`ident` is the identifier for the last introduced hypothesis. :n:`@qualid` If the hypothesis :token:`ident` (or :token:`natural`) has a type of the form :n:`@qualid__1 {+ @term__i } = @qualid__2 {+ @term__j }` where :n:`@qualid__1` and :n:`@qualid__2` are valid candidates to functional inversion, this variant allows choosing which :token:`qualid` is inverted. .. exn:: Hypothesis @ident must contain at least one Function. :undocumented: .. exn:: Cannot find inversion information for hypothesis @ident. This error may be raised when some inversion lemma failed to be generated by Function. .. _functional-scheme: Generation of induction principles with ``Functional`` ``Scheme`` ----------------------------------------------------------------- .. cmd:: Functional Scheme @func_scheme_def {* with @func_scheme_def } .. insertprodn func_scheme_def func_scheme_def .. prodn:: func_scheme_def ::= @ident := Induction for @qualid Sort @sort_quality_or_set An experimental high-level tool that automatically generates induction principles corresponding to functions that may be mutually recursive. The command generates an induction principle named :n:`@ident` for each given function named :n:`@qualid`. The :n:`@qualid`\s must be given in the same order as when they were defined. Note the command must be made available via ``From Stdlib`` :cmd:`Require Import` ``FunInd``. .. warning:: There is a difference between induction schemes generated by the command :cmd:`Functional Scheme` and these generated by the :cmd:`Function`. Indeed, :cmd:`Function` generally produces smaller principles that are closer to how a user would implement them. See :ref:`advanced-recursive-functions` for details. .. example:: Induction scheme for div2. We define the function div2 as follows: .. rocqtop:: all extra-stdlib From Stdlib Require Import FunInd. From Stdlib Require Import Arith. Fixpoint div2 (n:nat) : nat := match n with | O => 0 | S O => 0 | S (S n') => S (div2 n') end. The definition of a principle of induction corresponding to the recursive structure of `div2` is defined by the command: .. rocqtop:: all extra-stdlib Functional Scheme div2_ind := Induction for div2 Sort Prop. You may now look at the type of div2_ind: .. rocqtop:: all extra-stdlib Check div2_ind. We can now prove the following lemma using this principle: .. rocqtop:: all extra-stdlib Lemma div2_le' : forall n:nat, div2 n <= n. intro n. pattern n, (div2 n). apply div2_ind; intros. auto with arith. auto with arith. simpl; auto with arith. Qed. We can use directly the functional induction (:tacn:`functional induction`) tactic instead of the pattern/apply trick: .. rocqtop:: all extra-stdlib Reset div2_le'. Lemma div2_le : forall n:nat, div2 n <= n. intro n. functional induction (div2 n). auto with arith. auto with arith. auto with arith. Qed. .. example:: Induction scheme for tree_size. We define trees by the following mutual inductive type: .. original LaTeX had "Variable" instead of "Axiom", which generates an ugly warning .. rocqtop:: reset all extra-stdlib Axiom A : Set. Inductive tree : Set := node : A -> forest -> tree with forest : Set := | empty : forest | cons : tree -> forest -> forest. We define the function tree_size that computes the size of a tree or a forest. Note that we use ``Function`` which generally produces better principles. .. rocqtop:: all extra-stdlib From Stdlib Require Import FunInd. Function tree_size (t:tree) : nat := match t with | node A f => S (forest_size f) end with forest_size (f:forest) : nat := match f with | empty => 0 | cons t f' => (tree_size t + forest_size f') end. Notice that the induction principles ``tree_size_ind`` and ``forest_size_ind`` generated by ``Function`` are not mutual. .. rocqtop:: all extra-stdlib Check tree_size_ind. Mutual induction principles following the recursive structure of ``tree_size`` and ``forest_size`` can be generated by the following command: .. rocqtop:: all extra-stdlib Functional Scheme tree_size_ind2 := Induction for tree_size Sort Prop with forest_size_ind2 := Induction for forest_size Sort Prop. You may now look at the type of `tree_size_ind2`: .. rocqtop:: all extra-stdlib Check tree_size_ind2. .. cmd:: Functional Case @func_scheme_def Generate graph for @qualid Internal debugging commands. Flags ----- .. flag:: Functional Induction Rewrite Dependent Makes FunInd use dependent :tacn:`subst` instead of :tacn:`simple subst`. On by default. .. flag:: Function_raw_tcc When Function is using a well-founded relation, this flag (when set) prevents the post-processing of the tcc (type checking conditions) generated for termination. (The post-processing is basically conjunction splitting + auto.) Off by default. rocq-9.2.0/doc/sphinx/using/libraries/index.rst000066400000000000000000000042141516144147600215200ustar00rootroot00000000000000.. _libraries: ===================== Libraries and plugins ===================== Libraries and plugins contain compiled Rocq scripts with useful definitions, theorems, notations and settings that can be loaded at runtime. In addition, plugins can add new tactics and commands written in OCaml. The Rocq Prover is distributed with a standard library and a set of internal plugins (most of which provide tactics that have already been presented in :ref:`tactics`). This chapter presents this standard library and some of these internal plugins which provide features that are not tactics. In addition, Rocq has a rich ecosystem of external libraries and plugins. These libraries and plugins can be browsed online through the `Rocq Package Index `_ and installed with the `opam package manager `_. :gdef:`Libraries ` contain only compiled Rocq scripts. :gdef:`Plugins ` can also include compiled OCaml code that can change the behavior of Rocq. Both are :term:`packages `. While users configure and load them identically, there are a few differences to consider: - Nearly all plugins add functionality that could not be added otherwise and they likely add new top-level commands or tactics. - Compared to libraries, plugins can change Rocq's behavior in many possibly unexpected ways. Therefore, using a plugin requires a higher degree of trust in its authors than is needed for libraries. If desired, you can mitigate trust issues by running :ref:`rocqchk` on compiled files produced from Rocq scripts that load plugins. (`rocqchk` doesn't load plugins, so they won't be part of trusted code base.) - Plugins that aren't in Rocq's `CI (continuous integration) system `_ are more likely to break across major versions due to source code changes to Rocq. You may want to consider this before adopting a new plugin for your project. .. toctree:: :maxdepth: 1 ../../language/coq-library ../../addendum/extraction ../../addendum/miscellaneous-extensions funind writing rocq-9.2.0/doc/sphinx/using/libraries/writing.rst000066400000000000000000000144551516144147600221040ustar00rootroot00000000000000Writing Rocq libraries and plugins =================================== This section presents the part of the Rocq language that is useful only to library and plugin authors. A tutorial for writing Rocq plugins is available in the Rocq repository in `doc/plugin_tutorial `_. Deprecating library objects, tactics or library files ----------------------------------------------------- You may use the following :term:`attribute` to deprecate a notation, tactic, definition, axiom, theorem or file. When renaming a definition or theorem, you can introduce a deprecated compatibility alias using :cmd:`Abbreviation` (see :ref:`the example below `). .. attr:: deprecated ( {? since = @string , } {? note = @string , } {? use = @qualid } ) :name: deprecated At least one of :n:`since` or :n:`note` must be present. If both are present, either one may appear first and they must be separated by a comma. If they are present, they will be used in the warning message, and :n:`since` will also be used in the warning name and categories. Spaces inside :n:`since` are changed to hyphens. This attribute is supported by the following commands: :cmd:`Ltac`, :cmd:`Tactic Notation`, :cmd:`Notation`, :cmd:`Infix`, :cmd:`Ltac2`, :cmd:`Ltac2 Notation`, :cmd:`Ltac2 external`, :cmd:`Definition`, :cmd:`Theorem`, and similar commands. To attach it to a compiled library file, use :cmd:`Attributes`. The :n:`use` attribute can be used for commands such as :cmd:`Definition`, :cmd:`Theorem`, and :cmd:`Abbreviation`. Its value must refer to an existing constant or abbreviation and is printed as part of the warning message as well as used by LSP based user interfaces as a quick fix. It can trigger the following warnings: .. warn:: Library File @qualid is deprecated since @string__since. @string__note. Use @qualid__use instead. Library File (transitively required) @qualid is deprecated since @string__since. @string__note. Use @qualid__use instead. Ltac2 alias @qualid is deprecated since @string__since. @string__note. Ltac2 definition @qualid is deprecated since @string__since. @string__note. Ltac2 notation {+ @ltac2_syntax_class } is deprecated since @string__since. @string__note. Ltac2 constructor @qualid is deprecated since @string__since. @string__note. Notation @string is deprecated since @string__since. @string__note. Use @qualid__use instead. Tactic @qualid is deprecated since @string__since. @string__note. Tactic Notation @qualid is deprecated since @string__since. @string__note. :n:`@qualid` or :n:`@string` is the notation, :n:`@string__since` is the version number, :n:`@string__note` is the note (usually explains the replacement). Explicitly :cmd:`Require`\ing a file that has been deprecated, using the :cmd:`Attributes` command, triggers a ``Library File`` deprecation warning. Requiring a deprecated file, even indirectly through a chain of :cmd:`Require`\s, will produce a ``Library File (transitively required)`` deprecation warning if the :opt:`Warnings` option "deprecated-transitive-library-file" is set (it is "-deprecated-transitive-library-file" by default, silencing the warning). .. note:: Rocq and its standard library follow this deprecation policy: * it should always be possible for a project written in Rocq to be compatible with two successive major versions, * features must be deprecated in one major version before removal, * Rocq developers should provide an estimate of the required effort to fix a project with respect to a given change, * breaking changes should be clearly documented in the public release notes, along with recommendations on how to fix a project if it breaks. See :cite:`Zimmermann19`, Section 3.6.3, for more details. Triggering warning for library objects or library files ------------------------------------------------------- You may use the following :term:`attribute` to trigger a warning on a notation, definition, axiom, theorem or file. .. attr:: warn ( note = @string , {? cats = @string } ) :name: warn The :n:`note` field will be used as the warning message, and :n:`cats` is a comma separated list of categories to be used in the warning name and categories. Leading and trailing spaces in each category are trimmed, whereas internal spaces are changed to hyphens. If both :n:`note` and :n:`cats` are present, either one may appear first and they must be separated by a comma. This attribute is supported by the following commands: :cmd:`Notation`, :cmd:`Infix`, :cmd:`Definition`, :cmd:`Theorem`, and similar commands. To attach it to a compiled library file, use :cmd:`Attributes`. It can trigger the following warning: .. warn:: @string__note :n:`@string__note` is the note. It's common practice to start it with a capital and end it with a period. Explicitly :cmd:`Require`\ing a file that has a warn message set using the :cmd:`Attributes` command, triggers a ``warn-library-file`` warning. Requiring such a file, even indirectly through a chain of :cmd:`Require`\s, will produce a ``warn-transitive-library-file`` warning if the :opt:`Warnings` option "warn-transitive-library-file" is set (it is "-warn-transitive-library-file" by default, silencing the warning). .. example:: Deprecating a tactic. .. rocqtop:: all abort warn #[deprecated(since="mylib 0.9", note="Use idtac instead.")] Ltac foo := idtac. Goal True. Proof. now foo. .. _compatibility-alias: .. example:: Introducing a compatibility alias Let's say your library initially contained: .. rocqtop:: in Definition foo x := S x. and you want to rename `foo` into `bar`, but you want to avoid breaking your users' code without advanced notice. To do so, replace the previous code by the following: .. rocqtop:: in reset Definition bar x := S x. #[deprecated(since="mylib 1.2", note="Use bar instead.")] Abbreviation foo := bar (only parsing). Then, the following code still works, but emits a warning: .. rocqtop:: all warn Check (foo 0). rocq-9.2.0/doc/sphinx/using/tools/000077500000000000000000000000001516144147600170425ustar00rootroot00000000000000rocq-9.2.0/doc/sphinx/using/tools/coqdoc.rst000066400000000000000000000371641516144147600210570ustar00rootroot00000000000000.. index:: coqdoc .. _rocqdoc: Documenting Rocq files with rocq doc ------------------------------------ `rocq doc` is a documentation tool for the Rocq Prover, similar to ``javadoc`` or ``ocamldoc``. The task of `rocq doc` is #. to produce a nice |Latex| and/or HTML document from Rocq source files, readable for a human and not only for the proof assistant; #. to help users navigate their own (or third-party) sources. Principles ~~~~~~~~~~ Documentation is inserted into Rocq files as *special comments*. Thus your files will compile as usual, whether you use `rocq doc` or not. `rocq doc` presupposes that the given Rocq files are well-formed (at least lexically). Documentation starts with ``(**``, followed by a space, and ends with ``*)``. The documentation format is inspired by Todd A. Coram’s *Almost Free Text (AFT)* tool: it is mainly ``ASCII`` text with some syntax-light controls, described below. `rocq doc` is robust: it shouldn’t fail, whatever the input is. But remember: β€œgarbage in, garbage out”. Rocq material inside documentation. ++++++++++++++++++++++++++++++++++++ Rocq material is quoted between the delimiters ``[`` and ``]``. Square brackets may be nested, the inner ones being understood as being part of the quoted code (thus you can quote a term like ``let id := fun [T : Type] (x : t) => x in id 0`` by writing ``[let id := fun [T : Type] (x : t) => x in id 0]``). Inside quotations, the code is pretty-printed the same way as in code parts. Preformatted vernacular is enclosed by ``[[`` and ``]]``. The former must be followed by a newline and the latter must follow a newline. Pretty-printing. ++++++++++++++++ `rocq doc` uses different faces for identifiers and keywords. The pretty- printing of Rocq tokens (identifiers or symbols) can be controlled using one of the following commands: :: (** printing *token* %...LATEX...% #...html...# *) or :: (** printing *token* $...LATEX math...$ #...html...# *) It gives the |Latex| and HTML texts to be produced for the given Rocq token. Either the |Latex| or the HTML rule may be omitted, causing the default pretty-printing to be used for this token. The printing for one token can be removed with :: (** remove printing *token* *) Initially, the pretty-printing table contains the following mapping: ===== === ==== ===== === ==== ==== === `->` β†’ `<-` ← `*` Γ— `<=` ≀ `>=` β‰₯ `=>` β‡’ `<>` β‰  `<->` ↔ `|-` ⊒ `\\/` ∨ `/\\` ∧ `~` Β¬ ===== === ==== ===== === ==== ==== === Any of these can be overwritten or suppressed using the printing commands. .. note:: The recognition of tokens is done by a (``ocaml``) lex automaton and thus applies the longest-match rule. For instance, `->~` is recognized as a single token, where Rocq sees two tokens. It is the responsibility of the user to insert space between tokens *or* to give pretty-printing rules for the possible combinations, e.g. :: (** printing ->~ %\ensuremath{\rightarrow\lnot}% *) Sections ++++++++ Sections are introduced by 1 to 4 asterisks at the beginning of a line followed by a space and the title of the section. One asterisk is a section, two a subsection, etc. .. example:: :: (** * Well-founded relations In this section, we introduce... *) Lists. ++++++ List items are introduced by a leading dash. `rocq doc` uses whitespace to determine the depth of a new list item and which text belongs in which list items. A list ends when a line of text starts at or before the level of indenting of the list’s dash. A list item’s dash must always be the first non-space character on its line (so, in particular, a list can not begin on the first line of a comment - start it on the second line instead). .. example:: :: We go by induction on [n]: - If [n] is 0... - If [n] is [S n'] we require... two paragraphs of reasoning, and two subcases: - In the first case... - In the second case... So the theorem holds. Rules. ++++++ More than 4 leading dashes produce a horizontal rule. Emphasis. +++++++++ Text can be italicized by enclosing it in underscores. A non-identifier character must precede the leading underscore and follow the trailing underscore, so that uses of underscores in names aren’t mistaken for emphasis. Usually, these are spaces or punctuation. :: This sentence contains some _emphasized text_. Escaping to |Latex| and HTML. +++++++++++++++++++++++++++++++ Pure |Latex| or HTML material can be inserted using the following escape sequences: + ``$...LATEX stuff...$`` inserts some |Latex| material in math mode. Simply discarded in HTML output. + ``%...LATEX stuff...%`` inserts some |Latex| material. Simply discarded in HTML output. + ``#...HTML stuff...#`` inserts some HTML material. Simply discarded in |Latex| output. .. note:: to simply output the characters ``$``, ``%`` and ``#`` and escaping their escaping role, these characters must be doubled. Verbatim ++++++++ Verbatim material is introduced by a leading ``<<`` and closed by ``>>`` at the beginning of a line. .. example:: :: Here is the corresponding caml code: << let rec fact n = if n <= 1 then 1 else n * fact (n-1) >> Verbatim material on a single line is also possible (assuming that ``>>`` is not part of the text to be presented as verbatim). .. example:: :: Here is the corresponding caml expression: << fact (n-1) >> Hyperlinks ++++++++++ Hyperlinks can be inserted into the HTML output, so that any identifier is linked to the place of its definition. ``rocq c file.v`` automatically dumps localization information in ``file.glob`` or appends it to a file specified using the option ``--dump-glob file``. Take care of erasing this global file, if any, when starting the whole compilation process. Then invoke `rocq doc` or ``rocq doc --glob-from file`` to tell `rocq doc` to look for name resolutions in the file ``file`` (it will look in ``file.glob`` by default). Identifiers from the Rocq standard library are linked to the Coq website ``_. This behavior can be changed using command line options ``--no-externals`` and ``--coqlib_url``; see below. .. _rocqdoc-hide-show: Hiding / Showing parts of the source ++++++++++++++++++++++++++++++++++++ Some parts of the source can be hidden using command line options ``-g`` and ``-l`` (see below), or using such comments: :: (* begin hide *) *some Rocq material* (* end hide *) Conversely, some parts of the source which would be hidden can be shown using such comments: :: (* begin show *) *some Rocq material* (* end show *) The latter cannot be used around some inner parts of a proof, but can be used around a whole proof. Lastly, it is possible to adopt a middle-ground approach when the desired output is HTML, where a given snippet of Rocq material is hidden by default, but can be made visible with user interaction. :: (* begin details *) *some Rocq material* (* end details *) There is also an alternative syntax available. :: (* begin details : Some summary describing the snippet *) *some Rocq material* (* end details *) Usage ~~~~~ `rocq doc` is invoked on a shell command line as follows: ``rocq doc ``. Any command line argument which is not an option is considered to be a file (even if it starts with a ``-``). Rocq files are identified by the suffixes ``.v`` and ``.g`` and |Latex| files by the suffix ``.tex``. :HTML output: This is the default output format. One HTML file is created for each Rocq file given on the command line, together with a file ``index.html`` (unless option ``--no-index`` is passed). The HTML pages use a style sheet named ``style.css``. Such a file is distributed with `rocq doc`. :|Latex| output: A single |Latex| file is created, on standard output. It can be redirected to a file using the option ``-o``. The order of files on the command line is kept in the final document. |Latex| files given on the command line are copied β€˜as is’ in the final document . DVI and PostScript can be produced directly with the options ``-dvi`` and ``-ps`` respectively. :TEXmacs output: To translate the input files to TEXmacs format, to be used by the TEXmacs Rocq interface. Command line options ++++++++++++++++++++ **Overall options** :--HTML: Select a HTML output. :--|Latex|: Select a |Latex| output. :--dvi: Select a DVI output. :--ps: Select a PostScript output. :--texmacs: Select a TEXmacs output. :--stdout: Write output to stdout. :-o file, --output file: Redirect the output into the file β€˜file’ (meaningless with ``-html``). :-d dir, --directory dir: Output files into directory β€˜dir’ instead of the current directory (option ``-d`` does not change the filename specified with the option ``-o``, if any). :--body-only: Suppress the header and trailer of the final document. Thus, you can insert the resulting document into a larger one. :-p string, --preamble string: Insert some material in the |Latex| preamble, right before ``\begin{document}`` (meaningless with ``-html``). :--vernac-file file,--tex-file file: Considers the file β€˜file’ respectively as a ``.v`` (or ``.g``) file or a ``.tex`` file. :--files-from file: Read filenames to be processed from the file β€˜file’ as if they were given on the command line. Useful for program sources split up into several directories. :-q, --quiet: Be quiet. Do not print anything except errors. :-h, --help: Give a short summary of the options and exit. :-v, --version: Print the version and exit. **Index options** The default behavior is to build an index, for the HTML output only, into ``index.html``. :--no-index: Do not output the index. :--binder-index: Include variable binders in the index. Not recommended with large source files, where binder information may dominate the index. :--multi-index: Generate one page for each category and each letter in the index, together with a top page ``index.html``. :--index string: Make the filename of the index "``string``.html" instead of β€œindex.html”. Useful since β€œindex.html” is special. **Table of contents option** :-toc, --table-of-contents: Insert a table of contents. For a |Latex| output, it inserts a ``\tableofcontents`` at the beginning of the document. For a HTML output, it builds a table of contents into ``toc.html``. :--toc-depth int: Only include headers up to depth ``int`` in the table of contents. **Hyperlink options** :--glob-from file: Make references using Rocq globalizations from file file. (Such globalizations are obtained with Rocq option ``-dump-glob``). :--no-externals: Do not insert links to the Rocq standard library. :--external url coqdir: Use given URL for linking references whose name starts with prefix ``coqdir``. :--coqlib_url url: Set base URL for the Rocq standard library (default is ``_). This is equivalent to ``--external url Stdlib``. :-R dir coqdir: Recursively map physical directory dir to Rocq logical directory ``coqdir`` (similarly to Rocq option ``-R``). :-Q dir coqdir: Map physical directory dir to Rocq logical directory ``coqdir`` (similarly to Rocq option ``-Q``). .. note:: options ``-R`` and ``-Q`` only have effect on the files *following* them on the command line, so you will probably need to put this option first. **Title options** :-s , --short: Do not insert titles for the files. The default behavior is to insert a title like β€œLibrary Foo” for each file. :--lib-name string: Print β€œstring Foo” instead of β€œLibrary Foo” in titles. For example β€œChapter” and β€œModule” are reasonable choices. :--no-lib-name: Print just β€œFoo” instead of β€œLibrary Foo” in titles. :--lib-subtitles: Look for library subtitles. When enabled, the first line of each file is checked for a comment of the form: :: (** * ModuleName : text *) where ``ModuleName`` must be the name of the file. If it is present, the text is used as a subtitle for the module in appropriate places. :-t string, --title string: Set the document title. **Contents options** :-g, --gallina: Do not print proofs. :-l, --light: Light mode. Suppress proofs (as with ``-g``) and the following commands: + [Recursive] Tactic Definition + Hint / Hints + Require + Transparent / Opaque + Implicit Argument / Implicits + Section / Variable / Hypothesis / End The behavior of options ``-g`` and ``-l`` can be locally overridden using the ``(* begin show *) … (* end show *)`` environment (see above). There are a few options that control the parsing of comments: :--parse-comments: Parse regular comments delimited by ``(*`` and ``*)`` as well. They are typeset inline. :--plain-comments: Do not interpret comments, simply copy them as plain-text. :--interpolate: Use the globalization information to typeset identifiers appearing in Rocq escapings inside comments. **Language options** The default behavior is to assume ASCII 7 bit input files. :-latin1, --latin1: Select ISO-8859-1 input files. It is equivalent to --inputenc latin1 --charset iso-8859-1. :-utf8, --utf8: Set --inputenc utf8x for |Latex| output and --charset utf-8 for HTML output. Also use Unicode replacements for a couple of standard plain ASCII notations such as β†’ for ``->`` and βˆ€ for ``forall``. |Latex| UTF-8 support can be found at ``_. For the interpretation of Unicode characters by |Latex|, extra packages which `rocq doc` does not provide by default might be required, such as textgreek for some Greek letters or ``stmaryrd`` for some mathematical symbols. If a Unicode character is missing an interpretation in the utf8x input encoding, add ``\DeclareUnicodeCharacter{code}{LATEX-interpretation}``. Packages and declarations can be added with option ``-p``. :--inputenc string: Give a |Latex| input encoding, as an option to |Latex| package ``inputenc``. :--charset string: Specify the HTML character set, to be inserted in the HTML header. Custom HTML header and footer +++++++++++++++++++++++++++++ With `--with-header` and `--with-footer` respectively, in HTML mode `rocq doc` will include the header at the beginning and the footer at the end of the file. Additionally the string `@@TITLE@@` is replaced by the page title in the header file. The rocq doc |Latex| style file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In case you choose to produce a document without the default |Latex| preamble (by using option ``--no-preamble``), then you must insert into your own preamble the command :: \usepackage{coqdoc} The package optionally takes the argument ``[color]`` to typeset identifiers with colors (this requires the ``xcolor`` package). Then you may alter the rendering of the document by redefining some macros: :coqdockw, coqdocid, …: The one-argument macros for typesetting keywords and identifiers. Defaults are sans-serif for keywords and italic for identifiers.For example, if you would like a slanted font for keywords, you may insert :: \renewcommand{\coqdockw}[1]{\textsl{#1}} anywhere between ``\usepackage{coqdoc}`` and ``\begin{document}``. :coqdocmodule: One-argument macro for typesetting the title of a ``.v`` file. Default is :: \newcommand{\coqdocmodule}[1]{\section*{Module #1}} and you may redefine it using ``\renewcommand``. rocq-9.2.0/doc/sphinx/using/tools/index.rst000066400000000000000000000012741516144147600207070ustar00rootroot00000000000000.. _tools: ================================ Command-line and graphical tools ================================ This chapter presents the command-line tools that users will need to build their Rocq project, the documentation of the RocqIDE graphical user interface and the documentation of the parallel proof processing feature that is supported by RocqIDE and several other GUIs. A list of available user interfaces to interact with Rocq is available on the `Rocq website `_. .. toctree:: :maxdepth: 1 ../../practical-tools/utilities ../../practical-tools/coq-commands coqdoc ../../practical-tools/coqide ../../addendum/parallel-proof-processing rocq-9.2.0/doc/sphinx/zebibliography.html.rst000066400000000000000000000013311516144147600212620ustar00rootroot00000000000000.. There are multiple issues with sphinxcontrib-bibtex that we have to work around: - The list of cited entries is computed right after encountering `.. bibliography`, so the file containing that command has to come last alphabetically: https://sphinxcontrib-bibtex.readthedocs.io/en/latest/usage.html#unresolved-citations-across-documents - `.. bibliography::` puts the bibliography on its own page with its own title in LaTeX, but includes it inline without a title in HTML: https://sphinxcontrib-bibtex.readthedocs.io/en/latest/usage.html#mismatch-between-output-of-html-and-latex-backends .. _bibliography: ============== Bibliography ============== .. bibliography:: biblio.bib :cited: rocq-9.2.0/doc/sphinx/zebibliography.latex.rst000066400000000000000000000001471516144147600214370ustar00rootroot00000000000000.. See zebibliography.html.rst for details .. _bibliography: .. bibliography:: biblio.bib :cited: rocq-9.2.0/doc/tools/000077500000000000000000000000001516144147600144045ustar00rootroot00000000000000rocq-9.2.0/doc/tools/docgram/000077500000000000000000000000001516144147600160205ustar00rootroot00000000000000rocq-9.2.0/doc/tools/docgram/README.md000066400000000000000000000313021516144147600172760ustar00rootroot00000000000000# Grammar extraction tool for documentation `doc_grammar` extracts Coq's grammar from `.mlg` files, edits it and inserts it into `.rst` files. The tool inserts `prodn` directives for grammar productions. It also updates `tacn` and `cmd` directives when they can be unambiguously matched to productions of the grammar (in practice, that's probably almost always). `tacv` and `cmdv` directives are not updated because matching them appears to require human judgement. `doc_grammar` generates a few files that may be useful to developers and documenters. The mlg grammars present several challenges to generating an accurate grammar for documentation purposes: * The 30+ mlg files don't define an overall order in which nonterminals should appear in a complete grammar. * Even within a single mlg file, nonterminals and productions are often given in an order that's much different from what a reader of the documentation would expect. In a small number of cases, changing the order in the mlg would change how some inputs are parsed, in particular when the order determines how to distinguish otherwise ambiguous inputs. Strictly speaking, that means our grammar is not a context free grammar even though we gloss over that distinction in the documentation. * For a few nonterminals, some productions are only available if certain plugins are activated (e.g. SSR). Readers should be informed about these. * Some limited parts of the grammar are defined in OCaml, including lookahead symbols like `test_bracket_ident` and references to nonterminals in other files using qualified names such as `Prim.ident`. A few symbols are defined multiple times, such as `scope` and `orient`. ## What the tool does 1. The tool reads all the `mlg` files and generates `fullGrammar`, which includes all the grammar without the actions for each production or the OCaml code. This file is provided as a convenience to make it easier to examine the (mostly) unprocessed grammar of the mlg files with less clutter. This step includes two transformations that rename some nonterminal symbols: First, nonterminals that use levels (`"5" RIGHTA` below) are modified, for example: ``` ltac_expr: [ "5" RIGHTA [ ... ] [ "4" ... ``` becomes ``` tactic_expr5: [ | ... | tactic_expr4 ] ``` Second, nonterminals that are local to an .mlg will be renamed, if necessary, to make them unique. For example, `strategy_level` is defined as a local nonterminal in both `g_prim.mlg` and in `extraargs.mlg`. The nonterminal defined in the former remains `strategy_level` because it happens to be processed before the latter, in which the nonterminal is renamed to `EXTRAARGS_strategy_level` to make the local symbol unique. Nonterminals listed after `GLOBAL:` are global; otherwise they are local. References to renamed symbols are updated with the modified names. Note: the 4 SSR mlgs and ssreflect-proof-language.rst are currently excluded from processing (hard coded). 2. The tool applies grammar editing operations specified by `common.edit_mlg` to generate `editedGrammar`. 3. `orderedGrammar` gives the desired order for nonterminals and individual productions in the documented grammar. Developers should edit this file only to reorder lines. `doc_grammar` updates `orderedGrammar` so it has the same set of nonterminals and productions as `editedGrammar` while retaining the previous ordering. Since the position of new or renamed nonterminals is unspecified, they tend to show up in the wrong place in `orderedGrammar`, therefore users should review the output and make appropriate adjustments to the order. The update process removes manually-added comments from `orderedGrammar` while automatically-generated comments will be regenerated. 4. The tool updates the `.rst` files. Comments in the form `.. insertprodn ` indicate inserting the productions for a range of nonterminals (in `orderedGrammar` order). `.. cmd::` and `.. tacn::` directives are updated using prefixes in the form `[a-zA-Z0-9_ ]+` from the directive and the grammar. If there is unique match in the grammar, the directive is updated, if needed. Multiple matches or no match gives an error message. 5. For reference, the tool generates `prodnGrammar`, which has the entire grammar in the form of `prodns`. 6. If requested by command-line arguments `-check-cmds` or `-check-tacs`, the tool generates `prodnCommands` (for commands) and `prodnTactics` (for tactics). The former lists all commands that are under `command` in `orderedGrammar` and compares it to the `:cmd:` and `:cmdv:` given in the rst files. The latter lists all tactics that are under `simple_tactic` in the grammar and compares it to the `:tacn:` and `:tacv:`. The tags at the beginning of each line mean: - (no tag) - the grammar and the rst match exactly and uniquely - `-` - a grammar production that can't be matched to an rst file entry - `+` - an rst entry that doesn't match a grammar production - `v` - the rst entry is a `:cmdv:` or `:tacv:` - `?` - the match between the grammar and the rst files is not unique These command line arguments also generate error messages for commands and tactics that are in the grammar but not the documentation and vice versa. ## How to use the tool * `make doc_gram` updates `fullGrammar`. * `make doc_gram_verify` verifies that `fullGrammar`, `orderedGrammar` and `*.rst` are consistent with the `.mlg` files. This is for use by CI. * `make doc_gram_rsts` updates the `*Grammar` and `.rst` files. * `make doc_gram_rsts DOCGRAMWARN=1` will additionally print warnings. Changes to `fullGrammar`, `orderedGrammar` and `*.rst` should be checked in to git. The `prodn*` and other `*Grammar` files should not. ### Command line arguments The executable takes a list of `.mlg` and `.rst` files as arguments. The tool inserts the grammar into the `*.rst` as specified by comments in those files. The order of the `.mlg` files affects the order of nonterminals and productions in `fullGrammar`. The order doesn't matter for the `.rst` files. Specifying the `-verify` command line argument avoids updating any of the files, but verifies that the current files are consistent. This setting is meant for use in CI; it will be up to each developer to include the changes to `*Grammar` and the `.rst` files in their PRs when they've changed the grammar. Other command line arguments: * `-check-tacs` causes generation of `prodnTactics` * `-check-cmds` causes generation of `prodnCommands` * `-no-warn` suppresses printing of some warning messages * `-no-update` puts updates to `fullGrammar` and `orderedGrammar` into new files named `*.new`, leaving the originals unmodified. For use in Dune. * `-short` limits processing to updating/verifying only the `fullGrammar` file * `-verbose` prints more messages about the grammar * `-verify` described above ### Grammar editing scripts The grammar editing script `common.edit_mlg` is similar in format to `.mlg` files but stripped of all OCaml features. This is an easy way to include productions to match or add without writing another parser. The `DOC_GRAMMAR` token at the beginning of each file signals the use of the streamlined syntax. The edit file has a series of items in the form of productions. Items are applied in the order they appear. There are two types of editing operations: * Global edits - edit rules that apply to the entire grammar in a single operation. These are identified by using specific reserved names as the non-terminal name. * Local edits - edit rules that apply to the productions of a single non-terminal. The rule is a local edit if the non-terminal name isn't reserved. Individual productions within a local edit that begin with a different set of reserved names edit existing productions. For example `binders: [ | DELETE Procq.Constr.binders ]` deletes the production `binders: [ | Procq.Constr.binders]` Productions that don't begin with a reserved name are added to the grammar, such as `empty: [ | ]`, which adds a new non-terminal `empty` with an empty production on the right-hand side. Another example: `LEFTQMARK: [ | "?" ]` is a local edit that treats `LEFTQMARK` as the name of a non-terminal and adds a production for it. (We know that LEFTQMARK is a token but doc_grammar does not.) `SPLICE: [ | LEFTQMARK ]` requests replacing all uses of `LEFTQMARK` anywhere in the grammar with its productions and removing the non-terminal. The combined effect of these two is to replace all uses of `LEFTQMARK` with `"?"`. Here are the current operations: ### Global edits `DELETE` - deletes the specified non-terminals anywhere in the grammar. Each should appear as a separate production. Useful for removing non-terminals that only do lookahead that shouldn't be in the documentation. `RENAME` - each production specifies an (old name, new name) pair of non-terminals to rename. `SPLICE` - requests replacing all uses of the nonterminals anywhere in the grammar with its productions and removing the non-terminal. Each should appear as a separate production. (Doesn't work recursively; splicing for both `A: [ | B ]` and `B: [ | C ]` must be done in separate SPLICE operations.) `OPTINREF` - applies the local `OPTINREF` edit to every nonterminal `REACHABLE` - suppresses the "Unreachable symbol" warning for the listed nonterminals and any symbols reachable from them. `NOTINRSTS` - suppresses the "Nonterminal not included in .rst files" messages for the listed nonterminals. ### Local edits `DELETE ` - removes the specified production from the grammar `EDIT ` - modifies the specified production using the following tags that appear in the specified production: * `USE_NT ` LIST* - extracts LIST* as a new nonterminal with the specified new non-terminal name * `ADD_OPT ` - looks for a production that matches the specified production **without** ``. If found, both productions are replaced with single production with `OPT ` The current version handles a single USE_NT or ADD_OPT per EDIT. These symbols may appear in the middle of the production given in the EDIT. `APPENDALL ` - inserts at the end of every production in . `INSERTALL ` - inserts at the beginning of every production in . `REPLACE` - (2 sequential productions) - removes `` and inserts `` in its place. ``` | REPLACE | WITH ``` `COPYALL ` - creates a new nonterminal `` and copies all the productions in the nonterminal to ``. `MOVETO ` - moves the production to `` and, if needed, creates a new production -> \. `MOVEALLBUT ` - moves all the productions in the nonterminal to `` *except* for the productions following the `MOVEALLBUT` production in the edit script (terminated only by the closing `]`). `OPTINREF` - verifies that has an empty production. If so, it removes the empty production and replaces all references to throughout the grammar with `OPT ` `PRINT` - prints the nonterminal definition at that point in applying the edits. Most useful when the edits get a bit complicated to follow. `(any other nonterminal name)` - adds a new production (and possibly a new nonterminal) to the grammar. ### `.rst` file updates `doc_grammar` updates `.rst` files where it sees the following 3 lines ``` .. insertprodn .. prodn:: ``` The end of the existing `prodn` is recognized by a blank line. ### Tagging productions `doc_grammar` tags the origin of productions from plugins that aren't automatically loaded. In grammar files, they appear as `(* XXX plugin *)`. In rsts, productions generated by `.. insertprodn` will include where relevant three spaces as (a delimiter) and a tag name after each production, which Sphinx will show on the far right-hand side of the production. The origin of a production can be specified explicitly in `common.edit_mlg` with the `TAG name` appearing at the end of a production. `name` must be in quotes if it contains whitespace characters. Some edit operations preserve the tags, but others, such as `REPLACE ... WITH ...` do not. A mapping from filenames to tags (e.g. "g_ltac2.mlg" is "Ltac2") is hard-coded as is filtering to avoid showing tags for, say, Ltac2 productions from appearing on every production in that chapter. If desired, this mechanism could be extended to tag certain productions as deprecated, perhaps in conjunction with a coqpp change. rocq-9.2.0/doc/tools/docgram/common.edit_mlg000066400000000000000000002170611516144147600210250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* " LIST1 global OPT natural | WITH "Resolve" [ "->" | "<-" ] LIST1 global OPT natural | DELETE "Resolve" "<-" LIST1 global OPT natural | REPLACE "Variables" "Transparent" | WITH [ "Constants" | "Projections" | "Variables" ] [ "Transparent" | "Opaque" ] | DELETE "Variables" "Opaque" | DELETE "Constants" "Transparent" | DELETE "Constants" "Opaque" | DELETE "Projections" "Transparent" | DELETE "Projections" "Opaque" | REPLACE "Transparent" LIST1 global | WITH [ "Transparent" | "Opaque" ] LIST1 global | DELETE "Opaque" LIST1 global | REPLACE "Extern" natural OPT Constr.constr_pattern "=>" generic_tactic | WITH "Extern" natural OPT constr_pattern "=>" generic_tactic | INSERTALL "Hint" | APPENDALL opt_hintbases ] (* todo: does ARGUMENT EXTEND make the symbol global? It is in both extraargs and extratactics *) strategy_level_or_var: [ | DELETE EXTRAARGS_strategy_level | strategy_level ] EXTRAARGS_natural: [ | DELETENT ] EXTRAARGS_lconstr: [ | DELETENT ] EXTRAARGS_strategy_level: [ | DELETENT ] binders: [ | DELETE Procq.Constr.binders ] G_TACTIC_in_clause: [ | in_clause | MOVEALLBUT in_clause | in_clause ] SPLICE: [ | G_TACTIC_in_clause ] RENAME: [ | G_LTAC2_delta_flag ltac2_delta_reductions | G_LTAC2_strategy_flag ltac2_reductions | G_LTAC2_binder ltac2_binder | G_LTAC2_branches ltac2_branches | G_LTAC2_let_clause ltac2_let_clause | G_LTAC2_rewriter ltac2_rewriter | G_LTAC2_constr_with_bindings ltac2_constr_with_bindings | G_LTAC2_match_rule ltac2_match_rule | G_LTAC2_match_pattern ltac2_match_pattern | G_LTAC2_intropatterns ltac2_intropatterns | G_LTAC2_simple_intropattern ltac2_simple_intropattern | G_LTAC2_simple_intropattern_closed ltac2_simple_intropattern_closed | G_LTAC2_or_and_intropattern ltac2_or_and_intropattern | G_LTAC2_equality_intropattern ltac2_equality_intropattern | G_LTAC2_naming_intropattern ltac2_naming_intropattern | G_LTAC2_destruction_arg ltac2_destruction_arg | G_LTAC2_with_bindings ltac2_with_bindings | G_LTAC2_bindings ltac2_bindings | G_LTAC2_simple_binding ltac2_simple_binding | G_LTAC2_in_clause ltac2_in_clause | G_LTAC2_occs ltac2_occs | G_LTAC2_occs_nums ltac2_occs_nums | G_LTAC2_concl_occ ltac2_concl_occ | G_LTAC2_hypident_occ ltac2_hypident_occ | G_LTAC2_hypident ltac2_hypident | G_LTAC2_induction_clause ltac2_induction_clause | G_LTAC2_as_or_and_ipat ltac2_as_or_and_ipat | G_LTAC2_eqn_ipat ltac2_eqn_ipat | G_LTAC2_conversion ltac2_conversion | G_LTAC2_oriented_rewriter ltac2_oriented_rewriter | G_LTAC2_for_each_goal ltac2_for_each_goal | G_LTAC2_tactic_then_last ltac2_tactic_then_last | G_LTAC2_as_name ltac2_as_name | G_LTAC2_as_ipat ltac2_as_ipat | G_LTAC2_by_tactic ltac2_by_tactic | G_LTAC2_match_list ltac2_match_list ] (* Renames to eliminate qualified names. Put other renames at the end *) RENAME: [ (* map missing names for rhs *) | Constr.constr term | Constr.term0 term0 | Constr.global global | Constr.lconstr lconstr | Constr.cpattern cpattern | G_vernac.section_subset_expr section_var_expr | Prim.ident ident | Prim.identref identref | Prim.reference reference | Prim.string string | Prim.integer integer | Prim.qualid qualid | Prim.natural natural | Pvernac.Vernac_.main_entry vernac_control | Pltac.ltac_expr ltac_expr5 (* | G_vernac.def_body def_body | Prim.by_notation by_notation | Prim.natural natural *) | Vernac.fix_definition fix_definition ] (* written in OCaml *) impl_ident_head: [ | "{" ident ] lpar_id_coloneq: [ | "(" ident; ":=" ] (* lookahead symbols *) DELETE: [ | check_for_coloneq | local_test_lpar_id_colon | lookup_at_as_comma | test_only_starredidentrefs | test_bracket_ident | test_hash_ident | test_id_colon | test_lpar_id_colon | test_lpar_id_coloneq (* todo: grammar seems incorrect, repeats the "(" IDENT ":=" *) | test_lpar_nat_coloneq | test_lpar_id_rpar | test_lpar_idnum_coloneq | test_show_goal | test_show_natural | test_name_colon | test_pipe_closedcurly | ensure_fixannot | test_array_opening | test_array_closing | test_variance_ident | test_qualid_with_or_lpar_or_rbrac | test_leftsquarebracket_equal | test_old_sort_qvar | test_sort_qvar | test_ltac2_ident | test_doublepipe_univ_decl | test_doublepipe_cumul_univ_decl | test_semicolon_cumul_univ_decl | test_univ_cst ] (* additional nts to be spliced *) tactic_then_last: [ | REPLACE "|" LIST0 ( OPT ltac_expr5 ) SEP "|" | WITH LIST0 ( "|" ( OPT ltac_expr5 ) ) ] goal_tactics: [ | LIST0 ( OPT ltac_expr5 ) SEP "|" ] for_each_goal: [ | DELETENT ] for_each_goal: [ | goal_tactics | OPT ( goal_tactics "|" ) OPT ltac_expr5 ".." OPT ( "|" goal_tactics ) ] ltac2_tactic_then_last: [ | REPLACE "|" LIST0 ( OPT ltac2_expr6 ) SEP "|" (* Ltac2 plugin *) | WITH LIST0 ( "|" OPT ltac2_expr6 ) TAG Ltac2 ] ltac2_goal_tactics: [ | LIST0 ( OPT ltac2_expr6 ) SEP "|" TAG Ltac2 ] ltac2_for_each_goal: [ | DELETENT ] ltac2_for_each_goal: [ | ltac2_goal_tactics TAG Ltac2 | OPT ( ltac2_goal_tactics "|" ) OPT ltac2_expr6 ".." OPT ( "|" ltac2_goal_tactics ) TAG Ltac2 ] reference: [ | DELETENT ] reference: [ | qualid ] fullyqualid: [ | DELETENT ] fullyqualid: [ | qualid ] qualid: [ | DELETENT ] qualid: [ | ident LIST0 ("." ident) ] field: [ | DELETENT ] fields: [ | DELETENT ] dirpath: [ | REPLACE ident LIST0 field | WITH LIST0 ( ident "." ) ident ] let_type_cstr: [ | DELETE OPT [ ":" lconstr ] | type_cstr ] case_item: [ | REPLACE term100 OPT [ "as" name ] OPT [ "in" pattern200 ] | WITH term100 OPT ("as" name) OPT [ "in" pattern200 ] ] type: [ | term200 ] one_type: [ | constr ] term_forall_or_fun: [ | "forall" open_binders "," type ] binder_constr: [ | DELETE "forall" open_binders "," term200 | MOVETO term_forall_or_fun "fun" open_binders "=>" term200 | MOVETO term_let "let" name binders let_type_cstr ":=" term200 "in" term200 | MOVETO term_if "if" term200 as_return_type "then" term200 "else" term200 | MOVETO term_fix "let" "fix" fix_decl "in" term200 | MOVETO term_cofix "let" "cofix" cofix_body "in" term200 | MOVETO term_let "let" [ "(" LIST0 name SEP "," ")" | "()" ] as_return_type ":=" term200 "in" term200 | MOVETO term_let "let" "'" pattern200 OPT [ "in" pattern200 ] ":=" term200 OPT case_type "in" term200 | MOVETO term_fix "fix" fix_decls | MOVETO term_cofix "cofix" cofix_decls ] term_let: [ | REPLACE "let" name binders let_type_cstr ":=" term200 "in" term200 | WITH "let" name let_type_cstr ":=" term200 "in" term200 | "let" name LIST1 binder let_type_cstr ":=" term200 "in" term200 (* Don't need to document that "( )" is equivalent to "()" *) | REPLACE "let" [ "(" LIST0 name SEP "," ")" | "()" ] as_return_type ":=" term200 "in" term200 | WITH "let" "(" LIST0 name SEP "," ")" as_return_type ":=" term200 "in" term200 | MOVETO destructuring_let "let" "(" LIST0 name SEP "," ")" as_return_type ":=" term200 "in" term200 | MOVETO destructuring_let "let" "'" pattern200 OPT [ "in" pattern200 ] ":=" term200 OPT case_type "in" term200 ] qualid_annotated: [ | global univ_annot ] atomic_constr: [ | qualid_annotated | MOVETO term_evar "_" | REPLACE "?" "[" identref "]" | WITH "?[" identref "]" | MOVETO term_evar "?[" identref "]" | REPLACE "?" "[" pattern_ident "]" | WITH "?[" pattern_ident "]" | MOVETO term_evar "?[" pattern_ident "]" | MOVETO term_evar pattern_ident evar_instance ] ltac_expr0: [ | REPLACE "[" ">" for_each_goal "]" | WITH "[>" for_each_goal "]" ] (* lexer token *) IDENT: [ | ident ] scope_key: [ | IDENT ] scope_name: [ | IDENT ] scope: [ | scope_name | scope_key ] scope_delimiter: [ | REPLACE "%" IDENT | WITH "%" scope | REPLACE "%_" IDENT | WITH "%_" scope ] sort: [ | REPLACE "Type" "@{" reference ";" universe "}" | WITH "Type" "@{" OPT [ qualid [ "|" | ";" ] ] universe "}" | DELETE "Type" "@{" universe "}" | DELETE "Type" "@{" reference "|" universe "}" ] term100: [ | REPLACE term99 "<:" term200 | WITH term99 "<:" type | MOVETO term_cast term99 "<:" type | REPLACE term99 "<<:" term200 | WITH term99 "<<:" type | MOVETO term_cast term99 "<<:" type | REPLACE term99 ":>" term200 | WITH term99 ":>" type | MOVETO term_cast term99 ":>" type | REPLACE term99 ":" term200 | WITH term99 ":" type | MOVETO term_cast term99 ":" type ] constr: [ | REPLACE "@" global univ_annot | WITH "@" qualid_annotated | MOVETO term_explicit "@" qualid_annotated ] term10: [ (* Separate this LIST0 in the nonempty and the empty case *) (* The empty case is covered by constr *) | REPLACE "@" global univ_annot LIST0 term9 | WITH "@" qualid_annotated LIST1 term9 | REPLACE term9 | WITH constr | MOVETO term_application term10 LIST1 arg | MOVETO term_application "@" qualid_annotated LIST1 term9 (* fixme: add in as a prodn somewhere *) | MOVETO dangling_pattern_extension_rule "@" pattern_ident LIST1 identref | DELETE dangling_pattern_extension_rule ] term9: [ (* @Zimmi48: Special token .. is for use in the Notation command. (see bug_3304.v) *) | DELETE ".." term0 ".." ] term1: [ | REPLACE term1 ".(" global univ_annot LIST0 arg ")" | WITH term1 ".(" global univ_annot LIST0 arg ")" (* huh? *) | REPLACE term1 "%" IDENT | WITH term1 "%" scope_key | MOVETO term_scope term1 "%" scope_key | REPLACE term1 "%_" IDENT | WITH term1 "%_" scope_key | MOVETO term_scope term1 "%_" scope_key | MOVETO term_projection term1 ".(" global univ_annot LIST0 arg ")" | MOVETO term_projection term1 ".(" "@" global univ_annot LIST0 ( term9 ) ")" ] term0: [ | DELETE reference univ_annot | REPLACE "{|" record_declaration bar_cbrace | WITH "{|" OPT [ LIST1 field_def SEP ";" OPT ";" ] bar_cbrace | MOVETO number_or_string NUMBER | MOVETO number_or_string string | MOVETO term_record "{|" OPT [ LIST1 field_def SEP ";" OPT ";" ] bar_cbrace | MOVETO term_generalizing "`{" term200 "}" | MOVETO term_generalizing "`(" term200 ")" | MOVETO term_ltac "ltac" ":" "(" ltac_expr5 ")" | REPLACE "[" "|" array_elems "|" lconstr type_cstr "|" "]" univ_annot | WITH "[|" array_elems "|" lconstr type_cstr "|]" univ_annot ] fix_decls: [ | DELETE fix_decl | REPLACE fix_decl "with" LIST1 fix_decl SEP "with" "for" identref | WITH fix_decl OPT ( LIST1 ("with" fix_decl) "for" identref ) ] cofix_decls: [ | DELETE cofix_body | REPLACE cofix_body "with" LIST1 cofix_body SEP "with" "for" identref | WITH cofix_body OPT ( LIST1 ( "with" cofix_body ) "for" identref ) ] fields_def: [ | REPLACE field_def ";" fields_def | WITH LIST1 field_def SEP ";" | DELETE field_def ] binders_fixannot: [ | DELETE binder binders_fixannot | DELETE fixannot | DELETE (* empty *) | LIST0 binder OPT fixannot ] binder: [ | DELETE name ] open_binders: [ | REPLACE name LIST0 name ":" lconstr | WITH LIST1 name ":" type (* @Zimmi48: Special token .. is for use in the Notation command. (see bug_3304.v) *) | DELETE name ".." name | REPLACE name LIST0 name binders | WITH LIST1 binder | DELETE closed_binder binders ] closed_binder: [ | name | REPLACE "(" name LIST1 name ":" lconstr ")" | WITH "(" LIST1 name ":" type ")" | DELETE "(" name ":" lconstr ")" | DELETE "(" name ":=" lconstr ")" | REPLACE "(" name ":" lconstr ":=" lconstr ")" | WITH "(" name type_cstr ":=" lconstr ")" | DELETE "{" name "}" | DELETE "{" name LIST1 name "}" | REPLACE "{" name LIST1 name ":" lconstr "}" | WITH "{" LIST1 name type_cstr "}" | DELETE "{" name ":" lconstr "}" | MOVETO implicit_binders "{" LIST1 name type_cstr "}" | DELETE "[" name "]" | DELETE "[" name LIST1 name "]" | REPLACE "[" name LIST1 name ":" lconstr "]" | WITH "[" LIST1 name type_cstr "]" | DELETE "[" name ":" lconstr "]" | MOVETO implicit_binders "[" LIST1 name type_cstr "]" | REPLACE "(" name ":" lconstr "|" lconstr ")" | WITH "(" name ":" type "|" lconstr ")" | MOVETO generalizing_binder "`(" LIST1 typeclass_constraint SEP "," ")" | MOVETO generalizing_binder "`{" LIST1 typeclass_constraint SEP "," "}" | MOVETO generalizing_binder "`[" LIST1 typeclass_constraint SEP "," "]" ] (* next two used internally for declaring notations *) one_closed_binder: [ | DELETENT ] one_open_binder: [ | DELETENT ] name_colon: [ | name ":" ] typeclass_constraint: [ | EDIT ADD_OPT "!" term200 | REPLACE "{" name "}" ":" [ "!" | ] term200 | WITH "{" name "}" ":" OPT "!" term200 | REPLACE name ":" [ "!" | ] term200 | WITH name ":" OPT "!" term200 ] (* ?? From the grammar, Prim.name seems to be only "_" but ident is also accepted "*) Prim.name: [ | REPLACE "_" | WITH name ] oriented_rewriter: [ | REPLACE orient_rw rewriter | WITH orient rewriter ] DELETE: [ | orient_rw ] pattern10: [ | REPLACE pattern10 LIST1 pattern1 | WITH pattern10 LIST0 pattern1 | DELETE pattern1 ] pattern1: [ | REPLACE pattern1 "%" IDENT | WITH pattern1 "%" scope_key | REPLACE pattern1 "%_" IDENT | WITH pattern1 "%_" scope_key ] pattern0: [ | REPLACE "(" pattern200 ")" | WITH "(" LIST1 pattern200 SEP "|" ")" | DELETE "(" pattern200 "|" LIST1 pattern200 SEP "|" ")" | REPLACE "{|" record_patterns bar_cbrace | WITH "{|" LIST0 record_pattern bar_cbrace ] DELETE: [ | record_patterns ] eqn: [ | REPLACE LIST1 mult_pattern SEP "|" "=>" lconstr | WITH LIST1 [ LIST1 pattern100 SEP "," ] SEP "|" "=>" lconstr ] (* No constructor syntax, OPT [ "|" binders ] is not supported for Record *) record_definition: [ | opt_coercion ident_decl binders OPT [ ":" sort ] OPT ( ":=" OPT [ identref ] "{" record_fields "}" OPT [ "as" identref ] ) ] (* No mixed inductive-record definitions, opt_coercion is meaningless for Inductive *) inductive_definition: [ | cumul_ident_decl binders OPT [ "|" binders ] OPT [ ":" type ] ":=" OPT [ OPT "|" LIST1 constructor SEP "|" ] decl_notations ] (* No mutual recursion, no inductive classes, type must be a sort *) (* constructor is optional but "Class record_definition" covers that case *) singleton_class_definition: [ | ident_decl binders OPT [ ":" sort ] ":=" constructor ] (* No record syntax, opt_coercion not supported for Variant, := ... required *) variant_definition: [ | ident_decl binders OPT [ "|" binders ] OPT [ ":" type ] ":=" OPT [ OPT "|" LIST1 constructor SEP "|" ] decl_notations ] gallina: [ | REPLACE thm_token ident_decl binders ":" lconstr LIST0 [ "with" ident_decl binders ":" lconstr ] | WITH thm_token ident_decl binders ":" type LIST0 [ "with" ident_decl binders ":" type ] | DELETE assumptions_token inline assum_list | DELETE "Symbols" assum_list | REPLACE "Symbol" assum_list | WITH [ "Symbol" | "Symbols" ] assum_list | REPLACE inductive_token LIST1 inductive_or_record_definition SEP "with" | WITH "Inductive" inductive_definition LIST0 ( "with" inductive_definition ) | "Inductive" record_definition LIST0 ( "with" record_definition ) | "CoInductive" inductive_definition LIST0 ( "with" inductive_definition ) | "CoInductive" record_definition LIST0 ( "with" record_definition ) | REPLACE finite_token inductive_or_record_definition | WITH "Variant" variant_definition | [ "Record" | "Structure" ] record_definition | "Class" record_definition | "Class" singleton_class_definition | REPLACE "Fixpoint" LIST1 fix_definition SEP "with" | WITH "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) | REPLACE "Let" "Fixpoint" LIST1 fix_definition SEP "with" | WITH "Let" "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) | REPLACE "CoFixpoint" LIST1 cofix_definition SEP "with" | WITH "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) | REPLACE "Let" "CoFixpoint" LIST1 cofix_definition SEP "with" | WITH "Let" "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) | REPLACE "Scheme" LIST1 scheme SEP "with" | WITH "Scheme" scheme LIST0 ( "with" scheme ) | DELETE "Scheme" "Boolean" "Equality" "for" smart_global | DELETE "Scheme" "Equality" "for" smart_global | "Scheme" OPT "Boolean" "Equality" "for" smart_global | DELETE "Rewrite" "Rules" identref ":=" OPT "|" LIST1 rewrite_rule SEP "|" | REPLACE "Rewrite" "Rule" identref ":=" OPT "|" LIST1 rewrite_rule SEP "|" | WITH "Rewrite" [ "Rule" | "Rules" ] identref ":=" OPT "|" LIST1 rewrite_rule SEP "|" ] SPLICE: [ | variant_definition ] finite_token: [ | DELETENT ] inductive_token: [ | DELETENT ] inductive_or_record_definition: [ | DELETENT ] constructors_or_record: [ | DELETENT ] record_fields: [ | REPLACE record_field ";" record_fields | WITH OPT [ LIST1 record_field SEP ";" OPT ";" ] | DELETE record_field | DELETE (* empty *) ] assumptions_token: [ | DELETENT ] inline: [ | REPLACE "Inline" "(" natural ")" | WITH "Inline" OPT ( "(" natural ")" ) | DELETE "Inline" ] univ_level_or_quality: [ | REPLACE NUMBER "0" | WITH "0" ] univ_decl: [ | REPLACE "@{" LIST0 identref ";" LIST0 identref [ "+" | ] univ_decl_constraints | WITH "@{" OPT [ LIST0 identref [ "|" | ";" ] ] LIST0 identref OPT "+" OPT [ "|" LIST0 sort_constraint SEP "," OPT "+" ] "}" | DELETE "@{" LIST0 identref [ "+" | ] univ_decl_constraints | DELETE "@{" LIST0 identref "|" LIST0 identref [ "+" | ] univ_decl_constraints ] cumul_univ_decl: [ | REPLACE "@{" LIST0 identref ";" LIST0 variance_identref [ "+" | ] univ_decl_constraints | WITH "@{" OPT [ LIST0 identref [ "|" | ";" ] ] LIST0 variance_identref OPT "+" OPT [ "|" LIST0 sort_constraint SEP "," OPT "+" ] "}" | DELETE "@{" LIST0 variance_identref [ "+" | ] univ_decl_constraints | DELETE "@{" LIST0 identref "|" LIST0 variance_identref [ "+" | ] univ_decl_constraints ] of_type: [ | DELETENT ] of_type: [ | [ ":" | ":>" ] type ] of_type_inst: [ | DELETENT ] of_type_inst: [ | [ ":" | ":>" | "::" | "::>" ] type ] def_body: [ | DELETE binders ":=" reduce lconstr | REPLACE binders ":" lconstr ":=" reduce lconstr | WITH LIST0 binder OPT (":" type) ":=" reduce lconstr | REPLACE binders ":" lconstr | WITH LIST0 binder ":" type ] delta_flag: [ | REPLACE "-" "[" LIST1 smart_global "]" | WITH OPT "-" "[" LIST1 smart_global "]" | DELETE "[" LIST1 smart_global "]" | OPTINREF ] ltac2_delta_reductions: [ | EDIT ADD_OPT "-" "[" refglobals "]" (* Ltac2 plugin *) ] ltac2_branches: [ | EDIT ADD_OPT "|" LIST1 branch SEP "|" (* Ltac2 plugin *) ] strategy_flag: [ | REPLACE OPT "head" OPT delta_flag | WITH OPT "head" delta_flag (*| REPLACE LIST1 red_flags | WITH LIST1 red_flag*) | (* empty *) ] filtered_import: [ | REPLACE global "(" LIST1 one_import_filter_name SEP "," ")" | WITH global OPT [ "(" LIST1 one_import_filter_name SEP "," ")" ] | DELETE global ] is_module_expr: [ | REPLACE ":=" module_expr_inl LIST0 ext_module_expr | WITH ":=" LIST1 module_expr_inl SEP "<+" ] is_module_type: [ | REPLACE ":=" module_type_inl LIST0 ext_module_type | WITH ":=" LIST1 module_type_inl SEP "<+" ] gallina_ext: [ | REPLACE "Arguments" smart_global LIST0 arg_specs OPT [ "," LIST1 [ LIST0 implicits_alt ] SEP "," ] OPT [ ":" LIST1 args_modifier SEP "," ] | WITH "Arguments" smart_global LIST0 arg_specs LIST0 [ "," LIST0 implicits_alt ] OPT [ ":" LIST1 args_modifier SEP "," ] | REPLACE "Implicit" "Type" reserv_list | WITH "Implicit" [ "Type" | "Types" ] reserv_list | DELETE "Implicit" "Types" reserv_list (* Per @Zimmi48, the global (qualid) must be a simple identifier if def_body is present Note that smart_global is "qualid | by_notation" and that ident_decl is "ident OPT univ_decl"; move *) | REPLACE "Canonical" OPT "Structure" global OPT [ OPT univ_decl def_body ] | WITH "Canonical" OPT "Structure" ident_decl def_body | REPLACE "Canonical" OPT "Structure" by_notation | WITH "Canonical" OPT "Structure" smart_global | DELETE "Coercion" global ":" coercion_class ">->" coercion_class | REPLACE "Coercion" by_notation ":" coercion_class ">->" coercion_class | WITH "Coercion" smart_global OPT [ ":" coercion_class ">->" coercion_class ] (* semantically restricted per https://github.com/rocq-prover/rocq/pull/12936#discussion_r492705820 *) (* global OPT univ_decl is just ident_decl, the first OPT is moved to the rule above *) | REPLACE "Coercion" global OPT [ OPT univ_decl def_body ] | WITH "Coercion" ident_decl def_body | REPLACE "Include" "Type" module_type_inl LIST0 ext_module_type | WITH "Include" "Type" LIST1 module_type_inl SEP "<+" | REPLACE "Generalizable" [ "All" "Variables" | "No" "Variables" | [ "Variable" | "Variables" ] LIST1 identref ] | WITH "Generalizable" [ [ "Variable" | "Variables" ] LIST1 identref | "All" "Variables" | "No" "Variables" ] (* don't show Export for Set, Unset *) | DELETE "Export" "Set" setting_name option_setting | REPLACE "Export" "Unset" setting_name | WITH "Unset" setting_name | REPLACE "Instance" instance_name ":" term200 hint_info [ ":=" "{" record_declaration "}" | ":=" lconstr | ] | WITH "Instance" instance_name ":" type hint_info OPT [ ":=" "{" record_declaration "}" | ":=" lconstr ] | DELETE "Require" export_token LIST1 filtered_import | REPLACE "From" global "Require" export_token LIST1 filtered_import | WITH OPT [ "From" dirpath ] "Require" export_token LIST1 filtered_import | REPLACE "From" global "Extra" "Dependency" ne_string OPT [ "as" IDENT ] | WITH "From" dirpath "Extra" "Dependency" ne_string OPT [ "as" IDENT ] ] export_token: [ | REPLACE "Import" OPT import_categories | WITH [ "Import" | "Export" ] OPT import_categories | DELETE "Export" OPT import_categories ] (* lexer stuff *) LEFTQMARK: [ | "?" ] digit: [ | "0" ".." "9" ] decnat: [ | digit LIST0 [ digit | "_" ] ] hexdigit: [ | [ "0" ".." "9" | "a" ".." "f" | "A" ".." "F" ] ] hexnat: [ | [ "0x" | "0X" ] hexdigit LIST0 [ hexdigit | "_" ] ] bignat: [ | REPLACE NUMBER | WITH [ decnat | hexnat ] ] number: [ | OPT "-" decnat OPT ( "." LIST1 [ digit | "_" ] ) OPT ( [ "e" | "E" ] OPT [ "+" | "-" ] decnat ) | OPT "-" hexnat OPT ( "." LIST1 [ hexdigit | "_" ] ) OPT ( [ "p" | "P" ] OPT [ "+" | "-" ] decnat ) ] bigint: [ | DELETE bignat | REPLACE test_minus_nat "-" bignat | WITH OPT "-" bignat ] first_letter: [ | [ "a" ".." "z" | "A" ".." "Z" | "_" | unicode_letter ] ] subsequent_letter: [ | [ first_letter | digit | "'" | unicode_id_part ] ] ident: [ | DELETE IDENT | first_letter LIST0 subsequent_letter ] NUMBER: [ | number ] (* todo: QUOTATION only used in a test suite .mlg files, is it documented/useful? *) string: [ | DELETENT ] STRING: [ | string ] (* todo: is "bigint" useful?? *) (* todo: "check_int" in g_prim.mlg should be "check_num" *) (* added productions *) command_entry: [ | noedit_mode ] DELETE: [ | tactic_then_locality ] ltac_constructs: [ (* repeated in main ltac grammar - need to create a COPY edit *) | ltac_expr4 ";" [ ltac_expr3 ] | ltac_expr4 ";" "[" for_each_goal "]" | ltac_expr1 "+" [ ltac_expr2 ] | ltac_expr1 "||" [ ltac_expr2 ] (* | qualid LIST0 tactic_value add later due renaming tactic_value *) | "[>" for_each_goal "]" | toplevel_selector ltac_expr5 ] (* temporarily render left-associativity manually, see #21029 *) ltac_expr4: [ | REPLACE ltac_expr4 ";" for_each_goal "]" | WITH ltac_expr4 ";" "[" for_each_goal "]" ] l3_tactic: [ ] ltac_expr3: [ | DELETE "abstract" ltac_expr2 | REPLACE "abstract" ltac_expr2 "using" ident | WITH "abstract" ltac_expr2 OPT ( "using" ident ) | l3_tactic | MOVEALLBUT ltac_builtins | l3_tactic | ltac_expr2 ] l2_tactic: [ ] ltac_expr2: [ | MOVETO ltac_builtins "tryif" ltac_expr5 "then" ltac_expr5 "else" ltac_expr2 | l2_tactic | DELETE ltac_builtins ] l1_tactic: [ ] ltac_expr1: [ | REPLACE "let" [ "rec" | ] LIST1 let_clause SEP "with" "in" ltac_expr5 | WITH "let" OPT "rec" let_clause LIST0 ( "with" let_clause ) "in" ltac_expr5 | EDIT match_key ADD_OPT "reverse" "goal" "with" match_context_list "end" | MOVETO simple_tactic match_key OPT "reverse" "goal" "with" match_context_list "end" | MOVETO simple_tactic match_key ltac_expr5 "with" match_list "end" | REPLACE failkw [ nat_or_var | ] LIST0 message_token | WITH failkw OPT nat_or_var LIST0 message_token | REPLACE reference LIST0 tactic_arg | WITH reference LIST1 tactic_arg | l1_tactic | DELETE simple_tactic | MOVEALLBUT ltac_builtins | l1_tactic | tactic_value | reference LIST1 tactic_arg | ltac_expr0 ] (* split match_context_rule *) goal_pattern: [ | LIST0 match_hyp SEP "," "|-" match_pattern | "[" LIST0 match_hyp SEP "," "|-" match_pattern "]" | "_" ] match_context_rule: [ | DELETE LIST0 match_hyp SEP "," "|-" match_pattern "=>" ltac_expr5 | DELETE "[" LIST0 match_hyp SEP "," "|-" match_pattern "]" "=>" ltac_expr5 | DELETE "_" "=>" ltac_expr5 | goal_pattern "=>" ltac_expr5 ] match_context_list: [ | EDIT ADD_OPT "|" LIST1 match_context_rule SEP "|" ] match_list: [ | EDIT ADD_OPT "|" LIST1 match_rule SEP "|" ] match_rule: [ (* redundant; match_pattern -> term -> _ *) | DELETE "_" "=>" ltac_expr5 ] firstorder_rhs: [ | firstorder_using | "with" LIST1 preident | firstorder_using "with" LIST1 preident ] where: [ | "at" "top" | "at" "bottom" | "after" ident | "before" ident ] simple_occurrences: [ (* placeholder (yuck) *) ] simple_tactic: [ | REPLACE "assert" "(" identref ":" lconstr ")" by_tactic | WITH "assert" "(" identref ":" type ")" by_tactic | REPLACE "assert" constr as_ipat by_tactic | WITH "assert" one_type as_ipat by_tactic | REPLACE "eassert" "(" identref ":" lconstr ")" by_tactic | WITH "eassert" "(" identref ":" type ")" by_tactic | REPLACE "eassert" constr as_ipat by_tactic | WITH "eassert" one_type as_ipat by_tactic | REPLACE "cut" constr | WITH "cut" one_type | REPLACE "evar" constr | WITH "evar" one_type | REPLACE "absurd" constr | WITH "absurd" one_type | REPLACE "enough" "(" identref ":" lconstr ")" by_tactic | WITH "enough" "(" identref ":" type ")" by_tactic | REPLACE "enough" constr as_ipat by_tactic | WITH "enough" one_type as_ipat by_tactic | REPLACE "eenough" "(" identref ":" lconstr ")" by_tactic | WITH "eenough" "(" identref ":" type ")" by_tactic | REPLACE "eenough" constr as_ipat by_tactic | WITH "eenough" one_type as_ipat by_tactic | DELETE "autorewrite" "with" LIST1 preident clause | DELETE "autorewrite" "with" LIST1 preident clause "using" tactic | DELETE "autorewrite" "*" "with" LIST1 preident clause | REPLACE "autorewrite" "*" "with" LIST1 preident clause "using" tactic | WITH "autorewrite" OPT "*" "with" LIST1 preident clause OPT ( "using" tactic ) | REPLACE "autounfold" hintbases clause_dft_concl | WITH "autounfold" hintbases OPT simple_occurrences | REPLACE "red" clause_dft_concl | WITH "red" simple_occurrences | REPLACE "simpl" OPT "head" OPT delta_flag OPT ref_or_pattern_occ clause_dft_concl | WITH "simpl" OPT "head" OPT delta_flag OPT ref_or_pattern_occ simple_occurrences | REPLACE "hnf" clause_dft_concl | WITH "hnf" simple_occurrences | REPLACE "cbv" strategy_flag clause_dft_concl | WITH "cbv" strategy_flag simple_occurrences | REPLACE "compute" OPT delta_flag clause_dft_concl | WITH "compute" OPT delta_flag simple_occurrences | REPLACE "lazy" strategy_flag clause_dft_concl | WITH "lazy" strategy_flag simple_occurrences | REPLACE "cbn" strategy_flag clause_dft_concl | WITH "cbn" strategy_flag simple_occurrences | REPLACE "fold" LIST1 constr clause_dft_concl | WITH "fold" LIST1 constr simple_occurrences | DELETE "clear" LIST0 hyp | REPLACE "clear" "-" LIST1 hyp | WITH "clear" OPT ( OPT "-" LIST1 hyp ) | DELETE "cofix" ident | REPLACE "cofix" ident "with" LIST1 cofixdecl | WITH "cofix" ident OPT ( "with" LIST1 cofixdecl ) | DELETE "constructor" | DELETE "constructor" nat_or_var | REPLACE "constructor" nat_or_var "with" bindings | WITH "constructor" OPT nat_or_var OPT ( "with" bindings ) | DELETE "econstructor" | DELETE "econstructor" nat_or_var | REPLACE "econstructor" nat_or_var "with" bindings | WITH "econstructor" OPT ( nat_or_var OPT ( "with" bindings ) ) | DELETE "dependent" [ "simple" "inversion" | "inversion" | "inversion_clear" ] quantified_hypothesis as_or_and_ipat OPT [ "with" constr ] | "dependent" "inversion" quantified_hypothesis as_or_and_ipat OPT [ "with" constr ] | "dependent" "simple" "inversion" quantified_hypothesis as_or_and_ipat OPT [ "with" constr ] | "dependent" "inversion_clear" quantified_hypothesis as_or_and_ipat OPT [ "with" constr ] | DELETE "dependent" "rewrite" orient constr | REPLACE "dependent" "rewrite" orient constr "in" hyp | WITH "dependent" "rewrite" orient constr OPT ( "in" hyp ) | "firstorder" OPT tactic firstorder_rhs | DELETE "firstorder" OPT tactic firstorder_using | DELETE "firstorder" OPT tactic "with" LIST1 preident | DELETE "firstorder" OPT tactic firstorder_using "with" LIST1 preident | DELETE "fix" ident natural | REPLACE "fix" ident natural "with" LIST1 fixdecl | WITH "fix" ident natural OPT ( "with" LIST1 fixdecl ) | DELETE "generalize" constr | REPLACE "generalize" constr LIST1 constr | WITH "generalize" LIST1 constr | REPLACE "generalize" constr occs as_name LIST0 [ "," pattern_occ as_name ] | WITH "generalize" LIST1 [ pattern_occ as_name ] SEP "," | REPLACE "evar" "(" ident ":" lconstr ")" | WITH "evar" "(" ident ":" type ")" | EDIT "simplify_eq" ADD_OPT destruction_arg | EDIT "esimplify_eq" ADD_OPT destruction_arg | EDIT "discriminate" ADD_OPT destruction_arg | EDIT "ediscriminate" ADD_OPT destruction_arg | DELETE "injection" | DELETE "injection" destruction_arg | DELETE "injection" "as" LIST0 simple_intropattern | REPLACE "injection" destruction_arg "as" LIST0 simple_intropattern | WITH "injection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) | DELETE "einjection" | DELETE "einjection" destruction_arg | DELETE "einjection" "as" LIST0 simple_intropattern | REPLACE "einjection" destruction_arg "as" LIST0 simple_intropattern | WITH "einjection" OPT destruction_arg OPT ( "as" LIST0 simple_intropattern ) | EDIT "simple" "injection" ADD_OPT destruction_arg | DELETE "intro" (* todo: change the mlg to simplify! *) | DELETE "intro" ident | DELETE "intro" ident "at" "top" | DELETE "intro" ident "at" "bottom" | DELETE "intro" ident "after" hyp | DELETE "intro" ident "before" hyp | DELETE "intro" "at" "top" | DELETE "intro" "at" "bottom" | DELETE "intro" "after" hyp | DELETE "intro" "before" hyp | "intro" OPT ident OPT where | DELETE "intros" | REPLACE "intros" ne_intropatterns | WITH "intros" intropatterns | DELETE "eintros" | REPLACE "eintros" ne_intropatterns | WITH "eintros" intropatterns | DELETE "move" hyp "at" "top" | DELETE "move" hyp "at" "bottom" | DELETE "move" hyp "after" hyp | DELETE "move" hyp "before" hyp | "move" ident where | REPLACE "refine" uconstr | WITH OPT "simple" OPT "notypeclasses" "refine" uconstr | DELETE "simple" "refine" uconstr | DELETE "notypeclasses" "refine" uconstr | DELETE "simple" "notypeclasses" "refine" uconstr | DELETE "replace" "->" uconstr clause | DELETE "replace" "<-" uconstr clause | DELETE "replace" uconstr clause | "replace" orient uconstr clause | REPLACE "replace" uconstr "with" constr clause by_arg_tac | WITH "replace" orient constr "with" constr clause OPT ( "by" ltac_expr3 ) | DELETE "replace" "->" uconstr "with" constr clause by_arg_tac | DELETE "replace" "<-" uconstr "with" constr clause by_arg_tac | REPLACE "rewrite" "*" orient uconstr "in" hyp "at" occurrences by_arg_tac | WITH "rewrite" "*" orient uconstr OPT ( "in" hyp ) OPT ( "at" occurrences ) by_arg_tac | DELETE "rewrite" "*" orient uconstr "in" hyp by_arg_tac | DELETE "rewrite" "*" orient uconstr "at" occurrences by_arg_tac | DELETE "rewrite" "*" orient uconstr by_arg_tac | DELETE "setoid_rewrite" orient glob_constr_with_bindings | DELETE "setoid_rewrite" orient glob_constr_with_bindings "in" hyp | DELETE "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences | REPLACE "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences "in" hyp | WITH "setoid_rewrite" orient glob_constr_with_bindings OPT ( "at" occurrences ) OPT ( "in" hyp ) | REPLACE "stepl" constr "by" tactic | WITH "stepl" constr OPT ( "by" tactic ) | DELETE "stepl" constr | REPLACE "stepr" constr "by" tactic | WITH "stepr" constr OPT ( "by" tactic ) | DELETE "stepr" constr | DELETE "unify" constr constr | REPLACE "unify" constr constr "with" preident | WITH "unify" constr constr OPT ( "with" preident ) | REPLACE "autounfold_one" hintbases "in" hyp | WITH "autounfold_one" hintbases OPT ( "in" hyp ) | DELETE "autounfold_one" hintbases | REPLACE "rewrite_db" preident "in" hyp | WITH "rewrite_db" preident OPT ( "in" hyp ) | DELETE "rewrite_db" preident | DELETE "setoid_symmetry" | REPLACE "setoid_symmetry" "in" hyp | WITH "setoid_symmetry" OPT ( "in" hyp ) | REPLACE "rewrite_strat" rewstrategy "in" hyp | WITH "rewrite_strat" rewstrategy OPT ( "in" hyp ) | DELETE "rewrite_strat" rewstrategy | REPLACE "protect_fv" string "in" ident | WITH "protect_fv" string OPT ( "in" ident ) | DELETE "protect_fv" string | DELETE "symmetry" | REPLACE "symmetry" "in" in_clause | WITH "symmetry" OPT simple_occurrences | DELETE "split" | REPLACE "split" "with" bindings | WITH "split" OPT ( "with" bindings ) | DELETE "esplit" | REPLACE "esplit" "with" bindings | WITH "esplit" OPT ( "with" bindings ) | DELETE "specialize" constr_with_bindings | REPLACE "specialize" constr_with_bindings "as" simple_intropattern | WITH "specialize" constr_with_bindings as_ipat | DELETE "exists" | REPLACE "exists" LIST1 bindings SEP "," | WITH "exists" LIST0 bindings SEP "," | DELETE "eexists" | REPLACE "eexists" LIST1 bindings SEP "," | WITH "eexists" LIST0 bindings SEP "," | DELETE "left" | REPLACE "left" "with" bindings | WITH "left" OPT ( "with" bindings ) | DELETE "eleft" | REPLACE "eleft" "with" bindings | WITH "eleft" OPT ( "with" bindings ) | DELETE "right" | REPLACE "right" "with" bindings | WITH "right" OPT ( "with" bindings ) | DELETE "eright" | REPLACE "eright" "with" bindings | WITH "eright" OPT ( "with" bindings ) | DELETE "finish_timing" OPT string | REPLACE "finish_timing" "(" string ")" OPT string | WITH "finish_timing" OPT ( "(" string ")" ) OPT string | REPLACE "subst" LIST1 hyp | WITH "subst" LIST0 hyp | DELETE "subst" | DELETE "congruence" OPT natural | REPLACE "congruence" OPT natural "with" LIST1 constr | WITH "congruence" OPT natural OPT ( "with" LIST1 constr ) | DELETE "simple" "congruence" OPT natural | REPLACE "simple" "congruence" OPT natural "with" LIST1 constr | WITH "simple" "congruence" OPT natural OPT ( "with" LIST1 constr ) | DELETE "show" "ltac" "profile" | REPLACE "show" "ltac" "profile" "cutoff" integer | WITH "show" "ltac" "profile" OPT [ "cutoff" integer | string ] | DELETE "show" "ltac" "profile" string (* perversely, the mlg uses "tactic3" instead of "ltac_expr3" *) | DELETE "transparent_abstract" tactic3 | REPLACE "transparent_abstract" tactic3 "using" ident | WITH "transparent_abstract" ltac_expr3 OPT ( "using" ident ) | "typeclasses" "eauto" OPT [ "bfs" | "dfs" | "best_effort" ] OPT nat_or_var OPT ( "with" LIST1 preident ) | DELETE "typeclasses" "eauto" "dfs" OPT nat_or_var "with" LIST1 preident | DELETE "typeclasses" "eauto" "dfs" OPT nat_or_var | DELETE "typeclasses" "eauto" "bfs" OPT nat_or_var "with" LIST1 preident | DELETE "typeclasses" "eauto" "bfs" OPT nat_or_var | DELETE "typeclasses" "eauto" "best_effort" OPT nat_or_var "with" LIST1 preident | DELETE "typeclasses" "eauto" "best_effort" OPT nat_or_var | DELETE "typeclasses" "eauto" OPT nat_or_var "with" LIST1 preident | DELETE "typeclasses" "eauto" OPT nat_or_var (* first/solve variants defined with register_list_tactical in coretactics.mlg *) | "first" ident | "solve" ident (* in Tactic Notation: *) | "setoid_replace" constr "with" constr OPT ( "using" "relation" constr ) OPT ( "in" hyp ) OPT ( "at" LIST1 int_or_var ) OPT ( "by" ltac_expr3 ) ] (* todo: don't use DELETENT for this *) ne_intropatterns: [ | DELETENT ] or_and_intropattern: [ | REPLACE "[" LIST1 intropatterns SEP "|" "]" | WITH "[" LIST0 (LIST0 intropattern) SEP "|" "]" | DELETE "()" | DELETE "(" simple_intropattern ")" | REPLACE "(" simple_intropattern "," LIST1 simple_intropattern SEP "," ")" | WITH "(" LIST0 simple_intropattern SEP "," ")" (* makes the grammar a little ambiguous for "()" and "( simple_intropattern )" but semantically doesn't matter *) | REPLACE "(" simple_intropattern "&" LIST1 simple_intropattern SEP "&" ")" | WITH "(" LIST0 simple_intropattern SEP "&" ")" ] equality_intropattern: [ | REPLACE "[" "=" intropatterns "]" | WITH "[=" intropatterns "]" ] bar_cbrace: [ | REPLACE "|" "}" | WITH "|}" ] printable: [ | REPLACE "Scope" IDENT | WITH "Scope" scope_name | REPLACE "Visibility" OPT IDENT | WITH "Visibility" OPT scope_name | REPLACE [ "Sorted" | ] "Universes" OPT printunivs_subgraph OPT [ [ "With" | "Without" ] "Constraint" "Sources" ] OPT ne_string | WITH OPT "Sorted" "Universes" OPT printunivs_subgraph OPT [ [ "With" | "Without" ] "Constraint" "Sources" ] OPT ne_string | DELETE "Term" smart_global OPT univ_name_list (* readded in commands *) | REPLACE "Hint" | WITH "Hint" OPT [ "*" | smart_global ] | DELETE "Hint" smart_global | DELETE "Hint" "*" | DELETE "Notation" string | REPLACE "Notation" string "in" "custom" qualid | WITH "Notation" string OPT [ "in" "custom" qualid ] | INSERTALL "Print" ] add_zify: [ | [ "InjTyp" | "BinOp" | "UnOp" | "CstOp" | "BinRel" | "UnOpSpec" | "BinOpSpec" ] TAG Micromega | [ "PropOp" | "PropBinOp" | "PropUOp" | "Saturate" ]TAG Micromega ] show_zify: [ | [ "InjTyp" | "BinOp" | "UnOp" | "CstOp" | "BinRel" | "UnOpSpec" | "BinOpSpec" | "Spec" ] TAG Micromega ] command: [ | REPLACE "Print" printable | WITH printable | REPLACE "Hint" hint opt_hintbases | WITH hint | "SubClass" ident_decl def_body | REPLACE "Ltac" LIST1 ltac_tacdef_body SEP "with" | WITH "Ltac" ltac_tacdef_body LIST0 ( "with" ltac_tacdef_body ) | REPLACE "Function" LIST1 function_fix_definition SEP "with" (* funind plugin *) | WITH "Function" function_fix_definition LIST0 ( "with" function_fix_definition ) (* funind plugin *) | REPLACE "Functional" "Scheme" LIST1 fun_scheme_arg SEP "with" (* funind plugin *) | WITH "Functional" "Scheme" fun_scheme_arg LIST0 ( "with" fun_scheme_arg ) (* funind plugin *) | DELETE "Cd" | REPLACE "Cd" ne_string | WITH "Cd" OPT ne_string | DELETE "Back" | REPLACE "Back" natural | WITH "Back" OPT natural | REPLACE "Load" [ "Verbose" | ] [ ne_string | IDENT ] | WITH "Load" OPT "Verbose" [ ne_string | IDENT ] | DELETE "Unset" setting_name | REPLACE "Test" setting_name "for" LIST1 table_value | WITH "Test" setting_name OPT ( "for" LIST1 table_value ) | DELETE "Test" setting_name (* hide the fact that table names are limited to 2 IDENTs *) | REPLACE "Add" IDENT IDENT LIST1 table_value | WITH "Add" setting_name LIST1 table_value | DELETE "Add" IDENT LIST1 table_value | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Parametric" "Relation" binders ":" constr constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr OPT ( "reflexivity" "proved" "by" constr ) OPT ( "symmetry" "proved" "by" constr ) OPT ("transitivity" "proved" "by" constr ) "as" identref | DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "as" identref | DELETE "Add" "Relation" constr constr "symmetry" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | DELETE "Add" "Relation" constr constr "transitivity" "proved" "by" constr "as" identref | "Add" "Relation" constr constr OPT ( "reflexivity" "proved" "by" constr ) OPT ( "symmetry" "proved" "by" constr ) OPT ( "transitivity" "proved" "by" constr ) "as" identref | REPLACE "Admit" "Obligations" "of" identref | WITH "Admit" "Obligations" OPT ( "of" identref ) | DELETE "Admit" "Obligations" | REPLACE "Create" "HintDb" IDENT; [ "discriminated" | ] | WITH "Create" "HintDb" IDENT; OPT "discriminated" | DELETE "Debug" "On" | REPLACE "Debug" "Off" | WITH "Debug" [ "On" | "Off" ] | EDIT "Defined" ADD_OPT identref | REPLACE "Derive" "Inversion" identref "with" constr "Sort" sort_quality_or_set | WITH "Derive" "Inversion" identref "with" constr OPT ( "Sort" sort_quality_or_set ) | DELETE "Derive" "Inversion" identref "with" constr | REPLACE "Derive" "Inversion_clear" identref "with" constr "Sort" sort_quality_or_set | WITH "Derive" "Inversion_clear" identref "with" constr OPT ( "Sort" sort_quality_or_set ) | DELETE "Derive" "Inversion_clear" identref "with" constr | EDIT "Focus" ADD_OPT natural | DELETE "Hint" "Rewrite" orient LIST1 constr ":" LIST1 preident | REPLACE "Hint" "Rewrite" orient LIST1 constr "using" generic_tactic ":" LIST1 preident | WITH "Hint" "Rewrite" orient LIST1 constr OPT ( "using" generic_tactic ) OPT ( ":" LIST1 preident ) | DELETE "Hint" "Rewrite" orient LIST1 constr | DELETE "Hint" "Rewrite" orient LIST1 constr "using" generic_tactic | REPLACE "Next" "Obligation" "of" identref withtac | WITH "Next" "Obligation" OPT ( "of" identref ) withtac | DELETE "Next" "Obligation" withtac | REPLACE "Final" "Obligation" "of" identref withtac | WITH "Final" "Obligation" OPT ( "of" identref ) withtac | DELETE "Final" "Obligation" withtac | REPLACE "Obligation" natural "of" identref withtac | WITH "Obligation" natural OPT ( "of" identref ) withtac | DELETE "Obligation" natural withtac | REPLACE "Obligations" "of" identref | WITH "Obligations" OPT ( "of" identref ) | DELETE "Obligations" | REPLACE "Preterm" "of" identref | WITH "Preterm" OPT ( "of" identref ) | DELETE "Preterm" | REPLACE "Proof" "using" section_var_expr "with" generic_tactic | WITH "Proof" "using" section_subset_expr OPT [ "with" generic_tactic ] | DELETE "Proof" "using" section_var_expr (* hide the fact that table names are limited to 2 IDENTs *) | REPLACE "Remove" IDENT IDENT LIST1 table_value | WITH "Remove" setting_name LIST1 table_value | DELETE "Remove" IDENT LIST1 table_value (* hide special case command that looks like a "Set" command *) | DELETE "Set" "Firstorder" "Solver" generic_tactic | DELETE "Show" | DELETE "Show" natural | DELETE "Show" qualid | "Show" OPT [ qualid | natural ] | DELETE "Show" "Ltac" "Profile" | REPLACE "Show" "Ltac" "Profile" "CutOff" integer | WITH "Show" "Ltac" "Profile" OPT [ "CutOff" integer | string ] | DELETE "Show" "Ltac" "Profile" string | DELETE "Show" "Proof" (* combined with Show Proof Diffs in vernac_toplevel *) | REPLACE "Solve" "All" "Obligations" withtac | WITH "Solve" "All" "Obligations" OPT ( "with" tactic ) | REPLACE "Solve" "Obligations" "of" identref withtac | WITH "Solve" "Obligations" OPT ( "of" identref ) OPT ( "with" tactic ) | DELETE "Solve" "Obligations" withtac | DELETE "Undo" | DELETE "Undo" natural | REPLACE "Undo" "To" natural | WITH "Undo" OPT ( OPT "To" natural ) | DELETE "Abort" "All" | REPLACE "Abort" | WITH "Abort" OPT [ "All" ] (* show the locate options as separate commands *) | DELETE "Locate" locatable | locatable | REPLACE "Print" smart_global OPT univ_name_list | WITH "Print" OPT "Term" smart_global OPT univ_name_list | REPLACE "Declare" "Scope" IDENT | WITH "Declare" "Scope" scope_name | REPLACE "Derive" open_binders "SuchThat" constr "As" identref (* derive plugin *) | WITH "Derive" open_binders "SuchThat" type "As" ident (* derive plugin *) | REPLACE "Derive" open_binders "in" constr "as" identref (* derive plugin *) | WITH "Derive" open_binders "in" type "as" ident (* derive plugin *) (* odd that these are in command while other notation-related ones are in syntax *) | REPLACE "Number" "Notation" reference reference reference OPT number_options ":" preident | WITH "Number" "Notation" reference reference reference OPT number_options ":" scope_name | REPLACE "String" "Notation" reference reference reference OPT string_option ":" preident | WITH "String" "Notation" reference reference reference OPT string_option ":" scope_name | DELETE "Ltac2" ltac2_entry (* was split up *) | DELETE "Add" "Zify" "InjTyp" reference (* micromega plugin *) | DELETE "Add" "Zify" "BinOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "UnOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "CstOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "BinRel" reference (* micromega plugin *) | DELETE "Add" "Zify" "PropOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "PropBinOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "PropUOp" reference (* micromega plugin *) | DELETE "Add" "Zify" "BinOpSpec" reference (* micromega plugin *) | DELETE "Add" "Zify" "UnOpSpec" reference (* micromega plugin *) | DELETE "Add" "Zify" "Saturate" reference (* micromega plugin *) | "Add" "Zify" add_zify reference TAG Micromega | DELETE "Show" "Zify" "InjTyp" (* micromega plugin *) | DELETE "Show" "Zify" "BinOp" (* micromega plugin *) | DELETE "Show" "Zify" "UnOp" (* micromega plugin *) | DELETE "Show" "Zify" "CstOp" (* micromega plugin *) | DELETE "Show" "Zify" "BinRel" (* micromega plugin *) | DELETE "Show" "Zify" "UnOpSpec" (* micromega plugin *) | DELETE "Show" "Zify" "BinOpSpec" (* micromega plugin *) (* keep this one | "Show" "Zify" "Spec" (* micromega plugin *)*) | "Show" "Zify" show_zify TAG Micromega | REPLACE "Goal" lconstr | WITH "Goal" type ] syntax: [ | REPLACE "Open" "Scope" IDENT | WITH "Open" "Scope" scope | REPLACE "Close" "Scope" IDENT | WITH "Close" "Scope" scope | REPLACE "Delimit" "Scope" IDENT; "with" IDENT | WITH "Delimit" "Scope" scope_name; "with" scope_key | REPLACE "Undelimit" "Scope" IDENT | WITH "Undelimit" "Scope" scope_name | REPLACE "Bind" "Scope" IDENT; "with" LIST1 coercion_class | WITH "Bind" "Scope" scope_name; "with" LIST1 coercion_class ] opt_scope: [ | REPLACE ":" IDENT | WITH ":" scope_name ] syntax_modifier: [ | DELETE "in" "custom" qualid | REPLACE "in" "custom" qualid; "at" "level" natural | WITH "in" "custom" qualid OPT ( "at" "level" natural ) | DELETE IDENT; "in" "scope" IDENT | REPLACE IDENT; "," LIST1 IDENT SEP "," [ "at" level | "in" "scope" IDENT ] | WITH LIST1 IDENT SEP "," [ "at" level | "in" "scope" IDENT ] ] explicit_subentry: [ | REPLACE "strict" "pattern" "at" "level" natural | WITH "strict" "pattern" OPT ( "at" "level" natural ) | DELETE "strict" "pattern" | DELETE "pattern" | REPLACE "pattern" "at" "level" natural | WITH "pattern" OPT ( "at" "level" natural ) | DELETE "constr" (* covered by another prod *) ] field_body: [ | REPLACE binders of_type_inst lconstr | WITH binders of_type_inst | REPLACE binders of_type_inst lconstr ":=" lconstr | WITH binders of_type_inst ":=" lconstr ] assum_list: [ | DELETE LIST1 assum_coe | LIST1 assum_coe ] assumpt: [ | REPLACE LIST1 ident_decl of_type lconstr | WITH LIST1 ident_decl of_type ] constructor_type: [ | REPLACE binders [ of_type_inst lconstr | ] | WITH binders OPT of_type_inst ] (* todo: is this really correct? Search for "Pvernac.register_proof_mode" *) (* consider tactic_command vs tac2mode *) vernac_aux: [ | tactic_mode "." ] def_token: [ | DELETE "SubClass" (* document separately from Definition and Example *) ] assumption_token: [ | REPLACE "Axiom" | WITH [ "Axiom" | "Axioms" ] | REPLACE "Conjecture" | WITH [ "Conjecture" | "Conjectures" ] | REPLACE "Hypothesis" | WITH [ "Hypothesis" | "Hypotheses" ] | REPLACE "Parameter" | WITH [ "Parameter" | "Parameters" ] | REPLACE "Variable" | WITH [ "Variable" | "Variables" ] ] attributes: [ | LIST0 ( "#[" LIST0 attribute SEP "," "]" ) LIST0 legacy_attr ] legacy_attr: [ | REPLACE "Local" | WITH [ "Local" | "Global" ] | DELETE "Global" | REPLACE "Polymorphic" | WITH [ "Polymorphic" | "Monomorphic" ] | DELETE "Monomorphic" | REPLACE "Cumulative" | WITH [ "Cumulative" | "NonCumulative" ] | DELETE "NonCumulative" ] sentence: [ ] (* productions defined below *) fix_definition: [ | REPLACE ident_decl binders_fixannot type_cstr OPT [ ":=" lconstr ] decl_notations | WITH ident_decl binders_fixannot type_cstr OPT [ ":=" lconstr ] decl_notations ] cofix_definition: [ | REPLACE ident_decl binders type_cstr OPT [ ":=" lconstr ] decl_notations | WITH ident_decl binders type_cstr OPT [ ":=" lconstr ] decl_notations ] type_cstr: [ | REPLACE ":" lconstr | WITH ":" type ] record_binder: [ | REPLACE name field_body | WITH name OPT field_body | DELETE name ] query_command: [ | REPLACE "Eval" red_expr "in" lconstr "." | WITH "Eval" red_expr "in" lconstr | REPLACE "Compute" lconstr "." | WITH "Compute" lconstr | REPLACE "Check" lconstr "." | WITH "Check" lconstr | REPLACE "About" smart_global OPT univ_name_list "." | WITH "About" smart_global OPT univ_name_list | REPLACE "SearchPattern" constr_pattern in_or_out_modules "." | WITH "SearchPattern" constr_pattern in_or_out_modules | REPLACE "SearchRewrite" constr_pattern in_or_out_modules "." | WITH "SearchRewrite" constr_pattern in_or_out_modules | REPLACE "Search" search_query search_queries "." | WITH "Search" search_queries ] vernac_toplevel: [ (* note these commands can't be referenced by vernac_control commands *) | REPLACE "Drop" "." | WITH "Drop" | REPLACE "Quit" "." | WITH "Quit" | REPLACE "BackTo" natural "." | WITH "BackTo" natural | REPLACE "Show" "Goal" natural "at" natural "." | WITH "Show" "Goal" natural "at" natural | REPLACE "Show" "Proof" "Diffs" OPT "removed" "." | WITH "Show" "Proof" OPT ( "Diffs" OPT "removed" ) | DELETE vernac_control | DELETE "Show" "." | DELETE "Show" natural "." | REPLACE "Show" "Diffs" qualid "." | WITH "Show" "Diffs" ident ] (* Pretend that control flags are commands *) control_flag: [ (* using sentence is cheating a little; after a control_flag can't refer to the vernac_toplevel commands. cover this in the descriptions of these commands *) | REPLACE "Time" | WITH "Time" sentence | REPLACE "Instructions" | WITH "Instructions" sentence | REPLACE "Profile" OPT STRING | WITH "Profile" OPT STRING sentence | REPLACE "Redirect" ne_string | WITH "Redirect" ne_string sentence | REPLACE "Timeout" natural | WITH "Timeout" natural sentence | REPLACE "Fail" | WITH "Fail" sentence | REPLACE "Succeed" | WITH "Succeed" sentence ] vernac_control: [ | DELETE LIST0 control_flag decorated_vernac | control_flag ] of_module_type: [ | (* empty *) ] rewriter: [ | DELETE "!" constr_with_bindings_arg | DELETE [ "?" | LEFTQMARK ] constr_with_bindings_arg | DELETE natural "!" constr_with_bindings_arg | DELETE natural [ "?" | LEFTQMARK ] constr_with_bindings_arg | DELETE natural constr_with_bindings_arg | DELETE constr_with_bindings_arg | OPT natural OPT [ "?" | "!" ] constr_with_bindings_arg ] ltac2_rewriter: [ | DELETE "!" ltac2_constr_with_bindings (* Ltac2 plugin *) | DELETE [ "?" | LEFTQMARK ] ltac2_constr_with_bindings | DELETE lnatural "!" ltac2_constr_with_bindings (* Ltac2 plugin *) | DELETE lnatural [ "?" | LEFTQMARK ] ltac2_constr_with_bindings | DELETE lnatural ltac2_constr_with_bindings (* Ltac2 plugin *) | DELETE ltac2_constr_with_bindings (* Ltac2 plugin *) | OPT natural OPT [ "?" | "!" ] ltac2_constr_with_bindings ] ltac2_expr0: [ | DELETE "(" ")" ] tac2type_body: [ | REPLACE ":=" tac2typ_knd (* Ltac2 plugin *) | WITH [ ":=" | "::=" ] tac2typ_knd TAG Ltac2 | DELETE "::=" tac2typ_knd (* Ltac2 plugin *) ] record_declaration: [ | DELETE fields_def | LIST0 field_def ] fields_def: [ | DELETENT ] scheme: [ | DELETE scheme_kind | REPLACE identref ":=" scheme_kind | WITH OPT ( identref ":=" ) scheme_kind ] simple_reserv: [ | REPLACE LIST1 identref ":" lconstr | WITH LIST1 identref ":" type ] in_clause: [ | DELETE in_clause' | REPLACE LIST1 hypident_occ SEP "," "|-" concl_occ | WITH LIST1 hypident_occ SEP "," OPT ( "|-" concl_occ ) | DELETE LIST1 hypident_occ SEP "," | REPLACE "*" occs | WITH concl_occ (* todo: perhaps concl_occ should be "*" | "at" occs_nums *) ] ltac2_in_clause: [ | REPLACE LIST0 ltac2_hypident_occ SEP "," "|-" ltac2_concl_occ (* Ltac2 plugin *) | WITH LIST0 ltac2_hypident_occ SEP "," OPT ( "|-" ltac2_concl_occ ) TAG Ltac2 | DELETE LIST0 ltac2_hypident_occ SEP "," (* Ltac2 plugin *) ] decl_notations: [ | REPLACE "where" LIST1 notation_declaration SEP decl_sep | WITH "where" notation_declaration LIST0 (decl_sep notation_declaration ) ] module_expr: [ | REPLACE module_expr_atom | WITH LIST1 module_expr_atom | DELETE module_expr module_expr_atom ] locatable: [ | INSERTALL "Locate" ] ne_in_or_out_modules: [ | REPLACE "inside" LIST1 global | WITH [ "inside" | "in" | "outside" ] LIST1 global | DELETE "in" LIST1 global | DELETE "outside" LIST1 global ] search_queries: [ | DELETE ne_in_or_out_modules | REPLACE search_query search_queries | WITH LIST1 ( search_query ) OPT ne_in_or_out_modules | DELETE (* empty *) ] positive_search_mark: [ | OPTINREF ] SPLICE: [ | positive_search_mark ] search_query: [ | REPLACE OPT "-" search_item | WITH search_item | "-" search_query | REPLACE OPT "-" "[" LIST1 ( LIST1 search_query ) SEP "|" "]" | WITH "[" LIST1 ( LIST1 search_query ) SEP "|" "]" ] search_item: [ | REPLACE search_where ":" ne_string OPT scope_delimiter | WITH OPT ( search_where ":" ) ne_string OPT ( "%" scope_key ) | DELETE ne_string OPT scope_delimiter | REPLACE search_where ":" constr_pattern | WITH OPT ( search_where ":" ) constr_pattern | DELETE constr_pattern ] by_notation: [ | REPLACE ne_string OPT [ "%" IDENT ] | WITH ne_string OPT [ "%" scope_key ] ] notation_declaration: [ | REPLACE lstring ":=" constr syntax_modifiers OPT [ ":" IDENT ] | WITH lstring ":=" constr syntax_modifiers OPT [ ":" scope_name ] ] ltac_production_item: [ | REPLACE ident "(" ident OPT ltac_production_sep ")" | WITH ident OPT ( "(" ident OPT ltac_production_sep ")" ) | DELETE ident ] input_fun: [ | DELETE ident | DELETE "_" | name ] let_clause: [ | DELETE identref ":=" ltac_expr5 | REPLACE "_" ":=" ltac_expr5 | WITH name ":=" ltac_expr5 ] subprf_with_selector: [ | DELETE query_command ] SPLICE: [ | subprf_with_selector ] tactic_mode: [ (* todo: make sure to document this production! *) (* deleting to allow splicing query_command into command *) | DELETE OPT ltac_selector OPT ltac_info tactic ltac_use_default | DELETE "par" ":" OPT ltac_info tactic "." (* Ignore attributes (none apply) and "...". *) | ltac_info tactic | MOVETO command ltac_info tactic | MOVETO simple_tactic subprf | REPLACE OPT toplevel_selector "{" (* semantically restricted *) | WITH OPT ( [ natural | "[" fullyqualid "]" ] ":" ) "{" | MOVETO simple_tactic OPT ( [ natural | "[" fullyqualid "]" ] ":" ) "{" | DELETE command | DELETENT ] SPLICE: [ | subprf ] ltac2_syntax_class: [ | REPLACE syn_node (* Ltac2 plugin *) | WITH name TAG Ltac2 | REPLACE syn_node "(" LIST1 ltac2_syntax_class SEP "," ")" (* Ltac2 plugin *) | WITH name "(" LIST1 ltac2_syntax_class SEP "," ")" TAG Ltac2 ] tac2mode: [ | DELETENT ] (* not sure how this is used *) tac2expr_in_env: [ | DELETENT ] syn_node: [ | DELETENT ] RENAME: [ | toplevel_selector toplevel_selector_temp ] toplevel_selector: [ | goal_selector | "all" | "!" (* par is accepted even though it's not in the .mlg *) | "par" ] toplevel_selector_temp: [ | DELETE goal_selector ":" | DELETE "all" ":" | DELETE "!" ":" | toplevel_selector ":" ] (* not included in insertprodn; defined in rst with :production: *) control_command: [ ] (* move all commands under "command" *) vernac_aux: [ | DELETE gallina "." | DELETE gallina_ext "." | DELETE syntax "." | DELETE command_entry | DELETENT ] command: [ | gallina | gallina_ext | syntax | query_command | vernac_control | vernac_toplevel ] SPLICE: [ | query_command | control_flag ] query_command: [ ] (* re-add as a placeholder *) sentence: [ | OPT attributes command "." | OPT attributes OPT ( natural ":" ) query_command "." | OPT attributes OPT ( toplevel_selector ":" ) ltac_expr5 [ "." | "..." ] | control_command ] document: [ | LIST0 sentence ] (* add in ltac and Tactic Notation tactics that appear in the doc: *) ltac_defined_tactics: [ | "case_eq" constr (* | "case_eq" induction_clause_list ??? *) | "classical_left" | "classical_right" | "contradict" ident | "easy" | "inversion_sigma" OPT ( ident OPT ( "as" simple_intropattern ) ) | "lia" | "lra" | "nia" | "now_show" one_type | "nra" | "rapply" constr | "tauto" | "time_constr" ltac_expr5 | "zify" ] (* todo: need careful review; assume that "[" ... "]" are literals *) tactic_notation_tactics: [ | "assert_fails" ltac_expr3 | "clear" "dependent" hyp | "decide" constr "with" constr | "dependent" "destruction" ident OPT ( "generalizing" LIST1 hyp ) OPT ( "using" constr ) | "dependent" "induction" ident OPT ( [ "generalizing" | "in" ] LIST1 hyp ) OPT ( "using" constr ) | "dintuition" OPT ltac_expr5 | "dtauto" | "field" OPT ( "[" LIST1 constr "]" ) | "field_simplify" OPT ( "[" LIST1 constr "]" ) LIST1 constr OPT ( "in" ident ) | "field_simplify_eq" OPT ( "[" LIST1 constr "]" ) OPT ( "in" ident ) | "intuition" OPT ltac_expr5 (* todo: Not too keen on things like "with_power_flags" in tauto.ml, not easy to follow *) | "now" ltac_expr5 | "nsatz" OPT ( "with" "radicalmax" ":=" constr "strategy" ":=" constr "parameters" ":=" constr "variables" ":=" constr ) | "ensatz" OPT ( "with" "strategy" ":=" constr ) | "psatz" constr OPT nat_or_var | "revert" "dependent" hyp | "ring" OPT ( "[" LIST1 constr "]" ) | "ring_simplify" OPT ( "[" LIST1 constr "]" ) LIST1 constr OPT ( "in" ident ) (* todo: ident was "hyp", worth keeping? *) ] (* defined in OCaml outside of mlgs *) tactic_value: [ | MOVEALLBUT simple_tactic ] nonterminal: [ ] value_tactic: [ ] syn_value: [ | IDENT; ":" "(" nonterminal ")" ] tactic_value: [ | [ value_tactic | syn_value ] ] (* defined in Ltac2/Notations.v *) ltac2_match_key: [ | "lazy_match!" | "match!" | "multi_match!" ] ltac2_constructs: [ | ltac2_match_key ltac2_expr6 "with" ltac2_match_list "end" | ltac2_match_key OPT "reverse" "goal" "with" goal_match_list "end" ] simple_tactic: [ | ltac_builtins | ltac_constructs | ltac2_constructs | ltac_defined_tactics | tactic_notation_tactics ] tacdef_body: [ | REPLACE global LIST1 input_fun ltac_def_kind ltac_expr5 | WITH global LIST0 input_fun ltac_def_kind ltac_expr5 | DELETE global ltac_def_kind ltac_expr5 ] tac2def_typ: [ | REPLACE "Type" rec_flag LIST1 tac2typ_def SEP "with" (* Ltac2 plugin *) | WITH "Type" rec_flag tac2typ_def LIST0 ( "with" tac2typ_def ) TAG Ltac2 ] tac2def_val: [ | REPLACE mut_flag rec_flag LIST1 tac2def_body SEP "with" (* Ltac2 plugin *) | WITH mut_flag rec_flag tac2def_body LIST0 ( "with" tac2def_body ) TAG Ltac1 ] tac2alg_constructors: [ | REPLACE "|" LIST1 tac2alg_constructor SEP "|" (* Ltac2 plugin *) | WITH OPT "|" LIST1 tac2alg_constructor SEP "|" TAG Ltac2 | DELETE LIST0 tac2alg_constructor SEP "|" (* Ltac2 plugin *) | (* empty *) | OPTINREF ] SPLICE: [ | def_token | extended_def_token ] logical_kind: [ | DELETE thm_token | DELETE assumption_token | [ thm_token | assumption_token ] | DELETE "Definition" | DELETE "Example" | DELETE "Context" | DELETE "Primitive" | DELETE "Symbol" (* SubClass was deleted from def_token *) | [ "Definition" | "Example" | "Context" | "Primitive" | "Symbol" ] | DELETE "Coercion" | DELETE "Instance" | DELETE "Scheme" | DELETE "Canonical" | [ "Coercion" | "Instance" | "Scheme" | "Canonical" | "SubClass" ] | DELETE "Fixpoint" | DELETE "CoFixpoint" | DELETE "Field" | DELETE "Method" | [ "Fixpoint" | "CoFixpoint" | "Field" | "Method" ] ] (* ltac2 *) DELETE: [ | test_ltac1_env ] rec_flag: [ | OPTINREF ] q_orient: [ | DELETE "<-" | REPLACE "->" | WITH OPT ["->" | "<-"] ] (* todo: should | tac2pat1 "," LIST0 tac2pat1 SEP "," use LIST1? *) SPLICE: [ | ltac2_expr4 ] ltac2_expr3: [ | REPLACE ltac2_expr2 "," LIST1 ltac2_expr2 SEP "," (* Ltac2 plugin *) | WITH LIST1 ltac2_expr2 SEP "," TAG Ltac2 | DELETE ltac2_expr2 (* Ltac2 plugin *) ] tac2rec_fieldexprs: [ | DELETE tac2rec_fieldexpr ";" tac2rec_fieldexprs | DELETE tac2rec_fieldexpr ";" | DELETE tac2rec_fieldexpr | LIST1 tac2rec_fieldexpr SEP ";" OPT ";" ] tac2rec_fields: [ | DELETE tac2rec_field ";" tac2rec_fields | DELETE tac2rec_field ";" | DELETE tac2rec_field | LIST1 tac2rec_field SEP ";" OPT ";" TAG Ltac2 ] int_or_var: [ | REPLACE integer | WITH [ integer | identref ] | DELETE identref ] nat_or_var: [ | REPLACE natural | WITH [ natural | identref ] | DELETE identref ] ltac2_occs_nums: [ | DELETE LIST1 nat_or_anti (* Ltac2 plugin *) | REPLACE "-" nat_or_anti LIST0 nat_or_anti (* Ltac2 plugin *) | WITH OPT "-" LIST1 nat_or_anti TAG Ltac2 ] ltac2_entry: [ | REPLACE tac2def_typ (* Ltac2 plugin *) | WITH "Ltac2" tac2def_typ | REPLACE tac2def_mut (* Ltac2 plugin *) | WITH "Ltac2" tac2def_mut | REPLACE tac2def_val (* Ltac2 plugin *) | WITH "Ltac2" tac2def_val | REPLACE tac2def_ext (* Ltac2 plugin *) | WITH "Ltac2" tac2def_ext | MOVEALLBUT command (* todo: MOVEALLBUT should ignore tag on "but" prodns *) ] ltac2_match_list: [ | EDIT ADD_OPT "|" LIST1 ltac2_match_rule SEP "|" (* Ltac2 plugin *) ] ltac2_or_and_intropattern: [ | DELETE "(" ltac2_simple_intropattern ")" (* Ltac2 plugin *) | REPLACE "(" ltac2_simple_intropattern "," LIST1 ltac2_simple_intropattern SEP "," ")" (* Ltac2 plugin *) | WITH "(" LIST1 ltac2_simple_intropattern SEP "," ")" TAG Ltac2 | REPLACE "(" ltac2_simple_intropattern "&" LIST1 ltac2_simple_intropattern SEP "&" ")" (* Ltac2 plugin *) | WITH "(" LIST1 ltac2_simple_intropattern SEP "&" ")" TAG Ltac2 ] ltac2_equality_intropattern: [ | REPLACE "[" "=" ltac2_intropatterns "]" | WITH "[=" ltac2_intropatterns "]" ] SPLICE: [ | tac2def_val | tac2def_typ | tac2def_ext | tac2def_syn | tac2abbrev_syn | ltac2def_syn | ltac2abbrev_syn | tac2def_mut | rec_flag | tac2alg_constructors | ltac2_binder | branch | anti | array_literal | list_literal ] ltac2_expr5: [ | REPLACE "let" OPT "rec" LIST1 ltac2_let_clause SEP "with" "in" ltac2_expr6 (* Ltac2 plugin *) | WITH "let" OPT "rec" ltac2_let_clause LIST0 ( "with" ltac2_let_clause ) "in" ltac2_expr6 TAG Ltac2 | MOVETO simple_tactic "match" ltac2_expr5 "with" ltac2_branches "end" (* Ltac2 plugin *) | MOVETO simple_tactic "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5 (* Ltac2 plugin *) | DELETE simple_tactic ] ltac2_quotations: [ ] ltac2_atom: [ | MOVETO ltac2_quotations "constr" ":" "(" lconstr ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "open_constr" ":" "(" lconstr ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "preterm" ":" "(" lconstr ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "ident" ":" "(" identref ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "pat" ":" "(" cpattern ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "reference" ":" "(" globref ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "ltac1" ":" "(" ltac1_expr_in_env ")" (* Ltac2 plugin *) | MOVETO ltac2_quotations "ltac1val" ":" "(" ltac1_expr_in_env ")" (* Ltac2 plugin *) ] (* non-Ltac2 "clause" is really clause_dft_concl + there is an ltac2 "clause" *) ltac2_clause: [ ] clause: [ | MOVEALLBUT ltac2_clause ] clause: [ | clause_dft_concl ] q_clause: [ | REPLACE clause | WITH ltac2_clause TAG Ltac2 ] ltac2_induction_clause: [ | REPLACE ltac2_destruction_arg ltac2_as_or_and_ipat ltac2_eqn_ipat OPT clause (* Ltac2 plugin *) | WITH ltac2_destruction_arg ltac2_as_or_and_ipat ltac2_eqn_ipat OPT ltac2_clause TAG Ltac2 ] ltac2_constr_delimiters_arg: [ | scope_key | "delimiters" "(" LIST1 scope_key SEP "," ")" ] ltac2_constr_synclass_arg: [ | ltac2_constr_delimiters_arg | "custom" "(" qualid ")" | "level" "(" natural ")" ] starredidentref: [ | EDIT identref ADD_OPT "*" | EDIT "Type" ADD_OPT "*" | "All" ] ssexpr0: [ | DELETE "(" LIST0 starredidentref ")" | DELETE "(" LIST0 starredidentref ")" "*" | DELETE "(" ssexpr35 ")" | DELETE "(" ssexpr35 ")" "*" | "(" section_subset_expr ")" OPT "*" ] ssexpr35: [ | EDIT ADD_OPT "-" ssexpr50 ] simple_binding: [ | REPLACE "(" identref ":=" lconstr ")" | WITH "(" [ ident | natural ] ":=" lconstr ")" | DELETE "(" natural ":=" lconstr ")" ] ltac2_expr: [ | DELETE _ltac2_expr ] opt_clause: [ | DELETE "in" in_clause | DELETE "at" occs_nums | DELETE | clause_dft_concl ] fixdecl: [ | REPLACE "(" ident LIST0 simple_binder struct_annot ":" lconstr ")" | WITH "(" ident LIST0 simple_binder struct_annot ":" type ")" ] cofixdecl: [ | REPLACE "(" ident LIST0 simple_binder ":" lconstr ")" | WITH "(" ident LIST0 simple_binder ":" type ")" ] OPTINREF: [ ] destruction_arg: [ | DELETE constr_with_bindings ] firstorder_rhs: [ | DELETE OPT firstorder_using | DELETE "with" LIST1 preident | REPLACE OPT firstorder_using "with" LIST1 preident | WITH OPT firstorder_using OPT ( "with" LIST1 preident ) ] attribute: [ | DELETE "using" OPT attr_value ] ref_or_pattern_occ: [ | DELETE smart_global OPT occs | DELETE constr OPT occs | unfold_occ | pattern_occ ] clause_dft_concl: [ (* omit an OPT since clause_dft_concl is always OPT *) | REPLACE OPT occs | WITH occs ] simple_occurrences: [ | clause_dft_concl (* semantically restricted: no "at" clause *) ] occs_nums: [ | EDIT ADD_OPT "-" LIST1 nat_or_var ] variance_identref: [ | EDIT ADD_OPT variance identref ] conversion: [ | DELETE constr | DELETE constr "with" constr | REPLACE constr "at" occs_nums "with" constr | WITH OPT ( constr OPT ( "at" occs_nums ) "with" ) constr ] induction_principle: [ | eliminator opt_clause ] induction_clause: [ | REPLACE destruction_arg OPT as_or_and_ipat OPT eqn_ipat opt_clause | WITH destruction_arg OPT as_or_and_ipat OPT eqn_ipat opt_clause ] induction_clause_list: [ | DELETE LIST1 induction_clause SEP "," OPT eliminator opt_clause | LIST1 induction_clause SEP "," OPT induction_principle ] (* see https://github.com/rocq-prover/rocq/pull/14179#discussion_r654000296 *) as_or_and_ipat: [ | DELETE "as" or_and_intropattern_loc | DELETE "as" equality_intropattern | "as" or_and_intropattern ] ne_rewstrategy1_list_sep_semicolon: [ | DELETE rewstrategy1 | REPLACE ne_rewstrategy1_list_sep_semicolon ";" rewstrategy1 | WITH LIST1 rewstrategy1 SEP ";" ] SPLICE: [ | ne_rewstrategy1_list_sep_semicolon | clause | noedit_mode | match_list | match_context_list | IDENT | LEFTQMARK | NUMBER | STRING | hyp | identref | pattern_ident | constr_eval (* splices as multiple prods *) | tactic_then_last (* todo: dependency on c.edit_mlg edit?? really useful? *) | ltac2_tactic_then_last | Prim.name | ltac_selector | Constr.ident | attribute_list | term90 | term9 | term8 | pattern200 | pattern99 | pattern90 | ne_lstring | ne_string | lstring | fullyqualid | global | reference | bar_cbrace | lconstr | preident | lpar_id_coloneq | binders | check_module_types | decl_sep | function_fix_definition (* loses funind annotation *) | glob | glob_constr_with_bindings | id_or_meta | lglob | ltac_tacdef_body | mode | mult_pattern | open_constr | record_declaration | tactic | uconstr | impl_ident_head | branches | check_module_type | decorated_vernac | ext_module_expr | ext_module_type | test | binder_constr | atomic_constr | let_type_cstr | name_colon | closed_binder | binders_fixannot | as_return_type | case_type | universe_increment | type_cstr | record_pattern | evar_instance | fix_decls | cofix_decls | assum_list | assum_coe | inline | occs | ltac_info | field_mods | ltac_production_sep | ltac_tactic_level | printunivs_subgraph | ring_mods | eliminator (* todo: splice or not? *) | quoted_attributes (* todo: splice or not? *) | printable | hint | record_fields | constructor_type | record_binder | at_level_opt | table_value | in_or_out_modules | option_setting | orient | with_bindings | by_arg_tac | by_tactic | quantified_hypothesis | in_hyp_list | rename | export_token | reserv_tuple | inst | default_inhabitant_ident | opt_coercion | opt_constructors_or_fields | is_module_type | is_module_expr | module_expr | mlname | withtac | debug | eauto_search_strategy | reference_or_constr | opt_hintbases | opthints | scheme | fresh_id | ltac_def_kind | intropatterns | instance_name | failkw | ne_in_or_out_modules | search_queries | locatable | scope_delimiter | one_import_filter_name | search_where | message_token | input_fun | ltac_use_default | toplevel_selector_temp | comment | register_token | match_context_rule | match_rule | by_notation | lnatural | nat_or_anti | globref | let_binder | refglobals (* Ltac2 *) | syntax_modifiers | array_elems | G_LTAC2_input_fun | ltac2_with_bindings | int_or_id | fun_ind_using | with_names | eauto_search_strategy_name | simple_binding | ssexpr35 (* strange in mlg, ssexpr50 is after this *) | number_string_mapping | number_options | string_option | tac2type_body | tac2rec_fields | mut_flag | tac2rec_fieldexprs | syn_level | firstorder_rhs | firstorder_using | ref_or_pattern_occ | cumul_ident_decl | variance | variance_identref | rewriter | clause_dft_all | or_and_intropattern_loc | eqn_ipat | conversion | type_cast | opt_clause | struct_annot | fixdecl | cofixdecl | induction_clause_list | as_or_and_ipat | singleton_class_definition | constr_with_bindings_arg | enable_enable_disable | enable_notation_rule | enable_notation_interpretation | enable_notation_flags | opt_scope | located_notation | ltac_expr1l ] (* end SPLICE *) RENAME: [ | occurrences rewrite_occs ] RENAME: [ | tactic3 ltac_expr3 (* todo: can't figure out how this gets mapped by coqpp *) | tactic1 ltac_expr1 (* todo: can't figure out how this gets mapped by coqpp *) | tactic0 ltac_expr0 (* todo: can't figure out how this gets mapped by coqpp *) | ltac_expr5 ltac_expr (* | nonsimple_intropattern intropattern (* ltac2 *) *) | term200 term | pattern100 pattern (*| impl_ident_tail impl_ident*) | ssexpr50 section_var_expr50 | ssexpr0 section_var_expr0 | section_subset_expr section_var_expr | fun_scheme_arg func_scheme_def | BULLET bullet | constr one_term (* many, many, many *) | smart_global reference (* many, many *) (* | searchabout_query search_item *) | ltac2_type5 ltac2_type | ltac2_expr6 ltac2_expr | starredidentref starred_ident_ref | constr_pattern one_pattern | hints_path_entry hints_regexp | clause_dft_concl occurrences | in_clause goal_occurrences | unfold_occ reference_occs | pattern_occ pattern_occs | hypident_occ hyp_occs | concl_occ concl_occs | constr_with_bindings one_term_with_bindings | red_flag reduction | strategy_flag reductions | delta_flag delta_reductions | q_strategy_flag q_reductions | destruction_arg induction_arg | field_body field_spec | field_def field_val | bindings_with_parameters alias_definition ] bullet: [ | [ LIST1 "-" | LIST1 "+" | LIST1 "*" ] ] simple_tactic: [ (* due to renaming of tactic_value; Use LIST1 for function application *) | qualid LIST1 tactic_arg ] SPLICE: [ | gallina | gallina_ext | syntax | vernac_control | vernac_toplevel | command_entry | ltac_builtins | ltac_constructs | ltac2_constructs | ltac_defined_tactics | tactic_notation_tactics | bullet ] REACHABLE: [ | command | simple_tactic ] NOTINRSTS: [ | command | control_command | simple_tactic | hints_regexp (* manually inserted *) | REACHABLE | NOTINRSTS | l1_tactic | l2_tactic | l3_tactic | value_tactic | ltac2_entry (* ltac2 syntactic classes *) | q_intropatterns | q_intropattern | q_ident | q_destruction_arg | q_with_bindings | q_bindings | q_reductions | q_reference | q_clause | q_occurrences | q_induction_clause | q_conversion | q_rewriting | q_dispatch | q_hintdb | q_move_location | q_pose | q_assert | q_constr_matching | q_goal_matching ] REACHABLE: [ | NOTINRSTS ] rocq-9.2.0/doc/tools/docgram/doc_grammar.ml000066400000000000000000002052311516144147600206300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if plist then sprintf "%s" s else sprintf "\"%s\"" s | Snterm s -> if plist then sprintf "`%s`" s else sprintf "%s%s" s (if s = "IDENT" && need_semi then ";" else "") | Slist1 sym -> sprintf "LIST1 %s" (prod_to_str ~plist [sym]) | Slist1sep (sym, sep) -> sprintf "LIST1 %s SEP %s" (prod_to_str ~plist [sym]) (prod_to_str ~plist [sep]) | Slist0 sym -> sprintf "LIST0 %s" (prod_to_str ~plist [sym]) | Slist0sep (sym, sep) -> sprintf "LIST0 %s SEP %s" (prod_to_str ~plist [sym]) (prod_to_str ~plist [sep]) | Sopt sym -> sprintf "OPT %s" (prod_to_str ~plist [sym]) | Sparen sym_list -> sprintf "( %s )" (prod_to_str sym_list) | Sprod sym_list_list -> sprintf "[ %s ]" (String.concat " " (List.mapi (fun i r -> let prod = (prod_to_str r) in let sep = if i = 0 then "" else if prod <> "" then "| " else "|" in sprintf "%s%s" sep prod) sym_list_list)) | Sedit s -> sprintf "%s" s (* todo: make TAG info output conditional on the set of prods? *) | Sedit2 ("TAG", plugin) -> if plist then sprintf " (%s plugin)" plugin else sprintf " (* %s plugin *)" plugin | Sedit2 ("FILE", file) -> let file_suffix_regex = Str.regexp ".*/\\([a-zA-Z0-9_\\.]+\\)" in let suffix = if Str.string_match file_suffix_regex file 0 then Str.matched_group 1 file else file in if plist then sprintf " (%s)" suffix else sprintf " (* %s *)" suffix | Sedit2 (s, s2) -> sprintf "%s \"%s\"" s s2 and prod_to_str_r plist prod = match prod with | Sterm s :: Snterm "ident" :: tl when omit_space s && plist -> (sprintf "%s`ident`" s) :: (prod_to_str_r plist tl) | p :: tl -> let need_semi = match prod with | Snterm "IDENT" :: Sterm _ :: _ | Snterm "IDENT" :: Sprod _ :: _ -> true | _ -> false in (output_prod plist need_semi p) :: (prod_to_str_r plist tl) | [] -> [] and prod_to_str ?(plist=false) prod = String.concat " " (prod_to_str_r plist prod) (* Determine if 2 productions are equal ignoring Sedit and Sedit2 *) let ematch prod edit = let rec ematchr prod edit = (*Printf.printf "%s and\n %s\n\n" (prod_to_str prod) (prod_to_str edit);*) match (prod, edit) with | (_, Sedit _ :: tl) | (_, Sedit2 _ :: tl) -> ematchr prod tl | (Sedit _ :: tl, _) | (Sedit2 _ :: tl, _) -> ematchr tl edit | (phd :: ptl, hd :: tl) -> let m = match (phd, hd) with | (Slist1 psym, Slist1 sym) | (Slist0 psym, Slist0 sym) | (Sopt psym, Sopt sym) -> ematchr [psym] [sym] | (Slist1sep (psym, psep), Slist1sep (sym, sep)) | (Slist0sep (psym, psep), Slist0sep (sym, sep)) -> ematchr [psym] [sym] && ematchr [psep] [sep] | (Sparen psyml, Sparen syml) -> ematchr psyml syml | (Sprod psymll, Sprod symll) -> if List.compare_lengths psymll symll != 0 then false else List.fold_left (&&) true (List.map2 ematchr psymll symll) | _, _ -> phd = hd in m && ematchr ptl tl | ([], hd :: tl) -> false | (phd :: ptl, []) -> false | ([], []) -> true in (*Printf.printf "\n";*) let rv = ematchr prod edit in (*Printf.printf "%b\n" rv;*) rv let get_first m_prod prods = let rec find_first_r prods i = match prods with | [] -> raise Not_found | prod :: tl -> if ematch prod m_prod then i else find_first_r tl (i+1) in find_first_r prods 0 let pploc out = function | None -> () | Some loc -> Printf.fprintf out "File %s line %d: " loc.loc_start.pos_fname loc.loc_start.pos_lnum let find_first ~loc edit prods nt = try get_first edit prods with Not_found -> error "%aCan't find '%s' in edit for '%s'\n" pploc loc (prod_to_str edit) nt; raise Not_found module DocGram = struct (* these guarantee that order and map have a 1-1 relationship on the nt name. They don't guarantee that nts on rhs of a production are defined, nor do they prohibit duplicate productions *) exception Duplicate exception Invalid let g_empty () = ref { map = NTMap.empty; order = [] } (* add an nt at the end (if not already present) then set its prods *) let g_maybe_add g nt prods = if not (NTMap.mem nt !g.map) then g := { !g with order = !g.order @ [nt] }; g := { !g with map = NTMap.add nt prods !g.map } (* add an nt at the beginning (if not already present) then set its prods *) let g_maybe_add_begin g nt prods = if not (NTMap.mem nt !g.map) then g := { !g with order = nt :: !g.order }; g := { !g with map = NTMap.add nt prods !g.map } (* reverse the order of the grammar *) let g_reverse g = g := { !g with order = List.rev !g.order } (* update the productions of an existing nt *) let g_update_prods g nt prods = ignore (NTMap.find nt !g.map); (* don't add the nt if it's not present *) g := { !g with map = NTMap.add nt prods !g.map } (* remove a non-terminal *) let g_remove g nt = g := { map = NTMap.remove nt !g.map; order = List.filter (fun elt -> elt <> nt) !g.order } (* rename an nt and update its prods, keeping its original position. If the new name already exists, include its prods *) let g_rename_merge g nt nt' nprods = let oprods = try let oprods = NTMap.find nt' !g.map in g := { !g with order = List.filter (fun elt -> elt <> nt') !g.order }; oprods with Not_found -> g := { !g with map = NTMap.add nt' [] !g.map }; [] in g := { map = NTMap.remove nt !g.map; order = List.map (fun n -> if n = nt then nt' else n) !g.order }; g_update_prods g nt' (oprods @ nprods) (* add a new nonterminal after "ins_after" None means insert at the beginning *) let g_add_after g ?(update=true) ins_after nt prods = if (not update) && NTMap.mem nt !g.map then raise Duplicate; (* don't update the nt if it's already present *) let rec insert_nt order res = match ins_after, order with | None, _ -> nt :: order | Some _, [] -> raise Not_found | Some ins_after_nt, hd :: tl -> if hd = ins_after_nt then (List.rev res) @ (hd :: nt :: tl) else insert_nt tl (hd :: res) in g := { order = insert_nt !g.order []; map = NTMap.add nt prods !g.map } let g_add_prod_after g ins_after nt prod = let prods = try NTMap.find nt !g.map with Not_found -> [] in if prods <> [] then g_update_prods g nt (prods @ [prod]) else g_add_after g ~update:true ins_after nt [prod] (* replace the map and order *) let g_reorder g map order = let order_nts = StringSet.of_list order in let map_nts = List.fold_left (fun res b -> let (nt, _) = b in StringSet.add nt res) StringSet.empty (NTMap.bindings map) in if List.length order <> NTMap.cardinal map || not (StringSet.equal order_nts map_nts) then raise Invalid; g := { order = order; map = map } end open DocGram let remove_Sedit2 p = List.filter (fun sym -> match sym with | Sedit2 _ -> false | _ -> true) p let rec output_prodn = function | Sterm s -> let s = match s with | "|}" -> "%|%}" | "{|" -> "%{%|" | "`{" -> "`%{" | "@{" -> "@%{" | "|-" -> "%|-" | "|->" -> "%|->" | "||" -> "%||" | "|||" -> "%|||" | "||||" -> "%||||" | "{" | "}" | "|" -> "%" ^ s | _ -> s in sprintf "%s" s | Snterm s -> sprintf "@%s" s | Slist1 sym -> sprintf "{+ %s }" (output_prodn sym) | Slist1sep (sym, sep) -> sprintf "{+%s %s }" (output_sep sep) (output_prodn sym) | Slist0 sym -> sprintf "{* %s }" (output_prodn sym) | Slist0sep (sym, sep) -> sprintf "{*%s %s }" (output_sep sep) (output_prodn sym) | Sopt sym -> sprintf "{? %s }" (output_prodn sym) | Sparen sym_list -> sprintf "%s" (prod_to_prodn sym_list) | Sprod sym_list -> let lcurly, rcurly = if List.length sym_list = 1 then "", "" else "{| ", " }" in sprintf "%s%s%s" lcurly (String.concat " " (List.mapi (fun i r -> let prod = (prod_to_prodn r) in let sep = if i = 0 then "" else if prod <> "" then "| " else "|" in sprintf "%s%s" sep prod) sym_list)) rcurly | Sedit s -> sprintf "%s" s | Sedit2 ("TAG", s2) -> "" | Sedit2 (s, s2) -> sprintf "%s \"%s\"" s s2 and output_sep sep = match sep with | Sterm s -> sprintf "%s" s (* avoid escaping separator *) | _ -> output_prodn sep and prod_to_prodn_r prod = match prod with | Sterm s :: Snterm "ident" :: tl when omit_space s -> (sprintf "%s@ident" s) :: (prod_to_prodn_r tl) | p :: tl -> (output_prodn p) :: (prod_to_prodn_r tl) | [] -> [] and prod_to_prodn prod = String.concat " " (prod_to_prodn_r (remove_Sedit2 prod)) let get_tag file prod = List.fold_left (fun rv sym -> match sym with (* todo: only Ltac2 and SSR for now, outside of their main chapters *) | Sedit2 ("TAG", "Ltac2") when file <> "doc/sphinx/proof-engine/ltac2.rst" -> " Ltac2" | Sedit2 ("TAG", "SSR") when file <> "doc/sphinx/proof-engine/ssreflect-proof-language.rst" -> " SSR" | _ -> rv ) "" prod let pr_prods nt prods = (* duplicative *) Printf.printf "%s: [\n" nt; List.iter (fun prod -> let str = prod_to_str ~plist:false prod in let pfx = if str = "" then "|" else "| " in Printf.printf "%s%s\n" pfx str) prods; Printf.printf "]\n\n" (* print a subset of the grammar with nts in the specified order *) let print_in_order out g fmt nt_order hide = List.iter (fun nt -> if not (StringSet.mem nt hide) then try let prods = NTMap.find nt !g.map in match fmt with | `MLG -> fprintf out "%s: [\n" nt; List.iter (fun prod -> let str = prod_to_str ~plist:false prod in let pfx = if str = "" then "|" else "| " in fprintf out "%s%s\n" pfx str) prods; fprintf out "]\n\n" | `PRODLIST -> fprintf out "%s :" nt; List.iteri (fun i prod -> if i > 0 then fprintf out "%s :" (String.make (String.length nt) ' '); let str = prod_to_str ~plist:true prod in let pfx = if str = "" then "" else " " in fprintf out "%s%s\n" pfx str) prods; | `PRODN -> fprintf out "\n%s:\n%s " nt nt; List.iteri (fun i prod -> let str = prod_to_prodn prod in let op = if i = 0 then "::=" else "+=" in fprintf out "%s %s\n" op str) prods; with Not_found -> error "Missing nt '%s' in print_in_order\n" nt) nt_order (*** Read grammar routines ***) let cvt_ext prod = let rec to_doc_sym = function | Ulist1 sym -> Slist1 (to_doc_sym sym) | Ulist1sep (sym, s) -> Slist1sep ((to_doc_sym sym), Sterm s) | Ulist0 sym -> Slist0 (to_doc_sym sym) | Ulist0sep (sym, s) -> Slist0sep ((to_doc_sym sym), Sterm s) | Uopt sym -> Sopt (to_doc_sym sym) | Uentry s -> Snterm s | Uentryl (s, i) -> Snterm (s ^ (string_of_int i)) in let from_ext = function | ExtTerminal s -> Sterm s | ExtNonTerminal (s, _) -> to_doc_sym s in List.map from_ext prod let keywords = ref StringSet.empty let rec cvt_gram_sym = function | GSymbString s -> Sterm s | GSymbQualid (s, level) -> Snterm (match level with | Some str -> s ^ str | None -> s) | GSymbParen l -> Sparen (cvt_gram_sym_list l) | GSymbProd ll -> let cvt = List.map cvt_gram_prod ll in (match cvt with | (_, Snterm x :: []) :: [] -> Snterm x | (_, Sterm x :: []) :: [] -> Sterm x | _ -> Sprod (List.map snd cvt)) and cvt_gram_sym_list l = let get_sym = function | GSymbQualid (s, level) -> s | _ -> "" in match l with | GSymbQualid ("LIST0", _) :: s :: GSymbQualid ("SEP", _) :: sep :: tl -> Slist0sep (cvt_gram_sym s, cvt_gram_sym sep) :: cvt_gram_sym_list tl | GSymbQualid ("LIST1", _) :: s :: GSymbQualid ("SEP", _) :: sep :: tl -> Slist1sep (cvt_gram_sym s, cvt_gram_sym sep) :: cvt_gram_sym_list tl | GSymbQualid ("LIST0", _) :: s :: tl -> Slist0 (cvt_gram_sym s) :: cvt_gram_sym_list tl | GSymbQualid ("LIST1", _) :: s :: tl -> Slist1 (cvt_gram_sym s) :: cvt_gram_sym_list tl | GSymbQualid ("OPT", _) :: s :: tl -> Sopt (cvt_gram_sym s) :: cvt_gram_sym_list tl | GSymbQualid ("IDENT", _) :: s2 :: tl when get_sym s2 = "" -> cvt_gram_sym s2 :: cvt_gram_sym_list tl | GSymbQualid ("ADD_OPT", _) :: tl -> (Sedit "ADD_OPT") :: cvt_gram_sym_list tl | GSymbQualid ("NOTE", _) :: GSymbQualid (s2, l) :: tl -> (Sedit2 ("NOTE", s2)) :: cvt_gram_sym_list tl | GSymbQualid ("USE_NT", _) :: GSymbQualid (s2, l) :: tl -> (Sedit2 ("USE_NT", s2)) :: cvt_gram_sym_list tl | GSymbQualid ("TAG", _) :: GSymbQualid (s2, l) :: tl -> (Sedit2 ("TAG", s2)) :: cvt_gram_sym_list tl | GSymbQualid ("TAG", _) :: GSymbString (s2) :: tl -> (Sedit2 ("TAG", s2)) :: cvt_gram_sym_list tl | GSymbString s :: tl -> (* todo: not seeing "(bfs)" here for some reason *) keywords := StringSet.add s !keywords; cvt_gram_sym (GSymbString s) :: cvt_gram_sym_list tl | hd :: tl -> cvt_gram_sym hd :: cvt_gram_sym_list tl | [] -> [] and cvt_gram_prod p = p.gprod_body.loc, List.concat (List.map (fun x -> let _, gs = x in cvt_gram_sym_list gs) p.gprod_symbs) let add_symdef nt file symdef_map = let ent = try StringMap.find nt !symdef_map with Not_found -> [] in symdef_map := StringMap.add nt (Filename.basename file::ent) !symdef_map let rec edit_SELF nt cur_level next_level left_assoc right_assoc inner prod = let subedit sym = List.hd (edit_SELF nt cur_level next_level left_assoc right_assoc true [sym]) in let len = List.length prod in List.mapi (fun i sym -> match sym with | Sterm _ -> sym | Snterm s when s = nt || s = "SELF"-> if inner then Snterm nt (* first level *) else if i = 0 then (if left_assoc then Snterm cur_level else Snterm next_level) else if i + 1 = len then (if right_assoc then Snterm cur_level else Snterm next_level) else Snterm nt | Snterm "NEXT" -> Snterm next_level | Snterm _ -> sym | Slist1 sym -> Slist1 (subedit sym) | Slist0 sym -> Slist0 (subedit sym) | Slist1sep (sym, sep) -> Slist1sep ((subedit sym), (subedit sep)) | Slist0sep (sym, sep) -> Slist0sep ((subedit sym), (subedit sep)) | Sopt sym -> Sopt (subedit sym) | Sparen syms -> Sparen (List.map (fun sym -> subedit sym) syms) | Sprod prods -> Sprod (List.map (fun prod -> edit_SELF nt cur_level next_level left_assoc right_assoc true prod) prods) | Sedit _ -> sym | Sedit2 _ -> sym) prod let autoloaded_mlgs = [ (* productions from other mlgs are marked with TAGs *) "parsing/g_constr.mlg"; "parsing/g_prim.mlg"; "plugins/btauto/g_btauto.mlg"; "plugins/cc/g_congruence.mlg"; "plugins/firstorder/g_ground.mlg"; "plugins/ltac/coretactics.mlg"; "plugins/ltac/extraargs.mlg"; "plugins/ltac/extratactics.mlg"; "plugins/ltac/g_auto.mlg"; "plugins/ltac/g_class.mlg"; "plugins/ltac/g_eqdecide.mlg"; "plugins/ltac/g_ltac.mlg"; "plugins/ltac/g_obligations.mlg"; "plugins/ltac/g_rewrite.mlg"; "plugins/ltac/g_tactic.mlg"; "plugins/ltac/profile_ltac_tactics.mlg"; "plugins/rtauto/g_rtauto.mlg"; "plugins/syntax/g_number_string.mlg"; "toplevel/g_toplevel.mlg"; "vernac/g_proofs.mlg"; "vernac/g_vernac.mlg"; ] let has_match p prods = List.exists (fun p2 -> ematch p p2) prods let plugin_regex = Str.regexp "^plugins/\\([a-zA-Z0-9_]+\\)/" let level_regex = Str.regexp "[a-zA-Z0-9_]*l?$" let get_plugin_name file = if Str.string_match plugin_regex file 0 then let s = Str.matched_group 1 file in if List.mem s ["ssr"; "ssrmatching"] then "SSR" else s else "" let read_mlg g is_edit ast file level_renames symdef_map = let res = ref [] in let locals = ref StringSet.empty in let dup_renames = ref StringMap.empty in let add_prods nt prods gramext_globals = if not is_edit && NTMap.mem nt g.map && not (List.mem nt gramext_globals) && nt <> "command" && nt <> "simple_tactic" then begin let new_name = String.uppercase_ascii (Filename.remove_extension (Filename.basename file)) ^ "_" ^ nt in dup_renames := StringMap.add nt new_name !dup_renames; if false then Printf.printf "** dup local sym %s -> %s in %s\n" nt new_name file end; add_symdef nt file symdef_map; let plugin = get_plugin_name file in let prods = if not is_edit && not (List.mem file autoloaded_mlgs) && plugin <> "" then List.map (fun (loc,p) -> loc, p @ [Sedit2 ("TAG", plugin)]) prods else prods in (* todo: doesn't yet work perfectly with SPLICE *) (* let prods = if not is_edit then List.map (fun p -> p @ [Sedit2 ("FILE", file)]) prods else prods in*) res := (nt, prods) :: !res in let prod_loop = function | GramExt grammar_ext -> let get_label = function | Some s -> s | None -> "" in let gramext_globals = ref grammar_ext.gramext_globals in List.iter (fun ent -> let pos, rules = match ent.gentry_rules with | GDataFresh (pos, r) -> (pos, r) | GDataReuse (lbl, r) -> let r = { grule_label = lbl; grule_assoc = None; grule_prods = r; } in (None, [r]) in let len = List.length rules in List.iteri (fun i rule -> let nt = ent.gentry_name in if not (List.mem nt !gramext_globals) then locals := StringSet.add nt !locals; let level = (get_label rule.grule_label) in let level = if level <> "" then level else match pos with | Some (Before lev) | Some (After lev) -> lev (* Looks like FIRST/LAST can be ignored for documenting the current grammar *) | _ -> "" in if len > 1 && level = "" then error "Missing level string for '%s'\n" nt else if not (Str.string_match level_regex level 0) then error "Invalid level string '%s' for '%s'\n" level nt; let cur_level = nt ^ level in let next_level = nt ^ if i+1 < len then (get_label (List.nth rules (i+1)).grule_label) else "" in let (left_assoc, right_assoc) = match rule.grule_assoc with | Some NonA | None -> (false, false) | Some LeftA -> (true, false) | Some RightA -> (false, true) | Some BothA -> (true, true) in if i = 0 && cur_level <> nt && not (StringMap.mem nt !level_renames) then begin level_renames := StringMap.add nt cur_level !level_renames; end; let cvted = List.map cvt_gram_prod rule.grule_prods in (* edit names for levels *) (* See https://camlp5.github.io/doc/html/grammars.html#b:Associativity *) let edited = List.map (fun (loc,prod) -> loc, edit_SELF nt cur_level next_level left_assoc right_assoc false prod) cvted in let prods_to_add = if cur_level <> nt && i+1 < len then edited @ [None,[Snterm next_level]] else edited in if cur_level <> nt && List.mem nt !gramext_globals then gramext_globals := cur_level :: !gramext_globals; add_prods cur_level prods_to_add !gramext_globals) rules ) grammar_ext.gramext_entries | VernacExt vernac_ext -> let node = match vernac_ext.vernacext_entry with | None -> "command" | Some c -> String.trim c.code in add_prods node (List.map (fun r -> None, cvt_ext r.vernac_toks) vernac_ext.vernacext_rules) [] | VernacArgumentExt vernac_argument_ext -> add_prods vernac_argument_ext.vernacargext_name (List.map (fun r -> None, cvt_ext r.tac_toks) vernac_argument_ext.vernacargext_rules) [] | TacticExt tactic_ext -> add_prods "simple_tactic" (List.map (fun r -> None, cvt_ext r.tac_toks) tactic_ext.tacext_rules) [] | ArgumentExt argument_ext -> add_prods argument_ext.argext_name (List.map (fun r -> None, cvt_ext r.tac_toks) argument_ext.argext_rules) [] | _ -> () in List.iter prod_loop ast; List.rev !res, !locals, !dup_renames let dir s = "doc/tools/docgram/" ^ s let read_mlg_edit file = let fdir = dir file in let level_renames = ref StringMap.empty in (* ignored *) let symdef_map = ref StringMap.empty in (* ignored *) let prods, _, _ = read_mlg !(g_empty ()) true (Coqpp_parser.parse_file fdir) fdir level_renames symdef_map in prods let add_rule g nt prods file = let ent = try NTMap.find nt !g.map with Not_found -> [] in let nodups = List.concat (List.map (fun (_,prod) -> if has_match prod ent then begin if !show_warn then warn "%s: Duplicate production '%s -> %s'\n" file nt (prod_to_str prod); [] end else [prod]) prods) in g_maybe_add_begin g nt (ent @ nodups) let remove_Sedit2 p = List.filter (fun sym -> match sym with | Sedit2 _ -> false | _ -> true) p let check_for_duplicates cause rule oldrule nt = let prods = List.map (fun p -> prod_to_str p) rule in let sorted = List.sort String.compare prods in let rec aux prev = function | hd :: tl -> if hd = prev then begin if (List.length (List.filter (fun p -> (prod_to_str p) = hd) rule)) <> (List.length (List.filter (fun p -> (prod_to_str p) = hd) oldrule)) then error "Duplicate production '%s -> %s' %s\n%!" nt hd cause end; aux hd tl | [] -> () in aux " x " sorted (* edit a production: rename nonterminals, drop nonterminals, substitute nonterminals *) let rec edit_prod g top edit_map prod = let edit_nt edit_map sym0 nt = try let binding = StringMap.find nt edit_map in match binding with | "DELETE" -> [] | "SPLICE" -> begin try let splice_prods = NTMap.find nt g.map in match splice_prods with | [] -> error "Empty splice for '%s'\n" nt; [] | [p] -> List.rev (remove_Sedit2 p) | _ -> [Sprod (List.map remove_Sedit2 splice_prods)] (* todo? check if we create a dup *) with Not_found -> error "Missing nt '%s' for splice\n" nt; [Snterm nt] end | _ -> [Snterm binding] with Not_found -> [sym0] in let maybe_wrap syms = match syms with | s :: [] -> List.hd syms | s -> Sparen (List.rev syms) in let rec edit_symbol sym0 = match sym0 with | Sterm s -> [sym0] | Snterm s -> edit_nt edit_map sym0 s | Slist1 sym -> [Slist1 (maybe_wrap (edit_symbol sym))] (* you'll get a run-time failure deleting a SEP symbol *) | Slist1sep (sym, sep) -> [Slist1sep (maybe_wrap (edit_symbol sym), (List.hd (edit_symbol sep)))] | Slist0 sym -> [Slist0 (maybe_wrap (edit_symbol sym))] | Slist0sep (sym, sep) -> [Slist0sep (maybe_wrap (edit_symbol sym), (List.hd (edit_symbol sep)))] | Sopt sym -> [Sopt (maybe_wrap (edit_symbol sym))] | Sparen slist -> [Sparen (List.hd (edit_prod g false edit_map slist))] | Sprod slistlist -> let (_, prods) = edit_rule g edit_map "" slistlist in [Sprod prods] | Sedit _ | Sedit2 _ -> [sym0] (* these constructors not used here *) in let is_splice nt = try StringMap.find nt edit_map = "SPLICE" with Not_found -> false in let get_splice_prods nt = try NTMap.find nt g.map with Not_found -> (error "Missing nt '%s' for splice\n" nt; []) in (* special case splice creating multiple new productions *) let splice_prods = match prod with | Snterm nt :: [] when is_splice nt -> get_splice_prods nt | Snterm nt :: Sedit2 ("TAG", _) :: [] when is_splice nt -> get_splice_prods nt | _ -> [] in if top && splice_prods <> [] then splice_prods else [List.rev (List.concat (List.rev (List.map (fun sym -> edit_symbol sym) prod)))] and edit_rule g edit_map nt rule = let nt = try let new_name = StringMap.find nt edit_map in match new_name with | "SPLICE" -> nt | "DELETE" -> "" | _ -> new_name with Not_found -> nt in (nt, (List.concat (List.map (edit_prod g true edit_map) rule))) let read_mlg_files g args symdef_map = let level_renames = ref StringMap.empty in let last_autoloaded = List.hd (List.rev autoloaded_mlgs) in List.iter (fun file -> (* todo: ??? does nt renaming, deletion and splicing *) let rules, locals, dup_renames = read_mlg !g false (Coqpp_parser.parse_file file) file level_renames symdef_map in let numprods = List.fold_left (fun num rule -> let nt, prods = rule in (* rename local duplicates *) let prods = List.map (fun (loc,prod) -> loc, List.hd (edit_prod !g true dup_renames prod)) prods in let nt = try StringMap.find nt dup_renames with Not_found -> nt in (* if NTMap.mem nt !g.map && (StringSet.mem nt locals) &&*) (* StringSet.cardinal (StringSet.of_list (StringMap.find nt !symdef_map)) > 1 then*) (* warn "%s: local nonterminal '%s' already defined\n" file nt; (* todo: goes away *)*) add_rule g nt prods file; num + List.length prods) 0 rules in if args.verbose then begin Printf.eprintf "%s: %d nts, %d prods\n" file (List.length rules) numprods; if file = last_autoloaded then Printf.eprintf " Optionally loaded plugins:\n" end ) args.mlg_files; g_reverse g; !level_renames (* get the nt's in the production, preserving order, don't worry about dups *) let nts_in_prod prod = let rec traverse = function | Sterm s -> [] | Snterm s -> if List.mem s tokens then [] else [s] | Slist1 sym | Slist0 sym | Sopt sym -> traverse sym | Slist1sep (sym, sep) | Slist0sep (sym, sep) -> traverse sym @ (traverse sep) | Sparen sym_list -> List.concat (List.map traverse sym_list) | Sprod sym_list_list -> List.concat (List.map (fun l -> List.concat (List.map traverse l)) sym_list_list) | Sedit _ | Sedit2 _ -> [] in List.rev (List.concat (List.map traverse prod)) let get_refdef_nts g = let rec get_nts_r refd defd bindings = match bindings with | [] -> refd, defd | (nt, prods) :: tl -> get_nts_r (List.fold_left (fun res prod -> StringSet.union res (StringSet.of_list (nts_in_prod prod))) refd prods) (StringSet.add nt defd) tl in let toks = StringSet.of_list tokens in get_nts_r toks toks (NTMap.bindings !g.map) (*** global editing ops ***) let create_edit_map g op edits = let rec aux edits map = match edits with | [] -> map | edit :: tl -> let (loc, key, binding) = edit in let all_nts_ref, all_nts_def = get_refdef_nts g in (match op with (* todo: messages should tell you which edit file causes the error *) | "SPLICE" -> if not (StringSet.mem key all_nts_def) then error "%aUndefined nt '%s' in SPLICE\n" pploc loc key | "DELETE" -> if not (StringSet.mem key all_nts_ref || (StringSet.mem key all_nts_def)) then error "%aUnused/undefined nt '%s' in DELETE\n" pploc loc key; | "RENAME" -> if not (StringSet.mem key all_nts_ref || (StringSet.mem key all_nts_def)) then error "%aUnused/undefined nt '%s' in RENAME\n" pploc loc key; | _ -> ()); aux tl (StringMap.add key binding map) in aux edits StringMap.empty (* don't deal with Sedit, Sedit2 yet (ever?) *) let rec pmatch fullprod fullpat repl = let map_prod prod = List.concat (List.map (fun s -> pmatch [s] fullpat repl) prod) in let pmatch_wrap sym = let r = pmatch [sym] fullpat repl in match r with | a :: b :: tl -> Sparen r | [a] -> a | x -> error "pmatch: should not happen"; Sterm "??" in let symmatch_r s = let res = match s with | Slist1 sym -> Slist1 (pmatch_wrap sym) | Slist1sep (sym, sep) -> Slist1sep (pmatch_wrap sym, sep) | Slist0 sym -> Slist0 (pmatch_wrap sym) | Slist0sep (sym, sep) -> Slist0sep (pmatch_wrap sym, sep) | Sopt sym -> Sopt (pmatch_wrap sym) | Sparen prod -> Sparen (map_prod prod) | Sprod prods -> Sprod (List.map map_prod prods) | sym -> sym in (* Printf.printf "symmatch of %s gives %s\n" (prod_to_str [s]) (prod_to_str [res]);*) res in let rec pmatch_r prod pat match_start start_res res = (* Printf.printf "pmatch_r: prod = %s; pat = %s; res = %s\n" (prod_to_str prod) (prod_to_str pat) (prod_to_str res);*) match prod, pat with | _, [] -> let new_res = (List.rev repl) @ res in pmatch_r prod fullpat prod new_res new_res (* subst and continue *) | [], _ -> (List.rev ((List.rev match_start) @ res)) (* leftover partial match *) | hdprod :: tlprod, hdpat :: tlpat -> if hdprod = hdpat then pmatch_r tlprod tlpat match_start start_res res else (* match from the next starting position *) match match_start with | hd :: tl -> let new_res = (symmatch_r hd) :: start_res in pmatch_r tl fullpat tl new_res new_res | [] -> List.rev res (* done *) in pmatch_r fullprod fullpat fullprod [] [] (* global replace of production substrings, rhs only *) let global_repl g pat repl = List.iter (fun nt -> g_update_prods g nt (List.map (fun prod -> pmatch prod pat repl) (NTMap.find nt !g.map)) ) !g.order (*** splice: replace a reference to a nonterminal with its definition ***) (* todo: create a better splice routine *) (* todo: remove extraneous "(* ltac2 plugin *)" in Ltac2 Notation cmd *) let apply_splice g edit_map = List.iter (fun b -> let (nt0, prods0) = b in let rec splice_loop nt prods cnt = if cnt >= 10 then begin error "Splice for '%s' not done after %d iterations. Current value is:\n" nt0 cnt; List.iter (fun prod -> Printf.eprintf " %s\n" (prod_to_str prod)) prods; (nt, prods) end else begin let (nt', prods') = edit_rule !g edit_map nt prods in if nt' = nt && prods' = prods then (nt, prods) else splice_loop nt' prods' (cnt+1) end in let (nt', prods') = splice_loop nt0 prods0 0 in g_update_prods g nt' prods') (NTMap.bindings !g.map); List.iter (fun b -> let (nt, op) = b in match op with | "DELETE" | "SPLICE" -> g_remove g nt; | _ -> ()) (StringMap.bindings edit_map) let remove_prod edit prods nt = let res, got_first = List.fold_left (fun args prod -> let res, got_first = args in if not got_first && ematch prod edit then res, true else prod :: res, got_first) ([], false) prods in if not got_first then error "Can't find '%s' to DELETE for '%s'\n" (prod_to_str edit) nt; List.rev res let insert_after posn insert prods = List.concat (List.mapi (fun i prod -> if i = posn then prod :: insert else [prod]) prods) (*** replace LIST*, OPT with new nonterminals ***) (* generate a non-terminal name for a replacement *) let nt_regex = Str.regexp "^[a-zA-Z_][a-zA-Z0-9_\\.]*$" let good_name name = if Str.string_match nt_regex name 0 then name else "" let map_name s = let s = match s with | "|" -> "or" | "!" -> "exclam" | ">" -> "gt" | "<" -> "lt" | "+" -> "plus" | "?" -> "qmark" | "}" -> "rbrace" | "," -> "comma" | ";" -> "semi" | _ -> s in good_name s (* create a new nt for LIST* or OPT with the specified name *) let maybe_add_nt g insert_after name sym queue = let empty = [Snterm "empty"] in let maybe_unwrap ?(multi=false) sym = match sym with | Sprod slist when List.length slist = 1 || multi -> slist | Sparen slist -> [ slist ] | _ -> [ [sym] ] in let unw sym = List.hd (maybe_unwrap sym) in let get_prods nt = match sym with | Slist1 sym -> let sym' = unw sym in [ [Snterm nt] @ sym'; sym' ] | Slist1sep (sym, sep) | Slist0sep (sym, sep) -> let sym' = unw sym in [ [Snterm nt; sep] @ sym'; sym' ] | Slist0 sym -> [ [Snterm nt] @ (unw sym); empty ] | Sopt sym -> (maybe_unwrap ~multi:true sym) @ [ empty ] | Sprod slistlist -> slistlist | _ -> [] in let is_slist0sep sym = match sym with | Slist0sep _ -> true | _ -> false in (* find an existing nt with an identical definition, or generate an unused nt name *) let rec find_name nt i = let trial_name = sprintf "%s%s" nt (if i = 1 then "" else string_of_int i) in try if NTMap.find trial_name !g.map = get_prods trial_name then trial_name else find_name nt (succ i) with Not_found -> trial_name in let list_name sep = match sep with | Sterm s -> let name = map_name s in if name = s then "_list" else "_list_" ^ name | _ -> "_list" in let nt = name ^ match sym with | Slist1 sym -> "_list" | Slist1sep (sym, sep) -> list_name sep | Slist0 sym -> "_list_opt" | Slist0sep (sym, sep) -> list_name sep (* special handling *) | Sopt sym -> "_opt" | Sprod slistlist -> "_alt" | _ -> (error "Invalid symbol for USE_NT for nt '%s'\n" name; "ERROR") in let base_nt = find_name nt 1 in let new_nt = if is_slist0sep sym then base_nt ^ "_opt" else base_nt in if not (NTMap.mem new_nt !g.map) then begin let prods = if is_slist0sep sym then [ [Snterm base_nt]; empty ] else get_prods base_nt in g_add_after g (Some !insert_after) new_nt prods; insert_after := new_nt; Queue.add new_nt queue end; if is_slist0sep sym && not (NTMap.mem base_nt !g.map) then begin match sym with | Slist0sep (sym, sep) -> let prods = get_prods base_nt in g_add_after g (Some !insert_after) base_nt prods; insert_after := base_nt; Queue.add base_nt queue | _ -> () end; new_nt let apply_rename_delete g edit_map = List.iter (fun b -> let (nt, _) = b in let prods = try NTMap.find nt !g.map with Not_found -> [] in let (nt', prods') = edit_rule !g edit_map nt prods in if nt' = "" then g_remove g nt else if nt <> nt' then g_rename_merge g nt nt' prods' else g_update_prods g nt prods') (NTMap.bindings !g.map) let edit_all_prods g op eprods = let g_old_map = !g.map in let do_it op eprods num = let rec aux eprods res = match eprods with | [] -> res | (loc,[Snterm old_nt; Snterm new_nt]) :: tl when num = 2 -> aux tl ((loc, old_nt, new_nt) :: res) | (loc,[Snterm old_nt]) :: tl when num = 1 -> aux tl ((loc, old_nt, op) :: res) | (loc,eprod) :: tl -> error "Production '%s: %s' must have only %d nonterminal(s)\n" op (prod_to_str eprod) num; aux tl res in let edit_map = create_edit_map g op (aux eprods []) in match op with | "SPLICE" -> let rv = apply_splice g edit_map in let cause = Printf.sprintf "from SPLICE of '%s'" (prod_to_str (snd (List.hd eprods))) in NTMap.iter (fun nt rule -> check_for_duplicates cause rule (NTMap.find nt g_old_map) nt) !g.map; rv | "RENAME" | "DELETE" -> apply_rename_delete g edit_map | _ -> () in match op with | "RENAME" -> do_it op eprods 2; true | "DELETE" -> do_it op eprods 1; true | "SPLICE" -> (* iterate to give precise error messages *) List.iter (fun prod -> do_it op [ prod ] 1) eprods; true | "OPTINREF" -> List.iter (fun nt -> let prods = NTMap.find nt !g.map in if has_match [] prods then begin let prods' = remove_prod [] prods nt in g_update_prods g nt prods'; global_repl g [(Snterm nt)] [(Sopt (Snterm nt))] end) !g.order; true | _ -> false let edit_single_prod g ~loc edit0 prods nt = let rec edit_single_prod_r edit prods nt seen = match edit with | [] -> prods | Sedit "ADD_OPT" :: sym :: tl -> let prods' = (try let pfx = List.rev seen in let posn = find_first ~loc edit0 prods nt in let prods = insert_after posn [pfx @ (Sopt sym :: tl)] prods in let prods = remove_prod (pfx @ (sym :: tl)) prods nt in remove_prod (pfx @ tl) prods nt with Not_found -> prods) in edit_single_prod_r tl prods' nt seen | Sedit "ADD_OPT" :: [] -> error "Bad position for ADD_OPT\n"; prods | Sedit2 ("USE_NT", name) :: sym :: tl -> let prods' = (try let nt = maybe_add_nt g (ref nt) name sym (Queue.create ()) in let pfx = List.rev seen in let posn = find_first ~loc edit0 prods nt in let prods = insert_after posn [pfx @ (Snterm nt :: tl)] prods in remove_prod (pfx @ (sym :: tl)) prods nt with Not_found -> prods) in edit_single_prod_r tl prods' nt seen | Sedit2 ("USE_NT", _) :: [] -> error "Bad position for USE_NT\n"; prods | sym :: tl -> edit_single_prod_r tl prods nt (sym :: seen) in edit_single_prod_r edit0 prods nt [] let report_undef_nts g prod rec_nt = let nts = nts_in_prod prod in List.iter (fun nt -> if not (NTMap.mem nt !g.map) && not (List.mem nt tokens) && nt <> rec_nt then error "Undefined nonterminal '%s' in edit: %s\n" nt (prod_to_str prod)) nts let apply_edit_file g edits = let moveto src_nt dest_nt oprod prods = g_add_prod_after g (Some src_nt) dest_nt oprod; remove_prod oprod prods src_nt (* remove orig prod *) in List.iter (fun (nt,eprod) -> if not (edit_all_prods g nt eprod) then begin let rec aux eprod prods add_nt = let g_old_map = !g.map in let rv = match eprod with | [] -> prods, add_nt | (loc, Snterm "DELETE" :: oprod) :: tl -> aux tl (remove_prod oprod prods nt) add_nt | (loc, Snterm "DELETENT" :: _) :: tl -> (* note this doesn't remove references *) if not (NTMap.mem nt !g.map) then error "DELETENT for undefined nonterminal '%s'\n" nt; g_remove g nt; aux tl prods false | (loc, Snterm "MOVETO" :: Snterm dest_nt :: oprod) :: tl -> let prods = try (* add "nt -> dest_nt" production *) let posn = find_first ~loc oprod prods nt in if List.mem [Snterm dest_nt] prods then prods else insert_after posn [[Snterm dest_nt]] prods (* insert new prod *) with Not_found -> prods in let prods' = moveto nt dest_nt oprod prods in aux tl prods' add_nt | (loc, [Snterm "COPYALL"; Snterm dest_nt]) :: tl -> if NTMap.mem dest_nt !g.map then error "COPYALL target nonterminal '%s' already exists\n" dest_nt; g_maybe_add g dest_nt prods; aux tl prods add_nt | (loc, [Snterm "MOVEALLBUT"; Snterm dest_nt]) :: tl -> List.iter (fun (loc,tlprod) -> if not (List.mem tlprod prods) then error "MOVEALLBUT for %s can't find '%s'\n" nt (prod_to_str tlprod)) tl; let prods' = List.fold_left (fun prods oprod -> if not (CList.exists (fun (_,x) -> x = oprod) tl) then begin moveto nt dest_nt oprod prods end else prods) prods prods in prods', add_nt | (loc, Snterm "OPTINREF" :: _) :: tl -> if not (has_match [] prods) then error "OPTINREF but no empty production for %s\n" nt; global_repl g [(Snterm nt)] [(Sopt (Snterm nt))]; aux tl (remove_prod [] prods nt) add_nt | (loc, Snterm "INSERTALL" :: syms) :: tl -> aux tl (List.map (fun p -> syms @ p) prods) add_nt | (loc, Snterm "APPENDALL" :: syms) :: tl -> aux tl (List.map (fun p -> p @ syms) prods) add_nt | (loc, Snterm "PRINT" :: _) :: tl -> pr_prods nt prods; aux tl prods add_nt | (loc, Snterm "EDIT" :: oprod) :: tl -> aux tl (edit_single_prod ~loc g oprod prods nt) add_nt | (loc, Snterm "REPLACE" :: oprod) :: (loc', Snterm "WITH" :: rprod) :: tl -> report_undef_nts g rprod ""; (* todo: check result not already present *) let prods' = (try let posn = find_first ~loc oprod prods nt in let prods = insert_after posn [rprod] prods in (* insert new prod *) remove_prod oprod prods nt (* remove orig prod *) with Not_found -> prods) in aux tl prods' add_nt | (loc, (Snterm "REPLACE" :: _ as eprod)) :: tl -> error "Missing WITH after '%s' in '%s'\n" (prod_to_str eprod) nt; aux tl prods add_nt (* todo: check for unmatched editing keywords here *) | (loc, prod) :: tl -> (* add a production *) if has_match prod prods then error "Duplicate production '%s -> %s'\n" nt (prod_to_str prod); report_undef_nts g prod nt; aux tl (prods @ [prod]) add_nt in if eprod <> [] then begin let cause = Printf.sprintf "from '%s'" (prod_to_str (snd (List.hd eprod))) in NTMap.iter (fun nt rule -> let old_rule = try NTMap.find nt g_old_map with Not_found -> [] in check_for_duplicates cause rule old_rule nt) !g.map; end; rv in let prods, add_nt = aux eprod (try NTMap.find nt !g.map with Not_found -> []) true in if add_nt then g_maybe_add g nt prods end) edits (*** main routines ***) (* get the special tokens in the grammar *) let print_special_tokens g = let rec traverse set = function | Sterm s -> let c = s.[0] in if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') then set else StringSet.add s set | Snterm s -> set | Slist1 sym | Slist0 sym | Sopt sym -> traverse set sym | Slist1sep (sym, sep) | Slist0sep (sym, sep) -> traverse (traverse set sym) sep | Sparen sym_list -> traverse_prod set sym_list | Sprod sym_list_list -> traverse_prods set sym_list_list | Sedit _ | Sedit2 _ -> set and traverse_prod set prod = List.fold_left traverse set prod and traverse_prods set prods = List.fold_left traverse_prod set prods in let spec_toks = List.fold_left (fun set b -> let nt, prods = b in traverse_prods set prods) StringSet.empty (NTMap.bindings !g.map) in Printf.printf "Special tokens:"; StringSet.iter (fun t -> Printf.printf " %s" t) spec_toks; Printf.printf "\n\n" (* get the transitive closure of a non-terminal excluding "stops" symbols. Preserve ordering to the extent possible *) (* todo: at the moment, the code doesn't use the ordering; consider switching to using sets instead of lists *) let nt_closure g start stops = let stop_set = StringSet.of_list stops in let rec nt_closure_r res todo = match todo with | [] -> res | nt :: tl -> if List.mem nt res || StringSet.mem nt stop_set then nt_closure_r res tl else begin let more_to_do = try let prods = NTMap.find nt !g.map in tl @ (List.concat (List.map nts_in_prod prods)) with Not_found -> tl in nt_closure_r (nt :: res) more_to_do end in List.rev (nt_closure_r [] [start]) let index_of str list = let rec index_of_r str list index = match list with | [] -> None | hd :: list -> if hd = str then Some index else index_of_r str list (index+1) in index_of_r str list 0 (* todo: raise exception for bad n? *) let rec nthcdr n list = if n <= 0 then list else nthcdr (n-1) (List.tl list) let report_bad_nts g file = let all_nts_ref, all_nts_def = get_refdef_nts g in let undef = StringSet.diff all_nts_ref all_nts_def in if !show_warn then List.iter (fun nt -> warn "%s: Undefined symbol '%s'\n" file nt) (StringSet.elements undef); let reachable = List.fold_left (fun res sym -> StringSet.union res (StringSet.of_list (nt_closure g sym []))) StringSet.empty start_symbols in let unreachable = List.filter (fun nt -> not (StringSet.mem nt reachable)) !g.order in if !show_warn then List.iter (fun nt -> warn "%s: Unreachable symbol '%s'\n" file nt) unreachable let reorder_grammar eg reordered_rules file = let og = g_empty () in List.iter (fun rule -> let nt, prods = rule in try (* only keep nts and prods in common with editedGrammar *) let eg_prods = NTMap.find nt !eg.map in let prods = List.filter (fun (_,prod) -> (has_match prod eg_prods)) prods in if NTMap.mem nt !og.map && !show_warn then warn "%s: Duplicate nonterminal '%s'\n" file nt; add_rule og nt prods file with Not_found -> ()) reordered_rules; g_reverse og; (* insert a prod in a list after prev_prod (None=at the beginning) *) let rec insert_prod prev_prod prod prods res = match prev_prod, prods with | None, _ -> prod :: prods | Some _, [] -> raise Not_found | Some ins_after_prod, hd :: tl -> if ematch hd ins_after_prod then (List.rev res) @ (hd :: prod :: tl) else insert_prod prev_prod prod tl (hd :: res) in (* insert prods that are not already in og_prods *) let rec upd_prods prev_prod eg_prods og_prods = match eg_prods with | [] -> og_prods | prod :: tl -> let og_prods = if has_match prod og_prods then List.map (fun p -> if ematch p prod then prod else p) og_prods else insert_prod prev_prod prod og_prods [] in upd_prods (Some prod) tl og_prods in (* add nts and prods not present in orderedGrammar *) let _ = List.fold_left (fun prev_nt nt -> let e_prods = NTMap.find nt !eg.map in if not (NTMap.mem nt !og.map) then g_add_after og prev_nt nt e_prods else g_update_prods og nt (upd_prods None e_prods (NTMap.find nt !og.map)); Some nt) None !eg.order in g_reorder eg !og.map !og.order let finish_with_file old_file args = let files_eq f1 f2 = let chunksize = 8192 in (try let ofile = open_in_bin f1 in let nfile = open_in_bin f2 in let rv = if (in_channel_length ofile) <> (in_channel_length nfile) then false else begin let obuf = Bytes.create chunksize in Bytes.fill obuf 0 chunksize '\x00'; let nbuf = Bytes.create chunksize in Bytes.fill nbuf 0 chunksize '\x00'; let rec read () = let olen = input ofile obuf 0 chunksize in let _ = input nfile nbuf 0 chunksize in if obuf <> nbuf then false else if olen = 0 then true else read () in read () end in close_in ofile; close_in nfile; rv with Sys_error _ -> false) in let temp_file = (old_file ^ ".new") in if !exit_code <> 0 then Sys.remove temp_file else if args.verify then begin if not (files_eq old_file temp_file) then begin error "%s is not current\n" old_file; ignore (CUnix.sys_command "diff" [ "-u" ; old_file ; old_file ^ ".new"]) end; Sys.remove temp_file end else if args.update then Sys.rename temp_file old_file let open_temp_bin file = open_out_bin (sprintf "%s.new" file) let match_cmd_regex = Str.regexp "[a-zA-Z0-9_ ]+" let match_subscripts = Str.regexp "__[a-zA-Z0-9]+" let remove_subscrs str = Str.global_replace match_subscripts "" str let find_longest_match prods str = let get_pfx str = String.trim (if Str.string_match match_cmd_regex str 0 then Str.matched_string str else "") in let prods = StringSet.fold (fun a lst -> a :: lst) prods [] in (* todo: wasteful! *) let common_prefix_len s1 s2 = let limit = min (String.length s1) (String.length s2) in let rec aux off = if off = limit then off else if s1.[off] = s2.[off] then aux (succ off) else off in aux 0 in let slen = String.length str in let str_pfx = get_pfx str in let no_subscrs = remove_subscrs str in let has_subscrs = no_subscrs <> str in let rec longest best multi best_len prods = match prods with | [] -> best, multi, best_len | prod :: tl -> let pstr = String.trim prod in (* todo: should be pretrimmed *) let clen = common_prefix_len str pstr in if has_subscrs && no_subscrs = pstr then str, false, clen (* exact match ignoring subscripts *) else if pstr = str then pstr, false, clen (* exact match of full line *) else if str_pfx = "" || str_pfx <> get_pfx pstr then longest best multi best_len tl (* prefixes don't match *) else if clen = slen && slen = String.length pstr then pstr, false, clen (* exact match on prefix *) else if clen > best_len then longest pstr false clen tl (* better match *) else if clen = best_len then longest best true best_len tl (* 2nd match with same length *) else longest best multi best_len tl (* worse match *) in let mtch, multi, _ = longest "" false 0 prods in if has_subscrs && mtch <> str then "", multi, mtch (* no match for subscripted entry *) else mtch, multi, "" type seen = { nts: (string * int) NTMap.t; tacs: (string * int) NTMap.t; tacvs: (string * int) NTMap.t; cmds: (string * int) NTMap.t; cmdvs: (string * int) NTMap.t; } (* Sphinx notations can't handle empty productions *) let has_empty_prod rhs = let rec has_empty_prod_r rhs = match rhs with | [] -> false | Sterm _ :: tl | Snterm _ :: tl | Sedit _ :: tl | Sedit2 (_, _) :: tl -> has_empty_prod_r tl | Slist1 sym :: tl | Slist0 sym :: tl | Slist1sep (sym, _) :: tl | Slist0sep (sym, _) :: tl | Sopt sym :: tl -> has_empty_prod_r [ sym ] || has_empty_prod_r tl | Sparen prod :: tl -> List.length prod = 0 || has_empty_prod_r tl | Sprod prods :: tl -> List.fold_left (fun rv prod -> List.length prod = 0 || has_empty_prod_r tl || rv) false prods in List.length rhs = 0 || has_empty_prod_r rhs let process_rst g file args seen tac_prods cmd_prods = let old_rst = open_in file in let new_rst = open_temp_bin file in let linenum = ref 0 in let dir_regex = Str.regexp "^\\([ \t]*\\)\\.\\.[ \t]*\\([a-zA-Z0-9:]* *\\)\\(.*\\)" in let contin_regex = Str.regexp "^\\([ \t]*\\)\\(.*\\)" in let ip_args_regex = Str.regexp "^[ \t]*\\([a-zA-Z0-9_\\.]+\\)[ \t]+\\([a-zA-Z0-9_\\.]+\\)" in let blank_regex = Str.regexp "^[ \t]*$" in let end_prodlist_regex = Str.regexp "^[ \t]*$" in let getline () = let line = input_line old_rst in incr linenum; line in (* todo: maybe pass end_index? *) let output_insertprodn start_index end_ indent = let rec copy_prods list = match list with | [] -> () | nt :: tl -> (try let (prev_file, prev_linenum) = NTMap.find nt !seen.nts in if !show_warn then warn "%s line %d: '%s' already included at %s line %d\n" file !linenum nt prev_file prev_linenum; with Not_found -> seen := { !seen with nts = (NTMap.add nt (file, !linenum) !seen.nts)} ); let prods = NTMap.find nt !g.map in List.iteri (fun i prod -> let rhs = String.trim (prod_to_prodn prod) in let tag = get_tag file prod in let sep = if i = 0 then " ::=" else "|" in if has_empty_prod prod then error "%s line %d: Empty (sub-)production for %s, edit to remove: '%s %s'\n" file !linenum nt sep rhs; fprintf new_rst "%s %s%s %s%s\n" indent (if i = 0 then nt else "") sep rhs tag) prods; if nt <> end_ then copy_prods tl in copy_prods (nthcdr start_index !g.order) in let process_insertprodn line rhs = if not (Str.string_match ip_args_regex rhs 0) then error "%s line %d: bad arguments '%s' for 'insertprodn'\n" file !linenum rhs else begin let start = Str.matched_group 1 rhs in let end_ = Str.matched_group 2 rhs in let start_index = index_of start !g.order in let end_index = index_of end_ !g.order in if start_index = None then error "%s line %d: '%s' is undefined in insertprodn\n" file !linenum start; if end_index = None then error "%s line %d: '%s' is undefined in insertprodn\n" file !linenum end_; (* if start_index <> None && end_index <> None then*) (* check_range_consistency g start end_;*) match start_index, end_index with | Some start_index, Some end_index -> if start_index > end_index then error "%s line %d: '%s' must appear before '%s' in orderedGrammar\n" file !linenum start end_ else begin try let line2 = getline() in if not (Str.string_match blank_regex line2 0) then error "%s line %d: expecting a blank line after 'insertprodn'\n" file !linenum else begin let line3 = getline() in if not (Str.string_match dir_regex line3 0) || (String.trim (Str.matched_group 2 line3)) <> "prodn::" then error "%s line %d: expecting '.. prodn::' after 'insertprodn'\n" file !linenum else begin let indent = Str.matched_group 1 line3 in let rec skip_to_end () = let endline = getline() in if Str.string_match end_prodlist_regex endline 0 then begin fprintf new_rst "%s\n\n%s\n" line line3; output_insertprodn start_index end_ indent; fprintf new_rst "%s\n" endline end else skip_to_end () in skip_to_end () end end with End_of_file -> error "%s line %d: unexpected end of file\n" file !linenum; end | _ -> () end in let save_n_get_more direc pfx first_rhs seen_map prods = let replace rhs prods = if StringSet.is_empty prods then rhs (* no change *) else let mtch, multi, best = find_longest_match prods rhs in (* Printf.printf "mtch = '%s' rhs = '%s'\n" mtch rhs;*) if mtch = rhs then rhs (* no change *) else if mtch = "" then begin error "%s line %d: NO MATCH for '%s'\n" file !linenum rhs; if best <> "" then begin Printf.eprintf " closest match is: '%s'\n" best; Printf.eprintf " Please update the rst manually while preserving any subscripts, e.g. 'NT__sub'\n" end; rhs end else if multi then begin error "%s line %d: MULTIPLE MATCHES for '%s'\n" file !linenum rhs; Printf.eprintf " Please update the rst manually while preserving any subscripts, e.g. 'NT__sub'\n"; rhs end else mtch (* update cmd/tacn *) in let map = ref seen_map in if NTMap.mem first_rhs !map && !show_warn then warn "%s line %d: Repeated %s: '%s'\n" file !linenum direc first_rhs; (* if not (StringSet.mem rhs seen_map) then*) (* warn "%s line %d: Unknown tactic: '%s'\n" file !linenum rhs;*) fprintf new_rst "%s%s\n" pfx (replace first_rhs prods); map := NTMap.add (remove_subscrs first_rhs) (file, !linenum) !map; while try let nextline = getline() in ignore (Str.string_match contin_regex nextline 0); let indent = Str.matched_group 1 nextline in let rhs = Str.matched_group 2 nextline in let replaceable = rhs <> "" && rhs.[0] <> ':' in let upd_rhs = if replaceable then (replace rhs prods) else rhs in fprintf new_rst "%s%s\n" indent upd_rhs; if replaceable then begin map := NTMap.add (remove_subscrs rhs) (file, !linenum) !map end; rhs <> "" with End_of_file -> false do () done; !map in try while true do let line = getline() in if Str.string_match dir_regex line 0 then begin let dir = String.trim (Str.matched_group 2 line) in let rhs = Str.matched_group 3 line in let pfx = String.sub line 0 (Str.group_end 2) in match dir with | "prodn::" -> if rhs = "coq" && !show_warn then warn "%s line %d: Missing 'insertprodn' before 'prodn:: coq'\n" file !linenum; fprintf new_rst "%s\n" line; | "tacn::" -> seen := { !seen with tacs = save_n_get_more "tacn" pfx rhs !seen.tacs tac_prods } | "tacv::" -> seen := { !seen with tacvs = save_n_get_more "tacv" pfx rhs !seen.tacvs StringSet.empty } | "cmd::" -> seen := { !seen with cmds = save_n_get_more "cmd" pfx rhs !seen.cmds cmd_prods } | "cmdv::" -> seen := { !seen with cmdvs = save_n_get_more "cmdv" pfx rhs !seen.cmdvs StringSet.empty } | "insertprodn" -> process_insertprodn line rhs | _ -> fprintf new_rst "%s\n" line end else fprintf new_rst "%s\n" line; done with End_of_file -> (); close_in old_rst; close_out new_rst; finish_with_file file args let report_omitted_prods g seen label split = if !show_warn then begin let included = try List.map (fun prod -> match prod with | Snterm nt :: tl -> nt | _ -> "") (NTMap.find "NOTINRSTS" !g.map) with Not_found -> [] in Printf.printf "\n\n"; let missing = NTMap.filter (fun nt _ -> not (NTMap.mem nt seen || (List.mem nt included))) !g.map in NTMap.iter (fun nt _ -> warn "%s %s not included in .rst files\n" "Nonterminal" nt) missing; let total = NTMap.cardinal missing in if total <> 0 then Printf.eprintf "TOTAL %ss not included = %d\n" label total end let process_grammar args = let symdef_map = ref StringMap.empty in let g = g_empty () in let level_renames = read_mlg_files g args symdef_map in if args.verbose then begin Printf.printf "Keywords:\n"; StringSet.iter (fun kw -> Printf.printf "%s " kw) !keywords; Printf.printf "\n\n"; end; (* rename nts with levels *) List.iter (fun b -> let (nt, prod) = b in let (_, prod) = edit_rule !g level_renames nt prod in g_update_prods g nt prod) (NTMap.bindings !g.map); (* print the full grammar with minimal editing *) let out = open_temp_bin (dir "fullGrammar") in fprintf out "%s\n%s\n\n" "(* Coq grammar generated from .mlg files. Do not edit by hand. Not compiled into Coq *)" "DOC_GRAMMAR"; print_in_order out g `MLG !g.order StringSet.empty; close_out out; finish_with_file (dir "fullGrammar") args; if args.verbose then print_special_tokens g; if not args.fullGrammar then begin (* do shared edits *) if !exit_code = 0 then begin let common_edits = read_mlg_edit "common.edit_mlg" in apply_edit_file g common_edits end; let prodn_gram = ref { map = !g.map; order = !g.order } in (* todo: should just be 'g', right? *) if !exit_code = 0 && not args.verify then begin let out = open_temp_bin (dir "editedGrammar") in fprintf out "%s\n%s\n\n" "(* Edited Coq grammar generated from .mlg files. Do not edit by hand. Not compiled into Coq *)" "DOC_GRAMMAR"; print_in_order out g `MLG !g.order StringSet.empty; close_out out; finish_with_file (dir "editedGrammar") args; report_bad_nts g "editedGrammar" end; if !exit_code = 0 then begin let ordered_grammar = read_mlg_edit "orderedGrammar" in let out = open_temp_bin (dir "orderedGrammar") in fprintf out "%s\n%s\n\n" ("(* Defines the order to apply to editedGrammar to get the final grammar for the doc.\n" ^ "doc_grammar will modify this file to add/remove nonterminals and productions\n" ^ "to match editedGrammar, which will remove comments. Not compiled into Coq *)") "DOC_GRAMMAR"; reorder_grammar g ordered_grammar "orderedGrammar"; print_in_order out g `MLG !g.order StringSet.empty; close_out out; finish_with_file (dir "orderedGrammar") args; (* check_singletons g*) let seen = ref { nts=NTMap.empty; tacs=NTMap.empty; tacvs=NTMap.empty; cmds=NTMap.empty; cmdvs=NTMap.empty } in let plist nt = let list = (List.map (fun t -> String.trim (prod_to_prodn t)) (NTMap.find nt !g.map)) in list, StringSet.of_list list in let tac_list, tac_prods = plist "simple_tactic" in let cmd_list, cmd_prods = plist "command" in List.iter (fun file -> process_rst g file args seen tac_prods cmd_prods) args.rst_files; report_omitted_prods g !seen.nts "Nonterminal" ""; let out = open_out (dir "updated_rsts") in close_out out; (* generate report on cmds or tacs *) let cmdReport outfile cmdStr itemName cmd_nts cmds cmdvs = let rstCmds = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings cmds)) in let rstCmdvs = StringSet.of_list (List.map (fun b -> let c, _ = b in c) (NTMap.bindings cmdvs)) in let gramCmds = List.fold_left (fun set nt -> StringSet.union set (StringSet.of_list (List.map (fun p -> String.trim (prod_to_prodn p)) (NTMap.find nt !prodn_gram.map))) ) StringSet.empty cmd_nts in let allCmds = StringSet.union rstCmdvs (StringSet.union rstCmds gramCmds) in let out = open_out_bin (dir outfile) in StringSet.iter (fun c -> let rsts = StringSet.mem c rstCmds in let gram = StringSet.mem c gramCmds in let pfx = match rsts, gram with | true, false -> error "%s not in grammar: %s\n" itemName c; "+" | false, true -> error "%s not in doc: %s\n" itemName c; "-" | false, false -> "?" | _, _ -> " " in let var = if StringSet.mem c rstCmdvs then "v" else " " in fprintf out "%s%s %s\n" pfx var c) allCmds; close_out out; Printf.printf "# %s in rsts, gram, total = %d %d %d\n" cmdStr (StringSet.cardinal gramCmds) (StringSet.cardinal rstCmds) (StringSet.cardinal allCmds); in let cmd_nts = ["command"] in (* TODO: need to handle tactic_mode (overlaps with query_command) and subprf *) if args.check_cmds then cmdReport "prodnCommands" "cmds" "Command" cmd_nts !seen.cmds !seen.cmdvs; let tac_nts = ["simple_tactic"] in if args.check_tacs then cmdReport "prodnTactics" "tacs" "Tactic" tac_nts !seen.tacs !seen.tacvs; (* generate prodnGrammar for reference *) if not args.verify then begin let out = open_out_bin (dir "prodnGrammar") in print_in_order out prodn_gram `PRODN !prodn_gram.order StringSet.empty; close_out out; end end (* if !exit_code = 0 *) end (* if not args.fullGrammar *) let parse_args () = let suffix_regex = Str.regexp ".*\\.\\([a-z]+\\)$" in let args = List.fold_left (fun args arg -> match arg with | "-check-cmds" -> { args with check_cmds = true } | "-check-tacs" -> { args with check_tacs = true } | "-no-warn" -> show_warn := false; { args with show_warn = false } | "-no-update" -> { args with update = false } | "-short" -> { args with fullGrammar = true } | "-verbose" -> { args with verbose = true } | "-verify" -> { args with verify = true } | arg when Str.string_match suffix_regex arg 0 -> (match Str.matched_group 1 arg with | "mlg" -> { args with mlg_files = (arg :: args.mlg_files) } | "rst" -> { args with rst_files = (arg :: args.rst_files) } | _ -> error "Unknown command line argument '%s'\n" arg; args) | arg -> error "Unknown command line argument '%s'\n" arg; args) default_args (List.tl (Array.to_list Sys.argv)) in { args with mlg_files = (List.rev args.mlg_files); rst_files = (List.rev args.rst_files)} let () = (*try*) Printexc.record_backtrace true; let args = parse_args () in if !exit_code = 0 then begin process_grammar args end; if !error_count > 0 then Printf.eprintf "%d error(s)\n" !error_count; exit !exit_code (*with _ -> Printexc.print_backtrace stdout; exit 1*) rocq-9.2.0/doc/tools/docgram/doc_grammar.mli000066400000000000000000000000001516144147600207640ustar00rootroot00000000000000rocq-9.2.0/doc/tools/docgram/dune000066400000000000000000000041301516144147600166740ustar00rootroot00000000000000(executable (name doc_grammar) (libraries rocq-runtime.clib coqpp)) (env (_ (binaries doc_grammar.exe))) (rule (alias check-gram) (deps (:input ; Main grammar (glob_files %{project_root}/parsing/*.mlg) (glob_files %{project_root}/toplevel/*.mlg) (glob_files %{project_root}/vernac/*.mlg) (glob_files %{project_root}/plugins/btauto/*.mlg) (glob_files %{project_root}/plugins/cc/*.mlg) (glob_files %{project_root}/plugins/derive/*.mlg) (glob_files %{project_root}/plugins/extraction/*.mlg) (glob_files %{project_root}/plugins/firstorder/*.mlg) (glob_files %{project_root}/plugins/funind/*.mlg) (glob_files %{project_root}/plugins/ltac/*.mlg) (glob_files %{project_root}/plugins/micromega/*.mlg) (glob_files %{project_root}/plugins/nsatz/*.mlg) (glob_files %{project_root}/plugins/ring/*.mlg) (glob_files %{project_root}/plugins/rtauto/*.mlg) (glob_files %{project_root}/plugins/ssr/*.mlg) (glob_files %{project_root}/plugins/ssrmatching/*.mlg) (glob_files %{project_root}/plugins/syntax/*.mlg) (glob_files %{project_root}/plugins/ltac2/*.mlg) ; Sphinx files (glob_files %{project_root}/doc/sphinx/language/*.rst) (glob_files %{project_root}/doc/sphinx/proof-engine/*.rst) (glob_files %{project_root}/doc/sphinx/user-extensions/*.rst) (glob_files %{project_root}/doc/sphinx/practical-tools/*.rst) (glob_files %{project_root}/doc/sphinx/addendum/*.rst) (glob_files %{project_root}/doc/sphinx/language/core/*.rst) (glob_files %{project_root}/doc/sphinx/language/extensions/*.rst) (glob_files %{project_root}/doc/sphinx/proofs/writing-proofs/*.rst) (glob_files %{project_root}/doc/sphinx/proofs/automatic-tactics/*.rst) (glob_files %{project_root}/doc/sphinx/proofs/creating-tactics/*.rst) (glob_files %{project_root}/doc/sphinx/using/libraries/*.rst) (glob_files %{project_root}/doc/sphinx/using/tools/*.rst)) common.edit_mlg orderedGrammar) (action (progn (chdir %{project_root} (run doc_grammar -no-warn -check-cmds -no-update %{input})) (diff? fullGrammar fullGrammar.new) (diff? orderedGrammar orderedGrammar.new)))) rocq-9.2.0/doc/tools/docgram/fullGrammar000066400000000000000000002205021516144147600202150ustar00rootroot00000000000000(* Coq grammar generated from .mlg files. Do not edit by hand. Not compiled into Coq *) DOC_GRAMMAR Constr.ident: [ | Prim.ident ] Prim.name: [ | "_" ] global: [ | Prim.reference ] constr_pattern: [ | constr ] cpattern: [ | lconstr ] sort: [ | "Set" | "Prop" | "SProp" | "Type" | "Type" "@{" "_" "}" | "Type" "@{" test_old_sort_qvar reference "|" universe "}" | "Type" "@{" test_sort_qvar reference ";" universe "}" | "Type" "@{" universe "}" ] sort_quality_or_set: [ | "Prop" | "SProp" | "Set" | "Type" ] sort_quality_var: [ | "Prop" | "SProp" | "Type" | reference ] universe_increment: [ | "+" natural | ] universe_name: [ | global | "Set" | "Prop" ] universe_expr: [ | universe_name universe_increment | natural ] universe: [ | "max" "(" LIST1 universe_expr SEP "," ")" | "_" | universe_expr ] lconstr: [ | term200 ] constr: [ | term8 | "@" global univ_annot ] term200: [ | term100 ] term100: [ | term99 "<:" term200 | term99 "<<:" term200 | term99 ":>" term200 | term99 ":" term200 | term99 ] term99: [ | term90 ] term90: [ | term10 ] term10: [ | term10 LIST1 arg | "@" global univ_annot LIST0 term9 | "@" pattern_ident LIST1 identref | binder_constr | term9 ] term9: [ | ".." term0 ".." | term8 ] term8: [ | term1 ] term1: [ | term1 ".(" global univ_annot LIST0 arg ")" | term1 ".(" "@" global univ_annot LIST0 ( term9 ) ")" | term1 "%" IDENT | term1 "%_" IDENT | term0 ] term0: [ | atomic_constr | term_match | reference univ_annot | NUMBER | string | "(" term200 ")" | "{|" record_declaration bar_cbrace | "`{" term200 "}" | test_array_opening "[" "|" array_elems "|" lconstr type_cstr test_array_closing "|" "]" univ_annot | "`(" term200 ")" | "ltac" ":" "(" Pltac.ltac_expr ")" ] array_elems: [ | LIST0 lconstr SEP ";" ] record_declaration: [ | fields_def ] fields_def: [ | field_def ";" fields_def | field_def | ] field_def: [ | global binders ":=" lconstr ] binder_constr: [ | "forall" open_binders "," term200 | "fun" open_binders "=>" term200 | "let" name binders let_type_cstr ":=" term200 "in" term200 | "let" "fix" fix_decl "in" term200 | "let" "cofix" cofix_body "in" term200 | "let" [ "(" LIST0 name SEP "," ")" | "()" ] as_return_type ":=" term200 "in" term200 | "let" "'" pattern200 OPT [ "in" pattern200 ] ":=" term200 OPT case_type "in" term200 | "if" term200 as_return_type "then" term200 "else" term200 | "fix" fix_decls | "cofix" cofix_decls ] arg: [ | test_lpar_id_coloneq "(" identref ":=" lconstr ")" | test_lpar_nat_coloneq "(" natural ":=" lconstr ")" | term9 ] atomic_constr: [ | sort | "_" | "?" "[" identref "]" | "?" "[" pattern_ident "]" | pattern_ident evar_instance ] inst: [ | identref ":=" lconstr ] evar_instance: [ | "@{" LIST1 inst SEP ";" "}" | ] univ_annot: [ | "@{" LIST0 univ_level_or_quality OPT [ [ "|" | ";" ] LIST0 univ_level_or_quality ] "}" | ] univ_level_or_quality: [ | NUMBER "0" | "Set" | "SProp" | "Prop" | "Type" | "_" | global ] fix_decls: [ | fix_decl | fix_decl "with" LIST1 fix_decl SEP "with" "for" identref ] cofix_decls: [ | cofix_body | cofix_body "with" LIST1 cofix_body SEP "with" "for" identref ] fix_decl: [ | identref binders_fixannot type_cstr ":=" term200 ] cofix_body: [ | identref binders type_cstr ":=" term200 ] term_match: [ | "match" LIST1 case_item SEP "," OPT case_type "with" branches "end" ] case_item: [ | term100 OPT [ "as" name ] OPT [ "in" pattern200 ] ] case_type: [ | "return" term100 ] as_return_type: [ | OPT [ OPT [ "as" name ] case_type ] ] branches: [ | OPT "|" LIST0 eqn SEP "|" ] mult_pattern: [ | LIST1 pattern200 SEP "," ] eqn: [ | LIST1 mult_pattern SEP "|" "=>" lconstr ] record_pattern: [ | global ":=" pattern200 ] record_patterns: [ | record_pattern ";" record_patterns | record_pattern | ] pattern200: [ | pattern100 ] pattern100: [ | pattern99 ":" term200 | pattern99 ] pattern99: [ | pattern90 ] pattern90: [ | pattern10 ] pattern10: [ | pattern10 "as" name | pattern10 LIST1 pattern1 | "@" Prim.reference LIST0 pattern1 | pattern1 ] pattern1: [ | pattern1 "%" IDENT | pattern1 "%_" IDENT | pattern0 ] pattern0: [ | Prim.reference | "{|" record_patterns bar_cbrace | "_" | "(" pattern200 ")" | "(" pattern200 "|" LIST1 pattern200 SEP "|" ")" | NUMBER | string ] fixannot: [ | "{" "struct" identref "}" | "{" "wf" constr identref "}" | "{" "measure" constr OPT identref OPT constr "}" ] binders_fixannot: [ | ensure_fixannot fixannot | binder binders_fixannot | ] open_binders: [ | name LIST0 name ":" lconstr | name LIST0 name binders | name ".." name | closed_binder binders ] binders: [ | LIST0 binder | Procq.Constr.binders ] binder: [ | name | closed_binder ] closed_binder: [ | "(" name LIST1 name ":" lconstr ")" | "(" name ":" lconstr ")" | "(" name ":=" lconstr ")" | "(" name ":" lconstr ":=" lconstr ")" | "(" name ":" lconstr "|" lconstr ")" | "{" name "}" | "{" name LIST1 name ":" lconstr "}" | "{" name ":" lconstr "}" | "{" name LIST1 name "}" | "[" name "]" | "[" name LIST1 name ":" lconstr "]" | "[" name ":" lconstr "]" | "[" name LIST1 name "]" | "`(" LIST1 typeclass_constraint SEP "," ")" | "`{" LIST1 typeclass_constraint SEP "," "}" | "`[" LIST1 typeclass_constraint SEP "," "]" | "'" pattern0 ] one_open_binder: [ | name | name ":" lconstr | one_closed_binder ] one_closed_binder: [ | "(" name ":" lconstr ")" | "{" name "}" | "{" name ":" lconstr "}" | "[" name "]" | "[" name ":" lconstr "]" | "'" pattern0 ] typeclass_constraint: [ | "!" term200 | "{" name "}" ":" [ "!" | ] term200 | test_name_colon name ":" [ "!" | ] term200 | term200 ] type_cstr: [ | ":" lconstr | ] let_type_cstr: [ | OPT [ ":" lconstr ] ] preident: [ | IDENT ] ident: [ | IDENT ] pattern_ident: [ | LEFTQMARK ident ] identref: [ | ident ] hyp: [ | identref ] field: [ | FIELD ] fields: [ | field fields | field ] fullyqualid: [ | ident fields | ident ] name: [ | "_" | ident ] reference: [ | ident fields | ident ] qualid: [ | reference ] by_notation: [ | ne_string OPT [ "%" IDENT ] ] smart_global: [ | reference | by_notation ] ne_string: [ | STRING ] ne_lstring: [ | ne_string ] dirpath: [ | ident LIST0 field ] string: [ | STRING ] lstring: [ | string ] integer: [ | bigint ] natural: [ | bignat ] bigint: [ | bignat | test_minus_nat "-" bignat ] bignat: [ | NUMBER ] bar_cbrace: [ | test_pipe_closedcurly "|" "}" ] strategy_level: [ | "expand" | "opaque" | integer | "transparent" ] vernac_toplevel: [ | "Drop" "." | "Quit" "." | "BackTo" natural "." | test_show_goal "Show" "Goal" natural "at" natural "." | "Show" "Proof" "Diffs" OPT "removed" "." | "Show" "." | test_show_natural "Show" natural "." | "Show" "Diffs" qualid "." | Pvernac.Vernac_.main_entry ] opt_hintbases: [ | | ":" LIST1 IDENT ] command: [ | "Goal" lconstr | "Proof" | "Proof" "using" G_vernac.section_subset_expr | "Proof" "with" generic_tactic OPT [ "using" G_vernac.section_subset_expr ] | "Proof" "using" G_vernac.section_subset_expr "with" generic_tactic | "Proof" "Mode" string | "Proof" lconstr | "Abort" | "Abort" "All" | "Admitted" | "Qed" | "Save" identref | "Defined" | "Defined" identref | "Restart" | "Undo" | "Undo" natural | "Undo" "To" natural | "Focus" | "Focus" natural | "Unfocus" | "Unfocused" | "Show" | "Show" natural | "Show" qualid | "Show" "Existentials" | "Show" "Universes" | "Show" "Conjectures" | "Show" "Proof" | "Show" "Intro" | "Show" "Intros" | "Show" "Match" reference | "Guarded" | "Validate" "Proof" | "Create" "HintDb" IDENT; [ "discriminated" | ] | "Remove" "Hints" LIST1 global opt_hintbases | "Hint" hint opt_hintbases | "Optimize" "Proof" | "Optimize" "Heap" | "Comments" LIST0 comment | "Attributes" attribute_list | "Declare" "Instance" ident_decl binders ":" term200 hint_info | "Declare" "Scope" IDENT | "Pwd" | "Cd" | "Cd" ne_string | "Load" [ "Verbose" | ] [ ne_string | IDENT ] | "Declare" "ML" "Module" LIST1 ne_string | "Locate" locatable | "Type" lconstr | "Print" printable | "Print" smart_global OPT univ_name_list | "Print" "Module" "Type" global | "Print" "Module" global | "Print" "Namespace" dirpath | "Inspect" natural | "Set" setting_name option_setting | "Unset" setting_name | "Print" "Table" setting_name | "Add" IDENT IDENT LIST1 table_value | "Add" IDENT LIST1 table_value | "Test" setting_name "for" LIST1 table_value | "Test" setting_name | "Remove" IDENT IDENT LIST1 table_value | "Remove" IDENT LIST1 table_value | "Reset" "Initial" | "Reset" identref | "Back" | "Back" natural | "Debug" "On" | "Debug" "Off" | "Declare" "Reduction" IDENT; ":=" red_expr | "Declare" "Custom" "Entry" ident | "Obligation" natural "of" identref withtac | "Obligation" natural withtac | "Next" "Obligation" "of" identref withtac | "Next" "Obligation" withtac | "Final" "Obligation" "of" identref withtac | "Final" "Obligation" withtac | "Solve" "Obligations" "of" identref withtac | "Solve" "Obligations" withtac | "Solve" "All" "Obligations" withtac | "Admit" "Obligations" "of" identref | "Admit" "Obligations" | "Obligation" "Tactic" ":=" generic_tactic | "Show" "Obligation" "Tactic" | "Obligations" "of" identref | "Obligations" | "Preterm" "of" identref | "Preterm" | "Derive" open_binders "SuchThat" constr "As" identref (* derive plugin *) | "Derive" open_binders "in" constr "as" identref (* derive plugin *) | "Extraction" global (* extraction plugin *) | "Recursive" "Extraction" LIST1 global (* extraction plugin *) | "Extraction" string LIST1 global (* extraction plugin *) | "Extraction" "TestCompile" LIST1 global (* extraction plugin *) | "Separate" "Extraction" LIST1 global (* extraction plugin *) | "Extraction" "Library" identref (* extraction plugin *) | "Recursive" "Extraction" "Library" identref (* extraction plugin *) | "Extraction" "Language" language (* extraction plugin *) | "Extraction" "Inline" LIST1 global (* extraction plugin *) | "Extraction" "NoInline" LIST1 global (* extraction plugin *) | "Print" "Extraction" "Inline" (* extraction plugin *) | "Reset" "Extraction" "Inline" (* extraction plugin *) | "Extraction" "Implicit" global "[" LIST0 int_or_id "]" (* extraction plugin *) | "Extraction" "Blacklist" LIST1 preident (* extraction plugin *) | "Print" "Extraction" "Blacklist" (* extraction plugin *) | "Reset" "Extraction" "Blacklist" (* extraction plugin *) | "Extract" "Callback" OPT string global (* extraction plugin *) | "Print" "Extraction" "Callback" (* extraction plugin *) | "Reset" "Extraction" "Callback" (* extraction plugin *) | "Print" "Extraction" "Foreign" (* extraction plugin *) | "Extract" "Constant" global LIST0 string "=>" mlname (* extraction plugin *) | "Extract" "Foreign" "Constant" global "=>" string (* extraction plugin *) | "Extract" "Inlined" "Constant" global "=>" mlname (* extraction plugin *) | "Extract" "Inductive" global "=>" mlname "[" LIST0 mlname "]" OPT string (* extraction plugin *) | "Show" "Extraction" (* extraction plugin *) | "Set" "Firstorder" "Solver" generic_tactic | "Print" "Firstorder" "Solver" | "Function" LIST1 function_fix_definition SEP "with" (* funind plugin *) | "Functional" "Scheme" LIST1 fun_scheme_arg SEP "with" (* funind plugin *) | "Functional" "Case" fun_scheme_arg (* funind plugin *) | "Generate" "graph" "for" reference (* funind plugin *) | "Hint" "Rewrite" orient LIST1 constr ":" LIST1 preident | "Hint" "Rewrite" orient LIST1 constr "using" generic_tactic ":" LIST1 preident | "Hint" "Rewrite" orient LIST1 constr | "Hint" "Rewrite" orient LIST1 constr "using" generic_tactic | "Create" "Rewrite" "HintDb" ident | "Derive" "Inversion_clear" identref "with" constr "Sort" sort_quality_or_set | "Derive" "Inversion_clear" identref "with" constr | "Derive" "Inversion" identref "with" constr "Sort" sort_quality_or_set | "Derive" "Inversion" identref "with" constr | "Derive" "Dependent" "Inversion" identref "with" constr "Sort" sort_quality_or_set | "Derive" "Dependent" "Inversion_clear" identref "with" constr "Sort" sort_quality_or_set | "Declare" "Left" "Step" constr | "Declare" "Right" "Step" constr | "Unshelve" | "Declare" "Equivalent" "Keys" constr constr | "Print" "Equivalent" "Keys" | "infoH" tactic | "Hint" "Cut" "[" hints_path_entry "]" opthints | "Typeclasses" "Transparent" LIST1 reference | "Typeclasses" "Opaque" LIST1 reference | "Typeclasses" "eauto" ":=" debug eauto_search_strategy OPT natural | "Tactic" "Notation" OPT ltac_tactic_level LIST1 ltac_production_item ":=" tactic | "Print" "Ltac" reference | "Locate" "Ltac" reference | "Ltac" LIST1 ltac_tacdef_body SEP "with" | "Print" "Ltac" "Signatures" | "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "as" identref | "Add" "Relation" constr constr "symmetry" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Relation" constr constr "transitivity" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" identref | "Add" "Parametric" "Relation" binders ":" constr constr "transitivity" "proved" "by" constr "as" identref | "Add" "Setoid" constr constr constr "as" identref | "Add" "Parametric" "Setoid" binders ":" constr constr constr "as" identref | "Add" "Morphism" constr ":" identref | "Declare" "Morphism" constr ":" identref | "Add" "Morphism" constr "with" "signature" lconstr "as" identref | "Add" "Parametric" "Morphism" binders ":" constr "with" "signature" lconstr "as" identref | "Print" "Rewrite" "HintDb" preident | "Reset" "Ltac" "Profile" | "Show" "Ltac" "Profile" | "Show" "Ltac" "Profile" "CutOff" integer | "Show" "Ltac" "Profile" string | "Show" "Lia" "Profile" (* micromega plugin *) | "Add" "Zify" "InjTyp" reference (* micromega plugin *) | "Add" "Zify" "BinOp" reference (* micromega plugin *) | "Add" "Zify" "UnOp" reference (* micromega plugin *) | "Add" "Zify" "CstOp" reference (* micromega plugin *) | "Add" "Zify" "BinRel" reference (* micromega plugin *) | "Add" "Zify" "PropOp" reference (* micromega plugin *) | "Add" "Zify" "PropBinOp" reference (* micromega plugin *) | "Add" "Zify" "PropUOp" reference (* micromega plugin *) | "Add" "Zify" "BinOpSpec" reference (* micromega plugin *) | "Add" "Zify" "UnOpSpec" reference (* micromega plugin *) | "Add" "Zify" "Saturate" reference (* micromega plugin *) | "Show" "Zify" "InjTyp" (* micromega plugin *) | "Show" "Zify" "BinOp" (* micromega plugin *) | "Show" "Zify" "UnOp" (* micromega plugin *) | "Show" "Zify" "CstOp" (* micromega plugin *) | "Show" "Zify" "BinRel" (* micromega plugin *) | "Show" "Zify" "UnOpSpec" (* micromega plugin *) | "Show" "Zify" "BinOpSpec" (* micromega plugin *) | "Add" "Ring" identref ":" constr OPT ring_mods (* ring plugin *) | "Print" "Rings" (* ring plugin *) | "Add" "Field" identref ":" constr OPT field_mods (* ring plugin *) | "Print" "Fields" (* ring plugin *) | "Number" "Notation" reference reference reference OPT number_options ":" preident | "String" "Notation" reference reference reference OPT string_option ":" preident | "Ltac2" ltac2_entry (* ltac2 plugin *) | "Ltac2" "Import" "Type" reference "as" ident (* ltac2 plugin *) | "Ltac2" "Custom" "Entry" identref (* ltac2 plugin *) | "Ltac2" "Notation" ltac2def_syn (* ltac2 plugin *) | "Ltac2" "Abbreviation" ltac2abbrev_syn (* ltac2 plugin *) | "Ltac2" "Eval" ltac2_expr6 (* ltac2 plugin *) | "Print" test_ltac2_ident "Ltac2" reference (* ltac2 plugin *) | "Print" "Ltac2" "Type" reference (* ltac2 plugin *) | "Locate" "Ltac2" reference (* ltac2 plugin *) | "Print" "Ltac2" "Signatures" (* ltac2 plugin *) | "Ltac2" "Check" ltac2_expr6 (* ltac2 plugin *) | "Ltac2" "Globalize" ltac2_expr6 (* ltac2 plugin *) ] reference_or_constr: [ | global | constr ] hint: [ | "Resolve" LIST1 reference_or_constr hint_info | "Resolve" "->" LIST1 global OPT natural | "Resolve" "<-" LIST1 global OPT natural | "Immediate" LIST1 reference_or_constr | "Variables" "Transparent" | "Variables" "Opaque" | "Constants" "Transparent" | "Constants" "Opaque" | "Projections" "Transparent" | "Projections" "Opaque" | "Transparent" LIST1 global | "Opaque" LIST1 global | "Mode" global mode | "Unfold" LIST1 global | "Constructors" LIST1 global | "Extern" natural OPT Constr.constr_pattern "=>" generic_tactic ] mode: [ | LIST1 [ "+" | "!" | "-" ] ] int_or_var: [ | integer | identref ] nat_or_var: [ | natural | identref ] occs_nums: [ | LIST1 nat_or_var | "-" LIST1 nat_or_var ] occs: [ | "at" occs_nums | ] pattern_occ: [ | constr occs ] ref_or_pattern_occ: [ | smart_global occs | constr occs ] unfold_occ: [ | smart_global occs ] red_flag: [ | "beta" | "iota" | "match" | "fix" | "cofix" | "zeta" | "delta" delta_flag | "head" ] delta_flag: [ | "-" "[" LIST1 smart_global "]" | "[" LIST1 smart_global "]" | ] strategy_flag: [ | LIST1 red_flag | OPT "head" delta_flag ] red_expr: [ | "red" | "hnf" | "simpl" OPT "head" delta_flag OPT ref_or_pattern_occ | "cbv" strategy_flag | "cbn" strategy_flag | "lazy" strategy_flag | "compute" delta_flag | "vm_compute" OPT ref_or_pattern_occ | "native_compute" OPT ref_or_pattern_occ | "unfold" LIST1 unfold_occ SEP "," | "fold" LIST1 constr | "pattern" LIST1 pattern_occ SEP "," | IDENT ] vernac_control: [ | LIST0 control_flag decorated_vernac ] control_flag: [ | "Time" | "Instructions" | "Profile" OPT STRING | "Redirect" ne_string | "Timeout" natural | "Fail" | "Succeed" ] decorated_vernac: [ | quoted_attributes LIST0 legacy_attr vernac_aux ] quoted_attributes: [ | LIST0 [ "#[" attribute_list "]" ] ] attribute_list: [ | LIST1 attribute SEP "," ] attribute: [ | ident attr_value | "using" attr_value ] attr_value: [ | "=" string | "=" qualid | "(" attribute_list ")" | ] legacy_attr: [ | "Local" | "Global" | "Polymorphic" | "Monomorphic" | "Cumulative" | "NonCumulative" | "Private" | "Program" ] vernac_aux: [ | gallina "." | gallina_ext "." | command "." | syntax "." | command_entry ] noedit_mode: [ | query_command ] subprf: [ | BULLET | "}" ] subprf_with_selector: [ | "{" | query_command ] gallina: [ | thm_token ident_decl binders ":" lconstr LIST0 [ "with" ident_decl binders ":" lconstr ] | assumption_token inline assum_list | assumptions_token inline assum_list | def_token ident_decl def_body | "Symbol" assum_list | "Symbols" assum_list | "Let" ident_decl def_body | finite_token inductive_or_record_definition | inductive_token LIST1 inductive_or_record_definition SEP "with" | "Fixpoint" LIST1 fix_definition SEP "with" | "Let" "Fixpoint" LIST1 fix_definition SEP "with" | "CoFixpoint" LIST1 cofix_definition SEP "with" | "Let" "CoFixpoint" LIST1 cofix_definition SEP "with" | "Scheme" "All" "for" smart_global OPT [ "over" LIST1 ident SEP "," ] | "Scheme" LIST1 scheme SEP "with" | "Scheme" "Equality" "for" smart_global | "Scheme" "Boolean" "Equality" "for" smart_global | "Scheme" "Rewriting" "for" smart_global | "Combined" "Scheme" identref "from" LIST1 identref SEP "," | "Register" global "as" qualid | "Register" "Scheme" global "as" qualid "for" global | "Register" "Inline" global | "Primitive" ident_decl OPT [ ":" lconstr ] ":=" register_token | "Universe" LIST1 identref | "Universes" LIST1 identref | "Sort" LIST1 identref | "Sorts" LIST1 identref | "Constraint" LIST1 sort_constraint SEP "," | "Rewrite" "Rule" identref ":=" OPT "|" LIST1 rewrite_rule SEP "|" | "Rewrite" "Rules" identref ":=" OPT "|" LIST1 rewrite_rule SEP "|" ] register_token: [ | test_hash_ident "#" IDENT ] thm_token: [ | "Theorem" | "Lemma" | "Fact" | "Remark" | "Corollary" | "Proposition" | "Property" ] def_token: [ | "Definition" | "Example" | "SubClass" ] assumption_token: [ | "Hypothesis" | "Variable" | "Axiom" | "Parameter" | "Conjecture" ] assumptions_token: [ | "Hypotheses" | "Variables" | "Axioms" | "Parameters" | "Conjectures" ] inline: [ | "Inline" "(" natural ")" | "Inline" | ] sort_constraint: [ | test_univ_cst universe_name [ "<" | "=" | "<=" ] universe_name | sort_quality_var "->" sort_quality_var ] univ_decl_constraints: [ | "|" LIST0 sort_constraint SEP "," [ "+" | ] "}" | [ "}" | bar_cbrace ] ] univ_decl: [ | "@{" test_doublepipe_univ_decl LIST0 identref "|" LIST0 identref [ "+" | ] univ_decl_constraints | "@{" LIST0 identref ";" LIST0 identref [ "+" | ] univ_decl_constraints | "@{" LIST0 identref [ "+" | ] univ_decl_constraints ] variance: [ | "+" | "=" | "*" ] variance_identref: [ | identref | test_variance_ident variance identref ] cumul_univ_decl: [ | "@{" test_doublepipe_cumul_univ_decl LIST0 identref "|" LIST0 variance_identref [ "+" | ] univ_decl_constraints | "@{" test_semicolon_cumul_univ_decl LIST0 identref ";" LIST0 variance_identref [ "+" | ] univ_decl_constraints | "@{" LIST0 variance_identref [ "+" | ] univ_decl_constraints ] ident_decl: [ | identref OPT univ_decl ] cumul_ident_decl: [ | identref OPT cumul_univ_decl ] inductive_token: [ | "Inductive" | "CoInductive" ] finite_token: [ | "Variant" | "Record" | "Structure" | "Class" ] def_body: [ | binders ":=" reduce lconstr | binders ":" lconstr ":=" reduce lconstr | binders ":" lconstr ] reduce: [ | "Eval" red_expr "in" | ] notation_declaration: [ | lstring ":=" constr syntax_modifiers OPT [ ":" IDENT ] ] decl_sep: [ | "and" ] decl_notations: [ | "where" LIST1 notation_declaration SEP decl_sep | ] opt_constructors_or_fields: [ | ":=" constructors_or_record | ":=" | ] inductive_or_record_definition: [ | opt_coercion cumul_ident_decl binders OPT [ "|" binders ] OPT [ ":" lconstr ] opt_constructors_or_fields decl_notations ] constructors_or_record: [ | "|" LIST1 constructor SEP "|" | quoted_attributes identref constructor_type "|" LIST1 constructor SEP "|" | quoted_attributes identref constructor_type | quoted_attributes identref "{" record_fields "}" default_inhabitant_ident | "{" record_fields "}" default_inhabitant_ident ] default_inhabitant_ident: [ | "as" identref | ] opt_coercion: [ | ">" | ] fix_definition: [ | ident_decl binders_fixannot type_cstr OPT [ ":=" lconstr ] decl_notations ] cofix_definition: [ | ident_decl binders type_cstr OPT [ ":=" lconstr ] decl_notations ] rw_pattern: [ | lconstr ] rewrite_rule: [ | OPT [ univ_decl "|-" ] rw_pattern "=>" lconstr ] scheme: [ | scheme_kind | identref ":=" scheme_kind ] scheme_kind: [ | scheme_type "for" smart_global "Sort" sort_quality_or_set ] scheme_type: [ | "Induction" | "Minimality" | "Elimination" | "Case" ] record_field: [ | quoted_attributes record_binder OPT [ "|" natural ] decl_notations ] record_fields: [ | record_field ";" record_fields | record_field | ] field_body: [ | binders of_type_inst lconstr | binders of_type_inst lconstr ":=" lconstr | binders ":=" lconstr ] record_binder: [ | name | name field_body ] assum_list: [ | LIST1 assum_coe | assumpt ] assum_coe: [ | "(" assumpt ")" ] assumpt: [ | LIST1 ident_decl of_type lconstr ] constructor_type: [ | binders [ of_type_inst lconstr | ] ] constructor: [ | quoted_attributes identref constructor_type ] of_type: [ | ":>" | ":" ">" | ":" ] of_type_inst: [ | ":>" | ":" ">" | "::" | "::>" | ":" ] gallina_ext: [ | "Module" export_token identref LIST0 module_binder of_module_type is_module_expr | "Module" "Type" identref LIST0 module_binder check_module_types is_module_type | "Declare" "Module" export_token identref LIST0 module_binder ":" module_type_inl | "Section" identref | "End" identref | "Collection" identref ":=" section_subset_expr | "From" global "Extra" "Dependency" ne_string OPT [ "as" IDENT ] | "Require" export_token LIST1 filtered_import | "From" global "Require" export_token LIST1 filtered_import | "Import" OPT import_categories LIST1 filtered_import | "Export" OPT import_categories LIST1 filtered_import | "Include" module_type_inl LIST0 ext_module_type | "Include" "Type" module_type_inl LIST0 ext_module_type | "Transparent" OPT "!" LIST1 smart_global | "Opaque" OPT "!" LIST1 smart_global | "Strategy" LIST1 [ strategy_level "[" LIST1 smart_global "]" ] | "Canonical" OPT "Structure" global OPT [ OPT univ_decl def_body ] | "Canonical" OPT "Structure" by_notation | "Coercion" global OPT [ OPT univ_decl def_body ] | "Identity" "Coercion" identref ":" coercion_class ">->" coercion_class | "Coercion" global ":" coercion_class ">->" coercion_class | "Coercion" by_notation ":" coercion_class ">->" coercion_class | "Context" LIST1 binder | "Instance" instance_name ":" term200 hint_info [ ":=" "{" record_declaration "}" | ":=" lconstr | ] | "Existing" "Instance" global hint_info | "Existing" "Instances" LIST1 global OPT [ "|" natural ] | "Existing" "Class" global | "Arguments" smart_global LIST0 arg_specs OPT [ "," LIST1 [ LIST0 implicits_alt ] SEP "," ] OPT [ ":" LIST1 args_modifier SEP "," ] | "Implicit" "Type" reserv_list | "Implicit" "Types" reserv_list | "Generalizable" [ "All" "Variables" | "No" "Variables" | [ "Variable" | "Variables" ] LIST1 identref ] | "Export" "Set" setting_name option_setting | "Export" "Unset" setting_name ] import_categories: [ | OPT "-" "(" LIST1 qualid SEP "," ")" ] filtered_import: [ | global | global "(" LIST1 one_import_filter_name SEP "," ")" ] one_import_filter_name: [ | global OPT [ "(" ".." ")" ] ] export_token: [ | "Import" OPT import_categories | "Export" OPT import_categories | ] ext_module_type: [ | "<+" module_type_inl ] ext_module_expr: [ | "<+" module_expr_inl ] check_module_type: [ | "<:" module_type_inl ] check_module_types: [ | LIST0 check_module_type ] of_module_type: [ | ":" module_type_inl | check_module_types ] is_module_type: [ | ":=" module_type_inl LIST0 ext_module_type | ] is_module_expr: [ | ":=" module_expr_inl LIST0 ext_module_expr | ] functor_app_annot: [ | "[" "inline" "at" "level" natural "]" | "[" "no" "inline" "]" | ] module_expr_inl: [ | "!" module_expr | module_expr functor_app_annot ] module_type_inl: [ | "!" module_type | module_type functor_app_annot ] module_binder: [ | "(" export_token LIST1 identref ":" module_type_inl ")" ] module_expr: [ | module_expr_atom | module_expr module_expr_atom ] module_expr_atom: [ | qualid | "(" module_expr_atom ")" ] with_declaration: [ | "Definition" fullyqualid OPT univ_decl ":=" Constr.lconstr | "Module" fullyqualid ":=" qualid ] module_type: [ | qualid | "(" module_type ")" | module_type module_expr_atom | module_type "with" with_declaration ] section_subset_expr: [ | test_only_starredidentrefs LIST0 starredidentref | ssexpr35 ] starredidentref: [ | identref | identref "*" | "Type" | "Type" "*" ] ssexpr35: [ | "-" ssexpr50 | ssexpr50 ] ssexpr50: [ | ssexpr0 "-" ssexpr0 | ssexpr0 "+" ssexpr0 | ssexpr0 ] ssexpr0: [ | starredidentref | "()" | "(" test_only_starredidentrefs LIST0 starredidentref ")" | "(" test_only_starredidentrefs LIST0 starredidentref ")" "*" | "(" ssexpr35 ")" | "(" ssexpr35 ")" "*" ] args_modifier: [ | "simpl" "nomatch" | "simpl" "never" | "clear" "simpl" | "default" "implicits" | "clear" "implicits" | "clear" "scopes" | "clear" "bidirectionality" "hint" | "rename" | "assert" | "extra" "scopes" | "clear" "scopes" "and" "implicits" | "clear" "implicits" "and" "scopes" ] scope_delimiter: [ | "%" IDENT | "%_" IDENT ] argument_spec: [ | OPT "!" name LIST0 scope_delimiter ] arg_specs: [ | argument_spec | "/" | "&" | "(" LIST1 argument_spec ")" LIST0 scope_delimiter | "[" LIST1 argument_spec "]" LIST0 scope_delimiter | "{" LIST1 argument_spec "}" LIST0 scope_delimiter ] implicits_alt: [ | name | "[" LIST1 name "]" | "{" LIST1 name "}" ] instance_name: [ | ident_decl binders | ] hint_info: [ | "|" OPT natural OPT constr_pattern | ] reserv_list: [ | LIST1 reserv_tuple | simple_reserv ] reserv_tuple: [ | "(" simple_reserv ")" ] simple_reserv: [ | LIST1 identref ":" lconstr ] range_selector: [ | natural "-" natural | natural | test_bracket_ident "[" qualid "]" ] goal_selector: [ | LIST1 range_selector SEP "," ] toplevel_selector: [ | goal_selector ":" | "!" ":" | "all" ":" ] query_command: [ | "Eval" red_expr "in" lconstr "." | "Compute" lconstr "." | "Check" lconstr "." | "About" smart_global OPT univ_name_list "." | "SearchPattern" constr_pattern in_or_out_modules "." | "SearchRewrite" constr_pattern in_or_out_modules "." | "Search" search_query search_queries "." ] printable: [ | "Term" smart_global OPT univ_name_list | "All" | "Section" global | "Grammar" LIST0 IDENT | "Custom" "Grammar" qualid | "Keywords" | "LoadPath" OPT dirpath | "Libraries" | "Notation" string | "Notation" string "in" "custom" qualid | "ML" "Path" | "ML" "Modules" | "Debug" "GC" | "Graph" | "Classes" | "Typeclasses" | "Instances" smart_global | "Coercions" | "Coercion" "Paths" coercion_class coercion_class | "Canonical" "Projections" LIST0 smart_global | "Typing" "Flags" | "Tables" | "Options" | "Hint" | "Hint" smart_global | "Hint" "*" | "HintDb" IDENT | "Scopes" | "Scope" IDENT | "Visibility" OPT IDENT | "Implicit" smart_global | [ "Sorted" | ] "Universes" OPT printunivs_subgraph OPT [ [ "With" | "Without" ] "Constraint" "Sources" ] OPT ne_string | "Sorts" | "Assumptions" LIST1 smart_global | "Opaque" "Dependencies" LIST1 smart_global | "Transparent" "Dependencies" LIST1 smart_global | "All" "Dependencies" LIST1 smart_global | "Strategy" smart_global | "Strategies" | "Registered" | "Registered" "Schemes" ] debug_univ_name: [ | reference | STRING ] printunivs_subgraph: [ | "Subgraph" "(" LIST0 debug_univ_name ")" ] coercion_class: [ | "Funclass" | "Sortclass" | smart_global ] locatable: [ | smart_global | "Term" smart_global | "File" ne_string | "Library" global | "Module" global ] option_setting: [ | | integer | STRING ] table_value: [ | global | STRING ] setting_name: [ | LIST1 IDENT ] ne_in_or_out_modules: [ | "inside" LIST1 global | "in" LIST1 global | "outside" LIST1 global ] in_or_out_modules: [ | ne_in_or_out_modules | ] comment: [ | constr | STRING | natural ] positive_search_mark: [ | "-" | ] search_query: [ | positive_search_mark search_item | positive_search_mark "[" LIST1 ( LIST1 search_query ) SEP "|" "]" ] search_item: [ | test_id_colon search_where ":" ne_string OPT scope_delimiter | "is" ":" logical_kind | ne_string OPT scope_delimiter | test_id_colon search_where ":" constr_pattern | constr_pattern ] logical_kind: [ | thm_token | assumption_token | "Context" | extended_def_token | "Primitive" | "Symbol" ] extended_def_token: [ | def_token | "Coercion" | "Fixpoint" | "CoFixpoint" | "Instance" | "Scheme" | "Canonical" | "Field" | "Method" ] search_where: [ | "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] search_queries: [ | ne_in_or_out_modules | search_query search_queries | ] univ_name_list: [ | "@{" LIST0 name "}" ] syntax: [ | "Open" "Scope" IDENT | "Close" "Scope" IDENT | "Delimit" "Scope" IDENT; "with" IDENT | "Undelimit" "Scope" IDENT | "Bind" "Scope" IDENT; "with" LIST1 coercion_class | "Infix" notation_declaration | located_notation identref LIST0 ident ":=" constr syntax_modifiers | "Abbreviation" identref LIST0 ident ":=" constr syntax_modifiers | located_notation notation_declaration | "Reserved" "Infix" ne_lstring syntax_modifiers | "Reserved" "Notation" ne_lstring syntax_modifiers | enable_enable_disable "Notation" enable_notation_rule enable_notation_interpretation enable_notation_flags opt_scope ] located_notation: [ | "Notation" ] enable_enable_disable: [ | "Enable" | "Disable" ] enable_notation_rule: [ | ne_string | global LIST0 ident | ] enable_notation_interpretation: [ | ":=" constr | ] enable_notation_flags: [ | "(" LIST1 enable_notation_flag SEP "," ")" | ] enable_notation_flag: [ | "all" | "only" "parsing" | "only" "printing" | "in" "custom" qualid | "in" "constr" ] opt_scope: [ | ":" IDENT | ":" "no" "scope" | ] level: [ | "level" natural | "next" "level" ] syntax_modifier: [ | "at" "level" natural | "in" "custom" qualid | "in" "custom" qualid "at" "level" natural | "left" "associativity" | "right" "associativity" | "no" "associativity" | "only" "printing" | "only" "parsing" | "format" lstring | IDENT; "," LIST1 IDENT SEP "," [ "at" level | "in" "scope" IDENT ] | IDENT; "at" level OPT binder_interp | IDENT; "in" "scope" IDENT | IDENT binder_interp | IDENT explicit_subentry ] syntax_modifiers: [ | "(" LIST1 syntax_modifier SEP "," ")" | ] explicit_subentry: [ | "ident" | "name" | "global" | "bigint" | "binder" | "constr" | "constr" at_level_opt OPT binder_interp | "pattern" | "pattern" "at" "level" natural | "strict" "pattern" | "strict" "pattern" "at" "level" natural | "closed" "binder" | "custom" qualid at_level_opt OPT binder_interp ] at_level_opt: [ | "at" level | ] binder_interp: [ | "as" "ident" | "as" "name" | "as" "pattern" | "as" "strict" "pattern" ] withtac: [ | | "with" generic_tactic ] simple_tactic: [ | "btauto" | "congruence" OPT natural | "congruence" OPT natural "with" LIST1 constr | "simple" "congruence" OPT natural | "simple" "congruence" OPT natural "with" LIST1 constr | "f_equal" | "firstorder" OPT tactic firstorder_using | "firstorder" OPT tactic "with" LIST1 preident | "firstorder" OPT tactic firstorder_using "with" LIST1 preident | "functional" "inversion" quantified_hypothesis OPT reference (* funind plugin *) | "functional" "induction" lconstr fun_ind_using with_names (* funind plugin *) | "soft" "functional" "induction" LIST1 constr fun_ind_using with_names (* funind plugin *) | "reflexivity" | "exact" uconstr | "assumption" | "etransitivity" | "cut" constr | "exact_no_check" constr | "vm_cast_no_check" constr | "native_cast_no_check" constr | "exfalso" | "lapply" constr | "transitivity" constr | "left" | "eleft" | "left" "with" bindings | "eleft" "with" bindings | "right" | "eright" | "right" "with" bindings | "eright" "with" bindings | "constructor" | "constructor" nat_or_var | "constructor" nat_or_var "with" bindings | "econstructor" | "econstructor" nat_or_var | "econstructor" nat_or_var "with" bindings | "specialize" constr_with_bindings | "specialize" constr_with_bindings "as" simple_intropattern | "symmetry" | "symmetry" "in" in_clause | "split" | "esplit" | "split" "with" bindings | "esplit" "with" bindings | "exists" | "exists" LIST1 bindings SEP "," | "eexists" | "eexists" LIST1 bindings SEP "," | "intros" "until" quantified_hypothesis | "intro" | "intro" ident | "intro" ident "at" "top" | "intro" ident "at" "bottom" | "intro" ident "after" hyp | "intro" ident "before" hyp | "intro" "at" "top" | "intro" "at" "bottom" | "intro" "after" hyp | "intro" "before" hyp | "move" hyp "at" "top" | "move" hyp "at" "bottom" | "move" hyp "after" hyp | "move" hyp "before" hyp | "rename" LIST1 rename SEP "," | "revert" LIST1 hyp | "simple" "induction" quantified_hypothesis | "simple" "destruct" quantified_hypothesis | "admit" | "fix" ident natural | "cofix" ident | "clear" LIST0 hyp | "clear" "-" LIST1 hyp | "clearbody" LIST1 hyp | "generalize" "dependent" constr | "assert_succeeds" tactic3 | "replace" uconstr "with" constr clause by_arg_tac | "replace" "->" uconstr clause | "replace" "->" uconstr "with" constr clause by_arg_tac | "replace" "<-" uconstr clause | "replace" "<-" uconstr "with" constr clause by_arg_tac | "replace" uconstr clause | "simplify_eq" | "simplify_eq" destruction_arg | "esimplify_eq" | "esimplify_eq" destruction_arg | "discriminate" | "discriminate" destruction_arg | "ediscriminate" | "ediscriminate" destruction_arg | "injection" | "injection" destruction_arg | "einjection" | "einjection" destruction_arg | "injection" "as" LIST0 simple_intropattern | "injection" destruction_arg "as" LIST0 simple_intropattern | "einjection" "as" LIST0 simple_intropattern | "einjection" destruction_arg "as" LIST0 simple_intropattern | "simple" "injection" | "simple" "injection" destruction_arg | "dependent" "rewrite" orient constr | "dependent" "rewrite" orient constr "in" hyp | "decompose" "sum" constr | "decompose" "record" constr | "absurd" constr | "contradiction" OPT constr_with_bindings | "autorewrite" "with" LIST1 preident clause | "autorewrite" "with" LIST1 preident clause "using" tactic | "autorewrite" "*" "with" LIST1 preident clause | "autorewrite" "*" "with" LIST1 preident clause "using" tactic | "rewrite" "*" orient uconstr "in" hyp "at" occurrences by_arg_tac | "rewrite" "*" orient uconstr "at" occurrences "in" hyp by_arg_tac | "rewrite" "*" orient uconstr "in" hyp by_arg_tac | "rewrite" "*" orient uconstr "at" occurrences by_arg_tac | "rewrite" "*" orient uconstr by_arg_tac | "refine" uconstr | "simple" "refine" uconstr | "notypeclasses" "refine" uconstr | "simple" "notypeclasses" "refine" uconstr | "solve_constraints" | "subst" LIST1 hyp | "subst" | "simple" "subst" | "evar" test_lpar_id_colon "(" ident ":" lconstr ")" | "evar" constr | "instantiate" "(" ident ":=" lglob ")" | "instantiate" "(" natural ":=" lglob ")" hloc | "stepl" constr "by" tactic | "stepl" constr | "stepr" constr "by" tactic | "stepr" constr | "generalize_eqs" hyp | "dependent" "generalize_eqs" hyp | "generalize_eqs_vars" hyp | "dependent" "generalize_eqs_vars" hyp | "specialize_eqs" hyp | "transparent_abstract" tactic3 | "transparent_abstract" tactic3 "using" ident | "constr_eq" constr constr | "constr_eq_strict" constr constr | "constr_eq_nounivs" constr constr | "is_evar" constr | "has_evar" constr | "is_var" constr | "is_fix" constr | "is_cofix" constr | "is_ind" constr | "is_constructor" constr | "is_proj" constr | "is_const" constr | "shelve" | "shelve_unifiable" | "unshelve" tactic1 | "give_up" | "cycle" int_or_var | "swap" int_or_var int_or_var | "revgoals" | "guard" test | "decompose" "[" LIST1 constr "]" constr | "optimize_heap" | "with_strategy" strategy_level_or_var "[" LIST1 smart_global "]" tactic3 | "eassumption" | "eexact" constr | "trivial" auto_using hintbases | "info_trivial" auto_using hintbases | "debug" "trivial" auto_using hintbases | "auto" OPT nat_or_var auto_using hintbases | "info_auto" OPT nat_or_var auto_using hintbases | "debug" "auto" OPT nat_or_var auto_using hintbases | "eauto" OPT nat_or_var auto_using hintbases | "debug" "eauto" OPT nat_or_var auto_using hintbases | "info_eauto" OPT nat_or_var auto_using hintbases | "autounfold" hintbases clause_dft_concl | "autounfold_one" hintbases "in" hyp | "autounfold_one" hintbases | "unify" constr constr | "unify" constr constr "with" preident | "convert" constr constr | "typeclasses" "eauto" "dfs" OPT nat_or_var "with" LIST1 preident | "typeclasses" "eauto" "bfs" OPT nat_or_var "with" LIST1 preident | "typeclasses" "eauto" "best_effort" OPT nat_or_var "with" LIST1 preident | "typeclasses" "eauto" OPT nat_or_var "with" LIST1 preident | "typeclasses" "eauto" "bfs" OPT nat_or_var | "typeclasses" "eauto" "dfs" OPT nat_or_var | "typeclasses" "eauto" "best_effort" OPT nat_or_var | "typeclasses" "eauto" OPT nat_or_var | "not_evar" constr | "is_ground" constr | "autoapply" constr "with" preident | "decide" "equality" | "compare" constr constr | "rewrite_strat" rewstrategy "in" hyp | "rewrite_strat" rewstrategy | "rewrite_db" preident "in" hyp | "rewrite_db" preident | "substitute" orient glob_constr_with_bindings | "setoid_rewrite" orient glob_constr_with_bindings | "setoid_rewrite" orient glob_constr_with_bindings "in" hyp | "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences | "setoid_rewrite" orient glob_constr_with_bindings "at" occurrences "in" hyp | "setoid_rewrite" orient glob_constr_with_bindings "in" hyp "at" occurrences | "setoid_symmetry" | "setoid_symmetry" "in" hyp | "setoid_reflexivity" | "setoid_transitivity" constr | "setoid_etransitivity" | "intros" ne_intropatterns | "intros" | "eintros" ne_intropatterns | "eintros" | "apply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as | "eapply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as | "simple" "apply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as | "simple" "eapply" LIST1 constr_with_bindings_arg SEP "," in_hyp_as | "elim" constr_with_bindings_arg OPT eliminator | "eelim" constr_with_bindings_arg OPT eliminator | "case" induction_clause_list | "ecase" induction_clause_list | "fix" ident natural "with" LIST1 fixdecl | "cofix" ident "with" LIST1 cofixdecl | "pose" bindings_with_parameters | "pose" constr as_name | "epose" bindings_with_parameters | "epose" constr as_name | "set" bindings_with_parameters clause_dft_concl | "set" constr as_name clause_dft_concl | "eset" bindings_with_parameters clause_dft_concl | "eset" constr as_name clause_dft_concl | "remember" constr as_name eqn_ipat clause_dft_all | "eremember" constr as_name eqn_ipat clause_dft_all | "assert" test_lpar_id_coloneq "(" identref ":=" lconstr ")" | "eassert" test_lpar_id_coloneq "(" identref ":=" lconstr ")" | "assert" test_lpar_id_colon "(" identref ":" lconstr ")" by_tactic | "eassert" test_lpar_id_colon "(" identref ":" lconstr ")" by_tactic | "enough" test_lpar_id_colon "(" identref ":" lconstr ")" by_tactic | "eenough" test_lpar_id_colon "(" identref ":" lconstr ")" by_tactic | "assert" constr as_ipat by_tactic | "eassert" constr as_ipat by_tactic | "pose" "proof" test_lpar_id_coloneq "(" identref ":=" lconstr ")" | "epose" "proof" test_lpar_id_coloneq "(" identref ":=" lconstr ")" | "pose" "proof" lconstr as_ipat | "epose" "proof" lconstr as_ipat | "enough" constr as_ipat by_tactic | "eenough" constr as_ipat by_tactic | "generalize" constr | "generalize" constr LIST1 constr | "generalize" constr lookup_at_as_comma occs as_name LIST0 [ "," pattern_occ as_name ] | "induction" induction_clause_list | "einduction" induction_clause_list | "destruct" induction_clause_list | "edestruct" induction_clause_list | "rewrite" LIST1 oriented_rewriter SEP "," clause_dft_concl by_tactic | "erewrite" LIST1 oriented_rewriter SEP "," clause_dft_concl by_tactic | "dependent" [ "simple" "inversion" | "inversion" | "inversion_clear" ] quantified_hypothesis as_or_and_ipat OPT [ "with" constr ] | "simple" "inversion" quantified_hypothesis as_or_and_ipat in_hyp_list | "inversion" quantified_hypothesis as_or_and_ipat in_hyp_list | "inversion_clear" quantified_hypothesis as_or_and_ipat in_hyp_list | "inversion" quantified_hypothesis "using" constr in_hyp_list | "red" clause_dft_concl | "hnf" clause_dft_concl | "simpl" OPT "head" delta_flag OPT ref_or_pattern_occ clause_dft_concl | "cbv" strategy_flag clause_dft_concl | "cbn" strategy_flag clause_dft_concl | "lazy" strategy_flag clause_dft_concl | "compute" delta_flag clause_dft_concl | "vm_compute" OPT ref_or_pattern_occ clause_dft_concl | "native_compute" OPT ref_or_pattern_occ clause_dft_concl | "unfold" LIST1 unfold_occ SEP "," clause_dft_concl | "fold" LIST1 constr clause_dft_concl | "pattern" LIST1 pattern_occ SEP "," clause_dft_concl | "change" conversion clause_dft_concl | "change_no_check" conversion clause_dft_concl | "start" "ltac" "profiling" | "stop" "ltac" "profiling" | "reset" "ltac" "profile" | "show" "ltac" "profile" | "show" "ltac" "profile" "cutoff" integer | "show" "ltac" "profile" string | "restart_timer" OPT string | "finish_timing" OPT string | "finish_timing" "(" string ")" OPT string | "xlra_Q" tactic (* micromega plugin *) | "wlra_Q" ident constr (* micromega plugin *) | "xlra_R" tactic (* micromega plugin *) | "xlia" tactic (* micromega plugin *) | "wlia" ident constr (* micromega plugin *) | "xnra_Q" tactic (* micromega plugin *) | "wnra_Q" ident constr (* micromega plugin *) | "xnra_R" tactic (* micromega plugin *) | "xnia" tactic (* micromega plugin *) | "wnia" ident constr (* micromega plugin *) | "xsos_Z" tactic (* micromega plugin *) | "wsos_Z" ident constr (* micromega plugin *) | "xsos_Q" tactic (* micromega plugin *) | "wsos_Q" ident constr (* micromega plugin *) | "xsos_R" tactic (* micromega plugin *) | "xpsatz_Z" nat_or_var tactic (* micromega plugin *) | "wpsatz_Z" nat_or_var ident constr (* micromega plugin *) | "xpsatz_Q" nat_or_var tactic (* micromega plugin *) | "wpsatz_Q" nat_or_var ident constr (* micromega plugin *) | "xpsatz_R" nat_or_var tactic (* micromega plugin *) | "zify_iter_specs" (* micromega plugin *) | "zify_op" (* micromega plugin *) | "zify_saturate" (* micromega plugin *) | "zify_iter_let" tactic (* micromega plugin *) | "zify_elim_let" (* micromega plugin *) | "nsatz_compute" constr (* nsatz plugin *) | "protect_fv" string "in" ident (* ring plugin *) | "protect_fv" string (* ring plugin *) | "ring_lookup" tactic0 "[" LIST0 constr "]" LIST1 constr (* ring plugin *) | "field_lookup" tactic "[" LIST0 constr "]" LIST1 constr (* ring plugin *) | "rtauto" ] mlname: [ | preident (* extraction plugin *) | string (* extraction plugin *) ] int_or_id: [ | preident (* extraction plugin *) | integer (* extraction plugin *) ] language: [ | "OCaml" (* extraction plugin *) | "Haskell" (* extraction plugin *) | "Scheme" (* extraction plugin *) | "JSON" (* extraction plugin *) ] firstorder_using: [ | "using" LIST1 reference SEP "," | ] fun_ind_using: [ | "using" constr_with_bindings (* funind plugin *) | (* funind plugin *) ] with_names: [ | "as" simple_intropattern (* funind plugin *) | (* funind plugin *) ] function_fix_definition: [ | Vernac.fix_definition (* funind plugin *) ] fun_scheme_arg: [ | identref ":=" "Induction" "for" reference "Sort" sort_quality_or_set (* funind plugin *) ] orient: [ | "->" | "<-" | ] EXTRAARGS_natural: [ | _natural ] occurrences: [ | LIST1 integer | hyp ] glob: [ | constr ] EXTRAARGS_lconstr: [ | l_constr ] lglob: [ | EXTRAARGS_lconstr ] hloc: [ | | "in" "|-" "*" | "in" ident | "in" "(" "type" "of" ident ")" | "in" "(" "value" "of" ident ")" ] rename: [ | ident "into" ident ] by_arg_tac: [ | "by" tactic3 | ] in_clause: [ | in_clause' | "*" occs | "*" "|-" concl_occ | "|-" concl_occ | LIST1 hypident_occ SEP "," "|-" concl_occ | LIST1 hypident_occ SEP "," ] test_lpar_id_colon: [ | local_test_lpar_id_colon ] EXTRAARGS_strategy_level: [ | strategy_level0 ] strategy_level_or_var: [ | EXTRAARGS_strategy_level | identref ] comparison: [ | "=" | "<" | "<=" | ">" | ">=" ] test: [ | int_or_var comparison int_or_var ] hintbases: [ | "with" "*" | "with" LIST1 preident | ] auto_using: [ | "using" LIST1 uconstr SEP "," | ] hints_path_entry: [ | hints_path1 ] hints_path1: [ | hints_path1 "*" | hints_path1 "|" hints_path0 | hints_path1 hints_path0 | hints_path0 ] hints_path0: [ | "(" hints_path1 ")" | "emp" | "eps" | LIST1 global | "_" ] opthints: [ | ":" LIST1 preident | ] debug: [ | "debug" | ] eauto_search_strategy_name: [ | "bfs" | "dfs" ] eauto_search_strategy: [ | "(" eauto_search_strategy_name ")" | ] tactic_then_last: [ | "|" LIST0 ( OPT ltac_expr5 ) SEP "|" | ] for_each_goal: [ | ltac_expr5 "|" for_each_goal | ltac_expr5 ".." tactic_then_last | ".." tactic_then_last | ltac_expr5 | "|" for_each_goal | ] tactic_then_locality: [ | "[" OPT ">" ] ltac_expr5: [ | ltac_expr4 ] ltac_expr4: [ | ltac_expr4 ";" ltac_expr3 | ltac_expr4 ";" tactic_then_locality for_each_goal "]" | ltac_expr3 ] ltac_expr3: [ | "try" ltac_expr3 | "do" nat_or_var ltac_expr3 | "timeout" nat_or_var ltac_expr3 | "time" OPT string ltac_expr3 | "repeat" ltac_expr3 | "progress" ltac_expr3 | "once" ltac_expr3 | "exactly_once" ltac_expr3 | "abstract" ltac_expr2 | "abstract" ltac_expr2 "using" ident | "only" goal_selector ":" ltac_expr3 | ltac_expr2 ] ltac_expr2: [ | ltac_expr1l "+" ltac_expr2 | "tryif" ltac_expr5 "then" ltac_expr5 "else" ltac_expr2 | ltac_expr1l "||" ltac_expr2 | ltac_expr1l ] ltac_expr1l: [ | ltac_expr1 ] ltac_expr1: [ | "fun" LIST1 input_fun "=>" ltac_expr5 | "let" [ "rec" | ] LIST1 let_clause SEP "with" "in" ltac_expr5 | match_key "goal" "with" match_context_list "end" | match_key "reverse" "goal" "with" match_context_list "end" | match_key ltac_expr5 "with" match_list "end" | "first" "[" LIST0 ltac_expr5 SEP "|" "]" | "solve" "[" LIST0 ltac_expr5 SEP "|" "]" | "idtac" LIST0 message_token | failkw [ nat_or_var | ] LIST0 message_token | simple_tactic | tactic_value | reference LIST0 tactic_arg | ltac_expr0 ] ltac_expr0: [ | "(" ltac_expr5 ")" | "[" ">" for_each_goal "]" | tactic_atom ] failkw: [ | "fail" | "gfail" ] tactic_arg: [ | tactic_value | Constr.constr | "()" ] tactic_value: [ | constr_eval | "fresh" LIST0 fresh_id | "type_term" uconstr | "numgoals" ] fresh_id: [ | STRING | qualid ] constr_eval: [ | "eval" red_expr "in" Constr.constr | "context" identref "[" Constr.lconstr "]" | "type" "of" Constr.constr ] tactic_atom: [ | integer | reference | "()" ] match_key: [ | "match" | "lazymatch" | "multimatch" ] input_fun: [ | "_" | ident ] let_clause: [ | identref ":=" ltac_expr5 | "_" ":=" ltac_expr5 | identref LIST1 input_fun ":=" ltac_expr5 ] match_pattern: [ | "context" OPT Constr.ident "[" Constr.cpattern "]" | Constr.cpattern ] match_hyp: [ | name ":" match_pattern | name ":=" "[" match_pattern "]" ":" match_pattern | name ":=" match_pattern ] match_context_rule: [ | LIST0 match_hyp SEP "," "|-" match_pattern "=>" ltac_expr5 | "[" LIST0 match_hyp SEP "," "|-" match_pattern "]" "=>" ltac_expr5 | "_" "=>" ltac_expr5 ] match_context_list: [ | LIST1 match_context_rule SEP "|" | "|" LIST1 match_context_rule SEP "|" ] match_rule: [ | match_pattern "=>" ltac_expr5 | "_" "=>" ltac_expr5 ] match_list: [ | LIST1 match_rule SEP "|" | "|" LIST1 match_rule SEP "|" ] message_token: [ | identref | STRING | natural ] ltac_def_kind: [ | ":=" | "::=" ] tacdef_body: [ | Constr.global LIST1 input_fun ltac_def_kind ltac_expr5 | Constr.global ltac_def_kind ltac_expr5 ] tactic: [ | ltac_expr5 ] tactic_mode: [ | subprf | OPT toplevel_selector subprf_with_selector | OPT ltac_selector OPT ltac_info tactic ltac_use_default | "par" ":" OPT ltac_info tactic "." ] ltac_selector: [ | toplevel_selector ] ltac_info: [ | "Info" natural ] ltac_use_default: [ | "." | "..." ] ltac_tactic_level: [ | "(" "at" "level" natural ")" ] ltac_production_sep: [ | "," string ] ltac_production_item: [ | string | ident "(" ident OPT ltac_production_sep ")" | ident ] ltac_tacdef_body: [ | tacdef_body ] glob_constr_with_bindings: [ | constr_with_bindings ] rewstrategy: [ | "fix" identref ":=" rewstrategy1 | ne_rewstrategy1_list_sep_semicolon ] ne_rewstrategy1_list_sep_semicolon: [ | ne_rewstrategy1_list_sep_semicolon ";" rewstrategy1 | rewstrategy1 ] rewstrategy1: [ | "<-" constr | "subterms" rewstrategy1 | "subterm" rewstrategy1 | "innermost" rewstrategy1 | "outermost" rewstrategy1 | "bottomup" rewstrategy1 | "topdown" rewstrategy1 | "progress" rewstrategy1 | "try" rewstrategy1 | "any" rewstrategy1 | "repeat" rewstrategy1 | "choice" LIST1 rewstrategy0 | "old_hints" preident | "hints" preident | "terms" LIST0 constr | "eval" red_expr | "fold" constr | rewstrategy0 ] rewstrategy0: [ | constr | "id" | "fail" | "refl" | "(" rewstrategy ")" ] id_or_meta: [ | identref ] open_constr: [ | constr ] uconstr: [ | constr ] destruction_arg: [ | natural | test_lpar_id_rpar constr_with_bindings | constr_with_bindings_arg ] constr_with_bindings_arg: [ | constr_with_bindings ] quantified_hypothesis: [ | ident | natural ] conversion: [ | constr | constr "with" constr | constr "at" occs_nums "with" constr ] intropatterns: [ | LIST0 intropattern ] ne_intropatterns: [ | LIST1 intropattern ] or_and_intropattern: [ | "[" LIST1 intropatterns SEP "|" "]" | "()" | "(" simple_intropattern ")" | "(" simple_intropattern "," LIST1 simple_intropattern SEP "," ")" | "(" simple_intropattern "&" LIST1 simple_intropattern SEP "&" ")" ] equality_intropattern: [ | "->" | "<-" | test_leftsquarebracket_equal "[" "=" intropatterns "]" ] naming_intropattern: [ | pattern_ident | "?" | ident ] intropattern: [ | simple_intropattern | "*" | "**" ] simple_intropattern: [ | simple_intropattern_closed LIST0 [ "%" term0 ] ] simple_intropattern_closed: [ | equality_intropattern | or_and_intropattern | "_" | naming_intropattern ] simple_binding: [ | "(" identref ":=" lconstr ")" | "(" natural ":=" lconstr ")" ] bindings: [ | test_lpar_idnum_coloneq LIST1 simple_binding | LIST1 constr ] constr_with_bindings: [ | constr with_bindings ] with_bindings: [ | "with" bindings | ] hypident: [ | id_or_meta | "(" "type" "of" id_or_meta ")" | "(" "value" "of" id_or_meta ")" ] hypident_occ: [ | hypident occs ] clause_dft_concl: [ | "in" in_clause | occs | ] clause_dft_all: [ | "in" in_clause | ] opt_clause: [ | "in" in_clause | "at" occs_nums | ] concl_occ: [ | "*" occs | ] in_hyp_list: [ | "in" LIST1 id_or_meta | ] in_hyp_as: [ | "in" LIST1 [ id_or_meta as_ipat ] SEP "," | ] orient_rw: [ | "->" | "<-" | ] simple_binder: [ | name | "(" LIST1 name ":" lconstr ")" ] fixdecl: [ | "(" ident LIST0 simple_binder struct_annot ":" lconstr ")" ] struct_annot: [ | "{" "struct" name "}" | ] cofixdecl: [ | "(" ident LIST0 simple_binder ":" lconstr ")" ] bindings_with_parameters: [ | check_for_coloneq "(" ident LIST0 simple_binder ":=" lconstr ")" ] eliminator: [ | "using" constr_with_bindings ] as_ipat: [ | "as" simple_intropattern | ] or_and_intropattern_loc: [ | or_and_intropattern | identref ] as_or_and_ipat: [ | "as" equality_intropattern | "as" or_and_intropattern_loc | ] eqn_ipat: [ | "eqn" ":" naming_intropattern | ] as_name: [ | "as" ident | ] by_tactic: [ | "by" ltac_expr3 | ] rewriter: [ | "!" constr_with_bindings_arg | [ "?" | LEFTQMARK ] constr_with_bindings_arg | natural "!" constr_with_bindings_arg | natural [ "?" | LEFTQMARK ] constr_with_bindings_arg | natural constr_with_bindings_arg | constr_with_bindings_arg ] oriented_rewriter: [ | orient_rw rewriter ] induction_clause: [ | destruction_arg as_or_and_ipat eqn_ipat opt_clause ] induction_clause_list: [ | LIST1 induction_clause SEP "," OPT eliminator opt_clause ] ring_mod: [ | "decidable" constr (* ring plugin *) | "abstract" (* ring plugin *) | "morphism" constr (* ring plugin *) | "constants" "[" tactic "]" (* ring plugin *) | "closed" "[" LIST1 global "]" (* ring plugin *) | "preprocess" "[" tactic "]" (* ring plugin *) | "postprocess" "[" tactic "]" (* ring plugin *) | "setoid" constr constr (* ring plugin *) | "sign" constr (* ring plugin *) | "power" constr "[" LIST1 global "]" (* ring plugin *) | "power_tac" constr "[" tactic "]" (* ring plugin *) | "div" constr (* ring plugin *) ] ring_mods: [ | "(" LIST1 ring_mod SEP "," ")" (* ring plugin *) ] field_mod: [ | ring_mod (* ring plugin *) | "completeness" constr (* ring plugin *) ] field_mods: [ | "(" LIST1 field_mod SEP "," ")" (* ring plugin *) ] number_string_mapping: [ | reference "=>" reference | "[" reference "]" "=>" reference ] number_string_via: [ | "via" reference "mapping" "[" LIST1 number_string_mapping SEP "," "]" ] number_modifier: [ | "warning" "after" bignat | "abstract" "after" bignat | number_string_via ] number_options: [ | "(" LIST1 number_modifier SEP "," ")" ] string_option: [ | "(" number_string_via ")" ] tac2pat3: [ | tac2pat3 "|" LIST1 tac2pat2 SEP "|" (* ltac2 plugin *) | tac2pat3 "as" identref (* ltac2 plugin *) | tac2pat2 (* ltac2 plugin *) ] tac2pat2: [ | tac2pat1 "::" tac2pat2 (* ltac2 plugin *) | tac2pat1 (* ltac2 plugin *) ] tac2pat1: [ | Prim.qualid LIST1 tac2pat0 (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) | tac2pat0 (* ltac2 plugin *) ] tac2pat0: [ | "_" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | Prim.integer (* ltac2 plugin *) | Prim.string (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) | "(" atomic_tac2pat ")" (* ltac2 plugin *) | "{" tac2rec_fieldpats "}" (* ltac2 plugin *) | "[" LIST0 tac2pat3 SEP ";" "]" (* ltac2 plugin *) ] atomic_tac2pat: [ | (* ltac2 plugin *) | tac2pat3 ":" ltac2_type5 (* ltac2 plugin *) | tac2pat3 "," LIST0 tac2pat3 SEP "," (* ltac2 plugin *) | tac2pat3 (* ltac2 plugin *) ] ltac2_expr6: [ | ltac2_expr5 ";" ltac2_expr6 (* ltac2 plugin *) | ltac2_expr5 (* ltac2 plugin *) ] ltac2_expr5: [ | "fun" LIST1 G_LTAC2_input_fun type_cast "=>" ltac2_expr6 (* ltac2 plugin *) | "let" rec_flag LIST1 G_LTAC2_let_clause SEP "with" "in" ltac2_expr6 (* ltac2 plugin *) | "match" ltac2_expr5 "with" G_LTAC2_branches "end" (* ltac2 plugin *) | "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5 (* ltac2 plugin *) | ltac2_expr4 (* ltac2 plugin *) ] ltac2_expr4: [ | ltac2_expr3 (* ltac2 plugin *) ] ltac2_expr3: [ | ltac2_expr2 "," LIST1 ltac2_expr2 SEP "," (* ltac2 plugin *) | ltac2_expr2 (* ltac2 plugin *) ] ltac2_expr2: [ | ltac2_expr1 "::" ltac2_expr2 (* ltac2 plugin *) | ltac2_expr1 (* ltac2 plugin *) ] ltac2_expr1: [ | ltac2_expr1 LIST1 ltac2_expr0 (* ltac2 plugin *) | ltac2_expr1 ".(" Prim.qualid ")" (* ltac2 plugin *) | ltac2_expr1 ".(" Prim.qualid ")" ":=" ltac2_expr5 (* ltac2 plugin *) | ltac2_expr0 (* ltac2 plugin *) ] ltac2_expr0: [ | "(" ltac2_expr6 ")" (* ltac2 plugin *) | "(" ltac2_expr6 ":" ltac2_type5 ")" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | "(" ")" (* ltac2 plugin *) | array_literal (* ltac2 plugin *) | list_literal (* ltac2 plugin *) | "{" test_qualid_with_or_lpar_or_rbrac ltac2_expr0 "with" tac2rec_fieldexprs "}" (* ltac2 plugin *) | "{" tac2rec_fieldexprs "}" (* ltac2 plugin *) | ltac2_atom (* ltac2 plugin *) ] array_literal: [ | test_array_opening "[" "|" LIST0 ltac2_expr5 SEP ";" test_array_closing "|" "]" (* ltac2 plugin *) ] list_literal: [ | "[" LIST0 ltac2_expr5 SEP ";" "]" (* ltac2 plugin *) ] G_LTAC2_branches: [ | (* ltac2 plugin *) | "|" LIST1 branch SEP "|" (* ltac2 plugin *) | LIST1 branch SEP "|" (* ltac2 plugin *) ] branch: [ | atomic_tac2pat "=>" ltac2_expr6 (* ltac2 plugin *) ] rec_flag: [ | "rec" (* ltac2 plugin *) | (* ltac2 plugin *) ] mut_flag: [ | "mutable" (* ltac2 plugin *) | (* ltac2 plugin *) ] ltac2_typevar: [ | "'" Prim.ident (* ltac2 plugin *) ] ltac2_atom: [ | Prim.integer (* ltac2 plugin *) | Prim.string (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) | "@" Prim.ident (* ltac2 plugin *) | "&" identref (* ltac2 plugin *) | "'" Constr.constr (* ltac2 plugin *) | "constr" ":" "(" Constr.lconstr ")" (* ltac2 plugin *) | "open_constr" ":" "(" Constr.lconstr ")" (* ltac2 plugin *) | "preterm" ":" "(" Constr.lconstr ")" (* ltac2 plugin *) | "ident" ":" "(" identref ")" (* ltac2 plugin *) | "pat" ":" "(" Constr.cpattern ")" (* ltac2 plugin *) | "reference" ":" "(" globref ")" (* ltac2 plugin *) | "ltac1" ":" "(" ltac1_expr_in_env ")" (* ltac2_ltac1 plugin *) | "ltac1val" ":" "(" ltac1_expr_in_env ")" (* ltac2_ltac1 plugin *) ] tac2expr_in_env: [ | test_ltac1_env LIST0 identref "|-" ltac2_expr6 (* ltac2 plugin *) | ltac2_expr6 (* ltac2 plugin *) ] type_cast: [ | (* ltac2 plugin *) | ":" ltac2_type5 (* ltac2 plugin *) ] G_LTAC2_let_clause: [ | let_binder type_cast ":=" ltac2_expr6 (* ltac2 plugin *) ] let_binder: [ | LIST1 G_LTAC2_input_fun (* ltac2 plugin *) ] ltac2_type5: [ | ltac2_type2 "->" ltac2_type5 (* ltac2 plugin *) | ltac2_type2 (* ltac2 plugin *) ] ltac2_type2: [ | ltac2_type1 "*" LIST1 ltac2_type1 SEP "*" (* ltac2 plugin *) | ltac2_type1 (* ltac2 plugin *) ] ltac2_type1: [ | ltac2_type1 Prim.qualid (* ltac2 plugin *) | ltac2_type0 (* ltac2 plugin *) ] ltac2_type0: [ | "(" LIST1 ltac2_type5 SEP "," ")" OPT Prim.qualid (* ltac2 plugin *) | ltac2_typevar (* ltac2 plugin *) | "_" (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) ] G_LTAC2_binder: [ | "_" (* ltac2 plugin *) | Prim.ident (* ltac2 plugin *) ] G_LTAC2_input_fun: [ | tac2pat0 (* ltac2 plugin *) ] tac2def_body: [ | G_LTAC2_binder LIST0 G_LTAC2_input_fun type_cast ":=" ltac2_expr6 (* ltac2 plugin *) ] tac2def_val: [ | mut_flag rec_flag LIST1 tac2def_body SEP "with" (* ltac2 plugin *) ] tac2def_mut: [ | "Set" Prim.qualid OPT [ "as" identref ] ":=" ltac2_expr6 (* ltac2 plugin *) ] tac2typ_knd: [ | ltac2_type5 (* ltac2 plugin *) | "[" ".." "]" (* ltac2 plugin *) | "[" tac2alg_constructors "]" (* ltac2 plugin *) | "{" tac2rec_fields "}" (* ltac2 plugin *) ] tac2alg_constructors: [ | "|" LIST1 tac2alg_constructor SEP "|" (* ltac2 plugin *) | LIST0 tac2alg_constructor SEP "|" (* ltac2 plugin *) ] tac2alg_constructor: [ | quoted_attributes Prim.identref (* ltac2 plugin *) | quoted_attributes Prim.identref "(" LIST0 ltac2_type5 SEP "," ")" (* ltac2 plugin *) ] tac2rec_fields: [ | tac2rec_field ";" tac2rec_fields (* ltac2 plugin *) | tac2rec_field ";" (* ltac2 plugin *) | tac2rec_field (* ltac2 plugin *) | (* ltac2 plugin *) ] tac2rec_field: [ | mut_flag Prim.ident ":" ltac2_type5 (* ltac2 plugin *) ] tac2rec_fieldexprs: [ | tac2rec_fieldexpr ";" tac2rec_fieldexprs (* ltac2 plugin *) | tac2rec_fieldexpr ";" (* ltac2 plugin *) | tac2rec_fieldexpr (* ltac2 plugin *) | (* ltac2 plugin *) ] tac2rec_fieldexpr: [ | Prim.qualid OPT [ ":=" ltac2_expr1 ] (* ltac2 plugin *) ] tac2rec_fieldpats: [ | tac2rec_fieldpat ";" tac2rec_fieldpats (* ltac2 plugin *) | tac2rec_fieldpat ";" (* ltac2 plugin *) | tac2rec_fieldpat (* ltac2 plugin *) | (* ltac2 plugin *) ] tac2rec_fieldpat: [ | Prim.qualid OPT [ ":=" tac2pat3 ] (* ltac2 plugin *) ] tac2typ_prm: [ | (* ltac2 plugin *) | ltac2_typevar (* ltac2 plugin *) | "(" LIST1 ltac2_typevar SEP "," ")" (* ltac2 plugin *) ] tac2typ_def: [ | tac2typ_prm Prim.qualid tac2type_body (* ltac2 plugin *) ] tac2type_body: [ | (* ltac2 plugin *) | ":=" tac2typ_knd (* ltac2 plugin *) | "::=" tac2typ_knd (* ltac2 plugin *) ] tac2def_typ: [ | "Type" rec_flag LIST1 tac2typ_def SEP "with" (* ltac2 plugin *) ] tac2def_ext: [ | "@" "external" identref ":" ltac2_type5 ":=" Prim.string Prim.string (* ltac2 plugin *) ] syn_node: [ | "_" (* ltac2 plugin *) | qualid (* ltac2 plugin *) ] ltac2_syntax_class: [ | Prim.string (* ltac2 plugin *) | Prim.integer (* ltac2 plugin *) | syn_node (* ltac2 plugin *) | syn_node "(" LIST1 ltac2_syntax_class SEP "," ")" (* ltac2 plugin *) ] syn_level: [ | (* ltac2 plugin *) | ":" Prim.natural (* ltac2 plugin *) | ":" qualid OPT [ "(" Prim.natural ")" ] (* ltac2 plugin *) ] tac2def_syn: [ | LIST1 ltac2_syntax_class syn_level ":=" ltac2_expr6 (* ltac2 plugin *) ] tac2abbrev_syn: [ | Prim.identref ":=" ltac2_expr6 (* ltac2 plugin *) ] globref: [ | "&" Prim.ident (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) ] anti: [ | "$" Prim.ident (* ltac2 plugin *) ] ident_or_anti: [ | identref (* ltac2 plugin *) | "$" Prim.ident (* ltac2 plugin *) ] lnatural: [ | Prim.natural (* ltac2 plugin *) ] q_ident: [ | ident_or_anti (* ltac2 plugin *) ] qhyp: [ | anti (* ltac2 plugin *) | lnatural (* ltac2 plugin *) | identref (* ltac2 plugin *) ] G_LTAC2_simple_binding: [ | "(" qhyp ":=" Constr.lconstr ")" (* ltac2 plugin *) ] G_LTAC2_bindings: [ | test_lpar_idnum_coloneq LIST1 G_LTAC2_simple_binding (* ltac2 plugin *) | LIST1 Constr.constr (* ltac2 plugin *) ] q_bindings: [ | G_LTAC2_bindings (* ltac2 plugin *) ] q_with_bindings: [ | G_LTAC2_with_bindings (* ltac2 plugin *) ] G_LTAC2_intropatterns: [ | LIST0 nonsimple_intropattern (* ltac2 plugin *) ] G_LTAC2_or_and_intropattern: [ | "[" LIST1 G_LTAC2_intropatterns SEP "|" "]" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | "(" G_LTAC2_simple_intropattern ")" (* ltac2 plugin *) | "(" G_LTAC2_simple_intropattern "," LIST1 G_LTAC2_simple_intropattern SEP "," ")" (* ltac2 plugin *) | "(" G_LTAC2_simple_intropattern "&" LIST1 G_LTAC2_simple_intropattern SEP "&" ")" (* ltac2 plugin *) ] G_LTAC2_equality_intropattern: [ | "->" (* ltac2 plugin *) | "<-" (* ltac2 plugin *) | test_leftsquarebracket_equal "[" "=" G_LTAC2_intropatterns "]" (* ltac2 plugin *) ] G_LTAC2_naming_intropattern: [ | LEFTQMARK identref (* ltac2 plugin *) | "?$" identref (* ltac2 plugin *) | "?" (* ltac2 plugin *) | ident_or_anti (* ltac2 plugin *) ] nonsimple_intropattern: [ | G_LTAC2_simple_intropattern (* ltac2 plugin *) | "*" (* ltac2 plugin *) | "**" (* ltac2 plugin *) ] G_LTAC2_simple_intropattern: [ | G_LTAC2_simple_intropattern_closed LIST0 [ "%" Constr.term0 ] (* ltac2 plugin *) ] G_LTAC2_simple_intropattern_closed: [ | G_LTAC2_equality_intropattern (* ltac2 plugin *) | G_LTAC2_or_and_intropattern (* ltac2 plugin *) | "_" (* ltac2 plugin *) | G_LTAC2_naming_intropattern (* ltac2 plugin *) ] q_intropatterns: [ | G_LTAC2_intropatterns (* ltac2 plugin *) ] q_intropattern: [ | G_LTAC2_simple_intropattern (* ltac2 plugin *) ] nat_or_anti: [ | lnatural (* ltac2 plugin *) | "$" Prim.ident (* ltac2 plugin *) ] G_LTAC2_eqn_ipat: [ | "eqn" ":" G_LTAC2_naming_intropattern (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_with_bindings: [ | "with" G_LTAC2_bindings (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_constr_with_bindings: [ | Constr.constr G_LTAC2_with_bindings (* ltac2 plugin *) ] G_LTAC2_destruction_arg: [ | lnatural (* ltac2 plugin *) | identref (* ltac2 plugin *) | G_LTAC2_constr_with_bindings (* ltac2 plugin *) ] q_destruction_arg: [ | G_LTAC2_destruction_arg (* ltac2 plugin *) ] G_LTAC2_as_or_and_ipat: [ | "as" G_LTAC2_or_and_intropattern (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_occs_nums: [ | LIST1 nat_or_anti (* ltac2 plugin *) | "-" nat_or_anti LIST0 nat_or_anti (* ltac2 plugin *) ] G_LTAC2_occs: [ | "at" G_LTAC2_occs_nums (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_hypident: [ | ident_or_anti (* ltac2 plugin *) | "(" "type" "of" ident_or_anti ")" (* ltac2 plugin *) | "(" "value" "of" ident_or_anti ")" (* ltac2 plugin *) ] G_LTAC2_hypident_occ: [ | G_LTAC2_hypident G_LTAC2_occs (* ltac2 plugin *) ] G_LTAC2_in_clause: [ | "*" G_LTAC2_occs (* ltac2 plugin *) | "*" "|-" G_LTAC2_concl_occ (* ltac2 plugin *) | LIST0 G_LTAC2_hypident_occ SEP "," "|-" G_LTAC2_concl_occ (* ltac2 plugin *) | LIST0 G_LTAC2_hypident_occ SEP "," (* ltac2 plugin *) ] clause: [ | "in" G_LTAC2_in_clause (* ltac2 plugin *) | "at" G_LTAC2_occs_nums (* ltac2 plugin *) ] q_clause: [ | clause (* ltac2 plugin *) ] G_LTAC2_concl_occ: [ | "*" G_LTAC2_occs (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_induction_clause: [ | G_LTAC2_destruction_arg G_LTAC2_as_or_and_ipat G_LTAC2_eqn_ipat OPT clause (* ltac2 plugin *) ] q_induction_clause: [ | G_LTAC2_induction_clause (* ltac2 plugin *) ] G_LTAC2_conversion: [ | Constr.constr (* ltac2 plugin *) | Constr.constr "with" Constr.constr (* ltac2 plugin *) ] q_conversion: [ | G_LTAC2_conversion (* ltac2 plugin *) ] q_orient: [ | "->" (* ltac2 plugin *) | "<-" (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_rewriter: [ | "!" G_LTAC2_constr_with_bindings (* ltac2 plugin *) | [ "?" | LEFTQMARK ] G_LTAC2_constr_with_bindings (* ltac2 plugin *) | lnatural "!" G_LTAC2_constr_with_bindings (* ltac2 plugin *) | lnatural [ "?" | LEFTQMARK ] G_LTAC2_constr_with_bindings (* ltac2 plugin *) | lnatural G_LTAC2_constr_with_bindings (* ltac2 plugin *) | G_LTAC2_constr_with_bindings (* ltac2 plugin *) ] G_LTAC2_oriented_rewriter: [ | q_orient G_LTAC2_rewriter (* ltac2 plugin *) ] q_rewriting: [ | G_LTAC2_oriented_rewriter (* ltac2 plugin *) ] G_LTAC2_tactic_then_last: [ | "|" LIST0 ( OPT ltac2_expr6 ) SEP "|" (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_for_each_goal: [ | ltac2_expr6 "|" G_LTAC2_for_each_goal (* ltac2 plugin *) | ltac2_expr6 ".." G_LTAC2_tactic_then_last (* ltac2 plugin *) | ".." G_LTAC2_tactic_then_last (* ltac2 plugin *) | ltac2_expr6 (* ltac2 plugin *) | "|" G_LTAC2_for_each_goal (* ltac2 plugin *) | (* ltac2 plugin *) ] q_dispatch: [ | G_LTAC2_for_each_goal (* ltac2 plugin *) ] q_occurrences: [ | G_LTAC2_occs (* ltac2 plugin *) ] ltac2_red_flag: [ | "beta" (* ltac2 plugin *) | "iota" (* ltac2 plugin *) | "match" (* ltac2 plugin *) | "fix" (* ltac2 plugin *) | "cofix" (* ltac2 plugin *) | "zeta" (* ltac2 plugin *) | "delta" G_LTAC2_delta_flag (* ltac2 plugin *) | "head" (* ltac2 plugin *) ] refglobal: [ | "&" Prim.ident (* ltac2 plugin *) | Prim.qualid (* ltac2 plugin *) | "$" Prim.ident (* ltac2 plugin *) ] q_reference: [ | refglobal (* ltac2 plugin *) ] refglobals: [ | LIST1 refglobal (* ltac2 plugin *) ] G_LTAC2_delta_flag: [ | "-" "[" refglobals "]" (* ltac2 plugin *) | "[" refglobals "]" (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_strategy_flag: [ | LIST1 ltac2_red_flag (* ltac2 plugin *) | G_LTAC2_delta_flag (* ltac2 plugin *) ] q_strategy_flag: [ | G_LTAC2_strategy_flag (* ltac2 plugin *) ] hintdb: [ | "*" (* ltac2 plugin *) | LIST1 ident_or_anti (* ltac2 plugin *) ] q_hintdb: [ | hintdb (* ltac2 plugin *) ] G_LTAC2_match_pattern: [ | "context" OPT Prim.ident "[" Constr.cpattern "]" (* ltac2 plugin *) | Constr.cpattern (* ltac2 plugin *) ] G_LTAC2_match_rule: [ | G_LTAC2_match_pattern "=>" ltac2_expr6 (* ltac2 plugin *) ] G_LTAC2_match_list: [ | LIST1 G_LTAC2_match_rule SEP "|" (* ltac2 plugin *) | "|" LIST1 G_LTAC2_match_rule SEP "|" (* ltac2 plugin *) ] q_constr_matching: [ | G_LTAC2_match_list (* ltac2 plugin *) ] gmatch_hyp_pattern: [ | Prim.name ":" G_LTAC2_match_pattern (* ltac2 plugin *) | Prim.name ":=" "[" G_LTAC2_match_pattern "]" ":" G_LTAC2_match_pattern (* ltac2 plugin *) | Prim.name ":=" G_LTAC2_match_pattern (* ltac2 plugin *) ] gmatch_pattern: [ | "[" LIST0 gmatch_hyp_pattern SEP "," "|-" G_LTAC2_match_pattern "]" (* ltac2 plugin *) ] gmatch_rule: [ | gmatch_pattern "=>" ltac2_expr6 (* ltac2 plugin *) ] goal_match_list: [ | OPT "|" LIST1 gmatch_rule SEP "|" (* ltac2 plugin *) ] q_goal_matching: [ | goal_match_list (* ltac2 plugin *) ] move_location: [ | "at" "top" (* ltac2 plugin *) | "at" "bottom" (* ltac2 plugin *) | "after" ident_or_anti (* ltac2 plugin *) | "before" ident_or_anti (* ltac2 plugin *) ] q_move_location: [ | move_location (* ltac2 plugin *) ] G_LTAC2_as_name: [ | (* ltac2 plugin *) | "as" ident_or_anti (* ltac2 plugin *) ] pose: [ | test_lpar_id_coloneq "(" ident_or_anti ":=" Constr.lconstr ")" (* ltac2 plugin *) | Constr.constr G_LTAC2_as_name (* ltac2 plugin *) ] q_pose: [ | pose (* ltac2 plugin *) ] G_LTAC2_as_ipat: [ | "as" G_LTAC2_simple_intropattern (* ltac2 plugin *) | (* ltac2 plugin *) ] G_LTAC2_by_tactic: [ | "by" ltac2_expr5 (* ltac2 plugin *) | (* ltac2 plugin *) ] assertion: [ | test_lpar_id_coloneq "(" ident_or_anti ":=" Constr.lconstr ")" (* ltac2 plugin *) | test_lpar_id_colon "(" ident_or_anti ":" Constr.lconstr ")" G_LTAC2_by_tactic (* ltac2 plugin *) | Constr.constr G_LTAC2_as_ipat G_LTAC2_by_tactic (* ltac2 plugin *) ] q_assert: [ | assertion (* ltac2 plugin *) ] ltac2_entry: [ | tac2def_val (* ltac2 plugin *) | tac2def_typ (* ltac2 plugin *) | tac2def_ext (* ltac2 plugin *) | tac2def_mut (* ltac2 plugin *) ] ltac2def_syn: [ | tac2def_syn (* ltac2 plugin *) ] ltac2abbrev_syn: [ | tac2abbrev_syn (* ltac2 plugin *) ] ltac2_expr: [ | _ltac2_expr (* ltac2 plugin *) ] ltac2_selector: [ | toplevel_selector (* ltac2 plugin *) ] ltac2_use_default: [ | "." (* ltac2 plugin *) | "..." (* ltac2 plugin *) ] tac2mode: [ | OPT ltac2_selector ltac2_expr6 ltac2_use_default (* ltac2 plugin *) | "par" ":" ltac2_expr6 "." (* ltac2 plugin *) | subprf (* ltac2 plugin *) | OPT toplevel_selector subprf_with_selector (* ltac2 plugin *) ] test_ltac2_ident: [ | test_ltac2_ident_aux (* ltac2 plugin *) ] ltac1_expr_in_env: [ | test_ltac1_env LIST0 identref "|-" ltac_expr5 (* ltac2_ltac1 plugin *) | ltac_expr5 (* ltac2_ltac1 plugin *) ] rocq-9.2.0/doc/tools/docgram/orderedGrammar000066400000000000000000001703571516144147600207130ustar00rootroot00000000000000(* Defines the order to apply to editedGrammar to get the final grammar for the doc. doc_grammar will modify this file to add/remove nonterminals and productions to match editedGrammar, which will remove comments. Not compiled into Coq *) DOC_GRAMMAR term: [ | term100 ] term100: [ | term_cast | term99 ] term99: [ | term10 ] term10: [ | term_application | term_forall_or_fun | term_let | term_fix | term_cofix | term_if | one_term ] one_term: [ | term_explicit | term1 ] term1: [ | term_projection | term_scope | term0 ] term0: [ | qualid_annotated | sort | number_or_string | term_evar | term_match | term_record | term_generalizing | "[|" LIST0 term SEP ";" "|" term OPT ( ":" type ) "|]" OPT univ_annot | term_ltac | "(" term ")" ] qualid_annotated: [ | qualid OPT univ_annot ] term_ltac: [ | "ltac" ":" "(" ltac_expr ")" ] term_projection: [ | term1 ".(" qualid OPT univ_annot LIST0 arg ")" | term1 ".(" "@" qualid OPT univ_annot LIST0 ( term1 ) ")" ] term_scope: [ | term1 "%" scope_key | term1 "%_" scope_key ] term_evar: [ | "_" | "?[" ident "]" | "?[" "?" ident "]" | "?" ident OPT ( "@{" LIST1 ( ident ":=" term ) SEP ";" "}" ) ] dangling_pattern_extension_rule: [ | "@" "?" ident LIST1 ident ] term_application: [ | term10 LIST1 arg | "@" qualid_annotated LIST1 term1 ] arg: [ | "(" ident ":=" term ")" | "(" natural ":=" term ")" | term1 ] term_explicit: [ | "@" qualid_annotated ] number_or_string: [ | number | string ] assumption_token: [ | [ "Axiom" | "Axioms" ] | [ "Conjecture" | "Conjectures" ] | [ "Parameter" | "Parameters" ] | [ "Hypothesis" | "Hypotheses" ] | [ "Variable" | "Variables" ] ] assumpt: [ | LIST1 ident_decl of_type ] ident_decl: [ | ident OPT univ_decl ] of_type: [ | [ ":" | ":>" ] type ] qualid: [ | ident LIST0 ( "." ident ) ] type: [ | term ] one_type: [ | one_term ] number: [ | OPT "-" decnat OPT ( "." LIST1 [ digit | "_" ] ) OPT ( [ "e" | "E" ] OPT [ "+" | "-" ] decnat ) | OPT "-" hexnat OPT ( "." LIST1 [ hexdigit | "_" ] ) OPT ( [ "p" | "P" ] OPT [ "+" | "-" ] decnat ) ] integer: [ | bigint ] bigint: [ | OPT "-" bignat ] natural: [ | bignat ] bignat: [ | [ decnat | hexnat ] ] decnat: [ | digit LIST0 [ digit | "_" ] ] digit: [ | "0" ".." "9" ] hexnat: [ | [ "0x" | "0X" ] hexdigit LIST0 [ hexdigit | "_" ] ] hexdigit: [ | [ "0" ".." "9" | "a" ".." "f" | "A" ".." "F" ] ] ident: [ | first_letter LIST0 subsequent_letter ] first_letter: [ | [ "a" ".." "z" | "A" ".." "Z" | "_" | unicode_letter ] ] subsequent_letter: [ | [ first_letter | digit | "'" | unicode_id_part ] ] where: [ | "at" "top" | "at" "bottom" | "before" ident | "after" ident ] add_zify: [ | [ "InjTyp" | "BinOp" | "UnOp" | "CstOp" | "BinRel" | "UnOpSpec" | "BinOpSpec" ] (* Micromega plugin *) | [ "PropOp" | "PropBinOp" | "PropUOp" | "Saturate" ] (* Micromega plugin *) ] show_zify: [ | [ "InjTyp" | "BinOp" | "UnOp" | "CstOp" | "BinRel" | "UnOpSpec" | "BinOpSpec" | "Spec" ] (* Micromega plugin *) ] REACHABLE: [ | command | simple_tactic | NOTINRSTS ] NOTINRSTS: [ | command | control_command | simple_tactic | hints_regexp | REACHABLE | NOTINRSTS | l1_tactic | l3_tactic | l2_tactic | value_tactic | ltac2_entry | q_intropatterns | q_intropattern | q_ident | q_destruction_arg | q_with_bindings | q_bindings | q_reductions | q_reference | q_clause | q_occurrences | q_induction_clause | q_conversion | q_rewriting | q_dispatch | q_hintdb | q_move_location | q_pose | q_assert | q_constr_matching | q_goal_matching ] document: [ | LIST0 sentence ] nonterminal: [ ] sentence: [ | OPT attributes command "." | OPT attributes OPT ( natural ":" ) query_command "." | OPT attributes OPT ( toplevel_selector ":" ) ltac_expr [ "." | "..." ] | control_command ] control_command: [ ] query_command: [ ] attributes: [ | LIST0 ( "#[" LIST0 attribute SEP "," "]" ) LIST0 legacy_attr ] attribute: [ | ident OPT attr_value ] attr_value: [ | "=" string | "=" qualid | "(" LIST1 attribute SEP "," ")" ] legacy_attr: [ | [ "Local" | "Global" ] | [ "Polymorphic" | "Monomorphic" ] | [ "Cumulative" | "NonCumulative" ] | "Private" | "Program" ] sort: [ | "Set" | "Prop" | "SProp" | "Type" | "Type" "@{" "_" "}" | "Type" "@{" OPT [ qualid [ "|" | ";" ] ] universe "}" ] universe: [ | "max" "(" LIST1 universe_expr SEP "," ")" | "_" | universe_expr ] universe_expr: [ | universe_name OPT ( "+" natural ) | natural ] universe_name: [ | qualid | "Set" | "Prop" ] univ_annot: [ | "@{" LIST0 univ_level_or_quality OPT [ [ "|" | ";" ] LIST0 univ_level_or_quality ] "}" ] univ_level_or_quality: [ | "0" | "Set" | "SProp" | "Prop" | "Type" | "_" | qualid ] sort_quality_var: [ | "Prop" | "SProp" | "Type" | qualid ] univ_decl: [ | "@{" OPT [ LIST0 ident [ "|" | ";" ] ] LIST0 ident OPT "+" OPT [ "|" LIST0 sort_constraint SEP "," OPT "+" ] "}" ] cumul_univ_decl: [ | "@{" OPT [ LIST0 ident [ "|" | ";" ] ] LIST0 ( OPT [ "+" | "=" | "*" ] ident ) OPT "+" OPT [ "|" LIST0 sort_constraint SEP "," OPT "+" ] "}" ] sort_constraint: [ | universe_name [ "<" | "=" | "<=" ] universe_name | sort_quality_var "->" sort_quality_var ] univ_decl_constraints: [ | "|" LIST0 sort_constraint SEP "," [ "+" | ] "}" | [ "}" | "|}" ] ] term_fix: [ | "let" "fix" fix_decl "in" term | "fix" fix_decl OPT ( LIST1 ( "with" fix_decl ) "for" ident ) ] fix_decl: [ | ident LIST0 binder OPT fixannot OPT ( ":" type ) ":=" term ] fixannot: [ | "{" "struct" ident "}" | "{" "wf" one_term ident "}" | "{" "measure" one_term OPT ident OPT one_term "}" ] term_cofix: [ | "let" "cofix" cofix_body "in" term | "cofix" cofix_body OPT ( LIST1 ( "with" cofix_body ) "for" ident ) ] cofix_body: [ | ident LIST0 binder OPT ( ":" type ) ":=" term ] term_if: [ | "if" term OPT [ OPT [ "as" name ] "return" term100 ] "then" term "else" term ] term_let: [ | "let" name OPT ( ":" type ) ":=" term "in" term | "let" name LIST1 binder OPT ( ":" type ) ":=" term "in" term | destructuring_let ] destructuring_let: [ | "let" "(" LIST0 name SEP "," ")" OPT [ OPT [ "as" name ] "return" term100 ] ":=" term "in" term | "let" "'" pattern OPT [ "in" pattern ] ":=" term OPT ( "return" term100 ) "in" term ] term_forall_or_fun: [ | "forall" open_binders "," type | "fun" open_binders "=>" term ] open_binders: [ | LIST1 name ":" type | LIST1 binder ] name: [ | "_" | ident ] binder: [ | name | "(" LIST1 name ":" type ")" | "(" name OPT ( ":" type ) ":=" term ")" | implicit_binders | generalizing_binder | "(" name ":" type "|" term ")" | "'" pattern0 ] implicit_binders: [ | "{" LIST1 name OPT ( ":" type ) "}" | "[" LIST1 name OPT ( ":" type ) "]" ] generalizing_binder: [ | "`(" LIST1 typeclass_constraint SEP "," ")" | "`{" LIST1 typeclass_constraint SEP "," "}" | "`[" LIST1 typeclass_constraint SEP "," "]" ] typeclass_constraint: [ | OPT "!" term | "{" name "}" ":" OPT "!" term | name ":" OPT "!" term ] term_generalizing: [ | "`{" term "}" | "`(" term ")" ] term_cast: [ | term99 "<:" type | term99 "<<:" type | term99 ":>" type | term99 ":" type ] term_match: [ | "match" LIST1 case_item SEP "," OPT ( "return" term100 ) "with" OPT "|" LIST0 eqn SEP "|" "end" ] case_item: [ | term100 OPT ( "as" name ) OPT [ "in" pattern ] ] eqn: [ | LIST1 [ LIST1 pattern SEP "," ] SEP "|" "=>" term ] pattern: [ | pattern10 ":" term | pattern10 ] pattern10: [ | pattern10 "as" name | pattern10 LIST0 pattern1 | "@" qualid LIST0 pattern1 ] pattern1: [ | pattern1 "%" scope_key | pattern1 "%_" scope_key | pattern0 ] pattern0: [ | qualid | "{|" LIST0 ( qualid ":=" pattern ) "|}" | "_" | "(" LIST1 pattern SEP "|" ")" | number | string ] fix_definition: [ | ident_decl LIST0 binder OPT fixannot OPT ( ":" type ) OPT [ ":=" term ] OPT decl_notations ] thm_token: [ | "Theorem" | "Lemma" | "Fact" | "Remark" | "Corollary" | "Proposition" | "Property" ] def_body: [ | LIST0 binder OPT ( ":" type ) ":=" OPT reduce term | LIST0 binder ":" type ] reduce: [ | "Eval" red_expr "in" ] red_expr: [ | "lazy" OPT reductions | "cbv" OPT reductions | "compute" OPT delta_reductions | "vm_compute" OPT [ reference_occs | pattern_occs ] | "native_compute" OPT [ reference_occs | pattern_occs ] | "red" | "hnf" | "simpl" OPT "head" OPT delta_reductions OPT [ reference_occs | pattern_occs ] | "cbn" OPT reductions | "unfold" LIST1 reference_occs SEP "," | "fold" LIST1 one_term | "pattern" LIST1 pattern_occs SEP "," | ident ] reductions: [ | LIST1 reduction | OPT "head" delta_reductions ] reduction: [ | "head" | "beta" | "delta" OPT delta_reductions | "match" | "fix" | "cofix" | "iota" | "zeta" ] delta_reductions: [ | OPT "-" "[" LIST1 reference "]" ] reference_occs: [ | reference OPT ( "at" occs_nums ) ] pattern_occs: [ | one_term OPT ( "at" occs_nums ) ] record_definition: [ | OPT ">" ident_decl LIST0 binder OPT [ ":" sort ] OPT ( ":=" OPT ident "{" OPT [ LIST1 record_field SEP ";" OPT ";" ] "}" OPT [ "as" ident ] ) ] record_field: [ | LIST0 [ "#[" LIST1 attribute SEP "," "]" ] name OPT field_spec OPT [ "|" natural ] OPT decl_notations ] field_spec: [ | LIST0 binder of_type_inst | LIST0 binder ":=" term | LIST0 binder of_type_inst ":=" term ] of_type_inst: [ | [ ":" | ":>" | "::" | "::>" ] type ] term_record: [ | "{|" OPT [ LIST1 field_val SEP ";" OPT ";" ] "|}" ] field_val: [ | qualid LIST0 binder ":=" term ] inductive_definition: [ | ident OPT cumul_univ_decl LIST0 binder OPT [ "|" LIST0 binder ] OPT [ ":" type ] ":=" OPT [ OPT "|" LIST1 constructor SEP "|" ] OPT decl_notations ] constructor: [ | LIST0 [ "#[" LIST1 attribute SEP "," "]" ] ident LIST0 binder OPT of_type_inst ] import_categories: [ | OPT "-" "(" LIST1 qualid SEP "," ")" ] filtered_import: [ | qualid OPT [ "(" LIST1 ( qualid OPT [ "(" ".." ")" ] ) SEP "," ")" ] ] cofix_definition: [ | ident_decl LIST0 binder OPT ( ":" type ) OPT [ ":=" term ] OPT decl_notations ] rw_pattern: [ | term ] rewrite_rule: [ | OPT [ univ_decl "|-" ] rw_pattern "=>" term ] scheme_kind: [ | scheme_type "for" reference "Sort" sort_quality_or_set ] scheme_type: [ | "Induction" | "Minimality" | "Elimination" | "Case" ] sort_quality_or_set: [ | "Prop" | "SProp" | "Set" | "Type" ] hint_info: [ | "|" OPT natural OPT one_pattern ] one_pattern: [ | one_term ] module_binder: [ | "(" OPT ( [ "Import" | "Export" ] OPT import_categories ) LIST1 ident ":" module_type_inl ")" ] module_type_inl: [ | "!" module_type | module_type OPT functor_app_annot ] functor_app_annot: [ | "[" "inline" "at" "level" natural "]" | "[" "no" "inline" "]" ] module_type: [ | qualid | "(" module_type ")" | module_type module_expr_atom | module_type "with" with_declaration ] with_declaration: [ | "Definition" qualid OPT univ_decl ":=" term | "Module" qualid ":=" qualid ] module_expr_atom: [ | qualid | "(" module_expr_atom ")" ] of_module_type: [ | ":" module_type_inl | LIST0 ( "<:" module_type_inl ) ] module_expr_inl: [ | "!" LIST1 module_expr_atom | LIST1 module_expr_atom OPT functor_app_annot ] reference: [ | qualid | string OPT [ "%" scope_key ] ] arg_specs: [ | argument_spec | "/" | "&" | "(" LIST1 argument_spec ")" LIST0 [ "%" scope | "%_" scope ] | "[" LIST1 argument_spec "]" LIST0 [ "%" scope | "%_" scope ] | "{" LIST1 argument_spec "}" LIST0 [ "%" scope | "%_" scope ] ] argument_spec: [ | OPT "!" name LIST0 [ "%" scope | "%_" scope ] ] implicits_alt: [ | name | "[" LIST1 name "]" | "{" LIST1 name "}" ] args_modifier: [ | "simpl" "nomatch" | "simpl" "never" | "clear" "simpl" | "default" "implicits" | "clear" "implicits" | "clear" "scopes" | "clear" "bidirectionality" "hint" | "rename" | "assert" | "extra" "scopes" | "clear" "scopes" "and" "implicits" | "clear" "implicits" "and" "scopes" ] scope: [ | scope_name | scope_key ] scope_name: [ | ident ] scope_key: [ | ident ] strategy_level: [ | "opaque" | integer | "expand" | "transparent" ] strategy_level_or_var: [ | strategy_level | ident ] reserv_list: [ | LIST1 ( "(" simple_reserv ")" ) | simple_reserv ] simple_reserv: [ | LIST1 ident ":" type ] debug_univ_name: [ | qualid | string ] command: [ | "Goal" type | "Pwd" | "Cd" OPT string | "Load" OPT "Verbose" [ string | ident ] | "Declare" "ML" "Module" LIST1 string | "Locate" reference | "Locate" "Term" reference | "Locate" "Module" qualid | "Info" natural ltac_expr | "Add" "Zify" add_zify qualid (* Micromega plugin *) | "Show" "Zify" show_zify (* Micromega plugin *) | "Locate" "Ltac" qualid | "Locate" "Library" qualid | "Locate" "File" string | "Type" term | "Print" "All" | "Print" "Section" qualid | "Print" "Grammar" LIST0 ident | "Print" "Custom" "Grammar" qualid | "Print" "Keywords" | "Print" "LoadPath" OPT dirpath | "Print" "Libraries" | "Print" "ML" "Path" | "Print" "ML" "Modules" | "Print" "Debug" "GC" | "Print" "Graph" | "Print" "Classes" | "Print" "Typeclasses" | "Print" "Instances" reference | "Print" "Coercions" | "Print" "Notation" string OPT [ "in" "custom" qualid ] | "Print" "Coercion" "Paths" coercion_class coercion_class | "Print" "Canonical" "Projections" LIST0 reference | "Print" "Typing" "Flags" | "Print" "Tables" | "Print" "Options" | "Print" "Hint" OPT [ "*" | reference ] | "Print" "HintDb" ident | "Print" "Scopes" | "Print" "Scope" scope_name | "Print" "Visibility" OPT scope_name | "Print" "Implicit" reference | "Print" OPT "Sorted" "Universes" OPT ( "Subgraph" "(" LIST0 debug_univ_name ")" ) OPT [ [ "With" | "Without" ] "Constraint" "Sources" ] OPT string | "Print" "Sorts" | "Print" "Assumptions" LIST1 reference | "Print" "Opaque" "Dependencies" LIST1 reference | "Print" "Transparent" "Dependencies" LIST1 reference | "Print" "All" "Dependencies" LIST1 reference | "Print" "Strategy" reference | "Print" "Strategies" | "Print" "Registered" | "Print" "Registered" "Schemes" | "Print" OPT "Term" reference OPT univ_name_list | "Print" "Module" "Type" qualid | "Print" "Module" qualid | "Print" "Namespace" dirpath | "Inspect" natural | "Print" "Table" setting_name | "Add" setting_name LIST1 [ qualid | string ] | "Test" setting_name OPT ( "for" LIST1 [ qualid | string ] ) | "Remove" setting_name LIST1 [ qualid | string ] | "Reset" "Initial" | "Reset" ident | "Back" OPT natural | "Debug" [ "On" | "Off" ] | "Declare" "Reduction" ident ":=" red_expr | "Declare" "Custom" "Entry" ident | "Derive" open_binders "SuchThat" type "As" ident | "Derive" open_binders "in" type "as" ident | "Extraction" qualid (* extraction plugin *) | "Recursive" "Extraction" LIST1 qualid (* extraction plugin *) | "Extraction" string LIST1 qualid (* extraction plugin *) | "Extraction" "TestCompile" LIST1 qualid (* extraction plugin *) | "Separate" "Extraction" LIST1 qualid (* extraction plugin *) | "Extraction" "Library" ident (* extraction plugin *) | "Recursive" "Extraction" "Library" ident (* extraction plugin *) | "Extraction" "Language" language (* extraction plugin *) | "Extraction" "Inline" LIST1 qualid (* extraction plugin *) | "Extraction" "NoInline" LIST1 qualid (* extraction plugin *) | "Print" "Extraction" "Inline" (* extraction plugin *) | "Reset" "Extraction" "Inline" (* extraction plugin *) | "Extraction" "Implicit" qualid "[" LIST0 [ ident | integer ] "]" (* extraction plugin *) | "Extraction" "Blacklist" LIST1 ident (* extraction plugin *) | "Print" "Extraction" "Blacklist" (* extraction plugin *) | "Reset" "Extraction" "Blacklist" (* extraction plugin *) | "Extract" "Callback" OPT string qualid (* extraction plugin *) | "Print" "Extraction" "Callback" (* extraction plugin *) | "Reset" "Extraction" "Callback" (* extraction plugin *) | "Print" "Extraction" "Foreign" (* extraction plugin *) | "Extract" "Constant" qualid LIST0 string "=>" [ ident | string ] (* extraction plugin *) | "Extract" "Foreign" "Constant" qualid "=>" string (* extraction plugin *) | "Extract" "Inlined" "Constant" qualid "=>" [ ident | string ] (* extraction plugin *) | "Extract" "Inductive" qualid "=>" [ ident | string ] "[" LIST0 [ ident | string ] "]" OPT string (* extraction plugin *) | "Show" "Extraction" (* extraction plugin *) | "Proof" | "Proof" "Mode" string | "Proof" term | "Abort" OPT "All" | "Admitted" | "Qed" | "Save" ident | "Defined" OPT ident | "Restart" | "Undo" OPT ( OPT "To" natural ) | "Focus" OPT natural | "Unfocus" | "Unfocused" | "Show" OPT [ qualid | natural ] | "Show" "Existentials" | "Show" "Universes" | "Show" "Conjectures" | "Show" "Proof" OPT ( "Diffs" OPT "removed" ) | "Show" "Diffs" ident | "Show" "Intro" | "Show" "Intros" | "Show" "Match" qualid | "Guarded" | "Validate" "Proof" | "Create" "HintDb" ident OPT "discriminated" | "Remove" "Hints" LIST1 qualid OPT ( ":" LIST1 ident ) | "Comments" LIST0 [ one_term | string | natural ] | "Attributes" LIST1 attribute SEP "," | "Declare" "Instance" ident_decl LIST0 binder ":" term OPT hint_info | "Declare" "Scope" scope_name | "Obligation" natural OPT ( "of" ident ) OPT ( "with" generic_tactic ) | "Next" "Obligation" OPT ( "of" ident ) OPT ( "with" generic_tactic ) | "Final" "Obligation" OPT ( "of" ident ) OPT ( "with" generic_tactic ) | "Solve" "Obligations" OPT ( "of" ident ) OPT ( "with" ltac_expr ) | "Solve" "All" "Obligations" OPT ( "with" ltac_expr ) | "Admit" "Obligations" OPT ( "of" ident ) | "Obligation" "Tactic" ":=" generic_tactic | "Show" "Obligation" "Tactic" | "Obligations" OPT ( "of" ident ) | "Preterm" OPT ( "of" ident ) | "Add" "Relation" one_term one_term OPT ( "reflexivity" "proved" "by" one_term ) OPT ( "symmetry" "proved" "by" one_term ) OPT ( "transitivity" "proved" "by" one_term ) "as" ident | "Add" "Parametric" "Relation" LIST0 binder ":" one_term one_term OPT ( "reflexivity" "proved" "by" one_term ) OPT ( "symmetry" "proved" "by" one_term ) OPT ( "transitivity" "proved" "by" one_term ) "as" ident | "Add" "Setoid" one_term one_term one_term "as" ident | "Add" "Parametric" "Setoid" LIST0 binder ":" one_term one_term one_term "as" ident | "Add" "Morphism" one_term ":" ident | "Declare" "Morphism" one_term ":" ident | "Add" "Morphism" one_term "with" "signature" term "as" ident | "Add" "Parametric" "Morphism" LIST0 binder ":" one_term "with" "signature" term "as" ident | "Unshelve" | "Declare" "Equivalent" "Keys" one_term one_term | "Print" "Equivalent" "Keys" | "Optimize" "Proof" | "Optimize" "Heap" | "infoH" ltac_expr | "Reset" "Ltac" "Profile" | "Show" "Ltac" "Profile" OPT [ "CutOff" integer | string ] | "Show" "Lia" "Profile" (* micromega plugin *) | "Add" "Ring" ident ":" one_term OPT ( "(" LIST1 ring_mod SEP "," ")" ) (* ring plugin *) | "Print" "Rings" (* ring plugin *) | "Add" "Field" ident ":" one_term OPT ( "(" LIST1 field_mod SEP "," ")" ) (* ring plugin *) | "Print" "Fields" (* ring plugin *) | "Hint" "Cut" "[" hints_regexp "]" OPT ( ":" LIST1 ident ) | "Typeclasses" "Transparent" LIST1 qualid | "Typeclasses" "Opaque" LIST1 qualid | "Typeclasses" "eauto" ":=" OPT "debug" OPT ( "(" [ "bfs" | "dfs" ] ")" ) OPT natural | "Proof" "with" generic_tactic OPT [ "using" section_var_expr ] | "Proof" "using" section_var_expr OPT [ "with" generic_tactic ] | "Tactic" "Notation" OPT ( "(" "at" "level" natural ")" ) LIST1 ltac_production_item ":=" ltac_expr | "Print" "Rewrite" "HintDb" ident | "Print" "Ltac" qualid | "Ltac" tacdef_body LIST0 ( "with" tacdef_body ) | "Print" "Ltac" "Signatures" | "Print" "Firstorder" "Solver" | "Function" fix_definition LIST0 ( "with" fix_definition ) | "Functional" "Scheme" func_scheme_def LIST0 ( "with" func_scheme_def ) | "Functional" "Case" func_scheme_def (* funind plugin *) | "Generate" "graph" "for" qualid (* funind plugin *) | "Hint" "Rewrite" OPT [ "->" | "<-" ] LIST1 one_term OPT ( "using" generic_tactic ) OPT ( ":" LIST1 ident ) | "Create" "Rewrite" "HintDb" ident | "Derive" "Inversion_clear" ident "with" one_term OPT ( "Sort" sort_quality_or_set ) | "Derive" "Inversion" ident "with" one_term OPT ( "Sort" sort_quality_or_set ) | "Derive" "Dependent" "Inversion" ident "with" one_term "Sort" sort_quality_or_set | "Derive" "Dependent" "Inversion_clear" ident "with" one_term "Sort" sort_quality_or_set | "Declare" "Left" "Step" one_term | "Declare" "Right" "Step" one_term | "Number" "Notation" qualid qualid qualid OPT ( "(" LIST1 number_modifier SEP "," ")" ) ":" scope_name | "String" "Notation" qualid qualid qualid OPT ( "(" number_string_via ")" ) ":" scope_name | "Ltac2" "Import" "Type" qualid "as" ident (* ltac2 plugin *) | "Ltac2" "Custom" "Entry" ident (* ltac2 plugin *) | "Ltac2" "Notation" LIST1 ltac2_syntax_class OPT [ ":" natural | ":" qualid OPT [ "(" natural ")" ] ] ":=" ltac2_expr (* ltac2 plugin *) | "SubClass" ident_decl def_body | thm_token ident_decl LIST0 binder ":" type LIST0 [ "with" ident_decl LIST0 binder ":" type ] | assumption_token OPT ( "Inline" OPT ( "(" natural ")" ) ) [ assumpt | LIST1 ( "(" assumpt ")" ) ] | [ "Definition" | "Example" ] ident_decl def_body | [ "Symbol" | "Symbols" ] [ assumpt | LIST1 ( "(" assumpt ")" ) ] | "Let" ident_decl def_body | "Inductive" inductive_definition LIST0 ( "with" inductive_definition ) | "Inductive" record_definition LIST0 ( "with" record_definition ) | "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) | "Let" "Fixpoint" fix_definition LIST0 ( "with" fix_definition ) | "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) | "Let" "CoFixpoint" cofix_definition LIST0 ( "with" cofix_definition ) | "Scheme" "All" "for" reference OPT [ "over" LIST1 ident SEP "," ] | "Scheme" OPT ( ident ":=" ) scheme_kind LIST0 ( "with" OPT ( ident ":=" ) scheme_kind ) | "Scheme" "Rewriting" "for" reference | "Scheme" OPT "Boolean" "Equality" "for" reference | "Combined" "Scheme" ident "from" LIST1 ident SEP "," | "Register" qualid "as" qualid | "Register" "Scheme" qualid "as" qualid "for" qualid | "Register" "Inline" qualid | "Primitive" ident_decl OPT [ ":" term ] ":=" "#" ident | "Universe" LIST1 ident | "Universes" LIST1 ident | "Sort" LIST1 ident | "Sorts" LIST1 ident | "Constraint" LIST1 sort_constraint SEP "," | "Rewrite" [ "Rule" | "Rules" ] ident ":=" OPT "|" LIST1 rewrite_rule SEP "|" | "CoInductive" inductive_definition LIST0 ( "with" inductive_definition ) | "CoInductive" record_definition LIST0 ( "with" record_definition ) | "Variant" ident_decl LIST0 binder OPT [ "|" LIST0 binder ] OPT [ ":" type ] ":=" OPT [ OPT "|" LIST1 constructor SEP "|" ] OPT decl_notations | [ "Record" | "Structure" ] record_definition | "Class" record_definition | "Class" ident_decl LIST0 binder OPT [ ":" sort ] ":=" constructor | "Module" OPT ( [ "Import" | "Export" ] OPT import_categories ) ident LIST0 module_binder OPT of_module_type OPT ( ":=" LIST1 module_expr_inl SEP "<+" ) | "Module" "Type" ident LIST0 module_binder LIST0 ( "<:" module_type_inl ) OPT ( ":=" LIST1 module_type_inl SEP "<+" ) | "Declare" "Module" OPT ( [ "Import" | "Export" ] OPT import_categories ) ident LIST0 module_binder ":" module_type_inl | "Section" ident | "End" ident | "Collection" ident ":=" section_var_expr | "From" dirpath "Extra" "Dependency" string OPT [ "as" ident ] | OPT [ "From" dirpath ] "Require" OPT ( [ "Import" | "Export" ] OPT import_categories ) LIST1 filtered_import | "Import" OPT import_categories LIST1 filtered_import | "Export" OPT import_categories LIST1 filtered_import | "Include" module_type_inl LIST0 ( "<+" module_type_inl ) | "Include" "Type" LIST1 module_type_inl SEP "<+" | "Transparent" OPT "!" LIST1 reference | "Opaque" OPT "!" LIST1 reference | "Strategy" LIST1 [ strategy_level "[" LIST1 reference "]" ] | "Canonical" OPT "Structure" ident_decl def_body | "Canonical" OPT "Structure" reference | "Coercion" ident_decl def_body | "Identity" "Coercion" ident ":" coercion_class ">->" coercion_class | "Coercion" reference OPT [ ":" coercion_class ">->" coercion_class ] | "Context" LIST1 binder | "Instance" OPT ( ident_decl LIST0 binder ) ":" type OPT hint_info OPT [ ":=" "{" LIST0 field_val "}" | ":=" term ] | "Existing" "Instance" qualid OPT hint_info | "Existing" "Instances" LIST1 qualid OPT [ "|" natural ] | "Existing" "Class" qualid | "Arguments" reference LIST0 arg_specs LIST0 [ "," LIST0 implicits_alt ] OPT [ ":" LIST1 args_modifier SEP "," ] | "Implicit" [ "Type" | "Types" ] reserv_list | "Generalizable" [ [ "Variable" | "Variables" ] LIST1 ident | "All" "Variables" | "No" "Variables" ] | "Set" setting_name OPT [ integer | string ] | "Unset" setting_name | "Open" "Scope" scope | "Close" "Scope" scope | "Delimit" "Scope" scope_name "with" scope_key | "Undelimit" "Scope" scope_name | "Bind" "Scope" scope_name "with" LIST1 coercion_class | "Infix" notation_declaration | "Notation" ident LIST0 ident ":=" one_term OPT ( "(" LIST1 syntax_modifier SEP "," ")" ) | "Abbreviation" ident LIST0 ident ":=" one_term OPT ( "(" LIST1 syntax_modifier SEP "," ")" ) | "Notation" notation_declaration | "Reserved" "Infix" string OPT ( "(" LIST1 syntax_modifier SEP "," ")" ) | "Reserved" "Notation" string OPT ( "(" LIST1 syntax_modifier SEP "," ")" ) | [ "Enable" | "Disable" ] "Notation" OPT [ string | qualid LIST0 ident ] OPT ( ":=" one_term ) OPT ( "(" LIST1 enable_notation_flag SEP "," ")" ) OPT [ ":" scope_name | ":" "no" "scope" ] | "Eval" red_expr "in" term | "Compute" term | "Check" term | "About" reference OPT univ_name_list | "SearchPattern" one_pattern OPT ( [ "inside" | "in" | "outside" ] LIST1 qualid ) | "SearchRewrite" one_pattern OPT ( [ "inside" | "in" | "outside" ] LIST1 qualid ) | "Search" LIST1 ( search_query ) OPT ( [ "inside" | "in" | "outside" ] LIST1 qualid ) | "Ltac2" OPT "mutable" OPT "rec" tac2def_body LIST0 ( "with" tac2def_body ) | "Ltac2" "Type" OPT "rec" tac2typ_def LIST0 ( "with" tac2typ_def ) | "Ltac2" "@" "external" ident ":" ltac2_type ":=" string string | "Ltac2" "Abbreviation" ident ":=" ltac2_expr (* ltac2 plugin *) | "Ltac2" "Set" qualid OPT [ "as" ident ] ":=" ltac2_expr | "Ltac2" "Eval" ltac2_expr (* ltac2 plugin *) | "Print" "Ltac2" qualid (* ltac2 plugin *) | "Print" "Ltac2" "Type" qualid (* ltac2 plugin *) | "Locate" "Ltac2" qualid (* ltac2 plugin *) | "Print" "Ltac2" "Signatures" (* ltac2 plugin *) | "Ltac2" "Check" ltac2_expr (* ltac2 plugin *) | "Ltac2" "Globalize" ltac2_expr (* ltac2 plugin *) | "Hint" "Resolve" LIST1 [ qualid | one_term ] OPT hint_info OPT ( ":" LIST1 ident ) | "Hint" "Resolve" [ "->" | "<-" ] LIST1 qualid OPT natural OPT ( ":" LIST1 ident ) | "Hint" "Immediate" LIST1 [ qualid | one_term ] OPT ( ":" LIST1 ident ) | "Hint" [ "Constants" | "Projections" | "Variables" ] [ "Transparent" | "Opaque" ] OPT ( ":" LIST1 ident ) | "Hint" [ "Transparent" | "Opaque" ] LIST1 qualid OPT ( ":" LIST1 ident ) | "Hint" "Mode" qualid LIST1 [ "+" | "!" | "-" ] OPT ( ":" LIST1 ident ) | "Hint" "Unfold" LIST1 qualid OPT ( ":" LIST1 ident ) | "Hint" "Constructors" LIST1 qualid OPT ( ":" LIST1 ident ) | "Hint" "Extern" natural OPT one_pattern "=>" generic_tactic OPT ( ":" LIST1 ident ) | "Time" sentence | "Instructions" sentence | "Profile" OPT string sentence | "Redirect" string sentence | "Timeout" natural sentence | "Fail" sentence | "Succeed" sentence | "Drop" | "Quit" | "BackTo" natural | "Show" "Goal" natural "at" natural ] section_var_expr: [ | LIST0 starred_ident_ref | OPT "-" section_var_expr50 ] section_var_expr50: [ | section_var_expr0 "-" section_var_expr0 | section_var_expr0 "+" section_var_expr0 | section_var_expr0 ] section_var_expr0: [ | starred_ident_ref | "()" | "(" section_var_expr ")" OPT "*" ] starred_ident_ref: [ | ident OPT "*" | "Type" OPT "*" | "All" ] dirpath: [ | LIST0 ( ident "." ) ident ] setting_name: [ | LIST1 ident ] search_query: [ | search_item | "-" search_query | "[" LIST1 ( LIST1 search_query ) SEP "|" "]" ] search_item: [ | OPT ( [ "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] ":" ) string OPT ( "%" scope_key ) | OPT ( [ "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] ":" ) one_pattern | "is" ":" logical_kind ] logical_kind: [ | [ thm_token | assumption_token ] | [ "Definition" | "Example" | "Context" | "Primitive" | "Symbol" ] | [ "Coercion" | "Instance" | "Scheme" | "Canonical" | "SubClass" ] | [ "Fixpoint" | "CoFixpoint" | "Field" | "Method" ] ] univ_name_list: [ | "@{" LIST0 name "}" ] enable_notation_flag: [ | "all" | "only" "parsing" | "only" "printing" | "in" "custom" qualid | "in" "constr" ] tacdef_body: [ | qualid LIST0 name [ ":=" | "::=" ] ltac_expr ] ltac_production_item: [ | string | ident OPT ( "(" ident OPT ( "," string ) ")" ) ] ltac2_type: [ | ltac2_type2 "->" ltac2_type (* ltac2 plugin *) | ltac2_type2 (* ltac2 plugin *) ] ltac2_type2: [ | ltac2_type1 "*" LIST1 ltac2_type1 SEP "*" (* ltac2 plugin *) | ltac2_type1 (* ltac2 plugin *) ] ltac2_type1: [ | ltac2_type1 qualid (* ltac2 plugin *) | ltac2_type0 (* ltac2 plugin *) ] ltac2_type0: [ | "(" LIST1 ltac2_type SEP "," ")" OPT qualid (* ltac2 plugin *) | ltac2_typevar (* ltac2 plugin *) | "_" (* ltac2 plugin *) | qualid (* ltac2 plugin *) ] ltac2_typevar: [ | "'" ident (* ltac2 plugin *) ] occurrences: [ | "at" occs_nums | "in" goal_occurrences ] simple_occurrences: [ | occurrences ] occs_nums: [ | OPT "-" LIST1 nat_or_var ] nat_or_var: [ | [ natural | ident ] ] goal_occurrences: [ | LIST1 hyp_occs SEP "," OPT ( "|-" OPT concl_occs ) | "*" "|-" OPT concl_occs | "|-" OPT concl_occs | OPT concl_occs ] hyp_occs: [ | hypident OPT ( "at" occs_nums ) ] hypident: [ | ident | "(" "type" "of" ident ")" | "(" "value" "of" ident ")" ] concl_occs: [ | "*" OPT ( "at" occs_nums ) ] q_intropatterns: [ | ltac2_intropatterns (* ltac2 plugin *) ] ltac2_intropatterns: [ | LIST0 nonsimple_intropattern (* ltac2 plugin *) ] nonsimple_intropattern: [ | "*" (* ltac2 plugin *) | "**" (* ltac2 plugin *) | ltac2_simple_intropattern (* ltac2 plugin *) ] q_intropattern: [ | ltac2_simple_intropattern (* ltac2 plugin *) ] ltac2_simple_intropattern: [ | ltac2_simple_intropattern_closed LIST0 [ "%" term0 ] (* ltac2 plugin *) ] ltac2_simple_intropattern_closed: [ | ltac2_or_and_intropattern (* ltac2 plugin *) | ltac2_equality_intropattern (* ltac2 plugin *) | "_" (* ltac2 plugin *) | ltac2_naming_intropattern (* ltac2 plugin *) ] ltac2_naming_intropattern: [ | "?" ident (* ltac2 plugin *) | "?$" ident (* ltac2 plugin *) | "?" (* ltac2 plugin *) | ident_or_anti (* ltac2 plugin *) ] ltac2_or_and_intropattern: [ | "[" LIST1 ltac2_intropatterns SEP "|" "]" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | "(" LIST1 ltac2_simple_intropattern SEP "," ")" (* Ltac2 plugin *) | "(" LIST1 ltac2_simple_intropattern SEP "&" ")" (* Ltac2 plugin *) ] ltac2_equality_intropattern: [ | "->" (* ltac2 plugin *) | "<-" (* ltac2 plugin *) | "[=" ltac2_intropatterns "]" ] q_ident: [ | ident_or_anti (* ltac2 plugin *) ] ident_or_anti: [ | ident | "$" ident (* ltac2 plugin *) ] q_destruction_arg: [ | ltac2_destruction_arg (* ltac2 plugin *) ] ltac2_destruction_arg: [ | natural (* ltac2 plugin *) | ident | ltac2_constr_with_bindings (* ltac2 plugin *) ] ltac2_constr_with_bindings: [ | term OPT ( "with" ltac2_bindings ) (* ltac2 plugin *) ] q_bindings: [ | ltac2_bindings (* ltac2 plugin *) ] q_with_bindings: [ | OPT ( "with" ltac2_bindings ) (* ltac2 plugin *) ] ltac2_bindings: [ | LIST1 ltac2_simple_binding (* ltac2 plugin *) | LIST1 term (* ltac2 plugin *) ] ltac2_simple_binding: [ | "(" qhyp ":=" term ")" (* ltac2 plugin *) ] qhyp: [ | "$" ident (* ltac2 plugin *) | natural (* ltac2 plugin *) | ident ] language: [ | "OCaml" (* extraction plugin *) | "Haskell" (* extraction plugin *) | "Scheme" (* extraction plugin *) | "JSON" (* extraction plugin *) ] ring_mod: [ | "decidable" one_term (* ring plugin *) | "abstract" (* ring plugin *) | "morphism" one_term (* ring plugin *) | "constants" "[" ltac_expr "]" (* ring plugin *) | "preprocess" "[" ltac_expr "]" (* ring plugin *) | "postprocess" "[" ltac_expr "]" (* ring plugin *) | "setoid" one_term one_term (* ring plugin *) | "sign" one_term (* ring plugin *) | "power" one_term "[" LIST1 qualid "]" (* ring plugin *) | "power_tac" one_term "[" ltac_expr "]" (* ring plugin *) | "div" one_term (* ring plugin *) | "closed" "[" LIST1 qualid "]" (* ring plugin *) ] field_mod: [ | ring_mod (* ring plugin *) | "completeness" one_term (* ring plugin *) ] number_modifier: [ | "warning" "after" bignat | "abstract" "after" bignat | number_string_via ] number_string_via: [ | "via" qualid "mapping" "[" LIST1 [ qualid "=>" qualid | "[" qualid "]" "=>" qualid ] SEP "," "]" ] hints_regexp: [ | hints_path1 ] hints_path1: [ | hints_path1 "*" | hints_path1 "|" hints_path0 | hints_path1 hints_path0 | hints_path0 ] hints_path0: [ | "(" hints_path1 ")" | "emp" | "eps" | LIST1 qualid | "_" ] coercion_class: [ | "Funclass" | "Sortclass" | reference ] syntax_modifier: [ | "at" "level" natural | "in" "custom" qualid OPT ( "at" "level" natural ) | LIST1 ident SEP "," [ "at" level | "in" "scope" ident ] | ident "at" level OPT binder_interp | ident explicit_subentry | ident binder_interp | "left" "associativity" | "right" "associativity" | "no" "associativity" | "only" "parsing" | "format" string | "only" "printing" ] explicit_subentry: [ | "ident" | "name" | "global" | "bigint" | "strict" "pattern" OPT ( "at" "level" natural ) | "binder" | "closed" "binder" | "constr" OPT ( "at" level ) OPT binder_interp | "custom" qualid OPT ( "at" level ) OPT binder_interp | "pattern" OPT ( "at" "level" natural ) ] binder_interp: [ | "as" "ident" | "as" "name" | "as" "pattern" | "as" "strict" "pattern" ] level: [ | "level" natural | "next" "level" ] decl_notations: [ | "where" notation_declaration LIST0 ( "and" notation_declaration ) ] notation_declaration: [ | string ":=" one_term OPT ( "(" LIST1 syntax_modifier SEP "," ")" ) OPT [ ":" scope_name ] ] simple_tactic: [ | "reflexivity" | "exact" one_term | "assumption" | "etransitivity" | "cut" one_type | "exact_no_check" one_term | "vm_cast_no_check" one_term | "native_cast_no_check" one_term | "lapply" one_term | "transitivity" one_term | "left" OPT ( "with" bindings ) | "eleft" OPT ( "with" bindings ) | "right" OPT ( "with" bindings ) | "eright" OPT ( "with" bindings ) | "constructor" OPT nat_or_var OPT ( "with" bindings ) | "econstructor" OPT ( nat_or_var OPT ( "with" bindings ) ) | "specialize" one_term_with_bindings OPT as_ipat | "symmetry" OPT simple_occurrences | "split" OPT ( "with" bindings ) | "esplit" OPT ( "with" bindings ) | "exists" LIST0 bindings SEP "," | "eexists" LIST0 bindings SEP "," | "intros" "until" [ ident | natural ] | "intro" OPT ident OPT where | "move" ident where | "rename" LIST1 ( ident "into" ident ) SEP "," | "revert" LIST1 ident | "simple" "induction" [ ident | natural ] | "simple" "destruct" [ ident | natural ] | "admit" | "clear" OPT ( OPT "-" LIST1 ident ) | "clearbody" LIST1 ident | "simplify_eq" OPT induction_arg | "esimplify_eq" OPT induction_arg | "discriminate" OPT induction_arg | "ediscriminate" OPT induction_arg | "injection" OPT induction_arg OPT ( "as" LIST0 simple_intropattern ) | "einjection" OPT induction_arg OPT ( "as" LIST0 simple_intropattern ) | "simple" "injection" OPT induction_arg | "replace" OPT [ "->" | "<-" ] one_term OPT occurrences | "replace" OPT [ "->" | "<-" ] one_term "with" one_term OPT occurrences OPT ( "by" ltac_expr3 ) | "typeclasses" "eauto" OPT [ "bfs" | "dfs" | "best_effort" ] OPT nat_or_var OPT ( "with" LIST1 ident ) | "setoid_replace" one_term "with" one_term OPT ( "using" "relation" one_term ) OPT ( "in" ident ) OPT ( "at" LIST1 int_or_var ) OPT ( "by" ltac_expr3 ) | OPT ( [ natural | "[" qualid "]" ] ":" ) "{" | [ LIST1 "-" | LIST1 "+" | LIST1 "*" ] | "}" | "try" ltac_expr3 | "do" nat_or_var ltac_expr3 | "timeout" nat_or_var ltac_expr3 | "time" OPT string ltac_expr3 | "repeat" ltac_expr3 | "progress" ltac_expr3 | "once" ltac_expr3 | "exactly_once" ltac_expr3 | "abstract" ltac_expr2 OPT ( "using" ident ) | "only" goal_selector ":" ltac_expr3 | "tryif" ltac_expr "then" ltac_expr "else" ltac_expr2 | "first" "[" LIST0 ltac_expr SEP "|" "]" | "first" ident | "solve" "[" LIST0 ltac_expr SEP "|" "]" | "solve" ident | "idtac" LIST0 [ ident | string | natural ] | [ "fail" | "gfail" ] OPT nat_or_var LIST0 [ ident | string | natural ] | "eval" red_expr "in" term | "context" ident "[" term "]" | "type" "of" term | "fresh" LIST0 [ string | qualid ] | "type_term" one_term | "numgoals" | "fun" LIST1 name "=>" ltac_expr | "let" OPT "rec" let_clause LIST0 ( "with" let_clause ) "in" ltac_expr | ltac_expr4 ";" ltac_expr3 | ltac_expr4 ";" "[" for_each_goal "]" | ltac_expr1 "+" ltac_expr2 | ltac_expr1 "||" ltac_expr2 | "[>" for_each_goal "]" | toplevel_selector ":" ltac_expr | ltac2_match_key ltac2_expr "with" ltac2_match_list "end" | ltac2_match_key OPT "reverse" "goal" "with" goal_match_list "end" | "case_eq" one_term | "dependent" "rewrite" OPT [ "->" | "<-" ] one_term OPT ( "in" ident ) | "decompose" "sum" one_term | "decompose" "record" one_term | "absurd" one_type | "contradiction" OPT one_term_with_bindings | "autorewrite" OPT "*" "with" LIST1 ident OPT occurrences OPT ( "using" ltac_expr ) | "rewrite" "*" OPT [ "->" | "<-" ] one_term OPT ( "in" ident ) OPT ( "at" rewrite_occs ) OPT ( "by" ltac_expr3 ) | "rewrite" "*" OPT [ "->" | "<-" ] one_term "at" rewrite_occs "in" ident OPT ( "by" ltac_expr3 ) | OPT "simple" OPT "notypeclasses" "refine" one_term | "solve_constraints" | "subst" LIST0 ident | "simple" "subst" | "evar" "(" ident ":" type ")" | "evar" one_type | "instantiate" "(" ident ":=" term ")" | "instantiate" "(" natural ":=" term ")" OPT hloc | "stepl" one_term OPT ( "by" ltac_expr ) | "stepr" one_term OPT ( "by" ltac_expr ) | "generalize_eqs" ident | "dependent" "generalize_eqs" ident | "generalize_eqs_vars" ident | "dependent" "generalize_eqs_vars" ident | "specialize_eqs" ident | "transparent_abstract" ltac_expr3 OPT ( "using" ident ) | "constr_eq" one_term one_term | "constr_eq_strict" one_term one_term | "constr_eq_nounivs" one_term one_term | "is_evar" one_term | "has_evar" one_term | "is_var" one_term | "is_fix" one_term | "is_cofix" one_term | "is_ind" one_term | "is_constructor" one_term | "is_proj" one_term | "is_const" one_term | "shelve" | "shelve_unifiable" | "unshelve" ltac_expr1 | "give_up" | "cycle" int_or_var | "swap" int_or_var int_or_var | "revgoals" | "guard" int_or_var comparison int_or_var | "decompose" "[" LIST1 one_term "]" one_term | "optimize_heap" | "with_strategy" strategy_level_or_var "[" LIST1 reference "]" ltac_expr3 | "start" "ltac" "profiling" | "stop" "ltac" "profiling" | "reset" "ltac" "profile" | "show" "ltac" "profile" OPT [ "cutoff" integer | string ] | "restart_timer" OPT string | "finish_timing" OPT ( "(" string ")" ) OPT string | "eassumption" | "eexact" one_term | "trivial" OPT auto_using OPT hintbases | "info_trivial" OPT auto_using OPT hintbases | "debug" "trivial" OPT auto_using OPT hintbases | "auto" OPT nat_or_var OPT auto_using OPT hintbases | "info_auto" OPT nat_or_var OPT auto_using OPT hintbases | "debug" "auto" OPT nat_or_var OPT auto_using OPT hintbases | "eauto" OPT nat_or_var OPT auto_using OPT hintbases | "debug" "eauto" OPT nat_or_var OPT auto_using OPT hintbases | "info_eauto" OPT nat_or_var OPT auto_using OPT hintbases | "autounfold" OPT hintbases OPT simple_occurrences | "autounfold_one" OPT hintbases OPT ( "in" ident ) | "unify" one_term one_term OPT ( "with" ident ) | "convert" one_term one_term | "not_evar" one_term | "is_ground" one_term | "autoapply" one_term "with" ident | "rewrite_strat" rewstrategy OPT ( "in" ident ) | "rewrite_db" ident OPT ( "in" ident ) | "substitute" OPT [ "->" | "<-" ] one_term_with_bindings | "setoid_rewrite" OPT [ "->" | "<-" ] one_term_with_bindings OPT ( "at" rewrite_occs ) OPT ( "in" ident ) | "setoid_rewrite" OPT [ "->" | "<-" ] one_term_with_bindings "in" ident "at" rewrite_occs | "setoid_symmetry" OPT ( "in" ident ) | "setoid_reflexivity" | "setoid_transitivity" one_term | "setoid_etransitivity" | "intros" LIST0 intropattern | "eintros" LIST0 intropattern | "decide" "equality" | "compare" one_term one_term | "apply" LIST1 one_term_with_bindings SEP "," OPT in_hyp_as | "eapply" LIST1 one_term_with_bindings SEP "," OPT in_hyp_as | "simple" "apply" LIST1 one_term_with_bindings SEP "," OPT in_hyp_as | "simple" "eapply" LIST1 one_term_with_bindings SEP "," OPT in_hyp_as | "elim" one_term_with_bindings OPT ( "using" one_term_with_bindings ) | "eelim" one_term_with_bindings OPT ( "using" one_term_with_bindings ) | "case" LIST1 induction_clause SEP "," OPT induction_principle | "ecase" LIST1 induction_clause SEP "," OPT induction_principle | "fix" ident natural OPT ( "with" LIST1 ( "(" ident LIST0 simple_binder OPT ( "{" "struct" name "}" ) ":" type ")" ) ) | "cofix" ident OPT ( "with" LIST1 ( "(" ident LIST0 simple_binder ":" type ")" ) ) | "pose" alias_definition | "pose" one_term OPT as_name | "epose" alias_definition | "epose" one_term OPT as_name | "pose" "proof" "(" ident ":=" term ")" | "pose" "proof" term OPT as_ipat | "epose" "proof" "(" ident ":=" term ")" | "epose" "proof" term OPT as_ipat | "set" alias_definition OPT occurrences | "set" one_term OPT as_name OPT occurrences | "eset" alias_definition OPT occurrences | "eset" one_term OPT as_name OPT occurrences | "remember" one_term OPT as_name OPT ( "eqn" ":" naming_intropattern ) OPT ( "in" goal_occurrences ) | "eremember" one_term OPT as_name OPT ( "eqn" ":" naming_intropattern ) OPT ( "in" goal_occurrences ) | "assert" "(" ident ":" type ")" OPT ( "by" ltac_expr3 ) | "assert" "(" ident ":=" term ")" | "assert" one_type OPT as_ipat OPT ( "by" ltac_expr3 ) | "eassert" "(" ident ":" type ")" OPT ( "by" ltac_expr3 ) | "eassert" "(" ident ":=" term ")" | "eassert" one_type OPT as_ipat OPT ( "by" ltac_expr3 ) | "enough" "(" ident ":" type ")" OPT ( "by" ltac_expr3 ) | "eenough" "(" ident ":" type ")" OPT ( "by" ltac_expr3 ) | "enough" one_type OPT as_ipat OPT ( "by" ltac_expr3 ) | "eenough" one_type OPT as_ipat OPT ( "by" ltac_expr3 ) | "generalize" "dependent" one_term | "generalize" LIST1 one_term | "generalize" LIST1 [ pattern_occs OPT as_name ] SEP "," | "induction" LIST1 induction_clause SEP "," OPT induction_principle | "einduction" LIST1 induction_clause SEP "," OPT induction_principle | "destruct" LIST1 induction_clause SEP "," OPT induction_principle | "edestruct" LIST1 induction_clause SEP "," OPT induction_principle | "rewrite" LIST1 oriented_rewriter SEP "," OPT occurrences OPT ( "by" ltac_expr3 ) | "erewrite" LIST1 oriented_rewriter SEP "," OPT occurrences OPT ( "by" ltac_expr3 ) | "simple" "inversion" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT ( "in" LIST1 ident ) | "inversion" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT ( "in" LIST1 ident ) | "inversion_clear" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT ( "in" LIST1 ident ) | "inversion" [ ident | natural ] "using" one_term OPT ( "in" LIST1 ident ) | "red" simple_occurrences | "hnf" simple_occurrences | "simpl" OPT "head" OPT delta_reductions OPT [ reference_occs | pattern_occs ] simple_occurrences | "cbv" OPT reductions simple_occurrences | "cbn" OPT reductions simple_occurrences | "lazy" OPT reductions simple_occurrences | "compute" OPT delta_reductions simple_occurrences | "vm_compute" OPT [ reference_occs | pattern_occs ] OPT occurrences | "native_compute" OPT [ reference_occs | pattern_occs ] OPT occurrences | "unfold" LIST1 reference_occs SEP "," OPT occurrences | "fold" LIST1 one_term simple_occurrences | "pattern" LIST1 pattern_occs SEP "," OPT occurrences | "change" OPT ( one_term OPT ( "at" occs_nums ) "with" ) one_term OPT occurrences | "change_no_check" OPT ( one_term OPT ( "at" occs_nums ) "with" ) one_term OPT occurrences | "btauto" | "rtauto" | "congruence" OPT natural OPT ( "with" LIST1 one_term ) | "simple" "congruence" OPT natural OPT ( "with" LIST1 one_term ) | "f_equal" | "firstorder" OPT ltac_expr OPT ( "using" LIST1 qualid SEP "," ) OPT ( "with" LIST1 ident ) | "functional" "inversion" [ ident | natural ] OPT qualid (* funind plugin *) | "functional" "induction" term OPT ( "using" one_term_with_bindings ) OPT ( "as" simple_intropattern ) (* funind plugin *) | "soft" "functional" "induction" LIST1 one_term OPT ( "using" one_term_with_bindings ) OPT ( "as" simple_intropattern ) (* funind plugin *) | "xlra_Q" ltac_expr (* micromega plugin *) | "wlra_Q" ident one_term (* micromega plugin *) | "xlra_R" ltac_expr (* micromega plugin *) | "xlia" ltac_expr (* micromega plugin *) | "wlia" ident one_term (* micromega plugin *) | "xnra_Q" ltac_expr (* micromega plugin *) | "wnra_Q" ident one_term (* micromega plugin *) | "xnra_R" ltac_expr (* micromega plugin *) | "xnia" ltac_expr (* micromega plugin *) | "wnia" ident one_term (* micromega plugin *) | "xsos_Z" ltac_expr (* micromega plugin *) | "wsos_Z" ident one_term (* micromega plugin *) | "xsos_Q" ltac_expr (* micromega plugin *) | "wsos_Q" ident one_term (* micromega plugin *) | "xsos_R" ltac_expr (* micromega plugin *) | "xpsatz_Z" nat_or_var ltac_expr (* micromega plugin *) | "wpsatz_Z" nat_or_var ident one_term (* micromega plugin *) | "xpsatz_Q" nat_or_var ltac_expr (* micromega plugin *) | "wpsatz_Q" nat_or_var ident one_term (* micromega plugin *) | "xpsatz_R" nat_or_var ltac_expr (* micromega plugin *) | "zify_iter_specs" (* micromega plugin *) | "zify_op" (* micromega plugin *) | "zify_saturate" (* micromega plugin *) | "zify_iter_let" ltac_expr (* micromega plugin *) | "zify_elim_let" (* micromega plugin *) | "nsatz_compute" one_term (* nsatz plugin *) | "protect_fv" string OPT ( "in" ident ) | "ring_lookup" ltac_expr0 "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *) | "field_lookup" ltac_expr "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *) | "ring_lookup" ltac_expr0 "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *) | "field_lookup" ltac_expr "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *) | match_key OPT "reverse" "goal" "with" OPT "|" LIST1 ( goal_pattern "=>" ltac_expr ) SEP "|" "end" | match_key ltac_expr "with" OPT "|" LIST1 ( match_pattern "=>" ltac_expr ) SEP "|" "end" | "dependent" "inversion" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT [ "with" one_term ] | "dependent" "simple" "inversion" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT [ "with" one_term ] | "dependent" "inversion_clear" [ ident | natural ] OPT ( "as" or_and_intropattern ) OPT [ "with" one_term ] | "classical_left" | "classical_right" | "contradict" ident | "dintuition" OPT ltac_expr | "dtauto" | "easy" | "exfalso" | "inversion_sigma" OPT ( ident OPT ( "as" simple_intropattern ) ) | "lia" | "lra" | "nia" | "now_show" one_type | "nra" | "rapply" one_term | "tauto" | "time_constr" ltac_expr | "zify" | "assert_fails" ltac_expr3 | "assert_succeeds" ltac_expr3 | "clear" "dependent" ident | "decide" one_term "with" one_term | "dependent" "destruction" ident OPT ( "generalizing" LIST1 ident ) OPT ( "using" one_term ) | "dependent" "induction" ident OPT ( [ "generalizing" | "in" ] LIST1 ident ) OPT ( "using" one_term ) | "field" OPT ( "[" LIST1 one_term "]" ) | "field_simplify" OPT ( "[" LIST1 one_term "]" ) LIST1 one_term OPT ( "in" ident ) | "field_simplify_eq" OPT ( "[" LIST1 one_term "]" ) OPT ( "in" ident ) | "intuition" OPT ltac_expr | "now" ltac_expr | "nsatz" OPT ( "with" "radicalmax" ":=" one_term "strategy" ":=" one_term "parameters" ":=" one_term "variables" ":=" one_term ) | "ensatz" OPT ( "with" "strategy" ":=" one_term ) | "psatz" one_term OPT nat_or_var | "revert" "dependent" ident | "ring" OPT ( "[" LIST1 one_term "]" ) | "ring_simplify" OPT ( "[" LIST1 one_term "]" ) LIST1 one_term OPT ( "in" ident ) | "match" ltac2_expr5 "with" OPT ltac2_branches "end" | "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5 | qualid LIST1 tactic_arg ] hloc: [ | "in" "|-" "*" | "in" ident | "in" "(" "type" "of" ident ")" | "in" "(" "value" "of" ident ")" ] in_hyp_as: [ | "in" LIST1 [ ident OPT as_ipat ] SEP "," ] as_ipat: [ | "as" simple_intropattern ] oriented_rewriter: [ | OPT [ "->" | "<-" ] OPT natural OPT [ "?" | "!" ] one_term_with_bindings ] induction_clause: [ | induction_arg OPT ( "as" or_and_intropattern ) OPT ( "eqn" ":" naming_intropattern ) OPT occurrences ] induction_arg: [ | one_term_with_bindings | natural ] induction_principle: [ | "using" one_term_with_bindings OPT occurrences ] auto_using: [ | "using" LIST1 one_term SEP "," ] hintbases: [ | "with" "*" | "with" LIST1 ident ] intropattern: [ | "*" | "**" | simple_intropattern ] simple_intropattern: [ | simple_intropattern_closed LIST0 [ "%" term0 ] ] simple_intropattern_closed: [ | naming_intropattern | "_" | or_and_intropattern | equality_intropattern ] naming_intropattern: [ | ident | "?" | "?" ident ] or_and_intropattern: [ | "[" LIST0 ( LIST0 intropattern ) SEP "|" "]" | "(" LIST0 simple_intropattern SEP "," ")" | "(" LIST0 simple_intropattern SEP "&" ")" ] equality_intropattern: [ | "->" | "<-" | "[=" LIST0 intropattern "]" ] one_term_with_bindings: [ | one_term OPT ( "with" bindings ) ] bindings: [ | LIST1 one_term | LIST1 ( "(" [ ident | natural ] ":=" term ")" ) ] int_or_var: [ | [ integer | ident ] ] comparison: [ | "=" | "<" | "<=" | ">" | ">=" ] alias_definition: [ | "(" ident LIST0 simple_binder ":=" term ")" ] simple_binder: [ | name | "(" LIST1 name ":" term ")" ] as_name: [ | "as" ident ] q_clause: [ | ltac2_clause (* Ltac2 plugin *) ] ltac2_clause: [ | "in" ltac2_in_clause (* ltac2 plugin *) | "at" ltac2_occs_nums (* ltac2 plugin *) ] ltac2_in_clause: [ | "*" OPT ltac2_occs (* ltac2 plugin *) | "*" "|-" OPT ltac2_concl_occ (* ltac2 plugin *) | LIST0 ltac2_hypident_occ SEP "," OPT ( "|-" OPT ltac2_concl_occ ) (* Ltac2 plugin *) ] ltac2_constr_delimiters_arg: [ | scope_key | "delimiters" "(" LIST1 scope_key SEP "," ")" ] ltac2_constr_synclass_arg: [ | ltac2_constr_delimiters_arg | "custom" "(" qualid ")" | "level" "(" natural ")" ] q_occurrences: [ | OPT ltac2_occs (* ltac2 plugin *) ] ltac2_occs: [ | "at" ltac2_occs_nums (* ltac2 plugin *) ] ltac2_occs_nums: [ | OPT "-" LIST1 [ natural | "$" ident ] (* Ltac2 plugin *) ] ltac2_concl_occ: [ | "*" OPT ltac2_occs (* ltac2 plugin *) ] ltac2_hypident_occ: [ | ltac2_hypident OPT ltac2_occs (* ltac2 plugin *) ] ltac2_hypident: [ | ident_or_anti (* ltac2 plugin *) | "(" "type" "of" ident_or_anti ")" (* ltac2 plugin *) | "(" "value" "of" ident_or_anti ")" (* ltac2 plugin *) ] q_induction_clause: [ | ltac2_induction_clause (* ltac2 plugin *) ] ltac2_induction_clause: [ | ltac2_destruction_arg OPT ltac2_as_or_and_ipat OPT ltac2_eqn_ipat OPT ltac2_clause (* Ltac2 plugin *) ] ltac2_as_or_and_ipat: [ | "as" ltac2_or_and_intropattern (* ltac2 plugin *) ] ltac2_eqn_ipat: [ | "eqn" ":" ltac2_naming_intropattern (* ltac2 plugin *) ] q_conversion: [ | ltac2_conversion (* ltac2 plugin *) ] ltac2_conversion: [ | term (* ltac2 plugin *) | term "with" term (* ltac2 plugin *) ] q_rewriting: [ | ltac2_oriented_rewriter (* ltac2 plugin *) ] ltac2_oriented_rewriter: [ | OPT q_orient ltac2_rewriter (* ltac2 plugin *) ] q_orient: [ | OPT [ "->" | "<-" ] ] ltac2_rewriter: [ | OPT natural OPT [ "?" | "!" ] ltac2_constr_with_bindings ] q_dispatch: [ | ltac2_for_each_goal (* ltac2 plugin *) ] ltac2_for_each_goal: [ | ltac2_goal_tactics (* Ltac2 plugin *) | OPT ( ltac2_goal_tactics "|" ) OPT ltac2_expr ".." OPT ( "|" ltac2_goal_tactics ) (* Ltac2 plugin *) ] ltac2_goal_tactics: [ | LIST0 ( OPT ltac2_expr ) SEP "|" (* Ltac2 plugin *) ] q_reductions: [ | ltac2_reductions (* ltac2 plugin *) ] ltac2_reductions: [ | LIST1 ltac2_red_flag (* ltac2 plugin *) | OPT ltac2_delta_reductions (* ltac2 plugin *) ] ltac2_red_flag: [ | "beta" (* ltac2 plugin *) | "iota" (* ltac2 plugin *) | "match" (* ltac2 plugin *) | "fix" (* ltac2 plugin *) | "cofix" (* ltac2 plugin *) | "zeta" (* ltac2 plugin *) | "delta" OPT ltac2_delta_reductions (* ltac2 plugin *) | "head" (* ltac2 plugin *) ] ltac2_delta_reductions: [ | OPT "-" "[" LIST1 refglobal "]" ] q_reference: [ | refglobal (* ltac2 plugin *) ] refglobal: [ | "&" ident (* ltac2 plugin *) | qualid (* ltac2 plugin *) | "$" ident (* ltac2 plugin *) ] q_hintdb: [ | hintdb (* ltac2 plugin *) ] hintdb: [ | "*" (* ltac2 plugin *) | LIST1 ident_or_anti (* ltac2 plugin *) ] q_constr_matching: [ | ltac2_match_list (* ltac2 plugin *) ] ltac2_match_key: [ | "lazy_match!" | "match!" | "multi_match!" ] ltac2_match_list: [ | OPT "|" LIST1 ltac2_match_rule SEP "|" ] ltac2_match_rule: [ | ltac2_match_pattern "=>" ltac2_expr (* ltac2 plugin *) ] ltac2_match_pattern: [ | cpattern (* ltac2 plugin *) | "context" OPT ident "[" cpattern "]" (* ltac2 plugin *) ] q_goal_matching: [ | goal_match_list (* ltac2 plugin *) ] goal_match_list: [ | OPT "|" LIST1 gmatch_rule SEP "|" (* ltac2 plugin *) ] gmatch_rule: [ | gmatch_pattern "=>" ltac2_expr (* ltac2 plugin *) ] gmatch_pattern: [ | "[" LIST0 gmatch_hyp_pattern SEP "," "|-" ltac2_match_pattern "]" (* ltac2 plugin *) ] gmatch_hyp_pattern: [ | name ":" ltac2_match_pattern (* ltac2 plugin *) | name ":=" "[" ltac2_match_pattern "]" ":" ltac2_match_pattern (* ltac2 plugin *) | name ":=" ltac2_match_pattern (* ltac2 plugin *) ] q_move_location: [ | move_location (* ltac2 plugin *) ] move_location: [ | "at" "top" (* ltac2 plugin *) | "at" "bottom" (* ltac2 plugin *) | "after" ident_or_anti (* ltac2 plugin *) | "before" ident_or_anti (* ltac2 plugin *) ] q_pose: [ | pose (* ltac2 plugin *) ] pose: [ | "(" ident_or_anti ":=" term ")" (* ltac2 plugin *) | term OPT ltac2_as_name (* ltac2 plugin *) ] ltac2_as_name: [ | "as" ident_or_anti (* ltac2 plugin *) ] q_assert: [ | assertion (* ltac2 plugin *) ] assertion: [ | "(" ident_or_anti ":=" term ")" (* ltac2 plugin *) | "(" ident_or_anti ":" term ")" OPT ltac2_by_tactic (* ltac2 plugin *) | term OPT ltac2_as_ipat OPT ltac2_by_tactic (* ltac2 plugin *) ] ltac2_as_ipat: [ | "as" ltac2_simple_intropattern (* ltac2 plugin *) ] ltac2_by_tactic: [ | "by" ltac2_expr5 (* ltac2 plugin *) ] ltac2_entry: [ ] ltac2_selector: [ | toplevel_selector ":" ] ltac2_use_default: [ | "." (* ltac2 plugin *) | "..." (* ltac2 plugin *) ] tac2def_body: [ | [ "_" | ident ] LIST0 tac2pat0 OPT ( ":" ltac2_type ) ":=" ltac2_expr (* ltac2 plugin *) ] tac2typ_def: [ | OPT tac2typ_prm qualid OPT ( [ ":=" | "::=" ] tac2typ_knd ) (* ltac2 plugin *) ] tac2typ_prm: [ | ltac2_typevar (* ltac2 plugin *) | "(" LIST1 ltac2_typevar SEP "," ")" (* ltac2 plugin *) ] tac2typ_knd: [ | ltac2_type (* ltac2 plugin *) | "[" OPT ( OPT "|" LIST1 tac2alg_constructor SEP "|" ) "]" (* ltac2 plugin *) | "[" ".." "]" (* ltac2 plugin *) | "{" OPT ( LIST1 tac2rec_field SEP ";" OPT ";" ) "}" (* ltac2 plugin *) ] tac2alg_constructor: [ | LIST0 [ "#[" LIST1 attribute SEP "," "]" ] ident (* ltac2 plugin *) | LIST0 [ "#[" LIST1 attribute SEP "," "]" ] ident "(" LIST0 ltac2_type SEP "," ")" (* ltac2 plugin *) ] tac2rec_field: [ | OPT "mutable" ident ":" ltac2_type (* ltac2 plugin *) ] ltac2_syntax_class: [ | string (* ltac2 plugin *) | integer (* ltac2 plugin *) | name (* Ltac2 plugin *) | name "(" LIST1 ltac2_syntax_class SEP "," ")" (* Ltac2 plugin *) ] ltac2_expr: [ | ltac2_expr5 ";" ltac2_expr (* ltac2 plugin *) | ltac2_expr5 (* ltac2 plugin *) ] ltac2_expr5: [ | "fun" LIST1 tac2pat0 OPT ( ":" ltac2_type ) "=>" ltac2_expr (* ltac2 plugin *) | "let" OPT "rec" ltac2_let_clause LIST0 ( "with" ltac2_let_clause ) "in" ltac2_expr (* Ltac2 plugin *) | ltac2_expr3 (* ltac2 plugin *) ] ltac2_let_clause: [ | LIST1 tac2pat0 OPT ( ":" ltac2_type ) ":=" ltac2_expr (* ltac2 plugin *) ] ltac2_expr3: [ | LIST1 ltac2_expr2 SEP "," (* Ltac2 plugin *) ] ltac2_expr2: [ | ltac2_expr1 "::" ltac2_expr2 (* ltac2 plugin *) | ltac2_expr1 (* ltac2 plugin *) ] ltac2_expr1: [ | ltac2_expr1 LIST1 ltac2_expr0 (* ltac2 plugin *) | ltac2_expr1 ".(" qualid ")" (* ltac2 plugin *) | ltac2_expr1 ".(" qualid ")" ":=" ltac2_expr5 (* ltac2 plugin *) | ltac2_expr0 (* ltac2 plugin *) ] tac2rec_fieldexpr: [ | qualid OPT [ ":=" ltac2_expr1 ] (* ltac2 plugin *) ] ltac2_expr0: [ | "(" ltac2_expr ")" (* ltac2 plugin *) | "(" ltac2_expr ":" ltac2_type ")" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | "[" "|" LIST0 ltac2_expr5 SEP ";" "|" "]" (* ltac2 plugin *) | "[" LIST0 ltac2_expr5 SEP ";" "]" (* ltac2 plugin *) | "{" ltac2_expr0 "with" OPT ( LIST1 tac2rec_fieldexpr SEP ";" OPT ";" ) "}" (* ltac2 plugin *) | "{" OPT ( LIST1 tac2rec_fieldexpr SEP ";" OPT ";" ) "}" (* ltac2 plugin *) | ltac2_atom (* ltac2 plugin *) ] tac2rec_fieldpats: [ | tac2rec_fieldpat ";" OPT tac2rec_fieldpats (* ltac2 plugin *) | tac2rec_fieldpat ";" (* ltac2 plugin *) | tac2rec_fieldpat (* ltac2 plugin *) ] tac2rec_fieldpat: [ | qualid OPT [ ":=" tac2pat3 ] (* ltac2 plugin *) ] ltac2_atom: [ | integer (* ltac2 plugin *) | string (* ltac2 plugin *) | qualid (* ltac2 plugin *) | "@" ident (* ltac2 plugin *) | "&" ident (* ltac2 plugin *) | "'" term (* ltac2 plugin *) | ltac2_quotations ] ltac2_quotations: [ | "ident" ":" "(" ident ")" | "constr" ":" "(" term ")" | "open_constr" ":" "(" term ")" | "preterm" ":" "(" term ")" | "pat" ":" "(" cpattern ")" | "reference" ":" "(" [ "&" ident | qualid ] ")" | "ltac1" ":" "(" ltac1_expr_in_env ")" | "ltac1val" ":" "(" ltac1_expr_in_env ")" ] ltac1_expr_in_env: [ | ltac_expr (* ltac2_ltac1 plugin *) | LIST0 ident "|-" ltac_expr (* ltac2_ltac1 plugin *) ] generic_tactic: [ | ltac_expr ] ltac2_branches: [ | OPT "|" LIST1 ( OPT atomic_tac2pat "=>" ltac2_expr ) SEP "|" ] tac2pat3: [ | tac2pat3 "|" LIST1 tac2pat2 SEP "|" (* ltac2 plugin *) | tac2pat3 "as" ident (* ltac2 plugin *) | tac2pat2 (* ltac2 plugin *) ] tac2pat2: [ | tac2pat1 "::" tac2pat2 (* ltac2 plugin *) | tac2pat1 (* ltac2 plugin *) ] tac2pat1: [ | qualid LIST1 tac2pat0 (* ltac2 plugin *) | qualid (* ltac2 plugin *) | tac2pat0 (* ltac2 plugin *) ] tac2pat0: [ | "_" (* ltac2 plugin *) | "()" (* ltac2 plugin *) | integer (* ltac2 plugin *) | string (* ltac2 plugin *) | qualid (* ltac2 plugin *) | "(" OPT atomic_tac2pat ")" (* ltac2 plugin *) | "{" OPT tac2rec_fieldpats "}" (* ltac2 plugin *) | "[" LIST0 tac2pat3 SEP ";" "]" (* ltac2 plugin *) ] atomic_tac2pat: [ | tac2pat3 ":" ltac2_type (* ltac2 plugin *) | tac2pat3 "," LIST0 tac2pat3 SEP "," (* ltac2 plugin *) | tac2pat3 (* ltac2 plugin *) ] func_scheme_def: [ | ident ":=" "Induction" "for" qualid "Sort" sort_quality_or_set (* funind plugin *) ] rewrite_occs: [ | LIST1 integer | ident ] rewstrategy: [ | "fix" ident ":=" rewstrategy1 | LIST1 rewstrategy1 SEP ";" ] rewstrategy1: [ | "<-" one_term | "progress" rewstrategy1 | "try" rewstrategy1 | "choice" LIST1 rewstrategy0 | "repeat" rewstrategy1 | "any" rewstrategy1 | "subterm" rewstrategy1 | "subterms" rewstrategy1 | "innermost" rewstrategy1 | "outermost" rewstrategy1 | "bottomup" rewstrategy1 | "topdown" rewstrategy1 | "hints" ident | "terms" LIST0 one_term | "eval" red_expr | "fold" one_term | rewstrategy0 | "old_hints" ident ] rewstrategy0: [ | one_term | "fail" | "id" | "refl" | "(" rewstrategy ")" ] l3_tactic: [ ] l2_tactic: [ ] l1_tactic: [ ] value_tactic: [ ] syn_value: [ | ident ":" "(" nonterminal ")" ] ltac_expr: [ | ltac_expr4 ] ltac_expr4: [ | ltac_expr4 ";" ltac_expr3 | ltac_expr4 ";" "[" for_each_goal "]" | ltac_expr3 ] ltac_expr3: [ | l3_tactic | ltac_expr2 ] ltac_expr2: [ | ltac_expr1 "+" ltac_expr2 | ltac_expr1 "||" ltac_expr2 | l2_tactic | ltac_expr1 ] ltac_expr1: [ | tactic_value | qualid LIST1 tactic_arg | l1_tactic | ltac_expr0 ] tactic_value: [ | [ value_tactic | syn_value ] ] tactic_arg: [ | tactic_value | term | "()" ] ltac_expr0: [ | "(" ltac_expr ")" | "[>" for_each_goal "]" | tactic_atom ] tactic_atom: [ | integer | qualid | "()" ] let_clause: [ | name ":=" ltac_expr | ident LIST1 name ":=" ltac_expr ] for_each_goal: [ | goal_tactics | OPT ( goal_tactics "|" ) OPT ltac_expr ".." OPT ( "|" goal_tactics ) ] goal_tactics: [ | LIST0 ( OPT ltac_expr ) SEP "|" ] toplevel_selector: [ | goal_selector | "all" | "!" | "par" ] goal_selector: [ | LIST1 range_selector SEP "," ] range_selector: [ | natural | "[" qualid "]" | natural "-" natural ] match_key: [ | "lazymatch" | "match" | "multimatch" ] match_pattern: [ | cpattern | "context" OPT ident "[" cpattern "]" ] cpattern: [ | term ] goal_pattern: [ | LIST0 match_hyp SEP "," "|-" match_pattern | "[" LIST0 match_hyp SEP "," "|-" match_pattern "]" | "_" ] match_hyp: [ | name ":" match_pattern | name ":=" match_pattern | name ":=" "[" match_pattern "]" ":" match_pattern ] rocq-9.2.0/doc/tools/latex_filter000077500000000000000000000015201516144147600170120ustar00rootroot00000000000000#!/bin/sh # First argument is the number of lines to treat # Second argument is optional and, if it is "no", overfull are not displayed i=$1 nooverfull=$2 error=0 verbose=0 chapter="" file="" while : ; do read -r line; case $line in "! "*) echo $line $file; error=1 verbose=1 ;; "LaTeX Font Info"*|"LaTeX Info"*|"Underfull "*) verbose=0 ;; "Overfull "*) verbose=0 if [ "$nooverfull" != "no" ]; then echo $line $file; fi ;; "LaTeX "*) verbose=0 echo $line $chapter ;; "["*|"Chapter "*) verbose=0 ;; "(./"*) file="(file `echo $line | cut -b 4- | cut -d' ' -f 1`)" verbose=0 ;; *) if [ $verbose = 1 ]; then echo $line; fi esac; if [ "$i" = "0" ]; then break; else i=`expr $i - 1`; fi; done exit $error rocq-9.2.0/doc/tools/rocqrst/000077500000000000000000000000001516144147600161015ustar00rootroot00000000000000rocq-9.2.0/doc/tools/rocqrst/__init__.py000066400000000000000000000013221516144147600202100ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## 0: deps = " ".join(missing_deps) eprint('Cannot find package(s) `%s` (needed to build documentation)' % deps) eprint('You can run `pip3 install %s` to install it/them.' % deps) sys.exit(1) try: import sphinx_rtd_theme except: missing_dep('sphinx_rtd_theme') try: import pexpect except: missing_dep('pexpect') try: import antlr4 except: missing_dep('antlr4-python3-runtime') try: import bs4 except: missing_dep('beautifulsoup4') try: import sphinxcontrib.bibtex except: missing_dep('sphinxcontrib-bibtex') report_missing_deps() rocq-9.2.0/doc/tools/rocqrst/notations/000077500000000000000000000000001516144147600201175ustar00rootroot00000000000000rocq-9.2.0/doc/tools/rocqrst/notations/Makefile000066400000000000000000000022031516144147600215540ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## ../tests/antlr-notations.html rocq-9.2.0/doc/tools/rocqrst/notations/RocqNotations.ttf000066400000000000000000001121441516144147600234440ustar00rootroot00000000000000 FFTMt₯Λ•”HGDEF5Ρ‘ˆ*GPOS5ΞN°”@GSUBΜDχ:‘΄ROS/2‰υr¨`cmap{Ψ1¨jcvt :[)v \zfpgmv½DΔ#gasp‘€glyfZ- :tzhead£·Λ,6hheaΣ/d$hmtx a loca“Ίv Ψšmaxpβˆ name‘Ύ5»‰x΅postPε‰Œ0NprepφXΓ» 8#ΜΜ‘pυ3_<υτΙεΎΛΦχλOώ~ξ>Vτώ~ΰΜ`/Y§sτΌΌŠŒΌŠέ2ϊ  ΰP [DAMA Ύ΅[1>ͺ ŸV΅ ττττ§W"Ί^U.(~q‘/#0+)#.1&-‘v-((E 66??-6*-G.66('  .q1m˜,>,$!?$1?$??Y6$; C?½?§.& ½1Sh2-qll(qq˜;‘ŸJ2 2$- Δ€ Δ^Uq/q1m??„r6›©22EO‘m†JJJo‹wwMMM`«ͺ§ώΧώτ\]Zfώώ­ώ°ώžώφώφkGώ~ώœώΛώ½ώώώ - dH ~Ύ   ωυδγΒ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ardeixpkvjsgwl|cnm}byqz@?XUTSRQPONMLKJIHGFEDCBA@?>=<;:98765/.-,(&%$#" ,E#F` °&`°&#HH-,E#F#a °&a°&#HH-,E#F`° a °F`°&#HH-,E#F#a° ` °&a° a°&#HH-,E#F`°@a °f`°&#HH-,E#F#a°@` °&a°@a°&#HH-, <<-, E# °ΝD# ΈZQX# °D#Y °νQX# °MD#Y °&QX# ° D#Y!!-, EhD °` E°FvhŠE`D-,± C#Ce -,± C#C -,°(#p±(>°(#p±(E:± -, E°%Ead°PQXED!!Y-, E°C`D-,°C°Ce -, i°@a°‹ ±,ΐŠŒΈb`+ d#da\X°aY-,ŠEŠŠ‡°+°)#D°)zδ-,Ee°,#DE°+#D-,KRXED!!Y-,°%# Šυ°`#νμ-,°%# Šυ°a#νμ-,°%υνμ-, °` <<-, °a <<-,°C°C -,!! d#d‹Έ@b-,!°€QX d#d‹Έ b²@/+Y°`-,!°ΐQX d#d‹ΈUb²€/+Y°`-, d#d‹Έ@b`#!-,E#E`#E`#E`#vh°€b -,°&°&°%°%E#E °&`bch °&aeŠ#DD-, E°TX°@D E°@aD!!Y-,E±0/E#Ea`°`iD-,KQX°/#p°#B!!Y-,KQX °%EiSXD!!Y!!Y-,E°C°`c°`iD-,°/ED-,E# EŠ`D-,E#E`D-,K#QXΉ3ΰ±4 ³34YDD-,°CX°&EŠXdf°`d° `f X!°@Y°aY#XeY°)#D#°)ΰ!!!!!Y-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°% F°%°`#B< XY°%°%°)ΰ°%°%°)ΰ°%°% XY°%°%CH°%°%°`CH!Y!!!!!!!-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°%°%°% F°%°`#B< XY°%°%°)ΰ°) EeD°%°%°)ΰ°%°% XY°%°%CH°%°%°%°%°`CH!Y!!!!!!!-,°% F°%#B°%°%EH!!!!-,°% °%°%CH!!!-,E# E °P X#e#Y#h °@PX!°@Y#XeYŠ`D-,KS#KQZX EŠ`D!!Y-,KTX EŠ`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,°CTX°F+!!!!Y-,°CTX°G+!!!Y-,°CTX°H+!!!!Y-,°CTX°I+!!!Y-, Š#KSŠKQZX#8!!Y-, ŠI°QX°@# Š84!!Y-,F#F`#Fa#  FŠaΈ€bб@@ŠpE`h:-, Š#IdŠ#SX<!Y-,KRX}zY-,°KKTB-,±B±#ˆQ±@ˆSZXΉ ˆTX±BYY-,Eh#KQX# E d°@PX|YhŠ`YD-,°°%°%°#>°#>± ° #eB° #B°#?°#?± °#eB°#B°-@ vn)uodtrdrC)qodpndoBnBia)gedeC)dBcadaBYQ)XBWUdUC)TBSQdRBQBLD)JHdHC)FDdDBCA/B?Bœ* * U*Uœœ*U * U*U*U *U*UTSΈ³ΈKΈRK°P[°ˆ°%S°ˆ°@QZ°ˆ°UZ[X±ŽY…BK°SX° YK°€SX°±BY++++++++t+++s++++++++++++++++++++++++++++°kkυσΦ σ[ύ»[||f|P}fPkr{d}›fk›{}ofk{Ž}¦fTk¦vf³³PP<<::dd_@Ÿ~ΖrϊϋU*ΨW‡!ŒŒ‡£Gxo{΅ͺ9j•Z\Ά.rΣΎ+z4Y*CrrQY§τέ=****b¨ŒϊΎ‚Ίβ –ς"8„¨>ŠN€6  h ˜ Π ϊ  J ¨ ΄ r ΐ  N ˆ Ψ 8p²ΨΐN–κNΎΰ †|Ψl–Ίδ &<ͺ V΄pΠlΔRΠL–δ†ζhF‚ΠhŠβ""\Ό  Μ!>!b""<"β#X#’#Ύ#Μ$ͺ$ΐ$ϊ%T%ž&J&`&€&ζ''8'p'( (),)**2*¨+$+:+^+|+’++Κ+Ψ+ζ,F,X,f,x,ͺ,β,τ--"-0-B-j-†-’-κ. .Z.€.Ξ//\/²00040P0ž0π1V1Μ22Œ2Ά2Μ3"3v34.4Š4ζ5Z5Μ66T6ž6θ727|7ή8@8¦9 9x9δ:P:Ό;@;Δ<<.<|<Β=’M.±/<²»ν2±ά<²»ν2±/<²»ν2²Όό<²»ν233'3#‚rbbMώ³-§ΎM6 @qo u ??ύΞΦνΤν10#.=3#"&54632AfŽ 3 33 3’$:44 44:$€ύά(,,(&,,WmŸ‡ 6@n n@ °Έΐ@ H   ?Ε?Ε/Φ+]_qύήν10#.=##.=Ÿ H B G †0:><<><00:><<><0Δγ0jΉΐ³MΈΐ·LOΈΐ³ MΈΐ΄ LΈΐ³MΈΐ· LpΈ€³MΈΐ³ MΈψ@ M@MΈΐ³ MΈΠ³MΈΐ· L|Έΐ΄ LΈΐ³ M ΈΐΆ M@  Έΐ³ MΈΐ³MΈΐ΄L Έΐ@e My  y!yy  r r??Ν]22/2ν23??έ22ν22ήέ9]νν9]]ήΐΤ]]ν]ή]ΐά]9]ν910++++]+++]+++++++]++++]++733733#3##7##7#537#537#ŠfPf>RgzfPf753.#"#Α?M& V08,!08,!6'r.GO*0% &'B0%=.r' b %5'4,! a\g " !+:'5-!k·ς='3ο΅' M"Έΐ³ M ΈπΆ MΈΰ@ M MΈΐ³MΈΰ³MΈπ@BM" "°""|(―Ώ|(((―Ώ|` p €  55 .°..|44+Έΐ@,H+}―ΏΟ} p}%}1ΐ·Ο111??99//]]]νν]?ν]?ν+ΦΝΦν]ήΝΦ]ν]99//]]ν]ν]10+++++]+++#34632#"&74&#"3264632#"&74&#"326[Y—Yι<45<<54<‘ώp<36<<63<  <kώ#LOOLLOOL*$$**""zLOOLLPPL*##**""Ήβ;)5AΒΉ?ψ@ M%@ M"@ MΈΐ³ M Έΐ@ M9@ M.Έ€³ M.Έΐ³ M-Έΐ@ L9-  &C""y#C?<_<3267'.'326>54&#"m "H#-C-11.96*:>,f& Ύ<#*.f ">.>"0X H((<("6"0\ 24F8`&"F"|$B * "2x.<"Ίd= =ΆnR  Έ€@ H ΰ π  Έ€³H Έΐ· H  ?ΕΦ++]q+_qν10#.== H B:>>>>:B^B‘² @ p Š??ΕΦνήΖ107.5467Πm`9ˆ~‚ˆ9`qφ{΅8LKΰ‰ŠηKL8ΌUB˜² @ p  Š?Ε?Ζ2ήν10%4&'7'>&q`9ˆ‚~ˆ9`mφ|Ό8LKηŠ‰ΰKL8΅.6ΚΎ@Y@<@M<:.'4"'Έΐ@M AB/-;4 ' ?έΐέΕέΖΥΝΤΝ9/ΕΕέΖ2+έΕΕ9=/έΖ2+107'7>7*./7.=3>?"#'.ό ^ #$" %   t   $ "$# ^ Θ "" B  n  $" "$  p D ""(ΜΫ Ήΐ³ MΈΐ@ M@M@M@ MΈΐ³ MΈΐ³ MΈΐ@4 M@M@M R`@ P €   ΟUΟ ?έΐ]ύΝ]ΐ9/]Ν]3ύ2Ν]10++++++++++3533##5#(jj,d~Z[š@z {?ν?ΕήΞΦν107>7.54632~%!&*3'*/1N8ͺ 4 '280#F<,q½ƒ7΅‘?ΕΦΝ10!!qώξ6x‘‘TS_Ήΰ³MΈΰ@He L H M HjΈΰ³MΈΰ@Hez {?νΦύΞ10]++]++++]++%#".54>32T6#  #6ϋ,. !! ./JΕͺ-@v??/Α‡+Α‡}Δ10#3―€~Ά`#·Ρ= #U@4οΡΐŸd d%d$±! !!@e e ?ν?ν9/]Ν]]ΦνΪι/9/ν]]]]10%#"&546324&#"326'#"&54632Ρniinpgino532662350ϋ€  €’ Ÿ£joojkoou''((0ΔΛ0/@@ M a  ee ??νν9ήέύΝ3Ξ10+7'>733!5ΥH(882T{ώˆ*Z f "&ύϊff+½Ξ7%&@c ' c&g! e ?ν?ν2ΦνΖήΦν10!!&654>54&#"'>32²(2 " ώl%9A9%.#@=(i4&F6 † <84 $$f 2TF>84&*"V*(,B)·Γ=0€Ή-ΐ³ M,Έΐ³ M+Έΐ³ MΈΐ³ M Έΐ³ M Έΐ@* M L)c&, c,,21g!))e! g ?ν2?9/ν9=/ν2ΦΖΦ]ύΞΤν310+++++++".'732654&+532>54&#"'>32Υ3/( I3?3N<&.&)$#E,Y84M2*#05:ZI g 6(1'f"'Z%/@%%DN6+H5ΔΫ00@ ae  ??9/93ν22Φ2έ22ύΝ31033##5!5>7&%" Œ{CC{ώώ7!##".'732>A3^L <Υ|z>\=2.% D3$/ +T‘Kf Fh^+I6 f  .ΌΗ8->@&c`p/+cc Έΐ@ H .e&g% g ?ν?ν9νΦ+ννή]νΔ107"32>54&'2#"&54>3>ρ( # *$6K00J3hm5bŠT(L@/ $ο  5*$/3f 6H($J>'‰ZŠ^0i!4' 1ΔΕ0)Άa cΈΐ@ H ee ??ννΦ+έύήν10>7!5!„$3<ώό”@9+<@Œ|.f^pŽ’P&ΆΟ>+7ύ΅6@ M4Έ€³ M2Έΐ@ M0@ M/Έΐ³ M/Έΰ³ M.Έΐ΄ L,ΈΐΆ M ,Έΐ³ MΈΰ@ M @ M M5Έΐ³ M/Έΐ΄ L#Έΐ³M#ΈΐΆ M#"Έΐ@ M"2#dΈΐ³ MΈΐ@& H95d9//d&dP82##),g)g ?ν?ν9/9Φ]νΠι/Φ]νΦ++ν910]+]++++++++]++++++++#".5467.54>324.'326">54&Ύ*-9/3R2 *@&0R D&B4"Xώ€8(*,$$",8"$-»Ι9*@@%))c c@  ,&c 0@+e&g% g?ν?ν9νΦ]νΔΪ]ι/ι/10267>54.#"".54>32#'267*  # ,$6L01J2hn4a‰TP~' 4*&02f 6F*$J>&Œ|ZŒ^0jDH‘ Tλ#".54>32#".54>32T6#  #66#  #6’,.    .ώ¨,. "" .vΒT2##".54>32>7.54632T6#  #6ή%!&*3'*/1N8Ϊ,. "" .ώ 4 &280"F<,-!ΟΣ*@??9=/999Βήΐ910% %-€"ώθ"ώ€2‘lmml’(ȅ!@ UU£?ύΦνΦΐή2ΐ210!!!!(€ώ\€ώ\Žf\f(!ΛΣ.@??9=/9999ΦΐΞ910%'-7Λώ€#ώη#€Γ’lmml‘E·²=01@22q'''1,u" g?ύΒ?ύΖΖή]νήΕήΝ107&5467>54&#"'>32#".54>32¦*"(* <#"#^.9J*#(##3 € (H*^.80*$$&š&,  zΤz5EZΉ>ΐ³M8Έΐ@M!@M!8 M @ MΈΰ³ MΈΐ@M: M:@ M Έΐ@ MŸ @M@M@M MΈΐ³MΈΐ@ M@ LΈΰ΄LΈΐ³MΈΐ³MΈΐ΄LΈΰ@rL@ M@ M@ M@ M M MP==@>>y 505`55GO6_66y+!GŸ|+F@Py=@APAAy &> = = &}0 }&/ύ]Ζ?ν99//999ν]ν]]Φν]Ζ9/ν]Φ]ν]22]10++++++++++++++++++]++++++++++%#".54>3254&#"3267#".54>323275.#"ΤG&A0$9*0.!;+3U?/6 BrS0)FZ2)H6 Ε 8 1O9*J7 &5FuYFlI& W$Y“ol“['6W>ž( Θ" Δλ0 DΉ ΰ@' L L   H ????9/9νΖΖ910++'##6733.g₯€,Z*†,W)ς  y <Έ,ˆˆώΞ²τ$>>> >>>6½Υ7#0T@'F Fp€20D Έΐ@ H   1#H$$,J J ?ν?ν9/ν9=/Φ^]+ν2ή]]νΤν10%#"&'>32%32>54&#'2654.#"Υ&AY3)X+#T)FX2+$?-ώά (90/0  €8K- Y /:,DN)¨#-'f)$Ž·Υ=:Ά`  Έΐ@H!F J JJJ ?νΥν?νΥνΦνΦ+2Ζ]210"&54>32.#"3267(ƒŠ*Kg=!5( A*7+IS0?YI¨›MxS+ b1R=jq a6½Ω7!6@ F#DΈΐ@ H" HH ?ν?νΦ^]+ν}/ή]ν107232>54.#"#"&'>32± *9# 4)(+Li?!?$*J =eF') 8M.(L:#ΞVyL#\ $Mw?ΔΜ0 Q@ 0  D 0 H@MΈΐ³MΈΐ@ M H H?ν?ν9/+++νΦ]ν2Φ]ΖΖ10!#3#!?wόΫΫ<lfŒff?ΔΊ0 J@/@ M@€ D@ M0 H H?ν??9/νΦ]+ν2Φ^]]+Δ10!!3#?{ΰΰ<lf–fώφ·Π=#4@ %F$ D0  !JJ ??ν?ύΖ?9//]νΦνΞ10"326753#".54>32.8,<'FD  {]B:]B$*Hb8$9* @ 9O0oiβώΛ)QyPOyR) b-ΔΗ0 ;@  D  DΈΐ@ H  H@???9/]ν?Φ+ν2ήν210###335Η{€{{€0ύ”ώξlττ6ΔΏ0 .Ά  DΈΐ@ H H H?ν2?ν2Φ+ΐέύάΐ1053#5!#36‡‡‰††73^ )27{{0+$ ‹'29@9.<$PNBώδlώώDDBDLN$NX^,GΔΜ0,Ήΐ· HDΈΐ@ HH?ν?ή+νΖ+10!3!Μώ{| <lύϊΔέ0o΅ MΈΐ@ M0 MΈΰ@[ M@ L?@ M? M M L @ M M @ M @ L @ L?  @M L M MΈΰ@M@ M M L@ LΈΐ@ M@ M M M?Έ€³ MΈΐ@1 M@ M@ M/?@ M DDΈΐ@Mo  ??9/9??9/9|ή]]+νΡΙ/Φν9=/9999ΩΙ/10+]++]++]+++]++++++++++]++++++++]+]]+++]++>73###>7‘ f qLZIq 0BLN $PH@Rš–šPβώϊώL€’˜B.ΔΖ0S@ @ M Έΐ@ M?/ ?  DDΈΐ@ H  ????99Φ+ν2ήν]210]+]+.'#33c*c9oc85-o54.#"4632#"&˜& '& &}vimrtjmsϊ-O:"";N--O:"";N- ££  ££6ΑΨ3?@ F`D Έΐ@ H  HJ?ν?99//ν?Φ+ν2ή]ν102+#>"32654&ΰv‚ƒx,{-., ' 2;<;3anocΡckΘ/96-jΩŠ&/@F (F' J J  "J?ν?3νένΦνΪ2ι/9104632.'.732>54.#"vimrZU UJuw QW}& '& &G ££ Œ‘! XKFŸ‰-N;"";N--O:"";N6Αι3$Y@D` p €  &F`p€&!DDΈΐ@ H%H!!  J?ν????9/ν2Φ+ννή]νή]2ν2102#.'##>4&#"326Φ5V>!,3&$! =#@{+,(|<1 ?832M46X?EE54.'.54632.#"#"&'7θ) "*<1 qc9U$=(b'?5"qsM\$K  (;,Wb_G -C3W_!dΔΫ0@DH???ν2ΦέύΝ10###5Ϋ£|£0fύϊf'ΎΝ6/@ D`pDΈΐ@ H J ?ν?3Φ+νή]ν10".5332>53ψX6‹ώ}'5 !5'‚ώu6X>! Δθ0ƒ@ MMHΈΰ@ M$ M+Έΰ³MΈψ@0LG @ M   /  ???3??9]ΖΞ]910+]++]+]+]++.'3>73Ί60& ‚!  #-67( r f,0f r T8DN*4x|~”@Fš  L<~|x4 LJ> Δι0f΅ MΈΰ³MΈΰ³ M Έΰ@'M    ??9??//Ζ99=//99Ζ10++++.'#>7373d7:… '/4’…bg|ž4-" <4|><~4LX\,$ΖΖώή*^ZL Δθ0>@!D€      ???9??9/]Ξ2ν9=/Ν210>73#5.'3ώ  &*0|7S&„8FNP 4`^\2μμ`ΊfH–.ΔΖ0f΅@ MΈΰΆ MΈΐ@ HΈΐ΄ H Έΐ@ H Έΐ@ HHH?ν?ν?Ν/+]Ζ+Ζ+99Ξ+]10++!!5>7#5!½+H>7 ώh2>I,ξ‚ΪBtj`0fH*`l~JfqJ†ͺ/@_@_@ nrr?ν?νΦνΞ]]Ξ]]10!#3!q  ώλͺ`ύ``1JΗͺ*@v???/ΖΑ‡+‡}Δ103#1~ͺό mJƒͺ/@n@@ Prr?ν?νΦ]ΐΞ]ή]ν210!53#5!ƒώκ  Ά` `Dλ°)@r?ύΝ29=/9910%''3λo~~pΉiz6ΪΪ66Δμ0@ U??νΖΖ10!!δώ0l˜‘sS΅}?ΕΦΕ10'՞-SoCT,Ήρ.S@ $QS0, SΈΐ@$ H/_oWP"`"""@W(@ M(W ?ν+?ν]9/]ν]Φ+νΔήνν10]72675.#"2#".54>3254&#"'>ϋ& "$0:M.jB-I4 6F&0%,6#ATfl  Š2F,ώθ$<**8""0 d >™Φ[ [@ @ M @ M@ MΈΐ@ MS` p  !QQΈΐ@ H UW W?ν???νΥνΦ+ννή]ν10++++%4&#"3267#"&'7>32Y+,' 08}:T60d"{0.F/’BF @L8\@" ”κ "BZ,ρ5@0@`p!SΈΐ@ H W W ?ν?νΦ+νή]Ζ10]74>32.#"3267#"., BeF*D#1&,;$IX?J2HgBϊ2ZD& b $4BJ f &BZ™[ `@@Δ@ΐ@ΐ Έΐ³ MΈΐ@ M@ MQSU W W?ν?νΥν??Φνήν210+++]q]q]q73267.#"#"&5463257™/4$,("b/nq_]0{’>P Fώή ‚pt„ ΦΡρ%\Ήΐ@7LS ?  '% Sp& @MO _  U@W0  W ?ν]?ύ]Ζ9/]ν]+Φ]ν2ή]Ζν10+74>32!3267#".%4.#"&>P*hlώΟL<%C H-<_C$; "# φ>^> zv .6h >Zl"$$ŸμUVΉΐΆ MPΈΐ@) MP  Q`pOU W U ?ν?ν?ν?Φ]]έ2ν2Ζ]Ξ10]+]+#5354>32.#"3#‹gg!8H&'R!EΑΑ`pf:J.d&fώ!ΆΆ> 'GΉΐ@'LQQ`  )S`"p""(W W% @W?ύ]Ζ?ν9/νΦ]νΦ]νν10+32675.#"#"&'732>=#"&54632ž*-# lo{,Q%@0 * +\_€nMZX:= βώ½sn h # tgtr?ŸΉUB@Q@ ` p  QQΈΐ@ H W ????ν??}/Φ+νΠνή]ν107>32#54&#"?{*4F*{*! a‘δ 9O0ώχωB:ώ–$žΣV LΉψ@. MQp?!! !`!T `pWUX ?ύήν?ύΖ/]ν]ά]]]ύΝ10+#"&54632#".=#533267. -- .·&C0A'‚ύ$0$**$&**ύ’6L0fώά*(1O₯M@ MQ Έΐ@! H!T @PpUX W?ύΖ?ύήν/]νή+]ύΠΝ10+%#"&'73265#5!'#"&546321C'0R&&G"Ύ9. -- .9M/h%2Wf‡$**$%**?ŸηUQ@ @`0 QΈΐ@ H0p  ??9??/]3Φ+ν22]Ζ]2107>73#.'#7»%# ”.11:8/ ',-||»/2/684CHH?=7ή‘$œΣX6@!`p? Q P ` p   U W?ύΖ?ν?Φ]ΥνΞ]]10#"&5#533267Σ"1UN‚ύ&%2D f`fώ0" Χθ'„@^+@M@M/?_ŸίοR@M/?OΟR_) 0@R€(W" % W ?ν3??9/?νΦ]ν]ή]ν]+9/ν]++10_]]2#4.#"#54&#"#>32>W'2 d  dd'L).θ0J0ώζ ".^l0&ώŽΔ  ? Ήκ-Ά QQΈΐ@ H 0W ?ν]??Φ+νήν10>32#54&#"#?!a98J+{.{Ρ 9O0ώχωB:ώΨς&@S@ M!S W W?ν?νΦνή+ν10%#".54>3232654&#"Ψ :Q22Q; !;R01Q; ώΒ-201-201ό8\B$$B\86\@$$@\8>NN>@LL?·Υ= 6@S` p  QQΈΐ@ HW  W?ν??νΦ+ννή]ν104&#"#3267#"'#>32X23 (,*}.F./2{"c0mtD>Rώώ FF6\@$°l „·Ά= !5@QQ`p#Sp  "UW W ?ν??ύΦνΦ]νή]νν103267"&#"4>32#5#".œ+,% 33}9U630+{3.F/DBF R:6Z@$ ύ”² "@\Y Λκ!³Q Έΐ@ H W ??νΦ+ύΝ10.#"#>32΅ !" 2|1gE %*+dώ’Έ6Ίρ1LΉ/ΐ@ MS &&Έΐ@ H&3S .Έΐ@ H.2!W+W ?ν?ν99Φ+Φνή+]νΔ10+72654.'.54>32.#"#"&'7δ-0#8.1L5.OH-/!!:/3R<=V#Ol   0&4* h "2&4& h$ΔΨ0fΉΐ@@ M 0€@M@ Mo ` QP`pW U ?3έΕν2?νΦ]έ2ν2]Ξ^]]++Ζ]+10#53573#32>7#".5kk{ΕΕ "O%+B.@fvŠfΎ  j (J:; Άλ2@ Q Q Έΐ@ H   W?ν??Φ]+νή]ν10%#".533273Ά"a9:J+{-|$ :P0φ@@pζεPΉΰ³MΈΐ³ M Έΰ³ MΈΰ΄ LΈΰ@ L   ???ΒΞ910+++++7.'3>73Β-]*   }*f-YοŽ&VWR""RWV&ŽοY ιε(@Ή(ΠΆ M`('Έΐ³M'ΈΠ³ M!Έΐ@ M@MΈΐ³MΈΐ³ MΈΐ@ M@MΈΐ³ MΈΐ@ M M Έΐ³ M Έΐ³ M Έΐ³M Έΐ@ M@MΈΐ³MΈΐ³MΈ ³MΈΐ΄ LΈΐ΄ LΈΐ³MΈΐ@> M(`$$  ) %`%%*@ M0)(%   ??9/9??Ζ]+Ζ]9///q33Ζ333Ζ]310+++++++++++++++++++++++]+%.'#.'3>73>73B   ] i  Y  i '415 324 ,ky‚DW¦X&A;77;A&.TSS-‰ς[αε)@     ????/Ζ/Ζ91073#.'#>7'3ώ`}˜.*" €60}'+/₯R“βAB<3P (L/=?>δ»Ψ9"/@"Q$ #Q   ??έΖ?/νΖΦν9]10#"&'73267.'3>7Ψ#&+%-7%3$, ,X$€  9Byt7(:% g 0!Xγ‰%TTQ##QST&C΄εW΅Έΐ΅ HΈΐ· HΈΐ@ H@Pp U U?ν??ν?Ν/]/+99Ζ+Ξ+]103!5>7#5!ͺ4==ήώ664Β]‹?NU$fK&PMFf?J΅ͺ$7@"n n%r rr ?ν?ν9/ν9=/ή2ήύάΐΠν107;#"&=4&+5326=46;#"»6/ ]hZE66EZh] /ω D@q*&`NJ“*+`+)”JN`%+q@D½J9ͺ(@€ΰ_ @??ΖΖ]]]2103#½||ͺό ?J΅ͺ(C@%(@ M@ Mn&n* )r !r r ?ν?ν9/ν9=/ΖΖή2ΦύΠν10++%.=4&+532;#"+5326=46960 \g-=%77%=-g\ 0ϋ D@q*&`&9%“*+`+)”%9&`%+q@DηW@  ƒ?ΔέΞΤΕΦΔ]10%".#"'>3232>7Y/,) [!2#/,( ["1ž8.60§ΏM5 #@q ou  ??_]ύΞΦνΤν1074>73#4632#"&³fŽ 3 33 3c$944 449$€$'++''++.”Η`![Ήΐ@2 M #QQS 0P"W" W??έ2ύΖ9/ύ2ΕΦ]νΤν]Τν]Φ]Ζ10+746753.#"3267#5..Y`|-/$S@ES<2|0F-όT|€| h @<<@j ~‚ *7#5354>32.#"κ””ιώ MM4K/#?!$$f&&$fH|2f4BZ6b * βΪ)Ϋ΅%@MΈΰ³MΈΘ³ MΈΐ΄ LΈΰ³MΈΐ@ L@ M M @ L M@ LΈΐ³ MΈΐ@ M@ M M@ MΈΐ΄ L Έΐ@/ L@ M@ M P„$„*+ '„*!„§§??ήνήνήΖ9/ήΐύά]ν]ήΐ10++++++++++++++++++++27'#"&''7&547'764&#"326ϋ,&BS@@TB''BS@@TB$v++++ͺ?Q>$,,$>R@  ?Q>"..">R@°&((&&(( Δθ0!…Ή ΰ@E MD# !!  "#D" ss ????9/93ή2ν2ν2?Φν9=////////993333Φν10+%##5#535#53.'36733#3ΐ‡|ˆˆˆe)&! „3$G% #'^‡‡,hhT>T"LJH@‚HŽ|FLL"T>½J9ͺ$@ n?Ε??ΕΖΦ2ύ2ΦΖ1073#3#½||||¬ώž`ώž1ŒΑh4D„΅'@ M Έΰ@ M=@L5Έΐ@>LF.F5=/@?@@d((F#F8d0044E&5= =5& g1 g?ύΖ?ύΖ9////Ζ]Φ]νΤνΞΦ]ν]99ήν10++++732654&'.5467.54632.#"#"&'>54.R$$(!#%-#=. &d^(V#!=()*₯ d[E`œ 5- 5  &2#$@$,EMb  0q&8-#KG)(SΆ€>  @ 0 ŸŸ?Ν?ΝΦ]έήΝ107"&546323"&54632˜))**¬))))Ά$ $$ $$ $$ $έξ1E‰ΉDΰ³ MCΈΰ³ M?Έΰ@G L: MO94 M7?(_(((G@AF€ €O 0  <2€-<€# ?ν?ν99//]]ννΦύΦ]νή]ν99//9910+]++++%#".54>32.#"3267%4>32#".2>54.#"G%++#  !  ώγ&?Q,+R?&&?R+,Q?&α8-,98--8‹#-.$6( %:=\==\==[==[w.D,+C..C+,D.hG•­ +l@ )@M @MΈΐ³MΈΐ³ MΈΐ@* M!…`-) „0`p,Ÿ }°(%} ?ύΒ/]ν9ν]Φ]νΔή]ν210+++++%2635.#"2#"&54>3254&#"'> ( +:#N4FQ)6 %2 C”F$2 Κ 2>*  N 2*ΓΚ [@ _y R_yΈΐ@ H     ??99=//99=//ή+ΡΙύ]ών]ΩΙΩΙΡΙ10'%'ΊA^^?ŠOB]]@ˆΚ(§§*ΡΟ(§§*Ρ-Yΐ›@ yrƒ?ύΕΦέν10%#5!5!ΐiώΦ“ZΪfq½ƒ7!!qώξ6xέξ1EψΉDΰΆ MDC?Έΰ@! L:@ M: M4 MK4`M@MΈΐ³MΈΐ@tM@M@M@ M‚ @M_  @Hϋ δ ? O  7(?(_(((G‚@HAF€<2€-€/?<€# ?ύώqν?ν99//ν3ΦύΦ+νq2/23ή]ύή]]]+qν+Β2/ι/2/10+++++++]++++]+7#5>32#./32654&#"4>32#".2>54.#"ά6"97(  9  $  Γ&?Q,+R?&&?R+,Q?&α8-,98--8ΞMξ,*0/%2 J=\==\==[==[w.D,+C..C+,D.lΞŒ&Άs“?νΦΝ10!!l ώΰ&XloŒ…@||  }}?ύήνΦύήύΖ102#"&5462654&#"ό5&&5BNP@ „$4 4$HB@Jΐ(γΜ}Ήΐ³ MΈΐ@ Mp €  ΰ  Rp€pΈΐ@& Mp€Up €  @ L@ / ?  U?ύΦ]]+έ]2ύ2Ν]+?Φ]Πέ]2ύ]2έ]ΐ10++7!!3533##5#(€ώ\jjIf’œœfqD‚°7@„„ | °ΐ}t?ύΞ9/]99ν2ΦνΖήΦν103!5467>54&#"'>32y. Œώ/-,.H(F;B(4 R,F& D">qA€³*ί@ "@ M!@ M Έΐ³MΈΐ³MΈΐ@ M@ M(Έΐ³M(Έΐ³M(Έΰ³M(Έΐ³ M(Έΰ³ M(Έΐ@O L@L@M L@ L M―@M „?„,'+($}}, }t?ύΞ9=///ννΞΦΖΪι/Ξ2ΐ/]ν10+]+++++++++++++++++72654+532654#"'>32#"&'7η ?%%'("C $1 $:*E*”$IF%! -* O ˜‘sS΅}?ΝΦΕ10%'7s-žυTCo;ΌΆ87@ Q  °  QΈΐ@ H W ??ν??Φ+2ν2ή]ν1032673#"&'#Ά  | ^30{8$, rώ:  &T|nΗ†>@) 0 ΐ Π ΰ  R 0ΐΠΰR r?ν??9/ΦΤύ]Φν]107.54>32#.#¬LM#A\90e&e 0fό\V0J4 όώ°ύN‘‘TS%#".54>32T6#  #6ϋ,. !! .ŸœgX@   ?ΥΖ?ΦάΕ10#"'73254/>73,!!,-# ")$P . ' ? $ H¦¬;@!@M @L  yys   ?9/999ν2ΦΖύύΕ210++7535'>733Šd%&FMRHQ   N&ώνQJF§dΉ ΐ³M Έΐ³M Έΐ³M Έΐ³M Έΐ³MΈΐ³MΈΐ@M_„„@  ttž?ύΦνΦ]ύΦν]10+++++++%#".54>324&#"326§.@''@..@''@.f%#"'&##%ω*B..B**D..D*+11+)002*ΓΚ 8@         ?Δ?ΔΖ9///999ΥΔ10%'7'7'7'7;A^^?Šώ±B]]@ˆ*(¨§)ΠΠ(¨§)ΠΑο3  ΣΉΐ³MΈΐ³M Έΰ³M Έΐ³M Έΰ³ MΈΰ΄LΈΐ³ MΈΐ³MΈΐ@L M@ L  ―"@"! !!  !   ŒŽ Ž?ν2?Ε2ΕΥΖ?ν????99//9ΦΤν]ΖΦΥ]2ν2Τ‡+‡}Δ10++++++++++%3##5#5>7>73#53#Λ$$P|- ώŸ"2?Uf 3EώΓd=»”?''-+L/3ϊ– ώΘ)ύ•kΑλ3(,o@A @M M*),+*+,―)*)*). |.+-##$-%(-",+ )#Œ"™š ?ν?ύΖ?ν???9ΦΤν]ΒΦΦνΠ‡+Α‡}Δ10++!#&4546?>54#"'>32>73#5%#λΡ)  ): '= $ώ„"2?U«ώΓd=? #&   5(*" ξϊ– yύ•k ½ο7(5:>’@U+ M(@M@M<>=>―;<;<;@ |  @=?(?€ %€  ?>= < ;6:,0/ 5). €?ν?ν2?Υ2ΥΖ????9=///ννΤΖΒ9///93ν2Π‡+‡}Δ10+++32654+532654&#"'>32#"&'3##5#5>73# '; ( 840 *"-3Ώ$$P|-  3WώΓd=z  :  6 ( , †”@&&.*L0@(ύ–j2ƒΒq2@!0@‚‚ 0`pΈ?ν?νΦ]ύΦν]10!'!22ώΤ}ξύ2Šύv$žΣV #"&54632#".=#533267. -- .·&C0A'‚ύ$0$**$&**ύ’6L0fώά*(- T*e@ a,$@,,Έΐ@ H  0QΈΐ@ H+*#Ÿ   ???99//9??ΔΦ+ν]22/2/3+Τ]ΤΕΦν10.'#3>73.7>7 $&rr ‚ *3$:-"  E`$PNBώδlώώDDBDJP("RXX&Ί "4,(2X0   ŸΖU@ @L@LΈΐ@M 0@€Έθ@CMŸΏ@ H!/?Oo`p€/O_ Ÿ ????99?ΔΦΥΦ]]ν]qΦ+]Ε+Πν]q10+++.'#33'>54&'{WK  XώΔ  E`4^^b6ώxj&Z^`,jύ–΄&.($(F& č1g΅Ÿ?ΕΦΕ10#51OgΪΪ€»P9Ά ’?ΕΦήΝ103#"&'52>5ξ_=8# 80.<  £MQΆ Š?ΔΦΥΞ10%#&67mB>,€JR<*(Δ€/P΅Ÿ?ΕΦΕ10#5/MP¬¬^B‘² 7.5467Πm`9ˆ~‚ˆ9`qφ{΅8LKΰ‰ŠηKL8ΌUB˜² %4&'7'>&q`9ˆ‚~ˆ9`mφ|Ό8LKηŠ‰ΰKL8΅q½ƒ7!!qώξ6x/JΕͺ#3―€~Ά`zΤz5E%#".54>3254&#"3267#".54>323275.#"ΤG&A0$9*0.!;+3U?/6 BrS0)FZ2)H6 Ε 8 1O9*J7 &5FuYFlI& W$Y“ol“['6W>ž( Θ"qJ†ͺ!#3!q  ώλͺ`ύ``1JΗͺ3#1~ͺό mJƒͺ!53#5!ƒώκ  Ά` `?J΅ͺ$7;#"&=4&+5326=46;#"»6/ ]hZE66EZh] /ω D@q*&`NJ“*+`+)”JN`%+q@D?J΅ͺ(%.=4&+532;#"+5326=46960 \g-=%77%=-g\ 0ϋ D@q*&`&9%“*+`+)”%9&`%+q@D„#|Ρ%'7![e““eϊ¦0ΦΦ.rk‚‰%#".54>32‚#3 2##2 3#ϊ3((34((46ΜΏ(!!6‰ώw(\Μτ(!!τώ (\›#“Ρ7'7›e““e[’.ΦΦ0¦©ΏO5 74>73#4632#"&΅fŽ 3 33 3c$944 449$€$'++''++2*ΓΚ '%'ΊA^^?ŠOB]]@ˆΚ(§§*ΡΟ(§§*Ρ2*ΓΚ %'7'7'7'7;A^^?Šώ±B]]@ˆ*(¨§)ΠΠ(¨§)ΠEΌ²8 23267#".54>5'4632#".Q*"  * <#"#^.9J*#(##3 K (I  ^/7/'#"$š',  O ͺT@ ŸŸ?Ε?ΕΦΥΦΕ10/'>l6zgl6zTˆ,pDˆ,p‘^V–#+@‚Ο‚$$ !†?ΥήύΦνΦΕΦύΦ]ν10'7#".54>324&#"326R˜‘#    8  T8.Lΰ" "   m‘‡c >@%°o0 JJΟίPJ‹J ‹?ν?νήΕΦ]]ύΦνΤ]]]Ν107#"&54632#"&54632%3#ί"!!"¨""""ώώθθΚ~F†’nb @ J  J ‹?νήΕΦΝΤν10%#"&54632'3#3""""­θθΚ~GJx©|-@J   JJ‹ J‹·?Ε?ν?νΦνΤΕΦ]ν10'4632#"&'4632#"&Εk9xΈ"!!"ν"!!"|˜*ˆ’Jx©|7@!J―ΏJ °ΰJ‹J ‹·?Ε?ν?νΤ]ΕΦύΦ]ν10'7#"&54632#"&54632tx8jr!!!!ν""""Bˆ*˜ΜJ©s JΉΐ΄MΈΐ@"!H J―ΏίJ΄J‹J ‹?ν?ν?ΕΕΕΦύΦ]νΤ+Δ10+7#"&54632#"&54632%77Ό!!!!ν""""ώΞ,UW-„Ίj4@@4ro’…b>Ήΐ³ MΈΰ@ M /?  ˜?ΕήέΞήήΕήΝ]ήΝ10++%#".#"'>323267'3#…  1  Οθθθ  (   \H‹iF΅†?ΝήΝ10%'7iΓΎμ>>Zw}F·†?έΝΝΦΕ10%''7}&\^&„η9669_w}F@ ††?έΕ?ΦΕ107'77ϋ„&^\&`8668M§W C@*JOOJ@  †JΐΠΈ JΐΠΈ?]ν?]ν?ΕΦ]νΤqΕ]Τ]ν10%4632#"&'4632#"&7'5"!!"θ""""“V-^ΥœP5EM§W K@2 J//?O―ΏOJ@†JΐΠΈJΐ Π  Έ?]ν?]ν?ΕΦ]νΤΕ]Τ]qν107#"&54632#"&54632''7Ώ"!!"θ""""_]-UΥ(E5PM§W j@JJί   O _   O_J@P`°ΐ†Ÿ†JΐΠΈJΐ Π  Έ?]ν?]ν?έΕ]?Φ]qνΤΕ]Φ]]]ν107#"&54632#"&54632%77Ώ"!!"θ""""ώύ%1/'VΥ:.##.N™Χ[,<@@&-F #@#`#p##>F7Fp=2W :J(W ?ν?ν9/νΦ]νΤΕνΦ]Δν1074>7.54>3:63#"#".%4.'326 5+$)?,($! #R&  -!;F9Q12Q; :$#5**3€8:88*4$Z "&hH6Z> 32+3"32654&Π{CCCC*+)lwxn"Θ– '300XXcHbώVabWGc― -+)"`•F@    ??ήΕΦΔ107".'73267ϊ6*\""\*6!0##0 «‹Ii΅“?ΝήΝ10'7IGW1KΐΘͺeλ &6%'##6733.>7.546323#"&5473g₯€,Z*†,W)ς  y ώ§ $'B3N #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@ " ""(P"ώ, <.0§eλ &6%'##6733..546323#"&5473g₯€,Z*†,W)ς  y η3B'$ ά #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@0"P("" "ώ <.0ώΧeλ *:%'##6733.%'>7.546323#"&5473g₯€,Z*†,W)ς  y ώάl;Ί " ?0" #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@¬ͺ, €" ""(P"ώ, <.0ώτeλ *:%'##6733.%'.546323#"&5473g₯€,Z*†,W)ς  y ώΫl;.0> " !– #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@¬ͺ, ¦ R("" "ώ <.0eλ *:%'##6733.''7>7.546323#"&5473g₯€,Z*†,W)ς  y ‘~;lώφ! "!@/ή #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@v ,ͺΆ" ""(P"ώ, <.0eλ *:%'##6733.''7.546323#"&5473g₯€,Z*†,W)ς  y ‘;l§0?!" !| #8=_ŽŽΆ.†ˆώΠ²ς"@<>""><@v ,ͺά R("" "ώ <.0\=λ· ,>N'##6733.'.#"#>32>7.546323#"&5473g₯€,Z*†,W)ς  y Τ   E'11'Ρ   ""] #8=_·-‡ˆώΟ²σ#?=>!!>=?s%5##5%    !ώ- ;.0]=λ· ,>N'##6733.'.#"#>32.546323#"&5473g₯€,Z*†,W)ς  y Σ   E'11'h#"   σ #8=_·-‡ˆώΟ²σ#?=>!!>=?s%5##5%€!    ώ ;.0ZeǏ +###335>7.546323#"&5473Η{€{{€ώ $'B3§ #8=_zύ–ώπjττ€" ""(P"ώ, <.0feǏ +###335.546323#"&5473Η{€{{€ώ3B'$ & #8=_zύ–ώπjττΚ"P("" "ώ <.0ώeǏ /###335%'>7.546323#"&5473Η{€{{€ώLl;Ί " ?0r #8=_zύ–ώπjττͺ, €" ""(P"ώ, <.0ώ­eǏ /###335%'.546323#"&5473Η{€{{€ώKl;.0> " !ζ #8=_zύ–ώπjττͺ, ¦ R("" "ώ <.0ώ°eǏ /###335'7>7.546323#"&5473Η{€{{€ώ»~;lώφ! "!@/R #8=_zύ–ώπjττ$ ,ͺΆ" ""(P"ώ, <.0ώžeǏ /###335'7.546323#"&5473Η{€{{€ώΆ;l§0?!" !υ #8=_zύ–ώπjττ$ ,ͺά R("" "ώ <.0ώφ=Η· !3C###335.#"#>32>7.546323#"&5473Η{€{{€ώ}   E'11'Ρ   ""Μ #8=_Rύ•ώοkττ(%5##5%    !ώ- ;.0ώφ=Η· !3C###335.#"#>32.546323#"&5473Η{€{{€ώ}   E'11'h#"   c #8=_Rύ•ώοkττ(%5##5%€!    ώ ;.0keλG>7.546323#"&54734>323#5>54.#"#53.• $'B3– #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Φ" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.D3B'$ E #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%°"P("" "ώ <.0JjDDjJB~7.546323#"&54734>323#5>54.#"#53.zl;Ί " ?0„ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Œͺ, €" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.zl;.0> " !χ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%Œͺ, ¦ R("" "ώ <.0JjDDjJB~7.546323#"&54734>323#5>54.#"#53."~;lώφ! "!@/7 #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%V ,ͺΆ" ""(P"ώ, <.0JjDDjJB~323#5>54.#"#53.!;l§0?!" !Φ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%V ,ͺά R("" "ώ <.0JjDDjJB~32>7.546323#"&54734>323#5>54.#"#53..   E'11'Ρ   ""Γ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%*%5##5%    !ώ- ;.0KjCCjKB~32.546323#"&54734>323#5>54.#"#53./   E'11'h#"   [ #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%*%5##5%€!    ώ ;.0KjCCjKB~""><@ύό <.0-oΗ… ###3353#"&5473Η{€{{€" #8=_„ύ–ώπjττύb <.0 hλŒ73#"&54734>323#5>54.#"#53.* #8=_ώδ)BU-,UC)$*QΧ"5 + + 1&ΩT*%" :.0ŽLjB BjLB~?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a£„…½–θ†Ž‹©€ŠΪƒ“ςσ—ˆΓήρžͺυτφ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNuni00A0uni00AD SF030000.001i.loclkgreenlandic.casenapostrophe.case caron.alt commaaccentrevcommaaccentcaron.alt.short Parenleft ParenrightHyphenSlashAt Bracketleft Backslash Bracketright Braceleft Braceright GuilsinglleftBulletEndashEmdashGuilsinglright Exclamdown GuillemotleftGuillemotright Questiondown double_grave ring_acutedieresis_macron dot_macrondieresis_gravedieresis_acutedieresis_breve tilde_macron acute.asccircumflex.asc caron.ascdieresis_grave.capdieresis_acute.capdieresis_breve.capafii10066.locltengeroublekratka tonos.cap uni1F88.alt uni1F89.alt uni1F8A.alt uni1F8B.alt uni1F8C.alt uni1F8D.alt uni1F8E.alt uni1F8F.alt uni1F98.alt uni1F99.alt uni1F9A.alt uni1F9B.alt uni1F9C.alt uni1F9D.alt uni1F9E.alt uni1F9F.alt uni1FA8.alt uni1FA9.alt uni1FAA.alt uni1FAB.alt uni1FAC.alt uni1FAD.alt uni1FAE.alt uni1FAF.alt uni1FBC.alt uni1FCC.alt uni1FFC.alt SF540000.001 SF530000.001 "}~€Λ Β*cyrlgrek8latnJBGR MKD SRB "AZE 2CRT BMOL RROM RTRK ^afrc2case:loclBloclHloclNnumrTordnZss02` $,4<DLTHLPTblzŽΔ6L6L6L {tu l|DR {tutu{ ‰Š‹ŒŽ‘’˜™š #>?@^`cm}ΰD] <>cyrlgreklatn(ΣΘ!zΙεΎΛΦχλOrocq-9.2.0/doc/tools/rocqrst/notations/TacticNotations.g000066400000000000000000000037301516144147600234000ustar00rootroot00000000000000/************************************************************************/ /* * The Rocq Prover / The Rocq Development Team */ /* v * Copyright INRIA, CNRS and contributors */ /* ' | '%||' | '%|||' | '%||||'; // for SSR PIPE: '|'; ATOM: '@' | '_' | ~[@_{}| ]+; ID: '@' ('_'? [a-zA-Z0-9])+; SUB: '_' '_' [a-zA-Z0-9]+; WHITESPACE: ' '+; rocq-9.2.0/doc/tools/rocqrst/notations/TacticNotations.tokens000066400000000000000000000001541516144147600244520ustar00rootroot00000000000000LALT=1 LGROUP=2 LBRACE=3 RBRACE=4 ESCAPED=5 PIPE=6 ATOM=7 ID=8 SUB=9 WHITESPACE=10 '{|'=1 '{'=3 '}'=4 '|'=6 rocq-9.2.0/doc/tools/rocqrst/notations/TacticNotationsLexer.py000066400000000000000000000075661516144147600246150ustar00rootroot00000000000000# Generated from TacticNotations.g by ANTLR 4.7.2 from antlr4 import * from io import StringIO from typing import TextIO import sys def serializedATN(): with StringIO() as buf: buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\f") buf.write("f\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\3\2\3\2\3\2\3\3\3\3") buf.write("\3\3\3\3\3\3\3\3\5\3!\n\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6") buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3") buf.write("\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6") buf.write("\3\6\5\6F\n\6\3\7\3\7\3\b\3\b\6\bL\n\b\r\b\16\bM\5\bP") buf.write("\n\b\3\t\3\t\5\tT\n\t\3\t\6\tW\n\t\r\t\16\tX\3\n\3\n\3") buf.write("\n\6\n^\n\n\r\n\16\n_\3\13\6\13c\n\13\r\13\16\13d\2\2") buf.write("\f\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\3\2\5") buf.write("\4\2BBaa\6\2\"\"BBaa}\177\5\2\62;C\\c|\2v\2\3\3\2\2\2") buf.write("\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r") buf.write("\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3") buf.write("\2\2\2\3\27\3\2\2\2\5 \3\2\2\2\7\"\3\2\2\2\t$\3\2\2\2") buf.write("\13E\3\2\2\2\rG\3\2\2\2\17O\3\2\2\2\21Q\3\2\2\2\23Z\3") buf.write("\2\2\2\25b\3\2\2\2\27\30\7}\2\2\30\31\7~\2\2\31\4\3\2") buf.write("\2\2\32\33\7}\2\2\33!\7-\2\2\34\35\7}\2\2\35!\7,\2\2\36") buf.write("\37\7}\2\2\37!\7A\2\2 \32\3\2\2\2 \34\3\2\2\2 \36\3\2") buf.write("\2\2!\6\3\2\2\2\"#\7}\2\2#\b\3\2\2\2$%\7\177\2\2%\n\3") buf.write("\2\2\2&\'\7\'\2\2\'F\7}\2\2()\7\'\2\2)F\7\177\2\2*+\7") buf.write("\'\2\2+F\7~\2\2,-\7b\2\2-.\7\'\2\2.F\7}\2\2/\60\7B\2\2") buf.write("\60\61\7\'\2\2\61F\7}\2\2\62\63\7\'\2\2\63\64\7~\2\2\64") buf.write("F\7/\2\2\65\66\7\'\2\2\66\67\7~\2\2\678\7/\2\28F\7@\2") buf.write("\29:\7\'\2\2:;\7~\2\2;F\7~\2\2<=\7\'\2\2=>\7~\2\2>?\7") buf.write("~\2\2?F\7~\2\2@A\7\'\2\2AB\7~\2\2BC\7~\2\2CD\7~\2\2DF") buf.write("\7~\2\2E&\3\2\2\2E(\3\2\2\2E*\3\2\2\2E,\3\2\2\2E/\3\2") buf.write("\2\2E\62\3\2\2\2E\65\3\2\2\2E9\3\2\2\2E<\3\2\2\2E@\3\2") buf.write("\2\2F\f\3\2\2\2GH\7~\2\2H\16\3\2\2\2IP\t\2\2\2JL\n\3\2") buf.write("\2KJ\3\2\2\2LM\3\2\2\2MK\3\2\2\2MN\3\2\2\2NP\3\2\2\2O") buf.write("I\3\2\2\2OK\3\2\2\2P\20\3\2\2\2QV\7B\2\2RT\7a\2\2SR\3") buf.write("\2\2\2ST\3\2\2\2TU\3\2\2\2UW\t\4\2\2VS\3\2\2\2WX\3\2\2") buf.write("\2XV\3\2\2\2XY\3\2\2\2Y\22\3\2\2\2Z[\7a\2\2[]\7a\2\2\\") buf.write("^\t\4\2\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\24") buf.write("\3\2\2\2ac\7\"\2\2ba\3\2\2\2cd\3\2\2\2db\3\2\2\2de\3\2") buf.write("\2\2e\26\3\2\2\2\13\2 EMOSX_d\2") return buf.getvalue() class TacticNotationsLexer(Lexer): atn = ATNDeserializer().deserialize(serializedATN()) decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] LALT = 1 LGROUP = 2 LBRACE = 3 RBRACE = 4 ESCAPED = 5 PIPE = 6 ATOM = 7 ID = 8 SUB = 9 WHITESPACE = 10 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] modeNames = [ "DEFAULT_MODE" ] literalNames = [ "", "'{|'", "'{'", "'}'", "'|'" ] symbolicNames = [ "", "LALT", "LGROUP", "LBRACE", "RBRACE", "ESCAPED", "PIPE", "ATOM", "ID", "SUB", "WHITESPACE" ] ruleNames = [ "LALT", "LGROUP", "LBRACE", "RBRACE", "ESCAPED", "PIPE", "ATOM", "ID", "SUB", "WHITESPACE" ] grammarFileName = "TacticNotations.g" def __init__(self, input=None, output:TextIO = sys.stdout): super().__init__(input, output) self.checkVersion("4.7.2") self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) self._actions = None self._predicates = None rocq-9.2.0/doc/tools/rocqrst/notations/TacticNotationsLexer.tokens000066400000000000000000000001541516144147600254520ustar00rootroot00000000000000LALT=1 LGROUP=2 LBRACE=3 RBRACE=4 ESCAPED=5 PIPE=6 ATOM=7 ID=8 SUB=9 WHITESPACE=10 '{|'=1 '{'=3 '}'=4 '|'=6 rocq-9.2.0/doc/tools/rocqrst/notations/TacticNotationsParser.py000066400000000000000000001020151516144147600247530ustar00rootroot00000000000000# Generated from TacticNotations.g by ANTLR 4.7.2 # encoding: utf-8 from antlr4 import * from io import StringIO from typing import TextIO import sys def serializedATN(): with StringIO() as buf: buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\f") buf.write("\u0081\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\3\2\3\2\3\2\3\3\3\3\5\3&\n\3") buf.write("\3\3\7\3)\n\3\f\3\16\3,\13\3\3\4\3\4\5\4\60\n\4\3\5\3") buf.write("\5\3\5\3\5\3\5\3\5\5\58\n\5\3\6\3\6\5\6<\n\6\3\6\3\6\5") buf.write("\6@\n\6\3\6\3\6\3\7\3\7\5\7F\n\7\3\7\3\7\5\7J\n\7\3\7") buf.write("\3\7\6\7N\n\7\r\7\16\7O\3\b\3\b\5\bT\n\b\3\b\7\bW\n\b") buf.write("\f\b\16\bZ\13\b\3\t\3\t\5\t^\n\t\3\t\3\t\3\t\5\tc\n\t") buf.write("\3\t\3\t\3\n\3\n\5\ni\n\n\3\n\3\n\5\nm\n\n\3\n\3\n\3\13") buf.write("\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\5\17{\n\17\3") buf.write("\20\3\20\5\20\177\n\20\3\20\2\2\21\2\4\6\b\n\f\16\20\22") buf.write("\24\26\30\32\34\36\2\3\3\2\b\t\2\u0086\2 \3\2\2\2\4#\3") buf.write("\2\2\2\6/\3\2\2\2\b\67\3\2\2\2\n9\3\2\2\2\fC\3\2\2\2\16") buf.write("Q\3\2\2\2\20[\3\2\2\2\22f\3\2\2\2\24p\3\2\2\2\26r\3\2") buf.write("\2\2\30t\3\2\2\2\32v\3\2\2\2\34x\3\2\2\2\36|\3\2\2\2 ") buf.write("!\5\4\3\2!\"\7\2\2\3\"\3\3\2\2\2#*\5\6\4\2$&\5\30\r\2") buf.write("%$\3\2\2\2%&\3\2\2\2&\'\3\2\2\2\')\5\6\4\2(%\3\2\2\2)") buf.write(",\3\2\2\2*(\3\2\2\2*+\3\2\2\2+\5\3\2\2\2,*\3\2\2\2-\60") buf.write("\5\24\13\2.\60\5\b\5\2/-\3\2\2\2/.\3\2\2\2\60\7\3\2\2") buf.write("\2\618\5\34\17\2\628\5\32\16\2\638\5\36\20\2\648\5\n\6") buf.write("\2\658\5\20\t\2\668\5\22\n\2\67\61\3\2\2\2\67\62\3\2\2") buf.write("\2\67\63\3\2\2\2\67\64\3\2\2\2\67\65\3\2\2\2\67\66\3\2") buf.write("\2\28\t\3\2\2\29;\7\3\2\2:<\7\f\2\2;:\3\2\2\2;<\3\2\2") buf.write("\2<=\3\2\2\2=?\5\f\7\2>@\7\f\2\2?>\3\2\2\2?@\3\2\2\2@") buf.write("A\3\2\2\2AB\7\6\2\2B\13\3\2\2\2CM\5\16\b\2DF\7\f\2\2E") buf.write("D\3\2\2\2EF\3\2\2\2FG\3\2\2\2GI\5\26\f\2HJ\7\f\2\2IH\3") buf.write("\2\2\2IJ\3\2\2\2JK\3\2\2\2KL\5\16\b\2LN\3\2\2\2ME\3\2") buf.write("\2\2NO\3\2\2\2OM\3\2\2\2OP\3\2\2\2P\r\3\2\2\2QX\5\b\5") buf.write("\2RT\5\30\r\2SR\3\2\2\2ST\3\2\2\2TU\3\2\2\2UW\5\b\5\2") buf.write("VS\3\2\2\2WZ\3\2\2\2XV\3\2\2\2XY\3\2\2\2Y\17\3\2\2\2Z") buf.write("X\3\2\2\2[]\7\4\2\2\\^\t\2\2\2]\\\3\2\2\2]^\3\2\2\2^_") buf.write("\3\2\2\2_`\7\f\2\2`b\5\4\3\2ac\7\f\2\2ba\3\2\2\2bc\3\2") buf.write("\2\2cd\3\2\2\2de\7\6\2\2e\21\3\2\2\2fh\7\5\2\2gi\5\30") buf.write("\r\2hg\3\2\2\2hi\3\2\2\2ij\3\2\2\2jl\5\4\3\2km\5\30\r") buf.write("\2lk\3\2\2\2lm\3\2\2\2mn\3\2\2\2no\7\6\2\2o\23\3\2\2\2") buf.write("pq\7\b\2\2q\25\3\2\2\2rs\7\b\2\2s\27\3\2\2\2tu\7\f\2\2") buf.write("u\31\3\2\2\2vw\7\7\2\2w\33\3\2\2\2xz\7\t\2\2y{\7\13\2") buf.write("\2zy\3\2\2\2z{\3\2\2\2{\35\3\2\2\2|~\7\n\2\2}\177\7\13") buf.write("\2\2~}\3\2\2\2~\177\3\2\2\2\177\37\3\2\2\2\23%*/\67;?") buf.write("EIOSX]bhlz~") return buf.getvalue() class TacticNotationsParser ( Parser ): grammarFileName = "TacticNotations.g" atn = ATNDeserializer().deserialize(serializedATN()) decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] sharedContextCache = PredictionContextCache() literalNames = [ "", "'{|'", "", "'{'", "'}'", "", "'|'" ] symbolicNames = [ "", "LALT", "LGROUP", "LBRACE", "RBRACE", "ESCAPED", "PIPE", "ATOM", "ID", "SUB", "WHITESPACE" ] RULE_top = 0 RULE_blocks = 1 RULE_block = 2 RULE_nopipeblock = 3 RULE_alternative = 4 RULE_altblocks = 5 RULE_altblock = 6 RULE_repeat = 7 RULE_curlies = 8 RULE_pipe = 9 RULE_altsep = 10 RULE_whitespace = 11 RULE_escaped = 12 RULE_atomic = 13 RULE_hole = 14 ruleNames = [ "top", "blocks", "block", "nopipeblock", "alternative", "altblocks", "altblock", "repeat", "curlies", "pipe", "altsep", "whitespace", "escaped", "atomic", "hole" ] EOF = Token.EOF LALT=1 LGROUP=2 LBRACE=3 RBRACE=4 ESCAPED=5 PIPE=6 ATOM=7 ID=8 SUB=9 WHITESPACE=10 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) self.checkVersion("4.7.2") self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) self._predicates = None class TopContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def blocks(self): return self.getTypedRuleContext(TacticNotationsParser.BlocksContext,0) def EOF(self): return self.getToken(TacticNotationsParser.EOF, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_top def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitTop" ): return visitor.visitTop(self) else: return visitor.visitChildren(self) def top(self): localctx = TacticNotationsParser.TopContext(self, self._ctx, self.state) self.enterRule(localctx, 0, self.RULE_top) try: self.enterOuterAlt(localctx, 1) self.state = 30 self.blocks() self.state = 31 self.match(TacticNotationsParser.EOF) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class BlocksContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def block(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.BlockContext) else: return self.getTypedRuleContext(TacticNotationsParser.BlockContext,i) def whitespace(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.WhitespaceContext) else: return self.getTypedRuleContext(TacticNotationsParser.WhitespaceContext,i) def getRuleIndex(self): return TacticNotationsParser.RULE_blocks def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitBlocks" ): return visitor.visitBlocks(self) else: return visitor.visitChildren(self) def blocks(self): localctx = TacticNotationsParser.BlocksContext(self, self._ctx, self.state) self.enterRule(localctx, 2, self.RULE_blocks) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 33 self.block() self.state = 40 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,1,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: self.state = 35 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 34 self.whitespace() self.state = 37 self.block() self.state = 42 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,1,self._ctx) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class BlockContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def pipe(self): return self.getTypedRuleContext(TacticNotationsParser.PipeContext,0) def nopipeblock(self): return self.getTypedRuleContext(TacticNotationsParser.NopipeblockContext,0) def getRuleIndex(self): return TacticNotationsParser.RULE_block def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitBlock" ): return visitor.visitBlock(self) else: return visitor.visitChildren(self) def block(self): localctx = TacticNotationsParser.BlockContext(self, self._ctx, self.state) self.enterRule(localctx, 4, self.RULE_block) try: self.state = 45 self._errHandler.sync(self) token = self._input.LA(1) if token in [TacticNotationsParser.PIPE]: self.enterOuterAlt(localctx, 1) self.state = 43 self.pipe() pass elif token in [TacticNotationsParser.LALT, TacticNotationsParser.LGROUP, TacticNotationsParser.LBRACE, TacticNotationsParser.ESCAPED, TacticNotationsParser.ATOM, TacticNotationsParser.ID]: self.enterOuterAlt(localctx, 2) self.state = 44 self.nopipeblock() pass else: raise NoViableAltException(self) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class NopipeblockContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def atomic(self): return self.getTypedRuleContext(TacticNotationsParser.AtomicContext,0) def escaped(self): return self.getTypedRuleContext(TacticNotationsParser.EscapedContext,0) def hole(self): return self.getTypedRuleContext(TacticNotationsParser.HoleContext,0) def alternative(self): return self.getTypedRuleContext(TacticNotationsParser.AlternativeContext,0) def repeat(self): return self.getTypedRuleContext(TacticNotationsParser.RepeatContext,0) def curlies(self): return self.getTypedRuleContext(TacticNotationsParser.CurliesContext,0) def getRuleIndex(self): return TacticNotationsParser.RULE_nopipeblock def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitNopipeblock" ): return visitor.visitNopipeblock(self) else: return visitor.visitChildren(self) def nopipeblock(self): localctx = TacticNotationsParser.NopipeblockContext(self, self._ctx, self.state) self.enterRule(localctx, 6, self.RULE_nopipeblock) try: self.state = 53 self._errHandler.sync(self) token = self._input.LA(1) if token in [TacticNotationsParser.ATOM]: self.enterOuterAlt(localctx, 1) self.state = 47 self.atomic() pass elif token in [TacticNotationsParser.ESCAPED]: self.enterOuterAlt(localctx, 2) self.state = 48 self.escaped() pass elif token in [TacticNotationsParser.ID]: self.enterOuterAlt(localctx, 3) self.state = 49 self.hole() pass elif token in [TacticNotationsParser.LALT]: self.enterOuterAlt(localctx, 4) self.state = 50 self.alternative() pass elif token in [TacticNotationsParser.LGROUP]: self.enterOuterAlt(localctx, 5) self.state = 51 self.repeat() pass elif token in [TacticNotationsParser.LBRACE]: self.enterOuterAlt(localctx, 6) self.state = 52 self.curlies() pass else: raise NoViableAltException(self) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class AlternativeContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def LALT(self): return self.getToken(TacticNotationsParser.LALT, 0) def altblocks(self): return self.getTypedRuleContext(TacticNotationsParser.AltblocksContext,0) def RBRACE(self): return self.getToken(TacticNotationsParser.RBRACE, 0) def WHITESPACE(self, i:int=None): if i is None: return self.getTokens(TacticNotationsParser.WHITESPACE) else: return self.getToken(TacticNotationsParser.WHITESPACE, i) def getRuleIndex(self): return TacticNotationsParser.RULE_alternative def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitAlternative" ): return visitor.visitAlternative(self) else: return visitor.visitChildren(self) def alternative(self): localctx = TacticNotationsParser.AlternativeContext(self, self._ctx, self.state) self.enterRule(localctx, 8, self.RULE_alternative) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 55 self.match(TacticNotationsParser.LALT) self.state = 57 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 56 self.match(TacticNotationsParser.WHITESPACE) self.state = 59 self.altblocks() self.state = 61 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 60 self.match(TacticNotationsParser.WHITESPACE) self.state = 63 self.match(TacticNotationsParser.RBRACE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class AltblocksContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def altblock(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.AltblockContext) else: return self.getTypedRuleContext(TacticNotationsParser.AltblockContext,i) def altsep(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.AltsepContext) else: return self.getTypedRuleContext(TacticNotationsParser.AltsepContext,i) def WHITESPACE(self, i:int=None): if i is None: return self.getTokens(TacticNotationsParser.WHITESPACE) else: return self.getToken(TacticNotationsParser.WHITESPACE, i) def getRuleIndex(self): return TacticNotationsParser.RULE_altblocks def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitAltblocks" ): return visitor.visitAltblocks(self) else: return visitor.visitChildren(self) def altblocks(self): localctx = TacticNotationsParser.AltblocksContext(self, self._ctx, self.state) self.enterRule(localctx, 10, self.RULE_altblocks) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 65 self.altblock() self.state = 75 self._errHandler.sync(self) _alt = 1 while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt == 1: self.state = 67 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 66 self.match(TacticNotationsParser.WHITESPACE) self.state = 69 self.altsep() self.state = 71 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 70 self.match(TacticNotationsParser.WHITESPACE) self.state = 73 self.altblock() else: raise NoViableAltException(self) self.state = 77 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class AltblockContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def nopipeblock(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.NopipeblockContext) else: return self.getTypedRuleContext(TacticNotationsParser.NopipeblockContext,i) def whitespace(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.WhitespaceContext) else: return self.getTypedRuleContext(TacticNotationsParser.WhitespaceContext,i) def getRuleIndex(self): return TacticNotationsParser.RULE_altblock def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitAltblock" ): return visitor.visitAltblock(self) else: return visitor.visitChildren(self) def altblock(self): localctx = TacticNotationsParser.AltblockContext(self, self._ctx, self.state) self.enterRule(localctx, 12, self.RULE_altblock) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 79 self.nopipeblock() self.state = 86 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,10,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: self.state = 81 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 80 self.whitespace() self.state = 83 self.nopipeblock() self.state = 88 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,10,self._ctx) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class RepeatContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def LGROUP(self): return self.getToken(TacticNotationsParser.LGROUP, 0) def WHITESPACE(self, i:int=None): if i is None: return self.getTokens(TacticNotationsParser.WHITESPACE) else: return self.getToken(TacticNotationsParser.WHITESPACE, i) def blocks(self): return self.getTypedRuleContext(TacticNotationsParser.BlocksContext,0) def RBRACE(self): return self.getToken(TacticNotationsParser.RBRACE, 0) def ATOM(self): return self.getToken(TacticNotationsParser.ATOM, 0) def PIPE(self): return self.getToken(TacticNotationsParser.PIPE, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_repeat def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitRepeat" ): return visitor.visitRepeat(self) else: return visitor.visitChildren(self) def repeat(self): localctx = TacticNotationsParser.RepeatContext(self, self._ctx, self.state) self.enterRule(localctx, 14, self.RULE_repeat) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 89 self.match(TacticNotationsParser.LGROUP) self.state = 91 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.PIPE or _la==TacticNotationsParser.ATOM: self.state = 90 _la = self._input.LA(1) if not(_la==TacticNotationsParser.PIPE or _la==TacticNotationsParser.ATOM): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) self.consume() self.state = 93 self.match(TacticNotationsParser.WHITESPACE) self.state = 94 self.blocks() self.state = 96 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 95 self.match(TacticNotationsParser.WHITESPACE) self.state = 98 self.match(TacticNotationsParser.RBRACE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class CurliesContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def LBRACE(self): return self.getToken(TacticNotationsParser.LBRACE, 0) def blocks(self): return self.getTypedRuleContext(TacticNotationsParser.BlocksContext,0) def RBRACE(self): return self.getToken(TacticNotationsParser.RBRACE, 0) def whitespace(self, i:int=None): if i is None: return self.getTypedRuleContexts(TacticNotationsParser.WhitespaceContext) else: return self.getTypedRuleContext(TacticNotationsParser.WhitespaceContext,i) def getRuleIndex(self): return TacticNotationsParser.RULE_curlies def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitCurlies" ): return visitor.visitCurlies(self) else: return visitor.visitChildren(self) def curlies(self): localctx = TacticNotationsParser.CurliesContext(self, self._ctx, self.state) self.enterRule(localctx, 16, self.RULE_curlies) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 100 self.match(TacticNotationsParser.LBRACE) self.state = 102 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 101 self.whitespace() self.state = 104 self.blocks() self.state = 106 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.WHITESPACE: self.state = 105 self.whitespace() self.state = 108 self.match(TacticNotationsParser.RBRACE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class PipeContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def PIPE(self): return self.getToken(TacticNotationsParser.PIPE, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_pipe def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitPipe" ): return visitor.visitPipe(self) else: return visitor.visitChildren(self) def pipe(self): localctx = TacticNotationsParser.PipeContext(self, self._ctx, self.state) self.enterRule(localctx, 18, self.RULE_pipe) try: self.enterOuterAlt(localctx, 1) self.state = 110 self.match(TacticNotationsParser.PIPE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class AltsepContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def PIPE(self): return self.getToken(TacticNotationsParser.PIPE, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_altsep def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitAltsep" ): return visitor.visitAltsep(self) else: return visitor.visitChildren(self) def altsep(self): localctx = TacticNotationsParser.AltsepContext(self, self._ctx, self.state) self.enterRule(localctx, 20, self.RULE_altsep) try: self.enterOuterAlt(localctx, 1) self.state = 112 self.match(TacticNotationsParser.PIPE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class WhitespaceContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def WHITESPACE(self): return self.getToken(TacticNotationsParser.WHITESPACE, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_whitespace def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitWhitespace" ): return visitor.visitWhitespace(self) else: return visitor.visitChildren(self) def whitespace(self): localctx = TacticNotationsParser.WhitespaceContext(self, self._ctx, self.state) self.enterRule(localctx, 22, self.RULE_whitespace) try: self.enterOuterAlt(localctx, 1) self.state = 114 self.match(TacticNotationsParser.WHITESPACE) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class EscapedContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def ESCAPED(self): return self.getToken(TacticNotationsParser.ESCAPED, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_escaped def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitEscaped" ): return visitor.visitEscaped(self) else: return visitor.visitChildren(self) def escaped(self): localctx = TacticNotationsParser.EscapedContext(self, self._ctx, self.state) self.enterRule(localctx, 24, self.RULE_escaped) try: self.enterOuterAlt(localctx, 1) self.state = 116 self.match(TacticNotationsParser.ESCAPED) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class AtomicContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def ATOM(self): return self.getToken(TacticNotationsParser.ATOM, 0) def SUB(self): return self.getToken(TacticNotationsParser.SUB, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_atomic def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitAtomic" ): return visitor.visitAtomic(self) else: return visitor.visitChildren(self) def atomic(self): localctx = TacticNotationsParser.AtomicContext(self, self._ctx, self.state) self.enterRule(localctx, 26, self.RULE_atomic) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 118 self.match(TacticNotationsParser.ATOM) self.state = 120 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.SUB: self.state = 119 self.match(TacticNotationsParser.SUB) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx class HoleContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): super().__init__(parent, invokingState) self.parser = parser def ID(self): return self.getToken(TacticNotationsParser.ID, 0) def SUB(self): return self.getToken(TacticNotationsParser.SUB, 0) def getRuleIndex(self): return TacticNotationsParser.RULE_hole def accept(self, visitor:ParseTreeVisitor): if hasattr( visitor, "visitHole" ): return visitor.visitHole(self) else: return visitor.visitChildren(self) def hole(self): localctx = TacticNotationsParser.HoleContext(self, self._ctx, self.state) self.enterRule(localctx, 28, self.RULE_hole) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) self.state = 122 self.match(TacticNotationsParser.ID) self.state = 124 self._errHandler.sync(self) _la = self._input.LA(1) if _la==TacticNotationsParser.SUB: self.state = 123 self.match(TacticNotationsParser.SUB) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) self._errHandler.recover(self, re) finally: self.exitRule() return localctx rocq-9.2.0/doc/tools/rocqrst/notations/TacticNotationsVisitor.py000066400000000000000000000060341516144147600251620ustar00rootroot00000000000000# Generated from TacticNotations.g by ANTLR 4.7.2 from antlr4 import * if __name__ is not None and "." in __name__: from .TacticNotationsParser import TacticNotationsParser else: from TacticNotationsParser import TacticNotationsParser # This class defines a complete generic visitor for a parse tree produced by TacticNotationsParser. class TacticNotationsVisitor(ParseTreeVisitor): # Visit a parse tree produced by TacticNotationsParser#top. def visitTop(self, ctx:TacticNotationsParser.TopContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#blocks. def visitBlocks(self, ctx:TacticNotationsParser.BlocksContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#block. def visitBlock(self, ctx:TacticNotationsParser.BlockContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#nopipeblock. def visitNopipeblock(self, ctx:TacticNotationsParser.NopipeblockContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#alternative. def visitAlternative(self, ctx:TacticNotationsParser.AlternativeContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#altblocks. def visitAltblocks(self, ctx:TacticNotationsParser.AltblocksContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#altblock. def visitAltblock(self, ctx:TacticNotationsParser.AltblockContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#repeat. def visitRepeat(self, ctx:TacticNotationsParser.RepeatContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#curlies. def visitCurlies(self, ctx:TacticNotationsParser.CurliesContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#pipe. def visitPipe(self, ctx:TacticNotationsParser.PipeContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#altsep. def visitAltsep(self, ctx:TacticNotationsParser.AltsepContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#whitespace. def visitWhitespace(self, ctx:TacticNotationsParser.WhitespaceContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#escaped. def visitEscaped(self, ctx:TacticNotationsParser.EscapedContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#atomic. def visitAtomic(self, ctx:TacticNotationsParser.AtomicContext): return self.visitChildren(ctx) # Visit a parse tree produced by TacticNotationsParser#hole. def visitHole(self, ctx:TacticNotationsParser.HoleContext): return self.visitChildren(ctx) del TacticNotationsParser rocq-9.2.0/doc/tools/rocqrst/notations/UbuntuMono-B.ttf000066400000000000000000005656501516144147600231510ustar00rootroot00000000000000DSIGyacx0GSUBZΈ©<)Vτ[[™TUj/Y§―τΌΌŠŒΌŠέ2ϊ  ΰP [DAMA ύ΅[1>ͺ ŸV΅ τ2§W"Ί^U.(~q‘/#0+)#.1&-‘v-((E 66??-6*-G.66('  .q1m˜,>,$!?$1?$??Y6$; C?½?~ >:p („)r6Z6› §.& ½1Sh2-qll(qq˜;‘ŸJ2 E ????6666.<'''' 6,,,,,,,$$$$(?(;;;;? , , ,,,,,6 ?????!!!!-76$6$6$6$6$$7*1-?-?G$G$G$G$φ$.?.?.? ζ.?6Y6#6Y(6(6(6$$$';';';';';'; .C.C.C‹(6$1°pji³‘£C   fYqbkjfqqYqbkj5    ( (§ 1(,,fqqYqbkjfqqYqbkjΔ€‘Δ^Uq/q1m??„r6›©22E6?ςό(?Μ  6-?;Ό??6(6 $ $') ' .C(6-$5?½\§ -7 ,6$';';';';'; , , !!-71 !6.? ,  , ,<?6$6$,O6Y';';"K-7-.C ,? $$ 'ό$C7< 6*1 iO‘m†JJJo‹wwMMM??$(66*.-.- 66$? ..---6 --"6*,(DY3???;??,&?+ "6Y'6$$1.???.?6?$Y$-? 3-?-;-;$$,&   -+-6? 6 -?-;-;-+6 , , ? 3.?.?*-+$Y""` 6$ ?.-6- . -6   (6@6?$?;5??-$3θ{jm6€Z €(@?$$$33&—«&((((((((ΰΛώϋ6)wx@@@@@@k{ώ€ώΏώΓώ²????????Zfώώ­ώ°ώžώφώφ$$$$$$$$d`ώ™ώ΅ώΉώ§ώώώ}`ώ™ώ΅ώΟώΊ33333333rώΗώšώΫkGώ~ώœώΛώ½ώώώ((@@??$$33((((((((ͺžώΕώβώχώκ..????????Q]ώ‡ώ€ώ§ώ›ώΰώΰkGώ~ώœώΛώ½ώώώ((((((( g‹ «€«i^?????9B'1@Nn$$$$66%OHn33&&??33 7'W&&…Dώϊ3 …«ͺ§ώΧώτ\]Zfώώ­ώ°ώžώφώφkGώ~ώœώΛώ½ώώώ - .9[ ‚‚‚‚‚‚‚ ψώ ώ ώ ώ ώ ώ ώ ύύύύύύόόόόόόϋϋϋϋϋ ϋ!ϊ"ϊ#ϊ$ϊ%ϊ& ϊ' ω("ω)"ω*$ψ+%ψ,%ψ-&ψ.'χ/(χ0)χ1)χ2*χ3+χ4+φ5-φ6.φ7.φ8/φ90φ:1υ;2υ<2υ=3υ>4υ?5υ@6τA6τB7τC8τD9τE:τF;σG;σH<σI=σJ>σK?σL@ςMAςNAςOBςPCςQDςRDρSFρTFρUGρVHρWIρXIπYJπZKπ[Lπ\Mπ]Nπ^Nο_Oο`PοaQοbRοcSοdSξeTξfUξgVξhWξiXξjXξkYνlZνm[νn\νo\νp^νq^μr_μs`λtaλuaλvbλwdλxeλyeλzfκ{fκ|gκ}hκ~jκjκ€kκkκ‚lκƒmκ„nκ…nι†pι‡pιˆqι‰rιŠsι‹sθŒuθvθŽvθwθxθ‘xη’yη“zη”{η•|η–}ζ—}ζ˜ζ™ζš€ζ›ζœ‚εƒεž„εŸ„ε …ε‘†ε’‡δ£ˆδ€‰δ₯‰δ¦Šγ§‹γ¨‹γ©ŒγͺŽγ«Žβ¬β­β‘β―‘β°’β±“α²”α³•α΄–α΅–αΆ—α·˜αΈ™ΰΉšΰΊ›ΰ»›ΰΌœΰ½ΰΎžίΏŸίΐ ίΑ‘ίΒ‘ίΓ’ίΔ£ήΕ€ήΖ₯ήΗ¦ήΘ¦ήΙ§ήΚ¨έΛ©έΜ©έΝ«έΞ¬έΟ¬έΠ­έΡάάΣ―άΤ°άΥ²άΦ²άΧ³ΫΨ³ΫΩ΄ΫΪ΅ΫΫΆΫά·ΫέΈΪήΉΪίΉΪΰΊΪα»ΪβΌΪγ½ΩδΎΩεΎΩζΏΩηΐΩθΑΩιΑΨκΓΨλΔΨμΔΨνΕΨξΖΨοΖΧπΗΧρΙΧςΙΧσΚΧτΛΧυΜΦφΜΦχΝΦψΞΦωΟΦϊΠΥϋΡΥόΥύΥώΣΥΤΥ|`β€b ~17HQS_aw‘’67O’ΌΗΙέ†ŠŒ‘©°ΙΞ_cuω…σEMWY[]}΄ΔΣΫοτώ    " & 0 : D p y ‰ ¬ ΄ Ή!!!"!&!.!^""""""""+"H"`"e%%% %%%%%$%,%4%<%l%ˆ%“%Κΰούπυψϋύ   28IRT`bx€’“78’ΌΖΙΨ„ˆŒŽ‘£ͺ±ΚbrŠ€ς HPY[]_€ΆΖΦέςφ    & 0 9 D p t € ¬ ΄ Ή!!!"!&!.!S""""""""+"H"`"d%%% %%%%%$%,%4%<%P%ˆ%‘%Κΰούπυψ ϋύωυδγΫάέήάΪYώXAT&Sώ’ώ—“;;ψώ³ώ²ώ€ώβζβzδΩδΧδΥδΣδΡδΠδΟδΞδΝδΛδΚδΙδΗδΖδΔδΓΰ@ΰ:α*ΰΰόΰφίΆβίβΨδ$ΰmβtίTΰxΰSί˜ί•ίί‹ίˆί…ίyί]ίFίCίζίγίΨίήίΟίΚίΞίΓίΌί΅ί―ί‚ίzΫί#ίδ ˆ €γΠΠΠΜΜΤΤΤήΊΎΒΖΖΎœΚΚmykwzRSTUVWXi_abcdueΦΨΒΘΚΠΖΙΛΜΝΞΤΟΡΣΥst‹nocpqeghrlx‚ƒˆ‰Š‹Œ„…†‡Ÿχφ υσύςόπϊοωτώρϋψίͺ¬«­   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aŸ ’€¬±·Ό»½ΏΎΐΒΔΓΕΖΘΗΙΚΜΞΝΟΡΠΥΤΦΧg‹}~‚r‘Ί‰„vƒ¦‘³£Œ§¨€šœΈ€…•žΑӚ|‡’d₯›†–f{›ž°mystpqno©Ϊznblx«­h’cej₯œ¦£¨©ͺ§―­΅Ά΄ iuŠabc“ed_@?XUTSRQPONMLKJIHGFEDCBA@?>=<;:98765/.-,(&%$#" ,E#F` °&`°&#HH-,E#F#a °&a°&#HH-,E#F`° a °F`°&#HH-,E#F#a° ` °&a° a°&#HH-,E#F`°@a °f`°&#HH-,E#F#a°@` °&a°@a°&#HH-, <<-, E# °ΝD# ΈZQX# °D#Y °νQX# °MD#Y °&QX# ° D#Y!!-, EhD °` E°FvhŠE`D-,± C#Ce -,± C#C -,°(#p±(>°(#p±(E:± -, E°%Ead°PQXED!!Y-, E°C`D-,°C°Ce -, i°@a°‹ ±,ΐŠŒΈb`+ d#da\X°aY-,ŠEŠŠ‡°+°)#D°)zδ-,Ee°,#DE°+#D-,KRXED!!Y-,°%# Šυ°`#νμ-,°%# Šυ°a#νμ-,°%υνμ-, °` <<-, °a <<-,°C°C -,!! d#d‹Έ@b-,!°€QX d#d‹Έ b²@/+Y°`-,!°ΐQX d#d‹ΈUb²€/+Y°`-, d#d‹Έ@b`#!-,E#E`#E`#E`#vh°€b -,°&°&°%°%E#E °&`bch °&aeŠ#DD-, E°TX°@D E°@aD!!Y-,E±0/E#Ea`°`iD-,KQX°/#p°#B!!Y-,KQX °%EiSXD!!Y!!Y-,E°C°`c°`iD-,°/ED-,E# EŠ`D-,E#E`D-,K#QXΉ3ΰ±4 ³34YDD-,°CX°&EŠXdf°`d° `f X!°@Y°aY#XeY°)#D#°)ΰ!!!!!Y-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°% F°%°`#B< XY°%°%°)ΰ°%°%°)ΰ°%°% XY°%°%CH°%°%°`CH!Y!!!!!!!-,°CX°%Ed° `f X!°@Y°a#XeY°)#D°%°% XY°%°% F°%#B<°%°%°%°% F°%°`#B< XY°%°%°)ΰ°) EeD°%°%°)ΰ°%°% XY°%°%CH°%°%°%°%°`CH!Y!!!!!!!-,°% F°%#B°%°%EH!!!!-,°% °%°%CH!!!-,E# E °P X#e#Y#h °@PX!°@Y#XeYŠ`D-,KS#KQZX EŠ`D!!Y-,KTX EŠ`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,°CTX°F+!!!!Y-,°CTX°G+!!!Y-,°CTX°H+!!!!Y-,°CTX°I+!!!Y-, Š#KSŠKQZX#8!!Y-, ŠI°QX°@# Š84!!Y-,F#F`#Fa#  FŠaΈ€bб@@ŠpE`h:-, Š#IdŠ#SX<!Y-,KRX}zY-,°KKTB-,±B±#ˆQ±@ˆSZXΉ ˆTX±BYY-,Eh#KQX# E d°@PX|YhŠ`YD-,°°%°%°#>°#>± ° #eB° #B°#?°#?± °#eB°#B°-@ vn)uodtrdrC)qodpndoBnBia)gedeC)dBcadaBYQ)XBWUdUC)TBSQdRBQBLD)JHdHC)FDdDBCA/B?Bœ* * U*Uœœ*U * U*U*U *U*UTSΈ³ΈKΈRK°P[°ˆ°%S°ˆ°@QZ°ˆ°UZ[X±ŽY…BK°SX° YK°€SX°±BY++++++++t+++s++++++++++++++++++++++++++++°kkυσΦ σ[ύ»[||f|P}fPkr{d}›fk›{}ofk{Ž}¦fTk¦vf³³PP<<::dd_@Ÿ~ΖrϊϋU*ΨW‡!ŒŒ‡£Gxo{΅ͺ9j•Z\Ά.rΣΎ+z4Y*CrrQY§τέ\\\\ΜX ό„ |Π$ 8 π P |  \  ˆ ,¨Txά tΌΠθ|`όœˆ(θXά(ψ„   !H""π#4#΄$€&l'$'¨(L( (θ)<)Œ)Ό)θ*Δ+„,,Ψ-¨.P//˜0H0ψ1 233„4 4 5<5€6€7@7°8@9ό:t;;€<@<„=8=Έ>Έ??ΐ@XA A€B4B˜DˆD΄EEμFHF¬GLGτHLHxH€I˜J”JΌK<L\LLMMΘNŒOθPΜQR\RΘTUU˜UΠUΰWœWΘX<XπY„Zΰ[ [”\\,\˜] ]Π^@_ˆ`ˆaΤb¨bΨcc0c\cdΨeΐf¬fάg g<gpg gΠgόh0hτi iPi|i¨iΤjj°kΐkπllHl|l¨m<nTn|n€nΜnτo$oPpΐq¨qΤqόr$rTr€r¬rΨs t t4t`tˆt°tΨuuΐvvΌvδw w<wdxxDxpx˜xΔxμyΈzΠzό{${P{x{€{Μ{ψ| |P}}}Δ}τ~~L~t~€~Μˆ€ €Π€ψ$Lx Μτ‚‚@‚lƒƒΌ„Δ„π……H…t… …Μ†ˆ‡p‡œˆˆ(ˆΈ‰Δ‰πŠŠ@Šh‹P‹Μ‹όŒ„Œ¬ŒΠŒτ ŽPŽΘ\ˆ°Ψ,X‘P‘p’’ ’Μ’τ“ “H“|“¬“ά””,”T”„”¬”Ψ••,•T–˜˜˜Έ™΄™ΰšš˜›œ›Θ›πœœDœpœ˜΄θžžΔŸxŸ€ŸΜŸψ   L t   Μ ψ‘ ‘˜‘ΐ‘θ’’4’œ’θ£H£t£Τ€€˜€ψ₯H₯x₯€₯Π₯ψ¦,¦\¦Œ¦Έ¦π§Œ¨ ¨ό©ΨͺH«¬€¬”¬¨¬Ό¬Π¬δ¬ψ­ ­ ­4­Hτ°T±ψ³x΅`· ΉHΊ„Ό<ΎΏtΐ¬Β`Γ\ĈΖΗ,ȌΙάΛ@ΜΔΞDΟθΡ Σ€Τ`ΤΰΥ0հ֘ΦΘΦΨΧΧ”ΨtΩΩ0Ω°Ϊ,ΪΌΫ€ά|܌έ|݌ݜݬݼέΜέάέμέόή ήή,ή@ήTήhή|ސހ޸ήΜήΰήτί ίhί€ίΠίΰίπΰΰΰ ΰ0ΰ@ΰPΰ`ΰpΰ€ΰΰ ΰ°ΰΐΰΤΰδΰτααθβΤγŒδTεε€ζ4ηη¬ηΌθŒι(ιΌκΐλ<μννŒξPο@ππ ρHςςΠσhτ8υLυόφlχLχψψ¬ω”ϊϋHϋψό΄ύˆώŒώœp@ XΠl΄d<0,P  τ ΄ Œ | 8 όδt„œ<L€Έœ|œHd¨Τό(T€¨ΤόHPˆΨ H €!l#l#€$Π%%,%T&H'X'„'¬'ά( )p*@*l*”*Δ*μ+,-. .8.`/4/ΐ/π01d1Œ1Έ1ΰ2202d2”2ΐ2θ33P3€3¨3ά44<4h4œ4Π4ό5$5X5Œ5Ό5δ66L6x6 7€8D8p99„:Œ;œ<°=p>>H>p?D@@BBHC€CΤDD(ELE|E¨EΠFŒG¨H΄IΈJΈKpLtMhMΜNPO\PPŒQ R8S8SHSπUU VˆW@WμX¨Y0ZL[d\\l\°]L]δ^8^ΐ_T`` `Μaa<aάb€cLcxc¬dpdœe8eHeXeŒeœflg<gΔgτh hLhΈhΘiditiΠjΔjΤkΐlτmhm”m€nn$n4nDn n°nΐnΠo€p\plpψqˆqπr„ssΰtpuvv¬vΌw¨xΔy y΄yΔzΈ{”||0|ά}H~,~~ (xˆ€t€„€θ\ά‚ƒ@„ „΄…h†P†ό‡(‡Xˆ4ˆ\‰‰ ‰0‰d‰tŠH‹(‹8‹d‹‹ΈŒ,Θސx‘0‘Μ’Έ“€”l•X–$–ΰ—<—˜˜h™™ΜšΜ›΄ ž4žΤŸx p‘\’’Τ£d£ό€|₯₯Τ¦T§$§π©Pͺˆͺ˜ͺ¨««d«t«ψ¬Τ­œ@δ―d―ΰ°x±@±ά²˜³ ³0΄8΅@Ά<·@·P·|·€ΈhΉ,ΉΤΊx»»¬Ό\½½€ΎDΏPΐΐtΐ ΐΘΐόΑ,Α<ΑLΑxΑ Α°ΒlΒ ΒΤΓΓ8ΓlÜìüΓθΔΔDΔtΔ¨ΔΨΕxΖ$ΖXƈΖΌΖμΗΗ@ΗtΗ€ΗΨΘΘ<ΘlΘΰΙ4ΙhɘΚΨΛΜ ΜΤΝxΞTάμΞΜΞάΞμΞόΟ ΟΟΔΟΤΟδΠLΠ\ΠlΠΜΠάΠμΠόΡΠΡΰΡπΣΣΨԘՐΦ@Χ8ΨHΨτΩhΪΪpΫΫ°ΫΐΫΠάΨάθάψ݌ήHήό߈ίπΰΤΰδαœβ˜βΐβΨγγ(γ\γ„γ¬γΰδδ0δXδ€δ¬δάεε@εpε˜εΠεψζ$ζPζάηη4ηdη˜ηΘηψθ,θ`θˆθ°θάιι4ι`ιŒιΈιΰκ κ<κpκ κΠκψλ λLλxλ€λΠλόμ(μXμŒμΌμμν νTν|ν€νΠνόξ(ξTξ€ξ¬ξΨοο4οhο˜οΘοόπ0πXπ€π¬πΨρρ0ρ\ρˆρ°ρΨςς8ςhς˜ςΐςθσσ@σlσ˜σΐσθττHτxτ¨τΨυυ0υ\υˆυ΄υΰφ φ<φpφ φΠχχ8χ`χˆχ΄χΰψ ψ8ψdψψΈψΰωω0ωXω€ω¨ωΠωψϊ ϊHϊpϊ˜ϊΐϊπϋ ϋPϋ€ϋ°ϋΰόό@όXόpόˆό όΈόΠόθύύ0ύ`ύύΐύπώ ώPώ€ώ˜ώ°ώΘώΰώψ(@l˜Θψ(XˆΈΰ4`ŒΈδ<h”Όθ<h”ΌδŒœδ0Œ\Œ΄δ@hΈΰ€  | , X „ ΐ ό ( ` Œ Έ ΰ  l Π t œ Δ ό4`Œ΄θ@hΈ<Lx¨Μψ$T|€Μτΐμ8h˜Μ4hœΠ0d˜Μ4h˜Θό0d˜Μ$HlXΜ$L%°%Τ& &D&|&¨&Τ''l'ΐ( (x))„)Ό*H*΄+ +ˆ+π,`,ΐ-(-h.0.΄/T/Π0<0°1L1π2„2Θ3 3x3μ4T4Ό5(5˜6648<;ό?d?ό@l2Βξ2@!0@‚‚ 0`pΈ?ν?νΦ]ύΦν]103!'!22ώΤξύ2Šύv§τMk @qo u ??ύΞΦνΤν10#.553#"&54632AfŽ 3 33 3Η$954 549$€ύά',,'&,,WŽŸ§ 6@n n@ °Έΐ@ H   ?Ε?Ε/Φ+]_qύήν10#.55##.55Ÿ H B G §1;><<><01;><<><0γkjΉΐ³MΈΐ·LOΈΐ³ MΈΐ΄ LΈΐ³MΈΐ· LpΈ€³MΈΐ³ MΈψ@ M@MΈΐ³ MΈΠ³MΈΐ· L|Έΐ΄ LΈΐ³ M ΈΐΆ M@  Έΐ³ MΈΐ³MΈΐ΄L Έΐ@e My  y!yy  r r??Ν]22/2ν23??έ22ν22ήέ9]νν9]]ήΐΤ]]ν]ή]ΐά]9]ν910++++]+++]+++++++]++++]++733733#3##7##7#537#537#ŠfPf>RgzfPf753&&#"#Α?M& V08,!08,!6'r.GO*0% &'B0%=.r  b %5'4,! a\g " !+:'5-!kσςy'3ο΅' M"Έΐ³ M ΈπΆ MΈΰ@ M MΈΐ³MΈΰ³MΈπ@BM" "°""|(―Ώ|(((―Ώ|` p €  55 .°..|44+Έΐ@,H+}―ΏΟ} p}%}1ΐ·Ο111??99//]]]νν]?ν]?ν+ΦΝΦν]ήΝΦ]ν]99//]]ν]ν]10+++++]+++3#34632#"&74&#"3264632#"&74&#"326[Y—Yι<45<<54<‘ώp<36<<63<  kώ#LOOLLOOL*$$**""zLOOLLPPL*##**""ψβy)5AΒΉ?ψ@ M%@ M"@ MΈΐ³ M Έΐ@ M9@ M.Έ€³ M.Έΐ³ M-Έΐ@ L9-  &C""y#C?<_<3267'&&'3266654&#"m "H#-C-11.96*:>,f& Ύ<#*.f "/>"0W!H'(=(#5#0[ 23F 8`'!F#}#B +"2w-;"Ί|=§ =ΆnR  Έ€@ H ΰ π  Έ€³H Έΐ· H  ?ΕΦ++]q+_qν10#.55= H §B;>==>;B^V‘Ζ @ p Š??ΕΦνήΖ10&&5467Πm`9ˆ~‚ˆ9`q {΅8LKΰ‰ŠηKL8ΌUV˜Ζ @ p  Š?Ε?Ζ2ήν104&'7'66&q`9ˆ‚~ˆ9`m |Ό8LKηŠ‰ΰKL8΅.δΚk@Y@<@M<:.'4"'Έΐ@M AB/-;4 ' ?έΐέΕέΖΥΝΤΝ9/ΕΕέΖ2+έΕΕ9=/έΖ2+10'7>7""&&''7.553>77"#'.ό ^ #$" %   t   $ "$# ^ v "" C  m  !$"  "$!  o  D #!(&Μη Ήΐ³ MΈΐ@ M@M@M@ MΈΐ³ MΈΐ³ MΈΐ@4 M@M@M R`@ P €   ΟUΟ ?έΐ]ύΝ]ΐ9/]Ν]3ύ2Ν]10++++++++++3533##5#(jj9e~g[§@z {?ν?ΕήΞΦν10>7&&54632~%!&*3'*/1N8I 4 '280#F<,qΔƒ=΅‘?ΕΦΝ10!!qώξ=y‘υT§_Ήΰ³MΈΰ@He L H M HjΈΰ³MΈΰ@Hez {?νΦύΞ10]++]++++]++%#".54>32T6#  #6O,. !! ./[Ε»-@v??/Α‡+Α‡}Δ10#3―€~₯`#σΡy #U@4οΡΐŸd d%d$±! !!@e e ?ν?ν9/]Ν]]ΦνΪι/9/ν]]]]10#"&546324&#"326'#"&54632Ρniinpgino5326623507€  €’ Ÿ£joojkoou''((0Λk/@@ M a  ee ??νν9ήέύΝ3Ξ10+7'>733!5ΥH(882T{ώˆfZ f "&ύϋff+Ξy%&@c ' c&g! e ?ν?ν2ΦνΖήΦν10!!&654>54&#"'6632²(2 " ώl%9A9%.#@=(i4&F6 Θ ;84 !#$f 2TG=84&)!V*(,C)σΓy0€Ή-ΐ³ M,Έΐ³ M+Έΐ³ MΈΐ³ M Έΐ³ M Έΐ@* M L)c&, c,,21g!))e! g ?ν2?9/ν9=/ν2ΦΖΦ]ύΞΤν310+++++++".'732654&##532>54&#"'6632Υ3/( I3?3N<&.&)$#E,Y84M2*#05:Z  g 6(1'f"'Z%/@%%DN6+H5Ϋk0@ ae  ??9/93ν22Φ2έ22ύΝ31033##5!5>7&%" Œ{CC{ώώA3^L <Υ|z>\=2.% D3$/ Ά+T‘Kf Fh^+I6 f  .σΗo->@&c`p/+cc Έΐ@ H .e&g% g ?ν?ν9νΦ+ννή]νΔ10"32>54&'2#"&54>366ρ( # *$6K00J3hm5bŠT(L@/ $&  5*$/3f 6H($J>'‰ZŠ^0i!4' 1Εk)Άa cΈΐ@ H ee ??ννΦ+έύήν103>7!5!„$3<ώό”@9+@Œ}-f]pŽ‘P&σΟz+7ύ΅6@ M4Έ€³ M2Έΐ@ M0@ M/Έΐ³ M/Έΰ³ M.Έΐ΄ L,ΈΐΆ M ,Έΐ³ MΈΰ@ M @ M M5Έΐ³ M/Έΐ΄ L#Έΐ³M#ΈΐΆ M#"Έΐ@ M"2#dΈΐ³ MΈΐ@& H95d9//d&dP82##),g)g ?ν?ν9/9Φ]νΠι/Φ]νΦ++ν910]+]++++++++]++++++++#".5467&&54>324.'326"6654&Ύ*-9/3R1 +?'/S D&A4"Xώ€9()+$##,7##-ώΙ{*@@%))c c@  ,&c 0@+e&g% g?ν?ν9νΦ]νΔΪ]ι/ι/102676654.#"".54>32#'667*  # ,$6L01J2hn4a‰TP~'I 3*&/2f6G)$K='Œ}Z‹^1jCH‘υTΦ&/@ P O++4vgTΦ6ψ/-(ΟΪ*@??9=/999Βήΐ910%%-€"ώθ"ώ€9‘lmml’(rΜ›!@ UU£?ύΦνΦΐή2ΐ210!!!!(€ώ\€ώ\›f]f('ΛΩ.@??9=/9999ΦΐΞ910%'%%7Λώ€#ώη#€Ι’lmml‘Eτ²y01@22q'''1,u" g?ύΒ?ύΖΖή]νήΕήΝ107&54676654&#"'6632#".54>32¦*"(* <#"#^.9J*#(##3 α (I+^.70*%$&š',  yΤy5EZΉ>ΐ³M8Έΐ@M!@M!8 M @ MΈΰ³ MΈΐ@M: M:@ M Έΐ@ MŸ @M@M@M MΈΐ³MΈΐ@ M@ LΈΰ΄LΈΐ³MΈΐ³MΈΐ΄LΈΰ@rL@ M@ M@ M@ M M MP==@>>y 505`55GO6_66y+!GŸ|+F@Py=@APAAy &> = = &}0 }&/ύ]Ζ?ν99//999ν]ν]]Φν]Ζ9/ν]Φ]ν]22]10++++++++++++++++++]++++++++++%#".54>3254&#"3267#".54>323275&&#"ΤG&A0$9*0.!;+3U?/6 BrS0)FZ2)H6 Ε 7 1O9*J7 &5FuYFlI& W$Y“ol“['6W>ž( Θ" λk DΉ ΰ@' L L   H ????9/9νΖΖ910++!'##6733.g₯€,Z*†,W)ς  y ·-‡ˆώΟ²σ#?=>!!>=?6ψΥr#0T@'F Fp€20D Έΐ@ H   1#H$$,J J ?ν?ν9/ν9=/Φ^]+ν2ή]]νΤν10%#"&'6632%32>54&#'2654.#"Υ&AY3)X+#T)FX2+$?-ώά (90/0  »8K- Y /:,DN)¨#-'f)$ŽσΥy:Ά`  Έΐ@H!F J JJJ ?νΥν?νΥνΦνΦ+2Ζ]210"&54>32&&#"3267(ƒŠ*Kg=!5( A*7+IS0?Y ¨›MxS+ b1R=jq a6ψΩr!6@ F#DΈΐ@ H" HH ?ν?νΦ^]+ν}/ή]ν107232>54.#"#"&'6632± *9# 4)(+Li?!?$*J =eF'd 8M.(L:#ΞVyL#\ $Mw?Μk Q@ 0  D 0 H@MΈΐ³MΈΐ@ M H H?ν?ν9/+++νΦ]ν2Φ]ΖΖ103!#3#!?wόΫΫkf‹ff?Ίk J@/@ M@€ D@ M0 H H?ν??9/νΦ]+ν2Φ^]]+Δ103!!3#?{ΰΰkf–fώχσΠy#4@ %F$ D0  !JJ ??ν?ύΖ?9//]νΦνΞ10"326753#".54>32&&8,<'FD  {]B:]B$*Hb8$9* @ 9O0oiβώΛ)QyPOyR) b-Ηk ;@  D  DΈΐ@ H  H@???9/]ν?Φ+ν2ήν210###335Η{€{{€kύ•ώοkττ6Ώk .Ά  DΈΐ@ H H H?ν2?ν2Φ+ΐέύάΐ10353#5!#36‡‡‰††fŸffώaf*σΆk.@DH J ?ύΖ?ν?Ζ^]ή]ύΝ10%#"&'73265#5!Ά5T73^ )27{{0+$ ‹'29@9.#QMCώεkώDDBEKN$NY],GΜk,Ήΐ· HDΈΐ@ HH?ν?ή+νΖ+10!!3!Μώ{| kύϋέko΅ MΈΐ@ M0 MΈΰ@[ M@ L?@ M? M M L @ M M @ M @ L @ L?  @M L M MΈΰ@M@ M M L@ LΈΐ@ M@ M M M?Έ€³ MΈΐ@1 M@ M@ M/?@ M DDΈΐ@Mo  ??9/9??9/9|ή]]+νΡΙ/Φν9=/9999ΩΙ/10+]++]++]+++]++++++++++]++++++++]+]]+++]++>73###>7‘ f qLZIq kBLN!%OI@Qš—™PαώϊώL€’˜A.ΖkS@ @ M Έΐ@ M?/ ?  DDΈΐ@ H  ????99Φ+ν2ήν]210]+]+!&&'#33c*c9oc85-ogΝgώek,gf`$}ύ•σΩy,@ηΦ F!F J J?ν?νΦνή]ν10]]32>54.#"4632#"&˜& '& &}vimrtjms6-O:"";N--O:"";N- ££  ££6Ψr?@ F`D Έΐ@ H  HJ?ν?99//ν?Φ+ν2ή]ν102###>"32654&ΰv‚ƒx,{-., ' 2;<;ranocΡckΘ/96-VΩv&/@F (F' J J  "J?ν?3νένΦνΪ2ι/9104632&&'&&732>54.#"vimrZU UJuw QW}& '& &3 ££ Œ‘! XKFŸ‰-N;"";N--O:"";N6ιr$Y@D` p €  &F`p€&!DDΈΐ@ H%H!!  J?ν????9/ν2Φ+ννή]νή]2ν2102#&&'##>4&#"326Φ5V>!,3&$! =#@{+,(|<1 ?8r2M46X?EE54.'.54632&&#"#"&'7θ) "*<1 qc9U$=(b'?5"qsM\$KZ  (;,Wb_G -C3W_!dΫk@DH???ν2ΦέύΝ10###5Ϋ£|£kfύϋf'σΝk/@ D`pDΈΐ@ H J ?ν?3Φ+νή]ν10".5332>53ψX6‹ώ}'5 !5'‚ώu6X>! θkƒ@ MMHΈΰ@ M$ M+Έΰ³MΈψ@0LG @ M   /  ???3??9]ΖΞ]910+]++]+]+]++3.'3>73Ί60& ‚!  #-6E­š10‡ƒ43ƒ‡€0<”£©Oέk(s@%@ L#@M# M!@M Έΰ³ MΈΐ³ MΈΰ@ M@MΈΐ³MΈΘ@ M@MΈΰ³M Έΰ@ M € M € M@ MΈΰ@ M@LΈΐ@ M@ MΈΰ³ M(Έΐ³M(Έΐ@ L#@MΈΐ@ M@MΈΐ³MΈΐ@ L@MΈΐ³M Έ€³ M Έ€³ MΈΐ@ M@MΈΐ@6 L #( ?  D   *0D)#( ????9Φν]Ϊ]ι/]9=/9910+++++++++++++++++++++++++++++++++++4.53#&&'#.'3>7( r f,0f r 8DN)4w|;L‘ŸšE?‘B?”?E›Ÿ‘K;~}w4 LJ> ιkf΅ MΈΰ³MΈΰ³ M Έΰ@'M    ??9??//Ζ99=//99Ζ10++++!&&'#>7373d7:… '/4’…bg|ž4-" 3|>;3LX]+$ΖΖώί+^YM θk>@!D€      ???9??9/]Ξ2ν9=/Ν210>73#5&&'3ώ  &*0|7S&„8PFNP 3`^]1μλaΉfH•.Ζkf΅@ MΈΰΆ MΈΐ@ HΈΐ΄ H Έΐ@ H Έΐ@ HHH?ν?ν?Ν/+]Ζ+Ζ+99Ξ+]10++!!5>7#5!½+H>7 ώh2>I,ξ‚Btia/fG+_l~Jfq[†»/@_@_@ nrr?ν?νΦνΞ]]Ξ]]10!#3!q  ώλ»`ύ``1[Η»*@v???/ΖΑ‡+‡}Δ103#1~»ό m[ƒ»/@n@@ Prr?ν?νΦ]ΐΞ]ή]ν210!53#5!ƒώκ  ₯` `λk)@r?ύΝ29=/9910''3λo~~pΉi56ΪΪ66[μΖ@ U??νΖΖ10!!δώ:k˜s³΅}?ΕΦΕ10'՞-³oCT,υΉβ.S@ $QS0, SΈΐ@$ H/_oWP"`"""@W(@ M(W ?ν+?ν]9/]ν]Φ+νΔήνν10]72675&&#"2#".54>3254&#"'66ϋ& "$0:M.jB-I4 6F&0%,6#ATXl  Š1G,ώθ%;+)8"#/ c >υΦΆ [@ @ M @ M@ MΈΐ@ MS` p  !QQΈΐ@ H UW W?ν???νΥνΦ+ννή]ν10++++%4&#"3267#"&'76632Y+,' 08}:T60d"{0.F/ξBF AK8[@# “λ #AZ,υβ5@0@`p!SΈΐ@ H W W ?ν?νΦ+νή]Ζ10]74>32&&#"3267#"., BeF*D#1&,;$IX?J2HgBλ3ZC' c %4AJ e &BZυΆ `@@Δ@ΐ@ΐ Έΐ³ MΈΐ@ M@ MQSU W W?ν?νΥν??Φνήν210+++]q]q]q73267&&#"#"&5463257™/4$,("b/nq_]0{ξ?P Fώή ‚qs… ΦυΡβ%\Ήΐ@7LS ?  '% Sp& @MO _  U@W0  W ?ν]?ύ]Ζ9/]ν]+Φ]ν2ή]Ζν10+74>32!3267#".%4.#"&>P*hlώΟL<%C H-<_C$; "# η>^? {v .5i =Zm#$$μ΅VΉΐΆ MPΈΐ@) MP  Q`pOU W U ?ν?ν?ν?Φ]]έ2ν2Ζ]Ξ10]+]+3#5354>32&&#"3#‹gg!8H&'R!EΑΑpf9K-d%fώ!XΆΰ 'GΉΐ@'LQQ`  )S`"p""(W W% @W?ύ]Ζ?ν9/νΦ]νΦ]νν10+732675&&#"#"&'732>55#"&54632ž*-# lo{,Q%@0 * +\_€nMZϊ:= βώ½sn h # tgtr?ΉΆB@Q@ ` p  QQΈΐ@ H W ????ν??}/Φ+νΠνή]ν10376632#54&#"?{*4F*{*! ‘δ 9O0ώχωB:ώ–$υΣ¬ LΉψ@. MQp?!! !`!T `pWUX ?ύήν?ύΖ/]ν]ά]]]ύΝ10+#"&54632#".55#533267. -- .·&C0A'‚ύ$0]$**$%**ύ’ 5L1­fώέ*) 1V¬M@ MQ Έΐ@! H!T @PpUX W?ύΖ?ύήν/]νή+]ύΠΝ10+%#"&'73265#5!'#"&546321C'0R&&G"Ύ9. -- .9M/h%2Wf‡$**$%**?ηΆQ@ @`0 QΈΐ@ H0p  ??9??/]3Φ+ν22]Ζ]210>73#.'#7»%# ”.11:8/ ',-||/2/684CHH?=7ή‘$υΣ°6@!`p? Q P ` p   U W?ύΖ?ν?Φ]ΥνΞ]]10%#"&5#533267Σ"1UN‚ύ&%2 eafώ0"ΧΫ'„@^+@M@M/?_ŸίοR@M/?OΟR_) 0@R€(W" % W ?ν3??9/?νΦ]ν]ή]ν]+9/ν]++10_]]2#4.#"#54&#"#663266W'2 d  dd'L).Ϋ0I1ώη".^l0&ώΔ  ?Ήΰ-Ά QQΈΐ@ H 0W ?ν]??Φ+νήν106632#54&#"#?!a98J+{.{Η 9O0ώχωB:ώσΨβ&@S@ M!S W W?ν?νΦνή+ν10%#".54>3232654&#"Ψ :Q22Q; !;R01Q; ώΒ-201-201μ8[B$$B[87[A##A[8?NN??MM?[Υΰ 6@S` p  QQΈΐ@ HW  W?ν??νΦ+ννή]ν10%4&#"3267#"'#6632X23 (,*}.F./2{"c0mtη?Qώώ GE6[A$±l „[Άΰ !5@QQ`p#Sp  "UW W ?ν??ύΦνΦ]νή]νν1073267&&#"4>32#5#".œ+,% 33}9U630+{3.F/ηAG Q;6[@$ ύ”² #@[YΛί!³Q Έΐ@ H W ??νΦ+ύΝ10.#"#6632΅ !" 2|1gE %*+Yώ£·6υΊβ1LΉ/ΐ@ MS &&Έΐ@ H&3S .Έΐ@ H.2!W+W ?ν?ν99Φ+Φνή+]νΔ10+72654.'.54>32&&#"#"&'7δ-0#8.1L5.OH-/!!:/3R<=V#O]    1%5) h   !3%4& g$υΨ`fΉΐ@@ M 0€@M@ Mo ` QP`pW U ?3έΕν2?νΦ]έ2ν2]Ξ^]]++Ζ]+10#53573#32>7#".5kk{ΕΕ "O%+B.pfvŠfΎ  j (I;;υΆΦ2@ Q Q Έΐ@ H   W?ν??Φ]+νή]ν10%#".533273Ά"a9:J+{-|  ;P0φA?qζΦPΉΰ³MΈΐ³ M Έΰ³ MΈΰ΄ LΈΰ@ L   ???ΒΞ910+++++3&&'3>73Β-]*   }*f-YοŽ&VWR""RWV&ŽοY ιΦ(@Ή(ΠΆ M`('Έΐ³M'ΈΠ³ M!Έΐ@ M@MΈΐ³MΈΐ³ MΈΐ@ M@MΈΐ³ MΈΐ@ M M Έΐ³ M Έΐ³ M Έΐ³M Έΐ@ M@MΈΐ³MΈΐ³MΈ ³MΈΐ΄ LΈΐ΄ LΈΐ³MΈΐ@> M(`$$  ) %`%%*@ M0)(%   ??9/9??Ζ]+Ζ]9///q33Ζ333Ζ]310+++++++++++++++++++++++]+!.'#.'3>73>73B   ] i  Y  i '415 324 ,ky‚DW¦X&A;77;A&.TSS-‰ς[αΦ)@     ????/Ζ/Ζ91073#&&'#>7'3ώ`}˜.*" €60}'+/₯C“βAB<3P (L/=?>δXΨΦ"/@"Q$ #Q   ??έΖ?/νΖΦν9]10#"&'73267&&'3>7Ψ#&+%-7%3$, ,X$€  ΦByt7(:% g 0!Xγ‰%TTQ##QST&C΄ΦW΅Έΐ΅ HΈΐ· HΈΐ@ H@Pp U U?ν??ν?Ν/]/+99Ζ+Ξ+]103!5>7#5!ͺ4==ήώ664Β]|?NU$fK&PMFf?[΅»$7@"n n%r rr ?ν?ν9/ν9=/ή2ήύάΐΠν1033#"&554&##5326554633#"»6/ ]hZE66EZh] / D@q*&`NJ“*+`+)”JN`%+q@D½[9»(@€ΰ_ @??ΖΖ]]]2103#½||»ό ?[΅»(C@%(@ M@ Mn&n* )r !r r ?ν?ν9/ν9=/ΖΖή2ΦύΠν10++&&554&##53233#"##53265546960 \g-=%77%=-g\ 0 D@q*&`&9%“*+`+)”%9&`%+q@D«ηd@  ƒ?ΔέΞΤΕΦΔ]10%".#"'>3232>7Y/,) [!2#/,( ["1« 7.7/τήw.vΉΐ³ MΈΐ³ MΈΐ³ MΈ @- M 0-)+ c(+/J# )s*-s.Ÿ J?ύΖΦ]2ύ2Φ2ν2?ύΖΤ22ύ22Μ223Ν2ΞΞ10++++6632&&#"3#3#3267#".'#535#5d|Y@"/34 Ά±¦‰ <%>K&*N?- A99«gef 4-TT5/ c1O9T?T~g[§@ z ?ΕΔΦΞΦν10>7&&54632~%!&*3'*/1N8I 4 '280#F<,Vμ΅)3@(+&)QR*(U' W U?ύΖ?ύΦ2ν2ΖΦύ2ν2ΖΞ10%#"&'73265#5354>32&&#"3#2C'""gg!8H&'R!EΑΑ9M/f%2Wf9K-d%f pΓƒ'"@"'('?Ε?ΕΦΦΝέΔΦΝΝ10>7&&546327>7&&54632 %!!.'&.F.Ϊ% " .'&.F.M +##3$@6&C +##3$@6&τΫw #I@/ @MO  yO_yO!_!!y$t ???ν23Φύ]Φ]ύ]Φ]ν]+10"&54632#"&54632#"&54632‘ΒΒ )()))()))())>Έk:@ R @ P €    U  ˆ??Ξ9/ΐύΐ9/]Ν3ύ2Ν10#&&55#535331 K ††m‡PΜH{BA|HΜf΅΅f:΅klΉΐ³MΈΐ³MΈΐ³MΈΐ@,MR  0@Pr  r_o{ˆ??ύ]2ύ2Φ2ν2Φ]2Υ222ύ22Υ2Ζ10++++%#&&'#535#53533#3.J ††††n‡‡‡b=l:9m=g‡f΅΅f‡gpώ†³@@"@ M M+r~?3έν99=//999910]++''7†1YY3Œ9;EE;z σλy #'3?KΉ>ΐ@M<@M8 M8XM6Έΰ³M6Έΐ³M"Έΐ@MΔ" @MΜ  MΛΈΐΆMΔ Έΐ@MΔ @MΛ@MΛΈΐΆMΔ$Έΰ@KL ..(&'M::@F4%L+€'&7!7=€I€I7%$%% C€71€!€ ?ν?ν?ν99//99νν9/99νΦΦύΦν]ΦΕΦύΦ]ύΦύΦν]10+]+]+]+]+]+]+]+]+++++++74632#"&74&#"32674632#"&%'%4&#"3264632#"&74&#"326O0.0000.0{ _0/0000/0ώωΙF ώh0.0000.0{|CGGCCFFC$ $$ $CGGCCFF―,ε-ώ°$ $$ ˜CFFCDFFD$$%(σΜ>&6_‹@ /3+$P4O++4„'|Τ8Ήΐ³MΈΐ@ M ??9=/999ήέέΐ10++%'7![e““eώ§0ΧΦ/ϋλq%n@K@ M@ MD/?D/?O_? O _  ' !!S&HHOH J J ?ν?ν?ύΦ]ν?νΦν]Ξ]ή]Ξ]ύ]νΠΐ10++!#"&546323#3#3%27&#" eikbΖoXX|ώτ#"•¦₯–fŠf―ff–6M00M6mΟ@ z Š?ΔΦνΤΞ10#"&54>7m$!&*3'*/1N8 5 '280"G<,Ÿmί @@ M@ Mz £?ΔΦΦν10++>7&&54632%!&*3'*/1N8ο 4 '280#F<,)ΰ±'&@"('£ £?Δ?ΔΦέΦΞΦ]έΦΞ10#"&54>7#"&54>7ΰ$ !!.'&.F.Ϊ% " .'&.F.n +#$4$@6&C +#$4$@6&ΏΥ'.@"• 0•('Š Š?Δ?ΔΦ]ΦΝύή]ΦΝν10>7&&546327>7&&54632% " .'&.F.Ϊ% " -'&/E. +#$4$@6%B +#$4$@6%r«‚Ι@   ?ΕΦΕ]10#".54>32‚#3 2##2 3#:3((34((46έΏ9΅”?ΕΦΝ10!!6‰ώw9\έτ9Ά”?Εΐΐ10!!τώ 9\Zž Ήΐ³ MΈΰ³ MΈΐ³ MΈΰ΄ LΈΰ΄ LΈΐ³ MΈ ³ MΈΐ΄ L Έΐ³ M Έΰ@% M   0‚ ‚?ΥΖάΕ?Ζ]Ξ9////9910++++++++++#".#"'>323267ž";"y '  eάk$Ž@V $#$ ‚‚‚‚%‚//#$$ƒ ƒƒ?ν2?]??9/9??]9/9/]qqrνήξqύύqΦqν]9=/]9999]10]##5#5'#>7373#4.'Μ@:@4':6,/6:*k2ΤΤ2Αt<9,2J<3ˆˆ4?>*W$p€99 W033W 0W ?ν?ν]?ύΖ9/Ε]?νΖΖΖ9/////]10+++746326632#3267#"&'#"&732654&#"7"34.MB5.1$³#-)60#IF^ξ  X μ~x! "6X@ %' a %%~yP@?QP@?C%& θ,&<ƒ‹@)P!OO+++44§[MΡ #@q ou  ??_]ύΞΦνΤν104>73#4632#"&³fŽ 3 33 3$944 449$€$'++''++.ŸΗj![Ήΐ@2 M #QQS 0P"W" W??έ2ύΖ9/ύ2ΕΦ]νΤν]Τν]Φ]Ζ10+46753&&#"3267#5..Y`|-/$S@ES<2|0F-U{€{ h ?=<@j }‚ *32&&'"κ””ιώ MM4K/#?!$$[e&'$fH{3e4CY6 b  *!Vβ)Ϋ΅%@MΈΰ³MΈΘ³ MΈΐ΄ LΈΰ³MΈΐ@ L@ M M @ L M@ LΈΐ³ MΈΐ@ M@ M M@ MΈΐ΄ L Έΐ@/ L@ M@ M P„$„*+ '„*!„§§??ήνήνήΖ9/ήΐύά]ν]ήΐ10++++++++++++++++++++27'#"&''7&547'764&#"326ϋ,&BS@@TB''BS@@TB$v++++ζ?Q>$,,$>R@  ?Q>"..">R@°&((&&(( θk!…Ή ΰ@E MD# !!  "#D" ss ????9/93ή2ν2ν2?Φν9=////////993333Φν10+%##5#535#53.'36733#3ΐ‡|ˆˆˆe)&! „3$G% #'^‡‡hhhT>T"KKG@‚HŽ|GLK"T>½[9»$@ n?Ε??ΕΖΦ2ύ2ΦΖ1073#3#½||||½ώž`ώž1žΑz4D„΅'@ M Έΰ@ M=@L5Έΐ@>LF.F5=/@?@@d((F#F8d0044E&5= =5& g1 g?ύΖ?ύΖ9////Ζ]Φ]νΤνΞΦ]ν]99ήν10++++732654&'.5467&&54632&&#"#"&'6654.R$$(!#%-#=. &d^(V#!=()*₯ d[E`œ 5- 5(  &2#$@$,EMb  0q&8-#KG)(S€‘  @ 0 ŸŸ?Ν?ΝΦ]έήΝ10"&546323"&54632˜))**¬))))# $$ ## $$ #σέΫ1E‰ΉDΰ³ MCΈΰ³ M?Έΰ@G L: MO94 M7?(_(((G@AF€ €O 0  <2€-<€# ?ν?ν99//]]ννΦύΦ]νή]ν99//9910+]++++%#".54>32&&#"3267%4>32#".2>54.#"G%++#  !  ώγ&?Q,+R?&&?R+,Q?&α8-,98--8x#-.$6( %:=\==\==[==[w.D,+C..C+,D.h•x +l@ )@M @MΈΐ³MΈΐ³ MΈΐ@* M!…`-) „0`p,Ÿ }°(%} ?ύΒ/]ν9ν]Φ]νΔή]ν210+++++2675&&#"2#"&54>3254&#"'66 ( +:#N4FQ)6 %2 C_E#3Λ 3>)  O 2.ΓΞ [@ _y R_yΈΐ@ H     ??99=//99=//ή+ΡΙύ]ών]ΩΙΩΙΡΙ10'%'ΊA^^?ŠOB]]@ˆΞ(§§*ΡΟ(§§*Ρ-*ΐk@ yrƒ?ύΕΦέν10%#5!5!ΐiώΦ“*ΫfqΔƒ=σέΫ1EψΉDΰΆ MDC?Έΰ@! L:@ M: M4 MK4`M@MΈΐ³MΈΐ@tM@M@M@ M‚ @M_  @Hϋ δ ? O  7(?(_(((G‚@HAF€<2€-€/?<€# ?ύώqν?ν99//ν3ΦύΦ+νq2/23ή]ύή]]]+qν+Β2/ι/2/10+++++++]++++]+7#56632#&&''32654&#"4>32#".2>54.#"ά6"97(  9  $  Γ&?Q,+R?&&?R+,Q?&α8-,98--8»Mξ,*0/%2 J=\==\==[==[w.D,+C..C+,D.l0Œ‡Άs“?νΦΝ10!!l ώΰ‡Wl₯ŒΊ@||  }}?ύήνΦύήύΖ102#"&5462654&#"ό5&&5BNP@ Ί$4 3$IAAJΑ(Μ.}Ήΐ³ MΈΐ@ Mp €  ΰ  Rp€pΈΐ@& Mp€Up €  @ L@ / ?  U?ύΦ]]+έ]2ύ2Ν]+?Φ]Πέ]2ύ]2έ]ΐ10++7!!3533##5#(€ώ\jjff’œœfq‚y7@„„ | °ΐ}t?ύΞ9/]99ν2ΦνΖήΦν103!54676654&#"'6632y. Œώ/-,.H(F; '5 Q,F& E!=q€y*ί@ "@ M!@ M Έΐ³MΈΐ³MΈΐ@ M@ M(Έΐ³M(Έΐ³M(Έΰ³M(Έΐ³ M(Έΰ³ M(Έΐ@O L@L@M L@ L M―@M „?„,'+($}}, }t?ύΞ9=///ννΞΦΖΪι/Ξ2ΐ/]ν10+]+++++++++++++++++2654##532654#"'6632#"&'7η ?%%'("C $1 $:*E*Z$IF%! -* O ˜s³΅}?ΝΦΕ10'7s-žUTCo;[ΆΦ7@ Q  °  QΈΐ@ H W ??ν??Φ+2ν2ή]ν1032673#"&'#Ά  | ^30{Φ#- qώ:  'S{[Ηr>@) 0 ΐ Π ΰ  R 0ΐΠΰR r?ν??9/ΦΤύ]Φν]107&&54>32#&&#¬LM#A\90e&e 0fθ[W0J3 όώ―ύO‘―TaΊŸVg@   ?ΥΖ?ΦάΕ10#"'73254''6673,!!,-# ")$P  ' ? $ ¦r;@!@M @L  yys   ?9/999ν2ΦΖύύΕ210++535'66733Šd%&FMRQ   N&ώνQJ§ydΉ ΐ³M Έΐ³M Έΐ³M Έΐ³M Έΐ³MΈΐ³MΈΐ@M_„„@  ttž?ύΦνΦ]ύΦν]10+++++++#".54>324&#"326§.@''@..@''@.f%#"'&##%Δ*B..B**D..D*+11+)002.ΓΞ 8@         ?Δ?ΔΖ9///999ΥΔ10%'7'7'7'7;A^^?Šώ±B]]@ˆ.(¨§)ΠΠ(¨§)Ποr  ΣΉΐ³MΈΐ³M Έΰ³M Έΐ³M Έΰ³ MΈΰ΄LΈΐ³ MΈΐ³MΈΐ@L M@ L  ―"@"! !!  !   ŒŽ Ž?ν2?Ε2ΕΥΖ?ν????99//9ΦΤν]ΖΦΥ]2ν2Τ‡+‡}Δ10++++++++++%3##5#56676673#53#Λ$$P|- ώŸ"2?Uf 3EώΓd=ϊ”?''-+L/3ϊ– ώΘ)ύ•kλr(,o@A @M M*),+*+,―)*)*). |.+-##$-%(-",+ )#Œ"™š ?ν?ύΖ?ν???9ΦΤν]ΒΦΦνΠ‡+Α‡}Δ10++%#&4546776654#"'66326673#5%#λΡ)  ): '= $ώ„"2?U«ώΓd=?? #&   5(*" ξϊ– yύ•k οy(5:>’@U+ M(@M@M<>=>―;<;<;@ |  @=?(?€ %€  ?>= < ;6:,0/ 5). €?ν?ν2?Υ2ΥΖ????9=///ννΤΖΒ9///93ν2Π‡+‡}Δ10+++32654##532654&#"'6632#"&'3##5#56673# '; ( 840 *"-3Ώ$$P|-  3WώΓd=½  9  6 ) + †”?''-+L/@)ύ•kEV² 2CΉΐ@ H4)qP!`!p!!3 pΈΐ@ H3.u$  g?ύΖ?ύΖΦ+νή]νΖ+10%3267#".54>5'4632#".Q*"  * <#"#^.9J*#(##3 ε (I  ^/7/'#"$š',   λ>&$Cπ‹Ήό@  PO++4 λ>&$τ‹@  PO++4 λ>&$i‹@  PO++4 λ+&$u‹@ % P$O++4 λ,&$ƒ‹@+ P#OO+++44 λ#/΅΅"8 M!Έΐ³ MΈΰΆ M4Έΐ³ MΈΰ³MΈΰ³M Έΰ³ MΈΰ΄ LΈπ³MΈΐ³ MΈΐ@1 M  0*$*$$*0 ΐ1 0H  ???9/3ν2ΖΖ]9///9910++++++++]+++#'##67&&54>323.74&#"326c+V(„₯€+W)&+?j  y ­&†ώՏ²'„ (' 4ν#?=>!!>=?έ λkœΉΐ@ L@ MΈΐ΄ L Έΐ@I L @ M   HH H H ???ν?ν9/ν?9/9ν/]ΦΕ9/////////99910+++++7##>7!#3#3#3[€,,.oXX|μ"Ej‘Œ…OfŠf―fE‹SVΥy6M@,2 L2@ M$#3828,F7 72J36 $J#'J/J ’?Ε?ν?νΥν?ΥιΦάΕΦν3ΦΖ210++#"'73254''667&&54>32&&#"3267,!!,-# ")$ag*Kg=!5( A*7+IS0?U7 ' ?  ‘†MxS+ b1R=jq a?Μ>&(Cπ‹Ήπ@  PO++4?Μ>&(τ‹Ήτ@  P O++4?Μ>&(i‹Ήφ@  P O++4?Μ,&(ƒ‹±Έφ@  PO O+++446Ώ>&,Cπ‹Ήϋ@  PO++46Ώ>&,τ‹Ή@  P O++46Ώ>&,i‹@  P O++46Ώ,&,ƒ‹@ PO O+++44ψΩr)I@+/!?!!F€+)D  *   &JJ ?ν?ν9////ΦΦ]2ύΠΕΦ]ν]10#"&'#53566323#232>54.#"Ω)Id< =#55*F :`C%ώκLL &4 0%6VyL#fο $Mwfͺ 8M.(L:#.Ζ+&1u‹@ PO++4σΩ>&2Cπ‹Ήό@ #!P"O++4σΩ>&2τ‹@ " P!O++4σΩ>&2i‹@ $ P!O++4σΩ+&2u‹@ . P-O++4σΩ,&2ƒ‹@"4P,O O+++44<FΒΜ tΉΰ³M Έπ@ M MΈπ³MΈψ΄LΈπ@!M·       ??99=//99999ΖΖΖΖ10]++++++''7'7{F}~G}}E}}E}ΛG|}E~~D}}H}ΨΩ“(ŽΉΰ@ M LΈΰ@F LF_  @ H *)!"*!""!)*F)‘"!$J $J?ν???ν9Ε??Φν9/////9999ή+]ν10+++46327#"''7&%4&'32>'&#"vi7'P"&8Cη‹Ήσ@ PO++4'σΝ>&8‹@ PO++4'σΝ>&8i‹@ PO++4'σΝ,&8ƒ‹@.P&OO+++44 θ>&<‹@ PO++46ΨkD@(S Q 0 P  W W_o   ??99//]ννΦ]ν22ή]ν102###362"32654&ΰw‚y,{{  ' 2;<;fihjrkYkΘ6203υμ΅6~@-!@ L @ L@ L@ L@ M@ M@ M@ MΈΐ@' LS $SS 8@ M*Q-7'W2+W?ύΞ??νΦύΖ]+ΦνΤνΤν10+++++++++#"&'732654&'&&54>54&#"#4>32˜"&"M^/73+"- &&{0J42E+!+1#"- MRf$; #,%*":3ώ!ά/P: )5,υΉ³&DCο@ 20P1O++4,υΉ³&D@ 1/P0O++4,υΉ³&Di@ 3/P0O++4,υΉ &Du@  =/P32&&#"3267###"'73254''67., BeF*D#1&,;$IX?J2 !!,-# ")$ 1F-λ3ZC' c %4AJ e ' ?  ,>MυΡ³&HCοΉύ@ )'P(O++4υΡ³&H @ (&P'O++4υΡ³&Hi@ *&P'O++4υΡ‘&Hƒ@(:P2O&O+++44$υΣ³& CέΉη@  P O++4$υΣ³& τΉώ@  P O++4$υΣ³& iοΉο@  P O++4$υΣ‘& ƒο±Έο@ ( P O O+++44(σΰΉ#4_Ά LΈΐ@. M2S# ##65*S 5$W'Ws!#/W?ν?9/993ύ2Φνν?ΦνΤΖΦ]ΦύΔ10++#".54>32&&''7&&'77&&#"32654&‡ 0P<4M31K3,\D J=-m™+ *) 0'<…B:iO/#3277&#"4&'326Ψ :Q2 8&>)!;R0>2%?*ώΒ‰01ΐ‰01κ8[B$ 3/9 U37[A#3/9 R3Ό M? Ή N;υΆ³&XCοΉό@ P O++4;υΆ³&Xτ@ P O++4;υΆ³&Xi@ P O++4;υΆ‘&Xƒ@'P O O+++44XΨ³&\τ@ %# P$O++4?[ΥΆM²SΈΐ³MΈΐ@ H  Qπ  Έΐ@ H W  W?ν????νΦ+]ν22Φ++ν10%#"'#766324&#"326Υ.F./2{{mt}23 (,*λ6[A$±Fή„u?Qώώ GXΨ‘&\ƒ@%7 P/O#O+++44 λ&$Š‹@  PO++4,υΉ‡&DŠ@ /0P1O++4 λ5&$a‹@ % PO++4,υΉͺ&Da@ 3=P/O++4 Vωk ,@@$(!   .-%’ J  ?3???99ν?ΝΖΦ9ΦήΕ103.'##6733267#"&54677ω  y d₯€,Z*†,W)  30* σ#?=>!!>=?ώ0·-‡ˆώΟ² : %6,VΉβ4CY@5 S)E9Q(E.EAS 0@PD@P`W<< OW# 45W ??ν99?ν]9/ν]Φ]ΔνΦάΕήν2Φν10#"&5467#".54>3254&#"'66323267'2675&&#"·30*"-I4 6F&0%,6#AT-:M. ΅& "$0œ %5%;+)8"#/ c 1G,ώκ Ίl  σΥ>&&$‹@ 1" P!O++4,υ³&F@ !" P!O++4σΥ>&&i6‹@ 9$ P!O++4,υ³&Fi-@ )$ P!O++4σΥ.&&b6‹@ 8"(P O++4,υ£&Fb6@ 1"(P O++4σΥ>&&_6‹@ 9 $P%O++4,υ³&F_6@ 2 $P%O++46ψΩ>&'_έ‹ΉΡ@ "&P'O++4 υΆ Q@Q _ 0SΈΐ³HΈΐ@ H  WW?ν?ν????ή++ν]ΦΥ]ήΠύΐ107327&&#"#"&5463257#5Š!$ ηY+_bPN(|•Pξ?P Fώή ‚qs… ΦΪΪψΩr«υβΆ#@@#S%S $U!W0  W?ν?]νΥν?3Ν2??ΦΔνΦΦν22103##"&546325#53573267&&#"«77#`0mo^[0€€{ώξ-3$*'gSύϊ ‚qs… IS:ώ8?P F?Μ&(Š‹Ήχ@ PO++4υΡ‡&HŠ@ &'P(O++4?Μ5&(a‹Ήυ@  P O++4υΡͺ&Ha@ *4P&O++4?Μ.&(b‹Ήυ@  P O++4υΡ£&Hb@ (.P&O++4?VΪk [@9  @P`@ M?" D !’H@ H H?ν?ν9/]ν?ΕΦ]ν22Ζ]+Ζ]Φ]ΦάΕ103!#3#!3267#"&5467?wόΫΫ  30*!kf‹ff : %:VΡβ.9sΉ.ΐ΄ L!Έΐ@>L/S" @;(;9Sp:O_oU///044W !@W +’?Ν?ύ]Ζ?ν]9/]ν]2Φ]ν2ΦάΝΦ]Ζν10++#"&5467#".54>32!326732674.#"­30*<_C$&>P*hlώΟL<%C  L "# œ %3=Z<>^? {v .5g z#$?Μ>&(_‹Ήφ@  PO++4υΡ³&H_@ &*P+O++4σΠ>&*i-‹@ 2($ P%O++4!XΆ³&Ji@ ,(! P$)O++4σΠ5&*a-‹@ 1(2 P$O++4!XΆͺ&Ja@ ,6! P$(O++4σΠ.&*b-‹@ 1&, P$O++4!XΆ£&Jb@ *0! P$(O++4VΠy&*Γ Ά-& P+4!XΆΔ&JΔ$@ /*-! P$(O++4-Η>&+i‹@  P O++47Ή=HΉψ@LQ QΈΐ@ H† W ??ν???ΥΝΝΦ+ύΐΦΕΦν10+376632#54&#"''7?{*4F*{*! ƒ&\^&„yΌ 9O0ώχωB:ώ–ή9669_γkc@= 0D @PD 0D  / Ώ  H H ????Υ22ύ22ΦνΦ]qΞάύ]222ώ]222ύ]Ν3103##5###5353355#Ά--|€{--{€€kHcώ@ώώΐcHHHώψ]]ΉΆ²΅@ MΈΐ³ M Έΐ³M Έΐ@ M @M Έΐ³M Έΐ@ M @MΈΐ³MΈΐ@;MHMQ /? Q  W0 ???]ν??9////ΖΔΦ]2ν222Φ]]Δν10+++++++++++3#53573#6632#54&#"P77|&1A'{#S:OSB 9O0ώχωB:ώ–6Ώ+&,u‹@  PO++4$υΣ & uνΉξ@ " P !O++46Ώ&,Š‹@  PO++4$υΣ‡& ŠνΉξ@  P O++46Ώ5&,a‹@ P O++4$υΣͺ& aοΉξ@ " P O++46VΏk!YΉΐ΄ LΈΐ@- L#D 0@P" H H !’?Ε??ύΐ?ύΐΦ]2Υύ]ΔΕΦάΕ10++#"&5467#53#5!#3#3267N30*!Ÿ‡‡‰††€  œ %:fŸffώaf $VΣ¬ 3RΉ3ΐ³ M2Έΐ@& M355 5+Q(*T*42/U "’)U+X ?ύΦν?Ν?ΕύΖΦΦνΥν]ΖΦάΕ10++#"&546323267#".5467.55#533267. -- .Ÿ  ',$-=$‚ύ$0]$**$%**ύ~ :35K/­fώά+' e6Ώ=&,bš@ P O++4$υΣΦ;Ήΐ³ MΈΐ@ M @ Q  U W?ύΞ?νΦένΖ]10++%#".55#533267Σ&C0A'‚ύ$0 5L1­fώέ*) $υΣ¬Lσΰk?@ /?D`Έΐ@H Dΐ J ???ύΒ?Φ]ύΞΦ+]ν]1033%#"&'732>53{M0?$#>$0!  |kύ•Β>P.b*#‘7[»¬+‰Ήΐ³MΈΐ@M&T  ° €  ?  -TΟ ί  Έΐ@ H ,Q?O_QΈΐ@ H°,#X)WX ??ύΞ?ύΖ?ύΞΖ]Φ+ύ]Φ]νΦ+]νΦ]]_]ν10++3#37#"&54632"&'732653#"&54632Δ{{0 // 0- 1 |Qb0 // 0Φ‡%))%&))όΨe&#Ιώ;^X%))%&))*σΌ>&-i6‹@ APO++41V˜³&]i@ ,PO++4-Vιk&.Γο Ήή΄$P+4?VηΆ&NΓο ΉΦ΄$P+4-³*e@ a,$@,,Έΐ@ H  0QΈΐ@ H+*#Ÿ   ???99//9??ΔΦ+ν]22/2/3+Τ]ΤΕΦν10!.'#3>73&&7>7 $&rr ‚ *3$:-"  E#QMCώεkώDDBDKP'"SXX%Ί !4,)1Y/  ?ηΦ'@Q   ????9Φν2Ζ10>73#.'#7»%# ”.11:8/ ',-||/2/684CHH?=7ήΥGΜ>&/Λ‹ΉΗ@ PO++4$υΣ=9@ ?P S―  P  † žW?ύΖ??ΕΦ]Υ]νΤ]ΕΞ]10%#"&5#533267'7Σ"1UN‚ύ&%2cΓΎ eadfώ-0"l>>ZGVΜk&/Γ Ήρ΄P+4$VΣ°&OΓ- Ά+ P+4GΜm&/ΒYΈ ΆJP+4$υέ΅&OΒ¬ Ά« P+4GΜk F²TΈΐΆ HΈΐ@ HD 0@X H ?ν?9/νΦ]νΖ+9/+ν10#"&54632!3!Κ3 33 3ώ{| h(**((**ώpkύϋ$υ8΅ N@0T@P @ P  !Q@ L/P X UW?ύΖ?ν9/νΦ]έ]+νΖ]9/]ν10#"&54632#"&5#53326783 33 3e"1UN‚ύ&%2p(**((**ώ| ea”fύύ0"φΜk C@% D      H?ν??99//99ΖΤ2ν2Ζ]103!5'737Υχώ7,c|l+$ΎfζZ2Φ6Z$υΣ°>@%Q QΐΠ  UW?ύΖ??ν9Φ]ύ2ν2Ζ]10%#"&55'75#5373267Σ"1UN7(_‚ύ@(h&%2 eapS/Ήfβ R4Ά0".Ζ>&1‹@  PO++4?Ή³&Qψ@ PO++4.VΖk&1Γο Ήο΄P+4?VΉΰ&QΓζ Ήδ΄P+4.Ζ>&1_‹@ PO++4?Ή³&Q_Ή@ PO++4 Ζ΅@ @L@LΈΐ@M 0@€Έθ@CMŸΏ@ H!/?Oo`p€/O_ Ÿ ????99?ΔΦΥΦ]]ν]qΦ+]Ε+Πν]q10+++!.'#33'6654&'{WK  XώΔ  E4_]b7ώwk'Z^_-kύ•΅&.(%(G& ζΛ΅&Q^6³O+.YΖkFΉΰ@M/ ?  DDΈΐ@ HH’  ???99?ύΖΖΦ+νήν]10+%&&'#33#"&'73265W(]5oc85-oGN $_Ύ`ώek,gf`$}ύWXe" ?[Ήΰ5@ QQΈΐ@ HWW ??ν?ύΖΦ+νΖ]Φν10%4&#"#6632#"&'7325>.{!a98J+IT )1ωB:ώΗ 9O0ώϊVR_?σΩ&2Š‹@  !P"O++4σΨ‡&RŠ@  ! P"O++4σΩ5&2a‹@ $.P O++4σΨͺ&Ra@ $. P O++4σΪ>&2e$Š@&"$P%O!O+++44σΪ΄&Re$@&"$ P%O!O+++446ι>&5τ‹Ήκ@ '% P&O++4YΛ³&U@  P O++46Vιr&5Γο ΉΪ΄.' P+4#VΛί&UΓ Ήg΄ P+46ι>&5_ο‹ΉΫ@ %) P*O++4YΛ³&U_$@   P O++4(σΜ>&6ύ‹@ 1/+$P0O++46υΊ³&Vύ@  42.%P3O++4(σΜ>&6i‹@ 3/+$P0O++46υΊ³&Vi@ 62.%P3O++4(VΜyF~Ή@ΰ΄L;Έΰ@ M3@ M)Έΐ³ MΈΐ@ M"FB2H8F,Έΐ@" H,G @PG36J/=J''/J ’?Ε?ύΞ?9νύΞΖ]ΦάΝΦ+νΞήν10+++++#"'73254''667&&'732>54.'.54632&&#"!!,-# ")$8E$K6) "*<1 qc9U$=(b'?5"ab ' ?  d  (;,Wb_G -C3Q]6VΊβH‘@ 4 L3@LΈΰ³MΈΐ@L2 S C@CPC`CCJ9S*Έΐ@ H*I Έΐ@0 HI33/33O66W/ @W%>// ??9/9999ύ]Ξ]ύ]Ξ]Φ]+ΦάΕΦ+νή]νΔ10++++#"'73254''667&&'732654.'.54>32&&#"!!,-# ")$1G#O)-0#8.1L5.OH-/!!:/'?. ' ?  g    1%5) h   !3%/$VΫk P@1@ LDΠΰπ! /  !H ?ΥΖ?ν2?99Φ]άΕ]Φ]έ]ύΝ]10+#"'73254''667##5!##!!,-# ")$ £Β£ ' ?   ffύϋ$VΨ`4iΉ1ΐ@> M11@1`1€116?##$$"%QP`5  50+W4%U" !?Ε??Α?3ν2?νΕΦ]άΝΦ]Υ2ύ2Ε]2]Ζ]10+#"'73254''667.55#53573#32>7W!!,-# ")$/ kk{ΕΕ @  ' ?  *C2ΑfvŠfΎ  j Ϋ>&7_‹@  P O++4$υΨ΅&WΕ‚ Ά} P+4Ϋkc@ @ L @ LΈΐ΄ LΈΐ@$ LD  H H ??9/3ν2?ν2ΦΖΕ22/ν2/2ΥΖΖ10++++#3##5#535#5Ϋ£~~|}}£kf΄cξξc΄f$υΨ`%žΉΐ΄LΈΐ³MΈΐ΄LΈΐ@M @ ` p €  ΈΈ@ I  ' QP`pΈΐ@$H&W O_oUO _ o  U ?Υ2ύ]2Φ2ν]2?ύΖΦ+ΠΥ]ν333Ζ]+]10++++7#535#53573#3#32>7#".5kkkk{ΕΕΔΔ "O%+B.ΜTPfvŠfPT  j (I;'σΝ+&8u‹@ (P'O++4;υΆ &Xu@ !P O++4'σΝ&8Š‹@ PO++4;υΆ‡&XŠ@ P O++4'σΝ5&8a‹@ (PO++4;υΆͺ&Xa@ !P O++4'σΝ:)5`@$*€o0@PD`70"/""DΈΐ@ H6-€°''†3€ J ?ν???ν?]νΦ+νΤ]νΦ]νΤ]]]ν10".5332>53#".54>324&#"326ψX6wώ‘'5 !5'nώ‰6X>!ΰ24 &' 43;υΆΓ&Xc ·P+44'σΪ>&8e$Š@&POO+++44;υΡ΄&Xe@P O O+++44'VΝk,+@'D). .D-("J ’??ν??ΦνΦάΕΦν10%3267#"&5467".5332>53‡ 30*W6‹ώ}'5 !5'‚ώuDc;VΆΦ'A@Q)!)`)QP`pΈΐ@ H(  W ??ν??Φ+]ν]ΦάΕΦν10#"&5467#".5332733267²30* :J+{-| œ %5 ;P0φA?qώ: έ>&:i‹@ -) P *O++4 ι³&Zi@ -)%P*O++4 θ>&<i‹@ PO++4XΨ³&\i@ '# P$O++4.Ζ>&=‹@  PO++4C΄³&]@  PO++4.Ζ.&=b‹@ PO++4C΄£&]bΉ@ PO++4.Ζ>&=_‹@ PO++4C΄³&]_@ PO++4‹μ΅7³   Έΐ@ H Q Έΐ@ H W?ν?Φ+_]νΖ+]1034>32&&#"‹!8H&'R!Eρ9K- e%ώ(VΜy&6Γέ Ήέ΄81+$P+46VΊβ&VΓέ Ήί΄;4.%P+4VΫk&7Γζ Ήζ΄ P+4$VΨ`&WΓ$ Ά ' P+41VΥ%@DU W?ύΖ?νΖ]Φέν10%#"&'73265#5!1C'0R&&G"Ύ99M/h%2Vf°βC΅΅ Ÿ?ΕΦΕ10'6654&'C  W΅  .)&)D& pώ†³?΅ MΈΰ@ M MŸŸ???ΕΖΖ9=/9910+++77p1YY3Œx;EE;zj,Ї΅“?ΕΦΕ10!!j ώΰ‡[i‹ͺ@ } ?νάΐΦεΦν10".55332673ϊ5'[Z'5%4!&&!4%³A£ · • –˜?νΦν10"&54632ϊ****% && %‘φcΓ+@M€_Ÿ€ Š?ύΦ]qνΦύΦν10+#".54>324&#"326c?+&&+?A\24 &' 43£V\ @   ’???ΦΥΜ10#"&546733267Z30*-$h œ %C CώΆ΄&@  ??Ε??ΕΦ]ΥΦΕ10'7'7/yϊ/znp1…Fp1„έ>&:Cζ‹Ής@ ,* P +O++4 ι³&ZCζΉς@ ,*%P+O++4έ>&:‹@  +) P *O++4 ι³&Z@  +)%P*O++4έ,&:ƒ‹@+= P 5O )O+++44 ι‘&Zƒ@+=%P5O)O+++44 θ>&<Cέ‹Ήθ@ PO++4XΨ³&\CζΉφ@ &$ P%O++4Ϊk@ yy??ΦνΥν10#Ϊώ£d]kύ•kfy #2@„― Ώ  „$}! %}?ν9/99νΦύΦύΦ]ν104632#"&74&#"326'#"&54632fMHGMMGHMΚΐY``YY``Y/::/0993Y }r V@ @ LΈΐ@% L ?9/////9Φ]ΕΥ2ν2/Ε210+]+3##5#56673T))T§&M0%IrΞJMM@@e3c4 q|r€Ήΐ@ M@ L@MΈΐ³ MΈΐ@7 M― M „ 0@  Ÿ  }Ώ}E?ν299//ν]ύ]ΖΦΦΔΕΦ]νΔ10+]+++++#"&'73254&#>73#|BS A&!:IGΤ‰WC5C O $ 991Q  ;bss w@@M@L@LΈπ³MΈΐ@3L€| ` !Ÿ| } !}?ν99//Αν]ΦνΑ]Φ]qν]Δ10+++++"32654&'2#"&546366ζ 8 C8!2"EGs?E¬PA=.-"OIcqP k}r ?@( @ M @ M M M L  s?ν29/ΦΔΥΥΖ10+++++667#5!£ 2(Ÿ$ X€6VK=IT+jŠy)5¨Ή1ΐ³M1Έΐ³ M/ΈΘ³M)Έΐ@ M MΈΐ³MΈΐ@$M L @ M6$*0 7@P@ Έΐ@ M  67-3'!7??]9/]99////+]]99910+++++++++#".5467&&54>3232654&'74&#"66ŠCN,8 !3"'4 !Β%^q/;# '$%#* )      ’y !†Ήΐ΄LΈΐ΄LΈΐ³MΈΐ@@M M @M @M @M@ L„„ #„"p} }#}?ν99//νν]ΦνΔΦ]]νν10+++++++++2676#"".54>32#'667 6 !/ !2"FFv~ECΦOC(+"QHbqO fϋmoώτ¦f”ώτq‚mώτqϋ€mŽώτY}fpώτqϋ|fqώτbϋsgrώτk}fsώτjϋŠmtώτ’muώτ5σ­΅!/4@%I 1 /0//R!!0}*€?ν?ύΖΦ]Φ2ν]2ΦΦν1074>323267#".55'76654.#"(6&/ fT*-&!@+,<$; ­9@  δ=Q.-6_F'?9 >-; *0‚4yL 5+τΩ† 1aΉΰ@@ M/(M@  3°/?o/,,|2////_/o//―/Ώ//&£??ΥΖ]Φύ]2Φν]]]Ζ]10++7"32673#".54>32'4'&&#"3!25pD*,I ^6/Q<##?―@A@@A>C|+&|p€|18|C@B  !BA@ ? >%""%0 `  œ5€));.€ ;€ š?ν?ν9ν??]9///????ΦΤν]ΖΦΤύΦν]ύι/Μ‡+‡}Δ10+++++%467&&54>32#"&6673#54&'326'6654&#"# ''%6@3A"2?U‰#F  _ώΓd=E"   +0&ϊ– ώV   |  ͺύ•kωυyBMZ^Ψ΅H@MΈΐ@„L@"M@L=@ M$@L#@L!@M\^]^―[\[\[`!|:)|6:6:6`_@MŸ―|HC||NU|`]_0B_^] \ [883€0?`?°??#&,€3Q€FFXK€ X€ š?ν?ν9ν?ύΦν?]ν9=/????ΦΖΒΠΤύΦνύΦν]+99//ννΤ‡+‡}Δ10++++++++%467&&54>32#"&32654##532654&#"'6632#"&'4&'326'6654&#"# ''%6@3Aφ '< ' 840*"-3€#F  hώΓd=E"   +0&ž  9  6 )%+ ώΘ   |  ͺύ•kωυr;FSW>@:@L:@M9@L9@MΈΰ³MΈΐ@M@LPM@M(Έΐ³M'Έΐ³M'Έΰ³M'Έΐ΄LΈΐ³MΈΐ³MΈΐ³MΈΰ³MΈΐ³MΈΐ@fLUWVW―TUTUTY-| ΰY―Ώ|A<||GN|YVX;‚9P88&XWV U T:92&#8*€0#`#°##J??QD€ Q€  š?qν?ν9Ν?]qν?9/9ν?ν????ΦΦ]ΕνΖΠΤύΦνύΦν]Τ]νΤ‡+‡}Δ10+++++++++++++++++++%467&&54>32#"&#"&'732654.##>73#4&'326'6654&#"# ''%6@3A›?-!,2*!₯`6#F  hώΓd=E"   +0&0#!  =   " ?ώ   |  ͺύ•kωυr%2AEΦ@>@M> M>@ M> M:Έΐ΄LΈΰ@\M@M@LοCEDE―BCBCBG―Ώ| ||&-|GDF8<:A3 :°:_:o:::FED C B0A`A°AAœ8;)Έΐ@H)€ #€ 0€  š?qν?ν9/ν+?ν?]????Φ]]ΤνΥΕΒΠΤύΦνύΦν]Τ‡+‡}Δ10]++++++++%467&&54>32#"&74&'326'6654&#"%>7#53%# ''%6@3Aœ#F  ώΨ dΑ ,ώΓd=E"   +0&)   |  ·"0)&?2)+4%σύ•kψτr +/¦Ήΐ³MΈΐ³MΈΰ@XLDT-/./―,-,-,1)*|1.0+‚Ÿ##o00/. - ,"€ +)š€  0`°œ??]9///?ν?ν9ν????ΦΤν]Τ]Τ]νΒΠνΤΐΤ‡+‡}Δ10q+++6673#5#"&'732654.##>73##"2?Us?-!+2+!₯_?ώΓd=-ϊ– ώ·0$!  =   " ?―ύ•kψτy >Bφ΅2@M-Έ¨@/M) M"@M!@M2 M2 M@L@L@L Έΐ³ M Έΐ³M Έΰ³M Έΰ³HΈΐ@SL@BAB―?@?@?D-|99CD|DAC"#C ‚Ÿo  3CBA @ ?/™6!0"0"`"°""œ  š€ €/ν?ν?ν9?]qν?ν????ΐΤ]Τ]νΦΕΒΠνΔ9/νΤ‡+‡}Δ10+++++++++++++++%#"&'732654.##>73#'#&&546776654#"'6632%#ˆ?-!+2+!₯_΄Ρ)  ): '= $rώΓd=©0$!  =   " ?ω? #&   6(*" Άύ•k ψτy'HLώΉ4ΰ΄ L4Έΰ@ M4$4 Έΐ³M Έΐ³M Έΐ΄L Έΐ³M Έΐ³M Έΐ΄L Έΐ³M Έΐ³M Έΐ@XLLJIJ―KLKKLINF:|+N||NKMH‚Ÿ@@o33M'MLK J I?€((0HFš7€0 €0$`$°$$€?ν?]ν99=//ν?ν?ν9ν????ΦΖΤ]Τ]νΖάνΤνΠνΔΔ‡+‡}Δ10+++++++++q++32654##532654&#"'6632#"&'#"&'732654.##>73## '; ( 840*"-3|?-!+2+!₯_QώΓd=½  9  6 )%+ Χ0$!  =   " ?―ύ•kψτr -26ΉΆ2@L0Έΐ@M L @L Έΰ΄ L Έθ@SM6434―565563857%?""(221-*7 ‚o  7|65 4 3"2€(0&0&`&&°&&œ!€ š€ ?ν?ν9ν??]qΥν2????/νΤ]ΤνΠΕΡΒ/2Ε]2ΖΔΔ‡+‡}Δ10++++++%#"&'732654.##>73#3##5#56673%#ˆ?-!+2+!₯_Ύ$$P|-  3eώΓd=©0$!  =   " ?Ά”?''-+L/@)ύ•kχήr(,₯@ @L( MΈΐ@;L*,+,―)*)*).|  ΐ  .+-#$-|Ώ-,+ * )%((%!#Έΐ@ M`#°##œ!€ š€ ?ν?ν9/νq??]+9///????Τ]νΦΤνΒΦ]ΔνΦ‡+‡}Δ10+++%6632#"&546"326546673#5%#Ω0= 51740=ka_ ώm"2?U²ώΓd=Ώ )'*449RP™  Γϊ– yύ•kχήr3>Bλ@ =@L4@MΈΰ³!MΈΐ΄LΈΐ΄LΈΰ@ M@4Έΐ@jM$4B@?@―ABAAB?D%|1D=| @ MΏ ί  DAC3‚0C7|ΏCBA @ ?++31"€ 0@0`°ΰ4€ š:€ ?ν?ν9ν?]qν?ύι/????Τ]νΦΦνΖή]+ΔνΤΤνΖ‡+‡}Δ10q+qqq++++++%6632#"&546#"&'732654.##>73#"32654#Ω0= 51740=kaώž?-!,2*!₯` ;ώΓd=Ώ )'*449RP0#!  =   " ?ώ7  ύ•kτr ’@^@M@ M@M@M@M M―   ›  0`°œ??]9///??ν????ΦΤν]ΤΤνΖΠΕΔ‡+‡}Δ10++++++6673#5>7#53#"2?U8 dΑ 1ώΓd=-ϊ– ώ"0)'>2)+4%kύ•kτy,0—@e M M @M @ M@M@M@M@M0.-.―/0//0-22/1|'!110/ . -™$0`°ΰœ› ??ε?]ν?ν????ΤΤνΦΔΥΤνΖΠΕΔ‡+‡}Δ10++++++++!>7#53#&&546776654#"'6632%#M dΑ ΙΡ)  ): '= $nώΓd="0)'>2)+4%΅? #&   6(*" Άύ•k τy'6:Μ@3@M3 M/@M.@M Έΐ³M Έΐ³M Έΐ@_M:878―9:99:7<-1<|| 0€ °ΰπ<9;6(/;';:9 8 76 -/› €0$0$`$°$$?ν?]qν99=//ν?ν?????ΦΖΤΤνΖ99//]qννΠΕΔ‡+‡}Δ10+++++++32654##532654&#"'6632#"&'>7#53# '; ( 840*"-3A dΑ 3ώΓd=½  9  6 )%+ ώ€"0)'>2)+4%kύ•kτr $΅Ά @LΈΐ@nM @M M@M@M@M@M$"!"―#$##$!& &#%ΐΠ %/%$# " ! 0`°œ ››?ν???ν?]Υν2????ΤqΤνΠΕΡΒ/2Υ]Ε]3ΖΠΕΔ‡+‡}Δ10++++++++!>7#533##5#56673%#M dΑ Σ$$P|-  3_ώΓd="0)'>2)+4%r”?''-+L/@)ύ•kτr /3Β@ ,@M, M Έθ³M Έΰ³M Έΐ@ M$ 4 ΈΘ³MΈΐ΄LΈπ@IM3101―2322305&*5|524/!(4 ‚ 432 1 0/ )›&(› €00`°/ν?]qν?ν?ν??????ΦΦνΤΤνΖΤΤνΠΕΔ‡+‡}Δ10+++q+++++#"&'732654.##>73#>7#53#p?-!,2*!₯`ά dΑ 3ώΓd= 0#!  =   " ?ύΝ"0)'>2)+4%kύ•k τ{"-1²@$,@M@M M@M@M@M@MΈΐ@NL1/./―01001.33,| 302"2&|ο210 / .›› #€ €)€0 0 ` °  ?]qν?ν9/ν??ν?????Φ]νΤΤνΖΤΤνΠΕΔ‡+‡}Δ10++++++++6632#"&54633>7#53"32654%#έ1= 51640>e\ x dΑ ώΧ :ώΓd=7 )'*449OPύ…"0)'>2)+4%β  ‰ύ•kχπr'+ΦΉ&ΐ³MΈ€@ LΐM Έΐ³MΈΐ³MΈΐ@M M@M/Έΐ³MΈΐ@MM+)()―*+**+(- ||-*,,&|,+* ) (0`°œ€ € #€ š?ν?ν9/ν??]9///????ΤΔνΦΤν]ΖΦννΔ‡+‡}Δ10++q++++++++%667#"54632#6673#527&&#"#0= e64(fgώί"2?Un_ώΓd=; P*4 )RM6ϊ– ώž Ϋύ•kχπy:>Θ@ & M% MΈΐ@ M.@MΈΐ³MΈΐ³MΈΐ³MΈΰ³MΈΐ@MM><;<―=>==>;@||`@=?/?|ο?)|5>= < ;+™20`œ€ € € š?ν?ν9ν?]ν?ν????/ΦνΤ]ΔνΦΔΖΔ]ΦννΔ‡+‡}Δ10+++++++++%667#"54632#727&&#"#&&546776654#"'6632%#0= e64(fg`‹Ρ)  ): '= $iώΓd=; P*4 )RM™ %? #&   6(*" Άύ•kχτr*/3ίΉΐ³M&Έΐ³ M%Έΐ³ M!Έΐ³ MΈ ³MΈΐ³MΈΐ@M@MMΈΰ³MΈΐ@MM3101―2322305||524" %/.*&4|432 1 0/"%`##°##œ+€ € € š?ν?ν9/ν?ν?]Υ2ε2????ΤΔνΠΕΥΦΐΥΕΐΖΠννΔ‡+‡}Δ10+++++++++++%667#"&54632#727&&#"3##5#56673%# 1< 5164'eg_™$$P|-  3]ώΓd=; )'*4 )RM™ β”?''-+L/@)ύ•kχπr3=AαΉ5ΐ³M4Έΐ³MΈΐ³$MΈΐ΄!"LΈΐ΄LΈΐ³MΈΐ·L Έΐ@[MA?>?―@A@@A>C%|1C6|ΰC@B3‚0B<|BA@ ? >*31"00`°4€ € 9 š?ν?ν9/ν?]qqν?ν9/ν????ΤΔνΦΦνΖΦ]ύΕΤΤνΔ‡+‡}Δ10q+q+++++++%667#"54632##"&'732654.##>73#27&&#"#0= e64(fg³?-!,2*!₯`iώΓd=; P*4 )RM)0#!  =   " ?ώ] Ϋύ•kχήr!+/£@ @M M#Έΐ³M"Έΐ³MΈΰ³MΈΐ@DM/-,-―./../,1$|1.0!0*|0/. - ,0!`!!œ"€ € '€ š?ν?ν9/ν?ν?]????ΤΔνΦΤνΥΕΖΦύΕΖ‡+‡}Δ10++++++%667#"54632#>7#5327&&#"# 0= e64(fgΨ dΑ ζ bώΓd=; P*4 )RM"0)&?2)+4%θ Ϋύ•kχτy.9COSfΉBΐ³M/Έΐ³MΈΐ³MΈΐ³#MΈΐ΄ !LΈΐ΄LΈΐ³#MΈΐ΄ !LΈΐ΄LΈΰ@@MN@MN@LN@L/NM@MM@LM@L/ML@ML@LL@L/L;Έΐ@%M:!@MSQPQ―RSRRSPU<|+URTB|#TΈΐ³"MΈΐ@FMo| /°//4|o|JD|TSR Q P:€ &€. ?€&šG€22 7€00`M€ ?ν?]qν9ν?ν?ν9/ν????ΠΤύΦνqύΦ]νq++ΤΔνΖΠύΕΔ‡+‡}Δ10+q+q+++q+++q+++++++++++++467&&54>32#"&667#"&54632#4&'32627&&#"6654&#"%#''%6@3A 1< 5164'egŒ#λώρ  {ώΓd=»!   +0&ώ¦ )'*4 )RMΘ   ώά Ÿ  3ύ•kυΕ΅ 0O@2@ M@ M@ M@ M.dd   2&d1t!!)ttŸ?ύΖ?ν9/νΦΔνΦ]νν10++++"'6632#".54>32&&"32>7&&ΐ-'<M`67[B'E38O1.N ( +# -6O _ ;a}B?fA6O39_C% HWξ*558$>T0 λk@΅ M Έΰ@M   H?ύΐ??ΦΕΔ9=/999910++36733&& ,Z*†,W)ς,Ά(·-‡ˆώΟ²σZΓpqΔ(ŸΛk(@ nnΐΠΈΐ@ H‡??Φ+]ύΦν10###Λ{­{kύ4fύšΜŸΠk/@D `HH‡?ν?ν9=/ΖΦ]ΥνΖΖ10!!5667&&'5!!T,,+%ώO,`./\,ώβ**)CGFeGQš@BŒHDfA@> λy'wΉ!ΐ³M!Έΐ@H L@M@ L@M@ L) F―Ώ0"""F$(%H#" HJ?ν?ν???νΦΦύΔ]Φ]]Δ]ύΦΖ10++++++4>323#56654.#"#53&&)BU-,UC)$*QΧ"5 + + 1&ΩT*%bKjCCjKB~326632#"&'&&#"32677/-3$.%%.$83$-&&-$7E  ϊ*P$#6%%5#)$#5%%6#)r 1[ΔΆOΉ ΐ³MΈΐ@M/? QΈΐ@ HW W¦?ν?νΦ+Φ]]νΖ]]10++46322#"#""&퀑Ό[eF&[eF&νahk,$ώ,ahm,$>ηΟ6aka“(ωΜ=@%     r rO_§?Υ]2ύ2Φ2ν2?Φΐ910373#3#'7#537#(π@K)Rˆ1Ήο?K*U‹1Ό›w)Nf]fy)Pf],Ο. G@) L0Pp @r ¨??ν]9=/999Φ]ΕΦΔΕ10+%%!!-€"ώθ"ώ€£ώ]•™lddl™Αf,Ο- VΉΰ@/L L 0Pp @r ¨??ν]9=/999Φ]ΕΠΕΠΕ10++'%%7!!Οώ€#ώθ#€ώ]£ώ]&™lddl˜ώΡfρΩ{ Œ@ ppp Έΰ³M Έΰ³ M Έψ@? Mf  M M Mi p ž??9=//////9////]q9910]+++]+++]]]>7&&7&'66;764m>>m45nό+./.+61VPJ$I›abšIH›bS?I**F##Fΰ΅+Z@8 @ M TΟ- Q 0@Q"!,W( U# "U X  ???ν?ν?/?μ?νΦΥ2ύ]2ΥΦύ]ΖΤ]ν+10!#37#"&54632&"#"3###5354>32Λrr+ ** +Β VVs55(A0Φ‡%))%&))A  fώpf-J3ΰ΅ͺχτ΅ '|@7 @ M@ M  ) 0PQ@ M_@'' 0@QΈΐ@"H(W$U U  W?ν??ν??ν?νΦ+Υ2ύ]Ε3Υ]Φ]]+ν]ΐ]10++.57&"#"3###5354>32α09 r"Φ VVs55(A0 *9"ώ#)έ  fώpf-J3χτ΅¬frδoky¦έ”kqy‚δkqr€δŽkYx}έpkqr|έqkbrsήrkky}έskjrŠδtkx’δukfoώ‰—¦ϋ”ώ‰q—‚ώ‰q€Žώ‰Y–}ϋpώ‰q|ϋqώ‰bsόrώ‰k—}ϋsώ‰jŠtώ‰–’uώ‰ΔΫ1΅΅Ÿ?ΕΦΕ10#51O΅ΪΪ€VPΣΆ ’?ΕΦήΝ103#"&'52>5ξ_=8# -0.; ‘MΔΆ Š?ΔΦΥΞ10#&67mB>,JS=+(Δ /΅΅Ÿ?ΕΦΕ10#5/M΅««^‘ρ +U˜ρ +qψƒq4/…Εε*΅Τ΅#<q…†ε>*1…Ηε?*m…ƒε@*?…΅ε^*?…΅ε`*„^| l7r§‚Εrό6Ώcs*τct*›^“ x7©ϊOp|Ÿ2dΓ†62dΓ–6Eψ²tš’υΦΆ 'i@B"@ M!@ M@ M@ MS)'Q!$% "(&%# W UW0 !0s ?ν]2?]νΥν?ν???ΦΖΔΥ2ύΕ33Φν10++++%4&#"326#6632#"&'#5357Y')$  -4Ž-,D-8R4/a"77{ξBF AΗSI #AZ78[@# S:Oψηr!.9G@%2J+J;9#R :8W#"9  9"&W ?ν?9=/////9ν2ΦΕΦν2ΦνΤν10"&'#"&54>3232>54&#'2654&#"#=% Z $A\9!~v"K,²&::4("!*ξ,K7gd Ζώ’.33&ΆσΥy0΅ F`Έΐ@ H! JJ ?ύΖ?ύΖΦΖΦ+]ν10"&'732654.#"'>32Η:X@0RJ,8)A +8 @eF&‹ a qj=R1b (QyQ›¨σΎ*MΉΐ΄H#Έΐ·H#,FΈΐ@H+$'J  «J J J ?νΥν?ύΖ?]ύΖΦ+νΦ+Ζ+10&#"3267#".54>326632&&#"‡8/?I$2 #2*I,9[@#(E\3!$<&!  ρli>T3a*SxNRzP' ,$^ (σ +,)@%.S-%!W(W ¬W ?ύΖ?ν?νΕΦνΦΖ1074>326632&&#"&&#"3267#".(!>Z9  1))    ./"BD9E*A\<λ3ZC'- Z1 %3@K g &C[ψΩr«ωβr*RΉΐ³MΈ€³MΈΐ@"M@M"F, 0D „+H 'H?Δν2?νΠνΤν]Φν10++++2#"&'#"&54>232>54.#"ϊvr"=T33 Z 'C[<  &$ r•§XyK!  ("+6 ύς!:O-%L>'ϊΎk@@(@ L@ LQQS W WOH?ύΦ]ν?νΦΔν]Φνν10++5!#"&54>3352>35#"Pn-P#|ƒ#A\:)=/8A@fύ  dg7K,ώ^Ά'22/υ― 6@ @ M @ MQ S W W H?ν?ν?νΦνΔΦύΐ10++73267&&#"5!#"&546325™/4$,(Nc"b/nq_]0ξ?P Ffύ_ ‚qs… ~XΧβ*:[@<@L@M M LS5S @`<+S!;00 8W&W ?ύΖ?ν9///ΦΔνΦ]νΤν10++++#"&'732>54.'&&54>32>54&#"Χ 2'%-C+)L": / =D9P21R:!ώΖ&!5**37871#3% a  %iH0L63I9*# $'(432?Μk R@@ M@ MD Έΐ· H Έΐ@ H @H H H ??ν?ν9/ν]Φ+ΖΖΦ+ν210++35!5#535#5!?άάόwff‹fύ•σΥy'T΅'@ M$Έΐ³ M!Έΐ@% M@ M'S@`)S ('H"W W?ύΖ?ν9/νΦΔνΦ]ν210++++4.#"'>32#".546732>7c.=!<)*'EfC!zj:R4m;-)Y2E+ ` 1VuDž¨1Qh6#aQR-;!σηy0Ά&@LΈΐ³ MΈΐ³ MΈΐ· M%@Έΐ@/H20@ M0,ccp€1&)g"@00e" g ?ύΖ?99=//ν]ύΖΦ]νΤνΥΕ+Φ+]Ζ10++++#"3267#".5467&&54>32&&#"33~S4&!,,\!(*t<.VB(<)&$#:K)6g)*S'&747] "  f-H5:JK".A(_'#(ΜYΊk.@DHH J?Εν?ύΦνΔΦ]ύΐΦΖ107#"&'7325!!3#Ί%>- +2{ΰΰ.E/c?kf–fΗσΎ,@@%D° .F°((-J# „«J?ύΖ?ν?ν9/Φ]νΦ]_]Φν1026632&&#"&#"326753#".54>!$<&! ! 8/'4 FD  {]B:]B$&D\y ,$^ :%44>ώλ1M44M1 σΞk<Ήΐ@ M DHJ ?ύΖ?ν2ΦΔΥύΕ]Ζ]10+3267#".5#5!$-0:47G*twώ΄1( e  7H)Jff6ΏkpΉΐ@@ M Q0@PQ0@P  H H  H?ν2?9/3ν2ν2??Φ]ΥύΕΦ]ΖΕ2/ν2/Ε2/10+3535#535#5!#3#36‡ZZ‡‰†ZZ†f©c“ff“c©f- xR²DΈΐ@ H! DΈΐ@ H ­  ???9=///?ύΖΦ+ύΐ2=/ΦΦ+ν10!.'#37>32&#"] $08{{j!$ 6_Gm NNHώεkώš*  VŠB±[?η΅%^@! 0P`p' DP`pΈΐ@ H&#W¦   ??9=///??νΦ+]ύΐΕΦ]ΕΦ]Ζ10>73#.'#4632&&#"»%# ”.11:8/ ',-|L[   1/2/684CHH?=7ήUP_>;υκ΅H@ @Q  Έΐ@ H  s  HŸW?ύΖ?ύΥ2ν2Φ+ΖΥ22ύΕ3Ζ]10%#"&55#535#533#3267κ"1UN‚ώ„„&$2 ea€UΏfώΫU‰0"έ΅*K@)*)( o,!"o+(sW%¦???ύΦν2222ΦνΦΕΦν9=/9910#.'#>7&&''7&&#"'6632706-# Ž ˆ-03kb 0 1KmB”-$QRN!$RRO@}th, &J# b (1'Jτδk&£Ήΐ³ MΈΐ³MΈΐ³ MΈΐ³MΈΐ@ M@ LΈ€@AM$4R$DR 0R€'(J! J?ν???ν99//9///]]]ν_]ν]ν]10+++++++".533267&55332673#"&'š)4 d  d d-I+2 2H-΅ώF"%4ΒΟ0' ύ‘  ΌYΖkV@6/?RΟί@ HR   ’??ΥΖ??99//]Φ]ΜΦ]νΦ+]ν]10!&&'#"&'732533c*c9 :- +1c85-ogΝgώw)C2c?k,gf`$}ύ•?[Ήΰ,Ά QQΈΐ@ H  W?ν???Φ+νΦν106632#4&#"#?!a98J+{.{Η 9O0ώRžB:ώσΩy !t@Ÿ`p`pΈΐ@/H"#/ ?  J žH@ H 0J?ύ]Φ+]ν?ν]9//////+]]]]]]104632#"&2>7#"3.vimrtjmsί$ Β %# Β $6 ££  ££8->$%>-°,=##=,σρΛ-(@$Sd/S.J Š)J?ν??νΦνΦνΤν1046326654&53##"&732>54.#"viM2i"'tjms}& '& &6 £((  *J P ££ -O:"";N--O:"";Nσμ4 ,2@'SR @`.!S -*W$W ?ν?ν?ΦνΦ]νΤν10%#".54>3266544'332654&#"Ψ :Q22Q; !;R0F2 fώΒ-201-201μ8[B$$B[87[A#"   *<I+?NN??MMσάy%9CΉΐ@'HRy&0y€ :5J! J +J?ν?ν??νΦ]qύΦύΦν+104>326632#4.#"#".74.#"32>"7&,,44`  $6$%6#Ό   7`}H4Tk7ώ±•(0 G`~II~`>T23S>?S33T[ββ#7_@ ΐRΠΈΐ@ HRP3`3p3ΰ3π33 )0))R  °  Έΐ@H 8’ ??q??Φ+qύ]Φ]ύ+]Φqν]10%#".54>326632#4&#""'"32>54.H%;**9$%;*2 *2'`# ™    μ:[@""?\:7[@$ )G7ώ2°=4:; 8-.9 9--9 Ψr$MΉΐ@L/"?""d& R Έΐ@ Hd%H  H?ν2Δ?9/νΠύ+άύΐΦν]10+2####"&54>""32654&ϊ;T6_`i Z 'C[a "+&r1O9ocΡ ("+6 b,<66?[Υ΅+1@F-&Q ,"W W¦’)W ?ν??ύΖ?νΦύΠΐΦΔν10%#"'#4>32&#"62324&#"326Υ.F./2{*9"!mt}23 (,*λ6[A$±²0A'`'4„u?Qώώ G6  ΅&I@D (F("DΈΐ@ H'¦#H‡J?ν??9/ν?Φ+ύΠΐΦ]νΦΕύΖ102#.'##3624&#"326Φ5V>!/74-% ‚ !*07{{ u<1 ?8r2M49Y*_^V"PYX%δ΅DΚ1.Ί1(σΜy0IΉΐ@' MF" 02,F@ P  1J'J J ?ύΖ?9νύΖΦ]ΔνΦ]Φν10+%267#"&54>7>54#"'6632 6K$ "/='sq"4@'b(<$U9cq 2;*" )Zd _W3C- G_bW,;(  6υΊβ3o@ (M MΈΐ³ MΈΐ³ MΈΐ@, LS'51S  4P`W,,"OW" @W?ύ]Ζ?ύ]Ζ9/ν]Φ]ΔνΦΦν10+++++%267#".54>7>54&#"'6632 (P"V=32&&#"3#32>7#".5‹gg3N7*B.8*ΑΑ* "P,*D0pf-J3k-#f΄4( i.O;YΫk;@"`  DΠ W’H?ύΐ?ύΖΦ]Ζ]Υ]ύΕ]Ζ]10#5!#327#"&5Ό£Β£1+ OQffώDfX^'σΛ"4@@MD©$D@#Š t ?ν???ΔΦ]νΤνΤν10+".53326532654&'3έ5F*s&%!3'f-=+G !>X6‹ώtN<>M‹   /= ώΈ6X>!)υθ4 1@@ L QR "Q!W ¨??Δ?ν?ΦνΦνΤν10+36654&'3#".5332679#f-;Y35C&r" % Φ   /= ώ}  ;P0A> σλl'<@#F?""`$π$$)F 0($H#HJ ?ν?ν?νΦΕ]ΦνΦ]Ε]Φν10#".5467#5332>54&'53#ζ)BU-,UB)"+QΧ"4 + + 1&ΩU+% KjCCjKA54.#"'66:J,ks>Q1|")"  "r*RzP ™!?Z8†ώ…)8"7L-7R7k t|Ήΐ³ MΈπ³ MΈΰ³ MΈΐ³MΈΐ@. M―ΏD J?ύΖ??9///99//99ΖύΖ]310+++++>32&&#"#5&&'3( )+7  ^{3M ƒ ρ0# Xμνλ`Δ\HKI Xωέ,kΉ,ΰ΄ L)Έΰ@7 L M MLQ,,-) .))-."-, #&g ??ύΖ?ΖΖ9=////99ν10+++++6676632&&#"#"&'73267&&'˜89&  $/=)* 0;K"ΦLSX)Oj"63 a0RMM*'?+ f*&sίs.Ζk±@ @ L@ M Έΰ΄L Έΐ@f M@ L M` M@ M@ M@ L M@ M   H H@pH ?ύΦ]ΐύΐ??ν?9////////////////10++++++++++++3#!!5667#537#5!½;0j€- ώh3 `˜Zξ‚ZNb,R'fG,`8b˜fC΄ΦΣΉΐ@M@ M@ M Έΐ³ MΈΐ@w MP― ― °ΐΠ°ΐΠ°ΐА°ΐΠΏΏΐ Π ΐ Π     }OU  U ?ν2??ύ]Φ2ν2?9/////////////////]]]]]]]]]]9]10+++++3#3!5667#53667#5!ͺ-QŒ&ήώ)?x"Β]|7"O3-fK?O-fσαk&QΉΰ@)M"S `(&'Js& &&  H?ν??9///νύΖΦΦΕΤΕΦ]Δν10+>7!5!#".'732654&##¨++& ώπ‘ '.12D*Šy ;3) 'N17>54.#5>7#5!&&-*<$-# %C6 "! βz "#"6%8R5d[ ,   E  f[ ! !/"'3#   %Θy(wΉΰ@FM"@ L! M!@M! Mc  *)* c#)"g& @e e ?ύΔΦύ]ΐ??ύΖΦΦνΤΐ9////Φ]ΦΦν10+++++3#!!&&445467#536654&#"'6632Ά>š,Bώf8&I―(/%)# ='h7#6632T2- '9'+Lg;{ [7#5332654.#"777->%5-*@-Π  rΛ^Ήώ~/―"VU%z6^zHcIyŒ*nxz6]LHqff=]ύνtkCX5ζ)?@+iϊ  "/5—@0477767 ΐΠΰΈΐ@ HR@(P(€((°((#Έΐ³H#Έΐ@% H#R0@P6€7523 1  €" -₯ %₯ ?ν?ν??ν??έΕμΦqύ++Φ]qύ+]Ξ9/]9]ΦΐΦΔ10#"&'66323#5>7#5332654.#"777->%5-*@-Π  gΒ[Ήώ~/―!VU%z6^zHcIy HNP$]G0PHE%]ώ‚tkCX5[)@A+j σ ΅!06­@/@ M.@ M M155!87'Έΐ·HΒ''Έΐ@K H'R/7/ O  /.?._.Ο..R /O/Oo―634 2 €! €"₯ ,₯?ν?ν???ν?ν??έΕ/]qΥΖήύ]ΐ]Φqν+_]+99//ΖΦqΔ10+++%#"&54>32573#5>7#53"327&7773JI+Wγ  gΒ[Ήώ’   }!VU%z †t4Z@%ΣώΟHNP$]G0PHE%]S 1>0&σ)@A+jσαkR@9O _ Ο ί  R@ H 0€π 0ΐΠRUJ ????νμ/ύ]Υ]qΞή+ν]103#332>53#ύλW”+#W(H;kύλ# ΛώH2H/-Vγ—#o@.Sί  R_% `pΐΰπ0@PΐΠRΈΐ@ H$S°!Π!!˜ J’ U?ν???ύΖ?]νΦ+ύ]Ε]qΦ]ύ]ΖΤν10!!3332653#"&'#"&546321ώόW­9& X);%+ ϊ())(kύλž-2ΘώC8J.ο%% %%7VΡ΅+œ@ S Έΐ³HΈΐ@Z H€ @ H -o++Ο+ί++@H+%@H%@ H%€##@#P#`##Ππ_o,%Ÿ+@ H+₯S˜@ H₯’ ??ύ+Ζ?ν?ν+?Ζ]]Φ]ν++Δ+]Φ+ν++Τqqqν1032653#"&'#"&54632.57ζ& X);%+ ϊ())(ή:I*X +H-2ΘώC8J.ο%% %%ύ…,:" ώ!( σαk R@4@H/?O   @ H ₯    ???99//???νΦύ]Τ+ύ]Φ]Φν+103.'#3372>53Η WK^W"  W %D7:[Y^=ώwkώ•kύ•H"ΛώH1G/VΡ— +™@ S&& @H@ HOΈΐ@PH @M/ ? O   @H @ H @M/?O0@Ÿ―,#S)˜₯’     ??99//????ύΖ?νΖ]Φqύq+Τ++ύq+Φ+qν++Φqν103.'#3332653#"&'#"&54632Η WK^W,& X);%+ ϊ())(:[Y^=ώwkώ•kύ•H-2ΘώC8J.ο%% %%Vγ—'3«@"'@M'@M@M@M.S (`(€( ((Έΐ@H(5@H@ HΈΐ@H @H @ P `  Έΐ@)H @H@ H@'4+S1—₯$’  ₯ ?ν????ύΖ?νΖΦqύ++Φ+]ύ+Φ+ν++Φ+]_qν10++++6632#4.#"#32653#"&'#"&54632K-(7!W Wζ& X);%+ ϊ())(Η *D0ώ&!(ώ~H-2ΘώC8J.ο%% %% λ>&$_‹@  PO++4,υΉ³&D_@ /3P4O++46Ώ>&,_‹@  PO++4$υΣ³& _οΉο@  P O++4σΩ>&2_‹@  $P%O++4σΨ³&R_@  $ P%O++4'σΝ>&8_‹@ PO++4;υΆ³&X_@ P O++4'σΝ>%15x@OD 7ο44°556&³,³Ο P ` O  6D °6/4ί4ο444™2†/²Ώ))#²Ώ±± J ?ν???]ν?]ν?ν]qΦ]νΤ]]]ύΦνΤ]Ε]Φ]ν10".5332>53#"&54632#"&54632%3#ψX6cώ₯'5 !5'Zώ6X>!³~G;υΆά&X§@P -O !O O++++444'σΝ>%15k@G,,/,,³Ώ&ί&&7D 7246³  P Π ΰ  6D@P635†/²)ž#²ž±± J ?ν???ν?ν?ΕΦ]νΤ]νΤΕΦ]νΤ]ν]10".5332>53#"&54632#"&54632''7ψX6wώ‘'5 !5'nώ‰6X>!Ι(E5P;υΆ&Xͺ@#P %O O O++++444'σΝ>%17ͺΉ1ΰ@M- M+ M'Έΰ³M%Έΰ@M! M MΈΰ@ M,³ί&ο&&&9D 9628³P  Έΐ@$H 8D@P85†743†/²)ž#²ž±± J ?ν???ν?ν?ΥΕ?Φ]νΤ+]νΤΕΦ]νΤ]ν10++++++++".5332>53#"&54632#"&54632%77ψX6wώ‘'5 !5'nώ‰6X>!Ι:.##.N;υΆ&X«@P 0O !O O++++444'σΝ>%15œ΅1 M-Έΰ³M+Έΰ@M' M% M!Έΰ³MΈΰ@DM M³ί  7D 073556,³°&Π&ΰ&π&&6D642†)²/ž²#ž±± J ?ν???ν?ν?ΕΦνΤ]νΤqΕΦ]νΤ]ν10++++++++".5332>534632#"&'4632#"&7'ψX6wώ‘'5 !5'nώ‰6X>!ΙœP5E;υΆ&X©@#P +O O O++++444υΡβ"Ή ΐ³ MΈΐ³ MΈΐ³ MΈΐ@@ M@ M@ M@ M@ M @ MO  "S @P$Sp#  W W?ν?ν99//Φ]ΔνΦ]ύΐ10]+++++++++%#"&547!4&#"'66323267Ρ&=P*il0K<%D H-<_C$ώΕ #/-π>^? {v.4h =Zm$;' λ>&26_΅5@M2Έΰ³M2Έΰ@&LΤ2. M. MΫ.ϋ., M, MΫ,ϋ,(Έΰ³M(Έΰ@ MΤ(τ(&Έΰ³M&Έΰ@&MΤ&τ&" M" LΫ" M MΫ ϋ Έΰ³MΈΰ@ MΤτΈΰ΄ LΈΐ@f L-³ΐ'_'@''8    78567³ΰ!π!Ο!P!`!p!O!!7ί55™°33†0²**$²H ±???99//ν?]ν?]ν?]ν]ΖΦ]]]]νΤΕΖ9////////9Φ]]]ν10++]++]++]++]++]++]++]++]+++!'##>733.'#"&54632#"&54632%3#g₯€-,,†,++ς  y $"!!"¨""""ώώθθ{{[š‰DDƒ‹™XΛ#967!!769ώ~G,υΉά&D§@4;PIO=O1O++++444 λ>&*«Ή&ΰ³M&Έΰ@L" M" L M LΈΰ³MΈΰ@AL    +,(*+³!+ί))™'†$²ΏH ±???99//ν?]]ν?ε]ΖΦνΦΕΖ9////////910++++++++!'##>733.7#"&54632'3#g₯€-,,†,++ς  y 0""""­θθ{{[š‰DDƒ‹™XΛ#967!!769ώ~G,υΉά&D¨@;<P=O1O+++44 λ&‘ŠG‹@ IPO++4υθ‡&ΑŠ @ PQ% PRO++4σίy)Ή&ΐ@M L@ L @ L@L@M@M@L D&+F*s    !'J!J ?ν?ύΖ99//92ν2ΦνΦ]ΔΥΐύΕΐ10+++++++"32675#53533##"&54>32&&('7#?<HH{--X=m'D]5"5'!9 9O0oi[ZBBZ’‘OyR) b!XΩΰ/‰@)@M(@M(@ M@ M Έΐ@?L)*&Q1 0  S 0)}((P#`#?##W((O..W @W?ύ]Ζ?ν]99//ν]]3ν2ΦΔν]Φ]ΕΦύΠΠΕ10+++++3##"&'732>55#"&5463232675#535&&#"€55jw*L#=,' (WZ{iJUώϊ%( GG  b,P£sn h # tgtrΝ:= GPKσΠ>&*_$‹@ )$( P)O++4!XΆ³&J_ @ (,! P$-O++4-ι>&._‹Ήπ@ P O++47η= \@4" ! Q!††O@H   ?????9=///+]?]έΕ?]ΦύΠΕΦΕΦΕΦΕ10>73#.'#75'77»%# ”.11:8/ ',-||„&^\&/2/684CHH?=7ήe+`8668VΩy 49@!+F@`€66!F 50J&J ’?ΕΕ?ν?νΦνΦάΕΦ]ν10#"&5467&&54632326732>54.#"Z30*[_vimr1=  »& '& &œ %3‘’ ££ [lD, ˜-O:"";N--O:"";NVΨβ&2?@&-S" "@"`"€""4 4'S€30W *W  ’?ΥΖ?ν?νΦ]νΦάΕΦ]ν103267#"&5467.54>32'32654&#"=  30*-I4!;R01Q; ,7Α-201-201  : %3'AV57[A##A[78K9.ι?NN??MMVΩ&BŠ‹@ 56 P7O++4VΨ‡&ŠC±Έ΄%P+44σα>&_‹Ήώ@ '+P,O++4[Ί³&£_@ &*P+O++41V³&]_@ PO++4ϊλr"/`@;!"101( ((€ `p1/@H/@ H/€ 0 ₯!₯/₯ %₯ ?ν?ν?ν?νΦν++ΖΤ]Ζνq99//9ΦΕ10#"&'663273#5>7#5332654.#"->%5-*@-Π  rΛ^Ήώ~/6^zHcIyŒ*nxz6]LHqff=]ύνtkCX5ϊλr"/~@ 01010 @  !  1(Έΐ@3HŸ((€ `p °1/@ H/€ 0₯" ₯/₯ %₯ ?ν?ν?ν?νΦν+Τ]qν]+ΦΕ]]99//ΦΕ]10#"&'66323#5>7#5332654.#"->%5-*@-Π  gΒ[Ήώ~/6^zHcIy HNP$]G0PHE%]ώ‚tkCX5 σλ΅!0l@E .€ 0212 0 @  ΰ  20''O'_'o''…1₯! ₯˜"₯ ,₯?ν?ν???ν?νΦν]]qΦΕ]Ζ99//Τ]Φύΐ10%#"&54>32573#5>7#53"327&3JI+Wγ  gΒ[Ήώ’    †t4Z@%ΣώΟHNP$]G0PHE%]S 1>0&σΠ>&* ‹@ &$ P%O++4!XΆ³&J@ *(! P$)O++4σίk!s@/?@HRΐΠΰ#ΐΠΈΐ@ HRŸ  Ÿ R  Έΐ@H "    ₯?ν??99//??Φ+]ύΠΦ]ΐ]ν+]Φ]ν+]10".55##335332>553T-4RaaR`a 7 !>X61ώοkττώ}-<$%<-τύ6X>!6[Ϋr :@$S`€  D 0 HJ†??ν9νΦ]ύΐΦ]ν10#66325>54&#"±{#`9yp+NnC&?.92! ₯υusJy`Kt0AW<7C.Ζ>&1Cο‹Ήϋ@ PO++4?Ή³&QCέΉη@ PO++4 λ>'37£Ή%ΰ@ M M@1+@MΈΐ@LM(‚`/?9 8"#9"##"89468.‚ 8+€#H?1157†???Ε9////]ννΖΦνΦΕΖ9=///99Φ]]]ν10++]++!'##>7&54>323.74&#"3267'7g₯€+(&!  &'*ς  y   6˜‘……V“…~@!! !A€ˆ“TΥ#967!!769°9/K,υΉ>&D¦@  <3P+444 λ>&‘G‹@ RPO++4υθ³&Α@ RP% PQO++4ΨΩ>&³‹ Ά +) P+4ΪΨ³&Σ²Έυ΄P+444 λ=&$₯ν‹±Έπ@  POO+++44,υΉ²&D₯χ@60P5O1O+++44 λ.&$€‹@ % PO++4,υΉ£&D€@ =3P5O++4<Μ=&(₯ν‹±Έδ@  POO+++44υΡ²&H₯χ±Έό@ -'P,O(O+++44?Μ.&(€ ‹Ήώ@  PO++4υΡ£&H€@ 4*P,O++46Ώ=&,₯ν‹±Έο@  POO+++44$υΣ²& ₯Ω±ΈΪ@  P O O+++446Ώ.&,€‹@ PO++4$υΣ£& €έΉά@ " P O++4σΩ=&2₯ο‹±Ές@ '!P&O"O+++44σΨ²&R₯ο±Έρ@ '! P&O"O+++44σΩ.&2€‹@ .$P&O++4σΨ£&R€@ .$ P&O++4,ι=&5₯έ‹±ΈΚ@ ,& P+O'O+++44OΛ²&U₯±Έλ@  P O O+++446ι.&5€ο‹ΉΪ@ 3) P+O++4YΛ£&U€@ " P O++4'σΝ=&8₯ο‹±Ές@ !P OO+++44;υΆ²&X₯ο±Έσ@ P O O+++44'σΝ.&8€‹@ (P O++4;υΆ£&X€@ !P O++4"ZΠy0WΉ#ΐ@. L"@ M "%cc@%%2-1 e@  " "*.g*g?ύΖ?ύΖ99=//]νΖΖΦ]νΤνΥΕ10++2>54&##532>54&#"'6632#"&'7w0R="ZL:. 8)B.#E*&T41T>$..<9;c‚H % /;$7'D9k (14a2L6.Pb8Id=kKZ½β&S΅ @MΈΐ³ MΈΐ@ Mcc ($'eg’#!g ?ύΖ?ν99=//νΦΖΦνΤνΥΕ10+++2'>54&##52654&#"'66Χ.M9 )0388b„L-UD)F3C>%&?4Eβ'<*#BL3&+_‹@  PO++47Ή=H@+ °Q€  Q 0†† W ???ν???ΥΝ?Φ]ύΐΦΕΦ]ν]10376632#54&#"'77?{*4F*{*! „&^\&e¨ 9O0ώχωB:ώ–₯`8668-[Ηy,@ QQ 0 ’W?ν??Φ]νΦ]ν106632#4.#"#-%i>=P/{$!({] #R@/39|@/R@0''d??! ˜0""W ?,,W }<6} ’?ΔύΦν?Εν]?ν]??ΦΕΦν]ΥύΐΥύΖ10%632#"&''7#".5463257"3267&&32654&#"p+!+'> S;d'';)PM/i­ &  $Ÿ v'2%8%/3Y8o#?V3s… ΨώΕ(3!7'  ώr#"" σΩk-AZΉ ΐ@5M8S`++C/?S`##(C 0S B.SB/?J=3J ?ύΦν]??ΔΦνΤν]ΔΤ]ν]Φ]ν10+"&5467.5467332654.'3'32>54.#"ϊhw;/ u!!u /;wΚ$$$$ c]@L !%%)=%!,88,!%=)%%! L@]cΙ# ## #σΨ΅(4}Ήΐ³ MΈΰ@M M @ M M,F@`€6/?OF@ ` €  6 &0&@&&F 52F5#/?J/)J ??ύΦν]?ΔΦνΦν]ΔΦ]ν]Φ]ν10++++2654&'3#".5467&&54732654&#"ω"}#.84 :R33R:38."}"-38((72΅66P*#I&9Hh91Q9!:P/9hH9KG*P66ώ©?69??96?.YΖk \Ήΰ³MΈΰ@/L""! HH₯ ’?Εν?ν?ν?Ζ9/////]Φ]ΥΜ10++!#"&'73255!5>7#5!½+H>7 #;, +3ώΟ2>I,ξ‚Btia/W/D-V:G+_l~JfC[΄ΦNΉΰ³MΈΐ@" M    U U₯ ’?Εν?ν??ν?ΖΖΖ99//ΦΥΜ10++3#"&'732655!5>7#5!ͺ4==ގ / ώυ664Β]|?NU$z‘WK&PMFf λ.&$b‹@  PO++4,υΉ£&Db@ 17P/O++4?VΜk$i@C@ LO_"""?&D%  %"H@H H’?Ε?ν?ν9/]ν?Φ]άΕΦ]ύΠΐΖ]]Φ]Δ]10+#"'73254''667#!#3#!#+!!,-# ")$ ¦wόΫΫ— ' ?   kf‹ffVΡβ/:O@-0S $@$$,<%:Sp; ;/:s%%5W +@((W ’?ΕΕ?ύ]Ζ?ν9/ν?ΦάΕΦ]ύΐΖΦ]ν10#"'73254''667&&54>32!32674.#",!!,-# ")$]h&>P*hlώΟL<%CB&) "#  ' ?  wg>^? {v .5i ##$σΩ>+7;$Ή7ΰ³M7Έΰ@L3 M3 L1 M1 L-Έΰ³M-Έΰ΄L+Έΰ³M+Έΰ@L' M' L% M% L!Έΰ³M!Έΰ³M!Έθ³M!Έΰ@gL2³_,o,,ο,,@,,= F`€=o::8<υ  ³P&`&O&&<F<ί::™9†5² /Ÿ/Ώ///)² #Ÿ#Ώ###J J΄?ν?ν?]]rν?]]rν?ν]ΦνΤ]]ν]ΤΕ]Φ]νΤ]]ν10++++++++++++++++++32>54.#"4632#"&#"&54632#"&54632%3#˜& '& &}vimrtjmsΔ"!!"¨""""ώώθθ")H55G))H55G)˜——˜˜——~GσΨά&R§@%, P:O.O"O++++444σΩ>;?§΅8` M1Έΐ³ M.Έΰ@&M* L*@M) M)@M( L F@Έΐ@:HA><@ .@F@/>>@H>™==†83.-Ώ--;%Ώ%%J J΄?ν?ν?]qΕ?]qΕΥΜ?]ν+qΦνΤΕΤΕΦ+]ν10++++++++32>54.#"4632#"&#".#"'>323267'3#˜& '& &}vimrtjmsj  1  Οθθ")H55G))H55G)˜——˜˜——:  '   [GσΨά&R¬@. P>O-O+++44σΩ.&2b‹@ "(P O++4σΨ£&Rb@ "( P O++4σΩ>+/˜Ή+ΰ³M+Έΰ@L' M' L% M% L!Έΰ³M!Έΰ@ L FΈΐ@, H1./0 ³P&&0F0ί..™-†)²Ώ###J J΄?ν?ν?]]ν?ν]ΦνΤ]νΤΕΦ+]ν10++++++++32>54.#"4632#"&#"&54632'3#˜& '& &}vimrtjms""""­θθ")H55G))H55G)˜——˜˜——~GσΨά&R¨@,- P.O"O+++44 θ&<Š‹@ PO++4XΨ‡&\Š@ #$ P%O++4$[ζ΅&HΉ ΰ@' H €` °(&Q' ₯##₯’H?ν?ν9///νΖΖΦύΐΦ]ν+107#536632#".'732654&#";k‚ύ 1$UG)!I’  \v5fύΖ $9'NLNš "! [ΰ$0Ή0ΰ³M.Έΐ΄LΈΰ³ MΈπ@ L 00Έΐ@: Hy$$€$$$2€+++|2Oy1}... U (} ’?ν??ν9/////νΖΦν]Υν]Τ]ν+ΐ]10++++%632#"&''754&#"#663232654&#"p+!+'> S;u$# ' iY53B% v'2%8%03Z8δB8ώΗ 9O0ώδ#"" $[Ο`*@`/$Ο$ί$$$Q_ @_ @,*QP`pP`p+r₯''' !₯ ’?ν?3?9//////ν?3/ν222Ζ]Φ]ΥΐύΐΐΖ]]Φ]]ν]10%6632#"&''7#53573#32654&#"  3(UG0HCDkkk{ΕΕ  {$9'NL0!H@vVfvŠfώŽ "! σΫ΅ .;[@;@$P$$„€ =+/?y:3257632#"&72654.#""3267&ϊ&&8% .`.$8'(9  —  3 &C\54Z@%Ρζ$AY45\D& URP2'ώκ-&2€[Ϋβ!.:Z@;@4P44„ € 32"327&2>54#"ω&'8$. `.%8&(9   Ž  3 Μ &C[55Y@%ͺ«$AX46[D& TRP2'ώΣ&1₯ώλ ©λΏF@-   ! H????9/93ν2ΖΖ9107##6737#'#'37&&&&'Ι$€,Z*{8&&I"}N46d $.<·-‡T €vώω•ζ NG‚CΛϋ*S¨πΑ$/kΉΐ³ MΈΨ@8 M)(0@""@01%F 0(+J‡!J ?ύΖ??ύΐ?99//9ΒΦνΐ]Ζ]Ζ]910++"&''7&&54>327&&'3267&#"(O?A*Kg=  Q$ˆ0?YΚ~ 7+ QV&‘jMxS+KJb ώc aF9V1R'±Χ#%.^@:  M)#/ *0/ `p_   0&S"/!ΆW¬* W  ?ΕύΖΕ??ύΖ?ΖΦνΖ]]Ζ]9/9910+74>337&&'3267#"&''7&&77' DhG H!U DM3#FG@}O#0 λ3ZC'A8 c  ώϋ e HItK#7φ$0Μk 5@  QU U??ύΦΐύΐ??ΦΥΐύΕΠΠΕ]10!!#53533#3Μώ–PP{ƒƒοbοοb΄όΑ » C@%@M Q   Ά H?ύΐ????ΦΥΐΐύΐ9/9910+7#5'7#57#”3Dσ{^C‘„::kP-ώ„ώξR‘-όfΑ[$[ΊβDN@-=@M,5FS&FS P??E?418’!@W+OW ?ύ]Ζ?ν]99?ΥΖ?Φ]ΦνΦνΔΦΜ10+72654.'.54>32&&#"##3267#".'7δ-0#8.1L5.OH-/!!:/3R<&  7 #7-'(,#*+(]    1%5) h   !3%0"\!**(\ C[ΩΦ!=@"@ M"! # "U!  J?νΕ?Ε?νΖΖΖ9/////10+327#".##5>7#5!ͺ8CD!4// 1 !4-*/9$ 664Β]|EW`( -+!d%+%K&PMFf7Μx#!@ F%Q$ g??ύΖΖΦνΦν10!#5467>54&#"'6632|4#& 7&*'" (,b05P6),$Δ:G) b0>",S  '<Ώβ%%@ S'n&W ??ύΖΖΦνΦ]ν10!#54>7>54&#"'>32|%*#M ' '28ch $q)! b JD'  ψΥr+8vΉ Ψ³ M ΈΠ@> M @ M/F(F`:8D D 9@,,HΠΠ +    +4J#J ?ν?ν9=//////]]ν]ΦΥ2ύΐΤνΦ]νΤν10+++%#"&'5#536632%3#32>54&#'2654.#"Υ#>R0&S)>>!O&AR.+$?-ώχBB  "0)&)   »8K- O} /:,DN))O0#-'f)$Žσβk!£Ήΐ³ MΈΐ΄ LΈΐ@ L @ M @ M@ M@ M@ MΈΰ@= L D #0  D   " r J ?ν??9/33ν22ΦΕ]Φ]ν]2ΦqqΕΦ]ν210+++++++++".55#53533533#'2655#φ6G*++{{..,I5& !>X6DbεεεεbD6X>!k=N;327#3267#"&''7&&77"&#"3&&'7&?P*G69Β %BY3#D=;Ν " Π ˜ η>^? E@nU  V l KFtvb$'KR =*σβk:@D @r H J ?ύΖ?ν9/3ν]2ΖΖΦήΐύΠΕ103##"&'732655#535#5!šHH1N99M/5*3wwΔ?xbG-P<# b3E@bf1Vί¬'w@'@M@M@M Έΐ³MΈΐ³MΈΐ³MΈΐ@$MT"(DD(X%sH J’?ύΖ?ύΦ2ν2?νΖΦΠΥύΝΠνΤν10+++++++%#"&'732655#535#5!3##"&546321C'0R&&G"ΎΎΎ9OO. -- .9M/h%2―SUf»S•$**$%**Y y0*@'F2F1"J  J’,J?ν?νΕ?νΦνΔΦν1046323267#".55#"&732>54.#"ladj  " )4 .dj}  6 ££ ώΪ-"d,?)£ -O:"";N--O:"";N[ώΰ,*@'Q. S-#W J’*W ?ν?ν?νΦνΖΦύΐ1074>32327#"&55#".73267&&#"7P4-b  ?B/,A-}&&" -.λ6[@$ ώB#gEQ #@[4AG Qΰr%N@. @ M D F` €   °  '"D&H## J?ν?9/3ν2?ΦέΐύΐΦ]2Φνν210+2#&&'##5#53>4&#"326ς]q,3#" 4#{HH))'_-$ 0+rch6X?EE7#5!#".'73254&##’&'$ ιz ")+!:*~p0/*P#pC@(Ν+-*fK+25-<%ca a a5/i‹£@    ˜?ΥΞΞΦΕΦΕ102#&&#"#54>ϊ5'Z['5£%4!&&!4%Oͺ²@ ŸŸ?Ε?ΕΦΥΦΕ10'''>l6zgl6z²ˆ+pCˆ+p‘V>#+@‚Ο‚$$ !†?ΥήύΦνΦΕΦύΦ]ν10'7#".54>324&#"326R˜‘#    8  ύ9/Kί! !! !m ‡ά >@%°o0 JJΟίPJ‹J ‹?ν?νήΕΦ]]ύΦνΤ]]]Ν10#"&54632#"&54632%3#ί"!!"¨""""ώώθθD~G† nά @ J  J ‹?νήΕΦΝΤν10#"&54632'3#3""""­θθD~GJ©-@J   JJ‹ J‹·?Ε?ν?νΦνΤΕΦ]ν10'4632#"&'4632#"&Εk9xΈ"!!"ν"!!"˜*‰’J©7@!J―ΏJ °ΰJ‹J ‹·?Ε?ν?νΤ]ΕΦύΦ]ν10'7#"&54632#"&54632tx8jr!!!!ν""""Ω‰*˜ΛJ© JΉΐ΄MΈΐ@"!H J―ΏίJ΄J‹J ‹?ν?ν?ΕΕΕΦύΦ]νΤ+Δ10+#"&54632#"&54632%77Ό!!!!ν""""ώΞ,UW-„Gk4AA4ro …ά>Ήΐ³ MΈΰ@ M /?  ˜?ΕήέΞήήΕήΝ]ήΝ10++#".#"'>323267'3#…  1  Οθθb  '   [G‹₯i=΅†?ΝήΝ10'7iΓΎγ>>Zw₯}=·†?έΝΝΦΕ10''7}&\^&„ή9669_w₯}=@ ††?έΕ?ΦΕ10'77ϋ„&^\&₯`8668M„§> C@*JOOJ@  †JΐΠΈ JΐΠΈ?]ν?]ν?ΕΦ]νΤqΕ]Τ]ν104632#"&'4632#"&7'5"!!"θ""""“V-^ΌœP5EM„§> K@2 J//?O―ΏOJ@†JΐΠΈJΐ Π  Έ?]ν?]ν?ΕΦ]νΤΕ]Τ]qν10#"&54632#"&54632''7Ώ"!!"θ""""_]-UΌ(E5PM„§> j@JJί   O _   O_J@P`°ΐ†Ÿ†JΐΠΈJΐ Π  Έ?]ν?]ν?έΕ]?Φ]qνΤΕ]Φ]]]ν10#"&54632#"&54632%77Ώ"!!"θ""""ώύ%1/'VΌ:.##.N?Μ>&(C‹@  PO++4?Μ,&(ƒ‹±Έφ@  PO O+++44ϊηk#Z@9@ M@ M@ M0   F D!"$ JJ !OH?ύ]ΐ?ν9/ν?ΦΥύ]ΖΠΖ]Φν]]10+++#632#"'7232654&#"##5‡ͺ-K6'@- #%9.  {Pkf…1I0/J4d&/8+ώξf$δ>&Ə:‹@ ; P O++4σΥy"3@ $FF#WJJ ?ύΖ?ύΖ9/νήνύΕΦΖ10"&54>32&&#"3#3267(ƒŠ*Kg=!5( A*2*ΜΝMH0?Y ¨›MxS+ b$<,oPU a(σΜy66Ώk,6Ώ,&,ƒ‹@ PO O+++44*σΆk-υΰk+R@3@(P((„ΐ- …/?@Ho  …,}++ s #} ?ν???ν9/νΦΦν]Υ+qύΕΦ]ν]10%#"&'#'667>55332'32>54&#ΰ-54&#ΰ-&.‹Ήϋ@ PO++4.Ζ>&ΛC‹@   PO++4σξ9&֐‹@ &.P!O++4-[Ηk >@& D   D 0P ©P H’??3ν??Φ]νΦ]νΦ]ν10!#5#3332r“{€{₯₯kύϋύ• λk$6ψΥkD³FΈΐ@ HD Έΐ@ H J OHJ ?ν?ν]9/νΦ+ύΐΦ+Δν1032#"&'!2654&##±.8[@#}v#\-_¬6=@A*"v0M8gf afώ^.36*½6ψΥr%$δk 5@D° ΐ Π  Έΐ@H HH?ν?ν2Φ+]ΥύΕΠΕ107!#3!5}gμ†ώ¦ffώaff[βkŸΉΐ@ M M Έΐ³ MΈΐ@ M@M@M@M@M@DPΈΐ@5 H 0 @  ©©O©/?O©’H H  ’H?ν??ν?ν2?μ]ΦΥνΦ]νμ]ΦΦ+]ν]10++++++++73>55!3#5##3$ F#rοrΪ Ÿf-u}z0<ύϋώυ₯₯ͺ?LTOEŸ?Μk( λk-d@:… $*-%.%%/.$** ?????9//////?9///999ν2221053>73#.'##>7&&'p  `  g>-)#g ` g#)*Ak&A;9ωϊ954&##€O<<23'$ ,'d39R5,'3;:cM0k-) ")/&2 9Gbs+&&# c0=*IT4"D6"c  *..Ζk<@ M D   DΈΐ@ H  ????99Φ+νΦ]ν10+33>73#.o-58co9a,kώƒ#_hg,ύ•›gΘl.Ζ8&ːŠ@  PO++4-ιk.σΠk)@ D 0  D   H?ν???ΕΦΦύ]Φν107>7665!### F{Z1J6] !)BΗ€ύ•:zrgO2έk0-Ηk+σΩy2-Ηk4@D 0DpΠΈΐ@ HH???νΦ+]ύΦ]ν10###Η{€{kύ•ύϋk6Ψr3σΥy&Ϋk7σξk E@'@M@M!"!" "@"`" !H ??ύΖ?ΦΦΕ]ΦΕ9=/9910++#"&'73267&&'3>7ξ'#!-18!5$ ,Fp#ˆ=&kKudZ/;N. h,8uΫUFŠN,TJ>Ϊ“ @  M MΈΰ³MΈΰ³MΈΰ@9M M„@P€ R@ P   „―s s“?Υ2ν2?Υ2ν2Φ]νΦ]22ν22Φ]ν10++++++4753#5&74&'66±`°°`±b!.-"ύ!-,"LλAAιλGFκ@][\=@Zώ¦^ ιk;-[Ωk _@)@ L8 M@ M@ LD 0 @  DΐΈΐ@ HoŸ  H’??ν2??Δ]Φ+]ύΦ]ύΕ10++++%3#5!333Ά#rώΖ{’|fώυ₯kύϋ-ΗkF@ Ώ  D 0DpΠΈΐ@ HJ@  ??9/]ν?Φ+]ύΦ]ν]31032673#5#".553¨ $ '{{,,I5{΅&0 -ύ•Ο4YE½έk 9@!o  O_o H??ύΕ3??ΦΥ]ΦΥ]qΦΕ]10!!33333έώ:aR`Rakύϋώζ[λkY@:/?O Ÿ ―  Ο p  o 0Πΰ   H’??ύ2Ε3??Φ]qΥ]ΦΥ]]qqΦΥΥΕ]10%#5!33333λ`ώŒaGaG`fώυ₯kύϋώζύϋψΤk7@F@ `  DŸJJ H?ν?ν9/νΦΥ]ν2Φ]ν105332#"&'232654&#Λ1P9 ";P."O&{+230fΦ1L66P4 ϊΦΗ.67-"ψΟkjΉΐ@, H„/?R@ H@ P Π 1   Rΐ Π π  Έΐ@H  J J ?ν?9/ν??Φ+]ν]]]2ή+ύ]ήν+10%#"&'332'32654&##3L/@$="` a\Κ&"--?``Λ54&#Υ…t%T-{1σώά*I8Λij `ΦfΗ $9/*σδy$9@ F  &%J J ?ύΖ?99//ύΖΦΖΦ]ύ2Ε10"&'73267#53.#"'>32Ρ:S@0GNΞΝ(/*A *7 =cG'%Gf a \Io0<# b )QyPJwT.σΫy.e·ΐΠπΈΐ@ HR%ΐΠπΈΐ@ HR  0RΈΐ@H/*J H  J ?ν??Υν?νΦ+ύ]2Φ2ύ+]Φν+]10#".'##33>3232>54.#"Ϋ#6#>aa?$2!%6#»   6`}IAnTώρkφLe;I}`>U44T>?T44UΗr$:@ D&F D % H"J?ν?9/ν?Φ2ν2ΦνΦ]ύΐ102#5##>7&&54>335&&#"'(,+{@#= !$%3+!>V88? 1<rύžδ9o<EE?X64M2Κ-1Ί.,υΉβD(σΝ΅.`Ήΰ@ M M M M M*S Έΐ@ H 0 S/Ÿ%W-W0Pp ?]ν?ν?ΕΦνΖ]Φ+ν10+++++632#"&54>766732>54&#"Ζ,[N732&B1!7K*td$FjE9ώϊ! %'"G 9:9U832Ώ ,&*KJH!& ) :21++123J/  h`5T[ώάΒ#/#0 &ASYΏΦ(@ Q00U ??ν]Φ]ύΕ]10##!Ώκ|fpώΦzΩΦ]Ήΐ@ M QΈΐ@) H /? /?OU  U  U ?ν??νΕ?Εν2ΦΖ]ΕΥΕ]ΦΥ+νΦΕ10+73>5!3#5##3%1#rέrf$\bc+ώμ††φEFC υΡβHζΦ+s@A@P€R))$# #)  )#,-) +  + $  ??????99=//99999/////993ν]210>73#&&'#5#>7.'353+ g !#<g*!`"(g "" g `2443575†A oNέΰMn%CB=!743441Δ3σ³ΰ0Q@/(SS2$1@W?%O%%%%s" "0O--W ?ύ]Ζ?99=//ν]ύ]ΖΦ]ΦΔΦνΤν106632#"&'732654.##532654.#"@"N3'F5 "'&!7J)2_$S5,-jj&*KΗ  4�7+(7"e ] ?ΆΦ<@ R 0RpΈΐ@ H   ????99Φ+]ύ]ΥΥνΕ10336673#?n N8co)')Φώυ@Jώ* #BDK,?Ά&λ@ PO++4?θΦZ@ QQ€ °Έΐ@ H R0QΈΐ@ H   ??9=/99??Φ+ύ]ΠνΦ+]νΦν106673#.'#3»#I•,//96-Ž &,.||!*b)8:6AFF?=7ήΦψΆΦ!@ QS ???ΦΦύΦν]10'667>55!#π -C0#" 4{p+WRH7"f"?FG6ώ*pήΦ‡Ή ψ΄LΈΐ@E M@ M ΐΠ 0?  ???9/////?ΦΥΕ9=///]]9999Φ]ΥΕ10+++>73##'#>7’ f qKZJq Φuss=Lλλώ΄:|{t1;ΈΦ 9@ QŸQΈΐ@ H U  ????ΥνΦ+ύ2Φ]qν310!#5##3353Έ{‡{{‡{ΊΊΦΆΆσΨβR?ΆΦB@ΏQ°Ÿ―0ΏQΈΐ@ H0U ?ν]??Φ+ύ]Φ]]]ν]10###Ά|€{Φώ*pώΦ?[ΥΰS,υβF&ΟΦ+@ Q@P€U  ???ύΐΦ]Υύ]Ε10###5!Ο—|–©pώpfXΨΦ\[Ϋ΅ 't@/' "0"@"ΐ"Π""R   ? O  …  0@ΐΠRΈΐ@H―(I' I I I??ν?νΕ?νΕ?νΦ]+ύ]Φ]ΐΐύ]Φ]ν]Πΐ1036654&'#5.54>757Ι*%$+`$,,$`/C+*C1`&A00A'xO==LJEFHύγ£'=S0-N>(Οδ9T89T9 αΦ[?zΗΦ 5@ Q Q 0P`p  U?Ε?ύΐ??Φ]ύΦΝύΝ10%3#5!333€#rώκ{n|fμ†Φώp+ΆΦ,@ Q S0 W  ??9/ν?Φ]νΦύΐ10326753#5#".55¦! ||*''E4Φ•Οώ*š'A2™ ΤΦ S@_o p/?O_oΈΐ@Mp€ΐ   U?ύΠΕ???Φ]+Υ]ΦΥ]]ΦΕ]10!!335333ΤώLaI`IaΦώp zβΦ΅ @M Έΐ΄ L Έΐ@I L / ? O o  _ οp€_o 0p€  U U?νΕύΐ??ΖΦ]qΥ]ΦΥ]]]qΦΕ]Υ]Ε10+++!!3353333#‚ώža>a>a#`ΦώpώμφΤΦ K@1@ MS @`€" Q!WO_oU @  W?ν]?ν]9/νΦΥύΐΦ]ν10+%4&#"326'632#"&'#53Y+$   -|(!%@.4H(7V"P˘!l»)=*/=$cf"φΟΦ#]@ 0@yΈΐ@ H`p€@%€Έΐ@H$ @W  !W ?ν?9/ν]??Φ+ύΐΦ]ύ]Φ+ν]106632#"&';#'4&#"326‚/%-;$>!`ν``Š   !/'>+0=$ Νώ*˜#~"6φΥΦ!?²SΈΐ@ H# QpΈΐ@ H"W! W?ν?9/νΦ+]ύΐΦ+ν10%2654.#"'6632#"&'3 &+$% N/'H8!lZ7#53&&#"'6632Λ&C^80T0B#2+ΓΒR3%6,R&9_D&ξ<]?! e  #]2* d !?[υββ*m@$ ;KΛΫ/R@ ` €  Έΐ@ H ,ΐ&Π&&Έΐ@ H&RRΠ+W!W  ?ΥΕ?ν?ν?Φ]ύΐΦΠν+]Φ+]ν_]]10]336632#"&'##%2>54.#"a;FK*:#%:*JE;a3  Φ΅[f"?[:8[@$l[Ό[ 9--9 8-.9 Ηΰ"@@$"Q$Sh  Qo#U"" W ??ν?9/νΦ]2ν2Φ]νΦ]ύΐ107#667&&54632#55&&#"33ρ.9,!mh43/{ (6( E§*P-:f#;)NU ώ8§Ο!υΡ³&HCοΉύ@ )'P(O++4υΡ‘&Hƒ@(:P2O&O+++44[ΉΆ)i@C@ L"Q@ M @ H+  (Q@ M_*)W%W  s?Ζ?Ζύΐ?ν?Εν?Φή2Ζ]+ύΐ3/ΕΦ+]]+ν10+3#53573#6632#"&'7326554&#"P77|&1A'ZV 1%#S:OSB 9O0ψ]Yg+$δB:ώ–YΏ³&ζ@ PO++4'υΧβ P@1 `"@"@S!@W_oU O  W ?ύ]Ζ?9/ν]ύ]ΖΦύΕ]Ε]Φ]Ζ1074>32&&#"3#3267#".' DhG+F$3(HL ΓΔ QIDM3JiC λ3ZC' c 2*]-1 e &BZ6υΊβV$υΣ¬L$υΣ‘& ƒο±Έο@ ( P O O+++441V¬MυαΦ+P@1)@L_„%%%,}"" U W)} ?ν?ν?ν9/νΦΦύ]Φ]ύΠ]Φν]10+6632#"&'#'>5534&#"326. ??*8:3<<γQ  &TI,;$ yO„b:a-C/Αώ½#'Ž&.υαΦ%q@3O_„/?Oo °ΐ/?O Έΐ@ H&}   #} ?ν??ΥΕ?9/νΦ+qύ]qΠΦ]ΐύ]qΐΦν]106632#"&'5##33534&#"326. ??*8:QWWQXQ  &TI,;$ ΏΘΦΊΊώ½#'Ž&ΉΆ?θ³&ν Ήύ@ PO++4?Ά³&λCοΉϊ@ PO++4XΨ&\@ (0 P#O++4?zΆΦ H@ Q0 ° ΐ   QOQΈΐ@ H  U??Εν??Φ+ύ]Ε]ύΦ]]ν10!#5#3332r{€|††Φώpώ*σΧ΄,<@@&-F #@#`#p##>F7Fp=2W :J(W ?ν?ν9/νΦ]νΤΕνΦ]Δν1074>7&&54>322667#"#".%4.'326 5+$)?,($! #R&  -!;F9Q12Q; :$#5**3Ϊ8:79)3%[ "'gH7Y>!;VA*# $((DCBψΥ“ Q@1ŸΏS0@ Q !@W @ HU “W?ν?Υΐύ+ΐ9/ν]ΦΥΐύΐΕΠΦ]ν]10%#"&'#53533#32232>54&#Υwi#Q,CC{œœ+Ϊώϋ !;-Λij ιf99f_fΗ $9/φΥΆ)P@ŸS 0@$Q* Έΐ@ M  W!!W  ????ν9/ν]+ΦΥΐύΐΕΠΦ]ν]1053573#6632#"&'2654.#"C{••($A2aR9c1Θ! z\Λΰ\K&?.SK lώβ lσΩy 4bΉΐ΄LΈΐ@4L%F@`€60F 5 ° (°(-((- J  J?ν?ν9////]]Φ]ύΐΦ]ύΕ10++4632#"&"6632327.2>7#".#"vimrtjmsί$  %#     #6 ££  ££x.?%  &B0ώP)8!  #;*σΨβ#4IΉΐ@(M'S @`€6-S 50$$0*W W?ν?ν9////ΦύΕΦ]ύΕ10+%#".54>32"3267#".7267&&#"6632Ψ :Q22Q; !;R01Q; ώΰ..(/t -,&0  μ8[B$$B[87[A##A[F6A6.  "3<2+   t#H@' M@ M   % $J ??9/?ύΖΖΖ9///99910++#.'3>76632&#"‹  0+"‚ <0-#5 ±3U^vUE­š10‡ƒ47^TP+R@G!β 5@ M "!  ???ΖΖ99//999910+#&&'3>7>32&&#"“"Ah'Q%   -!+ S_²BYοŽ&VWR""523 , a.Wμ9*fΉ ΐ@; M³ ,   +,&/?O³ 0P+%†"†’???Ν???ήΕ]?Φ]ν]2ΦΔΔ99//]Φέν10+33>733'667#".'73267.o.69b$;54.#Υ…t%B.55|GGyzώξ*"/Ζhf Δb::bCaΎ$' φΥθ'v@<Q @ `  )$Q/(@Mo―ΏO!_!o!!JΈΐ@ H @J?ν]?9/+ν]Υ2Ε]q+2ΦΥ]qΐύΕΐΐΦ]ν10#6632#"&'#53532654.#"N‹+%D5eW:e355|Q!% ! 4³S1&?.SK RS55ώ© l6Ψr$[@7 %&"F`€& 0D%J   OJ?ν]?99//999νΦύ]ΐΦ]ν9102'###>"3263'7654&ΰv‚# 9S<1,{-., ' 2 'R# ?ran8P_.gΡckΜC/<"7*?[Υΰ"M@-S@`$#!$ #$Q# W W?ν??ν9Φύΐ9/999Φ]ν10#"&'#66324&#"3'7690{"c0mt##3S63 '*R(  ±l „qCg W-J?Qώϋ J/F$Ϋα 0·D Έΐ@H H H?Ζν?ν2Φ+ΥύΕΠΥΕ107353#3!5}μrγ†ώ¦fvάώaffYΏD1@@P―ΏQ °Π±U ??ν?Φ]ύ]Υ]Ε10##353Ώκ|σspώΦn$δkB@"   Q @H H H?ύΦ2ν2?ν]2ΖΦΥ22ύ2Ε233ΦΕ1075#53!#3#3!5}YYg솆†ώ¦f bfb ffΏΦ /@Q s OH ??ύΦ]2ν2ΦΥ2ύΕ3ΠΕ10#3##5#535!Ώκtt|GGfpzS££Sΰ-Yήk"L@/S €     $!QO#@W"@PU’H?ν?ύ]Ζ?9/ν]Ζ]Φν2Φ]Δν103!!632#"&'7232654.#"-ώϊ""6Z?#}  MM$5! kf DjI‡•eOa4F*ώί?ZΣΦ"H@, 0ΰW $"Q @ H#WOH! W?ν??ν]9/νΖ+]ΦύΠΕΦν]10#632#"&'732654&#"#!˜ή%$1M62O7 5.6= " {YpW 733#5#.'##>7&&'p  `  g>-8W ` g#)*Ak&A;9ωϊ9733#5#&&'#5#667.'353+ g8&"/W*!`"(g9'" g `2448f<#L'μ† oNέΰMn%>54&##532654&#"'6632!!,-# ")$-`*) ")/&2 9GbO<<23'$ ,'d39R5,'3;+J8 ' ? c  *.e+&&# c0=*IT4=3&3V³ΰFa@7*Q;>QAH H3&GF2O//J6$₯'>'>6 @P`J’?Ε?ύ]Ζ]?99=//νύ]Ζ?Φ]ΔΖΦΥΜΦνΕΤν10#"'73254''67&&'732654.##532654.#"'6632!!,-# ")$)KS5,-jj&*K"N3'F5 "'&*9! ' ?  e ] f  4�7+"2"-[ΩkF@'³ Q  e?ν??9??ΦύΠΕ]99//ΦύΕ10!.'#3>733#5L %-1{{*' ‹$-5-O"+r#QMCώεkώDDBDKN%+{Bώυ₯?zΗΦO@. @ L M³  Dˆ   y?ν???9?ΦύΐΖ9/99ΦύΕ10++!.'#366733#5? %%||;”*,,B8r?=7ήΦΊ*f*684V-μ†πk –@ @ L@ LΈΐ΄ L Έΐ΄ L Έΐ΄ L Έΐ@@ L@ M@ M !"?O O/³ !  ???ΦΥΥΕ?9Φύ]Ε]33/Ε]2910++++++++!.'#5##33536673t!D%rr%D=}%0(''0F>:$„ˆώκkϊ‰Š6ƒBGOR'!BMZ7η֐Ήΐ΄ LΈΐ΄ LΈΐ΄ LΈΐ΄ LΈΐ@4 M ` ‚‚Q   ??9=/99??ΦΥΥΕΦύΠΦνΦν9///]9910+++++>73#&&'#5##3353ϋ ƒO*+% |<&E{{E/003p,@GH 73#.'##53U{22'"ˆ&/594* ‡ (/{::“GVŒ"9;A*#JKI"NW[*#KJEώεφVηώ"W@5" L  °  $ 0Q #   ! ?Ε???9?ν2ΦΥ2ύ2Ν]33Φ]Ζ]10+3#>73#.'##5353»CC+% ”,38;9/  ',-|--|ΦAy120675BHG?=7ή•A(ιk=@" DP H?ν???9ΖΦ]2ν29/910536673#.'#Τ#8‹C@2,# ‹!${fώ@…<9YPX\*#QMCώεηΦ@@# `Q H  ????ν9Φέν29/]9910>73#.'##53Ϊ” &+.40) #%{MΘ23/684AKK?=7ήpf-[ΩkJ@   Q Q 0@QΈΐ@ H U U?ν??Υν??Φ+ύ2Φ]νΠΥν]10!##33533#5:’{{’|#rώοkττύϋώυ₯;zΣΦjΉ ΐ³ M Έΐ³ M Έΐ³ M Έΐ@, M Q  Q 0p U   ????99//ν?ΕΦ]ν2ΦΕ]ήν210++++!5##33533#54~{{~{$rΊΊΦΆΆώμ†-βk ŠΆ   Έΐ³ M Έΐ³ MΈΐ³ MΈΐ@ M  0  D / ?  Dΐ Π  Έΐ@ H    H??/99//ν2???Φ+]νq2Φέqνq2210++++qq####335βY{f{{fkfύϋώοkττ;βΦ N@? Q  Q@P °Έΐ@ H U ????99//νΦ+]qύ2Φ2ύΕ10]##5##3353βM|c{{cΙpώΊΊΦΆΆ$[ήk&\@;P„_Ÿ@ H(@ H…"#…P&`&p&&'$₯""!₯ /?ν?99//ν?ΖΦ]ύήν+2ή+]ν]106632#"&'7232>54.#"###' JP'>.   aB`kβ…’AhI(\+G5:J*ώΣύςk$[ήΦ&[@P„?_(@ H…"#…&Έΐ@H&'$!₯""₯ ??ν99//ν??ΖΦ+ύήν+2ή]ν]106632#"&'7232>54.#"###' JP'>.   aB`Φ΄lw5U32&&'.54>32&&#">54.#"†" '<*&7$'<)9)Cf 4O6 CeE'!-.?&ž     6Ki160WA' 5E&)NC3 #eXC5Tn>BwY5 d#;N 4!*0%*8|κβ/<‹Ήΐ³ MΈΐ@O M@M@M@M@M,/>„00@8P88„'>c=,:J"33"@M@MJ /J?έν?ν+2+9///ν?ήνΔ2Φν]9/νΦήΕ10++++++&&'.54>32&&#"&54>32'>54#"ΝP{#3N3=[<#<%'5 60<2&!1!;&Ί *„@8+@R/.XD) e(2f#/D-"3$70& § 0(VΥy’,VβΒ[Ϋk 1@D° Π   U U?νΕ?ύΐΦ]έΝ]ύΝ3Ν10#3#5##5Ϋ£DsM£kfώaώυ₯f&zΟΦ -@ D H ?Ε??ν2ΦέΝν2ΝΝ210#3#5##5!Ο—Xrb–©pώφμ†pf θk<[ζΦ:@Q  /???9///9/99993ν210#5&&'3>7ζ&^/{.W%    ցγ^Ή»^δ~'YWP PWX( θk‹Ήΰ³MΈΐ³MΈΰ³MΈΐ³M Έΰ@:MD―Ώ D_o_o  ??9////]]9?Φν9=/////]9Φν10+++++>733##5#53&&'3ώ  %).x~||u4P%„8PFNP 2][[/R₯₯R^΄bH•[ζΦu@ @ M@ L@M@ LΈΐ@. L   DD   }?ύΐ????9ΦνΦν9=/////9910+++++3##5#53&&'3>7ζ M'Ml{oR&H    ΦlΓUR₯₯RVΔj'YWP PWX( [ΩkK@) ³   ???9??ΖΦΖν99=//9910!&&'#>73733#5R51… $+0•…Td{™">,r3|>;3LX]+$ΖΖώί8w5ώυ₯zΙΦO@*    U?νΕ???9?ΖΦΖΕ99=//99210!#&&'#>7'3733#g3*} $(+—Z\}“20`3P (K0=?>δ““β J$μ^δrH@ DDΈΐ@ HD 0  HH   r?ν2???ννΖΦ]ύΔ+άν]έν10#333#5!#5Er|#{ώξFrnώsϋώώη’nzΩΦH@. @ L @ L y yΟy―ΏΟ r   ???Εν2?ΦΥ]ύΥ]ΦύΦν10++#53#333#5!YGψG‰j#iώιy]]ώνpώμ†-[ΩkF³QΈΐ@ H³ Q Έΐ@ H S r?ν??9/ν?Φ+νΦνΦ+ν210!#5#".55332733#g-!,G3{ !|#rΟ4YE½Ά&0 -ύϋώυ+zΗΦr@ @ L/ΈΠ@?MM M@ M/Q_³Q0   S r ?νΕ???9/ν]Φ]νΦν]Φ]ν210]++++]+!#5#".55332>7533#U-*D.{*|#rš'A0™˜"ώμΗkG@)D‚ 0  D ° J???9/ΕΐύΥΕΦ]ύ]ΦΐύΐΦ]νΐ10%#5.553536673#5D)D1{ D  {{ `i5V?½Ί:7nr1ύ•Ο-ΙΦo@*@Q ― Ώ ο  ‚   0QΈΐ@ H WO     ???9///]ΕύΕΦ+ύ]Φ]ΐύ]qΐΦ]ν]ΐ10%#5&&5535326753#5#ESX{0E ||!JKJZ™˜/ KNώ*š6Πk<@D 0@ D Έΐ@ H J   ???9/νΦ+ύΐΦ]ν10%4.#"#36632#U $ '{{,,I5{Ά%1 ώΣkΟ4YD½?ΉΆK σδy(/|Ή. @( L*@M*` L/@ L)@ L)R(1ΐΠΰΈΐ@# HR0/R0@//H O,,J  J ?ύΖ??ν]9/ν]ΦΕύΕΦν+]ΦΦν10+++++3267#".'&&54676632'4&#"ύ3?0 ")4L3HBT UI3A% d$ dZ V -Ol? Q7 '}ˆ6Se.&`XLZJ υΡβ%,€@7) M'@ M0 M+&K&Λ&Ϋ&&S»##[$D.,S  $  Έΐ@H „-,sM))W   "W?ύΖ?Δ]ν_]9/νΦν+qΥΕύΐΦ]]Ζ]ν]10+++"&'&&54676632#32674&#"Q\fI7\X8QTά#+1"$ lkI?   \^{v  ) ` #3580 δy+2i@A@ M,@ M?,O,_,,S(4 2022S 3 R3 2U /0//W# W ?ύΖ?Ε??ν]9/ΕύΕΦνΦΥήΕύ]ΕΦΦν]+10+3267#5.'&&54676632'4&#"ύ3?0 !`"2!HBT UI3A% d$ dZ V u 5J[3 Q7 '}ˆ6Se.&`XLZJ Ρβ(/r@I/)?))S_o#@ H#1S/S 0'R0"W&@//U&O,_,o,,W   (?Ε?Δ]ν]?9/ν]ύΖΦνΦΥή]νΥνΖ+Φ]]ν]10&&'&&54676632#3267#4&#" ;AI7\X8QTά#+%a^"$fUI?   \^{v ) ` x™35806Ώk, λ9&ɐ‹@ 3;%P.O++4ζ&ι@ 19#P,O++4-Yοk%T@0!F' &'DO&@P`J J??9///ν??ύ]ΖΖ]Φύΐ9/99Φν10"#36673#"&'7232654.έ {{2b'Œ-9A"[krv  BC$5ώkξ:{97665!3'667##$##:55!3'667#π -C0#" 4$>3J" %p+WRH7"f"?FG6ώ—K‰-.7p-[ΗkR@0DΏ DpΈΐ@ HH@ J’?ύΖ??9/]ν?ΖΦ+]ύ]ΠΥ]ν]310#"&'73265##335ΗZU 1#€{{€kύ¦]Yg' ώοkττ;[ΈΦL@ Q0QΈΐ@ HO U  W?ύΖ??9/ν?Ζ]]Φ+ύΐΦ]ΐν]10%#"&'732655##3353ΈZV 1#‡{{‡{]Yg' ­ΊΦΆΆ-WΩkh@)@ L@ L @ L @ L D 0 DΈΐ@ HH@   ’?Ε?Ε?έ]ν??ΖΦ+ύΐΦ]ύΝ3Ν10++++3'667###335Ά#:3J" %…{{…{mK‰-.7ΊΊΦΆΆ-[ΗkK@-D 0 D 0  J ???99//ν?Φ]νΔ]Φ]ύΠΞ10]]%5#".55332673##L,,I5{ $ '{Lsfi4YE½Ά&0 -ύ•₯ +zΆΦPΉΐ΄ L Έΐ@% L@H  Q Q0W   ???Ε9/ήνΦ]νΖΦύΠΝΕ+10++326753##535#".55¦! |brX*''E4Φ•Οώ*†μ4'A2™Wμk#›Ήΰ@^L L0Mo@ H% @ H %$%$% ##ψ##$³ H$’ ?????9///9ΖΦ+νΠ]qΑ/9=/9999Π+Α/Φ]έ+Ν]10+++>733'667###>7‘ e $;733'667###>7« n %<4I# EY:q ΦHSX((YSH`[Lˆ-.7Lώσ ώ΄:|{t16Ώk -@ Q0 H H?ύΐ?ύΐΦ]ΠΥΐύΕΠΕ10353#5!#36‡‡‰††fŸffώaf λ9&$‹@ $ PO++4,υΉ&D@ 4<P/O++4 λ,&$ƒ‹@+ P#OO+++44,υΉ‘&Dƒ@ 1CP;O/O+++44 λk‘υθβΑ?Μ9&(‹@  P O++4υΡ&H @  +3P&O++4σΥyθυΡβ#M@0# S @%Sp$OWO#_#o##U  ?  W?ν]?9/ν]ύ]ΖΦ]ΔνΦ]ύΐ10%#"&5467!4&#"'66323267Ρ&=P*il0K<%D H-<_C$ώΕ #/-π>^? {v  .4h =Zm$;'σΥ,&θƒο‹±Έτ@ *<P 4O (O+++44υΡ‘&iƒψ±Έό@ &8P0O$O+++44 λ,&Ιƒ‹@0B%P:O.O+++44ζ‘&ιƒ@.@#P8O,O+++44σί,&Κƒ‹@5G#P?O3O+++443σ³‘&κƒψ@3E P=O1O+++44σαk[ΊΦ£.Ζ&ΛŠ‹@  PO++4?Ά‡&λŠ@ PO++4.Ζ,&Λƒ‹@$ POO+++44?Ά‘&λƒ@$POO+++44σΩ,&2ƒ‹@"4P,O O+++44σΨ‘&Rƒ@"4 P,O O+++44σΩy !5@F@`#F"HJ J?ν?ν9/νΦύΐΦ]ύΕ104632#"&"3.2>7#vimrtjmsί$ Β $# Α $6 ££  ££x-=$$>-ώP,=$$=,σΨβ!A@(S @`€#S€  "sOW W?ν?ν]9/νΦ]ύΕΦ]ύΐ10%#".54>32267#"3&&Ψ :Q22Q; !;R01Q; ί(/½-,(/Ό-μ8[B$$B[87[A##A[Ε60065..5σΩ,&xƒ‹@$6P.O"O+++44σΨ‘&yƒ@$6 P.O"O+++44*σδ,&ΰƒψ‹±Έν@ '9P1O%O+++44υΛ‘&ƒψ@%7P/O#O+++44σξ&ΦŠ‹@ !"P#O++4XΨ‡&\Š@ #$ P%O++4σξ,&Φƒ‹@#5P-O!O+++44XΨ‘&\ƒ @%7 P/O#O+++44σξ?&Φe$‹@'#%P&O"O+++44XΪ΄&\e$@*%' P(O$O+++44-Η,&Ϊƒ‹@, P $O O+++44+Ά‘&ϊƒ@ + P#OO+++44$zδk J@/@M 0@³_Ÿί ? Q€  r r?ν?Εν2Φ]ΥνΦΕ]Φ]ν]+107!#3#5#5}gμ‡rιffώaμ†fYzΏΦ -@Q /?O H H?νΖ?νΦΥΕ]ΦύΕ10%#5#!#-rbfκfμ†Φfώφ"ψΟ,&ήƒ‹@ 2P *O O+++44"φΟ‘&ώƒ@&8P0O$O+++44λy %Κ@6?Ÿ| @`'  90 p €   Έΐ@[H |P ` p      °  /Oo@`€&#€/_‘€ U  Œ????99?]ν?ν?]νΦqύΤ]ύ]]qήΕ]qήν+qr^]Φ^]ν]qr10^]3#3373#4632#"&74&#"326ΗcRBcRΗΗ03311330€  eώ›kώΉGύ•πbPLOOLLPPL0%%01%%έτ9΅‘?ΕΠΕ10!!τώ 9\σηy5sΉ#ΐ@@ L@L@LF_$$7/F- 6#@  J)s330s-33 $) J ?ύΖ?Ε99//3ν23ν2ύ]ΖΔΦνΝΦ]ΖΤΥν10+++654&#"'66323#3!3267#"&55#53667#5<7%#F$W9ag1h<ΨώΙ9)%T " !-:%rj#M6΅± (  _bXY"Y ,%_ `W Y!YΫkzΉ Π@ M M Έΰ@ M (MΈΰ³ MΈΰ³ MΈπ@'MD ΠJ   ??9ν2Φ]Υ]22ύ22Ε]10+++++++7#5'75'75#5!#78P&v|I&oK$o£Β£P%DE%Q8›a"R3F#N4œffb%MΫk w@SŸ € O  ί ο   °  ` / ?   0@Πΰ― QP` U U  ????ύήύΐΦ]ΕύΕΦ]]qΕ]]]]]]qqqq10###=!Ϋ£|£ΒΏfώ§YfFffΨr%s@C›#F`€'D &O_oJ HO  J???ν99//]q3ν23ν]2Φ]222ύ22Ε3Ν2Φ]ν10]7#5#535#535>32##3"32654&Π{CCCC*+)lwxn"Θ– '300XXXcHbώVabWGc― -+)"`•@    ??ήΕΦΔ10".'73267ϊ6*\""\*6!0##0  λk$6ψΥr%$δkΖ λk›?Μk(.Ζk=-Ηk+σήy#>²F Έΐ@ H 0 F$₯J J?ν?ν9/νΦύή]Υ]ή+ν103#'32654&#"4>32#".³)0@?10@?1t θ441¬ώψ*+(275#ώF3769??8Kf5648>;fQ;><Ϋk7 θk<Ϊ“Χ ιk;Ϋk²@p@M M M @ M @ M@ M_/?OR`ΏΟί _o@ HPR_ @  R 0@R 0Έΐ@ H± ??Φ]+qν]Τν]2/3/33/]ν]ή+]]]qqν]10]++++++%2>553#5&&553353* `\U`U\` `π !=0αΦƒx““xƒΦα0=! λ λy'SΆ%@ L Έΐ@+ LF ``?)F#/!!(%H" HJ?ν?ν?νΔ]ΦΤνΔ]]]Φ]Τν10++4>323#56654.#"#53&&)BU-,UC)$*QΧ"5 + + 1&ΩT*%bKjCCjKB~3232>54&##532>54&#"#*D6#9H%,{5G)"A3ύ"(% 24  ! # +J\<=R2 °†8Q4+@ώB'-@b!229[θΦi΅ M Έΰ³ M Έΐ@ M MΈΐ@(M M M M  Q QQ ???ΦΦννΦν9=/910++++++++.'36673Α ,56"2#<"g< ₯W΄¨’6`žII«S†λi0I(σΧ΅*:P³;0Έΐ@* M@M+S0@!`!!<S5S;0 8W&W Ÿ?ύΖ?ν9ΦνΤνΦ]Δ]ν10++]74>7&&54>32&&#"#".%4.'326 5+$*@+5H"?&  -!;F9Q12Q; :$#5**3Ϊ8:79)4'\  "'gH7Y>!;VA*# $((DCB@σΖβ0ƒ@ * M MΈΐ΄LΈΰ΄LΈΐ@6Mΐ0Π0ΰ002 %S(S"1_o0U % %-OW- @W?ύ]Ζ?ύ]Ζ99=//ν]]ΦνΤνΥΕΦΖ]10+++++&&#"33#"3267#".5467&&54>32œL*%ji.,4S%d2)J7!&'! 5F&3N"c ] e"7(+70#&4  6VΡ―$>·SΈΐ@ H&SΈΐ@ H%U?Ε?νΦ+νΤΕΦ+]ΔύΖ10'6654&'.54>7#5!Ρg88*B-/DLΓmYU=5=-@*%%@ %$ 0D/8j_OfQNas=43!+?[Ήΰ2@ Q QPΈΐ@ H 0W ?ν]??Φ+]νΦν106632#4&#"#?!a98J+{.{Η 9O0ώRžB:ώσΤ΅ 5@S@`SUW Ÿ W?ν?ν9/νΦύΐΦ]ύΐ10#"&546322>7#"3&&ΤtffuufftΪ# Ύ #0.Ύ,U³――³²ώV3G++G3οiWWi$υΣΦ-@ @  Q  U W?ύΖ?νΦΦνΖ]10%#".55#533267Σ&C0A'‚ύ$. 5L1­fώζ*'?ηΦKΉΰ³ MΈΰ@$ M`€  Q   ??9??Φύ2ΐΦ]ΕΦΕ10++>73#.'#3»%# ”.11:8/ ',-||/2/684CHH?=7ήΠέ΅$2@Q&%&$Q%$ W?ύΖ??9ΖΦν9Φν103>7.#"'6632#.'-12  &@M81'Ž @}uh,*4 c==B™˜9$QQN!$QSN;[ΆΦζΦY5V΅8g· @ MS5ΈΐΆ H5:$Έΐ@ H:S+S Έΐ@ H 9&U0 8# # 8W?ύΖ?Ε99=//99νΖΦ+νΤνΦ+ΖΦ+ν10+6654&'&&5467&&54632&&#"33#":A6ZRC2.%ng6P:) &jd3((,C-ƒ" ^JBPK/O``    f(!#  ,"%@ σΨβR?ΆΦς?[Υΰ8²S Έΐ@ H QΈΐ@ HW W?ν??νΦ+ύΐΦ+ν10"&'#4632'32654&#",{damd0HŠ !+0%* . ²«cw‚s6ZA#y IHEC2;-Vβ%K@#S 0@ 0  'P'SΈΐ@ H & W ?ύΖ?Ε99ΖΦ+ν]Ζ]Φ]ν107.54>32&&#"'6654&λ+F2%Ed?+G"4!HR332>54&'#"“4Q7/M7!=W5δύ! )  p#O)+R?&#@Z7:Y=fών#/+P(5/$$υΰΦ@· Έΐ@ HQΈΐ@H WU ?ύΐ?ύΖΦ+ΥύΕΖ+]10#5!#32>7#".5‹g€Α)  "P,)C0pff΄4( i.O;3σΏΦ,@ QQ 0  W?ν??Φ]νΦ]ν10"&53326553ωh^|++}] hp ό>66>όώυph[ΫΦ$u@Q/?@HR`€ &$@P`R€%& 0ΐΠR―Ώ%@  U$OU ???ν]2?ν]2Φ]ν]9/]3ν]2Φ]ν+]1032>54&'#5.54632Ι#, `,$`/C+qmsr+D0x@G)6"#9)FCύγ£(?Q/szzs/Q?(αΦ[[ΪΦ]@?/?ΟίR€! 0ΐΠR @PΰπR  W  ????ύ2Ε?Φ]2ν]2Φν]Φ]ν]10%2>553#5.55333) `-B*`*B-a `R !=0κΰB^> šš >^Bΰκ0=! χέβ0s@7 0@ΠRπ0ΐ0ΰ0―0Ώ0P0'00Rΐ/π// &0&@&Π&&R"Έΐ@H1#" +W0W ?Ε?νΥΕ?ν?ΕΦ+Εύ]ή]ύ]]]]qή]ν]10%32654&'7#"&'#".5467326553+#S! 3&!-1&2 -,R# `Μ78>16‚9%CHJ"+N<#$##$#N]## "" ## ""5²½(φδζ&©‰Ήτ@ '2 P 6O++4(φδζ&©ΑΉτ@ )6 P 'O++4(φδζ&©–@+( P :O )O+++44(φδζ&©£±Έτ@ -( P +O )O+++44(φδζ&©—@+' P :O (O+++44(φδζ&©€@-' P +O (O+++44(φδ7&©˜±Έτ@ 2< P NO 'O+++44(φδ7&©₯±Έτ@ 2< P =O 'O+++44ΰλ&$‰5™ Ή5΄" P+4Λλ&$Α ™ Ή ΄& P+4ώϋλ&$–ώ»™±Έώ»΄ P+44λ&$£ώΘ™±ΈώΘ΄ P+446λ&$—ώθ™±Έώθ΄ P+44)λ&$€ώα™±Έώα΄ P+44wλΠ&$˜ ™±Έ ΄", P+44xλΠ&$₯ ™±Έ ΄", P+44@σΖζ&­‰@  1™±Έώ>΄,)#P+44ώœλ&¨£ώM™±ΈώM΄.)#P+44ώΛλ&¨—ώ}™±Έώ}΄,(#P+44ώ½λ&¨€ώu™±Έώu΄.(#P+44ώλΠ&¨˜ώ‘™±Έώ‘΄3=#P+44ώώλΠ&¨₯ώ™±Έώ΄3=#P+44(φδΑ&©΅@ *( P )O++4(φδΑ&©ΐ@ )' P (O++4@σΖΑ&­΅@  42!P,3O++4@σΖΑ&­ΐ@  31!P,2O++4?[ΉΑ&―΅@ PO++4?[ΉΑ&―ΐ@ PO++4$υΣΑ&±΅@  P O++4$υΣΑ&±ΐ@  P O++4σΨΑ&R΅@ #! P"O++4σΨΑ&Rΐ@ " P!O++43σΏΑ&½΅@ PO++43σΏΑ&½ΐ@ PO++4χέΑ&Α΅@ 42P 3O++4χέΑ&Αΐ@ 31P 2O++4(Vδζ&©&‰ˆ±Έτ΄B< P+44(Vδζ&©&Αˆ±Έτ΄B< P+44(Vδζ&©&–ˆ@ +( P+444(Vδζ&©&£ˆ²Έτ΄-( P+444(Vδζ&©&—ˆ@ +' P+444(Vδζ&©&€ˆ@ -' P+444(Vδ7&©&˜ˆ²Έτ΄2< P+444(Vδ7&©&₯ˆ²Έτ΄2< P+444ͺφό7‰ώ™†žφό7Αώσ™†ώΕφό7–ώ…™†ώβφό7£ώ“™†ώχφό7—ώ©™†ώκφό7€ώ’™†.φόΠ7˜ώΐ™†.φόΠ7₯ώΐ™†?VΉζ&―&‰ˆ¨±ΈΟ΄/P+44?VΉζ&―&Αˆ¨±ΈΟ΄/#P+44?VΖζ&―&–ˆ¨@  3P+444?VΉζ&―&£ˆ¨²Έύ΄3P+444?VΉζ&―&—ˆ¨@ 3P+444?VΎζ&―&€ˆ¨@  3P+444?VΉ7&―&˜ˆ¨²Έν΄G)P+444?VΉ7&―&₯ˆ¨²Έν΄G)P+444Qφσ7‰ώ¦™•]φσ7Αώ²™•ώ‡φσ7–ώG™•ώ€φσ7£ώU™•ώ§φσ7—ώY™•ώ›φσ7€ώS™•ώΰφσΠ7˜ώr™•ώΰφσΠ7₯ώr™•Vέζ&Α&‰ˆ ·1FP+44Vέζ&Α&Αˆ ·3FP+44Vέζ&Α&–ˆ@ 52P+444Vέζ&Α&£ˆ²Έ΄72P+444Vέζ&Α&—ˆ@ 51P+444Vέζ&Α&€ˆ@ 71P+444Vέ7&Α&˜ˆ²Έ΄™±Έώ6΄85#3P+44ώœφό&Ώ£ώM™±ΈώE΄:5#3P+44ώΛφό&Ώ—ώ}™±Έώt΄84#3P+44ώ½φό&Ώ€ώu™±Έώm΄:4#3P+44ώφόΠ&Ώ˜ώ‘™±Έώ‰΄?I#3P+44ώώφόΠ&Ώ₯ώ™±Έώˆ΄?I#3P+44(φδͺ&©aΉτ@ +5 P 'O++4(φδ‡&©ŠΉυ@ '( P )O++4(VδΑ&©&΅ˆ ·*( P+44(Vδΰ&©ˆ Ήτ΄2, P+4(VδΑ&©&ΐˆ ·)' P+44(φδͺ&©Š@ 5+ P -O++4(Vδͺ&©&Šˆ ·5+ P+44 λ5&$a‹@ % PO++4 λ&$Š‹@  PO++4gλk&$CώΟ΄ ΉώΫ΄ P+4‹λk&$ώσ΄ Ήώ΄ P+4 φόk I@,  @ HR W s ????9/9ν?ν?ΖΦήύ+Ζ9107##673#.53%3ηee6†5iσ(2 `ώ“L&˜˜·-‡ˆώΟ² *8#:ώ» #’"«I所VPΣΆ  ’?ΕΦΥΞ103#"&5473 #8=_4 ;.0«IζΆ  Έ?ΔΦήΕ10667&&54632« $'B3.!!#!(P"i‹ͺ@   §§??ήΕΦΥΦΕ102#&&#"#54>ϊ5'Z['5ͺ$5!&&!5$^•7 -K@--"#. ³³.ο""" (†Π²§Π  ²§?]ν]?]ν]?Υ]Ξ]2ΦύΦνάΥΦΕ10#"&54632#"&54632'.#"#>32Υ$""$ΐ"##"T  E'11'M!! !! A%5##5%?VΉΑ&―&΅ˆ¨±Έν΄#P+44?VΉΰ&―ˆ¨ Ή¦΄P+4?VΉΑ&―&ΐˆ¨±Έν΄#P+44?[Ήͺ&―ŠΉώ@ "PO++4?VΉͺ&―&Šˆ¨±Έπ΄3P+449Μk&(Cώ‘΄ Ήώ‘΄ P+4BΜk&(ώͺ΄ Ήώͺ΄ P+4'Ηk&+Cώ΄ Ήώ›΄ P+41Ηk&+ώ™΄ Ήώ₯΄ P+4φσk q@ R °ΐΐΠΰΈΐ@ HR  ΐΠΰΈΐ@ HR W  U ????9/ν?ν?Φύ+]2Φq2ύ+]Φqύ]ήΞ10###335.539af``f(2 `kύ•ώζkύύύ‹*8#:ώ» #@΄ζ!@  Έ?ΔέέΖ/ΖΕέΦΝέΝ10'667&&54632Hl;Ί " ?0δ«+Ÿ!!#!)O"N₯ζ!@  Έ?ΔέέΖάΖέήΝέΝ10'7667&&54632₯~;lώφ! "!@/­Ÿ+«Ά!!#!)O"n†7'6@'ΰ"" ΰ  '  /ήΝή]ΐέΝ/έά]ΝΦ]έΕΖ210.#"#>32667&&54632A   E'11'Ρ   ""ͺ%5##5%    !$υΣͺ&±aέΉά@ " P O++4$υΣ‡&±ŠέΉή@  P O++4υΣΪ&±³ο!²Έξ@ P .O "O O++++444υΣΪ&±Ψο!²Έξ@ P -O "O O++++444$υΣͺ&±ŠέΉά@ " P O++4$υΣ7&±‹έ²ΈΫ@ P "O O++4+4446Ώ5&,a‹@ P O++46Ώ&,Š‹@  PO++4%Ώk&,Cώ΄ Ήώ˜΄ P+4Ώk&,ώ‡΄ Ήώ’΄ P+4O₯ζ@   ~~?Ε?ΔΦΕΥήΕ10'&&546329l;.0> " !δ«+Ÿ₯ R(!#!!H¬ζ@   ~~?Ε?ΔΦΥΦήΝ10'7&&54632¬;l§0?!" !­Ÿ+«ά R(!#!!n†7'+@'$!°  ( †?ΕΕΥήΕήΥΤΕΦ]ΕΥΞ10.#"#>32.54632A   E'11'h#"   ͺ%5##5%€!    3σΏͺ&½a@  PO++43σΏ‡&½Š@ PO++4&σΞΪ&½³@P,O OO++++444&σΞΪ&½Ψ@P+O OO++++444?[Υζ&Ή‰Ήπ@ ) P-O++4?[Υζ&ΉΑΉπ@ - PO++43σΏͺ&½Š@  PO++43σΏ7&½‹@P OO++4+444 θ5&<a‹@ #PO++4 θ&<Š‹@ PO++47θk&<CώŸ΄ Ήώͺ΄P+4'θk&<ώ΄ Ήώš΄P+4WΨ&3Αώ¬™ ΉώŸ΄) P+4&ΞΪ )@ ••~–˜– ˜?ν?ν?ΕΦύΞΤΥΦν10#"&54632#"&54632''«(''(#(''(άN>a]## "" ## ""]½²&ΞΪΨ…oΑ΅~?ΕΦΕ10'Ύ±.ΌΑuG`VέΑ&Α&ˆ΅±Έ΄DBP+44Vέβ&Αˆ Ά<6P+4VέΑ&Α&ˆΐ$ ·#CAP+44χέͺ&ΑŠΉ@ ?5P 7O++4Vέͺ&Α&ˆŠ±Έ΄OEP+44σΩy&2Cώ|΄ Ήώˆ΄#!P+4DσΩy&2ώ¬΄ ΉώΈ΄" P+4ώϊλy&¨Cώb΄ Ήώn΄+)#P+43λy&¨ώ›΄ Ήώ§΄*(#P+4 φόy'37Ή3ΐ΄ L%Έΰ³M%Έΐ@ L$@M$@ L @M Έΐ³ M Έΐ³M Έΐ³ M Έΐ@ M @MΈπ³MΈΐ³ MΈΐ³ MΈΐ@ M33€3΄3 33‹33/Έΐ³H/Έΐ@f H/R4- ----@M@ MO_ΟίR @0 P   /  ―!!! !!%ΐΠRΰπ%$4/ 3W( %U" U W?ν?ν?ν?ν?ΦέΥ]ν]Υ]]ή]Υ]Τ]Νν]++ή]_]]ν++Δ]]q10+++++++++++++++46323#5>54.#"#53&&.53TIHT"@Ž  B!α(2 `bŒ‹‹ŒB†=]W5DO+&E45F'*OB4W]=‰ώΣ*8#:ώ» #…oΑ΅~?ΕΦΕ10'7oΌ.±e`Gu«IζΆ ~?ΔΦΥΞ10&&54632 3B'$ "P(!#!!ͺVλ&$'‰ώ™ˆ±Έ‘΄, P+44§Vλ&$'Αώό™ˆ±Έ΄, P+44ώΧVλ&$'–ώ—™ˆ²Έ'΄0 P+444ώτVλ&$'£ώ₯™ˆ²Έ6΄0 P+444Vλ&$'—ώΝ™ˆ²ΈI΄0 P+444Vλ&$'€ώΖ™ˆ²ΈC΄0 P+444\VλΠ&$'˜ώξ™ˆ²Έj΄"D P+444]VλΠ&$'₯ώο™ˆ²Έj΄"D P+444ZVΗ&+'‰ώ―™ˆ$±Έm΄ !P+44fVΗ&+'Αώ»™ˆ$±Έs΄!P+44ώVΗ&+'–ώP™ˆ$²Έ΄%P+444ώ­VΗ&+'£ώ^™ˆ$²Έ΄%P+444ώ°VΗ&+'—ώb™ˆ$²Έ΄%P+444ώžVΗ&+'€ώV™ˆ$²Έ΄%P+444ώφVΗΠ&+'˜ώˆ™ˆ$²Έ;΄9P+444ώφVΗΠ&+'₯ώˆ™ˆ$²Έ;΄9P+444kVλ&¨'‰ώΐ™ˆ$±Έv΄(=#P+44GVλ&¨'Αώœ™ˆ$±Έd΄*=#P+44ώ~Vλ&¨'–ώ>™ˆ$²Έώ΄,A#P+444ώœVλ&¨'£ώM™ˆ$²Έ΄.A#P+444ώΛVλ&¨'—ώ}™ˆ$²Έ&΄,A#P+444ώ½Vλ&¨'€ώu™ˆ$²Έ΄.A#P+444ώVλΠ&¨'˜ώ‘™ˆ$²Έ@΄3U#P+444ώώVλΠ&¨'₯ώ™ˆ$²Έ?΄3U#P+444 Vλk&$ˆ Ά" P+4-VΗk&+ˆ$ Ά$P+4 Vλy&¨ˆ$ Ά$3-#P+4.μk#@ @ L@ LΈΰ΄ LΈΐ³ MΈΰ@1 M%$% %# S!#$"@ H"U #OoU?ύ]2ή2ύ+2Ζ??ΦΠΥ2ν2ΠΕΦΖ9/9910+++++&&##5!#3##.'53267#5 :.nΎsE:hJ84.Ž444?@DΧΣ'YY !XDD =?<?;6Z#X94Ί΅+;Nam)@ no32"32654&766'&&'467'7&&727&&''&&5&#"6"'3274676667'7676&'&Ί5F((F44F((F5ώ½  ¬  ‰$  $K+%  %+  τ(F44F((F55F  u  V )  ( _(%  —  %(§  [™΄ #'+/37―@3 M2 M+ M* M' M& M#Έπ³ M"Έψ@ M! M  MΈψ@Ή M M M&6Ff†= &6Ff†= &f&f=  >  A&%"!  x I i i6f 6 f  9  9=š1ͺ1i1y1‰11@ H 11/€4;H/((^(n(M(>((Έ€@N(+Hš(ͺ(i(y(‰((@ H(° I($€4;H$$^$n$M$.$>$ $$ύ$š$ͺ$i$y$‰$$@ H $$6Έ€@ 4;H6652Έ€@ H2'2722+Έώ@-1H1+ +++ρ++Έ€@ H+ +0++'Έώ³-1H'Έώ@³(,H'Έ€@ H' '0''   "/ ;Ÿ^½νύ[LͺΊy  ; ? o =O  Ώ ο  ­ ν { L  ͺ Ϊ 9 i   /_ ;鏿ν{LͺΪ8 f†3`=P€παρ²SD΅v¦ 0`=€°ΰAαr’DΤ@>₯f7  0 = ΐ ! ρ ‚ T δ ΅ F   9ζΈ€@ 4EH",585Έώ@;1;Ha5@5P5!51555α5ρ5²5Β55“5£5‚5c5s5T5C5’55Έ€@H355 555"Έ@H΅"Ε"Υ"¦""X33έ,,Έ@@ &HK,[,<,,Έ@Hͺ,Ί,Κ,,€HZ,I,,@ H,Έ·2EH11&4Έ³0;H4Έΐ³,/H4Έ€@3#+H|4Œ4k4\4K44€HZ44@ H4#+#;##ΐH#W))+-Έώ€³$'H-Έώΐ³#H-Έ³H-Έ@³H-Έ€@ H--'- -Έώ@2EH$$& @P`€ ;ΐΰ±`€ !Aα’Βƒrc$D₯ΕΥεf†G6  <Φ€wαC₯ i™3/?<―οžO Έ`@*IL\l¬μ ΛͺΊ)i A؏ŸύξL\»ͺ  /O_o―;ΏΟοOo.­ΝνLl| +ΫλŠͺΚIi8) >ΩŽxνKͺ f  3  `=€ ΰAαρ’ScDe₯΅Ε@9' Aΰπ§PA²£`p― ?Νr2_]_q_qqrrrr^]2^]]qqqqrr^]?Ν^]]2^]]qqrrr^]2^]]]]]]qqqrrrr^]9/]3^]]]qqqrr^]3^]]]]qq+rrrr^]]Ν^]]2^]]qqrrr^]]2^]]]]]qqqqqqrrrr^]]]?Ν^]2+2^]+++++?Ν]2+q2+]+qqqq+++9/3+3+]]+]+qq+qΝ]2]]+2_]]_]+_]_qqqqqqqrrrrr+ά2ά2+ή2ά2rΜΝ22]]]]qqqrr^]2^]]]]qqqrr^]2^]]]qqqqr^]Ν^]]2^]]qqqrrr^]]2^]]]qqqqrr^]2^]2^]]]qqqqrr^]]Ν_^]22]+++2]+_qrrr+2]+Ν]+2]+]]qrrrrr+2++]]+rrrr2+2]+]]10^]]]]]]+^]]]]]^]]^]]^]]^]^]^]^]+++++++++++++335!5!35!3335!5!35!3|ώ―4ώΜ4ώ―4ώ―›ώ―5ώΛ5ώ5ώk*ώΦώ΄*ώΦyύhk*ώΦώΣ*ώΦL*ώΦώ΄*ώΦyύhk*ώΦώΣ*ώΦσπή)η@( M(@M'@M L MΈΰ³MΈΰ@M@ M@ MΈΐ³MΈΰ³MΈΐ³ MΈΨ³MΈΐ³MΈπ³MΈΨ³ MΈΰ³ MΈΐ@1 L'!'! !'+*D$ $0$$ ??99//99]]99ΖΖ9/////99910++++++++++++++++++7774>54.#"6322654&#"φφφ #,θφφυ±!   .   iΠυ y'oj&t–"">@ EI†?ΥνΠΥν1033!PώήrΜύδ"τ>@ EI†?ΥνΠΥν1033!Pώή>ώ4PVτr@ EI’?ΥνΠΥν10!##"PrPώ4V">·E†’??Φν10#3"PPͺθ"τrΆI’?νΠΕ105!τ"PPV">@ EI†’??ΥνΠΥν310##533"PPͺΜPΜVτr2@@P `p EIœ’??ν]2ΠΥνΐ]q10###5τPrPώ4ΜP"τ>1@@`ΐ ŸEI†?Υ2νΠΥν]ΐ]q105333P"PΜώ4PVτ>(@ŸE’I†?έν]?Φύ]Ν]31033##PP>ώ4Pώ4Vτ> @@(@ 0pΐ  E0 ’  I†?Υ2ν]2?ΠΥ]2ν2ΐ]q10#5333##PP"PΜώ4Pώ4Vτ>V@7  ` p ΐ   `pΐ E E ’ IΏI€†?Υ]2ύή]ν2?ΠΥνΠΥνΐ]qΐ]q105333###5PPrP|ώ„PPPώ„|PVτ>J@.€E ? Ώ  ŸE0°’ I †I†’??Υν?Υν?ΠΥ]ν]3ΠΥ]2ν]10##53;3##P‚‚PPP‚‚PͺΜPΜώ4Pώ4V"r@ EI’?ΥνΠΥν10!##"PrύδΜV"> \@>_oE _oE @M_I_   0  ’P`IΏ€†?Υ]]]νq?Υ]]νq+ΠΥνqΠΥνq1033!!##Pώή"PΒ|ώ4Pώ4|Vτ> 8@ ΠE ΠE I°’I†?Υν?Υ]]νΦύΕ]ΦύΕ]10!33##!τώήPP"rΜώ„πώ„Μτ> @@)  @ P  ` p ΐ  0ΠE II†?Υ2ύΦνΠΥύΕ]ΠΕ]q105333!5Pώ rP|ώ„PPPP"> <@%@ MΏPίp E II†?ΥύΦνΠΥνΠΕ]]qq+1033!!!Pώή"ώήΒ|ώ4PPτ> 8@!p p_0ΠE II†?ΥύΦνΦύΕ]qqΦΕ]q10!33!!τώήPώή"ώήrΜώ„ PVτΒ @@)  @ P  ` p ΐ   0ΠE I I’?ΥΐύΦνΠΥύΕ]ΠΕ]q10###=!τPτ"Pώ„|PPPPV"Β 4@Pίp? E II’?ΥύΦνΠΥνΠΕ]]]q10!##5!!"P"ώή"ώ4|πPVτΒ 8@"Pp p°0ΠE II’?ΥύΦνΦύΕ]qΦΕ]q10%##!%!!τP"ώή"ώήώ„Μ P‚Vr>@EE’††’????ΦύΦν10#;#PPPPPͺθόVτ> v@N0°Ep   ° ΐ Π  E°0°Ep   ° ΐ Π  E°’I I† ’II†?ΥύΦν??ΥύΦν?ΠΥ]ύΦ]qύΕ]ΠΥ]ύΦ]qύΕ]1033###35#333##‚Pτ‚PP‚ώ P‚Β|ώ4 ώ„ΜPΜώ„ ώ4|Vr> E@)Ÿ  E@MEŸE ’I I†’†???ΥύΦν?ΠΥύ]Φν]+ΠΥν]103#33#3##"PPώή‚PP‚>όl|ώ4Pώ4|‚Vτ> c@@  E  E  @ME@M°0 ’ II ††’???ΤύΦν?Φ]]]+ν]+Π]Υν]Π]Υν]10#3#33##3PP"P‚‚Pͺθώ4Μώ„πώ„Μτ> ?@$ E?ΏE0° I †II†?ΥύΦν?ΥνΠΕΠΥ]νΠΥ]ν10!5533#!#33τώ ‚PτP‚"PP |ώ4Μώ„r> :@" E ? E I †IP?†?Υ]]ν?ΥνΠΥνΠΥ]]ν1033#!3!‚P"PώŽΒ|ώ4Pύ”‚τ> @@'?  E0° E° I †IP?†?Υ]]ν?ΥνΤ]ύΕΦ]ύΕ]10#33!3!τP‚ώŽP"rΜώ„πlύδVτΒ c@A€E?Ώ  Ÿ  E0°@MI ° I° ’ I°’?Υ]ν?Υ]ύΦ]ν]+ΠΕΠέ]ν]ΠΥ]ν]105!##3!3##τ‚Pώ P‚rPP ώ„Μώ4|VrΒ r@ @MŸE Έΐ@#M€  EŸ―0 @MŸI Έΐ@M€   ’I_0’?Υ]]ν?Υ]+ν]+ΠΥ]]νΠΥ]+ν]+103##5!#!P‚rPώή"ώ4|πύ”‚VτΒ d@Fp€ŸE°  Ÿ―0E °?   Ÿ  Ip€’I0’?Υ]ν?Υ]ν]Τ]]ύΕ]]Φ]ύ]Ε]10%##35!#!τ‚PώήPrώ„ΜPύδlτΒ@ II ?ύΦνΠΕΠΕ1055!%5!τώ τPP PPVr> '@ E E † ’†I’?Υν???ΠΥ2ύΦν10##533#3P‚‚P PPͺΜPΜόθ‚Vτ> '@ E E ’ †I’†??Υν??ΠΥ2ύΦν1033##3#"P‚‚P PP>ώ4Pώ4θό"τ> E@- @H E@HE0`p°ΐΠ † I†?Υν]33?ΠΥ]ύ+Φν+ΐ10!53333τώ ‚PPPrPPΜώ4Μώ4"r> ;@%ŸE ŸE ‘†ŸI‘†??]ν]??]ΠΥύ]Φν]1033#3#‚P"PPrΜύδύδ‚"τ> ;@%€E€E †‘†ŸI‘?]ν]??]?ΠΥύ]Φν]10#33#3τP‚ώήPP"ώ4PVτr @@'€EΏ ŸE0 °  ’’ Iƒ?ν23??ΠΥ]ν]ΠΥ]ν]105!####τ‚PPP"PPώ4Μώ4ΜVrr C@*„”EΏ?  ŸE ’ƒ’Iƒ?ν]???ΠΥν]Φ]]_]ν]103##%3#P‚"PPrύδΜPύδ‚Vτr C@*„”E$ ‹ ›  E°0 ƒ’Iƒ’??ν]??Φ]_]ν]Π]Υν]10##3#3τ‚PώήPP"ώ4ύδVτ>΅†’??/Ε10!τώ >όθ.nτ> #'+/37;?CGKOSW[_cgkosw{ƒ‡‹“—›Ÿ£§«―³·3#3#73#3#3#3#73#3#3#3#73#3#3#3#73#3#3#3#73#3#3#3#73#3#3#73#3#3#73#3#3#73#3#3#73#3#3#73#3#3#73#3#3#73#3#73#''N''N''N''κ''N''N''N''κ''N''N''N''κ''N''N''N''κ''N''N''N''κ''N''N''N''κ''œ''œ''N''N œ''N''N œ''N''N œ''N''N œ''N''N œ''N''N œ''œ >'''u'''''''u'''''''u'''('''u'''''''u'''''''u'''''''Π'''u'u'''u'u'''u'v'''u'u'''u'u'''u'u'''Unτ> #'+/37;?CGKOSW[_cgkosw{ƒ‡‹“—›Ÿ£§«―³·»ΏΓΗΛΟΣΧΫίγηλοσχϋ #'+/37;?CGKOS3#73#3#73#73#73#3#73#73#73#3#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#73#73#73#73#73#3#3#73#73#73#73#73#73#3#73#73#73#73#73#73#3#73#73#73#73#73#73#3#73#73#73#73#73#73#3#73#73#73#73#73#73#3#73#73#73#73#73#73#''N'''''N'''''N'''''N'''''N'''''N''ώz''N''N''N''N''N''ώz''N''N''N''N''N''ώz''N''N''N''N''N''ώz''N''N''N''N''N''ώz''N''N''N''N''N''' ώ,''N''N''N''N''N''N ώ,''N''N''N''N''N''N ώ,''N''N''N''N''N''N ώ,''N''N''N''N''N''N ώ,''N''N''N''N''N''N ώ,''N''N''N''N''N''N >'''''''u'''''''u'''''''u'''''''''''u'''''''''''v'''''''''''u'''''''''''u'''''''''''‚'u'''''''''''''u'''''''''''''v'''''''''''''u'''''''''''''u'''''''''''''u'''''''''''''IVτ> #'+/37;?CGKOSW[_cgkosw{ƒ‡‹“—›Ÿ£§«―³·»ΏΓΗΛΟΣΧΫίγηλοσχϋ ;35#35#35#35#735#35#35#35#735#35#35#35#35#35#35#35#735#35#35#35#735#35#35#35#35#35#35#35#735#35#35#35#735#35#35#35#35#35#35#35#735#35#35#35#735#35#35#35#35#35#35#35#735#35#35#35#735#35#35#35#35#35#35#35#735#35#35#35#735#35#35#35##5##5##5##5##5##5##'''N''N''N''N''N''N''N''N''N''N''N''ώz''N''N''N''N''N''N''N''N''N''N''N''ώz''N''N''N''N''N''N''N''N''N''N''N''ώz''N''N''N''N''N''N''N''N''N''N''N''ώz''N''N''N''N''N''N''N''N''N''N''N''ώz''N''N''N''N''N''N''N''N''N''N''N''G ''''''''''''π'''u'''''''u'''''''u'''u'''u'''''''u'''''''u'''u'''v(((''''v(((''''v(((v'''u'''''''u'''''''u'''u'''u'''''''u'''''''u'''u'''u'''''''u'''''''u'''‚όθVτ>W@6€E?ΏŸE 0 °  † €I †’’???Υ22ν]22?ΠΥ]2ν]2ΠΥ]2ν]2103#####53333r‚‚PPP‚‚PPPrPώ4Μώ4ΜPΜώ4ΜVτ>1@E I I †’??Υ2ύ2Φ2ν2ΠΥ22ύΕ3310###535#5333#τPP"Pώ„|PPP|ώ„PPnI ITXu …‘@ ΰ ΰ ο ο ITu ’  › ± :Ή  σ  + €I Ι Ι 4η 4η › ±  σCopyright 2011 Canonical Ltd. Licensed under the Ubuntu Font Licence 1.0Ubuntu MonoBoldUbuntu Mono Bold Version 0.80Ubuntu Mono BoldVersion 0.80UbuntuMono-BoldUbuntu and Canonical are registered trademarks of Canonical Ltd.Dalton Maag Ltdhttp://www.daltonmaag.com/Copyright 2011 Canonical Ltd. Licensed under the Ubuntu Font Licence 1.0Ubuntu MonoBoldUbuntu Mono Bold Version 0.80Ubuntu Mono BoldVersion 0.80UbuntuMono-BoldUbuntu and Canonical are registered trademarks of Canonical Ltd.Dalton Maag Ltdhttp://www.daltonmaag.com/…  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aΔ¦Ε«‚ΒΨΖδΎ°Ά·΄΅‡²³ΩŒεΏ±»£„…½–θ†Ž‹©€Šƒ“ςσ—ˆήρžͺυτφ’­ΙΗbcdΛeΘΚΟΜΝΞιfΣΠΡ―gπ‘ΦΤΥhλν‰jikmln oqprsutvwκxzy{}|Έ‘~€μξΊ     ύώ !ψω"#$%&'()*+,-./012Χ3456789:;<=>?@ABCβγDEFGHIJKLMNOPQRSTUVWXYZ[\]ϋό^_`abcdefghijklmnopqrstuvwζηxyz{|}~αΫάέΰί€‚ƒ„…†‡Όˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±²˜³š™΄ο΅Ά₯’œ§”•Ήΐ·ΑΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±²Ÿ³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑ›ΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικ !"υφ#ψωϊϋόύώ     .nullEurouni00A0uni00ADmacronperiodcenteredAmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatdcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccent Gcommaaccent gcommaaccent Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Idotaccenti.loclIJij Jcircumflex jcircumflex Kcommaaccent kcommaaccentkgreenlandic.case kgreenlandicLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaronnapostrophe.case napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacute Scircumflex scircumflexuni0162uni0163TcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Scommaaccent scommaaccentuni021Auni021Bdotlessj apostropheuni02C9WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave zerosuperior foursuperior fivesuperior sixsuperior sevensuperior eightsuperior ninesuperior zeroinferior oneinferior twoinferior threeinferior fourinferior fiveinferior sixinferior seveninferior eightinferior nineinferior afii61289 estimatedonethird twothirds oneeighth threeeighths fiveeighths seveneighthsonefifth twofifths threefifths fourfifthsonesixth fivesixths oneseventh twosevenths threesevenths foursevenths fivesevenths sixseventhsoneninth twoninths fourninths fiveninths sevenninths eightninthsDeltauni2126uni2215uni2219f_if_l zero.supsone.supstwo.sups three.sups four.sups five.supssix.sups seven.sups eight.sups nine.sups zero.sinfone.sinftwo.sinf three.sinf four.sinf five.sinfsix.sinf seven.sinf eight.sinf nine.sinf caron.alt commaaccentrevcommaaccentcaron.alt.short Parenleft ParenrightHyphenSlashAt Bracketleft Backslash Bracketright Braceleft Braceright GuilsinglleftBulletEndashEmdashGuilsinglright Exclamdown GuillemotleftGuillemotright Questiondownuni0180uni0181uni0182uni0183uni0184uni0185uni0186uni0187uni0188uni0189uni018Auni018Buni018Cuni018Duni018Euni018Funi0190uni0191uni0193uni0194uni0195uni0196uni0197uni0198uni0199uni019Auni019Buni019Cuni019Duni019Euni019FOhornohornuni01A2uni01A3uni01A4uni01A5uni01A6uni01A7uni01A8uni01A9uni01AAuni01ABuni01ACuni01ADuni01AEUhornuhornuni01B1uni01B2uni01B3uni01B4uni01B5uni01B6uni01B7uni01B8uni01B9uni01BAuni01BBuni01BCuni01BDuni01BEuni01BFuni01C0uni01C1uni01C2uni01C3uni01C4uni01C5uni01C6uni01C7uni01C8uni01C9uni01CAuni01CBuni01CCuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01D5uni01D6uni01D7uni01D8uni01D9uni01DAuni01DBuni01DCuni01DDuni01DEuni01DFuni01E0uni01E1uni01E2uni01E3uni01E4uni01E5Gcarongcaronuni01E8uni01E9uni01EAuni01EBuni01ECuni01EDuni01EEuni01EFuni01F0uni01F1uni01F2uni01F3uni01F4uni01F5uni01F6uni01F7uni01F8uni01F9 Aringacute aringacuteAEacuteaeacute Oslashacute oslashacuteuni0200uni0201uni0202uni0203uni0204uni0205uni0206uni0207uni0208uni0209uni020Auni020Buni020Cuni020Duni020Euni020Funi0210uni0211uni0212uni0213uni0214uni0215uni0216uni0217uni021Cuni021Duni021Euni021Funi0220uni0221uni0222uni0223uni0224uni0225uni0226uni0227uni0228uni0229uni022Auni022Buni022Cuni022Duni022Euni022Funi0230uni0231uni0232uni0233uni0234uni0235uni0236uni0238uni0239uni023Auni023Buni023Cuni023Duni023Euni023Funi0240uni0241uni0242uni0243uni0244uni0245uni0246uni0247uni0248uni0249uni024Auni024Buni024Cuni024Duni024Euni024Funi0292breve_inverted double_grave ring_acutedieresis_macron dot_macrondieresis_gravedieresis_acutedieresis_breve tilde_macron acute.asccircumflex.asc caron.ascdieresis_grave.capdieresis_acute.capdieresis_breve.capuni0400 afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061uni040D afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097uni0450 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109uni045D afii10110 afii10193afii10066.locluni0462uni0463uni0472uni0473uni0474uni0475uni048Auni048Buni048Cuni048Duni048Euni048F afii10050 afii10098uni0492uni0493uni0494uni0495uni0496uni0497uni0498uni0499uni049Auni049Buni049Cuni049Duni049Euni049Funi04A0uni04A1uni04A2uni04A3uni04A4uni04A5uni04A6uni04A7uni04A8uni04A9uni04AAuni04ABuni04ACuni04ADuni04AEuni04AFuni04B0uni04B1uni04B2uni04B3uni04B4uni04B5uni04B6uni04B7uni04B8uni04B9uni04BAuni04BBuni04BCuni04BDuni04BEuni04BFuni04C0uni04C1uni04C2uni04C3uni04C4uni04C5uni04C6uni04C7uni04C8uni04C9uni04CAuni04CBuni04CCuni04CDuni04CEuni04CFuni04D0uni04D1uni04D2uni04D3uni04D4uni04D5uni04D6uni04D7uni04D8uni04D9uni04DAuni04DBuni04DCuni04DDuni04DEuni04DFuni04E0uni04E1uni04E2uni04E3uni04E4uni04E5uni04E6uni04E7uni04E8uni04E9uni04EAuni04EBuni04ECuni04EDuni04EEuni04EFuni04F0uni04F1uni04F2uni04F3uni04F4uni04F5uni04F6uni04F7uni04F8uni04F9 afii61352 afii00208uni20B4uni20AEtengeroublekratkaAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonPhiChiPsialphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega Alphatonos EpsilontonosEtatonos Iotatonos Iotadieresis Omicrontonos UpsilontonosUpsilondieresis Omegatonos alphatonos epsilontonosetatonos iotatonos iotadieresisiotadieresistonos omicrontonosupsilondieresis upsilontonosupsilondieresistonos omegatonostonos tonos.cap dieresistonosuni1F00uni1F01uni1F02uni1F03uni1F04uni1F05uni1F06uni1F07uni1F08uni1F09uni1F0Auni1F0Buni1F0Cuni1F0Duni1F0Euni1F0Funi1F10uni1F11uni1F12uni1F13uni1F14uni1F15uni1F18uni1F19uni1F1Auni1F1Buni1F1Cuni1F1Duni1F20uni1F21uni1F22uni1F23uni1F24uni1F25uni1F26uni1F27uni1F28uni1F29uni1F2Auni1F2Buni1F2Cuni1F2Duni1F2Euni1F2Funi1F30uni1F31uni1F32uni1F33uni1F34uni1F35uni1F36uni1F37uni1F38uni1F39uni1F3Auni1F3Buni1F3Cuni1F3Duni1F3Euni1F3Funi1F40uni1F41uni1F42uni1F43uni1F44uni1F45uni1F48uni1F49uni1F4Auni1F4Buni1F4Cuni1F4Duni1F50uni1F51uni1F52uni1F53uni1F54uni1F55uni1F56uni1F57uni1F59uni1F5Buni1F5Duni1F5Funi1F60uni1F61uni1F62uni1F63uni1F64uni1F65uni1F66uni1F67uni1F68uni1F69uni1F6Auni1F6Buni1F6Cuni1F6Duni1F6Euni1F6Funi1F70uni1F71uni1F72uni1F73uni1F74uni1F75uni1F76uni1F77uni1F78uni1F79uni1F7Auni1F7Buni1F7Cuni1F7Duni1F80uni1F81uni1F82uni1F83uni1F84uni1F85uni1F86uni1F87uni1F88uni1F89uni1F8Auni1F8Buni1F8Cuni1F8Duni1F8Euni1F8Funi1F90uni1F91uni1F92uni1F93uni1F94uni1F95uni1F96uni1F97uni1F98uni1F99uni1F9Auni1F9Buni1F9Cuni1F9Duni1F9Euni1F9Funi1FA0uni1FA1uni1FA2uni1FA3uni1FA4uni1FA5uni1FA6uni1FA7uni1FA8uni1FA9uni1FAAuni1FABuni1FACuni1FADuni1FAEuni1FAFuni1FB0uni1FB1uni1FB2uni1FB3uni1FB4uni1FB6uni1FB7uni1FB8uni1FB9uni1FBAuni1FBBuni1FBCuni1FBDuni1FBEuni1FBFuni1FC0uni1FC1uni1FC2uni1FC3uni1FC4uni1FC6uni1FC7uni1FC8uni1FC9uni1FCAuni1FCBuni1FCCuni1FCDuni1FCEuni1FCFuni1FD0uni1FD1uni1FD2uni1FD3uni1FD6uni1FD7uni1FD8uni1FD9uni1FDAuni1FDBuni1FDDuni1FDEuni1FDFuni1FE0uni1FE1uni1FE2uni1FE3uni1FE4uni1FE5uni1FE6uni1FE7uni1FE8uni1FE9uni1FEAuni1FEBuni1FECuni1FEDuni1FEEuni1FEFuni1FF2uni1FF3uni1FF4uni1FF6uni1FF7uni1FF8uni1FF9uni1FFAuni1FFBuni1FFCuni1FFDuni1FFE uni1F88.alt uni1F89.alt uni1F8A.alt uni1F8B.alt uni1F8C.alt uni1F8D.alt uni1F8E.alt uni1F8F.alt uni1F98.alt uni1F99.alt uni1F9A.alt uni1F9B.alt uni1F9C.alt uni1F9D.alt uni1F9E.alt uni1F9F.alt uni1FA8.alt uni1FA9.alt uni1FAA.alt uni1FAB.alt uni1FAC.alt uni1FAD.alt uni1FAE.alt uni1FAF.alt uni1FBC.alt uni1FCC.alt uni1FFC.altuni20B9uniE0FFuniF000uniFFFDuniEFFD SF040000.001 SF020000.001 SF010000.001 SF110000.001 SF100000.001 SF090000.001 SF060000.001 SF070000.001 SF080000.001 SF050000.001 SF540000.001 SF530000.001 SF030000.001SF190000SF360000SF450000SF280000SF500000SF470000SF220000SF510000SF240000SF440000SF230000SF420000SF400000SF260000SF380000SF410000SF250000SF390000SF430000SF200000SF370000SF460000SF270000SF490000SF480000SF210000SF520000blockltshadeshadedkshadeSF530000SF540000SF040000SF020000SF010000SF110000SF100000SF090000SF060000SF070000SF080000SF050000SF030000 tcyrlgreklatn°BGR .MKD HSRB b 0>KVa   *1?LWb  !+2@MXc ",3ANYd #4<BIOZe"AZE @CRT ZMOL tROM ŠTRK   $5;=CJP[f %-6DQ\g &.7ER]h'8FS^i (9GT_j )/:HU`klafrcŠafrc”afrcžafrc¨afrc²afrcΌafrcΖafrcΠafrcΪafrcδafrcξcaseψcasecasecasecasecase case(case0case8dnom@dnomFdnomLdnomRdnomXdnom^dnomddnomjdnompdnomvdnom|frac‚fracŠfrac’fracšfrac’fracͺfrac²fracΊfracΒfracΚfracloclΪloclΰloclζloclμloclςloclψnumrώnumrnumr numrnumrnumrnumr"numr(numr.numr4numr:ordn@saltFsaltPsinfZsinf`sinffsinflsinfrsinfxsinf~sinf„sinfŠsinfsinf–ss01œss01¦ss02°ss02Ίss02Δss02Ξss02Ψss02βss02μss02φss02ss02 ss02subssubs$subs*subs0subs6subsFNV^‡n˜n‡nt˜nu‡n~˜n‡nΆ˜n·‡nΐ˜nΑ $,™n™nu™n™n·™nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒƒn‰nn•nƒnމnqns•nuƒny‰n{n}•nƒn±‰n³n΅•n·ƒn»‰n½nΏ•nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒ™nŠnn…n™npŠnqns…nt™nzŠn{n}…n~™n²Šn³n΅…nΆ™nΌŠn½nΏ…nΐ(RZbjrz‚Š’š’ͺ²ΊΒΚΪβκςϊ "*2:BJRZbjrz‚Š˜n‚n—nˆnŒnŽn„n”n˜n‚nŽ—npˆnqŒnrŽns„nt”nu˜nx‚ny—nzˆn{Œn|Žn}„n~”n˜n°‚n±—n²ˆn³Œn΄Žn΅„nΆ”n·˜nΊ‚n»—nΌˆn½ŒnΎŽnΏ„nΐ”nΑ (08@HPX`hpx€ˆ‹n‘n–n‹nq‘ns–nu‹n{‘n}–n‹n³‘n΅–n·‹n½‘nΏ–nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒn’n†n—nnr’ns†nt—nun|’n}†n~—nn΄’n΅†nΆ—n·nΎ’nΏ†nΐ—nΑ $,“n“ns“n}“n΅“nΏ &.6>FNV^‡n˜n‡nt˜nu‡n~˜n‡nΆ˜n·‡nΐ˜nΑ $,™n™nu™n™n·™nΑ(RZbjrz‚Š’š’ͺ²ΊΒΚΪβκςϊ "*2:BJRZbjrz‚Š˜n‚n—nˆnŒnŽn„n”n˜n‚nŽ—npˆnqŒnrŽns„nt”nu˜nx‚ny—nzˆn{Œn|Žn}„n~”n˜n°‚n±—n²ˆn³Œn΄Žn΅„nΆ”n·˜nΊ‚n»—nΌˆn½ŒnΎŽnΏ„nΐ”nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒƒn‰nn•nƒnމnqns•nuƒny‰n{n}•nƒn±‰n³n΅•n·ƒn»‰n½nΏ•nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒ™nŠnn…n™npŠnqns…nt™nzŠn{n}…n~™n²Šn³n΅…nΆ™nΌŠn½nΏ…nΐ (08@HPX`hpx€ˆ‹n‘n–n‹nq‘ns–nu‹n{‘n}–n‹n³‘n΅–n·‹n½‘nΏ–nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒn’n†n—nnr’ns†nt—nun|’n}†n~—nn΄’n΅†nΆ—n·nΎ’nΏ†nΐ—nΑ $,“n“ns“n}“n΅“nΏ &.6>FNV^‡n˜n‡nt˜nu‡n~˜n‡nΆ˜n·‡nΐ˜nΑ $,™n™nu™n™n·™nΑ(RZbjrz‚Š’š’ͺ²ΊΒΚΪβκςϊ "*2:BJRZbjrz‚Š˜n‚n—nˆnŒnŽn„n”n˜n‚nŽ—npˆnqŒnrŽns„nt”nu˜nx‚ny—nzˆn{Œn|Žn}„n~”n˜n°‚n±—n²ˆn³Œn΄Žn΅„nΆ”n·˜nΊ‚n»—nΌˆn½ŒnΎŽnΏ„nΐ”nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒƒn‰nn•nƒnމnqns•nuƒny‰n{n}•nƒn±‰n³n΅•n·ƒn»‰n½nΏ•nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒ™nŠnn…n™npŠnqns…nt™nzŠn{n}…n~™n²Šn³n΅…nΆ™nΌŠn½nΏ…nΐ (08@HPX`hpx€ˆ‹n‘n–n‹nq‘ns–nu‹n{‘n}–n‹n³‘n΅–n·‹n½‘nΏ–nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒn’n†n—nnr’ns†nt—nun|’n}†n~—nn΄’n΅†nΆ—n·nΎ’nΏ†nΐ—nΑ $,“n“ns“n}“n΅“nΏ &.6>FNV^‡n˜n‡nt˜nu‡n~˜n‡nΆ˜n·‡nΐ˜nΑ $,™n™nu™n™n·™nΑ(RZbjrz‚Š’š’ͺ²ΊΒΚΪβκςϊ "*2:BJRZbjrz‚Š˜n‚n—nˆnŒnŽn„n”n˜n‚nŽ—npˆnqŒnrŽns„nt”nu˜nx‚ny—nzˆn{Œn|Žn}„n~”n˜n°‚n±—n²ˆn³Œn΄Žn΅„nΆ”n·˜nΊ‚n»—nΌˆn½ŒnΎŽnΏ„nΐ”nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒƒn‰nn•nƒnމnqns•nuƒny‰n{n}•nƒn±‰n³n΅•n·ƒn»‰n½nΏ•nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒ™nŠnn…n™npŠnqns…nt™nzŠn{n}…n~™n²Šn³n΅…nΆ™nΌŠn½nΏ…nΐ (08@HPX`hpx€ˆ‹n‘n–n‹nq‘ns–nu‹n{‘n}–n‹n³‘n΅–n·‹n½‘nΏ–nΑ*2:BJRZbjrz‚Š’š’ͺ²ΊΒn’n†n—nnr’ns†nt—nun|’n}†n~—nn΄’n΅†nΆ—n·nΎ’nΏ†nΐ—nΑ $,“n“ns“n}“n΅“nΏ &.6>FNV^‡n˜n‡nt˜nu‡n~˜n‡nΆ˜n·‡nΐ˜nΑ $,™n™nu™n™n·™nΑ˜nn (o”Žpqrstuo”Žpqrstuo”Žpqrstuo”Žpqrstun~‚ΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨ6-€$%&'()*+,-./0123456789:;<=km›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±³΄΅Ά·ΈΉzΫέίαγεηιλνορσυχωϋύ   "$&(*,.02468:<>@BDFHJLNPRTVY[fhjl~ ΒΓΔΕΖΗΘΙΪv ΚΛΜΝΞΟΠΡΫn ΣΤΥΦΧΨΩάπ xywvz{|}~Lδv ΑDRŽ ”” ou ΑŽ ”” o ΈΑŽ ”” o · Ž”” pt w~―ΆΉΐ nnvŽ””ou #>?@^`lrstx|†–šX]DEFGHIJKLMNOPQRSTUVWXYZ[\]wy»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪάήΰβδζθκμξπςτφψϊόώ  !#%')+-/13579;=?ACEGIKMOQSUWZ\gikmSZ††cj••szΏΏ0‚ *†H†χ  ‚0‚ϋ1 0 +0a +‚7 S0Q0, +‚7’€<<<Obsolete>>>0!0 +Š;±ͺ’h³₯,w5¦BΫυR"¨ ‚‚0‚V0‚>  0  *†H†χ 0Ο1 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1:08U 1http://certificates.starfieldtech.com/repository/1604U-Starfield Services Root Certificate Authority0 110503070000Z 160503070000Z0Α1 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1301U *http://certs.starfieldtech.com/repository/1/0-U&Starfield Services Timestamp Authority0‚"0  *†H†χ ‚0‚ ‚ς³‘₯ΊΧΦI φ}ΦΒ-Ξϋι`Zcœ΄0 ›ΤxκC;ν#(2&_2%θ•… >O€΄ °œ’^>Qϊ“.»²ΚΖ;V ‹A)„΄+5yϋ°iρˆ]r­ΐβΛE%―Δ΄ΒΦ¬e΄aβί- v—cLy<» tfυYPβ ›_Y$ϊ9™Σ‰pUH¦™¦ ΰ{¦( εŠΛ]’­P(€ Μ*/ΣΏρΉ«J^=—zu‘™_^νΜ§@ցU]θE'ψΒ€υ·μt°ΞΒ?>3χοΑ ΥHΙe27m UΙUOΝ"ΏŸρ”/+« ¨0tC,ηŠK "«@xQΛ£‚F0‚B0 U00Uΐ0U% 0 +0UΚ#£ ΄±krŸΊošƒ> ΙΨ±Ψ§0U#0€΄ΖCΜ›u]/ΔKς‹˜ιρQ0:+.0,0*+0†http://ocsp.starfieldtech.com/09U2000. , *†(http://crl.starfieldtech.com/sfsroot.crl0SU L0J0H `†H†ύn0907++https://certs.starfieldtech.com/repository/0  *†H†χ ‚S~t¬§z£+κxY<ΒωΒχ%_B7[<a¦4jhΎΪ"€!ZH…UMΞ«¦Λ4ΖΐΖ­ΊΆ€Ύ yΐ§δΪ§ηΟWΘ9ωοί00Π *―\%S-Lχυm΄{rR£·ΉκUƒ>:EK”–dΦθ`γ―5T%L[ψΦ7Ω«Έ6ΰJ‰ϋ ioΜWακά"²΅ΕAΧcιžd¬²ΓΗΎΪwΰX6™†f8½dφΖR^/`ΠΚΛΓΔro6…D"@œΕAT3#l{£ŽΩX…ρͺΈ4~»΅hTx R“M²KςΑˆG•ΝlS¨Lπ>Œ3£ΔŠΟΞs’I"ν»Θœ|c«0‚0‚θ 0  *†H†χ 0c1 0 UUS1!0U The Go Daddy Group, Inc.110/U (Go Daddy Class 2 Certification Authority0 040629170620Z 340629170620Z0c1 0 UUS1!0U The Go Daddy Group, Inc.110/U (Go Daddy Class 2 Certification Authority0‚ 0  *†H†χ ‚ 0‚‚ޝΧκWI‘[λΧ_H†κΎέδοgτeh³Wq ^w»ν›Iιp€=VcoΪςΜΠ?T"TΨ²Τΐu=KΗwΓ>x«΅ k/j+±Εˆ~Δ»°ΑΨE'oͺ7Xχ‡&ΧΨ-φ©·r6N¦?e˜’Ϋ*n]’ώˆΰ ήεαλΛ:Υβ’-؎―_= Ά\₯e8E™£``tΕA₯rbbΕo_BΎQe¨#jόx©M€Γϊ«Zό‘@€Κώ²Θο^s ξw½šφy˜Ό±g’ έ XΖD{ >b(_ΊASXΟ~8tΕψ΅i„tκ—―£ΐ0½0UΔ°‘ΤLq³aΛ=‘ώέ¨jΤγ0U#…0‚€Δ°‘ΤLq³aΛ=‘ώέ¨jΤγ‘g€e0c1 0 UUS1!0U The Go Daddy Group, Inc.110/U (Go Daddy Class 2 Certification Authority‚0 U00  *†H†χ ‚2Kσ²Κ>‘όΖ‘ŒŽw 3\χ¦= ω‡€niδ–04‘cr8ξΜ£”(€1φzΔTΧφε1X’ΜΞbΫ”Es΅ΏEΙ$΅Υ‚­#yiΈΆMΞΟLΚ3#θˆͺ‹AnΙ ε‰žΝ;Ϊpχ~™& T%«ns…ζ›! l‚¨ψΒ ϊl–ο‡ Δa‹­ξƒ+•ψŽ’„r9λ κƒνƒΝ—nΌλN&Άs+δΣφLώ&qβatJW‡uH.ΟQi a•ΥΡ@²LξΔ¬C¦₯ž Υ•bš ψ‚Ε2 δ+ŸEζ Ÿ(œ±Ή*ZW­7―Ϋ½Ÿ0‚ή0‚Ζ 0  *†H†χ 0c1 0 UUS1!0U The Go Daddy Group, Inc.110/U (Go Daddy Class 2 Certification Authority0 061116015437Z 261116015437Z0Κ1 0 UUS10UArizona10U Scottsdale10U GoDaddy.com, Inc.1301U *http://certificates.godaddy.com/repository100.U'Go Daddy Secure Certification Authority10U079692870‚"0  *†H†χ ‚0‚ ‚Δ-ΥŒœ&Lμ25λ_ΈYZ¦aY;pc«γά=Η*ΈΙ3Σyδ:ν<0#„޳0Ά²‡Γ=•Tžί™έ %!ήe)~5¨©Tλφχ29Τ&U•­οϋώX†ΧžτŒ* ½BΞ§?φξ€ςͺοR‘ifΪΎ­]Ϊ,fκk»εQJ/HǘuΨΉ)Θξψfm œ³σόx|’ψ£ς΅ΓσΉz‘Α§ζ%.œ¨νenjφDSp0•Γœ+X+=tJςΎQ°Ώ‡ΠL'Xk΅5ŝ―1ψ ξ­6‰˜Ο:―%‡ΐIκ§ύgχEŽ—Μ9β6…΅~7ύφqšt0ώ”£?„ O£‚20‚.0Uύ¬a2“lEΦβξ…_šΊηv™hΜη0U#0€Δ°‘ΤLq³aΛ=‘ώέ¨jΤγ0U003+'0%0#+0†http://ocsp.godaddy.com0FU?0=0; 9 7†5http://certificates.godaddy.com/repository/gdroot.crl0KU D0B0@U 0806+*http://certificates.godaddy.com/repository0U0  *†H†χ ‚†ΐμ½ω‘Άgξf ’:PŽr¬Jt•SΛ7ΛDIοk3Ω–π”V₯0<…2!{ΙΗ ¨$€ήFΣ%#gΒΦo]{z̟ΕX*ΑĞ!¨Zσ¬€FσžδcΛ/€))Ωr,)ί7'ΌOξhΣ!ΐ³δυ νͺS΄ΎπΜY Φ;–•$IίΞμύ§H‘E:6oΪE³E’AΙΤΧDN>ΉtvΥ’U,Ζ‡£΅™¬„‡uόΏLΜnΔί=·qτθρQ@"(IΰK‡¨4Μ’έZΡ†6d5oownλς…P˜^«S­‘#cœΝΉ²c:ατh5•Sξ0‚>0‚&  οτΏi{0  *†H†χ 0Κ1 0 UUS10UArizona10U Scottsdale10U GoDaddy.com, Inc.1301U *http://certificates.godaddy.com/repository100.U'Go Daddy Secure Certification Authority10U079692870 090924134423Z 120924134423Z0k1 0 UGB10 ULondon10 ULondon10U Dalton Maag Limited10UDalton Maag Limited0‚"0  *†H†χ ‚0‚ ‚’_ζΨΫ‘’σ~Ε4ηrΨϋ•Ομ€κ’Ϋφ¬S5ρ”œ£Ž™Fΰ+‘Ά¦  Ί+Fnb执 AυζΐκkUr]ŽΟάX3‰εuάΓΜ-`>Φι©ΖT>”ΌμŠ‘6zνUύΨ=k'F _ΤΫΑ_’χˆδˆ~ϊγ‚ΰ/BbQF»Ζ0q{²ΜŒ3vνΰ΅™­Γ γˆwx1http://certificates.godaddy.com/repository/gd_intermediate.crt0U#0€ύ¬a2“lEΦβξ…_šΊηv™hΜη0Uhf0gU‘³‘ι7Ζu‰3γ…Χ0  *†H†χ ‚½V> ΄}ϊνΣώEΆίίHψ£ŒΥTΤ’DΑqi£Γ0€Ϊ7ΚGhΩ³% 6 ι;βΫQtώ^Ιή;$±ž9–Γ LRΚηBfZuhI:-#k^ΔCρž±/ ₯œ>=nZ°•t?.Kα0msÞo―γGϊέ$`d§\cέ©·P4eΗ(IώZzκΐFΆš*فe²‘Κ Φ{ˆπκ>ιU0‡Ο―‘¨#kE™ά‘7 ΏΤέf_Uτργν`4•>—’ΒΚja@0‘Δ₯[Π`mO4~ 1Sειx–ΠƒΔͺ½εbͺ2"#N.|ΆŸί\#–1‚ώ0‚ϊ0Υ0Κ1 0 UUS10UArizona10U Scottsdale10U GoDaddy.com, Inc.1301U *http://certificates.godaddy.com/repository100.U'Go Daddy Secure Certification Authority10U07969287 οτΏi{0 + †0 +‚7 100 +‚7(10 *†H†χ  1  +‚70 +‚7 10  +‚70# *†H†χ  1VψΠΛ˜©šΒae• Ζ ½0  *†H†χ ‚0L#ŒΚKό-θ[Uς{» E-&οNΔ™0suχέ›΄739„$ߊZ›FΠH:e‚°“a_wγΚμΛHΐW7‰UWξθ'9$υώ=ϋ/x`Β¨o$χυ@NCΣθ?{HρΘ3‹Χ―+Ϊ]Σμ2Ωά&έ†~(2Ργv*Ψ™`ώ[υ¨„†š.$J»Œυ”ίnξΫ=ιϋ`λΈraβjδ;Ω]@=»ΛMΦδ>š‰Qσ .ωœξ[›dCQNφœ½F ηί 2€Ά&­ΛI#•ΜˆΠl€Σ‡ŸΕΗ”Q~B5xT^wx.ύΐ Ή€xΥ‚Ο΄†ŠefΆΠ‘‚t0‚p *†H†χ  1‚a0‚]0Φ0Ο1 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1:08U 1http://certificates.starfieldtech.com/repository/1604U-Starfield Services Root Certificate Authority 0  *†H†χ  ]0 *†H†χ  1  *†H†χ 0 *†H†χ  1 110922154442Z0# *†H†χ  1?σ}!Q€ knAξ4 FZNγε0  *†H†χ ‚ΔϋI3x¨­ Θ›|¦ϋΰΓί@ΌGΰd)~8UœΊ†žκ+‰„dŒw'ρέ,qΚς.P½₯β?ΨώPbωDqsœeψf<{ σžΠ\θAœ―Ηi„žLΆ­FwΑΤ jΖ8θ§ΜȞj‘U!ζ«·ΐpθkJdβΪS;|ΒδpWŸάΖ~Χfs/mψn ΓRiAhΗ)hŽΜOζ.xI‹}ί\`ΩΚ•ύ²Pξΐš‘a'‡ψVΆ°Ιε1²=Ο½FΞ~Χg$θδAφ+KξΕqθDΏτΎφYΎuqXςν–qlnΓ Ξαaͺ—©ρα˜cfΖ¬ϊφi" 7ζ `ΈξΌεNΛ³Zrocq-9.2.0/doc/tools/rocqrst/notations/__init__.py000066400000000000000000000000001516144147600222160ustar00rootroot00000000000000rocq-9.2.0/doc/tools/rocqrst/notations/fontsupport.py000077500000000000000000000060001516144147600230730ustar00rootroot00000000000000#!/usr/bin/env python2 # -*- coding: utf-8 -*- ########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## = 191: fnt.removeGlyph(g) return fnt def center_glyphs(src_font_path, dst_font_path, dst_name): fnt = trim_font(fontforge.open(src_font_path)) size = max(g.width for g in fnt.glyphs()) fnt.ascent, fnt.descent = size, 0 for glyph in fnt.glyphs(): scale_single_glyph(glyph, size, size) fnt.sfnt_names = [] fnt.fontname = fnt.familyname = fnt.fullname = dst_name fnt.generate(dst_font_path) if __name__ == '__main__': from os.path import dirname, join, abspath curdir = dirname(abspath(__file__)) ubuntumono_path = join(curdir, "UbuntuMono-B.ttf") ubuntumono_mod_path = join(curdir, "RocqNotations.ttf") center_glyphs(ubuntumono_path, ubuntumono_mod_path, "RocqNotations") rocq-9.2.0/doc/tools/rocqrst/notations/html.py000066400000000000000000000063211516144147600214370ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## str: """Configure a rocq top instance (but don't start it yet). :param rocqbin: The path to rocq; uses $COQBIN by default, falling back to "rocq" :param color: When True, tell "rocq top" to produce ANSI color codes (see the ansicolors module) :param args: Additional arguments to "rocq top". """ self.rocqbin = rocqbin or os.path.join(os.getenv("COQBIN", ""), "rocq") if not pexpect.utils.which(self.rocqbin): raise ValueError("'{}: not found".format(rocqbin)) self.args = ["top"] + (args or []) + ["-q"] + ["-color", "on"] * color self.rocqtop = None self.debugfile = None def __enter__(self): if self.rocqtop: raise ValueError("This module isn't re-entrant") self.rocqtop = pexpect.spawn(self.rocqbin, args=self.args, echo=False, encoding="utf-8") # Disable delays (http://pexpect.readthedocs.io/en/stable/commonissues.html?highlight=delaybeforesend) self.rocqtop.delaybeforesend = 0 if os.getenv ("ROCQ_DEBUG_REFMAN"): self.debugfile = tempfile.NamedTemporaryFile(mode="w+", prefix="rocqdomain", suffix=".v", delete=False, dir="/tmp/") self.next_prompt() return self def __exit__(self, type, value, traceback): if self.debugfile: self.debugfile.close() self.debugfile = None self.rocqtop.kill(9) def next_prompt(self): """Wait for the next rocq top prompt, and return the output preceding it.""" self.rocqtop.expect(RocqTop.ROCQTOP_PROMPT, timeout = 10) return self.rocqtop.before def sendone(self, sentence): """Send a single sentence to rocq top. :sentence: One Rocq sentence (otherwise, rocq top will produce multiple prompts and we'll get confused) """ # Suppress newlines, but not spaces: they are significant in notations sentence = re.sub(r"[\r\n]+", " ", sentence).strip() try: if self.debugfile: self.debugfile.write(sentence+"\n") self.rocqtop.sendline(sentence) output = self.next_prompt() except Exception as err: raise RocqTopError(err, sentence, self.rocqtop.before) return output def send_initial_options(self): """Options to send when starting the toplevel and after a Reset Initial.""" self.sendone('Set Rocqtop Exit On Error.') self.sendone('Set Warnings "+default".') def sendmany(*sentences): """A small demo: send each sentence in sentences and print the output""" with RocqTop() as rocqtop: for sentence in sentences: print("=====================================") print(sentence) print("-------------------------------------") response = rocqtop.sendone(sentence) print(response) def main(): """Run a simple performance test and demo `sendmany`""" with RocqTop() as rocqtop: for _ in range(200): print(repr(rocqtop.sendone("Check nat."))) sendmany("Goal False -> True.", "Proof.", "intros H.", "Check H.", "Chchc.", "apply I.", "Qed.") if __name__ == '__main__': main() rocq-9.2.0/doc/tools/rocqrst/rocqdoc/000077500000000000000000000000001516144147600175335ustar00rootroot00000000000000rocq-9.2.0/doc/tools/rocqrst/rocqdoc/__init__.py000066400000000000000000000012671516144147600216520ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## ", "<-", "<->", "=>", "<=", ">=", "<>", "~", "/\\", "\\/", "|-", "*", "forall", "exists"] ROCQDOC_HEADER = "".join("(** remove printing {} *)".format(s) for s in ROCQDOC_SYMBOLS) def rocqdoc(rocq_code, rocqbin=None): """Get the output of rocq doc on rocq_code.""" rocqbin = rocqbin or os.path.join(os.getenv("COQBIN", ""), "rocq") if not pexpect.utils.which(rocqbin): raise ValueError("'{}: not found".format(rocqbin)) args = [rocqbin, "doc"] fd, filename = mkstemp(prefix="rocqdoc_", suffix=".v") if platform.system().startswith("CYGWIN"): # rocqdoc currently doesn't accept cygwin style paths in the form "/cygdrive/c/..." filename = check_output(["cygpath", "-w", filename]).decode("utf-8").strip() try: os.write(fd, ROCQDOC_HEADER.encode("utf-8")) os.write(fd, rocq_code.encode("utf-8")) os.close(fd) return check_output(args + ROCQDOC_OPTIONS + [filename], timeout = 10).decode("utf-8") finally: os.remove(filename) def first_string_node(node): """Return the first string node, or None if does not exist""" while node.children: node = next(node.children) if isinstance(node, NavigableString): return node def lex(source): """Convert source into a stream of (css_classes, token_string).""" rocqdoc_output = rocqdoc(source) soup = BeautifulSoup(rocqdoc_output, "html.parser") root = soup.find(class_='code') # strip the leading '\n' first = first_string_node(root) if first and first.string[0] == '\n': first.string.replace_with(first.string[1:]) for elem in root.children: if isinstance(elem, NavigableString): yield [], elem elif elem.name == "span": if elem.string: cls = "rocqdoc-{}".format(elem.get("title", "comment")) yield [cls], elem.string else: # handle multi-line comments children = list(elem.children) mlc = children[0].startswith("(*") and children[-1].endswith ("*)") for elem2 in children: if isinstance(elem2, NavigableString): cls = ["rocqdoc-comment"] if mlc else [] yield cls, elem2 elif elem2.name == 'br': pass elif elem.name == 'br': pass else: raise ValueError(elem) def main(): """Lex stdin (for testing purposes)""" import sys for classes, text in lex(sys.stdin.read()): print(repr(text) + "\t" ' '.join(classes)) if __name__ == '__main__': main() rocq-9.2.0/doc/tools/rocqrst/rocqdomain.py000066400000000000000000001465761516144147600206320ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## = (4, 5): from sphinx.writers.latex import CR def visit_desc_signature(self, node): hyper = '' if node.parent['objtype'] != 'describe' and node['ids']: for id in node['ids']: hyper += self.hypertarget(id) self.body.append(hyper) if not self.in_desc_signature: self.in_desc_signature = True self.body.append(CR + r'\pysigstartsignatures') if not node.get('is_multiline'): self._visit_signature_line(node) else: self.body.append(CR + r'\pysigstartmultiline') else: def visit_desc_signature(self, node): hyper = '' if node.parent['objtype'] != 'describe' and node['ids']: for id in node['ids']: hyper += self.hypertarget(id) self.body.append(hyper) if not node.get('is_multiline'): self._visit_signature_line(node) else: self.body.append('%\n\\pysigstartmultiline\n') LaTeXTranslator.visit_desc_signature = visit_desc_signature PARSE_ERROR = """{}:{} Parse error in notation! Offending notation: {} Error message: {}""" def notation_to_sphinx(notation, source, line, rawtext=None): """Parse notation and wrap it in an inline node""" try: node = nodes.inline(rawtext or notation, '', *sphinxify(notation), classes=['notation']) node.source, node.line = source, line return node except ParseError as e: raise ExtensionError(PARSE_ERROR.format(os.path.basename(source), line, notation, e.msg)) from e def notation_to_string(notation): """Parse notation and format it as a string with ellipses.""" try: return stringify_with_ellipses(notation) except ParseError as e: # FIXME source and line aren't defined below β€” see cc93f419e0 raise ExtensionError(PARSE_ERROR.format(os.path.basename(source), line, notation, e.msg)) from e def highlight_using_rocqdoc(sentence): """Lex sentence using rocqdoc, and yield inline nodes for each token""" tokens = rocqdoc.lex(utils.unescape(sentence, 1)) for classes, value in tokens: yield nodes.inline(value, value, classes=classes) def make_target(objtype, targetid): """Create a target to an object of type objtype and id targetid""" return "rocq:{}.{}".format(objtype, targetid) def make_math_node(latex, docname, nowrap): node = nodes.math_block(latex, latex) node['label'] = None # Otherwise equations are numbered node['nowrap'] = nowrap node['docname'] = docname node['number'] = None return node # To support any character in tacn, ... names. # see https://github.com/rocq-prover/rocq/pull/13564 def make_id(tag): return tag.replace(" ", "-") class RocqObject(ObjectDescription): """A generic Rocq object for Sphinx; all Rocq objects are subclasses of this. The fields and methods to override are listed at the top of this class' implementation. Each object supports the :name: option, which gives an explicit name to link to. See the comments and docstrings in RocqObject for more information. """ # The semantic domain in which this object lives (eg. β€œtac”, β€œcmd”, β€œchm”…). # It matches exactly one of the roles used for cross-referencing. subdomain = None # type: str # The suffix to use in indices for objects of this type (eg. β€œ(tac)”) index_suffix = None # type: str # The annotation to add to headers of objects of this type # (eg. β€œCommand”, β€œTheorem”) annotation = None # type: str def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._sig_names = None def _name_from_signature(self, signature): # pylint: disable=no-self-use, unused-argument """Convert a signature into a name to link to. β€˜Signature’ is Sphinx parlance for an object's header (think β€œtype signature”); for example, the signature of the simplest form of the ``exact`` tactic is ``exact @id``. Generates a name for the directive. Override this method to return None to avoid generating a name automatically. This is a convenient way to automatically generate names (link targets) without having to write explicit names everywhere. """ m = re.match(r"[a-zA-Z0-9_ ]+", signature) if m: return m.group(0).strip() def _render_signature(self, signature, signode): """Render a signature, placing resulting nodes into signode.""" raise NotImplementedError(self) option_spec = { # Explicit object naming 'name': directives.unchanged, # Silence warnings produced by report_undocumented_rocq_objects 'undocumented': directives.flag, # noindex omits this object from its index 'noindex': directives.flag } def subdomain_data(self): if self.subdomain is None: raise ValueError() return self.env.domaindata['rocq']['objects'][self.subdomain] def _render_annotation(self, signode): if self.annotation: annot_node = nodes.inline(self.annotation, self.annotation, classes=['sigannot']) signode += addnodes.desc_annotation(self.annotation, '', annot_node) signode += nodes.Text(' ') def handle_signature(self, signature, signode): """Prefix signature with the proper annotation, then render it using ``_render_signature`` (for example, add β€œCommand” in front of commands). :returns: the names given to the resulting node. """ self._render_annotation(signode) self._render_signature(signature, signode) names = self._sig_names.get(signature) if names is None: name = self._name_from_signature(signature) # pylint: disable=assignment-from-none # remove trailing β€˜.’ found in commands, but not β€˜...’ (ellipsis) if name is not None and name.endswith(".") and not name.endswith("..."): name = name[:-1] names = [name] if name else None return names def _warn_if_duplicate_name(self, objects, name, signode): """Check that two objects in the same domain don't have the same name.""" if name in objects: MSG = 'Duplicate name {} (other is in {}) attached to {}' msg = MSG.format(name, self.env.doc2path(objects[name][0]), signode) self.state_machine.reporter.warning(msg, line=self.lineno) def _record_name(self, name, target_id, signode): """Record a `name` in the current subdomain, mapping it to `target_id`. Warns if another object of the same name already exists; `signode` is used in the warning. """ names_in_subdomain = self.subdomain_data() self._warn_if_duplicate_name(names_in_subdomain, name, signode) names_in_subdomain[name] = (self.env.docname, self.objtype, target_id) def _target_id(self, name): return make_target(self.objtype, make_id(name)) def _add_target(self, signode, name): """Register a link target β€˜name’, pointing to signode.""" targetid = self._target_id(name) if targetid not in self.state.document.ids: signode['ids'].append(targetid) signode['names'].append(name) signode['first'] = (not self.names) self._record_name(name, targetid, signode) else: # We don't warn for duplicates in the SSReflect chapter, because # it's the style of this chapter to repeat all the defined # objects at the end. if self.env.docname != 'proof-engine/ssreflect-proof-language': self._warn_if_duplicate_name(self.subdomain_data(), name, signode) return targetid def _add_index_entry(self, name, target): """Add `name` (pointing to `target`) to the main index.""" assert isinstance(name, str) # remove trailing . , found in commands, but not ... (ellipsis) trim = name.endswith(".") and not name.endswith("...") index_text = name[:-1] if trim else name if self.index_suffix: index_text += " " + self.index_suffix self.indexnode['entries'].append(('single', index_text, target, '', None)) def add_target_and_index(self, names, _, signode): """Attach a link target to `signode` and index entries for `names`. This is only called (from ``ObjectDescription.run``) if ``:noindex:`` isn't specified.""" if names: for name in names: if isinstance(name, str) and name.startswith('_'): continue target = self._add_target(signode, name) self._add_index_entry(name, target) self.state.document.note_explicit_target(signode) def _prepare_names(self): """Construct ``self._sig_names``, a map from signatures to names. A node may have either one signature with no name, multiple signatures with one name per signatures, or one signature with multiple names. """ sigs = self.get_signatures() names = self.options.get("name") if names is None: self._sig_names = {} else: names = [n.strip() for n in names.split(";")] if len(names) != len(sigs): if len(sigs) != 1: #Multiple names for one signature ERR = ("Expected {} semicolon-separated names, got {}. " + "Please provide one name per signature line.") raise self.error(ERR.format(len(names), len(sigs))) self._sig_names = { sigs[0]: names } else: self._sig_names = { sig: [name] for (sig, name) in zip(sigs, names) } def run(self): self._prepare_names() return super().run() class DocumentableObject(RocqObject): def _warn_if_undocumented(self): document = self.state.document config = document.settings.env.config report = config.report_undocumented_rocq_objects if report and not self.content and "undocumented" not in self.options: # This is annoyingly convoluted, but we don't want to raise warnings # or interrupt the generation of the current node. For more details # see https://github.com/sphinx-doc/sphinx/issues/4976. msg = 'No contents in directive {}'.format(self.name) node = document.reporter.info(msg, line=self.lineno) getLogger(__name__).info(node.astext()) if report == "warning": raise self.warning(msg) def run(self): self._warn_if_undocumented() return super().run() class PlainObject(DocumentableObject): """A base class for objects whose signatures should be rendered literally.""" def _render_signature(self, signature, signode): signode += addnodes.desc_name(signature, signature) class NotationObject(DocumentableObject): """A base class for objects whose signatures should be rendered as nested boxes. Objects that inherit from this class can use the notation grammar (β€œ{+ …}”, β€œ@…”, etc.) in their signature. """ def _render_signature(self, signature, signode): position = self.state_machine.get_source_and_line(self.lineno) tacn_node = notation_to_sphinx(signature, *position) signode += addnodes.desc_name(signature, '', tacn_node) class GallinaObject(PlainObject): """ A Theorem object. See the documentation of the ".. thm::" object in doc/sphinx/README.rst. """ subdomain = "thm" index_suffix = "(theorem)" annotation = "Theorem" class VernacObject(NotationObject): """A Rocq command object. See the documentation of the ".. cmd::" object in doc/sphinx/README.rst. """ subdomain = "cmd" index_suffix = "(command)" annotation = "Command" def _name_from_signature(self, signature): m = re.match(r"[a-zA-Z0-9_ ]+", signature) return m.group(0).strip() if m else None class VernacVariantObject(VernacObject): """An object for a variant of a Rocq command. See the documentation of the ".. cmdv::" object in doc/sphinx/README.rst. """ index_suffix = "(command variant)" annotation = "Variant" def _name_from_signature(self, signature): return None class TacticObject(NotationObject): """An object for a tactic, or a tactic notation. See the documentation of the ".. tacn::" object in doc/sphinx/README.rst. """ subdomain = "tacn" index_suffix = "(tactic)" annotation = "Tactic" class AttributeObject(NotationObject): """An attribute object. See the documentation of the ".. attr::" object in doc/sphinx/README.rst. """ subdomain = "attr" index_suffix = "(attribute)" annotation = "Attribute" def _name_from_signature(self, signature): return notation_to_string(signature) class TacticVariantObject(TacticObject): """An object for a variant of a tactic. See the documentation of the ".. tacv::" object in doc/sphinx/README.rst. """ index_suffix = "(tactic variant)" annotation = "Variant" def _name_from_signature(self, signature): return None class OptionObject(NotationObject): """An object for a Rocq option (a setting with non-boolean value, e.g. a string or numeric value). See the documentation of the ".. opt::" object in doc/sphinx/README.rst. """ subdomain = "opt" index_suffix = "(option)" annotation = "Option" class FlagObject(NotationObject): """An object for a Rocq flag (i.e. a boolean setting). See the documentation of the ".. flag::" object in doc/sphinx/README.rst. """ subdomain = "flag" index_suffix = "(flag)" annotation = "Flag" class TableObject(NotationObject): """An object for a Rocq table, i.e. a setting that is a set of values. See the documentation of the ".. table::" object in doc/sphinx/README.rst. """ subdomain = "table" index_suffix = "(table)" annotation = "Table" class ProductionObject(RocqObject): """A grammar production. See the documentation of the ".. prodn::" object in doc/sphinx/README.rst. """ subdomain = "prodn" #annotation = "Grammar production" # handle_signature is called for each line of input in the prodn:: # 'signatures' accumulates them in order to combine the lines into a single table: signatures = None # FIXME this should be in init, shouldn't it? def _render_signature(self, signature, signode): raise NotImplementedError(self) SIG_ERROR = ("{}: Invalid syntax in ``.. prodn::`` directive" + "\nExpected ``name ::= ...`` or ``name += ...``" + " (e.g. ``pattern += constr:(@ident)``)\n" + " in `{}`") def handle_signature(self, signature, signode): parts = signature.split(maxsplit=1) if parts[0].strip() == "|" and len(parts) == 2: lhs = "" op = "|" rhs = parts[1].strip() else: parts = signature.split(maxsplit=2) if len(parts) != 3: loc = os.path.basename(get_node_location(signode)) raise ExtensionError(ProductionObject.SIG_ERROR.format(loc, signature)) lhs, op, rhs = (part.strip() for part in parts) if op not in ["::=", "+="]: loc = os.path.basename(get_node_location(signode)) raise ExtensionError(ProductionObject.SIG_ERROR.format(loc, signature)) parts = rhs.split(" ", maxsplit=1) rhs = parts[0].strip() tag = parts[1].strip() if len(parts) == 2 else "" self.signatures.append((lhs, op, rhs, tag)) return [('token', lhs)] if op == '::=' else None def _add_index_entry(self, name, target): pass def _target_id(self, name): return make_id('grammar-token-{}'.format(name[1])) def _record_name(self, name, targetid, signode): env = self.state.document.settings.env objects = env.domaindata['std']['objects'] self._warn_if_duplicate_name(objects, name, signode) objects[name] = env.docname, targetid def run(self): self.signatures = [] indexnode = super().run()[0] # makes calls to handle_signature table = nodes.inline(classes=['prodn-table']) tgroup = nodes.inline(classes=['prodn-column-group']) for _ in range(4): tgroup += nodes.inline(classes=['prodn-column']) table += tgroup tbody = nodes.inline(classes=['prodn-row-group']) table += tbody # create rows for signature in self.signatures: lhs, op, rhs, tag = signature position = self.state_machine.get_source_and_line(self.lineno) row = nodes.inline(classes=['prodn-row']) entry = nodes.inline(classes=['prodn-cell-nonterminal']) if lhs != "": target_name = make_id('grammar-token-' + lhs) target = nodes.target('', '', ids=[target_name], names=[target_name]) # putting prodn-target on the target node won't appear in the tex file inline = nodes.inline(classes=['prodn-target']) inline += target entry += inline entry += notation_to_sphinx('@'+lhs, *position) else: entry += nodes.literal('', '') row += entry entry = nodes.inline(classes=['prodn-cell-op']) entry += nodes.literal(op, op) row += entry entry = nodes.inline(classes=['prodn-cell-production']) entry += notation_to_sphinx(rhs, *position) row += entry entry = nodes.inline(classes=['prodn-cell-tag']) entry += nodes.literal(tag, tag) row += entry tbody += row return [indexnode, table] # only this node goes into the doc class ExceptionObject(NotationObject): """An object for an error raised by a Rocq command or tactic. See the documentation of the ".. exn::" object in doc/sphinx/README.rst. """ subdomain = "exn" index_suffix = "(error)" annotation = "Error" # Uses β€œexn” since β€œerr” already is a CSS class added by β€œwriter_aux”. # Generate names automatically def _name_from_signature(self, signature): return notation_to_string(signature) class WarningObject(NotationObject): """An object for a warning raised by a Rocq command or tactic.. See the documentation of the ".. warn::" object in doc/sphinx/README.rst. """ subdomain = "warn" index_suffix = "(warning)" annotation = "Warning" # Generate names automatically def _name_from_signature(self, signature): return notation_to_string(signature) def NotationRole(role, rawtext, text, lineno, inliner, options={}, content=[]): #pylint: disable=unused-argument, dangerous-default-value """A role for any text using the notation syntax (``@id``, ``{+, …}``, etc.). See the documentation of the ":n:" role in doc/sphinx/README.rst. """ notation = utils.unescape(text, 1) position = inliner.reporter.get_source_and_line(lineno) return [nodes.literal(rawtext, '', notation_to_sphinx(notation, *position, rawtext=rawtext))], [] def rocq_code_role(role, rawtext, text, lineno, inliner, options={}, content=[]): #pylint: disable=dangerous-default-value """A Rocq code role for Gallina and Ltac snippets. See the documentation of the ":g:" role in doc/sphinx/README.rst. """ options['language'] = 'Coq' return code_role(role, rawtext, text, lineno, inliner, options, content) ## Too heavy: ## Forked from code_role to use our custom tokenizer; this doesn't work for ## snippets though: for example RocqDoc swallows the parentheses around this: ## β€œ(a: A) (b: B)” # set_classes(options) # classes = ['code', 'rocq'] # code = utils.unescape(text, 1) # node = nodes.literal(rawtext, '', *highlight_using_rocqdoc(code), classes=classes) # return [node], [] RocqCodeRole = rocq_code_role class RocqtopDirective(Directive): """A reST directive to describe interactions with Rocq Top. See the documentation of the ".. rocqtop::" directive in doc/sphinx/README.rst. """ has_content = True required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = { 'name': directives.unchanged } directive_name = "rocqtop" def run(self): # Uses a β€˜container’ instead of a β€˜literal_block’ to disable # Pygments-based post-processing (we could also set rawsource to '') content = '\n'.join(self.content) args = self.arguments[0].split() node = nodes.container(content, rocqtop_options = set(args), classes=['rocqtop', 'literal-block']) self.add_name(node) return [node] class RocqdocDirective(Directive): """A reST directive to display Rocq Doc-formatted source code. See the documentation of the ".. rocqdoc::" directive in doc/sphinx/README.rst. """ # TODO implement this as a Pygments highlighter? has_content = True required_arguments = 0 optional_arguments = 0 final_argument_whitespace = True option_spec = { 'name': directives.unchanged } directive_name = "rocqdoc" def run(self): # Uses a β€˜container’ instead of a β€˜literal_block’ to disable # Pygments-based post-processing (we could also set rawsource to '') content = '\n'.join(self.content) node = nodes.inline(content, '', *highlight_using_rocqdoc(content)) wrapper = nodes.container(content, node, classes=['rocqdoc', 'literal-block']) self.add_name(wrapper) return [wrapper] class ExampleDirective(BaseAdmonition): """A reST directive for examples. See the documentation of the ".. example::" directive in doc/sphinx/README.rst. """ node_class = nodes.admonition directive_name = "example" optional_arguments = 1 def run(self): # β€˜BaseAdmonition’ checks whether β€˜node_class’ is β€˜nodes.admonition’, # and uses arguments[0] as the title in that case (in other cases, the # title is unset, and it is instead set in the HTML visitor). assert len(self.arguments) <= 1 self.arguments = [": ".join(['Example'] + self.arguments)] self.options['classes'] = ['admonition', 'note'] return super().run() class PreambleDirective(Directive): """A reST directive to include a TeX file. See the documentation of the ".. preamble::" directive in doc/sphinx/README.rst """ has_content = False required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = {} directive_name = "preamble" def run(self): document = self.state.document env = document.settings.env if not document.settings.file_insertion_enabled: msg = 'File insertion disabled' return [document.reporter.warning(msg, line=self.lineno)] rel_fname, abs_fname = env.relfn2path(self.arguments[0]) env.note_dependency(rel_fname) with open(abs_fname, encoding="utf-8") as ltx: latex = ltx.read() node = make_math_node(latex, env.docname, nowrap=False) node['classes'] = ["math-preamble"] set_source_info(self, node) return [node] class InferenceDirective(Directive): """A reST directive to format inference rules. See the documentation of the ".. inference::" directive in doc/sphinx/README.rst """ required_arguments = 1 optional_arguments = 0 has_content = True final_argument_whitespace = True directive_name = "inference" @staticmethod def prepare_latex_operand(op): # TODO: Could use a fancier inference class in LaTeX return '%\n\\hspace{3em}%\n'.join(op.strip().splitlines()) def prepare_latex(self, content): parts = re.split('^ *----+ *$', content, flags=re.MULTILINE) if len(parts) != 2: raise self.error('Expected two parts in β€˜inference’ directive, separated by a rule (----).') top, bottom = tuple(InferenceDirective.prepare_latex_operand(p) for p in parts) return "%\n".join(("\\frac{", top, "}{", bottom, "}")) def run(self): self.assert_has_content() title = self.arguments[0] content = '\n'.join(self.content) latex = self.prepare_latex(content) docname = self.state.document.settings.env.docname math_node = make_math_node(latex, docname, nowrap=False) tid = make_id(title) target = nodes.target('', '', ids=['inference-' + tid]) self.state.document.note_explicit_target(target) term, desc = nodes.term('', title), nodes.description('', math_node) dli = nodes.definition_list_item('', term, desc) dl = nodes.definition_list(content, target, dli) set_source_info(self, dl) return [dl] class AnsiColorsParser(): """Parse ANSI-colored output from Rocqtop into Sphinx nodes.""" # Rocqtop's output crashes ansi.py, because it contains a bunch of extended codes # This class is a fork of the original ansi.py, released under a BSD license in sphinx-contribs COLOR_PATTERN = re.compile('\x1b\\[([^m]+)m') def __init__(self): self.new_nodes, self.pending_nodes = [], [] def _finalize_pending_nodes(self): self.new_nodes.extend(self.pending_nodes) self.pending_nodes = [] def _add_text(self, raw, beg, end): if beg < end: text = raw[beg:end] if self.pending_nodes: self.pending_nodes[-1].append(nodes.Text(text)) else: self.new_nodes.append(nodes.inline('', text)) def colorize_str(self, raw): """Parse raw (an ANSI-colored output string from Rocqtop) into Sphinx nodes.""" last_end = 0 for match in AnsiColorsParser.COLOR_PATTERN.finditer(raw): self._add_text(raw, last_end, match.start()) last_end = match.end() classes = ansicolors.parse_ansi(match.group(1)) if 'ansi-reset' in classes: self._finalize_pending_nodes() else: node = nodes.inline() self.pending_nodes.append(node) node['classes'].extend(classes) self._add_text(raw, last_end, len(raw)) self._finalize_pending_nodes() return self.new_nodes class RocqtopBlocksTransform(Transform): """Filter handling the actual work for the rocqtop directive Adds rocqtop's responses, colorizes input and output, and merges consecutive rocqtop directives for better visual rendition. """ default_priority = 10 @staticmethod def is_rocqtop_block(node): return isinstance(node, nodes.Element) and 'rocqtop_options' in node @staticmethod def is_rocqtop_args_field(node): return isinstance(node, nodes.field) and node.children[0].rawsource == 'ROCQTOP_ARGS' @staticmethod def split_lines(source): r"""Split Rocq input into chunks, which may include single- or multi-line comments. Nested comments are not supported. A chunk is a minimal sequence of consecutive lines of the input that ends with a '.' or a focusing brace, possibly followed by blanks and/or comments. >>> split_lines('A.\nB.''') ['A.\n', 'B.'] >>> split_lines('A.\n\nB.''') ['A.\n', '\nB.'] >>> split_lines('A.\n\nB.\n''') ['A.\n', '\nB.'] >>> split_lines("SearchPattern (_ + _ = _ + _).\n" ... "SearchPattern (nat -> bool).\n" ... "SearchPattern (forall l : list _, _ l l).") ... # doctest: +NORMALIZE_WHITESPACE ['SearchPattern (_ + _ = _ + _).\n', 'SearchPattern (nat -> bool).\n', 'SearchPattern (forall l : list _, _ l l).'] >>> split_lines('SearchHead le.\nSearchHead (@eq bool).') ['SearchHead le.\n', 'SearchHead (@eq bool).'] >>> split_lines("(* *) x. (* *)\ny.\n") ['(* *) x. (* *)\n', 'y.'] >>> split_lines("(* *) x (* \n *)\ny.\n") ['(* *) x (* \n *)\ny.'] >>> split_lines("Check (* check *) list (* comment *)\n" ... "nat. (* another *) (*and another *)")) ['Check (* check *) list (* comment *)\nnat. (* another *) (*and another *)'] """ comment = r"\(\*.*\*\)" # the end of a chunk is marked by # a period (\.) or a focusing brace (:\s*\{) # optional blanks or comments (?:[ \t]*|{comment})* # followed by a newline \n # We capture everything starting from the '.' to recover it afterwards blank = r"[ \t]" dot = r"\." focusing_brace = r":\s*\{" end_of_chunk = fr"((?:{dot}|{focusing_brace})(?:{blank}*|{comment})*\n)" splits = re.split(end_of_chunk, source.strip()) return [''.join(splits[i:i+2]) for i in range(0, len(splits), 2)] @staticmethod def parse_options(node): """Parse options according to the description in RocqtopDirective.""" options = node['rocqtop_options'] # Behavior options opt_reset = 'reset' in options opt_fail = 'fail' in options opt_warn = 'warn' in options opt_restart = 'restart' in options opt_abort = 'abort' in options opt_extra = set([opt for opt in options if opt.startswith('extra-')]) options = options - {'reset', 'fail', 'warn', 'restart', 'abort'} options = set([opt for opt in options if not (opt.startswith('extra-'))]) unexpected_options = list(options - {'all', 'none', 'in', 'out'}) if unexpected_options: loc = os.path.basename(get_node_location(node)) raise ExtensionError("{}: Unexpected options for .. rocqtop:: {}".format(loc,unexpected_options)) # Display options if len(options) != 1: loc = os.path.basename(get_node_location(node)) raise ExtensionError("{}: Exactly one display option must be passed to .. rocqtop::".format(loc)) opt_all = 'all' in options opt_input = 'in' in options opt_output = 'out' in options # if 'extra' is given and not a subset of env variable 'ROCQRST_EXTRA', # allow errors env_extra = os.environ.get('ROCQRST_EXTRA', '') opt_fail = opt_fail or (env_extra != 'all' and len(opt_extra - set(env_extra.split(','))) != 0) return { 'reset': opt_reset, 'fail': opt_fail, # if errors are allowed, then warnings too # and they should be displayed as warnings, not errors 'warn': opt_warn or opt_fail, 'restart': opt_restart, 'abort': opt_abort, 'input': opt_input or opt_all, 'output': opt_output or opt_all } @staticmethod def block_classes(should_show, contents=None): """Compute classes to add to a node containing contents. :param should_show: Whether this node should be displayed""" is_empty = contents is not None and re.match(r"^\s*$", contents) return ['rocqtop-hidden'] if is_empty or not should_show else [] @staticmethod def make_rawsource(pairs, opt_input, opt_output): blocks = [] for sentence, output in pairs: output = AnsiColorsParser.COLOR_PATTERN.sub("", output).strip() if opt_input: blocks.append(sentence) if output and opt_output: blocks.append(re.sub("^", " ", output, flags=re.MULTILINE) + "\n") return '\n'.join(blocks) def add_rocq_output_1(self, repl, node): options = self.parse_options(node) pairs = [] if options['restart']: repl.sendone('Restart.') if options['reset']: repl.sendone('Reset Initial.') repl.send_initial_options() if options['fail']: repl.sendone('Unset Rocqtop Exit On Error.') if options['warn']: repl.sendone('Set Warnings "default".') for sentence in self.split_lines(node.rawsource): comment = re.compile(r"\s*\(\*.*?\*\)\s*", re.DOTALL) wo_comments = re.sub(comment, "", sentence) has_tac = wo_comments != "" and not wo_comments.isspace() output = repl.sendone(sentence) if has_tac else "" pairs.append((sentence, output)) if options['abort']: repl.sendone('Abort All.') if options['fail']: repl.sendone('Set Rocqtop Exit On Error.') if options['warn']: repl.sendone('Set Warnings "+default".') dli = nodes.definition_list_item() for sentence, output in pairs: # Use Rocqdoc to highlight input in_chunks = highlight_using_rocqdoc(sentence) dli += nodes.term(sentence, '', *in_chunks, classes=self.block_classes(options['input'])) if output: # Parse ANSI sequences to highlight output out_chunks = AnsiColorsParser().colorize_str(output) dli += nodes.definition(output, *out_chunks, classes=self.block_classes(options['output'], output)) node.clear() node.rawsource = self.make_rawsource(pairs, options['input'], options['output']) node['classes'].extend(self.block_classes(options['input'] or options['output'])) node += nodes.inline('', '', classes=['rocqtop-reset'] * options['reset']) node += nodes.definition_list(node.rawsource, dli) def add_rocqtop_output(self): """Add rocqtop's responses to a Sphinx AST Finds nodes to process using is_rocqtop_block.""" arg_fields = self.document.traverse(RocqtopBlocksTransform.is_rocqtop_args_field) additional_args = [arg for field in arg_fields for arg in shlex.split(field.children[1].rawsource)] with RocqTop(color=True, args=additional_args) as repl: repl.send_initial_options() for node in self.document.traverse(RocqtopBlocksTransform.is_rocqtop_block): try: self.add_rocq_output_1(repl, node) except RocqTopError as err: import textwrap MSG = ("{}: Error while sending the following to rocqtop:\n{}" + "\n rocqtop output:\n{}" + "\n Full error text:\n{}") indent = " " loc = get_node_location(node) le = textwrap.indent(str(err.last_sentence), indent) bef = textwrap.indent(str(err.before), indent) fe = textwrap.indent(str(err.err), indent) raise ExtensionError(MSG.format(loc, le, bef, fe)) @staticmethod def merge_rocqtop_classes(kept_node, discarded_node): discarded_classes = discarded_node['classes'] if not 'rocqtop-hidden' in discarded_classes: kept_node['classes'] = [c for c in kept_node['classes'] if c != 'rocqtop-hidden'] @staticmethod def merge_consecutive_rocqtop_blocks(_app, doctree, _): """Merge consecutive divs wrapping lists of Rocq sentences; keep β€˜dl’s separate.""" for node in doctree.traverse(RocqtopBlocksTransform.is_rocqtop_block): if node.parent: rawsources, names = [node.rawsource], set(node['names']) for sibling in node.traverse(include_self=False, descend=False, siblings=True, ascend=False): if RocqtopBlocksTransform.is_rocqtop_block(sibling): RocqtopBlocksTransform.merge_rocqtop_classes(node, sibling) rawsources.append(sibling.rawsource) names.update(sibling['names']) node.extend(sibling.children) node.parent.remove(sibling) sibling.parent = None else: break node.rawsource = "\n\n".join(rawsources) node['names'] = list(names) def apply(self): self.add_rocqtop_output() class RocqSubdomainsIndex(Index): """Index subclass to provide subdomain-specific indices. Just as in the original manual, we want to have separate indices for each Rocq subdomain (tactics, commands, options, etc)""" name, localname, shortname, subdomains = None, None, None, [] # Must be overwritten def generate(self, docnames=None): content = defaultdict(list) items = chain(*(self.domain.data['objects'][subdomain].items() for subdomain in self.subdomains)) for itemname, (docname, _, anchor) in sorted(items, key=lambda x: x[0].lower()): if docnames and docname not in docnames: continue entries = content[itemname[0].lower()] entries.append([itemname, 0, docname, anchor, '', '', '']) collapse = False content = sorted(content.items()) return content, collapse class RocqVernacIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "cmdindex", "Command Index", "commands", ["cmd"] class RocqTacticIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "tacindex", "Tactic Index", "tactics", ["tacn"] class RocqAttributeIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "attrindex", "Attribute Index", "attributes", ["attr"] class RocqOptionIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "optindex", "Flags, options and Tables Index", "options", ["flag", "opt", "table"] class RocqGallinaIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "thmindex", "Gallina Index", "theorems", ["thm"] class RocqExceptionIndex(RocqSubdomainsIndex): name, localname, shortname, subdomains = "exnindex", "Errors and Warnings Index", "errors", ["exn", "warn"] class IndexXRefRole(XRefRole): """A link to one of our domain-specific indices.""" lowercase = True innernodeclass = nodes.inline warn_dangling = True def process_link(self, env, refnode, has_explicit_title, title, target): if not has_explicit_title: index = RocqDomain.find_index_by_name(target) if index: title = index.localname return title, target class StdGlossaryIndex(Index): name, localname, shortname = "glossindex", "Glossary", "terms" def generate(self, docnames=None): def ci_sort(entry): ((type, itemname), (docname, anchor)) = entry return itemname.lower() content = defaultdict(list) for ((type, itemname), (docname, anchor)) in sorted(self.domain.data['objects'].items(), key=ci_sort): if type == 'term': entries = content[itemname[0].lower()] entries.append([itemname, 0, docname, anchor, '', '', '']) return content.items(), False def GrammarProductionRole(typ, rawtext, text, lineno, inliner, options={}, content=[]): """A grammar production not included in a ``prodn`` directive. See the documentation of the ":production:" role in doc/sphinx/README.rst """ #pylint: disable=dangerous-default-value, unused-argument env = inliner.document.settings.env targetid = make_id('grammar-token-{}'.format(text)) target = nodes.target('', '', ids=[targetid]) inliner.document.note_explicit_target(target) code = nodes.literal(rawtext, text, role=typ.lower()) node = nodes.inline(rawtext, '', target, code, classes=['inline-grammar-production']) set_role_source_info(inliner, lineno, node) env.domaindata['std']['objects']['token', text] = env.docname, targetid return [node], [] GrammarProductionRole.role_name = "production" def GlossaryDefRole(typ, rawtext, text, lineno, inliner, options={}, content=[]): """A role to mark the definition of a glossary term inline in the text. See the documentation of the ":gdef:" role in doc/sphinx/README.rst """ #pylint: disable=dangerous-default-value, unused-argument env = inliner.document.settings.env std = env.domaindata['std']['objects'] m = ReferenceRole.explicit_title_re.match(text) if m: (text, term) = m.groups() text = text.strip() else: term = text key = ('term', term) if key in std: MSG = 'Duplicate object: {}; other is at {}' msg = MSG.format(term, env.doc2path(std[key][0])) inliner.document.reporter.warning(msg, line=lineno) targetid = make_id('term-{}'.format(term)) std[key] = (env.docname, targetid) target = nodes.target('', '', ids=[targetid], names=[term]) inliner.document.note_explicit_target(target) node = nodes.inline(rawtext, '', target, nodes.Text(text), classes=['term-defn']) set_role_source_info(inliner, lineno, node) return [node], [] GlossaryDefRole.role_name = "gdef" class RocqDomain(Domain): """A domain to document Rocq code. Sphinx has a notion of β€œdomains”, used to tailor it to a specific language. Domains mostly consist in descriptions of the objects that we wish to describe (for Rocq, this includes tactics, tactic notations, options, exceptions, etc.), as well as domain-specific roles and directives. Each domain is responsible for tracking its objects, and resolving references to them. In the case of Rocq, this leads us to define Rocq β€œsubdomains”, which classify objects into categories in which names must be unique. For example, a tactic and a theorem may share a name, but two tactics cannot be named the same. """ name = 'rocq' label = 'Rocq' object_types = { # ObjType (= directive type) β†’ (Local name, *xref-roles) 'cmd': ObjType('cmd', 'cmd'), 'cmdv': ObjType('cmdv', 'cmd'), 'tacn': ObjType('tacn', 'tacn'), 'tacv': ObjType('tacv', 'tacn'), 'opt': ObjType('opt', 'opt'), 'flag': ObjType('flag', 'flag'), 'table': ObjType('table', 'table'), 'attr': ObjType('attr', 'attr'), 'thm': ObjType('thm', 'thm'), 'prodn': ObjType('prodn', 'prodn'), 'exn': ObjType('exn', 'exn'), 'warn': ObjType('warn', 'exn'), 'index': ObjType('index', 'index', searchprio=-1) } directives = { # Note that some directives live in the same semantic subdomain; ie # there's one directive per object type, but some object types map to # the same role. 'cmd': VernacObject, 'cmdv': VernacVariantObject, 'tacn': TacticObject, 'tacv': TacticVariantObject, 'opt': OptionObject, 'flag': FlagObject, 'table': TableObject, 'attr': AttributeObject, 'thm': GallinaObject, 'prodn' : ProductionObject, 'exn': ExceptionObject, 'warn': WarningObject, } roles = { # Each of these roles lives in a different semantic β€œsubdomain” 'cmd': XRefRole(warn_dangling=True), 'tacn': XRefRole(warn_dangling=True), 'opt': XRefRole(warn_dangling=True), 'flag': XRefRole(warn_dangling=True), 'table': XRefRole(warn_dangling=True), 'attr': XRefRole(warn_dangling=True), 'thm': XRefRole(warn_dangling=True), 'prodn' : XRefRole(warn_dangling=True), 'exn': XRefRole(warn_dangling=True), 'warn': XRefRole(warn_dangling=True), # This one is special 'index': IndexXRefRole(), # These are used for highlighting 'n': NotationRole, 'g': RocqCodeRole } indices = [RocqVernacIndex, RocqTacticIndex, RocqOptionIndex, RocqGallinaIndex, RocqExceptionIndex, RocqAttributeIndex] data_version = 1 initial_data = { # Collect everything under a key that we control, since Sphinx adds # others, such as β€œversion” 'objects' : { # subdomain β†’ name β†’ docname, objtype, targetid 'cmd': {}, 'tacn': {}, 'opt': {}, 'flag': {}, 'table': {}, 'attr': {}, 'thm': {}, 'prodn' : {}, 'exn': {}, 'warn': {}, } } @staticmethod def find_index_by_name(targetid): for index in RocqDomain.indices: if index.name == targetid: return index return None def get_objects(self): # Used for searching and object inventories (intersphinx) for _, objects in self.data['objects'].items(): for name, (docname, objtype, targetid) in objects.items(): yield (name, name, objtype, docname, targetid, self.object_types[objtype].attrs['searchprio']) for index in self.indices: yield (index.name, index.localname, 'index', "rocq-" + index.name, '', -1) def merge_domaindata(self, docnames, otherdata): DUP = "Duplicate declaration: '{}' also defined in '{}'.\n" for subdomain, their_objects in otherdata['objects'].items(): our_objects = self.data['objects'][subdomain] for name, (docname, objtype, targetid) in their_objects.items(): if docname in docnames: if name in our_objects: self.env.warn(docname, DUP.format(name, our_objects[name][0])) our_objects[name] = (docname, objtype, targetid) def resolve_xref(self, env, fromdocname, builder, role, targetname, node, contnode): # β€˜target’ is the name that was written in the document # β€˜role’ is where this xref comes from; it's exactly one of our subdomains if role == 'index': index = RocqDomain.find_index_by_name(targetname) if index: return make_refnode(builder, fromdocname, "rocq-" + index.name, '', contnode, index.localname) else: resolved = self.data['objects'][role].get(targetname) if resolved: (todocname, _, targetid) = resolved return make_refnode(builder, fromdocname, todocname, targetid, contnode, targetname) return None def clear_doc(self, docname_to_clear): for subdomain_objects in self.data['objects'].values(): for name, (docname, _, _) in list(subdomain_objects.items()): if docname == docname_to_clear: del subdomain_objects[name] def is_rocqtop_or_rocqdoc_block(node): return (isinstance(node, nodes.Element) and ('rocqtop' in node['classes'] or 'rocqdoc' in node['classes'])) def simplify_source_code_blocks_for_latex(app, doctree, fromdocname): # pylint: disable=unused-argument """Simplify rocqdoc and rocqtop blocks. In HTML mode, this does nothing; in other formats, such as LaTeX, it replaces rocqdoc and rocqtop blocks by plain text sources, which will use pygments if available. This prevents the LaTeX builder from getting confused. """ is_html = app.builder.tags.has("html") for node in doctree.traverse(is_rocqtop_or_rocqdoc_block): if is_html: node.rawsource = '' # Prevent pygments from kicking in elif 'rocqtop-hidden' in node['classes']: node.parent.remove(node) else: node.replace_self(nodes.literal_block(node.rawsource, node.rawsource, language="Coq")) ROCQ_ADDITIONAL_DIRECTIVES = [RocqtopDirective, RocqdocDirective, ExampleDirective, InferenceDirective, PreambleDirective] ROCQ_ADDITIONAL_ROLES = [GrammarProductionRole, GlossaryDefRole] def setup(app): """Register the Rocq domain""" # A few sanity checks: subdomains = set(obj.subdomain for obj in RocqDomain.directives.values()) found = set (obj for obj in chain(*(idx.subdomains for idx in RocqDomain.indices))) assert subdomains.issuperset(found), "Missing subdomains: {}".format(found.difference(subdomains)) assert subdomains.issubset(RocqDomain.roles.keys()), \ "Missing from RocqDomain.roles: {}".format(subdomains.difference(RocqDomain.roles.keys())) # Add domain, directives, and roles app.add_domain(RocqDomain) app.add_index_to_domain('std', StdGlossaryIndex) for role in ROCQ_ADDITIONAL_ROLES: app.add_role(role.role_name, role) for directive in ROCQ_ADDITIONAL_DIRECTIVES: app.add_directive(directive.directive_name, directive) app.add_transform(RocqtopBlocksTransform) app.connect('doctree-resolved', simplify_source_code_blocks_for_latex) app.connect('doctree-resolved', RocqtopBlocksTransform.merge_consecutive_rocqtop_blocks) # Add extra styles app.add_css_file("ansi.css") app.add_css_file("coqdoc.css") app.add_js_file("notations.js") app.add_css_file("notations.css") app.add_css_file("pre-text.css") # Tell Sphinx about extra settings app.add_config_value("report_undocumented_rocq_objects", None, 'env') # ``env_version`` is used by Sphinx to know when to invalidate # rocqdomain-specific bits in its caches. It should be incremented when the # contents of ``env.domaindata['rocq']`` change. See # `https://github.com/sphinx-doc/sphinx/issues/4460`. meta = { "version": "0.1", "env_version": 2, "parallel_read_safe": True } return meta rocq-9.2.0/doc/tools/show_latex_messages000077500000000000000000000002751516144147600204020ustar00rootroot00000000000000#!/bin/sh tooldir=$(dirname $0) if [ "$1" = "-no-overfull" ]; then cat $2 | "$tooldir"/latex_filter `cat $2 | wc -l` no else cat $1 | "$tooldir"/latex_filter `cat $1 | wc -l` yes fi rocq-9.2.0/dune000066400000000000000000000047141516144147600133630ustar00rootroot00000000000000; Default flags for all Rocq libraries. (env (dev (flags :standard -w -9-27@60-69@70 \ -short-paths) (coq (flags :standard -w +default))) (release (flags :standard) (ocamlopt_flags :standard -O3 -unbox-closures)) (ireport (flags :standard -w -9-27+60-70) (ocamlopt_flags :standard -O3 -unbox-closures -inlining-report))) ; Information about flags for release mode: ; ; In #9665 we tried to add (c_flags -O3) to the release setup, ; unfortunately the resulting VM seems to be slower [5% slower on ; fourcolor, thus we keep the default C flags for now, which seem to ; be -O2. ; The _ profile could help factoring the above, however it doesn't ; seem to work like we'd expect/like: ; ; (_ (flags :standard))) (alias (name default) (deps rocq-runtime.install coq-core.install rocq-core.install coqide-server.install)) (alias (name runtime) (deps rocq-runtime.install coq-core.install)) (install (section lib) (package rocq-runtime) (files revision)) (rule (targets revision) (mode fallback) (deps (:rev-script dev/tools/make_git_revision.sh)) (action (with-stdout-to revision (bash %{rev-script})))) ; bootstrap for theories/Corelib/dune (rule (targets corelib_dune) (deps (source_tree plugins) (source_tree theories) %{workspace_root}/_build/install/%{context_name}/lib/rocq-runtime/META) (action (with-stdout-to %{targets} (run tools/dune_rule_gen/gen_rules.exe Corelib theories/Corelib %{env:COQ_DUNE_EXTRA_OPT=})))) (rule (targets ltac2_dune) (deps (source_tree plugins) (source_tree theories) %{workspace_root}/_build/install/%{context_name}/lib/rocq-runtime/META) (action (with-stdout-to %{targets} (run tools/dune_rule_gen/gen_rules.exe Ltac2 theories/Ltac2 -noinit %{env:COQ_DUNE_EXTRA_OPT=})))) (rule (targets corelib_dune_split) (deps (source_tree plugins) (source_tree theories)) (action (with-stdout-to %{targets} (run tools/dune_rule_gen/gen_rules.exe Corelib theories/Corelib -split %{env:COQ_DUNE_EXTRA_OPT=})))) (rule (targets ltac2_dune_split) (deps (source_tree plugins) (source_tree theories)) (action (with-stdout-to %{targets} (run tools/dune_rule_gen/gen_rules.exe Ltac2 theories/Ltac2 -noinit -split %{env:COQ_DUNE_EXTRA_OPT=})))) ; Use summary.log as the target (alias (name runtest) (package rocq-test-suite) (deps test-suite/summary.log)) ; For make compat (alias (name all-src) (deps (source_tree theories) (source_tree plugins))) ; (dirs (:standard _build_ci)) rocq-9.2.0/dune-project000066400000000000000000000150261516144147600150250ustar00rootroot00000000000000(lang dune 3.8) (name rocq-prover) ; We use directory targets in documentation (using directory-targets 0.1) ; We need this for when we use the dune.disabled files instead of our rule_gen (using coq 0.8) (formatting (enabled_for ocaml)) (generate_opam_files true) (license LGPL-2.1-only) (maintainers "The Rocq development team ") (authors "The Rocq development team, INRIA, CNRS, and contributors") ; This generates bug-reports and dev-repo (source (github rocq-prover/rocq)) (homepage https://rocq-prover.org/) (documentation "https://rocq-prover.org/docs/") (version dev) ; Note that we use rocq-runtime.opam.template to have dune add the correct opam ; prefix for configure (package (name rocq-runtime) (depends (ocaml (>= 4.14.0)) (ocamlfind (and (>= 1.9.1) (or (>= 1.9.8) (<> :os-family "windows")))) (zarith (>= 1.11)) (conf-linux-libc-dev (= :os "linux"))) (conflicts (coq (< 8.17)) (coq-core (< 8.21))) (depopts rocq-native memprof-limits memtrace) (synopsis "The Rocq Prover -- Core Binaries and Tools") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package includes the Rocq Prover core binaries, plugins, and tools, but not the vernacular standard library. Note that in this setup, Rocq needs to be started with the -boot and -noinit options, as will otherwise fail to find the regular Rocq prelude, now living in the rocq-core package.")) (package (name rocq-devtools) (depends (rocq-runtime (= :version)) (yojson (>= 2.0)) camlzip) (synopsis "Development tools for Rocq") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package includes tools to help when developing Rocq projects (timelog2html).")) (package (name coq-core) (depends (rocq-runtime (= :version))) (synopsis "Compatibility binaries for Coq after the Rocq renaming") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package includes compatibility binaries to call Rocq through previous Coq commands like coqc coqtop,...")) (package (name rocq-core) (depends (rocq-runtime (= :version))) (synopsis "The Rocq Prover with its prelude") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package includes the Rocq prelude, that is loaded automatically by Rocq in every .v file, as well as other modules bound to the Corelib.* and Ltac2.* namespaces.")) (package (name coqide-server) (depends (rocq-runtime (= :version))) (synopsis "The Rocq Prover, XML protocol server") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. This package provides the `coqidetop` language server, an implementation of Rocq's [XML protocol](https://github.com/rocq-prover/rocq/blob/master/dev/doc/xml-protocol.md) which allows clients, such as RocqIDE, to interact with the Rocq Prover in a structured way.")) (package (name rocqide) (depends (ocamlfind :build) (conf-findutils :build) conf-adwaita-icon-theme (coqide-server (= :version)) (cairo2 (>= 0.6.4)) (lablgtk3-sourceview3 (and (>= 3.1.2) (or (>= 3.1.5) (<> :os-family "windows"))))) (synopsis "The Rocq Prover --- GTK3 IDE") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. This package provides the RocqIDE, a graphical user interface for the development of interactive proofs.")) (package (name rocq-test-suite) (depends (rocq-core (= :version)) coqide-server ounit2 conf-python-3 conf-time) (synopsis "The Rocq Prover test suite") (description "The Rocq Prover is an interactive theorem prover, or proof assistant. It provides a formal language to write mathematical definitions, executable algorithms and theorems together with an environment for semi-interactive development of machine-checked proofs. Typical applications include the certification of properties of programming languages (e.g. the CompCert compiler certification project, or the Bedrock verified low-level programming library), the formalization of mathematics (e.g. the full formalization of the Feit-Thompson theorem or homotopy type theory) and teaching. This package runs the test suite.")) rocq-9.2.0/engine/000077500000000000000000000000001516144147600137445ustar00rootroot00000000000000rocq-9.2.0/engine/dune000066400000000000000000000004501516144147600146210ustar00rootroot00000000000000(library (name engine) (synopsis "Rocq's Tactic Engine") (public_name rocq-runtime.engine) (wrapped false) ; until ocaml/dune#4892 fixed ; (private_modules univSubst) (libraries library)) (deprecated_library_name (old_public_name coq-core.engine) (new_public_name rocq-runtime.engine)) rocq-9.2.0/engine/eConstr.ml000066400000000000000000001364401516144147600157230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* handle * t val repr : Evd.evar_map -> handle -> t -> Evd.econstr val liftn_handle : int -> handle -> handle val kind : Evd.evar_map -> handle -> t -> handle * kind val expand_instance : skip:bool -> Evd.undefined Evd.evar_info -> handle -> t SList.t -> t SList.t val iter : Evd.evar_map -> (handle -> t -> unit) -> handle -> kind -> unit val iter_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> handle -> t -> unit) -> 'a -> handle -> kind -> unit end = struct include Evd.Expand type t = Evd.econstr type kind = (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term let make c = (empty_handle, c) let repr = expand let iter sigma f h knd = match knd with | Evar (evk, args) -> let evi = Evd.find_undefined sigma evk in let args = expand_instance ~skip:false evi h args in (* Despite the type, the sparse list contains no default element *) SList.Skip.iter (f h) args | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _ -> () | Cast (c, _, t) -> f h c; f h t | Prod (_, t, c) -> f h t; f (liftn_handle 1 h) c | Lambda (_, t, c) -> f h t; f (liftn_handle 1 h) c | LetIn (_, b, t, c) -> f h b; f h t; f (liftn_handle 1 h) c | App (c, l) -> f h c; Array.Fun1.iter f h l | Case (_, _, pms, (p, _), iv, c, bl) -> Array.Fun1.iter f h pms; f (liftn_handle (Array.length (fst p)) h) (snd p); iter_invert (f h) iv; f h c; Array.Fun1.iter (fun h (ctx, b) -> f (liftn_handle (Array.length ctx) h) b) h bl | Proj (_p, _r, c) -> f h c | Fix (_, (_, tl, bl)) -> Array.Fun1.iter f h tl; Array.Fun1.iter f (liftn_handle (Array.length tl) h) bl | CoFix (_, (_, tl, bl)) -> Array.Fun1.iter f h tl; Array.Fun1.iter f (liftn_handle (Array.length tl) h) bl | Array(_u, t, def, ty) -> Array.iter (f h) t; f h def; f h ty let iter_with_binders sigma g f l h knd = match knd with | Evar (evk, args) -> let evi = Evd.find_undefined sigma evk in let args = expand_instance ~skip:false evi h args in (* Despite the type, the sparse list contains no default element *) SList.Skip.iter (f l h) args | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _ -> () | Cast (c, _, t) -> f l h c; f l h t | Prod (_, t, c) -> f l h t; f (g l) (liftn_handle 1 h) c | Lambda (_, t, c) -> f l h t; f (g l) (liftn_handle 1 h) c | LetIn (_, b, t, c) -> f l h b; f l h t; f (g l) (liftn_handle 1 h) c | App (c, args) -> f l h c; Array.iter (fun c -> f l h c) args | Case (_, _, pms, (p, _), iv, c, bl) -> Array.iter (fun c -> f l h c) pms; f (iterate g (Array.length (fst p)) l) (liftn_handle (Array.length (fst p)) h) (snd p); iter_invert (fun c -> f l h c) iv; f l h c; Array.iter (fun (ctx, b) -> f (iterate g (Array.length ctx) l) (liftn_handle (Array.length ctx) h) b) bl | Proj (_p, _r, c) -> f l h c | Fix (_, (_, tl, bl)) -> Array.iter (fun c -> f l h c) tl; Array.iter (f (iterate g (Array.length tl) l) (liftn_handle (Array.length tl) h)) bl | CoFix (_, (_, tl, bl)) -> Array.iter (fun c -> f l h c) tl; Array.iter (f (iterate g (Array.length tl) l) (liftn_handle (Array.length tl) h)) bl | Array(_u, t, def, ty) -> Array.iter (fun c -> f l h c) t; f l h def; f l h ty end include (Evd.MiniEConstr : module type of Evd.MiniEConstr with module ERelevance := ERelevance and module ESorts := ESorts and module EInstance := EInstance) type types = t type constr = t type existential = t pexistential type case_return = (t, ERelevance.t) pcase_return type case_branch = (t, ERelevance.t) pcase_branch type case_invert = t pcase_invert type case = (t, t, EInstance.t, ERelevance.t) pcase type rec_declaration = (t, t, ERelevance.t) prec_declaration type fixpoint = (t, t, ERelevance.t) pfixpoint type cofixpoint = (t, t, ERelevance.t) pcofixpoint type unsafe_judgment = (constr, types) Environ.punsafe_judgment type unsafe_type_judgment = (types, ESorts.t) Environ.punsafe_type_judgment type named_declaration = (constr, types, ERelevance.t) Context.Named.Declaration.pt type rel_declaration = (constr, types, ERelevance.t) Context.Rel.Declaration.pt type compacted_declaration = (constr, types, ERelevance.t) Context.Compacted.Declaration.pt type named_context = (constr, types, ERelevance.t) Context.Named.pt type compacted_context = compacted_declaration list type rel_context = (constr, types, ERelevance.t) Context.Rel.pt type 'a binder_annot = ('a, ERelevance.t) Context.pbinder_annot let annotR x = Context.make_annot x ERelevance.relevant let nameR x = annotR (Name x) let anonR = annotR Anonymous type 'a puniverses = 'a * EInstance.t let in_punivs a = (a, EInstance.empty) let mkSProp = of_kind (Sort (ESorts.make Sorts.sprop)) let mkProp = of_kind (Sort (ESorts.make Sorts.prop)) let mkSet = of_kind (Sort (ESorts.make Sorts.set)) let mkType u = of_kind (Sort (ESorts.make (Sorts.sort_of_univ u))) let mkRel n = of_kind (Rel n) let mkVar id = of_kind (Var id) let mkMeta n = of_kind (Meta n) let mkEvar e = of_kind (Evar e) let mkSort s = of_kind (Sort s) let mkCast (b, k, t) = of_kind (Cast (b, k, t)) let mkProd (na, t, u) = of_kind (Prod (na, t, u)) let mkLambda (na, t, c) = of_kind (Lambda (na, t, c)) let mkLetIn (na, b, t, c) = of_kind (LetIn (na, b, t, c)) let mkApp (f, arg) = of_kind (App (f, arg)) let mkConstU pc = of_kind (Const pc) let mkIndU pi = of_kind (Ind pi) let mkConstructU pc = of_kind (Construct pc) let mkConstructUi ((ind,u),i) = of_kind (Construct ((ind,i),u)) let mkCase (ci, u, pms, c, iv, r, p) = of_kind (Case (ci, u, pms, c, iv, r, p)) let mkFix f = of_kind (Fix f) let mkCoFix f = of_kind (CoFix f) let mkProj (p, r, c) = of_kind (Proj (p, r, c)) let mkArrow t1 r t2 = of_kind (Prod (make_annot Anonymous r, t1, t2)) let mkArrowR t1 t2 = mkArrow t1 ERelevance.relevant t2 let mkInt i = of_kind (Int i) let mkFloat f = of_kind (Float f) let mkString s = of_kind (String s) let mkArray (u,t,def,ty) = of_kind (Array (u,t,def,ty)) let mkRef (gr,u) = let open GlobRef in match gr with | ConstRef c -> mkConstU (c,u) | IndRef ind -> mkIndU (ind,u) | ConstructRef c -> mkConstructU (c,u) | VarRef x -> mkVar x let mkLEvar = Evd.MiniEConstr.mkLEvar let type1 = mkSort ESorts.type1 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 let isInd sigma c = match kind sigma c with Ind _ -> true | _ -> false let isEvar sigma c = match kind sigma c with Evar _ -> true | _ -> false let isMeta sigma c = match kind sigma c with Meta _ -> true | _ -> false let isSort sigma c = match kind sigma c with Sort _ -> true | _ -> false let isCast sigma c = match kind sigma c with Cast _ -> true | _ -> false let isApp sigma c = match kind sigma c with App _ -> true | _ -> false let isLambda sigma c = match kind sigma c with Lambda _ -> true | _ -> false let isLetIn sigma c = match kind sigma c with LetIn _ -> true | _ -> false let isProd sigma c = match kind sigma c with Prod _ -> true | _ -> false let isConst sigma c = match kind sigma c with Const _ -> true | _ -> false let isConstruct sigma c = match kind sigma c with Construct _ -> true | _ -> false let isFix sigma c = match kind sigma c with Fix _ -> true | _ -> false let isCoFix sigma c = match kind sigma c with CoFix _ -> true | _ -> false let isCase sigma c = match kind sigma c with Case _ -> true | _ -> false let isProj sigma c = match kind sigma c with Proj _ -> true | _ -> false let rec isType sigma c = match kind sigma c with | Sort s -> (match ESorts.kind sigma s with | Sorts.Type _ -> true | _ -> false ) | Cast (c,_,_) -> isType sigma c | _ -> false let isVarId sigma id c = match kind sigma c with Var id' -> Id.equal id id' | _ -> false let isRelN sigma n c = match kind sigma c with Rel n' -> Int.equal n n' | _ -> false let isRef sigma c = match kind sigma c with | Const _ | Ind _ | Construct _ | Var _ -> true | _ -> false let isRefX env sigma x c = let open GlobRef in match x, kind sigma c with | ConstRef c, Const (c', _) -> Environ.QConstant.equal env c c' | IndRef i, Ind (i', _) -> Environ.QInd.equal env i i' | ConstructRef i, Construct (i', _) -> Environ.QConstruct.equal env i i' | VarRef id, Var id' -> Id.equal id id' | _ -> false let is_lib_ref env sigma x c = match Rocqlib.lib_ref_opt x with | Some x -> isRefX env sigma x c | None -> false let destRel sigma c = match kind sigma c with | Rel p -> p | _ -> raise DestKO let destVar sigma c = match kind sigma c with | Var p -> p | _ -> raise DestKO let destInd sigma c = match kind sigma c with | Ind p -> p | _ -> raise DestKO let destEvar sigma c = match kind sigma c with | Evar p -> p | _ -> raise DestKO let destMeta sigma c = match kind sigma c with | Meta p -> p | _ -> raise DestKO let destSort sigma c = match kind sigma c with | Sort p -> p | _ -> raise DestKO let destCast sigma c = match kind sigma c with | Cast (c, k, t) -> (c, k, t) | _ -> raise DestKO let destApp sigma c = match kind sigma c with | App (f, a) -> (f, a) | _ -> raise DestKO let destLambda sigma c = match kind sigma c with | Lambda (na, t, c) -> (na, t, c) | _ -> raise DestKO let destLetIn sigma c = match kind sigma c with | LetIn (na, b, t, c) -> (na, b, t, c) | _ -> raise DestKO let destProd sigma c = match kind sigma c with | Prod (na, t, c) -> (na, t, c) | _ -> raise DestKO let destConst sigma c = match kind sigma c with | Const p -> p | _ -> raise DestKO let destConstruct sigma c = match kind sigma c with | Construct p -> p | _ -> raise DestKO let destFix sigma c = match kind sigma c with | Fix p -> p | _ -> raise DestKO let destCoFix sigma c = match kind sigma c with | CoFix p -> p | _ -> raise DestKO let destCase sigma c = match kind sigma c with | Case (ci, u, pms, t, iv, c, p) -> (ci, u, pms, t, iv, c, p) | _ -> raise DestKO let destProj sigma c = match kind sigma c with | Proj (p, r, c) -> (p, r, c) | _ -> raise DestKO let destRef sigma c = let open GlobRef in match kind sigma c with | Var x -> VarRef x, EInstance.empty | Const (c,u) -> ConstRef c, u | Ind (ind,u) -> IndRef ind, u | Construct (c,u) -> ConstructRef c, u | _ -> raise DestKO let decompose_app sigma c = match kind sigma c with | App (f,cl) -> (f, cl) | _ -> (c,[||]) let decompose_app_list sigma c = match kind sigma c with | App (f,cl) -> (f, Array.to_list cl) | _ -> (c,[]) let decompose_lambda sigma c = let rec lamdec_rec l c = match kind sigma c with | Lambda (x,t,c) -> lamdec_rec ((x,t)::l) c | Cast (c,_,_) -> lamdec_rec l c | _ -> l,c in lamdec_rec [] c let decompose_lambda_decls sigma c = let open Rel.Declaration in let rec lamdec_rec l c = match kind sigma c with | Lambda (x,t,c) -> lamdec_rec (Context.Rel.add (LocalAssum (x,t)) l) c | LetIn (x,b,t,c) -> lamdec_rec (Context.Rel.add (LocalDef (x,b,t)) l) c | Cast (c,_,_) -> lamdec_rec l c | _ -> l,c in lamdec_rec Context.Rel.empty c let decompose_lambda_n sigma n = if n < 0 then anomaly Pp.(str "decompose_lambda_n: integer parameter must be positive"); let rec lamdec_rec l n c = if Int.equal n 0 then (l, c) else match kind sigma c with | Lambda (x, t, c) -> lamdec_rec ((x, t) :: l) (n - 1) c | Cast (c, _, _) -> lamdec_rec l n c | _ -> anomaly Pp.(str "decompose_lambda_n: not enough abstractions") in lamdec_rec [] n let decompose_lambda_n_assum sigma n c = let open Rel.Declaration in if n < 0 then anomaly Pp.(str "decompose_lambda_n_assum: integer parameter must be positive."); let rec lamdec_rec l n c = if Int.equal n 0 then l,c else match kind sigma c with | Lambda (x,t,c) -> lamdec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c | LetIn (x,b,t,c) -> lamdec_rec (Context.Rel.add (LocalDef (x,b,t)) l) n c | Cast (c,_,_) -> lamdec_rec l n c | c -> anomaly Pp.(str "decompose_lambda_n_assum: not enough abstractions.") in lamdec_rec Context.Rel.empty n c let decompose_lambda_n_decls sigma n = let open Rel.Declaration in if n < 0 then anomaly Pp.(str "decompose_lambda_n_decls: integer parameter must be positive."); let rec lamdec_rec l n c = if Int.equal n 0 then l,c else match kind sigma c with | Lambda (x,t,c) -> lamdec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c | LetIn (x,b,t,c) -> lamdec_rec (Context.Rel.add (LocalDef (x,b,t)) l) (n-1) c | Cast (c,_,_) -> lamdec_rec l n c | c -> anomaly Pp.(str "decompose_lambda_n_decls: not enough abstractions.") in lamdec_rec Context.Rel.empty n let rec to_lambda sigma n prod = if Int.equal n 0 then prod else match kind sigma prod with | Prod (na,ty,bd) -> mkLambda (na,ty,to_lambda sigma (n-1) bd) | Cast (c,_,_) -> to_lambda sigma n c | _ -> anomaly Pp.(str "Not enough products.") let decompose_prod sigma c = let rec proddec_rec l c = match kind sigma c with | Prod (x,t,c) -> proddec_rec ((x,t)::l) c | Cast (c,_,_) -> proddec_rec l c | _ -> l,c in proddec_rec [] c let decompose_prod_n sigma n = if n < 0 then anomaly Pp.(str "decompose_prod_n: integer parameter must be positive"); let rec proddec_rec l n c = if Int.equal n 0 then (l, c) else match kind sigma c with | Prod (x, t, c) -> proddec_rec ((x, t) :: l) (n - 1) c | Cast (c, _, _) -> proddec_rec l n c | _ -> anomaly Pp.(str "decompose_prod_n: not enough products") in proddec_rec [] n let decompose_prod_decls sigma c = let open Rel.Declaration in let rec proddec_rec l c = match kind sigma c with | Prod (x,t,c) -> proddec_rec (Context.Rel.add (LocalAssum (x,t)) l) c | LetIn (x,b,t,c) -> proddec_rec (Context.Rel.add (LocalDef (x,b,t)) l) c | Cast (c,_,_) -> proddec_rec l c | _ -> l,c in proddec_rec Context.Rel.empty c let decompose_prod_n_decls sigma n c = let open Rel.Declaration in if n < 0 then anomaly Pp.(str "decompose_prod_n_decls: integer parameter must be positive."); let rec prodec_rec l n c = if Int.equal n 0 then l,c else match kind sigma c with | Prod (x,t,c) -> prodec_rec (Context.Rel.add (LocalAssum (x,t)) l) (n-1) c | LetIn (x,b,t,c) -> prodec_rec (Context.Rel.add (LocalDef (x,b,t)) l) (n-1) c | Cast (c,_,_) -> prodec_rec l n c | c -> anomaly Pp.(str "decompose_prod_n_decls: not enough assumptions.") in prodec_rec Context.Rel.empty n c let prod_decls sigma t = fst (decompose_prod_decls sigma t) let existential_type = Evd.existential_type let lift n c = of_constr (Vars.lift n (unsafe_to_constr c)) let of_branches : Constr.case_branch array -> case_branch array = match Evd.MiniEConstr.(unsafe_eq, unsafe_relevance_eq) with | Refl, Refl -> fun x -> x let unsafe_to_branches : case_branch array -> Constr.case_branch array = match Evd.MiniEConstr.(unsafe_eq, unsafe_relevance_eq) with | Refl, Refl -> fun x -> x let of_return : Constr.case_return -> case_return = match Evd.MiniEConstr.(unsafe_eq, unsafe_relevance_eq) with | Refl, Refl -> fun x -> x let unsafe_to_return : case_return -> Constr.case_return = match Evd.MiniEConstr.(unsafe_eq, unsafe_relevance_eq) with | Refl, Refl -> fun x -> x let of_binder_annot : 'a Constr.binder_annot -> 'a binder_annot = match Evd.MiniEConstr.unsafe_relevance_eq with | Refl -> fun x -> x let to_binder_annot sigma (x:_ binder_annot) : _ Constr.binder_annot = let Refl = unsafe_relevance_eq in Context.map_annot_relevance (ERelevance.kind sigma) x let to_rel_decl sigma (d:rel_declaration) : Constr.rel_declaration = let Refl = unsafe_eq in let Refl = unsafe_relevance_eq in Context.Rel.Declaration.map_constr_with_relevance (ERelevance.kind sigma) (to_constr sigma) d let to_rel_context sigma (ctx:rel_context) : Constr.rel_context = let Refl = unsafe_eq in let Refl = unsafe_relevance_eq in List.Smart.map (to_rel_decl sigma) ctx let to_named_decl sigma (d:named_declaration) : Constr.named_declaration = let Refl = unsafe_eq in let Refl = unsafe_relevance_eq in Context.Named.Declaration.map_constr_with_relevance (ERelevance.kind sigma) (to_constr sigma) d let to_named_context sigma (ctx:named_context) : Constr.named_context = let Refl = unsafe_eq in let Refl = unsafe_relevance_eq in List.Smart.map (to_named_decl sigma) ctx let map_branches f br = let f c = unsafe_to_constr (f (of_constr c)) in of_branches (Constr.map_branches f (unsafe_to_branches br)) let map_return_predicate f p = let f c = unsafe_to_constr (f (of_constr c)) in of_return (Constr.map_return_predicate f (unsafe_to_return p)) let map_instance sigma f evk args = let rec map ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (Some c, rem) -> let c' = f c in let rem' = map ctx rem in if c' == c && rem' == rem then args else if Constr.isVarId (NamedDecl.get_id decl) c' then SList.default rem' else SList.cons c' rem' | decl :: ctx, Some (None, rem) -> let c = Constr.mkVar (NamedDecl.get_id decl) in let c' = f c in let rem' = map ctx rem in if c' == c && rem' == rem then args else SList.cons c' rem' | [], Some _ | _ :: _, None -> assert false in let EvarInfo evi = Evd.find sigma evk in let ctx = Evd.evar_filtered_context evi in map ctx args let map sigma f c = let f c = unsafe_to_constr (f (of_constr c)) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar (evk, args) -> let args' = map_instance sigma f evk args in if args' == args then of_constr c else of_constr @@ Constr.mkEvar (evk, args') | _ -> of_constr (Constr.map f c) let map_with_binders sigma g f l c = let f l c = unsafe_to_constr (f l (of_constr c)) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar (evk, args) -> let args' = map_instance sigma (fun c -> f l c) evk args in if args' == args then of_constr c else of_constr @@ Constr.mkEvar (evk, args') | _ -> of_constr (Constr.map_with_binders g f l c) let map_existential sigma f ((evk, args) as ev : existential) = let f c = unsafe_to_constr (f (of_constr c)) in let args : Constr.t SList.t = match Evd.MiniEConstr.unsafe_eq with Refl -> args in let args' = map_instance sigma f evk args in if args' == args then ev else let args' : t SList.t = match Evd.MiniEConstr.unsafe_eq with Refl -> args' in (evk, args') let iter sigma f c = let f c = f (of_constr c) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar ((evk, _) as ev) -> let args = Evd.expand_existential0 sigma ev in List.iter (fun c -> f c) args | _ -> Constr.iter f c let expand_case env _sigma (ci, u, pms, p, iv, c, bl) = let u = EInstance.unsafe_to_instance u in let pms = unsafe_to_constr_array pms in let p = unsafe_to_return p in let iv = unsafe_to_case_invert iv in let c = unsafe_to_constr c in let bl = unsafe_to_branches bl in let (ci, (p,r), iv, c, bl) = Inductive.expand_case env (ci, u, pms, p, iv, c, bl) in let p = of_constr p in let r = ERelevance.make r in let c = of_constr c in let iv = of_case_invert iv in let bl = of_constr_array bl in (ci, (p,r), iv, c, bl) let annotate_case env sigma (ci, u, pms, p, iv, c, bl as case) = let (_, (p,r), _, _, bl) = expand_case env sigma case in let p = (* Too bad we need to fetch this data in the environment, should be in the case_info instead. *) let (_, mip) = Inductive.lookup_mind_specif env ci.ci_ind in decompose_lambda_n_decls sigma (mip.Declarations.mind_nrealdecls + 1) p in let mk_br c n = decompose_lambda_n_decls sigma n c in let bl = Array.map2 mk_br bl ci.ci_cstr_ndecls in (ci, u, pms, (p,r), iv, c, bl) let expand_branch env _sigma u pms (ind, i) (nas, _br) = let open Declarations in let u = EInstance.unsafe_to_instance u in let pms = unsafe_to_constr_array pms in let (mib, mip) = Inductive.lookup_mind_specif env ind in let paramdecl = Vars.subst_instance_context u mib.mind_params_ctxt in let paramsubst = Vars.subst_of_rel_context_instance paramdecl pms in let (ctx, _) = mip.mind_nf_lc.(i - 1) in let (ctx, _) = List.chop mip.mind_consnrealdecls.(i - 1) ctx in let nas = let gen : type a b. (a,b) eq -> (_,a) Context.pbinder_annot array -> (_,b) Context.pbinder_annot array = fun Refl x -> x in gen unsafe_relevance_eq nas in let ans = Inductive.instantiate_context u paramsubst nas ctx in let ans : rel_context = match Evd.MiniEConstr.(unsafe_eq, unsafe_relevance_eq) with | Refl, Refl -> ans in ans let contract_case env _sigma (ci, (p,r), iv, c, bl) = let p = unsafe_to_constr p in let r = ERelevance.unsafe_to_relevance r in let iv = unsafe_to_case_invert iv in let c = unsafe_to_constr c in let bl = unsafe_to_constr_array bl in let (ci, u, pms, p, iv, c, bl) = Inductive.contract_case env (ci, (p,r), iv, c, bl) in let u = EInstance.make u in let pms = of_constr_array pms in let p = of_return p in let iv = of_case_invert iv in let c = of_constr c in let bl = of_branches bl in (ci, u, pms, p, iv, c, bl) let iter_with_full_binders env sigma g f n c = let open Context.Rel.Declaration in match kind sigma c with | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _) -> () | 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 | LetIn (na,b,t,c) -> f n b; f n t; f (g (LocalDef (na, b, t)) n) c | App (c,l) -> f n c; Array.Fun1.iter f n l | Evar ((_,l) as ev) -> let l = Evd.expand_existential sigma ev in List.iter (fun c -> f n c) l | Case (ci,u,pms,p,iv,c,bl) -> let (ci, _, pms, (p,_), iv, c, bl) = annotate_case env sigma (ci, u, pms, p, iv, c, bl) in let f_ctx (ctx, c) = f (List.fold_right g ctx n) c in Array.Fun1.iter f n pms; f_ctx p; iter_invert (f n) iv; f n c; Array.iter f_ctx bl | Proj (_,_,c) -> f n c | Fix (_,(lna,tl,bl)) -> Array.iter (f n) tl; let n' = Array.fold_left2_i (fun i n na t -> g (LocalAssum (na, lift i t)) n) n lna tl in Array.iter (f n') bl | CoFix (_,(lna,tl,bl)) -> Array.iter (f n) tl; let n' = Array.fold_left2_i (fun i n na t -> g (LocalAssum (na,lift i t)) n) n lna tl in Array.iter (f n') bl | Array (_u,t,def,ty) -> Array.Fun1.iter f n t; f n def; f n ty let iter_with_binders sigma g f n c = let f l c = f l (of_constr c) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar ((evk, _) as ev) -> let args = Evd.expand_existential0 sigma ev in List.iter (fun c -> f n c) args | _ -> Constr.iter_with_binders g f n c let fold sigma f acc c = let f acc c = f acc (of_constr c) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar ((evk, _) as ev) -> let args = Evd.expand_existential0 sigma ev in List.fold_left f acc args | _ -> Constr.fold f acc c let fold_with_binders sigma g f e acc c = let f e acc c = f e acc (of_constr c) in let c = unsafe_to_constr @@ whd_evar sigma c in match Constr.kind c with | Evar ((evk, _) as ev) -> let args = Evd.expand_existential0 sigma ev in List.fold_left (fun acc c -> f e acc c) acc args | _ -> Constr.fold_constr_with_binders g f e acc c let compare_gen k eq_inst eq_sort eq_constr eq_evars nargs c1 c2 = (c1 == c2) || Constr.compare_head_gen_with k k eq_inst eq_sort eq_constr eq_evars nargs c1 c2 let eq_existential sigma eq (evk1, args1) (evk2, args2) = if Evar.equal evk1 evk2 then let args1 = Evd.expand_existential sigma (evk1, args1) in let args2 = Evd.expand_existential sigma (evk2, args2) in List.equal eq args1 args2 else false let eq_constr sigma c1 c2 = let kind c = kind sigma c in let eq_inst _ i1 i2 = EInstance.equal sigma i1 i2 in let eq_sorts s1 s2 = ESorts.equal sigma s1 s2 in let eq_existential eq e1 e2 = eq_existential sigma (eq 0) e1 e2 in let rec eq_constr nargs c1 c2 = compare_gen kind eq_inst eq_sorts (eq_existential eq_constr) eq_constr nargs c1 c2 in eq_constr 0 c1 c2 let eq_constr_nounivs sigma c1 c2 = let kind c = kind sigma c in let eq_existential eq e1 e2 = eq_existential sigma (eq 0) e1 e2 in let rec eq_constr nargs c1 c2 = compare_gen kind (fun _ _ _ -> true) (fun _ _ -> true) (eq_existential eq_constr) eq_constr nargs c1 c2 in eq_constr 0 c1 c2 let compare_constr sigma cmp c1 c2 = let kind c = kind sigma c in let eq_inst _ i1 i2 = EInstance.equal sigma i1 i2 in let eq_sorts s1 s2 = ESorts.equal sigma s1 s2 in let eq_existential eq e1 e2 = eq_existential sigma (eq 0) e1 e2 in let cmp nargs c1 c2 = cmp c1 c2 in compare_gen kind eq_inst eq_sorts (eq_existential cmp) cmp 0 c1 c2 let cmp_inductives cv_pb (mind,ind as spec) nargs u1 u2 cstrs = let open UnivProblem in match mind.Declarations.mind_variance with | None -> enforce_eq_instances_univs false u1 u2 cstrs | Some variances -> let num_param_arity = Conversion.inductive_cumulativity_arguments spec in if not (Int.equal num_param_arity nargs) then enforce_eq_instances_univs false u1 u2 cstrs else compare_cumulative_instances cv_pb variances u1 u2 cstrs let cmp_constructors (mind, ind, cns as spec) nargs u1 u2 cstrs = let open UnivProblem in match mind.Declarations.mind_variance with | None -> enforce_eq_instances_univs false u1 u2 cstrs | Some _ -> let num_cnstr_args = Conversion.constructor_cumulativity_arguments spec in if not (Int.equal num_cnstr_args nargs) then enforce_eq_instances_univs false u1 u2 cstrs else let qs1, us1 = UVars.Instance.to_array u1 and qs2, us2 = UVars.Instance.to_array u2 in let cstrs = enforce_eq_qualities qs1 qs2 cstrs in Array.fold_left2 (fun cstrs u1 u2 -> UnivProblem.(Set.add (UWeak (u1,u2)) cstrs)) cstrs us1 us2 let eq_universes env sigma cstrs cv_pb refargs l l' = if EInstance.is_empty l then (assert (EInstance.is_empty l'); true) else let l = EInstance.kind sigma l and l' = EInstance.kind sigma l' in let open GlobRef in let open UnivProblem in match refargs with | Some (ConstRef c, 1) when Environ.is_array_type env c -> cstrs := compare_cumulative_instances cv_pb [|UVars.Variance.Irrelevant|] l l' !cstrs; true | None | Some (ConstRef _, _) -> cstrs := enforce_eq_instances_univs true l l' !cstrs; true | Some (VarRef _, _) -> assert false (* variables don't have instances *) | Some (IndRef ind, nargs) -> let mind = Environ.lookup_mind (fst ind) env in cstrs := cmp_inductives cv_pb (mind,snd ind) nargs l l' !cstrs; true | Some (ConstructRef ((mi,ind),ctor), nargs) -> let mind = Environ.lookup_mind mi env in cstrs := cmp_constructors (mind,ind,ctor) nargs l l' !cstrs; true let test_constr_universes env sigma leq ?(nargs=0) m n = let open UnivProblem in let kind c = kind sigma c in if m == n then Some Set.empty else let cstrs = ref Set.empty in let cv_pb = if leq then Conversion.CUMUL else Conversion.CONV in let eq_universes refargs l l' = eq_universes env sigma cstrs Conversion.CONV refargs l l' and leq_universes refargs l l' = eq_universes env sigma cstrs cv_pb refargs l l' in let eq_sorts s1 s2 = let s1 = ESorts.kind sigma s1 in let s2 = ESorts.kind sigma s2 in if Sorts.equal s1 s2 then true else (cstrs := Set.add (UEq (s1, s2)) !cstrs; true) in let leq_sorts s1 s2 = let s1 = ESorts.kind sigma s1 in let s2 = ESorts.kind sigma s2 in if Sorts.equal s1 s2 then true else (cstrs := Set.add (ULe (s1, s2)) !cstrs; true) in let eq_existential eq e1 e2 = eq_existential sigma (eq 0) e1 e2 in let rec eq_constr' nargs m n = compare_gen kind eq_universes eq_sorts (eq_existential eq_constr') eq_constr' nargs m n in let res = if leq then let rec compare_leq nargs m n = Constr.compare_head_gen_leq_with kind kind leq_universes leq_sorts (eq_existential eq_constr') eq_constr' leq_constr' nargs m n and leq_constr' nargs m n = m == n || compare_leq nargs m n in compare_leq nargs m n else Constr.compare_head_gen_with kind kind eq_universes eq_sorts (eq_existential eq_constr') eq_constr' nargs m n in if res then Some !cstrs else None let eq_constr_universes env sigma ?nargs m n = test_constr_universes env sigma false ?nargs m n let leq_constr_universes env sigma ?nargs m n = test_constr_universes env sigma true ?nargs m n let compare_head_gen_proj env sigma equ eqs eqev eqc' nargs m n = let kind c = kind sigma c in match kind m, kind n with | Proj (p, _, c), App (f, args) | App (f, args), Proj (p, _, c) -> (match kind f with | Const (p', u) when Environ.QConstant.equal env (Projection.constant p) p' -> let npars = Projection.npars p in if Array.length args == npars + 1 then eqc' 0 c args.(npars) else false | _ -> false) | _ -> Constr.compare_head_gen_with kind kind equ eqs eqev eqc' nargs m n let eq_constr_universes_proj env sigma m n = let open UnivProblem in if m == n then Some Set.empty else let cstrs = ref Set.empty in let eq_universes ref l l' = eq_universes env sigma cstrs Conversion.CONV ref l l' in let eq_sorts s1 s2 = let s1 = ESorts.kind sigma s1 in let s2 = ESorts.kind sigma s2 in if Sorts.equal s1 s2 then true else (cstrs := Set.add (UEq (s1, s2)) !cstrs; true) in let eq_existential eq e1 e2 = eq_existential sigma (eq 0) e1 e2 in let rec eq_constr' nargs m n = m == n || compare_head_gen_proj env sigma eq_universes eq_sorts (eq_existential eq_constr') eq_constr' nargs m n in let res = eq_constr' 0 m n in if res then Some !cstrs else None let add_universes_of_instance sigma (qs,us) u = let u = EInstance.kind sigma u in let qs', us' = UVars.Instance.levels u in let qs = Sorts.Quality.(Set.fold (fun q qs -> match q with | QVar q -> Sorts.QVar.Set.add q qs | QConstant _ -> qs) qs' qs) in qs, Univ.Level.Set.union us us' let add_relevance sigma (qs,us as v) r = let open Sorts in (* NB this normalizes above_prop to Relevant which makes it disappear *) match ERelevance.kind sigma r with | Irrelevant | Relevant -> v | RelevanceVar q -> QVar.Set.add q qs, us let univs_and_qvars_visitor sigma = let open Univ in let visit_sort (qs,us as acc) s = match ESorts.kind sigma s with | Sorts.Type u -> qs, Universe.levels ~init:us u | Sorts.QSort (q,u) -> Sorts.QVar.Set.add q qs, Universe.levels ~init:us u | Sorts.(SProp | Prop | Set) -> acc in let visit_instance acc u = add_universes_of_instance sigma acc u in let visit_relevance acc r = add_relevance sigma acc r in { Vars.visit_sort = visit_sort; visit_instance = visit_instance; visit_relevance = visit_relevance; } let universes_of_constr ?(init=Sorts.QVar.Set.empty,Univ.Level.Set.empty) sigma c = let visit = univs_and_qvars_visitor sigma in let rec aux s c = let kc = kind sigma c in let s = Vars.visit_kind_univs visit s kc in match kc with | Evar (k, args) -> let concl = Evd.evar_concl (Evd.find_undefined sigma k) in fold sigma aux (aux s concl) c | _ -> fold sigma aux s c in aux init c open Context open Environ let cast_list : type a b. (a,b) eq -> a list -> b list = fun Refl x -> x let cast_vect : type a b. (a,b) eq -> a array -> b array = fun Refl x -> x let cast_rel_decl : type a b c d. (a,b) eq -> (c,d) eq -> (a, a, c) Rel.Declaration.pt -> (b, b, d) Rel.Declaration.pt = fun Refl Refl x -> x let cast_rel_context : type a b c d. (a,b) eq -> (c,d) eq -> (a, a, c) Rel.pt -> (b, b, d) Rel.pt = fun Refl Refl x -> x let cast_rec_decl : type a b c d. (a,b) eq -> (c,d) eq -> (a, a, c) Constr.prec_declaration -> (b, b, d) Constr.prec_declaration = fun Refl Refl x -> x let cast_named_decl : type a b c d. (a,b) eq -> (c,d) eq -> (a, a, c) Named.Declaration.pt -> (b, b, d) Named.Declaration.pt = fun Refl Refl x -> x let cast_named_context : type a b c d. (a,b) eq -> (c,d) eq -> (a, a, c) Named.pt -> (b, b, d) Named.pt = fun Refl Refl x -> x module Vars = struct exception LocalOccur let to_constr = unsafe_to_constr let to_rel_decl = unsafe_to_rel_decl type instance = t array type instance_list = t list type substl = t list (** Operations that commute with evar-normalization *) let exliftn s c = of_constr (exliftn s (to_constr c)) let lift = lift let liftn n m c = of_constr (Vars.liftn n m (to_constr c)) let substnl subst n c = of_constr (Vars.substnl (cast_list unsafe_eq subst) n (to_constr c)) let substl subst c = of_constr (Vars.substl (cast_list unsafe_eq subst) (to_constr c)) let subst1 c r = of_constr (Vars.subst1 (to_constr c) (to_constr r)) let substnl_decl subst n d = of_rel_decl (Vars.substnl_decl (cast_list unsafe_eq subst) n (to_rel_decl d)) let substl_decl subst d = of_rel_decl (Vars.substl_decl (cast_list unsafe_eq subst) (to_rel_decl d)) let subst1_decl c d = of_rel_decl (Vars.subst1_decl (to_constr c) (to_rel_decl d)) type substituend = Vars.substituend let make_substituend c = Vars.make_substituend (unsafe_to_constr c) let lift_substituend n s = of_constr (Vars.lift_substituend n s) let replace_vars = replace_vars (* (subst_var str t) substitute (Var str) by (Rel 1) in t *) let subst_var sigma str t = replace_vars sigma [(str, mkRel 1)] t (* (subst_vars [id1;...;idn] t) substitute (Var idj) by (Rel j) in t *) let substn_vars sigma p vars c = let _,subst = List.fold_left (fun (n,l) var -> ((n+1),(var, mkRel n)::l)) (p,[]) vars in replace_vars sigma (List.rev subst) c let subst_vars sigma subst c = substn_vars sigma 1 subst c let subst_univs_level_constr subst c = of_constr (Vars.subst_univs_level_constr subst (to_constr c)) let subst_instance_context subst ctx = let subst = EInstance.unsafe_to_instance subst in cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.subst_instance_context subst (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let subst_instance_constr subst c = let subst = EInstance.unsafe_to_instance subst in of_constr (Vars.subst_instance_constr subst (to_constr c)) let subst_instance_relevance subst r = let subst = EInstance.unsafe_to_instance subst in let r = ERelevance.unsafe_to_relevance r in let r = UVars.subst_instance_relevance subst r in ERelevance.make r (** Operations that dot NOT commute with evar-normalization *) let noccurn sigma n term = let rec occur_rec n h c = let (h, knd) = Expand.kind sigma h c in match knd with | Rel m -> if Int.equal m n then raise LocalOccur | Evar (evk, l) -> let evi = Evd.find_undefined sigma evk in let l = Expand.expand_instance ~skip:true evi h l in SList.Skip.iter (fun c -> occur_rec n h c) l | _ -> Expand.iter_with_binders sigma succ occur_rec n h knd in let h, term = Expand.make term in try occur_rec n h term; true with LocalOccur -> false let noccur_between sigma n m term = let rec occur_rec n h c = let (h, knd) = Expand.kind sigma h c in match knd with | Rel p -> if n<=p && p let evi = Evd.find_undefined sigma evk in let l = Expand.expand_instance ~skip:true evi h l in SList.Skip.iter (fun c -> occur_rec n h c) l | _ -> Expand.iter_with_binders sigma succ occur_rec n h knd in let h, term = Expand.make term in try occur_rec n h term; true with LocalOccur -> false let closedn sigma n c = let rec closed_rec n h c = let (h, knd) = Expand.kind sigma h c in match knd with | Rel m -> if m>n then raise LocalOccur | Evar (evk, l) -> let evi = Evd.find_undefined sigma evk in let l = Expand.expand_instance ~skip:true evi h l in SList.Skip.iter (fun c -> closed_rec n h c) l | _ -> Expand.iter_with_binders sigma succ closed_rec n h knd in let h, c = Expand.make c in try closed_rec n h c; true with LocalOccur -> false let closed0 sigma c = closedn sigma 0 c let subst_of_rel_context_instance ctx subst = cast_list (sym unsafe_eq) (Vars.subst_of_rel_context_instance (cast_rel_context unsafe_eq unsafe_relevance_eq ctx) (cast_vect unsafe_eq subst)) let subst_of_rel_context_instance_list ctx subst = cast_list (sym unsafe_eq) (Vars.subst_of_rel_context_instance_list (cast_rel_context unsafe_eq unsafe_relevance_eq ctx) (cast_list unsafe_eq subst)) let liftn_rel_context n k ctx = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.liftn_rel_context n k (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let lift_rel_context n ctx = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.lift_rel_context n (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let substnl_rel_context subst n ctx = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.substnl_rel_context (cast_list unsafe_eq subst) n (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let substl_rel_context subst ctx = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.substl_rel_context (cast_list unsafe_eq subst) (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let smash_rel_context ctx = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (Vars.smash_rel_context (cast_rel_context unsafe_eq unsafe_relevance_eq ctx)) let esubst : (int -> 'a -> t) -> 'a Esubst.subs -> t -> t = match unsafe_eq with | Refl -> Vars.esubst end (* Constructs either [forall x:t, c] or [let x:=b:t in c] *) let mkProd_or_LetIn decl c = let open Context.Rel.Declaration in match decl with | LocalAssum (na,t) -> mkProd (na, t, c) | LocalDef (na,b,t) -> mkLetIn (na, b, t, c) (* Constructs either [forall x:t, c] or [c] in which [x] is replaced by [b] *) let mkProd_wo_LetIn decl c = let open Context.Rel.Declaration in match decl with | LocalAssum (na,t) -> mkProd (na, t, c) | LocalDef (_,b,_) -> Vars.subst1 b c let mkLambda_or_LetIn decl c = let open Context.Rel.Declaration in match decl with | LocalAssum (na,t) -> mkLambda (na, t, c) | LocalDef (na,b,t) -> mkLetIn (na, b, t, c) let mkLambda_wo_LetIn decl c = let open Context.Rel.Declaration in match decl with | LocalAssum (na,t) -> mkLambda (na, t, c) | LocalDef (_,b,_) -> Vars.subst1 b c let mkNamedProd sigma id typ c = mkProd (map_annot Name.mk_name id, typ, Vars.subst_var sigma id.binder_name c) let mkNamedLambda sigma id typ c = mkLambda (map_annot Name.mk_name id, typ, Vars.subst_var sigma id.binder_name c) let mkNamedLetIn sigma id c1 t c2 = mkLetIn (map_annot Name.mk_name id, c1, t, Vars.subst_var sigma id.binder_name c2) let mkNamedProd_or_LetIn sigma decl c = let open Context.Named.Declaration in match decl with | LocalAssum (id,t) -> mkNamedProd sigma id t c | LocalDef (id,b,t) -> mkNamedLetIn sigma id b t c let mkNamedLambda_or_LetIn sigma decl c = let open Context.Named.Declaration in match decl with | LocalAssum (id,t) -> mkNamedLambda sigma id t c | LocalDef (id,b,t) -> mkNamedLetIn sigma id b t c let mkNamedProd_wo_LetIn sigma decl c = let open Context.Named.Declaration in match decl with | LocalAssum (id,t) -> mkNamedProd sigma id t c | LocalDef (id,b,t) -> Vars.subst1 b c let it_mkProd init = List.fold_left (fun c (n,t) -> mkProd (n, t, c)) init let it_mkLambda init = List.fold_left (fun c (n,t) -> mkLambda (n, t, c)) init let it_mkProd_or_LetIn t ctx = List.fold_left (fun c d -> mkProd_or_LetIn d c) t ctx let it_mkLambda_or_LetIn t ctx = List.fold_left (fun c d -> mkLambda_or_LetIn d c) t ctx let it_mkProd_wo_LetIn t ctx = List.fold_left (fun c d -> mkProd_wo_LetIn d c) t ctx let it_mkLambda_wo_LetIn t ctx = List.fold_left (fun c d -> mkLambda_wo_LetIn d c) t ctx let it_mkNamedProd_or_LetIn sigma t ctx = List.fold_left (fun c d -> mkNamedProd_or_LetIn sigma d c) t ctx let it_mkNamedLambda_or_LetIn sigma t ctx = List.fold_left (fun c d -> mkNamedLambda_or_LetIn sigma d c) t ctx let it_mkNamedProd_wo_LetIn sigma t ctx = List.fold_left (fun c d -> mkNamedProd_wo_LetIn sigma d c) t ctx let rec isArity sigma c = match kind sigma c with | Prod (_,_,c) -> isArity sigma c | LetIn (_,_,_,c) -> isArity sigma c | Cast (c,_,_) -> isArity sigma c | Sort _ -> true | _ -> false type arity = rel_context * ESorts.t let mkArity (ctx, s) = it_mkProd_or_LetIn (mkSort s) ctx let destArity sigma = let open Context.Rel.Declaration in let rec prodec_rec l c = match kind sigma c with | Prod (x,t,c) -> prodec_rec (LocalAssum (x,t) :: l) c | LetIn (x,b,t,c) -> prodec_rec (LocalDef (x,b,t) :: l) c | Cast (c,_,_) -> prodec_rec l c | Sort s -> l,s | _ -> anomaly ~label:"destArity" (Pp.str "not an arity.") in prodec_rec [] let push_rel d e = push_rel (cast_rel_decl unsafe_eq unsafe_relevance_eq d) e let push_rel_context d e = push_rel_context (cast_rel_context unsafe_eq unsafe_relevance_eq d) e let push_rec_types d e = push_rec_types (cast_rec_decl unsafe_eq unsafe_relevance_eq d) e let push_named d e = push_named (cast_named_decl unsafe_eq unsafe_relevance_eq d) e let push_named_context d e = push_named_context (cast_named_context unsafe_eq unsafe_relevance_eq d) e let push_named_context_val d e = push_named_context_val (cast_named_decl unsafe_eq unsafe_relevance_eq d) e let rel_context e = cast_rel_context (sym unsafe_eq) (sym unsafe_relevance_eq) (rel_context e) let named_context e = cast_named_context (sym unsafe_eq) (sym unsafe_relevance_eq) (named_context e) let val_of_named_context e = val_of_named_context (cast_named_context unsafe_eq unsafe_relevance_eq e) let named_context_of_val e = cast_named_context (sym unsafe_eq) (sym unsafe_relevance_eq) (named_context_of_val e) let of_existential : Constr.existential -> existential = let gen : type a b. (a,b) eq -> 'c * b SList.t -> 'c * a SList.t = fun Refl x -> x in gen unsafe_eq let lookup_rel i e = cast_rel_decl (sym unsafe_eq) (sym unsafe_relevance_eq) (lookup_rel i e) let lookup_named n e = cast_named_decl (sym unsafe_eq) (sym unsafe_relevance_eq) (lookup_named n e) let lookup_named_val n e = cast_named_decl (sym unsafe_eq) (sym unsafe_relevance_eq) (lookup_named_ctxt n e) let map_rel_context_in_env f env sign = let rec aux env acc = function | d::sign -> aux (push_rel d env) (Context.Rel.Declaration.map_constr (f env) d :: acc) sign | [] -> acc in aux env [] (List.rev sign) let match_named_context_val : named_context_val -> (named_declaration * named_context_val) option = match unsafe_eq, unsafe_relevance_eq with | Refl, Refl -> match_named_context_val let identity_subst_val : named_context_val -> t SList.t = fun ctx -> SList.defaultn (List.length ctx.Environ.env_named_ctx) SList.empty let fresh_global ?loc ?rigid ?names env sigma reference = let (evd,t) = Evd.fresh_global ?loc ?rigid ?names env sigma reference in evd, t let lookup_constant = Evd.MiniEConstr.lookup_constant let constant_value_in env sigma (kn, u) = let u = EInstance.unsafe_to_instance u in let cb = lookup_constant env sigma kn in match cb.const_body with | Def l_body -> of_constr (CVars.subst_instance_constr u l_body) | OpaqueDef _ -> raise (NotEvaluableConst Opaque) | Undef _ -> raise (NotEvaluableConst NoBody) | Primitive p -> raise (NotEvaluableConst (IsPrimitive (u ,p))) | Symbol b -> let r = Environ.lookup_rewrite_rules kn env in raise (NotEvaluableConst (HasRules (u, b, r))) (** Kind of type *) type kind_of_type = | SortType of ESorts.t | CastType of types * t | ProdType of Name.t binder_annot * t * t | LetInType of Name.t binder_annot * t * t * t | AtomicType of t * t array let kind_of_type sigma t = match kind sigma t with | Sort s -> SortType s | Cast (c,_,t) -> CastType (c, t) | Prod (na,t,c) -> ProdType (na, t, c) | LetIn (na,b,t,c) -> LetInType (na, b, t, c) | App (c,l) -> AtomicType (c, l) | (Rel _ | Meta _ | Var _ | Evar _ | Const _ | Proj _ | Case _ | Fix _ | CoFix _ | Ind _) -> AtomicType (t,[||]) | (Lambda _ | Construct _ | Int _ | Float _ | String _ | Array _) -> failwith "Not a type" module Unsafe = struct let to_relevance = ERelevance.unsafe_to_relevance let to_sorts = ESorts.unsafe_to_sorts let to_instance = EInstance.unsafe_to_instance let to_constr = unsafe_to_constr let to_constr_array = unsafe_to_constr_array let to_binder_annot : 'a binder_annot -> 'a Constr.binder_annot = match unsafe_relevance_eq with Refl -> fun x -> x let to_rel_decl = unsafe_to_rel_decl let to_named_decl = unsafe_to_named_decl let to_named_context = let gen : type a b c d. (a, b) eq -> (c,d) eq -> (a,a,c) Context.Named.pt -> (b,b,d) Context.Named.pt = fun Refl Refl x -> x in gen unsafe_eq unsafe_relevance_eq let to_rel_context = let gen : type a b c d. (a, b) eq -> (c,d) eq -> (a,a,c) Context.Rel.pt -> (b,b,d) Context.Rel.pt = fun Refl Refl x -> x in gen unsafe_eq unsafe_relevance_eq let to_case_invert = unsafe_to_case_invert let eq = unsafe_eq let relevance_eq = unsafe_relevance_eq end module UnsafeMonomorphic = struct let mkConst c = of_kind (Const (in_punivs c)) let mkInd i = of_kind (Ind (in_punivs i)) let mkConstruct c = of_kind (Construct (in_punivs c)) end include UnsafeMonomorphic rocq-9.2.0/engine/eConstr.mli000066400000000000000000000516021516144147600160700ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t val kind : Evd.evar_map -> t -> Sorts.relevance val equal : Evd.evar_map -> t -> t -> bool val relevant : t val irrelevant : t val is_irrelevant : Evd.evar_map -> t -> bool end module ESorts : sig type t = Evd.esorts (** Type of sorts up-to universe unification. Essentially a wrapper around Sorts.t so that normalization is ensured statically. *) val make : Sorts.t -> t (** Turn a sort into an up-to sort. *) val kind : Evd.evar_map -> t -> Sorts.t (** Returns the view into the current sort. Note that the kind of a variable may change if the unification state of the evar map changes. *) val equal : Evd.evar_map -> t -> t -> bool val is_small : Evd.evar_map -> t -> bool val is_prop : Evd.evar_map -> t -> bool val is_sprop : Evd.evar_map -> t -> bool val is_set : Evd.evar_map -> t -> bool val prop : t val sprop : t val set : t val type1 : t val super : Evd.evar_map -> t -> t val relevance_of_sort : t -> ERelevance.t val quality : Evd.evar_map -> t -> Sorts.Quality.t val quality_or_set : Evd.evar_map -> t -> UnivGen.QualityOrSet.t end module EInstance : sig type t = Evd.einstance (** Type of universe instances up-to universe unification. Similar to [ESorts.t] for [UVars.Instance.t]. *) val make : UVars.Instance.t -> t val kind : Evd.evar_map -> t -> UVars.Instance.t val empty : t val is_empty : t -> bool val length : t -> int * int end type types = t type constr = t type existential = t pexistential type case_return = (t,ERelevance.t) pcase_return type case_branch = (t,ERelevance.t) pcase_branch type rec_declaration = (t, t, ERelevance.t) prec_declaration type fixpoint = (t, t, ERelevance.t) pfixpoint type cofixpoint = (t, t, ERelevance.t) pcofixpoint type unsafe_judgment = (constr, types) Environ.punsafe_judgment type unsafe_type_judgment = (types, Evd.esorts) Environ.punsafe_type_judgment type named_declaration = (constr, types, ERelevance.t) Context.Named.Declaration.pt type rel_declaration = (constr, types, ERelevance.t) Context.Rel.Declaration.pt type compacted_declaration = (constr, types, ERelevance.t) Context.Compacted.Declaration.pt type named_context = (constr, types, ERelevance.t) Context.Named.pt type compacted_context = compacted_declaration list type rel_context = (constr, types, ERelevance.t) Context.Rel.pt type 'a binder_annot = ('a,ERelevance.t) Context.pbinder_annot val annotR : 'a -> 'a binder_annot val nameR : Id.t -> Name.t binder_annot val anonR : Name.t binder_annot type case_invert = t pcase_invert type case = (t, t, EInstance.t, ERelevance.t) pcase type 'a puniverses = 'a * EInstance.t (** {5 Destructors} *) val kind : Evd.evar_map -> t -> (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term (** Same as {!Constr.kind} except that it expands evars and normalizes universes on the fly. *) val kind_upto : Evd.evar_map -> Constr.t -> (Constr.t, Constr.t, Sorts.t, UVars.Instance.t, Sorts.relevance) Constr.kind_of_term val to_constr : ?abort_on_undefined_evars:bool -> Evd.evar_map -> t -> Constr.t (** Returns the evar-normal form of the argument. Note that this function is supposed to be called when the original term has not more free-evars anymore. If you need compatibility with the old semantics, set [abort_on_undefined_evars] to [false]. For getting the evar-normal form of a term with evars see {!Evarutil.nf_evar}. *) val to_constr_opt : Evd.evar_map -> t -> Constr.t option (** Same as [to_constr], but returns [None] if some unresolved evars remain *) type kind_of_type = | SortType of ESorts.t | CastType of types * t | ProdType of Name.t binder_annot * t * t | LetInType of Name.t binder_annot * t * t * t | AtomicType of t * t array val kind_of_type : Evd.evar_map -> t -> kind_of_type (** {5 Constructors} *) val of_kind : (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term -> t (** Construct a term from a view. *) val of_constr : Constr.t -> t (** Translate a kernel term into an incomplete term in O(1). *) (** {5 Insensitive primitives} Evar-insensitive versions of the corresponding functions. See the {!Constr} module for more information. *) (** {6 Constructors} *) val mkRel : int -> t val mkVar : Id.t -> t val mkMeta : metavariable -> t val mkEvar : t pexistential -> t val mkSort : ESorts.t -> t val mkSProp : t val mkProp : t val mkSet : t val mkType : Univ.Universe.t -> t val mkCast : t * cast_kind * t -> t val mkProd : Name.t binder_annot * t * t -> t val mkLambda : Name.t binder_annot * t * t -> t val mkLetIn : Name.t binder_annot * t * t * t -> t val mkApp : t * t array -> t val mkConstU : Constant.t * EInstance.t -> t val mkProj : (Projection.t * ERelevance.t * t) -> t val mkIndU : inductive * EInstance.t -> t val mkConstructU : constructor * EInstance.t -> t val mkConstructUi : (inductive * EInstance.t) * int -> t val mkCase : case -> t val mkFix : (t, t, ERelevance.t) pfixpoint -> t val mkCoFix : (t, t, ERelevance.t) pcofixpoint -> t val mkArrow : t -> ERelevance.t -> t -> t val mkArrowR : t -> t -> t val mkInt : Uint63.t -> t val mkFloat : Float64.t -> t val mkString : Pstring.t -> t val mkArray : EInstance.t * t array * t * t -> t module UnsafeMonomorphic : sig val mkConst : Constant.t -> t val mkInd : inductive -> t val mkConstruct : constructor -> t end val mkRef : GlobRef.t * EInstance.t -> t val type1 : t val applist : t * t list -> t val applistc : t -> t list -> t (** { Abstracting/generalizing over binders } *) (** it = iterated or_LetIn = turn a local definition into a LetIn wo_LetIn = inlines local definitions (i.e. substitute them in the body) Named = binding is by name and the combinators turn it into a binding by index (complexity is nb(binders) * size(term)) *) val it_mkProd : t -> (Name.t binder_annot * t) list -> t val it_mkLambda : t -> (Name.t binder_annot * t) list -> t val mkProd_or_LetIn : rel_declaration -> t -> t val mkLambda_or_LetIn : rel_declaration -> t -> t val it_mkProd_or_LetIn : t -> rel_context -> t val it_mkLambda_or_LetIn : t -> rel_context -> t val mkProd_wo_LetIn : rel_declaration -> t -> t val mkLambda_wo_LetIn : rel_declaration -> t -> t val it_mkProd_wo_LetIn : t -> rel_context -> t val it_mkLambda_wo_LetIn : t -> rel_context -> t val mkNamedProd : Evd.evar_map -> Id.t binder_annot -> types -> types -> types val mkNamedLambda : Evd.evar_map -> Id.t binder_annot -> types -> constr -> constr val mkNamedLetIn : Evd.evar_map -> Id.t binder_annot -> constr -> types -> constr -> constr val mkNamedProd_or_LetIn : Evd.evar_map -> named_declaration -> types -> types val mkNamedLambda_or_LetIn : Evd.evar_map -> named_declaration -> types -> types val it_mkNamedProd_or_LetIn : Evd.evar_map -> t -> named_context -> t val it_mkNamedLambda_or_LetIn : Evd.evar_map -> t -> named_context -> t val mkNamedProd_wo_LetIn : Evd.evar_map -> named_declaration -> t -> t val it_mkNamedProd_wo_LetIn : Evd.evar_map -> t -> named_context -> t val mkLEvar : Evd.evar_map -> Evar.t * t list -> t (** Variant of {!mkEvar} that removes identity variable instances from its argument. *) (** {6 Simple case analysis} *) val isRel : Evd.evar_map -> t -> bool val isVar : Evd.evar_map -> t -> bool val isInd : Evd.evar_map -> t -> bool val isRef : Evd.evar_map -> t -> bool val isEvar : Evd.evar_map -> t -> bool val isMeta : Evd.evar_map -> t -> bool val isSort : Evd.evar_map -> t -> bool val isCast : Evd.evar_map -> t -> bool val isApp : Evd.evar_map -> t -> bool val isLambda : Evd.evar_map -> t -> bool val isLetIn : Evd.evar_map -> t -> bool val isProd : Evd.evar_map -> t -> bool val isConst : Evd.evar_map -> t -> bool val isConstruct : Evd.evar_map -> t -> bool val isFix : Evd.evar_map -> t -> bool val isCoFix : Evd.evar_map -> t -> bool val isCase : Evd.evar_map -> t -> bool val isProj : Evd.evar_map -> t -> bool val isType : Evd.evar_map -> constr -> bool type arity = rel_context * ESorts.t val mkArity : arity -> types val destArity : Evd.evar_map -> types -> arity val isArity : Evd.evar_map -> t -> bool val isVarId : Evd.evar_map -> Id.t -> t -> bool val isRelN : Evd.evar_map -> int -> t -> bool val isRefX : Environ.env -> Evd.evar_map -> GlobRef.t -> t -> bool (** The string is interpreted by [Rocqlib.lib_ref]. If it is not registered, return [false]. *) val is_lib_ref : Environ.env -> Evd.evar_map -> string -> t -> bool val destRel : Evd.evar_map -> t -> int val destMeta : Evd.evar_map -> t -> metavariable val destVar : Evd.evar_map -> t -> Id.t val destSort : Evd.evar_map -> t -> ESorts.t val destCast : Evd.evar_map -> t -> t * cast_kind * t val destProd : Evd.evar_map -> t -> Name.t binder_annot * types * types val destLambda : Evd.evar_map -> t -> Name.t binder_annot * types * t val destLetIn : Evd.evar_map -> t -> Name.t binder_annot * t * types * t val destApp : Evd.evar_map -> t -> t * t array val destConst : Evd.evar_map -> t -> Constant.t * EInstance.t val destEvar : Evd.evar_map -> t -> t pexistential val destInd : Evd.evar_map -> t -> inductive * EInstance.t val destConstruct : Evd.evar_map -> t -> constructor * EInstance.t val destCase : Evd.evar_map -> t -> case val destProj : Evd.evar_map -> t -> Projection.t * ERelevance.t * t val destFix : Evd.evar_map -> t -> (t, t, ERelevance.t) pfixpoint val destCoFix : Evd.evar_map -> t -> (t, t, ERelevance.t) pcofixpoint val destRef : Evd.evar_map -> t -> GlobRef.t * EInstance.t val decompose_app : Evd.evar_map -> t -> t * t array val decompose_app_list : Evd.evar_map -> t -> t * t list (** Pops lambda abstractions until there are no more, skipping casts. *) val decompose_lambda : Evd.evar_map -> t -> (Name.t binder_annot * t) list * t (** Pops lambda abstractions and letins until there are no more, skipping casts. *) val decompose_lambda_decls : Evd.evar_map -> t -> rel_context * t (** Pops [n] lambda abstractions, skipping casts. @raise UserError if the term doesn't have enough lambdas. *) val decompose_lambda_n : Evd.evar_map -> int -> t -> (Name.t binder_annot * t) list * t (** Pops [n] lambda abstractions, and pop letins only if needed to expose enough lambdas, skipping casts. @raise UserError if the term doesn't have enough lambdas. *) val decompose_lambda_n_assum : Evd.evar_map -> int -> t -> rel_context * t (** Pops [n] lambda abstractions and letins, skipping casts. @raise UserError if the term doesn't have enough lambdas/letins. *) val decompose_lambda_n_decls : Evd.evar_map -> int -> t -> rel_context * t val prod_decls : Evd.evar_map -> t -> rel_context val to_lambda : Evd.evar_map -> int -> t -> t val decompose_prod : Evd.evar_map -> t -> (Name.t binder_annot * t) list * t val decompose_prod_n : Evd.evar_map -> int -> t -> (Name.t binder_annot * t) list * t val decompose_prod_decls : Evd.evar_map -> t -> rel_context * t val decompose_prod_n_decls : Evd.evar_map -> int -> t -> rel_context * t val existential_type : Evd.evar_map -> existential -> types val whd_evar : Evd.evar_map -> constr -> constr (** {6 Equality} *) val eq_constr : Evd.evar_map -> t -> t -> bool val eq_constr_nounivs : Evd.evar_map -> t -> t -> bool val eq_constr_universes : Environ.env -> Evd.evar_map -> ?nargs:int -> t -> t -> UnivProblem.Set.t option (** Does not produce QLeq nor QElimTo constraints *) val leq_constr_universes : Environ.env -> Evd.evar_map -> ?nargs:int -> t -> t -> UnivProblem.Set.t option val eq_existential : Evd.evar_map -> (t -> t -> bool) -> existential -> existential -> bool (** [eq_constr_universes_proj] can equate projections and their eta-expanded constant form. *) val eq_constr_universes_proj : Environ.env -> Evd.evar_map -> t -> t -> UnivProblem.Set.t option val compare_constr : Evd.evar_map -> (t -> t -> bool) -> t -> t -> bool (** {6 Iterators} *) val map : Evd.evar_map -> (t -> t) -> t -> t val map_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> t -> t) -> 'a -> t -> t val map_branches : (t -> t) -> case_branch array -> case_branch array val map_return_predicate : (t -> t) -> case_return -> case_return val map_existential : Evd.evar_map -> (t -> t) -> existential -> existential val iter : Evd.evar_map -> (t -> unit) -> t -> unit val iter_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> t -> unit) -> 'a -> t -> unit val iter_with_full_binders : Environ.env -> Evd.evar_map -> (rel_declaration -> 'a -> 'a) -> ('a -> t -> unit) -> 'a -> t -> unit val fold : Evd.evar_map -> ('a -> t -> 'a) -> 'a -> t -> 'a val fold_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> 'b -> t -> 'b) -> 'a -> 'b -> t -> 'b (** Gather the universes transitively used in the term, including in the type of evars appearing in it. *) val universes_of_constr : ?init:Sorts.QVar.Set.t * Univ.Level.Set.t -> Evd.evar_map -> t -> Sorts.QVar.Set.t * Univ.Level.Set.t (** {6 Substitutions} *) module Vars : sig (** See vars.mli for the documentation of the functions below *) type instance = t array type instance_list = t list type substl = t list val exliftn : Esubst.lift -> t -> t val lift : int -> t -> t val liftn : int -> int -> t -> t val substnl : substl -> int -> t -> t val substl : substl -> t -> t val subst1 : t -> t -> t val substnl_decl : substl -> int -> rel_declaration -> rel_declaration val substl_decl : substl -> rel_declaration -> rel_declaration val subst1_decl : t -> rel_declaration -> rel_declaration val replace_vars : Evd.evar_map -> (Id.t * t) list -> t -> t val substn_vars : Evd.evar_map -> int -> Id.t list -> t -> t val subst_vars : Evd.evar_map -> Id.t list -> t -> t val subst_var : Evd.evar_map -> Id.t -> t -> t val noccurn : Evd.evar_map -> int -> t -> bool val noccur_between : Evd.evar_map -> int -> int -> t -> bool val closedn : Evd.evar_map -> int -> t -> bool val closed0 : Evd.evar_map -> t -> bool val subst_univs_level_constr : UVars.sort_level_subst -> t -> t val subst_instance_context : EInstance.t -> rel_context -> rel_context val subst_instance_constr : EInstance.t -> t -> t val subst_instance_relevance : EInstance.t -> ERelevance.t -> ERelevance.t val subst_of_rel_context_instance : rel_context -> instance -> substl val subst_of_rel_context_instance_list : rel_context -> instance_list -> substl val liftn_rel_context : int -> int -> rel_context -> rel_context val lift_rel_context : int -> rel_context -> rel_context val substnl_rel_context : substl -> int -> rel_context -> rel_context val substl_rel_context : substl -> rel_context -> rel_context val smash_rel_context : rel_context -> rel_context val esubst : (int -> 'a -> t) -> 'a Esubst.subs -> t -> t type substituend val make_substituend : t -> substituend val lift_substituend : int -> substituend -> t end (** {5 Environment handling} *) val push_rel : rel_declaration -> env -> env val push_rel_context : rel_context -> env -> env val push_rec_types : rec_declaration -> env -> env val push_named : named_declaration -> env -> env val push_named_context : named_context -> env -> env val push_named_context_val : named_declaration -> named_context_val -> named_context_val val rel_context : env -> rel_context val named_context : env -> named_context val val_of_named_context : named_context -> named_context_val val named_context_of_val : named_context_val -> named_context val lookup_rel : int -> env -> rel_declaration val lookup_named : variable -> env -> named_declaration val lookup_named_val : variable -> named_context_val -> named_declaration val lookup_constant : env -> Evd.evar_map -> Constant.t -> Declarations.constant_body val constant_value_in : env -> Evd.evar_map -> Constant.t * EInstance.t -> constr val map_rel_context_in_env : (env -> constr -> constr) -> env -> rel_context -> rel_context val match_named_context_val : named_context_val -> (named_declaration * named_context_val) option val identity_subst_val : named_context_val -> t SList.t (* XXX Missing Sigma proxy *) val fresh_global : ?loc:Loc.t -> ?rigid:Evd.rigid -> ?names:EInstance.t -> Environ.env -> Evd.evar_map -> GlobRef.t -> Evd.evar_map * t val expand_case : Environ.env -> Evd.evar_map -> case -> (t,t,ERelevance.t) Inductive.pexpanded_case val annotate_case : Environ.env -> Evd.evar_map -> case -> case_info * EInstance.t * t array * ((rel_context * t) * ERelevance.t) * case_invert * t * (rel_context * t) array (** Same as above, but doesn't turn contexts into binders *) val expand_branch : Environ.env -> Evd.evar_map -> EInstance.t -> t array -> constructor -> case_branch -> rel_context (** Given a universe instance and parameters for the inductive type, constructs the typed context in which the branch lives. *) val contract_case : Environ.env -> Evd.evar_map -> (t,t,ERelevance.t) Inductive.pexpanded_case -> case (** {5 Extra} *) val of_existential : Constr.existential -> existential val of_named_decl : Constr.named_declaration -> named_declaration val of_rel_decl : Constr.rel_declaration -> rel_declaration val to_rel_decl : Evd.evar_map -> rel_declaration -> Constr.rel_declaration val to_named_decl : Evd.evar_map -> named_declaration -> Constr.named_declaration val of_named_context : Constr.named_context -> named_context val of_rel_context : Constr.rel_context -> rel_context val to_named_context : Evd.evar_map -> named_context -> Constr.named_context val to_rel_context : Evd.evar_map -> rel_context -> Constr.rel_context val of_case_invert : Constr.case_invert -> case_invert val of_constr_array : Constr.t array -> t array val of_binder_annot : 'a Constr.binder_annot -> 'a binder_annot val to_binder_annot : Evd.evar_map -> 'a binder_annot -> 'a Constr.binder_annot (** {5 Unsafe operations} *) module Unsafe : sig val to_constr : t -> Constr.t (** Physical identity. Does not care for defined evars. *) val to_constr_array : t array -> Constr.t array (** Physical identity. Does not care for defined evars. *) val to_binder_annot : 'a binder_annot -> 'a Constr.binder_annot val to_rel_decl : (t, types, ERelevance.t) Context.Rel.Declaration.pt -> (Constr.t, Constr.types, Sorts.relevance) Context.Rel.Declaration.pt (** Physical identity. Does not care for defined evars. *) val to_named_decl : (t, types, ERelevance.t) Context.Named.Declaration.pt -> (Constr.t, Constr.types, Sorts.relevance) Context.Named.Declaration.pt (** Physical identity. Does not care for defined evars. *) val to_named_context : (t, types, ERelevance.t) Context.Named.pt -> Constr.named_context val to_rel_context : (t, types, ERelevance.t) Context.Rel.pt -> Constr.rel_context val to_relevance : ERelevance.t -> Sorts.relevance val to_sorts : ESorts.t -> Sorts.t (** Physical identity. Does not care for normalization. *) val to_instance : EInstance.t -> UVars.Instance.t (** Physical identity. Does not care for normalization. *) val to_case_invert : case_invert -> Constr.case_invert val eq : (t, Constr.t) eq (** Use for transparent cast between types. *) val relevance_eq : (ERelevance.t, Sorts.relevance) eq end (** {5 Delayed evar expansion} *) module Expand : sig type t (** A variant of [EConstr.t] where evar substitution is performed on the fly. The [handle] type below is a kind of substitution that is needed to make sense of the delayed term. Such representation is more efficient than [EConstr.t] when iterating over a whole term. Caveat: the [kind] function below only returns the expanded head of the term. This means that when it returns [Evar (evk, inst)], [evk] is guaranteed to be undefined in the evar map but [inst] is, in general, not the same as you would get after expansion. You must call [expand_instance] before performing any operation on it. *) type kind = (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term type handle val make : Evd.econstr -> handle * t val repr : Evd.evar_map -> handle -> t -> Evd.econstr val liftn_handle : int -> handle -> handle val kind : Evd.evar_map -> handle -> t -> handle * kind val expand_instance : skip:bool -> Evd.undefined Evd.evar_info -> handle -> t SList.t -> t SList.t val iter : Evd.evar_map -> (handle -> t -> unit) -> handle -> kind -> unit val iter_with_binders : Evd.evar_map -> ('a -> 'a) -> ('a -> handle -> t -> unit) -> 'a -> handle -> kind -> unit end rocq-9.2.0/engine/evar_kinds.ml000066400000000000000000000043401516144147600164240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t val repr : t -> Libnames.full_path end = struct type t = { basename: Id.t; path: Id.t list } let make path = let (dp, id) = Libnames.repr_qualid path in { basename = id; path = DirPath.repr dp } let repr { basename; path } = Libnames.make_path (DirPath.make path) basename end (** Module for evar name resolution, using a reversed trie. Example: given evars "true.A" (?X1), "true.A" (?X2) and "false.A" (?X3), we have the following trie: [ { A -> { true (?X1, ?X2), false (?X3) } } ] In this representation, determining whether a qualified name is unambiguous amounts to checking whether the node has a single value. For example, "A" does not resolve to an evar, "true.A" is ambiguous (?X1, ?X2), while "false.A" (?X3) is unambiguous. *) module NameResolution : sig type t (** Returns an empty trie. *) val empty : t (** Adds a new binding for the evar at the shortest unambiguous suffix of the given qualified name, if possible. If there is no such suffix, creates an ambiguous node. *) val add : EvarQualid.t -> Evar.t -> t -> t (** Transfers the qualified name of the first evar to the second evar. *) val transfer : EvarQualid.t -> Evar.t -> Evar.t -> t -> t (** Removes the qualified name of the given evar from name resolution. *) val remove : EvarQualid.t -> Evar.t -> t -> t (** Returns the shortest unambiguous name of the given qualified name. Raises [Not_found] if the evar is not present at a suffix of the qualified name. *) val shortest_name : EvarQualid.t -> Evar.t -> t -> EvarQualid.t (** Returns the list of bindings for the given qualified name. *) val find : EvarQualid.t -> t -> Evar.Set.t (** Returns true if there exists a binding that has the given basename. *) val mem_basename : Id.t -> t -> bool end = struct (** Represents a trie node. For code deduplication reasons, the root is also a node with an empty value. *) type t = { value: Evar.Set.t; children: t Id.Map.t } open EvarQualid let empty = { value = Evar.Set.empty; children = Id.Map.empty } let is_empty { value; children } = Evar.Set.is_empty value && Id.Map.is_empty children let rec add path ev node = match path with | segment :: rest -> let update = function | Some child -> Some (add rest ev child) | None -> Some { value = Evar.Set.singleton ev; children = Id.Map.empty } in { node with children = Id.Map.update segment update node.children } | [] -> { node with value = Evar.Set.add ev node.value } let add { basename; path } ev trie = add (basename :: path) ev trie let rec transfer path ev ev' node = match path with | segment :: rest -> { node with children = Id.Map.modify segment (fun _ child -> transfer rest ev ev' child) node.children } | [] -> { node with value = Evar.Set.add ev' (Evar.Set.remove ev node.value) } let transfer { basename; path } ev ev' trie = transfer (basename :: path) ev ev' trie let[@tail_mod_cons] rec shortest_name path ev node = if Evar.Set.mem ev node.value then [] else match path with | segment :: rest -> segment :: shortest_name rest ev (Id.Map.find segment node.children) | [] -> raise Not_found let shortest_name { basename; path } ev trie = match shortest_name (basename :: path) ev trie with | basename :: path -> { basename; path } | [] -> assert false let rec find path node = match path with | segment :: rest -> begin match Id.Map.find_opt segment node.children with | Some segment -> find rest segment | None -> Evar.Set.empty end | [] -> node.value let find { basename; path } trie = find (basename :: path) trie let rec remove path ev node = match path with | segment :: rest -> let update_child = function | Some child -> remove rest ev child | None -> None in let node = { node with children = Id.Map.update segment update_child node.children } in (* Prune empty nodes. *) if is_empty node then None else Some node | [] -> let node = { node with value = Evar.Set.remove ev node.value } in if is_empty node then None else Some node let remove { basename; path } ev trie = match remove (basename :: path) ev trie with | Some trie -> trie | None -> empty let mem_basename basename trie = Id.Map.mem basename trie.children end type t = { basename_map : Id.t EvMap.t; (** Map from evar to basename. *) name_resolution : NameResolution.t; (** Trie for resolving qualified names to evars. *) fresh_gen : Fresh.t; (** Fresh basename generator (to support [refine ?[?A]]) *) parent_map : Evar.t EvMap.t; (** Map from evar to its parent, if any. *) children_map : EvSet.t EvMap.t; (** Map from an evar to its children that are pending. Essentially the reverse of [parent_map]. *) removed_evars : EvSet.t; (** Set of evars marked for removal, and thus unfocusable, whose names are still used as the parent of an open goal. *) } let empty = { basename_map = EvMap.empty; name_resolution = NameResolution.empty; fresh_gen = Fresh.empty; parent_map = EvMap.empty; children_map = EvMap.empty; removed_evars = EvSet.empty } (** Returns the absolute path of [ev], obtained by following the [parent_map]. *) let[@tail_mod_cons] rec path ev evn = match EvMap.find_opt ev evn.parent_map with | Some parent -> begin match EvMap.find_opt parent evn.basename_map with | Some parent_name -> parent_name :: path parent evn | None -> [] end | None -> [] (** Return the absolute qualified name of [ev]. *) let absolute_name ev evn = match EvMap.find_opt ev evn.basename_map with | Some basename -> Some EvarQualid.{ basename; path = path ev evn } | None -> None (** Returns the shortest name that resolves to [ev], or [None] if [ev] does not resolve to a name. *) let shortest_name ev evn = match absolute_name ev evn with | Some name -> Some (NameResolution.shortest_name name ev evn.name_resolution) | None -> None (* Returns the set of focusable evars that have the given qualid as name. *) let get_matching_evars qualid evn = let evs = NameResolution.find qualid evn.name_resolution in (* Do not consider removed evars as conflicts for name resolution purposes *) Evar.Set.diff evs evn.removed_evars let register_parent ev parent evn = let add_child = function | Some children -> Some (EvSet.add ev children) | None -> Some (EvSet.singleton ev) in { evn with parent_map = EvMap.add ev parent evn.parent_map; children_map = EvMap.update parent add_child evn.children_map } let add basename ev ?parent evn = let evn = match parent with | Some parent -> register_parent ev parent evn | None -> evn in let qualid = EvarQualid.{ basename; path = path ev evn } in { evn with basename_map = EvMap.add ev basename evn.basename_map; name_resolution = NameResolution.add qualid ev evn.name_resolution; fresh_gen = Fresh.add basename evn.fresh_gen } let add_fresh basename ev ?parent evn = let evn = match parent with | Some parent -> register_parent ev parent evn | None -> evn in let qualid = EvarQualid.{ basename; path = path ev evn } in let conflicts = get_matching_evars qualid evn in if Evar.Set.is_empty conflicts then (* No need to give the parent since it's already registered *) add basename ev evn else (* Generate a fresh basename and try again. *) let basename, fresh_gen = Fresh.fresh basename evn.fresh_gen in add basename ev { evn with fresh_gen } let rec remove ev evn = match EvMap.find_opt ev evn.basename_map with | None -> evn | Some basename -> (* When defining an evar and making its name unresolvable, there are two scenarios: - The evar has no remaining children, in which case we can safely remove it from all maps since it is not used for name resolution. We also try to remove recursively its parent, since solving the evar might have closed the parent. - The evar has some children which might rely on the parent's name for name resolution. In that case, we simply add it to [removed_evars] (so that [name_of ev] fails), and removal will occur when all children will be solved. *) let children = match EvMap.find_opt ev evn.children_map with | Some children -> children | None -> EvSet.empty in if EvSet.is_empty children then let parent = EvMap.find_opt ev evn.parent_map in let name_resolution = match shortest_name ev evn with | Some name -> NameResolution.remove name ev evn.name_resolution | None -> assert false in let evn = { basename_map = EvMap.remove ev evn.basename_map; name_resolution; fresh_gen = (* If the basename still exists in the new trie, do not remove. *) if NameResolution.mem_basename basename name_resolution then evn.fresh_gen else Fresh.remove basename evn.fresh_gen; children_map = EvMap.remove ev evn.children_map; parent_map = EvMap.remove ev evn.parent_map; removed_evars = EvSet.remove ev evn.removed_evars; } in (* If there is a parent, try to remove it recursively as well. *) match parent with | Some parent -> let evn = remove parent evn in (* Rollback if removal failed. *) { evn with removed_evars = EvSet.remove ev evn.removed_evars } | None -> evn else (* Mark [ev] as deleted. *) { evn with removed_evars = EvSet.add ev evn.removed_evars } let transfer_name ev ev' evn = (* We assume that [ev] is an open goal, hence undefined and has no children. *) (* Transfer the name. *) let basename_map, name_resolution = match shortest_name ev evn with | Some name -> let basename_map = EvMap.add ev' name.basename (EvMap.remove ev evn.basename_map) in let name_resolution = NameResolution.transfer name ev ev' evn.name_resolution in basename_map, name_resolution | None -> (* [ev] has no name. *) evn.basename_map, evn.name_resolution in (* If [ev] has a parent, we update the parent's children. *) let parent_map, children_map = match EvMap.find_opt ev evn.parent_map with | Some parent -> let parent_map = EvMap.add ev' parent (EvMap.remove ev evn.parent_map) in let children_map = EvMap.modify parent (fun _ children -> EvSet.add ev' (EvSet.remove ev children)) evn.children_map in parent_map, children_map | None -> evn.parent_map, evn.children_map in { evn with basename_map; name_resolution; parent_map; children_map } type set_kind = | SetEmpty | SetSingleton of Evar.t | SetOther let classify_set s = if Evar.Set.is_empty s then SetEmpty else let evk = Evar.Set.choose s in let s = Evar.Set.remove evk s in if Evar.Set.is_empty s then SetSingleton evk else SetOther let name_of ev evn = match shortest_name ev evn with | None -> None | Some name -> let conflicts = get_matching_evars name evn in (* TODO: we should the caller handle the conflict themselves instead of generating nonsensical names in linear time. *) match classify_set conflicts with | SetEmpty | SetSingleton _ -> Some (EvarQualid.repr name) | SetOther -> let nconflicts = Evar.Set.cardinal conflicts in (* If the qualified name is ambiguous, we append a suffix corresponding to the index in the list. *) let { EvarQualid.basename; path } = name in let i = nconflicts - CList.index Evar.equal ev (Evar.Set.elements conflicts) - 1 in let basename = if Int.equal i (-1) then basename else Id.of_string ((Id.to_string name.basename) ^ (string_of_int i)) in Some (Libnames.make_path (DirPath.make path) basename) let has_name ev evn = not (EvSet.mem ev evn.removed_evars) && EvMap.mem ev evn.basename_map let has_unambiguous_name ev evn = match shortest_name ev evn with | None -> false | Some name -> let matches = get_matching_evars name evn in match classify_set matches with | SetEmpty | SetOther -> false | SetSingleton e -> Evar.equal e ev let resolve fp evn = let qualid = EvarQualid.make fp in let evs = get_matching_evars qualid evn in let open Pp in match classify_set evs with | SetEmpty -> raise Not_found | SetSingleton ev -> ev | SetOther -> CErrors.user_err ?loc:fp.loc (str "Ambiguous evar name " ++ Libnames.pr_qualid fp ++ str ".") rocq-9.2.0/engine/evarnames.mli000066400000000000000000000041321516144147600164300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool (** Represents an evar name map. *) type t (** Returns an empty name map. *) val empty : t (** Adds a binding for the given undefined evar to the given basename. The absolute path is obtained using the parent of the evar. *) val add : Id.t -> Evar.t -> ?parent:Evar.t -> t -> t (** Adds a (potentially fresh) binding for the given undefined evar to the given basename by first checking for conflicts. *) val add_fresh : Id.t -> Evar.t -> ?parent:Evar.t -> t -> t (** Removes the name of the given evar. This indicates that the evar was defined, and therefore is no longer accessible by name. *) val remove : Evar.t -> t -> t (** Transfers the name of the first evar to the second. *) val transfer_name : Evar.t -> Evar.t -> t -> t (** Returns the qualified name associated to the evar, if any. *) val name_of : Evar.t -> t -> Libnames.full_path option (** Returns [true] if the evar has a name. Equivalent to [name_of ev <> None] but faster since it does not compute the fully qualified name of [ev]. *) val has_name : Evar.t -> t -> bool (** Returns [true] if the evar has a name that is unambiguous. *) val has_unambiguous_name : Evar.t -> t -> bool (** Resolves the given (partially) qualified name to an evar. If the name resolution failed, raises [Not_found]. *) val resolve : Libnames.qualid -> t -> Evar.t rocq-9.2.0/engine/evarutil.ml000066400000000000000000001006401516144147600161320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* nf_evar_info evm evi } evm let nf_evar_map_undefined evm = Evd.raw_map_undefined (fun _ evi -> nf_evar_info evm evi) evm (*-------------------*) (* Auxiliary functions for the conversion algorithms modulo evars *) let has_undefined_evars evd t = let rec f h t = let (h, knd) = EConstr.Expand.kind evd h t in match knd with | Evar _ -> raise NotInstantiatedEvar | _ -> EConstr.Expand.iter evd f h knd in let h, t = EConstr.Expand.make t in try let _ = f h t in false with (Not_found | NotInstantiatedEvar) -> true let has_undefined_evars_or_metas evd t = let rec has_ev t = match EConstr.kind evd t with | Evar _ | Meta _ -> raise NotInstantiatedEvar | _ -> EConstr.iter evd has_ev t in try let _ = has_ev t in false with (Not_found | NotInstantiatedEvar) -> true let is_ground_term evd t = not (has_undefined_evars evd t) let is_ground_env evd env = let is_ground_rel_decl = function | RelDecl.LocalDef (_,b,_) -> is_ground_term evd (EConstr.of_constr b) | _ -> true in let is_ground_named_decl = function | NamedDecl.LocalDef (_,b,_) -> is_ground_term evd (EConstr.of_constr b) | _ -> true in List.for_all is_ground_rel_decl (rel_context env) && List.for_all is_ground_named_decl (named_context env) (* Expand head evar if any (currently consider only applications but I guess it should consider Case too) *) let whd_head_evar_stack sigma c = let rec whrec (c, l) = match EConstr.kind sigma c with | Cast (c,_,_) -> whrec (c, l) | App (f,args) -> whrec (f, args :: l) | c -> (EConstr.of_kind c, l) in whrec (c, []) let whd_head_evar sigma c = let open EConstr in let (f, args) = whd_head_evar_stack sigma c in match args with | [arg] -> mkApp (f, arg) | _ -> mkApp (f, Array.concat args) (**********************) (* Creating new metas *) (**********************) let meta_counter_summary_name = "meta counter" (* Generator of metavariables *) let meta_ctr, meta_counter_summary_tag = Summary.ref_tag 0 ~name:meta_counter_summary_name let new_meta () = incr meta_ctr; !meta_ctr (* The list of non-instantiated existential declarations (order is important) *) (*------------------------------------* * functional operations on evar sets * *------------------------------------*) (* [push_rel_context_to_named_context] builds the defining context and the * initial instance of an evar. If the evar is to be used in context * * Gamma = a1 ... an xp ... x1 * \- named part -/ \- de Bruijn part -/ * * then the x1...xp are turned into variables so that the evar is declared in * context * * a1 ... an xp ... x1 * \----------- named part ------------/ * * but used applied to the initial instance "a1 ... an Rel(p) ... Rel(1)" * so that ev[a1:=a1 ... an:=an xp:=Rel(p) ... x1:=Rel(1)] is correctly typed * in context Gamma. * * Remark 1: The instance is reverted in practice (i.e. Rel(1) comes first) * Remark 2: If some of the ai or xj are definitions, we keep them in the * instance. This is necessary so that no unfolding of local definitions * happens when inferring implicit arguments (consider e.g. the problem * "x:nat; x':=x; f:forall y, y=y -> Prop |- f _ (refl_equal x')" which * produces the equation "?y[x,x']=?y[x,x']" =? "x'=x'": we want * the hole to be instantiated by x', not by x (which would have been * the case in [invert_definition] if x' had disappeared from the instance). * Note that at any time, if, in some context env, the instance of * declaration x:A is t and the instance of definition x':=phi(x) is u, then * we have the property that u and phi(t) are convertible in env. *) let next_ident_away id avoid = let avoid id = Id.Set.mem id avoid in next_ident_away_from id avoid type subst_val = | SRel of int | SVar of Id.t type csubst = { csubst_len : int; (** Cardinal of [csubst_rel] *) csubst_var : Constr.t Id.Map.t; (** A mapping of variables to variables. We use the more general [Constr.t] to share allocations, but all values are of shape [Var _]. *) csubst_rel : Constr.t Int.Map.t; (** A contiguous mapping of integers to variables. Same remark for values. *) csubst_rev : subst_val Id.Map.t; (** Reverse mapping of the substitution *) } (** This type represents a name substitution for the named and De Bruijn parts of an environment. For efficiency we also store the reverse substitution. Invariant: all identifiers in the codomain of [csubst_var] and [csubst_rel] must be pairwise distinct. *) let empty_csubst = { csubst_len = 0; csubst_rel = Int.Map.empty; csubst_var = Id.Map.empty; csubst_rev = Id.Map.empty; } let csubst_subst sigma { csubst_len = k; csubst_var = v; csubst_rel = s } c = (* Safe because this is a substitution *) let c = EConstr.Unsafe.to_constr c in let rec subst n c = match Constr.kind c with | Rel m -> if m <= n then c else if m - n <= k then Int.Map.find (k - m + n) s else mkRel (m - k) | Var id -> begin try Id.Map.find id v with Not_found -> c end | Evar (evk, args) -> let EvarInfo evi = Evd.find sigma evk in let args' = subst_instance n (evar_filtered_context evi) args in if args' == args then c else Constr.mkEvar (evk, args') (* FIXME: preserve sharing *) | _ -> Constr.map_with_binders succ subst n c and subst_instance n ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (c, args) -> let c' = match c with | None -> begin try Some (Id.Map.find (NamedDecl.get_id decl) v) with Not_found -> c end | Some c -> let c' = subst n c in if isVarId (NamedDecl.get_id decl) c' then None else Some c' in SList.cons_opt c' (subst_instance n ctx args) | _ :: _, None | [], Some _ -> assert false in let c = if k = 0 && Id.Map.is_empty v then c else subst 0 c in EConstr.of_constr c type ext_named_context = { ext_subst : csubst; ext_avoid : Id.Set.t; ext_ctx : named_context_val; } let ext_named_context_val ext = ext.ext_ctx let ext_csubst ext = ext.ext_subst let push_var id { csubst_len = n; csubst_var = v; csubst_rel = s; csubst_rev = r } = let s = Int.Map.add n (Constr.mkVar id) s in let r = Id.Map.add id (SRel n) r in { csubst_len = succ n; csubst_var = v; csubst_rel = s; csubst_rev = r } (** Post-compose the substitution with the generator [src ↦ tgt] *) let update_var src tgt subst = let cur = try Some (Id.Map.find src subst.csubst_rev) with Not_found -> None in match cur with | None -> (* Missing keys stand for identity substitution [src ↦ src] *) let csubst_var = Id.Map.add src (Constr.mkVar tgt) subst.csubst_var in let csubst_rev = Id.Map.add tgt (SVar src) subst.csubst_rev in { subst with csubst_var; csubst_rev } | Some bnd -> let csubst_rev = Id.Map.add tgt bnd (Id.Map.remove src subst.csubst_rev) in match bnd with | SRel m -> let csubst_rel = Int.Map.add m (Constr.mkVar tgt) subst.csubst_rel in { subst with csubst_rel; csubst_rev } | SVar id -> let csubst_var = Id.Map.add id (Constr.mkVar tgt) subst.csubst_var in { subst with csubst_var; csubst_rev } module VarSet = struct type t = Id.t -> bool let empty _ = false let full _ = true let variables env id = is_section_variable env id end type naming_mode = VarSet.t let push_rel_decl_to_named_context ~hypnaming sigma decl (ext : ext_named_context) = let open EConstr in let open Vars in let map_decl f d = NamedDecl.map_constr f d in let rec replace_var_named_declaration id0 id nc = match match_named_context_val nc with | None -> empty_named_context_val | Some (decl, nc) -> if Id.equal id0 (NamedDecl.get_id decl) then (* Stop here, the variable cannot occur before its definition *) push_named_context_val (NamedDecl.set_id id decl) nc else let nc = replace_var_named_declaration id0 id nc in let vsubst = [id0 , mkVar id] in push_named_context_val (map_decl (fun c -> replace_vars sigma vsubst c) decl) nc in let extract_if_neq id = function | Anonymous -> None | Name id' when Id.compare id id' = 0 -> None | Name id' -> Some id' in let na = RelDecl.get_name decl in let id = (* id_of_name_using_hdchar only depends on the rel context which is empty here *) next_ident_away (id_of_name_using_hdchar empty_env sigma (RelDecl.get_type decl) na) ext.ext_avoid in match extract_if_neq id na with | Some id0 -> if hypnaming id0 then (* spiwack: if [id0] is a section variable renaming it is incorrect. We revert to a less robust behaviour where the new binder has name [id]. Which amounts to the same behaviour than when [id=id0]. *) let d = decl |> NamedDecl.of_rel_decl (fun _ -> id) |> map_decl (csubst_subst sigma ext.ext_subst) in { ext_subst = push_var id ext.ext_subst; ext_avoid = Id.Set.add id ext.ext_avoid; ext_ctx = push_named_context_val d ext.ext_ctx } else (* spiwack: if [id<>id0], rather than introducing a new binding named [id], we will keep [id0] (the name given by the user) and rename [id0] into [id] in the named context. Unless [id] is a section variable. *) let subst = update_var id0 id ext.ext_subst in let d = decl |> NamedDecl.of_rel_decl (fun _ -> id0) |> map_decl (csubst_subst sigma subst) in let nc = replace_var_named_declaration id0 id ext.ext_ctx in let avoid = Id.Set.add id (Id.Set.add id0 ext.ext_avoid) in { ext_subst = push_var id0 subst; ext_avoid = avoid; ext_ctx = push_named_context_val d nc } | None -> let d = decl |> NamedDecl.of_rel_decl (fun _ -> id) |> map_decl (csubst_subst sigma ext.ext_subst) in { ext_subst = push_var id ext.ext_subst; ext_avoid = Id.Set.add id ext.ext_avoid; ext_ctx = push_named_context_val d ext.ext_ctx } let csubst_instance subst ctx = let fold decl accu = match Id.Map.find (NamedDecl.get_id decl) subst.csubst_rev with | SRel n -> SList.cons (EConstr.mkRel (subst.csubst_len - n)) accu | SVar id -> SList.cons (EConstr.mkVar id) accu | exception Not_found -> SList.default accu in List.fold_right fold ctx SList.empty let ext_rev_subst { ext_subst = subst } id0 = match Id.Map.find id0 subst.csubst_rev with | SRel n -> EConstr.mkRel (subst.csubst_len - n) | SVar id -> EConstr.mkVar id let default_ext_instance { ext_subst = subst; ext_ctx = ctx } = csubst_instance subst (named_context_of_val ctx) let push_rel_context_to_named_context ~hypnaming env sigma typ = (* compute the instances relative to the named context and rel_context *) let open EConstr in let ctx = named_context_val env in if List.is_empty (Environ.rel_context env) then let inst = SList.defaultn (List.length @@ named_context_of_val ctx) SList.empty in (ctx, typ, inst, empty_csubst) else let avoid = Environ.ids_of_named_context_val (named_context_val env) in (* move the rel context to a named context and extend the named instance *) (* with vars of the rel context *) (* We do keep the instances corresponding to local definition (see above) *) let init = { ext_subst = empty_csubst; ext_avoid = avoid; ext_ctx = ctx } in let ext = Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context ~hypnaming sigma d acc) (rel_context env) ~init in let inst = default_ext_instance ext in (ext.ext_ctx, csubst_subst sigma ext.ext_subst typ, inst, ext.ext_subst) let ext_named_context_of_env ~hypnaming env sigma = let avoid = Environ.ids_of_named_context_val (Environ.named_context_val env) in let init = { ext_subst = empty_csubst; ext_avoid = avoid; ext_ctx = named_context_val env } in Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context ~hypnaming sigma d acc) (EConstr.rel_context env) ~init (*------------------------------------* * Entry points to define new evars * *------------------------------------*) let new_pure_evar = Evd.new_pure_evar let next_evar_name naming = match naming with | IntroAnonymous -> None | IntroFresh id -> Some (id, true) | IntroIdentifier id -> Some (id, false) (* [new_evar] declares a new existential in an env env with type typ *) (* Converting the env into the sign of the evar to define *) let new_evar ?src ?filter ?relevance ?abstract_arguments ?candidates ?(naming = IntroAnonymous) ?parent ?typeclass_candidate ?rrpat ?hypnaming env evd typ = let name = next_evar_name naming in let hypnaming = match hypnaming with | Some n -> n | None -> VarSet.variables (Global.env ()) in let sign,typ',instance,subst = push_rel_context_to_named_context ~hypnaming env evd typ in let map c = csubst_subst evd subst c in let candidates = Option.map (fun l -> List.map map l) candidates in let instance = match filter with | None -> instance | Some filter -> Filter.filter_slist filter instance in let relevance = match relevance with | Some r -> r | None -> ERelevance.relevant (* FIXME: relevant_of_type not defined yet *) in let (evd, evk) = new_pure_evar sign evd typ' ?src ?rrpat ?filter ~relevance ?abstract_arguments ?candidates ?name ?parent ?typeclass_candidate in (evd, EConstr.mkEvar (evk, instance)) let new_type_evar ?src ?filter ?naming ?hypnaming env evd rigid = let (evd', s) = new_sort_variable rigid evd in let relevance = EConstr.ESorts.relevance_of_sort s in let (evd', e) = new_evar env evd' ?src ?filter ~relevance ?naming ~typeclass_candidate:false ?hypnaming (EConstr.mkSort s) in evd', (e, s) let new_Type ?(rigid=Evd.univ_flexible) evd = let open EConstr in let (evd, s) = new_sort_variable rigid evd in (evd, mkSort s) (* Safe interface to unification problems *) type unification_pb = conv_pb * env * EConstr.constr * EConstr.constr let eq_unification_pb evd (pbty,env,t1,t2) (pbty',env',t1',t2') = pbty == pbty' && env == env' && EConstr.eq_constr evd t1 t1' && EConstr.eq_constr evd t2 t2' let add_unification_pb ?(tail=false) pb evd = let conv_pbs = Evd.conv_pbs evd in if not (List.exists (eq_unification_pb evd pb) conv_pbs) then let (pbty,env,t1,t2) = pb in Evd.add_conv_pb ~tail (pbty,env,t1,t2) evd else evd (* This assumes an evar with identity instance and generalizes it over only the de Bruijn part of the context *) let generalize_evar_over_rels sigma (ev,args) = let open EConstr in let evi = Evd.find_undefined sigma ev in let args = Evd.expand_existential sigma (ev, args) in let sign = named_context_of_val (Evd.evar_hyps evi) in List.fold_left2 (fun (c,inst as x) a d -> if isRel sigma a then (mkNamedProd_or_LetIn sigma d c,a::inst) else x) (Evd.evar_concl evi,[]) args sign (************************************) (* Removing a dependency in an evar *) (************************************) type clear_dependency_error = | OccurHypInSimpleClause of Id.t option | EvarTypingBreak of EConstr.existential | NoCandidatesLeft of Evar.t exception ClearDependencyError of Id.t * clear_dependency_error * GlobRef.t option exception Depends of Id.t let set_of_evctx l = List.fold_left (fun s decl -> Id.Set.add (NamedDecl.get_id decl) s) Id.Set.empty l let filter_effective_candidates evd evi filter candidates = let ids = set_of_evctx (Filter.filter_list filter (evar_context evi)) in List.filter (fun a -> Id.Set.subset (collect_vars evd a) ids) candidates let restrict_evar evd evk filter candidates = let evar_info = Evd.find_undefined evd evk in let candidates = Option.map (filter_effective_candidates evd evar_info filter) candidates in match candidates with | Some [] -> raise (ClearDependencyError (*FIXME*)(Id.of_string "blah", (NoCandidatesLeft evk), None)) | _ -> Evd.restrict evk filter ?candidates evd (* FIXME: put this somewhere more sensible *) let vars_of_global env sigma gr = let open GlobRef in match gr with | ConstRef cst -> let eff = Evd.eval_side_effects sigma in if Safe_typing.is_empty_private_constants @@ Evd.seff_private @@ eff then Environ.vars_of_global env gr else let senv = Evd.get_senv_side_effects eff in Environ.vars_of_global (Safe_typing.env_of_safe_env senv) gr | VarRef _ | IndRef _ | ConstructRef _ -> Environ.vars_of_global env gr let check_vars env sigma ids c = let rec check_rec c = match EConstr.destRef sigma c with | gr, _ -> let vars = vars_of_global env sigma gr in Id.Map.iter (fun id _ -> if Id.Set.mem id vars then raise (Depends id)) ids | exception DestKO -> EConstr.iter sigma check_rec c in check_rec c let rec check_and_clear_in_constr ~is_section_variable env evdref err ids ~global c = (* returns a new constr where all the evars have been 'cleaned' (ie the hypotheses ids have been removed from the contexts of evars). [global] should be true iff there is some variable of [ids] which is a section variable *) match EConstr.kind !evdref c with | Var id' -> if Id.Set.mem id' ids then raise (ClearDependencyError (id', err, None)) else c | ( Const _ | Ind _ | Construct _ ) as ref -> let () = if global then let r = match ref with | Const (c, _) -> GlobRef.ConstRef c | Ind (ind, _) -> IndRef ind | Construct (c, _) -> ConstructRef c | _ -> assert false in let check id' = if Id.Set.mem id' ids then raise (ClearDependencyError (id',err,Some r)) in Id.Set.iter check (vars_of_global env !evdref r) in c | Evar (evk,l as ev) -> (* We check for dependencies to elements of ids in the evar_info corresponding to e and in the instance of arguments. Concurrently, we build a new evar corresponding to e where hypotheses of ids have been removed *) let evi = Evd.find_undefined !evdref evk in let ctxt = Evd.evar_filtered_context evi in let rec fold accu ctxt args = match ctxt, SList.view args with | [], Some _ | _ :: _, None -> assert false | [], None -> accu | h :: ctxt, Some (a, args) -> let (ri, filter) = fold accu ctxt args in try (* Check if some id to clear occurs in the instance a of rid in ev and remember the dependency *) let check id = if Id.Set.mem id ids then raise (Depends id) in let a = match a with | None -> Id.Set.singleton (NamedDecl.get_id h) | Some a -> collect_vars !evdref a in let () = Id.Set.iter check a in (* Check if some rid to clear in the context of ev has dependencies in another hyp of the context of ev and transitively remember the dependency *) let () = if not @@ Id.Map.is_empty ri then NamedDecl.iter_constr (fun c -> check_vars env !evdref ri c) h in (* No dependency at all, we can keep this ev's context hyp *) (ri, true::filter) with Depends id -> (Id.Map.add (NamedDecl.get_id h) id ri, false::filter) in let (rids, filter) = fold (Id.Map.empty, []) ctxt l in if Id.Map.is_empty rids then c else (* Check if some rid to clear in the context of ev has dependencies in the type of ev and adjust the source of the dependency *) let _nconcl : EConstr.t = try let nids = Id.Map.domain rids in let global = Id.Set.exists is_section_variable nids in let concl = evar_concl evi in check_and_clear_in_constr ~is_section_variable env evdref (EvarTypingBreak ev) nids ~global concl with ClearDependencyError (rid,err,where) -> raise (ClearDependencyError (Id.Map.find rid rids,err,where)) in let origfilter = Evd.evar_filter evi in let filter = Evd.Filter.apply_subfilter origfilter filter in let evd = !evdref in let candidates = Evd.evar_candidates evi in let (evd,_) = restrict_evar evd evk filter candidates in evdref := evd; Evd.existential_value !evdref ev | _ -> EConstr.map !evdref (check_and_clear_in_constr ~is_section_variable env evdref err ids ~global) c let clear_hyps_in_evi_main env sigma hyps terms ids = (* clear_hyps_in_evi erases hypotheses ids in hyps, checking if some hypothesis does not depend on a element of ids, and erases ids in the contexts of the evars occurring in evi *) let evdref = ref sigma in let is_section_variable id = is_section_variable (Global.env ()) id in let global = Id.Set.exists is_section_variable ids in let terms = List.map (check_and_clear_in_constr ~is_section_variable env evdref (OccurHypInSimpleClause None) ids ~global) terms in let nhyps = let check_context decl = let decl = EConstr.of_named_decl decl in let err = OccurHypInSimpleClause (Some (NamedDecl.get_id decl)) in EConstr.Unsafe.to_named_decl @@ NamedDecl.map_constr (check_and_clear_in_constr ~is_section_variable env evdref err ids ~global) decl in remove_hyps ids check_context hyps in (!evdref, nhyps, terms) let check_and_clear_in_constr env evd err ids c = let evdref = ref evd in let _ : EConstr.constr = check_and_clear_in_constr ~is_section_variable:(fun _ -> true) ~global:true env evdref err ids c in !evdref let clear_hyps_in_evi env sigma hyps concl ids = match clear_hyps_in_evi_main env sigma hyps [concl] ids with | (sigma,nhyps,[nconcl]) -> (sigma,nhyps,nconcl) | _ -> assert false let clear_hyps2_in_evi env sigma hyps t concl ids = match clear_hyps_in_evi_main env sigma hyps [t;concl] ids with | (sigma,nhyps,[t;nconcl]) -> (sigma,nhyps,t,nconcl) | _ -> assert false (** [advance sigma g] returns [Some g'] if [g'] is undefined and is the current avatar of [g] (for instance [g] was changed by [clear] into [g']). It returns [None] if [g] has been (partially) solved. *) (* spiwack: [advance] is probably performance critical, and the good behaviour of its definition may depend sensitively to the actual definition of [Evd.find]. Currently, [Evd.find] starts looking for a value in the heap of undefined variable, which is small. Hence in the most common case, where [advance] is applied to an unsolved goal ([advance] is used to figure if a side effect has modified the goal) it terminates quickly. *) let rec advance sigma evk = if Evd.is_undefined sigma evk then Some evk else match is_aliased_evar sigma evk with | Some evk -> advance sigma evk | None -> None let reachable_from_evars sigma evars = let aliased = Evd.get_aliased_evars sigma in let rec search evk visited = if Evar.Set.mem evk visited then visited else let visited = Evar.Set.add evk visited in match Evar.Map.find evk aliased with | evk' -> search evk' visited | exception Not_found -> visited in Evar.Set.fold (fun evk visited -> search evk visited) evars Evar.Set.empty (** The following functions return the set of undefined evars contained in the object, the defined evars being traversed. This is roughly a combination of the previous functions and [nf_evar]. *) let undefined_evars_of_term evd t = let rec evrec acc c = match EConstr.kind evd c with | Evar (n, l) -> let acc = Evar.Set.add n acc in SList.Skip.fold evrec acc l | _ -> EConstr.fold evd evrec acc c in evrec Evar.Set.empty t let undefined_evars_of_named_context evd nc = Context.Named.fold_outside (NamedDecl.fold_constr (fun c s -> Evar.Set.union s (undefined_evars_of_term evd (EConstr.of_constr c)))) nc ~init:Evar.Set.empty type undefined_evars_cache = { mutable cache : (EConstr.named_declaration * Evar.Set.t) ref Id.Map.t; } let create_undefined_evars_cache () = { cache = Id.Map.empty; } let cached_evar_of_hyp cache sigma decl accu = match cache with | None -> let fold c acc = let evs = undefined_evars_of_term sigma c in Evar.Set.union evs acc in NamedDecl.fold_constr fold decl accu | Some cache -> let id = NamedDecl.get_annot decl in let r = try Id.Map.find id.binder_name cache.cache with Not_found -> (* Dummy value *) let r = ref (NamedDecl.LocalAssum (id, EConstr.mkProp), Evar.Set.empty) in let () = cache.cache <- Id.Map.add id.binder_name r cache.cache in r in let (decl', evs) = !r in let evs = if NamedDecl.equal (==) (==) decl decl' then snd !r else let fold c acc = let evs = undefined_evars_of_term sigma c in Evar.Set.union evs acc in let evs = NamedDecl.fold_constr fold decl Evar.Set.empty in let () = r := (decl, evs) in evs in Evar.Set.fold Evar.Set.add evs accu let filtered_undefined_evars_of_evar_info (type a) ?cache sigma (evi : a evar_info) = let evars_of_named_context cache accu nc = let fold decl accu = cached_evar_of_hyp cache sigma (EConstr.of_named_decl decl) accu in Context.Named.fold_outside fold nc ~init:accu in let accu = match Evd.evar_body evi with | Evar_empty -> undefined_evars_of_term sigma (Evd.evar_concl evi) | Evar_defined b -> evars_of_term sigma b in let ctxt = EConstr.Unsafe.to_named_context (evar_filtered_context evi) in evars_of_named_context cache accu ctxt (* spiwack: this is a more complete version of {!Termops.occur_evar}. The latter does not look recursively into an [evar_map]. If unification only need to check superficially, tactics do not have this luxury, and need the more complete version. *) let occur_evar_upto sigma n c = let rec occur_rec c = match EConstr.kind sigma c with | Evar (evk, _) -> if Evar.equal evk n then raise Occur | _ -> EConstr.iter sigma occur_rec c in try occur_rec c; false with Occur -> true (* We don't try to guess in which sort the type should be defined, since any type has type Type. May cause some trouble, but not so far... *) let judge_of_new_Type evd = let open EConstr in let (evd', s) = new_sort_variable univ_rigid evd in (evd', { uj_val = mkSort s; uj_type = mkSort (ESorts.super evd s) }) let subterm_source evk ?where (loc,k) = let evk = match k with | Evar_kinds.SubEvar (None,evk) when where = None -> evk | _ -> evk in (loc,Evar_kinds.SubEvar (where,evk)) (* Add equality constraints for covariant/invariant positions. For irrelevant positions, unify universes when flexible. *) let compare_cumulative_instances cv_pb variances u u' sigma = let open UnivProblem in let cstrs = Univ.UnivConstraints.empty in let soft = Set.empty in let qs, us = UVars.Instance.to_array u and qs', us' = UVars.Instance.to_array u' in let qcstrs = enforce_eq_qualities qs qs' Set.empty in match Evd.add_constraints sigma qcstrs with | exception UGraph.UniverseInconsistency p -> Inr p | sigma -> let cstrs, soft = Array.fold_left3 (fun (cstrs, soft) v u u' -> let open UVars.Variance in match v with | Irrelevant -> cstrs, Set.add (UWeak (u,u')) soft | Covariant when cv_pb == Conversion.CUMUL -> Univ.UnivConstraints.add (u,Univ.UnivConstraint.Le,u') cstrs, soft | Covariant | Invariant -> Univ.UnivConstraints.add (u,Univ.UnivConstraint.Eq,u') cstrs, soft) (cstrs,soft) variances us us' in match Evd.add_univ_constraints sigma cstrs with | sigma -> Inl (Evd.add_constraints sigma soft) | exception UGraph.UniverseInconsistency p -> Inr p let compare_constructor_instances evd u u' = let open UnivProblem in let qs, us = UVars.Instance.to_array u and qs', us' = UVars.Instance.to_array u' in let qcstrs = enforce_eq_qualities qs qs' Set.empty in match Evd.add_constraints evd qcstrs with | exception UGraph.UniverseInconsistency p -> Inr p | evd -> let soft = Array.fold_left2 (fun cs u u' -> Set.add (UWeak (u,u')) cs) Set.empty us us' in Inl (Evd.add_constraints evd soft) (** [eq_constr_univs_test ~evd ~extended_evd t u] tests equality of [t] and [u] up to existential variable instantiation and equalisable universes. The term [t] is interpreted in [evd] while [u] is interpreted in [extended_evd]. The universe constraints in [extended_evd] are assumed to be an extension of those in [evd]. *) let eq_constr_univs_test ~evd ~extended_evd t u = (* spiwack: mild code duplication with {!Evd.eq_constr_univs}. *) let open Evd in let t = EConstr.Unsafe.to_constr t and u = EConstr.Unsafe.to_constr u in let sigma = ref extended_evd in let eq_universes _ u1 u2 = let u1 = EConstr.EInstance.(kind !sigma (make u1)) in let u2 = EConstr.EInstance.(kind !sigma (make u2)) in let check_qeq q1 q2 = UState.check_eq_quality (Evd.ustate !sigma) q1 q2 in UGraph.check_eq_instances check_qeq (universes !sigma) u1 u2 in let eq_sorts s1 s2 = if Sorts.equal s1 s2 then true else try sigma := add_constraints !sigma UnivProblem.(Set.singleton (UEq (s1, s2))); true with UGraph.UniverseInconsistency _ | UniversesDiffer -> false in let eq_existential eq e1 e2 = let eq c1 c2 = eq 0 (EConstr.Unsafe.to_constr c1) (EConstr.Unsafe.to_constr c2) in EConstr.eq_existential evd eq (EConstr.of_existential e1) (EConstr.of_existential e2) in let kind1 = kind_of_term_upto evd in let kind2 = kind_of_term_upto extended_evd in let rec eq_constr' nargs m n = Constr.compare_head_gen_with kind1 kind2 eq_universes eq_sorts (eq_existential eq_constr') eq_constr' nargs m n in Constr.compare_head_gen_with kind1 kind2 eq_universes eq_sorts (eq_existential eq_constr') eq_constr' 0 t u rocq-9.2.0/engine/evarutil.mli000066400000000000000000000230441516144147600163050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* metavariable (** {6 Creating a fresh evar given their type and context} *) val next_evar_name : intro_pattern_naming_expr -> (Id.t * bool) option module VarSet : sig type t val empty : t val full : t val variables : Environ.env -> t end type naming_mode = VarSet.t val new_evar : ?src:Evar_kinds.t Loc.located -> ?filter:Filter.t -> ?relevance:ERelevance.t -> ?abstract_arguments:Abstraction.t -> ?candidates:constr list -> ?naming:intro_pattern_naming_expr -> ?parent:Evar.t -> ?typeclass_candidate:bool -> ?rrpat:bool -> ?hypnaming:naming_mode -> env -> evar_map -> types -> evar_map * EConstr.t (** Alias of {!Evd.new_pure_evar} *) val new_pure_evar : ?src:Evar_kinds.t Loc.located -> ?filter:Filter.t -> relevance:ERelevance.t -> ?abstract_arguments:Abstraction.t -> ?candidates:constr list -> ?name:(Id.t * bool) -> ?parent:Evar.t -> ?typeclass_candidate:bool -> ?rrpat:bool -> named_context_val -> evar_map -> types -> evar_map * Evar.t (** Create a new Type existential variable, as we keep track of them during type-checking and unification. *) val new_type_evar : ?src:Evar_kinds.t Loc.located -> ?filter:Filter.t -> ?naming:intro_pattern_naming_expr -> ?hypnaming:naming_mode -> env -> evar_map -> rigid -> evar_map * (constr * ESorts.t) val new_Type : ?rigid:rigid -> evar_map -> evar_map * constr (** {6 Unification utils} *) (* Expand head evar if any *) val whd_head_evar : evar_map -> constr -> constr (* An over-approximation of [has_undefined (nf_evars evd c)] *) val has_undefined_evars : evar_map -> constr -> bool val has_undefined_evars_or_metas : evar_map -> constr -> bool val is_ground_term : evar_map -> constr -> bool val is_ground_env : evar_map -> env -> bool (** [advance sigma g] returns [Some g'] if [g'] is undefined and is the current avatar of [g] (for instance [g] was changed by [clear] into [g']). It returns [None] if [g] has been (partially) solved. *) val advance : evar_map -> Evar.t -> Evar.t option (** [reachable_from_evars sigma seeds] computes the descendents of evars in [seeds] by restriction or evar-evar unifications in [sigma]. *) val reachable_from_evars : evar_map -> Evar.Set.t -> Evar.Set.t (** The following functions return the set of undefined evars contained in the object, the defined evars being traversed. This is roughly a combination of the previous functions and [nf_evar]. *) val undefined_evars_of_term : evar_map -> constr -> Evar.Set.t val undefined_evars_of_named_context : evar_map -> Constr.named_context -> Evar.Set.t type undefined_evars_cache val create_undefined_evars_cache : unit -> undefined_evars_cache val filtered_undefined_evars_of_evar_info : ?cache:undefined_evars_cache -> evar_map -> 'a evar_info -> Evar.Set.t (** [occur_evar_upto sigma k c] returns [true] if [k] appears in [c]. It looks up recursively in [sigma] for the value of existential variables. *) val occur_evar_upto : evar_map -> Evar.t -> constr -> bool (** {6 Value/Type constraints} *) val judge_of_new_Type : evar_map -> evar_map * unsafe_judgment (***********************************************************) val create_clos_infos : env -> evar_map -> RedFlags.reds -> CClosure.clos_infos val whd_evar : evar_map -> constr -> constr val nf_evar : evar_map -> constr -> constr val j_nf_evar : evar_map -> unsafe_judgment -> unsafe_judgment val jl_nf_evar : evar_map -> unsafe_judgment list -> unsafe_judgment list val jv_nf_evar : evar_map -> unsafe_judgment array -> unsafe_judgment array val tj_nf_evar : evar_map -> unsafe_type_judgment -> unsafe_type_judgment val nf_named_context_evar : evar_map -> Constr.named_context -> Constr.named_context val nf_rel_context_evar : evar_map -> rel_context -> rel_context val nf_env_evar : evar_map -> env -> env val nf_evar_info : evar_map -> 'a evar_info -> 'a evar_info val nf_evar_map : evar_map -> evar_map val nf_evar_map_undefined : evar_map -> evar_map val nf_relevance : evar_map -> Sorts.relevance -> Sorts.relevance (** Presenting terms without solved evars *) val nf_evars_universes : evar_map -> Constr.constr -> Constr.constr (** [finalize env sigma f] combines universe minimisation, evar-and-universe normalisation and universe restriction. It minimizes universes in [sigma], calls [f] a normalisation function with respect to the updated [sigma] and restricts the local universes of [sigma] to those encountered while running [f]. Note that the normalizer passed to [f] holds some imperative state in its closure. *) val finalize : ?abort_on_undefined_evars:bool -> evar_map -> ((EConstr.t -> Constr.t) -> 'a) -> evar_map * 'a (** {6 Term manipulation up to instantiation} *) (** Like {!Constr.kind} except that [kind_of_term sigma t] exposes [t] as an evar [e] only if [e] is uninstantiated in [sigma]. Otherwise the value of [e] in [sigma] is (recursively) used. *) val kind_of_term_upto : evar_map -> Constr.constr -> (Constr.constr, Constr.types, Sorts.t, UVars.Instance.t, Sorts.relevance) kind_of_term (** [eq_constr_univs_test ~evd ~extended_evd t u] tests equality of [t] and [u] up to existential variable instantiation and equalisable universes. The term [t] is interpreted in [evd] while [u] is interpreted in [extended_evd]. The universe constraints in [extended_evd] are assumed to be an extension of those in [evd]. *) val eq_constr_univs_test : evd:Evd.evar_map -> extended_evd:Evd.evar_map -> constr -> constr -> bool (** [compare_cumulative_instances cv_pb variance u1 u2 sigma] Returns [Inl sigma'] where [sigma'] is [sigma] augmented with universe constraints such that [u1 cv_pb? u2] according to [variance]. Additionally flexible universes in irrelevant positions are unified if possible. Returns [Inr p] when the former is impossible. *) val compare_cumulative_instances : Conversion.conv_pb -> UVars.Variance.t array -> UVars.Instance.t -> UVars.Instance.t -> evar_map -> (evar_map, UGraph.univ_inconsistency) Util.union (** We should only compare constructors at convertible types, so this is only an opportunity to unify universes. But what about qualities? *) val compare_constructor_instances : evar_map -> UVars.Instance.t -> UVars.Instance.t -> (evar_map, UGraph.univ_inconsistency) Util.union (** {6 Unification problems} *) type unification_pb = conv_pb * env * constr * constr (** [add_unification_pb ?tail pb sigma] Add a unification problem [pb] to [sigma], if not already present. Put it at the end of the list if [tail] is true, by default it is false. *) val add_unification_pb : ?tail:bool -> unification_pb -> evar_map -> evar_map (** {6 Removing hyps in evars'context} raise OccurHypInSimpleClause if the removal breaks dependencies *) type clear_dependency_error = | OccurHypInSimpleClause of Id.t option | EvarTypingBreak of EConstr.existential | NoCandidatesLeft of Evar.t exception ClearDependencyError of Id.t * clear_dependency_error * GlobRef.t option (** Restrict an undefined evar according to a (sub)filter and candidates. The evar will be defined if there is only one candidate left, @raise ClearDependencyError NoCandidatesLeft if the filter turns the candidates into an empty list. *) val restrict_evar : evar_map -> Evar.t -> Filter.t -> constr list option -> evar_map * Evar.t val clear_hyps_in_evi : env -> evar_map -> named_context_val -> types -> Id.Set.t -> evar_map * named_context_val * types val clear_hyps2_in_evi : env -> evar_map -> named_context_val -> types -> types -> Id.Set.t -> evar_map * named_context_val * types * types val check_and_clear_in_constr : Environ.env -> Evd.evar_map -> clear_dependency_error -> Names.Id.Set.t -> EConstr.constr -> Evd.evar_map type csubst val empty_csubst : csubst val csubst_subst : Evd.evar_map -> csubst -> constr -> constr type ext_named_context val ext_named_context_of_env : hypnaming:naming_mode -> env -> evar_map -> ext_named_context val ext_named_context_val : ext_named_context -> named_context_val val ext_csubst : ext_named_context -> csubst val default_ext_instance : ext_named_context -> constr SList.t val ext_rev_subst : ext_named_context -> Id.t -> constr val push_rel_decl_to_named_context : hypnaming:naming_mode -> evar_map -> rel_declaration -> ext_named_context -> ext_named_context val push_rel_context_to_named_context : hypnaming:naming_mode -> Environ.env -> evar_map -> types -> named_context_val * types * constr SList.t * csubst val generalize_evar_over_rels : evar_map -> existential -> types * constr list val subterm_source : Evar.t -> ?where:Evar_kinds.subevar_kind -> Evar_kinds.t Loc.located -> Evar_kinds.t Loc.located val meta_counter_summary_tag : int Summary.Dyn.tag rocq-9.2.0/engine/evd.ml000066400000000000000000001733571516144147600150740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a list val filter_array : t -> 'a array -> 'a array val filter_slist : t -> 'a SList.t -> 'a SList.t val extend : int -> t -> t val compose : t -> t -> t val apply_subfilter : t -> bool list -> t val restrict_upon : t -> int -> (int -> bool) -> t option val map_along : (bool -> 'a -> bool) -> t -> 'a list -> t val make : bool list -> t val repr : t -> bool list option type compact = | Empty | TCons of int * compact | FCons of int * compact val unfold : t -> compact option end = struct type compact = | Empty | TCons of int * compact | FCons of int * compact let rec compact l = match l with | [] -> Empty | true :: l -> begin match compact l with | TCons (n, c) -> TCons (n + 1, c) | (Empty | FCons _ as c) -> TCons (1, c) end | false :: l -> begin match compact l with | FCons (n, c) -> FCons (n + 1, c) | (Empty | TCons _ as c) -> FCons (1, c) end type t = { data : bool list option; compact : compact; } (** We guarantee through the interface that if a filter is [Some _] then it contains at least one [false] somewhere. *) let identity = { data = None; compact = Empty } let rec equal l1 l2 = match l1, l2 with | [], [] -> true | h1 :: l1, h2 :: l2 -> (if h1 then h2 else not h2) && equal l1 l2 | _ -> false let equal l1 l2 = match l1.data, l2.data with | None, None -> true | Some _, None | None, Some _ -> false | Some l1, Some l2 -> equal l1 l2 let rec is_identity = function | [] -> true | true :: l -> is_identity l | false :: _ -> false let normalize f = if is_identity f then identity else { data = Some f; compact = compact f } let filter_list f l = match f.data with | None -> l | Some f -> CList.filter_with f l let filter_array f v = match f.data with | None -> v | Some f -> CArray.filter_with f v let filter_slist f l = match f.data with | None -> l | Some f -> let rec filter f l = match f, SList.view l with | [], None -> SList.empty | true :: f, Some (o, l) -> SList.cons_opt o (filter f l) | false :: f, Some (_, l) -> filter f l | _ :: _, None | [], Some _ -> invalid_arg "List.filter_with" in filter f l let rec extend n l = if n = 0 then l else extend (pred n) (true :: l) let extend n f = match f.data with | None -> identity | Some f0 -> let compact = match f.compact with | Empty -> assert false | TCons (m, c) -> TCons (n + m, c) | c -> TCons (n, c) in { data = Some (extend n f0); compact } let compose f1 f2 = match f1.data with | None -> f2 | Some f1 -> match f2.data with | None -> identity | Some f2 -> normalize (CList.filter_with f1 f2) let apply_subfilter_array filter subfilter = (* In both cases we statically know that the argument will contain at least one [false] *) match filter.data with | None -> let l = Array.to_list subfilter in { data = Some l; compact = compact l } | Some f -> let len = Array.length subfilter in let fold b (i, ans) = if b then let () = assert (0 <= i) in (pred i, Array.unsafe_get subfilter i :: ans) else (i, false :: ans) in let data = snd (List.fold_right fold f (pred len, [])) in { data = Some data; compact = compact data } let apply_subfilter filter subfilter = apply_subfilter_array filter (Array.of_list subfilter) let restrict_upon f len p = let newfilter = Array.init len p in if Array.for_all (fun id -> id) newfilter then None else Some (apply_subfilter_array f newfilter) let map_along f flt l = let ans = match flt.data with | None -> List.map (fun x -> f true x) l | Some flt -> List.map2 f flt l in normalize ans let make l = normalize l let repr f = f.data let unfold f = match f.data with | None -> None | Some _ -> Some f.compact end module Abstraction = struct type abstraction = | Abstract | Imitate type t = abstraction list let identity = [] let abstract_last l = Abstract :: l end (* The kinds of existential variables are now defined in [Evar_kinds] *) (* The type of mappings for existential variables *) module Store = Store.Make () let string_of_existential evk = "?X" ^ string_of_int (Evar.repr evk) type defined = [ `defined ] type undefined = [ `undefined ] type _ evar_body = | Evar_empty : undefined evar_body | Evar_defined : econstr -> defined evar_body type (_, 'a) when_undefined = | Defined : (defined, 'a) when_undefined | Undefined : 'a -> (undefined, 'a) when_undefined type 'a evar_info = { evar_concl : ('a, constr) when_undefined; evar_hyps : named_context_val; evar_body : 'a evar_body; evar_filter : Filter.t; evar_abstract_arguments : ('a, Abstraction.t) when_undefined; evar_source : Evar_kinds.t Loc.located; evar_candidates : ('a, constr list option) when_undefined; (* if not None, list of allowed instances *) evar_relevance: Sorts.relevance; } type any_evar_info = EvarInfo : 'a evar_info -> any_evar_info let instance_mismatch () = anomaly (Pp.str "Signature and its instance do not match.") let evar_concl evi = match evi.evar_concl with | Undefined c -> c let evar_filter evi = evi.evar_filter let evar_body evi = evi.evar_body let evar_context evi = named_context_of_val evi.evar_hyps let evar_filtered_context evi = Filter.filter_list (evar_filter evi) (evar_context evi) let evar_candidates evi = match evi.evar_candidates with | Undefined c -> c let evar_abstract_arguments evi = match evi.evar_abstract_arguments with | Undefined c -> c let evar_relevance evi = evi.evar_relevance let evar_hyps evi = evi.evar_hyps let evar_filtered_hyps evi = match Filter.repr (evar_filter evi) with | None -> evar_hyps evi | Some filter -> let rec make_hyps filter ctxt = match filter, ctxt with | [], [] -> empty_named_context_val | false :: filter, _ :: ctxt -> make_hyps filter ctxt | true :: filter, decl :: ctxt -> let hyps = make_hyps filter ctxt in push_named_context_val decl hyps | _ -> instance_mismatch () in make_hyps filter (evar_context evi) let evar_env env evi = Environ.reset_with_named_context evi.evar_hyps env let evar_filtered_env env evi = Environ.reset_with_named_context (evar_filtered_hyps evi) env let evar_identity_subst evi = let len = match Filter.repr evi.evar_filter with | None -> List.length @@ Environ.named_context_of_val evi.evar_hyps | Some f -> List.count (fun b -> b) f in SList.defaultn len SList.empty let map_evar_body (type a) f : a evar_body -> a evar_body = function | Evar_empty -> Evar_empty | Evar_defined d -> Evar_defined (f d) let map_when_undefined (type a b) f : (a, b) when_undefined -> (a, b) when_undefined = function | Defined -> Defined | Undefined x -> Undefined (f x) let map_evar_info f evi = {evi with evar_body = map_evar_body f evi.evar_body; evar_hyps = map_named_val (fun d -> NamedDecl.map_constr f d) evi.evar_hyps; evar_concl = map_when_undefined f evi.evar_concl; evar_candidates = map_when_undefined (fun c -> Option.map (List.map f) c) evi.evar_candidates } (* This exception is raised by *.existential_value *) exception NotInstantiatedEvar (* Note: let-in contributes to the instance *) let evar_instance_array empty push info args = let rec instrec pos filter args = match filter with | Filter.Empty -> if SList.is_empty args then empty else instance_mismatch () | Filter.TCons (n, filter) -> instpush pos n filter args | Filter.FCons (n, filter) -> instrec (pos + n) filter args and instpush pos n filter args = if n <= 0 then instrec pos filter args else match args with | SList.Nil -> assert false | SList.Cons (c, args) -> let d = Range.get info.evar_hyps.env_named_idx pos in let id = NamedDecl.get_id d in push id c (instpush (pos + 1) (n - 1) filter args) | SList.Default (m, args) -> if m <= n then instpush (pos + m) (n - m) filter args else instrec (pos + n) filter (SList.defaultn (m - n) args) in match Filter.unfold (evar_filter info) with | None -> let rec instance pos args = match args with | SList.Nil -> empty | SList.Cons (c, args) -> let d = Range.get info.evar_hyps.env_named_idx pos in let id = NamedDecl.get_id d in push id c (instance (pos + 1) args) | SList.Default (n, args) -> instance (pos + n) args in instance 0 args | Some filter -> instrec 0 filter args let make_evar_instance_array info args = if SList.is_default args then [] else let push id c l = if isVarId id c then l else (id, c) :: l in evar_instance_array [] push info args type 'a in_ustate = 'a * UState.t (*************************) (* Unification state *) type conv_pb = Conversion.conv_pb type evar_constraint = conv_pb * Environ.env * constr * constr (** Exporting from Evarnames. *) let generate_goal_names = Evarnames.generate_goal_names module EvMap = Evar.Map type evar_flags = { obligation_evars : Evar.Set.t; aliased_evars : Evar.t Evar.Map.t; typeclass_evars : Evar.Set.t; impossible_case_evars : Evar.Set.t; rewrite_rule_evars : Evar.Set.t; } type side_effect_role = | Schema of inductive * string type side_effects = { seff_safeenv : Safe_typing.safe_environment option; (* If seff_safeenv = Some senv, then senv = Global.safe_env + seff_private *) seff_labels : Id.Set.t; seff_private : Safe_typing.private_constants; seff_roles : side_effect_role Cmap_env.t; seff_univs : UState.named_universes_entry Cmap_env.t; } module FutureGoals : sig type t val comb : t -> Evar.t list val map_filter : (Evar.t -> Evar.t option) -> t -> t (** Applies a function on the future goals *) val filter : (Evar.t -> bool) -> t -> t (** Applies a filter on the future goals *) type stack val empty_stack : stack val push : stack -> stack val pop : stack -> t * stack val add : Evar.t -> stack -> stack val remove : Evar.t -> stack -> stack val fold : ('a -> Evar.t -> 'a) -> 'a -> stack -> 'a val pr_stack : stack -> Pp.t end = struct type t = { uid : int; comb : Evar.t Int.Map.t; revmap : int Evar.Map.t; } let comb g = (* Keys are reversed, highest number is last introduced *) Int.Map.fold (fun _ evk accu -> evk :: accu) g.comb [] type stack = t list let set f = function | [] -> anomaly Pp.(str"future_goals stack should not be empty") | hd :: tl -> f hd :: tl let add evk stack = let add fgl = let comb = Int.Map.add fgl.uid evk fgl.comb in let revmap = Evar.Map.add evk fgl.uid fgl.revmap in let uid = fgl.uid + 1 in let () = assert (0 <= uid) in { comb; revmap; uid } in set add stack let remove e stack = let remove fgl = let comb, revmap = match Evar.Map.find e fgl.revmap with | index -> (Int.Map.remove index fgl.comb, Evar.Map.remove e fgl.revmap) | exception Not_found -> fgl.comb, fgl.revmap in { comb; revmap; uid = fgl.uid } in List.map remove stack let empty = { uid = 0; comb = Int.Map.empty; revmap = Evar.Map.empty; } let empty_stack = [empty] let push stack = empty :: stack let pop stack = match stack with | [] -> anomaly Pp.(str"future_goals stack should not be empty") | hd :: tl -> hd, tl let fold f acc stack = let future_goals = List.hd stack in List.fold_left f acc (comb future_goals) let filter f fgl = let fold index evk (comb, revmap) = if f evk then (comb, revmap) else (Int.Map.remove index comb, Evar.Map.remove evk revmap) in let (comb, revmap) = Int.Map.fold fold fgl.comb (fgl.comb, fgl.revmap) in { comb; revmap; uid = fgl.uid } let map_filter f fgl = let fold index evk (comb, revmap) = match f evk with | None -> (comb, revmap) | Some evk' -> (Int.Map.add index evk' comb, Evar.Map.add evk' index revmap) in let (comb, revmap) = Int.Map.fold fold fgl.comb (Int.Map.empty, Evar.Map.empty) in { comb; revmap; uid = fgl.uid } let pr_stack stack = let open Pp in let pr_future_goals fgl = let comb = comb fgl in prlist_with_sep spc Evar.print comb in if List.is_empty stack then str"(empty stack)" else prlist_with_sep (fun () -> str"||") pr_future_goals stack end type evar_map = { (* Existential variables *) defn_evars : defined evar_info EvMap.t; undf_evars : undefined evar_info EvMap.t; evar_names : Evarnames.t; candidate_evars : Evar.Set.t; (* The subset of undefined evars with a non-empty candidate list. *) (** Universes *) universes : UState.t; (** Conversion problems *) conv_pbs : evar_constraint list; last_mods : Evar.Set.t; evar_flags : evar_flags; (** Interactive proofs *) effects : side_effects; future_goals : FutureGoals.stack; (** list of newly created evars, to be eventually turned into goals if not solved.*) given_up : Evar.Set.t; shelf : Evar.t list list; extras : Store.t; } let find d e = try EvarInfo (EvMap.find e d.undf_evars) with Not_found -> EvarInfo (EvMap.find e d.defn_evars) let rec thin_val = function | [] -> [] | (id, c) :: tl -> match Constr.kind c with | Constr.Var v -> if Id.equal id v then thin_val tl else (id, make_substituend c) :: (thin_val tl) | _ -> (id, make_substituend c) :: (thin_val tl) let rec find_var id = function | [] -> raise_notrace Not_found | (idc, c) :: subst -> if Id.equal id idc then c else find_var id subst let replace_vars sigma var_alist x = let var_alist = thin_val var_alist in match var_alist with | [] -> x | _ -> let rec substrec n c = match Constr.kind c with | Constr.Var id -> begin match find_var id var_alist with | var -> (lift_substituend n var) | exception Not_found -> c end | Constr.Evar (evk, args) -> let EvarInfo evi = find sigma evk in let args' = substrec_instance n (evar_filtered_context evi) args in if args' == args then c else Constr.mkEvar (evk, args') | _ -> Constr.map_with_binders succ substrec n c and substrec_instance n ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (c, args) -> let c' = match c with | None -> begin match find_var (NamedDecl.get_id decl) var_alist with | var -> Some (lift_substituend n var) | exception Not_found -> None end | Some c -> let c' = substrec n c in if isVarId (NamedDecl.get_id decl) c' then None else Some c' in SList.cons_opt c' (substrec_instance n ctx args) | _ :: _, None | [], Some _ -> instance_mismatch () in substrec 0 x let instantiate_evar_array sigma info c args = let inst = make_evar_instance_array info args in match inst with | [] -> c | _ -> replace_vars sigma inst c let expand_existential sigma (evk, args) = let EvarInfo evi = find sigma evk in let rec expand ctx args = match ctx, SList.view args with | [], None -> [] | _ :: ctx, Some (Some c, args) -> c :: expand ctx args | decl :: ctx, Some (None, args) -> mkVar (NamedDecl.get_id decl) :: expand ctx args | [], Some _ | _ :: _, None -> instance_mismatch () in expand (evar_filtered_context evi) args let expand_existential0 = expand_existential (*** Lifting primitive from Evar.Map. ***) let add_name evk basename ?parent evd = { evd with evar_names = Evarnames.add basename evk ?parent evd.evar_names } let transfer_name evk evk' evd = { evd with evar_names = Evarnames.transfer_name evk evk' evd.evar_names } let add_with_name (type a) ?name ?parent ~typeclass_candidate ~rrpat d e (i : a evar_info) = match i.evar_body with | Evar_empty -> let evar_names = match name with | Some (basename, fresh) -> (* If fresh (i.e. coming from ?[?ident] syntax), we first check for conflicts. *) if fresh then Evarnames.add_fresh basename e ?parent d.evar_names else Evarnames.add basename e ?parent d.evar_names | None -> d.evar_names in let evar_flags = if typeclass_candidate then let flags = d.evar_flags in { flags with typeclass_evars = Evar.Set.add e flags.typeclass_evars } else d.evar_flags in let evar_flags = if rrpat then { evar_flags with rewrite_rule_evars = Evar.Set.add e evar_flags.rewrite_rule_evars } else evar_flags in let evar_flags = match i.evar_source with | _, ImpossibleCase -> { evar_flags with impossible_case_evars = Evar.Set.add e evar_flags.impossible_case_evars } | _ -> evar_flags in let candidate_evars = match i.evar_candidates with | Undefined None -> Evar.Set.remove e d.candidate_evars | Undefined (Some _) -> Evar.Set.add e d.candidate_evars in { d with undf_evars = EvMap.add e i d.undf_evars; evar_names; evar_flags; candidate_evars } | Evar_defined _ -> let evar_names = Evarnames.remove e d.evar_names in { d with defn_evars = EvMap.add e i d.defn_evars; evar_names } (** Evd.add is a low-level function mainly used to update the evar_info associated to an evar, so we prevent registering its typeclass status. *) let add d e i = add_with_name ~typeclass_candidate:false ~rrpat:false d e i (*** Evar flags: typeclasses, aliased or obligation flag *) let get_typeclass_evars evd = evd.evar_flags.typeclass_evars let set_typeclass_evars evd tcs = let flags = evd.evar_flags in let tcs = Evar.Set.filter (fun evk -> Evar.Map.mem evk evd.undf_evars) tcs in { evd with evar_flags = { flags with typeclass_evars = tcs } } let is_typeclass_evar evd evk = let flags = evd.evar_flags in Evar.Set.mem evk flags.typeclass_evars let get_obligation_evars evd = evd.evar_flags.obligation_evars let set_obligation_evar evd evk = let flags = evd.evar_flags in let evar_flags = { flags with obligation_evars = Evar.Set.add evk flags.obligation_evars } in { evd with evar_flags } let is_obligation_evar evd evk = let flags = evd.evar_flags in Evar.Set.mem evk flags.obligation_evars let get_impossible_case_evars evd = evd.evar_flags.impossible_case_evars let get_rewrite_rule_evars evd = evd.evar_flags.rewrite_rule_evars let is_rewrite_rule_evar evd evk = let flags = evd.evar_flags in Evar.Set.mem evk flags.rewrite_rule_evars (** Inheritance of flags: for evar-evar and restriction cases *) let inherit_evar_flags evar_flags evk evk' = if Evar.Set.mem evk evar_flags.rewrite_rule_evars then CErrors.anomaly Pp.(str "Tried to define or restrict a rewrite rule evar."); let evk_typeclass = Evar.Set.mem evk evar_flags.typeclass_evars in let evk_obligation = Evar.Set.mem evk evar_flags.obligation_evars in let evk_impossible = Evar.Set.mem evk evar_flags.impossible_case_evars in let aliased_evars = Evar.Map.add evk evk' evar_flags.aliased_evars in let typeclass_evars = if evk_typeclass then let typeclass_evars = Evar.Set.remove evk evar_flags.typeclass_evars in Evar.Set.add evk' typeclass_evars else evar_flags.typeclass_evars in let obligation_evars = if evk_obligation then let obligation_evars = Evar.Set.remove evk evar_flags.obligation_evars in Evar.Set.add evk' obligation_evars else evar_flags.obligation_evars in let impossible_case_evars = if evk_impossible then let impossible_case_evars = Evar.Set.remove evk evar_flags.impossible_case_evars in Evar.Set.add evk' impossible_case_evars else evar_flags.impossible_case_evars in let rewrite_rule_evars = evar_flags.rewrite_rule_evars in { obligation_evars; aliased_evars; typeclass_evars; impossible_case_evars; rewrite_rule_evars } (** Removal: in all other cases of definition *) let remove_evar_flags evk evar_flags = if Evar.Set.mem evk evar_flags.rewrite_rule_evars then CErrors.anomaly Pp.(str "Tried to define or restrict a rewrite rule evar."); { typeclass_evars = Evar.Set.remove evk evar_flags.typeclass_evars; obligation_evars = Evar.Set.remove evk evar_flags.obligation_evars; impossible_case_evars = Evar.Set.remove evk evar_flags.impossible_case_evars; (* Aliasing information is kept. *) aliased_evars = evar_flags.aliased_evars; (* Cannot be a rewrite rule evar *) rewrite_rule_evars = evar_flags.rewrite_rule_evars } (** New evars *) let evar_counter_summary_name = "evar counter" (* Generator of existential names *) let evar_ctr, evar_counter_summary_tag = Summary.ref_tag 0 ~name:evar_counter_summary_name let new_untyped_evar () = incr evar_ctr; Evar.unsafe_of_int !evar_ctr let default_source = Loc.tag @@ Evar_kinds.InternalHole let remove d e = let undf_evars = EvMap.remove e d.undf_evars in let defn_evars = EvMap.remove e d.defn_evars in let future_goals = FutureGoals.remove e d.future_goals in let evar_flags = remove_evar_flags e d.evar_flags in let candidate_evars = Evar.Set.remove e d.candidate_evars in { d with undf_evars; defn_evars; future_goals; evar_flags; candidate_evars } let find_defined d e = EvMap.find_opt e d.defn_evars let find_undefined d e = EvMap.find e d.undf_evars let mem d e = EvMap.mem e d.undf_evars || EvMap.mem e d.defn_evars let undefined_map d = d.undf_evars let defined_map d = d.defn_evars let drop_all_defined d = { d with defn_evars = EvMap.empty } (* spiwack: not clear what folding over an evar_map, for now we shall simply fold over the inner evar_map. *) let fold f d a = let f evk evi accu = f evk (EvarInfo evi) accu in EvMap.fold f d.defn_evars (EvMap.fold f d.undf_evars a) let fold_undefined f d a = EvMap.fold f d.undf_evars a type map = { map : 'r. Evar.t -> 'r evar_info -> 'r evar_info } let raw_map f d = let defn_evars = EvMap.Smart.mapi f.map d.defn_evars in let undf_evars = EvMap.Smart.mapi f.map d.undf_evars in { d with defn_evars; undf_evars; } let raw_map_undefined f d = { d with undf_evars = EvMap.Smart.mapi f d.undf_evars; } let is_evar = mem let is_defined d e = EvMap.mem e d.defn_evars let is_undefined d e = EvMap.mem e d.undf_evars let existential_opt_value d (n, args) = match EvMap.find_opt n d.defn_evars with | None -> None | Some info -> let Evar_defined c = evar_body info in Some (instantiate_evar_array d info c args) let existential_value d ev = match existential_opt_value d ev with | None -> raise NotInstantiatedEvar | Some v -> v let existential_opt_value0 = existential_opt_value let existential_expand_value0 sigma (evk, args) = match existential_opt_value sigma (evk, args) with | None -> let args = expand_existential sigma (evk, args) in CClosure.EvarUndefined (evk, args) | Some c -> CClosure.EvarDefined c let mkLEvar sigma (evk, args) = let EvarInfo evi = find sigma evk in let fold decl arg accu = if isVarId (NamedDecl.get_id decl) arg then SList.default accu else SList.cons arg accu in let args = List.fold_right2 fold (evar_filtered_context evi) args SList.empty in mkEvar (evk, args) let is_relevance_irrelevant sigma r = match UState.nf_relevance sigma.universes r with | Irrelevant -> true | Relevant | RelevanceVar _ -> false let get_senv_side_effects eff = match eff.seff_safeenv with | Some senv -> senv | None -> let (_, senv) = Safe_typing.export_private_constants eff.seff_private (Global.safe_env ()) in senv let evar_handler sigma = let evar_expand ev = existential_expand_value0 sigma ev in let qvar_irrelevant q = is_relevance_irrelevant sigma (Sorts.RelevanceVar q) in let evar_irrelevant (evk, _) = match find sigma evk with | EvarInfo evi -> is_relevance_irrelevant sigma evi.evar_relevance | exception Not_found -> false (* Should be an anomaly *) in let evar_repack ev = mkLEvar sigma ev in let abstr_const cst = (* XXX: be more efficient *) let open Declarations in let senv = get_senv_side_effects sigma.effects in let env = Safe_typing.env_of_safe_env senv in let cb = Environ.lookup_constant cst env in let drop_opaque = function | OpaqueDef _ -> OpaqueDef () | Def _ | Undef _ | Primitive _ | Symbol _ as body -> body in let drop_code = function | None -> Vmemitcodes.BCconstant | Some (Vmemitcodes.BCdefined (mask, idx, patch)) -> let code () = Environ.lookup_vm_code idx env in Vmemitcodes.BCdefined (mask, code, patch) | Some (BCalias _ | BCconstant as code) -> code in { cb with const_body = drop_opaque cb.const_body; const_body_code = drop_code cb.const_body_code } in let qual_equal q1 q2 = UState.check_eq_quality sigma.universes q1 q2 in { CClosure.evar_expand; evar_irrelevant; evar_repack; qvar_irrelevant; qual_equal; abstr_const } let existential_type_opt d (n, args) = match find_undefined d n with | exception Not_found -> None | info -> Some (instantiate_evar_array d info (evar_concl info) args) let existential_type d n = match existential_type_opt d n with | Some t -> t | None -> anomaly (str "Evar " ++ str (string_of_existential (fst n)) ++ str " was not declared.") let add_univ_constraints d c = { d with universes = UState.add_univ_constraints d.universes c } let add_poly_constraints ?src d c = { d with universes = UState.add_poly_constraints ?src d.universes c } let add_constraints d c = { d with universes = UState.add_constraints d.universes c } (*** /Lifting... ***) (* evar_map are considered empty disregarding histories *) let is_empty d = EvMap.is_empty d.defn_evars && EvMap.is_empty d.undf_evars && List.is_empty d.conv_pbs let cmap f evd = { evd with defn_evars = EvMap.map (map_evar_info f) evd.defn_evars; undf_evars = EvMap.map (map_evar_info f) evd.undf_evars } (* spiwack: deprecated *) let create_evar_defs sigma = { sigma with conv_pbs=[]; last_mods=Evar.Set.empty } let empty_evar_flags = { obligation_evars = Evar.Set.empty; aliased_evars = Evar.Map.empty; typeclass_evars = Evar.Set.empty; impossible_case_evars = Evar.Set.empty; rewrite_rule_evars = Evar.Set.empty; } let empty_side_effects = { seff_safeenv = None; seff_labels = Id.Set.empty; seff_private = Safe_typing.empty_private_constants; seff_roles = Cmap_env.empty; seff_univs = Cmap_env.empty; } let empty = { defn_evars = EvMap.empty; undf_evars = EvMap.empty; universes = UState.empty; conv_pbs = []; last_mods = Evar.Set.empty; evar_flags = empty_evar_flags; candidate_evars = Evar.Set.empty; effects = empty_side_effects; evar_names = Evarnames.empty; (* id<->key for undefined evars *) future_goals = FutureGoals.empty_stack; given_up = Evar.Set.empty; shelf = [[]]; extras = Store.empty; } let from_env ?binders e = { empty with universes = UState.from_env ?binders e } let from_ctx uctx = { empty with universes = uctx } let has_undefined evd = not (EvMap.is_empty evd.undf_evars) let has_given_up evd = not (Evar.Set.is_empty evd.given_up) let has_shelved evd = not (List.for_all List.is_empty evd.shelf) let merge_universe_context evd uctx' = { evd with universes = UState.union evd.universes uctx' } let set_universe_context evd uctx' = { evd with universes = uctx' } (* TODO: make unique *) let add_conv_pb ?(tail=false) pb d = if tail then {d with conv_pbs = d.conv_pbs @ [pb]} else {d with conv_pbs = pb::d.conv_pbs} let conv_pbs d = d.conv_pbs let evar_source evi = evi.evar_source let evar_ident evk evd = Evarnames.name_of evk evd.evar_names let evar_has_name evk evd = Evarnames.has_name evk evd.evar_names let evar_has_unambiguous_name evk evd = Evarnames.has_unambiguous_name evk evd.evar_names let evar_key name evd = Evarnames.resolve name evd.evar_names let get_aliased_evars evd = evd.evar_flags.aliased_evars let max_undefined_with_candidates evd = try Some (Evar.Set.max_elt evd.candidate_evars) with Not_found -> None let is_aliased_evar evd evk = try Some (Evar.Map.find evk evd.evar_flags.aliased_evars) with Not_found -> None let downcast evk ccl evd = let evar_info = EvMap.find evk evd.undf_evars in let evar_info' = { evar_info with evar_concl = Undefined ccl } in { evd with undf_evars = EvMap.add evk evar_info' evd.undf_evars } let mem_head_evar c evars = (* Note: evar-sensitive code *) let rec hrec c = match kind c with | Evar (evk,_) -> Evar.Set.mem evk evars | Case (_, _, _, _, _, c, _) -> hrec c | App (c,_) -> hrec c | Cast (c,_,_) -> hrec c | Proj (_, _, c) -> hrec c | _ -> false in hrec c let has_evar evars (pbty,_,t1,t2) = match evars with | None -> true | Some evars -> mem_head_evar t1 evars || mem_head_evar t2 evars (* extracts conversion problems that satisfy predicate p *) (* Note: conv_pbs not satisying p are stored back in reverse order *) let extract_conv_pbs evd p = let (pbs,pbs1) = List.fold_left (fun (pbs,pbs1) pb -> if p pb then (pb::pbs,pbs1) else (pbs,pb::pbs1)) ([],[]) evd.conv_pbs in {evd with conv_pbs = pbs1; last_mods = Evar.Set.empty}, pbs let extract_changed_conv_pbs evd = extract_conv_pbs evd (has_evar (Some evd.last_mods)) let extract_changed_conv_pbs_from evd evars= extract_conv_pbs evd (has_evar evars) let extract_all_conv_pbs evd = extract_conv_pbs evd (fun _ -> true) let loc_of_conv_pb evd (pbty,env,t1,t2) = match kind (fst (decompose_app t1)) with | Evar (evk1,_) -> let EvarInfo evi = find evd evk1 in fst (evar_source evi) | _ -> match kind (fst (decompose_app t2)) with | Evar (evk2,_) -> let EvarInfo evi = find evd evk2 in fst (evar_source evi) | _ -> None (**********************************************************) (* Sort variables *) type rigid = UState.rigid = | UnivRigid | UnivFlexible of bool (** Is substitution by an algebraic ok? *) let univ_rigid = UnivRigid let univ_flexible = UnivFlexible false let univ_flexible_alg = UnivFlexible true let ustate d = d.universes let elim_graph d = UState.elim_graph d.universes let evar_universe_context d = ustate d let universe_context_set d = UState.universe_context_set d.universes let sort_context_set d = UState.sort_context_set d.universes let to_universe_context evd = UState.context evd.universes let univ_entry ~poly evd = UState.univ_entry ~poly evd.universes let check_univ_decl ~poly evd decl = UState.check_univ_decl ~poly evd.universes decl let check_univ_decl_early ~poly ~with_obls sigma udecl terms = let () = if with_obls && not @@ PolyFlags.univ_poly poly && (not udecl.UState.univdecl_extensible_instance || not udecl.UState.univdecl_extensible_constraints) then CErrors.user_err Pp.(str "Non extensible universe declaration not supported \ with monomorphic Program definitions.") in let vars = List.fold_left (fun acc b -> Univ.Level.Set.union acc (Vars.universes_of_constr b)) Univ.Level.Set.empty terms in let uctx = ustate sigma in let uctx = UState.collapse_sort_variables uctx in let uctx = UState.restrict uctx vars in ignore (UState.check_univ_decl ~poly uctx udecl) let restrict_universe_context evd vars = { evd with universes = UState.restrict evd.universes vars } let universe_subst evd = UState.subst evd.universes let merge_universe_context_set ?loc ?(sideff=false) rigid evd uctx' = {evd with universes = UState.merge_universe_context ?loc ~sideff rigid evd.universes uctx'} let merge_sort_context_set ?loc ?sort_rigid ?(sideff=false) ?src rigid evd ctx' = {evd with universes = UState.merge_sort_context ?loc ?sort_rigid ~sideff rigid ?src evd.universes ctx'} let with_sort_context_set ?loc ?sort_rigid ?src rigid d (a, ctx) = (merge_sort_context_set ?loc ?sort_rigid ?src rigid d ctx, a) let new_univ_level_variable ?loc ?name rigid evd = let uctx', u = UState.new_univ_variable ?loc rigid name evd.universes in ({evd with universes = uctx'}, u) let new_univ_variable ?loc ?name rigid evd = let uctx', u = UState.new_univ_variable ?loc rigid name evd.universes in ({evd with universes = uctx'}, Univ.Universe.make u) let new_quality_variable ?loc ?name evd = let uctx, q = UState.new_sort_variable ?loc ?name evd.universes in {evd with universes = uctx}, q let new_sort_info ?loc ?sort_rigid ?name rigid sigma = let (sigma, u) = new_univ_variable ?loc rigid sigma in let uctx, q = UState.new_sort_variable ?sort_rigid ?name sigma.universes in ({ sigma with universes = uctx }, q, u) let new_sort_variable ?loc ?sort_rigid ?name rigid sigma = let (sigma, u) = new_univ_variable ?loc rigid sigma in let uctx, q = UState.new_sort_variable ?loc ?sort_rigid ?name sigma.universes in ({ sigma with universes = uctx }, Sorts.qsort q u) let add_forgotten_univ d u = { d with universes = UState.add_forgotten_univ d.universes u } let make_nonalgebraic_variable evd u = { evd with universes = UState.make_nonalgebraic_variable evd.universes u } (****************************************) (* Operations on constants *) (****************************************) (* FIXME: do this more cleanly *) let lookup_constant env sigma c = match Environ.lookup_constant_opt c env with | Some cb -> cb | None -> if Safe_typing.is_empty_private_constants sigma.effects.seff_private then CErrors.anomaly Pp.(str "Constant " ++ Constant.print c ++ str" does not appear in the environment.") else let senv = get_senv_side_effects sigma.effects in Environ.lookup_constant c (Safe_typing.env_of_safe_env senv) let fresh_sort_in_quality ?loc ?(rigid=univ_flexible) evd s = with_sort_context_set ?loc rigid ~src:UState.Internal evd (UnivGen.fresh_sort_in_quality s) let fresh_instance ?loc ?names env sigma gr = let open GlobRef in let auctx = match gr with | VarRef _ -> UVars.AbstractContext.empty | ConstRef c -> let cb = lookup_constant env sigma c in Declareops.constant_polymorphic_context cb | IndRef (mind,_) | ConstructRef ((mind,_),_) -> let mib = lookup_mind mind env in Declareops.inductive_polymorphic_context mib in let names = Option.map (fun x -> gr, x) names in let u, ctx = UnivGen.fresh_instance_from ?loc auctx names in u, ctx let fresh_constant_instance ?loc ?(rigid=univ_flexible) env evd c = let (u, ctx) = fresh_instance env evd (GlobRef.ConstRef c) in with_sort_context_set ?loc rigid ~src:UState.Internal evd ((c, u), ctx) let fresh_inductive_instance ?loc ?sort_rigid ?(rigid=univ_flexible) env evd i = with_sort_context_set ?loc ?sort_rigid rigid ~src:UState.Internal evd (UnivGen.fresh_inductive_instance env i) let fresh_constructor_instance ?loc ?(rigid=univ_flexible) env evd c = with_sort_context_set ?loc rigid ~src:UState.Internal evd (UnivGen.fresh_constructor_instance env c) let fresh_array_instance ?loc ?(rigid=univ_flexible) env evd = with_sort_context_set ?loc rigid ~src:UState.Internal evd (UnivGen.fresh_array_instance env) let fresh_global ?loc ?(rigid=univ_flexible) ?names env evd gr = let (u, ctx) = fresh_instance ?loc ?names env evd gr in with_sort_context_set ?loc rigid ~src:UState.Internal evd (mkRef (gr, u), ctx) let is_flexible_level evd l = let uctx = evd.universes in UnivFlex.mem l (UState.subst uctx) let is_eq_sort s1 s2 = if Sorts.equal s1 s2 then None else Some (s1, s2) let normalize_universe_instance evd l = UState.nf_instance evd.universes l let normalize_sort evars s = UState.nf_sort evars.universes s (* FIXME inefficient *) let set_eq_sort evd s1 s2 = let s1 = normalize_sort evd s1 and s2 = normalize_sort evd s2 in match is_eq_sort s1 s2 with | None -> evd | Some (u1, u2) -> if not (UGraph.type_in_type (UState.ugraph evd.universes)) then add_constraints evd (UnivProblem.Set.singleton (UnivProblem.UEq (u1,u2))) else evd let set_eq_level d u1 u2 = add_univ_constraints d (Univ.enforce_eq_level u1 u2 Univ.UnivConstraints.empty) let set_leq_level d u1 u2 = add_univ_constraints d (Univ.enforce_leq_level u1 u2 Univ.UnivConstraints.empty) let set_eq_instances ?(flex=false) d u1 u2 = add_constraints d (UnivProblem.enforce_eq_instances_univs flex u1 u2 UnivProblem.Set.empty) let set_leq_sort evd s1 s2 = let s1 = normalize_sort evd s1 and s2 = normalize_sort evd s2 in match is_eq_sort s1 s2 with | None -> evd | Some (u1, u2) -> if not (UGraph.type_in_type (UState.ugraph evd.universes)) then add_constraints evd @@ UnivProblem.Set.singleton (UnivProblem.ULe (u1,u2)) else evd let set_eq_qualities evd q1 q2 = add_constraints evd @@ UnivProblem.Set.singleton (QEq (q1, q2)) let set_above_prop evd q = add_constraints evd @@ UnivProblem.Set.singleton (QLeq (Sorts.Quality.qprop, q)) let set_elim_to evd q1 q2 = add_constraints evd @@ UnivProblem.Set.singleton (QElimTo (q1, q2)) let check_eq evd s s' = let ustate = evd.universes in let univs = UState.ugraph ustate in UGraph.check_eq_sort Sorts.Quality.equal univs (UState.nf_sort ustate s) (UState.nf_sort ustate s') let check_leq evd s s' = let ustate = evd.universes in let univs = UState.ugraph ustate in UGraph.check_leq_sort Sorts.Quality.equal univs (UState.nf_sort ustate s) (UState.nf_sort ustate s') let check_univ_constraints evd csts = UGraph.check_constraints csts (UState.ugraph evd.universes) let check_elim_constraints evd csts = UState.check_elim_constraints evd.universes csts let check_poly_constraints evd (qcsts,ucsts) = check_elim_constraints evd qcsts && check_univ_constraints evd ucsts let check_quality_constraints evd qcst = let fold (q1, q2) accu = UnivProblem.Set.add (UnivProblem.QEq (q1, q2)) accu in let qcst = UVars.QPairSet.fold fold qcst UnivProblem.Set.empty in UState.check_constraints evd.universes qcst let fix_undefined_variables evd = { evd with universes = UState.fix_undefined_variables evd.universes } let nf_univ_variables evd = let uctx = UState.normalize_variables evd.universes in {evd with universes = uctx} let collapse_sort_variables ?except evd = let universes = UState.collapse_sort_variables ?except evd.universes in { evd with universes } let minimize_universes ?(collapse_sort_variables=true) evd = let uctx' = if collapse_sort_variables then UState.collapse_sort_variables evd.universes else evd.universes in let uctx' = UState.normalize_variables uctx' in let uctx' = UState.minimize uctx' in {evd with universes = uctx'} let universe_of_name evd s = UState.universe_of_name evd.universes s let quality_of_name evd s = UState.quality_of_name evd.universes s let is_rigid_qvar evd q = UState.is_rigid_qvar evd.universes q let universe_binders evd = UState.universe_binders evd.universes let universes evd = UState.ugraph evd.universes let update_sigma_univs ugraph evd = { evd with universes = UState.update_sigma_univs evd.universes ugraph } exception UniversesDiffer = UState.UniversesDiffer (**********************************************************) (* Side effects *) let concat_side_effects eff1 eff2 = { seff_safeenv = None; seff_labels = Id.Set.fold Id.Set.add eff1.seff_labels eff2.seff_labels; seff_private = Safe_typing.concat_private eff1.seff_private eff2.seff_private; seff_roles = Cmap_env.fold Cmap_env.add eff1.seff_roles eff2.seff_roles; seff_univs = Cmap_env.fold Cmap_env.add eff1.seff_univs eff2.seff_univs; } let emit_side_effects eff evd = let senv = get_senv_side_effects eff in let _, senv = Safe_typing.export_private_constants eff.seff_private senv in let effects = concat_side_effects eff evd.effects in let effects = { effects with seff_safeenv = Some senv } in { evd with effects; universes = UState.emit_side_effects eff.seff_private evd.universes } let set_side_effects eff evd = { evd with effects = eff } let eval_side_effects evd = evd.effects let push_side_effects ?role ?ts name de ctx effs = let senv = get_senv_side_effects effs in let senv = match ts with | None -> senv | Some ts -> Safe_typing.set_oracle ts senv in let (kn, prv), senv = Safe_typing.add_private_constant name ctx de senv in let seff_univs = if Univ.Level.Set.is_empty (fst ctx) then effs.seff_univs else Cmap_env.add kn (UState.Monomorphic_entry ctx, UnivNames.empty_binders) effs.seff_univs in let seff_roles = match role with | None -> effs.seff_roles | Some r -> Cmap_env.add kn r effs.seff_roles in let effs = { seff_private = Safe_typing.concat_private prv effs.seff_private; seff_labels = Id.Set.add (Constant.label kn) effs.seff_labels; seff_roles = seff_roles; seff_univs = seff_univs; seff_safeenv = Some senv; } in kn, effs let seff_mem_label id effs = Id.Set.mem id effs.seff_labels let seff_private eff = eff.seff_private let seff_roles effs = effs.seff_roles let seff_univs effs = effs.seff_univs (* Future goals *) let declare_future_goal evk evd = let future_goals = FutureGoals.add evk evd.future_goals in { evd with future_goals } let push_future_goals evd = { evd with future_goals = FutureGoals.push evd.future_goals } let pop_future_goals evd = let hd, future_goals = FutureGoals.pop evd.future_goals in hd, { evd with future_goals } let fold_future_goals f sigma = FutureGoals.fold f sigma sigma.future_goals let remove_future_goal evd evk = { evd with future_goals = FutureGoals.remove evk evd.future_goals } let pr_future_goals_stack evd = FutureGoals.pr_stack evd.future_goals let give_up ev evd = { evd with given_up = Evar.Set.add ev evd.given_up } let push_shelf evd = { evd with shelf = [] :: evd.shelf } let pop_shelf evd = match evd.shelf with | [] -> anomaly Pp.(str"shelf stack should not be empty") | hd :: tl -> hd, { evd with shelf = tl } let filter_shelf f evd = { evd with shelf = List.map (List.filter f) evd.shelf } let shelve evd l = match evd.shelf with | [] -> anomaly Pp.(str"shelf stack should not be empty") | hd :: tl -> { evd with shelf = (hd@l) :: tl } let unshelve evd l = { evd with shelf = List.map (List.filter (fun ev -> not (CList.mem_f Evar.equal ev l))) evd.shelf } let given_up evd = evd.given_up let shelf evd = List.flatten evd.shelf let mem_shelf e evd = List.exists (List.exists (fun e' -> Evar.equal e e')) evd.shelf let pr_shelf evd = let open Pp in if List.is_empty evd.shelf then str"(empty stack)" else prlist_with_sep (fun () -> str"||") (prlist_with_sep spc Evar.print) evd.shelf let new_pure_evar ?(src=default_source) ?(filter = Filter.identity) ~relevance ?(abstract_arguments = Abstraction.identity) ?candidates ?name ?parent ?(typeclass_candidate = false) ?(rrpat = false) sign evd typ = let evi = { evar_hyps = sign; evar_concl = Undefined typ; evar_body = Evar_empty; evar_filter = filter; evar_abstract_arguments = Undefined abstract_arguments; evar_source = src; evar_candidates = Undefined candidates; evar_relevance = relevance; } in let newevk = new_untyped_evar () in let evd = add_with_name evd ?name ?parent ~typeclass_candidate ~rrpat newevk evi in let evd = declare_future_goal newevk evd in (evd, newevk) let define_aux def undef evk body = let oldinfo = try EvMap.find evk undef with Not_found -> if EvMap.mem evk def then anomaly ~label:"Evd.define" (Pp.str "cannot define an evar twice.") else anomaly ~label:"Evd.define" (Pp.str "cannot define undeclared evar.") in let () = assert (oldinfo.evar_body == Evar_empty) in let newinfo = { oldinfo with evar_body = Evar_defined body; evar_concl = Defined; evar_candidates = Defined; evar_abstract_arguments = Defined; } in EvMap.add evk newinfo def, EvMap.remove evk undef (* define the existential of section path sp as the constr body *) let define_gen evk body evd evar_flags = let future_goals = FutureGoals.remove evk evd.future_goals in let evd = { evd with future_goals } in let (defn_evars, undf_evars) = define_aux evd.defn_evars evd.undf_evars evk body in let last_mods = match evd.conv_pbs with | [] -> evd.last_mods | _ -> Evar.Set.add evk evd.last_mods in let evar_names = Evarnames.remove evk evd.evar_names in let candidate_evars = Evar.Set.remove evk evd.candidate_evars in { evd with defn_evars; undf_evars; last_mods; evar_names; evar_flags; candidate_evars } (** By default, the obligation and evar tag of the evar is removed *) let define evk body evd = let evar_flags = remove_evar_flags evk evd.evar_flags in define_gen evk body evd evar_flags (** In case of an evar-evar solution, the flags are inherited *) let define_with_evar evk body evd = let evk' = fst (destEvar body) in let evar_flags = inherit_evar_flags evd.evar_flags evk evk' in let evd = unshelve evd [evk] in define_gen evk body evd evar_flags (* In case of restriction, we declare the aliasing and inherit the obligation and typeclass flags. *) let restrict evk filter ?candidates ?src evd = let evk' = new_untyped_evar () in let evar_info = EvMap.find evk evd.undf_evars in let len = Range.length evar_info.evar_hyps.env_named_idx in let id_inst = Filter.filter_slist filter (SList.defaultn len SList.empty) in let evar_info' = { evar_info with evar_filter = filter; evar_candidates = Undefined candidates; evar_source = (match src with None -> evar_info.evar_source | Some src -> src); } in let last_mods = match evd.conv_pbs with | [] -> evd.last_mods | _ -> Evar.Set.add evk evd.last_mods in let evar_names = Evarnames.transfer_name evk evk' evd.evar_names in let body = mkEvar(evk',id_inst) in let (defn_evars, undf_evars) = define_aux evd.defn_evars evd.undf_evars evk body in let evar_flags = inherit_evar_flags evd.evar_flags evk evk' in let evar_flags = match src with | Some (_,Evar_kinds.ImpossibleCase) -> { evar_flags with impossible_case_evars = Evar.Set.add evk' evar_flags.impossible_case_evars } | _ -> evar_flags in let candidate_evars = Evar.Set.remove evk evd.candidate_evars in let candidate_evars = match candidates with | None -> candidate_evars | Some _ -> Evar.Set.add evk' candidate_evars in let evd = { evd with undf_evars = EvMap.add evk' evar_info' undf_evars; defn_evars; last_mods; evar_names; evar_flags; candidate_evars } in (* Mark new evar as future goal, removing previous one, circumventing Proofview.advance but making Proof.run_tactic catch these. *) let evd = unshelve evd [evk] in let evd = remove_future_goal evd evk in let evd = declare_future_goal evk' evd in (evd, evk') let update_source evd evk src = let modify _ info = { info with evar_source = src } in { evd with undf_evars = EvMap.modify evk modify evd.undf_evars } let dependent_evar_ident ev evd = let EvarInfo evi = find evd ev in match evi.evar_source with | (_,Evar_kinds.VarInstance id) -> id | _ -> anomaly (str "Not an evar resulting of a dependent binding.") (**********************************************************) (* Extra data *) let get_extra_data evd = evd.extras let set_extra_data extras evd = { evd with extras } (*******************************************************************) (* The state monad with state an evar map. *) module MonadR = Monad.Make (struct type +'a t = evar_map -> evar_map * 'a let return a = fun s -> (s,a) let (>>=) x f = fun s -> let (s',a) = x s in f a s' let (>>) x y = fun s -> let (s',()) = x s in y s' let map f x = fun s -> on_snd f (x s) end) module Monad = Monad.Make (struct type +'a t = evar_map -> 'a * evar_map let return a = fun s -> (a,s) let (>>=) x f = fun s -> let (a,s') = x s in f a s' let (>>) x y = fun s -> let ((),s') = x s in y s' let map f x = fun s -> on_fst f (x s) end) (**********************************************************) (* Failure explanation *) type unsolvability_explanation = SeveralInstancesFound of int module Expand : sig type handle val empty_handle : handle val liftn_handle : int -> handle -> handle val kind : evar_map -> handle -> constr -> handle * (constr, constr, Sorts.t, UVars.Instance.t, Sorts.relevance) kind_of_term val expand : evar_map -> handle -> constr -> constr val expand_instance : skip: bool -> undefined evar_info -> handle -> econstr SList.t -> econstr SList.t end = struct type clos = { evc_map : (int * clos * Constr.t) Id.Map.t; (* Map each bound ident to its value and the depth it was introduced at *) evc_lift : int; (* number of binders crossed since last evar *) evc_stack : int list; (* stack of binders crossed at each evar *) evc_depth : int; (* length of evc_stack *) evc_cache : int Int.Map.t ref option; (* Cache get_lift on evc_stack *) } let empty_clos = { evc_lift = 0; evc_depth = 0; evc_stack = []; evc_map = Id.Map.empty; evc_cache = None; } let push_clos info clos args = let push id c map = Id.Map.add id (clos.evc_depth, clos, c) map in let nmap = evar_instance_array clos.evc_map push info args in { evc_lift = 0; evc_map = nmap; evc_depth = clos.evc_depth + 1; evc_stack = clos.evc_lift :: clos.evc_stack; evc_cache = Some (ref Int.Map.empty); } let find_clos clos id = match Id.Map.find_opt id clos.evc_map with | None -> None | Some (depth, nclos, v) -> let pos = clos.evc_depth - depth - 1 in let rec get_lift accu n lft = if Int.equal n 0 then accu else match lft with | [] -> assert false | k :: lft -> get_lift (accu + k) (n - 1) lft in let ans = match clos.evc_cache with | None -> assert false | Some cache -> match Int.Map.find_opt pos !cache with | None -> let ans = get_lift 0 pos clos.evc_stack in let () = cache := Int.Map.add pos ans !cache in ans | Some ans -> ans in let k = clos.evc_lift + ans in Some (k, nclos, v) type handle = { h_clos : clos; h_lift : Esubst.lift; } let empty_handle = { h_clos = empty_clos; h_lift = Esubst.el_id; } let liftn_clos n s = { s with evc_lift = s.evc_lift + n } let liftn_handle n h = { h_clos = liftn_clos n h.h_clos; h_lift = Esubst.el_liftn n h.h_lift; } let rec kind sigma h c = match Constr.kind c with | Rel n -> h, Rel (Esubst.reloc_rel n h.h_lift) | Var id as c0 -> begin match find_clos h.h_clos id with | None -> (h, c0) | Some (k, clos, v) -> let h = { h_clos = clos; h_lift = Esubst.el_shft k h.h_lift } in kind sigma h v end | Evar (evk, args) as c0 -> begin match EvMap.find_opt evk sigma.defn_evars with | None -> (h, c0) | Some info -> let Evar_defined c = evar_body info in let nclos = push_clos info h.h_clos args in kind sigma { h_lift = h.h_lift; h_clos = nclos } c end | Meta _ | Sort _ | Cast _ | Prod _ | Lambda _ | LetIn _ | App _ | Const _ | Ind _ | Construct _ | Case _ | Fix _ | CoFix _ | Proj _ | Int _ | Float _ | String _ | Array _ as c0 -> (h, c0) let expand0 sigma h c = let lift h = liftn_handle 1 h in let rec aux h c = match Constr.kind c with | Rel n -> let n' = Esubst.reloc_rel n h.h_lift in if Int.equal n n' then c else mkRel n' | Var id -> begin match find_clos h.h_clos id with | None -> c | Some (k, clos, v) -> let h = { h_clos = clos; h_lift = Esubst.el_shft k h.h_lift } in aux h v end | Evar (evk, args) -> (* for efficiency do not expand evars, just their instance *) let EvarInfo evi = find sigma evk in let push decl c args = if isVarId (NamedDecl.get_id decl) c then SList.default args else SList.cons c args in let rec expand ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (Some c, args) -> let c = aux h c in push decl c (expand ctx args) | decl :: ctx, Some (None, args) -> let c = aux h (mkVar (NamedDecl.get_id decl)) in push decl c (expand ctx args) | [], Some _ | _ :: _, None -> instance_mismatch () in let args = expand (evar_filtered_context evi) args in mkEvar (evk, args) | _ -> Constr.map_with_binders lift aux h c in aux h c let expand sigma h c = if Esubst.is_lift_id h.h_lift && Id.Map.is_empty h.h_clos.evc_map then c else expand0 sigma h c let expand_instance ~skip (evi : undefined evar_info) h (args : Constr.t SList.t) = if skip && Id.Map.is_empty h.h_clos.evc_map then args else let rec expand ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (None, args) -> let args = expand ctx args in let id = NamedDecl.get_id decl in if Id.Map.mem id h.h_clos.evc_map then (* Keep the non-default representation as kind will expand it *) SList.cons (mkVar id) args else if skip then SList.default args else SList.cons (mkVar id) args | decl :: ctx, Some (Some c, args) -> let args = expand ctx args in let id = NamedDecl.get_id decl in (* Same as above *) if skip && isVarId id c && not (Id.Map.mem id h.h_clos.evc_map) then SList.default args else SList.cons c args | [], Some _ | _ :: _, None -> instance_mismatch () in expand (evar_filtered_context evi) args end module MiniEConstr = struct module ERelevance = struct type t = Sorts.relevance let make r = r let unsafe_to_relevance r = r let kind sigma r = UState.nf_relevance sigma.universes r end module ESorts = struct type t = Sorts.t let make s = s let kind = normalize_sort let unsafe_to_sorts s = s end module EInstance = struct type t = UVars.Instance.t let make i = i let kind sigma i = if UVars.Instance.is_empty i then i else normalize_universe_instance sigma i let empty = UVars.Instance.empty let is_empty = UVars.Instance.is_empty let unsafe_to_instance t = t end type t = econstr let rec whd_evar sigma c = match Constr.kind c with | Evar ev -> let (h, knd) = Expand.kind sigma Expand.empty_handle c in if Constr.kind c == knd then c else whd_kind sigma h knd | App (f, args) when isEvar f -> (* Enforce smart constructor invariant on applications *) let (h, knd) = Expand.kind sigma Expand.empty_handle f in if Constr.kind f == knd then c else mkApp (whd_kind sigma h knd, args) | Cast (c0, k, t) when isEvar c0 -> (* Enforce smart constructor invariant on casts. *) let (h, knd) = Expand.kind sigma Expand.empty_handle c0 in if Constr.kind c0 == knd then c else mkCast (whd_kind sigma h knd, k, t) | _ -> c and whd_kind sigma h knd = (* we need to force the head as Expand.expand does not expand evar subterms *) whd_evar sigma (Expand.expand sigma h (Constr.of_kind knd)) let mkLEvar = mkLEvar let replace_vars = replace_vars let kind sigma c = Constr.kind (whd_evar sigma c) let kind_upto = kind let of_kind = Constr.of_kind let of_constr c = c let of_constr_array v = v let unsafe_to_constr c = c let unsafe_to_constr_array v = v let unsafe_eq = Refl let unsafe_relevance_eq = Refl type evclos = { evc_map : (int * Vars.substituend Lazy.t) Id.Map.t; (* Map each bound ident to its value and the depth it was introduced at *) evc_lift : int; (* number of binders crossed since last evar *) evc_stack : int list; (* stack of binders crossed at each evar *) evc_depth : int; (* length of evc_stack *) evc_cache : int Int.Map.t ref; (* Cache get_lift on evc_stack *) } let to_constr_gen ~expand ~ignore_missing sigma c = let saw_evar = ref false in let lsubst = universe_subst sigma in let univ_value l = UnivFlex.normalize_univ_variable lsubst l in let relevance_value r = UState.nf_relevance sigma.universes r in let qvar_value q = UState.nf_qvar sigma.universes q in let next s = { s with evc_lift = s.evc_lift + 1 } in let find clos id = match Id.Map.find_opt id clos.evc_map with | None -> None | Some (depth, lazy v) -> let pos = clos.evc_depth - depth - 1 in let rec get_lift accu n lft = if Int.equal n 0 then accu else match lft with | [] -> assert false | k :: lft -> get_lift (accu + k) (n - 1) lft in let ans = match Int.Map.find_opt pos clos.evc_cache.contents with | None -> let ans = get_lift 0 pos clos.evc_stack in let () = clos.evc_cache := Int.Map.add pos ans clos.evc_cache.contents in ans | Some ans -> ans in let k = clos.evc_lift + ans in Some (lift_substituend k v) in let rec self clos c = match Constr.kind c with | Var id -> begin match find clos id with | None -> c | Some v -> v end | Evar (evk, args) -> begin match EvMap.find_opt evk sigma.defn_evars with | None -> let () = saw_evar := true in begin match EvMap.find_opt evk sigma.undf_evars with | None -> if ignore_missing then let map c = self clos c in let args' = SList.Smart.map map args in if args' == args then c else mkEvar (evk, args') else raise Not_found | Some evi -> let rec inst ctx args = match ctx, SList.view args with | [], None -> SList.empty | decl :: ctx, Some (c, args) -> let c = match c with | None -> let c = find clos (NamedDecl.get_id decl) in if expand then match c with | None -> Some (mkVar (NamedDecl.get_id decl)) | Some _ -> c else c | Some c -> Some (self clos c) in SList.cons_opt c (inst ctx args) | _ :: _, None | [], Some _ -> instance_mismatch () in let args' = inst (evar_filtered_context evi) args in if args == args' then c else mkEvar (evk, args') end | Some info -> let Evar_defined c = evar_body info in let push id c map = Id.Map.add id (clos.evc_depth, lazy (make_substituend (self clos c))) map in let nmap = evar_instance_array clos.evc_map push info args in let nclos = { evc_lift = 0; evc_map = nmap; evc_depth = clos.evc_depth + 1; evc_stack = clos.evc_lift :: clos.evc_stack; evc_cache = ref Int.Map.empty; } in self nclos c end | _ -> UnivSubst.map_universes_opt_subst_with_binders next self relevance_value qvar_value univ_value clos c in let clos = { evc_lift = 0; evc_depth = 0; evc_stack = []; evc_map = Id.Map.empty; evc_cache = ref Int.Map.empty; } in let c = self clos c in !saw_evar, c let check_evar c = let exception SawEvar in let rec iter c = match Constr.kind c with | Evar _ -> raise SawEvar | _ -> Constr.iter iter c in try iter c; false with SawEvar -> true let to_constr ?(abort_on_undefined_evars=true) sigma c = let saw_evar, c = to_constr_gen ~expand:true ~ignore_missing:false sigma c in if abort_on_undefined_evars && saw_evar && check_evar c then anomaly ~label:"econstr" Pp.(str "grounding a non evar-free term") else c let to_constr_opt sigma c = let saw_evar, c = to_constr_gen ~expand:false ~ignore_missing:false sigma c in if saw_evar && check_evar c then None else Some c let nf_evar sigma c = let _, c = to_constr_gen ~expand:false ~ignore_missing:true sigma c in c let of_named_decl d = d let unsafe_to_named_decl d = d let of_rel_decl d = d let unsafe_to_rel_decl d = d let of_named_context d = d let of_rel_context d = d let unsafe_to_case_invert x = x let of_case_invert x = x let lookup_constant = lookup_constant end (** The following functions return the set of evars immediately contained in the object *) (* excluding defined evars *) let evars_of_term evd c = let rec evrec acc c = let c = MiniEConstr.whd_evar evd c in match kind c with | Evar (n, l) -> Evar.Set.add n (SList.Skip.fold evrec acc l) | _ -> Constr.fold evrec acc c in evrec Evar.Set.empty c let evars_of_named_context evd nc = Context.Named.fold_outside (NamedDecl.fold_constr (fun constr s -> Evar.Set.union s (evars_of_term evd constr))) nc ~init:Evar.Set.empty let evars_of_filtered_evar_info (type a) evd (evi : a evar_info) = let concl = match evi.evar_concl with | Undefined c -> evars_of_term evd c | Defined -> Evar.Set.empty in Evar.Set.union concl (Evar.Set.union (match evi.evar_body with | Evar_empty -> Evar.Set.empty | Evar_defined b -> evars_of_term evd b) (evars_of_named_context evd (evar_filtered_context evi))) let drop_new_defined ~original sigma = NewProfile.profile "drop_new_defined" (fun () -> let to_keep, to_drop = Evar.Map.partition (fun ev _ -> Evar.Map.mem ev original.defn_evars || Evar.Map.mem ev original.undf_evars) sigma.defn_evars in let dummy = { empty with defn_evars = to_drop } in let nfc c = snd @@ MiniEConstr.to_constr_gen ~expand:true ~ignore_missing:false dummy c in (* FIXME: do we really need to expand? *) assert (List.is_empty sigma.conv_pbs); let normalize_changed _ev orig evi = match orig, evi with | _, None -> None | None, Some evi -> Some (map_evar_info nfc evi) | Some orig, Some evi -> if orig == evi then None else Some (map_evar_info nfc evi) in let normalize_against original current = let normalized = EvMap.merge normalize_changed original current in EvMap.union (fun _ _ x -> Some x) current normalized in let to_keep = normalize_against original.defn_evars to_keep in let undf_evars = normalize_against original.undf_evars sigma.undf_evars in { sigma with defn_evars = to_keep; undf_evars }) () rocq-9.2.0/engine/evd.mli000066400000000000000000000671411516144147600152360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a list (** Filter a list. Sizes must coincide. *) val filter_array : t -> 'a array -> 'a array (** Filter an array. Sizes must coincide. *) val filter_slist : t -> 'a SList.t -> 'a SList.t (** Filter a sparse list. Sizes must coincide. *) val extend : int -> t -> t (** [extend n f] extends [f] on the left with [n]-th times [true]. *) val compose : t -> t -> t (** Horizontal composition : [compose f1 f2] only keeps parts of [f2] where [f1] is set. In particular, [f1] and [f2] must have the same length. *) val apply_subfilter : t -> bool list -> t (** [apply_subfilter f1 f2] applies filter [f2] where [f1] is [true]. In particular, the length of [f2] is the number of times [f1] is [true] *) val restrict_upon : t -> int -> (int -> bool) -> t option (** Ad-hoc primitive. *) val map_along : (bool -> 'a -> bool) -> t -> 'a list -> t (** Apply the function on the filter and the list. Sizes must coincide. *) val make : bool list -> t (** Create out of a list *) val repr : t -> bool list option (** Observe as a bool list. *) end module Abstraction : sig type abstraction = | Abstract | Imitate type t = abstraction list val identity : t val abstract_last : t -> t end (** {6 Evar infos} *) type defined = [ `defined ] type undefined = [ `undefined ] type _ evar_body = | Evar_empty : undefined evar_body | Evar_defined : econstr -> defined evar_body type 'a evar_info type any_evar_info = EvarInfo : 'a evar_info -> any_evar_info (** {6 Projections from evar infos} *) val evar_concl : undefined evar_info -> econstr (** Type of the evar. *) val evar_context : 'a evar_info -> (econstr, etypes, erelevance) Context.Named.pt (** Context of the evar. *) val evar_hyps : 'a evar_info -> named_context_val (** Context of the evar. *) val evar_body : 'a evar_info -> 'a evar_body (** Optional content of the evar. *) val evar_candidates : undefined evar_info -> econstr list option (** List of possible solutions when known that it is a finite list *) val evar_source : 'a evar_info -> Evar_kinds.t located val evar_filter : 'a evar_info -> Filter.t (** Boolean mask over {!evar_hyps}. Should have the same length. When filtered out, the corresponding variable is not allowed to occur in the solution *) val evar_abstract_arguments : undefined evar_info -> Abstraction.t (** Boolean information over {!evar_hyps}, telling if an hypothesis instance can be imitated or should stay abstract in HO unification problems and inversion (see [second_order_matching_with_args] for its use). *) val evar_relevance : 'a evar_info -> erelevance (** Relevance of the conclusion of the evar. *) (** {6 Derived projections} *) val evar_filtered_context : 'a evar_info -> (econstr, etypes, erelevance) Context.Named.pt val evar_filtered_hyps : 'a evar_info -> named_context_val val evar_env : env -> 'a evar_info -> env val evar_filtered_env : env -> 'a evar_info -> env val evar_identity_subst : 'a evar_info -> econstr SList.t val map_evar_body : (econstr -> econstr) -> 'a evar_body -> 'a evar_body val map_evar_info : (econstr -> econstr) -> 'a evar_info -> 'a evar_info (** {6 Unification state} **) type evar_map (** Type of unification state. Essentially a bunch of state-passing data needed to handle incremental term construction. *) val empty : evar_map (** The empty evar map. *) val from_env : ?binders:lident list -> env -> evar_map (** The empty evar map with given universe context, taking its initial universes from env, possibly with initial universe binders. This is the main entry point at the beginning of the process of interpreting a declaration (e.g. before entering the interpretation of a Theorem statement). *) val from_ctx : UState.t -> evar_map (** The empty evar map with given universe context. This is the main entry point when resuming from a already interpreted declaration (e.g. after having interpreted a Theorem statement and preparing to open a goal). *) val is_empty : evar_map -> bool (** Whether an evarmap is empty. *) val has_undefined : evar_map -> bool (** [has_undefined sigma] is [true] if and only if there are uninstantiated evars in [sigma]. *) val has_given_up : evar_map -> bool (** [has_given_up sigma] is [true] if and only if there are given up evars in [sigma]. *) val has_shelved : evar_map -> bool (** [has_shelved sigma] is [true] if and only if there are shelved evars in [sigma]. *) val new_pure_evar : ?src:Evar_kinds.t Loc.located -> ?filter:Filter.t -> relevance:erelevance -> ?abstract_arguments:Abstraction.t -> ?candidates:econstr list -> ?name:(Id.t * bool) -> ?parent:Evar.t -> ?typeclass_candidate:bool -> ?rrpat:bool -> named_context_val -> evar_map -> etypes -> evar_map * Evar.t (** Low-level interface to create an evar. @param src User-facing source for the evar @param filter See {!Evd.Filter}, must be the same length as [named_context_val] @param name A name for the evar @param named_context_val The context of the evar @param types The type of conclusion of the evar *) val add : evar_map -> Evar.t -> 'a evar_info -> evar_map (** [add sigma ev info] adds [ev] with evar info [info] in sigma. Precondition: ev must not preexist in [sigma]. *) val find_defined : evar_map -> Evar.t -> defined evar_info option val find : evar_map -> Evar.t -> any_evar_info (** Recover the data associated to an evar. *) val find_undefined : evar_map -> Evar.t -> undefined evar_info (** Same as {!find} but restricted to undefined evars. For efficiency reasons. *) val remove : evar_map -> Evar.t -> evar_map (** Remove an evar from an evar map. Use with caution. *) val mem : evar_map -> Evar.t -> bool (** Whether an evar is present in an evarmap. *) val fold : (Evar.t -> any_evar_info -> 'a -> 'a) -> evar_map -> 'a -> 'a (** Apply a function to all evars and their associated info in an evarmap. *) val fold_undefined : (Evar.t -> undefined evar_info -> 'a -> 'a) -> evar_map -> 'a -> 'a (** Same as {!fold}, but restricted to undefined evars. For efficiency reasons. *) type map = { map : 'r. Evar.t -> 'r evar_info -> 'r evar_info } val raw_map : map -> evar_map -> evar_map (** Apply the given function to all evars in the map. Beware: this function expects the argument function to preserve the kind of [evar_body], i.e. it must send [Evar_empty] to [Evar_empty] and [Evar_defined c] to some [Evar_defined c']. *) val raw_map_undefined : (Evar.t -> undefined evar_info -> undefined evar_info) -> evar_map -> evar_map (** Same as {!raw_map}, but restricted to undefined evars. For efficiency reasons. *) val define : Evar.t -> econstr -> evar_map -> evar_map (** Set the body of an evar to the given constr. It is expected that: {ul {- The evar is already present in the evarmap.} {- The evar is not defined in the evarmap yet.} {- All the evars present in the constr should be present in the evar map.} } *) val define_with_evar : Evar.t -> econstr -> evar_map -> evar_map (** Same as [define ev body evd], except the body must be an existential variable [ev']. This additionally makes [ev'] inherit the [obligation] and [typeclass] flags of [ev]. *) val cmap : (econstr -> econstr) -> evar_map -> evar_map (** Map the function on all terms in the evar map. *) val is_evar : evar_map -> Evar.t-> bool (** Alias for {!mem}. *) val is_defined : evar_map -> Evar.t-> bool (** Whether an evar is defined in an evarmap. *) val is_undefined : evar_map -> Evar.t-> bool (** Whether an evar is not defined in an evarmap. *) val add_univ_constraints : evar_map -> Univ.UnivConstraints.t -> evar_map (** Add universe constraints in an evar map. *) val add_poly_constraints : ?src:UState.constraint_source -> evar_map -> PConstraints.t -> evar_map val undefined_map : evar_map -> undefined evar_info Evar.Map.t (** Access the undefined evar mapping directly. *) val defined_map : evar_map -> defined evar_info Evar.Map.t (** Access the defined evar mapping directly. *) val drop_all_defined : evar_map -> evar_map val drop_new_defined : original:evar_map -> evar_map -> evar_map (** Drop the defined evars in the second evar map which did not exist in the first. *) (** {6 Instantiating partial terms} *) exception NotInstantiatedEvar val existential_value : evar_map -> econstr pexistential -> econstr (** [existential_value sigma ev] raises [NotInstantiatedEvar] if [ev] has no body and [Not_found] if it does not exist in [sigma] *) val existential_type_opt : evar_map -> econstr pexistential -> etypes option val existential_type : evar_map -> econstr pexistential -> etypes val existential_opt_value : evar_map -> econstr pexistential -> econstr option (** Same as {!existential_value} but returns an option instead of raising an exception. *) val existential_opt_value0 : evar_map -> existential -> constr option val evar_handler : evar_map -> CClosure.evar_handler val existential_expand_value0 : evar_map -> existential -> constr CClosure.evar_expansion val expand_existential : evar_map -> econstr pexistential -> econstr list (** Returns the full evar instance with implicit default variables turned into explicit [Var] nodes. *) val expand_existential0 : evar_map -> constr pexistential -> constr list val instantiate_evar_array : evar_map -> 'a evar_info -> econstr -> econstr SList.t -> econstr (** {6 Misc} *) val restrict : Evar.t-> Filter.t -> ?candidates:econstr list -> ?src:Evar_kinds.t located -> evar_map -> evar_map * Evar.t (** Restrict an undefined evar into a new evar by filtering context and possibly limiting the instances to a set of candidates (candidates are filtered according to the filter) *) val update_source : evar_map -> Evar.t -> Evar_kinds.t located -> evar_map (** To update the source a posteriori, e.g. when an evar type of another evar has to refer to this other evar, with a mutual dependency *) val get_aliased_evars : evar_map -> Evar.t Evar.Map.t (** The map of aliased evars *) val is_aliased_evar : evar_map -> Evar.t -> Evar.t option (** Tell if an evar has been aliased to another evar, and if yes, which *) val max_undefined_with_candidates : evar_map -> Evar.t option (** If any, the evar with highest id with a non-empty list of candidates. *) val set_typeclass_evars : evar_map -> Evar.Set.t -> evar_map (** Mark the given set of evars as available for resolution. (The previous marked set is replaced, not added to.) Precondition: they should indeed refer to undefined typeclass evars. *) val get_typeclass_evars : evar_map -> Evar.Set.t (** The set of undefined typeclass evars *) val is_typeclass_evar : evar_map -> Evar.t -> bool (** Is the evar declared resolvable for typeclass resolution *) val get_obligation_evars : evar_map -> Evar.Set.t (** The set of obligation evars *) val set_obligation_evar : evar_map -> Evar.t -> evar_map (** Declare an evar as an obligation *) val is_obligation_evar : evar_map -> Evar.t -> bool (** Is the evar declared as an obligation *) val get_impossible_case_evars : evar_map -> Evar.Set.t (** Set of undefined evars with ImpossibleCase evar source. *) val get_rewrite_rule_evars : evar_map -> Evar.Set.t (** Set of evars declared as an ununifiable rewrite rule evar *) val is_rewrite_rule_evar : evar_map -> Evar.t -> bool (** Is the evar declared as an ununifiable rewrite rule evar *) val downcast : Evar.t-> etypes -> evar_map -> evar_map (** Change the type of an undefined evar to a new type assumed to be a subtype of its current type; subtyping must be ensured by caller *) (** {6 Evar names} *) val evar_ident : Evar.t -> evar_map -> Libnames.full_path option val evar_has_name : Evar.t -> evar_map -> bool val evar_has_unambiguous_name : Evar.t -> evar_map -> bool val add_name : Evar.t -> Id.t -> ?parent:Evar.t -> evar_map -> evar_map val transfer_name : Evar.t -> Evar.t -> evar_map -> evar_map val evar_key : Libnames.qualid -> evar_map -> Evar.t val dependent_evar_ident : Evar.t -> evar_map -> Id.t (** {5 Side-effects} *) type side_effect_role = | Schema of inductive * string type side_effects val empty_side_effects : side_effects val get_senv_side_effects : side_effects -> Safe_typing.safe_environment val set_side_effects : side_effects -> evar_map -> evar_map (** Replaces the side-effects of the evarmap. *) val emit_side_effects : side_effects -> evar_map -> evar_map (** Push a side-effect into the evar map. *) val eval_side_effects : evar_map -> side_effects (** Return the effects contained in the evar map. *) val push_side_effects : ?role:side_effect_role -> ?ts:Conv_oracle.oracle -> Id.t -> Safe_typing.side_effect_declaration -> Univ.ContextSet.t -> side_effects -> Constant.t * side_effects (** {6 Accessors} *) val seff_mem_label : Id.t -> side_effects -> bool val seff_private : side_effects -> Safe_typing.private_constants val seff_roles : side_effects -> side_effect_role Cmap_env.t val seff_univs : side_effects -> UState.named_universes_entry Names.Cmap_env.t (** {5 Future goals} *) val declare_future_goal : Evar.t -> evar_map -> evar_map (** Adds an existential variable to the list of future goals. For internal uses only. *) module FutureGoals : sig type t val comb : t -> Evar.t list val map_filter : (Evar.t -> Evar.t option) -> t -> t (** Applies a function on the future goals *) val filter : (Evar.t -> bool) -> t -> t (** Applies a filter on the future goals *) end val push_future_goals : evar_map -> evar_map val pop_future_goals : evar_map -> FutureGoals.t * evar_map val fold_future_goals : (evar_map -> Evar.t -> evar_map) -> evar_map -> evar_map val remove_future_goal : evar_map -> Evar.t -> evar_map val pr_future_goals_stack : evar_map -> Pp.t val push_shelf : evar_map -> evar_map val pop_shelf : evar_map -> Evar.t list * evar_map val filter_shelf : (Evar.t -> bool) -> evar_map -> evar_map val give_up : Evar.t -> evar_map -> evar_map val shelve : evar_map -> Evar.t list -> evar_map val unshelve : evar_map -> Evar.t list -> evar_map val given_up : evar_map -> Evar.Set.t val shelf : evar_map -> Evar.t list (** All evars in the shelf (not just the shallowest shelf) *) val mem_shelf : Evar.t -> evar_map -> bool (** [true] if the evar is in the shelf (not necessarily in the shallowest shelf) *) val pr_shelf : evar_map -> Pp.t (** {5 Sort variables} Evar maps also keep track of the universe constraints defined at a given point. This section defines the relevant manipulation functions. *) exception UniversesDiffer val add_constraints : evar_map -> UnivProblem.Set.t -> evar_map (** Add the given universe unification constraints to the evar map. @raise UniversesDiffer in case a first-order unification fails. @raise UniverseInconsistency . *) (** {5 Extra data} Evar maps can contain arbitrary data, allowing to use an extensible state. As evar maps are theoretically used in a strict state-passing style, such additional data should be passed along transparently. Some old and bug-prone code tends to drop them nonetheless, so you should keep cautious. *) module Store : Store.S (** Datatype used to store additional information in evar maps. *) val get_extra_data : evar_map -> Store.t val set_extra_data : Store.t -> evar_map -> evar_map (** {5 The state monad with state an evar map} *) module MonadR : Monad.S with type +'a t = evar_map -> evar_map * 'a module Monad : Monad.S with type +'a t = evar_map -> 'a * evar_map (** Unification constraints *) type conv_pb = Conversion.conv_pb type evar_constraint = conv_pb * env * econstr * econstr (** The following two functions are for internal use only, see [Evarutil.add_unification_pb] for a safe interface. *) val add_conv_pb : ?tail:bool -> evar_constraint -> evar_map -> evar_map val conv_pbs : evar_map -> evar_constraint list val extract_conv_pbs : evar_map -> (evar_constraint -> bool) -> evar_map * evar_constraint list val extract_changed_conv_pbs : evar_map -> evar_map * evar_constraint list val extract_changed_conv_pbs_from : evar_map -> Evar.Set.t option -> evar_map * evar_constraint list val extract_all_conv_pbs : evar_map -> evar_map * evar_constraint list val loc_of_conv_pb : evar_map -> evar_constraint -> Loc.t option (** The following functions return the set of undefined evars contained in the object. *) val evars_of_term : evar_map -> econstr -> Evar.Set.t (** including evars in instances of evars *) val evars_of_named_context : evar_map -> (econstr, etypes, erelevance) Context.Named.pt -> Evar.Set.t val evars_of_filtered_evar_info : evar_map -> 'a evar_info -> Evar.Set.t (** {5 FIXME: Nothing to do here} *) (********************************************************* Sort/universe variables *) (** Rigid or flexible universe variables. [UnivRigid] variables are user-provided or come from an explicit [Type] in the source, we do not minimize them or unify them eagerly. [UnivFlexible alg] variables are fresh universe variables of polymorphic constants or generated during refinement, sometimes in algebraic position (i.e. not appearing in the term at the moment of creation). They are the candidates for minimization (if alg, to an algebraic universe) and unified eagerly in the first-order unification heurstic. *) type rigid = UState.rigid = | UnivRigid | UnivFlexible of bool (** Is substitution by an algebraic ok? *) val univ_rigid : rigid val univ_flexible : rigid val univ_flexible_alg : rigid type 'a in_ustate = 'a * UState.t val restrict_universe_context : evar_map -> Univ.Level.Set.t -> evar_map (** Raises Not_found if not a name for a universe in this map. *) val universe_of_name : evar_map -> Id.t -> Univ.Level.t val quality_of_name : evar_map -> Id.t -> Sorts.QVar.t val is_rigid_qvar : evar_map -> Sorts.QVar.t -> bool val is_relevance_irrelevant : evar_map -> erelevance -> bool (** Whether the relevance is irrelevant modulo qstate *) (* XXX move to ERelevance *) val universe_binders : evar_map -> UnivNames.universe_binders val new_univ_level_variable : ?loc:Loc.t -> ?name:Id.t -> rigid -> evar_map -> evar_map * Univ.Level.t val new_quality_variable : ?loc:Loc.t -> ?name:Id.t -> evar_map -> evar_map * Sorts.QVar.t val new_sort_info : ?loc:Loc.t -> ?sort_rigid:bool -> ?name:Names.Id.t -> rigid -> evar_map -> evar_map * Sorts.QVar.t * Univ.Universe.t val new_sort_variable : ?loc:Loc.t -> ?sort_rigid:bool -> ?name:Names.Id.t -> rigid -> evar_map -> evar_map * esorts val add_forgotten_univ : evar_map -> Univ.Level.t -> evar_map val make_nonalgebraic_variable : evar_map -> Univ.Level.t -> evar_map (** See [UState.make_nonalgebraic_variable]. *) val is_flexible_level : evar_map -> Univ.Level.t -> bool val normalize_universe_instance : evar_map -> einstance -> einstance val set_leq_sort : evar_map -> esorts -> esorts -> evar_map val set_eq_sort : evar_map -> esorts -> esorts -> evar_map val set_eq_level : evar_map -> Univ.Level.t -> Univ.Level.t -> evar_map val set_leq_level : evar_map -> Univ.Level.t -> Univ.Level.t -> evar_map val set_eq_instances : ?flex:bool -> evar_map -> einstance -> einstance -> evar_map val set_eq_qualities : evar_map -> Sorts.Quality.t -> Sorts.Quality.t -> evar_map val set_elim_to : evar_map -> Sorts.Quality.t -> Sorts.Quality.t -> evar_map val set_above_prop : evar_map -> Sorts.Quality.t -> evar_map val check_eq : evar_map -> esorts -> esorts -> bool val check_leq : evar_map -> esorts -> esorts -> bool val check_univ_constraints : evar_map -> Univ.UnivConstraints.t -> bool val check_elim_constraints : evar_map -> Sorts.ElimConstraints.t -> bool val check_poly_constraints : evar_map -> PConstraints.t -> bool val check_quality_constraints : evar_map -> UVars.QPairSet.t -> bool val ustate : evar_map -> UState.t val elim_graph : evar_map -> QGraph.t val evar_universe_context : evar_map -> UState.t [@@deprecated "(9.0) Use [Evd.ustate]"] val universe_context_set : evar_map -> Univ.ContextSet.t val sort_context_set : evar_map -> UnivGen.sort_context_set val universe_subst : evar_map -> UnivFlex.t val universes : evar_map -> UGraph.t (** [to_universe_context evm] extracts the local universes and constraints of [evm] and orders the universes *) val to_universe_context : evar_map -> UVars.UContext.t val univ_entry : poly:PolyFlags.t -> evar_map -> UState.named_universes_entry val check_univ_decl : poly:PolyFlags.t -> evar_map -> UState.universe_decl -> UState.named_universes_entry (** An early check of compatibility of the universe declaration before starting to build a declaration interactively *) val check_univ_decl_early : poly:PolyFlags.t -> with_obls:bool -> evar_map -> UState.universe_decl -> Constr.t list -> unit val merge_universe_context : evar_map -> UState.t -> evar_map val set_universe_context : evar_map -> UState.t -> evar_map val merge_universe_context_set : ?loc:Loc.t -> ?sideff:bool -> rigid -> evar_map -> Univ.ContextSet.t -> evar_map val merge_sort_context_set : ?loc:Loc.t -> ?sort_rigid:bool -> ?sideff:bool -> ?src:UState.constraint_source -> rigid -> evar_map -> UnivGen.sort_context_set -> evar_map val with_sort_context_set : ?loc:Loc.t -> ?sort_rigid:bool -> ?src:UState.constraint_source -> rigid -> evar_map -> 'a UnivGen.in_sort_context_set -> evar_map * 'a val nf_univ_variables : evar_map -> evar_map val collapse_sort_variables : ?except:Sorts.QVar.Set.t -> evar_map -> evar_map val fix_undefined_variables : evar_map -> evar_map (** Universe minimization (collapse_sort_variables is true by default) *) val minimize_universes : ?collapse_sort_variables:bool -> evar_map -> evar_map (** Lift [UState.update_sigma_univs] *) val update_sigma_univs : UGraph.t -> evar_map -> evar_map (** Polymorphic universes *) val fresh_sort_in_quality : ?loc:Loc.t -> ?rigid:rigid -> evar_map -> UnivGen.QualityOrSet.t -> evar_map * esorts val fresh_constant_instance : ?loc:Loc.t -> ?rigid:rigid -> env -> evar_map -> Constant.t -> evar_map * Constant.t puniverses val fresh_inductive_instance : ?loc:Loc.t -> ?sort_rigid:bool -> ?rigid:rigid -> env -> evar_map -> inductive -> evar_map * inductive puniverses val fresh_constructor_instance : ?loc:Loc.t -> ?rigid:rigid -> env -> evar_map -> constructor -> evar_map * constructor puniverses val fresh_array_instance : ?loc:Loc.t -> ?rigid:rigid -> env -> evar_map -> evar_map * einstance val fresh_global : ?loc:Loc.t -> ?rigid:rigid -> ?names:einstance -> env -> evar_map -> GlobRef.t -> evar_map * econstr (** Partially constructed constrs. *) type unsolvability_explanation = SeveralInstancesFound of int (** Failure explanation. *) (** {5 Summary names} *) (* This stuff is internal and should not be used. Currently a hack in the STM relies on it. *) val evar_counter_summary_tag : int Summary.Dyn.tag (** {5 Deprecated functions} *) val create_evar_defs : evar_map -> evar_map (* XXX: This is supposed to be deprecated by used by ssrmatching, what should the replacement be? *) (** Create an [evar_map] with empty meta map: *) (** Use this module only to bootstrap EConstr *) module MiniEConstr : sig module ERelevance : sig type t = erelevance val make : Sorts.relevance -> t val kind : evar_map -> t -> Sorts.relevance val unsafe_to_relevance : t -> Sorts.relevance end module ESorts : sig type t = esorts val make : Sorts.t -> t val kind : evar_map -> t -> Sorts.t val unsafe_to_sorts : t -> Sorts.t end module EInstance : sig type t = einstance val make : UVars.Instance.t -> t val kind : evar_map -> t -> UVars.Instance.t val empty : t val is_empty : t -> bool val unsafe_to_instance : t -> UVars.Instance.t end type t = econstr val kind : evar_map -> t -> (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term val kind_upto : evar_map -> constr -> (constr, types, Sorts.t, UVars.Instance.t, Sorts.relevance) Constr.kind_of_term val whd_evar : evar_map -> t -> t val mkLEvar : evar_map -> Evar.t * t list -> t val replace_vars : evar_map -> (Id.t * t) list -> t -> t val of_kind : (t, t, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term -> t val of_constr : Constr.t -> t val of_constr_array : Constr.t array -> t array val to_constr : ?abort_on_undefined_evars:bool -> evar_map -> t -> Constr.t val to_constr_opt : evar_map -> t -> Constr.t option val nf_evar : evar_map -> t -> t val unsafe_to_constr : t -> Constr.t val unsafe_to_constr_array : t array -> Constr.t array val unsafe_eq : (t, Constr.t) eq val unsafe_relevance_eq : (ERelevance.t, Sorts.relevance) eq val of_named_decl : (Constr.t, Constr.types, Sorts.relevance) Context.Named.Declaration.pt -> (t, t, ERelevance.t) Context.Named.Declaration.pt val unsafe_to_named_decl : (t, t, ERelevance.t) Context.Named.Declaration.pt -> (Constr.t, Constr.types, Sorts.relevance) Context.Named.Declaration.pt val unsafe_to_rel_decl : (t, t, ERelevance.t) Context.Rel.Declaration.pt -> (Constr.t, Constr.types, Sorts.relevance) Context.Rel.Declaration.pt val of_case_invert : constr pcase_invert -> econstr pcase_invert val unsafe_to_case_invert : econstr pcase_invert -> constr pcase_invert val of_rel_decl : (Constr.t, Constr.types, Sorts.relevance) Context.Rel.Declaration.pt -> (t, t, ERelevance.t) Context.Rel.Declaration.pt val of_named_context : (Constr.t, Constr.types, Sorts.relevance) Context.Named.pt -> (t, t, ERelevance.t) Context.Named.pt val of_rel_context : (Constr.t, Constr.types, Sorts.relevance) Context.Rel.pt -> (t, t, ERelevance.t) Context.Rel.pt val lookup_constant : env -> evar_map -> Constant.t -> Declarations.constant_body end (** Only used as EConstr internals *) module Expand : sig open MiniEConstr type handle val empty_handle : handle val liftn_handle : int -> handle -> handle val kind : evar_map -> handle -> econstr -> handle * (econstr, econstr, ESorts.t, EInstance.t, ERelevance.t) Constr.kind_of_term val expand : evar_map -> handle -> econstr -> econstr val expand_instance : skip:bool -> undefined evar_info -> handle -> econstr SList.t -> econstr SList.t end rocq-9.2.0/engine/ftactic.ml000066400000000000000000000070141516144147600157150ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* b t) : b t = m >>= function | Uniform x -> f x | Depends l -> let f arg = f arg >>= function | Uniform x -> (* We dispatch the uniform result on each goal under focus, as we know that the [m] argument was actually dependent. *) Proofview.Goal.goals >>= fun goals -> let ans = List.map (fun g -> (g,x)) goals in Proofview.tclUNIT ans | Depends l -> Proofview.Goal.goals >>= fun goals -> Proofview.tclUNIT (List.combine goals l) in (* After the tactic has run, some goals which were previously produced may have been solved by side effects. The values attached to such goals must be discarded, otherwise the list of result would not have the same length as the list of focused goals, which is an invariant of the [Ftactic] module. It is the reason why a goal is attached to each result above. *) let filter (g,x) = g >>= fun g -> Proofview.Goal.unsolved g >>= function | true -> Proofview.tclUNIT (Some x) | false -> Proofview.tclUNIT None in Proofview.tclDISPATCHL (List.map f l) >>= fun l -> Proofview.Monad.List.map_filter filter (List.concat l) >>= fun filtered -> Proofview.tclUNIT (Depends filtered) let goals = Proofview.Goal.goals >>= fun l -> Proofview.tclUNIT (Depends l) let enter f = bind goals (fun gl -> gl >>= fun gl -> Proofview.wrap_exceptions (fun () -> f gl)) let with_env t = t >>= function | Uniform a -> Proofview.tclENV >>= fun env -> Proofview.tclUNIT (Uniform (env,a)) | Depends l -> Proofview.Goal.goals >>= fun gs -> Proofview.Monad.(List.map (map Proofview.Goal.env) gs) >>= fun envs -> Proofview.tclUNIT (Depends (List.combine envs l)) let lift (type a) (t:a Proofview.tactic) : a t = Proofview.tclBIND t (fun x -> Proofview.tclUNIT (Uniform x)) (** If the tactic returns unit, we can focus on the goals if necessary. *) let run m k = m >>= function | Uniform v -> k v | Depends l -> let tacs = List.map k l in Proofview.tclDISPATCH tacs let (>>=) = bind let (<*>) = fun m n -> bind m (fun () -> n) module Self = struct type 'a t = 'a focus Proofview.tactic let return = return let (>>=) = bind let (>>) = (<*>) let map f x = x >>= fun a -> return (f a) end module Ftac = Monad.Make(Self) module List = Ftac.List module Notations = struct let (>>=) = bind let (<*>) = fun m n -> bind m (fun () -> n) end rocq-9.2.0/engine/ftactic.mli000066400000000000000000000051271516144147600160710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t (** The unit of the monad. *) val bind : 'a t -> ('a -> 'b t) -> 'b t (** The bind of the monad. *) (** {5 Operations} *) val lift : 'a Proofview.tactic -> 'a t (** Transform a tactic into a focussing tactic. The resulting tactic is not focused. *) val run : 'a t -> ('a -> unit Proofview.tactic) -> unit Proofview.tactic (** Given a continuation producing a tactic, evaluates the focussing tactic. If the tactic has not focused, then the continuation is evaluated once. Otherwise it is called in each of the currently focused goals. *) (** {5 Focussing} *) (** Enter a goal. The resulting tactic is focused. *) val enter : (Proofview.Goal.t -> 'a t) -> 'a t (** Enter a goal, without evar normalization. The resulting tactic is focused. *) val with_env : 'a t -> (Environ.env*'a) t (** [with_env t] returns, in addition to the return type of [t], an environment, which is the global environment if [t] does not focus on goals, or the local goal environment if [t] focuses on goals. *) (** {5 Notations} *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t (** Notation for {!bind}. *) val (<*>) : unit t -> 'a t -> 'a t (** Sequence. *) (** {5 List operations} *) module List : Monad.ListS with type 'a t := 'a t (** {5 Notations} *) module Notations : sig val (>>=) : 'a t -> ('a -> 'b t) -> 'b t val (<*>) : unit t -> 'a t -> 'a t end rocq-9.2.0/engine/logic_monad.ml000066400000000000000000000274641516144147600165660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some (CErrors.print e) | TacticFailure e -> Some (CErrors.print e) | _ -> None end (** {6 Non-logical layer} *) (** The non-logical monad is a simple [unit -> 'a] (i/o) monad. The operations are simple wrappers around corresponding usual operations and require little documentation. *) module NonLogical = struct (* The functions in this module follow the pattern that they are defined with the form [(); fun ()->...]. This is an optimisation which signals to the compiler that the function is usually partially applied up to the [();]. Without this annotation, partial applications can be significantly slower. Documentation of this behaviour can be found at: https://blog.janestreet.com/the-dangers-of-being-too-partial/ *) include Monad.Make(struct type 'a t = unit -> 'a let return a = (); fun () -> a let (>>=) a k = (); fun () -> k (a ()) () let (>>) a k = (); fun () -> a (); k () let map f a = (); fun () -> f (a ()) end) type 'a ref = 'a Stdlib.ref let ignore a = (); fun () -> ignore (a ()) let ref a = (); fun () -> ref a (** [Pervasives.(:=)] *) let (:=) r a = (); fun () -> r := a (** [Pervasives.(!)] *) let (!) = fun r -> (); fun () -> ! r (** [Pervasives.raise]. Except that exceptions are wrapped with {!Exception}. *) let raise (e, info) () = Exninfo.iraise (Exception e, info) (** [try ... with ...] but restricted to {!Exception}. *) let catch = fun s h -> (); fun () -> try s () with Exception e as src -> let (src, info) = Exninfo.capture src in h (e, info) () let read_line = fun () -> try read_line () with e -> let (e, info) = Exninfo.capture e in raise (e,info) () let print_char = fun c -> (); fun () -> print_char c let timeout = fun n t -> (); fun () -> Control.timeout n t () let make f = (); fun () -> try f () with e when CErrors.noncritical e -> let (e, info) = Exninfo.capture e in Exninfo.iraise (Exception e, info) (** Use the current logger. The buffer is also flushed. *) let print_debug s = make (fun _ -> Feedback.msg_debug s) let print_info s = make (fun _ -> Feedback.msg_info s) let print_notice s = make (fun _ -> Feedback.msg_notice s) let run = fun x -> try x () with Exception e as src -> let (src, info) = Exninfo.capture src in Exninfo.iraise (e, info) end (** {6 Logical layer} *) (** The logical monad is a backtracking monad on top of which is layered a state monad (which is used to implement all of read/write, read only, and write only effects). The state monad being layered on top of the backtracking monad makes it so that the state is backtracked on failure. Backtracking differs from regular exception in that, writing (+) for exception catching and (>>=) for bind, we require the following extra distributivity laws: x+(y+z) = (x+y)+z zero+x = x x+zero = x (x+y)>>=k = (x>>=k)+(y>>=k) *) (** A view type for the logical monad, which is a form of list, hence we can decompose it with as a list. *) type ('a, 'b, 'e) list_view_ = | Nil of 'e | Cons of 'a * 'b type ('a, 'b, 'e) list_view = ('a, 'e -> 'b, 'e) list_view_ module BackState = struct (** Double-continuation backtracking monads are reasonable folklore for "search" implementations (including the Tac interactive prover's tactics). Yet it's quite hard to wrap your head around these. I recommend reading a few times the "Backtracking, Interleaving, and Terminating Monad Transformers" paper by O. Kiselyov, C. Shan, D. Friedman, and A. Sabry. The peculiar shape of the monadic type is reminiscent of that of the continuation monad transformer. The paper also contains the rationale for the [split] abstraction. An explanation of how to derive such a monad from mathematical principles can be found in "Kan Extensions for Program Optimisation" by Ralf Hinze. A somewhat concrete view is that the type ['a iolist] is, in fact the impredicative encoding of the following stream type: [type 'a _iolist' = Nil of exn | Cons of 'a*'a iolist' and 'a iolist = 'a _iolist NonLogical.t] Using impredicative encoding avoids intermediate allocation and is, empirically, very efficient in Ocaml. It also has the practical benefit that the monadic operation are independent of the underlying monad, which simplifies the code and side-steps the limited inlining of Ocaml. In that vision, [bind] is simply [concat_map] (though the cps version is significantly simpler), [plus] is concatenation, and [split] is pattern-matching. *) type ('a, 'i, 'o, 'e) t = { iolist : 'r. 'i -> ('e -> 'r NonLogical.t) -> ('a -> 'o -> ('e -> 'r NonLogical.t) -> 'r NonLogical.t) -> 'r NonLogical.t } let return x = { iolist = fun s nil cons -> cons x s nil } let (>>=) m f = { iolist = fun s nil cons -> m.iolist s nil (fun x s next -> (f x).iolist s next cons) } let (>>) m f = { iolist = fun s nil cons -> m.iolist s nil (fun () s next -> f.iolist s next cons) } let map f m = { iolist = fun s nil cons -> m.iolist s nil (fun x s next -> cons (f x) s next) } let zero e = { iolist = fun _ nil cons -> nil e } let plus m1 m2 = { iolist = fun s nil cons -> m1.iolist s (fun e -> (m2 e).iolist s nil cons) cons } let ignore m = { iolist = fun s nil cons -> m.iolist s nil (fun _ s next -> cons () s next) } let lift m = { iolist = fun s nil cons -> NonLogical.(m >>= fun x -> cons x s nil) } (** State related *) let get = { iolist = fun s nil cons -> cons s s nil } let set s = { iolist = fun _ nil cons -> cons () s nil } let modify f = { iolist = fun s nil cons -> cons () (f s) nil } (** Exception manipulation *) let interleave src dst m = { iolist = fun s nil cons -> m.iolist s (fun e1 -> nil (src e1)) (fun x s next -> cons x s (fun e2 -> next (dst e2))) } (** List observation *) let once m = { iolist = fun s nil cons -> m.iolist s nil (fun x s _ -> cons x s nil) } let break f m = { iolist = fun s nil cons -> m.iolist s nil (fun x s next -> cons x s (fun e -> match f e with None -> next e | Some e -> nil e)) } (** For [reflect] and [split] see the "Backtracking, Interleaving, and Terminating Monad Transformers" paper. *) type ('a, 'e) reified = ('a, ('a, 'e) reified_, 'e) list_view_ NonLogical.t and ('a, 'e) reified_ = {r : 'e -> ('a, 'e) reified} [@@unboxed] let rec reflect (m : ('a * 'o, 'e) reified) = { iolist = fun s0 nil cons -> let next = function | Nil e -> nil e | Cons ((x, s), {r=l}) -> cons x s (fun e -> (reflect (l e)).iolist s0 nil cons) in NonLogical.(m >>= next) } let split m : (_ list_view, _, _, _) t = let rnil e = NonLogical.return (Nil e) in let rcons p s l = NonLogical.return (Cons ((p, s), {r=l})) in { iolist = fun s nil cons -> let open NonLogical in m.iolist s rnil rcons >>= begin function | Nil e -> cons (Nil e) s nil | Cons ((x, s), {r=l}) -> let l e = reflect (l e) in cons (Cons (x, l)) s nil end } let run m s = let rnil e = NonLogical.return (Nil e) in let rcons x s l = let p = (x, s) in NonLogical.return (Cons (p, {r=l})) in m.iolist s rnil rcons let repr x = x end module type Param = sig (** Read only *) type e (** Write only *) type w (** [w] must be a monoid *) val wunit : w val wprod : w -> w -> w (** Read-write *) type s (** Update-only. Essentially a writer on [u->u]. *) type u (** [u] must be pointed. *) val uunit : u end module Logical (P:Param) = struct module Unsafe = struct (** All three of environment, writer and state are coded as a single state-passing-style monad.*) type state = { rstate : P.e; ustate : P.u; wstate : P.w; sstate : P.s; } let make m = m let repr m = m end open Unsafe type state = Unsafe.state type iexn = Exninfo.iexn type 'a reified = ('a, iexn) BackState.reified type 'a reified_ = ('a, iexn) BackState.reified_ (** Inherited from Backstate *) open BackState include Monad.Make(struct type 'a t = ('a, state, state, iexn) BackState.t let return = BackState.return let (>>=) = BackState.(>>=) let (>>) = BackState.(>>) let map = BackState.map end) let zero = BackState.zero let plus = BackState.plus let ignore = BackState.ignore let lift = BackState.lift let once = BackState.once let break = BackState.break let split = BackState.split let repr = BackState.repr (** State related. We specialize them here to ensure soundness (for reader and writer) and efficiency. *) let get = { iolist = fun s nil cons -> cons s.sstate s nil } let set (sstate : P.s) = { iolist = fun s nil cons -> cons () { s with sstate } nil } let modify (f : P.s -> P.s) = { iolist = fun s nil cons -> cons () { s with sstate = f s.sstate } nil } let current = { iolist = fun s nil cons -> cons s.rstate s nil } let local e m = { iolist = fun s nil cons -> m.iolist { s with rstate = e } nil (fun x s' next -> cons x {s' with rstate = s.rstate} next) } let put w = { iolist = fun s nil cons -> cons () { s with wstate = P.wprod s.wstate w } nil } let update (f : P.u -> P.u) = { iolist = fun s nil cons -> cons () { s with ustate = f s.ustate } nil } (** Monadic run is specialized to handle reader / writer *) let run m r s = let s = { wstate = P.wunit; ustate = P.uunit; rstate = r; sstate = s } in let rnil e = NonLogical.return (Nil e) in let rcons x s l = let p = (x, s.sstate, s.wstate, s.ustate) in NonLogical.return (Cons (p, {r=l})) in m.iolist s rnil rcons end rocq-9.2.0/engine/logic_monad.mli000066400000000000000000000154611516144147600167310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a] (i/o) monad. The operations are simple wrappers around corresponding usual operations and require little documentation. *) module NonLogical : sig include Monad.S val ignore : 'a t -> unit t type 'a ref val ref : 'a -> 'a ref t (** [Pervasives.(:=)] *) val (:=) : 'a ref -> 'a -> unit t (** [Pervasives.(!)] *) val (!) : 'a ref -> 'a t val read_line : string t val print_char : char -> unit t (** Loggers. The buffer is also flushed. *) val print_debug : Pp.t -> unit t val print_notice : Pp.t -> unit t val print_info : Pp.t -> unit t (** [Pervasives.raise]. Except that exceptions are wrapped with {!Exception}. *) val raise : Exninfo.iexn -> 'a t (** [try ... with ...] but restricted to {!Exception}. *) val catch : 'a t -> (Exninfo.iexn -> 'a t) -> 'a t val timeout : float -> 'a t -> ('a, Exninfo.info) result t (** Construct a monadified side-effect. Exceptions raised by the argument are wrapped with {!Exception}. *) val make : (unit -> 'a) -> 'a t (** [run] performs effects. *) val run : 'a t -> 'a end (** {6 Logical layer} *) (** The logical monad is a backtracking monad on top of which is layered a state monad (which is used to implement all of read/write, read only, and write only effects). The state monad being layered on top of the backtracking monad makes it so that the state is backtracked on failure. Backtracking differs from regular exception in that, writing (+) for exception catching and (>>=) for bind, we require the following extra distributivity laws: x+(y+z) = (x+y)+z zero+x = x x+zero = x (x+y)>>=k = (x>>=k)+(y>>=k) *) (** A view type for the logical monad, which is a form of list, hence we can decompose it with as a list. *) type ('a, 'b, 'e) list_view_ = | Nil of 'e | Cons of 'a * 'b type ('a, 'b, 'e) list_view = ('a, 'e -> 'b, 'e) list_view_ module BackState : sig type (+'a, -'i, +'o, 'e) t val return : 'a -> ('a, 's, 's, 'e) t val (>>=) : ('a, 'i, 'm, 'e) t -> ('a -> ('b, 'm, 'o, 'e) t) -> ('b, 'i, 'o, 'e) t val (>>) : (unit, 'i, 'm, 'e) t -> ('b, 'm, 'o, 'e) t -> ('b, 'i, 'o, 'e) t val map : ('a -> 'b) -> ('a, 'i, 'o, 'e) t -> ('b, 'i, 'o, 'e) t val ignore : ('a, 'i, 'o, 'e) t -> (unit, 'i, 'o, 'e) t val set : 'o -> (unit, 'i, 'o, 'e) t val get : ('s, 's, 's, 'e) t val modify : ('i -> 'o) -> (unit, 'i, 'o, 'e) t val interleave : ('e1 -> 'e2) -> ('e2 -> 'e1) -> ('a, 'i, 'o, 'e1) t -> ('a, 'i, 'o, 'e2) t (** [interleave src dst m] adapts the exceptional content of the monad according to the functions [src] and [dst]. To ensure a meaningful result, those functions must form a retraction, i.e. [dst (src e1) = e1] for all [e1]. This is typically the case when the type ['e1] is [unit]. *) val zero : 'e -> ('a, 'i, 'o, 'e) t val plus : ('a, 'i, 'o, 'e) t -> ('e -> ('a, 'i, 'o, 'e) t) -> ('a, 'i, 'o, 'e) t val split : ('a, 's, 's, 'e) t -> (('a, ('a, 'i, 's, 'e) t, 'e) list_view, 's, 's, 'e) t val once : ('a, 'i, 'o, 'e) t -> ('a, 'i, 'o, 'e) t val break : ('e -> 'e option) -> ('a, 'i, 'o, 'e) t -> ('a, 'i, 'o, 'e) t val lift : 'a NonLogical.t -> ('a, 's, 's, 'e) t type ('a, 'e) reified type ('a, 'e) reified_ val repr : ('a, 'e) reified -> ('a, ('a, 'e) reified_, 'e) list_view_ NonLogical.t val run : ('a, 'i, 'o, 'e) t -> 'i -> ('a * 'o, 'e) reified end (** The monad is parametrised in the types of state, environment and writer. *) module type Param = sig (** Read only *) type e (** Write only *) type w (** [w] must be a monoid *) val wunit : w val wprod : w -> w -> w (** Read-write *) type s (** Update-only. Essentially a writer on [u->u]. *) type u (** [u] must be pointed. *) val uunit : u end module Logical (P:Param) : sig include Monad.S val ignore : 'a t -> unit t val set : P.s -> unit t val get : P.s t val modify : (P.s -> P.s) -> unit t val put : P.w -> unit t val current : P.e t val local : P.e -> 'a t -> 'a t val update : (P.u -> P.u) -> unit t val zero : Exninfo.iexn -> 'a t val plus : 'a t -> (Exninfo.iexn -> 'a t) -> 'a t val split : 'a t -> ('a, 'a t, Exninfo.iexn) list_view t val once : 'a t -> 'a t val break : (Exninfo.iexn -> Exninfo.iexn option) -> 'a t -> 'a t val lift : 'a NonLogical.t -> 'a t type 'a reified = ('a, Exninfo.iexn) BackState.reified type 'a reified_ = ('a, Exninfo.iexn) BackState.reified_ val repr : 'a reified -> ('a, 'a reified_, Exninfo.iexn) list_view_ NonLogical.t val run : 'a t -> P.e -> P.s -> ('a * P.s * P.w * P.u) reified module Unsafe : sig type state = { rstate : P.e; ustate : P.u; wstate : P.w; sstate : P.s; } val make : ('a, state, state, Exninfo.iexn) BackState.t -> 'a t val repr : 'a t -> ('a, state, state, Exninfo.iexn) BackState.t end end rocq-9.2.0/engine/namegen.ml000066400000000000000000000464341516144147600157230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* true | IntroIdentifier id1, IntroIdentifier id2 -> Names.Id.equal id1 id2 | IntroFresh id1, IntroFresh id2 -> Names.Id.equal id1 id2 | _ -> false (**********************************************************************) (* Conventional names *) let default_prop_string = "H" let default_prop_ident = Id.of_string default_prop_string let default_small_string = "H" let default_small_ident = Id.of_string default_small_string let default_type_string = "X" let default_type_ident = Id.of_string default_type_string let default_non_dependent_string = "H" let default_non_dependent_ident = Id.of_string default_non_dependent_string let default_dependent_ident = Id.of_string "x" let default_generated_non_letter_string = "x" (**********************************************************************) (* Globality of identifiers *) let is_imported_modpath = function | MPfile dp -> let rec find_prefix = function |MPfile dp1 -> not (DirPath.equal dp1 dp) |MPdot(mp,_) -> find_prefix mp |MPbound(_) -> false in find_prefix (Lib.current_mp ()) | _ -> false let is_imported_ref = let open GlobRef in function | VarRef _ -> false | IndRef (kn,_) | ConstructRef ((kn,_),_) -> let mp = MutInd.modpath kn in is_imported_modpath mp | ConstRef kn -> let mp = Constant.modpath kn in is_imported_modpath mp let locate id = match Nametab.locate_extended_nowarn (qualid_of_ident id) with | TrueGlobal r -> r | Abbrev _ -> raise Not_found let is_global id = try let ref = locate id in not (is_imported_ref ref) with Not_found -> false let is_constructor id = try match locate id with | GlobRef.ConstructRef _ -> true | _ -> false with Not_found -> false let is_section_variable env id = try let _ = Environ.lookup_named id env in true with Not_found -> false (**********************************************************************) (* Generating "intuitive" names from its type *) let global_of_constr = let open GlobRef in function | Const (c, _) -> ConstRef c | Ind (i, _) -> IndRef i | Construct (c, _) -> ConstructRef c | Var id -> VarRef id | _ -> assert false let head_name sigma c = (* Find the head constant of a constr if any *) let rec hdrec c = match EConstr.kind sigma c with | Prod (_,_,c) | Lambda (_,_,c) | LetIn (_,_,_,c) | Cast (c,_,_) | App (c,_) -> hdrec c | Proj (kn,_,_) -> Some (Constant.label (Projection.constant kn)) | Const _ | Ind _ | Construct _ | Var _ as c -> Some (Nametab.basename_of_global (global_of_constr c)) | Fix ((_,i),(lna,_,_)) | CoFix (i,(lna,_,_)) -> Some (match lna.(i).binder_name with Name id -> id | _ -> assert false) | Sort _ | Rel _ | Meta _ | Evar _ | Case _ | Int _ | Float _ | String _ | Array _ -> None in hdrec c let lowercase_first_char id = (* First character of a constr *) let s = Id.to_string id in match Unicode.split_at_first_letter s with | None -> (* General case: nat -> n *) Unicode.lowercase_first_char s | Some (s,s') -> if String.length s' = 0 then (* No letter, e.g. __, or __'_, etc. *) default_generated_non_letter_string else s ^ Unicode.lowercase_first_char s' let sort_hdchar = function | SProp -> "P" | Prop -> "P" | Set -> "S" | Type _ | QSort _ -> "T" let hdchar env sigma c = let rec hdrec k c = match EConstr.kind sigma c with | Prod (_,_,c) | Lambda (_,_,c) | LetIn (_,_,_,c) -> hdrec (k+1) c | Cast (c,_,_) | App (c,_) -> hdrec k c | Proj (kn,_,_) -> lowercase_first_char (Constant.label (Projection.constant kn)) | Const (kn,_) -> lowercase_first_char (Constant.label kn) | Ind (x,_) -> (try lowercase_first_char (Nametab.basename_of_global (GlobRef.IndRef x)) with Not_found when !Flags.in_debugger -> "zz") | Construct (x,_) -> (try lowercase_first_char (Nametab.basename_of_global (GlobRef.ConstructRef x)) with Not_found when !Flags.in_debugger -> "zz") | Var id -> lowercase_first_char id | Sort s -> sort_hdchar (ESorts.kind sigma s) | Rel n -> (if n<=k then "p" (* the initial term is flexible product/function *) else try match let d = lookup_rel (n-k) env in get_name d, get_type d with | Name id, _ -> lowercase_first_char id | Anonymous, t -> hdrec 0 (lift (n-k) t) with Not_found -> "y") | Fix ((_,i),(lna,_,_)) | CoFix (i,(lna,_,_)) -> let id = match lna.(i).binder_name with Name id -> id | _ -> assert false in lowercase_first_char id | Evar _ (* We could do better... *) | Meta _ | Case _ -> "y" | Int _ -> "i" | Float _ -> "f" | String _ -> "s" | Array _ -> "a" in hdrec 0 c let id_of_name_using_hdchar env sigma a = function | Anonymous -> Id.of_string (hdchar env sigma a) | Name id -> id let named_hd env sigma a = function | Anonymous -> Name (Id.of_string (hdchar env sigma a)) | x -> x let mkProd_name env sigma (n,a,b) = mkProd (map_annot (named_hd env sigma a) n, a, b) let mkLambda_name env sigma (n,a,b) = mkLambda (map_annot (named_hd env sigma a) n, a, b) let lambda_name = mkLambda_name let prod_name = mkProd_name let prod_create env sigma (r,a,b) = mkProd (make_annot (named_hd env sigma a Anonymous) r, a, b) let lambda_create env sigma (r,a,b) = mkLambda (make_annot (named_hd env sigma a Anonymous) r, a, b) let name_assumption env sigma = function | LocalAssum (na,t) -> LocalAssum (map_annot (named_hd env sigma t) na, t) | LocalDef (na,c,t) -> LocalDef (map_annot (named_hd env sigma c) na, c, t) let name_context env sigma hyps = snd (List.fold_left (fun (env,hyps) d -> let d' = name_assumption env sigma d in (push_rel d' env, d' :: hyps)) (env,[]) (List.rev hyps)) let mkProd_or_LetIn_name env sigma b d = mkProd_or_LetIn (name_assumption env sigma d) b let mkLambda_or_LetIn_name env sigma b d = mkLambda_or_LetIn (name_assumption env sigma d) b let it_mkProd_or_LetIn_name env sigma b hyps = it_mkProd_or_LetIn b (name_context env sigma hyps) let it_mkLambda_or_LetIn_name env sigma b hyps = it_mkLambda_or_LetIn b (name_context env sigma hyps) (**********************************************************************) (* Fresh names *) (* Introduce a mode where auto-generated names are mangled to test dependence of scripts on auto-generated names. We also supply a version which only adds a prefix. *) let { Goptions.get = get_mangle_names } = Goptions.declare_bool_option_and_ref ~key:["Mangle";"Names"] ~value:false () let { Goptions.get = get_mangle_names_light } = Goptions.declare_bool_option_and_ref ~key:["Mangle";"Names";"Light"] ~value:false () let { Goptions.get = mangle_names_prefix } = Goptions.declare_interpreted_string_option_and_ref ~key:["Mangle";"Names";"Prefix"] ~value:("_") (fun x -> Id.to_string (try Id.of_string x with | CErrors.UserError _ -> CErrors.user_err Pp.(str ("Not a valid identifier: \"" ^ x ^ "\".")) ) ) (fun x -> x) () (** The name "foo" becomes "_0" if we get_mangle_names and "_foo" if get_mangle_names_light is also set. Otherwise it is left alone. *) let mangle_id id = let prfx = mangle_names_prefix () in if get_mangle_names () then if get_mangle_names_light () then Id.of_string (prfx ^ Id.to_string id) else Id.of_string (prfx ^ "0") else id (* Looks for next "good" name by lifting subscript *) let next_ident_away_from_post_mangling id bad = let rec name_rec id = if bad id then name_rec (increment_subscript id) else id in name_rec id let next_ident_away_from id bad = let id = mangle_id id in next_ident_away_from_post_mangling id bad (* Restart subscript from x0 if name starts with xN, or x00 if name starts with x0N, etc *) let restart_subscript id = if not (has_subscript id) then id else (* It would probably be better with something in the spirit of *** make_ident id (Some 0) *** but compatibility would be lost... *) forget_subscript id module Generator = struct type _ t = | Fresh : Fresh.t t | IdSet : Id.Set.t t type 'a input = 'a t * 'a let fresh = Fresh let idset = IdSet let max_map (type a) (gen : a t) (avoid : a) = match gen with | Fresh -> Fresh.max_map avoid | IdSet -> let fold id accu = let id, ss = get_subscript id in match Id.Map.find_opt id accu with | Some old_ss when Subscript.compare ss old_ss <= 0 -> accu | _ -> Id.Map.add id ss accu in Id.Set.fold fold avoid Id.Map.empty let is_fresh (type a) (gen : a t) id (avoid : a) = match gen with | Fresh -> not (Fresh.mem id avoid) | IdSet -> not (Id.Set.mem id avoid) let gen_ident (type a) ?(mangle = true) ?(filter = (fun _ -> false)) (gen : a t) id (state : a) : Id.t * a = let id = if mangle then mangle_id id else id in match gen with | Fresh -> let rec gen state id = let (id, state) = Fresh.fresh id state in if filter id then gen state id else id in let id = gen state id in (id, Fresh.add id state) | IdSet -> let rec gen id = if Id.Set.mem id state || filter id then gen (increment_subscript id) else id in let id = gen id in (id, Id.Set.add id state) let next_name_away gen na avoid = let id = match na with Name id -> id | Anonymous -> default_non_dependent_ident in let id = mangle_id id in let id = if is_fresh gen id avoid then id else restart_subscript id in gen_ident ~mangle:false gen id avoid end let visible_ids sigma (nenv, c) = let accu = ref (GlobRef.Set_env.empty, Int.Set.empty, Id.Set.empty) in let rec visible_ids n c = match EConstr.kind sigma c with | Const _ | Ind _ | Construct _ | Var _ as c -> let (gseen, vseen, ids) = !accu in let g = global_of_constr c in if not (GlobRef.Set_env.mem g gseen) then let gseen = GlobRef.Set_env.add g gseen in let ids = match Nametab.shortest_qualid_of_global ~force_short:true Id.Set.empty g with | short -> let dir, id = repr_qualid short in if DirPath.is_empty dir then Id.Set.add id ids else ids | exception Not_found -> (* This may happen if given pathological terms or when manipulating open modules *) ids in accu := (gseen, vseen, ids) | Rel p -> let (gseen, vseen, ids) = !accu in if p > n && not (Int.Set.mem (p - n) vseen) then let vseen = Int.Set.add (p - n) vseen in let name = try Some (List.nth nenv (p - n - 1)) with Invalid_argument _ | Failure _ -> (* Unbound index: may happen in debug and actually also while computing temporary implicit arguments of an inductive type *) None in let ids = match name with | Some (Name id) -> Id.Set.add id ids | _ -> ids in accu := (gseen, vseen, ids) | Evar (_,args as ev) -> (* Useful for at least debugger: do the same as in iter_with_binders *) (* except that Not_found is not fatal *) begin match Evd.expand_existential sigma ev with | args -> List.iter (visible_ids n) args | exception Not_found when !Flags.in_debugger -> SList.Skip.iter (visible_ids n) args end | _ -> EConstr.iter_with_binders sigma succ visible_ids n c in let () = visible_ids 1 c in (* n = 1 to count the binder to rename *) let (_, _, ids) = !accu in ids (* Now, there are different renaming strategies... *) (* 1- Looks for a fresh name for printing in cases pattern *) let next_name_away_in_cases_pattern gen sigma env_t na avoid = let id = match na with Name id -> id | Anonymous -> default_dependent_ident in let visible = visible_ids sigma env_t in let bad id = is_constructor id || Id.Set.mem id visible in Generator.gen_ident ~filter:bad gen id avoid (* 2- Looks for a fresh name for introduction in goal *) (* The legacy strategy for renaming introduction variables is not very uniform: - if the name to use is fresh in the context but used as a global name, then a fresh name is taken by finding a free subscript starting from the current subscript; - but if the name to use is not fresh in the current context, the fresh name is taken by finding a free subscript starting from 0 *) let next_ident_away_in_goal env id avoid = let id = if Id.Set.mem id avoid then restart_subscript id else id in let bad id = Id.Set.mem id avoid || (is_global id && not (is_section_variable env id)) in next_ident_away_from id bad let next_name_away_in_goal (type a) (gen : a Generator.t) env na (avoid : a) = let id = match na with | Name id -> id | Anonymous -> default_non_dependent_ident in let id = if Generator.is_fresh gen id avoid then id else restart_subscript id in let bad id = is_global id && not (is_section_variable env id) in Generator.gen_ident ~filter:bad gen id avoid (* 3- Looks for next fresh name outside a list that is moreover valid as a global identifier; the legacy algorithm is that if the name is already used in the list, one looks for a name of same base with lower available subscript; if the name is not in the list but is used globally, one looks for a name of same base with lower subscript beyond the current subscript *) let next_global_ident_away senv id avoid = let id = if Id.Set.mem id avoid then restart_subscript id else id in let bad id = Id.Set.mem id avoid || Safe_typing.exists_objlabel id senv in next_ident_away_from id bad (* 4- Looks for next fresh name outside a list; if name already used, looks for same name with lower available subscript *) let next_ident_away id avoid = let id = mangle_id id in if Id.Set.mem id avoid then next_ident_away_from_post_mangling (restart_subscript id) (fun id -> Id.Set.mem id avoid) else id let next_name_away_with_default default na avoid = let id = match na with Name id -> id | Anonymous -> Id.of_string default in next_ident_away id avoid let reserved_type_name = ref (fun _ _ _ -> Anonymous) let set_reserved_typed_name f = reserved_type_name := f let next_name_away_with_default_using_types env sigma default na avoid t = let id = match na with | Name id -> id | Anonymous -> match !reserved_type_name env sigma t with | Name id -> id | Anonymous -> Id.of_string default in next_ident_away id avoid let next_name_away = next_name_away_with_default default_non_dependent_string let make_all_rel_context_name_different env sigma ctx = let avoid = ref (Id.Set.union (Context.Rel.to_vars (Environ.rel_context env)) (ids_of_named_context_val (named_context_val env))) in Context.Rel.fold_outside (fun decl (newenv,ctx) -> let na = named_hd newenv sigma (RelDecl.get_type decl) (RelDecl.get_name decl) in let id = next_name_away na !avoid in avoid := Id.Set.add id !avoid; let decl = RelDecl.set_name (Name id) decl in push_rel decl newenv, decl :: ctx) ctx ~init:(env,[]) let make_all_name_different env sigma = (* FIXME: this is inefficient, but only used in printing *) let sign = named_context_val env in let rels = rel_context env in let env0 = reset_with_named_context sign env in let env,_ = make_all_rel_context_name_different env0 sigma rels in env (* 5- Looks for next fresh name outside a list; avoids also to use names that would clash with short name of global references; if name is already used, looks for name of same base with lower available subscript beyond current subscript *) let next_ident_away_for_default_printing gen sigma env_t id avoid = let visible = visible_ids sigma env_t in let bad id = Id.Set.mem id visible in Generator.gen_ident ~filter:bad gen id avoid let next_name_away_for_default_printing gen sigma env_t na avoid = let id = match na with | Name id -> id | Anonymous -> (* In principle, an anonymous name is not dependent and will not be *) (* taken into account by the function compute_displayed_name_in; *) (* just in case, invent a valid name *) default_non_dependent_ident in next_ident_away_for_default_printing gen sigma env_t id avoid (**********************************************************************) (* Displaying terms avoiding bound variables clashes *) (* Renaming strategy introduced in December 1998: - Rule number 1: all names, even if unbound and not displayed, contribute to the list of names to avoid - Rule number 2: only the dependency status is used for deciding if a name is displayed or not Example: bool_ind: "forall (P:bool->Prop)(f:(P true))(f:(P false))(b:bool), P b" is displayed "forall P:bool->Prop, P true -> P false -> forall b:bool, P b" but f and f0 contribute to the list of variables to avoid (knowing that f and f0 are how the f's would be named if introduced, assuming no other f and f0 are already used). *) type renaming_flags = (* The term is the body of a binder and the environment excludes this binder *) (* so, there is a missing binder in the environment *) | RenamingForCasesPattern of (Name.t list * constr) | RenamingForGoal | RenamingElsewhereFor of (Name.t list * constr) let next_name_for_display gen env sigma flags na avoid = match flags with | RenamingForCasesPattern env_t -> next_name_away_in_cases_pattern gen sigma env_t na avoid | RenamingForGoal -> next_name_away_in_goal gen env na avoid | RenamingElsewhereFor env_t -> next_name_away_for_default_printing gen sigma env_t na avoid (* Remark: Anonymous var may be dependent in Evar's contexts *) let compute_displayed_name_in_gen_poly gen noccurn_fun env sigma flags avoid na c = let noccurs = try noccurn_fun sigma 1 c with _ when !Flags.in_debugger -> false in if noccurs then Anonymous, avoid else let fresh_id, avoid = next_name_for_display gen env sigma flags na avoid in Name fresh_id, avoid let compute_displayed_name_in gen = compute_displayed_name_in_gen_poly gen noccurn let compute_displayed_name_in_gen gen f env sigma = (* only flag which does not need a constr, maybe to be refined *) let flag = RenamingForGoal in compute_displayed_name_in_gen_poly gen f env sigma flag let compute_displayed_let_name_in gen env sigma flags avoid na = let fresh_id, avoid = next_name_for_display gen env sigma flags na avoid in (Name fresh_id, avoid) rocq-9.2.0/engine/namegen.mli000066400000000000000000000136151516144147600160670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* intro_pattern_naming_expr -> bool (********************************************************************* Conventional default names *) val default_prop_ident : Id.t (* "H" *) val default_small_ident : Id.t (* "H" *) val default_type_ident : Id.t (* "X" *) val default_non_dependent_ident : Id.t (* "H" *) val default_dependent_ident : Id.t (* "x" *) (********************************************************************* Generating "intuitive" names from their type *) val lowercase_first_char : Id.t -> string val sort_hdchar : Sorts.t -> string val hdchar : env -> evar_map -> types -> string val id_of_name_using_hdchar : env -> evar_map -> types -> Name.t -> Id.t val named_hd : env -> evar_map -> types -> Name.t -> Name.t val head_name : evar_map -> types -> Id.t option val mkProd_name : env -> evar_map -> Name.t EConstr.binder_annot * types * types -> types val mkLambda_name : env -> evar_map -> Name.t EConstr.binder_annot * types * constr -> constr (** Deprecated synonyms of [mkProd_name] and [mkLambda_name] *) val prod_name : env -> evar_map -> Name.t EConstr.binder_annot * types * types -> types val lambda_name : env -> evar_map -> Name.t EConstr.binder_annot * types * constr -> constr val prod_create : env -> evar_map -> ERelevance.t * types * types -> constr val lambda_create : env -> evar_map -> ERelevance.t * types * constr -> constr val name_assumption : env -> evar_map -> rel_declaration -> rel_declaration val name_context : env -> evar_map -> rel_context -> rel_context val mkProd_or_LetIn_name : env -> evar_map -> types -> rel_declaration -> types val mkLambda_or_LetIn_name : env -> evar_map -> constr -> rel_declaration -> constr val it_mkProd_or_LetIn_name : env -> evar_map -> types -> rel_context -> types val it_mkLambda_or_LetIn_name : env -> evar_map -> constr -> rel_context -> constr (********************************************************************* Fresh names *) val mangle_id : Id.t -> Id.t (** Avoid clashing with a name satisfying some predicate *) val next_ident_away_from : Id.t -> (Id.t -> bool) -> Id.t (** [next_ident_away original_id unwanted_ids] returns a new identifier as close as possible to the [original_id] while avoiding all [unwanted_ids]. In particular: {ul {- if [original_id] does not appear in the list of [unwanted_ids], then [original_id] is returned.} {- if [original_id] appears in the list of [unwanted_ids], then this function returns a new id that: {ul {- has the same {i root} as the [original_id],} {- does not occur in the list of [unwanted_ids],} {- has the smallest possible {i subscript}.}}}} where by {i subscript} of some identifier we mean last part of it that is composed only from (decimal) digits and by {i root} of some identifier we mean the whole identifier except for the {i subscript}. E.g. if we take [foo42], then [42] is the {i subscript}, and [foo] is the root. *) val next_ident_away : Id.t -> Id.Set.t -> Id.t (** Avoid clashing with a name already used in current module *) val next_ident_away_in_goal : Environ.env -> Id.t -> Id.Set.t -> Id.t (** Avoid clashing with a name already used in current module but tolerate overwriting section variables, as in goals *) val next_global_ident_away : Safe_typing.safe_environment -> Id.t -> Id.Set.t -> Id.t (** Default is [default_non_dependent_ident] *) val next_name_away : Name.t -> Id.Set.t -> Id.t val next_name_away_with_default : string -> Name.t -> Id.Set.t -> Id.t val next_name_away_with_default_using_types : Environ.env -> evar_map -> string -> Name.t -> Id.Set.t -> types -> Id.t val set_reserved_typed_name : (Environ.env -> evar_map -> types -> Name.t) -> unit (********************************************************************* Making name distinct for displaying *) val make_all_rel_context_name_different : env -> evar_map -> rel_context -> env * rel_context val make_all_name_different : env -> evar_map -> env module Generator : sig type 'a t type 'a input = 'a t * 'a val fresh : Nameops.Fresh.t t val idset : Id.Set.t t val next_name_away : 'a t -> Name.t -> 'a -> Id.t * 'a val max_map : 'a t -> 'a -> Nameops.Subscript.t Id.Map.t end type renaming_flags = | RenamingForCasesPattern of (Name.t list * constr) (** avoid only global constructors *) | RenamingForGoal (** avoid all globals (as in intro) *) | RenamingElsewhereFor of (Name.t list * constr) val compute_displayed_name_in : 'a Generator.t -> Environ.env -> evar_map -> renaming_flags -> 'a -> Name.t -> constr -> Name.t * 'a val compute_displayed_let_name_in : 'a Generator.t -> Environ.env -> evar_map -> renaming_flags -> 'a -> Name.t -> Name.t * 'a (* Generic function expecting a "not occurn" function *) val compute_displayed_name_in_gen : 'a Generator.t -> (evar_map -> int -> 'constr -> bool) -> Environ.env -> evar_map -> 'a -> Name.t -> 'constr -> Name.t * 'a rocq-9.2.0/engine/nameops.ml000066400000000000000000000443211516144147600157440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* [0] *) { ss_zero = 1; ss_subs = 0 } else (* [0...00] -> [0..01] *) { ss_zero = s.ss_zero - 1; ss_subs = 1 } else if overflow s.ss_subs then if Int.equal s.ss_zero 0 then (* [9...9] -> [10...0] *) { ss_zero = 0; ss_subs = 1 + s.ss_subs } else (* [0...009...9] -> [0...010...0] *) { ss_zero = s.ss_zero - 1; ss_subs = 1 + s.ss_subs } else (* [0...0n] -> [0...0{n+1}] *) { ss_zero = s.ss_zero; ss_subs = s.ss_subs + 1 } let equal s1 s2 = Int.equal s1.ss_zero s2.ss_zero && Int.equal s1.ss_subs s2.ss_subs let compare s1 s2 = (* Lexicographic order is reversed in order to ensure that [succ] is strictly increasing. *) let c = Int.compare s1.ss_subs s2.ss_subs in if Int.equal c 0 then Int.compare s1.ss_zero s2.ss_zero else c end let code_of_0 = Char.code '0' let code_of_9 = Char.code '9' let cut_ident skip_quote s = let s = Id.to_string s in let slen = String.length s in (* [n'] is the position of the first non nullary digit *) let rec numpart n n' = if Int.equal n 0 then (* ident made of _ and digits only [and ' if skip_quote]: don't cut it *) slen else let c = Char.code (String.get s (n-1)) in if Int.equal c code_of_0 && not (Int.equal n slen) then numpart (n-1) n' else if code_of_0 <= c && c <= code_of_9 then numpart (n-1) (n-1) else if skip_quote && (Int.equal c (Char.code '\'') || Int.equal c (Char.code '_')) then numpart (n-1) (n-1) else n' in numpart slen slen let repr_ident s = let numstart = cut_ident false s in let s = Id.to_string s in let slen = String.length s in if Int.equal numstart slen then (s, None) else (String.sub s 0 numstart, Some (int_of_string (String.sub s numstart (slen - numstart)))) let make_ident sa = function | Some n -> let c = Char.code (String.get sa (String.length sa -1)) in let s = if c < code_of_0 || c > code_of_9 then sa ^ (string_of_int n) else sa ^ "_" ^ (string_of_int n) in Id.of_string s | None -> Id.of_string sa let root_of_id id = let suffixstart = cut_ident true id in Id.of_string_soft (String.sub (Id.to_string id) 0 suffixstart) (* Return the same identifier as the original one but whose {i subscript} is incremented. If the original identifier does not have a suffix, [0] is appended to it. Example mappings: [bar] ↦ [bar0] [bar0] ↦ [bar1] [bar00] ↦ [bar01] [bar1] ↦ [bar2] [bar01] ↦ [bar02] [bar9] ↦ [bar10] [bar09] ↦ [bar10] [bar99] ↦ [bar100] *) let increment_subscript id = let id = Id.to_string id in let len = String.length id in let rec add carrypos = let c = id.[carrypos] in if is_digit c then if Int.equal (Char.code c) (Char.code '9') then begin assert (carrypos>0); add (carrypos-1) end else begin let newid = Bytes.of_string id in Bytes.fill newid (carrypos+1) (len-1-carrypos) '0'; Bytes.set newid carrypos (Char.chr (Char.code c + 1)); newid end else begin let newid = Bytes.of_string (id^"0") in if carrypos < len-1 then begin Bytes.fill newid (carrypos+1) (len-1-carrypos) '0'; Bytes.set newid (carrypos+1) '1' end; newid end in Id.of_bytes (add (len-1)) let has_subscript id = let id = Id.to_string id in is_digit (id.[String.length id - 1]) let get_subscript id = let id0 = id in let id = Id.to_string id in let len = String.length id in let rec get_suf accu pos = if pos < 0 then (pos, accu) else let c = id.[pos] in if is_digit c then get_suf (Char.code c - Char.code '0' :: accu) (pos - 1) else (pos, accu) in let (pos, suf) = get_suf [] (len - 1) in if Int.equal pos (len - 1) then (id0, Subscript.zero) else let id = String.sub id 0 (pos + 1) in let rec compute_zeros accu = function | [] -> (accu, []) | 0 :: l -> compute_zeros (succ accu) l | _ :: _ as l -> (accu, l) in let (ss_zero, suf) = compute_zeros 0 suf in let rec compute_suf accu = function | [] -> accu | n :: l -> compute_suf (10 * accu + n) l in let ss_subs = compute_suf 0 suf in (Id.of_string id, { Subscript.ss_subs; ss_zero; }) let add_subscript id ss = if Subscript.equal Subscript.zero ss then id else if Int.equal ss.Subscript.ss_subs 0 then let id = Id.to_string id in let pad = String.make ss.Subscript.ss_zero '0' in Id.of_string (Printf.sprintf "%s%s" id pad) else let id = Id.to_string id in let pad = String.make ss.Subscript.ss_zero '0' in let suf = ss.Subscript.ss_subs in Id.of_string (Printf.sprintf "%s%s%i" id pad suf) let forget_subscript id = let numstart = cut_ident false id in let newid = Bytes.make (numstart+1) '0' in String.blit (Id.to_string id) 0 newid 0 numstart; (Id.of_bytes newid) let add_suffix id s = Id.of_string (Id.to_string id ^ s) let add_prefix s id = Id.of_string (s ^ Id.to_string id) let atompart_of_id id = fst (repr_ident id) (** Segment trees: efficient lookup of the next free integer *) module SegTree : sig type t val empty : t val mem : int -> t -> bool val add : int -> t -> t val remove : int -> t -> t val union : t -> t -> t val next : int -> t -> int (** [next n s] returns the smallest integer [k] not in [s] s.t. [n <= k] *) val fresh : int -> t -> int * t (** Efficient composition of [next] and [add] *) val max_elt_opt : t -> int option end = struct module Segment = struct type t = int * int (* segment [p, q[, in particular p < q *) let compare (p, _) (q, _) = Int.compare p q end module SegSet = Set.Make(Segment) type t = SegSet.t (* Invariants: forall [p1, q1[, [p2, q2[ in such a set, either: - p1 = p2 and q1 = q2 - p1 < q1 < p2 < q2 - p2 < q2 < p1 < q1 *) let empty = SegSet.empty let mem n s = let find (_p, q) = n < q in match SegSet.find_first_opt find s with | None -> false | Some (p, _q) -> p <= n let add n s = let find_min (_p, q) = n < q in let find_max (_p, q) = q <= n in match SegSet.find_first_opt find_min s with | None -> (* n larger than all elements *) begin match SegSet.max_elt_opt s with | None -> SegSet.add (n, n + 1) s | Some (pl, ql) -> if Int.equal n ql then SegSet.add (pl, n + 1) (SegSet.remove (pl, ql) s) else SegSet.add (n, n + 1) s end | Some (pr, qr) -> if pr <= n then s (* already present *) else match SegSet.find_last_opt find_max s with | None -> (* n smaller than all elements *) if Int.equal pr (n + 1) then SegSet.add (n, qr) (SegSet.remove (pr, qr) s) else SegSet.add (n, n + 1) s | Some (pl, ql) -> (* pl < ql <= n < pr < qr *) if Int.equal ql n && Int.equal pr (n + 1) then SegSet.add (pl, qr) (SegSet.remove (pl, ql) (SegSet.remove (pr, qr) s)) else if Int.equal ql n then SegSet.add (pl, n + 1) (SegSet.remove (pl, ql) s) else if Int.equal pr (n + 1) then SegSet.add (n, qr) (SegSet.remove (pr, qr) s) else SegSet.add (n, n + 1) s (* could probably be more efficient but I couldn't figure it out *) let rec add_seg (x,y) s = let s = add x s in if Int.equal (x+1) y then s else add_seg (x+1,y) s let union s1 s2 = let count s = SegSet.fold (fun (p,q) acc -> acc + (q-p)) s 0 in let smaller, bigger = if count s1 <= count s2 then s1, s2 else s2, s1 in SegSet.fold add_seg smaller bigger let remove n s = let find_min (_p, q) = n < q in match SegSet.find_first_opt find_min s with | None -> s | Some (pr, qr) -> if pr <= n then let s = SegSet.remove (pr, qr) s in if Int.equal (pr + 1) qr then s else if Int.equal pr n then SegSet.add (n + 1, qr) s else if Int.equal (n + 1) qr then SegSet.add (pr, n) s else SegSet.add (pr, n) (SegSet.add (n + 1, qr) s) else s let next n s = let find (_p, q) = n < q in match SegSet.find_first_opt find s with | None -> n | Some (p, q) -> if p <= n then q else n let fresh n s = let find_min (_p, q) = n < q in let find_max (_p, q) = q <= n in match SegSet.find_first_opt find_min s with | None -> let s = match SegSet.max_elt_opt s with | None -> SegSet.add (n, n + 1) s | Some (pl, ql) -> if Int.equal n ql then SegSet.add (pl, n + 1) (SegSet.remove (pl, ql) s) else SegSet.add (n, n + 1) s in n, s | Some (pr, qr) -> if pr <= n then (* equivalent to adding qr *) let next = SegSet.find_first_opt (fun (p, _q) -> qr < p) s in let s = match next with | None -> SegSet.add (pr, qr + 1) (SegSet.remove (pr, qr) s) | Some (pk, qk) -> if Int.equal (qr + 1) pk then SegSet.add (pr, qk) (SegSet.remove (pk, qk) (SegSet.remove (pr, qr) s)) else SegSet.add (pr, qr + 1) (SegSet.remove (pr, qr) s) in qr, s else let s = match SegSet.find_last_opt find_max s with | None -> if Int.equal pr (n + 1) then SegSet.add (n, qr) (SegSet.remove (pr, qr) s) else SegSet.add (n, n + 1) s | Some (pl, ql) -> if Int.equal ql n && Int.equal pr (n + 1) then SegSet.add (pl, qr) (SegSet.remove (pl, ql) (SegSet.remove (pr, qr) s)) else if Int.equal ql n then SegSet.add (pl, n + 1) (SegSet.remove (pl, ql) s) else if Int.equal pr (n + 1) then SegSet.add (n, qr) (SegSet.remove (pr, qr) s) else SegSet.add (n, n + 1) s in n, s let max_elt_opt s = match SegSet.max_elt_opt s with | None -> None | Some (p, q) -> Some (q - 1) end module SubSet = struct type t = { num : SegTree.t; pre : SegTree.t list; (* lists are OK because we are already logarithmic *) } (* We represent sets of subscripts by case-splitting on ss_zero. If it is zero, we store the number in the [num] set. Otherwise, we know the set of possible values is finite. At position k, [pre] contains a set of maximum size 10^k representing k-digit numbers with at least one leading zero. *) let empty = { num = SegTree.empty; pre = []; } let rec pow10 k accu = if k <= 0 then accu else pow10 (k - 1) (10 * accu) let rec log10 n accu = if n <= 0 then accu else log10 (n / 10) (accu + 1) let max_subscript ss = let exp = log10 ss.Subscript.ss_subs 0 + ss.Subscript.ss_zero - 1 in pow10 exp 1 let add ss s = let open Subscript in if Int.equal ss.ss_zero 0 then { s with num = SegTree.add ss.ss_subs s.num } else let pre = let len = List.length s.pre in if len < ss.ss_zero then s.pre @ List.make (ss.ss_zero - len) SegTree.empty else s.pre in let set = match List.nth_opt pre (ss.ss_zero - 1) with | None -> assert false | Some m -> SegTree.add ss.ss_subs m in { s with pre = List.assign pre (ss.ss_zero - 1) set } let union {num=num1; pre=pre1} {num=num2; pre=pre2} = let rec merge_pre pre1 pre2 = match pre1, pre2 with | [], x | x, [] -> x | v1 :: rest1, v2 :: rest2 -> SegTree.union v1 v2 :: merge_pre rest1 rest2 in let num = SegTree.union num1 num2 in {num; pre=merge_pre pre1 pre2} let remove ss s = let open Subscript in if Int.equal ss.ss_zero 0 then { s with num = SegTree.remove ss.ss_subs s.num } else match List.nth_opt s.pre (ss.ss_zero - 1) with | None -> s | Some m -> let m = SegTree.remove ss.ss_subs m in { s with pre = List.assign s.pre (ss.ss_zero - 1) m } let mem ss s = let open Subscript in if Int.equal ss.ss_zero 0 then SegTree.mem ss.ss_subs s.num else match List.nth_opt s.pre (ss.ss_zero - 1) with | None -> false | Some m -> SegTree.mem ss.ss_subs m let ss_O = { Subscript.ss_zero = 1; ss_subs = 0 } (* [0] *) let next ss s = let open Subscript in if ss.ss_zero > 0 then match List.nth_opt s.pre (ss.ss_zero - 1) with | None -> ss | Some m -> let next = SegTree.next ss.ss_subs m in let max = max_subscript ss in if max <= next then (* overflow *) { ss_zero = 0; ss_subs = SegTree.next max s.num } else { ss_zero = ss.ss_zero; ss_subs = next } else if Int.equal ss.ss_subs 0 then (* Handle specially [] *) if not @@ SegTree.mem 0 s.num then Subscript.zero else match s.pre with | [] -> ss_O | m :: _ -> if SegTree.mem 0 m then { ss_zero = 0; ss_subs = SegTree.next 1 s.num } else ss_O else { ss_zero = 0; ss_subs = SegTree.next ss.ss_subs s.num } let fresh ss s = let open Subscript in if ss.ss_zero > 0 then match List.nth_opt s.pre (ss.ss_zero - 1) with | None -> ss, add ss s | Some m -> let subs, m = SegTree.fresh ss.ss_subs m in let max = max_subscript ss in if max <= subs then let subs, num = SegTree.fresh max s.num in { ss_zero = 0; ss_subs = subs }, { s with num } else let s = { s with pre = List.assign s.pre (ss.ss_zero - 1) m } in { ss_zero = ss.ss_zero; ss_subs = subs }, s else if Int.equal ss.ss_subs 0 then if not @@ SegTree.mem 0 s.num then Subscript.zero, { num = SegTree.add 0 s.num; pre = s.pre } else match s.pre with | [] -> ss_O, { num = s.num; pre = [SegTree.add 0 SegTree.empty] } | m :: rem -> if SegTree.mem 0 m then let subs, num = SegTree.fresh 1 s.num in { ss_zero = 0; ss_subs = subs }, { num; pre = s.pre } else ss_O, { num = s.num; pre = SegTree.add 0 SegTree.empty :: rem } else let subs, num = SegTree.fresh ss.ss_subs s.num in { ss_zero = 0; ss_subs = subs }, { s with num } let max_elt_opt s = let mapi i m = match SegTree.max_elt_opt m with | None -> None | Some k -> Some { Subscript.ss_zero = i; ss_subs = k } in let maxs = List.mapi mapi (s.num :: s.pre) in let fold s accu = match s with | None -> accu | Some ss -> match accu with | None -> Some ss | Some ss' -> if Subscript.compare ss ss' <= 0 then accu else s in List.fold_left fold None maxs end module Fresh = struct type t = SubSet.t Id.Map.t let empty = Id.Map.empty let add id m = let (id, s) = get_subscript id in let old = try Id.Map.find id m with Not_found -> SubSet.empty in Id.Map.add id (SubSet.add s old) m let union m1 m2 = Id.Map.union (fun _ s1 s2 -> Some (SubSet.union s1 s2)) m1 m2 let remove id m = let (id, s) = get_subscript id in match Id.Map.find id m with | old -> Id.Map.add id (SubSet.remove s old) m | exception Not_found -> m let mem id m = let (id, s) = get_subscript id in try SubSet.mem s (Id.Map.find id m) with Not_found -> false let next id0 m = let (id, s) = get_subscript id0 in match Id.Map.find_opt id m with | None -> id0 | Some old -> let ss = SubSet.next s old in add_subscript id ss let fresh id0 m = let (id, s) = get_subscript id0 in match Id.Map.find_opt id m with | None -> id0, Id.Map.add id (SubSet.add s SubSet.empty) m | Some old -> let ss, n = SubSet.fresh s old in add_subscript id ss, Id.Map.add id n m let of_list l = List.fold_left (fun accu id -> add id accu) empty l let of_set s = Id.Set.fold add s empty let of_named_context_val s = of_set @@ Environ.ids_of_named_context_val s let max_map s = let filter id m = SubSet.max_elt_opt m in Id.Map.filter_map filter s end (* Names *) module type ExtName = sig include module type of struct include Names.Name end exception IsAnonymous val fold_left : ('a -> Id.t -> 'a) -> 'a -> t -> 'a val fold_right : (Id.t -> 'a -> 'a) -> t -> 'a -> 'a val iter : (Id.t -> unit) -> t -> unit val map : (Id.t -> Id.t) -> t -> t val fold_left_map : ('a -> Id.t -> 'a * Id.t) -> 'a -> t -> 'a * t val fold_right_map : (Id.t -> 'a -> Id.t * 'a) -> Name.t -> 'a -> Name.t * 'a val get_id : t -> Id.t val pick : t -> t -> t val pick_annot : (t,'r) Context.pbinder_annot -> (t,'r) Context.pbinder_annot -> (t,'r) Context.pbinder_annot val cons : t -> Id.t list -> Id.t list val to_option : Name.t -> Id.t option end module Name : ExtName = struct include Names.Name exception IsAnonymous let fold_left f a = function | Name id -> f a id | Anonymous -> a let fold_right f na a = match na with | Name id -> f id a | Anonymous -> a let iter f na = fold_right (fun x () -> f x) na () let map f = function | Name id -> Name (f id) | Anonymous -> Anonymous let fold_left_map f a = function | Name id -> let (a, id) = f a id in (a, Name id) | Anonymous -> a, Anonymous let fold_right_map f na a = match na with | Name id -> let (id, a) = f id a in (Name id, a) | Anonymous -> Anonymous, a let get_id = function | Name id -> id | Anonymous -> raise IsAnonymous let pick na1 na2 = match na1 with | Name _ -> na1 | Anonymous -> na2 let pick_annot na1 na2 = let open Context in match na1.binder_name with | Name _ -> na1 | Anonymous -> na2 let cons na l = match na with | Anonymous -> l | Name id -> id::l let to_option = function | Anonymous -> None | Name id -> Some id end (* Metavariables *) let pr_meta = Pp.int let string_of_meta = string_of_int rocq-9.2.0/engine/nameops.mli000066400000000000000000000110751516144147600161150ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int option -> Id.t val repr_ident : Id.t -> string * int option val atompart_of_id : Id.t -> string (** remove trailing digits *) val root_of_id : Id.t -> Id.t (** remove trailing digits, ' and _ *) val add_suffix : Id.t -> string -> Id.t val add_prefix : string -> Id.t -> Id.t (** Below, by {i subscript} we mean a suffix composed solely from (decimal) digits. *) module Subscript : sig type t (** Abstract datatype of subscripts. Isomorphic to a string of digits. *) val zero : t (** Empty subscript *) val succ : t -> t (** Guarantees that [x < succ x], but [succ x] might not be the smallest element strictly above [x], generally it does not exist. Example mappings: "" ↦ "0" "0" ↦ "1" "00" ↦ "01" "1" ↦ "2" "01" ↦ "02" "9" ↦ "10" "09" ↦ "10" "99" ↦ "100" *) val compare : t -> t -> int (** Well-founded order. *) val equal : t -> t -> bool end module Fresh : sig type t val empty : t val add : Id.t -> t -> t val union : t -> t -> t val remove : Id.t -> t -> t val mem : Id.t -> t -> bool val next : Id.t -> t -> Id.t val fresh : Id.t -> t -> Id.t * t val of_list : Id.t list -> t val of_set : Id.Set.t -> t val of_named_context_val : Environ.named_context_val -> t val max_map : t -> Subscript.t Id.Map.t end val has_subscript : Id.t -> bool val get_subscript : Id.t -> Id.t * Subscript.t (** Split an identifier into a base name and a subscript. *) val add_subscript : Id.t -> Subscript.t -> Id.t (** Append the subscript to the identifier. *) val increment_subscript : Id.t -> Id.t (** Return the same identifier as the original one but whose {i subscript} is incremented. If the original identifier does not have a suffix, [0] is appended to it. Example mappings: [bar] ↦ [bar0] [bar0] ↦ [bar1] [bar00] ↦ [bar01] [bar1] ↦ [bar2] [bar01] ↦ [bar01] [bar9] ↦ [bar10] [bar09] ↦ [bar10] [bar99] ↦ [bar100] *) val forget_subscript : Id.t -> Id.t module Name : sig include module type of struct include Names.Name end exception IsAnonymous val fold_left : ('a -> Id.t -> 'a) -> 'a -> Name.t -> 'a (** [fold_left f na a] is [f id a] if [na] is [Name id], and [a] otherwise. *) val fold_right : (Id.t -> 'a -> 'a) -> Name.t -> 'a -> 'a (** [fold_right f a na] is [f a id] if [na] is [Name id], and [a] otherwise. *) val iter : (Id.t -> unit) -> Name.t -> unit (** [iter f na] does [f id] if [na] equals [Name id], nothing otherwise. *) val map : (Id.t -> Id.t) -> Name.t -> t (** [map f na] is [Anonymous] if [na] is [Anonymous] and [Name (f id)] if [na] is [Name id]. *) val fold_left_map : ('a -> Id.t -> 'a * Id.t) -> 'a -> Name.t -> 'a * Name.t (** [fold_left_map f a na] is [a',Name id'] when [na] is [Name id] and [f a id] is [(a',id')]. It is [a,Anonymous] otherwise. *) val fold_right_map : (Id.t -> 'a -> Id.t * 'a) -> Name.t -> 'a -> Name.t * 'a (** [fold_right_map f na a] is [Name id',a'] when [na] is [Name id] and [f id a] is [(id',a')]. It is [Anonymous,a] otherwise. *) val get_id : Name.t -> Id.t (** [get_id] associates [id] to [Name id]. @raise IsAnonymous otherwise. *) val pick : Name.t -> Name.t -> Name.t (** [pick na na'] returns [Anonymous] if both names are [Anonymous]. Pick one of [na] or [na'] otherwise. *) val pick_annot : (Name.t,'r) Context.pbinder_annot -> (Name.t,'r) Context.pbinder_annot -> (Name.t,'r) Context.pbinder_annot val cons : Name.t -> Id.t list -> Id.t list (** [cons na l] returns [id::l] if [na] is [Name id] and [l] otherwise. *) val to_option : Name.t -> Id.t option (** [to_option Anonymous] is [None] and [to_option (Name id)] is [Some id] *) end (** Metavariables *) val pr_meta : Constr.metavariable -> Pp.t val string_of_meta : Constr.metavariable -> string rocq-9.2.0/engine/polyFlags.ml000066400000000000000000000035031516144147600162370ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* collapse_sort_variables:bool -> cumulative:bool -> t (** The [default] is monomorphic: [univ_poly] and [cumulative] are [false], [collapse_sort_variables] is [true] *) val default : t (** Only sets the universe [univ_poly] flag. Use with care, this probably indicates that the code does not handle [cumulative] constructions when it should. Code relying on elaboration should also support the [collapse_sort_variables] flag. *) val of_univ_poly : bool -> t (** Accessors *) val univ_poly : t -> bool val collapse_sort_variables : t -> bool val cumulative : t -> bool (** Pretty print *) val pr : t -> Pp.t (** Used to have distinguished default behaviors when treating assumptions/axioms, definitions or inductives *) type construction_kind = Assumption | Definition | Inductive rocq-9.2.0/engine/profile_tactic.ml000066400000000000000000000421461516144147600172740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* CErrors.user_err Pp.(str "Ltac Profiling Cutoff must be interpretable as a float.") let encountered_invalid_stack_no_self = ref false let warn_invalid_stack_no_self = CWarnings.create ~name:"profile-invalid-stack-no-self" ~category:CWarnings.CoreCategories.ltac (fun () -> strbrk "Ltac Profiler encountered an invalid stack (no self \ node). This can happen if you reset the profile during \ tactic execution.") let encounter_invalid_stack_no_self () = if not !encountered_invalid_stack_no_self then begin encountered_invalid_stack_no_self := true; warn_invalid_stack_no_self () end (* *************** tree data structure for profiling ****************** *) type treenode = { name : string; total : float; local : float; ncalls : int; max_total : float; children : treenode M.t } let empty_treenode name = { name; total = 0.0; local = 0.0; ncalls = 0; max_total = 0.0; children = M.empty; } let root = "root" let stack = Summary.ref ~name:"LtacProf-stack" ~local:true [empty_treenode root] let reset_profile_tmp () = stack := [empty_treenode root] (* ************** XML Serialization ********************* *) let rec of_ltacprof_tactic (name, t) = assert (String.equal name t.name); let open Xml_datatype in let total = string_of_float t.total in let local = string_of_float t.local in let ncalls = string_of_int t.ncalls in let max_total = string_of_float t.max_total in let children = List.map of_ltacprof_tactic (M.bindings t.children) in Element ("ltacprof_tactic", [ ("name", name); ("total",total); ("local",local); ("ncalls",ncalls); ("max_total",max_total)], children) let of_ltacprof_results t = let open Xml_datatype in assert(String.equal t.name root); let children = List.map of_ltacprof_tactic (M.bindings t.children) in Element ("ltacprof", [("total_time", string_of_float t.total)], children) let rec to_ltacprof_tactic m xml = let open Xml_datatype in match xml with | Element ("ltacprof_tactic", [("name", name); ("total",total); ("local",local); ("ncalls",ncalls); ("max_total",max_total)], xs) -> let node = { name; total = float_of_string total; local = float_of_string local; ncalls = int_of_string ncalls; max_total = float_of_string max_total; children = List.fold_left to_ltacprof_tactic M.empty xs; } in M.add name node m | _ -> CErrors.anomaly Pp.(str "Malformed ltacprof_tactic XML.") let to_ltacprof_results xml = let open Xml_datatype in match xml with | Element ("ltacprof", [("total_time", t)], xs) -> { name = root; total = float_of_string t; ncalls = 0; max_total = 0.0; local = 0.0; children = List.fold_left to_ltacprof_tactic M.empty xs } | _ -> CErrors.anomaly Pp.(str "Malformed ltacprof XML.") let feedback_results results = Feedback.(feedback (Custom (None, "ltacprof_results", of_ltacprof_results results))) (* ************** pretty printing ************************************* *) let format_sec x = (Printf.sprintf "%.3fs" x) let format_ratio x = (Printf.sprintf "%.1f%%" (100. *. x)) let padl n s = ws (max 0 (n - utf8_length s)) ++ str s let padr_with c n s = let ulength = utf8_length s in if Int.equal n ulength then str s else if n < ulength then str (utf8_sub s 0 n) else str s ++ str (String.make (n - ulength) c) let rec list_map_is_last f = function | [] -> [] | [x] -> [f true x] | x :: xs -> f false x :: list_map_is_last f xs let repeat_str n s = if String.is_empty s then s else let len = String.length s in String.init (n * len) (fun i -> s.[i mod len]) let header_name = " tactic" let header_name_width = utf8_length header_name let header_rest = "β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜" let header_rest_width = utf8_length header_rest let header name_width = str " tactic" ++ str (String.make (name_width - header_name_width) ' ') ++ str " local total calls max" ++ fnl () ++ str (repeat_str name_width "─") ++ str header_rest ++ fnl () module Line = struct type t = { prefix : string; tac_name : string; local : float; total : float; calls : int; maxtime : float; } let pr ~name_width l = h ( padr_with '-' name_width (l.prefix ^ l.tac_name ^ " ") ++ padl 7 (format_ratio l.local) ++ padl 7 (format_ratio l.total) ++ padl 8 (string_of_int l.calls) ++ padl 10 (format_sec l.maxtime)) end let rec linearize_node ~filter all_total indent prefix (s, e) = { Line.prefix; tac_name=s; local = (e.local /. all_total); total = (e.total /. all_total); calls = e.ncalls; maxtime = e.max_total; } :: linearize_table ~filter all_total indent false e.children and linearize_table ~filter all_total indent first_level table = let fold _ n l = let s, total = n.name, n.total in if filter s total then (s, n) :: l else l in let ls = M.fold fold table [] in match ls with | [s, n] when not first_level -> linearize_node ~filter all_total indent (indent ^ "β””") (s, n) | _ -> let ls = List.sort (fun (_, { total = s1 }) (_, { total = s2}) -> compare s2 s1) ls in let iter is_last = let sep0 = if first_level then "" else if is_last then " " else " β”‚" in let sep1 = if first_level then "─" else if is_last then " └─" else " β”œβ”€" in linearize_node ~filter all_total (indent ^ sep0) (indent ^ sep1) in List.concat (list_map_is_last iter ls) let get_printing_width = ref (fun () -> Format.pp_get_margin Format.std_formatter ()) let set_get_printing_width f = get_printing_width := f let get_printing_width () = !get_printing_width () let print_table ~filter all_total table = let lines = linearize_table ~filter all_total "" true table in let name_width = List.fold_left (fun acc (l:Line.t) -> max acc (utf8_length (l.prefix ^ l.tac_name))) 0 lines in let name_width = name_width + 1 (* +1 for a space at the end *) in (* respect Printing Width unless it's so short that we can't print the header correctly *) let name_width = min (get_printing_width() - header_rest_width) name_width in let name_width = max header_name_width name_width in header name_width ++ prlist_with_sep fnl (Line.pr ~name_width) lines let to_string ~filter ~cutoff node = let tree = node.children in let all_total = M.fold (fun _ { total } a -> total +. a) node.children 0.0 in let flat_tree = let global = ref M.empty in let find_tactic tname l = try M.find tname !global with Not_found -> let e = empty_treenode tname in global := M.add tname e !global; e in let add_tactic tname stats = global := M.add tname stats !global in let sum_stats add_total { name; total = t1; local = l1; ncalls = n1; max_total = m1 } { total = t2; local = l2; ncalls = n2; max_total = m2 } = { name; total = if add_total then t1 +. t2 else t1; local = l1 +. l2; ncalls = n1 + n2; max_total = if add_total then max m1 m2 else m1; children = M.empty; } in let rec cumulate table = let iter _ ({ name; children } as statistics) = if filter name then begin let stats' = find_tactic name global in add_tactic name (sum_stats true stats' statistics); end; cumulate children in M.iter iter table in cumulate tree; !global in let filter s n = filter s && (all_total <= 0.0 || n /. all_total >= cutoff /. 100.0) in let msg = h (str "total time: " ++ padl 11 (format_sec (all_total))) ++ fnl () ++ fnl () ++ print_table ~filter all_total flat_tree ++ fnl () ++ fnl () ++ print_table ~filter all_total tree in msg (* ******************** profiling code ************************************** *) let get_child name node = try M.find name node.children with Not_found -> empty_treenode name let time () = let times = Unix.times () in times.Unix.tms_utime +. times.Unix.tms_stime let string_of_call ck = let s = string_of_ppcmds ck in let s = String.map (fun c -> if c = '\n' then ' ' else c) s in let s = try String.sub s 0 (CString.string_index_from s 0 "(*") with Not_found -> s in String.trim s let rec merge_sub_tree name tree acc = try let t = M.find name acc in let t = { name; total = t.total +. tree.total; ncalls = t.ncalls + tree.ncalls; local = t.local +. tree.local; max_total = max t.max_total tree.max_total; children = M.fold merge_sub_tree tree.children t.children; } in M.add name t acc with Not_found -> M.add name tree acc let merge_roots ?(disjoint=true) t1 t2 = assert(String.equal t1.name t2.name); { name = t1.name; ncalls = t1.ncalls + t2.ncalls; local = if disjoint then t1.local +. t2.local else t1.local; total = if disjoint then t1.total +. t2.total else t1.total; max_total = if disjoint then max t1.max_total t2.max_total else t1.max_total; children = M.fold merge_sub_tree t2.children t1.children } let rec find_in_stack what acc = function | [] -> None | { name } as x :: rest when String.equal name what -> Some(acc, x, rest) | { name } as x :: rest -> find_in_stack what (x :: acc) rest let exit_tactic ~count_call start_time name = let diff = time () -. start_time in match !stack with | [] | [_] -> (* oops, our stack is invalid *) encounter_invalid_stack_no_self (); reset_profile_tmp () | node :: (parent :: rest as full_stack) -> if not (String.equal name node.name) then (* oops, our stack is invalid *) CErrors.anomaly (Pp.strbrk "Ltac Profiler encountered an invalid stack (wrong self node) \ likely due to backtracking into multi-success tactics."); let node = { node with total = node.total +. diff; local = node.local +. diff; ncalls = node.ncalls + (if count_call then 1 else 0); max_total = max node.max_total diff; } in (* updating the stack *) let parent = match find_in_stack node.name [] full_stack with | None -> (* no rec-call, we graft the subtree *) let parent = { parent with local = parent.local -. diff; children = M.add node.name node parent.children } in stack := parent :: rest; parent | Some(to_update, self, rest) -> (* we coalesce the rec-call and update the lower stack *) let self = merge_roots ~disjoint:false self node in let updated_stack = List.fold_left (fun s x -> (try M.find x.name (List.hd s).children with Not_found -> x) :: s) (self :: rest) to_update in stack := updated_stack; List.hd !stack in (* Calls are over, we reset the stack and send back data *) if rest == [] && get_profiling () then begin assert(String.equal root parent.name); encountered_invalid_stack_no_self := false; reset_profile_tmp (); feedback_results parent end (** [tclWRAPFINALLY before tac finally] runs [before] before each entry-point of [tac] and passes the result of [before] to [finally], which is then run at each exit-point of [tac], regardless of whether it succeeds or fails. Said another way, if [tac] succeeds, then it behaves as [before >>= fun v -> tac >>= fun ret -> finally v <*> tclUNIT ret]; otherwise, if [tac] fails with [e], it behaves as [before >>= fun v -> finally v <*> tclZERO e]. *) let rec tclWRAPFINALLY before tac finally = let open Proofview in let open Proofview.Notations in before >>= fun v -> tclCASE tac >>= function | Fail (e, info) -> finally v >>= fun () -> tclZERO ~info e | Next (ret, tac') -> tclOR (finally v >>= fun () -> tclUNIT ret) (fun e -> tclWRAPFINALLY before (tac' e) finally) let do_profile_gen pp_call call_trace ?(count_call=true) tac = let open Proofview.Notations in (* We do an early check to [is_profiling] so that we save the overhead of [tclWRAPFINALLY] when profiling is not set *) Proofview.tclLIFT (Proofview.NonLogical.make (fun () -> !is_profiling)) >>= function | false -> tac | true -> tclWRAPFINALLY (Proofview.tclLIFT (Proofview.NonLogical.make (fun () -> match pp_call call_trace, !stack with | Some c, parent :: rest -> let name = string_of_call c in let node = get_child name parent in stack := node :: parent :: rest; Some (name, time ()) | Some _, [] -> assert false | _ -> None ))) tac (function | Some (name, start_time) -> (Proofview.tclLIFT (Proofview.NonLogical.make (fun () -> exit_tactic ~count_call start_time name))) | None -> Proofview.tclUNIT ()) (* ************** Accumulation of data from workers ************************* *) let get_local_profiling_results () = List.hd !stack (* We maintain our own cache of document data, given that the semantics of the STM implies that synchronized state for opaque proofs will be lost on QED. This provides some complications later on as we will have to simulate going back on the document on our own. *) module DData = struct type t = Feedback.doc_id * Stateid.t let compare x y = compare x y end module SM = Map.Make(DData) let data = ref SM.empty let _ = Feedback.(add_feeder (function | { doc_id = d; span_id = s; contents = Custom (_, "ltacprof_results", xml) } -> let results = to_ltacprof_results xml in let other_results = (* Multi success can cause this *) try SM.find (d,s) !data with Not_found -> empty_treenode root in data := SM.add (d,s) (merge_roots results other_results) !data | _ -> ())) let reset_profile () = encountered_invalid_stack_no_self := false; reset_profile_tmp (); data := SM.empty (* ****************************** Named timers ****************************** *) let timer_data = ref M.empty let timer_name = function | Some v -> v | None -> "" let restart_timer name = timer_data := M.add (timer_name name) (System.get_time ()) !timer_data let get_timer name = try M.find (timer_name name) !timer_data with Not_found -> System.get_time () let finish_timing ~prefix name = let tend = System.get_time () in let tstart = get_timer name in Feedback.msg_notice(str prefix ++ pr_opt str name ++ str " ran for " ++ System.fmt_time_difference tstart tend) (* ******************** *) let print_results_filter ~cutoff ~filter = let cutoff = Option.default !profile_ltac_cutoff cutoff in data := SM.filter (fun (doc,id) _ -> Stateid.is_valid ~doc id) !data; let results = SM.fold (fun _ -> merge_roots ~disjoint:true) !data (empty_treenode root) in let results = merge_roots results (CList.last !stack) in Feedback.msg_notice (to_string ~cutoff ~filter results) ;; let print_results ~cutoff = print_results_filter ~cutoff ~filter:(fun _ -> true) let print_results_tactic tactic = print_results_filter ~cutoff:None ~filter:(fun s -> String.(equal tactic (sub (s ^ ".") 0 (min (1+length s) (length tactic))))) let do_print_results_at_close () = if get_profiling () then print_results ~cutoff:None let () = let open Goptions in declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Ltac"; "Profiling"]; optread = get_profiling; optwrite = set_profiling } let () = let open Goptions in declare_string_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Ltac"; "Profiling"; "Cutoff"]; optread = get_profiling_cutoff; optwrite = set_profiling_cutoff } rocq-9.2.0/engine/profile_tactic.mli000066400000000000000000000100721516144147600174360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.t option) -> 'a -> ?count_call:bool -> 'b Proofview.tactic -> 'b Proofview.tactic val set_profiling : bool -> unit val get_profiling : unit -> bool (* Cut off results < than specified cutoff *) val print_results : cutoff:float option -> unit val print_results_tactic : string -> unit val reset_profile : unit -> unit val restart_timer : string option -> unit val finish_timing : prefix:string -> string option -> unit val do_print_results_at_close : unit -> unit (* The collected statistics for a tactic. The timing data is collected over all * instances of a given tactic from its parent. E.g. if tactic 'aaa' calls * 'foo' twice, then 'aaa' will contain just one entry for 'foo' with the * statistics of the two invocations combined, and also combined over all * invocations of 'aaa'. * total: time spent running this tactic and its subtactics (seconds) * local: time spent running this tactic, minus its subtactics (seconds) * ncalls: the number of invocations of this tactic that have been made * max_total: the greatest running time of a single invocation (seconds) *) type treenode = { name : string; total : float; local : float; ncalls : int; max_total : float; children : treenode CString.Map.t } (* Returns the profiling results known by the current process *) val get_local_profiling_results : unit -> treenode val feedback_results : treenode -> unit val set_get_printing_width : (unit -> int) -> unit (** Internal hook *) rocq-9.2.0/engine/proofview.ml000066400000000000000000001272611516144147600163270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* map_constr nf0 d) hyps in let size = Evd.fold (fun _ _ i -> i+1) solution 0 in let new_el = List.map (fun (hyps,t,ty) -> nf_hyps hyps, nf t, nf ty) el in let pruned_solution = Evd.drop_all_defined solution in let apply_subst_einfo _ ei = Evd.map_evar_info nf ei in let new_solution = Evd.raw_map_undefined apply_subst_einfo pruned_solution in let new_size = Evd.fold (fun _ _ i -> i+1) new_solution 0 in Feedback.msg_info (Pp.str (Printf.sprintf "Evars: %d -> %d\n" size new_size)); new_el, { pv with solution = new_solution; } (** {6 Starting and querying a proof view} *) type telescope = | TNil of Evd.evar_map | TCons of Environ.env * Evd.evar_map * EConstr.types * (Evd.evar_map -> EConstr.constr -> telescope) let map_telescope_evd f = function | TNil sigma -> TNil (f sigma) | TCons (env,sigma,ty,g) -> TCons(env,(f sigma),ty,g) let dependent_init = (* Goals don't have a source location. *) let src = Loc.tag @@ Evar_kinds.GoalEvar in (* Main routine *) let rec aux = function | TNil sigma -> [], { solution = sigma; comb = [] } | TCons (env, sigma, typ, t) -> let (sigma, econstr) = Evarutil.new_evar env sigma ~src ~typeclass_candidate:false typ in let (gl, _) = EConstr.destEvar sigma econstr in let ret, { solution = sol; comb = comb } = aux (t sigma econstr) in let entry = (Environ.named_context_val env, econstr, typ) :: ret in entry, { solution = sol; comb = with_empty_state gl :: comb } in fun t -> let t = map_telescope_evd Evd.push_future_goals t in let entry, v = aux t in (* The created goal are not to be shelved. *) let _goals, solution = Evd.pop_future_goals v.solution in entry, { v with solution } let init = let rec aux sigma = function | [] -> TNil sigma | (env,g)::l -> TCons (env,sigma,g,(fun sigma _ -> aux sigma l)) in fun sigma l -> dependent_init (aux sigma l) let initial_goals initial = initial let finished = function | {comb = []} -> true | _ -> false let return { solution=defs } = defs let return_constr { solution = defs } c = Evarutil.nf_evar defs c let partial_proof entry pv = CList.map (return_constr pv) (CList.map pi2 entry) (** {6 Normalizing evars} *) let cleared_alias evd g = let evk = drop_state g in let state = get_state g in Option.map (fun g -> goal_with_state g state) (Evarutil.advance evd evk) (** [undefined defs l] is the list of goals in [l] which are still unsolved (after advancing cleared goals). Note that order matters. *) let undefined_evars defs l = let fold evk (seen, ans as accu) = match Evarutil.advance defs evk with | None -> accu | Some evk -> if Evar.Set.mem evk seen then accu else (Evar.Set.add evk seen, evk :: ans) in snd @@ List.fold_right fold l (Evar.Set.empty, []) let undefined defs l = let fold gl (seen, ans as accu) = match cleared_alias defs gl with | None -> accu | Some gl -> let evk = drop_state gl in if Evar.Set.mem evk seen then accu else (Evar.Set.add evk seen, gl :: ans) in snd @@ List.fold_right fold l (Evar.Set.empty, []) (** {6 Focusing commands} *) (** A [focus_context] represents the part of the proof view which has been removed by a focusing action, it can be used to unfocus later on. *) (* First component is a reverse list of the goals which come before and second component is the list of the goals which go after (in the expected order). *) type focus_context = goal_with_state list * goal_with_state list (** Returns a stylised view of a focus_context for use by, for instance, ide-s. *) (* spiwack: the type of [focus_context] will change as we push more refined functions to ide-s. This would be better than spawning a new nearly identical function every time. Hence the generic name. *) (* In this version: the goals in the context, as a "zipper" (the first list is in reversed order). *) let focus_context sigma (left,right) = (undefined_evars sigma (List.map drop_state left), undefined_evars sigma (List.map drop_state right)) (** This (internal) function extracts a sublist between two indices, and returns this sublist together with its context: if it returns [(a,(b,c))] then [a] is the sublist and [(rev b) @ a @ c] is the original list. The focused list has length [j-i-1] and contains the goals from number [i] to number [j] (both included) the first goal of the list being numbered [1]. [focus_sublist i j l] raises [IndexOutOfRange] if [i > length l], or [j > length l] or [j < i]. *) let focus_sublist i j l = let (left,sub_right) = CList.goto (i-1) l in let (sub, right) = try CList.chop (j-i+1) sub_right with Failure _ -> raise CList.IndexOutOfRange in (sub, (left,right)) (** Inverse operation to the previous one. *) let unfocus_sublist (left,right) s = CList.rev_append left (s@right) (** [focus i j] focuses a proofview on the goals from index [i] to index [j] (inclusive, goals are indexed from [1]). I.e. goals number [i] to [j] become the only focused goals of the returned proofview. It returns the focused proofview, and a context for the focus stack. *) let focus i j sp = let (new_comb, (left, right)) = focus_sublist i j sp.comb in ( { sp with comb = new_comb } , (left, right) ) (* Returns [ev, Some n] if [n] is the index of evar [ev] with name [id] in the list of currently focused goals, or [ev, None] if [ev] is shelved. Raises [Not_found] if the evar does not exist. *) let find_evar_in_pv id pv = let ev = Evd.evar_key id pv.solution in let comb = CList.map drop_state pv.comb in try ev, Some (CList.index Evar.equal ev comb) with Not_found -> ev, None (** Unfocuses a proofview with respect to a context. *) let unfocus (left, right) sp = { sp with comb = undefined sp.solution (unfocus_sublist (left, right) sp.comb) } let with_empty_state = Proofview_monad.with_empty_state let drop_state = Proofview_monad.drop_state let goal_with_state = Proofview_monad.goal_with_state (** {6 The tactic monad} *) (** - Tactics are objects which apply a transformation to all the subgoals of the current view at the same time. By opposition to the old vision of applying it to a single goal. It allows tactics such as [shelve_unifiable], tactics to reorder the focused goals, or global automation tactic for dependent subgoals (instantiating an evar has influences on the other goals of the proof in progress, not being able to take that into account causes the current eauto tactic to fail on some instances where it could succeed). Another benefit is that it is possible to write tactics that can be executed even if there are no focused goals. - Tactics form a monad ['a tactic], in a sense a tactic can be seen as a function (without argument) which returns a value of type 'a and modifies the environment (in our case: the view). Tactics of course have arguments, but these are given at the meta-level as OCaml functions. Most tactics in the sense we are used to return [()], that is no really interesting values. But some might pass information around. The tactics seen in Rocq's Ltac are (for now at least) only [unit tactic], the return values are kept for the OCaml toolkit. The operation or the monad are [Proofview.tclUNIT] (which is the "return" of the tactic monad) [Proofview.tclBIND] (which is the "bind") and [Proofview.tclTHEN] (which is a specialized bind on unit-returning tactics). - Tactics have support for full-backtracking. Tactics can be seen having multiple success: if after returning the first success a failure is encountered, the tactic can backtrack and use a second success if available. The state is backtracked to its previous value, except the non-logical state defined in the {!NonLogical} module below. *) (* spiwack: as far as I'm aware this doesn't really relate to F. Kirchner and C. MuΓ±oz. *) module Proof = Logical (** type of tactics: tactics can - access the environment, - report unsafe status, shelved goals and given up goals - access and change the current [proofview] - backtrack on previous changes of the proofview *) type +'a tactic = 'a Proof.t (** Applies a tactic to the current proofview. *) let apply ~name ~poly env t sp = let open Logic_monad in NewProfile.profile "Proofview.apply" (fun () -> let ans = Proof.repr (Proof.run t P.{trace=false; name; poly} (sp,env)) in let ans = Logic_monad.NonLogical.run ans in match ans with | Nil (e, info) -> Exninfo.iraise (TacticFailure e, info) | Cons ((r, (state, env), status, info), _) -> r, state, env, status, Trace.to_tree info) () (** {7 Monadic primitives} *) (** Unit of the tactic monad. *) let tclUNIT = Proof.return (** Bind operation of the tactic monad. *) let tclBIND = Proof.(>>=) (** Interprets the ";" (semicolon) of Ltac. As a monadic operation, it's a specialized "bind". *) let tclTHEN = Proof.(>>) (** [tclIGNORE t] has the same operational content as [t], but drops the returned value. *) let tclIGNORE = Proof.ignore module Monad = Proof (** {7 Failure and backtracking} *) (** [tclZERO e] fails with exception [e]. It has no success. *) let tclZERO ?(info=Exninfo.null) e = if not (CErrors.noncritical e) then CErrors.anomaly (Pp.str "tclZERO receiving critical error: " ++ CErrors.print e); Proof.zero (e, info) (** [tclOR t1 t2] behaves like [t1] as long as [t1] succeeds. Whenever the successes of [t1] have been depleted and it failed with [e], then it behaves as [t2 e]. In other words, [tclOR] inserts a backtracking point. *) let tclOR = Proof.plus (** [tclORELSE t1 t2] is equal to [t1] if [t1] has at least one success or [t2 e] if [t1] fails with [e]. It is analogous to [try/with] handler of exception in that it is not a backtracking point. *) let tclORELSE t1 t2 = let open Logic_monad in let open Proof in split t1 >>= function | Nil e -> t2 e | Cons (a,t1') -> plus (return a) t1' (** [tclIFCATCH a s f] is a generalisation of {!tclORELSE}: if [a] succeeds at least once then it behaves as [tclBIND a s] otherwise, if [a] fails with [e], then it behaves as [f e]. *) let tclIFCATCH a s f = let open Logic_monad in let open Proof in split a >>= function | Nil e -> f e | Cons (x,a') -> plus (s x) (fun e -> (a' e) >>= fun x' -> (s x')) (** [tclONCE t] behave like [t] except it has at most one success: [tclONCE t] stops after the first success of [t]. If [t] fails with [e], [tclONCE t] also fails with [e]. *) let tclONCE = Proof.once exception MoreThanOneSuccess let _ = CErrors.register_handler begin function | MoreThanOneSuccess -> Some (Pp.str "This tactic has more than one success.") | _ -> None end (** [tclEXACTLY_ONCE e t] succeeds as [t] if [t] has exactly one success. Otherwise it fails. The tactic [t] is run until its first success, then a failure with exception [e] is simulated. It [t] yields another success, then [tclEXACTLY_ONCE e t] fails with [MoreThanOneSuccess] (it is a user error). Otherwise, [tclEXACTLY_ONCE e t] succeeds with the first success of [t]. Notice that the choice of [e] is relevant, as the presence of further successes may depend on [e] (see {!tclOR}). *) let tclEXACTLY_ONCE e t = let open Logic_monad in let open Proof in split t >>= function | Nil (e, info) -> tclZERO ~info e | Cons (x,k) -> let info = Exninfo.null in Proof.split (k (e, Exninfo.null)) >>= function | Nil _ -> tclUNIT x | _ -> tclZERO ~info MoreThanOneSuccess (** [tclCASE t] wraps the {!Proofview_monad.Logical.split} primitive. *) type 'a case = | Fail of Exninfo.iexn | Next of 'a * (Exninfo.iexn -> 'a tactic) let tclCASE t = let open Logic_monad in let map = function | Nil e -> Fail e | Cons (x, t) -> Next (x, t) in Proof.map map (Proof.split t) let tclBREAK = Proof.break (** {7 Focusing tactics} *) (** Represents a range selector as accepted by [tclFOCUSSELECTORLIST]. *) type goal_range_selector = | NthSelector of int | RangeSelector of (int * int) | IdSelector of Libnames.qualid exception NoSuchGoals of int exception CannotSelectShelvedAndFocused let _ = CErrors.register_handler begin function | NoSuchGoals n -> Some (str "No such " ++ str (String.plural n "goal") ++ str ".") | CannotSelectShelvedAndFocused -> Some (str "Cannot simultaneously select shelved and unshelved goals.") | _ -> None end (** [tclFOCUS ?nosuchgoal i j t] applies [t] in a context where only the goals numbered [i] to [j] are focused (the rest of the goals is restored at the end of the tactic). If the range [i]-[j] is not valid, then it [tclFOCUS_gen nosuchgoal i j t] is [nosuchgoal]. *) let tclFOCUS ?nosuchgoal i j t = let nosuchgoal ~info = Option.default (tclZERO ~info (NoSuchGoals (j+1-i))) nosuchgoal in let open Proof in Pv.get >>= fun initial -> try let (focused,context) = focus i j initial in Pv.set focused >> t >>= fun result -> Pv.modify (fun next -> unfocus context next) >> return result with CList.IndexOutOfRange as exn -> let _, info = Exninfo.capture exn in nosuchgoal ~info let tclTRYFOCUS i j t = tclFOCUS ~nosuchgoal:(tclUNIT ()) i j t (** Like {!tclFOCUS} but selects goals on the shelf, applies [t], and shelves generated subgoals. This method assumes that the list [evs] is a list of existing evars. *) let tclFOCUSSHELF ?(nosuchgoal=tclZERO (NoSuchGoals 1)) evs t = if CList.is_empty evs then nosuchgoal else let open Proof in Comb.get >>= fun initial_comb -> Comb.set (CList.map with_empty_state evs) >> t >>= fun result -> Comb.get >>= fun subgoals -> Comb.set initial_comb >> let subgoals = CList.filter_map (fun ev -> let ev = drop_state ev in (* If ev is still undefined, leave it on its original shelf *) if (CList.mem_f Evar.equal ev evs) then None else Some ev) subgoals in Pv.modify (fun pv -> { pv with solution = Evd.shelve pv.solution (undefined_evars pv.solution subgoals) }) >> return result let tclFOCUSLIST ?(nosuchgoal=tclZERO (NoSuchGoals 0)) l t = let open Proof in Comb.get >>= fun comb -> let n = CList.length comb in let ok (i, j) = 1 <= i && i <= j && j <= n in if not (CList.for_all ok l) then nosuchgoal else match l with | [] -> nosuchgoal | (mi, _) :: _ -> (* Get the left-most goal to focus. This goal won't move, and we will then place all the other goals to focus to the right. *) let mi = CList.fold_left (fun m (i, _) -> min m i) mi l in (* [CList.goto] returns a zipper, so that [(rev left) @ sub_right = comb]. *) let left, sub_right = CList.goto (mi-1) comb in let p x _ = CList.exists (fun (i, j) -> i <= x + mi && x + mi <= j) l in let sub, right = CList.partitioni p sub_right in let mj = mi - 1 + CList.length sub in Comb.set (CList.rev_append left (sub @ right)) >> tclFOCUS mi mj t let tclFOCUSSELECTORLIST ?(nosuchgoal=tclZERO (NoSuchGoals 0)) l t = let open Proof in Pv.get >>= fun initial -> try let (ranges, shelved_evars) = CList.partition_map (function | NthSelector n -> Left (n, n) | RangeSelector r -> Left r | IdSelector id -> match find_evar_in_pv id initial with | ev, Some n -> Left (n, n) (* goal is focused with index n *) | ev, None -> Right ev (* goal is shelved *)) l in match CList.is_empty ranges, CList.is_empty shelved_evars with | true, true -> nosuchgoal | true, false -> tclFOCUSSHELF ~nosuchgoal shelved_evars t | false, true -> tclFOCUSLIST ~nosuchgoal ranges t | false, false -> tclZERO CannotSelectShelvedAndFocused with Not_found -> nosuchgoal (** Like {!tclFOCUS} but selects a single goal by name. *) let tclFOCUSID ?(nosuchgoal=tclZERO (NoSuchGoals 1)) id t = let open Proof in Pv.get >>= fun initial -> try match find_evar_in_pv id initial with | ev, Some n -> (* Goal is under focus with index n *) let (focused,context) = focus n n initial in Pv.set focused >> t >>= fun result -> Pv.modify (fun next -> unfocus context next) >> return result | ev, None -> (* Goal is shelved. *) tclFOCUSSHELF ~nosuchgoal [ev] t with Not_found -> nosuchgoal (** {7 Dispatching on goals} *) exception SizeMismatch of int*int let _ = CErrors.register_handler begin function | SizeMismatch (i,j) -> let open Pp in Some ( str"Incorrect number of goals" ++ spc() ++ str"(expected "++int i++str(String.plural i " tactic") ++ str", was given "++ int j++str").") | _ -> None end (** A variant of [Monad.List.iter] where we iter over the focused list of goals. The argument tactic is executed in a focus comprising only of the current goal, a goal which has been solved by side effect is skipped. The generated subgoals are concatenated in order. *) let iter_goal i = let open Proof in Comb.get >>= fun initial -> Proof.List.fold_left begin fun (subgoals as cur) goal -> Solution.get >>= fun step -> match cleared_alias step goal with | None -> return cur | Some goal -> Comb.set [goal] >> i goal >> Proof.map (fun comb -> comb :: subgoals) Comb.get end [] initial >>= fun subgoals -> Solution.get >>= fun evd -> Comb.set CList.(undefined evd (flatten (rev subgoals))) (** List iter but allocates a list of results *) let map_goal i = let rev = List.rev in (* hem... Proof masks List... *) let open Proof in Comb.get >>= fun initial -> Proof.List.fold_left begin fun (acc, subgoals as cur) goal -> Solution.get >>= fun step -> match cleared_alias step goal with | None -> return cur | Some goal -> Comb.set [goal] >> i goal >>= fun res -> Proof.map (fun comb -> comb :: subgoals) Comb.get >>= fun x -> return (res :: acc, x) end ([],[]) initial >>= fun (results_rev, subgoals) -> Solution.get >>= fun evd -> Comb.set CList.(undefined evd (flatten (rev subgoals))) >> return (rev results_rev) (** A variant of [Monad.List.fold_left2] where the first list is the list of focused goals. The argument tactic is executed in a focus comprising only of the current goal, a goal which has been solved by side effect is skipped. The generated subgoals are concatenated in order. *) let fold_left2_goal i s l = let open Proof in Pv.get >>= fun initial -> let err = return () >>= fun () -> (* Delay the computation of list lengths. *) tclZERO (SizeMismatch (CList.length initial.comb,CList.length l)) in Proof.List.fold_left2 err begin fun ((r,subgoals) as cur) goal a -> Solution.get >>= fun step -> match cleared_alias step goal with | None -> return cur | Some goal -> Comb.set [goal] >> i goal a r >>= fun r -> Proof.map (fun comb -> (r, comb :: subgoals)) Comb.get end (s,[]) initial.comb l >>= fun (r,subgoals) -> Solution.get >>= fun evd -> Comb.set CList.(undefined evd (flatten (rev subgoals))) >> return r (** Dispatch tacticals are used to apply a different tactic to each goal under focus. They come in two flavours: [tclDISPATCH] takes a list of [unit tactic]-s and build a [unit tactic]. [tclDISPATCHL] takes a list of ['a tactic] and returns an ['a list tactic]. They both work by applying each of the tactic in a focus restricted to the corresponding goal (starting with the first goal). In the case of [tclDISPATCHL], the tactic returns a list of the same size as the argument list (of tactics), each element being the result of the tactic executed in the corresponding goal. When the length of the tactic list is not the number of goal, raises [SizeMismatch (g,t)] where [g] is the number of available goals, and [t] the number of tactics passed. [tclDISPATCHGEN join tacs] generalises both functions as the successive results of [tacs] are stored in reverse order in a list, and [join] is used to convert the result into the expected form. *) let tclDISPATCHGEN0 join tacs = match tacs with | [] -> begin let open Proof in Comb.get >>= function | [] -> tclUNIT (join []) | comb -> tclZERO (SizeMismatch (CList.length comb,0)) end | [tac] -> begin let open Proof in Pv.get >>= function | { comb=[goal] ; solution } -> begin match cleared_alias solution goal with | None -> tclUNIT (join []) | Some _ -> Proof.map (fun res -> join [res]) tac end | {comb} -> tclZERO (SizeMismatch(CList.length comb,1)) end | _ -> let iter _ t cur = Proof.map (fun y -> y :: cur) t in let ans = fold_left2_goal iter [] tacs in Proof.map join ans let tclDISPATCHGEN join tacs = let branch t = InfoL.tag (Info.DBranch) t in let tacs = CList.map branch tacs in InfoL.tag (Info.Dispatch) (tclDISPATCHGEN0 join tacs) let tclDISPATCH tacs = tclDISPATCHGEN ignore tacs let tclDISPATCHL tacs = tclDISPATCHGEN CList.rev tacs (** [extend_to_list startxs rx endxs l] builds a list [startxs @ [rx,...,rx] @ endxs] of the same length as [l]. Raises [SizeMismatch] if [startxs @ endxs] is already longer than [l]. *) let extend_to_list startxs rx endxs l = (* spiwack: I use [l] essentially as a natural number *) let rec duplicate acc = function | [] -> acc | _::rest -> duplicate (rx::acc) rest in let rec tail to_match rest = match rest, to_match with | [] , _::_ -> raise (SizeMismatch(0,0)) (* placeholder *) | _::rest , _::to_match -> tail to_match rest | _ , [] -> duplicate endxs rest in let rec copy pref rest = match rest,pref with | [] , _::_ -> raise (SizeMismatch(0,0)) (* placeholder *) | _::rest, a::pref -> a::(copy pref rest) | _ , [] -> tail endxs rest in copy startxs l (** [tclEXTEND b r e] is a variant of {!tclDISPATCH}, where the [r] tactic is "repeated" enough time such that every goal has a tactic assigned to it ([b] is the list of tactics applied to the first goals, [e] to the last goals, and [r] is applied to every goal in between). *) let tclEXTEND tacs1 rtac tacs2 = let open Proof in Comb.get >>= fun comb -> try let tacs = extend_to_list tacs1 rtac tacs2 comb in tclDISPATCH tacs with SizeMismatch _ -> tclZERO (SizeMismatch( CList.length comb, (CList.length tacs1)+(CList.length tacs2))) (* spiwack: failure occurs only when the number of goals is too small. Hence we can assume that [rtac] is replicated 0 times for any error message. *) (** [tclEXTEND [] tac []]. *) let tclINDEPENDENT tac = let open Proof in Pv.get >>= fun initial -> match initial.comb with | [] -> tclUNIT () | [_] -> tac | _ -> let tac = InfoL.tag (Info.DBranch) tac in InfoL.tag (Info.Dispatch) (iter_goal (fun _ -> tac)) let tclINDEPENDENTL tac = let open Proof in Pv.get >>= fun initial -> match initial.comb with | [] -> tclUNIT [] | [_] -> tac >>= fun x -> return [x] | _ -> let tac = InfoL.tag (Info.DBranch) tac in InfoL.tag (Info.Dispatch) (map_goal (fun _ -> tac)) (** {7 Goal manipulation} *) (** Shelves all the goals under focus. *) let shelve = let open Proof in Comb.get >>= fun initial -> Comb.set [] >> InfoL.leaf (Info.Tactic (fun () -> Pp.str"shelve")) >> let initial = CList.map drop_state initial in Pv.modify (fun pv -> { pv with solution = Evd.shelve pv.solution initial }) let shelve_goals l = let open Proof in Comb.get >>= fun initial -> let comb = CList.filter (fun g -> not (CList.mem (drop_state g) l)) initial in Comb.set comb >> InfoL.leaf (Info.Tactic (fun () -> Pp.str"shelve_goals")) >> Pv.modify (fun pv -> { pv with solution = Evd.shelve pv.solution l }) (** [depends_on sigma src tgt] checks whether the goal [src] appears as an existential variable in the definition of the goal [tgt] in [sigma]. *) let depends_on sigma src tgt = let evi = Evd.find_undefined sigma tgt in Evar.Set.mem src (Evd.evars_of_filtered_evar_info sigma (Evarutil.nf_evar_info sigma evi)) let unifiable_delayed g l = CList.exists (fun (tgt, lazy evs) -> not (Evar.equal g tgt) && Evar.Set.mem g evs) l let free_evars sigma l = let cache = Evarutil.create_undefined_evars_cache () in let map ev = (* Computes the set of evars appearing in the hypotheses, the conclusion or the body of the evar_info [evi]. Note: since we want to use it on goals, the body is actually supposed to be empty. *) let EvarInfo evi = Evd.find sigma ev in let fevs = lazy (Evarutil.filtered_undefined_evars_of_evar_info ~cache sigma evi) in (ev, fevs) in List.map map l let free_evars_with_state sigma l = let cache = Evarutil.create_undefined_evars_cache () in let map ev = (* Computes the set of evars appearing in the hypotheses, the conclusion or the body of the evar_info [evi]. Note: since we want to use it on goals, the body is actually supposed to be empty. *) let ev = drop_state ev in let EvarInfo evi = Evd.find sigma ev in let fevs = lazy (Evarutil.filtered_undefined_evars_of_evar_info ~cache sigma evi) in (ev, fevs) in List.map map l (** [unifiable sigma g l] checks whether [g] appears in another subgoal of [l]. The list [l] may contain [g], but it does not affect the result. *) let unifiable_delayed_with_state sigma g l = let g = drop_state g in unifiable_delayed g l let unifiable sigma g l = let l = free_evars sigma l in unifiable_delayed g l (** [partition_unifiable sigma l] partitions [l] into a pair [(u,n)] where [u] is composed of the unifiable goals, i.e. the goals on whose definition other goals of [l] depend, and [n] are the non-unifiable goals. *) let partition_unifiable sigma l = let fevs = free_evars_with_state sigma l in CList.partition (fun g -> unifiable_delayed_with_state sigma g fevs) l (** Shelves the unifiable goals under focus, i.e. the goals which appear in other goals under focus (the unfocused goals are not considered). *) let shelve_unifiable_informative = let open Proof in Pv.get >>= fun initial -> let (u,n) = partition_unifiable initial.solution initial.comb in Comb.set n >> InfoL.leaf (Info.Tactic (fun () -> Pp.str"shelve_unifiable")) >> let u = CList.map drop_state u in Pv.modify (fun pv -> { pv with solution = Evd.shelve pv.solution u }) >> tclUNIT u let shelve_unifiable = let open Proof in shelve_unifiable_informative >>= fun _ -> tclUNIT () (** [guard_no_unifiable] returns the list of unifiable goals if some goals are unifiable (see {!shelve_unifiable}) in the current focus. *) let guard_no_unifiable = let open Proof in Pv.get >>= fun initial -> let (u,n) = partition_unifiable initial.solution initial.comb in match u with | [] -> tclUNIT None | gls -> let l = CList.map (fun g -> Evd.dependent_evar_ident (drop_state g) initial.solution) gls in let l = CList.map (fun id -> Names.Name id) l in tclUNIT (Some l) (** [unshelve l p] moves all the goals in [l] from the shelf and put them at the end of the focused goals of p, if they are still undefined after [advance] *) let unshelve l p = let solution = Evd.unshelve p.solution l in let l = List.map with_empty_state l in (* advance the goals in case of clear *) let l = undefined p.solution l in { comb = p.comb@l; solution } let filter_shelf f pv = { pv with solution = Evd.filter_shelf f pv.solution } let mark_in_evm ~goal evd evars = let evd = if goal then let mark evd content = let EvarInfo info = Evd.find evd content in let source = match Evd.evar_source info with (* Two kinds for goal evars: - GoalEvar (morally not dependent) - VarInstance (morally dependent of some name). This is a heuristic for naming these evars. *) | loc, (Evar_kinds.QuestionMark { Evar_kinds.qm_name=Names.Name id} | Evar_kinds.ImplicitArg (_,(_,id),_)) -> loc, Evar_kinds.VarInstance id | _, (Evar_kinds.VarInstance _ | Evar_kinds.GoalEvar) as x -> x | loc,_ -> loc,Evar_kinds.GoalEvar in Evd.update_source evd content source in CList.fold_left mark evd evars else evd in let tcs = Evd.get_typeclass_evars evd in let evset = Evar.Set.of_list evars in Evd.set_typeclass_evars evd (Evar.Set.diff tcs evset) let with_shelf tac = let open Proof in Pv.get >>= fun pv -> let { solution } = pv in Pv.set { pv with solution = Evd.push_shelf @@ Evd.push_future_goals solution } >> tac >>= fun ans -> Pv.get >>= fun npv -> let { solution = sigma } = npv in let gls, sigma = Evd.pop_shelf sigma in (* The pending future goals are necessarily coming from legacy tactics *) (* and thus considered as to shelve, as in Proof.run_tactic *) (* TODO: is it still relevant since the removal of the compat layer? *) let fgl, sigma = Evd.pop_future_goals sigma in (* Ensure we mark and return only unsolved goals *) let gls' = CList.rev_append (Evd.FutureGoals.comb fgl) gls in let gls' = undefined_evars sigma gls' in let sigma = mark_in_evm ~goal:false sigma gls' in let npv = { npv with solution = sigma } in Pv.set npv >> tclUNIT (gls', ans) (** [goodmod p m] computes the representative of [p] modulo [m] in the interval [[0,m-1]].*) let goodmod p m = if m = 0 then 0 else let p' = p mod m in (* if [n] is negative [n mod l] is negative of absolute value less than [l], so [(n mod l)+l] is the representative of [n] in the interval [[0,l-1]].*) if p' < 0 then p'+m else p' let cycle n = let open Proof in InfoL.leaf (Info.Tactic (fun () -> Pp.(str"cycle "++int n))) >> Comb.modify begin fun initial -> let l = CList.length initial in let n' = goodmod n l in let (front,rear) = CList.chop n' initial in rear@front end let swap i j = let open Proof in InfoL.leaf (Info.Tactic (fun () -> Pp.(hov 2 (str"swap"++spc()++int i++spc()++int j)))) >> Comb.modify begin fun initial -> let l = CList.length initial in let i = if i>0 then i-1 else i and j = if j>0 then j-1 else j in let i = goodmod i l and j = goodmod j l in CList.map_i begin fun k x -> match k with | k when Int.equal k i -> CList.nth initial j | k when Int.equal k j -> CList.nth initial i | _ -> x end 0 initial end let revgoals = let open Proof in InfoL.leaf (Info.Tactic (fun () -> Pp.str"revgoals")) >> Comb.modify CList.rev let numgoals = let open Proof in Comb.get >>= fun comb -> return (CList.length comb) (** {7 Access primitives} *) let tclEVARMAP = Solution.get let tclENV = Env.get (** {7 Put-like primitives} *) let mark_as_unsafe = Status.put false (** Gives up on the goal under focus. Reports an unsafe status. Proofs with given up goals cannot be closed. *) let give_up evs pv = let solution = List.fold_left (fun sigma ev -> Evd.give_up (drop_state ev) sigma) pv.solution evs in { pv with solution } let give_up = let open Proof in Comb.get >>= fun initial -> Comb.set [] >> mark_as_unsafe >> InfoL.leaf (Info.Tactic (fun () -> Pp.str"give_up")) >> Pv.modify (give_up initial) (** {7 Control primitives} *) module Progress = struct let eq_constr evd extended_evd = Evarutil.eq_constr_univs_test ~evd ~extended_evd (** equality function on hypothesis contexts *) let eq_named_context_val sigma1 sigma2 ctx1 ctx2 = let r_eq _ _ = true (* ignore relevances *) in let c1 = EConstr.named_context_of_val ctx1 and c2 = EConstr.named_context_of_val ctx2 in let eq_named_declaration d1 d2 = match d1, d2 with | LocalAssum (i1,t1), LocalAssum (i2,t2) -> Context.eq_annot Names.Id.equal r_eq i1 i2 && eq_constr sigma1 sigma2 t1 t2 | LocalDef (i1,c1,t1), LocalDef (i2,c2,t2) -> Context.eq_annot Names.Id.equal r_eq i1 i2 && eq_constr sigma1 sigma2 c1 c2 && eq_constr sigma1 sigma2 t1 t2 | _ -> false in (* NB: can't use List.equal because it shortcuts on physical equality *) List.for_all2eq eq_named_declaration c1 c2 let eq_evar_body (type a1 a2) sigma1 sigma2 (b1 : a1 Evd.evar_body) (b2 : a2 Evd.evar_body) = let open Evd in match b1, b2 with | Evar_empty, Evar_empty -> true | Evar_defined t1, Evar_defined t2 -> eq_constr sigma1 sigma2 t1 t2 | _ -> false let eq_evar_concl (type a1 a2) sigma1 sigma2 (e1 : a1 Evd.evar_info) (e2 : a2 Evd.evar_info) = let open Evd in match Evd.evar_body e1, Evd.evar_body e2 with | Evar_empty, Evar_empty -> eq_constr sigma1 sigma2 (Evd.evar_concl e1) (Evd.evar_concl e2) | Evar_defined _, Evar_defined _ -> true | _ -> false let eq_evar_info sigma1 sigma2 ei1 ei2 = eq_evar_concl sigma1 sigma2 ei1 ei2 && eq_named_context_val sigma1 sigma2 (Evd.evar_hyps ei1) (Evd.evar_hyps ei2) && eq_evar_body sigma1 sigma2 (Evd.evar_body ei1) (Evd.evar_body ei2) let fast_eq_evar_body (type a1 a2) (e1 : a1 Evd.evar_info) (e2 : a2 Evd.evar_info) = let open Evd in match Evd.evar_body e1, Evd.evar_body e2 with | Evar_empty, Evar_empty -> true | Evar_defined _, Evar_defined _ -> true | _ -> false let fast_eq_named_context_val ctx1 ctx2 = let r_eq _ _ = true (* ignore relevances *) in let c1 = EConstr.named_context_of_val ctx1 in let c2 = EConstr.named_context_of_val ctx2 in let eq_named_declaration d1 d2 = match d1, d2 with | LocalAssum (i1, _), LocalAssum (i2, _) -> Context.eq_annot Names.Id.equal r_eq i1 i2 | LocalDef (i1, _, _), LocalDef (i2, _, _) -> Context.eq_annot Names.Id.equal r_eq i1 i2 | _ -> false in List.for_all2eq eq_named_declaration c1 c2 let fast_eq_evar_info ei1 ei2 = fast_eq_evar_body ei1 ei2 && fast_eq_named_context_val (Evd.evar_hyps ei1) (Evd.evar_hyps ei2) (** Equality function on goals *) let goal_equal ~evd ~extended_evd evar extended_evar = let EvarInfo evi = Evd.find evd evar in let EvarInfo extended_evi = Evd.find extended_evd extended_evar in if fast_eq_evar_info evi extended_evi then eq_evar_info evd extended_evd evi extended_evi else false end let tclPROGRESS t = let open Proof in Pv.get >>= fun initial -> t >>= fun res -> Pv.get >>= fun final -> (* [*_test] test absence of progress. [quick_test] is approximate whereas [exhaustive_test] is complete. *) let quick_test = initial.solution == final.solution && initial.comb == final.comb in let test = quick_test || (CList.same_length initial.comb final.comb && Util.List.for_all2eq begin fun i f -> Progress.goal_equal ~evd:initial.solution ~extended_evd:final.solution (drop_state i) (drop_state f) end initial.comb final.comb) in if not test then tclUNIT res else let info = Exninfo.reify () in tclZERO ~info (CErrors.UserError Pp.(str "Failed to progress.")) let () = CErrors.register_handler begin function | Logic_monad.Tac_Timeout -> Some (Pp.str "Tactic timeout!") | _ -> None end let tclTIMEOUTF n t = let open Proof in (* spiwack: as one of the monad is a continuation passing monad, it doesn't force the computation to be threaded inside the underlying (IO) monad. Hence I force it myself by asking for the evaluation of a dummy value first, lest [timeout] be called when everything has already been computed. *) let t = Proof.lift (Logic_monad.NonLogical.return ()) >> t in Proof.get >>= fun initial -> Proof.current >>= fun envvar -> Proof.lift begin let open Logic_monad.NonLogical in timeout n (Proof.repr (Proof.run t envvar initial)) >>= fun r -> match r with | Error info -> return (Util.Inr (Logic_monad.Tac_Timeout, info)) | Ok (Logic_monad.Nil e) -> return (Util.Inr e) | Ok (Logic_monad.Cons (r, _)) -> return (Util.Inl r) end >>= function | Util.Inl (res,s,m,i) -> Proof.set s >> Proof.put m >> Proof.update (fun _ -> i) >> return res | Util.Inr (e, info) -> tclZERO ~info e let tclTIMEOUT n t = tclTIMEOUTF (float_of_int n) t let tclTIME s t = let pr_time t1 t2 n msg = let msg = if n = 0 then str msg else str (msg ^ " after ") ++ int n ++ str (String.plural n " backtracking") in Feedback.msg_info(str "Tactic call" ++ pr_opt str s ++ str " ran for " ++ System.fmt_time_difference t1 t2 ++ str " " ++ surround msg) in let rec aux n t = let open Proof in tclUNIT () >>= fun () -> let tstart = System.get_time() in Proof.split t >>= let open Logic_monad in function | Nil (e, info) -> begin let tend = System.get_time() in pr_time tstart tend n "failure"; tclZERO ~info e end | Cons (x,k) -> let tend = System.get_time() in pr_time tstart tend n "success"; tclOR (tclUNIT x) (fun e -> aux (n+1) (k e)) in aux 0 t let tclProofInfo = let open Proof in Logical.current >>= fun P.{name; poly} -> tclUNIT (name, poly) (** {7 Unsafe primitives} *) module Unsafe = struct let (>>=) = tclBIND let tclEVARS evd = Pv.modify (fun ps -> { ps with solution = evd }) let tclNEWGOALS ?(before = false) gls = Pv.modify begin fun step -> let gls = undefined step.solution gls in let comb = if before then gls @ step.comb else step.comb @ gls in { step with comb } end let tclNEWSHELVED gls = Pv.modify begin fun step -> let gls = undefined_evars step.solution gls in { step with solution = Evd.shelve step.solution gls } end let tclGETSHELF = tclEVARMAP >>= fun sigma -> tclUNIT @@ Evd.shelf sigma let tclSETENV = Env.set let tclGETGOALS = Comb.get let tclSETGOALS = Comb.set let tclEVARSADVANCE evd = Pv.modify (fun ps -> { solution = evd; comb = undefined evd ps.comb }) let tclEVARUNIVCONTEXT ctx = Pv.modify (fun ps -> { ps with solution = Evd.set_universe_context ps.solution ctx }) let push_future_goals p = { p with solution = Evd.push_future_goals p.solution } let mark_as_goals evd content = mark_in_evm ~goal:true evd content let advance = Evarutil.advance let undefined = undefined let mark_unresolvables evm evs = mark_in_evm ~goal:false evm evs let mark_as_unresolvables p evs = { p with solution = mark_in_evm ~goal:false p.solution evs } let update_sigma_univs ugraph pv = { pv with solution = Evd.update_sigma_univs ugraph pv.solution } let purge_side_effects pv = let effs = Evd.eval_side_effects pv.solution in { pv with solution = Evd.set_side_effects Evd.empty_side_effects pv.solution }, effs end module UnsafeRepr = Proof.Unsafe let (>>=) = tclBIND (** {6 Goal-dependent tactics} *) let catchable_exception = function | Logic_monad.Exception _ -> false | e -> CErrors.noncritical e module Goal = struct type t = { env : Environ.env; sigma : Evd.evar_map; concl : EConstr.constr ; state : StateStore.t; self : Evar.t ; (* for compatibility with old-style definitions *) } let state { state=state } = state let env {env} = env let sigma {sigma} = sigma let hyps {env} = EConstr.named_context env let concl {concl} = concl let relevance {sigma; self} = Evd.evar_relevance (Evd.find_undefined sigma self) let gmake_with info env sigma goal state = { env = Environ.reset_with_named_context (Evd.evar_filtered_hyps info) env ; sigma = sigma ; concl = Evd.evar_concl info; state = state ; self = goal } let gmake env sigma goal = let state = get_state goal in let goal = drop_state goal in let info = Evd.find_undefined sigma goal in gmake_with info env sigma goal state let enter f = let f gl = InfoL.tag (Info.DBranch) (f gl) in InfoL.tag (Info.Dispatch) begin iter_goal begin fun goal -> Env.get >>= fun env -> tclEVARMAP >>= fun sigma -> try f (gmake env sigma goal) with e when catchable_exception e -> let (e, info) = Exninfo.capture e in tclZERO ~info e end end let enter_one ?(__LOC__=__LOC__) f = let open Proof in Comb.get >>= function | [goal] -> begin Env.get >>= fun env -> tclEVARMAP >>= fun sigma -> try f (gmake env sigma goal) with e when catchable_exception e -> let (e, info) = Exninfo.capture e in tclZERO ~info e end | _ -> CErrors.anomaly Pp.(str __LOC__ ++ str " enter_one") let goals = Pv.get >>= fun step -> let sigma = step.solution in let map goal = match cleared_alias sigma goal with | None -> None (* ppedrot: Is this check really necessary? *) | Some goal -> let oinfo = Evd.find_undefined sigma (drop_state goal) in let gl = Env.get >>= fun env -> tclEVARMAP >>= fun sigma -> let state = get_state goal in let goal = drop_state goal in let EvarInfo info = Evd.find sigma goal in let goal = { env = Environ.reset_with_named_context (Evd.evar_filtered_hyps info) env ; sigma = sigma ; concl = Evd.evar_concl oinfo; state = state; self = goal; } in tclUNIT goal in Some gl in tclUNIT (CList.map_filter map step.comb) let unsolved { self=self } = tclEVARMAP >>= fun sigma -> tclUNIT (not (Option.is_empty (Evarutil.advance sigma self))) (* compatibility *) let goal { self=self } = self end (** {6 Trace} *) module Trace = struct let record_info_trace = InfoL.record_trace let log m = InfoL.leaf (Info.Msg m) let name_tactic m t = InfoL.tag (Info.Tactic m) t let pr_info env sigma ?(lvl=0) info = assert (lvl >= 0); Info.(print env sigma (collapse lvl info)) end (** {6 Non-logical state} *) module NonLogical = Logic_monad.NonLogical let tclLIFT = Proof.lift let tclCHECKINTERRUPT = tclLIFT (NonLogical.make Control.check_for_interrupt) let wrap_exceptions f = try f () with e when catchable_exception e -> let (e, info) = Exninfo.capture e in tclZERO ~info e (** {7 Notations} *) module Notations = struct let (>>=) = tclBIND let (<*>) = tclTHEN let (<+>) t1 t2 = tclOR t1 (fun _ -> t2) end rocq-9.2.0/engine/proofview.mli000066400000000000000000000627531516144147600165040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Evar.t list * Evd.evar_map (** {6 Starting and querying a proof view} *) (** Abstract representation of the initial goals of a proof. *) type entry (** Optimize memory consumption *) val compact : entry -> proofview -> entry * proofview (** Initialises a proofview, the main argument is a list of environments (including a [named_context] which are used as hypotheses) pair with conclusion types, creating accordingly many initial goals. Because a proof does not necessarily starts in an empty [evar_map] (indeed a proof can be triggered by an incomplete pretyping), [init] takes an additional argument to represent the initial [evar_map]. *) val init : Evd.evar_map -> (Environ.env * types) list -> entry * proofview (** A [telescope] is a list of environment and conclusion like in {!init}, except that each element may depend on the previous goals. The telescope passes the goals in the form of a [Term.constr] which represents the goal as an [evar]. The [evar_map] is threaded in state passing style. *) type telescope = | TNil of Evd.evar_map | TCons of Environ.env * Evd.evar_map * types * (Evd.evar_map -> constr -> telescope) (** Like {!init}, but goals are allowed to be dependent on one another. Dependencies between goals is represented with the type [telescope] instead of [list]. Note that the first [evar_map] of the telescope plays the role of the [evar_map] argument in [init]. *) val dependent_init : telescope -> entry * proofview (** [finished pv] is [true] if and only if [pv] is complete. That is, if it has an empty list of focused goals. There could still be unsolved subgoals, but they would then be out of focus. *) val finished : proofview -> bool (** Returns the current [evar] state. *) val return : proofview -> Evd.evar_map val partial_proof : entry -> proofview -> constr list val initial_goals : entry -> (Environ.named_context_val * constr * types) list (** goal <-> goal_with_state *) val with_empty_state : Proofview_monad.goal -> Proofview_monad.goal_with_state val drop_state : Proofview_monad.goal_with_state -> Proofview_monad.goal val goal_with_state : Proofview_monad.goal -> Proofview_monad.StateStore.t -> Proofview_monad.goal_with_state (** {6 Focusing commands} *) (** A [focus_context] represents the part of the proof view which has been removed by a focusing action, it can be used to unfocus later on. *) type focus_context (** Returns a stylised view of a focus_context for use by, for instance, ide-s. *) (* spiwack: the type of [focus_context] will change as we push more refined functions to ide-s. This would be better than spawning a new nearly identical function every time. Hence the generic name. *) (* In this version: the goals in the context, as a "zipper" (the first list is in reversed order). *) val focus_context : Evd.evar_map -> focus_context -> Evar.t list * Evar.t list (** [focus i j] focuses a proofview on the goals from index [i] to index [j] (inclusive, goals are indexed from [1]). I.e. goals number [i] to [j] become the only focused goals of the returned proofview. It returns the focused proofview, and a context for the focus stack. *) val focus : int -> int -> proofview -> proofview * focus_context (** Unfocuses a proofview with respect to a context. *) val unfocus : focus_context -> proofview -> proofview (** {6 The tactic monad} *) (** - Tactics are objects which apply a transformation to all the subgoals of the current view at the same time. By opposition to the old vision of applying it to a single goal. It allows tactics such as [shelve_unifiable], tactics to reorder the focused goals, or global automation tactic for dependent subgoals (instantiating an evar has influences on the other goals of the proof in progress, not being able to take that into account causes the current eauto tactic to fail on some instances where it could succeed). Another benefit is that it is possible to write tactics that can be executed even if there are no focused goals. - Tactics form a monad ['a tactic], in a sense a tactic can be seen as a function (without argument) which returns a value of type 'a and modifies the environment (in our case: the view). Tactics of course have arguments, but these are given at the meta-level as OCaml functions. Most tactics in the sense we are used to return [()], that is no really interesting values. But some might pass information around. The tactics seen in Rocq's Ltac are (for now at least) only [unit tactic], the return values are kept for the OCaml toolkit. The operation or the monad are [Proofview.tclUNIT] (which is the "return" of the tactic monad) [Proofview.tclBIND] (which is the "bind") and [Proofview.tclTHEN] (which is a specialized bind on unit-returning tactics). - Tactics have support for full-backtracking. Tactics can be seen having multiple success: if after returning the first success a failure is encountered, the tactic can backtrack and use a second success if available. The state is backtracked to its previous value, except the non-logical state defined in the {!NonLogical} module below. *) (** The abstract type of tactics *) type +'a tactic (** Applies a tactic to the current proofview. Returns a tuple [a,pv,(b,sh,gu)] where [a] is the return value of the tactic, [pv] is the updated proofview, [b] a boolean which is [true] if the tactic has not done any action considered unsafe (such as admitting a lemma), [sh] is the list of goals which have been shelved by the tactic, and [gu] the list of goals on which the tactic has given up. In case of multiple success the first one is selected. If there is no success, fails with {!Logic_monad.TacticFailure}*) val apply : name:Names.Id.t -> poly:PolyFlags.t -> Environ.env -> 'a tactic -> proofview -> 'a * proofview * Environ.env * bool * Proofview_monad.Info.tree (** {7 Monadic primitives} *) (** Unit of the tactic monad. *) val tclUNIT : 'a -> 'a tactic (** Bind operation of the tactic monad. *) val tclBIND : 'a tactic -> ('a -> 'b tactic) -> 'b tactic (** Interprets the ";" (semicolon) of Ltac. As a monadic operation, it's a specialized "bind". *) val tclTHEN : unit tactic -> 'a tactic -> 'a tactic (** [tclIGNORE t] has the same operational content as [t], but drops the returned value. *) val tclIGNORE : 'a tactic -> unit tactic (** Generic monadic combinators for tactics. *) module Monad : Monad.S with type +'a t = 'a tactic (** {7 Failure and backtracking} *) (** [tclZERO e] fails with exception [e]. It has no success. Exception is supposed to be non critical *) val tclZERO : ?info:Exninfo.info -> exn -> 'a tactic (** [tclOR t1 t2] behaves like [t1] as long as [t1] succeeds. Whenever the successes of [t1] have been depleted and it failed with [e], then it behaves as [t2 e]. In other words, [tclOR] inserts a backtracking point. In [t2], exception can be assumed non critical. *) val tclOR : 'a tactic -> (Exninfo.iexn -> 'a tactic) -> 'a tactic (** [tclORELSE t1 t2] is equal to [t1] if [t1] has at least one success or [t2 e] if [t1] fails with [e]. It is analogous to [try/with] handler of exception in that it is not a backtracking point. In [t2], exception can be assumed non critical. *) val tclORELSE : 'a tactic -> (Exninfo.iexn -> 'a tactic) -> 'a tactic (** [tclIFCATCH a s f] is a generalisation of {!tclORELSE}: if [a] succeeds at least once then it behaves as [tclBIND a s] otherwise, if [a] fails with [e], then it behaves as [f e]. In [f] exception can be assumed non critical. *) val tclIFCATCH : 'a tactic -> ('a -> 'b tactic) -> (Exninfo.iexn -> 'b tactic) -> 'b tactic (** [tclONCE t] behave like [t] except it has at most one success: [tclONCE t] stops after the first success of [t]. If [t] fails with [e], [tclONCE t] also fails with [e]. *) val tclONCE : 'a tactic -> 'a tactic (** [tclEXACTLY_ONCE e t] succeeds as [t] if [t] has exactly one success. Otherwise it fails. The tactic [t] is run until its first success, then a failure with exception [e] is simulated ([e] has to be non critical). If [t] yields another success, then [tclEXACTLY_ONCE e t] fails with [MoreThanOneSuccess] (it is a user error). Otherwise, [tclEXACTLY_ONCE e t] succeeds with the first success of [t]. Notice that the choice of [e] is relevant, as the presence of further successes may depend on [e] (see {!tclOR}). *) exception MoreThanOneSuccess val tclEXACTLY_ONCE : exn -> 'a tactic -> 'a tactic (** [tclCASE t] splits [t] into its first success and a continuation. It is the most general primitive to control backtracking. *) type 'a case = | Fail of Exninfo.iexn | Next of 'a * (Exninfo.iexn -> 'a tactic) val tclCASE : 'a tactic -> 'a case tactic (** [tclBREAK p t] is a generalization of [tclONCE t]. Instead of stopping after the first success, it succeeds like [t] until a failure with an exception [e] such that [p e = Some e'] is raised. At which point it drops the remaining successes, failing with [e']. [tclONCE t] is equivalent to [tclBREAK (fun e -> Some e) t]. *) val tclBREAK : (Exninfo.iexn -> Exninfo.iexn option) -> 'a tactic -> 'a tactic (** {7 Focusing tactics} *) (** Represents a range selector as accepted by [tclFOCUSSELECTORLIST]. *) type goal_range_selector = | NthSelector of int | RangeSelector of (int * int) | IdSelector of Libnames.qualid exception NoSuchGoals of int exception CannotSelectShelvedAndFocused (** [tclFOCUS i j t] applies [t] after focusing on the goals number [i] to [j] (see {!focus}). The rest of the goals is restored after the tactic action. If the specified range doesn't correspond to existing goals, fails with the [nosuchgoal] argument, by default raising [NoSuchGoals] (a user error). This exception is caught at toplevel with a default message. *) val tclFOCUS : ?nosuchgoal:'a tactic -> int -> int -> 'a tactic -> 'a tactic (** [tclFOCUSLIST li t] applies [t] on the list of focused goals described by [li]. Each element of [li] is a pair [(i, j)] denoting the goals numbered from [i] to [j] (inclusive, starting from 1). It will try to apply [t] to all the valid goals in any of these intervals. If the set of such goals is not a single range, then it will move goals such that it is a single range. (So, for instance, [[1, 3-5]; idtac.] is not the identity.) If the set of such goals is empty, it will fail with [nosuchgoal], by default raising [NoSuchGoals 0]. *) val tclFOCUSLIST : ?nosuchgoal:'a tactic -> (int * int) list -> 'a tactic -> 'a tactic (** [tclFOCUSSELECTORLIST l t] applies [t] on the list of goal selectors described by [l]. Each element of [l] is either a range selector [RangeSelector (i, j)] denoting the focused goals numbered from [i] to [j] (inclusive, starting from 1), or a named selector [IdSelector id] targetting a goal which may or may not be shelved. All selected goals must be in focus, or all selected goals must be shelved. If that is not the case, this method will fail with [CannotSelectShelvedAndFocused]. This restriction is due to the fact that tactics applied to shelved goals must shelve their subgoals, and it is currently hard to keep track of subgoals. If all selected goals are in focus, then [tclFOCUSLIST] is called by converting each goal selector to a range. If all selected goals are shelved, then [tclFOCUSSHELF] is called. *) val tclFOCUSSELECTORLIST : ?nosuchgoal:'a tactic -> goal_range_selector list -> 'a tactic -> 'a tactic (** [tclFOCUSID x t] applies [t] on a (single) focused goal like {!tclFOCUS}. The goal is found by its name rather than its number. Fails with [nosuchgoal], by default raising [NoSuchGoals 1]. *) val tclFOCUSID : ?nosuchgoal:'a tactic -> Libnames.qualid -> 'a tactic -> 'a tactic (** [tclTRYFOCUS i j t] behaves like {!tclFOCUS}, except that if the specified range doesn't correspond to existing goals, behaves like [tclUNIT ()] instead of failing. *) val tclTRYFOCUS : int -> int -> unit tactic -> unit tactic (** {7 Dispatching on goals} *) (** Dispatch tacticals are used to apply a different tactic to each goal under focus. They come in two flavours: [tclDISPATCH] takes a list of [unit tactic]-s and build a [unit tactic]. [tclDISPATCHL] takes a list of ['a tactic] and returns an ['a list tactic]. They both work by applying each of the tactic in a focus restricted to the corresponding goal (starting with the first goal). In the case of [tclDISPATCHL], the tactic returns a list of the same size as the argument list (of tactics), each element being the result of the tactic executed in the corresponding goal. When the length of the tactic list is not the number of goal, raises [SizeMismatch (g,t)] where [g] is the number of available goals, and [t] the number of tactics passed. *) exception SizeMismatch of int*int val tclDISPATCH : unit tactic list -> unit tactic val tclDISPATCHL : 'a tactic list -> 'a list tactic (** [tclEXTEND b r e] is a variant of {!tclDISPATCH}, where the [r] tactic is "repeated" enough time such that every goal has a tactic assigned to it ([b] is the list of tactics applied to the first goals, [e] to the last goals, and [r] is applied to every goal in between). *) val tclEXTEND : unit tactic list -> unit tactic -> unit tactic list -> unit tactic (** [tclINDEPENDENT tac] runs [tac] on each goal successively, from the first one to the last one. Backtracking in one goal is independent of backtracking in another. It is equivalent to [tclEXTEND [] tac []]. *) val tclINDEPENDENT : unit tactic -> unit tactic val tclINDEPENDENTL: 'a tactic -> 'a list tactic (** {7 Goal manipulation} *) (** Shelves all the goals under focus. The goals are placed on the shelf for later use (or being solved by side-effects). *) val shelve : unit tactic (** Shelves the given list of goals, which might include some that are under focus and some that aren't. All the goals are placed on the shelf for later use (or being solved by side-effects). *) val shelve_goals : Evar.t list -> unit tactic (** [unifiable sigma g l] checks whether [g] appears in another subgoal of [l]. The list [l] may contain [g], but it does not affect the result. Used by [shelve_unifiable]. *) val unifiable : Evd.evar_map -> Evar.t -> Evar.t list -> bool (** Shelves the unifiable goals under focus, i.e. the goals which appear in other goals under focus (the unfocused goals are not considered). *) val shelve_unifiable : unit tactic (** [guard_no_unifiable] returns the list of unifiable goals if some goals are unifiable (see {!shelve_unifiable}) in the current focus. *) val guard_no_unifiable : Names.Name.t list option tactic (** [unshelve l p] moves all the goals in [l] from the shelf and put them at the end of the focused goals of p, if they are still undefined after [advance] *) val unshelve : Evar.t list -> proofview -> proofview val filter_shelf : (Evar.t -> bool) -> proofview -> proofview (** [depends_on g1 g2 sigma] checks if g1 occurs in the type/ctx of g2 *) val depends_on : Evd.evar_map -> Evar.t -> Evar.t -> bool (** [with_shelf tac] executes [tac] and returns its result together with the set of goals shelved by [tac]. The current shelf is unchanged and the returned list contains only unsolved goals. *) val with_shelf : 'a tactic -> (Evar.t list * 'a) tactic (** If [n] is positive, [cycle n] puts the [n] first goals last. If [n] is negative, then it puts the [n] last goals first.*) val cycle : int -> unit tactic (** [swap i j] swaps the position of goals number [i] and [j] (negative numbers can be used to address goals from the end. Goals are indexed from [1]. For simplicity index [0] corresponds to goal [1] as well, rather than raising an error. *) val swap : int -> int -> unit tactic (** [revgoals] reverses the list of focused goals. *) val revgoals : unit tactic (** [numgoals] returns the number of goals under focus. *) val numgoals : int tactic (** {7 Access primitives} *) (** [tclEVARMAP] doesn't affect the proof, it returns the current [evar_map]. *) val tclEVARMAP : Evd.evar_map tactic (** [tclENV] doesn't affect the proof, it returns the current environment. It is not the environment of a particular goal, rather the "global" environment of the proof. The goal-wise environment is obtained via {!Proofview.Goal.env}. *) val tclENV : Environ.env tactic (** {7 Put-like primitives} *) (** [mark_as_unsafe] declares the current tactic is unsafe. *) val mark_as_unsafe : unit tactic (** Gives up on the goal under focus. Reports an unsafe status. Proofs with given up goals cannot be closed. *) val give_up : unit tactic (** {7 Control primitives} *) (** [tclPROGRESS t] checks the state of the proof after [t]. It it is identical to the state before, then [tclPROGRESS t] fails, otherwise it succeeds like [t]. *) val tclPROGRESS : 'a tactic -> 'a tactic module Progress : sig (** [goal_equal ~evd ~extended_evd evar extended_evar] tests whether the [evar_info] from [evd] corresponding to [evar] is equal to that from [extended_evd] corresponding to [extended_evar], up to existential variable instantiation and equalisable universes. The universe constraints in [extended_evd] are assumed to be an extension of the universe constraints in [evd]. *) val goal_equal : evd:Evd.evar_map -> extended_evd:Evd.evar_map -> Evar.t -> Evar.t -> bool end (** Checks for interrupts *) val tclCHECKINTERRUPT : unit tactic (** [tclTIMEOUT n t] can have only one success. In case of timeout it fails with [tclZERO Tac_Timeout]. *) val tclTIMEOUTF : float -> 'a tactic -> 'a tactic val tclTIMEOUT : int -> 'a tactic -> 'a tactic (** [tclTIME s t] displays time for each atomic call to t, using s as an identifying annotation if present *) val tclTIME : string option -> 'a tactic -> 'a tactic (** Internal, don't use. *) val tclProofInfo : (Names.Id.t * PolyFlags.t) tactic [@@ocaml.deprecated "(8.10) internal, don't use"] (** {7 Unsafe primitives} *) (** The primitives in the [Unsafe] module should be avoided as much as possible, since they can make the proof state inconsistent. They are nevertheless helpful, in particular when interfacing the pretyping and the proof engine. *) module Unsafe : sig (** [tclEVARS sigma] replaces the current [evar_map] by [sigma]. If [sigma] has new unresolved [evar]-s they will not appear as goal. If goals have been solved in [sigma] they will still appear as unsolved goals. *) val tclEVARS : Evd.evar_map -> unit tactic (** Like {!tclEVARS} but also checks whether goals have been solved. *) val tclEVARSADVANCE : Evd.evar_map -> unit tactic (** Set the global environment of the tactic *) val tclSETENV : Environ.env -> unit tactic (** [tclNEWGOALS ~before gls] adds the goals [gls] to the ones currently being proved. If [before] is true, it prepends them to the list of focused goals, otherwise it appends them (default). If a goal is already solved, it is not added. *) val tclNEWGOALS : ?before:bool -> Proofview_monad.goal_with_state list -> unit tactic (** [tclNEWSHELVED gls] adds the goals [gls] to the shelf. If a goal is already solved, it is not added. *) val tclNEWSHELVED : Evar.t list -> unit tactic (** [tclSETGOALS gls] sets goals [gls] as the goals being under focus. If a goal is already solved, it is not set. *) val tclSETGOALS : Proofview_monad.goal_with_state list -> unit tactic (** [tclGETGOALS] returns the list of goals under focus. *) val tclGETGOALS : Proofview_monad.goal_with_state list tactic (** [tclGETSHELF] returns the list of goals on the shelf. *) val tclGETSHELF : Evar.t list tactic (** Sets the evar universe context. *) val tclEVARUNIVCONTEXT : UState.t -> unit tactic (** Clears the future goals store in the proof view. *) val push_future_goals : proofview -> proofview (** Give the evars the status of a goal (changes their source location and makes them unresolvable for type classes. *) val mark_as_goals : Evd.evar_map -> Evar.t list -> Evd.evar_map (** Make some evars unresolvable for type classes. We need two functions as some functions use the proofview and others directly manipulate the undelying evar_map. *) val mark_unresolvables : Evd.evar_map -> Evar.t list -> Evd.evar_map val mark_as_unresolvables : proofview -> Evar.t list -> proofview (** [advance sigma g] returns [Some g'] if [g'] is undefined and is the current avatar of [g] (for instance [g] was changed by [clear] into [g']). It returns [None] if [g] has been (partially) solved. *) val advance : Evd.evar_map -> Evar.t -> Evar.t option (** [undefined sigma l] applies [advance] to the goals of [l], then returns the subset of resulting goals which have not yet been defined *) val undefined : Evd.evar_map -> Proofview_monad.goal_with_state list -> Proofview_monad.goal_with_state list (** [update_sigma_univs] lifts [UState.update_sigma_univs] to the proofview *) val update_sigma_univs : UGraph.t -> proofview -> proofview val purge_side_effects : proofview -> proofview * Evd.side_effects end (** This module gives access to the innards of the monad. Its use is restricted to very specific cases. *) module UnsafeRepr : sig type state = Proofview_monad.Logical.Unsafe.state val repr : 'a tactic -> ('a, state, state, Exninfo.iexn) Logic_monad.BackState.t val make : ('a, state, state, Exninfo.iexn) Logic_monad.BackState.t -> 'a tactic end (** {6 Goal-dependent tactics} *) module Goal : sig (** Type of goals. *) type t (** [concl], [hyps], [env] and [sigma] given a goal [gl] return respectively the conclusion of [gl], the hypotheses of [gl], the environment of [gl] (i.e. the global environment and the hypotheses) and the current evar map. *) val concl : t -> constr val relevance : t -> ERelevance.t val hyps : t -> named_context val env : t -> Environ.env val sigma : t -> Evd.evar_map val state : t -> Proofview_monad.StateStore.t (** [enter t] applies the goal-dependent tactic [t] in each goal independently, in the manner of {!tclINDEPENDENT} except that the current goal is also given as an argument to [t]. *) val enter : (t -> unit tactic) -> unit tactic (** Like {!enter}, but assumes exactly one goal under focus, raising a fatal error otherwise. *) val enter_one : ?__LOC__:string -> (t -> 'a tactic) -> 'a tactic (** Recover the list of current goals under focus, without evar-normalization. FIXME: encapsulate the level in an existential type. *) val goals : t tactic list tactic (** [unsolved g] is [true] if [g] is still unsolved in the current proof state. *) val unsolved : t -> bool tactic (** Compatibility: avoid if possible *) val goal : t -> Evar.t end (** {6 Trace} *) module Trace : sig (** [record_info_trace t] behaves like [t] except the [info] trace is stored. *) val record_info_trace : 'a tactic -> 'a tactic val log : Proofview_monad.lazy_msg -> unit tactic val name_tactic : Proofview_monad.lazy_msg -> 'a tactic -> 'a tactic val pr_info : Environ.env -> Evd.evar_map -> ?lvl:int -> Proofview_monad.Info.tree -> Pp.t end (** {6 Non-logical state} *) (** The [NonLogical] module allows the execution of effects (including I/O) in tactics (non-logical side-effects are not discarded at failures). *) module NonLogical : module type of Logic_monad.NonLogical (** [tclLIFT c] is a tactic which behaves exactly as [c]. *) val tclLIFT : 'a NonLogical.t -> 'a tactic (* transforms every Ocaml (catchable) exception into a failure in the monad. *) val wrap_exceptions : (unit -> 'a tactic) -> 'a tactic (** {7 Notations} *) module Notations : sig (** {!tclBIND} *) val (>>=) : 'a tactic -> ('a -> 'b tactic) -> 'b tactic (** {!tclTHEN} *) val (<*>) : unit tactic -> 'a tactic -> 'a tactic (** {!tclOR}: [t1+t2] = [tclOR t1 (fun _ -> t2)]. *) val (<+>) : 'a tactic -> 'a tactic -> 'a tactic end rocq-9.2.0/engine/proofview_monad.ml000066400000000000000000000206221516144147600174760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* { head = a::head ; opened=[] } | a::Seq(b,f)::opened -> { head ; opened=Seq(b,a::f)::opened } | [] -> assert false let leaf a s = close (opn a s) (** Returning a forest. It is the responsibility of the library builder to close all the tags. *) (* spiwack: I may want to close the tags instead, to deal with interruptions. *) let rec mirror f = List.rev_map mirror_tree f and mirror_tree (Seq(a,f)) = Seq(a,mirror f) let to_tree = function | { head ; opened=[] } -> mirror head | { head ; opened=_::_} -> assert false end (** {6 State types} *) (** We typically label nodes of [Trace.tree] with messages to print. But we don't want to compute the result. *) type lazy_msg = unit -> Pp.t (** Info trace. *) module Info = struct (** The type of the tags for [info]. *) type tag = | Msg of lazy_msg (** A simple message *) | Tactic of lazy_msg (** A tactic call *) | Dispatch (** A call to [tclDISPATCH]/[tclEXTEND] *) | DBranch (** A special marker to delimit individual branch of a dispatch. *) type state = tag Trace.incr type tree = tag Trace.forest let pr_in_comments m = Pp.(str"(* "++ m () ++str" *)") let unbranch = function | Trace.Seq (DBranch,brs) -> brs | _ -> assert false let is_empty_branch = let open Trace in function | Seq(DBranch,[]) -> true | _ -> false (** Dispatch with empty branches are (supposed to be) equivalent to [idtac] which need not appear, so they are removed from the trace. *) let dispatch brs = let open Trace in if CList.for_all is_empty_branch brs then None else Some (Seq(Dispatch,brs)) let constr = let open Trace in function | Dispatch -> dispatch | t -> fun br -> Some (Seq(t,br)) let rec compress_tree = let open Trace in function | Seq(t,f) -> constr t (compress f) and compress f = CList.map_filter compress_tree f (** [with_sep] is [true] when [Tactic m] must be printed with a trailing semi-colon. *) let rec pr_tree with_sep = let open Trace in function | Seq (Msg m,[]) -> pr_in_comments m | Seq (Tactic m,_) -> let tail = if with_sep then Pp.str";" else Pp.mt () in Pp.(m () ++ tail) | Seq (Dispatch,brs) -> let tail = if with_sep then Pp.str";" else Pp.mt () in Pp.(pr_dispatch brs++tail) | Seq (Msg _,_::_) | Seq (DBranch,_) -> assert false and pr_dispatch brs = let open Pp in let brs = List.map unbranch brs in match brs with | [br] -> pr_forest br | _ -> let sep () = spc()++str"|"++spc() in let branches = prlist_with_sep sep pr_forest brs in str"[>"++spc()++branches++spc()++str"]" and pr_forest = function | [] -> Pp.mt () | [tr] -> pr_tree false tr | tr::l -> Pp.(pr_tree true tr ++ pr_forest l) let print _env _sigma f = pr_forest (compress f) let rec collapse_tree n t = let open Trace in match n , t with | 0 , t -> [t] | _ , (Seq(Tactic _,[]) as t) -> [t] | n , Seq(Tactic _,f) -> collapse (pred n) f | n , Seq(Dispatch,brs) -> [Seq(Dispatch, (collapse n brs))] | n , Seq(DBranch,br) -> [Seq(DBranch, (collapse n br))] | _ , (Seq(Msg _,_) as t) -> [t] and collapse n f = CList.map_append (collapse_tree n) f end module StateStore = Store.Make() (* let (set_state, get_state) = StateDyn.Easy.make_dyn "goal_state" *) type goal = Evar.t type goal_with_state = Evar.t * StateStore.t let drop_state = fst let get_state = snd let goal_with_state g s = (g, s) let with_empty_state g = (g, StateStore.empty) let map_goal_with_state f (g, s) = (f g, s) (** Type of proof views: current [evar_map] together with the list of focused goals. *) type proofview = { solution : Evd.evar_map; comb : goal_with_state list; } (** {6 Instantiation of the logic monad} *) (** Parameters of the logic monads *) module P = struct type s = proofview * Environ.env (** Recording info trace (true) or not. *) type e = { trace: bool; name : Names.Id.t; poly : PolyFlags.t } (** Status (safe/unsafe) * shelved goals * given up *) type w = bool let wunit = true let wprod b1 b2 = b1 && b2 type u = Info.state let uunit = Trace.empty_incr end module Logical = Logic_monad.Logical(P) (** {6 Lenses to access to components of the states} *) module type State = sig type t val get : t Logical.t val set : t -> unit Logical.t val modify : (t->t) -> unit Logical.t end module type Reader = sig type t val get : t Logical.t end module type Writer = sig type t val put : t -> unit Logical.t end module Pv : State with type t := proofview = struct let get = Logical.(map fst get) let set p = Logical.modify (fun (_,e) -> (p,e)) let modify f= Logical.modify (fun (p,e) -> (f p,e)) end module Solution : State with type t := Evd.evar_map = struct let get = Logical.map (fun {solution} -> solution) Pv.get let set s = Pv.modify (fun pv -> { pv with solution = s }) let modify f = Pv.modify (fun pv -> { pv with solution = f pv.solution }) end module Comb : State with type t = goal_with_state list = struct (* spiwack: I don't know why I cannot substitute ([:=]) [t] with a type expression. *) type t = goal_with_state list let get = Logical.map (fun {comb} -> comb) Pv.get let set c = Pv.modify (fun pv -> { pv with comb = c }) let modify f = Pv.modify (fun pv -> { pv with comb = f pv.comb }) end module Env : State with type t := Environ.env = struct let get = Logical.(map snd get) let set e = Logical.modify (fun (p,_) -> (p,e)) let modify f = Logical.modify (fun (p,e) -> (p,f e)) end module Status : Writer with type t := bool = struct let put s = Logical.put s end (** Lens and utilities pertaining to the info trace *) module InfoL = struct let recording = Logical.(map (fun {P.trace} -> trace) current) let if_recording t = let open Logical in recording >>= fun r -> if r then t else return () let record_trace t = Logical.( current >>= fun s -> local {s with P.trace = true} t) let raw_update = Logical.update let update f = if_recording (raw_update f) let opn a = update (Trace.opn a) let close = update Trace.close let leaf a = update (Trace.leaf a) let tag a t = let open Logical in recording >>= fun r -> if r then begin raw_update (Trace.opn a) >> t >>= fun a -> raw_update Trace.close >> return a end else t end rocq-9.2.0/engine/proofview_monad.mli000066400000000000000000000114611516144147600176500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a forest (** [open a] opens a tag with name [a]. *) val opn : 'a -> 'a incr -> 'a incr (** [close] closes the last open tag. It is the responsibility of the user to close all the tags. *) val close : 'a incr -> 'a incr (** [leaf] creates an empty tag with name [a]. *) val leaf : 'a -> 'a incr -> 'a incr end (** {6 State types} *) (** We typically label nodes of [Trace.tree] with messages to print. But we don't want to compute the result. *) type lazy_msg = unit -> Pp.t (** Info trace. *) module Info : sig (** The type of the tags for [info]. *) type tag = | Msg of lazy_msg (** A simple message *) | Tactic of lazy_msg (** A tactic call *) | Dispatch (** A call to [tclDISPATCH]/[tclEXTEND] *) | DBranch (** A special marker to delimit individual branch of a dispatch. *) type state = tag Trace.incr type tree = tag Trace.forest val print : Environ.env -> Evd.evar_map -> tree -> Pp.t (** [collapse n t] flattens the first [n] levels of [Tactic] in an info trace, effectively forgetting about the [n] top level of names (if there are fewer, the last name is kept). *) val collapse : int -> tree -> tree end module StateStore : Store.S type goal = Evar.t type goal_with_state val drop_state : goal_with_state -> goal val get_state : goal_with_state -> StateStore.t val goal_with_state : goal -> StateStore.t -> goal_with_state val with_empty_state : goal -> goal_with_state val map_goal_with_state : (goal -> goal) -> goal_with_state -> goal_with_state (** Type of proof views: current [evar_map] together with the list of focused goals, locally shelved goals and globally shelved goals. *) type proofview = { solution : Evd.evar_map; comb : goal_with_state list; } (** {6 Instantiation of the logic monad} *) module P : sig type s = proofview * Environ.env (** Status (safe/unsafe) * given up *) type w = bool val wunit : w val wprod : w -> w -> w (** Recording info trace (true) or not. *) type e = { trace: bool; name : Names.Id.t; poly : PolyFlags.t } type u = Info.state val uunit : u end module Logical : module type of Logic_monad.Logical(P) (** {6 Lenses to access to components of the states} *) module type State = sig type t val get : t Logical.t val set : t -> unit Logical.t val modify : (t->t) -> unit Logical.t end module type Reader = sig type t val get : t Logical.t end module type Writer = sig type t val put : t -> unit Logical.t end (** Lens to the [proofview]. *) module Pv : State with type t := proofview (** Lens to the [evar_map] of the proofview. *) module Solution : State with type t := Evd.evar_map (** Lens to the list of focused goals. *) module Comb : State with type t = goal_with_state list (** Lens to the global environment. *) module Env : State with type t := Environ.env (** Lens to the tactic status ([true] if safe, [false] if unsafe) *) module Status : Writer with type t := bool (** Lens and utilities pertaining to the info trace *) module InfoL : sig (** [record_trace t] behaves like [t] and compute its [info] trace. *) val record_trace : 'a Logical.t -> 'a Logical.t val update : (Info.state -> Info.state) -> unit Logical.t val opn : Info.tag -> unit Logical.t val close : unit Logical.t val leaf : Info.tag -> unit Logical.t (** [tag a t] opens tag [a] runs [t] then closes the tag. *) val tag : Info.tag -> 'a Logical.t -> 'a Logical.t end rocq-9.2.0/engine/termops.ml000066400000000000000000001335741516144147600160040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* mt () | LocalDef (_,c,_) -> (* Force evaluation *) let c = EConstr.of_constr c in let pb = print_constr_env env sigma c in (str" := " ++ pb ++ cut () ) in let pt = print_constr_env env sigma (EConstr.of_constr (get_type decl)) in let ptyp = (str" : " ++ pt) in (Id.print (get_id decl) ++ hov 0 (pbody ++ ptyp)) let pr_rel_decl env sigma decl = let open RelDecl in let pbody = match decl with | LocalAssum _ -> mt () | LocalDef (_,c,_) -> (* Force evaluation *) let c = EConstr.of_constr c in let pb = print_constr_env env sigma c in (str":=" ++ spc () ++ pb ++ spc ()) in let ptyp = print_constr_env env sigma (EConstr.of_constr (get_type decl)) in match get_name decl with | Anonymous -> hov 0 (str"<>" ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp) | Name id -> hov 0 (Id.print id ++ spc () ++ pbody ++ str":" ++ spc () ++ ptyp) let print_named_context env sigma = hv 0 (fold_named_context (fun env d pps -> pps ++ ws 2 ++ pr_var_decl env sigma d) env ~init:(mt ())) let print_rel_context env sigma = hv 0 (fold_rel_context (fun env d pps -> pps ++ ws 2 ++ pr_rel_decl env sigma d) env ~init:(mt ())) let print_env env sigma = let sign_env = fold_named_context (fun env d pps -> let pidt = pr_var_decl env sigma d in (pps ++ fnl () ++ pidt)) env ~init:(mt ()) in let db_env = fold_rel_context (fun env d pps -> let pnat = pr_rel_decl env sigma d in (pps ++ fnl () ++ pnat)) env ~init:(mt ()) in (sign_env ++ db_env) let protect f x = try f x with e when (* maybe should be just "not is_interrupted"? *) CErrors.noncritical e || !Flags.in_debugger -> str "EXCEPTION: " ++ str (Printexc.to_string e) let print_kconstr env sigma a = protect (fun c -> print_constr_env env sigma c) a end let vars_of_env env = let s = Environ.ids_of_named_context_val (Environ.named_context_val env) in Context.Rel.fold_outside (fun decl s -> match RelDecl.get_name decl with Name id -> Id.Set.add id s | _ -> s) (rel_context env) ~init:s let pr_global_env env g = Nametab.pr_global_env (vars_of_env env) g let evar_suggested_name env sigma evk = let open Evd in let base_id evk' evi = match evar_ident evk' sigma with | Some id -> Libnames.basename id | None -> match Evd.evar_source evi with | _,Evar_kinds.ImplicitArg (c,(n,id),b) -> id | _,Evar_kinds.VarInstance id -> id | _,Evar_kinds.QuestionMark {Evar_kinds.qm_name = Name id} -> id | _,Evar_kinds.GoalEvar -> Id.of_string "Goal" | _ -> let env = reset_with_named_context (Evd.evar_hyps evi) env in Namegen.id_of_name_using_hdchar env sigma (Evd.evar_concl evi) Anonymous in let names = Evar.Map.mapi base_id (undefined_map sigma) in let id = Evar.Map.find evk names in let fold evk' id' (seen, n) = if seen then (seen, n) else if Evar.equal evk evk' then (true, n) else if Id.equal id id' then (seen, succ n) else (seen, n) in let (_, n) = Evar.Map.fold fold names (false, 0) in if n = 0 then id else Nameops.add_suffix id (string_of_int (pred n)) let pr_existential_key env sigma evk = let open Evd in match evar_ident evk sigma with | None -> str "?" ++ Id.print (evar_suggested_name env sigma evk) | Some id -> str "?" ++ Libnames.pr_path id let pr_decl env sigma (decl,ok) = let open NamedDecl in let print_constr = Internal.print_kconstr in match decl with | LocalAssum ({binder_name=id},_) -> if ok then Id.print id else (str "{" ++ Id.print id ++ str "}") | LocalDef ({binder_name=id},c,_) -> str (if ok then "(" else "{") ++ Id.print id ++ str ":=" ++ print_constr env sigma c ++ str (if ok then ")" else "}") let pr_evar_source env sigma = function | Evar_kinds.NamedHole id -> Id.print id | Evar_kinds.QuestionMark _ -> str "underscore" | Evar_kinds.CasesType false -> str "pattern-matching return predicate" | Evar_kinds.CasesType true -> str "subterm of pattern-matching return predicate" | Evar_kinds.BinderType (Name id) -> str "type of " ++ Id.print id | Evar_kinds.BinderType Anonymous -> str "type of anonymous binder" | Evar_kinds.EvarType (ido,evk) -> let pp = match ido with | Some id -> str "?" ++ Id.print id | None -> try pr_existential_key env sigma evk with (* defined *) Not_found -> str "an internal placeholder" in str "type of " ++ pp | Evar_kinds.ImplicitArg (c,(n,id),b) -> str "parameter " ++ Id.print id ++ spc () ++ str "of" ++ spc () ++ pr_global_env env c | Evar_kinds.InternalHole -> str "internal placeholder" | Evar_kinds.TomatchTypeParameter (ind,n) -> pr_nth n ++ str " argument of type " ++ pr_global_env env (IndRef ind) | Evar_kinds.GoalEvar -> str "goal evar" | Evar_kinds.ImpossibleCase -> str "type of impossible pattern-matching clause" | Evar_kinds.MatchingVar _ -> str "matching variable" | Evar_kinds.VarInstance id -> str "instance of " ++ Id.print id | Evar_kinds.SubEvar (where,evk) -> (match where with | None -> str "subterm of " | Some Evar_kinds.Body -> str "body of " | Some Evar_kinds.Domain -> str "domain of " | Some Evar_kinds.Codomain -> str "codomain of ") ++ Evar.print evk | Evar_kinds.RewriteRulePattern Anonymous -> str "anonymous pattern variable" | Evar_kinds.RewriteRulePattern Name id -> str "pattern variable " ++ Id.print id let pr_evar_info (type a) env sigma (evi : a Evd.evar_info) = let open Evd in let print_constr = Internal.print_kconstr in let phyps = try let decls = match Filter.repr (evar_filter evi) with | None -> List.map (fun c -> (c, true)) (evar_context evi) | Some filter -> List.combine (evar_context evi) filter in prlist_with_sep spc (pr_decl env sigma) (List.rev decls) with Invalid_argument _ -> str "Ill-formed filtered context" in let pb = match Evd.evar_body evi with | Evar_empty -> print_constr env sigma (Evd.evar_concl evi) | Evar_defined c -> str"=> " ++ print_constr env sigma c in let candidates = match Evd.evar_body evi with | Evar_empty -> begin match evar_candidates evi with | None -> mt () | Some l -> spc () ++ str "{" ++ prlist_with_sep (fun () -> str "|") (print_constr env sigma) l ++ str "}" end | _ -> mt () in let src = str "(" ++ pr_evar_source env sigma (snd (Evd.evar_source evi)) ++ str ")" in hov 2 (str"[" ++ phyps ++ spc () ++ str"|-" ++ spc() ++ pb ++ str"]" ++ candidates ++ spc() ++ src) let compute_evar_dependency_graph sigma = let open Evd in (* Compute the map binding ev to the evars whose body depends on ev *) let fold evk (EvarInfo evi) acc = let fold_ev evk' acc = let tab = try Evar.Map.find evk' acc with Not_found -> Evar.Set.empty in Evar.Map.add evk' (Evar.Set.add evk tab) acc in match evar_body evi with | Evar_empty -> acc | Evar_defined c -> Evar.Set.fold fold_ev (evars_of_term sigma c) acc in Evd.fold fold sigma Evar.Map.empty let evar_dependency_closure n sigma = let open Evd in (* Create the DAG of depth [n] representing the recursive dependencies of undefined evars. *) let graph = compute_evar_dependency_graph sigma in let rec aux n curr accu = if Int.equal n 0 then Evar.Set.union curr accu else let fold evk accu = try let deps = Evar.Map.find evk graph in Evar.Set.union deps accu with Not_found -> accu in (* Consider only the newly added evars *) let ncurr = Evar.Set.fold fold curr Evar.Set.empty in (* Merge the others *) let accu = Evar.Set.union curr accu in aux (n - 1) ncurr accu in let undef = Evar.Map.domain (undefined_map sigma) in aux n undef Evar.Set.empty let evar_dependency_closure n sigma = let open Evd in let deps = evar_dependency_closure n sigma in let map = Evar.Map.bind (fun ev -> find sigma ev) deps in Evar.Map.bindings map let has_no_evar sigma = try let () = Evd.fold (fun _ _ () -> raise_notrace Exit) sigma () in true with Exit -> false let pr_evd_level sigma = UState.pr_uctx_level (Evd.ustate sigma) let pr_evd_qvar sigma = UState.pr_uctx_qvar (Evd.ustate sigma) let reference_of_level sigma l = UState.qualid_of_level (Evd.ustate sigma) l let pr_evar_universe_context = UState.pr let print_env_short env sigma = let print_constr = Internal.print_kconstr in let pr_rel_decl = function | RelDecl.LocalAssum (n,_) -> Name.print n.binder_name | RelDecl.LocalDef (n,b,_) -> str "(" ++ Name.print n.binder_name ++ str " := " ++ print_constr env sigma (EConstr.of_constr b) ++ str ")" in let pr_named_decl = NamedDecl.to_rel_decl %> pr_rel_decl in let nc = List.rev (named_context env) in let rc = List.rev (rel_context env) in str "[" ++ pr_sequence pr_named_decl nc ++ str "]" ++ spc () ++ str "[" ++ pr_sequence pr_rel_decl rc ++ str "]" let pr_evar_constraints sigma pbs = let pr_evconstr (pbty, env, t1, t2) = let env = (* We currently allow evar instances to refer to anonymous de Bruijn indices, so we protect the error printing code in this case by giving names to every de Bruijn variable in the rel_context of the conversion problem. MS: we should rather stop depending on anonymous variables, they can be used to indicate independency. Also, this depends on a strategy for naming/renaming. *) Namegen.make_all_name_different env sigma in hov 2 (hov 2 (print_env_short env sigma) ++ spc () ++ str "|-" ++ spc () ++ Internal.print_kconstr env sigma t1 ++ spc () ++ str (match pbty with | Conversion.CONV -> "==" | Conversion.CUMUL -> "<=") ++ spc () ++ Internal.print_kconstr env sigma t2) in prlist_with_sep fnl pr_evconstr pbs let pr_evar_map_gen with_univs pr_evars env sigma = let uvs = Evd.ustate sigma in let (_, conv_pbs) = Evd.extract_all_conv_pbs sigma in let evs = if has_no_evar sigma then mt () else pr_evars sigma ++ fnl () and svs = if with_univs then UState.pr uvs else mt () and cstrs = if List.is_empty conv_pbs then mt () else str "CONSTRAINTS:" ++ brk (0, 1) ++ pr_evar_constraints sigma conv_pbs ++ fnl () and typeclasses = let evars = Evd.get_typeclass_evars sigma in if Evar.Set.is_empty evars then mt () else str "TYPECLASSES:" ++ brk (0, 1) ++ prlist_with_sep spc Evar.print (Evar.Set.elements evars) ++ fnl () and obligations = let evars = Evd.get_obligation_evars sigma in if Evar.Set.is_empty evars then mt () else str "OBLIGATIONS:" ++ brk (0, 1) ++ prlist_with_sep spc Evar.print (Evar.Set.elements evars) ++ fnl () and shelf = str "SHELF:" ++ brk (0, 1) ++ Evd.pr_shelf sigma ++ fnl () and future_goals = str "FUTURE GOALS STACK:" ++ brk (0, 1) ++ Evd.pr_future_goals_stack sigma ++ fnl () in evs ++ svs ++ cstrs ++ typeclasses ++ obligations ++ shelf ++ future_goals let pr_evar_list env sigma l = let open Evd in let pr_alias ev = match is_aliased_evar sigma ev with | None -> mt () | Some ev' -> str " (aliased to " ++ Evar.print ev' ++ str ")" in let pr (ev, EvarInfo evi) = h (Evar.print ev ++ str "==" ++ pr_evar_info env sigma evi ++ pr_alias ev ++ begin match Evd.evar_body evi with | Evar_empty -> str " {" ++ pr_existential_key env sigma ev ++ str "}" | Evar_defined _ -> mt () end) in hv 0 (prlist_with_sep fnl pr l) let to_list d = let open Evd in (* Workaround for change in Map.fold behavior in ocaml 3.08.4 *) let l = ref [] in let fold_def evk (EvarInfo evi) () = match Evd.evar_body evi with | Evar_defined _ -> l := (evk, EvarInfo evi) :: !l | Evar_empty -> () in let fold_undef evk (EvarInfo evi) () = match Evd.evar_body evi with | Evar_empty -> l := (evk, EvarInfo evi) :: !l | Evar_defined _ -> () in Evd.fold fold_def d (); Evd.fold fold_undef d (); !l let pr_evar_by_depth depth env sigma = match depth with | None -> (* Print all evars *) str"EVARS:" ++ brk(0,1) ++ pr_evar_list env sigma (to_list sigma) ++ fnl() | Some n -> (* Print closure of undefined evars *) str"UNDEFINED EVARS:"++ (if Int.equal n 0 then mt() else str" (+level "++int n++str" closure):")++ brk(0,1)++ pr_evar_list env sigma (evar_dependency_closure n sigma) ++ fnl() let pr_evar_by_filter filter env sigma = let open Evd in let elts = Evd.fold (fun evk evi accu -> (evk, evi) :: accu) sigma [] in let elts = List.rev elts in let is_def (_, EvarInfo evi) = match Evd.evar_body evi with | Evar_defined _ -> true | Evar_empty -> false in let (defined, undefined) = List.partition is_def elts in let filter (evk, evi) = filter evk evi in let defined = List.filter filter defined in let undefined = List.filter filter undefined in let prdef = if List.is_empty defined then mt () else str "DEFINED EVARS:" ++ brk (0, 1) ++ pr_evar_list env sigma defined in let prundef = if List.is_empty undefined then mt () else str "UNDEFINED EVARS:" ++ brk (0, 1) ++ pr_evar_list env sigma undefined in prdef ++ prundef let pr_evar_map ?(with_univs=true) depth env sigma = pr_evar_map_gen with_univs (fun sigma -> pr_evar_by_depth depth env sigma) env sigma let pr_evar_map_filter ?(with_univs=true) filter env sigma = pr_evar_map_gen with_univs (fun sigma -> pr_evar_by_filter filter env sigma) env sigma (* [Rel (n+m);...;Rel(n+1)] *) let rel_vect n m = Array.init m (fun i -> mkRel(n+m-i)) let rel_list n m = let open EConstr in let rec reln l p = if p>m then l else reln (mkRel(n+p)::l) (p+1) in reln [] 1 let push_rel_assum (x,t) env = let open RelDecl in let open EConstr in push_rel (LocalAssum (x,t)) env let push_rels_assum assums = let open RelDecl in push_rel_context (List.map (fun (x,t) -> LocalAssum (x,t)) assums) let push_named_rec_types (lna,typarray,_) env = let open NamedDecl in let ctxt = Array.map2_i (fun i na t -> let id = map_annot (function | Name id -> id | Anonymous -> anomaly (Pp.str "Fix declarations must be named.")) na in LocalAssum (id, lift i t)) lna typarray in Array.fold_left (fun e assum -> push_named assum e) env ctxt let lookup_rel_id id sign = let open RelDecl in let rec lookrec n = function | [] -> raise Not_found | decl :: l -> if Names.Name.equal (Name id) (get_name decl) then (n, get_value decl, get_type decl) else lookrec (n+1) l in lookrec 1 sign (* On Constr *) let it_named_context_quantifier f ~init = List.fold_left (fun c d -> f d c) init let it_mkNamedProd_wo_LetIn init = it_named_context_quantifier mkNamedProd_wo_LetIn ~init let it_mkLambda_or_LetIn_from_no_LetIn c decls = let open RelDecl in let rec aux k decls c = match decls with | [] -> c | LocalDef (na,b,t) :: decls -> mkLetIn (na,b,t,aux (k-1) decls (liftn 1 k c)) | LocalAssum (na,t) :: decls -> mkLambda (na,t,aux (k-1) decls c) in aux (List.length decls) (List.rev decls) c (* strips head casts and flattens head applications *) let rec strip_head_cast sigma c = match EConstr.kind sigma c with | App (f,cl) -> let rec collapse_rec f cl2 = match EConstr.kind sigma f with | App (g,cl1) -> collapse_rec g (Array.append cl1 cl2) | Cast (c,_,_) -> collapse_rec c cl2 | _ -> if Int.equal (Array.length cl2) 0 then f else EConstr.mkApp (f,cl2) in collapse_rec f cl | Cast (c,_,_) -> strip_head_cast sigma c | _ -> c let rec drop_extra_implicit_args sigma c = match EConstr.kind sigma c with (* Removed trailing extra implicit arguments, what improves compatibility for constants with recently added maximal implicit arguments *) | App (f,args) when EConstr.isEvar sigma (Array.last args) -> let open EConstr in drop_extra_implicit_args sigma (mkApp (f,fst (Array.chop (Array.length args - 1) args))) | _ -> c let last_arg sigma c = match EConstr.kind sigma c with | App (f,cl) -> Array.last cl | _ -> anomaly (Pp.str "last_arg.") let adjust_app_list_size f1 l1 f2 l2 = let open EConstr in let len1 = List.length l1 and len2 = List.length l2 in if Int.equal len1 len2 then (f1,l1,f2,l2) else if len1 < len2 then let extras,restl2 = List.chop (len2-len1) l2 in (f1, l1, applist (f2,extras), restl2) else let extras,restl1 = List.chop (len1-len2) l1 in (applist (f1,extras), restl1, f2, l2) let adjust_app_array_size f1 l1 f2 l2 = let open EConstr in let len1 = Array.length l1 and len2 = Array.length l2 in if Int.equal len1 len2 then (f1,l1,f2,l2) else if len1 < len2 then let extras,restl2 = Array.chop (len2-len1) l2 in (f1, l1, mkApp (f2,extras), restl2) else let extras,restl1 = Array.chop (len1-len2) l1 in (mkApp (f1,extras), restl1, f2, l2) (* [map_constr_with_binders_left_to_right g f n c] maps [f n] on the immediate subterms of [c]; it carries an extra data [n] (typically a lift index) which is processed by [g] (which typically add 1 to [n]) at each binder traversal; the subterms are processed from left to right according to the usual representation of the constructions (this may matter if [f] does a side-effect); it is not recursive; in fact, the usual representation of the constructions is at the time being almost those of the ML representation (except for (co-)fixpoint) *) let fold_rec_types g (lna,typarray,_) e = let open EConstr in let open Vars in let ctxt = Array.map2_i (fun i na t -> RelDecl.LocalAssum (na, lift i t)) lna typarray in Array.fold_left (fun e assum -> g assum e) e ctxt let map_left2 f a g b = let l = Array.length a in if Int.equal l 0 then [||], [||] else begin let r = Array.make l (f a.(0)) in let s = Array.make l (g b.(0)) in for i = 1 to l - 1 do r.(i) <- f a.(i); s.(i) <- g b.(i) done; r, s end let map_constr_with_binders_left_to_right env sigma g f l c = let open RelDecl in let open EConstr in match EConstr.kind sigma c with | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _) -> c | Cast (b,k,t) -> let b' = f l b in let t' = f l t in if b' == b && t' == t then c else mkCast (b',k,t') | Prod (na,t,b) -> let t' = f l t in let b' = f (g (LocalAssum (na,t)) l) b in if t' == t && b' == b then c else mkProd (na, t', b') | Lambda (na,t,b) -> let t' = f l t in let b' = f (g (LocalAssum (na,t)) l) b in if t' == t && b' == b then c else mkLambda (na, t', b') | LetIn (na,bo,t,b) -> let bo' = f l bo in let t' = f l t in let b' = f (g (LocalDef (na,bo,t)) l) b in if bo' == bo && t' == t && b' == b then c else mkLetIn (na, bo', t', b') | App (c,[||]) -> assert false | App (t,al) -> (*Special treatment to be able to recognize partially applied subterms*) let a = al.(Array.length al - 1) in let app = (mkApp (t, Array.sub al 0 (Array.length al - 1))) in let app' = f l app in let a' = f l a in if app' == app && a' == a then c else mkApp (app', [| a' |]) | Proj (p,r,b) -> let b' = f l b in if b' == b then c else mkProj (p, r, b') | Evar ev -> let ev' = EConstr.map_existential sigma (fun c -> f l c) ev in if ev' == ev then c else mkEvar ev' | Case (ci,u,pms,(p,r),iv,b,bl) -> let (ci, _, pms, (p0,_), _, b, bl0) = annotate_case env sigma (ci, u, pms, (p,r), iv, b, bl) in let f_ctx (nas, _ as r) (ctx, c) = let c' = f (List.fold_right g ctx l) c in if c' == c then r else (nas, c') in (* In v8 concrete syntax, predicate is after the term to match! *) let b' = f l b in let pms' = Array.map_left (f l) pms in let p' = f_ctx p p0 in let iv' = map_invert (f l) iv in let bl' = Array.map_left (fun (c, c0) -> f_ctx c c0) (Array.map2 (fun x y -> (x, y)) bl bl0) in if b' == b && pms' == pms && p' == p && iv' == iv && bl' == bl then c else mkCase (ci, u, pms', (p',r), iv', b', bl') | Fix (ln,(lna,tl,bl as fx)) -> let l' = fold_rec_types g fx l in let (tl', bl') = map_left2 (f l) tl (f l') bl in if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl' then c else mkFix (ln,(lna,tl',bl')) | CoFix(ln,(lna,tl,bl as fx)) -> let l' = fold_rec_types g fx l in let (tl', bl') = map_left2 (f l) tl (f l') bl in if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl' then c else mkCoFix (ln,(lna,tl',bl')) | Array(u,t,def,ty) -> let t' = Array.map_left (f l) t in let def' = f l def in let ty' = f l ty in if def' == def && t' == t && ty' == ty then c else mkArray(u,t',def',ty') (* strong *) let map_constr_with_full_binders env sigma g f l cstr = let open EConstr in match EConstr.kind sigma cstr with | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _) -> cstr | Cast (c,k, t) -> let c' = f l c in let t' = f l t in if c==c' && t==t' then cstr else mkCast (c', k, t') | Prod (na,t,c) -> let t' = f l t in let c' = f (g (RelDecl.LocalAssum (na, t)) l) c in if t==t' && c==c' then cstr else mkProd (na, t', c') | Lambda (na,t,c) -> let t' = f l t in let c' = f (g (RelDecl.LocalAssum (na, t)) l) c in if t==t' && c==c' then cstr else mkLambda (na, t', c') | LetIn (na,b,t,c) -> let b' = f l b in let t' = f l t in let c' = f (g (RelDecl.LocalDef (na, b, t)) l) c in if b==b' && t==t' && c==c' then cstr else mkLetIn (na, b', t', c') | App (c,al) -> let c' = f l c in let al' = Array.map (f l) al in if c==c' && Array.for_all2 (==) al al' then cstr else mkApp (c', al') | Proj (p,r,c) -> let c' = f l c in if c' == c then cstr else mkProj (p, r, c') | Evar ev -> let ev' = EConstr.map_existential sigma (fun c -> f l c) ev in if ev' == ev then cstr else mkEvar ev' | Case (ci, u, pms, (p,r), iv, c, bl) -> let (ci, _, pms, (p0,_), _, c, bl0) = annotate_case env sigma (ci, u, pms, (p,r), iv, c, bl) in let f_ctx (nas, _ as r) (ctx, c) = let c' = f (List.fold_right g ctx l) c in if c' == c then r else (nas, c') in let pms' = Array.Smart.map (f l) pms in let p' = f_ctx p p0 in let iv' = map_invert (f l) iv in let c' = f l c in let bl' = Array.map2 f_ctx bl bl0 in if pms==pms' && p==p' && iv'==iv && c==c' && Array.for_all2 (==) bl bl' then cstr else mkCase (ci, u, pms', (p',r), iv', c', bl') | Fix (ln,(lna,tl,bl as fx)) -> let tl' = Array.map (f l) tl in let l' = fold_rec_types g fx l in let bl' = Array.map (f l') bl in if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl' then cstr else mkFix (ln,(lna,tl',bl')) | CoFix(ln,(lna,tl,bl as fx)) -> let tl' = Array.map (f l) tl in let l' = fold_rec_types g fx l in let bl' = Array.map (f l') bl in if Array.for_all2 (==) tl tl' && Array.for_all2 (==) bl bl' then cstr else mkCoFix (ln,(lna,tl',bl')) | Array(u,t,def,ty) -> let t' = Array.Smart.map (f l) t in let def' = f l def in let ty' = f l ty in if def==def' && t == t' && ty==ty' then cstr else mkArray (u,t', def',ty') (* [fold_constr_with_binders g f n acc c] folds [f n] on the immediate subterms of [c] starting from [acc] and proceeding from left to right according to the usual representation of the constructions as [fold_constr] but it carries an extra data [n] (typically a lift index) which is processed by [g] (which typically add 1 to [n]) at each binder traversal; it is not recursive *) let fold_constr_with_full_binders env sigma g f n acc c = let open EConstr.Vars in let open Context.Rel.Declaration in match EConstr.kind sigma c with | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _ -> 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 | LetIn (na,b,t,c) -> f (g (LocalDef (na,b,t)) n) (f n (f n acc b) t) c | App (c,l) -> Array.fold_left (f n) (f n acc c) l | Proj (_,_,c) -> f n acc c | Evar ev -> let args = Evd.expand_existential sigma ev in List.fold_left (fun c -> f n c) acc args | Case (ci, u, pms, p, iv, c, bl) -> let (ci, _, pms, (p,_), _, c, bl) = EConstr.annotate_case env sigma (ci, u, pms, p, iv, c, bl) in let f_ctx acc (ctx, c) = f (List.fold_right g ctx n) acc c in Array.fold_left f_ctx (f n (fold_invert (f n) (f_ctx (Array.fold_left (f n) acc pms) p) iv) c) bl | Fix (_,(lna,tl,bl)) -> let n' = CArray.fold_left2_i (fun i c n t -> g (LocalAssum (n,lift i t)) c) n lna tl in let fd = Array.map2 (fun t b -> (t,b)) tl bl in Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd | CoFix (_,(lna,tl,bl)) -> let n' = CArray.fold_left2_i (fun i c n t -> g (LocalAssum (n,lift i t)) c) n lna tl in let fd = Array.map2 (fun t b -> (t,b)) tl bl in Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd | Array(_u,t,def,ty) -> f n (f n (Array.fold_left (f n) acc t) def) ty (***************************) (* occurs check functions *) (***************************) exception Occur let occur_meta sigma c = let rec occrec h c = let h, knd = EConstr.Expand.kind sigma h c in match knd with | Meta _ -> raise Occur | Evar (evk, args) -> let evi = Evd.find_undefined sigma evk in let args = EConstr.Expand.expand_instance ~skip:true evi h args in SList.Skip.iter (fun c -> occrec h c) args | _ -> EConstr.Expand.iter sigma occrec h knd in let h, c = EConstr.Expand.make c in try occrec h c; false with Occur -> true let occur_existential sigma c = let rec occrec h c = let h, knd = EConstr.Expand.kind sigma h c in match knd with | Evar _ -> raise Occur | _ -> EConstr.Expand.iter sigma occrec h knd in let h, c = EConstr.Expand.make c in try occrec h c; false with Occur -> true let occur_meta_or_existential sigma c = let rec occrec h c = let h, knd = EConstr.Expand.kind sigma h c in match knd with | Evar _ -> raise Occur | Meta _ -> raise Occur | _ -> EConstr.Expand.iter sigma occrec h knd in let h, c = EConstr.Expand.make c in try occrec h c; false with Occur -> true let occur_metavariable sigma m c = let rec occrec c = match EConstr.kind sigma c with | Meta m' -> if Int.equal m m' then raise Occur | Evar (_, args) -> SList.Skip.iter occrec args | _ -> EConstr.iter sigma occrec c in try occrec c; false with Occur -> true let occur_evar sigma n c = let rec occur_rec c = match EConstr.kind sigma c with | Evar (sp, args) -> if Evar.equal sp n then raise Occur else SList.Skip.iter occur_rec args | _ -> EConstr.iter sigma occur_rec c in try occur_rec c; false with Occur -> true let occur_in_global env id constr = let vars = vars_of_global env constr in Id.Set.mem id vars let occur_var env sigma id c = let rec occur_rec c = match EConstr.destRef sigma c with | gr, _ -> if occur_in_global env id gr then raise Occur | exception DestKO -> EConstr.iter sigma occur_rec c in try occur_rec c; false with Occur -> true let occur_vars env sigma ids c = let rec occur_rec c = match EConstr.destRef sigma c with | gr, _ -> let vars = vars_of_global env gr in if not (Id.Set.is_empty (Id.Set.inter ids vars)) then raise Occur | exception DestKO -> EConstr.iter sigma occur_rec c in try occur_rec c; false with Occur -> true exception OccurInGlobal of GlobRef.t let occur_var_indirectly env sigma id c = let var = GlobRef.VarRef id in let rec occur_rec c = match EConstr.destRef sigma c with | gr, _ -> if not (QGlobRef.equal env gr var) && occur_in_global env id gr then raise (OccurInGlobal gr) | exception DestKO -> EConstr.iter sigma occur_rec c in try occur_rec c; None with OccurInGlobal gr -> Some gr let occur_var_in_decl env sigma hyp decl = NamedDecl.exists (occur_var env sigma hyp) decl let occur_vars_in_decl env sigma hyps decl = NamedDecl.exists (occur_vars env sigma hyps) decl let local_occur_var sigma id c = let rec occur c = match EConstr.kind sigma c with | Var id' -> if Id.equal id id' then raise Occur | _ -> EConstr.iter sigma occur c in try occur c; false with Occur -> true let local_occur_var_in_decl sigma hyp decl = NamedDecl.exists (local_occur_var sigma hyp) decl (* returns the list of free debruijn indices in a term *) let free_rels sigma m = let rec frec depth acc c = match EConstr.kind sigma c with | Rel n -> if n >= depth then Int.Set.add (n-depth+1) acc else acc | Evar (_, args) -> SList.Skip.fold (fun acc c -> frec depth acc c) acc args | _ -> EConstr.fold_with_binders sigma succ frec depth acc c in frec 1 Int.Set.empty m let free_rels_and_unqualified_refs sigma t = let rec aux k (gseen, vseen, ids as accu) t = match EConstr.kind sigma t with | Const _ | Ind _ | Construct _ | Var _ -> let g, _ = EConstr.destRef sigma t in if not (GlobRef.Set_env.mem g gseen) then begin try let gseen = GlobRef.Set_env.add g gseen in let short = Nametab.shortest_qualid_of_global ~force_short:true Id.Set.empty g in let dir, id = Libnames.repr_qualid short in let ids = if DirPath.is_empty dir then Id.Set.add id ids else ids in (gseen, vseen, ids) with Not_found when !Flags.in_debugger || !Flags.in_ml_toplevel -> accu end else accu | Rel p -> if p > k && not (Int.Set.mem (p - k) vseen) then let vseen = Int.Set.add (p - k) vseen in (gseen, vseen, ids) else accu | _ -> EConstr.fold_with_binders sigma succ aux k accu t in let accu = (GlobRef.Set_env.empty, Int.Set.empty, Id.Set.empty) in let (_, rels, ids) = aux 0 accu t in rels, ids (* collects all metavar occurrences, in left-to-right order, preserving * repetitions and all. *) let collect_metas sigma c = let rec collrec acc c = match EConstr.kind sigma c with | Meta mv -> List.add_set Int.equal mv acc | Evar (_, args) -> SList.Skip.fold collrec acc args | _ -> EConstr.fold sigma collrec acc c in List.rev (collrec [] c) (* collects all vars; warning: this is only visible vars, not dependencies in all section variables; for the latter, use global_vars_set *) let collect_vars sigma c = let rec aux vars c = match EConstr.kind sigma c with | Var id -> Id.Set.add id vars | _ -> EConstr.fold sigma aux vars c in aux Id.Set.empty c (* Tests whether [m] is a subterm of [t]: [m] is appropriately lifted through abstractions of [t] *) let dependent_main noevar sigma m t = let open EConstr in let eqc x y = eq_constr_nounivs sigma x y in let rec deprec m t = if eqc m t then raise Occur else match EConstr.kind sigma m, EConstr.kind sigma t with | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt -> deprec m (mkApp (ft,Array.sub lt 0 (Array.length lm))); Array.Fun1.iter deprec m (Array.sub lt (Array.length lm) ((Array.length lt) - (Array.length lm))) | _, Cast (c,_,_) when noevar && isMeta sigma c -> () | _, Evar _ when noevar -> () | _ -> EConstr.iter_with_binders sigma (fun c -> Vars.lift 1 c) deprec m t in try deprec m t; false with Occur -> true let dependent sigma c t = dependent_main false sigma c t let dependent_no_evar sigma c t = dependent_main true sigma c t let dependent_in_decl sigma a decl = let open NamedDecl in match decl with | LocalAssum (_,t) -> dependent sigma a t | LocalDef (_, body, t) -> dependent sigma a body || dependent sigma a t let count_occurrences sigma m t = let open EConstr in let n = ref 0 in let rec countrec m t = if EConstr.eq_constr sigma m t then incr n else match EConstr.kind sigma m, EConstr.kind sigma t with | App (fm,lm), App (ft,lt) when Array.length lm < Array.length lt -> countrec m (mkApp (ft,Array.sub lt 0 (Array.length lm))); Array.iter (countrec m) (Array.sub lt (Array.length lm) ((Array.length lt) - (Array.length lm))) | _, Cast (c,_,_) when isMeta sigma c -> () | _, Evar _ -> () | _ -> EConstr.iter_with_binders sigma (Vars.lift 1) countrec m t in countrec m t; !n let pop t = EConstr.Vars.lift (-1) t (***************************) (* bindings functions *) (***************************) type meta_type_map = (metavariable * types) list type meta_value_map = (metavariable * constr) list let isMetaOf sigma mv c = match EConstr.kind sigma c with Meta mv' -> Int.equal mv mv' | _ -> false let rec subst_meta bl c = match kind c with | Meta i -> (try Int.List.assoc i bl with Not_found -> c) | _ -> Constr.map (subst_meta bl) c let rec strip_outer_cast sigma c = match EConstr.kind sigma c with | Cast (c,_,_) -> strip_outer_cast sigma c | _ -> c (* First utilities for avoiding telescope computation for subst_term *) let prefix_application sigma eq_fun k l1 t = let open EConstr in if 0 < l1 then match EConstr.kind sigma t with | App (f2,cl2) -> let l2 = Array.length cl2 in if l1 <= l2 && eq_fun sigma k (mkApp (f2, Array.sub cl2 0 l1)) then Some (Array.sub cl2 l1 (l2 - l1)) else None | _ -> None else None let eq_upto_lift cache c sigma k t = let c = try Int.Map.find k !cache with Not_found -> let c = EConstr.Vars.lift k c in let () = cache := Int.Map.add k c !cache in c in EConstr.eq_constr sigma c t (* Recognizing occurrences of a given subterm in a term : [replace_term c1 c2 t] substitutes [c2] for all occurrences of term [c1] in a term [t]; works if [c1] and [c2] have rels *) let replace_term_gen sigma eq_fun ar by_c in_t = let rec substrec k t = match prefix_application sigma eq_fun k ar t with | Some args -> EConstr.mkApp (EConstr.Vars.lift k by_c, args) | None -> (if eq_fun sigma k t then (EConstr.Vars.lift k by_c) else EConstr.map_with_binders sigma succ substrec k t) in substrec 0 in_t let replace_term sigma c byc t = let cache = ref Int.Map.empty in let ar = Array.length (snd (EConstr.decompose_app sigma c)) in let eq sigma k t = eq_upto_lift cache c sigma k t in replace_term_gen sigma eq ar byc t let subst_term sigma c t = replace_term sigma c (EConstr.mkRel 1) t let add_vname vars = function Name id -> Id.Set.add id vars | _ -> vars (*************************) (* Names environments *) (*************************) type names_context = Name.t list let add_name n nl = n::nl let lookup_name_of_rel p names = try List.nth names (p-1) with Invalid_argument _ | Failure _ -> raise Not_found let lookup_rel_of_name id names = let rec lookrec n = function | Anonymous :: l -> lookrec (n+1) l | (Name id') :: l -> if Id.equal id' id then n else lookrec (n+1) l | [] -> raise Not_found in lookrec 1 names let empty_names_context = [] let ids_of_rel_context sign = Context.Rel.fold_outside (fun decl l -> match RelDecl.get_name decl with Name id -> id::l | Anonymous -> l) sign ~init:[] let ids_of_named_context sign = Context.Named.fold_outside (fun decl idl -> NamedDecl.get_id decl :: idl) sign ~init:[] let ids_of_context env = (ids_of_rel_context (rel_context env)) @ (ids_of_named_context (named_context env)) let names_of_rel_context env = List.map RelDecl.get_name (rel_context env) let is_section_variable env id = try let _ = Environ.lookup_named id env in true with Not_found -> false let is_template_polymorphic_ref env sigma f = match EConstr.kind sigma f with | Ind (ind, u) | Construct ((ind, _), u) -> if not (EConstr.EInstance.is_empty u) then false else Environ.template_polymorphic_ind ind env | _ -> false let is_template_polymorphic_ind env sigma f = match EConstr.kind sigma f with | Ind (ind, u) -> if not (EConstr.EInstance.is_empty u) then false else Environ.template_polymorphic_ind ind env | _ -> false let base_sort_cmp pb s0 s1 = match (s0,s1) with | SProp, SProp | Prop, Prop | Set, Set | Type _, Type _ -> true | QSort (q1, _), QSort (q2, _) -> Sorts.QVar.equal q1 q2 | QSort _, _ | _, QSort _ -> false | SProp, _ | _, SProp -> false | Prop, Set | Prop, Type _ | Set, Type _ -> pb == Conversion.CUMUL | Set, Prop | Type _, Prop | Type _, Set -> false let rec is_Prop sigma c = match EConstr.kind sigma c with | Sort u -> begin match EConstr.ESorts.kind sigma u with | Prop -> true | _ -> false end | Cast (c,_,_) -> is_Prop sigma c | _ -> false let rec is_Set sigma c = match EConstr.kind sigma c with | Sort u -> begin match EConstr.ESorts.kind sigma u with | Set -> true | _ -> false end | Cast (c,_,_) -> is_Set sigma c | _ -> false let rec is_Type sigma c = match EConstr.kind sigma c with | Sort u -> begin match EConstr.ESorts.kind sigma u with | Type _ -> true | _ -> false end | Cast (c,_,_) -> is_Type sigma c | _ -> false (* eq_constr extended with universe erasure *) let compare_constr_univ env sigma f cv_pb t1 t2 = let open EConstr in match EConstr.kind sigma t1, EConstr.kind sigma t2 with Sort s1, Sort s2 -> base_sort_cmp cv_pb (ESorts.kind sigma s1) (ESorts.kind sigma s2) | Prod (_,t1,c1), Prod (_,t2,c2) -> f Conversion.CONV t1 t2 && f cv_pb c1 c2 | Const (c, u), Const (c', u') -> QConstant.equal env c c' | Ind (i, _), Ind (i', _) -> QInd.equal env i i' | Construct (i, _), Construct (i', _) -> QConstruct.equal env i i' | _ -> EConstr.compare_constr sigma (fun t1 t2 -> f Conversion.CONV t1 t2) t1 t2 let constr_cmp env sigma cv_pb t1 t2 = let rec compare cv_pb t1 t2 = compare_constr_univ env sigma compare cv_pb t1 t2 in compare cv_pb t1 t2 let eq_constr env sigma t1 t2 = constr_cmp env sigma Conversion.CONV t1 t2 let nb_lam sigma c = let rec nbrec n c = match EConstr.kind sigma c with | Lambda (_,_,c) -> nbrec (n+1) c | Cast (c,_,_) -> nbrec n c | _ -> n in nbrec 0 c let nb_prod sigma c = let rec nbrec n c = match EConstr.kind sigma c with | Prod (_,_,c) -> nbrec (n+1) c | Cast (c,_,_) -> nbrec n c | _ -> n in nbrec 0 c let nb_prod_modulo_zeta sigma x = let rec count n c = match EConstr.kind sigma c with Prod(_,_,t) -> count (n+1) t | LetIn(_,a,_,t) -> count n (EConstr.Vars.subst1 a t) | Cast(c,_,_) -> count n c | _ -> n in count 0 x (* We reduce a series of head eta-redex or nothing at all *) (* [x1:c1;...;xn:cn]@(f;a1...an;x1;...;xn) --> @(f;a1...an) *) (* Remplace 2 earlier buggish versions *) let rec eta_reduce_head sigma c = let open EConstr in let open Vars in match EConstr.kind sigma c with | Lambda (_,c1,c') -> (match EConstr.kind sigma (eta_reduce_head sigma c') with | App (f,cl) -> let lastn = (Array.length cl) - 1 in if lastn < 0 then anomaly (Pp.str "application without arguments.") else (match EConstr.kind sigma cl.(lastn) with | Rel 1 -> let c' = if Int.equal lastn 0 then f else mkApp (f, Array.sub cl 0 lastn) in if noccurn sigma 1 c' then lift (-1) c' else c | _ -> c) | _ -> c) | _ -> c let eta_expand_instantiation ?evars env inst ctxt = let open Context.Rel.Declaration in let eta_inst = Array.make (Array.length inst) mkProp in let rec fold subst i = function | [] -> assert (Array.length inst = i) | LocalAssum (_, ty) :: ctx -> let ty = substl subst ty in let eta_t = Reduction.eta_expand ?evars env inst.(i) ty in let () = eta_inst.(i) <- eta_t in fold (eta_t :: subst) (i + 1) ctx | LocalDef (_, bd, _) :: ctx -> fold (bd :: subst) i ctx in let () = fold [] 0 (List.rev ctxt) in eta_inst (* iterator on rel context *) let process_rel_context f env = let sign = named_context_val env in let rels = EConstr.rel_context env in let env0 = reset_with_named_context sign env in Context.Rel.fold_outside f rels ~init:env0 let assums_of_rel_context sign = Context.Rel.fold_outside (fun decl l -> match decl with | RelDecl.LocalDef _ -> l | RelDecl.LocalAssum (na,t) -> (na, t)::l) sign ~init:[] let map_rel_context_in_env f env sign = let rec aux env acc = function | d::sign -> aux (push_rel d env) (RelDecl.map_constr (f env) d :: acc) sign | [] -> acc in aux env [] (List.rev sign) let fold_named_context_both_sides f l ~init = List.fold_right_and_left f l init let mem_named_context_val id ctxt = try ignore(Environ.lookup_named_ctxt id ctxt); true with Not_found -> false let compact_named_context sigma sign = let compact l decl = match decl, l with | NamedDecl.LocalAssum (i,t), [] -> [CompactedDecl.LocalAssum ([i],t)] | NamedDecl.LocalDef (i,c,t), [] -> [CompactedDecl.LocalDef ([i],c,t)] | NamedDecl.LocalAssum (i1,t1), CompactedDecl.LocalAssum (li,t2) :: q -> if EConstr.eq_constr sigma t1 t2 then CompactedDecl.LocalAssum (i1::li, t2) :: q else CompactedDecl.LocalAssum ([i1],t1) :: CompactedDecl.LocalAssum (li,t2) :: q | NamedDecl.LocalDef (i1,c1,t1), CompactedDecl.LocalDef (li,c2,t2) :: q -> if EConstr.eq_constr sigma c1 c2 && EConstr.eq_constr sigma t1 t2 then CompactedDecl.LocalDef (i1::li, c2, t2) :: q else CompactedDecl.LocalDef ([i1],c1,t1) :: CompactedDecl.LocalDef (li,c2,t2) :: q | NamedDecl.LocalAssum (i,t), q -> CompactedDecl.LocalAssum ([i],t) :: q | NamedDecl.LocalDef (i,c,t), q -> CompactedDecl.LocalDef ([i],c,t) :: q in sign |> Context.Named.fold_inside compact ~init:[] |> List.rev let clear_named_body id env = let open NamedDecl in let aux _ = function | LocalDef (id',c,t) when Id.equal id id'.binder_name -> push_named (LocalAssum (id',t)) | d -> push_named d in fold_named_context aux env ~init:(reset_context env) let global_vars_set env sigma constr = let rec filtrec acc c = match EConstr.destRef sigma c with | gr, _ -> Id.Set.union (vars_of_global env gr) acc | exception DestKO -> EConstr.fold sigma filtrec acc c in filtrec Id.Set.empty constr let global_vars_set_of_decl env sigma = function | NamedDecl.LocalAssum (_,t) -> global_vars_set env sigma t | NamedDecl.LocalDef (_,c,t) -> Id.Set.union (global_vars_set env sigma t) (global_vars_set env sigma c) let dependency_closure env sigma sign hyps = if Id.Set.is_empty hyps then [] else let (_,lh) = Context.Named.fold_inside (fun (hs,hl) d -> let x = NamedDecl.get_id d in if Id.Set.mem x hs then (Id.Set.union (global_vars_set_of_decl env sigma d) (Id.Set.remove x hs), x::hl) else (hs,hl)) ~init:(hyps,[]) sign in List.rev lh let global_app_of_constr sigma c = let open GlobRef in match EConstr.kind sigma c with | Const (c, u) -> (ConstRef c, u), None | Ind (i, u) -> (IndRef i, u), None | Construct (c, u) -> (ConstructRef c, u), None | Var id -> (VarRef id, EConstr.EInstance.empty), None | Proj (p, _, c) -> (ConstRef (Projection.constant p), EConstr.EInstance.empty), Some c | _ -> raise Not_found let prod_applist sigma c l = let open EConstr in let rec app subst c l = match EConstr.kind sigma c, l with | Prod(_,_,c), arg::l -> app (arg::subst) c l | _, [] -> Vars.substl subst c | _ -> anomaly (Pp.str "Not enough prod's.") in app [] c l let prod_applist_decls sigma n c l = let open EConstr in let rec app n subst c l = if Int.equal n 0 then if l == [] then Vars.substl subst c else anomaly (Pp.str "Not enough arguments.") else match EConstr.kind sigma c, l with | Prod(_,_,c), arg::l -> app (n-1) (arg::subst) c l | LetIn(_,b,_,c), _ -> app (n-1) (Vars.substl subst b::subst) c l | _ -> anomaly (Pp.str "Not enough prod/let's.") in app n [] c l (* Do not skip let-in's *) let env_rel_context_chop k env = let open EConstr in let rels = rel_context env in let ctx1,ctx2 = List.chop k rels in push_rel_context ctx2 (reset_with_named_context (named_context_val env) env), ctx1 rocq-9.2.0/engine/termops.mli000066400000000000000000000271131516144147600161440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* env -> env val push_rels_assum : (Name.t Constr.binder_annot * Constr.types) list -> env -> env val push_named_rec_types : Name.t Constr.binder_annot array * Constr.types array * 'a -> env -> env val lookup_rel_id : Id.t -> ('c, 't, 'r) Context.Rel.pt -> int * 'c option * 't (** Associates the contents of an identifier in a [rel_context]. Raise [Not_found] if there is no such identifier. *) (** Functions that build argument lists matching a block of binders or a context. [rel_vect n m] builds [|Rel (n+m);...;Rel(n+1)|] *) val rel_vect : int -> int -> Constr.constr array val rel_list : int -> int -> constr list (** Prod/Lambda/LetIn destructors on constr *) val it_mkNamedProd_wo_LetIn : Constr.types -> Constr.named_context -> Constr.types (* Ad hoc version reinserting letin, assuming the body is defined in the context where the letins are expanded *) val it_mkLambda_or_LetIn_from_no_LetIn : Constr.constr -> Constr.rel_context -> Constr.constr (** {6 Generic iterators on constr} *) val map_constr_with_binders_left_to_right : Environ.env -> Evd.evar_map -> (rel_declaration -> 'a -> 'a) -> ('a -> constr -> constr) -> 'a -> constr -> constr val map_constr_with_full_binders : Environ.env -> Evd.evar_map -> (rel_declaration -> 'a -> 'a) -> ('a -> constr -> constr) -> 'a -> constr -> constr val fold_constr_with_full_binders : Environ.env -> Evd.evar_map -> (rel_declaration -> 'a -> 'a) -> ('a -> 'b -> constr -> 'b) -> 'a -> 'b -> constr -> 'b (**********************************************************************) val strip_head_cast : Evd.evar_map -> constr -> constr val drop_extra_implicit_args : Evd.evar_map -> constr -> constr (** occur checks *) exception Occur val occur_meta : Evd.evar_map -> constr -> bool val occur_existential : Evd.evar_map -> constr -> bool val occur_meta_or_existential : Evd.evar_map -> constr -> bool val occur_metavariable : Evd.evar_map -> metavariable -> constr -> bool val occur_evar : Evd.evar_map -> Evar.t -> constr -> bool val occur_var : env -> Evd.evar_map -> Id.t -> constr -> bool val occur_var_indirectly : env -> Evd.evar_map -> Id.t -> constr -> GlobRef.t option val occur_var_in_decl : env -> Evd.evar_map -> Id.t -> named_declaration -> bool val occur_vars : env -> Evd.evar_map -> Id.Set.t -> constr -> bool val occur_vars_in_decl : env -> Evd.evar_map -> Id.Set.t -> named_declaration -> bool (** As {!occur_var} but assume the identifier not to be a section variable *) val local_occur_var : Evd.evar_map -> Id.t -> constr -> bool val local_occur_var_in_decl : Evd.evar_map -> Id.t -> named_declaration -> bool val free_rels : Evd.evar_map -> constr -> Int.Set.t (* Return the list of unbound rels and unqualified reference (same strategy as in Namegen) *) val free_rels_and_unqualified_refs : Evd.evar_map -> constr -> Int.Set.t * Id.Set.t (** [dependent m t] tests whether [m] is a subterm of [t] *) val dependent : Evd.evar_map -> constr -> constr -> bool val dependent_no_evar : Evd.evar_map -> constr -> constr -> bool val dependent_in_decl : Evd.evar_map -> constr -> named_declaration -> bool val count_occurrences : Evd.evar_map -> constr -> constr -> int val collect_metas : Evd.evar_map -> constr -> int list val collect_vars : Evd.evar_map -> constr -> Id.Set.t (** for visible vars only *) (* Substitution of metavariables *) type meta_value_map = (metavariable * Constr.constr) list val subst_meta : meta_value_map -> Constr.constr -> Constr.constr val isMetaOf : Evd.evar_map -> metavariable -> constr -> bool (** Type assignment for metavariables *) type meta_type_map = (metavariable * Constr.types) list (** [pop c] lifts by -1 the positive indexes in [c] *) val pop : constr -> constr (** {6 ... } *) (** Substitution of an arbitrary large term. Uses equality modulo reduction of let *) (** [replace_term_gen eq arity e c] replaces matching subterms according to [eq] by [e] in [c]. If [arity] is non-zero applications of larger length are handled atomically. *) val replace_term_gen : Evd.evar_map -> (Evd.evar_map -> int -> constr -> bool) -> int -> constr -> constr -> constr (** [subst_term d c] replaces [d] by [Rel 1] in [c] *) val subst_term : Evd.evar_map -> constr -> constr -> constr (** [replace_term d e c] replaces [d] by [e] in [c] *) val replace_term : Evd.evar_map -> constr -> constr -> constr -> constr (** Alternative term equalities *) val base_sort_cmp : Conversion.conv_pb -> Sorts.t -> Sorts.t -> bool val compare_constr_univ : Environ.env -> Evd.evar_map -> (Conversion.conv_pb -> constr -> constr -> bool) -> Conversion.conv_pb -> constr -> constr -> bool val constr_cmp : Environ.env -> Evd.evar_map -> Conversion.conv_pb -> constr -> constr -> bool val eq_constr : Environ.env -> Evd.evar_map -> constr -> constr -> bool (* FIXME rename: erases universes*) val eta_reduce_head : Evd.evar_map -> constr -> constr (* Eta expand the instantiation of a context *) val eta_expand_instantiation : ?evars:CClosure.evar_handler -> env -> Constr.constr array -> Constr.rel_context -> Constr.constr array (** [prod_applist] [forall (x1:B1;...;xn:Bn), B] [a1...an] @return [B[a1...an]] *) val prod_applist : Evd.evar_map -> constr -> constr list -> constr (** In [prod_applist_decls n c args], [c] is supposed to have the form [βˆ€Ξ“.c] with [Ξ“] of length [m] and possibly with let-ins; it returns [c] with the assumptions of [Ξ“] instantiated by [args] and the local definitions of [Ξ“] expanded. Note that [n] counts both let-ins and prods, while the length of [args] only counts prods. In other words, varying [n] changes how many trailing let-ins are expanded. *) val prod_applist_decls : Evd.evar_map -> int -> constr -> constr list -> constr (** Remove recursively the casts around a term i.e. [strip_outer_cast (Cast (Cast ... (Cast c, t) ... ))] is [c]. *) val strip_outer_cast : Evd.evar_map -> constr -> constr (** [nb_lam sigma t] counts the number of head lambda abstractions in [t], ignoring casts. For instance on [fun x1 x2 x3 => c] (where [c] is not itself a lambda abstraction) it returns 3. *) val nb_lam : Evd.evar_map -> constr -> int (** [nb_prod sigma t] counts the number of head products in [t], ignoring casts. *) val nb_prod : Evd.evar_map -> constr -> int (** Variant of [nb_prod] which also does zeta-reduction (i.e. reduces let-ins) along the way. *) val nb_prod_modulo_zeta : Evd.evar_map -> constr -> int (** [last_arg sigma t] returns the last argument of [t]. Fails if [t] is not an application. *) val last_arg : Evd.evar_map -> constr -> constr val adjust_app_list_size : constr -> constr list -> constr -> constr list -> (constr * constr list * constr * constr list) val adjust_app_array_size : constr -> constr array -> constr -> constr array -> (constr * constr array * constr * constr array) (** name contexts *) type names_context = Name.t list val add_name : Name.t -> names_context -> names_context val lookup_name_of_rel : int -> names_context -> Name.t val lookup_rel_of_name : Id.t -> names_context -> int val empty_names_context : names_context val ids_of_rel_context : ('c, 't, 'r) Context.Rel.pt -> Id.t list val ids_of_named_context : ('c, 't, 'r) Context.Named.pt -> Id.t list val ids_of_context : env -> Id.t list val names_of_rel_context : env -> names_context (* [env_rel_context_chop n env] extracts out the [n] top declarations of the rel_context part of [env], counting both local definitions and hypotheses *) val env_rel_context_chop : int -> env -> env * rel_context (** Set of local names *) val vars_of_env: env -> Id.Set.t val add_vname : Id.Set.t -> Name.t -> Id.Set.t (** other signature iterators *) val process_rel_context : (rel_declaration -> env -> env) -> env -> env val assums_of_rel_context : ('c, 't, 'r) Context.Rel.pt -> ((Name.t,'r) Context.pbinder_annot * 't) list val map_rel_context_in_env : (env -> Constr.constr -> Constr.constr) -> env -> Constr.rel_context -> Constr.rel_context val fold_named_context_both_sides : ('a -> Constr.named_declaration -> Constr.named_declaration list -> 'a) -> Constr.named_context -> init:'a -> 'a val mem_named_context_val : Id.t -> named_context_val -> bool val compact_named_context : Evd.evar_map -> EConstr.named_context -> EConstr.compacted_context val clear_named_body : Id.t -> env -> env val global_vars_set : env -> Evd.evar_map -> constr -> Id.Set.t val global_vars_set_of_decl : env -> Evd.evar_map -> named_declaration -> Id.Set.t val global_app_of_constr : Evd.evar_map -> constr -> (GlobRef.t * EInstance.t) * constr option (** Gives an ordered list of hypotheses, closed by dependencies, containing a given set *) val dependency_closure : env -> Evd.evar_map -> named_context -> Id.Set.t -> Id.t list (** Test if an identifier is the basename of a global reference *) val is_section_variable : env -> Id.t -> bool val is_template_polymorphic_ref : env -> Evd.evar_map -> constr -> bool val is_template_polymorphic_ind : env -> Evd.evar_map -> constr -> bool val is_Prop : Evd.evar_map -> constr -> bool val is_Set : Evd.evar_map -> constr -> bool val is_Type : Evd.evar_map -> constr -> bool val reference_of_level : Evd.evar_map -> Univ.Level.t -> Libnames.qualid option (** {5 Debug pretty-printers} *) open Evd val pr_global_env : env -> GlobRef.t -> Pp.t val pr_existential_key : env -> evar_map -> Evar.t -> Pp.t val evar_suggested_name : env -> evar_map -> Evar.t -> Id.t val pr_evar_info : env -> evar_map -> 'a evar_info -> Pp.t val pr_evar_constraints : evar_map -> evar_constraint list -> Pp.t val pr_evar_map : ?with_univs:bool -> int option -> env -> evar_map -> Pp.t val pr_evar_map_filter : ?with_univs:bool -> (Evar.t -> any_evar_info -> bool) -> env -> evar_map -> Pp.t val pr_evd_level : evar_map -> Univ.Level.t -> Pp.t val pr_evd_qvar : evar_map -> Sorts.QVar.t -> Pp.t module Internal : sig (** NOTE: to print terms you always want to use functions in Printer, not these ones which are for very special cases. *) (** debug printers: print raw form for terms with evar-substitution. *) val debug_print_constr : evar_map -> constr -> Pp.t (** Pretty-printer hook: [print_constr_env env sigma c] will pretty print c if the pretty printing layer has been linked into the Rocq binary. *) val print_constr_env : env -> Evd.evar_map -> constr -> Pp.t (** [set_print_constr f] sets f to be the pretty printer *) val set_print_constr : (env -> Evd.evar_map -> constr -> Pp.t) -> unit (** Printers for contexts *) val print_named_context : env -> Evd.evar_map -> Pp.t val pr_rel_decl : env -> Evd.evar_map -> Constr.rel_declaration -> Pp.t val print_rel_context : env -> Evd.evar_map -> Pp.t val print_env : env -> Evd.evar_map -> Pp.t val print_kconstr : Environ.env -> Evd.evar_map -> Evd.econstr -> Pp.t end val pr_evar_universe_context : UState.t -> Pp.t [@@deprecated "(9.0) Use [UState.pr] instead"] rocq-9.2.0/engine/uState.ml000066400000000000000000001661751516144147600155630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* cache_template_default_univs us); discharge_function = (fun x -> Some x); classify_function = (fun _ -> Escape); } let add_template_default_univs env kn = match (Environ.lookup_mind kn env).mind_template with | None -> () | Some template -> let _, us = UVars.Instance.levels template.template_defaults in Lib.add_leaf (template_default_univs_obj us) let template_default_univs () = !template_default_univs module UnivFlex = UnivFlex type universes_entry = | Monomorphic_entry of Univ.ContextSet.t | Polymorphic_entry of UVars.UContext.t module UNameMap = Id.Map type uinfo = { uname : Id.t option; uloc : Loc.t option; } open Quality let sort_inconsistency ?explain cst l r = let explain = Option.map (fun p -> UGraph.Other p) explain in raise (UGraph.UniverseInconsistency (None, (cst, l, r, explain))) module QSet = QVar.Set module QMap = QVar.Map module QState : sig type t type elt = QVar.t val empty : t val union : fail:(t -> Quality.t -> Quality.t -> t) -> t -> t -> t val add : check_fresh:bool -> rigid:bool -> elt -> t -> t val repr : elt -> t -> Quality.t val is_rigid : t -> QVar.t -> bool val is_above_prop : t -> QVar.t -> bool val unify_quality : fail:(unit -> t) -> Conversion.conv_pb -> Quality.t -> Quality.t -> t -> t val undefined : t -> QVar.Set.t val collapse_above_prop : to_prop:bool -> t -> t val collapse : ?except:QVar.Set.t -> t -> t val pr : (QVar.t -> Libnames.qualid option) -> t -> Pp.t val of_elims : QGraph.t -> t val elims : t -> QGraph.t val set_elims : QGraph.t -> t -> t val initial_elims : t -> QGraph.t val merge_constraints : (QGraph.t -> QGraph.t) -> t -> t val normalize_elim_constraints : t -> ElimConstraints.t -> ElimConstraints.t end = struct type node = | Equiv of Quality.t | Canonical of { rigid : bool } (** Rigid variables may not be set to another *) type t = { qmap : node QMap.t; (* TODO: use a persistent union-find structure *) above_prop : QSet.t; (** Set for quality variables known to be either in Prop or Type. If q ∈ above_prop then it must map to None in qmap. *) elims : QGraph.t; (** Elimination graph for quality variables. *) initial_elims : QGraph.t; (** Keep the qvar domain without any constraints to optimize computation. *) } type elt = QVar.t let empty = { qmap = QMap.empty; above_prop = QSet.empty; elims = QGraph.initial_graph; initial_elims = QGraph.initial_graph } let rec repr q m = match QMap.find q m.qmap with | Canonical _ -> QVar q | Equiv (QVar q) -> repr q m | Equiv (QConstant _ as q) -> q | exception Not_found -> QVar q type repr = | ReprConstant of Quality.constant | ReprVar of QVar.t * bool let rec repr_node q m = match QMap.find q m.qmap with | Canonical { rigid } -> ReprVar (q, rigid) | Equiv (QVar q) -> repr_node q m | Equiv (QConstant qc) -> ReprConstant qc | exception Not_found -> ReprVar (q, true) (* a bit dubious but missing variables are considered rigid *) let is_above_prop m q = QSet.mem q m.above_prop let eliminates_to_prop m q = QGraph.eliminates_to_prop m.elims (QVar q) let is_rigid m q = match repr_node q m with | ReprVar (_, rigid) -> rigid | ReprConstant _ -> true let set q qv m = let q = repr_node q m in let q, rigid = match q with ReprVar (q, rigid) -> q, rigid | ReprConstant _ -> assert false in let qv = match qv with QVar qv -> repr_node qv m | QConstant qc -> ReprConstant qc in let enforce_eq q1 q2 g = let ans = QGraph.enforce_eliminates_to q1 q2 (QGraph.enforce_eliminates_to q2 q1 g) in let () = QGraph.check_rigid_paths ans in ans in match q, qv with | q, ReprVar (qv, _qvrigd) -> if QVar.equal q qv then Some m else if rigid then None else let above_prop = if is_above_prop m q then QSet.add qv (QSet.remove q m.above_prop) else m.above_prop in Some { qmap = QMap.add q (Equiv (QVar qv)) m.qmap; above_prop; elims = enforce_eq (QVar qv) (QVar q) m.elims; initial_elims = m.initial_elims } | q, ReprConstant qc -> if qc == QSProp && (is_above_prop m q || eliminates_to_prop m q) then None else if rigid then None else let qv = QConstant qc in Some { m with qmap = QMap.add q (Equiv qv) m.qmap; above_prop = QSet.remove q m.above_prop; elims = enforce_eq qv (QVar q) m.elims } let set_above_prop q m = let q = repr_node q m in let q, rigid = match q with ReprVar (q, rigid) -> q, rigid | ReprConstant _ -> assert false in if rigid then None else Some { m with above_prop = QSet.add q m.above_prop } let unify_quality ~fail c q1 q2 local = match q1, q2 with | QConstant QType, QConstant QType | QConstant QProp, QConstant QProp | QConstant QSProp, QConstant QSProp -> local | QConstant QProp, QVar q when c == Conversion.CUMUL -> begin match set_above_prop q local with | Some local -> local | None -> fail () end | QVar qv1, QVar qv2 -> begin match set qv1 q2 local with | Some local -> local | None -> match set qv2 q1 local with | Some local -> local | None -> fail () end | QVar q, (QConstant (QType | QProp | QSProp) as qv) | (QConstant (QType | QProp | QSProp) as qv), QVar q -> begin match set q qv local with | Some local -> local | None -> fail () end | (QConstant QType, QConstant (QProp | QSProp)) -> fail () | (QConstant QProp, QConstant QType) -> begin match c with | CONV -> fail () | CUMUL -> local end | (QConstant QSProp, QConstant (QType | QProp)) -> fail () | (QConstant QProp, QConstant QSProp) -> fail () let nf_quality m = function | QConstant _ as q -> q | QVar q -> repr q m let add_qvars m qmap qs = let g = m.initial_elims in let filter v = match QMap.find_opt v qmap with | None | Some (Canonical _) -> true | Some (Equiv _) -> false in (* Here, we filter instead of enforcing equality due to the collapse: simply enforcing equality may lead to inconsistencies after it *) let qs = QVar.Set.filter filter qs in let fold v g = try QGraph.add_quality (QVar v) g with QGraph.AlreadyDeclared -> g in QVar.Set.fold fold qs g let union ~fail s1 s2 = let extra = ref [] in let qmap = QMap.union (fun qk q1 q2 -> match q1, q2 with | Equiv q, (Canonical _) | (Canonical _), Equiv q -> Some (Equiv q) | Canonical { rigid = r1 }, Canonical { rigid = r2 } -> (* XXX this looks wrong, but this preserves the previous behaviour *) Some (Canonical { rigid = r1 || r2 }) | Equiv q1, Equiv q2 -> let () = if not (Quality.equal q1 q2) then extra := (q1,q2) :: !extra in Some (Equiv q1)) s1.qmap s2.qmap in let extra = !extra in let qs = QVar.Set.union (QGraph.qvar_domain s1.elims) (QGraph.qvar_domain s2.elims) in let filter v = match QMap.find_opt v qmap with | None | Some (Canonical _) -> true | Some (Equiv _) -> false in let above_prop = QSet.filter filter @@ QSet.union s1.above_prop s2.above_prop in let elims = add_qvars s2 qmap qs in let s = { qmap; above_prop; elims; initial_elims = elims } in List.fold_left (fun s (q1,q2) -> let q1 = nf_quality s q1 and q2 = nf_quality s q2 in unify_quality ~fail:(fun () -> fail s q1 q2) CONV q1 q2 s) s extra let add ~check_fresh ~rigid q m = if check_fresh then assert (not (QMap.mem q m.qmap)); let add_quality g = try QGraph.add_quality (QVar q) g with QGraph.AlreadyDeclared as e -> if check_fresh then raise e else g in { qmap = QMap.add q (Canonical { rigid }) m.qmap; above_prop = m.above_prop; elims = add_quality m.elims; initial_elims = add_quality m.initial_elims } let of_elims elims = let qs = QGraph.qvar_domain elims in let initial_elims = QSet.fold (fun v -> QGraph.add_quality (QVar v)) qs (QGraph.initial_graph) in let initial_elims = QGraph.update_rigids elims initial_elims in { empty with elims; initial_elims } (* XXX what about qvars in the elimination graph? *) let undefined m = let filter _ v = match v with | Canonical _ -> true | Equiv _ -> false in let mq = QMap.filter filter m.qmap in QMap.domain mq let collapse_above_prop ~to_prop m = QMap.fold (fun q v m -> match v with | Equiv _ -> m | Canonical _ -> if not @@ is_above_prop m q then m else if to_prop then Option.get (set q qprop m) else Option.get (set q qtype m) ) m.qmap m let collapse ?(except=QSet.empty) m = QMap.fold (fun q v m -> match v with | Equiv _ -> m | Canonical { rigid } -> if rigid || QSet.mem q except then m else Option.get (set q qtype m)) m.qmap m let pr prqvar_opt ({ qmap; elims } as m) = let open Pp in (* Print the QVar using its name if any, e.g. "Ξ±1" or "s" *) let prqvar q = match prqvar_opt q with | None -> QVar.raw_pr q | Some qid -> Libnames.pr_qualid qid in (* Print the "body" of the QVar, e.g. "Ξ±1 := Type", "Ξ±2 >= Prop" *) let prbody u = function | Canonical { rigid } -> if is_above_prop m u then str " >= Prop" else if rigid then str " (rigid)" else mt () | Equiv q -> let q = Quality.pr prqvar q in str " := " ++ q in (* Print the "name" (given by the user) of the Qvar, e.g. "(named s)" *) let prqvar_name q = match prqvar_opt q with | None -> mt () | Some qid -> str " (named " ++ Libnames.pr_qualid qid ++ str ")" in let prqvar_full (q1, q2) = QVar.raw_pr q1 ++ prbody q1 q2 ++ prqvar_name q1 in hov 0 (prlist_with_sep fnl prqvar_full (QMap.bindings qmap) ++ str " |=" ++ brk (1, 2) ++ hov 0 (QGraph.pr_qualities (Quality.pr prqvar) elims)) let elims m = m.elims let set_elims elims m = { m with elims } let initial_elims m = m.initial_elims let merge_constraints f m = { m with elims = f m.elims } let normalize_elim_constraints m cstrs = let subst q = match q with | QConstant _ -> q | QVar qv -> repr qv m in let is_instantiated q = is_qconst q || is_qglobal q in let can_drop (q1,_,q2) = not (is_instantiated q1 && is_instantiated q2) in let subst_cst (q1,c,q2) = (subst q1,c,subst q2) in let cstrs = ElimConstraints.map subst_cst cstrs in ElimConstraints.filter can_drop cstrs end module UPairSet = UnivMinim.UPairSet type univ_names = UnivNames.universe_binders * (uinfo QVar.Map.t * uinfo Level.Map.t) (* 2nd part used to check consistency on the fly. *) type t = { names : univ_names; (** Printing/location information *) local : PContextSet.t; (** The local graph of universes (variables and constraints) *) univ_variables : UnivFlex.t; (** The local universes that are unification variables *) sort_variables : QState.t; (** Local quality variables. *) universes : UGraph.t; (** The current graph extended with the local constraints *) initial_universes : UGraph.t; (** The graph at the creation of the evar_map + local universes (but not local constraints) *) minim_extra : UnivMinim.extra; } let empty = { names = UnivNames.empty_binders, (QMap.empty, Level.Map.empty); local = PContextSet.empty; univ_variables = UnivFlex.empty; sort_variables = QState.empty; universes = UGraph.initial_universes; initial_universes = UGraph.initial_universes; minim_extra = UnivMinim.empty_extra; } let make ~qualities univs = { empty with universes = univs; initial_universes = univs ; sort_variables = QState.of_elims qualities } let is_empty uctx = PContextSet.is_empty uctx.local && UnivFlex.is_empty uctx.univ_variables let id_of_level uctx l = try (Level.Map.find l (snd (snd uctx.names))).uname with Not_found -> None let id_of_qvar uctx l = try (QVar.Map.find l (fst (snd uctx.names))).uname with Not_found -> None let is_rigid_qvar uctx q = QState.is_rigid uctx.sort_variables q let get_uname info = match info.uname with | None -> raise Not_found | Some id -> id let qualid_of_qvar_names (bind, (qrev,_)) l = try Some (Libnames.qualid_of_ident (get_uname (QVar.Map.find l qrev))) with Not_found -> UnivNames.qualid_of_quality bind l let qualid_of_level_names (bind, (_,urev)) l = try Some (Libnames.qualid_of_ident (get_uname (Level.Map.find l urev))) with Not_found -> UnivNames.qualid_of_level bind l let qualid_of_level uctx l = qualid_of_level_names uctx.names l let pr_uctx_qvar_names names l = match qualid_of_qvar_names names l with | Some qid -> Libnames.pr_qualid qid | None -> QVar.raw_pr l let pr_uctx_level_names names l = match qualid_of_level_names names l with | Some qid -> Libnames.pr_qualid qid | None -> Level.raw_pr l let pr_uctx_level uctx l = pr_uctx_level_names uctx.names l let pr_uctx_qvar uctx l = pr_uctx_qvar_names uctx.names l let merge_univ_constraints uctx cstrs g = try UGraph.merge_constraints cstrs g with UGraph.UniverseInconsistency (_, i) -> let printers = (pr_uctx_qvar uctx, pr_uctx_level uctx) in raise (UGraph.UniverseInconsistency (Some printers, i)) type constraint_source = | Internal | Rigid | Static let merge_elim_constraints ?(src = Internal) uctx cstrs g = try let g = QGraph.merge_constraints cstrs g in match src with | Static -> g | Internal -> let () = if not (ElimConstraints.is_empty cstrs) then QGraph.check_rigid_paths g in g | Rigid -> let fold (q1, _, q2) accu = QGraph.add_rigid_path q1 q2 accu in Sorts.ElimConstraints.fold fold cstrs g with QGraph.(EliminationError (QualityInconsistency (_, i))) -> let printer = pr_uctx_qvar uctx in raise (QGraph.(EliminationError (QualityInconsistency (Some printer, i)))) let uname_union s t = if s == t then s else UNameMap.merge (fun k l r -> match l, r with | Some _, _ -> l | _, _ -> r) s t let names_union ((qbind,ubind),(qrev,urev)) ((qbind',ubind'),(qrev',urev')) = let qbind = uname_union qbind qbind' and ubind = uname_union ubind ubind' and qrev = QVar.Map.union (fun _ l _ -> Some l) qrev qrev' and urev = Level.Map.lunion urev urev' in ((qbind,ubind),(qrev,urev)) let union uctx uctx' = if uctx == uctx' then uctx else if is_empty uctx' then uctx else let local = PContextSet.union uctx.local uctx'.local in let names = names_union uctx.names uctx'.names in let newus = Level.Set.diff (PContextSet.levels uctx'.local) (PContextSet.levels uctx.local) in let newus = Level.Set.diff newus (UnivFlex.domain uctx.univ_variables) in let extra = UnivMinim.extra_union uctx.minim_extra uctx'.minim_extra in let declarenew g = Level.Set.fold (fun u g -> UGraph.add_universe u ~strict:false g) newus g in let fail_union s q1 q2 = if UGraph.type_in_type uctx.universes then s else CErrors.user_err Pp.(str "Could not merge universe contexts: could not unify" ++ spc() ++ Quality.raw_pr q1 ++ strbrk " and " ++ Quality.raw_pr q2 ++ str ".") in { names; local = local; univ_variables = UnivFlex.biased_union uctx.univ_variables uctx'.univ_variables; (* FIXME: merge constraints from contextset *) sort_variables = QState.union ~fail:fail_union uctx.sort_variables uctx'.sort_variables; initial_universes = declarenew uctx.initial_universes; universes = (if local == uctx.local then uctx.universes else let cstrsr = PContextSet.univ_constraints uctx'.local in merge_univ_constraints uctx cstrsr (declarenew uctx.universes)); minim_extra = extra} let context_set uctx = uctx.local let universe_context_set uctx = let us, (_, ucst) = uctx.local in us, ucst let sort_context_set uctx = let us, csts = uctx.local in (QState.undefined uctx.sort_variables, us), csts let constraints uctx = snd uctx.local let compute_instance_binders uctx inst = let (qrev, urev) = snd uctx.names in let qinst, uinst = Instance.to_array inst in let qmap = function | QVar q -> begin try Name (get_uname (QVar.Map.find q qrev)) with Not_found -> Anonymous end | QConstant _ -> assert false in let umap lvl = try Name (get_uname (Level.Map.find lvl urev)) with Not_found -> Anonymous in {quals = Array.map qmap qinst; univs = Array.map umap uinst} let context uctx = let qvars = QState.undefined uctx.sort_variables in let (uvars, (qcst, ucst)) = uctx.local in UContext.of_context_set (compute_instance_binders uctx) ((qvars, qcst), (uvars, ucst)) type named_universes_entry = universes_entry * UnivNames.universe_binders let check_mono_sort_constraints uctx = let (uvar, (qcst, ucst)) = uctx.local in (* This looks very stringent but it passes nonetheless all the tests? *) let () = assert (Sorts.ElimConstraints.is_empty qcst) in (uvar, ucst) let univ_entry ~poly uctx = let (binders, _) = uctx.names in let entry = if PolyFlags.univ_poly poly then Polymorphic_entry (context uctx) else let uctx = check_mono_sort_constraints uctx in Monomorphic_entry uctx in entry, binders type universe_opt_subst = UnivFlex.t let subst uctx = uctx.univ_variables let ugraph uctx = uctx.universes let elim_graph uctx = QState.elims uctx.sort_variables let initial_elim_graph uctx = QState.initial_elims uctx.sort_variables let is_above_prop uctx qv = QState.is_above_prop uctx.sort_variables qv let is_algebraic l uctx = UnivFlex.is_algebraic l uctx.univ_variables let of_names (ubind,(revqbind,revubind)) = let revqbind = QVar.Map.map (fun id -> { uname = Some id; uloc = None }) revqbind in let revubind = Level.Map.map (fun id -> { uname = Some id; uloc = None }) revubind in let qgraph = QVar.Map.fold (fun v _ -> QGraph.add_quality (QVar v)) revqbind QGraph.initial_graph in { empty with names = (ubind,(revqbind,revubind)); sort_variables = QState.of_elims qgraph; } let universe_of_name uctx s = UNameMap.find s (snd (fst uctx.names)) let quality_of_name uctx s = Id.Map.find s (fst (fst uctx.names)) let name_level level id uctx = let ((qbind,ubind),(qrev,urev)) = uctx.names in assert(not(Id.Map.mem id ubind)); let ubind = Id.Map.add id level ubind in let urev = Level.Map.add level { uname = Some id; uloc = None } urev in { uctx with names = ((qbind,ubind),(qrev,urev)) } let universe_binders uctx = let named, _ = uctx.names in named let nf_qvar uctx q = QState.repr q uctx.sort_variables let instantiate_variable l (b : Universe.t) v = v := UnivFlex.define l b !v exception UniversesDiffer let { Goptions.get = weak_constraints } = Goptions.declare_bool_option_and_ref ~key:["Cumulativity";"Weak";"Constraints"] ~value:true () let level_inconsistency cst l r = let mk u = Sorts.sort_of_univ @@ Universe.make u in raise (UGraph.UniverseInconsistency (None, (cst, mk l, mk r, None))) let nf_universe uctx u = UnivSubst.(subst_univs_universe (UnivFlex.normalize_univ_variable uctx.univ_variables)) u let nf_level uctx u = UnivSubst.(level_subst_of (UnivFlex.normalize_univ_variable uctx.univ_variables)) u let nf_instance uctx u = Instance.subst_fn (nf_qvar uctx, nf_level uctx) u let nf_quality uctx q = Quality.subst (nf_qvar uctx) q let nf_sort uctx s = let normalize u = nf_universe uctx u in let qnormalize q = QState.repr q uctx.sort_variables in Sorts.subst_fn (qnormalize, normalize) s let nf_relevance uctx r = match r with | Relevant | Irrelevant -> r | RelevanceVar q -> match nf_qvar uctx q with | QConstant QSProp -> Sorts.Irrelevant | QConstant QProp | QConstant QType -> Sorts.Relevant | QVar q' -> (* XXX currently not used in nf_evars_and_universes_opt_subst does it matter? *) if QState.is_above_prop uctx.sort_variables q' then Relevant else if QVar.equal q q' then r else Sorts.RelevanceVar q' let nf_universes uctx c = let lsubst = uctx.univ_variables in let nf_univ u = UnivFlex.normalize_univ_variable lsubst u in let rec self () c = match Constr.kind c with | Evar (evk, args) -> let args' = SList.Smart.map (self ()) args in if args == args' then c else Constr.mkEvar (evk, args') | _ -> UnivSubst.map_universes_opt_subst_with_binders ignore self (nf_relevance uctx) (nf_qvar uctx) nf_univ () c in self () c type small_universe = USet | UProp | USProp let is_uset = function USet -> true | UProp | USProp -> false type sort_classification = | USmall of small_universe (* Set, Prop or SProp *) | ULevel of Level.t (* Var or Global *) | UMax of Universe.t * Level.Set.t (* Max of Set, Var, Global without increments *) | UAlgebraic of Universe.t (* Arbitrary algebraic expression *) let classify s = match s with | Prop -> USmall UProp | SProp -> USmall USProp | Set -> USmall USet | Type u | QSort (_, u) -> if Universe.is_levels u then match Universe.level u with | None -> UMax (u, Universe.levels u) | Some u -> ULevel u else UAlgebraic u type local = { local_cst : PConstraints.t; local_above_prop : Level.Set.t; local_weak : UPairSet.t; local_sorts : QState.t; } let add_univ_local cst local = { local with local_cst = PConstraints.add_univ cst local.local_cst } (* Constraint with algebraic on the left and a single level on the right *) let enforce_leq_up u v local = let elim_csts = PConstraints.qualities local.local_cst in let univ_csts = UnivSubst.enforce_leq u (Universe.make v) @@ PConstraints.univs local.local_cst in { local with local_cst = PConstraints.make elim_csts univ_csts } let get_constraint = function | Conversion.CONV -> UnivConstraint.Eq | Conversion.CUMUL -> UnivConstraint.Le let warn_template = CWarnings.create_warning ~from:[CWarnings.CoreCategories.fragile] ~default:Disabled ~name:"bad-template-constraint" () let do_warn_template = CWarnings.create_in warn_template Pp.(fun (uctx,csts) -> str "Adding constraints involving global template univs:" ++ spc() ++ UnivConstraints.pr (pr_uctx_level uctx) csts ) let warn_template uctx csts = match CWarnings.warning_status warn_template with | Disabled -> () | Enabled | AsError -> let is_template u = Level.Set.mem u (template_default_univs()) in let csts = UnivConstraints.filter (fun (u,_,v as cst) -> not (Level.is_set u) && not (Level.is_set v) && (is_template u || is_template v) && not (UGraph.check_constraint uctx.universes cst)) csts in if not @@ UnivConstraints.is_empty csts then do_warn_template (uctx,csts) let unify_quality univs c s1 s2 l = let fail () = if UGraph.type_in_type univs then l.local_sorts else sort_inconsistency (get_constraint c) s1 s2 in { l with local_sorts = QState.unify_quality ~fail c (Sorts.quality s1) (Sorts.quality s2) l.local_sorts; } let process_constraints uctx cstrs = let open UnivSubst in let open UnivProblem in let univs = uctx.universes in let vars = ref uctx.univ_variables in let normalize u = UnivFlex.normalize_univ_variable !vars u in let qnormalize sorts q = QState.repr q sorts in let normalize_sort sorts s = Sorts.subst_fn ((qnormalize sorts), subst_univs_universe normalize) s in let nf_constraint sorts = function | QElimTo (a, b) -> QElimTo (Quality.subst (qnormalize sorts) a, Quality.subst (qnormalize sorts) b) | QLeq (a, b) -> QLeq (Quality.subst (qnormalize sorts) a, Quality.subst (qnormalize sorts) b) | QEq (a, b) -> QEq (Quality.subst (qnormalize sorts) a, Quality.subst (qnormalize sorts) b) | ULub (u, v) -> ULub (level_subst_of normalize u, level_subst_of normalize v) | UWeak (u, v) -> UWeak (level_subst_of normalize u, level_subst_of normalize v) | UEq (u, v) -> UEq (normalize_sort sorts u, normalize_sort sorts v) | ULe (u, v) -> ULe (normalize_sort sorts u, normalize_sort sorts v) in let is_local l = UnivFlex.mem l !vars in let equalize_small l s local = let ls = match l with | USProp -> sprop | UProp -> prop | USet -> set in if UGraph.check_eq_sort Sorts.Quality.equal univs ls s then local else if is_uset l then match classify s with | USmall _ -> sort_inconsistency Eq set s | ULevel r -> if is_local r then let () = instantiate_variable r Universe.type0 vars in add_univ_local (Level.set, Eq, r) local else sort_inconsistency Eq set s | UMax (u, _)| UAlgebraic u -> if univ_level_mem Level.set u then let inst = univ_level_rem Level.set u u in enforce_leq_up inst Level.set local else sort_inconsistency Eq ls s else sort_inconsistency Eq ls s in let equalize_variables fo l' r' local = if Level.equal l' r' then local else let () = if is_local l' then instantiate_variable l' (Universe.make r') vars else if is_local r' then instantiate_variable r' (Universe.make l') vars else if not (UnivProblem.check_eq_level univs l' r') then (* Two rigid/global levels, none of them being local, one of them being Prop/Set, disallow *) if Level.is_set l' || Level.is_set r' then level_inconsistency Eq l' r' else if fo then raise UniversesDiffer in add_univ_local (l', Eq, r') local in let equalize_algebraic l ru local = let alg = UnivFlex.is_algebraic l uctx.univ_variables in let inst = univ_level_rem l ru ru in if alg && not (Level.Set.mem l (Universe.levels inst)) then let () = instantiate_variable l inst vars in local else if univ_level_mem l ru then enforce_leq_up inst l local else sort_inconsistency Eq (sort_of_univ (Universe.make l)) (sort_of_univ ru) in let equalize_universes l r local = match classify l, classify r with | USmall l', (USmall _ | ULevel _ | UMax _ | UAlgebraic _) -> equalize_small l' r local | (ULevel _ | UMax _ | UAlgebraic _), USmall r' -> equalize_small r' l local | ULevel l', ULevel r' -> equalize_variables false l' r' local | ULevel l', (UAlgebraic r | UMax (r, _)) | (UAlgebraic r | UMax (r, _)), ULevel l' -> equalize_algebraic l' r local | (UAlgebraic _ | UMax _), (UAlgebraic _ | UMax _) -> (* both are algebraic *) if UGraph.check_eq_sort Sorts.Quality.equal univs l r then local else sort_inconsistency Eq l r in let unify_universes cst local = let cst = nf_constraint local.local_sorts cst in if UnivProblem.is_trivial cst then local else (* TODO sort_inconsistency should be able to handle raw qualities instead of having to make a dummy sort *) let mk q = Sorts.make q Universe.type0 in match cst with | QEq (a, b) -> unify_quality univs CONV (mk a) (mk b) local | QLeq (a, b) -> unify_quality univs CUMUL (mk a) (mk b) local | QElimTo (a, b) -> { local with local_cst = PConstraints.add_quality (a, ElimTo, b) local.local_cst } | ULe (l, r) -> let local = unify_quality univs CUMUL l r local in let l = normalize_sort local.local_sorts l in let r = normalize_sort local.local_sorts r in begin match classify r with | UAlgebraic _ | UMax _ -> if UGraph.check_leq_sort Sorts.Quality.equal univs l r then local else sort_inconsistency Le l r ~explain:(Pp.str "(cannot handle algebraic on the right)") | USmall r' -> (* Invariant: there are no universes u <= Set in the graph. Except for template levels, Set <= u anyways. Otherwise, for template levels, any constraint u <= Set is turned into u := Set. *) if UGraph.type_in_type univs then local else begin match classify l with | UAlgebraic _ -> (* l contains a +1 and r=r' small so l <= r impossible *) sort_inconsistency Le l r | USmall l' -> if UGraph.check_leq_sort Sorts.Quality.equal univs l r then local else sort_inconsistency Le l r | ULevel l' -> if is_uset r' && is_local l' then (* Unbounded universe constrained from above, we equalize it *) let () = instantiate_variable l' Universe.type0 vars in add_univ_local (l', Eq, Level.set) local else sort_inconsistency Le l r | UMax (_, levels) -> if is_uset r' then let fold l' local = let l = sort_of_univ @@ Universe.make l' in if Level.is_set l' || is_local l' then equalize_variables false l' Level.set local else sort_inconsistency Le l r in Level.Set.fold fold levels local else sort_inconsistency Le l r end | ULevel r' -> (* We insert the constraint in the graph even if the graph already contains it. Indeed, checking the existence of the constraint is costly when the constraint does not already exist directly as a single edge in the graph, but adding an edge in the graph which is implied by others is cheap. Hence, by doing this, we avoid a costly check here, and make further checks of this constraint easier since it will exist directly in the graph. *) match classify l with | USmall UProp -> { local with local_above_prop = Level.Set.add r' local.local_above_prop } | USmall USProp -> if UGraph.type_in_type univs then local else sort_inconsistency Le l r | USmall USet -> add_univ_local (Level.set, Le, r') local | ULevel l' -> add_univ_local (l', Le, r') local | UAlgebraic l -> enforce_leq_up l r' local | UMax (_, l) -> Univ.Level.Set.fold (fun l' accu -> add_univ_local (l', Le, r') accu) l local end | ULub (l, r) -> equalize_variables true l r local | UWeak (l, r) -> if weak_constraints () then { local with local_weak = UPairSet.add (l, r) local.local_weak } else local | UEq (l, r) -> let local = unify_quality univs CONV l r local in let l = normalize_sort local.local_sorts l in let r = normalize_sort local.local_sorts r in equalize_universes l r local in let unify_universes cst local = if not (UGraph.type_in_type univs) then unify_universes cst local else try unify_universes cst local with UGraph.UniverseInconsistency _ -> local in let local = { local_cst = PConstraints.empty; local_weak = uctx.minim_extra.UnivMinim.weak_constraints; local_above_prop = uctx.minim_extra.UnivMinim.above_prop; local_sorts = uctx.sort_variables; } in let local = UnivProblem.Set.fold unify_universes cstrs local in let extra = { UnivMinim.above_prop = local.local_above_prop; UnivMinim.weak_constraints = local.local_weak } in let () = warn_template uctx (PConstraints.univs local.local_cst) in !vars, extra, local.local_cst, local.local_sorts let add_constraints ?src uctx cstrs = let univs, local = uctx.local in let vars, extra, local', sorts = process_constraints uctx cstrs in { uctx with local = (univs, PConstraints.union local local'); univ_variables = vars; universes = merge_univ_constraints uctx (PConstraints.univs local') uctx.universes; sort_variables = QState.merge_constraints (merge_elim_constraints ?src uctx (PConstraints.qualities local')) sorts ; minim_extra = extra; } let problem_of_univ_constraints cstrs = UnivConstraints.fold (fun (l,d,r) acc -> let l = Universe.make l and r = sort_of_univ @@ Universe.make r in let cstr' = let open UnivProblem in match d with | Lt -> ULe (sort_of_univ @@ Universe.super l, r) | Le -> ULe (sort_of_univ l, r) | Eq -> UEq (sort_of_univ l, r) in UnivProblem.Set.add cstr' acc) cstrs UnivProblem.Set.empty let problem_of_elim_constraints cstrs = ElimConstraints.fold (fun (l, k, r) pbs -> let open ElimConstraint in match k with | ElimTo -> UnivProblem.Set.add (QElimTo (l, r)) pbs) cstrs UnivProblem.Set.empty let add_univ_constraints uctx cstrs = let cstrs = problem_of_univ_constraints cstrs in add_constraints ~src:Static uctx cstrs let add_poly_constraints ?src uctx (qcstrs, ucstrs) = let lvl_pbs = problem_of_univ_constraints ucstrs in let elim_pbs = problem_of_elim_constraints qcstrs in let uctx = add_constraints ?src uctx (UnivProblem.Set.union lvl_pbs elim_pbs) in let local = on_snd (fun cst -> PConstraints.union cst (PConstraints.of_qualities qcstrs)) uctx.local in let sort_variables = QState.merge_constraints (fun cst -> merge_elim_constraints ?src uctx qcstrs cst) uctx.sort_variables in { uctx with local; sort_variables } let check_elim_constraints uctx csts = Sorts.ElimConstraints.for_all (fun (l,k,r) -> let l = nf_quality uctx l in let r = nf_quality uctx r in match l,k,r with | _, ElimTo, _ -> Inductive.eliminates_to (QState.elims uctx.sort_variables) l r) csts let check_eq_quality uctx q1 q2 = Sorts.Quality.equal q1 q2 || Sorts.Quality.equal (nf_quality uctx q1) (nf_quality uctx q2) let check_constraint uctx (c:UnivProblem.t) = match c with | QEq (a,b) -> let a = nf_quality uctx a in let b = nf_quality uctx b in Quality.equal a b | QLeq (a,b) -> let a = nf_quality uctx a in let b = nf_quality uctx b in Quality.equal a b || begin match a, b with | QConstant QProp, QConstant QType -> true | QConstant QProp, QVar q -> QState.is_above_prop uctx.sort_variables q | (QConstant _ | QVar _), _ -> false end | QElimTo (a, b) -> let a = nf_quality uctx a in let b = nf_quality uctx b in Inductive.eliminates_to (QState.elims uctx.sort_variables) a b | ULe (u,v) -> UGraph.check_leq_sort (fun q1 q2 -> check_eq_quality uctx q1 q2) uctx.universes u v | UEq (u,v) -> UGraph.check_eq_sort (fun q1 q2 -> check_eq_quality uctx q1 q2) uctx.universes u v | ULub (u,v) -> UGraph.check_eq_level uctx.universes u v | UWeak _ -> true let check_constraints uctx csts = UnivProblem.Set.for_all (check_constraint uctx) csts let constrain_variables diff uctx = let (us, (qcst, ucst)) = uctx.local in let (us, ucst), vars = UnivFlex.constrain_variables diff uctx.univ_variables (us, ucst) in { uctx with local = (us, (qcst, ucst)); univ_variables = vars } type ('a, 'b, 'c, 'd) gen_universe_decl = { univdecl_qualities : 'a; univdecl_extensible_qualities : bool; univdecl_elim_constraints : 'b; univdecl_instance : 'c; (* Declared universes *) univdecl_extensible_instance : bool; (* Can new universes be added *) univdecl_univ_constraints : 'd; (* Declared univ constraints *) univdecl_extensible_constraints : bool; (* Can new constraints (elim or univ) be added *) } type universe_decl = (QVar.t list, Sorts.ElimConstraints.t, Level.t list, Univ.UnivConstraints.t) gen_universe_decl let default_univ_decl = { univdecl_qualities = []; (* in practice non named qualities will get collapsed for toplevel definitions, but side effects see named qualities from the surrounding definitions while using default_univ_decl *) univdecl_extensible_qualities = true; univdecl_elim_constraints = ElimConstraints.empty; univdecl_instance = []; univdecl_extensible_instance = true; univdecl_univ_constraints = UnivConstraints.empty; univdecl_extensible_constraints = true } let univ_decl_csts decl = PConstraints.make decl.univdecl_elim_constraints decl.univdecl_univ_constraints let pr_error_unbound_universes quals univs names = let open Pp in let nqs = QVar.Set.cardinal quals in let prqvar q = let info = QVar.Map.find_opt q (fst (snd names)) in h (pr_uctx_qvar_names names q ++ (match info with | None | Some {uloc=None} -> mt () | Some {uloc=Some loc} -> spc() ++ str"(" ++ Loc.pr loc ++ str")")) in let nus = Level.Set.cardinal univs in let prlev u = let info = Level.Map.find_opt u (snd (snd names)) in h (pr_uctx_level_names names u ++ (match info with | None | Some {uloc=None} -> mt () | Some {uloc=Some loc} -> spc() ++ str"(" ++ Loc.pr loc ++ str")")) in let ppqs = if nqs > 0 then str (if nqs = 1 then "Quality" else "Qualities") ++ spc () ++ prlist_with_sep spc prqvar (QVar.Set.elements quals) else mt() in let ppus = if nus > 0 then let universe_s = CString.plural nus "universe" in let universe_s = if nqs = 0 then CString.capitalize_ascii universe_s else universe_s in str universe_s ++ spc () ++ prlist_with_sep spc prlev (Level.Set.elements univs) else mt() in (hv 0 (ppqs ++ (if nqs > 0 && nus > 0 then strbrk " and " else mt()) ++ ppus ++ spc () ++ str (CString.conjugate_verb_to_be (nus + nqs)) ++ str" unbound.")) exception UnboundUnivs of QVar.Set.t * Level.Set.t * univ_names (* XXX when we have multi location errors we won't have to pick an arbitrary error *) let error_unbound_universes qs us uctx = let exception Found of Loc.t in let loc = try Level.Set.iter (fun u -> match Level.Map.find_opt u (snd (snd uctx)) with | None -> () | Some info -> match info.uloc with | None -> () | Some loc -> raise_notrace (Found loc)) us; QVar.Set.iter (fun s -> match QVar.Map.find_opt s (fst (snd uctx)) with | None -> () | Some info -> match info.uloc with | None -> () | Some loc -> raise_notrace (Found loc)) qs; None with Found loc -> Some loc in Loc.raise ?loc (UnboundUnivs (qs,us,uctx)) let () = CErrors.register_handler (function | UnboundUnivs (qs,us,uctx) -> Some (pr_error_unbound_universes qs us uctx) | _ -> None) let universe_context_inst decl qvars levels names = let leftqs = List.fold_left (fun acc l -> QSet.remove l acc) qvars decl.univdecl_qualities in let leftus = List.fold_left (fun acc l -> Level.Set.remove l acc) levels decl.univdecl_instance in let () = let unboundqs = if decl.univdecl_extensible_qualities then QSet.empty else leftqs in let unboundus = if decl.univdecl_extensible_instance then Level.Set.empty else leftus in if not (QSet.is_empty unboundqs && Level.Set.is_empty unboundus) then error_unbound_universes unboundqs unboundus names in let leftqs = UContext.sort_qualities (Array.map_of_list (fun q -> Quality.QVar q) (QVar.Set.elements leftqs)) in let leftus = UContext.sort_levels (Array.of_list (Level.Set.elements leftus)) in let instq = Array.append (Array.map_of_list (fun q -> QVar q) decl.univdecl_qualities) leftqs in let instu = Array.append (Array.of_list decl.univdecl_instance) leftus in let inst = Instance.of_array (instq,instu) in inst let check_universe_context_set ~prefix levels names = let left = List.fold_left (fun left l -> Level.Set.remove l left) levels prefix in if not (Level.Set.is_empty left) then error_unbound_universes QVar.Set.empty left names let check_univ_implication uctx cstrs cstrs' = let gr = uctx.initial_universes in let grext = merge_univ_constraints uctx cstrs gr in let cstrs' = UnivConstraints.filter (fun c -> not (UGraph.check_constraint grext c)) cstrs' in if UnivConstraints.is_empty cstrs' then () else CErrors.user_err Pp.(str "Universe constraints are not implied by the ones declared: " ++ UnivConstraints.pr (pr_uctx_level uctx) cstrs') let check_elim_implication uctx cstrs cstrs' = let g = initial_elim_graph uctx in let grext = merge_elim_constraints ~src:Rigid uctx cstrs g in let cstrs' = ElimConstraints.filter (fun c -> not (QGraph.check_constraint grext c)) cstrs' in if ElimConstraints.is_empty cstrs' then () else CErrors.user_err Pp.(str "Elimination constraints are not implied by the ones declared: " ++ ElimConstraints.pr (pr_uctx_qvar uctx) cstrs') let check_implication uctx (elim_csts,univ_csts) (elim_csts',univ_csts') = check_univ_implication uctx univ_csts univ_csts'; check_elim_implication uctx elim_csts elim_csts' let check_template_univ_decl uctx ~template_qvars decl = let () = match List.filter (fun q -> not @@ QSet.mem q template_qvars) decl.univdecl_qualities with | (_ :: _) as qvars -> CErrors.user_err Pp.(str "Qualities " ++ prlist_with_sep spc (pr_uctx_qvar uctx) qvars ++ str " cannot be template.") | [] -> if not (QVar.Set.equal template_qvars (QState.undefined uctx.sort_variables)) then CErrors.anomaly Pp.(str "Bugged template univ declaration.") in (* XXX: when the kernel takes template entries closer to the polymorphic ones, we should perform some additional checks here. *) let () = assert (Sorts.ElimConstraints.is_empty decl.univdecl_elim_constraints) in let levels, csts = uctx.local in let () = let prefix = decl.univdecl_instance in if not decl.univdecl_extensible_instance then check_universe_context_set ~prefix levels uctx.names in if decl.univdecl_extensible_constraints then PContextSet.univ_context_set uctx.local else let () = check_implication uctx (univ_decl_csts decl) csts in (levels, decl.univdecl_univ_constraints) let check_mono_univ_decl uctx decl = (* Note: if [decl] is [default_univ_decl], behave like [uctx.local] *) let () = if not (List.is_empty decl.univdecl_qualities) || not (QSet.is_empty (QState.undefined uctx.sort_variables)) then CErrors.user_err Pp.(str "Monomorphic declarations may not have sort variables.") in let levels, csts = uctx.local in let () = let prefix = decl.univdecl_instance in if not decl.univdecl_extensible_instance then check_universe_context_set ~prefix levels uctx.names in if decl.univdecl_extensible_constraints then check_mono_sort_constraints uctx else let () = assert (Sorts.ElimConstraints.is_empty (fst csts)) in let () = check_implication uctx (univ_decl_csts decl) csts in levels, decl.univdecl_univ_constraints let check_poly_univ_decl uctx decl = (* Note: if [decl] is [default_univ_decl], behave like [context uctx] *) let levels, (elim_csts,univ_csts) = uctx.local in let qvars = QState.undefined uctx.sort_variables in let inst = universe_context_inst decl qvars levels uctx.names in let nas = compute_instance_binders uctx inst in let univ_csts = if decl.univdecl_extensible_constraints then univ_csts else begin check_univ_implication uctx decl.univdecl_univ_constraints univ_csts; decl.univdecl_univ_constraints end in let elim_csts = if decl.univdecl_extensible_constraints then elim_csts else begin check_elim_implication uctx decl.univdecl_elim_constraints elim_csts; decl.univdecl_elim_constraints end in let uctx = UContext.make nas (inst, (elim_csts,univ_csts)) in uctx let check_univ_decl ~poly uctx decl = let (binders, _) = uctx.names in let entry = if PolyFlags.univ_poly poly then Polymorphic_entry (check_poly_univ_decl uctx decl) else Monomorphic_entry (check_mono_univ_decl uctx decl) in entry, binders let restrict_universe_context (univs, univ_csts) keep = let removed = Level.Set.diff univs keep in if Level.Set.is_empty removed then univs, univ_csts else let allunivs = UnivConstraints.fold (fun (u,_,v) all -> Level.Set.add u (Level.Set.add v all)) univ_csts univs in let g = UGraph.initial_universes in let g = Level.Set.fold (fun v g -> if Level.is_set v then g else UGraph.add_universe v ~strict:false g) allunivs g in let g = UGraph.merge_constraints univ_csts g in let allkept = Level.Set.union (UGraph.domain UGraph.initial_universes) (Level.Set.diff allunivs removed) in let univ_csts = UGraph.constraints_for ~kept:allkept g in let univ_csts = UnivConstraints.filter (fun (l,d,r) -> not (Level.is_set l && d == Le)) univ_csts in (Level.Set.inter univs keep, univ_csts) let restrict_universe_pcontext (us, (qcst, ucst)) keep = let (us, ucst) = restrict_universe_context (us, ucst) keep in (us, (qcst, ucst)) let restrict uctx vars = let vars = Id.Map.fold (fun na l vars -> Level.Set.add l vars) (snd (fst uctx.names)) vars in let uctx' = restrict_universe_pcontext uctx.local vars in { uctx with local = uctx' } let restrict_even_binders uctx vars = let uctx' = restrict_universe_pcontext uctx.local vars in { uctx with local = uctx' } let restrict_univ_constraints uctx csts = let levels, (elim_csts,univ_csts) = uctx.local in let uctx' = { uctx with local = (levels,(elim_csts,UnivConstraints.empty)); universes = uctx.initial_universes } in add_univ_constraints uctx' csts let restrict_elim_constraints ?src uctx csts = let levels, (elim_csts,univ_csts) = uctx.local in let g = initial_elim_graph uctx in (* XXX we are wreaking havoc with elimination constraints *) let sort_variables = QState.set_elims g uctx.sort_variables in let sort_variables = QState.merge_constraints (fun cst -> merge_elim_constraints ?src uctx elim_csts cst) sort_variables in { uctx with local = (levels, (csts, univ_csts)); sort_variables } type rigid = | UnivRigid | UnivFlexible of bool (** Is substitution by an algebraic ok? *) let univ_rigid = UnivRigid let univ_flexible = UnivFlexible false let univ_flexible_alg = UnivFlexible true (** ~sideff indicates that it is ok to redeclare a universe. Also merges the universe context in the local constraint structures and not only in the graph. *) let merge_universe_context ?loc ~sideff rigid uctx (levels, ucst) = let declare g = Level.Set.fold (fun u g -> try UGraph.add_universe ~strict:false u g with UGraph.AlreadyDeclared when sideff -> g) levels g in let names = let fold u accu = let update = function | None -> Some { uname = None; uloc = loc } | Some info -> match info.uloc with | None -> Some { info with uloc = loc } | Some _ -> Some info in Level.Map.update u update accu in (fst uctx.names, (fst (snd uctx.names), Level.Set.fold fold levels (snd (snd uctx.names)))) in let initial = declare uctx.initial_universes in let univs = declare uctx.universes in let universes = merge_univ_constraints uctx ucst univs in let uctx = match rigid with | UnivRigid -> uctx | UnivFlexible b -> assert (not sideff); let uvars' = UnivFlex.add_levels levels ~algebraic:b uctx.univ_variables in { uctx with univ_variables = uvars' } in let (us, (qcst, ucst0)) = uctx.local in let local = (Univ.Level.Set.union us levels, (qcst, Univ.UnivConstraints.union ucst0 ucst)) in { uctx with names; local; universes; initial_universes = initial } let merge_sort_variables ?loc ?(sort_rigid=false) ?src ~sideff uctx (qvars, csts) = let sort_variables = QVar.Set.fold (fun qv qstate -> QState.add ~check_fresh:(not sideff) ~rigid:sort_rigid qv qstate) qvars uctx.sort_variables in let names = let fold u accu = let update = function | None -> Some { uname = None; uloc = loc } | Some info -> match info.uloc with | None -> Some { info with uloc = loc } | Some _ -> Some info in QVar.Map.update u update accu in let qrev = QVar.Set.fold fold qvars (fst (snd uctx.names)) in (fst uctx.names, (qrev, snd (snd uctx.names))) in let sort_variables = QState.merge_constraints (merge_elim_constraints ?src uctx csts) sort_variables in let (us, (qcst, ucst)) = uctx.local in let local = (us, (Sorts.ElimConstraints.union qcst csts, ucst)) in { uctx with local; sort_variables; names } let merge_sort_context ?loc ?sort_rigid ?src ~sideff rigid uctx ((qvars, levels), (qcst, ucst)) = let uctx = merge_sort_variables ?loc ?sort_rigid ?src ~sideff uctx (qvars, qcst) in merge_universe_context ?loc ~sideff rigid uctx (levels, ucst) let demote_global_univs (lvl_set, univ_csts) uctx = let (local_univs, local_constraints) = uctx.local in let local_univs = Level.Set.diff local_univs lvl_set in let univ_variables = Level.Set.fold UnivFlex.remove lvl_set uctx.univ_variables in let update_ugraph g = let g = Level.Set.fold (fun u g -> try UGraph.add_universe u ~strict:true g with UGraph.AlreadyDeclared -> g) lvl_set g in UGraph.merge_constraints univ_csts g in let initial_universes = update_ugraph uctx.initial_universes in let universes = update_ugraph uctx.universes in { uctx with local = (local_univs, local_constraints); univ_variables; universes; initial_universes } let demote_global_univ_entry entry uctx = match entry with | Monomorphic_entry ucst -> demote_global_univs ucst uctx | Polymorphic_entry _ -> uctx (* Check bug_4363 bug_6323 bug_3539 and success/rewrite lemma l1 for quick feedback when changing this code *) let emit_side_effects eff u = let uctx = Safe_typing.universes_of_private eff in demote_global_univs uctx u let merge_seff uctx uctx' = let levels = PContextSet.levels uctx' in let declare g = Level.Set.fold (fun u g -> try UGraph.add_universe ~strict:false u g with UGraph.AlreadyDeclared -> g) levels g in let initial_universes = declare uctx.initial_universes in let univs = declare uctx.universes in let universes = merge_univ_constraints uctx (PContextSet.univ_constraints uctx') univs in { uctx with universes; initial_universes } let update_sigma_univs uctx univs = let eunivs = { uctx with initial_universes = univs; universes = univs } in merge_seff eunivs eunivs.local let add_qnames ?loc s l ((qnames,unames), (qnames_rev,unames_rev)) = if Id.Map.mem s qnames then user_err ?loc Pp.(str "Quality " ++ Id.print s ++ str" already bound."); ((Id.Map.add s l qnames, unames), (QVar.Map.add l { uname = Some s; uloc = loc } qnames_rev, unames_rev)) let add_names ?loc s l ((qnames,unames), (qnames_rev,unames_rev)) = if UNameMap.mem s unames then user_err ?loc Pp.(str "Universe " ++ Id.print s ++ str" already bound."); ((qnames,UNameMap.add s l unames), (qnames_rev, Level.Map.add l { uname = Some s; uloc = loc } unames_rev)) let add_qloc l loc (names, (qnames_rev,unames_rev) as orig) = match loc with | None -> orig | Some _ -> (names, (QVar.Map.add l { uname = None; uloc = loc } qnames_rev, unames_rev)) let add_loc l loc (names, (qnames_rev,unames_rev) as orig) = match loc with | None -> orig | Some _ -> (names, (qnames_rev, Level.Map.add l { uname = None; uloc = loc } unames_rev)) let add_universe ?loc name strict uctx u = let initial_universes = UGraph.add_universe ~strict u uctx.initial_universes in let universes = UGraph.add_universe ~strict u uctx.universes in let local = PContextSet.add_level u uctx.local in let names = match name with | Some n -> add_names ?loc n u uctx.names | None -> add_loc u loc uctx.names in { uctx with names; local; initial_universes; universes } let new_sort_variable ?loc ?(sort_rigid = false) ?name uctx = let q = UnivGen.fresh_sort_quality () in (* don't need to check_fresh as it's guaranteed new *) let sort_variables = QState.add ~check_fresh:false ~rigid:(sort_rigid || Option.has_some name) q uctx.sort_variables in let names = match name with | Some n -> add_qnames ?loc n q uctx.names | None -> add_qloc q loc uctx.names in { uctx with sort_variables; names }, q let new_univ_variable ?loc rigid name uctx = let u = UnivGen.fresh_level () in let uctx = match rigid with | UnivRigid -> uctx | UnivFlexible algebraic -> let univ_variables = UnivFlex.add u ~algebraic uctx.univ_variables in { uctx with univ_variables } in let uctx = add_universe ?loc name false uctx u in uctx, u let add_forgotten_univ uctx u = add_universe None true uctx u let make_with_initial_binders ~qualities univs binders = let uctx = make ~qualities univs in List.fold_left (fun uctx { CAst.loc; v = id } -> fst (new_univ_variable ?loc univ_rigid (Some id) uctx)) uctx binders let from_env ?(binders=[]) env = make_with_initial_binders ~qualities:(Environ.qualities env) (Environ.universes env) binders let make_nonalgebraic_variable uctx u = { uctx with univ_variables = UnivFlex.make_nonalgebraic_variable uctx.univ_variables u } let make_flexible_nonalgebraic uctx = { uctx with univ_variables = UnivFlex.make_all_undefined_nonalgebraic uctx.univ_variables } let subst_univs_context_with_def def usubst (uctx, (elim_csts,univ_csts)) = (Level.Set.diff uctx def, PConstraints.make elim_csts @@ UnivSubst.subst_univs_constraints usubst univ_csts) let normalize_univ_variables uctx = let normalized_variables, def, subst = UnivFlex.normalize_univ_variables uctx.univ_variables in let uctx_local = subst_univs_context_with_def def subst uctx.local in let univs = UGraph.merge_constraints (snd (snd uctx_local)) uctx.initial_universes in { uctx with local = uctx_local; univ_variables = normalized_variables; universes = univs } let normalize_quality_variables uctx = let (lvls, (elim_cstrs, lvl_cstrs)) = uctx.local in let elim_cstrs = QState.normalize_elim_constraints uctx.sort_variables elim_cstrs in { uctx with local = (lvls, (elim_cstrs, lvl_cstrs)) } let normalize_variables uctx = let uctx = normalize_univ_variables uctx in normalize_quality_variables uctx let fix_undefined_variables uctx = { uctx with univ_variables = UnivFlex.fix_undefined_variables uctx.univ_variables } let collapse_above_prop_sort_variables ~to_prop uctx = let sorts = QState.collapse_above_prop ~to_prop uctx.sort_variables in normalize_quality_variables { uctx with sort_variables = sorts } let collapse_sort_variables ?except uctx = let sorts = QState.collapse ?except uctx.sort_variables in normalize_quality_variables { uctx with sort_variables = sorts } let minimize uctx = let open UnivMinim in let (us, (qcst, ucst)) = uctx.local in let (vars', (us', ucst')) = normalize_context_set uctx.universes (us, ucst) uctx.univ_variables uctx.minim_extra in if Univ.ContextSet.equal (us', ucst') (us, ucst) then uctx else let universes = UGraph.merge_constraints ucst' uctx.initial_universes in { names = uctx.names; local = (us', (qcst, ucst')); univ_variables = vars'; sort_variables = uctx.sort_variables; universes = universes; initial_universes = uctx.initial_universes; minim_extra = UnivMinim.empty_extra; (* weak constraints are consumed *) } let universe_context_inst_decl decl qvars levels names = let leftqs = List.fold_left (fun acc l -> QSet.remove l acc) qvars decl.univdecl_qualities in let leftus = List.fold_left (fun acc l -> Level.Set.remove l acc) levels decl.univdecl_instance in let () = let unboundqs = if decl.univdecl_extensible_qualities then QSet.empty else leftqs in let unboundus = if decl.univdecl_extensible_instance then Level.Set.empty else leftus in if not (QSet.is_empty unboundqs && Level.Set.is_empty unboundus) then error_unbound_universes unboundqs unboundus names in let instq = Array.map_of_list (fun q -> QVar q) decl.univdecl_qualities in let instu = Array.of_list decl.univdecl_instance in let inst = Instance.of_array (instq,instu) in inst let check_univ_decl_rev uctx decl = let levels, (elim_csts,univ_csts as csts) = uctx.local in let qvars = QState.undefined uctx.sort_variables in let inst = universe_context_inst_decl decl qvars levels uctx.names in let nas = compute_instance_binders uctx inst in let () = check_implication uctx csts (univ_decl_csts decl) in let uctx = fix_undefined_variables uctx in let uctx, univ_csts = if decl.univdecl_extensible_constraints then uctx, univ_csts else restrict_univ_constraints uctx decl.univdecl_univ_constraints, univ_csts in let uctx, elim_csts = if decl.univdecl_extensible_constraints then uctx, elim_csts else restrict_elim_constraints ~src:Rigid uctx decl.univdecl_elim_constraints, elim_csts in let uctx' = UContext.make nas (inst, (elim_csts,univ_csts)) in uctx, uctx' let check_uctx_impl ~fail uctx uctx' = let levels, (elim_csts,univ_csts) = uctx'.local in let qvars_diff = QVar.Set.diff (QState.undefined uctx'.sort_variables) (QState.undefined uctx.sort_variables) in let levels_diff = Level.Set.diff levels (fst uctx.local) in let () = if not @@ (QVar.Set.is_empty qvars_diff && Level.Set.is_empty levels_diff) then error_unbound_universes qvars_diff levels_diff uctx'.names in let () = let grext = ugraph uctx in let cstrs' = UnivConstraints.filter (fun c -> not (UGraph.check_constraint grext c)) univ_csts in if UnivConstraints.is_empty cstrs' then () else fail (UnivConstraints.pr (pr_uctx_level uctx) cstrs') in let () = let grext = elim_graph uctx in let cstrs' = ElimConstraints.filter (fun c -> not (QGraph.check_constraint grext c)) elim_csts in if ElimConstraints.is_empty cstrs' then () else fail (ElimConstraints.pr (pr_uctx_qvar uctx) cstrs') in () (* XXX print above_prop too *) let pr_weak prl {minim_extra={UnivMinim.weak_constraints=weak; above_prop}} = let open Pp in v 0 ( prlist_with_sep cut (fun (u,v) -> h (prl u ++ str " ~ " ++ prl v)) (UPairSet.elements weak) ++ if UPairSet.is_empty weak || Level.Set.is_empty above_prop then mt() else cut () ++ prlist_with_sep cut (fun u -> h (str "Prop <= " ++ prl u)) (Level.Set.elements above_prop)) let pr_sort_opt_subst uctx = QState.pr (qualid_of_qvar_names uctx.names) uctx.sort_variables let pr ctx = let open Pp in let prl = pr_uctx_level ctx in let prq = pr_uctx_qvar ctx in if is_empty ctx then mt () else v 0 (str"UNIVERSES:"++brk(0,1)++ h (PContextSet.pr prq prl (context_set ctx)) ++ fnl () ++ UnivFlex.pr prl (subst ctx) ++ fnl() ++ str"SORTS:"++brk(0,1)++ h (pr_sort_opt_subst ctx) ++ fnl() ++ str "WEAK CONSTRAINTS:"++brk(0,1)++ h (pr_weak prl ctx) ++ fnl ()) module Internal = struct let reboot env uctx = let uctx_global = from_env env in { uctx_global with univ_variables = uctx.univ_variables; sort_variables = uctx.sort_variables } end rocq-9.2.0/engine/uState.mli000066400000000000000000000247661516144147600157330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* UGraph.t -> t [@@ocaml.deprecated "(8.13) Use from_env"] val make_with_initial_binders : qualities:QGraph.t -> UGraph.t -> lident list -> t [@@ocaml.deprecated "(8.13) Use from_env"] val from_env : ?binders:lident list -> Environ.env -> t (** Main entry point at the beginning of a declaration declaring the binding names as rigid universes. *) val of_names : (UnivNames.universe_binders * UnivNames.rev_binders) -> t (** Main entry point when only names matter, e.g. for printing. *) (** Misc *) val is_empty : t -> bool val union : t -> t -> t (** {5 Projections and other destructors} *) val universe_context_set : t -> Univ.ContextSet.t val sort_context_set : t -> UnivGen.sort_context_set (** The local context of the state, i.e. a set of bound variables together with their associated constraints. *) type universe_opt_subst = UnivFlex.t (* Reexport because UnivSubst is private *) val subst : t -> UnivFlex.t (** The local universes that are unification variables *) val nf_universes : t -> Constr.t -> Constr.t (** Apply the local substitution [subst] *) val ugraph : t -> UGraph.t (** The current graph extended with the local constraints *) val elim_graph : t -> QGraph.t (** The elimination graph for above prop variables *) val is_above_prop : t -> Sorts.QVar.t -> bool val is_algebraic : Level.t -> t -> bool (** Can this universe be instantiated with an algebraic universe (ie it appears in inferred types only). *) val constraints : t -> PConstraints.t (** Shorthand for {!context_set} composed with {!ContextSet.constraints}. *) val context : t -> UVars.UContext.t (** Shorthand for {!context_set} with {!Context_set.to_context}. *) type named_universes_entry = universes_entry * UnivNames.universe_binders val univ_entry : poly:PolyFlags.t -> t -> named_universes_entry (** Pick from {!context} or {!context_set} based on [poly]. *) val universe_binders : t -> UnivNames.universe_binders (** Return local names of universes. *) val compute_instance_binders : t -> UVars.Instance.t -> UVars.bound_names val nf_qvar : t -> QVar.t -> Quality.t (** Returns the normal form of the sort variable. *) val nf_quality : t -> Quality.t -> Quality.t val nf_instance : t -> UVars.Instance.t -> UVars.Instance.t val nf_level : t -> Level.t -> Level.t (** Must not be allowed to be algebraic *) val nf_universe : t -> Universe.t -> Universe.t val nf_sort : t -> Sorts.t -> Sorts.t (** Returns the normal form of the sort. *) val nf_relevance : t -> relevance -> relevance (** Returns the normal form of the relevance. *) (** {5 UnivConstraints handling} *) type constraint_source = | Internal | Rigid | Static (** On an [Internal] enforcement, checks whether a path is created between two ground/global sorts. The [Rigid] [constraint_source] should be used for constraints entered by the user. It allows to create paths between ground/global sorts, but disables path creation between two ground sorts. No additional check is performed on a [Static] constraint. *) val add_univ_constraints : t -> Univ.UnivConstraints.t -> t (** @raise UniversesDiffer when universes differ *) val add_poly_constraints : ?src:constraint_source -> t -> PConstraints.t -> t val add_constraints : ?src:constraint_source -> t -> UnivProblem.Set.t -> t (** @raise UniversesDiffer when universes differ *) val check_elim_constraints : t -> ElimConstraints.t -> bool val check_constraints : t -> UnivProblem.Set.t -> bool val check_eq_quality : t -> Sorts.Quality.t -> Sorts.Quality.t -> bool (** {5 Names} *) val quality_of_name : t -> Id.t -> Sorts.QVar.t val universe_of_name : t -> Id.t -> Univ.Level.t (** Retrieve the universe associated to the name. *) val name_level : Univ.Level.t -> Id.t -> t -> t (** Gives a name to the level (making it a binder). Asserts the name is not already used by a level *) (** {5 Unification} *) (** [restrict_universe_context (univs,csts) keep] restricts [univs] to the universes in [keep]. The constraints [csts] are adjusted so that transitive constraints between remaining universes (those in [keep] and those not in [univs]) are preserved. *) val restrict_universe_context : Univ.ContextSet.t -> Level.Set.t -> Univ.ContextSet.t (** [restrict uctx ctx] restricts the local universes of [uctx] to [ctx] extended by local named universes and side effect universes (from [demote_seff_univs]). Transitive constraints between retained universes are preserved. *) val restrict : t -> Univ.Level.Set.t -> t (** [restrict_even_binders uctx ctx] restricts the local universes of [uctx] to [ctx] extended by side effect universes (from [demote_seff_univs]). Transitive constraints between retained universes are preserved. *) val restrict_even_binders : t -> Univ.Level.Set.t -> t type rigid = | UnivRigid | UnivFlexible of bool (** Is substitution by an algebraic ok? *) val univ_rigid : rigid val univ_flexible : rigid val univ_flexible_alg : rigid val merge_sort_context : ?loc:Loc.t -> ?sort_rigid:bool -> ?src:constraint_source -> sideff:bool -> rigid -> t -> UnivGen.sort_context_set -> t val merge_universe_context : ?loc:Loc.t -> sideff:bool -> rigid -> t -> Univ.ContextSet.t -> t val demote_global_univs : Univ.ContextSet.t -> t -> t (** After declaring global universes, call this if you want to keep using the UState. Removes from the uctx_local part of the UState the universes that are present in the input constraint set (supposedly the global ones), and adds any new universes and constraints to the UGraph part of the UState. *) val demote_global_univ_entry : universes_entry -> t -> t (** After declaring a global, call this with its universe entry if you want to keep using the ustate instead of restarting it with [from_env (Global.env())] or using the slow [update_sigma_univs _ (Environ.universes (Global/env()))]. Equivalently: - In the monomorphic case, call [demote_global_univs] on the contextset. - In the polymorphic case, do nothing. *) val emit_side_effects : Safe_typing.private_constants -> t -> t (** Calls [demote_global_univs] for the private constant universes. *) val new_sort_variable : ?loc:Loc.t -> ?sort_rigid:bool -> ?name:Id.t -> t -> t * QVar.t (** Declare a new local sort. *) val new_univ_variable : ?loc:Loc.t -> rigid -> Id.t option -> t -> t * Univ.Level.t (** Declare a new local universe; use rigid if a global or bound universe; use flexible for a universe existential variable; use univ_flexible_alg for a universe existential variable allowed to be instantiated with an algebraic universe *) val add_forgotten_univ : t -> Univ.Level.t -> t (** Don't use this, it only exists for funind *) val make_nonalgebraic_variable : t -> Univ.Level.t -> t (** cf UnivFlex *) val make_flexible_nonalgebraic : t -> t (** cf UnivFlex *) val normalize_variables : t -> t val constrain_variables : Univ.Level.Set.t -> t -> t val fix_undefined_variables : t -> t (** cf UnivFlex *) (** Universe minimization *) val minimize : t -> t val collapse_above_prop_sort_variables : to_prop:bool -> t -> t val collapse_sort_variables : ?except:QVar.Set.t -> t -> t type ('a, 'b, 'c, 'd) gen_universe_decl = { univdecl_qualities : 'a; univdecl_extensible_qualities : bool; univdecl_elim_constraints : 'b; univdecl_instance : 'c; (* Declared universes *) univdecl_extensible_instance : bool; (* Can new universes be added *) univdecl_univ_constraints : 'd; (* Declared univ constraints *) univdecl_extensible_constraints : bool; (* Can new constraints (elim or univ) be added *) } type universe_decl = (QVar.t list, Sorts.ElimConstraints.t, Level.t list, Univ.UnivConstraints.t) gen_universe_decl val default_univ_decl : universe_decl (** [check_poly_decl ctx decl] If non extensible in [decl], check that the local universes (resp. universe constraints) in [ctx] are implied by [decl]. Return a [universes_entry] containing the local universes of [ctx] and their constraints. When polymorphic, the universes corresponding to [decl.univdecl_instance] come first in the order defined by that list. *) val check_univ_decl : poly:PolyFlags.t -> t -> universe_decl -> named_universes_entry val check_univ_decl_rev : t -> universe_decl -> t * UVars.UContext.t val check_uctx_impl : fail:(Pp.t -> unit) -> t -> t -> unit val check_mono_univ_decl : t -> universe_decl -> Univ.ContextSet.t val check_template_univ_decl : t -> template_qvars:QVar.Set.t -> universe_decl -> Univ.ContextSet.t val check_mono_sort_constraints : t -> Univ.ContextSet.t (** {5 TODO: Document me} *) val update_sigma_univs : t -> UGraph.t -> t (** {5 Pretty-printing} *) val pr_uctx_level : t -> Univ.Level.t -> Pp.t val pr_uctx_qvar : t -> Sorts.QVar.t -> Pp.t val qualid_of_level : t -> Univ.Level.t -> Libnames.qualid option (** Only looks in the local names, not in the nametab. *) val id_of_level : t -> Univ.Level.t -> Id.t option val id_of_qvar : t -> Sorts.QVar.t -> Id.t option val is_rigid_qvar : t -> Sorts.QVar.t -> bool val pr_weak : (Univ.Level.t -> Pp.t) -> t -> Pp.t val pr : t -> Pp.t val pr_sort_opt_subst : t -> Pp.t module Internal : sig val reboot : Environ.env -> t -> t (** Madness-inducing hack dedicated to the handling of universes of Program. DO NOT USE OUTSIDE OF DEDICATED AREA. *) end val add_template_default_univs : Environ.env -> MutInd.t -> unit rocq-9.2.0/engine/univFlex.ml000066400000000000000000000110051516144147600160730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* f l ~is_defined:(Option.has_some v) acc) subst acc let is_algebraic l {algs} = Level.Set.mem l algs let make_nonalgebraic_variable {subst;algs} l = { subst; algs = Level.Set.remove l algs } let make_all_undefined_nonalgebraic {subst;algs=_} = { subst; algs = Level.Set.empty } let fix_undefined_variables us = Level.Map.fold (fun u v ({subst; algs} as acc) -> match v with | None -> { subst = Level.Map.remove u subst; algs = Level.Set.remove u algs } | Some _ -> acc) us.subst us let add l ~algebraic {subst; algs} = let subst = Level.Map.update l (function | None -> Some None | Some _ -> assert false) subst in let algs = if algebraic then Level.Set.add l algs else algs in { subst; algs } let remove l { subst; algs } = let subst = match Level.Map.find_opt l subst with | None -> subst | Some None -> Level.Map.remove l subst | Some (Some _) -> (* removing [l := v] is unsound as it loses a constraint *) assert false in { subst = subst; algs = Level.Set.remove l algs } let add_levels levels ~algebraic subst = Level.Set.fold (fun l subst -> add l ~algebraic subst) levels subst let define l v {subst;algs} = (* XXX update algs? *) let subst = try Level.Map.modify l (fun _ old -> assert (Option.is_empty old); Some v) subst with Not_found -> assert false in { subst; algs } let constrain_variables diff us ctx = (* XXX update algs? *) Level.Set.fold (fun l ((univs,cstrs),{subst;algs} as acc) -> match Level.Map.find_opt l subst with | None | Some None -> acc | Some (Some u) -> match Universe.level u with | None -> acc | Some u -> ((Level.Set.add l univs, Univ.UnivConstraints.add (l, UnivConstraint.Eq, u) cstrs), {subst = Level.Map.remove l subst; algs})) diff (ctx,us) let biased_union {subst=lsubst;algs=lalgs} {subst=rsubst; algs=ralgs} = let subst = Level.Map.union (fun _k l r -> match l, r with | Some _, _ -> Some l | None, None -> Some l | _, _ -> Some r) lsubst rsubst in { subst; algs = Level.Set.union lalgs ralgs } let normalize_univ_variable ~find = let rec aux cur = find cur |> Option.map (fun b -> let b' = UnivSubst.subst_univs_universe aux b in if Universe.equal b' b then b else b') in aux let normalize_univ_variable ectx = let find l = Option.flatten (Univ.Level.Map.find_opt l ectx.subst) in normalize_univ_variable ~find let normalize_universe subst = let normlevel = normalize_univ_variable subst in UnivSubst.subst_univs_universe normlevel let normalize ctx = let normalize = normalize_universe ctx in let subst = Univ.Level.Map.mapi (fun u -> function | None -> None | Some v -> Some (normalize v)) ctx.subst in {subst; algs = ctx.algs} let normalize_univ_variables ctx = let ctx = normalize ctx in let def, subst = Univ.Level.Map.fold (fun u v (def, subst) -> match v with | None -> (def, subst) | Some b -> (Univ.Level.Set.add u def, Univ.Level.Map.add u b subst)) ctx.subst (Univ.Level.Set.empty, Univ.Level.Map.empty) in let subst l = Level.Map.find_opt l subst in ctx, def, subst let pr prl {subst; algs} = let open Pp in let ppsubst = Level.Map.pr prl (function | None -> mt() | Some x -> str " := " ++ Universe.pr prl x) subst in str"ALGEBRAIC UNIVERSES:"++brk(0,1)++ h (Level.Set.pr prl algs) ++ fnl() ++ str"FLEXIBLE UNIVERSES:"++brk(0,1)++ h ppsubst rocq-9.2.0/engine/univFlex.mli000066400000000000000000000065671516144147600162650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool val domain : t -> Level.Set.t (** Contains both defined and undefined flexible levels. *) val fold : (Level.t -> is_defined:bool -> 'a -> 'a) -> t -> 'a -> 'a (** For universe minimization. *) val mem : Level.t -> t -> bool (** Returns [true] for both defined and undefined flexible levels. *) val is_algebraic : Level.t -> t -> bool (** Is the level allowed to be defined by an algebraic universe? *) val make_nonalgebraic_variable : t -> Level.t -> t (** Make the level non algebraic. Undefined behaviour on already-defined algebraics. *) val make_all_undefined_nonalgebraic : t -> t (** Turn all undefined flexible algebraic variables into simply flexible ones. Can be used in case the variables might appear in universe instances (typically for polymorphic program obligations). *) val fix_undefined_variables : t -> t (** Make all undefined flexible levels into rigid levels, ie remove them. *) val add : Level.t -> algebraic:bool -> t -> t (** Makes a level flexible with no definition. It must not already be flexible. *) val remove : Level.t -> t -> t val add_levels : Level.Set.t -> algebraic:bool -> t -> t (** Make the levels flexible with no definitions. They must not already be flexible. *) val define : Level.t -> Universe.t -> t -> t (** Define the level to the given universe. The level must already be flexible and must be undefined. *) val constrain_variables : Level.Set.t -> t -> Univ.ContextSet.t -> Univ.ContextSet.t * t (** [constrain_variables diff subst ctx] removes bindings [l := l'] from the substitution where [l] is in [diff] and [l'] is a level, and adds [l, l = l'] to [ctx]. *) val biased_union : t -> t -> t (** [biased_union x y] favors the bindings of the first map that are defined, otherwise takes the second's bindings. *) val normalize : t -> t (** Return an optimized representation of the input *) val normalize_univ_variables : t -> t * Level.Set.t * UnivSubst.universe_subst_fn (** As [normalize] and also returns the set of defined variables and a function which is equivalent to calling [normalize_univ_variable] on the substitution but may be faster. *) val normalize_univ_variable : t -> UnivSubst.universe_subst_fn (** Apply the substitution to a variable. *) val normalize_universe : t -> Universe.t -> Universe.t (** Apply the substitution to an algebraic universe. *) val pr : (Level.t -> Pp.t) -> t -> Pp.t (** "Show Universes"-style printing. *) rocq-9.2.0/engine/univGen.ml000066400000000000000000000173511516144147600157200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Quality.equal a b | Set, Set -> true | Qual _, Set | Set, Qual _ -> false let compare a b = match a, b with | Qual a, Qual b -> Quality.compare a b | Set, Set -> 0 | Qual _, Set -> 1 | Set, Qual _ -> -1 let eliminates_to a b = let to_qual = function | Set -> Quality.qtype | Qual q -> q in Inductive.raw_eliminates_to (to_qual a) (to_qual b) let of_quality q = Qual q let of_sort s = match s with | Sorts.Set -> Set | s -> of_quality (Sorts.quality s) let quality q = match q with | Set -> Quality.qtype | Qual q -> q let set = Set let qtype = Qual Quality.qtype let prop = Qual Quality.qprop let sprop = Qual Quality.qsprop let is_type q = match q with | Set -> false | Qual q -> Quality.is_qtype q let is_set q = match q with | Set -> true | Qual _ -> false let is_prop q = match q with | Set -> false | Qual q -> Quality.is_qprop q let is_sprop q = match q with | Set -> false | Qual q -> Quality.is_qsprop q let pr prv q = match q with | Set -> Pp.str"Set" | Qual q -> Quality.pr prv q let raw_pr = pr Sorts.QVar.raw_pr let all_constants = Set :: List.map (fun q -> Qual q) Quality.all_constants let all = Set :: List.map (fun q -> Qual q) Quality.all end type sort_context_set = (QVar.Set.t * Univ.Level.Set.t) * PConstraints.t type 'a in_sort_context_set = 'a * sort_context_set let empty_sort_context = (QVar.Set.empty, Level.Set.empty), PConstraints.empty let is_empty_sort_context ((qs,us),csts) = QVar.Set.is_empty qs && Level.Set.is_empty us && PConstraints.is_empty csts let sort_context_union ((qs,us),csts) ((qs',us'),csts') = ((QVar.Set.union qs qs', Level.Set.union us us'), PConstraints.union csts csts') let diff_sort_context ((qs,us),csts) ((qs',us'),csts') = (QVar.Set.diff qs qs', Level.Set.diff us us'), PConstraints.diff csts csts' let pr_sort_context prv prl ((vs, us), cst as ctx) = let open Pp in if is_empty_sort_context ctx then mt () else let vs = if Sorts.QVar.Set.is_empty vs then mt () else Sorts.QVar.Set.pr prv vs ++ pr_semicolon () in hov 0 (h (vs ++ Level.Set.pr prl us ++ str " |=") ++ brk(1,2) ++ h (PConstraints.pr prv prl cst)) type univ_length_mismatch = { gref : GlobRef.t; actual : int * int; expect : int * int; } (* Due to an OCaml bug ocaml/ocaml#10027 inlining this record will cause compliation with -rectypes to crash. *) exception UniverseLengthMismatch of univ_length_mismatch let () = CErrors.register_handler (function | UniverseLengthMismatch { gref; actual=(aq,au); expect=(eq,eu) } -> let ppreal, ppexpected = if aq = 0 && eq = 0 then Pp.(int au, int eu) else Pp.(str "(" ++ int aq ++ str " | " ++ int au ++ str ")" , str "(" ++ int eq ++ str " | " ++ int eu ++ str ")") in Some Pp.(str "Universe instance length for " ++ Nametab.pr_global_env Id.Set.empty gref ++ spc() ++ str "is " ++ ppreal ++ spc() ++ str "but should be " ++ ppexpected ++ str".") | _ -> None) (* Generator of levels *) let new_univ_id = let cnt = ref 0 in fun () -> incr cnt; !cnt let new_univ_global () = let s = if Flags.async_proofs_is_worker() then !Flags.async_proofs_worker_id else "" in Univ.UGlobal.make (Global.current_dirpath ()) s (new_univ_id ()) let fresh_level () = Univ.Level.make (new_univ_global ()) let new_sort_id = let cnt = ref 0 in fun () -> incr cnt; !cnt let new_sort_global id = Sorts.QGlobal.make (Global.current_dirpath ()) id let fresh_sort_quality () = let s = if Flags.async_proofs_is_worker() then !Flags.async_proofs_worker_id else "" in Sorts.QVar.make_unif s (new_sort_id ()) let fresh_instance auctx : _ in_sort_context_set = let qlen, ulen = AbstractContext.size auctx in let qinst = Array.init qlen (fun _ -> Sorts.Quality.QVar (fresh_sort_quality ())) in let uinst = Array.init ulen (fun _ -> fresh_level()) in let qctx = Array.fold_left (fun qctx q -> match q with | Sorts.Quality.QVar q -> Sorts.QVar.Set.add q qctx | _ -> assert false) Sorts.QVar.Set.empty qinst in let uctx = Array.fold_right Level.Set.add uinst Level.Set.empty in let inst = Instance.of_array (qinst,uinst) in inst, ((qctx,uctx), AbstractContext.instantiate inst auctx) let existing_instance ?loc ~gref auctx inst = let () = let actual = Instance.length inst and expect = AbstractContext.size auctx in if not (UVars.eq_sizes actual expect) then Loc.raise ?loc (UniverseLengthMismatch { gref; actual; expect }) else () in inst, ((Sorts.QVar.Set.empty,Level.Set.empty), AbstractContext.instantiate inst auctx) let fresh_instance_from ?loc ctx = function | Some (gref,inst) -> existing_instance ?loc ~gref ctx inst | None -> fresh_instance ctx (** Fresh universe polymorphic construction *) let fresh_global_instance ?loc ?names env gr = let auctx = Environ.universes_of_global env gr in let names = Option.map (fun x -> gr, x) names in let u, ctx = fresh_instance_from ?loc auctx names in u, ctx let fresh_constant_instance env c = let u, ctx = fresh_global_instance env (GlobRef.ConstRef c) in (c, u), ctx let fresh_inductive_instance env ind = let u, ctx = fresh_global_instance env (GlobRef.IndRef ind) in (ind, u), ctx let fresh_constructor_instance env c = let u, ctx = fresh_global_instance env (GlobRef.ConstructRef c) in (c, u), ctx let fresh_array_instance env = let auctx = CPrimitives.typ_univs CPrimitives.PT_array in let u, ctx = fresh_instance_from auctx None in u, ctx let fresh_global_instance ?loc ?names env gr = let u, ctx = fresh_global_instance ?loc ?names env gr in mkRef (gr, u), ctx let constr_of_monomorphic_global env gr = if not (Environ.is_polymorphic env gr) then fst (fresh_global_instance env gr) else CErrors.user_err Pp.(str "globalization of polymorphic reference " ++ Nametab.pr_global_env Id.Set.empty gr ++ str " would forget universes.") let fresh_sort_in_quality = let open QualityOrSet in function | Qual (QConstant QSProp) -> Sorts.sprop, empty_sort_context | Qual (QConstant QProp) -> Sorts.prop, empty_sort_context | Set -> Sorts.set, empty_sort_context | Qual (QConstant QType | QVar _ (* Treat as Type *)) -> let u = fresh_level () in sort_of_univ (Univ.Universe.make u), ((QVar.Set.empty,Level.Set.singleton u), PConstraints.empty) let fresh_sort_context_instance ((qs, us), csts) = let ufold u (us, usubst) = let u' = fresh_level () in (Level.Set.add u' us, Level.Map.add u u' usubst) in let qfold q (qs, qsubst) = let q' = fresh_sort_quality () in QVar.Set.add q' qs, QVar.Map.add q (Sorts.Quality.QVar q') qsubst in let us, usubst = Level.Set.fold ufold us (Level.Set.empty, Level.Map.empty) in let qs, qsubst = QVar.Set.fold qfold qs (QVar.Set.empty, QVar.Map.empty) in let csts = subst_poly_constraints (qsubst, usubst) csts in (qsubst, usubst), ((qs, us), csts) rocq-9.2.0/engine/univGen.mli000066400000000000000000000074061516144147600160710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool val compare : t -> t -> int val of_quality : Sorts.Quality.t -> t val of_sort : Sorts.t -> t val quality : t -> Sorts.Quality.t val eliminates_to : t -> t -> bool val set : t val qtype : t val prop : t val sprop : t val is_type : t -> bool val is_set : t -> bool val is_prop : t -> bool val is_sprop : t -> bool val pr : (Sorts.QVar.t -> Pp.t) -> t -> Pp.t val raw_pr : t -> Pp.t val all_constants : t list val all : t list end type univ_length_mismatch = { gref : GlobRef.t; actual : int * int; expect : int * int; } (* Due to an OCaml bug ocaml/ocaml#10027 inlining this record will cause compliation with -rectypes to crash. *) exception UniverseLengthMismatch of univ_length_mismatch (** Side-effecting functions creating new universe levels. *) val new_univ_global : unit -> UGlobal.t val new_sort_global : Id.t -> Sorts.QGlobal.t val fresh_level : unit -> Level.t val fresh_sort_quality : unit -> Sorts.QVar.t (** Build a fresh instance for a given context, its associated substitution and the instantiated constraints. *) (* TODO: move this type and its associated functions somewhere reasonable *) type sort_context_set = (Sorts.QVar.Set.t * Univ.Level.Set.t) * PConstraints.t type 'a in_sort_context_set = 'a * sort_context_set val sort_context_union : sort_context_set -> sort_context_set -> sort_context_set val empty_sort_context : sort_context_set val is_empty_sort_context : sort_context_set -> bool val diff_sort_context : sort_context_set -> sort_context_set -> sort_context_set val pr_sort_context : (Sorts.QVar.t -> Pp.t) -> (Univ.Level.Set.elt -> Pp.t) -> sort_context_set -> Pp.t val fresh_instance : AbstractContext.t -> Instance.t in_sort_context_set (** The globref is only used for the error message when there is a mismatch. *) val fresh_instance_from : ?loc:Loc.t -> AbstractContext.t -> (GlobRef.t * Instance.t) option -> Instance.t in_sort_context_set val fresh_sort_in_quality : QualityOrSet.t -> Sorts.t in_sort_context_set (** NB: QSort is treated as QType *) val fresh_constant_instance : env -> Constant.t -> pconstant in_sort_context_set val fresh_inductive_instance : env -> inductive -> pinductive in_sort_context_set val fresh_constructor_instance : env -> constructor -> pconstructor in_sort_context_set val fresh_array_instance : env -> Instance.t in_sort_context_set val fresh_global_instance : ?loc:Loc.t -> ?names:UVars.Instance.t -> env -> GlobRef.t -> constr in_sort_context_set val fresh_sort_context_instance : sort_context_set -> sort_level_subst * sort_context_set (** Create a fresh global in the environment argument, without side effects. BEWARE: this raises an error on polymorphic constants/inductives: the constraints should be properly added to an evd. See Evd.fresh_global, Evarutil.new_global, and pf_constr_of_global for the proper way to get a fresh copy of a polymorphic global reference. *) val constr_of_monomorphic_global : env -> GlobRef.t -> constr rocq-9.2.0/engine/univMinim.ml000066400000000000000000000406521516144147600162600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Level.Map.add u [t] map (** Precondition: flexible <= ctx *) let choose_canonical ctx flexible algebraic s = let global = Level.Set.diff s ctx in let flexible, rigid = Level.Set.partition flexible (Level.Set.inter s ctx) in (* If there is a global universe in the set, choose it *) if not (Level.Set.is_empty global) then let canon = Level.Set.choose global in canon, (Level.Set.remove canon global, rigid, flexible) else (* No global in the equivalence class, choose a rigid one *) if not (Level.Set.is_empty rigid) then let canon = Level.Set.choose rigid in canon, (global, Level.Set.remove canon rigid, flexible) else (* There are only flexible universes in the equivalence class, choose a non-algebraic. *) let algs, nonalgs = Level.Set.partition algebraic flexible in if not (Level.Set.is_empty nonalgs) then let canon = Level.Set.choose nonalgs in canon, (global, rigid, Level.Set.remove canon flexible) else let canon = Level.Set.choose algs in canon, (global, rigid, Level.Set.remove canon flexible) let compare_constraint_type d d' = let open UnivConstraint in match d, d' with | Eq, Eq -> 0 | Eq, _ -> -1 | _, Eq -> 1 | Le, Le -> 0 | Le, _ -> -1 | _, Le -> 1 | Lt, Lt -> 0 type lowermap = UnivConstraint.kind Level.Map.t let lower_union = let merge k a b = match a, b with | Some _, None -> a | None, Some _ -> b | None, None -> None | Some l, Some r -> if compare_constraint_type l r >= 0 then a else b in Level.Map.merge merge let lower_add l c m = try let c' = Level.Map.find l m in if compare_constraint_type c c' > 0 then Level.Map.add l c m else m with Not_found -> Level.Map.add l c m let lower_of_list l = List.fold_left (fun acc (d,l) -> Level.Map.add l d acc) Level.Map.empty l type lbound = { enforce : bool; alg : bool; lbound: Universe.t; lower : lowermap } module LBMap : sig type t = private { lbmap : lbound Level.Map.t; lbrev : (Level.t * lowermap) Universe.Map.t } val empty : t val add : Level.t -> lbound -> t -> t end = struct type t = { lbmap : lbound Level.Map.t; lbrev : (Level.t * lowermap) Universe.Map.t } (* lbrev is uniquely given from lbmap as a partial reverse mapping *) let empty = { lbmap = Level.Map.empty; lbrev = Universe.Map.empty } let add u bnd m = let lbmap = Level.Map.add u bnd m.lbmap in let lbrev = if not bnd.alg && bnd.enforce then match Universe.Map.find bnd.lbound m.lbrev with | (v, _) -> if Level.compare u v <= 0 then Universe.Map.add bnd.lbound (u, bnd.lower) m.lbrev else m.lbrev | exception Not_found -> Universe.Map.add bnd.lbound (u, bnd.lower) m.lbrev else m.lbrev in { lbmap; lbrev } end let find_inst insts v = Universe.Map.find v insts.LBMap.lbrev let compute_lbound left = (* The universe variable was not fixed yet. Compute its level using its lower bound. *) let sup l lbound = match lbound with | None -> Some l | Some l' -> Some (Universe.sup l l') in List.fold_left (fun lbound (d, l) -> if d == UnivConstraint.Le (* l <= ?u *) then sup l lbound else (* l < ?u *) (assert (d == Lt); if not (Universe.level l == None) then sup (Universe.super l) lbound else None)) None left let instantiate_with_lbound u lbound lower ~alg ~enforce (ctx, us, insts, cstrs) = if enforce then let inst = Universe.make u in let cstrs' = enforce_leq lbound inst cstrs in (ctx, UnivFlex.make_nonalgebraic_variable us u, LBMap.add u {enforce;alg;lbound;lower} insts, cstrs'), {enforce; alg; lbound=inst; lower} else (* Actually instantiate *) (Level.Set.remove u ctx, UnivFlex.define u lbound us, LBMap.add u {enforce;alg;lbound;lower} insts, cstrs), {enforce; alg; lbound; lower} type constraints_map = (UnivConstraint.kind * Level.Map.key) list Level.Map.t let _pr_constraints_map (cmap:constraints_map) = let open Pp in Level.Map.fold (fun l cstrs acc -> Level.raw_pr l ++ str " => " ++ prlist_with_sep spc (fun (d,r) -> UnivConstraint.pr_kind d ++ Level.raw_pr r) cstrs ++ fnl () ++ acc) cmap (mt ()) let remove_alg l (ctx, us, insts, cstrs) = (ctx, UnivFlex.make_nonalgebraic_variable us l, insts, cstrs) let not_lower lower (d,l) = (* We're checking if (d,l) is already implied by the lower constraints on some level u. If it represents l < u (d is Lt or d is Le and i > 0, the i < 0 case is impossible due to invariants of Univ), and the lower constraints only have l <= u then it is not implied. *) Universe.exists (fun (l,i) -> let d = if i == 0 then d else match d with | UnivConstraint.Le -> UnivConstraint.Lt | d -> d in try let d' = Level.Map.find l lower in (* If d is stronger than the already implied lower * constraints we must keep it. *) compare_constraint_type d d' > 0 with Not_found -> (* No constraint existing on l *) true) l exception UpperBoundedAlg (** [enforce_uppers upper lbound cstrs] interprets [upper] as upper constraints to [lbound], adding them to [cstrs]. @raise UpperBoundedAlg if any [upper] constraints are strict and [lbound] algebraic. *) let enforce_uppers upper lbound cstrs = List.fold_left (fun cstrs (d, r) -> if d == UnivConstraint.Le then enforce_leq lbound (Universe.make r) cstrs else match Universe.level lbound with | Some lev -> UnivConstraints.add (lev, d, r) cstrs | None -> raise UpperBoundedAlg) cstrs upper let minimize_univ_variables ctx us left right cstrs = let left, lbounds = Level.Map.fold (fun r lower (left, lbounds as acc) -> if UnivFlex.mem r us || not (Level.Set.mem r ctx) then acc else (* Fixed universe, just compute its glb for sharing *) let lbounds = match compute_lbound (List.map (fun (d,l) -> d, Universe.make l) lower) with | None -> lbounds | Some lbound -> LBMap.add r {enforce=true; alg=false; lbound; lower=lower_of_list lower} lbounds in (Level.Map.remove r left, lbounds)) left (left, LBMap.empty) in let rec instance (ctx, us, insts, cstrs as acc) u = let acc, left, lower = match Level.Map.find u left with | exception Not_found -> acc, [], Level.Map.empty | l -> let acc, left, newlow, lower = List.fold_left (fun (acc, left, newlow, lower') (d, l) -> let acc', {enforce=enf;alg;lbound=l';lower} = aux acc l in let l' = if enf then Universe.make l else l' in acc', (d, l') :: left, lower_add l d newlow, lower_union lower lower') (acc, [], Level.Map.empty, Level.Map.empty) l in let left = CList.uniquize (List.filter (not_lower lower) left) in (acc, left, Level.Map.lunion newlow lower) in let instantiate_lbound lbound = let alg = UnivFlex.is_algebraic u us in if Universe.is_type0 lbound && not (get_set_minimization()) then (* Minim to Set disabled, do not instantiate with Set *) instantiate_with_lbound u lbound lower ~alg ~enforce:true acc else if alg then (* u is algebraic: we instantiate it with its lower bound, if any, or enforce the constraints if it is bounded from the top. *) let lower = Level.Set.fold Level.Map.remove (Universe.levels lbound) lower in instantiate_with_lbound u lbound lower ~alg:true ~enforce:false acc else (* u is non algebraic *) match Universe.level lbound with | Some l -> (* The lowerbound is directly a level *) (* u is not algebraic but has no upper bounds, we instantiate it with its lower bound if it is a different level, otherwise we keep it. *) let lower = Level.Map.remove l lower in if not (Level.equal l u) then (* Should check that u does not have upper constraints that are not already in right *) let acc = remove_alg l acc in instantiate_with_lbound u lbound lower ~alg:false ~enforce:false acc else acc, {enforce=true; alg=false; lbound; lower} | None -> begin match find_inst insts lbound with | can, lower -> (* Another universe represents the same lower bound, we can share them with no harm. *) let lower = Level.Map.remove can lower in instantiate_with_lbound u (Universe.make can) lower ~alg:false ~enforce:false acc | exception Not_found -> (* We set u as the canonical universe representing lbound *) instantiate_with_lbound u lbound lower ~alg:false ~enforce:true acc end in let enforce_uppers ((ctx,us,insts,cstrs), b as acc) = match Level.Map.find u right with | exception Not_found -> acc | upper -> let upper = List.filter (fun (d, r) -> not (UnivFlex.mem r us)) upper in let cstrs = enforce_uppers upper b.lbound cstrs in (ctx, us, insts, cstrs), b in if not (Level.Set.mem u ctx) then enforce_uppers (acc, {enforce=true; alg=false; lbound=Universe.make u; lower}) else let lbound = compute_lbound left in match lbound with | None -> (* Nothing to do *) enforce_uppers (acc, {enforce=true;alg=false;lbound=Universe.make u; lower}) | Some lbound -> try enforce_uppers (instantiate_lbound lbound) with UpperBoundedAlg -> enforce_uppers (acc, {enforce=true; alg=false; lbound=Universe.make u; lower}) and aux (ctx, us, seen, cstrs as acc) u = try acc, Level.Map.find u seen.LBMap.lbmap with Not_found -> instance acc u in UnivFlex.fold (fun u ~is_defined (ctx, us, seen, cstrs as acc) -> if not is_defined then fst (aux acc u) else Level.Set.remove u ctx, UnivFlex.make_nonalgebraic_variable us u, seen, cstrs) us (ctx, us, lbounds, cstrs) module UPairs = OrderedType.UnorderedPair(Level) module UPairSet = Set.Make (UPairs) type extra = { weak_constraints : UPairSet.t; above_prop : Level.Set.t; } let empty_extra = { weak_constraints = UPairSet.empty; above_prop = Level.Set.empty; } let extra_union a b = { weak_constraints = UPairSet.union a.weak_constraints b.weak_constraints; above_prop = Level.Set.union a.above_prop b.above_prop; } let normalize_context_set g ctx (us:UnivFlex.t) {weak_constraints=weak;above_prop} = let (ctx, csts) = ctx in (* Keep the Set <= i constraints separate *) let smallles, csts = UnivConstraints.partition (fun (l,d,r) -> d == Le && Level.is_set l) csts in (* Process weak constraints: when one side is flexible and the 2 universes are unrelated unify them. *) let smallles, csts, g = UPairSet.fold (fun (u,v) (smallles, csts, g as acc) -> let norm = level_subst_of (UnivFlex.normalize_univ_variable us) in let u = norm u and v = norm v in if (Level.is_set u || Level.is_set v) then begin if get_set_minimization() then begin if Level.is_set u then (UnivConstraints.add (u,Le,v) smallles,csts,g) else (UnivConstraints.add (v,Le,u) smallles,csts,g) end else acc end else let set_to a b = (smallles, UnivConstraints.add (a,Eq,b) csts, UGraph.enforce_constraint (a,Eq,b) g) in let check_le a b = UGraph.check_constraint g (a,Le,b) in if check_le u v || check_le v u then acc else if UnivFlex.mem u us then set_to u v else if UnivFlex.mem v us then set_to v u else acc) weak (smallles, csts, g) in let smallles = if get_set_minimization () then UnivConstraints.filter (fun (l,d,r) -> UnivFlex.mem r us) smallles else UnivConstraints.empty (* constraints Set <= u may be dropped *) in let smallles = if get_set_minimization() then let fold u accu = if UnivFlex.mem u us then UnivConstraints.add (Level.set, Le, u) accu else accu in Level.Set.fold fold above_prop smallles else smallles in let csts, partition = (* We first put constraints in a normal-form: all self-loops are collapsed to equalities. *) let g = UGraph.initial_universes_with g in (* use lbound:Set to collapse [u <= v <= Set] into [u = v = Set] *) let g = Level.Set.fold (fun v g -> UGraph.add_universe ~strict:false v g) ctx g in let add_soft u g = if not (Level.is_set u || Level.Set.mem u ctx) then try UGraph.add_universe ~strict:false u g with UGraph.AlreadyDeclared -> g else g in let g = UnivConstraints.fold (fun (l, d, r) g -> add_soft r (add_soft l g)) csts g in let g = UGraph.merge_constraints csts g in UGraph.constraints_of_universes g in (* Ignore constraints from lbound:Set *) let noneqs = UnivConstraints.filter (fun (l,d,r) -> not (d == Le && Level.is_set l)) csts in (* Put back constraints [Set <= u] from type inference *) let noneqs = UnivConstraints.union noneqs smallles in let flex x = UnivFlex.mem x us in let algebraic x = UnivFlex.is_algebraic x us in let ctx, us, eqs = List.fold_left (fun (ctx, us, cstrs) s -> let canon, (global, rigid, flexible) = choose_canonical ctx flex algebraic s in (* Add equalities for globals which can't be merged anymore. *) let cstrs = Level.Set.fold (fun g cst -> UnivConstraints.add (canon, Eq, g) cst) global cstrs in (* Also add equalities for rigid variables *) let cstrs = Level.Set.fold (fun g cst -> UnivConstraints.add (canon, Eq, g) cst) rigid cstrs in let canonu = Universe.make canon in let us = Level.Set.fold (fun f -> UnivFlex.define f canonu) flexible us in (Level.Set.diff ctx flexible, us, cstrs)) (ctx, us, UnivConstraints.empty) partition in (* Noneqs is now in canonical form w.r.t. equality constraints, and contains only inequality constraints. *) let noneqs = let norm = level_subst_of (UnivFlex.normalize_univ_variable us) in let fold (u,d,v) noneqs = let u = norm u and v = norm v in if d != UnivConstraint.Lt && Level.equal u v then noneqs else UnivConstraints.add (u,d,v) noneqs in UnivConstraints.fold fold noneqs UnivConstraints.empty in (* Compute the left and right set of flexible variables, constraints mentioning other variables remain in noneqs. *) let noneqs, ucstrsl, ucstrsr = UnivConstraints.fold (fun (l,d,r as cstr) (noneq, ucstrsl, ucstrsr) -> let lus = UnivFlex.mem l us and rus = UnivFlex.mem r us in let ucstrsl' = if lus then add_list_map l (d, r) ucstrsl else ucstrsl and ucstrsr' = add_list_map r (d, l) ucstrsr in let noneqs = if lus || rus then noneq else UnivConstraints.add cstr noneq in (noneqs, ucstrsl', ucstrsr')) noneqs (UnivConstraints.empty, Level.Map.empty, Level.Map.empty) in (* Now we construct the instantiation of each variable. *) let ctx', us, inst, noneqs = minimize_univ_variables ctx us ucstrsr ucstrsl noneqs in let us = UnivFlex.normalize us in us, (ctx', UnivConstraints.union noneqs eqs) rocq-9.2.0/engine/univMinim.mli000066400000000000000000000030561516144147600164260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* extra -> extra (** Simplification and pruning of constraints: [normalize_context_set ctx us] - Instantiate the variables in [us] with their most precise universe levels respecting the constraints. - Normalizes the context [ctx] w.r.t. equality constraints, choosing a canonical universe in each equivalence class (a global one if there is one) and transitively saturate the constraints w.r.t to the equalities. *) val normalize_context_set : UGraph.t -> Univ.ContextSet.t -> UnivFlex.t (* The defined and undefined variables *) -> extra -> UnivFlex.t * Univ.ContextSet.t rocq-9.2.0/engine/univNames.ml000066400000000000000000000033411516144147600162440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (try Some (Nametab.shortest_qualid_of_universe ctx qid) with Not_found -> None) | None -> None let pr_level_with_global_universes ?(binders=empty_binders) l = match qualid_of_level binders l with | Some qid -> Libnames.pr_qualid qid | None -> Level.raw_pr l let qualid_of_quality (ctx,_) q = match Sorts.QVar.repr q with | Global qid -> (try Some (Nametab.Quality.shortest_qualid_gen (fun id -> Id.Map.mem id ctx) qid) with Not_found -> None) | _ -> None let pr_quality_with_global_universes ?(binders=empty_binders) q = match qualid_of_quality binders q with | Some qid -> Libnames.pr_qualid qid | None -> Sorts.QVar.raw_pr q rocq-9.2.0/engine/univNames.mli000066400000000000000000000025231516144147600164160ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* level mapping *) type universe_binders = QVar.t Id.Map.t * Level.t Id.Map.t type rev_binders = Id.t QVar.Map.t * Id.t Level.Map.t val empty_binders : universe_binders val empty_rev_binders : rev_binders type univ_name_list = Names.lname list type full_name_list = lname list * lname list val pr_level_with_global_universes : ?binders:universe_binders -> Level.t -> Pp.t val qualid_of_level : universe_binders -> Level.t -> Libnames.qualid option val pr_quality_with_global_universes : ?binders:universe_binders -> Sorts.QVar.t -> Pp.t val qualid_of_quality : universe_binders -> Sorts.QVar.t -> Libnames.qualid option rocq-9.2.0/engine/univProblem.ml000066400000000000000000000121101516144147600165730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Inductive.raw_eliminates_to a b | QElimTo (a, b) -> Inductive.raw_eliminates_to a b | QEq (a, b) -> Quality.equal a b | ULe (u, v) | UEq (u, v) -> Sorts.equal u v | ULub (u, v) | UWeak (u, v) -> Level.equal u v let force = function | QEq _ | QElimTo _ | QLeq _ | ULe _ | UEq _ | UWeak _ as cst -> cst | ULub (u,v) -> UEq (Sorts.sort_of_univ @@ Universe.make u, Sorts.sort_of_univ @@ Universe.make v) let check_eq_level g u v = UGraph.check_eq_level g u v module Set = struct module S = Set.Make( struct type nonrec t = t let compare x y = let compare_qualities (a, b) (a', b') = let i = Quality.compare a a' in if i <> 0 then i else Quality.compare b b' in match x, y with | QEq (a, b), QEq (a', b') | QLeq (a, b), QLeq (a', b') | QElimTo (a, b), QElimTo (a', b') -> compare_qualities (a, b) (a', b') | ULe (u, v), ULe (u', v') -> let i = Sorts.compare u u' in if Int.equal i 0 then Sorts.compare v v' else i | UEq (u, v), UEq (u', v') -> let i = Sorts.compare u u' in if Int.equal i 0 then Sorts.compare v v' else if Sorts.equal u v' && Sorts.equal v u' then 0 else i | ULub (u, v), ULub (u', v') | UWeak (u, v), UWeak (u', v') -> let i = Level.compare u u' in if Int.equal i 0 then Level.compare v v' else if Level.equal u v' && Level.equal v u' then 0 else i | QEq _, _ -> -1 | _, QEq _ -> 1 | QLeq _, _ -> -1 | _, QLeq _ -> 1 | QElimTo _, _ -> -1 | _, QElimTo _ -> 1 | ULe _, _ -> -1 | _, ULe _ -> 1 | UEq _, _ -> -1 | _, UEq _ -> 1 | ULub _, _ -> -1 | _, ULub _ -> 1 end) include S let add cst s = if is_trivial cst then s else add cst s let pr_one = let open Pp in function | QEq (a, b) -> Quality.raw_pr a ++ str " = " ++ Quality.raw_pr b | QLeq (a, b) -> Quality.raw_pr a ++ str " <= " ++ Quality.raw_pr b | QElimTo (a, b) -> Quality.raw_pr a ++ str " -> " ++ Quality.raw_pr b | ULe (u, v) -> Sorts.debug_print u ++ str " <= " ++ Sorts.debug_print v | UEq (u, v) -> Sorts.debug_print u ++ str " = " ++ Sorts.debug_print v | ULub (u, v) -> Level.raw_pr u ++ str " /\\ " ++ Level.raw_pr v | UWeak (u, v) -> Level.raw_pr u ++ str " ~ " ++ Level.raw_pr v let pr c = let open Pp in fold (fun cst pp_std -> pp_std ++ pr_one cst ++ fnl ()) c (str "") let equal x y = x == y || equal x y let force s = map force s end type 'a constraint_function = 'a -> 'a -> Set.t -> Set.t let enforce_eq_instances_univs strict x y c = let mkU u = Sorts.sort_of_univ @@ Universe.make u in let mk u v = if strict then ULub (u, v) else UEq (mkU u, mkU v) in if not (UVars.eq_sizes (UVars.Instance.length x) (UVars.Instance.length y)) then CErrors.anomaly Pp.(str "Invalid argument: enforce_eq_instances_univs called with" ++ str " instances of different lengths."); let xq, xu = UVars.Instance.to_array x and yq, yu = UVars.Instance.to_array y in let c = CArray.fold_left2 (* TODO strict? *) (fun c x y -> if Sorts.Quality.equal x y then c else Set.add (QEq (x,y)) c) c xq yq in let c = CArray.fold_left2 (fun c x y -> Set.add (mk x y) c) c xu yu in c let enforce_eq_qualities qs qs' cstrs = CArray.fold_left2 (fun c a b -> if Sorts.Quality.equal a b then c else Set.add (QEq (a, b)) c) cstrs qs qs' let compare_cumulative_instances cv_pb variances u u' cstrs = let make u = Sorts.sort_of_univ @@ Univ.Universe.make u in let qs, us = UVars.Instance.to_array u and qs', us' = UVars.Instance.to_array u' in let cstrs = enforce_eq_qualities qs qs' cstrs in CArray.fold_left3 (fun cstrs v u u' -> let open UVars.Variance in match v with | Irrelevant -> Set.add (UWeak (u,u')) cstrs | Covariant -> (match cv_pb with | Conversion.CONV -> Set.add (UEq (make u, make u')) cstrs | Conversion.CUMUL -> Set.add (ULe (make u, make u')) cstrs) | Invariant -> Set.add (UEq (make u, make u')) cstrs) cstrs variances us us' rocq-9.2.0/engine/univProblem.mli000066400000000000000000000035551516144147600167610ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool (** Wrapper around the UGraph function to handle Prop *) val check_eq_level : UGraph.t -> Level.t -> Level.t -> bool module Set : sig include Set.S with type elt = t val pr : t -> Pp.t (** Replace ULub constraints by UEq *) val force : t -> t end type 'a constraint_function = 'a -> 'a -> Set.t -> Set.t val enforce_eq_instances_univs : bool -> Instance.t constraint_function val enforce_eq_qualities : Sorts.Quality.t array constraint_function val compare_cumulative_instances : Conversion.conv_pb -> Variance.t array -> Instance.t constraint_function rocq-9.2.0/engine/univSubst.ml000066400000000000000000000170231516144147600163030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let a' = addn n u' in (a' :: subst, nosubst) | None -> (subst, (u, n) :: nosubst)) (Universe.repr ul) ([], []) in match subst with | [] -> ul | u :: ul -> let substs = List.fold_left Universe.sup u subst in List.fold_left (fun acc (u, n) -> Universe.sup acc (addn n (Universe.make u))) substs nosubst let enforce_eq u v c = if Universe.equal u v then c else match Universe.level u, Universe.level v with | Some u, Some v -> enforce_eq_level u v c | _ -> CErrors.anomaly (Pp.str "A universe comparison can only happen between variables.") let constraint_add_leq v u c = let eq (x, n) (y, m) = Int.equal m n && Level.equal x y in (* We just discard trivial constraints like u<=u *) if eq v u then c else match v, u with | (x,n), (y,m) -> let j = m - n in if j = -1 (* n = m+1, v+1 <= u <-> v < u *) then UnivConstraints.add (x,Lt,y) c else if j <= -1 (* n = m+k, v+k <= u and k>0 *) then if Level.equal x y then (* u+k <= u with k>0 *) UnivConstraints.add (x,Lt,x) c else CErrors.user_err (Pp.str"Unable to handle arbitrary u+k <= v constraints.") else if j = 0 then UnivConstraints.add (x,Le,y) c else (* j >= 1 *) (* m = n + k, u <= v+k *) if Level.equal x y then c (* u <= u+k, trivial *) else if Level.is_set x then c (* Prop,Set <= u+S k, trivial *) else UnivConstraints.add (x,Le,y) c (* u <= v implies u <= v+k *) let check_univ_leq_one u v = let leq (u,n) (v,n') = let cmp = Level.compare u v in if Int.equal cmp 0 then n <= n' else false in Universe.exists (leq u) v let check_univ_leq u v = Universe.for_all (fun u -> check_univ_leq_one u v) u let enforce_leq u v c = List.fold_left (fun c v -> (List.fold_left (fun c u -> constraint_add_leq u v c) c u)) c v let enforce_leq u v c = if check_univ_leq u v then c else enforce_leq (Universe.repr u) (Universe.repr v) c let enforce_univ_constraint (u,d,v) = match d with | UnivConstraint.Eq -> enforce_eq u v | UnivConstraint.Le -> enforce_leq u v | UnivConstraint.Lt -> enforce_leq (Universe.super u) v let subst_univs_constraint fn (u,d,v as c) cstrs = let u' = fn u in let v' = fn v in match u', v' with | None, None -> UnivConstraints.add c cstrs | Some u, None -> enforce_univ_constraint (u,d,Universe.make v) cstrs | None, Some v -> enforce_univ_constraint (Universe.make u,d,v) cstrs | Some u, Some v -> enforce_univ_constraint (u,d,v) cstrs let subst_univs_constraints subst csts = UnivConstraints.fold (fun c cstrs -> subst_univs_constraint subst c cstrs) csts UnivConstraints.empty let level_subst_of f = fun l -> match f l with | None -> l | Some u -> match Universe.level u with | None -> assert false | Some l -> l let subst_univs_fn_puniverses f (c, u as cu) = let u' = Instance.subst_fn f u in if u' == u then cu else (c, u') let map_universes_opt_subst_with_binders next aux frel fqual funiv k c = let flevel = fqual, level_subst_of funiv in let aux_rec ((nas, tys, bds) as rc) = let nas' = Array.Smart.map (Context.map_annot_relevance frel) nas in let tys' = Array.Fun1.Smart.map aux k tys in let k' = iterate next (Array.length tys') k in let bds' = Array.Fun1.Smart.map aux k' bds in if nas' == nas && tys' == tys && bds' == bds then rc else (nas', tys', bds') in let aux_ctx ((nas, c) as p) = let nas' = Array.Smart.map (Context.map_annot_relevance frel) nas in let k' = iterate next (Array.length nas) k in let c' = aux k' c in if nas' == nas && c' == c then p else (nas', c') in match kind c with | Const pu -> let pu' = subst_univs_fn_puniverses flevel pu in if pu' == pu then c else mkConstU pu' | Ind pu -> let pu' = subst_univs_fn_puniverses flevel pu in if pu' == pu then c else mkIndU pu' | Construct pu -> let pu' = subst_univs_fn_puniverses flevel pu in if pu' == pu then c else mkConstructU pu' | Sort s -> let s' = Sorts.subst_fn (fqual, subst_univs_universe funiv) s in if s' == s then c else mkSort s' | Case (ci,u,pms,(p,rel),iv,t,br) -> let u' = Instance.subst_fn flevel u in let rel' = frel rel in let pms' = Array.Fun1.Smart.map aux k pms in let p' = aux_ctx p in let iv' = map_invert (aux k) iv in let t' = aux k t in let br' = Array.Smart.map aux_ctx br in if rel' == rel && u' == u && pms' == pms && p' == p && iv' == iv && t' == t && br' == br then c else mkCase (ci, u', pms', (p',rel'), iv', t', br') | Array (u,elems,def,ty) -> let u' = Instance.subst_fn flevel u in let elems' = CArray.Fun1.Smart.map aux k elems in let def' = aux k def in let ty' = aux k ty in if u == u' && elems == elems' && def == def' && ty == ty' then c else mkArray (u',elems',def',ty') | Prod (na, t, u) -> let na' = Context.map_annot_relevance frel na in let t' = aux k t in let u' = aux (next k) u in if na' == na && t' == t && u' == u then c else mkProd (na', t', u') | Lambda (na, t, u) -> let na' = Context.map_annot_relevance frel na in let t' = aux k t in let u' = aux (next k) u in if na' == na && t' == t && u' == u then c else mkLambda (na', t', u') | LetIn (na, b, t, u) -> let na' = Context.map_annot_relevance frel na in let b' = aux k b in let t' = aux k t in let u' = aux (next k) u in if na' == na && b' == b && t' == t && u' == u then c else mkLetIn (na', b', t', u') | Fix (i, rc) -> let rc' = aux_rec rc in if rc' == rc then c else mkFix (i, rc') | CoFix (i, rc) -> let rc' = aux_rec rc in if rc' == rc then c else mkCoFix (i, rc') | Proj (p, r, v) -> let r' = frel r in let v' = aux k v in if r' == r && v' == v then c else mkProj (p, r', v') | _ -> Constr.map_with_binders next aux k c let nf_evars_and_universes_opt_subst fevar frel fqual funiv c = let rec self () c = match Constr.kind c with | Evar (evk, args) -> let args' = SList.Smart.map (self ()) args in begin match try fevar (evk, args') with Not_found -> None with | None -> if args == args' then c else mkEvar (evk, args') | Some c -> self () c end | _ -> map_universes_opt_subst_with_binders ignore self frel fqual funiv () c in self () c let pr_universe_subst prl = let open Pp in Level.Map.pr prl (fun u -> str" := " ++ Universe.pr prl u ++ spc ()) rocq-9.2.0/engine/univSubst.mli000066400000000000000000000037151516144147600164570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a) -> ('a -> constr -> constr) -> (Sorts.relevance -> Sorts.relevance) -> quality_subst_fn -> universe_subst_fn -> 'a -> constr -> constr val nf_evars_and_universes_opt_subst : (existential -> constr option) -> (Sorts.relevance -> Sorts.relevance) -> quality_subst_fn -> universe_subst_fn -> constr -> constr [@@ocaml.deprecated "(8.20) Use [UnivSubst.map_universes_opt_subst_with_binders]"] val subst_univs_universe : universe_subst_fn -> Universe.t -> Universe.t val pr_universe_subst : (Level.t -> Pp.t) -> universe_subst -> Pp.t val enforce_eq : Universe.t constraint_function val enforce_leq : Universe.t constraint_function rocq-9.2.0/flake.lock000066400000000000000000000025511516144147600144360ustar00rootroot00000000000000{ "nodes": { "flake-utils": { "inputs": { "systems": "systems" }, "locked": { "lastModified": 1710146030, "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "nixpkgs": { "locked": { "lastModified": 0, "narHash": "sha256-UHGnmQRnbykGt17ycgPddaQxbbs/XZfy9L3vW2RMZ0I=", "path": "/nix/store/y81rakc9v1cv0j0mbqgvnszf6gq5jgwb-source", "type": "path" }, "original": { "id": "nixpkgs", "type": "indirect" } }, "root": { "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } }, "systems": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", "owner": "nix-systems", "repo": "default", "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { "owner": "nix-systems", "repo": "default", "type": "github" } } }, "root": "root", "version": 7 } rocq-9.2.0/flake.nix000066400000000000000000000005231516144147600143010ustar00rootroot00000000000000{ inputs.flake-utils.url = "github:numtide/flake-utils"; outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: { packages = with import nixpkgs { inherit system; }; coq.override { version = ./.; }; defaultPackage = self.packages.${system}; } ); } rocq-9.2.0/gramlib/000077500000000000000000000000001516144147600141145ustar00rootroot00000000000000rocq-9.2.0/gramlib/LICENSE000066400000000000000000000032511516144147600151220ustar00rootroot00000000000000gramlib was derived from Daniel de Rauglaudre's camlp5 (https://github.com/camlp5/camlp5) whose licence follows: * Copyright (c) 2007-2017, INRIA (Institut National de Recherches en * Informatique et Automatique). All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of INRIA, nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY INRIA AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INRIA AND * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. rocq-9.2.0/gramlib/dune000066400000000000000000000003551516144147600147750ustar00rootroot00000000000000(library (name gramlib) (public_name rocq-runtime.gramlib) (modules_without_implementation plexing) (libraries rocq-runtime.lib)) (deprecated_library_name (old_public_name coq-core.gramlib) (new_public_name rocq-runtime.gramlib)) rocq-9.2.0/gramlib/gramext.ml000066400000000000000000000013041516144147600161130ustar00rootroot00000000000000(* camlp5r *) (* gramext.ml,v *) (* Copyright (c) INRIA 2007-2017 *) type position = | First | Last | Before of string | After of string type g_assoc = NonA | RightA | LeftA | BothA let pr_assoc = function | BothA -> Pp.str "multi associativity" | LeftA -> Pp.str "left associativity" | RightA -> Pp.str "right associativity" | NonA -> Pp.str "no associativity" (** Returns whether SELF means SELF, respectively on the left and on the right. *) let split_assoc = function | BothA -> (true, true) | LeftA -> (true, false) | RightA -> (false, true) | NonA -> (false, false) let self_on_the_left assoc = fst (split_assoc assoc) let self_on_the_right assoc = snd (split_assoc assoc) rocq-9.2.0/gramlib/gramext.mli000066400000000000000000000006741516144147600162750ustar00rootroot00000000000000(* camlp5r *) (* gramext.mli,v *) (* Copyright (c) INRIA 2007-2017 *) type position = | First | Last | Before of string | After of string type g_assoc = NonA | RightA | LeftA | BothA val pr_assoc : g_assoc -> Pp.t (** Prints a [g_assoc] value. *) val self_on_the_left : g_assoc -> bool (** Returns whether SELF means SELF on the left. *) val self_on_the_right : g_assoc -> bool (** Returns whether SELF means SELF on the right. *) rocq-9.2.0/gramlib/grammar.ml000066400000000000000000002106401516144147600160770ustar00rootroot00000000000000(* camlp5r *) (* grammar.ml,v *) (* Copyright (c) INRIA 2007-2017 *) open Gramext open Format open Util exception ParseError of string (** Raised by parsers when the first component of a stream pattern is accepted, but one of the following components is rejected. *) (* Functorial interface *) type norec = private [ `norec ] type mayrec = private [ `mayrec ] module type S = sig type keyword_state type te type 'c pattern type ty_pattern = TPattern : 'a pattern -> ty_pattern type peek_error = unit type 'a parser_v = ('a, peek_error) result (** Type combinators to factor the module type between explicit state passing in Grammar and global state in Procq *) type 'a with_gstate (** Reader of grammar state *) type 'a with_kwstate (** Read keyword state *) type 'a with_estate (** Read entry state *) type 'a mod_estate (** Read/write entry state *) module Parsable : sig type t (** [Parsable.t] Stream tokenizers with Rocq-specific functionality *) val make : ?loc:Loc.t -> (unit,char) Stream.t -> t (** [make ?loc strm] Build a parsable from stream [strm], resuming at position [?loc] *) val comments : t -> ((int * int) * string) list val loc : t -> Loc.t (** [loc pa] Return parsing position for [pa] *) val consume : t -> int -> unit with_kwstate (** [consume pa n] Discard [n] tokens from [pa], updating the parsing position *) end module Entry : sig type 'a t val make : string -> 'a t mod_estate val parse : 'a t -> Parsable.t -> 'a with_gstate val name : 'a t -> string type 'a parser_fun = { parser_fun : keyword_state -> (keyword_state,te) LStream.t -> 'a parser_v } val of_parser : string -> 'a parser_fun -> 'a t mod_estate val parse_token_stream : 'a t -> (keyword_state,te) LStream.t -> 'a parser_v with_gstate val print : Format.formatter -> 'a t -> unit with_kwstate with_estate val is_empty : 'a t -> bool with_estate type any_t = Any : 'a t -> any_t val accumulate_in : any_t list -> any_t list CString.Map.t with_estate val all_in : unit -> any_t list CString.Map.t with_estate end module rec Symbol : sig type ('self, 'trec, 'a) t val nterm : 'a Entry.t -> ('self, norec, 'a) t val nterml : 'a Entry.t -> string -> ('self, norec, 'a) t val list0 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list0sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val list1 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list1sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val opt : ('self, 'trec, 'a) t -> ('self, 'trec, 'a option) t val self : ('self, mayrec, 'self) t val next : ('self, mayrec, 'self) t val token : 'c pattern -> ('self, norec, 'c) t val tokens : ty_pattern list -> ('self, norec, unit) t val rules : 'a Rules.t list -> ('self, norec, 'a) t end and Rule : sig type ('self, 'trec, 'f, 'r) t val stop : ('self, norec, 'r, 'r) t val next : ('self, _, 'a, 'r) t -> ('self, _, 'b) Symbol.t -> ('self, mayrec, 'b -> 'a, 'r) t val next_norec : ('self, norec, 'a, 'r) Rule.t -> ('self, norec, 'b) Symbol.t -> ('self, norec, 'b -> 'a, 'r) t end and Rules : sig type 'a t val make : (_, norec, 'f, Loc.t -> 'a) Rule.t -> 'f -> 'a t end module Production : sig type 'a t val make : ('a, _, 'f, Loc.t -> 'a) Rule.t -> 'f -> 'a t end type 'a single_extend_statement = string option * Gramext.g_assoc option * 'a Production.t list type 'a extend_statement = | Reuse of string option * 'a Production.t list | Fresh of Gramext.position * 'a single_extend_statement list val generalize_symbol : ('a, 'tr, 'c) Symbol.t -> ('b, norec, 'c) Symbol.t option (* Used in custom entries, should tweak? *) val level_of_nonterm : ('a, norec, 'c) Symbol.t -> string option end module type ExtS = sig type keyword_state module EState : sig type t val empty : t end module GState : sig type t = { estate : EState.t; kwstate : keyword_state; recover : bool; has_non_assoc : bool; } end include S with type keyword_state := keyword_state and type 'a with_gstate := GState.t -> 'a and type 'a with_kwstate := keyword_state -> 'a and type 'a with_estate := EState.t -> 'a and type 'a mod_estate := EState.t -> EState.t * 'a type 's add_kw = { add_kw : 'c. 's -> 'c pattern -> 's } val safe_extend : 's add_kw -> EState.t -> 's -> 'a Entry.t -> 'a extend_statement -> EState.t * 's module Unsafe : sig val existing_entry : EState.t -> 'a Entry.t -> EState.t val existing_of_parser : EState.t -> 'a Entry.t -> 'a Entry.parser_fun -> EState.t end end (* Implementation *) module GMake (L : Plexing.S) : ExtS with type keyword_state := L.keyword_state and type te := L.te and type 'c pattern := 'c L.pattern = struct type te = L.te type 'c pattern = 'c L.pattern type ty_pattern = TPattern : 'a pattern -> ty_pattern type peek_error = unit type 'a parser_v = ('a, peek_error) result type 'a parser_t = (L.keyword_state,L.te) LStream.t -> 'a parser_v let (let*) : 'a parser_v -> ('a -> 'b parser_v) -> 'b parser_v = Result.bind let (let+) : 'a parser_v -> ('a ->' b) -> 'b parser_v = fun x f -> Result.map f x let (<+>) (x: 'a parser_v) (y:unit -> 'a parser_v) : 'a parser_v = match x with | Ok _ -> x | Error () -> y () (** Used to propagate possible presence of SELF/NEXT in a rule (binary and) *) type ('a, 'b, 'c) ty_and_rec = | NoRec2 : (norec, norec, norec) ty_and_rec | MayRec2 : ('a, 'b, mayrec) ty_and_rec (** Used to propagate possible presence of SELF/NEXT in a tree (ternary and) *) type ('a, 'b, 'c, 'd) ty_and_rec3 = | NoRec3 : (norec, norec, norec, norec) ty_and_rec3 | MayRec3 : ('a, 'b, 'c, mayrec) ty_and_rec3 type _ tag = .. module DMap = PolyMap.Make (struct type nonrec 'a tag = 'a tag = .. end) type 'a ty_entry = { ename : string; etag : 'a DMap.onetag; } and ('self, 'trec, 'a) ty_symbol = | Stoken : 'c pattern -> ('self, norec, 'c) ty_symbol | Stokens : ty_pattern list -> ('self, norec, unit) ty_symbol | Slist1 : ('self, 'trec, 'a) ty_symbol -> ('self, 'trec, 'a list) ty_symbol | Slist1sep : ('self, 'trec, 'a) ty_symbol * ('self, norec, unit) ty_symbol -> ('self, 'trec, 'a list) ty_symbol | Slist0 : ('self, 'trec, 'a) ty_symbol -> ('self, 'trec, 'a list) ty_symbol | Slist0sep : ('self, 'trec, 'a) ty_symbol * ('self, norec, unit) ty_symbol -> ('self, 'trec, 'a list) ty_symbol | Sopt : ('self, 'trec, 'a) ty_symbol -> ('self, 'trec, 'a option) ty_symbol | Sself : ('self, mayrec, 'self) ty_symbol | Snext : ('self, mayrec, 'self) ty_symbol | Snterm : 'a ty_entry -> ('self, norec, 'a) ty_symbol (* norec but the entry can nevertheless introduce a loop with the current entry*) | Snterml : 'a ty_entry * string -> ('self, norec, 'a) ty_symbol | Stree : ('self, 'trec, Loc.t -> 'a) ty_tree -> ('self, 'trec, 'a) ty_symbol and ('self, _, _, 'r) ty_rule = | TStop : ('self, norec, 'r, 'r) ty_rule | TNext : ('trr, 'trs, 'tr) ty_and_rec * ('self, 'trr, 'a, 'r) ty_rule * ('self, 'trs, 'b) ty_symbol -> ('self, 'tr, 'b -> 'a, 'r) ty_rule and ('self, 'trec, 'a) ty_tree = | Node : ('trn, 'trs, 'trb, 'tr) ty_and_rec3 * ('self, 'trn, 'trs, 'trb, 'b, 'a) ty_node -> ('self, 'tr, 'a) ty_tree | LocAct : 'k -> ('self, norec, 'k) ty_tree | DeadEnd : ('self, norec, 'k) ty_tree and ('self, 'trec, 'trecs, 'trecb, 'a, 'r) ty_node = { node : ('self, 'trec, 'a) ty_symbol; son : ('self, 'trecs, 'a -> 'r) ty_tree; brother : ('self, 'trecb, 'r) ty_tree; } type ('trecs, 'trecp, 'a) ty_rec_level = { assoc : g_assoc; lname : string option; lsuffix : ('a, 'trecs, 'a -> Loc.t -> 'a) ty_tree; lprefix : ('a, 'trecp, Loc.t -> 'a) ty_tree; } type 'a ty_level = Level : (_, _, 'a) ty_rec_level -> 'a ty_level type 'a ty_desc = | Dlevels of 'a ty_level list | Dparser of (L.keyword_state -> 'a parser_t) (** The closures are built by partially applying the parsing functions to [edesc] but without depending on the state (so when we update an entry we don't need to update closures in unrelated entries). This is an important optimisation, see eg https://gitlab.com/coq/coq/-/jobs/3585529623 (+40% on mathcomp-ssreflect, +15% on stdlib without this, significant slowdowns on most developments) *) type ('t,'a) entry_data = { eentry : 'a ty_entry; edesc : 'a ty_desc; estart : 't -> int -> 'a parser_t; econtinue : 't -> int option -> int -> int -> 'a -> 'a parser_t; } module rec EState : DMap.MapS with type 'a value := (GState.t, 'a) entry_data = DMap.Map(struct type 'a t = (GState.t, 'a) entry_data end) and GState : sig type t = { estate : EState.t; kwstate : L.keyword_state; recover : bool; has_non_assoc : bool; } end = struct type t = { estate : EState.t; kwstate : L.keyword_state; recover : bool; has_non_assoc : bool; } end open GState let get_entry estate e = try EState.find (DMap.tag_of_onetag e.etag) estate with Not_found -> assert false type 'a ty_rules = | TRules : (_, norec, 'act, Loc.t -> 'a) ty_rule * 'act -> 'a ty_rules type 'a ty_production = | TProd : ('a, _, 'act, Loc.t -> 'a) ty_rule * 'act -> 'a ty_production let rec derive_eps : type s r a. (s, r, a) ty_symbol -> bool = function Slist0 _ -> true | Slist0sep (_, _) -> true | Sopt _ -> true | Stree t -> tree_derive_eps t | Slist1 _ -> false | Slist1sep (_, _) -> false | Snterm _ -> false | Snterml (_, _) -> false | Snext -> false | Sself -> false | Stoken _ -> false | Stokens _ -> false and tree_derive_eps : type s tr a. (s, tr, a) ty_tree -> bool = function LocAct _ -> true | Node (_, {node = s; brother = bro; son = son}) -> derive_eps s && tree_derive_eps son || tree_derive_eps bro | DeadEnd -> false let eq_entry : type a1 a2. a1 ty_entry -> a2 ty_entry -> (a1, a2) eq option = fun e1 e2 -> DMap.eq_onetag e1.etag (DMap.tag_of_onetag e2.etag) let tok_pattern_eq_list pl1 pl2 = let f (TPattern p1) (TPattern p2) = Option.has_some (L.tok_pattern_eq p1 p2) in if List.for_all2eq f pl1 pl2 then Some Refl else None let rec eq_symbol : type s r1 r2 a1 a2. (s, r1, a1) ty_symbol -> (s, r2, a2) ty_symbol -> (a1, a2) eq option = fun s1 s2 -> match s1, s2 with Snterm e1, Snterm e2 -> eq_entry e1 e2 | Snterml (e1, l1), Snterml (e2, l2) -> if String.equal l1 l2 then eq_entry e1 e2 else None | Slist0 s1, Slist0 s2 -> begin match eq_symbol s1 s2 with None -> None | Some Refl -> Some Refl end | Slist0sep (s1, sep1), Slist0sep (s2, sep2) -> begin match eq_symbol s1 s2 with | None -> None | Some Refl -> match eq_symbol sep1 sep2 with | None -> None | Some Refl -> Some Refl end | Slist1 s1, Slist1 s2 -> begin match eq_symbol s1 s2 with None -> None | Some Refl -> Some Refl end | Slist1sep (s1, sep1), Slist1sep (s2, sep2) -> begin match eq_symbol s1 s2 with | None -> None | Some Refl -> match eq_symbol sep1 sep2 with | None -> None | Some Refl -> Some Refl end | Sopt s1, Sopt s2 -> begin match eq_symbol s1 s2 with None -> None | Some Refl -> Some Refl end | Stree _, Stree _ -> None | Sself, Sself -> Some Refl | Snext, Snext -> Some Refl | Stoken p1, Stoken p2 -> L.tok_pattern_eq p1 p2 | Stokens pl1, Stokens pl2 -> tok_pattern_eq_list pl1 pl2 | _ -> None let is_before : type s1 s2 r1 r2 a1 a2. (s1, r1, a1) ty_symbol -> (s2, r2, a2) ty_symbol -> bool = fun s1 s2 -> match s1, s2 with | Stoken p1, Stoken p2 -> L.tok_pattern_exact p1 && not (L.tok_pattern_exact p2) | Stoken _, _ -> true | _ -> false (** Ancillary datatypes *) type 'a ty_rec = MayRec : mayrec ty_rec | NoRec : norec ty_rec type ('a, 'b, 'c) ty_and_ex = | NR00 : (mayrec, mayrec, mayrec) ty_and_ex | NR01 : (mayrec, norec, mayrec) ty_and_ex | NR10 : (norec, mayrec, mayrec) ty_and_ex | NR11 : (norec, norec, norec) ty_and_ex type ('a, 'b) ty_mayrec_and_ex = | MayRecNR : ('a, 'b, _) ty_and_ex -> ('a, 'b) ty_mayrec_and_ex type ('s, 'a) ty_mayrec_symbol = | MayRecSymbol : ('s, _, 'a) ty_symbol -> ('s, 'a) ty_mayrec_symbol type ('s, 'a) ty_mayrec_tree = | MayRecTree : ('s, 'tr, 'a) ty_tree -> ('s, 'a) ty_mayrec_tree type ('s, 'a, 'r) ty_mayrec_rule = | MayRecRule : ('s, _, 'a, 'r) ty_rule -> ('s, 'a, 'r) ty_mayrec_rule type ('self, 'trec, _) ty_symbols = | TNil : ('self, norec, unit) ty_symbols | TCns : ('trh, 'trt, 'tr) ty_and_rec * ('self, 'trh, 'a) ty_symbol * ('self, 'trt, 'b) ty_symbols -> ('self, 'tr, 'a * 'b) ty_symbols (** ('i, 'p, 'f, 'r) rel_prod0 ~ βˆƒ α₁ ... Ξ±β‚™. p ≑ Ξ±β‚™ * ... α₁ * 'i ∧ f ≑ α₁ -> ... -> Ξ±β‚™ -> 'r *) type ('i, _, 'f, _) rel_prod0 = | Rel0 : ('i, 'i, 'f, 'f) rel_prod0 | RelS : ('i, 'p, 'f, 'a -> 'r) rel_prod0 -> ('i, 'a * 'p, 'f, 'r) rel_prod0 type ('p, 'k, 'r) rel_prod = (unit, 'p, 'k, 'r) rel_prod0 type ('s, 'tr, 'i, 'k, 'r) any_symbols = | AnyS : ('s, 'tr, 'p) ty_symbols * ('i, 'p, 'k, 'r) rel_prod0 -> ('s, 'tr, 'i, 'k, 'r) any_symbols type ('s, 'tr, 'k, 'r) ty_belast_rule = | Belast : ('trr, 'trs, 'tr) ty_and_rec * ('s, 'trr, 'k, 'a -> 'r) ty_rule * ('s, 'trs, 'a) ty_symbol -> ('s, 'tr, 'k, 'r) ty_belast_rule (* unfortunately, this is quadratic, but ty_rules aren't too long * (99% of the time of length less or equal 10 and maximum is 22 * when compiling Rocq and its standard library) *) let rec get_symbols : type s trec k r. (s, trec, k, r) ty_rule -> (s, trec, unit, k, r) any_symbols = let rec belast_rule : type s trr trs tr a k r. (trr, trs, tr) ty_and_rec -> (s, trr, k, r) ty_rule -> (s, trs, a) ty_symbol -> (s, tr, a -> k, r) ty_belast_rule = fun ar r s -> match ar, r with | NoRec2, TStop -> Belast (NoRec2, TStop, s) | MayRec2, TStop -> Belast (MayRec2, TStop, s) | NoRec2, TNext (NoRec2, r, s') -> let Belast (NoRec2, r, s') = belast_rule NoRec2 r s' in Belast (NoRec2, TNext (NoRec2, r, s), s') | MayRec2, TNext (_, r, s') -> let Belast (_, r, s') = belast_rule MayRec2 r s' in Belast (MayRec2, TNext (MayRec2, r, s), s') in function | TStop -> AnyS (TNil, Rel0) | TNext (MayRec2, r, s) -> let Belast (MayRec2, r, s) = belast_rule MayRec2 r s in let AnyS (r, pf) = get_symbols r in AnyS (TCns (MayRec2, s, r), RelS pf) | TNext (NoRec2, r, s) -> let Belast (NoRec2, r, s) = belast_rule NoRec2 r s in let AnyS (r, pf) = get_symbols r in AnyS (TCns (NoRec2, s, r), RelS pf) let get_rec_symbols (type s tr p) (s : (s, tr, p) ty_symbols) : tr ty_rec = match s with TCns (MayRec2, _, _) -> MayRec | TCns (NoRec2, _, _) -> NoRec | TNil -> NoRec let get_rec_tree (type s tr f) (s : (s, tr, f) ty_tree) : tr ty_rec = match s with Node (MayRec3, _) -> MayRec | Node (NoRec3, _) -> NoRec | LocAct _ -> NoRec | DeadEnd -> NoRec let and_symbols_tree (type s trs trt p f) (s : (s, trs, p) ty_symbols) (t : (s, trt, f) ty_tree) : (trs, trt) ty_mayrec_and_ex = match get_rec_symbols s, get_rec_tree t with | MayRec, MayRec -> MayRecNR NR00 | MayRec, NoRec -> MayRecNR NR01 | NoRec, MayRec -> MayRecNR NR10 | NoRec, NoRec -> MayRecNR NR11 let and_and_tree (type s tr' trt tr trn trs trb f) (ar : (tr', trt, tr) ty_and_rec) (arn : (trn, trs, trb, trt) ty_and_rec3) (t : (s, trb, f) ty_tree) : (tr', trb, tr) ty_and_rec = match ar, arn, get_rec_tree t with | MayRec2, _, MayRec -> MayRec2 | MayRec2, _, NoRec -> MayRec2 | NoRec2, NoRec3, NoRec -> NoRec2 let insert_tree (type s trs trt tr p k a) entry_name (ar : (trs, trt, tr) ty_and_ex) (gsymbols : (s, trs, p) ty_symbols) (pf : (p, k, a) rel_prod) (action : k) (tree : (s, trt, a) ty_tree) : (s, tr, a) ty_tree = let rec insert : type trs trt tr p f k. (trs, trt, tr) ty_and_ex -> (s, trs, p) ty_symbols -> (p, k, f) rel_prod -> (s, trt, f) ty_tree -> k -> (s, tr, f) ty_tree = fun ar symbols pf tree action -> match symbols, pf with TCns (ars, s, sl), RelS pf -> (* descent in tree at symbol [s] *) insert_in_tree ar ars s sl pf tree action | TNil, Rel0 -> (* insert the action *) let node (type tb) ({node = s; son = son; brother = bro} : (_, _, _, tb, _, _) ty_node) = let ar : (norec, tb, tb) ty_and_ex = match get_rec_tree bro with MayRec -> NR10 | NoRec -> NR11 in {node = s; son = son; brother = insert ar TNil Rel0 bro action} in match ar, tree with | NR10, Node (_, n) -> Node (MayRec3, node n) | NR11, Node (NoRec3, n) -> Node (NoRec3, node n) | NR11, LocAct old_action -> (* What to do about this warning? For now it is disabled *) if false then begin let msg = " Grammar extension: " ^ (if entry_name = "" then "" else "in ["^entry_name^"%s], ") ^ "some rule has been masked" in Feedback.msg_warning (Pp.str msg) end; LocAct action | NR11, DeadEnd -> LocAct action and insert_in_tree : type trs trs' trs'' trt tr a p f k. (trs'', trt, tr) ty_and_ex -> (trs, trs', trs'') ty_and_rec -> (s, trs, a) ty_symbol -> (s, trs', p) ty_symbols -> (p, k, a -> f) rel_prod -> (s, trt, f) ty_tree -> k -> (s, tr, f) ty_tree = fun ar ars s sl pf tree action -> let ar : (trs'', trt, tr) ty_and_rec = match ar with NR11 -> NoRec2 | NR00 -> MayRec2 | NR01 -> MayRec2 | NR10 -> MayRec2 in match try_insert ar ars s sl pf tree action with Some t -> t | None -> let node ar = {node = s; son = insert ar sl pf DeadEnd action; brother = tree} in match ar, ars, get_rec_symbols sl with | MayRec2, MayRec2, MayRec -> Node (MayRec3, node NR01) | MayRec2, _, NoRec -> Node (MayRec3, node NR11) | NoRec2, NoRec2, NoRec -> Node (NoRec3, node NR11) and try_insert : type trs trs' trs'' trt tr a p f k. (trs'', trt, tr) ty_and_rec -> (trs, trs', trs'') ty_and_rec -> (s, trs, a) ty_symbol -> (s, trs', p) ty_symbols -> (p, k, a -> f) rel_prod -> (s, trt, f) ty_tree -> k -> (s, tr, f) ty_tree option = fun ar ars symb symbl pf tree action -> match tree with Node (arn, {node = symb1; son = son; brother = bro}) -> (* merging rule [symb; symbl -> action] in tree [symb1; son | bro] *) begin match eq_symbol symb symb1 with | Some Refl -> (* reducing merge of [symb; symbl -> action] with [symb1; son] to merge of [symbl -> action] with [son] *) let MayRecNR arss = and_symbols_tree symbl son in let son = insert arss symbl pf son action in let node = {node = symb1; son = son; brother = bro} in (* propagate presence of SELF/NEXT *) begin match ar, ars, arn, arss with | MayRec2, _, _, _ -> Some (Node (MayRec3, node)) | NoRec2, NoRec2, NoRec3, NR11 -> Some (Node (NoRec3, node)) end | None -> let ar' = and_and_tree ar arn bro in if is_before symb1 symb || derive_eps symb && not (derive_eps symb1) then (* inserting new rule after current rule, i.e. in [bro] *) let bro = match try_insert ar' ars symb symbl pf bro action with Some bro -> (* could insert in [bro] *) bro | None -> (* not ok to insert in [bro] or after; we insert now *) let MayRecNR arss = and_symbols_tree symbl DeadEnd in let son = insert arss symbl pf DeadEnd action in let node = {node = symb; son = son; brother = bro} in (* propagate presence of SELF/NEXT *) match ar, ars, arn, arss with | MayRec2, _, _, _ -> Node (MayRec3, node) | NoRec2, NoRec2, NoRec3, NR11 -> Node (NoRec3, node) in let node = {node = symb1; son = son; brother = bro} in (* propagate presence of SELF/NEXT *) match ar, arn with | MayRec2, _ -> Some (Node (MayRec3, node)) | NoRec2, NoRec3 -> Some (Node (NoRec3, node)) else (* should insert in [bro] or before the tree [symb1; son | bro] *) match try_insert ar' ars symb symbl pf bro action with Some bro -> (* could insert in [bro] *) let node = {node = symb1; son = son; brother = bro} in begin match ar, arn with | MayRec2, _ -> Some (Node (MayRec3, node)) | NoRec2, NoRec3 -> Some (Node (NoRec3, node)) end | None -> (* should insert before [symb1; son | bro] *) None end | LocAct _ -> None | DeadEnd -> None in insert ar gsymbols pf tree action let insert_tree_norec (type s p k a) entry_name (gsymbols : (s, norec, p) ty_symbols) (pf : (p, k, a) rel_prod) (action : k) (tree : (s, norec, a) ty_tree) : (s, norec, a) ty_tree = insert_tree entry_name NR11 gsymbols pf action tree let insert_tree (type s trs trt p k a) entry_name (gsymbols : (s, trs, p) ty_symbols) (pf : (p, k, a) rel_prod) (action : k) (tree : (s, trt, a) ty_tree) : (s, a) ty_mayrec_tree = let MayRecNR ar = and_symbols_tree gsymbols tree in MayRecTree (insert_tree entry_name ar gsymbols pf action tree) let srules (type self a) (rl : a ty_rules list) : (self, norec, a) ty_symbol = let rec retype_tree : type s a. (s, norec, a) ty_tree -> (self, norec, a) ty_tree = function | Node (NoRec3, {node = s; son = son; brother = bro}) -> Node (NoRec3, {node = retype_symbol s; son = retype_tree son; brother = retype_tree bro}) | LocAct k -> LocAct k | DeadEnd -> DeadEnd and retype_symbol : type s a. (s, norec, a) ty_symbol -> (self, norec, a) ty_symbol = function | Stoken p -> Stoken p | Stokens l -> Stokens l | Slist1 s -> Slist1 (retype_symbol s) | Slist1sep (s, sep) -> Slist1sep (retype_symbol s, retype_symbol sep) | Slist0 s -> Slist0 (retype_symbol s) | Slist0sep (s, sep) -> Slist0sep (retype_symbol s, retype_symbol sep) | Sopt s -> Sopt (retype_symbol s) | Snterm e -> Snterm e | Snterml (e, l) -> Snterml (e, l) | Stree t -> Stree (retype_tree t) in let rec retype_rule : type s k r. (s, norec, k, r) ty_rule -> (self, norec, k, r) ty_rule = function | TStop -> TStop | TNext (NoRec2, r, s) -> TNext (NoRec2, retype_rule r, retype_symbol s) in let t = List.fold_left (fun tree (TRules (symbols, action)) -> let symbols = retype_rule symbols in let AnyS (symbols, pf) = get_symbols symbols in insert_tree_norec "" symbols pf action tree) DeadEnd rl in Stree t let is_level_labelled n (Level lev) = match lev.lname with Some n1 -> n = n1 | None -> false let insert_level (type s tr p k) entry_name (symbols : (s, tr, p) ty_symbols) (pf : (p, k, Loc.t -> s) rel_prod) (action : k) (slev : s ty_level) : s ty_level = match symbols with | TCns (_, Sself, symbols) -> (* Insert a rule of the form "SELF; ...." *) let Level slev = slev in let RelS pf = pf in let MayRecTree lsuffix = insert_tree entry_name symbols pf action slev.lsuffix in Level {assoc = slev.assoc; lname = slev.lname; lsuffix = lsuffix; lprefix = slev.lprefix} | _ -> (* Insert a rule not starting with SELF *) let Level slev = slev in let MayRecTree lprefix = insert_tree entry_name symbols pf action slev.lprefix in Level {assoc = slev.assoc; lname = slev.lname; lsuffix = slev.lsuffix; lprefix = lprefix} let empty_lev lname assoc = let assoc = match assoc with Some a -> a | None -> LeftA in Level {assoc = assoc; lname = lname; lsuffix = DeadEnd; lprefix = DeadEnd} let err_no_level lev e = let msg = sprintf "Grammar.extend: No level labelled \"%s\" in entry \"%s\"" lev e in failwith msg let get_position entry position levs = match position with First -> [], levs | Last -> levs, [] | Before n -> let rec get = function [] -> err_no_level n entry.ename | lev :: levs -> if is_level_labelled n lev then [], lev :: levs else let (levs1, levs2) = get levs in lev :: levs1, levs2 in get levs | After n -> let rec get = function [] -> err_no_level n entry.ename | lev :: levs -> if is_level_labelled n lev then [lev], levs else let (levs1, levs2) = get levs in lev :: levs1, levs2 in get levs let get_level entry name levs = match name with | Some n -> let rec get = function [] -> err_no_level n entry.ename | lev :: levs -> if is_level_labelled n lev then [], lev, levs else let (levs1, rlev, levs2) = get levs in lev :: levs1, rlev, levs2 in get levs | None -> begin match levs with lev :: levs -> [], lev, levs | [] -> let msg = sprintf "Grammar.extend: No top level in entry \"%s\"" entry.ename in failwith msg end let change_to_self0 (type s) (type trec) (type a) (entry : s ty_entry) : (s, trec, a) ty_symbol -> (s, a) ty_mayrec_symbol = function | Snterm e -> begin match eq_entry e entry with | None -> MayRecSymbol (Snterm e) | Some Refl -> MayRecSymbol (Sself) end | x -> MayRecSymbol x let rec change_to_self : type s trec a r. s ty_entry -> (s, trec, a, r) ty_rule -> (s, a, r) ty_mayrec_rule = fun e r -> match r with | TStop -> MayRecRule TStop | TNext (_, r, t) -> let MayRecRule r = change_to_self e r in let MayRecSymbol t = change_to_self0 e t in MayRecRule (TNext (MayRec2, r, t)) type 's add_kw = { add_kw : 'c. 's -> 'c pattern -> 's } let insert_tokens {add_kw} lstate symbols = let rec insert : type s trec a. _ -> (s, trec, a) ty_symbol -> _ = fun lstate -> function | Slist0 s -> insert lstate s | Slist1 s -> insert lstate s | Slist0sep (s, t) -> let lstate = insert lstate s in insert lstate t | Slist1sep (s, t) -> let lstate = insert lstate s in insert lstate t | Sopt s -> insert lstate s | Stree t -> tinsert lstate t | Stoken tok -> add_kw lstate tok | Stokens (TPattern tok::_) -> (* Only the first token is liable to trigger a keyword effect *) add_kw lstate tok | Stokens [] -> assert false | Snterm _ | Snterml _ | Snext | Sself -> lstate and tinsert : type s tr a. _ -> (s, tr, a) ty_tree -> _ = fun lstate -> function Node (_, {node = s; brother = bro; son = son}) -> let lstate = insert lstate s in let lstate = tinsert lstate bro in tinsert lstate son | LocAct _ | DeadEnd -> lstate and linsert : type s tr p. _ -> (s, tr, p) ty_symbols -> _ = fun lstate -> function | TNil -> lstate | TCns (_, s, r) -> let lstate = insert lstate s in linsert lstate r in linsert lstate symbols type 'a single_extend_statement = string option * Gramext.g_assoc option * 'a ty_production list type 'a extend_statement = | Reuse of string option * 'a ty_production list | Fresh of Gramext.position * 'a single_extend_statement list let add_prod add_kw entry (lstate, lev) (TProd (symbols, action)) = let MayRecRule symbols = change_to_self entry symbols in let AnyS (symbols, pf) = get_symbols symbols in let lstate = insert_tokens add_kw lstate symbols in lstate, insert_level entry.ename symbols pf action lev let levels_of_rules add_kw lstate entry edata st = let elev = match edata.edesc with Dlevels elev -> elev | Dparser _ -> let msg = sprintf "Grammar.extend: entry not extensible: \"%s\"" entry.ename in failwith msg in match st with | Reuse (name, []) -> lstate, elev | Reuse (name, prods) -> let (levs1, lev, levs2) = get_level entry name elev in let lstate, lev = List.fold_left (fun lev prod -> add_prod add_kw entry lev prod) (lstate, lev) prods in lstate, levs1 @ [lev] @ levs2 | Fresh (position, rules) -> let (levs1, levs2) = get_position entry position elev in let fold (lstate, levs) (lname, assoc, prods) = let lev = empty_lev lname assoc in let lstate, lev = List.fold_left (fun lev prod -> add_prod add_kw entry lev prod) (lstate, lev) prods in lstate, lev :: levs in let lstate, levs = List.fold_left fold (lstate, []) rules in lstate, levs1 @ List.rev levs @ levs2 type 's ex_symbols = | ExS : ('s, 'tr, 'p) ty_symbols -> 's ex_symbols let rec flatten_tree : type s tr a. (s, tr, a) ty_tree -> s ex_symbols list = function DeadEnd -> [] | LocAct _ -> [ExS TNil] | Node (_, {node = n; brother = b; son = s}) -> List.map (fun (ExS l) -> ExS (TCns (MayRec2, n, l))) (flatten_tree s) @ flatten_tree b let utf8_string_escaped s = let b = Buffer.create (String.length s) in let rec loop i = if i = String.length s then Buffer.contents b else begin begin match s.[i] with '"' -> Buffer.add_string b "\\\"" | '\\' -> Buffer.add_string b "\\\\" | '\n' -> Buffer.add_string b "\\n" | '\t' -> Buffer.add_string b "\\t" | '\r' -> Buffer.add_string b "\\r" | '\b' -> Buffer.add_string b "\\b" | c -> Buffer.add_char b c end; loop (i + 1) end in loop 0 let string_escaped s = utf8_string_escaped s let print_str ppf s = fprintf ppf "\"%s\"" (string_escaped s) let print_token kwstate b ppf p = match L.tok_pattern_strings kwstate p with | "", Some s -> print_str ppf s | con, Some prm -> if b then fprintf ppf "%s@ %a" con print_str prm else fprintf ppf "(%s@ %a)" con print_str prm | con, None -> fprintf ppf "%s" con let print_tokens kwstate ppf = function | [] -> assert false | TPattern p :: pl -> fprintf ppf "[%a%a]" (print_token kwstate true) p (fun ppf -> List.iter (function TPattern p -> fprintf ppf ";@ "; print_token kwstate true ppf p)) pl let rec print_symbol : type s tr r. _ -> formatter -> (s, tr, r) ty_symbol -> unit = fun kwstate ppf -> function | Slist0 s -> fprintf ppf "LIST0 %a" (print_symbol1 kwstate) s | Slist0sep (s, t) -> fprintf ppf "LIST0 %a SEP %a" (print_symbol1 kwstate) s (print_symbol1 kwstate) t | Slist1 s -> fprintf ppf "LIST1 %a" (print_symbol1 kwstate) s | Slist1sep (s, t) -> fprintf ppf "LIST1 %a SEP %a" (print_symbol1 kwstate) s (print_symbol1 kwstate) t | Sopt s -> fprintf ppf "OPT %a" (print_symbol1 kwstate) s | Stoken p -> print_token kwstate true ppf p | Stokens [TPattern p] -> print_token kwstate true ppf p | Stokens pl -> print_tokens kwstate ppf pl | Snterml (e, l) -> fprintf ppf "%s%s@ LEVEL@ %a" e.ename "" print_str l | s -> (print_symbol1 kwstate) ppf s and print_symbol1 : type s tr r. _ -> formatter -> (s, tr, r) ty_symbol -> unit = fun kwstate ppf -> function | Snterm e -> fprintf ppf "%s%s" e.ename "" | Sself -> pp_print_string ppf "SELF" | Snext -> pp_print_string ppf "NEXT" | Stoken p -> print_token kwstate false ppf p | Stokens [TPattern p] -> print_token kwstate false ppf p | Stokens pl -> print_tokens kwstate ppf pl | Stree t -> print_level kwstate ppf pp_print_space (flatten_tree t) | s -> fprintf ppf "(%a)" (print_symbol kwstate) s and print_rule : type s tr p. _ -> formatter -> (s, tr, p) ty_symbols -> unit = fun kwstate ppf symbols -> fprintf ppf "@["; let rec fold : type s tr p. _ -> (s, tr, p) ty_symbols -> unit = fun sep symbols -> match symbols with | TNil -> () | TCns (_, symbol, symbols) -> fprintf ppf "%t%a" sep (print_symbol kwstate) symbol; fold (fun ppf -> fprintf ppf ";@ ") symbols in let () = fold (fun ppf -> ()) symbols in fprintf ppf "@]" and print_level : type s. _ -> _ -> _ -> s ex_symbols list -> _ = fun kwstate ppf pp_print_space rules -> fprintf ppf "@[[ "; let () = Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf "%a| " pp_print_space ()) (fun ppf (ExS rule) -> print_rule kwstate ppf rule) ppf rules in fprintf ppf " ]@]" let print_levels kwstate ppf elev = Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf "@,| ") (fun ppf (Level lev) -> let rules = List.map (fun (ExS t) -> ExS (TCns (MayRec2, Sself, t))) (flatten_tree lev.lsuffix) @ flatten_tree lev.lprefix in fprintf ppf "@["; begin match lev.lname with Some n -> fprintf ppf "%a@;<1 2>" print_str n | None -> () end; begin match lev.assoc with BothA -> fprintf ppf "BOTHA" | LeftA -> fprintf ppf "LEFTA" | RightA -> fprintf ppf "RIGHTA" | NonA -> fprintf ppf "NONA" end; fprintf ppf "@]@;<1 2>"; print_level kwstate ppf pp_force_newline rules) ppf elev let print_entry estate kwstate ppf e = fprintf ppf "@[[ "; begin match (get_entry estate e).edesc with Dlevels elev -> print_levels kwstate ppf elev | Dparser _ -> fprintf ppf "" end; fprintf ppf " ]@]" let name_of_symbol : type s tr a. s ty_entry -> (s, tr, a) ty_symbol -> string = fun entry -> function Snterm e -> "[" ^ e.ename ^ "]" | Snterml (e, l) -> "[" ^ e.ename ^ " level " ^ l ^ "]" | Sself -> "[" ^ entry.ename ^ "]" | Snext -> "[" ^ entry.ename ^ "]" | Stoken tok -> L.tok_text tok | Stokens tokl -> String.concat " " (List.map (function TPattern tok -> L.tok_text tok) tokl) | Slist0 _ -> assert false | Slist1sep _ -> assert false | Slist1 _ -> assert false | Slist0sep _ -> assert false | Sopt _ -> assert false | Stree _ -> assert false type ('r, 'f) tok_list = | TokNil : ('f, 'f) tok_list | TokCns : 'a pattern * ('r, 'f) tok_list -> ('a -> 'r, 'f) tok_list type ('s, 'f) tok_tree = TokTree : 'a pattern * ('s, _, 'a -> 'r) ty_tree * ('r, 'f) tok_list -> ('s, 'f) tok_tree let rec get_token_list : type s tr a r f. s ty_entry -> a pattern -> (r, f) tok_list -> (s, tr, a -> r) ty_tree -> (s, f) tok_tree option = fun entry last_tok rev_tokl tree -> match tree with Node (_, {node = Stoken tok; son = son; brother = DeadEnd}) -> get_token_list entry tok (TokCns (last_tok, rev_tokl)) son | _ -> match rev_tokl with | TokNil -> None | _ -> Some (TokTree (last_tok, tree, rev_tokl)) let rec name_of_symbol_failed : type s tr a. s ty_entry -> (s, tr, a) ty_symbol -> _ = fun entry -> function | Slist0 s -> name_of_symbol_failed entry s | Slist0sep (s, _) -> name_of_symbol_failed entry s | Slist1 s -> name_of_symbol_failed entry s | Slist1sep (s, _) -> name_of_symbol_failed entry s | Sopt s -> name_of_symbol_failed entry s | Stree t -> name_of_tree_failed entry t | s -> name_of_symbol entry s and name_of_tree_failed : type s tr a. s ty_entry -> (s, tr, a) ty_tree -> _ = fun entry -> function Node (_, {node = s; son = son; brother = bro}) -> let tokl = match s with Stoken tok -> get_token_list entry tok TokNil son | _ -> None in let txt = match tokl with | None -> let txt = name_of_symbol_failed entry s in let txt = match s, son with Sopt _, Node _ -> txt ^ " or " ^ name_of_tree_failed entry son | _ -> txt in txt | Some (TokTree (last_tok, _, rev_tokl)) -> let rec build_str : type a b. string -> (a, b) tok_list -> string = fun s -> function | TokNil -> s | TokCns (tok, t) -> build_str (L.tok_text tok ^ " " ^ s) t in build_str (L.tok_text last_tok) rev_tokl in begin match bro with | DeadEnd -> txt | LocAct _ -> "nothing else" | Node _ -> txt ^ " or " ^ name_of_tree_failed entry bro end | DeadEnd -> "???" | LocAct _ -> "nothing else" let tree_failed (type s tr a) (entry : s ty_entry) (prev_symb_result : a) (prev_symb : (s, tr, a) ty_symbol) tree = let txt = name_of_tree_failed entry tree in let txt = match prev_symb with Slist0 s -> let txt1 = name_of_symbol_failed entry s in txt1 ^ " or " ^ txt ^ " expected" | Slist1 s -> let txt1 = name_of_symbol_failed entry s in txt1 ^ " or " ^ txt ^ " expected" | Slist0sep (s, sep) -> begin match prev_symb_result with [] -> let txt1 = name_of_symbol_failed entry s in txt1 ^ " or " ^ txt ^ " expected" | _ -> let txt1 = name_of_symbol_failed entry sep in txt1 ^ " or " ^ txt ^ " expected" end | Slist1sep (s, sep) -> begin match prev_symb_result with [] -> let txt1 = name_of_symbol_failed entry s in txt1 ^ " or " ^ txt ^ " expected" | _ -> let txt1 = name_of_symbol_failed entry sep in txt1 ^ " or " ^ txt ^ " expected" end | Sopt _ -> txt ^ " expected" | Stree _ -> txt ^ " expected" | Snterm _ | Snterml _ | Sself | Snext | Stoken _ | Stokens _ -> txt ^ " expected after " ^ name_of_symbol_failed entry prev_symb in txt ^ " (in [" ^ entry.ename ^ "])" let symb_failed entry prev_symb_result prev_symb symb = let tree = Node (MayRec3, {node = symb; brother = DeadEnd; son = DeadEnd}) in tree_failed entry prev_symb_result prev_symb tree (* XXX don't use exceptions for this *) exception TokenListFailed : 's ty_entry * 'a * ('s, 'tr, 'a) ty_symbol * ('s, 'b, 'c) ty_tree -> exn let level_number entry lab = let rec lookup levn = function [] -> failwith ("unknown level " ^ lab) | lev :: levs -> if is_level_labelled lab lev then levn else lookup (succ levn) levs in match entry.edesc with Dlevels elev -> lookup 0 elev | Dparser _ -> raise Not_found let rec top_symb : type s tr a. s ty_entry -> (s, tr, a) ty_symbol -> (s, norec, a) ty_symbol parser_v = fun entry -> function Sself -> Ok (Snterm entry) | Snext -> Ok (Snterm entry) | Snterml (e, _) -> Ok (Snterm e) | Slist1sep (s, sep) -> let+ s = top_symb entry s in Slist1sep (s, sep) | _ -> Error () let entry_of_symb : type s tr a. s ty_entry -> (s, tr, a) ty_symbol -> a ty_entry parser_v = fun entry -> function Sself -> Ok entry | Snext -> Ok entry | Snterm e -> Ok e | Snterml (e, _) -> Ok e | _ -> Error () let top_tree : type s tr a. s ty_entry -> (s, tr, a) ty_tree -> (s, tr, a) ty_tree parser_v = fun entry -> function | Node (MayRec3, {node = s; brother = bro; son = son}) -> let+ s' = top_symb entry s in Node (MayRec3, {node = s'; brother = bro; son = son}) | Node (NoRec3, {node = s; brother = bro; son = son}) -> let+ s' = top_symb entry s in Node (NoRec3, {node = s'; brother = bro; son = son}) | LocAct _ | DeadEnd -> Error () let warn_tolerance = CWarnings.(create_in (create_warning ~name:"level-tolerance" ~from:[CoreCategories.parsing; Deprecation.Version.v9_2] ()) ~quickfix:(fun ~loc (_, _, qf) -> qf) Pp.(fun (e, msg, _) -> strbrk "In " ++ str e ++ str ", tolerating this expression at" ++ strbrk " a higher level than expected " ++ strbrk msg ++ str "." ++ strbrk " This tolerance will be eventually removed." ++ strbrk " Insert parentheses or try to lower the level at which the top symbol of this expression is parsed.")) let warn_recover_qf ename bp ?ep strm__ msg = let has_ep = Option.has_some ep in let ep = Option.default (LStream.count strm__) ep in let loc = LStream.interval_loc bp ep strm__ in let qf = let paren_enames = ["term"; "pattern"; "ltac_expr"] in if not (has_ep && List.mem ename paren_enames) then [] else let qf le s = Quickfix.make ~loc:(le loc 0 0) (Pp.str s) in [qf Loc.sub "("; qf Loc.after ")"] in warn_tolerance ~loc (ename, msg, qf) let warn_recover ename bp ?ep strm__ = warn_recover_qf ename bp ?ep strm__ "by the notation started on the left" let warn_recover_continuation ename bp ep strm__ strict = let msg = "by the notation continuing on the right" ^ if not strict then "" else " (which is not left-associative)" in warn_recover_qf ename bp ~ep strm__ msg let warn_recover_last_start ename bp ep strm__ = warn_recover_qf ename bp ~ep strm__ "(there is no next level of last level)" let empty_entry ename levn strm = raise (ParseError ("entry [" ^ ename ^ "] is empty")) let start_parser_of_entry gstate entry levn (strm:_ LStream.t) = (get_entry gstate.estate entry).estart gstate levn strm let continue_parser_of_entry gstate entry levfrom levn bp a (strm:_ LStream.t) = (get_entry gstate.estate entry).econtinue gstate levfrom levn bp a strm (** nlevn: level for Snext alevn: level for recursive calls on the right-hand side of the rule (depending on associativity) *) let rec parser_of_tree : type s tr r. s ty_entry -> int -> int -> (s, tr, r) ty_tree -> GState.t -> r parser_t = fun entry nlevn alevn -> function | DeadEnd -> (fun _ (strm__ : _ LStream.t) -> Error ()) | LocAct act -> (fun _ (strm__ : _ LStream.t) -> Ok act) | Node (_, {node = Sself; son = LocAct act; brother = DeadEnd}) -> (* SELF on the right-hand side of the last rule *) (fun gstate (strm__ : _ LStream.t) -> let+ a = start_parser_of_entry gstate entry alevn strm__ in act a) | Node (_, {node = Sself; son = LocAct act; brother = bro}) -> (* SELF on the right-hand side of a rule *) let p2 = parser_of_tree entry nlevn alevn bro in (fun gstate (strm__ : _ LStream.t) -> match start_parser_of_entry gstate entry alevn strm__ with | Ok a -> Ok (act a) | Error () -> p2 gstate strm__) | Node (_, {node = Stoken tok; son = son; brother = DeadEnd}) -> parser_of_token_list entry nlevn alevn tok son | Node (_, {node = Stoken tok; son = son; brother = bro}) -> let p2 = parser_of_tree entry nlevn alevn bro in let p1 = parser_of_token_list entry nlevn alevn tok son in (fun gstate (strm__ : _ LStream.t) -> p1 gstate strm__ <+> (fun () -> p2 gstate strm__)) | Node (_, {node = s; son = son; brother = DeadEnd}) -> let ps = parser_of_symbol entry nlevn s in let p1 = parser_of_tree entry nlevn alevn son in let p1 = parser_cont p1 entry nlevn alevn s son in (fun gstate (strm__ : _ LStream.t) -> let bp = LStream.count strm__ in let* a = ps gstate strm__ in p1 gstate bp a strm__) | Node (_, {node = s; son = son; brother = bro}) -> let ps = parser_of_symbol entry nlevn s in let p1 = parser_of_tree entry nlevn alevn son in let p1 = parser_cont p1 entry nlevn alevn s son in let p2 = parser_of_tree entry nlevn alevn bro in (fun gstate (strm : _ LStream.t) -> let bp = LStream.count strm in match ps gstate strm with | Ok a -> p1 gstate bp a strm | Error () -> p2 gstate strm) and parser_cont : type s tr tr' a r. (GState.t -> (a -> r) parser_t) -> s ty_entry -> int -> int -> (s, tr, a) ty_symbol -> (s, tr', a -> r) ty_tree -> GState.t -> int -> a -> _ -> r parser_v = fun p1 entry nlevn alevn s son gstate bp a0 (strm__ : _ LStream.t) -> match p1 gstate strm__ with | Ok v -> Ok (v a0) | Error () -> let fail a = raise (ParseError (tree_failed entry a s son)) in let or_fail a x = match x with Ok x -> x | Error () -> fail a in (* Recover from a success on [s] with result [a] followed by a failure on [son] in a rule of the form [a = s; son] *) (* Discard the rule if what has been consumed before failing is the empty sequence (due to some OPT or LIST0); example: Β« OPT "!"; ident Β» fails to see an ident and the OPT was resolved into the empty sequence, with application e.g. to being able to safely write Β« LIST1 [ OPT "!"; id = ident -> id] Β». *) if LStream.count strm__ == bp then Error () else if not gstate.recover then fail a0 else (* Try to replay the son with the top occurrence of NEXT (by default at level nlevn) and trailing SELF (by default at alevn) replaced with self at top level; This allows for instance to recover from a failure on the second SELF of Β« SELF; "\/"; SELF Β» by doing as if it were Β« SELF; "\/"; same-entry-at-top-level Β» with application e.g. to accept "A \/ forall x, x = x" w/o requiring the expected parentheses as in "A \/ (forall x, x = x)". *) match let* top = top_tree entry son in parser_of_tree entry nlevn alevn top gstate strm__ with | Ok a -> warn_recover entry.ename bp strm__; Ok (a a0) | Error () -> (* In case of success on just SELF, NEXT or an explicit call to a subentry followed by a failure on the rest (son), retry parsing as if this entry had been called at its toplevel; example: Β« "{"; entry-at-some-level; "}" Β» fails on "}" and is retried with Β« "{"; same-entry-at-top-level; "}" Β», allowing e.g. to parse Β« {1 + 1} Β» while Β« {(1 + 1)} Β» would have been expected according to the level. *) let p1 = parser_of_tree entry nlevn alevn son in let a = let* s' = entry_of_symb entry s in continue_parser_of_entry gstate s' None 0 bp a0 strm__ in let ep = LStream.count strm__ in let a = or_fail a0 a in let act = or_fail a (p1 gstate strm__) in warn_recover entry.ename bp ~ep strm__; Ok (act a) (** [parser_of_token_list] attempts to look-ahead an arbitrary-long finite sequence of tokens. E.g., in [ [ "foo"; "bar1"; "bar3"; ... -> action1 | "foo"; "bar2"; ... -> action2 | other-rules ] ] compiled as: [ [ "foo"; ["bar1"; "bar3"; ... -> action1 |"bar2"; ... -> action2] | other-rules ] ] this is able to look ahead "foo"; "bar1"; "bar3" and if not found "foo"; "bar1", then, if still not found, "foo"; "bar2" _without_ consuming the tokens until it is sure that a longest chain of tokens (before finding non-terminals or the end of the production) is found (and backtracking to [other-rules] if no such longest chain can be found). *) and parser_of_token_list : type s tr lt r. s ty_entry -> int -> int -> lt pattern -> (s, tr, lt -> r) ty_tree -> GState.t -> r parser_t = fun entry nlevn alevn tok tree -> let rec loop : type tr lt r. int -> lt pattern -> (s, tr, r) ty_tree -> GState.t -> lt -> r parser_t = fun n last_tok tree -> match tree with | Node (_, {node = Stoken tok; son = son; brother = bro}) -> let p2 = loop n last_tok bro in let p1 = loop (n+1) tok son in fun gstate last_a strm -> (match Option.bind (LStream.peek_nth gstate.kwstate n strm) (L.tok_match tok) with | Some a -> (match p1 gstate a strm with | Ok act -> Ok (act a) | Error () -> (try p2 gstate last_a strm with TokenListFailed _ -> raise (TokenListFailed (entry, a, Stoken tok, son)))) | None -> (try p2 gstate last_a strm with TokenListFailed _ -> raise (TokenListFailed (entry, last_a, Stoken last_tok, tree)))) | DeadEnd -> fun gstate last_a strm -> Error () | _ -> let ps = parser_of_tree entry nlevn alevn tree in fun gstate last_a strm -> for _i = 1 to n do LStream.junk gstate.kwstate strm done; let v = ps gstate strm in let v = if not gstate.recover then v else v <+> fun () -> (* Tolerance: retry w/o granting the level constraint (see recover) *) let bp = LStream.count strm in let* top = top_tree entry tree in let+ a = parser_of_tree entry nlevn alevn top gstate strm in warn_recover entry.ename bp strm; a in match v with | Ok v -> Ok v | Error () -> raise (TokenListFailed (entry, last_a, (Stoken last_tok), tree)) in let ps = loop 1 tok tree in fun gstate strm -> match LStream.peek gstate.kwstate strm with | Some tok' -> (match L.tok_match tok tok' with | Some a -> begin try let+ act = ps gstate a strm in act a with TokenListFailed (entry, a, tok, tree) -> raise (ParseError (tree_failed entry a tok tree)) end | None -> Error ()) | None -> Error () and parser_of_symbol : type s tr a. s ty_entry -> int -> (s, tr, a) ty_symbol -> GState.t -> a parser_t = fun entry nlevn -> function | Slist0 s -> let ps = parser_of_symbol entry nlevn s in let rec loop gstate al (strm__ : _ LStream.t) = match ps gstate strm__ with | Ok a -> loop gstate (a::al) strm__ | Error () -> al in (fun gstate (strm__ : _ LStream.t) -> let a = loop gstate [] strm__ in Ok (List.rev a)) | Slist0sep (symb, sep) -> let ps = parser_of_symbol entry nlevn symb in let pt = parser_of_symbol entry nlevn sep in let rec kont gstate al (strm__ : _ LStream.t) = match pt gstate strm__ with | Ok v -> let a = match ps gstate strm__ with | Ok a -> a | Error () -> raise (ParseError (symb_failed entry v sep symb)) in kont gstate (a::al) strm__ | Error () -> al in (fun gstate (strm__ : _ LStream.t) -> match ps gstate strm__ with | Ok a -> let a = kont gstate [a] strm__ in Ok (List.rev a) | Error () -> Ok []) | Slist1 s -> let ps = parser_of_symbol entry nlevn s in let rec loop gstate al (strm__ : _ LStream.t) = match ps gstate strm__ with | Ok a -> loop gstate (a::al) strm__ | Error () -> al in (fun gstate (strm__ : _ LStream.t) -> let* a = ps gstate strm__ in let a = loop gstate [a] strm__ in Ok (List.rev a)) | Slist1sep (symb, sep) -> let ps = parser_of_symbol entry nlevn symb in let pt = parser_of_symbol entry nlevn sep in let rec kont gstate al (strm__ : _ LStream.t) = match pt gstate strm__ with | Ok v -> let* a = match ps gstate strm__ with | Ok a -> Ok a | Error () -> if not gstate.recover then Error () else let bp = LStream.count strm__ in let a = match let* top = top_symb entry symb in parser_of_symbol entry 0 top gstate strm__ with | Ok a -> a | Error () -> raise (ParseError (symb_failed entry v sep symb)) in let () = warn_recover entry.ename bp strm__ in Ok a in kont gstate (a::al) strm__ | Error () -> Ok al in (fun gstate (strm__ : _ LStream.t) -> let* a = ps gstate strm__ in let+ a = kont gstate [a] strm__ in List.rev a) | Sopt s -> let ps = parser_of_symbol entry nlevn s in (fun gstate (strm__ : _ LStream.t) -> match ps gstate strm__ with | Ok a -> Ok (Some a) | Error () -> Ok None) | Stree t -> let pt = parser_of_tree entry 1 0 t in (fun gstate (strm__ : _ LStream.t) -> let bp = LStream.count strm__ in let+ a = pt gstate strm__ in let ep = LStream.count strm__ in let loc = LStream.interval_loc bp ep strm__ in a loc) | Snterm e -> (fun gstate (strm__ : _ LStream.t) -> start_parser_of_entry gstate e 0 strm__) | Snterml (e, l) -> (fun gstate (strm__ : _ LStream.t) -> start_parser_of_entry gstate e (level_number (get_entry gstate.estate e) l) strm__) | Sself -> (fun gstate (strm__ : _ LStream.t) -> start_parser_of_entry gstate entry 0 strm__) | Snext -> (fun gstate (strm__ : _ LStream.t) -> start_parser_of_entry gstate entry nlevn strm__) | Stoken tok -> let p = parser_of_token entry tok in (fun gstate strm -> p gstate.kwstate strm) | Stokens tokl -> let p = parser_of_tokens entry tokl in (fun gstate strm -> p gstate.kwstate strm) and parser_of_token : type s a. s ty_entry -> a pattern -> L.keyword_state -> a parser_t = fun entry tok -> let f = L.tok_match tok in fun kwstate strm -> match LStream.peek kwstate strm with | Some tok -> (match f tok with | Some r -> LStream.junk kwstate strm; Ok r | None -> Error ()) | None -> Error () and parser_of_tokens : type s. s ty_entry -> ty_pattern list -> L.keyword_state -> unit parser_t = fun entry tokl -> let rec loop n = function | [] -> fun kwstate strm -> for _i = 1 to n do LStream.junk kwstate strm done; Ok () | TPattern tok :: tokl -> fun kwstate strm -> let tok' = LStream.peek_nth kwstate n strm in match Option.bind tok' (L.tok_match tok) with | Some _ -> loop (n+1) tokl kwstate strm | None -> Error () in loop 0 tokl (** [start_parser_of_levels entry clevn levels levn strm] goes top-down from level [clevn] to the last level, ignoring rules between [levn] and [clevn], as if starting from [max(clevn,levn)]. On each rule of the form [prefix] (where [prefix] is a rule not starting with [SELF]), it tries to consume the stream [strm]. The interesting case is [entry.estart] which is [start_parser_of_levels entry 0 entry.edesc], thus practically going from [levn] to the end. More schematically, assuming each level has the normalized form level n: [ a = SELF; b = suffix_tree_n -> action_n(a,b) | a = prefix_tree_n -> action'_n(a) ] then the main loop does the following: estart n = if prefix_tree_n matches the stream as a then econtinue n (action'_n(a)) else start (n+1) econtinue n a = if suffix_tree_n matches the stream as b then econtinue n (action_n(a,b)) else if n=0 then a else econtinue (n-1) a *) let rec start_parser_of_levels entry clevn = function [] -> (fun _gstate levn (strm__ : _ LStream.t) -> Error ()) | Level lev :: levs -> let p1 = start_parser_of_levels entry (succ clevn) levs in match lev.lprefix with DeadEnd -> p1 | tree -> let alevn = if self_on_the_right lev.assoc then clevn else succ clevn in let p2 = parser_of_tree entry (succ clevn) alevn tree in match levs with [] -> (fun gstate levn strm -> (* Recovery here means that a grammar entry e: [[ "x"; a = e | "y" ]] works even though it should be: e: [RIGHTA[ "x"; a = e | "y" ]] *) if not gstate.recover && levn > clevn then Error () else let (strm__ : _ LStream.t) = strm in let bp = LStream.count strm__ in let* act = p2 gstate strm__ in let ep = LStream.count strm__ in let a = act (LStream.interval_loc bp ep strm__) in let () = if levn > clevn then warn_recover_last_start entry.ename bp ep strm__ in continue_parser_of_entry gstate entry (Some clevn) levn bp a strm) | _ -> fun gstate levn strm -> if levn > clevn then (* Skip rules before [levn] *) p1 gstate levn strm else let (strm__ : _ LStream.t) = strm in let bp = LStream.count strm__ in match p2 gstate strm__ with | Ok act -> let ep = LStream.count strm__ in let a = act (LStream.interval_loc bp ep strm__) in continue_parser_of_entry gstate entry (Some clevn) levn bp a strm | Error () -> p1 gstate levn strm__ (** [continue_parser_of_levels entry clevn levels levn bp a strm] goes bottom-up from the last level to level [clevn], ignoring rules between [levn] and [clevn], as if stopping at [max(clevn,levn)]. It tries to consume the stream [strm] on the suffix of rules of the form [SELF; suffix] knowing that [a] is what consumed [SELF] at level [levn] (or [levn+1] depending on associativity). The interesting case is [entry.econtinue levn bp a] which is [try continue_parser_of_levels entry 0 entry.edesc levn bp a with Failure -> a], thus practically going from the end to [levn]. *) let rec continue_parser_of_levels entry clevn = function [] -> (fun _gstate levfrom levn bp a (strm__ : _ LStream.t) -> Error ()) | Level lev :: levs -> let p1 = continue_parser_of_levels entry (succ clevn) levs in match lev.lsuffix with DeadEnd -> p1 | tree -> let alevn = if self_on_the_right lev.assoc then clevn else succ clevn in let p2 = parser_of_tree entry (succ clevn) alevn tree in fun gstate levfrom levn bp a strm -> let tolerance = match levfrom with | Some levfrom when levfrom = clevn && not (self_on_the_left lev.assoc) -> Some true | Some levfrom when levfrom < clevn -> Some false | _ -> None in (* Apply the lsuffix continuation if the level is in the interval [levn;levfrom] *) if levn > clevn then (* Skip rules before [levn] *) p1 gstate levfrom levn bp a strm else if (not gstate.recover && Option.has_some tolerance) then Error () else let (strm__ : _ LStream.t) = strm in let ep = LStream.count strm__ in let+ c = p1 gstate levfrom levn bp a strm__ <+> fun () -> let* act = p2 gstate strm__ in let ep = LStream.count strm__ in let a = act a (LStream.interval_loc bp ep strm__) in if gstate.has_non_assoc && lev.assoc = NonA then if clevn = levn then Ok a else continue_parser_of_entry gstate entry (Some (clevn-1)) levn bp a strm else continue_parser_of_entry gstate entry (Some clevn) levn bp a strm in let () = Option.iter (warn_recover_continuation entry.ename bp ep strm__) tolerance in c let make_continue_parser_of_entry entry = function | [] -> (fun _ _ _ _ _ (_ : _ LStream.t) -> Error ()) | elev -> let p = lazy (continue_parser_of_levels entry 0 elev) in (fun gstate levfrom levn bp a (strm__ : _ LStream.t) -> Lazy.force p gstate levfrom levn bp a strm__ <+> fun () -> Ok a) let make_start_parser_of_entry entry = function | [] -> empty_entry entry.ename | elev -> let p = lazy (start_parser_of_levels entry 0 elev) in (fun gstate levn (strm:_ LStream.t) -> Lazy.force p gstate levn strm) let make_entry_data entry elev = { eentry = entry; edesc = Dlevels elev; estart = make_start_parser_of_entry entry elev; econtinue = make_continue_parser_of_entry entry elev; } (* Extend syntax *) let modify_entry estate e f = try EState.modify (DMap.tag_of_onetag e.etag) f estate with Not_found -> CErrors.anomaly Pp.(str "modify_entry: " ++ str e.ename ++ str " not found") let add_entry otag estate e v = assert (not (EState.mem (DMap.tag_of_onetag e.etag) estate)); EState.add otag v estate let extend_entry add_kw estate kwstate entry statement = let kwstate = ref kwstate in let estate = modify_entry estate entry (fun edata -> let kwstate', elev = levels_of_rules add_kw !kwstate entry edata statement in kwstate := kwstate'; make_entry_data entry elev) in estate, !kwstate (* Normal interface *) module Parsable = struct type t = { pa_tok_strm : (L.keyword_state,L.te) LStream.t ; lexer_state : L.State.t ref } let parse_parsable gstate entry p = let efun = start_parser_of_entry gstate entry 0 in let ts = p.pa_tok_strm in let get_parsing_loc () = (* Build the loc spanning from just after what is consumed (count) up to the further token known to have been read (max_peek). Being a parsing error, there needs to be a next token that caused the failure, except when the rule is empty (e.g. an empty custom entry); thus, we need to ensure that the token at location cnt has been peeked (which in turn ensures that the max peek is at least the current position) *) let _ = LStream.peek gstate.kwstate ts in let loc' = LStream.max_peek_loc ts in let loc = LStream.get_loc (LStream.count ts) ts in Loc.merge loc loc' in match efun ts with | Ok v -> v | Error () -> let loc = get_parsing_loc () in let exn = ParseError ("illegal begin of " ^ entry.ename) in Loc.raise ~loc exn | exception (ParseError _ as exn) -> let exn, info = Exninfo.capture exn in let loc = get_parsing_loc () in let info = Loc.add_loc info loc in Exninfo.iraise (exn, info) | exception exc -> (* An error produced by the evaluation of the right-hand side *) (* of a rule, or a signal such as Sys.Break; we leave to the *) (* error the responsibility of locating itself *) let exc,info = Exninfo.capture exc in Exninfo.iraise (exc,info) let parse_parsable gstate e p = L.State.set !(p.lexer_state); try let c = parse_parsable gstate e p in p.lexer_state := L.State.get (); c with exn -> let exn,info = Exninfo.capture exn in L.State.drop (); Exninfo.iraise (exn,info) let make ?loc cs = let lexer_state = ref (L.State.init ()) in L.State.set !lexer_state; let ts = L.tok_func ?loc cs in lexer_state := L.State.get (); {pa_tok_strm = ts; lexer_state} let comments p = L.State.get_comments !(p.lexer_state) let loc t = LStream.current_loc t.pa_tok_strm let consume { pa_tok_strm } len kwstate = LStream.njunk kwstate len pa_tok_strm end module Entry = struct type 'a t = 'a ty_entry let fresh n = let etag = DMap.make () in { ename = n; etag }, etag let empty_entry_val e = { eentry = e; edesc = Dlevels []; estart = empty_entry e.ename; econtinue = (fun _ _ _ _ _ (strm__ : _ LStream.t) -> assert false); } let make n estate = let e, otag = fresh n in let estate = add_entry otag estate e (empty_entry_val e) in estate, e let parse (e : 'a t) p gstate : 'a = Parsable.parse_parsable gstate e p let parse_token_stream (e : 'a t) ts gstate : 'a parser_v = start_parser_of_entry gstate e 0 ts let name e = e.ename type 'a parser_fun = { parser_fun : L.keyword_state -> (L.keyword_state,te) LStream.t -> 'a parser_v } let of_parser_val e { parser_fun = p } = { eentry = e; estart = (fun gstate _ (strm:_ LStream.t) -> p gstate.kwstate strm); econtinue = (fun _ _ _ _ _ (strm__ : _ LStream.t) -> Error ()); edesc = Dparser p; } let of_parser n p estate = let e, otag = fresh n in let estate = add_entry otag estate e (of_parser_val e p) in estate, e let print ppf e estate kwstate = fprintf ppf "%a@." (print_entry estate kwstate) e let is_empty e estate = match (get_entry estate e).edesc with | Dparser _ -> failwith "Arbitrary parser entry" | Dlevels elev -> List.is_empty elev type any_t = Any : 'a t -> any_t let rec iter_in_symbols : type s tr p. _ -> (s, tr, p) ty_symbols -> unit = fun f symbols -> match symbols with | TNil -> () | TCns (_, symbol, symbols) -> iter_in_symbol f symbol; iter_in_symbols f symbols and iter_in_symbol : type s tr r. _ -> (s, tr, r) ty_symbol -> unit = fun f -> function | Snterml (e, _) | Snterm e -> f (Any e) | Slist0 s -> iter_in_symbol f s | Slist0sep (s, t) -> iter_in_symbol f s; iter_in_symbol f t | Slist1 s -> iter_in_symbol f s | Slist1sep (s, t) -> iter_in_symbol f s; iter_in_symbol f t | Sopt s -> iter_in_symbol f s | Stoken _ | Stokens _ -> () | Sself | Snext -> () | Stree t -> List.iter (fun (ExS rule) -> iter_in_symbols f rule) (flatten_tree t) let iter_in estate f e = match (get_entry estate e).edesc with | Dparser _ -> () | Dlevels elev -> List.iter (fun (Level lev) -> let rules = List.map (fun (ExS t) -> ExS (TCns (MayRec2, Sself, t))) (flatten_tree lev.lsuffix) @ flatten_tree lev.lprefix in List.iter (fun (ExS rule) -> iter_in_symbols f rule) rules) elev let same_entry (Any e) (Any e') = Option.has_some (eq_entry e e') let all_in () estate = let add_entry (Any e as a) acc = String.Map.update e.ename (function | None -> Some [a] | Some l -> Some (a::l)) acc in EState.fold { fold = fun _ data acc -> add_entry (Any data.eentry) acc} estate String.Map.empty let accumulate_in initial estate = let add_visited visited (Any e as any) = String.Map.update e.ename (function | None -> Some [any] | Some vl as v -> if List.mem_f same_entry any vl then v else Some (any :: vl)) visited in let todo = ref initial in let visited = List.fold_left add_visited String.Map.empty initial in let visited = ref visited in while not (List.is_empty !todo) do let Any e = List.hd !todo in todo := List.tl !todo; iter_in estate (fun (Any e as any) -> let visited' = add_visited !visited any in if not (!visited == visited') then begin visited := visited'; todo := any :: !todo end) e done; !visited end module rec Symbol : sig type ('self, 'trec, 'a) t = ('self, 'trec, 'a) ty_symbol val nterm : 'a Entry.t -> ('self, norec, 'a) t val nterml : 'a Entry.t -> string -> ('self, norec, 'a) t val list0 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list0sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val list1 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list1sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val opt : ('self, 'trec, 'a) t -> ('self, 'trec, 'a option) t val self : ('self, mayrec, 'self) t val next : ('self, mayrec, 'self) t val token : 'c pattern -> ('self, norec, 'c) t val tokens : ty_pattern list -> ('self, norec, unit) t val rules : 'a Rules.t list -> ('self, norec, 'a) t end = struct type ('self, 'trec, 'a) t = ('self, 'trec, 'a) ty_symbol let nterm e = Snterm e let nterml e l = Snterml (e, l) let list0 s = Slist0 s let list0sep s sep = Slist0sep (s, sep) let list1 s = Slist1 s let list1sep s sep = Slist1sep (s, sep) let opt s = Sopt s let self = Sself let next = Snext let token tok = Stoken tok let tokens tokl = Stokens tokl let rules (t : 'a Rules.t list) = srules t end and Rule : sig type ('self, 'trec, 'f, 'r) t = ('self, 'trec, 'f, 'r) ty_rule val stop : ('self, norec, 'r, 'r) t val next : ('self, _, 'a, 'r) t -> ('self, _, 'b) Symbol.t -> ('self, mayrec, 'b -> 'a, 'r) t val next_norec : ('self, norec, 'a, 'r) Rule.t -> ('self, norec, 'b) Symbol.t -> ('self, norec, 'b -> 'a, 'r) t end = struct type ('self, 'trec, 'f, 'r) t = ('self, 'trec, 'f, 'r) ty_rule let stop = TStop let next r s = TNext (MayRec2, r, s) let next_norec r s = TNext (NoRec2, r, s) end and Rules : sig type 'a t = 'a ty_rules val make : (_, norec, 'f, Loc.t -> 'a) Rule.t -> 'f -> 'a t end = struct type 'a t = 'a ty_rules let make p act = TRules (p, act) end module Production = struct type 'a t = 'a ty_production let make p act = TProd (p, act) end module Unsafe = struct let existing_entry estate e = add_entry e.etag estate e (Entry.empty_entry_val e) let existing_of_parser estate e p = add_entry e.etag estate e (Entry.of_parser_val e p) end let safe_extend = extend_entry let level_of_nonterm sym = match sym with | Snterml (_,l) -> Some l | _ -> None exception SelfSymbol let rec generalize_symbol : type a tr s u. (s, tr, a) Symbol.t -> (u, norec, a) ty_symbol = function | Stoken tok -> Stoken tok | Stokens tokl -> Stokens tokl | Slist1 e -> Slist1 (generalize_symbol e) | Slist1sep (e, sep) -> let e = generalize_symbol e in let sep = generalize_symbol sep in Slist1sep (e, sep) | Slist0 e -> Slist0 (generalize_symbol e) | Slist0sep (e, sep) -> let e = generalize_symbol e in let sep = generalize_symbol sep in Slist0sep (e, sep) | Sopt e -> Sopt (generalize_symbol e) | Sself -> raise SelfSymbol | Snext -> raise SelfSymbol | Snterm e -> Snterm e | Snterml (e, l) -> Snterml (e, l) | Stree r -> Stree (generalize_tree r) and generalize_tree : type a tr s u. (s, tr, a) ty_tree -> (u, norec, a) ty_tree = fun r -> match r with | Node (fi, n) -> let fi = match fi with | NoRec3 -> NoRec3 | MayRec3 -> raise SelfSymbol in let n = match n with | { node; son; brother } -> let node = generalize_symbol node in let son = generalize_tree son in let brother = generalize_tree brother in { node; son; brother } in Node (fi, n) | LocAct _ as r -> r | DeadEnd as r -> r let generalize_symbol s = try Some (generalize_symbol s) with SelfSymbol -> None end rocq-9.2.0/gramlib/grammar.mli000066400000000000000000000141141516144147600162460ustar00rootroot00000000000000(* camlp5r *) (* grammar.mli,v *) (* Copyright (c) INRIA 2007-2017 *) (** Extensible grammars. This module implements the Camlp5 extensible grammars system. Grammars entries can be extended using the [EXTEND] statement, added by loading the Camlp5 [pa_extend.cmo] file. *) exception ParseError of string (** Raised by parsers when the first component of a stream pattern is accepted, but one of the following components is rejected. *) (** {6 Functorial interface} *) (** Alternative for grammars use. Grammars are no more Ocaml values: there is no type for them. Modules generated preserve the rule "an entry cannot call an entry of another grammar" by normal OCaml typing. *) (** The input signature for the functor [Grammar.GMake]: [te] is the type of the tokens. *) type norec type mayrec module type S = sig type keyword_state type te type 'c pattern type ty_pattern = TPattern : 'a pattern -> ty_pattern type peek_error = unit type 'a parser_v = ('a, peek_error) result (** Recoverable parsing errors are signaled use [Error]. To be correctly recovered we must not have consumed any tokens since the last choice point, ie we only peeked at the stream. Other errors are signaled using the [ParseError] exception or even arbitrary exceptions. *) (** Type combinators to factor the module type between explicit state passing in Grammar and global state in Procq *) type 'a with_gstate (** Reader of grammar state *) type 'a with_kwstate (** Read keyword state *) type 'a with_estate (** Read entry state *) type 'a mod_estate (** Read/write entry state *) module Parsable : sig type t val make : ?loc:Loc.t -> (unit,char) Stream.t -> t val comments : t -> ((int * int) * string) list val loc : t -> Loc.t val consume : t -> int -> unit with_kwstate end module Entry : sig type 'a t val make : string -> 'a t mod_estate val parse : 'a t -> Parsable.t -> 'a with_gstate val name : 'a t -> string type 'a parser_fun = { parser_fun : keyword_state -> (keyword_state,te) LStream.t -> 'a parser_v } val of_parser : string -> 'a parser_fun -> 'a t mod_estate val parse_token_stream : 'a t -> (keyword_state,te) LStream.t -> 'a parser_v with_gstate val print : Format.formatter -> 'a t -> unit with_kwstate with_estate val is_empty : 'a t -> bool with_estate type any_t = Any : 'a t -> any_t val accumulate_in : any_t list -> any_t list CString.Map.t with_estate val all_in : unit -> any_t list CString.Map.t with_estate end module rec Symbol : sig type ('self, 'trec, 'a) t val nterm : 'a Entry.t -> ('self, norec, 'a) t val nterml : 'a Entry.t -> string -> ('self, norec, 'a) t val list0 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list0sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val list1 : ('self, 'trec, 'a) t -> ('self, 'trec, 'a list) t val list1sep : ('self, 'trec, 'a) t -> ('self, norec, unit) t -> ('self, 'trec, 'a list) t val opt : ('self, 'trec, 'a) t -> ('self, 'trec, 'a option) t val self : ('self, mayrec, 'self) t val next : ('self, mayrec, 'self) t val token : 'c pattern -> ('self, norec, 'c) t val tokens : ty_pattern list -> ('self, norec, unit) t val rules : 'a Rules.t list -> ('self, norec, 'a) t end and Rule : sig type ('self, 'trec, 'f, 'r) t val stop : ('self, norec, 'r, 'r) t val next : ('self, _, 'a, 'r) t -> ('self, _, 'b) Symbol.t -> ('self, mayrec, 'b -> 'a, 'r) t val next_norec : ('self, norec, 'a, 'r) Rule.t -> ('self, norec, 'b) Symbol.t -> ('self, norec, 'b -> 'a, 'r) t end and Rules : sig type 'a t val make : (_, norec, 'f, Loc.t -> 'a) Rule.t -> 'f -> 'a t end module Production : sig type 'a t val make : ('a, _, 'f, Loc.t -> 'a) Rule.t -> 'f -> 'a t end type 'a single_extend_statement = string option * Gramext.g_assoc option * 'a Production.t list type 'a extend_statement = | Reuse of string option * 'a Production.t list (** Extend an existing level by its optional given name. If None, picks the topmost level. *) | Fresh of Gramext.position * 'a single_extend_statement list (** Create a level at the given position. *) val generalize_symbol : ('a, 'tr, 'c) Symbol.t -> ('b, norec, 'c) Symbol.t option (* Used in custom entries, should tweak? *) val level_of_nonterm : ('a, norec, 'c) Symbol.t -> string option end (* Interface private to clients *) module type ExtS = sig type keyword_state module EState : sig type t val empty : t end module GState : sig type t = { estate : EState.t; kwstate : keyword_state; recover : bool; has_non_assoc : bool; } end include S with type keyword_state := keyword_state and type 'a with_gstate := GState.t -> 'a and type 'a with_kwstate := keyword_state -> 'a and type 'a with_estate := EState.t -> 'a and type 'a mod_estate := EState.t -> EState.t * 'a type 's add_kw = { add_kw : 'c. 's -> 'c pattern -> 's } val safe_extend : 's add_kw -> EState.t -> 's -> 'a Entry.t -> 'a extend_statement -> EState.t * 's module Unsafe : sig val existing_entry : EState.t -> 'a Entry.t -> EState.t val existing_of_parser : EState.t -> 'a Entry.t -> 'a Entry.parser_fun -> EState.t end end (** Signature type of the functor [Grammar.GMake]. The types and functions are almost the same than in generic interface, but: - Grammars are not values. Functions holding a grammar as parameter do not have this parameter yet. - The type [parsable] is used in function [parse] instead of the char stream, avoiding the possible loss of tokens. - The type of tokens (expressions and patterns) can be any type (instead of (string * string)); the module parameter must specify a way to show them as (string * string) *) module GMake (L : Plexing.S) : ExtS with type keyword_state := L.keyword_state and type te := L.te and type 'c pattern := 'c L.pattern rocq-9.2.0/gramlib/lStream.ml000066400000000000000000000046061516144147600160630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Loc.t; (* Remember max token peeked *) mutable max_peek : int; } let from ?(loc=Loc.(initial ToplevelInput)) f = let loct = Hashtbl.create 207 in let loct_func loct i = Hashtbl.find loct i in let loct_add loct i loc = Hashtbl.add loct i loc in let strm = let i = ref 0 in Stream.from (fun e -> match f e with | None -> None | Some (a,loc) -> loct_add loct !i loc; incr i; Some a) in let fun_loc i = if i = 0 then loc else loct_func loct (i - 1) in { strm; max_peek = 0; fun_loc } let count strm = Stream.count strm.strm let current_loc strm = strm.fun_loc (Stream.count strm.strm) let max_peek_loc strm = strm.fun_loc strm.max_peek let interval_loc bp ep strm = assert (bp <= ep); if ep > strm.max_peek then failwith "Not peeked position"; if bp == ep then Loc.after (strm.fun_loc bp) 0 0 else let loc1 = strm.fun_loc (bp + 1) in let loc2 = strm.fun_loc ep in Loc.merge loc1 loc2 let get_loc n strm = strm.fun_loc (n + 1) let peek e strm = let a = Stream.peek e strm.strm in if Option.has_some a then strm.max_peek <- max (Stream.count strm.strm + 1) strm.max_peek; a let npeek e n strm = let l = Stream.npeek e n strm.strm in strm.max_peek <- max (Stream.count strm.strm + List.length l) strm.max_peek; l let peek_nth e n strm = let list = npeek e (n + 1) strm in List.nth_opt list n let junk e strm = Stream.junk e strm.strm let njunk e len strm = Stream.njunk e len strm.strm let next e strm = Stream.next e strm.strm rocq-9.2.0/gramlib/lStream.mli000066400000000000000000000045351516144147600162350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ('e -> ('a * Loc.t) option) -> ('e,'a) t (** Returning the loc of the last consumed element or the initial loc if no element is consumed *) val current_loc : ('e,'a) t -> Loc.t (** Returning the loc of the max visited element or the initial loc if no element is consumed *) val max_peek_loc : ('e,'a) t -> Loc.t (** [interval_loc bp ep strm] returns the loc starting after element [bp] (counting from 0) and spanning up to already peeked element at position [ep], under the assumption that [bp] <= [ep]; returns an empty interval if [bp] = [ep]; returns the empty initial interval if additionally [bp] = 0; fails if the elements have not been peeked yet *) val interval_loc : int -> int -> ('e,'a) t -> Loc.t (** Return location of an already peeked element at some position counting from 0; fails if the element has not been peeked yet *) val get_loc : int -> ('e,'a) t -> Loc.t (** Lifted usual function on streams *) val count : ('e,'a) t -> int val peek : 'e -> ('e,'a) t -> 'a option val npeek : 'e -> int -> ('e,'a) t -> 'a list val junk : 'e -> ('e,'a) t -> unit (** consumes the next element if there is one *) val njunk : 'e -> int -> ('e,'a) t -> unit (** [njunk e n strm] consumes [n] elements from [strm] *) val next : 'e -> ('e,'a) t -> 'a option (** [next e strm] returns and consumes the next element; [None] if the stream is empty *) (** Other functions *) val peek_nth : 'e -> int -> ('e,'a) t -> 'a option (** [peek_nth e n strm] returns the nth element counting from 0 without consuming the stream; [None] if not enough elements *) rocq-9.2.0/gramlib/plexing.mli000066400000000000000000000020611516144147600162640ustar00rootroot00000000000000(* camlp5r *) (* plexing.mli,v *) (* Copyright (c) INRIA 2007-2017 *) (** Lexing for Camlp5 grammars. This module defines the Camlp5 lexer type to be used in extensible grammars (see module [Grammar]). It also provides some useful functions to create lexers. *) (** Lexer type *) module type S = sig type keyword_state type te type 'c pattern val tok_pattern_eq : 'a pattern -> 'b pattern -> ('a, 'b) Util.eq option val tok_pattern_exact : _ pattern -> bool val tok_pattern_strings : keyword_state -> 'c pattern -> string * string option (** Returning a stream equipped with a location function *) val tok_func : ?loc:Loc.t -> (unit,char) Stream.t -> (keyword_state,te) LStream.t val tok_match : 'c pattern -> te -> 'c option val tok_text : 'c pattern -> string (* State for the comments, at some point we should make it functional *) module State : sig type t val init : unit -> t val set : t -> unit val get : unit -> t val drop : unit -> unit val get_comments : t -> ((int * int) * string) list end end rocq-9.2.0/gramlib/stream.ml000066400000000000000000000067551516144147600157560ustar00rootroot00000000000000(**************************************************************************) (* *) (* OCaml *) (* *) (* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 1997 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) type ('e,'a) t = { mutable count : int; mutable data : ('e,'a) data } and ('e,'a) data = Sempty | Scons of 'a * ('e,'a) data | Sgen of ('e,'a) gen | Sbuffio : buffio -> (unit,char) data and ('e,'a) gen = { mutable curr : 'a option option; func : 'e -> 'a option } and buffio = { ic : in_channel; buff : bytes; mutable len : int; mutable ind : int } let count { count } = count let fill_buff b = b.len <- input b.ic b.buff 0 (Bytes.length b.buff); b.ind <- 0 let peek : type e v. e -> (e,v) t -> v option = fun e s -> (* consult the first item of s *) match s.data with Sempty -> None | Scons (a, _) -> Some a | Sgen {curr = Some a} -> a | Sgen g -> let x = g.func e in g.curr <- Some x; x | Sbuffio b -> if b.ind >= b.len then fill_buff b; if b.len == 0 then begin s.data <- Sempty; None end else Some (Bytes.unsafe_get b.buff b.ind) let rec junk : type e v. e -> (e,v) t -> unit = fun e s -> match s.data with Scons (_, d) -> s.count <- (succ s.count); s.data <- d | Sgen ({curr = Some _} as g) -> s.count <- (succ s.count); g.curr <- None | Sbuffio b -> if b.ind >= b.len then fill_buff b; if b.len == 0 then s.data <- Sempty else (s.count <- (succ s.count); b.ind <- succ b.ind) | Sempty -> () | Sgen { curr = None } -> match peek e s with None -> () | Some _ -> junk e s let rec nget e n s = if n <= 0 then [], s.data, 0 else match peek e s with Some a -> junk e s; let (al, d, k) = nget e (pred n) s in a :: al, Scons (a, d), succ k | None -> [], s.data, 0 let npeek e n s = let (al, d, len) = nget e n s in s.count <- (s.count - len); s.data <- d; al let nth e n st = List.nth_opt (npeek e (n+1) st) n let rec njunk e n st = if n <> 0 then (junk e st; njunk e (n-1) st) let next e s = match peek e s with | Some _ as a -> junk e s; a | None -> None let is_empty e s = match peek e s with | Some _ -> false | None -> true (* Stream building functions *) let from ?(offset=0) f = {count = offset; data = Sgen {curr = None; func = f}} (* NB we need the thunk for value restriction *) let empty () = {count = 0; data = Sempty} let of_string ?(offset=0) s = let count = ref 0 in from ~offset (fun () -> let c = !count in if c < String.length s then (incr count; Some s.[c]) else None) let of_channel ic = {count = 0; data = Sbuffio {ic = ic; buff = Bytes.create 4096; len = 0; ind = 0}} rocq-9.2.0/gramlib/stream.mli000066400000000000000000000063101516144147600161120ustar00rootroot00000000000000(**************************************************************************) (* *) (* OCaml *) (* *) (* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 1997 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) (** Streams and parsers. *) type ('e,'a) t (** The type of streams holding values of type ['a]. Producing a new value needs an environment ['e]. *) (** {1 Stream builders} *) val from : ?offset:int -> ('e -> 'a option) -> ('e,'a) t (** [Stream.from f] returns a stream built from the function [f]. To create a new stream element, the function [f] is called. The user function [f] must return either [Some ] for a value or [None] to specify the end of the stream. [offset] will initialize the stream [count] to start with [offset] consumed items, which is useful for some uses cases such as parsing resumption. *) val empty : unit -> ('e,'a) t (** Return the stream holding the elements of the list in the same order. *) val of_string : ?offset:int -> string -> (unit,char) t (** Return the stream of the characters of the string parameter. If set. [offset] parameter is similar to [from]. *) val of_channel : in_channel -> (unit,char) t (** Return the stream of the characters read from the input channel. *) (** {1 Predefined parsers} *) val next : 'e -> ('e,'a) t -> 'a option (** Return the first element of the stream and remove it from the stream. [None] if the stream is empty. *) val is_empty : 'e -> ('e,'a) t -> bool (** Return [true] if the stream is empty, else [false]. *) (** {1 Useful functions} *) val peek : 'e -> ('e,'a) t -> 'a option (** Return [Some] of "the first element" of the stream, or [None] if the stream is empty. *) val junk : 'e -> ('e,'a) t -> unit (** Remove the first element of the stream, possibly unfreezing it before. *) val count : ('e,'a) t -> int (** Return the current count of the stream elements, i.e. the number of the stream elements discarded. *) val npeek : 'e -> int -> ('e,'a) t -> 'a list (** [npeek e n] returns the list of the [n] first elements of the stream, or all its remaining elements if less than [n] elements are available. *) val nth : 'e -> int -> ('e,'a) t -> 'a option (** Returns the [n]th (0-indexed) element of the sream without consuming, or [None] if less than [n+1] elements are available. *) val njunk : 'e -> int -> ('e,'a) t -> unit (**/**) rocq-9.2.0/ide/000077500000000000000000000000001516144147600132405ustar00rootroot00000000000000rocq-9.2.0/ide/rocqide/000077500000000000000000000000001516144147600146665ustar00rootroot00000000000000rocq-9.2.0/ide/rocqide/FAQ000066400000000000000000000050751516144147600152270ustar00rootroot00000000000000 RocqIDE FAQ TODO: Put the relevant info in the doc and delete this file. Q0) What is RocqIDE? R0: A powerful graphical interface for Coq. See https://rocq-prover.org/refman/practical-tools/coqide.html. for more information. Q1) How to enable Emacs keybindings? R1: Insert gtk-key-theme-name = "Emacs" in your gtkrc file. The location of this file is system-dependent. If you're running Gnome, you may use the graphical configuration tools. Q2) How to enable antialiased fonts? R2) Set the GDK_USE_XFT variable to 1. This is by default with Gtk >= 2.2. If some of your fonts are not available, set GDK_USE_XFT to 0. Q4) How to use those Forall and Exists pretty symbols? R4) Thanks to the Notation features in Coq, you just need to insert these lines in your Coq Buffer : ====================================================================== Notation "βˆ€ x : t, P" := (forall x:t, P) (at level 200, x ident). Notation "βˆƒ x : t, P" := (exists x:t, P) (at level 200, x ident). ====================================================================== Copy/Paste of these lines from this file will not work outside of RocqIDE. You need to load a file containing these lines or to enter the "βˆ€" using an input method (see Q5). To try it just use "Require utf8" from inside RocqIDE. To enable these notations automatically start rocqide with rocqide -l utf8 In the ide subdir of Coq library, you will find a sample utf8.v with some pretty simple notations. Q5) How to define an input method for non ASCII symbols? R5)-First solution : type "2200" to enter a forall in the script widow. 2200 is the hexadecimal code for forall in unicode charts and is encoded as "βˆ€" in UTF-8. 2203 is for exists. See http://www.unicode.org for more codes. -Second solution : Use an input method editor, such as SCIM or iBus. The latter offers a module for LaTeX-like inputting. Q6) How to customize the shortcuts for menus? R6) Two solutions are offered: - Edit $XDG_CONFIG_HOME/coq/coqide.keys by hand or - If your system allows it, from RocqIDE, you may select a menu entry and press the desired shortcut. Q7) What encoding should I use? What is this \x{iiii} in my file? R7) The encoding option is related to the way files are saved. Keep it as UTF-8 until it becomes important for you to exchange files with non UTF-8 aware applications. If you choose something else than UTF-8, then missing characters will be encoded by \x{....} or \x{........} where each dot is an hex. digit. The number between braces is the hexadecimal UNICODE index for the missing character. rocq-9.2.0/ide/rocqide/MacOS/000077500000000000000000000000001516144147600156305ustar00rootroot00000000000000rocq-9.2.0/ide/rocqide/MacOS/coqfile.icns000066400000000000000000007121471516144147600201440ustar00rootroot00000000000000icns”gTOC His32s8mkil32 Ol8mkit32r°t8mk@ic08Σ~ic09ϊhis32ώωκλλκικ€λμιφώš£Ÿ£₯£‘’‘ ‘φτ‰χυϊςθρϊφϊσ—δυŠικί΅²Χμλθχ–ζτŠρψΤ³ΐ²Ύύυο—δυŠρσγΌΗ™Ηφορ—δυ‰σρπΠΑΊίΝΣέ–ευ‰σττϊΔΑΟΗΞ΄˜δυ‰τπφοΚ½ΠΘΠs­ϊ›γτŠσοιΚΠΎΜΛ§’ητŠρφάΒΙΠ³ΈͺΖώ–ευ‰ςνρίΟΏ€·»ήΒsτŠτοςοέΆΧβςα]Ψυ‰λγιΧΒΐ΅ίέkΡϊτŒωμΙΎΚΖbΦχώ…‰‹Šˆ‰mΫχώώω€λκηι€λμκφώ™’ž€ͺ€ ‘  ‘φτ‰υτϋκΣκϋυϊρ—δυ‹ζμΡ~v|Τμλθφ–ζτ‹νύ±tw°σο–δτŠοφڐ«uΔψπς—δτ‰ςρσΗ§Έ΅ΏΩ–ευ‰ςυτω―·³­°§—ευ‰σπων±¨΄΅s όšγτŠρπβ»°΅§΅ ‘ητŠοχΣ¨°΄ £™Ηύ–ευ‰ρνσίΉ¦œ²½ίΓsτŠσπρρΙ Ϊδςΰ\Ψυ‰ιβλΜ£₯―ίάjΡϊτŒώψθΎ³ΗΗaΧχώ„Œ‰Œ‹Š‰lΫχώώωλλμιειμλλμκφώ™£¦­₯Ÿ‘  ‘φτ‰χτύδΒεόυϊς—δυ‹ηπΕNBQνμιχ–ζτŒν”>eB£ςπ–δτ‹πψa‚TΒωρτ—δυ‰τρυ΄|΅½ŽŸΤ•ευ‰τφσψާ‡„‘•ευ‰υπώθŠ†ˆ†‰‹™δτŠςςΧ•†‰ƒ~•θτ‹ρϊΕ~†‡€€~Κύ–ευ‰σνχή”|©ΐίΓsτŠυςοτͺ|ίερΰ\Ψυ‰μαπΌrx€αΫkΡϊτ‹ψα¬’ΔΙaΧχώ„‰ŠlΫχώs8mk<˜ˆŒŒˆ˜Kpχώώφ‹kξϊυφφφυϊξ…oχώώφŠnφύώώώύυŠoχώώφŠoχώώφŠoχώώφŠoχώώφ‡oχώώυ‹nφύώώώχLoχώχhkοϋφχχψχhpχώύ_ =™‰‹•Fil32 O€ώώ”ώύύά¦§₯†¦₯„¦ ₯¨£Λύόε9nopqr€qrrƒqprk~7ΌψχΕAχωŽTώςjσψΘ?ΰΫγήίίβγήΪέαγήίήάίδαηΦώa’σψΖ@μλσρρυκΜΒΎΐΗεχστςςσρχζgŽσψΖ?θιπμξλΓ΅€·Ά―γονλρροτγeσψΖ@νθςμςΥ΅Ί·Ή΄Ώ₯ΎχλππρπτδfσψΖ?θνχςψΞΆΊ··Έ½§―τψυτσωηfσψΖAπκτπχΩ΄Έ·Δ©½€¨ώπυστρφζgσψΖ?κουξρξΏΏΖΤ’³…ΐύξτπξτϊθgσψΖ@ξλυςρωΫΒΜΞ«™‘τηΰΰεπτφηgσψΖ@ξοτροψΥΙ£ΉυΪΜΚΙΞθώθgŽσψΖ@κμςπρσσφΟΤ ΛδΐΞΛΛΜΕ―φηgŽσψΖ@ροψχψωφύγΡ§8ΕΪΗΝΚΜΘΣ£βπhŽσψΖ?θμτσυυτϊγΠ¬ΣΗΞΚΝΗԟΠπiŽσψΖ@ςπυξ€π@χΫΜΐΆΠΗΙΛΝΖΦ”ΟτiŽσψΖ?μμτςςρφβΚΛΜΝΙΟΡΚΜΚΠ‹άξgŽσψΖ@ξπτνρσΪΜ€ΛΘΟΌ²ΡΙΜΏ‰χζfσψΖ@ομτνρΣΚΜΚΛΜΘ²ŸΏα“¦ΫdσψΖ?κξψτωΩ»ΛΛΚΜΙΝΓ’Υ֝|δνή_‘σψΖAρλτρστΦΑΙΜΜΘ՞¨½ˆ‹ήηκΦχ\šτψΖ?κοσκμμυηΚΛΗΥ›‡±‡²ίΤΘΡΊαόψΖ@ξκτ€οrξρπΡΙΜ‚ΧλλκΥΞΕΓΕ”ψψΖ@νξπιοπκλλΝΝΔ–λγΥΣψρε‚φώψΖ@κλςξππνμΟΚΛΞ¬ΪκΧΩτλίvσώψΖ@ονοηκιμγΘΛΕΟ΅ΰΥΡςή|ςώ€ψΖ@μοφοσπφιΠΦΠάΊžοΗΧά ‚ςώψΘ>ζβδήΰγάΧ™‡ˆ}ΣΟƍςώ‚χΕDϊω„ ώύόψχς§™ςώƒϋΫ&nc€gfgghjhheaP₯σύ…ό΄irm‚n‚mqΫφώ„€ώώ”ώύύά¦¨₯€¦₯₯€¦₯₯„¦ ₯¨£Λύόε9nnpqrpoprr€qpqqprj~7ΌψχΕAφψŽώςjσψΘ?ίΧα€ήγζΧΟΦδγήήέΫήγΰεΥό`’σψΖ?μησρπφᣌ…Š£δχςτςρσρχεfŽσψΖ?θζολξζŽzw’ηννκπρξτγeσψΖ@νεςλχΆx†ƒ‡vΏχλρπρουγfσψΖ?θιχρϋ¦|„~~„u¬τψυτσψζfσψΖ@πηυοόΏu€—ƒ…vͺώουστςφζfσψΖ?κμυορ𝎫Ί•|jΕόρφρξτϊθgσψΖ@οιυσρϋΣ¨΅±š„ŸχβΧΨαςυχηgŽσψΖ@οντςοψΡ₯Έ”ΏυΙ±²ΒθύθgŽσψΖ?λκσςςτυψΐΆΞΦ£΅±²³¨©ψηgŽσψΖ@ςνψχψωυά³—Εΐ³―±―·–δοhŽσψΖ?ικττφχυόά²œ¨·³°²·πiŽσψΖ@ςνυξπρAοωΜ―ͺ€΅―±²Ί†ΡςiŽσψΖ?μκυςρςωΪ°±±²°΄Ά°²°΄‚ήμgŽσψΖ@ξμσνππΚ°€±―΄¦Ά―²¦‡χεeσψΖ@οισνσΏ«΄°±²―·šΈ¦Δƒ¨ώάdσψΖ?κλψτω¦―±±²°³ͺœΌΉ‹{γξέ_‘σψΖ@ρθτστφΧΆ―²²―Ή•€}‹ίθκΦχ\šτψΖ?κνσκμλυλΒ―ΉŠ…«ˆ΄ίΤΘΊαόψΖ@οθτποποπσ½±}ΪνλιΦΟΖΔΔ”ψψΖ@νμπιορκνθ΅³©’λαΦΣψρβ‚φώψΖ@λιρξππξν»­²²ŸάκΨΨυκέwσώψΖ@οιξηκημΫ­²¬ ΅Ÿ­ίΤΠρά|ςώ€ψΖ@μμυοσπψΰ²»΄Ώ’žξΗΦΪ ƒςώψΘ=ζήγέΰγάԐ…vΣΟΕ Žςώ‚χΕDϊψ„ ώώύωχρ§™ςώƒϋΫ&mafgffgfghggdaP₯σύ…ό΄irmnno€nm€nq€Ϋφώ„€ώώ”ώύύά¦§₯€¦₯₯§§¦₯₯„¦ ₯¨£Λύόε9noprronpsr€qpqqprj~7ΌψχΕAφωŽώςjσψΘ?ίΪβήίήειΖηγήίήάίγαζΥό`’σψΖ?μλτσπωά€]UZ…δχστςςσςψζfŽσψΖ?θθπλοβ`FQORAyλμοκπρξτγeσψΖ@νθτκύDZNSQWMΐχμρρςπυδfσψΖ?θμψπώ„JUONMQJ©υωυτσωζfσψΖ@πκχξ©>SPh^VM¬ύοτσφςχζfσψΖ?κουορρ€]‚Œ}OSΙόφωσντϊθgσψΖ@ονφυρΕ}„~sžϋΪΙΛάυφψθgŽσψΖ@ξπυςπχΜ—ƒ‹zΖ󭄁‡¨ιύιgŽσψΖ@λντςσφψϋ¦‡vΣ½uˆ‰ŠzžϋζgŽσψΖ@ςοωψψϊσΠƒ}Δ—…‰…††‹€θξhŽσψΖ?ινφυφωφЁ‚ŸŠ…ˆ‡ˆ…Š;wΦοhŽσψΖ@ςοφξπςμώ΅ˆ…ˆ††‡ˆ…ŒpΥρiŽσψΖ?μνφσςσύΟ†ˆ‡‡†‰‹‡tβμgŽσψΖ@ξοτνρο°ƒ€‡<†‰zŠ…ˆ~„ψεeσψΖ@ομυνφŸzŽ…‡ˆ…‹{‘€•j«ύέdσψΖ?κξωτϊΖƒ‚€‡†‰‚““Šn{δξή_‘σψΖ@ςμυτυωΧ£…‡‡†Œrv}lŒΰθλΧχ\šτψΖ?κπσκμλτρ΅ƒ‡Œoƒ ‰·ίΤΘΊαόψΖ@ομφρπρρξχ‚‡tήομιΧΠΗΕΕ”ψψΖ@νξπκπρκπδŽ‰MŒνΰΧΤψπβ‚φώψΖ@λμςορρξξ›Š„ŠΰκΩΩυκέwσώψΖ@ομοηλζορ‹ƒ‹{­ίΤΠρά|ςώ€ψΖ@μπχπυπόΤƒ‡‘{žοΘΧΪ ‚ςώψΘ>ζαδέΰβέЁrrwjΣΟΕ Žςώ‚χΕDϊω† ώύψς¨™ςώƒϋΫ&ma€fegeegeeb`P₯σύ… ό΄irmonono€nonq€Ϋφώ„l8mk4 ”š˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜—š“£S`ψώώχ•\πϊφχχχχχχχχχχχχχχχφϋο_ψώώχ”^χύώώώώώώώώώώώώώώώύφ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ“^ψώώχ’^ψώύυ‰^ψώώύύπ/^ψώώώϋψG^ψώώώϊόS^ψώώώϊόW^χύώώώώώώώώώώύύϋωR_ψώώόότI\ρϋχψψψψψψψψψψχο@aψώώη86‘–œšššššššššš›Œ#it32r°Œέώ›ώίώ›ωΫχϊ›ϊόέϋϋ˜ύώψΐ‘vimΠl kmiz”Θόύύ”ώόΐ(ά7ΣόώώόΫΩ"ξώ‘ ώψ}K™ŠΤ Œˆ˜;šωώ όγ ”χώΣώχq!φ‘ώόβ‹ώΰκδΰββγββγββ†γδ€ε‚ζεε…ζ‰η…ζ€ε‚ζεεδδ†γββγ‚βΰεΨlφ‘ώό⏅yέςορρ€π…ρςς‡σžτ‡σς†ρƒποτζpφ‘ώόβ ”τ?wΗπινμλλμ…νξοο„ξοπ†οπ„οξο€ξοξξ…νμ‚λκπαoφ‘ώό⏳Μομξνξν…ο‡π₯ρˆπ…οξ€νμργoφ‘ώόβθτλννξ†ο†πŠρ€ς ρςςρρςςρςρςρρς„ρπ‚ρπρ‡π„ο ξννμργoφ‘ώόββπνξοπρ€πμξƒρπρςσπρςρςρƒς€ρσρξσσρξτςτσστσςοο…ςσρσνρςρρ‚πρπποοπο ξμργoφ‘ ώόβ‘βσκ€ξBοξξοιλοκιλθλιμκιιλρνκθλμκννομλμμρτνηηλθλιιθλζςμζμιβππζθιδεελγηίλρππ†οξ€ονςγoφ‘ώόβθνσρςςσςςτξςσνσκονξμ€ο/ξσρκτρκννππδηβαβιδπεμςικπσεοχξκνκλφρλζθξκξαιηησυτ†σ ςςποοξσεoφ‘QώόβŽpjηδζηζζηαΰγαγαεγβγδδεγθζαίγθεέΤΛΓΑΏΎΎΐΒΙΟΩέίααγαηνζίίβήκγέάίζβδέήαήβζι€θι†θ ζμποξσζoφ‘ώόβ ”χI„ΗήΩέ݁ΫΪΫάΫ€έΫάέέ€ή.ίΩέΫΗΐΎ»Ό½ΎΎ½½Ό»Ί»ΌΉΔΣΨΫΰΰαΰήααΰΰαήίίΰΰίΰέήΰάέΰ…ίή ίέιπξξσζoφ‘ ώόβŽΒΣυσ„υ€φχ‚φχχψψχωωβΙ€ΑΐΏ½Ό‚» ΌΌ½ΎΐΘΩκςχƒωψψωψψχχψχωψχωχφ…υƒτ ςπποτηoφ‘ώόβ‘λωνοοππ€ο…πρ€ςσςτοΜ»ΎΐΎΌ»ΊΊΉΉƒΈΉΉΊΊ·Αέκςσσττσττ‚σςσςσσςρπ‚ρππο€π€ροτηoφ‘ ώόβερρ„ςσςσστυυτυτφπΗΎΓΐ½»ΊΉ‰ΈΉΉ½¬Ίίξυφυυφυφυ€φυφυυτ€υ σσςσσςσσςρςς€ρπτηoφ‘ώόβ‘θϋξςρςςρςσςσςςστυυτυσΘΎΒΌΌ»ΉŒΈ ·ΉΈ›Ώγςφςχφχ€φυυχρξρπυ„τσ„ς‚ρπυηoφ‘&ώόβŽεγσοππρπρνκξκμξκξμλπλμτΡ½ΑΌΌΊ‹Έ·Έ·Ή΅½‘”ΚΫλξκιολζουιιθιζδυς„σς„ρπ€ρπυθoφ‘%ώόβaaΣψςφυυτοφντσμυποπξξςίΐΑ½ΌΉ„Έ·Έ·ΈΈ··ΈΈ·Έ΅†¦Ϋνινυετπρχενηλκπϊψψ„χφ„υ ςρρπυθoφ‘ώόβ”ωTΝκηιιθθβγ€δ γιδδβεγθΛΎΏ»ΊΈ·Έ··Ή΅Ύƒ»Χΰεκΰείεξίγβΰααθλ€μ„λκι θοςρπυθoφ‘ώόβŽΝάθΪήίΰήήέέίέήΰίΰαΥΎΏΌΊ’ΈΉ΅½ r€ΛίβγαΧΥΰεβΰγββΰαγγβγ…β€α βΰλσρπυθoφ‘ώόβ‘νόρχχ‚ψωωϊϊωϋψΨΎΑΌΊ“Έ·Ί±y£Φςϊϋϋψψϋϊϋϋ„ϊ…ω„ψ φςςρφιoφ‘ ώόβζρςσ€ς„σττυςΕΏΎ»Ή”Έ ·ΉyŒΖθτυυφφƒυ‚τυττ‚στσ‚ς στσρφιoφ‘ ώόβ‘μςφ‚υ…φψφϊμΑΑΌΊ”Έ ΉΆ½Ύεχωψχχƒψ…χ„φ‚υ€τρφιoφ‘ ώόβŽάΦχστ„υ φφχτϊεΎΐ»Ή”ΈΉ΅Ύƒw΄ίυ€ωψ…χ…φ„υƒτσχιoφ‘ώόβS[Νψρτς„τ€υφσωα½ΐ»Ή”ΈΉ΅Ώ„q¬Ϊσψχ…φ„υ…τσσ€τσψιoφ‘ώόβ“ύb™άϊφ…ψωϊχύιΎΏΊΉΈΉƒΈΉ΅Ύ‚q«Ϊφƒό…ϊ„ω„ψ χχυττσψκoφ‘ώόβŽΩΰξικλμ‚λƒμλογΏΎΊΈ·΅ƒΈΉΆ½vl£Ρκ„πο„ξ…νƒμ λπυτσψλoφ‘ώόβ‘πώέΰΰ†αƒβαΕΌ»†Έ ·ΈΈ··Ή·ΉΏ··‚Έ··hkΙα…ζεˆδƒγ βνφττωλoφ‘ ώόβισω„ϊ‚ϋόϊύά»Ύ‰Έ»ΐΑΗ³šΊΉ€ΈΉ·»¬e}°βωώ…ύό„ϋ…ϊ ωωχυυτωμoφ‘ώόβ‘πρσστυ‚τƒυφυφξΔ»Ί…Έ ·»ΒΗΚΜΜΚil΅€Έ Ή΅Ώ–^…΄βυωƒψχψχφφ€υφυφυ„τ στυυτωμoφ‘ώόβΕφυφ‚χψχψψχψχψχωωυΫΌΌ‚Έ"Ή·ΈΑΙΜΜΚΝΗΤ‘TΎ·ΉΉΆ½xcΓλψϋϋϊϋϋϊωϋϊ€ωϊωψψ€χ€ψ„χφ€υτωμoφ‘ώόβ‘HYΛϋσψφφυψοςχςψχ€ψωϊχνΜΌ»ΈΉΈΉ·ΌΉΛ$ΜΙΟ΄fœΏΉ»ΆΌ©_sΟιϋϋϊόσψόυσψωωϋωϊωχψχψχ„φ€υτωμoφ‘*ώόβ’q£ήφτφυυτχμθςξπνρμννσωμΨΎΊΉΆΈ·ΐΛΜ‚Λ(ΜΚΞΐc˜ΑΉΌ΄Ύ{Yx¬Ϋΰμτλνθζξρβξκλνζρζμξδοχυφφ‡υτωμoφ‘ ώόβŽαιϋψ‚ωϊστορτονυσυτύσθΥΑΉΌ·ΔΜ†Λ&ΜΖd‘ΑΌΈΎ‘Sm“Ηκξχνςικϋοκπςοημκοκμεκλϋωϊϊ„ω χυυτωμoφ‘'ώόβ‘οινμννμλξελεΰεββλικθοδαάΡ¨²ΗΜ‡Λ#ΜΖ_‚ΑΉ½²_XuœΟηηξΰγΰήγγδγΰαέδήαβάΰήζοξ‚ν μςφυτωμoφ‘ ώόβκπ€αβδ„βααβγ εγβαήΖΏΟΚΜ„Λ%ΜΚΝΔ^v»Ό½vUn·Ψδηθζβγδαεηεεβγβΰεαδζΰδε…δ εγξχυυϊνoφ‘ώόβςωϊϊ…ϋύ€ώύώώψΦΜΘΙ…ΛΜΚΝΑd}±ΐ–mvΏεψύ‚όϊϊϋύ€ύύόόώύύό…ϋ ϊψφφυϊνoφ‘ώόβΓ²ρστφƒυφ…χ€ψϊΤΖΜΠΠΜ„Λ&ΜΚΞΏa|―Ό‡΅ΪπωψϊύψλήΥΠΞΝΝΞΡΥΫακπτφφχψχ…υ τυφφυϊνoφ‘ώόβ’ώ@\Ιύυωχψψχψχ‚ϊωϊωϋϋωώέΖΟΗ©ˆΓΝΚ‚ΛΜΚΞΎa€΄ΞΎΌΨοωϋϊδΡΙΘΙʁΛΚ€ΙΜΣέθρφψω…ψχ€φυϊνoφ‘ώό⑁ζχφψ€χψψχσϊϊψφϊωϊϊϋϊϊνήΗ‘|lΌΟΊΛΜΚΞΏa‚΅ΨίγπωϊόθΟΖΙ€ΜƒΛ€ΜΛΙΙΜΤβου†χ€φυϊνoφ‘ ώόβŽηξχτ‚φμμοοπξνκρλσοξωχξΪΌžΊΝΚ́ΛΜΚΞΏa‚ΆΩμβημπξήΗΚΝΜ€Κ„Λ ΚΚΛΜΜΛΚΕΣιρˆφυϊνoφ‘ ώόβοχωϊωοϊξρυοπσξςοφλύυςλΟ½ΐΜΛΝƒΛΜΚΞΐdΏέλννονΨΗΝΛʎΛΜΚ²Κθτ„ϊ χφφυϊνoφ‘ώόβιςλμνξξννα€εδγβζδεεδαννδΰΨΦΥέΧΗƒΛΜΚΝΑ_xΆΥένίλΰΗΝʏΛΜΙΠΈ—Ζίμ‚ξ νςχφυϊνoφ‘ώόβσβαβγδβαΩήβγαα€βΰγβγδζβαγδαββΡΚ́ΛΜΚΝΒ]t¬ΤεηεάΘΜΚ’ΛΚΛ„˜Ηہδ εγοχυυϊνoφ‘ ώόβŒ³ ςƒϋϊόόύώώύώύώύώώώώώύτΤΘΜΛ ΚΝΔh½κύώΩΙΜΚ‘ΛΝΗΣ‘†Ηθω‚ϋ ψφφυϊνoφ‘ώόβ“ϋtΓζΰδγ‚β€γβγΰαγ ΰβδδεζίηΤΘΜ†ΛΚɜΛΙ`^ŽΑέδδεβξψυτωμoφ‘ ώό⏱Ιφϊ…ϋύώ€ύώώύ ώύώώόόξΝ̈ΛΜ™ΛΜΙΠ·Xu¨άτϊ χφφτωμoφ‘ ώόβρύυφυφυ€χψ„χψχφϊωαΗΚ₯Λ ΚΝΗΥ™Q~­ήρτ φφυτωμnφ‘ ώόβμϊχƒψ χψχωψωϊωϊω‚ϊωϋύοΥΘΝΜ“ΛΜŒΛΝΘwXнηυ€χ φφυτσψλnφ‘ ώόβλϊτ€χψχχψψυςφψωϋϊϊωϊωϊψόοΩΙΙΜΚ”ΛΙΙΘΚ̊ΛΜΚΝΒ[g•Λμ€φ€υ ττσψκnφ‘ ώόβςωωυ€φχσπρλελνισθξψοφομήΝΗΜΜΚ”ΛΚΡΞΠΞΙΜˆΛ ΚΝΗԞOv’Φξ‚τ€σρφιnφ‘ώόβŽ{nήύωϋϊϊωνςπιζξμύρλζΠΙΛΜΚ”Λ ΜΙΠ―d|ΑΟΚ̈ΛΜΘtX…·δτψψχχφσςςρυθnφ‘ώόβ ”ωE~Ιρλξξμπγίθ€ΰ έίΰδοξΪΞΙΜΛΚ”Λ ΚΝΖΧ?QpΛΚˆΛ ΜΙΡΆPdŒΐΰκμ€λ ιξςρπυηnφ‘ώόβŽΏνήββγββα ΰίίβήΰδάΙΚΛΚ–Λ ΚΝΗΣ’Qu΄ΟΙΜ…Λ ΚΝΗΤ„Hp˜ΗΫαα€ΰ ήιροοτηmφ‘ώόβςώφϋϊ…ϋ€όϋύϊύάΘΝʚΛΜΗp†»ΚΚ‰ΛΜΓZaˆ½ετφφυττσροοξσεmφ‘ ώόβλχυ€τŠυτΞΚΜΜ™ΛΝΗΤ™}ΏΩΟΚ…Λ ΚΞΖΥ~OršΝθοπποƒξμργmφ‘ ώόβνώσψχ‡ψχϊΪΘΛΙΜ˜Λ ΜΙΟ»x¬ΩΤΙΜƒΛΚΞΕΧ—KeƒΆέξρρποοξξνμμλοβlφ‘ώόβŽλνϊυφφχφ‰χξΟΝΞΙΛΝ̘ΛΙy’ΞΣΊΛΚΛΞΖΦ£M_w£Ξηοποξννμμ€λιξΰlφ‘ώόβicΦωσφυ†φ υπΩ»ΔΠΜΗΚΜ•ΛΚΝΒgƒΏΟΚΜ€ΛΚΝΛΖ֟L\p–Αίλξμ€λκ ιιημήlυ‘ώόβ ”ϊO‰Υώχϊω‡ϊ χλΜ©¬ΗΣΞΘΛΜ‘Λ.ΚΝΗΤ U„΄ΞΚΜΚΚΜΝΗΜΥ’L_r•Ώήμποξξννμλλιηηεκέύjφ‘ώόβŽΜΧολμμνμ‡ν ιήΖ‘‘ΒΡΚΙΜ‘ΛΜΚΚfWƒΓΜΚΛΜΝΙΘΤΔuG\m޳Πίδγ€βαΰίίήγζεδθΪϊiυ‘ώόβςύίααβγƒα†β ίΧΜ΄”Œ¬ΛΟΙ̎ΛΚΞΖΥ‹Bg―ΠΛΞΛΘΘΡ£WG`o°ΘΥΨΩΨΧΧΦΦ€Υ έεβαδΧυeω‘ ώόβλφ‰ϊ†ϋ ωσκέΒ ›ΌΠʍΛΚΝΖΤ₯EwΏΡΙΙΗΚΣΣ²sLZpƒ₯Εέι€μλκκιιθηζζγΰίέΰξR3ό ώόβορ€τυ†τƒυ€φσξζΪΌ ²ΞŒΛ#ΚΝΘ²L‹ΜΜΘΝΡΤΛͺvQRjy‘±Μήεζηζεεδγγααΰί άΩΨΠέ.UψώŽ ώόβŽβίϊφƒχ ψφψχφχφχψχψ€χ ψψχτξηΤ°±ΜΚ‰Λ ΚΜΙΟΌP’ΩΚΞΝΓ°iPUh{Œ§ΒΦβζηθζεεδγβ€αΰΰήάΪΧΣΜΟ΅ •χώŽώόβY]ϋτψφφυψνζθσψφψχχψψω€ψ χψϊυοξδΒΊΞ‰Λ5ΜΚΝΔ]V{•«¦‘waT`v„“§ΐΰεθηθεζζγδγΰβίίήΫΪΨΤΛΠΆΨO ΠϋώŽ.ώόβ“ό\”ΦψτφυυτψζξξεκδμγηνγμλγττμσαγωαΥΏΌΛΚ‡Λ2ΜΙΞgKfuž–ƒu{€‰š«ΆΏΣζΧΠΠΡάΞΣΦΘΜΛΕΛΓΦΦΣΞΘΜ­ƒ ?ϋ‘ώόβŽΦΰϋχϊ€ωψόμυϊΰοφήπνήμβκψχυμτδρώεσήΐΝΜ…Λ6ΚΝΗ֊Ia}’ΏΔΈ¨«§²΅ΛΥΞΤΩνΥΪΤΧΞΤΔΙήΔΖΣΑΜΉΛΚΗΒ§Τ›ωώ-ώόβ‘πθλμννμλοίάέαίίάζγάέΰήέθλΫάΫΰρΫάάΟΏ†Λ5ΜΚΞ½MZk“³ΚΞΕΖΕΚΚΜΝΙΠΝΙίΜΠΛΝΌΐΉ½Α³½Ζ±΄¬ΉΒ΅²ͺί€ Uωώ ώόβκρ€ΰαγ€αΰάήγήέβΰΰαάαΰάαβήέβήδΥΩβίΟ…Λ4ΚΝΖ֎Fi‹ΆΠάΩέάΦΫΩΪΥΣΦΞΞΜΚΙΗΑΓ·¨±ΏΊΉ±«¦Ÿ£΄θ₯+μώ’ ώόβ‘οφωϊόϋωϋόϊϋϊϊόϊϊϋϋϊϋϊψόϋωφΥΙΜƒΛ4ΜΘΡrX†΄ασφχττυρροονιθαΫΦΡΝΛΘΗΕΏΉΌΊ·΄΄·½ΡΨδ₯ήόώ‘ώόβΨΝτςσστστυ€τυττυ…τυστυσ€τήΘΜΚ„ΛΘbd“ΖζοπξοομλλκηεγάβηαίΫΨΥΠ€ΡΣΧΫαδλάΤͺΦϊώ’ώόβ‘MZΝϋτχ€φυφχχφφχφχφχ€φψφχ€φχψυϊάΘΜʁΛΜΚΝΑ^n£ΥνσρρποξνμκιεβΨκώ„ώύϊφςιδΣΞΈ Εψώ“ώόβ“ώjŸέψτφ€υχυχφψψχχφχφφχχψψφμωφψχψσπψςΟΚƒΛ2ΜΚΞΑ^w¦ΪορσρρπξμλιζεαΤζώφωχφυττσςξλιααΥΡΏ Όχώ” ώόβŽήεχσ‚τεεξβθηγδζςχονοδσθγγαιμρίΰνΣΚ†Λ/ΜΖ]p›ΣορεΦαΨΨΤΨήΞΣΙΐΪψόϊωψψχφσπνζδΦΠΓ#―χώ• ώόβ‘ου€ψωψψηιγηεενλλσύφηθδυζζγωήκσΰξΰΙΜ…ΛΜΙΞnj€έτσΫςΥΩάίΩΦΥΒΞΈΣυϋ€χφτρξλδβΥΟΙ)¨χώ– ώόβιρ€λμμλλίΨάΫήΰδγβαθρΫάγΨΩέΥέάάΨΫέΝΚ…Λ/ΚΝΗΥ…bœΖΰκΦΥΠΧΧΩΕΘΊΘ΅ΞυϊφχφυρομδγΥΠΛ+υύ— ώόβ‘ςΰ€αβαβέέβάή€ΰαΫήβαβαΫαΰάγίήίȈΛ-ΜΘΡ°a—½ΥΰέΥΪΩΧΥΥΡΜΙΘΆΣυψφφυρομδγΥΡΝ+‹φώ˜ ώόβΙΊχω‚ϊϋϋϊόϋϊϋϋϊ όϊϊψόϊϊύΪΚΜΚ‡Λ+ΜΘӘŒΞθςσσοξνλιθείάΘήτψφυρομδδΥΣΟ+‹χώ™ώόβ’C[Ηωρφ†τυƒτυτυτσχίΖΜʊΛ(Κ̐©ΨθμλκιζεδβέΩΥΑΫτχτρομδδΤΥΞ(‹φώšώόβ’z©γχυχφχχφ€χφχ€φχφχχφψρΛΜ‹Λ(ΜΙΡΆΓήμνλκιζδαΰΪΨΕάσφρομδδΣΦΝ%‹φώ›+ώόβŽελψτυυφυφψυμρχχψχψσσψφψχςσψχυϊέΗΜΚ‹Λ&ΚΝΓ}‘ΡζνμκΫδδγήάΚ―βύςσξμδδΣΩΝ#‹φώœ ώόβ‘ξρ€τυττθΰήμθαζγγκιαλεδμζααΰοΨΘΜΚ‹ΛΚΝΕe{ΈΛΧίΠΙΧΚΦέΨΖ›ΫύξπλδεΡάΙ €šχώ ώόβθςχψωτηφδδηχήκοακδκηζκΰνθκλΪΗΝΚ‹Λ$ΚΜΕcy™ΗΦΝιΗΠΞαΪΙ―ΰϊλνγεΡίΓ¨φώž ώόβςλμλκάΫΧέάήΤδζΩαΪΨίΦάΫεβγαΦΘΜʌΛ"ΜΗ]gš»ΠΟΜΕΗΕΜΜΠ½«λτκεεΠ⽨υύŸ#ώόβŒ»₯ΫΰΰαβίαήΪίίΙΦαΰΰαάαήέβΰ€αβΡΚΜŽΛ Θ^f ΐΡΧΝΡΡΙΜΗΔΎ­ιρβηΟζ΅ ¨φύ ώόβ“ό=_Λφϊψ€ωϋωωφτ‚ωόϊϋϋ€ϊϋωόΨΘΝΛŒΜ ΛΜkr¬ΨλκλθδεαέΦΝΓςεεΟθ― ­φώ‘ώόβ‘гητστσςτστυƒστσσ€τυσφΧΙΛΘɊΘΙΗΙjm§ΡγζγαίήΫΥΡΓΕπγΠ馀 ½χώ’ ώόβŽκπψυ‚φυφ€υτ€υφυφφχφχ€φυωΨΘΟЁцΡΠΣnl©εζζβΰίΫΤΡ½ΟσΛμ› ½φώ£ ώόβνώσ€υφυυχυχφφχφφχφφυφηφλπχχυχΨΚΑΆ΄€²°„² ±±²±΄mm’δηγΪαέΪΣΝΉαΨθ“Ηψώ€ ώόβθσσƒτDβαηννδίζιένσχΰλαβΰθήηΣΗ—h^[^[X[]ZXVVY`\UXU_s—ΗΙΫβΡΚΑΙΎ΄ΈΩμ…%Ψωώ₯ ώόβσχψEωυδςάοξΫρβαχρωωςήεήεββζβΥ£”ƒ—Œ‰‹–…ŒŽŠ•މ‚‡’΄ΒΠΤζΚΔΫΌΉ¬ΐφx*εωώ¦ώόβŒ¨•ζλλ€μCιήζΨΪΦΧηάΩΫΰηλνΞβΫΨΰΨΥΧΣΒ΅΄²°­³±―«ΈΆΈ²Ώ°ͺ₯Ή±½ΕΖΣΪΔΉ»ΈΆυr*εϊώ§:ώόβ”ϊ:gΏγέααΰΰήίίΫΫίίΰίΪίήΰαΰαίΪΰΪίίάέΥΦΪΣΧΩΨΣΧΨΧΧΦΧΤΟ€ΡΠΠΜΡΠΚ΄ΌΎ₯ηn+εϋώ¨ώό⏙»νχχφφχψωωψϊ‚ψ χψωψωψψωχωψφωχ υυττσςρςοξνκκθθδγΰάΒδfAςόόώ© ώόβπωψ€φχφφŒχψψχψχ(ψχχψχψψχφχφυυττςρποξμιθεδίΧΚΞΦNBφόόώͺ ώόβŒαοι‡μ—ν€μλκιιθηζεδβίήέΫΨΧέεΉ/Bφϋύώ« ώόα”χώ°ύϊχνΜo Eυϋύώ ύζ?ymsqŸr‡qp€omleC dόϊύώώχ· ‹ωώώ±ύθ ³  0ΔχΆύΦEΈH§ϊωΈύύέ³―š’¬‘ ‘–ΘκόϊώΈϋϊΊϊψώ»όψψ³χψψϊύ€ώΊώ»ώώ­Œέώ›ώίώ›ωΫχϊ›ϊόέϋϋ˜ύώψΐ‘vimΠl kmiz”Θόύύ”ώόΐ(ά7ΣόώώόΫΩ"ξώ‘ώψ}K™ŠŽ‹‰ŽΞ Œˆ˜;šωώόγ ”χώόωΟώχq!φ‘ώόβ‹ύίιγίβέΨγΰααβγγ€β€γδƒγδδε‘ζ‚εδδ‡γ€βγγβ„αίδΦlφ‘ώό⏅yέπομηρξ…πρςρςς€σ€τ•σ€τσς‚ρςρπρ€πο πξσεpφ‘ώόβ ”σ?wΗξκζίμιλκ€λ€μλλμμνν‚ξ€ν‰ξοˆξνξ€νμλλμ…λ‚κθοΰoφ‘ώό⏳Μξινηβξλμ„νξξ‡ο˜πˆοξξ„ν…μ λλκοαpφ‘ώόβζςιλνιδξλμμ„νξξ‡ο‚π‚ρ”π‚οποξ„ν…μιοαpφ‘ώόβαομμοκεομξλξπποπρ πρξπςρςρςσςρππ€οςπξςςονσρςςρςςρξξ€ρςρρπρμπρπ„οξƒνλπγoφ‘Pώόβ‘αςιμνηβξλοιλοιθκθμθλιθθκπμκθλνικκνλμνξςυμεεκιλιιηλζρλελθΰοοεηθδεελγηέκπ‚ο„ξνμμ€νμρβoφ‘PώόβημρξρλεσρσμπρμςιξλμκννξνσπισξζλοτςβΰΧΦΧββσιξοηκορδξφξιμιλυπκδζμθμΰθηζςσ…ςƒρ πξννμργoφ‘ώόβŽpjηεγήιζθβαδβδβεδβδ€ζ0δθηαήενεΟΆ ‘‰…„…ˆ ΄Οΰβίβγαζμζίΰγίμείήΰζγδήήβίγηλ…ιƒθ μξνμργoφ‘ώόβ ”φH„ΘΰήΪΣΰέήήέήήέ€ίή߁ΰ ααΪεΫ―ƒ~„†„‚~„“ΊΩΪήββγβΰββαβγΰαβγ€βήΰαέίγββ„α€ΰ αίιπνμργoφ‘ώόβŽΑΣσπυξηυςσσ„τυ€τσυσχωΘ“‚…ˆŠˆ†„ƒ‚‚ƒ„††…‚„¦Ψθπφφχψ€φυυφφ€υφυφυτυƒτ„σ€ς ποονργoφ‘ώόβ‘κψνοπκδρξπποοποππρπρ ουμ’~…‰‡„‚… €€ƒ„|•Εάμς‹σ€ρπ‚ρ„πο€πξσζoφ‘ώόβδρππςνθςρςρςσςςσςχ딁‡„ƒƒ‚ˆ€…€”Ύάξυφυυ‚τυσσςςσςσςς‚ρςρρποτζoφ‘(ώόβ‘ηϊνπρμθσπςρςρςσςσσςσστυς—‚Œƒ„ƒ‚Œ €‚€”Ώαρυςφυχ€φ υυφπνππυττ…ς„ρ€ποτηoφ‘'ώόβŽδβσνρληςπμιξκμνινλλπνκφ€‹‚„‚€Š€€€‚~—ΗΫκνθηξκζουι€θεγτςσσς„ρ†ποτηoφ‘%ώόβaaφςπκυρνυνςρκςξξοξλτΠƒŠ„„‚„€€€€€€§Ϊνιμτγσξουδνηκθξψυφυƒτ‚σ ςρποτηoφ‘ώόβ”ωTΞμκζΰμι€εδεδιζζγζβκŸ‚ˆƒ‚‹€€€€‚t‰»Ωαζλαζίζοΰδγ€βθμνμ„λ€κ ιξςροτηoφ‘#ώόβŽΝΫλήδήΪγαβΰγΰαγβγβγβθΘ‚‰„ƒ“€ƒxw€ΞβζζδΩΧβηδβζεδγδ‚εδƒεδγγδβμσρπυθoφ‘ώόβ‘μϋρυφπκχυψψχψψχ€ψϊυ²‹ƒƒ”‚~v£Φς€ϊφχ€ωϊω„ψ„χφ€υ σςςπυθoφ‘#ώόβερςπςνθσςσςσςςσττσσυ‡ƒ‚– oΔθτφφχφυυττ€υ†τ„σςρρ€ςρφθoφ‘ώόβ‘μπστνθχσ‚υ€φχσϋΰ†‰„‚• €‚oƒ»δυψψχχψ€χφχφφυφφυυφυ€τυτυσςρφθoφ‘ώόβŽάΤυπτοκφσ€τ‚υφςώŠ‚‚•€ƒo{³ΰτ…χ…φ„υƒτσ€ςρφιoφ‘ώόβS[Νφςοιυςσσ‚τσφςύΜ€‰‚‚”‚€ƒnu«Ϋσψχ…φ„υ…τ‚σςχιoφ‘ώόβ“ύb™άωχσξϊχψωϋυΧ‚‰‚Œ€‚ƒ‚€ƒmuͺΫτϋόϋϊ…ω„ψ„χ φυττσψκoφ‘ώόβŽΩΰπκξθεομ€ν‚ξομσά‡†‚ˆ€€‚‚„€‚gp’Σλ„ρπ„οƒξοξ‚ν ξμρυτσψλoφ‘ώόβ‘ούΰγγαέδβδγδδ‚εζε嘁„† €€‚‚€}„€…anžΝδιι‚θιθ„η„ζ‚ε ζδξυσσψλoφ‘ώόβθςχχϊςκϋχψ„ωϊόχΓ‡€‚„ ‚‚€ˆ™Šs‚‚ €‚|c|°αψύύ„όϋ„ϊ„ωƒψ φττσψλoφ‘ώόβ‘πρσυομυς‚τυτ€φυυ픁ƒ€€‚~‘’³΄³hc€‚€„taƒ΅βυ€ω ψχψψχψψφφυφ„υƒτ υττσψλoφ‘ώόβΡΔφτχρκψυχψχχψ‚χωχχΟ‚„)€‚€~¨΄΄±²¬ΈŽ]‚‚€ƒhgŽΓλψϊϋϊϋϊϊωϋϊϊωψωψψ„χ…φ€υτωμoφ‘ώόβ‘HYΛϊυσμψυψοςχςψχ€ψωϋυςΉ…€ƒ~†’³³€°$²°Άžj†ƒƒ‚€ƒ{`ržΟιϋϋϊόσψόυσψωωϋωϋωχψχψχ„φ€υτωμoφ‘Uώόβ’q£ίφυρμχτχνιςξρνρμννσωλΫͺ‚}‘―΄°°²²±²°΄§g……ƒƒƒg^w¬Ϋΰμτμνθζξρβξκλνζρζμοδοχ€φ‡υτωμoφ‘+ώόβŽαιϋχϋσνϋψϊσσξρσοντςτσύσζΩ³„~›΄±°²‚±%°²¬e€†„„wVl“Ζιξφνςθιϋξκοςοζμκοιμδκκϊψ€ωƒψ χυυτωμoφ‘*ώόβ‘ολξοιδπμπηνηβηδδνλμκρεγάΥ¦‹‘΅―±²„±'²­`x‡ƒ„}ZZvΠθθοβεβΰεεζδαβήζίβγήβΰηποπποƒξ σφυτωμoφ‘ώόβιπδγζΰΪηδζεεζζδδε€η ζθζεεΰΙ΅―²…±$°²«]uˆ‚ƒiYnΉΫηκλκδδηδθκθηδεδβθδηθβηθηζ ηεπχττωμoφ‘ώόβςωψϋυξόω€ϊϋό‚ύ όόύώύώφΎ――°†±°³ͺa‚†Špt‘Ύδχώόώ€ώϊωωϊύ€ύόϋόώόόϋ…ϊ ωχφφυϊνoφ‘ώόβΓ²ςτφςνψυφψ€χ ψχψψωωψϋΑ«³΄΅…±&²°³¨_©΄‘…΄ΪοωχϊψδΠΑΊ·ΆΆΈΌΓΝΩηρφφυχψχ…φυ€φυϊνoφ‘*ώόβ’ώ@\ΙόφφπωχχψχϊωωϊϊωϊωϊϋψΝ§΅°«²°‚±²°΄§a΅Ο½―ΌΨοωϊψΧΊ¬―° ―­¬­³ΐΤθςυψωψ…χ€φυϊνoφ‘+ώό⑁­ζχψσνωφψψχσϊϊψφϊωϊϊϋϊϋζΥΒ‘~n§΄°²±²°³¨`‚΄Χίγπϊϊώΰ·ͺ―€³²²±€²€³±­­·Οδου†χ€φυϊνoφ‘*ώόβŽηξχσψρλψυνμοορξνλςλτοξωχπά½ž‹Ž¨²°‚±²°³¨`‚·ΪμγημοοΠ«°³²°±°±²³°―ΌΤθςˆφυϊνoφ‘*ώόβοχωϋυοόψοωξρτξοσνςουλόυριΞ½ΏΝΒ°²‚±²°³©cΎέλμνξξΙͺ΄²°‹±°°²²―­Λητ„ω χφφυϊνoφ‘+ώόβιςνξπκζρξγηηζεεδθζηηζγοοζβΪΨΧήΪΈ―²±²°³©]y·ΧήπΰξΤ«΅―±―΅€™Ζΰξοπ οσχφυϊνoφ‘ώόβσζδθβέθεέβζηεε€ζδθεζθιεεζηδεεΥΆ°‚± °³©]wΧθκκΪ­²°”±›Ι߁η θζπχυυϊνoφ‘ώόβŒ³Ÿςωϋφπόωϊϋϋ€ύόύόύόώώύύώώύύώώότΣƒ± °²«fΌιόύΕ²°‘±²·“‡Εθψ‚ϊ χφφυϊνoφ‘ώόβ“ϋtΔθγβέηεζζεζ€εηβδηζηζδζ€ηθΰμΚ¬³°…±°―œ±―]`Δΰζζηδοφττωμoφ‘ώό⏱Θφψϋυοόω€ϊϋϊϋϋόύύόύϋϊδ±²ˆ±²™±²―΅‘Xt¨Ϋσψ φυυτωμoφ‘ώόβςϋυτφρλφυ€φυυ€φυφυχψψχψχυϋϊΤ­°¦±³ΈŠS}ήπτ€υτωλnφ‘)ώόβνϊφφωςμωφψψχψψχψχψχψχψωϊψϋώιΐ­³²“±²Œ± ²―·oZ‰½εσφφ€υ ττσψιoφ‘ώόβλϊσφχςμψφψψυςφψχ€ψ χψχψψώμΙ―­³°”±―°―°²‹± °³ͺZg•Κλτυυ‚τσχιnφ‘'ώόβςωωσχπλψροςλελνιρθνχξτξμΣ΄«²²°”±°΅³΅³°²‰±²ΈQu’Υν…σρφθnφ‘&ώόβŽ{nήϋωτμϋχμλμνροιενκϋξλβΌ¬±΄°°“± ²―΅š_t©΄°²ˆ±²―ΆmY„Άβσ€φ υυσςςπτηnφ‘$ώόβ ”ωE~ΚςξκεξπγίθαβαίαβεοπΤ΄³±°”± °³­ΊuBSm²°ˆ± ²―΅ QeŒΐΰκμ€λ κοςροτζnφ‘ώόβŽΎοαζΰάζγ€δ γδγγεβγιΫ°°²°—± ²Έ‘Ttƒ§³°†± °³ΈyLpšΘ݁β γΰκςοξσεmφ‘ώόβρώφωϊτρϋψϊ€ω ϊϋϋϊύωώΘ¬΄―²™±²m†ΊΖˆ± ²±²«Xa‡Όγς€τ€σ ρονμργmφ‘ώόβκχφτφπνφτυττυφυφσΆ°›± ²·‹~ΌΩΊ―²°„±³­ΉuQqšΜηοξ μμλπβmφ‘ώόβμύςχψσνωφχφƒχωφϋΙ«³―²˜± ²°΄₯wͺΪΔ­³°ƒ± ΄¬ΊˆLd‚΅άν€ποοξνμλλκξαlφ‘ώόβŽλμωτωπκωυ…φ χχψν½°³°±²™±―u‘ΟΓ­³°‚±³­Ί‘M_v‘Νζξοξξννμλκκιθμίlφ‘ώόβicΥχτςνχτˆυρΫ±¬΄²°²–±³ͺf‚ΐΌ²°€± ²±­ΊM[p–ΐήκμμ€λκι€θ ηζλέlυ‘ώόβ ”ϊO‰Υόψτλϋψˆω φκΞ§Ÿ·³―±²’±³ΈW…±³°€± ²²²Ή„M^q”Ύάκο€ξνμλιιθζζδιάόjφ‘ώόβŽΜΧρμπκζον€ξ†ο λίΘ€Ž•ͺΆ±°²‘±²°°aX„°€± ²²――Έ¬mI]n΅ΰ€δγγβααΰίγζεδθΪϊiυ‘ώόβςώβδεΰάζγ€δε…ζ εβΫΞ·™‹±΄°±°³­ΉFhž΄±³±―ΆΆ’VK`q²ΛΨΫΫΪ€ΩΨΨΧΧΥήεβαδΧυeω‘ώόβλφωψϋσξϋψω‡ϊ ψςκάΒ’–§΄°±1°³­Ή“Hr¨΅°°±··lN[oƒ₯ΕέθμμλκιιθθηηζεγΰίέΰξR3όώόβοςυφπκχτυτυττυυ†φσξζΩ½ £²Œ±°²·M€²²―²ΆΈ±—nQTiz’±Μήζζηζ€εδγβαΰΰ€ί έΩΨΠέ.UψώŽώόβŽβίϊυωρκωφχχφψχφχφ€χψφ‚χτοηΤ²¦°‹±!²°΄¦P…»―²²¬ƒeRWhzŒ§ΑΦαζηθζεεγγβαα€ΰήάΪΧΣΜΟ΅ •χώŽώόβY]ϊφσλωτψμζθσψφψχχψχω€ψ χψωτοξγΕ―²‰±5²°³¬[Ww£ŸŒvbVauƒ”§ΏΰζθηθεζζγδγΰβίίήΫΪΨΤΛΠΆΨO ΠϋώŽ-ώόβ“ό\”ΦψυσνχσψζξξεκδνδθξδμλγττμταγωβΤΑ―ˆ±2²―³aMfwŸŸ—„u{ˆ›«·ΏΣζΧΠΡΡάΞΣΦΙΝΜΖΛΓΦΦΣΞΘΜ­ƒ ?ϋ‘.ώόβŽΦίϋφϋυπϋχόλτϊίξυήπμήλβιχφτμτγπώδσέΏΆ°†±5³Ή}K`}‘ΎΓ·¦ͺ§²΅ΚΤΝΤΩμΥΪΤΧΞΤΓΘήΔΖΣΑΜΈΚΚΗΒ¨Τ›ωώ#ώόβ‘πκνξκδπμρΰήίγααήθεέίβΰίιν€έασΫέέΣ·―²„±5²°΄¦MZl”΅ΛΠΗΗΖΜΛΝΞΚΡΞΚΰΝΡΝΞ½ΑΊΏΒ΅ΎΗ²΅­»ΓΆ³ͺί’ Uωώώόβκρδβδίάηγδγίβηαΰε€δίδγίεζαΰεβηΨέζβΡ΅°ƒ±4°³­ΊJjΈΣίάίίΩέάέΨΦΩΡΤΥΠΟΜΛΚΓΕΉ«³Α½»³­¨‘₯Άη’+μώ’ώόβ‘οφψωσοϋψωωϋϊψϊϊωϋωωϋωωϊϊωϊωψϋϋψψΖ­³°‚±4²―΅kZ…΄ΰςφχτστροξονιθΰΪΥΠΝΚΗΗΕΏΉ»ΊΆ΄³·½ΡΧβ’ήόώ‘ώόβΨΝυςφοιυσυ€τυυτυτυυτυυττυσυσφΤ¬³°„±1―_d“ΖζοροπονμλκθεγάβηβίάΨΥΠΡΡΤΧΫαδιΩΠ§Φϊώ’ώόβ‘MZΝϊυσμψτυφφχφχφφχ‚φψφχ€φχωτϋΞ¬³°‚±°³©\o£ΥνσρρποξμμκιδβΨκώ„ώύωυρηβΠΛ΅ Εψώ“ώόβ“jŸέχφρλχτχυχφψψχχφχφ€χψχφμψφψχψσρψρ·°²‚±2²°³©]w¦ΪορςρρπξμλιζδαΤζώφωχφυττσςξλθΰίΞΌΌχώ”0ώόβŽήεχςφπλυτεζογθηγδζσχοξπδσθγδβιμρΰίπΓ²°„±/²­[qšΣπρεΧαΨΩΤΨήΞΣΙΐΪψόϊωψψχφςομδβΤΝΐ#―χώ•/ώόβ‘ουψωσνϊχηιγηδδνλλσόφζηδυεζγωέκσίπΧ­³°„±²°³ik€έτσΫρΤΩάήΩΦΤΒΞ·Συϋ€χφτρξκβΰΣΜΖ(¨χώ–-ώόβιρνμξιγομαΩέέίαεδδγκσάήεΪΫήΧίέήΩέΪ³°†±.³­Ί{eœΗαλΧΦΨΨΪΣΖΙΌΙΆΟυϊφχφυρξλγαΣΝΙ+υύ—,ώόβ‘ργβδΰάεγΰίδήαγγβδήαεδεδίδγΥήζβΰα²°‡±-²―Άœb˜ΏΦβίΧέΫΩΨΧΤΞΛΚΈΤυψφφυρξλγαΣΞΛ+‹φώ˜ώόβΙΊφχωυξϊχϊωψϊωψωω€ψ ωϋϊωψϋωωώΗ³°‡±+²―·ŒΜθςςσοξμκιηεήΫΗέτψφυρξλγαΟΜ+‹χώ™ώόβ’BZΘωσριφστστστσστ σσττυυσϊͺ³°Œ±&ŠͺΧθνλλιζεγαήΨΤΐΫτχτρξκββΜ(‹φώšώόβ’zͺγφχρκψυφ‡υφφ€υτψλ±²‹±(²―΅£ŽΒίλμκιθεγαΰΩΧΔάσφρξκββΡΣΛ%‹φώ›+ώόβŽδκχςφρμχτχτκπφφχφχρςχυχφπςφχσϋΝ«³°Œ± ²«z‘ΠεμλθΪ€γέΪΙαύςςνλβγΠΦΛ#‹φώœ+ώόβ‘νώρσυνθφτιίέληΰεββιθΰκδγλεΰαήπΕ¬³°Œ±²¬c{·ΚΦήΟΘΦΚΥΫΧΕ›ΫύξοκβγΟΩΗ€šχώ+ώόβηρφφωςιϊςζφδβζυάινΰθγθεδθήλζθλΗ«΄°‹±$°²¬`y˜ΖΤΛθΡΖΟΝίΩΘίϊλμαγΞέΒ¨φώž+ώόβςνλξηαξκέάΩίέίΤδζΩαΪΨΰΦάΫεβγγΓ¬³°Œ±"²YgšΌΠΟΜΕΗΕΜΜΠ½«λσθγδΝΰΌ¨υύŸώό⍹₯ήβδΰΪδγαάαβΥΜΩδ€β ήγΰίδβγδβεΐ²°± ―Zg ΒΩΞΣΚΝΙΕΏιπΰεΜγ΄ ¨φύ +ώόβ“ό=_ΚύφυοωφψωχχτσψωψωψϊψϊωψωψωχϋΕ¬³±²±gsͺΧιθκζδδίΫΥΛΑςδγΜε ­φώ‘ώόβ‘гηστξθυςσςσσττς€στστ‚συςχΕ²Œ―°fm¦ΠγεαΰΰάΪΥΠΒΕοβΝζ₯€ ½χώ’ώόβιπχτχρμχττυ€τσ€τυ χφχφυυσωΕ«΄΄΅ŠΆ·΅·im§ΡδεδβΰήΪΤΡ½ΟρΘκ› ½φώ£,ώόβμύςτυπκφσφτφυυφτυφυυττζυκπχψυψΚ΄­‘ €žœƒž€žœŸin‘γζβΪαέΪΣΜΉαΥε’Ηψώ€ ώόβη€ςIτοιυςααζμμγήζθάνςυίκΰαΰθήηΣȘj_\_\Y\_[XWWZa]VYV_s—ΗΙάβΡΚΑΙ½²·Ψι„%Ψωώ₯VώόβςχφωςλϊσγπΫνμΪπΰίφπψψπάγέγίαδΰΤ­‘“‚–‹ˆŠ•„‹‰•ˆ†Ž’³ΑΟΣεΙΓΩ»Έ«ΐτv*εωώ¦Uώό⍦”ζλνθβοιήηΩΫΦΨηέΩΫΰηλνΟβΫΨαΨΥΧΤΒ΅΅²±­΄²―«Ή·Ή²ΐ°ͺ¦Ή±ΎΖΖΣΪΔΉ»ΈΆ­τr*εϊώ§ώόβ”ω;gΐεαήΨδ€α%βέήβαβαάβαγγβδαάγάααήίΦΨΫΤΨΫΩΤΨΩΨΨΧΨΦΡ€ΡΣΝΡΛ΅ΎΏ¦ηm+εϋώ¨ώόβ˜»μσφοκχυχφφχχφψφχ€φ υφψφψφφχυχφτχ€υφσσ€ςποπξμλιθηζγαήΪΠΐγfAςόόώ©ώόβοψχτχπλχτφχχφφχφχφ‚χφχφχχφχφφχφχχφτυ€τσσροοξμκιζδγήΦΙΝΥNBφόόώͺώόβŒίνηικεαλθιικλ“μλμμλικι€θηηεδγβίήέάΪΧΦάεΉ/Bφϋύώ«ώόα”χώύό«ώόϊχνΛo Eυϋύώύζ?ymtqrrqosšrˆqpoommeC dόϊύώώχ· ‹ωώώ±ύθ „•Š  0ΔχΆύΦEΈH§ϊωΈύύέ³―š’¬‘ ‘–ΘκόϊώΈϋϊΊϊψώ»όψψ³χψψϊύ€ώΊώ»ώώ­Œέώ›ώίώ›ωΫχϊ›ϊόέϋϋ˜ύώψΐ‘vimΠl kmiz”Θόύύ”ώόΐ(ά7ΣόώώόΫΩ"ξώ‘ ώψ}K™ŠŒΟ Œˆ˜;šωώ όγ ”χώΣώχq!φ‘ώόβ‹ύίιγίαΰΰαβγγ€β€γδƒγδδε‘ζ‚εδδ‡γ€βγγβ„αίδΦlφ‘ώό⏅yάροπξοο…πρςρςς€σ€τ•σ€τσς‚ρςρπρ€πο πξσεpφ‘ώόβ ”σ?wΗοθκθκκλκ€λ€μλλμμνν‚ξ€ν‰ξοˆξνξ€νμλλμ…λ‚κθοΰoφ‘ώό⏳Μξιμκλƒμ„νξξ‡ο˜πˆοξξ„ν…μ λλκοαpφ‘ώόβζσιλμμλμ„νξξ‡ο πποππρρςρρπρƒπ‚οποξ„ν…μιοαpφ‘ ώόβαομ€νμννξλνποοποππρρπρππξπρστςροοξξοςροςςονσρςςρςρρνξ€ρςςρςρρπρμ‚π…ο„νλπγoφ‘ ώόβ‘αςι€μ@λμμοιλοιθλιμιλιθθκπνλθλξκιθμλνοπυχνδγιιμιιθλζςμεμθαοοεθιδεζλγηήλπƒο„ξμμ€νμρβoφ‘PώόβημρξπξνρρςμοπλρθνκλιμννμςοθσνδλςψτΰΪΞΜΟάΰυνοξεκξρδξφνιλικτοκδζμθμίθζζςσƒς„ρ ποξννμργoφ‘PώόβŽpjΣκζιθιικδγζεζδθζδζθθιζκιδίησζÜ{eZTRTYf}žΘεζΰγεγθνθααεανηΰίβθδζίΰδΰεθ†λƒκ μννμργoφ‘ώόβ ”φI„Ιεαγβγβγγβ€δγδ€ε1δζεήνܜhQJNSVWWVUQLKTt΄αήβηζηζγζζεεζγεεζζεζβγεαβηζ€ε€δε€δγδβκπνμργoφ‘ώόβŽΑΣςπςπορρςςσσςσςσστ€σ$ςυςφϊ³eNTZ[YVTSRRSTWXUNR‰Ψηπυφφχφφυττ€υττυτυτστƒσ„ς€ρ ποονργoφ‘ώόβ‘κψνοοξνοο„π‚ρ πςοχκJU\XS…QPOOQTVFvΘΫμςτσττ‡σ†ρ…π€ο€πξσζoφ‘ ώόβδρ€ποο„ρς σςςσρψζiN_W€SRR„Q RRQPOXL€ΑΫοτ‚υ„τ€υσσ„ς…ρποτζoφ‘ώόβ‘ηϊνπποορςρςσςσσςςστυρnO^RTSRŒQORQΐΰρυρφυφυφφυτυπνππυτσ…ς„ρ€ποτηoφ‘&ώόβŽδβσξποξππμιξλμνινλλπνιϊL]QURQRO`›Ζάκνιθξκζουιιθθεγυςσσς„ρ†ποτηoφ‘%ώόβaaφρσρτςμυμρπιρννξξιυΓQ[SUR’QPz¨Ωνθλσγςξουδμηιθνψυ€φυ„τ‚σ ςρποτηoφ‘ώόβ”ωTΟξλμκμμζη ζλθθεθδξzOYSS’QRO`ŽΊΫγθνγθαθραζεγδγκν‚ξ‚νƒμ ορροτηoφ‘ώόβŽΞΫξδηεε€ζεηεζ€ηζθεπΏPZTS”QPV|¦εικηέΪζλθζκιθηηιθ…η€ζ ενσρπυθoφ‘ώόβ‘μϋπυτσςτυχχφχχφ€χϊς‘M\RS•QRs£Υρ€ωφφωψωω‚ψƒχ„φυ€τ σςςπυθoφ‘ ώόβερποςƒστσυμeUWRR•Q PfΔιυφφχφ†υ„τ„σςρρ€ςρφθoφ‘ώόβ‘μοςςρρυττυττ€υτχςύΥTZSR•QRPa‡Ίευχψ€χφχφφ„υ‚τυτςρφθoφ‘ώόβŽάΤυρσςς‚τυτχρΒN[RR•QRP]±ΰτ…χ…φ„υƒτσ€ςρφιoφ‘ώόβS[Νχπσρ„τ υυτχπ»L[QR–QP[y©Ϋσψχ…φ…υ„τ‚σςχιoφ‘ώόβ“όb™Ϋωυφυƒχ€ψχϊσΘOZQRŠQ€P†QP\x§Ϋτƒϋ…ω„ψ…χ φυττσψκoφ‘ώόβŽΩαςμοξξ‚ο‚πρξχΧWVRˆQPPQRSS†QP[t’Υν„σς„ρ„π„ο ξρυτσψλoφ‘ώόβ‘οώδηθθηθ„ιμιλrOUP…QPPRSPNMN‡Q[r Ρθν…μ„λ„κƒι θουτσψλoφ‘ώόβθςφφψφτψχχ…ψϋτ―JYORƒQ PRRNNV`hbR…QRb|°αχόό‚ϋόϋϊ„ω„ψƒχ υττσψλoφ‘ώόβ‘πρττσς€τƒυφυνlPTOR€QPQRNPauƒŠ‹Šc[SPQPUeΆγφ€ωχƒψχƒφ„υƒτ υττσψλoφ‘ώόβΡΔυτφυσ€φ€χψ‚χ$ϊυϊΖPUQPQQPSPNa|Š‹ˆ‡ƒŠsfdNSPQQPZjŒΔλψƒϊωϋ€ωψωψχφ€χ…φ€υτωμoφ‘7ώόβ‘HYΛϊτχτχυψοςχςψχψχψωϋττ©LUQPQSMUvŠŠ†…‡ˆ‡‹|nsPU€QSaqžΟιϋϋωόσψόυσψωϊϋωϊωχψχψχ„φ€υτωμoφ‘Xώόβ’q£ίφτυσφτχνισξρνρμξνσϊκߚMQSQMb„‹††ˆˆ‡‡†ŠiuQUQQPVauΫαμτμνιζξρβξκλξηςηνοδοχυφφ‡υτωμoφ‘,ώόβŽαιϊφωχφωχωςσξπςξμτςτσϋσδΫ¨VMOm‹ˆ…ˆˆ‡'†ˆƒerSURRSXj“Εθνφμρθιϊξιορξελιξιλδικϊψωω„ψ χυυτωμoφ‘*ώόβ‘ονπποοροςιοιδιηζονξμσηζήΩ¦js„‡ˆ„‡#ˆ„`oTUSPV\vŸκκρδηεβηζηζγδΰθβεείγαιςρ‚π οτφυτωμoφ‘ώόβθπθιιθθιι€κλκιθιλλ€μ€κεˎ‰†‡‡"ˆ„\u\QR_]n’Όίλξοξηηκθμομληθζεμθμμεκ‚λ‚κ ιρχυτωμoφ‘ώόβςψψωψχ‚ωϊϋ€ό ϋόϋόόύόόσ™‚ˆ†‡‡ˆ…]…sS€qs‘½δφώύωύ€ώωφψωύ€ύϋωϋύϋϋϊ…ω ψχφφυϊνoφ‘ώόβΓ²ςτφφτ‚φχ…ψωωψό‘‰†‰†‡"†ˆƒ]£¬₯„‘΄ΪπϊχϋχΨΉ’—“‘‘”›§·Μγτϊυυ€ψ…φυ€φυϊνoφ‘ώόβ’ώ@\Θότψυ‚χ€ωϊϊωϊωϊόχ³wŒ‹‰u„ˆ„‡&†ˆ‚`ΆΡΌ―»ΨξωψτΒ•~ƒ„……„ƒ€Š‘Ζκττψωψ„χφυϊνoφ‘ ώό⑁ζ€χυχχψψχσϊϊψφϊωϊϊϋϊϋΪΗΊ’pƒˆ„‡†ˆ‚_‚΄ΧίΡγπϊψ}„ЋЉˆ ‰Š‹Š‡€•Ζηξφ†χ€φυϊνoφ‘)ώόβŽηξχτχυτφφνμποροξλςμτοξωχσίΐžˆŒ†„‡†ˆ‚_‚·ΪμγηνξρΉ~†‹ˆ†……† …†‡‰Š„ƒΧηςυ‡φυϊνoφ‘+ώόβουψωψχϊψξωνπτξξςμπξυκϋτοηΝΎΎΠ΄‚І‚‡†ˆ‚aΎάκλνμπ°|Œ‡…†‡ˆ…‡ ˆ‡‡†…ˆˆƒ€Μζτ„ω χφφυϊνoφ‘ώόβιςοπρππρπε€ιηηζκ€ιθερριεάΪΩήޞ‰†‚‡ˆƒ]{ΉΩΰςασΑ}„†ˆ‡††‰…Ηβο‚ρ πσφφυϊνoφ‘ώόβσκιλκκλκβηλμκκ€λιμκμμξκικλικκژƒˆ†‡ ˆƒ\y±ΫμνπΥ‚Š…“‡†zŸΜγ‚λ κρχφυϊνoφ‘ώόβŒ³Ÿρωωψχ€ωϊϊϋόϋόϋόύόόώύύόύώϋτ‹†‚‡ ˆ„b€»θϋϋ’‚‰†‘‡ˆ†‰|ŠΓθχ‚ω χφφυϊνoφ‘ώόβ“ϋtΖξηκθλκλ€κληιμ€λθκ€μξβυ»І¦‡†Yc‘Ηγ€κ θπφυτωμoφ‘ώό⏱Θυχωχφ‚ωϊϊ€ωϊϊϋόϋϋύϋόύωψΤ…‰†₯‡†‰~Xt§Ϋςχ φυυτωμoφ‘ώόβςϋτυυτσυ†φ υφφχψψχωφυύϋΐ§‡ˆ…ŒrW|―ήπτ€υτωλnφ‘ ώόβνϊ€φυτφφχψχψψ€χψ€χ ψϊϊφϋߞ‰”‡ˆ‡ˆˆŒ‡ˆ†Šc]‡½εσ‚υ ττσψιoφ‘ώόβλϊσφφυτφφχψυςφψχψχψχ€ψχ肁‹†”‡†‡ ˆƒXg”Κλτυυ‚τσχιnφ‘'ώόβςωωτφτσφρπςμζλνιρθνφοσονΑ‹~‰‰…”‡†‰ˆ‰ˆ†Š‡ˆ…‹sTt£Υν…σρφθnφ‘ώόβŽ{nήϋχψυωχ€λμροθδμιϋννߜ†‹††ˆ’‡ˆ†ŠzXg‚‰†‰‡ ˆ†Šb\‚Άβςφ€υ τσςςπτηnφ‘ώόβ ”ωE}Λυξπξοσζβλ€δ αγδθπτ̌‚‹‡…ˆ”‡ˆ…dHWhˆ†‰‡ †Š}ReΑβμνμ οςροτζnφ‘ώόβŽΎρηκθθ‚ιθ κηηοΪ‡…Š…‡ˆ•‡ ˆ…‹uXq‰’…ˆ‡‡ ˆ…‹gPqœΛΰζζ€ε δλροξσεmφ‘ώόβρώυψψχχ‚ψ ωωϊϊωόχ©Œ„ˆš‡…i†»Α‡ˆˆ‡ˆ„Ua‡»γρτσ ςρονμργmφ‘ ώόβκχ€υττ†υφυφ󑆛‡ ˆ†Šv‚»άšƒ‰†„‡ˆ…‹eSošΜη‚ο€ξ μμλπβmφ‘ώόβμύςφφυτ„φ χφφωτύ|Œ…ˆ™‡ †‰x¨ή©€Š†ƒ‡ ˆ„ŒpOcƒ΅άν€ποοξνμλλκξαlφ‘ώόβŽλμωτχυσχ†φχχψμŸƒ‰œ‡†p‘ͺ€Š†‚‡ˆ…ŒuO]v‘Νζξοξξννμλκκιθμίlφ‘ώόβicΦψσυσŠυρά …†‡††—‡ˆƒd‚‚‰†€‡ ˆ‡…ŒtO[p–Αήκ€μ€λι€θ ηζλέlυ‘ώόβ ”ϊO‰ΤϋφχυŠψυιΠ€‰†‰ˆ•‡ˆ†‹uX„¬‰‡ˆˆ…ˆŒnP]q”½άκξξ€νμκιιηζζδιάόjφ‘ώόβŽΜΨσξροοπ‡ρνίΚͺ€ƒˆ–‡+†[Z†‘„ˆ†ˆˆ††‹ƒ`M\oΆΣβζζεεδγγββΰδζεδθΪϊiυ‘ώόβςώηιιθθ‚ικλλκλ κκθίΡ»Ÿ‰„†ˆ‘‡.ˆ…ŒjLiƒ‡ˆˆ‡††ŠŠvSN`s“΄ΞΫίίήέάάΫΫΪΪΩίδβαδΧυeω‘ώόβλφψψωχφƒψ‡ω ψςιΪΓ₯Ž…†ˆŽ‡ˆ…‹vMi…ˆ‡†…‡ŠŠ|`P[n„₯Εάθ€λιι€θηζεεβΰίέΰξR3όώόβοςυυτσ†υ†φτοζΧΏ‘‹…ˆŒ‡ˆ†Š|Pnˆ‡†‡‰‹‡xbSWhy’±Νήζηηζ€εδγβαΰΰ€ί έΩΨΠέ.UψώŽώόβŽβίωυχυτ€φχφχχ€φ†χ φτοζΣΆ”…‡†‰‡!ˆ†ˆ€Qo‹„‡‡†~p^TYgy§ΑΦαζηθζεεδγβαα€ΰήάΪΧΣΜΟ΅ •χώŽώόβY]ϊτφσχυψνεθσψφψχχψχω€ψ χψωτοοαɞ…ˆ†‰‡3ˆ„WXqˆ˜•…tdZct‚”§ΏΰζθηθεζεγδγΰβίίήΫΪΨΤΛΠΆΨO ΠϋώŽ/ώόβ“ό\”ΧψτυσφτψζξξεκδνγθξδμλγττντβγωγΖ—‚‰†‡‡1†‰XPez‘‘š†uz~ˆ›¬·ΏΣζΨΠΡΡάΞΣΦΙΝΜΖΣΛΓΦΧΣΞΘΜ­ƒ ?ϋ‘/ώόβŽΦίϊφωχφωχϋκσωήξυέολέλαιχυτλσγπύγσάΏ’…ˆ…‡5ˆ…ŒhN^~Ÿ½Α΅₯ͺ§²΄ΙΤΝΣΩμΤΩΣΦΝΣΓΘέΔΕΑΛΈΚΡΚΗΒ¨Τ›ωώ#ώόβ‘πμοποξροσγίαεγγΰκηίαδβΰλο€ί γυέΰίΨ«ƒ‰†„‡4†ˆ€M[m•·ΞΘΙΘΝΝΟΟΜΣΟΛβΟΣΞΟΎΒ»ΐΓΆΏΙ΄ΆΌΔ·³ͺί’ Uωώ ώόβις‚θ€ιθδζλζεκθικδθθδικζδιζμάακηԐ…ˆƒ‡3ˆ…ŒlOj»ΧγίγβάαίΰΫΩΫΤΨΨΤΟΞΜΖΘΌΆΓΐ½Ά―«£¨Άζ’+μώ’ώόβ‘ουχχφυψϊϊχωϊψψωψϊψωϊψψωϊψωψχϊϋφϋ€Š†‚‡4ˆ†Š`\ƒ΄ΰςυφσςτπονξμθηΰΩΥΠΜΚΗΖΔΎΈ»ΉΆ³³·½ΠΦα’ήόώ‘ώόβΨΝυσυσςττυυτυφƒυτ‚υτυφσφςϊΒŠ…„‡1†Zf“ΗηοροπονμλκθεδάβθβΰάΨΥΠΡΡΤΧΫαδιΪΡ§Φϊώ’ώόβ‘MZΝϊσφσ€υ‡φχ‚φψ‚φχως·~‹…ˆ‚‡ˆ‚Zo’ΥνσρρποξμλκθδβΨκώ„ύύωυρηβΠΛ΅ Εψώ“ώόβ“jŸέχτυσυυφυχφχφχφ€χψψφμψφψχψσπωˆ†ƒ‡0ˆƒ[w¦ΪορςρρπξμλιζδαΤζώφωχχφττσςξλθΰίΞ½ Όχώ”0ώόβŽήεχσυσςττζζογθθγδησχοξπεσθγδβιμραή󩁊†…‡.…WršΤορεΧγΩΩΤΨήΞΣΚΐΪψόϊωψψχφςομδβΤΝΐ#―χώ•/ώόβ‘οτχχφυχχζθβζδδμκκςϋυεηγτεεβψέισέσΙ€Š†…‡†ˆ`m’έσςΪρΤΨάήΨΦΤΒΝ·Συϋ€χφτρνκβΰΣΜΗ(¨χώ– ώόβιρ€οξνοογάίίβγηζζεμυίΰηάέΰΩΰίΰΪαΤ‰††‡.ˆ…ŒiiœΚγνΩΨΣΪΩΫΥΗΛ½ΛΈΟυϊφχφυρξλγαΣΝΘ*υύ— ώόβ‘ρθηθθεδκδζθθηιγζκθιιγθηΩγκζεδŽ…ˆ†…‡-ˆ†Š{fšΓΪζβΪΰίέΫΪΧΡΞΝ»ΥυψφφυρξλγαΣΞΛ+‹φώ˜ώόβΙΊυφχφυχχψψχωψχψψχ€ψ ϊωψχϊωχώ§Š…ˆ‡‡*†Šy‘ΚθρςςξξμκθζδήΫΖέτψφυρξλγαΣΟΜ+‹χώ™ώόβ’B[Θϊςτρ€τστσˆτ στυτφςύ½}‹…ˆŠ‡'†‚­ΧινλλιηζδβήΨΥΑΫτχτρξλγβΜ(‹φώšώόβ’zͺγφυτσ€υφφ€υτ„υ φφυυφτϊ冉†‹‡'†ˆ‚ΑίλμκθθεγαΰΨΧΔάσφρξκββΡΤΜ%‹φώ›,ώόβŽδλχσυτσυυχτκπφυχυχςςχυφφπςφχς΅~Š…ˆ‹‡ ˆ„x’ΠεμκθΪ€γέΫΙαύςςνλβγΠΧΛ#‹φώœ+ώόβ‘νώρσσςρττιΰήληαεγβκθΰλδγλεΰβές§ІŒ‡ˆ„_|·ΛΧήΟΘΦΚΥάΧΕ›ΫύξοκβγΟΩΗ€šχώ+ώόβηρυφφυσψςευγβετάθνίηβθεγηήκζημ©‹…Œ‡#ˆƒ[z—ΖΤΛηΠΕΟΜίΨΘ­ίϊλμβγΞέΒ¨φώž ώόβς€ξνμξνίίΫαίαΧζθΫγέΪβΨήέηεδη¦ІŒ‡"ˆ„Ui›½ΡΡΞΗΙΖΝΝΎ¬λσθγγΞΰΌ¨υύŸ ώό⍹₯β€ηζηθζαζηΪΡήιηηθβθεγθηθιεν£Š†‡ …Vk£ΕΦάΥΦΞΠΜΘΑ±κοΰεΜγ΄ ¨φύ +ώόβ“ό=_Ιότχτφφχψφχσςψψχψχωχωωχψχωυύ§Іˆ‡`t©ΧθθιεγγίΪΤΚΑςδγΝε ­φώ‘ώόβ‘гητσςρ€σςσστυσσ€τστσσ€τφρϊ©‚‹…ކ_o¦ΡβεααΰέΫΥΡΒΕοαΝη₯€ ½χώ’ώόβιπφσυσς„τσ‚τυυχ€φυφςό¦{ЇŒŠ‰Š`o¦ΡδεδβΰήΪΤΡ½ΞρΘκš ½φώ£,ώόβμύςττσςττφτφυυφτυυτυττζυκπχψτϋ΄‘€€}{ƒ}€|}|}bo‘γζβΪαέΪΤΜΉαΥζ’Ηψώ€WώόβηςςσσςρσσααζμμγήζθάνσυΰκααΰθήηΥʚk`^`^Z^`]ZYX[b^WZX_s—ΘΚάβΡΙΑΙ½²·Ψι„%Ψωώ₯ ώόβς€φGυσχσβοΪνμΩοίίυοχχπάγάβίΰδί¬ ’•Ї‰”ƒ‹ŠŒˆ“Œ‡„Ž’³ΑΞεΘΒΩ»Έ«Ώυw*εωώ¦ ώό⍦”η€ξEμολΰιΫέΩΪκίάέβινοΡδέΪβΪΧΩΦΕΈ·΅³―Ά΄±­»Ή»΄Β²¬¨°Ί²ΏΘΘΤΫΖ»ΌΉ·­τr*εϊώ§2ώόβ”ω;gΒλδηεηηζζηγγηζηζαζεηθζθζαηαζεβγΪΫίΨάήέ؁άΪΫΩΤ€ΦΥΥΧΡΦΤΟΈΑΒ©θm+εϋώ¨ώόβ˜»μσσςς‚υφφυχυφ‚υχυχυυφυφυτφττυυσσςρρ€ονμκθηζζβΰήΪΠΐγeAςόόώ©ώόβοψφτυττυυχφχφ„χφχφχφχψφχχφτυ€τσσρποξμκιηδγήΦΙΝΥNBφόόώͺώόβŒίνηιιθθ€ικκλμλμλμ‚λμλμλλμλμμλμλλικιθθ€ηεδγβίήέάΪΧΦάεΉ/Bφϋύώ« ώόα”χώ―ώόϊχνΛo Eυϋύώ ύζ?ymtq€rq›rˆqpoommeC dόϊύώώχ· ‹ωώώ±ύθ ‰•Š  0ΔχΆύΦEΈH§ϊωΈύύέ³―š’¬‘ ‘–ΘκόϊώΈϋϊΊϊψώ»όψψ³χψψϊύ€ώΊώ»ώώ­t8mk@     r·±·΅ΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆΆ΅·°Άa ³ωώώω™ $²υόωϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊωύυœ %Ήϊώώω’&Έωύώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώύω‘&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ’&Έϊώώϊ‘&Έϊώώωž &Έϊώώϊ &Έϊώόl&Έϊώόή=&Έϊώώω‡&Έϊώώψ·2&ΈϊώώϊΛ@&ΈϊώώϊΡE! &ΈϊώώϋΨI" &ΈϊώώόαQ#&Έϊώώόι[#&Έϊώώύοd%&Έϊώώύώςk'&Έϊώώύώτq(&Έϊώώώύχv)&Έϊώώώύχx+&Έϊώώύύχy+&Έϊώώύώφy,&Έϊώώύώτv,&Έϊώώόώςq+&Έϊώώόοm*&Έϊώώόμh)&Έϊώώϋθa(&Έϊώώϋγ\'&ΈϊώώϊάU&&ΈϊώώϊΧP%&ΈϊώώϊΡL%&ΈϊώώϊΜG%&ΈϊώώϊΕD% &ΈϊώώϊΎA$ &ΈϊώώϊΈ># &Έϊώώώϊ±;# &Έϊώώϊͺ8" &Έωύώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώώύϊ’5!&Ήϊώώϋώό’1%΄υόωϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊϊόώιw,Άωώς°R& l¨§­¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬«§Œ[0 #-//////////////////////////////////////////////////////.*#  ic08Σ~‰PNG  IHDR\r¨f$iCCPICC Profile8…UίoΫT>‰oR€? XG‡ŠΕ―US[Ή­ΖI“₯νJ₯ιΨ*$δ:7‰©ΫιΆͺO{7ό@ΩH§kk?μ<Κ»ψΞνΎkktόqσέ‹mΗ6°nΖΆΒψΨ―±-όmR;`zŠ–‘ΚπvΒ x#=\Σ% λoΰYΠΪRΪ±£₯κωΠ#&Α?Θ>ΜΉαΠͺώ’ώ©n¨_¨Τί;j„;¦$}*}+ύ(}'}/ύLŠtYΊ"ύ$]•Ύ‘.9»ο½Ÿ%Ψ{―_a݊]hΥkŸ5'SNΚ{δε”όΌό²<°Ή_“§δ½πμ φΝ ύ½t ³jM΅{-ρ4%ΧΖTΕ„«tY۟“¦R6ΘΖΨτ#§v\œε–Šx:žŠ'H‰ο‹OΔΗβ3·žΌψ^ψ&°¦υώ“0::ΰm,L%Θ3β:qVEτ t›ΠΝ]~ί’I«vΦ6ΚWΩ―ͺ―) |ΚΈ2]ΥG‡Ν4Οε(6wΈ½Β‹£$Ύƒ"ŽθAήϋΎEvέ mξ[D‡Β;λVh[¨}νυΏΪ†πN|ζ3’‹υΊ½βη£Hδ‘S:°ίϋιKβέt·Ρx€χUΟ'D;77;_"Ρeσ?Yqxl+@IDATxμ½ilΙUηι‘Ή/o―½T›ͺ$$F1bX„€ΐ3–²Ά6ΐ 0L#γ|kc˜6Γl>Ω˜ fσaΔΜֈa`  TBKKhA*©φυΥΫ_Ύά·Θ̘̈οψ=7o¬™/—xUι™7ξ½~ݏ»?ηψργ[V«…w‚ Ό51ΠχΦ,φI©O0p‚0p"Nθΰoa œ€·pεŸύ'ΰ„N0πΖΐ‰x WώIΡO0ο%œŒHτRmœδε(0ΛεŽ"™ΆiδŽ›ι<ύγFD[ |8Αΐ!cΰ8yΰX5 ξŒΟs΅Z ΫΫΫΑrΘx?‚cΓ@___ΰκοο―γ燣ΚΨ±iΞό›››Ζτ)"Žͺπ'ιœ`ΰΈ1°΅΅*•JΘησv9_UΎŽMΠSx ŽΤ›žž—/_―ΎϊjXYY1Ι2ΎϊΥ―ζ²οG…˜“tN0p»€~iα766Β½χήήρŽwΤ\Λ=sζLxπΑΓύχίFGGΰ‡B‘p€ α±˜Ÿ ζϋΏϋπ'ς'ΉΟ~φ³α₯KΉ€ €eδdŽςνRΰIό^Ε@N‚‘†pxμ±ΗjόΰΓΟύάΟΥήυw4βb±xdω>rΰ*ΞΥ«WΓoόΖoδ>ρ‰Oδ€I ΘυI €˜Ύ€tΌζΡ#«‚“„ή‚ΤPύ·Υκo«ό΅αααšψ‘φ;Ώσ;5·^ŽTΠΊΓά333αG~δGrO?ύtT*υΛΏOΘθRϊUh.ζ'ΈπϋQΰγ$ &\«εΎΕ₯Fo[ Ώ%ΎΨVWaϋgφgkπPsMΐΜΓΚΤ‘Žxη£ύ¨1ΘΘHŸϊχδ‘(D λΤsAWVœ€ΓͺύΈG?e~=WΔθ«² ¬ρ,~¨όαώa +π›Ώω›G"]p †ρC >ύιO‡ρ§―O«_δPαGA`ΟɝwŸ©x"„ŒwΗbΐ[~ @Λ_Υ΅‘kYύί Ρͺ4MρEUΖΑνϊ§ͺέsΟ=ϊ,Uψ' ™ΰΰƍXEMυGν—ΥsDR0‘|δίΰψΎΕΕΕ ’-¨ΰ΄""ΦԍκSΠ’.zTc)ΐ‰;Αΐρ`@ŒΎ-;WN<°6>>^ό½ίϋ½?ϊάη>χχ2ό ‹*Ίχ]Ήr₯677Wcδ@”ϋΒΎPΗ?ΞOŠv`<{$€·ώψΘΈ~Σ!€Ά»_…aΜc¨\.Σv3 ²ΊΊΪ§8[’Φ–K΄nΤΡd-ΘΝm…ZQAGυ‚‚uΐmD%ϋθkρžωmφΙ|<¨Ηιθ਎ŽΒ5₯r@ι6ΑέOaΊΘ L/­·_ιUΔτEΡ9τγ—uaϋΪ‚ΑςΙ'Γχ|ΟχΨ YΊΟ‡αjCN]“—d³/PΎ ΐδ‘$€Δ2Šρϋsω|_₯Z5²ξ§πΘ%6"Cϊr‚—ο5δ χΚqJe―Q”J½Λ0 Γς{}ΐΫxΛ€ΡJΠd!xΪYΰzΆlπ«{ΝΦWφΉ.Πώ^šΏ˜Iδ4υ/IΚ†ΎαCC;nxfΏ?G"Έ#ωώ§τŸΒWΎς•pαΒ…πΓ?όΓα'ς'γΚ©V¨ nŒίκ³ω)Μ.!ΪFυψ܁qΫp’²άΜΟmΑΝΐιεΗ¦2 Ζ(­p‚PΨƒ`pΨvwΈBF'Fμ„+‡C˜ύΐ¨‹ίΎ³ I^R^p~IόεζΨ‘ο¨!@ύ~ ΞˆΏψ‹ΏωWe (Ο?˜6Μ"‘Ν‘Fpaa;WUυp9ύNα-^-RόqΏŒWέ£}ΟΔw1]¨ΫΑ!/v%q<}Ώw κΝΞΛοχ΄|Ž/ξϋpΟξ‚at° ,γΙω»ΓΘ֟‡ιζn4Ϋ>νl2έ€;°0Gͺ΄ΚuΚΜδ\Γ?ώφ·‡»ξΊ+œ:u*άwί}6κΜΆ².}71|Iΰω7Ώσ5ϋάκ½]%7ΖKRj}KZλΝΎ{‚έ½ή'ƒΛϊόΦΎUΫSBΩj#b.Ό,~wΘ‰ΝΘ_χrOiCώλςδ‰|βο]½h'δΟγ¦ιγyΜξψ5€€\έ‘0όΧο}o ΄ώwK\Πuχέw‡“ƒ„0›βO3ώιBIˆoΏ°2q=˜ΗηήΡ¦χ«cΰ|9ό]‚Χφ|Ά»Χ‡>Ό·vιγΏη8π{WQΟάwIΟα6ε*›.m‚γρ»ˆλAΖnyφπ‡}?v ΐ₯Ώ¬­…οώο7&Ÿ_X>ψ`xθ‘‡ΒˆF˜P”£Β³’ bυ‚h·ΨkA@Z<ίΫDι^6ώ.0³A{ξΉ]ή³uΧ&ӍΈΪ΅:=­=ΐn‚ΉGžGΰμG#πψmPpdήΗ.Z•-ΰ‡θ‡ΒZΉl†?ΦMkXPBShk¬dωΩ4!i ΅kΔz…7d «ψΔm? +Xuφ#ϋΞxn…·Ζ:m(I+MŒλaλ˜ΰΆ…ιωλΧ“δξp,_{Œ›…s\Ο='ΌΔ.@MBν―θb±NυwdS ”"οU± *3ρ›²1y,k¦₯ΩWτ ρ›₯1`›wΒR?ΐΩΤήwλκΆΓΰ៹aοΨq²Nq-M'Œξ†—$Œω'œΊέˆ`ιXΤ,žέeύρkx'ύ4€™λ0:ά)•pρ:€<΄O–ΟCƒ~›€!€:iœT ™N«κ 3«yΖωݞυ’xxA0­ ά”ρδX„δΔ±…6’w'4ΰX<ωC,y'OώNήΉ²Žχ*†Ω$,Άφ³ƒ9W–—›Βƒ %Ž>ξΤ‘€’ΰΡΥCXgσG<ΎSrLΈ₯ΕE8ŽϋlΎK–ψRNΏ²wyNaμ#. Φφw—¬ΨηήλaΛδ žu―c^jΗκΎ‰©6”T™}ΣO\Lh•WςUO;bυ9ΧΫ“γΓ°C+ 2ΨΥΥ@ŠπXΙHΧΔόžΌY>u‡havΒΰoĜψχ‹x[α!-ŽώΒΦhš ε/•DψqΫθB‘΄bRωV±-›ˆΎ§ΟJ“uΪVQ-)eΛ…uεyCpΙ[΅Z‰»,λ £,”—΄(Ÿφ’‹ψ<„ΐ²fα;‹·(?φ˜4’ςSV­Ϊ΄2σΜ°-pΑ2#pa9LΒήΘ».β¬)?h 8ß#>ψ#=ς³S΅mα°ŠΚ7Z Ϊ ωV+ηΎΰ6uVπ»q) βeγvί %d#]Ζι&_¦Ž§ θmΑ’ nQ Uς†˜ΗJ‰ΆΞ>&κυš0?θ•hρβ†hhUΈ`ϊ’.ƒcUDŒcζ!£0ΜJ gCίi₯ nˆΥ—°%…P‰ν*-Dν­°J “ΣjfΧΞΪzΔ„Η–žΙ~Ή\ΏςT ›λe΅šλa}M†QMyT^a°ώ|_Π6RΦ’V*›b΅δΊo―…΅ε•I >ƒKP Ϊo˜mTq˜qIYΈœ`Pς­* '0§3sIy.*]Κγ!`(λδΤ”1!ψΰ‚™ c‚SwΔγ"Ώΐ·²+m` 4¦‡΄)Χδδ€α“gΊΠ~cγc&D¨bp?¨«Ι8μ fξM4ΐ7hŒ«KWcρOά(—cγΦe’G¬η4ˆ’ƒNkοtQ΅ψQΩu.©Ώ\Ώ4•Δ™5bώδ“ǟ:³KΤΓ7m1W‘d `41–hKα ›J‹B«μΊX[–ο/†>1ύ&Γ§ƒ}‘¨8Ae,€lˆΩ΅YBQšρ Εε…΄mΫeΑƒ Λ0 DΎ\}––R8ς cΞΟΟ ‡~ ΏΆΆjε/}ͺκΕ8Wω­{€ΠΣ^Θpƒ₯άάΑš #@ΰγU΄ݝςΒ7‚ˆΌΛΫκ$&Ζ/nvξ«μμ8*“Š3ηwΉ̟œ…΅§wŒgqΑ‡h¦ fΈžΒ@-ŸŸ·ύ!¬χ23ΠZ,ˆUοΨΆ(j)‘~‚ΊΗτ¬u5`ΙΔΗκKZWνQD«ΌmkΪ•YΫ‹d’FΐψRf‡V‹ΓΔΔbD˜ ·-ͺ.SwυΈΌ£Η“#n=“.aΣΧϋαρ9¦Ε30KbΤΪV%¬­ͺߜ³›_A‡JάΊ–§/‡₯υΕ°:s%άά\ ΥυU1ωŠΚš”¦.”†BaxRφ‘Π74Ά.<'/„ -“iΏU±T¨l”Γφ€ͺ½/6Υ½Θ>%p₯MΔΌŠ1ΕΠ0>εΘo+–π3R>7p4BχA‰/./YXeβo0¦3-šΑ’ΊCŠ3 ψ«kεXdΎ&νAy‰Έ#Ύ43₯WΥ7„1BaP8Ÿ½!θκ€o’šΖžAΏΣ…gΤrΫώ')N&@β“ΒΙ|jzΣ›Ÿ~υOwΓΦ„IAΜ£χθΰ’V‚S‚ώ‡πΒ΅λΧm πw=ύtψχΏψ‹aR* c™£40WΤ{ ΅ΨΊ ΓΒ~/QΛc)?jLD5€VL-£Ψω ϊAuέ”M_~@­i­¦ώ|u[­“ZfνT ½JΰΆΠWγΠ*N­dQ¨Ψ­J^ž7νΐς)βfΓ’’˜nCΆ ˆ]$­+'ΆTi §αρ©PΥή•ςBXΏρtXΊς|¨Ξ_ ε™«j½W•Dμ'[`Zε?¦M²Κ„€_Β|•ΰψъ#SΪoιTΊλρ0v;C΅0rΒCφjΨΪX £“§BycέΚWΘ—¬n]αĐπ¦T,ΖΦΩm[εͺl e fυύ«$$MΫώ„‹²²„@Knέ!εͺ V~@p,Η}±υWŸΖpE½…·- J41Β!tθ2hŸH•' ƒ α‘€ξš€ηTV4‡5u]θ~‘+<γFύtα’1dW (‰9+έΊ.³Υ-Έ}‡;vΰΜμ€VεψΨΗΒΕ‹Γϋί~λBD/Ότr8{Χƒf€9!Dk­ΕΕΥ΅θͺΚΖJΤA μbl3c“ Π?κ0ώτΡqS^-)F3έ΄ Qρ’ΰ‘Z-¦§₯‘…+–Ν›–΄°j0P©ϋσj­I@ˆΦmβl¬oHuWΏψJpx4τ©΅^_ž[ίώr·žΣ―†Κβ-Α­Šq€ζͺ+ς:7±˜l˜qB­bx'Z`;lΘ?\MΖΒυ₯ΩP[ΈΦ―<Ύυ·!?ywΈvκρ°uκQ1©0½|CZΪƒΚOΏ{{{V`lO‘IΪ†Τπ™₯h‹1Τκ‡l0S³zuFe‘DυΆ­τ0Τ e3N/¬[χa[yE”Υκo\]ΰΟ.ΟXλΞ·ι}SΧ€ψs+Š›U³ Vdό\—nΜ[ιz,hXΊΥκ’΄Ε3\ ˜."$Ψq$YΖ -έύΟ`uήΡ\ΜΣtυAi$xEφt;G?φ―Η.1  ьΰ˜ΟJ@.ΞO›’h¨€Ύ‘Zϊ~†_~T‚ΒΊR|²5,‘/;•fkADjΌί`#]Pηq§r>rƒ ΘΨ=p|ς ©Ÿv9―§΄ΰ$hΥ₯Uδ$dςκΧ―Ο_³ίz*¬_όjKΧLŒ’’ϊG’ΡS€Lυ–Ω¦›Cbρ'IR‹‚Πā}χœθtI ˜V •Κτ+!ά|9lž λwgθΫG§€l¨%Ξ‡Ι‰1|¦ιD!7’>π£`p02ΎθWωΰ›)Ι™< &FA―•ΟŽϊΪŒF €}8άaβ%q ·ΒΣΠΰ€bͺόJw@ZvΒ[rlkLw9ϊ ζ’»W\β›ήb¨―?}΅h# mDΩ–JϋΨΕ€™²Υ‡μΝ·γ Ά½†λ_ύΰ†W_{-p€"K‚ΩωΎ{ο C΄ΎΒ#­‡ΝϋQkŸΣf ΉšΤcMͺUq6‚Q„pŒkV•e΄kΘ‘n,\ς#fj/‘’˜σΗgΗ72€”Ξ;“±mΣαρΣasu!ά|ϊοΒβӟU΅Ξω>©/₯EQ`ZΡͺ _I jZuϋfΔ™ΖfΰYΊ*7H!ήτσŠΣ΅ˆόΡmΘdΤK±²r―}:Τζž }OόH~ΰ½Ϊ˜±/γŠ2VΚ&Πί_0ŽΐSrΦsΜQFχL<’μλmηKΜ§e6ρMκ±.nφ…°ŠO9t₯Δ\fγeŸ-B‡Έ|7ϋ‰ΒΔ*PN„7«˜ρΘg|KδθŽ]8"¬₯SωΛzzΟ»ίώϋ_ύΥpνΪ΅Θό: ΛpYj‘1θ£Β‘?]RΒτ b’&`ƒΏΝ`:% žwœ}Ϊy­κ/`-α€ρE΄κJlkX¦—Ώώ©pυKΚ³WCΏΤϊΎΒ¨υek²­qΓ‘ι#ύ¨}o €ΖwΛ—#3›Ιδ9Ά¬B–Zz˞ςϊ΅ΒrώfXϋόζ_ώJzηF&ΟJSa.CœήΝΪΎνΚH™lα³i[^¬ΏςπΪ"§xʁλΩp’xσ­ΌZxΛ·…kΐe6D[d‡xmΠ(erA¦ωn)›π1=»H˝ b+«ΟωΔγΫ¦ :κ%W^ͺΰx5Œ«}2Υd¬©Υ² 2υκP ™GK_½^RμW>f>4όvEsFΗΓΊZϊWŸ£½ψeΰ5¬66eF£ΪΆΖοI†TglZםgΟhLΖύ3‰vρ˜ΐH§£™GJ΅ςΨj7Ÿ•e~.lΌηί†‘q Θ¨'εΜ8jφυΥλ5&·T.4`¦iγΪΙD°ψaλ=λΕ³£]ώ)%ρΜLB9ΘΊΐ 0,(?^Θ$n&NΆ˜€l ή=πΨ+w@‚‡‘Οf½9±&„ώ ΉYμ¨q">:~#φ“@†ψœΈΈlτfΜWDβΥ½2‘ ΔΏΎπQ ½%UΎ82ζ^ωZxνo·°)c_~hΜΤς­M ₯ΌYKOήŐΞΨνξ€aι^ΟδΕήωΠΑy8Ο;AMθ€ŒNΜ₯‰¬L‡ςΏόiX}όίh–ž& UΖm¨―΄­ Oi1m€ΊPό¨‰%ΉΥ#Ÿ$φδΪ–ΓλΟΰ·ε^~Wͺ–έ3^I^τ%ΝgβΥ(ωΠΏEά4dσƒηa§΅RΚcηψ±Φ^–w^Guθs ƒT3ιnNB7 ».nwow/ρs²¦Ϋ$#η_ύΚ'Β₯Οό_jυ‹ΖόΫ ¦,Š‘`τFΖob~ςHΈymεΧ"XΧΒ§°Qm5!΄©E<,,_ +/}:άxΰ‡4:°!KϋT3m!BF0Ρ§Ι5ΰ¬‰Ρš"Τ{dρΫT.`gαgςSeη x]'uΐiιΗϊŸζgq”ΖχΌw™n}.χm‡Λ7=A§uahΕZ=;"λ€x­€TV2Πl˜Ίeά:@™―¨ŒWΧΚZƒί6σ†ΗΒ•/ό?αS Ι9‹—qϘ_Σ{Νΐ§ΌšΘάI6™ηLvτΡ’ςΠ§| §Šζ" /Ύ¦/‡ηΏΓ†΅šs<24Κ3]΅¨΄ΙR#.½nΪΟz{Z^ΕΩoφ¬<˜fp έ$ΠE\‚‘Ÿ4/^.γΦΕ'nΒ‹8GεzRXα…,nΦnGz;¬$ہYUejΛ ©]΄ΤΏό=1>ρE0–ϊό…α‰pυ‹jΜ?0zZ~λJŠώ3ΜUύ”ΡΟωI™2ΝάΡ<ΨX½’Κ1δ(ΫΕδΒ·Γ%ΝJΜmߍ―δkfZ³Ζβa~ΖοΉ§ΜΡ)«ΰΘ]—Μγ1RψΐΘΖu˜Y?O£αξυΩ$Ίˆ ¨]σ^γ+ρ­.ΌΣ{Ο ¦Ϊ 2UP–Ašπf™a§!,w^Yώήφξ” °eΗ3­Ό/Q„|ΣψJkΏZώβΠD˜}ώ‹αgPύSjT΅‚Oί¨|7μyyΈγœιύέ<α'ζF=*qIQ§W/>n憀`1χ"Ξn΄yώͺκǘQ8`θ–I<Ú΅ ΓΏόΛcΒ‚2§x³Β§%Ν~ίδ,ζ3-œEIq’QœPΔ Ε6°^­«Χo*<ξγΙν2…Lιάu‘Χ1‡ψΰψ8Δ$φZ‚zΙ*1[ fύPώΛΐ2*γ]Τfςžzg‚ƒ©’ 0ΏTbJD‰vlΔ‘‘R™σΏUΈΒ ˜Hόt—‡^dQΧ¬½Υι‹α΅Ώϋί5yO3γd\£νiy>²w`ψ; Ϋ5­)9ςΚ΄i-7 §Άn…άΒΕpνΦBXΤ’Ÿ₯₯%cFf2cΠgPR_ΜΠÁ[Κ„PΰΩ/ΚȌJξuŽ:I.[¨υ@Έu₯Ch`gA›Δ²Δ9u€τcuιšB’‡.]]HΟβϊŽ.£j°žΣ¨\€?Kf©xlηΣ… #F©T….*AοiβΠΔ „₯³—mV^:-X„6,?Β°Δ•4 `ZΦ@pδpΐˆ`‚Xq΄„LC­Θͺ_Ρ°ΪΕό?΅Xg%τŒΨ i&‡°γ4f1ŠžυΏ“oƒΨπ£οIQpΔΑ₯卯+y¬ϋζαύ[φnι{|݁‰Υ…™9ΝΊ<΅ρFxnZσjZ3‘QL…¦.X§>XΣΟ<™yϋh ΰΪ_Υί2σω…+²Nγου N.pΟtpΦX5κ«ρ']i§qΝ'σγB€‚qup.φ£ 7\šˆΫ%½lxo@Žρ§g€· 0ۈˆγ_ΎρπΙO~μψ@xδα‡Θ . kOPšLZ­ΔyψΜΝg‘5"cZ.KOYτ‚zιŒΡ"xX‰±Aΐ,B e’D<βC„0κκZΨ`_q8Μ}ϋΓκΕ§mω.Ά3ŠpqδΩΛhΟζ.~ίyN>Ε›(Ε‰ϊ’Ψ8ΏΗ·ψ›υσ°~χpΌγκόfβO‚,`Ϊάξ§ϋWΓΔφbXX cX9¦Ε8LΡ†‘Α°ΐMΔΧF8sϊ΄­Ϊ»53JΒ9ͺ|Q‘XΟΟ†# x >ρC “:B X($£$¬!(MMΪεAΥιPW²ž‰bν8G†xηKΣS βv@uqχ―)Ηδqμβ¬O©;“OžώΦ·Β/ς/[ |—ΞΌyσfψε|Δ PP9½ΡΎ­π xα¦ηͺ&A`,ςaρΈ—M1LΠΌ| Φz)­αq΄0\:Β] ΚFt‘°θΕ¦φ*!L`Ν6—¦ΓΜΧ>‘n€¦+‹8™K[ψ˜S.,‘]~ AŠƒσβΕ·ΞΏ]n[ ––~Έ3Ε}ͺz3ΌΈ4Φ'GΒάܜ„$+&+ͺ«A΅Φ#ΦBS'ΰΑ8 yό䁡L 14ΧSPΏ09ε’ΞΉΑŒ 0Ζ–?x2§” κ‚π,Ζ—ήν­… 1„Pš/ žήά7Υψβq-TϋΈT?6²c/Iš―χŽ]’…'3ψιΞFσ7cκ{ίσ[ΔΖ W^ΣA‘wΕ5βjŒ‘T/F$e©ψ΄B>stß=hΝY3Ž[WkΞΚ=_£/ͺ’*ΟN6Rω‰•\ ­iWΛC\ZΌ>΅8›Š»²²j+ΞH Ο :19}’Ζϋ―ωΟΓΖβ΄Mό©nJUΕπg„ύν΄ώ–‘½ό$Τ™άΊŠYG»]Ε¨DZ` - ͺc—Οjuί³σ³αϊt1œ=M_|$LτfαΑJέmΩz~αLx«Ÿΐ―ύΞΈƒΣ‚Fk‡Ο8ƒ‘‘Zυ!­ω―h₯$0‘‹XqΏμ0UαQ7Υv“hkp°δ'ΦΆϋ$˜ΓΣΦ.ΤυP~·`φβOΒ'uιαοf·π(·[ΐρύψ@CαPωP9ΜWή{Ο½αž{.ˆ€vbŠš%*„Ί‘£ΊhΞ‹ςΧΏQŸn¬oΧJR«x0βV«E ΔRΩΈcΝΆT|uok+ρ‡ˆ«Ϋκ&h];KxΡ ³!`Ψ ¨_Άγ’G»-ΥvcφrXxασ‘Ώ4¬– Γ_T]SΖl#,'"^œXτΨθFNGάΒyςν`yΊώd+bΈαόV8›_ 3«εpzͺ—ʜŠ}ŒώΌΒ‚―ŠφC(©εΗ±ΌxHΪBΏζh¬•ΧTy a F³’ΤγRχ——¬uίΦG΄«!­ˆ\Wx`4Mύ„q[y·¬ΪF^i΅€š›€ƒ£ΜVWΙ= Ί ςVΠPš¦WΪ.ρRψΗτΠ3#ƒΟ‡υΏW΅ˆ}βξΡB ‡~[¨iαΚ·_ΎfΔTΣR@Γ―°]S#\\YˆΘͺ,t‹λ‚Rtš€ͺ°S^„LλC+α@„­?u•Ο«?―ˆ–γ‹”Pw‰Ο¦…βš©¬•Š4υσKγgBε™O†Νυ5ΘάŸήKKfCδβŒΤeŸΟμχvΟ?ϋέύοΖοώέίΉ[62yρo„uoό&ϋVΓσσK¦Φ—e˜«Ύ&-ΰt8wξ|˜_Υ(Β…›J₯ͺυόΒ—ά&v”EI`Uύψ+ΧηMPcWYΩ”₯V?2―ΎK@\^„^›f€]Π~2°.­U%Μ΅˜θctTvΑFˆδ₯‘΅”€ΌΣMKνΖ)JŠ‹Σ:" ς¬ν€ΡZڏό<ιΉΞY†όκνΛ± G”ίiΠϊ_׎@W\±%Α, ž[ξ5ΪπΓZp$²PvͺP\Χ0ΤΛͺvnτ©Pε3Δ`Ύ@1GΪ^O;€βkέi₯¦…£ΚI‹@dl|su1\yνkφ“Υ_ΒΒΊN1,ΚNʞFL΅G~UΰNωΒ{Ÿ”tETΩP&δǞγͺφ7ΦN½ΨGΨ: MΛλR8ή1κ -Ξͺ6ςΤι•™0&<ΑξHρέ™G₯Žh«4αy4 ݌HΒ'‘HΫ!r£³ϊŠžφ΅U˜Ζ8mήcΤi$αIŠώDY°Lβm`φ’χ± €FtaθA°ΘΉ³g“ΦΊΞMiχQͺWj€-V jRQmk°1£ΦΨ  ΒXkœΕ8ρxw@#\βηΜ ‘€O“c 7NχՌ?©©WΎς₯+Οk>Y΅Yΰ£ό㜠ž€g’k‚yœ^ήvy 4˜U†σjε†d‘βKymΨ!;\ŒΑ±Α01>b#-¨ψΆ5y ,JxΘxΘΦβΰdB»1ΜηΖVJ·?:=X!bέψσπPΤC‹Μ§`H™ξβZ† ή.qiω±Qx–,omβ@Y-ΣΩ%o‡ρωΨ@#" „*:έ˜žVcγ{YΌŸ[Χ7|6DΦΠjΒΦΤΧχω’±Ψ|Ώ$ž}IήcJ©…!/j‘*² \ζ‹:’Μ‡&‘ΤΞϊ+΅”;ο‡ΝSϋ5'`(”Γ­΅u3†.-―„Q]Γ(h‚c+ΫƒE&*«‘TΒbD« ՚ϋ†žUΩcΪ9j£ΩeκΘΑλ§uΘfίΔΗ‰¨mΛrύW D΅uΖ,,ΓΔΛ:j#^cz9υπρνΨ@SΩ… ¦gώ9ΌΣβCQά’ΗˆmY™sύb80Ο~T­°1Ώ^3.BΛx΄zlQAuρȟˆƒ³ώ6f.ΩΖψ‘3g~@Ϋs«4ξ0ΏX~΅ή…ΝπZrΆ[{ΫjAυωE°"¬­ЈCΥ§±―Υ c°J{ׁϒH ±{ 6Aφš‚™Πκ(ΒςD]γvI8 ά?½'€8#ωπ xƒΘpφΛ†6ŒΞπΎΤ°ψQ”A΄WWŒ­p­œm&Αˆ›ΖΣ·8ΉG³ά4ξ½pρ[ڞ{Ωvήέj9m"t<οΔwΒΰωΞufωΓύš©ρz†SΧ΅‘(¨6ugŸα½νΒΞΎύνΛꡨ ΈnŒ“β½ρCφ}Ώ0v‰G­Σ―§­lVόΉ£p:σΐΗ|ο,Š9sΩώ4ŒθŒlΩςέΩζΪj’:γg«55'ίΛ>”" ’¦•Χώ‹ŒŠph]4.ŸΒΥdΗD₯jƒw žΉ:Ί.`΄ŒΏK<β΄L›x 4Φ ~=,–‘VρŽΪ―)ŸGvιq*%ˆ£΅mYY_ -Β&ΕI·“IΥ+&γΕcλΈ¨ψκΗj‡s¬Ν]΅>π#‚3ΏkώήϊŽ{ιŠμΩoœΘΰ₯aR˜[MUέ†VέΦAxj‚«5υΑ]RΗώΪκήŒVΏΆρΫΤ}TΫΈ·#² σsο IHΤ~ΤK›-&γ *f+‹―γf-ΏΏΕ{ۊΛkCmγ*MΖIυYΘδ¦ύ£§έ>Dϋ/†Lšέ ’˜ίφpϊKΟ_ Θ=?ͺ>όΌѐƒAίφΠCΆςΜVε‰@ԍxJ* oSν[1iέ¦wB£3«وΗzf"dΎ >«α―œχμΣQ_[KΪ7OΓ‚œζΛ·}Qb&…^~DΫŽωγΩ4ξI—ΐV^Ϊj8ν£€QΆ+G%Ζ:1 o?œlι VW §Ίeή4‚ΚOžc<ž©zŸm―m Ή&;–ΕGοzFx%0©„ύ~ι—~Ιvβ|ψI- ’Υυ0)š„ϋœΦεηJZΪΛ±`μ°«PlUΒ~ΠMVϋqΌwql2Œœ:fη΅D™ξ@Uν#Β!Νά›η2 ³Ϊ"L€†[XηΗγΤϋ΅N_—–Z—΄¬š]€πo\μΣ ΐυ!α.#cS=wŠœ|#>όpڏΫOš–Ž%E0ΫΘd—ΔχΞ.pχϋΉg€Βb|™ e#\ŸΡžtΪ–KΝ H¦‘Ε‹2σμ ;G„GS«}nσγ-Ώh&_ΝUUkƒΪ’]Μ|’™VͺL˜ͺŠ ‘G0ͺ6.2Σ)ڞ{ΝXRvφ\άΤ±α%΅tbψ‘Α0E½L…σjύΞγΆMWABΫqYI#gΩ£t• ⡈ Œ]u„6ρvMί2Φ9w­ΎΪPhF;υtzύήs [αn”Y@|A;Γo=F?q{Ž-¨0?§Ω¬ΐΤ'ΜΉyητέΡY<ρzf& Ϋ~΅=φ;~0,½ρνΠ‡ύ! e‘ΟZhσ= p Έμΐk-;P]3@±y©vεΡ<ε0€9f—7Β•[ΛαΜ°ρh•Ήίζ#οΗ!_fΦUFε!vy9”QΥ lΚv`ύZ1Έ-ͺΚΩΦL€€”­ξκΣ­k—#βŠΥ-Ύγ'μξB€ΝρBsKΟC΅Ύ7Ζe„n]ϋu αΰΒυžΘ”Φ #ωs¬O‘,rI7νΓ_RG@Œ©εj­5€TqΗu¬Œ6qˆέ?0hΗ~½ν=aθGÚVΪ¬@\ € ±2« οCP^–%χ„Ύ± ;uΈΝJmκ4’Ξιχ3Ÿz%άΌΊξΣ^Ol†{†΅Ώ!Γx;Είυ‰€±―–΅Ψjf]‡₯ίBΩύ'^:,DΟ\hllΥrOrEΖ\ ―LΎŠD‘8-άξεPˆ ΄€/ν?¦9Ι‰Βžτ²ΎiО}θIΑπ¨UΈt柽QνIι–“°=* ₯$Φ4q·€;?0r‹ŠI ν„Λ>΅‰γA"iuάΐP8σήήψ›%2>v‰λ0v½γ+—b8ατ«₯νW»βtΘk"―έx„+›-Δ1”…9Ϊ­W{υ}ψ»ξ ΏΙΥπΖrxcu |ίωυπΨΨΊ4ϋ4,vΜψAΙΠn@7Δό+Ϊ€qD@88\…SYΉ‡Α€(N[Ν§Eβ΄wT²rBΏΖͺn‚Σ&MΧ6ν]βΏm\ήαNή{Αu―·UnζaχΧ’TZŒJ#*Ύ΅p9¨ΉΝ·vώ­!΅ήΒΛβη΅Ve-Œ=π0φθχ†­υε8CΠΥςvyj³ή+!- AX*_«κΠΡ‘PΊηΑ0ψθwθώ@Θ³Ε–Ύ¦Il€#9Τr˜rus+œ?5»o\ž[aLϋχ}si",UΕΈͺuμ»β@Θ έΛ+yΑŽ­;™ΦžttρŒ‚Ϋ―ϊς$oϋΖ‡β·‰»+·‰ηωk‹ƒ]βΏeά.βyΪ½pο9 FΗ€4¬5_έ¬Ιχά{οŽp¬ ϋ֝Ų΅$΅{Pͺο°ZCš,¨’ƒx6έαμρNή¬βΙ§|QJ[TŸώŸ ε[CeξŠ †m3Βi{4*ΌYπtοΣb›’TϋβΉ»Caς΄ žΪaΘ*Dr±ΡνΑOΞθOΟδΤG°%κ?g%pv"Ή \X&:ύ΄`ςΪ.)¨l<φ2οίΓ§ΐ8 Ύ 2›|λμ Μ,@u!2€σ˜½ΉΊΊj:5Φ fΧδ”48ΟΓβηa8;€:–MSXΎ' ΣαΔIN;8πΊqx„Γ5ƍΎϋΫ w›ΒαAλ-βk―½όρp·‘πLEϊ°`$Ω$Ԏ €a@c ωοΠE Β€Ωύˆi>@lΨ¨@8–[oV"αψΞ3ΔιD†ω’\,ιΤZ‘Αˆ@ι=O*āθΩΞ •\/­ycΥΔ¬μΈ3zοƒaψα'tΞ€6Aш‚•©Žρ[iφ#mfM€ΓIC²IAJ­[P¬<1V|ΞζŽg3ώiΐ+Rύo¬1΄(όK aωηH.ŽCΰ@ΗMWΐF¨SgŽ3ΒΑδΰ?.cPωΑ‚Fΰψξ©·¬Γ87ω€πΌ!ρ<Gψ·’λ™.€3χχθPΠgŸ}Φ4Nβœ@ŽσΦΏ©’Dθ‘ι›+x^Ή­Ο|ƒˆ€KΛΔ;„ 1r˜qωN8ž]`°oΔfπυmC-ΰ†ΫΦ^ύg}οώι°υνO*ΆTwΝΣ²#^p2%†ϊτ#£aδώ‡Bί°Œ{0>Np-‘φθ8δaΉA͐δσΈu™4-ΟωH`[9xM.’Ÿ†o܊“z8:-'!.p¬€IYΐ~πŸΠ€ ŽgqxγB›γaL8¬υˆΗŒΧμNΔ\Ÿpΐ%ΏΤΙYC?Y[~εrΩ„ yυ΄]8ΰΧΚΈϋq·w?ιTœžΡœ°¨τ|ΰαg~ζg¬"zθ‘πΔOA8#šYΝ™H•6UitXy¦ώό[‚%―‚ƒ` Tw •Θ‡·,ΐŽ.§‹cα”ΞΚ+ζͺaπξ·‡ά»~F“b†4|§S‰ΚΪBJcœ˜ψΜΉ0ϊΨ;uδΨH4πΣΚ²?b¬‹₯Δ†u,W|ΪΒ[ο†ΏQiώΙ‹ B²βs΅ψ!Ό0— o,Φ4φΟ6`A‡xŽΪςlZk.„(‚ FζΏΰΗ†0% ΖΕΑ―04έΒ»`7(.`" ηLN΄†Ω#‚0€ƒΦ€1#-i!$¨kΒQF„uΌ_wZy³έ{FpΔRATΤOόΔOXeΫP“*¦"S‚%BΒ{6 ˆΉ‡α’[|‰κ€·N‡Q’΅vs³O„XΦvΧ:ά“Ωgr7‡²6ΑN§Υ3- Žψΐ„9¨rSqΩ'° CC΄QX(ήϋhΈΥd¨Όπ·:ΐτrΨκ—―ZR²ˆzή§±ύQ΅ϊ2φΩΑ"%ΑR ώAό°V"oΈ‘φΒ~𠍔My*†Χ$Mn_α_Ύ‘Σ€ RDΝσc" οR· A8˜œ ²j‘Σ‚`’ €gπΝ,Aκƒι˜ 8γ‚I‰OπΙ…βΗ…s– sΨƒ‚hffΖVŠΖnΘ€ε †gσXς $„΅3dZYIΰ€έ*XzNPA “VΑΥtĜΎρ—Ί„‚sjžŒgiΤΉ²AŒ°™»·±b»’ˆM†€¨——WpGGuΐ§ΒWE.CΣς›–πΆ@EΏ$Ž­Υ—]ͺZΪ‡½ΗwΠΘEς¬TίσΣb^ ©!ΩVr²ό#ˆUΎa1X^Ο…‚ŽL—ΆΔ(†0DPƒ3vu¦΅Ρd%π²ΌΌbaX§3[••ΓFKΪΜ|Γΰΐ /«fηfM£ΠϊΊ0¬ΊΛΒι3§%¨+Ζά” Asϊτ₯Ή¦§§M8Q?%z”$€6”WŒ˜„΅‚ΖΛC«Ÿύ03πv[ΑμUΏžŽ(b€Di‘!βHI^i¨α(–3θ= b€+@Þ*“Φd{‹‰*šΈ"KxQgгz‹ΦρqΒ0&ΞtV4€ΌΒxΖΪvΞΊ·ΕΦ»c“_μŽU]q%^,.«γΘ3ρh ϋG†Ν?―M _―|X^Έ?”5”rj1zLSy‡ΓΆcZοA3Ύ0`ŽάQ6φΣόόνœ†ϋ κΟkQ²hTήŠfŽjαΫs…πςb> vμΧ)½jέ₯ύ ͺLΓžΤΗΔψ¨ό₯λ`€/»[Λ/¨ϊ^T‹^” )iF"«Ά°?πΚφn›£&tΕ§κ:‡™ΩΓ{- D8Ž}ΐ%›­ 4ϊ₯¬K#ˆ] u5Τ} ­²ξ”oBΪΑ: ‡˜žνېΧΑ€›κHHxύΐ¨ά~l?ρ:εγ(Ύυ¬πmΐσͺτλΣ aaYgΝ‹ h‘ΣκεŠ—Cq^ΘWKU•¦qIDΖ֚ν«Ε¨·V’§Β¬—7Β­εVήg»vKΔ[΄ώ™Uƒs}Ύ,p²^«E+βP}Lδς2Fa€¬ςΊΊ—g,Ÿš$Μ†Z²•Uυ{EΨ³…ϋΓΨωνp~bAγρ2B2Y谘ίp€²Oή6ΓςͺΩς+aa*.hz―ΛJ˜6UrŠZΈ(ό§^e¨u%T€ΝeύίΠΗ’–ό.•΅ΚRYΛ©pk‘V6ζ4hΝ–/¬±7‚N– ₯€η²4‘Χ―Š±%8hΥτ̞΄ήΣ ―+lM*»φ¨Μ„Υ•Υ0·*FW+Ώ²²,{ƒΊiΒέ₯―X|ZΨ•Φr¨^Ό!b(k‚ŠΖςς’ςqΝ΄ GWdqq)Όrι¦ mΊ7•ηθ¬‡0Aγ9wJC·Ι~έΔλ•0=)RώU% Ui…ΗlΪ;έƒu2 @?[‚‰·‡υƒ€κ=άiEέcχ" e­j)ΰ¨Σψ’γojyβiηΧΗη‘!T9OCΗ΅<–W`•Ν% ζͺˆbTjλδΈ¬βWΏΖ+mΘ«ΥT ΜπίNx€ΞσH=£ωpυkp-―–Άη•Ύϊά:κKm«ΆT¬jšp>|qnLjΎZs΄ α}XZ ύύΣ§N‡³2pž>{Ζ œ ŒŠW ΜόS„ `G~O₯…J³ΤΠ#DG†γ¨ ΒφΜ©IτSAӘ3ΖΣ―K½LMp°ή‡mΙhύOMΚΟBΚO ©ζ^Λ•eTU8Φ)`{IΣ7¨VSiޚ€ί…£(²~5Nδ<‘}Τ%Φ‡”{ΕυœH‘#DΊ±ν”φ8£χΊ*! κΩ–αΦΔLl :©β°$˜Fά.S;π©ΤcξԝGΰMžζ―ΚLΏ[έςΡκ9I>¦žφΩ~ Ft•ͺTόνάΉ0ύϊW5§uΥm`H έ·.͝Έ·ϋδΉJHΡ}P›ͺp K₯ΥΥ«SτΙ°Ή% ½ϊQ_[Ώ+δ6…FρΔΤCRχi9Ο¨ΟΝ­\§5,;©!:,υXήiΡS$₯—Κ…•OwΛPς.Α€pˆΨŽαψμΜλ Ό?mQ ρ£kΉ@IDATΩ”F830»„ίIj§ώ’Š―0bLwΡΟίΠ<ο|ίωύS6ΝΈ3r’ήΨξ3p!{N€;S‹%Εέ’Λ°OS]QσEBζ€P†Ο˜J0ˆςhv}Ψ <œS’sΊξIΰΨ²xπ”ρuΑΰ[Ϊ:¬―8f.~=\φSZ# –Ÿώ8PR ε@<—~―ΚπgFM-ΖΰΈ^Έ+¬—Ξ…‘ΥΛf!ί,M†—r†jy% δ₯΅HκΡΟgzσθΨx“φΒ}Xs0Θa„"\πΰΘσœΡϘ} pj‰ϋ4*͞=NŠŠτΑ„3‘„${F`¨Ž(ό9ΞhفcψΎ}K ςpφ©ρG°hΉoΗeεM‹”>΄ΎΫχ6ΡΓ»ηˆ΄aέQ=qτΉν z*<γŒΘhΒQΏl‘ŠΎ«[ίΘDhx€_Ι€αC—―NδυΑE j·e΄*I}žΏφRΈώΜίJFΕυ–/‘eφ±πόσΟ‡οώξοΆ© 0ύK/½>ΣΜڍD χ4ΡV'Fχ%― 2―?ύ7a}eVD:"UWC‰­¦Ζ­· αϊŒΪΜ¬…—/Ν…wήW ίχ§ΒκΊ–‹3ν€ŒΜΊ &¨aο:ςΒΠgQέ%1acaΆ#sΐ―ΝΒSkΰbφ“m|Ϊο#Ih©%‡! Ϊa£Όn\όF˜Ήόν°αUͺ<§(™Ύ£ίΊA΄ό‰²Ά#Ιλ ,lEnΰΑ‘ XR'‘U)Ο‡ΝΥ[aεϊ32^އ‰{ΓΰιGBiμœͺΚ€ωhb”ϊς|gοwz žβcŸ=#υSΧo†…k/(―yυmΕPσΧΖ}a= i¬»/\™^Υά†M`ќy©ΛeΤα˜aWˆo#ϋMQα!oΜνΰ1―“ιΟ3I†Φ™~[΄0ži΅δVΜo8RyσšρˆΠ»φς—Βτ+l*>LŸΧViΈΨΏ‹›¬Ξ„'kωuγ)ώΖ'{΅Ÿ;?6Ύ ρ%ΔH ·]њ‚›ίk·^Π‘-Ξ2έΈ&Χ°*Ρ–λ€αZuΕ••[ –’D;b#ρЊž<7δq‘o877g‚€η›7oš0Xn!/|ρ?‡υΉΧΤΟ.€I) †:³ΒW/Ηηœ‘MH[Ρ0ρπΪsαVy3”5j09ΞΊε]εn Γo5!Πs€J€©w±R εHΔφnT‡—Z3ύٞ€T|βο #SΙx³~₯ΊQ °€ϊίIkΗD”¨eD#Μΐ;kΪc ¨”αl] ^V—֝o8B…Ύ<+πe^|ymΔ‹Ύ5}gfΣΕ5ρ6“&ΐXvyQ{ΜήΠΥΑ:.θ:α(εpa†#ο#jάc™ΛιLLΚΗRιε•΅0ύβ6ζ/σΧԝΩiρ#lέ+?&$ΰTbV“ŽU_—―kλ°Mi9ͺ'~F2 Kγ_{)†Σΐ^βτB؞ †ΚρŠΨ™²™°U¬%4—ΓD7ήΊΊ«F‰ΛόμM1)λΐΩΜ²Ββ]Œλ“Vι­ΪŠ5ζ»ΫŠ@Ν„c ‡TΪ’†ΈXάΓBζΤΜΟ³Ϋ †3YφΕ<δ/..{*ϊΕ ƒτiΆΟ€&ΖΨZz†ίŠ«ΦΟ¦…e«-›‘ΧŸ †7Γφς«fX˜ΔΠFdU=ά–]&£”wp―˜ηi!+šΔJKΦΤ“n .―Q ζ,K#aϊ₯ ‹Χž³ 9ۚ琳i½I%άV32“ΕU'κZ kGδΑ•λαςU {ναΐvΉ’T1Xόδ ›φ’#oœ,χχΈΓφ¬1.UΩΡ†qjw.L ΄9Έ€KKWm°Ρ PύVυljΆΈŒϋΨθZ9υmu† λkZ―^”…xCΦϊ>u%ΨCΛΌ:Φz³ΞΝKΕ]Σž! oUΤj³Ά<§ =j―͚o;ξ"΄΄ηζ†Œ S€ŠΜ Ίt3˜ΆŠ°Y”:Ν"Œo‘qΝ³EΎ\x_¨\―„ςΒU[€Cψύٜίγ”g„ΒOΓbv³†‹±'4 0/•αf’HZ/K{‘Am@ǟ­­,„Α©σαΚσζ.ύ‹–ΫΫφά%p’^―ήd–5!ΐΦ觇6Β—oi§&‘Š„1ϋ ”$ˆUιͺgΝYPέ’ΑAcέ‹6„~μFυ*Ϊε«g€«c0ώ5ν0·€VJLγΦ €HT(ΞΚβ«:¬fφ ιΧ³₯TAkΰι·χI j1jUΜ”ek¨nM[ίΧτ}ρΈηί°Τ^Ίλε[JŽkΩ?ξm·Ή‘΅ν"ςΉ][ ƒs쀋σΦΦ΄γΠΦMY$¨…5MZΡ:ψEfΕ)²&Ν„ά²©αεͺ lΚΗςͺβΤ Ε­Ω0’I,bW Lέε2c£%г±Y ‹Λe ­‡Ο/‡Α;ΨtC‡ƒ,j&’ŠŠ2φ­_ΌŽΤ5ΓίΪΥ9=²{XX^z!,Ύρe3ψŐw„q—Y:φ`,f¨uLΘΆζΓΣΟ/…ϋES7f—Μή1&@ΖHλuΦM¦MΣmeχH¨ns˜žτCYδΓll ΒzϋTΕς€$y>ΩΩ’ͺƒ+8”–)ώHρŠφωcί½q­'2 *ή³oŽχqi.κqόΕΠvθϋd\”„hD»ΰPΙ\1ώ0jt€4‘ \ƒ‘obŸaJΕ'Ήά$²‚'}ΫΆΝ$&΅~}eU# ίΆgώ‹,ΨZœ£4φεοαΚΧJ§ ±nsύΜΎŠr`‘„JfE>xΆ^ΌΆ¬Ο²‡+›²ΡΤF€@jCα…-Ο ΑnPOΆ›Kχˆ•z`Y>l@='`*‚e&Ž{Uκ;J­€,΅2‡Ύ(€ξΉ1IΫΨ’YKΏ±ΙD¬ώΔσΡ'WEΥ|2Œcνό’œθ₯ΞΉ_“”O3•·ˆžP|9ΡυΌZΥ£4‡ym>r«φ_…ά­/+τ`χΔ”b9!jv5*ζž §΅ΖΉS£Ϊ胡ύ;-_λΎΊ7^ώ’ΆNš•Ζ ΝΙΖψιs5 %Fκι_Ѝ!pSͺϊω©pa’¬FFέ΄>­ΕPΧo€TΠR‘ΝMKΦMjͺγΆ%Œ]€μ”λΆA{μCΟ p ©q.ΐ'?ωIcώϊ‘>ψ ŒdμK7@X„wΰ 5LΉ5Y⇀–²'@C·™!:(sΗ±ZΝUX΄σ΅ώ©ΥχΔOιgD‘’αŸu σ'<ΏϋKς- .W‘Πd:T+-½cς^MΦ°γςσ’\φΥΫ―P>•xΕŠυc(Sι¬o0όˆαΕ FτJ‹‰>ε…ιpωω/Hh1“lΡβίXΞ΄=ΦΡηΗsαk―.ˆΎ΄BZ ΊyΩ°†MO»].ξέR“η=…ϊ φŒp¦€σόΟΌ1*SYψkΏφkš|—ϊυΥD¨–¨QuršQgΓ€ΖhYώBZ€  ίmΕΦ£ͺω­ϋ’9n£OŸςΉ- ’™AΜ¦ν·Ε¨›§‘AρVΘWf“iΞϋ6Ι+—hί.ˆFΐ(ΘΠ#*lԎ΄IΦqΊ]7_ϊ‚6)kΘO šΠˆt;#[ΐύη†Β7_[Υ₯+2φj¦g³ο#ΓΑ‘‘!›ˆ·έŠLx;ΡυŒpβbhμŸψ„α’‚8‚λ₯KΆc7œσCλΙM?ΌB§Ωϊh¨œΫΩ@Υ!œ˜4Δœ ]ΝmΌ#lίψ’ŠδΫ{ς0Ί(¨ …γ!?ξψq‡Ώmχ]­Ί[ž»kA“ζ(ΨdŸ;œωΑΏu&†‹ΊrZ›±"' ­h„Fϋ"°²ΊŸΜ4ΩΠx΄ΒΎγΆΥ·^χs]Έgς 2™’Κ‰.0>SSο»ο>νKwΖΤXΧ S«0Ό ˜ψβw:ŽV˜‘6ά’±qtκ‚Yμw†χ^84\dvgϊxw4! ‘‰ ˜~ύλξc^?6ˆ½§ιp{νN· ˜—ΝθάD1¬jB½˜ ±ιέn|¦‘ΑέΙΜέ ξ{F8Β™wα8<όπΓ&Xxύχ›@πΚ𻐖‰•ZgMX7₯> 0uω8˜QHMW«C ΔTcφβc'_wΏW^„uQ磆…±#Θ2eπrύαΥΕι0υy=k§cωΕΎ°@P~#ΡΜέ§U>Νσ`v(k;XοΐΔ.†1D;Mφ@Ά- =Σp"€}τΡπя~4\Ύ|Ωv’Εΐ΄UΒDBΞΰ 7υ?γΧΨΘ|βΡ» ή=ρκε³]{Τr3#o`䔦߾n£ w7Gρq¦΅ gΖa(ihΥηi`Œ 8wι[ΪΝxΝVψέΙ–+WÏΠaΆŠŒ©1ύ&ϋΡͺΐ†v1B@4B>Τη£4€yΣΌφŒpŒϊ‘†Ρς£ϊS^ΞΦ™œ;”Ž€λ†CbΘωm)”n2εδβγ4£’φX‚rε¬3v£hμ2ŠŒανÎ…5 ™qgΆpγ%0ςΰ+0Zη4ο”―F.†Γ₯ΌΞlΘ‡ω΅ 3’ d5psυΫKxκ™.€#„»`vΈc%@›©Ήζ’[|ΉƒUπ€•Ύ8¨ωκ‹γ {q Η4Q=Βΐ‰š»9έ8XώΩliζb(sZ’ Qή[z{ΙΫq…‡(C )Ÿ’ΐ9†ΠΜΟά ox_Η•ΧΓN·η4 cλ‰/%Φδ›i ύΪΤ4xƒ )QλωMΰθ{ΣZ4Χή0ΚΡ5?б…pWΠ T{#fι;Φτ‰θ―_{žΏςœ£ Ώ=$xG`άΙ†Μ‚Ÿ©QŽN_TΏ_@ΜΟ^Y@–φξˆξ1“=§xώA<-Π ­Aέ{t»ΒέΌƒ„•&›α=ΆΨf»λ(ίφPVczŒ€ΙμGθΚβ–gζό3ajsm)¬Μ]ΆI@LJz3―`ΟP«&_© ”ΐΫΠ:MM4£υχ‘οzzά7γ½'5Zxh5NΨ‰h·V?©μ3bœωιΆΕ?Ν%5ΜΥ…«ƒΣEψέ‚,<UΙgύ³RώyM“Tφβ@x΄Υ”κ"AπΈΘτ0~œωǝγΜo½6Φ4#nH]fώu‰Hƒz'ύΔ‘–~ι¨4Vz«ΏΙ2a Ψ„ ϊ ‰Ϋ ‡xβ‡xο9’AfœςλΛμ-€ΞΆΚ€6©ˆTύW[ΐα ΡkbԎ¨;ΈJ3VKZΜ.†*š¬"4EU„[εέΣ€ΧΑL? Ε@Eiqύ»ζ­'†UήνΤ`PΈxλU Q‚’F—ˆlΘr―ΏnDKt…ς²‘δΤκW¬°‘=!Φu™F ‘ΐ’pΓτ`β΄rNCΩΖͺUΈ^υλ9B1~1$Γ"†ΗYSοΘ6F©fj ‹μ‚ΉΊpΐ?h—ζν@G&¬miVšͺ vH PΤ0ΰ@Q»k£^fRjξ20G€U‚a[;ΝJύ·uoNλMΠΣG0‚Ÿ-³{Δξ- 8Κ‹>ОXMi‡™΄ +§IΊ«”;Νυœ€˜„Α‚ Τ2˜tvq-ΌtρŠ*ƒ7ͺ *ƒΦQ%(ΞωΪ€:"6AKnQQ-+0PΒ.nχ‚·³v/ €rιT,ζ΅{"3"ΎΠ¦ΨavΎlxΤ΄Yfi6TrƒaIgŒNlκlΰ•P‘ϊί§8"Q§ΘξΝσnΨ—!RφiXΠ~θRλ—½Eg8lаΛUΫΕi€=’Ζ¨`‰έ Ξ·eΤΨ Ί‘©F8ΗυήsΒόώη>ρ—Ξj›ͺούΎσ=ο8r…vDt" lj!  ͺ.@.Ω ›.HfΆ@~ι_-©ιβwψd‰ίωUΉ΄Q₯―tš^‹Lξζ»S΄φ#CZέΆ C2Τ’a,J(”€ώ’³`eφ ;³―CL±5t!wK½ΧΏ »Zά'<¨…ΧΑ yα©_εV;ρ£5C<Ω&.–jΉœκ-λd?€Ϋ¬mWΗaώΟ|ζ3α·~λ·l pEγ³_όόSα‰Ηήyτ1›°A‹fN ͺώZΑ₯΅ι~‡.ωλϊΣ:i΄™^,Ϋ]ύΘͺiF:υ?ΛK:\DΒo/Ι‚‘A€ρ6Ω΄}F‡ΒΔ¨6ύ˜ g§΄'ΐ™±pσΦBX!GΤ1„x;™οͺ„=ˆΦzPΫΒ•ΤE²ΝQ΄gΒΈφL˜g&G΅PhάNNςΕA™φ.Z‚ΰΐi©1Α~ο ΐΥ&Ζ?χΉΟ…{ξΉ'<ρΔΆΰόω αϊΝ[αΎϋί&u­*ΓUΒέά΄bN»qMΐή°…OsoQΫ„ŽΜ‰η}ΐVd››― 9ευ5i?μYˆ1 ©·wζdΦ«ΰl/©Όλ¬kσή¨θμ„εd|Νϊ>2Π¦`oBο8/‚3XjΞ&²1 ‚£νˆ7‘έiΤ‘ΰΜΟ;ίξ4ζ'ί=#Θ €2˜½ψϞ=›,Ίξ“@PcmύYίΘψŠ….jαβ~Iӟά"Δέcειΰ]$нΓ&O¨¨ύRΩ·7΅•9jΉ tq|~οωœS?VrόαJ&ε΄•2kͺε…°΅±Ό3Ωhfο9κ•Rϋ³Υc²šα^u`FSΊ ΤId…A―”¬›|τŒˆΣNƒYμΗ~Μά`O„ΑC=Ξ;'γ`άΩΗT-JλΙZύτh0xκί £8ήι2JΧΑΘΞή[ ζ­½œς’Ω?Ψ"4nw η!I›mΐΗGԏεY6ΆΒφ݁ΆΤΥ(/ή°₯ΏbŠ€yKρΏˆ…ω"+;Έ1u^xoΠZ*4jύNeϊl1zF82±ό³ΐ―ώκ―ΪΩ€l£ΝYu8cΟͺΈΨO…YδLŠ'ΟΙ-~θξ؍Ύ»˜»‡Ϊ;lΨο3Ύ)’ψlω`TFΐ’¦#DιZlιΞόmέ«+7χήςxηώ@?π>ϋRχF6ό$LŸ-Ycfi1ξN{ξΰˆ£%F°ό—=Π lιTQ[mPn]’ZϋΌQy‰%«e”vžά.ά~ύχ _₯1¦‡QΧ—¦ E„jB*έέzDΨUQωlƒ²vc`(Υf» ·-ϋέ^•€Ρ!κ »ΜΩψΒp£2€‹JEYΫ€Φ7 “wͺͺlο§SΈ#ϋά}ifΗΔ©4ΖΑ|€Ζ ΜΖλ¦2» “…ΩκΉ ΎuϊΎA&fSn-4€γσbΨ½6Υήΰxμ -|1blΏHhμ>Τ6WV#+p…qΒNNήΜO؎Μ0*M(n‰ςƒϊ€Π‡₯φN{N˜*f„¨^° Tϊζ^Qš΅‘,©9$yƒC‹ΰΰO·3 >ό°P4KkpψgσΤπΩ^ωξS~=Œ ξίΏω…”)©3Χ^ [j₯γjΐ΄Δ¬γΠh  “±»N ›•›Ύ-ZΒ`kM’Φ4EΠ–ο ~ΗΔ{ψ#Υξ1π•eν_Υ~<ƒ'AΆ>½Y?―?v'ί{Nd‘ Γ:ΣΆG2Τ­―Τ #H x4 ―Hž‘1eZUΎ§Ο°‘QκwΔεΖ4KNΟ„!,ώ¬+oΜ3YrΈI?„!]ΰgΗYhΑΤy†Ϊ u}ρ²βGmY΄h-žK@#.ͺξ½Ϊ —‰@ZυΖΚ·jeC{ώΟ(„Θ@y+9ŠK›Qή`»τ8W?κƒΊτεθN/oVάτœ ’ε‚ ©\jυ··?˜·ΫΠ/ŒΗρbƒbτ 1=³ή8Ρ—#Ώ8Š­  SΦε§γ’-p: LΚ¦$6 ;ΧoQ*Ήΰ°}9Žο<³“,gώ!Ql$[U1ψʊvŸ•JζG₯ηlΐΈύWΰτ`΄’••eΑ,g :ϊl_~ŸIͺέ;ςΒ|upοΩα ω@:άT+ώ΄ΔxE;–F΄†Fϊ΅".ξ–ά=μ;5dԊ8μ΅/,­h 0IπΔΡρœκΜρθμHεΜοw+―Β}ξ‘πmHs/hΟiΓ(6d%&Ι Z‡ 0ΛEcL3‡k¨*Ri/0>Lm*Ώ‚uψgfSL?sζap†ΉaZ?(•΅‹,‚ ˜šgq‡tΈΔ9Ν]ΐoEŒLV`ς‚Κβλ̍Π‡*ΞǍziΠ:c₯ŸnΘΛΣ/λQ –K h*œAιζ'β€Ε??πξσ&p˜|ŸNΗ!?†²^¦nŠΨe+¦ ¬b›ž_’ή9,Eέ Ή3ͺ?΄B΄:걎ω»LγN Φs€1²’ΦzPGWS0FΛ]|ιT :©ΎK UΗͺ€Θ šξΙažΐ’r‹j± L)|φαίͺ₯ŠGmαƒΠ©ξ`BNf£Nˆ­`TϋΘ35 1―Φfη›ηm‚²°έρθg’m¬™@‘PQh$ ϊ’μœΣΜΏ₯λΟ&Μ“R ύq)εgžϋΊfL>rίx˜œPW@ZΑΈΦNljνDΚ‹ώ¦»GLΦΒΜ’Lni ΤK σ&”ΩšΪƒΈΫτάʁγ;ΡυœpD‹±_»f8eW`Vleχ°ΰ\υ‘[“ ΗΉbΞVS#LΤψ’NΊeΖ›˜ltΜϊΩhν\Њ―εε% ˆM©ξ: #©Π’G+ΜΖ[[ekΉ™:Κ„ΦΣ3΄677ofb|ŽέB“ ί½₯Φ~ϊ§J 6ΤͺfΨU󅻦ΕAjmφpΠlPžΗΗΗΒͺϊΧEΝ―6υ·€•^ΖθΗs0' 81~Ζ@E-vN­>-xYnjsj.kΓ9l“ξ§μς< |±nœ•c’#-4ΕVΤΒ 1Σ2δUΠiΑλ:~Š~ζ]Ξ™vγ3ΌΗ<m8lD«Ÿ{ώΉπυo>Ξ\xΐΊύΦ'5σ―ζ„|iΥ1©kπR›šB[]ΥΊο~­_ΉaΑFωόš1τšNˆA#XάΈi0°Ξ—/ΟX IΏpfΉjj~aA§Κζ—€Βkο|ž Λ¦ή―ΞXΏMƒ–veΛl¨φύ¬ϋ‘ώζΖEΑWή9ˆβ΅«³4MWΪΕμς0  @·o~1T4φί——QpΪ©†°=ώ@|ΦZEτν1φœ–Ÿ©Ώμ’tcv-LΟ«ξΕΰe-Š ’‹7ά4 Θ$ΌveΪ„A<(T΄Υ’ψΠΜoϋθ$'Eh΄'½zFd±σΒ /„·ΏύνΆ`J²ϋο½ΧϊΝΓ%Mg•œΐ`RTDŒΩ½LRU`{PU΄‹­ldX>(šKα±ϊ~ aXϋοσΝίϋtL·Φ…³€gtD§Ι$αGψgbh‰ν)ΒΚ9‘Žoώ>"=ώ¨–δZx­ςΫnθΞΡ0wω›aιΦ κ’h_>iΨA»$ϋ ΆηαErH0/⦘Ÿύ†ΥκHŸ>}*œWwσŒθ(υ’iqm¨Ψκ"Š6yžͺ ±;υ• Ω³Έι9@ όξwΏ;<σΜ3αœΤ3²†s@‹‚.œ·Ήλlβa¬†)Α 4έs#’6"ΠίΔC™CSΗΒ«Μ+¬ώ}'„νΜk±GΌΎ ί’©τΑaY΄l<)aώΎΒDXՎΌ7―~Α†θΨ©χ0˜?Ιώ[όG>¦ηΦΤε*Hx—tλ Ί…CαΤΔX8=5.œ™ S“Su VŸ~γCΡh8A^Χ₯sΠ/=#Ppτ‘?τ‘Ω°Vυ|ΠΦLš’ϊ­‰+ΖR¨Εz€΅Χ~ΉeYΠδQ”]€]:·Τ Ž9υή•£so1β²ΟP²Τ²ζζokK]Ώ½|λJxιKΧ²_mƒ¦.NK*k}ςΎ' €}«{Υ!ΖΠ+Ӛƒ‘z09¬.]K₯A(+ ο@ ί,Œwκ’LΨΖ2™άdk=γέs=#3¨Η ‘=ωδ“š°2oF1&ΤΨ±Υ‰ΐΒ‚.Œ€ZδRΓ„ΐwjΘΤBuόq5}|ΔΌMmϊΈ‹dA\}{5αgαΖkα΅―™ΎΘx(u›ΑΧ”μRς^ψL}£aE'σΛα¦4vbΗeμ0u—hn«YΤ—Θ»uυΎ½ΦsDSIŒΑ3ΩΔf§Ϊ¦(…—Έ`ψ~)φf}G%C€›t°·Ά?„ς@Ϋ@­>0)Η„$΅gΓκΠΚk&‡\}ρΏ„kΟ?%pΚIRφn·ώήCΚoω VΧΰWC-»vk%¬Wdβ‘MHΈgξ B€gϊόhΈ½27iut’ο½Βμο6>φœ1*Ζ‡AmΪ¬1u¦€ΤρΉ˜JΟ<«°]џ"ω‘·ύ $„Hκ€6Ύ8!%κ}~`ΘΆΰΊϊμgΒτ+ڍ61,&ekrς~0Ϋ‘HευkKΦNX ―αZoύ\ΦκK@‹»΅ώςΥΘθhw5ΑT&f#}g>ζcΟ ΠΜςͺηF$Φ!Δ„€|ΰβ,οƒΠn˜SΡnON’<˜Ί/$?0¨έ}VΓ΅?n½φ›ΰ“Wΐ–.σ[Wώ“—0@{aγRλiω/ήX²y΄ώής3ƒ«ˆϊ€Hω^βg؞Ž„ΞU1χ―»ΫΉ`.²@‘vHv.‘v7/–€~ °€ΫLŒBτρkh1† ·Γ­‹ί° >λΛ·μψ-Zών­ΫŸεΧM6ίκa¨kfm²βΥ«‹6‰]4 ΒψΜυΰ™‰_ΨbΊN?]αzδκ!ΧsΐΥ-ξ¦Yγ―FāK…³–Ώ’Œœ ΠΒQQ¨uŒ2πΜά|&ϊPρ&hHOWΆBy&YΏ c₯Z²δ!Z“YjΛτβ-7]ΎρBXΎϊυ°xγνλ©™‡₯QΙ±Μλeλ<·L«Η=½ώΐ₯jYoG\ςi'VFΎryΑ¦3Ύευ? 4f†Ζ΅ ^–ΖμΆ£‡]kQι;Μ]Γ6&zHο='@#‰E58T΄&ηΤ‘U»±†λ(Ξ‚θ;B˜0:°xfυ̧5Οΐ™|]†GVΜ1©ƒ|ΰ1’Φj Ήmυi7BIkϊcDIȚΌ.‘psϊF¨ήόjX›}=ͺϋ2ςΥΠŒρΣR½ιLaΗ*Μ²&UrbXΟ*Ώκ°$ۈ΄μπΟ/†ϋξͺ†σύ:‡UsZΛCΐ$‚ΐπνW΄τZ­{AΆš΅φhˆγc:TטθkTτ14¨‘Ρ]=«C˜ΉMΎπ·oϊA«D`ΤΉLž uaι₯g€«E΄ή¨όΟkIπ9υΏΉξ½χž04:žyωjŠ&'@νg ³jυ‡%΅Ydv4˜j2UΒβϊr˜^ԁ:h²eΗ]vθΉ‘υό¨τ«—gΝψ“WλΐζCZϋΏ‘Γ3_ΉόŠ΅tlvλoοΝΓ,;ͺΟϋr_*3kΛͺRUIͺΒ" Œ±1<γ–i›v±φ˜ωß=0ŸΑFƟΫφG†Ο-cw·7h Νb±1 „ΝΎΘ`6Ι`Ϊ«Jͺ5+χ}Ο7ΏίΉ7^ήΜΪTKV=IU/oάΈqγFœ8ηΔ‰ˆsNLτσfΡΙ •n»¦~‰ƒ5ΨΧoλρUI€Or⺁Ϋ1+.χnlΟΖ§ζύΫ³ΙitpΊ†4ΥΒθLg?ύ8bΉΈ ‚p,ώΕήHφ½}ύ,τ΅dcϋw5΄ΖϊΔθΤ|Φ>Ž«Άa¦s‹Yϋ˜SΐB Ψ[ή₯ΆΉαΫΥβμΆ-=XΆ‡dPfώ ―ΛοFΌNp€n€σkƒ+σ2‰θψργεq6`•ƒ12VΨWlΗΩ 0€FE0‚–ΊΈQ ΈCΊ ~³wΆk³o†*ηε]Ζ_ 6Γ4·εΟι›²ΐπ½‘I7ξνLȞΤ•ϊΏχ£YΏϊ -Œ|XυU*‚Σ7žόAό• Έώβ’ίή]=Œ’ν7uf›XPΣ‘ͺk‘šΊ6mΟg&³Λ{¦˜ '‘β‹"ͺ’ΈS•oήœ^ΓχŸ£;Μ©‹5GώMHˆ›0Ξ₯¦{ΤέicΨχΧκXΤ—JηυN΅χ ω7άb‡ƒ1š+ΤJ¨EHΎ—™E-ΟEŒΤ Hm nΡύ؏ύX,άΙb}Ρrs·:σyΞ=ρΠ£iAξW`C’SοΌ_R‘tGNΈ&”».οVή©ε_~jR~Ηί"ΩγΉΩΚkbdS•7›8ΨΞ<βΰŽ”±φε'wDDΞ]Ž/dWμθΞqεΦμΨ06›Ί˜zuγZ Κ˜qoήΌ•arš­ϋa¦1­1hμΏπόΓϊΔ±ΑΙμΑG‡³­=8σύ ]²-ψbά±mKΆkG/.ΪΆ…3½OΉ0xΊmΐ„!V?βΕ₯€άlΨΛΉœE(8fH>/εΙ3\šΏuǝL` IΐE»2·t_yE ³  2½―Μ@Μf©τŠά§Έ)8†tΖ£!ί ΞC{ΰl±‚Ρˆk0†—8cO ΚCξΛnΈjSvψλΗ‚a “.Φ]6βTΓΡΆ±eKVd 5s‘MKHkΜΟ^–k4‹,Ϊm‡Ύυ@?ӝέΨύη⟫­8υڈΘ_EZqAΈRa‡‰&―[`c©9σ2΅Dύ‘Wœ βγ5’/½)ΑΗ{ΎjάJρˆ\’?uΗPμ$”6ίΦS”[„‘ ΐ•%Wώ\<ΌŠβW}£ψ υPΛ―ƒžΡ‘Η²*ώϊ›ΡρΧOΟžͺΑ©R#Δ6;»”=㊍ٷFBrΫMΙΝ5NiοΚfwgsǎΩ/χ€JΜ«˜Υ7<}γώc,ξIό !΄s~Γ† Ήb—ξΩ;dΰ›‹ƒκ3¬ΤΙςAΐ2ΌεˆΈ j ΒNy‚ΨΣ Χΐιύ₯ŽΦ%(±η.aΠΜ9πVΜώRŸό”yEΖΗyS.kΕ+>p{ˆ‘θόΜβ%„Ώ"ΟSχΖUv‰~CGΣ€ξμξGπ΅‡θλΦͺ Β‘QβjθΉ,›οwτO#μ…‡™= G_Ι€ώρKgHˆΊϋrλVΝM’ΫΊ‘ΙɜίΑ&ϋέ"ˆsΦ»–οςΨκη‘΅τήrώεB‚y.ˏ.YΜ‘³nC˜rΪΠD‡Ϋ’3d;mιαIΏ%©[Έ )ΧιΟηόΎT€}ŠY΄£nΆΩ΅!Ό³Oq‚’‘¨Ζ½HΊpΣ>’±΅θš§γ ΡaΛ@·λΤ:œEτοκlΙώι_Λξ;0ŒΏφ‰ι;}<ηΑQ_΅ξ~ή»#  (j5q[Λ„‹ιZϋjAΠ2<‰:ς–ΚIωW—yFœ}`m#uΗ¨ͺXν@mA怄)pxCΡkΰ+1Iyδϊ­Uί³%z­ό:6_ž΅χμ@γC%pη½–σΩslΑE}MP9=›GKwkΦΫΓω‡μΨhGž‘]ΉΐΡ[žqΨȎIν˜3©ελΞ@μ†ψΏρύΎμσz#Ρ±φD―#Τ}ρ³ϊ―Ϊ·€*ζ5KψSΤΙ>’ΆπU!ž%’ηšάkϊ•_Iiεkωω₯ŠΧԊnjZyd–*Ή‘Škη”;BZ7³λo3D˜ƒ/gαΙω…“ζΊDcΆύι?ΊώαΜƐ―>žίηžΘoΗb έ MĎM“6ε9ŠΣΔ2κω!¬°k&dε¬ΰ‚»I⏑Ώ£%{ψΠHφ‘Ο?Θ|ί~Ι ~TχΦ&ΔC[UςRλΣ΄š °’Be½R0έiiϊyoX‘Ώ„/'€ϋŒ_Ό—©πKx­; ^¨niΗτpp¦ζJ­Lΰ„˜€{ψyK;εŽ;ᝳM(:.-'~Νy[»{³­Χ½ΜΓΧ? @ΑΑ.$bŸmU/eώ€9ύ‘ΌqƒξάζγμC%€)˜AL΄‹ž1•Ί0΅΅ΈX„DϊθloΖΣοxφ??}iϊωγd&pΗ9Ώb»όΌΚ dJ™'[Δu•Bb]MπΦΊLάy{V¦%"χY9oΜϋ‹΄zY¨»E@ήN‡=τΰƒΩ§?σ™° ΈρΖ³Λwού€Π'·Χ₯)ώ·Aό±'rΩCρ_4»p‘φ͜ T°ωίΠ›u\ω“ΩΨΑΙZζϋή8K.―šΎςT JξΏ{Κ±ΌN£z-˜Ε†cž©ΐ"pSσ2@sž$|CμwΞΟ*ΏΔξέ σa€ύ¦&v rνKzTψa@Ω΄ΩA₯;˜BZό§Ÿ(ΠzŒ8ƒ¨ΛiήrρZ—eΕ+₯gΎΣPά—‹»TρΊa‰ ;W{+ΐλ―E œςΰCe7Ώζ5‘¬tΰ!€oΗρ*§η `%νŒσΔ±U¦ξeλ‹εΊ΅9ν¦ηdύ}dfΝ|£‚ϊbB…†ηZΐ±ό# Μ₯B—‡ Ί8Η‘hsξžΜr8+ ηŽηΧ;N7f8ίΟ9¬ίσροΕn„6ώž­Ÿσρ«„>‚  ‡Γ[ݐ1ΘΔ₯eŒϊωέJβ.ΌΤˆ^".9°βTρUοϊώ©ΦJY/Z΄n@κˆVΐνωHˆŒ?ς#?Ζ@ͺ•xτΡΜS‚—; z# €*θψW•pψ§6ζ0΄sΞΝNμ Λcί|t.Žοܝ=zœ}ζρΎlϋ†Ω¬«MY¦3ό”Δ³GN,π ž"<μΫ(AξΓηžπ‘ Θ°5±–!ΞMΗG"Ά μɟ£"0 šεͺ–ωΎσ`φ;ΰ›œΒŒ‘—nΎ:qψ!‘‡6"ψ³©ψiζβ_χ• ~HΔ“Υ#ή_>)ˊ>ρ4Ο™ΚΉkΈΊβurXFιγ‹­Z.`œk°…s%ώ+―Ό2\wΉzμγ?Ιx-W"’œΧH^ρη$I+žŸνΊβ*Θ°:7pœsήl©7;ΪΗxt ۊά΄“aL ~B%ό9ky2₯·dt³οΘhvπψDμ»k‚mˆy4σ₯‰Η°΄<Ώ–;ίχ[~³›Ώ/ί}(ϋΨW _‰Z‡žŒξnρmΪΈ1p¨—3Ά‚K2ηώόΗ}˜πΒj…*qUVΣi"ώ”Η¬)~2’^f^Σjε¬ώ@ρν‹u©₯ΨθΡ`ϋχοΞ“\Ž9°Η„Ο9€–bτ "4E|Δ *œ‰ΊR―ψB)Ψ©"Dρˆ²n!)rΚœ{:–τ£w΄({lh4ΫΥ=ŸνιmΘ:eTŽ<Ξ[O†\’^» α SK”ς΅οƒαimχΘͺιT›ζ²Ζ₯~ό6ΰ“ρ,GΪ7(Ν#½υμ+x?£ώΧωž³j§Ρ„=‡Š>yΔΏ±υ{TGfδΧPΙ=Pέ¦οΤίΟG ‰Ύ@˜βbνKќh!ΦΌίς'Λ΄kΊ}Jο§D―ή—;€xfZL7Rήrž‹―ΰ(apλθϊλ―Ο^χΊΧe ΒΏβ φέιX—N@’Ά@3`Ρ€βΏyͺuͺ‡₯τ=WJ/Eνμ›Z0!ΦΙD;Œ s3§Λ d}όφg»7.Βš²ŽΖ“εUπγS₯―ΦW4iv΄5‡θύύΓμ½s¬9‹2ΨΦ7α,₯­ ΛΛκax3#n΄ωttbϋœλ«§―ψΰΎΎ‹}ώόCΩΑΎ ΰάΑ·άκs΅ί­Ύl# ~[6oΙΆ0ς+E:χΧήίΕeU~΅φKx΄L°Λί §Sj,€~Ξi•Dͺ^£ΫθΈ<Νϊ₯²5e¬έσ‰„η‘8ΞσΜRΚΏεŠ\„Xέ0€ΤVΧd{φμΙφξέsθΨp6τθb›&—τAΒΐ¦`σ +h.ͺξ-IΟS‘+9·>C¦3>ΆΘθ;$%’|λ‚ΧΞ1πA0‹γΡ o3ˆ£Γ#σΩΧΟΎωπxv펦μ†+q&Κy†38Θ°ͺΞikH΅’O€*.p>ώα~_³`s…ω7έ°»ίΠγλΒΧBuγ)%qύτΑς;/WςӍ—πώτϋ²Oˁ˜RιsPZψ5‚ψ|β¬Ψ&ΎΣ‚‹H³β•h 5ΰ₯†™lW Νxͺ9ϊ¨U!wJ(ΘΎθe&?―Υ^ά³₯ΤQ―H½œ(¬$b|…$ΐkΦ»όσΉŒΐ­mI3—KNρΔ€5ΥπB^λŽΨxΕj€Rμε67dΪτK(΅ †Hμl5Ν  AK–4v–`Ύ<‰Ÿ*ΠηΚoEgρ-=α,0Ο]p΅{'€§ΩώκΑ £Τζ‰lŠλπθXΆd,ΐ2νΊ]Υlχ–άλŒΣΕhΛ}<Υ>—:_θwΔWηγzνξlFηώFζΙlS7£,P3&Σ½˜―ΧΒ šY δgΫψxΪ§χη |˜ŠnΪ»˜λ;κβ«ϋ²{€Π0ιΕΆY>φςΫ1ζQ±Η>GϋYνΗά·»‹?ΆCέΧ‘?¬6sHDΧS™¨Ο2ρqŸ'ΦΏ\JO½―πGβΤη RŠV‘βC"ΰΥq‹2MΌN & [ ―OŸ©<ž_πPw ΐΪ`%Ρl v܍›œ_•Ϊ/΅.FώJcq<8*¨ΉwΰRΎ“D}5BDς»ZZzvškͺFzΗϋΤΩrυei`6Χ†ΓχΨΨ‡QNŒΗ―p4ϋ^‹eΓ3Ω3/«d[ΊAe"O iΐ~Ν;ζγκάγΎΎμΛί:’νμ펹xcs{vύսُ߀βΏ ΞιN‚ΫΙ@+,u.
4‘"Ϋ{zοω§;Λξόξ‘XcΉ¬wcΎ[xΉ3O”|οϋc«}ώM0€p‡έΏΫΚiΏ?ϊ ‚υšϊL€ͺΥ+"Ε}‘X{Z ίrή<–ξνsΘ¦π‘|/Ρ§tβ½RON 3WGl6p˜TΎΥύτ§?=€ƒ΅ uΙl¬€JAsΦΨO fζ@%.ž‰XΞX₯5Μ`·ΔΘϜ·£½‰‘y"ϋΘΑ»R+ͺΈ(q±Vσ‚z³~Z7‹l‹³„δ^V‚š£œΠSyHϋ}wVρ§f²;Ώs$ϋς=‡³ΎΑi$@|ψ±Ν[EΩͺ½0κqtwnοήώFF|Wύέσ—!΄aςΫ¨Ϊ±:0”Ψ9πK~L’?+γ©’ώε9ςRυ&σ@IDATw|”ΏΆό~ΊO£uδ‰ςSΩζ]ρ«χ΅#9{b”wXΔΌ΄,Γ] ™—‘\v$\ΐ?uΙl°πΟ‰QQ΅ηJΑΫ$4Ή Π ₯]τx§₯βŒζŸXυUyΞ|Kg/‘¨€*£ΤΏ6ηθΜ\s&QDιΐUbλΘXWv|`4~t<»nΗBΆ‘N”―Έ|ζϊ\Έ’΄Σ0½ακίo”‰υ{?u_Hk3Œς—οθΙ~ϊω»³+ΆαfΫ ϋLβ·›ΚPΞnΐ)ζK˜vY Σ< υ'ψυοΛΎzΟ‘μpdθσoέā,δo.VωΓ’―ω%ψψσΣΐǟpvgF}€„7‘A  (+υ΅Δ˜β"mŒPTX<4ΤM¨5&g^ιy"τx?ε?=σj:ΈΡˆϊIάήυY|ΑΨΜ’a-T=±J)ƐtdR["ρύ©K œϋ—ƒ@;!Ψ+ώœ{”Α5μ ”~Β §OπU_>o@‹Q”%γ=ŸΞ,Ÿ?Ÿ―XsDψdglMuƒΜ χΝθžΘ.ί„Δy< f§oΡ…}L‰nˆUy`ΞύΔ΄V~ΩσžΉ=ϋwΟΏœgžΰHΎ&»>›ΙΎϊ£ΩέταΒk †Π„[±`Η: ΖVŽϊΆ?‰\βψΣΟύ}uώ}ξθι{Ώc:OόH)ž₯[σ₯β^S|υ3οΛΟVΗ½/3γ鞭ξEκΩΈoίΎC‡SΔgκ¨GΩ*u_r+όškΙφξέΪ”$kκ’ΨaŠG^ύ LPς €8Μ\ΐΎγ·Ο5€w1=3Π2νh‘ΣΆ΄Ί=†TЁ¨:Ξώ΄[Tc£ΩΡΑ‘l–ίU›9 ρ΅ή‚c€JPούΔ}ΩΑcΤΏ5{Ρσ―Θ^π¬νŒϊϊΛΟΧ$tC\ƒφrBDp έ.~²ΫΓΤνΗ†XΨΚ:8” adΕΆκfΦ|‚π—Μ2Žν‚°ωρΛόyoΊ„_³μ£~ ώ ςڜžhΝ“ϊ>]Λi«γήR^―‰ΘΛρDόΉP©°ΐ½4ή}χέί!>LY>°ŽTeΟyΞs’lί5X^jS$\ ?uΙ\H“£lxΪ<‰i#~†-@Ό―ςOBΛ5œPfιΝ τrω2ΫβO&ΠΔ(':ΊMx2 Μ “λ±Αφμα‘Αμͺž1…ΥhJΥΊ$QΫα‚u;σπχφv8ΫΤӞ½μΖ«³η^»%λg‹­…φΙ -tlν»ότ% ή©Γ§%ο;:‰Ξ;"h φ O†DΰΑ½›»ΘΟΘ |t%&ƒ”°Γš|'0ξΟη2 α)|­g機ΣUΰ,žV_°SzΊOε˜~²Ÿ8lΊlά+’=U‹-ΐξαώαNΚ™%>Ν5ֈ‹˜U”αrυCkκŽ,9ϋ§>υ©μρCψg~ζg²η=οy0ˆ§Φi€Ϋ¬Ο1;Αwν‘ΕP+λ@NΟΛH•ή[vŠ""ΉœW)ΐΊX‡$¨‘V;§€ξλoΟ`W°—=τœœΞΤΊΣ}ύόžIΔξΕo`qΞνΎo=8ΐκ?‹rŒώωeί;0Ξy-±η€ή /˜Λ2xΝΜ‘Α” Ÿσ<”³h2ΑXˆ…§έθμG_ΐ œJ΄0Οo§\‰ΏΣNλθΑ{•!ψ3πσ'SΖe8[ϋ/υyκΛ3]Σ{^ ιύχΎ\FΊχjΏ–β³?ηυΤ­‚Ϋϋω]»v5ίuΧ]ς΅―}ν€%v&(Ϋ‘~ΡΡίφ>σ™ΟτsΡΆˆ¬ΡŸΊav Αώς—Ώš€¨|ϋν·#π˜0υD˜Τ .lΓ‹wω/%r5Ÿek’:88Έ 2ΕG;̐κΰ}‘Œ§ο₯tσ¦4ίMί1Ύϊ}ΣRHeΩžr{>JΜ@"Π}U_[vdͺ1ΫيOϋΠ’KL₯­νΠλ\ύΆgCKφ…ob»ο0{ύΈggŒŸcβsίdδvΎ™ωΈ~φπ1kύ§[°±ρΙ81ΩTgg8™Žjβ4¦΄UΕ•QttvNk‚ Cδ/F}‰Ό,β‹9cπ(/,ώθGώΚύgš}"Όύ₯>N}VNKy½ZFΚλ½!₯₯τT†W¦§xνΛW.ξ]ύ—‹7!΅LίvΫmO|‚w%~η¬7+ώWŸύμggnΚ Rϋ¬οZ„Ίa©6ψ _ψB˜ώ>λYΟ UNO’xe'aκ™N.ΣΔ³,-S˜ΫӫǍΩa±S0‘Ξ|ζρ Ρ{γζ-wDJwW"NΜΘ«i‘ΣχNRΉ‘Έ"bΛΉό倓iΆ“:<Φ’ ŒW²mMA†vΫŚ֚’#wκΟ>yη~jδΔ―Κ³Ηmb![Εc(†-ʍ2(΄4B$τQ[S;]dϊBhHšW₯‘-œ`Ϋ=})ΈŒY`z’Δ akš0LύšΓ,?ΠU˜›/υ{R(σ=Σ Εˆ\#Τ§¦›ίΌΏ!ρš–ϊΖΌε_κg―e’7ž~ΰE•:Uϊϋϋη~όΗΌυώΰ>tί}χ}›Άβ2afŒv,πώ"νp°ϊ’—Ό$*κϋ©-Φe-Bέ0€Τ8ιΘ―w:Π‚MσY"οΗτ pμά3ΙN΄sνT5Ζdjκ™ΦΧηnL>z§Ε&:¬FΘ~Ϋ­‘Nfδ½AΔ—€%fEδp^ͺ£yDN·3M3χ~S©Δφ{–λΟŠΗΗΗ£Ž.ͺ΅cί0ΣubσDΆ΅u’`k/ Pκΐœ•εΓΗΗ²χ}κήΠt[X°ΎΕθ άη™Χ»ΣaΫ<yΫΫλ°mœ™E XžΐΏMζδmΞΧxΑ ½Αώ±ο}W /aκVŸ]―>Ώ} œ„™ωeβ^eΒΦΕΌ‡^Ρ'–o{βT"(ί·_νϋΞ~2 1=πΓγβ½7}ΫΆmΡW~Η`~ƒΟόYΧχκΐA^Wφ+¬φΟ½π…/l½ύΓώΚ[ής–Ώ§έ‹ΰί υp ΐ‘cΈU­ϋK_ϊ(W8­u¨ π ₯s~;D= fη©ΠaΗΑƒWΒΕιΌ3ˆΌˆ•ΟJw~£Μ½%NU’σ™LF±\δJjdFŒcΛ,ΞΌ2₯‘‘αl˜“‡½±L³|™/Γ1Hζ‰Ί3:NNN"%Fc=D*σΫ~ƒ’Zζ£ψAθΒΕΦαΡ]YΗΒ#Y;:‹ήڌριόOπSG@­ξξη¬?¦% YHYiΡΝΎqtΆΝ2AOaή΅kw0β£ΘͺΡΝ8„½gΟ•OͺΖ:α“Ÿχ„‰ 1ζDtΆ[ωSκ[Π½nΕΜ'a /™ƒ0φYϋΖ~xΖ3žWγ–kω»wο˜ω¦-ܝZzh¬Μ@&ξ;~߁αAΌQ‰φ—yΕ½ύϋχG^MΣ­ƒΟΌϊtMqϋΊq―ΈPα; φ…/lωΦέw?xΛk_ϋpk‚~ΠjΞς[¦K2€ŸωŸ―ˆm„­ίZ«P7 ΐ†œΏω曣ƒμ 0ˆ'ˆHJ/a#αP ^ΐΛwΚΏ[₯τ\τ—ΠετŠ" „θ¨#ˆxΖυG0ΗͺΧu”IHΨͺ¬ŠŒζ“i(ήΚ ΆΙ2ύY±Ό.@ζjΞ"²[jIΡΙΊΚυΓr-£1›ίΒ:•mΪ›ΝbτΤΎψ e­‚»@Αnˆy?‹~7΄eωό}Ω£ΗΖ³]Ϋ7³m‡y"»Dο֜u΅Ν^E%μQl™ΟK(Βp†*"ΣΘl;#¨>!ϋuž«ΟΐΔ©€„.ΎoƚOwβǎ Ν>q@8 ΓWϋΜΎ‘!Y'λαΟη–iΩ2λ!QκdΦgJ«uΙΔΡπ,6Ϊ‡~ΓΕXλ¦ο@qAF1ΞiP©%xΡl‰<ω‘`Λ#ΏψΟωίUΫo‘­ιήο~χΔύGτqy†x}”ψ ΩζΉ.:MpτΝίόΝ Ϋq1Bέ0€ΤX‰@1ΞN•£ L=Λhh!bΠsό°Υ!-βŒβ΅ETΞι-ˆάŽ`"θHΑBxΧ{;_΅QOφ~[}n;QΔ P#%Ξ֘Δ9¬Ž&}Oη.xΝΰχN+@ρΓ-D|άMS†²Μ¨ΘF.0ΫεΟZΉ=l}Xσ:Η·΄Y‡£Nmν¬|S~CηUΩΘ8š6‡ ΅9^‹*FΪُμΨXφTq΅Ί|š<λEΨθ¨ΥSb²νOΖ7ΫΆmΟ†•Œ8yY^ˆ~λΦήΨςœΘHGGGCΊ‹~¦7p­2(T`JK/zΡ‹ΏυΝoύ™Ώψψξ£ό0?€[1ϊΓ¨–<«―zΥ«ηX¬3ω’ύ–ΉV‘ξ€ ΅‚cƒ0@χMωH)@jτπ.£AρCΑd΅1P•ΥsG$L¦¦9sp<:M€u―Ή—QΗΞ)υ]ηΐοmΔqδέ†ͺοŠό2€nN V _Λ<·ε6£w―(―—GEΥl5Μ†]ΰμάε©Λ’\;ˆ¬Τ ΓμGάΦ;Oθϋ3ΊŠθΑL(Γ‘Ϊs0Ža=·Uγ¦ywμΨΞHŒΚ40o‘_°‘‰ώ.Ήηίά3“¦βšϊF:ο;Q΄ΤZœš˜ŽΏ«žEΗ“-±ΖΠ?ΠžΑμI§ ‘Χ2e:œo-„λ°¨ΧδD€‡ΓΚΒςOβ‡Ykͺ― ™;Έ€Zo…Αkρ†λ―oόςΏxόxωΛ λSκ(ϜχKόŽώόρ»ΰ}λ­·’”O±μΙΌΖΦ.Τ%6ޟr€yζ€Δ²έc¨0ΪViAλέ…Δ4?ΐ;'1²ύ92κCΉΖΞFO\$Ϋ T©f“γΣفΓ3ςΈٝΝ fn] #v75„Ÿ{9ަ§#£γΩώΓΨΈ£α'bNΐX`.‡ϊD½6°­5΅8 Τytt2;pτΑœ‘πν‡=ŽXΙθΓΫf¬ΙΜβ8ž„œ:φμΔR΄;6Šq.2ŽuάΆ**°•Qd VΓC†H‰―σ…*–£Cώp8ήvŽΠvϋψ ΝH%μύW‘<*͝Ω6χŽ dΫΆo£Mθν=qA °u™b.άК πl±o$F‘‰Ϊ¾ט‚]L“fΩvχ>ΔΘη*svt`,ΗΜϋπwr_šχξ;Δv(#Ώύ9μdX“³‡`ˆραάώC!ΝΙ8g²‘‘)΄ΏLk ΩχΨ±`X#HQ}”/ž™7kb­Δύ”―$2569ΚWyύυr„π‘ƒ!δβ?ΘF]¬S+i–`[Άl­<χΉΟ]ΒΞ£ρŽΟ~vθ•Ώς+m`pπΚCR8Nέ§)Χ…žύ‰W•žώβ/ώ’j_+MXΏm;Χ:Τ%°Ρ ͺ£Œ ݝΞλ ψςΐGœ±¬ΩSΨfZμ<9 ²•΅usOΟ°μΌδχ”ΣΝΘζ¨*ΠΣ·»πA`ά°ε9χ]˜γ›χD)gCΗ欻)ςϊΘ"q*ΏΦΣΕ!ΧZω<ς#5Οο61†g!Φ!œ:u’d>ΝVμλ%ΖΩAmΰk ’ˆOžχ‹q$wτw€½ΐPŒώ[6vςFpΰ£KmWΒ%ϊmΫv„ψ/U\΅]e\ΖqΫ ~–εθ½cΗƒσΏσ||ŠZ›Ώ§{oHfή“ ;;z‘"zΙΕԈVλBΈLδΫL_ZF|£§‹,Ζa‰μPΈK‘hΎk§Nd}ΡάQ››Ύ£0€…ΞΞ LιWΌο$2'’Ύ·‘ςΌϊNΗε» ί)iτ‰‘Š€VAu]‡iτZ7υ„²‹ K,`λ_uβ–Χ½ξY?Έ‚/mœ§.KHOUώήρŽwTŸόηΗtΔu λ).F¨k '4lξξΜz7jΆ2Δΐ41’(ώwΡ)Μ§Ν—ΐ·β[ΎΘ΅|bŠ7ρr-΅TΡ"δΔΝͺΌaΘϋ.•‘§ωN +Ÿ“nϝ.θ;P±ΨΕH‘M’²bΎο:ΔpκβIG,If;/ۚνέ»—λNƒ«ί½ηž*Ξ__λ­ozψ‘GΎIΩLgϋΐ5GώDό‹ΞϋY¨ώٟύYυW~εW. ρΫGuΛςN)Έm e±ˆg­ -\™VP+u^–΅ΠΙ0€6νΙf<]0ί™ςœξ}Ÿ¬Œ“₯œΌΎ­Έ·2¦?ύDΣ%Šζφž¬΅ γ›Α‡c‘QΔ,ΈΞŠWΞφFΊuš₯Žγ«νz„fΦ.˜Y/%“ΔUύ˜ζ3Α­Zc‘ir‚JιΡeψ Θ»¦xF>ίρ™Δ*!K¬fJΜ F‘n^‰?Fγ όœ€όΒΒ<‘«@‹9{‘f%7oΩί‘)Ήθ87ŸOΑ·SqΚΕAύΜ§ΔθΒ[ž;w'Ήv΄οα‡]¬\DŒoΈνo|λ·οΉη«ŒπS,tJόSΤg &9O[aξK2‹ίψίΘnΊι&G0|λ|±FώΌκ”γ] Ξ½d'±Ζ]Q™δ„C -œπBύ'ˆQ}±3Hή:ηρ 5Y{hνή‘MΛŸΛ–·αd ι>Υ'₯₯oXηΔΆ%ιψ γ1΅ακYNqΤύPμw΄qG‡ΕCξ«”W‘N σΩΟ~Œwηορ;ςKόKΐ.Vό_ύκWgο|η;,­Ϋ₯ΒΥΊcÁ;fŸϋάηB)θ§ϊ§3τ£SΏεΧ„kbH›E–ΐΘρ.`WVφΒάIj΄ξ“«πPœ °Ιη@D ΣΣίrFb($z‰Β«χΟD]Š&σφdq σd!ευΉρτ+ί+ͺoΰ@ΰσ΅κSE§XŽξ‘Βθμ±£΄jΞ¦ΜcEŽ*#ΓΓσ(A5ΏιΝoώϋδ#Fκχ‘ŽdqΞ#?ΔΏθ^/ύ/eοzΧ»TͺIΈk՞“Α{uZέ0€΄ΰηΘ―υίΫήφΆL«(Η ‘ςω?π±Xb^!\] ’OiΛΝLω.%—ksΎ1Ϋi2ŠΝb* Ήζιη[zb#3Ψμ /Eΰ&Ά,σ5Dώρ§‘τlαšϊ#]­σκΈχώџ‘ί`όt‘\–ωRYεwRΉ¦5‘W)Βο›^ΤΓ6:(ιΦ<즦« K‹•ρΡΡyTŠ›ίρw}όέύΧο>Πuψ§yo–2Iβχ¨;π:œ~ΚD ~σla/^ ?uΓΚνωξwΏζW]uUl‡©sξ(pΚΞΗζKauZωTv0Ύ₯Θ Œ\%tηόώjΟ©C?Ίήc##σίΌχ½_ψγ?ύΣ?‡ψ'™&Hόγ”;ΙUβ-?ΚZJΔ―‘‘!΅5Α*ΥχR\λFHˆ~Ύs~η^v„F%Z„ilb‡Φ€&Ξ'>ΰΚrY2,?#“ϊߎZiκ`ΞλΌ:ΕŒ[Ύί4Ν`žς{‘Xϊ“ήKIή,Λ_z.KΜ)ψΣQSΎτΜk*'Yͺy²­*Γ1=t4λίχ5VηΥ‘G;/Fˆr)η·$e¨DΤ£ua ₯ `εϊŽΫ‡ΒLψωŽχΆ%]M³έ©νΦΠ2„‡πIΜ%υ³}‘‚ΰsΊϋΣερ™ίπg<~ΖM£Ξ¦[ητ“LOsά#?+sYίςΎΏϋ»/Αύ―o§'h³ ~c”S#~Ϊͺm’ƒΧϋίώπς›pΛοΩξzuΓ0Ύ+ΝΏψ‹Ώ .<Ήϊlg¬ ηf €¬qCΊpοΘ+ΰ-ΧυΥ-“%ŸaΩ.0Ilήϋ;GdL¨‹Δκσ(ž«\ά²­ŸeJ2-ƒiΙΜΡ?ΊΔ‘Ξ»οZš₯šΗg29Ώ™Κ•4²ιοχΠMT_ύ"†γμΚ€Ι…B€ΐΗ1[±­ m“'όXOλgϋ$ΔΥΘλ½uΥ„ΫΈ0ρ%xxLφΪο' _₯;ίKφωι=α‘Ωί&ΪYX–&¦₯TΨ€>1žΒκ΄ς½qΛπg<ˆΎΈOk΅mFΪa`ΔdΗW`‚Ξ–ΏΠ‡ξϊΟ·έφ?˜ΫOPΧc<₯¬$φΧF~½ϊ°žUέ³gOΐ€<Ψ€Ί^κkέMqˆͺΓΚ Κάd‹.M3ιΦ@WZE:§ΉεLp"ΆDνΟ‘MΡ”WδA΄%yEό„tήΌΊHδϋ>σκ;"ŒΔbšΚ#ŒδΞ‡n>§7kψ½ΑΑœAYΧτ λ'ΣΠΌΦΡq­³&Žάš?–͍>†^>*ʞ#QΤ%*tΎJL³‡85φƒp“QJΔ‰&8 Ά§¦{χξ }‰Ϊ6i ”¨=ŠΑ—_~Eΐ[˜ /™₯λ=ΒO»|α'œdΒΒ|~Ϋ ŒRˆ~O7ΕΥ2Κ‘œΗΈΟύE½‹x€Ρ7ξŸHό3z_€ψΗη˜†Ά|τcϋΖΊυΦ·‡1`s”oa‰’9ς«ι·£’˜₯%ΧϋήχΎκuΧ]π“ωΝ·r/e|š—²₯o' 0‘C’±Σ܊bάσ¬3`’8lZWΛIƒΘ)Q;R‹\v²666ΚΘΒhΜ½yUtΡψEd7.κŸΟ²ςw ί0τtwΡΉŒ ΊεZ~ͺ«DοΜΔς©υŠW‚¨$,ƒL)™”ζ’#―e¨2«Α”{ώ cΩΰ#_Α1σώω/\ΧY΅`šTRΟ½[7Ά³†ΡŽK”$Υ|sψG’ΐΈ€~F[°πͺβŒΑsΫ(ρϊπΙ᚟zcί ΅ε§°–4Ν SωΫoΒW&`H}‘‘Xό±žεPΞcάηώŒŸiδWμGΟ?ΤΖΖΗηwοήΥςιΟ|ζΫΏυ;Ώσί!ώapΣ‘˜Ÿ#XφΡoXW«29ό~θ‡~(h=Žό Nu7°bΡAt’ΘΕ HaΗ&",ͺ.֚ΜΥΕ1ΜΣςQQό1 „So[k=Β†}}ΗQ(aήMΉΪͺλpΒF¬ΟTωωtfιȝXωe€mΔβΘΡ^?ύUž4•@υωμ˜ξΔς“kdZ*ލŽθ©7–«ΆZ}ςΙ(,[‹·ό›9RΖ 9ΑΈX{@υTEσY·Ιρ‘μΰ=EoΫ鉄Ώ Vθ<Ν ¦£ xΟνVpΐΊH4‘‚Λ·„,Αξ!=Ÿ:ιΗ 5aσ {’0$žٌۿήkw?|8·8ά†ΑLΩ–I€Jω§θΔdjβjB7}ušίHΑΈΟύnρH£§ωi`AόΝ=ΏώΏρ&¦.CΤλ8ε$βwδŸ—ψωUaxU‰ί…?₯'·Nύ¦ψXαΒ #kΠΊθ €ΧΜ’T8£ΐ*π„+έ‘θ'5lχU\Ινχ›EΗqL‘­Έ£΅εlζI­ YνabC»ŸτΙ濝ςςΈώ)“LϊP-unfͺζΐ“kT‘ΥHfbb,¬ή6ΰβZ«9½ίjϋoΊ€uΦΒΞ²ρϋL:Ύ(k||υRN΄₯N‹σ$ŠΝωiJ(–­Ϋμ™Μdό'l&σmΏ5XυO]η(/avrζίΞ^Gf—zIΙJ$ŽΔ’ρ> ”š¬£šƒ΄[ψ‘Ή9==‰ νgωα·X4±m)ΌmτQHUΐυνd――J±’ŽYͺ\•œ5]'Ψ„•΄£>ΎαdΔ$ž”ƒyR0xt–Δ―Θ3>11Εξέ͟ωμgΎsΛ―ϊ› πˆΏ2΅ιwδβη[τAr΅ϊΑ~0ˆ_ΙEβχΫυJόΒ¨.%+&Πό)BΖ–|d| ‚Π* njύζΐct2φؘΰ―π#λ,vδRmp!jnϋρYμωχGŠ€#,ΠONNg£ΣŒΈί‘Π{οΗ~~©‘…,ϊ³–ΞC05σ8 Q_)Κ}τ¦aCƒγx’Ÿ1ΈΩ’ǏΒτ"m9’Οτ46χ‡Y(dΒ66ŸΏωiFϊ*°:¬ruάiŽkΰ™ raίoŽαW ? ΧΩεφΏ‘ˆ{_ε{γgCό!φc‘³«°v4Εε—7ςSŸΊηζΧζďTβΘ?ΔχΓΈ‡«ΫKzμυ«αχ?ρ1mqϊβ·aεκΥ]Ό.€μOqYe”φVέt·Ε(΄’Ών{FρFHF°„?€ΨΜρ#€έ½A;­H€”Γn@Η8…j₯y˜ΦCΎ€£lŽHμ΄aηO]:Ϋrύρ–HX|Gϋρ؏·ΌGΌΟ™XBBΧd&³3­,.ξD’  u"‰yr‹EzCsG6rψۈe•ΪΐΘHEς ―Α_K–ΉΚdυF|έήήμΪ+G8•™ƒ7xθhΏ?H1=,N:΅jG2ΚZσ:U«ΝΩΖ+hK>/sŠΰΊΒFόΨΖv`Χƒ7₯d—ίΡ†{φΘKο°v ₯pPϊ‰ύxήΡ…˜iϊP Ψ`_LχWε{γηDό|ΐ‘ŸνηζO|ς“kω!ώΪΘOَώaӟˆ_έώW£γ―”τD!~aWw ‘Ξwθβ‘©8Ž) ΈΌϋ‹n·!|wgvΗ·†ˆ³h‡ΘΎ‘]"oγ(ξM8λθdjΓZLΜfΛ2$¬«k1jY'ΓκΊ™ΆΈΘzG '?πεlτθ±p)ˆίΊΔcG]]„½ΰ™]Ωό,‹€8C@±j'œΣΈBwΟώHκ³itΞΫWdε2c°ΜΪsαRΐ&OOD !σ^‚SŠη5[ώλσŒŸ ρ+φ«ΫqUejzzώκknοΎ~ΣM7»Υ7PŒόŠύ5³^ΎqΪ‘‰FόΒΞρ²‚xuYΕ~ΥI]όaA&F–ΚβUτ?Γƒ6μψ¬Jς†&-γF}΄―„¬Q‘4RpUΜmb΄ŸdήίχπˆΨ,–­αŠγˆ·Ϋ¨³¬ςoνnʞΎs!{οΜέψge…Ϋ-.u쏀X.·Lœεtγ‰θΝSξ&» – ¨½yΈOύ&ž€`ΪΩ?{ταΜƒΓBζ―ΎφšζΏyΟ{ξόΝίϊ-Υ{Gy¦nY‰ύODβ~u#Ψ‰G“Όΰ‘ –¬U ΥΠg†”7z•½h+°)rΦρΫ»κwτΑ/3ƒI —21REύκΟ±Λ²·bηϋA\“‡εxœ΄“+6‘DUdτMΡ—Ίm ‚/β+ˆ›š?zήkz/₯—ڏυJω„ρs%~vζ―ΉφiΝο~χ»Ώ ρΏβQ½Wβ§hGώΗ5η’Ώπ« qtυς9A5bIΰ F«φξ †kŸE―η“D1ǟ΄˜‘ώ§c"Lt˜Θ–FaŠ8ΫP+§τβ i«ΎQ~nάQΝώ&ΆωFϋΚ&ϊχ# h|sρVύKΥ?iT©•ΨΡޘυ΄-dΗa*<9κ·γͺάΣ‘Tئ῏«m‹ΐ΅,Ύ›^ϋΙόKωγέR>Λ1ΝΕQƒε₯`ϊγ%~Ε~έx±^α‘]σΧ<νiΝΈδώηηΦ[߁ΣΣqœ{:ς{rV]šož°Υ·zΑο‰LόΒ±n€•1Pχ‚βίό›ΨS•Hό9Χ\μX;αƒ’F ‡ΙΛxεΊΖ "#–Ίώ™hl$%ρxϊ†ΘezC\ζΖ,θΆ';y .Ώcώtοκς†0NaR™εηyΩKΤ6ώ.Œ‘9Rκ史ˆc΄#p+‹~ΪOŒy"ŽBc+W5ό\τDၫρΤvν1Τπa# έοόEήk―ž°oί>7EIHpρ=aνΟΈRFΊ—ΨOPοEy k7T8’kώZˆ­o}λoψέί}v Φ™ˆ?φxpGΜω](TΙΗ}ώ΄ΥWn[ͺΣρZ7S€2πDwΌ θˆίΜAψ  Ο₯"‘¦Lυήϋ³ Nξ/bΠ™‘Wΰ~mκDŸω3o ΖMσ]γ¬Zƒi$’‘¨Φ›/}O§‘"‘yEpν RπΫκ†αSgλAfξ!4β¦Η8²»ΫSͺFzύ’^±•R!Θ“‡G8ϋod”ψD„ύ#χ"󝻲1FN‰DηζS 甆ϊΥύΧκ’ΰ©ž‚νWΠ)ΐ'πjΏ/σσ¨­=Wξ Ζ&Sνηgξέ»7ΔxGa‰|?N DΪέΔAΗ‚ρEϋ!~Ρί€ΒΎκΞφ£ Σ`ZZT<έΘ/3€Ρc[ρη@ίsΥήζΧΏώυ„ψf5IΉ‡!ϊˆŸΟT™Ί…UŸΔο v:dO¦P@ Ί‰πϊ €·βǟfψ—ΘGg‹hŽ:vœ§π:ηχ™σI [ΎαΒ•ˆ₯XοYχ¦mή”Φ*! 8’iο―q‹ˆ©Y¬ˆ ε›ηΦwl@­o=žœ«]ϋαΓ‡γ[›ωŽsP% ƒίˆιuΨΐ鹞&£₯‘¦Ικ/Ψ *θίϊ E•ς‹0­Δ|_"΄ΎŠεJXZύ)&£[šα{™§ΜΝ©R‘’—ώτ%fa₯}EΉ^0{₯Ÿ\Rβδ€Λ,]G±Ώ ~[snqC¦?Κs~‰ί‘ŸuΦ%ζwcΨσλ―{έ{ϊ=οI»%~}ψMp ~Žό~<©™τ>Εώdρ§ώ@A¬D,e:Šz Œr\$Xy£ Ψ°W΅:QE‚ 9"θΜ³A W( ’Sί½‘}sG&ŠQ,7νΆyΎιwΝ―Κ«ˆη{ϊ π@L.ςž}'’€’°UΞrΌBψΰd/1X¦gοω‹ς‹rσΧρ_ϊA+Ω‡EUu!fOΖΎz/ω‡#½ŒmςΨtΊύh₯6=£…_>ͺBΤ2ςΉπ§C‰VψΛτ™ΠIήnŽkP&|€πγ*Σ±jΔΏΈT9TρΝ°ΘY†Ν―zυ«ίύ~πv¦€T;Fώ²ΟypM4XAό2±'£ΨŸ2[S:8†NuήθΙ«€Λvϊ«}`ϋ£hΑ9‡ώτΠjk½6υγcΈ™B“mϋ|ο΅οoζͺ†`DόaD\…MŽƒΌEϊ¨ύ΄_ΟϊI—²MXšΗϊ θΩ(bηφξΛ~¨ωΒ.žrΪ¬£e[¦y‰η̍N‘Κκ-P'%$uζρ0ΗorjΒ_Δ0¨‡υŽ66žOLŒΗθέΫ»8 ‡ζΰπΕΘ&Ά7“ί³ττΡΰ"’πw―e”…E%­f΅0φͺ"’R‡}ߌ‘~Ϊ‘œ‰#T-Uπ/Pmλh_Ϊ~Ωφ†_ϊε_~Δaˆڟ9~Œψ—Κ#ΏΔ―¨„!>>YCέIێVτλd€τ:§ "”ΫΧ:¬Τ ΈoQ1j CFj ‡όθ β*τηΨf„g› ‚k©dƒω\vlfD^Βp,ΞΝ’ή:Δ3EV―Ζf1zλΡw–8L‚obn˜2η±kίΗ‡0γ₯Ž •Ιll|!{τπΓ|”£ §ηY(Δΰψ ΗHMΟe³‹x ’>Μϋ熲VόŒqΧΘδRΦ?ΔZνΛ€΄z ΤŽcΨ†FρœΊ6Rχ1N ޜMȎφγο)N΅QWb•l _Gο}FΧ> πά΅™ώγ£ΩcGB¬ίΌ₯9ν‹u’`#Α)ν)]Μ0}?t Ώ ˆ±[B_$‚ŒΡήΌiδ'ŽCΠ κJ•~YB­|ι^ώώΩwάρ9F~τ~¦ϋ5κ™D›₯¬4ςKόαΖ«μΙΗo)΅=™Cέ0 Ψ`Η:Ÿ~μΰΑμŽΟέ1vd7<ϋΉ1ZΫΩ5β—ZΪ8΅9kžfE‡ ˜€)!Qd\φnΡ»εϋR.b64vΗΩξγ sράωηθ<Ž,62Rα.,¦dΟZr›φbΔΧ†½»φνΨ¨η₯Q"ˆ²‘G!;zσ4ΪβΧzz ⛐ D&C—ώ |Ξ―£c[Δ¨Γ, *VΒ ζ™λ쏀k*ξ”tl莹3’WWwύ³%χt‡} 6\žŸε Μm›βΉΟΊ―ΪΓ5‡‡ v©Ϊ0•ιΚΰM‹o9•ΐξ •«R’σqί–!ϊS^bŒΨ|±Za]aIseΞœΙK_ϊ–;οΌσ‹!φ—‰_ο½|n©ζΓο©Fό’Wέ0€Δi»φ8ύί―|%#δx†φμ‡ξ»?»ε¦Χd[Άχ2GΔeˆˆWωhί 2‘–­ς*Z™©΅ό ;ΫΪΣ–M2ςΛvφ^YxŸ΅`ς₯¬άΖϋ~ΤHQ¦&†Ho!₯E%#*€‡©ŒΘ™7a‰…Ζρ‡ΠΐϋVβ]ΕγKz‰ζ[uj!K„8όόFΒG«ώduΗ\tωπ‡>„묑μGτGY™ί 1ί»μα^yΞƒΰD"ZPAŒw*ΐ°Α507uۊ›”X»ΆγΨ’ wΦαj bΕφ|9κrkΖσkmΎ^˘žΥVδOοεOSYήωυ‡gρε'yήK7 \tάαΌ\8ι8Τ…Ώ Tΰ5‘ΖB§°σ9ΟrͺW±‰ώ‘Π‹8σ΄b4‡ΰ$:ΛΘ―Ψθ‡/ΌAτ[˜ά‚t+ΕΒΔO‡@δΒΡ@ώџ{ΙKώSςoΈΥGΊJ>ΊπRμχ Ξ ~κ^έ»woΪρTωfΥ HΤΆΫƒ ΐΆŽάΊ’=sχƒέ"Šω Hγ σ}β—€€ΗDΔ|Δμ Ρ3^2ŠςNSΦς§¬Μςέi^Yω(^γOρͺ“κ-X'wJ„#xQSψ2έΈζΓI[Ρ=§}z‹τn(Θ4Ιc_δg²mΚ‚Ÿ>"ΙdR΅/pΧΐΰ„!'~Χ TžΚ*¬Ν,β7’‘-ΙAΔώ?yΰΎΝΓ$Σ‚£ύ$8εέΞωγ N§ ύG?ϊΡͺgFΈ-™όž*#’?uΓbD BŽ*?υS?•=²o_l₯©UΖn8Ρ₯!ω’Λ) pλΘαΕ v‰™Εm€ΕŸTό}Λ²°S‡ςgDΨ³Τ7―ςyTϊ¬?zn/8/N„“Ώ˜Ϋ{u/ξˆ›‘Ϋε||2½_‡i/Ώ/£° ŒξEY^θNρ_B•@en+Ί 855½pΕ—7‘Wpμ₯/{Ω3}Όβg;ςy§NEόŠύ.β› Ξ~©FόφCέ0ΘΰΦί³oΈ!ϋυΧΎ6;ΘB -α‚Œξ5§­φγιhΏλ·ό7ˆΨίOi‘Pό1―§δh ŠΘζΥΘΗ2 ΉόΎ.³pEέjGύ%)¨Λ―₯Ρ0ζΔδ΅*{˜~Κ_̟OςΌHΟηΥyΩA|EY‘Nžόθ2Vφ#ΎLˆ*(9£Λ¨›‹°ΆΩ[œ?ϋ x‘/oπ ΉζιΞέ >KύaήH+2αιΥό.ώJόžΠ‹έž{'Γ…Χηω χ½μe/ϋ/33Σ‡θ—AςΖΘO<άvσώ#ˆύž4ύΩΟ~6FώΌξυyPgβ"©?  €`g2δxWi…8ΝZ QA³\ΩΤEΟυξ]G0HΘε²Σ½iŠήλδ"Υm-RdLοG!Ελ©Λr§-š »°δH8Κ6¦εΉe‰ΣɈ{RθoΊ:σ­κ4ŠYάψ¬¬­·‰Ί.eΗϊŽ…Ι죏>ίcτΛ ς ˆ.Ρd@΄Sθ2hԀƜυŽgE,rσ'ζΠ<Ρ¨)ˆ‘ŒΖέ8χτž/»ΥFEcW„β)8qЦ/@Ϋb»΄x XΒΠΒN€Ά»•›‚°”‰«1)ƒπ^ψ¨U)ƒz’&%tƒΜa†ΈFVΪ?v΄Š{τΚ8n»―ΑίΗ>φρ{^ρΚWΎ‰ςΠΰέκNλΡmχ’ΔοΘkΏφk^ͺΒΫr­«uˆ:§J>…―uΗDΒμ¨tZ qzΰ50Η+‘Y˜š€n5εhl2DΖJ±¦ͺvΌΘι衝m-Ψ΄ΧΧ±fΌiHdΪλ{/οΨ±#L5y΅‹&Β"Αo8‚IδjΗq„t0ίw sΩe;P{=žb)g^ΛΤ,Y3Z•œ$BMc=²l ΟΖννTŠfέδ,miμΘ&˜©F<ΑΉκΪKΰͺβz4xeΙ,fΠ«χγιyδ φιύΆŒJέω)μ(„ˆίφ˜rExWΩ%βt ‡†;νθ°¦ˆ% ώρ£}Ά­ω·eΕi”/ eˆž ΡΖβω4yφL@a#αΊx›ΝόZ nδϋzRγΟ²½ͺˆ£‘ΠαC‡fΣώŽm·<­ 1βͺNŒOTπ@ΆόχώόλknzΝ[XΌσ„^κsoΝg?_€ύK|ΣίμχχƒψƒΩ‡T§hΰϊŸ:XVξ!-BL,ž‹l§ Aψtn"ώςΘ/"Ή‹ ρ8πhψPΟ\„pdrd`U9ˆDO»φΪH;‚Hο¨5±nΒLΈk΄#8Έp—ΒQIβ•°όͺuS}Y?σX*ώ[ΆUα(°]A|Ρ]ΠΜΆφn ¦α±ΨΊκιʏ$—qx4X7Φu]m(Bq:6l!ϊω£)y%(ν 4UΦΩI‡«δSY;Gš1?Ξ6pψH+*»2·¨£ `j:Ύiέtλ½uλ˜ΕBŒΊ9γΟύwGyaΣΓq^ΆgΓacœƒoΓ\Ί †₯tcšR’Ύ’M,νέ³'κ΅ο‘G‚ΙIΘ!Ξ«1,'5ƒ–ωυnνenΏ#;zδhL“άζ³ϊ~†Βΐο^~ΕΥ‰±ρ mœΏαΩΟnώσΏψ‹―p^ΔΫωήύζQ]eΟ½ϊο«­φŸμΐŽuβ?‘‚κN°Š*œˆ’Ό£•χiΤ]Ρ©τ^yΓOζ!kQeΣΥc b]Αw˜W‹τI4QuΘ €ΦΡ‡ίνΖώί°kW>ͺIπ–!ΎC™νh:‡›,ήΩΥπsδΦ*.!ŸΧΝX!Ί> 3ΡΜΥQV»ψ–Β\6ωΨΎύ²¬[{5ΰ$r% ½πΘ%`œYΒ¨Ί!j¬νh«Δ­i†Σ‹Τ6ίι… GGΗβ»Ζ­›e ƒŒm||Bν0σeΥάοψŽπ‘™ͺ‘)lB΄'³v2#a&Ιϋ NšcΫvΫζχΈ±nΜ†9½Ω:κ³aίώύ01ΟrΜdΪUη¬άwοχζŸqέuΝo{ΫΫώω?έz«.ΌΖΐcd¦l=χΞp=)ρΛμό^‚}ΌώgκŽˆ0"«b±„oηρ?gΕΚ$0Hrη« še*9©ε™#¦‹WŠJ aΧrj‹™#e 2χy Q½f§O:―‡Hν~΄Ξ/­Δν5gωw\Π“Hυ„c}U`ΚΝ^a ŒΦ…’±sη Η™νήέει;D¦c{(Β·"–wΑxΆ²¦`P%j½ρŸΛ±e’š)oΖGίJ)cψ&ŒΜΐ=n%)ΗDhιIDAT§(ϊBΨΉσ2 ]Φ*τaΰΊ…Ζ;N‹‚)ς}½ωδΔΎ5Δv‰Hb„lγpPG{ϋ@"Ά2Wλ$cr{ΝυλiΉͺφΪ'Ή~?L€†ΔγΑX‡ιLξsQfα»2¬Μ‚aΥ§=ύι˜δόΞΛw7χ·Όε3ωΆΫώβ/;οLn»θ‹F~™«ΔoΙ`ΦΓΙ!P7 @‚2ˆ ]ΈΟϊΒΏ˜}όγqϋί½θEΩ>η9 œκ’ωH#½ @O6`€’!ͺΚQηη9›Δl5φLzmΛΕΚ)Dε)z’Ά ,žΟE^WΉU9nΐΜ«@,υF±ίˆAΚΰ@ΆQpE;ηΪε©€Ÿί† |ρ>ˆ¬w» PζΞ.ΰ‘_bœbnνθμθ/αl†1L2EΙύΈˆσ Œmτ?ΨΓχ(Kι £›yˆFB•‰;v#œžl‚QuqΛfNΉ"Κt}a[t׏αΔδ1έΒΜυ+ΘΧUxοΡ%™σw}Θ¬”΄Ψ_2Ό­[ΆΖΤΔS]χPzr^/€-Ηάέu„yΰ£DcΫ”(τΕ`›Ϋ·f °ΊδŽeσ-" JΝ‚u%Φ κ±ΗΛv1Uή€ιM)c΅βζ?ώ“?ω(ΏΏψυί§9οΈ’άvŸ’ψ•(Φ‰_¬<}Έτ ΐQDPβ_8τζ[n `Ε`£jje€ι`ήΦ€ Έ ΓD['½UHs>’§‹LŽ’γ ǐ&ؚ›@ŸbAψ sΦ‡9Λή©ΑN@ρ QO.‰=κ)lΣ§†A’*£σοG%F|φ7LΕΚ·Ϋr]CΉcPG˜„lΣ‹xbρξώ}G’~“ΣΥμΡ£‚h:±•Ÿ―(‚/e9ΜΞ‘Ίρψx64:›ΝτygW6Λ‚ήάΘtΦ²aK6:5—υαl€•cΓHΐQ=RBkwv°o8$…φžmΩωΫ{²©9\v΅oΜ†hΫψμhΦΊa+ ²#·‚G'π~\mΙZ»(W€ƒΆUTGŠβήζΞMΩψΰυ„‘1Οo`]+Εfʝΐ·Β4λ ΤƒjΡ&]‚ΝfMΨφW+νΩΓŽD·t0ͺ6MgΗ‡YΥ§{qΚίx ŸΓγμ–Μα0τgoΠχ2ͺ鑉lο]χWΊ:[³g]yε₯h‹²jiάOΟNH/ε/ž ‹νΈΚόΒlΫ…El0Ωώk~Χ;ίωω7ώώο•κ§―uδ‘9oυπNψοCRHΔ”vήYλΈ Ή¨ Θ!bˆGK€y],DύςŠše… ·G8΅ψξ›‘ΑΚ|³K/εο ϊ&–‡Dπ‚F’i)½Έ~-½ώDΈ*rŸŽ™9\)$β]}Ÿζωi1ήρ]a”δyǝHμ!φΗwΜΟOυ`§,ψ-¨„¦d#φύMχέwίρ›nΊιύŸ' ςO‘1„˜zύ4ΧπβΓ6―/=e}φ§ΎYΛλEe"ƒ―βG‡»β€±WΘϊ,ώΈΨΣPe«€>=MF dΡW ΛNc‰—C¬ε€Δ’ΑŠ Oœ›ΥΔ|²šƒ(=X& Άx υ^b7­€]ϊFΐ‹η¦Ηoε}œΙG?KτM¬Π£ά˜νί·oμ­o}λ?sβξ'°|‘ sZτ‘Wεž‚pδΑ³Ež=εέv—ΊlM’…ˆ•| ttΰQχs%έIsb=dΑβT|ΑezΡ—NvσΠ·OΟ.NWΒϊ³ »5:f V%Μ\sμ©»ξΊλ0ΈξF΅ϋ.ξυΫ7.θΈ3μψωτ4ΏYΊ#Λώϋ~ψ‡8{Ο{ήS½ξΊλ’<€…(’΄xͺό”/β’0€œή΅m·ŸCπ’8°’θ’α]οzΧν_όβοi0άkj’0f²Ά€`\ΧΓYA υΝκ—ο=ΥσΥωkω`ˆσKœΡ7ίΧΧ7r`~¬¨Fr‘Μ9ˆ˜GsCδηήE> _'ϊό^bXͺΛ­’ a2Ώ±Nό«!~χ!ͺ_g~ێ‘8©%{ϋΫίnΗV ς&¦†-€·σά£_u—£-¨qumeNi\?3 σzΈδH’W§vώ– ^Χxf!δ1»†<šπ:εSϊ S^ž›―Κ.@υ5―yxŽ<œ:ψK8Dώυp!°ζ uœβ ΪZο}ο{³_ώε_04ΠΩψΒhh)0kξ’£;iφ¦™s‰}\$ΐ„Λ‘|'sΎPώNL€n]β”οE=σJμAπ|KuN‰ήϋ%ζϋK0‡ͺψρ‡ψ‡Υ[0_ω­[Β‘ UΗυr–!°ζS€„\trtδώΰfžΖ‚έ9 Λvό–ζΈVAΓU“ψΛβ…ΓΞεv―ΗΦ‰xurζNk=θU%ό˜ϊqοˆo.)°ΣαObΰΕΓϊΧ»Lά>φj')Αοωά°Nό†Kςη’1[+¬ξ|‘%!†yVί›ΆκiύΖΪΩ‡Jmiδ/Χ8υοκΎ/ηY_\R`2_G‘πδ λ}\Ώ}zΙΐjΠ”‘eυ³υϋ'Φ™z}χYέ1€ϊΧzνΦ!πδ‚ΐΊύ“«?Χ[³³‚ΐ:8+p­g^‡ΐ“ ?Γψ‰oR€? XG‡ŠΕ―US[Ή­ΖI“₯νJ₯ιΨ*$δ:7‰©ΫιΆͺO{7ό@ΩH§kk?μ<Κ»ψΞνΎkktόqσέ‹mΗ6°nΖΆΒψΨ―±-όmR;`zŠ–‘ΚπvΒ x#=\Σ% λoΰYΠΪRΪ±£₯κωΠ#&Α?Θ>ΜΉαΠͺώ’ώ©n¨_¨Τί;j„;¦$}*}+ύ(}'}/ύLŠtYΊ"ύ$]•Ύ‘.9»ο½Ÿ%Ψ{―_a݊]hΥkŸ5'SNΚ{δε”όΌό²<°Ή_“§δ½πμ φΝ ύ½t ³jM΅{-ρ4%ΧΖTΕ„«tY۟“¦R6ΘΖΨτ#§v\œε–Šx:žŠ'H‰ο‹OΔΗβ3·žΌψ^ψ&°¦υώ“0::ΰm,L%Θ3β:qVEτ t›ΠΝ]~ί’I«vΦ6ΚWΩ―ͺ―) |ΚΈ2]ΥG‡Ν4Οε(6wΈ½Β‹£$Ύƒ"ŽθAήϋΎEvέ mξ[D‡Β;λVh[¨}νυΏΪ†πN|ζ3’‹υΊ½βη£Hδ‘S:°ίϋιKβέt·Ρx€χUΟ'D;77;_"Ρeσ?Yqxl+@IDATxμ½k¬-ΙUηϋΌχY·ήUvΚmcƒ‡6’e,#K#΅δ±Τƒ„Δ hΐB|/|žm΅„|% AB`3ξi0―Ζ@΅‡φ£ΚΈl—νͺrΉΚͺ[[χqή―=ίΚ\ΉcηΞ̝ΉwξsΞ='γή}"2k­X±b­‘‘™½~ΏΊΠq γ@ǁŽ:œ/̝―ξv½ν8Πq γ@ǁŽΰ@ηtrΠq γ@ǁŽΞ!:ΰzΧεŽ:tθ8Π9 tθ8Πq γ@ǁsȁΞ8‡ƒήuΉγ@ǁŽ:t@':tθ8Πqΰr sΞα w]ξ8Πq γ@ǁŽΠΙ@ǁŽ:t8‡θ€s8θ]—;tθ8Πq γ@ηt2Πq γ@ǁŽΞ!:ΰzΧεŽ:tθ8Π9 tθ8Πq γ@ǁsȁΞ8‡ƒήuΉγ@ǁŽ:t@':tθ8Πqΰr sΞα w]ξ8Πq γ@ǁŽ  ͺ9Ποχ«+t₯:tθ8pΧp Χλέ5΄ΞšΠΞˆ8\dμ;a‰Τ%;tθ8p—s ―ηΟ³Žοε™q—mcςγώηαθθ(μοο7†Ω5θ8Πq γ@ǁΣǁΉΉΉ°ΈΈ8DX• ͺx/Ξ΅ΐΐΗFcxxhy”ΝΟϏΛ”K:t8(ZΤαΰάˆνΒYfΜΉtβAΖθ#ˆ›7o†Ο|ζ3aii)s ΘίΫΫ .\_ωΚWΒΗ>φ±iς\ˆΞ²ΐt}λ8Πq γΐiβϊ½±±ήρŽw„ŸωŸο“&2_Μ‘£ο½χήπžχΌΗς]_Ωڜ'ΰά9>°±ΌΌœ 4ύŸώιŸΒoφoχ._Ύ^yε•πΤSO™a§~:tθ8ΠqΰξγΖ~ι₯πΎχ½/Όώϊλαέο~wψΘG>žοωžpνΪ5+gσ@L8ˎΐΉrάψγρω ?σΜ3αSŸϊTψƒ?ψƒήΣO?`τ\XˆΣϋEρ±Ρξ±€»oώwwθ8p~9ΰϊ»€ώΓΫίώφώόȏ„ŸόɟμΏλ]ο χάsOΨΪΪ «««gΪψΓƒsεψͺee%loo‡?ϊ£? Ώψ‹ΏΨΣ`›€`μΉο/η@N_m^^XΰY,<]Ίγ@ǁŽN5²E[΄¨#EvvvΒΒΒB888ώπ‡ϋΏρΏΡόρΗνΪЧΊwSw._ω3ΠO|βα—ω—{Ο>ϋlG(0φ=9 nΰ-6O`ΐ`/δt©Ž:t8­@gέΏ•=0γŸάΧv?Ž@ζ °ςρρώoύΦoυ±,YžΕp.Ž1ίάά ϊ§~α~‘§€ƒ»»» l½Ε€ύηeΊ&ο!N{^wθ8Πq γΐιΰ€―ό=†*3φΔιοH:ήΣ}ϊ>η¸໏=φ˜ί ¦ύ™ gΪ`\±ι ζΪΪZψύίύπ³?ϋ³½‹/φpXν+°ό7ƒ―ϊ€γ_ζ€ωωΑ€8―Χ]wθ8Πq γΐμ8y°]»‘gG€41Fΐβ4ΰˆ'»x’@gϊŸύμgΙ³γͺs¦Β™u0Œ?χπΉ·Ε/~1όΐό[ώ=n¨œΓ~sι–?ϋ;pތˆΐ΅ηe‚ςά!PBgτ]άq γ@ǁΣÁΨpΓοFŸψ0ύaό=Νξΐ‘~6…scncNOw'£δL:Ξ žιd°nέΊΎφ΅―Ωc  ‚ίχw#x?δ‚–ύιOϋ½e'Ϋ8*b0ύ7΄  |N}"΄[DPpŽe`Ct―Ι³\ς%‘G7 ² :tθ8Π ΜH‘£ίψΖ`1ώnLsžŒMΰΫ·o‡ΏύΫΏε0yΠ-bU“·ž5³‹»πΟ™s| ό1¦ͺίπAχ]―—τΠېΓδρAί^Œ‘s7΄γ΄ΣΧk©DJꜘύΟ­BOŠŽΔ•KXΡ—QΓ7©}LΛV¬9ώ QSΦΖ+΅-Κσϊwk\Δ‡’Ό|ΚxQΦΆ¬~n‹Χ.›:“_.DkiεΗb: m‰¦Œž–ιΐ€/λΥοι{νt]’C€ξOφτΣ•Ώέ>ΈZΙ†νμ‰šίυαΜ:ά x¬$²• dšζڝΥΔ·L\Ρό*Κkν¬ΐωφΈΟ)κߝ'H—Ρ1όΨ‚+W―šρφ]]ΕΨ@~ u€:q•β±²τΨ@²˜ΌλWώΦύ9³€wΟO!Dώ󏝀Έ ς Lμd!MφP#G^#69φ9 ΏόPέqH`N °NV RΪνJiGι1ušIύf8DK†#’Αp§τ‘–ΛnΨ½Η–©? ΟhGx¬™σ'†‘―CYQ=ςγΊq:_Ζu>”ΑT½|ŸσM›\75osDUΒͺ³ͺŠωS–ŽqζωOYάΞλΦ­ηυkΔ(ήο‘8Εic‘dεiΪςΣ:ήΞα΅»<8αULŸα-βUΫ žσ‚Ψι› v€C|Ύeέv€ϋύ ™@Iš|‚‘ 8FVjW’’»ψο™w Vν €Ίxΐql )π ‘73¬CJί֎…Μ-ϊΪM[ͺθpFCKpΛΐŒΰ(Rt‘"ΜΚHϋ2Duς} «κŽ«+Ε8‡9NZ?ίί<˜i―[ε_bŠϊ•ΡR“7Ί2>ΗpβtΦ° Q·^AΣ²¬¬_Q…ΈGFκΡ/Ρcω3 +"'Kζip:ΙΟ—AΫqηΥ π’ΡΎΧtίY`ώΗιπΨσοΦψΜ;ιΐδΤ―|.Δ•ΟΟοΔB§+x‘ΰ˜„₯3¬Ώ:ζ_;ύΛΊΥ°¬;κ•[Œ#₯iψ[έTD‹·uš<φόV§ θΤυmŠΎ΄Ρ΄?ƚœx\βtL .γ²cNΣη|ΏSUPχαιuυ,τ0‡Ž‘&Γ,ό™ ΄‹ΟΟΑ“φΞz<άχ3tu^·h0Ι‹ρΰ 3ή·}x$i~nψKή70Γ.h7šzG.…md ―‡AΚsŽ1Žθˆ±ΒψSκlI—}’<.‘ιnΞβgν™γ²η1 9E§Έι£χΣχmΜbzΫ5~ΎΞ§+γ΅ΣtŒτd4΄‹ΫΩN«!G{βtvέ5uΞ‹ΰR6δϋΟλf1FžU?χ0ϊ|&’%όυΞΚ”φΗE²†qBν ‘§™Μ££KZύϋfTaε`΄O”΄j k`­’£ƒ ΠrbτŒR˜δL`πO]Κϊv†σΛΖ 3VU}Ϗω)qbKD?²ΎΔs鍯³Πy=BΟ1’Ρ༘7ΰ`·ϋ\\; οφ™Ο‹hœf`γλ8 Ί^`ƝG 767Γɟ„/ωΛ|+:<όπΓαο|gxpΈtιRζ$dS!-L%f…μp0›YN|b€ΝKqOΎV³ qθ9šb"ςŠ?.+IŸ8Ν%tuΩΕ(―±Σ«H.NΨ)π~ŒΠΟ±ιŒ`1+r&ͺ]NΛ1α4d·'¦Ην ½η\ησΌμLΔηΕΘVΡΐϊ@{lmXρJπόηsΟ=ώΓG?ψΒ »λλλαϊυλαλ_zxξωηΓϊοώ]xTυυά`>9νΨ¨ΎΰωJ5―}ͺϊ”j",¨Ρΰ₯Πrbτ8EŠέΛ β§·€¦.kzλˆaΝ£ΙΛΞ 8ω9ΝCtϋΌ›ήζ{?φΪyz*ζύΟ³Φϋλέςλ3Η;Mg²ƒc:Uk©€oB‡ώΗτ]θπΨc…xΐV>ψ ΕoάΈώρ1l©ΖΏLͺFθaΦ¨rQς}ͺy] Νμ‘£LώTΤΖ; eςΗοJH αβGϊDŠΫcpΎy<¦zW|†8ΰcξρΨΉLŸP€VŸ_C$ΜΕ‘ς^ ρΟι˜!Ύ=lσχxΘόrΰoύΒ…π‰ς_ΒSO>όq»°’ΌU*xŒ#ΐK"^xα… WŸˆϋVaδδo_ χtΑ¨ Q7ˆΡ$sβ£RK–εηλMrν!γΆ”ΐ{μ!VΜc”³σΕγc§΅Cxj9ΰ2αq%‘ dΞ…EsΞh—~`ŽΞ*8ς<ίπF:jVtΔp3άΝπz³|WbΠg2}^oΤLŸ@Ο<σLΈ G€ ρ»|ω²]s+€ό΅΅5»%ΐΑ@;4Θ䫃C―<§·šαΧ!@{ΥDUγŠIν’œG]._·ςΊwμͺ²J›33θn‘ŒΜΓiρΖrά²3Σ_‹nƒρzœ&θ‘iΖψ}¨b:'ΐΉ2ˆgnC¨ξ”'ΰ=οy­ψ/k₯ΰ«vΈΐ1@fτλN.fǜD•Ϋϊ(`6s˜$>QrμsΑΞe·sY7:ό—/›κeιΏ© 7vZ=.Ρ•σ³(žΚ»lŸ<ο;ζ2Bάzpَ‚–8έ΅ΐ9_‰g*ιqό3Βν`;CηœŽ»€a~Œ\-ρμΏΆ?π„―θΐsΟ>kO¬κž|v0ό8χίΈ¨Ϋ;ΫΫ²Ϋ5&Uxύ„ξϋΟέΖςΛwΰ+Υ}”HlIΆ΅ϊOšS$5zלœ)Γζ„LΨ’&ΔΠ5+γq]g{Bζε}dE;!\kζr†wΰŸσΠίΈ3Δ2׍#γΣ0„ϋ_ΜԞœ Ύ"˜ϊι«€?ύο}ψΑόΑ0§-ώέΰV‡Ψ x葇Βύχέφυ$@-γs\*]œ}ύlΕο3%b 5³ΑJϋ‘+Lϊ* ―°~­Μ–WB1­™οŒσ,ŽσuΊλγγ@<qzFΜDΞZž qםή8―4νό+­0]A₯.wŽέΐVΙ#垾½φwa!όo?ώγφήˆ#pU[χάsOX[] Ϋ[[ΙK€&βC ΎpegRη`fFŸ~Χ€s&SW=cψ_§x&τňkς)n₯O ςc7£f,ƒLέ©C lodf΄’A¬ϊS/ΔΚ‘^‹ŠZ<<¨:¨UΊbd-Πƒ;τΜψΡBΪΫH"?ώ-ΊxŒ¦ζILη hKŸγow<8¨»‘έ*ΜoLΓyKwΐ˜χ μNΥΩ ΰ:6φqΊ€ s\IHzKzπΪB8ZΣ³Δcgd €$]„― ͺχ³ h²,πΦΔ]… uΊ@Φ]U4OS6“ώNCΠ„mλφ£ ŸΔςf±|΄hμbžLΥoŸ[Π6ϊΖζόi·Fιnΐ;œŽϋ<ƝΠ`Τ1ϊvΩ„φ aΉ κqΟΏ'©ηΐ}ΐ¦·* Τ+*ΐUΤ0λCQα$yΰ­‰» όLh*Cvω­χοϊΠΚ*^Œ5DmQ'/Λ- Έίχ3žkΠΥ2mcιrή΄„7†RG`†8cόη%έ9γF:dΩ''U߁qM ΛSF˜pM ΓίΫ8 ύ5θ6ΐΠϋ 5ΘLϋ+ˆ‘>M`Ÿhަ¬Žηηλ{;βͺ²΄ž³!nvμιt6‘ιTτ© Α§¬nΖ§¦}q9Χeχ³vŸŠh….~^֝CtεαΖ[ΐUΖφΒΫΠ'υ›Ά)#κ εwΐq f$|ξέf¨™ωϊπάλr.καΊjπZ`*ΦΦ 4nEπδs CB/|R'΅ΣΏmCωρEY¦ω1L₯ ιΙΥ©Ί΄ώκ &ύ΄ώVUΞ—•Ρž―7ζzΪ>Œ_«>pΗndάΗ@°ΆπP0ζΣΫ[cšΜΌΈ/s š8sS4E€>ζϋoΤ]Χβ€σΆVε„ˆ&eΓϋ‹:hx― ΆbYπΔ2ΝΈzΈ1ώϋ2(OwhΙ$Ά‰\Μδ΅θkΤί"@NKτ`(φτ&SΎ,Οiσ8+h–ˆιo£Ν°Χ†;zΕΎ^ΩTlpψ’εΆ>e œΣί-=V»'Ί ΟœͺqΏΛTcγ22F–›πŠ>πuQζ'ιͺχ₯ͺžΝ΅i¬Βε4 ΥΑpg`¨ ύ tg¦?}|ΪGs fόΞFB:$ΌyόšY|¨I«}Ψ48³­iHρJ‰ΫS j_8i›ΒWίϋI\fB‹p²κ-Ε\“Ά2²ζ8.«{’ω8{<¦Κc©γŒKGjGϋΨi,ͺwœy¬ώύV}ΒAα]ΠZ7ΔγV*#γ€Ε2DzΒΐΨlnn†υ‘‰£ε}¨Dλ4VVj§°žcv²žL1ŒsœθnΜbπ#‘¬λaυφDȜ€M/m4±²¬4Š%ΐQ²pKͺdΩ¬_ŠκΊρρ²Ju)|"~ΩuY~R{θ/xx]³ˆΠ“‡—ΆΫΏo%έCŒΏΘσΔ[”ε{ωΈΈI{λ»,ΰOεzΤωBϋ‚Ά–Έ Mͺ<πuspy†·l2Ύόph΄Σƒs λOML‡§ΏvΉτλΈί–Nϋ:R/βΑPY”ούqΨCυ”IφΩ‘Qίςty›ͺΨe2¦y€~Μ“˜Ά‘ŠΣg@Ο-ΰŸ1^(w½jϋUήηcΐ;=ΧN„Ξh{<\#!­ƒ’Ώsz| θ’& ΜΧ8Ϊ~σΙθ“c\SΚQJώ³‰+ϊνΎ+«―6«/§>†€ϋΕsŠQfδΩκS0Q |A1ΎmuΓ•"uiΏΟKΛ—oZε₯ό*'4+D`+λ›ςΉvšΪ±κuΌ΄σώƒίλ‡U[œ§¦‡ί«¦pΤΨh6Άώ)yls‹@γtΑ3Ηg ώ8œ^λ“ΰrHΥΗ?nmΤ΅ϊ)ύΠ9ΔW΅…Φ‘Ÿ€.n'±3 ΆΪρ9lΖΝyξ°‘ΕΣ8eτ©(˜lη~Γ~>ΦΤaΉ3†Σλο(½¬<ηeί‘° έΫ9/h·[ )l>νMpZ©Ÿ‡aλ‚ίΌΏπc.pfA0 Φk2Δ{xkχχα·`Μ τ#ŸτqYν ΐgŽR:V7Ž‘i7ώτΟivψΗΟσΌξ²ΰy]psΦ`SoόΔ@ΫGΏΔoœBhˆaΐx ― ‘ΊΠμΈpb |”Q—4ށ;1퓦Γyu1ΟΗA4Ο*‘ώ[_gΐ’a ―3μη,ϋqœ°£YzœhΟ.›F4„ήυŒΖH/«ψDJλΠl` VŠΧ 4Jˍ(JE·―ς9MZ˜Wd^Γ‡t₯oωͺlΚRŠ» Ψϊ,―Kž―φ1^ͺΗκάaCγh8όW^4ΚπΣf(@JC‘οΣVόΒ·¬| νι Y€Β‚Q¬8)¨3¨E*Ήb…ŒοΝ₯―‰–”μlΚΘ-†•5Ώψ’όόBΨ£Ÿϊ L&P#Βm;2Π»ΆΆšΐMϋ νΠ€Ρqz©Η5}ΖΨP‡@9c`'μUΞXΔγλup¨K[λΈtνpΜΑQ[Ϊ“O]VΧΐ7t!ΐΜΰͺ¬':έΉa ψωm œ‚E]#πœ6V[œt~N t1φπ:\œ ϊJΪ#{8*\“Oί  Z\~¨cυ4.ΐςHrγΞkΓ™KΠΜώρC.§]ύtέτωy,¨ κη¬BŠa˜ρR ›JƒλšΚ°C?gΪ™cή9M™¬IƒAq£ΒŠΰJ§)8›!’Zέ#ƒ°’ v-™A>?™8QπΙeeIo’e”$P\”P¬°Q–¬ΐηUΖ*z™•’Cy±3@ =«eΚωqνψ©Až)Ι”G΄³^Τo‹#@ΧψΛ΅2 &p«ϊmmψ£@=ŒΨΗ‰|ϊΙ–Ύέ«•ΰ―Ρ-ϊθ+4ΐςLY«?΄)Pε=6`ΒΝΰ–‘Z’ρ§ͺ“ΘΫΓβ|€ϋϋlσ¨’₯Θ ~ ύΎh τ›²ž½&RωΠxΐ=qΑ¦<–9Ζ#δΖ‹ώ`δθGάϊ†q’>Fœ:Ξs!΄ήΈ‘†nΘ(§ρPνi‹!Η0Βς —h¨'Η…π‘ΫρΈQ6|ώGx­b!Jyγ…£1}sG„Rδ9„'μLAkžwΰw> :œ.ΰΡw·5¨<±œΰ%9xG>νeσHΧΐ0έ,~3 =’ΞQlN΄Ν(@ΗtƏfΐ’aπ~Ξίέ ΊsŽΖ£w$e‚0£&‘Ξ+•F`5Cϊ,06e(Zl†Ε£ΖΗ'v#ψΉΚ('7ΦΠνŠΟ•8²Ό¨­)Ώh2™±‘Β#F‘£μH{`kΧp)Ο8±₯½’ΗžΑχ"ψlΏ’2U‚KyΎδ ‡e X}vΊPό2”4+PΪα<`όPΰΓγJίώ½ΒLίR₯Φ?-νβξΩΆφΡ‘(mχcΔq z ’—Emέ/λΆΒJrΒέ oO†C=•Λ1iπ v»fO+MντuΞυ:ωotΪ-Υ΅±•ŒΒΖΜxΣΐυ‚hήSž;xδωΟΞ+¨Œ:ζ˜yCbΑƒ?ΰ²ρ΅¬Δ(Β+‡1ΐ6hΜΈΓSVεl…σImψΟ#λFΈL>:†γώΡgύIΖ™>šS£1Ά) z¨›—wλGšŸ§Η― Άd˜κPbΤΤ†ΰςή’Clh$›z3NΔ\¨εk&Αλ'WΕ ’Ϊ›# -J—΅ €ί’°ƒ}©γMμ P†#Π8D}c•Ώ₯ηνέΨƒ˜&‡τ•_KΑ!1χΑγΑσwO¬~J{›t9ך3¦£pΆ8ήί8F¦mι}Œ+œγtηΤ|Άr1€ ^{ν΅πΤ /Ψ ζκ•+α‘G Χ]³ςšΰΥΠH¨Ύ0·-%~UÐjŸ4ƒΣ§Lα`h2€†Ι+(3ڊw~Ϊ ψˆγ{νN!FΘ`S'δ­NΝΙθmͺhqœΔΦ'Œ8ƍ~FΑϊFΎpC7ΧŒO_F£ŠΑ©ΫΣύό‚ξέΚXχΕVτ}~}έ‘±οιή½96»ZYn|'lνάG[7Ýλ/†›―†W·o†ώή–Άυw΅c€ί?ξ}νΘ8 PJ‡h4> hαLΐΖYηψ­]aΔKαha5,]z το{4¬^} ΜΙ9°ώ¨ΝΑώ–cκΎ½ΰμ«/tΤΧC+ΰ,ΓΌυaΠgο;•mΧ€X°ŒΟβMΆƒ―”O k•Γλυ“VΙ_ςΨ=ςΒΟVζβ7;ά¦mΉΗ €‘X88v~Xάπ|pƒΐ«f|_œ^?λΙ€‘y€~θησΔdE€²φ1P‚gA}˜Uπq©Δ3¦!Γ.Η7CœhpfxgΕΰ» nηŒ0†-ή#))Ά>?ρ‰O„ίύ½ί ·nή4Eψΐύχ‡7Ώε-αωΠ‡ΒΎχ½ΆΚˆ•ΐπ©ΆU­ετ Ψ|2E“Ώc[W'εšp¬L¬_(dM<§Ό\χe8˜—¬š\1εi²-gU²ϊjcΧ)E¬FmkT10œ$Γ`~δ'Έΐ¨[T„²EΡ³•7|ΰ»AΘe‰/σZΕγπmιΧή.§φΕ―%=5ΠΟd˜Žt»ΰϊσaηυ—Βν—ΎΆ^{1lί ‡ΫwΒαNΞΗΩ0Š€qξΈ  ώSΎؚj5ΏΏy;μέyCΖ2y<Ρψg<λ…ΧW/ΚΈ/,_}0¬ήχ–°tυ‘p΄tAο‘£}‚λΦ—£qΈ/£ͺ-ΕΕ„F—``Ψ9A°U«ψλZ/~πŠ_l詉!%ΠΦeΐ2Ζό±Ά2ΐφ όŠκŒxlu.Xΰb7E 1ή0ζόœOcΐ[1τ9Γ(ϋnM q† ΎI2RΙί:Π‡λΠ9‚?ΰ$8―ŒΙ oύ[Π vΰSˆxm ?Τ'dσ#Ν·¨€M\₯i:ξs‚9Αd-Ν›!ώ 7ψψkψΐCŸ½ίηz}ξ.‡΅γΉλώψ3‘yμ₯KαwώΣ Ώϊ«ΏξΉz5\Φʊ~¬0x\ΗƒχχΏ?Sš>©+±˜ΰKΝΝImοΛkϋΈΗν€ 'νψ‡BβΠX―—(&£AΈP0¦d”1'ct …Ϋ“1@Qϊ€ ¬‚ΝHͺΎΑύ˜ŸΙ΄e»#ΐjΩN:+ί|Κ©ύR8Ξ“„ή¦ΑuΨ΄±ΊI[ΫήφFQL>?œ§ΛœυšP*fδΤž°Κ„œ9£Iνφφ΄ͺ/–ΉO―-{V¨‡Κλ±ϊ_Ώ w=ρςσα–Œύkίy>μί|%μκw ƒ―Nφ³#° γ,‚ tρΨ.4\JΙΐΓkŒ›ΡqžΚcŒDŸmχχ’Ητl[>i»[r@Ά^ωzxγΛ(:΅½½v%Μ]|0¬½ιέaώ±ο5aξp.lΛ!ιέ΄χsκ φ΅S8…Ο5«rβΑxˆQ–aγQ:ΆW΄’Ζ‘’Œ³;œ•―£ίϊες‘IGr!©+§KγbΞαϊΐ.|·ͺ˜Œ}Σψ¨] !τrHΥε8‡F—Ι;|ό©ΗΨsΖƒ³œσ`gdNsšΰ­Ρ πXδΈZ,3ΛwϊϊαόDΐ+tθζζ–ςwτΞ©Ωΰ­’ΗηβΎάέα±Q]–σιΘςqJ[>»­λ€η1΄%ώ\~άd‚tΚq΅θ&‡ ΐuMp sΖ0‹•?[‰Ÿ{ςΙπ±},ά―εΛ—m˘mcΞΰπbgžy&<ώψγαQέ`’Ϋ)φl ’bBθ±=)œΫgh₯ΘsΰΪΎ-Χ°¬>†$όR,Y0\Ι₯΅„²αι)+V„($WΌ?ΥMžrΕs’ΝW9@λq"]Α Ύ”«­p₯ν€ Œ [Ϊ28΄wε lŒ1žCg1lΤ·ŸjdΈβ?Nu½-«J!7hx£ EŒΣfͺή²Ρ&£(E½£w½½LH§ψŽd€n½n|νλαΞ7%l½ϊ\8άΩPsΈ΄^\» Έ„gκ/}ζ4L%«q ν%—(Ύ€ϊ+A”»Nσ—!© ΐOΜ?nOnibγυpλΫ_ _ΌVξ°όΠχ„pια°ΏzυM&έp°Ÿ²¨qa|Α!Δx•ΰ&Α…?8RπG“srdΤGn'¬ξΥ3>Œu~lSj‡"^κc‡eŒ1Œ αPΞκΌd’3t/'’£ϋϊΊΏξ|=τn|=„ο|=μέxQFŸU>·tΟεb2„ΰT»γ³SwbŒ±ήnw@£)΄$Α_γU³|ΛώcόΚ²¨mΐ³Θښs—Φ΄1Εια™wυEŽΚη>k?vϊW »Wί/½I(ΗO»BΛ2<‹KΙ› Yj{œΖK·vm[”ΰΩWm΅žRaγ*#ΎΈ‘ΗιTίκˆ8œ―ίIv|’^fNˆdœ 3Ɯ1¦w8ˌΛΝ l%Fq_·1ζηd¨oβΈ¨_jc/:Ϊ0ηuY‡%Ω€ Π­°ϊίγ¬…­τ™³].•³γΣ»£Cž·xΛa"·77“‡…!ίΌςo&/M’ŒώξΚy` on )Dx?€ν€¨έ5δqω0Ό±Αν œ*­τιCοζΆτΕ¦½ε<€εάήQMώ%ΑFΨ/‡‘aοοo‡ώwΎϊίϊ¬β―ΙBlh,’UώΌί¨$ƒβγf^›ΖΛβˆ7€4 ”­’Υͺ_ρIF”LdiΐA(™Vλ«νPθ€ αHO τΏύdX|ειΠΏψhΨΏοϋΒζ•οΫ‡Ϊ!ΩΌ%E|Ρ­ŒυFήa艍Lαuš{z‚aW‡Ω:’>u¬OκWoΧw?tρŠΜ6ί πGι=|—„K4ΤVy€ο H νvτVDύΰC†ΝYΥ”&hc5ϊβϞvxΤΤΚHμ$―ξ%o[afp Δ`gΔhςρTeKͺςφήvΦLά#&³€κ‘Πρ*†K[«£ψp[όRpr··χΒ‚œ°ύƒ„ηOβΆ °ΰ™^ΙcΟχzΔ€ ±ƒΝΐx†W †ηe•&OΜIξ½vQjP€"ŸΙχδ°»–Εθ€bΎ εš1ΡκγΟV?±~Œ?NΐΊξ³5ϊθƒWΓ΅+ΙkN3ο‚l“YΓ<29—ΞXψŽρM)€G΄%Ή¦’dΡ:DGρ…AIQCΐβ,O§s—iξψh|;Υ_ΙΕΥΪ“εΦ6+FmSλyv;pT–~=ͺ§C}{·‡7žύLΈύΥ'ΒαoJɈι zΖ^[ϋ ϊiHΚΪۊD%Ž‹ΞψHfγL&ρNC\†,Ε!M™ΫšΈ^œΞHŠ|)lΰE±BςώN₯k/κi“—ΒαΕ‡Βcο «~Ÿncθ F >0&/Ί‘βZ»=lsCcςl…'tΣϋΔ`ιoΒcH[£j]˜ΩŸi¨LΊ™‡ΰc;.?©Η˜b7„Γ¨μP° β!ƒβ`½ #0V9k‘―1υu%δqΫϋŠt+«Ϋ]ŠΫI-tŽ@Μ•©Σ0†…>[Φo{ϋΫΓΧΎφ53ϊlŸ³ε@μ?‚«: Έͺ-¬έ;Μ”;ΚΩ΄ΆO#ft”ΦeΥ€%q`Hί¨v’Άy8¦RΌ|Lη☚z-Ό„“Αͺy³ŠΈn½aj•6δpΧβ<ύηω~έ{ετ΅.y„on^χŒuŠΓύσ^ϊΒΞ―¨ͺnkh7@ΦOueτyωŽAn²BŒ—ٟ!Γ>ΘΞFΔ³29PFάΖΛσq‘ΟWΉŽΖ<5ΨY9μ*υη“·ΥΝέy9|ρ;/ώsθ½νaν-ο΅sσ}my‹άJ™—αη^6·|l7ΐεA\Κ“Δ)‹ςψke Šh‘ =Β!*8j¦sp¬Nέ?ΐŠΫηa'ΑΓ_sςΘ ˜h¨Šα *XYV”$,oP₯2εMŽtS†Ϋ Ecου*Q˜UΜc›4©P Υ +kΤB…ρχ˜ηIΥOΥ‘©¬F—hΐΞΓ,¦ρa˜ωΐΒgώΗ°C=|π`πIσDΐebδ ‘γή£ +3š›’%Α„\0ώs·΅…{YκfEΞNο`>”C0 c+Ά·¦…%U™Lωd8‹ ;ΥΞsȍθb`εš]ώΦ½ΰχπu~oσπΪg"\ς“2ό/Ϋ-€Ήε ΙψΨΚBpR7P0Ψ€Š ψ Ζ0…Eu½FU™Χigކx0D“ϊd|Υγ‹τ―?ŸΌJxχΦ«aχΣ[/<VΏηΛΧ zŸΖί^FdN@zSΞ€ρ‘Ν ϋ *,σμ’1DΖ±"―˜'£ kc(jZ˜WFqY>@†Κμ"ΗϋBLΓ™ΦLLdχͺ΅2 Ό‘>50^PΉ Η4Dβ•PƒΐΕrΣ”Ζ~ƁΞΘX1œpAd΅Ο)θυψγα§~κ§Β£Ηύ0ώ~N_Lo<όπΓΆ’βD½=6εša€αζ2Κιs)Uέ d½ΙΛ\μ¦h™ΰ³ψ$Λ`Owiψ*jZXίαΚαyΌ,ΛOAϋυ0¦‘+―y%/σλ‘8O’FlasÜ.­|ηW.ΨσπןόΛπͺVύ›Χ_0ΓΏ΄ΓqΪβοΫj_T\ΕŠΕu„&F™‘θυ²Œ4Q–ουΖ•{½’Ψε”²28π8‘ώΙ`λQGΒŽ€δnΥgnμ½ε‡Βςγο Kz”ρπ@‡Xυœώ‚ŒpΉ—žœέΤ­ΪꇱwΈΠAžρvΚQΘ‰=₯I€ o›\©Νƒ£‹hLΘM›{³α± ‹”DΝσυ½aT%Ɋ+ަ­¨ST–εG@"Ίg{MŸζ€uΠ^VvΓ)L€Κ:βφ΄pœΗyqέ‘tŠ.ΩnςΦ#΅jeŒΕ‰Ž€_ ϊV ρ9«Τ9ež '–Ή7wϋΦ­πo~θ‡Βύz ΰΙΟή<ΥU9¬ϊο»οΎπΰƒšρη%žα6_>Ξh>dσΔq“Α—Τύ½X_~IJͺn#ΈΦ(ν8Ψq3Λ+«ζ pςeωλΞ’KθpZj5ρ°€‘έλη0ΫΨ:ΐwσ…§ΒKψG᎞αοιό‚ξycψνp–(ΰφ °β±JΑΤ<Ϊ|ό5€z¨*σ:Mγ*˜ξΔu`crηY1/R‡zzzžl?σ·zίΑ—ΒΫ>–|GXδΎ΄œ€ΕވΘ#qz4OŠΧƒ“Œ“φΫΰ²χ(歏}ΙπΐAΘυ*ΟΔ΄x(;?ήΤIΗh¨^΄υ'―²~άΎNΕ²:EωΖμ’‚iΎ$žω²όuLφΨτ:βφ1θα:Ξ‹λŽ€γŠ pŽΐI3b~Φ‰e$7 λw™#θ€– g˜b“p±ΐ‹>Λ[ΒcozSΰ;ί(Vύ³WšκQ(7ώΓ†―\¨‡suΕΦκŽV[z,³Œ#•(+…PT{(o’–SΰBž^Ψ*±¨ ,―~4 «ƒάλ_XΣvΦνπβϋύπκηώRƈ<ζ—3Η«xΕi±‘GΥ.§8€dz,ʷ눾ؠ’Ώ.Λ‹@Ά‰Λ'M»Ρ/’ΑeΩa[]ρ ώ W=½vΈΏu#μ|φΓΑΫmXŽΐβώm½ΈPOΎHΎ퐚Nh‹7σϊρΞ ΈΘ˜βxpΈ―άπ’ c—ŒΰW…XήσcXΥΥ2§9’§*ψΠμtWχ JAtΤ€!n -σaίcΌqΊ’†Η„}Œq·t甍Έ ±”“‘ΟΛnθΝh(»5m3£θ’GxΆ onˌ·Oα#Δ#LK‹ΞέΠv4Ÿ^7Π§#Ν 3rψβ:…Έγ Σ€+πΖ`›v'n[™–Rγ€{ŸΓ{RσΪΎΎ‘“ύ/~κ?λε=Ο‡έΠΐ~Wk)ύ°<;*θ:W^UFσ8δλΖem§‹pe92δeu•FFx}°ξ θ@δZ8ψκ_‡ƒ9ν˜<τ}2ώ·ΒN;':€Ε£|Ηx¦Ψœβδ9vX:ŒOΚc]Ά"§cΰό˜Ψ¨ΕˆΖ8 qUδ©iπ9SΫˆΖ·Χ4Η)Λ³2όβϋ`ςgxΪqΊ,TαςΊ΄­ͺη°ΟAά95%Ζ!nσθŽ+7Κς 5λ(Ξ³΄Ο(ΝpŒOκ]f@SŸΫ΄h―38Ν#Θ₯ΈΛΰΥΝƒΧΑΈσλΆc^{€Gυx¦Ÿ½π7Ώ^ωά_h‚λeFΌ©Ο^˜ΓϋŽ‘°73„)qρuœ¦8ΎŽΣiS‹Κςγ:€γzγ†9ίΦ―}|«ŒlŒΗλ εA 9έ/ΩξλY^žωdΨ–©ίΏχqΙ;Nΐšv»xqji.ΐ{œ^ύΰ.η˜FΛw€νx©£Ž[t’œoFΞ€„ΈΡ‘½ψ1«ΰsh,Ÿ“3β―σ¬tτΐ?#άπΆŒqΞjLO άΞ¨9(L”+~βLΉ₯Ÿ)T2 ΓWQ'© ™έΏOCΑ)νD+³tšyK΄κ K•—δ*NrYΧΑΉςλΦcΡΐʟ-}VωΫϊϊήσω„[Ο=™lχΛ°ν~ξρ[ε'9ΩΈΥL*nStM^Όώ(q­ΙΣq8!븞—ym žΙ4ςΝ“―eΨξ(μ_zΠ^s{°’/ςζ?9Φ©ιΉΧτnt} §Ώ,3Š0"ε‚˜Γγ˜o  ,]Σ›ΜΤπƒ?’ΑŒΏ ψ½όΉΎωwΏoΚf^‡Ψψno±F= ©#•lqp£η1eeι|YΞ0δΈτδΣƍ¨ο~ή)σ>ΞhE», »·ΓςKO„ۏόˆψ«o&θ•΅μ„αΠΞ‹³b'€z±ƒΰu*γhά­^Τ‡ΚvSΖsi’quG:fδ ψœ«Ό5ΰό›ίΰS)ΐ=#Ό°ΥΗ(Γ?γΎ‚σ¬…ΑL=k=;ώΈΠ₯ψ\(k£Gz})aιL€`rxƒ‰η΅’ΐιπ] ωu«q¬D 0$έφΧaΏ—>ύ§αΕΏϋ» 3dO Œ0%pԍ%Eι’<‡—Εy#εΕ§:vGq‹²χ“‘·ΎιQΑ½/`mλ₯°}ύ©pλΪ»ΓE»pΑœwβγΧa—΄ΗqέFιΌLΞΠΐ8]πΘΓDγνr &΄ήΊ_§Ωy€ΩKuWŒcjΌ1°8]Σ«ΝΜψ»ΒtDilƟGϊ0ώOό±Nϊ‘έοOϊιΠYzΠoH¨-ΧnΨεiΛςβ|άxϊυέΗΌ‰wœ7fΔεκ-Wo}%lΟ_·/>.έΡ»f9τŸσΓe“s8 μ΄β8⼜ΞXρ{Ÿς2“TšvΉŽψVZ·aΟΕΑˆ”€_3βΌ)εΛ ρΣά3ΖWΒέ».»s&²œq₯0 (“\5μ―h΅΄ŸNNήZ—γ˜ §)ŠKπΕU]ΩΔy­€]AŽ“ZaερΧγh/ώΣ…—>υqϋΝΰ _’ς CζynΤοiγΌ|škΒY2όI†zςŽ€‰#C Οτή›_ίμιM‹‡u•ύ|Ϊ#@IDATnΛ Α}sTΩb]‡΄iΖΓΓυ,C F†ς½.[Ίδr~RŽ€σhό/₯<™!^“!άΰ›Aυ)―ά9MΘ…8m犠)˜‘ϊθEήώ§·ςέΎ=d-Θ%ΐK²‡@6ΎΘυ«¨=xg‚ΫbR©;ν―Oρ&+? /ώύ†₯υΛ#§ό‡&Ώ`ΉA¬zΗεQN ~nRrv:ίά@‡κων,„•Γ;Ϊ ψrΈΎOoόγσΓ’ώK~ωHiμπŠfxΙc†φr ©Μ͌Ώ±LΣ‰ƒυ%ν3`Mb|upΉάΟΘ8©έΧ₯‡O-‡³άCx}Lf„Ορή­qηΤ9€¨Ύ z”5Y@<χδΪςΊryΙd¨­UAίbhΗΏβO±c$τJίΓύ][νηΛ •bόyi ‡=Δ“ž΄)δ LRκySμiΣ&–Γτόσǎ€FΒΎ!p [χμΏήΨΈ/άΙςohΜH >†_o΅τΥζˆq€1JsŒ«πάΚ•Gϊ@g vˆpŒLZΕ&bxΒ5M8:Ήΐ›υγuαΠNΪƒ€o)‚ZσuFŽ€ΟŽJGΐω2%OŠψIߝ#εΰNπ8Ο‡pΟίHίΞ(¬ΌpFδVΦt’|[ύλ [&ΎΓPf‚Σ'0ͺ‘+W"C™Σ\€³^SRŒΌδgqiMoυ{6|γ“Ώζ—τš}λΚP΄˜¦A`ΗΖάΣe1-½Μ‘Έασλ»6†1s&μόΐ Γ'^Ά΄4Χμ>ž»Άϊ+t΅―ρβ>ΏXιΣΞΫΗd$dD8O°­οh€c}}=q"z‡”y”?Q2–?hi oW_έ­ΠΉ’>ςR0^Ύͺ·ƒς}Nύγ™·‡ϊNΚX4‚e‘εŸΓc†ΌΫU@όJ9Μ8Μ§Σ5„\SŒ»Γ…αF˜²‘zYƒ€Œ~<Ϋά'?6^~.,ιΥΎάΰk‹ΐΙ―ΤvY ψΈΜhNιΝÊHι’C—pκήCGί 7v.‡­ΉΛΚ“s&Γ•ύy‹η’-ρy9qδ3ή&CD₯1τ.P[=3ΐ|PΎΛ˜Ιh*O^ΝΛ||=ία“οi/‰S˜Cυ=΅”{%2†ž>hΏ':ϋΪ%°>“¦°np΄μ8gΗ:Qλ’<žρ£¬ΌŸNΠMΔ2:ΟX~ηL0 (+B¬lβtm6#RρdFκή©K« ν8XΰΝ?‹mŠ˜INIbδX½Δ΄rΟ”Άκ9ͺs€IΫrΏ“ϊΐςΊ€>ƒ©:¬zq=ηωlρR'ΖοπμΎ)•μS²ŠχvτYemύ_Βί…ο<ύ){άο€OψʘXŸE“RΎš·Ύ©,3θJj&-¨cυtI™§“ξoΰ+bz¨υδϊάnΈvπνπΒm}@ŽΩώ‘d@ž¬Ι€ γκNγcFQ²ƒΌ---%?m‘«"ƒ`cnŒcbΫθj‡C@Y$πibΎΙAμrHl+smΗο§2 ΞƒŸt,k,ϊN‡aΈuMύ%΅c+Ÿ~Yπ8m›ΙŸUΆ»³c·(φΫΠλνσς˜‚)ŽD»Ρίfj%Dο£xΠf€ƒ₯ΑΩ2Ύ6i?‹°: Ζ¨¦Σ>›ΐȘΠn<ͺK! Ÿ`|MSςŽΎ3ΐ¬τΌΒ†ƒLW’ώa"/ΡLΩ‘tP~  ϊ°€zόΤA3;ΊΗiJXQœήGκεMƒΎ§Ί(ά8 °W–—MqSΠȏtͺ˜όΐδ끌Ι᝗Γ+ύO΅β_”]α NU !1δ@§ό:Žι8,O\א]'P€ςˆ#uTδΈΌVQ/#ΞΧχ²’veu½MU\Υ6‹ΊδΩK*u+ΰ@·ξοίΟm_ ·Ž.ΘqĈΛΑT%ΖΥ .NγⲆαfŒ‘£ Z!ϋ+…·τ‰m:ΞjšΊ\#3Μ-ŒΏ;u8“KΪ~Ώ ϋνΰ( 6υwd|γB[ζεά³η>=°σ6ΤaλΪ<O?Φ… ™. Μ+Ϊ­Š&>D{θF0pp‚ovŽ=/7E°³<Αs³Λ6Μ&B%Tx%΄*ϋ?|N;x·ηχΈsΖH€ Œ2ͺ£ l₯ …ΑδFΙΈq+R.#(bΔάɞ€έΖ9β‘Ζƒ h@ωP„l©β@Κǝ”E)Y”J‰ϊΤ3gEutνuiΛ*ΗVκjΏ―6ΎJ£ ε ΰZ{υ₯ŒρGΑšSn))x±šςΌT©G{w p θςΌ”+kυύύƒ°»½–/\ ―ύ¬χϋΏbοϋ·ηύ΅ϊGΉ!P3뱕ΡW‚Ηv‘?ΦFeΞ#ΟΟΗ4Wwk…ΥHύ< ―Π:°½~Ύ.ωe°‹κζ;‘‡λΧEtα‚§ ϋάυω½ππβνπνpIWG6ξwnί6y°U³dΐJΕ/^ +2ΐΘ$²‡,m(ςΰ«|ƍ±b#ŒϊŠ +†γΚθbT·•osOyFς0Β8²ΰ ΜIκ"ƒΐ) Θ#νq QπŒεΫgΐ…kI΄Ϊ D€hK_θײꀇ>Φδ8,₯ΞpΤΔ’.f‰ΔζK Υ' ΒΧfj%D.„’Ε@ !Ξ_‹€ŸP0f(QHnόY lJ™ό_φgαK_ϊRΈyσfxτ‘GΒχ~οχ†χ½ο}α₯K¦h*nΗλZ`I‰E)φWkθΒx/Kρψ%Χf䀐P€VOFڍ?Κ ƒmX€ΜφD­X0δ(7&%J™ΊΆrQΰ θά‘ KžΥ“β₯ί|ž>Ϊ8~b£;*Τ6ΚyOύ€·ŒβΪ₯°σν/…O}ςš_= `«΄)Ο΄ηCς₯AΎͺMΚΪƒ:_–ΏBNγ‚ΖήΗΝθΧΘ*Ƙ8ick2+<ΐηg+mΙΣαA]F+Œ8Ξ*yeΓmN«θE>‘•v`A‡ο ,hωΞ£]yΩΌIΫ³kΜͺΰ΄VΥ*Kω ŽeOs1Φ Έ Ε4ˆrm+ϋ>|9τηώ²sƈJκHΚƒIόό7Ύ>ϊя†Ο|ζ3Ά ΐ–βK/½žώς—ΓWΏφ΅π£?ϊ£ζ  €TqδQ2 xv:liB―’R”N£|]ΏFα`€QŠv/4… ή9¬ς©CΐPNnόΑΙ„FΡ±zqƒdːWυγ~˜v<Φά Ψ.4l•»δΨZuΈ\Η+xκ°‹p$ΛάΧ+gν€βΑNψφ'6Sδ΄χ•‘Σο_Ρ΅—yŒSt(=m]·*ΐΐ’”υ‘JY<Άν48Ζ/©N§£±―οW\ΰ,@υπςŽ^<―ΞΛhbpq{Ζ£Κψ!gΘU_ylύ#+\ά°:dU?«z`x>υ †ΰ1ΎoίβgžΊΜ"Ά*—γIDZmv>Γ ή΄α€rνs†4²Mΰδ_Ξy6όΞ+M¨ :—ΣW)J{ύ ±mOZv@RιVΠgϊΨb ο₯g€―EοzPP2„Lr i̊γΔO„·Ύυ­¦ΈXργ_Ώ~=όύί½9ά  EΚB•|β3©z;šzG2šYζ”,Γ”Ϊ`¨]αYaͺ|\©ϊ ‰:V7ΖI:ΝηΕ&YŸ•Οn@L†γ°Ι OԎ]‡E΅Γ€³UλŠ§ΒΆΰP¨lχΗαΒaςΉν€ς?άΫ΅S―}ξΟΓΦ+ΟΩNΐ‘½πGChηt“|ςœvbOSξNC²ς'§ΰ ΛXτό(kκ$8NcΫ5vŒ^ΈξfψΖζ= ρΠΛ›Ψ°σ!Š1τŒ3Fœ žζΪΖӘ™JΐυγΎ9-ι8Δcξ²L—―K+œp±Ρ‘Ϊν0Ι1; 81h‡ΛU\ft₯΄ΞNGέΨι)’΅N!ΙΕtΨ9Σρπniέ9cF ₯…‘Οψ‡ΆςΗψ£X)°zAΉ‘Θξ½χ^SΟ=ϋlxχ»ίm …T5‘m²SA‰ή Χ’*‹‘4―’΄"«P‘|\±x\{HΑ•U. ξ·.Ha’4Q”Δμ(ΐ~p’TX…³£βΑς‘YυxΎΌΏΈ6_Χ£eO·0—Ύπ'>ψηtΉ".‹Ύο4;λtά6ˆ l;J6€2\5ZΨÏη'9'ϋΎΞΛΰhΰκ‚Ξ|ήoάΖ;²U³;‚ŒσΘξSfσ$휏©χΜΗύwαΰ΍0―sA«Κθ!u«θς2bοψ ή?»hϋΟΠ@Ά<%½=€3‚DχΩXž; ξ†Ρ.ΐαάΠ›ρΨΊG6n \σC>q 8ΡΆBOΗΞ2Ηύq)φ³+6οωΜ‚.YέϋœΜςγ0$—μ¬Ι‘ε dŽ€LA/uθKe GHr}ΒΨ»Γ3―7Ύ‘Ψ—eδQθΦΡLSξ‚γΈΩ0EͺςƒόλΙψο~η›αφΧ>ζ–ΧτΆ?ΰ±Ώ”oKμ?H‹ΣNͺ|λŸκΟ"δXΡŠ&δŽSk”Šq:­œ«ΰΕ@―μ„΅yΙށ~2ψ8‚nθΉE„L’w Cδ³έΞδs¨I0yHeΉΓ ΰVηbβp(9Ϊ|π•˜“EŒΏJ€^*³Μζη8θK Ÿ4σΕΚSΪ²|bsΝh·JυώΠ4ƒ3 g‰Ds~ŽkVVށΰW‰?νkŒIςKρ« ­q ΫΓJ&+Jΰφ†r;€]Vύ8]Τ5N€Μ)"Π Ί…ζˆΜe­ΧυγΧ…•VΥϋR΄˜p  Χ”¬-ŠpΎBBΊrŒ9 »RΎτQ°ΈOZΣ8%…’” °΅ΧWϊ’όt{TQ˜‡^£H‘i{{G»'ZνA§ΰ™!šzΪ˜Σ³ώןϊΛp°}Η^ϊΓc¬ώΑα˜qˆ―=νΖίw²ϊτIuτhςυr¨`+κζad*΄)Γ5,¨&τŽΐPFUϋq}ΰl6g_gW.Ξν…Λsα[;zf~ ηPΖιm€vVVt»Hr†œςΈ'γΟ!=Ɗq³1<Ζάe™4ω>ΎΐJI)¨ “9‰|ΝΛPσΤ2F[œ ~ΖpΙ_θβΗS) zάtYrΚr<­° w$π½nέ8_άΔ* ϊEσ§ΈAun_ώz€uΜ€‘Βρρ δβs‘œΧxjΞ~Ξ7Ζ6Α{ήσžπΤSO…+W˜ΒςΥ?Ž? ?ΞΑ½χ^3…Ψ!av‘-ΒΗ\έ•‘“0·,…9ΦεN€, & EŠ‚r£G ‘έ”#__γX"u8œ5g«‘DyqΰU;υ]ιΞ/JI£¨ΥΦϊύ–xG?m?;~iCΚP’Τσϊ€`pŠ'„χΔ₯δ χάξ|ϋ™πΖ3}ψ±?• ΰƒΣœψOJΌJΡPη“&ΟΫΔ°σιͺΊ1Μ|»:Χuπ§Š†:xΌNΎΒ> •ΣγφφχΞo†o­hΞθP§δŒqXXLŒρΖζΙƒŒͺVε‹ϊ¦Θq`η“qCώˆ‘bXŒ8Χ”yΰzQ2κmxε0σYΨ‘ΐ|@>ƒ|€Ί‰l#Ο™L;°4^ό rζ7ξάΡ‡~’GS(η”ΫTΜqs,Gai‰Ϋ^ ]sκΣ qn˜“Ιn؞œœ­­M^`ΞςŽό/.φυŽŒΥΜ1Ο‘2φ2/σε 4Xxg-pϋX·6•οΤησ²ΚŸΖa’6‘ά= :`ΜX‘„X|πƒ΄gyμοΝo~³)Œ>ЧεπθΓι©‹αKΟ}ΫV½‰œˆ*YUΩ‚ήˆ²°­g¨―h5ΔcΓΓv­J&"†…ΧΧJƒ‰”œ½‡έ”f‚˜2SΘRΎ€n@Q’Π8lGΝ#­bXυΰτ Π’Φ z!«˜D!'+;ήΠGή‘γWGη8Ω–Υ›έ€"‡ΞCmω;œπ^^§ο›ό = Χ\T§Xυ' άΫ;θ°0¬χτ…$„Z"‹όRIH‹ύ2‹Λς³ Q’nέ’zEyθΪΙ¦pςυγkg]ςΈž—ε%erθ4χ,갟v₯^ΏΥ ›:ΨΊ±½ΦΦ1€+αΞΞAΈ΅Ήo·ΦΧΦν™ύ­ύ^xύŽVξs:C"ΩΔθήTξώμοκ6Ύ±!ηVrκ™ΫΧξc~c#9kΒc€Θνξ^ςΜ?t9DξvwvΓ…­9ΊέT2‘}n›±sLƒ›y€±Ώ³#ψ6/χIζΞμ-Α[π2―p65ϋonšάq½½%yΎ©—Z­l&€ζt07oάIfοS“ΨDέfp"λρSY8R»^†x‹ά B|59B†εΑ{―θrόΰ}Š€ρJζϋc—j‡PΒΗXI |½|δ#αΟόΟν<ω±κ_]] ?ό`X^ΏΎψυoI ωcDΙ=pPδ§H|Mω² +·e₯wφυEQΎ˜Ν*Œ Ρ„ΡΓu‘Γα˜’ιd)ΚGx’ΓX  –@YΒdΖ!*Λ*QFΐNψ&‡GΚΎ(PgPO|šΧ“―?ŽΎυEΠ3Ψ2rKT'έϊOρYC“|K'΄Ϊc“FtΖ.―Œ.eεuσΓγϋ²ΛK‡ϊFΐŽ 3·o”w(ƒ©xUΓΊ¦G\ζ΄>Ώ -ρelρύžΥ—!Υό²Ί”ύφΎŒt,ό{L†\HΗ»''αHΞ'†ŸΥ7ŸΆsϋk_rΈΉΉ!Γz=½¦Χ`%s!Q—δϋ-`’~;»z“εήNT]2Hm}›’ίOœnΜ; ~ν]Θ—•c"·Ρ @W~O Ωήε°Οτ!aΤ`-γg3š€rοΥKa%cΤnη4γeέڝ0†SŒ?=ی?σΣ?m/ύαP +η«W―†kΧYٍ[α»αL½d₯1„’Y€•Κό-έχΤΐΑ½RŒΚ`v U/Ό8φΐκhˆNζk-ΊaŽϊ)Ί /ό½όΔ§Γwv’{}ξύk΅Ηj m m5 NρΤπ€H ϋŸ¦•“ΤU’ γ9ŽU1Œ!αΛzΰ[θΞJΈ²ΆuίβΊNΦΛQf·μΒ~λa]s‰]#]^V=mΣ3ŸΨNηλάBπωΓ¬ ‡2ξw΄u ηqM0Y±›άΘωΨΩέ[›:œͺΫ / ήπΓsθΦ‡¬ 5ς°te…™˜ΣΖjͺR1™¬d΄Nκ'p†ρ%y…ΗT4Όξ0©[ΒLγLΩMd¨YO·…Ένγ ‰‘B“‡q²0ά’»ǁΞΓ!SBpœΆύ€Yήρφ·[+Œ ΗŒvtΨθβͺ”ž i…V2Φ€`wsG«v­ ϊλΪ―y άΆΟY υδEΤJ00Ν`Φf’―„ƒέ­°ύΟ„y=ΐ—ιϋ €mqP¨ή«4=θb+έλ€LΞVΈ­ξ‡oμ%·‚dΟνVΣ‚Ά8ΈΈΐΗ§ζuHPα–9 §·VΚ0'`!}I»rywŠ<λ,a2±Ό¨[lΏλυΨI#_ΈzY‡u/^„ΣP'ΠJ* §νR8*(@Cπ›^4γΈiYΦ‡ϊT4ΒΟVOK·“ 2]WTιŠp sΖ1+5ς<¦„@ΰLΑΝYZe‡ZqΨD°ωW<…b΅A; TΥΑ ΦcΟ4јΙ8­PΩ œŠΥazuΰπ©!°Ρκ~­πYύ―λƒ?ϊάοζk/Ω[μƒ?άΈMyVχψ=Žσœ*έ!σλ.ζ@₯ίXέ΄°”Η‘Ζυωƒ°tΰs_–.螺ΆηuHΤ†.+?M³]Ο@Ξ‘$‡ό’•2³μH/BΩ;9΄ΩγΠ©ΎΤw!ωFχ䑃æ+«FMζΜA³Λ dQa“ΌH†›4‹λND‹5―b―–p’—0Ψ”λ—]η+ꚲ4DΙΪ¬ΚPεŞΟ54q—yZΩ<‹ͺήάΛ’83§†}}CώΖWžH”Ώ&4;ޞΊqΪ£IοA>Npt›Œ"ΛϋΦuun?ά>XΛ2Ɯ€ηδ??;Jž*eN1†>ŽNwΌP(Gq¦pβ@ΰ σ˜)[ΘΜOnQΩNR:‡γ&އΨεΜΛύš8ŸηΧqϋ‘4•D“…HfGκΥΘ(’₯²ƒξ)ρ:πΗ|πό‘}”ς}€¬A†χΧΊ‘v~=‚1m©#°ΟQFη4l_°εOπλ „„²L&Su0*ΠHΚ{΄υΝ'=τFqiΫUUχ*Y Μτ’ͺšU)«ΰω©ΒηeΒA’/<’ςŸΧΛ~6τΎWž s‹ϊΐŠήhNFΔ@7 ƒ‘4=@ί₯Nœ[Π[/Μο‡:<ηοΨηΉδη―N“'SGgΐl z’γ%h.qΏŠδOυX?¦uqmK5‰+εΛΣ©WšCρE (ιD\:q:[ Δ+΅ˆ·ˆ#ψΑΫ"NΰΕΫ2Ύ‘>ƒŒ’uζ9θφt]Δπ2¨•Lφ Λ«€yΐ―KUBΛZΉΞ2&M0Ι„κΪΙ*/‰Gο|σ‹α`gCΏ†ί½Ί<Κ ?u»­ΈpΊΒ΅E}ŽZ=Yύvς?«ΗΆ}Ί@OοxΜkχyυ_νFε«εΉΌέPIΓ94Τ6½€ŽΖ΄΄€Χi©›Ϋ’όZ c!΅ΨΗ–HΎ«ΐŒεο]Υ›“"ΆBk3˜¦§˜|Άyμύͺ9±ςΝΌyγΈ’_yXΰ—-~ϊ§wθyλ›ίψ‚’z 5χ±Ρwεο1ψΚyZΊλ“δ@2Š—υΨ[?y?„―ςyNPγn·Hϋ/5ώ88‡6ΞΡNΠΔ½A~Θpžz²]Φ:Νo‘–1˜†‹[θΏ?Ώ½¦βšΊ*jQš«C[μc)g΄`,oΟhΏΫλV…πΥb.³J:³YGŸμX]Ν΄šͺ¨iγΞ6TV΅q n_Κ~^_ϊΫΎρ­°ωκsvϊŸ[Ά£’*ύΨ€φ*Γί­ώξL :œXΡm€e½Μβ€DΙ°σb[ω+Ζπ›@Zεφ±ΨΗ`<οVΗ΅‘<—19―-λ₯@¦†ΠœϊίRh©¦ΞͺCΪX]ΪbλΠsVκŒελYιθLϊQ!tΛ¬ΪΣκηͺœ}ΐŽΐ’η–°ΖD’:Ώ©CEŸŠ`ΧΗιΫΌ}!άyρKaoσVθιΡ/{ekD½|Α§‹θθςNžˆ+ςΐY°}hY/ύαE@8Ύ ΰN€½=RŽo£Œ7YΚ` gΧd»‘|S_ζ‹Z+―:ΣΠNοM#ά5t—Ïթ-Œν8ΞZωXžž΅·ΦŸ akΔΤTkφτ"  W§pԘ@&δ‚άEEŸr5νrRΌΈwΎυLdς‡‘ΗpcΓοι|<άΊ»:I0vGΪΰ…@+rψ@ς ιd…oϋΫ€ŒΏ­όΣΥΏpGΐw„Ϊv σ†²žη)ύŒε4_^λϊ$h˜§χ«Qίkθ0‡;.«[[κί8:ΞJωX~ž•ŽΆΪ !›”‘ύ%M©-V@ιΤGοO£‰θŠβΈΌ8›γMοKιU―;oΌbie+>Wφ‚sƒνH\·ήHΓ.γX8ΐ〬ώωαΨ£€JΫκίΆΙΣOί‡ˆ·ΝΑs£―˜9Υ\ήjt±Μ—A›š“ ‘œπ£Qί;' L„N4R{u’DŸ(ςŠΙ3135“ψ`’nπ@¦Vο£ 荊βΈΌΩΔ8…ƒΈΜι};·^ »·_ΣKbτyUεΕͺ€huοyΠ§¦.>0 3žΝ·φ°βOvΐί@ƒŒ>ΞŽ4rΗόjέ@φΘΏH Π6ρΌΪ”ψ š„p‚QΏ;' ΙKέ‰mΦ±PwšŒQS1=§W€φ^Υ³π|s„/«ΈΦ+αA£‰WΓ²(‚ΙqjΣ?}ÏόνήώŽξίΤ£€ΙύXΖ8bc§‘»ΥCbUόιΚ&ΰ@²7ΓA@3ζtsήΔ‡OVύΊ―|[ω“Οa@κEΏ2ΔΘΘTσ­π˜ω]Τ$ŸΛnΎlμυIΰo0χ«θoΤογtͺˆξʌ­Ο£3ΗW)€’@)+ō&@0`ι›ιϊŒš4[­u+ψΜθ6PU%=¨Κ΄¦K[ןO|‘mŒLΪFΙ Xήπg]βΤs€ƒ€ŒvrCoN€ε%ŸΥυÁΌ/ΐ96ζ8czˆςςߘͺυ‹Μ‰" ˆτ@Ϊ‹jŒΙk ΓΕSβs`SυفL3ώ₯‘₯Ύ•Β?•ό;ύk§ ‚Δ+Fyυθ‚βv„_κŽ•?ΐ*4_+Έ ϊSΕ¨©p‚+€ϋƒ0θ¬{u’”η{œ/οOΥ}@'>dόg9s[Άΐκ?5φΆ# ΄<€ΔΉNcz5nΜ[uLfsBې΅S΅n8?σ€5Ζ=%>Η_o‹»ΰ4b-υΝϋxΦβJޝ΅ΞNԟœΩGK”g3ρu@=ΚDy3`d‚Χ;ΠτI•_ή`:¨ΪΜΕΉώUρ<πM…3‡ΛΧt‡;›†";ΎŽ~œ¦αΐe00ݟSΖ†W/κγV‹Ί lν'»Œ₯―ϊέ!πωglΉ#–άύO:–ͺξž&G –η*š Λrs§°NEfcάSβsRjγ=n' ₯ώy?ΟJά}  ΑHbδχυ&3œ€u}ǜ”Ÿ &6η <«ΚŒ\{ €—˜λ³¦Ω{"X΅'VΤf$Ω`L…oO½^΄Ώ-€>³Ψ£ϋϊσλΒέΝCbvτ–kn$ΖƒΞΟv$ξ{Y‚ΏID™ΔˆˆΜdςŒ°Nœζ‰ZOR}^Υ&{J|ާ6^œΆ‡Ίpbθ€š¬ΗψcδWτiΡΫ·o‡―|ε+፛7Γ΅«WΓ£>\Ύlε5Α%՘p6ιtΙ¬ΩΦdXΣ€XΧEt8ž’©xj†ϊ5 –ΰ±Uœ>ϋzΈΏ­Η·υ œΜόΰX½τ²,=¨έ₯N+2ƒ‘Χ8»a'vƒΟ|Š―γ:€ '•© fΝNγZ116Oš¨Νώ2§&jνσi €ή)ϋι\©έߝ€±N_K}σ>ž…ΈsjŒ’}»ό―ώκ―ΒοόΞο„Χ_έΆ|θ‘π–Η ώπ‡Γ{υΏσθΪ·|r‹†žξχΧeυ4@¬)¦2Ζή·g•ΕSα«ΔΓ§”ηΒαξf8ά“ 4oLπ%’Œ¦8ί CœΧ₯OlLeuqPBΖˌ»­πΣƒιjߝ7ώΎ 0#€a,0„ akŽ€ΛwCόήψΘ{Cbpή)p ‘¬‹Zύ=n' &ςœ§}nœs6”wŸm}ξσ―――‡όγα—~ι—ΒσΟ?oΫύ<π@X^Z oΌρFψ³?ϋ³πOO~σ73\Υ–?Ώ%ώεεεpαΒ…pεΚsΎτ₯/…οώξοo~σ›m›sNχτN šΔΚ£W΅"^“z`gœν“β©ΤE)Κ’‚±KQ£†yπ’§χπόbύ#εΖ},ΟβνͺŸ |t“ρΤ.c,ΰη+=ίγ±c &0Rnΐ;U˜·γ3Y& Η‰w \qίjχ·e'`κ1Ž;qFΣ>Ξhχ¦οχ)Γ'?ωΙ°½½ξΉη[ύ_Ίt)π»xρ’9€ΧΦΦΒ+―ďΈΑ`vπΑ”+²ό\οθnτό•ΐc@΄Q<{γ―>‘LΨςΧ‡€pPτρς€wαμp€ρΤM-ϋ‘vޏQδMμLΘ²‰μNˆ«¨Ωμη\V¦! § t;c$ ƒπνoΫVϋά ΐ!`εΟΐκ³kΐfδΖΐ·bΣ–R–7΅τη)ΞΘ)°]ΚfŽS!ΐ9}ύΞΐλcΜ»8«Φ]žR`f8αγXΠψ3–E?Κγό€Α 9₯ΌMyu'ΰ€VŠή'ολqΕ'χ$p2Ύ.SΗΕΫ» OηŒ1Ar£ΐφ?†ί€8¦œ6ΥyίXΦ¦ ίS%ο 1Ε Ao~IόLwŒIt²Ώ˜Μ]8ύ`”x‘ε|ΌΓt'‹‘c^˜X—8Eγ[”Χ6˜ί'ιПγθgΜ·“0ΘηgΜηӞξnΤ!NΏνmo3£αΗΘΗ+ΛzΠά"hΌϊgτ°t/ΰ躞M¬A}q•ΖNJ1˜šΉιΚMŠŸΥόΚiBςמ?ΛΨwf‰£ φρΞΗ„’gՈœ²Ξ3Ξ(^ώσ| ά{ο½vŸ#ο«~Ά1ώΔ€ŒΠtrρ ώθΑ1”M^ά”ΆΙ1%-“uΑIηVξyhZ]ϋSΜlyβh @žέΡσ8–GΟ£{qϊ8ΊΛ\i9œ1Ž“ΐ}pΗ“θg<Ά§5έ9%#γΓκŸΓο|η;ΓOόΔOXmŒ?FƒΟγOήΓ?lko'¦Λ₯žφK{oθώ?׌H,!σΤg£•>][½φhζ œ‘žϊ±8N{zΰα;(ίb‘Ž ΌΟ7§‘²8/λufƒ3Ζ; U0OχIΰ¬βΑ,ΚNz\gΡ§6`vgΖpΕƒ°±±>ψΑžύκ©§l›U―ζV;χτZΰΪJΦΟκ_ΰΠ ˆaΙΔnΐ BmΊZΗ'ΥΚ².,_y@ό[²΄ε΅„―s:8€#Α;‡:«‹Θ"³"ΈGfόWŸΝŒˆ1 srΘω–49]ƒΩ¦¬ŸβΑ±γ=fœ޳ŸŽsΆ#xwAο€ㅐr_Ÿ€w½λ]α­o}«9<ΐΙ ?«ώ)―KxM:Νt»ηΔHπ8 yΐ…Yƒμα*Žk8wfWLΆ‘Ι­{ώ}εμ……΅+aaύ²Ύ pΗ^ Μ·β»pφ8pgΌΩFόω%β™\ύ€,ΙCBζΘ8† v~Ηλxόκ:’š³Η€6―3ΗΐτEηDΜ¨JΊΐNΞ·V ޞήβ']1―ηΫΛ=^ρ‹­;π'ƒίΫΧ-V‹\PHφΒqN¬b\ڝ[Τ·φΓκΥΒΚ΅GΒξσ_ «δτπζ£–;άλ:H 9ΐHbΊ6Σ{κLύ#œ^+Υ6ŸΦζήWOχΰΉoyŠηηυ[˜OςδX#WŲՐΐFΥηυPŽάγ·ΕΈǎχDpFŽ]ή!h4T]εΖθ€,c₯Κ〉ΡίΛZβΌτꍰ±Ή+₯ΕΚ7+*M$ŠLŠΊΪ4XΈ£§¦΅νx°₯φMYΪΎIA‘lˆ£vuSζΤ‰)}ήΏΏΒZΨΉψ]βΣηυ¨J΅ί\αιΪς(J@€Έ §œ”δ)Φ^xmγ άήΨ֘˩ί»Ό=s(μκ‘Χ]=#HΌ£ίΦ^?άήΦλΆ7χ΄›ΆVV—νQΫΕ…₯°°¨G™αOŽ+Κr–Τ–γ¦ΩΞ\œw\ιzsxŽ«†'χβσCχέV–₯cΥο‰ΖκXιΎϋ‘u@“1”":Ά?J£O0£%I½sg;άΈ½₯σZ1H–ΩAG—¬‡‹†Α_Ύ£?ϊΏΗMSΕΣ€K+§"`…™EδΡι’ŽχRCή?·ζφΓαΚΓa~q5ω.€±!ω0ItžύH§?£"ν’₯»?§“0†Iv>άΪ§Ÿυy‹]}؞p‘§ΫοiήΜιœ o„\Ψ s: ›Ϋ GΚΧ΅Γž6ƒvΥxqι@sI/ΤZЎ€dxπ˜ήtB@λI2™Hδ€&mgˆ'mΤuΌA:SŠπώ{ΨYΥ‹ΒΜ‹œf΄Ž—ϊ»[ηΤ9Δ0E7p‰6Hς5W{δήπΘ‰sP RΨϊY·DΖθΫr¦σ΄7ƒ#ŠπsTE•k$iμΌ)ͺ.|Ύͺ?<ΨGoΎ^όζ›ΓΞυgCΟY œρՌ?υ'esQ' ²τYMx§`τb6%Βvi%\ΣΪE9Ε‹z/ΠZY] «:7³ίΕ‹z•φ₯δMš/θIš‹μL ίήXw6–xg„v0ώ|e“Y˜ν40PΞΟ©Yβœ@§₯ΑStόδΙ&aΣFΕΦκ;•„suyΙv[’ΫBΕπšδΦΒέΰ«Ϋ9c΄ή€ι‡ kvΦΉZ$†2rƒ0ΘοΝIunΚψιE@½UaκΆxJ΅δŽήΡT½~ŽΆKrΤΊ€d·DοUΨΩ s+ΓΖw½;Όός3a^o?ΤƊ§Φ½[υcZXFωiΛ§ίZ'‹,υ™$“ΛŒTXν|Κ2OIzη΅βίΆ^1¬κεV¬φ—–τρ,ύ–”§-ή)ϊ΅•₯°νώυ}Tk}%\\_Υ-€ε°¦C΅8άn[΄[ΙΌΙ8ΰςQCψZε—Zbύ‘ φδ4€x¬ΏυqζE’~αΙψ›‡ΤόΊnα«ύusΊθ€¦L’Εcƒδ‚zšk=m—†-­oΧ΄5ͺΗ§¦sD‰αKQV΅2Y€ψZΣ;5β< '`w;\ωW&ΌφΤίΨΉžž8/F>ζ³|±M!Ζ€_2vΙœe7τPŒΛ€₯(½>Υ V–$Oό/”ίΨMήhvΪ¨KœΖ»BΏ‘™4ύ%BωsϋμΠbGr ΄@=υΩvT14΄}‡8³8mU‹‹šηBxƒ]€jβΜw¬1~ <”ζΧuρšό7_Ϊxuq—9ÝΠΰΪ–U™τ"d/ΟK$ωϊpοY,Ό€{€z'r8°‘τΗq)Y78YuλΥΓNεζϋ5TQΕT•B™Χ瀏δ¬^{SΈόψ{Γλ_ψλ0Ώz)μŠMΙI™3ΰ]́Ύ«.δΦρC0’•m²κΟ:#^qKDoˆP½~z>€–tΠ”‡FΨn'ΐv^¨1C@υΩ`φBρέy£Ηϋ₯Z“SώάΧη Nϊ'§όΩβΟΚ”¦Ώ„OJSλ‘ΰ—‰` ]ΐ~ή¬¨Nν<Ρ#%XƒιTA²}Μjγ‰+B8}₯5pΖM©žΆŒ³Η§αΉ κψͺγjΠwh( Y—ZΒW†§Λp sΌ˜*eΒ›Ip ¨Šςή¦¦‡ξχuί&\ΥL)Ÿh·f ©]AV¦$ί”CZ₯ŸΧ¬eΝ0h5sΟΫ8άόκŒ:?‘yΓO½‘ΌRuηΪ/…τyύ±Υ;ό`[ŸfP Uκι8†ΟvG―©ώm”Ώ‘§M.,Ν…Υω#m·'υχτΖ=ΏšS‘¬Γ‘"j/b|ΑΏ§¬›{ά·O`»1Š1θΦ·ΔΠ›<¨«™Χ₯όΰΤHŸF2TiL(„3¦Ma1eό؞©¨ ώ‰GεqMΌ^Ν›yμωΗ·Ζϋ†ƒ—pRύN°ŸΞΏpγ)ϊ!t ΄|λέ‘”ροk' ΫώŸ±ΔϊΔ’©ξEYŸ*Ϊ£ΤMoJΞλ―ύ½°ϊΰ[Γ…GΏ7άzφ3any]Oθ0`Ίυ‘ΤO˜ΰι“R"έ[Ν ²Œ<ίnύ°rƒΈm”’9˜›Σα·ωU}Rzy5Μ--λp$€VμŠΘXΓ?|κωπκΟή›ύΘ–]υŸ;2ΖοTuΗšμ² S`c›f24κnK@‹F mυο°Δ߁„%$$xE<τOLέm~πCπ³i, 6Ψr™²Λ5έnέΊCΞSf?kŸq22ζŒΜΘΌχμΜϋœ=½φΪk­=Ώ³ž\^Š­pcι \[n‡ε‚F μψέ8"pΒδcπψedΠͺ€Α«ϋ΅…°²·ƒ–”'-ψ½Χoξ)?Owl[qΝ€Ο†£CHΔ½©—΄βζξCljrj%€t)λεΒΔε?f~ƒΰθ~Ϊω δΡχΘ€“cgL#ςAψ‡=±%zŒηNcΖΜkš€gGb@ 8ŽΠcΌό©_ ΫοΌ"¦ζƒ„3cΟ³{⴨ż Θc½x•™m€ΤqNΫΫςΛ+!Ώz!V.HΰKΠ·."9 ­XbφT-σγ‹•bψ•Ÿ{.όŸν፠mœ[(…— ‡•ƒπμj;όΨΕfX.j½zαΡ©a’Ό” ον±/–₯ P †ξ]π»ΐΗφαws‘ŸMJc5†pT¨Ωαf %`¬² 4f9‡%1‘ίŒςο3Κ/]FςΞΜa ΔnΕa·μλ΄0pgΫϊ¦ΓPVŽQ4˜ Μd‘{ž0―tlΟ`Akš{aε揄‹Ÿψ…Πkw€ά`ΰ7ιw܎Μ{ΐ3d3ό]RΈΐy*ΟΎΆ>r=όυ[aιων©άx&€ΠΫ?hλŒ„Vςθέ’D˜™^(ASΣι9O\(‡ω3Χu4zύBWQλΆ4δώ­επ_ί]oνhΛ]^y ],ž0rZΖzΏͺ…¬hvΤ!Θv‘nB_ίΰΕΪ&ί¨Mα0ʐοfΌPc$D”€ Μd‘'HxΜ 3-ϋ˜yz°yζν0dvΔΐΌιπΡ‡1‘Χ.}κWΤ ΦNν7˜ŽΠ“ΰ―ž' =OI‡ή”$ sκιΣγ_Π^φΚSΟ…₯Kθ?ύ‘PX»h=[ϊΆmT±\ΰ&½}Lμ;AŠ’°?ω#OD…JΑθνs’k *’£o¬_χλΪG/%ΰ€G(;#δu·ΊΆšR€DΞ`ΕΊV½gŸVΈe“‘ π0”ΪθCτ†mψ”φ& O¦Η5S(*Ηfΐ§]Ξεw–Ϊοq«ύ<Η?6ύηΒO »c:“κΫC£‘t^rM΄™IkdŒ|bΒσϋ₯œb₯αΥ;SyυC«Φ>φ3aω™Ok‹ΰŽζΘεf‹«"–ΐ5¦Χ6ΗyώHsόsI—8-h'ΓΎzτ KΛ‘ςΜG%ψ<”=e«ω;=}`EP$Ϋ»ΌB YSPo΄ΒΗn]7Ÿ\Ά£sMˆ’(έσΉBψώξZ€ΒΎo§s{ΌάΖυςΌ½£ƒƒΊν?ο#e ™`+ ·©ρs2MkΓ‚ ρ›Ψk %`βe™J„xScϋΛ•|ψˆ¦ήΏ_5₯`_{ΔMψ+oΞ x°Ώ6[;αb‘‘-‚R„-Ηiπή―“ΐBXFμψ_­Cψ@σŒ ΨβG•Ϋ½ ~lλύ'#¦PC<‚Λ‡ƒο© qΗΐχf=ψ{r7Ώ€±q>£όDTGŠώ8;d ΐˆΪwAƒπ‡AΥj΅πgφgα•W^ > O?ύtxρΕΓΟόΜΟ„ .„–”‚QŒλ?ό&αΕ}Φ8r{ŒηΩ\XΟOψΝΚa‘Ά–nύxXύρ_ [ίώ+ν‰ΧbΉδ„ΐ~Μ™ž,‚π4 ω#˜Šb_ΘA=…Ο„ς“Χ»Γό0q˜ BΈN6’€ά-όsυbΈ΄Z»υ}――|εŽ`#Υ܊ԧu£Ι¨&t γΣθQ‰N…E`ς[:ΰMβPv=XΌ“Ά x„{§η―Άδί…Ύ‡5x’ MΏŸF?y€g§‡ΗcΉ3`D­Σ0θνs1ΙνΫ·Γούήο…ϊ§ ΛΛΛaee%όπ‡? ίόζ7Γ«―Ύ~σ73άΊukς†ηΥ%@Ί ]&=Ό±ΌηΕDaόύL/<„‹”ν‡ΟΧͺaεG—Pψ^¨ίώ–”€ ₯Χ…υ %¦€i†Ά¦^ύ€βfŒ) PΈςd(]}ΚΆυωφ=“z’ OΠ0ύΠTΧϋΒr)\»Ό~πξvGΰΪΒ: Xm8(Ύ€κ§ΰ]eMY½―ΕwjωPfΡa2b—ώΰ/­ΈΰwwΒ“ΫN'nO‹NΫqӘ6οIβQn;r’H@Xκ&S>ζS‘ύ9τ|`9SΉφd½^_ϊ—Βίύί[―ƍαζΝ›Ανwήy'|υ«_ »»»CΛq„Ή¬Χ°ιΑEqR1φγH3ΰnκvžaΜΏQa†d„η‘r OX˜S*- doϋΪπΏ‡Β΅ΒAcWsκΊ7žή΅—€›$―T΄ρ^䂏ωμ‚&ϊ +«‘ςΡ ‹Ο|\«ό+qŽŸ”·™ό1“ΓΏΟήX1šGπ0 p/kw€(BgΙ–Ό4ΎοΦ{?œτ˜_ᇛŸ΀Œ8ΌN­^α"έo€Œ GΏTΛαr{L@£-05GΫυtθωππΔI·^^Πν‘ω<$P °OΓ€»ΗьKw#nN²Μ'΅MˆQΑΛ/ΏlCώύU-Όxρ’Νω―­­Ω;S¬€αxοa"Α*f}`«Κœ+ΒIpς„‘Ο žξ.όgέψΖIΟ0ϋ{T’abλ).„Re9,ώδΡ ‰ΪσήΦ4€¨ωw 9kΆ}Νκ'φϊιΣλ/Iΰ/κδΎ²ϊ©rm‘Ÿ ~`ΎηcP0 œPΦ|YΛπΉ28β₯ ?ψΪ78#Ξ‚Ώnœ@IDAT^Η‘c‘φιy'o%Ɋ¨χΏΫ–’$7A`Sύ:ψiΫ§€zLΣ+nύ`μdθ'ŠχθΗiix’ΌΉΉΩYδ;4³y·ΜΗcžyξ,ξtΘ€x£A Πay> σ<Όγ†πηAA |oCκύξdλWάτΰŠζm} »wNφφή‹+$½)ŒΓ{γ ϋ&½t9ωφ§_<λv> α«©€‚”’ςΚΕPϊτ΄Eς’&ue°)Gq<ύvtτž5PTή‹7Υλא^{ϋΩΛ―κQ³™›ΰ°’=x³ϋJ-ΜKx'gL Hˆ­”s―γšιϊJ»ΗΨƒI7 ]ϋ«s Εe‘Δz‰Π&=κΣGt°ιω§άόq…xώί(γτεvΏπιt<œΫιπΐβk{xΗ <Έ"NΗγαFϋβιη?M8‡mTzγ„σό'±'‘…Iv^ωŽ‚λQφΟŽQ»0'†ψίzλ-›¨hΨί•„Ώ?(Œ ~b£!\M{w˜χΔρShH("ΐ£ΗΕχ8 ΜGΌ'FΔ‡!z|gx|σξ# „ΑΗ{sψΞ{}½ΈΑF†;yvΣΤ6Λ††^%Τ8*Έ΄r%΄?ύ„ΦK©σfοi$@η$7*‰σE 8ΦΕΟΫΙ„k‘|σ9νν_5ΑΟ>IFz-˜RΥqb―Œϊ·…ί%@O|£m”eυψMπl…_οΧƒ¨vΗ»‡JΫ#q¨d”­mύ{u£dΗj-’-ώσΊ ή©O§#―ήα§­tώτΪΊN4ΈP&,~„σ7ό‘σ~΄<€Ixή‘7Β‘v:]§AπCΫα!#„+λtGlΐ===@Zž¦ΣΉΓI8ΒcG:Ψδƒ!=ϏΆƒρpδηαH°€GxΎ.Β{Ύ–@φ“a`2`‚Ό}ϊӟίωΞw:ή{(<τώ±/_Ύl  Ι{γν›²Δψ²^6%eu» Stζ"oθm”#Œ†ΣγIΰ6ΘPNayX˜ J3V w˜ρ1„!/g΄Έσ–΅0Ύ4>xχΈΌ“6Μ–ψτhΫ‚©₯₯ζνf=–.…φ'Ώφ_ωrXΨzW[&5- &(Dy:ž°$ ρj&α΅ώ™²»υκ΅ΥS©-ή|Z+όoΙI{ϊ½ΧOθήS)ΜγU₯ξ―zέ#QΫ«λ]σύΉ( φ‘ψODaH_ΨΤ 6Έ4’Lυ’γŽ~ΑΑ?χkΉπκCΠΠϋΧΚς€BŸοX—ZŠ(Ί€&y\!ΐ Ϊπ| ˜½ΓΐνΠζ4²½½}ˆVq']ςΕΕΕNΐΓΊ‡p<δλ=~βŽ5δ‡;4ξJƒ+„ΓŸτϊεύΓ h/`τ›xž7ώ„£=`Θ‡p”ίΓ/επ‘EββOΎΐΓ7ΫΛ ž(ΧqΓpάt&?―|'…σQ ?X"<*%œ²"fΕ’ ΟώσΆΰξέ»α©§žκ4L˜ ½~ΖOθ½Σp=ώXΩ“UM™‹ΣcΆ]{¬"o`˜‹ μ~ΜB8Β όaJ0Œ+ψαF|%i’~:,ap' ~0/ήaZξ0ρ΄V` /ΐΐΘ0‘αmι€1FzζΊD§φcΏZ―ώu(<|#μ—΄;@7ν!Γ•ŽχώM„1€’ό{MŒCD-ZΣ‚ΎbΉŸ~ήτ±­}*§ ‡νz&Ύ *Ρ ΰ]XY^w­nP’¨#nΔoτŽwl Ώm‹p8†Ÿ`T § σްΤω—# œΪQΗ8κ›oά1Πί<Όσ@ψCΤ?4E{Βw„2qH:α›p] qŽΪ#MhIX”ά= ” Ύq',Έ(σΐ6°’ρp'ω₯^A`']Ύ=o`ΗπG\ΰ~ψ ε'mΒπ8žˆKΩKZ—{ccΓΒwf2 ŒƒL%*jŒ4Έ/~ρ‹α/ς/­‘{„©Π―^½]»v$5gG<π[¦j7Ε5ΝΰgπΛΘ—υ2ΑL0 gΌ½©9Œ0˜ „Έgx0Lόq‡aΖ<,n0P ξδ‡ιMƒο΄!iς– ς$άu Ηκ›νxAWκξ|βWCσ΅―„βύ΄ο”‚Β%Š—ΑG1]ΟKΞQ€Ήƒ‘π׊ώΚ…‹ΪΪχΌΆφ©η¨|, ΰR’ιΠgφ»ΐ+Έl«<-Υ9Στ8ΰεp;…πiγu‘vƒ EPzμϋ{[sλz/‡κXδΒhυGέS‡ήF )κ‘΄±{…?p§i ‘J›rX _ο“&ίψΡφλτGΊ(šΉ;iΣ\XS6άΘ—ΓΌ²½B“τΫaş40žΏCzθV0ΐΐκy&ωϋγν“ψ„ΓΣΕ%Έθh—π(ξοeΗύΌ―χσχy„7SFΤ Ωφ•+WL ψήχΎΧιe\ΊtΙzώ Σѐ9ŒHφ¨·xΘΒ-ς’£ώcΊ83ςΰΐ£@˜σ€1ΰγpΓ;ρ`ψσNΉq'eςoβΰO8”ηΗ·?0yςp?ŸNΓσvΫΣƒz<άΘίΰΣ;§Ϋ•΄χž“ξφ»/όRΨ«ˆΎ Kf_Cί ή kqp¬±|ύe9ψ,]Ώ©ωώgcXΆχ)Ύ")rG–ΑYύΝ°XŒ,1ΈήWYΪϋš¦‘viƒ!Β‘ Έ?n’¬cwOR6t(xΰήͺo| t…k‰ΡD9ˆι@.π]Ψ#Μ~Lhw§§lh†pΔ.§Β:œΐDiΑοτ‰°EHΖa§\„‡ΆΣτŠ;°π ΄]ΩΔݍηίk». Έ”lςχφE<Κ…=wŒγ~ŒψΫ{ςΰ‰΄A!-/ώΎqwœπNY<= tŒOϋIdQΟ82`DΡhP4jΧζ?ϋΩϚLwόρήMϊέέΪtΦ$xΨ0ƒήΏη 0gt0˜aΪ8œΞ¬(L›2R6Β€™*ί„Ηφψ€™vχ<< ρΣiΈΏΫžωΑP=oΎ1μ (©,,R3ρ| ‘α§:μ–/…Κν/,4w΄εMΒCGߐ'yQΌϋΤ@”bRT6ΚYΦ­}Ε+ΧβΦ>)*”‚t’e|~Pϋ@Βίπ,FZΪHΉω‹ΖνnΑ_]—ΓoB‘F45£ΞιΏ} οlνwNύγ βSΠm›ν‘Ψρπν~ΦΫiΈbΐ»ήύΫmς‚–]ψcΣ>q#έ4Φ•ˆtšξξtξέΓ€mΟ7βρBMΎN«δΟγ=}ΒQfάPΞt`ƒ ‡…†t˜Z Ouά9\^FF,xΗeυ2τ–έe?` S ƝMˆ$ FΕ·Οψhάg o"^§ƒ€ΜΐΈ§TL*?°Αp€0HΚΡk`(0(Β8Sςx„u†γρy₯ίέRΌ’7Μ fFήΐIΪΨ䏻3MW Ό­°σδσa» !Φ·1,Φξ†6;δ‰šΰ’₯‘€g±Ÿ*/VΒςG^ωε5 ωKΑΏ~b’“Β3:1Ψΰʟ¦)c ’t17τs§š ίΊ_ ΛB±tC›’αΠ!κ‹|©+πΤ• 1x|γPKΧ1υμO:ίτ»—6Η<8ΆηεizΩΣρΘ§Ÿ™†nIŸ6Δ” ͺηOωxηιtδΰex΄1hœ°ΜχΣ›'<6nCΑWzQ#aI'mψφυƒΚ›?ξ;ω9ήǍ3‹pσΚw°Ÿ§42`DmAˆή¨έ¦Qφ6ŠήoβMdθυ#<šΫ%280 ‚ž‰3˜ή3εq†MψXφd@Œ­Ÿ™Έœύ‘Έ…ρ!聆κ0—ϋΑ$ωσƒ mz;Ϋ=y"<Όω?…έ;ί WφήVŠκύ.hθX ‘g„eUΏΆ„ΚΪ…°όœNt€ώΈθ›’Žδ3|¨LπNyšΊ΄θ8Τ@Ξθ¦_@’_S0%Ξό—u„ΐq‘ƒMAGώπ&κŽoWœ†ά«Σ ΥGH‡Έψ!d‘Οš2–*N΅+w'Σα{ p»!8ωΠkΟΦGO<”ό}аΩl¨ Ζ (ΰ| 6SŠΔ‘ ΄UF‡Ÿγ–<φi|iΰζuα0gv†AΘ€A˜ιγξ ΞZŸ Σ;-'½ζr»όfμτΆA¦…Ωΐ\¦½Lm?aΐ< PΚːΉσNβ¦γ{Xό=Œ»₯νa~€G>0βŠ„?ΧΕb`lΚΜήρƒ™¦₯ <ΚΉΎ΄<ρ™Πά»l~7”›ΪVeSŠ―Ip„ύ’.ρY|φy}£ œνUώιrŽzί·:‰υ"α¬Ρ¦=¨·ζz‹@© «„T&λΨ,ς[*„ύ°ξΦ5Ÿ… ‘Ž$6.Τ©+Ύ]PΉ@Q·ψσŽ0#އυw§a·SΰzE8†΅iEΜc΄*O‡k»ΨΛ _R©)*€LNWύΠγι`Sςfς§Œΰ₯ŒψyxΒ2ZHX6εζ)k ~»»U OαΆ··” Χ,M₯l€ ŒΨ₯RTΘώpγUαυŠ»ΏΗQψMύ“&ŠlL##{ζ(qϋ(ωΏ­Ε ;;l§+Jhλμ >½kΪBΧΪ‚ά QšηKXp]'6JέΔ¨xδ?αΩ‘²“lε#_Βγ‡ \Ό3€M\žœμπΧ΅Λ₯VSzr«HAΐ ΄X8α(―)p@‘`$€ψδπ§Mγρθ-Θ’:φψ8 ~2szΘ€αš†θf""¦]‰ζsœ¬’aU΅hc&Ηm Δ76Dt˜EdΌΌ§αΎ’NŠ[:X2AΝ7Œ0½½Θθb£‡qΑdx`ΰ… ψθ.ιΐd=Νtή\Q{p ?1Η΄;0˜‘;ωΐά\9q&Lx˜ŠnδΏ †ˆ;ΈŽιi=Ζ²VͺiΤ’Y)…ZωηΒήΓkαςΖwΓΪΝ'BIgωwΆψY¦§ΓΤ’ž¨՚π…t"iiΞ:_ ­ύx‘⠁ ]ψ%3Μ-ι†Μϋ?¬ηΒ?ΌΛju }VVD:+%΄C‚ €Š”KκΕ„©„f[;, „Γε ƒΣϋ-qΫ£ά”V—ͺGβ‹ύ ΰύr#δN^υM―–°ΔYYY–`l˜`…&¨}ε…€ΔΑΙSΉ„GθcΧtΝt½…Ά u tζήΧΦ΄κ^πhIƒςO™„Ύ€“τ‘Klh”ΆΆ–Β΄Άρ‘)lΛΒZ ¬’gt&₯οy«¦,Ϋ ?5~ ~JL»fΊ₯!e΍΅#ʏ’—Χ‰aI;JC«ΛΛμ1fh[ϋ›az=IAΗW―θe oŒ$Φ{όν œ}Ξ™pL4B΄κf„ηn>žΊ&V$9‰1>'¦° }ΥaCsΧT%ꭚ,+)+άQ¨¦Œ’ά2žΖ(¦γαbδψΫΟΝύ==cΒ_yš‚ ζ€Νˆ‡έ΄Τc2@v}oWσΦ ‘Άq;TΆ(ω ι …7ωβ‰z&ηΨvΌH€.ΨΈΆ²€Gg<θ@€EmsdΈ}eI‚xωBh–„ƒζ†Ύ0FεŠ(pΎzπ“Ϊ*šλΧυ‹αΎzπΧ/k] ±„Hz¦ =Σƒ§ΝΒ3zΖ g3mO2½€oΛαG™…n6ό/ΕΑ§q¨ΘΪ’ΧIΊΌ°ξη6ΓBFa™6Φν΄ί w›²iƒ’Έ;`­kŏήίTΈ^―Cίι|Sΰ )ώαθ‡Ύ&ϋ0εc²(GB;ΘG<‡ —YΡ^ώbΞΌ§Λ=(rζ>12`b”Q―,JŸPψ“’±-~$Μξ«Η’‘Αƒ5υl€ωΣ‘pζAΨΎ&έPϊμHςΣ¬žΧQ3ͺy#†A˜ 6†•Γήbτœˆ„‘°υ)Q$ šυjhk>wϋώaaχeυH姞‘ ΤέH‘Σθ-―ηp,{dή€ξeˆπϋΧ±ςŸθ¦;yJŒ–'ώ,ρ0<ψZ–ΙK–Ε˜™0 ΦϊΔ‘—9qγ3Νў%οs4Βώš1σ e+~ ψM •ΡΧ٘~_Ÿ1α!Ά"zŒ°‚Πslϊ°γ[±η――B‡Ηζ΄΅+΄φB‘²ͺw6_KΪ{'"j>†ΑU\› ς0Ηψ 8j£ψθΖΔzαR¨/‡•ϊ:AsεZ(©ΦD˜1,^8h†ΧZ7ΒλM-Ψ[¨i*E  BR*ζmψž)EzτκΩ³»„…jΆΘOίE 0B…FaΟθy’sώθGωH`IςΛr :q8šŽ°Ρ 1³—gύς;šGT5rΤk—Nή“G6ΌO­cE†‡©θ  ]φ6!2`„ΑœF0(λO8,IύDž¨Υ/bΚ2·-€˜Kρη‘ N’§'DΆ}{π` ›|•Ξγπτϊr§·w$ζp‡$ΏλΙ‹…$Wήζ4έUΑε₯Υ°yηϋαώ«gΓώ‘Gz¦Γ“~|YγΠΟtHWΒwgω™°\Ώ{8ˆB0Λ.h•ΫωηΒνΦMθΚY)VEυό΅>Ν λύKΐ—u`‡61ΌΏ¨a~κO†ϋqσ˜&H―ϊG€ώ:‹A•ξ€δ`… ν21•#ς‘"zΈΎ„Χρ•ˆξG‹ήρ"AΣqτd»_ΚΙ\»#-‡}ψŠqz‡Ω€dG\SΙ σS0!ΕpD¨Tz=―Gpήγ?Ζ§ΥO΄υqκ¦ΦΑwΧ){;>2ΰ8ŒΓ¦±)a:£ujΗV£ΚνihVLάz«ΈΉ¨t¦ρWΪΓΫ/Ÿa0ς“;myͺό;i‚sV³J«ΓΛΛaϋήλα½—«gAšςJf*B@dψ0ιΆz―o|σ/΄ϊGBF»'ΔΐΩx(#ѐ@α/E?Ό‚wΫ€"!ΦΌυΣ!ƒΏ ϋ7>ZOύlΘλœ…’›i•tJŸŽk·J’σ(όή.Œ w{Zθϋ?ˆ[ύsώέS)Α*d*Z Ε&ΰzG±ΘKq‰ZC«­ κέPέϊ0T7ξ„fmS΄Β‘=:δΚ„Tl!)‚š'eΗlKΛΝΰ–‚nB_J€Ξΰπ,€|Q·ύ•–CQ P ežU{Οu¦L™ =ΝαYœ¦(ΰ#¬γ@η‘«°‚“΄ χw―ƒhΣαO €/Wξιeο2`Μ:§a"όapœνύϊλ―‡‡†Λ—/‡§žzΚΆ=Ήr0*ΙCŒΟΈ™bp[­ό{T"³? T‚μνo}9ΤΆξ†Biɘ;Σγ ΠlΈv< υθ]ηΥt·O9Y cqD»˜‹οΆ^Ή~ό !·v#DΣZHΩFψKθ·5·»ΰq‘‘ώG `Ώ?‚ί•άzβ{ΟϋνGθΖϊυxτΠι΅#„σΪy€iιΑέυΫaϋΑΫ²ίυέ‡R6Lθ{%[| ZlοαλΕ„Έ%‚β=ΠDβ'ϋ.t wτG’’Τ‰ͺ4Q  IS /„ς‘ΌςD(.κΞ) 9";Γ3§ JZ@Ώ~Ž*ΐκuSϊo7Ž>λ6πR–ΜΜ™0ώ!V˜"Μμ«_ύjψγ?ώγpοή=λύ_Ώ~=|δ# ΏφkΏ>σ™Ο³›Έ1Β_8heKΜ™(Œt;c@9^˜πy50Czqy «w^ϊ»°‘UτΊώWψΓla;ΆkΣxwμχ1΅cLω!ΗΨ'’±£{eΗΟΔ‘ο€PXΰΟ„1e½pKK%Lu^€Ξω³ήο~»d=Cz‡Δƒή] žλχp7_ρOXβ» L‡λcŸΒ™ΰΥp½Α€#ˆυ΅Pύπύ°uσΰPΫΎgΒ °SΑN#TόAhSϋ.xlN?†0\ ?Ί˜Τ·ς%}S Ԍ€N$n‡#2τr°ϋ@)ΰΦBeU[Uuς“‘rα†hΊJϊfj g{8γ©€ΐΏ2`ΙC€ŒήΔΌx{T”ΓΨΛΎN™0Ϋ0>.α`“?ω“? Ώϋ»Ώk½ξν¦χOƒόΰƒŸώιŸΪ…!Ώψ‹Ώh ‹xckΈ΄mΞJη [  δ―Κ `Θa€σθ΅Χόή›ίw_bE!0†<²@§ν“—ά³Ch&ΞΊε@vηΠt§Ίΐ»°ΐN?Π&ΒΏ as"ΘD†ύf Cί‡Šύ›>Ώ_οΑOΌ΄π'ηtW£o„‘‡Ν0?œή>CθΫή λοΏ6?x-μν¬‹44g―Ρ ΌŽ:^Π)rfL°sT·wNs2c/ώ%;yu6ά²P&΅Oπ́Ž`ξniͺͺYΫ΅‡·Γζ»:\IΒ% "e¬’јβ›ZΘq “¦  O¦LρΤN=‚ΟΡxΟψ²—Η™0 Ϊ2Η³{ι₯—Βώαš"pεŠ4χd·œ‘ ΐ Ώϋέ|δ#α™gž1ζ3v„Ÿ\RUΨιjΩƒΛX}ηΈθyήΪζύπήχΎ"†/α₯žV§(EΜ€Νp:4)ŸΧ™ρ]YίΥEH[pw}O—5Γ§>Ί_­yR˜+O§pζρ+`MyάfάΦ‡γΫS$0γ³ττ£€¦Τψ™Ώz‘ΠΎΰζ#ΠΎ+ιΉόΣ q<Ο4 ”}-ΒEΑΟC:qPΓΤΥΫGΰ?|ο•°«ή~[‹ω˜/h$Θ ΒΨζςγ'ΒQ%Wήρϋd~•ψ°τQBR ˆAΔβDM]X<ΥΩ~cW—l†Ϊƒ7DΟ:²yεj¨\z6”₯+4]#ό©¬”Γα3Ο‡ž4nywE_Yχi?β€€΄ίi½ΗΊ>W-ν΄Psjωd ΐT3ΚηίώνίΪύαw #lzD\Σ S|ύχΓΣO?=0Υ~‘ΐ9έ’ξjΠuέt·ζΚ€ε=Ψ³β£…Ι«7xϋεΏ΅EΝ³²j[¬°‹$cΘ0HΉ%ιnEό}²Ϋ,„{ΫΉpg½e‚s»ͺaγfΨΤENΜ-o?»¨ _ΨΩ‘4fˆχ“FcUΏ)˜]ψQηώŒŸEˆž:~.J«Χγθ»\”^›‘[/ ]0I]zg…oπέkυΫλ—}?ήΘ€υO£’'τΞ;ο˜ΐG€ΩqG7‹ PxΗζ›θλF$}Ψώύ€˜]€ΪqŠ‘<έW?ζ0]JΣŚ<ξΠ?ΗΜήϋ%ψσ–ζMWm57½@3ΰΞ‘₯ž—€ΊΠUw‘Ά•π šW_Β~»¦ ƒŠ―ιέ w P)κ€0]αζ žoβΟ^@ρ{„ί”.>c ύPXΉ‰υGηiάπސ)ΥΩo™ΠΕΕΠ7˜ž? ›Η…?6ί(ψ˜PNΌ@ΏGt#ΐΈβ‰Νϊ^Έσƒ–lΧ½κB‘υz4―€_"eη΅2ΌΈš Λ‘ΊΏ¬»ήuί»|έέΩ±΅ ά―ksus`Sw¨ZORIμιαCόω!φά) Π4BΫ„ ~άιω§KθŸΗ§~Ό{~iταvΤΰ·σεΥ³'Ο»oώGΈϋΪΧΤγώžή~R–£iS—^PnΜPWš@%mιΌ†νBώώ«‘tω…PΊπ¬­έΘλΚk)a΄DS8ŽwήγA·Ξ3^Ο΄§kG ³; d ΐˆ*§ΐτ^xα…πΖotzόώ ό™ΰ›…„χ‘ΣΙGo ΫΏ#°,¦X£Žμ,uΚΑy0gcΑv fΰΏφ±ΟΩͺοFuΛζmλw’k^u?hhTΗάΆσKaG‹©·5¬Οξ{ZxΥ–½―{θϊu]Δή0?ιipGυ”Σ­v Z {ς+λ]^ηΘΠM ΆΡξΜO6Ζ…=|zςΠš…vμFCϋεεζ=ΒΉ?nώ›§Cϊ.\xΗΈmκ4α ΧΟβΎχσΒζ‡―+>=ώΰ'™ώit{4^|QS(·ri„DΗ7Χήϋ—PψΓPΌό M<Š:ͺyaAGa'λ9¨ƒύ}ΦhΪKοΤά₯ρΗ;υš™ ™0‚h,0Γ_ψ…_ίψΖ7:½|zϋ|„Ε‹ΝF @@Έ€œgΡΟΝύlyϊžβI°ιk<ΰŸ3Fΐ΄··gp±p 1!.“f,γΖ?v8εΏ !Ο'žϋtΈςΜO,-„ΊpΣ’ίΪΪ››RTWΪ§]«ή;›MαijΕ_C6υ{ϊ]A₯}πBzC‹0₯|΅”π9[Π—ήzρύ9=W«UζΠwκ™<ρ°ϋZO+ iΟ;x„.H£‹ΣaΒ_‡υΤkqυΎβήωώ?hWΗΏΪz φΟϋόΎ’«\½ε|$Ύ)<†)-x§κο φ ΤίϋZhn=ς—ΤΆš»6%@]T\׌€χzΑξW/Τ5†z›—qΊ›Wώ{Ύ™0€ΌQΠӁYώΔOόDψΒΎΎς•―t†ύψ(<(7nά°)˜¦Η|ΧΩ·>‘M‹jΰήϋ'DlŸΌΫΠΨpΑΟχΈ0ΒLj΅šΑΐ4Θ< =’–ζ큅«nΥ52aί”bD Ά»e·ΛQFΚ€„z[ρόπ‡f¨!•ίWO ΥJ²)^hh‡'ΞžχIΩ]ήh―klh€ή=ί.ā όρ ,bό( ωχ αqαβv:/K$υt¬Ώ¨ξ΅΅wύ°}ϋ_Βφ‡oκ€NΤc«ί9žίO•sv―ͺY£ΕDЈ€ΈD8Ψ~+΄ͺ†ΦΕO„όΪ³‘€»ΈzΩ”3)λ>BC[θWOiψ&αιxΩϋωΗ@¦Œ¨C %ΰ—ω—MΘ³%7ζϋιΡλΏuλ–}ΣSv8"ιθέεάςΣcΕξhTƒξ珛›^ψρC©1Αš0λφ°ψ;ŽοήΌpλgl―ΏV«©CSθ‘rŽ»B"ΔMΓ΅˜OΓΚ’’V‘£0x~δγŒτ) †$Šš7e  %…TΞ£Aq‰Ζ€…)2ξβ68ΰv1ΰ€z/ξ†?ξτώΠwz”ΐρHΗ§§λΆηηΈη›ξXηxβίΈσοaγΝΡΎΊφΓkΈ_‹α¨ΘL? /V΅τdXλ’υ,αΑ·tτρz¨―½Κ’yŸ‘^©S¨SWˆNέΉηΤU†{ΗΘγcg ΐuMγ ΑΠcϊɟόΙπ‰O|BΓΚ‡V#ƒA’Πx|Ž}Œ$»A7΄E•ΐjΩΡo >θBΨhΰ(ސ½αjΤ€AΌ~q=]ΚΕCΪ ι“6ρyά7ό`DΌ{ώΔυpΨ|ÐΞ4CŠ8όKx`lΠγ,ΌSf ιΩ–@α 7π#g|„s˜pc»WΥ–Š:_S ;υρΞƒ`$’WxM“—ΥλΐmΗ‡Χ+ΈηΑγΈ₯χοΓξξυLxFΨθ΄@ϊΤ“.PΐSTΟ…¬ Σ—φ₯d½χέΎύoΆκ}Ak8b―Z!—Μ Η@‚$)ΊVΫΒ_Ύϊ–Ž=ήΫ+?ͺv)©ύσd-υ@Q7ήξ°ΣmΞλΞid8 ™ο£‚L³&½αloo›p{ςΙ'-&ξiα9(Ή ‹φŒ[” Uθ6± 'ΔmC$_„1ΜΖ…`ˆΐ@~ΎW;έΠρsά ν“†υΈΔ‡yΰοe$Oσ4ω& βΉ!Ύ~ΒaγοαI‡&yyšžNΪ&Fax€ΙΛ‹αΚiΰ–VT<™ώBα#uL!\ΜKu­‹KΪA³\ οι‡uθc‹ό4’Γ|ΏΓt¦‘|ζ€K˜Šΐ‚ΞFhκΜαΝΕO„’P–ΛΊψH[g©§lWΌΑ½·;ή©Γ¬>Ξ\eŸ@™0ji0Ξ΄€‘±x#ΒbCFή€Ήιq y94jΰ‚Y ΜaΓζaάk`NΒΑ$CXάaβ<€λi?΅χξ=yΓT€Ι……»{š ςV a]¨“¦3’^XΣα‡Ÿ‹™€Ν—Χ…Ϋ„ΗXGΈy^ΐDoiIjA+0λνB)―Ρ›θ…δl~CBΎ'|„ΰΓ οŽp ½€κNΐ/λ=Η·+^¬w‘½Nq'Jx¦>HoEq9»£šwkΪ†Ήυ ά}ωŸΒήζ ω―„Mψΰβγ€eφ₯H-μ„₯κχΒfγcͺ³=μτ@‰o«Νvοy žx¨[§ o|γηξS”E9GOڜ£4¨0L‡7ςσuœΌtYŽK€ΰΑpτ.Ώ˜,ωˆiΘLC°!LaΚ;κy!Œ]ΰ¦α䝲–Έ„χƏ»3rό=='-ς# icˆοy–pτ]θ†όžn.Δ Gzi†„Ώy#CΨ„ΗΖ ¬ ƒ†™°|£€ψH0ςD偓₯< ψ7ω—Ρƒ^€tόQ‚a+άΝ Ml‹JΉιhd)€Ξΰk‡‡ ₯Ÿ4θ”A~ ή©κΡp†Ÿϋ3ͺγJ“§γ΄Bω­¬¬…-Ι°©³ͺΫ›aύ‡»5 α―ΩΎΩΥr=•Μž$υΗH@>\*mι0¬BXo^«I;υφš¦ΪH―.0Πa»΄Υ2ϋ>οΘ€³Pƒ(Τ„²σ˜"?αΡg6‚Ÿ‡Ξ⎠Tφ4όq q{…‚7`<Μ#dpslςAΐŒkL‰w`φ4af€‰G˜ω6ωC―ΰεεlυ£š+e7@³ρT;ί^€ <ͺγΒzšαΐΕ0Σ[ŸŽ;Wδΰ|β~Ηγ8Ζ-m|έ αΩQ±ΌGivw·Γ—ώοΠ­λrzώ² 4ξNζ:§^Ε“)`λ…°½Ώ¨Ί₯ηw:-8Νx;<½ίξžΩ2ΰκΤZί¬œoϋπxrΧ’"(‚œ§WLΡΘqΗτζ̞‘[:CγNgξΈΣd,―”PπαύtxƒIω7BELX„ yΖ{˜ιΈ½οoyHƒΚ€€0r%›<€όΣ‚ΝΛ .bω₯8μ©ά:o}!§•μ[oΫΊeΠ Φ™ϊξž3ϊ~€ΊŸ+MΤ7Jšγ wΗ«Χ ύΐSΪX=« ΓϋΎpYώοΌς7‘΅{?ΞωgΓώi”ψ;*šδ}X.ξ‡ΛΕΝπήΆZ¬ BηiΎ NΌ{}ccΌmΖέΜ#ϋyd0pΈ5?2Ε:GqΙΝ€eυ¨wQŒ\"ΘιαΪΠΆ„‘1‡εp4(C³ z¨λΜ€xE=°K-Q<έ~"–4]9‘œςΕΰœΐ ³*j??‚‹ς θψ<„aQ#ιπM|Βγ^Χ%CΐWQx`«^„₯[?v΅ ]Χ’@\ΓΉυ‡1h œ™ŸξT&ΆΦQ6ŒΫύuά‚”>p„wŽcπΔ~ςšκ<γηυ UεN½¬jw@cO»GφZaγν6ήOέ^§~2αίυ'κFΝs¦'a^]i„wΧw4 ©ξ’«C―GlΪ?vϊ9Q {wžΠγœ}ž02`FΖhGfaP?όΓΈν{x,ΒўΫˆ[΅3η–s]n\~‡hιmkQŸ]05z€yσpƒ‚ƒwzƒEV[Ότ0ŒHšœΚ£@`V%4vw«&θ]¨πp±aI§ήΠ@ΰqδ‚0qΞ™i), ές#ΈyK,D νIθsd\ρD;ΞB/HhΉ2@J€νe‰·₯EΈ#€΄ι΅"τΈfu!§-ΕΕ°ότηΒζλoxa‰U/\]ησfBZIŒΡ„κp_Κd±•8ΌŒ¦°ύIhΐ£R~NιCπiσS8πZΎ«RX€AΑΒPˆp’_A+ό7_η°ωΞ·γι~(~’•³†7ώ‘!π—t΄ψ₯Κ^Έ½Ξ‘L΄Υ¬W| Τ3 ΫξE{Γ Š~ξ3[Ϋiτ$σ˜-ďFj™0£z€‘ 2C‰šΖ¨¨6­Ϋ™»3υιn~PͺlΠMv;=M q#΄Ι‹žαοCξ€ΒHpzAʐ/Œwη %ν‹η›tP&ŠJaΚjb˜>`!0@‚5¦‘₯Gήϋ@f„Δβ’†ϋ•'!Ν)~("ρ ~RΞΰvόΠ”₯·ΰδ`²+}5Dί)§Β“?επή)aihΙ wφAKAσΣΥZ\‡`(ž"œEΫΪΆ¨© qΉ°¨rΥλe•sW­\ ΛΟό‘vϋŸ„›ψΜgΝDˆ€OF?” eNˆ–CdκΠ…XΉύQ·φΰ¦wF?ω8Π  τΎςrwC=‚sθo ƒςα¨e­Υε%τ³6οί[ο~#Ξω›π?{Ές2=ςΆκμ#οo^ αΝ{΅°SEˆ½ύ»68ςψuŠM„ˆj2~νS‚'EΈύΘΧΟ)`¦³" X˜θ;wΧΕ 9?=-§“ετF ™_Ό/ [£ΜΝ¦΄mζβ>Δ ΙΣϋFpV–ιΞJ@³ jκή’ΘtώPšΝδς—ρ€ ¦ήzyλ~ρ€-F€AΰƁ`φυΊάџε#`ˆK„…y ά …Έ=,_P]aΐy›§["7π„°wψ¦Έ^3e#²Γ…Ǎ¨πΝuΐ('*ž†šΫa£Ο A)μ²ϊ_—©l(&Δoj’½ΏkSp΄₯#˜σΚ”“ώξξž7œ;ΨR΄o½πρpΉυ}Ν’Ε³5΅ΦY¨Ό;U• \θRCi‡ͺWmkιŽέr¬ma!T΅Λd[ΗoV›Ϊ’WK‹US`ώq„D8^― ΒGJ θϊGY#,†x)XΫUΥΕ½­°χζίؐ?gύS'™™ ͺ°)bΈ΄’ΡA­iyσνpω4-IιΥ‘A(nRξόaϊ‹Q; *h: ₯₯ΐ%fκ£ΪghζζΥKv§όκ„r:πΟk’™0ƒš£loΧΒϊ&σΜhΡαTΒ6 šϊξyΥ(y(KN5[Σϋώ8 €Q­¦a~ »%1x+BΡLNω«αοκΖ5ΣΨ ω™Ώ2Θi;–‰;B‹½{<)9 H‰Ώ’Δ‡5F%iΤΫR$φG!ε&y€€Ε;—Sϊ^hοπÝ,υ’Žj‰BΙΏw$taSfΘGF( YR²P$ΔΰL–1>a°`Jq(‹ΚJίΠgqAΈ’·•N“ E`•ͺ…ΆŽήηHaa’©Γ”ΪOθͺΰέp-[ιQ9ΕΙώP&7T/4ˆА"¦Ν‘Ζψ™rY"ςͺ?ς"2 gM΄Ψn?.K;`H^·ΜqpΟnM§ώεž8hͺ(‘η–pΔ),ξΟέzXΨΉ«σύu―¦7€n*ΩΫιb:‘枿V ―Ό©σ-TϋΕ’Ξ~ί¨© W–υi†Ε½†xP<( €»˜JcgG\ Ζ¦z‡ρΆYGmΎzεB¨ C'’Ρ¬~4Ι€)κΡzŸ qB΄τ|Ÿ½u%άΊ~Ή/Νf”YΠΐό= Ή?)»€πΘ€!ΡΘsw‡€FXΡκlŸ—ν—ω{R.8zΏϋΕs7ΒztŒuˆvπή«š5m Τύσϋ‡κ΅˜μ{ ^%zξj%ΌygέψXnAΣ[E]“-α_ZζόΝΆι -ΤόAόŒ6ΰ XΗ΄H+³*πeζτ1)#pΑ»πΏsηNψύίύπ•―|ΕzߍŠ"πΟόΟαsŸϋ\ψυ_υpγƍCLwDς]ofΚbβ~$pΧηΨo0ϊŒ9FcGΰΜŸςh\IG«ξλjΥΆφΈ·–uiPγΎζΩXΐΐ0΅1 ϋΓ Α}\cmA‚>―s"ΦίύΟ°ώή+Ιi™π‡σG3ΊΓ–ΐ›OTΒ²–ΩW΅κA4ΝΘ%BŸEΔl€ƒΓ™<,†₯CύΓ©η%nΟ£W ¨ώ˜hiύΖΛaIӍρnŽb’DΑ•‚x?ο(»0 @»ΐ@?#yΫ\ œe>NΆΫ0g< DNΨΨΨ0ρ*|„=6 €²ΒA+ή`ΖnΞ›ώgUV#s§―»΄ γc$ΐφΛK (kW€=šΘ-^G”ΰwΔηJθ I£€ΏΏ»νΩσέkϊΉNχγ’€^ ;ί‰ηύkD`žeξ…=ϋŒjΪ¦΄ΨψJIO!ΤκάΏ‘£Ό H¦ €ψ@z`pN™ΟyΒ@60’Ά`ˆ0ώkΧ™°Gπ3€ΰw២Q?ΆρžΎΫιΡdw;±,ΰ,1€ΰγρa¨W聡0ΤR[[ωΣT@c=“jηπΓύ ƒŒ+2ξOϊ zχο΅MM0<„ϋoύ»υό{ΓdίηΤ%³E7.WΒΫwkκάΔάόιΓ>8έ€i‡χ^ϊ:˜Θ ƒΉF†Ÿθύ}κSŸ²^?%ΐώΈσ\Ίt©³ “ΐ°Z$‚žjΓw<βΒ?ΝD†‘g^~i¦Ζ»?((vC"+§YΈΈ¦σπΉϊx>Γΰ¨ E€nΊoΡeρK?žFΗVΩXω―σα7?|=lέ+φώε–υώ;X:W/ͺςpλI-5Ά₯λ°ΉΘ+έσg €ϋ(€+ιQ€atuς›)#*f_Σ]θŸόηΓ'?ωIλ ^½z΅3μΟZ¦\Ήb #-@FdΡυΦ­tρŒSφ6? xΊπήQx8&΅¨žwyiMwμ°&ΐ‡ΔΡκNΟΐΠσRyxeΜ?-άύŸ^ζνeνu·TTf†<ξΏωο2žn cY²ίγaΐθDŠ"‡]Y+‡5MμiΊeaο‚»wΐ§tt<ˆ²ΨσΖ@¦ ¨gˆΨhΏττΏψΕ/†~τ£ΦΓ_΄‹Vt‘†Fxž|ςIΫ ΰ‹d${Τ™ξά΄ ή p·£‘3—SΖ@š¨[ΎyβHηηη΅-pE{γWTœ­Κ;5ιΘ"<qvN£δ1朐ζƒή‡’SεD8δ ₯°σΰΌ‘ήΏυώ/CγgžgΤ W α‰Υ’έ Έ/Ίua?Θφώiz:s…ΜΩ€¨‚Πaφ{{{&ΰϋ·;ΌτKΆΪŸ ω#ό±Ρi(1G„jΨN²π„¦€mbεdnŽλ n'ΒΥq3œ2>0:¬ΰ\βΖ;#DLͺ–/†ϊΖΫΚΑDς”9MΝτΗΤτcΠ½n½ίιάIe†cUΤππ½οι¬ΊNύΣ1ΨΊ.Z₯'—t”μύ\a žΌTίwΗ¦r GG|ΐ…ΏΫЍ?ιΆqŠŸkΘ€1bG ¨λ ˜ώΟώμϚ §°*ή±§hπQnάΡ;Ήhn~ΣΙc`δρ ’ft.ό΅0*ΊΈ¨…€fN[ώ+?‘tJθl0ΈE»Λ¬£K_hχ1₯GΒ?―³βuςζ]o‘wε@#Θ„!tΗ«+ͺΖx)Τ‚ ςήΏ ~ΎyGπσ―σiοLLΝσΞ#ΒA˜³)€1*Υ™?Jf{{ΫF ~FP 0S η₯‹€psKνρψ9"xΞp±½~±yrw»€…€§.%³c/];4 Q` w-{z‚WπνNώξe‹ΑH8ώΝoέ{3ΤwθBD.DΚ4Σ•ηΤ"–κqmYWDλͺλF“Λβ?ύ”ά\π;½PψH η Ψ†Lƒ zŒΫ ύ»2€νοc$u4IΓ±kb¬LτηΫGγe.sΓ€+IzB\²R,/ι )q½=ι„H%Ργ"ΐδzκ¨tθΥι6ΝΌ‡ƒ•$ Β€8ούgF–Γvn|©Oθ·₯#Η/,—l- #-νπήΎ+ΨΈωπΏΫNSη¦ΰ }1)}Ρ2ά‘Fΰ `|¦:$Mψ-wp@EU’u²† kΎ^ήS6%@’ϋΤ1-Ž[ΠΡΈΜ™£œ–!'n{΄¦L+θκ!i:u˜ϊΉΉ_΄cοŸmλ^Ψ~π–ͺlκ%zω‡ΟΎΞ¨Ch¦\Κ‡KZˆΰ§7Ορΐπ6ϊi›wΒ8ΏKΏSv§©σ„‡ Φ쀩h`&8²a«$Θ’†jYΒΘ§p@€³:d7GΚ3/g―δ|NB7—“.-JHVR ΐ Tΰ€Σ«γ.Γ₯e}4όΧn{’‡hCε:³ΧΰFΨΈσƒΠΤ€ά‚?BΉI&<^fŸc ˆDžΈΐ}ρ²lWϊώΈ»‡₯ΤNO½΄tŽ1ς؁žΜ»ΚαΣΤBUΓl,κ#γ³σ•‘ωw•­`Ν+ρ€zΙΙ£ςwdšΣ@ ‘X·ω[€6 7LšAϋ»»»}ˆy7zH©YΠ!1MύϋύdjC -αS*X„$ϋ=I ˆN.λ<h`_ΚέΎΊ wΑŸV \ψ»IεψτpˆO²ΌYΪG0)GPrΚ0kΪœΌ*Ι_O$Œό”!šKvη‘  Ψ₯8ŒHˆ«δU™Τε©™8Oπ @”.Λ ΗoΪζέΒE2Τ(‚”˜8όWSwν€ν?έr9δ™={ Δ…’,]Ρy¬iλp ΄°G@πΖi†χ̜o d ΐY¨?qήƒ’„†b4nŸΰNN§—γ r’ͺωš @hF1:ƒt'Le€μRIGuf›Ώ;ž}#ήΓqΩίφ½·B»©.ϊπ8½a³οσ‰κΎ-`±\‹%φΨΊ¦£J€χφΣ €»υΣωΔΔγ u¦Μ»ώ­Ϋ%‹}A‹8€•\‰`™5x™Φ>;ŒΡgX<ŽH`Ÿό Η3ΰJšQ§ί‘…£‚=žeΑp0ΫώΡ<žJ©γπQ²‚v£-lj! ˆA½~Ρ„θΪ@θϋT@ZHӐγΕέό;³ΟΌuŸhe(9˜)v<ΖΌφ¨@:γ•ή©+ ΐJω\·Ozφtd§—)ϋ·ΫiΨpC‘a?x._ {ΫχCuσƒ8όŸ­ώO£κ‘xw`©RK•ΌFΞGΠ"ΐDψ§…Ύχϊέ†^0nΫGφsξ0)σ2m‰α‡:b%@ΓΙΩBΐyWΜ8ω[Ώ0Nt>Oύ…αά~¦OΏΛΌ‰›ή ζΟΩœύίͺ³ϊŸ+³Ήή~x=ΟnP.fAšΐκ"'ό±0Y ˜Œψ(@ΪvZr›4xΟΜωΔ@¦œ‘z;(ͺIjΞ”Ψ6O 2gψ'–Α1>λπ *ήΌ§θΝa| <ςΠ³χχ΄ma“0Fx±S§°AΓ―ΗqbKρ„ ςΘ~NIU»YՁ@Fδ, tΟοΎ ΠΏ]ψ;-nΘΜό0)ΗΐύL‰W<φΰiέ+°¨*9ρ³FwŒj?U–ž‚vžfY ΒίLͺŠQχ£W@Ά‡‘zϊŒbμν> Ս;Ά¦ωΰy—kž8}ς^Τ΄>Ϋ Θv@Ύe§…ΎΉ'~ΓhκqΐΩ£RΖώc†JιN°0E†JΗi„ΚDaΒ ±nΦα ’±“bβΡa6Ώ(έ '”ψl@4ΌΕٌς™I2B(u|b6&Kšˆτ$¦4}Βΐ{‚Εα_ι: .―ͺ„zuΣ7ΪΟώϋη7XY»œNŽΠG2 €»­ θCCψ9?œ ±έtc›6ίω\Ώe ΐ„ΥηBίχΰ–γΨ4ύJΨ¦θ<ξš„Θ’†kυΨ­€²NΚο &?3°‡βmfΉ'!Υ—Nΰƒζ³z3*r έuˆ; Ν^rtFλŒήV/ΠυOhΦπ¬OμέυwU–³­ §Ζ²Έ‡)u±ΔΘQΊΚcοίhE>ΠΣ!ϊQPθΔΆΏŠΨό!£%^Ζ0žνύvχΜ> d ΐxu‚Ζf> "-—Λaqq±³MζφΊ°i ‘³OΌ―‘εIv”?Τ‹F{b½œ ΐΊšQϊ¦3…£—kЍG’œ¨³ZŸ |}‘°ίϋΉrhnξΨ•ΌΤ?²υ΄ y1hT”"ΤΕ.υF;”JνPoξΫ³§%΅¦n”ŽYΥHΣΞή~ΨΨm†ε­½°$.W*RJ‘ ε!_Ψ ΝίΆ›O»§…―,Ÿ’Θ”ƒ€v«5£έ°Π  TƒvŒnτΓΙvλν°UΝμˆf–ͺΖϋJ₯r(–Š:’hΗP³et²©0 Ž07―^Z”Hκxd/'…L³0B4\†ΐΈ Σ±ή|σΝπΰΑƒpωςεpλΦS‘Ρh…{·Τ+ؐκΠΩOέ'CQz₯*=  {mΕQ­ΨΉ}‚Ξ  έώF¦M'w€β5 ΖΈΞ0!Θ:΄‡28.3θ89o?4Bq―Κ“βτ”S|%ΰ-σΌ…½Ί”T½΅΅Vρης ρζΊlS° +}sν6Υα/ϋ9SJbπ₯RÎ2.μ―‡Ε½ …WX[ύ?¨δSΐšE93°–€ͺΩΨ ’œϋPΣ΅ζ,d΅ΡΜ#›’έD/<ϋΊ¬šjͺ£‚rY*΅€8Jψ‹ηq§bΒSΖξXyΚοκ• ‘Ι‘ΡZ›OΘ^gށL₯&ΒΏ BϊΧΏώθώ(ά½{ΧzW―^ Ο?Ρπ+ΏςΏ†O~βE#Ϊ~  Ÿ[:λάξ~(ΌΥ ν§€ύr η U·‘t”™Ό£±ΟŒσΨΉΐ\fθ”iXή}ΰU X]t΅ΧΒζ¦Ψ€zT§%;Α;UΘ\>Ί\Ύ k‰σ-υμιΥΓςbX\Z+«+amu-¬­].¬…Υ΅΅°²²"₯PY\’βšε₯ΥP»Zxp·¦ς,ͺ 2˜}L‰φ,Ϊ‰a@*’θ†υeM\ΊΈ€€‚Ž΄.…J₯l#CKΛΠΝͺhFtν@7+«ζΆ(š!\‰-Eˆ C\;Ψ(­½¦RŽ[GρΛήxΩχtΘ€x£η_—f ³όσ?σπ;Ώσ;γ₯Kb€€4ΓΫoΏώβ/ώ<όΖoόzψάη>—ΜΑ=>΅/QΣ$θs¨Υ7΄ ΰ²ͺ€LΛ”{_cΩΟμΗ―³Y‚3O¨Λ$Ίψ1]χ™g9v‚‚A=₯v+―^P%lhΗ‘Β>…κ3H](k`Y{Ί·t±TYλ Ε‚”€Ό ”υ£·£_+EώR9πbτKšΚZ’² α₯ε₯P}η Ώ2cušeεYΐ™b€:.¨²‘s  B7Ψ%=ΡME L+φ‹’hgyQŠ‚θΗ¦7Ÿηшθ¦ΫN‡ƒΪO@!ΙΜιa SΰΪ‰“ž?σύίϋήχΒόΑX―κκΥ«f£¬JCΎxρ’…ωζ7=<υΤΣzž²ΉΨή†ΠϋmY'τžΣΌ[Θi± cτώOΙΨHΫ)ε5‹lϊβp O›†o€FTw­¦pΜΕΔ)„xI£Πo›© ή“•ΫΐOyKŽyΥ7'ΐ΅u ,#AzΥvΨGŠZ Μ\P–ezΠ‹Τ‘•τqΐ ι❻°σyю:IqΥrώγΆQη±i@ƍ›Ž“½OL;ύ±ΨοoώζoΒΖΖFxζ™g,Βί†P5LΖΊ€Λ—/iH¬ή}ο½π΄€~‹aϊ·sΩ% ϋk€Δ΅ΐ§4@aΌ»7s•θD†+ζυήωτ ύϋιeζΐ?©Κ40W#Ό,©wo»@ΨˆI~{†]γϊ¦·–B³Ά‘g=ξgΓέI({yΔ0›SPd“¦‘¨DB7Έγο¦—,ψ& ψˆύυπˆ)ͺŒΉvϋ5―oφvΘ€XE»E Έ}ϋΆυφςŒΠσχζΘV47Ά€ωTJSα›ˆ ά·ž4Ί1Π°ΗχVγ>`±Ψ8f’“ΰ„a,ΰ g2O˜ΧΈΑIυΥn7uŸΊΦ°Ψ³‡aŽ›Τ,Β]XαFΒΘΜaάlΔf$€ν\ιΗό-ŒFžD}œίͺk5ΈΞ8ΠώΚ•™GFΏ*cͺqYtθΖθ:π@[\DIc€c ΜŽ. r²Θ€ π‹€GΨ³ΈΚ…?ŠOTVl΄`P’4 #£4Φh{Vάϋ/¦‹Ϋ)šΈoœaΌσcϊβr.ΰsŠ”ΔFMWηξΩ»Uΰ)ΚNΛ*‘™Λ«έ ‰ #œ{·ολ>δp΅χ =,f™ΞΠO$ΧΓBή!r:qε‘ο~χ#ό­_ΐΜνΜ`ΰ|qύ9  ’fυ /Ό`‚~YCώ<|όΌσ°(m„ΤHށ–G{β`Ϋr$Dζ0cγx@όc;«ΧdLOΫ₯Pxβε9Thd©ΗΞcŒŒ'tΔ3:ΜηΪφ‡γ_‰ΟθE}ηžΐ*|f $4Jο_ιφ4ŒfαKi·τ»ϋ§νQώι°ΩϋΙb SFΰ–…/?σ?o‘ϒ?”ού#ψypGΐŒ­ ;―Υ@ΨΡ£α΄S”£έŸG3OfbμSΒ2ΗN€F5*s ΐ·Ζλ] ’Y¦”"SGώ€{¦$ˆΆu@hT³ωσH³€ΩιΈ“V’B3izq"œΏcgζόb Sԝ p†ϋ«Υjψμg?~λ·~ΛBΠ󰐇ή? ΑυλΧ͞J˜jΚΥwAήΈGηΉ3!qΠζήΆζΫ%L8εJ€³θ”ώ\ĝμΐ˜WpδΜ»σΞb?­iTΧ₯ΐT~6pΚΥ7Η캊#τΟσΆδΆσAΎέ-ύ>G೬g€l ΐ$Β(―ΥjαWυWΓ΅kΧΒΛ/Ώl+ώΩ€ΰG`λλX0荦_4ž#ώ¦‚+τŠ˜―6 βnύ9!7Κ·τœP'˜l_Όž`~½IΧwΧη2rγpΨ€n‘䔀‡ΫZΘ$€»3μ~Ά<ΝΏΎu'Ij„η…ΘμSΕ€ͺήxQάΦGΫΧJΎ”IΣKΚΉ£ΈαΖ5“„7Ν,άτΘ€1q‡ΠζΰŸϋΉŸ /ΎψbΨΪΪ²^Σ(¬ϊΗjΓޝΧ.θα.€ρΫΤΤY>ja.G”«S*δήΆζΟηhΨREωσAZΣ:€ƒuΆ΄ n<ήλοΪ:»@ ŸΌδΧ ΝέϋJαŸž!ξ‘1υPνEǎHIdʈΓ| •~Ζέέξ7όηΥΑ”ΉΖ@¦ ΖMΗΗ‰žήρφφΆ­τ§·;k Ά€MΡ{rž‹ΠΧ€œ”€ƒŠFNι(ΰN!“—σ< @N“]hΘΌYί υέ‡ͺΈj *θ­†‰Ώm+cμ‹(ό}"δKφ‹nug€ΰoΥΆBkoS‡"δ1 O qα,`₯αίΤθQjΘHЌφG†Κœu d ΐ5ΡsθΓόήΫGθσ ŒΫ(ΧQΰΨ)%ΰ@ηΘ+‘UbMbT8„ί“Βˆκœ9…|)Τ΄ΎQέ<3θ\^« E%€~TΐK|O+Ία²Ύφ›šΟ—…<­c0‚<)Δeιž ˜’šπž¦N!΅#x‘ιn\ώx‚ dIχ` [ΨƒQŸτφφ ωσψœωΤΔνΒ_½ώ܇͐ΣU­Ά+iœ£ΰ9 „Δy7SΧǘ TŠœ†άγ:ΆŽ―Ž™ΝΔΑΠΧ–Ή’ΕG’M½¦›ΛoνΞwϊbβBffЁ=]™Η™0a½ΣsGΈ€Ÿ “8i’!ƒλΊ ˆ³ΔΈ;£GCuWπnhfgάΣλθ$ΐD?snίΏ}YL”&°pkK½Ή +eSθΩ‰\­wηχ 0δΛπΏΩΝFhΧˆάL₯™(Ο,πωΗ΅^Ohe\ΣΑ7BξLb SζT-.<,{€ ηs  ―EΦƒ'_¦/xηο‡ΰ8ØΚ¦ΞΆ·lS'”ŠΨώκ =՝P]ΟzŒ»OΐCS©ΝζςiJΈ_\)†+kεΠΠe- κrΨυ ˜γη}_#YΜ·λ›α@ghΘ@€Μ³³ΑC–ΚdΨΪm$ΚμΰΊWΰ wmp²Rf‘ϋa Sϊaε4έώΤBUΜW q¦Uh`\[Μ"Ε½½½€A-JΒΞΞNΨέέ5αΟ<ύ(½ΖGΕτ+ί΄e£Κj΅jΨΩ­…­‡wt‚ή}[ 0t‘Σ›ΏωĊ½>²Σ7½Ε{Έ)P2ΏώPώΊΔˆύ ›™ΗΠCDλ[Uέ©νΛ=Eσ^ήϋM”~nΈgζμc SΞHε6uύΣ`eΌ/Δ4BΦ#°@E _!θώ–E‡΅ ύ Ό Εϊ9Wn”ψн|αZ%/Š‘ΆyGΜ³ή8+ΉωΔbΤ%Σ½~I|φΧβEΑώμ%Γ —™Ηͺφ `RφΔv‘N{αέBωΊ§q±uό67nNYΈI1)“bl†α­aΠΰθ‰έΠ-nΪ˜«ιƒtΎ½QŽ™'ρ°%AίkΘ?lv3– Ž8ΠΘό‘8ιQ€>B‚΄Ooότ·‡K»ρήΟέέΊCΧ£”ΗιMίΏρΗΈνο/νn“wα,V( g«+K‘ΆώΆ¨¨Ρπ%ɝ˜|œΠhΆΓ+KαΚ…²”AM. γΌ:Υz+μξΡ.»*,mΙG iG΄': ΄Lš7τƒ#νοqϊ…Λά揁LQ°tFΞ›6₯Ζ—c @M+8L.H F  ²„WMsϊΟυR$ΤΜ¨ρ"χυ”+•P” GhU΅³€°wΜ\ρš9’Ρc€†pψ!D8 ¦ΐ7k\8zCχ㑦ψ±&†‚©T”7ρ‰λ‚w„η‰eΚεiwE'/ζαV½FaYϋΐǚΒT€LΈ@ώ†`G1Z#Λ«¬{‚Ÿ΅­DΈ[9•ppΊ#y7q(+0“Ά)Ήεp ξΏϋŠ]œ/Š9κ4=Ο―΄Σό¦ yώ?΅Ύώέ;Β΅Ά(ꐣ•ƒ­‹%ΥοςE­ρ±Ppš;ΝreyΝθ©Πν¨&`kGk€|"*½>‚H»ƒξipιY?“ϊihΡώieφˆδ“)s―Θ„ωͺ₯δHˆ\Π^ς%}¨ρΩDσTMc£‘ς  𠉀0₯acθiΣ`Y Žπ5Α₯oάQω”ιρ $λrg™0(0Η 3*ΐ;‚wΒΰŽ%O3н«ε#wΒσŸχώ Ky₯yAξ(0π$m+ŸόH#mθω’g]Bάʘ„Έ)bh¬ΰί–πΗ…†4A3εB)€ιαζpβFz‹L—^”βο­ί|~z^šω½Sœ°§‘ηn¬I X ―½»n\Σ5Υ(7KeνPύ,l‡₯ΒB¨kψ7/Δ)Zf ¨ν«Βσͺψ½=μΦΥ^­΅εŽβNϋεA¦}Ί2lόBx’m€PΧΫ&OωN‡ν>]©ιΚbM‰§\u’.I˜p πS$ΓƒV€2α+AGCǝFR€@uαfΓω%z9$‚εƒ@ρ‘r%BΪ™„ u˜Β”ž?Β p?˜ yπMΊ0 ˜ ·)ŸoΒ£P¬*|…!ΌŒP`P(Σ+±8„§DΪΚ%ΐαx―+ž)μ(2( ΛΚΈκ€o£JΗσF7ψ_ΌpQα4zR^ υΝwB³ͺt )9‹Ϋη€ώηκiθhΔC31ΦγkζΒ•ΥBxαΊΞ ΩΞΣn1½Έ™ύcΥΪζ܈M ½¦vθ2@ΩώΩ{³ K“«ΞΣoμ[Fξ™U•΅I΅tiAR@HƒΨd6f Ίλ6šΝllxa^Ζϊ0Μΐΐϊ‡αaΜfČ#$h(iΠH% ’J΅H΅¦²2³2«2+χŒΘΨ#ξεΞwό;7όήΈk,ΫηίυοσݏϋYόψ††αœΗo·wr ΐ:ΪΓ™Χ:’֏"D)³¨Fޜςή‘ρhΞ¨ad0V&ΞH„φ9πJςd¬2ΐxyKΈ*Ν#e…³‘΄"›Ώ†1d}C pC€€ι’/n”ΗΛ” ² ξNωpw­Βι«,¦ΡM^)cΤA/Δ±) „η›z‘ώ‡°!LΨτ#a AXA( άΤ͝ΎυbΙ[9Užžnk–εei–ίyFUV=γbΐcΓΟύχ…ηޘΠVpςHWψΰÚ*’ά’jΗ>·σͺ—h‹!`δEύδζύAt ΰ›πΧaπAA ΕcΗY··ΈΘ “ί™XΨ°Έ;Κ#ΦΡΞ@Ξ;NLτΜz9nμ—#Σζ†₯¦¨²ΐψzΕδŒ‘ ‘a`,ͺƒ+̚€εF½E£‚ω‰ηšO“z’BG@@5^‹ό0QΰΒƒιΊ0ΰ΅©ηŽα˜ ή)Lœw•§“Ϊδƒ@bAαYλγ_P]`όψ‘Gž}Ζ™?Σ%0ΰ„am«όυbebΛ#ύΎ0}ύ|˜Ώ¬i ί™\”’#°ΚϋΑ“CαΤρAiAΚaH'M"ΫδΜ?ν9ϋηέρΗlΫσ«•Χ78Ππš‘ ζΰPϊ¬&ΌΡs³γ! -šˆnLgwΓ;Μc#Ε¬£3g ³X―)pϋŸ³·Υμ:NŽT|fΜƒ‘Μ†ΜBπ΄>ζ™όσ%HO<˜=#κ a ήύI’W4δ…iF(άΟγ#\ΐΌ,0#Fι€eDIώΝ@Cz”Ÿπ”ί…‡Eκ"MH·Γΐψ§u3£ˆα™Η¦~΅π‰yͺΦJŸCunΏυ]55k'ΈuO–₯Ίσ~b;©Ώr$°ώϊ΅Σ€΄Ίδcη8/Ρ–C€ΎjύB}yI[BοL-ΔQΏΎ»tx†ΦΠpBψN"€λΰΣu˜wkρΕδ?»ΉΠF31@sΗ0{FΒΜ9γΗΌ8f]ΘV.jXVbΨΟ•²€΄~S2Γ<)#g εΆι•·žq„ρΡΐψa’ΔΗ―Ώ/ŽžIƒ9wζΟQ‹§,ΠFι‚ ιπή‰!<Μ8ϋJ|ς#yΑΧ΄UΉ­MB5Λ"=Εq·n₯CΪ€ƒ@6”•<Θίγ€)γWΦ‘9έέ£aβΪ™0qύ¬IjΡ”άπΫΙ™M}*ΎG{'—9/ΫΦB .,„ιΩΕΐ1ΐ=Z ˆ]Ω4_Κ|Aεο _ΑCpύπαΓU$NΠΡξ’i7'ΚθEσzΊ}—Š»γ²Ι€6š„Ξ γ€Ή,ͺ#=υΤSατιΣαΖυλᑇO<ρDψΰ>`Θ‚*Ή Z₯O†‡ ¨ζ₯­b6φWzlσC€‘1υg΄ksΰ΅1AΉQ W•‹ ΆJΌήή[8‡?ο‹:ŸΉω.ωψΐ‘8Œ$άΰρ<βW*6Dβρ@||‚ι"lα‡!£VΨ5¦KΔ ΝLήΕ€iν¨Ί’εƒω£ξ'-¦ |€piΖό€ύXZΧΟK9šKMΞ;χSU˜τ½β˜ΏμΐδWtδxO_w˜EΫ¦SΚεˆ₯.΄»`ΜΊeπΕ¦ώ2ϊζ‚9ΆΏο ξw†ήiδ@ ˆΑX σΏqλVψΣ?ύΣπ₯/}ɘ ˆ1ςβ‹αΰ‘Cα“?ϊ£αӟώt8yβ„1¬ΙzCœyΈ€‘Π|c܎_νOεf$ΤΎ΄ΐώύΥνzžΑ’δ/δWΎŽ$"Κ‘Iω&š ’Ή΅K @oΡ MΞh‹Ά‹φiα1nμ e8ζSh&| °‘-σκϟ pΟuΨ€Ρ±|Ϋ œ‡« \¨ –jG:²:ζύΡ…/|α αΡG΅Q&Μ‘ƒgΎύοΫ¨υίώόΏ•=P@³/Έ’ψHaE?ΣΚ*[fΪΗ…Ί9 τg#ίΈ€½ύlsΓ©pΎίŸw$y άηYΘb:gΈΔF-Θh:59eD²Βœ‰§bΧ‚` DψHτΙΛ…„ΤMπ„ΩOOOi‘L>j_πΓp³Lšψ5ΧκΆ0 ι`# $qNS‡ 0¨ξhFF”Η²Κ:3­ii:8A@bŠ~ νŒ(}ές7Ώ °ΪΦ¨ΆσΣ·Βυsί΄B rζ_ σόkχAΰΚνx˜α ΄ΰ%x‚A ω†Ρ’‘;rδˆiΐiάyΝF .h:@λ5δΥΘΤϊ5Ω(…ά½ΉP ‘μΫ;L ¦τδ“O†―}νkα±Η3FCβA΅ “ΔBHTκ½3ρόy[―τY\tkZλ%²ΌΡ¨P.ΜmΉϋ΄ιrO}QΪ…EUωzΕt{4ν€ F{Œ+N€&eιΥ#7K΅/,HSΠ₯9₯;I‚―„»ΚWZ€•Œ™3­fƒ$΄i~lz" Li!!πΣ±=·Ώ-­9±ΏJΐ4,Vό'‡ΐƒ@$.o]EέΡ£ν‘ΛΒεB―ξ@€ΦvDpΉ 3=8*Ίg0”–»ΒΨΤ|˜_ΧaΞΒ"ˆƒ£Π?ΈΎ^ωΉηψamΧν5\_o:yΌφ! mΐ aΰE©ϊ‘‚ι’Ϊί·ΑfΌ‘ρ‚‰νΦ5±w¦f₯ZΣͺr1±„ηΦΟMΏWΒx―vδΐŽ—…ŒJ7b@q)τμΉPRΚk“P‘„F„ŒΏ™²>.N#5Χ€H€ύ―ˆ92XP–ό•Pλt±hPσ&BGŽzϊDtA8—ΈVΎbτ+eD— λυ]@`Iι§(c΄Z^βΔ’σ–™˜±>tDpI€M(nδΑߊNΔ+IhΐXέ :Ο@mDψΊ§Ξ„Βτ[FPi₯‰Y”ό'‡ΐ€Σq0ό ©―sj§°3Σ6r‰”0Ξ΄\½kGM ΎbMΏp»¬9YS€“&΅hΉ―/»Dtφo’1`‡Σ°ώΨaν2θ'‹¦ƒ•Zΰ-¨uΜΏ;†@.΄‘ηΨؘ1yΆΑΈšΖΟƒgd#0 ~θΎ#α{ΉΪ@z²kטFΝβ-ΛGυa‡E„jQΌΆ½Ϋ(IΫi5 ؠΝζŸ"x'q; [Ώl\H€UΪη?}ϋ­pγΚ+šnθ7·ΆΪ΄~ΒΉkm…}—­ƒb°ΧnΟI{WG¨ΏΗ£―}p3€ι³‘‘aέ»Α靣ϊ62’5O’wqg@ͺ€©₯M:hΫ2η_KQγθl3Ά2Λ5‚@.4‚LζΞθυΦ -ξσ9ζΗAΎaώnG·Ρ02Δ…7uΰBkZ•ι€lV倬°EazΗYξ†ή =ΌΚΰώž€ΒQfΣ4'υOΏ½{:νΨiΥαcύ«C§_‘πΠζ…Β`X\˜ —ΞΝ¦ 8σ?§I)¬ςχέΓ ‘ύψφ€.ώΘΏ_S_κνf3 foP뇆 s M; #₯yΠ„BΉBΈW7KΖσΔόΦ x(r-ήμ{υ'₯h#PG47΅)4ϋ6ƒ@.4ƒNζ‡πmσ{ν΅Χl€Ο7LίΧ 9rؐ`I'°­E†™  Euό ²sRM‚π€0Π‘Ρ usΆδšΨL? 3ͺόf¦Έ΄:.eΆsύ!XΛαό ζgΖ΅κ_'ώ±qΤi]€Θ#ε¨@v_Wniz‹ξ.w"½b$1ΗΏcΤFŽ€Μϊ–,/gλ8¬ y@KœΘτ;cΧiό˜ο&J"›œπξL.Z΄+^Yνώ“?ω“α₯—^²­o'Ož4)Ψ?λX(ΘB@VΚ‚ Ύ°­EςΡ[Έe—qθ€Ά‚nr3ΜdΎέπΠ~ΪJ¦Y Π0KΉY°ϋ‘‰γΌ₯Œ ΔΜ½δβaκUΟύ—¦Η·›zρά;MCŸUΌ»ΖO[Υ/ζ·Cw…‹/ώM˜»€Ξ ˆ[ώX]Q.ΉΙ!°[ ΐΪlIƒ“›Ω‚`Π7άπΔ•ώά OβtΫWs“ jΧ]'ξkz jαcΰ&w6ΨLnκ@ΐ;.Θΐ–˜όoόΖo„ϋοΏί5#~nŠƒωίwί}ΆεNάφ£€0ς΄hΰlο?ί ­θ$oΟf₯Y7/³„ FΝ•0wΥΙί©ο΅ξώ€aέ­QΌ44¬ήYXΙ§ΚO’TŒψ£κΏ;\όήίλΔΏ³‘;gώ‚Tnφ`Ζ,Hξλνγ“ Ίh^j.ϋ‚yG¦οΆoοƒΙϋ»ovΊh0Bω,ά­g*8ηψ§@zmψΤK#wΫ:δ€°eN $ΰΜ|0όζoώfxωε—ν›-€‹yμΨ1{μ491½*$i‘~Ε»O²˜¦LυΟ–wπIHk\ μέ$ςm^jm Β ³ uΗTΥ_#ϋ²ό1Β—B3\|αoΕόί°+Wϋρ˜1~ώ›C`·A@γtυsi&₯aΌ66§Á!]Νz%h– ΌϋHίέ°=LJίx·οM€Q`»a,DΉ εlTώθž m΄Š©τ%p:;>ρ‰O˜VΐΎ½ρ^9U―4+AΰF0ϋA!k8ΠΡαG―ίδŽKvw•%ο !@U7"°Δ&ίέ; ΣαΒ‹g«ώύ€ΏΨΔΘM½8pρΪd₯2πCgβΨ0ϊτ ŸU @ΤxH“1ώJJωΛn„@.΄Ρjtt°§§§£„,dαΚ]ά\Bn#ΉΊAΚlύ;’yζ^ΈR&λfVέtάΟB€΅§„;βYjώΩρwΒ[ίϋbX˜Ήσ»Α~•Gί™`pšΣΧnΝiͺ’SB`βx Λ―ή㚳³0Τ0nϋΫe£ Ξ`Κ¬-$–ΓξψΙ€6Ϊ οBΑΩ/‹›Ήƒrγ}έ)œ›αʈΦ·γΧ¦k<Ω»jo·& S­θt!Žτ-tυ…›_WN?%Ν ϋώ΅Χ_Ά-Ό«€Ι3Λ!°u€v±Z@½sk&ά@Φ@²˜ΰfOΐ`;ΣO5ζ/?J+5 eΈ΅u΅XΚ•υ *§o3ά½^Qv\Μ\XG“p”,ήx΄:ΥXjξ0i₯;,qB»L0Ιb5ˆaμ&"Ϊ]ΧP•m Zϋ‹aqίΒΜXΈvζιpηΧCWOŸν‡Άck%/‹’δΨ΅ GΦœΧ•›³ΊbI{ϋ«ηΑZuΏ ©M8FΞπIΫ‚­P§τu s§ς2ζNΩsS@.T@ΡΑKΦ‰θV›Φ¬F‘’α+/”­Γ Ϋ&PN(ΆΪ@œΚΪήgWk„Οj›o>nθbŸ‚ξGΠΝ~0~Β8QΫκ2ειηΨˆž\Ό:i4 Jw΅κίGύvΖvΩOE0.±½Ω>ΆαLF·£Nk˜}m!2ζ_λœGδΐvχ˜Ότu PΉ_pεF’…‰ς<ΧW™m(κVj2’Υύ:­Lg™ΟήΉžy:Lέ<―_6ߏΚxn.LΧΧy¬› z5Ϋz{»Βι’M ώ«#3χΉι»€νŒ?&ˆ8³υXS;jΙπkΑ— ΅©ϊΞ€*ptώAέ0λπDΨ°€‡Ϋs! σΖ°‚ώγΙ}Qέ_šŸ¨ŸΒΨ₯οκΦ³…lԏVΐ™:³Κ£εΨιpΛΌχ€τaώŽnΈΦφ?ψ"W];σwΫ…€Τv?`ώΎΠ4[ƒŽ~Z–œω§Π¨ϋž uΑ² ŽˆδH<Ϋdv½&€‘Όˆ‹~Ί{u‚ίR)άΌπ‚˜³‘¨ώlχcώίΏbΆ άyΆ9Ά˜(}ύμ₯;Z―Δ»άδΞβ?άyR†Ο»όM p=rK Z"€Ab›hR†O7dr %ψr %ˆZ0dj¬qphA©ΐέ΄Β+:w›Θηΐ“nfoΈ.ΝoζΗtFΔ¦3Γn f4ek.Υ>p™Όq>ά8Œνλοκ’*³Ψόωw–G:‡ΐξ„ΫzuύοτL1\Ί>zΕΘ9nΤGπ>Ί―eϊΖψΥ?~]<‰ΐΰ‚Pو2όM…pΞόΫg.΄¦- £Χ-’„=›Hνpβ6„€eνXΰ(cGθV5![L+ω#†Ϊ‚_Ά…Ά7-‡RQj}έLΦ?8ζ&nˆρK§ω6M€-ς³E€QέΏb΅΅Ν“Μ!°e ―ϋυΏNΩ €CΊνo‘ cθ.`;ΐξсgvώΏΒ1ϊ·pJΟ… ½Ρ.Γw:΄nΰδ@[ Λ€ΆΐΤ:P;όΊn*DΤ ·λΞR(O‰ωΠG›#ϋΊιΥ8rBαμμ¬]^Δύά  z=†ΈξΊΤδ½ξΟ6΄”ζ_\˜3sEνk.…qΝρίΌπ\X*Έ€©μΔΖF)λG1‡ΐ6A #+¦ώgόε α‚Τz/ ΘFσΨ©ϊߘ?€˜~w—˜Ώ YŸ:h·jν2}O²oΘ4`ώ~oiwZ¦ •gGΞ€νnΔhρύ•cbΖ3bΜΊ¨l€Π Σ4-b-ά$χ qI¦‰@ε:cΌžAAφλ‘ςλ₯·.7`aπ … YS=E˜tpΈόΜΝsaαΦλšηΏa‡ωΨ¨_ ό0υσΘrμa€·0Ό]θ3»°hΫΈάrΡΕιΒ)§ Π€”ρχfnέ<Œι+Mβ9Mΐ­žΩVζJυPχά΄†@.΄†QΓtτ”ΑΠε9Fjδ!ɜΡ™C€ΌσΆΫ‡ _a’1/ϋyaτ ;χ’Ž/ζ»’Ί;ΩΫ\‘Ε\ϋcΕσ²&„amΘU―R#8yΉ=†•ΕιΡ2θrΩ’Τ•ΪΏ?3~%ά8σΟaζφ›ζΧΣΗ<ΎΊίa—ΫϋΠ%ΤCύ=α -ώ»‘λ€ώG¦ξΥqγΞό±«Tά »‹[Ξβ€ηΩtώ9ΝΨ(ĝ>tšŽπ§rY;ΌΓηΐ:ŸŽοL4νόtΰFΜ­nVD@λ?₯SκPs'€ΏλFˆLœy}ςEZ7I<|ήδ₯œ|cž | €*S ]l€wκΗ( _GCάPδeε_T‚—ƒΌ6xμ€0œΨK*i“&εN ;~V§, Ξκ_\€<Λ¦Κ‡υŽˆ-‡ΫηΎn]|ΞΆυuiuΏ ’―ξOΊή;Ζ₯=PηΝ¨BFR —ΐϋΣΗ% H¨χQ'nsΖήςΨh^ΪόΏpΠύ° οͺΔ€to³Κέn:~€oUxh`n:‚@5ξ(κώ Lη灩 A ΜΊ|*©σ" (-ΟmΪnKuνω,ˆyΓ¬GFGA[(Ή3}“Ÿ››³yΚκο 9~Δsw'ΤeffΖ9φ½>¬@‹ΐΒ!ά`όL#¬˜€e[ο”ώ‘‘0 π΅B¨‰°055ΈFΩ¦2Έ‘Ε΄ς£ΚkEizyl_Gυ =aβζΫaξΖKa^‡ϊψΆ>Ξρ'"εΘΝή€M‰Ξ‡ώf;d³φ₯…sυnσ6F,τλΣή ­ώσ ;ϋ?ώύZ=Τ§Βόaόώ Θ#θ©05ˆγmβοΝK²yΎu~mς*Wn:ƒ@.΄/ομΨtDFΊŒž΅ΒΨπσptC°#Σ‡@1Π΄θΗ–ςƒΓ„ϋTΟ›#oaς” 掠Γη#ΚΛ³ 8„6wΚ‰6¦NΈ‘‘‘J\άx¨o·άaτ|#TΒΜΎ¨N'Ϊh|C§DJζϋƍαζΝ›αψργαΨ±cζ³νΘ€?Φσυ2/μ„Ίρέ―@<5*9˜ύ ˜©«Τ— δζ|Z&κ@<όHƒ‘ΈΧ‡p0yFζ–Άό©'u&=WΟ#t @†‘:κBκ…α+Ϊ…₯AuΑ"‚!α ŒΜ%ώ@|(š„ς€Œ1 ΚΑ’XœΠ₯ˆ½A‹όΎ¦#|_Αyώbώ\ζCf^ξ$ωόu—CήΒΉυƒZΈv}|6<ϋΚ•pιΖ΄F³œTW‡FΒέΏ:nLj‘΄lΪ€Œ–οςΪoNρ!ΈΧ§³oMΜΫκώήΉ•Γ8Ÿ ¦"ŒΫ¨_οΠή{4νVYό‡  Δ+xGF<λ40b tƒgC¦A¨eξφ½2o¨Œ;4r.΄h††Κϊ‹_όbψ½ίϋ=ϋ>xπ`8tθΝSŸ={6όΕ_όEψΉŸϋΉπC?τC‘ω)-Ι•H»`χΐαT°&˜AΉ`Β0’FΣΌƒT%}ƒ΄>-PAΨ&υ$ „€Q>ΜS†Ρ#`πŽΑ·E=sRΧ£’U%+)σMκkmέΙ‡r“Lɏz0±¬Ρ g”³’\θ ₯™[:ΝοΕ°<{ΛVό«rϊW9@ΰΪ„+%Θ_v+hVϊ@_Oψξ7Γ“_#LLq~ΣL,ς :Θ¦ΞΏ3^Ώ0>υΡΒ'Gt΅ν² I7ά­ ΨpΉΑ9ΦM€‡C œΥήιΩRΠ”Κκ–`p|7ζ£η^"˜ sC`¨œ rZβv§v¦ŸΖ[₯©λϊήkώϊRΩ_±r A{{g‚ωηΝ ς'΅lσ@IDATb ξώϋο7€Ρ‚·Q-ΒC`dϋβ‹/†|0ά{ο½mD VDηΕΰω³Ή £#mΤξ / Œ™ω˜jŸΚ‚{ʜTӜaΪΜιΓό=]' όkM—Η/­# `,-Τ3Œ,VŠ%-F”pζ’XZTP]X‚F@ψL]όf˜½τ¬,Ρ.mχσΓ|ŒωΧK4wΫΥXeώέανk“αoΎ~VmΎ’;λϋMXδD:_ΉN»r{>όŸ_x=ότ<~ψύχ†YM0e°ί§ΐ8θΣ$ Ε₯πκyέ‘c€M0Θφώ?ΗoζώΪθ_xŠν8n;²ΈδS»“nΘ  …TΆζ_I»EI‰ςΧ:Θ€:@I`¬Μ‹Γ?όC =τulΠ! `D{δΘ³/_Ύli€htΤ–ΘB`:2ͺνΡ­;|&LyaΆΜ©£ €QCa° }7C4Κη#ΒS'¦(;Α€‚VΉ‘.DbHa†Ο‡Π Œ>Lm˜Ε·D’Β! tΝtiήވLq…Zx(Ο·_ϊϋ0qυu;δGsΊΥ/Ώ±/ߞ|KRΏsϊΟΎvΥ4}έZORRCR.—Ρ¨Ε>94Ψ§ώ^Ο ֌|ΰ‘ΓaNšΦTބTσJ³ιή+Ίύo@4+½ZL‹?ψjΜ_6ƒ„Κ¨_8ΝwTύGν@EύŸ Šύ’iώ„nF—,±δ§έt“(ωkΘ€@b$‹πφΫo› Γεaԏ€p€ΖΙ7•π Y[6΄P€ρΟI͍ΆV;2ΏFE™) LšτD9#ϐ²€1δ4Iή ηκ~Κo«ϊ•.αΒρ>6{ϊ±] ΐ˚“E! Σ@X*Υ?Δa€] LOM†r—&ϋ—ηΒΕηΏζ'―KεΔjΉ«SΙΏφQΑ³’VkΕΊ^e8ͺZ±ϊ.Μu4xΕ|6ύhx¨?|υΕaDš‚‡O…’Ξ‹`τ›uϋ½’κΞ„πςΉ[ΒQ­§œΨμΈj@Βόϋ΄ΠœvAΐήυ ώVΤ‚©Ο“IλŒή­‹‘)ž)8³Ο†VΛ4ΧΡΠ΅‹fΎO„¨­eB ΰεγt±t«qέHF¬uƒφ±#Γ€ςuIΦ?6£aιg κr—›εph(Yw›Κόη΅Οž{ξ §OŸ6U;κvΨ8¬)€•Βl8|π&)Φ2Ε΄0+vzGjτΓΩ΄qPU)n5Η˜yΎ¬ΉϋΪΰ€‹w=χͺ<³ΟΊUψθ/2$‚΄(!εΪχώ1¬ˆΠ£Ζ%Ο™=ΰξ7²m]#:u|$<ώΰ±pmLΗEφ‹αDΝ’i—€yλΧϊ֘ ±bZŠέ7#Βυh»Ϋ²ά)N‡{†ηlDΫ]0ΡuOCΌγbε•π½7nιΔDi(΅@R2’-£ΝΠtΣsLŽ k “OcŠn VsHtmΘ΄‚ύύqτΰ…v/ήΠ\pZ@{Lj«ŒάXΘΐ) „λI§6Nczτ™υ–―6έ½πkZ΅’:³K½Μsς“Ÿ ?π?`—ΪπΝθŸi…yΚΓ£š›lͺ¦πE :@7όιόξp@ΝΒε@ nΪΖ%'­*”ϊ+XWΙ€ͺTY@/@―zaqχπΌ―”ζ 4_Ϋ.Ύρ‘4;Cr“VΑFqυγ­¦ΏνUΠς6ŠU`ϋΑǎ‡wή1f ΡΐΦ‹ ΐψ‡Δΐμ` EbέΐαC€‰;dZ‚‚ϊQ±<W.‰!ξ}ζO€6±υΣ/\™ o]›²ƒ AύhN€5A‹ΙŽΩ4α`Pΐ Βι’/1ύΡQΆ4λa„Β‘ώ·uύw)ς±?£iOŒxK~k!iD"DΙ«Ώ3šΙ6β†τ³ ΊJ’Ξπ«΄V@•dMω«‹±ίΎr U‹«ΓΠ‘\`₯;σ¨1¨’lξ\a™ϋoΧ €Ϋ"ΐQώΡiO³™xΚn»Ι­3œς«ΑΕu&Τ0£‡E­μολ·ήώnΈ}ω΅Π; m‰-ψλHΚi˜Gξ±{!@χƒy°•τγ ί~Mλh4wέ§9h7š#ΤΩέ:žvunΊG8-:•``#UαŸφκ„…ε©0TΎ­wέy`½Υ|€Ύ υ?[!ϋ΄F&jL[01›QΌΰΗφ>¦L8cΈ™›` žΒδΣβ9nd­&ΔΛ-2tΩφβ_υΠάΧΣ n ιtvMj1³΅ΞΚW=³Ε0 Β―I`Ÿ;δ@‡€‘ξ°έMc±ι΄¨Ι@:ΆΔU0€΄- Μu4‡_–}Χ YwY=„ε•½ύrκφ>›E©go]ψŽNϋΣ=½EdoE"ΪΟ%Ή{!½w˜—>~x0€XG-κͺa‡΄$‚YOΈsευ0?uS„œy>΄)yθ ς {Œ4eΤΰΡ#₯ΖΖ€Δ)ΐ» ξΓsυΆζ¬9[‚ν₯}#zF”*4HΨΈ· 52¦©a:pϊžξO˜Σ³ V‚τ‰c»ιWϋαζ-ψΩB? V6žh g–¬…ŠgˆTΓ²ζhsϊΆh³Bgπ­6k]2βH ρΗ¬ŽZχΛΣσςΟΚ_7τώuΜ€Ϋή€`οΘtL½―Ϋΐμ‰ ¦-“ΡΉα`TPφέ6©Kƒ² }UΜ΄]pϊζSC΄ήΘ‘AΉσ>έν¬Jθδπ .ϋ)κ¦ž. ΈπmϋΪ]`‘ ‘‘0tpI₯Ύ· ΅‚©φjρ#§'Ύrώ–κm}‚BκώT`2@L†Π„έkšΩ™p,ντ?˜ άjΏ[ΑΤ……υΠGgΪf‹ΖΆcŒŽ*`Χ>~ξίNZϋ)L.l΄΅7Β4ι•ΒdζΨΈ Π>Έ h;iΦFκ³–R ρgΗ4ϊΏ!’€=Ύ~«ίšπΉCζŸY½ή>πθΡ¦„4‰σΪΜi3Œ9πž Ϊφf‰ν1 ;}SΈ…ϊ[―\ 3Eθγz „(TI0ώtτoΜ_‚‹ϋ%Ψ"AΑ°ΐH n· ?gΎ0ήNΗŘ6˜/eψ•4ς—¦Θ€¦ΰΉ žτw°NSΆ·Γ5[RB0EΔυfbΤD#7­Ξ^.-hν„ΞyΧb£\_/@χ~<:[ω?rίH8qx@ορœ _!nL"λŸ&ΐ¨ǘB@ >’ϋ5†Υ՘jΪ;Ӑ ೨’Γƒ½α•7o‡g^Ή’ΛΉzm7€1rM»U¦J²Ρ½ψQϋgί‘ωg§ύ)œk Lƒ0F£”ωZ›¨l ϋnΪYλΕ­ŠΠ€ω{<˜}' Ÿry\·«ςΫ§Ή° ΏΜ’ƒ€4κ1Z΅eڌ46X―Θ…zzaΕ?7ϋ‘’έ`²›Q³< 7Ψ τ„υΐ¨ν €΅°γ†}άΆσ†w=FΜ±₯E£ŸΕνΊpj@[sΛ_€k›3ν`ΈP4Ζ0ΦΫΫΖ&ΒεM[ i~™ΪŸ“ιθ Œί„TΨ<˜πχ8΅ΜΏΞ<±kΝZ—κΝβV‡\ύς83|•ΟγZYλ”w5—ύϋ– ›Υφλν`Bh#NάˆΖR„oG™υΦ+«–ΥEiΨ1’ŒώyίQΜ ³σ wΣpZέ#§tεφ€Žͺ•†Ο-”,ΔεxjήΉ€ Ϋ֚d±Ck΄n wδĞaό«m„V-θ:δσaRW&s§&r°βXάgκŒΩ# ϊ7a@6;e1 ‹ΰeρeƒ£>ς―b€«©z«G΅xΖ„«bΤω€Φθ)Ӟ²;α/yꀞ;Ձ@.ΤΚΊΤ;6DۘϋΗHΔ_G*1ξVύ§^”Eρ˜Wd`οΰA=£φ.*³U%ΝΣέ »ΡEPsν žΠή~U fpοΫpΝΦ;Β€i`ΐ₯ΘΘ4έ?jΠ½v»‰0‘κ_猠ϊΖ ο„3oΫ;w&°P1οΚθ_ŒQΎ©ύY σOΆω„ΏϊטΎ€΅Ε΄ —·c&¬ŠY΅ςΡζΤ€™$_yMσi·œDΆέYž•ΔφρKN‰·»ρ‘N,tRS0ϊΧ…;rΚ ΔΣ‘(‘ώο“0tθ”0ήφΧ v˜e|@€ήCzόzΣωυΩhΏ$›ƒ·μ<½sgΔLL`+-BŸn ΤTλkJg·Ў…}% D#ƒ}αεs·Β7^Ό$ζ―3ID3ωWVύΧωgLίl¦l€3ΑΗGόΐ©]hΡF)3nΖixεÐ‰Ψ„Ύ€q¬=ΫΘ¨6ŽΕΫΕύ *w$:Y‹M:qӘ0ώ$!DΣΫδ™”±Xp!]™c[ψ rŸΥ³]ΣNy˜½ϊ-vΣΑ@'ιϊνAσ[\΄50|4ΖΕ» |λρu’€ήΠF€υ7$μέΩγK‚Γ ΦD\Ό6ώφλημκδθ'΅ΏπΛ©MLεκ΅Ώ˜<ΜήF&ΐό†ω΄ιΌ?B€A [O#3uζέ(L­»Εa„―ΈώTΒP™γa°Ϋ1iψNβ΄“φ^ “ [Ρ²mvΨJΦžnjΑR² Cv€ι¨~:ρOsΛΪ0tψ Ž€9fFf»—0οΘvΩc…‚0Βμ ‡G΄•΄„Gό0{cώ™€6€«©—₯"§{rO@·ŸκέΦΟ —Ϊc$;Œ”6nχΛφϋOΜ‡ΟεŒ6 Ε½ώ ›™*±y{1r˜ΏΟωϋ|?—'q}9Η%σnσΧ­EΗ.Έ]ρΧ2ΧftζλqΚ*‚Y=ΰfτΔΓ»]/hκζαάNύκΎ+_DJyr•Ν9:„₯i'Œ'’δΚμΰ0 D­²,ΪΘΙSΉ»6υk«ŽΤ%.\Y*†cοώ‘0|ό‘°Tœ΅σβ6­»[τ<·έVΎίwtΐξΩπΉ˜‰ΡΏ?ΜOB€έψ–MΔ‘?Xdΐͺ8̘Q6υ/J°ωΛοL˜iœ‘ΐ!@ά€Θ›-ψΛΩk„o#ώδaε?ξ¦0!`Uΐ€ γΟFώΞXkι]3šδqœαΧΖ­mί*ρ°m…Gې>Π«¬n΅εΨ―ίΉ`-οR3γ«nλ&ӊAB“ΐ&€ψ[Ϊ"Ηa@Ύ€–Ι0­ΒΥΝχn:Άͺc²βSaπθ»ΒΚβΌτΌ½«­6wΪί0œ<2 Ϊ­E€ZμΗ€ γχ΅’ ξ°Γ΅LΓφ8’νXB[ŒΙ©ψ,πϋ믞 WnΝ„>φ§έ)σ‡yΗ-}q»L~€G#~ξI°Ρ&Ψ"@¦ΟιW…ω D͘k--r¦άr”ŸήΓ»Νΰ ™ρpΨ­L³―3Β§δ¦ΉP ΅_5„a’-BJQŠ@kiα‚TΚ?W#ξΧιλuœZ$z½Q œκεnDM‹Ή8θθcŸ ΗΧqν4ŠΩDΊ^s·M†€ΠQpΏφ½k·›\ωο Ρ€‹6%iβθ3*o§_nr‰7œœ3PŠΡώηΏz&œykάrυo―Φ³Γ~˜Λ‡‘Λ†ρWFώϊGΠΚhό΄D›ΘΈΚΤ~»§Σ gΚεΧ‘žΆΫžw=»ΓOγPv»ΩPyΆ“vw/ΏsώlnšA S”txF\Œ*‰w΄uͺ…bΡRY#ΠΙ³4fC)μ*`4ъίFB@#δl˜φέτhQW―˘=ς‚V4?π#a₯ΠΗΞΨθN³Ά’ƒ@Υάδˆ`I݊ …kLέΟ¨¦/\δέΟXΡ}φ:NHΒCvΠ.h-σ«―Ύ‘U·Γ!έ¦©icώ„˜Ϊ?›σ·yŒω3ΒχQ?ŒP-ˆB―ŽJ6Ί₯tΘώΖv:εv3[πΗ7Ρ†Χ›šΔΏeΨ,!ΫαΡ4ΡUOΚ››ΦΘ€V0RG1θPϊζ7ΏΞΌρFΈ~ύzx葇Βγ=ήϋήχš„ ͺ ’§Mg¬ƒT)―+χ‹ΐυιiΑαιΦ-‚xΫc;βΥ«―J²3o Ρ +:ΏόψϋΓbΧhXΎσzθ^žHt©Βιϊ+όݞͺδΉn?Ψ FYΤ*xκΦ1Ώ&ΟυΫ:°Ε$mK §4kΣLhœ"γΪΉ˜c}^8~€B¨ψ?oΜ¦˜Ώ„dmδ*dπΖθΖψkFώ0|ρΓό™Θμώώ¨φ7ζŸϋ«©]ν/›Ή~˜>BΐŒ_-”›MdSυΏς\3ϊ~ΎΏ2NŽμ£ζ§.« γŸ•°YΊξ^koΓ'ΚP)GmΖϋτ;Z4Ό Hές_ώKψ―ύΧα‘G1δ:pΰ€M0%πΚ+―ώάΏω76W7Y:=!ΐ³ΞWe4`ώτlΔƒnŸέΩ!bΐ! GͺΪΝᒚœμW˜ž #εα@k4ΪΛθΆ-ˆ4iϋκ“η|W!`ύ[m5pα­«ΣbqΉ-8³Ε€q΄σgΝΐ’nš\R8ΆΜίΉ«ε]ofΰeξQ'Gψ|ζo£Τώ0sgώΩ/!±KΈ₯₯’ —5ΒG#`ΪlώΩo‡ι­₯…‰°5ŽΓύG΄s@‹%Π0-£hƒΆμˆΊη…h(£%rΞύχ΅nvΎn0{Ί?6R„Ρ¨IoVf―«“”4 Ι‘;; OΥqKρ χ…7/O„Οi«ίœΦ8 iŸI»7;ίί5eιΘίVϊ3ϊ‡ω‹α3ίοΟ θ’kϊϊβT7:ΞΩϊε.šΙl`)΄jiΪe€NmΜ΄Γτ;Κ―IfΤ–΄RΑ±έ΄›$»«½r EσΑXAœ£ZθΗhΖbωΘζο ܭݞΙΨ6=$Τ}eΈš3}·ΫKΜ’‘ΤN5Np¬Ί*$pZΙ¦₯ψhΞΤƒͺ3ω™Ω.KΈ2Ή mΐrxθhA. «a_.μΤ–οΌ\0V½OιΊΫWΟί–Π­γ€ΕLΊΊ΅K$Γ 'ήΨ怑~Y+ώ Λs‘<{Y8ΕθŸƒΰ€MQ¨.ΔόΏϋΖΝπδ7Ξ™Χϊ§νfΏL8†ρΫjζόυΨyώ’?ΎΊί?Θ‘”ω3­–Ε! p9lFn€ΠADjfΦ…ρ†J"έM†OΆiΉ­ŸdυMŠ΄―_s Uσ«Γ …Ώύο―ΏώΊ1{Ύ ΐ‘#GL`€™9Γk˜E€Zκ₯BA©ύΛ@L9fyΓxMύ₯o] όβ;bΤ0g Γ’τsπcΝΘ_ΜάFτbώ6Βχ‘?L•ΏΞϊχ9^όMυΟ›θ̟‘ΏΓ ‚g|7£;V^η₯aPνΩ0L’ήf…!ΙvΣj'\RΔ=ωš Σž¬ί†+…κlaa!όΤOύTxι₯—t#Y1œ8q¦ΟθΠ‘C¦@KpDkθτ©”έ΄Ζp­‘jΜ£σ˟hPΖfŒAxT.Δ€•‘ςځΐ #±Π„jK.Ε.]*Δ(ivn!œ»5.-…₯ pA $ζ‚@„έnύ₯_0JδϊΫΉ…ΕπμλΧ#JΠg¬?G&ΖϋκΓEμΩφ+s‘wιͺivΒά?}”FD)iQίΠ@o˜˜^χOoκtΏ1;έΑŒ`ΊΓ™Ώ/ψγά~;Γ_ŒΐϊΑόΕπYœ<ΰΆΝϋΗE€vγŸΒ²K Uύ+qF°²β~²)_jΪaŠΝΒΈŸΫ–Ά5N’ xž|Φ ƒcmΈΪt,Ț”ͺ鞰€«Η‰fnζ±Οr AˆΔF£IΞ5zμΨ±πλΏώλαΙ'Ÿ4·t ΘxτθνΈOΧk7–πυΞŒ~ލ£v΅^>tφˆθz©|Τ Ωιlΐ8LIΒ΅Ό³:™ΒtgόAΡBK0―§[wγώ^Ξ^/†K·KΊττΨN‚E| έU†ξGΛbn}αΫ―\ —―OKUήosώŒ”½Πxw›u –.…ΒJI8iΫ`‡έθωώ~NΎ< :½qιNψ»§Ο‡ρ©…ΈΗ_gόΞό‘9φgΟSaώbτΓƒ0~φϋK폐1„Βρ ώ' 28eΆΓͺU1ι:ίυͺŸΖq~μόΏzώ1―ΥΤj[…t4VC}KΣ_λ»κR/nΤ;y(Ž>­΅E[MpΎε@‹†Eb‰ζζζΒ£>~λ·~+|χ»ί5‘u»ω?~ά:1ϋ‘ιdΊHpXΣZα\ΡΙm°;Ζ>ΝH©³β΄Ι†½cΉ"Γ§p"㚠θ–ΚV*^.χ'##^"φ¦ΒT;8qμΦ\0 ―_)†‹7‹α]špA €‘ΧΙΒ „η†+ž'Π΄Qœϋοά1|λ•+¦gO?§ω9σ2¦―>Ατ‘TCRq+fW8XΈϊΛ“aYΜ?κ•šf·₯žΰ½€.μd Μ_ρrψΪso[ΎCύ=6ΠσΟΤώƒbώlσ3ζojΈΠTώΒp„ό(&#{5²<έ€ΈV /ΟtŒ^/ !Xˆ‰iδK­ œρW ŸX.χ΅p™UY³ΰΥι{Υv³0>κ'Lϊή Eφ§:“=ψ• m4*€b*)ϋ'~β'l*€έHΩ0'N σpm$YĈ…:η° α‡γHuΘu~eBΐ:cov4GόθπΘ=ά)Z6Άd5εη%Κνν‚}€`^‚έ“OΥνšKΞΙΟ6…*ˆF«ΊuržϊΗ΄NΞ|βΑBψΰ©Eαάφ3)Βpsί΅±Ωπߞ>ΎχΖ -βcd/tA—‰9cW₯XΨΚμ…tζ0`E>ώœ!"[ΩϊΆ³ τ-‘A‡ κÁ>/q`IΒPO―Φ@Θ­»[pC¨P?¬Ÿ 6 }ή8vϊΨχ(ˆ›Μ_qψ‹¦ŽΏyΥσ1γxξy­Ϊΰγ±Γ£*§Έ1£&&ŒΐιF½ΰiΈŒfλςVK»ΐ·Ά‰`ŸσσόΆ@~ι^Nω³£΄aώJΥ?΄ υ y ž›ƒ1Aͺc„cCτw„ˆ>uό@ΕΉς² I9EΧZΏŒζTό­/ω;£^M°ϊ­™¬S5£ΆA…7ΪEΑ©οW8ΝαbUjR[XΛΤ½‘3΄»Β0s»Ωδΐ&΅^=©΅­€³ξVX : ž¨•π64Εύ.™υ„™ΆΚ½ΙV1PDV2B4ΛΜ•ZΎ¨B γξ€.γ£*Ά rΣ #ͺi ]E#Άh.OuΌπ’1wiλ ’7΅**Hή+€` κ˜'!@£ςgZFζΥΙπεo_Τ6Ξxέ/σβp.ڞ6FΎ€)²ƒ£}αγο§LxƒΧe\&&ΌΕΏ_"γg½‡MLΓ?>ϋVxώτu›gFΖt§wύaT1lΟΦ=4ΎέΟFϊv›}υӟ‰Gόq!UžΖλ/ΤΚF“fπ«pΝρ­Žw†«˜˜†YŏΞύ[Η­Ÿ¦ηί¬ά^Ÿ4Œ»ίί™VΤ{ΧτΜLqvffN^L   00fΆ¬Ψ³€!qiŸψΔ'μ`8ήqΓ/φ ’μ.“ ›Τ^Œ6b "&ε;ηBI¬Έ^\Ί|Vv³šγ_;)w†rX@ΠX(Š29b•aώ ΔE˜Lθ…l1E‘ ΰδ34}¦ θοΧ”ΣΕxcΘ σ#Θ>[°ΙΦΑλKα=χι¨gΒΘά*ΣΈH)ΏΞͺ‘‡ξ ts˜$#Χi­f{ςληβ7{ύQ—+sΩ¬”g„Ό(ζψΒ'ή§;7€Ή±ωξ»ΧNNΰΉΉ² jŸv—|η΅λαi-τ»­Σ 9δgx ηK½xlž_Lΐ™?£~`θΞψ±αΧΎσMXgB±=Œόy2ό‘)ԁ-θ$‡ˆOΰ”α—\`άxw?’ͺ€—ΰBΔΙ ‡‹ΗυdYӐόΝϜΑι˜0ΆΏ§αύέύάvwlwΓφχZwΖ?Σh,Ρ]Ÿ›šžž‘?λLP εQ1 V΅ Ÿdwώζΐ&΅[Uι4Mb†ώ§ž6š©”H°ΜΣ~[Ÿ'ε­Μ°AΙ½n'ΑΑ°™rλ’v$ΊiΊDnι¨Κ ¬Hˆ%Β@ok4ϊ‡xκA XΠΣ«mSCƒΕ0₯UζΟj}ΐΓΗ–Γ£'i²HPB€@Q§HIις׍A€ͺσ‰αέWΟ‡±ΙΘ@iηnΆΒJΓΣ/ζΟβ·²˜ΫΏηHψπcΘ³ˆσn iQΥ/₯œ?Ψ1€m|h-^=?žΡ9―MΩΕ=ςÚύΫB`2ΜΩϋ%οτMΆ΅²ΥώYΛόaς΅ŒŸ&OΚόIΗΣ&}πΎeΌ ΌΠγΈ§κχdΠ>ς»ϊ-™ͺγλ…hδOnE+ΑŸf¦^\ws›ψΌ§ί΅n΅~ž§ά1ν*’2`Y{)LΧΚT:Wž΄€ώξΆ΅£Β¬Ι·έfr`§΄˜¦™qΞ³ΌŠ γΔΓ>ΆαΗσ’VΚ ]”ΎρG’Η?%°¬ ΰΑ„ΒY”ΝB'ΊΚ[Xˆs―¬x{|A7.†χήW'G»L€βC^+˜Ώ °Ψ‹YΖ3ργ’Ώ/ώΛΕpFϋ㇡ržεX¬  ύωk#@8ub(όψ‡N„ŽJε/Ϊ¬6ΉΜ& ³bŽ_―:OB‹ΣτΝ^ώg^ΉήΤ|?fD£~Β‘9²½ό*;εOϋ₯χE·ι‡ΞΨaψΌ3ςwΫέϊžγαcο?¦uέΪ¨Ά”pOkΐΧ6\VΠN,Uy‹ρ«α)λ°TύœΥ𭗯ΪQΎτΏA1~ ύƒ…Šlσ³νw σ§οωγLά™ΊΫ0"gψώΗΟ…‡Ν¨ίGώŽ”!}η;ς2ήͺ εndΆΒ―Q9(C;ω5 “¦KWΟv7β8œxσΏ%9ΑΆ,ϊ°$7ΙrRKEκλΐͺ΅ΓΓ?Lφ„Ι€ΠŒt1&Η&€Ϊ>¬Ν6@Ί‘¬ν2Ž8Ž4ΫUς₯ iyόΫ€w ”n» ΰŒŸ5«ο,Τβ*Y¦ޚX“Ίˆζ½χθς–~Ά¨‰9©-œl',vkήΐG}ΌΘŠ©ΛY0χ•g/Ϊ©¨Ξi7ϊ1Κ?~x8όΤGξέ?"aaEΫ:W™fΧ_]Ș>εcm ύ fŽͺNϋφ_ΦUΔ/~†Fό“6 €&€~AeΦΙƒΣǝώ–2}w†ξŒΫ?Άkœω;γ'i.yπ`wΚΝ·γ‰Θ~κΉαΥΘ½™_³8)cΞ²²šΕ­υ«ύφ2₯ξΌσΤζλξή?ΫϋΟΐX=όση”.”6U»PUvΟϋΧ~νΧφ )Θ€5ΝΌ ΰ3έnHΌΓ8 ˆγg SΙΛΰHνίEά@rάRAΒ‰ΰ6D•©l+B@JhmJ@ΪΆc±6ΰΕwΒγΗ5%w dt·R¦ό₯=¨yD|ωλŠ_mχCώίώιMmη‹£λΈΟ?Žςίϋ£αψ‘Β¨ŽΕžΧ)wŒΒ‰K›iΌ0Ν6SΠ_š†Ν/ά™*j;βυπ½³·tΒη΄ ~μTΰΨa΄L ΩΎu?ύ‘>εŒίϋLή…gό.ΈΆχG·ωSήτ|;~z}FŽ'ώΪόΉ·‘_-σm'Ÿfι5Κwχσw·Σ<]=ο~©MΫΰ/šΠ…ϋιΣ§―(ξ²`‡ξ•*μ@ϊn½Οa Ω+&Ά»%aώt―>½θ8`λ†Έν ²`Ά³h^Κδο”§‘ @Χ €ό„sβŒνΪ…ˆ4ΪάηζϋΒi];<­έΣϊN›z"DΘ97Ν @ׁ‰3—Ξ9ψo_Ÿ υ΅³ΖhΝO —φa?ύλSαG?t―1d˜fͺό£πΛ™>εξΣhŸrq,ο•›3αυ·ΖΓkυ³ͺΑ„•ύŒπ™`j"έΦGί’?ΥλSΞΐι§#ZΖ_;κχΈ€ lxΘΛ‡w-ΰξΈκaάn侞8λeϊΝςjδGΉύIΓΰζBΏϋ{Ήo'.f~~~E—(uέΈqγϊ™3g.Λ©[κiΩ¨k…ƒ9i@+ όΰΓ'?ωI+톑]v«Ι€-Gγ724|3FρͺάIžώΓΘbP/΄ˆ»Uάώ―λNθπ^Κδο@’‰›' |σξΫ m­Ν+σσρ~ΜtU-.Ο‡ΗO•Ά¦”OΎ8°u€Γό—{nΔ»ug>όε?ž1U; Y)zυkdύ38Όχ‘CaŽ#€εηΜΏu.υCINθ2LŸΕz˜^1φνΟοΖtκΰΉw&Γι cαΣ–?jύ]ALpβt©Ν{9Ϋ?cΔ΅ύ¨V €?9γw;|Δο~ΫΣς~λyΗΣ~N=oΗMάS³™ξ¦E9ΕiTFΒS/ljΣAχtk™ΎΗΑ=}™χ/θVΧ•“'Ov}α _x}llμν"ΖΎ(/€zSΦih 7ΏΊ0@\ς Ό»Υδ@‹–£q™Τ›†§#:‚β‡[ΗΖϋΐζχt·}™έΊΈF‡ΪοX.³“:}ΪώNΤ .Έ?Σ΄Ÿ  6DΨΆΚfJ€ƒ…X‘>9ΣNߜ ›Σ\Άƒ€ρ©\Π Γƒ ΐ•9#i.ΑωμWΞ„Y.aޜ~―ŸCύα?|κΡpίΡa-Βd‘f ‡5dQqΆpI`АψΎMΌ˜ΧοQ[SΙ™RΈz{6œyϋŽΝνs«ώϋϋΊΒθHΏξž@€Tω m«Σ;ίή_θ+ήo°ω†‘§3}gτ΅ίΞψ‰λ}΄ΘƒΎμ6οiί¦βώ]ζΤs#N#χf~ΰK=³ž΄₯CZizι·»»›Ϋ^fΖ¦¬ι·Ώg8_ίεΦΕz‹Ο~φ³ίVϊ,—d£Σηq έS±o{Ε_όE³ώ1ΨξύΝ€mG'Β`Σθ0}:Θ‹$Ο|nψ­«S<Βε˜:§œΩ=P/LfŏυλpYW· *^o'Ο‚κnTޝˆ;α†0ππŽΒόTΑωy "S³½αΜνξπΨ‘ γΦ―\pHWΫρ‘…Žp^ ω•7€˜³yλήU£ψβ‘pβΠ  ΜΑΓ΄αε<­Œ£ιehj8CžhβA<’₯%LO•Β•[sαΒΥ)Ω³šηŸ7MWƒkLCΏ]7œ0|ϊKΪgΌί€Œ&O߁ΙΧjέ γBιωC>Ύ½O»»Ώ;ώα榞~Ί7bϊλIΛΛ–Ϊ^žzωΈ_=7γΆ»a§ώξΟΒΤΤΤ<ΠsφμΩ O?ύτΉ‘ώη$@ύ»€ΤcέKi˜ §½>ϊяZUΌμcδ@‹Ζs„Γ†Ρƒδ4ΎΤGl# Ǐ‡67όΧmΐ{Φ΄Cω֝ΙζGΜπ£B˜6?‡ΞRτφ’\ώN Tά ΈcӎώΰΟ{JΤy§½ΡΜiJ€γ…gg{ΒΩ;½α‘ƒaΈOχˆ<ΠtF%:+κžΝT‰H²­όόWί°ΉΞϋg-«ύΥαίΤ£α‘S£¬JΆE‚i› ˆ΅HAΚ–„Α^MGr ‹μΆΗ‰Ω₯09»nάY0ΖM#ώ©YiΨΤξ„gQΏœΜτHΰͺήxˆOύΎA?IϋύΓ>οήηέ™ΎΫΫΣΐφΎGέιƒΨ·c λ3sΗAγv'ξΞP=njw’N―φtόIύ<}·ρσwίΘvFοώι7ο<ΐΪ,!Ώ, όαώαΣΚbZν ‹F—‹‚ρ’βCΌS`Eξr^=ψΗόΗχΜΐͺ«™\pH4°ι ‘3- ώηή~ϋm;rVσIαρΗ?σ3?}τQλΈ΅HΫ ιθ mƒšUΊωOqΞΏί¨‘ά΅¦£rΥFnρνωme-ŠPενεπφsOˆ-D'ΆΨΈσ ιϋ{J€yGΐE+s =αβtOxdτvμΥ‘Δ\νjθΉμo›ξΛΚzFτσΤωpZ«ώ9)Ο.ΞσgΔΞή Wgu₯ο²4:B·ΗŽΡ¬ηf?Ρ²ίU fθΑY%\,–mϋΰδ܊n,i΄_ w€ΦŸžY°Ε}+Ί@ͺKά‘~„@1ΐ§bΫG†Λ{νC_p&νύΑΈϊ±k™<ί<„ερΏΗυ4=?*G^ο»n›cΗΉZ―zξάκΉ“^§ξ΅eπoOœ«5ξη6ώώξαωnτΖύjίωv7ΑΎ011±όΔOτjε₯Ο|ζ3,Xw/,,θvΞw*£ώOη½Γeέ/~ϊ―U»Pέbr EK ¬ώΤΚΡπΥ―~5όξοώn˜žž ‡ wξά ―Ύϊͺi~ώη>|ψΓHtΞ–† ΄)M#”θμI άΣοΔ«Ρ+žς’N υ γ¦„g+:2uފtΣΊtςξeIΛ,ψVΐΓ …ΓDη‚μVwλ™—ί₯ωBxΈpSσΔJK#ή\`ޟ:?A ώΎy1ΌπύλΪΧoΜΏ‡Ε2¬ΰΈεηΌIHθΣx]Ρ|p(< A@ο¬Όπ0 †έΛ@ηΗ½χέL₯?/mΑ|q%ΜκΌ†9]€5§5v€‡ζΦΘ Η χθψhνϊYLΥi4Θ΅Φ|YπφΕφφOέxχΆwfΞ7 Η™»ΏΧ )ΓχwΟΛσsΫϋͺۍϊy=ΊRύψυάιουL½°¨?u#-jέύΫσKντpŽ›Έ§ο|ϋƒ»ϋω;qΑcΑΊ,‘Ύ Ψ—ο½χήπΫΏύΫ/Ϊ8©φ’weτ±δq TΧ§XΩσΉΟ}ξ;O>ωδ·Υή=’‚υ’ρE€Ξό‘ΐ&!‘šJωΑόAϋ¦μ“ -Z’‘4Œ^ΫFΒυλΧΓƒ>h:<ή‘Ϋ΄™’….M¬H0X\ŒmμLΪϊ¦’/e"Ά—‘°ΞΌ=^j»ΰnώνq΄ΌOQοcΨwk†#ŽK¦φ»™;ύΊΦtΏ6{iϊΈQχ« λξ©Ν»{xδqΏτ=uσpξΓW?‚ω—ίώχχLMNΝό/Ώσ;₯τ%ϋ-²π―¨gAOΊΐ…υ“}šωρ|ΟΝ«ξΆλ;7 @g¦S½υΦ[&@,θ£££ Œ!€ŽHxžΤ–hΔ5ϊh3Z³΄)#ε‚Ή‘<BŒ033S!p»ΆάN¨0ώήNΨΪ0·έt›…σ΄:±i#4ΚζιCψρ㛇w οNΐ±Ν_ΛάyοξšΣ φcαΊ¦oξ齦Υ~‘[άύπÞ~Vϊχijδ–ŽQώ―O΅½ό‚)‡3Vϊ$L†9 ~Ϊo8₯Sπtί=·4φȝ]hZˆoσυRNά ˆ¦ΕXΏ-4€}€}PΚ4τ΄zΛϋF΄/ όΡ~‘7ΖΏζYγ†?ί^N·SFοnžΊxlάέφώTkSά0Ž#ιw­›LΒΊ?6§οιΉΟΓ₯nώ^k§ύΏΦΟΣ&ŒΏ7 “ϊσξίι;qݝ4=]άόΫΓўšλαπS[•ΕΈ °-έsΟ=½ΏποώέηίΈqIν΄"ܟ¬JŠ—Žώ+̟’Τ€#Iό!0tDˆ^[όWwγΰŒ:Ές2ŠFά€qbΰ…€x‡PQ^ Σ”B…‘žψ9‚AΘ&¨³Χ d#ίΔΡbšJIŸ‡xn€ι!Ic{9H—pi K8‡#αx<O7΅½LN„λωy™¨7ιSvήκ¨επ:y|Κ@Ϊψaλ$± |Pyχ Yœιp2ά‘jϊhχ-1'ΥΙ΄ˆϋCŽ%ΝύφK―…;“³vY·η‘r¦ΐΫΫΈleγ60ΐυΜƒf3%ΰ𦝀;yΰ¦Σΐ؞~M+”₯σ§/.)ol$\wΖ„iGββNίsžω”ΰΣ­²ήQΉ`ώŒώλ Dή‘“6uςνi(οn7Υ=e·Χf ΚOG!ήύξw‡‹uy‰ˆ‚Ρ5ΜΤΎQ«ƒάtΖΆ; }mA?wDHΨ Έ…Q&ΚΠΎXCxή©'7?5κ">wβtκ Q!,ΒρpƒHxΊ)L „…pa@6Β‘™pψ‘>i:ΌI³ž‘μZι[ ηωŸό)/e’-aϊ:ς /&Gž^v΄%„!κN9έ&^oί@Uψρ;ΗC—N=/‚(Υ³xβf(sκUwΗΈ1B_’ϊŸύβ«αΝwβŠωωƒ)πfώψρ;ΰ |iΪ;φΛAk#Ϊ ΈγNxϊ˜cπΛMI‹ϋˆOŸυτ<}ΒyXόˆO ΏSΚFΏ§i[ς O:Ž{™ι/ψQ>p€wϊ y’u‘ €O_&nτ%§ Δ£txΌάδK|κMz€bfVVΓo||ά#Cρ£>œVGόθ§iXΒ`¨ οδΟτ%e€\L—ΊyΩH›π”ψΒ‚Wψ{xχ2Pςp?/« ϋ©›†­υKΏ ίξζߊ―ž+…S§N-}θCκ{ςoώζΜοώο.^τUœTΆEω3kΉϊŸ+ƒΛτ‹_ύΥ_έ“κΥ=Χ„f†L'ϋαώαπΒ /TόΞ”`bhψ™0ŽhΝψ ' %!Ρ1·}¬s @%½/”Ν £Nl(6„"I8D ? ²A€0ΤΩηΡ‰ A ,ιbΕ7q€DxBΰΩMρsψφΈμ°p"ιξ|SΆZΨB4 Vδ…]kp£oΚEδQ£ό” CΊ€…νu’ώNό©«—dd8¨Qo1\Ήq( H 0ΘAA’Ν‘άΦ–hχΓwΠ€p΅/[όΎό­ α₯s7Γ±ΓμΖΏ> ΄9ύ¦lyhΰHΐ“p΄―χ/Ϊ’v‘}0ΐ™Ύ;qΌyϊτ!Οƒ°΄7ω’ξϊι₯}’‡φφ>>SgδΔ£άΔ#_Βα–Έτ'(}•:7χ#βcΟ(}›ϊΓ€9[„ώIy8_„ψ€‹;xEΊ”ΙρoκCY=]ϊ$π”‘tyΘ‡²ίϋ4a)ωGκ…u€nΔ‘όΰ:eΈ}ϋΆ₯M)ι’7aq# ڈ‡2ΰGόԐŸΓΒmoχ«΅kύωφ‡°ή>™[α‘GYyίϋήΧσܳώύζoύΦ‘0³Zπ ΑbξζοsΞόQαT¦Hœ€ΑοόΞο˜ƒχ#σά#?Ή ACzΗ₯cƒ.\ίωΞw‚ζ”Œ‰8ΣΗ†©°ψ„€C‚Όmu―2η° _ΪN’Σ€NœΉ 4ΚaςΞΡ#,„8@άˆ a0€@± Λθ‰w`DX‡ 8‘&HF~0Zό!^N|H?ς‡ψ»»—!΅qS·τˆε₯씏τpsγνNXήyx'#+ΚB™hoβ±0te…Ρ‘FŽCa¬o8άΦJψzn©Q՘w©=½όwΛFεoΫύ΄eΗΓן+>8,GΑ#Ϊ Μ€nΐžώE?¦Ξπι{ή60pή½/’†ϋΓι;΄αH›vq¦KXϊ}›όhgڐoΟ—~F\˜nΟΣΫ–oڟzίΣ",οτSβ{:€IxO›p|»MnˆηηΚγl(3ψPβRvπόpsά"σŝ°ΐ…Ί‚{Ό½;ξψαΟCώιCš€MήΒ‚§€ ,¨/yαξ0 \^„灅ό1Τγαωv?wΓ¦œι7α<¬ΏSO ayΔψ˜Λςϊ«―.όςόΫ­Ϋ·/«Ό‹ςcήAιΉκίG.PΈ5£Tψΐ¬ξ΄9ε‘{Ε¬RΎ½R£M N‡‡ύΒ/ό‚1y%i€²@@€r²O‡tdθ€£ζΤnJυ~Tw£Bš ή@ΉΫ1„™¨υ„H`{Ωy‡ΈBX@~GJwˆ€‡Εol%,Dα›Όά@`°αNϊδwγω†?ξ·»6 ΎλwΗ†ΞN½4ΐβHύϊ€£+œσΪg>n‰!’fpQ?Ÿzyο7Ϊ—yxΞφΫ§Ύ―κΕ/ݎ6nΐ„wΪΩ™66°wx'Œ₯₯0ΐ—>…ύ‚ώ>Ρ§;ύΓϋp'<ν@ZΈσ`ΘβΑlq'-Β’mHΑ]Ύ‰ƒε£Μ䇁™—ςωΎΠφδλuaΤN>.8Xδμ‡Όx0Τ‡r“Ÿ——8<ž>α܏pΐ‚‡4¨ε$_ww€6e₯>.ΐˆ λωS/ς§ž„'βxٰݐ?e#=ςΓ—ΊS^βαNΎΐؐ——πžGj'υηΫΛβa=ύΤΟέ¨yQ§|δ#emΓ^9/ϊό«ΏφkvφάΉΣ*χŠΚ5©p0yεεκ?ό§2ςΕ d\ΘςΡ?υί‹foΦj[ŠNH'σΞψ©O}*hnΙTrΈA<œΡSγqS·Fο„ ΗΥΨθi[ZώΡΐ& ȍyѝPxT‹Η‘wΒΈ»‡swO"A`tAN ιΖ›wt1|c(S[6sά’ς%?Κ‘sXαFΩ €R#efE{_?„]#€Ύw…ή™)-”ϊx1Z„χ¦ϊΧxκLΈt}2œ<~Hν¨Q4νd} ˜;‡πβΨ9ΓpXΒp€1νμmMŸa4‰qa~Δ‘O‘žχ!vjΘΫ™œ3xΒπŽ;ύtΘ f†εΒ7βσΠ7ΙΚ#eΤKωιΟΈΗγQβΉ! ιx?>#‡MXκθqΌΧ~S˜=*xΚAxΌ<žn€αεαέΣ$?ρrΈ;ί^wσ²a{Ϊ€ μΡΘΛ΄ ΄ q)ιy:Ψώΰ‡ρoμFι·ηιώΔεCp~δc £._Ίx±ηϊOιαΕŸ£~*ϋύ™χχ­ΜύΣY(€3«ύ«6ΆΉ_ώε_?ϋ³?kψM»S&o …ί&Z4# NgσŽ Q’Γω\?~tH˜€#Sšd[F4ΒΚ@9ςΉ4‰M§L -Ζ‘}=™΄ƒ δεDΕ ‘ηΕ7Δ’ 1Α4J“tšωγηa,`ςƒ{#Ώ$XέWΚCωέ&iy]€οφ»χΒδΔ †jqά‘kξœ$.›Φμ~- —Ψο―³τίΊ:ΎύΚ;½ wϊt›^!cnΐΛa“2~ϊνΝ3‡q‘εžΈ#XCΰavΰp'Lœ~Γƒ άΫ#mDΪ ?β/}Œoςΰάε›tΘ#-ƒ·9aΌδΑCΉHƒΡξάάΌΕumΒA:…FόF†zΧλ—Έ ο<ΈS?ͺ}ό)εγαΫρšπΠ%β€ιΤ+‹°€pΒσ—xώ_Zθ λπχ2Πfΐ 8zΐΛΣHmJΣδ;uσoβψ;6εΒPOϊ‡²1=«~·τΦ… =σoφυ§Ÿώ†π± rŒ©ŒόyԎό]υOA¨Ό‚)3Ω”Ÿ>³ΧGͺkΎ 43±ODΔ \:κpΔΒφŽ^/-OΓΓ― C·λ²³ Υ?;θ–Χί¨H„”²ϊ(€χ%ζH˜ζAxά ΓγΖλεί΅ΆΓ…<\K’†q„†x₯ˆ;πtΓ7šτ 6”‘,λ•Ισρτ°λ…Kύύp”‡wςε‘ ^fκΑΰ»OοΤΉpΰ‘°RΊΊ–fΤ–Τ‡†ή†+Ÿzώ’-ψΤ‚?€Ϊψ/`ΞΰΡ†ι3 £τΡ8̘‘>αx0ΐ˜0<τUF›Ψ€C\gό€GΏπxΨ΄νNz”Εt h„ƒασν„žΆγ!ڎ2{Jmοw€MTώ”…ς#°N……r€EΩj πˆύo•‘޲β‡Νγπsw†5ΤΕΛ…Pcφ|œ&QOΚι8…?upw.HβρΌπΗπIΛ…p·ψΎ3ΐσr8xZ䓦ǻ?„ρpΖۍoχOmΪƒΆΓFϋžχΌ‡>±tυςεžυ?ηηK_ώς?ͺmΊT·Ϋ γ#˜ΏΟύΓψSζO%}ξίΰΙ”Ο/ύ/Ωά?u₯=)χ…ί3&Χ΄hΚΪF§ƒ:"yTοΠώ½.[KΖΥ]ρ³vΜ φ:xF$ΖY5姃ӱ!†tnHΏŽeōlj&Q©› TάNlπσbς^Ο–΄ˆoΗ΅fΜ›° 5Ĝό ¨_Ύ ŸΒ· ½>•ΡΛFΉ0ή>^.'8ξΞ·φ,BPχnΝ‰Ρqυ3‘‰Q₯¬Œ|€#SοΨ^θLKοΦφΞ—‰ `n‘TΧΌ ›βΟω_Ρ~ύžπΪ›cvβߐNϋcτΟ鈴νζmD»l`F[;σσκΛΰF\ΒπΠ?ιhΪ|ΔξΪ‚kΧtβ’‘ο’–η?i`θ[33ΣκK%kΒςΆς~_,Ζ­Š΄nδλύ¨Tα]P ]όH ,ŽˆΧγΣΧRθn…)§χYZ›Υμ7Κ΅κcΦϋΖmQ}‘τŽFΨ€3ΈΣφή4JΆ«ΊσΌ‘9η›ίΣψduΉΜΰαCw±VUθ^6 Λ@›Υ,// vΡΆilμ‚bUW74« [HΨH¨tQ¦ΫHLΆΑPX` ,Q,$!4!ιΝ/_‘‘‘‘™Ρί>wGœΈ‘9I/ί»'σΖΉχœ}φ™χήgŸ©•Vβ/sΚ’²Βx\.΄`{\Ψ<Ξp i nψy’ONhΡ+ˆχUόPπ£Lγχolw‹γsw‡s?wςˆΰ£;Wš² 禧§Ž/ύ_οyΟϊ̝w~Ny.ͺ|œω3ςgήί·όQ1ώ7ΖO•OEem΅IΠɁΙm·έΦ€LΙ&”…½^P?Ή°Ακτ” Fκg Fͺƒq Ί% ©AL“a&ΰα}ΐ_βP?ΣkXg€s’4H‚ξΎ΄ΞY©BΡğ<κΆ‘!]™ͺ„ΒL:Ωg Q£σ₯*>β§υ ^Rάƒοΰa­¨SΝ₯x9ιΤTΥ‘ΑλρcC„η5ĝπE»’›άHΣ’ˆΚΈˆMΆόΓ8T²<'@thF%tζψκWΒ9'OΦΓςΉh°N TΎ€]vͺέ’β_–6…r\=’J{’β   IΆ±#wΏύƒ“*.ʞ²Σ―ςJ~νž1%κ’.x(3܁3΄ |δξεo~ZC‘Η ΗCϋ[Y Β7Ϋ.aδZΰ€-Q/΄OF²0ΘJ₯ͺxΓGυˆMš°Y«A:xΖ¬ύ‡…ƒΰ^M『iO–^r«4Qη΄i’aHŒπz»ΔΆnœΆ%Λ‡ΞMπΆΥδθbύqΪa°ƒšΫΛƒ[ γ"°°‹ΥEλίδ…|ΡΞI+i¨)- •eξ}Šό"P‘Κ‡>E›?—$5„<ώΖΫ?0τΕΆ;ZΉ%‹—4ηΪ ΰεα8ΧΚ³š @ΰυwό=ŸνxΓ:pβχόη?Ÿ§©8 Ǟ~Ί1sζLιύ7έτηŸψδ'ο’Μ?«φΟͺώγΉpλ‘νΡVήϋήχr‡@K#-^δηB2Ή°M΅Iγوi5(šŸ‚Ϊ…S’™Mπ0ΡJ[˓֍BνΤ:87ΦΡm€"\ΈΣΞ}:ͺSΧL…*’ιι†Ήξ€0@H €Ρ§:^ؚˆ #\FI„χΌΠQg~‚αέπκ”Άωr8d„90uQό!Jt6ˆω>1R:9„„xΑΝwC„‡τςw73"ΑΉωΉdšύΙvΦΌ24bΝρ²ΜΣ‡τλš₯p ££ΐP: œό)D\fΞwΡς …h’~ό)‡ΚΔwALC%―›κ”ΟDϋΕ ε΄J©ŒΞxΊεη|s³Ά b͈‘'f’Ǐi_Ί420_ΪεD™Σ&Β?‘ώa@œπ7!•8Μ8καŽΣϋ8ΆενŒv1΅gΚꜢΘ<3ν„v Ž {ΤMθR£‚™αO}ƒƒ:?x0L3Pβˆ›0¬ΣΐŸ:Η¦ξ¦φN%ϋ–φYϋ?}ϊ΄΅β€ LNLJ°QώΗ%F΄ι2ζβΛσeΓ[Χ)δΌLL„u ΦηTΧFΤ6@ΙΛθhΊS†JΖS DX±ςS%c<²i―č;m‘ΡΜμL‚6„΄Ηƒ?5Ε(ΉfναdΏ¦PHΣ΄]β§€'ο΄c Ρ"ρÍΊ&οΨ”°‘ίΘOιD[ΈgΟ^αœIN:eύŠ£K`δΤ=uΔΐώBšεix€AΨρ²υ΄σ€‡@δBρcΰι£D—ρ\¦ύ¦πΠ4ͺ•JιΆΫoάϋ؟+έΡΌs γsώΎβŸΕE>κύ‘΅U₯ƒƒ¬-Π.oΈα»Ϊ²B¨$}žr‘™ξΤτBΛεζ‡B#κΤ9 4ΒΡ;nƒkX€ͺŒΜ¨“IV]ͺ¨ΣQ+ƒ‘X Rϊ’QΧ΅¨α «t„!Α-Fd΄ή ΌTVΗμ\•Ο½ιΛ5T‰œv ’ŸΝjC’Μkq°ˆΨ--i\-λώυ0κ!!从ΟΥ«ε₯ΉdxFσφϊΧ’!£ψUurάHΗ¨.©,‹HLkϊ:αY‡PΥ―:ΫΎ!ŒΓΓZΎ\T|ηzvFHa+Ί_ΎVΣήfΒB0!JŒt–σ:«^i’ŒΠLλήψΙΉ%1m©•žͺ;ͺV˜PP™‚bΉάl$e;` K§Ϊ©ά+υ‚ˆΦ²ΚRΖGaUΖ°ΆLJHmΙ.y₯dΌ]σϋO'³ Υdv,K[₯’Qέκ€>­>¬ο†ζ°Fτ t­JΙ‚κ>)i‹Ϊ z ΊΎ·νΨ«πJœ¨›Z#±$χΥΣsɏI[₯SμV‹Ι¬κ†6C»ΡΑγšV™žΧIxhΊ(ΈΞ\Π‘AΖάV$0¨(ήa:ζ₯Ή©iN\α—ͺJŸNg<9­jχ΄ΕεϊPrϊœΉͺ¨NUwͺΪ€¦[ ηgBΏ _·¦r4Νqς¬Ϊt±’|JH]J+κ/°Ύ€QˆpaIνL΄€“f+7ή$ΠΣξΠl,KN1\s,L—‘χ²ϊΤ"aWjj§:C"ˆ £Ρ}EύQ /O(~1}΄¦ψη€ΙSΒ­œκΗTŽZ`y;~z&/«μh³B²¨ιΕ9M‹˜’:<}Έͺ>”ζ’ςbθχΛ\I>£2Y@kŒ₯{‘5Ϊ©<]NŠΓΪ™¦‘¦4ΐΠ‘Τ/ΒAC¬*pZe]V?ƒΞ―υ!›M™£YE  ¨V$ξΫ£ι4 Y:„μcσύo5•ίχο»―^,†ΓŸώι_}θΆΫώSΔό«j£±ΪŸLΠP|ή›‘ΡΩͺ˜ΏhDζς—Ώ<ΉυΦ[ΉCΐκ]0=ι ~‚Ι€m¨ExY‘3ΠΡΨ;YI·Hi0‘π£jΆκWΙ’„tr€‹ΊΝ»ΠήΗKbŒ §θˆΊ„ϊD!ΠlΚθ§Y#/₯­ͺέ Ku4iΰ ½‡Ξ\Ρ*h8A0ζgb„+ΑχΤID^£αfΔ‘ρ}²"‚_³Ξ±nΡ?VΞλ_Hλ+…d^„$4YθπMάΒŠ*@Σ@kuΉˆ~]§,β³ά1#08ꨀyJ}TΔ ͺ5σjύΐxfη5§Ή¬QξH8™Ž0ΔE7šCIYωO$ h&Q±@4RΥθAy(Φ!θ…dnυ@rdθ˜ό4ŠΪeη(«j7šΡΑGΣi4*—T[Φ€Jž”Ή΅+ςBQ_rΦAˆb–ΪQIl†TAλζ?ΞJ€Q°ždX2Z–gQ~Cbά0Ϊ†UA{•:έΎΒ(™t4ͺψ·+ αaxL{χεGεΨBr[ƒƒΙ`ΒoQBΊΪ₯DcBJW΅¦6(/ΐˆ‘IΨ•°ƒΧ³_²>]YDΓβ&ώ’ς1’όΡn(#.!²8«΄Υ(}J– O‚AiͺέT€ΡCΨ X £ΰŒ±κtEσ‹1Iω©#”α ‰ώ“!Κ†Α†>•N~+&―v(CJS]εX™7ΑΘ΄bψ%•1̚ͽ ³sš“Π<ς΄ϊ2β©h°ͺ‡h0„я₯‰©Mš“0"VyI³’wυ:•‘h…4―τΥ…΄^–€ΔΕ‘„ [phqα.7αΖnJ315ΑŽ CLkgξημŠuišgNŸ.θ-¨8Ή0ΏYΧp=σ΅έqβ”‚{Ϊz₯κόr'΅FάΥΖ‡u¦#OλXgϊƒ:υ―!Ζ0,υQ£_TΤhDPCkOYMNς„£vQλσŽ:}\*rΰ- LŠͺb*ˆϊ€©…6J ΌlυŽŸΉ΄θΑΘ?όΫ§ β^Ώ8Ί[»"C+ΐΌΔζBnf¨_’£’ƒ…ΰΕθ˘tψ4ΐ-6.˜_νi νΤγLσ`mHn0ΨΘ„°ΑΑΪYδgι2άm°2’=sFτHΰίΏGε-‹²€ΑΞΟI0Ε‘L΅›α°M3XzΘ§’ΩŠΓC»6GΛ»½+*Λ·•Kπ'ΝΞΓ€ε„žg ƒ@mšjυiY˜)‘βΏ“Ί§~ꧬ]h*¨yμΙ' O?υTύΘαΓΓω₯/ύύ{ήϋޏhΗMSjY…GνοΜΖߍωS <Δ¨β ̟)ϊκ]wέΥΤ)‚Vfh ρΫΒ\&Ά©Z‘\CΫΪ(Bυ ˆf8`RΐΆl„:υ2­^Χ WΈυΒdΡ8Ž8Œ»eacχλΫ ΞαέξΞύ<|Ζ݁ ~0" |Ήͺ•κͺ’}S:μEŒk­ ᝐ£‹«ΈμE#\βΪψQΝΫθVB€F˜»ε\Š‚γPy<όδ\2:Μ\? ωX€§Ρ·8σκ£<iNͺœ&χθ„Lώ'eξΥ˜€ζ₯™{·C“`ώ"ΐΜq£Ϊ¦ό‰ΗΛ?&ΐmFυ2:i£Μ³Ζάbw! pr– ΫbΉnαŽ™[ˆ+ΰ‹΅dIx ·’Ω΅βΖΟΌ–εΰζ Π›0Π 4i€Œ°Cόš„1fΫ)4p=scy­Z(ΟJ}.­ Β°F‚Ή}ZχΞόG0qY:œq[aIœ€π|„ΈI #zΩϊ[Υ”N('΄> ωvΩΦ/(4>š&2ν S/,¬kτ?‘\}υUΪΪχ| &α”Β'ΌyV#ωΉΉΖ%GŽ νξ»Ώύ―oU›iH`ΰrTώ0Ώ«ύ}δοŒί™?«ώΙGΣΧCΐό_φ²—]tΜ_e•k(„ν0,\Ω”QηBP(Υ΄&MΕyθέ›Β–ΪΖ€Ψ±υEL<,ϊKιdΧXq D’D’ρ3Šš:ΩUX8Ββ·²υ¬Β ή#ύŸ›―iΞ|ΡFύrJ™u(ζΛ}€-–“P`ΆΤδv8ίbψ]ΰlaXΚuΓcΤ/œ*΄ 8ΓE€0Φ6‘sxy·έΫo~b@Φ?C8‡κ„qζζΎ|σΒ΄˜{κMΨvx\XX‡·3uށ ω ψƒμΔιxœ‘ZΓDb<―ύκΗΛ©·>ထςΝ’6˜>ο”>1[1„/Γ††CώφξΆ>‚πΥ#Ν‚³Άž†%Ό?ξNώyχζŽ?iaΔO½°pς/ψiΝυ#Σ±ΥρΙ89uςd³^«€Ιh輁·ο½χαί{Η;ώXIZ½ε&1υ―Ηό!Μ1σWτΝ¦ςβ/ώ˜ŲθOeΡar @GqlώƒyΗ­˜#dέ,ΕeV»_o}vΘT!$‹•Τ,&•:J―zζO1ΐg"‘μαUVVλΔ΄½—'UΦ'Θ_όΌΆQΈCΐKš‹?3³˜Μk~~r\‹ΝDRΉζΖOΩπΐLP©B\yPο3ηαΫmKF‹ xoύ'-“ΈŒ)KXGq‘&ώS―ˆM†’τςη ”ΐ1£@ °ρj ©_Š ό Ώ!|™`’ΊΖq8ƒΗ?Έ|Όw~wͺΘ ηa–xΰWAˆ_όβoœΡwΠΈWˆ/†ΏŸ₯@|ΰ‘ΜqwΓά{'Ξ6ΖΣζi0[x(CΗιeΰίΖγ!6˜>ƒ%„η=š\sΝ5ΙUW]eibη<™ΦaJZ”§ QC©ηW4η_zπ‘‡ž|ϋοώΝ‚™Ίπ—eϋΌ?£~_Δ#ζ/|RB¬6Ω₯ΐ‘;ξΈ£ΙΒ?ήq#ν”ΝΕdr`›j;νž›ΖΦΤ’‚ž0υ'lΘ¬jmgpƒ%Π₯³Α‰`ŒYt°e’W#²0Ά!1ΊΒͺXš8”Ζχ'υΚ™]5 @ζ ΰOždyψ€°³HŽςαA€ωΓτݎ0׏ͺ?0}Ÿλ7ΖΚM ^/cw νίΰ˜lΫ5ΌyXwοΤWWl²Μ6φ_Œ“Ξμΐαš?‡ΛΪΐΰζŒ‘Έb-α_‡s7Η›uΏ6vγݍ·eΰβ8=œΗ‘ύ&|μΧΞKΠΚ8|€ °ϊ΅Ήu˜:Σa¨aϊW\q…ΤόW›Άq&Z0§΅ g’²lΰΑ―-»νΤXLρΨ‰§ήφφ·ί€νΙgΥΞj*³΅Ÿχχ9˜?ͺ Φ•ω³«†γΥ_ύUSϋΓόΙƒ—Β^4&6QΥήΰ!V[6)Š‚ΞQΧή©xψaόΫΟ–š#€¨ΞΈ}PwCιΒ6v OIκ ,„Ρ xšΠ ιΪ* I=)υ?ω±GΜ&ξ̟Ѽk\pΐύ™λ' •μžΖ ¨»―—qμΫΝ-φη}˜8Œ3J‡οΖό9:6nϋϋ»Η— Ηϋω{·p&k{μμ{μζαά-†υψΖmΟ_Xψ¦Bpƒα³’Žjζ uNπs¦£?qμX27;§m‹Ϊˆ ₯ ζ―Ά3€σ fχ·½νΊvϋxΚόΉάΗχϊϋœΜόaόΞό-‰jkŒόmkͺ~ζϋ?σ™Ο(kα,lΪβΕhr`΅ξΔΛ6Ο¦Œ3E ­ΪΦΓzEνΡγΩώ<Π³^-F§)‚Ρ}—'•Sχ?λi4eϋq [1Kz§}"ΤΠω»νLή·]0ΐήΓx?rβλvΏ΄uλkƒΊeqΗαβwΰ`±‰ύ‘γ?ΐ{>Οƒ?yυ0ΐΰζpqx‡Η γiˆapw·›ŸΓΔ~Ό†4Έ?ΆΏΗ°ΐωC`τŸΓΓΨ9¬Ηœ>‹ yά,i―ύI^Tf??Έ, €Eq―°&[[ώΤv :Ρ°ϊΦίύέ›{β‰GΥv­]λΛωώ,όλ6ςgτσwbά:θG#;ζζΟ’?ς@ϋΔx=ΨΗEφ“ }*άΈƒΡ‘}1wlˆ[ΦΓ¬k;£ŸΠKYgJBν’fμ~zuάsc]·Ο#ΟΈ]πΞβ6JΡ¦w-„›ΑI₯Ό¨~Ο£δ·’Β hE*kV“Οθ<„ynΔΆ?±.›²Ό †Nϋηq¦νjήρ‹Ώ3l»Ϋ΅3(Ǐν}Θέ²ίξŽMψΨ?~wάΈegjΈgίcXǟu#nά²ΆΓ™Gγp&ϋναάίγΞίρ‹σϋρŽqΑ †ΞΤ6k `ψ0~ήq‹λ‘ν‡œΘ!;Λ<ΡbCXtΚμmβ*BιPb4mF¬όΞΫί~σ<π΅ŸUΡ\ΏΦΧ™vΞίU„εiτӍωΣ6I+yΣ¬p•Ι€>՝m0ζ‘\€°ΡyΨs›…νƒ:xΣTΕ’Š˜ΏΦΣΗ­‡ΉΨlb9οœcβBυr°4₯aέΉΐφ'­οπΞ» @ ΡTt:#Z€Ιqg gΰΨΞ\ˆοΕό{υΪy7ΣΝ½›[6lf½oόbμ»;œΫΠ˜#ΜƒοΖ߁εqwχμ·Η‘΅.v'^oΤOlpχ2' υCέx=‘v€?ψΉ?ωγ=kH§2²gΫ+*~FΩfΘg*("p4'drA˜ IZQ σ§ΖΡΥλΌ‚‚ζόo½χή{+i₯9ωϋ’?"πQ?Ν’4ΖόΙ_ΞόU똡5ΉπΕθE#ςƒMƒόΞwΎ“<ςΘ#‰ζ₯lλ΅Χ^›όδOώ€u ΰ7l2ͺαΝwγqxΊ’ƒώρ'Χ\sM’ƒ)LΪgξ‹ηž{ξ1˜_ϊ₯_κͺ"[‹9u‘Χ¨ο55χ_ΠEΆ )ΞA“,!4|·σ%`€QUΚͺω†.IυάωH·9†‘‘7#›φζL=fώΞτcAgln{ςΆn½ν;nv&ϋ‡ιΕό Σλ!Όγtζ[6ŸΈΉΩJžΑαρ9Ύ^nξοπž‡Ψ½ΓF­Ζo¦KΎq§υ:–Ν¨^π„77p†/΅?G2-`‚…ΉιΪ Άϋι¦0ρ[Ίιζ›ο΅ΎŸ£Ž™?sώ>ςGˆχω“Π5#•―u0Ϊβϋήχ>;ρx)wΆΥςWœŒΙ€UICΑψœ_υ_'wήyg‚Ί?ž'cNŒ5¨ύΈ“©@ψOh‚3́]2ZzXπψ7oΨΥ³σ§b«3Ηd§ŒτYIΙζ"­ι>R ρd ΐμB€3 ΔΌΗ‚ΐζR±~¨ϊZ„bx`b8wwΆ‘mΚό’(,l,XΔ~ƒΌ;ώ,lμξοnwƒν懛?ziix7κω;œΩ1s'²τΫ>aό»σΧt@Σφϊ/-Υ/Ήδ’αί~ϋ_ίϊαšC’4ηΟ΅Ύ~³_ΌΪί™Ώό±MΌ’fΜέ.τα_¬ηϋgλ½ο\X―th]‘Q%ίόζ7ρ³†οSΨhtXΕ@jΐV΄4_xƒnά³™¬.Ϋ[°}^H+βœ›σ£¨ "·βUΛΊZxξ˜έzg‹wQ=YΣJΣ‹•=&οŒήίb¦·ΛψέkΚΫ―»έΝ}·&~oόΝ{φΫγŽm‡qx·[£^αΙ2{χλ†'vΛΎ{\ξ{ΩyόΣˎΓ:Lμ΅HΗόŒ•…Q’”‘Ζγκ°ρ&…£χdώ|JΑ˜ΏΆωUaώ—^:όя}μ«ο£?ϊΈ1°Ϊίωι6ςχ…>ςηlΙk™ΕzΎ?Υ2¨Ι€>%EgCΊŸΦ½π0yω0—δLŸoί Ρ{C!@w o‡ρΞν„b;pζ86Yj?œόV,Ž%‹Σ?NκKΊ2Z­r]²i6‰χΦΠό­kΠ`؟ςζ Ϋ?6mw‡q7o—n―—oΛ1L7·,γνγˆίΫίρΏιΣώ…!nςΩΗρlε½[YΕιθ…»Œ»aΣƁۙwƒKΛΖΌ‡˜ω«ό€Υ^¦ξ†(T«Œό/ώΣOόιέΟόΑΗ ©ω³ΥoQΈ»©ύγΡ?Ι΅Gπ=™ΕzΎ?Υ7¨Ω —ν…GηγΒ =Bjgόnγ† ά°©ͺ=—Db‘²Φ7ŒaM:i7Β±πp ―l=‚ΘP?04Δ‡ι[ΎΤΛmΤ*ΙΜροke΄Ί\Ίš~'Σ·έΈνΈ\Ϊ&ζn'v2yΪ½3ϋυ@ωλε»vs‹ύύ½\Φ?ώ¦½Έ‰έέ Ϋέ©kήύ1ζ—†χ)€8\·wΗΥΝΟέϊΑxόίΛξ†ΗέΜ&/ l-9}7!@ο¨σύέγΫ(σ·­~bό&<±PΧ‹ΡΫΘRό?ύgŸώ/η»ίύΉω΅Ύ0_πη§ό9γοΊέ΄©­qp­/π›ύrζί«UtΊο,•μŒkW~ΡΐΝsW4ΜίΎ}¦κ‡ιϋΣǝ‡©ˆα6d†E]ΗDdΆΣŽ §e;π α‚ΘθήπD'‡!ΨΙh!ό¬0Fΰθ]Ά_CHV΄β,™;ρ`R=eg¦³½υΌ“ω70κ7揠Ǚ=ο.τ’7ΦΝ`\ΰέ™'nYΣ» ³έΏ³αγοψΠρwόžΕμ~Ψρ{¨»€Ηέq‹ί³ΈόΫaό»›½“0Ž›ΗημυΡRwsKα ^ytxό›Ό§ο”ƒΟωΓόΓΚiNσoŽH0―Φj¦φΏσ;οΡ΅Ύ·‹q―2ςWY0κ‡ωϋΝ~4$˜οGZsΥ?{ύυ™¬ΉΦΧ™?ιIa€ΛM—XΫ»]ΜN6ΈxΡ‹^€λ*#jZ΄bΜί™ΎkόψK:Μ†²ΒΈˆͺN,°€ZΩ όΠ―ŽΌΣχƒΫ­ώδ† cv"½SyaΡŒN8[_Ψͺ‘!]·Z+'gόύ3θΦN₯ngπr`§i .ΰΟ©obΎκ7gϊέϊυΆ“…ΟΦuΦPάqΈμ»{\|Ηnέήݍψcψυ‡ιηiθε{7<ξζiqΫ}dαΆkδίbώbΒZύσΧj1-ψϋβΎπέωΞwή¦•dΕΊΆΕ$΅ ζϋωϋjύ;γwζΟΌ?ι΅k}yηlζόcζονŽμε¦{ δ@χri1p LΖo΄σ­Ρψz_ ΐΘΚ+―4mkCAVM›PZ`^6€ΐ;³Ϋ½‚βιηα;6±{Φ/†λχΎ^ΨυόzαυtΉόνοn;LlγΧΛΈ6eˆPΘӍ [B€NLύκαo$Kε3ι €Π0ΉτŠκΌs§TΠxι  ˆ…°?ŒώcΝξYγ°YχψΫΚ0-λ^m6vwψn6p<>O<–χ8ŒΓ: 6Ζaβwǁ_όn6ψŽ~†8ϊ™nxά ;~τ±s#iΎ˜6’ `ΜίFώ—ώ—Ώόύίω½ίϋ˜sMBβΌςΓΝ~>οοj\νο£ ζ―l4› ΐψΉΥΟ―υe!6ε”3~-%ψηkϊ” †_©T’η=οyΙ[ής; sΝάpΕ™˜xδΣuπv†OΣή§Q–‹dkιζttfβƒacH+ιbN,&Ύ?!ŽΒΒ.ρπΞΎ!8Ÿgσψΐβ#ήA eJΗυ4Διτ<‘pΛ“ΧŽόΈ_6nχ'ύΰ1Ήv€ό€‡w pψKžbCZˆ ?Κ(XΜΒΒ‚Upa€Ε―ΆT₯*%Λε’™'ο³i€ζjΨ‹l€»θ‡¦86’CŒTFυ:Σ,μ£­ [ή½ώ(c eD;ρΫίΜq€―4 ^_ΰ§|Αεu@½ƒίΫ'ο„e—Ά»ƒΓύhΏψΗυΗGœ„£]ΖνlΘοΐη ‡ph>˜ά¨?C~ϋ™nxά ;~τ±sΜ_eAzWΊΤGsώΊΩ―~Ι‘#Γωk_ϋnφϋcΥη’Κ«¬τΨΘ_ΆόΊςCζω«Μ5γ°Ϊ€-°γ Ζλ­·6©gʞ4fDFφβΏΨ€»γQΰΫ‰αΐA³†Β²€»44t=Ϋγ% /€c: ξ0%N1Dˆρ4bΓό|1#οŽΟq‘'β’ ±ƒBP1ψΛˆ,~tbIx(³ά €ΔNlnΗAήΐαiv<€<jπƒƒ0ΰη!ΏqΊΙϋΉsη,Lι8Φύ|(εHΊˆ“ri#-L T$HΟb'ύ՞ϊ/ͺ_$«Ϊ€:Οΐyb6‘:ž(YY–Š’ź̈m€LΫφ)Κ›ΆAP.”ύ…2ŽMΆžb?ΚΤuΗ7πΨϊš6ʚΊd†8¨+κƒvO]ΰF½GέΕυŽ@{ΑΖx|ΐ‡!>Ξ΄ψ;}ϊ΄εΌι‘mαGzρ'}ŽΓ^ϊόxήΦ#Ύ~¦wÎ}μ,σ~FώΓcv”/‡ό kυ·ίών?V^ͺz`ώ>ςwζDνΧϊRŒhΘx‹ω«-σ§ΝράqΗΝλ―ΏΎ% v ΐ-7½K z—ωΠqœ9£‡¨x#tb‘XΈυŒ&ε T€Ί €½Ώ ^ˆ,  sΖ@όp‡BœHί(Ύ!Z€έ…`ΑρsFN6„α\Ξπΐ°αDΥ¬σγε >β%=^v0jά1Nx!°Nœ-υB=Κ±ΑŸpδt‘olpŽ4Γ@Θ;~ΰ‡¨“―¬q? i$Ν”x‰―RYήr2:RJφ<’œ{δo“κςΌΞΏF E}ή{Чt LdDڞai}TδŸ2£<]ΰ€>(CΚ…r’ΌέxϋwΦ¦igΤ νΙ,8©/ Β uBΫǍ6D|ΨΔMšΐAό΄apaΌΞIu‰ γ'Nϊπ΄ΪΰΩ³g 7pΰ& ΐ¦―Χ»γΦϋaΏΌ’ΪL?C™τ3έπΈvόμ<σgκ+¨ύuoγπ‘C%’ϊθ[ώΕΏΈEεΊ Ό,(=e•του‡ιwχW]σ§MPΧ]w]rΓ 7Ψ»ΧCΏrΚύΧ–@'Υ\λΡ»Π‘ι„nC xθT!άύ{S… ,ΤΥΡ‘{Ω Ψ‡ωi‚π?„N€qζΒSΞ‰‘ηŠ?D’0ΰε’Lj ς‡ͺΒρΓΟq@ιψχ~|€—x!βM/Cˆ78‰¦NšΦ3ψ§ηΧaύ›Έ™yΩΈ±‘v/;›΅Α!Βο „²ηΆ Ί—Œ “K.;š,Ν<‘”O> ζ―rέ₯Μߚ‘ςΜ.cbκ{Ζ•έ'&KYzύΠi7ΈQFΨ”1νzνeΌ\ρη<.ΒδΑ“7mΡڠǍ?νxά€ι€Y0‚' ^w΄cΪυ…žϊD+χΪ '{ΑN.β# ΈΡ†hΐabΫΟ_?Σ »aǏ>vdδΟ…?”'Y2ζ?2Z¨/Χ‡,έχ½ο=ώΟΧίΌYe>―:¨(OΨYζο#u™?νώΚb?έΙ€© υ››—@[<ίxΨ‹.Μ;™χFηnSB»…Œͺ*4PXV§§VϊΠβv‚5Μbq„ΐAΜ€% 7ˆ nΐΰο‘oˆ-Dœw‡oˆ~ξŽ Μ ΔΚυNˆ-aιΔN΄Iίΰ…(coΖPāqf„γ'/0βΗl¦'ε>91žΎδ²dU“}UšΞ©"w)m’<υsΠή)M+MŽ%Λu••ά©+Ο;εηeˆ[\–½Κ΄›» .Π:γ¦Ύ¨+ά4σ8pwΐγΖΖέ=oGΰ£ΠVy€Csσw!ŽΎ@DΓΓ{ λνΌ„%΄Ϊ2ί^–@ύtΛg77‡w{ώΤ »aǏ>IIέ·k΅?[όΈΨGhΣ‘HAuΤΨΰ@遇|κ7ής–[ζΛσ\绨<Αό9εΟϊq΅?Œ?Λό‘€M•9#«Kκζ―#ٍ:Ίΰξyφ²ΛνΑK Χ ^V;IS†Οqœ‚ΉUkήλG1ƒA€ Š= t,5DΣ 6X!^:~NΌp# ίNΰpΓΰξOpi:‘i»τ#Οθ ‚ vβΞ;Οvʁ'kœPnN΄½\²°ƒ}K S<Ϊκ”œϊΑ_%υκ\24<ͺui¦ε=žσ Škλ “šώJŽ)'Ϊ ΄`Τ#m)nλeό²e›ΧuO[Γ8Ύ½i'܈ΫsLpΓ/6ΔινΌ„Ž>Δ4xyψ¦]gβ|œž6pλ}0ύΦx~βteί‰³Ÿι†Ηέ°γξl$%uίVζ―ΥώΰΦyZνσoˆωο/=ςθ£Ηύ7~γfiΟ‡†–€EšSωωΘ Ž'»ΪŸŒσJΑ;σ_s­―·ΑiKΈεf°θμ!ƒ…Ι‘v’΄e†…€ΦQΐ1B†€Α@adΨ¨$!Rh19Qއpnψ–ΞΔ»VΒΔpNL»;žΝΨQJt# `Cόx']±Π²™8Czύqž?Ο‹»7˜žFq¬huόόB59ϋ£―%υΩ'ΕόΉξWŒJ ζ’θz"?<ΤτwιΑ©δGOiη–Ι©‘\aΦ^_žR/Οl™ρMύΖ ΤΓ`wƒύγpΐςΔu› ‡ΝϊQ΄/Φ ΐόΑπL_pζC qηΈάwoO|Ηο|cbψΰ²φwΧ1Άϊ5Wُ/΅}eίώ}₯Η{μΔ›ήτζœ:}ϊ€θJMε σχ‘ΌθΥ›?ΜΙt0ΚKmk σ§ΝQΎψw+η΅₯š»τ*\θU2Ο”;όή²G#žy΅ήΫ<Ίg* 0%jLTώŒDP“ΑT™K…ΡA€AεΞάe›ˆ"AΔ BΔΑCΊθΘ]^Hi;v·8q[Ρ£έόβψURNΐ9Nlάy8­ΌγΟCΉfqβΖ‰~Yw«,‘φϋΧ4J>χδw“ϊΉ%-ϊ³3μ¬u‡8‘ηυ»ς¨Ώ«/ί—άσΓi«Ÿ‘‘°₯ŽΊ’½ ½όz•e―lR'ή©Β{}†oTlΰπ㝧ŸΙΒ„oέΜ¨φ†@›σ5ή?ΐO?ς4xΎβΈΐ<ύ a›ΆŒΒv3\6/ΰu7μψΡ‡‘³υΎ]#U©ύ½?σgΞΏaΜΏψ¨˜―½ιM8~βψqΥ̟σύω³φ‡ρ»ΪΏ+σWyζΜ_…΄“&θΩv2†w€†5ΊΰJ`ΆΊΰv 0΅ωω9SUιaςŒΔPAξΩ3eLˆSM’ ρδ»X #™9„p`ˆ²[΄±›ΓZΰEδβpψga6ΆIZ‰ΐΒ\*ί.αC\I/ΈbβΘ7ΒNmΉf~­Έ<²έ 8=qΈΑΟU½##aΔG\<ΐΕqρ©6=xjSO*CΑ•tΔayΟΈ@IDATιΜΣIνΤwν¦?m€n1ŽL ]χ AŽaγ₯‡΄Ϊ~bΤή½ύPgK:σ ‘sή­Μ©{F…‘ …;εΧA·‚pAΠ™=p„G(¨ͺRGΐaB«³Χu,]ΐό›zmH¨˜Σf‹ΑOΪIώλΔί΄{Ϊ0a\{Ζ{lbψΨ=ϋ·Ή¬ŸwΓεnΨρ£eώJ”τσΝ1όUχ+ϋχο+>φΈ˜ίψγ2κ·Λͺοxδ―φ‡ρχeώ΄-ζό9ߟϊwΊ@>)ϋάl½r ΐΦΛΠ0xGά:Ϊ0ƒί30u*¦«9ΣgΰΠΠΈZ]0σ§S@ˆj΅esƒωθί΅h ŠΊ ž΅ε…Š ŠΩ£ž8?Ό»οϊΧFΚ.#φ$WξŒ|™†ΐ0‚―g5‘Nή}τOBΙ€ξδΫάb8ϊ­§}ΨΎυ.ΖΚ [υ gϋΣΧΣ9I„κ―ω7Δόχ5ηβΖ_{γΝ'Nœθ6ςΥώ1σ‡ΒρP ~Βtΐφαώ•œωwΦωvεΐ6•(ŒeSώ!ά―…w₯p Ω Yp3‡ΐj•mRΥ(Œ‘wΤ=J&˜D”‘>D FgT £3‘ΐ΄α@ΥΈ”Mήΐƒ Έά‚!"ˆš3άυΚ…42cρ£pΊ™šš LYΔΖ=$?ˆ4m2΅―…F©9+ ώΝ*|πC€η%@TΩ©*V.οΫΛNάήΘ’Η‘d―˜ΣΉιsΙΉ³ΣΙΒθˆΕA>(βb ω~TΜͺ\žΣ6Κ™dι©―'Λ‹³:νoχ/ϊσrwΚΜ5@RυΪΗˍ%?όρt2’νͺb‘Ϊ0eeLΉPφ0l? ΤλΖΚ|zIεΆGπβ*οπm†οQ•ωA­Θ‡!πΡ& ŸκjY£τΓ‡΅bL[U‡Γ:ΐκCψ-~αν\ή.‰Γ‚FFωjΉΦFhτΉΉωδδΙ“ζFZf&'&Ό@x±τ©~Α‰α6Δ!ˆ¦Φh'L'o x1»ωλ,iΊ:™Ώϊ«ύWˆωθ‘GŽίψ†7άrβδIωwSϋϋ‚?ωΓψQΛ9σ—όaνΐ Ž>όΎχ½Ο.ϊ‘=QώήN)Χf°Θ€ΑΚ©'βσΤ)ν§_\6F4hηo!…p.ΊH½¬ΑΝ€}釀|ͺ₯šL@ŽΉ­4tHJEjk:Žΰ ˜Ί‚[LΏbί0GSΑiτ½4k ˜%iζ—ty͜Άζ*„‡ͺˆ & ΅i1αTΨQ|ΛZό¦-ΏI₯½Π3¨ΪW“9MM¬¨ΣΞkgƒŽ Hzό"ˆ,+ΞjCŒYι]:qΞ―ƒγΏ΄΄"‘‚΄‡‚Jbτ0vEŸjJσΚ΄εsI£8U΅~Φ‚Ÿ=;£‘θ’tX₯ŽfΔκKιg©qMRYžQ6C~Z΄WYR™J˜Z]Y°2Q<Œv+Μ,$s‹a* ² ΅‹‚=ύΝdΈϊ”M45:’Ό/$CnhŠ0Ο†ΪΡσ9”|υž'“9-xUΦ4eUθN„BYοΪΝ*-ΔΊ‘²Z)œK–aKήBYZ!!kΒΊ`θ70ΫΆΘ«=¨-,.’š„$p0nΆœ™žΩŠ΅³j5lg}Z}Ο…ΖΥ¦ΪJEš₯λψιpΠψ‰%ΑJΰwV` ―dΚ€Ά’> Όh)‚Π8¬τ¨?Τ’ϊ wκWδ₯&άΥΖ9λC€0¦υ¦N Υ^hΐ fW0MgQG+ιΘ_ωΥ1Όγ6η―ιFgώ7‹ωŸPψœΏ/ψs΅?+ώ³#́ †οΧϊ’I’MεΜΠV΅1Έ\ΨXyu…†˜•Egζ΄Ÿͺ8Σ†Ψ€€G΄ΰxhUF€J‹LˆeŸV(p˜Σo2jQΧZ^€gˆ‘7 κL„o1\ΕW F§zΌ #¬_ΫΖ…šZ#0aχ1&¬ZC8y_\δψUΕ1΄(‚ͺÊVυ4Š“<,-k_υr'~Β@Ό›Zt6€φμ‹<Ά’'!€!ϊ"τ:Ύ‰Ά,‡Φ ”Ζ&’QF‹Ί–©α‡Ό/H¨hpZHΌΕ˜΄‚Ώ`Gή2ΚU\J—τ“IC §*Bύ₯fΠtEύq1'»{ϋI³½Eέ3珰yΥe{’ŸΌϊPςΓ'η€ΧρΡΛZˆΊ€64$Z―»VΥΖ&'u°SI„\SYτ‹%5Ț¦K0#Tžκ«¨”w¨΅všbβR§$ΓcςΧš-ϊΨ’Λͺ"¦$+θuH*{ψKh_‘Oθ”ΏEά1aτΘνΥΓπŽRZGΗI‹ …ΝFUy%mE΅›Ί±xϋnh±gΝΪ—£ςGΨE@O©ΐbT ΧΟxŸ‹αά ;~HΌe'u§š[ §8q·pΌϋ·lόΜMΤώ+0υ#λΛ$BώŒόϋΤ>>όπρήπ†›₯=qζΟ~˜? ώθΘTΐΐ#,σG“θS|ΤnΆΏr`‹eJΓ€Σ\sΕ‘δθ₯œIΏ9„CΪ0tN£“Γ:P„KDtl`j½ΊΞ~8—ˆ8Πzp=βμ㌺pqQσ©B=nsξ©:Ώ•^ZοB%g½²3ςfW%’½ΐΦK £ˆΣS΅‰a_vιe¦Ž†‘`ΐ΅.A‘ ‰ ‰’YΓZσ/θό‚S'gŽέ/ζΟθ$hZ ωώ£ϋ§?sErznEκ i‘4o―iζξ§΄ψt―¦₯φμ Q‘²Ÿ*M—1m²WS.A5O;’nGsP9SΦ±YοΫ] l‘R!0„‘ Θ g2wΉ…γ m+|#@Θ40ω²ΞCorγa1cΨ=γΜR+ΰ ߁}:Qπ@Έ h½φeΈCrzώzΪbwÎ"'…fλ}ϋ˜?#Κ#Δ7*m˜΄„ύ”^ΛόQϋχbώHΩ< hδŸ3•Τ3`r` …μŒZΨ$;&f£&PQ fB’ψ1Μt »~ψAc‚4 »~ŒƒψB@χθΔ8‡΅¬Ηm$*E!7w6ˆaβΨά?vσχ8 pα›Lmq\#‘dߞ ει 0ζŽi˜ F·¨6!|Έ!γƒ"€f Ύζ@1ΚQLj85‘~ε~Žπ|³I_;»!½ϊv'KΎηΑΙƒ»ρήαžzΔώYΎ0Υ»ΠHΨ*ΒτQέˆ†4Ί{κ{ŸΥβ΄SZά8‘vPW½ΓΚβLτΔ²λ=hΪEi–Δπ―<2™ΌπΉu0«ύGΕψιlcdFΘμΦ ―؍”IΆΚ*0k ¬¨χ"μ(IΈB‚ “ψ΅šAΰ»Έι=,&Τ ξbΜτG½Ϊ°SVjΔtτΧ‡ΎpƒyΊp089ϋ vswϊ•/mq₯ΨΝ?zχΧΓv‡6pYγnŽΓνfώ₯…Τ8σ?$ζΐC{έ ―ΏY—$ω Ω‘–ωwSϋ+ ζθ˜ίœωgkϋ™Ξ€>eΑ@πΓ£QΫΦττΣOΫ bΜub v1Α0βd>}~XaMΞjαΡ^1”)½² ΪχΞ«Μ·}fά,MέάπpθώPα-˜ ‰€uF±qT0 }bτ₯‘©δδΓw'³ΗLJ£΄Δ’Η‹‡ω{ΩQE%1Ύ%-ώ{ασ&ΣσυδιsΛΙa©χ—΅Π$-š6@)Υ ‰2¦)™„ͺ&ƒ ΝβMϊ Μ-6ρ'>ώrpθŽQΉχηΫΓΖxΦs …c ΆΓ[Dͺt›†BοξΗιρϊ‘[η—‡]έ ;~τςžΊoηΘί5.hkΖuΉΗϋκ”Δβ>xμu―{έΝ:ήχT΄Ϊ?>α―σgΓcΕΣΗ`ηΜ?ιgο=ϊ”=βs§Ρκ¨ΛδŽ;ξHόqΫώsΙ%—$Ο}ξsνΔͺ«―ΎΊ₯ p΄Nϊ±²ζˆ k«Ά‹ϊ_›Β9²‹ΝVΩ·Μ…ž_Rζ―•ΠEύώQrκGί°€œρ`p1WΝ&ω?ώάαδ³ί>“,jΥ|iDϋυ΄ΰΟ¦τ>"a`8žaψΝ雝©ϊ]lΦϋΞϊyΈnξέάHOΦ¬#=©#,TˆΞ$κ[}‡ο5qEnψΕψ-ΪΤ}{™;C0ό>rΈtύχ?ύΪΧΏώ]Ÿ σ_-̎ό³sώŒόsζOεžη&ϊT£H!aEϋέwߝΌσ_ύ+ώrΞΞίη ~ξ”ηD=ξΏξΊλ’Ÿύٟ5GΈΈcΣ΅ š] Œψχ‹© ¬ άΓ…οΦgDPύ‰ΰ •tΘΟ\ςτ?ό•*0₯φ¬Θ ΏΘ!ΝSΝ[+ΔuY‹Άκύ?s ωςwg5¦ω1}4a-@Έ)Α™o΄g<Ξp]°rM΅gΈaZ~φΥωχ«NŸφW Ώ;Δzn~γ§w?· _Ϊ6$/1x€ξ†?;Γό™’‘FΖςIN ZΠΛ‰8£χN±B}yμψρδ=οy!{ΥUWιD²Γ‰Ř}ωε—ΑϊΦ·ΎeG˜f™Ώη―“”Έk° uωV5Y;ιΜΏD₯TVρ³e’qΤόΗξ+;ιoH{ΣΓθ/ο6π ¦jΪ›₯NόoΡ”ΞUΠ)šηΐ₯eΏΐ9vHŽi4=€6@οΆ.@ύŠΎe NvΦxΛΊgΏc8,²0λ}w ΣΒIs~N“‹ΗΩ όL+lΖέ°γ‡φnΨSχνωG̟u’oΗ'σ—f³tΟ=χ<ώšΧΌζ¦ιιιΣbώΥ.#Τώ9σκo·½ζ”¬OA΄8쳟ύlς”ζό=j„‹*ό¨SF8ŒZžxβ ΓHηυΡL6Šdζ―“ε h :9ρΙ"ΘΏ;K@e ΄§ΣgS_6ϊ#+ŽŒ%'₯φŸ;υ#½sΓ_ϊχ₯iš`‹W“\=™\ud8™―Τ¬œͺ:ΖΧ…ΏζΟCŸ’ΐ|[B€ΎαοΫab<ρ»΅•(ŽΏLΔζ§ GΰαaHiλΙepω§‡υolwÎ"ΆHέ·ω§˜Ϊ‘θufƒŽχm4.½τίύέί=ϊšΧΎφ³ssη4 qζΏ¨tω!?ωœ\y»τ=ŸθSq0F,iξŸΕ~KΙƒϊŸΓOXiΞΓ;°<½΄“7i–83c6&<žp ”ΫύK K€7¨’E…Λjφ’N ,Ÿy,9υΘ7₯Ε@.φyn…Oq3Š`=ΐ?‘ΰoΎΏ,ΪώΓv–?ηυ³[Υ?στ ·ι[.$»MΞ=Ύψ»Χ{<’aΦΰH™h‹©:@j[XΪLͺ•p\Ψρ;ΰ)[Μ9 ΟAI±!Lœ7όOΞύ<.ƒ#ήΰaαΆ•ω«ΞH­π7'&' Λ:κQΪΜWΏϊΥ‡uΒί%ΈΝ+ν‹’gάκσηtΏ^'όεsώΤΣ.3Ή`€ £#2ЁΑΓψbζΟ…"Έσ„3κηάvΈΰΪϊWΠi€‰Ξ’7‰·NZ2@Js5% ΊƒΨ·ž5ΑjC§F±ΛΙ‰‡ΎΒe@ςΟΞ`=d][ζφŒ%Ο½rDηαλό| Νe>άΕ@ίቧΠΈ°3o0γλŒbσ_qέλέ™ͺΕ“bΝΖΗξ„5¦››!IΫ–ήΑΣΊ'c ‚ΰ+ ρα?ϊΨζΟΪίy!ι€)ZVΠjϊεW^Yϊ—Ύτ όέ¬ΊαδΙ‚κΖ™?W|:σΟΥώ‘:wύo.τ©B:$„\{ν΅vsͺ˜>#ltAΖ†/’ϋ7΅£¬)υΞσϋTΘV½UŸ֎'ΕΙHƒ}Š:²φΜγχ&•sΗ€ Π6Ϊ ΰΗΦn5ϊ 1<ΕΙz€e΅ίk/MŒλ6?Ο_―Χt“£˜Ώ.’BΰV½μš˜Ώ?Ξόβ2Β­―qΩΎ-Ϙg:ŠοŸΒ]u@“Hγr; θ©pifΝ ‚½ŒΓΖώξ†?–~SχνωσNΞ0`I«ξm(¨NκW\qΕπ>ωΌώΖoQ}ΐψyL tΑό}ΎζΟB?ύε ώT»Ωτn­»9WۘvSί©ΓΌπ…/4†“w•Ώ«]ΐ΅ \gκaJ”_8€-REιπρΰζTg D9Π¦K@υkzP¦n΄Πo©|69ϋΔ½v‘ Aϊ dΥ†™Ս}¬XΤE΅E'€SC΄~εϊ뭐M}τQ›λgΎƏΰŠ+―LH`TC'λ0N²ξͺTΦ‹Z—Q’{ιοM›”˜΄³^:6Iχ€”[+ήξ [rέ^όAυ?TθΏr6™Ρ-Ε’nωkώ·”Τ‹"0\ήWמςS₯dοΈΆ,/%#ΓΊζY‚[iy˜Nσσl1 Ii+΄υ!Ϊ¨ bzΥ±1Hƒά'}m1xΒΉ‰ίaΊVO“Β.k!3~ξο±aw²q΅Β₯q΄ββΰΤ}³Μa‰γ—Ή·`EmΨΤώBK+}bώέΥΠxŽ˜ψψΗούΝίόΝΫ†GtsC½ξ̟‘¬φοw₯―ΐs柭ηέπ }j‰IΗQϋ6ϋ₯/}i’ϋ―“ΉΉ9scτΏO;Φ5Β!$ D½+‹,i+`α υŒ}eB΅ό{½0ͺbτEΪG”6JΓ7ξ;el«—Ά{‰¨±ίΦx”Κ™3η)s˜ΘV eAy‹γΙάΙ‡mτ_ŒΆύm5†‹'ςνί~λ[?¬mΜ+κS³©(OφgŸ'gώ*„ Υδ@Ÿš…(Ρ‘μι¬εωωδ°ζω/9rΔBβΗK"<1Αι‰Vπf .,œFυ²ͺ8RgΌbγD©‡w jοh"΄‡Χδˆ”ˆγœΡβΒ΅†2Bέ[.—M0šΤ”qn—‘Ό™’©ˆs‹2·jH³™¬jε:[lΞ_naLΊUμ_xΪπ„Ά³r"  ΕCEM…m€#bόΆ-€„Ϊaƒφ(¦E;ρ~f+ρυMέτl?Τ[j€ƒρqJ'οLΗ )Ž–IaΫ!Z>ν‡Im˜2O+ ŸšβXPϋ;‘ƒΑΘ‡ΞΙ7Ϋڐ0‘~ -ήέΜ!ϊΖ=~Zq€ξ›eώ6•’2Xι2ς/5ς/Τ$½=ϊœα[o»ν›Ώσ»Ώϋο%D―Hhb₯?ϋϋ³#Ÿλχ(Or΅ΏWθ`ο Έ Ζ³ΰί;3‡ώ0ΚΰΫؚˆ Ιίa<μΊΆΒ+`ΊΑ.u±^Bΐ€' …SWΓ'¨\-­€Q·Χ"₯H6ι„°;1ά$šΑŒI€Œ£'c貇£ΚΕVώG’jωtR?₯[tΝ/s0qύτž;―-ΪηΈξX«,΅2žQ?S#j“0N;X6—5ds_€ίΆiυͺφkν‡ϊ‘―€¦γέeγDψΔπÚ£~S7?‡ΙΪΐΞβ@ TYΗΣΗθS¬r:Ϋζ C~<>ΓΎτΡKHSϊ½ΜΏ‘4’6 ƒ1dL«ύΕϋλΟΡ‚Ώ[nΉεξίΗ;>*ζΏ*ΑΉώ¦ξWš°YπΗ¨ΏσWR-oωΕ>*¬έjr OΝe™-£Œ¬ΪΉΥ™ϋΰZγ­d½Ÿ›Υε zŒτaρNΔnž^6ΌΑ“^Αy<ŽΓνV~N°nΐΗΊ Nat’‹Ÿ₯ ;τ΄ΆβOΣάrΞρ„–Ζςb²²\΅S8ψ§εŸβΜ­~%@=QŒδ bξαθ_DεšΪm ̟ι)l4UhΠVΤVl+ΖeX|$-»[;ρ6βΆ§ΜΏ±CJBΫ°v›kΤΉκίαiΣYγ8po·@αKCaζ₯ι’ξ΅«§£E€ήΆ"€†Oaά&Ξ8][eώAνΰΓ μiŠBε=¦ιΡ-Ϋκχώ»χ7ΗΏω71eώΩ‘Ώ«όβ­~Ω‘Ώ1 rMκπ»ξjΎμe/³©΄rΤeV²Dε?ηU δΐ«ƒNΥ" Ϋ<…dBd¦€ͺSœ££1"a΄!ea55ˆ–/PŒ' aQ՚pCx `€ΗfΔ†0,0bΚΓΰυΝ\< +Q\Cς§Ό€]b%Έpπp0ͺE”£J+0ά²jœ<‘?FŽ,Ά$O¦½ y&m¦uQ}˚Ύ™Ÿ%mΰ" ‚„ˆ΄³ΝσNγπ#ε`%#?73c£K΄~ˆcdtΔΆ\Nhδ/κo·/.V΄ΰΠA#δΜΙ²ζ|€™Ό1Tψ)…A œ VψαΓ‡”Ώ ‘Π >ΉΩl ΓU9Β€˜VY(/$£jΣ°€z}Μʟ:pAζ„ †k:œ‘Σ6©K­΄5ƚ›)΅CπSwάΎ©ΫιLpufO»C¨€!#Tbh§œ3Z@{DΦ>5΅u ‹΄=mγ₯͚ΰŠ;ΜΨBΆpΓ?Έ>KΌ¬oU{›~„J‚q5Ό…wϊ€Δ°¦ίΫΕόY LAjωα‚“βjp±ΟΏ|Η;>sΛ?x'e.ζ?£τ£κ―(Mρ6?WϋΣQxΦ@JrWUΖΚ*λnš,‚dΔΣM75Ή~Ηȟ†1Ψh^y#­δƒo`ν“Ά1Ω*Β°( !A`o*ΐhˆwvn^a&”•΅όQ‚s³α ž[FΕ©ͺ“&§šT΅ `llάFθΤΒυE»Ϋ£:A¨+ͺ­0B‡‰ΨΐσπˆJλώŒ˜=m„°΄ΰF›€πNΪ€χΪνC˜W=ΪΪ)&ΪxaΨήքȁΟMόn9όΨ/ΈΠX»EΐP›5Α% LX…Ω† 7όSΏΝ2ϊΉoυƒρϋyκ3ΜΙ(υυ†„œoΦo}ς#ύθηΥ†Τ§ΟΑό•€ψ€˜?L ζΟȟ<ρ6}67»§rΰΩ«΄Ώ°π―0&ŽούGΙdο ζη£ZFτ>ϊ&;0@FJC#0Q½Γ2κb!£5˜9L—Q8ώŒdΓΔέxΈqR=Ax1cJ̜έvΒ:ω$+„Ýτ@,ν#„Œλα&/ψπΐ˜V@yG cΩ ¦Dyθ8ŒΫΌ“Fu0|άyZHΗ~1˜  FBΩp0M˜:έΐ.fQnΆ\Uhoφ`ήUB4­8š§}jK03κ ZGgΤ!́–vΗH~D‡q± uΓ‡σ1ΑPπ0'ΰΑΠhƒlηm·[!08πΠvΌ₯¬ΫΪ΄%W}JΈ7xέήΣb6ίx¦ξ[aώτΪ1εΌ6UΎ΅¦Κ{E4‘ψζ7Ώωϋδ§?ύε”ωO+ΝKJ‹/φλ¦φGθ;ς‡ωCCΘoΞό©Τέirΰ<©· Δ+A09Ί΄Y·vb!vŒΠq@ΐθˆ.}γ…hΆζ8ΫAν βœQ„Ιϊ<<8 Ψ„G-λwˆ-Β Τγ2/KϊœPzlgD^ζLz}δεΔ—τ“nLD”ω†Y“@m ‘qγΥӁό-7αÝό1'Ό6‘©f©M¨noΎhΆ4cΚΑŠ*BνΆ¨φƒa„Οz κœφHύ―ͺ>L`Τ;υ8J+ ‚"m•6‰p€€n p„e$O{2#&‹@I1‘S0hB» ι’ΠI7ή =ΞΫ—»a›vψ°oϊšŒŠƒPιmŒ4‘WΒ΄ΰ£p[eώ”•όaώjη•ISύwU}aθ΅―}ννŸΒώ6eώg•&˜ΏmχSR`ώ.ΈΚΙ|]΅Ώ3§δ‘όζfχ•@»ΥοΎ΄_8)†@r δnΫHΌjDYT'3£ŽF‡³Q³ˆΠˆlԝ By'€χhο¦0Tπΐ0ω{l„qZx“Bδ#Xˆ#%˜~ΛΦΧ“M6ρΑ˜!ΌςPί’%Gπ c& sͺϊ……Š1όΠ8πΈ0€ ‘L|όC8ChΉ Νθ3K \Ϋλ©^‹·…+Y·β’£4i\ŒΓ₯3΄3ξ €!S“όYπ‰¦iUu#ζœ όiΣ%h; ΤΖm€+wΪ-ν%=a΄eFδΔGπΠN­ /ύΕΫΎμ•G  -̉CX ωρ>Γ·»σž5Δλ+ښ,„Οϋ ž-3ΫηŸ2₯_imͺԏ›κ3MΚζϊλ―Πί|ε+—aώ>ςg± s¨όaϊ~?Yfτι:ηŸ3P8Κo»΅^(9ڍω€Ϊθ €δ2©39XΔ2Œώ»d&%PFδRββ„- »&·6A‹aDϊkLΦCuψteΐΣ4zˆ2 Ή˜°ΥΨ•U57OάlŸBmΦa\Έ0΅šwYjU;jVTΐΒGG€½?ΘEGNoAχBικ/χι]V„*O˜wΰ’ι1ϊ·yλΘ¦ώa’η!4PΧ0xθ`γZC0΅'¨ν©·^m6[}Δ‡8L`πΎ#7φΖӞΖFΗΦ Ž€G¦£DίΦ ‚ξ΄fhՎݴ4bΔ«‡0ΫΙόΣ5+Mi=$ΟΪΏΔ±rέuΧύρΧΏρΏσ/Hβ#˜vΑ_7ζOΦΩή§βλ\π—3―Ω ΗΞ€σ₯.‘—Kκ{Ί bΈžΑ—18“Q‘^< „‚Λ¨gΝ¨X@τpι ΝφπΊ4„WΨUν…Wjν†l[m­–₯A`a±š›‘ΧbuQ»ζ΅@kΦ4 f@: Μϋ”~TΑ¨|YΰΗb>F†Œ΄Άjβ%!‡V*[E‡OKΐšpڎвω©NaΚ½’ύmI6Z".ΪbΚ¦mώ‚‘½ΐΐΑAϋπ𦑒?ξΦΞ€ΦΫ2mŸp¨θλδΞ–ΰ ͺζŒ|N*DCα}-Γ»σŠP.γq9ω‘m“VΪ6Έ 7€- ·½ΜίβlŽkΔ04΄ͺΈ ’Τ{Υ«nωϋ{ξω.³”ωΧ”gώ.Δ—ϊψ|?Ά%Uε—3―ΰ ܎tΉxNΟΗμΑ‰θr"BCΣbΆ: 9’*As©.iw5(―¦ρNtD‡μ=ΟΜΊ»£p΄Ζ΅(,8 SξEΟJλ͘€§M0Ylxξ܌ΕCΊΡψjo°ΝωJH@<3;c «ΐ'&'΄eρ `ΰ,?"ͺ-bΎ™φ³8{DuA:[Σώ”;Κ’ωi[gΑφ4‘„Uά¨KιӁ§bΓD‹²aδL όΡq·ͺ‚c'G«m§pW«š:|hy:][#λΌέ‚E±€-°fΥΦ*šnr΄}˜ΊγΈ’–©*7–WΉaZοϊζ½υ(„ϋζ=ϋŸάLΰ‰ΤώL_ιiŽλt?ŠΈ-”Λ σ+^ρ‡σgΑ̟9σδ̟ΚΘMG δ€Žβ샋X©χΪΐέÐB†‡Q?w”E|φIΨ£εβYˆJ/"ΐά:*υY’Cκ"8―=ΨԁqB£4“Φΐˆ'ΒθZΫ€φ­ξ³Ρ£p²€ΠΤΆBh8„—pώxjμΫόΪώΘ/ d°ϊ1ΒV.‡}Ψϋ΅έyi ξžς‘c΄ΟΞ„½ΪŸ?€[ΠP Θ¨°;Fj!ν8=]ؘψ;~_λ`™£&¨jΑŒΫιgn \‘O0@FŽ-₯ŒŸvIϋ³…™ͺΧa΅Ϋ’Ξ¬˜“FΘμ©-Œ Ψ(}zzZυΏ¬-œαŒ‰Ι©=ΙΌΚ3g§m}[ Ε%mΚ!“Ά:g<+ώiSΰAΛDΌΔP; m6Oz'&&Mxhχ΄(oKψ9Γ&«΄yΆ©ΆŒόM;€Ÿή) kv–ΩΗίJK ΏήMHγFνΟΪ ΗΕΏrπΠ‘’v3ΜHνσ>ψ°΄dςsNΒΣ’ό}ΞίϋeGώ>ϊ§ΣΈΪŸΫmA#ϋόs΅«F/Θ—\ΨD΅221ζŸ†₯CΗίFIχ»T'β‰λΣΑ›šŸΤ½¨λ €•# ΒA35©PΑΔ9νŒ•ό£"€ΐ’Fi1’‚’j‡ˆ±z<ΈαQxˆL‘°¨haΪ¨ΰYηΌFΜεg#·χ°οa!n¨v—u.<‡χ,7DόεQc$855iω mleŽνarβq8{ωIKIΪt’x‹Γ¨Ž΄—§-NΈYθˆ7ςN9ρmαR`¨’\ $6n¬μ`μ0Ρ/`ΰ‰Ž›§.Ρ*Α ™BD½Π¦H0d”O;Fΰ£>ΩβF&!J›*κ3κŒόQϋΗΫόrζo5“dK ²%ηΫT„Ή0κe{RX‰ 1;žΜ•«& @7b†5K71SH*‡tθΞ+) œG³)©£ ½ωE‘E\ΧwCDΣ8‘¨ξ²4r‡θ`–: HΒ#.β`κ`¨hΗ†\MΔΉ<_A”qLϋ‚Βy¨ζ—ΕP+KΠ—Ά hε'Ζ](°Χ?}W Žμ4 ¦)’YΠ:Ϋ½­xWuOό"‚‚‹–1wi-Fhš q–n&QΠƒQρΚD|kϊΥ:}55 \ΡwΈΘ wκiΉb‚sκ§/όΈ΄2C“Wό1\$έP °¦)-Ϊ—sοz€‘‚-"°UTή…’41ͺί Μ‘—†uφƒΰl»©Β)΄Α…k!ΦΎ$Y ι,€uUL½.αBG©h6m±½.¦_ή1β’ρΨHZ§LκŽ‚E=„ηx`꽩6Y©fΓz2—λΨ\ΌΒΓζΨn„εΑaΆ\ΦJ―… Œ;h7Λό‰‹ι ς&ΖޜΤB?1ωΖΡ£GKίϊΦ·~όκ_ώεœ9sζ΄hQMΪ4.φ©*½ρ|?‚NCΓBΫζ‡mΩnem5Wϋ«@.F“ }j^ωΑ$<ϊ¨νiΏβŠ+’kβ'’Ÿ8zTΔA½*pΏ8Hw1ΒŒΞ§ΣHϋ¨Τπ“rΨ€@€S‘Φ7&•ΕΉχܝ>mBjРԞς‡p‘a?φδˆVOŒ„γ„cδ}㊁;ή=₯²_79‘#ž΅Νn\mkXŒ›ƒ€ΥοΡ\>κz¦‡˜Κbξ_χΥKϋΔ™šj’v•χ¦ΓP΅Η&4 1ckυςQ]1BΗXKλΞϋ’―ΰoΘ |ƒΑ>i‚‚pJ€AceŒFή™2@(π…²•=£Ι‘ƒϋ ύΘvθ daB)ε=ώξ2ςΗζΟΪ˜΄Κ§ &_Ώκͺ«†Ώς•―<ςΛΧ_³4t3šX’vζο‡όΔ#$˜?%dN˜yG°P<9σWa\¬&ϊΤ|Μ1Ι‡>”|κSŸ2Ζ‰0»ςΚ+“—Όδ%Ιτ’ins*0>x[ήtE£o&Œ‰XR•ˆπν΄A­8\\Υ6x@Σρ³2B³Ÿš5¬œΤg«©1$ »“a†ΡZSG0’φ<Έ=HΎs˜v Pn4]F—ΜΛσnŒƚ>Ζ ΥΦX³eΤΝ{COΙή% ―hΪ@}OΛE# bϊΰ>ŒΫφ.|˜Ά`Μ/…Wƒ €Ϊw¦•>}σnZΩ&K`6ΫξξάSΑΪ°ΥβVΦ̏γ1ά„εIέ™vΰέάτNπήωλd?Fώ2Τ₯eώΔ'?ω―}έλnMͺ 7ωΝϋ»βGώφΟGώVΣωO―Θ€%C‡Εΐ9ƒό«_ϋšό―½φڰȎ…vιƒJ“ΥΖǏOžψρΙsκ±€:žΡ΄α>š{η(`nάΠ@›Ζ΅ρΕoΞΝ.ύ.hΎ³€Ό1χΚ(†ΉY ρεέ8’‡sœŽΟΏεί!HλCοΉy°σΓ&ΑΚ³η7MΙυ€Ÿιά-©P©©ο © £ΚgŠ=•Bδ§εΓ;E―7kgζ"Ώ΄ά=ϋMΘu›RΪΰίaˆ3υ3χθΫβcθ2€#…i₯!έ€Z^{π ~0ν‰I¦;›7υν@‹ΩΛmpζ―iR±)Ί‚ΪΏσθΗ>φ_ίπkΏφ'Z‰<° Ί‚ΐ%„ΥώŒό(qTώkΤώiz,l‘oΎΥO₯t›\θSω0p:ό7ΎώuΫf†&€ΥΙl‘£1‡‰ΐˆ›mLŒd Ra±Ox‹βhνœ…aK“Q’u©6`²Έβo0cψa"Ι”PX λQvs‹όbo£‘ξwžΪ€7€ΩHΏ₯²ύvž&ϊ|LVZρX¦Ύ780J’Ϋ†Υ( ΤνL^€³~Ή§¨[ΜΏ…+†I™²ΓF^­p'o£|Ύέ- μώLΨv–ω}ή[ίZΐΪ˜+°ά3Œ €ω‹W ZγΜ_ΌΏώRϋΙ­·~ϋ-oyΛm0š ˜WΌ1σGώ=™Ώb‘°6ηΟŸ—Ώόεɝwήi·ϊ1˜±τ“†΄SNΉΉ°K ϊΤ/Uίι3gΒβ%1|: ΜίΦΨB: μ3ϋπן7ΟFΫdτ―ξk7§e=wϊ;ΫαEZ&λΧςό%ΒFWƒ}†!sΆΏ•oΥ³^LPΫiΉ₯ˆω67΅1{Η¦½₯mΞό€ρoΩΐά-NcW7+ΕΓχzw<؞XKbšVχh₯‘ ―[ΥΒλZCƒ`a­Iv‘?u1Ξ΄Πωќϊ5ωΏπξ·½νmσ_Ρωs‚ͺ¨<|δ?0σ'_τ›Π'ήοΈγަ. ²w4”1ξ^Φ–žόη‚/\ Šι­Λbό.0ϊΗ=φγ}Cj₯€θF@ν† ζ|αE" fΆAOŠ- ΄ίσηgCυvώ$ϋόJ‰Ϊ­5iΩ­&Σ«-{ΫRβ…χυŒΑe|>?γlŸ-ψ(>‡kωΉCΖΆ©1… bAπl©υΝ=€›Α€ΉqΓ‘γ”ωΣφΨωΐΊ ΥΟΉϊκαwΏη=_~Χ»ήυεΦΤΑX³‚±“ύ„;ήκΗbΏnsώV€ £δc·[™šΠ"ζ&£vϋ°&δ!½hJ sΝE“νΑ3JΗ “Όΰ/°λja𬠈Ώ L θhN©πB§<Km7J–ΤυΣΑ@_*ΈδΫ«r•Οvΰ£P©½M(·†¦Ε±Ά†ζbx=£M¦–Β¨’ς Y§mˆ―Ψ\ΪΜ¨ν†s6„γŒ±ψ<~§[φΛρ:F&ή[ίQ@9ΖνX΅N64i 5ooιEΨwτό₯]{όωKjͺ½ςΚ;ίωΞ/τ`ώΎΪŸΡΐ̟A ̟£}aώL0mI^>xrsρ•@θSη¨Μ8³ώηώη“ο|η;¨Ρμόpίˆ €ϊ!€kmκa4²‘Eίƒπ Žν†~¨΄šΩF’αΔ8 ήΕΰiΝνΞ yψ>ή€q§ž­iοι»}(3_w7&Όώu’ς+κ².’L¬žτн‘:#nκ:Ζλ?N›—Λ@~^·)Βψγqϊ7Μ>λζq°ζΟ’`ά–΄ΊMΗ3ΐI «:%PΉΦ5Γ01ΘκΤΎ½\ξ³€‘οΉηžϋΔόόΟ(Ÿ5ααmΤώ~Ό――φΟ2²,΄aΟ΅h#|«_ΎΰZΛMΏΘ€~%τLψC'9 pBτLDxώΕΑ<+#*FP#ZUΝ}π’όk Af‘Βι™5€8XQ+ QQΙ\ϊΣνkάσnR31Ώβςj‘~ˆ›‡ΤΉ{ˆσ+Έ₯@k³Bβ  ϊuχΰΠ†o!>^`Φ…ΐν’!ɏ™8ο–5 ?~χπCΖΰου‘zΡfΐΰ₯Ξ<5=0dž^Ζα½±³ΖέΖΧΈ;mρΞύΐΠv5woωXΛό΅ΙG#…YΡtAqΎ\.Ώς•―ΌεΎο}ω³Ϊί™?jWω;σgԏ€4‚mΩV‘l’Άφq5£IDATW³sζ―’ΙΝ†J 6T\;¬ξάΤ6ΐd^‹{%˜&€ZK›v(Ο2Z²ͺFP3³³vσͺ­=Κα‡ΘMOO[b΅mjK@gŽ%h΄–¬ˆˆ«άu@Ί1c`\Λj/‘‘6C Θά+Όt’πΛ‚νa‡*ž8hRn˜΄žΩr\އrZ֍–“γ\ύ[TΈ0EfL_~nΫ‚9 {ΨYΖξΒ@άτιV>²έ=ŒΝCΜ0Β…JEΧ[ΟΨylΡ%.άcΓwΦΝύέΖξpξf  ›ϊ‘βg Ёtώυ?Bπv€.Χ #¬ϋCtγΰŠ„…β©Σ§g»ξΊ[xπΑ‡ΕόW%̞S{bΞ?Vϋ3οΏ.σW%E—ML4ΩΧψ¦›nj^}υΥΆΑωiυ!Οdnη%•@.D…ρ¬Ό:%FΨ#ύΏS9ΣI»ž•δ=c‘ŠX³–‚Ρ=[.§€Z£5“qˆ+BΒBΉl§2Ά™πΦRi„ζ?€;觎Κ.Ϊ½υ”c₯‘…]ΛFT‰dQ‹>}†!Ά‘aΚ¨6gI™αc± aΘ»Κd[MZŽλα\·Ια'© 0J”j96RJͺ΅Nƒ&‡k¦aF<δOWΪ%ωy;G£…†­(μ[ο¦N—Vέ¬—κΰ‡6ˆ-»έ˜^·ϊp7μnο0yyΨ|~ΜψrjJΏ– ΅Ω„Fη΄˜Ώφά«Ν¬Ήδ’βOφΨγZόΗΩώ0Z†ω3ϊg›ŸoυS"Z£+…ωΫ₯>Ξό9αΟσφƒχνκŠ?7h δΐωP±"ͺv0BΫιζ1‘ν‘F:9ƈ  d|‹@e; V~Y“υσoƒsœ|tΑΓxΈnρ\ŸVDŽŒΪvKVS3 ΠΚ‡Αh‚£dTU„I¦ι5ρ;ΌΫq”žΎ8”―ΥU-ήΩ“.y‘ό½‡ΎŠF•‹JΜΟΟ)ξj2;7“<ωδ|2+7-+ΏZΒτE#ϋE ` ςPGέκ”šψΫ;ΧɎ*Οί¬ΚzχΣέ~4ΖΠ–w7ΒΒΘϋ ‰o| ο‡5³ΨΓ6‹ΗƒdΟ αω²°Φ >°=Ψ`΅Ζf5c4FΒΓȌ5ΫBFrŒΣ»έΟzΏ³ͺrΏsοɊΜΚ¬ΚͺvuW¨ΊyοΗ‰ˆ7̈ΈqΣ(Π’~έέ]2ξ§XžΊφ8δ4‘»’eˆ'ν?ς+Š”ΣηιYtΞ£EΏ*Riέ·.mαΙκώPz{ψЌ>rS^TPuFνi#€KΚιΓμj›žqEΐσlv¦½YG›pxϋ{}8›‚%š„₯ώ5z°Lα/)qν(ˆ"xωε—­i)„γγcFf^ #uΧW=Π}%΅)»ϋ•eρŸψ/·άrί«r*_υK-tΞYπWΩ όΩ€ EΛπ§<(>ԝ²zύku‹‹ΰ@„Π„)©WƒΌKƒΦχš€¦4¨9 P£UΘ8• Ή!¨°’ X>σŸš΄} ˜[μ ΪŠdΕ€ ξηδ°r,]†°υΈΔah³’8mš-OΣωy„ s―S’οAAψ€Sƞ]Λ3e#]ŸΎͺ698eJΫ-ΧζψnΦ·²«œΣ‡*VεeώΥ„ xAέI‹5θ>MMOeΣSΣ5žy<§δt6)°Ÿž΅πΡr^ž*½Z‘:ŸuwV³nωχχ ψϋ΄ƒΚ1#*†ŸΜΤN•±T(‚―βΟΌFπ#ŸΤ' Cffέ=έΪ]ΟhΠ>΅%ΆΟEλΩp0ƒ&‡ίΓGθΒ ]XZψ`ώzΨ§žpxΗ7+ΰ/―μΉR`τλ ™Όœ6΄-DΤυΩZKΰαΰ1q)•Aχ<£=E½ααΠpx-΅ž1Ύ―αe‡μΉαΟΆ·ηεu&-ωC‹Όy~©#όAΉ"?ΒύYφ;­ŽφŒLg(}( €!-qα!}?ΚF^Whσ/#R³³R ‹Β±ΰ―ΏΏ·€‘£Ή7i_mφΚ-ς'χ9sζ”θ¨ˆΆχυWύŸσoώH[μΗΗπ>ΰŸσ-§5s`QB™ΔζOHΔyΟοΦρWHΆd ;…$Œψ–ΐžyš‚H‡ΦΩ†D2‚Ο°„3«Ωžτ2mZΔa…ΕŠΰΓ―«Ȑ$ŒyS2PmŽIˆBαȁۑMO˜χtKaHzΞfω(βκ]ηl·ςBX™`©—!ρ)λΔΔdΆsΗN+©ΌμΏ€’ƒυƒPfΛUx02<’ΝΩjkΨ&šBΨE]άJ;ͺαζ‘‘aw αΜ&.;Uκ @LΟδ|,ONK‰ΠKΩΈ,Ρρ «3 _*(Vά©i)^R*ϊόœΞΨΙέ]έWIΝovvΖ”²ήb8άΈ vςΩXa„ΕνQ˜i¨Ό€…ˆΪ%ΖΪbšp°Ω`ώΉhژ΄ϋ‚iζY„6kuηtϋŽ=g½5Φ₯Eyΰˆγh£’y>ΊΛΆ½<—>γΔC±ƒφ‚θΐά‚”’Ž"=Ο’ςpΰΓΰ,€Νxφ\‘ƒ¦O‘Έ@»αOΐ<—Π!ώ΄ω^νΈ‰bινg™?Δ!]Ί…ξμΩ³6W=]β‘Tι€όΫμ~φςη!o>ϋΝ·Ώ—pžΚΓύ™Σ§³½²ώιK(β<ƒ¬φ/«νΔU³όU―Κ›―Ή¦λ§?ύΩΛωΘ½O Ξ)ύ΄Κ1’ςϋη|SπgΞU4-ΣΆ_μ1Εͺφ9ίΓ‡g<π€Όm`'ή>J.8°"BX‰Eκΰκέ2—θάΉ[WE’…aXνΧ―.ώAB˜Žπ1Πd>A…dΓ:5…pFΈΉεƒΐJ‚λ€ žΈIοleVΌΓ$4Ψ,Π:7h£Όώh fGΎ†Ά­Ψe ά‘ψV°άΌ</„όΜΜ΄Ά¦~ψSθΒ~εȏOŒgƒ*CΞ|„ ₯€2Žδ`ί! uχέf vrδΛkΤEcXώn ²ξ€r“ΧΝΫs _ΌA)8΅{›5σΪώ₯»mΫ²mΩ€<žšΚ§(ςΆςtΊ§s•θΆvrMϋUf₯HXX…Ν–(Ά˜Ξχ–Gq oxΒχζ©3ν…#/X§Fέ‘ί/ώ9(Ύ(Nδg`―Ίͺ€ΰ”ό©τiβ4:ž}šήΪΌ·—·.r‘ μςη™α+ Ώ­/ŽwΠ€Π‚'Xςπ™η–h&ψ³Ίήί―§MFτœ“Γξ΄_£3~*oΦgπΪ™ς=ž?#LΫΜ=”ς‚&Κ χ“κ;<Λ<ƒπh€Θ›ϊ‘T2zΑbΓCΪGΩP4:5"’n[νθ+iΤ‘rΝ[ήυψ㏿xλŸώιύͺϋ¨ΪeZυwπηU?¬~?άςG;C “r`ωψλŸσCΒ­/Bh—Ÿκψζ°Ht±JΔXo4ί&ΥAΐcΥΌΈΒ8OΙjE@#tqX„h˜GρcBz:Ό^Μ_3<ΌK  m† ¨Π:-‹ @Α°CYΨ6 λLΫA .ωΪξΜ€)Ν·Υ5ω2Ώ?5τ>‚ΰ:=τΒ±Ρq²+φ\a`αI9^ύu η1+i±ώvȊDˆ;Ψ(e,«>'`ˆίΆMλ Τrλ@ο’eΟθ `E|Ός2φšEπ"œ©ΰ †¦»™†0K›ί/,I o);yz\θ’?εΑZΆgAαGIcJ’Β½^]. P§FGS?θQ~ςΕ‘7Χ¨Ύfgυ$‡oŽCβ@+™ϊxωP MY½Όψcϋ;E2k_εA H-Vϊ3.φk ώ 1ίΟΌΏ-”ο¨gϊLY‘β'8Π&Bh“Q΅h [ήΗ-ŠσZŒΥ]@@²ͺ„ε/{@x–;δZΔ }6GΨΊ @ΠXφU²U ²νdΌ,VΐΠ>uΥθ1—Πη˜|:H{™ΧεOYPH W ŠZ-RδgυΡp=ΦάN„p!œΫe-ͺ€sϊ,€Ύά£P~Ξ Υ3kώŠ+™VΡθ@ ” «αJγμβ Α}ΚΔ\±ƒ$ λΐEή€„Z€υη^‘‹ΦΫF·Η# 0NγH„SNς#­›Βγ4Œr0σΈδA™ˆG:¬`―q‘gόV9)k3ηy@Ÿ:XΖ3β ΄Έ§|”Ηiφ¦ΈΌ³4E~©ΒB~πΐΫ€ϊS&γ™,rΪΫλL^Μ΅£$PGΤ—v―s*ŽφCρ£<ΠΒqζω†Φ<4­m—Ρ0F£\(L™’¨λa…8xΠ†Η€sχέŠσβوH§ΰŸ.ψsπO‡ό)πŠ–€ΏΈnέ8 ΐ*X‰A˜ΝK( ψ]θV%ΨLXΙΟΡ4ΑΥm€΅Ϊ8›Π‘Y΄”«ŽγBΟro‚Xε§.uNaΛ9¦HΓΪ@Œ3#8θXοƒ sρN&L—£Kt˜€>‚½];σ·Έ' Μ€c-:€‘ΏƒαΚ€€Ε>©υ ,DΨΣ–6Z!ΊjEΞeωHfι’hήX[ΉΫbKκΖHucNπΌΙ—©€„‘c?7ΐH^p‰ηˆ<ψ’$eœΙ‡zΊB@Ωνžπ"-uγΐΞ€–>ω“v»¦IμΥ>Ε™Ρκ}β‘W£@»Υ0Β`Tα5 ε‡8ΒΞκšςΩΌ<|.ϊe’Ύ(Oδ‹rOΘα‹)ZθIa hψC{’ΨPΣ·˜{'-t•_£[κ“Η`%?ε’Ό”έωΗsΟ[΄υ³{Εγm‹έ¬}Q˜ΦΊŸχ‡ΖuΧ]g„Οœ:Ε³Η{ώ•«ί|uΧ>rδ'ŸύάηΎ£η‘ͺgcX墝ύ”ηεΐλŸ π7ΞΖΟɁPΪδΆ 2 „E2‘g„*@€ A@”4^[l·<†ζ9#Ήˆ‡ γƒ@Ϊ ΨΆfў‡΅(#Α­I< +Œ!P„‹ζά! YΗk^uκπ%ΐAv@k$Š7¨+eζm€Žx5 h@QXc›°ΖƒόΕΠΕϊ«¦³²œα³΄ψ@9‘A\ή’ΰšƒΝ‚xΨ(νή!~Α«n½ζΨΣ­ z΄PUΕP ½ΛE›Œ\Œλa­εΆηDPͺgځ‡ΚžHKhW΅g“6…/φ¬ZΞωs OΟ ž³φ έ΄3―žYvwΥϊ>+?Ο>ύ€v΄!£2Œ`pΠ(ΥLΟΆ½>8§Ύ_Ύηž{ώωΘίών?ͺ-JŠ7(²‰ΰΰ ώ|_†ώ}Ψ?,1#άΖr €ψΠaG1^Ezϊ™g²Ο~φ³Ωk―½f–Φ– Β ?}δ#;xΰ€)½Uvm1!˜ƒ]KΘ#`Jς`VΩ³ pYΔn–H‚CBs‘[£€”Σ8ΧωΒΌ€^Xxš«΄Ήo*ͺ Dˆνg±0’Π%=Β2ΊΉ …›ά΄F³rχμΥ’­s&΄΄Π3KP€³{·Vƒ‹oИ˜ŒŽΩHΒΥ-ΤVμ‡ Θ’?Ψ±mG^^Ξ🼰πNŸ:m{rv„ ΄Υω"ΐαμτι3ζΗP>ρ/βQJρNώτ΄ΦHΨΉS{+(+PĜ_ SΓ†Ψy>T\© \ΪϊΥ^‘„W6β’@¬Fshε–·Λ €PrΐΤ”€Ϊh»,xΐšΆ ξ–Vΐ„2ΑTΛΌΚNέΘw»Ε…;ώŒrPNάμL—ΕŒ±ΤύzhΟκΩEΡxΙ―ΡQNς§NπjL|Ξί‘#eδΚ+―²Es€c4%†‘&hΡΖΖ…‘PwxE™ΙaZ°ηϊqρ˜M¨HOyΨ[β΄6Ϋa?\E{R0²ΆgΟeΦ(yΩς:rΝνA{ρœΪ’PίF)tF¨ |D!eqθžΛv[](#νΨΣ6€ΓGέ―?p ͺ6*’ 8ώwυ_ίoώύί?V€?_τ›TΑ¦”-J–ϊQŸfΰΏ 4*ΎMιmΩ₯«ύαε‘άα‚λ́PZpΤŒΒθ|mγ™}ώ _ΘNœ8‘ρΕ-€…°Cp` >υΤSYφ]ΩΜ\.˜Z6aU “΄`Κ η¬.ϊ³;Άmτud³Y\­‰ωΑΪά,›2³ε-ΦΨ”Βψ –γΤ4;­1ά=XΕΦΎ˜σΪ`jnZ–φYK;5©!X­’›9kρ(+Ŝ—ε7©°ρŠζF§ΞXJΔτ,«τ™£ΕθAk‘œΐrnh:cw<„(Cњ{Ÿ“_n [δe~(σΔ¬VΩW{²s#³Ωψ΄Κ#`sξF}yn\vΦμŒ>Ζ’ψJήΧοΠτΐYYΎ%φ\ˆHθOV4κ1ͺ]ζμ’Σ-E§ +;=4)ϊ|b˜M^€¨LΚBœΤ&A)9½β3―ψ•²gG-ο ε7ί!pŽ€ΣβΓφ€2ΰΧΫ­zgέΩπ―°ε#ssjΠr6©xcψN)G ΣQRϋ &ζ‡s€Ÿοθτά ‰—*γœ–ΚJ«‘ν:χhγΐ’£~*ν[ΧκUΏN-rœΡš K›3vNό‘<4ΒΉQmό£‰pπnFν–uφfΣz­o>o»Ε53uώνδeiΌ)Ρv―Cκ₯ΆRδηV$kυW„Ε΄]Ε'gm¨tԎί<\Χ&xšo«kώ€'KΞΈΩ灍ΏEbΟ»18₯›†-ϋό)b«πΌΆu”Œ΅ζSTΐNΖΟΕx)½Ελϊ™’¦‡,‚ΧΖ§-Ί¬[πϊβ]£Wδιχτ9ΏfΤ‹k,ϊΑA-ΰΣ S¬!ΑίΒφΠeτŠψl π3ŠΓΣΤ_#iU­ο)©―WOž8±€’±Ϋo¦ΆψύYπG‹ό]@τ£)ψ‹^Υ§$M~bΨ_œ χ†p €6،Π`μ)ψϋ4—WΕψZ\YΓΑ+:³œ$wΙ*:£γJ™=; %…@\‘VDX_X$ֲځηΤζDΓΨ½ηŠa˜‘Π‘ηάΗPTΉηχ^ΞεŠSW‡$b³zΠ¦qς ηMξE|{έ.)΅Šˆrσ4U”Ϊx|”,ay8ELx‘Λ @Kπ§ξ¬Gπ—ΒmBXνˆ^9ΫΏvόψq³ς`ώί”Xρ6 Ι΅ϊ|έ²δ 8ζτ©YΆF(”$˜jb#ΏΔ(ςV»$§δΠΝΓμ¨YhρS€K½ΞηZO‡’Χε {~§\ά[ލa'?ΧκWσ¦ότ Δ?‘E”4š‚ΥωΉX§—:;υQŸΎ»ήυy-ώνxι·ΏΊυΆΫξε/ω«ΒςgΞί-ό±0,,~¬ŠRώ*²²m«€=τΑς‡/(ωταRŠNΈΰΐγ@(-Xλΰ ΨσΑχΎχ½Ω‹ΏύmφόσΟgoϋώ^-σα¦Ψ€‘η»ιEo$‡$O‰Εx\kaRΦ%ρΔΚ0ζ@ ζ§Ρ₯~ιυrρΓοι4ή§ρ— Kγ]ΒΧU«!I―G½ΟΈθT Η°es0€C]6VN―!’εΡΰ•VώžΌJ“εχyψuOγ₯μ…Ύ;Ώ°κ±ς3ώ(ΔuεRάΣ‡yƒG7ω°ΏFa€ί‹0βk+δJΧ<8―ώέωΛgŸϊ¨,cǎύZ£ μπψΟ(n³a€ί+^+πgψEγεΝkΏΑ7†‘¬ΐgz°­B––~λG>’ύψ_5ϋγh S?–?Jο“³M°++ vΛ\λPne‰K“–Ίfψα–HΦdzΝΈΉ€HΪδζROP«χizη`Ϋ4p%ΟυbΈΎΡ-υIcδΟϋxϊεΣxμό (.q…_]~ŁΏ…ΉŸT|ρηηΧLആΌͺ₯wΌγs—νή]ώ·Ÿόδ€ζόοϋύְΙΰί8μΕΟ‘Ξχ£Pxω5΅ό¦(”e-2CτΓΞ‹‘¬Δ>:§΄tίωμ?ί|³)ls‹c€ƒMEx|Υ‰Ž¨ΰ¬χτυRt– H@„XX!άTQqνA3~7l¨ΊŠΈΌRT@§]Χnή­θ­”Wž^;½f%MγžΖρςš? /˟ψώfω ψιΣτ£NΝΙΛ―€}ώmƒŸGιŸώπ‰O|βΎS§OŸΤ¦Bϊΐ,Ϋϋ2μοΰΟ°?½όέϊ·¬όΕ‘p5Bh£y Υ!8Ψc~Ÿvz»Zϋ‚ΛΣόΠζΩj–8kuΜωW$ŽH₯™,,»U>%gΠζ=§`·΅\ozeZBΚFV’ΖŸuKιφά§ρ όy³Αγρ{1HΉ―ͺ–½φڊFρΊΎuτθ‹wύε_ή§]-G4}0£°‘ό}΅? @€Ώ7Hœ/Y„ΠfΣ!8¦cΎŽψάαΗΑ\#qVε@ol½_:!y’€Υhς[Ω]Hς]. αα.=Έ5{±•Όέg}­εoJ?tηGγˆ‡ηGz”v»όω“ΰ/ΛΎͺν¬KϊΨRιΊ·½­rεε—w}ιή{ŸώŸϋάQšiυιIΕΣΩ7ωΑβOWϊ§Γώaω{ƒΔω’β@(«lBx,I…`Y“΅Vύ~Ύ Smψ%‚‰"@T/A(+1.ΒΫε€jŸη̟΅ΤΙυZϋDBhΉυ iΩ δ‹ό¬|τ©δPSτύUω”ο‚>πSΥ·-ΊξΊλΗΎφυ―_Šμοΐο–Ώ/ψ£x€Ώ³Δηό«¬κOWϋǜ¨qyΡp €Ε¦πN\Ÿ²ξS‡΅/αz­ύ2—©ς5ΐYy° Wžˆ•ϊ¬[ηγŠ1’Qv“·&!ɁΰΦ«λρμΆK£1^zŸ^·U·&}Ξ­­"χζ§dΧ…υ/‹ΏΚžVσσžωnΈ‘γΜιΣσΏύφ£O<ρΔO΄(―Cσύ#*Οdƒεπϋ?©εΐAOπΒ]ZΨΚ €γ£uή€ΩΈ―9†φΩτ‚:rTiJΓB}­¨φKΠυlΡߞ©•”e₯E%ρφΚ&^qysΐμ"._Z΄v˚>iϊv―Σ|―ύž<μZσUvϊc―¦ξ:5δίΡQ’U^ΥΧηήρΆ·•΅«ί‰OύΥ_ύΝo~σΌƒN9%ΗڟTΊtΎίΑAφπCΒ]ΊΨΚ @­σͺωLnηΊΦδ³·¨uΎλ|:λ+.ΥB|­Θ_“ίZ%&–Pa YI“QξC0\΄?Βς_―ΚΊΥ½Zzi:kh΄Ίn—~šή”^›σWwŽ8^οΣ§­KϊZ'ΰ?―Ό%½[ώΚWΎςτό›Ώω–¦τFψ|°¦|w?šŸϋ§ΰQdGM~«ύcΨ_L wiq`«*­~¦ΥΈ¦SΧ9 ϋlkEί gψέΉ2οΟF@Όΐπ?₯XΟ¬|Š (Ώο+°žY¬;_Ά*ΑTq[gԁεh§e Ι/xκΗΑcO-W5zΗP?Ÿρ]`Ρί‘C‡:_9~|ςΞ;οόΗ~μ±+œνyYι?ͺ3σύ€?–?Cώ>μŸΞχs]~‹·ƒόŌp—ΆŠ€μrΌγ:=θΠιQ/η$PΨ°Α’‚­…/ˆ"ΐ‡r£ΕςΈ ?ͺCΝΕAΣΟΩEλš”m΅εm'ώŠqTFIˆη<ΓgΔΰΧ-?ψ,\uΥUΪ‘³γΑ£GυΏξ½χ‘Χ_ύΈ†ό;~₯ŸHΐΠΗς§£s€Cώnω»μπƒΒ]ΪΨ* @ ώi‹Ή΄E ƒΟύjρ|Νfs.lσλ―Υ"¬υΒsύ²Χ+€Ά5»—d­tWJ‡ ηΐTΒ…2σaƒ7zθEΰmƒ?«‘‘ΖM―νΩT^ΣΦ1ynεθ“:ͺω™χωυίQ’o:πk¨ΏSίζ(κΉηΞήsΟ=?Π.ž?—r0§Ρ€ ω‰ ―ϋρšŸΟχϊ(ιB?·ϊές·sXώβRΈKž[EΘ₯Fή\\§‡ƒ?°‹?χX–ΖΟψ•΅‚˜cέΛH?š¨ξνΤ‡HΘ]j¦Βm)ΫyΧ™g³©ΣγltΣΐά³YRΏ%΄šΛ¦ρλ‹r₯~O)Μ²Χz΅π<†σΝβ' €>ε W΅yΟΌβ”vξάiK/½4ς…Οώ§}χ»O(μ4 ύwB–?―ψ±­/ΰοsύ>δŸ‚?2Αε‚Ι”ς*ίΡτBνΓ>ρͺœ w)q`«(ή&.9[‡ΦΩ;9šΎΛ10$R‡7Η΅;΄us”‚\ϋ»U"ΡE `M@ΈΰΐΘΐ΅™KύΉφ{λ@ΊηΡΕYκi\Wά/O”η™ϊ±Ο†:.*,{hψΑ;όv―°ήžžςΎ}ϋLžύϊ…Ώσνo?υο}οgΓCC―©ΏvόS«ίΐ_eτψ}ΘyΰVπ/Κjsώ€?ψΑμΡGe7ΑΨΫί5~.%lz@θM{ iκd•ξ1•άϊ§Γ£ωW%T8σpEΓ…κΨσhψ­»ƒ*%ΰΥΏ!"ZPB 4αΆ R<ίJˆΝάry΄FΌ4n«kΟ? χr₯~~νg-/οΘ²πτžήήYϊ€Υmφκ«―Nύψ_ώε₯GΎύgώσŸΓβ'žΦοΠ§Gtπn? Οb?·ϊΉηp«?~— ΞX,¨dΆHƒωϊƒ£GV?όαO€`˜Ρ@œ %.(HΈΰΐzr`Σ+tH9pn8Όs»Ά0!ΐβ ]gϊ_—ζ ΅¦H³ŒoDΎFΐεΏŽƒ Τ#\pΰbη@ΡG­˜ €ίsF7Χ’>Άβžϋγ+―ŒΎόςΛΓ―όα―θG?ϊυσǎ½ͺΕ}―ŠΘ,έUύ·ͺΈ£:XُVrΐ,ΰ@6€–ΏoπΓ6ΰU‘P„Gy€Šυ―υl+lJ@€Ώξ’βΐ¦UΠΘqœeΝ§R§¨Σόe ΎτΥσ©O}κώ½{χ^!ΑQψ³g(„ΰπμν …Ÿt~ͺŒ9\ ‡σ+a€^oνΞ§ ν¦m7ΌhŒ[άλT]Πh_ζ«θ˜>yςδȐœ€½’0ϊ0Cπt!uεΚ€ϊ< ϋ* ŸU8ΰοCύΔu«ίAί-7 \FθΩ’Yό€?JΘώύϋ³#GŽT?πΨό?λD;¬~15ά₯ǁM«`-ΰŠ³KZοΨήΡ6ό―΍uΠράsΟ=£³Μρl@GOqΐ‘*ΓlqιuξΏΑΰΐZ8ΰύ•΄~ν}ΧύJeαs‰ώ;'Λ|Ε@Χ€ϋœόQ ~|}ξSΰηΪεyp  ΫYι—,φ#Ήΰ'Β]Κ°•΅—rΛΝ,χμ™gž±―~=ύτΣΩ'?ωI„ΆC›yC·ζQ€vΏ—³βmΣΤa_α‡?‡Ηg€žΓΑ?@_ΜΈ@4€Μ½^¨ΞKaŸΣα`ngυmΐάGLΰ>9\αw ψMΙςQ2νΚ]|Τ']μǚδ #\‡ \ͺΨt#ή!υ‘ζ³ιiŒ‘φbGu-πFΠƒά³`?ζ Sπ‡O)πϋ΅ΌΓ‚ˆΚmlnY˜Η½ƒωœ@ΫFδηgWΈχxœg§ogπ(‡ΞxΰS ~d ώ‰L™pΑK›Nπ&`ˆΐνώtrg:? w‡PaDΐ‚#΅ώ‰λ*šŽτχψ… VΟ吏ο°ΐ9¨γοלΏτ½CΧ€ΏΘ¬Šάΰ΅>ωΕbΏ‚)qڜΨ΄ š:Žι€&Φρ†p¨έB‚υ@bί@ށήξ―(α‚Αuΰ€χ­τμ}ΥAΌρμ`οηΖπ4=‹ό(&Κ„Σ!}0¨zν΅ΧΪ"βΎΎ>³ϊ‹ψλP΅ ΨxlΊ5)KΒcΰ«_ύjφιOΊΔλ:μΥ‡m’žˆsNΎΡβηž8ι‘[»OΟ\‡ ֏)πCΥου: Χ} τ„₯н‡Ι»Ξβ7ΰΤym«ÁwϋςgϋoFύ[ Δ ΨLΨ”#hσtVŸxΟ{ήcm†?66†Φο«| ή«.(|θŸ0·τύμρfό‚oΌΏ:ψ§gΒΌϋ™‚₯qμ΅ΎΒΟ,zζϊ‘Ό*Μhaϊ~?D€?, ·Y9°©Gh4΄zϋοΏ?ϋΜg>Sς!>-ΰ±]ΔΤωτΖΓGάRι5χ8όΒ‚žδž€οΞ―ύμqύŒA`Χ€=N–>Ÿ ΆEΒXύwί}wυΰΑƒζΗ:Œβs،Ψτ F'f*ΰζ›o.ύπ‡?Μ\ Pǁzƒ"@2ουnω§~\7:ίθχΑΰΐκ8£tλ45`/’€χžΆ6Ώ―8κήΉ·ΏovέuΧeΜυ󚟏ψΞ~Ππ/8§MɁM­Πιιΐtl4ϊcǎeϊΠ‡JǏ·ν;βΣθ€w‘ X#'Κ€7z3poζηργ¬/ΨSͺ5?υ_Ώτy]Ο‡ϊ €ί:tˆAΫ˟^fD€5.7Œβ:8°9°©Μ;sφόŒ<φΨc6Ώηͺ]Δj€ž*^œkqάί…ŒίΗ988 Έ/γδkQŠ~Xστ±φ‰ΰ}Ÿkώ[nΉΕFΥοΝHpΰ'Ξ y%\p`Sp`Σ+΄RͺΈ0xψᇳ/ωΛ₯^xΑ6τ@ΰŠπε€O]X c[όΦ•Λ(Φ5O3€bΑ+ ύ³φ‡ΎΜ±gϞμο|gvΫm·U?ϊяΪh #L ²ΘeΑσ‹ώœr57;Ά„@#Αιά„Ÿ/yέyη%Ά Fΐ‡ιζΉΈ ΈΝO…²Pη7Αΰΐωq °ήW"R§ψΠ>iSΠΏυΦ[«ο{ίϋ²λ―Ώήθπ―ΔΦίJΨ2 @Ϊ¨)pφηΝ³υ=τPιΙ'ŸΜ^|ρΕ4zΛλ6UΛτ,ε@Ϊ?—†Φϋ8ΰίtΣM¦ΈΏύνoΟnΏύvΫΝ?h‘Τ³ˆ3#€qΏpΑ­Κ-©€£Μ²κ—αC„ΑθθhφΤSOe—]v™)ίψΖ7J|υ‹xβψΠαΩ³g3}=Πό4α‚Α΅sΐΑ|Χ]ΰMŸ+†υ(}Œ‘»ρρρμΐΩwάQšβ«ΏYvγ7f»wο6ΐw:Xϋ8ξ}Š/€ίX?Αγΐ–T¨y*R‹#­žβoxx8{φΩgM(‘„5ъcαXžτGΐΠί»woφξwΏ»ζΛ§ΜC}hŸ>θ΄τ‰‘φχvθEœΰΐVΰΐ–UΌqCͺ xœVηv”…ViΓ?8h΁ΥτA§ΰCϋ~ΟΩϋ6Χ‘œΓ…pΑzlyΐΩ±a±AεωΕ98h΁΅(ΦiuͺϊΞ‰8šs €&|i&LšD3―2­8ώΑ΅s`5}\’Χ‘rλr €σlϋΥ ͺσΜ.’ΆΠ·D3G%7˜‘lpDφΑΰ@p 8Ψ€ΊΩˆό#Οΰ@p 86€‘lΣ#Λΰ@p 8l4BΨθˆόƒΑΰ@p 8°`˜Y‚Αΰ@p`£9 ΐF·@δ‚Α ΰ@(ΐτΘ28‚́P6Ί"ΰ@p 8lBΨ¦G–Αΰ@p 8Ψh„°Ρ-ω‚Αΰ@p`8 ΐ0=² ‚ΑΰΐFsΰ}¦ ½ί&WƒIENDB`‚icnV Ώ€rocq-9.2.0/ide/rocqide/MacOS/coqide.icns000066400000000000000000000125111516144147600177520ustar00rootroot00000000000000icnsIic08A‰PNG  IHDR\r¨f pHYsΓΓΗo¨dtEXtSoftwarewww.inkscape.org›ξ<ΖIDATxœνέ{”]eyΗρο³g&ɜ3I ‰υF ’h‘xE@ͺ€HfN‘Ά‹*Ί΅ΆΤ’­’©.—β…‚V$Α33pS΅”€  ΕΚEnΑHfΞ™$dφΣ?&t!MΘΩημ½ί}Ξώ}Φb‘„³ίηaΑϋ›w_Ξ»Νέ‘rŠB7 "α(DJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJ¬ΏεOΦζξ…O/ϊ£?sbˆΦ₯έΤs²Έ‰ΩΖ\kΖρΉΦˆ6 LεZsuλ8Γγ\kJpΦς»‡+§bφεlΫ‘‚Ϊ L10ψΖ“8ΗpΖXρ1ωj¦y˜εS‘—OZλ+€(zύ·,«~`ώ–_οΐ3W°-χ-Ώv›9Ήlb€ϊ[°;ΐοΏο»“hς.κ>Wσ²m­@μkο?΄Hkf{ο5σ[‹Α+©ήŒϋJΜgΦΐυ\ψdΎ§Y$9¨Uή„ΫuΩΆ#%cά‰s=Ψu DW±tύšΠM•A‚˜»ί‘m;"ΐΜ΅†[Λ±¨N}βΞΠ υͺ0΄χG²mGdkόn`Ζ%Τ›?έM/i=>c«*SΜœΧ‰βwƒ]„ωw¨7έM·k=FͺΏf֍HλbŒŸβ~.6΅‚Ίo έP7Jφ$ ω}Ω΄!’X„sX―όžακg9fξσB7Υm’€›–\RDΟΓ8Ύψ†+η3UŠg^’ΐHυaΰω©w#R λΑ>Δθδ…‘ΙZ{»7€ά‡H‘Μ>Γ•σ©ΩPθf²Τ^Έι;Ωϋ̎Η+·±Έr@θV²ζ Φ @Κb!‘]K­ςQΜznWΜφΌΥϊΩ₯ςκτΫ‘ŽΉΏlYθ6z“]„5ώŠΊηϋΞ† ΅R\ΓCϋ`ώ›Πmτ°_cώ^ٍH―Iζ5ΈέΜβΑC7’€Hr»EWS:1t#Rˆ΄g6ξη1Rύ—ЍtB ™O1\ύ&Ÿ±œK]Ω΄H‘δφΑ 8ΩB·’”@$ fΗρDeœ“lNθV’Pˆ€Ε9’ΙΑς]ζ†n₯U ‘TΩ[˜=u95 έI+"is?―¬ΰ6;t+Ϋ£ΙΖ‘T+K©Y_θFžK*£;ΈΣΡ·RK:1€}› γΌr6f'SΠgξΣϋ.@­z ΞkΣL€—ΨYŒN~$t[“ή)@ΜΏ§6–HOρΏ£Vωhθ.Ά&½ΐQVavεA`~:Šτ”γ(κ+B7ςLι­.υ&Ψ©'["œ₯ Ο]Ί‘gJχ.€Gg£W‡‰lΛ<πεΌw‡Β¬’Σ €±υwaό$Υ1Ez‰ωlzκ"ήjι܁λPϊΟxτΉΤΗι-‡±sυίB7Ym VΊχžΨ1E$CG3ΪX²lžŒωΧLΖι-ηqlεE!Θ&Ζ&―».“±EzΗ|6G„|\8Λο|6Γ±Ez„„W?ͺzΆΫ‚To^Ÿ]‘žπ1odΌρΛΌ gϋm@σΣΠs"Ϋ3@ΔR޲Jή…³ €zσηΈ?Σ"½awfž‘wΡμί TZ€ϋέΐΌl ‰t½Ν8ϋ3ΦΈ5―‚ΩoRŸ|£=ˆ\?ηδyW Ÿ&›_»'—Z"έΜΩόP^ες{9θpυhŒ‹σ)&Ν|‚~±¬ωϋ¬+ε·'ΰXγά~[=‘esΩl_Ν£RΎ›‚ΖΡ)ΐ£ΉΦιNο¦6χଋδΛΧ―Ε89ך"έΚγΟcfY–Θ[πzγRά—ζ^W€ϋμΟπΰp–ΒΌ`zφ)ΐCAj‹tϋ5›•ΩθΑΆ+― ½ χ SΌ—E Α—„ξBRδ|˜±Ζ7²:\H6†«ϋbό*t’ͺΗΨTٝ˜H{`½LJΒξΑνΛ`oΗϋ^Ι¬ΩT™Gίτ+ˆ£ƒΟ·…ξržΗ¬©f1°V½F+€g»γL5ΏΝoχΣΓC‡ω’ΎεκQ†š 9Ο7€9¨V»œοbΝ=¨7ΞmiςΓΜnV‹šϋπ:Κ&*Η₯=¨V½F+€§Ξhγ̎F:ό< σƒοbο©E-‡Y ς/&’"ηλO~€ΡΙσΑώ1…ŽRb{²ͺrdš#*€Χ¬dmσΤΤF\‚1žΪxϋDšƒ)€—8ζ§ρ3ߜξ°ρǁMιŽΩΆ7°Έr@Zƒ)€—\F½ω‹ΤG­Oέ |'υqΫΩR*­D‚³ ΏnnΡhfc'χj6”Ζ@ ιΣlŽΚlτω“Χλ3?™!βκβ4*ΔJϊπg‘Ϋθ Ζ‘[d5ΛΧ―Νlτsό)Fͺχ―Λ¬FΖIΐχ:&|œds r:Ϊ5X:³:‡ΪΜΖ€6gwκ~ΫΙ(αO&*‡£Ι/³Ιj€ώeœqί‰>π‘ΠHpί9ϋ"ρ.ΩΧHΐ8ΆΣ!Β@Ν1R}²IJΚXC‘j$ςRŽ™»w'^T›Άισž—έ3΅?Ω(ή6}ρQ6œw­/½Εβwf7ψτα@noμI@ 2ΓOΚμ΅Z§φτ]Κφcqυων.†‡φΑxQ°ϊ‹αΥR΅6t8Xζ{τ·)Β8’ύƒC‰τΣ_²ΰgR«Ό ΅αή=<ώJjγeΑΪ? ¬Άτ²Έ]Ζ Vνx€ΟXD¦ ΐ^‘B_ςƒΪ=υ 5›φϊ ΅₯ φeͺzΗΜΫ©νN°*«*?€φ—Χω±ΉΔ•}Ϊ92Π‹Aχ*AjKIψADΣ7±ΈΊ_βC‡ηνΙTε: Σ·ς€ΚόMν&";(H])γeDάΔπΠE m'dmΞξ WΟΑ¦oφΝΎΑ4Eohη¨0›‚ŽT―ΛΏ°”šsp5ΰφ0NŒ±χb~hρΟυŸΣƒŒ6ίUΛ?̌αΚγPΪ―­Šd#Žwc|κώ$‡δ 02ϋehς‹€――οIΙ?β(ωEΩ>ί Θ?¬ ;ͺˆτ³½’β.@—]]ι1έΙSJDZ`,€fƒIΙ7ή=Θcγ‘RŠ šθVfΎ0°ρ•ΉΦ)ŸD+μ|ΐ£βν¨"Kb/pΰ/Ο·žHΩψ‹“|:οHԜˆ$Y’݁ς ‹΄HΆ]dΟω€+D²δt`fΐŸζVO€œvœΩp§5ωΐΘΌωΐμάꉔ“Ρ7Έk«Ξ/’σs«%RfΣ­ŸδqŸΎ,’‡8jω‡mŽmΗόj‰”˜ωœV?š_x¬€HŠ‘vΙC0Μr«%Rf…\@Λχ&E€ήςž9€+Dς`E< *β»ΥEzPλ?ls €xS~΅DJΜmc«Νσ»-7%"ˆ nr«%Rf ζZŽ+€ΦSID:1΄ΙG\ΔS]ΙGDWΔ“ωΥ)1­~4ΗύβΗr«%RfFΛs-Ηύ*«s«%RfΣής\Λ/ꏯ¦r«'RNΞΞΝ5­~8ο—ƒκ4@$[k9ǟjυΓyΐ£9Χ)›D§ΪύYu± Ί IlVέ~/π;ŒΗp_C_Ό†ΝΆ™¨‚ΎΝlxjυUΑgαΆΞ ‰ό%ΔΌγEΐ" ΗίNεHςιΌΰχ9Χ“ξr?ξEdΧ²Ωnf—ƝI–³-9fήNDρΎDμ‹ϋΐΑ@οlWηΙζXΎ`~nΉ–”B›[ \†oΎ”± χd^qωϊ΅ΐ5[ώ‚šυαƒŽΫΫ1φΟΌ‡,Evw’ηΌˆξΟ·€Ρν`ηΣοKY6ωpΠNκ> ά°ε―3žσrθ{ΖρΐΒ ½΅Ε€Ήη8!k•γv~₯@žΒm9ρζυ‘›Ω.3γ˜9o&Š>MώΜΫcΆυΙΫ[ώx`f W&€j~E%°&Ψ·‰γ/2ή|0t3myϜ=˜ξϋpΕ~½]ΜP³Κyήςwς €‘κ―€}σ-*lΔνΔΆ„ε½ρόΗβκσ1>ρ ˆ[άέΛhγ₯I°¬±»ς―)9r°eτΗ{26yZΟL~€ρΖ#Œ5Nf:z puθvΆ"Ρω?„9―Ή%@MΙƒσ?ΔΡ۝<ŽeSχ…n'3Λ'V1Ϊx;Ξ;"]ΣϊUς€8Ύ1χš’΅η\’ζkŸψYθfr3ΦΈ’Ν½ΐ—qθvpΟ­ό―œds˜¬¬C/ ι·σΖΏ έHP΅‘Cq6!Ÿ4°,Lτ΄mώ+€™+”ΏΞ½€Νq;6_WϊΙPŸό1ΦΏ/πΓ υϋ’N~voΣtΠΥ|χƚϊ£Ίέ¬Ύξqƚοϋ$ΉŸΨMν&\ΧΊ–± _ΗXsΩφX²KΧ―Αό0ΰήΤΖ4neΌρH»‡‡ύŽsŒΟj,z3γMέͺΝB½ωΦχ€΅ϊu::•³.ffγG)†Η˜Ž‘>‘φ2Už©ΎώnάώhλΒέ™Άz'‡‡ € Ÿ| τθ€<ΫcLGocωΔͺЍ”ΒΨδUgt6ˆίΕςΙίt2BψmŽb~θ„ΥXτVMώœ6ΟΔΈ€ύli§-„€ΉSWO†n£Δ΄μΕέιοϋΪ}aŽO_Τi α`ζہc‘Ϋ()-ϋC[Ί~ ΖΙ‰3nLγ‘μπ@taθJH“Ώ(κKο%:&φei”.FŒM^‹Ϋ‡n£DtΞ_4³NZ}«ο’Ύ w'ŠΏΊ’Π9Νάϋη–>λ\D}"Ρ;·₯ΐΤwΡ£ΑYΣ²ΏΠšη·mχcΞ7ΣͺXœ¨ϋ$ΨwB·ΡΓ4ω‹ξΣXtκs~ΖΈ1Ν-؊ύΣg‘ΖΣQςlšόέ’>ρSπŸnσŸ»}=ΝrΕ €™½δ―έFΡδο6}~δ4©ή2/Vkγ‰τθj7›Όγ/σ―s₯§ϊέ™βΐθΤuΰ? έFΠΥώnζώ…gύΙ:RΏSVΌ˜ΡΪνΩύδοv{O]‚sίύήω*>™ϊ.ΓΕ €Ρζ ΠΩχœKL?ω{Αc|wΛοΦ3{ΰ+Y”)fΪ²Έkι‚_/‰ύ?˜Ή+–ΙO(rΤ·`\Ί.’ΙίkΖ›+θ;+«Ε €Νφ)τ\@+tΞί«6UNdιϊVΏ#XΈƒ΄j€z6π·‘Ϋ(0ύδ—Ά{`ύ§kC·QPšό‘β@}έγ˜:t€Ι/+~0u6­|Kͺ<4ω%έuŸΖόt[4ω%EέυζJπŽwAνrΊΪ/©κžΨ<ϋΓδυΎυβΡ~’Ίξ €‹Ÿx烑Ϋ@Λ~ΙDwΐXγ2π2ν"¬Ι/™ιΎ€2 hςK¦Ί3.~βIΰ”ΠmdLό$sέ£ΐ7B·‘]π“\to4š§·„n#eZφKnΊ;τΔρbΰρΠ­€D“_rΥέ0>u?π~Ί)AM~Ι]χΐhγr°LΆLΚ‰&ΏΡ°cγο»t7a]ν—`ŠΏ!HοΫi7¬^Ί•ι'ΏΥ[pμΰnlŽnv έΚvhςKp½s π΄eSχα4C·ς4ω₯z/Ζ7cώ~ έΚVhςKaτfΤ›cΈ?χ«–σ§ ~R(½cΝ³ 0! Η{₯pz;F›_Α8#pZφK!υή]€m~γτ•5ω₯°Κ#•/‚},NJ«±θ`-ϋ₯¨zΰ™F›ϋdNΥtΞ/…WΐΣF†N?θΟ¨‚–ύΚΓΥ£1–sRY“_ΊFy`dξ[ ^ΜKiDM~ι*εΊπl£‰σΰFΣC>uΚc[™ξ{m‡_%Φ?ιJ €ελΧ²fκpπ%m­eΏt­r_ؚ‘‘χ‚ lαӚόΥ[S«μΫEΐΒηψ”ς‘§S€­©7Α¦Κ«qΞέΖ'tΞ/=A+€ν©U†q;Ψq˟hΩ/=CЊZεΕxt>ψ+5ω₯—(ZU³>\@½Y†—’JI(DJLEJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJL Rb ‘Sˆ”˜@€Δ"%¦)1€H‰)DJL Rb ˆ@l=Yk:IENDB`‚rocq-9.2.0/ide/rocqide/Make000066400000000000000000000001131516144147600154610ustar00rootroot00000000000000interface.mli xmlprotocol.mli xmlprotocol.ml ide_slave.ml coqidetop.mllib rocq-9.2.0/ide/rocqide/config.mli000066400000000000000000000013211516144147600166330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list Util.String.Map.t -> unit val load_file : string -> string list Util.String.Map.t rocq-9.2.0/ide/rocqide/config_lexer.mll000066400000000000000000000043431516144147600200440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* s))::l) lexbuf } |ignore+ { List.rev l} and string = parse | '"' { Buffer.add_char string_buffer '"' } | '\\' '"' | _ { Buffer.add_string string_buffer (lexeme lexbuf); string lexbuf } | eof { eprintf "coqiderc: unterminated string\n@." } { let load_file f = let c = open_in f in let lb = from_channel c in let m = prefs Util.String.Map.empty lb in close_in c; m let print_file f m = let c = open_out f in let fmt = formatter_of_out_channel c in let rec print_list fmt = function | [] -> () | s :: sl -> fprintf fmt "%S@ %a" s print_list sl in Util.String.Map.iter (fun k s -> fprintf fmt "@[%s = %a@]@\n" k print_list s) m; fprintf fmt "@."; close_out c } rocq-9.2.0/ide/rocqide/coq-ssreflect.lang000066400000000000000000000252021516144147600203040ustar00rootroot00000000000000 *.v \(\* \*\)

Timings for foo.v

  1. foo.v.time1 (total time: 3s)
  2. foo.v.time2 (total time: 2.5s)
(* some comment *) (* other comment multiline *)
Definition a := 1.
Definition b := 2.
Definition c := 3.
(* hello *)
Definition d := 4.
(* end of file comment *)
rocq-9.2.0/test-suite/misc/bench-render/stderr1v3000066400000000000000000000001131516144147600216470ustar00rootroot00000000000000Mismatch between foo.v.time1 and foo.v.time3: different measurement counts rocq-9.2.0/test-suite/misc/bench-render/stderr1v4000066400000000000000000000000751516144147600216570ustar00rootroot00000000000000Mismatch between foo.v.time1 and foo.v.time4 (measurement 1) rocq-9.2.0/test-suite/misc/bug_14550.sh000077500000000000000000000001531516144147600174110ustar00rootroot00000000000000#!/usr/bin/env bash $coqc misc/bug_14550/bug_14550.v R=$? if [ $R == 0 ]; then exit 1 else exit 0 fi rocq-9.2.0/test-suite/misc/bug_14550/000077500000000000000000000000001516144147600170535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/bug_14550/bug_14550.v000066400000000000000000000001271516144147600205550ustar00rootroot00000000000000Require Import Corelib.Program.Tactics. Program Definition bar : exists n, n = 0 := _. rocq-9.2.0/test-suite/misc/bug_7393.v000066400000000000000000000001711516144147600171700ustar00rootroot00000000000000Goal forall x, x -> x. Proof. intros. match goal with | [ |- _ ] => idtac (* . From *) end. assumption. Qed. rocq-9.2.0/test-suite/misc/changelog.sh000077500000000000000000000013141516144147600200250ustar00rootroot00000000000000#!/usr/bin/env bash config=../tools/configure/configure.ml if ! [ -e "$config" ]; then echo "Could not find configure.ml" exit 1 fi if grep -q -F "is_a_released_version = true" "$config"; then : elif grep -q -F "is_a_released_version = false" "$config"; then echo "This is not a released version: nothing to test." exit 0 else echo "Could not find is_a_released_version setting" exit 1 fi for d in ../doc/changelog/*; do if [ -d "$d" ]; then files=("$d"/*.rst) if [ "${#files[@]}" != 1 ]; then echo "Fatal: unreleased changelog entries remain in ${d#../}/" echo "Include them in doc/sphinx/changes.rst and remove them from doc/changelog/" exit 1 fi fi done rocq-9.2.0/test-suite/misc/comment-lexing.sh000077500000000000000000000005361516144147600210310ustar00rootroot00000000000000#!/bin/sh set -ex export COQBIN=$BIN export PATH="$COQBIN:$PATH" diff() { command diff -a -u --strip-trailing-cr "$1" "$2" } cd misc/comment-lexing/ rm -rf _test mkdir _test cp test.v _test cd _test rocq c -q -d comment-lexing -beautify test.v > test.out.real 2>&1 diff ../test.out test.out.real diff ../test.v.beautified test.v.beautified rocq-9.2.0/test-suite/misc/comment-lexing/000077500000000000000000000000001516144147600204665ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/comment-lexing/test.out000066400000000000000000000011631516144147600221770ustar00rootroot00000000000000Debug: [comment-lexing] comment at chars 333-587: (** Pour démontrer [c0 = Rouge -> coul_suiv c0 = Vert], on suppose [c0 = Rouge] et on doit alors prouver [coul_suiv c0 = Vert] sous cette hypothèse supplémentaire ; lorsque l'on introduit une hypothèse, on lui donne un nom. *) Debug: [comment-lexing] comment at chars 603-639: (* /!\ CRASH ON THIS LINE /!\ *) Debug: [comment-lexing] comment at chars 642-814: (** Le raisonnement sous-jacent est : soit c0rou une preuve arbitraire (inconnue) de [c0 = Rouge], on peut s'en servir pour démontrer coul_suiv [c0 = Vert]. *) rocq-9.2.0/test-suite/misc/comment-lexing/test.v000066400000000000000000000015431516144147600216370ustar00rootroot00000000000000Inductive coulfeu : Set := | Vert : coulfeu | Orange : coulfeu | Rouge : coulfeu . Definition coul_suiv : coulfeu -> coulfeu := fun c => match c with | Vert => Orange | Orange => Rouge | Rouge => Vert end. Theorem th_crou_gen : forall c : coulfeu, c = Rouge -> coul_suiv c = Vert. Proof. intro c0. (** Pour démontrer [c0 = Rouge -> coul_suiv c0 = Vert], on suppose [c0 = Rouge] et on doit alors prouver [coul_suiv c0 = Vert] sous cette hypothèse supplémentaire ; lorsque l'on introduit une hypothèse, on lui donne un nom. *) intro c0rou. (* /!\ CRASH ON THIS LINE /!\ *) (** Le raisonnement sous-jacent est : soit c0rou une preuve arbitraire (inconnue) de [c0 = Rouge], on peut s'en servir pour démontrer coul_suiv [c0 = Vert]. *) rewrite c0rou. cbn [coul_suiv]. reflexivity. Qed. rocq-9.2.0/test-suite/misc/comment-lexing/test.v.beautified000066400000000000000000000015121516144147600237330ustar00rootroot00000000000000Inductive coulfeu : Set := | Vert : coulfeu | Orange : coulfeu | Rouge : coulfeu. Definition coul_suiv : coulfeu -> coulfeu := fun c => match c with | Vert => Orange | Orange => Rouge | Rouge => Vert end. Theorem th_crou_gen : forall c : coulfeu, c = Rouge -> coul_suiv c = Vert. Proof. intro c0. (** Pour démontrer [c0 = Rouge -> coul_suiv c0 = Vert], on suppose [c0 = Rouge] et on doit alors prouver [coul_suiv c0 = Vert] sous cette hypothèse supplémentaire ; lorsque l'on introduit une hypothèse, on lui donne un nom. *) intro c0rou. (* /!\ CRASH ON THIS LINE /!\ *) (** Le raisonnement sous-jacent est : soit c0rou une preuve arbitraire (inconnue) de [c0 = Rouge], on peut s'en servir pour démontrer coul_suiv [c0 = Vert]. *) rewrite c0rou. cbn[coul_suiv]. reflexivity. Qed. rocq-9.2.0/test-suite/misc/coq_environment.sh000077500000000000000000000026351516144147600213130ustar00rootroot00000000000000#!/usr/bin/env bash export COQBIN=$BIN export PATH=$COQBIN:$PATH set -e TMP=`mktemp -d` cd $TMP mkdir -p overridden/theories/Init/ mkdir overridden/plugins touch overridden/theories/Init/Prelude.vo cat > coq_environment.txt < /dev/null N=`grep COQMF_OCAMLFIND CoqMakefile.conf | grep /overridden | wc -l` if [ $N -ne 1 ]; then echo COQMF_OCAMLFIND not overridden by coq_environment cat CoqMakefile.conf exit 1 fi mkdir -p overridden2/theories/Init/ mkdir overridden2/plugins touch overridden2/theories/Init/Prelude.vo export ROCQLIB="$PWD/overridden2" N=`./rocq c -config | grep COQLIB | grep overridden2 | wc -l` if [ $N -ne 1 ]; then echo ROCQLIB not overridden by ROCQLIB when coq_environment present rocq -config exit 1 fi rm -rf $TMP exit 0 rocq-9.2.0/test-suite/misc/coq_makefile_destination_of.sh000077500000000000000000000010401516144147600235760ustar00rootroot00000000000000#!/usr/bin/env bash export COQBIN=$BIN export PATH=$COQBIN:$PATH TMP=`mktemp -d` cd $TMP function assert_eq() { if [ "$1" != "$2" ]; then echo "rocq makefile generates destination $1 != $2" cd / rm -rf "$TMP" exit 1 fi } assert_eq `rocq makefile -destination-of src/Y/Z/Test.v -Q src X` "X//Y/Z" mkdir src assert_eq `rocq makefile -destination-of src/Y/Z/Test.v -Q src X` "X//Y/Z" mkdir -p src/Y/Z touch src/Y/Z/Test.v assert_eq `rocq makefile -destination-of src/Y/Z/Test.v -Q src X` "X//Y/Z" cd / rm -rf "$TMP" exit 0 rocq-9.2.0/test-suite/misc/coqc_cmdline.v000066400000000000000000000000251516144147600203440ustar00rootroot00000000000000Definition x := nat. rocq-9.2.0/test-suite/misc/coqc_dash_o.sh000077500000000000000000000003641516144147600203440ustar00rootroot00000000000000#!/usr/bin/env bash DOUT=misc/tmp_coqc_cmdline/ OUT=${DOUT}coqc_cmdline.vo mkdir -p "${DOUT}" rm -f "${OUT}" $coqc misc/coqc_cmdline.v -o "${OUT}" if [ ! -f "${OUT}" ]; then printf "coqc -o not working" exit 1 fi rm -fr "${DOUT}" exit 0 rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories.sh000077500000000000000000000003251516144147600244320ustar00rootroot00000000000000#!/usr/bin/env bash set -e cd misc/coqdep-require-filter-categories code=0 $coqdep -worker @ROCQWORKER@ -R . 'Bla' ./*.v > stdout 2> stderr || code=$? diff stdout.ref stdout diff stderr.ref stderr exit $code rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/000077500000000000000000000000001516144147600240735ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fA.v000066400000000000000000000000631516144147600246070ustar00rootroot00000000000000Require Import Prelude(something(..)) nonexistent. rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fB.v000066400000000000000000000000351516144147600246070ustar00rootroot00000000000000Require Import(bla) fA(bli). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fC.v000066400000000000000000000000431516144147600246070ustar00rootroot00000000000000Require Export (blo) fB (blu.blu). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fD.v000066400000000000000000000000371516144147600246130ustar00rootroot00000000000000Require Import -(bla) fA(bli). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fE.v000066400000000000000000000000361516144147600246130ustar00rootroot00000000000000Require Import-(bla) fA(bli). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fF.v000066400000000000000000000000401516144147600246070ustar00rootroot00000000000000Require Import - (bla) fA(bli). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/fG.v000066400000000000000000000000371516144147600246160ustar00rootroot00000000000000Require Import- (bla) fA(bli). rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/stderr.ref000066400000000000000000000002271516144147600260750ustar00rootroot00000000000000Warning: in file fA.v, library nonexistent is required and has not been found in the loadpath! [module-not-found,filesystem,default] rocq-9.2.0/test-suite/misc/coqdep-require-filter-categories/stdout.ref000066400000000000000000000007441516144147600261200ustar00rootroot00000000000000fA.vo fA.glob fA.v.beautified fA.required_vo: fA.v @ROCQWORKER@ fB.vo fB.glob fB.v.beautified fB.required_vo: fB.v fA.vo @ROCQWORKER@ fC.vo fC.glob fC.v.beautified fC.required_vo: fC.v fB.vo @ROCQWORKER@ fD.vo fD.glob fD.v.beautified fD.required_vo: fD.v fA.vo @ROCQWORKER@ fE.vo fE.glob fE.v.beautified fE.required_vo: fE.v fA.vo @ROCQWORKER@ fF.vo fF.glob fF.v.beautified fF.required_vo: fF.v fA.vo @ROCQWORKER@ fG.vo fG.glob fG.v.beautified fG.required_vo: fG.v fA.vo @ROCQWORKER@ rocq-9.2.0/test-suite/misc/coqdoc-options.sh000077500000000000000000000003461516144147600210430ustar00rootroot00000000000000#!/usr/bin/env bash set -e export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/coqdoc-options/ rocq makefile -f _CoqProject -o Makefile make clean make html diff -u --strip-trailing-cr html/Coqdoc.test.html 15933.html.out rocq-9.2.0/test-suite/misc/coqdoc-options/000077500000000000000000000000001516144147600205015ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/coqdoc-options/15933.html.out000066400000000000000000000245371516144147600226740ustar00rootroot00000000000000 Coqdoc.test

Library Coqdoc.test

Class C := {}.

Global Declare Instance I0 : C.
Local Declare Instance I1 : C.
Global Polymorphic Declare Instance I3 : C.
Polymorphic Global Declare Instance I4 : C.
Local Polymorphic Declare Instance I5 : C.
Polymorphic Local Declare Instance I6 : C.

Global Program Instance I7 : C := {}.
Local Program Instance I8 : C := {}.
Program Global Instance I9 : C := {}.
Program Local Instance I10 : C := {}.

Polymorphic Program Global Instance I11 : C := {}.
Polymorphic Program Local Instance I12 : C := {}.
Program Global Polymorphic Instance I13 : C := {}.
Program Local Polymorphic Instance I14 : C := {}.
Global Program Polymorphic Instance I15 : C := {}.
Local Program Polymorphic Instance I16 : C := {}.

Global Notation x0 := 0.
Local Notation x1 := 0.

Global Definition x2 := 0.
Local Definition x3 := 0.
Polymorphic Definition x4 := 0.
Polymorphic Global Definition x5 := 0.
Polymorphic Local Definition x6 := 0.
Global Polymorphic Definition x7 := 0.
Local Polymorphic Definition x8 := 0.

Polymorphic Inductive y0 := z0.
Polymorphic Variant y1 := z1.

Local Obligation Tactic := auto.
Global Obligation Tactic := auto.

Global Typeclasses Opaque I7.
Local Typeclasses Opaque I8.

Global Hint Extern 10 (_ ≀ _) β‡’ auto : arith.
Local Hint Extern 10 (_ ≀ _) β‡’ auto : arith.

Global Ltac lt0 := auto.
Local Ltac lt1 := auto.

Require Corelib.Program.Tactics.

Global Program Definition x9 := 0.
Local Program Definition x10 := 0.
Program Global Definition x11 := 0.
Program Local Definition x12 := 0.

Polymorphic Program Global Definition x13 := 0.
Polymorphic Program Local Definition x14 := 0.
Program Global Polymorphic Definition x15 := 0.
Program Local Polymorphic Definition x16 := 0.
Global Program Polymorphic Definition x17 := 0.
Local Program Polymorphic Definition x18 := 0.
rocq-9.2.0/test-suite/misc/coqdoc-options/_CoqProject000066400000000000000000000001731516144147600226350ustar00rootroot00000000000000-R theories Coqdoc COQDOCFLAGS = "--index indexpage -g -coqlib_url http://rocq-prover.org/stdlib --utf8" theories/test.v rocq-9.2.0/test-suite/misc/coqdoc-options/theories/000077500000000000000000000000001516144147600223235ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/coqdoc-options/theories/test.v000066400000000000000000000034061516144147600234740ustar00rootroot00000000000000Class C := {}. Global Declare Instance I0 : C. Local Declare Instance I1 : C. Global Polymorphic Declare Instance I3 : C. Polymorphic Global Declare Instance I4 : C. Local Polymorphic Declare Instance I5 : C. Polymorphic Local Declare Instance I6 : C. Global Program Instance I7 : C := {}. Local Program Instance I8 : C := {}. Program Global Instance I9 : C := {}. Program Local Instance I10 : C := {}. Polymorphic Program Global Instance I11 : C := {}. Polymorphic Program Local Instance I12 : C := {}. Program Global Polymorphic Instance I13 : C := {}. Program Local Polymorphic Instance I14 : C := {}. Global Program Polymorphic Instance I15 : C := {}. Local Program Polymorphic Instance I16 : C := {}. Global Notation x0 := 0. Local Notation x1 := 0. Global Definition x2 := 0. Local Definition x3 := 0. Polymorphic Definition x4 := 0. Polymorphic Global Definition x5 := 0. Polymorphic Local Definition x6 := 0. Global Polymorphic Definition x7 := 0. Local Polymorphic Definition x8 := 0. Polymorphic Inductive y0 := z0. Polymorphic Variant y1 := z1. Local Obligation Tactic := auto. Global Obligation Tactic := auto. Global Typeclasses Opaque I7. Local Typeclasses Opaque I8. Global Hint Extern 10 (_ <= _) => auto : arith. Local Hint Extern 10 (_ <= _) => auto : arith. Global Ltac lt0 := auto. Local Ltac lt1 := auto. Require Corelib.Program.Tactics. Global Program Definition x9 := 0. Local Program Definition x10 := 0. Program Global Definition x11 := 0. Program Local Definition x12 := 0. Polymorphic Program Global Definition x13 := 0. Polymorphic Program Local Definition x14 := 0. Program Global Polymorphic Definition x15 := 0. Program Local Polymorphic Definition x16 := 0. Global Program Polymorphic Definition x17 := 0. Local Program Polymorphic Definition x18 := 0. rocq-9.2.0/test-suite/misc/coqtop_print-mod-uid.sh000077500000000000000000000002511516144147600221520ustar00rootroot00000000000000#!/usr/bin/env bash export COQBIN=$BIN export PATH=$COQBIN:$PATH [ "$(rocq repl -print-mod-uid prerequisite/admit.vo)" = "prerequisite/.coq-native/NTestSuite_admit" ] rocq-9.2.0/test-suite/misc/deps-checksum.sh000077500000000000000000000003701516144147600206320ustar00rootroot00000000000000#!/bin/sh 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 mv misc/deps/A/A.vo misc/deps/B/A.vo $coqc -R misc/deps/B A misc/deps/checksum.v rocq-9.2.0/test-suite/misc/deps-order-distinct-root.sh000077500000000000000000000023641516144147600227500ustar00rootroot00000000000000#!/usr/bin/env bash # Check that both coqdep and coqtop/coqc support -R # Check that both coqdep and coqtop/coqc takes -R preferably to installed $ROCQPATH # See also bugs #2242, #2337, #2339 set -ex export PATH=$BIN:$PATH cd misc/deps/DistinctRoot rm -rf _test mkdir _test find . -maxdepth 1 -not -name . -not -name _test -exec cp -r '{}' -t _test ';' cd _test if ! rocq dep -worker @ROCQWORKER@ -R A A -R B B A/File1.v A/File11.v B/File1.v File2.v > coqdep1.real 2>&1; then cat coqdep1.real exit 1 fi diff -u --strip-trailing-cr coqdep1.out coqdep1.real || true touch A/File1.vo # bad vo, must not be loaded rocq c -R A A -R B B A/File11.v rocq c -R A A -R B B B/File1.v # now test with A "installed" mkdir install cp -r A install/A export ROCQPATH=install if ! rocq dep -worker @ROCQWORKER@ -R B B B/File1.v File2.v > coqdep2.real 2>&1; then cat coqdep2.real exit 1 fi diff -u --strip-trailing-cr coqdep2.out coqdep2.real rocq c -R B B File2.v rm A/File1.vo if ! rocq dep -worker @ROCQWORKER@ -R A A -R B B A/File1.v A/File11.v B/File1.v File2.v > coqdep3.real 2>&1; then cat coqdep3.real exit 1 fi # reuse coqdep1.out: output should be same as first rocq dep run diff -u --strip-trailing-cr coqdep1.out coqdep3.real rocq c -R A A -R B B File2.v rocq-9.2.0/test-suite/misc/deps-order-from.sh000077500000000000000000000015251516144147600211070ustar00rootroot00000000000000#!/bin/sh # Check that both coqdep and coqtop/coqc support -R # Check that both coqdep and coqtop/coqc take the latter -R # See bugs #11631, #14539 rm -f misc/deps/test-from/A/C.vo misc/deps/test-from/B/C.vo misc/deps/test-from/D.vo misc/deps/test-from/E.vo output=misc/deps/deps-from.real $coqdep -worker @ROCQWORKER@ -R misc/deps/test-from T misc/deps/test-from/D.v misc/deps/test-from/E.v > "$output" 2>&1 diff -u --strip-trailing-cr misc/deps/deps-from.out "$output" R=$? times $coqc -R misc/deps/test-from T misc/deps/test-from/A/C.v $coqc -R misc/deps/test-from T misc/deps/test-from/B/C.v $coqc -R misc/deps/test-from T misc/deps/test-from/D.v $coqc -R misc/deps/test-from T misc/deps/test-from/E.v S=$? if [ $R = 0 ] && [ $S = 0 ]; then printf "coqdep and coqc agree\n" exit 0 else printf "coqdep and coqc disagree.\n" exit 1 fi rocq-9.2.0/test-suite/misc/deps-order-subdir1-file.sh000077500000000000000000000022131516144147600224250ustar00rootroot00000000000000#!/bin/sh # Check that both coqdep and coqtop/coqc takes a file matching exactly # the logical path (if any) rm -f misc/deps/Theory1/*.vo misc/deps/Theory1/Subtheory?/*.vo misc/deps/Theory1/Subtheory?/Subsubtheory?/*.vo output=misc/deps/Theory1Deps.real (cd misc/deps; $coqdep -worker @ROCQWORKER@ -f _CoqTheory1Project) > "$output" 2>&1 diff -u --strip-trailing-cr misc/deps/Theory1Deps.out "$output" R=$? times $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory1/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory1/Subsubtheory1/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory1/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory2/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory2/Subsubtheory1/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/Subtheory2/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory1 Theory misc/deps/Theory1/File2.v S=$? if [ $R = 0 ] && [ $S = 0 ]; then printf "coqdep and coqc agree.\n" exit 0 else printf "coqdep and coqc disagree.\n" exit 1 fi rocq-9.2.0/test-suite/misc/deps-order-subdir2-file.sh000077500000000000000000000024661516144147600224400ustar00rootroot00000000000000#!/bin/sh # Check that coqtop/coqc and coqdep behave the same in the presence of ambiguity # over child and sibling directories # Same test as deps-order-subdir1-file.sh but without Theory1/File1.v # This test is platform-dependent, we renounce to it dotest=true if [ $dotest = false ]; then exit 0; fi rm -f misc/deps/Theory2/*.vo misc/deps/Theory2/Subtheory?/*.vo misc/deps/Theory2/Subtheory?/Subsubtheory?/*.vo output=misc/deps/Theory2Deps.real (cd misc/deps; $coqdep -worker @ROCQWORKER@ -f _CoqTheory2Project) > "$output" 2>&1 diff -u --strip-trailing-cr misc/deps/Theory2Deps.out $output R=$? if [ $R != 0 ]; then printf "Unexpected coqdep result.\n" exit 1 fi times $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory1/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory1/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory1/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory2/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory2/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/Subtheory2/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory2 Theory misc/deps/Theory2/File2.v S=$? if [ $S = 0 ]; then printf "Unexpected coqc success.\n" exit 1 fi printf "coqdep and coqc ok.\n" rocq-9.2.0/test-suite/misc/deps-order-subdir3-file.sh000077500000000000000000000023501516144147600224310ustar00rootroot00000000000000#!/bin/sh # Check that coqtop/coqc and coqdep behave the same in the presence of ambiguity # over child and sibling directories # Same test as deps-order-subdir2-file.sh but without Subtheory2/Subsubtheory? # so that it checks what comes first between siblings and (non immediate) children # This test is platform-dependent, we renounce to it dotest=true if [ $dotest = false ]; then exit 0; fi rm -f misc/deps/Theory3/*.vo misc/deps/Theory3/Subtheory?/*.vo misc/deps/Theory3/Subtheory?/Subsubtheory?/*.vo output=misc/deps/Theory3Deps.real (cd misc/deps; $coqdep -worker @ROCQWORKER@ -f _CoqTheory3Project) > "$output" 2>&1 diff -u --strip-trailing-cr misc/deps/Theory3Deps.out $output R=$? if [ $R != 0 ]; then printf "Unexpected coqdep result.\n" exit 1 fi times $coqc -Q misc/deps/Theory3 Theory misc/deps/Theory3/Subtheory1/File1.v $coqc -Q misc/deps/Theory3 Theory misc/deps/Theory3/Subtheory1/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory3 Theory misc/deps/Theory3/Subtheory1/Subsubtheory2/File1.v $coqc -Q misc/deps/Theory3 Theory misc/deps/Theory3/Subtheory2/File1.v $coqc -Q misc/deps/Theory3 Theory misc/deps/Theory3/File2.v S=$? if [ $S = 0 ]; then printf "Unexpected coqc success.\n" exit 1 fi printf "coqdep and coqc ok.\n" rocq-9.2.0/test-suite/misc/deps-order.sh000077500000000000000000000014631516144147600201470ustar00rootroot00000000000000#!/bin/sh # Check that both coqdep and coqtop/coqc supports -R # Check that both coqdep and coqtop/coqc takes -R preferably to installed $ROCQPATH # See bugs 2242, 2337, 2339 rm -f misc/deps/lib/*.vo misc/deps/client/*.vo output=misc/deps/deps.real $coqdep -worker @ROCQWORKER@ -R misc/deps/lib lib -R misc/deps/client client misc/deps/client/bar.v 2>&1 | head -n 1 > "$output" diff -u --strip-trailing-cr misc/deps/deps.out "$output" 2>&1 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 export ROCQPATH=misc/deps $coqc -R misc/deps/client client misc/deps/client/bar.v 2>&1 S=$? if [ $R = 0 ] && [ $S = 0 ]; then printf "coqdep and coqc agree\n" exit 0 else printf "coqdep and coqc disagree\n" exit 1 fi rocq-9.2.0/test-suite/misc/deps-utf8.sh000077500000000000000000000006571516144147600177260ustar00rootroot00000000000000#!/bin/sh # Check reading directories matching non pure ascii idents # See bug #5715 (utf-8 working on macos X and linux) # Windows is still not compliant a=$(uname) if [ "$a" = "Darwin" ] || [ "$a" = "Linux" ]; then rm -f misc/deps/thΓ©orΓ¨mes/*.v $coqc -R misc/deps AlphaBΓͺta misc/deps/Ξ±Ξ²/Ξ³Ξ΄.v R=$? $coqc -R misc/deps AlphaBΓͺta misc/deps/Ξ±Ξ²/Ρ΢.v S=$? if [ $R = 0 ] && [ $S = 0 ]; then exit 0 else exit 1 fi fi rocq-9.2.0/test-suite/misc/deps/000077500000000000000000000000001516144147600164735ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/A/000077500000000000000000000000001516144147600166535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/A/A.v000066400000000000000000000000261516144147600172200ustar00rootroot00000000000000Definition b := true. rocq-9.2.0/test-suite/misc/deps/B/000077500000000000000000000000001516144147600166545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/B/A.v000066400000000000000000000000271516144147600172220ustar00rootroot00000000000000Definition b := false. rocq-9.2.0/test-suite/misc/deps/B/B.v000066400000000000000000000001211516144147600172160ustar00rootroot00000000000000Require A. Definition c := A.b. Lemma foo : c = false. Proof. reflexivity. Qed. rocq-9.2.0/test-suite/misc/deps/DistinctRoot/000077500000000000000000000000001516144147600211205ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/A/000077500000000000000000000000001516144147600213005ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/A/File1.v000066400000000000000000000000001516144147600224150ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/A/File11.v000066400000000000000000000000001516144147600224760ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/A/OtherFile.txt000066400000000000000000000000001516144147600237100ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/B/000077500000000000000000000000001516144147600213015ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/B/File1.v000066400000000000000000000000001516144147600224160ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/DistinctRoot/File2.v000066400000000000000000000001171516144147600222470ustar00rootroot00000000000000Require File1. From A Require File11. From A Extra Dependency "OtherFile.txt". rocq-9.2.0/test-suite/misc/deps/DistinctRoot/coqdep1.out000066400000000000000000000006061516144147600232070ustar00rootroot00000000000000A/File1.vo A/File1.glob A/File1.v.beautified A/File1.required_vo: A/File1.v @ROCQWORKER@ A/File11.vo A/File11.glob A/File11.v.beautified A/File11.required_vo: A/File11.v @ROCQWORKER@ B/File1.vo B/File1.glob B/File1.v.beautified B/File1.required_vo: B/File1.v @ROCQWORKER@ File2.vo File2.glob File2.v.beautified File2.required_vo: File2.v A/File11.vo B/File1.vo @ROCQWORKER@ A/OtherFile.txt rocq-9.2.0/test-suite/misc/deps/DistinctRoot/coqdep2.out000066400000000000000000000002631516144147600232070ustar00rootroot00000000000000B/File1.vo B/File1.glob B/File1.v.beautified B/File1.required_vo: B/File1.v @ROCQWORKER@ File2.vo File2.glob File2.v.beautified File2.required_vo: File2.v B/File1.vo @ROCQWORKER@ rocq-9.2.0/test-suite/misc/deps/Theory1/000077500000000000000000000000001516144147600200265ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/File1.v000066400000000000000000000000231516144147600211500ustar00rootroot00000000000000Definition a := 0. rocq-9.2.0/test-suite/misc/deps/Theory1/File2.v000066400000000000000000000000701516144147600211530ustar00rootroot00000000000000From Theory Require File1. Check eq_refl : File1.a = 0. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/000077500000000000000000000000001516144147600220735ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/File1.v000066400000000000000000000000231516144147600232150ustar00rootroot00000000000000Definition a := 1. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/Subsubtheory1/000077500000000000000000000000001516144147600246525ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/Subsubtheory1/File1.v000066400000000000000000000000241516144147600257750ustar00rootroot00000000000000Definition a := 11. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/Subsubtheory2/000077500000000000000000000000001516144147600246535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory1/Subsubtheory2/File1.v000066400000000000000000000000241516144147600257760ustar00rootroot00000000000000Definition a := 12. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/000077500000000000000000000000001516144147600220745ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/File1.v000066400000000000000000000000231516144147600232160ustar00rootroot00000000000000Definition a := 2. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/Subsubtheory1/000077500000000000000000000000001516144147600246535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/Subsubtheory1/File1.v000066400000000000000000000000241516144147600257760ustar00rootroot00000000000000Definition a := 21. rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/Subsubtheory2/000077500000000000000000000000001516144147600246545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory1/Subtheory2/Subsubtheory2/File1.v000066400000000000000000000000241516144147600257770ustar00rootroot00000000000000Definition a := 22. rocq-9.2.0/test-suite/misc/deps/Theory1Deps.out000066400000000000000000000030531516144147600213740ustar00rootroot00000000000000Theory1/File1.vo Theory1/File1.glob Theory1/File1.v.beautified Theory1/File1.required_vo: Theory1/File1.v @ROCQWORKER@ Theory1/File2.vo Theory1/File2.glob Theory1/File2.v.beautified Theory1/File2.required_vo: Theory1/File2.v Theory1/File1.vo @ROCQWORKER@ Theory1/Subtheory1/File1.vo Theory1/Subtheory1/File1.glob Theory1/Subtheory1/File1.v.beautified Theory1/Subtheory1/File1.required_vo: Theory1/Subtheory1/File1.v @ROCQWORKER@ Theory1/Subtheory1/Subsubtheory1/File1.vo Theory1/Subtheory1/Subsubtheory1/File1.glob Theory1/Subtheory1/Subsubtheory1/File1.v.beautified Theory1/Subtheory1/Subsubtheory1/File1.required_vo: Theory1/Subtheory1/Subsubtheory1/File1.v @ROCQWORKER@ Theory1/Subtheory1/Subsubtheory2/File1.vo Theory1/Subtheory1/Subsubtheory2/File1.glob Theory1/Subtheory1/Subsubtheory2/File1.v.beautified Theory1/Subtheory1/Subsubtheory2/File1.required_vo: Theory1/Subtheory1/Subsubtheory2/File1.v @ROCQWORKER@ Theory1/Subtheory2/File1.vo Theory1/Subtheory2/File1.glob Theory1/Subtheory2/File1.v.beautified Theory1/Subtheory2/File1.required_vo: Theory1/Subtheory2/File1.v @ROCQWORKER@ Theory1/Subtheory2/Subsubtheory1/File1.vo Theory1/Subtheory2/Subsubtheory1/File1.glob Theory1/Subtheory2/Subsubtheory1/File1.v.beautified Theory1/Subtheory2/Subsubtheory1/File1.required_vo: Theory1/Subtheory2/Subsubtheory1/File1.v @ROCQWORKER@ Theory1/Subtheory2/Subsubtheory2/File1.vo Theory1/Subtheory2/Subsubtheory2/File1.glob Theory1/Subtheory2/Subsubtheory2/File1.v.beautified Theory1/Subtheory2/Subsubtheory2/File1.required_vo: Theory1/Subtheory2/Subsubtheory2/File1.v @ROCQWORKER@ rocq-9.2.0/test-suite/misc/deps/Theory2/000077500000000000000000000000001516144147600200275ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/File2.v000066400000000000000000000000701516144147600211540ustar00rootroot00000000000000From Theory Require File1. Check eq_refl : File1.a = 1. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/000077500000000000000000000000001516144147600220745ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/File1.v000066400000000000000000000000231516144147600232160ustar00rootroot00000000000000Definition a := 1. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/Subsubtheory1/000077500000000000000000000000001516144147600246535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/Subsubtheory1/File1.v000066400000000000000000000000241516144147600257760ustar00rootroot00000000000000Definition a := 11. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/Subsubtheory2/000077500000000000000000000000001516144147600246545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory1/Subsubtheory2/File1.v000066400000000000000000000000241516144147600257770ustar00rootroot00000000000000Definition a := 12. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/000077500000000000000000000000001516144147600220755ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/File1.v000066400000000000000000000000231516144147600232170ustar00rootroot00000000000000Definition a := 2. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/Subsubtheory1/000077500000000000000000000000001516144147600246545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/Subsubtheory1/File1.v000066400000000000000000000000241516144147600257770ustar00rootroot00000000000000Definition a := 21. rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/Subsubtheory2/000077500000000000000000000000001516144147600246555ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory2/Subtheory2/Subsubtheory2/File1.v000066400000000000000000000000241516144147600260000ustar00rootroot00000000000000Definition a := 22. rocq-9.2.0/test-suite/misc/deps/Theory2Deps.out000066400000000000000000000037001516144147600213740ustar00rootroot00000000000000Theory2/File2.vo Theory2/File2.glob Theory2/File2.v.beautified Theory2/File2.required_vo: Theory2/File2.v Theory2/Subtheory1/File1.vo Theory2/Subtheory1/Subsubtheory1/File1.vo Theory2/Subtheory1/Subsubtheory2/File1.vo Theory2/Subtheory2/File1.vo Theory2/Subtheory2/Subsubtheory1/File1.vo Theory2/Subtheory2/Subsubtheory2/File1.vo @ROCQWORKER@ Theory2/Subtheory1/File1.vo Theory2/Subtheory1/File1.glob Theory2/Subtheory1/File1.v.beautified Theory2/Subtheory1/File1.required_vo: Theory2/Subtheory1/File1.v @ROCQWORKER@ Theory2/Subtheory1/Subsubtheory1/File1.vo Theory2/Subtheory1/Subsubtheory1/File1.glob Theory2/Subtheory1/Subsubtheory1/File1.v.beautified Theory2/Subtheory1/Subsubtheory1/File1.required_vo: Theory2/Subtheory1/Subsubtheory1/File1.v @ROCQWORKER@ Theory2/Subtheory1/Subsubtheory2/File1.vo Theory2/Subtheory1/Subsubtheory2/File1.glob Theory2/Subtheory1/Subsubtheory2/File1.v.beautified Theory2/Subtheory1/Subsubtheory2/File1.required_vo: Theory2/Subtheory1/Subsubtheory2/File1.v @ROCQWORKER@ Theory2/Subtheory2/File1.vo Theory2/Subtheory2/File1.glob Theory2/Subtheory2/File1.v.beautified Theory2/Subtheory2/File1.required_vo: Theory2/Subtheory2/File1.v @ROCQWORKER@ Theory2/Subtheory2/Subsubtheory1/File1.vo Theory2/Subtheory2/Subsubtheory1/File1.glob Theory2/Subtheory2/Subsubtheory1/File1.v.beautified Theory2/Subtheory2/Subsubtheory1/File1.required_vo: Theory2/Subtheory2/Subsubtheory1/File1.v @ROCQWORKER@ Theory2/Subtheory2/Subsubtheory2/File1.vo Theory2/Subtheory2/Subsubtheory2/File1.glob Theory2/Subtheory2/Subsubtheory2/File1.v.beautified Theory2/Subtheory2/Subsubtheory2/File1.required_vo: Theory2/Subtheory2/Subsubtheory2/File1.v @ROCQWORKER@ *** Warning: in file Theory2/File2.v, required library File1 matches several files in path (found File1.v in Theory2/Subtheory2/Subsubtheory2, Theory2/Subtheory2/Subsubtheory1, Theory2/Subtheory2, Theory2/Subtheory1/Subsubtheory2, Theory2/Subtheory1/Subsubtheory1 and Theory2/Subtheory1; Require will fail). rocq-9.2.0/test-suite/misc/deps/Theory3/000077500000000000000000000000001516144147600200305ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory3/File2.v000066400000000000000000000000701516144147600211550ustar00rootroot00000000000000From Theory Require File1. Check eq_refl : File1.a = 1. rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/000077500000000000000000000000001516144147600220755ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/File1.v000066400000000000000000000000231516144147600232170ustar00rootroot00000000000000Definition a := 1. rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/Subsubtheory1/000077500000000000000000000000001516144147600246545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/Subsubtheory1/File1.v000066400000000000000000000000241516144147600257770ustar00rootroot00000000000000Definition a := 11. rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/Subsubtheory2/000077500000000000000000000000001516144147600246555ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory1/Subsubtheory2/File1.v000066400000000000000000000000241516144147600260000ustar00rootroot00000000000000Definition a := 12. rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory2/000077500000000000000000000000001516144147600220765ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Theory3/Subtheory2/File1.v000066400000000000000000000000231516144147600232200ustar00rootroot00000000000000Definition a := 2. rocq-9.2.0/test-suite/misc/deps/Theory3Deps.out000066400000000000000000000025001516144147600213720ustar00rootroot00000000000000Theory3/File2.vo Theory3/File2.glob Theory3/File2.v.beautified Theory3/File2.required_vo: Theory3/File2.v Theory3/Subtheory1/File1.vo Theory3/Subtheory1/Subsubtheory1/File1.vo Theory3/Subtheory1/Subsubtheory2/File1.vo Theory3/Subtheory2/File1.vo @ROCQWORKER@ Theory3/Subtheory1/File1.vo Theory3/Subtheory1/File1.glob Theory3/Subtheory1/File1.v.beautified Theory3/Subtheory1/File1.required_vo: Theory3/Subtheory1/File1.v @ROCQWORKER@ Theory3/Subtheory1/Subsubtheory1/File1.vo Theory3/Subtheory1/Subsubtheory1/File1.glob Theory3/Subtheory1/Subsubtheory1/File1.v.beautified Theory3/Subtheory1/Subsubtheory1/File1.required_vo: Theory3/Subtheory1/Subsubtheory1/File1.v @ROCQWORKER@ Theory3/Subtheory1/Subsubtheory2/File1.vo Theory3/Subtheory1/Subsubtheory2/File1.glob Theory3/Subtheory1/Subsubtheory2/File1.v.beautified Theory3/Subtheory1/Subsubtheory2/File1.required_vo: Theory3/Subtheory1/Subsubtheory2/File1.v @ROCQWORKER@ Theory3/Subtheory2/File1.vo Theory3/Subtheory2/File1.glob Theory3/Subtheory2/File1.v.beautified Theory3/Subtheory2/File1.required_vo: Theory3/Subtheory2/File1.v @ROCQWORKER@ *** Warning: in file Theory3/File2.v, required library File1 matches several files in path (found File1.v in Theory3/Subtheory2, Theory3/Subtheory1/Subsubtheory2, Theory3/Subtheory1/Subsubtheory1 and Theory3/Subtheory1; Require will fail). rocq-9.2.0/test-suite/misc/deps/_CoqTheory1Project000066400000000000000000000004151516144147600221020ustar00rootroot00000000000000-Q Theory1/ Theory Theory1/File1.v Theory1/File2.v Theory1/Subtheory1/File1.v Theory1/Subtheory1/Subsubtheory1/File1.v Theory1/Subtheory1/Subsubtheory2/File1.v Theory1/Subtheory2/File1.v Theory1/Subtheory2/Subsubtheory1/File1.v Theory1/Subtheory2/Subsubtheory2/File1.v rocq-9.2.0/test-suite/misc/deps/_CoqTheory2Project000066400000000000000000000003751516144147600221100ustar00rootroot00000000000000-Q Theory2/ Theory Theory2/File2.v Theory2/Subtheory1/File1.v Theory2/Subtheory1/Subsubtheory1/File1.v Theory2/Subtheory1/Subsubtheory2/File1.v Theory2/Subtheory2/File1.v Theory2/Subtheory2/Subsubtheory1/File1.v Theory2/Subtheory2/Subsubtheory2/File1.v rocq-9.2.0/test-suite/misc/deps/_CoqTheory3Project000066400000000000000000000002531516144147600221040ustar00rootroot00000000000000-Q Theory3/ Theory Theory3/File2.v Theory3/Subtheory1/File1.v Theory3/Subtheory1/Subsubtheory1/File1.v Theory3/Subtheory1/Subsubtheory2/File1.v Theory3/Subtheory2/File1.v rocq-9.2.0/test-suite/misc/deps/checksum.v000066400000000000000000000000511516144147600204600ustar00rootroot00000000000000Require Import A. Fail Require Import B. rocq-9.2.0/test-suite/misc/deps/client/000077500000000000000000000000001516144147600177515ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/client/bar.v000066400000000000000000000003641516144147600207070ustar00rootroot00000000000000(* We assume the file compiled with -R ../lib lib -R . client *) (* foo alone should refer to client.foo because -R . client comes last *) Require Import foo. Goal a = 1. reflexivity. Qed. Require Import lib.foo. Goal a = 0. reflexivity. Qed. rocq-9.2.0/test-suite/misc/deps/client/foo.v000066400000000000000000000000231516144147600207160ustar00rootroot00000000000000Definition a := 1. rocq-9.2.0/test-suite/misc/deps/deps-from.out000066400000000000000000000005641516144147600211250ustar00rootroot00000000000000misc/deps/test-from/D.vo misc/deps/test-from/D.glob misc/deps/test-from/D.v.beautified misc/deps/test-from/D.required_vo: misc/deps/test-from/D.v misc/deps/test-from/A/C.vo @ROCQWORKER@ misc/deps/test-from/E.vo misc/deps/test-from/E.glob misc/deps/test-from/E.v.beautified misc/deps/test-from/E.required_vo: misc/deps/test-from/E.v misc/deps/test-from/B/C.vo @ROCQWORKER@ rocq-9.2.0/test-suite/misc/deps/deps.out000066400000000000000000000003071516144147600201570ustar00rootroot00000000000000misc/deps/client/bar.vo misc/deps/client/bar.glob misc/deps/client/bar.v.beautified misc/deps/client/bar.required_vo: misc/deps/client/bar.v misc/deps/client/foo.vo misc/deps/lib/foo.vo @ROCQWORKER@ rocq-9.2.0/test-suite/misc/deps/lib/000077500000000000000000000000001516144147600172415ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/lib/foo.v000066400000000000000000000000231516144147600202060ustar00rootroot00000000000000Definition a := 0. rocq-9.2.0/test-suite/misc/deps/test-from/000077500000000000000000000000001516144147600204135ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/test-from/A/000077500000000000000000000000001516144147600205735ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/test-from/A/C.v000066400000000000000000000000261516144147600211420ustar00rootroot00000000000000Definition c := true. rocq-9.2.0/test-suite/misc/deps/test-from/B/000077500000000000000000000000001516144147600205745ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/test-from/B/C.v000066400000000000000000000000271516144147600211440ustar00rootroot00000000000000Definition c := false. rocq-9.2.0/test-suite/misc/deps/test-from/D.v000066400000000000000000000002121516144147600207600ustar00rootroot00000000000000(* Assumed to be compiled with -R test-from T *) From T.A Require C. Definition c := C.c. Lemma foo : c = true. Proof. reflexivity. Qed. rocq-9.2.0/test-suite/misc/deps/test-from/E.v000066400000000000000000000002131516144147600207620ustar00rootroot00000000000000(* Assumed to be compiled with -R test-from T *) From T.B Require C. Definition c := C.c. Lemma foo : c = false. Proof. reflexivity. Qed. rocq-9.2.0/test-suite/misc/deps/Ξ±Ξ²/000077500000000000000000000000001516144147600201515ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/deps/Ξ±Ξ²/Ξ³Ξ΄.v000066400000000000000000000000651516144147600220230ustar00rootroot00000000000000Theorem simple : forall A, A -> A. Proof. auto. Qed. rocq-9.2.0/test-suite/misc/deps/Ξ±Ξ²/Ρ΢.v000066400000000000000000000000251516144147600220230ustar00rootroot00000000000000Require Import Ξ³Ξ΄. rocq-9.2.0/test-suite/misc/exitstatus.sh000077500000000000000000000002221516144147600203100ustar00rootroot00000000000000#!/bin/sh $coqc misc/exitstatus/illtyped.v P=$? printf "On ill-typed input, coqc returned %s.\n" "$P" if [ $P = 1 ]; then exit 0; else exit 1; fi rocq-9.2.0/test-suite/misc/exitstatus/000077500000000000000000000000001516144147600177555ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/exitstatus/illtyped.v000066400000000000000000000000131516144147600217640ustar00rootroot00000000000000Check S S. rocq-9.2.0/test-suite/misc/external-deps.sh000077500000000000000000000026431516144147600206570ustar00rootroot00000000000000#!/bin/sh set -e # Set Extra Dependency syntax output=misc/external-deps/file1.found.real $coqdep -worker @ROCQWORKER@ -Q misc/external-deps/deps foo.bar misc/external-deps/file1.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file1.found.deps $output output=misc/external-deps/file1.ambiguous.real $coqdep -worker @ROCQWORKER@ -Q misc/external-deps/deps foo.bar -Q misc/external-deps/more foo.bar misc/external-deps/file1.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file1.ambiguous.deps $output output=misc/external-deps/file1.notfound.real $coqdep -worker @ROCQWORKER@ misc/external-deps/file1.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file1.notfound.deps $output # From bla Extra Dependency syntax output=misc/external-deps/file2.found.real $coqdep -worker @ROCQWORKER@ -Q misc/external-deps/deps foo.bar misc/external-deps/file2.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file2.found.deps $output output=misc/external-deps/file2.ambiguous.real $coqdep -worker @ROCQWORKER@ -Q misc/external-deps/deps foo.bar -Q misc/external-deps/more foo.bar misc/external-deps/file2.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file2.ambiguous.deps $output output=misc/external-deps/file2.notfound.real $coqdep -worker @ROCQWORKER@ misc/external-deps/file2.v > $output 2>&1 diff -u --strip-trailing-cr misc/external-deps/file2.notfound.deps $output rocq-9.2.0/test-suite/misc/external-deps/000077500000000000000000000000001516144147600203135ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/external-deps/deps/000077500000000000000000000000001516144147600212465ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/external-deps/deps/d1000066400000000000000000000000001516144147600214630ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/external-deps/file1.ambiguous.deps000066400000000000000000000006271516144147600241670ustar00rootroot00000000000000misc/external-deps/file1.vo misc/external-deps/file1.glob misc/external-deps/file1.v.beautified misc/external-deps/file1.required_vo: misc/external-deps/file1.v @ROCQWORKER@ misc/external-deps/more/d1 *** Warning: in file misc/external-deps/file1.v, required external file d1 exactly matches several files in path (found d1 in misc/external-deps/deps and misc/external-deps/more; used the latter). rocq-9.2.0/test-suite/misc/external-deps/file1.found.deps000066400000000000000000000003111516144147600232750ustar00rootroot00000000000000misc/external-deps/file1.vo misc/external-deps/file1.glob misc/external-deps/file1.v.beautified misc/external-deps/file1.required_vo: misc/external-deps/file1.v @ROCQWORKER@ misc/external-deps/deps/d1 rocq-9.2.0/test-suite/misc/external-deps/file1.notfound.deps000066400000000000000000000005521516144147600240250ustar00rootroot00000000000000Warning: in file misc/external-deps/file1.v, external file d1 is required from root foo.bar and has not been found in the loadpath! [module-not-found,filesystem,default] misc/external-deps/file1.vo misc/external-deps/file1.glob misc/external-deps/file1.v.beautified misc/external-deps/file1.required_vo: misc/external-deps/file1.v @ROCQWORKER@ rocq-9.2.0/test-suite/misc/external-deps/file1.v000066400000000000000000000000551516144147600215020ustar00rootroot00000000000000Comments From foo.bar Extra Dependency "d1". rocq-9.2.0/test-suite/misc/external-deps/file2.ambiguous.deps000066400000000000000000000006271516144147600241700ustar00rootroot00000000000000misc/external-deps/file2.vo misc/external-deps/file2.glob misc/external-deps/file2.v.beautified misc/external-deps/file2.required_vo: misc/external-deps/file2.v @ROCQWORKER@ misc/external-deps/more/d1 *** Warning: in file misc/external-deps/file2.v, required external file d1 exactly matches several files in path (found d1 in misc/external-deps/deps and misc/external-deps/more; used the latter). rocq-9.2.0/test-suite/misc/external-deps/file2.found.deps000066400000000000000000000003111516144147600232760ustar00rootroot00000000000000misc/external-deps/file2.vo misc/external-deps/file2.glob misc/external-deps/file2.v.beautified misc/external-deps/file2.required_vo: misc/external-deps/file2.v @ROCQWORKER@ misc/external-deps/deps/d1 rocq-9.2.0/test-suite/misc/external-deps/file2.notfound.deps000066400000000000000000000005521516144147600240260ustar00rootroot00000000000000Warning: in file misc/external-deps/file2.v, external file d1 is required from root foo.bar and has not been found in the loadpath! [module-not-found,filesystem,default] misc/external-deps/file2.vo misc/external-deps/file2.glob misc/external-deps/file2.v.beautified misc/external-deps/file2.required_vo: misc/external-deps/file2.v @ROCQWORKER@ rocq-9.2.0/test-suite/misc/external-deps/file2.v000066400000000000000000000000441516144147600215010ustar00rootroot00000000000000From foo.bar Extra Dependency "d1". rocq-9.2.0/test-suite/misc/external-deps/more/000077500000000000000000000000001516144147600212555ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/external-deps/more/d1000066400000000000000000000000001516144147600214720ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/non-marshalable-state.sh000077500000000000000000000013111516144147600222540ustar00rootroot00000000000000#!/usr/bin/env bash set -ex export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/non-marshalable-state/ if which cygpath >/dev/null 2>&1; then OCAMLFINDSEP=\;; else OCAMLFINDSEP=:; fi rocq makefile -f _CoqProject -o Makefile make clean make src/evil_plugin.cmxs make src/good_plugin.cmxs if rocq c -async-proofs on -I src -Q theories Marshal theories/evil.v 2> log1 1>&2; then >&2 echo "evil.v should have failed with async proofs on" exit 1 fi if ! grep -q 'Marshalling error' log1; then >&2 echo "Missing expected error message in evil.v output" exit 1 fi rocq c -async-proofs off -I src -Q theories Marshal theories/evil.v rocq c -async-proofs on -I src -Q theories Marshal theories/good.v rocq-9.2.0/test-suite/misc/non-marshalable-state/000077500000000000000000000000001516144147600217215ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/non-marshalable-state/_CoqProject000066400000000000000000000002341516144147600240530ustar00rootroot00000000000000src/META.coq-test-suite -Q theories Marshal -I src src/evil.mlg src/good.mlg src/evil_plugin.mlpack src/good_plugin.mlpack theories/evil.v theories/good.v rocq-9.2.0/test-suite/misc/non-marshalable-state/src/000077500000000000000000000000001516144147600225105ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/non-marshalable-state/src/META.coq-test-suite000066400000000000000000000011431516144147600260450ustar00rootroot00000000000000package "evil" ( directory = "." version = "dev" description = "An evil test plugin" requires = "rocq-runtime.plugins.ltac" archive(byte) = "evil_plugin.cma" archive(native) = "evil_plugin.cmxa" plugin(byte) = "evil_plugin.cma" plugin(native) = "evil_plugin.cmxs" ) package "good" ( directory = "." version = "dev" description = "A good test plugin" requires = "rocq-runtime.plugins.ltac" archive(byte) = "good_plugin.cma" archive(native) = "good_plugin.cmxa" plugin(byte) = "good_plugin.cma" plugin(native) = "good_plugin.cmxs" ) directory = "." rocq-9.2.0/test-suite/misc/non-marshalable-state/src/evil.mlg000066400000000000000000000003251516144147600241500ustar00rootroot00000000000000DECLARE PLUGIN "coq-test-suite.evil" { let state = Summary.ref ~name:"elpi-compiler-cache" None } VERNAC COMMAND EXTEND magic CLASSIFIED AS SIDEFF | [ "magic" ] -> { state := Some (fun () -> ()) } END rocq-9.2.0/test-suite/misc/non-marshalable-state/src/evil_plugin.mlpack000066400000000000000000000000051516144147600262110ustar00rootroot00000000000000Evil rocq-9.2.0/test-suite/misc/non-marshalable-state/src/good.mlg000066400000000000000000000003411516144147600241370ustar00rootroot00000000000000DECLARE PLUGIN "coq-test-suite.good" { let state = Summary.ref ~local:true ~name:"elpi-compiler-cache" None } VERNAC COMMAND EXTEND magic CLASSIFIED AS SIDEFF | [ "magic" ] -> { state := Some (fun () -> ()) } END rocq-9.2.0/test-suite/misc/non-marshalable-state/src/good_plugin.mlpack000066400000000000000000000000051516144147600262020ustar00rootroot00000000000000Good rocq-9.2.0/test-suite/misc/non-marshalable-state/theories/000077500000000000000000000000001516144147600235435ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/non-marshalable-state/theories/evil.v000066400000000000000000000001271516144147600246710ustar00rootroot00000000000000Declare ML Module "coq-test-suite.evil". magic. Lemma x : True. Proof. trivial. Qed. rocq-9.2.0/test-suite/misc/non-marshalable-state/theories/good.v000066400000000000000000000001271516144147600246620ustar00rootroot00000000000000Declare ML Module "coq-test-suite.good". magic. Lemma x : True. Proof. trivial. Qed. rocq-9.2.0/test-suite/misc/poly-capture-global-univs.sh000077500000000000000000000003761516144147600231310ustar00rootroot00000000000000#!/usr/bin/env bash set -e export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/poly-capture-global-univs/ rocq makefile -f _CoqProject -o Makefile make clean make src/evil_plugin.cma if make; then >&2 echo 'Should have failed!' exit 1 fi rocq-9.2.0/test-suite/misc/poly-capture-global-univs/000077500000000000000000000000001516144147600225645ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/poly-capture-global-univs/_CoqProject000066400000000000000000000002031516144147600247120ustar00rootroot00000000000000META.coq-test-suite -Q theories Evil -I src src/evil.mlg src/evilImpl.ml src/evilImpl.mli src/evil_plugin.mlpack theories/evil.v rocq-9.2.0/test-suite/misc/poly-capture-global-univs/src/000077500000000000000000000000001516144147600233535ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/poly-capture-global-univs/src/evil.mlg000066400000000000000000000002641516144147600250150ustar00rootroot00000000000000{ open Stdarg open EvilImpl } DECLARE PLUGIN "rocq-runtime.plugins.evil" VERNAC COMMAND EXTEND VernacEvil CLASSIFIED AS SIDEFF | [ "Evil" ident(x) ident(y) ] -> { evil x y } END rocq-9.2.0/test-suite/misc/poly-capture-global-univs/src/evilImpl.ml000066400000000000000000000015431516144147600254710ustar00rootroot00000000000000open Names let evil name name_f = let open Univ in let open UVars in let open Constr in let kind = Decls.(IsDefinition Definition) in let u = Level.var 0 in let tu = mkType (Universe.make u) in let te = Declare.definition_entry ~univs:(UState.Monomorphic_entry (Univ.ContextSet.singleton u), UnivNames.empty_binders) tu in let tc = Declare.declare_constant ~name ~kind (Declare.DefinitionEntry te) in let tc = mkConst tc in let fe = Declare.definition_entry ~univs:(UState.Polymorphic_entry (UContext.make {quals = [||]; univs= [|Anonymous|]} (Instance.of_array ([||],[|u|]),PConstraints.empty)), UnivNames.empty_binders) ~types:(Term.mkArrowR tc tu) (mkLambda (Context.nameR (Id.of_string "x"), tc, mkRel 1)) in let _ : Constant.t = Declare.declare_constant ~name:name_f ~kind (Declare.DefinitionEntry fe) in () rocq-9.2.0/test-suite/misc/poly-capture-global-univs/src/evilImpl.mli000066400000000000000000000000551516144147600256370ustar00rootroot00000000000000 val evil : Names.Id.t -> Names.Id.t -> unit rocq-9.2.0/test-suite/misc/poly-capture-global-univs/src/evil_plugin.mlpack000066400000000000000000000000161516144147600270560ustar00rootroot00000000000000EvilImpl Evil rocq-9.2.0/test-suite/misc/poly-capture-global-univs/theories/000077500000000000000000000000001516144147600244065ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/poly-capture-global-univs/theories/evil.v000066400000000000000000000004011516144147600255270ustar00rootroot00000000000000 Declare ML Module "coq-test-suite.evil". Evil T f. (* <- if this doesn't fail then the rest goes through *) Definition g : Type -> Set := f. Require Import Hurkens. Lemma absurd : False. Proof. exact (TypeNeqSmallType.paradox (g Type) eq_refl). Qed. rocq-9.2.0/test-suite/misc/print-assumptions-vok.sh000077500000000000000000000006061516144147600224150ustar00rootroot00000000000000#!/bin/sh set -e # Use rocq c instead of $coqc to work in async mode export PATH="$BIN:$PATH" rocq c -R misc/print-assumptions-vok/ PrintAssumptionsVOK -vos misc/print-assumptions-vok/file1.v rocq c -R misc/print-assumptions-vok/ PrintAssumptionsVOK -vos misc/print-assumptions-vok/file2.v rocq c -R misc/print-assumptions-vok/ PrintAssumptionsVOK -vok misc/print-assumptions-vok/file2.v rocq-9.2.0/test-suite/misc/print-assumptions-vok/000077500000000000000000000000001516144147600220545ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/print-assumptions-vok/file1.v000066400000000000000000000001251516144147600232410ustar00rootroot00000000000000Lemma hidden : False. Proof. Admitted. Lemma aux : False. Proof. apply hidden. Qed. rocq-9.2.0/test-suite/misc/print-assumptions-vok/file2.v000066400000000000000000000002041516144147600232400ustar00rootroot00000000000000From PrintAssumptionsVOK Require file1. Lemma main : False. Proof. apply file1.aux. Qed. Print Assumptions main. (* this fails *) rocq-9.2.0/test-suite/misc/printers.sh000077500000000000000000000006111516144147600177430ustar00rootroot00000000000000#!/bin/sh f=$(mktemp) { printf 'Drop.\n#go;;\nQuit.\n' | "${BIN}rocq" repl-with-drop -q } 2>&1 | grep -a -v "Welcome to Rocq" | tee "$f" # if there's an issue in `include_utilities`, `#go;;` won't be mentioned # if there's an issue in `include_printers`, it will be an undefined printer if ! grep -q -F '#go;;' "$f" || grep -q -E -i 'Error|Unbound|Anomaly' "$f"; then exit 1; fi rocq-9.2.0/test-suite/misc/qed-time.sh000077500000000000000000000013501516144147600176030ustar00rootroot00000000000000#!/usr/bin/env bash set -ex export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/qed-time/ # This test checks that the Qed time includes the time of the replayed command # The version of this test in output-modulo-time checks that each # command gets 1 time line, but because output-modulo-time normalizes # times to 0 it can't check that the replayed command is not ignored rocq c -time file.v > out last=$(tail -n 1 out) last=${last#"Chars 98 - 102 [Qed.] "} last=${last%" secs"*} # sanity check: regex produces a float [[ $last =~ [0-9]+"."[0-9]* ]] test() { printf 'if %s <= 0.9:\n\texit (1)\n' "$1" | python3 } # sanity checks: python works on the code we produce if test 0.9; then exit 1; fi test 1. test 1.1 test "$last" rocq-9.2.0/test-suite/misc/qed-time/000077500000000000000000000000001516144147600172455ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/qed-time/file.v000066400000000000000000000001471516144147600203550ustar00rootroot00000000000000Lemma foo : True. Proof. Axiom X : ltac:(try timeout 1 repeat pose True; exact nat). exact I. Qed. rocq-9.2.0/test-suite/misc/quotation_token.sh000077500000000000000000000010561516144147600213240ustar00rootroot00000000000000#!/usr/bin/env bash set -e export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/quotation_token/ if which cygpath >/dev/null 2>&1; then OCAMLFINDSEP=\;; else OCAMLFINDSEP=:; fi rocq makefile -f _CoqProject -o Makefile make clean make src/quotation_plugin.cma TMP=output.txt rm -f $TMP if make > $TMP 2>&1; then echo "should fail" rm $TMP exit 1 fi if grep "File.*quotation.v., line 12, characters 6-30" $TMP; then exit 0 elif grep "File.*quotation.v" $TMP; then echo "wrong loc" exit 1 else echo "wrong error:" cat $TMP exit 1 fi rocq-9.2.0/test-suite/misc/quotation_token/000077500000000000000000000000001516144147600207635ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/quotation_token/META.coq-test-suite000066400000000000000000000005311516144147600243200ustar00rootroot00000000000000package "quotation" ( directory = "src" version = "dev" description = "A quotation test plugin" requires = "rocq-runtime.plugins.ltac" archive(byte) = "quotation_plugin.cma" archive(native) = "quotation_plugin.cmxa" plugin(byte) = "quotation_plugin.cma" plugin(native) = "quotation_plugin.cmxs" ) directory = "." rocq-9.2.0/test-suite/misc/quotation_token/_CoqProject000066400000000000000000000003251516144147600231160ustar00rootroot00000000000000META.coq-test-suite -Q theories Quotation # we need -I . so coqdep can find the META # and -I src so ocamllibdep finds the contents -I . -I src src/quotation.mlg src/quotation_plugin.mlpack theories/quotation.v rocq-9.2.0/test-suite/misc/quotation_token/src/000077500000000000000000000000001516144147600215525ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/quotation_token/src/quotation.mlg000066400000000000000000000003751516144147600243030ustar00rootroot00000000000000DECLARE PLUGIN "coq-test-suite.quotation" { open Procq.Constr } GRAMMAR EXTEND Gram GLOBAL: term; term: LEVEL "0" [ [ s = QUOTATION "foobar:" -> { CAst.make ~loc Constrexpr.(CSort Constrexpr_ops.expr_Prop_sort) } ] ] ; END rocq-9.2.0/test-suite/misc/quotation_token/src/quotation_plugin.mlpack000066400000000000000000000000121516144147600263350ustar00rootroot00000000000000Quotation rocq-9.2.0/test-suite/misc/quotation_token/theories/000077500000000000000000000000001516144147600226055ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/quotation_token/theories/quotation.v000066400000000000000000000002701516144147600250160ustar00rootroot00000000000000 Declare ML Module "coq-test-suite.quotation". Definition x := foobar:{{ hello there }}. Definition y := foobar:{{ another multi line thing }}. Check foobar:{{ oops ips }} y. rocq-9.2.0/test-suite/misc/redirect_printing.out000066400000000000000000000001461516144147600220050ustar00rootroot00000000000000nat_ind : forall P : nat -> Prop, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n rocq-9.2.0/test-suite/misc/redirect_printing.sh000077500000000000000000000001511516144147600216070ustar00rootroot00000000000000#!/usr/bin/env bash $coqc misc/redirect_printing.v diff -u redirect_test.out misc/redirect_printing.out rocq-9.2.0/test-suite/misc/redirect_printing.v000066400000000000000000000001031516144147600214340ustar00rootroot00000000000000Set Printing Width 999999. Redirect "redirect_test" Check nat_ind. rocq-9.2.0/test-suite/misc/side-eff-leak-univs.sh000077500000000000000000000003701516144147600216350ustar00rootroot00000000000000#!/usr/bin/env bash set -e export COQBIN=$BIN export PATH=$COQBIN:$PATH cd misc/side-eff-leak-univs/ rocq makefile -f _CoqProject -o Makefile make clean make src/evil_plugin.cma if make; then >&2 echo 'Should have failed!' exit 1 fi rocq-9.2.0/test-suite/misc/side-eff-leak-univs/000077500000000000000000000000001516144147600212765ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/side-eff-leak-univs/_CoqProject000066400000000000000000000001411516144147600234250ustar00rootroot00000000000000META.coq-test-suite -Q theories Evil -I src src/evil.mlg src/evil_plugin.mlpack theories/evil.v rocq-9.2.0/test-suite/misc/side-eff-leak-univs/src/000077500000000000000000000000001516144147600220655ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/side-eff-leak-univs/src/evil.mlg000066400000000000000000000005171516144147600235300ustar00rootroot00000000000000DECLARE PLUGIN "rocq-runtime.plugins.evil" { open Ltac_plugin open Stdarg } TACTIC EXTEND magic | [ "magic" ident(i) ident(j) ] -> { let open Constrexpr in DeclareUniv.do_constraint ~poly:false [ UnivCst (CType (Libnames.qualid_of_ident i), Univ.UnivConstraint.Lt, CType (Libnames.qualid_of_ident j))]; Proofview.tclUNIT() } END rocq-9.2.0/test-suite/misc/side-eff-leak-univs/src/evil_plugin.mlpack000066400000000000000000000000051516144147600255660ustar00rootroot00000000000000Evil rocq-9.2.0/test-suite/misc/side-eff-leak-univs/theories/000077500000000000000000000000001516144147600231205ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/side-eff-leak-univs/theories/evil.v000066400000000000000000000003061516144147600242450ustar00rootroot00000000000000Declare ML Module "coq-test-suite.evil". Universes i j. Lemma foo@{} : Type@{j}. Proof. magic i j; transparent_abstract exact_no_check Type@{i}. Defined. Definition bar : Type@{i} := Type@{j}. rocq-9.2.0/test-suite/misc/tc_declaration_observer.sh000077500000000000000000000003541516144147600227630ustar00rootroot00000000000000#!/usr/bin/env bash set -e export COQBIN="$BIN" export PATH="$BIN:$PATH" cd misc/tc_declaration_observer rocq makefile -f _CoqProject -o Makefile make clean rm -f main.out make diff -u --strip-trailing-cr main.out main.out.reference rocq-9.2.0/test-suite/misc/tc_declaration_observer/000077500000000000000000000000001516144147600224225ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/tc_declaration_observer/_CoqProject000066400000000000000000000001421516144147600245520ustar00rootroot00000000000000 -R . observer -I . observer_plugin.mlpack observer.ml -generate-meta-for-package observer main.v rocq-9.2.0/test-suite/misc/tc_declaration_observer/main.out.reference000066400000000000000000000001351516144147600260330ustar00rootroot00000000000000NewClass Def NewInstance def_nat NewInstance def_bool 33 NewInstance def_bool2 21 local rocq-9.2.0/test-suite/misc/tc_declaration_observer/main.v000066400000000000000000000004231516144147600235340ustar00rootroot00000000000000Declare ML Module "observer.plugin". Class Def (A : Type) := { default : A }. Instance def_nat : Def nat := {| default := 0 |}. Instance def_bool : Def bool | 33 := {| default := false |}. Section X. Instance def_bool2 : Def bool | 21 := {| default := false |}. End X. rocq-9.2.0/test-suite/misc/tc_declaration_observer/observer.ml000066400000000000000000000012021516144147600245760ustar00rootroot00000000000000 let o = open_out "main.out" let observe x = let open Classes in let open Event in let open Typeclasses in let open Hints in let p = Pp.string_of_ppcmds in match x with | NewClass { cl_impl } -> Printf.fprintf o "NewClass %s\n" (p (Printer.pr_global cl_impl)) | NewInstance { instance ; info = { hint_priority }; locality } -> Printf.fprintf o "NewInstance %s %s %s\n" (p (Printer.pr_global instance)) (p (Pp.pr_opt Pp.int hint_priority)) (if locality = Local then "local" else "") let obs = Classes.register_observer ~name:"test observer" observe let () = Classes.activate_observer obs rocq-9.2.0/test-suite/misc/tc_declaration_observer/observer_plugin.mlpack000066400000000000000000000000111516144147600270100ustar00rootroot00000000000000Observer rocq-9.2.0/test-suite/misc/universes.sh000077500000000000000000000007111516144147600201210ustar00rootroot00000000000000#!/bin/sh # Sort universes for the whole standard library EXPECTED_UNIVERSES=2 # Prop is not counted $coqc -R misc/universes Universes misc/universes/all_stdlib 2>&1 $coqc -R misc/universes Universes misc/universes/universes 2>&1 mv universes.txt misc/universes N=$(awk '{print $3}' misc/universes/universes.txt | sort -u | wc -l) printf "Found %s/%s universes\n" "$N" "$EXPECTED_UNIVERSES" if [ "$N" -eq $EXPECTED_UNIVERSES ]; then exit 0; else exit 1; fi rocq-9.2.0/test-suite/misc/universes/000077500000000000000000000000001516144147600175635ustar00rootroot00000000000000rocq-9.2.0/test-suite/misc/universes/build_all_stdlib.sh000077500000000000000000000003101516144147600234040ustar00rootroot00000000000000#!/usr/bin/env bash echo "Require $(find ../../../theories ../../../plugins -type f -name "*.v" | \ sed 's/^.*\/theories\///' | sed 's/^.*\/plugins\///' | sed 's/\.v$//' | sed 's/\//./g') ." rocq-9.2.0/test-suite/misc/universes/dune000066400000000000000000000003421516144147600204400ustar00rootroot00000000000000(rule (targets all_stdlib.v) (mode fallback) (deps build_all_stdlib.sh (source_tree ../../../theories) (source_tree ../../../plugins)) (action (with-stdout-to all_stdlib.v (bash "./build_all_stdlib.sh")))) rocq-9.2.0/test-suite/misc/universes/universes.v000066400000000000000000000000741516144147600217760ustar00rootroot00000000000000Require all_stdlib. Print Sorted Universes "universes.txt". rocq-9.2.0/test-suite/misc/votour.sh000077500000000000000000000001761516144147600174410ustar00rootroot00000000000000command -v "${BIN}votour" || { echo "Missing votour"; exit 1; } "${BIN}votour" prerequisite/ssr_mini_mathcomp.vo < /dev/null rocq-9.2.0/test-suite/modules/000077500000000000000000000000001516144147600162555ustar00rootroot00000000000000rocq-9.2.0/test-suite/modules/Demo.v000066400000000000000000000011501516144147600173250ustar00rootroot00000000000000Module M. Definition t := nat. Definition x := 0. End M. Print M.t. Module Type SIG. Parameter t : Set. Parameter x : t. End SIG. Module F (X: SIG). Definition t := X.t -> X.t. Definition x : t. intro. exact X.x. Defined. Definition y := X.x. End F. Module N := F M. Print N.t. Eval compute in N.t. Module N' : SIG := N. Print N'.t. Eval compute in N'.t. Module N'' <: SIG := F N. Print N''.t. Eval compute in N''.t. Eval compute in N''.x. Module N''' : SIG with Definition t := nat -> nat := N. Print N'''.t. Eval compute in N'''.t. Print N'''.x. Import N'''. Print t. rocq-9.2.0/test-suite/modules/Przyklad.v000066400000000000000000000073511516144147600202520ustar00rootroot00000000000000Definition ifte (T : Set) (A B : Prop) (s : {A} + {B}) (th el : T) := if s then th else el. Arguments ifte : default implicits. Lemma Reflexivity_provable : forall (A : Set) (a : A) (s : {a = a} + {a <> a}), exists x : _, s = left _ x. intros. elim s. intro x. split with x; reflexivity. intro. absurd (a = a); auto. Qed. Lemma Disequality_provable : forall (A : Set) (a b : A), a <> b -> forall s : {a = b} + {a <> b}, exists x : _, s = right _ x. intros. elim s. intro. absurd (a = a); auto. intro. split with b0; reflexivity. Qed. Module Type ELEM. Parameter T : Set. Parameter eq_dec : forall a a' : T, {a = a'} + {a <> a'}. End ELEM. Module Type SET (Elt: ELEM). Parameter T : Set. Parameter empty : T. Parameter add : Elt.T -> T -> T. Parameter find : Elt.T -> T -> bool. (* Axioms *) Axiom find_empty_false : forall e : Elt.T, find e empty = false. Axiom find_add_true : forall (s : T) (e : Elt.T), find e (add e s) = true. Axiom find_add_false : forall (s : T) (e e' : Elt.T), e <> e' -> find e (add e' s) = find e s. End SET. Module FuncDict (E: ELEM). Definition T := E.T -> bool. Definition empty (e' : E.T) := false. Definition find (e' : E.T) (s : T) := s e'. Definition add (e : E.T) (s : T) (e' : E.T) := ifte (E.eq_dec e e') true (find e' s). Lemma find_empty_false : forall e : E.T, find e empty = false. auto. Qed. Lemma find_add_true : forall (s : T) (e : E.T), find e (add e s) = true. intros. unfold find, add. elim (Reflexivity_provable _ _ (E.eq_dec e e)). intros. rewrite H. auto. Qed. Lemma find_add_false : forall (s : T) (e e' : E.T), e <> e' -> find e (add e' s) = find e s. intros. unfold add, find. cut (exists x : _, E.eq_dec e' e = right _ x). intros. elim H0. intros. rewrite H1. unfold ifte. reflexivity. apply Disequality_provable. auto. Qed. End FuncDict. Module F : SET := FuncDict. Module Nat. Definition T := nat. Lemma eq_dec : forall a a' : T, {a = a'} + {a <> a'}. decide equality. Qed. End Nat. Module SetNat := F Nat. Lemma no_zero_in_empty : SetNat.find 0 SetNat.empty = false. apply SetNat.find_empty_false. Qed. (***************************************************************************) Module Lemmas (G: SET) (E: ELEM). Module ESet := G E. Lemma commute : forall (S : ESet.T) (a1 a2 : E.T), let S1 := ESet.add a1 (ESet.add a2 S) in let S2 := ESet.add a2 (ESet.add a1 S) in forall a : E.T, ESet.find a S1 = ESet.find a S2. intros. unfold S1, S2. elim (E.eq_dec a a1); elim (E.eq_dec a a2); intros H1 H2; try rewrite <- H1; try rewrite <- H2; repeat (try ( rewrite ESet.find_add_true; auto); try ( rewrite ESet.find_add_false; auto); auto). Qed. End Lemmas. Inductive list (A : Set) : Set := | nil : list A | cons : A -> list A -> list A. Module ListDict (E: ELEM). Definition T := list E.T. Definition elt := E.T. Definition empty := nil elt. Definition add (e : elt) (s : T) := cons elt e s. Fixpoint find (e : elt) (s : T) {struct s} : bool := match s with | nil _ => false | cons _ e' s' => ifte (E.eq_dec e e') true (find e s') end. Definition find_empty_false (e : elt) := refl_equal false. Lemma find_add_true : forall (s : T) (e : E.T), find e (add e s) = true. intros. simpl. elim (Reflexivity_provable _ _ (E.eq_dec e e)). intros. rewrite H. auto. Qed. Lemma find_add_false : forall (s : T) (e e' : E.T), e <> e' -> find e (add e' s) = find e s. intros. simpl. elim (Disequality_provable _ _ _ H (E.eq_dec e e')). intros. rewrite H0. simpl. reflexivity. Qed. End ListDict. Module L : SET := ListDict. rocq-9.2.0/test-suite/modules/SeveralWith.v000066400000000000000000000003351516144147600207020ustar00rootroot00000000000000Module Type S. Parameter A : Type. End S. Module Type ES. Parameter A : Type. Parameter eq : A -> A -> Type. End ES. Module Make (AX : S) (X : ES with Definition A := AX.A with Definition eq := @eq AX.A). End Make. rocq-9.2.0/test-suite/modules/Tescik.v000066400000000000000000000010701516144147600176640ustar00rootroot00000000000000 Module Type ELEM. Parameter A : Set. Parameter x : A. End ELEM. Module Nat. Definition A := nat. Definition x := 0. End Nat. Module List (X: ELEM). Inductive list : Set := | nil : list | cons : X.A -> list -> list. Definition head (l : list) := match l with | nil => X.x | cons x _ => x end. Definition singl (x : X.A) := cons x nil. Lemma head_singl : forall x : X.A, head (singl x) = x. auto. Qed. End List. Module N := List Nat. rocq-9.2.0/test-suite/modules/WithDefUBinders.v000066400000000000000000000007141516144147600214340ustar00rootroot00000000000000 Set Universe Polymorphism. Module Type T. Axiom foo@{u v|u < v} : Type@{v}. End T. Module M : T with Definition foo@{u v} := Type@{u} : Type@{v}. Definition foo@{u v} := Type@{u} : Type@{v}. End M. Fail Module M' : T with Definition foo := Type. (* Without the binder expression we have to do trickery to get the universes in the right order. *) Module M' : T with Definition foo := let t := Type in t. Definition foo := let t := Type in t. End M'. rocq-9.2.0/test-suite/modules/cumpoly.v000066400000000000000000000011461516144147600201360ustar00rootroot00000000000000Set Universe Polymorphism. (** Check that variance subtyping is respected. The signature T is asking for invariance, while M provide an irrelevant implementation, which is deemed legit. There is currently no way to go the other way around, so it's not possible to generate a counter-example that should fail with the wrong subtyping. *) Module Type T. Parameter t@{i|Set <= i} : Type@{i}. Cumulative Inductive I@{i|Set <= i} : Type@{i} := C : t@{i} -> I. End T. Module M : T. Definition t@{i|Set <= i} : Type@{i} := nat. Cumulative Inductive I@{i|Set <= i} : Type@{i} := C : t@{i} -> I. End M. rocq-9.2.0/test-suite/modules/errors.v000066400000000000000000000064471516144147600177730ustar00rootroot00000000000000(* coq-prog-args: ("-impredicative-set") *) (* Inductive mismatches *) Module Type SA. Inductive TA : nat -> Prop := CA : nat -> TA 0. End SA. Module MA : SA. Inductive TA : Prop := CA : bool -> TA. Fail End MA. Reset Initial. Module Type SA0. Inductive TA0 := CA0 : nat -> TA0. End SA0. Module MA0 : SA0. Inductive TA0 := CA0 : bool -> TA0. Fail End MA0. Reset Initial. Module Type SA1. Inductive TA1 := CA1 : nat -> TA1. End SA1. Module MA1 : SA1. Inductive TA1 := CA1 : bool -> nat -> TA1. Fail End MA1. Reset Initial. Module Type SA2. Inductive TA2 := CA2 : nat -> TA2. End SA2. Module MA2 : SA2. Inductive TA2 := CA2 : nat -> TA2 | DA2 : TA2. Fail End MA2. Reset Initial. Module Type SA3. Inductive TA3 := CA3 : nat -> TA3. End SA3. Module MA3 : SA3. Inductive TA3 := CA3 : nat -> TA3 with UA3 := DA3. Fail End MA3. Reset Initial. Module Type SA4. Inductive TA4 := CA4 : nat -> TA4 with UA4 := DA4. End SA4. Module MA4 : SA4. Inductive TA4 := CA4 : nat -> TA4 with VA4 := DA4. Fail End MA4. Reset Initial. Module Type SA5. Inductive TA5 := CA5 : nat -> TA5 with UA5 := DA5. End SA5. Module MA5 : SA5. Inductive TA5 := CA5 : nat -> TA5 with UA5 := EA5. Fail End MA5. Reset Initial. Module Type SA6. Inductive TA6 (A:Type) := CA6 : A -> TA6 A. End SA6. Module MA6 : SA6. Inductive TA6 (A B:Type):= CA6 : A -> TA6 A B. Fail End MA6. Reset Initial. Module Type SA7. Inductive TA7 (A:Type) := CA7 : A -> TA7 A. End SA7. Module MA7 : SA7. CoInductive TA7 (A:Type):= CA7 : A -> TA7 A. Fail End MA7. Reset Initial. Module Type SA8. CoInductive TA8 (A:Type) := CA8 : A -> TA8 A. End SA8. Module MA8 : SA8. Inductive TA8 (A:Type):= CA8 : A -> TA8 A. Fail End MA8. Reset Initial. Module Type SA9. Record TA9 (A:Type) := { CA9 : A }. End SA9. Module MA9 : SA9. Inductive TA9 (A:Type):= CA9 : A -> TA9 A. Fail End MA9. Reset Initial. Module Type SA10. Inductive TA10 (A:Type) := CA10 : A -> TA10 A. End SA10. Module MA10 : SA10. Record TA10 (A:Type):= { CA10 : A }. Fail End MA10. Reset Initial. Module Type SA11. Record TA11 (A:Type):= { CA11 : A }. End SA11. Module MA11 : SA11. Record TA11 (A:Type):= { DA11 : A }. Fail End MA11. Reset Initial. (* Basic mismatches *) Module Type SB. Inductive TB := CB : nat -> TB. End SB. Module MB : SB. Module Type TB. End TB. Fail End MB. Inductive TB := CB : nat -> TB. End MB. Module Type SC. Module Type TC. End TC. End SC. Module MC : SC. Inductive TC := CC : nat -> TC. Fail End MC. Reset Initial. Module Type SD. Module TD. End TD. End SD. Module MD : SD. Inductive TD := DD : nat -> TD. Fail End MD. Reset Initial. Module Type SE. Definition DE := nat. End SE. Module ME : SE. Definition DE := bool. Fail End ME. Reset Initial. Module Type SF. Parameter DF : nat. End SF. Module MF : SF. Definition DF := bool. Fail End MF. Reset Initial. (* Needs a type constraint in module type *) Module Type SG. Definition DG := Type. End SG. Module MG : SG. Definition DG := Type : Type. Fail End MG. Reset Initial. (* Should work *) Module Type SA70. Inductive TA70 (A:Type) := CA70 : A -> TA70 A. End SA70. Module MA70 : SA70. Inductive TA70 (B:Type):= CA70 : B -> TA70 B. End MA70. Module Type SA12. Record TA12 (B:Type):= { CA12 : B }. End SA12. Module MA12 : SA12. Record TA12 (A:Type):= { CA12 : A }. End MA12. Module Type SH. Parameter DH : Type. End SH. Module MH : SH. Definition DH := Type : Type. End MH. rocq-9.2.0/test-suite/modules/fun_objects.v000066400000000000000000000007341516144147600207510ustar00rootroot00000000000000(* coq-prog-args: ("-impredicative-set") *) Set Implicit Arguments. Unset Strict Implicit. Module Type SIG. Parameter id : forall A : Set, A -> A. End SIG. Module M (X: SIG). Definition idid := X.id X.id. Definition id := idid X.id. End M. Module N := M. Module Nat. Definition T := nat. Definition x := 0. Definition id (A : Set) (x : A) := x. End Nat. Module Z := N Nat. Check (Z.idid 0). Module P (Y: SIG) := N. Module Y := P Nat Z. Check (Y.id 0). rocq-9.2.0/test-suite/modules/grammar.v000066400000000000000000000003571516144147600200770ustar00rootroot00000000000000Module N. Definition f := plus. (* : Syntax is discontinued *) Check (f 0 0). End N. Check (N.f 0 0). Import N. Check (f 0 0). Check (f 0 0). Module M := N. Check (f 0 0). Check (f 0 0). Import M. Check (f 0 0). Check (N.f 0 0). rocq-9.2.0/test-suite/modules/include_module_type.v000066400000000000000000000004151516144147600224750ustar00rootroot00000000000000Module Type type1. Parameter A : Prop. End type1. Module Type type2. Parameter B : Prop. End type2. Module Type type3 := type1 <+ type2 with Definition B := True. Print type3. Module Type type3''. Include type1 <+ type2 with Definition B := True. End type3''. rocq-9.2.0/test-suite/modules/ind.v000066400000000000000000000024521516144147600172210ustar00rootroot00000000000000Module Type SIG. Inductive w : Set := A : w. Parameter f : w -> w. End SIG. Module M : SIG. Inductive w : Set := A : w. Definition f x := match x with | A => A end. End M. Module N := M. Check (N.f M.A). (* Check use of equivalence on inductive types (bug #1242) *) Module Type ASIG. Inductive t : Set := a | b : t. Definition f := fun x => match x with a => true | b => false end. End ASIG. Module Type BSIG. Declare Module A : ASIG. Definition f := fun x => match x with A.a => true | A.b => false end. End BSIG. Module C (A : ASIG) (B : BSIG with Module A:=A). (* Check equivalence is considered in "case_info" *) Lemma test : forall x, A.f x = B.f x. intro x. unfold B.f, A.f. destruct x; reflexivity. Qed. (* Check equivalence is considered in pattern-matching *) Definition f (x : A.t) := match x with B.A.a => true | B.A.b => false end. End C. (* Check subtyping of the context of parameters of the inductive types *) (* Only the number of expected uniform parameters and the convertibility *) (* of the inductive arities and constructors types are checked *) Module Type S. Inductive I (x:=0) (y:nat): Set := c: x=y -> I y. End S. Module P : S. Inductive I (y':nat) (z:=y'): Set := c : 0=y' -> I y'. End P. rocq-9.2.0/test-suite/modules/injection_discriminate_inversion.v000066400000000000000000000011431516144147600252540ustar00rootroot00000000000000Module M. Inductive I : Set := C : nat -> I. End M. Module M1 := M. Goal forall x, M.C x = M1.C 0 -> x = 0 . intros x H. (* injection sur deux constructeurs egaux mais appeles par des modules differents *) injection H. tauto. Qed. Goal M.C 0 <> M1.C 1. (* Discriminate sur deux constructeurs egaux mais appeles par des modules differents *) intro H;discriminate H. Qed. Goal forall x, M.C x = M1.C 0 -> x = 0. intros x H. (* inversion sur deux constructeurs egaux mais appeles par des modules differents *) inversion H. reflexivity. Qed. rocq-9.2.0/test-suite/modules/inlining.v000066400000000000000000000051571516144147600202630ustar00rootroot00000000000000Module Type T. Parameter Inline(50) t : Type. End T. Module Type F (X : T). Parameter p : X.t. End F. Module M. Definition t := nat. End M. Set Inline Level 49. Module G (X : F M [inline at level 49]) (Y : F M [inline at level 50]) (Z : F M) : F M [inline at level 50]. (* M.t should not be inlined in the type of X.p, because 49 < 50 *) Goal X.p = X.p. match goal with |- _ = _ :> M.t => idtac | _ => fail end. Fail match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. (* M.t should be inlined in the type of Y.p, because 50 >= 50 *) Goal Y.p = Y.p. Fail match goal with |- _ = _ :> M.t => idtac | _ => fail end. match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. (* M.t should not be inlined in the type of Z.p, because default level < 50 *) Goal Z.p = Z.p. match goal with |- _ = _ :> M.t => idtac | _ => fail end. Fail match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. Definition p := X.p. End G. Module N. Definition p := 0. End N. Module P := G N N N. (* M.t should be inlined in the type of P.p, because 50 >= 50 *) Goal P.p = P.p. Fail match goal with |- _ = _ :> M.t => idtac | _ => fail end. match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. Set Inline Level 50. Module G' (X : F M [inline at level 49]) (Y : F M [inline at level 50]) (Z : F M) : F M [inline at level 49]. (* M.t should be inlined in the type of Z.p, because default level >= 50 *) Goal Z.p = Z.p. Fail match goal with |- _ = _ :> M.t => idtac | _ => fail end. match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. Definition p := X.p. End G'. Module P' := G' N N N. (* M.t should not be inlined in the type of P'.p, because 49 < 50 *) Goal P'.p = P'.p. match goal with |- _ = _ :> M.t => idtac | _ => fail end. Fail match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. Set Inline Level 50. Module G'' (X : F M [inline at level 49]) (Y : F M [inline at level 50]) (Z : F M) : F M. Definition p := X.p. End G''. Module P'' := G'' N N N. (* M.t should not be inlined in the type of P''.p, because default level >= 50 *) Goal P''.p = P''.p. Fail match goal with |- _ = _ :> M.t => idtac | _ => fail end. match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. Set Inline Level 49. Module G''' (X : F M [inline at level 49]) (Y : F M [inline at level 50]) (Z : F M) : F M. Definition p := X.p. End G'''. Module P''' := G''' N N N. (* M.t should not be inlined in the type of P'.p, because default level < 50 *) Goal P'''.p = P'''.p. match goal with |- _ = _ :> M.t => idtac | _ => fail end. Fail match goal with |- _ = _ :> nat => idtac | _ => fail end. Abort. rocq-9.2.0/test-suite/modules/mod_decl.v000066400000000000000000000010371516144147600202130ustar00rootroot00000000000000Module Type SIG. Axiom A : Set. End SIG. Module M0. Definition A : Set. exact nat. Qed. End M0. Module M1 : SIG. Definition A := nat. End M1. Module M2 <: SIG. Definition A := nat. End M2. Module M3 := M0. Module M4 : SIG := M0. Module M5 <: SIG := M0. Module F (X: SIG) := X. Module Type T. Module M0. Axiom A : Set. End M0. Declare Module M1: SIG. Module M2 <: SIG. Definition A := nat. End M2. Module M3 := M0. Module M4 : SIG := M0. Module M5 <: SIG := M0. Module M6 := F M0. End T. rocq-9.2.0/test-suite/modules/modeq.v000066400000000000000000000005541516144147600175550ustar00rootroot00000000000000(* coq-prog-args: ("-top" "modeq") *) Module M. Definition T := nat. Definition x : T := 0. End M. Module Type SIG. Module M := modeq.M. Module Type SIG. Parameter T : Set. End SIG. Declare Module N: SIG. End SIG. Module Z. Module M := modeq.M. Module Type SIG. Parameter T : Set. End SIG. Module N := M. End Z. Module A : SIG := Z. rocq-9.2.0/test-suite/modules/modul.v000066400000000000000000000006741516144147600175730ustar00rootroot00000000000000(* coq-prog-args: ("-top" "modul") *) Module M. Parameter rel : nat -> nat -> Prop. Axiom w : forall n : nat, rel 0 (S n). #[export] Hint Resolve w. (* : Grammar is replaced by Notation *) Print Hint *. Lemma w1 : rel 0 1. auto. Qed. End M. Locate Module M. (*Lemma w1 : (M.rel O (S O)). Auto. *) Import M. Lemma w1 : rel 0 1. auto. Qed. Check (rel 0 0). Locate rel. Locate Module M. Module N := modul.M. rocq-9.2.0/test-suite/modules/nested_mod_types.v000066400000000000000000000006561516144147600220200ustar00rootroot00000000000000Module Type T. Module Type U. Module Type V. #[local] Parameter b : nat. End V. #[local] Parameter a : nat. End U. Declare Module u : U. Declare Module v : u.V. End T. Module F (t:T). End F. Module M:T. Module Type U. Module Type V. #[local] Parameter b : nat. End V. #[local] Parameter a : nat. End U. Declare Module u : U. Declare Module v : u.V. End M. Module FM := F M. rocq-9.2.0/test-suite/modules/obj.v000066400000000000000000000006021516144147600172140ustar00rootroot00000000000000Set Implicit Arguments. Unset Strict Implicit. Module M. Definition a (s : Set) := s. Print a. End M. Print M.a. Module K. Definition app (A B : Set) (f : A -> B) (x : A) := f x. Module N. Definition apap (A B : Set) := app (app (A:=A) (B:=B)). Print app. Print apap. End N. Print N.apap. End K. Print K.app. Print K.N.apap. Module W := K.N. Print W.apap. rocq-9.2.0/test-suite/modules/objects.v000066400000000000000000000006221516144147600200750ustar00rootroot00000000000000Module Type SET. Axiom T : Set. Axiom x : T. End SET. Set Implicit Arguments. Unset Strict Implicit. Module M (X: SET). Definition T := nat. Definition x := 0. Definition f (A : Set) (x : A) := X.x. End M. Module N := M. Module Nat. Definition T := nat. Definition x := 0. End Nat. Module Z := N Nat. Check (Z.f 0). Module P (Y: SET) := N. Module Y := P Z Nat. Check (Y.f 0). rocq-9.2.0/test-suite/modules/objects2.v000066400000000000000000000006001516144147600201530ustar00rootroot00000000000000(* Check that non logical object loading is done after registration of the logical objects in the environment *) (* BZ#1118 (simplified version), submitted by Evelyne Contejean (used to failed in pre-V8.1 trunk because of a call to lookup_mind for structure objects) *) Module Type S. Record t : Set := { a : nat; b : nat }. End S. Module Make (X:S). Module Y:=X. End Make. rocq-9.2.0/test-suite/modules/pliczek.v000066400000000000000000000000731516144147600201050ustar00rootroot00000000000000Require Export plik. Definition tutu (X : Set) := toto X. rocq-9.2.0/test-suite/modules/plik.v000066400000000000000000000001231516144147600173770ustar00rootroot00000000000000Definition toto (x : Set) := x. (* : Grammar is replaced by Notation *) rocq-9.2.0/test-suite/modules/polymorphism.v000066400000000000000000000020431516144147600212050ustar00rootroot00000000000000Set Universe Polymorphism. (** Tests for module subtyping of polymorphic terms *) Module Type S. Section Foo. Universes i j. Constraint i <= j. Parameter foo : Type@{i} -> Type@{j}. End Foo. End S. (** Same constraints *) Module OK_1. Definition foo@{i j} (A : Type@{i}) : Type@{j} := A. End OK_1. Module OK_1_Test : S := OK_1. (** More general constraints *) Module OK_2. Inductive X@{i} : Type@{i} :=. Definition foo@{i j} (A : Type@{i}) : Type@{j} := X@{j}. End OK_2. Module OK_2_Test : S := OK_2. (** Wrong instance length *) Module KO_1. Definition foo@{i} (A : Type@{i}) : Type@{i} := A. End KO_1. Fail Module KO_Test_1 : S := KO_1. (** Less general constraints *) Module KO_2. Section Foo. Universe i j. Constraint i < j. Definition foo (A : Type@{i}) : Type@{j} := A. End Foo. End KO_2. Fail Module KO_Test_2 : S := KO_2. (** Less general constraints *) Module KO_3. Section Foo. Universe i j. Constraint i = j. Definition foo (A : Type@{i}) : Type@{j} := A. End Foo. End KO_3. Fail Module KO_Test_3 : S := KO_3. rocq-9.2.0/test-suite/modules/polymorphism2.v000066400000000000000000000020321516144147600212650ustar00rootroot00000000000000Set Universe Polymorphism. (** Tests for module subtyping of polymorphic terms *) Module Type S. Section Foo. Universes i j. Constraint i <= j. Inductive foo : Type@{i} -> Type@{j} :=. End Foo. End S. (** Same constraints *) Module OK_1. Section Foo. Universes i j. Constraint i <= j. Inductive foo : Type@{i} -> Type@{j} :=. End Foo. End OK_1. Module OK_1_Test : S := OK_1. (** More general constraints *) Module OK_2. Inductive foo@{i j} : Type@{i} -> Type@{j} :=. End OK_2. Module OK_2_Test : S := OK_2. (** Wrong instance length *) Module KO_1. Inductive foo@{i} : Type@{i} -> Type@{i} :=. End KO_1. Fail Module KO_Test_1 : S := KO_1. (** Less general constraints *) Module KO_2. Section Foo. Universe i j. Constraint i < j. Inductive foo : Type@{i} -> Type@{j} :=. End Foo. End KO_2. Fail Module KO_Test_2 : S := KO_2. (** Less general constraints *) Module KO_3. Section Foo. Universe i j. Constraint i = j. Inductive foo : Type@{i} -> Type@{j} :=. End Foo. End KO_3. Fail Module KO_Test_3 : S := KO_3. rocq-9.2.0/test-suite/modules/pseudo_circular_with.v000066400000000000000000000002341516144147600226610ustar00rootroot00000000000000Module Type S. End S. Module Type T. Declare Module M:S. End T. Module N:S. End N. Module NN:T. Module M:=N. End NN. Module Type U := T with Module M:=NN. rocq-9.2.0/test-suite/modules/resolver.v000066400000000000000000000007221516144147600203060ustar00rootroot00000000000000Module Type TA. Parameter t : Set. End TA. Module Type TB. Declare Module A: TA. End TB. Module Type TC. Declare Module B : TB. End TC. Module Type TD. Declare Module B: TB . Declare Module C: TC with Module B := B . End TD. Module Type TE. Declare Module D : TD. End TE. Module Type TF. Declare Module E: TE. End TF. Module G (D: TD). Module B' := D.C.B. End G. Module H (F: TF). Module I := G(F.E.D). End H. Declare Module F: TF. Module K := H(F). rocq-9.2.0/test-suite/modules/sig.v000066400000000000000000000006571516144147600172360ustar00rootroot00000000000000Module M. Module Type SIG. Parameter T : Set. Parameter x : T. End SIG. Module N : SIG. Definition T := nat. Definition x := 0. End N. End M. Module N := M. Module Type SPRYT. Module N. Definition T := M.N.T. Parameter x : T. End N. End SPRYT. Module K : SPRYT := N. Module K' : SPRYT := M. Module Type SIG. Definition T : Set := M.N.T. Parameter x : T. End SIG. Module J : SIG := M.N. rocq-9.2.0/test-suite/modules/sub_objects.v000066400000000000000000000011301516144147600207410ustar00rootroot00000000000000Set Implicit Arguments. Unset Strict Implicit. Module M. Definition id (A : Set) (x : A) := x. Module Type SIG. Parameter idid : forall A : Set, A -> A. End SIG. Module N. Definition idid (A : Set) (x : A) := id x. (* : Grammar is replaced by Notation *) Notation inc := (plus 1). End N. Definition zero := N.idid 0. End M. Definition zero := M.N.idid 0. Definition jeden := M.N.inc 0. Module Goly := M.N. Definition Gole_zero := Goly.idid 0. Definition Goly_jeden := Goly.inc 0. Module Ubrany : M.SIG := M.N. Definition Ubrane_zero := Ubrany.idid 0. rocq-9.2.0/test-suite/modules/subtyping.v000066400000000000000000000025351516144147600204750ustar00rootroot00000000000000(* Non regression for bug #1302 *) (* With universe polymorphism for inductive types, subtyping of inductive types needs a special treatment: the standard conversion algorithm does not work as it only knows to deal with constraints of the form alpha = beta or max(alphas, alphas+1) <= beta, while subtyping of inductive types in Type generates constraints of the form max(alphas, alphas+1) <= max(betas, betas+1). These constraints are anyway valid by monotonicity of subtyping but we have to detect it early enough to avoid breaking the standard algorithm for constraints on algebraic universes. *) Module Type T. Parameter A : Type (* Top.1 *) . Inductive L : Type (* max(Top.1,1) *) := | L0 | L1 : (A -> Prop) -> L. End T. Axiom Tp : Type (* Top.5 *) . Module TT : T. Definition A : Type (* Top.6 *) := Tp. (* generates Top.5 <= Top.6 *) Inductive L : Type (* max(Top.6,1) *) := | L0 | L1 : (A -> Prop) -> L. End TT. (* Generates Top.6 <= Top.1 (+ auxiliary constraints for L_rect) *) (* Note: Top.6 <= Top.1 is generated by subtyping on A; subtyping of L follows and has not to be checked *) (* The same bug as #1302 but for Definition *) (* Check that inferred algebraic universes in interfaces are considered *) Module Type U. Definition A := Type -> Type. End U. Module M:U. Definition A := Type -> Type. End M. rocq-9.2.0/test-suite/ocaml_pwd.ml000066400000000000000000000012211516144147600171000ustar00rootroot00000000000000open Arg let quoted = ref false let trailing_slash = ref false let arguments = [ "-quoted",Set quoted, "Quote path"; "-trailing-slash",Set trailing_slash, "End the path with a /"; ] let subject = ref None let set_subject x = if !subject <> None then failwith "only one path"; subject := Some x let () = Arg.parse arguments set_subject "Usage:"; let subject = match !subject with | None -> failwith "no path given"; | Some x -> x in Sys.chdir subject; let dir = Sys.getcwd () in let dir = if !trailing_slash then dir ^ "/" else dir in let dir = if !quoted then Filename.quote dir else dir in Format.printf "%s%!" dir rocq-9.2.0/test-suite/output-coqchk/000077500000000000000000000000001516144147600174135ustar00rootroot00000000000000rocq-9.2.0/test-suite/output-coqchk/bug_12845.out000066400000000000000000000004611516144147600214650ustar00rootroot00000000000000 CONTEXT SUMMARY =============== * Theory: Set is predicative * Theory: Rewrite rules are not allowed * Axioms: * Constants/Inductives relying on type-in-type: * Constants/Inductives relying on unsafe (co)fixpoints: * Inductives whose positivity is assumed: rocq-9.2.0/test-suite/output-coqchk/bug_12845.v000066400000000000000000000002271516144147600211230ustar00rootroot00000000000000Module Type A. Module B. Axiom t : Set. End B. End A. Module a : A. Module B. Definition t : Set := unit. End B. End a. Check a.B.t. rocq-9.2.0/test-suite/output-coqchk/bug_13324.out000066400000000000000000000004611516144147600214560ustar00rootroot00000000000000 CONTEXT SUMMARY =============== * Theory: Set is predicative * Theory: Rewrite rules are not allowed * Axioms: * Constants/Inductives relying on type-in-type: * Constants/Inductives relying on unsafe (co)fixpoints: * Inductives whose positivity is assumed: rocq-9.2.0/test-suite/output-coqchk/bug_13324.v000066400000000000000000000002571516144147600211170ustar00rootroot00000000000000Require Import Program.Basics Program.Tactics. Obligation Tactic := abstract exact I. Program Definition foo : True := _. Definition bar : True := ltac:(abstract exact I). rocq-9.2.0/test-suite/output-coqchk/bug_5030.out000066400000000000000000000004611516144147600213710ustar00rootroot00000000000000 CONTEXT SUMMARY =============== * Theory: Set is predicative * Theory: Rewrite rules are not allowed * Axioms: * Constants/Inductives relying on type-in-type: * Constants/Inductives relying on unsafe (co)fixpoints: * Inductives whose positivity is assumed: rocq-9.2.0/test-suite/output-coqchk/bug_5030.v000066400000000000000000000002411516144147600210230ustar00rootroot00000000000000Module Type testt. Parameter proof : True. End testt. Module Export test : testt. Definition proof := I. End test. Lemma true : True. Proof. apply proof. Qed. rocq-9.2.0/test-suite/output-coqtop/000077500000000000000000000000001516144147600174505ustar00rootroot00000000000000rocq-9.2.0/test-suite/output-coqtop/BracketLoc.out000066400000000000000000000007641516144147600222210ustar00rootroot00000000000000 Rocq < 1 goal ============================ True Toplevel input, characters 11-12: > Goal True. } > ^ Error: The proof is not focused Unnamed_thm < Toplevel input, characters 2-3: > } > ^ Error: The proof is not focused Unnamed_thm < Toplevel input, characters 2-3: > } > ^ Error: The proof is not focused Unnamed_thm < Toplevel input, characters 8-9: > exact 0. > ^ Error: The term "0" has type "nat" while it is expected to have type "True". Unnamed_thm < rocq-9.2.0/test-suite/output-coqtop/BracketLoc.v000066400000000000000000000000421516144147600216440ustar00rootroot00000000000000Goal True. } } } exact 0. rocq-9.2.0/test-suite/output-coqtop/DependentEvars.out000066400000000000000000000027351516144147600231170ustar00rootroot00000000000000 Rocq < Rocq < Rocq < 1 goal ============================ forall P Q R : Prop, (Q -> R) -> (P -> Q) -> (P -> Q) -> P -> R (dependent evars: ; in current goal:) strange_imp_trans < strange_imp_trans < No more goals. (dependent evars: ; in current goal:) strange_imp_trans < Rocq < Rocq < 1 goal ============================ forall P Q : Prop, (P -> Q) /\ P -> Q (dependent evars: ; in current goal:) modpon < modpon < No more goals. (dependent evars: ; in current goal:) modpon < Rocq < Rocq < Rocq < P1 is declared P2 is declared P3 is declared P4 is declared Rocq < p12 is declared Rocq < p123 is declared Rocq < p34 is declared Rocq < Rocq < 1 goal P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ P4 (dependent evars: ; in current goal:) p14 < p14 < 4 focused goals (shelved: 2) P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ ?Q -> P4 goal 2 is: ?P -> ?Q goal 3 is: ?P -> ?Q goal 4 is: ?P (dependent evars: ?X4:?P, ?X5:?Q; in current goal: ?X5) p14 < 3 focused goals (shelved: 2) P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ ?P -> (?P0 -> P4) /\ ?P0 goal 2 is: ?P -> (?P0 -> P4) /\ ?P0 goal 3 is: ?P (dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal: ?X4 ?X5 ?X10 ?X11) p14 < Rocq < Rocq < rocq-9.2.0/test-suite/output-coqtop/DependentEvars.v000066400000000000000000000007221516144147600225470ustar00rootroot00000000000000Set Printing Dependent Evars Line. Lemma strange_imp_trans : forall P Q R : Prop, (Q -> R) -> (P -> Q) -> (P -> Q) -> P -> R. Proof. auto. Qed. Lemma modpon : forall P Q : Prop, (P -> Q) /\ P -> Q. Proof. tauto. Qed. Section eex. Variables P1 P2 P3 P4 : Prop. Hypothesis p12 : P1 -> P2. Hypothesis p123 : (P1 -> P2) -> P3. Hypothesis p34 : P3 -> P4. Lemma p14 : P4. Proof. eapply strange_imp_trans. apply modpon. Abort. End eex. rocq-9.2.0/test-suite/output-coqtop/DependentEvars2.out000066400000000000000000000037731516144147600232040ustar00rootroot00000000000000 Rocq < Rocq < Rocq < 1 goal ============================ forall P Q R : Prop, (Q -> R) -> (P -> Q) -> (P -> Q) -> P -> R (dependent evars: ; in current goal:) strange_imp_trans < strange_imp_trans < No more goals. (dependent evars: ; in current goal:) strange_imp_trans < Rocq < Rocq < 1 goal ============================ forall P Q : Prop, (P -> Q) /\ P -> Q (dependent evars: ; in current goal:) modpon < modpon < No more goals. (dependent evars: ; in current goal:) modpon < Rocq < Rocq < Rocq < P1 is declared P2 is declared P3 is declared P4 is declared Rocq < p12 is declared Rocq < p123 is declared Rocq < p34 is declared Rocq < Rocq < 1 goal P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ P4 (dependent evars: ; in current goal:) p14 < p14 < Second proof: p14 < 4 focused goals (shelved: 2) P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ ?Q -> P4 goal 2 is: ?P -> ?Q goal 3 is: ?P -> ?Q goal 4 is: ?P (dependent evars: ?X4:?P, ?X5:?Q; in current goal: ?X5) p14 < 1 focused goal (shelved: 2) P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ ?Q -> P4 (dependent evars: ?X4:?P, ?X5:?Q; in current goal: ?X5) p14 < This subproof is complete, but there are some unfocused goals. Try unfocusing with "}". 3 goals (shelved: 2) goal 1 is: ?P -> (?P0 -> P4) /\ ?P0 goal 2 is: ?P -> (?P0 -> P4) /\ ?P0 goal 3 is: ?P (dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal:) p14 < 3 focused goals (shelved: 2) P1, P2, P3, P4 : Prop p12 : P1 -> P2 p123 : (P1 -> P2) -> P3 p34 : P3 -> P4 ============================ ?P -> (?P0 -> P4) /\ ?P0 goal 2 is: ?P -> (?P0 -> P4) /\ ?P0 goal 3 is: ?P (dependent evars: ?X4:?P, ?X5 using ?X10 ?X11, ?X10 using ?X11, ?X11:?P0; in current goal: ?X4 ?X5 ?X10 ?X11) p14 < Rocq < Rocq < rocq-9.2.0/test-suite/output-coqtop/DependentEvars2.v000066400000000000000000000010071516144147600226260ustar00rootroot00000000000000Set Printing Dependent Evars Line. Lemma strange_imp_trans : forall P Q R : Prop, (Q -> R) -> (P -> Q) -> (P -> Q) -> P -> R. Proof. auto. Qed. Lemma modpon : forall P Q : Prop, (P -> Q) /\ P -> Q. Proof. tauto. Qed. Section eex. Variables P1 P2 P3 P4 : Prop. Hypothesis p12 : P1 -> P2. Hypothesis p123 : (P1 -> P2) -> P3. Hypothesis p34 : P3 -> P4. Lemma p14 : P4. Proof. idtac "Second proof:". eapply strange_imp_trans. { apply modpon. } Abort. End eex. rocq-9.2.0/test-suite/output-coqtop/DependentEvars3.out000066400000000000000000000012501516144147600231710ustar00rootroot00000000000000 Rocq < Rocq < 1 goal ============================ (exists n : nat, n = 5 \/ True) /\ (exists m : nat, m = 6 \/ True) (dependent evars: ; in current goal:) x < x < 2 goals ============================ exists n : nat, n = 5 \/ True goal 2 is: exists m : nat, m = 6 \/ True (dependent evars: ; in current goal:) x < 2 focused goals (shelved: 1) ============================ ?n = 5 \/ True goal 2 is: exists m : nat, m = 6 \/ True (dependent evars: ?X10:?n; in current goal: ?X10) x < 2 focused goals (shelved: 1) ============================ True goal 2 is: exists m : nat, m = 6 \/ True (dependent evars: ?X10:?n; in current goal:) x < rocq-9.2.0/test-suite/output-coqtop/DependentEvars3.v000066400000000000000000000002411516144147600226260ustar00rootroot00000000000000Set Printing Dependent Evars Line. Lemma x : (exists(n : nat), n = 5 \/ True) /\ (exists(m : nat), m = 6 \/ True). Proof using. split. eexists. right. rocq-9.2.0/test-suite/output-coqtop/LevelTolerance.out000066400000000000000000001263011516144147600231100ustar00rootroot00000000000000 Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < T is defined T_rect is defined T_ind is defined T_rec is defined T_sind is defined Rocq < Parsing is defined Parsing_rect is defined Parsing_ind is defined Parsing_rec is defined Parsing_sind is defined Rocq < Rocq < Rocq < Rocq < Identifier 'op22' now a keyword Rocq < Identifier 'op12' now a keyword Rocq < Identifier 'op10' now a keyword Rocq < Rocq < Setting notation at level 0. Rocq < Setting notation at level 0. Rocq < Setting notation at level 0. Rocq < Setting notation at level 0. Rocq < Rocq < Identifier 'atom3' now a keyword Rocq < Identifier 'atom2' now a keyword Rocq < Identifier 'atom1' now a keyword Rocq < Rocq < Rocq < Identifier 'pre22' now a keyword Rocq < Identifier 'pre21' now a keyword Rocq < Identifier 'pre11' now a keyword Rocq < Identifier 'pre10' now a keyword Rocq < Rocq < Rocq < Rocq < Identifier 'post12' now a keyword Rocq < Identifier 'post11' now a keyword Rocq < Rocq < Entry custom:Top.expr is [ "3" RIGHTA [ SELF; "op22"; NEXT | "atom3" ] | "2" RIGHTA [ SELF; "post12" | SELF; "op12"; custom:Top.expr LEVEL "2" | "pre21"; NEXT | "pre22"; custom:Top.expr LEVEL "2" | "atom2" ] | "1" LEFTA [ SELF; "post11" | SELF; "op10"; NEXT | "pre10"; NEXT | "pre11"; custom:Top.expr LEVEL "1" | "atom1" ] | "0" RIGHTA [ IDENT "pre0x"; NEXT | IDENT "pre00"; custom:Top.expr LEVEL "0" | IDENT "atom0" ] ] Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Toplevel input, characters 496-503: > Check Reject 10 [2 atom3 ]. > ^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 11 E : Parsing Rocq < Toplevel input, characters 19-26: > Check Reject 12 [1 atom2 ]. > ^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 13 E : Parsing Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 20 [2 pre22 atom3 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 21 (F E) : Parsing Rocq < Toplevel input, characters 19-32: > Check Reject 22 [1 pre22 atom2 ]. > ^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 30 [2 pre21 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 31 (F E) : Parsing Rocq < Toplevel input, characters 19-32: > Check Reject 32 [1 pre21 atom1 ]. > ^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 40 [2 pre11 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 25-30: > Check Reject 41 [1 pre11 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 42 (F E) : Parsing Rocq < Toplevel input, characters 19-32: > Check Reject 43 [0 pre11 atom1 ]. > ^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 50 [1 pre10 atom1 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 51 (F E) : Parsing Rocq < Toplevel input, characters 19-32: > Check Reject 52 [0 pre10 atom0 ]. > ^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 60 [1 pre00 atom1 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 25-30: > Check Reject 61 [0 pre00 atom1 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 62 (F E) : Parsing Rocq < Rocq < Toplevel input, characters 26-31: > Check Reject 70 [0 pre0x atom0 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected (there is no next level of last level). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 20-25: > Check Reject 80 [2 atom3 post12 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 19-24: > Check Reject 81 [2 atom2 post12 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 82 (F E) : Parsing Rocq < Toplevel input, characters 19-31: > Check Reject 83 [1 atom1 post12 ]. > ^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 3154-3154 with ( Replace Toplevel input, characters 3166-3166 with ) Rocq < Rocq < Toplevel input, characters 20-25: > Check Reject 90 [2 atom2 post11 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 91 (F E) : Parsing Rocq < Accept 92 (F E) : Parsing Rocq < Toplevel input, characters 19-33: > Check Reject 93 [0 atom1 post11 ]. > ^^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 21-26: > Check Reject 100 [3 atom3 op22 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 31-36: > Check Reject 101 [3 atom2 op22 atom3 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 102 (G E E) : Parsing Rocq < Toplevel input, characters 20-36: > Check Reject 103 [2 atom2 op22 atom2 ]. > ^^^^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 3452-3452 with ( Replace Toplevel input, characters 3468-3468 with ) Rocq < Rocq < Toplevel input, characters 21-26: > Check Reject 110 [2 atom2 op12 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 31-36: > Check Reject 111 [2 atom1 op12 atom3 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 112 (G E E) : Parsing Rocq < Toplevel input, characters 20-36: > Check Reject 113 [1 atom1 op12 atom2 ]. > ^^^^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 3613-3613 with ( Replace Toplevel input, characters 3629-3629 with ) Rocq < Rocq < Toplevel input, characters 21-26: > Check Reject 120 [1 atom2 op10 atom0]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 31-36: > Check Reject 121 [1 atom1 op10 atom1]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 122 (G E E) : Parsing Rocq < Toplevel input, characters 20-37: > Check Reject 123 [0 atom1 op10 atom0]. > ^^^^^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Toplevel input, characters 27-32: > Check Reject 130 [2 pre22 atom2 op12 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 20-31: > Check Reject 131 [2 pre21 atom1 op12 atom2 ]. > ^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 132 (F (G E E)) : Parsing Rocq < Rocq < Toplevel input, characters 21-33: > Check Reject 140 [2 atom2 post12 op12 atom2 ]. > ^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 20-32: > Check Reject 141 [2 atom1 post12 op12 atom2 ]. > ^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 142 (G (F E) E) : Parsing Rocq < Rocq < Accept 150 (G E (F E)) : Parsing Rocq < Toplevel input, characters 37-42: > Check Reject 151 [2 atom1 op12 pre21 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 152 (G E (F E)) : Parsing Rocq < Rocq < Toplevel input, characters 32-37: > Check Reject 160 [2 atom1 op12 atom2 post12 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 161 (G E (F E)) : Parsing Rocq < Toplevel input, characters 31-43: > Check Reject 162 [2 atom1 op10 atom1 post12 ]. > ^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 163 (F (G E E)) : Parsing Rocq < Rocq < Accept 170 (F (G E E)) : Parsing Rocq < Toplevel input, characters 26-42: > Check Reject 171 [1 pre10 atom1 op10 atom0 ]. > ^^^^^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 172 (G (F E) E) : Parsing Rocq < Rocq < Toplevel input, characters 21-33: > Check Reject 180 [1 atom1 post12 op10 atom0 ]. > ^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 181 (G (F E) E) : Parsing Rocq < Rocq < Toplevel input, characters 32-43: > Check Reject 190 [1 atom1 op10 pre11 atom0 ]. > ^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Toplevel input, characters 31-42: > Check Reject 191 [1 atom1 op10 pre10 atom0 ]. > ^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Rocq < Accept 200 (F (G E E)) : Parsing Rocq < Toplevel input, characters 20-43: > Check Reject 201 [1 atom1 op10 atom0 post12 ]. > ^^^^^^^^^^^^^^^^^^^^^^^ Error: In term, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 4794-4794 with ( Replace Toplevel input, characters 4817-4817 with ) Rocq < Accept 202 (F (G E E)) : Parsing Rocq < Rocq < Toplevel input, characters 32-37: > Check Reject 210 [2 atom1 op12 atom2 op12 atom2 ]. > ^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 211 (G E (G E E)) : Parsing Rocq < Rocq < Toplevel input, characters 32-48: > Check Reject 220 [1 atom1 op10 atom1 op10 atom0 ]. > ^^^^^^^^^^^^^^^^ Error: In custom:Top.expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 221 (G (G E E) E) : Parsing Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Entry ltac_expr is [ "5" RIGHTA [ IDENT "atom5" ] | "4" LEFTA [ SELF; IDENT "post44" | SELF; ";"; SELF | SELF; ";"; tactic_then_locality; for_each_goal; "]" | IDENT "pre43"; NEXT | IDENT "pre44"; SELF | IDENT "atom4" ] | "3" RIGHTA [ "atom3" | IDENT "try"; SELF | IDENT "do"; nat_or_var; SELF | IDENT "timeout"; nat_or_var; SELF | IDENT "time"; OPT string; SELF | IDENT "repeat"; SELF | IDENT "progress"; SELF | IDENT "once"; SELF | IDENT "exactly_once"; SELF | IDENT "abstract"; NEXT; "using"; ident | IDENT "abstract"; NEXT | IDENT "only"; goal_selector; ":"; SELF ] | "2" RIGHTA [ SELF; "post12" | SELF; "+"; SELF | SELF; "||"; SELF | "pre21"; NEXT | "pre22"; SELF | "atom2" | IDENT "tryif"; SELF; "then"; SELF; "else"; SELF ] | "1l" LEFTA [ ] | "1" RIGHTA [ "atom1" | "fun"; LIST1 input_fun; "=>"; ltac_expr LEVEL "5" | "let"; [ IDENT "rec" | ]; LIST1 let_clause SEP "with"; "in"; ltac_expr LEVEL "5" | IDENT "first"; "["; LIST0 ltac_expr SEP "|"; "]" | IDENT "solve"; "["; LIST0 ltac_expr SEP "|"; "]" | IDENT "idtac"; LIST0 message_token | match_key; IDENT "goal"; "with"; match_context_list; "end" | match_key; IDENT "reverse"; IDENT "goal"; "with"; match_context_list; "end" | match_key; SELF; "with"; match_list; "end" | failkw; [ nat_or_var | ]; LIST0 message_token | simple_tactic | tactic_value | reference; LIST0 tactic_arg ] | "0" LEFTA [ "("; SELF; ")" | "["; ">"; for_each_goal; "]" | tactic_atom ] ] Entry simple_tactic is [ LEFTA [ IDENT "firstorder"; OPT tactic; "with"; LIST1 preident | IDENT "firstorder"; OPT tactic; firstorder_using; "with"; LIST1 preident | IDENT "firstorder"; OPT tactic; firstorder_using | IDENT "congruence"; OPT natural; "with"; LIST1 constr | IDENT "congruence"; OPT natural | IDENT "dintuition"; tactic | IDENT "dintuition" | IDENT "intuition"; tactic | IDENT "intuition" | IDENT "assert_fails"; ltac_expr LEVEL "3" | IDENT "inversion_sigma"; hyp; "as"; simple_intropattern | IDENT "inversion_sigma"; hyp | IDENT "inversion_sigma" | IDENT "now"; tactic | IDENT "rewrite_all"; "<-"; constr | IDENT "rewrite_all"; constr | IDENT "destruct_with_eqn"; ":"; ident; ident | IDENT "destruct_with_eqn"; ":"; ident; constr | IDENT "destruct_with_eqn"; ident | IDENT "destruct_with_eqn"; constr | IDENT "clearbody"; LIST1 hyp | IDENT "clear"; IDENT "dependent"; hyp | IDENT "clear"; "-"; LIST1 hyp | IDENT "clear"; LIST0 hyp | IDENT "revert"; IDENT "dependent"; hyp | IDENT "revert"; LIST1 hyp | IDENT "rename"; LIST1 rename SEP "," | IDENT "move"; hyp; "at"; IDENT "top" | IDENT "move"; hyp; "at"; IDENT "bottom" | IDENT "move"; hyp; IDENT "after"; hyp | IDENT "move"; hyp; IDENT "before"; hyp | IDENT "intro"; "at"; IDENT "top" | IDENT "intro"; "at"; IDENT "bottom" | IDENT "intro"; IDENT "after"; hyp | IDENT "intro"; IDENT "before"; hyp | IDENT "intro"; ident; "at"; IDENT "top" | IDENT "intro"; ident; "at"; IDENT "bottom" | IDENT "intro"; ident; IDENT "after"; hyp | IDENT "intro"; ident; IDENT "before"; hyp | IDENT "intro"; ident | IDENT "intro" | IDENT "eexists"; LIST1 bindings SEP "," | IDENT "eexists" | "exists"; LIST1 bindings SEP "," | "exists" | IDENT "esplit"; "with"; bindings | IDENT "split"; "with"; bindings | IDENT "symmetry"; "in"; in_clause | IDENT "specialize"; constr_with_bindings; "as"; simple_intropattern | IDENT "specialize"; constr_with_bindings | IDENT "econstructor"; nat_or_var; "with"; bindings | IDENT "econstructor"; nat_or_var | IDENT "econstructor" | IDENT "constructor"; nat_or_var; "with"; bindings | IDENT "constructor"; nat_or_var | IDENT "constructor" | IDENT "eright"; "with"; bindings | IDENT "right"; "with"; bindings | IDENT "eleft"; "with"; bindings | IDENT "left"; "with"; bindings | IDENT "exact"; uconstr | IDENT "with_strategy"; strategy_level_or_var; "["; LIST1 smart_global; "]"; ltac_expr LEVEL "3" | IDENT "guard"; test | IDENT "swap"; int_or_var; int_or_var | IDENT "cycle"; int_or_var | IDENT "unshelve"; ltac_expr LEVEL "1" | IDENT "transparent_abstract"; ltac_expr LEVEL "3"; "using"; ident | IDENT "transparent_abstract"; ltac_expr LEVEL "3" | IDENT "specialize_eqs"; hyp | IDENT "generalize_eqs_vars"; hyp | IDENT "generalize_eqs"; hyp | IDENT "stepr"; constr; "by"; tactic | IDENT "stepr"; constr | IDENT "stepl"; constr; "by"; tactic | IDENT "stepl"; constr | IDENT "instantiate"; "("; ident; ":="; lconstr; ")" | IDENT "instantiate"; "("; natural; ":="; lconstr; ")"; hloc | IDENT "evar"; test_lpar_id_colon; "("; ident; ":"; lconstr; ")" | IDENT "evar"; constr | IDENT "subst"; LIST1 hyp | IDENT "subst" | IDENT "notypeclasses"; IDENT "refine"; uconstr | IDENT "refine"; uconstr | IDENT "autorewrite"; "*"; "with"; LIST1 preident; clause; "using"; tactic | IDENT "autorewrite"; "*"; "with"; LIST1 preident; clause | IDENT "autorewrite"; "with"; LIST1 preident; clause; "using"; tactic | IDENT "autorewrite"; "with"; LIST1 preident; clause | IDENT "contradiction"; OPT constr_with_bindings | IDENT "decompose"; "["; LIST1 constr; "]"; constr | IDENT "decompose"; IDENT "record"; constr | IDENT "decompose"; IDENT "sum"; constr | IDENT "einjection"; "as"; LIST0 simple_intropattern | IDENT "einjection"; destruction_arg; "as"; LIST0 simple_intropattern | IDENT "einjection"; destruction_arg | IDENT "einjection" | IDENT "injection"; "as"; LIST0 simple_intropattern | IDENT "injection"; destruction_arg; "as"; LIST0 simple_intropattern | IDENT "injection"; destruction_arg | IDENT "injection" | IDENT "ediscriminate"; destruction_arg | IDENT "ediscriminate" | IDENT "discriminate"; destruction_arg | IDENT "discriminate" | IDENT "esimplify_eq"; destruction_arg | IDENT "esimplify_eq" | IDENT "simplify_eq"; destruction_arg | IDENT "simplify_eq" | IDENT "replace"; "<-"; uconstr; "with"; constr; clause; by_arg_tac | IDENT "replace"; "<-"; uconstr; clause | IDENT "replace"; "->"; uconstr; "with"; constr; clause; by_arg_tac | IDENT "replace"; "->"; uconstr; clause | IDENT "replace"; uconstr; "with"; constr; clause; by_arg_tac | IDENT "replace"; uconstr; clause | IDENT "assert_succeeds"; ltac_expr LEVEL "3" | IDENT "unify"; constr; constr; "with"; preident | IDENT "unify"; constr; constr | IDENT "autounfold_one"; hintbases; "in"; hyp | IDENT "autounfold_one"; hintbases | IDENT "autounfold"; hintbases; clause | IDENT "info_eauto"; OPT nat_or_var; auto_using; hintbases | IDENT "eauto"; OPT nat_or_var; auto_using; hintbases | IDENT "info_auto"; OPT nat_or_var; auto_using; hintbases | IDENT "auto"; OPT nat_or_var; auto_using; hintbases | IDENT "debug"; IDENT "eauto"; OPT nat_or_var; auto_using; hintbases | IDENT "debug"; IDENT "auto"; OPT nat_or_var; auto_using; hintbases | IDENT "debug"; IDENT "trivial"; auto_using; hintbases | IDENT "info_trivial"; auto_using; hintbases | IDENT "trivial"; auto_using; hintbases | IDENT "autoapply"; constr; "with"; preident | IDENT "typeclasses"; IDENT "eauto"; IDENT "bfs"; OPT nat_or_var; "with"; LIST1 preident | IDENT "typeclasses"; IDENT "eauto"; IDENT "bfs"; OPT nat_or_var | IDENT "typeclasses"; IDENT "eauto"; IDENT "dfs"; OPT nat_or_var; "with"; LIST1 preident | IDENT "typeclasses"; IDENT "eauto"; IDENT "dfs"; OPT nat_or_var | IDENT "typeclasses"; IDENT "eauto"; IDENT "best_effort"; OPT nat_or_var; "with"; LIST1 preident | IDENT "typeclasses"; IDENT "eauto"; IDENT "best_effort"; OPT nat_or_var | IDENT "typeclasses"; IDENT "eauto"; OPT nat_or_var; "with"; LIST1 preident | IDENT "typeclasses"; IDENT "eauto"; OPT nat_or_var | IDENT "decide"; IDENT "equality" | IDENT "decide"; constr; "with"; constr | IDENT "setoid_transitivity"; constr | IDENT "setoid_etransitivity" | IDENT "setoid_symmetry"; "in"; hyp | IDENT "setoid_symmetry" | IDENT "setoid_rewrite"; orient; constr_with_bindings; "at"; occurrences; "in"; hyp | IDENT "setoid_rewrite"; orient; constr_with_bindings; "at"; occurrences | IDENT "setoid_rewrite"; orient; constr_with_bindings; "in"; hyp; "at"; occurrences | IDENT "setoid_rewrite"; orient; constr_with_bindings; "in"; hyp | IDENT "setoid_rewrite"; orient; constr_with_bindings | IDENT "substitute"; orient; constr_with_bindings | IDENT "rewrite_strat"; rewstrategy; "in"; hyp | IDENT "rewrite_strat"; rewstrategy | IDENT "rewrite_db"; preident; "in"; hyp | IDENT "rewrite_db"; preident | IDENT "finish_timing"; "("; string; ")"; OPT string | IDENT "finish_timing"; OPT string | IDENT "restart_timer"; OPT string | IDENT "show"; IDENT "ltac"; IDENT "profile"; IDENT "cutoff"; integer | IDENT "show"; IDENT "ltac"; IDENT "profile"; string | IDENT "show"; IDENT "ltac"; IDENT "profile" | IDENT "reset"; IDENT "ltac"; IDENT "profile" | IDENT "stop"; IDENT "ltac"; IDENT "profiling" | IDENT "start"; IDENT "ltac"; IDENT "profiling" | IDENT "intros"; IDENT "until"; quantified_hypothesis | IDENT "intros"; ne_intropatterns | IDENT "intros" | IDENT "eintros"; ne_intropatterns | IDENT "eintros" | IDENT "apply"; "<-"; constr; "in"; hyp | IDENT "apply"; "<-"; constr | IDENT "apply"; "->"; constr; "in"; hyp | IDENT "apply"; "->"; constr | IDENT "apply"; LIST1 constr_with_bindings_arg SEP ","; in_hyp_as | IDENT "eapply"; LIST1 constr_with_bindings_arg SEP ","; in_hyp_as | IDENT "elim"; constr_with_bindings_arg; OPT eliminator | IDENT "eelim"; constr_with_bindings_arg; OPT eliminator | IDENT "case"; induction_clause_list | IDENT "ecase"; induction_clause_list | "fix"; ident; natural; "with"; LIST1 fixdecl | "fix"; ident; natural | "cofix"; ident; "with"; LIST1 cofixdecl | "cofix"; ident | IDENT "set"; bindings_with_parameters; clause | IDENT "set"; constr; as_name; clause | IDENT "eset"; bindings_with_parameters; clause | IDENT "eset"; constr; as_name; clause | IDENT "remember"; constr; as_name; eqn_ipat; clause_dft_all | IDENT "eremember"; constr; as_name; eqn_ipat; clause_dft_all | IDENT "assert"; lpar_id_coloneq; "("; identref; ":="; lconstr; ")" | IDENT "assert"; test_lpar_id_colon; "("; identref; ":"; lconstr; ")"; by_tactic | IDENT "assert"; constr; as_ipat; by_tactic | IDENT "eassert"; lpar_id_coloneq; "("; identref; ":="; lconstr; ")" | IDENT "eassert"; test_lpar_id_colon; "("; identref; ":"; lconstr; ")"; by_tactic | IDENT "eassert"; constr; as_ipat; by_tactic | IDENT "pose"; IDENT "proof"; lpar_id_coloneq; "("; identref; ":="; lconstr; ")" | IDENT "pose"; IDENT "proof"; lconstr; as_ipat | IDENT "pose"; bindings_with_parameters | IDENT "pose"; constr; as_name | IDENT "epose"; IDENT "proof"; lpar_id_coloneq; "("; identref; ":="; lconstr; ")" | IDENT "epose"; IDENT "proof"; lconstr; as_ipat | IDENT "epose"; bindings_with_parameters | IDENT "epose"; constr; as_name | IDENT "enough"; test_lpar_id_colon; "("; identref; ":"; lconstr; ")"; by_tactic | IDENT "enough"; constr; as_ipat; by_tactic | IDENT "eenough"; test_lpar_id_colon; "("; identref; ":"; lconstr; ")"; by_tactic | IDENT "eenough"; constr; as_ipat; by_tactic | IDENT "generalize"; IDENT "dependent"; constr | IDENT "generalize"; constr; LIST1 constr | IDENT "generalize"; constr; lookup_at_as_comma; occs; as_name; LIST0 [ ","; pattern_occ; as_name ] | IDENT "generalize"; constr | IDENT "induction"; induction_clause_list | IDENT "einduction"; induction_clause_list | IDENT "destruct"; induction_clause_list | IDENT "edestruct"; induction_clause_list | IDENT "rewrite"; "*"; orient; uconstr; "in"; hyp; "at"; occurrences; by_arg_tac | IDENT "rewrite"; "*"; orient; uconstr; "in"; hyp; by_arg_tac | IDENT "rewrite"; "*"; orient; uconstr; "at"; occurrences; "in"; hyp; by_arg_tac | IDENT "rewrite"; "*"; orient; uconstr; "at"; occurrences; by_arg_tac | IDENT "rewrite"; "*"; orient; uconstr; by_arg_tac | IDENT "rewrite"; LIST1 oriented_rewriter SEP ","; clause; by_tactic | IDENT "erewrite"; LIST1 oriented_rewriter SEP ","; clause; by_tactic | IDENT "dependent"; IDENT "destruction"; ident | IDENT "dependent"; IDENT "induction"; ident | IDENT "dependent"; IDENT "generalize_eqs_vars"; hyp | IDENT "dependent"; IDENT "generalize_eqs"; hyp | IDENT "dependent"; IDENT "rewrite"; orient; constr; "in"; hyp | IDENT "dependent"; IDENT "rewrite"; orient; constr | IDENT "dependent"; [ IDENT "simple"; IDENT "inversion" | IDENT "inversion" | IDENT "inversion_clear" ]; quantified_hypothesis; as_or_and_ipat; OPT [ "with"; constr ] | IDENT "simple"; IDENT "congruence"; OPT natural; "with"; LIST1 constr | IDENT "simple"; IDENT "congruence"; OPT natural | IDENT "simple"; IDENT "destruct"; quantified_hypothesis | IDENT "simple"; IDENT "induction"; quantified_hypothesis | IDENT "simple"; IDENT "subst" | IDENT "simple"; IDENT "notypeclasses"; IDENT "refine"; uconstr | IDENT "simple"; IDENT "refine"; uconstr | IDENT "simple"; IDENT "injection"; destruction_arg | IDENT "simple"; IDENT "injection" | IDENT "simple"; IDENT "apply"; LIST1 constr_with_bindings_arg SEP ","; in_hyp_as | IDENT "simple"; IDENT "eapply"; LIST1 constr_with_bindings_arg SEP ","; in_hyp_as | IDENT "simple"; IDENT "inversion"; quantified_hypothesis; as_or_and_ipat; in_hyp_list | IDENT "inversion_clear"; quantified_hypothesis; as_or_and_ipat; in_hyp_list | IDENT "inversion"; quantified_hypothesis; "using"; constr; in_hyp_list | IDENT "inversion"; quantified_hypothesis; as_or_and_ipat; in_hyp_list | IDENT "red"; clause | IDENT "hnf"; clause | IDENT "simpl"; OPT [ IDENT "head" ]; delta_flag; OPT ref_or_pattern_occ; clause | IDENT "cbv"; strategy_flag; clause | IDENT "cbn"; strategy_flag; clause | IDENT "lazy"; strategy_flag; clause | IDENT "compute"; delta_flag; clause | IDENT "vm_compute"; OPT ref_or_pattern_occ; clause | IDENT "native_compute"; OPT ref_or_pattern_occ; clause | IDENT "unfold"; LIST1 unfold_occ SEP ","; clause | IDENT "fold"; LIST1 constr; clause | IDENT "pattern"; LIST1 pattern_occ SEP ","; clause | IDENT "change"; conversion; clause | IDENT "change_no_check"; conversion; clause ] ] Entry tactic_value is [ LEFTA [ IDENT "firstorder_using"; ":"; "("; firstorder_using; ")" | IDENT "test"; ":"; "("; test; ")" | IDENT "comparison"; ":"; "("; comparison; ")" | IDENT "opthints"; ":"; "("; opthints; ")" | IDENT "auto_using"; ":"; "("; auto_using; ")" | IDENT "hintbases"; ":"; "("; hintbases; ")" | IDENT "eauto_search_strategy"; ":"; "("; eauto_search_strategy; ")" | IDENT "eauto_search_strategy_name"; ":"; "("; eauto_search_strategy_name; ")" | IDENT "debug"; ":"; "("; debug; ")" | IDENT "rewstrategy"; ":"; "("; rewstrategy; ")" | IDENT "glob_constr_with_bindings"; ":"; "("; constr_with_bindings; ")" | IDENT "strategy_level_or_var"; ":"; "("; strategy_level_or_var; ")" | IDENT "strategy_level"; ":"; "("; strategy_level; ")" | IDENT "test_lpar_id_colon"; ":"; "("; test_lpar_id_colon; ")" | IDENT "in_clause"; ":"; "("; in_clause; ")" | IDENT "by_arg_tac"; ":"; "("; by_arg_tac; ")" | IDENT "rename"; ":"; "("; rename; ")" | IDENT "hloc"; ":"; "("; hloc; ")" | IDENT "lglob"; ":"; "("; lconstr; ")" | IDENT "lconstr"; ":"; "("; lconstr; ")" | IDENT "glob"; ":"; "("; constr; ")" | IDENT "occurrences"; ":"; "("; occurrences; ")" | IDENT "natural"; ":"; "("; natural; ")" | IDENT "orient"; ":"; "("; orient; ")" | IDENT "ltac"; ":"; "("; ltac_expr LEVEL "5"; ")" | IDENT "open_constr"; ":"; "("; lconstr; ")" | IDENT "ipattern"; ":"; "("; simple_intropattern; ")" | IDENT "constr"; ":"; "("; lconstr; ")" | IDENT "uconstr"; ":"; "("; lconstr; ")" | IDENT "reference"; ":"; "("; reference; ")" | IDENT "ident"; ":"; "("; ident; ")" | IDENT "smart_global"; ":"; "("; smart_global; ")" | IDENT "string"; ":"; "("; string; ")" | IDENT "integer"; ":"; "("; integer; ")" | IDENT "fresh"; LIST0 fresh_id | IDENT "type_term"; uconstr | IDENT "numgoals" | constr_eval ] ] Rocq < Rocq < Toplevel input, characters 24-29: > Check Reject 230 ltac:(atom5 ; atom3). > ^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 5725-5725 with ( Replace Toplevel input, characters 5730-5730 with ) Rocq < Toplevel input, characters 31-36: > Check Reject 231 ltac:(atom4 ; atom4). > ^^^^^ Error: The reference atom4 was not found in the current environment. Rocq < Accept 232 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Accept 233 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Rocq < Toplevel input, characters 30-35: > Check Reject 240 ltac:(pre43 atom4 ; atom3). > ^^^^^ Error: The reference atom4 was not found in the current environment. Rocq < Accept 241 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Toplevel input, characters 29-34: > Check Reject 242 ltac:(pre44 atom4 ; atom3). > ^^^^^ Error: The reference atom4 was not found in the current environment. Rocq < Accept 243 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Rocq < Accept 250 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Accept 251 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Rocq < Toplevel input, characters 24-29: > Check Reject 260 ltac:(atom2 + atom2). > ^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 6164-6164 with ( Replace Toplevel input, characters 6169-6169 with ) Rocq < Toplevel input, characters 31-36: > Check Reject 261 ltac:(atom1 + atom3). > ^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation started on the left. This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Rocq < Accept 262 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Accept 263 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Rocq < Toplevel input, characters 30-35: > Check Reject 270 ltac:(pre22 atom2 + atom2). > ^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 6335-6335 with ( Replace Toplevel input, characters 6340-6340 with ) Rocq < Toplevel input, characters 23-34: > Check Reject 271 ltac:(pre21 atom1 + atom2). > ^^^^^^^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 6374-6374 with ( Replace Toplevel input, characters 6385-6385 with ) Rocq < Accept 272 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Accept 273 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < Rocq < Toplevel input, characters 24-36: > Check Reject 280 ltac:(atom1 post12 + atom2). > ^^^^^^^^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 6510-6510 with ( Replace Toplevel input, characters 6522-6522 with ) Rocq < Toplevel input, characters 31-36: > Check Reject 281 ltac:(atom1 + atom2 post12). > ^^^^^ Error: In ltac_expr, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace Toplevel input, characters 6564-6564 with ( Replace Toplevel input, characters 6569-6569 with ) Rocq < Accept 282 ?Goal : Parsing where ?A : [ |- Type] ?Goal : [ |- ?A] Rocq < rocq-9.2.0/test-suite/output-coqtop/LevelTolerance.v000066400000000000000000000147411516144147600225520ustar00rootroot00000000000000Set Warnings "+level-tolerance". Set Warnings "-closed-notation-not-level-0". Set Warnings "-level-0-notation-not-closed". Set Warnings "-postfix-notation-not-level-1". Inductive T := E : T | F : T -> T | G : T -> T -> T. Inductive Parsing {A} := Accept (_ : nat) (_ : A) | Reject (_ : nat) (_ : A). Declare Custom Entry expr. Notation "x 'op22' y" := (G x y) (in custom expr at level 3, only parsing, no associativity). Notation "x 'op12' y" := (G x y) (in custom expr at level 2, only parsing, right associativity). Notation "x 'op10' y" := (G x y) (in custom expr at level 1, only parsing, left associativity). Notation "[3 e ]" := e (e custom expr at level 3, only parsing). Notation "[2 e ]" := e (e custom expr at level 2, only parsing). Notation "[1 e ]" := e (e custom expr at level 1, only parsing). Notation "[0 e ]" := e (e custom expr at level 0, only parsing). Notation "'atom3'" := E (in custom expr at level 3, only parsing). Notation "'atom2'" := E (in custom expr at level 2, only parsing). Notation "'atom1'" := E (in custom expr at level 1, only parsing). Notation "'atom0'" := E (in custom expr at level 0, only parsing). Notation "'pre22' x" := (F x) (in custom expr at level 2, x at level 2, only parsing). Notation "'pre21' x" := (F x) (in custom expr at level 2, x at next level, only parsing). Notation "'pre11' x" := (F x) (in custom expr at level 1, x at level 1, only parsing). Notation "'pre10' x" := (F x) (in custom expr at level 1, x at next level, only parsing). Notation "'pre00' x" := (F x) (in custom expr at level 0, x at level 0, only parsing). Notation "'pre0x' x" := (F x) (in custom expr at level 0, x at next level, only parsing). Notation "x 'post12'" := (F x) (in custom expr at level 2, only parsing). Notation "x 'post11'" := (F x) (in custom expr at level 1, only parsing). Print Custom Grammar expr. (* The following sed script prints the first line with a wrong result: sed -En '/Accept/{/^(Rocq < )+Accept/!bf};/Reject/{/^> Check Reject/!bf};b;:f;p;q1' \ test-suite/output-coqtop/LevelTolerance.out The script checks that: - Each line containing "Reject" starts with "> Check Reject" - Each line containing "Accept" starts with one or more "Rocq < " followed by "Accept" In case of failure, it prints the line containing "Reject" or "Accept". *) Check Reject 10 [2 atom3 ]. Check Accept 11 [2 atom2 ]. Check Reject 12 [1 atom2 ]. Check Accept 13 [1 atom1 ]. Check Reject 20 [2 pre22 atom3 ]. Check Accept 21 [2 pre22 atom2 ]. Check Reject 22 [1 pre22 atom2 ]. Check Reject 30 [2 pre21 atom2 ]. Check Accept 31 [2 pre21 atom1 ]. Check Reject 32 [1 pre21 atom1 ]. Check Reject 40 [2 pre11 atom2 ]. Check Reject 41 [1 pre11 atom2 ]. Check Accept 42 [1 pre11 atom1 ]. Check Reject 43 [0 pre11 atom1 ]. Check Reject 50 [1 pre10 atom1 ]. Check Accept 51 [1 pre10 atom0 ]. Check Reject 52 [0 pre10 atom0 ]. Check Reject 60 [1 pre00 atom1 ]. Check Reject 61 [0 pre00 atom1 ]. Check Accept 62 [0 pre00 atom0 ]. Check Reject 70 [0 pre0x atom0 ]. Check Reject 80 [2 atom3 post12 ]. Check Reject 81 [2 atom2 post12 ]. Check Accept 82 [2 atom1 post12 ]. Check Reject 83 [1 atom1 post12 ]. Check Reject 90 [2 atom2 post11 ]. Check Accept 91 [2 atom1 post11 ]. Check Accept 92 [1 atom1 post11 ]. Check Reject 93 [0 atom1 post11 ]. Check Reject 100 [3 atom3 op22 atom2 ]. Check Reject 101 [3 atom2 op22 atom3 ]. Check Accept 102 [3 atom2 op22 atom2 ]. Check Reject 103 [2 atom2 op22 atom2 ]. Check Reject 110 [2 atom2 op12 atom2 ]. Check Reject 111 [2 atom1 op12 atom3 ]. Check Accept 112 [2 atom1 op12 atom2 ]. Check Reject 113 [1 atom1 op12 atom2 ]. Check Reject 120 [1 atom2 op10 atom0]. Check Reject 121 [1 atom1 op10 atom1]. Check Accept 122 [1 atom1 op10 atom0]. Check Reject 123 [0 atom1 op10 atom0]. Check Reject 130 [2 pre22 atom2 op12 atom2 ]. Check Reject 131 [2 pre21 atom1 op12 atom2 ]. Check Accept 132 [2 pre22 atom1 op12 atom2 ]. Check Reject 140 [2 atom2 post12 op12 atom2 ]. Check Reject 141 [2 atom1 post12 op12 atom2 ]. Check Accept 142 [2 atom1 post11 op12 atom2 ]. Check Accept 150 [2 atom1 op12 pre22 atom2 ]. Check Reject 151 [2 atom1 op12 pre21 atom2 ]. Check Accept 152 [2 atom1 op12 pre21 atom1 ]. Check Reject 160 [2 atom1 op12 atom2 post12 ]. Check Accept 161 [2 atom1 op12 atom1 post12 ]. Check Reject 162 [2 atom1 op10 atom1 post12 ]. Check Accept 163 [2 atom1 op10 atom0 post12 ]. Check Accept 170 [1 pre11 atom1 op10 atom0 ]. Check Reject 171 [1 pre10 atom1 op10 atom0 ]. Check Accept 172 [1 pre10 atom0 op10 atom0 ]. Check Reject 180 [1 atom1 post12 op10 atom0 ]. Check Accept 181 [1 atom1 post11 op10 atom0 ]. Check Reject 190 [1 atom1 op10 pre11 atom0 ]. Check Reject 191 [1 atom1 op10 pre10 atom0 ]. Check Accept 200 [2 atom1 op10 atom0 post12 ]. Check Reject 201 [1 atom1 op10 atom0 post12 ]. Check Accept 202 [1 atom1 op10 atom0 post11 ]. Check Reject 210 [2 atom1 op12 atom2 op12 atom2 ]. Check Accept 211 [2 atom1 op12 atom1 op12 atom2 ]. Check Reject 220 [1 atom1 op10 atom1 op10 atom0 ]. Check Accept 221 [1 atom1 op10 atom0 op10 atom0 ]. From Corelib Require Import Notations. Tactic Notation (at level 5) "atom5" := idtac. Tactic Notation (at level 4) "atom4" := idtac. Tactic Notation (at level 3) "atom3" := idtac. Tactic Notation (at level 2) "atom2" := idtac. Tactic Notation (at level 1) "atom1" := idtac. Tactic Notation (at level 4) "pre44" tactic4(x) := x. Tactic Notation (at level 4) "pre43" tactic3(x) := x. Tactic Notation (at level 2) "pre22" tactic2(x) := x. Tactic Notation (at level 2) "pre21" tactic1(x) := x. Tactic Notation (at level 4) tactic4(x) "post44" := x. Tactic Notation (at level 2) tactic2(x) "post12" := x. Print Grammar tactic. Check Reject 230 ltac:(atom5 ; atom3). Check Reject 231 ltac:(atom4 ; atom4). Check Accept 232 ltac:(atom4 ; atom3). Check Accept 233 ltac:(atom4 ; atom3 ; atom3). Check Reject 240 ltac:(pre43 atom4 ; atom3). Check Accept 241 ltac:(pre43 atom3 ; atom3). Check Reject 242 ltac:(pre44 atom4 ; atom3). Check Accept 243 ltac:(pre44 atom3 ; atom3). Check Accept 250 ltac:(atom4 post44 ; atom3). Check Accept 251 ltac:(atom4 ; atom3 post44). Check Reject 260 ltac:(atom2 + atom2). Check Reject 261 ltac:(atom1 + atom3). Check Accept 262 ltac:(atom1 + atom2). Check Accept 263 ltac:(atom1 + atom1 + atom2). Check Reject 270 ltac:(pre22 atom2 + atom2). Check Reject 271 ltac:(pre21 atom1 + atom2). Check Accept 272 ltac:(pre22 atom1 + atom2). Check Accept 273 ltac:(atom1 + pre22 atom2). Check Reject 280 ltac:(atom1 post12 + atom2). Check Reject 281 ltac:(atom1 + atom2 post12). Check Accept 282 ltac:(atom1 + atom1 post12). rocq-9.2.0/test-suite/output-coqtop/ListTags.out000066400000000000000000000016161516144147600217370ustar00rootroot00000000000000ROCQ_COLORS="constr.evar=94:constr.keyword=1:constr.notation=37:constr.path=95:constr.reference=92:constr.type=33;1:diff.added=48;2;0;141;0;4:diff.added.bg=48;2;0;91;0:diff.removed=48;2;170;0;0;4:diff.removed.bg=48;2;91;0;0:message.debug=37;45;1:message.error=37;41;1:message.prompt=32:message.warning=37;43;1:module.definition=91;1:module.keyword=1:tactic.keyword=1:tactic.primitive=92:tactic.string=91" constr.evar constr.keyword constr.notation constr.path constr.reference constr.type diff.added diff.added.bg diff.removed diff.removed.bg message.debug message.error message.prompt message.warning module.definition module.keyword tactic.keyword tactic.primitive tactic.string rocq-9.2.0/test-suite/output-coqtop/ListTags.v000066400000000000000000000000551516144147600213710ustar00rootroot00000000000000(* -*- coq-prog-args: ("-list-tags"); -*- *) rocq-9.2.0/test-suite/output-coqtop/LookaheadErrors.out000066400000000000000000000006621516144147600232710ustar00rootroot00000000000000 Rocq < Rocq < Rocq < Rocq < Toplevel input, characters 9-11: > Check ## []. > ^^ Error: Syntax error: '##' or [term] expected after '##' (in [term]). Rocq < Rocq < Rocq < Setting x constr at next level to match previous notation with longest common prefix: "## _". Rocq < Rocq < Toplevel input, characters 9-11: > Check ## []. > ^^ Error: Syntax error: '##' or [term] expected after '##' (in [term]). Rocq < rocq-9.2.0/test-suite/output-coqtop/LookaheadErrors.v000066400000000000000000000004101516144147600227160ustar00rootroot00000000000000#[warning="-level-0-notation-not-closed"] Notation "## x" := (S x) (at level 0). Notation "## ##" := 0 (at level 0). Check ## []. #[warning="-level-0-notation-not-closed"] Notation "## x" := (S x) (at level 0). Notation "## ## ##" := 0 (at level 0). Check ## []. rocq-9.2.0/test-suite/output-coqtop/ShowGoal.out000066400000000000000000000020061516144147600217220ustar00rootroot00000000000000 Rocq < 1 goal ============================ forall i : nat, exists j k : nat, i = j /\ j = k /\ i = k x < x < 1 focused goal (shelved: 1) i : nat ============================ exists k : nat, i = ?j /\ ?j = k /\ i = k x < 1 focused goal (shelved: 2) i : nat ============================ i = ?j /\ ?j = ?k /\ i = ?k x < 2 focused goals (shelved: 2) i : nat ============================ i = ?j goal 2 is: ?j = ?k /\ i = ?k x < 1 focused goal (shelved: 1) i : nat ============================ i = ?k /\ i = ?k x < 2 focused goals (shelved: 1) i : nat ============================ i = ?k goal 2 is: i = ?k x < 1 goal i : nat ============================ i = i x < goal ID 13 at state 5 i : nat ============================ i = ?j /\ ?j = ?k /\ i = ?k x < goal ID 13 at state 7 i : nat ============================ i = i /\ i = ?k /\ i = ?k x < goal ID 13 at state 9 i : nat ============================ i = i /\ i = i /\ i = i x < rocq-9.2.0/test-suite/output-coqtop/ShowGoal.v000066400000000000000000000003161516144147600213620ustar00rootroot00000000000000Lemma x: forall(i : nat), exists(j k : nat), i = j /\ j = k /\ i = k. Proof using. eexists. eexists. split. trivial. split. trivial. Show Goal 13 at 5. Show Goal 13 at 7. Show Goal 13 at 9. rocq-9.2.0/test-suite/output-coqtop/ShowProofDiffs.out000066400000000000000000000045721516144147600231130ustar00rootroot00000000000000 Rocq < Rocq < 1 goal ============================ forall i : nat, exists j k : nat, i = j /\ j = k /\ i = k x < x < 1 focused goal (shelved: 1) i : nat ============================ exists k : nat, i = ?j /\ ?j = k /\ i = k (fun i : nat => ex_intro (fun j : nat => exists k : nat, i = j /\ j = k /\ i = k) ?j ?Goal) x < 1 focused goal (shelved: 2) i : nat ============================ i = ?j /\ ?j = ?k /\ i = ?k (fun i : nat => ex_intro (fun j : nat => exists k : nat, i = j /\ j = k /\ i = k)  ?j (ex_intro (fun k : nat => i = ?j /\ ?j = k /\ i = k) ?k ?Goal)) x < 2 focused goals (shelved: 2) i : nat ============================ i = ?j goal 2 is: ?j = ?k /\ i = ?k (fun i : nat => ex_intro (fun j : nat => exists k : nat, i = j /\ j = k /\ i = k)  ?j (ex_intro (fun k : nat => i = ?j /\ ?j = k /\ i = k)  ?k (conj ?Goal ?Goal0))) x < rocq-9.2.0/test-suite/output-coqtop/ShowProofDiffs.v000066400000000000000000000003361516144147600225430ustar00rootroot00000000000000(* coq-prog-args: ("-color" "on" "-diffs" "on") *) Lemma x: forall(i : nat), exists(j k : nat), i = j /\ j = k /\ i = k. Proof using. eexists. Show Proof Diffs. eexists. Show Proof Diffs. split. Show Proof Diffs. rocq-9.2.0/test-suite/output-coqtop/attributes.out000066400000000000000000000023641516144147600223740ustar00rootroot00000000000000 Rocq < Toplevel input, characters 17-29: > #[canonical=yes, canonical=no] Definition a := 3. > ^^^^^^^^^^^^ Error: Attribute for canonical specified twice. Rocq < Rocq < Toplevel input, characters 29-43: > #[universes(polymorphic=yes,polymorphic=no)] Definition a := 3. > ^^^^^^^^^^^^^^ Error: key 'polymorphic' has been already set. Rocq < Rocq < Toplevel input, characters 13-28: > #[universes(polymorphic=foo)] Definition a := 3. > ^^^^^^^^^^^^^^^ Error: Invalid value 'foo' for key polymorphic use one of {yes, no} Rocq < Rocq < Toplevel input, characters 13-29: > #[universes(polymorphic(foo))] Definition a := 3. > ^^^^^^^^^^^^^^^^ Error: Invalid syntax polymorphic(foo), try polymorphic={yes, no} instead. Rocq < Rocq < Toplevel input, characters 13-33: > #[universes(polymorphic(foo,bar))] Definition a := 3. > ^^^^^^^^^^^^^^^^^^^^ Error: Invalid syntax polymorphic(foo, bar), try polymorphic={yes, no} instead. Rocq < Rocq < Toplevel input, characters 30-37: > #[universes(polymorphic=yes, bla=bla)] Definition a := 3. > ^^^^^^^ Error: This command does not support this attribute: universes. [unsupported-attributes,parsing,default] Rocq < rocq-9.2.0/test-suite/output-coqtop/attributes.v000066400000000000000000000005121516144147600220230ustar00rootroot00000000000000#[canonical=yes, canonical=no] Definition a := 3. #[universes(polymorphic=yes,polymorphic=no)] Definition a := 3. #[universes(polymorphic=foo)] Definition a := 3. #[universes(polymorphic(foo))] Definition a := 3. #[universes(polymorphic(foo,bar))] Definition a := 3. #[universes(polymorphic=yes, bla=bla)] Definition a := 3. rocq-9.2.0/test-suite/output-coqtop/backto.out000066400000000000000000000000531516144147600214420ustar00rootroot00000000000000 Rocq < Error: Unknown state 404. Rocq < rocq-9.2.0/test-suite/output-coqtop/backto.v000066400000000000000000000000141516144147600210750ustar00rootroot00000000000000BackTo 404. rocq-9.2.0/test-suite/output-coqtop/bug_12138.out000066400000000000000000000004001516144147600215060ustar00rootroot00000000000000 Rocq < Rocq < Rocq < Toplevel input, characters 0-1: > { > ^ Error: Syntax error: illegal begin of toplevel:vernac_toplevel. Rocq < Rocq < Rocq < Toplevel input, characters 58-59: > } > ^ Error: Syntax error: illegal begin of toplevel:vernac_toplevel. rocq-9.2.0/test-suite/output-coqtop/bug_12138.v000066400000000000000000000000771516144147600211560ustar00rootroot00000000000000{ Comments. (* coqtop parsing recovery skips to the dot *) } rocq-9.2.0/test-suite/output-coqtop/bug_16462.out000066400000000000000000000012211516144147600215140ustar00rootroot00000000000000 Rocq < foo is defined Rocq < bar is defined Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < Rocq < baz is defined Rocq < Rocq < 1 goal ============================ True Unnamed_thm < Top.Unnamed_thm_subproof Top.Unnamed_thm_subproof Toplevel input, characters 2-7: > baz I. > ^^^^^ Error: Tactic failure (level 1). In nested Ltac calls to "baz", "f" (bound to fun f x y => idtac v; f x), "f" (bound to fun _ => let v' := v in constr:((fun _ => ltac:(idtac v'; fail 1)))) and "(fun _ => ltac:(idtac v'; fail 1))" (with x:=I, v':=Top.Unnamed_thm_subproof, v:=Top.Unnamed_thm_subproof, H:=H), last term evaluation failed. Unnamed_thm < rocq-9.2.0/test-suite/output-coqtop/bug_16462.v000066400000000000000000000007131516144147600211570ustar00rootroot00000000000000Ltac foo x y := idtac; fail 1. Ltac bar x f := idtac; f foo x I. Ltac baz x := let H := fresh in simple refine (let H : True := _ in _); [ abstract exact I | let v := (eval cbv in H) in let F := ltac:(fun _ => let v' := v in constr:(fun _ => ltac:(idtac v'; fail 1))) in let f := ltac:(fun f x y => idtac v; f x) in f F () () ]. Set Ltac Backtrace. Goal True. baz I. rocq-9.2.0/test-suite/output-coqtop/bug_16745.out000066400000000000000000000006521516144147600215270ustar00rootroot00000000000000 Rocq < Rocq < 1 goal ============================ True Unnamed_thm < Unnamed_thm < Unnamed_thm < Unnamed_thm < Toplevel input, characters 111-112: > | match goal with x := ?v |- _ => exact v end]. > ^ Error: In environment x := Top.Unnamed_thm_subproof : nat The term "Top.Unnamed_thm_subproof" has type "nat" while it is expected to have type "True". Unnamed_thm < rocq-9.2.0/test-suite/output-coqtop/bug_16745.v000066400000000000000000000002121516144147600211550ustar00rootroot00000000000000 Goal True. Proof. unshelve refine (let x := _ : nat in _);[ abstract exact 0 | match goal with x := ?v |- _ => exact v end]. rocq-9.2.0/test-suite/output-coqtop/diffs_in_show_cmd.out000066400000000000000000000017721516144147600236540ustar00rootroot00000000000000 Rocq < Rocq < 1 goal ============================ forall n m : nat, n = m Unnamed_thm < 1 goal (?foo) ============================ forall n m : nat, n = m Unnamed_thm < 1 goal (?foo) n, m : nat ============================ n = m Unnamed_thm < Unnamed_thm < 1 goal (?foo) n, m : nat ============================ n = m Unnamed_thm < Unnamed_thm < 1 goal (?foo) n, m : nat ============================ n = m Unnamed_thm < goal 1 (?foo) is: n, m : nat ============================ n = m Unnamed_thm < goal foo (?foo) is: n, m : nat ============================ n = m Unnamed_thm < Unnamed_thm < Rocq < rocq-9.2.0/test-suite/output-coqtop/diffs_in_show_cmd.v000066400000000000000000000003321516144147600233010ustar00rootroot00000000000000(* -*- coq-prog-args: ("-color" "on"); -*- *) Goal forall n m:nat, n = m. refine ?[foo]. intros. Set Diffs "on". (* diffs should appear identically on each of these in coqtop: *) Show. Show 1. Show Diffs foo. Abort. rocq-9.2.0/test-suite/output-coqtop/ltac2_var_quot.out000066400000000000000000000026461516144147600231360ustar00rootroot00000000000000 Rocq < Rocq < Toplevel input, characters 7-9: > Check $x. > ^^ Error: Unbound value x Rocq < Rocq < Toplevel input, characters 16-17: > Check $preterm:x. > ^ Error: Unbound value x Rocq < Rocq < Toplevel input, characters 7-11: > Check $ x. > ^^^^ Error: Syntax error: [lconstr] expected after 'Check' (in [query_command]). Rocq < Rocq < Toplevel input, characters 7-18: > Check $ preterm:x. > ^^^^^^^^^^^ Error: Syntax error: [lconstr] expected after 'Check' (in [query_command]). Rocq < Rocq < Toplevel input, characters 7-20: > Check $ preterm : x. > ^^^^^^^^^^^^^ Error: Syntax error: [lconstr] expected after 'Check' (in [query_command]). Rocq < Rocq < Toplevel input, characters 18-19: > Check $preterm : x. > ^ Error: The reference x was not found in the current environment. Rocq < Rocq < Toplevel input, characters 16-24: > Check fun x => $preterm : x. > ^^^^^^^^ Error: Unbound value preterm Rocq < Rocq < Toplevel input, characters 17-18: > Check $preterm: x. > ^ Error: The reference x was not found in the current environment. Rocq < Rocq < Toplevel input, characters 16-24: > Check fun x => $preterm: x. > ^^^^^^^^ Error: Unbound value preterm Rocq < Rocq < Toplevel input, characters 7-19: > Check $ preterm :x. > ^^^^^^^^^^^^ Error: Syntax error: [lconstr] expected after 'Check' (in [query_command]). Rocq < rocq-9.2.0/test-suite/output-coqtop/ltac2_var_quot.v000066400000000000000000000003511516144147600225630ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Check $x. Check $preterm:x. Check $ x. Check $ preterm:x. Check $ preterm : x. Check $preterm : x. Check fun x => $preterm : x. Check $preterm: x. Check fun x => $preterm: x. Check $ preterm :x. rocq-9.2.0/test-suite/output-modulo-time/000077500000000000000000000000001516144147600203765ustar00rootroot00000000000000rocq-9.2.0/test-suite/output-modulo-time/abort.out000066400000000000000000000001261516144147600222350ustar00rootroot00000000000000Chars 40 - 50 [Goal~True.] 0. secs (0.u,0.s) Chars 51 - 57 [Abort.] 0. secs (0.u,0.s) rocq-9.2.0/test-suite/output-modulo-time/abort.v000066400000000000000000000001071516144147600216720ustar00rootroot00000000000000(* -*- coq-prog-args: ("-time") -*- *) Goal True. Abort. (* #15666 *) rocq-9.2.0/test-suite/output-modulo-time/ltacprof.out000066400000000000000000000013341516144147600227420ustar00rootroot00000000000000total time: 0.942s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─sleep' ----- 100.0% 100.0% 1 0.942s ─constructor 0.0% 0.0% 1 0.000s ─sleep ------ 0.0% 0.0% 0 0.000s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─sleep' ----- 100.0% 100.0% 1 0.942s ─constructor 0.0% 0.0% 1 0.000s ─sleep ------ 0.0% 0.0% 0 0.000s β””sleep' ----- 0.0% 0.0% 0 0.000s rocq-9.2.0/test-suite/output-modulo-time/ltacprof.v000066400000000000000000000003101516144147600223710ustar00rootroot00000000000000(* -*- coq-prog-args: ("-profile-ltac-cutoff" "0.0") -*- *) Ltac sleep' := do 100 (do 100 (do 100 idtac)). Ltac sleep := sleep'. Theorem x : True. Proof. idtac. idtac. sleep. constructor. Defined. rocq-9.2.0/test-suite/output-modulo-time/ltacprof_abstract.out000066400000000000000000000021641516144147600246270ustar00rootroot00000000000000total time: 0.986s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─abstract (sleep; constructor) 0.0% 100.0% 1 0.986s ─sleep' ----------------------- 100.0% 100.0% 1 0.986s ─constructor ------------------ 0.0% 0.0% 1 0.000s ─sleep ------------------------ 0.0% 0.0% 0 0.000s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─abstract (sleep; constructor) 0.0% 100.0% 1 0.986s β”œβ”€sleep' --------------------- 100.0% 100.0% 1 0.986s β”œβ”€constructor ---------------- 0.0% 0.0% 1 0.000s └─sleep ---------------------- 0.0% 0.0% 0 0.000s β””sleep' --------------------- 0.0% 0.0% 0 0.000s rocq-9.2.0/test-suite/output-modulo-time/ltacprof_abstract.v000066400000000000000000000003231516144147600242600ustar00rootroot00000000000000(* -*- coq-prog-args: ("-profile-ltac-cutoff" "0.0") -*- *) Ltac sleep' := do 100 (do 100 (do 100 idtac)). Ltac sleep := sleep'. Theorem x : True. Proof. idtac. idtac. abstract (sleep; constructor). Defined. rocq-9.2.0/test-suite/output-modulo-time/qed_time.out000066400000000000000000000003421516144147600227150ustar00rootroot00000000000000Chars 40 - 57 [Lemma~foo~:~True.] 0. secs (0.u,0.s) Chars 58 - 64 [Proof.] 0. secs (0.u,0.s) Chars 67 - 81 [Axiom~(X~:~nat).] 0. secs (0.u,0.s) Chars 84 - 92 [exact~I.] 0. secs (0.u,0.s) Chars 93 - 97 [Qed.] 0. secs (0.u,0.s) rocq-9.2.0/test-suite/output-modulo-time/qed_time.v000066400000000000000000000001421516144147600223510ustar00rootroot00000000000000(* -*- coq-prog-args: ("-time") -*- *) Lemma foo : True. Proof. Axiom X : nat. exact I. Qed. rocq-9.2.0/test-suite/output/000077500000000000000000000000001516144147600161455ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/Arguments.out000066400000000000000000000125551516144147600206530ustar00rootroot00000000000000Nat.sub : nat -> nat -> nat Nat.sub is not universe polymorphic Arguments Nat.sub (n m)%_nat_scope : simpl nomatch The reduction tactics unfold Nat.sub but avoid exposing match constructs Nat.sub is transparent Expands to: Constant Corelib.Init.Nat.sub Declared in library Corelib.Init.Nat, line 71, characters 9-12 Nat.sub : nat -> nat -> nat Nat.sub is not universe polymorphic Arguments Nat.sub n%_nat_scope / m%_nat_scope : simpl nomatch The reduction tactics unfold Nat.sub when applied to 1 argument but avoid exposing match constructs Nat.sub is transparent Expands to: Constant Corelib.Init.Nat.sub Declared in library Corelib.Init.Nat, line 71, characters 9-12 Nat.sub : nat -> nat -> nat Nat.sub is not universe polymorphic Arguments Nat.sub !n%_nat_scope / m%_nat_scope : simpl nomatch The reduction tactics unfold Nat.sub when the 1st argument evaluates to a constructor and when applied to 1 argument but avoid exposing match constructs Nat.sub is transparent Expands to: Constant Corelib.Init.Nat.sub Declared in library Corelib.Init.Nat, line 71, characters 9-12 Nat.sub : nat -> nat -> nat Nat.sub is not universe polymorphic Arguments Nat.sub (!n !m)%_nat_scope / The reduction tactics unfold Nat.sub when the 1st and 2nd arguments evaluate to a constructor and when applied to 2 arguments Nat.sub is transparent Expands to: Constant Corelib.Init.Nat.sub Declared in library Corelib.Init.Nat, line 71, characters 9-12 Nat.sub : nat -> nat -> nat Nat.sub is not universe polymorphic Arguments Nat.sub (!n !m)%_nat_scope The reduction tactics unfold Nat.sub when the 1st and 2nd arguments evaluate to a constructor Nat.sub is transparent Expands to: Constant Corelib.Init.Nat.sub Declared in library Corelib.Init.Nat, line 71, characters 9-12 pf : forall {D1 C1 : Type}, (D1 -> C1) -> forall [D2 C2 : Type], (D2 -> C2) -> D1 * D2 -> C1 * C2 pf is not universe polymorphic Arguments pf {D1}%_foo_scope {C1}%_type_scope f [D2 C2] g x : simpl never The reduction tactics never unfold pf pf is transparent Expands to: Constant Arguments.pf Declared in library Arguments, line 12, characters 11-13 fcomp : forall {A B C : Type}, (B -> C) -> (A -> B) -> A -> C fcomp is not universe polymorphic Arguments fcomp {A B C}%_type_scope f g x / The reduction tactics unfold fcomp when applied to 6 arguments fcomp is transparent Expands to: Constant Arguments.fcomp Declared in library Arguments, line 19, characters 11-16 volatile : nat -> nat volatile is not universe polymorphic Arguments volatile / x%_nat_scope The reduction tactics always unfold volatile volatile is transparent Expands to: Constant Arguments.volatile Declared in library Arguments, line 22, characters 11-19 f : T1 -> T2 -> nat -> unit -> nat -> nat f is not universe polymorphic Arguments f x y n%_nat_scope v m%_nat_scope f uses section variables T1 T2. f is transparent Expands to: Constant Arguments.S1.S2.f Declared in library Arguments, line 30, characters 9-10 f : T1 -> T2 -> nat -> unit -> nat -> nat f is not universe polymorphic Arguments f x y !n%_nat_scope !v !m%_nat_scope f uses section variables T1 T2. The reduction tactics unfold f when the 3rd, 4th and 5th arguments evaluate to a constructor f is transparent Expands to: Constant Arguments.S1.S2.f Declared in library Arguments, line 30, characters 9-10 f : forall [T2 : Type], T1 -> T2 -> nat -> unit -> nat -> nat f is not universe polymorphic Arguments f [T2]%_type_scope x y !n%_nat_scope !v !m%_nat_scope f uses section variable T1. The reduction tactics unfold f when the 4th, 5th and 6th arguments evaluate to a constructor f is transparent Expands to: Constant Arguments.S1.f Declared in library Arguments, line 30, characters 9-10 f : forall [T1 T2 : Type], T1 -> T2 -> nat -> unit -> nat -> nat f is not universe polymorphic Arguments f [T1 T2]%_type_scope x y !n%_nat_scope !v !m%_nat_scope The reduction tactics unfold f when the 5th, 6th and 7th arguments evaluate to a constructor f is transparent Expands to: Constant Arguments.f Declared in library Arguments, line 30, characters 9-10 = forall v : unit, f 0 0 5 v 3 = 2 : Prop = 2 = 2 : Prop f : forall T1 T2 : Type, T1 -> T2 -> nat -> unit -> nat -> nat f is not universe polymorphic Arguments f T1 T2 x y !n !v !m The reduction tactics unfold f when the 5th, 6th and 7th arguments evaluate to a constructor f is transparent Expands to: Constant Arguments.f Declared in library Arguments, line 30, characters 9-10 forall w : r, w 3 true = tt : Prop File "./output/Arguments.v", line 52, characters 28-29: The command has indeed failed with message: Unknown interpretation for notation "$". This notation is available in foo_scope and bar_scope. w 3 true = tt : Prop File "./output/Arguments.v", line 56, characters 0-28: The command has indeed failed with message: Extra arguments: _, _. volatilematch : nat -> nat volatilematch is not universe polymorphic Arguments volatilematch / n%_nat_scope : simpl nomatch The reduction tactics always unfold volatilematch but avoid exposing match constructs volatilematch is transparent Expands to: Constant Arguments.volatilematch Declared in library Arguments, line 58, characters 11-24 = fun n : nat => volatilematch n : nat -> nat *** [ f : A -> forall xxxxxxxxxxxxxx' xxxxxxxxxxxxxx'' : nat, nat -> xxxxxxxxxxxxxx' + xxxxxxxxxxxxxx' + xxxxxxxxxxxxxx'' = 0 ] Arguments f xxxxxxxxxxxxxx (xxxxxxxxxxxxxx' xxxxxxxxxxxxxx'' xxxxxxxxxxxxxx''')%_nat_scope rocq-9.2.0/test-suite/output/Arguments.v000066400000000000000000000037251516144147600203100ustar00rootroot00000000000000(* coq-prog-args: ("-top" "Arguments") *) Arguments Nat.sub n m : simpl nomatch. About Nat.sub. Arguments Nat.sub n / m : simpl nomatch. About Nat.sub. Arguments Nat.sub !n / m : simpl nomatch. About Nat.sub. Arguments Nat.sub !n !m /. About Nat.sub. Arguments Nat.sub !n !m. About Nat.sub. Definition pf (D1 C1 : Type) (f : D1 -> C1) (D2 C2 : Type) (g : D2 -> C2) := fun x => (f (fst x), g (snd x)). Declare Scope foo_scope. Declare Scope bar_scope. Delimit Scope foo_scope with F. Arguments pf {D1%_F C1%_type} f [D2 C2] g x : simpl never. About pf. Definition fcomp A B C f (g : A -> B) (x : A) : C := f (g x). Arguments fcomp {_ _ _}%_type_scope f g x /. About fcomp. Definition volatile := fun x : nat => x. Arguments volatile / _. About volatile. Set Implicit Arguments. Section S1. Variable T1 : Type. Section S2. Variable T2 : Type. Fixpoint f (x : T1) (y : T2) n (v : unit) m {struct n} : nat := match n, m with | 0,_ => 0 | S _, 0 => n | S n', S m' => f x y n' v m' end. About f. Global Arguments f x y !n !v !m. About f. End S2. About f. End S1. About f. Eval cbn in forall v, f 0 0 5 v 3 = 2. Eval cbn in f 0 0 5 tt 3 = 2. Arguments f : clear implicits and scopes. About f. Record r := { pi :> nat -> bool -> unit }. Notation "$" := 3 (only parsing) : foo_scope. Notation "$" := true (only parsing) : bar_scope. Delimit Scope bar_scope with B. Arguments pi _ _%_F _%_B. Check (forall w : r, pi w $ $ = tt). Fail Check (forall w : r, w $ $ = tt). Axiom w : r. Arguments w x%_F y%_B : extra scopes. Check (w $ $ = tt). Fail Arguments w _%_F _%_B. Definition volatilematch (n : nat) := match n with | O => O | S p => p end. Arguments volatilematch / n : simpl nomatch. About volatilematch. Eval simpl in fun n => volatilematch n. Module Formatting. Parameter A : Type. Parameter f : forall (xxxxxxxxxxxxxx : A) (xxxxxxxxxxxxxx' : nat) (xxxxxxxxxxxxxx'' : nat) (xxxxxxxxxxxxxx''' : nat), xxxxxxxxxxxxxx' + xxxxxxxxxxxxxx' + xxxxxxxxxxxxxx'' = 0. Print f. End Formatting. rocq-9.2.0/test-suite/output/ArgumentsScope.out000066400000000000000000000077371516144147600216530ustar00rootroot00000000000000a : bool -> bool a is not universe polymorphic Arguments a _%_bool_scope Expands to: Variable a b : bool -> bool b is not universe polymorphic Arguments b _%_bool_scope Expands to: Variable b negb'' : bool -> bool negb'' is not universe polymorphic Arguments negb'' b%_bool_scope negb'' is transparent Expands to: Constant ArgumentsScope.A.B.negb'' Declared in library ArgumentsScope, line 9, characters 11-17 negb' : bool -> bool negb' is not universe polymorphic Arguments negb' b%_bool_scope negb' is transparent Expands to: Constant ArgumentsScope.A.negb' Declared in library ArgumentsScope, line 6, characters 11-16 negb : bool -> bool negb is not universe polymorphic Arguments negb b%_bool_scope negb is transparent Expands to: Constant Corelib.Init.Datatypes.negb Declared in library Corelib.Init.Datatypes, line 88, characters 11-15 a : bool -> bool a is not universe polymorphic Expands to: Variable a b : bool -> bool b is not universe polymorphic Expands to: Variable b negb : bool -> bool negb is not universe polymorphic Arguments negb b negb is transparent Expands to: Constant Corelib.Init.Datatypes.negb Declared in library Corelib.Init.Datatypes, line 88, characters 11-15 negb' : bool -> bool negb' is not universe polymorphic Arguments negb' b negb' is transparent Expands to: Constant ArgumentsScope.A.negb' Declared in library ArgumentsScope, line 6, characters 11-16 negb'' : bool -> bool negb'' is not universe polymorphic Arguments negb'' b negb'' is transparent Expands to: Constant ArgumentsScope.A.B.negb'' Declared in library ArgumentsScope, line 9, characters 11-17 a : bool -> bool a is not universe polymorphic Expands to: Variable a negb : bool -> bool negb is not universe polymorphic Arguments negb b negb is transparent Expands to: Constant Corelib.Init.Datatypes.negb Declared in library Corelib.Init.Datatypes, line 88, characters 11-15 negb' : bool -> bool negb' is not universe polymorphic Arguments negb' b negb' is transparent Expands to: Constant ArgumentsScope.negb' Declared in library ArgumentsScope, line 6, characters 11-16 negb'' : bool -> bool negb'' is not universe polymorphic Arguments negb'' b negb'' is transparent Expands to: Constant ArgumentsScope.negb'' Declared in library ArgumentsScope, line 9, characters 11-17 f : bool -> bool f is not universe polymorphic Arguments f x%_A_scope%_B_scope f is transparent Expands to: Constant ArgumentsScope.f Declared in library ArgumentsScope, line 41, characters 11-12 f tt : bool f true : bool f : bool -> bool f is not universe polymorphic Arguments f x%_B_scope%_A_scope f is transparent Expands to: Constant ArgumentsScope.f Declared in library ArgumentsScope, line 41, characters 11-12 f tt : bool f false : bool g : bool -> bool g is not universe polymorphic Arguments g x%_A_scope%_B_scope g is transparent Expands to: Constant ArgumentsScope.g Declared in library ArgumentsScope, line 64, characters 11-12 g' : nat -> nat g' is not universe polymorphic Arguments g' x%_B_scope%_A_scope g' is transparent Expands to: Constant ArgumentsScope.g' Declared in library ArgumentsScope, line 71, characters 11-13 g'' : unit -> unit g'' is not universe polymorphic Arguments g'' x%_B_scope g'' is transparent Expands to: Constant ArgumentsScope.g'' Declared in library ArgumentsScope, line 78, characters 11-14 f : A -> B -> A f is not universe polymorphic Arguments f _%_X _%_Y f is transparent Expands to: Constant ArgumentsScope.SectionTest1.S.f Declared in library ArgumentsScope, line 91, characters 15-16 f : A -> B -> A f is not universe polymorphic f is transparent Expands to: Constant ArgumentsScope.SectionTest1.f Declared in library ArgumentsScope, line 91, characters 15-16 N.f : A -> A N.f is not universe polymorphic Arguments N.f _%_X Expands to: Constant ArgumentsScope.SectionTest2.N.f Declared in library ArgumentsScope, line 110, characters 12-13 g : A -> A g is not universe polymorphic Expands to: Constant ArgumentsScope.SectionTest2.g Declared in library ArgumentsScope, line 116, characters 8-9 rocq-9.2.0/test-suite/output/ArgumentsScope.v000066400000000000000000000045141516144147600212770ustar00rootroot00000000000000(* coq-prog-args: ("-top" "ArgumentsScope") *) (* A few tests to check Global Argument Scope command *) Section A. Variable a : bool -> bool. Definition negb' := negb. Section B. Variable b : bool -> bool. Definition negb'' := negb. About a. About b. About negb''. About negb'. About negb. Global Arguments negb'' _ : clear scopes. Global Arguments negb' _ : clear scopes. Global Arguments negb _ : clear scopes. Global Arguments a _ : clear scopes. Global Arguments b _ : clear scopes. About a. About b. About negb. About negb'. About negb''. End B. About a. End A. About negb. About negb'. About negb''. (* Check multiple scopes *) Declare Scope A_scope. Delimit Scope A_scope with A. Declare Scope B_scope. Delimit Scope B_scope with B. Notation "'tt'" := true : A_scope. Notation "'tt'" := false : B_scope. Definition f (x : bool) := x. Arguments f x%_A%_B. About f. Check f tt. Set Printing All. Check f tt. Unset Printing All. Arguments f x%_B%_A. About f. Check f tt. Set Printing All. Check f tt. Unset Printing All. (* Check binding scope inside/outside *) Bind Scope A_scope with bool. #[add_bottom] Bind Scope B_scope with bool. Definition g (x : bool) := x. About g. Bind Scope A_scope with nat. #[add_top] Bind Scope B_scope with nat. Definition g' (x : nat) := x. About g'. Bind Scope A_scope with unit. Bind Scope B_scope with unit. (* default: reset *) Definition g'' (x : unit) := x. About g''. Module SectionTest1. Inductive A :=. Inductive B :=. Declare Scope X. Section S. Declare Scope Y. Bind Scope X with A. Bind Scope Y with B. Definition f : A -> B -> A := fun x _ => x. About f. End S. (* In section, Bind Scope do not survive the section nor have a persistent effect: outside the section, f does not know any more about X and Y, even thoug X exists outside the section *) About f. End SectionTest1. Module SectionTest2. Inductive A :=. Module M. Declare Scope X. Bind Scope X with A. End M. Module N. Import M. Section S. Axiom f : A -> A. End S. End N. (* In modules, Bind Scope has a persistent effect even if not imported: f knows about X even if M not imported *) About N.f. Axiom g : A -> A. (* Without the Import, Bind Scope has however no effect on declarations not already aware of this binding *) About g. End SectionTest2. rocq-9.2.0/test-suite/output/Arguments_renaming.out000066400000000000000000000116121516144147600225240ustar00rootroot00000000000000File "./output/Arguments_renaming.v", line 2, characters 0-36: The command has indeed failed with message: Flag "rename" expected to rename A into B. File "./output/Arguments_renaming.v", line 3, characters 0-19: Warning: This command is just asserting the names of arguments of eq. If this is what you want, add ': assert' to silence the warning. If you want to clear implicit arguments, add ': clear implicits'. If you want to clear notation scopes, add ': clear scopes' [arguments-assert,vernacular,default] @eq_refl : forall (B : Type) (y : B), y = y eq_refl : ?y = ?y where ?y : [ |- nat] Inductive eq (A : Type) (x : A) : A -> Prop := eq_refl : x = x. Arguments eq {A}%_type_scope x _ Arguments eq_refl {B}%_type_scope {y}, [_] _ (where some original arguments have been renamed) eq_refl : forall {B : Type} {y : B}, y = y eq_refl is template universe polymorphic Arguments eq_refl {B}%_type_scope {y}, [_] _ (where some original arguments have been renamed) Expands to: Constructor Corelib.Init.Logic.eq_refl Declared in library Corelib.Init.Logic, line 380, characters 4-11 Inductive myEq (B : Type) (x : A) : A -> Prop := myrefl : B -> myEq B x x. Arguments myEq B%_type_scope x _ Arguments myrefl {C}%_type_scope x _ (where some original arguments have been renamed) myrefl : forall {C : Type} (x : A), C -> myEq C x x myrefl is template universe polymorphic Arguments myrefl {C}%_type_scope x _ (where some original arguments have been renamed) myrefl uses section variable A. Expands to: Constructor Arguments_renaming.Test1.myrefl Declared in library Arguments_renaming, line 25, characters 40-46 myplus = fix myplus (T : Type) (t : T) (n m : nat) {struct n} : nat := match n with | 0 => m | S n' => S (myplus T t n' m) end : forall {T : Type}, T -> nat -> nat -> nat Arguments myplus {Z}%_type_scope !t (!n m)%_nat_scope (where some original arguments have been renamed) myplus : forall {Z : Type}, Z -> nat -> nat -> nat myplus is not universe polymorphic Arguments myplus {Z}%_type_scope !t (!n m)%_nat_scope (where some original arguments have been renamed) The reduction tactics unfold myplus when the 2nd and 3rd arguments evaluate to a constructor myplus is transparent Expands to: Constant Arguments_renaming.Test1.myplus Declared in library Arguments_renaming, line 31, characters 9-15 @myplus : forall Z : Type, Z -> nat -> nat -> nat Inductive myEq (A B : Type) (x : A) : A -> Prop := myrefl : B -> myEq A B x x. Arguments myEq (A B)%_type_scope x _ Arguments myrefl A%_type_scope {C}%_type_scope x _ (where some original arguments have been renamed) myrefl : forall (A : Type) {C : Type} (x : A), C -> myEq A C x x myrefl is template universe polymorphic Arguments myrefl A%_type_scope {C}%_type_scope x _ (where some original arguments have been renamed) Expands to: Constructor Arguments_renaming.myrefl Declared in library Arguments_renaming, line 25, characters 40-46 myrefl : forall (A C : Type) (x : A), C -> myEq A C x x myplus = fix myplus (T : Type) (t : T) (n m : nat) {struct n} : nat := match n with | 0 => m | S n' => S (myplus T t n' m) end : forall {T : Type}, T -> nat -> nat -> nat Arguments myplus {Z}%_type_scope !t (!n m)%_nat_scope (where some original arguments have been renamed) myplus : forall {Z : Type}, Z -> nat -> nat -> nat myplus is not universe polymorphic Arguments myplus {Z}%_type_scope !t (!n m)%_nat_scope (where some original arguments have been renamed) The reduction tactics unfold myplus when the 2nd and 3rd arguments evaluate to a constructor myplus is transparent Expands to: Constant Arguments_renaming.myplus Declared in library Arguments_renaming, line 31, characters 9-15 @myplus : forall Z : Type, Z -> nat -> nat -> nat File "./output/Arguments_renaming.v", line 49, characters 0-36: The command has indeed failed with message: Argument lists should agree on the names they provide. File "./output/Arguments_renaming.v", line 50, characters 0-41: The command has indeed failed with message: Sequences of implicit arguments must be of different lengths. File "./output/Arguments_renaming.v", line 51, characters 0-37: The command has indeed failed with message: Argument number 3 is a trailing implicit, so it can't be declared non maximal. Please use { } instead of [ ]. File "./output/Arguments_renaming.v", line 52, characters 0-37: The command has indeed failed with message: Argument z is a trailing implicit, so it can't be declared non maximal. Please use { } instead of [ ]. File "./output/Arguments_renaming.v", line 53, characters 0-28: The command has indeed failed with message: Extra arguments: y. File "./output/Arguments_renaming.v", line 54, characters 0-26: The command has indeed failed with message: Flag "rename" expected to rename A into R. File "./output/Arguments_renaming.v", line 58, characters 2-36: The command has indeed failed with message: Arguments of section variables such as allTrue may not be renamed. rocq-9.2.0/test-suite/output/Arguments_renaming.v000066400000000000000000000022541516144147600221640ustar00rootroot00000000000000(* coq-prog-args: ("-top" "Arguments_renaming") *) Fail Arguments eq_refl {B y}, [B] y. Arguments eq A _ _. Arguments eq_refl A x : assert. Arguments eq_refl {B y}, [B] y : rename. Check @eq_refl. Check (eq_refl (B := nat)). Print eq_refl. About eq_refl. Goal 3 = 3. Succeed apply @eq_refl with (B := nat). Succeed apply @eq_refl with (y := 3). pose (y := nat). apply (@eq_refl y) with (y := 3). Qed. Section Test1. Variable A : Type. Inductive myEq B (x : A) : A -> Prop := myrefl : B -> myEq B x x. Global Arguments myrefl {C} x _ : rename. Print myrefl. About myrefl. Fixpoint myplus T (t : T) (n m : nat) {struct n} := match n with O => m | S n' => S (myplus T t n' m) end. Global Arguments myplus {Z} !t !n m : rename. Print myplus. About myplus. Check @myplus. End Test1. Print myrefl. About myrefl. Check myrefl. Print myplus. About myplus. Check @myplus. Fail Arguments eq_refl {F g}, [H] k. Fail Arguments eq_refl {F}, [F] : rename. Fail Arguments eq {A} x [_] : rename. Fail Arguments eq {A} x [z] : rename. Fail Arguments eq {F} x z y. Fail Arguments eq {R} s t. Section RenameVar. Variable allTrue : forall P, P. Fail Arguments allTrue Q : rename. End RenameVar. rocq-9.2.0/test-suite/output/BadOptionValueType.out000066400000000000000000000021071516144147600224140ustar00rootroot00000000000000File "./output/BadOptionValueType.v", line 1, characters 0-29: The command has indeed failed with message: Bad type of value for this option: expected int, got string. File "./output/BadOptionValueType.v", line 2, characters 0-25: The command has indeed failed with message: This is an option. A value must be provided. File "./output/BadOptionValueType.v", line 3, characters 0-27: The command has indeed failed with message: Bad type of value for this option: expected string, got int. File "./output/BadOptionValueType.v", line 4, characters 0-25: The command has indeed failed with message: This is an option. A value must be provided. File "./output/BadOptionValueType.v", line 5, characters 0-27: The command has indeed failed with message: This is a flag. It does not take a value. File "./output/BadOptionValueType.v", line 6, characters 0-23: The command has indeed failed with message: This is a flag. It does not take a value. File "./output/BadOptionValueType.v", line 7, characters 0-20: The command has indeed failed with message: This option does not support the "Unset" command. rocq-9.2.0/test-suite/output/BadOptionValueType.v000066400000000000000000000002671516144147600220570ustar00rootroot00000000000000Fail Set Default Timeout "2". Fail Set Default Timeout. Fail Set Bullet Behavior 2. Fail Set Bullet Behavior. Fail Set Debug Eauto "yes". Fail Set Debug Eauto 1. Fail Unset Warnings. rocq-9.2.0/test-suite/output/CantApplyBadType.out000066400000000000000000000016031516144147600220420ustar00rootroot00000000000000File "./output/CantApplyBadType.v", line 8, characters 16-24: The command has indeed failed with message: The term "Type" has type "Type@{u+1}" while it is expected to have type "Type@{u1}" (universe inconsistency: Cannot enforce u < u1 because u1 <= u). File "./output/CantApplyBadType.v", line 15, characters 0-58: The command has indeed failed with message: Illegal application: The term "idu1" of type "Type -> Type" cannot be applied to the term "Type" : "Type" This term has type "Type@{u+1}" which should be a subtype of "Type@{u1}". File "./output/CantApplyBadType.v", line 27, characters 2-108: The command has indeed failed with message: Illegal application: The term "idu1" of type "Type -> Type" cannot be applied to the term "Type" : "Type" This term has type "Type@{u+1}" which should be a subtype of "Type@{u1}". (universe inconsistency: Cannot enforce u < u1 because u1 <= u) rocq-9.2.0/test-suite/output/CantApplyBadType.v000066400000000000000000000015131516144147600215000ustar00rootroot00000000000000Universes u0 u1. Constraint u1 <= u0. Axiom idu1 : Type@{u1} -> Type@{u1}. Universe u. Constraint u = u0. (* pretyping error *) Fail Check idu1 Type@{u}. (* The command has indeed failed with message: The term "Type" has type "Type@{u+1}" while it is expected to have type "Type@{u1}" (universe inconsistency: Cannot enforce u < u1 because u1 <= u0 = u). *) (* kernel error *) Fail Type ltac:(refine (idu1 _); exact_no_check Type@{u}). (* The command has indeed failed with message: Illegal application: The term "idu1" of type "Type -> Type" cannot be applied to the term "Type" : "Type" This term has type "Type@{u+1}" which should be coercible to "Type@{u1}". *) (* typing.ml error *) Goal True. Fail let c := constr:(ltac:(refine (idu1 _); exact_no_check Type@{u})) in let _ := type of c in idtac. (* same as kernel *) Abort. rocq-9.2.0/test-suite/output/Cases.out000066400000000000000000000214621516144147600177410ustar00rootroot00000000000000t_rect = fun (P : t -> Type) (k : let x := t in forall x0 : x, P x0 -> P (k x0)) => fix F (t : t) : P t := match t as t0 return P t0 with | Cases.k _ x0 => k x0 (F x0) end : forall P : t -> Type, (let x := t in forall x0 : x, P x0 -> P (k x0)) -> forall t : t, P t Arguments t_rect (P k)%_function_scope t = fun d : TT => match d with | {| f3 := b |} => b end : TT -> 0 = 0 = fun d : TT => match d with | {| f3 := b |} => b end : TT -> 0 = 0 proj = fun (x y : nat) (P : nat -> Type) (def : P x) (prf : P y) => match eq_nat_dec x y with | left eqprf => match eqprf in _ = z return P z with | eq_refl => def end | right _ => prf end : forall (x y : nat) (P : nat -> Type), P x -> P y -> P y Arguments proj (x y)%_nat_scope P%_function_scope def prf foo = fix foo (A : Type) (l : list A) {struct l} : option A := match l with | nil => None | (x0 :: nil)%list => Some x0 | (x0 :: (_ :: _) as l0)%list => foo A l0 end : forall A : Type, list A -> option A Arguments foo A%_type_scope l%_list_scope uncast = fun (A : Type) (x : I A) => match x with | x0 <: _ => x0 end : forall A : Type, I A -> A Arguments uncast A%_type_scope x foo' = if A 0 then true else false : bool f = fun H : B => match H with | AC x => (fun x0 : P b => let b0 := b in (if b0 as b return P b -> True then fun _ : P true => Logic.I else fun _ : P false => Logic.I) x0) x end : B -> True File "./output/Cases.v", line 91, characters 0-98: The command has indeed failed with message: Non exhaustive pattern-matching: no clause found for pattern gadtTy _ _ File "./output/Cases.v", line 108, characters 17-18: The command has indeed failed with message: In environment texpDenote : forall t : type, texp t -> typeDenote t t : type e : texp t n : nat The term "n" has type "nat" while it is expected to have type "typeDenote ?t@{t1:=Nat}". fun '{{n, m, _}} => n + m : J -> nat fun '{{n, m, p}} => n + m + p : J -> nat fun '(D n m p q) => n + m + p + q : J -> nat File "./output/Cases.v", line 126, characters 29-42: The command has indeed failed with message: Once notations are expanded, the resulting constructor D (in type J) is expected to be applied to no arguments while it is actually applied to 1 argument. lem1 = fun dd : nat * nat => let (bb, cc) as aa return aa = aa := dd in eq_refl : forall k : nat * nat, k = k Arguments lem1 k lem2 = fun dd : bool => if dd as aa return aa = aa then eq_refl else eq_refl : forall k : bool, k = k Arguments lem2 k%_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 Arguments lem3 k 1 goal x : nat n, n0 := match x + 0 with | 0 | S _ => 0 end : nat e, e0 := match x + 0 as y return y = y with | 0 => eq_refl | S n => eq_refl end : x + 0 = x + 0 n1, n2 := match x with | 0 | S _ => 0 end : nat e1, e2 := match x return x = x with | 0 => eq_refl | S n => eq_refl end : x = x ============================ x + 0 = 0 1 goal p : nat a, a0 := match eq_refl as y in _ = e return y = y /\ e = e with | eq_refl => conj eq_refl eq_refl end : eq_refl = eq_refl /\ p = p a1, a2 := match eq_refl in _ = e return p = p /\ e = e with | eq_refl => conj eq_refl eq_refl end : p = p /\ p = p ============================ eq_refl = eq_refl fun x : comparison => match x with | Eq => 1 | _ => 0 end : comparison -> nat fun x : comparison => match x with | Eq => 1 | Lt => 0 | Gt => 0 end : comparison -> nat fun x : comparison => match x with | Eq => 1 | Lt | Gt => 0 end : comparison -> nat fun x : comparison => match x return nat with | Eq => S O | Lt => O | Gt => O end : forall _ : comparison, nat fun x : K => match x with | a3 | a4 => 3 | _ => 2 end : K -> nat fun x : K => match x with | a1 | a2 => 4 | a3 => 3 | _ => 2 end : K -> nat fun x : K => match x with | a1 | a2 => 4 | a4 => 3 | _ => 2 end : K -> nat fun x : K => match x with | a1 | a3 | a4 => 3 | _ => 2 end : K -> nat File "./output/Cases.v", line 224, characters 38-86: The command has indeed failed with message: Pattern "S _, _" is redundant in this clause. stray = fun N : Tree => match N with | App (App Node (Node as strayvariable)) _ | App (App Node (App Node _ as strayvariable)) _ | App (App Node (App (App Node Node) (App _ _) as strayvariable)) _ | App (App Node (App (App Node (App _ _)) _ as strayvariable)) _ | App (App Node (App (App (App _ _) _) _ as strayvariable)) _ => strayvariable | _ => Node end : Tree -> Tree Arguments stray N File "./output/Cases.v", line 253, characters 4-5: Warning: Unused variable B might be a misspelled constructor. Use _ or _B to silence this warning. [unused-pattern-matching-variable,default] File "./output/Cases.v", line 266, characters 33-40: The command has indeed failed with message: Application of arguments to a recursive notation not supported in patterns. File "./output/Cases.v", line 267, characters 33-43: The command has indeed failed with message: The constructor cons (in type list) is expected to be applied to 2 arguments while it is actually applied to 3 arguments. File "./output/Cases.v", line 268, characters 33-39: The command has indeed failed with message: The constructor cons (in type list) is expected to be applied to 2 arguments while it is actually applied to 1 argument. File "./output/Cases.v", line 271, characters 33-45: The command has indeed failed with message: The constructor D' (in type J') is expected to be applied to 4 arguments (or 6 arguments when including variables for local definitions) while it is actually applied to 5 arguments. fun x : J' bool (true, true) => match x with | @D' _ _ _ _ _ m _ e => existT (fun x0 : nat => x0 = x0) m e end : J' bool (true, true) -> {x : nat & x = x} fun x : J' bool (true, true) => match x with | D' _ _ _ n p _ => n + p end : J' bool (true, true) -> nat File "./output/Cases.v", line 277, characters 33-40: The command has indeed failed with message: Application of arguments to a recursive notation not supported in patterns. File "./output/Cases.v", line 278, characters 33-43: The command has indeed failed with message: The constructor cons (in type list) is expected to be applied to 2 arguments while it is actually applied to 3 arguments. File "./output/Cases.v", line 279, characters 33-39: The command has indeed failed with message: The constructor cons (in type list) is expected to be applied to 2 arguments while it is actually applied to 1 argument. File "./output/Cases.v", line 281, characters 33-39: The command has indeed failed with message: The constructor D' (in type J') is expected to be applied to 3 arguments (or 4 arguments when including variables for local definitions) while it is actually applied to 2 arguments. File "./output/Cases.v", line 282, characters 33-45: The command has indeed failed with message: The constructor D' (in type J') is expected to be applied to 3 arguments (or 4 arguments when including variables for local definitions) while it is actually applied to 5 arguments. fun x : J' bool (true, true) => match x with | @D' _ _ _ _ _ m _ e => existT (fun x0 : nat => x0 = x0) m e end : J' bool (true, true) -> {x : nat & x = x} fun x : J' bool (true, true) => match x with | @D' _ _ _ _ n _ p _ => (n, p) end : J' bool (true, true) -> nat * nat File "./output/Cases.v", line 313, characters 3-4: Warning: Unused variable x might be a misspelled constructor. Use _ or _x to silence this warning. [unused-pattern-matching-variable,default] File "./output/Cases.v", line 314, characters 6-7: Warning: Unused variable y might be a misspelled constructor. Use _ or _y to silence this warning. [unused-pattern-matching-variable,default] File "./output/Cases.v", line 314, characters 3-4: Warning: Unused variable x might be a misspelled constructor. Use _ or _x to silence this warning. [unused-pattern-matching-variable,default] File "./output/Cases.v", line 325, characters 4-12: The command has indeed failed with message: Once notations are expanded, the resulting constructor true (in type bool) is expected to be applied to no arguments while it is actually applied to 2 arguments. rocq-9.2.0/test-suite/output/Cases.v000066400000000000000000000216221516144147600173750ustar00rootroot00000000000000(* Cases with let-in in constructors types *) Unset Printing Allow Match Default Clause. Inductive t : Set := k : let x := t in x -> x. Print t_rect. Record TT : Type := CTT { f1 := 0 : nat; f2: nat; f3 : f1=f1 }. Eval cbv in fun d:TT => match d return 0 = 0 with CTT a _ b => b end. Eval lazy in fun d:TT => match d return 0 = 0 with CTT a _ b => b end. (* Do not contract nested patterns with dependent return type *) (* see bug #1699 *) Require Import TestSuite.arith. Definition proj (x y:nat) (P:nat -> Type) (def:P x) (prf:P y) : P y := match eq_nat_dec x y return P y with | left eqprf => match eqprf in (_ = z) return (P z) with | refl_equal => def end | _ => prf end. Print proj. (* Use notations even below aliases *) Require Import TestSuite.list. Fixpoint foo (A:Type) (l:list A) : option A := match l with | nil => None | cons x0 nil => Some x0 | cons x0 (cons x1 xs as l0) => foo A l0 end. Print foo. (* Accept and use notation with binded parameters *) #[universes(template)] Inductive I (A: Type) : Type := C : A -> I A. Notation "x <: T" := (C T x) (at level 38). Definition uncast A (x : I A) := match x with | x <: _ => x end. Print uncast. (* Do not duplicate the matched term *) Axiom A : nat -> bool. Definition foo' := match A 0 with | true => true | x => x end. Print foo'. (* Was bug #3293 (eta-expansion at "match" printing time was failing because of let-in's interpreted as being part of the expansion) *) Axiom b : bool. Axiom P : bool -> Prop. Inductive B : Prop := AC : P b -> B. Definition f : B -> True. Proof. intros [x]. destruct b as [|] ; exact Logic.I. Defined. Print f. (* Was enhancement request #5142 (error message reported on the most general return clause heuristic) *) Inductive gadt : Type -> Type := | gadtNat : nat -> gadt nat | gadtTy : forall T, T -> gadt T. Fail Definition gadt_id T (x: gadt T) : gadt T := match x with | gadtNat n => gadtNat n end. (* A variant of #5142 (see Satrajit Roy's example on coq-club (Oct 17, 2016)) *) Inductive type:Set:=Nat. Inductive tbinop:type->type->type->Set:= TPlus : tbinop Nat Nat Nat. Inductive texp:type->Set:= |TNConst:nat->texp Nat |TBinop:forall t1 t2 t, tbinop t1 t2 t->texp t1->texp t2->texp t. Definition typeDenote(t:type):Set:= match t with Nat => nat end. (* We expect a failure on TBinop *) Fail Fixpoint texpDenote t (e:texp t):typeDenote t:= match e with | TNConst n => n | TBinop t1 t2 _ b e1 e2 => O end. (* Test notations with local definitions in constructors *) Inductive J := D : forall n m, let p := n+m in nat -> J. Notation "{{ n , m , q }}" := (D n m q). Check fun x : J => let '{{n, m, _}} := x in n + m. Check fun x : J => let '{{n, m, p}} := x in n + m + p. (* Cannot use the notation because of the dependency in p *) Check fun x => let '(D n m p q) := x in n+m+p+q. (* This used to succeed, being interpreted as "let '{{n, m, p}} := ..." *) Fail Check fun x : J => let '{{n, m, _}} p := x in n + m + p. (* Test use of idents bound to ltac names in a "match" *) Lemma lem1 : forall k, k=k :>nat * nat. let x := fresh "aa" in let y := fresh "bb" in let z := fresh "cc" in let k := fresh "dd" in refine (fun k : nat * nat => match k as x return x = x with (y,z) => eq_refl end). Qed. Print lem1. Lemma lem2 : forall k, k=k :> bool. let x := fresh "aa" in let y := fresh "bb" in let z := fresh "cc" in let k := fresh "dd" in refine (fun k => if k as x return x = x then eq_refl else eq_refl). Qed. Print lem2. Lemma lem3 : forall k, k=k :>nat * nat. let x := fresh "aa" in let y := fresh "bb" in let z := fresh "cc" in let k := fresh "dd" in refine (fun k : nat * nat => let (y,z) as x return x = x := k in eq_refl). Qed. Print lem3. Lemma lem4 x : x+0=0. match goal with |- ?y = _ => pose (match y with 0 => 0 | S n => 0 end) end. match goal with |- ?y = _ => pose (match y as y with 0 => 0 | S n => 0 end) end. match goal with |- ?y = _ => pose (match y as y return y=y with 0 => eq_refl | S n => eq_refl end) end. match goal with |- ?y = _ => pose (match y return y=y with 0 => eq_refl | S n => eq_refl end) end. match goal with |- ?y + _ = _ => pose (match y with 0 => 0 | S n => 0 end) end. match goal with |- ?y + _ = _ => pose (match y as y with 0 => 0 | S n => 0 end) end. match goal with |- ?y + _ = _ => pose (match y as y return y=y with 0 => eq_refl | S n => eq_refl end) end. match goal with |- ?y + _ = _ => pose (match y return y=y with 0 => eq_refl | S n => eq_refl end) end. Show. Abort. Lemma lem5 (p:nat) : eq_refl p = eq_refl p. let y := fresh "n" in (* Checking that y is hidden *) let z := fresh "e" in (* Checking that z is hidden *) match goal with |- ?y = _ => pose (match y as y in _ = z return y=y /\ z=z with eq_refl => conj eq_refl eq_refl end) end. let y := fresh "n" in let z := fresh "e" in match goal with |- ?y = _ => pose (match y in _ = z return y=y /\ z=z with eq_refl => conj eq_refl eq_refl end) end. let y := fresh "n" in let z := fresh "e" in match goal with |- eq_refl ?y = _ => pose (match eq_refl y in _ = z return y=y /\ z=z with eq_refl => conj eq_refl eq_refl end) end. let p := fresh "p" in let z := fresh "e" in match goal with |- eq_refl ?p = _ => pose (match eq_refl p in _ = z return p=p /\ z=z with eq_refl => conj eq_refl eq_refl end) end. Show. Abort. Set Printing Allow Match Default Clause. (***************************************************) (* Testing strategy for factorizing cases branches *) (* Factorization + default clause *) Check fun x => match x with Eq => 1 | _ => 0 end. (* No factorization *) Unset Printing Factorizable Match Patterns. Check fun x => match x with Eq => 1 | _ => 0 end. Set Printing Factorizable Match Patterns. (* Factorization but no default clause *) Unset Printing Allow Match Default Clause. Check fun x => match x with Eq => 1 | _ => 0 end. Set Printing Allow Match Default Clause. (* No factorization in printing all mode *) Set Printing All. Check fun x => match x with Eq => 1 | _ => 0 end. Unset Printing All. (* Several clauses *) Inductive K := a1|a2|a3|a4|a5|a6. Check fun x => match x with a3 | a4 => 3 | _ => 2 end. Check fun x => match x with a3 => 3 | a2 | a1 => 4 | _ => 2 end. Check fun x => match x with a4 => 3 | a2 | a1 => 4 | _ => 2 end. Check fun x => match x with a3 | a4 | a1 => 3 | _ => 2 end. (* Test redundant clause within a disjunctive pattern *) Fail Check fun n m => match n, m with 0, 0 | _, S _ | S 0, _ | S (S _ | _), _ => false end. Module Bug11231. (* Missing dependency in computing if a clause is a default clause *) Inductive Tree: Set := | Node : Tree | App : Tree -> Tree -> Tree . Definition stray N := match N with | App (App Node (App (App Node Node) Node)) _ => Node | App (App Node strayvariable) _ => strayvariable | _ => Node end. Print stray. End Bug11231. Module Wish12762. Inductive foo := a | b | c. Definition bar (f : foo) := match f with | a => 0 | B => 1 end. End Wish12762. Module ConstructorArgumentsNumber. Arguments cons {A} _ _. Inductive J' A {B} (C:=(A*B)%type) (c:C) := D' : forall n {m}, let p := n+m in m=m -> J' A c. Unset Asymmetric Patterns. Fail Check fun x => match x with (y,z) w => y+z+w end. Fail Check fun x => match x with cons y z w => 0 | nil => 0 end. Fail Check fun x => match x with cons y => 0 | nil => 0 end. (* Missing a let-in to be in let-in mode *) Fail Check fun x => match x with D' _ _ n p e => 0 end. Check fun x : J' bool (true,true) => match x with D' _ _ n e => existT (fun x => eq x x) _ e end. Check fun x : J' bool (true,true) => match x with D' _ _ _ n p e => n+p end. Set Asymmetric Patterns. Fail Check fun x => match x with (y,z) w => y+z+w end. Fail Check fun x => match x with cons y z w => 0 | nil => 0 end. Fail Check fun x => match x with cons y => 0 | nil => 0 end. Fail Check fun x => match x with D' n _ => 0 end. Fail Check fun x => match x with D' n m p e _ => 0 end. Check fun x : J' bool (true,true) => match x with D' n m e => existT (fun x => eq x x) m e end. Check fun x : J' bool (true,true) => match x with D' n m p e => (n,p) end. End ConstructorArgumentsNumber. Module Bug14207. Inductive type {base_type : Type} := base (t : base_type) | arrow (s d : type). Global Arguments type : clear implicits. Fixpoint interp {base_type} (base_interp : base_type -> Type) (t : type base_type) : Type := match t with | base t => base_interp t | arrow s d => @interp _ base_interp s -> @interp _ base_interp d end. Axiom admit : forall {T}, T. Section with_base. Context {base_type : Type} {base_interp : base_type -> Type}. Local Abbreviation type := (@type base_type). Fixpoint default {t} : interp base_interp t := match t with | base x => admit | arrow s d => fun _ => @default d end. End with_base. Definition c := match 0, 0 with | S (S x), y => 0 | x, S (S y) => 1 | x, y => 2 end. End Bug14207. Module Bug17071. Notation "x :||: l" := (true x l) (at level 51). Fail Check match true with | x :||: l => 0 end. End Bug17071. rocq-9.2.0/test-suite/output/ClassMissingInstance.out000066400000000000000000000003211516144147600227560ustar00rootroot00000000000000File "./output/ClassMissingInstance.v", line 7, characters 0-28: The command has indeed failed with message: Could not find an instance for the following existential variables: ?arg_2 : Foo 1 ?arg_20 : Foo 2 rocq-9.2.0/test-suite/output/ClassMissingInstance.v000066400000000000000000000002051516144147600224150ustar00rootroot00000000000000 Class Foo (n:nat) := {}. Axiom thing : forall n {_:Foo n}, nat. (* both missing args are reported *) Fail Goal thing 1 = thing 2. rocq-9.2.0/test-suite/output/CoercionOnHole.out000066400000000000000000000004341516144147600215450ustar00rootroot00000000000000File "./output/CoercionOnHole.v", line 23, characters 17-20: The command has indeed failed with message: In environment e1, e2, v1 : expr IH1 : eval e1 v1 IHe2 : exists v : expr, eval e2 v The term "IH1" has type "eval e1 v1" while it is expected to have type "eval e1 (Const ?v1)". rocq-9.2.0/test-suite/output/CoercionOnHole.v000066400000000000000000000007421516144147600212050ustar00rootroot00000000000000 Inductive expr := | Const: nat -> expr | Add: expr -> expr -> expr. Inductive eval: expr -> expr -> Prop := | EConst: forall n, eval (Const n) (Const n) | EAdd: forall e1 v1 e2 v2, eval e1 (Const v1) -> eval e2 (Const v2) -> eval (Add e1 e2) (Const (v1 + v2)). Coercion Const: nat >-> expr. Lemma eval_total: forall e, exists v, eval e v. Proof. induction e. - admit. - destruct IHe1 as [v1 IH1]. eexists. eapply EAdd. + Fail exact IH1. Abort. rocq-9.2.0/test-suite/output/Coercions.out000066400000000000000000000001321516144147600206160ustar00rootroot00000000000000P x : Prop R x x : Prop fun (x : foo) (n : nat) => x n : foo -> nat -> nat rocq-9.2.0/test-suite/output/Coercions.v000066400000000000000000000006351516144147600202640ustar00rootroot00000000000000(* Submitted by Randy Pollack *) Record pred (S : Set) : Type := {sp_pred :> S -> Prop}. Record rel (S : Set) : Type := {sr_rel :> S -> S -> Prop}. Section testSection. Variables (S : Set) (P : pred S) (R : rel S) (x : S). Check (P x). Check (R x x). End testSection. (* Check the removal of coercions with target Funclass *) Record foo : Type := {D :> nat -> nat}. Check (fun (x : foo) (n : nat) => x n). rocq-9.2.0/test-suite/output/CompactContexts.out000066400000000000000000000002131516144147600220100ustar00rootroot000000000000001 goal hP1 : True a : nat b : list nat h : forall x : nat, {y : nat | y > x} h2 : True ============================ False rocq-9.2.0/test-suite/output/CompactContexts.v000066400000000000000000000002151516144147600214500ustar00rootroot00000000000000Set Printing Compact Contexts. Lemma f (hP1:True) (a:nat) (b:list nat) (h:forall (x:nat) , { y:nat | y > x}) (h2:True): False. Show. Abort. rocq-9.2.0/test-suite/output/DebugFlags.out000066400000000000000000000003231516144147600206770ustar00rootroot00000000000000File "./output/DebugFlags.v", line 1, characters 0-33: Warning: There is no debug flag "ThisFlagDoesNotExist". [unknown-debug-flag,default] Debug: [Cbv] Unfolding Corelib.Init.Datatypes.id = tt : unit rocq-9.2.0/test-suite/output/DebugFlags.v000066400000000000000000000001101516144147600203270ustar00rootroot00000000000000Set Debug "ThisFlagDoesNotExist". Set Debug "Cbv". Eval cbv in id tt. rocq-9.2.0/test-suite/output/DebugRelevances.out000066400000000000000000000026131516144147600217360ustar00rootroot00000000000000foo@{u} = fun (A : (* Relevant *) Type) (a : (* Relevant *) A) => a : forall A : (* Relevant *) Type, A -> A Arguments foo A%_type_scope a foo'@{} = fun (A : (* Relevant *) Prop) (a : (* Relevant *) A) => a : forall A : (* Relevant *) Prop, A -> A Arguments foo' A%_type_scope a bar@{} = fun (A : (* Relevant *) SProp) (a : (* Irrelevant *) A) => a : forall A : (* Relevant *) SProp, A -> A Arguments bar A%_type_scope a baz@{s ; u} = fun (A : (* Relevant *) Type@{s ; _}) (a : (* s *) A) => a : forall A : (* Relevant *) Type@{s ; _}, A -> A Arguments baz A%_type_scope a boz@{s s' ; u} = fun (A : (* Relevant *) Type@{s ; _}) (B : (* Relevant *) Type@{s' ; _}) (a : (* s *) hide) (_ : (* s' *) hide) => a : forall (A : (* Relevant *) Type@{s ; _}) (B : (* Relevant *) Type@{s' ; _}), hide -> hide -> hide Arguments boz (A B)%_type_scope a b 1 goal f := fun (A : (* Relevant *) Type) (_ : (* Ξ±8 *) A) => A : forall (A : (* Relevant *) Type) (_ : (* Ξ±8 *) A), Type ============================ True 1 goal f := fun (A : (* Relevant *) Type) (_ : (* Relevant *) A) => A : forall (A : (* Relevant *) Type) (_ : (* Relevant *) A), Type ============================ True let x := 0 in x : nat fix f (n : (* Relevant *) nat) : nat := 0 : nat -> nat match 0 with | 0 | _ => 0 end : nat fun v : (* Relevant *) R => p v : R -> nat rocq-9.2.0/test-suite/output/DebugRelevances.v000066400000000000000000000022371516144147600213760ustar00rootroot00000000000000 Set Universe Polymorphism. Set Printing Relevance Marks. Definition foo (A:Type) (a:A) := a. Definition foo' (A:Prop) (a:A) := a. Definition bar (A:SProp) (a:A) := a. Definition baz@{s;u|} (A:Type@{s;u}) (a:A) := a. Definition hide@{s;u|} {A:Type@{s;u}} := A. Definition boz@{s s';u|} (A:Type@{s;u}) (B:Type@{s';u}) (a:@hide A) (b:@hide B) := a. Print foo. Print foo'. Print bar. Print baz. (* arguments a and b are printed separately because they have different relevances even though the types are printed the same (difference hidden by implicit arguments) *) Print boz. Inductive sFalse : SProp := . Goal True. Unset Printing Notations. (* arrow notation has no binder so relevance isn't printed *) pose (f:=fun A (a:A) => A). Show. let _ := constr:(f nat) in idtac. Show. Abort. Set Printing Notations. (* TODO print relevance of letin *) Check let x := 0 in x. (* TODO print relevance of fixpoints (should be fix f (* Relevant *) ...) *) Check fix f (n:nat) := 0. (* TODO print case relevance *) Check match 0 with 0 | _ => 0 end. (* TODO print primitive projection relevance *) Set Primitive Projections. Record R := { p : nat }. Check fun v => v.(p). rocq-9.2.0/test-suite/output/DeclareSort.out000066400000000000000000000047061516144147600211140ustar00rootroot00000000000000File "./output/DeclareSort.v", line 4, characters 35-36: The command has indeed failed with message: In environment A : Type@{s ; _} The term "A" has type "Type@{s ; _}" while it is expected to have type "Type@{s' ; _}" (universe inconsistency: Cannot enforce Type@{s | Set} <= Type@{s' | DeclareSort.21}). File "./output/DeclareSort.v", line 6, characters 35-36: The command has indeed failed with message: In environment A : Type@{s ; _} The term "A" has type "Type@{s ; _}" while it is expected to have type "Type" (universe inconsistency: Cannot enforce Type@{s | Set} <= DeclareSort.22). File "./output/DeclareSort.v", line 8, characters 26-27: The command has indeed failed with message: In environment A : Set The term "A" has type "Set" while it is expected to have type "Type@{s ; _}" (universe inconsistency: Cannot enforce Set <= Type@{s | DeclareSort.23}). fun A : Type@{s ; _} => A : Type@{s ; _} : Type@{s ; _} -> Type@{s ; _} File "./output/DeclareSort.v", line 15, characters 2-15: The command has indeed failed with message: Cannot declare global sort qualities inside sections foo : Type@{S1 ; _} -> Type@{S2 ; _} foo@{S2 ; } : Type@{S1 ; _} -> Type@{S2 ; _} foo is universe polymorphic Arguments foo _%_type_scope Expands to: Constant DeclareSort.foo Declared in library DeclareSort, line 19, characters 8-11 foo@{S2 ; } : Type@{S1 ; Set} -> Type@{S2 ; Set} (* S2 ; |= *) foo is universe polymorphic Arguments foo _%_type_scope Expands to: Constant DeclareSort.foo Declared in library DeclareSort, line 19, characters 8-11 foo@{SProp ; } : Type@{S1 ; Set} -> SProp : Type@{S1 ; Set} -> SProp foo@{Type ; } : Type@{S1 ; Set} -> Set : Type@{S1 ; Set} -> Set File "./output/DeclareSort.v", line 30, characters 11-14: The command has indeed failed with message: The term "foo@{Ξ±6 ; }" has type "Type@{S1 ; Set} -> Type@{Ξ±6 ; Set}" while it is expected to have type "SProp -> ?T" (universe inconsistency: Cannot enforce SProp <= Type@{S1 | Set}). File "./output/DeclareSort.v", line 31, characters 11-14: The command has indeed failed with message: The term "foo@{Ξ±8 ; }" has type "Type@{S1 ; Set} -> Type@{Ξ±8 ; Set}" while it is expected to have type "Set -> ?T" (universe inconsistency: Cannot enforce Set <= Type@{S1 | Set}). foo@{Type ; } : Type@{S1 ; Set} -> Set : Type@{S1 ; Set} -> Set File "./output/DeclareSort.v", line 36, characters 4-18: The command has indeed failed with message: Cannot declare global sort qualities inside module types. rocq-9.2.0/test-suite/output/DeclareSort.v000066400000000000000000000011351516144147600205430ustar00rootroot00000000000000Sort s. Sort s'. Fail Check fun (A:Type@{s;Set}) => A : Type@{s';_}. Fail Check fun (A:Type@{s;Set}) => A : Type. Fail Check fun (A:Set) => A : Type@{s;_}. Check fun (A:Type@{s;Set}) => A : Type@{s;_}. Sort S1. Section S. Fail Sort S2. Local Set Universe Polymorphism. Sort S2. Axiom foo : Type@{S1;Set} -> Type@{S2;Set}. Check foo. End S. About foo. Set Printing Universes. About foo. Check foo : _ -> SProp. Check foo : _ -> Set. Fail Check foo : SProp -> _. Fail Check foo : Set -> _. Check foo : Type@{S1;Set} -> Set. Module Type T. Module M. Fail Sort foz. End M. End T. rocq-9.2.0/test-suite/output/DelimitScope.out000066400000000000000000000001471516144147600212610ustar00rootroot00000000000000(~~ false)%bool : bool (~~ false)%B : bool (~~ false)%B : bool (~~ false)%B : bool rocq-9.2.0/test-suite/output/DelimitScope.v000066400000000000000000000004211516144147600207120ustar00rootroot00000000000000Reserved Notation "~~ b" (at level 35, right associativity). Notation "~~ b" := (negb b) : bool_scope. Check negb false. Delimit Scope bool_scope with B. Check negb false. (* %bool still works even if not used by printing *) Check (~~ false)%bool. Check (~~ false)%B. rocq-9.2.0/test-suite/output/Deprecation.out000066400000000000000000000025141516144147600211350ustar00rootroot00000000000000File "./output/Deprecation.v", line 4, characters 33-48: The command has indeed failed with message: This command does not support this attribute: why. [unsupported-attributes,parsing,default] File "./output/Deprecation.v", line 7, characters 0-3: Warning: Tactic foo is deprecated since X.Y. Use idtac instead. [deprecated-tactic-since-X.Y,deprecated-since-X.Y,deprecated-tactic,deprecated,default] File "./output/Deprecation.v", line 19, characters 5-8: The command has indeed failed with message: Tactic foo is deprecated since X.Y. Use idtac instead. [deprecated-tactic-since-X.Y,deprecated-since-X.Y,deprecated-tactic,deprecated,default] File "./output/Deprecation.v", line 26, characters 0-3: Warning: Tactic bar is deprecated since library X.Y. Use baz instead. [deprecated-tactic-since-library-X.Y,deprecated-since-library-X.Y,deprecated-tactic,deprecated,default] File "./output/Deprecation.v", line 31, characters 6-9: Warning: hello [warn-reference,user-warn,default] bar : nat File "./output/Deprecation.v", line 36, characters 6-13: Warning: use less +s [warn-notation-fragile-too-many-plus,too-many-plus,fragile,warn-notation,user-warn,default] 1 ++ 2 : nat File "./output/Deprecation.v", line 37, characters 6-12: Warning: use less +s 2 [warn-notation-too-many-plus,too-many-plus,warn-notation,user-warn,default] 1 ++ 2 : nat rocq-9.2.0/test-suite/output/Deprecation.v000066400000000000000000000012561516144147600205750ustar00rootroot00000000000000#[deprecated(since = "X.Y", note = "Use idtac instead.")] Ltac foo := idtac. Fail #[deprecated(since="today", why="I said so")] Definition foo := 1. Goal True. foo. Abort. Set Warnings "-deprecated-since-X.Y". Goal True. foo. Abort. Set Warnings "+deprecated-since-X.Y". Goal True. Fail foo. Abort. #[deprecated(since = "library X.Y", note = "Use baz instead.")] Ltac bar := idtac. Goal True. bar. Abort. #[warn(note="hello")] Definition bar := 2. Check bar. #[warn(note="use less +s", cats="too many plus,fragile")] Notation "x +++ y" := (x + y) (at level 2). #[warn(note="use less +s 2", cats="too-many-plus")] Notation "x ++ y" := (x + y). Check 1 +++ 2. Check 1 ++ 2. rocq-9.2.0/test-suite/output/Emacs_and_diffs.out000066400000000000000000000000001516144147600217110ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/Emacs_and_diffs.v000066400000000000000000000001441516144147600213600ustar00rootroot00000000000000(* coq-prog-args: ("-emacs") *) Set Diffs "on". (* verify this does not produce an error message *) rocq-9.2.0/test-suite/output/EmptyExtraction.out000066400000000000000000000012101516144147600220270ustar00rootroot00000000000000 type empty_set = | Extracted code successfully compiled type empty_set = | type 'x not = 'x -> empty_set Extracted code successfully compiled type empty_set = | type 'x not = 'x -> empty_set (** val foo : 'a1 not not not -> 'a1 not **) let foo p q = p (fun r -> r q) Extracted code successfully compiled type empty = | Extracted code successfully compiled type empty = | (** val empty_rect : empty -> 'a1 **) let empty_rect _ = assert false (* absurd case *) Extracted code successfully compiled type empty = | (** val bar : empty -> 'a1 **) let bar _ = assert false (* absurd case *) Extracted code successfully compiled rocq-9.2.0/test-suite/output/EmptyExtraction.v000066400000000000000000000017741516144147600215040ustar00rootroot00000000000000From Corelib Require Extraction. (** Testing extraction of stdlib Empty_set *) Recursive Extraction Empty_set. Extraction TestCompile Empty_set. (** Testing extraction of a type level not *) Definition not : Type -> Type := fun X => X -> Empty_set. Recursive Extraction not. Extraction TestCompile not. (** Testing extraction of a simple proof using not but no elimination. *) Definition foo : forall X, not (not (not X)) -> not X. Proof. intros X. intros p q. apply p. intros r. apply r. exact q. Defined. Recursive Extraction foo. Extraction TestCompile foo. (** Testing extraction of a user defined Empty *) Inductive Empty : Set := . Recursive Extraction Empty. Extraction TestCompile Empty. (** Testing extraction of Empty eliminator *) Recursive Extraction Empty_rect. Extraction TestCompile Empty_rect. (** Testing extraction of an slightly different eliminator *) Definition bar : Empty -> forall A, A := fun x => Empty_rect _ x. Recursive Extraction bar. Extraction TestCompile bar. rocq-9.2.0/test-suite/output/EqNotation.out000066400000000000000000000002471516144147600207620ustar00rootroot00000000000000File "./output/EqNotation.v", line 2, characters 21-26: The command has indeed failed with message: Cannot infer the implicit parameter A of eq whose type is "Type". rocq-9.2.0/test-suite/output/EqNotation.v000066400000000000000000000001231516144147600204110ustar00rootroot00000000000000(* should mention "the implicit parameter A of eq" *) Fail Type (forall x, x = x). rocq-9.2.0/test-suite/output/ErrorInCanonicalStructures.out000066400000000000000000000006361516144147600241770ustar00rootroot00000000000000File "./output/ErrorInCanonicalStructures.v", line 5, characters 0-29: The command has indeed failed with message: Could not declare a canonical structure Foo. Expected an instance of a record or structure. File "./output/ErrorInCanonicalStructures.v", line 7, characters 0-29: The command has indeed failed with message: Could not declare a canonical structure bar. Expected an instance of a record or structure. rocq-9.2.0/test-suite/output/ErrorInCanonicalStructures.v000066400000000000000000000002201516144147600236220ustar00rootroot00000000000000Record Foo := MkFoo { field1 : nat; field2 : nat -> nat }. Definition bar := 99. Fail Canonical Structure Foo. Fail Canonical Structure bar. rocq-9.2.0/test-suite/output/ErrorInModule.out000066400000000000000000000002531516144147600214240ustar00rootroot00000000000000File "./output/ErrorInModule.v", line 3, characters 25-36: The command has indeed failed with message: The reference nonexistent was not found in the current environment. rocq-9.2.0/test-suite/output/ErrorInModule.v000066400000000000000000000001501516144147600210560ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vos") -*- *) Module M. Fail Definition foo := nonexistent. End M. rocq-9.2.0/test-suite/output/ErrorInSection.out000066400000000000000000000002541516144147600216040ustar00rootroot00000000000000File "./output/ErrorInSection.v", line 3, characters 25-36: The command has indeed failed with message: The reference nonexistent was not found in the current environment. rocq-9.2.0/test-suite/output/ErrorInSection.v000066400000000000000000000001511516144147600212360ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vos") -*- *) Section S. Fail Definition foo := nonexistent. End S. rocq-9.2.0/test-suite/output/ErrorLocation_12152.out000066400000000000000000000004441516144147600222140ustar00rootroot00000000000000File "./output/ErrorLocation_12152.v", line 3, characters 5-12: The command has indeed failed with message: No product even after head-reduction. File "./output/ErrorLocation_12152.v", line 4, characters 5-13: The command has indeed failed with message: No product even after head-reduction. rocq-9.2.0/test-suite/output/ErrorLocation_12152.v000066400000000000000000000001241516144147600216450ustar00rootroot00000000000000(* Reported in #12152 *) Goal True. Fail intro H; auto. Fail intros H; auto. Abort. rocq-9.2.0/test-suite/output/ErrorLocation_12255.out000066400000000000000000000003201516144147600222110ustar00rootroot00000000000000File "./output/ErrorLocation_12255.v", line 4, characters 5-21: The command has indeed failed with message: Ltac variable x is bound to i > 0 of type constr which cannot be coerced to an evaluable reference. rocq-9.2.0/test-suite/output/ErrorLocation_12255.v000066400000000000000000000001751516144147600216570ustar00rootroot00000000000000Ltac can_unfold x := let b := eval cbv delta [x] in x in idtac. Definition i := O. Goal False. Fail can_unfold (i>0). Abort. rocq-9.2.0/test-suite/output/ErrorLocation_12774.out000066400000000000000000000007671516144147600222360ustar00rootroot00000000000000File "./output/ErrorLocation_12774.v", line 5, characters 18-19: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "Type". File "./output/ErrorLocation_12774.v", line 6, characters 14-15: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "Type". File "./output/ErrorLocation_12774.v", line 7, characters 5-6: The command has indeed failed with message: No product even after head-reduction. rocq-9.2.0/test-suite/output/ErrorLocation_12774.v000066400000000000000000000001511516144147600216570ustar00rootroot00000000000000Ltac f := simpl. Ltac g := auto; intro. Goal Type. Fail simpl; exact 0. Fail f; exact 0. Fail g. Abort. rocq-9.2.0/test-suite/output/ErrorLocation_13241.out000066400000000000000000000004431516144147600222130ustar00rootroot00000000000000File "./output/ErrorLocation_13241.v", line 5, characters 5-6: The command has indeed failed with message: No product even after head-reduction. File "./output/ErrorLocation_13241.v", line 13, characters 5-6: The command has indeed failed with message: No product even after head-reduction. rocq-9.2.0/test-suite/output/ErrorLocation_13241.v000066400000000000000000000002561516144147600216530ustar00rootroot00000000000000Module Direct. Ltac a := intro. Ltac b := a. Goal True. Fail b. Abort. End Direct. Module Thunked. Ltac a _ := intro. Ltac b := a (). Goal True. Fail b. Abort. End Thunked. rocq-9.2.0/test-suite/output/ErrorLocation_ltac.out000066400000000000000000000010321516144147600224570ustar00rootroot00000000000000File "./output/ErrorLocation_ltac.v", line 5, characters 12-16: The command has indeed failed with message: Tactic failure: Cannot solve this goal. File "./output/ErrorLocation_ltac.v", line 6, characters 12-13: The command has indeed failed with message: Tactic failure. File "./output/ErrorLocation_ltac.v", line 7, characters 12-15: The command has indeed failed with message: Not a negated primitive equality. File "./output/ErrorLocation_ltac.v", line 8, characters 27-28: The command has indeed failed with message: Tactic failure. rocq-9.2.0/test-suite/output/ErrorLocation_ltac.v000066400000000000000000000002131516144147600221150ustar00rootroot00000000000000Ltac f := fail. Ltac inj := injection. Goal False. Fail idtac; easy. Fail idtac; f. Fail idtac; inj. Fail let x := fail in x || x. Abort. rocq-9.2.0/test-suite/output/ErrorLocation_tac_in_term.out000066400000000000000000000021311516144147600240210ustar00rootroot00000000000000File "./output/ErrorLocation_tac_in_term.v", line 3, characters 11-14: The command has indeed failed with message: Illegal application (Non-functional construction): The expression "I" of type "True" cannot be applied to the term "I" : "True" File "./output/ErrorLocation_tac_in_term.v", line 8, characters 0-15: The command has indeed failed with message: Illegal application (Non-functional construction): The expression "I" of type "True" cannot be applied to the term "I" : "True" File "./output/ErrorLocation_tac_in_term.v", line 12, characters 16-19: The command has indeed failed with message: Illegal application (Non-functional construction): The expression "I" of type "True" cannot be applied to the term "I" : "True" File "./output/ErrorLocation_tac_in_term.v", line 17, characters 26-30: The command has indeed failed with message: The term "true" has type "bool" while it is expected to have type "nat". File "./output/ErrorLocation_tac_in_term.v", line 18, characters 17-25: The command has indeed failed with message: The term "true" has type "bool" while it is expected to have type "nat". rocq-9.2.0/test-suite/output/ErrorLocation_tac_in_term.v000066400000000000000000000005541516144147600234660ustar00rootroot00000000000000Abbreviation foo := (I I). Fail Check foo. Abbreviation bar := (ltac:(exact (I I))) (only parsing). (* whole command: it would be nice to be more precise *) Fail Check bar. Abbreviation baz x := (ltac:(exact x)) (only parsing). Fail Check baz (I I). Ltac f x y := apply (x y). Goal True. Fail apply ltac:(apply (S true)). Fail apply ltac:(f S true). Abort. rocq-9.2.0/test-suite/output/ErrorModuleWith.out000066400000000000000000000012721516144147600217730ustar00rootroot00000000000000File "./output/ErrorModuleWith.v", line 5, characters 0-53: The command has indeed failed with message: No field named V in module A.B of M. File "./output/ErrorModuleWith.v", line 6, characters 0-53: The command has indeed failed with message: No field named C in module A of M. File "./output/ErrorModuleWith.v", line 7, characters 0-49: The command has indeed failed with message: No field named V in M. File "./output/ErrorModuleWith.v", line 8, characters 0-53: The command has indeed failed with message: Module A' of M not expected to be a functor. File "./output/ErrorModuleWith.v", line 13, characters 0-38: The command has indeed failed with message: Module M2 is not equal to module M1. rocq-9.2.0/test-suite/output/ErrorModuleWith.v000066400000000000000000000010571516144147600214320ustar00rootroot00000000000000Module Type T. Axiom U : Type. End T. Module Type S. Declare Module B : T. End S. Module Type S' (X : T). Axiom U' : Type. End S'. Module Type M. Declare Module A : S. Declare Module A' : S'. End M. Fail Module Type N := M with Definition A.B.V := nat. Fail Module Type N := M with Definition A.C.U := nat. Fail Module Type N := M with Definition V := nat. Fail Module Type N := M with Definition A'.U' := nat. Module M1. Axiom T : Type. End M1. Module M2. Axiom T : Type. End M2. Module Type V. Module N := M1. End V. Fail Module Q : V with Module N := M2. rocq-9.2.0/test-suite/output/Error_msg_diffs.out000066400000000000000000000012511516144147600220070ustar00rootroot00000000000000File "./output/Error_msg_diffs.v", line 34, characters 5-16: The command has indeed failed with message: In environment T : Type p : T -> bool a : T t1, t2 : btree T IH1 : count p (rev_tree t1) = count p t1 IH2 : count p (rev_tree t2) = count p t2 Unable to unify "(if p a then 1 else 0) + (count p t1 + count p t2)" with "(if p a then 1 else 0) + (count p t2 + count p t1)". rocq-9.2.0/test-suite/output/Error_msg_diffs.v000066400000000000000000000016671516144147600214600ustar00rootroot00000000000000(* coq-prog-args: ("-color" "on" "-diffs" "on" "-async-proofs" "off") *) (* Re: -async-proofs off, see https://github.com/rocq-prover/rocq/issues/9671 *) (* Shows diffs in an error message for an "Unable to unify" error *) Require Import ListDef. Inductive btree (T : Type) : Type := Leaf | Node (val : T) (t1 t2 : btree T). Arguments Leaf {T}. Arguments Node {T}. Fixpoint rev_tree {T : Type} (t : btree T) : btree T := match t with | Leaf => Leaf | Node x t1 t2 => Node x (rev_tree t2) (rev_tree t1) end. Fixpoint count {T : Type} (p : T -> bool) (t : btree T) : nat := match t with | Leaf => 0 | Node x t1 t2 => (if p x then 1 else 0) + (count p t1 + count p t2) end. Axiom add_comm : forall x y, x + y = y + x. Lemma count_rev_tree {T} (p : T -> bool) t : count p (rev_tree t) = count p t. Proof. induction t as [ | a t1 IH1 t2 IH2]. easy. simpl. rewrite IH1. rewrite IH2. Fail reflexivity. rewrite (add_comm (count p t2)). easy. Qed. rocq-9.2.0/test-suite/output/Errors.out000066400000000000000000000035041516144147600201540ustar00rootroot00000000000000File "./output/Errors.v", line 12, characters 0-11: The command has indeed failed with message: The field t is missing in Errors.M. File "./output/Errors.v", line 19, characters 18-19: The command has indeed failed with message: Unable to unify "nat" with "True". File "./output/Errors.v", line 20, characters 12-15: The command has indeed failed with message: Unable to unify "nat" with "True". In nested Ltac calls to "f" and "apply x", last call failed. File "./output/Errors.v", line 29, characters 21-30: The command has indeed failed with message: Instance is not well-typed in the environment of ?x. Ltac call to "instantiate ( (ident) := (lglob) )" failed. File "./output/Errors.v", line 34, characters 19-20: The command has indeed failed with message: Cannot infer ?T in the partial instance "?T -> nat" found for the type of f. File "./output/Errors.v", line 35, characters 22-24: The command has indeed failed with message: Cannot infer ?T in the partial instance "?T -> nat" found for the implicit parameter A of id whose type is "Type". File "./output/Errors.v", line 36, characters 17-18: The command has indeed failed with message: Cannot infer ?T in the partial instance "forall x : nat, ?T" found for the type of f in environment: x : nat File "./output/Errors.v", line 44, characters 5-23: The command has indeed failed with message: The first term has type "nat" while the second term has incompatible type "bool". File "./output/Errors.v", line 49, characters 7-24: The command has indeed failed with message: Replacement would lead to an ill-typed term: Illegal application: The term "@eq" of type "forall A : Type, A -> A -> Prop" cannot be applied to the terms "Set" : "Type" "n" : "Type" "n" : "Type" The 2nd term has type "Type" which should be a subtype of "Set". (universe inconsistency: Cannot enforce Errors.57 <= Set) rocq-9.2.0/test-suite/output/Errors.v000066400000000000000000000017411516144147600176130ustar00rootroot00000000000000(* coq-prog-args: ("-top" "Errors") *) (* Test error messages *) Set Ltac Backtrace. (* Test non-regression of bug fixed in r13486 (bad printer for module names) *) Module Type S. Parameter t:Type. End S. Module M : S. Fail End M. (* A simple check of how Ltac trace are used or not *) (* Unfortunately, cannot test error location... *) Ltac f x := apply x. Goal True. Fail simpl; apply 0. Fail simpl; f 0. Abort. (* Test instantiate error messages *) Goal forall T1 (P1 : T1 -> Type), sigT P1 -> sigT P1. intros T1 P1 H1. eexists ?[x]. destruct H1 as [x1 H1]. Fail instantiate (x:=projT1 x1). Abort. (* Test some messages for non solvable evars *) Fail Goal forall a f, f a = 0. Fail Goal forall f x, id f x = 0. Fail Goal forall f P, P (f 0). Definition t := unit. End M. Module Change. Goal 0 = 0. Fail change 0 with true. Abort. Goal nat = nat. pose (nat : Type) as n. Fail change nat with n. (* Error: Replacement would lead to an ill-typed term. *) Abort. End Change. rocq-9.2.0/test-suite/output/Existentials.out000066400000000000000000000004441516144147600213540ustar00rootroot00000000000000Existential 1 = ?Goal : [p : nat q := S p : nat n : nat m : nat |- ?y = m] (only printing) Existential 2 = ?y : [p : nat q := S p : nat n : nat m : nat |- nat] (p, q cannot be used) (shelved; only printing) Existential 3 = ?Goal0 : [q : nat n : nat m : nat |- n = ?y] (only printing) rocq-9.2.0/test-suite/output/Existentials.v000066400000000000000000000003621516144147600210110ustar00rootroot00000000000000(* Test propagation of clear/clearbody in existential variables *) Section Test. Variable p:nat. Let q := S p. Goal forall n m:nat, n = m. intros. eapply eq_trans. clearbody q. clear p. (* Error ... *) Show Existentials. Abort. End Test. rocq-9.2.0/test-suite/output/ExistingInstance.out000066400000000000000000000000731516144147600221550ustar00rootroot00000000000000Debug: [vernacinterp] interpreting: Existing Instances x y rocq-9.2.0/test-suite/output/ExistingInstance.v000066400000000000000000000001361516144147600216130ustar00rootroot00000000000000Class A := {}. Axioms x y : A. Set Debug "vernacinterp". #[ local ] Existing Instances x y. rocq-9.2.0/test-suite/output/Extraction_ffi.out000066400000000000000000000014541516144147600216460ustar00rootroot00000000000000File "./output/Extraction_ffi.v", line 15, characters 0-18: Warning: The following axiom must be realized in the extracted code: ax_fun. [extraction-axiom-to-realize,extraction,default] (** val ax_fun : nat -> nat **) let ax_fun = failwith "AXIOM TO BE REALIZED (Extraction_ffi.ax_fun)" (** User defined extraction *) (** val ax_fun : nat -> nat **) external ax_fun: nat -> nat = "my_c_fun" (** val exact_fun : nat -> nat **) let exact_fun a = add (ax_fun a) (S O) (** User defined extraction *) (** val exact_fun : nat -> nat **) external exact_fun: nat -> nat = "my_exact_c_fun" (** val exact_fun2 : nat -> nat **) let exact_fun2 a = add (ax_fun a) (S O) let () = Stdlib.Callback.register "call_exact_fun" exact_fun2 (** val exact_fun2 : nat -> nat **) let exact_fun2 a = add (ax_fun a) (S O) rocq-9.2.0/test-suite/output/Extraction_ffi.v000066400000000000000000000017501516144147600213030ustar00rootroot00000000000000(* @eladrion's example for issue #18212 *) From Corelib Require Extraction. (* Define an axiomatic function. *) Axiom ax_fun : nat -> nat. (* Define a fully specified function*) Definition exact_fun (a : nat) := (ax_fun a) + 1. (* Define duplicate of the fully specified function*) Definition exact_fun2 (a : nat) := (ax_fun a) + 1. (* before we give the directive axioms produce failwith "axiom to be realized" *) Extraction ax_fun. (* ax_fun shall be a FFI call to the C function my_c_fun *) Extract Foreign Constant ax_fun => "my_c_fun". Extraction ax_fun. (* Extract exact_fun *) Extraction exact_fun. (* exact_fun shall now be a FFI call to the C function my_c_fun *) Extract Foreign Constant exact_fun => "my_exact_c_fun". Extraction exact_fun. (* Now, exact_fun is an entry point exposed to C *) Extract Callback "call_exact_fun" exact_fun2. Extraction exact_fun2. (* Now we make sure that a callback registration can be reverted *) Reset Extraction Callback. Extraction exact_fun2. rocq-9.2.0/test-suite/output/Extraction_infix.out000066400000000000000000000004271516144147600222160ustar00rootroot00000000000000(** val test : foo **) let test = (fun (b, p) -> bar) (True, False) (** val test : foo **) let test = True@@?False (** val test : foo **) let test = True#^^False (** val test : foo **) let test = True@?:::False (** val test : foo **) let test = True @?::: False rocq-9.2.0/test-suite/output/Extraction_infix.v000066400000000000000000000011571516144147600216550ustar00rootroot00000000000000(* @herbelin's example for issue #6212 *) Require Import Extraction. Inductive I := C : bool -> bool -> I. Definition test := C true false. (* the parentheses around the function wrong signalled an infix operator *) Extract Inductive I => "foo" [ "(fun (b, p) -> bar)" ]. Extraction test. (* some bonafide infix operators *) Extract Inductive I => "foo" [ "(@@?)" ]. Extraction test. Extract Inductive I => "foo" [ "(#^^)" ]. Extraction test. Extract Inductive I => "foo" [ "(@?:::)" ]. Extraction test. (* allow whitespace around infix operator *) Extract Inductive I => "foo" [ "( @?::: )" ]. Extraction test. rocq-9.2.0/test-suite/output/Extraction_matchs_2413.out000066400000000000000000000020421516144147600230240ustar00rootroot00000000000000(** val test1 : bool -> bool **) let test1 b = b (** val test2 : bool -> bool **) let test2 _ = False (** val wrong_id : 'a1 hole -> 'a2 hole **) let wrong_id = function | Hole -> Hole | Hole2 -> Hole2 (** val test3 : 'a1 option -> 'a1 option **) let test3 o = o (** val test4 : indu -> indu **) let test4 = function | A m -> A (S m) | x -> x (** val test5 : indu -> indu **) let test5 = function | A m -> A (S m) | _ -> B (** val test6 : indu' -> indu' **) let test6 = function | A' m -> A' (S m) | E' -> B' | F' -> B' | _ -> C' (** val test7 : indu -> nat option **) let test7 = function | A m -> Some m | _ -> None (** val decode_cond_mode : (word -> opcode option) -> (word -> 'a1 decoder_result) -> word -> ('a1 -> opcode -> 'a2) -> 'a2 decoder_result **) let decode_cond_mode condition f w g = match condition w with | Some oc -> (match f w with | DecUndefined -> DecUndefined | DecUnpredictable -> DecUnpredictable | DecInst i -> DecInst (g i oc) | DecError m -> DecError m) | None -> DecUndefined rocq-9.2.0/test-suite/output/Extraction_matchs_2413.v000066400000000000000000000053361516144147600224730ustar00rootroot00000000000000(** Extraction : tests of optimizations of pattern matching *) Require Corelib.extraction.Extraction. (** First, a few basic tests *) Definition test1 b := match b with | true => true | false => false end. Extraction test1. (** should be seen as the identity *) Definition test2 b := match b with | true => false | false => false end. Extraction test2. (** should be seen a the always-false constant function *) Inductive hole (A:Set) : Set := Hole | Hole2. Definition wrong_id (A B : Set) (x:hole A) : hole B := match x with | Hole _ => @Hole _ | Hole2 _ => @Hole2 _ end. Extraction wrong_id. (** should _not_ be optimized as an identity *) Definition test3 (A:Type)(o : option A) := match o with | Some x => Some x | None => None end. Extraction test3. (** Even with type parameters, should be seen as identity *) Inductive indu : Type := A : nat -> indu | B | C. Definition test4 n := match n with | A m => A (S m) | B => B | C => C end. Extraction test4. (** should merge branchs B C into a x->x *) Definition test5 n := match n with | A m => A (S m) | B => B | C => B end. Extraction test5. (** should merge branches B C into _->B *) Inductive indu' : Type := A' : nat -> indu' | B' | C' | D' | E' | F'. Definition test6 n := match n with | A' m => A' (S m) | B' => C' | C' => C' | D' => C' | E' => B' | F' => B' end. Extraction test6. (** should merge some branches into a _->C' *) (** NB : In Coq, "| a => a" corresponds to n, hence some "| _ -> n" are extracted *) Definition test7 n := match n with | A m => Some m | B => None | C => None end. Extraction test7. (** should merge branches B,C into a _->None *) (** Script from bug #2413 *) Set Implicit Arguments. Section S. Definition message := nat. Definition word := nat. Definition mode := nat. Definition opcode := nat. Variable condition : word -> option opcode. Section decoder_result. Variable inst : Type. Inductive decoder_result : Type := | DecUndefined : decoder_result | DecUnpredictable : decoder_result | DecInst : inst -> decoder_result | DecError : message -> decoder_result. End decoder_result. Definition decode_cond_mode (mode : Type) (f : word -> decoder_result mode) (w : word) (inst : Type) (g : mode -> opcode -> inst) : decoder_result inst := match condition w with | Some oc => match f w with | DecInst i => DecInst (g i oc) | DecError _ m => @DecError inst m | DecUndefined _ => @DecUndefined inst | DecUnpredictable _ => @DecUnpredictable inst end | None => @DecUndefined inst end. End S. Extraction decode_cond_mode. (** inner match should not be factorized with a partial x->x (different type) *) rocq-9.2.0/test-suite/output/Fixpoint.out000066400000000000000000000075471516144147600205130ustar00rootroot00000000000000fix F (A B : Set) (f : A -> B) (l : list A) {struct l} : list B := match l with | nil => nil | a :: l0 => f a :: F A B f l0 end : forall A B : Set, (A -> B) -> list A -> list B let fix f (m : nat) : nat := match m with | 0 => 0 | S m' => f m' end in f 0 : nat Ltac f id1 id2 := fix id1 2 with (id2 (n:_) (H:odd n) {struct H} : n >= 1) = cofix inf : Inf := {| projS := inf |} : Inf File "./output/Fixpoint.v", line 39, characters 0-51: Warning: Not a truly recursive fixpoint. [non-recursive,fixpoints,default] File "./output/Fixpoint.v", line 42, characters 0-103: Warning: Not a fully mutually defined fixpoint (k1 depends on k2 but not conversely). Well-foundedness check may fail unexpectedly. [non-full-mutual,fixpoints,default] File "./output/Fixpoint.v", line 44, characters 0-106: Warning: Not a fully mutually defined fixpoint (l2 and l1 are not mutually dependent). Well-foundedness check may fail unexpectedly. [non-full-mutual,fixpoints,default] File "./output/Fixpoint.v", line 46, characters 0-103: Warning: Not a fully mutually defined fixpoint (m2 and m1 are not mutually dependent). Well-foundedness check may fail unexpectedly. [non-full-mutual,fixpoints,default] File "./output/Fixpoint.v", line 54, characters 0-25: Warning: Not a truly recursive cofixpoint. [non-recursive,fixpoints,default] File "./output/Fixpoint.v", line 57, characters 0-48: Warning: Not a fully mutually defined cofixpoint (a2 and a1 are not mutually dependent). [non-full-mutual,fixpoints,default] File "./output/Fixpoint.v", line 73, characters 2-15: The command has indeed failed with message: Recursive definition of foo and bar is ill-formed. As a mutual fixpoint: Not enough abstractions in the definition: expected at least 1 according to the "struct" annotation. The 1st recursive definition is: "?Goal". The 2nd recursive definition is: "?Goal0". The condition holds up to here. File "./output/Fixpoint.v", line 78, characters 6-19: The command has indeed failed with message: Recursive definition of foo and bar is ill-formed. As a mutual fixpoint decreasing on the 1st argument of foo and 1st argument of bar: Recursive call to bar has principal argument equal to "0" instead of a subterm of "n". As a mutual fixpoint decreasing on the 1st argument of foo and 2nd argument of bar: Recursive call to bar has principal argument equal to "0" instead of a subterm of "n". As a mutual fixpoint decreasing on the 2nd argument of foo and 1st argument of bar: Recursive call to bar has principal argument equal to "0" instead of a subterm of "m". As a mutual fixpoint decreasing on the 2nd argument of foo and 2nd argument of bar: Recursive call to bar has principal argument equal to "0" instead of a subterm of "m". The 1st recursive definition is: "fun n m : nat => match n with | 0 => bar 0 0 | S n0 => (fun n1 : nat => ?Goal0@{n:=n1}) n0 end". The 2nd recursive definition is: "fun n m : nat => ?Goal". The condition holds up to here. The condition holds up to here. The condition holds up to here. The condition holds up to here. File "./output/Fixpoint.v", line 105, characters 6-19: The command has indeed failed with message: Recursive definition of foo' and bar' is ill-formed. As a mutual fixpoint decreasing on the 1st argument of foo' and 1st argument of bar': Cannot define a fixpoint with principal argument living in sort "SProp" to produce a value in sort "Prop" because "SProp" does not eliminate to "Prop". As a mutual fixpoint decreasing on the 1st argument of foo' and 2nd argument of bar': Recursive call to bar' has principal argument equal to "0" instead of a subterm of "n". The 1st recursive definition is: "fun (n : nat) (m : Prop) => match n with | 0 => bar' SI 0 | S n0 => (fun n1 : nat => ?Goal0@{n:=n1}) n0 end". The 2nd recursive definition is: "fun (n : STrue) (m : nat) => ?Goal". rocq-9.2.0/test-suite/output/Fixpoint.v000066400000000000000000000050331516144147600201350ustar00rootroot00000000000000Require Import ListDef. Check (fix F (A B : Set) (f : A -> B) (l : list A) {struct l} : list B := match l with | nil => nil | a :: l => f a :: F _ _ f l end). (* V8 printing of this term used to failed in V8.0 and V8.0pl1 (cf BZ#860) *) Check let fix f (m : nat) : nat := match m with | O => 0 | S m' => f m' end in f 0. Inductive even : nat -> Type := | even_O : even 0 | even_S : forall n, odd n -> even (S n) with odd : nat -> Type := odd_S : forall n, even n -> odd (S n). (* Check printing of fix *) Ltac f id1 id2 := fix id1 2 with (id2 n (H:odd n) {struct H} : n >= 1). Print Ltac f. CoInductive Inf := IS { projS : Inf }. Definition expand_Inf (x : Inf) := IS (projS x). CoFixpoint inf := IS inf. Eval compute in inf. Module Recursivity. Open Scope nat_scope. Fixpoint f n := match n with 0 => 0 | S n => f n end. Fixpoint g n := match n with 0 => 0 | S n => n end. Fixpoint h1 n := match n with 0 => 0 | S n => h2 n end with h2 n := match n with 0 => 0 | S n => h1 n end. Fixpoint k1 n := match n with 0 => 0 | S n => k2 n end with k2 n := match n with 0 => 0 | S n => n end. Fixpoint l1 n := match n with 0 => 0 | S n => l1 n end with l2 n := match n with 0 => 0 | S n => l2 n end. Fixpoint m1 n := match n with 0 => 0 | S n => m1 n end with m2 n := match n with 0 => 0 | S n => n end. (* Why not to allow this definition ? Fixpoint h1' n := match n with 0 => 0 | S n => h2' n end with h2' n := h1' n. *) CoInductive S := cons : nat -> S -> S. CoFixpoint c := cons 0 c. CoFixpoint d := cons 0 c. CoFixpoint e1 := cons 0 e2 with e2 := cons 1 e1. CoFixpoint a1 := cons 0 a1 with a2 := cons 1 a2. (* Why not to allow this definition ? CoFixpoint b1 := cons 0 b2 with b2 := b1. *) End Recursivity. Module Guard. Open Scope nat_scope. Lemma foo : nat -> nat -> bool with bar : nat -> nat -> bool. Proof. Fail Guarded. (* not enough abstractions in the definition *) all:intros n m. Guarded. - destruct n as [|n]. + exact (bar 0 0). Fail Guarded. (* failure is correct here *) Abort. Lemma foo : nat -> nat -> bool with bar : nat -> nat -> bool. Proof. all:intros n m. - destruct n as [|n]. + exact true. + Guarded. exact (bar m n). - Guarded. destruct m as [|m]. + exact false. + exact (foo m n). Guarded. Defined. Inductive STrue : SProp := SI. Lemma foo' : nat -> Prop -> bool with bar' : STrue -> nat -> bool. Proof. all:intros n m. - destruct n as [|n]. Guarded. + exact (bar' SI 0). Fail Guarded. Abort. End Guard. rocq-9.2.0/test-suite/output/FixpointNoElim.out000066400000000000000000000007631516144147600216100ustar00rootroot00000000000000File "./output/FixpointNoElim.v", line 4, characters 0-48: Warning: Not a truly recursive fixpoint. [non-recursive,fixpoints,default] File "./output/FixpointNoElim.v", line 4, characters 0-48: The command has indeed failed with message: Recursive definition of bar is ill-formed. Cannot define a fixpoint with principal argument living in sort "Type@{Ξ±3 ; Set}" to produce a value in sort "Prop" because "Type@{Ξ±3 ; Set}" does not eliminate to "Prop". Recursive definition is: "fun _ : foo => I". rocq-9.2.0/test-suite/output/FixpointNoElim.v000066400000000000000000000001661516144147600212430ustar00rootroot00000000000000Set Universe Polymorphism. Inductive foo@{s;} : Type@{s;Set} := XX. Fail Fixpoint bar@{s;} (f:foo@{s;}) : True := I. rocq-9.2.0/test-suite/output/FloatNumberSyntax.out000066400000000000000000000046261516144147600223330ustar00rootroot000000000000002%float : float 2.5%float : float (-2.5)%float : float File "./output/FloatNumberSyntax.v", line 9, characters 6-13: Warning: The constant 2.5e123 is not a binary64 floating-point value. A closest value 0x1.e412f0f768fadp+409 will be used and unambiguously printed 2.4999999999999999e+123. [inexact-float,parsing,default] 2.4999999999999999e+123%float : float File "./output/FloatNumberSyntax.v", line 10, characters 7-16: Warning: The constant -2.5e-123 is not a binary64 floating-point value. A closest value -0x1.a71368f0f3047p-408 will be used and unambiguously printed -2.5000000000000001e-123. [inexact-float,parsing,default] (-2.5000000000000001e-123)%float : float (2 + 2)%float : float (2.5 + 2.5)%float : float 2 : float 2.5 : float -2.5 : float File "./output/FloatNumberSyntax.v", line 19, characters 6-13: Warning: The constant 2.5e123 is not a binary64 floating-point value. A closest value 0x1.e412f0f768fadp+409 will be used and unambiguously printed 2.4999999999999999e+123. [inexact-float,parsing,default] 2.4999999999999999e+123 : float File "./output/FloatNumberSyntax.v", line 20, characters 7-16: Warning: The constant -2.5e-123 is not a binary64 floating-point value. A closest value -0x1.a71368f0f3047p-408 will be used and unambiguously printed -2.5000000000000001e-123. [inexact-float,parsing,default] -2.5000000000000001e-123 : float 2 + 2 : float 2.5 + 2.5 : float -26 : float 11.171875 : float -6882 : float 44.6875 : float 2860 : float -2.79296875 : float File "./output/FloatNumberSyntax.v", line 30, characters 6-11: Warning: The constant 1e309 is not a binary64 floating-point value. A closest value infinity will be used and unambiguously printed infinity. [inexact-float,parsing,default] infinity : float File "./output/FloatNumberSyntax.v", line 31, characters 6-12: Warning: The constant -1e309 is not a binary64 floating-point value. A closest value neg_infinity will be used and unambiguously printed neg_infinity. [inexact-float,parsing,default] neg_infinity : float 0x1p-1 : float 0.5 : float 0x1p-1 : float 0.5 : float 2 : nat 2%float : float t = 2%flt : float File "./output/FloatNumberSyntax.v", line 50, characters 0-35: Warning: Hiding binding of key float to float_scope [hiding-delimiting-key,parsing,default] t = 2%flt : float 2 : nat 2 : float rocq-9.2.0/test-suite/output/FloatNumberSyntax.v000066400000000000000000000016751516144147600217720ustar00rootroot00000000000000Require Import PrimFloat. Check 2%float. Check 2.5%float. Check (-2.5)%float. (* Avoid exponents with less than three digits as they are usually displayed with two digits (1e7 is displayed 1e+07) except on Windows where three digits are used (1e+007). *) Check 2.5e123%float. Check (-2.5e-123)%float. Check (2 + 2)%float. Check (2.5 + 2.5)%float. Open Scope float_scope. Check 2. Check 2.5. Check (-2.5). Check 2.5e123. Check (-2.5e-123). Check (2 + 2). Check (2.5 + 2.5). Check -0x1a. Check 0xb.2c. Check -0x1ae2. Check 0xb.2cp2. Check 0xb.2cp8. Check -0xb.2cp-2. Check 1e309. Check -1e309. Set Printing All. Check 0.5. Unset Printing All. Check 0.5. Unset Printing Float. Check 0.5. Set Printing Float. Check 0.5. Open Scope nat_scope. Check 2. Check 2%float. Delimit Scope float_scope with flt. Definition t := 2%float. Print t. Delimit Scope nat_scope with float. Print t. Check 2. Close Scope nat_scope. Check 2. Close Scope float_scope. rocq-9.2.0/test-suite/output/HintLocality.out000066400000000000000000000066241516144147600213110ustar00rootroot00000000000000Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all Unfoldable projection definitions: all Cut: emp For any goal -> For nat -> simple apply 0 ; trivial (cost 1, pattern nat, id 0) Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all Unfoldable projection definitions: all Cut: emp For any goal -> For nat -> simple apply 0 ; trivial (cost 1, pattern nat, id 0) Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all Unfoldable projection definitions: all Cut: emp For any goal -> For nat -> simple apply 0 ; trivial (cost 1, pattern nat, id 0) Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> File "./output/HintLocality.v", line 61, characters 0-38: The command has indeed failed with message: This command does not support the global attribute in sections. Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all except: id Unfoldable projection definitions: all Cut: _ For any goal -> For S (modes !) -> For nat -> simple apply 0 ; trivial (cost 1, pattern nat, id 0) File "./output/HintLocality.v", line 92, characters 0-39: Warning: This hint is not local but depends on a section variable. It will disappear when the section is closed. [non-local-section-hint,automation,default] File "./output/HintLocality.v", line 94, characters 0-40: Warning: This hint is not local but depends on a section variable. It will disappear when the section is closed. [non-local-section-hint,automation,default] File "./output/HintLocality.v", line 98, characters 0-39: Warning: This hint is not local but depends on a section variable. It will disappear when the section is closed. [non-local-section-hint,automation,default] Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all Unfoldable projection definitions: all Cut: emp For any goal -> For refl (modes - !) -> rocq-9.2.0/test-suite/output/HintLocality.v000066400000000000000000000037721516144147600207500ustar00rootroot00000000000000(** Test hint command locality w.r.t. modules *) Create HintDb foodb. Create HintDb bardb. Create HintDb quxdb. #[global] Hint Immediate O : foodb. #[global] Hint Immediate O : bardb. #[global] Hint Immediate O : quxdb. Module Test. #[global] Hint Cut [ _ ] : foodb. #[global] Hint Mode S ! : foodb. #[global] Hint Opaque id : foodb. #[global] Remove Hints O : foodb. #[local] Hint Cut [ _ ] : bardb. #[local] Hint Mode S ! : bardb. #[local] Hint Opaque id : bardb. #[local] Remove Hints O : bardb. #[export] Hint Cut [ _ ] : quxdb. #[export] Hint Mode S ! : quxdb. #[export] Hint Opaque id : quxdb. #[export] Remove Hints O : quxdb. (** All three agree here *) Print HintDb foodb. Print HintDb bardb. Print HintDb quxdb. End Test. (** bardb and quxdb agree here *) Print HintDb foodb. Print HintDb bardb. Print HintDb quxdb. Import Test. (** foodb and quxdb agree here *) Print HintDb foodb. Print HintDb bardb. Print HintDb quxdb. (** Test hint command locality w.r.t. sections *) Create HintDb secdb. #[global] Hint Immediate O : secdb. Section Sec. #[global] Hint Cut [ _ ] : secdb. #[global] Hint Mode S ! : secdb. #[global] Hint Opaque id : secdb. Fail #[global] Remove Hints O : secdb. #[local] Hint Cut [ _ ] : secdb. #[local] Hint Mode S ! : secdb. #[local] Hint Opaque id : secdb. #[local] Remove Hints O : secdb. Print HintDb secdb. End Sec. Print HintDb secdb. (** Variant of the above test - modes are correctly generalized at section closure - non-local section-specific hints trigger a warning *) Create HintDb seclocaldb. Set Warnings "non-local-section-hint". Section SecLocal. Variable A : Type. Definition refl (n : A) : n = n := eq_refl. Variable prf : forall n : nat, n = 0. #[export] Hint Mode refl ! : seclocaldb. #[export] Hint Mode prf ! : seclocaldb. #[export] Hint Cut [ prf ] : seclocaldb. #[export] Hint Variables Transparent : seclocaldb. #[export] Hint Constants Transparent : seclocaldb. #[export] Hint Opaque prf : seclocaldb. End SecLocal. Print HintDb seclocaldb. rocq-9.2.0/test-suite/output/IllTypedInstance.out000066400000000000000000000005471516144147600221170ustar00rootroot00000000000000File "./output/IllTypedInstance.v", line 7, characters 37-44: The command has indeed failed with message: In environment T : Type b : T The term "eq_refl" has type "apply _ _ ?a {| fst := ?fst; snd := ?snd |} = apply _ _ ?a {| fst := ?fst; snd := ?snd |}" while it is expected to have type "apply _ _ ?a {| fst := ?fst; snd := ?snd |} = apply _ _ ?a0 b". rocq-9.2.0/test-suite/output/IllTypedInstance.v000066400000000000000000000003701516144147600215470ustar00rootroot00000000000000Set Primitive Projections. Record prod A B := pair { fst: A; snd : B }. Arguments pair {_ _}. Record Apply (A B : Type) : Type := {apply : A -> B}. Fail Check fun (T : Type) (b : T) => eq_refl : @apply (prod T T) T _ (pair _ _) = @apply T T _ b. rocq-9.2.0/test-suite/output/Implicit.out000066400000000000000000000012531516144147600204510ustar00rootroot00000000000000compose S : (nat -> nat) -> nat -> nat ex_intro (P:=fun _ : nat => True) (x:=0) I : ex (fun _ : nat => True) d2 = fun x : nat => d1 (y:=x) : forall [x x0 : nat], x0 = x -> x0 = x Arguments d2 [x x]%_nat_scope h map id (1 :: nil) : list nat map id' (1 :: nil) : list nat map (id'' (A:=nat)) (1 :: nil) : list nat fix f (x : nat) : option nat := match x with | 0 => None | S _ => x end : nat -> option nat fun x : False => let y := False_rect (A:=bool) x in y : False -> bool fun x : False => let y : True := False_rect x in y : False -> True rocq-9.2.0/test-suite/output/Implicit.v000066400000000000000000000034561516144147600201160ustar00rootroot00000000000000Set Implicit Arguments. Unset Strict Implicit. (* Suggested by Pierre Casteran (BZ#169) *) (* Argument 3 is needed to typecheck and should be printed *) Definition compose (A B C : Set) (f : A -> B) (g : B -> C) (x : A) := g (f x). Check (compose (C:=nat) S). (* Better to explicitly display the arguments inferable from a position that could disappear after reduction *) Inductive ex (A : Set) (P : A -> Prop) : Prop := ex_intro : forall x : A, P x -> ex P. Check (ex_intro (P:=fun _ => True) (x:=0) I). (* Test for V8 printing of implicit by names *) Definition d1 y x (h : x = y :>nat) := h. Definition d2 x := d1 (y:=x). Print d2. Set Strict Implicit. Unset Implicit Arguments. (* Check maximal insertion of implicit *) Require Import TestSuite.list. Set Implicit Arguments. Set Maximal Implicit Insertion. Definition id (A:Type) (x:A) := x. Check map id (1::nil). Definition id' (A:Type) (x:A) := x. Arguments id' {A} x. Check map id' (1::nil). Unset Maximal Implicit Insertion. Unset Implicit Arguments. (* Check explicit insertion of last non-maximal trailing implicit to ensure *) (* correct arity of partiol applications *) Set Implicit Arguments. Definition id'' (A:Type) (x:A) := x. Check map (@id'' nat) (1::nil). Module MatchBranchesInContext. Set Implicit Arguments. Set Contextual Implicit. Inductive option A := None | Some (a:A). Coercion some_nat := @Some nat. Check fix f x := match x with 0 => None | n => some_nat n end. End MatchBranchesInContext. Module LetInContext. Set Implicit Arguments. Set Contextual Implicit. Axiom False_rect : forall A:Type, False -> A. Check fun x:False => let y:= False_rect (A:=bool) x in y. (* will not be in context: explicitation *) Check fun x:False => let y:= False_rect (A:=True) x in y. (* will be in context: no explicitation *) End LetInContext. rocq-9.2.0/test-suite/output/ImplicitTypes.out000066400000000000000000000011471516144147600215000ustar00rootroot00000000000000forall b, b = b : Prop forall b : nat, b = b : Prop forall b : bool, @eq bool b b : Prop forall b : bool, b = b : Prop forall b c : bool, b = c : Prop forall c b : bool, b = c : Prop forall b1 b2, b1 = b2 : Prop fun b => b = b : bool -> Prop fun b c : bool => b = c : bool -> bool -> Prop fun c b : bool => b = c : bool -> bool -> Prop fun b1 b2 => b1 = b2 : bool -> bool -> Prop fix f b (n : nat) {struct n} : bool := match n with | 0 => b | S p => f b p end : bool -> nat -> bool βˆ€ b c : bool, b = c : Prop βˆ€ b1 b2, b1 = b2 : Prop rocq-9.2.0/test-suite/output/ImplicitTypes.v000066400000000000000000000020431516144147600211320ustar00rootroot00000000000000Implicit Types b : bool. Check forall b, b = b. (* Check the type is not used if not the reserved one *) Check forall b:nat, b = b. (* Check full printing *) Set Printing All. Check forall b, b = b. Unset Printing All. (* Check printing of type *) Unset Printing Use Implicit Types. Check forall b, b = b. Set Printing Use Implicit Types. (* Check factorization: we give priority on factorization over implicit type *) Check forall b c, b = c. Check forall c b, b = c. (* Check factorization of implicit types *) Check forall b1 b2, b1 = b2. (* Check in "fun" *) Check fun b => b = b. Check fun b c => b = c. Check fun c b => b = c. Check fun b1 b2 => b1 = b2. (* Check in binders *) Check fix f b n := match n with 0 => b | S p => f b p end. (* Check in notations *) Module Notation. Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'") : type_scope. Check forall b c, b = c. Check forall b1 b2, b1 = b2. End Notation. rocq-9.2.0/test-suite/output/Inductive.out000066400000000000000000000062571516144147600206420ustar00rootroot00000000000000File "./output/Inductive.v", line 1, characters 0-93: The command has indeed failed with message: In environment list' : Set -> Set A : Set a : A l : list' A Unable to unify "list' (A * A)%type" with "list' A". Inductive foo (A : Type) (x : A) (y : A := x) : Prop := Foo : foo A x. Arguments foo A%_type_scope x Arguments Foo A%_type_scope x myprod unit bool : Set option : Type -> Type option is template universe polymorphic Arguments option A%_type_scope Expands to: Inductive Corelib.Init.Datatypes.option Declared in library Corelib.Init.Datatypes, line 211, characters 10-16 option : Type@{option.u0} -> Type@{max(Set,option.u0)} option is template universe polymorphic on option.u0 (cannot be instantiated to Prop) Arguments option A%_type_scope Expands to: Inductive Corelib.Init.Datatypes.option Declared in library Corelib.Init.Datatypes, line 211, characters 10-16 File "./output/Inductive.v", line 27, characters 4-13: The command has indeed failed with message: Parameters should be syntactically the same for each inductive type. Type "B" has no parameters but type "Inductive" has parameters "A". File "./output/Inductive.v", line 30, characters 6-15: The command has indeed failed with message: Parameters should be syntactically the same for each record type. Type "B" has no parameters but type "Inductive" has parameters "A". or : Prop -> Prop -> Prop or is not universe polymorphic or may only be eliminated to produce values whose type is SProp or Prop. Arguments or (A B)%_type_scope Expands to: Inductive Corelib.Init.Logic.or Declared in library Corelib.Init.Logic, line 87, characters 10-12 sunit : SProp sunit is not universe polymorphic sunit may only be eliminated to produce values whose type is SProp. Expands to: Inductive Inductive.sunit Declared in library Inductive, line 38, characters 10-15 sempty@{q ; } : Type@{q ; Set} (* q ; |= *) sempty is universe polymorphic sempty@{q ; } may only be eliminated to produce values whose type is in sort quality q, unless instantiated such that the quality SProp is equal to the instantiation of q, or to qualities smaller (SProp <= Prop <= Type, and all variables <= Type) than the instantiation of q. Expands to: Inductive Inductive.sempty Declared in library Inductive, line 44, characters 22-28 ssig@{q1 q2 q3 ; a b} : forall A : Type@{q1 ; a}, (A -> Type@{q2 ; b}) -> Type@{q3 ; max(a,b)} (* q1 q2 q3 ; a b |= *) ssig is universe polymorphic ssig@{q1 q2 q3 ; a b} may only be eliminated to produce values whose type is in sort quality q3, unless instantiated such that the qualities q1, q2 and Prop are equal to the instantiation of q3, or to qualities smaller (SProp <= Prop <= Type, and all variables <= Type) than the instantiation of q3. Arguments ssig A%_type_scope B%_function_scope Expands to: Inductive Inductive.ssig Declared in library Inductive, line 48, characters 22-26 BoxP@{q ; a} : Type@{q ; a} -> Prop (* q ; a |= *) BoxP is universe polymorphic BoxP@{q ; a} may only be eliminated to produce values whose type is SProp or Prop, unless instantiated such that the quality q is SProp or Prop. Arguments BoxP A%_type_scope Expands to: Inductive Inductive.BoxP Declared in library Inductive, line 56, characters 22-26 rocq-9.2.0/test-suite/output/Inductive.v000066400000000000000000000022241516144147600202660ustar00rootroot00000000000000Fail Inductive list' (A:Set) : Set := | nil' : list' A | cons' : A -> list' A -> list' (A*A). (* Check printing of let-ins *) Inductive foo (A : Type) (x : A) (y := x) := Foo. Print foo. (* Check where clause *) Reserved Notation "x ** y" (at level 40, left associativity). Inductive myprod A B := mypair : A -> B -> A ** B where "A ** B" := (myprod A B) (only parsing). Check unit ** bool. (* "option is template" *) About option. Set Printing Universes. About option. (* "option is template on xxx" *) Module DiffParams. Fail Inductive B: Type := | F: A -> B with Inductive A: Type := mkA. Fail Inductive B := { x : nat } with Inductive A := { y : nat }. End DiffParams. (* print squash info (can't test impredicative set squashes in this file) *) About or. Inductive sunit : SProp := stt. About sunit. Set Universe Polymorphism. Polymorphic Inductive sempty@{q; |} : Type@{q;Set} := . About sempty. Polymorphic Inductive ssig@{q1 q2 q3;a b|} (A:Type@{q1;a}) (B:A -> Type@{q2;b}) : Type@{q3;max(a,b)} := sexist (a:A) (b:B a). About ssig. Polymorphic Inductive BoxP@{q;a|} (A:Type@{q;a}) : Prop := boxP (_:A). About BoxP. rocq-9.2.0/test-suite/output/InductiveMainName.out000066400000000000000000000015431516144147600222410ustar00rootroot00000000000000bar : foo -> nat bar is not universe polymorphic bar is a projection of foo Arguments bar id bar is transparent Expands to: Constant InductiveMainName.bar Declared in library InductiveMainName, line 1, characters 16-19 bar' : foo' -> nat bar' is not universe polymorphic bar' is a projection of foo' Arguments bar' {id'} bar' is transparent Expands to: Constant InductiveMainName.bar' Declared in library InductiveMainName, line 3, characters 16-20 bar'' : foo'' -> foo'' bar'' is not universe polymorphic bar'' is a projection of foo'' Arguments bar'' id'' bar'' is transparent Expands to: Constant InductiveMainName.bar'' Declared in library InductiveMainName, line 5, characters 23-28 Record foo''' : Set := Build_foo''' { bar''' : nat } as id. foo''' has primitive projections with eta conversion. Arguments Build_foo''' bar'''%_nat_scope Arguments bar''' id rocq-9.2.0/test-suite/output/InductiveMainName.v000066400000000000000000000003561516144147600217000ustar00rootroot00000000000000Record foo := { bar : nat } as id. About bar. Class foo' := { bar' : nat } as id'. About bar'. CoInductive foo'' := { bar'' : foo'' } as id''. About bar''. Set Primitive Projections. Record foo''' := { bar''' : nat } as id. Print bar'''. rocq-9.2.0/test-suite/output/InitSyntax.out000066400000000000000000000004741516144147600210150ustar00rootroot00000000000000Inductive sig2 (A : Type) (P Q : A -> Prop) : Type := exist2 : forall x : A, P x -> Q x -> {x : A | P x & Q x}. Arguments sig2 [A]%_type_scope (P Q)%_type_scope Arguments exist2 [A]%_type_scope (P Q)%_function_scope x _ _ exists x : nat, x = x : Prop fun b : bool => if b then b else b : bool -> bool rocq-9.2.0/test-suite/output/InitSyntax.v000066400000000000000000000001571516144147600204510ustar00rootroot00000000000000(* Soumis par Pierre *) Print sig2. Check (exists x : nat, x = x). Check (fun b : bool => if b then b else b). rocq-9.2.0/test-suite/output/Int63NumberSyntax.out000066400000000000000000000040331516144147600221610ustar00rootroot000000000000002%uint63 : int 2 : int 9223372036854775807 : int 427 : int 427 : int 427 : int 427 : int 427 : int File "./output/Int63NumberSyntax.v", line 12, characters 11-17: The command has indeed failed with message: Cannot interpret this number as a value of type int File "./output/Int63NumberSyntax.v", line 13, characters 11-17: The command has indeed failed with message: Cannot interpret this number as a value of type int 0 : int 0 : int File "./output/Int63NumberSyntax.v", line 16, characters 12-14: The command has indeed failed with message: The reference xg was not found in the current environment. File "./output/Int63NumberSyntax.v", line 17, characters 12-14: The command has indeed failed with message: The reference xG was not found in the current environment. File "./output/Int63NumberSyntax.v", line 18, characters 13-15: The command has indeed failed with message: The reference x1 was not found in the current environment. File "./output/Int63NumberSyntax.v", line 19, characters 12-13: The command has indeed failed with message: The reference x was not found in the current environment. add 2 2 : int File "./output/Int63NumberSyntax.v", line 21, characters 11-13: The command has indeed failed with message: Cannot interpret this number as a value of type int File "./output/Int63NumberSyntax.v", line 22, characters 11-30: The command has indeed failed with message: Overflow in int63 literal: 9223372036854775808. 0x1 : int 2 : nat 2%uint63 : int t = 2%ui63 : int File "./output/Int63NumberSyntax.v", line 34, characters 0-36: Warning: Hiding binding of key uint63 to uint63_scope [hiding-delimiting-key,parsing,default] t = 2%ui63 : int 2 : nat 2 : int add 2 2 : int add 2 2 : int = 4 : int = 37151199385380486 : int = 4 : int = 4 : int = 4 : int = add : int -> int -> int = 12 : int = 12 : int = 12 : int = add 3 x : int = add (add 1 2) x : int rocq-9.2.0/test-suite/output/Int63NumberSyntax.v000066400000000000000000000022131516144147600216150ustar00rootroot00000000000000Require Import PrimInt63. Check 2%uint63. Open Scope uint63_scope. Check 2. Check 9223372036854775807. Check 0x1ab. Check 0X1ab. Check 0x1Ab. Check 0x1aB. Check 0x1AB. Fail Check 0x1ap5. (* exponents not implemented (yet?) *) Fail Check 0x1aP5. Check 0x0. Check 0x000. Fail Check 0xg. Fail Check 0xG. Fail Check 00x1. Fail Check 0x. Check (PrimInt63.add 2 2). Fail Check -1. Fail Check 9223372036854775808. Set Printing All. Check 1%uint63. Unset Printing All. Open Scope nat_scope. Check 2. (* : nat *) Check 2%uint63. Delimit Scope uint63_scope with ui63. Definition t := 2%uint63. Print t. Delimit Scope nat_scope with uint63. Print t. Check 2. Close Scope nat_scope. Check 2. Close Scope uint63_scope. Check add 2 2. Open Scope uint63_scope. Check (add 2 2). Eval vm_compute in add 2 2. Eval vm_compute in mul 65675757 565675998. Eval simpl in add 2 2. Eval hnf in add 2 2. Eval cbn in add 2 2. Eval hnf in PrimInt63.add. Eval simpl in add (mul 2 3) (mul 2 3). Eval hnf in add (mul 2 3) (mul 2 3). Eval cbn in add (mul 2 3) (mul 2 3). Section TestNoSimpl. Variable x : int. Eval simpl in add (add 1 2) x. Eval hnf in add (add 1 2) x. End TestNoSimpl. rocq-9.2.0/test-suite/output/InvalidDisjunctiveIntro.out000066400000000000000000000023611516144147600235120ustar00rootroot00000000000000File "./output/InvalidDisjunctiveIntro.v", line 2, characters 31-32: The command has indeed failed with message: Cannot coerce to a disjunctive/conjunctive pattern. File "./output/InvalidDisjunctiveIntro.v", line 4, characters 2-32: The command has indeed failed with message: Disjunctive/conjunctive introduction pattern expected. File "./output/InvalidDisjunctiveIntro.v", line 6, characters 48-49: The command has indeed failed with message: Cannot coerce to a disjunctive/conjunctive pattern. File "./output/InvalidDisjunctiveIntro.v", line 8, characters 49-50: The command has indeed failed with message: Cannot coerce to a disjunctive/conjunctive pattern. File "./output/InvalidDisjunctiveIntro.v", line 10, characters 32-33: The command has indeed failed with message: Ltac variable H is bound to idtac of type tacvalue which cannot be coerced to an introduction pattern. File "./output/InvalidDisjunctiveIntro.v", line 13, characters 2-52: The command has indeed failed with message: Disjunctive/conjunctive introduction pattern expected. File "./output/InvalidDisjunctiveIntro.v", line 15, characters 50-52: The command has indeed failed with message: Ltac variable H' is bound to idtac of type tacvalue which cannot be coerced to an introduction pattern. rocq-9.2.0/test-suite/output/InvalidDisjunctiveIntro.v000066400000000000000000000015701516144147600231510ustar00rootroot00000000000000Theorem test (A:Prop) : A \/ A -> A. Fail intros H; destruct H as H. (* Cannot coerce to a disjunctive/conjunctive pattern. *) Fail intro H; destruct H as H. (* Disjunctive/conjunctive introduction pattern expected. *) Fail let H := fresh in intro H; destruct H as H. (* Cannot coerce to a disjunctive/conjunctive pattern. *) Fail let H := fresh in intros H; destruct H as H. (* Cannot coerce to a disjunctive/conjunctive pattern. *) Fail let H := idtac in intros H; destruct H as H. (* Ltac variable H is bound to which cannot be coerced to an introduction pattern. *) Fail let H := idtac in intros H; destruct H as H'. (* Disjunctive/conjunctive introduction pattern expected. *) Fail let H' := idtac in intros H; destruct H as H'. (* Ltac variable H' is bound to which cannot be coerced to an introduction pattern. *) Abort. rocq-9.2.0/test-suite/output/Load.out000066400000000000000000000002621516144147600175550ustar00rootroot00000000000000f = 2 : nat u = I : True File "./output/Load.v", line 7, characters 0-41: The command has indeed failed with message: Files processed by Load cannot leave open proofs. rocq-9.2.0/test-suite/output/Load.v000066400000000000000000000002021516144147600172050ustar00rootroot00000000000000Load "output/load/Load_noproof.v". Print f. Load "output/load/Load_proof.v". Print u. Fail Load "output/load/Load_openproof.v". rocq-9.2.0/test-suite/output/Match_subterm.out000066400000000000000000000000441516144147600214710ustar00rootroot00000000000000(0 = 1) (eq 0) eq @eq nat 0 1 S 0 2 rocq-9.2.0/test-suite/output/Match_subterm.v000066400000000000000000000001351516144147600211300ustar00rootroot00000000000000Goal 0 = 1. match goal with | |- context [?v] => idtac v ; fail | _ => idtac 2 end. Abort. rocq-9.2.0/test-suite/output/ModuleErrors.out000066400000000000000000000056521516144147600213300ustar00rootroot00000000000000File "./output/ModuleErrors.v", line 10, characters 0-43: The command has indeed failed with message: Signature components for field I do not match: types given to constructor c differ: expected "nat -> ModuleErrors.IndTest1.I" but found "bool -> ModuleErrors.IndTest1.I". File "./output/ModuleErrors.v", line 19, characters 0-46: The command has indeed failed with message: Signature components for field I do not match: types given to constructor c1 differ: expected "nat -> ModuleErrors.ConsTest1.I" but found "bool -> ModuleErrors.ConsTest1.I". File "./output/ModuleErrors.v", line 28, characters 0-55: The command has indeed failed with message: Signature components for field I do not match: constructor names differ: expected foo, bar but found baz, qux. File "./output/ModuleErrors.v", line 39, characters 0-52: The command has indeed failed with message: Signature components for field Foo do not match: inductive type names differ: expected Bar but found Baz. File "./output/ModuleErrors.v", line 49, characters 0-49: The command has indeed failed with message: Signature components for field I1 do not match: number of inductive types differs: expected 2 but found 1. File "./output/ModuleErrors.v", line 58, characters 0-49: The command has indeed failed with message: Signature components for field I do not match: number of parameters differs: expected 2 but found 1. File "./output/ModuleErrors.v", line 67, characters 0-43: The command has indeed failed with message: Signature components for field x do not match: the body of definitions differs: expected "42" but found "0". File "./output/ModuleErrors.v", line 76, characters 0-58: The command has indeed failed with message: Signature components for field x do not match: expected type "nat" but found type "bool". File "./output/ModuleErrors.v", line 83, characters 0-99: The command has indeed failed with message: Incorrect constraint for label "b": expected type "ModuleErrors.WithParamType.a" but found type "bool" File "./output/ModuleErrors.v", line 92, characters 0-82: The command has indeed failed with message: Incorrect constraint for label "x": expected type "nat" but found type "bool" File "./output/ModuleErrors.v", line 101, characters 0-40: The command has indeed failed with message: Signature components for field R do not match: constructor names differ: expected Build_R but found mkR. File "./output/ModuleErrors.v", line 110, characters 0-52: The command has indeed failed with message: Signature components for field R do not match: projection names differ: expected foo and bar but found baz and qux. File "./output/ModuleErrors.v", line 119, characters 0-49: The command has indeed failed with message: Signature components for field I do not match: type is expected to be coinductive. File "./output/ModuleErrors.v", line 125, characters 0-70: The command has indeed failed with message: Incorrect constraint for label "x": the body of definitions differs: expected "5" but found "10" rocq-9.2.0/test-suite/output/ModuleErrors.v000066400000000000000000000074651516144147600207720ustar00rootroot00000000000000(* Test improved error messages for module type errors *) (* Test 1: NotConvertibleInductiveField - types given to inductive differ *) Module Type IndType1. Inductive I : Type := c : nat -> I. End IndType1. Module IndMod1. Inductive I : Type := c : bool -> I. End IndMod1. Fail Module IndTest1 : IndType1 := IndMod1. (* Test 2: NotConvertibleConstructorField - constructor types differ *) Module Type ConsType1. Inductive I : Type := c1 : nat -> I | c2 : I. End ConsType1. Module ConsMod1. Inductive I : Type := c1 : bool -> I | c2 : I. End ConsMod1. Fail Module ConsTest1 : ConsType1 := ConsMod1. (* Test 3: NotSameConstructorNamesField - constructor names differ *) Module Type ConsNameType. Inductive I : Type := foo : I | bar : I. End ConsNameType. Module ConsNameMod. Inductive I : Type := baz : I | qux : I. End ConsNameMod. Fail Module ConsNameTest : ConsNameType := ConsNameMod. (* Test 4: NotSameInductiveNameInBlockField - mutual inductive type names differ *) Module Type IndNameType. Inductive Foo : Type := mkFoo : Bar -> Foo with Bar : Type := mkBar : Foo -> Bar. End IndNameType. Module IndNameMod. Inductive Foo : Type := mkFoo : Baz -> Foo with Baz : Type := mkBar : Foo -> Baz. End IndNameMod. Fail Module IndNameTest : IndNameType := IndNameMod. (* Test 5: InductiveNumbersFieldExpected - number of inductives differs *) Module Type NumIndType. Inductive I1 : Type := c1 : I1 with I2 : Type := c2 : I2. End NumIndType. Module NumIndMod. Inductive I1 : Type := c1 : I1. End NumIndMod. Fail Module NumIndTest : NumIndType := NumIndMod. (* Test 6: InductiveParamsNumberField - number of parameters differs *) Module Type ParamsType. Inductive I (A B : Type) : Type := c : A -> B -> I A B. End ParamsType. Module ParamsMod. Inductive I (A : Type) : Type := c : A -> A -> I A. End ParamsMod. Fail Module ParamsTest : ParamsType := ParamsMod. (* Test 7: NotConvertibleBodyField - body of definitions differs *) Module Type BodyType. Definition x := 42. End BodyType. Module BodyMod. Definition x := 0. End BodyMod. Fail Module BodyTest : BodyType := BodyMod. (* Test 8: NotConvertibleTypeField - type of definitions differs *) Module Type TypeFieldType. Definition x : nat := 0. End TypeFieldType. Module TypeFieldMod. Definition x : bool := true. End TypeFieldMod. Fail Module TypeFieldTest : TypeFieldType := TypeFieldMod. (* Test 9: With Definition type mismatch with complex types from module *) Module Type WithParamType. Parameter a : Type. Parameter b : a. End WithParamType. Fail Module Type WithParamTest := WithParamType with Definition a := nat with Definition b := true. (* Test 10: Nested with definition error - type mismatch in submodule *) Module Type InnerType. Parameter x : nat. End InnerType. Module Type NestedWithType. Declare Module Inner : InnerType. End NestedWithType. Fail Module Type NestedWithTest := NestedWithType with Definition Inner.x := true. (* Test 11: RecordFieldExpected - expected record but got non-record *) Module Type RecType. Record R := { field : nat }. End RecType. Module RecMod. Inductive R := mkR : nat -> R. End RecMod. Fail Module RecTest : RecType := RecMod. (* Test 12: RecordProjectionsExpected - projection names differ *) Module Type RecProjType. Record R := { foo : nat; bar : bool }. End RecProjType. Module RecProjMod. Record R := { baz : nat; qux : bool }. End RecProjMod. Fail Module RecProjTest : RecProjType := RecProjMod. (* Test 13: FiniteInductiveFieldExpected - inductive vs coinductive *) Module Type FiniteType. Inductive I := c : I. End FiniteType. Module FiniteMod. CoInductive I := c : I. End FiniteMod. Fail Module FiniteTest : FiniteType := FiniteMod. (* Test 14: With Definition body mismatch *) Module Type WithBodyType. Definition x := 5. End WithBodyType. Fail Module Type WithBodyTest := WithBodyType with Definition x := 10. rocq-9.2.0/test-suite/output/ModuleErrorsComprehensive.out000066400000000000000000000134261516144147600240560ustar00rootroot00000000000000File "./output/ModuleErrorsComprehensive.v", line 12, characters 0-64: The command has indeed failed with message: Signature components for field I do not match: an inductive definition is expected. File "./output/ModuleErrorsComprehensive.v", line 21, characters 0-64: The command has indeed failed with message: Signature components for field x do not match: a definition is expected. Hint: you can rename the inductive or constructor and add a definition mapping the old name to the new name. File "./output/ModuleErrorsComprehensive.v", line 34, characters 0-64: The command has indeed failed with message: Signature components for field M.x do not match: a definition is expected. Hint: you can rename the inductive or constructor and add a definition mapping the old name to the new name. File "./output/ModuleErrorsComprehensive.v", line 47, characters 0-76: The command has indeed failed with message: Signature components for field T do not match: a module type is expected. File "./output/ModuleErrorsComprehensive.v", line 56, characters 0-61: The command has indeed failed with message: Signature components for field I do not match: types given to constructor c differ: expected "nat -> ModuleErrorsComprehensive.NotConvIndTest.I" but found "bool -> ModuleErrorsComprehensive.NotConvIndTest.I". File "./output/ModuleErrorsComprehensive.v", line 65, characters 0-64: The command has indeed failed with message: Signature components for field I do not match: types given to constructor c1 differ: expected "nat -> ModuleErrorsComprehensive.NotConvConsTest.I" but found "bool -> ModuleErrorsComprehensive.NotConvConsTest.I". File "./output/ModuleErrorsComprehensive.v", line 74, characters 0-64: The command has indeed failed with message: Signature components for field x do not match: the body of definitions differs: expected "42" but found "0". File "./output/ModuleErrorsComprehensive.v", line 83, characters 0-64: The command has indeed failed with message: Signature components for field x do not match: expected type "nat" but found type "bool". File "./output/ModuleErrorsComprehensive.v", line 92, characters 0-55: The command has indeed failed with message: Signature components for field I do not match: a cumulative declaration was expected, but a non-cumulative declaration was found. File "./output/ModuleErrorsComprehensive.v", line 101, characters 0-52: The command has indeed failed with message: Signature components for field x do not match: a polymorphic declaration was expected, but a monomorphic declaration was found. File "./output/ModuleErrorsComprehensive.v", line 110, characters 0-58: The command has indeed failed with message: Signature components for field I do not match: constructor names differ: expected foo, bar but found baz, qux. File "./output/ModuleErrorsComprehensive.v", line 121, characters 0-55: The command has indeed failed with message: Signature components for field A do not match: inductive type names differ: expected B but found C. File "./output/ModuleErrorsComprehensive.v", line 130, characters 0-49: The command has indeed failed with message: Signature components for field I do not match: type is expected to be coinductive. File "./output/ModuleErrorsComprehensive.v", line 140, characters 0-49: The command has indeed failed with message: Signature components for field I1 do not match: number of inductive types differs: expected 2 but found 1. File "./output/ModuleErrorsComprehensive.v", line 149, characters 0-49: The command has indeed failed with message: Signature components for field I do not match: number of parameters differs: expected 2 but found 1. File "./output/ModuleErrorsComprehensive.v", line 158, characters 0-49: The command has indeed failed with message: Signature components for field R do not match: type is expected to be a record. File "./output/ModuleErrorsComprehensive.v", line 167, characters 0-52: The command has indeed failed with message: Signature components for field R do not match: projection names differ: expected foo and bar but found baz and qux. File "./output/ModuleErrorsComprehensive.v", line 176, characters 0-67: The command has indeed failed with message: Signature components for field f do not match: incompatible polymorphic binders: got @{u v | u <= v} but expected @{u}. File "./output/ModuleErrorsComprehensive.v", line 185, characters 0-55: The command has indeed failed with message: Signature components for field f do not match: incompatible polymorphic binders: got @{u v | v < u} but expected @{u v | u < v} (incompatible constraints). File "./output/ModuleErrorsComprehensive.v", line 197, characters 0-55: The command has indeed failed with message: Signature components for field I do not match: incompatible variance information. File "./output/ModuleErrorsComprehensive.v", line 214, characters 0-72: The command has indeed failed with message: Incorrect constraint for label "x": expected type "nat" but found type "bool" File "./output/ModuleErrorsComprehensive.v", line 220, characters 0-70: The command has indeed failed with message: Incorrect constraint for label "x": the body of definitions differs: expected "5" but found "10" File "./output/ModuleErrorsComprehensive.v", line 227, characters 0-76: The command has indeed failed with message: Incorrect constraint for label "x": the universe constraints are inconsistent: Cannot enforce big_type.u0 < Set because Set < big_type.u0 when comparing "Type" and "Set" File "./output/ModuleErrorsComprehensive.v", line 233, characters 0-71: The command has indeed failed with message: Incorrect constraint for label "p": incompatible polymorphic binders: got @{} but expected @{u} File "./output/ModuleErrorsComprehensive.v", line 240, characters 0-95: The command has indeed failed with message: Incorrect constraint for label "b": expected type "ModuleErrorsComprehensive.WithAbsType.a" but found type "bool" rocq-9.2.0/test-suite/output/ModuleErrorsComprehensive.v000066400000000000000000000202241516144147600235060ustar00rootroot00000000000000(* Comprehensive tests for all module signature and constraint mismatch errors *) (* ========== signature_mismatch_error tests ========== *) (* 1. InductiveFieldExpected - expected inductive but found definition *) Module Type IndFieldExpType. Inductive I : Type := c : I. End IndFieldExpType. Module IndFieldExpMod. Definition I : Type := nat. End IndFieldExpMod. Fail Module IndFieldExpTest : IndFieldExpType := IndFieldExpMod. (* 2. DefinitionFieldExpected - expected definition but found inductive *) Module Type DefFieldExpType. Definition x : Type := nat. End DefFieldExpType. Module DefFieldExpMod. Inductive x : Type := c : x. End DefFieldExpMod. Fail Module DefFieldExpTest : DefFieldExpType := DefFieldExpMod. (* 3. ModuleFieldExpected - expected module but found definition *) Module Type ModFieldExpType. Module M. Definition x := 0. End M. End ModFieldExpType. Module ModFieldExpMod. Module M. Inductive x : Type := c : x. End M. End ModFieldExpMod. Fail Module ModFieldExpTest : ModFieldExpType := ModFieldExpMod. (* 4. ModuleTypeFieldExpected - expected module type but found module *) Module Type ModTypeFieldExpType. Module Type T. Definition x := 0. End T. End ModTypeFieldExpType. Module ModTypeFieldExpMod. Module T. Definition x := 0. End T. End ModTypeFieldExpMod. Fail Module ModTypeFieldExpTest : ModTypeFieldExpType := ModTypeFieldExpMod. (* 5. NotConvertibleInductiveField - inductive types differ *) Module Type NotConvIndType. Inductive I : Type := c : nat -> I. End NotConvIndType. Module NotConvIndMod. Inductive I : Type := c : bool -> I. End NotConvIndMod. Fail Module NotConvIndTest : NotConvIndType := NotConvIndMod. (* 6. NotConvertibleConstructorField - constructor types differ *) Module Type NotConvConsType. Inductive I : Type := c1 : nat -> I | c2 : I. End NotConvConsType. Module NotConvConsMod. Inductive I : Type := c1 : bool -> I | c2 : I. End NotConvConsMod. Fail Module NotConvConsTest : NotConvConsType := NotConvConsMod. (* 7. NotConvertibleBodyField - definition bodies differ *) Module Type NotConvBodyType. Definition x := 42. End NotConvBodyType. Module NotConvBodyMod. Definition x := 0. End NotConvBodyMod. Fail Module NotConvBodyTest : NotConvBodyType := NotConvBodyMod. (* 8. NotConvertibleTypeField - definition types differ *) Module Type NotConvTypeType. Definition x : nat := 0. End NotConvTypeType. Module NotConvTypeMod. Definition x : bool := true. End NotConvTypeMod. Fail Module NotConvTypeTest : NotConvTypeType := NotConvTypeMod. (* 9. CumulativeStatusExpected - expected cumulative but got non-cumulative *) Module Type CumulExpType. Polymorphic Cumulative Inductive I@{u} : Type@{u} := c : I. End CumulExpType. Module CumulExpMod. Polymorphic Inductive I@{u} : Type@{u} := c : I. End CumulExpMod. Fail Module CumulExpTest : CumulExpType := CumulExpMod. (* 10. PolymorphicStatusExpected - expected polymorphic but got monomorphic *) Module Type PolyExpType. Polymorphic Definition x : Type := nat. End PolyExpType. Module PolyExpMod. Definition x : Type := nat. End PolyExpMod. Fail Module PolyExpTest : PolyExpType := PolyExpMod. (* 11. NotSameConstructorNamesField - constructor names differ *) Module Type ConsNamesType. Inductive I : Type := foo : I | bar : I. End ConsNamesType. Module ConsNamesMod. Inductive I : Type := baz : I | qux : I. End ConsNamesMod. Fail Module ConsNamesTest : ConsNamesType := ConsNamesMod. (* 12. NotSameInductiveNameInBlockField - mutual inductive names differ *) Module Type IndNamesType. Inductive A : Type := mkA : B -> A with B : Type := mkB : A -> B. End IndNamesType. Module IndNamesMod. Inductive A : Type := mkA : C -> A with C : Type := mkB : A -> C. End IndNamesMod. Fail Module IndNamesTest : IndNamesType := IndNamesMod. (* 13. FiniteInductiveFieldExpected - expected inductive but got coinductive *) Module Type FiniteType. Inductive I : Type := c : I. End FiniteType. Module FiniteMod. CoInductive I : Type := c : I. End FiniteMod. Fail Module FiniteTest : FiniteType := FiniteMod. (* 14. InductiveNumbersFieldExpected - number of mutual inductives differs *) Module Type NumIndType. Inductive I1 : Type := c1 : I1 with I2 : Type := c2 : I2. End NumIndType. Module NumIndMod. Inductive I1 : Type := c1 : I1. End NumIndMod. Fail Module NumIndTest : NumIndType := NumIndMod. (* 15. InductiveParamsNumberField - number of parameters differs *) Module Type ParamsType. Inductive I (A B : Type) : Type := c : A -> B -> I A B. End ParamsType. Module ParamsMod. Inductive I (A : Type) : Type := c : A -> A -> I A. End ParamsMod. Fail Module ParamsTest : ParamsType := ParamsMod. (* 16. RecordFieldExpected - expected record but got non-record *) Module Type RecExpType. Record R := { field : nat }. End RecExpType. Module RecExpMod. Inductive R := Build_R : nat -> R. End RecExpMod. Fail Module RecExpTest : RecExpType := RecExpMod. (* 17. RecordProjectionsExpected - projection names differ *) Module Type RecProjType. Record R := { foo : nat; bar : bool }. End RecProjType. Module RecProjMod. Record R := { baz : nat; qux : bool }. End RecProjMod. Fail Module RecProjTest : RecProjType := RecProjMod. (* 18. IncompatiblePolymorphism - polymorphic conversion generates constraints *) Module Type IncompatPolyType. Polymorphic Definition f@{u} : Type@{u} -> Type@{u} := fun x => x. End IncompatPolyType. Module IncompatPolyMod. Polymorphic Definition f@{u v} : Type@{u} -> Type@{v} := fun x => x. End IncompatPolyMod. Fail Module IncompatPolyTest : IncompatPolyType := IncompatPolyMod. (* 19. IncompatibleUnivConstraints - universe constraints incompatible *) Module Type UnivConsType. Polymorphic Definition f@{u v|u < v} : Type@{u} := nat. End UnivConsType. Module UnivConsMod. Polymorphic Definition f@{u v|v < u} : Type@{u} := nat. End UnivConsMod. Fail Module UnivConsTest : UnivConsType := UnivConsMod. (* 20. IncompatibleVariance - variance information incompatible Note: Variance subtyping is v1 <= v2 (module variance <= expected). Covariant (+) is more restrictive than Invariant (=). To trigger: module has Invariant but type expects Covariant. *) Module Type VarianceType. Polymorphic Cumulative Inductive I@{+u} : Type@{u} := c : I. End VarianceType. Module VarianceMod. Polymorphic Cumulative Inductive I@{=u} : Type@{u} := c : I. End VarianceMod. Fail Module VarianceTest : VarianceType := VarianceMod. (* NOTE: Some errors are not easily triggerable from this test file: - NoRewriteRulesSubtyping: requires -allow-rewrite-rules flag - NotEqualInductiveAliases: this error checks inductive aliasing through module resolvers; it may be dead code or only triggerable in very specific module functor contexts - IncompatibleUniverses in subtyping: tested above with Set/Type mismatch (Test4 in WithDefErrors) - IncompatibleQualities in subtyping: requires quality constraint conflicts during conversion - WithCannotConstrainPrimitive/Symbol: module types export primitives/symbols as Parameters, so "with Definition" finds a Parameter, not Primitive/Symbol *) (* ========== with_constraint_error tests ========== *) (* 22. WithTypeMismatch - type mismatch in with Definition *) Module Type WithTypeType. Parameter x : nat. End WithTypeType. Fail Module Type WithTypeTest := WithTypeType with Definition x := true. (* 23. WithBodyMismatch - body mismatch in with Definition *) Module Type WithBodyType. Definition x := 5. End WithBodyType. Fail Module Type WithBodyTest := WithBodyType with Definition x := 10. (* 24. WithUniverseMismatch - universe mismatch in with Definition *) Module Type WithUnivType. Parameter x : Set. End WithUnivType. Definition big_type := Type. Fail Module Type WithUnivTest := WithUnivType with Definition x := big_type. (* 25. WithConstraintsMismatch - polymorphic binders mismatch *) Module Type WithConsType. Polymorphic Parameter p@{u} : Type@{u}. End WithConsType. Fail Module Type WithConsTest := WithConsType with Definition p := nat. (* 26. WithTypeMismatch with abstract type - test where expected type references module *) Module Type WithAbsType. Parameter a : Type. Parameter b : a. End WithAbsType. Fail Module Type WithAbsTest := WithAbsType with Definition a := nat with Definition b := true. rocq-9.2.0/test-suite/output/ModuleSubtyping.out000066400000000000000000000021651516144147600220340ustar00rootroot00000000000000File "./output/ModuleSubtyping.v", line 8, characters 2-41: The command has indeed failed with message: Signature components for field x do not match: the body of definitions differs: expected "0" but found "1". File "./output/ModuleSubtyping.v", line 14, characters 2-30: The command has indeed failed with message: Signature components for field B.C.x do not match: the body of definitions differs: expected "0" but found "1". File "./output/ModuleSubtyping.v", line 20, characters 2-31: The command has indeed failed with message: Signature components for field B.C.x in the 1st functor argument do not match: the body of definitions differs: expected "1" but found "0". File "./output/ModuleSubtyping.v", line 30, characters 2-34: The command has indeed failed with message: Signature components for field B.C.x in the 1st functor argument of F do not match: the body of definitions differs: expected "1" but found "0". File "./output/ModuleSubtyping.v", line 46, characters 2-38: The command has indeed failed with message: Signature components for field v do not match: expected type "A1.t -> A1.t" but found type "A1.t -> Prop". rocq-9.2.0/test-suite/output/ModuleSubtyping.v000066400000000000000000000023251516144147600214700ustar00rootroot00000000000000 Module Qualification. (* test that field mismatch errors print the qualified fields *) Module Type EasyT. Definition x := O. End EasyT. Module EasyM. Definition x := S O. End EasyM. Fail Module Easytest <: EasyT := EasyM. Module Type A. Module B. Module C. Definition x := O. End C. End B. End A. Module Type A'. Module B. Module C. Definition x := S O. End C. End B. End A'. Module Av. Include A'. End Av. Fail Module test <: A := Av. (* was Error: Signature components for field C do not match: the body of definitions differs. *) Module Type FT (X:A). End FT. Module F (X:A'). End F. Fail Module Ftest <: FT := F. Module Type FXT. Module F (X:A). End F. End FXT. Module FX. Module F (X:A'). End F. End FX. Fail Module FXtest <: FXT := FX. End Qualification. Module PrintBound. (* printing an inductive from a bound module in an error from the command where the bound module is introduced *) Module Type E. End E. Module Type T. Inductive t : Prop := . Parameter v : t -> t. End T. Module Type FE(A:E). Inductive t : Prop :=. Parameter v : t -> Prop. End FE. Module Type FT(A:T). End FT. Module VE. End VE. Fail Module F (A1:FE VE) (A2:FT A1). End PrintBound. rocq-9.2.0/test-suite/output/Nametab.out000066400000000000000000000034551516144147600202540ustar00rootroot00000000000000Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is Q.N.K.foo) Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is Q.N.K.foo) Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is Q.N.K.foo) Constant Nametab.Q.N.K.foo Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is Q.N.K.foo) Module Nametab.Q.N.K (shorter name to refer to it in current context is Q.N.K) Module Nametab.Q.N.K (shorter name to refer to it in current context is Q.N.K) Module Nametab.Q.N.K Module Nametab.Q.N.K (shorter name to refer to it in current context is Q.N.K) Module Nametab.Q.N (shorter name to refer to it in current context is Q.N) Module Nametab.Q.N Module Nametab.Q.N (shorter name to refer to it in current context is Q.N) Module Nametab.Q Module Nametab.Q (shorter name to refer to it in current context is Q) Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is K.foo) Constant Nametab.Q.N.K.foo Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is K.foo) Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is K.foo) Constant Nametab.Q.N.K.foo (shorter name to refer to it in current context is K.foo) Module Nametab.Q.N.K Module Nametab.Q.N.K (shorter name to refer to it in current context is K) Module Nametab.Q.N.K (shorter name to refer to it in current context is K) Module Nametab.Q.N.K (shorter name to refer to it in current context is K) Module Nametab.Q.N (shorter name to refer to it in current context is Q.N) Module Nametab.Q.N Module Nametab.Q.N (shorter name to refer to it in current context is Q.N) Module Nametab.Q Module Nametab.Q (shorter name to refer to it in current context is Q) No object of basename T Open Section Nametab.T rocq-9.2.0/test-suite/output/Nametab.v000066400000000000000000000020461516144147600177050ustar00rootroot00000000000000(* coq-prog-args: ("-top" "Nametab") *) Module Q. Module N. Module K. Definition foo := Set. End K. End N. End Q. (* Bad *) Locate foo. (* Bad *) Locate K.foo. (* Bad *) Locate N.K.foo. (* OK *) Locate Q.N.K.foo. (* OK *) Locate Nametab.Q.N.K.foo. (* Bad *) Locate Module K. (* Bad *) Locate Module N.K. (* OK *) Locate Module Q.N.K. (* OK *) Locate Module Nametab.Q.N.K. (* Bad *) Locate Module N. (* OK *) Locate Module Q.N. (* OK *) Locate Module Nametab.Q.N. (* OK *) Locate Module Q. (* OK *) Locate Module Nametab.Q. Import Q.N. (* Bad *) Locate foo. (* OK *) Locate K.foo. (* Bad *) Locate N.K.foo. (* OK *) Locate Q.N.K.foo. (* OK *) Locate Nametab.Q.N.K.foo. (* OK *) Locate Module K. (* Bad *) Locate Module N.K. (* OK *) Locate Module Q.N.K. (* OK *) Locate Module Nametab.Q.N.K. (* Bad *) Locate Module N. (* OK *) Locate Module Q.N. (* OK *) Locate Module Nametab.Q.N. (* OK *) Locate Module Q. (* OK *) Locate Module Nametab.Q. (* A slightly different request *) Section T. Locate T. About T. End T. rocq-9.2.0/test-suite/output/Naming.out000066400000000000000000000046601516144147600201150ustar00rootroot000000000000001 goal x3 : nat ============================ forall x x1 x4 x0 : nat, (forall x2 x5 : nat, x2 + x1 = x4 + x5) -> x + x1 = x4 + x0 1 goal x3, x, x1, x4, x0 : nat H : forall x x3 : nat, x + x1 = x4 + x3 ============================ x + x1 = x4 + x0 1 goal x3 : nat ============================ forall x x1 x4 x0 : nat, (forall x2 x5 : nat, x2 + x1 = x4 + x5 -> foo (S x2 + x1)) -> x + x1 = x4 + x0 -> foo (S x) 1 goal x3 : nat ============================ forall x x1 x4 x0 : nat, (forall x2 x5 : nat, x2 + x1 = x4 + x5 -> forall x6 x7 x8 S0 : nat, x6 + S0 = x7 + x8 + (S x2 + x1)) -> x + x1 = x4 + x0 -> forall x5 x6 x7 S : nat, x5 + S = x6 + x7 + Datatypes.S x 1 goal x3, x, x1, x4, x0 : nat ============================ (forall x2 x5 : nat, x2 + x1 = x4 + x5 -> forall x6 x7 x8 S0 : nat, x6 + S0 = x7 + x8 + (S x2 + x1)) -> x + x1 = x4 + x0 -> forall x5 x6 x7 S : nat, x5 + S = x6 + x7 + Datatypes.S x 1 goal x3, x, x1, x4, x0 : nat H : forall x x3 : nat, x + x1 = x4 + x3 -> forall x0 x4 x5 S0 : nat, x0 + S0 = x4 + x5 + (S x + x1) H0 : x + x1 = x4 + x0 ============================ forall x5 x6 x7 S : nat, x5 + S = x6 + x7 + Datatypes.S x 1 goal x3, x, x1, x4, x0 : nat H : forall x x3 : nat, x + x1 = x4 + x3 -> forall x0 x4 x5 S0 : nat, x0 + S0 = x4 + x5 + (Datatypes.S x + x1) H0 : x + x1 = x4 + x0 x5, x6, x7, S : nat ============================ x5 + S = x6 + x7 + Datatypes.S x 1 goal x3, a : nat H : a = 0 -> forall a : nat, a = 0 ============================ a = 0 File "./output/Naming.v", line 101, characters 47-48: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax,default] File "./output/Naming.v", line 105, characters 36-37: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax,default] File "./output/Naming.v", line 106, characters 34-35: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax,default] File "./output/Naming.v", line 112, characters 22-23: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax,default] File "./output/Naming.v", line 112, characters 30-31: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax,default] rocq-9.2.0/test-suite/output/Naming.v000066400000000000000000000052001516144147600175420ustar00rootroot00000000000000(* This file checks the compatibility of naming strategy *) (* This does not mean that the given naming strategy is good *) Parameter x2:nat. Definition foo y := forall x x3 x4 S, x + S = x3 + x4 + y. Section A. Variable x3:nat. Goal forall x x1 x2 x3:nat, (forall x x3:nat, x+x1 = x2+x3) -> x+x1 = x2+x3. Show. intros. Show. (* Remark: in V8.2, this used to be printed x3 : nat ============================ forall x x1 x4 x5 : nat, (forall x0 x6 : nat, x0 + x1 = x4 + x6) -> x + x1 = x4 + x5 before intro and x3 : nat x : nat x1 : nat x4 : nat x0 : nat H : forall x x3 : nat, x + x1 = x4 + x3 ============================ x + x1 = x4 + x0 after. From V8.3, the quantified hypotheses are printed the sames as they would be intro. However the hypothesis H remains printed differently to avoid using the same name in autonomous but nested subterms *) Abort. Goal forall x x1 x2 x3:nat, (forall x x3:nat, x+x1 = x2+x3 -> foo (S x + x1)) -> x+x1 = x2+x3 -> foo (S x). Show. unfold foo. Show. do 4 intro. (* --> x, x1, x4, x0, ... *) Show. do 2 intro. Show. do 4 intro. Show. (* Remark: in V8.2, this used to be printed x3 : nat ============================ forall x x1 x4 x5 : nat, (forall x0 x6 : nat, x0 + x1 = x4 + x6 -> forall x7 x8 x9 S0 : nat, x7 + S0 = x8 + x9 + (S x0 + x1)) -> x + x1 = x4 + x5 -> forall x0 x6 x7 S0 : nat, x0 + S0 = x6 + x7 + S x before the intros and x3 : nat x : nat x1 : nat x4 : nat x0 : nat H : forall x x3 : nat, x + x1 = x4 + x3 -> forall x0 x4 x5 S0 : nat, x0 + S0 = x4 + x5 + (S x + x1) H0 : x + x1 = x4 + x0 x5 : nat x6 : nat x7 : nat S : nat ============================ x5 + S = x6 + x7 + Datatypes.S x after (note the x5/x0 and the S0/S) *) Abort. (* Check naming in hypotheses *) Goal forall a, (a = 0 -> forall a, a = 0) -> a = 0. intros. Show. apply H with (a:=a). (* test compliance with printing *) Abort. End A. Module B. (* Check valid/invalid implicit arguments *) Definition f1 {x} (y:forall {x}, x=0) := x+0. Definition f2 := (((fun x => 0):forall {x:nat}, nat), 0). Definition f3 := fun {x} (y:forall {x}, x=0) => x+0. Definition g1 {x} := match x with true => fun {x:bool} => x | false => fun x:bool => x end. (* TODO: do not ignore the implicit here *) Definition g2 '(x,y) {z} := x+y+z. Definition h1 := fun x:nat => (fun {x} => x) 0. Definition h2 := let g := forall {y}, y=0 in g. Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'") : type_scope. Definition l1 := βˆ€ {x:nat} {y:nat}, x=0. End B. rocq-9.2.0/test-suite/output/NatSyntax.out000066400000000000000000000021071516144147600206270ustar00rootroot0000000000000042 : nat 0 : nat 0 : nat 427 : nat 427 : nat 427 : nat 427 : nat 427 : nat File "./output/NatSyntax.v", line 9, characters 11-17: The command has indeed failed with message: Cannot interpret this number as a value of type nat File "./output/NatSyntax.v", line 10, characters 11-17: The command has indeed failed with message: Cannot interpret this number as a value of type nat 0 : nat 0 : nat File "./output/NatSyntax.v", line 13, characters 12-14: The command has indeed failed with message: The reference xg was not found in the current environment. File "./output/NatSyntax.v", line 14, characters 12-14: The command has indeed failed with message: The reference xG was not found in the current environment. File "./output/NatSyntax.v", line 15, characters 13-15: The command has indeed failed with message: The reference x1 was not found in the current environment. File "./output/NatSyntax.v", line 16, characters 12-13: The command has indeed failed with message: The reference x was not found in the current environment. 0x2a : nat rocq-9.2.0/test-suite/output/NatSyntax.v000066400000000000000000000004501516144147600202640ustar00rootroot00000000000000Check 42. Check 0. Check 00. Check 0x1ab. Check 0X1ab. Check 0x1Ab. Check 0x1aB. Check 0x1AB. Fail Check 0x1ap1. (* exponents not implemented (yet?) *) Fail Check 0x1aP1. Check 0x0. Check 0x000. Fail Check 0xg. Fail Check 0xG. Fail Check 00x1. Fail Check 0x. Open Scope hex_nat_scope. Check 42. rocq-9.2.0/test-suite/output/Notations.out000066400000000000000000000146111516144147600206570ustar00rootroot00000000000000true ? 0; 1 : nat if true as x return x ? nat; bool then 0 else true : nat fun e : nat * nat => proj1 e : nat * nat -> nat decomp (true, true) as t, u in (t, u) : bool * bool ! (0 = 0) : Prop forall n : nat, n = 0 : Prop ! (0 = 0) : Prop forall n : nat, # (n = n) : Prop forall n n0 : nat, ## (n = n0) : Prop forall n n0 : nat, ### (n = n0) : Prop [1; 2; 4] : list nat (1; 2, 4) : nat * nat * nat ifzero 3 : bool pred 3 : nat fun n : nat => pred n : nat -> nat fun n : nat => pred n : nat -> nat fun x : nat => ifn x is succ n then n else 0 : nat -> nat 1 - : bool File "./output/Notations.v", line 97, characters 46-62: The command has indeed failed with message: Cannot find where the recursive pattern starts. File "./output/Notations.v", line 100, characters 0-58: The command has indeed failed with message: in the right-hand side, y and z should appear in term position as part of a recursive pattern. File "./output/Notations.v", line 103, characters 57-58: The command has indeed failed with message: The reference w was not found in the current environment. File "./output/Notations.v", line 109, characters 0-78: The command has indeed failed with message: in the right-hand side, y and z should appear in term position as part of a recursive pattern. File "./output/Notations.v", line 110, characters 56-57: The command has indeed failed with message: z is expected to occur in binding position in the right-hand side. File "./output/Notations.v", line 114, characters 0-102: The command has indeed failed with message: as y is a non-closed binder, no such "," is allowed to occur. File "./output/Notations.v", line 118, characters 46-69: The command has indeed failed with message: Cannot find where the recursive pattern starts. File "./output/Notations.v", line 119, characters 46-62: The command has indeed failed with message: Cannot find where the recursive pattern starts. File "./output/Notations.v", line 120, characters 49-63: The command has indeed failed with message: Cannot find where the recursive pattern starts. File "./output/Notations.v", line 121, characters 50-64: The command has indeed failed with message: Cannot find where the recursive pattern starts. File "./output/Notations.v", line 124, characters 0-73: The command has indeed failed with message: Both ends of the recursive pattern are the same. SUM (nat * nat) nat : Set FST (0; 1) : nat Nil : forall A : Type, list A NIL : list nat : list nat (false && I 3)%bool /\ I 6 : Prop [|1, 2, 3; 4, 5, 6|] : nat * nat * nat * (nat * nat * nat) File "./output/Notations.v", line 167, characters 0-210: Warning: Notations "[| _ , _ , .. , _ ; _ , _ , .. , _ |]" defined at level 0 with arguments constr and "[| _ * ( _ , _ , .. , _ ) ; ( _ , _ , .. , _ ) * _ |]" defined at level 0 with arguments constr at level 39 have incompatible prefixes. One of them will likely not work. [notation-incompatible-prefix,parsing,default] [|0 * (1, 2, 3); (4, 5, 6) * false|] : nat * nat * (nat * nat) * (nat * nat) * (nat * bool * (nat * bool) * (nat * bool)) fun f : nat -> nat -> nat -> nat => {|f; 0; 1; 2|} : nat : (nat -> nat -> nat -> nat) -> nat {|fun x : nat => x + x; 0|} : nat {|op; 0; 1|} : nat File "./output/Notations.v", line 196, characters 0-26: Warning: New coercion path [c] : nat >-> bool is ambiguous with existing [of_nat] : nat >-> bool. [ambiguous-paths,coercions,default] false = 0 : Prop fun x : option nat => match x with | SOME x0 => x0 | NONE => 0 end : option nat -> nat fun x : option nat => match x with | SOME2 x0 => x0 | NONE2 => 0 end : option nat -> nat fun x : option nat => match x with | SOME3 _ x0 => x0 | NONE3 _ => 0 end : option nat -> nat fun x : list ?T => match x with | NIL => NONE3 (list ?T) | _ :' t => SOME3 (list ?T) t end : list ?T -> option (list ?T) where ?T : [x : list ?T x1 : list ?T x0 := x1 : list ?T |- Type] (x, x1, x0 cannot be used) s : s 10 : nat fun _ : nat => 9 : nat -> nat fun (x : nat) (p : x = x) => match p in _ = n return n = n with | ONE => ONE end = p : forall x : nat, x = x -> Prop fun (x : nat) (p : x = x) => match p in _ = n return n = n with | 1 => 1 end = p : forall x : nat, x = x -> Prop bar 0 : nat let k := rew [P] p in v in k : P y let k := rew [P] p in v in k : P y let k := rew <- [P] p in v' in k : P x let k := rew [P] p in v in k : P y let k := rew [P] p in v in k : P y let k := rew <- [P] p in v' in k : P x let k := rew [fun y : A => P y] p in v in k : P y let k := rew [fun y : A => P y] p in v in k : P y let k := rew <- [fun y : A => P y] p in v' in k : P x let k := rew [fun y : A => P y] p in v in k : P y let k := rew [fun y : A => P y] p in v in k : P y let k := rew <- [fun y : A => P y] p in v' in k : P x let k := rew dependent [P] p in v in k : P y p let k := rew dependent [P] p in v in k : P y p let k := rew dependent <- [P'] p in v' in k : P' x (eq_sym p) let k := rew dependent [P] p in v in k : P y p let k := rew dependent [P] p in v in k : P y p let k := rew dependent <- [P'] p in v' in k : P' x (eq_sym p) let k := rew dependent [P] p in v in k : P y p let k := rew dependent [P] p in v in k : P y p let k := rew dependent <- [P'] p in v' in k : P' x (eq_sym p) let k := rew dependent [fun y p => id (P y p)] p in v in k : P y p let k := rew dependent [fun y p => id (P y p)] p in v in k : P y p let k := rew dependent <- [fun y0 p => id (P' y0 p)] p in v' in k : P' x (eq_sym p) let k := rew dependent [P] p in v in k : P y p let k := rew dependent [P] p in v in k : P y p let k := rew dependent <- [P'] p in v' in k : P' x (eq_sym p) let k := rew dependent [fun y p0 => id (P y p0)] p in v in k : P y p let k := rew dependent [fun y p0 => id (P y p0)] p in v in k : P y p let k := rew dependent <- [fun y0 p0 => id (P' y0 p0)] p in v' in k : P' x (eq_sym p) rew dependent [P] p in v : P y p rew dependent <- [P'] p in v' : P' x (eq_sym p) rew dependent [fun a x => id (P a x)] p in v : id (P y p) rew dependent <- [fun a p' => id (P' a p')] p in v' : id (P' x (eq_sym p)) rocq-9.2.0/test-suite/output/Notations.v000066400000000000000000000243611516144147600203200ustar00rootroot00000000000000(* Bug 5568, don't warn for notations in repeated module import *) Module foo. Abbreviation compose := (fun g f => g f). Notation "g & f" := (compose g f) (at level 10). End foo. Import foo. Import foo. Import foo. (**********************************************************************) (* Notations for if and let (submitted by Roland Zumkeller) *) Notation "a ? b ; c" := (if a then b else c) (at level 10). Check (true ? 0 ; 1). Check if true as x return (if x then nat else bool) then 0 else true. Notation "'proj1' t" := (let (a,_) := t in a) (at level 1). Check (fun e : nat * nat => proj1 e). Notation "'decomp' a 'as' x , y 'in' b" := (let (x,y) := a in b) (at level 1). Check (decomp (true,true) as t, u in (t,u)). (**********************************************************************) (* Behaviour wrt to binding variables (submitted by Roland Zumkeller) *) Section A. Notation "! A" := (forall _:nat, A) (at level 60). Check ! (0=0). Check forall n, n=0. Check forall n:nat, 0=0. End A. (**********************************************************************) (* Behaviour wrt to binding variables (cf bug report #1186) *) Section B. Notation "# A" := (forall n:nat, n=n->A) (at level 60). Check forall n:nat, # (n=n). Notation "## A" := (forall n n0:nat, n=n0->A) (at level 60). Check forall n n0:nat, ## (n=n0). Notation "### A" := (forall n n0:nat, match n with O => True | S n => n=n0 end ->A) (at level 60). Check forall n n0:nat, ### (n=n0). End B. (**********************************************************************) (* Check recursive notations *) Notation "[ x ; .. ; y ]" := (cons x .. (cons y nil) ..). Check [1;2;4]. Reserved Notation "( x ; y , .. , z )" (at level 0). Notation "( x ; y , .. , z )" := (pair .. (pair x y) .. z). Check (1;2,4). (* Check basic notations involving "match" *) Section C. Notation "'ifzero' n" := (match n with 0 => true | S _ => false end) (at level 2, n at level 0). Check (ifzero 3). Notation "'pred' n" := (match n with 0 => 0 | S n' => n' end) (at level 2, n at level 0). Check (pred 3). Check (fun n => match n with 0 => 0 | S n => n end). Check (fun n => match n with S p as x => p | _ => 0 end). Notation "'ifn' x 'is' 'succ' n 'then' t 'else' u" := (match x with O => u | S n => t end) (at level 2, u at level 0). Check fun x => ifn x is succ n then n else 0. End C. (* Check correction of bug #1179 *) Notation "1 -" := true (at level 0). Check 1-. (**********************************************************************) (* Check ill-formed recursive notations *) (* Recursive variables not part of a recursive pattern *) Fail Notation "( x , y , .. , z )" := (pair x .. (pair y z) ..). (* No recursive notation *) Fail Notation "( x , y , .. , z )" := (pair x (pair y z)). (* Left-unbound variable *) Fail Notation "( x , y , .. , z )" := (pair x .. (pair y w) ..). (* Right-unbound variable *) Notation "( x , y , .. , z )" := (pair y .. (pair z 0) ..) (only parsing). (* Not the right kind of recursive pattern *) Fail Notation "( x , y , .. , z )" := (ex (fun z => .. (ex (fun y => x)) ..)). Fail Notation "( x -- y , .. , z )" := (pair y .. (pair z 0) ..) (y closed binder, z closed binder). (* No separator allowed with open binders *) Fail Notation "( x -- y , .. , z )" := (ex (fun z => .. (ex (fun y => x)) ..)) (y binder, z binder). (* Ends of pattern do not match *) Fail Notation "( x , y , .. , z )" := (pair y .. (pair (plus z) 0) ..). Fail Notation "( x , y , .. , z )" := (pair y .. (plus z 0) ..). Fail Notation "( x1 , x2 , y , .. , z )" := (y y .. (x2 z 0) ..). Fail Notation "( x1 , x2 , y , .. , z )" := (x1 y .. (x2 z 0) ..). (* Ends of pattern are the same *) Fail Notation "( x , y , .. , z )" := (pair .. (pair (pair y z) x) .. x). (**********************************************************************) (* Check preservation of scopes at printing time *) Abbreviation SUM := sum. Check SUM (nat*nat) nat. (**********************************************************************) (* Check preservation of implicit arguments at printing time *) Abbreviation FST := fst. Check FST (0;1). (**********************************************************************) (* Check notations for references with activated or deactivated *) (* implicit arguments *) Abbreviation Nil := @nil. Check Nil. Abbreviation NIL := nil. Check NIL : list nat. (**********************************************************************) (* Test printing of notation with coercions in scope of a coercion *) Open Scope nat_scope. Coercion is_true := fun b => b=true. Coercion of_nat n := match n with 0 => true | _ => false end. Notation "'I' x" := (of_nat (S x) || true)%bool (at level 10). Check (false && I 3)%bool /\ I 6. (**********************************************************************) (* Check notations with several recursive patterns *) Notation "[| x , y , .. , z ; a , b , .. , c |]" := (pair (pair .. (pair x y) .. z) (pair .. (pair a b) .. c)). Check [|1,2,3;4,5,6|]. Notation "[| t * ( x , y , .. , z ) ; ( a , b , .. , c ) * u |]" := (pair (pair .. (pair (pair t x) (pair t y)) .. (pair t z)) (pair .. (pair (pair a u) (pair b u)) .. (pair c u))) (t at level 39). Check [|0*(1,2,3);(4,5,6)*false|]. (**********************************************************************) (* Test recursive notations involving applications *) Module Application. Notation "{| f ; x ; .. ; y |}" := ( .. (f x) .. y). (* Application to a variable *) Check fun f => {| f; 0; 1; 2 |} : nat. (* Application to a fun *) Check {| (fun x => x+x); 0 |}. (* Application to a reference *) Axiom op : nat -> nat -> nat. Check {| op; 0; 1 |}. (* Interaction with coercion *) Axiom c : nat -> bool. Coercion c : nat >-> bool. Check false = {| c; 0 |}. End Application. (* Check notations in cases patterns *) Abbreviation SOME := Some. Abbreviation NONE := None. Check (fun x => match x with SOME x => x | NONE => 0 end). Abbreviation NONE2 := (@None _). Abbreviation SOME2 := (@Some _). Check (fun x => match x with SOME2 x => x | NONE2 => 0 end). Abbreviation NONE3 := @None. Abbreviation SOME3 := @Some. Check (fun x => match x with SOME3 _ x => x | NONE3 _ => 0 end). Notation "a :'" := (cons a) (at level 1). Check (fun x => match x with | nil => NONE | h :' t => SOME3 _ t end). (* Check correct matching of "Type" in notations. Of course the notation denotes a term that will be reinterpreted with a different universe than the actual one; but it would be the same anyway without a notation *) Abbreviation s := Type. Check s. (* Test bug #2835: notations were not uniformly managed under prod and lambda *) Open Scope nat_scope. Notation "'foo' n" := (S n) (at level 50): nat_scope. Check (foo 9). Check (fun _ : nat => 9). (* Checking parsing and printing of numerical and non-numerical notations for eq_refl *) (* This notation was not correctly printed until Pierre B.'s improvements to the interpretation of patterns *) Notation "'ONE'" := eq_refl. Check fun (x:nat) (p : x=x) => match p with ONE => ONE end = p. (* This one used to failed at parsing until now *) Notation "1" := eq_refl. Check fun (x:nat) (p : x=x) => match p with 1 => 1 end = p. (* Check bug 5693 *) Module M. Definition A := 0. Definition bar (a b : nat) := plus a b. Notation "" := A (format "", only printing). Check (bar A 0). End M. (* Check eq notations *) Module EqNotationsCheck. Import EqNotations. Section nd. Context (A : Type) (x : A) (P : A -> Type) (y : A) (p : x = y) (v : P x) (v' : P y). Check let k : P y := rew p in v in k. Check let k : P y := rew -> p in v in k. Check let k : P x := rew <- p in v' in k. Check let k : P y := rew [P] p in v in k. Check let k : P y := rew -> [P] p in v in k. Check let k : P x := rew <- [P] p in v' in k. Check let k : P y := rew [fun y => P y] p in v in k. Check let k : P y := rew -> [fun y => P y] p in v in k. Check let k : P x := rew <- [fun y => P y] p in v' in k. Check let k : P y := rew [fun (y : A) => P y] p in v in k. Check let k : P y := rew -> [fun (y : A) => P y] p in v in k. Check let k : P x := rew <- [fun (y : A) => P y] p in v' in k. End nd. Section dep. Context (A : Type) (x : A) (P : forall y, x = y -> Type) (y : A) (p : x = y) (P' : forall x, y = x -> Type) (v : P x eq_refl) (v' : P' y eq_refl). Check let k : P y p := rew dependent p in v in k. Check let k : P y p := rew dependent -> p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- p in v' in k. Check let k : P y p := rew dependent [P] p in v in k. Check let k : P y p := rew dependent -> [P] p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- [P'] p in v' in k. Check let k : P y p := rew dependent [fun y p => P y p] p in v in k. Check let k : P y p := rew dependent -> [fun y p => P y p] p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- [fun y p => P' y p] p in v' in k. Check let k : P y p := rew dependent [fun y p => id (P y p)] p in v in k. Check let k : P y p := rew dependent -> [fun y p => id (P y p)] p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- [fun y p => id (P' y p)] p in v' in k. Check let k : P y p := rew dependent [(fun (y : A) (p : x = y) => P y p)] p in v in k. Check let k : P y p := rew dependent -> [(fun (y : A) (p : x = y) => P y p)] p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- [(fun (x : A) (p : y = x) => P' x p)] p in v' in k. Check let k : P y p := rew dependent [(fun (y : A) (p : x = y) => id (P y p))] p in v in k. Check let k : P y p := rew dependent -> [(fun (y : A) (p : x = y) => id (P y p))] p in v in k. Check let k : P' x (eq_sym p) := rew dependent <- [(fun (x : A) (p : y = x) => id (P' x p))] p in v' in k. Check match p as x in _ = a return P a x with | eq_refl => v end. Check match eq_sym p as p' in _ = a return P' a p' with | eq_refl => v' end. Check match p as x in _ = a return id (P a x) with | eq_refl => v end. Check match eq_sym p as p' in _ = a return id (P' a p') with | eq_refl => v' end. End dep. End EqNotationsCheck. rocq-9.2.0/test-suite/output/Notations2.out000066400000000000000000000037111516144147600207400ustar00rootroot000000000000002 3 : PAIR 2 [+] 3 : nat forall (A : Set) (le : A -> A -> Prop) (x y : A), le x y \/ le y x : Prop match (0, 0, 0) with | (x, y, z) => x + y + z end : nat let '(a, _, _) := (2, 3, 4) in a : nat exists myx y : bool, myx = y : Prop fun (P : nat -> nat -> Prop) (x : nat) => exists y, P x y : (nat -> nat -> Prop) -> nat -> Prop βˆƒ n p : nat, n + p = 0 : Prop let a := 0 in βˆƒ (x y : nat) (b := 1) (c := b) (d := 2) (z : nat), let e := 3 in let f := 4 in x + y = z + d : Prop βˆ€ n p : nat, n + p = 0 : Prop Ξ» n p : nat, n + p = 0 : nat -> nat -> Prop Ξ» (A : Type) (n p : A), n = p : βˆ€ A : Type, A -> A -> Prop Ξ» A : Type, βˆƒ n p : A, n = p : Type -> Prop Ξ» A : Type, βˆ€ n p : A, n = p : Type -> Prop let' f (x y : nat) (a := 0) (z : nat) (_ : bool) := x + y + z + 1 in f 0 1 2 : bool -> nat Ξ» (f : nat -> nat) (x : nat), f(x) + S(x) : (nat -> nat) -> nat -> nat Notation plus2 n := (S(S(n))) Ξ» n : list(nat), match n with | list1 => 0 | _ => 2 end : list(nat) -> nat Ξ» n : list(nat), match n with | list1 => 0 | nil | 0 :: _ | 1 :: _ :: _ | plus2 _ :: _ => 2 end : list(nat) -> nat Ξ» n : list(nat), match n with | nil => 2 | 0 :: _ => 2 | list1 => 0 | 1 :: _ :: _ => 2 | plus2 _ :: _ => 2 end : list(nat) -> nat # x : nat => x : nat -> nat # _ : nat => 2 : nat -> nat # x : nat => # H : x <= 0 => exist (le x) 0 H : βˆ€ x : nat, x <= 0 -> {x0 : nat | x <= x0} exist (Q x) y conj : {x0 : A | Q x x0} % i : nat -> nat % j : nat -> nat {1, 2} : nat -> Prop a# : Set a# : Set a≑ : Set a≑ : Set .≑ : Set .≑ : Set .a# : Set .a# : Set .a≑ : Set .a≑ : Set .Ξ± : Set .Ξ± : Set # a : .Ξ± => # b : .Ξ± => let res := 0 in for i from 0 to a updating (res) {{for j from 0 to b updating (res) {{S res}};; res}};; res : .Ξ± -> .Ξ± -> .Ξ± rocq-9.2.0/test-suite/output/Notations2.v000066400000000000000000000115561516144147600204040ustar00rootroot00000000000000(**********************************************************************) (* Test call to primitive printers in presence of coercion to *) (* functions (cf bug #2044) *) Inductive PAIR := P (n1:nat) (n2:nat). Coercion P : nat >-> Funclass. Check (2 3). (* Check that notations with coercions to functions inserted still work *) (* (were not working from revision 11886 to 12951) *) Record Binop := { binop :> nat -> nat -> nat }. Class Plusop := { plusop : Binop; zero : nat }. Infix "[+]" := plusop (at level 40). #[global] Instance Plus : Plusop := {| plusop := {| binop := plus |} ; zero := 0 |}. Check 2[+]3. (* Test bug #2091 (variable le was printed using <= !) *) Check forall (A: Set) (le: A -> A -> Prop) (x y: A), le x y \/ le y x. (* Test recursive notations in cases pattern *) Remove Printing Let prod. Check match (0,0,0) with (x,y,z) => x+y+z end. Check let '(a,b,c) := ((2,3),4) in a. (* Check printing of notations with mixed reserved binders (see bug #2571) *) Implicit Type myx : bool. Check exists myx y, myx = y. (* Test notation for anonymous functions up to eta-expansion *) Check fun P:nat->nat->Prop => fun x:nat => ex (P x). (* Test notations with binders *) Notation "βˆƒ x .. y , P":= (ex (fun x => .. (ex (fun y => P)) ..)) (x binder, y binder, at level 200, right associativity, format "'[ ' βˆƒ x .. y ']' , P"). Check (βˆƒ n p, n+p=0). Check βˆƒ (a:=0) (x:nat) y (b:=1) (c:=b) (d:=2) z (e:=3) (f:=4), x+y = z+d. Notation "βˆ€ x .. y , P":= (forall x, .. (forall y, P) ..) (x binder, at level 200, right associativity). Check (βˆ€ n p, n+p=0). Notation "'Ξ»' x .. y , P":= (fun x => .. (fun y => P) ..) (y binder, at level 200, right associativity). Check (Ξ» n p, n+p=0). Generalizable Variable A. Check `(Ξ» n p : A, n=p). Check `(βˆƒ n p : A, n=p). Check `(βˆ€ n p : A, n=p). Notation "'let'' f x .. y := t 'in' u":= (let f := fun x => .. (fun y => t) .. in u) (f name, x closed binder, y closed binder, at level 200, right associativity). Check let' f x y (a:=0) z (b:bool) := x+y+z+1 in f 0 1 2. (* In practice, only the printing rule is used here *) (* Note: does not work for pattern *) Module A. #[warning="-postfix-notation-not-level-1"] Notation "f ( x )" := (f x) (at level 10, format "f ( x )"). Check fun f x => f x + S x. Open Scope list_scope. Abbreviation list1 := (1::nil)%list. Abbreviation plus2 n := (S (S n)). (* plus2 was not correctly printed in the two following tests in 8.3pl1 *) Print plus2. Check fun n => match n with list1 => 0 | _ => 2 end. Unset Printing Allow Match Default Clause. Check fun n => match n with list1 => 0 | _ => 2 end. Unset Printing Factorizable Match Patterns. Check fun n => match n with list1 => 0 | _ => 2 end. Set Printing Allow Match Default Clause. Set Printing Factorizable Match Patterns. End A. (* This one is not fully satisfactory because binders in the same type are re-factorized and parentheses are needed even for atomic binder Notation "'mylet' f [ x ; .. ; y ] := t 'in' u":= (let f := fun x => .. (fun y => t) .. in u) (f name, x closed binder, y closed binder, at level 200, right associativity). Check mylet f [x;y;z;(a:bool)] := x+y+z+1 in f 0 1 2. *) (* Check notations for functional terms which do not necessarily depend on their parameter *) (* Old request mentioned again on coq-club 20/1/2012 *) Notation "# x : T => t" := (fun x : T => t) (at level 2, t at level 200, x name). Check # x : nat => x. Check # _ : nat => 2. (* Check bug 4677 *) Check fun x (H:le x 0) => exist (le x) 0 H. Parameters (A : Set) (x y : A) (Q : A -> A -> Prop) (conj : Q x y). Check (exist (Q x) y conj). (* Check bug #4854 *) Notation "% i" := (fun i : nat => i) (at level 2, i name). Check %i. Check %j. (* Check bug raised on coq-club on Sep 12, 2016 *) Notation "{ x , y , .. , v }" := (fun a => (or .. (or (a = x) (a = y)) .. (a = v))). Check ({1, 2}). (**********************************************************************) (* Check notations of the form ".a", ".a≑", "a≑" *) (* Only "a#", "a≑" and ".≑" were working properly for parsing. The *) (* other ones were working only for printing. *) Notation "a#" := nat. Check nat. Check a#. Notation "a≑" := nat. Check nat. Check a≑. Notation ".≑" := nat. Check nat. Check .≑. Notation ".a#" := nat. Check nat. Check .a#. Notation ".a≑" := nat. Check nat. Check .a≑. Notation ".Ξ±" := nat. Check nat. Check .Ξ±. (* A test for #6304 *) Module M6304. Notation "'for' m 'from' 0 'to' N 'updating' ( s1 ) {{ b }} ;; rest" := (let s1 := (fix rec(n: nat) := match n with | 0 => s1 | S m => let s1 := rec m in b end) N in rest) (at level 20). Check fun (a b : nat) => let res := 0 in for i from 0 to a updating (res) {{ for j from 0 to b updating (res) {{ S res }};; res }};; res. End M6304. rocq-9.2.0/test-suite/output/Notations3.out000066400000000000000000000210131516144147600207340ustar00rootroot00000000000000{x : nat | x = 0} + {True /\ False} + {forall x : nat, x = 0} : Set [<0, 2 >] : nat * nat * (nat * nat) [<0, 2 >] : nat * nat * (nat * nat) (0, 2, (2, 2)) : nat * nat * (nat * nat) pair (pair 0 2) (pair 2 0) : prod (prod nat nat) (prod nat nat) << 0, 2, 4 >> : nat * nat * nat * (nat * (nat * nat)) << 0, 2, 4 >> : nat * nat * nat * (nat * (nat * nat)) (0, 2, 4, (2, (2, 0))) : nat * nat * nat * (nat * (nat * nat)) (0, 2, 4, (0, (2, 4))) : nat * nat * nat * (nat * (nat * nat)) pair (pair (pair 0 2) 4) (pair 4 (pair 2 0)) : prod (prod (prod nat nat) nat) (prod nat (prod nat nat)) ETA x y : nat, Nat.add : nat -> nat -> nat ETA x y : nat, Nat.add : nat -> nat -> nat ETA x y : nat, Nat.add : nat -> nat -> nat fun x y : nat => Nat.add x y : forall (_ : nat) (_ : nat), nat ETA x y : nat, le_S : forall x y : nat, x <= y -> x <= S y fun f : forall x : nat * (bool * unit), ?T => CURRY (x : nat) (y : bool), f : (forall x : nat * (bool * unit), ?T) -> forall (x : nat) (y : bool), ?T@{x:=(x, (y, tt))} where ?T : [x : nat * (bool * unit) |- Type] fun f : forall x : bool * (nat * unit), ?T => CURRYINV (x : nat) (y : bool), f : (forall x : bool * (nat * unit), ?T) -> forall (x : nat) (y : bool), ?T@{x:=(y, (x, tt))} where ?T : [x : bool * (nat * unit) |- Type] fun f : forall x : unit * nat * bool, ?T => CURRYLEFT (x : nat) (y : bool), f : (forall x : unit * nat * bool, ?T) -> forall (x : nat) (y : bool), ?T@{x:=(tt, x, y)} where ?T : [x : unit * nat * bool |- Type] fun f : forall x : unit * bool * nat, ?T => CURRYINVLEFT (x : nat) (y : bool), f : (forall x : unit * bool * nat, ?T) -> forall (x : nat) (y : bool), ?T@{x:=(tt, y, x)} where ?T : [x : unit * bool * nat |- Type] forall n : nat, {#n | 1 > n} : Prop forall x : nat, {|x | x > 0|} : Prop exists2 x : nat, x = 1 & x = 2 : Prop fun n : nat => foo2 n (fun x y z : nat => (fun _ _ _ : nat => x + y + z = 0) z y x) : nat -> Prop fun n : nat => foo2 n (fun a b c : nat => (fun _ _ _ : nat => a + b + c = 0) c b a) : nat -> Prop fun n : nat => foo2 n (fun n0 y z : nat => (fun _ _ _ : nat => n0 + y + z = 0) z y n0) : nat -> Prop fun n : nat => foo2 n (fun x n0 z : nat => (fun _ _ _ : nat => x + n0 + z = 0) z n0 x) : nat -> Prop fun n : nat => foo2 n (fun x y n0 : nat => (fun _ _ _ : nat => x + y + n0 = 0) n0 y x) : nat -> Prop fun n : nat => {|n, y | fun _ _ _ : nat => n + y = 0 |}_2 : nat -> Prop fun n : nat => {|n, y | fun _ _ _ : nat => n + y = 0 |}_2 : nat -> Prop fun n : nat => {|n, n0 | fun _ _ _ : nat => n + n0 = 0 |}_2 : nat -> Prop fun n : nat => foo2 n (fun x y z : nat => (fun _ _ _ : nat => x + y + n = 0) z y x) : nat -> Prop fun n : nat => foo2 n (fun x y z : nat => (fun _ _ _ : nat => x + y + n = 0) z y x) : nat -> Prop fun n : nat => {|n, fun _ : nat => 0 = 0 |}_3 : nat -> Prop fun n : nat => {|n, fun _ : nat => n = 0 |}_3 : nat -> Prop fun n : nat => foo3 n (fun x _ : nat => ETA z : nat, (fun _ : nat => x = 0)) : nat -> Prop fun n : nat => {|n, fun _ : nat => 0 = 0 |}_4 : nat -> Prop fun n : nat => {|n, fun _ : nat => n = 0 |}_4 : nat -> Prop fun n : nat => foo4 n (fun _ _ : nat => ETA z : nat, (fun _ : nat => z = 0)) : nat -> Prop fun n : nat => foo4 n (fun _ y : nat => ETA z : nat, (fun _ : nat => y = 0)) : nat -> Prop tele (t : Type) '(y, z) (x : t) := tt : forall t : Type, nat * nat -> t -> fpack tele (t : Type) (y := nat) (x : t) (z : y) := (y, z) : forall t : Type, t -> nat -> fpack [fun x : nat => x + 0;; fun x : nat => x + 1;; fun x : nat => x + 2] : (nat -> nat) * ((nat -> nat) * ((nat -> nat) * ((nat -> nat) * ((nat -> nat) * ((nat -> nat) * (nat -> nat)))))) foo5 x nat x : nat -> nat fun x : ?A => x === x : forall x : ?A, x = x where ?A : [x : ?A |- Type] (x cannot be used) {{0, 1}} : nat * nat {{0, 1, 2}} : nat * (nat * nat) {{0, 1, 2, 3}} : nat * (nat * (nat * nat)) File "./output/Notations3.v", line 179, characters 0-174: Warning: Closed notations (i.e. starting and ending with a terminal symbol) should usually be at level 0 (default). [closed-notation-not-level-0,parsing,default] letpair x [1] = {0}; return (1, 2, 3, 4) : nat * nat * nat * nat ((*1).2).3 : nat *(1.2) : nat {{ 1 | 1 // 1 }} : nat !!! _ _ : nat, True : (nat -> Prop) * ((nat -> Prop) * Prop) ! '{{x, y}}, x.y = 0 : Prop exists_mixed (x y : nat) '{{u, t}}, x.y = 0 /\ u.t = 0 : Prop exists_mixed (x y : nat) '{{z, t}}, x.y = 0 /\ z.t = 0 : Prop exists_true '{{x, y}} (u := 0) '{{z, t}}, x.y = 0 /\ z.t = 0 : Prop exists_true (A : Type) (R : A -> A -> Prop) (_ : Reflexive R), (forall x : A, R x x) : Prop exists_true (x : nat) (A : Type) (R : A -> A -> Prop) (_ : Reflexive R) (y : nat), x.y = 0 -> forall z : A, R z z : Prop !! _ _ : nat # True # : Prop * Prop * Prop {{D 1, 2}} : nat * nat * (nat * nat * (nat * nat)) ! a b : nat # True # : Prop * (Prop * Prop) {{forall x : nat, x = 0, nat}} : Prop * Set !!!! a b : nat # True # : Prop * Prop * (Prop * Prop * Prop) @@ a b : nat # a = b # b = a # : Prop * Prop exists_non_null x y z t : nat , x = y /\ z = t : Prop forall_non_null x y z t : nat , x = y /\ z = t : Prop {{RL 1, 2}} : nat * (nat * nat) {{RR 1, 2}} : nat * nat * nat @pair nat (prod nat nat) (S (S O)) (@pair nat nat (S O) O) : prod nat (prod nat nat) @pair (prod nat nat) nat (@pair nat nat O (S (S O))) (S O) : prod (prod nat nat) nat {{RLRR 1, 2}} : nat * (nat * nat) * (nat * nat * nat) * (nat * (nat * nat)) * (nat * nat * nat) pair (pair (pair (pair 2 (pair 1 0)) (pair (pair 0 2) 1)) (pair 1 (pair 2 0))) (pair (pair 0 1) 2) : prod (prod (prod (prod nat (prod nat nat)) (prod (prod nat nat) nat)) (prod nat (prod nat nat))) (prod (prod nat nat) nat) fun x : nat => if x is n .+ 1 then n else 1 : nat -> nat {'{{x, y}} : nat * nat | x.y = 0} : Set exists2' {{x, y}}, x = 0 & y = 0 : Prop myexists2 x : nat * nat, let '{{y, z}} := x in y > z & let '{{y, z}} := x in z > y : Prop fun '({{x, y}} as z) => x.y = 0 /\ z = z : nat * nat -> Prop myexists ({{x, y}} as z), x.y = 0 /\ z = z : Prop exists '({{x, y}} as z), x.y = 0 /\ z = z : Prop βˆ€ '({{x, y}} as z), x.y = 0 /\ z = z : Prop fun '({{{{x, y}}, true}} | {{{{x, y}}, false}}) => x.y : nat * nat * bool -> nat myexists ({{{{x, y}}, true}} | {{{{x, y}}, false}}), x > y : Prop exists '({{{{x, y}}, true}} | {{{{x, y}}, false}}), x > y : Prop βˆ€ '({{{{x, y}}, true}} | {{{{x, y}}, false}}), x > y : Prop fun p : nat => if p is S n then n else 0 : nat -> nat fun p : comparison => if p is Lt then 1 else 0 : comparison -> nat fun S : nat => [S | S.S] : nat -> nat * (nat -> nat) fun N : nat => [N | N.0] : nat -> nat * (nat -> nat) fun S : nat => [[S | S.S]] : nat -> nat * (nat -> nat) {I : nat | I = I} : Set {'I : True | I = I} : Prop {'{{x, y}} : nat * nat | x.y = 0} : Set exists2 '{{y, z}} : nat * nat, y > z & z > y : Prop foo = fun l : list nat => match l with | _ :: (_ :: _) as l1 => l1 | _ => l end : list nat -> list nat Arguments foo l%_list_scope Notation "'exists' x .. y , p" := (ex (fun x => .. (ex (fun y => p)) ..)) : type_scope (default interpretation) (from Corelib.Init.Logic) Notation "'exists' ! x .. y , p" := (ex (unique (fun x => .. (ex (unique (fun y => p))) ..))) : type_scope (default interpretation) (from Corelib.Init.Logic) Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope (default interpretation) (from Corelib.Init.Datatypes) 1 goal ============================ ##@% ^^^ myfoo01 tt : nat myfoo01 tt : nat myfoo01 tt : nat 1 βͺ― 2 βͺ― 3 βͺ― 4 : Prop 1 goal x : nat ============================ |-_0 x 1 goal xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx : nat ============================ |-_0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx * xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx FORALL [[a, b]], a - b = 0 : Prop βˆ€ (A : TypTerm) (B : β—» A -> TypTerm), (βˆ€ a : β—» A, β—» {B a}) -> β—» (βˆ€' {a : β—» A}, {B a}) : Type FORALL [[a, b]], a - b = 0 : Prop βˆ€ a b : nat, a - b = 0 : Prop fun x : option unit => match x with | # tt & => # tt & | None => None end : option unit -> option unit rocq-9.2.0/test-suite/output/Notations3.v000066400000000000000000000436561516144147600204130ustar00rootroot00000000000000(**********************************************************************) (* Check precedence, spacing, etc. in printing with curly brackets *) Check {x|x=0}+{True/\False}+{forall x, x=0}. (**********************************************************************) (* Check printing of notations with several instances of a recursive pattern *) (* Was wrong but I could not trigger a problem due to the collision between *) (* different instances of ".." *) Notation "[< x , y , .. , z >]" := (pair (.. (pair x y) ..) z,pair y ( .. (pair z x) ..)). Check [<0,2>]. Check ((0,2),(2,0)). Check ((0,2),(2,2)). Unset Printing Notations. Check [<0,2>]. Set Printing Notations. Notation "<< x , y , .. , z >>" := ((.. (x,y) .., z),(z, .. (y,x) ..)). Check <<0,2,4>>. Check (((0,2),4),(4,(2,0))). Check (((0,2),4),(2,(2,0))). Check (((0,2),4),(0,(2,4))). Unset Printing Notations. Check <<0,2,4>>. Set Printing Notations. (**********************************************************************) (* Check notations with recursive notations both in binders and terms *) Notation "'ETA' x .. y , f" := (fun x => .. (fun y => (.. (f x) ..) y ) ..) (at level 200, x binder, y binder). Check ETA (x:nat) (y:nat), Nat.add. Check ETA (x y:nat), Nat.add. Check ETA x y, Nat.add. Unset Printing Notations. Check ETA (x:nat) (y:nat), Nat.add. Set Printing Notations. Check ETA x y, le_S. Notation "'CURRY' x .. y , f" := (fun x => .. (fun y => f (x, .. (y,tt) ..)) ..) (at level 200, x binder, y binder). Check fun f => CURRY (x:nat) (y:bool), f. Notation "'CURRYINV' x .. y , f" := (fun x => .. (fun y => f (y, .. (x,tt) ..)) ..) (at level 200, x binder, y binder). Check fun f => CURRYINV (x:nat) (y:bool), f. Notation "'CURRYLEFT' x .. y , f" := (fun x => .. (fun y => f (.. (tt,x) .., y)) ..) (at level 200, x binder, y binder). Check fun f => CURRYLEFT (x:nat) (y:bool), f. Notation "'CURRYINVLEFT' x .. y , f" := (fun x => .. (fun y => f (.. (tt,y) .., x)) ..) (at level 200, x binder, y binder). Check fun f => CURRYINVLEFT (x:nat) (y:bool), f. (**********************************************************************) (* Notations with variables bound both as a term and as a binder *) (* This is #4592 *) Notation "{# x | P }" := (ex2 (fun y => x = y) (fun x => P)). Check forall n:nat, {# n | 1 > n}. Parameter foo : forall {T}(x : T)(P : T -> Prop), Prop. Notation "{| x | P |}" := (foo x (fun x => P)). Check forall x:nat, {| x | x > 0 |}. Check ex2 (fun x => x=1) (fun x0 => x0=2). (* Other tests about alpha-conversions: the following notation contains all three kinds of bindings: - x is bound in the lhs as a term and a binder: its name is forced by its position as a term; it can bind variables in P - y is bound in the lhs as a binder only: its name is given by its name as a binder in the term to display; it can bind variables in P - z is a binder local to the rhs; it cannot bind a variable in P *) Parameter foo2 : forall {T}(x : T)(P : T -> T -> T -> Prop), Prop. Notation "{| x , y | P |}_2" := (foo2 x (fun x y z => P z y x)). (* Not printable: z (resp c, n) occurs in P *) Check fun n => foo2 n (fun x y z => (fun _ _ _ => x+y+z=0) z y x). Check fun n => foo2 n (fun a b c => (fun _ _ _ => a+b+c=0) c b a). Check fun n => foo2 n (fun n y z => (fun _ _ _ => n+y+z=0) z y n). Check fun n => foo2 n (fun x n z => (fun _ _ _ => x+n+z=0) z n x). Check fun n => foo2 n (fun x y n => (fun _ _ _ => x+y+n=0) n y x). (* Printable *) Check fun n => foo2 n (fun x y z => (fun _ _ _ => x+y=0) z y x). Check fun n => foo2 n (fun n y z => (fun _ _ _ => n+y=0) z y n). Check fun n => foo2 n (fun x n z => (fun _ _ _ => x+n=0) z n x). (* Not printable: renaming x into n would bind the 2nd occurrence of n *) Check fun n => foo2 n (fun x y z => (fun _ _ _ => x+y+n=0) z y x). Check fun n => foo2 n (fun x y z => (fun _ _ _ => x+y+n=0) z y x). (* Other tests *) Parameter foo3 : forall {T}(x : T)(P : T -> T -> T -> Prop), Prop. Notation "{| x , P |}_3" := (foo3 x (fun x x x => P x)). (* Printable *) Check fun n : nat => foo3 n (fun x y z => (fun _ => 0=0) z). Check fun n => foo3 n (fun x y z => (fun _ => z=0) z). (* Not printable: renaming z in n would hide the renaming of x into n *) Check fun n => foo3 n (fun x y z => (fun _ => x=0) z). (* Other tests *) Parameter foo4 : forall {T}(x : T)(P : T -> T -> T -> Prop), Prop. Notation "{| x , P |}_4" := (foo4 x (fun x _ z => P z)). (* Printable *) Check fun n : nat => foo4 n (fun x y z => (fun _ => 0=0) z). Check fun n => foo4 n (fun x y z => (fun _ => x=0) z). (* Not printable: y, z not allowed to occur in P *) Check fun n => foo4 n (fun x y z => (fun _ => z=0) z). Check fun n => foo4 n (fun x y z => (fun _ => y=0) z). (**********************************************************************) (* Test printing of #4932 *) Inductive ftele : Type := | fb {T:Type} : T -> ftele | fr {T} : (T -> ftele) -> ftele. Fixpoint args ftele : Type := match ftele with | fb _ => unit | fr f => sigT (fun t => args (f t)) end. Definition fpack := sigT args. Definition pack fp fa : fpack := existT _ fp fa. Notation "'tele' x .. z := b" := (fun x => .. (fun z => pack (fr (fun x => .. ( fr (fun z => fb b) ) .. ) ) (existT _ x .. (existT _ z tt) .. ) ) ..) (at level 85, x binder, z binder). Check tele (t:Type) '((y,z):nat*nat) (x:t) := tt. Check tele (t:Type) (y:=nat) (x:t) (z:y) := (y,z). (* Checking that "fun" in a notation does not mixed up with the detection of a recursive binder *) Notation "[ x ;; .. ;; y ]" := ((x,((fun u => S u), .. (y,(fun u => S u,fun v:nat => v)) ..))). Check [ fun x => x+0 ;; fun x => x+1 ;; fun x => x+2 ]. (* Cyprien's part of bug #4765 *) Section Bug4765. Abbreviation foo5 x T y := (fun x : T => y). Check foo5 x nat x. End Bug4765. (**********************************************************************) (* Test printing of #5526 *) Notation "x === x" := (eq_refl x) (only printing, at level 10). Check (fun x => eq_refl x). (* Test recursive notations with the recursive pattern repeated on the right *) Notation "{{ x , .. , y , z }}" := (pair x .. (pair y z) ..). Check {{0,1}}. Check {{0,1,2}}. Check {{0,1,2,3}}. (* Test printing of #5608 *) Reserved Notation "'letpair' x [1] = { A } ; 'return' ( b0 , b1 , .. , b2 )" (at level 200, format "'letpair' x [1] = { A } ; '//' 'return' ( b0 , b1 , .. , b2 )"). Notation "'letpair' x [1] = { a } ; 'return' ( b0 , b1 , .. , b2 )" := (let x:=a in ( .. (b0,b1) .., b2)). Check letpair x [1] = {0}; return (1,2,3,4). (* Allow level for leftmost nonterminal when printing-only, BZ#5739 *) Notation "* x" := (id x) (only printing, at level 15, format "* x"). Notation "x . y" := (x + y) (only printing, at level 20, x at level 14, left associativity, format "x . y"). Check (((id 1) + 2) + 3). Check (id (1 + 2)). (* Test spacing in #5569 *) Notation "{ { xL | xR // xcut } }" := (xL+xR+xcut) (at level 0, xR at level 39, format "{ { xL | xR // xcut } }"). Check 1+1+1. (* Test presence of notation variables in the recursive parts (introduced in dfdaf4de) *) Notation "!!! x .. y , b" := ((fun x => b), .. ((fun y => b), True) ..) (at level 200, x binder). Check !!! (x y:nat), True. (* Test contraction of "forall x, let 'pat := x in ..." into "forall 'pat, ..." *) (* for isolated "forall" (was not working already in 8.6) *) Notation "! x .. y , A" := (id (forall x, .. (id (forall y, A)) .. )) (at level 200, x binder). Check ! '(x,y), x+y=0. (* Check that the terminator of a recursive pattern is interpreted in the correct environment of bindings *) Notation "'exists_mixed' x .. y , P" := (ex (fun x => forall z:nat, .. (ex (fun y => forall z:nat, z=0 /\ P)) ..)) (at level 200, x binder). Check exists_mixed x y '(u,t), x+y=0/\u+t=0. Check exists_mixed x y '(z,t), x+y=0/\z+t=0. (* Check that intermediary let-in are inserted in between instances of the repeated pattern *) Notation "'exists_true' x .. y , P" := (exists x, True /\ .. (exists y, True /\ P) ..) (at level 200, x binder). Check exists_true '(x,y) (u:=0) '(z,t), x+y=0/\z+t=0. (* Check that generalized binders are correctly interpreted *) Module G. Generalizable Variables A R. Class Reflexive {A:Type} (R : A->A->Prop) := reflexivity : forall x : A, R x x. Check exists_true `(Reflexive A R), forall x, R x x. Check exists_true x `(Reflexive A R) y, x+y=0 -> forall z, R z z. End G. (* Allows recursive patterns for binders to be associative on the left *) Notation "!! x .. y # A #" := (.. (A,(forall x, True)) ..,(forall y, True)) (at level 0, x binder). Check !! a b : nat # True #. (* Examples where the recursive pattern refer several times to the recursive variable *) Notation "{{D x , .. , y }}" := ((x,x), .. ((y,y),(0,0)) ..). Check {{D 1, 2 }}. #[warning="-closed-notation-not-level-0"] Notation "! x .. y # A #" := ((forall x, x=x), .. ((forall y, y=y), A) ..) (at level 200, x binder). Check ! a b : nat # True #. Check ((forall x, x=0), nat). (* should not use the notation *) Notation "!!!! x .. y # A #" := (((forall x, x=x),(forall x, x=0)), .. (((forall y, y=y),(forall y, y=0)), A) ..) (at level 0, x binder). Check !!!! a b : nat # True #. Notation "@@ x .. y # A # B #" := ((forall x, .. (forall y, A) ..), (forall x, .. (forall y, B) ..)) (at level 0, x binder). Check @@ a b : nat # a=b # b=a #. Notation "'exists_non_null' x .. y , P" := (ex (fun x => x <> 0 /\ .. (ex (fun y => y <> 0 /\ P)) ..)) (at level 200, x binder). Check exists_non_null x y z t , x=y/\z=t. Notation "'forall_non_null' x .. y , P" := (forall x, x <> 0 -> .. (forall y, y <> 0 -> P) ..) (at level 200, x binder). Check forall_non_null x y z t , x=y/\z=t. (* Examples where the recursive pattern is in reverse order *) Notation "{{RL c , .. , d }}" := (pair d .. (pair c 0) ..). Check {{RL 1 , 2}}. Notation "{{RR c , .. , d }}" := (pair .. (pair 0 d) .. c). Check {{RR 1 , 2}}. Set Printing All. Check {{RL 1 , 2}}. Check {{RR 1 , 2}}. Unset Printing All. Notation "{{RLRR c , .. , d }}" := (pair d .. (pair c 0) .., pair .. (pair 0 d) .. c, pair c .. (pair d 0) .., pair .. (pair 0 c) .. d). Check {{RLRR 1 , 2}}. Unset Printing Notations. Check {{RLRR 1 , 2}}. Set Printing Notations. (* Check insensitivity of "match" clauses to order *) Module IfPat. Notation "'if' t 'is' n .+ 1 'then' p 'else' q" := (match t with S n => p | 0 => q end) (at level 200). Check fun x => if x is n.+1 then n else 1. End IfPat. (* Examples with binding patterns *) Check {'(x,y)|x+y=0}. Module D. Notation "'exists2'' x , p & q" := (ex2 (fun x => p) (fun x => q)) (at level 200, x pattern, p at level 200, right associativity, format "'[' 'exists2'' '/ ' x , '/ ' '[' p & '/' q ']' ']'") : type_scope. Check exists2' (x,y), x=0 & y=0. End D. (* Ensuring for reparsability that printer of notations does not use a pattern where only an ident could be reparsed *) Module E. Inductive myex2 {A:Type} (P Q:A -> Prop) : Prop := myex_intro2 : forall x:A, P x -> Q x -> myex2 P Q. Notation "'myexists2' x : A , p & q" := (myex2 (A:=A) (fun x => p) (fun x => q)) (at level 200, x name, A at level 200, p at level 200, right associativity, format "'[' 'myexists2' '/ ' x : A , '/ ' '[' p & '/' q ']' ']'") : type_scope. Check myex2 (fun x => let '(y,z) := x in y>z) (fun x => let '(y,z) := x in z>y). End E. (* A canonical example of a notation with a non-recursive binder *) Parameter myex : forall {A}, (A -> Prop) -> Prop. Notation "'myexists' x , p" := (myex (fun x => p)) (at level 200, x pattern, p at level 200, right associativity). (* A canonical example of a notation with recursive binders *) Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity) : type_scope. (* Check that printing 'pat uses an "as" when the variable bound to the pattern is dependent. We check it for the three kinds of notations involving bindings of patterns *) Check fun '((x,y) as z) => x+y=0/\z=z. (* Primitive fun/forall *) Check myexists ((x,y) as z), x+y=0/\z=z. (* Isolated binding pattern *) Check exists '((x,y) as z), x+y=0/\z=z. (* Applicative recursive binder *) Check βˆ€ '((x,y) as z), x+y=0/\z=z. (* Other example of recursive binder, now treated as the exists case *) (* Check parsability and printability of irrefutable disjunctive patterns *) Check fun '(((x,y),true)|((x,y),false)) => x+y. Check myexists (((x,y),true)|((x,y),false)), x>y. Check exists '(((x,y),true)|((x,y),false)), x>y. Check βˆ€ '(((x,y),true)|((x,y),false)), x>y. (* Check Georges' printability of a "if is then else" notation *) Module IfPat2. Notation "'if' c 'is' p 'then' u 'else' v" := (match c with p => u | _ => v end) (at level 200, p pattern at level 100). Check fun p => if p is S n then n else 0. Check fun p => if p is Lt then 1 else 0. End IfPat2. (* Check that mixed binders and terms defaults to ident and not pattern *) Module F. (* First without an indirection *) Notation "[ n | t ]" := (n, (fun n : nat => t)). Check fun S : nat => [ S | S+S ]. Check fun N : nat => (N, (fun n => n+0)). (* another test in passing *) (* Then with an indirection *) Notation "[[ n | p | t ]]" := (n, (fun p : nat => t)). Notation "[[ n | t ]]" := [[ n | n | t ]]. Check fun S : nat => [[ S | S+S ]]. End F. (* Check parsability/printability of {x|P} and variants *) Check {I:nat|I=I}. Check {'I:True|I=I}. Check {'(x,y)|x+y=0}. (* Check exists2 with a pattern *) Check ex2 (fun x => let '(y,z) := x in y>z) (fun x => let '(y,z) := x in z>y). Module Issue7110. Open Scope list_scope. Notation "[ :: x1 , x2 , .. , xn & s ]" := (x1 :: x2 :: .. (xn :: s) ..) (at level 0). Definition foo (l : list nat) := match l with | a :: (b :: l) as l1 => l1 | _ => l end. Print foo. End Issue7110. Module LocateNotations. Locate "exists". Locate "( _ , _ , .. , _ )". End LocateNotations. Module Issue7731. Axiom (P : nat -> Prop). Parameter (X : nat). Notation "## @ E ^^^" := (P E) (at level 0, E at level 1, format "'[ ' ## '/' @ E '/' ^^^ ']'"). Notation "%" := X. Set Printing Width 7. Goal ## @ % ^^^. Show. Abort. End Issue7731. Module Issue8126. Definition myfoo (x : nat) (y : nat) (z : unit) := y. Abbreviation myfoo0 := (@myfoo 0). Abbreviation myfoo01 := (@myfoo0 1). Check myfoo 0 1 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *) Check myfoo0 1 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *) Check myfoo01 tt. (* was printing [myfoo0 1 HI], but should print [myfoo01 HI] *) End Issue8126. Module RecursiveNotationPartialApp. (* Discussed on Coq Club, 28 July 2020 *) Notation "x βͺ― y βͺ― .. βͺ― z βͺ― t" := ((fun b A a => a <= b /\ A b) y .. ((fun b A a => a <= b /\ A b) z (fun b => b <= t)) .. x) (at level 70, y at next level, z at next level, t at next level). Check 1 βͺ― 2 βͺ― 3 βͺ― 4. End RecursiveNotationPartialApp. Module GoalConclBox. (* The conclusion was sometimes printed vertically (see https://coq.zulipchat.com/#narrow/stream/237977-Coq-users/topic/Strange.20newline.20in.20printing) *) Notation "|-_0 x" := (x = 0) (at level 70, format "|-_0 '/' x"). Lemma test x : |-_0 x. Show. Abort. Lemma test xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx : |-_0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx * xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. Show. Abort. End GoalConclBox. Module PartOfIssue17094. Notation "'FORALL' x .. y , P" := (forall x , .. (forall y , P) .. ) (at level 200, x constr at level 8 as pattern, right associativity, format "'[ ' '[ ' 'FORALL' x .. y ']' , '/' P ']'") : type_scope. Notation "[[ x , y ]]" := (x, y). Check FORALL [[a , b]], a - b = 0. End PartOfIssue17094. Module PartOfIssue17094PrintingAssumption. Declare Custom Entry quoted. Notation "( x )" := x (in custom quoted at level 0, x at level 200). Notation "x" := x (in custom quoted at level 0, x global). Notation "{ A }" := A (in custom quoted at level 0, A constr at level 200). Axiom TypTerm : Type. Axiom qType : Type -> TypTerm. Axiom ValTerm : TypTerm -> Type. Notation "β—» A" := (ValTerm A) (at level 9, right associativity, A custom quoted at level 9). Notation "β—» A" := (qType (ValTerm A)) (in custom quoted at level 9, right associativity, A custom quoted at level 9). Declare Custom Entry quoted_binder. Notation "{ x }" := x (in custom quoted_binder at level 0, x constr). Axiom FORALL : forall {A : TypTerm} (B : ValTerm A -> TypTerm), TypTerm. Notation "βˆ€' x .. y , P" := (FORALL (fun x => .. (FORALL (fun y => P)) .. )) (in custom quoted at level 200, x custom quoted_binder as pattern, right associativity, format "'[ ' '[ ' βˆ€' x .. y ']' , '/' P ']'") : type_scope. Check βˆ€ A (B : ValTerm A -> TypTerm), (βˆ€ (a : β—»A), β—»{B a}) -> β—»(βˆ€' {a}, {B a}). End PartOfIssue17094PrintingAssumption. Module PartOfIssue17094Pattern. (* The same but referring this time to a pattern *) Notation "'FORALL' x .. y , P" := (forall x , .. (forall y , P) .. ) (at level 200, x constr at level 8 as pattern, right associativity, format "'[ ' '[ ' 'FORALL' x .. y ']' , '/' P ']'") : type_scope. Notation "[[ x , y ]]" := (x,y) (x pattern, y pattern). Check FORALL [[a , b]], a - b = 0. End PartOfIssue17094Pattern. Module PartOfIssue17094Ident. (* A variant with custom entries and referring this time to a ident *) Declare Custom Entry quoted_binder'. Notation "x" := x (in custom quoted_binder' at level 0, x ident). Notation "'FORALL' x .. y , P" := (forall x , .. (forall y , P) .. ) (at level 200, x custom quoted_binder' as pattern, right associativity, format "'[ ' '[ ' 'FORALL' x .. y ']' , '/' P ']'") : type_scope. (* Note: notation not used for printing because no rule to print "a:nat" and "b:nat" *) Check FORALL a b, a - b = 0. End PartOfIssue17094Ident. Module BetterFix13078. (* We now support referring to ident and pattern in notations for pattern *) Notation "# x &" := (Some x) (at level 0, x pattern). Check fun (x : option unit) => match x with | None => None | # tt & => # tt & end. End BetterFix13078. rocq-9.2.0/test-suite/output/Notations4.out000066400000000000000000000250641516144147600207470ustar00rootroot00000000000000[< 0 > + < 1 > * < 2 >] : nat Entry custom:Notations4.A.myconstr is [ "6" RIGHTA [ ] | "5" RIGHTA [ SELF; "+"; NEXT ] | "4" RIGHTA [ SELF; "*"; NEXT ] | "0" RIGHTA [ "<"; term LEVEL "10"; ">" ] ] [< b > + < b > * < 2 >] : nat [<< # 0 >>] : option nat [b + c] : nat fun a : nat => [a + a] : nat -> nat File "./output/Notations4.v", line 38, characters 0-88: Warning: This notation will not be used for printing as it is bound to a single variable. [notation-bound-to-variable,parsing,default] [1 {f 1}] : Expr fun (x : nat) (y z : Expr) => [1 + y z + {f x}] : nat -> Expr -> Expr -> Expr fun e : Expr => match e with | [x y + z] => [x + y z] | [1 + 1] => [1] | _ => [e + e] end : Expr -> Expr File "./output/Notations4.v", line 77, characters 41-45: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 77, characters 41-45 with B.expr File "./output/Notations4.v", line 78, characters 31-35: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 78, characters 31-35 with B.expr File "./output/Notations4.v", line 79, characters 41-45: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 79, characters 41-45 with B.expr File "./output/Notations4.v", line 80, characters 33-37: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 80, characters 33-37 with B.expr [(1 + 1)] : Expr myAnd1 True True : Prop r 2 3 : Prop let v := 0%test17 in v : myint63 : myint63 fun y : nat => # (x, z) |-> y & y : forall y : nat, (?T * ?T0 -> ?T * ?T0 * nat) * (?T1 * ?T2 -> ?T1 * ?T2 * nat) where ?T : [y : nat pat : ?T * ?T0 p0 : ?T * ?T0 p := p0 : ?T * ?T0 |- Type] (pat, p0, p cannot be used) ?T0 : [y : nat pat : ?T * ?T0 p0 : ?T * ?T0 p := p0 : ?T * ?T0 |- Type] (pat, p0, p cannot be used) ?T1 : [y : nat pat : ?T1 * ?T2 p0 : ?T1 * ?T2 p := p0 : ?T1 * ?T2 |- Type] (pat, p0, p cannot be used) ?T2 : [y : nat pat : ?T1 * ?T2 p0 : ?T1 * ?T2 p := p0 : ?T1 * ?T2 |- Type] (pat, p0, p cannot be used) fun y : nat => # (x, z) |-> (x + y) & (y + z) : forall y : nat, (nat * ?T -> nat * ?T * nat) * (?T0 * nat -> ?T0 * nat * nat) where ?T : [y : nat pat : nat * ?T p0 : nat * ?T p := p0 : nat * ?T |- Type] (pat, p0, p cannot be used) ?T0 : [y : nat pat : ?T0 * nat p0 : ?T0 * nat p := p0 : ?T0 * nat |- Type] (pat, p0, p cannot be used) fun '{| |} => true : R -> bool File "./output/Notations4.v", line 147, characters 82-85: The command has indeed failed with message: The format is not the same on the right- and left-hand sides of the special token "..". File "./output/Notations4.v", line 151, characters 76-78: The command has indeed failed with message: The format is not the same on the right- and left-hand sides of the special token "..". File "./output/Notations4.v", line 155, characters 78-81: The command has indeed failed with message: The format is not the same on the right- and left-hand sides of the special token "..". File "./output/Notations4.v", line 159, characters 52-55: The command has indeed failed with message: The format is not the same on the right- and left-hand sides of the special token "..". File "./output/Notations4.v", line 165, characters 35-39: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 165, characters 35-39 with B.expr File "./output/Notations4.v", line 166, characters 21-25: Warning: Accessing custom entry B.expr by its unqualified name is deprecated. [deprecated-unqualified-custom-entry,deprecated-since-9.2,deprecated,default] Quickfix: Replace File "./output/Notations4.v", line 166, characters 21-25 with B.expr Entry custom:Notations4.B.expr is [ "0" RIGHTA [ "{"; term LEVEL "200"; "}" ] ] fun x : nat => [ x ] : nat -> nat fun x : nat => [x] : nat -> nat βˆ€ x : nat, x = x : Prop File "./output/Notations4.v", line 193, characters 0-160: Warning: Notation "βˆ€ _ .. _ , _" was already defined with a different format in scope type_scope. [notation-incompatible-format,parsing,default] βˆ€x : nat,x = x : Prop File "./output/Notations4.v", line 206, characters 0-60: Warning: Notation "_ %%% _" was already defined with a different format. [notation-incompatible-format,parsing,default] File "./output/Notations4.v", line 210, characters 0-64: Warning: Notation "_ %%% _" was already defined with a different format. [notation-incompatible-format,parsing,default] File "./output/Notations4.v", line 215, characters 0-62: Warning: Lonely notation "_ %%%% _" was already defined with a different format. [notation-incompatible-format,parsing,default] 3 %% 4 : nat 3 %% 4 : nat 3 %% 4 : nat File "./output/Notations4.v", line 243, characters 47-59: Warning: The format modifier is irrelevant for only-parsing rules. [irrelevant-format-only-parsing,parsing,default] File "./output/Notations4.v", line 247, characters 36-48: Warning: The only parsing modifier has no effect in Reserved Notation. [irrelevant-reserved-notation-only-parsing,parsing,default] fun x : nat => U (S x) : nat -> nat V tt : unit * (unit -> unit) fun x : nat => V x : forall x : nat, nat * (?T -> ?T) where ?T : [x : nat |- Type] File "./output/Notations4.v", line 264, characters 0-30: Warning: Notation "_ :=: _" was already used. [notation-overridden,parsing,default] 0 :=: 0 : Prop fun x : nat => <{ x; (S x) }> : nat -> nat Set : Type fun x : nat => S x : nat -> nat True : Prop exists p : nat, β–’_p (p >= 1) : Prop β–’_n (n >= 1) : Prop File "./output/Notations4.v", line 334, characters 17-20: The command has indeed failed with message: Found an inductive type while a variable name was expected. File "./output/Notations4.v", line 335, characters 17-18: The command has indeed failed with message: Found a constructor while a variable name was expected. File "./output/Notations4.v", line 337, characters 17-18: The command has indeed failed with message: Found a constant while a variable name was expected. exists x y : nat, β–’_(x, y) (x >= 1 /\ y >= 2) : Prop β–’_n (n >= 1) : Prop File "./output/Notations4.v", line 350, characters 17-20: The command has indeed failed with message: Found an inductive type while a pattern was expected. β–’_tt (tt = tt) : Prop File "./output/Notations4.v", line 353, characters 17-18: The command has indeed failed with message: Found a constant while a pattern was expected. exists x y : nat, β–’_(x, y) (x >= 1 /\ y >= 2) : Prop pseudo_force n (fun n : nat => n >= 1) : Prop File "./output/Notations4.v", line 366, characters 17-20: The command has indeed failed with message: Found an inductive type while a pattern was expected. β–’_tt (tt = tt) : Prop File "./output/Notations4.v", line 369, characters 17-18: The command has indeed failed with message: Found a constant while a pattern was expected. exists x y : nat, myforce (x, y) (x >= 1 /\ y >= 2) : Prop myforce n (n >= 1) : Prop File "./output/Notations4.v", line 381, characters 21-24: The command has indeed failed with message: Found an inductive type while a pattern was expected. myforce tt (tt = tt) : Prop File "./output/Notations4.v", line 384, characters 21-22: The command has indeed failed with message: Found a constant while a pattern was expected. id nat : Set fun a : bool => id a : bool -> bool fun nat : bool => id nat : bool -> bool File "./output/Notations4.v", line 396, characters 17-20: The command has indeed failed with message: Found an inductive type while a pattern was expected. !! nat, nat = true : Prop !!! nat, nat = true : Prop !!!! (nat, id), nat = true /\ id = false : Prop βˆ€ x : nat, x = 0 : Prop βˆ€β‚ x, x = 0 : Prop βˆ€β‚ x, x = 0 : Prop βˆ€β‚‚ x y, x + y = 0 : Prop ((1, 2)) : nat * nat %% [x == 1] : Prop %%% [1] : Prop [[2]] : nat * nat %%% : Type ## (x, _) (x = 0) : Prop File "./output/Notations4.v", line 492, characters 21-30: The command has indeed failed with message: Unexpected type constraint in notation already providing a type constraint. ## '(x, y) (x + y = 0) : Prop ## x (x = 0) : Prop ## '(x, y) (x = 0) : Prop fun f : ## a (a = 0) => f 1 eq_refl : ## a (a = 0) -> 1 = 0 [MyNotation 0] : nat fun MyNone : nat => MyNone : nat -> nat MyNone+ : option ?A where ?A : [ |- Type] Some MyNone+ : option (option ?A) where ?A : [ |- Type] 0+ : option ?A where ?A : [ |- Type] 0+ : option ?A where ?A : [ |- Type] 0 : nat File "./output/Notations4.v", line 542, characters 0-78: The command has indeed failed with message: Notation "func _ .. _ , _" is already defined at level 200 with arguments binder, constr at next level while it is now required to be at level 200 with arguments constr, constr at next level. File "./output/Notations4.v", line 547, characters 0-57: The command has indeed failed with message: Notation "[[ _ ]]" is already defined at level 0 with arguments custom foo while it is now required to be at level 0 with arguments custom bar. lambda x y : nat, x + y = 0 : nat -> nat -> Prop ((!!nat) + bool)%type : Set fun z : nat => (z, 1, z, 2) : nat -> nat * nat * nat * nat fun z : nat => [(!!z) + z] : nat -> nat * nat * nat * nat * nat uncurryΞ» a b c => a + b + c : unit * nat * nat * nat -> nat fun x : unit * nat * (nat * nat) => match x with | (x0, y) => match y with | (a, b) => let d := 1 in match x0 with | (x1, c) => let 'tt := x1 in a + b + c + d end end end : unit * nat * (nat * nat) -> nat fun x : unit * nat * (nat * nat) => match x with | (x0, (a, b)) => let d := 1 in match x0 with | (tt, c) => a + b + c + d end end : unit * nat * (nat * nat) -> nat uncurryΞ» '(a, b) => a + b : unit * (nat * nat) -> nat lets a b c := 0 in a + b + c : nat let '(a, b) := (0, 0) in lets d := 1 in let '(c, e) := (0, 0) in a + b + c + d + e : nat rocq-9.2.0/test-suite/output/Notations4.v000066400000000000000000000415171516144147600204060ustar00rootroot00000000000000(* An example with constr subentries *) Module A. Declare Custom Entry myconstr. Notation "[ x ]" := x (x custom myconstr at level 6). Notation "x + y" := (Nat.add x y) (in custom myconstr at level 5). Notation "x * y" := (Nat.mul x y) (in custom myconstr at level 4). Notation "< x >" := x (in custom myconstr at level 0, x constr at level 10). Check [ < 0 > + < 1 > * < 2 >]. Print Custom Grammar myconstr. Axiom a : nat. Abbreviation b := a. Check [ < b > + < a > * < 2 >]. Declare Custom Entry anotherconstr. Notation "[ x ]" := x (x custom myconstr at level 6). Notation "<< x >>" := x (in custom myconstr at level 0, x custom anotherconstr at level 10). Notation "# x" := (Some x) (in custom anotherconstr at level 8, x constr at level 9). Check [ << # 0 >> ]. (* Now check with global *) Axiom c : nat. Notation "x" := x (in custom myconstr at level 0, x global). Check [ b + c ]. Check fun a => [ a + a ]. Module NonCoercions. (* Should we forbid extra coercions in constr (knowing the "( x )" is hard-wiree)? *) Notation "[[ x ]]" := x (at level 0, x at level 42). (* Check invalid coercions (thus not used for printing) *) Notation "[[[ x ]]]" := x (in custom myconstr at level 0, x custom myconstr at level 0). End NonCoercions. End A. Module B. Inductive Expr := | Mul : Expr -> Expr -> Expr | Add : Expr -> Expr -> Expr | One : Expr. Declare Custom Entry expr. Notation "[ expr ]" := expr (expr custom expr at level 3). Notation "1" := One (in custom expr at level 0). Notation "x y" := (Mul x y) (in custom expr at level 1, left associativity). Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity). Notation "( x )" := x (in custom expr at level 0, x at level 3). Notation "{ x }" := x (in custom expr at level 0, x constr). Notation "x" := x (in custom expr at level 0, x ident). Axiom f : nat -> Expr. Check [1 {f 1}]. Check fun x y z => [1 + y z + {f x}]. Check fun e => match e with | [x y + z] => [x + y z] | [1 + 1] => [1] | y => [y + e] end. End B. Module C. Inductive Expr := | Add : Expr -> Expr -> Expr | One : Expr. Notation "[ expr ]" := expr (expr custom expr at level 1). Notation "1" := One (in custom expr at level 0). Notation "x + y" := (Add x y) (in custom expr at level 2, left associativity). Notation "( x )" := x (in custom expr at level 0, x at level 2). (* Check the use of a two-steps coercion from constr to expr 1 then from expr 0 to expr 2 *) Check [(1 + 1)]. End C. (* Fixing overparenthesizing reported by G. Gonthier in #9207 (PR #9214, in 8.10)*) Module I. Definition myAnd A B := A /\ B. Abbreviation 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. Require Import PrimInt63. Module NumberNotations. Module Test17. (** Test uint63 *) Declare Scope test17_scope. Delimit Scope test17_scope with test17. Local Set Primitive Projections. Record myint63 := of_int { to_int : int }. Definition parse x := match x with Pos x => Some (of_int x) | Neg _ => None end. Definition print x := Pos (to_int x). Number Notation myint63 parse print : test17_scope. Check let v := 0%test17 in v : myint63. End Test17. End NumberNotations. Module K. Notation "# x |-> t & u" := ((fun x => (x,t)),(fun x => (x,u))) (at level 2, x pattern, t, u at level 39). Check fun y : nat => # (x,z) |-> y & y. Check fun y : nat => # (x,z) |-> (x + y) & (y + z). End K. Module EmptyRecordSyntax. Record R := { n : nat }. Check fun '{|n:=x|} => true. End EmptyRecordSyntax. Module M. (* Accept boxes around the end variables of a recursive notation (if equal boxes) *) Notation " {@ T1 ; T2 ; .. ; Tn } " := (and T1 (and T2 .. (and Tn True)..)) (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'"). Fail Notation " {@ T1 ; T2 ; .. ; Tn } " := (and T1 (and T2 .. (and Tn True)..)) (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'"). Fail Notation " {@ T1 ; T2 ; .. ; Tn } " := (and T1 (and T2 .. (and Tn True)..)) (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[v' Tn ']' } ']'"). Fail Notation " {@ T1 ; T2 ; .. ; Tn } " := (and T1 (and T2 .. (and Tn True)..)) (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'"). Fail Notation " {@ T1 ; T2 ; .. ; Tn } " := (and T1 (and T2 .. (and Tn True)..)) (format "'[v' {@ '[' T1 ']' ; '//' '[' T2 ']' ; '//' .. ; '//' '[' Tn ']' } ']'"). End M. Module Bug11331. Notation "{ p }" := (p) (in custom expr at level 0, p constr). Print Custom Grammar expr. End Bug11331. Module Bug_6082. Declare Scope foo. Notation "[ x ]" := (S x) (format "[ x ]") : foo. Open Scope foo. Check fun x => S x. Declare Scope bar. Notation "[ x ]" := (S x) (format "[ x ]") : bar. Open Scope bar. Check fun x => S x. End Bug_6082. Module Bug_7766. Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' βˆ€ x .. y ']' , P") : type_scope. Check forall (x : nat), x = x. Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "βˆ€ x .. y , P") : type_scope. Check forall (x : nat), x = x. End Bug_7766. Module N. (* Other tests about generic and specific formats *) Reserved Notation "x %%% y" (format "x %%% y", at level 35). Reserved Notation "x %%% y" (format "x %%% y", at level 35). (* Not using the reserved format, we warn *) Notation "x %%% y" := (x+y) (format "x %%% y", at level 35). (* Same scope (here lonely): we warn *) Notation "x %%%% y" := (x+y) (format "x %%%% y", at level 35). Notation "x %%%% y" := (x+y) (format "x %%%% y", at level 35). (* Test if the format for a specific notation becomes the default generic format or if the generic format, in the absence of a Reserved Notation, is the one canonically obtained from the notation *) Declare Scope foo_scope. Declare Scope bar_scope. Declare Scope bar'_scope. Notation "x %% y" := (x+y) (at level 47, format "x %% y") : foo_scope. Open Scope foo_scope. Check 3 %% 4. (* No scope, we inherit the initial format *) Notation "x %% y" := (x*y) : bar_scope. (* Inherit the format *) Open Scope bar_scope. Check 3 %% 4. (* Different scope and no reserved notation, we don't warn *) Notation "x %% y" := (x*y) (at level 47, format "x %% y") : bar'_scope. Open Scope bar'_scope. Check 3 %% 4. (* Warn for combination of "only parsing" and "format" *) Notation "###" := 0 (at level 0, only parsing, format "###"). (* In reserved notation, warn only for the "only parsing" *) Reserved Notation "##" (at level 0, only parsing, format "##"). End N. Module O. Abbreviation U t := (match t with 0 => 0 | S t => t | _ => 0 end). Check fun x => U (S x). Abbreviation V t := (t,fun t => t). Check V tt. Check fun x : nat => V x. End O. Module Bug12691. Notation "x :=: y" := True (at level 70, no associativity, only parsing). Notation "x :=: y" := (x = y). Check (0 :=: 0). End Bug12691. Module CoercionEntryTransitivity. Declare Custom Entry com. Declare Custom Entry com_top. Notation "<{ e }>" := e (at level 0, e custom com_top at level 99). Notation "x ; y" := (x + y) (in custom com_top at level 90, x custom com at level 90, right associativity). Notation "x" := x (in custom com at level 0, x constr at level 0). Notation "x" := x (in custom com_top at level 90, x custom com at level 90). Check fun x => <{ x ; (S x) }>. End CoercionEntryTransitivity. Module CoercionEntryOnlyParsing. (* bug #15335 *) Declare Custom Entry ent. Notation "ent:( x )" := x (x custom ent, only parsing). Notation "!" := Set (in custom ent at level 0). Check ent:( ! ). End CoercionEntryOnlyParsing. Module CustomIdentOnlyParsing. Declare Custom Entry ent2. Notation "ent:( x )" := x (x custom ent2, format "ent:( x )"). Notation "# x" := (S x) (in custom ent2 at level 2, x at level 0). Notation "x" := x (in custom ent2 at level 0, x ident, only parsing). Check fun x : nat => ent:(# x). End CustomIdentOnlyParsing. Module CustomGlobalOnlyParsing. Declare Custom Entry ent3. Notation "ent:( x )" := x (x custom ent3, format "ent:( x )"). Notation "# x" := (S x) (in custom ent3 at level 2, x at level 0). Notation "x" := x (in custom ent3 at level 0, x global, only parsing). Check ent:(True). End CustomGlobalOnlyParsing. (* Some corner cases *) Module P. (* Basic rules: - a section variable be used for itself and as a binding variable - a global name cannot be used for itself and as a binding variable *) Definition pseudo_force {A} (n:A) (P:A -> Prop) := forall n', n' = n -> P n'. Module NotationMixedTermBinderAsIdent. Notation "β–’_ n P" := (pseudo_force n (fun n => P)) (at level 2, n ident, P at level 9, format "β–’_ n P"). Check exists p, β–’_p (p >= 1). Section S. Variable n:nat. Check β–’_n (n >= 1). End S. Fail Check β–’_nat (nat = bool). Fail Check β–’_O (O >= 1). Axiom n:nat. Fail Check β–’_n (n >= 1). End NotationMixedTermBinderAsIdent. Module NotationMixedTermBinderAsPattern. Notation "β–’_ n P" := (pseudo_force n (fun n => P)) (at level 2, n pattern, P at level 9, format "β–’_ n P"). Check exists x y, β–’_(x,y) (x >= 1 /\ y >= 2). Section S. Variable n:nat. Check β–’_n (n >= 1). End S. Fail Check β–’_nat (nat = bool). Check β–’_tt (tt = tt). Axiom n:nat. Fail Check β–’_n (n >= 1). End NotationMixedTermBinderAsPattern. Module NotationMixedTermBinderAsStrictPattern. Notation "β–’_ n P" := (pseudo_force n (fun n => P)) (at level 2, n strict pattern, P at level 9, format "β–’_ n P"). Check exists x y, β–’_(x,y) (x >= 1 /\ y >= 2). Section S. Variable n:nat. Check β–’_n (n >= 1). End S. Fail Check β–’_nat (nat = bool). Check β–’_tt (tt = tt). Axiom n:nat. Fail Check β–’_n (n >= 1). End NotationMixedTermBinderAsStrictPattern. Module AbbreviationMixedTermBinderAsStrictPattern. Abbreviation myforce n P := (pseudo_force n (fun n => P)). Check exists x y, myforce (x,y) (x >= 1 /\ y >= 2). Section S. Variable n:nat. Check myforce n (n >= 1). (* strict hence not used for printing *) End S. Fail Check myforce nat (nat = bool). Check myforce tt (tt = tt). Axiom n:nat. Fail Check myforce n (n >= 1). End AbbreviationMixedTermBinderAsStrictPattern. Module Bug4765Part. Abbreviation id x := ((fun y => y) x). Check id nat. Abbreviation id' x := ((fun x => x) x). Check fun a : bool => id' a. Check fun nat : bool => id' nat. Fail Check id' nat. End Bug4765Part. Module NotationBinderNotMixedWithTerms. Notation "!! x , P" := (forall x, P) (at level 200, x pattern). Check !! nat, nat = true. Notation "!!! x , P" := (forall x, P) (at level 200). Check !!! nat, nat = true. Notation "!!!! x , P" := (forall x, P) (at level 200, x strict pattern). Check !!!! (nat,id), nat = true /\ id = false. End NotationBinderNotMixedWithTerms. End P. Module MorePrecise1. (* A notation with limited iteration is strictly more precise than a notation with unlimited iteration *) Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'") : type_scope. Check forall x, x = 0. Notation "βˆ€β‚ z , P" := (forall z, P) (at level 200, right associativity) : type_scope. Check forall x, x = 0. Notation "βˆ€β‚‚ y x , P" := (forall y x, P) (at level 200, right associativity) : type_scope. Check forall x, x = 0. Check forall x y, x + y = 0. Notation "(( x , y ))" := (x,y) : core_scope. Check ((1,2)). End MorePrecise1. Module MorePrecise2. (* Case of a bound binder *) Notation "%% [ x == y ]" := (forall x, S x = y) (at level 0, x pattern, y at level 60). (* Case of an internal binder *) Notation "%%% [ y ]" := (forall x : nat, x = y) (at level 0). (* Check that the two previous notations are indeed finer *) Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'"). Notation "βˆ€' x .. y , P" := (forall y, .. (forall x, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€' x .. y ']' , '/' P ']'"). Check %% [x == 1]. Check %%% [1]. Notation "[[ x ]]" := (pair 1 x). Notation "( x ; y ; .. ; z )" := (pair .. (pair x y) .. z). Notation "[ x ; y ; .. ; z ]" := (pair .. (pair x z) .. y). (* Check which is finer *) Check [[ 2 ]]. End MorePrecise2. Module MorePrecise3. (* This is about a binder not bound in a notation being strictly more precise than a binder bound in the notation (since the notation applies - a priori - stricly less often) *) Notation "%%%" := (forall x, x) (at level 0). Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'"). Check %%%. End MorePrecise3. Module TypedPattern. Notation "## x P" := (forall x:nat*nat, P) (x pattern, at level 1). Check ## (x,y) (x=0). Fail Check ## ((x,y):bool*bool) (x=y). End TypedPattern. Module SingleBinder. Notation "## x P" := (forall x, x = x -> P) (x binder, at level 1). Check ## '(x,y) (x+y=0). Check ## (x:nat) (x=0). Check ## '((x,y):nat*nat) (x=0). Check fun (f : ## {a} (a=0)) => f (a:=1) eq_refl. End SingleBinder. Module GenericFormatPrecedence. (* Check that if a generic format exists, we use it preferably to no explicit generic format *) Notation "[ 'MyNotation' G ]" := (S G) (at level 0, format "[ 'MyNotation' G ]") : nat_scope. Notation "[ 'MyNotation' G ]" := (G+0) (at level 0, only parsing) : bool_scope. Notation "[ 'MyNotation' G ]" := (G*0). Check 0*0. End GenericFormatPrecedence. Module LeadingIdent. Notation "'MyNone' +" := None (format "'MyNone' +"). Check fun MyNone : nat => MyNone. Check MyNone+. Check Some MyNone+. End LeadingIdent. Module SymbolsStartingWithNumbers. Notation "0+" := None. Check 0+. End SymbolsStartingWithNumbers. Module LeadingNumber. Notation "0 +" := None (format "0 +"). Check 0+. Check 0. End LeadingNumber. Module Incompatibility. Notation "'func' x .. y , P" := (fun x => .. (fun y => P) ..) (x binder, y binder, at level 200). Fail Notation "'func' x .. y , P" := (pair x .. (pair y P) ..) (at level 200). Declare Custom Entry foo. Declare Custom Entry bar. Notation "[[ x ]]" := x (x custom foo) : nat_scope. Fail Notation "[[ x ]]" := x (x custom bar) : type_scope. End Incompatibility. Module RecursivePatternsArgumentsInRecursiveNotations. Notation "'Ξ»' x .. y , t" := (fun x => .. (fun y => t) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' 'Ξ»' x .. y ']' , '/' t ']'"). Notation "'lambda' x .. y , t" := (Ξ» x .. y, t) (at level 200, x binder, y binder). Check lambda x y, x+y=0. End RecursivePatternsArgumentsInRecursiveNotations. Module CyclicNotations. Notation "! x" := (list x) (at level 2, x at level 50, right associativity, format "! x"). Check ((!!nat) + bool)%type. End CyclicNotations. Module CustomCyclicNotations. Declare Custom Entry myconstr2. Notation "[ x ]" := x (x custom myconstr2 at level 6). Notation "! x" := (x,1) (in custom myconstr2 at level 1, x at level 2, format "! x"). Notation "x + y" := (x,y,2) (in custom myconstr2 at level 2, left associativity). Notation "x" := x (in custom myconstr2 at level 0, x ident). (* Check that the custom notation is not used, because parentheses are missing in the entry *) Check fun z:nat => ((z,1),z,2). Notation "( x )" := x (in custom myconstr2 at level 0, x at level 2). (* Check that parentheses are preserved when an entry refers on the right on a higher level than where it is *) Check fun z:nat => [(!! z) + z]. End CustomCyclicNotations. Module RecursivePatternsInMatch. Remove Printing Let prod. Unset Printing Matching. Notation "'uncurryΞ»' x1 .. xn => body" := (fun x => match x with (pair x x1) => .. (match x with (pair x xn) => let 'tt := x in body end) .. end) (at level 200, x1 binder, xn binder, right associativity). Check uncurryΞ» a b c => a + b + c. (* Check other forms of binders, but too complex interaction with pattern-matching compaction for printing *) Check uncurryΞ» '(a,b) (d:=1) c => a + b + c + d. Set Printing Matching. Check uncurryΞ» '(a,b) (d:=1) c => a + b + c + d. (* This is a case where printing is easy though, relying on pattern-matching compaction *) Check uncurryΞ» '(a,b) => a + b. Notation "'lets' x1 .. xn := c 'in' body" := (let x1 := c in .. (let xn := c in body) ..) (at level 200, x1 binder, xn binder, right associativity). Check lets a b c := 0 in a + b + c. (* Check other forms of binders, but too complex interaction with pattern-matching factorization for printing *) Check lets '(a,b) (d:=1) '(c,e) := (0,0) in a + b + c + d + e. End RecursivePatternsInMatch. rocq-9.2.0/test-suite/output/Notations5.out000066400000000000000000000211041516144147600207370ustar00rootroot00000000000000p 0 0 true : 0 = 0 /\ true = true p 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] p 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b p 0 0 : forall b : bool, 0 = 0 /\ b = b p 0 0 : forall b : bool, 0 = 0 /\ b = b p : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b p : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b @p nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b @p : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b p 0 0 : forall b : bool, 0 = 0 /\ b = b p : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b p 0 0 true : 0 = 0 /\ true = true p 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] p 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b p 0 0 : forall b : bool, 0 = 0 /\ b = b p 0 0 : forall b : bool, 0 = 0 /\ b = b p : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b p : forall (a1 a2 : nat) (B : Type) (b : B), a1 = a2 /\ b = b @p nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b @p : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b f x true : 0 = 0 /\ true = true f x : forall b : bool, 0 = 0 /\ b = b f x : forall b : bool, 0 = 0 /\ b = b @f nat : forall a1 a2 : nat, T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b @f : forall (A : Type) (a1 a2 : A), T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b x.(f) true : 0 = 0 /\ true = true x.(f) : forall b : bool, 0 = 0 /\ b = b x.(f) : forall b : bool, 0 = 0 /\ b = b @f nat : forall a1 a2 : nat, T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b @f : forall (A : Type) (a1 a2 : A), T a1 a2 -> forall (B : Type) (b : B), a1 = a2 /\ b = b f : T 0 0 -> forall (B : Type) (b : B), 0 = 0 /\ b = b u ?A : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] u ?A : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] u : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b u : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b u nat 0 0 ?B : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] u nat 0 0 bool : forall b : bool, 0 = 0 /\ b = b u nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b u nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b u : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] @u : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b @u : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b u : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] u 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] u 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] @u nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b @u nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b u 0 0 true : 0 = 0 /\ true = true u 0 0 true : 0 = 0 /\ true = true v : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b v 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] v 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] v 0 true : 0 = 0 /\ true = true v : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b @v 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b @v 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b v 0 : forall b : bool, 0 = 0 /\ b = b = ?n@{x:=v 0 (B:=bool)} : nat where ?n : [x : forall b : bool, 0 = 0 /\ b = b |- nat] v : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b v 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] v 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] v 0 true : 0 = 0 /\ true = true v : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b @v 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b @v 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b v 0 : forall b : bool, 0 = 0 /\ b = b = ?n@{x:=v 0 (B:=bool)} : nat where ?n : [x : forall b : bool, 0 = 0 /\ b = b |- nat] ## : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] ## : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## 0 0 true : 0 = 0 /\ true = true ## 0 0 true : 0 = 0 /\ true = true ## 0 0 : forall b : bool, 0 = 0 /\ b = b ## 0 0 : forall b : bool, 0 = 0 /\ b = b = ?n@{x:=## 0 0 (B:=bool)} : nat where ?n : [x : forall b : bool, 0 = 0 /\ b = b |- nat] ## ?A : forall (a1 a2 : ?A) (B : Type) (b : B), a1 = a2 /\ b = b where ?A : [ |- Type] ## : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b ## : forall (A : Type) (a1 a2 : A) (B : Type) (b : B), a1 = a2 /\ b = b ## nat 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## nat 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## nat 0 0 : forall (B : Type) (b : B), 0 = 0 /\ b = b ## nat 0 0 ?B : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## nat 0 0 ?B : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## nat 0 0 bool : forall b : bool, 0 = 0 /\ b = b ## nat 0 0 bool true : 0 = 0 /\ true = true ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## 0 0 : forall b : bool, 0 = 0 /\ b = b ## 0 0 : forall b : bool, 0 = 0 /\ b = b = ?n@{x:=## 0 0 (B:=bool)} : nat where ?n : [x : forall b : bool, 0 = 0 /\ b = b |- nat] ## 0 0 true : 0 = 0 /\ true = true ## 0 0 true : 0 = 0 /\ true = true ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 : forall (a2 : nat) (B : Type) (b : B), 0 = a2 /\ b = b ## 0 0 : forall b : ?B, 0 = 0 /\ b = b where ?B : [ |- Type] ## 0 0 : forall b : bool, 0 = 0 /\ b = b ## 0 0 : forall b : bool, 0 = 0 /\ b = b = ?n@{x:=## 0 0 (B:=bool)} : nat where ?n : [x : forall b : bool, 0 = 0 /\ b = b |- nat] ## 0 0 true : 0 = 0 /\ true = true ## 0 0 true : 0 = 0 /\ true = true # 0 0 bool 0%bool : T fun a : T => match a with | # 0 0 _ _ => 1 | _ => 2 end : T -> nat #' 0 0 0%bool : T fun a : T => match a with | #' 0 0 _ => 1 | _ => 2 end : T -> nat ## 0 0 0%bool : T fun a : T => match a with | ## 0 0 _ => 1 | _ => 2 end : T -> nat ##' 0 0 0%bool : T fun a : T => match a with | ##' 0 0 _ => 1 | _ => 2 end : T -> nat P 0 0 bool 0%bool : T fun a : T => match a with | P 0 0 _ _ => 1 | _ => 2 end : T -> nat P' 0 0 0%bool : T fun a : T => match a with | P' 0 0 _ => 1 | _ => 2 end : T -> nat Q 0 0 0%bool : T fun a : T => match a with | Q 0 0 _ => 1 | _ => 2 end : T -> nat Q' 0 0 0%bool : T fun a : T => match a with | Q' 0 0 _ => 1 | _ => 2 end : T -> nat Nat.add 0 0 : nat File "./output/Notations5.v", line 415, characters 13-14: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "Type". File "./output/Notations5.v", line 418, characters 13-18: The command has indeed failed with message: Unknown interpretation for notation "_ + _". This notation is currently disabled in nat_scope and type_scope. Some 0 : option nat File "./output/Notations5.v", line 425, characters 13-14: The command has indeed failed with message: The reference f was not found in the current environment. 0 + 0 : nat 0 + 0 : nat Nat.add 0 0 : nat File "./output/Notations5.v", line 438, characters 13-18: The command has indeed failed with message: Unknown interpretation for notation "_ + _". This notation is currently disabled in nat_scope and type_scope. rocq-9.2.0/test-suite/output/Notations5.v000066400000000000000000000204471516144147600204060ustar00rootroot00000000000000Module AppliedTermsPrinting. (* Test different printing paths for applied terms *) Module InferredGivenImplicit. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Check p 0 0 true. (* p 0 0 true *) Check p 0 0. (* p 0 0 *) Check p 0. (* p 0 *) Check @p _ 0 0 bool. (* p 0 0 (B:=bool) *) Check p 0 0 (B:=bool). (* p 0 0 (B:=bool) *) Check @p nat. (* p (A:=nat) *) Check p (A:=nat). (* p (A:=nat) *) Check @p _ 0 0. (* @p nat 0 0 *) Check @p. (* @p *) Unset Printing Implicit Defensive. Check @p _ 0 0 bool. (* p 0 0 *) Check @p nat. (* p *) Set Printing Implicit Defensive. End InferredGivenImplicit. Module ManuallyGivenImplicit. Axiom p : forall {A} (a1 a2:A) {B} (b:B), a1 = a2 /\ b = b. Check p 0 0 true. (* p 0 0 true *) Check p 0 0. (* p 0 0 *) Check p 0. (* p 0 *) Check @p _ 0 0 bool. (* p 0 0 *) Check p 0 0 (B:=bool). (* p 0 0 *) Check @p nat. (* p *) Check p (A:=nat). (* p *) Check @p _ 0 0. (* @p nat 0 0 *) Check @p. (* @p *) End ManuallyGivenImplicit. Module ProjectionWithImplicits. Set Implicit Arguments. Set Maximal Implicit Insertion. Record T {A} (a1 a2:A) := { f : forall B (b:B), a1 = a2 /\ b = b }. Parameter x : T 0 0. Check f x true. (* f x true *) Check @f _ _ _ x bool. (* f x (B:=bool) *) Check f x (B:=bool). (* f x (B:=bool) *) Check @f nat. (* @f nat *) Check @f _ 0 0. (* f (a1:=0) (a2:=0) *) Check f (a1:=0) (a2:=0). (* f (a1:=0) (a2:=0) *) Check @f. (* @f *) Unset Printing Implicit Defensive. Check f (a1:=0) (a2:=0). (* f *) Set Printing Implicit Defensive. Set Printing Projections. Check x.(f) true. (* x.(f) true *) Check x.(@f _ _ _) bool. (* x.(f) (B:=bool) *) Check x.(f) (B:=bool). (* x.(f) (B:=bool) *) Check @f nat. (* @f nat *) Check @f _ 0 0. (* f (a1:=0) (a2:=0) *) Check f (a1:=0) (a2:=0). (* f (a1:=0) (a2:=0) *) Check @f. (* @f *) Unset Printing Implicit Defensive. Check f (a1:=0) (a2:=0). (* f *) End ProjectionWithImplicits. Module AtAbbreviationForApplicationHead. Axiom p : forall {A} (a1 a2:A) {B} (b:B), a1 = a2 /\ b = b. Abbreviation u := @p. Check u _. (* u ?A *) Check p. (* u ?A *) Check @p. (* u *) Check u. (* u *) Check p 0 0. (* u nat 0 0 ?B *) Check u nat 0 0 bool. (* u nat 0 0 bool *) Check u nat 0 0. (* u nat 0 0 *) Check @p nat 0 0. (* u nat 0 0 *) End AtAbbreviationForApplicationHead. Module AbbreviationForApplicationHead. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Abbreviation u := p. Check p. (* u *) Check @p. (* @u *) Check @u. (* @u *) Check u. (* u *) Check p 0 0. (* u 0 0 *) Check u 0 0. (* u 0 0 *) Check @p nat 0 0. (* @u nat 0 0 *) Check @u nat 0 0. (* @u nat 0 0 *) Check p 0 0 true. (* u 0 0 true *) Check u 0 0 true. (* u 0 0 true *) End AbbreviationForApplicationHead. Module AtAbbreviationForPartialApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Abbreviation v := (@p _ 0). Check v. (* v *) Check p 0 0. (* v 0 *) Check v 0. (* v 0 *) Check v 0 true. (* v 0 true *) Check @p nat 0. (* v *) Check @p nat 0 0. (* @v 0 *) Check @v 0. (* @v 0 *) Check @p nat 0 0 bool. (* v 0 *) Eval simpl in (fun x => _:nat) (@p nat 0 0 bool). (* ?n@{x:=v 0 (B:=bool)} *) End AtAbbreviationForPartialApplication. Module AbbreviationForPartialApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Abbreviation v := (p 0). Check v. (* v *) Check p 0 0. (* v 0 *) Check v 0. (* v 0 *) Check v 0 true. (* v 0 true *) Check @p nat 0. (* v *) Check @p nat 0 0. (* @v 0 *) Check @v 0. (* @v 0 *) Check @p nat 0 0 bool. (* v 0 *) Eval simpl in (fun x => _:nat) (@p nat 0 0 bool). (* ?n@{x:=v 0 (B:=bool)} *) End AbbreviationForPartialApplication. Module NotationForHeadApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Notation "##" := p (at level 0). Check p. (* ## *) Check ##. (* ## *) Check p 0. (* ## 0 *) Check ## 0. (* ## 0 *) Check p 0 0. (* ## 0 0 *) Check ## 0 0. (* ## 0 0 *) Check p 0 0 true. (* ## 0 0 true *) Check ## 0 0 true. (* ## 0 0 true *) Check p 0 0 (B:=bool). (* ## 0 0 *) Check ## 0 0 (B:=bool). (* ## 0 0 *) Eval simpl in (fun x => _:nat) (@p nat 0 0 bool). (* ?n@{x:=## 0 0 (B:=bool)} *) End NotationForHeadApplication. Module AtNotationForHeadApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Notation "##" := @p (at level 0). Check p. (* ## ?A *) Check @p. (* ## *) Check ##. (* ## *) Check p 0. (* ## nat 0 *) Check ## nat 0. (* ## nat 0 *) Check ## nat 0 0. (* ## nat 0 0 *) Check p 0 0. (* ## nat 0 0 ?B *) Check ## nat 0 0 _. (* ## nat 0 0 ?B *) Check ## nat 0 0 bool. (* ## nat 0 0 bool *) Check ## nat 0 0 bool true. (* ## nat 0 0 bool true *) End AtNotationForHeadApplication. Module NotationForPartialApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Notation "## q" := (p q) (at level 2, q at level 0). Check p 0. (* ## 0 *) Check ## 0. (* ## 0 *) Check ## 0 0. (* ## 0 0 *) Check p 0 0 (B:=bool). (* ## 0 0 *) Check ## 0 0 (B:=bool). (* ## 0 0 *) Eval simpl in (fun x => _:nat) (## 0 0 (B:=bool)). (* ?n@{## 0 0 (B:=bool)} *) Check p 0 0 true. (* ## 0 0 true *) Check ## 0 0 true. (* ## 0 0 true *) End NotationForPartialApplication. Module AtNotationForPartialApplication. Set Implicit Arguments. Set Maximal Implicit Insertion. Axiom p : forall A (a1 a2:A) B (b:B), a1 = a2 /\ b = b. Notation "## q" := (@p _ q) (at level 2, q at level 0). Check p 0. (* ## 0 *) Check ## 0. (* ## 0 *) Check ## 0 0. (* ## 0 0 *) Check p 0 0 (B:=bool). (* ## 0 0 *) Check ## 0 0 (B:=bool). (* ## 0 0 *) Eval simpl in (fun x => _:nat) (## 0 0 (B:=bool)). (* ?n@{## 0 0 (B:=bool)} *) Check p 0 0 true. (* ## 0 0 true *) Check ## 0 0 true. (* ## 0 0 true *) End AtNotationForPartialApplication. End AppliedTermsPrinting. Module AppliedPatternsPrinting. (* Other tests testing inheritance of scope and implicit in term and pattern for parsing and printing *) Inductive T := p (a:nat) (b:bool) {B} (b:B) : T. Notation "0" := true : bool_scope. Module A. Notation "#" := @p (at level 0). Check # 0 0 _ true. Check fun a => match a with # 0 0 _ _ => 1 | _ => 2 end. (* !! *) End A. Module B. Notation "#'" := p (at level 0). Check #' 0 0 true. Check fun a => match a with #' 0 0 _ => 1 | _ => 2 end. End B. Module C. Notation "## q" := (@p q) (at level 2, q at level 0). Check ## 0 0 true. Check fun a => match a with ## 0 0 _ => 1 | _ => 2 end. End C. Module D. Notation "##' q" := (p q) (at level 2, q at level 0). Check ##' 0 0 true. Check fun a => match a with ##' 0 0 _ => 1 | _ => 2 end. End D. Module E. Abbreviation P := @ p. Check P 0 0 _ true. Check fun a => match a with P 0 0 _ _ => 1 | _ => 2 end. End E. Module F. Abbreviation P' := p. Check P' 0 0 true. Check fun a => match a with P' 0 0 _ => 1 | _ => 2 end. End F. Module G. Abbreviation Q q := (@p q). Check Q 0 0 true. Check fun a => match a with Q 0 0 _ => 1 | _ => 2 end. End G. Module H. Abbreviation Q' q := (p q). Check Q' 0 0 true. Check fun a => match a with Q' 0 0 _ => 1 | _ => 2 end. End H. End AppliedPatternsPrinting. Module Activation0. Module Activation. Disable Notation "_ + _" : nat_scope. Check Nat.add 0 0. Fail Check 0 + 0. Disable Notation "_ + _" : type_scope. Fail Check 0 + 0. Abbreviation f x := (Some x). Disable Notation f. Check Some 0. Fail Check f 0. End Activation. End Activation0. Module Activation1. Import Activation0. Check Nat.add 0 0. Check 0 + 0. Import Activation. Check Nat.add 0 0. Fail Check 0 + 0. End Activation1. rocq-9.2.0/test-suite/output/NotationsCoercions.out000066400000000000000000000002371516144147600225230ustar00rootroot00000000000000b = a : Prop foo : (_ BitVec 32) #[ r ] 0 : nat ##[ r ] : nat ##[ r ] : nat #[ r ] 0 : nat ##[ r ] : nat ##[ r ] : nat rocq-9.2.0/test-suite/output/NotationsCoercions.v000066400000000000000000000026471516144147600221700ustar00rootroot00000000000000(* Tests about skipping a coercion vs using a notation involving a coercion *) (* Skipping a coercion vs using a notation for the coercion itself (regression #11053 in 8.10 after PR #8890, addressed by PR #11090) *) Module B. Section Test. Variables (A B : Type) (a : A) (b : B). Variable c : A -> B. Coercion c : A >-> B. Abbreviation COERCION := (c). Check b = a. (* printed the same except in 8.10 *) End Test. End B. Module C. Record word := { rep: Type }. Coercion rep : word >-> Sortclass. Axiom myword: word. Axiom foo: myword. Notation "'(_' 'BitVec' '32)'" := (rep myword). Check foo. (* printed with Bitvec from #8890 in 8.10 and 8.11, regression due to #11172 in 8.12 *) End C. (* Examples involving coercions to funclass *) Module D. Record R := { f :> nat -> nat }. Axiom r : R. Notation "#[ x ]" := (f x). Check #[ r ] 0. (* printed the same from 8.10 (due to #8890), but not 8.11 and 8.12 (due to #11090) *) Notation "##[ x ]" := (f x 0). Check ##[ r ]. (* printed the same from 8.10 *) Check #[ r ] 0. (* printed ##[ r ] from 8.10 *) End D. (* Same examples with a parameter *) Module E. Record R A := { f :> A -> A }. Axiom r : R nat. Notation "#[ x ]" := (f nat x). Check #[ r ] 0. (* printed the same from 8.10 (due to #8890), but not 8.11 and 8.12 (due to #11090) *) Notation "##[ x ]" := (f nat x 0). Check ##[ r ]. (* printed the same from 8.10 *) Check #[ r ] 0. (* printed ##[ r ] from 8.10 *) End E. rocq-9.2.0/test-suite/output/NotationsScope.out000066400000000000000000000001051516144147600216420ustar00rootroot00000000000000f1 (f1 T T) T : t f2 (f2 T T) T : t f2 (f1 T T) T : t rocq-9.2.0/test-suite/output/NotationsScope.v000066400000000000000000000006061516144147600213060ustar00rootroot00000000000000(* Check notations scopes for terms % and %_ *) Declare Scope A_scope. Declare Scope B_scope. Delimit Scope B_scope with B. Variant t := T. Definition f1 (x y : t) := x. Definition f2 (x y : t) := y. Notation "x * y" := (f1 x y) : A_scope. Notation "x * y" := (f2 x y) : B_scope. Set Printing All. Local Open Scope A_scope. Check T * T * T. Check (T * T * T)%B. Check (T * T * T)%_B. rocq-9.2.0/test-suite/output/NotationsSigma.out000066400000000000000000000014341516144147600216370ustar00rootroot00000000000000{0 = 0} + {0 < 1} : Set (0 = 0) + {0 < 1} : Set {x : nat | x = 1} : Set {x : nat | x = 1 & 0 < x} : Set {x : nat | x = 1} : Set {x : nat | x = 1 & 0 < x} : Set {x : nat & x = 1} : Set {x : nat & x = 1 & 0 < x} : Set {x : nat & x = 1} : Set {x : nat & x = 1 & 0 < x} : Set {'(x, _) : nat * ?T | x = 1} : Type where ?T : [pat : nat * ?T |- Type] (pat cannot be used) {'(x, y) : nat * nat | x = 1 & y = 0} : Set {'(x, _) : nat * nat | x = 1} : Set {'(x, y) : nat * nat | x = 1 & y = 0} : Set {'(x, _) : nat * ?T & x = 1} : Type where ?T : [pat : nat * ?T |- Type] (pat cannot be used) {'(x, y) : nat * nat & x = 1 & y = 0} : Set {'(x, _) : nat * nat & x = 1} : Set {'(x, y) : nat * nat & x = 1 & y = 0} : Set rocq-9.2.0/test-suite/output/NotationsSigma.v000066400000000000000000000011311516144147600212670ustar00rootroot00000000000000(* Check notations for sigma types *) Check { 0 = 0 } + { 0 < 1 }. Check (0 = 0) + { 0 < 1 }. Check { x | x = 1 }. Check { x | x = 1 & 0 < x }. Check { x : nat | x = 1 }. Check { x : nat | x = 1 & 0 < x }. Check { x & x = 1 }. Check { x & x = 1 & 0 < x }. Check { x : nat & x = 1 }. Check { x : nat & x = 1 & 0 < x }. Check {'(x,y) | x = 1 }. Check {'(x,y) | x = 1 & y = 0 }. Check {'(x,y) : nat * nat | x = 1 }. Check {'(x,y) : nat * nat | x = 1 & y = 0 }. Check {'(x,y) & x = 1 }. Check {'(x,y) & x = 1 & y = 0 }. Check {'(x,y) : nat * nat & x = 1 }. Check {'(x,y) : nat * nat & x = 1 & y = 0 }. rocq-9.2.0/test-suite/output/NumberNotations.out000066400000000000000000000363171516144147600220370ustar00rootroot00000000000000File "./output/NumberNotations.v", line 11, characters 13-14: The command has indeed failed with message: Unexpected term (nat -> nat) while parsing a number notation. File "./output/NumberNotations.v", line 21, characters 13-14: The command has indeed failed with message: Unexpected non-option term opaque4 while parsing a number notation. File "./output/NumberNotations.v", line 32, characters 13-14: The command has indeed failed with message: Unexpected term (fun (A : Type) (x : A) => x) while parsing a number notation. let v := 0%ppp in v : punit : punit let v := 0%ppp in v : punit : punit let v := 0%ppp in v : punit : punit let v := 0%ppp in v : punit : punit let v := 0%uto in v : unit : unit File "./output/NumberNotations.v", line 72, characters 13-14: The command has indeed failed with message: Cannot interpret this number as a value of type unit File "./output/NumberNotations.v", line 73, characters 14-16: The command has indeed failed with message: Cannot interpret this number as a value of type unit let v := 0%upp in v : unit : unit let v := 0%upp in v : unit : unit let v := 0%upp in v : unit : unit let v := 0%ppps in v : punit : punit File "./output/NumberNotations.v", line 91, characters 2-46: Warning: To avoid stack overflow, large numbers in punit are interpreted as applications of pto_punits. [abstract-large-number,numbers,default] File "./output/NumberNotations.v", line 91, characters 32-33: The command has indeed failed with message: In environment v := pto_punits (Number.UIntDecimal (Decimal.D1 Decimal.Nil)) : punit The term "v" has type "punit@{Set}" while it is expected to have type "punit@{u}" (universe inconsistency: Cannot enforce Set = u). S : nat -> nat S (ack 4 4) : nat let v := 0%wnat in v : wnat : wnat 0%wnat : wnat {| unwrap := ack 4 4 |} : wnat {| Test6.unwrap := 0 |} : Test6.wnat let v := 0%wnat in v : Test6.wnat : Test6.wnat let v := 0%wuint in v : wuint : wuint let v := 1%wuint in v : wuint : wuint let v := 0%wuint8 in v : wuint : wuint let v := 0 in v : nat : nat File "./output/NumberNotations.v", line 164, characters 34-35: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "wuint". = {| unwrap := Number.UIntDecimal (Decimal.D0 Decimal.Nil) |} : wuint let v := 0%wuint8' in v : wuint : wuint let v := 0%wuint9 in v : wuint : wuint let v := 0%wuint9' in v : wuint : wuint let v := 0 in v : nat : nat File "./output/NumberNotations.v", line 191, characters 34-35: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "wuint". File "./output/NumberNotations.v", line 203, characters 2-71: Warning: The 'abstract after' directive has no effect when the parsing function (of_uint) targets an option type. [abstract-large-number-no-op,numbers,default] File "./output/NumberNotations.v", line 206, characters 2-77: The command has indeed failed with message: The 'abstract after' directive has no effect when the parsing function (of_uint) targets an option type. [abstract-large-number-no-op,numbers,default] let v := of_uint (Number.UIntDecimal (Decimal.D1 Decimal.Nil)) in v : unit : unit let v := 0%test13 in v : unit : unit File "./output/NumberNotations.v", line 238, characters 36-44: The command has indeed failed with message: to_uint' is bound to a notation that does not denote a reference. File "./output/NumberNotations.v", line 239, characters 35-36: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". File "./output/NumberNotations.v", line 240, characters 36-45: The command has indeed failed with message: to_uint'' is bound to a notation that does not denote a reference. File "./output/NumberNotations.v", line 241, characters 36-37: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". let v := 0%test14' in v : unit : unit let v := 0%test14' in v : unit : unit File "./output/NumberNotations.v", line 264, characters 34-35: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". File "./output/NumberNotations.v", line 265, characters 35-36: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". File "./output/NumberNotations.v", line 267, characters 34-35: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". let v := 0%test14' in v : unit : unit File "./output/NumberNotations.v", line 273, characters 4-71: The command has indeed failed with message: This command does not support the Global option in sections. let v := 0%test14'' in v : unit : unit File "./output/NumberNotations.v", line 275, characters 39-40: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". File "./output/NumberNotations.v", line 277, characters 36-37: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". File "./output/NumberNotations.v", line 278, characters 37-38: The command has indeed failed with message: In environment v := 0 : nat The term "v" has type "nat" while it is expected to have type "unit". let v := 0%test15 in v : unit : unit let v := 0%test15 in v : unit : unit let v := 0%test15 in v : unit : unit let v := foo a.t in v : Foo : Foo File "./output/NumberNotations.v", line 320, characters 22-23: The command has indeed failed with message: Cannot interpret in test16_scope because NumberNotations.Test16.F.Foo could not be found in the current environment. let v := 0%test17 in v : myint63 : myint63 let v := 0%Q in v : Q : Q let v := 1%Q in v : Q : Q let v := 2%Q in v : Q : Q let v := 3%Q in v : Q : Q let v := 4%Q in v : Q : Q = (0, 1) : nat * nat = (1, 1) : nat * nat = (2, 1) : nat * nat = (3, 1) : nat * nat = (4, 1) : nat * nat let v := (-1)%Zlike in v : Zlike : Zlike let v := 0%Zlike in v : Zlike : Zlike let v := 1%Zlike in v : Zlike : Zlike let v := 2%Zlike in v : Zlike : Zlike let v := 3%Zlike in v : Zlike : Zlike let v := 4%Zlike in v : Zlike : Zlike 2%Zlike : Zlike 0%Zlike : Zlike let v := 0%kt in v : ty : ty let v := 1%kt in v : ty : ty let v := 2%kt in v : ty : ty let v := 3%kt in v : ty : ty let v := 4%kt in v : ty : ty let v := 5%kt in v : ty : ty File "./output/NumberNotations.v", line 463, characters 22-23: The command has indeed failed with message: Cannot interpret this number as a value of type ty = 0%kt : ty = 1%kt : ty = 2%kt : ty = 3%kt : ty = 4%kt : ty = 5%kt : ty let v : ty := Build_ty Empty_set zero in v : ty : ty let v : ty := Build_ty unit one in v : ty : ty let v : ty := Build_ty bool two in v : ty : ty let v : ty := Build_ty Prop prop in v : ty : ty let v : ty := Build_ty Set set in v : ty : ty let v : ty := Build_ty Type type in v : ty : ty 1 : nat 1000 : nat 0 : Prop +0 : bool -0 : bool 00 : nat * nat 1000 : Prop 1_000 : list nat 0 : Set 1 : Set 2 : Set 3 : Set Empty_set : Set unit : Set sum unit unit : Set sum unit (sum unit unit) : Set File "./output/NumberNotations.v", line 558, characters 0-112: The command has indeed failed with message: Missing mapping for constructor Isum. File "./output/NumberNotations.v", line 564, characters 68-73: The command has indeed failed with message: Iunit was already mapped to unit and cannot be remapped to unit. File "./output/NumberNotations.v", line 568, characters 47-50: The command has indeed failed with message: add is not an inductive type. File "./output/NumberNotations.v", line 574, characters 40-43: The command has indeed failed with message: add is not a constructor of an inductive type. File "./output/NumberNotations.v", line 578, characters 0-103: The command has indeed failed with message: Missing mapping for constructor Iempty. File "./output/NumberNotations.v", line 592, characters 56-61: Warning: Type of I'sum seems incompatible with the type of sum. Expected type is: (I' -> I' -> I') instead of (I -> I' -> I'). This might yield ill typed terms when using the notation. [via-type-mismatch,numbers,default] File "./output/NumberNotations.v", line 597, characters 32-33: Warning: I was already mapped to Set, mapping it also to nat might yield ill typed terms when using the notation. [via-type-remapping,numbers,default] File "./output/NumberNotations.v", line 597, characters 37-42: Warning: Type of Iunit seems incompatible with the type of O. Expected type is: I instead of I. This might yield ill typed terms when using the notation. [via-type-mismatch,numbers,default] File "./output/NumberNotations.v", line 601, characters 0-146: The command has indeed failed with message: 'via' and 'abstract' cannot be used together. File "./output/NumberNotations.v", line 680, characters 21-23: Warning: Type of I1 seems incompatible with the type of Fin.F1. Expected type is: (nat -> I) instead of I. This might yield ill typed terms when using the notation. [via-type-mismatch,numbers,default] File "./output/NumberNotations.v", line 680, characters 35-37: Warning: Type of IS seems incompatible with the type of Fin.FS. Expected type is: (nat -> I -> I) instead of (I -> I). This might yield ill typed terms when using the notation. [via-type-mismatch,numbers,default] File "./output/NumberNotations.v", line 683, characters 11-12: The command has indeed failed with message: The term "0" has type "forall n : nat, Fin.t (S n)" while it is expected to have type "nat". 0 : Fin.t (S ?n) where ?n : [ |- nat] 1 : Fin.t (S (S ?n)) where ?n : [ |- nat] 2 : Fin.t (S (S (S ?n))) where ?n : [ |- nat] 3 : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat] 0 : Fin.t 3 : Fin.t 3 1 : Fin.t 3 : Fin.t 3 2 : Fin.t 3 : Fin.t 3 File "./output/NumberNotations.v", line 696, characters 11-42: The command has indeed failed with message: The term "3" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t 3". @Fin.F1 ?n : Fin.t (S ?n) where ?n : [ |- nat] @Fin.FS (S ?n) (@Fin.F1 ?n) : Fin.t (S (S ?n)) where ?n : [ |- nat] @Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)) : Fin.t (S (S (S ?n))) where ?n : [ |- nat] @Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))) : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat] @Fin.F1 (S (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) File "./output/NumberNotations.v", line 705, characters 11-12: The command has indeed failed with message: The term "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t (S (S (S O)))". 0 : list unit 1 : list unit 2 : list unit 2 : list unit 0 :: 0 :: nil : list nat 0 : Ip nat bool 1 : Ip nat bool 2 : Ip nat bool 3 : Ip nat bool 1 : Ip nat bool 1 : Ip nat bool 1 : Ip nat bool 1 : Ip nat bool Ip0 nat nat 1 : Ip nat nat Ip0 bool bool 1 : Ip bool bool Ip1 nat nat 1 : Ip nat nat Ip3 1 nat nat : Ip nat nat Ip0 nat bool O : Ip nat bool Ip1 bool nat (S O) : Ip nat bool Ip2 nat (S (S O)) bool : Ip nat bool Ip3 (S (S (S O))) nat bool : Ip nat bool 0 : 0 = 0 eq_refl : 1 = 1 0 : 0 = 0 eq_refl : id 0 = id 0 eq_refl : 1 = 1 0 : 0 = 0 eq_refl : id 0 = id 0 2 : extra_list_unit cons O unit tt (cons O unit tt (nil O unit)) : extra_list unit 0 : Set 1 : Set 2 : Set 3 : Set Empty_set : Set unit : Set sum unit unit : Set sum unit (sum unit unit) : Set 0 : Fin.t (S ?n) where ?n : [ |- nat] 1 : Fin.t (S (S ?n)) where ?n : [ |- nat] 2 : Fin.t (S (S (S ?n))) where ?n : [ |- nat] 3 : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat] 0 : Fin.t 3 : Fin.t 3 1 : Fin.t 3 : Fin.t 3 2 : Fin.t 3 : Fin.t 3 File "./output/NumberNotations.v", line 933, characters 11-42: The command has indeed failed with message: The term "3" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t 3". @Fin.F1 ?n : Fin.t (S ?n) where ?n : [ |- nat] @Fin.FS (S ?n) (@Fin.F1 ?n) : Fin.t (S (S ?n)) where ?n : [ |- nat] @Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)) : Fin.t (S (S (S ?n))) where ?n : [ |- nat] @Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))) : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat] @Fin.F1 (S (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) File "./output/NumberNotations.v", line 942, characters 11-12: The command has indeed failed with message: The term "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t (S (S (S O)))". 0 : Fin.t (S ?n) where ?n : [ |- nat : Set] 1 : Fin.t (S (S ?n)) where ?n : [ |- nat : Set] 2 : Fin.t (S (S (S ?n))) where ?n : [ |- nat : Set] 3 : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat : Set] 0 : Fin.t 3 : Fin.t 3 1 : Fin.t 3 : Fin.t 3 2 : Fin.t 3 : Fin.t 3 File "./output/NumberNotations.v", line 987, characters 11-42: The command has indeed failed with message: The term "3" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t 3". @Fin.F1 ?n : Fin.t (S ?n) where ?n : [ |- nat : Set] @Fin.FS (S ?n) (@Fin.F1 ?n) : Fin.t (S (S ?n)) where ?n : [ |- nat : Set] @Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)) : Fin.t (S (S (S ?n))) where ?n : [ |- nat : Set] @Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))) : Fin.t (S (S (S (S ?n)))) where ?n : [ |- nat : Set] @Fin.F1 (S (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) @Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O))) : Fin.t (S (S (S O))) File "./output/NumberNotations.v", line 996, characters 11-12: The command has indeed failed with message: The term "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))" has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type "Fin.t (S (S (S O)))". 0%float : float 1%float : float infinity : float neg_infinity : float nan : float 2 : nunit2 2 : nunit2 NUnit 3 : nunit 3 NUnit 0 : nunit 0 NUnit (1 + 1) : nunit (1 + 1) rocq-9.2.0/test-suite/output/NumberNotations.v000066400000000000000000000747361516144147600215040ustar00rootroot00000000000000(* Test that we fail, rather than raising anomalies, on opaque terms during interpretation *) Declare Scope opaque_scope. (* https://github.com/rocq-prover/rocq/pull/8064#discussion_r202497516 *) Module Test1. Axiom hold : forall {A B C}, A -> B -> C. Definition opaque3 (x : Number.int) : Number.int := hold x (fix f (x : nat) : nat := match x with O => O | S n => S (f n) end). Number Notation Number.int opaque3 opaque3 : opaque_scope. Delimit Scope opaque_scope with opaque. Fail Check 1%opaque. End Test1. (* https://github.com/rocq-prover/rocq/pull/8064#discussion_r202497990 *) Module Test2. Axiom opaque4 : option Number.int. Definition opaque6 (x : Number.int) : option Number.int := opaque4. Number Notation Number.int opaque6 opaque6 : opaque_scope. Delimit Scope opaque_scope with opaque. Open Scope opaque_scope. Fail Check 1%opaque. End Test2. Declare Scope silly_scope. Module Test3. Inductive silly := SILLY (v : Number.uint) (f : forall A, A -> A). Definition to_silly (v : Number.uint) := SILLY v (fun _ x => x). Definition of_silly (v : silly) := match v with SILLY v _ => v end. Number Notation silly to_silly of_silly : silly_scope. Delimit Scope silly_scope with silly. Fail Check 1%silly. End Test3. Module Test4. Declare Scope opaque_scope. Declare Scope silly_scope. Declare Scope pto. Declare Scope ppo. Declare Scope ptp. Declare Scope ppp. Declare Scope uto. Declare Scope upo. Declare Scope utp. Declare Scope upp. Declare Scope ppps. Polymorphic NonCumulative Inductive punit := ptt. Polymorphic Definition pto_punit (v : Number.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end. Polymorphic Definition pto_punit_all (v : Number.uint) : punit := ptt. Polymorphic Definition pof_punit (v : punit) : Number.uint := Nat.to_num_uint 0. Definition to_punit (v : Number.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end. Definition of_punit (v : punit) : Number.uint := Nat.to_num_uint 0. Polymorphic Definition pto_unit (v : Number.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end. Polymorphic Definition pof_unit (v : unit) : Number.uint := Nat.to_num_uint 0. Definition to_unit (v : Number.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end. Definition of_unit (v : unit) : Number.uint := Nat.to_num_uint 0. Number Notation punit to_punit of_punit : pto. Number Notation punit pto_punit of_punit : ppo. Number Notation punit to_punit pof_punit : ptp. Number Notation punit pto_punit pof_punit : ppp. Number Notation unit to_unit of_unit : uto. Delimit Scope pto with pto. Delimit Scope ppo with ppo. Delimit Scope ptp with ptp. Delimit Scope ppp with ppp. Delimit Scope uto with uto. Check let v := 0%pto in v : punit. Check let v := 0%ppo in v : punit. Check let v := 0%ptp in v : punit. Check let v := 0%ppp in v : punit. Check let v := 0%uto in v : unit. Fail Check 1%uto. Fail Check (-1)%uto. Number Notation unit pto_unit of_unit : upo. Number Notation unit to_unit pof_unit : utp. Number Notation unit pto_unit pof_unit : upp. Delimit Scope upo with upo. Delimit Scope utp with utp. Delimit Scope upp with upp. Check let v := 0%upo in v : unit. Check let v := 0%utp in v : unit. Check let v := 0%upp in v : unit. Polymorphic Definition pto_punits := pto_punit_all@{Set}. Polymorphic Definition pof_punits := pof_punit@{Set}. Number Notation punit pto_punits pof_punits (abstract after 0) : ppps. Delimit Scope ppps with ppps. Universe u. Constraint Set < u. Check let v := 0%ppps in v : punit@{u}. (* Check that universes are refreshed *) Fail Check let v := 1%ppps in v : punit@{u}. (* Note that universes are not refreshed here *) End Test4. Module Test5. Check S. (* At one point gave Error: Anomaly "Uncaught exception Pretype_errors.PretypeError(_, _, _)." Please report at http://coq.inria.fr/bugs/. *) End Test5. Module Test6. (* Check that number notations on enormous terms don't take forever to print/parse *) (* Ackerman definition from https://stackoverflow.com/a/10303475/377022 *) Fixpoint ack (n m : nat) : nat := match n with | O => S m | S p => let fix ackn (m : nat) := match m with | O => ack p 1 | S q => ack p (ackn q) end in ackn m end. Timeout 1 Check (S (ack 4 4)). (* should be instantaneous *) Local Set Primitive Projections. Record > wnat := wrap { unwrap :> nat }. Definition to_uint (x : wnat) : Number.uint := Nat.to_num_uint x. Definition of_uint (x : Number.uint) : wnat := Nat.of_num_uint x. Module Export Scopes. Declare Scope wnat_scope. Delimit Scope wnat_scope with wnat. End Scopes. Module Export Notations. Export Scopes. Number Notation wnat of_uint to_uint (abstract after 4999) : wnat_scope. End Notations. Set Printing Coercions. Check let v := 0%wnat in v : wnat. Check wrap O. Timeout 1 Check wrap (ack 4 4). (* should be instantaneous *) End Test6. Module Test6_2. Import Test6.Scopes. Check Test6.wrap 0. Import Test6.Notations. Check let v := 0%wnat in v : Test6.wnat. End Test6_2. Module Test7. Local Set Primitive Projections. Record wuint := wrap { unwrap : Number.uint }. Declare Scope wuint_scope. Delimit Scope wuint_scope with wuint. Number Notation wuint wrap unwrap : wuint_scope. Check let v := 0%wuint in v : wuint. Check let v := 1%wuint in v : wuint. End Test7. Module Test8. Local Set Primitive Projections. Record wuint := wrap { unwrap : Number.uint }. Declare Scope wuint8_scope. Declare Scope wuint8'_scope. Delimit Scope wuint8_scope with wuint8. Delimit Scope wuint8'_scope with wuint8'. Section with_var. Context (dummy : unit). Definition wrap' := let __ := dummy in wrap. Definition unwrap' := let __ := dummy in unwrap. Number Notation wuint wrap' unwrap' : wuint8_scope. Check let v := 0%wuint8 in v : wuint. End with_var. Check let v := 0%wuint8 in v : nat. Fail Check let v := 0%wuint8 in v : wuint. Compute wrap (Nat.to_num_uint 0). Abbreviation wrap'' := wrap. Abbreviation unwrap'' := unwrap. Number Notation wuint wrap'' unwrap'' : wuint8'_scope. Check let v := 0%wuint8' in v : wuint. End Test8. Module Test9. Declare Scope wuint9_scope. Declare Scope wuint9'_scope. Delimit Scope wuint9_scope with wuint9. Delimit Scope wuint9'_scope with wuint9'. Section with_let. Local Set Primitive Projections. Record wuint := wrap { unwrap : Number.uint }. Let wrap' := wrap. Let unwrap' := unwrap. Local Abbreviation wrap'' := wrap. Local Abbreviation unwrap'' := unwrap. Number Notation wuint wrap' unwrap' : wuint9_scope. Check let v := 0%wuint9 in v : wuint. Number Notation wuint wrap'' unwrap'' : wuint9'_scope. Check let v := 0%wuint9' in v : wuint. End with_let. Check let v := 0%wuint9 in v : nat. Fail Check let v := 0%wuint9 in v : wuint. End Test9. Module Test10. (* Test that it is only a warning to add abstract after to an optional parsing function *) Definition to_uint (v : unit) := Nat.to_num_uint 0. Definition of_uint (v : Number.uint) := match Nat.of_num_uint v with O => Some tt | _ => None end. Definition of_any_uint (v : Number.uint) := tt. Declare Scope unit_scope. Declare Scope unit2_scope. Delimit Scope unit_scope with unit. Delimit Scope unit2_scope with unit2. Number Notation unit of_uint to_uint (abstract after 0) : unit_scope. Local Set Warnings "+abstract-large-number-no-op". (* Check that there is actually a warning here *) Fail Number Notation unit of_uint to_uint (abstract after 0) : unit2_scope. (* Check that there is no warning here *) Number Notation unit of_any_uint to_uint (abstract after 0) : unit2_scope. End Test10. Module Test12. (* Test for number notations on context variables *) Declare Scope test12_scope. Delimit Scope test12_scope with test12. Section test12. Context (to_uint : unit -> Number.uint) (of_uint : Number.uint -> unit). Number Notation unit of_uint to_uint : test12_scope. Check let v := 1%test12 in v : unit. End test12. End Test12. Module Test13. (* Test for number notations on notations which do not denote references *) Declare Scope test13_scope. Declare Scope test13'_scope. Declare Scope test13''_scope. Delimit Scope test13_scope with test13. Delimit Scope test13'_scope with test13'. Delimit Scope test13''_scope with test13''. Definition to_uint (x y : unit) : Number.uint := Nat.to_num_uint O. Definition of_uint (x : Number.uint) : unit := tt. Definition to_uint_good := to_uint tt. Abbreviation to_uint' := (to_uint tt). Abbreviation to_uint'' := (to_uint _). Number Notation unit of_uint to_uint_good : test13_scope. Check let v := 0%test13 in v : unit. Fail Number Notation unit of_uint to_uint' : test13'_scope. Fail Check let v := 0%test13' in v : unit. Fail Number Notation unit of_uint to_uint'' : test13''_scope. Fail Check let v := 0%test13'' in v : unit. End Test13. Module Test14. (* Test that number notations follow [Import], not [Require], and also test that [Local Number Notation]s do not escape modules nor sections. *) Declare Scope test14_scope. Declare Scope test14'_scope. Declare Scope test14''_scope. Declare Scope test14'''_scope. Delimit Scope test14_scope with test14. Delimit Scope test14'_scope with test14'. Delimit Scope test14''_scope with test14''. Delimit Scope test14'''_scope with test14'''. Module Inner. Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O. Definition of_uint (x : Number.uint) : unit := tt. Local Number Notation unit of_uint to_uint : test14_scope. Global Number Notation unit of_uint to_uint : test14'_scope. Check let v := 0%test14 in v : unit. Check let v := 0%test14' in v : unit. End Inner. Fail Check let v := 0%test14 in v : unit. Fail Check let v := 0%test14' in v : unit. Import Inner. Fail Check let v := 0%test14 in v : unit. Check let v := 0%test14' in v : unit. Section InnerSection. Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O. Definition of_uint (x : Number.uint) : unit := tt. Local Number Notation unit of_uint to_uint : test14''_scope. Fail Global Number Notation unit of_uint to_uint : test14'''_scope. Check let v := 0%test14'' in v : unit. Fail Check let v := 0%test14''' in v : unit. End InnerSection. Fail Check let v := 0%test14'' in v : unit. Fail Check let v := 0%test14''' in v : unit. End Test14. Module Test15. (** Test module include *) Declare Scope test15_scope. Delimit Scope test15_scope with test15. Module Inner. Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O. Definition of_uint (x : Number.uint) : unit := tt. Number Notation unit of_uint to_uint : test15_scope. Check let v := 0%test15 in v : unit. End Inner. Module Inner2. Include Inner. Check let v := 0%test15 in v : unit. End Inner2. Import Inner Inner2. Check let v := 0%test15 in v : unit. End Test15. Module Test16. (** Test functors *) Declare Scope test16_scope. Delimit Scope test16_scope with test16. Module Type A. Axiom T : Set. Axiom t : T. End A. Module F (a : A). Inductive Foo := foo (_ : a.T). Definition to_uint (x : Foo) : Number.uint := Nat.to_num_uint O. Definition of_uint (x : Number.uint) : Foo := foo a.t. Global Number Notation Foo of_uint to_uint : test16_scope. Check let v := 0%test16 in v : Foo. End F. Module a <: A. Definition T : Set := unit. Definition t : T := tt. End a. Module Import f := F a. (** Ideally this should work, but it should definitely not anomaly *) Fail Check let v := 0%test16 in v : Foo. End Test16. Require Import PrimInt63. Module Test17. (** Test uint63 *) Declare Scope test17_scope. Declare Scope test17_scope. Delimit Scope test17_scope with test17. Local Set Primitive Projections. Record myint63 := of_int { to_int : int }. Definition parse x := match x with Pos x => Some (of_int x) | Neg _ => None end. Definition print x := Pos (to_int x). Number Notation myint63 parse print : test17_scope. Check let v := 0%test17 in v : myint63. End Test17. Module Test18. (** Test https://github.com/rocq-prover/rocq/issues/9840 *) Record Q := { num : nat ; den : nat ; reduced : Nat.gcd num den = 1 }. Declare Scope Q_scope. Delimit Scope Q_scope with Q. Definition nat_eq_dec (x y : nat) : {x = y} + {x <> y}. Proof. decide equality. Defined. Definition transparentify {A} (D : {A} + {not A}) (H : A) : A := match D with | left pf => pf | right npf => match npf H with end end. Axiom gcd_good : forall x, Nat.gcd x 1 = 1. Definition Q_of_nat (x : nat) : Q := {| num := x ; den := 1 ; reduced := transparentify (nat_eq_dec _ _) (gcd_good _) |}. Definition nat_of_Q (x : Q) : option nat := if Nat.eqb x.(den) 1 then Some (x.(num)) else None. Definition Q_of_uint (x : Number.uint) : Q := Q_of_nat (Nat.of_num_uint x). Definition uint_of_Q (x : Q) : option Number.uint := option_map Nat.to_num_uint (nat_of_Q x). Number Notation Q Q_of_uint uint_of_Q : Q_scope. Check let v := 0%Q in v : Q. Check let v := 1%Q in v : Q. Check let v := 2%Q in v : Q. Check let v := 3%Q in v : Q. Check let v := 4%Q in v : Q. Compute let v := 0%Q in (num v, den v). Compute let v := 1%Q in (num v, den v). Compute let v := 2%Q in (num v, den v). Compute let v := 3%Q in (num v, den v). Compute let v := 4%Q in (num v, den v). End Test18. Require Import Corelib.Lists.ListDef. Require Import BinNums IntDef. Module Test19. (** Test another thing related to https://github.com/rocq-prover/rocq/issues/9840 *) Record Zlike := { summands : list Z }. Declare Scope Zlike_scope. Delimit Scope Zlike_scope with Zlike. Section Fold_Right_Recursor. Variables (A : Type) (B : Type). Variable f : B -> A -> A. Variable a0 : A. Fixpoint fold_right (l:list B) : A := match l with | nil => a0 | cons b t => f b (fold_right t) end. End Fold_Right_Recursor. Definition Z_of_Zlike (x : Zlike) := fold_right _ _ Z.add Z0 (summands x). Definition Zlike_of_Z (x : Z) := {| summands := cons x nil |}. Number Notation Zlike Zlike_of_Z Z_of_Zlike : Zlike_scope. Check let v := (-1)%Zlike in v : Zlike. Check let v := 0%Zlike in v : Zlike. Check let v := 1%Zlike in v : Zlike. Check let v := 2%Zlike in v : Zlike. Check let v := 3%Zlike in v : Zlike. Check let v := 4%Zlike in v : Zlike. Check {| summands := cons (Zpos xH) (cons (Zpos (xO xH)) (cons (Zneg xH) nil)) |}. Check {| summands := nil |}. End Test19. Module Test20. (** Test Sorts *) Local Set Universe Polymorphism. Inductive known_type : Type -> Type := | prop : known_type Prop | set : known_type Set | type : known_type Type | zero : known_type Empty_set | one : known_type unit | two : known_type bool. Existing Class known_type. #[global] Existing Instances zero one two prop. #[global] Existing Instance set | 2. #[global] Existing Instance type | 4. Record > ty := { t : Type ; kt : known_type t }. Definition ty_of_uint (x : Number.uint) : option ty := match Nat.of_num_uint x with | 0 => @Some ty zero | 1 => @Some ty one | 2 => @Some ty two | 3 => @Some ty prop | 4 => @Some ty set | 5 => @Some ty type | _ => None end. Definition uint_of_ty (x : ty) : Number.uint := Nat.to_num_uint match kt x with | prop => 3 | set => 4 | type => 5 | zero => 0 | one => 1 | two => 2 end. Declare Scope kt_scope. Delimit Scope kt_scope with kt. Number Notation ty ty_of_uint uint_of_ty : kt_scope. Check let v := 0%kt in v : ty. Check let v := 1%kt in v : ty. Check let v := 2%kt in v : ty. Check let v := 3%kt in v : ty. Check let v := 4%kt in v : ty. Check let v := 5%kt in v : ty. Fail Check let v := 6%kt in v : ty. Eval cbv in (_ : known_type Empty_set) : ty. Eval cbv in (_ : known_type unit) : ty. Eval cbv in (_ : known_type bool) : ty. Eval cbv in (_ : known_type Prop) : ty. Eval cbv in (_ : known_type Set) : ty. Eval cbv in (_ : known_type Type) : ty. Local Set Printing All. Check let v := 0%kt in v : ty. Check let v := 1%kt in v : ty. Check let v := 2%kt in v : ty. Check let v := 3%kt in v : ty. Check let v := 4%kt in v : ty. Check let v := 5%kt in v : ty. End Test20. Module Test21. Check 00001. Check 1_000. End Test21. Module Test22. Notation "0" := False. Notation "+0" := true. Notation "-0" := false. Notation "00" := (0%nat, 0%nat). Check 0. Check +0. Check -0. Check 00. Notation "1000" := True. Notation "1_000" := (cons 1 nil). Check 1000. Check 1_000. (* To do: preserve parsing of -0: Require Import ZArith. Check (-0)%Z. *) End Test22. (* Test the via ... mapping ... option *) Module Test23. Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B. Inductive I := | Iempty : I | Iunit : I | Isum : I -> I -> I. Definition of_uint (x : Number.uint) : I := let fix f n := match n with | O => Iempty | S O => Iunit | S n => Isum Iunit (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with | Iempty => O | Iunit => 1 | Isum i1 i2 => f i1 + f i2 end in Nat.to_num_uint (f x). Abbreviation nSet := (Set) (only parsing). (* needed as a reference is expected in Number Notation and Set is syntactically not a reference *) Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum]) : type_scope. Local Open Scope type_scope. Check Empty_set. Check unit. Check sum unit unit. Check sum unit (sum unit unit). Set Printing All. Check 0. Check 1. Check 2. Check 3. Unset Printing All. (* Test error messages *) (* missing constructor *) Fail Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit]) : type_scope. (* duplicate constructor *) Fail Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum, unit => Iunit]) : type_scope. (* not an inductive *) Fail Number Notation nSet of_uint to_uint (via add mapping [Empty_set => Iempty, unit => Iunit, sum => Isum]) : type_scope. (* not a constructor *) Fail Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => add, sum => Isum]) : type_scope. (* put constructors of the wrong inductive ~~> missing constructors *) Fail Number Notation nSet of_uint to_uint (via I mapping [Empty_set => O, unit => S]) : type_scope. (* Test warnings *) (* wrong type *) Inductive I' := | I'empty : I' | I'unit : I' | I'sum : I -> I' -> I'. Definition of_uint' (x : Number.uint) : I' := I'empty. Definition to_uint' (x : I') : Number.uint := Number.UIntDecimal Decimal.Nil. Number Notation nSet of_uint' to_uint' (via I' mapping [Empty_set => I'empty, unit => I'unit, sum => I'sum]) : type_scope. (* wrong type mapping *) Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, O => Iunit, sum => Isum]) : type_scope. (* incompatibility with abstract (but warning is fine) *) Fail Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum], abstract after 11) : type_scope. Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum], warning after 12) : type_scope. (* Test reduction of types when building the notation *) Inductive foo := bar : match (true <: bool) with true => nat -> foo | false => True end. Definition foo_of_uint (x : Number.uint) : foo := bar (Nat.of_num_uint x). Definition foo_to_uint (x : foo) : Number.uint := match x with | bar x => Nat.to_num_uint x end. Number Notation foo foo_of_uint foo_to_uint (via foo mapping [bar => bar]) : type_scope. Inductive foo' := bar' : let n := nat in n -> foo'. Definition foo'_of_uint (x : Number.uint) : foo' := bar' (Nat.of_num_uint x). Definition foo'_to_uint (x : foo') : Number.uint := match x with | bar' x => Nat.to_num_uint x end. Number Notation foo' foo'_of_uint foo'_to_uint (via foo' mapping [bar' => bar']) : type_scope. Inductive foo'' := bar'' : (nat <: Type) -> (foo'' <: Type). Definition foo''_of_uint (x : Number.uint) : foo'' := bar'' (Nat.of_num_uint x). Definition foo''_to_uint (x : foo'') : Number.uint := match x with | bar'' x => Nat.to_num_uint x end. Number Notation foo'' foo''_of_uint foo''_to_uint (via foo'' mapping [bar'' => bar'']) : type_scope. End Test23. (* Test the via ... mapping ... option with implicit arguments *) Module Test24. Inductive I := | I1 : I | IS : I -> I. Definition of_uint (x : Number.uint) : I := let fix f n := match n with | O => I1 | S n => IS (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with | I1 => O | IS n => S (f n) end in Nat.to_num_uint (f x). Local Open Scope type_scope. Module Fin. Inductive t : nat -> Set := |F1 : forall {n}, t (S n) |FS : forall {n}, t n -> t (S n). End Fin. (* ignoring implicit arguments doesn't work *) Number Notation Fin.t of_uint to_uint (via I mapping [Fin.F1 => I1, Fin.FS => IS]) : type_scope. Fail Check 1. Number Notation Fin.t of_uint to_uint (via I mapping [[Fin.F1] => I1, [Fin.FS] => IS]) : type_scope. Check Fin.F1. Check Fin.FS Fin.F1. Check Fin.FS (Fin.FS Fin.F1). Check Fin.FS (Fin.FS (Fin.FS Fin.F1)). Check Fin.F1 : Fin.t 3. Check Fin.FS Fin.F1 : Fin.t 3. Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3. Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3. Set Printing All. Check 0. Check 1. Check 2. Check 3. Check 0 : Fin.t 3. Check 1 : Fin.t 3. Check 2 : Fin.t 3. Fail Check 3 : Fin.t 3. Unset Printing All. End Test24. (* Test number notations for parameterized inductives *) Module Test25. Definition of_uint (u : Number.uint) : list unit := let fix f n := match n with | O => nil | S n => cons tt (f n) end in f (Nat.of_num_uint u). Definition to_uint (l : list unit) : Number.uint := let fix f n := match n with | nil => O | cons tt l => S (f l) end in Nat.to_num_uint (f l). Abbreviation listunit := (list unit) (only parsing). Number Notation listunit of_uint to_uint : nat_scope. Check 0. Check 1. Check 2. Check cons tt (cons tt nil). Check cons O (cons O nil). (* printer not called on list nat *) (* inductive with multiple parameters that are not the first parameters and not in the same order for each constructor *) Inductive Ip : Type -> Type -> Type := | Ip0 : forall T T', nat -> Ip T T' | Ip1 : forall T' T, nat -> Ip T T' | Ip2 : forall T, nat -> forall T', Ip T T' | Ip3 : nat -> forall T T', Ip T T'. Definition Ip_of_uint (u : Number.uint) : option (Ip nat bool) := let f n := match n with | O => Some (Ip0 nat bool O) | S O => Some (Ip1 bool nat (S O)) | S (S O) => Some (Ip2 nat (S (S O)) bool) | S (S (S O)) => Some (Ip3 (S (S (S O))) nat bool) | _ => None end in f (Nat.of_num_uint u). Definition Ip_to_uint (l : Ip nat bool) : Number.uint := let f n := match n with | Ip0 _ _ n => n | Ip1 _ _ n => n | Ip2 _ n _ => n | Ip3 n _ _ => n end in Nat.to_num_uint (f l). Abbreviation Ip_nat_bool := (Ip nat bool) (only parsing). Number Notation Ip_nat_bool Ip_of_uint Ip_to_uint : nat_scope. Check 0. Check 1. Check 2. Check 3. Check Ip0 nat bool (S O). Check Ip1 bool nat (S O). Check Ip2 nat (S O) bool. Check Ip3 (S O) nat bool. Check Ip0 nat nat (S O). (* not printed *) Check Ip0 bool bool (S O). (* not printed *) Check Ip1 nat nat (S O). (* not printed *) Check Ip3 (S O) nat nat. (* not printed *) Set Printing All. Check 0. Check 1. Check 2. Check 3. Unset Printing All. Abbreviation eqO := (eq _ O) (only parsing). Definition eqO_of_uint (x : Number.uint) : eqO := eq_refl O. Definition eqO_to_uint (x : O = O) : Number.uint := match x with | eq_refl _ => Nat.to_num_uint O end. Number Notation eqO eqO_of_uint eqO_to_uint : nat_scope. Check 42. Check eq_refl (S O). (* doesn't match eq _ O, printer not called *) Check eq_refl O. (* matches eq _ O, printer called *) Check eq_refl (id O). (* doesn't match eq _ O, printer not called *) Abbreviation eq_ := (eq _ _) (only parsing). Number Notation eq_ eqO_of_uint eqO_to_uint : nat_scope. Check eq_refl (S O). (* matches eq _ _, printer called, but type incorrect *) Check eq_refl O. (* matches eq _ _, printer called *) Check eq_refl (id O). (* matches eq _ _, but contains a global constant, printer not called *) Inductive extra_list : Type -> Type := | nil (n : nat) (v : Type) : extra_list v | cons (n : nat) (t : Type) (x : t) : extra_list t -> extra_list t. Definition extra_list_unit_of_uint (x : Number.uint) : extra_list unit := let fix f n := match n with | O => nil O unit | S n => cons O unit tt (f n) end in f (Nat.of_num_uint x). Definition extra_list_unit_to_uint (x : extra_list unit) : Number.uint := let fix f T (x : extra_list T) := match x with | nil _ _ => O | cons _ T _ x => S (f T x) end in Nat.to_num_uint (f unit x). Abbreviation extra_list_unit := (extra_list unit). Number Notation extra_list_unit extra_list_unit_of_uint extra_list_unit_to_uint : nat_scope. Check 2. Set Printing All. Check 2. Unset Printing All. End Test25. (* Test the via ... mapping ... option with let-binders, beta-redexes, delta-redexes, etc *) Module Test26. Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B. Inductive I (dummy:=O) := | Iempty : let v := I in id v | Iunit : (fun x => x) I | Isum : let v := I in (fun A B => A -> B) (let v' := v in v') (forall x : match O with O => I | _ => Empty_set end, let dummy2 := x in I). Definition of_uint (x : (fun x => let v := I in x) Number.uint) : (fun x => let v := I in x) I := let fix f n := match n with | O => Iempty | S O => Iunit | S n => Isum Iunit (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : (fun x => let v := x in v) I) : match O with O => Number.uint | _ => Empty_set end := let fix f i := match i with | Iempty => O | Iunit => 1 | Isum i1 i2 => f i1 + f i2 end in Nat.to_num_uint (f x). Abbreviation nSet := (Set) (only parsing). (* needed as a reference is expected in Number Notation and Set is syntactically not a reference *) Number Notation nSet of_uint to_uint (via I mapping [Empty_set => Iempty, unit => Iunit, sum => Isum]) : type_scope. Local Open Scope type_scope. Check Empty_set. Check unit. Check sum unit unit. Check sum unit (sum unit unit). Set Printing All. Check 0. Check 1. Check 2. Check 3. Unset Printing All. End Test26. (* Test the via ... mapping ... option with implicit arguments with let binders, etc *) Module Test27. Module Fin. Inductive t0 (x:=O) := with t (x:=O) : forall y : nat, let z := y in Set := | F1 (y:=O) {n} : match y with O => t (S n) | _ => Empty_set end | FS (y:=x) {n} (v:=n+y) (m:=n) : id (match y with O => id (t n) | _ => Empty_set end -> (fun x => x) t (S m)) with t' (x:=O) := . End Fin. Inductive I (dummy:=O) := | I1 : I | IS : let x := I in id x -> I. Definition of_uint (x : Number.uint) : I := let fix f n := match n with | O => I1 | S n => IS (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with | I1 => O | IS n => S (f n) end in Nat.to_num_uint (f x). Local Open Scope type_scope. Number Notation Fin.t of_uint to_uint (via I mapping [[Fin.F1] => I1, [Fin.FS] => IS]) : type_scope. Check Fin.F1. Check Fin.FS Fin.F1. Check Fin.FS (Fin.FS Fin.F1). Check Fin.FS (Fin.FS (Fin.FS Fin.F1)). Check Fin.F1 : Fin.t 3. Check Fin.FS Fin.F1 : Fin.t 3. Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3. Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3. Set Printing All. Check 0. Check 1. Check 2. Check 3. Check 0 : Fin.t 3. Check 1 : Fin.t 3. Check 2 : Fin.t 3. Fail Check 3 : Fin.t 3. Unset Printing All. End Test27. Module Test28. Module Fin. Inductive t : nat -> Set := | F1 {n : (nat : Set)} : (t (S n) : Set) | FS {n : (nat : Set)} : (t n : Set) -> (t (S n) : Set). End Fin. Inductive I := | I1 : I | IS : I -> I. Definition of_uint (x : Number.uint) : I := let fix f n := match n with | O => I1 | S n => IS (f n) end in f (Nat.of_num_uint x). Definition to_uint (x : I) : Number.uint := let fix f i := match i with | I1 => O | IS n => S (f n) end in Nat.to_num_uint (f x). Local Open Scope type_scope. Number Notation Fin.t of_uint to_uint (via I mapping [[Fin.F1] => I1, [Fin.FS] => IS]) : type_scope. Check Fin.F1. Check Fin.FS Fin.F1. Check Fin.FS (Fin.FS Fin.F1). Check Fin.FS (Fin.FS (Fin.FS Fin.F1)). Check Fin.F1 : Fin.t 3. Check Fin.FS Fin.F1 : Fin.t 3. Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3. Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3. Set Printing All. Check 0. Check 1. Check 2. Check 3. Check 0 : Fin.t 3. Check 1 : Fin.t 3. Check 2 : Fin.t 3. Fail Check 3 : Fin.t 3. Unset Printing All. End Test28. Require Import PrimFloat. Module Test29. Definition printer (x : float_wrapper) : Number.uint := if get_sign (float_wrap x) then Number.UIntDecimal (Decimal.D1 Decimal.Nil) else Number.UIntDecimal (Decimal.D0 Decimal.Nil). Definition parser (x : float) : float := x. Number Notation float parser printer : float_scope. Check 12%float. Check (-12)%float. Check infinity. Check neg_infinity. Check nan. End Test29. Module Test30. Inductive nunit : nat -> Type := NUnit n : nunit n. Definition printer2 (x : nunit 2) : Number.uint := Number.UIntDecimal (Decimal.D2 Decimal.Nil). Definition parser2 (_ : Number.uint) : nunit 2 := NUnit 2. Abbreviation nunit2 := (nunit 2). Number Notation nunit2 parser2 printer2 : nat_scope. Check 2. Check NUnit (S (S O)). Check NUnit (S (S (S O))). Check NUnit O. Check NUnit (S O + S O). (* doesn't print as 2, because (S O + S O) is not syntactically equal to (S (S O)), we could want to use a convertibility test rather than a syntactic equality, but this could be more costly *) End Test30. Module Bug10878. Definition Zto_pos_opt (v : Z) : option positive := match v with | Zpos v => Some v | _ => None end. Declare Scope mypos_scope. Declare Scope mypos_scope2. Number Notation positive Zto_pos_opt Zpos : mypos_scope. (* success *) Arguments option {_}. Number Notation positive Zto_pos_opt Zpos : mypos_scope2. (* was failing *) End Bug10878. rocq-9.2.0/test-suite/output/NumberNotationsUnivPoly.out000066400000000000000000000004631516144147600235360ustar00rootroot000000000000000 : B ?a where ?a : [ |- A] 1 : B ?a where ?a : [ |- A] 2 : B ?a where ?a : [ |- A] foo@{v v'} = fun (v : A@{v}) (v' : A@{v'}) => (0 : B@{v} v, 1 : B@{v'} v') : forall (v : A@{v}) (v' : A@{v'}), B@{v} v * B@{v'} v' (* v v' |= v <= prod.u0 v' <= prod.u1 *) Arguments foo v v' rocq-9.2.0/test-suite/output/NumberNotationsUnivPoly.v000066400000000000000000000006561516144147600232000ustar00rootroot00000000000000Set Universe Polymorphism. Axiom A : Type. Inductive B : A -> Type := | x {a} : B a | y {a} : B a -> B a . Number Notation B Nat.of_num_uint Nat.to_num_uint (via nat mapping [[x] => O, [y] => S]) : nat_scope. Check 0. Check 1. Check 2. (* check it generates independent univs *) Definition foo@{v v' | v <= prod.u0, v' <= prod.u1} := fun (v:A@{v}) (v':A@{v'}) => (x : B v, y x : B v'). Set Printing Universes. Print foo. rocq-9.2.0/test-suite/output/Partac.out000066400000000000000000000005501516144147600201100ustar00rootroot00000000000000File "./output/Partac.v", line 4, characters 2-24: The command has indeed failed with message: The term "false" has type "bool" while it is expected to have type "nat". (for goal 1) File "./output/Partac.v", line 5, characters 2-20: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "bool". (for goal 2) rocq-9.2.0/test-suite/output/Partac.v000066400000000000000000000001261516144147600175450ustar00rootroot00000000000000Goal nat * bool. Proof. split. Fail par: exact false. Fail par: exact 0. Abort. rocq-9.2.0/test-suite/output/PatternsInBinders.out000066400000000000000000000025501516144147600222760ustar00rootroot00000000000000swap = fun '(x, y) => (y, x) : A * B -> B * A Arguments swap pat fun '(x, y) => (y, x) : A * B -> B * A forall '(x, y), swap (x, y) = (y, x) : Prop proj_informative = fun '(exist _ x _) => x : {x : A | P x} -> A Arguments proj_informative pat foo = fun '(Bar n b tt p) => if b then n + p else n - p : Foo -> nat Arguments foo pat baz = fun '(Bar n1 _ tt p1) '(Bar _ _ tt _) => n1 + p1 : Foo -> Foo -> nat Arguments baz pat pat swap = fun (A B : Type) '(x, y) => (y, x) : forall {A B : Type}, A * B -> B * A Arguments swap {A B}%_type_scope pat fun (A B : Type) '(x, y) => swap (x, y) = (y, x) : forall A B : Type, A * B -> Prop forall (A B : Type) '(x, y), swap (x, y) = (y, x) : Prop exists '(x, y), swap (x, y) = (y, x) : Prop exists '(x, y) '(z, w), swap (x, y) = (z, w) : Prop fun '(x, y) => (y, x) : A * B -> B * A forall '(x, y), swap (x, y) = (y, x) : Prop both_z = fun pat : nat * nat => let '(n, p) as x := pat return F x in (Z n, Z p) : forall pat : nat * nat, F pat Arguments both_z pat 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) : Prop fun (pat : nat) '(x, y) => x + y = pat : nat -> nat * nat -> Prop f = fun x : nat => x + x : nat -> nat Arguments f x%_nat_scope fun x : nat => x + x : nat -> nat rocq-9.2.0/test-suite/output/PatternsInBinders.v000066400000000000000000000033211516144147600217310ustar00rootroot00000000000000(** The purpose of this file is to test printing of the destructive patterns used in binders ([fun] and [forall]). *) Parameters (A B : Type) (P:A->Prop). Definition swap '((x,y) : A*B) := (y,x). Print swap. Check fun '((x,y) : A*B) => (y,x). Check forall '(x,y), swap (x,y) = (y,x). Definition proj_informative '(exist _ x _ : { x:A | P x }) : A := x. Print proj_informative. Inductive Foo := Bar : nat -> bool -> unit -> nat -> Foo. Definition foo '(Bar n b tt p) := if b then n+p else n-p. Print foo. Definition baz '(Bar n1 b1 tt p1) '(Bar n2 b2 tt p2) := n1+p1. Print baz. Module WithParameters. Definition swap {A B} '((x,y) : A*B) := (y,x). Print swap. Check fun (A B:Type) '((x,y) : A*B) => swap (x,y) = (y,x). Check forall (A B:Type) '((x,y) : A*B), swap (x,y) = (y,x). Check exists '((x,y):A*A), swap (x,y) = (y,x). Check exists '((x,y):A*A) '(z,w), swap (x,y) = (z,w). End WithParameters. (** Some test involving unicode notations. *) Module WithUnicode. Check fun '((x,y) : A*B) => (y,x). Check forall '(x,y), swap (x,y) = (y,x). End WithUnicode. (** * Suboptimal printing *) Module Suboptimal. (** This test shows an example which exposes the [let] introduced by the pattern notation in binders. *) Inductive Fin (n:nat) := Z : Fin n. Definition F '(n,p) : Type := (Fin n * Fin p)%type. Definition both_z '(n,p) : F (n,p) := (Z _,Z _). Print both_z. (** Test factorization of binders *) Check fun '((x,y) : A*B) '(z,t) => swap (x,y) = (z,t). Check forall '(x,y) '((z,t) : B*A), swap (x,y) = (z,t). End Suboptimal. (** Test risk of collision for internal name *) Check fun pat => fun '(x,y) => x+y = pat. (** Test name in degenerate case *) Definition f 'x := x+x. Print f. Check fun 'x => x+x. rocq-9.2.0/test-suite/output/PrimStringSyntax.out000066400000000000000000000002751516144147600222070ustar00rootroot00000000000000"hello"%pstring : string ""%pstring : string "a"%char63 : char63_wrapper "a" : char63 : char63 0%uint63 : int 0%uint63 : char63 : char63 "hello" : string rocq-9.2.0/test-suite/output/PrimStringSyntax.v000066400000000000000000000003171516144147600216420ustar00rootroot00000000000000Require Import PrimInt63 PrimString. Check "hello"%pstring. Check ""%pstring. Check "a"%char63. Check ("a"%char63 : char63). Check 0%uint63. Check (0%uint63 : char63). Open Scope pstring. Check "hello". rocq-9.2.0/test-suite/output/PrimitiveProjectionsAttribute.out000066400000000000000000000032331516144147600247530ustar00rootroot00000000000000Foo0 : Type Foo0 is not universe polymorphic Expands to: Inductive PrimitiveProjectionsAttribute.Foo0 Declared in library PrimitiveProjectionsAttribute, line 3, characters 7-11 Foo1 : Type Foo1 is not universe polymorphic Foo1 has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute.Foo1 Declared in library PrimitiveProjectionsAttribute, line 10, characters 7-11 Foo2 : Type Foo2 is not universe polymorphic Foo2 has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute.Foo2 Declared in library PrimitiveProjectionsAttribute, line 17, characters 7-11 Foo3 : Type Foo3 is not universe polymorphic Expands to: Inductive PrimitiveProjectionsAttribute.Foo3 Declared in library PrimitiveProjectionsAttribute, line 24, characters 7-11 Foo4 : Type Foo4 is not universe polymorphic Foo4 has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute.Foo4 Declared in library PrimitiveProjectionsAttribute, line 32, characters 7-11 Foo5 : Type Foo5 is not universe polymorphic Foo5 has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute.Foo5 Declared in library PrimitiveProjectionsAttribute, line 39, characters 7-11 Foo6 : Type Foo6 is not universe polymorphic Foo6 has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute.Foo6 Declared in library PrimitiveProjectionsAttribute, line 46, characters 7-11 Foo7 : Type Foo7 is not universe polymorphic Expands to: Inductive PrimitiveProjectionsAttribute.Foo7 Declared in library PrimitiveProjectionsAttribute, line 53, characters 7-11 rocq-9.2.0/test-suite/output/PrimitiveProjectionsAttribute.v000066400000000000000000000011631516144147600244110ustar00rootroot00000000000000Unset Primitive Projections. Record Foo0 := { bar0 : Type ; }. About Foo0. #[projections(primitive)] Record Foo1 := { bar1 : Type ; }. About Foo1. #[projections(primitive=yes)] Record Foo2 := { bar2 : Type ; }. About Foo2. #[projections(primitive=no)] Record Foo3 := { bar3 : Type ; }. About Foo3. Set Primitive Projections. Record Foo4 := { bar4 : Type ; }. About Foo4. #[projections(primitive)] Record Foo5 := { bar5 : Type ; }. About Foo5. #[projections(primitive=yes)] Record Foo6 := { bar6 : Type ; }. About Foo6. #[projections(primitive=no)] Record Foo7 := { bar7 : Type ; }. About Foo7. rocq-9.2.0/test-suite/output/PrimitiveProjectionsAttribute_Records.out000066400000000000000000000014051516144147600264330ustar00rootroot00000000000000B : Set B is not universe polymorphic B has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute_Records.B Declared in library PrimitiveProjectionsAttribute_Records, line 5, characters 6-7 C : Set C is not universe polymorphic C has primitive projections with eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute_Records.C Declared in library PrimitiveProjectionsAttribute_Records, line 10, characters 10-11 G : Prop G is not universe polymorphic G is in Prop but its eliminators are declared dependent by default G has primitive projections without eta conversion. Expands to: Inductive PrimitiveProjectionsAttribute_Records.G Declared in library PrimitiveProjectionsAttribute_Records, line 15, characters 12-13 rocq-9.2.0/test-suite/output/PrimitiveProjectionsAttribute_Records.v000066400000000000000000000006061516144147600260730ustar00rootroot00000000000000Unset Primitive Projections. (* Classes *do* support primitive projections. *) #[projections(primitive)] Class B := { b : nat ; }. About B. (* Structures *do* support primitive projections. *) #[projections(primitive)] Structure C := { c : nat ; }. About C. (* (negative) CoInductives *do* support primitive projections. *) #[projections(primitive)] CoInductive G := { g : G }. About G. rocq-9.2.0/test-suite/output/PrintAssumptions.out000066400000000000000000000004101516144147600222330ustar00rootroot00000000000000Axioms: foo : nat Axioms: foo : nat Axioms: bli : Type Axioms: bli : Type Axioms: seq relies on definitional UIP. Axioms: M.foo : False Closed under the global context Closed under the global context Closed under the global context Closed under the global context rocq-9.2.0/test-suite/output/PrintAssumptions.v000066400000000000000000000052621516144147600217030ustar00rootroot00000000000000 (** Print Assumption and opaque modules : Print Assumption used to consider as axioms the modular fields unexported by their signature, cf bug report #2186. This should now be fixed, let's test this here. *) (* First, a minimal test-case *) Axiom foo : nat. Module Type T. Parameter bar : nat. End T. Module M : T. Module Hide. (* An entire sub-module could be hidden *) Definition x := foo. End Hide. Definition bar := Hide.x. End M. Module N (X:T) : T. Definition y := X.bar. (* A non-exported field *) Definition bar := y. End N. Module P := N M. Print Assumptions M.bar. (* Should answer: foo *) Print Assumptions P.bar. (* Should answer: foo *) (* Print Assumptions used empty instances on polymorphic inductives *) Module Poly. Set Universe Polymorphism. Axiom bli : Type. Definition bla := bli -> bli. Inductive blo : bli -> Type := . Print Assumptions bla. Print Assumptions blo. End Poly. Module UIP. Set Definitional UIP. Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. Arguments srefl {_ _}. Definition eq_to_seq {A x y} (e:x = y :> A) : seq x y := match e with eq_refl => srefl end. Definition seq_to_eq {A x y} (e:seq x y) : x = y :> A := match e with srefl => eq_refl end. Definition norm {A x y} (e:x = y :> A) : x = y := seq_to_eq (eq_to_seq e). Definition norm_id {A x y} (e:x = y :> A) : norm e = e := match e with eq_refl => eq_refl end. Theorem UIP {A x y} (e e':x = y :> A) : e = e'. Proof. rewrite <-(norm_id e), <-(norm_id e'). reflexivity. Defined. Print Assumptions UIP. End UIP. (** Print Assumption and Include *) Module INCLUDE. Module M. Axiom foo : False. End M. Module N. Include M. End N. Print Assumptions N.foo. End INCLUDE. (* Print Assumptions did not enter implementation of submodules (#7192) *) Module SUBMODULES. Definition a := True. Module Type B. Axiom f : Prop. End B. Module Type C. Declare Module D : B. End C. Module E: C. Module D <: B. Definition f := a. End D. End E. Print Assumptions E.D.f. (* Idem in the scope of a functor *) Module Type T. End T. Module F (X : T). Definition a := True. Module Type B. Axiom f : Prop. End B. Module Type C. Declare Module D : B. End C. Module E: C. Module D <: B. Definition f := a. End D. End E. Print Assumptions E.D.f. End F. End SUBMODULES. (* Testing a variant of #7192 across files *) (* This was missing in the original fix to #7192 *) Require Import module_bug7192. Print Assumptions M7192.D.f. (* Testing reporting assumptions from modules in files *) (* A regression introduced in the original fix to #7192 was missing implementations *) Require Import module_bug8416. Print Assumptions M8416.f. rocq-9.2.0/test-suite/output/PrintCanonicalProjections.out000066400000000000000000000010601516144147600240170ustar00rootroot00000000000000bool <- sort_eq ( bool_eqType ) bool <- sort_TYPE ( bool_TYPE ) nat <- sort_eq ( nat_eqType ) nat <- sort_TYPE ( nat_TYPE ) prod <- sort_eq ( prod_eqType ) prod <- sort_TYPE ( prod_TYPE ) sum <- sort_eq ( sum_eqType ) sum <- sort_TYPE ( sum_TYPE ) sum <- sort_TYPE ( sum_TYPE ) prod <- sort_TYPE ( prod_TYPE ) nat <- sort_TYPE ( nat_TYPE ) bool <- sort_TYPE ( bool_TYPE ) sum <- sort_eq ( sum_eqType ) prod <- sort_eq ( prod_eqType ) nat <- sort_eq ( nat_eqType ) bool <- sort_eq ( bool_eqType ) bool <- sort_TYPE ( bool_TYPE ) bool <- sort_eq ( bool_eqType ) rocq-9.2.0/test-suite/output/PrintCanonicalProjections.v000066400000000000000000000025231516144147600234620ustar00rootroot00000000000000Record TYPE := Pack_TYPE { sort_TYPE :> Type }. Record eqType := Pack_eq { sort_eq :> Type; _ : sort_eq -> sort_eq -> bool }. Definition eq_op (T : eqType) : T -> T -> bool := match T with Pack_eq _ op => op end. Definition bool_eqb b1 b2 := match b1, b2 with | false, false => true | true, true => true | _, _ => false end. Canonical bool_TYPE := Pack_TYPE bool. Canonical bool_eqType := Pack_eq bool bool_eqb. Canonical nat_TYPE := Pack_TYPE nat. Canonical nat_eqType := Pack_eq nat Nat.eqb. Definition prod_eqb (T U : eqType) (x y : T * U) := match x, y with | (x1, x2), (y1, y2) => andb (eq_op _ x1 y1) (eq_op _ x2 y2) end. Canonical prod_TYPE (T U : TYPE) := Pack_TYPE (T * U). Canonical prod_eqType (T U : eqType) := Pack_eq (T * U) (prod_eqb T U). Definition sum_eqb (T U : eqType) (x y : T + U) := match x, y with | inl x, inl y => eq_op _ x y | inr x, inr y => eq_op _ x y | _, _ => false end. Canonical sum_TYPE (T U : TYPE) := Pack_TYPE (T + U). Canonical sum_eqType (T U : eqType) := Pack_eq (T + U) (sum_eqb T U). Print Canonical Projections bool. Print Canonical Projections nat. Print Canonical Projections prod. Print Canonical Projections sum. Print Canonical Projections sort_TYPE. Print Canonical Projections sort_eq. Print Canonical Projections sort_TYPE bool. Print Canonical Projections bool_eqType. rocq-9.2.0/test-suite/output/PrintFullyQualified.out000066400000000000000000000001621516144147600226310ustar00rootroot00000000000000use_foo use_bar use_nested PrintFullyQualified.use_foo PrintFullyQualified.use_bar PrintFullyQualified.use_nested rocq-9.2.0/test-suite/output/PrintFullyQualified.v000066400000000000000000000012421516144147600222670ustar00rootroot00000000000000(* Test file for Printing Fully Qualified option *) Module Foo. Axiom ax : False. End Foo. Module Bar. Axiom ax : False. End Bar. Definition use_foo := Foo.ax. Definition use_bar := Bar.ax. (* Test with nested modules *) Module Outer. Module Inner. Definition def := 0. End Inner. End Outer. Definition use_nested := Outer.Inner.def. (* Search with name-only output - default (shortest names) *) Set Search Output Name Only. Search "use_foo". Search "use_bar". Search "use_nested". (* Search with name-only output - fully qualified *) Set Printing Fully Qualified. Search "use_foo". Search "use_bar". Search "use_nested". Unset Printing Fully Qualified. rocq-9.2.0/test-suite/output/PrintGenarg.out000066400000000000000000000004111516144147600211120ustar00rootroot00000000000000Ltac foo := let x := open_constr:(ltac:(exact 0)) in idtac x Ltac2 bar : unit -> unit bar := fun _ => let _ := open_constr:(ltac2:(let c := preterm:(0) in exact1 false c)) in () rocq-9.2.0/test-suite/output/PrintGenarg.v000066400000000000000000000002721516144147600205550ustar00rootroot00000000000000Ltac foo := let x := open_constr:(ltac:(exact 0)) in idtac x. Print foo. Require Import Ltac2.Ltac2. Ltac2 bar () := let _ := open_constr:(ltac2:(exact 0)) in (). Print bar. rocq-9.2.0/test-suite/output/PrintGrammar.out000066400000000000000000000115731516144147600213100ustar00rootroot00000000000000Entry binder_constr is [ LEFTA [ "exists2"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; ","; term LEVEL "200"; "&"; term LEVEL "200" | "exists2"; "'"; pattern LEVEL "0"; ","; term LEVEL "200"; "&"; term LEVEL "200" | "exists2"; name; ":"; term LEVEL "200"; ","; term LEVEL "200"; "&"; term LEVEL "200" | "exists2"; name; ","; term LEVEL "200"; "&"; term LEVEL "200" | "exists"; "!"; open_binders; ","; term LEVEL "200" | "exists"; open_binders; ","; term LEVEL "200" | "forall"; open_binders; ","; term LEVEL "200" | "fun"; open_binders; "=>"; term LEVEL "200" | "let"; "fix"; fix_decl; "in"; term LEVEL "200" | "let"; "cofix"; cofix_body; "in"; term LEVEL "200" | "let"; "'"; pattern LEVEL "200"; OPT [ "in"; pattern LEVEL "200" ]; ":="; term LEVEL "200"; OPT case_type; "in"; term LEVEL "200" | "let"; name; binders; let_type_cstr; ":="; term LEVEL "200"; "in"; term LEVEL "200" | "let"; [ "("; LIST0 name SEP ","; ")" | "()" ]; as_return_type; ":="; term LEVEL "200"; "in"; term LEVEL "200" | "if"; term LEVEL "200"; as_return_type; "then"; term LEVEL "200"; "else"; term LEVEL "200" | "fix"; fix_decls | "cofix"; cofix_decls ] ] Entry constr is [ LEFTA [ "@"; global; univ_annot | term LEVEL "8" ] ] Entry lconstr is [ LEFTA [ term LEVEL "200" ] ] Entry term is [ "200" RIGHTA [ ] | "100" RIGHTA [ SELF; "<:"; term LEVEL "200" | SELF; "<<:"; term LEVEL "200" | SELF; ":>"; term LEVEL "200" | SELF; ":"; term LEVEL "200" ] | "99" RIGHTA [ SELF; "->"; term LEVEL "200" ] | "95" RIGHTA [ SELF; "<->"; NEXT ] | "90" RIGHTA [ ] | "85" RIGHTA [ SELF; "\\/"; term LEVEL "85" ] | "80" RIGHTA [ SELF; "/\\"; term LEVEL "80" ] | "75" RIGHTA [ "~"; term LEVEL "75" ] | "70" RIGHTA [ SELF; ">"; NEXT | SELF; ">="; NEXT | SELF; "<"; NEXT; "<="; NEXT | SELF; "<"; NEXT; "<"; NEXT | SELF; "<"; NEXT | SELF; "<="; NEXT; "<"; NEXT | SELF; "<="; NEXT; "<="; NEXT | SELF; "<="; NEXT | SELF; "<>"; NEXT; ":>"; NEXT | SELF; "<>"; NEXT | SELF; "="; NEXT; "="; NEXT | SELF; "="; NEXT; ":>"; NEXT | SELF; "="; NEXT ] | "60" RIGHTA [ SELF; "++"; term LEVEL "60" | SELF; "::"; term LEVEL "60" ] | "50" LEFTA [ SELF; "||"; NEXT | SELF; "-"; NEXT | SELF; "+"; NEXT ] | "40" LEFTA [ SELF; "&&"; NEXT | SELF; "/"; NEXT | SELF; "*"; NEXT ] | "35" RIGHTA [ "/"; term LEVEL "35" | "-"; term LEVEL "35" ] | "30" RIGHTA [ SELF; "^"; term LEVEL "30" ] | "10" LEFTA [ SELF; LIST1 arg | "@"; global; univ_annot; LIST0 NEXT | "@"; pattern_ident; LIST1 identref | binder_constr ] | "9" LEFTA [ ".."; term LEVEL "0"; ".." ] | "8" LEFTA [ ] | "1" LEFTA [ SELF; ".2" | SELF; ".1" | SELF; ".("; "@"; global; univ_annot; LIST0 (term LEVEL "9"); ")" | SELF; ".("; global; univ_annot; LIST0 arg; ")" | SELF; "%"; IDENT | SELF; "%_"; IDENT ] | "0" LEFTA [ "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; "'"; pattern LEVEL "0"; "|"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; ":"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; ":"; term LEVEL "200"; "|"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; "|"; term LEVEL "200"; "&"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; "|"; term LEVEL "200"; "}" | "{"; term LEVEL "99"; "}" | IDENT "ltac"; ":"; "("; ltac_expr; ")" | "("; term LEVEL "200"; ","; term LEVEL "200"; ","; LIST1 (term LEVEL "200") SEP ","; ")" | "("; term LEVEL "200"; ","; term LEVEL "200"; ")" | "("; term LEVEL "200"; ")" | "{|"; record_declaration; '|}' | "`{"; term LEVEL "200"; "}" | "`("; term LEVEL "200"; ")" | NUMBER | atomic_constr | term_match | reference; univ_annot | string | test_array_opening; "["; "|"; array_elems; "|"; lconstr; type_cstr; test_array_closing; "|"; "]"; univ_annot ] ] Entry univ_annot is [ LEFTA [ "@{"; LIST0 univ_level_or_quality; OPT [ [ "|" | ";" ]; LIST0 univ_level_or_quality ]; "}" | ] ] Entry fix_decls is [ LEFTA [ fix_decl; "with"; LIST1 fix_decl SEP "with"; "for"; identref | fix_decl ] ] rocq-9.2.0/test-suite/output/PrintGrammar.v000066400000000000000000000000741516144147600207400ustar00rootroot00000000000000 Print Grammar constr univ_annot. Print Grammar fix_decls. rocq-9.2.0/test-suite/output/PrintGrammarConstr.out000066400000000000000000000036701516144147600225000ustar00rootroot00000000000000Entry binder_constr is [ LEFTA [ "forall"; open_binders; ","; term LEVEL "200" | "fun"; open_binders; "=>"; term LEVEL "200" | "let"; "fix"; fix_decl; "in"; term LEVEL "200" | "let"; "cofix"; cofix_body; "in"; term LEVEL "200" | "let"; "'"; pattern LEVEL "200"; OPT [ "in"; pattern LEVEL "200" ]; ":="; term LEVEL "200"; OPT case_type; "in"; term LEVEL "200" | "let"; name; binders; let_type_cstr; ":="; term LEVEL "200"; "in"; term LEVEL "200" | "let"; [ "("; LIST0 name SEP ","; ")" | "()" ]; as_return_type; ":="; term LEVEL "200"; "in"; term LEVEL "200" | "if"; term LEVEL "200"; as_return_type; "then"; term LEVEL "200"; "else"; term LEVEL "200" | "fix"; fix_decls | "cofix"; cofix_decls ] ] Entry constr is [ LEFTA [ "@"; global; univ_annot | term LEVEL "8" ] ] Entry lconstr is [ LEFTA [ term LEVEL "200" ] ] Entry term is [ "200" RIGHTA [ ] | "100" RIGHTA [ SELF; "<:"; term LEVEL "200" | SELF; "<<:"; term LEVEL "200" | SELF; ":>"; term LEVEL "200" | SELF; ":"; term LEVEL "200" ] | "99" RIGHTA [ ] | "90" RIGHTA [ ] | "10" LEFTA [ SELF; LIST1 arg | "@"; global; univ_annot; LIST0 NEXT | "@"; pattern_ident; LIST1 identref | binder_constr ] | "9" LEFTA [ ".."; term LEVEL "0"; ".." ] | "8" LEFTA [ ] | "1" LEFTA [ SELF; ".("; "@"; global; univ_annot; LIST0 (term LEVEL "9"); ")" | SELF; ".("; global; univ_annot; LIST0 arg; ")" | SELF; "%"; IDENT | SELF; "%_"; IDENT ] | "0" LEFTA [ "["; term LEVEL "10"; "+"; "+"; "*"; LIST1 (term LEVEL "10") SEP ["+"; "+"; "*"]; "|"; term LEVEL "200"; "]" | "["; term LEVEL "10"; "|"; term LEVEL "200"; "]" | "("; term LEVEL "200"; ")" | "{|"; record_declaration; '|}' | "`{"; term LEVEL "200"; "}" | "`("; term LEVEL "200"; ")" | NUMBER | atomic_constr | term_match | reference; univ_annot | string | test_array_opening; "["; "|"; array_elems; "|"; lconstr; type_cstr; test_array_closing; "|"; "]"; univ_annot ] ] rocq-9.2.0/test-suite/output/PrintGrammarConstr.v000066400000000000000000000002301516144147600221230ustar00rootroot00000000000000(* coq-prog-args: ("-nois") *) Notation "[ a + + * .. + + * c | d ]" := (forall _ : a, .. (forall _ : c, d) ..) (a at level 10). Print Grammar constr. rocq-9.2.0/test-suite/output/PrintInfos.out000066400000000000000000000116201516144147600207710ustar00rootroot00000000000000existT : forall [A : Type] (P : A -> Type) (x : A), P x -> {x : A & P x} existT is template universe polymorphic Arguments existT [A]%_type_scope P%_function_scope x _ Expands to: Constructor Corelib.Init.Specif.existT Declared in library Corelib.Init.Specif, line 45, characters 4-10 Inductive sigT (A : Type) (P : A -> Type) : Type := existT : forall x : A, P x -> {x : A & P x}. Arguments sigT [A]%_type_scope P%_type_scope Arguments existT [A]%_type_scope P%_function_scope x _ existT : forall [A : Type] (P : A -> Type) (x : A), P x -> {x : A & P x} Argument A is implicit Inductive eq (A : Type) (x : A) : A -> Prop := eq_refl : x = x. Arguments eq {A}%_type_scope x _ Arguments eq_refl {A}%_type_scope {x}, [_] _ eq_refl : forall {A : Type} {x : A}, x = x eq_refl is template universe polymorphic Arguments eq_refl {A}%_type_scope {x}, [_] _ Expands to: Constructor Corelib.Init.Logic.eq_refl Declared in library Corelib.Init.Logic, line 380, characters 4-11 eq_refl : forall {A : Type} {x : A}, x = x When applied to no arguments: Arguments A, x are implicit and maximally inserted When applied to 1 argument: Argument A is implicit Nat.add = fix add (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (add p m) end : nat -> nat -> nat Arguments Nat.add (n m)%_nat_scope Nat.add : nat -> nat -> nat Nat.add is not universe polymorphic Arguments Nat.add (n m)%_nat_scope Nat.add is transparent Expands to: Constant Corelib.Init.Nat.add Declared in library Corelib.Init.Nat, line 47, characters 9-12 Nat.add : nat -> nat -> nat plus_n_O : forall n : nat, n = n + 0 plus_n_O is not universe polymorphic Arguments plus_n_O n%_nat_scope plus_n_O is opaque Expands to: Constant Corelib.Init.Peano.plus_n_O Declared in library Corelib.Init.Peano, line 99, characters 6-14 Inductive le (n : nat) : nat -> Prop := le_n : n <= n | le_S : forall m : nat, n <= m -> n <= S m. Arguments le (n _)%_nat_scope Arguments le_n n%_nat_scope Arguments le_S {n}%_nat_scope [m]%_nat_scope _ comparison : Set comparison is not universe polymorphic Expands to: Inductive Corelib.Init.Datatypes.comparison Declared in library Corelib.Init.Datatypes, line 369, characters 10-20 Inductive comparison : Set := Eq : comparison | Lt : comparison | Gt : comparison. bar : foo bar is not universe polymorphic Expanded type for implicit arguments bar : forall {x : nat}, x = 0 Arguments bar {x} Expands to: Constant PrintInfos.bar Declared in library PrintInfos, line 23, characters 10-13 *** [ bar : foo ] Expanded type for implicit arguments bar : forall {x : nat}, x = 0 Arguments bar {x} Module Corelib.Init.Peano Notation sym_eq := eq_sym Expands to: Notation Corelib.Init.Logic.sym_eq Declared in library Corelib.Init.Logic, line 764, characters 0-45 eq_sym : forall [A : Type] [x y : A], x = y -> y = x eq_sym is not universe polymorphic Arguments eq_sym [A]%_type_scope [x y] H eq_sym is transparent Expands to: Constant Corelib.Init.Logic.eq_sym Declared in library Corelib.Init.Logic, line 409, characters 0-24 Inductive eq (A : Type) (x : A) : A -> Prop := eq_refl : x = x. Arguments eq {A}%_type_scope x _ Arguments eq_refl {A}%_type_scope {x}, {_} _ n:nat Hypothesis of the goal context. h:(n <> newdef n) Hypothesis of the goal context. g:(nat -> nat) Constant (let in) of the goal context. h:(n <> newdef n) Hypothesis of the goal context. Alias.eq : forall {A : Type}, A -> A -> Prop Alias.eq is template universe polymorphic Arguments Alias.eq {A}%_type_scope x _ Expands to: Inductive PrintInfos.Alias.eq (syntactically equal to Corelib.Init.Logic.eq) Declared in library Corelib.Init.Logic, line 379, characters 10-12 Alias.eq_refl : forall {A : Type} {x : A}, x = x Alias.eq_refl is template universe polymorphic Arguments Alias.eq_refl {A}%_type_scope {x}, [_] _ Expands to: Constructor PrintInfos.Alias.eq_refl (syntactically equal to Corelib.Init.Logic.eq_refl) Declared in library Corelib.Init.Logic, line 380, characters 4-11 Alias.eq_ind : forall [A : Type] (x : A) (P : A -> Prop), P x -> forall y : A, x = y -> P y Alias.eq_ind is not universe polymorphic Arguments Alias.eq_ind [A]%_type_scope x P%_function_scope eq_refl y e (where some original arguments have been renamed) Alias.eq_ind is transparent Expands to: Constant PrintInfos.Alias.eq_ind (syntactically equal to Corelib.Init.Logic.eq_ind) Declared in library Corelib.Init.Logic, line 379, characters 0-115 fst : forall A B : Type, prod A B -> A fst is not universe polymorphic fst is a projection of prod Arguments fst (A B)%_type_scope p fst is transparent Expands to: Constant PrintInfos.AboutProj.fst Declared in library PrintInfos, line 57, characters 21-24 fst : forall A B : Type, prod A B -> A fst is not universe polymorphic fst is a primitive projection of prod Arguments fst (A B)%_type_scope p fst is transparent Expands to: Constant PrintInfos.AboutPrimProj.fst Declared in library PrintInfos, line 63, characters 21-24 rocq-9.2.0/test-suite/output/PrintInfos.v000066400000000000000000000023671516144147600204370ustar00rootroot00000000000000(* coq-prog-args: ("-top" "PrintInfos") *) About existT. Print existT. Print Implicit existT. Print eq_refl. About eq_refl. Print Implicit eq_refl. Print Nat.add. About Nat.add. Print Implicit Nat.add. About plus_n_O. Arguments le_S {n} [m] _. Print le_S. About comparison. Print comparison. Definition foo := forall x, x = 0. Parameter bar : foo. Arguments bar {x}. About bar. Print bar. About Peano. (* Module *) About sym_eq. (* Notation *) Arguments eq_refl {A} {x}, {A} x. Print eq_refl. Definition newdef := fun x:nat => x. Goal forall n:nat, n <> newdef n -> newdef n <> n -> False. intros n h h'. About n. (* search hypothesis *) About h. (* search hypothesis *) Abort. Goal forall n:nat, let g := newdef in n <> newdef n -> newdef n <> n -> False. intros n g h h'. About g. (* search hypothesis *) About h. (* search hypothesis *) Abort. Module Alias := Logic. About Alias.eq. About Alias.eq_refl. About Alias.eq_ind. Module AboutProj. Record prod A B := { fst:A ; snd:B }. About fst. End AboutProj. Module AboutPrimProj. Set Primitive Projections. Record prod A B := { fst:A ; snd:B }. About fst. End AboutPrimProj. rocq-9.2.0/test-suite/output/PrintKeywords.out000066400000000000000000000005601516144147600215230ustar00rootroot00000000000000! # #[ % %_ & && ' ( () ) * ** + ++ , - -> . .( .. ... .1 .2 / /\ : :: ::= ::> := :> ; < <+ <- <-> <: <<: <= <> = => > >-> >= ? @ @{ Axiom CoFixpoint Definition Fixpoint Hypothesis Parameter Prop SProp Set Theorem Type Variable [ \/ ] ^ _ `( `[ `{ as at by cofix else end exists exists2 fix for forall fun if in let match return then using where with { {| | |- || } ~ rocq-9.2.0/test-suite/output/PrintKeywords.v000066400000000000000000000000201516144147600211500ustar00rootroot00000000000000Print Keywords. rocq-9.2.0/test-suite/output/PrintMatch.out000066400000000000000000000034741516144147600207570ustar00rootroot00000000000000eqT_rect@{u u0} = fun (A : Type@{u}) (a : A) (P : forall a0 : A, eqT@{u} a a0 -> Type@{u0}) (reflT : P a (reflT@{u} a)) (a0 : A) (e : eqT@{u} a a0) => match e :> eqT@{u} a _ as e0 in eqT _ a1 return P a1 e0 with | MatchAllSubterms.reflT _ => reflT end : forall (A : Type@{u}) (a : A) (P : forall a0 : A, eqT@{u} a a0 -> Type@{u0}), P a (reflT@{u} a) -> forall (a0 : A) (e : eqT@{u} a a0), P a0 e (* u u0 |= *) Arguments eqT_rect A%_type_scope a P%_function_scope reflT a0 e seq_rect = fun (A : Type@{seq_rect.u1}) (a : A) (P : forall a0 : A, seq a a0 -> Type@{seq_rect.u0}) (srefl : P a (srefl a)) (a0 : A) (s : seq a a0) => match s :> seq a a0 as s0 in seq _ a1 return P a1 s0 with | MatchAllSubterms.srefl _ => srefl end : forall (A : Type@{seq_rect.u1}) (a : A) (P : forall a0 : A, seq a a0 -> Type@{seq_rect.u0}), P a (srefl a) -> forall (a0 : A) (s : seq a a0), P a0 s Arguments seq_rect A%_type_scope a P%_function_scope srefl a0 s eq_sym = fun (A : Type) (x y : A) (H : @eq A x y) => match H in @eq _ _ y0 return @eq A y0 x with | @eq_refl _ _ => @eq_refl A x end : forall [A : Type] [x y : A] (_ : @eq A x y), @eq A y x Arguments eq_sym [A]%_type_scope [x y] H eq_sym = fun (A : Type) (x y : A) (H : x = y) => match H in _ = y0 return y0 = x with | @eq_refl _ _ => @eq_refl A x end : forall [A : Type] [x y : A], x = y -> y = x Arguments eq_sym [A]%_type_scope [x y] H eq_sym = fun (A : Type) (x y : A) (H : x = y) => match H in _ = y0 return y0 = x with | @eq_refl _ _ => @eq_refl A x end : forall [A : Type] [x y : A], x = y -> y = x Arguments eq_sym [A]%_type_scope [x y] H test = fun (O : unit) (S : nat -> unit) (n : nat) => match n with | 0 => O | Datatypes.S n0 => S n0 end : unit -> (nat -> unit) -> nat -> unit Arguments test O S%_function_scope n%_nat_scope rocq-9.2.0/test-suite/output/PrintMatch.v000066400000000000000000000013321516144147600204040ustar00rootroot00000000000000(* NB feel free to add other tests about printing match, not just about Match All Subterms *) Module MatchAllSubterms. Set Printing Match All Subterms. Set Printing Universes. Polymorphic Inductive eqT@{u} {A:Type@{u}} (a:A) : A -> Type@{u} := reflT : eqT a a. Print eqT_rect. Set Definitional UIP. Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. Print seq_rect. End MatchAllSubterms. Module Bug18163. Set Printing All. Print eq_sym. Unset Printing All. Set Printing Implicit. Print eq_sym. Set Asymmetric Patterns. Print eq_sym. End Bug18163. Module AvoidName. Definition test (O : unit) (S : nat -> unit) (n : nat) := match n with | Datatypes.O => O | Datatypes.S n => S n end. Print test. End AvoidName. rocq-9.2.0/test-suite/output/PrintModule.out000066400000000000000000000005371516144147600211450ustar00rootroot00000000000000Module N : S with Definition T := nat := M Module N : S with Definition T := M Module N : S with Module T := K := M Module N : S with Module T := M Module Type Func = Funsig (T0:Test) Sig Parameter x : T0.t. End Module A := Struct Variant I : Set := C : nat -> I. Record R : Set := Build_R { n : nat }. Definition n : R -> nat. End rocq-9.2.0/test-suite/output/PrintModule.v000066400000000000000000000015021516144147600205740ustar00rootroot00000000000000(* Bug #2169 *) Module FOO. Module M. Definition T := nat. End M. Module Type S. Parameter T : Set. End S. Module N : S with Definition T := nat := M. Print Module N. Set Short Module Printing. Print Module N. Unset Short Module Printing. End FOO. Module BAR. Module K. End K. Module Type KS. End KS. Module M. Module T := K. End M. Module Type S. Declare Module T : KS. End S. Module N : S with Module T := K := M. Print Module N. Set Short Module Printing. Print Module N. Unset Short Module Printing. End BAR. (* Bug #4661 *) Module QUX. Module Type Test. Parameter t : Type. End Test. Module Type Func (T:Test). Parameter x : T.t. End Func. Module Shortest_path (T : Test). Print Func. End Shortest_path. End QUX. Module A. Variant I := C : nat -> I. Record R := { n : nat }. End A. Print Module A. rocq-9.2.0/test-suite/output/PrintNotation.out000066400000000000000000000416121516144147600215120ustar00rootroot00000000000000Notation "_ $ _" at level 123 with arguments constr at next level, constr at next level, no associativity. File "./output/PrintNotation.v", line 8, characters 9-14: Warning: In term, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace File "./output/PrintNotation.v", line 8, characters 9-9 with ( Replace File "./output/PrintNotation.v", line 8, characters 14-14 with ) bar (bar ?f ?f0) ?f1 : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] Notation "_ $ _" at level 123 with arguments constr at next level, constr at next level, no associativity. File "./output/PrintNotation.v", line 17, characters 9-14: Warning: In term, tolerating this expression at a higher level than expected by the notation continuing on the right (which is not left-associative). This tolerance will be eventually removed. Insert parentheses or try to lower the level at which the top symbol of this expression is parsed. [level-tolerance,deprecated-since-9.2,deprecated,parsing,default] Quickfix: Replace File "./output/PrintNotation.v", line 17, characters 9-9 with ( Replace File "./output/PrintNotation.v", line 17, characters 14-14 with ) bar (bar ?f ?f0) ?f1 : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] Notation "_ $ _" at level 123 with arguments constr at level 123, constr at next level, left associativity. bar (bar ?f ?f0) ?f1 : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] Notation "_ $ _" at level 123 with arguments constr at next level, constr at level 123, right associativity. bar ?f (bar ?f0 ?f1) : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] File "./output/PrintNotation.v", line 36, characters 2-30: The command has indeed failed with message: "_ $ x" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 37, characters 2-28: The command has indeed failed with message: "_ $" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 38, characters 2-28: The command has indeed failed with message: "$ x" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 39, characters 2-28: The command has indeed failed with message: "x$y" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 40, characters 2-28: The command has indeed failed with message: "_$_" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Notation "_ $ _" at level 123 with arguments constr at next level, constr at level 123, right associativity. Notation "_ $ _" at level 123 with arguments constr at next level, constr at level 123, right associativity. Notation "_ -> _" at level 99 with arguments constr at next level, constr at level 200, no associativity. Notation "_ <-> _" at level 95 with arguments constr at next level, constr at next level, no associativity. Notation "_ /\ _" at level 80 with arguments constr at next level, constr at level 80, right associativity. Notation "_ \/ _" at level 85 with arguments constr at next level, constr at level 85, right associativity. Notation "~ _" at level 75 with arguments constr at level 75, right associativity. Notation "_ = _ :> _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ = _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ = _ = _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <> _ :> _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <> _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ <= _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ < _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ >= _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ > _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ <= _ <= _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <= _ < _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ < _ < _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ < _ <= _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ + _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ - _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ * _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "_ / _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "- _" at level 35 with arguments constr at level 35, right associativity. Notation "/ _" at level 35 with arguments constr at level 35, right associativity. Notation "_ ^ _" at level 30 with arguments constr at next level, constr at level 30, right associativity. Notation "_ || _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ && _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "( _ , _ , .. , _ )" at level 0 with arguments constr, constr, no associativity. Notation "{ _ }" at level 0 with arguments constr at level 99, no associativity. Notation "{ _ } + { _ }" at level 50 with arguments constr, constr, left associativity. Notation "_ + { _ }" at level 50 with arguments constr at level 50, constr, left associativity. Notation "{ _ | _ }" at level 0 with arguments constr at level 99, constr, no associativity. Notation "{ _ | _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ | _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ | _ & _ }" at level 0 with arguments constr at level 99, constr, constr, constr, no associativity. Notation "{ _ & _ }" at level 0 with arguments constr at level 99, constr, no associativity. Notation "{ _ & _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ & _ & _ }" at level 0 with arguments constr at level 99, constr, constr, constr, no associativity. Notation "{ ' _ | _ }" at level 0 with arguments strict pattern at level 0, constr, no associativity. Notation "{ ' _ | _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ | _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ | _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, constr, no associativity. Notation "{ ' _ & _ }" at level 0 with arguments strict pattern at level 0, constr, no associativity. Notation "{ ' _ & _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ & _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, constr, no associativity. Notation "if _ is _ then _ else _" at level 200 with arguments constr, pattern at level 100 at level 100, constr, constr at next level, no associativity. Notation "_ -> _" at level 99 with arguments constr at next level, constr at level 200, no associativity. Notation "_ <-> _" at level 95 with arguments constr at next level, constr at next level, no associativity. Notation "_ /\ _" at level 80 with arguments constr at next level, constr at level 80, right associativity. Notation "_ \/ _" at level 85 with arguments constr at next level, constr at level 85, right associativity. Notation "~ _" at level 75 with arguments constr at level 75, right associativity. Notation "_ = _ :> _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ = _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ = _ = _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <> _ :> _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <> _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ <= _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ < _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ >= _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ > _" at level 70 with arguments constr at next level, constr at next level, no associativity. Notation "_ <= _ <= _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ <= _ < _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ < _ < _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ < _ <= _" at level 70 with arguments constr at next level, constr at next level, constr at next level, no associativity. Notation "_ + _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ - _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ * _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "_ / _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "- _" at level 35 with arguments constr at level 35, right associativity. Notation "/ _" at level 35 with arguments constr at level 35, right associativity. Notation "_ ^ _" at level 30 with arguments constr at next level, constr at level 30, right associativity. Notation "_ || _" at level 50 with arguments constr at level 50, constr at next level, left associativity. Notation "_ && _" at level 40 with arguments constr at level 40, constr at next level, left associativity. Notation "( _ , _ , .. , _ )" at level 0 with arguments constr, constr, no associativity. Notation "{ _ }" at level 0 with arguments constr at level 99, no associativity. Notation "{ _ } + { _ }" at level 50 with arguments constr, constr, left associativity. Notation "_ + { _ }" at level 50 with arguments constr at level 50, constr, left associativity. Notation "{ _ | _ }" at level 0 with arguments constr at level 99, constr, no associativity. Notation "{ _ | _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ | _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ | _ & _ }" at level 0 with arguments constr at level 99, constr, constr, constr, no associativity. Notation "{ _ & _ }" at level 0 with arguments constr at level 99, constr, no associativity. Notation "{ _ & _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ & _ }" at level 0 with arguments constr at level 99, constr, constr, no associativity. Notation "{ _ : _ & _ & _ }" at level 0 with arguments constr at level 99, constr, constr, constr, no associativity. Notation "{ ' _ | _ }" at level 0 with arguments strict pattern at level 0, constr, no associativity. Notation "{ ' _ | _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ | _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ | _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, constr, no associativity. Notation "{ ' _ & _ }" at level 0 with arguments strict pattern at level 0, constr, no associativity. Notation "{ ' _ & _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, no associativity. Notation "{ ' _ : _ & _ & _ }" at level 0 with arguments strict pattern at level 0, constr, constr, constr, no associativity. Notation "if _ is _ then _ else _" at level 200 with arguments constr, pattern at level 100 at level 100, constr, constr at next level, no associativity. Notation "{{ _ }}" in Foo at level 0 with arguments custom Foo, no associativity. Notation "{{ _ }}" in Foo at level 0 with arguments custom Foo, no associativity. File "./output/PrintNotation.v", line 156, characters 42-45: The command has indeed failed with message: Unknown custom entry: Bar. File "./output/PrintNotation.v", line 157, characters 42-45: The command has indeed failed with message: Unknown custom entry: Bar. File "./output/PrintNotation.v", line 158, characters 2-46: The command has indeed failed with message: "[[ x ]]" cannot be interpreted as a known notation in Foo entry. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 159, characters 2-46: The command has indeed failed with message: "[[ _ ]]" cannot be interpreted as a known notation in Foo entry. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 164, characters 2-32: The command has indeed failed with message: "x mod y" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Notation "_ mod _" at level 40 with arguments constr at next level, constr at next level, no associativity. Notation "_ mod _" at level 40 with arguments constr at next level, constr at next level, no associativity. Notation "_ mod _" at level 40 with arguments constr at next level, constr at next level, no associativity. bar (bar ?f ?f0) ?f1 : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] File "./output/PrintNotation.v", line 176, characters 2-34: The command has indeed failed with message: "x 'mod' y" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Notation "_ 'mod' _" at level 40 with arguments constr at next level, constr at next level, no associativity. File "./output/PrintNotation.v", line 178, characters 2-34: The command has indeed failed with message: "_ 'mod' _" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Notation "_ 'mod' _" at level 40 with arguments constr at next level, constr at next level, no associativity. bar (bar ?f ?f0) ?f1 : foo where ?f : [ |- foo] ?f0 : [ |- foo] ?f1 : [ |- foo] File "./output/PrintNotation.v", line 190, characters 2-42: The command has indeed failed with message: "exists x .. y , p" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". Notation "exists _ .. _ , _" at level 200 with arguments binder, constr at level 200, right associativity. Notation "exists _ .. _ , _" at level 200 with arguments binder, constr at level 200, right associativity. File "./output/PrintNotation.v", line 193, characters 2-37: The command has indeed failed with message: "exists _ , _" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". File "./output/PrintNotation.v", line 194, characters 2-39: The command has indeed failed with message: "exists _ _ , _" cannot be interpreted as a known notation. Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by "_". rocq-9.2.0/test-suite/output/PrintNotation.v000066400000000000000000000135721516144147600211540ustar00rootroot00000000000000Set Printing All. Module NoDefinedAssoc. Reserved Notation "x $ y" (at level 123). Print Notation "x $ x". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Notation "x $ y" := (bar x y) (only parsing). Check (_ $ _ $ _). End NoDefinedAssoc. Module NoAssoc. Reserved Notation "x $ y" (at level 123, no associativity). Print Notation "x $ x". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Notation "x $ y" := (bar x y) (only parsing). Check (_ $ _ $ _). End NoAssoc. Module LeftAssoc. Reserved Notation "x $ y" (at level 123, left associativity). Print Notation "x $ x". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Notation "x $ y" := (bar x y) (only parsing). Check (_ $ _ $ _). End LeftAssoc. Module RightAssoc. Reserved Notation "x $ y" (at level 123, right associativity). Print Notation "x $ x". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Notation "x $ y" := (bar x y) (only parsing). Check (_ $ _ $ _). Fail Print Notation "_ $ x". Fail Print Notation "_ $". Fail Print Notation "$ x". Fail Print Notation "x$y". Fail Print Notation "_$_". Print Notation "y $ x". Print Notation "_ $ _". End RightAssoc. (** Stdlib notations *) Module StdlibNotations. Import IfNotations. Print Notation "x -> y". Print Notation "x <-> y". Print Notation "x /\ y". Print Notation "x \/ y". Print Notation "~ x". Print Notation "x = y :> T". Print Notation "x = y". Print Notation "x = y = z". Print Notation "x <> y :> T". Print Notation "x <> y". Print Notation "x <= y". Print Notation "x < y". Print Notation "x >= y". Print Notation "x > y". Print Notation "x <= y <= z". Print Notation "x <= y < z". Print Notation "x < y < z". Print Notation "x < y <= z". Print Notation "x + y". Print Notation "x - y". Print Notation "x * y". Print Notation "x / y". Print Notation "- x". Print Notation "/ x". Print Notation "x ^ y". Print Notation "x || y". Print Notation "x && y". Print Notation "( x , y , .. , z )". Print Notation "{ x }". Print Notation "{ A } + { B }". Print Notation "A + { B }". Print Notation "{ x | P }". Print Notation "{ x | P & Q }". Print Notation "{ x : A | P }". Print Notation "{ x : A | P & Q }". Print Notation "{ x & P }". Print Notation "{ x & P & Q }". Print Notation "{ x : A & P }". Print Notation "{ x : A & P & Q }". Print Notation "{ ' pat | P }". Print Notation "{ ' pat | P & Q }". Print Notation "{ ' pat : A | P }". Print Notation "{ ' pat : A | P & Q }". Print Notation "{ ' pat & P }". Print Notation "{ ' pat & P & Q }". Print Notation "{ ' pat : A & P }". Print Notation "{ ' pat : A & P & Q }". Print Notation "'if' c 'is' p 'then' u 'else' v". End StdlibNotations. Module StdlibNotationsUnderscored. Import IfNotations. Print Notation "_ -> _". Print Notation "_ <-> _". Print Notation "_ /\ _". Print Notation "_ \/ _". Print Notation "~ _". Print Notation "_ = _ :> _". Print Notation "_ = _". Print Notation "_ = _ = _". Print Notation "_ <> _ :> _". Print Notation "_ <> _". Print Notation "_ <= _". Print Notation "_ < _". Print Notation "_ >= _". Print Notation "_ > _". Print Notation "_ <= _ <= _". Print Notation "_ <= _ < _". Print Notation "_ < _ < _". Print Notation "_ < _ <= _". Print Notation "_ + _". Print Notation "_ - _". Print Notation "_ * _". Print Notation "_ / _". Print Notation "- _". Print Notation "/ _". Print Notation "_ ^ _". Print Notation "_ || _". Print Notation "_ && _". Print Notation "( _ , _ , .. , _ )". Print Notation "{ _ }". Print Notation "{ _ } + { _ }". Print Notation "_ + { _ }". Print Notation "{ _ | _ }". Print Notation "{ _ | _ & _ }". Print Notation "{ _ : _ | _ }". Print Notation "{ _ : _ | _ & _ }". Print Notation "{ _ & _ }". Print Notation "{ _ & _ & _ }". Print Notation "{ _ : _ & _ }". Print Notation "{ _ : _ & _ & _ }". Print Notation "{ ' _ | _ }". Print Notation "{ ' _ | _ & _ }". Print Notation "{ ' _ : _ | _ }". Print Notation "{ ' _ : _ | _ & _ }". Print Notation "{ ' _ & _ }". Print Notation "{ ' _ & _ & _ }". Print Notation "{ ' _ : _ & _ }". Print Notation "{ ' _ : _ & _ & _ }". Print Notation "if _ is _ then _ else _". End StdlibNotationsUnderscored. (* Print Notatation doesn't work with custom notations *) Module Custom. Declare Custom Entry Foo. Reserved Notation "{{ x }}" (in custom Foo at level 0). Print Notation "{{ x }}" in custom Foo. Print Notation "{{ _ }}" in custom Foo. Fail Print Notation "{{ x }}" in custom Bar. Fail Print Notation "{{ _ }}" in custom Bar. Fail Print Notation "[[ x ]]" in custom Foo. Fail Print Notation "[[ _ ]]" in custom Foo. End Custom. Module OnlyLetters. Reserved Infix "mod" (at level 40, no associativity). Fail Print Notation "x mod y". Print Notation "x 'mod' y". Print Notation "_ mod _". Print Notation "_ 'mod' _". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Infix "mod" := bar (only parsing). Check (_ mod _ mod _). End OnlyLetters. Module SingleQuotes. Reserved Infix "'mod'" (at level 40, no associativity). Fail Print Notation "x 'mod' y". Print Notation "x ''mod'' y". Fail Print Notation "_ 'mod' _". (* FIXME I expected this to work *) Print Notation "_ ''mod'' _". Axiom foo : Type. Axiom bar : forall _ : foo, forall _ : foo, foo. Infix "'mod'" := bar (only parsing). Check (_ 'mod' _ 'mod' _). End SingleQuotes. Module Recursive. Reserved Notation "'exists' x .. y , p" (at level 200, x binder, right associativity, format "'[' 'exists' '/ ' x .. y , '/ ' p ']'"). Fail Print Notation "exists x .. y , p". Print Notation "'exists' x .. y , p". Print Notation "exists _ .. _ , _". Fail Print Notation "exists _ , _". Fail Print Notation "exists _ _ , _". End Recursive. rocq-9.2.0/test-suite/output/PrintPrimProj.out000066400000000000000000000006371516144147600214630ustar00rootroot00000000000000(trip (unbox nat n) (unbox _ n) (unbox _ n)) (trip (unbox nat n) (unbox _ n) (let '{| unbox := unbox |} := n in unbox)) (trip n.(unbox nat) n.(unbox _) (let '{| unbox := unbox |} := n in unbox)) (trip n.(unbox nat) n.(unbox _) n.(unbox _)) (trip n.(unbox) n.(unbox) n.(unbox)) (trip n.(unbox) n.(unbox) (let '{| unbox := unbox |} := n in unbox)) (trip (unbox n) (unbox n) (let '{| unbox := unbox |} := n in unbox)) rocq-9.2.0/test-suite/output/PrintPrimProj.v000066400000000000000000000013411516144147600211120ustar00rootroot00000000000000Set Primitive Projections. Record Box (A:Type) := box { unbox : A }. Definition ubox := @unbox. Axiom trip : nat -> nat -> nat -> Prop. Ltac show_goal := match goal with |- ?g => idtac g end. Lemma foo (n:Box nat) : (* constant, folded, unfolded *) trip (ubox _ n) (unbox _ n) (match n with box _ n => n end). Proof. simpl. (* remove extra letins introduced by match compilation *) cbv delta [ubox]. show_goal. Set Printing Unfolded Projection As Match. show_goal. Set Printing Projections. show_goal. Unset Printing Unfolded Projection As Match. show_goal. Arguments unbox {_}. show_goal. Set Printing Unfolded Projection As Match. show_goal. Unset Printing Projections. show_goal. Abort. rocq-9.2.0/test-suite/output/PrintPrimitives.out000066400000000000000000000002111516144147600220400ustar00rootroot00000000000000*** [ string = #string_type : Set ] *** [ cat = #string_cat : string -> string -> string ] Arguments cat (_ _)%_pstring_scope rocq-9.2.0/test-suite/output/PrintPrimitives.v000066400000000000000000000000651516144147600215050ustar00rootroot00000000000000Require Import PrimString. Print string. Print cat. rocq-9.2.0/test-suite/output/PrintSecDeps.out000066400000000000000000000013301516144147600212360ustar00rootroot00000000000000bla : Prop bla is not universe polymorphic bla uses section variables A x. bla is transparent Expands to: Constant PrintSecDeps.S.bla Declared in library PrintSecDeps, line 6, characters 13-16 bli : nat bli is not universe polymorphic bli is transparent Expands to: Constant PrintSecDeps.S.bli Declared in library PrintSecDeps, line 10, characters 13-16 bla : forall A : Type, A -> Prop bla is not universe polymorphic Arguments bla A%_type_scope x bla is transparent Expands to: Constant PrintSecDeps.bla Declared in library PrintSecDeps, line 6, characters 13-16 bli : nat bli is not universe polymorphic bli is transparent Expands to: Constant PrintSecDeps.bli Declared in library PrintSecDeps, line 10, characters 13-16 rocq-9.2.0/test-suite/output/PrintSecDeps.v000066400000000000000000000002711516144147600206770ustar00rootroot00000000000000 Section S. Variables (A:Type) (x:A) (y:A). Let z := x. Definition bla := x = z. About bla. Let zz := 0. Definition bli := zz. About bli. End S. About bla. About bli. rocq-9.2.0/test-suite/output/PrintUnivsSubgraph.out000066400000000000000000000003101516144147600225050ustar00rootroot00000000000000Set < i < j i < j (because i <(from foo) j) Set < i < k i < k (because i <(from foo) j <(from connect) l <(from baz) k) Set < u < v v < u (because v <(from PrintUnivsSubgraph.T.foo) u) rocq-9.2.0/test-suite/output/PrintUnivsSubgraph.v000066400000000000000000000006621516144147600221550ustar00rootroot00000000000000 Universes i j k l. Definition foo : Type@{j} := Type@{i}. Definition baz : Type@{k} := Type@{l}. Print Universes Subgraph(i j). (* should print [i < j], not [l < k] (and not prelude universes) *) Definition connect : Type@{l} := Type@{j}. Print Universes Subgraph (i k). Universes u v. Module Type T. Definition foo : Type@{u} := Type@{v}. End T. Print Universes Subgraph (u v). (* T.foo does not exist but we don't fail *) rocq-9.2.0/test-suite/output/PrintingCoercion.out000066400000000000000000000011421516144147600221500ustar00rootroot00000000000000a : C : C File "./output/PrintingCoercion.v", line 25, characters 6-43: The command has indeed failed with message: h' cannot be added with locality global. File "./output/PrintingCoercion.v", line 26, characters 6-46: The command has indeed failed with message: h' cannot be added with locality export. g (f a) : D : D File "./output/PrintingCoercion.v", line 30, characters 6-35: The command has indeed failed with message: h is not a coercion. h' (g (f a)) : D : D g a : C : C h (g (f a)) : D : D f a : C : C f a : C : C a : C : C a : D : D h (g a) : D : D rocq-9.2.0/test-suite/output/PrintingCoercion.v000066400000000000000000000016221516144147600216110ustar00rootroot00000000000000 Parameter A B C D : Type. Parameter f : A -> B. Parameter g : B -> C. Parameter h : C -> D. Coercion f : A >-> B. Coercion g : B >-> C. Parameter a : A. Check a : C. Module M. Module N. Section S. Add Printing Coercion f. (* implicit local *) #[export] Add Printing Coercion g. Variable h' : C -> D. Coercion h' : C >-> D. Fail Global Add Printing Coercion h'. Fail #[export] Add Printing Coercion h'. Check a : D. Fail Add Printing Coercion h. Add Printing Coercion h'. Check a : D. End S. Check a : C. Global Add Printing Coercion f. Coercion h : C >-> D. Add Printing Coercion h. (* implicit export *) Check a : D. End N. Check a : C. Remove Printing Coercion f. (* implicit export *) End M. Check a : C. Import M. Check a : C. Import(coercions) N. Check a : D. Import(options) N. Check a : D. rocq-9.2.0/test-suite/output/PrintingNamedGoals.out000066400000000000000000000000651516144147600224240ustar00rootroot000000000000001 goal (?G) ============================ True rocq-9.2.0/test-suite/output/PrintingNamedGoals.v000066400000000000000000000000661516144147600220630ustar00rootroot00000000000000Goal True. Proof. refine ?[G]. Show. auto. Qed. rocq-9.2.0/test-suite/output/PrintingParentheses.out000066400000000000000000000030411516144147600226700ustar00rootroot00000000000000((1 + (2 * 3), 4), 5) : (nat * nat) * nat mult_n_Sm = fun n m : nat => nat_ind (fun n0 : nat => ((n0 * m) + n0) = (n0 * (S m))) (eq_refl : ((0 * m) + 0) = (0 * (S m))) (fun (p : nat) (H : ((p * m) + p) = (p * (S m))) => (let n0 := p * (S m) in match H in _ = n1 return ((m + (p * m)) + (S p)) = (S (m + n1)) with | eq_refl => eq_ind (S ((m + (p * m)) + p)) (fun n1 : nat => n1 = (S (m + ((p * m) + p)))) (eq_S ((m + (p * m)) + p) (m + ((p * m) + p)) (nat_ind (fun n1 : nat => ((n1 + (p * m)) + p) = (n1 + ((p * m) + p))) (eq_refl : ((0 + (p * m)) + p) = (0 + ((p * m) + p))) ((fun (n1 : nat) (H0 : ((n1 + (p * m)) + p) = (n1 + ((p * m) + p))) => f_equal_nat nat S ((n1 + (p * m)) + p) (n1 + ((p * m) + p)) H0) : forall n1 : nat, (((n1 + (p * m)) + p) = (n1 + ((p * m) + p))) -> ((((S n1) + (p * m)) + p) = ((S n1) + ((p * m) + p)))) m : ((m + (p * m)) + p) = (m + ((p * m) + p)))) ((m + (p * m)) + (S p)) (plus_n_Sm (m + (p * m)) p) end) : (((S p) * m) + (S p)) = ((S p) * (S m))) n : forall n m : nat, ((n * m) + n) = (n * (S m)) Arguments mult_n_Sm (n m)%_nat_scope 1 :: (2 :: [3; 4]) : list nat {0 = 1} + {2 <= (4 + 5)} : Set forall x y z : nat, [(x + y) + z] = [x + y + z] : Prop forall x y z : nat, [(x + y) + z] = [x + (y + z)] : Prop rocq-9.2.0/test-suite/output/PrintingParentheses.v000066400000000000000000000014131516144147600223270ustar00rootroot00000000000000Module Test1. Set Printing Parentheses. Check (1+2*3,4,5). Print mult_n_Sm. End Test1. Require Import TestSuite.list. Module Test2. Set Printing Parentheses. Import ListNotations. Check [1;2;3;4]. Check {0=1}+{2<=4+5}. End Test2. (* A test with custom entries *) Module CustomEntry. Declare Custom Entry myconstr. Notation "[ x ]" := x (x custom myconstr at level 6). Notation "x + y" := (Nat.add x y) (in custom myconstr at level 5, right associativity). Notation "( x )" := x (in custom myconstr at level 0). Notation "x" := x (in custom myconstr at level 0, x ident). Unset Printing Parentheses. Check forall x y z : nat, [ (x + y) + z ] = [ x + (y + z) ]. Set Printing Parentheses. Check forall x y z : nat, [ (x + y) + z ] = [ x + (y + z) ]. End CustomEntry. rocq-9.2.0/test-suite/output/Projections.out000066400000000000000000000012121516144147600211710ustar00rootroot00000000000000fun S : store => S.(store_funcs) : store -> host_func a = fun A : Type => let B := A in fun (C : Type) (u : U A C) => (A, B, C, c _ _ u) : forall A : Type, let B := A in forall C : Type, U A C -> Type * Type * Type * (B * A * C) a is a projection of U Arguments a (A C)%_type_scope u Record U (A : Type) (B : Type := A) (C : Type) : Type := Build_U { c : (B * A * C)%type; a := (A, B, C, c); b : a = a }. U has primitive projections with eta conversion. Arguments U (A C)%_type_scope Arguments Build_U (A C)%_type_scope c b Arguments c (A C)%_type_scope u Arguments a (A C)%_type_scope u Arguments b (A C)%_type_scope u rocq-9.2.0/test-suite/output/Projections.v000066400000000000000000000006131516144147600206330ustar00rootroot00000000000000 Set Printing Projections. Set Primitive Projections. Class HostFunction := host_func : Type. Section store. Context `{HostFunction}. Record store := { store_funcs : host_func }. End store. Check (fun (S:@store nat) => S.(store_funcs)). Module LocalDefUnfolding. Unset Printing Projections. Record U A (B:=A) C := {c:B*A*C;a:=(A,B,C,c);b:a=a}. Print a. Print b. End LocalDefUnfolding. rocq-9.2.0/test-suite/output/ProofUsingClashWarning.out000066400000000000000000000023541516144147600232760ustar00rootroot00000000000000File "./output/ProofUsingClashWarning.v", line 3, characters 2-39: Warning: clashing_name was already a defined Variable, the name clashing_name will refer to Collection when executing "Proof using" command. [variable-shadowing,deprecated-since-8.15,deprecated,default] File "./output/ProofUsingClashWarning.v", line 6, characters 2-39: Warning: New Collection definition of redefined_col shadows the previous one. [collection-redefinition,deprecated-since-8.15,deprecated,default] File "./output/ProofUsingClashWarning.v", line 8, characters 2-34: The command has indeed failed with message: "All" is a predefined collection containing all variables. It can't be redefined. File "./output/ProofUsingClashWarning.v", line 11, characters 2-28: Warning: clashing_name is both name of a Collection and Variable, Collection clashing_name takes precedence over Variable. [collection-precedence,deprecated-since-8.15,deprecated,default] File "./output/ProofUsingClashWarning.v", line 16, characters 2-18: Warning: Variable All is shadowed by Collection named All containing all variables. [all-collection-precedence,deprecated-since-8.15,deprecated,default] foo : bool -> True : bool -> True bar : bool -> nat -> unit -> True : bool -> nat -> unit -> True rocq-9.2.0/test-suite/output/ProofUsingClashWarning.v000066400000000000000000000006761516144147600227410ustar00rootroot00000000000000Section Test. Variables (bool_var : bool) (clashing_name : nat) (All : unit). Collection clashing_name := bool_var. Collection redefined_col := bool_var. Collection redefined_col := bool_var. Fail Collection All := bool_var. Lemma foo : True. Proof using clashing_name. trivial. Qed. Lemma bar : True. Proof using All. trivial. Qed. End Test. Check foo : bool -> True. Check bar : bool -> nat -> unit -> True. rocq-9.2.0/test-suite/output/Qf_deprecated.out000066400000000000000000000017371516144147600214340ustar00rootroot00000000000000File "./output/Qf_deprecated.v", line 10, characters 17-18: Warning: Reference x is deprecated. Use M.y instead. [deprecated-reference,deprecated,default] Quickfix: Replace File "./output/Qf_deprecated.v", line 10, characters 17-18 with M.y File "./output/Qf_deprecated.v", line 13, characters 18-19: Warning: Reference x is deprecated. Use M.y instead. [deprecated-reference,deprecated,default] Quickfix: Replace File "./output/Qf_deprecated.v", line 13, characters 18-19 with M.y File "./output/Qf_deprecated.v", line 25, characters 17-18: Warning: Notation v is deprecated. Use M1.w instead. [deprecated-syntactic-definition,deprecated,default] Quickfix: Replace File "./output/Qf_deprecated.v", line 25, characters 17-18 with M1.w File "./output/Qf_deprecated.v", line 27, characters 0-69: The command has indeed failed with message: Attribute use not allowed File "./output/Qf_deprecated.v", line 30, characters 22-33: The command has indeed failed with message: nonexisting not found. rocq-9.2.0/test-suite/output/Qf_deprecated.v000066400000000000000000000007121516144147600210620ustar00rootroot00000000000000Module M. Definition y := 4. End M. Import M. #[deprecated(use=y)] Definition x := 3. Module N. Definition y := 5. End N. Import N. Definition d1 := x = 3. Module M1. Abbreviation w := x. End M1. Import M1. #[deprecated(use=w)] Abbreviation v := 3. Module M2. Abbreviation w := 5. End M2. Import M2. Definition d2 := v = 3. Fail #[deprecated(use=w)] Notation "a +++ b" := (a + b) (at level 2). Fail #[deprecated(use=nonexisting)] Definition y := 2. rocq-9.2.0/test-suite/output/Qf_end.out000066400000000000000000000002731516144147600200740ustar00rootroot00000000000000File "./output/Qf_end.v", line 2, characters 4-5: Error: Last block to end has name A. Quickfix: Replace File "./output/Qf_end.v", line 2, characters 4-5 with A coqc exited with code 1 rocq-9.2.0/test-suite/output/Qf_end.v000066400000000000000000000000211516144147600175210ustar00rootroot00000000000000Module A. End B. rocq-9.2.0/test-suite/output/Qf_extraction.out000066400000000000000000000010151516144147600215010ustar00rootroot00000000000000File "./output/Qf_extraction.v", line 5, characters 11-14: Warning: The name nat is ambiguous, do you mean module Qf_extraction.nat or object Corelib.Init.Datatypes.nat ? First choice is assumed, for the second one please use fully qualified name. [extraction-ambiguous-name,extraction,default] Quickfix: Replace File "./output/Qf_extraction.v", line 5, characters 11-14 with Qf_extraction.nat Replace File "./output/Qf_extraction.v", line 5, characters 11-14 with Corelib.Init.Datatypes.nat module Coq_nat = struct end rocq-9.2.0/test-suite/output/Qf_extraction.v000066400000000000000000000001021516144147600211330ustar00rootroot00000000000000Require Import Extraction. Module nat. End nat. Extraction nat. rocq-9.2.0/test-suite/output/Qf_stdlib.out000066400000000000000000000015031516144147600206040ustar00rootroot00000000000000File "./output/Qf_stdlib.v", line 16, characters 6-22: Warning: Coq.Init.Nat.add has been replaced by Corelib.Init.Nat.add. [deprecated-dirpath-Coq,deprecated-since-9.0,deprecated,default] Quickfix: Replace File "./output/Qf_stdlib.v", line 16, characters 6-22 with Corelib.Init.Nat.add Nat.add : nat -> nat -> nat Nat.add is not universe polymorphic Arguments Nat.add (n m)%_nat_scope Nat.add is transparent Expands to: Constant Corelib.Init.Nat.add Declared in library Corelib.Init.Nat, line 47, characters 9-12 File "./output/Qf_stdlib.v", line 17, characters 6-22: Warning: Coq.Init.Nat.add has been replaced by Corelib.Init.Nat.add. [deprecated-dirpath-Coq,deprecated-since-9.0,deprecated,default] Quickfix: Replace File "./output/Qf_stdlib.v", line 17, characters 6-22 with Corelib.Init.Nat.add Nat.add : nat -> nat -> nat rocq-9.2.0/test-suite/output/Qf_stdlib.v000066400000000000000000000011651516144147600202460ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "off"); -*- *) (* async proofs off because the output order ends up different with and without async *) (* Example from coq-lsp: we need to test 3 methods where the quickfix can come from for the Coq -> Stdlib transition: - Coq appearing in require (tested in line 2 of code) - Coq appearing in identifiers (tested in Check and Line 1) - Coq being looked up via nametab (tested in About) *) Require Import Corelib.ssr.ssrbool. From Corelib Require Import ssreflect ssrbool. (* Note: this tests the two different lookup modes *) About Coq.Init.Nat.add. Check Coq.Init.Nat.add. rocq-9.2.0/test-suite/output/RecognizePluginWarning.out000066400000000000000000000000001516144147600233160ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/RecognizePluginWarning.v000066400000000000000000000004301516144147600227630ustar00rootroot00000000000000(* -*- 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 plugins are not known at command line parsing time. *) rocq-9.2.0/test-suite/output/Record.out000066400000000000000000000060231516144147600201150ustar00rootroot00000000000000{| field := 5 |} : test {| field := 5 |} : test {| field_r := 5 |} : test_r build_c 5 : test_c build 5 : test build 5 : test {| field_r := 5 |} : test_r build_c 5 : test_c fun '(C _ p) => p : N -> True fun '{| T := T |} => T : N -> Type fun '(C T p) => (T, p) : N -> Type * True fun '{| q := p |} => p : M -> True fun '{| U := T |} => T : M -> Type fun '{| U := T; q := p |} => (T, p) : M -> Type * True fun '{| U := T; a := a; q := p |} => (T, p, a) : M -> Type * True * nat fun '{| U := T; a := a; q := p |} => (T, p, a) : M -> Type * True * nat {| a := 0; b := 0 |} : T fun '{| |} => 0 : LongModuleName.test -> nat = {| a := {| LongModuleName.long_field_name0 := 0; LongModuleName.long_field_name1 := 1; LongModuleName.long_field_name2 := 2; LongModuleName.long_field_name3 := 3 |}; b := fun '{| LongModuleName.long_field_name0 := a; LongModuleName.long_field_name1 := b; LongModuleName.long_field_name2 := c; LongModuleName.long_field_name3 := d |} => (a, b, c, d) |} : T = {| a := {| long_field_name0 := 0; long_field_name1 := 1; long_field_name2 := 2; long_field_name3 := 3 |}; b := fun '{| long_field_name0 := a; long_field_name1 := b; long_field_name2 := c; long_field_name3 := d |} => (a, b, c, d) |} : T fun x : R => 0 +++ x.(field) 0 : R -> nat File "./output/Record.v", line 85, characters 23-24: The command has indeed failed with message: Projection f expected 1 explicit parameter. File "./output/Record.v", line 93, characters 2-40: Warning: The record squashed could not be defined as a primitive record because it is squashed. [non-primitive-record,records,default] File "./output/Record.v", line 93, characters 30-31: Warning: x cannot be defined because it is informative and squashed is not. [cannot-define-projection,records,default] File "./output/Record.v", line 95, characters 2-31: Warning: The record noprojs could not be defined as a primitive record because it has no projections. [non-primitive-record,records,default] norelevantprojs : SProp -> Prop norelevantprojs is not universe polymorphic norelevantprojs is in Prop but its eliminators are declared dependent by default norelevantprojs has primitive projections without eta conversion. Arguments norelevantprojs A%_type_scope Expands to: Inductive Record.WhyNotPrim.norelevantprojs Declared in library Record, line 97, characters 9-24 File "./output/Record.v", line 101, characters 2-33: Warning: The record anonproj could not be defined as a primitive record because it has an anonymous projection. [non-primitive-record,records,default] rocq-9.2.0/test-suite/output/Record.v000066400000000000000000000047141516144147600175600ustar00rootroot00000000000000Record test := build { field : nat }. Record test_r := build_r { field_r : nat }. Record test_c := build_c { field_c : nat }. Add Printing Constructor test_c. Add Printing Record test_r. Set Printing Records. Check build 5. Check {| field := 5 |}. Check build_r 5. Check build_c 5. Unset Printing Records. Check build 5. Check {| field := 5 |}. Check build_r 5. Check build_c 5. Set Printing Records. Record N := C { T : Type; _ : True }. Check fun x:N => let 'C _ p := x in p. Check fun x:N => let 'C T _ := x in T. Check fun x:N => let 'C T p := x in (T,p). Record M := D { U : Type; a := 0; q : True }. Check fun x:M => let 'D T _ p := x in p. Check fun x:M => let 'D T _ p := x in T. Check fun x:M => let 'D T p := x in (T,p). Check fun x:M => let 'D T a p := x in (T,p,a). Check fun x:M => let '{|U:=T;a:=a;q:=p|} := x in (T,p,a). Module FormattingIssue13142. Record T {A B} := {a:A;b:B}. Module LongModuleName. Record test := { long_field_name0 : nat; long_field_name1 : nat; long_field_name2 : nat; long_field_name3 : nat }. End LongModuleName. Definition c := {| LongModuleName.long_field_name0 := 0; LongModuleName.long_field_name1 := 1; LongModuleName.long_field_name2 := 2; LongModuleName.long_field_name3 := 3 |}. Definition d := fun '{| LongModuleName.long_field_name0 := a; LongModuleName.long_field_name1 := b; LongModuleName.long_field_name2 := c; LongModuleName.long_field_name3 := d |} => (a,b,c,d). Check {|a:=0;b:=0|}. Check fun '{| LongModuleName.long_field_name0:=_ |} => 0. Eval compute in {|a:=c;b:=d|}. Import LongModuleName. Eval compute in {|a:=c;b:=d|}. End FormattingIssue13142. Module ProjectionPrinting. Notation "a +++ b" := (a * b) (at level 40, format "'[v' a '/' +++ '/' b ']'"). Record R := { field : nat -> nat }. Set Printing Projections. Check fun x => 0 +++ x.(field) 0. End ProjectionPrinting. Module RecordImplicitParameters. (* Check that implicit parameters are treated independently of extra implicit arguments (at some time they did not and it was failing at typing time) *) Record R A := { f : A -> A }. Fail Check fun x => x.(f). End RecordImplicitParameters. Module WhyNotPrim. Set Primitive Projections. Record squashed : Prop := { x : nat }. Record noprojs := { y := 0 }. Record norelevantprojs (A:SProp) := { z : A }. About norelevantprojs. Record anonproj := { _ : nat }. End WhyNotPrim. rocq-9.2.0/test-suite/output/RecordFieldErrors.out000066400000000000000000000017451516144147600222640ustar00rootroot00000000000000File "./output/RecordFieldErrors.v", line 10, characters 14-18: The command has indeed failed with message: unit: Not a projection. File "./output/RecordFieldErrors.v", line 13, characters 14-18: The command has indeed failed with message: unit: Not a projection. File "./output/RecordFieldErrors.v", line 17, characters 14-48: The command has indeed failed with message: This record contains fields of both t and t'. File "./output/RecordFieldErrors.v", line 21, characters 14-18: The command has indeed failed with message: unit: Not a projection. File "./output/RecordFieldErrors.v", line 25, characters 14-48: The command has indeed failed with message: This record defines several times the field foo. File "./output/RecordFieldErrors.v", line 29, characters 14-75: The command has indeed failed with message: This record defines several times the field unit. File "./output/RecordFieldErrors.v", line 37, characters 14-18: The command has indeed failed with message: unit: Not a projection. rocq-9.2.0/test-suite/output/RecordFieldErrors.v000066400000000000000000000016651516144147600217230ustar00rootroot00000000000000(** Check that various errors in record fields are reported with the correct underlying issue. *) Record t := { foo: unit }. Record t' := { bar: unit }. Fail Check {| unit := tt |}. (* unit: Not a projection. *) Fail Check {| unit := tt; foo := tt |}. (* unit: Not a projection. *) Fail Check {| foo := tt; bar := tt |}. (* This record contains fields of both t and t'. *) Fail Check {| unit := tt; unit := tt |}. (* unit: Not a projection. *) Fail Check {| foo := tt; foo := tt |}. (* This record defines several times the field foo. *) Fail Check {| foo := tt; unit := tt; unit := tt |}. (* This is slightly wrong (would prefer "unit: Not a projection."), but it's acceptable and seems an unlikely mistake. *) (* This record defines several times the field unit. *) Fail Check {| foo := tt; unit := tt |}. (* unit: Not a projection. *) rocq-9.2.0/test-suite/output/RecordMissingField.out000066400000000000000000000013631516144147600224150ustar00rootroot00000000000000File "./output/RecordMissingField.v", line 6, characters 0-80: The command has indeed failed with message: The following term contains unresolved implicit arguments: (fun p : point2d => {| x2p := x2p p + 1; y2p := ?y2p |}) More precisely: - ?y2p: Cannot infer field y2p of record point2d in environment: p : point2d File "./output/RecordMissingField.v", line 11, characters 0-93: The command has indeed failed with message: The following term contains unresolved implicit arguments: (fun p : point2d => {| x2p := x2p p + (fun n : nat => ?n) 1; y2p := ?y2p |}) More precisely: - ?n: Cannot infer this placeholder of type "nat" in environment: p : point2d n : nat - ?y2p: Cannot infer field y2p of record point2d in environment: p : point2d rocq-9.2.0/test-suite/output/RecordMissingField.v000066400000000000000000000007261516144147600220550ustar00rootroot00000000000000(** Check for error message when missing a record field. Error message should contain missing field, and the inferred type of the record **) Record point2d := mkPoint { x2p: nat; y2p: nat }. Fail Definition increment_x (p: point2d) : point2d := {| x2p := x2p p + 1; |}. (* Here there is also an unresolved implicit, which should give an understadable error as well *) Fail Definition increment_x (p: point2d) : point2d := {| x2p := x2p p + (fun n => _) 1; |}. rocq-9.2.0/test-suite/output/RecordProjParameter.out000066400000000000000000000026621516144147600226160ustar00rootroot00000000000000t1 : Atype -> forall a : Type, a t1 is not universe polymorphic t1 is a projection of Atype Arguments t1 a0 a%_type_scope t1 is transparent Expands to: Constant RecordProjParameter.t1 Declared in library RecordProjParameter, line 2, characters 4-6 t3 : forall a0 : Atype, t2 a0 t3 is not universe polymorphic t3 is a projection of Atype Arguments t3 a0 t3 is transparent Expands to: Constant RecordProjParameter.t3 Declared in library RecordProjParameter, line 4, characters 4-6 u1 : Btype -> forall b b0 : Type, b * b0 u1 is not universe polymorphic u1 is a projection of Btype Arguments u1 b1 (b b0)%_type_scope u1 is transparent Expands to: Constant RecordProjParameter.u1 Declared in library RecordProjParameter, line 9, characters 4-6 u3 : forall b1 : Btype, u2 b1 u3 is not universe polymorphic u3 is a projection of Btype Arguments u3 b1 u3 is transparent Expands to: Constant RecordProjParameter.u3 Declared in library RecordProjParameter, line 11, characters 4-6 v1 : Ctype -> forall c0 : Type, c0 v1 is not universe polymorphic v1 is a projection of Ctype Arguments v1 c c0%_type_scope v1 is transparent Expands to: Constant RecordProjParameter.v1 Declared in library RecordProjParameter, line 16, characters 4-6 v3 : forall c : Ctype, v2 c v3 is not universe polymorphic v3 is a projection of Ctype Arguments v3 c v3 is transparent Expands to: Constant RecordProjParameter.v3 Declared in library RecordProjParameter, line 18, characters 4-6 rocq-9.2.0/test-suite/output/RecordProjParameter.v000066400000000000000000000005111516144147600222430ustar00rootroot00000000000000Record Atype : Type := { t1 : forall (a : Type), a ; t2 : Type ; t3 : t2 }. About t1. About t3. Record Btype : Type := { u1 : forall (b : Type) (b0 : Type), b * b0 ; u2 : Type ; u3 : u2 }. About u1. About u3. Record Ctype : Type := { v1 : forall (c0 : Type), c0 ; v2 : Type ; v3 : v2 }. About v1. About v3. rocq-9.2.0/test-suite/output/RecursiveAssumptions.out000066400000000000000000000001641516144147600231140ustar00rootroot00000000000000Axioms: B : A -> Prop A : Prop Axioms: R : forall x : P, Q x Q : P -> Prop P : Type Closed under the global context rocq-9.2.0/test-suite/output/RecursiveAssumptions.v000066400000000000000000000011611516144147600225500ustar00rootroot00000000000000(* Test for Print Assumptions with recursive type traversal *) (* Test case 1: Simple axiom depending on another axiom in its type *) Axiom A : Prop. Axiom B : A -> Prop. Definition C := B. (* Print Assumptions now includes both B and A *) Print Assumptions C. (* Test case 2: Axiom with type depending on function type *) Axiom P : Type. Axiom Q : P -> Prop. Axiom R : forall x, Q x. (* Testing with a theorem *) Lemma test : forall x, Q x. Proof. exact R. Qed. Print Assumptions test. (* Test case 3: No axioms - should show "Closed under the global context" *) Definition simple := 1 + 1. Print Assumptions simple. rocq-9.2.0/test-suite/output/SchemeNames.out000066400000000000000000000574441516144147600211040ustar00rootroot00000000000000File "./output/SchemeNames.v", line 14, characters 2-47: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Prop" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Prop" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 15, characters 2-46: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Set" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Set" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 16, characters 2-47: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Type" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Type" because strict proofs can be eliminated only to build strict proofs. fooSProp_inds : forall P : fooSProp -> SProp, P aSP -> P bSP -> forall f : fooSProp, P f fooSProp_inds is not universe polymorphic Arguments fooSProp_inds P%_function_scope aSP bSP f fooSProp_inds is transparent Expands to: Constant SchemeNames.fooSProp_inds Declared in library SchemeNames, line 13, characters 7-48 File "./output/SchemeNames.v", line 23, characters 2-48: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Prop" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Prop" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 24, characters 2-47: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Set" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Set" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 25, characters 2-48: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Type" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Type" because strict proofs can be eliminated only to build strict proofs. fooSProp_inds_nodep : forall P : SProp, P -> P -> fooSProp -> P fooSProp_inds_nodep is not universe polymorphic Arguments fooSProp_inds_nodep P%_type_scope aSP bSP f fooSProp_inds_nodep is transparent Expands to: Constant SchemeNames.fooSProp_inds_nodep Declared in library SchemeNames, line 22, characters 7-49 File "./output/SchemeNames.v", line 32, characters 2-49: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Prop" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Prop" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 33, characters 2-48: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Set" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Set" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 34, characters 2-49: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Type" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Type" because strict proofs can be eliminated only to build strict proofs. fooSProp_cases : forall P : fooSProp -> SProp, P aSP -> P bSP -> forall f : fooSProp, P f fooSProp_cases is not universe polymorphic Arguments fooSProp_cases P%_function_scope aSP bSP f fooSProp_cases is transparent Expands to: Constant SchemeNames.fooSProp_cases Declared in library SchemeNames, line 31, characters 7-50 File "./output/SchemeNames.v", line 41, characters 2-42: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Prop" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Prop" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 42, characters 2-41: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Set" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Set" because strict proofs can be eliminated only to build strict proofs. File "./output/SchemeNames.v", line 43, characters 2-42: The command has indeed failed with message: Incorrect elimination in the inductive type "fooSProp": the return type has sort "Type" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Type" because strict proofs can be eliminated only to build strict proofs. fooSProp_cases_nodep : forall P : SProp, P -> P -> fooSProp -> P fooSProp_cases_nodep is not universe polymorphic Arguments fooSProp_cases_nodep P%_type_scope aSP bSP f fooSProp_cases_nodep is transparent Expands to: Constant SchemeNames.fooSProp_cases_nodep Declared in library SchemeNames, line 40, characters 7-43 File "./output/SchemeNames.v", line 49, characters 2-36: The command has indeed failed with message: Cannot extract computational content from proposition "fooSProp". File "./output/SchemeNames.v", line 61, characters 2-45: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Set" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Set" because proofs can be eliminated only to build proofs. File "./output/SchemeNames.v", line 62, characters 2-46: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Type" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Type" because proofs can be eliminated only to build proofs. fooProp_inds_dep : forall P : fooProp -> SProp, P aP -> P bP -> forall f : fooProp, P f fooProp_inds_dep is not universe polymorphic Arguments fooProp_inds_dep P%_function_scope aP bP f fooProp_inds_dep is transparent Expands to: Constant SchemeNames.fooProp_inds_dep Declared in library SchemeNames, line 59, characters 7-47 fooProp_ind_dep : forall P : fooProp -> Prop, P aP -> P bP -> forall f : fooProp, P f fooProp_ind_dep is not universe polymorphic Arguments fooProp_ind_dep P%_function_scope aP bP f fooProp_ind_dep is transparent Expands to: Constant SchemeNames.fooProp_ind_dep Declared in library SchemeNames, line 60, characters 7-46 File "./output/SchemeNames.v", line 71, characters 2-46: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Set" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Set" because proofs can be eliminated only to build proofs. File "./output/SchemeNames.v", line 72, characters 2-47: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Type" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Type" because proofs can be eliminated only to build proofs. fooProp_inds : forall P : SProp, P -> P -> fooProp -> P fooProp_inds is not universe polymorphic Arguments fooProp_inds P%_type_scope aP bP f fooProp_inds is transparent Expands to: Constant SchemeNames.fooProp_inds Declared in library SchemeNames, line 69, characters 7-48 fooProp_ind : forall P : Prop, P -> P -> fooProp -> P fooProp_ind is not universe polymorphic Arguments fooProp_ind P%_type_scope aP bP f fooProp_ind is transparent Expands to: Constant SchemeNames.fooProp_ind Declared in library SchemeNames, line 70, characters 7-47 File "./output/SchemeNames.v", line 81, characters 2-47: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Set" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Set" because proofs can be eliminated only to build proofs. File "./output/SchemeNames.v", line 82, characters 2-48: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Type" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Type" because proofs can be eliminated only to build proofs. fooProp_cases_dep : forall P : fooProp -> SProp, P aP -> P bP -> forall f : fooProp, P f fooProp_cases_dep is not universe polymorphic Arguments fooProp_cases_dep P%_function_scope aP bP f fooProp_cases_dep is transparent Expands to: Constant SchemeNames.fooProp_cases_dep Declared in library SchemeNames, line 79, characters 7-49 fooProp_case_dep : forall P : fooProp -> Prop, P aP -> P bP -> forall f : fooProp, P f fooProp_case_dep is not universe polymorphic Arguments fooProp_case_dep P%_function_scope aP bP f fooProp_case_dep is transparent Expands to: Constant SchemeNames.fooProp_case_dep Declared in library SchemeNames, line 80, characters 7-48 File "./output/SchemeNames.v", line 91, characters 2-40: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Set" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Set" because proofs can be eliminated only to build proofs. File "./output/SchemeNames.v", line 92, characters 2-41: The command has indeed failed with message: Incorrect elimination in the inductive type "fooProp": the return type has sort "Type" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Type" because proofs can be eliminated only to build proofs. fooProp_cases : forall P : SProp, P -> P -> fooProp -> P fooProp_cases is not universe polymorphic Arguments fooProp_cases P%_type_scope aP bP f fooProp_cases is transparent Expands to: Constant SchemeNames.fooProp_cases Declared in library SchemeNames, line 89, characters 7-42 fooProp_case : forall P : Prop, P -> P -> fooProp -> P fooProp_case is not universe polymorphic Arguments fooProp_case P%_type_scope aP bP f fooProp_case is transparent Expands to: Constant SchemeNames.fooProp_case Declared in library SchemeNames, line 90, characters 7-41 File "./output/SchemeNames.v", line 99, characters 2-35: The command has indeed failed with message: Cannot extract computational content from proposition "fooProp". fooSet_inds : forall P : fooSet -> SProp, P aS -> P bS -> forall f : fooSet, P f fooSet_inds is not universe polymorphic Arguments fooSet_inds P%_function_scope aS bS f fooSet_inds is transparent Expands to: Constant SchemeNames.fooSet_inds Declared in library SchemeNames, line 109, characters 2-41 fooSet_ind : forall P : fooSet -> Prop, P aS -> P bS -> forall f : fooSet, P f fooSet_ind is not universe polymorphic Arguments fooSet_ind P%_function_scope aS bS f fooSet_ind is transparent Expands to: Constant SchemeNames.fooSet_ind Declared in library SchemeNames, line 110, characters 2-40 fooSet_rec : forall P : fooSet -> Set, P aS -> P bS -> forall f : fooSet, P f fooSet_rec is not universe polymorphic Arguments fooSet_rec P%_function_scope aS bS f fooSet_rec is transparent Expands to: Constant SchemeNames.fooSet_rec Declared in library SchemeNames, line 111, characters 2-39 fooSet_rect : forall P : fooSet -> Type, P aS -> P bS -> forall f : fooSet, P f fooSet_rect is not universe polymorphic Arguments fooSet_rect P%_function_scope aS bS f fooSet_rect is transparent Expands to: Constant SchemeNames.fooSet_rect Declared in library SchemeNames, line 112, characters 2-40 fooSet_inds_nodep : forall P : SProp, P -> P -> fooSet -> P fooSet_inds_nodep is not universe polymorphic Arguments fooSet_inds_nodep P%_type_scope aS bS f fooSet_inds_nodep is transparent Expands to: Constant SchemeNames.fooSet_inds_nodep Declared in library SchemeNames, line 121, characters 2-42 fooSet_ind_nodep : forall P : Prop, P -> P -> fooSet -> P fooSet_ind_nodep is not universe polymorphic Arguments fooSet_ind_nodep P%_type_scope aS bS f fooSet_ind_nodep is transparent Expands to: Constant SchemeNames.fooSet_ind_nodep Declared in library SchemeNames, line 122, characters 2-41 fooSet_rec_nodep : forall P : Set, P -> P -> fooSet -> P fooSet_rec_nodep is not universe polymorphic Arguments fooSet_rec_nodep P%_type_scope aS bS f fooSet_rec_nodep is transparent Expands to: Constant SchemeNames.fooSet_rec_nodep Declared in library SchemeNames, line 123, characters 2-40 fooSet_rect_nodep : forall P : Type, P -> P -> fooSet -> P fooSet_rect_nodep is not universe polymorphic Arguments fooSet_rect_nodep P%_type_scope aS bS f fooSet_rect_nodep is transparent Expands to: Constant SchemeNames.fooSet_rect_nodep Declared in library SchemeNames, line 124, characters 2-41 fooSet_cases : forall P : fooSet -> SProp, P aS -> P bS -> forall f : fooSet, P f fooSet_cases is not universe polymorphic Arguments fooSet_cases P%_function_scope aS bS f fooSet_cases is transparent Expands to: Constant SchemeNames.fooSet_cases Declared in library SchemeNames, line 136, characters 2-43 fooSet_case : forall P : fooSet -> Prop, P aS -> P bS -> forall f : fooSet, P f fooSet_case is not universe polymorphic Arguments fooSet_case P%_function_scope aS bS f fooSet_case is transparent Expands to: Constant SchemeNames.fooSet_case Declared in library SchemeNames, line 137, characters 2-42 fooSet'_case : forall P : fooSet' -> Set, P aS' -> P bS' -> forall f : fooSet', P f fooSet'_case is not universe polymorphic Arguments fooSet'_case P%_function_scope aS' bS' f fooSet'_case is transparent Expands to: Constant SchemeNames.fooSet'_case Declared in library SchemeNames, line 138, characters 2-42 fooSet'_caset : forall P : fooSet' -> Type, P aS' -> P bS' -> forall f : fooSet', P f fooSet'_caset is not universe polymorphic Arguments fooSet'_caset P%_function_scope aS' bS' f fooSet'_caset is transparent Expands to: Constant SchemeNames.fooSet'_caset Declared in library SchemeNames, line 139, characters 2-43 fooSet_cases_nodep : forall P : SProp, P -> P -> fooSet -> P fooSet_cases_nodep is not universe polymorphic Arguments fooSet_cases_nodep P%_type_scope aS bS f fooSet_cases_nodep is transparent Expands to: Constant SchemeNames.fooSet_cases_nodep Declared in library SchemeNames, line 148, characters 2-36 fooSet_case_nodep : forall P : Prop, P -> P -> fooSet -> P fooSet_case_nodep is not universe polymorphic Arguments fooSet_case_nodep P%_type_scope aS bS f fooSet_case_nodep is transparent Expands to: Constant SchemeNames.fooSet_case_nodep Declared in library SchemeNames, line 149, characters 2-35 fooSet'_case_nodep : forall P : Set, P -> P -> fooSet' -> P fooSet'_case_nodep is not universe polymorphic Arguments fooSet'_case_nodep P%_type_scope aS' bS' f fooSet'_case_nodep is transparent Expands to: Constant SchemeNames.fooSet'_case_nodep Declared in library SchemeNames, line 150, characters 2-35 fooSet'_caset_nodep : forall P : Type, P -> P -> fooSet' -> P fooSet'_caset_nodep is not universe polymorphic Arguments fooSet'_caset_nodep P%_type_scope aS' bS' f fooSet'_caset_nodep is transparent Expands to: Constant SchemeNames.fooSet'_caset_nodep Declared in library SchemeNames, line 151, characters 2-36 fooSet_beq : fooSet -> fooSet -> bool fooSet_beq is not universe polymorphic Arguments fooSet_beq X Y fooSet_beq is transparent Expands to: Constant SchemeNames.fooSet_beq Declared in library SchemeNames, line 160, characters 2-29 fooSet_eq_dec : forall x y : fooSet, {x = y} + {x <> y} fooSet_eq_dec is not universe polymorphic Arguments fooSet_eq_dec x y fooSet_eq_dec is transparent Expands to: Constant SchemeNames.fooSet_eq_dec Declared in library SchemeNames, line 160, characters 2-29 internal_fooSet_dec_bl : forall x : fooSet, (fun x0 : fooSet => forall y : fooSet, fooSet_beq x0 y = true -> x0 = y) x internal_fooSet_dec_bl is not universe polymorphic Arguments internal_fooSet_dec_bl x y _ internal_fooSet_dec_bl is transparent Expands to: Constant SchemeNames.internal_fooSet_dec_bl Declared in library SchemeNames, line 160, characters 2-29 internal_fooSet_dec_lb : forall x : fooSet, (fun x0 : fooSet => forall y : fooSet, x0 = y -> fooSet_beq x0 y = true) x internal_fooSet_dec_lb is not universe polymorphic Arguments internal_fooSet_dec_lb x y _ internal_fooSet_dec_lb is transparent Expands to: Constant SchemeNames.internal_fooSet_dec_lb Declared in library SchemeNames, line 160, characters 2-29 fooType_inds : forall P : fooType -> SProp, P aT -> P bT -> forall f : fooType, P f fooType_inds is not universe polymorphic Arguments fooType_inds P%_function_scope aT bT f fooType_inds is transparent Expands to: Constant SchemeNames.fooType_inds Declared in library SchemeNames, line 175, characters 2-42 fooType_ind : forall P : fooType -> Prop, P aT -> P bT -> forall f : fooType, P f fooType_ind is not universe polymorphic Arguments fooType_ind P%_function_scope aT bT f fooType_ind is transparent Expands to: Constant SchemeNames.fooType_ind Declared in library SchemeNames, line 176, characters 2-41 fooType_rec : forall P : fooType -> Set, P aT -> P bT -> forall f : fooType, P f fooType_rec is not universe polymorphic Arguments fooType_rec P%_function_scope aT bT f fooType_rec is transparent Expands to: Constant SchemeNames.fooType_rec Declared in library SchemeNames, line 177, characters 2-40 fooType_rect : forall P : fooType -> Type, P aT -> P bT -> forall f : fooType, P f fooType_rect is not universe polymorphic Arguments fooType_rect P%_function_scope aT bT f fooType_rect is transparent Expands to: Constant SchemeNames.fooType_rect Declared in library SchemeNames, line 178, characters 2-41 fooType_inds_nodep : forall P : SProp, P -> P -> fooType -> P fooType_inds_nodep is not universe polymorphic Arguments fooType_inds_nodep P%_type_scope aT bT f fooType_inds_nodep is transparent Expands to: Constant SchemeNames.fooType_inds_nodep Declared in library SchemeNames, line 187, characters 2-43 fooType_ind_nodep : forall P : Prop, P -> P -> fooType -> P fooType_ind_nodep is not universe polymorphic Arguments fooType_ind_nodep P%_type_scope aT bT f fooType_ind_nodep is transparent Expands to: Constant SchemeNames.fooType_ind_nodep Declared in library SchemeNames, line 188, characters 2-42 fooType_rec_nodep : forall P : Set, P -> P -> fooType -> P fooType_rec_nodep is not universe polymorphic Arguments fooType_rec_nodep P%_type_scope aT bT f fooType_rec_nodep is transparent Expands to: Constant SchemeNames.fooType_rec_nodep Declared in library SchemeNames, line 189, characters 2-41 fooType_rect_nodep : forall P : Type, P -> P -> fooType -> P fooType_rect_nodep is not universe polymorphic Arguments fooType_rect_nodep P%_type_scope aT bT f fooType_rect_nodep is transparent Expands to: Constant SchemeNames.fooType_rect_nodep Declared in library SchemeNames, line 190, characters 2-42 fooType_cases : forall P : fooType -> SProp, P aT -> P bT -> forall f : fooType, P f fooType_cases is not universe polymorphic Arguments fooType_cases P%_function_scope aT bT f fooType_cases is transparent Expands to: Constant SchemeNames.fooType_cases Declared in library SchemeNames, line 202, characters 2-44 fooType_case : forall P : fooType -> Prop, P aT -> P bT -> forall f : fooType, P f fooType_case is not universe polymorphic Arguments fooType_case P%_function_scope aT bT f fooType_case is transparent Expands to: Constant SchemeNames.fooType_case Declared in library SchemeNames, line 203, characters 2-43 fooType'_case : forall P : fooType' -> Set, P aT' -> P bT' -> forall f : fooType', P f fooType'_case is not universe polymorphic Arguments fooType'_case P%_function_scope aT' bT' f fooType'_case is transparent Expands to: Constant SchemeNames.fooType'_case Declared in library SchemeNames, line 204, characters 2-43 fooType'_caset : forall P : fooType' -> Type, P aT' -> P bT' -> forall f : fooType', P f fooType'_caset is not universe polymorphic Arguments fooType'_caset P%_function_scope aT' bT' f fooType'_caset is transparent Expands to: Constant SchemeNames.fooType'_caset Declared in library SchemeNames, line 205, characters 2-44 fooType_cases_nodep : forall P : SProp, P -> P -> fooType -> P fooType_cases_nodep is not universe polymorphic Arguments fooType_cases_nodep P%_type_scope aT bT f fooType_cases_nodep is transparent Expands to: Constant SchemeNames.fooType_cases_nodep Declared in library SchemeNames, line 214, characters 2-37 fooType_case_nodep : forall P : Prop, P -> P -> fooType -> P fooType_case_nodep is not universe polymorphic Arguments fooType_case_nodep P%_type_scope aT bT f fooType_case_nodep is transparent Expands to: Constant SchemeNames.fooType_case_nodep Declared in library SchemeNames, line 215, characters 2-36 fooType'_case_nodep : forall P : Set, P -> P -> fooType' -> P fooType'_case_nodep is not universe polymorphic Arguments fooType'_case_nodep P%_type_scope aT' bT' f fooType'_case_nodep is transparent Expands to: Constant SchemeNames.fooType'_case_nodep Declared in library SchemeNames, line 216, characters 2-36 fooType'_caset_nodep : forall P : Type, P -> P -> fooType' -> P fooType'_caset_nodep is not universe polymorphic Arguments fooType'_caset_nodep P%_type_scope aT' bT' f fooType'_caset_nodep is transparent Expands to: Constant SchemeNames.fooType'_caset_nodep Declared in library SchemeNames, line 217, characters 2-37 fooType_beq : fooType -> fooType -> bool fooType_beq is not universe polymorphic Arguments fooType_beq X Y fooType_beq is transparent Expands to: Constant SchemeNames.fooType_beq Declared in library SchemeNames, line 226, characters 2-30 fooType_eq_dec : forall x y : fooType, {x = y} + {x <> y} fooType_eq_dec is not universe polymorphic Arguments fooType_eq_dec x y fooType_eq_dec is transparent Expands to: Constant SchemeNames.fooType_eq_dec Declared in library SchemeNames, line 226, characters 2-30 internal_fooType_dec_bl : forall x : fooType, (fun x0 : fooType => forall y : fooType, fooType_beq x0 y = true -> x0 = y) x internal_fooType_dec_bl is not universe polymorphic Arguments internal_fooType_dec_bl x y _ internal_fooType_dec_bl is transparent Expands to: Constant SchemeNames.internal_fooType_dec_bl Declared in library SchemeNames, line 226, characters 2-30 internal_fooType_dec_lb : forall x : fooType, (fun x0 : fooType => forall y : fooType, x0 = y -> fooType_beq x0 y = true) x internal_fooType_dec_lb is not universe polymorphic Arguments internal_fooType_dec_lb x y _ internal_fooType_dec_lb is transparent Expands to: Constant SchemeNames.internal_fooType_dec_lb Declared in library SchemeNames, line 226, characters 2-30 F_rect : forall (f : Type) (P : F f -> Type), (forall f0 : f, P (C f f0)) -> forall f0 : F f, P f0 F_rect is not universe polymorphic Arguments F_rect f%_type_scope (P C)%_function_scope f0 F_rect is transparent Expands to: Constant SchemeNames.F_rect Declared in library SchemeNames, line 235, characters 0-30 PP_rect : forall (P : Type) (P0 : PP P -> Type), (forall p : P, P0 (D P p)) -> forall p : PP P, P0 p PP_rect is not universe polymorphic Arguments PP_rect P%_type_scope (P0 D)%_function_scope p PP_rect is transparent Expands to: Constant SchemeNames.PP_rect Declared in library SchemeNames, line 238, characters 0-32 rocq-9.2.0/test-suite/output/SchemeNames.v000066400000000000000000000155671516144147600205420ustar00rootroot00000000000000Unset Elimination Schemes. (** In this file we test the generation and naming of elimination schemes. *) (** * Schemes for inductive SProp *) (** Here is an inductive SProp. *) Inductive fooSProp : SProp := aSP | bSP. (** ** Try Induction into all Sorts *) Scheme Induction for fooSProp Sort SProp. (* fooSProp_inds *) Fail Scheme Induction for fooSProp Sort Prop. Fail Scheme Induction for fooSProp Sort Set. Fail Scheme Induction for fooSProp Sort Type. About fooSProp_inds. (** ** Try Minimality into all Sorts *) Scheme Minimality for fooSProp Sort SProp. (* fooSProp_inds_nodep *) Fail Scheme Minimality for fooSProp Sort Prop. Fail Scheme Minimality for fooSProp Sort Set. Fail Scheme Minimality for fooSProp Sort Type. About fooSProp_inds_nodep. (** ** Try Elimination into all Sorts *) Scheme Elimination for fooSProp Sort SProp. (* fooSProp_cases *) Fail Scheme Elimination for fooSProp Sort Prop. Fail Scheme Elimination for fooSProp Sort Set. Fail Scheme Elimination for fooSProp Sort Type. About fooSProp_cases. (** ** Try Case into all Sorts *) Scheme Case for fooSProp Sort SProp. (* fooSProp_cases_nodep *) Fail Scheme Case for fooSProp Sort Prop. Fail Scheme Case for fooSProp Sort Set. Fail Scheme Case for fooSProp Sort Type. About fooSProp_cases_nodep. (** ** Scheme Equality *) Fail Scheme Equality for fooSProp. (** * Schemes for inductive Prop *) (** Here is an inductive Prop. *) Inductive fooProp : Prop := aP | bP. (** ** Try Induction into all Sorts *) Scheme Induction for fooProp Sort SProp. (* fooProp_inds_dep *) Scheme Induction for fooProp Sort Prop. (* fooProp_ind_dep *) Fail Scheme Induction for fooProp Sort Set. Fail Scheme Induction for fooProp Sort Type. About fooProp_inds_dep. About fooProp_ind_dep. (** ** Try Minimality into all Sorts *) Scheme Minimality for fooProp Sort SProp. (* fooProp_inds *) Scheme Minimality for fooProp Sort Prop. (* fooProp_ind *) Fail Scheme Minimality for fooProp Sort Set. Fail Scheme Minimality for fooProp Sort Type. About fooProp_inds. About fooProp_ind. (** ** Try Elimination into all Sorts *) Scheme Elimination for fooProp Sort SProp. (* fooProp_cases_dep *) Scheme Elimination for fooProp Sort Prop. (* fooProp_case_dep *) Fail Scheme Elimination for fooProp Sort Set. Fail Scheme Elimination for fooProp Sort Type. About fooProp_cases_dep. About fooProp_case_dep. (** ** Try Case into all Sorts *) Scheme Case for fooProp Sort SProp. (* fooProp_cases *) Scheme Case for fooProp Sort Prop. (* fooProp_case *) Fail Scheme Case for fooProp Sort Set. Fail Scheme Case for fooProp Sort Type. About fooProp_cases. About fooProp_case. (** ** Scheme Equality *) Fail Scheme Equality for fooProp. (** * Schemes for inductive Set *) (** Here is an inductive Set. *) Inductive fooSet : Set := aS | bS. (** ** Try Induction into all Sorts *) Scheme Induction for fooSet Sort SProp. (* fooSet_inds *) Scheme Induction for fooSet Sort Prop. (* fooSet_ind *) Scheme Induction for fooSet Sort Set. (* fooSet_rec *) Scheme Induction for fooSet Sort Type. (* fooSet_rect *) About fooSet_inds. About fooSet_ind. About fooSet_rec. About fooSet_rect. (** ** Try Minimality into all Sorts *) Scheme Minimality for fooSet Sort SProp. (* fooSet_inds_nodep *) Scheme Minimality for fooSet Sort Prop. (* fooSet_ind_nodep *) Scheme Minimality for fooSet Sort Set. (* fooSet_rec_nodep *) Scheme Minimality for fooSet Sort Type. (* fooSet_rect_nodep *) About fooSet_inds_nodep. About fooSet_ind_nodep. About fooSet_rec_nodep. About fooSet_rect_nodep. (** ** Try Elimination into all Sorts *) (** Unforunately there is some overlap with names so we need to create a fresh inductive. *) Inductive fooSet' : Set := aS' | bS'. Scheme Elimination for fooSet Sort SProp. (* fooSet_cases *) Scheme Elimination for fooSet Sort Prop. (* fooSet_case *) Scheme Elimination for fooSet' Sort Set. (* fooSet'_case *) Scheme Elimination for fooSet' Sort Type. (* fooSet'_caset *) About fooSet_cases. About fooSet_case. About fooSet'_case. About fooSet'_caset. (** ** Try Case into all Sorts *) Scheme Case for fooSet Sort SProp. (* fooSet_cases_nodep *) Scheme Case for fooSet Sort Prop. (* fooSet_case_nodep *) Scheme Case for fooSet' Sort Set. (* fooSet'_case_nodep *) Scheme Case for fooSet' Sort Type. (* fooSet'_caset_nodep *) About fooSet_cases_nodep. About fooSet_case_nodep. About fooSet'_case_nodep. About fooSet'_caset_nodep. (** ** Scheme Equality *) Scheme Equality for fooSet. About fooSet_beq. About fooSet_eq_dec. About internal_fooSet_dec_bl. About internal_fooSet_dec_lb. (** * Schemes for inductive Type *) (** Here is an inductive Type. *) Inductive fooType : Type := aT | bT. (** ** Try Induction into all Sorts *) Scheme Induction for fooType Sort SProp. (* fooType_inds *) Scheme Induction for fooType Sort Prop. (* fooType_ind *) Scheme Induction for fooType Sort Set. (* fooType_rec *) Scheme Induction for fooType Sort Type. (* fooType_rect *) About fooType_inds. About fooType_ind. About fooType_rec. About fooType_rect. (** ** Try Minimality into all Sorts *) Scheme Minimality for fooType Sort SProp. (* fooType_inds_nodep *) Scheme Minimality for fooType Sort Prop. (* fooType_ind_nodep *) Scheme Minimality for fooType Sort Set. (* fooType_rec_nodep *) Scheme Minimality for fooType Sort Type. (* fooType_rect_nodep *) About fooType_inds_nodep. About fooType_ind_nodep. About fooType_rec_nodep. About fooType_rect_nodep. (** ** Try Elimination into all Sorts *) (** Unforunately there is some overlap with names so we need to create a fresh inductive. *) Inductive fooType' : Type := aT' | bT'. Scheme Elimination for fooType Sort SProp. (* fooType_cases *) Scheme Elimination for fooType Sort Prop. (* fooType_case *) Scheme Elimination for fooType' Sort Set. (* fooType'_case *) Scheme Elimination for fooType' Sort Type. (* fooType'_caset *) About fooType_cases. About fooType_case. About fooType'_case. About fooType'_caset. (** ** Try Case into all Sorts *) Scheme Case for fooType Sort SProp. (* fooType_cases_nodep *) Scheme Case for fooType Sort Prop. (* fooType_case_nodep *) Scheme Case for fooType' Sort Set. (* fooType'_case_nodep *) Scheme Case for fooType' Sort Type. (* fooType'_caset_nodep *) About fooType_cases_nodep. About fooType_case_nodep. About fooType'_case_nodep. About fooType'_caset_nodep. (** ** Scheme Equality *) Scheme Equality for fooType. About fooType_beq. About fooType_eq_dec. About internal_fooType_dec_bl. About internal_fooType_dec_lb. Set Elimination Schemes. Inductive F f := C : f -> F f. About F_rect. Inductive PP P := D : P -> PP P. About PP_rect. rocq-9.2.0/test-suite/output/Search.out000066400000000000000000000464671516144147600201240ustar00rootroot00000000000000le_n: forall n : nat, n <= n le_0_n: forall n : nat, 0 <= n le_S: forall n m : nat, n <= m -> n <= S m le_S_n: forall n m : nat, S n <= S m -> n <= m le_pred: forall n m : nat, n <= m -> Nat.pred n <= Nat.pred m le_n_S: forall n m : nat, n <= m -> S n <= S m max_l: forall n m : nat, m <= n -> Nat.max n m = n max_r: forall n m : nat, n <= m -> Nat.max n m = m min_r: forall n m : nat, m <= n -> Nat.min n m = m min_l: forall n m : nat, n <= m -> Nat.min n m = n le_ind: forall (n : nat) (P : nat -> Prop), P n -> (forall m : nat, n <= m -> P m -> P (S m)) -> forall n0 : nat, n <= n0 -> P n0 le_sind: forall (n : nat) (P : nat -> SProp), P n -> (forall m : nat, n <= m -> P m -> P (S m)) -> forall n0 : nat, n <= n0 -> P n0 false: bool true: bool is_true: bool -> Prop eq_true: bool -> Prop negb: bool -> bool xorb: bool -> bool -> bool implb: bool -> bool -> bool reflect: Prop -> bool -> Set andb: bool -> bool -> bool orb: bool -> bool -> bool Nat.even: nat -> bool Nat.odd: nat -> bool BoolSpec: Prop -> Prop -> bool -> Prop Decimal.uint_beq: Decimal.uint -> Decimal.uint -> bool Nat.leb: nat -> nat -> bool Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool Number.uint_beq: Number.uint -> Number.uint -> bool Number.signed_int_beq: Number.signed_int -> Number.signed_int -> bool Decimal.signed_int_beq: Decimal.signed_int -> Decimal.signed_int -> bool Nat.eqb: nat -> nat -> bool Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool Nat.ltb: nat -> nat -> bool Number.number_beq: Number.number -> Number.number -> bool Hexadecimal.signed_int_beq: Hexadecimal.signed_int -> Hexadecimal.signed_int -> bool Hexadecimal.hexadecimal_beq: Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool Nat.testbit: nat -> nat -> bool Nat.bitwise: (bool -> bool -> bool) -> nat -> nat -> nat -> nat eq_true_rew_r: forall [b : bool] (P : bool -> Type), P b -> eq_true b -> P true eq_true_rew: forall P : bool -> Type, P true -> forall [b : bool], eq_true b -> P b bool_rec: forall P : bool -> Set, P true -> P false -> forall b : bool, P b eq_true_rec_r: forall (P : bool -> Set) [b : bool], P b -> eq_true b -> P true eq_true_ind: forall P : bool -> Prop, P true -> forall [b : bool], eq_true b -> P b eq_true_rect: forall P : bool -> Type, P true -> forall [b : bool], eq_true b -> P b eq_true_rect_r: forall (P : bool -> Type) [b : bool], P b -> eq_true b -> P true eq_true_rec: forall P : bool -> Set, P true -> forall [b : bool], eq_true b -> P b eq_true_ind_r: forall (P : bool -> Prop) [b : bool], P b -> eq_true b -> P true bool_ind: forall P : bool -> Prop, P true -> P false -> forall b : bool, P b eq_true_sind: forall P : bool -> SProp, P true -> forall [b : bool], eq_true b -> P b bool_sind: forall P : bool -> SProp, P true -> P false -> forall b : bool, P b bool_rect: forall P : bool -> Type, P true -> P false -> forall b : bool, P b bool_of_sumbool: forall [A B : Prop], {A} + {B} -> {b : bool | if b then A else B} sumbool_of_bool: forall b : bool, {b = true} + {b = false} Decimal.internal_signed_int_dec_lb: forall x y : Decimal.signed_int, x = y -> Decimal.signed_int_beq x y = true Number.internal_signed_int_dec_lb1: forall x y : Number.signed_int, x = y -> Number.signed_int_beq x y = true Number.internal_signed_int_dec_bl1: forall x y : Number.signed_int, Number.signed_int_beq x y = true -> x = y Decimal.internal_signed_int_dec_bl: forall x y : Decimal.signed_int, Decimal.signed_int_beq x y = true -> x = y Hexadecimal.internal_hexadecimal_dec_lb: forall x y : Hexadecimal.hexadecimal, x = y -> Hexadecimal.hexadecimal_beq x y = true Hexadecimal.internal_signed_int_dec_lb0: forall x y : Hexadecimal.signed_int, x = y -> Hexadecimal.signed_int_beq x y = true Number.internal_number_dec_lb: forall x y : Number.number, x = y -> Number.number_beq x y = true Hexadecimal.internal_signed_int_dec_bl0: forall x y : Hexadecimal.signed_int, Hexadecimal.signed_int_beq x y = true -> x = y Number.internal_uint_dec_lb1: forall x y : Number.uint, x = y -> Number.uint_beq x y = true Number.internal_uint_dec_bl1: forall x y : Number.uint, Number.uint_beq x y = true -> x = y Decimal.internal_decimal_dec_bl: forall x y : Decimal.decimal, Decimal.decimal_beq x y = true -> x = y Number.internal_number_dec_bl: forall x y : Number.number, Number.number_beq x y = true -> x = y Byte.of_bits: bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) -> Byte.byte Byte.to_bits: Byte.byte -> bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) Decimal.internal_decimal_dec_lb: forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true Hexadecimal.internal_hexadecimal_dec_bl: forall x y : Hexadecimal.hexadecimal, Hexadecimal.hexadecimal_beq x y = true -> x = y eq_true_rew_fwd_dep: forall [b : bool] (H : eq_true b) (P : forall b0 : bool, eq_true b0 -> Type), P b H -> P true is_eq_true eq_true_rew_dep: forall P : forall b : bool, eq_true b -> Type, P true is_eq_true -> forall [b : bool] (e : eq_true b), P b e Decimal.internal_uint_dec_bl: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, Decimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_lb: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, x0 = y -> Decimal.uint_beq x0 y = true) x Hexadecimal.internal_uint_dec_lb0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, x0 = y -> Hexadecimal.uint_beq x0 y = true) x Hexadecimal.internal_uint_dec_bl0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, Hexadecimal.uint_beq x0 y = true -> x0 = y) x andb_prop: forall a b : bool, (a && b)%bool = true -> a = true /\ b = true andb_true_intro: forall [b1 b2 : bool], b1 = true /\ b2 = true -> (b1 && b2)%bool = true bool_eq_rec: forall (b : bool) (P : bool -> Set), (b = true -> P true) -> (b = false -> P false) -> P b bool_eq_ind: forall (b : bool) (P : bool -> Prop), (b = true -> P true) -> (b = false -> P false) -> P b BoolSpec_sind: forall [P Q : Prop] (P0 : bool -> SProp), (P -> P0 true) -> (Q -> P0 false) -> forall [b : bool], BoolSpec P Q b -> P0 b BoolSpec_ind: forall [P Q : Prop] (P0 : bool -> Prop), (P -> P0 true) -> (Q -> P0 false) -> forall [b : bool], BoolSpec P Q b -> P0 b reflect_ind: forall [P : Prop] (P0 : forall b : bool, reflect P b -> Prop), (forall p : P, P0 true (ReflectT P p)) -> (forall n : ~ P, P0 false (ReflectF P n)) -> forall [b : bool] (r : reflect P b), P0 b r reflect_sind: forall [P : Prop] (P0 : forall b : bool, reflect P b -> SProp), (forall p : P, P0 true (ReflectT P p)) -> (forall n : ~ P, P0 false (ReflectF P n)) -> forall [b : bool] (r : reflect P b), P0 b r reflect_rect: forall [P : Prop] (P0 : forall b : bool, reflect P b -> Type), (forall p : P, P0 true (ReflectT P p)) -> (forall n : ~ P, P0 false (ReflectF P n)) -> forall [b : bool] (r : reflect P b), P0 b r reflect_rec: forall [P : Prop] (P0 : forall b : bool, reflect P b -> Set), (forall p : P, P0 true (ReflectT P p)) -> (forall n : ~ P, P0 false (ReflectF P n)) -> forall [b : bool] (r : reflect P b), P0 b r Byte.to_bits_of_bits: forall b : bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))), Byte.to_bits (Byte.of_bits b) = b bool_choice: forall [S : Set] [R1 R2 : S -> Prop], (forall x : S, {R1 x} + {R2 x}) -> {f : S -> bool | forall x : S, f x = true /\ R1 x \/ f x = false /\ R2 x} mult_n_O: forall n : nat, 0 = n * 0 plus_O_n: forall n : nat, 0 + n = n plus_n_O: forall n : nat, n = n + 0 n_Sn: forall n : nat, n <> S n pred_Sn: forall n : nat, n = Nat.pred (S n) O_S: forall n : nat, 0 <> S n f_equal_pred: forall x y : nat, x = y -> Nat.pred x = Nat.pred y eq_S: forall x y : nat, x = y -> S x = S y eq_add_S: forall n m : nat, S n = S m -> n = m min_r: forall n m : nat, m <= n -> Nat.min n m = m min_l: forall n m : nat, n <= m -> Nat.min n m = n max_r: forall n m : nat, n <= m -> Nat.max n m = m max_l: forall n m : nat, m <= n -> Nat.max n m = n plus_Sn_m: forall n m : nat, S n + m = S (n + m) plus_n_Sm: forall n m : nat, S (n + m) = n + S m f_equal_nat: forall (B : Type) (f : nat -> B) (x y : nat), x = y -> f x = f y not_eq_S: forall n m : nat, n <> m -> S n <> S m mult_n_Sm: forall n m : nat, n * m + n = n * S m f_equal2_plus: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2 f_equal2_mult: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 * x2 = y1 * y2 f_equal2_nat: forall (B : Type) (f : nat -> nat -> B) (x1 y1 x2 y2 : nat), x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2 sumbool_of_bool: forall b : bool, {b = true} + {b = false} Number.internal_number_dec_lb: forall x y : Number.number, x = y -> Number.number_beq x y = true Number.internal_signed_int_dec_lb1: forall x y : Number.signed_int, x = y -> Number.signed_int_beq x y = true Number.internal_signed_int_dec_bl1: forall x y : Number.signed_int, Number.signed_int_beq x y = true -> x = y Number.internal_uint_dec_lb1: forall x y : Number.uint, x = y -> Number.uint_beq x y = true Number.internal_number_dec_bl: forall x y : Number.number, Number.number_beq x y = true -> x = y Hexadecimal.internal_hexadecimal_dec_lb: forall x y : Hexadecimal.hexadecimal, x = y -> Hexadecimal.hexadecimal_beq x y = true Decimal.internal_decimal_dec_bl: forall x y : Decimal.decimal, Decimal.decimal_beq x y = true -> x = y Decimal.internal_signed_int_dec_lb: forall x y : Decimal.signed_int, x = y -> Decimal.signed_int_beq x y = true Number.internal_uint_dec_bl1: forall x y : Number.uint, Number.uint_beq x y = true -> x = y Decimal.internal_decimal_dec_lb: forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true Hexadecimal.internal_hexadecimal_dec_bl: forall x y : Hexadecimal.hexadecimal, Hexadecimal.hexadecimal_beq x y = true -> x = y Hexadecimal.internal_signed_int_dec_lb0: forall x y : Hexadecimal.signed_int, x = y -> Hexadecimal.signed_int_beq x y = true Hexadecimal.internal_signed_int_dec_bl0: forall x y : Hexadecimal.signed_int, Hexadecimal.signed_int_beq x y = true -> x = y Decimal.internal_signed_int_dec_bl: forall x y : Decimal.signed_int, Decimal.signed_int_beq x y = true -> x = y Hexadecimal.internal_uint_dec_lb0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, x0 = y -> Hexadecimal.uint_beq x0 y = true) x Hexadecimal.internal_uint_dec_bl0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, Hexadecimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_bl: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, Decimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_lb: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, x0 = y -> Decimal.uint_beq x0 y = true) x andb_prop: forall a b : bool, (a && b)%bool = true -> a = true /\ b = true andb_true_intro: forall [b1 b2 : bool], b1 = true /\ b2 = true -> (b1 && b2)%bool = true bool_eq_rec: forall (b : bool) (P : bool -> Set), (b = true -> P true) -> (b = false -> P false) -> P b bool_eq_ind: forall (b : bool) (P : bool -> Prop), (b = true -> P true) -> (b = false -> P false) -> P b bool_choice: forall [S : Set] [R1 R2 : S -> Prop], (forall x : S, {R1 x} + {R2 x}) -> {f : S -> bool | forall x : S, f x = true /\ R1 x \/ f x = false /\ R2 x} Number.internal_number_dec_lb: forall x y : Number.number, x = y -> Number.number_beq x y = true Number.internal_number_dec_bl: forall x y : Number.number, Number.number_beq x y = true -> x = y Number.internal_signed_int_dec_lb1: forall x y : Number.signed_int, x = y -> Number.signed_int_beq x y = true Number.internal_signed_int_dec_bl1: forall x y : Number.signed_int, Number.signed_int_beq x y = true -> x = y Number.internal_uint_dec_lb1: forall x y : Number.uint, x = y -> Number.uint_beq x y = true Number.internal_uint_dec_bl1: forall x y : Number.uint, Number.uint_beq x y = true -> x = y Hexadecimal.internal_hexadecimal_dec_lb: forall x y : Hexadecimal.hexadecimal, x = y -> Hexadecimal.hexadecimal_beq x y = true Hexadecimal.internal_hexadecimal_dec_bl: forall x y : Hexadecimal.hexadecimal, Hexadecimal.hexadecimal_beq x y = true -> x = y Hexadecimal.internal_signed_int_dec_lb0: forall x y : Hexadecimal.signed_int, x = y -> Hexadecimal.signed_int_beq x y = true Hexadecimal.internal_signed_int_dec_bl0: forall x y : Hexadecimal.signed_int, Hexadecimal.signed_int_beq x y = true -> x = y Decimal.internal_decimal_dec_lb: forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true Decimal.internal_decimal_dec_bl: forall x y : Decimal.decimal, Decimal.decimal_beq x y = true -> x = y Decimal.internal_signed_int_dec_lb: forall x y : Decimal.signed_int, x = y -> Decimal.signed_int_beq x y = true Decimal.internal_signed_int_dec_bl: forall x y : Decimal.signed_int, Decimal.signed_int_beq x y = true -> x = y Hexadecimal.internal_uint_dec_bl0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, Hexadecimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_bl: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, Decimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_lb: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, x0 = y -> Decimal.uint_beq x0 y = true) x Hexadecimal.internal_uint_dec_lb0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, x0 = y -> Hexadecimal.uint_beq x0 y = true) x andb_true_intro: forall [b1 b2 : bool], b1 = true /\ b2 = true -> (b1 && b2)%bool = true andb_prop: forall a b : bool, (a && b)%bool = true -> a = true /\ b = true andb_prop: forall a b : bool, (a && b)%bool = true -> a = true /\ b = true h: n <> newdef n h': newdef n <> n h: n <> newdef n h': newdef n <> n h: n <> newdef n h: n <> newdef n h: n <> newdef n h': newdef n <> n File "./output/Search.v", line 23, characters 2-23: The command has indeed failed with message: [Focus] No such goal. File "./output/Search.v", line 24, characters 2-25: The command has indeed failed with message: Query commands only support the single numbered goal selector. File "./output/Search.v", line 25, characters 2-25: The command has indeed failed with message: Query commands only support the single numbered goal selector. h: P n h': ~ P n h: P n h': ~ P n h: P n h': ~ P n h: P n h: P n a: A b: A or_assoc: forall A B C : Prop, (A \/ B) \/ C <-> A \/ B \/ C and_assoc: forall A B C : Prop, (A /\ B) /\ C <-> A /\ B /\ C eq_trans_assoc: forall [A : Type] [x y z t : A] (e : x = y) (e' : y = z) (e'' : z = t), eq_trans e (eq_trans e' e'') = eq_trans (eq_trans e e') e'' plus_O_n: forall n : nat, 0 + n = n plus_n_O: forall n : nat, n = n + 0 plus_n_Sm: forall n m : nat, S (n + m) = n + S m plus_Sn_m: forall n m : nat, S n + m = S (n + m) mult_n_Sm: forall n m : nat, n * m + n = n * S m f_equal2_plus: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2 nat_rect_plus: forall (n m : nat) {A : Type} (f : A -> A) (x : A), nat_rect (fun _ : nat => A) x (fun _ : nat => f) (n + m) = nat_rect (fun _ : nat => A) (nat_rect (fun _ : nat => A) x (fun _ : nat => f) m) (fun _ : nat => f) n Nat.bitwise: (bool -> bool -> bool) -> nat -> nat -> nat -> nat Number.internal_number_dec_bl: forall x y : Number.number, Number.number_beq x y = true -> x = y Number.internal_signed_int_dec_bl1: forall x y : Number.signed_int, Number.signed_int_beq x y = true -> x = y Number.internal_uint_dec_bl1: forall x y : Number.uint, Number.uint_beq x y = true -> x = y Hexadecimal.internal_hexadecimal_dec_bl: forall x y : Hexadecimal.hexadecimal, Hexadecimal.hexadecimal_beq x y = true -> x = y Hexadecimal.internal_signed_int_dec_bl0: forall x y : Hexadecimal.signed_int, Hexadecimal.signed_int_beq x y = true -> x = y Decimal.internal_decimal_dec_bl: forall x y : Decimal.decimal, Decimal.decimal_beq x y = true -> x = y Decimal.internal_signed_int_dec_bl: forall x y : Decimal.signed_int, Decimal.signed_int_beq x y = true -> x = y Byte.of_bits: bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) -> Byte.byte Byte.to_bits_of_bits: forall b : bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))), Byte.to_bits (Byte.of_bits b) = b bool_of_sumbool: forall [A B : Prop], {A} + {B} -> {b : bool | if b then A else B} sumbool_of_bool: forall b : bool, {b = true} + {b = false} Number.internal_number_dec_lb: forall x y : Number.number, x = y -> Number.number_beq x y = true Number.internal_uint_dec_lb1: forall x y : Number.uint, x = y -> Number.uint_beq x y = true Number.internal_signed_int_dec_lb1: forall x y : Number.signed_int, x = y -> Number.signed_int_beq x y = true Decimal.internal_signed_int_dec_lb: forall x y : Decimal.signed_int, x = y -> Decimal.signed_int_beq x y = true Hexadecimal.internal_hexadecimal_dec_lb: forall x y : Hexadecimal.hexadecimal, x = y -> Hexadecimal.hexadecimal_beq x y = true Hexadecimal.internal_signed_int_dec_lb0: forall x y : Hexadecimal.signed_int, x = y -> Hexadecimal.signed_int_beq x y = true Decimal.internal_decimal_dec_lb: forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true Byte.to_bits: Byte.byte -> bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) Hexadecimal.internal_uint_dec_bl0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, Hexadecimal.uint_beq x0 y = true -> x0 = y) x Decimal.internal_uint_dec_lb: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, x0 = y -> Decimal.uint_beq x0 y = true) x Decimal.internal_uint_dec_bl: forall x : Decimal.uint, (fun x0 : Decimal.uint => forall y : Decimal.uint, Decimal.uint_beq x0 y = true -> x0 = y) x Hexadecimal.internal_uint_dec_lb0: forall x : Hexadecimal.uint, (fun x0 : Hexadecimal.uint => forall y : Hexadecimal.uint, x0 = y -> Hexadecimal.uint_beq x0 y = true) x andb_prop: forall a b : bool, (a && b)%bool = true -> a = true /\ b = true andb_true_intro: forall [b1 b2 : bool], b1 = true /\ b2 = true -> (b1 && b2)%bool = true Byte.to_bits_of_bits: forall b : bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))), Byte.to_bits (Byte.of_bits b) = b bool_choice: forall [S : Set] [R1 R2 : S -> Prop], (forall x : S, {R1 x} + {R2 x}) -> {f : S -> bool | forall x : S, f x = true /\ R1 x \/ f x = false /\ R2 x} Nat.two: nat Nat.one: nat Nat.zero: nat newdef: nat -> nat Nat.succ: nat -> nat Nat.log2: nat -> nat Nat.sqrt: nat -> nat Nat.square: nat -> nat Nat.double: nat -> nat Nat.pred: nat -> nat Nat.ldiff: nat -> nat -> nat Nat.tail_mul: nat -> nat -> nat Nat.land: nat -> nat -> nat Nat.div: nat -> nat -> nat Nat.modulo: nat -> nat -> nat Nat.lor: nat -> nat -> nat Nat.lxor: nat -> nat -> nat Nat.of_hex_uint: Hexadecimal.uint -> nat Nat.of_uint: Decimal.uint -> nat Nat.of_num_uint: Number.uint -> nat length: forall [A : Type], list A -> nat plus_n_O: forall n : nat, n = n + 0 plus_O_n: forall n : nat, 0 + n = n plus_n_Sm: forall n m : nat, S (n + m) = n + S m plus_Sn_m: forall n m : nat, S n + m = S (n + m) mult_n_Sm: forall n m : nat, n * m + n = n * S m should say both t and t_alias - : Init.unit = () t: T t_alias: T should say only t - : Init.unit = () BlacklistLocals.t: BlacklistLocals.T should say both t and t_alias - : Init.unit = () BlacklistLocals.t_alias: BlacklistLocals.T BlacklistLocals.t: BlacklistLocals.T rocq-9.2.0/test-suite/output/Search.v000066400000000000000000000040411516144147600175400ustar00rootroot00000000000000(* Some tests of the Search command *) Search le. (* app nodes *) Search bool. (* no apps *) Search (@eq nat). (* complex pattern *) Search (@eq _ _ true). Search (@eq _ _ _) true -false. (* andb_prop *) Search (@eq _ _ _) true -false "prop" -"intro". (* andb_prop *) Definition newdef := fun x:nat => x. Goal forall n:nat, n <> newdef n -> newdef n <> n -> False. cut False. intros _ n h h'. Search n. (* search hypothesis *) Search newdef. (* search hypothesis *) Search ( _ <> newdef _). (* search hypothesis, pattern *) Search ( _ <> newdef _) -"h'". (* search hypothesis, pattern *) 1:Search newdef. 2:Search newdef. Fail 3:Search newdef. Fail 1-2:Search newdef. Fail all:Search newdef. Abort. Goal forall n (P:nat -> Prop), P n -> ~P n -> False. intros n P h h'. Search P. (* search hypothesis also for patterns *) Search (P _). (* search hypothesis also for patterns *) Search (P n). (* search hypothesis also for patterns *) Search (P _) -"h'". (* search hypothesis also for patterns *) Search (P _) -not. (* search hypothesis also for patterns *) Abort. Module M. Section S. Variable A:Type. Variable a:A. Theorem Thm (b:A) : True. Search A. (* Test search in hypotheses *) Abort. End S. End M. (* Reproduce the example of the doc *) Search "_assoc". Search "+". Search hyp:bool -headhyp:bool. Search concl:bool -headconcl:bool. Search [ is:Definition headconcl:nat | is:Lemma (_ + _) ]. (* used to print something between search outputs, otherwise we can't tell which lines are from which command *) Require Import Ltac2.Printf. Module BlacklistLocals. Axiom T : Type. Axiom t : T. Local Definition t_alias := t. Ltac2 Eval printf "should say both t and t_alias". Search T. End BlacklistLocals. Ltac2 Eval printf "should say only t". Search BlacklistLocals.T. Unset Search Blacklist Locals. Ltac2 Eval printf "should say both t and t_alias". Search BlacklistLocals.T. rocq-9.2.0/test-suite/output/SearchFixpoint.out000066400000000000000000000000751516144147600216260ustar00rootroot00000000000000Foo.bar: nat -> nat Foo.from: nat -> Foo.Stream Foo.foo: nat rocq-9.2.0/test-suite/output/SearchFixpoint.v000066400000000000000000000010301516144147600212540ustar00rootroot00000000000000(** Test file for #18983 *) (** We test that [Search] allows the [is:Fixpoint] and [is:CoFixpoint] search items while not changing [is:Definition]. *) Module Foo. Definition foo := 42. Fixpoint bar (n : nat) := match n with | 0 => 0 | S n => bar n end. (* Example shamelessly taken from the reference manual. *) CoInductive Stream := Seq : nat -> Stream -> Stream. CoFixpoint from (n : nat) := Seq n (from (S n)). End Foo. Search is:Fixpoint inside Foo. Search is:CoFixpoint inside Foo. Search is:Definition inside Foo. rocq-9.2.0/test-suite/output/SearchPattern.out000066400000000000000000000070041516144147600214420ustar00rootroot00000000000000false: bool true: bool negb: bool -> bool xorb: bool -> bool -> bool andb: bool -> bool -> bool orb: bool -> bool -> bool implb: bool -> bool -> bool Nat.odd: nat -> bool Nat.even: nat -> bool Number.uint_beq: Number.uint -> Number.uint -> bool Nat.testbit: nat -> nat -> bool Nat.eqb: nat -> nat -> bool Hexadecimal.hexadecimal_beq: Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool Nat.ltb: nat -> nat -> bool Nat.leb: nat -> nat -> bool Number.number_beq: Number.number -> Number.number -> bool Number.signed_int_beq: Number.signed_int -> Number.signed_int -> bool Hexadecimal.signed_int_beq: Hexadecimal.signed_int -> Hexadecimal.signed_int -> bool Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool Decimal.signed_int_beq: Decimal.signed_int -> Decimal.signed_int -> bool Decimal.uint_beq: Decimal.uint -> Decimal.uint -> bool Nat.two: nat Nat.zero: nat Nat.one: nat O: nat Nat.double: nat -> nat Nat.sqrt: nat -> nat Nat.div2: nat -> nat Nat.log2: nat -> nat Nat.pred: nat -> nat Nat.square: nat -> nat S: nat -> nat Nat.succ: nat -> nat Nat.ldiff: nat -> nat -> nat Nat.add: nat -> nat -> nat Nat.land: nat -> nat -> nat Nat.lxor: nat -> nat -> nat Nat.sub: nat -> nat -> nat Nat.mul: nat -> nat -> nat Nat.tail_mul: nat -> nat -> nat Nat.max: nat -> nat -> nat Nat.tail_add: nat -> nat -> nat Nat.pow: nat -> nat -> nat Nat.min: nat -> nat -> nat Nat.modulo: nat -> nat -> nat Nat.div: nat -> nat -> nat Nat.lor: nat -> nat -> nat Nat.gcd: nat -> nat -> nat Hexadecimal.nb_digits: Hexadecimal.uint -> nat Nat.of_hex_uint: Hexadecimal.uint -> nat Nat.of_num_uint: Number.uint -> nat Nat.of_uint: Decimal.uint -> nat Decimal.nb_digits: Decimal.uint -> nat Nat.tail_addmul: nat -> nat -> nat -> nat Nat.of_hex_uint_acc: Hexadecimal.uint -> nat -> nat Nat.of_uint_acc: Decimal.uint -> nat -> nat Nat.sqrt_iter: nat -> nat -> nat -> nat -> nat Nat.log2_iter: nat -> nat -> nat -> nat -> nat length: forall [A : Type], list A -> nat Nat.bitwise: (bool -> bool -> bool) -> nat -> nat -> nat -> nat Nat.div2: nat -> nat Nat.sqrt: nat -> nat Nat.log2: nat -> nat Nat.double: nat -> nat S: nat -> nat Nat.square: nat -> nat Nat.succ: nat -> nat Nat.pred: nat -> nat Nat.land: nat -> nat -> nat Nat.max: nat -> nat -> nat Nat.gcd: nat -> nat -> nat Nat.modulo: nat -> nat -> nat Nat.ldiff: nat -> nat -> nat Nat.tail_add: nat -> nat -> nat Nat.pow: nat -> nat -> nat Nat.lxor: nat -> nat -> nat Nat.div: nat -> nat -> nat Nat.lor: nat -> nat -> nat Nat.mul: nat -> nat -> nat Nat.min: nat -> nat -> nat Nat.add: nat -> nat -> nat Nat.sub: nat -> nat -> nat Nat.tail_mul: nat -> nat -> nat Nat.tail_addmul: nat -> nat -> nat -> nat Nat.of_uint_acc: Decimal.uint -> nat -> nat Nat.of_hex_uint_acc: Hexadecimal.uint -> nat -> nat Nat.sqrt_iter: nat -> nat -> nat -> nat -> nat Nat.log2_iter: nat -> nat -> nat -> nat -> nat Nat.bitwise: (bool -> bool -> bool) -> nat -> nat -> nat -> nat mult_n_Sm: forall n m : nat, n * m + n = n * S m iff_refl: forall A : Prop, A <-> A le_n: forall n : nat, n <= n eq_refl: forall {A : Type} {x : A}, x = x Nat.divmod: nat -> nat -> nat -> nat -> nat * nat refl: forall {eq : forall A : Type@{Ξ²0 ; _}, A -> A -> Type@{Ξ²1 ; _}}, Has_refl eq -> forall (A : Type@{Ξ²0 ; _}) (x : A), eq A x x (use "About" for full details on the implicit arguments of eq_refl) conj: forall [A B : Prop], A -> B -> A /\ B pair: forall {A B : Type}, A -> B -> A * B Nat.divmod: nat -> nat -> nat -> nat -> nat * nat h: n <> newdef n h: n <> newdef n h: P n h': ~ P n h: P n h: P n rocq-9.2.0/test-suite/output/SearchPattern.v000066400000000000000000000017531516144147600211050ustar00rootroot00000000000000(* Some tests of the SearchPattern command *) (* Simple, random tests *) SearchPattern bool. SearchPattern nat. SearchPattern le. (* With some hypothesis *) SearchPattern (nat -> nat). SearchPattern (?n * ?m + ?n = ?n * S ?m). (* Non-linearity *) SearchPattern (_ ?X ?X). (* Non-linearity with hypothesis *) SearchPattern (forall (x:?A) (y:?B), _ ?A ?B). (* No delta-reduction *) SearchPattern (Exc _). Definition newdef := fun x:nat => x. Goal forall n:nat, n <> newdef n -> False. intros n h. SearchPattern ( _ <> newdef _). (* search hypothesis *) SearchPattern ( n <> newdef _). (* search hypothesis *) Abort. Goal forall n (P:nat -> Prop), P n -> ~P n -> False. intros n P h h'. SearchPattern (P _). (* search hypothesis also for patterns *) Search (~P n). (* search hypothesis also for patterns *) Search (P _) -"h'". (* search hypothesis also for patterns *) Search (P _) -not. (* search hypothesis also for patterns *) Abort. rocq-9.2.0/test-suite/output/SearchRewrite.out000066400000000000000000000001701516144147600214430ustar00rootroot00000000000000plus_n_O: forall n : nat, n = n + 0 plus_O_n: forall n : nat, 0 + n = n h: n = newdef n h: n = newdef n h: n = newdef n rocq-9.2.0/test-suite/output/SearchRewrite.v000066400000000000000000000006001516144147600210770ustar00rootroot00000000000000(* Some tests of the SearchRewrite command *) SearchRewrite (_+0). (* left *) SearchRewrite (0+_). (* right *) Definition newdef := fun x:nat => x. Goal forall n:nat, n = newdef n -> False. intros n h. SearchRewrite (newdef _). SearchRewrite n. (* use hypothesis for patterns *) SearchRewrite (newdef n). (* use hypothesis for patterns *) Abort. rocq-9.2.0/test-suite/output/SearchScheme.out000066400000000000000000000012501516144147600212260ustar00rootroot00000000000000nat_sind: forall P : nat -> SProp, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n nat_rec: forall P : nat -> Set, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n nat_ind: forall P : nat -> Prop, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n nat_rect: forall P : nat -> Type, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n le_ind: forall (n : nat) (P : nat -> Prop), P n -> (forall m : nat, n <= m -> P m -> P (S m)) -> forall n0 : nat, n <= n0 -> P n0 le_sind: forall (n : nat) (P : nat -> SProp), P n -> (forall m : nat, n <= m -> P m -> P (S m)) -> forall n0 : nat, n <= n0 -> P n0 rocq-9.2.0/test-suite/output/SearchScheme.v000066400000000000000000000000721516144147600206650ustar00rootroot00000000000000Search nat is:Scheme. (* was "le : nat -> nat -> Prop" *) rocq-9.2.0/test-suite/output/Search_bug13298.out000066400000000000000000000000351516144147600213450ustar00rootroot00000000000000snd: forall c : c, fst c = 0 rocq-9.2.0/test-suite/output/Search_bug13298.v000066400000000000000000000001361516144147600210050ustar00rootroot00000000000000Set Primitive Projections. Record c : Type := { fst : nat; snd : fst = 0 }. Search concl:fst. rocq-9.2.0/test-suite/output/Search_bug17963.out000066400000000000000000000000251516144147600213470ustar00rootroot00000000000000H: Some ?y = Some ?y rocq-9.2.0/test-suite/output/Search_bug17963.v000066400000000000000000000001371516144147600210110ustar00rootroot00000000000000Goal exists y, Some y = Some y :> option nat -> True. eexists. intro H. Search Some eq. Abort. rocq-9.2.0/test-suite/output/Search_headconcl.out000066400000000000000000000037531516144147600221130ustar00rootroot00000000000000le_n: forall n : nat, n <= n le_0_n: forall n : nat, 0 <= n le_S: forall n m : nat, n <= m -> n <= S m le_pred: forall n m : nat, n <= m -> Nat.pred n <= Nat.pred m le_n_S: forall n m : nat, n <= m -> S n <= S m le_S_n: forall n m : nat, S n <= S m -> n <= m false: bool true: bool negb: bool -> bool xorb: bool -> bool -> bool andb: bool -> bool -> bool orb: bool -> bool -> bool implb: bool -> bool -> bool Nat.odd: nat -> bool Nat.even: nat -> bool Number.uint_beq: Number.uint -> Number.uint -> bool Nat.testbit: nat -> nat -> bool Nat.eqb: nat -> nat -> bool Hexadecimal.hexadecimal_beq: Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool Nat.ltb: nat -> nat -> bool Nat.leb: nat -> nat -> bool Number.number_beq: Number.number -> Number.number -> bool Number.signed_int_beq: Number.signed_int -> Number.signed_int -> bool Hexadecimal.signed_int_beq: Hexadecimal.signed_int -> Hexadecimal.signed_int -> bool Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool Decimal.signed_int_beq: Decimal.signed_int -> Decimal.signed_int -> bool Decimal.uint_beq: Decimal.uint -> Decimal.uint -> bool mult_n_O: forall n : nat, 0 = n * 0 plus_O_n: forall n : nat, 0 + n = n plus_n_O: forall n : nat, n = n + 0 pred_Sn: forall n : nat, n = Nat.pred (S n) f_equal_pred: forall x y : nat, x = y -> Nat.pred x = Nat.pred y eq_add_S: forall n m : nat, S n = S m -> n = m eq_S: forall x y : nat, x = y -> S x = S y max_r: forall n m : nat, n <= m -> Nat.max n m = m max_l: forall n m : nat, m <= n -> Nat.max n m = n min_r: forall n m : nat, m <= n -> Nat.min n m = m min_l: forall n m : nat, n <= m -> Nat.min n m = n plus_n_Sm: forall n m : nat, S (n + m) = n + S m plus_Sn_m: forall n m : nat, S n + m = S (n + m) mult_n_Sm: forall n m : nat, n * m + n = n * S m f_equal2_plus: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2 f_equal2_mult: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 * x2 = y1 * y2 h: newdef n h: P n rocq-9.2.0/test-suite/output/Search_headconcl.v000066400000000000000000000007561516144147600215510ustar00rootroot00000000000000(* Some tests of the Search command *) Search headconcl: le. (* app nodes *) Search headconcl: bool. (* no apps *) Search headconcl: (@eq nat). (* complex pattern *) Definition newdef := fun x:nat => x = x. Goal forall n:nat, newdef n -> False. intros n h. Search headconcl: newdef. (* search hypothesis *) Abort. Goal forall n (P:nat -> Prop), P n -> False. intros n P h. Search headconcl: P. (* search hypothesis also for patterns *) Abort. rocq-9.2.0/test-suite/output/Show.out000066400000000000000000000002131516144147600176120ustar00rootroot000000000000003 goals (ID 27) H : 0 = 0 ============================ 1 = 1 goal 2 (ID 31) is: 1 = S (S m') goal 3 (ID 18) is: S (S n') = S m rocq-9.2.0/test-suite/output/Show.v000066400000000000000000000004111516144147600172500ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-emacs") -*- *) (* tests of Show output with -emacs flag to coqtop; see bug 5535 *) Theorem nums : forall (n m : nat), n = m -> (S n) = (S m). Proof. intros. induction n as [| n']. induction m as [| m']. Show. Admitted. rocq-9.2.0/test-suite/output/ShowMatch.out000066400000000000000000000000721516144147600205720ustar00rootroot00000000000000match # with | f => end match # with | A.f => end rocq-9.2.0/test-suite/output/ShowMatch.v000066400000000000000000000005441516144147600202340ustar00rootroot00000000000000(* Bug 5546 complained about unqualified constructors in Show Match output, when qualification is needed to disambiguate them *) Module A. Inductive foo := f. Show Match foo. (* no need to disambiguate *) End A. Module B. Inductive foo := f. (* local foo shadows A.foo, so constructor "f" needs disambiguation *) Show Match A.foo. End B. rocq-9.2.0/test-suite/output/ShowProof.out000066400000000000000000000000371516144147600206240ustar00rootroot00000000000000(fun x : Type => conj I ?Goal) rocq-9.2.0/test-suite/output/ShowProof.v000066400000000000000000000002301516144147600202550ustar00rootroot00000000000000(* Was #4524 *) Definition foo (x : Type) : True /\ True. Proof. split. - exact I. Show Proof. (* Was not finding an evar name at some time *) Abort. rocq-9.2.0/test-suite/output/ShowUnivs.out000066400000000000000000000015611516144147600206460ustar00rootroot00000000000000UNIVERSES: {w v u} |= u <= v v <= w ALGEBRAIC UNIVERSES: {} FLEXIBLE UNIVERSES: SORTS: |= Prop -> SProp Type -> Prop -> SProp WEAK CONSTRAINTS: Normalized constraints: {w v u} |= u <= v v <= w UNIVERSES: {ShowUnivs.28 ShowUnivs.27 ShowUnivs.26 ShowUnivs.25 ShowUnivs.24} |= ShowUnivs.25 < ShowUnivs.26 ShowUnivs.26 < ShowUnivs.27 ShowUnivs.26 <= ShowUnivs.28 ShowUnivs.27 <= ShowUnivs.24 ShowUnivs.28 <= ShowUnivs.24 ALGEBRAIC UNIVERSES: {ShowUnivs.28 ShowUnivs.27 ShowUnivs.24} FLEXIBLE UNIVERSES: ShowUnivs.28 ShowUnivs.27 ShowUnivs.26 ShowUnivs.24 SORTS: Ξ±1 := Type Ξ±2 := Type Ξ±3 := Ξ±1 |= Ξ±1 <-> Type Ξ±2 <-> Type Ξ±3 <-> Ξ±1 Prop -> SProp Type -> Prop -> SProp WEAK CONSTRAINTS: Normalized constraints: {ShowUnivs.26 ShowUnivs.25} |= ShowUnivs.25 < ShowUnivs.26 rocq-9.2.0/test-suite/output/ShowUnivs.v000066400000000000000000000014301516144147600202770ustar00rootroot00000000000000 Lemma foo@{u v w|u <= v, v <= w} : Prop. Show Universes. Abort. Goal True. pose (fun x => let y := Type in x y :y). Show Universes. Abort. (* was: UNIVERSES: {ShowUnivs.5 ShowUnivs.4 ShowUnivs.3 ShowUnivs.2 ShowUnivs.1} |= ShowUnivs.2 < ShowUnivs.3 ShowUnivs.3 < ShowUnivs.4 ShowUnivs.3 <= ShowUnivs.5 ShowUnivs.4 <= ShowUnivs.1 ShowUnivs.5 <= ShowUnivs.1 ALGEBRAIC UNIVERSES:{ShowUnivs.5 ShowUnivs.4 ShowUnivs.1} UNDEFINED UNIVERSES: ShowUnivs.5 ShowUnivs.4 ShowUnivs.3 ShowUnivs.1 WEAK CONSTRAINTS: Normalized constraints: {ShowUnivs.3 ShowUnivs.2} |= ShowUnivs.2 < ShowUnivs.3 *) rocq-9.2.0/test-suite/output/SortQuality.out000066400000000000000000000003001516144147600211670ustar00rootroot00000000000000Type Type@{Ξ±1 ; SortQuality.21} Type@{Ξ±1 ; SortQuality.21} Type A : Type@{s ; _} A : Type@{s ; u} (* {s}; {u} |= *) A : Type@{s ; u} (* {s}; {u} |= *) A : Type@{s ; _} rocq-9.2.0/test-suite/output/SortQuality.v000066400000000000000000000010061516144147600206310ustar00rootroot00000000000000Ltac show H := let T := type of H in let s := type of T in idtac s. Module M1. Goal True. Proof. refine (let H := _ in _). show H. Set Printing Universes. show H. Set Printing Sort Qualities. show H. Unset Printing Universes. show H. Abort. End M1. Module M2. Set Universe Polymorphism. Lemma foo@{s;u|} (A : Type@{s;u}) : True. Proof. Check A. Set Printing Universes. Check A. Set Printing Sort Qualities. Check A. Unset Printing Universes. Check A. Abort. End M2. rocq-9.2.0/test-suite/output/StringNotationErrors.out000066400000000000000000000010651516144147600230570ustar00rootroot00000000000000"hello" : smallstring File "./output/StringNotationErrors.v", line 21, characters 13-30: The command has indeed failed with message: Cannot interpret this string as a value of type smallstring ("not a small string: too long string"%pstring) "too long string" : smallstring "hello" : smallstring File "./output/StringNotationErrors.v", line 45, characters 13-30: The command has indeed failed with message: Cannot interpret this string as a value of type smallstring (NotSmallString "too long string") SmallString "too long string" : smallstring rocq-9.2.0/test-suite/output/StringNotationErrors.v000066400000000000000000000022751516144147600225210ustar00rootroot00000000000000Require Import PrimInt63 PrimString. Inductive smallstring := SmallString (_:string). Declare Scope smallstring_scope. Open Scope smallstring_scope. Module V1. Definition of_smallstring '(SmallString v) := v. Definition to_smallstring v := if PrimInt63.leb (length v) 10 then Ok (SmallString v) else Error (cat "not a small string: " v). String Notation smallstring to_smallstring of_smallstring : smallstring_scope. Check "hello". Fail Check "too long string". (* printing function doesn't check so we print something that doesn't parse *) Check SmallString "too long string". End V1. Module V2. Inductive smallstring_error := NotSmallString (_:string). Definition to_smallstring v := if PrimInt63.leb (length v) 10 then Ok (SmallString v) else Error (NotSmallString v). Definition of_smallstring '(SmallString v) := match to_smallstring v with | Ok _ => Ok v | Error e => Error e end. String Notation smallstring to_smallstring of_smallstring : smallstring_scope. Check "hello". Fail Check "too long string". (* printing function produces an error message but its content is ignored *) Check SmallString "too long string". End V2. rocq-9.2.0/test-suite/output/Succeed.out000066400000000000000000000006131516144147600202510ustar00rootroot000000000000000 : nat File "./output/Succeed.v", line 5, characters 11-12: The command has indeed failed with message: The reference x was not found in the current environment. File "./output/Succeed.v", line 7, characters 19-23: The command has indeed failed with message: The term "Prop" has type "Type" while it is expected to have type "Prop" (universe inconsistency: Cannot enforce Set+1 <= Prop). rocq-9.2.0/test-suite/output/Succeed.v000066400000000000000000000001351516144147600177060ustar00rootroot00000000000000 Succeed Check 0. Succeed Definition x := 0. Fail Check x. Fail Succeed Check Prop : Prop. rocq-9.2.0/test-suite/output/SuggestNotFoundRef.out000066400000000000000000000002601516144147600224270ustar00rootroot00000000000000File "./output/SuggestNotFoundRef.v", line 1, characters 6-10: Error: The reference plas was not found in the current environment. Did you mean plus? coqc exited with code 1 rocq-9.2.0/test-suite/output/SuggestNotFoundRef.v000066400000000000000000000000141516144147600220620ustar00rootroot00000000000000Check plas. rocq-9.2.0/test-suite/output/SuggestProofUsing.out000066400000000000000000000013741516144147600223400ustar00rootroot00000000000000File "./output/SuggestProofUsing.v", line 8, characters 31-43: Warning: "Proof term." is deprecated. Use "Proof. exact term. Qed." instead. [deprecated-exact-proof,deprecated-since-9.2,deprecated,default] The proof of Nat should start with one of the following commands: Proof using . Proof using Type*. Proof using Type. The proof of foo should start with one of the following commands: Proof using A B. Proof using All. File "./output/SuggestProofUsing.v", line 53, characters 31-42: Warning: "Proof term." is deprecated. Use "Proof. exact term. Qed." instead. [deprecated-exact-proof,deprecated-since-9.2,deprecated,default] The proof of sec_exactproof should start with one of the following commands: Proof using . Proof using Type*. Proof using Type. rocq-9.2.0/test-suite/output/SuggestProofUsing.v000066400000000000000000000022131516144147600217670ustar00rootroot00000000000000Require Program.Tactics. Set Suggest Proof Using. Set Warnings "-opaque-let". Lemma nosec : nat. Proof. exact 0. Qed. Lemma nosec_exactproof : bool. Proof false. Program Definition nosec_program : nat := _. Next Obligation. exact 1. Qed. Lemma nosec_abstract : nat. Proof. abstract exact 3. Defined. Section Sec. Variables A B : Type. (* Some normal lemma. *) Lemma Nat : Set. Proof. exact nat. Qed. (* Make sure All is suggested even though we add an unused variable to the context. *) Let foo : Type. Proof. exact (A -> B). Qed. (* Having a [Proof using] disables the suggestion message. *) Definition bar : Type. Proof using A. exact A. Qed. (* Transparent definitions don't get a suggestion message. *) Definition baz : Type. Proof. exact A. Defined. (* No suggest, is this OK? There's nowhere to put it anyway. *) Program Definition program : nat := _. Next Obligation. exact 1. Qed. (* Must not suggest *) Lemma sec_abstract : nat. Proof. abstract exact 3. Defined. (* Suggests even though there's nowhere to put it, bug? *) Lemma sec_exactproof : bool. Proof true. End Sec. rocq-9.2.0/test-suite/output/Sum.out000066400000000000000000000001431516144147600174400ustar00rootroot00000000000000nat + nat + {True} : Set {True} + {True} + {True} : Set nat + {True} + {True} : Set rocq-9.2.0/test-suite/output/Sum.v000066400000000000000000000001351516144147600170770ustar00rootroot00000000000000Check (nat + nat + {True}). Check ({True} + {True} + {True}). Check (nat + {True} + {True}). rocq-9.2.0/test-suite/output/Tactics.out000066400000000000000000000013351516144147600202720ustar00rootroot00000000000000Ltac f H := split; [ a H | e H ] Ltac g := match goal with | |- context [ if ?X then _ else _ ] => case X end File "./output/Tactics.v", line 22, characters 13-19: The command has indeed failed with message: H is already used. File "./output/Tactics.v", line 23, characters 20-26: The command has indeed failed with message: H is already used. a File "./output/Tactics.v", line 36, characters 29-34: The command has indeed failed with message: The term "False" has type "Prop" while it is expected to have type "True". File "./output/Tactics.v", line 42, characters 16-17: The command has indeed failed with message: This variable is used in hypothesis H. Ltac test a b c d e := apply a, b in c as [], d, e as -> rocq-9.2.0/test-suite/output/Tactics.v000066400000000000000000000021431516144147600177260ustar00rootroot00000000000000(* Test printing of Tactic Notation *) Tactic Notation "a" constr(x) := apply x. Tactic Notation "e" constr(x) := exact x. Ltac f H := split; [a H|e H]. Print Ltac f. (* Test printing of match context *) (* Used to fail after translator removal (see BZ#1070) *) Ltac g := match goal with |- context [if ?X then _ else _ ] => case X end. Print Ltac g. (* Test an error message (BZ#5390) *) Lemma myid (P : Prop) : P <-> P. Proof. split; auto. Qed. Goal True -> (True /\ True) -> True. Proof. intros H. Fail intros [H%myid ?]. Fail destruct 1 as [H%myid ?]. Abort. (* Test that assert_succeeds only runs a tactic once *) Ltac should_not_loop := idtac + should_not_loop. Goal True. assert_succeeds should_not_loop. assert_succeeds (idtac "a" + idtac "b"). (* should only output "a" *) Abort. (* assert_succeeds preserves the error *) Goal True. Fail assert_succeeds exact False. Abort. Module IntroWildcard. Theorem foo : { p:nat*nat & p = (0,0) } -> True. Fail intros ((n,_),H). Abort. End IntroWildcard. Module ApplyIn. Ltac test a b c d e := apply a, b in c as [], d, e as ->. Print test. End ApplyIn. rocq-9.2.0/test-suite/output/TermSyntax.out000066400000000000000000000004571516144147600210220ustar00rootroot00000000000000nat * nat : Type : Type 0 * 0 : nat : nat Z0 * Z0 : Z : Z File "./output/TermSyntax.v", line 11, characters 17-22: The command has indeed failed with message: Unknown interpretation for notation "{ _ ; _ }". This notation is available in b_scope. fun '(exist _ x _) => x : b -> bool rocq-9.2.0/test-suite/output/TermSyntax.v000066400000000000000000000005331516144147600204530ustar00rootroot00000000000000(* Check cast setting scopes *) Check nat * nat : Type. Check 0 * 0 : nat. Require Import BinNums IntDef. Infix "*" := Z.mul : Z_scope. Check Z0 * Z0 : Z. Declare Scope b_scope. Definition b := {x:bool|x=true}. Notation "{ x ; y }" := (exist _ x y) : b_scope. Fail Check fun '({x;y}:b) => x. Bind Scope b_scope with b. Check fun '({x;y}:b) => x. rocq-9.2.0/test-suite/output/TranspModtype.out000066400000000000000000000001311516144147600215020ustar00rootroot00000000000000TrM.A = M.A : Set OpM.A = M.A : Set TrM.B = M.B : Set *** [ OpM.B : Set ] rocq-9.2.0/test-suite/output/TranspModtype.v000066400000000000000000000006011516144147600211420ustar00rootroot00000000000000Module Type SIG. Axiom A : Set. Axiom B : Set. End SIG. Module M : SIG. Definition A := nat. Definition B := nat. End M. Module N <: SIG := M. Module TranspId (X: SIG) <: SIG with Definition A := X.A := X. Module OpaqueId (X: SIG) : SIG with Definition A := X.A := X. Module TrM := TranspId M. Module OpM := OpaqueId M. Print TrM.A. Print OpM.A. Print TrM.B. Print OpM.B. rocq-9.2.0/test-suite/output/TypeclassDebug.out000066400000000000000000000015121516144147600216130ustar00rootroot00000000000000Debug: 1: looking for foo without backtracking Debug: 1.1: simple apply H on foo, 1 subgoal(s) Debug: 1.1-1 : foo Debug: 1.1-1: looking for foo without backtracking Debug: 1.1-1.1: simple apply H on foo, 1 subgoal(s) Debug: 1.1-1.1-1 : foo Debug: 1.1-1.1-1: looking for foo without backtracking Debug: 1.1-1.1-1.1: simple apply H on foo, 1 subgoal(s) Debug: 1.1-1.1-1.1-1 : foo Debug: 1.1-1.1-1.1-1: looking for foo without backtracking Debug: 1.1-1.1-1.1-1.1: simple apply H on foo, 1 subgoal(s) Debug: 1.1-1.1-1.1-1.1-1 : foo Debug: 1.1-1.1-1.1-1.1-1: looking for foo without backtracking Debug: 1.1-1.1-1.1-1.1-1.1: simple apply H on foo, 1 subgoal(s) Debug: 1.1-1.1-1.1-1.1-1.1-1 : foo File "./output/TypeclassDebug.v", line 13, characters 5-33: The command has indeed failed with message: Tactic failure: Proof search reached its limit. rocq-9.2.0/test-suite/output/TypeclassDebug.v000066400000000000000000000004231516144147600212510ustar00rootroot00000000000000(* show alternating separators in typeclass debug output; see discussion in PR #868 *) Parameter foo : Prop. Axiom H : foo -> foo. #[global] Create HintDb foo. #[global] Hint Resolve H : foo. Goal foo. Typeclasses eauto := debug. Fail typeclasses eauto 5 with foo. Abort. rocq-9.2.0/test-suite/output/UnboundRef.out000066400000000000000000000002361516144147600207460ustar00rootroot00000000000000File "./output/UnboundRef.v", line 1, characters 16-17: The command has indeed failed with message: The reference a was not found in the current environment. rocq-9.2.0/test-suite/output/UnboundRef.v000066400000000000000000000001231516144147600203770ustar00rootroot00000000000000Fail Check Prop a b. (* Prop is because we need a real head for the application *) rocq-9.2.0/test-suite/output/UnclosedBlocks.out000066400000000000000000000001441516144147600216070ustar00rootroot00000000000000Error: The section Baz, module type Bar and module Foo need to be closed. coqc exited with code 1 rocq-9.2.0/test-suite/output/UnclosedBlocks.v000066400000000000000000000002661516144147600212520ustar00rootroot00000000000000Module Foo. Module Closed. End Closed. Module Type Bar. Section Baz. (* end-of-compilation error message reports unclosed sections, blocks, and module types *) rocq-9.2.0/test-suite/output/UnexpectedType.out000066400000000000000000000003751516144147600216510ustar00rootroot00000000000000File "./output/UnexpectedType.v", line 33, characters 22-30: The command has indeed failed with message: Found type "A β†’ UU" where "?T" was expected (unable to find a well-typed instantiation for "?T": cannot ensure that "Type" is a subtype of "UU"). rocq-9.2.0/test-suite/output/UnexpectedType.v000066400000000000000000000017451516144147600213110ustar00rootroot00000000000000 Notation "'Ξ»' x .. y , t" := (fun x => .. (fun y => t) ..) (at level 200, x binder, y binder, right associativity). (* type this in emacs in agda-input method with \lambda *) Notation "x β†’ y" := (x -> y) (at level 99, y at level 200, right associativity): type_scope. (* written \to or \r- in Agda input method *) (* the level comes from sub/coq/theories/Unicode/Utf8_core.v *) Set Primitive Projections. Set Nonrecursive Elimination Schemes. Definition UU := Type. Identity Coercion fromUUtoType : UU >-> Sortclass. Record total2 { T: UU } ( P: T -> UU ) := tpair { pr1 : T; pr2 : P pr1 }. Arguments tpair {_} _ _ _. Arguments pr1 {_ _} _. Arguments pr2 {_ _} _. Notation "'βˆ‘' x .. y , P" := (total2 (Ξ» x, .. (total2 (Ξ» y, P)) ..)) (at level 200, x binder, y binder, right associativity) : type_scope. (* type this in emacs in agda-input method with \sum *) Section Test. Variables (A : UU) (P: (A β†’ UU) β†’ UU). Fail Check βˆ‘ (F : A β†’ UU), P(F). End Test. rocq-9.2.0/test-suite/output/UnivBinders.out000066400000000000000000000225361516144147600211360ustar00rootroot00000000000000Inductive Empty@{uu} : Type@{uu} := . (* uu |= *) Record PWrap@{uu} (A : Type@{uu}) : Type@{uu} := pwrap { punwrap : A }. (* uu |= *) PWrap has primitive projections with eta conversion. Arguments PWrap A%_type_scope Arguments pwrap A%_type_scope punwrap Arguments punwrap A%_type_scope p Record PWrap@{uu} (A : Type@{uu}) : Type@{uu} := pwrap { punwrap : A }. (* uu |= *) PWrap has primitive projections with eta conversion. Arguments PWrap A%_type_scope Arguments pwrap A%_type_scope punwrap Arguments punwrap A%_type_scope p Record RWrap@{uu} (A : Type@{uu}) : Type@{uu} := rwrap { runwrap : A }. (* uu |= *) Arguments RWrap A%_type_scope Arguments rwrap A%_type_scope runwrap Arguments runwrap A%_type_scope r runwrap@{uu} = fun (A : Type@{uu}) (r : RWrap@{uu} A) => let (runwrap) := r in runwrap : forall A : Type@{uu}, RWrap@{uu} A -> A (* uu |= *) runwrap is a projection of RWrap Arguments runwrap A%_type_scope r Wrap@{uu} = fun A : Type@{uu} => A : Type@{uu} -> Type@{uu} (* uu |= *) Arguments Wrap A%_type_scope wrap@{uu} = fun (A : Type@{uu}) (Wrap : Wrap@{uu} A) => Wrap : forall {A : Type@{uu}}, Wrap@{uu} A -> A (* uu |= *) Arguments wrap {A}%_type_scope {Wrap} bar@{uu} = nat : Wrap@{uu} Set (* uu |= Set < uu *) foo@{uu u v} = Type@{u} -> Type@{v} -> Type@{uu} : Type@{max(uu+1,u+1,v+1)} (* uu u v |= *) Type@{i} -> Type@{j} : Type@{max(i+1,j+1)} (* {j i} |= *) = Type@{i} -> Type@{j} : Type@{max(i+1,j+1)} (* {j i} |= *) mono = Type@{mono.uu} : Type@{mono.uu+1} mono : Type@{mono.uu+1} Type@{mono.uu} : Type@{mono.uu+1} File "./output/UnivBinders.v", line 50, characters 2-31: The command has indeed failed with message: Universe uu already exists. monomono : Type@{MONOU+1} mono.monomono : Type@{mono.MONOU+1} monomono : Type@{MONOU+1} mono : Type@{mono.uu+1} File "./output/UnivBinders.v", line 70, characters 0-52: The command has indeed failed with message: Universe uu already exists. bobmorane = let tt := Type@{fooS.u1} in let ff := Type@{fooS.u3} in tt -> ff : Type@{max(fooS.u0,fooS.u2)} File "./output/UnivBinders.v", line 87, characters 23-25: The command has indeed failed with message: Universe uu already bound. foo@{E M N} = Type@{M} -> Type@{N} -> Type@{E} : Type@{max(E+1,M+1,N+1)} (* E M N |= *) foo@{uu u v} = Type@{u} -> Type@{v} -> Type@{uu} : Type@{max(uu+1,u+1,v+1)} (* uu u v |= *) foo@{u u IMPORTANT} = Type@{u} -> Type@{IMPORTANT} -> Type@{u} : Type@{max(u+1,u+1,IMPORTANT+1)} (* u u IMPORTANT |= *) Inductive Empty@{E} : Type@{E} := . (* E |= *) Record PWrap@{E} (A : Type@{E}) : Type@{E} := pwrap { punwrap : A }. (* E |= *) PWrap has primitive projections with eta conversion. Arguments PWrap A%_type_scope Arguments pwrap A%_type_scope punwrap Arguments punwrap A%_type_scope p punwrap@{K} : forall A : Type@{K}, PWrap@{K} A -> A (* K |= *) punwrap is universe polymorphic punwrap is a primitive projection of PWrap Arguments punwrap A%_type_scope p punwrap is transparent Expands to: Constant UnivBinders.punwrap Declared in library UnivBinders, line 12, characters 43-50 File "./output/UnivBinders.v", line 104, characters 0-19: The command has indeed failed with message: Universe instance length for foo is 3 but should be 1. File "./output/UnivBinders.v", line 105, characters 0-20: The command has indeed failed with message: Universe instance length for mono is 0 but should be 1. File "./output/UnivBinders.v", line 108, characters 0-33: The command has indeed failed with message: This object does not support universe names. File "./output/UnivBinders.v", line 112, characters 0-50: The command has indeed failed with message: Cannot enforce v < u because u < gU < gV < v insec@{v} = Type@{uu} -> Type@{v} : Type@{max(uu+1,v+1)} (* v |= *) Inductive insecind@{k} : Type@{k+1} := inseccstr : Type@{k} -> insecind@{k}. (* k |= *) Arguments inseccstr _%_type_scope insec@{uu v} = Type@{uu} -> Type@{v} : Type@{max(uu+1,v+1)} (* uu v |= *) Inductive insecind@{uu k} : Type@{k+1} := inseccstr : Type@{k} -> insecind@{uu k}. (* uu k |= *) Arguments inseccstr _%_type_scope insec2@{u} = Prop : Type@{Set+1} (* u |= *) inmod@{uu} = Type@{uu} : Type@{uu+1} (* uu |= *) SomeMod.inmod@{uu} = Type@{uu} : Type@{uu+1} (* uu |= *) inmod@{uu} = Type@{uu} : Type@{uu+1} (* uu |= *) Applied.infunct@{uu v} = inmod@{uu} -> Type@{v} : Type@{max(uu+1,v+1)} (* uu v |= *) axfoo@{i u u0} : Type@{u} -> Type@{i} (* i u u0 |= *) axfoo is universe polymorphic Arguments axfoo _%_type_scope Expands to: Constant UnivBinders.axfoo Declared in library UnivBinders, line 151, characters 6-11 axbar@{i u u0} : Type@{u0} -> Type@{i} (* i u u0 |= *) axbar is universe polymorphic Arguments axbar _%_type_scope Expands to: Constant UnivBinders.axbar Declared in library UnivBinders, line 151, characters 17-22 axfoo' : Type@{axfoo'.u0} -> Type@{axfoo'.i} axfoo' is not universe polymorphic Arguments axfoo' _%_type_scope Expands to: Constant UnivBinders.axfoo' Declared in library UnivBinders, line 152, characters 18-24 axbar' : Type@{axfoo'.u1} -> Type@{axfoo'.i} axbar' is not universe polymorphic Arguments axbar' _%_type_scope Expands to: Constant UnivBinders.axbar' Declared in library UnivBinders, line 152, characters 30-36 *** [ axfoo@{i u u0} : Type@{u} -> Type@{i} ] (* i u u0 |= *) Arguments axfoo _%_type_scope *** [ axbar@{i u u0} : Type@{u0} -> Type@{i} ] (* i u u0 |= *) Arguments axbar _%_type_scope *** [ axfoo' : Type@{axfoo'.u0} -> Type@{axfoo'.i} ] Arguments axfoo' _%_type_scope *** [ axbar' : Type@{axfoo'.u1} -> Type@{axfoo'.i} ] Arguments axbar' _%_type_scope File "./output/UnivBinders.v", line 158, characters 19-26: The command has indeed failed with message: When declaring multiple assumptions in one command, only the first name is allowed to mention a universe binder (which will be shared by the whole block). foo@{i} = Type@{M.i} -> Type@{i} : Type@{max(M.i+1,i+1)} (* i |= *) Type@{u0} -> Type@{UnivBinders.83} : Type@{max(u0+1,UnivBinders.83+1)} (* {UnivBinders.83} |= *) bind_univs.mono = Type@{bind_univs.mono.u} : Type@{bind_univs.mono.u+1} bind_univs.poly@{u} = Type@{u} : Type@{u+1} (* u |= *) Inductive MutualR1@{u} (A : Type@{u}) : Prop := Build_MutualR1 { p1 : MutualR2@{u} A } with MutualR2@{u} (A : Type@{u}) : Prop := Build_MutualR2 { p2 : MutualR1@{u} A }. (* u |= *) Arguments MutualR1 A%_type_scope Arguments Build_MutualR1 A%_type_scope p1 Arguments p1 A%_type_scope m Arguments MutualR2 A%_type_scope Arguments Build_MutualR2 A%_type_scope p2 Arguments p2 A%_type_scope m Inductive MutualI1@{u u0} (A : Type@{u}) : Type@{u0} := C1 : MutualI2@{u u0} A -> MutualI1@{u u0} A with MutualI2@{u u0} (A : Type@{u}) : Type@{u0} := C2 : MutualI1@{u u0} A -> MutualI2@{u u0} A. (* u u0 |= *) Arguments MutualI1 A%_type_scope Arguments C1 A%_type_scope p1 Arguments MutualI2 A%_type_scope Arguments C2 A%_type_scope p2 CoInductive MutualR1'@{u} (A : Type@{u}) : Prop := Build_MutualR1' { p1' : MutualR2'@{u} A } with MutualR2'@{u} (A : Type@{u}) : Prop := Build_MutualR2' { p2' : MutualR1'@{u} A }. (* u |= *) Arguments MutualR1' A%_type_scope Arguments Build_MutualR1' A%_type_scope p1' Arguments p1' A%_type_scope m Arguments MutualR2' A%_type_scope Arguments Build_MutualR2' A%_type_scope p2' Arguments p2' A%_type_scope m CoInductive MutualI1'@{u u0} (A : Type@{u}) : Type@{u0} := C1' : MutualI2'@{u u0} A -> MutualI1'@{u u0} A with MutualI2'@{u u0} (A : Type@{u}) : Type@{u0} := C2' : MutualI1'@{u u0} A -> MutualI2'@{u u0} A. (* u u0 |= *) Arguments MutualI1' A%_type_scope Arguments C1' A%_type_scope p1 Arguments MutualI2' A%_type_scope Arguments C2' A%_type_scope p2 File "./output/UnivBinders.v", line 209, characters 0-33: The command has indeed failed with message: Universe inconsistency. Cannot enforce a < a because a = a. JMeq : forall [A : Type@{JMeq.u0}], A -> forall [B : Type@{JMeq.u1}], B -> Prop JMeq is template universe polymorphic on JMeq.u0 (cannot be instantiated to Prop) Arguments JMeq [A]%_type_scope x [B]%_type_scope _ Expands to: Inductive UnivBinders.PartialTemplate.JMeq Declared in library UnivBinders, line 219, characters 10-14 File "./output/UnivBinders.v", line 234, characters 2-38: The command has indeed failed with message: Universe u0 already exists. File "./output/UnivBinders.v", line 241, characters 6-26: The command has indeed failed with message: Tactic failure: Not equal (due to universes). eq_rect : forall (A : Type@{eq_rect.u1}) (x : A) (P : A -> Type@{eq_rect.u0}), P x -> forall y : A, x = y -> P y File "./output/UnivBinders.v", line 259, characters 18-19: Warning: Separating sorts from universes with "|" is deprecated. Use ";" instead. [deprecated-sort-poly-syntax,deprecated-since-9.1,deprecated,default] File "./output/UnivBinders.v", line 259, characters 33-34: Warning: Separating sorts from universes with "|" is deprecated. Use ";" instead. [deprecated-sort-poly-syntax,deprecated-since-9.1,deprecated,default] File "./output/UnivBinders.v", line 265, characters 16-17: Warning: Separating sorts from universes with "|" is deprecated. Use ";" instead. [deprecated-sort-poly-syntax,deprecated-since-9.1,deprecated,default] id@{Prop ; Set} : forall A : Prop, A -> A id@{SProp ; Set} : forall A : SProp, A -> A id3@{s ; u} = fun (A : Type@{s ; u}) (a : A) => a : forall A : Type@{s ; u}, A -> A (* s ; u |= Set < u *) Arguments id3 A%_type_scope a rocq-9.2.0/test-suite/output/UnivBinders.v000066400000000000000000000145771516144147600206020ustar00rootroot00000000000000(* -*- coq-prog-args: ("-top" "UnivBinders"); -*- *) Set Universe Polymorphism. Set Printing Universes. (* Unset Strict Universe Declaration. *) (* universe binders on inductive types and record projections *) Inductive Empty@{uu} : Type@{uu} := . Print Empty. Set Primitive Projections. Record PWrap@{uu} (A:Type@{uu}) := pwrap { punwrap : A }. Print PWrap. Print punwrap. Unset Primitive Projections. Record RWrap@{uu} (A:Type@{uu}) := rwrap { runwrap : A }. Print RWrap. Print runwrap. (* universe binders also go on the constants for operational typeclasses. *) Class Wrap@{uu} (A:Type@{uu}) := wrap : A. Print Wrap. Print wrap. (* Instance in lemma mode used to ignore the binders. *) #[global] Instance bar@{uu} : Wrap@{uu} Set. Proof. exact nat. Qed. Print bar. Unset Strict Universe Declaration. (* The universes in the binder come first, then the extra universes in order of appearance. *) Definition foo@{uu +} := Type -> Type@{v} -> Type@{uu}. Print foo. Check Type@{i} -> Type@{j}. Eval cbv in Type@{i} -> Type@{j}. Set Strict Universe Declaration. (* Binders even work with monomorphic definitions! *) Monomorphic Definition mono@{uu} := Type@{uu}. Print mono. Check mono. Check Type@{mono.uu}. Module mono. Fail Monomorphic Universe uu. Monomorphic Universe MONOU. Monomorphic Definition monomono := Type@{MONOU}. Check monomono. Monomorphic Inductive monoind@{i} : Type@{i} := . Monomorphic Record monorecord@{i} : Type@{i} := mkmonorecord {}. End mono. Check mono.monomono. (* qualified MONOU *) Import mono. Check monomono. (* unqualified MONOU *) Check mono. (* still qualified mono.u *) Monomorphic Constraint Set < UnivBinders.mono.uu. Module mono2. Monomorphic Universe uu. End mono2. Fail Monomorphic Definition mono2@{uu} := Type@{uu}. Module SecLet. Unset Universe Polymorphism. Section fooS. (* Fail Let foo@{} := Type@{uu}. (* doesn't parse: Let foo@{...} doesn't exist *) *) Unset Strict Universe Declaration. (* the names used disappear, and fresh names are generated instead of exposing raw ints *) Let tt : Type@{uu} := Type@{v}. #[clearbody] Let ff : Type@{uu}. Proof. exact Type@{v}. Defined. Definition bobmorane := tt -> ff. End fooS. Print bobmorane. End SecLet. (* fun x x => foo is nonsense with local binders *) Fail Definition fo@{uu uu} := Type@{uu}. (* Using local binders for printing. *) Print foo@{E M N}. (* Underscores discard the name if there's one. *) Print foo@{_ _ _}. (* Can use a name for multiple universes *) Print foo@{u u IMPORTANT}. (* Also works for inductives and records. *) Print Empty@{E}. Print PWrap@{E}. (* Also works for About. *) About punwrap@{K}. (* Instance length check. *) Fail Print foo@{E}. Fail Print mono@{E}. (* Not everything can be printed with custom universe names. *) Fail Print Stdlib.Init.Logic@{E}. (* Nice error when constraints are impossible. *) Monomorphic Universes gU gV. Monomorphic Constraint gU < gV. Fail Lemma foo'@{u v|u < gU, gV < v, v < u} : nat. Section SomeSec. Universe uu. Definition insec@{v} := Type@{uu} -> Type@{v}. Print insec. Inductive insecind@{k} := inseccstr : Type@{k} -> insecind. Print insecind. End SomeSec. Print insec. Print insecind. Section SomeSec2. Universe u. Definition insec2@{} := Prop. End SomeSec2. Print insec2. Module SomeMod. Definition inmod@{uu} := Type@{uu}. Print inmod. End SomeMod. Print SomeMod.inmod. Import SomeMod. Print inmod. Module Type SomeTyp. Definition inmod := Type. End SomeTyp. Module SomeFunct (In : SomeTyp). Definition infunct@{uu v} := In.inmod@{uu} -> Type@{v}. End SomeFunct. Module Applied := SomeFunct(SomeMod). Print Applied.infunct. (* Multi-axiom declaration In polymorphic mode the domain Type gets separate universes for the different axioms, but all axioms have to declare all universes. In monomorphic mode they also get separate universes. *) Axiom axfoo@{i+} axbar : Type -> Type@{i}. Monomorphic Axiom axfoo'@{i+} axbar' : Type -> Type@{i}. About axfoo. About axbar. About axfoo'. About axbar'. Print axfoo. Print axbar. Print axfoo'. Print axbar'. Fail Axiom failfoo failbar@{i} : Type. (* Notation interaction *) Module Notas. Unset Universe Polymorphism. Module Import M. Universe i. End M. Polymorphic Definition foo@{i} := Type@{M.i} -> Type@{i}. Print foo. (* must not print Type@{i} -> Type@{i} *) End Notas. Module NoAutoNames. Monomorphic Universe u0. (* The anonymous universe doesn't get a name (names are only invented at the end of a definition/inductive) so no need to qualify u0. *) Check (Type@{u0} -> Type). End NoAutoNames. (* Universe binders survive through compilation, sections and modules. *) Require TestSuite.bind_univs. Print bind_univs.mono. Print bind_univs.poly. Module MutualTypes. Inductive MutualR1 (A:Type) := { p1 : MutualR2 A } with MutualR2 (A:Type) := { p2 : MutualR1 A }. Print MutualR1. Inductive MutualI1 (A:Type) := C1 (p1 : MutualI2 A) with MutualI2 (A:Type) := C2 (p2 : MutualI1 A). Print MutualI1. CoInductive MutualR1' (A:Type) := { p1' : MutualR2' A } with MutualR2' (A:Type) := { p2' : MutualR1' A }. Print MutualR1'. CoInductive MutualI1' (A:Type) := C1' (p1 : MutualI2' A) with MutualI2' (A:Type) := C2' (p2 : MutualI1' A). Print MutualI2'. End MutualTypes. Module Inconsistency. Set Universe Polymorphism. Definition g@{a b} := Type@{a} : Type@{b}. Fail Definition h@{a} := g@{a a}. End Inconsistency. Module PartialTemplate. Set Implicit Arguments. Unset Elimination Schemes. Unset Universe Polymorphism. Inductive JMeq (A:Type) (x:A) : forall B:Type, B -> Prop := JMeq_refl : JMeq x x. About JMeq. End PartialTemplate. Module Collision. Unset Universe Polymorphism. Module x. Universe u0. Definition a := Type@{u0}. End x. Fail Definition x@{u0} := Type@{u0}. Definition x := Type. Goal True. Fail let a := eval cbv in x.a in let b := eval cbv in x in constr_eq_strict a b. let a := eval cbv in Type@{x.u1} in let b := eval cbv in x in constr_eq_strict a b. Abort. End Collision. Module Schemes. Check eq_rect. End Schemes. Module SortPoly. Set Warnings "deprecated-sort-poly-syntax". Definition idu@{u} (A:Type@{u}) (a:A) := a. Definition id@{s|u|} (A:Type@{s|u}) (a:A) := a. Definition id2@{s;u} (A:Type@{s;u}) (a:A) := a. Definition id3@{s ; u | Set < u} (A:Type@{s;u}) (a:A) := a. Check id@{Prop|Set}. Check id@{SProp;Set}. Print id3. End SortPoly. rocq-9.2.0/test-suite/output/UnivNotations.out000066400000000000000000000013001516144147600215100ustar00rootroot00000000000000! nat : Type foo Set nat : Type foo Type@{s ; _} S : Type File "./output/UnivNotations.v", line 20, characters 13-14: The command has indeed failed with message: The term "S" has type "Type@{s ; _}" while it is expected to have type "Type" (universe inconsistency: Cannot enforce Type@{s | Set} <= UnivNotations.24). 1 goal ============================ forall A : Type, A -> ! A foo Type@{UnivNotations.27} nat : Type@{foo.u1} (* {UnivNotations.27} |= UnivNotations.27 < foo.u0 *) foo Type@{s ; Set} S : Type@{foo.u1} (* {} |= Set < foo.u0 *) 1 goal ============================ forall A : Type@{Ξ±4 ; UnivNotations.29}, A -> foo Type@{Ξ±4 ; UnivNotations.29} A rocq-9.2.0/test-suite/output/UnivNotations.v000066400000000000000000000020531516144147600211540ustar00rootroot00000000000000Axiom foo : forall A:Type, A -> Type. (* this test is about checking when Type in a notation is considered to match a term *) Notation "! x" := (foo Type x) (at level 2). (* first with Printing Universes off *) (* terms produced using the notation print using the notation *) Check ! nat. (* Set does not match Type *) Check foo Set nat. Sort s. Axiom S : Type@{s;Set}. (* rigid sorts (here global sort) should not match Type but currently do *) Check foo _ S. Fail Check ! S. Goal True. (* sort unification variable matches Type (and is printed as Type in the [forall] annotation) *) (* NB don't use Check here as it collapses before printing (maybe this will change someday?) *) assert (forall A, A -> foo _ A). 2:trivial. Show. Abort. (* now with Printing Universes on *) Set Printing Universes. (* Printing Universes makes universes not match Type *) Check ! nat. (* global sort still doesn't match Type *) Check foo _ S. Goal True. (* sort unif variable doesn't match Type *) assert (forall A, A -> foo _ A). 2:trivial. Show. Abort. rocq-9.2.0/test-suite/output/UpdateLoc.out000066400000000000000000000005221516144147600205550ustar00rootroot00000000000000File "./output/UpdateLoc.v", line 5, characters 14-15: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "False". File "./output/UpdateLoc.v", line 6, characters 7-9: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "False". rocq-9.2.0/test-suite/output/UpdateLoc.v000066400000000000000000000002761516144147600202210ustar00rootroot00000000000000Ltac r0 := refine 0. Goal False. Proof. Fail refine 0. (* before: whole tactic, after: just 0 *) Fail r0. (* before: "refine 0" in the ltac definition, after: r0 in this line *) Abort. rocq-9.2.0/test-suite/output/UsePluginWarning.out000066400000000000000000000000161516144147600221340ustar00rootroot00000000000000type foo = __ rocq-9.2.0/test-suite/output/UsePluginWarning.v000066400000000000000000000002031516144147600215700ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-w" "-extraction-logical-axiom") -*- *) Require Extraction. Axiom foo : Prop. Extraction foo. rocq-9.2.0/test-suite/output/UselessSyndef.out000066400000000000000000000000151516144147600214660ustar00rootroot00000000000000a : nat rocq-9.2.0/test-suite/output/UselessSyndef.v000066400000000000000000000001761516144147600211340ustar00rootroot00000000000000Module M. Definition a := 0. End M. Module N. Abbreviation a := M.a (only parsing). End N. Import M. Import N. Check a. rocq-9.2.0/test-suite/output/Utf8Impargs.out000066400000000000000000000003131516144147600210440ustar00rootroot00000000000000id : βˆ€ {A : Type}, A -> A id is not universe polymorphic Arguments id {A}%_type_scope a id is transparent Expands to: Constant Utf8Impargs.id Declared in library Utf8Impargs, line 6, characters 11-13 rocq-9.2.0/test-suite/output/Utf8Impargs.v000066400000000000000000000003741516144147600205110ustar00rootroot00000000000000Notation "βˆ€ x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity, format "'[ ' '[ ' βˆ€ x .. y ']' , '/' P ']'") : type_scope. (* from Utf8_core.v *) Definition id {A} (a:A) := a. About id. rocq-9.2.0/test-suite/output/Warnings.out000066400000000000000000000003221516144147600204630ustar00rootroot00000000000000File "./output/Warnings.v", line 4, characters 0-22: Warning: Projection value has no head constant: let H := tt in True in canonical instance a of b, ignoring it. [projection-no-head-constant,records,default] rocq-9.2.0/test-suite/output/Warnings.v000066400000000000000000000002731516144147600201260ustar00rootroot00000000000000(* Term in warning was not printed in the right environment at some time *) Record A := { B:Type; b:Prop }. Definition a B := {| B:=B; b:= let _ := tt in True |}. Canonical Structure a. rocq-9.2.0/test-suite/output/WithDefErrors.out000066400000000000000000000015131516144147600214250ustar00rootroot00000000000000File "./output/WithDefErrors.v", line 8, characters 0-51: The command has indeed failed with message: Incorrect constraint for label "x": expected type "nat" but found type "bool" File "./output/WithDefErrors.v", line 15, characters 0-51: The command has indeed failed with message: Incorrect constraint for label "x": the body of definitions differs: expected "0" but found "y2" File "./output/WithDefErrors.v", line 21, characters 0-52: The command has indeed failed with message: Incorrect constraint for label "p": incompatible polymorphic binders: got @{} but expected @{u} File "./output/WithDefErrors.v", line 28, characters 0-51: The command has indeed failed with message: Incorrect constraint for label "x": the universe constraints are inconsistent: Cannot enforce y4.u0 < Set because Set < y4.u0 when comparing "Type" and "Set" rocq-9.2.0/test-suite/output/WithDefErrors.v000066400000000000000000000017401516144147600210650ustar00rootroot00000000000000(* Test improved error messages for "with Definition" constraints *) (* Test 1: Type mismatch - expected nat but got bool *) Module Type T1. Parameter x : nat. End T1. Definition y1 : bool := true. Fail Module Type T1' := T1 with Definition x := y1. (* Test 2: Body mismatch - definitions with different values *) Module Type T2. Definition x := 0. End T2. Definition y2 : nat := 1. Fail Module Type T2' := T2 with Definition x := y2. (* Test 3: Polymorphic constraint mismatch *) Module Type T3. Polymorphic Parameter p : Type. End T3. Fail Module Type T3' := T3 with Definition p := nat. (* Test 4: Universe constraint issues *) Module Type T4. Parameter x : Set. End T4. Definition y4 := Type. Fail Module Type T4' := T4 with Definition x := y4. (* NOTE: WithCannotConstrainPrimitive and WithCannotConstrainSymbol errors cannot be triggered from user code because module types export primitives and symbols as parameters. These errors exist for internal consistency. *) rocq-9.2.0/test-suite/output/activation.out000066400000000000000000000017031516144147600210400ustar00rootroot00000000000000File "./output/activation.v", line 5, characters 0-47: The command has indeed failed with message: More than one interpretation bound to this notation, confirm with the "all" modifier. File "./output/activation.v", line 12, characters 0-22: The command has indeed failed with message: No notation provided. File "./output/activation.v", line 16, characters 0-24: The command has indeed failed with message: Found no matching notation to enable or disable. [no-notation-to-enable-or-disable,syntax,default] a : Type File "./output/activation.v", line 26, characters 11-12: The command has indeed failed with message: The reference a was not found in the current environment. Prop : Type a : Type a : Type 0 : nat x : bool 0 : nat File "./output/activation.v", line 47, characters 0-49: The command has indeed failed with message: Found no matching notation to enable or disable. [no-notation-to-enable-or-disable,syntax,default] rocq-9.2.0/test-suite/output/activation.v000066400000000000000000000024531516144147600205010ustar00rootroot00000000000000Disable Notation "x + y" := (Nat.add x y). Declare Custom Entry foo. Notation "x * y" := (Nat.mul x y) (in custom foo at level 2). Fail Disable Notation "x * y" := (Nat.mul x y). (* need flag all *) Disable Notation "x * y" := (Nat.mul x y) (all). Enable Notation := (Nat.mul _ _) : nat_scope. Disable Notation := ex2 (all). Disable Notation "<=" (all). Disable Notation (all) : nat_scope. Fail Disable Notation. Module Abbrev. Set Warnings "+no-notation-to-enable-or-disable". Fail Disable Notation f. (* no abbreviation with such suffix *) Set Warnings "no-notation-to-enable-or-disable". Abbreviation f w := (S w). Disable Notation f w := (S w). Enable Notation := (S _). Module A. Abbreviation a := Prop. End A. Include A. Disable Notation A.a. Check a. Disable Notation a. Fail Check a. Check Prop. Enable Notation a (all). (* Note: reactivation is not necessarily in the same order as it was earlier *) Check a. Check Prop. Module Shadowed. Abbreviation x := true. End Shadowed. Import Shadowed. Abbreviation x := 0. Check x. Disable Notation Abbrev.x. Check x. Enable Notation x. Check x. End Abbrev. Module Bug17782. Declare Custom Entry trm. Set Warnings "+no-notation-to-enable-or-disable". Fail Disable Notation "'foo' _" (in custom trm). Set Warnings "no-notation-to-enable-or-disable". End Bug17782. rocq-9.2.0/test-suite/output/apply_with.out000066400000000000000000000016331516144147600210610ustar00rootroot00000000000000File "./output/apply_with.v", line 3, characters 11-26: The command has indeed failed with message: No such bound variable d (possible names are: a, b and c). File "./output/apply_with.v", line 4, characters 11-26: The command has indeed failed with message: Unable to find an instance for the variable b. File "./output/apply_with.v", line 5, characters 24-25: The command has indeed failed with message: No such bound variable d (possible names are: a, b and c). File "./output/apply_with.v", line 6, characters 5-31: The command has indeed failed with message: Unable to find an instance for the variables b, c. File "./output/apply_with.v", line 14, characters 23-24: The command has indeed failed with message: No such bound variable c (possible names are: a and b). File "./output/apply_with.v", line 15, characters 5-16: The command has indeed failed with message: Unable to find an instance for the variables a, b. rocq-9.2.0/test-suite/output/apply_with.v000066400000000000000000000005741516144147600205220ustar00rootroot00000000000000Axiom f : forall a b c, a + b = 0 -> c = 0. Goal 0 = 0. Fail apply f with (d := 0). Fail apply f with (a := 0). Fail rewrite <- f with (d := 0). Fail rewrite <- f with (a := 0). apply f with (a:=0) (b:=0). auto. Qed. Axiom g : forall a b, S a = S b. Goal forall n, n = 0. intros n. Fail injection g with (c := 0). Fail injection g. injection g with (a := n) (b := 0). auto. Qed. rocq-9.2.0/test-suite/output/auto.out000066400000000000000000000007501516144147600176500ustar00rootroot00000000000000(* info auto: *) simple apply or_intror (in core). intro. assumption. (* debug auto: *) * assumption. (*fail*) * intro. (*fail*) * simple apply or_intror (in core). (*success*) ** assumption. (*fail*) ** intro. (*success*) ** assumption. (*success*) (* info eauto: *) simple apply or_intror. intro. exact H. (* debug eauto: *) Debug: 1 depth=5 Debug: 1.1 depth=4 simple apply or_intror Debug: 1.1.1 depth=4 intro Debug: 1.1.1.1 depth=4 exact H (* info trivial: *) exact I (in core). rocq-9.2.0/test-suite/output/auto.v000066400000000000000000000002711516144147600173040ustar00rootroot00000000000000(* testing info_*/debug auto/eauto *) Goal False \/ (True -> True). Succeed info_auto. Succeed debug auto. Succeed info_eauto. debug eauto. Defined. Goal True. info_trivial. Defined. rocq-9.2.0/test-suite/output/auto_order.out000066400000000000000000000013731516144147600210450ustar00rootroot00000000000000Non-discriminated database Unfoldable variable definitions: none Unfoldable constant definitions: none Unfoldable projection definitions: none Cut: emp For any goal -> (*external*) (idtac "second"; fail) (cost 1, id 0) (*external*) (idtac "first"; fail) (cost 1, id 0) (*external*) (idtac "fourth"; fail) (cost 2, id 0) (*external*) (idtac "third"; fail) (cost 2, id 0) (* info auto: *) second first fourth third fifth, different hintDb idtac. (* info eauto: *) second first fifth, different hintDb fourth third idtac. second first fifth, different hintDb fourth third File "./output/auto_order.v", line 26, characters 5-45: The command has indeed failed with message: Tactic failure: Proof search failed. rocq-9.2.0/test-suite/output/auto_order.v000066400000000000000000000013221516144147600204750ustar00rootroot00000000000000Create HintDb plus. Hint Constants Opaque : plus. Hint Projections Opaque : plus. Hint Variables Opaque : plus. Hint Extern 1 => idtac "first"; fail : plus. Hint Extern 1 => idtac "second"; fail : plus. Hint Extern 2 => idtac "third"; fail : plus. Hint Extern 2 => idtac "fourth"; fail : plus. Create HintDb plus2. Hint Constants Opaque : plus2. Hint Projections Opaque : plus2. Hint Variables Opaque : plus2. Hint Extern 1 => idtac "fifth, different hintDb"; fail : plus2. Print HintDb plus. Goal False. (* auto tries hintdbs in order, ignoring cost. the others apply cost across hintdbs *) info_auto with plus plus2 nocore. info_eauto with plus plus2 nocore. Fail typeclasses eauto with plus plus2 nocore. Abort. rocq-9.2.0/test-suite/output/bug12442.out000066400000000000000000000005751516144147600200570ustar00rootroot00000000000000File "./output/bug12442.v", line 6, characters 7-19: The command has indeed failed with message: No product even after head-reduction. File "./output/bug12442.v", line 7, characters 7-18: The command has indeed failed with message: Not an inductive product. File "./output/bug12442.v", line 9, characters 7-25: The command has indeed failed with message: Not an inductive product. rocq-9.2.0/test-suite/output/bug12442.v000066400000000000000000000002421516144147600175040ustar00rootroot00000000000000Parameter A B : Prop. Axiom P : inhabited (A -> B). Goal A -> True. Proof. Fail intros ?%P ?. Fail intros []%P. intro a. Fail apply P in a as []. Abort. rocq-9.2.0/test-suite/output/bug5778.out000066400000000000000000000004431516144147600200070ustar00rootroot00000000000000File "./output/bug5778.v", line 7, characters 7-11: The command has indeed failed with message: The term "I" has type "True" which should be Set, Prop or Type. In nested Ltac calls to "c", "abs", "abstract b ltac:(())", "b", "a", "pose (I : I)" and "(I : I)", last term evaluation failed. rocq-9.2.0/test-suite/output/bug5778.v000066400000000000000000000002201516144147600174360ustar00rootroot00000000000000Set Ltac Backtrace. Ltac a _ := pose (I : I). Ltac b _ := a (). Ltac abs _ := abstract b (). Ltac c _ := abs (). Goal True. Fail c (). Abort. rocq-9.2.0/test-suite/output/bug6404.out000066400000000000000000000004551516144147600177750ustar00rootroot00000000000000File "./output/bug6404.v", line 7, characters 7-11: The command has indeed failed with message: The term "I" has type "True" which should be Set, Prop or Type. In nested Ltac calls to "c", "abs", "transparent_abstract (tactic3)", "b", "a", "pose (I : I)" and "(I : I)", last term evaluation failed. rocq-9.2.0/test-suite/output/bug6404.v000066400000000000000000000002341516144147600174260ustar00rootroot00000000000000Set Ltac Backtrace. Ltac a _ := pose (I : I). Ltac b _ := a (). Ltac abs _ := transparent_abstract b (). Ltac c _ := abs (). Goal True. Fail c (). Abort. rocq-9.2.0/test-suite/output/bug6821.out000066400000000000000000000000731516144147600177740ustar00rootroot00000000000000forall f : nat -> Type, f x where x : nat := 1 : Type rocq-9.2.0/test-suite/output/bug6821.v000066400000000000000000000004021516144147600174260ustar00rootroot00000000000000(* Was failing at printing time with stack overflow due to an infinite eta-expansion *) Notation "x 'where' y .. z := v " := ((fun y => .. ((fun z => x) v) ..) v) (at level 11, v at next level, y binder, z binder). Check forall f, f x where x := 1. rocq-9.2.0/test-suite/output/bug7191.out000066400000000000000000000001401516144147600177700ustar00rootroot00000000000000 type unit0 = | Tt (** val f : unit0 -> unit0 **) let f _ = assert false (* absurd case *) rocq-9.2.0/test-suite/output/bug7191.v000066400000000000000000000001511516144147600174300ustar00rootroot00000000000000Require Extraction. Definition f (x : False) : unit -> unit := match x with end. Recursive Extraction f. rocq-9.2.0/test-suite/output/bug7348.out000066400000000000000000000012121516144147600177750ustar00rootroot00000000000000Extracted code successfully compiled type __ = Obj.t type unit0 = | Tt type bool = | True | False module Case1 = struct type coq_rec = { f : bool } (** val f : bool -> coq_rec -> bool **) let f _ r = r.f (** val silly : bool -> coq_rec -> __ **) let silly x b = match x with | True -> Obj.magic b.f | False -> Obj.magic Tt end module Case2 = struct type coq_rec = { f : (bool -> bool) } (** val f : bool -> coq_rec -> bool -> bool **) let f _ r = r.f (** val silly : bool -> coq_rec -> __ **) let silly x b = match x with | True -> Obj.magic b.f False | False -> Obj.magic Tt end rocq-9.2.0/test-suite/output/bug7348.v000066400000000000000000000010011516144147600174270ustar00rootroot00000000000000Require Extraction. Extraction Language OCaml. Set Extraction KeepSingleton. Module Case1. Record rec (x : bool) := { f : bool }. Definition silly x (b : rec x) := if x return (if x then bool else unit) then f x b else tt. End Case1. Module Case2. Record rec (x : bool) := { f : bool -> bool }. Definition silly x (b : rec x) := if x return (if x then bool else unit) then f x b false else tt. End Case2. Extraction TestCompile Case1.silly Case2.silly. Recursive Extraction Case1.silly Case2.silly. rocq-9.2.0/test-suite/output/bug_10739.out000066400000000000000000000017611516144147600202230ustar00rootroot00000000000000 type nat = | O | S of nat (** val f : nat **) let f = O (** val f : nat **) let f = O type nat = | O | S of nat (** val f : nat **) let f = O module M = struct (** val g : nat **) let g = f end (** val g : nat **) let g = f type nat = | O | S of nat (** val f : nat **) let f = O module M = struct (** val g : nat **) let g = f module N = struct (** val h : nat **) let h = g end end (** val h : nat **) let h = M.g type nat = | O | S of nat (** val add : nat -> nat -> nat **) let rec add n m = match n with | O -> m | S p -> S (add p m) (** val f : nat **) let f = O module M = struct (** val g : nat **) let g = f module type S = sig val b : nat end module F = functor (X:S) -> struct (** val h : nat **) let h = add g X.b end end (** val h : nat **) let h = add M.g X.b type nat = | O | S of nat type nat = | O | S of nat (** val foo : nat **) let foo = O rocq-9.2.0/test-suite/output/bug_10739.v000066400000000000000000000011671516144147600176610ustar00rootroot00000000000000Require Extraction. Definition f := 0. Module M. Recursive Extraction f. Extraction f. Definition g := f. Recursive Extraction g. Extraction g. Module Type S. Definition b := 0. End S. (* Test with sealed module *) Module N : S. Definition b := 0. Definition h := g. Recursive Extraction h. Extraction h. End N. (* Test with a functor *) Module F (X:S). Definition h := g + X.b. Recursive Extraction h. Extraction h. End F. (* Test elsewhere *) Recursive Extraction nat. Extraction nat. Module Type T. Definition foo := 0. Extraction foo. End T. End M. rocq-9.2.0/test-suite/output/bug_10803.out000066400000000000000000000001261516144147600202050ustar00rootroot00000000000000a ! : Foo where ?y : [ |- nat] a ! : Foo a : Foo -> Foo a ! : Foo rocq-9.2.0/test-suite/output/bug_10803.v000066400000000000000000000006471516144147600176530ustar00rootroot00000000000000Inductive Foo := foo. Declare Scope foo_scope. Delimit Scope foo_scope with foo. Bind Scope foo_scope with Foo. Notation "'!'" := foo : foo_scope. Definition of_foo {x : nat} {y : nat} (f : Foo) := f. Abbreviation a := (@of_foo O). Abbreviation b := (@a). Check a !. Check @a O !. Check @b O. Check @b O !. (* was failing *) (* All are printed "a !", without making explicit the "0", which is incidentally disputable *) rocq-9.2.0/test-suite/output/bug_10824.out000066400000000000000000000000361516144147600202100ustar00rootroot00000000000000!! : Prop !! : Prop rocq-9.2.0/test-suite/output/bug_10824.v000066400000000000000000000003361516144147600176510ustar00rootroot00000000000000Module A. Abbreviation F := False. Notation "!!" := False (at level 0). Check False. End A. Module B. Notation "!!" := False (at level 0). Abbreviation F := False. Notation "!!" := False (at level 0). Check False. End B. rocq-9.2.0/test-suite/output/bug_11342.out000066400000000000000000000000161516144147600202020ustar00rootroot00000000000000without using rocq-9.2.0/test-suite/output/bug_11342.v000066400000000000000000000004741516144147600176500ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vos") -*- *) Section foo. Context {H:True}. Theorem test1 : True. Proof. (* this gets printed with -vos because there's no annotation (either [Set Default Proof Using ...] or an explicit [Proof using ...]) *) idtac "without using". exact I. Qed. End foo. rocq-9.2.0/test-suite/output/bug_11347.out000066400000000000000000000002351516144147600202120ustar00rootroot00000000000000File "./output/bug_11347.v", line 5, characters 7-29: The command has indeed failed with message: Tactic failure: setoid rewrite failed: Nothing to rewrite. rocq-9.2.0/test-suite/output/bug_11347.v000066400000000000000000000003011516144147600176420ustar00rootroot00000000000000Require Import Setoid. Lemma foo (b:unit) : (match b with tt => fun (C : Prop) => C end) True. Proof. Fail setoid_rewrite or_comm. (* or any lemma that can be used for rewriting *) Abort. rocq-9.2.0/test-suite/output/bug_11608.out000066400000000000000000000000341516144147600202070ustar00rootroot00000000000000creating x without [Proof.] rocq-9.2.0/test-suite/output/bug_11608.v000066400000000000000000000005241516144147600176510ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vos") -*- *) Set Default Proof Using "Type". Section foo. Context (A:Type). Definition x : option A. (* this can get printed with -vos since without "Proof." there's no Proof using, even with a default annotation. *) idtac "creating x without [Proof.]". exact None. Qed. End foo. rocq-9.2.0/test-suite/output/bug_11934.out000066400000000000000000000003411516144147600202120ustar00rootroot00000000000000thing = forall x y : foo, bla x y : Prop thing = forall (x : foo@{thing.u0}) (y : foo@{thing.u1}), bla x y : Prop thing = forall (x : @foo@{thing.u0} True) (y : @foo@{thing.u1} True), @bla True True x y : Prop rocq-9.2.0/test-suite/output/bug_11934.v000066400000000000000000000006731516144147600176600ustar00rootroot00000000000000Polymorphic Axiom foo@{u} : Prop -> Prop. Arguments foo {_}. Axiom bla : forall {A B}, @foo A -> @foo B -> Prop. Definition thing := forall (x:@foo@{Type} True) (y:@foo@{Type} True), bla x y. Print thing. (* forall x y : foo, bla x y *) Set Printing Universes. Print thing. (* forall (x : foo@{thing.u0}) (y : foo@{thing.u1}), bla x y *) Set Printing Implicit. Print thing. (* BAD: forall x y : @foo@{thing.u0} True, @bla True True x y *) rocq-9.2.0/test-suite/output/bug_12159.out000066400000000000000000000003221516144147600202110ustar00rootroot00000000000000f 1%B : unit f 0 : unit 1%B : unit 0 : unit 1%B : unit 1 : unit 1 : unit 0 : unit 1 : unit 0%A : unit 1 : unit 0%A : unit 0 : unit 0 : unit rocq-9.2.0/test-suite/output/bug_12159.v000066400000000000000000000015301516144147600176510ustar00rootroot00000000000000Declare Scope A. Declare Scope B. Delimit Scope A with A. Delimit Scope B with B. Definition to_unit (v : Number.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end. Definition of_unit (v : unit) : Number.uint := Nat.to_num_uint 0. Definition of_unit' (v : unit) : Number.uint := Nat.to_num_uint 1. Number Notation unit to_unit of_unit : A. Number Notation unit to_unit of_unit' : B. Definition f x : unit := x. Check f tt. Arguments f x%_A. Check f tt. Check tt. Open Scope A. Check tt. Close Scope A. Check tt. Open Scope B. Check tt. Undelimit Scope B. Check tt. Open Scope A. Check tt. Close Scope A. Check tt. Close Scope B. Check tt. Open Scope B. Check tt. Notation "1" := true. Check tt. Open Scope A. Check tt. Declare Scope C. Notation "0" := false : C. Open Scope C. Check tt. (* gives 0 but should now be 0%A *) rocq-9.2.0/test-suite/output/bug_12463.out000066400000000000000000000003461516144147600202150ustar00rootroot00000000000000File "./output/bug_12463.v", line 4, characters 2-11: The command has indeed failed with message: The user-defined tactic "foo" was not fully applied: There is a missing argument for variable H, no arguments at all were provided. rocq-9.2.0/test-suite/output/bug_12463.v000066400000000000000000000003161516144147600176500ustar00rootroot00000000000000Ltac foo H := idtac H. Goal True. Proof. Fail foo. (* Error: An unnamed user-defined tactic was not fully applied: There is a missing argument for variable H, no arguments at all were provided. *) Abort. rocq-9.2.0/test-suite/output/bug_12777.out000066400000000000000000000000701516144147600202170ustar00rootroot00000000000000Notation tt' := tt Inductive unit : Set := tt : unit. rocq-9.2.0/test-suite/output/bug_12777.v000066400000000000000000000001301516144147600176520ustar00rootroot00000000000000Module Import M1. Module Export M2. Abbreviation tt' := tt. End M2. End M1. Print tt'. rocq-9.2.0/test-suite/output/bug_12887.out000066400000000000000000000006701516144147600202270ustar00rootroot00000000000000File "./output/bug_12887.v", line 5, characters 25-26: The command has indeed failed with message: Cannot infer this placeholder of type "Type" in environment: Functor : (Type -> Type) -> Type F : Type -> Type fmap : forall A B : Type, (A -> B) -> F A -> F B File "./output/bug_12887.v", line 8, characters 0-53: The command has indeed failed with message: Cannot infer an existential variable of type "nat" in environment: R : nat -> Type rocq-9.2.0/test-suite/output/bug_12887.v000066400000000000000000000003731516144147600176650ustar00rootroot00000000000000Arguments id {_} _. Fail Record Functor (F : Type -> Type) := { fmap : forall A B, (A -> B) -> F A -> F B; fmap_identity : fmap _ _ id = id; }. Fail Inductive R (x:nat) := { y : R ltac:(clear x) }. Inductive R (x:nat) := { y : bool; z : R _ }. rocq-9.2.0/test-suite/output/bug_12908.out000066400000000000000000000004201516144147600202120ustar00rootroot00000000000000forall m n : nat, m * n = (2 * m * n)%nat : Prop File "./output/bug_12908.v", line 11, characters 0-31: Warning: Notation "_ * _" was already used in scope nat_scope. [notation-overridden,parsing,default] forall m n : nat, m * n = Nat.mul (Nat.mul 2 m) n : Prop rocq-9.2.0/test-suite/output/bug_12908.v000066400000000000000000000005421516144147600176550ustar00rootroot00000000000000Definition mult' m n := 2 * m * n. Module A. (* Test hiding of a scoped notation by a lonely notation *) Infix "*" := mult'. Check forall m n, mult' m n = Nat.mul (Nat.mul 2 m) n. End A. Module B. (* Test that an overridden scoped notation is deactivated *) Infix "*" := mult' : nat_scope. Check forall m n, mult' m n = Nat.mul (Nat.mul 2 m) n. End B. rocq-9.2.0/test-suite/output/bug_13004.out000066400000000000000000000000751516144147600202040ustar00rootroot00000000000000Ltac t := ltac2:(print (of_string "hi")) Ltac u := ident:(H) rocq-9.2.0/test-suite/output/bug_13004.v000066400000000000000000000001751516144147600176430ustar00rootroot00000000000000Require Import Ltac2.Ltac2 Ltac2.Message. Ltac t := ltac2:(print (of_string "hi")). Ltac u := ident:(H). Print t. Print u. rocq-9.2.0/test-suite/output/bug_13018.out000066400000000000000000000003601516144147600202060ustar00rootroot00000000000000gargs:( (!) ) : list nat gargs:( (!, !, !) ) : list nat OnlyGargs[ (!) ] : list nat gargs999:( (!) ) : list nat gargs999:( (!, !, !) ) : list nat OnlyGargs[ (!) ] : list nat OnlyGargs999[ (!) ] : list nat rocq-9.2.0/test-suite/output/bug_13018.v000066400000000000000000000025211516144147600176450ustar00rootroot00000000000000Undelimit Scope list_scope. Declare Custom Entry gnat. Declare Custom Entry gargs. Notation "!" := 42 (in custom gnat). Notation "gargs:( e )" := e (e custom gargs). Notation "( x )" := (cons x (@nil nat)) (in custom gargs, x custom gnat). Notation "( x , y , .. , z )" := (cons x (cons y .. (cons z nil) ..)) (in custom gargs, x custom gnat, y custom gnat, z custom gnat). Check gargs:( (!) ). (* cons 42 nil *) Check gargs:( (!, !, !) ). (* cons 42 (42 :: 42 :: nil) *) Definition OnlyGargs {T} (x:T) := x. Notation "OnlyGargs[ x ]" := (OnlyGargs x) (at level 0, x custom gargs). Check OnlyGargs[ (!) ]. (* OnlyGargs[ cons 42 nil] *) Declare Custom Entry gargs999. Notation "gargs999:( e )" := e (e custom gargs999 at level 999). Notation "( x )" := (cons x (@nil nat)) (in custom gargs999, x custom gnat at level 999). Notation "( x , y , .. , z )" := (cons x (cons y .. (cons z nil) ..)) (in custom gargs999, x custom gnat at level 999, y custom gnat at level 999, z custom gnat at level 999). Check gargs999:( (!) ). (* gargs999:( (!)) *) Check gargs999:( (!, !, !) ). (* gargs999:( (!, !, !)) *) Check OnlyGargs[ (!) ]. (* OnlyGargs[ gargs999:( (!))] *) Definition OnlyGargs999 {T} (x:T) := x. Notation "OnlyGargs999[ x ]" := (OnlyGargs999 x) (at level 0, x custom gargs999 at level 999). Check OnlyGargs999[ (!) ]. (* OnlyGargs999[ (!)] *) rocq-9.2.0/test-suite/output/bug_13112.out000066400000000000000000000000371516144147600202020ustar00rootroot000000000000000 + 0 : nat HI : nat rocq-9.2.0/test-suite/output/bug_13112.v000066400000000000000000000002511516144147600176360ustar00rootroot00000000000000Reserved Notation "'HI'". Notation "'HI'" := (O + O) (only parsing). Check HI. (* 0 + 0 : nat *) Notation "'HI'" := (O + O) (only printing). Check HI. (* 0 + 0 : nat *) rocq-9.2.0/test-suite/output/bug_13238.out000066400000000000000000000001521516144147600202110ustar00rootroot00000000000000Ltac t1 x := replace (x x) with (x x) Ltac t2 x := case : x Ltac t3 := by move -> Ltac t4 := congr True rocq-9.2.0/test-suite/output/bug_13238.v000066400000000000000000000002601516144147600176470ustar00rootroot00000000000000Require Import ssreflect. Ltac t1 x := replace (x x) with (x x). Print t1. Ltac t2 x := case: x. Print t2. Ltac t3 := by move->. Print t3. Ltac t4 := congr True. Print t4. rocq-9.2.0/test-suite/output/bug_13240.out000066400000000000000000000001111516144147600201750ustar00rootroot00000000000000Ltac t1 a b := a ; last b Ltac t2 := do !idtac Ltac t3 := idtac => True rocq-9.2.0/test-suite/output/bug_13240.v000066400000000000000000000002051516144147600176370ustar00rootroot00000000000000Require Import ssreflect. Ltac t1 a b := a; last b. Print t1. Ltac t2 := do !idtac. Print t2. Ltac t3 := idtac => True. Print t3. rocq-9.2.0/test-suite/output/bug_13244.out000066400000000000000000000010121516144147600202020ustar00rootroot00000000000000negbT: forall [b : bool], b = false -> ~~ b contra_notN: forall [P : Prop] [b : bool], (b -> P) -> ~ P -> ~~ b contraPN: forall [P : Prop] [b : bool], (b -> ~ P) -> P -> ~~ b contraNN: forall [c b : bool], (c -> b) -> ~~ b -> ~~ c contraL: forall [c b : bool], (c -> ~~ b) -> b -> ~~ c contraTN: forall [c b : bool], (c -> ~~ b) -> b -> ~~ c contra: forall [c b : bool], (c -> b) -> ~~ b -> ~~ c introN: forall [P : Prop] [b : bool], reflect P b -> ~ P -> ~~ b contraFN: forall [c b : bool], (c -> b) -> b = false -> ~~ c rocq-9.2.0/test-suite/output/bug_13244.v000066400000000000000000000001271516144147600176460ustar00rootroot00000000000000Require Import ssr.ssrbool. Set Warnings "-ssr-search-moved". Search headconcl:(~~ _). rocq-9.2.0/test-suite/output/bug_13266.out000066400000000000000000000007571516144147600202250ustar00rootroot00000000000000File "./output/bug_13266.v", line 17, characters 7-18: The command has indeed failed with message: Abstracting over the terms "S", "p" and "u" leads to a term fun (S0 : Type) (p0 : proc S0) (_ : S0) => p0 = Tick -> True which is ill-typed. Reason is: Illegal application: The term "@eq" of type "forall A : Set, A -> A -> Prop" cannot be applied to the terms "proc S0" : "Prop" "p0" : "proc S0" "Tick" : "proc unit" The 3rd term has type "proc unit" which should be a subtype of "proc S0". rocq-9.2.0/test-suite/output/bug_13266.v000066400000000000000000000003741516144147600176560ustar00rootroot00000000000000Inductive proc : Type -> Prop := | Tick : proc unit . Inductive exec : forall T, proc T -> T -> Prop := | ExecTick : exec _ (Tick) tt . Lemma foo : exec _ Tick tt -> True. Proof. intros H. remember Tick as p. Fail induction H. Abort. rocq-9.2.0/test-suite/output/bug_13320.out000066400000000000000000000001731516144147600202040ustar00rootroot00000000000000File "./output/bug_13320.v", line 2, characters 0-21: The command has indeed failed with message: No obligations remaining rocq-9.2.0/test-suite/output/bug_13320.v000066400000000000000000000001271516144147600176410ustar00rootroot00000000000000(* Next Obligation should fail normally, not with an anomaly. *) Fail Next Obligation. rocq-9.2.0/test-suite/output/bug_13595.out000066400000000000000000000004321516144147600202200ustar00rootroot00000000000000File "./output/bug_13595.v", line 5, characters 7-17: The command has indeed failed with message: Tactic failure: Goal is solvable by congruence but some arguments are missing. Try "congruence with ((Triple a _ _)) ((Triple d c _))", replacing metavariables by arbitrary terms. rocq-9.2.0/test-suite/output/bug_13595.v000066400000000000000000000003671516144147600176650ustar00rootroot00000000000000Inductive Cube:Set :=| Triple: nat -> nat -> nat -> Cube. Theorem incomplete :forall a b c d : nat,Triple a = Triple b->Triple d c = Triple d b->a = c. Proof. Fail congruence. intros. congruence with ((Triple a a a)) ((Triple d c a)). Qed. rocq-9.2.0/test-suite/output/bug_13821_native_command_line_warn.out000066400000000000000000000000001516144147600253010ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/bug_13821_native_command_line_warn.v000066400000000000000000000002361516144147600247520ustar00rootroot00000000000000(* -*- coq-prog-args: ("-w" "-deprecated-native-compiler-option" "-w" "-native-compiler-disabled" "-native-compiler" "ondemand" "-async-proofs" "no"); -*- *) rocq-9.2.0/test-suite/output/bug_13857.out000066400000000000000000000006361516144147600202270ustar00rootroot00000000000000File "./output/bug_13857.v", line 6, characters 13-16: The command has indeed failed with message: Unable to find an instance for the variable x. File "./output/bug_13857.v", line 7, characters 13-17: The command has indeed failed with message: Unable to unify "foo2" with "foo". File "./output/bug_13857.v", line 8, characters 13-17: The command has indeed failed with message: Unable to unify "foo3" with "foo". rocq-9.2.0/test-suite/output/bug_13857.v000066400000000000000000000002661516144147600176640ustar00rootroot00000000000000Inductive foo := Foo (x:nat) (H: x=x). Inductive foo2 := Foo2 (x : nat). Inductive foo3 := Foo3 (f : foo2). Goal foo. Fail apply Foo. Fail apply Foo2. Fail apply Foo3. Abort. rocq-9.2.0/test-suite/output/bug_14141.out000066400000000000000000000001441516144147600202040ustar00rootroot000000000000001 goal n : nat ============================ forall (n0 : nat) (H : n0 <= S n), S n0 <= S n rocq-9.2.0/test-suite/output/bug_14141.v000066400000000000000000000002271516144147600176440ustar00rootroot00000000000000Set Fast Name Printing. Lemma le_succ_diag_r (n : nat) : n <= S n. Proof. apply (nat_ind (fun p : nat => p <= S n)). apply le_0_n. Show. Abort. rocq-9.2.0/test-suite/output/bug_14815.out000066400000000000000000000003131516144147600202120ustar00rootroot00000000000000f = fix f (n : nat) : nat := match n with | 0 => 0 | S n0 => g n0 end with g (n : nat) : nat := match n with | 0 => 0 | S n0 => f n0 end for f : nat -> nat Arguments f n%_nat_scope rocq-9.2.0/test-suite/output/bug_14815.v000066400000000000000000000001611516144147600176510ustar00rootroot00000000000000Fixpoint f n := match n with S n => g n | O => O end with g n := match n with S n => f n | O => O end. Print f. rocq-9.2.0/test-suite/output/bug_14899.out000066400000000000000000000001361516144147600202310ustar00rootroot00000000000000proj2_sig a : 0 < proj1_sig a = le_S 1 2 (le_S 1 1 (le_n 1)) : 0 < proj1_sig a rocq-9.2.0/test-suite/output/bug_14899.v000066400000000000000000000001471516144147600176710ustar00rootroot00000000000000Definition a : { x | 0 < x }. exists 3. eauto. Defined. Check (proj2_sig a). Compute (proj2_sig a). rocq-9.2.0/test-suite/output/bug_15020.out000066400000000000000000000006021516144147600202000ustar00rootroot00000000000000eq_rect : forall {A : Type} {x : A} (P : A -> Type), P x -> forall {y : A}, x = y -> P y eq_rect is not universe polymorphic Arguments eq_rect {A}%_type_scope {x} P%_function_scope eq_refl {y} e (where some original arguments have been renamed) eq_rect is transparent Expands to: Constant Corelib.Init.Logic.eq_rect Declared in library Corelib.Init.Logic, line 379, characters 0-115 rocq-9.2.0/test-suite/output/bug_15020.v000066400000000000000000000001161516144147600176360ustar00rootroot00000000000000(* A variant of bug #13392 *) Arguments eq_rect {_ _} _ _ {_}. About eq_rect. rocq-9.2.0/test-suite/output/bug_15097.out000066400000000000000000000005461516144147600202250ustar00rootroot00000000000000File "./output/bug_15097.v", line 1, characters 20-42: The command has indeed failed with message: Cannot find a physical path bound to logical path Corelib.Does.Not.Exist. File "./output/bug_15097.v", line 2, characters 33-47: The command has indeed failed with message: Cannot find a physical path bound to logical path Does.Not.Exist with prefix Corelib. rocq-9.2.0/test-suite/output/bug_15097.v000066400000000000000000000001351516144147600176550ustar00rootroot00000000000000Fail Require Import Corelib.Does.Not.Exist. Fail From Corelib Require Import Does.Not.Exist. rocq-9.2.0/test-suite/output/bug_15106.out000066400000000000000000000001771516144147600202140ustar00rootroot00000000000000File "./output/bug_15106.v", line 7, characters 0-18: The command has indeed failed with message: Obligation 2 already solved. rocq-9.2.0/test-suite/output/bug_15106.v000066400000000000000000000003401516144147600176420ustar00rootroot00000000000000Require Import Corelib.Program.Tactics. Local Obligation Tactic := try constructor. Axiom P : Prop. Axiom p : P. Program Definition foo := (fun (x : P) (y : True) => I) _ _. Fail Obligation 2. Obligation 1. exact p. Qed. rocq-9.2.0/test-suite/output/bug_15221.out000066400000000000000000000002511516144147600202030ustar00rootroot00000000000000chain = fun x y : nat => let/c f := foo x y in let/c b := bar x y in f = b : nat -> nat -> Prop Arguments chain (x y)%_nat_scope rocq-9.2.0/test-suite/output/bug_15221.v000066400000000000000000000006031516144147600176420ustar00rootroot00000000000000Definition foo{A}(a b: nat)(k: nat -> A): A := k (a + b). Definition bar{A}(a b: nat)(k: nat -> A): A := k (a - b). Notation "'let/c' x := r 'in' b" := (r (fun x => b)) (x binder, at level 200, right associativity, format "'[hv' 'let/c' x := r 'in' '//' b ']'"). Definition chain(x y: nat): Prop := let/c f := foo x y in let/c b := bar x y in f = b. Print chain. rocq-9.2.0/test-suite/output/bug_15322.out000066400000000000000000000003021516144147600202020ustar00rootroot00000000000000x `+ (y `+ z) : nat [x `+ (y `+ z)] : nat fun x y z : nat => [x `+ (y `+ z)] : nat -> (nat -> (nat -> nat)) fun x y z : nat => [x `+ (y `+ z)] : nat -> (nat -> (nat -> nat)) rocq-9.2.0/test-suite/output/bug_15322.v000066400000000000000000000015321516144147600176460ustar00rootroot00000000000000Set Printing Parentheses. Module Constr. Parameters x y z : nat. Notation "a `+ b" := (a + b) (at level 50, b at level 50, left associativity). Check (x `+ y `+ z). End Constr. Module CustomGlobal. Declare Custom Entry foo. Notation "a `+ b" := (a + b) (in custom foo at level 50, b at level 50). Notation "x" := x (in custom foo at level 0, x global). Notation "( x )" := x (in custom foo at level 0). Notation "[ a ]" := a (a custom foo). Parameters x y z : nat. Check [x `+ y `+ z]. Check fun x y z => [x `+ y `+ z]. End CustomGlobal. Module CustomIdent. Declare Custom Entry bar. Notation "a `+ b" := (a + b) (in custom bar at level 50, b at level 50). Notation "x" := x (in custom bar at level 0, x ident). Notation "( x )" := x (in custom bar at level 0). Notation "[ a ]" := a (a custom bar). Check fun x y z => [x `+ y `+ z]. End CustomIdent. rocq-9.2.0/test-suite/output/bug_15334.out000066400000000000000000000002411516144147600202070ustar00rootroot00000000000000File "./output/bug_15334.v", line 4, characters 11-12: Error: Syntax error: [custom:bug_15334.ent] expected after 'ent:(' (in [term]). coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_15334.v000066400000000000000000000002231516144147600176450ustar00rootroot00000000000000Declare Custom Entry ent. Notation "ent:( x )" := x (x custom ent). Notation "a ; b" := (pair a b) (in custom ent at level 50). Check ent:(_ ; _). rocq-9.2.0/test-suite/output/bug_15687.out000066400000000000000000000010171516144147600202240ustar00rootroot00000000000000File "./output/bug_15687.v", line 7, characters 11-16: The command has indeed failed with message: This expression has type int -> 'a but an expression was expected of type int File "./output/bug_15687.v", line 10, characters 11-16: The command has indeed failed with message: This expression has type int -> bool but an expression was expected of type int File "./output/bug_15687.v", line 18, characters 55-65: The command has indeed failed with message: This expression should not be a function, the expected type is int. rocq-9.2.0/test-suite/output/bug_15687.v000066400000000000000000000010471516144147600176650ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Fail Ltac2 rec foo(i: int)(j: int) := foo i (bar j) (*^^^*) with bar(i: int) := Int.add (foo i (*i*)) 1. Fail Ltac2 rec bar(i: int) := Int.add (foo i (*i*)) 1 with foo(i: int)(j: int) : bool := foo i (bar j). (* The location is not great if we write "fun x y => x" but that's unrelated to what we're testing here. Also the toplevel "Ltac2 rec foo :=" is currently not smart enough to recognize a function with type annotation. *) Fail Ltac2 foo := let rec foo : int -> int := fun x => fun y => x in foo. rocq-9.2.0/test-suite/output/bug_16219.out000066400000000000000000000007511516144147600202200ustar00rootroot00000000000000Closed under the global context Closed under the global context File "./output/bug_16219.v", line 7, characters 0-76: The command has indeed failed with message: Incorrect elimination of "e" in the inductive type "squashed_eq": the return type has sort "Type" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Type" because strict proofs can be eliminated only to build strict proofs. Axioms: seq relies on definitional UIP. rocq-9.2.0/test-suite/output/bug_16219.v000066400000000000000000000006141516144147600176540ustar00rootroot00000000000000Inductive sUnit : SProp := stt. Print Assumptions sUnit. (* was bug: sUnit relies on definitional UIP. *) Inductive squashed_eq {A} a : A -> SProp := squashed_refl : squashed_eq a a. Print Assumptions squashed_eq. Fail Check fun e : squashed_eq 0 1 => match e with squashed_refl _ => 2 end. Set Definitional UIP. Inductive seq {A} a : A -> SProp := srefl : seq a a. Print Assumptions seq_rect. rocq-9.2.0/test-suite/output/bug_16224.out000066400000000000000000000003301516144147600202050ustar00rootroot00000000000000[reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget [cic] : Cic >-> A (reversible) [rc] : Rc >-> A (reversible) [ric] : Ric >-> A (reversible) ric : Ric -> A cic : Cic -> A ri : Ri -> A ci : Ci -> A rocq-9.2.0/test-suite/output/bug_16224.v000066400000000000000000000003701516144147600176470ustar00rootroot00000000000000Class A := { n : nat }. Record Rn := { rn : A }. Class Cn := { cn : A }. Record Rc := { rc :> A }. Record Ri := { ri :: A }. Class Ci := { ci :: A }. Record Ric := { ric ::> A }. Class Cic := { cic ::> A }. Print Graph. Print Instances A. rocq-9.2.0/test-suite/output/bug_16262.out000066400000000000000000000004121516144147600202100ustar00rootroot00000000000000nat -> nat : Set nat -> nat : Set (1->2)%foo : nat * nat File "./output/bug_16262.v", line 9, characters 0-116: Warning: Notation "_ -> _" was already defined with a different format. [notation-incompatible-format,parsing,default] nat->nat : Set rocq-9.2.0/test-suite/output/bug_16262.v000066400000000000000000000005501516144147600176510ustar00rootroot00000000000000Declare Scope foo. Delimit Scope foo with foo. Check (nat -> nat). Notation "a -> b" := (a,b) (b at level 200, only printing, right associativity, at level 99, format "a -> b") : foo. Check (nat -> nat). Check (1,2). Reserved Notation "a -> b" (b at level 200, only printing, right associativity, at level 99, format "a -> b"). Check (nat -> nat). rocq-9.2.0/test-suite/output/bug_16335.out000066400000000000000000000001341516144147600202120ustar00rootroot00000000000000Error: There are pending proofs in file ./output/bug_16335.v: foo. coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_16335.v000066400000000000000000000000301516144147600176430ustar00rootroot00000000000000Lemma foo: True. Proof. rocq-9.2.0/test-suite/output/bug_16411.out000066400000000000000000000000631516144147600202060ustar00rootroot00000000000000Axioms: foo : nat 0 : nat Axioms: axiom : nat rocq-9.2.0/test-suite/output/bug_16411.v000066400000000000000000000002361516144147600176460ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vok") -*- *) Require Import TestSuite.for_vos. Print Assumptions foo. Check 0. (* separator *) Print Assumptions bar. rocq-9.2.0/test-suite/output/bug_16558.out000066400000000000000000000000341516144147600202200ustar00rootroot00000000000000Ltac t x y := abstract : x rocq-9.2.0/test-suite/output/bug_16558.v000066400000000000000000000000761516144147600176640ustar00rootroot00000000000000Require Import ssreflect. Ltac t x y := abstract: x. Print t. rocq-9.2.0/test-suite/output/bug_16562.out000066400000000000000000000000251516144147600202130ustar00rootroot00000000000000Ltac t x := unlock x rocq-9.2.0/test-suite/output/bug_16562.v000066400000000000000000000000721516144147600176530ustar00rootroot00000000000000Require Import ssreflect. Ltac t x := unlock x. Print t. rocq-9.2.0/test-suite/output/bug_16565.out000066400000000000000000000000521516144147600202160ustar00rootroot00000000000000Ltac u a b := functional induction a as b rocq-9.2.0/test-suite/output/bug_16565.v000066400000000000000000000001251516144147600176550ustar00rootroot00000000000000Require Import TestSuite.funind. Ltac u a b := functional induction a as b. Print u. rocq-9.2.0/test-suite/output/bug_16566.out000066400000000000000000000000741516144147600202230ustar00rootroot00000000000000Ltac t a b := rewrite a, b Ltac t a b := rewrite -> a, -> b rocq-9.2.0/test-suite/output/bug_16566.v000066400000000000000000000001101516144147600176500ustar00rootroot00000000000000Ltac t a b := rewrite a, b. Print t. Require Import ssreflect. Print t. rocq-9.2.0/test-suite/output/bug_16596.out000066400000000000000000000000431516144147600202220ustar00rootroot00000000000000Ltac t := unshelve (only 1: idtac) rocq-9.2.0/test-suite/output/bug_16596.v000066400000000000000000000000551516144147600176630ustar00rootroot00000000000000Ltac t := unshelve (only 1: idtac). Print t. rocq-9.2.0/test-suite/output/bug_16613.out000066400000000000000000000002421516144147600202110ustar00rootroot00000000000000File "./output/bug_16613.v", line 2, characters 2-10: Warning: This command does not support these attributes: bar, foo. [unsupported-attributes,parsing,default] rocq-9.2.0/test-suite/output/bug_16613.v000066400000000000000000000001101516144147600176410ustar00rootroot00000000000000Set Warnings "unsupported-attributes". #[foo, bar] Definition foo := I. rocq-9.2.0/test-suite/output/bug_16716.out000066400000000000000000000002221516144147600202130ustar00rootroot00000000000000File "./output/bug_16716.v", line 11, characters 0-55: The command has indeed failed with message: Uncaught Ltac2 exception: E constr:(?X4.(r _)) rocq-9.2.0/test-suite/output/bug_16716.v000066400000000000000000000004631516144147600176600ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Set Primitive Projections. Record R A := mkR { r : A }. Ltac2 Type exn ::= [ E (constr) ]. Set Printing Projections. Set Printing Primitive Projection Parameters. Fail Ltac2 Eval Control.zero (E open_constr:(_.(r _))). (* Error: Uncaught Ltac2 exception: E (constr:(...)) *) rocq-9.2.0/test-suite/output/bug_16816.out000066400000000000000000000005001516144147600202130ustar00rootroot00000000000000File "./output/bug_16816.v", line 6, characters 15-16: The command has indeed failed with message: In environment s : Box unit T : Type x : T The term "x" has type "T" while it is expected to have type "?S@{u0:=T}" (unable to find a well-typed instantiation for "?S": cannot ensure that "Type" is a subtype of "Set"). rocq-9.2.0/test-suite/output/bug_16816.v000066400000000000000000000002301516144147600176510ustar00rootroot00000000000000Inductive Box : Type -> Type := | box : forall A, A -> Box A. Fail Definition open_box (s : Box unit) : unit := match s with | box _ x => x end. rocq-9.2.0/test-suite/output/bug_17002.out000066400000000000000000000011721516144147600202050ustar00rootroot00000000000000File "./output/bug_17002.v", line 7, characters 2-24: The command has indeed failed with message: Universe inconsistency. Cannot enforce u < v because v = u. File "./output/bug_17002.v", line 8, characters 2-24: The command has indeed failed with message: Universe inconsistency. Cannot enforce v < u because u = v. File "./output/bug_17002.v", line 15, characters 2-24: The command has indeed failed with message: Universe inconsistency. Cannot enforce u = v because u < v. File "./output/bug_17002.v", line 16, characters 2-24: The command has indeed failed with message: Universe inconsistency. Cannot enforce v = u because u < v. rocq-9.2.0/test-suite/output/bug_17002.v000066400000000000000000000004631516144147600176450ustar00rootroot00000000000000 Module Eq. Universes u v. Constraint u = v. (* we test both directions to be invariant wrt which universe got picked as canonical *) Fail Constraint u < v. Fail Constraint v < u. End Eq. Module Lt. Universes u v. Constraint u < v. Fail Constraint u = v. Fail Constraint v = u. End Lt. rocq-9.2.0/test-suite/output/bug_17155.out000066400000000000000000000007121516144147600202150ustar00rootroot00000000000000File "./output/bug_17155.v", line 6, characters 0-23: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None File "./output/bug_17155.v", line 8, characters 0-23: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None Backtrace: Call M.g Call bug_17155.M.f (* local *) Prim Ltac2 M.g : unit -> 'a M.g := fun _ => bug_17155.M.f (* local *) () rocq-9.2.0/test-suite/output/bug_17155.v000066400000000000000000000004601516144147600176530ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. Module M. #[local] Ltac2 f () := Control.throw (Invalid_argument None). Ltac2 g () := f (). End M. Fail Ltac2 Eval M.g (). (* Fails, as expected. *) Set Ltac2 Backtrace. Fail Ltac2 Eval M.g (). (* Anomaly "Uncaught exception Not_found." *) Print M.g. rocq-9.2.0/test-suite/output/bug_17369.out000066400000000000000000000002051516144147600202210ustar00rootroot00000000000000{- my_inductive_prop : logical inductive with constructors : constr_1 constr_2 constr_3 constr_4 constr_5 constr_6 constr_7 -} rocq-9.2.0/test-suite/output/bug_17369.v000066400000000000000000000005421516144147600176630ustar00rootroot00000000000000(* Ensure that 'logical inductive' comments in extracted Haskell * do not get uncommented by line wrapping *) From Corelib Require Import Extraction. Set Printing Width 60. Inductive my_inductive_prop : Prop := constr_1 | constr_2 | constr_3 | constr_4 | constr_5 | constr_6 | constr_7 . Extraction Language Haskell. Extraction my_inductive_prop. rocq-9.2.0/test-suite/output/bug_17372.out000066400000000000000000000002371516144147600202200ustar00rootroot00000000000000File "./output/bug_17372.v", line 2, characters 13-16: The command has indeed failed with message: The reference bar was not found in the current environment. rocq-9.2.0/test-suite/output/bug_17372.v000066400000000000000000000000601516144147600176500ustar00rootroot00000000000000Goal Prop. Fail refine (bar (A := nat)). Abort. rocq-9.2.0/test-suite/output/bug_17386.out000066400000000000000000000001021516144147600202140ustar00rootroot000000000000001 goal x, y := 1 : nat ============================ True rocq-9.2.0/test-suite/output/bug_17386.v000066400000000000000000000002111516144147600176530ustar00rootroot00000000000000Goal True. evar (x:nat). pose (y:=1). let _ := constr:(eq_refl : x = 1) in idtac. Show. (* x := 1 y := 1 should be x, y := 1 *) Abort. rocq-9.2.0/test-suite/output/bug_17579.out000066400000000000000000000004231516144147600202260ustar00rootroot00000000000000File "./output/bug_17579.v", line 4, characters 0-26: The command has indeed failed with message: Timeout must be > 0. File "./output/bug_17579.v", line 7, characters 8-9: Error: Syntax error: [natural] expected after 'Timeout' (in [control_flag]). coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_17579.v000066400000000000000000000003171516144147600176660ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "no"); -*- *) (* disable async proofs because they get the parse error before running the Fail *) Fail Timeout 0 Check True. (* parse error *) Timeout -1 Check True. rocq-9.2.0/test-suite/output/bug_17594.out000066400000000000000000000023551516144147600202310ustar00rootroot000000000000001 3 2 3 File "./output/bug_17594.v", line 12, characters 19-20: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "True". 1 3 2 3 File "./output/bug_17594.v", line 17, characters 26-27: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "True". 1 3 2 3 File "./output/bug_17594.v", line 23, characters 19-20: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "True". 1 3 2 3 File "./output/bug_17594.v", line 28, characters 26-27: The command has indeed failed with message: The term "0" has type "nat" while it is expected to have type "True". 1 3 File "./output/bug_17594.v", line 31, characters 2-106: The command has indeed failed with message: Uncaught Ltac2 exception: Match_failure 1 3 File "./output/bug_17594.v", line 37, characters 2-113: The command has indeed failed with message: No matching clauses for match. 1 3 File "./output/bug_17594.v", line 42, characters 2-119: The command has indeed failed with message: No matching clauses for match. 1 3 File "./output/bug_17594.v", line 48, characters 2-119: The command has indeed failed with message: No matching clauses for match. rocq-9.2.0/test-suite/output/bug_17594.v000066400000000000000000000021161516144147600176620ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. From Ltac2 Require Import Message. Ltac2 msg s := print (of_string s). Goal True. (* should be the exact error *) Fail multi_match! 'True with | True => msg "1" | _ => msg "2" end; msg "3"; exact 0. Fail ltac1:(multimatch True with | True => idtac "1" | _ => idtac "2" end; idtac "3"; exact 0). Fail multi_match! goal with | [ |- True ] => msg "1" | [ |- _ ] => msg "2" end; msg "3"; exact 0. Fail ltac1:(multimatch goal with | |- True => idtac "1" | |- _ => idtac "2" end; idtac "3"; exact 0). (* should be match error *) Fail multi_match! 'True with | True => msg "1" | False => msg "2" end; msg "3"; exact 0. Fail ltac1:(multimatch True with | True => idtac "1" | False => idtac "2" end; idtac "3"; exact 0). Fail multi_match! goal with | [ |- True ] => msg "1" | [ |- False ] => msg "2" end; msg "3"; exact 0. Fail ltac1:(multimatch goal with | |- True => idtac "1" | |- False => idtac "2" end; idtac "3"; exact 0). Abort. rocq-9.2.0/test-suite/output/bug_17627.out000066400000000000000000000000201516144147600202110ustar00rootroot00000000000000Ο† 0 : nat rocq-9.2.0/test-suite/output/bug_17627.v000066400000000000000000000001321516144147600176530ustar00rootroot00000000000000Module Import Bar. Notation "'Ο†' x" := (id x) (at level 3) . End Bar. Check (Ο† 0). rocq-9.2.0/test-suite/output/bug_17708.out000066400000000000000000000003251516144147600202210ustar00rootroot00000000000000File "./output/bug_17708.v", line 1, characters 0-39: Warning: This notation contains Ltac expressions: it will not be used for printing. [non-reversible-notation,parsing,default] Ltac foo := exact ltac:(exact 0) rocq-9.2.0/test-suite/output/bug_17708.v000066400000000000000000000001131516144147600176520ustar00rootroot00000000000000Abbreviation zero := (ltac: (exact 0)). Ltac foo := exact zero. Print foo. rocq-9.2.0/test-suite/output/bug_17829.out000066400000000000000000000000321516144147600202200ustar00rootroot00000000000000Ltac f := foo (foo idtac) rocq-9.2.0/test-suite/output/bug_17829.v000066400000000000000000000001501516144147600176570ustar00rootroot00000000000000Tactic Notation (at level 3) "foo" tactic2(tac) := intro; tac. Ltac f := foo (foo idtac). Print Ltac f. rocq-9.2.0/test-suite/output/bug_17854.out000066400000000000000000000007001516144147600202200ustar00rootroot00000000000000File "./output/bug_17854.v", line 3, characters 11-31: The command has indeed failed with message: The variable a is bound several times in pattern. File "./output/bug_17854.v", line 9, characters 11-31: The command has indeed failed with message: The variable a is bound several times in pattern. File "./output/bug_17854.v", line 27, characters 12-21: The command has indeed failed with message: The variable n is bound several times in pattern. rocq-9.2.0/test-suite/output/bug_17854.v000066400000000000000000000011671516144147600176660ustar00rootroot00000000000000Fail Check fun b : bool => match b, b with | true as a, true as a | true as a, _ => true | _, _ => false end. Fail Check fun b : bool => match b, b with | true as a, true as a => true | _, _ => false end. Definition f b := match b, b with | true as a as a, true as b => true | _, _ => false end. Module Bug18002. (* Non linearity to be checked first also at the level of inner disjunctive patterns *) Inductive U := p :nat->nat->U. Fail Check match p 1 2 with | (p n 0 | p n (S n)) => 0 | _ => 1 end. End Bug18002. rocq-9.2.0/test-suite/output/bug_18138.out000066400000000000000000000002111516144147600202110ustar00rootroot00000000000000Ltac2 bar : 'a -> unit bar := fun foo => M.foo Ltac2 baz : (unit -> 'a) -> constr baz := fun foo => constr:(ltac2:(foo foo)) rocq-9.2.0/test-suite/output/bug_18138.v000066400000000000000000000004111516144147600176510ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Module Import M. Ltac2 foo := (). End M. #[warnings="-ltac2-unused-variable"] Ltac2 bar foo := M.foo. Print bar. (* was fun foo => foo *) (* sadly this is still incorrect *) Ltac2 baz foo := constr:(ltac2:(foo M.foo)). Print baz. rocq-9.2.0/test-suite/output/bug_18223.out000066400000000000000000000001401516144147600202050ustar00rootroot00000000000000fun a b : A => < {| b a |} > : A -> A -> A fun a b : A => < {| b a |} > : A -> A -> A rocq-9.2.0/test-suite/output/bug_18223.v000066400000000000000000000011351516144147600176500ustar00rootroot00000000000000Declare Custom Entry foo. Declare Custom Entry bar. Parameter (A : Type). Parameter (Q : A -> A -> A). Parameter (P : A -> A). Notation "< x >" := (P x) (x custom foo). Notation "x y" := (Q x y) (in custom bar at level 1, right associativity). Notation "x" := x (in custom bar at level 0, x global). Module Order1. Notation "| x |" := (x) (x custom bar). Notation "{ x }" := (x) (in custom foo, x constr). Check (fun a b => < {Q b a} >). End Order1. Module Order2. Notation "{ x }" := (x) (in custom foo, x constr). Notation "| x |" := (x) (x custom bar). Check (fun a b => < {Q b a} >). End Order2. rocq-9.2.0/test-suite/output/bug_18342.out000066400000000000000000000002641516144147600202160ustar00rootroot00000000000000<{ SS (? I) }> : nat <{ SS [[{{?}} I]] }> : nat fun x : I => match x with | <{ DD [[{{?}} y]] }> => y | _ => 0 end : I -> nat rocq-9.2.0/test-suite/output/bug_18342.v000066400000000000000000000023301516144147600176500ustar00rootroot00000000000000Declare Custom Entry stlc. Module Bug18342. Definition A (T : True) := 0. Notation "?" := A. Notation "<{ e }>" := e (e custom stlc at level 99). Notation "x" := x (in custom stlc at level 0, x constr at level 0). Notation "'SS' x" := (S x) (in custom stlc at level 89, x custom stlc at level 99). Check <{SS (? I)}>. End Bug18342. Declare Custom Entry qmark. Module Bug18342VariantWithExplicitCoercions. Definition A (T : True) := 0. Notation "?" := A (in custom qmark). Notation "{{ x }}" := x (x custom qmark). Notation "<{ e }>" := e (e custom stlc at level 99). Notation "[[ x ]]" := x (in custom stlc at level 0, x constr). Notation "'SS' x" := (S x) (in custom stlc at level 89, x custom stlc at level 99). Check <{SS [[{{?}} I]]}>. End Bug18342VariantWithExplicitCoercions. Module Bug18342VariantPattern. Inductive I := C : nat -> I | D : I -> I. Notation "?" := C (in custom qmark). Notation "{{ x }}" := x (x custom qmark). Notation "<{ e }>" := e (e custom stlc at level 99). Notation "[[ x ]]" := x (in custom stlc at level 0, x constr). Notation "'DD' x" := (D x) (in custom stlc at level 89, x custom stlc at level 99). Check fun x => match x with <{DD [[{{?}} y]]}> => y | _ => 0 end. End Bug18342VariantPattern. rocq-9.2.0/test-suite/output/bug_18368.out000066400000000000000000000000021516144147600202140ustar00rootroot00000000000000B rocq-9.2.0/test-suite/output/bug_18368.v000066400000000000000000000001751516144147600176650ustar00rootroot00000000000000Tactic Notation (at level 4) "test" := idtac "A". Tactic Notation (at level 5) "test" := idtac "B". Goal True. test. Abort. rocq-9.2.0/test-suite/output/bug_18657.out000066400000000000000000000003261516144147600202260ustar00rootroot00000000000000bar_1: bar = 1 First.bar_1: First.bar = 1 bar: nat First.bar: nat First.bar_1: First.bar = 1 bar_1: bar = 1 bar_1: bar = 1 bar_1: bar = 1 one_bar: 1 = bar baz_foo: baz tt = foo baz: unit -> t baz_foo: baz tt = foo rocq-9.2.0/test-suite/output/bug_18657.v000066400000000000000000000017641516144147600176730ustar00rootroot00000000000000Module First. Definition bar := 1. Lemma bar_1 : bar = 1. Proof. reflexivity. Qed. End First. Module Import Second. Include First. Search bar. (*First.bar_1: First.bar = 1*) Search "bar". Lemma one_bar : 1 = bar. Proof. rewrite bar_1. reflexivity. Qed. End Second. Module Type B. Definition bar := 1. Lemma bar_1 : bar = 1. Proof. reflexivity. Qed. End B. Module A. Include B. Search bar. (* was nothing *) Lemma one_bar : 1 = bar. Proof. rewrite bar_1; reflexivity. Qed. Search bar. (* was only one_bar *) End A. Module Type HasFoo. Parameter t : Type. Parameter foo : t. End HasFoo. Module MakeBaz (Import M : HasFoo). Definition baz := fun (_ : unit) => foo. Lemma baz_foo : baz tt = foo. Proof. reflexivity. Qed. End MakeBaz. Module Import Baz <: HasFoo. Definition t := nat. Definition foo := 42. Include MakeBaz. Search baz. (* was nothing *) Search "baz". (* was nothing *) Lemma foo_bas : foo = baz tt. Proof. rewrite baz_foo. reflexivity. Qed. End Baz. rocq-9.2.0/test-suite/output/bug_18914.out000066400000000000000000000000311516144147600202130ustar00rootroot00000000000000< a ++ b ++ c > : C rocq-9.2.0/test-suite/output/bug_18914.v000066400000000000000000000006141516144147600176600ustar00rootroot00000000000000Declare Custom Entry mor. Declare Custom Entry obj. Notation "< x >" := (x) (x custom mor). Notation "x" := x (in custom mor at level 0, x global). Notation "x" := x (in custom obj at level 0, x global). Parameter C : Type. Parameters a b c : C. Parameter op3 : C -> C -> C. Notation "x ++ y" := (op3 x y) (y custom obj, in custom mor at level 40, left associativity). Check (< a ++ b ++ c >). rocq-9.2.0/test-suite/output/bug_19047.out000066400000000000000000000013661516144147600202250ustar00rootroot00000000000000File "./output/bug_19047.v", line 11, characters 2-135: The command has indeed failed with message: Recursive definition of F is ill-formed. In environment coacc_rect : forall (A : Type) (R : A -> A -> Prop) (P : A -> Type), (forall x : A, (forall y : A, R x y -> coAcc R y) -> (forall y : A, R x y -> P y) -> P x) -> forall x : A, coAcc R x -> P x A : Type R : A -> A -> Prop P : A -> Type f : forall x : A, (forall y : A, R x y -> coAcc R y) -> (forall y : A, R x y -> P y) -> P x F : forall x : A, coAcc R x -> P x x : R a : coAcc P x The codomain is "f x" which should be a coinductive type. Recursive definition is: "fun (x : A) (a : coAcc R x) => match a with | coAcc_intro _ _ g => f x g (fun (y : A) (r : R x y) => F y (g y r)) end". rocq-9.2.0/test-suite/output/bug_19047.v000066400000000000000000000012061516144147600176540ustar00rootroot00000000000000CoInductive coAcc {A : Type} (R : A -> A -> Prop) (x : A) : Prop := | coAcc_intro : (forall y : A, R x y -> coAcc R y) -> coAcc R x. Fail CoFixpoint coacc_rect : forall (A : Type) (R : A -> A -> Prop) (P : A -> Type), (forall x : A, (forall y : A, R x y -> coAcc R y) -> (forall y : A, R x y -> P y) -> P x) -> forall x : A, coAcc R x -> P x := fun (A : Type) (R : A -> A -> Prop) (P : A -> Type) (f : (forall x : A, (forall y : A, R x y -> coAcc R y) -> (forall y : A, R x y -> P y) -> P x)) => cofix F (x : A) (a : coAcc R x) : P x := match a with | coAcc_intro _ _ g => f x g (fun (y : A) (r : R x y) => F y (g y r)) end. rocq-9.2.0/test-suite/output/bug_19138.out000066400000000000000000000001421516144147600202150ustar00rootroot00000000000000Existential 1 = ?f : [ |- False] (only printing) Existential 1 = ?f : [ |- False] (only printing) rocq-9.2.0/test-suite/output/bug_19138.v000066400000000000000000000010521516144147600176540ustar00rootroot00000000000000From Ltac2 Require Import Ltac2 Constr. Import Constr.Unsafe. Goal True. let t := open_constr:(_ :> False) in match kind t with | Evar e _ => Control.new_goal e > [refine 'I|] | _ => Control.throw Not_found end. Show Existentials. (* Existential 1 = ?Goal : [ |- False] (shelved) *) Abort. Goal True. let t := unshelve open_constr:(_ :> False) in Control.extend [Control.shelve] (fun () => ()) []; match kind t with | Evar e _ => Control.new_goal e > [refine 'I|] | _ => Control.throw Not_found end. Show Existentials. Abort. rocq-9.2.0/test-suite/output/bug_19227.out000066400000000000000000000002221516144147600202130ustar00rootroot00000000000000test = fun x : T 0 => match x in T _ e return e = e with | C _ => eq_refl end : T 0 -> 0 = 0 Arguments test x rocq-9.2.0/test-suite/output/bug_19227.v000066400000000000000000000004211516144147600176520ustar00rootroot00000000000000Inductive T (a := 0) : nat -> Set := C : T 0. Definition test (x : T 0) := match x in T e return e = e with C => eq_refl end. Print test. (* was test = fun x : T 0 => match x in (@T _ _ e) return (e = e) with | C _ => eq_refl end : T 0 -> 0 = 0 Arguments test x *) rocq-9.2.0/test-suite/output/bug_19541.out000066400000000000000000000000001516144147600202040ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/bug_19541.v000066400000000000000000000002031516144147600176470ustar00rootroot00000000000000Reserved Notation "{[ x ]}" (at level 0, x at level 200). Reserved Notation "{[ x | P ]}" (at level 0, x at level 200 as pattern). rocq-9.2.0/test-suite/output/bug_19658.out000066400000000000000000000000001516144147600202150ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/bug_19658.v000066400000000000000000000003071516144147600176650ustar00rootroot00000000000000Reserved Notation "'<{' x1 .. xn '<<{' z '}>'" (at level 0, z at level 50, x1 binder, xn binder). Reserved Notation "'<{' x1 .. xn '<{' z '}>'" (at level 0, z at level 60, x1 binder, xn binder). rocq-9.2.0/test-suite/output/bug_19806.out000066400000000000000000000000221516144147600202140ustar00rootroot00000000000000(define y test) rocq-9.2.0/test-suite/output/bug_19806.v000066400000000000000000000002721516144147600176610ustar00rootroot00000000000000Require Extraction. Parameter X : Set. Parameter x : X. Extract Constant X => "X". Extract Inlined Constant x => "test". Definition y := x. Extraction Language Scheme. Extraction y. rocq-9.2.0/test-suite/output/bug_19861.out000066400000000000000000000004421516144147600202230ustar00rootroot00000000000000File "./output/bug_19861.v", line 8, characters 2-6: Error: The following section variable is used but not declared: HypFalse. You can either update your proof to not depend on HypFalse, or you can update your Proof line from Proof using to Proof using HypFalse coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_19861.v000066400000000000000000000003411516144147600176570ustar00rootroot00000000000000Section S. Hypothesis HypFalse : False. Lemma false_in_section : False. Proof using. abstract (apply HypFalse). (* in bad versions, both Qed and Fail Qed succeed (ie Qed fails when wrapped in Fail) *) Qed. rocq-9.2.0/test-suite/output/bug_20020.out000066400000000000000000000000221516144147600201700ustar00rootroot00000000000000"bla"%ts : t rocq-9.2.0/test-suite/output/bug_20020.v000066400000000000000000000005331516144147600176350ustar00rootroot00000000000000Require PrimString. Declare Scope t_scope. Delimit Scope t_scope with ts. Import PrimString. Inductive t := v : string -> t. Definition parse : string -> t := v. Definition print : t -> string := fun x => match x with v s => s end. String Notation t parse print : t_scope. Check v "bla". (* string notation not used: [v "bla"] *) rocq-9.2.0/test-suite/output/bug_20188.out000066400000000000000000000005511516144147600202160ustar00rootroot00000000000000File "./output/bug_20188.v", line 4, characters 11-14: The command has indeed failed with message: The reference foo was not found in the current environment. ?Goal : ?T where ?T : [ |- Type] ?Goal : [ |- ?T] File "./output/bug_20188.v", line 6, characters 8-11: Error: The reference foo was not found in the current environment. coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_20188.v000066400000000000000000000004541516144147600176560ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Notation "[[ x ]]" := ltac2:(()) (only parsing). Notation "[ x ]" := ltac2:(let x := Ltac2.Constr.pretype x in exact $x) (only parsing). Fail Check foo. (* Error: The reference foo was not found in the current environment. *) Check [[ foo ]]. (* success *) Check [ foo ]. rocq-9.2.0/test-suite/output/bug_20242.out000066400000000000000000000005011516144147600202000ustar00rootroot00000000000000File "./output/bug_20242.v", line 5, characters 49-60: The command has indeed failed with message: Signature components for field B do not match: expected type "foo@{Type ; A.A.u0} bug_20242.B.A" but found type "foo@{SProp ; bug_20242.26} bug_20242.B.A". Error: The module B needs to be closed. coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_20242.v000066400000000000000000000003411516144147600176400ustar00rootroot00000000000000Polymorphic Record foo@{s;u|} (x : Type@{s;u}) := {}. Inductive sEmpty : SProp := . Module Type A. Axiom A : Type. Axiom B : foo A. End A. Unset Universe Checking. Module B <: A. Axiom A : SProp. Axiom B : foo A. Fail End B. rocq-9.2.0/test-suite/output/bug_20668.out000066400000000000000000000001171516144147600202170ustar00rootroot00000000000000tt : unit A'.B'.x : unit x : unit B.x : unit x : unit rocq-9.2.0/test-suite/output/bug_20668.v000066400000000000000000000010141516144147600176520ustar00rootroot00000000000000Module Import A. Module B. Abbreviation x := tt. End B. End A. Check B.x. (* should say tt *) Module A'. Module B'. #[global] Abbreviation x := tt. End B'. End A'. Check tt. (* should say A'.B'.x *) Import B. Check tt. (* should say x *) Import A'.B'. Check tt. (* should say B.x (qualified because "x" is short name for B'.x, but B'.x not used for printing because the printing rule didn't get replayed by Import so is still shadowed by B.x) *) Disable Notation B.x. Check tt. (* should say x *) rocq-9.2.0/test-suite/output/bug_20711.out000066400000000000000000000002611516144147600202040ustar00rootroot00000000000000module Main where import qualified Prelude data Bool = True | False type Foo = Bool type Wrapper = Foo -- singleton inductive, whose constructor was Build_Wrapper rocq-9.2.0/test-suite/output/bug_20711.v000066400000000000000000000002141516144147600176400ustar00rootroot00000000000000Require Extraction. Extraction Language Haskell. Definition foo := bool. Record Wrapper := { v1 : foo; }. Recursive Extraction Wrapper. rocq-9.2.0/test-suite/output/bug_20754.out000066400000000000000000000003751516144147600202210ustar00rootroot00000000000000Notation "x * y" := (prod x y) prod : Type -> Type -> Type prod is template universe polymorphic Arguments prod (A B)%_type_scope Expands to: Inductive Corelib.Init.Datatypes.prod Declared in library Corelib.Init.Datatypes, line 257, characters 10-14 rocq-9.2.0/test-suite/output/bug_20754.v000066400000000000000000000000241516144147600176460ustar00rootroot00000000000000About "_ * _"%type. rocq-9.2.0/test-suite/output/bug_20766.out000066400000000000000000000007211516144147600202170ustar00rootroot00000000000000File "./output/bug_20766.v", line 10, characters 39-40: The command has indeed failed with message: An entry of name f already exists in the mutual block. File "./output/bug_20766.v", line 15, characters 30-31: The command has indeed failed with message: An entry of name f already exists in the mutual block. File "./output/bug_20766.v", line 19, characters 50-51: The command has indeed failed with message: An entry of name f already exists in the mutual block. rocq-9.2.0/test-suite/output/bug_20766.v000066400000000000000000000012511516144147600176540ustar00rootroot00000000000000Inductive loop := L { deloop : loop }. Module M1. (* succeeds producing fix f := f0 _ with f0 := f0 _ for f *) Definition f := fix f (t : loop) : False := f (deloop t) with f (t : loop) := f (deloop t) for f. End M1. Module M2. (* Warning: Not a fully mutually defined fixpoint (f and f are not mutually dependent). then fails with "f already exists" (because we try to add 2 constants named f) *) Fail Fixpoint f (t : unit) := 0 with f (t : unit) := 1. End M2. Module M3. (* stack overflow *) Fail Fixpoint f _ := _ with f _ := _. End M3. Module M4. (* stack overflow *) Fail Fixpoint f (t : loop) := f (deloop t) with f (t : loop) := f (deloop t). End M4. rocq-9.2.0/test-suite/output/bug_20968.out000066400000000000000000000001241516144147600202200ustar00rootroot00000000000000fun x : T => match x with | C i => i end : T -> True rocq-9.2.0/test-suite/output/bug_20968.v000066400000000000000000000001541516144147600176610ustar00rootroot00000000000000Inductive T := C (c := I) (n : nat). Arguments C {_}. Check fun x => match x return True with C i => i end. rocq-9.2.0/test-suite/output/bug_21176.out000066400000000000000000000000661516144147600202150ustar00rootroot00000000000000(** val effect0 : nat -> nat **) let effect0 x = x rocq-9.2.0/test-suite/output/bug_21176.v000066400000000000000000000001221516144147600176440ustar00rootroot00000000000000Require Import Extraction. Definition effect (x : nat) := x. Extraction effect. rocq-9.2.0/test-suite/output/bug_21288.out000066400000000000000000000003211516144147600202130ustar00rootroot00000000000000Ltac foo := (intuition idtac) || fail "boom" Ltac bar := intuition idtac || fail "baam" File "./output/bug_21288.v", line 12, characters 7-10: The command has indeed failed with message: Tactic failure: baam. rocq-9.2.0/test-suite/output/bug_21288.v000066400000000000000000000006111516144147600176530ustar00rootroot00000000000000Ltac foo := (intuition idtac) || fail "boom". Ltac bar := intuition idtac || fail "baam". (* parsed as [intuition (idtac || fail "baam")] *) Print Ltac foo. (* printed without parentheses, ie equivalent to bar *) Print Ltac bar. Goal True -> 2 = 3. (* yet foo is not equivalent to bar ( "||" runs the second tactic if the first doesn't make progress) *) Succeed foo. Fail bar. Abort. rocq-9.2.0/test-suite/output/bug_21319.out000066400000000000000000000002361516144147600202130ustar00rootroot00000000000000File "./output/bug_21319.v", line 3, characters 26-29: The command has indeed failed with message: The variable bar was not found in the current environment. rocq-9.2.0/test-suite/output/bug_21319.v000066400000000000000000000003321516144147600176460ustar00rootroot00000000000000Goal True. Proof. Fail assert (h:forall x:bar, True). (* Toplevel input, characters 11-12: > assert (h:forall x:bar, True). > ^ Error: The variable bar was not found in the current environment. *) Abort. rocq-9.2.0/test-suite/output/bug_2304.out000066400000000000000000000002141516144147600201200ustar00rootroot00000000000000File "./output/bug_2304.v", line 3, characters 21-22: The command has indeed failed with message: Could not find an instance for "A unit". rocq-9.2.0/test-suite/output/bug_2304.v000066400000000000000000000002201516144147600175530ustar00rootroot00000000000000(* This used to fail with an anomaly NotASort at some time *) Class A (O: Type): Type := a: O -> Type. Fail Goal forall (x: a tt), @a x = @a x. rocq-9.2.0/test-suite/output/bug_3810.out000066400000000000000000000003231516144147600201240ustar00rootroot00000000000000test : Foo -> nat -> forall {A : Type}, A test is not universe polymorphic Arguments test H n%_nat_scope {A}%_type_scope Expands to: Constant bug_3810.test Declared in library bug_3810, line 3, characters 9-13 rocq-9.2.0/test-suite/output/bug_3810.v000066400000000000000000000003311516144147600175610ustar00rootroot00000000000000Class Foo. Fixpoint test (H : Foo) (n : nat) {A : Type} {struct n} : A. Admitted. About test. (* test : Foo -> nat -> forall A : Type, A test is universe polymorphic Argument n is implicit and maximally inserted *) rocq-9.2.0/test-suite/output/bug_4167.out000066400000000000000000000000661516144147600201360ustar00rootroot00000000000000foo = foo : Prop t1.(foo) = t2.(foo) : Prop rocq-9.2.0/test-suite/output/bug_4167.v000066400000000000000000000003221516144147600175670ustar00rootroot00000000000000Class test {y x: nat} : Set := { foo: nat }. Parameter (x y:nat) (t1 t2: @ test x y). Existing Instance t1. Existing Instance t2. Check t1.(foo) = t2.(foo). Set Printing Projections. Check t1.(foo) = t2.(foo). rocq-9.2.0/test-suite/output/bug_4337.out000066400000000000000000000003531516144147600201340ustar00rootroot00000000000000File "./output/bug_4337.v", line 4, characters 35-36: The command has indeed failed with message: In environment Foo : list var -> term -> Prop l : list var x : var The term "x" has type "var" while it is expected to have type "term". rocq-9.2.0/test-suite/output/bug_4337.v000066400000000000000000000001571516144147600175740ustar00rootroot00000000000000Axiom var term : Type. Fail Inductive Foo : list var -> term -> Prop := | foo : forall l x, Foo (cons x l) x. rocq-9.2.0/test-suite/output/bug_4712_part2.out000066400000000000000000000004521516144147600212410ustar00rootroot00000000000000File "./output/bug_4712_part2.v", line 6, characters 21-28: The command has indeed failed with message: The reference foobarA was not found in the current environment. File "./output/bug_4712_part2.v", line 8, characters 21-22: Error: Syntax Error: Lexer: Undefined token coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_4712_part2.v000066400000000000000000000003151516144147600206750ustar00rootroot00000000000000Module Example2. Notation "'foobar'" := 1. Definition a := foobar. Definition A := 2. Fail Definition b := foobarA. Notation "'\foobar'" := (fun x => 1 + x). Fail Definition b := \foobarA. End Example2. rocq-9.2.0/test-suite/output/bug_4900.out000066400000000000000000000003111516144147600201220ustar00rootroot00000000000000File "./output/bug_4900.v", line 1, characters 0-48: The command has indeed failed with message: Timeout! File "./output/bug_4900.v", line 2, characters 0-48: Error: Timeout! coqc exited with code 1 rocq-9.2.0/test-suite/output/bug_4900.v000066400000000000000000000001421516144147600175620ustar00rootroot00000000000000Fail Timeout 1 Check ltac:(repeat pose proof I). Timeout 1 Fail Check ltac:(repeat pose proof I). rocq-9.2.0/test-suite/output/bug_5222.out000066400000000000000000000004401516144147600201230ustar00rootroot000000000000001 goal ============================ True = (nil : T1 nat) File "./output/bug_5222.v", line 16, characters 2-40: Warning: C2 does not respect the uniform inheritance condition. [uniform-inheritance,coercions,default] 1 goal ============================ True = (nil : T2 nat) rocq-9.2.0/test-suite/output/bug_5222.v000066400000000000000000000006611516144147600175660ustar00rootroot00000000000000(* coq-prog-args: ("-async-proofs" "off") *) Definition T1 (X : Type) : Type := list X. Coercion C1 (X: Type) (A : T1 X) : Prop := True. (* Works fine. *) Goal True = (nil : T1 nat). Proof. Show. trivial. Qed. Definition T2 (X : Type) : Type := list X. Section S. Context (X : Type). Coercion C2 (A : T2 X) : Prop := True. End S. Goal True = (nil : T2 nat). (* The coercion works... *) Proof. Show. trivial. Qed. rocq-9.2.0/test-suite/output/bug_6613.out000066400000000000000000000000331516144147600201260ustar00rootroot00000000000000Ltac bar := foo constr:(5) rocq-9.2.0/test-suite/output/bug_6613.v000066400000000000000000000001031516144147600175620ustar00rootroot00000000000000Ltac foo n := idtac. Ltac bar := foo constr:(5). Print Ltac bar. rocq-9.2.0/test-suite/output/bug_6764.out000066400000000000000000000002301516144147600201340ustar00rootroot00000000000000forall f : foo, β–  f = β–  f : Prop forall f : foo, β–  f = β–  f : Prop fun x : T => %% x : T -> nat fun x : T => %% x : T -> nat rocq-9.2.0/test-suite/output/bug_6764.v000066400000000000000000000011311516144147600175730ustar00rootroot00000000000000Module A. Set Primitive Projections. Record foo := Foo { foo_n : nat }. Notation "'β– ' x" := (foo_n x) (at level 50). Check forall (f:foo), β–  f = β–  f. End A. Module A'. Set Primitive Projections. Record foo := Foo { foo_n : nat }. Notation "'β– ' x" := x.(foo_n) (at level 50). Check forall (f:foo), β–  f = β–  f. End A'. (* Variant with non-primitive projections *) Module B. Record T := {a:nat}. Notation "%% x" := (a x) (at level 2, x at level 2). Check fun x => %%x. End B. Module B'. Record T := {a:nat}. Notation "%% x" := x.(a) (at level 2, x at level 2). Check fun x => %%x. End B'. rocq-9.2.0/test-suite/output/bug_7443.out000066400000000000000000000013541516144147600201370ustar00rootroot00000000000000Literal 1 : Type File "./output/bug_7443.v", line 21, characters 2-46: Warning: Notation "[ _ ]" was already used in scope foo_scope. [notation-overridden,parsing,default] [1] : Type File "./output/bug_7443.v", line 23, characters 2-82: Warning: Notation "[ _ ]" was already used in scope foo_scope. [notation-overridden,parsing,default] Literal 1 : Type [1] : Type File "./output/bug_7443.v", line 30, characters 14-15: The command has indeed failed with message: The term "1" has type "Datatypes.nat" while it is expected to have type "denote ?t". File "./output/bug_7443.v", line 33, characters 2-82: Warning: Notation "[ _ ]" was already used in scope foo_scope. [notation-overridden,parsing,default] Literal 1 : Type rocq-9.2.0/test-suite/output/bug_7443.v000066400000000000000000000032521516144147600175740ustar00rootroot00000000000000Inductive type := nat | bool. Definition denote (t : type) := match t with | nat => Datatypes.nat | bool => Datatypes.bool end. Ltac reify t := lazymatch eval cbv beta in t with | Datatypes.nat => nat | Datatypes.bool => bool end. Abbreviation reify t := (ltac:(let rt := reify t in exact rt)) (only parsing). Abbreviation reify_type_of e := (reify ((fun t (_ : t) => t) _ e)) (only parsing). Axiom Literal : forall {t}, denote t -> Type. Declare Scope foo_scope. Delimit Scope foo_scope with foo. Open Scope foo_scope. Section A. Notation "[ x ]" := (Literal (t:=reify_type_of x) x) (only parsing) : foo_scope. Check [1]. (* Literal 1 : Type *) (* as expected *) Notation "[ x ]" := (Literal x) : foo_scope. Check @Literal nat 1. (* Incorred: gives Literal 1 : Type when it should give [1]. Fixed by #12950 *) Notation "[ x ]" := (Literal (t:=reify_type_of x) x) (only parsing) : foo_scope. Check [1]. (* Incorrect: gives Literal 1 : Type when it should give [1]. This is disputable: #12950 considers that giving an only parsing a previous both-parsing-and-printing notation *) End A. Section B. Notation "[ x ]" := (Literal x) : foo_scope. Check @Literal nat 1. (* [1] : Type *) Fail Check [1]. (* As expected: The command has indeed failed with message: The term "1" has type "Datatypes.nat" while it is expected to have type "denote ?t". *) Notation "[ x ]" := (Literal (t:=reify_type_of x) x) (only parsing) : foo_scope. Check [1]. (* Should succeed, but instead fails with: Error: The term "1" has type "Datatypes.nat" while it is expected to have type "denote ?t". Fixed by #12950, but previous declaration is cancelled by #12950. *) End B. rocq-9.2.0/test-suite/output/bug_8206.out000066400000000000000000000004631516144147600201350ustar00rootroot00000000000000File "./output/bug_8206.v", line 11, characters 0-28: The command has indeed failed with message: Signature components for field homework do not match: expected type "forall a b : nat, bug_8206.M.add a b = bug_8206.M.add b a" but found type "nat -> forall b : nat, bug_8206.M.add 0 b = bug_8206.M.add b 0". rocq-9.2.0/test-suite/output/bug_8206.v000066400000000000000000000004141516144147600175670ustar00rootroot00000000000000Module Type Sig. Parameter add: nat -> nat -> nat. Axiom homework: forall (a b: nat), add a b = add b a. End Sig. Module Impl. Definition add(a b: nat) := plus a b. Axiom homework: forall (a b: nat), add 0 b = add b 0. End Impl. Fail Module M : Sig := Impl. rocq-9.2.0/test-suite/output/bug_9180.out000066400000000000000000000002251516144147600201330ustar00rootroot00000000000000Notation "n .+1" := (S n) (* n in scope _nat_scope *) : nat_scope (default interpretation) (from bug_9180) forall x : nat, x.+1 = x.+1 : Prop rocq-9.2.0/test-suite/output/bug_9180.v000066400000000000000000000004541516144147600175750ustar00rootroot00000000000000Abbreviation succn := (Datatypes.S). Notation "n .+1" := (succn n) (at level 1, left associativity, format "n .+1") : nat_scope. Locate ".+1". (* Notation *) (* "n .+1" := S n : nat_scope (default interpretation) *) (** so Coq does not apply succn notation *) Check forall x : nat, x.+1 = x.+1. rocq-9.2.0/test-suite/output/bug_9403.out000066400000000000000000000002271516144147600201330ustar00rootroot000000000000001 goal X : tele Ξ±, Ξ², Ξ³1, Ξ³2 : X -> Prop ============================ accessor Ξ± Ξ² Ξ³1 -> accessor Ξ± Ξ² (Ξ».. x : X, Ξ³1 x \/ Ξ³2 x) rocq-9.2.0/test-suite/output/bug_9403.v000066400000000000000000000065021516144147600175730ustar00rootroot00000000000000(* Uselessly long but why not *) Local Set Universe Polymorphism. Module tele. (** Telescopes *) Inductive tele : Type := | TeleO : tele | TeleS {X} (binder : X -> tele) : tele. Arguments TeleS {_} _. (** The telescope version of Coq's function type *) Fixpoint tele_fun (TT : tele) (T : Type) : Type := match TT with | TeleO => T | TeleS b => forall x, tele_fun (b x) T end. Notation "TT -t> A" := (tele_fun TT A) (at level 99, A at level 200, right associativity). (** An eliminator for elements of [tele_fun]. We use a [fix] because, for some reason, that makes stuff print nicer in the proofs in iris:bi/lib/telescopes.v *) Definition tele_fold {X Y} {TT : tele} (step : forall {A : Type}, (A -> Y) -> Y) (base : X -> Y) : (TT -t> X) -> Y := (fix rec {TT} : (TT -t> X) -> Y := match TT as TT return (TT -t> X) -> Y with | TeleO => fun x : X => base x | TeleS b => fun f => step (fun x => rec (f x)) end) TT. Arguments tele_fold {_ _ !_} _ _ _ /. (** A sigma-like type for an "element" of a telescope, i.e. the data it takes to get a [T] from a [TT -t> T]. *) Inductive tele_arg : tele -> Type := | TargO : tele_arg TeleO (* the [x] is the only relevant data here *) | TargS {X} {binder} (x : X) : tele_arg (binder x) -> tele_arg (TeleS binder). Definition tele_app {TT : tele} {T} (f : TT -t> T) : tele_arg TT -> T := fun a => (fix rec {TT} (a : tele_arg TT) : (TT -t> T) -> T := match a in tele_arg TT return (TT -t> T) -> T with | TargO => fun t : T => t | TargS x a => fun f => rec a (f x) end) TT a f. Arguments tele_app {!_ _} _ !_ /. Coercion tele_arg : tele >-> Sortclass. Local Coercion tele_app : tele_fun >-> Funclass. (** Operate below [tele_fun]s with argument telescope [TT]. *) Fixpoint tele_bind {U} {TT : tele} : (TT -> U) -> TT -t> U := match TT as TT return (TT -> U) -> TT -t> U with | TeleO => fun F => F TargO | @TeleS X b => fun (F : TeleS b -> U) (x : X) => (* b x -t> U *) tele_bind (fun a => F (TargS x a)) end. Arguments tele_bind {_ !_} _ /. (** Notation-compatible telescope mapping *) (* This adds (tele_app ∘ tele_bind), which is an identity function, around every binder so that, after simplifying, this matches the way we typically write notations involving telescopes. *) Notation "t $ r" := (t r) (at level 65, right associativity, only parsing). Notation "'Ξ»..' x .. y , e" := (tele_app $ tele_bind (fun x => .. (tele_app $ tele_bind (fun y => e)) .. )) (at level 200, x binder, y binder, right associativity, format "'[ ' 'Ξ»..' x .. y ']' , e"). (** Telescopic quantifiers *) Definition texist {TT : tele} (Ξ¨ : TT -> Prop) : Prop := tele_fold ex (fun x => x) (tele_bind Ξ¨). Arguments texist {!_} _ /. Notation "'βˆƒ..' x .. y , P" := (texist (fun x => .. (texist (fun y => P)) .. )) (at level 200, x binder, y binder, right associativity, format "βˆƒ.. x .. y , P"). End tele. Import tele. (* This is like Iris' accessors, but in Prop. Just to play with telescopes. *) Definition accessor {X : tele} (Ξ± Ξ² Ξ³ : X -> Prop) : Prop := βˆƒ.. x, Ξ± x /\ (Ξ² x -> Ξ³ x). (* Working with abstract telescopes. *) Section tests. Context {X : tele}. Implicit Types Ξ± Ξ² Ξ³ : X -> Prop. Lemma acc_mono_disj Ξ± Ξ² Ξ³1 Ξ³2 : accessor Ξ± Ξ² Ξ³1 -> accessor Ξ± Ξ² (Ξ».. x, Ξ³1 x \/ Ξ³2 x). Show. Abort. End tests. rocq-9.2.0/test-suite/output/bug_9555.out000066400000000000000000000001121516144147600201340ustar00rootroot00000000000000Module Type F = Funsig (X:S) Sig Parameter T : Type. Parameter a : T. End rocq-9.2.0/test-suite/output/bug_9555.v000066400000000000000000000001441516144147600175770ustar00rootroot00000000000000Module Type S. Axiom T : Type. Axiom a : T. End S. Module Type F (X : S) := S. Print Module Type F. rocq-9.2.0/test-suite/output/bug_9569.out000066400000000000000000000005521516144147600201510ustar00rootroot000000000000001 goal ============================ exists I : True, I = Logic.I 1 goal ============================ f True False True False (Logic.True /\ Logic.False) 1 goal ============================ [I | I = Logic.I; I = Logic.I] = [I | I = Logic.I; I = Logic.I] 1 goal ============================ [I & I = Logic.I | I = Logic.I; Logic.I = I] rocq-9.2.0/test-suite/output/bug_9569.v000066400000000000000000000010461516144147600176060ustar00rootroot00000000000000Goal exists I, I = Logic.I. Show. Abort. Abbreviation f x y p q r := ((forall x, p /\ r) /\ forall y, q /\ r). Goal f True False True False (Logic.True /\ Logic.False). Show. Abort. Notation "[ x | y ; z ; .. ; t ]" := (pair .. (pair (forall x, y) (forall x, z)) .. (forall x, t)). Goal [ I | I = Logic.I ; I = Logic.I ] = [ I | I = Logic.I ; I = Logic.I ]. Show. Abort. Notation "[ x & p | y ; .. ; z ; t ]" := (forall x, p -> y -> .. (forall x, p -> z -> forall x, p -> t) ..). Goal [ I & I = Logic.I | I = Logic.I ; Logic.I = I ]. Show. Abort. rocq-9.2.0/test-suite/output/bug_9682.out000066400000000000000000000001601516144147600201400ustar00rootroot00000000000000mmatch 1 + 2 + 3 + 4 + 5 + 6 in nat as x return M (x = x) with | 1 end : unit # : True ## : True rocq-9.2.0/test-suite/output/bug_9682.v000066400000000000000000000025411516144147600176030ustar00rootroot00000000000000Declare Scope blafu. Delimit Scope blafu with B. Axiom DoesNotMatch : Type. Axiom consumer : forall {A} (B : A -> Type) (E:Type) (x : A) (ls : list nat), unit. Notation "| p1 | .. | pn" := (@cons _ p1 .. (@cons _ pn nil) ..) (at level 91) : blafu. Notation "'mmatch_do_not_write' x 'in' T 'as' y 'return' 'M' p 'with_do_not_write' ls" := (@consumer _ (fun y : T => p%type) DoesNotMatch x ls%B) (at level 200, ls at level 91, only parsing). Notation "'mmatch' x 'in' T 'as' y 'return' 'M' p 'with' ls 'end'" := (mmatch_do_not_write x in T as y return M p with_do_not_write ls) (at level 0, ls at level 91, p at level 10, only parsing). (* This should not gives a warning *) Notation "'mmatch' x 'in' T 'as' y 'return' 'M' p 'with' ls 'end'" := (@consumer _ (fun y : T => p%type) DoesNotMatch x ls%B) (at level 0, ls at level 91, p at level 10, only printing, format "'[ ' mmatch '/' x ']' '/' '[ ' in '/' T ']' '/' '[ ' as '/' y ']' '/' '[ ' return M p ']' with '//' '[' ls ']' '//' end" ). (* Check use of "mmatch" *) Check (mmatch 1 + 2 + 3 + 4 + 5 + 6 in nat as x return M (x = x) with | 1 end). (* 2nd example *) Notation "#" := I (at level 0, only parsing). Notation "#" := I (at level 0, only printing). Check #. Notation "##" := I (at level 0, only printing). Notation "##" := I (at level 0, only parsing). Check ##. rocq-9.2.0/test-suite/output/clear.out000066400000000000000000000000771516144147600177700ustar00rootroot000000000000001 goal z := 0 : nat ============================ True rocq-9.2.0/test-suite/output/clear.v000066400000000000000000000003611516144147600174220ustar00rootroot00000000000000Module Wish11692. (* Support for let-in in clear dependent *) Goal forall x : Prop, let z := 0 in let z' : (fun _ => True) x := I in let y := x in y -> True. Proof. intros x z z' y H. clear dependent x. Show. exact I. Qed. End Wish11692. rocq-9.2.0/test-suite/output/coercions_cs.out000066400000000000000000000001421516144147600213440ustar00rootroot00000000000000f foo_nat x : T2 nat : T2 nat f (foo_A nat ?n) x : T2 nat : T2 nat where ?n : [ |- nat] rocq-9.2.0/test-suite/output/coercions_cs.v000066400000000000000000000010351516144147600210040ustar00rootroot00000000000000Set Warnings "-uniform-inheritance". Set Printing All. Module CS. Structure foo := { sort :> Type; a : sort }. Axiom T1 : Type -> Type. Axiom T2 : Type -> Type. Axiom x : T1 nat. Module T1. Axiom f : forall A : foo, T1 (sort A) -> T2 nat. #[canonical] Definition foo_nat := {| sort := nat; a := 1 |}. Coercion f : T1 >-> T2. Check (x : T2 _). End T1. Module T2. Axiom f : forall A : foo, T1 (sort A) -> T2 nat. #[canonical] Definition foo_A A x := {| sort := A; a := x |}. Coercion f : T1 >-> T2. Check (f _ x : T2 _). End T2. End CS. rocq-9.2.0/test-suite/output/coercions_nonuniform.out000066400000000000000000000005231516144147600231340ustar00rootroot00000000000000File "./output/coercions_nonuniform.v", line 22, characters 0-21: Warning: f does not respect the uniform inheritance condition. [uniform-inheritance,coercions,default] File "./output/coercions_nonuniform.v", line 55, characters 0-17: Warning: f' does not respect the uniform inheritance condition. [uniform-inheritance,coercions,default] rocq-9.2.0/test-suite/output/coercions_nonuniform.v000066400000000000000000000027021516144147600225730ustar00rootroot00000000000000(* Test the nonuniform attribute to silence warnings on coercions not satisfying the non uniform inheritance condition. *) Module Test0. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (n : nat) (b : bool), C n b -> D. (* uniform inheritance satisfied, no warning *) Coercion f : C >-> D. End Test0. Module Test1. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (b : bool) (n : nat), C n b -> D. (* uniform inheritance not satisfied, warning *) Coercion f : C >-> D. End Test1. Module Test2. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (b : bool) (n : nat), C n b -> D. (* uniform inheritance not satisfied but attribute, no warning *) #[warning="-uniform-inheritance"] Coercion f : C >-> D. End Test2. Module Test3. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (n : nat) (b : bool), C n b -> D. (* uniform inheritance satisfied, no warning *) Coercion f' := f. End Test3. Module Test4. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (b : bool) (n : nat), C n b -> D. (* uniform inheritance not satisfied, warning *) Coercion f' := f. End Test4. Module Test5. Parameter C : nat -> bool -> Type. Parameter D : Type. Parameter f : forall (b : bool) (n : nat), C n b -> D. (* uniform inheritance not satisfied but attribute, no warning *) #[warning="-uniform-inheritance"] Coercion f' := f. End Test5. rocq-9.2.0/test-suite/output/coercions_tc.out000066400000000000000000000002661516144147600213540ustar00rootroot00000000000000f nat (pair_foo nat bool nat_foo bool_foo) x : T2 nat : T2 nat f ?T ?f x : T2 ?T : T2 ?T where ?T : [ |- Type] ?f : [ |- foo ?T] f bool bool_foo x : T2 bool : T2 bool rocq-9.2.0/test-suite/output/coercions_tc.v000066400000000000000000000012501516144147600210040ustar00rootroot00000000000000Set Warnings "-uniform-inheritance". Set Printing All. Module TC. Class foo (A : Type) := { a : A }. #[local] Hint Mode foo + : typeclass_instances. #[local] Instance bool_foo : foo bool := {| a := true |}. #[local] Instance nat_foo : foo nat := {| a := 1 |}. #[local] Instance pair_foo A B : foo A -> foo B -> foo (A * B) := fun x y => {| a := (a,a) |}. Axiom T1 : Type -> Type. Axiom T2 : Type -> Type. Axiom x : T1 nat. Module T1. Axiom f : forall A, foo (A * bool) -> T1 A -> T2 nat. Coercion f : T1 >-> T2. Check (x : T2 _). End T1. Module T2. Axiom f : forall A, foo A -> T1 nat -> T2 A. Coercion f : T1 >-> T2. Check (x : T2 _). Check (x : T2 bool). End T2. End TC. rocq-9.2.0/test-suite/output/compat_not_found.out000066400000000000000000000002231516144147600222310ustar00rootroot00000000000000While loading initial state: Warning: Did not find compatibility module tutu with prefix Tata. [compatibility-module-not-found,filesystem,default] rocq-9.2.0/test-suite/output/compat_not_found.v000066400000000000000000000003141516144147600216700ustar00rootroot00000000000000(* -*- coq-prog-args: ("-compat-from" "Tata" "tutu"); -*- *) (* From Tata Require tutu. would fail but -compat-from only issues a warning and the file compiles fine. *) Goal True. Proof. exact I. Qed. rocq-9.2.0/test-suite/output/deprecation_definition.out000066400000000000000000000031211516144147600234000ustar00rootroot00000000000000File "./output/deprecation_definition.v", line 27, characters 6-11: Warning: Reference depr1 is deprecated. deprecable [deprecated-reference,deprecated,default] depr1 : True File "./output/deprecation_definition.v", line 28, characters 6-11: Warning: Reference depr2 is deprecated. deprecable [deprecated-reference,deprecated,default] depr2 : True File "./output/deprecation_definition.v", line 29, characters 6-11: Warning: Reference depr3 is deprecated. deprecable [deprecated-reference,deprecated,default] depr3 : True File "./output/deprecation_definition.v", line 30, characters 6-11: Warning: Reference depr4 is deprecated. deprecable [deprecated-reference,deprecated,default] depr4 : Prop File "./output/deprecation_definition.v", line 31, characters 6-11: Warning: Reference depr5 is deprecated. deprecable [deprecated-reference,deprecated,default] depr5 : Prop File "./output/deprecation_definition.v", line 32, characters 6-11: Warning: Reference depr6 is deprecated. deprecable [deprecated-reference,deprecated,default] depr6 : nat -> nat File "./output/deprecation_definition.v", line 38, characters 6-11: Warning: Reference depr7 is deprecated. deprecable [deprecated-reference,deprecated,default] File "./output/deprecation_definition.v", line 38, characters 6-11: Warning: be careful [warn-reference-be-careful-careful,careful,be-careful,warn-reference,user-warn,default] File "./output/deprecation_definition.v", line 38, characters 6-11: Warning: also about bla [warn-reference-careful-careful-bla,careful-bla,careful,warn-reference,user-warn,default] depr7 : Prop rocq-9.2.0/test-suite/output/deprecation_definition.v000066400000000000000000000013411516144147600230400ustar00rootroot00000000000000Require Import Corelib.Program.Tactics. #[deprecated(note="deprecable")] Lemma depr1 : True. Proof. exact I. Qed. #[deprecated(note="deprecable")] Theorem depr2 : True. Proof. exact I. Qed. #[deprecated(note="deprecable")] Axiom depr3 : True. #[deprecated(note="deprecable")] Definition depr4 := True. #[deprecated(note="deprecable")] Program Definition depr5 := True. #[deprecated(note="deprecable")] Fixpoint depr6 n := match n with S n => depr6 n | 0 => 1 end. Check depr1. Check depr2. Check depr3. Check depr4. Check depr5. Check depr6. #[deprecated(note="deprecable"), warn(note="be careful", cats="careful, be careful"), warn(note="also about bla", cats="careful, careful bla")] Definition depr7 := True. Check depr7. rocq-9.2.0/test-suite/output/detype_cast.out000066400000000000000000000003051516144147600212000ustar00rootroot00000000000000(Nat.add : forall (_ : nat) (_ : nat), nat) O O : nat (Nat.add O : forall _ : nat, nat) O : nat (?n O : forall _ : nat, nat) O : nat where ?n : [ |- forall (_ : nat) (_ : nat), nat] rocq-9.2.0/test-suite/output/detype_cast.v000066400000000000000000000001631516144147600206400ustar00rootroot00000000000000Set Printing All. Check (plus : nat -> nat -> nat) O O. Check (plus O : nat -> nat) O. Check (_ O : nat -> nat) O. rocq-9.2.0/test-suite/output/extra_dep.out000066400000000000000000000004161516144147600206520ustar00rootroot00000000000000File "./output/extra_dep.v", line 1, characters 0-55: The command has indeed failed with message: No LoadPath found for NonExistent. File "./output/extra_dep.v", line 2, characters 0-49: The command has indeed failed with message: File not_there not found in TestSuite. rocq-9.2.0/test-suite/output/extra_dep.v000066400000000000000000000001521516144147600203050ustar00rootroot00000000000000Fail From NonExistent Extra Dependency "extra_dep.txt". Fail From TestSuite Extra Dependency "not_there". rocq-9.2.0/test-suite/output/extraction_projection.out000066400000000000000000000123401516144147600233120ustar00rootroot00000000000000 type unit0 = | Tt type bool = | True | False type non_prim_record_two_fields = { non_prim_proj1_of_2 : bool; non_prim_proj2_of_2 : bool } type non_prim_record_one_field = bool (* singleton inductive, whose constructor was Build_non_prim_record_one_field *) (** val d11 : non_prim_record_two_fields -> bool **) let d11 x = x.non_prim_proj1_of_2 (** val d12 : (unit0 -> non_prim_record_two_fields) -> bool **) let d12 x = (x Tt).non_prim_proj1_of_2 (** val e11 : non_prim_record_one_field -> bool **) let e11 x = x (** val e12 : (unit0 -> non_prim_record_one_field) -> bool **) let e12 x = x Tt type prim_record_two_fields = { prim_proj1_of_2 : bool; prim_proj2_of_2 : bool } type prim_record_one_field = bool (* singleton inductive, whose constructor was Build_prim_record_one_field *) (** val d21 : prim_record_two_fields -> bool **) let d21 x = x.prim_proj1_of_2 (** val d22 : (unit0 -> prim_record_two_fields) -> bool **) let d22 x = (x Tt).prim_proj1_of_2 (** val e21 : prim_record_one_field -> bool **) let e21 x = x (** val e22 : (unit0 -> prim_record_one_field) -> bool **) let e22 x = x Tt type unit0 = | Tt type bool = | True | False module A = struct type non_prim_record_two_fields = { non_prim_proj1_of_2 : bool; non_prim_proj2_of_2 : bool } (** val non_prim_proj1_of_2 : non_prim_record_two_fields -> bool **) let non_prim_proj1_of_2 n = n.non_prim_proj1_of_2 type non_prim_record_one_field = bool (* singleton inductive, whose constructor was Build_non_prim_record_one_field *) (** val non_prim_proj1_of_1 : non_prim_record_one_field -> bool **) let non_prim_proj1_of_1 n = n (** val d11 : non_prim_record_two_fields -> bool **) let d11 x = x.non_prim_proj1_of_2 (** val d12 : (unit0 -> non_prim_record_two_fields) -> bool **) let d12 x = (x Tt).non_prim_proj1_of_2 (** val e11 : non_prim_record_one_field -> bool **) let e11 x = x (** val e12 : (unit0 -> non_prim_record_one_field) -> bool **) let e12 x = x Tt type prim_record_two_fields = { prim_proj1_of_2 : bool; prim_proj2_of_2 : bool } type prim_record_one_field = bool (* singleton inductive, whose constructor was Build_prim_record_one_field *) (** val d21 : prim_record_two_fields -> bool **) let d21 x = x.prim_proj1_of_2 (** val d22 : (unit0 -> prim_record_two_fields) -> bool **) let d22 x = (x Tt).prim_proj1_of_2 (** val e21 : prim_record_one_field -> bool **) let e21 x = x (** val e22 : (unit0 -> prim_record_one_field) -> bool **) let e22 x = x Tt end type unit0 = | Tt type bool = | True | False module type Nop = sig end module Empty = struct end module M = functor (X:Nop) -> struct type non_prim_record_two_fields = { non_prim_proj1_of_2 : bool; non_prim_proj2_of_2 : bool } (** val non_prim_proj1_of_2 : non_prim_record_two_fields -> bool **) let non_prim_proj1_of_2 n = n.non_prim_proj1_of_2 (** val non_prim_proj2_of_2 : non_prim_record_two_fields -> bool **) let non_prim_proj2_of_2 n = n.non_prim_proj2_of_2 type non_prim_record_one_field = bool (* singleton inductive, whose constructor was Build_non_prim_record_one_field *) (** val non_prim_proj1_of_1 : non_prim_record_one_field -> bool **) let non_prim_proj1_of_1 n = n type non_prim_record_one_field_unused = bool (* singleton inductive, whose constructor was Build_non_prim_record_one_field_unused *) (** val non_prim_proj1_of_1_unused : non_prim_record_one_field_unused -> bool **) let non_prim_proj1_of_1_unused n = n (** val d11 : non_prim_record_two_fields -> bool **) let d11 x = x.non_prim_proj1_of_2 (** val d12 : (unit0 -> non_prim_record_two_fields) -> bool **) let d12 x = (x Tt).non_prim_proj1_of_2 (** val e11 : non_prim_record_one_field -> bool **) let e11 x = x (** val e12 : (unit0 -> non_prim_record_one_field) -> bool **) let e12 x = x Tt type prim_record_two_fields = { prim_proj1_of_2 : bool; prim_proj2_of_2 : bool } (** val prim_proj1_of_2 : prim_record_two_fields -> bool **) let prim_proj1_of_2 p = p.prim_proj1_of_2 (** val prim_proj2_of_2 : prim_record_two_fields -> bool **) let prim_proj2_of_2 p = p.prim_proj2_of_2 type prim_record_one_field = bool (* singleton inductive, whose constructor was Build_prim_record_one_field *) (** val prim_proj1_of_1 : prim_record_one_field -> bool **) let prim_proj1_of_1 p = p type prim_record_one_field_unused = bool (* singleton inductive, whose constructor was Build_prim_record_one_field_unused *) (** val prim_proj1_of_1_unused : prim_record_one_field_unused -> bool **) let prim_proj1_of_1_unused p = p (** val d21 : prim_record_two_fields -> bool **) let d21 x = x.prim_proj1_of_2 (** val d22 : (unit0 -> prim_record_two_fields) -> bool **) let d22 x = (x Tt).prim_proj1_of_2 (** val e21 : prim_record_one_field -> bool **) let e21 x = x (** val e22 : (unit0 -> prim_record_one_field) -> bool **) let e22 x = x Tt end module N = M(Empty) rocq-9.2.0/test-suite/output/extraction_projection.v000066400000000000000000000061071516144147600227540ustar00rootroot00000000000000(** Miscellaneous tests on the ocaml extraction *) Require Import Extraction. Extraction Language OCaml. (** Extraction at toplevel *) Record non_prim_record_two_fields := {non_prim_proj1_of_2:bool;non_prim_proj2_of_2:bool}. Record non_prim_record_one_field := {non_prim_proj1_of_1:bool}. Record non_prim_record_one_field_unused := {non_prim_proj1_of_1_unused:bool}. Definition d11 x := x.(non_prim_proj1_of_2). Definition d12 x := (x tt).(non_prim_proj1_of_2). Definition e11 x := x.(non_prim_proj1_of_1). Definition e12 x := (x tt).(non_prim_proj1_of_1). Set Primitive Projections. Record prim_record_two_fields := {prim_proj1_of_2:bool;prim_proj2_of_2:bool}. Record prim_record_one_field := {prim_proj1_of_1:bool}. Record prim_record_one_field_unused := {prim_proj1_of_1_unused:bool}. Unset Primitive Projections. Definition d21 x := x.(prim_proj1_of_2). Definition d22 x := (x tt).(prim_proj1_of_2). Definition e21 x := x.(prim_proj1_of_1). Definition e22 x := (x tt).(prim_proj1_of_1). Recursive Extraction d11 d12 d21 d22 e11 e12 e21 e22. (** Extraction in module *) Module A. Record non_prim_record_two_fields := {non_prim_proj1_of_2:bool;non_prim_proj2_of_2:bool}. Record non_prim_record_one_field := {non_prim_proj1_of_1:bool}. Record non_prim_record_one_field_unused := {non_prim_proj1_of_1_unused:bool}. Definition d11 x := x.(non_prim_proj1_of_2). Definition d12 x := (x tt).(non_prim_proj1_of_2). Definition e11 x := x.(non_prim_proj1_of_1). Definition e12 x := (x tt).(non_prim_proj1_of_1). Set Primitive Projections. Record prim_record_two_fields := {prim_proj1_of_2:bool;prim_proj2_of_2:bool}. Record prim_record_one_field := {prim_proj1_of_1:bool}. Record prim_record_one_field_unused := {prim_proj1_of_1_unused:bool}. Unset Primitive Projections. Definition d21 x := x.(prim_proj1_of_2). Definition d22 x := (x tt).(prim_proj1_of_2). Definition e21 x := x.(prim_proj1_of_1). Definition e22 x := (x tt).(prim_proj1_of_1). End A. Recursive Extraction A.d11 A.d12 A.d21 A.d22 A.e11 A.e12 A.e21 A.e22. (* Inside a functor *) Module Type Nop. End Nop. Module Empty. End Empty. Module M (X : Nop). Record non_prim_record_two_fields := {non_prim_proj1_of_2:bool;non_prim_proj2_of_2:bool}. Record non_prim_record_one_field := {non_prim_proj1_of_1:bool}. Record non_prim_record_one_field_unused := {non_prim_proj1_of_1_unused:bool}. Definition d11 x := x.(non_prim_proj1_of_2). Definition d12 x := (x tt).(non_prim_proj1_of_2). Definition e11 x := x.(non_prim_proj1_of_1). Definition e12 x := (x tt).(non_prim_proj1_of_1). Set Primitive Projections. Record prim_record_two_fields := {prim_proj1_of_2:bool;prim_proj2_of_2:bool}. Record prim_record_one_field := {prim_proj1_of_1:bool}. Record prim_record_one_field_unused := {prim_proj1_of_1_unused:bool}. Unset Primitive Projections. Definition d21 x := x.(prim_proj1_of_2). Definition d22 x := (x tt).(prim_proj1_of_2). Definition e21 x := x.(prim_proj1_of_1). Definition e22 x := (x tt).(prim_proj1_of_1). End M. Module N := M Empty. Recursive Extraction N.d11 N.d12 N.d21 N.d22 N.e11 N.e12 N.e21 N.e22. rocq-9.2.0/test-suite/output/global_inst.out000066400000000000000000000000201516144147600211630ustar00rootroot00000000000000foo_0 : Foo | 2 rocq-9.2.0/test-suite/output/global_inst.v000066400000000000000000000002551516144147600206330ustar00rootroot00000000000000Class Foo := foo : nat. Definition foo_0 : Foo := 0. Module X. Global Existing Instance foo_0 | 1. End X. Existing Instance foo_0 | 2. Import X. Print Instances Foo. rocq-9.2.0/test-suite/output/goal_output.out000066400000000000000000000020771516144147600212460ustar00rootroot00000000000000Nat.t = nat : Set Nat.t = nat : Set 2 goals ============================ True goal 2 is: True 2 goals, goal 1 (?Goal) ============================ True goal 2 (?Goal0) is: True 1 goal ============================ True 1 goal (?Goal0) ============================ True 1 goal (?Goal0) ============================ True *** Unfocused goals: goal 2 (?Goal1) is: True goal 3 (?Goal) is: True 1 goal ============================ True *** Unfocused goals: goal 2 is: True goal 3 is: True This subproof is complete, but there are some unfocused goals. Focus next goal with bullet -. 2 goals goal 1 is: True goal 2 is: True This subproof is complete, but there are some unfocused goals. Focus next goal with bullet -. 2 goals goal 1 (?Goal0) is: True goal 2 (?Goal) is: True This subproof is complete, but there are some unfocused goals. Focus next goal with bullet -. 1 goal goal 1 is: True This subproof is complete, but there are some unfocused goals. Focus next goal with bullet -. 1 goal goal 1 (?Goal) is: True rocq-9.2.0/test-suite/output/goal_output.v000066400000000000000000000010751516144147600207010ustar00rootroot00000000000000(* From - https://coq.inria.fr/bugs/show_bug.cgi?id=5529 - https://coq.inria.fr/bugs/show_bug.cgi?id=5537 *) Print Nat.t. Timeout 1 Print Nat.t. Set Printing All. Lemma toto: True/\True. Proof. split. Show. Set Printing Goal Names. Show. Unset Printing Goal Names. assert True. - idtac. Show. Set Printing Goal Names. Show. Set Printing Unfocused. Show. Unset Printing Goal Names. Show. Unset Printing Unfocused. auto. Show. Set Printing Goal Names. Show. Unset Printing Goal Names. - auto. Show. Set Printing Goal Names. Show. Unset Printing Goal Names. Abort. rocq-9.2.0/test-suite/output/idtac.out000066400000000000000000000001251516144147600177600ustar00rootroot00000000000000"foo" True foo 3 foo 2 < True False Prop > < True False Prop > < > < > << 1 2 3 >> rocq-9.2.0/test-suite/output/idtac.v000066400000000000000000000017451516144147600174270ustar00rootroot00000000000000(* Printing all kinds of Ltac generic arguments *) Tactic Notation "myidtac" string(v) := idtac v. Goal True. myidtac "foo". Abort. Tactic Notation "myidtac2" ref(c) := idtac c. Goal True. myidtac2 True. Abort. Tactic Notation "myidtac3" preident(s) := idtac s. Goal True. myidtac3 foo. Abort. Tactic Notation "myidtac4" int_or_var(n) := idtac n. Goal True. myidtac4 3. Abort. Tactic Notation "myidtac5" ident(id) := idtac id. Goal True. myidtac5 foo. Abort. (* Checking non focussing of idtac for integers *) Goal True/\True. split. all:let c:=numgoals in idtac c. Abort. (* Checking printing of lists and its focussing *) Tactic Notation "myidtac6" constr_list(l) := idtac "<" l ">". Goal True/\True. split. all:myidtac6 True False Prop. (* An empty list is focussing because of interp_genarg of a constr *) (* even if it is not focussing on printing *) all:myidtac6. Abort. Tactic Notation "myidtac7" int_list(l) := idtac "<<" l ">>". Goal True/\True. split. all:myidtac7 1 2 3. Abort. rocq-9.2.0/test-suite/output/inference.out000066400000000000000000000007041516144147600206350ustar00rootroot00000000000000P = fun e : option L => match e with | Some cl => Some cl | None => None end : option L -> option L Arguments P e fun n : nat => let y : T n := A n in ?t ?x : T n : forall n : nat, T n where ?t : [n : nat y := A n : T n |- ?T -> T n] ?x : [n : nat y := A n : T n |- ?T] fun n : nat => ?t ?x : T n : forall n : nat, T n where ?t : [n : nat |- ?T -> T n] ?x : [n : nat |- ?T] rocq-9.2.0/test-suite/output/inference.v000066400000000000000000000013271516144147600202750ustar00rootroot00000000000000(* Check that types are not uselessly unfolded *) (* Check here that P returns something of type "option L" and not "option (list nat)" *) Definition L := list nat. Definition P (e:option L) := match e with | None => None | Some cl => Some cl end. Print P. (* Check that the heuristic to solve constraints is not artificially dependent on the presence of a let-in, and in particular that the second [_] below is not inferred to be n, as if obtained by first-order unification with [T n] of the conclusion [T _] of the type of the first [_]. *) (* Note: exact numbers of evars are not important... *) Inductive T (n:nat) := A : T n. Check fun n (y:=A n:T n) => _ _ : T n. Check fun n => _ _ : T n. rocq-9.2.0/test-suite/output/injection.out000066400000000000000000000003701516144147600206600ustar00rootroot00000000000000File "./output/injection.v", line 4, characters 39-42: The command has indeed failed with message: Unexpected pattern. File "./output/injection.v", line 5, characters 35-42: The command has indeed failed with message: Unexpected injection pattern. rocq-9.2.0/test-suite/output/injection.v000066400000000000000000000003231516144147600203140ustar00rootroot00000000000000(* Test error messages *) Goal forall x, (x,0) = (0, S x) -> x = 0. Fail intros x H; injection H as [= H'] H''. Fail intros x H; injection H as H' [= H'']. intros x H; injection H as [= H' H'']. exact H'. Qed. rocq-9.2.0/test-suite/output/interleave_options_bad_order.out000066400000000000000000000002331516144147600246060ustar00rootroot00000000000000While loading initial state: Warning: There is no flag or option with this name: "Extraction Optimize". [unknown-option,default] Extraction Optimize is on rocq-9.2.0/test-suite/output/interleave_options_bad_order.v000066400000000000000000000001441516144147600242450ustar00rootroot00000000000000(* coq-prog-args: ("-unset" "Extraction Optimize" "-ri" "Extraction") *) Test Extraction Optimize. rocq-9.2.0/test-suite/output/interleave_options_correct_order.out000066400000000000000000000000331516144147600255170ustar00rootroot00000000000000Extraction Optimize is off rocq-9.2.0/test-suite/output/interleave_options_correct_order.v000066400000000000000000000001441516144147600251600ustar00rootroot00000000000000(* coq-prog-args: ("-ri" "Extraction" "-unset" "Extraction Optimize") *) Test Extraction Optimize. rocq-9.2.0/test-suite/output/lexical_convention_in_doc.out000066400000000000000000000005511516144147600240750ustar00rootroot00000000000000not (not True) : Prop not True : Prop not (not True) : Prop not (not True) : Prop not False : Prop (fun x : Prop => not (not x)) o : Prop File "./output/lexical_convention_in_doc.v", line 53, characters 12-15: The command has indeed failed with message: The reference _ho was not found in the current environment. True : Prop rocq-9.2.0/test-suite/output/lexical_convention_in_doc.v000066400000000000000000000032611516144147600235340ustar00rootroot00000000000000Set Printing All. Set Warnings "-prefix-incompatible-level". (* if ``~`` and ``~~`` are both defined as tokens, the inputs ``~ ~`` and ``~~`` generate different tokens *) Section TestLexer0. #[warning="-closed-notation-not-level-0"] Local Notation "~" := not. Local Notation "~~" := not. Check ~ ~ True. Check ~~ True. End TestLexer0. (* whereas if ``~~`` is not defined, then the two inputs are equivalent *) Section TestLexer1. #[warning="-closed-notation-not-level-0"] Local Notation "~" := not. Set Printing All. Check ~ ~ True. Check ~~ True. End TestLexer1. (* Also, if ``~`` and ``~_h`` are both defined as tokens, the input ``~_ho`` is interpreted as ``~ _ho`` rather than ``~_h o`` so as not to cut the identifier-like subsequence ``ho``. *) Section TestLexer2. #[warning="-closed-notation-not-level-0"] Local Notation "~" := not. Local Notation "~_h" := (fun x => not (not x)). Local Notation "'_ho'" := False. Let o := True. Check ~_ho. Check ~_h o. End TestLexer2. (* Contrastingly, if only ``~_h`` is defined as a token, then ``~_ho`` is an error because no token can be found that includes the whole subsequence ``ho`` without cutting it in the middle. *) Section TestLexer3. Local Notation "~_h" := (fun x => not (not x)). Fail Check ~_ho. End TestLexer3. (* Finally, if all of ``~``, ``~_h`` and ``~_ho`` are defined as tokens, the input ``~_ho`` is interpreted using the longest match rule, i.e. as the token ``~_ho``. *) Section TestLexer4. #[warning="-closed-notation-not-level-0"] Local Notation "~" := not. Local Notation "~_h" := (fun x => not (not x)). Local Notation "'_ho'" := False. Local Notation "~_ho" := True. Check ~_ho. End TestLexer4. rocq-9.2.0/test-suite/output/library_attributes.out000066400000000000000000000012451516144147600226120ustar00rootroot00000000000000File "./output/library_attributes.v", line 4, characters 16-21: The command has indeed failed with message: This command does not support this attribute: local. [unsupported-attributes,parsing,default] File "./output/library_attributes.v", line 7, characters 0-70: The command has indeed failed with message: A library attribute should be at toplevel of the library. File "./output/library_attributes.v", line 11, characters 0-69: The command has indeed failed with message: A library attribute should be at toplevel of the library. File "./output/library_attributes.v", line 14, characters 0-71: The command has indeed failed with message: Library file is already deprecated. rocq-9.2.0/test-suite/output/library_attributes.v000066400000000000000000000010501516144147600222420ustar00rootroot00000000000000Attributes deprecated(note="This library is useless.", since="XX YY"). (* unsupported attributes *) Fail Attributes local. Section Sec. Fail Attributes deprecated(note="No library attributes in sections."). End Sec. Module Mod. Fail Attributes deprecated(note="No library attributes in modules."). End Mod. Fail Attributes deprecated(note="This library is already deprecated."). Attributes warn(note="This library is dangerous.", cats="dangerous library"). Attributes warn(note="This library is tricky.", cats="dangerous library, tricky library"). rocq-9.2.0/test-suite/output/library_attributes_require.out000066400000000000000000000012771516144147600243530ustar00rootroot00000000000000File "./output/library_attributes_require.v", line 1, characters 0-37: Warning: Library File TestSuite.deprecated_library is deprecated since XX YY. This library is useless. [deprecated-library-file-since-XX-YY,deprecated-since-XX-YY,deprecated-library-file,deprecated,default] File "./output/library_attributes_require.v", line 1, characters 0-37: Warning: This library is dangerous. [warn-library-file-dangerous-library,dangerous-library,warn-library-file,user-warn,default] File "./output/library_attributes_require.v", line 1, characters 0-37: Warning: This library is tricky. [warn-library-file-dangerous-library-tricky-library,tricky-library,dangerous-library,warn-library-file,user-warn,default] rocq-9.2.0/test-suite/output/library_attributes_require.v000066400000000000000000000000461516144147600240020ustar00rootroot00000000000000Require TestSuite.deprecated_library. rocq-9.2.0/test-suite/output/library_attributes_require_transitive.out000066400000000000000000000013401516144147600266120ustar00rootroot00000000000000File "./output/library_attributes_require_transitive.v", line 5, characters 0-37: Warning: Library File TestSuite.deprecated_library is deprecated since XX YY. This library is useless. [deprecated-library-file-since-XX-YY,deprecated-since-XX-YY,deprecated-library-file,deprecated,default] File "./output/library_attributes_require_transitive.v", line 5, characters 0-37: Warning: This library is dangerous. [warn-library-file-dangerous-library,dangerous-library,warn-library-file,user-warn,default] File "./output/library_attributes_require_transitive.v", line 5, characters 0-37: Warning: This library is tricky. [warn-library-file-dangerous-library-tricky-library,tricky-library,dangerous-library,warn-library-file,user-warn,default] rocq-9.2.0/test-suite/output/library_attributes_require_transitive.v000066400000000000000000000004421516144147600262520ustar00rootroot00000000000000(* check that file deprecations are only printed on direct requirement *) Require TestSuite.requires_deprecated_library. (* but still printed on direct requirement even if the Require doesn't actually do anything (because file is already loaded) *) Require TestSuite.deprecated_library. rocq-9.2.0/test-suite/output/library_attributes_require_transitive_2.out000066400000000000000000000014501516144147600270350ustar00rootroot00000000000000File "./output/library_attributes_require_transitive_2.v", line 5, characters 0-46: Warning: Library File (transitively required) TestSuite.deprecated_library is deprecated since XX YY. This library is useless. [deprecated-transitive-library-file-since-XX-YY,deprecated-since-XX-YY,deprecated-transitive-library-file,deprecated] File "./output/library_attributes_require_transitive_2.v", line 5, characters 0-46: Warning: This library is dangerous. [warn-transitive-library-file-dangerous-library,dangerous-library,warn-transitive-library-file,user-warn] File "./output/library_attributes_require_transitive_2.v", line 5, characters 0-46: Warning: This library is tricky. [warn-transitive-library-file-dangerous-library-tricky-library,tricky-library,dangerous-library,warn-transitive-library-file,user-warn] rocq-9.2.0/test-suite/output/library_attributes_require_transitive_2.v000066400000000000000000000004131516144147600264710ustar00rootroot00000000000000(* We have the second warning "deprecated-transitive-library-file" that always triggers (even on transitive requires) *) Set Warnings "deprecated-transitive-library-file". Set Warnings "warn-transitive-library-file". Require TestSuite.requires_deprecated_library. rocq-9.2.0/test-suite/output/load/000077500000000000000000000000001516144147600170645ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/load/Load_noproof.v000066400000000000000000000000231516144147600216670ustar00rootroot00000000000000Definition f := 2. rocq-9.2.0/test-suite/output/load/Load_openproof.v000066400000000000000000000000201516144147600222110ustar00rootroot00000000000000Lemma k : True. rocq-9.2.0/test-suite/output/load/Load_proof.v000066400000000000000000000000451516144147600213360ustar00rootroot00000000000000Lemma u : True. Proof. exact I. Qed. rocq-9.2.0/test-suite/output/locate.out000066400000000000000000000016231516144147600201470ustar00rootroot00000000000000Notation "b1 && b2" := (if b1 then b2 else false) (default interpretation) (from locate) Notation "x && y" := (andb x y) (* x in scope _bool_scope, y in scope _bool_scope *) : bool_scope (from Corelib.Init.Datatypes) Notation "'U' t" := (S t) (* t in scope _nat_scope *) (default interpretation) (from locate.M) Notation "'_' t" := (S t) (* t in scope _nat_scope *) (default interpretation) (from locate.M) Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope (default interpretation) (from Corelib.Init.Datatypes) Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope (default interpretation) (from Corelib.Init.Datatypes) Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope (default interpretation) (from Corelib.Init.Datatypes) Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope (default interpretation) (from Corelib.Init.Datatypes) rocq-9.2.0/test-suite/output/locate.v000066400000000000000000000007201516144147600176020ustar00rootroot00000000000000Set Printing Width 400. Notation "b1 && b2" := (if b1 then b2 else false). Locate "&&". Module M. Notation "'U' t" := (S t) (at level 2). Notation "'_' t" := (S t) (at level 2). Locate "U". (* was wrongly returning also "'_' t" *) Locate "_". End M. Module N. (* Was not working at some time *) Locate "( t , u , .. , v )". (* Was working though *) Locate "( _ , _ , .. , _ )". (* We also support this *) Locate "( t , u )". Locate "( t , u , v )". End N. rocq-9.2.0/test-suite/output/ltac.out000066400000000000000000000040331516144147600176210ustar00rootroot00000000000000File "./output/ltac.v", line 8, characters 13-31: The command has indeed failed with message: Ltac variable y depends on pattern variable name z which is not bound in current context. Ltac f x y z := symmetry in x, y; auto with z; auto; intros; clearbody x; generalize dependent z File "./output/ltac.v", line 38, characters 5-9: The command has indeed failed with message: The term "I" has type "True" while it is expected to have type "False". In nested Ltac calls to "g1" and "refine (uconstr)", last call failed. File "./output/ltac.v", line 39, characters 5-9: The command has indeed failed with message: The term "I" has type "True" while it is expected to have type "False". In nested Ltac calls to "f1 (constr)" and "refine (uconstr)", last call failed. File "./output/ltac.v", line 40, characters 5-9: The command has indeed failed with message: The term "I" has type "True" while it is expected to have type "False". In nested Ltac calls to "g2 (constr)", "g1" and "refine (uconstr)", last call failed. File "./output/ltac.v", line 41, characters 5-9: The command has indeed failed with message: The term "I" has type "True" while it is expected to have type "False". In nested Ltac calls to "f2", "f1 (constr)" and "refine (uconstr)", last call failed. File "./output/ltac.v", line 46, characters 5-8: The command has indeed failed with message: No primitive equality found. In nested Ltac calls to "h" and "injection (destruction_arg)", last call failed. File "./output/ltac.v", line 48, characters 5-8: The command has indeed failed with message: No primitive equality found. In nested Ltac calls to "h" and "injection (destruction_arg)", last call failed. Hx nat nat 0 0 Ltac foo := let x := intros in let y := intros -> in let v := constr:(nil) in let w := () in let z := 1 in pose v 2 goals n : nat ============================ (fix a (n0 : nat) : nat := match n0 with | 0 => 0 | S n1 => a n1 end) n = n goal 2 is: forall a : nat, a = 0 rocq-9.2.0/test-suite/output/ltac.v000066400000000000000000000033041516144147600172570ustar00rootroot00000000000000Set Ltac Backtrace. (* This used to refer to b instead of z sometimes between 8.4 and 8.5beta3 *) Goal True. Fail let T := constr:((fun a b : nat => a+b) 1 1) in lazymatch T with | (fun x z => ?y) 1 1 => pose ((fun x _ => y) 1 1) end. Abort. (* This should not raise a warning (see #4317) *) Goal True. assert (H:= eq_refl ((fun x => x) 1)). let HT := type of H in lazymatch goal with | H1 : HT |- _ => idtac end. Abort. Ltac f x y z := symmetry in x, y; auto with z; auto; intros; clearbody x; generalize dependent z. Print Ltac f. (* Error messages *) Ltac g1 x := refine x. Tactic Notation "g2" constr(x) := g1 x. Tactic Notation "f1" constr(x) := refine x. Ltac f2 x := f1 x. Goal False. Fail g1 I. Fail f1 I. Fail g2 I. Fail f2 I. Abort. Ltac h x := injection x. Goal True -> False. Fail h I. intro H. Fail h H. Abort. (* Check printing of the "var" argument "Hx" *) Ltac m H := idtac H; exact H. Goal True. let a:=constr:(let Hx := 0 in ltac:(m Hx)) in idtac. Abort. (* Check consistency of interpretation scopes (#4398) *) Goal nat*(0*0=0) -> nat*(0*0=0). intro. match goal with H: ?x*?y |- _ => idtac x end. match goal with |- ?x*?y => idtac x end. match goal with H: context [?x*?y] |- _ => idtac x end. match goal with |- context [?x*?y] => idtac x end. Abort. (* Check printing of let in Ltac and Tactic Notation *) Ltac foo := let x := intros in let y := intros -> in let v := constr:(@ nil True) in let w := () in let z := 1 in pose v. Print Ltac foo. (* Ltac renaming was not applied to "fix" and "cofix" *) Goal forall a, a = 0. match goal with |- (forall x, x = _) => assert (forall n, (fix x n := match n with O => O | S n => x n end) n = n) end. intro. Show. Abort. rocq-9.2.0/test-suite/output/ltac2_abstract.out000066400000000000000000000036351516144147600215750ustar00rootroot00000000000000File "./output/ltac2_abstract.v", line 20, characters 27-28: The command has indeed failed with message: This expression has type int but an expression was expected of type M.t - : M.t = File "./output/ltac2_abstract.v", line 28, characters 27-28: The command has indeed failed with message: This expression has type int but an expression was expected of type t - : int = 2 Ltac2 foo : t -> t foo := fun x => Int.add x 1 Ltac2 three : t three := 3 - : t = File "./output/ltac2_abstract.v", line 47, characters 18-21: The command has indeed failed with message: Unbound constructor M.A File "./output/ltac2_abstract.v", line 49, characters 40-43: The command has indeed failed with message: Unbound constructor M.A - : M.t = - : bool = false Ltac2 M.a : M.t M.a := Ltac2 M.is_b : M.t -> bool M.is_b := fun x => match x with end Ltac2 M.get_b : int -> M.t -> int M.get_b := fun def x => match x with | => x | _ => def end - : int M.t = File "./output/ltac2_abstract.v", line 73, characters 20-21: The command has indeed failed with message: p is not a projection File "./output/ltac2_abstract.v", line 75, characters 30-31: The command has indeed failed with message: p is not a projection - : int t = - : int = 42 File "./output/ltac2_abstract.v", line 81, characters 27-40: The command has indeed failed with message: This expression has type bool but an expression was expected of type int Ltac2 make : 'a -> 'a t make := fun x => Ltac2 p : 'a t -> 'a p := fun x => Ltac2 set : 'a t -> 'a -> unit set := fun x v => File "./output/ltac2_abstract.v", line 91, characters 32-33: The command has indeed failed with message: Open types currently do not support #[abstract]. rocq-9.2.0/test-suite/output/ltac2_abstract.v000066400000000000000000000037701516144147600212330ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Module AbstractType. (* redundant, maybe should be an error? *) #[abstract] Ltac2 Type t. End AbstractType. Module DefinedType. Module M. #[abstract] Ltac2 Type t := int. Ltac2 foo (x:t) : t := Int.add x 1. Ltac2 make (x:int) : t := x. Ltac2 repr (x:t) : int := x. Ltac2 three : t := 3. End M. Fail Ltac2 nope : M.t := 0. Ltac2 ok () : M.t := M.make 0. Ltac2 Eval ok (). Import M. Fail Ltac2 nope : M.t := 0. Ltac2 Eval repr (foo (make 1)). Print foo. Print three. Ltac2 Eval three. End DefinedType. Module AlgebraicType. Module M. #[abstract] Ltac2 Type t := [ A | B (int option) ]. Ltac2 a := A. Ltac2 is_b x := match x with B _ => true | _ => false end. Ltac2 get_b def x := match x with B (Some x) => x | _ => def end. End M. Fail Ltac2 Eval M.A. Fail Ltac2 Eval fun x => match x with M.A => true | _ => false end. Ltac2 Eval M.a. Ltac2 Eval M.is_b M.a. Print M.a. Print M.is_b. Print M.get_b. End AlgebraicType. Module RecordType. Module M. #[abstract] Ltac2 Type 'a t := { mutable p : 'a }. Ltac2 make x := { p := x }. Ltac2 set x v := x.(p) := v. Ltac2 p x := x.(p). End M. Ltac2 Eval M.make 0. Import M. Fail Ltac2 Eval { p := 0 }. Fail Ltac2 Eval fun x => x.(p). Ltac2 Eval make 42. Ltac2 Eval p (make 42). Fail Ltac2 Eval Int.add (p (make true)) 0. Print make. Print p. Print set. End RecordType. Module ExtensibleType. Module M. (* TODO figure out what this should do, error until then. *) Fail #[abstract] Ltac2 Type t := [ .. ]. (* Ltac2 Type t ::= [ E | E' ]. *) (* Fail #[abstract] Ltac2 Type t ::= [ F ]. *) (* Ltac2 e := E. *) (* Ltac2 is_e x := match x with E => true | _ => false end. *) End M. (* Import M. *) (* Ltac2 Eval E. *) (* Ltac2 Eval match E with E => true | _ => false end. *) (* Fail Ltac2 Type t ::= [ F ]. *) (* add more tests once we have something to test *) End ExtensibleType. rocq-9.2.0/test-suite/output/ltac2_anomaly_backtrace.out000066400000000000000000000004251516144147600234230ustar00rootroot00000000000000File "./output/ltac2_anomaly_backtrace.v", line 9, characters 0-18: Error: Anomaly "Uncaught exception Not_found." Please report at http://rocq-prover.org/bugs/. Backtrace: Call foo Call Std.eval_hnf Prim coqc exited with code 129 rocq-9.2.0/test-suite/output/ltac2_anomaly_backtrace.v000066400000000000000000000011051516144147600230550ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Ltac2 foo () := let v := Constr.Unsafe.make (Constr.Unsafe.Rel -1) in let x := Constr.Binder.make None 'True in let vv := Constr.Unsafe.make (Constr.Unsafe.App v (Array.of_list [v])) in let f := Constr.Unsafe.make (Constr.Unsafe.Lambda x vv) in let ff := Constr.Unsafe.make (Constr.Unsafe.App f (Array.of_list [f])) in Std.eval_hnf ff. Set Ltac2 Backtrace. Ltac2 Eval foo (). (* Error: Anomaly "Uncaught exception Not_found." Please report at http://coq.inria.fr/bugs/. *) rocq-9.2.0/test-suite/output/ltac2_bt.out000066400000000000000000000020671516144147600203750ustar00rootroot00000000000000File "./output/ltac2_bt.v", line 8, characters 2-48: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None Backtrace: Prim Call Prim File "./output/ltac2_bt.v", line 9, characters 2-49: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None Backtrace: Prim Call Prim File "./output/ltac2_bt.v", line 10, characters 2-60: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None Backtrace: Prim Call f Prim File "./output/ltac2_bt.v", line 11, characters 2-61: The command has indeed failed with message: Uncaught Ltac2 exception: Invalid_argument None Backtrace: Prim Call f Prim Backtrace: Call h Call g Call print_stack Prim rocq-9.2.0/test-suite/output/ltac2_bt.v000066400000000000000000000010401516144147600200210ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. Set Ltac2 Backtrace. Ltac2 f () := Control.zero (Invalid_argument None). Goal True. Proof. Fail Control.plus f (fun e => Control.zero e). Fail Control.plus f (fun e => Control.throw e). Fail Control.plus_bt f (fun e bt => Control.zero_bt e bt). Fail Control.plus_bt f (fun e bt => Control.throw_bt e bt). Abort. (* based on #21312 *) Ltac2 print_stack () := Message.print (Message.of_exninfo (Control.current_exninfo())). Ltac2 g () := print_stack (). Ltac2 h () := g (). Goal True. h (). Abort. rocq-9.2.0/test-suite/output/ltac2_check_globalize.out000066400000000000000000000022031516144147600230650ustar00rootroot00000000000000() () : unit fun x => x : 'a -> 'a () () (1, 2) 3 let x := () in x () File "./output/ltac2_check_globalize.v", line 22, characters 32-33: The command has indeed failed with message: This expression has type unit. It is not a function and cannot be applied. let x := fun x => x in let _ := x 1 in let _ := x "" in () let x := fun x => x in let _ := x 1 in let _ := x "" in () : unit let accu := { contents := []} in (let x := fun x => accu.(contents) := (x :: accu.(contents)) in let _ := x 1 in let _ := x "" in ()); accu.(contents) File "./output/ltac2_check_globalize.v", line 38, characters 0-144: The command has indeed failed with message: This expression has type string but an expression was expected of type int let (m : '__Ξ± Pattern.goal_matching) := ([(([(None, (Pattern.MatchPattern, pat:(_)))], (Pattern.MatchPattern, pat:(_))), (fun h => let h := Array.get h 0 in fun _ => fun _ => fun _ => fun _ => Std.clear h)); (([], (Pattern.MatchPattern, pat:(_))), (fun _ => fun _ => fun _ => fun _ => fun _ => ()))] : _ Pattern.goal_matching) in Pattern.lazy_goal_match0 false m :'__Ξ± constr:(ltac2:(())) rocq-9.2.0/test-suite/output/ltac2_check_globalize.v000066400000000000000000000021021516144147600225210ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Unset Ltac2 Typed Notations. Ltac2 Notation "foo" := (). Ltac2 Globalize foo. Ltac2 Check foo. Ltac2 Check (fun x => x : 'a -> 'a). Ltac2 Globalize (() ()). Ltac2 Notation "bar" := (1,2). (* check that CTacApp nodes don't get merged or that we handle merging them correctly. *) Ltac2 Globalize bar 3. Ltac2 Globalize let x := () in x (). Fail Ltac2 Check let x := () in x (). Ltac2 Notation "complicated_typing" x(tactic) := let _ := x 1 in let _ := x "" in (). Ltac2 Globalize complicated_typing (fun x => x). Ltac2 Check complicated_typing (fun x => x). Ltac2 Globalize let accu := { contents := [] } in complicated_typing (fun x => accu.(contents) := x :: accu.(contents)); accu.(contents). Fail Ltac2 Check let accu := { contents := [] } in complicated_typing (fun x => accu.(contents) := x :: accu.(contents)); accu.(contents). Ltac2 Globalize lazy_match! goal with | [h: _ |- _] => (* lots of code... *) Std.clear h (* more code... *) | [|- _] => (* lots of code... *) () end. Ltac2 Globalize constr:(ltac2:(foo)). rocq-9.2.0/test-suite/output/ltac2_deprecated.out000066400000000000000000000010771516144147600220700ustar00rootroot00000000000000File "./output/ltac2_deprecated.v", line 13, characters 11-14: Warning: Ltac2 definition foo is deprecated. test_definition [deprecated-ltac2-definition,deprecated,default] - : unit = () File "./output/ltac2_deprecated.v", line 14, characters 11-14: Warning: Ltac2 abbreviation bar is deprecated. test_notation [deprecated-ltac2-abbreviation,deprecated,default] - : unit = () File "./output/ltac2_deprecated.v", line 15, characters 11-14: Warning: Ltac2 definition qux is deprecated. test_external [deprecated-ltac2-definition,deprecated,default] - : 'a array -> int = rocq-9.2.0/test-suite/output/ltac2_deprecated.v000066400000000000000000000005541516144147600215250ustar00rootroot00000000000000Require Import Ltac2.Ltac2. #[deprecated(note="test_definition")] Ltac2 foo := (). #[deprecated(note="test_notation")] Ltac2 Abbreviation bar := (). #[deprecated(note="test_external")] Ltac2 @ external qux : 'a array -> int := "rocq-runtime.plugins.ltac2" "array_length". (* Randomly picked external function *) Ltac2 Eval foo. Ltac2 Eval bar. Ltac2 Eval qux. rocq-9.2.0/test-suite/output/ltac2_hyp_var.out000066400000000000000000000020051516144147600214300ustar00rootroot00000000000000File "./output/ltac2_hyp_var.v", line 3, characters 16-18: The command has indeed failed with message: Unbound value id - : constr = constr:(fun (_ : nat) (x : bool) => eq_refl : (x, x) = (x, x)) File "./output/ltac2_hyp_var.v", line 7, characters 33-40: The command has indeed failed with message: Hypothesis "x" (value of ltac2 variable "id") not found. File "./output/ltac2_hyp_var.v", line 8, characters 49-56: The command has indeed failed with message: In environment x : nat The term "x" has type "nat" while it is expected to have type "bool". - : constr = constr:(fun x : nat => x : nat) - : constr = constr:(fun x0 : bool => eq_refl : (x0, x) = (x0, x)) - : constr = constr:(x : nat) File "./output/ltac2_hyp_var.v", line 18, characters 36-43: The command has indeed failed with message: In environment x : nat The term "x" has type "nat" while it is expected to have type "bool". - : constr = constr:(fun (_ : nat) (_0 : bool) => eq_refl : _0 = _0) - : constr = constr:(fun (_0 : nat) (_ : bool) => eq_refl : _0 = _0) rocq-9.2.0/test-suite/output/ltac2_hyp_var.v000066400000000000000000000013271516144147600210740ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Fail Check $hyp:id. Ltac2 Eval let id := @x in '(fun (x:nat) (x : bool) => eq_refl : (x, &x) = (x, $hyp:id)). Fail Ltac2 Eval let id := @x in '$hyp:id. Fail Ltac2 Eval let id := @x in '(fun x : nat => $hyp:id : bool). Ltac2 Eval let id := @x in constr:(fun x => $hyp:id : nat). Section S. Variable x : nat. Ltac2 Eval let id := @x in '(fun x : bool => eq_refl : (x, &x) = (x, $hyp:id)). Ltac2 Eval let id := @x in '($hyp:id : nat). Fail Ltac2 Eval let id := @x in '($hyp:id : bool). End S. Set Mangle Names. Ltac2 Eval let id := @x in '(fun (x:nat) (x:bool) => eq_refl : &x = $hyp:id :> bool). Ltac2 Eval let id := @_1 in '(fun (x:nat) (x:bool) => eq_refl : &_1 = $hyp:id :> nat). rocq-9.2.0/test-suite/output/ltac2_match.out000066400000000000000000000006401516144147600210570ustar00rootroot00000000000000File "./output/ltac2_match.v", line 12, characters 41-42: Warning: This pattern is redundant. [redundant-pattern,ltac2,default] File "./output/ltac2_match.v", line 34, characters 5-51: Warning: This clause is redundant. [redundant-pattern,ltac2,default] File "./output/ltac2_match.v", line 36, characters 5-51: Warning: This clause is redundant. [redundant-pattern,ltac2,default] - : string = "10" - : string = "12" rocq-9.2.0/test-suite/output/ltac2_match.v000066400000000000000000000026201516144147600205150ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Ltac2 Type rec autre := [ C | D | E (autre) | F (autre, autre) | H (autre) | I | J | K (string) ]. Ltac2 rec autre x := match x with | C,_,_ => 1 | _,C,_ => 2 | D,D,_ => 3 | (D|(F _ _)|(H _)|K _),_,_ => 4 | (_, (D|I|E _|F _ _|H _|K _), _) => 8 | (J,J,((C|D) as x |E x|F _ x)) | (J,_,((C|J) as x)) => autre (x,x,x) | (J, J, (I|H _|K _)) => 9 | I,_,_ => 6 | E _,_,_ => 7 end. Ltac2 Type t_l := [A | B]. Ltac2 f x := match x with | _, _, _, _, _, _, _, _, _, _, _, _, _, B, _, _ => "0" | _, _, _, B, A, _, _, _, _, _, _, _, _, _, _, _ => "1" | _, _, _, B, _, A, _, _, A, _, _, _, _, _, _, _ => "2" | _, _, _, _, _, _, _, _, _, _, B, A, _, A, _, _ => "3" | _, _, _, _, _, _, _, B, _, _, _, _, B, _, A, A => "4" | A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ => "5" | _, _, _, _, _, _, _, B, _, B, _, _, _, _, _, _ => "6" | _, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _ => "7" | _, A, A, _, A, _, B, _, _, _, _, _, _, _, _, B => "8" | _, _, _, _, B, _, _, _, _, _, _, _, _, _, B, _ => "9" | _, _, _, _, _, _, _, _, _, _, _, B, _, _, _, _ => "10" | _, _, _, _, _, A, _, _, _, _, B, _, _, _, _, _ => "11" | B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ => "12" | _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ => "13" end. Ltac2 Eval f (B, A, A, A, A, A, A, A, A, A, A, B, A, A, A, A). Ltac2 Eval f (B, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A). rocq-9.2.0/test-suite/output/ltac2_notations_eval_in.out000066400000000000000000000012211516144147600234720ustar00rootroot00000000000000- : constr = constr:((fix add (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (add p m) end) (1 + 2) 3) - : constr = constr:(S (0 + 2 + 3)) - : constr = constr:(6) - : constr = constr:(1 + 2 + 3) - : constr = constr:(6) - : constr = constr:(1 + 2 + 3) - : constr = constr:(1 + 2 + 3) - : constr = constr:(6) - : constr = constr:(1 + 2 + 3) - : constr = constr:(1 + 2 + 3) - : constr = constr:(6) - : constr = constr:(1 + 2 + 3) - : constr = constr:(1 + 2 + 3) - : constr list = [constr:(0 <> 0); constr:(0 = 0 -> False); constr:((fun P : Prop => P -> False) (0 = 0)); constr:(0 <> 0)] rocq-9.2.0/test-suite/output/ltac2_notations_eval_in.v000066400000000000000000000020741516144147600231370ustar00rootroot00000000000000From Ltac2 Require Import Ltac2. From Corelib Require Import BinNums PosDef IntDef. (** * Test eval ... in / reduction tactics *) (** The below test cases test if the notation syntax works - not the tactics as such *) Ltac2 Eval (eval red in (1+2+3)). Ltac2 Eval (eval hnf in (1+2+3)). Ltac2 Eval (eval simpl in (1+2+3)). Ltac2 Eval (eval simpl Z.add in (1+2+3)). Ltac2 Eval (eval cbv in (1+2+3)). Ltac2 Eval (eval cbv delta [Z.add] beta iota in (1+2+3)). Ltac2 Eval (eval cbv delta [Z.add Pos.add] beta iota in (1+2+3)). Ltac2 Eval (eval cbn in (1+2+3)). Ltac2 Eval (eval cbn delta [Z.add] beta iota in (1+2+3)). Ltac2 Eval (eval cbn delta [Z.add Pos.add] beta iota in (1+2+3)). Ltac2 Eval (eval lazy in (1+2+3)). Ltac2 Eval (eval lazy delta [Z.add] beta iota in (1+2+3)). Ltac2 Eval (eval lazy delta [Z.add Pos.add] beta iota in (1+2+3)). (* The example for [fold] in the reference manual *) Ltac2 Eval ( let t1 := '(~0=0) in let t2 := eval unfold not in $t1 in let t3 := eval pattern (0=0) in $t2 in let t4 := eval fold not in $t3 in [t1; t2; t3; t4] ). rocq-9.2.0/test-suite/output/ltac2_pr_ctor.out000066400000000000000000000000751516144147600214350ustar00rootroot00000000000000- : pair = C 0 0 - : pair' = C' (0, 0) - : ppair = D (C 0 0) rocq-9.2.0/test-suite/output/ltac2_pr_ctor.v000066400000000000000000000005101516144147600210650ustar00rootroot00000000000000Require Import Ltac2.Ltac2. (* cf bug #18556 *) Ltac2 Type pair := [ C (int, int) ]. Ltac2 Eval C 0 0. (* prints "C (0, 0)", should be "C 0 0" *) Ltac2 Type pair' := [ C' (int * int) ]. Ltac2 Eval C' (0, 0). (* prints "C' ((0, 0))", sound but over-parenthesized *) Ltac2 Type ppair := [ D (pair) ]. Ltac2 Eval D (C 0 0). rocq-9.2.0/test-suite/output/ltac2_print_exn.out000066400000000000000000000012501516144147600217670ustar00rootroot00000000000000File "./output/ltac2_print_exn.v", line 11, characters 0-23: The command has indeed failed with message: hello Backtrace: Call foo Prim File "./output/ltac2_print_exn.v", line 24, characters 0-23: The command has indeed failed with message: Uncaught Ltac2 exception: WithTerm constr:(?X1) File "./output/ltac2_print_exn.v", line 33, characters 0-23: The command has indeed failed with message: test ?X1 File "./output/ltac2_print_exn.v", line 38, characters 0-23: The command has indeed failed with message: Uncaught Ltac2 exception: Tactic_failure (Some message:(hello)) Custom Ltac2 printer failed: Uncaught Ltac2 exception: Assertion_failure rocq-9.2.0/test-suite/output/ltac2_print_exn.v000066400000000000000000000016561516144147600214370ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Import Printf. (** basic test, we also check that the backtrace isn't forgotten when using the custom printer *) Set Ltac2 Backtrace. Ltac2 foo () := Control.zero (Tactic_failure (Some (Message.of_string "hello"))). Fail Ltac2 Eval foo (). Unset Ltac2 Backtrace. (** Test printing constr even though we have a bad evar map *) Ltac2 Type exn ::= [ WithTerm (constr) ]. Ltac2 bar () := let c := open_constr:(_ :> nat) in Control.zero (WithTerm c). (* default printer doesn't have the evar map but doesn't fail *) Fail Ltac2 Eval bar (). Ltac2 Set Control.print_exn := fun e => match e with | WithTerm c => Some (fprintf "test %t" c) | _ => None end. (* custom printer also doesn't have the evar map but doesn't fail *) Fail Ltac2 Eval bar (). (** Test custom printer producing an error *) Ltac2 Set Control.print_exn := fun _ => Control.throw Assertion_failure. Fail Ltac2 Eval foo (). rocq-9.2.0/test-suite/output/ltac2_printabout.out000066400000000000000000000016541516144147600221600ustar00rootroot00000000000000fst : 'a * 'b -> 'a snd : 'b * 'a -> 'a type : constr -> constr Ltac2 type : constr -> constr type := @external "rocq-runtime.plugins.ltac2" "constr_type" Ltac2 ltac2_printabout.type Ltac2 type : constr -> constr None : 'a option Some : 'a -> 'a option Ltac2 constructor Err : exn -> 'a result Inl : 'a -> ('a, 'b) either Inr : 'b -> ('a, 'b) either Triple : 'c -> 'b -> 'a -> ('a, 'b, 'c) triple Not_found : exn Out_of_bounds : message option -> exn Ltac2 Notation nota := () () Ltac2 Type constr Ltac2 Type constr := Init.constr ('a, 'b) thing := 'b option Ltac2 Type empty := [ ] 'a option := [ None | Some ('a) ] bool := [ true | false ] Ltac2 Type ('a, 'b, 'c) triple := [ Triple ('c, 'b, 'a) ] Ltac2 Type 'a ref := { mutable contents : 'a; } Ltac2 Type ('a, 'b, 'c) trirecord := { cproj : 'c; mutable bproj : 'b; aproj : 'a; } Ltac2 Type extensible := [ .. ] Ltac2 Type extensible := [ .. | OtherThing (bool) | Thing (string) ] rocq-9.2.0/test-suite/output/ltac2_printabout.v000066400000000000000000000020371516144147600216120ustar00rootroot00000000000000Require Import Ltac2.Init. Ltac2 @ external type : constr -> constr := "rocq-runtime.plugins.ltac2" "constr_type". Print Ltac2 Signatures. Print type. Locate type. About type. (* constructors *) Print Ltac2 None. Print Ltac2 Some. Print Err. Ltac2 Type ('a,'b) either := [ Inl ('a) | Inr ('b) ]. Print Ltac2 Inl. Print Ltac2 Inr. Ltac2 Type ('a,'b,'c) triple := [ Triple ('c, 'b, 'a) ]. Print Ltac2 Triple. Print Ltac2 Not_found. Print Ltac2 Out_of_bounds. (* alias *) Ltac2 Abbreviation nota := () (). Print nota. (* types *) Print constr. Ltac2 Type constr := constr. Print constr. Ltac2 Type ('a,'b) thing := 'b option. Print Ltac2 Type thing. Ltac2 Type empty := []. Print empty. Print Ltac2 Type option. Print Ltac2 Type bool. Print triple. Print ref. Ltac2 Type ('a,'b,'c) trirecord := { cproj : 'c; mutable bproj : 'b; aproj : 'a }. Print trirecord. Ltac2 Type extensible := [ .. ]. Print extensible. Ltac2 Type extensible ::= [ Thing (string) ]. Ltac2 Type extensible ::= [ OtherThing (bool) ]. Print extensible. rocq-9.2.0/test-suite/output/ltac2_printf.out000066400000000000000000000045511516144147600212720ustar00rootroot00000000000000File "./output/ltac2_printf.v", line 5, characters 6-29: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] 42 - : unit = () abc - : unit = () Foo - : unit = () (1 + 1 = 0) - : unit = () % - : unit = () dummy - : unit = () dummy - : unit = () hello world! - : unit = () ok foodummy bar yes - : unit = () ok foodummy bar yes - : unit = () ok foodummy bar yes - : unit = () ok foodummy bar yes - : unit = () File "./output/ltac2_printf.v", line 31, characters 28-33: The command has indeed failed with message: This expression has type string but an expression was expected of type int File "./output/ltac2_printf.v", line 32, characters 28-29: The command has indeed failed with message: This expression has type int but an expression was expected of type string File "./output/ltac2_printf.v", line 33, characters 28-33: The command has indeed failed with message: This expression has type string but an expression was expected of type ident File "./output/ltac2_printf.v", line 34, characters 28-33: The command has indeed failed with message: This expression has type string but an expression was expected of type constr File "./output/ltac2_printf.v", line 35, characters 40-42: The command has indeed failed with message: This expression has type unit but an expression was expected of type message File "./output/ltac2_printf.v", line 36, characters 38-40: The command has indeed failed with message: This expression has type unit but an expression was expected of type message File "./output/ltac2_printf.v", line 37, characters 58-63: The command has indeed failed with message: This expression has type string but an expression was expected of type int File "./output/ltac2_printf.v", line 38, characters 43-48: The command has indeed failed with message: This expression has type string but an expression was expected of type int File "./output/ltac2_printf.v", line 39, characters 28-29: The command has indeed failed with message: This expression has type int but an expression was expected of type message - : unit = () - : unit = () - : unit = () File "./output/ltac2_printf.v", line 60, characters 0-81: The command has indeed failed with message: Uncaught Ltac2 exception: Assertion_failure File "./output/ltac2_printf.v", line 61, characters 0-81: The command has indeed failed with message: Uncaught Ltac2 exception: Assertion_failure - : string = "" - : string = "" rocq-9.2.0/test-suite/output/ltac2_printf.v000066400000000000000000000043361516144147600207310ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Require Import Ltac2.Printf. (* Check that the arguments have type unit *) Ltac2 ignore (x : unit) := (). Ltac2 dummy0 (_ : int) := Message.of_string "dummy". Ltac2 dummy (_ : unit) (_ : int) := Message.of_string "dummy". (** Simple test for all specifications *) Ltac2 Eval ignore (printf "%i" 42). Ltac2 Eval ignore (printf "%s" "abc"). Ltac2 Eval ignore (printf "%I" @Foo). Ltac2 Eval ignore (printf "%t" '(1 + 1 = 0)). Ltac2 Eval ignore (printf "%%"). Ltac2 Eval ignore (printf "%a" dummy 18). Ltac2 Eval ignore (printf "%A" dummy0 18). Ltac2 Eval ignore (printf "%m!" (fprintf "%s %s" "hello" "world")). (** More complex tests *) Ltac2 Eval ignore (printf "%I foo%a bar %s" @ok dummy 18 "yes"). Ltac2 Eval ignore (printf "%I foo%A bar %s" @ok dummy0 18 "yes"). Ltac2 Eval Message.print (fprintf "%I foo%a bar %s" @ok dummy 18 "yes"). Ltac2 Eval Message.print (fprintf "%I foo%A bar %s" @ok dummy0 18 "yes"). (** Failure tests *) Fail Ltac2 Eval printf "%i" "foo". Fail Ltac2 Eval printf "%s" 0. Fail Ltac2 Eval printf "%I" "foo". Fail Ltac2 Eval printf "%t" "foo". Fail Ltac2 Eval printf "%a" (fun _ _ => ()). Fail Ltac2 Eval printf "%A" (fun _ => ()). Fail Ltac2 Eval printf "%a" (fun _ i => Message.of_int i) "foo". Fail Ltac2 Eval printf "%A" Message.of_int "foo". Fail Ltac2 Eval printf "%m" 0. Import Message. Ltac2 Eval Control.assert_true ( String.equal (Message.to_string Message.empty) (Message.to_string (Message.of_string "")) ). Ltac2 print_if b fmt := if b then Format.kfprintf Message.to_string fmt else Format.ikfprintf Message.to_string (Message.of_string "") fmt. Ltac2 Notation "print_if" b(tactic(0)) fmt(format) := print_if b fmt. Ltac2 Eval Control.assert_true (String.equal "hello friend" (print_if true "hello %s" "friend")). Ltac2 Eval Control.assert_true (String.equal "" (print_if false "hello %s" "friend")). Fail Ltac2 Eval print_if true "%a" (fun _ => Control.throw Assertion_failure) (). Fail Ltac2 Eval print_if true "%A" (fun _ => Control.throw Assertion_failure) (). (* ikfprintf doesn't run the closure *) Ltac2 Eval print_if false "%a" (fun _ => Control.throw Assertion_failure) (). Ltac2 Eval print_if false "%A" (fun _ => Control.throw Assertion_failure) (). rocq-9.2.0/test-suite/output/ltac2_typed_notations.out000066400000000000000000000007761516144147600232200ustar00rootroot00000000000000File "./output/ltac2_typed_notations.v", line 5, characters 9-10: The command has indeed failed with message: This expression has type bool but an expression was expected of type constr fun (b : bool) => (let c := b in let (m : '__Ξ± Pattern.constr_matching) := [(Pattern.MatchPattern, pat:(true), (fun _ => fun (_ : constr array) => true)); (Pattern.MatchPattern, pat:(false), (fun _ => fun (_ : constr array) => false))] with (t : constr) := c in Pattern.one_match0 t m :'__Ξ± : bool) rocq-9.2.0/test-suite/output/ltac2_typed_notations.v000066400000000000000000000004531516144147600226460ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Fail Ltac2 foo(b: bool): bool := let c := b in match! c with | true => true | false => false end. (* error used to be on the whole command *) Ltac2 Globalize fun (b: bool) => (let c := b in match! c with | true => true | false => false end : bool). rocq-9.2.0/test-suite/output/ltac2_unused_var.out000066400000000000000000000034301516144147600221360ustar00rootroot00000000000000File "./output/ltac2_unused_var.v", line 3, characters 6-18: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 5, characters 16-27: Warning: Unused variable: y. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 5, characters 6-27: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 10, characters 0-38: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 16, characters 17-23: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 18, characters 16-40: Warning: Unused variable: y. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 20, characters 16-56: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 22, characters 16-43: Warning: Unused variable: b. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 24, characters 15-32: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 26, characters 23-26: Warning: Unused variables: x y. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 28, characters 23-26: Warning: Unused variable: y. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 30, characters 18-55: Warning: Unused variable: y. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 42, characters 37-39: Warning: Unused variable: x. [ltac2-unused-variable,ltac2,default] File "./output/ltac2_unused_var.v", line 49, characters 6-20: Warning: Unused variable: a. [ltac2-unused-variable,ltac2,default] rocq-9.2.0/test-suite/output/ltac2_unused_var.v000066400000000000000000000025361516144147600216020ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Ltac2 foo1 x := (). Ltac2 foo2 x := fun y => (). (* we don't warn on _ prefixed variable *) Ltac2 foo3 _x := (). Ltac2 Notation "foo4" x(constr) := (). (* questionable behaviour: unused variable in untyped notation warns at notation use time *) Unset Ltac2 Typed Notations. Ltac2 Notation "foo5" x(constr) := (). Set Ltac2 Typed Notations. Ltac2 foo6 () := foo5 1. Ltac2 foo7 x := match x with y => () end. Ltac2 foo8 x := match x with Some x => 1 | None => 2 end. Ltac2 foo9 x := match x with (a,b) => a end. Ltac2 foo10 := let x := () in (). Ltac2 foo11 () := let (x,y) := (1,2) in (). Ltac2 foo12 () := let (x,y) := (1,2) in x. Ltac2 foo13 () := let rec x () := 1 with y () := 2 in x. Ltac2 foo14 () := let rec x () := y () with y () := 2 in x. (* missing warning for unused letrec (bug?) *) Ltac2 foo15 () := let rec x () := y () with y () := x () in (). Ltac2 mutable bar () := (). (* missing warning for unused "Set as" (bug?) *) Ltac2 Set bar as bar0 := fun () => (). Ltac2 foo16 () := ltac1:(ltac2:(x |- ())). (* no warning for y even though it's bound in the ltac2 context (ltac2 can't tell that the notation isn't eg "ltac2:(...) + y") *) Abbreviation foo17 x y := ltac2:(exact $preterm:x) (only parsing). (* the usage of the second "a" binder should not prevent warning for the first "a" *) Ltac2 foo18 a a := a. rocq-9.2.0/test-suite/output/ltac_extra_args.out000066400000000000000000000011521516144147600220370ustar00rootroot00000000000000File "./output/ltac_extra_args.v", line 6, characters 2-13: The command has indeed failed with message: Illegal tactic application: got 1 extra argument. File "./output/ltac_extra_args.v", line 7, characters 2-16: The command has indeed failed with message: Illegal tactic application: got 2 extra arguments. File "./output/ltac_extra_args.v", line 8, characters 2-16: The command has indeed failed with message: Illegal tactic application: got 1 extra argument. File "./output/ltac_extra_args.v", line 9, characters 2-20: The command has indeed failed with message: Illegal tactic application: got 2 extra arguments. rocq-9.2.0/test-suite/output/ltac_extra_args.v000066400000000000000000000002071516144147600214750ustar00rootroot00000000000000Ltac foo := idtac. Ltac bar H := idtac. Goal True. Proof. Fail foo H. Fail foo H H'. Fail bar H H'. Fail bar H H' H''. Abort. rocq-9.2.0/test-suite/output/ltac_missing_args.out000066400000000000000000000052651516144147600223760ustar00rootroot00000000000000File "./output/ltac_missing_args.v", line 11, characters 2-11: The command has indeed failed with message: The user-defined tactic "foo" was not fully applied: There is a missing argument for variable x, no arguments at all were provided. Ltac call to "foo" failed. File "./output/ltac_missing_args.v", line 12, characters 2-11: The command has indeed failed with message: The user-defined tactic "bar" was not fully applied: There is a missing argument for variable x, no arguments at all were provided. Ltac call to "bar" failed. File "./output/ltac_missing_args.v", line 13, characters 2-16: The command has indeed failed with message: The user-defined tactic "bar" was not fully applied: There is a missing argument for variable y and 1 more, 1 argument was provided. Ltac call to "bar" failed. File "./output/ltac_missing_args.v", line 14, characters 2-11: The command has indeed failed with message: The user-defined tactic "baz" was not fully applied: There is a missing argument for variable x, no arguments at all were provided. In nested Ltac calls to "baz" and "foo", last call failed. File "./output/ltac_missing_args.v", line 15, characters 2-11: The command has indeed failed with message: The user-defined tactic "qux" was not fully applied: There is a missing argument for variable x, no arguments at all were provided. In nested Ltac calls to "qux" and "bar", last call failed. File "./output/ltac_missing_args.v", line 16, characters 2-36: The command has indeed failed with message: The user-defined tactic "mydo" was not fully applied: There is a missing argument for variable _, no arguments at all were provided. In nested Ltac calls to "mydo" and "tac" (bound to fun _ _ => idtac), last call failed. File "./output/ltac_missing_args.v", line 17, characters 2-42: The command has indeed failed with message: An unnamed user-defined tactic was not fully applied: There is a missing argument for variable _, no arguments at all were provided. File "./output/ltac_missing_args.v", line 18, characters 2-24: The command has indeed failed with message: An unnamed user-defined tactic was not fully applied: There is a missing argument for variable _, no arguments at all were provided. File "./output/ltac_missing_args.v", line 19, characters 2-16: The command has indeed failed with message: The user-defined tactic "rec" was not fully applied: There is a missing argument for variable x, no arguments at all were provided. In nested Ltac calls to "rec" and "rec", last call failed. File "./output/ltac_missing_args.v", line 20, characters 2-40: The command has indeed failed with message: An unnamed user-defined tactic was not fully applied: There is a missing argument for variable x, 1 argument was provided. rocq-9.2.0/test-suite/output/ltac_missing_args.v000066400000000000000000000006251516144147600220270ustar00rootroot00000000000000Set Ltac Backtrace. Ltac foo x := idtac x. Ltac bar x := fun y _ => idtac x y. Ltac baz := foo. Ltac qux := bar. Ltac mydo tac := tac (). Ltac rec x := rec. Goal True. Fail foo. Fail bar. Fail bar True. Fail baz. Fail qux. Fail mydo ltac:(fun _ _ => idtac). Fail let tac := (fun _ => idtac) in tac. Fail (fun _ => idtac). Fail rec True. Fail let rec tac x := tac in tac True. Abort. rocq-9.2.0/test-suite/output/names.out000066400000000000000000000005031516144147600177770ustar00rootroot00000000000000File "./output/names.v", line 5, characters 37-40: The command has indeed failed with message: In environment y : nat The term "a y" has type "{y0 : nat | y = y0}" while it is expected to have type "{x : nat | x = y}". 1 focused goal (shelved: 1) H : ?n <= 3 -> 3 <= ?n -> ?n = 3 ============================ True rocq-9.2.0/test-suite/output/names.v000066400000000000000000000003531516144147600174400ustar00rootroot00000000000000(* Test no clash names occur *) (* see bug #2723 *) Parameter a : forall x, {y:nat|x=y}. Fail Definition b y : {x:nat|x=y} := a y. Goal (forall n m, n <= m -> m <= n -> n = m) -> True. intro H; epose proof (H _ 3) as H. Show. Abort. rocq-9.2.0/test-suite/output/nested_eliminators.out000066400000000000000000002242351516144147600225760ustar00rootroot00000000000000File "./output/nested_eliminators.v", line 30, characters 13-21: The command has indeed failed with message: The reference True_all was not found in the current environment. Inductive list_all@{Ξ± ; u u0} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : list A -> Type@{max(Set,u,u0)} := nil_all : list_all@{Ξ± ; u u0} A PA (nil A) | cons_all : forall a : A, PA a -> forall l : list A, list_all@{Ξ± ; u u0} A PA l -> list_all@{Ξ± ; u u0} A PA (cons A a l). (* Ξ± ; *u *u0 |= *) Arguments list_all A%_type_scope PA%_function_scope l Arguments nil_all A%_type_scope PA%_function_scope Arguments cons_all A%_type_scope PA%_function_scope a _ l _ list_all_forall@{Ξ± ; u u0} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall l : list A, list_all@{Ξ± ; u u0} A PA l (* Ξ± ; u u0 |= *) list_all_forall is universe polymorphic Arguments list_all_forall A%_type_scope (PA HPA)%_function_scope l list_all_forall is transparent Expands to: Constant nested_eliminators.Template.list_all_forall Declared in library nested_eliminators, line 33, characters 2-88 Inductive list_all_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}) : forall l : list A, list_all@{Ξ± ; u u0} A PA l -> Type@{max(Set,u,u0,u1)} := nil_all_all : list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA (nil A) (nil_all@{Ξ± ; u u0} A PA) | cons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (l : list A) (l0 : list_all@{Ξ± ; u u0} A PA l), list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA l l0 -> list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA (cons A a l) (cons_all@{Ξ± ; u u0} A PA a p l l0). (* Ξ± Ξ±0 ; *u *u0 *u1 |= *) Arguments list_all_all A%_type_scope (PA PPA)%_function_scope l l0 Arguments nil_all_all A%_type_scope (PA PPA)%_function_scope Arguments cons_all_all A%_type_scope (PA PPA)%_function_scope a p _ l l _ list_all_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}), (forall (a : A) (p : PA a), PPA a p) -> forall (l : list A) (l0 : list_all@{Ξ± ; u u0} A PA l), list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA l l0 (* Ξ± Ξ±0 ; u u0 u1 |= *) list_all_all_forall is universe polymorphic Arguments list_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope l l0 list_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.list_all_all_forall Declared in library nested_eliminators, line 33, characters 2-88 MRT_ind : forall P : MRT -> Prop, (forall l : list MRT, list_all@{Prop ; Set Set} MRT P l -> P (MRTnode l)) -> forall m : MRT, P m MRT_ind is not universe polymorphic Arguments MRT_ind (P MRTnode)%_function_scope m MRT_ind is transparent Expands to: Constant nested_eliminators.Template.MRT_ind Declared in library nested_eliminators, line 45, characters 2-55 RoseTree_ind : forall (A : Type@{RoseTree_ind.u0}) (P : RoseTree A -> Prop), (forall a : A, P (RTleaf A a)) -> (forall l : list (RoseTree A), list_all@{Prop ; RoseTree_ind.u1 Set} (RoseTree A) P l -> P (RTnode A l)) -> forall r : RoseTree A, P r RoseTree_ind is not universe polymorphic Arguments RoseTree_ind A%_type_scope (P RTleaf RTnode)%_function_scope r RoseTree_ind is transparent Expands to: Constant nested_eliminators.Template.RoseTree_ind Declared in library nested_eliminators, line 50, characters 2-113 Inductive RoseTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : RoseTree A -> Type@{max(Set,u,u0,u1)} := RTleaf_all : forall a : A, PA a -> RoseTree_all@{Ξ± ; u u0 u1 u2} A PA (RTleaf A a) | RTnode_all : forall l : list (RoseTree A), list_all@{Type ; u2 u1} (RoseTree A) (RoseTree_all@{Ξ± ; u u0 u1 u2} A PA) l -> RoseTree_all@{Ξ± ; u u0 u1 u2} A PA (RTnode A l). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments RoseTree_all A%_type_scope PA%_function_scope r Arguments RTleaf_all A%_type_scope PA%_function_scope a _ Arguments RTnode_all A%_type_scope PA%_function_scope l _ RoseTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall r : RoseTree A, RoseTree_all@{Ξ± ; u u0 u1 u2} A PA r (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) RoseTree_all_forall is universe polymorphic Arguments RoseTree_all_forall A%_type_scope (PA HPA)%_function_scope r RoseTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.RoseTree_all_forall Declared in library nested_eliminators, line 50, characters 2-113 Inductive RoseTreeMut_all@{Ξ± ; u} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) : RoseTreeMut A -> Type@{max(Set,RoseTreeMut.u0,u)} := node_mut_all : forall f : forest A, forest_all@{Ξ± ; u} A PA f -> RoseTreeMut_all@{Ξ± ; u} A PA (node_mut A f) with forest_all@{Ξ± ; u} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) : forest A -> Type@{max(Set,RoseTreeMut.u0,u)} := forest_nil_all : forest_all@{Ξ± ; u} A PA (forest_nil A) | forest_cons_all : forall a : A, PA a -> forall r : RoseTreeMut A, RoseTreeMut_all@{Ξ± ; u} A PA r -> forest_all@{Ξ± ; u} A PA (forest_cons A a r). (* Ξ± ; *u |= *) Arguments RoseTreeMut_all A%_type_scope PA%_function_scope r Arguments node_mut_all A%_type_scope PA%_function_scope f _ Arguments forest_all A%_type_scope PA%_function_scope f Arguments forest_nil_all A%_type_scope PA%_function_scope Arguments forest_cons_all A%_type_scope PA%_function_scope a _ r _ RoseTreeMut_all_forall@{Ξ± ; u} : forall (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}), (forall a : A, PA a) -> forall r : RoseTreeMut A, RoseTreeMut_all@{Ξ± ; u} A PA r (* Ξ± ; u |= *) RoseTreeMut_all_forall is universe polymorphic Arguments RoseTreeMut_all_forall A%_type_scope (PA HPA)%_function_scope r RoseTreeMut_all_forall is transparent Expands to: Constant nested_eliminators.Template.RoseTreeMut_all_forall Declared in library nested_eliminators, line 58, characters 2-164 Inductive RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}) : forall r : RoseTreeMut A, RoseTreeMut_all@{Ξ± ; u} A PA r -> Type@{max(Set,RoseTreeMut.u0,u,u0)} := node_mut_all_all : forall (f : forest A) (f0 : forest_all@{Ξ± ; u} A PA f), forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA f f0 -> RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (node_mut A f) (node_mut_all@{Ξ± ; u} A PA f f0) with forest_all_all@{Ξ± Ξ±0 ; u u0} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}) : forall f : forest A, forest_all@{Ξ± ; u} A PA f -> Type@{max(Set,RoseTreeMut.u0,u,u0)} := forest_nil_all_all : forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (forest_nil A) (forest_nil_all@{Ξ± ; u} A PA) | forest_cons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (r : RoseTreeMut A) (r0 : RoseTreeMut_all@{Ξ± ; u} A PA r), RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA r r0 -> forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (forest_cons A a r) (forest_cons_all@{Ξ± ; u} A PA a p r r0). (* Ξ± Ξ±0 ; *u *u0 |= *) Arguments RoseTreeMut_all_all A%_type_scope (PA PPA)%_function_scope r r0 Arguments node_mut_all_all A%_type_scope (PA PPA)%_function_scope f f _ Arguments forest_all_all A%_type_scope (PA PPA)%_function_scope f f0 Arguments forest_nil_all_all A%_type_scope (PA PPA)%_function_scope Arguments forest_cons_all_all A%_type_scope (PA PPA)%_function_scope a p _ r r _ RoseTreeMut_all_all_forall@{Ξ± Ξ±0 ; u u0} : forall (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}), (forall (a : A) (p : PA a), PPA a p) -> forall (r : RoseTreeMut A) (r0 : RoseTreeMut_all@{Ξ± ; u} A PA r), RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA r r0 (* Ξ± Ξ±0 ; u u0 |= *) RoseTreeMut_all_all_forall is universe polymorphic Arguments RoseTreeMut_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope r r0 RoseTreeMut_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.RoseTreeMut_all_all_forall Declared in library nested_eliminators, line 58, characters 2-164 Inductive RoseTreeMut_all@{Ξ± ; u} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) : RoseTreeMut A -> Type@{max(Set,RoseTreeMut.u0,u)} := node_mut_all : forall f : forest A, forest_all@{Ξ± ; u} A PA f -> RoseTreeMut_all@{Ξ± ; u} A PA (node_mut A f) with forest_all@{Ξ± ; u} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) : forest A -> Type@{max(Set,RoseTreeMut.u0,u)} := forest_nil_all : forest_all@{Ξ± ; u} A PA (forest_nil A) | forest_cons_all : forall a : A, PA a -> forall r : RoseTreeMut A, RoseTreeMut_all@{Ξ± ; u} A PA r -> forest_all@{Ξ± ; u} A PA (forest_cons A a r). (* Ξ± ; *u |= *) Arguments RoseTreeMut_all A%_type_scope PA%_function_scope r Arguments node_mut_all A%_type_scope PA%_function_scope f _ Arguments forest_all A%_type_scope PA%_function_scope f Arguments forest_nil_all A%_type_scope PA%_function_scope Arguments forest_cons_all A%_type_scope PA%_function_scope a _ r _ forest_all_forall@{Ξ± ; u} : forall (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}), (forall a : A, PA a) -> forall f : forest A, forest_all@{Ξ± ; u} A PA f (* Ξ± ; u |= *) forest_all_forall is universe polymorphic Arguments forest_all_forall A%_type_scope (PA HPA)%_function_scope f forest_all_forall is transparent Expands to: Constant nested_eliminators.Template.forest_all_forall Declared in library nested_eliminators, line 58, characters 2-164 Inductive RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}) : forall r : RoseTreeMut A, RoseTreeMut_all@{Ξ± ; u} A PA r -> Type@{max(Set,RoseTreeMut.u0,u,u0)} := node_mut_all_all : forall (f : forest A) (f0 : forest_all@{Ξ± ; u} A PA f), forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA f f0 -> RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (node_mut A f) (node_mut_all@{Ξ± ; u} A PA f f0) with forest_all_all@{Ξ± Ξ±0 ; u u0} (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}) : forall f : forest A, forest_all@{Ξ± ; u} A PA f -> Type@{max(Set,RoseTreeMut.u0,u,u0)} := forest_nil_all_all : forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (forest_nil A) (forest_nil_all@{Ξ± ; u} A PA) | forest_cons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (r : RoseTreeMut A) (r0 : RoseTreeMut_all@{Ξ± ; u} A PA r), RoseTreeMut_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA r r0 -> forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA (forest_cons A a r) (forest_cons_all@{Ξ± ; u} A PA a p r r0). (* Ξ± Ξ±0 ; *u *u0 |= *) Arguments RoseTreeMut_all_all A%_type_scope (PA PPA)%_function_scope r r0 Arguments node_mut_all_all A%_type_scope (PA PPA)%_function_scope f f _ Arguments forest_all_all A%_type_scope (PA PPA)%_function_scope f f0 Arguments forest_nil_all_all A%_type_scope (PA PPA)%_function_scope Arguments forest_cons_all_all A%_type_scope (PA PPA)%_function_scope a p _ r r _ forest_all_all_forall@{Ξ± Ξ±0 ; u u0} : forall (A : Type@{RoseTreeMut.u0}) (PA : A -> Type@{Ξ± ; u}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u0}), (forall (a : A) (p : PA a), PPA a p) -> forall (f : forest A) (f0 : forest_all@{Ξ± ; u} A PA f), forest_all_all@{Ξ± Ξ±0 ; u u0} A PA PPA f f0 (* Ξ± Ξ±0 ; u u0 |= *) forest_all_all_forall is universe polymorphic Arguments forest_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope f f0 forest_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.forest_all_all_forall Declared in library nested_eliminators, line 58, characters 2-164 RoseRoseTree_ind : forall (A : Type@{RoseRoseTree_ind.u0}) (P : RoseRoseTree A -> Prop), (forall a : A, P (Nleaf A a)) -> (forall p : list (list (RoseRoseTree A)), list_all@{Type ; RoseRoseTree_ind.u1 RoseRoseTree_ind.u1} (list (RoseRoseTree A)) (list_all@{Prop ; RoseRoseTree_ind.u1 Set} (RoseRoseTree A) P) p -> P (Nnode A p)) -> forall r : RoseRoseTree A, P r RoseRoseTree_ind is not universe polymorphic Arguments RoseRoseTree_ind A%_type_scope (P Nleaf Nnode)%_function_scope r RoseRoseTree_ind is transparent Expands to: Constant nested_eliminators.Template.RoseRoseTree_ind Declared in library nested_eliminators, line 74, characters 2-136 Inductive RoseRoseTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : RoseRoseTree A -> Type@{max(Set,u,u0,u1)} := Nleaf_all : forall a : A, PA a -> RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA (Nleaf A a) | Nnode_all : forall p : list (list (RoseRoseTree A)), list_all@{Type ; u2 u1} (list (RoseRoseTree A)) (list_all@{Type ; u2 u1} (RoseRoseTree A) (RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA)) p -> RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA (Nnode A p). (* Ξ± ; *u *u0 =u1 =u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments RoseRoseTree_all A%_type_scope PA%_function_scope r Arguments Nleaf_all A%_type_scope PA%_function_scope a _ Arguments Nnode_all A%_type_scope PA%_function_scope p _ RoseRoseTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall r : RoseRoseTree A, RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA r (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) RoseRoseTree_all_forall is universe polymorphic Arguments RoseRoseTree_all_forall A%_type_scope (PA HPA)%_function_scope r RoseRoseTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.RoseRoseTree_all_forall Declared in library nested_eliminators, line 74, characters 2-136 ArrowTree1_ind : forall (A : Type@{ArrowTree1_ind.u0}) (P : ArrowTree1 A -> Prop), (forall a : A, P (ATleaf1 A a)) -> (forall l : bool -> list (ArrowTree1 A), (forall H : bool, list_all@{Prop ; ArrowTree1_ind.u1 Set} (ArrowTree1 A) P (l H)) -> P (ATnode1 A l)) -> forall a : ArrowTree1 A, P a ArrowTree1_ind is not universe polymorphic Arguments ArrowTree1_ind A%_type_scope (P ATleaf1 ATnode1)%_function_scope a ArrowTree1_ind is transparent Expands to: Constant nested_eliminators.Template.ArrowTree1_ind Declared in library nested_eliminators, line 82, characters 2-133 Inductive ArrowTree1_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : ArrowTree1 A -> Type@{max(Set,u,u0,u1)} := ATleaf1_all : forall a : A, PA a -> ArrowTree1_all@{Ξ± ; u u0 u1 u2} A PA (ATleaf1 A a) | ATnode1_all : forall l : bool -> list (ArrowTree1 A), (forall H : bool, list_all@{Type ; u2 u1} (ArrowTree1 A) (ArrowTree1_all@{Ξ± ; u u0 u1 u2} A PA) (l H)) -> ArrowTree1_all@{Ξ± ; u u0 u1 u2} A PA (ATnode1 A l). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments ArrowTree1_all A%_type_scope PA%_function_scope a Arguments ATleaf1_all A%_type_scope PA%_function_scope a _ Arguments ATnode1_all A%_type_scope (PA l _)%_function_scope ArrowTree1_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall a : ArrowTree1 A, ArrowTree1_all@{Ξ± ; u u0 u1 u2} A PA a (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) ArrowTree1_all_forall is universe polymorphic Arguments ArrowTree1_all_forall A%_type_scope (PA HPA)%_function_scope a ArrowTree1_all_forall is transparent Expands to: Constant nested_eliminators.Template.ArrowTree1_all_forall Declared in library nested_eliminators, line 82, characters 2-133 ArrowTree2_ind : forall (A : Type@{ArrowTree2_ind.u0}) (P : ArrowTree2 A -> Prop), (forall a : A, P (ATleaf2 A a)) -> (forall l : list (nat -> ArrowTree2 A), list_all@{Prop ; ArrowTree2_ind.u1 Set} (nat -> ArrowTree2 A) (fun H : nat -> ArrowTree2 A => forall H0 : nat, P (H H0)) l -> P (ATnode2 A l)) -> forall a : ArrowTree2 A, P a ArrowTree2_ind is not universe polymorphic Arguments ArrowTree2_ind A%_type_scope (P ATleaf2 ATnode2)%_function_scope a ArrowTree2_ind is transparent Expands to: Constant nested_eliminators.Template.ArrowTree2_ind Declared in library nested_eliminators, line 90, characters 2-130 Inductive ArrowTree2_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : ArrowTree2 A -> Type@{max(Set,u,u0,u1)} := ATleaf2_all : forall a : A, PA a -> ArrowTree2_all@{Ξ± ; u u0 u1 u2} A PA (ATleaf2 A a) | ATnode2_all : forall l : list (nat -> ArrowTree2 A), list_all@{Type ; u2 u1} (nat -> ArrowTree2 A) (fun H : nat -> ArrowTree2 A => forall H0 : nat, ArrowTree2_all@{Ξ± ; u u0 u1 u2} A PA (H H0)) l -> ArrowTree2_all@{Ξ± ; u u0 u1 u2} A PA (ATnode2 A l). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments ArrowTree2_all A%_type_scope PA%_function_scope a Arguments ATleaf2_all A%_type_scope PA%_function_scope a _ Arguments ATnode2_all A%_type_scope PA%_function_scope l _ ArrowTree2_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall a : ArrowTree2 A, ArrowTree2_all@{Ξ± ; u u0 u1 u2} A PA a (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) ArrowTree2_all_forall is universe polymorphic Arguments ArrowTree2_all_forall A%_type_scope (PA HPA)%_function_scope a ArrowTree2_all_forall is transparent Expands to: Constant nested_eliminators.Template.ArrowTree2_all_forall Declared in library nested_eliminators, line 90, characters 2-130 ArrowTree3_ind : forall (A : Type@{ArrowTree3_ind.u0}) (P : ArrowTree3 A -> Prop), (forall a : A, P (ATleaf3 A a)) -> (forall l : bool -> list (nat -> ArrowTree3 A), (forall H : bool, list_all@{Prop ; ArrowTree3_ind.u1 Set} (nat -> ArrowTree3 A) (fun H0 : nat -> ArrowTree3 A => forall H1 : nat, P (H0 H1)) (l H)) -> P (ATnode3 A l)) -> forall a : ArrowTree3 A, P a ArrowTree3_ind is not universe polymorphic Arguments ArrowTree3_ind A%_type_scope (P ATleaf3 ATnode3)%_function_scope a ArrowTree3_ind is transparent Expands to: Constant nested_eliminators.Template.ArrowTree3_ind Declared in library nested_eliminators, line 98, characters 2-140 Inductive ArrowTree3_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : ArrowTree3 A -> Type@{max(Set,u,u0,u1)} := ATleaf3_all : forall a : A, PA a -> ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (ATleaf3 A a) | ATnode3_all : forall l : bool -> list (nat -> ArrowTree3 A), (forall H : bool, list_all@{Type ; u2 u1} (nat -> ArrowTree3 A) (fun H0 : nat -> ArrowTree3 A => forall H1 : nat, ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (H0 H1)) (l H)) -> ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (ATnode3 A l). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments ArrowTree3_all A%_type_scope PA%_function_scope a Arguments ATleaf3_all A%_type_scope PA%_function_scope a _ Arguments ATnode3_all A%_type_scope (PA l _)%_function_scope ArrowTree3_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall a : ArrowTree3 A, ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA a (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) ArrowTree3_all_forall is universe polymorphic Arguments ArrowTree3_all_forall A%_type_scope (PA HPA)%_function_scope a ArrowTree3_all_forall is transparent Expands to: Constant nested_eliminators.Template.ArrowTree3_all_forall Declared in library nested_eliminators, line 98, characters 2-140 Inductive prod_all@{Ξ± Ξ±0 ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (B : Type@{u0}) (PB : B -> Type@{Ξ±0 ; u2}) : prod A B -> Type@{max(u,u0,u1,u2)} := pair_all : forall a : A, PA a -> forall b : B, PB b -> prod_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA B PB (pair A B a b). (* Ξ± Ξ±0 ; *u *u0 *u1 *u2 |= *) Arguments prod_all A%_type_scope PA%_function_scope B%_type_scope PB%_function_scope p Arguments pair_all A%_type_scope PA%_function_scope B%_type_scope PB%_function_scope a _ b _ prod_all_forall@{Ξ± Ξ±0 ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}), (forall a : A, PA a) -> forall (B : Type@{u0}) (PB : B -> Type@{Ξ±0 ; u2}), (forall b : B, PB b) -> forall p : prod A B, prod_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA B PB p (* Ξ± Ξ±0 ; u u0 u1 u2 |= *) prod_all_forall is universe polymorphic Arguments prod_all_forall A%_type_scope (PA HPA)%_function_scope B%_type_scope (PB HPB)%_function_scope p prod_all_forall is transparent Expands to: Constant nested_eliminators.Template.prod_all_forall Declared in library nested_eliminators, line 108, characters 2-70 Inductive prod_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±1 ; u3}) (B : Type@{u0}) (PB : B -> Type@{Ξ±0 ; u2}) (PPB : forall b : B, PB b -> Type@{Ξ±2 ; u4}) : forall p : prod A B, prod_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA B PB p -> Type@{max(u,u0,u1,u2,u3,u4)} := pair_all_all : forall (a : A) (p : PA a), PPA a p -> forall (b : B) (p0 : PB b), PPB b p0 -> prod_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4} A PA PPA B PB PPB (pair A B a b) (pair_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA B PB a p b p0). (* Ξ± Ξ±0 Ξ±1 Ξ±2 ; *u *u0 *u1 *u2 *u3 *u4 |= *) Arguments prod_all_all A%_type_scope (PA PPA)%_function_scope B%_type_scope (PB PPB)%_function_scope p p0 Arguments pair_all_all A%_type_scope (PA PPA)%_function_scope B%_type_scope (PB PPB)%_function_scope a p _ b p _ prod_all_all_forall@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±1 ; u3}), (forall (a : A) (p : PA a), PPA a p) -> forall (B : Type@{u0}) (PB : B -> Type@{Ξ±0 ; u2}) (PPB : forall b : B, PB b -> Type@{Ξ±2 ; u4}), (forall (b : B) (p : PB b), PPB b p) -> forall (p : prod A B) (p0 : prod_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA B PB p), prod_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4} A PA PPA B PB PPB p p0 (* Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 |= *) prod_all_all_forall is universe polymorphic Arguments prod_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope B%_type_scope (PB PPB HPPB)%_function_scope p p0 prod_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.prod_all_all_forall Declared in library nested_eliminators, line 108, characters 2-70 PairTree_ind : forall (A : Type@{PairTree_ind.u0}) (P : PairTree A -> Prop), (forall a : A, P (Pleaf A a)) -> (forall p : prod (PairTree A) (PairTree A), prod_all@{Prop Prop ; PairTree_ind.u1 PairTree_ind.u1 Set Set} (PairTree A) P (PairTree A) P p -> P (Pnode A p)) -> forall p : PairTree A, P p PairTree_ind is not universe polymorphic Arguments PairTree_ind A%_type_scope (P Pleaf Pnode)%_function_scope p PairTree_ind is transparent Expands to: Constant nested_eliminators.Template.PairTree_ind Declared in library nested_eliminators, line 118, characters 2-124 Inductive PairTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : PairTree A -> Type@{max(Set,u,u0,u1)} := Pleaf_all : forall a : A, PA a -> PairTree_all@{Ξ± ; u u0 u1 u2} A PA (Pleaf A a) | Pnode_all : forall p : prod (PairTree A) (PairTree A), prod_all@{Type Type ; u2 u2 u1 u1} (PairTree A) (PairTree_all@{Ξ± ; u u0 u1 u2} A PA) (PairTree A) (PairTree_all@{Ξ± ; u u0 u1 u2} A PA) p -> PairTree_all@{Ξ± ; u u0 u1 u2} A PA (Pnode A p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments PairTree_all A%_type_scope PA%_function_scope p Arguments Pleaf_all A%_type_scope PA%_function_scope a _ Arguments Pnode_all A%_type_scope PA%_function_scope p _ PairTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall p : PairTree A, PairTree_all@{Ξ± ; u u0 u1 u2} A PA p (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) PairTree_all_forall is universe polymorphic Arguments PairTree_all_forall A%_type_scope (PA HPA)%_function_scope p PairTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.PairTree_all_forall Declared in library nested_eliminators, line 118, characters 2-124 LeftTree_ind : forall (A : Type@{LeftTree_ind.u0}) (P : LeftTree A -> Prop), (forall a : A, P (Lleaf A a)) -> (forall p : prod (LeftTree A) nat, prod_all@{Prop Type ; LeftTree_ind.u1 Set Set Set} (LeftTree A) P nat (fun _ : nat => unit) p -> P (Lnode A p)) -> forall l : LeftTree A, P l LeftTree_ind is not universe polymorphic Arguments LeftTree_ind A%_type_scope (P Lleaf Lnode)%_function_scope l LeftTree_ind is transparent Expands to: Constant nested_eliminators.Template.AutoGeneratedScheme.LeftTree_ind Declared in library nested_eliminators, line 128, characters 4-121 Inductive LeftTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : LeftTree A -> Type@{max(Set,u,u0,u1)} := Lleaf_all : forall a : A, PA a -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lleaf A a) | Lnode_all : forall p : prod (LeftTree A) nat, prod_all@{Type Type ; u2 Set u1 Set} (LeftTree A) (LeftTree_all@{Ξ± ; u u0 u1 u2} A PA) nat (fun _ : nat => unit) p -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lnode A p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments LeftTree_all A%_type_scope PA%_function_scope l Arguments Lleaf_all A%_type_scope PA%_function_scope a _ Arguments Lnode_all A%_type_scope PA%_function_scope p _ LeftTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall l : LeftTree A, LeftTree_all@{Ξ± ; u u0 u1 u2} A PA l (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) LeftTree_all_forall is universe polymorphic Arguments LeftTree_all_forall A%_type_scope (PA HPA)%_function_scope l LeftTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.AutoGeneratedScheme.LeftTree_all_forall Declared in library nested_eliminators, line 128, characters 4-121 LeftTree_ind : forall (A : Type@{LeftTree_ind.u0}) (P : LeftTree A -> Prop), (forall a : A, P (Lleaf A a)) -> (forall p : prod (LeftTree A) nat, prod_all@{Type Type ; LeftTree_ind.u1 Set Set Set} (LeftTree A) P nat (fun _ : nat => unit) p -> P (Lnode A p)) -> forall l : LeftTree A, P l LeftTree_ind is not universe polymorphic Arguments LeftTree_ind A%_type_scope (P Lleaf Lnode)%_function_scope l LeftTree_ind is transparent Expands to: Constant nested_eliminators.Template.Scheme.LeftTree_ind Declared in library nested_eliminators, line 146, characters 4-44 Inductive LeftTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : LeftTree A -> Type@{max(Set,u,u0,u1)} := Lleaf_all : forall a : A, PA a -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lleaf A a) | Lnode_all : forall p : prod (LeftTree A) nat, prod_all@{Type Type ; u2 Set u1 Set} (LeftTree A) (LeftTree_all@{Ξ± ; u u0 u1 u2} A PA) nat (fun _ : nat => unit) p -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lnode A p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments LeftTree_all A%_type_scope PA%_function_scope l Arguments Lleaf_all A%_type_scope PA%_function_scope a _ Arguments Lnode_all A%_type_scope PA%_function_scope p _ LeftTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall l : LeftTree A, LeftTree_all@{Ξ± ; u u0 u1 u2} A PA l (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) LeftTree_all_forall is universe polymorphic Arguments LeftTree_all_forall A%_type_scope (PA HPA)%_function_scope l LeftTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.Scheme.LeftTree_all_forall Declared in library nested_eliminators, line 142, characters 4-121 Inductive prod_all_10@{Ξ± ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (B : Type@{u0}) : prod A B -> Type@{max(u,u0,u1)} := pair_all_10 : forall a : A, PA a -> forall b : B, prod_all_10@{Ξ± ; u u0 u1} A PA B (pair a b). (* Ξ± ; *u *u0 *u1 |= *) Arguments prod_all_10 A%_type_scope PA%_function_scope B%_type_scope p Arguments pair_all_10 A%_type_scope PA%_function_scope B%_type_scope a _ b prod_all_forall_10@{Ξ± ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}), (forall a : A, PA a) -> forall (B : Type@{u0}) (p : prod A B), prod_all_10@{Ξ± ; u u0 u1} A PA B p (* Ξ± ; u u0 u1 |= *) prod_all_forall_10 is universe polymorphic Arguments prod_all_forall_10 A%_type_scope (PA HPA)%_function_scope B%_type_scope p prod_all_forall_10 is transparent Expands to: Constant nested_eliminators.Template.PartialAll.prod_all_forall_10 Declared in library nested_eliminators, line 156, characters 4-31 Inductive prod_all_10_all@{Ξ± Ξ±0 ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u2}) (B : Type@{u0}) : forall p : prod A B, prod_all_10@{Ξ± ; u u0 u1} A PA B p -> Type@{max(u,u0,u1,u2)} := pair_all_10_all : forall (a : A) (p : PA a), PPA a p -> forall b : B, prod_all_10_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA PPA B (pair a b) (pair_all_10@{Ξ± ; u u0 u1} A PA B a p b). (* Ξ± Ξ±0 ; *u *u0 *u1 *u2 |= *) Arguments prod_all_10_all A%_type_scope (PA PPA)%_function_scope B%_type_scope p p0 Arguments pair_all_10_all A%_type_scope (PA PPA)%_function_scope B%_type_scope a p _ b prod_all_10_all_forall@{Ξ± Ξ±0 ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u2}), (forall (a : A) (p : PA a), PPA a p) -> forall (B : Type@{u0}) (p : prod A B) (p0 : prod_all_10@{Ξ± ; u u0 u1} A PA B p), prod_all_10_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA PPA B p p0 (* Ξ± Ξ±0 ; u u0 u1 u2 |= *) prod_all_10_all_forall is universe polymorphic Arguments prod_all_10_all_forall A%_type_scope (PA PPA HPPA)%_function_scope B%_type_scope p p0 prod_all_10_all_forall is transparent Expands to: Constant nested_eliminators.Template.PartialAll.prod_all_10_all_forall Declared in library nested_eliminators, line 156, characters 4-31 LeftTree_ind : forall (A : Type@{LeftTree_ind.u0}) (P : LeftTree A -> Prop), (forall a : A, P (Lleaf A a)) -> (forall p : prod (LeftTree A) nat, prod_all_10@{Prop ; LeftTree_ind.u1 Set Set} (LeftTree A) P nat p -> P (Lnode A p)) -> forall l : LeftTree A, P l LeftTree_ind is not universe polymorphic Arguments LeftTree_ind A%_type_scope (P Lleaf Lnode)%_function_scope l LeftTree_ind is transparent Expands to: Constant nested_eliminators.Template.PartialAll.LeftTree_ind Declared in library nested_eliminators, line 162, characters 4-121 Inductive LeftTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : LeftTree A -> Type@{max(Set,u,u0,u1)} := Lleaf_all : forall a : A, PA a -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lleaf A a) | Lnode_all : forall p : prod (LeftTree A) nat, prod_all_10@{Type ; u2 Set u1} (LeftTree A) (LeftTree_all@{Ξ± ; u u0 u1 u2} A PA) nat p -> LeftTree_all@{Ξ± ; u u0 u1 u2} A PA (Lnode A p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments LeftTree_all A%_type_scope PA%_function_scope l Arguments Lleaf_all A%_type_scope PA%_function_scope a _ Arguments Lnode_all A%_type_scope PA%_function_scope p _ LeftTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall l : LeftTree A, LeftTree_all@{Ξ± ; u u0 u1 u2} A PA l (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) LeftTree_all_forall is universe polymorphic Arguments LeftTree_all_forall A%_type_scope (PA HPA)%_function_scope l LeftTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.PartialAll.LeftTree_all_forall Declared in library nested_eliminators, line 162, characters 4-121 RightTree_ind : forall (A : Type@{RightTree_ind.u0}) (P : RightTree A -> Prop), (forall a : A, P (Rleaf A a)) -> (forall p : prod nat (RightTree A), prod_all@{Type Prop ; Set RightTree_ind.u1 Set Set} nat (fun _ : nat => unit) (RightTree A) P p -> P (Rnode A p)) -> forall r : RightTree A, P r RightTree_ind is not universe polymorphic Arguments RightTree_ind A%_type_scope (P Rleaf Rnode)%_function_scope r RightTree_ind is transparent Expands to: Constant nested_eliminators.Template.RightTree_ind Declared in library nested_eliminators, line 172, characters 2-119 Inductive RightTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : RightTree A -> Type@{max(Set,u,u0,u1)} := Rleaf_all : forall a : A, PA a -> RightTree_all@{Ξ± ; u u0 u1 u2} A PA (Rleaf A a) | Rnode_all : forall p : prod nat (RightTree A), prod_all@{Type Type ; Set u2 Set u1} nat (fun _ : nat => unit) (RightTree A) (RightTree_all@{Ξ± ; u u0 u1 u2} A PA) p -> RightTree_all@{Ξ± ; u u0 u1 u2} A PA (Rnode A p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments RightTree_all A%_type_scope PA%_function_scope r Arguments Rleaf_all A%_type_scope PA%_function_scope a _ Arguments Rnode_all A%_type_scope PA%_function_scope p _ RightTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall r : RightTree A, RightTree_all@{Ξ± ; u u0 u1 u2} A PA r (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) RightTree_all_forall is universe polymorphic Arguments RightTree_all_forall A%_type_scope (PA HPA)%_function_scope r RightTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.RightTree_all_forall Declared in library nested_eliminators, line 172, characters 2-119 Inductive vec_all@{Ξ± ; u u0} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : forall n : nat, vec A n -> Type@{max(Set,u,u0)} := vnil_all : vec_all@{Ξ± ; u u0} A PA zero (vnil A) | vcons_all : forall a : A, PA a -> forall (n : nat) (v : vec A n), vec_all@{Ξ± ; u u0} A PA n v -> vec_all@{Ξ± ; u u0} A PA (S n) (vcons A a n v). (* Ξ± ; *u *u0 |= *) Arguments vec_all A%_type_scope PA%_function_scope n v Arguments vnil_all A%_type_scope PA%_function_scope Arguments vcons_all A%_type_scope PA%_function_scope a _ n v _ vec_all_forall@{Ξ± ; u u0} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall (n : nat) (v : vec A n), vec_all@{Ξ± ; u u0} A PA n v (* Ξ± ; u u0 |= *) vec_all_forall is universe polymorphic Arguments vec_all_forall A%_type_scope (PA HPA)%_function_scope n v vec_all_forall is transparent Expands to: Constant nested_eliminators.Template.vec_all_forall Declared in library nested_eliminators, line 182, characters 2-107 Inductive vec_all_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}) : forall (n : nat) (v : vec A n), vec_all@{Ξ± ; u u0} A PA n v -> Type@{max(Set,u,u0,u1)} := vnil_all_all : vec_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA zero (vnil A) (vnil_all@{Ξ± ; u u0} A PA) | vcons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (n : nat) (v : vec A n) (v0 : vec_all@{Ξ± ; u u0} A PA n v), vec_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA n v v0 -> vec_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA (S n) (vcons A a n v) (vcons_all@{Ξ± ; u u0} A PA a p n v v0). (* Ξ± Ξ±0 ; *u *u0 *u1 |= *) Arguments vec_all_all A%_type_scope (PA PPA)%_function_scope n v v0 Arguments vnil_all_all A%_type_scope (PA PPA)%_function_scope Arguments vcons_all_all A%_type_scope (PA PPA)%_function_scope a p _ n v v _ vec_all_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}), (forall (a : A) (p : PA a), PPA a p) -> forall (n : nat) (v : vec A n) (v0 : vec_all@{Ξ± ; u u0} A PA n v), vec_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA n v v0 (* Ξ± Ξ±0 ; u u0 u1 |= *) vec_all_all_forall is universe polymorphic Arguments vec_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope n v v0 vec_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.vec_all_all_forall Declared in library nested_eliminators, line 182, characters 2-107 VecTree_ind : forall (A : Type@{VecTree_ind.u0}) (P : VecTree A -> Prop), (forall a : A, P (VNleaf A a)) -> (forall (n : nat) (p : vec (VecTree A) n), vec_all@{Prop ; VecTree_ind.u1 Set} (VecTree A) P n p -> P (VNnode A n p)) -> forall v : VecTree A, P v VecTree_ind is not universe polymorphic Arguments VecTree_ind A%_type_scope (P VNleaf VNnode)%_function_scope v VecTree_ind is transparent Expands to: Constant nested_eliminators.Template.VecTree_ind Declared in library nested_eliminators, line 191, characters 2-112 Inductive VecTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : VecTree A -> Type@{max(Set,u,u0,u1)} := VNleaf_all : forall a : A, PA a -> VecTree_all@{Ξ± ; u u0 u1 u2} A PA (VNleaf A a) | VNnode_all : forall (n : nat) (p : vec (VecTree A) n), vec_all@{Type ; u2 u1} (VecTree A) (VecTree_all@{Ξ± ; u u0 u1 u2} A PA) n p -> VecTree_all@{Ξ± ; u u0 u1 u2} A PA (VNnode A n p). (* Ξ± ; *u *u0 *u1 *u2 |= Set <= u1 Set <= u2 u <= u1 u <= u2 u0 <= u1 u2 <= u1 *) Arguments VecTree_all A%_type_scope PA%_function_scope v Arguments VNleaf_all A%_type_scope PA%_function_scope a _ Arguments VNnode_all A%_type_scope PA%_function_scope n p _ VecTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall v : VecTree A, VecTree_all@{Ξ± ; u u0 u1 u2} A PA v (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u2 u0 <= u1 u2 <= u1 *) VecTree_all_forall is universe polymorphic Arguments VecTree_all_forall A%_type_scope (PA HPA)%_function_scope v VecTree_all_forall is transparent Expands to: Constant nested_eliminators.Template.VecTree_all_forall Declared in library nested_eliminators, line 191, characters 2-112 Inductive All2i_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (B : Type@{u0}) (R : nat -> A -> B -> Type@{u1}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ± ; u2}) (n : nat) : forall (l : list A) (l0 : list B), All2i A B R n l l0 -> Type@{max(Set,u,u0,u1,u2)} := All2i_nil_all : All2i_all@{Ξ± ; u u0 u1 u2} A B R PR n nil nil (All2i_nil A B R n) | All2i_cons_all : forall (a : A) (b : B) (lA : list A) (lB : list B) (r : R n a b), PR n a b r -> forall a0 : All2i A B R (S n) lA lB, All2i_all@{Ξ± ; u u0 u1 u2} A B R PR (S n) lA lB a0 -> All2i_all@{Ξ± ; u u0 u1 u2} A B R PR n (cons a lA) (cons b lB) (All2i_cons A B R n a b lA lB r a0). (* Ξ± ; *u *u0 *u1 *u2 |= *) Arguments All2i_all (A B)%_type_scope (R PR)%_function_scope n l l a Arguments All2i_nil_all (A B)%_type_scope (R PR)%_function_scope n Arguments All2i_cons_all (A B)%_type_scope (R PR)%_function_scope n a b lA lB r _ a _ All2i_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (B : Type@{u0}) (R : nat -> A -> B -> Type@{u1}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ± ; u2}), (forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r) -> forall (n : nat) (l : list A) (l0 : list B) (a : All2i A B R n l l0), All2i_all@{Ξ± ; u u0 u1 u2} A B R PR n l l0 a (* Ξ± ; u u0 u1 u2 |= *) All2i_all_forall is universe polymorphic Arguments All2i_all_forall (A B)%_type_scope (R PR HPR)%_function_scope n l l a All2i_all_forall is transparent Expands to: Constant nested_eliminators.Template.All2i_all_forall Declared in library nested_eliminators, line 202, characters 2-304 Inductive All2i_all_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3} (A : Type@{u}) (B : Type@{u0}) (R : nat -> A -> B -> Type@{u1}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ± ; u2}) (PPR : forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r -> Type@{Ξ±0 ; u3}) (n : nat) : forall (l : list A) (l0 : list B) (a : All2i A B R n l l0), All2i_all@{Ξ± ; u u0 u1 u2} A B R PR n l l0 a -> Type@{max(Set,u,u0,u1,u2,u3)} := All2i_nil_all_all : All2i_all_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3} A B R PR PPR n nil nil (All2i_nil A B R n) (All2i_nil_all@{Ξ± ; u u0 u1 u2} A B R PR n) | All2i_cons_all_all : forall (a : A) (b : B) (lA : list A) (lB : list B) (r : R n a b) (p : PR n a b r), PPR n a b r p -> forall (a0 : All2i A B R (S n) lA lB) (a1 : All2i_all@{Ξ± ; u u0 u1 u2} A B R PR (S n) lA lB a0), All2i_all_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3} A B R PR PPR (S n) lA lB a0 a1 -> All2i_all_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3} A B R PR PPR n (cons a lA) (cons b lB) (All2i_cons A B R n a b lA lB r a0) (All2i_cons_all@{Ξ± ; u u0 u1 u2} A B R PR n a b lA lB r p a0 a1). (* Ξ± Ξ±0 ; *u *u0 *u1 *u2 *u3 |= *) Arguments All2i_all_all (A B)%_type_scope (R PR PPR)%_function_scope n l l a a0 Arguments All2i_nil_all_all (A B)%_type_scope (R PR PPR)%_function_scope n Arguments All2i_cons_all_all (A B)%_type_scope (R PR PPR)%_function_scope n a b lA lB r p _ a a _ All2i_all_all_forall@{Ξ± Ξ±0 ; u u0 u1 u2 u3} : forall (A : Type@{u}) (B : Type@{u0}) (R : nat -> A -> B -> Type@{u1}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ± ; u2}) (PPR : forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r -> Type@{Ξ±0 ; u3}), (forall (n : nat) (a : A) (b : B) (r : R n a b) (p : PR n a b r), PPR n a b r p) -> forall (n : nat) (l : list A) (l0 : list B) (a : All2i A B R n l l0) (a0 : All2i_all@{Ξ± ; u u0 u1 u2} A B R PR n l l0 a), All2i_all_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3} A B R PR PPR n l l0 a a0 (* Ξ± Ξ±0 ; u u0 u1 u2 u3 |= *) All2i_all_all_forall is universe polymorphic Arguments All2i_all_all_forall (A B)%_type_scope (R PR PPR HPPR)%_function_scope n l l a a0 All2i_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.All2i_all_all_forall Declared in library nested_eliminators, line 202, characters 2-304 File "./output/nested_eliminators.v", line 212, characters 2-35: The command has indeed failed with message: The variable A is not included in the uniform parameters that are strictly positive and can be nested on. Allowed parameters are R. typing_ind : forall (A : Type@{typing_ind.u0}) (B : Type@{typing_ind.u1}) (P : forall (n : nat) (a : A) (b : B), typing A B n a b -> Prop), (forall (n : nat) (a : A) (b : B), P n a b (typ_nil A B n a b)) -> (forall (n : nat) (a : A) (b : B) (lA : list A) (lB : list B) (a0 : All2i A B (fun n0 : nat => typing A B n0) n lA lB), All2i_all@{Prop ; typing_ind.u0 typing_ind.u1 typing_ind.u2 Set} A B (fun (n0 : nat) (H : A) (H0 : B) => typing A B n0 H H0) P n lA lB a0 -> P n a b (typ_cons A B n a b lA lB a0)) -> forall (n : nat) (a : A) (b : B) (t : typing A B n a b), P n a b t typing_ind is not universe polymorphic Arguments typing_ind (A B)%_type_scope (P typ_nil typ_cons)%_function_scope n a b t typing_ind is transparent Expands to: Constant nested_eliminators.Template.typing_ind Declared in library nested_eliminators, line 214, characters 2-218 Inductive All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} (A : Type@{u}) (B : Type@{u0}) (C : Type@{u1}) (PC : C -> Type@{Ξ± ; u3}) (R : nat -> A -> B -> Type@{u2}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ±0 ; u4}) (n : nat) : forall (l : list A) (l0 : list B), All2i_bis A B C R n l l0 -> Type@{max(Set,u,u0,u1,u2,u3,u4)} := All2i_bis_nil_all : forall c : C, PC c -> All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n nil nil (All2i_bis_nil A B C R n c) | All2i_bis_cons_all : forall (a : A) (b : B) (lA : list A) (lB : list B) (r : R n a b), PR n a b r -> forall a0 : All2i_bis A B C R (S n) lA lB, All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR (S n) lA lB a0 -> All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n (cons a lA) (cons b lB) (All2i_bis_cons A B C R n a b lA lB r a0). (* Ξ± Ξ±0 ; *u *u0 *u1 *u2 *u3 *u4 |= *) Arguments All2i_bis_all (A B C)%_type_scope (PC R PR)%_function_scope n l l a Arguments All2i_bis_nil_all (A B C)%_type_scope (PC R PR)%_function_scope n c _ Arguments All2i_bis_cons_all (A B C)%_type_scope (PC R PR)%_function_scope n a b lA lB r _ a _ All2i_bis_all_forall@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} : forall (A : Type@{u}) (B : Type@{u0}) (C : Type@{u1}) (PC : C -> Type@{Ξ± ; u3}), (forall c : C, PC c) -> forall (R : nat -> A -> B -> Type@{u2}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ±0 ; u4}), (forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r) -> forall (n : nat) (l : list A) (l0 : list B) (a : All2i_bis A B C R n l l0), All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n l l0 a (* Ξ± Ξ±0 ; u u0 u1 u2 u3 u4 |= *) All2i_bis_all_forall is universe polymorphic Arguments All2i_bis_all_forall (A B C)%_type_scope (PC HPC R PR HPR)%_function_scope n l l a All2i_bis_all_forall is transparent Expands to: Constant nested_eliminators.Template.All2i_bis_all_forall Declared in library nested_eliminators, line 223, characters 2-341 Inductive All2i_bis_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} (A : Type@{u}) (B : Type@{u0}) (C : Type@{u1}) (PC : C -> Type@{Ξ± ; u3}) (PPC : forall c : C, PC c -> Type@{Ξ±1 ; u5}) (R : nat -> A -> B -> Type@{u2}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ±0 ; u4}) (PPR : forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r -> Type@{Ξ±2 ; u6}) (n : nat) : forall (l : list A) (l0 : list B) (a : All2i_bis A B C R n l l0), All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n l l0 a -> Type@{max(Set,u,u0,u1,u2,u3,u4,u5,u6)} := All2i_bis_nil_all_all : forall (c : C) (p : PC c), PPC c p -> All2i_bis_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} A B C PC PPC R PR PPR n nil nil (All2i_bis_nil A B C R n c) (All2i_bis_nil_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n c p) | All2i_bis_cons_all_all : forall (a : A) (b : B) (lA : list A) (lB : list B) (r : R n a b) (p : PR n a b r), PPR n a b r p -> forall (a0 : All2i_bis A B C R (S n) lA lB) (a1 : All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR (S n) lA lB a0), All2i_bis_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} A B C PC PPC R PR PPR (S n) lA lB a0 a1 -> All2i_bis_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} A B C PC PPC R PR PPR n (cons a lA) (cons b lB) (All2i_bis_cons A B C R n a b lA lB r a0) (All2i_bis_cons_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n a b lA lB r p a0 a1). (* Ξ± Ξ±0 Ξ±1 Ξ±2 ; *u *u0 *u1 *u2 *u3 *u4 *u5 *u6 |= *) Arguments All2i_bis_all_all (A B C)%_type_scope (PC PPC R PR PPR)%_function_scope n l l a a0 Arguments All2i_bis_nil_all_all (A B C)%_type_scope (PC PPC R PR PPR)%_function_scope n c p _ Arguments All2i_bis_cons_all_all (A B C)%_type_scope (PC PPC R PR PPR)%_function_scope n a b lA lB r p _ a a _ All2i_bis_all_all_forall@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} : forall (A : Type@{u}) (B : Type@{u0}) (C : Type@{u1}) (PC : C -> Type@{Ξ± ; u3}) (PPC : forall c : C, PC c -> Type@{Ξ±1 ; u5}), (forall (c : C) (p : PC c), PPC c p) -> forall (R : nat -> A -> B -> Type@{u2}) (PR : forall (n : nat) (a : A) (b : B), R n a b -> Type@{Ξ±0 ; u4}) (PPR : forall (n : nat) (a : A) (b : B) (r : R n a b), PR n a b r -> Type@{Ξ±2 ; u6}), (forall (n : nat) (a : A) (b : B) (r : R n a b) (p : PR n a b r), PPR n a b r p) -> forall (n : nat) (l : list A) (l0 : list B) (a : All2i_bis A B C R n l l0) (a0 : All2i_bis_all@{Ξ± Ξ±0 ; u u0 u1 u2 u3 u4} A B C PC R PR n l l0 a), All2i_bis_all_all@{Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6} A B C PC PPC R PR PPR n l l0 a a0 (* Ξ± Ξ±0 Ξ±1 Ξ±2 ; u u0 u1 u2 u3 u4 u5 u6 |= *) All2i_bis_all_all_forall is universe polymorphic Arguments All2i_bis_all_all_forall (A B C)%_type_scope (PC PPC HPPC R PR PPR HPPR)%_function_scope n l l a a0 All2i_bis_all_all_forall is transparent Expands to: Constant nested_eliminators.Template.All2i_bis_all_all_forall Declared in library nested_eliminators, line 223, characters 2-341 triv_All2_bis_ind : forall P : triv_All2_bis -> Prop, (forall a : All2i_bis bool bool triv_All2_bis (fun (_ : nat) (_ _ : bool) => nat) zero nil nil, All2i_bis_all@{Prop Type ; Set Set Set Set Set Set} bool bool triv_All2_bis P (fun (_ : nat) (_ _ : bool) => nat) (fun (_ : nat) (_ _ : bool) (_ : nat) => unit) zero nil nil a -> P (ctriv_All2_bis a)) -> forall t : triv_All2_bis, P t triv_All2_bis_ind is not universe polymorphic Arguments triv_All2_bis_ind (P ctriv_All2_bis)%_function_scope t triv_All2_bis_ind is transparent Expands to: Constant nested_eliminators.Template.triv_All2_bis_ind Declared in library nested_eliminators, line 233, characters 2-176 Inductive sig_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ±0 ; u1}) : sig A P -> Type@{max(u,u0,u1)} := exist_all : forall x : A, PA x -> forall p : P x, PP x p -> sig_all@{Ξ± Ξ±0 ; u u0 u1} A PA P PP (exist A P x p). (* Ξ± Ξ±0 ; *u *u0 *u1 |= *) Arguments sig_all A%_type_scope (PA P PP)%_function_scope s Arguments exist_all A%_type_scope (PA P PP)%_function_scope x _ p _ sig_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ±0 ; u1}), (forall (a : A) (p : P a), PP a p) -> forall s : sig A P, sig_all@{Ξ± Ξ±0 ; u u0 u1} A PA P PP s (* Ξ± Ξ±0 ; u u0 u1 |= *) sig_all_forall is universe polymorphic Arguments sig_all_forall A%_type_scope (PA HPA P PP HPP)%_function_scope s sig_all_forall is transparent Expands to: Constant nested_eliminators.Template.sig_all_forall Declared in library nested_eliminators, line 241, characters 2-94 Inductive sig_all_10@{Ξ± ; u u0} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (P : A -> Prop) : sig A P -> Type@{max(u,u0)} := exist_all_10 : forall x : A, PA x -> forall p : P x, sig_all_10@{Ξ± ; u u0} A PA P (exist A P x p). (* Ξ± ; *u *u0 |= *) Arguments sig_all_10 A%_type_scope (PA P)%_function_scope s Arguments exist_all_10 A%_type_scope (PA P)%_function_scope x _ p sig_all_forall_10@{Ξ± ; u u0} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall (P : A -> Prop) (s : sig A P), sig_all_10@{Ξ± ; u u0} A PA P s (* Ξ± ; u u0 |= *) sig_all_forall_10 is universe polymorphic Arguments sig_all_forall_10 A%_type_scope (PA HPA P)%_function_scope s sig_all_forall_10 is transparent Expands to: Constant nested_eliminators.Template.sig_all_forall_10 Declared in library nested_eliminators, line 247, characters 2-28 Inductive sig_all_01@{Ξ± ; u u0} (A : Type@{u}) (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ± ; u0}) : sig A P -> Type@{max(u,u0)} := exist_all_01 : forall (x : A) (p : P x), PP x p -> sig_all_01@{Ξ± ; u u0} A P PP (exist A P x p). (* Ξ± ; *u *u0 |= *) Arguments sig_all_01 A%_type_scope (P PP)%_function_scope s Arguments exist_all_01 A%_type_scope (P PP)%_function_scope x p _ sig_all_forall_01@{Ξ± ; u u0} : forall (A : Type@{u}) (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ± ; u0}), (forall (a : A) (p : P a), PP a p) -> forall s : sig A P, sig_all_01@{Ξ± ; u u0} A P PP s (* Ξ± ; u u0 |= *) sig_all_forall_01 is universe polymorphic Arguments sig_all_forall_01 A%_type_scope (P PP HPP)%_function_scope s sig_all_forall_01 is transparent Expands to: Constant nested_eliminators.Template.sig_all_forall_01 Declared in library nested_eliminators, line 251, characters 2-28 Inductive NestRel_all@{Ξ± Ξ±0 ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (R : A -> A -> Prop) (PR : forall a a0 : A, R a a0 -> Type@{Ξ±0 ; u1}) : NestRel A R -> Type@{max(u,u0,u1,u2)} := mkR_all : forall x : A, PA x -> forall o : or (and (R x x) (R x x)) True, or_all@{Prop Type ; Set Set} (and (R x x) (R x x)) (and_all@{Ξ±0 Ξ±0 ; u1 u1} (R x x) (PR x x) (R x x) (PR x x)) True (fun _ : True => unit) o -> NestRel_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA R PR (mkR A R x o). (* Ξ± Ξ±0 ; *u *u0 =u1 *u2 |= *) Arguments NestRel_all A%_type_scope (PA R PR)%_function_scope n Arguments mkR_all A%_type_scope (PA R PR)%_function_scope x _ o _ NestRel_all_forall@{Ξ± Ξ±0 ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall (R : A -> A -> Prop) (PR : forall a a0 : A, R a a0 -> Type@{Ξ±0 ; u1}), (forall (a a0 : A) (r : R a a0), PR a a0 r) -> forall n : NestRel A R, NestRel_all@{Ξ± Ξ±0 ; u u0 u1 u2} A PA R PR n (* Ξ± Ξ±0 ; u u0 u1 u2 |= *) NestRel_all_forall is universe polymorphic Arguments NestRel_all_forall A%_type_scope (PA HPA R PR HPR)%_function_scope n NestRel_all_forall is transparent Expands to: Constant nested_eliminators.Template.NestRel_all_forall Declared in library nested_eliminators, line 264, characters 2-111 File "./output/nested_eliminators.v", line 278, characters 4-26: The command has indeed failed with message: Not implemented for primitive records. Inductive ex_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ±0 ; u1}) : ex A P -> Prop := ex_intro_all : forall x : A, PA x -> forall p : P x, PP x p -> ex_all@{Ξ± Ξ±0 ; u u0 u1} A PA P PP (ex_intro A P x p). (* Ξ± Ξ±0 ; *u *u0 *u1 |= *) Arguments ex_all A%_type_scope (PA P PP)%_function_scope e Arguments ex_intro_all A%_type_scope (PA P PP)%_function_scope x _ p _ ex_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall (P : A -> Prop) (PP : forall a : A, P a -> Type@{Ξ±0 ; u1}), (forall (a : A) (p : P a), PP a p) -> forall e : ex A P, ex_all@{Ξ± Ξ±0 ; u u0 u1} A PA P PP e (* Ξ± Ξ±0 ; u u0 u1 |= *) ex_all_forall is universe polymorphic Arguments ex_all_forall A%_type_scope (PA HPA P PP HPP)%_function_scope e ex_all_forall is transparent Expands to: Constant nested_eliminators.Template.ex_all_forall Declared in library nested_eliminators, line 284, characters 2-87 adequate_ind : forall (L : language) (Ο† : unit -> Type@{adequate_ind.u0}) (P : adequate L Ο† -> Prop), (forall p : prod False (ex (expr L) (fun e2 : expr L => prim_step L e2)), P (cadequate L Ο† p)) -> forall a : adequate L Ο†, P a adequate_ind is not universe polymorphic Arguments adequate_ind L (Ο† P cadequate)%_function_scope a adequate_ind is transparent Expands to: Constant nested_eliminators.Template.adequate_ind Declared in library nested_eliminators, line 295, characters 2-131 adequate_all@{Ξ± ; u u0} : forall (L : language) (Ο† : unit -> Type@{u}), (forall u : unit, Ο† u -> Type@{Ξ± ; u0}) -> adequate L Ο† -> Prop (* Ξ± ; *u *u0 |= *) adequate_all is universe polymorphic Arguments adequate_all L (Ο† PΟ†)%_function_scope a Expands to: Inductive nested_eliminators.Template.adequate_all Declared in library nested_eliminators, line 295, characters 2-131 casenat_all@{Ξ± ; u} : forall P : nat -> Set, (forall n : nat, P n -> Type@{Ξ± ; u}) -> casenat P -> Type@{max(Set,u)} (* Ξ± ; *u |= *) casenat_all is universe polymorphic Arguments casenat_all (P PP)%_function_scope c Expands to: Inductive nested_eliminators.Template.casenat_all Declared in library nested_eliminators, line 302, characters 2-94 casenat'_all@{Ξ± Ξ±0 ; u u0} : forall (A : nat -> Set) (PZ : Set), (PZ -> Type@{Ξ± ; u}) -> forall PS : forall n : nat, A n -> Set, (forall (n : nat) (a : A n), PS n a -> Type@{Ξ±0 ; u0}) -> casenat' A PZ PS -> Type@{max(Set,u,u0)} (* Ξ± Ξ±0 ; *u *u0 |= *) casenat'_all is universe polymorphic Arguments casenat'_all A%_function_scope PZ%_type_scope (PPZ PS PPS)%_function_scope c Expands to: Inductive nested_eliminators.Template.casenat'_all Declared in library nested_eliminators, line 307, characters 2-147 File "./output/nested_eliminators.v", line 325, characters 13-21: The command has indeed failed with message: The reference True_all was not found in the current environment. Inductive list_all@{Ξ± ; u u0} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) : list@{u} A -> Type@{max(Set,u,u0)} := nil_all : list_all@{Ξ± ; u u0} A PA (nil@{u} A) | cons_all : forall a : A, PA a -> forall l : list@{u} A, list_all@{Ξ± ; u u0} A PA l -> list_all@{Ξ± ; u u0} A PA (cons@{u} A a l). (* Ξ± ; =u *u0 |= *) Arguments list_all A%_type_scope PA%_function_scope l Arguments nil_all A%_type_scope PA%_function_scope Arguments cons_all A%_type_scope PA%_function_scope a _ l _ list_all_forall@{Ξ± ; u u0} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}), (forall a : A, PA a) -> forall l : list@{u} A, list_all@{Ξ± ; u u0} A PA l (* Ξ± ; u u0 |= *) list_all_forall is universe polymorphic Arguments list_all_forall A%_type_scope (PA HPA)%_function_scope l list_all_forall is transparent Expands to: Constant nested_eliminators.UnivPoly.list_all_forall Declared in library nested_eliminators, line 328, characters 2-88 Inductive list_all_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}) : forall l : list@{u} A, list_all@{Ξ± ; u u0} A PA l -> Type@{max(Set,u,u0,u1)} := nil_all_all : list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA (nil@{u} A) (nil_all@{Ξ± ; u u0} A PA) | cons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (l : list@{u} A) (l0 : list_all@{Ξ± ; u u0} A PA l), list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA l l0 -> list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA (cons@{u} A a l) (cons_all@{Ξ± ; u u0} A PA a p l l0). (* Ξ± Ξ±0 ; =u *u0 *u1 |= *) Arguments list_all_all A%_type_scope (PA PPA)%_function_scope l l0 Arguments nil_all_all A%_type_scope (PA PPA)%_function_scope Arguments cons_all_all A%_type_scope (PA PPA)%_function_scope a p _ l l _ list_all_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u0}) (PPA : forall a : A, PA a -> Type@{Ξ±0 ; u1}), (forall (a : A) (p : PA a), PPA a p) -> forall (l : list@{u} A) (l0 : list_all@{Ξ± ; u u0} A PA l), list_all_all@{Ξ± Ξ±0 ; u u0 u1} A PA PPA l l0 (* Ξ± Ξ±0 ; u u0 u1 |= *) list_all_all_forall is universe polymorphic Arguments list_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope l l0 list_all_all_forall is transparent Expands to: Constant nested_eliminators.UnivPoly.list_all_all_forall Declared in library nested_eliminators, line 328, characters 2-88 MRT_ind@{} : forall P : MRT -> Prop, (forall l : list@{Set} MRT, list_all@{Prop ; Set Set} MRT P l -> P (MRTnode l)) -> forall m : MRT, P m MRT_ind is universe polymorphic Arguments MRT_ind (P MRTnode)%_function_scope m MRT_ind is transparent Expands to: Constant nested_eliminators.UnivPoly.MRT_ind Declared in library nested_eliminators, line 337, characters 2-55 RoseTree_ind@{u u0} : forall (A : Type@{u}) (P : RoseTree@{u u0} A -> Prop), (forall a : A, P (RTleaf@{u u0} A a)) -> (forall l : list@{u0} (RoseTree@{u u0} A), list_all@{Prop ; u0 Set} (RoseTree@{u u0} A) P l -> P (RTnode@{u u0} A l)) -> forall r : RoseTree@{u u0} A, P r (* u u0 |= u <= u0 *) RoseTree_ind is universe polymorphic Arguments RoseTree_ind A%_type_scope (P RTleaf RTnode)%_function_scope r RoseTree_ind is transparent Expands to: Constant nested_eliminators.UnivPoly.RoseTree_ind Declared in library nested_eliminators, line 342, characters 2-113 Inductive RoseTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) : RoseTree@{u u0} A -> Type@{max(u0,u1,u2)} := RTleaf_all : forall a : A, PA a -> RoseTree_all@{Ξ± ; u u0 u1 u2} A PA (RTleaf@{u u0} A a) | RTnode_all : forall l : list@{u0} (RoseTree@{u u0} A), list_all@{Type ; u0 u2} (RoseTree@{u u0} A) (RoseTree_all@{Ξ± ; u u0 u1 u2} A PA) l -> RoseTree_all@{Ξ± ; u u0 u1 u2} A PA (RTnode@{u u0} A l). (* Ξ± ; =u =u0 *u1 *u2 |= u <= u0 u0 <= u2 u1 <= u2 *) Arguments RoseTree_all A%_type_scope PA%_function_scope r Arguments RTleaf_all A%_type_scope PA%_function_scope a _ Arguments RTnode_all A%_type_scope PA%_function_scope l _ RoseTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}), (forall a : A, PA a) -> forall r : RoseTree@{u u0} A, RoseTree_all@{Ξ± ; u u0 u1 u2} A PA r (* Ξ± ; u u0 u1 u2 |= u <= u0 u0 <= u2 u1 <= u2 *) RoseTree_all_forall is universe polymorphic Arguments RoseTree_all_forall A%_type_scope (PA HPA)%_function_scope r RoseTree_all_forall is transparent Expands to: Constant nested_eliminators.UnivPoly.RoseTree_all_forall Declared in library nested_eliminators, line 342, characters 2-113 RoseRoseTree_ind@{u u0 u1} : forall (A : Type@{u}) (P : RoseRoseTree@{u u0} A -> Prop), (forall a : A, P (Nleaf@{u u0} A a)) -> (forall p : list@{u0} (list@{u0} (RoseRoseTree@{u u0} A)), list_all@{Type ; u0 u1} (list@{u0} (RoseRoseTree@{u u0} A)) (list_all@{Prop ; u0 Set} (RoseRoseTree@{u u0} A) P) p -> P (Nnode@{u u0} A p)) -> forall r : RoseRoseTree@{u u0} A, P r (* u u0 u1 |= Set <= u1 u <= u0 u0 <= u1 *) RoseRoseTree_ind is universe polymorphic Arguments RoseRoseTree_ind A%_type_scope (P Nleaf Nnode)%_function_scope r RoseRoseTree_ind is transparent Expands to: Constant nested_eliminators.UnivPoly.RoseRoseTree_ind Declared in library nested_eliminators, line 350, characters 2-136 Inductive RoseRoseTree_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) : RoseRoseTree@{u u0} A -> Type@{max(u0,u1,u2)} := Nleaf_all : forall a : A, PA a -> RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA (Nleaf@{u u0} A a) | Nnode_all : forall p : list@{u0} (list@{u0} (RoseRoseTree@{u u0} A)), list_all@{Type ; u0 u2} (list@{u0} (RoseRoseTree@{u u0} A)) (list_all@{Type ; u0 u2} (RoseRoseTree@{u u0} A) (RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA)) p -> RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA (Nnode@{u u0} A p). (* Ξ± ; =u =u0 *u1 =u2 |= Set <= u2 u <= u0 u0 <= u2 u1 <= u2 *) Arguments RoseRoseTree_all A%_type_scope PA%_function_scope r Arguments Nleaf_all A%_type_scope PA%_function_scope a _ Arguments Nnode_all A%_type_scope PA%_function_scope p _ RoseRoseTree_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}), (forall a : A, PA a) -> forall r : RoseRoseTree@{u u0} A, RoseRoseTree_all@{Ξ± ; u u0 u1 u2} A PA r (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u0 u0 <= u2 u1 <= u2 *) RoseRoseTree_all_forall is universe polymorphic Arguments RoseRoseTree_all_forall A%_type_scope (PA HPA)%_function_scope r RoseRoseTree_all_forall is transparent Expands to: Constant nested_eliminators.UnivPoly.RoseRoseTree_all_forall Declared in library nested_eliminators, line 350, characters 2-136 ArrowTree3_ind@{u u0} : forall (A : Type@{u}) (P : ArrowTree3@{u u0} A -> Prop), (forall a : A, P (ATleaf3@{u u0} A a)) -> (forall l : bool -> list@{u0} (nat -> ArrowTree3@{u u0} A), (forall H : bool, list_all@{Prop ; u0 Set} (nat -> ArrowTree3@{u u0} A) (fun H0 : nat -> ArrowTree3@{u u0} A => forall H1 : nat, P (H0 H1)) (l H)) -> P (ATnode3@{u u0} A l)) -> forall a : ArrowTree3@{u u0} A, P a (* u u0 |= u <= u0 *) ArrowTree3_ind is universe polymorphic Arguments ArrowTree3_ind A%_type_scope (P ATleaf3 ATnode3)%_function_scope a ArrowTree3_ind is transparent Expands to: Constant nested_eliminators.UnivPoly.ArrowTree3_ind Declared in library nested_eliminators, line 358, characters 2-140 Inductive ArrowTree3_all@{Ξ± ; u u0 u1 u2} (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}) : ArrowTree3@{u u0} A -> Type@{max(u0,u1,u2)} := ATleaf3_all : forall a : A, PA a -> ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (ATleaf3@{u u0} A a) | ATnode3_all : forall l : bool -> list@{u0} (nat -> ArrowTree3@{u u0} A), (forall H : bool, list_all@{Type ; u0 u2} (nat -> ArrowTree3@{u u0} A) (fun H0 : nat -> ArrowTree3@{u u0} A => forall H1 : nat, ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (H0 H1)) (l H)) -> ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA (ATnode3@{u u0} A l). (* Ξ± ; =u =u0 *u1 *u2 |= Set <= u2 u <= u0 u0 <= u2 u1 <= u2 *) Arguments ArrowTree3_all A%_type_scope PA%_function_scope a Arguments ATleaf3_all A%_type_scope PA%_function_scope a _ Arguments ATnode3_all A%_type_scope (PA l _)%_function_scope ArrowTree3_all_forall@{Ξ± ; u u0 u1 u2} : forall (A : Type@{u}) (PA : A -> Type@{Ξ± ; u1}), (forall a : A, PA a) -> forall a : ArrowTree3@{u u0} A, ArrowTree3_all@{Ξ± ; u u0 u1 u2} A PA a (* Ξ± ; u u0 u1 u2 |= Set <= u2 u <= u0 u0 <= u2 u1 <= u2 *) ArrowTree3_all_forall is universe polymorphic Arguments ArrowTree3_all_forall A%_type_scope (PA HPA)%_function_scope a ArrowTree3_all_forall is transparent Expands to: Constant nested_eliminators.UnivPoly.ArrowTree3_all_forall Declared in library nested_eliminators, line 358, characters 2-140 Inductive list_all@{Ξ± Ξ±0 ; u u0 u1} (A : Type@{Ξ± ; u}) (PA : A -> Type@{Ξ±0 ; u1}) : list@{Ξ± ; u u0} A -> Type@{Ξ± ; max(u0,u1)} := nil_all : list_all@{Ξ± Ξ±0 ; u u0 u1} A PA (nil@{Ξ± ; u u0} A) | cons_all : forall a : A, PA a -> forall l : list@{Ξ± ; u u0} A, list_all@{Ξ± Ξ±0 ; u u0 u1} A PA l -> list_all@{Ξ± Ξ±0 ; u u0 u1} A PA (cons@{Ξ± ; u u0} A a l). (* Ξ± Ξ±0 ; =u =u0 *u1 |= u <= u0 *) Arguments list_all A%_type_scope PA%_function_scope l Arguments nil_all A%_type_scope PA%_function_scope Arguments cons_all A%_type_scope PA%_function_scope a _ l _ list_all_forall@{Ξ± Ξ±0 ; u u0 u1} : forall (A : Type@{Ξ± ; u}) (PA : A -> Type@{Ξ±0 ; u1}), (forall a : A, PA a) -> forall l : list@{Ξ± ; u u0} A, list_all@{Ξ± Ξ±0 ; u u0 u1} A PA l (* Ξ± Ξ±0 ; u u0 u1 |= u <= u0 *) list_all_forall is universe polymorphic Arguments list_all_forall A%_type_scope (PA HPA)%_function_scope l list_all_forall is transparent Expands to: Constant nested_eliminators.SortPoly.list_all_forall Declared in library nested_eliminators, line 378, characters 2-22 Inductive list_all_all@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} (A : Type@{Ξ± ; u}) (PA : A -> Type@{Ξ±0 ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±1 ; u2}) : forall l : list@{Ξ± ; u u0} A, list_all@{Ξ± Ξ±0 ; u u0 u1} A PA l -> Type@{Ξ± ; max(u0,u1,u2)} := nil_all_all : list_all_all@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} A PA PPA (nil@{Ξ± ; u u0} A) (nil_all@{Ξ± Ξ±0 ; u u0 u1} A PA) | cons_all_all : forall (a : A) (p : PA a), PPA a p -> forall (l : list@{Ξ± ; u u0} A) (l0 : list_all@{Ξ± Ξ±0 ; u u0 u1} A PA l), list_all_all@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} A PA PPA l l0 -> list_all_all@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} A PA PPA (cons@{Ξ± ; u u0} A a l) (cons_all@{Ξ± Ξ±0 ; u u0 u1} A PA a p l l0). (* Ξ± Ξ±0 Ξ±1 ; =u =u0 *u1 *u2 |= u <= u0 *) Arguments list_all_all A%_type_scope (PA PPA)%_function_scope l l0 Arguments nil_all_all A%_type_scope (PA PPA)%_function_scope Arguments cons_all_all A%_type_scope (PA PPA)%_function_scope a p _ l l _ list_all_all_forall@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} : forall (A : Type@{Ξ± ; u}) (PA : A -> Type@{Ξ±0 ; u1}) (PPA : forall a : A, PA a -> Type@{Ξ±1 ; u2}), (forall (a : A) (p : PA a), PPA a p) -> forall (l : list@{Ξ± ; u u0} A) (l0 : list_all@{Ξ± Ξ±0 ; u u0 u1} A PA l), list_all_all@{Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2} A PA PPA l l0 (* Ξ± Ξ±0 Ξ±1 ; u u0 u1 u2 |= u <= u0 *) list_all_all_forall is universe polymorphic Arguments list_all_all_forall A%_type_scope (PA PPA HPPA)%_function_scope l l0 list_all_all_forall is transparent Expands to: Constant nested_eliminators.SortPoly.list_all_all_forall Declared in library nested_eliminators, line 382, characters 2-26 MRT_ind@{} : forall P : MRT -> Prop, (forall l : list@{Type ; Set Set} MRT, list_all@{Type Prop ; Set Set Set} MRT P l -> P (MRTnode l)) -> forall m : MRT, P m MRT_ind is universe polymorphic Arguments MRT_ind (P MRTnode)%_function_scope m MRT_ind is transparent Expands to: Constant nested_eliminators.SortPoly.MRT_ind Declared in library nested_eliminators, line 386, characters 2-55 SRT_sind@{u u0} : forall P : SRT@{u} -> SProp, (forall l : list@{SProp ; u u} SRT@{u}, list_all@{SProp SProp ; u u u0} SRT@{u} P l -> P (SRTnode@{u} l)) -> forall s : SRT@{u}, P s (* u u0 |= *) SRT_sind is universe polymorphic Arguments SRT_sind (P SRTnode)%_function_scope s SRT_sind is transparent Expands to: Constant nested_eliminators.SortPoly.SRT_sind Declared in library nested_eliminators, line 391, characters 2-57 File "./output/nested_eliminators.v", line 408, characters 2-60: The command has indeed failed with message: MRT is nested using list. No scheme for list is registered as All. It can be generated using command "Scheme All" e.g. "Scheme All for list.". [register-all,automation,default] MRT_ind : forall P : MRT -> Prop, (forall l : list MRT, P (MRTnode l)) -> forall m : MRT, P m MRT_ind is not universe polymorphic Arguments MRT_ind (P MRTnode)%_function_scope m MRT_ind is transparent Expands to: Constant nested_eliminators.TestWarning.MRT_ind Declared in library nested_eliminators, line 413, characters 2-55 Nester_all@{Ξ± ; u} : forall X : unit -> P unit, (forall u u0 : unit, X u u0 -> Type@{Ξ± ; u}) -> Nester X -> Type@{max(P.u1,u)} (* Ξ± ; *u |= *) Nester_all is universe polymorphic Arguments Nester_all (X PX)%_function_scope n Expands to: Inductive nested_eliminators.DeepArities.Nester_all Declared in library nested_eliminators, line 427, characters 2-24 rocq-9.2.0/test-suite/output/nested_eliminators.v000066400000000000000000000226311516144147600222300ustar00rootroot00000000000000(* Some prelude to be able to test the file without being able to compile the prelude *) Notation "A -> B" := (forall (_ : A), B) (right associativity, at level 99). Inductive nat : Type := | zero : nat | S : nat -> nat. Inductive bool : Type := | true : bool | false : bool. (* The type unit needs to be defined and registered to instantiate partial nesting. *) Inductive unit : Set := tt : unit. Register unit as core.unit.type. Register tt as core.unit.tt. Set Printing Universes. Module Template. (* Example with Template Inductive Types *) Set Depth Scheme All 2. Inductive True := c. Fail Check True_all. (* Example with list *) Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. Print list_all. About list_all_forall. Print list_all_all. About list_all_all_forall. Arguments nil {_}. Arguments cons {_}. Inductive MRT : Set := | MRTnode : list MRT -> MRT. About MRT_ind. Inductive RoseTree A : Type := | RTleaf (a : A) : RoseTree A | RTnode (l : list (RoseTree A)) : RoseTree A. About RoseTree_ind. Print RoseTree_all. About RoseTree_all_forall. Inductive RoseTreeMut A := | node_mut : forest A -> RoseTreeMut A with forest A := | forest_nil : forest A | forest_cons : A -> RoseTreeMut A -> forest A. Print RoseTreeMut_all. About RoseTreeMut_all_forall. Print RoseTreeMut_all_all. About RoseTreeMut_all_all_forall. Print forest_all. About forest_all_forall. Print forest_all_all. About forest_all_all_forall. Inductive RoseRoseTree A : Type := | Nleaf (a : A) : RoseRoseTree A | Nnode (p : (list (list (RoseRoseTree A)))) : RoseRoseTree A. About RoseRoseTree_ind. Print RoseRoseTree_all. About RoseRoseTree_all_forall. Inductive ArrowTree1 A : Type := | ATleaf1 (a : A) : ArrowTree1 A | ATnode1 (l : (bool -> list (ArrowTree1 A))) : ArrowTree1 A. About ArrowTree1_ind. Print ArrowTree1_all. About ArrowTree1_all_forall. Inductive ArrowTree2 A : Type := | ATleaf2 (a : A) : ArrowTree2 A | ATnode2 (l : list (nat -> ArrowTree2 A)) : ArrowTree2 A. About ArrowTree2_ind. Print ArrowTree2_all. About ArrowTree2_all_forall. Inductive ArrowTree3 A : Type := | ATleaf3 (a : A) : ArrowTree3 A | ATnode3 (l : (bool -> list (nat -> ArrowTree3 A))) : ArrowTree3 A. About ArrowTree3_ind. Print ArrowTree3_all. About ArrowTree3_all_forall. (* Example Prod *) Inductive prod (A B : Type) : Type := pair : A -> B -> prod A B. Print prod_all. About prod_all_forall. Print prod_all_all. About prod_all_all_forall. Arguments pair {_ _}. Inductive PairTree A : Type := | Pleaf (a : A) : PairTree A | Pnode (p : prod (PairTree A) (PairTree A)) : PairTree A. About PairTree_ind. Print PairTree_all. About PairTree_all_forall. Module AutoGeneratedScheme. Inductive LeftTree A : Type := | Lleaf (a : A) : LeftTree A | Lnode (p : prod (LeftTree A) nat) : LeftTree A. About LeftTree_ind. Print LeftTree_all. About LeftTree_all_forall. End AutoGeneratedScheme. Module Scheme. Unset Elimination Schemes. Inductive LeftTree A : Type := | Lleaf (a : A) : LeftTree A | Lnode (p : prod (LeftTree A) nat) : LeftTree A. Scheme Induction for LeftTree Sort Prop. About LeftTree_ind. Print LeftTree_all. About LeftTree_all_forall. End Scheme. Module PartialAll. Scheme All for prod over A. Print prod_all_10. About prod_all_forall_10. Print prod_all_10_all. About prod_all_10_all_forall. Inductive LeftTree A : Type := | Lleaf (a : A) : LeftTree A | Lnode (p : prod (LeftTree A) nat) : LeftTree A. About LeftTree_ind. Print LeftTree_all. About LeftTree_all_forall. End PartialAll. Inductive RightTree A : Type := | Rleaf (a : A) : RightTree A | Rnode (p : prod nat (RightTree A)) : RightTree A. About RightTree_ind. Print RightTree_all. About RightTree_all_forall. (* Nesting with vec *) Inductive vec A : nat -> Type := | vnil : vec A zero | vcons : A -> forall n, vec A n -> vec A (S n). Print vec_all. About vec_all_forall. Print vec_all_all. About vec_all_all_forall. Inductive VecTree A : Type := | VNleaf (a : A) : VecTree A | VNnode n (p : vec (VecTree A) n) : VecTree A. About VecTree_ind. Print VecTree_all. About VecTree_all_forall. (* Example All2i *) Inductive All2i (A B : Type) (R : nat -> A -> B -> Type) (n : nat) : list A -> list B -> Type := | All2i_nil : All2i A B R n nil nil | All2i_cons : forall (a : A) (b : B) (lA : list A) (lB : list B), R n a b -> All2i A B R (S n) lA lB -> All2i A B R n (cons a lA) (cons b lB). Print All2i_all. About All2i_all_forall. Print All2i_all_all. About All2i_all_all_forall. Fail Scheme All for All2i over A. Inductive typing A B (n : nat) (a : A) (b : B) : Type := | typ_nil : typing A B n a b | typ_cons : forall (lA : list A) (lB : list B), All2i A B (fun n => typing A B n) n lA lB -> typing A B n a b. About typing_ind. (* Example All2i_bis_bis with trivial nesting on R *) Inductive All2i_bis (A B C : Type) (R : nat -> A -> B -> Type) (n : nat) : list A -> list B -> Type := | All2i_bis_nil : C -> All2i_bis A B C R n nil nil | All2i_bis_cons : forall (a : A) (b : B) (lA : list A) (lB : list B), R n a b -> All2i_bis A B C R (S n) lA lB -> All2i_bis A B C R n (cons a lA) (cons b lB). Print All2i_bis_all. About All2i_bis_all_forall. Print All2i_bis_all_all. About All2i_bis_all_all_forall. Inductive triv_All2_bis : Type := | ctriv_All2_bis : All2i_bis bool bool triv_All2_bis (fun _ _ _ => nat) zero (@nil bool) (@nil bool) -> triv_All2_bis. About triv_All2_bis_ind. (* sig *) Inductive sig (A : Type) (P : A -> Prop) : Type := | exist : forall x : A, P x -> sig A P. Print sig_all. About sig_all_forall. Scheme All for sig over A. Print sig_all_10. About sig_all_forall_10. Scheme All for sig over P. Print sig_all_01. About sig_all_forall_01. (* Test collapse above prop *) Inductive and (A B : Prop) : Prop := | conj : A -> B -> and A B. Inductive or (A B : Prop) : Prop := | or_introl : A -> or A B | or_intror : B -> or A B. Inductive NestRel A (R : A -> A -> Prop) := | mkR : forall x, or (and (R x x) (R x x)) True -> NestRel A R. Print NestRel_all. About NestRel_all_forall. (* Test Primtive Projections *) Module PrimRecord. Set Primitive Projections. Inductive X (U:Type) := { b : U }. Fail Scheme All for X. End PrimRecord. (* Test Deeply Nested + variable binding *) Inductive ex (A:Type) (P:A -> Prop) : Prop := ex_intro : forall x:A, P x -> ex A P. Print ex_all. About ex_all_forall. Record language := Language { expr : Type; prim_step : expr -> Prop; }. Inductive adequate L (Ο† : unit -> Type) := | cadequate : prod False (ex (expr L) (fun e2 => prim_step L e2)) -> adequate L Ο†. About adequate_ind. About adequate_all. (* ISSUE 21710 *) Inductive casenat (P : nat -> Set) : Set := | casenat_fold : (forall m, P m) -> casenat P. About casenat_all. Inductive casenat' (A : nat -> Set) (PZ : Set) (PS : forall n, A n -> Set) : Set := | casenat'_fold : (forall m a, PS m a) -> casenat' A PZ PS. About casenat'_all. End Template. Module UnivPoly. (* Example with Template Inductive Types *) Set Universe Polymorphism. Set Depth Scheme All 2. Inductive True := c. Fail Check True_all. (* Example with list *) Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. Print list_all. About list_all_forall. Print list_all_all. About list_all_all_forall. Inductive MRT : Set := | MRTnode : list MRT -> MRT. About MRT_ind. Inductive RoseTree A : Type := | RTleaf (a : A) : RoseTree A | RTnode (l : list (RoseTree A)) : RoseTree A. About RoseTree_ind. Print RoseTree_all. About RoseTree_all_forall. Inductive RoseRoseTree A : Type := | Nleaf (a : A) : RoseRoseTree A | Nnode (p : (list (list (RoseRoseTree A)))) : RoseRoseTree A. About RoseRoseTree_ind. Print RoseRoseTree_all. About RoseRoseTree_all_forall. Inductive ArrowTree3 A : Type := | ATleaf3 (a : A) : ArrowTree3 A | ATnode3 (l : (bool -> list (nat -> ArrowTree3 A))) : ArrowTree3 A. About ArrowTree3_ind. Print ArrowTree3_all. About ArrowTree3_all_forall. End UnivPoly. Module SortPoly. (* Example with a sort polymorphic containers *) Set Universe Polymorphism. Inductive list@{sA;uA uR} (A : Type@{sA;uA}) : Type@{sA; uR} := | nil : list A | cons : A -> list A -> list A. Scheme All for list. Print list_all. About list_all_forall. Scheme All for list_all. Print list_all_all. About list_all_all_forall. Inductive MRT : Set := | MRTnode : list MRT -> MRT. About MRT_ind. Inductive SRT : SProp := | SRTnode : list SRT -> SRT. About SRT_sind. End SortPoly. Module TestWarning. Set Warnings "+register-all". Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. Fail Inductive MRT : Set := | MRTnode : list MRT -> MRT. Set Warnings "-register-all". Inductive MRT : Set := | MRTnode : list MRT -> MRT. About MRT_ind. End TestWarning. Module DeepArities. Definition P A := A -> Type. Inductive Nester (X : unit -> P unit) : Type := | nester_intro : X tt tt -> Nester X. Scheme All for Nester. About Nester_all. End DeepArities. rocq-9.2.0/test-suite/output/non_reversible_notation.out000066400000000000000000000006531516144147600236310ustar00rootroot00000000000000File "./output/non_reversible_notation.v", line 2, characters 0-35: Warning: This notation contains Ltac expressions: it will not be used for printing. [non-reversible-notation,parsing,default] File "./output/non_reversible_notation.v", line 4, characters 0-31: Warning: This notation contains volatile casts: it will not be used for printing. [non-reversible-notation,parsing,default] 1 : nat 2 : nat baz : nat rocq-9.2.0/test-suite/output/non_reversible_notation.v000066400000000000000000000002111516144147600232550ustar00rootroot00000000000000 Abbreviation foo := ltac:(exact 1). Abbreviation bar := (2 :> nat). Abbreviation baz := (3 <: nat). Check foo. Check bar. Check baz. rocq-9.2.0/test-suite/output/notation_prefix_incompatible_level.out000066400000000000000000000005401516144147600260220ustar00rootroot00000000000000File "./output/notation_prefix_incompatible_level.v", line 7, characters 0-63: Warning: Notations "#20 #21 _ #3 _" defined at level 50 with arguments constr at level 30 and "#20 #21 _ #34" defined at level 50 with arguments constr at level 40 have incompatible prefixes. One of them will likely not work. [notation-incompatible-prefix,parsing,default] rocq-9.2.0/test-suite/output/notation_prefix_incompatible_level.v000066400000000000000000000005021516144147600254560ustar00rootroot00000000000000Set Warnings "-closed-notation-not-level-0". Reserved Notation "#0 #1" (at level 30). Reserved Notation "#0 #1 #2" (at level 40). (* no warning, parser takes successive terminals at once *) Reserved Notation "#20 #21 x #3 y" (x at level 30, at level 50). Reserved Notation "#20 #21 x #34" (x at level 40, at level 50). rocq-9.2.0/test-suite/output/notation_previous_prefix.out000066400000000000000000000005601516144147600240430ustar00rootroot00000000000000Notation "#0 _ #1 _" at level 30 with arguments constr at next level, constr at next level, no associativity. Notation "#0 _ #1 _" in foo at level 40 with arguments custom foo at next level, custom foo at next level, no associativity. Notation "#2 _ #3 _ #4 _" at level 30 with arguments constr at level 20, constr at level 25, constr at next level, no associativity. rocq-9.2.0/test-suite/output/notation_previous_prefix.v000066400000000000000000000006361516144147600235050ustar00rootroot00000000000000Reserved Notation "#0 x" (at level 30). Reserved Notation "#0 x #1 y". Print Notation "#0 _ #1 _". Declare Custom Entry foo. Reserved Notation "#0 x" (in custom foo at level 40). Reserved Notation "#0 x #1 y" (in custom foo). Print Notation "#0 _ #1 _" in custom foo. Reserved Notation "#2 x #3 y" (at level 30, x at level 20, y at level 25). Reserved Notation "#2 z #3 x #4 y". Print Notation "#2 _ #3 _ #4 _". rocq-9.2.0/test-suite/output/notation_principal_scope.out000066400000000000000000000025431516144147600237670ustar00rootroot00000000000000File "./output/notation_principal_scope.v", line 4, characters 32-33: The command has indeed failed with message: Argument X was previously inferred to be in scope function_scope but is here used in the empty scope stack. Scope function_scope will be used at parsing time unless you override it by annotating the argument with an explicit scope of choice. [inconsistent-scopes,syntax,default] File "./output/notation_principal_scope.v", line 6, characters 27-40: The command has indeed failed with message: Abbreviations don't support only printing File "./output/notation_principal_scope.v", line 8, characters 26-37: The command has indeed failed with message: The reference nonexisting was not found in the current environment. File "./output/notation_principal_scope.v", line 10, characters 38-61: The command has indeed failed with message: Notation scope for argument X can be specified only once. pp I : True /\ True File "./output/notation_principal_scope.v", line 19, characters 18-19: The command has indeed failed with message: Illegal application (Non-functional construction): The expression "I" of type "True" cannot be applied to the term "I" : "True" File "./output/notation_principal_scope.v", line 21, characters 0-54: Warning: This notation will not be used for printing as it is bound to a single variable. [notation-bound-to-variable,parsing,default] rocq-9.2.0/test-suite/output/notation_principal_scope.v000066400000000000000000000012261516144147600234220ustar00rootroot00000000000000Arguments conj {_ _} _ _%_function. Set Warnings "+inconsistent-scopes". Fail Abbreviation pp X := (conj X X). Fail Abbreviation pp := 1 (only printing). Fail Abbreviation pp X := nonexisting. Fail Abbreviation pp X := (conj X X) (X, X in scope nat_scope). Abbreviation pp X := (conj X X) (X in scope nat_scope). Notation "$" := I (only parsing) : nat_scope. Notation "$" := (I I) (only parsing) : bool_scope. Open Scope bool_scope. Check pp $. Fail Check pp (id $). Abbreviation pp1 X := (X%nat) (X in scope bool_scope). Abbreviation pp2 X := ((X + X)%type) (X in scope bool_scope). Abbreviation pp3 X := (((X, X)%type, X)%nat) (X in scope bool_scope). rocq-9.2.0/test-suite/output/onlyprinting.out000066400000000000000000000012221516144147600214270ustar00rootroot000000000000000:-) 0 : nat 1 +_a 2 : nat 1 +_b 2 : nat 1 +_b 2 : nat 1 +_c 2 : nat 1 +_c 2 : nat Scope nat_scope Delimiting key is nat Bound to class nat "x >= y" := (ge x y) "x > y" := (gt x y) "x <= y <= z" := (and (le x y) (le y z)) "x <= y < z" := (and (le x y) (lt y z)) "n <= m" := (le n m) "x < y <= z" := (and (lt x y) (le y z)) "x < y < z" := (and (lt x y) (lt y z)) "x < y" := (lt x y) "x - y" := (Nat.sub x y) "x +_c y" := (Nat.add x y) (only printing) "x +_b y" := (Nat.add x y) "x +_a y" := (Nat.add x y) "x + y" := (Nat.add x y) "x * y" := (Nat.mul x y) 1 +_b 2 : nat 1 +_a 2 : nat 1 + 2 : nat 1 +_c 2 : nat rocq-9.2.0/test-suite/output/onlyprinting.v000066400000000000000000000012621516144147600210710ustar00rootroot00000000000000Module A. Reserved Notation "x :-) y" (at level 50, only printing). Notation "x :-) y" := (plus x y). Check 0 + 0. End A. Module B. Notation "x +_a y" := (plus x y) (at level 50) : nat_scope. Check 1 +_a 2. Notation "x +_b y" := (plus x y) (at level 50) : nat_scope. Check 1 +_a 2. Check 1 +_b 2. Notation "x +_c y" := (plus x y) (at level 50, only printing) : nat_scope. Check 1 +_a 2. Check 1 +_b 2. Print Scope nat_scope. Disable Notation "_ +_c _" : nat_scope. Check 1 +_a 2. Disable Notation "x +_b y" : nat_scope. Check 1 +_a 2. Disable Notation "_ +_a _" (only printing) : nat_scope. Check 1 +_a 2. Enable Notation "a +_c b" (only printing) : nat_scope. Check 1 +_a 2. End B. rocq-9.2.0/test-suite/output/optimize_heap.out000066400000000000000000000001401516144147600215260ustar00rootroot000000000000001 goal ============================ True 1 goal ============================ True rocq-9.2.0/test-suite/output/optimize_heap.v000066400000000000000000000001631516144147600211710ustar00rootroot00000000000000(* optimize_heap should not affect the proof state *) Goal True. idtac. Show. optimize_heap. Show. Abort. rocq-9.2.0/test-suite/output/prim_array.out000066400000000000000000000003661516144147600210500ustar00rootroot00000000000000[| | 0 : nat |] : array nat [| 1; 2; 3 | 0 : nat |] : array nat [| | 0 : nat |]@{Set} : array@{Set} nat [| bool; list nat | nat : Set |]@{prim_array.29} : array@{prim_array.29} Set (* {prim_array.29} |= Set < prim_array.29 *) rocq-9.2.0/test-suite/output/prim_array.v000066400000000000000000000002311516144147600204750ustar00rootroot00000000000000Primitive array := #array_type. Check [| | 0 |]. Check [| 1; 2; 3 | 0 |]. Set Printing Universes. Check [| | 0 |]. Check [| bool; list nat | nat |]. rocq-9.2.0/test-suite/output/primitive_tokens.out000066400000000000000000000015451516144147600222760ustar00rootroot000000000000001234 : nat Nat.add 1 2 : nat match 1 with | 1 => true | _ => false end : bool {| field := 7 |} : test S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S ...))))))))))))))))))))))) : nat Nat.add (S O) (S (S O)) : nat match S O with | S O => true | _ => false end : bool {| field := S (S (S (S (S (S (S O)))))) |} : test rocq-9.2.0/test-suite/output/primitive_tokens.v000066400000000000000000000004311516144147600217250ustar00rootroot00000000000000Record test := { field : nat }. Unset Printing Notations. Check 1234. Check 1 + 2. Check match 1 with 1 => true | _ => false end. Check {| field := 7 |}. Set Printing Raw Literals. Check 1234. Check 1 + 2. Check match 1 with 1 => true | _ => false end. Check {| field := 7 |}. rocq-9.2.0/test-suite/output/print_hintdb_metas.out000066400000000000000000000004551516144147600225570ustar00rootroot00000000000000Non-discriminated database Unfoldable variable definitions: all Unfoldable constant definitions: all Unfoldable projection definitions: all Cut: emp For any goal -> For and -> simple apply x (cost 0, pattern ?n = 1 /\ (forall n : nat, n = ?m), id 0) rocq-9.2.0/test-suite/output/print_hintdb_metas.v000066400000000000000000000004051516144147600222100ustar00rootroot00000000000000Theorem x : forall n m:nat, n = 1 /\ forall n : nat, n = m. Admitted. Create HintDb foo. Hint Resolve x : foo. (* Note that the pattern doesn't have a metavariable for the inner forall n ie pattern is ?n = 1 /\ (forall n : nat, n = ?m) *) Print HintDb foo. rocq-9.2.0/test-suite/output/print_ltac.out000066400000000000000000000074711516144147600210460ustar00rootroot00000000000000Ltac t1 := time "my tactic" idtac Ltac t2 := let x := string:("my tactic") in idtac x Ltac t3 := idtacstr "my tactic" Ltac t4 x := match x with | ?A => constr:((A, A)) end File "./output/print_ltac.v", line 17, characters 27-32: The command has indeed failed with message: idnat is bound to a notation that does not denote a reference. Ltac withstrategy l x := let idx := smart_global:(id) in let tl := strategy_level:(transparent) in with_strategy 1 [ id id ] with_strategy l [ id id ] with_strategy tl [ id id ] with_strategy transparent [ id id ] with_strategy transparent [ id id ] with_strategy opaque [ id id ] with_strategy expand [ id id ] with_strategy transparent [ idx ] with_strategy transparent [ id x ] with_strategy transparent [ x id ] with_strategy transparent [ id ] with_strategy transparent [ id x ] with_strategy transparent [ id id ] with_strategy transparent [ id id x ] with_strategy transparent [ id ] with_strategy transparent [ id x ] with_strategy transparent [ id id ] with_strategy transparent [ id id x ] idtac File "./output/print_ltac.v", line 52, characters 29-34: The command has indeed failed with message: idnat is bound to a notation that does not denote a reference. Ltac withstrategy l x := let idx := smart_global:(id) in let tl := strategy_level:(transparent) in with_strategy 1 [ id id ] with_strategy l [ id id ] with_strategy tl [ id id ] with_strategy transparent [ id id ] with_strategy transparent [ id id ] with_strategy opaque [ id id ] with_strategy expand [ id id ] with_strategy transparent [ idx ] with_strategy transparent [ id x ] with_strategy transparent [ x id ] with_strategy transparent [ id ] with_strategy transparent [ id x ] with_strategy transparent [ id id ] with_strategy transparent [ id id x ] with_strategy transparent [ id ] with_strategy transparent [ id x ] with_strategy transparent [ id id ] with_strategy transparent [ id id x ] idtac Ltac FE.withstrategy l x := let idx := smart_global:(FE.id) in let tl := strategy_level:(transparent) in with_strategy 1 [ FE.id FE.id ] with_strategy l [ FE.id FE.id ] with_strategy tl [ FE.id FE.id ] with_strategy transparent [ FE.id FE.id ] with_strategy transparent [ FE.id FE.id ] with_strategy opaque [ FE.id FE.id ] with_strategy expand [ FE.id FE.id ] with_strategy transparent [ idx ] with_strategy transparent [ FE.id x ] with_strategy transparent [ x FE.id ] with_strategy transparent [ FE.id ] with_strategy transparent [ FE.id x ] with_strategy transparent [ FE.id FE.id ] with_strategy transparent [ FE.id FE.id x ] with_strategy transparent [ FE.id ] with_strategy transparent [ FE.id x ] with_strategy transparent [ FE.id FE.id ] with_strategy transparent [ FE.id FE.id x ] idtac rocq-9.2.0/test-suite/output/print_ltac.v000066400000000000000000000045301516144147600204750ustar00rootroot00000000000000(* Testing of various things about Print Ltac *) (* https://github.com/rocq-prover/rocq/issues/10971 *) Ltac t1 := time "my tactic" idtac. Print Ltac t1. Ltac t2 := let x := string:("my tactic") in idtac x. Print Ltac t2. Tactic Notation "idtacstr" string(str) := idtac str. Ltac t3 := idtacstr "my tactic". Print Ltac t3. (* https://github.com/rocq-prover/rocq/issues/9716 *) Ltac t4 x := match x with ?A => constr:((A, A)) end. Print Ltac t4. Abbreviation idnat := (@id nat). Abbreviation idn := id. Abbreviation idan := (@id). Fail Strategy transparent [idnat]. Strategy transparent [idn]. Strategy transparent [idan]. Ltac withstrategy l x := let idx := smart_global:(id) in let tl := strategy_level:(transparent) in with_strategy 1 [id id] ( with_strategy l [id id] ( with_strategy tl [id id] ( with_strategy 0 [id id] ( with_strategy transparent [id id] ( with_strategy opaque [id id] ( with_strategy expand [id id] ( with_strategy 0 [idx] ( with_strategy 0 [id x] ( with_strategy 0 [x id] ( with_strategy 0 [idn] ( with_strategy 0 [idn x] ( with_strategy 0 [idn id] ( with_strategy 0 [idn id x] ( with_strategy 0 [idan] ( with_strategy 0 [idan x] ( with_strategy 0 [idan id] ( with_strategy 0 [idan id x] ( idtac )))))))))))))))))). Print Ltac withstrategy. Module Type Empty. End Empty. Module E. End E. Module F (E : Empty). Definition id {T} := @id T. Abbreviation idnat := (@id nat). Abbreviation idn := id. Abbreviation idan := (@id). Fail Strategy transparent [idnat]. Strategy transparent [idn]. Strategy transparent [idan]. Ltac withstrategy l x := let idx := smart_global:(id) in let tl := strategy_level:(transparent) in with_strategy 1 [id id] ( with_strategy l [id id] ( with_strategy tl [id id] ( with_strategy 0 [id id] ( with_strategy transparent [id id] ( with_strategy opaque [id id] ( with_strategy expand [id id] ( with_strategy 0 [idx] ( with_strategy 0 [id x] ( with_strategy 0 [x id] ( with_strategy 0 [idn] ( with_strategy 0 [idn x] ( with_strategy 0 [idn id] ( with_strategy 0 [idn id x] ( with_strategy 0 [idan] ( with_strategy 0 [idan x] ( with_strategy 0 [idan id] ( with_strategy 0 [idan id x] ( idtac )))))))))))))))))). Print Ltac withstrategy. End F. Module FE := F E. Print Ltac FE.withstrategy. rocq-9.2.0/test-suite/output/qualification.out000066400000000000000000000004011516144147600215210ustar00rootroot00000000000000File "./output/qualification.v", line 20, characters 0-7: Error: Signature components for field test do not match: expected type "qualification.M2.t = qualification.M2.M.t" but found type "qualification.M2.t = qualification.M2.t". coqc exited with code 1 rocq-9.2.0/test-suite/output/qualification.v000066400000000000000000000005621516144147600211670ustar00rootroot00000000000000(* coq-prog-args: ("-top" "qualification") *) Module Type T1. Parameter t : Type. End T1. Module Type T2. Declare Module M : T1. Parameter t : Type. Parameter test : t = M.t. End T2. Module M1 <: T1. Definition t : Type := bool. End M1. Module M2 <: T2. Module M := M1. Definition t : Type := nat. Lemma test : t = t. Proof. reflexivity. Qed. End M2. rocq-9.2.0/test-suite/output/reduction.out000066400000000000000000000023251516144147600206740ustar00rootroot00000000000000 = a : nat = n + 0 : nat = S (1 + 2) : nat = S (1 + 2) : nat = S ((fix add (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (add p m) end) 1 2) : nat = 4 : nat = (fix add (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (add p m) end) 2 2 : nat = S (1 + (2 + 2)) : nat = S (1 + 2 + 2) : nat = 6 : nat = ignore (fun x : nat => 1 + x) : unit = ignore (fun x : nat => 1 + x) : unit = ignore (fun x : nat => 1 + x) : unit = ignore (fun x : nat => 1 + x) : unit - : constr = constr:(4) - : constr = constr:(2 + 2) = let x := 2 in 2 + 2 : nat = let x := 2 in 4 : nat = (let x := 2 in fun x0 : nat => 1 + x0) 2 : nat = match n with | 0 => 1 + 1 | S n => 1 + n end : nat = fix f (n : nat) : nat := match 0 + n with | 0 => 1 + 1 | S n0 => 1 + f n0 end : nat -> nat = 4%uint63 : int = add 2 x : int = 1%float : float rocq-9.2.0/test-suite/output/reduction.v000066400000000000000000000027461516144147600203410ustar00rootroot00000000000000(* Test the behaviour of hnf and simpl introduced in revision *) Parameter n:nat. Definition a:=0. Eval simpl in (fix plus (n m : nat) {struct n} : nat := match n with | 0 => m | S p => S (p + m) end) a a. Eval hnf in match (plus (S n) O) with S n => n | _ => O end. Eval simpl head in 2 + 2. Eval cbn head in 2 + 2. Eval lazy head in 2 + 2. Eval cbv head in 2 + 2. Eval lazy head delta in 2 + 2. Eval simpl head in 2 + (2 + 2). Eval simpl head in (2 + 2) + 2. Eval cbv head in (2 + 2) + 2. Axiom ignore : forall {T}, T -> unit. Eval simpl head in ignore (fun x => 1 + x). Eval cbn head in ignore (fun x => 1 + x). Eval lazy head in ignore (fun x => 1 + x). Eval cbv head in ignore (fun x => 1 + x). Require Import Ltac2.Ltac2. Ltac2 Eval eval lazy in (2 + 2). Ltac2 Eval eval lazy head in (2 + 2). (* Cbv examples *) Eval cbv head beta delta iota in let x := 1 + 1 in 2 + 2. (* not fully clear what head w/o zeta should be *) Eval cbv beta delta iota in let x := 1 + 1 in 2 + 2. (* not fully clear what head w/o zeta should be *) Eval cbv head beta delta iota in (let x := 1 + 1 in fun x => 1 + x) 2. (* not fully clear whether we should apply commutative cuts or not *) Eval cbv head in match 0 + n with 0 => 1 + 1 | S n => 1 + n end. Eval cbv head in fix f n := match 0 + n with 0 => 1 + 1 | S n => 1 + f n end. Require Import PrimInt63. Eval cbv head in PrimInt63.add 2 2. Parameter x:int. Eval cbv head in PrimInt63.add 2 x. Require Import PrimFloat. Eval cbv head in 0x1p+0%float. rocq-9.2.0/test-suite/output/relaxed_ambiguous_paths.out000066400000000000000000000061001516144147600235710ustar00rootroot00000000000000File "./output/relaxed_ambiguous_paths.v", line 13, characters 0-29: Warning: New coercion path [g1; f2] : A >-> B' is ambiguous with existing [f1; g2] : A >-> B'. [ambiguous-paths,coercions,default] File "./output/relaxed_ambiguous_paths.v", line 14, characters 0-29: Warning: New coercion path [h1; f3] : B >-> C' is ambiguous with existing [f2; h2] : B >-> C'. [ambiguous-paths,coercions,default] [f1] : A >-> A' [g1] : A >-> B [f1; g2] : A >-> B' [g1; h1] : A >-> C [f1; g2; h2] : A >-> C' [g2] : A' >-> B' [g2; h2] : A' >-> C' [f2] : B >-> B' [h1] : B >-> C [f2; h2] : B >-> C' [h2] : B' >-> C' [f3] : C >-> C' [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget File "./output/relaxed_ambiguous_paths.v", line 33, characters 0-28: Warning: New coercion path [ab; bc] : A >-> C is ambiguous with existing [ac] : A >-> C. [ambiguous-paths,coercions,default] [ab] : A >-> B [ac] : A >-> C [ac; cd] : A >-> D [bc] : B >-> C [bc; cd] : B >-> D [cd] : C >-> D [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget File "./output/relaxed_ambiguous_paths.v", line 50, characters 0-28: Warning: New coercion path [ab; bc] : A >-> C is ambiguous with existing [ac] : A >-> C. [ambiguous-paths,coercions,default] File "./output/relaxed_ambiguous_paths.v", line 51, characters 0-28: Warning: New coercion path [ba; ab] : B >-> B is not definitionally an identity function. New coercion path [ab; ba] : A >-> A is not definitionally an identity function. [ambiguous-paths,coercions,default] [ab] : A >-> B [ac] : A >-> C [ba] : B >-> A [bc] : B >-> C [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget [B_A] : B >-> A [C_A] : C >-> A [D_A] : D >-> A [D_B] : D >-> B [D_C] : D >-> C [A'_A] : A' >-> A [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget [B_A'; A'_A] : B >-> A [B_A'] : B >-> A' [C_A'; A'_A] : C >-> A [C_A'] : C >-> A' [D_A] : D >-> A [D_B; B_A'] : D >-> A' [D_B] : D >-> B [D_C] : D >-> C File "./output/relaxed_ambiguous_paths.v", line 147, characters 0-86: Warning: New coercion path [D_C; C_A'] : D >-> A' is ambiguous with existing [D_B; B_A'] : D >-> A'. [ambiguous-paths,coercions,default] [reverse_coercion] : ReverseCoercionSource >-> ReverseCoercionTarget [A'_A] : A' >-> A [B_A'; A'_A] : B >-> A [B_A'] : B >-> A' [C_A'; A'_A] : C >-> A [C_A'] : C >-> A' [D_A] : D >-> A [D_B; B_A'] : D >-> A' [D_B] : D >-> B [D_C] : D >-> C File "./output/relaxed_ambiguous_paths.v", line 156, characters 0-47: Warning: New coercion path [unwrap_nat; wrap_nat] : NAT >-> NAT is not definitionally an identity function. [ambiguous-paths,coercions,default] File "./output/relaxed_ambiguous_paths.v", line 157, characters 0-64: Warning: New coercion path [unwrap_list; wrap_list] : LIST >-> LIST is not definitionally an identity function. [ambiguous-paths,coercions,default] File "./output/relaxed_ambiguous_paths.v", line 158, characters 0-51: Warning: New coercion path [unwrap_Type; wrap_Type] : TYPE >-> TYPE is not definitionally an identity function. [ambiguous-paths,coercions,default] rocq-9.2.0/test-suite/output/relaxed_ambiguous_paths.v000066400000000000000000000072701516144147600232400ustar00rootroot00000000000000Module test1. Section test1. Variable (A B C A' B' C' : Type). Variable (f1 : A -> A') (f2 : B -> B') (f3 : C -> C'). Variable (g1 : A -> B) (g2 : A' -> B') (h1 : B -> C) (h2 : B' -> C'). Local Coercion g1 : A >-> B. Local Coercion g2 : A' >-> B'. Local Coercion h1 : B >-> C. Local Coercion h2 : B' >-> C'. Local Coercion f1 : A >-> A'. Local Coercion f2 : B >-> B'. Local Coercion f3 : C >-> C'. (* [g1; h1; f3], [f1; g2; h2] : A >-> C' should not be reported as ambiguous *) (* paths because they are redundant with `[g1; f2], [f1; g2] : A >-> B'` and *) (* `[h1; f3], [f2; h2] : B >-> C'`. *) Print Graph. End test1. End test1. Module test2. Section test2. Variable (A B C D : Type). Variable (ab : A -> B) (bc : B -> C) (ac : A -> C) (cd : C -> D). Local Coercion ac : A >-> C. Local Coercion cd : C >-> D. Local Coercion ab : A >-> B. Local Coercion bc : B >-> C. (* `[ab; bc; cd], [ac; cd] : A >-> D` should not be reported as ambiguous *) (* paths because they are redundant with `[ab; bc], [ac] : A >-> C`. *) Print Graph. End test2. End test2. Module test3. Section test3. Variable (A B C : Type). Variable (ab : A -> B) (ba : B -> A) (ac : A -> C) (bc : B -> C). Local Coercion ac : A >-> C. Local Coercion bc : B >-> C. Local Coercion ab : A >-> B. Local Coercion ba : B >-> A. (* `[ba; ac], [bc] : B >-> C` should not be reported as ambiguous paths *) (* because they are redundant with `[ab; bc], [ac] : A >-> C` and *) (* `[ba; ab] : B >-> B`. *) Print Graph. End test3. End test3. Module test4. Section test4. Variable (A : Type) (P Q : A -> Prop). Record B := { B_A : A; B_P : P B_A }. Record C := { C_A : A; C_Q : Q C_A }. Record D := { D_A : A; D_P : P D_A; D_Q : Q D_A }. Local Coercion B_A : B >-> A. Local Coercion C_A : C >-> A. Local Coercion D_A : D >-> A. Local Coercion D_B (d : D) : B := Build_B (D_A d) (D_P d). Local Coercion D_C (d : D) : C := Build_C (D_A d) (D_Q d). Print Graph. End test4. End test4. Module test5. Section test5. Variable (A : Type) (P Q : A -> Prop). Definition A' (x : bool) := A. Record B (x : bool) := { B_A' : A' x; B_P : P B_A' }. Record C (x : bool) := { C_A' : A' x; C_Q : Q C_A' }. Record D := { D_A : A; D_P : P D_A; D_Q : Q D_A }. Local Coercion A'_A (x : bool) (a : A' x) : A := a. Local Coercion B_A' : B >-> A'. Local Coercion C_A' : C >-> A'. Local Coercion D_A : D >-> A. Local Coercion D_B (d : D) : B false := Build_B false (D_A d) (D_P d). Local Coercion D_C (d : D) : C true := Build_C true (D_A d) (D_Q d). Print Graph. End test5. End test5. Module test6. Section test6. Variable (A : Type) (P Q : A -> Prop). Record A' (x : bool) := { A'_A : A }. Record B (x : bool) := { B_A' : A' x; B_P : P (A'_A x B_A') }. Record C (x : bool) := { C_A' : A' x; C_Q : Q (A'_A x C_A') }. Record D := { D_A : A; D_P : P D_A; D_Q : Q D_A }. Local Coercion A'_A : A' >-> A. Local Coercion B_A' : B >-> A'. Local Coercion C_A' : C >-> A'. Local Coercion D_A : D >-> A. Local Coercion D_B (d : D) : B false := Build_B false (Build_A' false (D_A d)) (D_P d). Local Coercion D_C (d : D) : C true := Build_C true (Build_A' true (D_A d)) (D_Q d). Print Graph. End test6. End test6. Module test7. Record > NAT := wrap_nat { unwrap_nat :> nat }. Record > LIST (T : Type) := wrap_list { unwrap_list :> list T }. Record > TYPE := wrap_Type { unwrap_Type :> Type }. End test7. Module test8. Set Primitive Projections. Record > NAT_prim := wrap_nat { unwrap_nat :> nat }. Record > LIST_prim (T : Type) := wrap_list { unwrap_list :> list T }. Record > TYPE_prim := wrap_Type { unwrap_Type :> Type }. End test8. rocq-9.2.0/test-suite/output/reverse_coercions.out000066400000000000000000000001501516144147600224110ustar00rootroot00000000000000nat : S : S reverse_coercion S_nat nat : S : S @reverse_coercion S Set S_nat nat : S : S rocq-9.2.0/test-suite/output/reverse_coercions.v000066400000000000000000000003231516144147600220510ustar00rootroot00000000000000Structure S := { ssort :> Type; sstuff : ssort; }. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. Check nat : S. Set Printing Coercions. Check nat : S. Set Printing All. Check nat : S. rocq-9.2.0/test-suite/output/rewrite_2172.out000066400000000000000000000002251516144147600210310ustar00rootroot00000000000000File "./output/rewrite_2172.v", line 21, characters 7-23: The command has indeed failed with message: Unable to find an instance for the variable E. rocq-9.2.0/test-suite/output/rewrite_2172.v000066400000000000000000000013451516144147600204730ustar00rootroot00000000000000(* This checks an error message as reported in bug #2172 *) Axiom axiom : forall (E F : nat), E = F. Lemma test : forall (E F : nat), E = F. Proof. intros. (* This used to raise the following non understandable error message: Error: Unable to find an instance for the variable x The reason this error was that rewrite generated the proof "eq_ind ?A ?x ?P ? ?y (axiom ?E ?F)" and the equation ?x=?E was solved in the way ?E:=?x leaving ?x unresolved. A stupid hack for solve this consisted in ordering meta=meta equations the other way round (with most recent evars instantiated first - since they are assumed to come first from the user in rewrite/induction/destruct calls). *) Fail rewrite <- axiom. Abort. rocq-9.2.0/test-suite/output/rewrite_strat.out000066400000000000000000000021461516144147600215770ustar00rootroot00000000000000Ltac k1 := rewrite_strat subterms id; choice (subterm fail) fail; fail Ltac k2 := rewrite_strat subterms id; choice (subterm fail) fail; fail Ltac k3 := rewrite_strat subterms id; (choice (subterm fail) fail; fail) Ltac k4 := rewrite_strat subterms (id; choice (subterm fail) fail; fail) Ltac k5 := rewrite_strat subterms subterms fail; subterms subterms fail; choice (subterms try fail; subterms repeat fail) Ltac mytry rewstrategy1 := rewrite_strat choice (rewstrategy1) id Ltac myany rewstrategy1 := rewrite_strat fix fixident := try (rewstrategy1; fixident) Ltac myrepeat rewstrategy1 := rewrite_strat rewstrategy1; any rewstrategy1 Ltac mybottomup rewstrategy1 := rewrite_strat fix fixident := (choice (progress subterms fixident) (rewstrategy1); try fixident) Ltac mytopdown rewstrategy1 := rewrite_strat fix fixident := (choice (rewstrategy1) (progress subterms fixident); try fixident) Ltac myinnermost rewstrategy1 := rewrite_strat fix fixident := choice (subterm fixident) (rewstrategy1) Ltac myoutermost rewstrategy1 := rewrite_strat fix fixident := choice (rewstrategy1) (subterm fixident) rocq-9.2.0/test-suite/output/rewrite_strat.v000066400000000000000000000025121516144147600212320ustar00rootroot00000000000000Ltac k1 := rewrite_strat (subterms id; (choice (subterm fail) fail)); fail. Print Ltac k1. Ltac k2 := rewrite_strat subterms id; (choice (subterm fail) fail); fail. Print Ltac k2. Ltac k3 := rewrite_strat subterms id; ((choice (subterm fail) fail); fail). Print Ltac k3. Ltac k4 := rewrite_strat subterms (id; choice (subterm fail) fail; fail). Print Ltac k4. Ltac k5 := rewrite_strat (subterms subterms fail; subterms subterms fail); choice (subterms try fail; subterms repeat fail). Print Ltac k5. Ltac mytry rewstrategy1 := rewrite_strat choice (rewstrategy1) id. Print Ltac mytry. Ltac myany rewstrategy1 := rewrite_strat fix fixident := try (rewstrategy1 ; fixident). Print Ltac myany. Ltac myrepeat rewstrategy1 := rewrite_strat (rewstrategy1; any rewstrategy1). Print Ltac myrepeat. Ltac mybottomup rewstrategy1 := rewrite_strat fix fixident := (choice (progress subterms fixident) (rewstrategy1) ; try fixident). Print Ltac mybottomup. Ltac mytopdown rewstrategy1 := rewrite_strat fix fixident := (choice (rewstrategy1) (progress subterms fixident) ; try fixident). Print Ltac mytopdown. Ltac myinnermost rewstrategy1 := rewrite_strat fix fixident := choice (subterm fixident) (rewstrategy1). Print Ltac myinnermost. Ltac myoutermost rewstrategy1 := rewrite_strat fix fixident := choice (rewstrategy1) (subterm fixident). Print Ltac myoutermost. rocq-9.2.0/test-suite/output/section_have.out000066400000000000000000000002021516144147600213370ustar00rootroot00000000000000toto = ssr_have I (fun y : True => conj y y) : True /\ True toto = ssr_have I (fun y : True => conj y y) : True /\ True rocq-9.2.0/test-suite/output/section_have.v000066400000000000000000000002511516144147600210010ustar00rootroot00000000000000Require Import ssreflect. Section Foo. Variable x : nat. Lemma toto : True /\ True. Proof. have y : True by []. by split. Qed. Print toto. End Foo. Print toto. rocq-9.2.0/test-suite/output/set.out000066400000000000000000000004131516144147600174670ustar00rootroot000000000000001 goal y1 := 0 : nat x := 0 + 0 : nat ============================ x = x 1 goal y1, y2 := 0 : nat x := y2 + 0 : nat ============================ x = x 1 goal y1, y2, y3 := 0 : nat x := y2 + y3 : nat ============================ x = x rocq-9.2.0/test-suite/output/set.v000066400000000000000000000002321516144147600171240ustar00rootroot00000000000000Goal let x:=O+O in x=x. intro. set (y1:=O) in (type of x). Show. set (y2:=O) in (value of x) at 1. Show. set (y3:=O) in (value of x). Show. trivial. Qed. rocq-9.2.0/test-suite/output/signatureT.out000066400000000000000000000000001516144147600210110ustar00rootroot00000000000000rocq-9.2.0/test-suite/output/signatureT.v000066400000000000000000000000571516144147600204630ustar00rootroot00000000000000From Corelib Require Import Setoid CMorphisms. rocq-9.2.0/test-suite/output/smartlocate.out000066400000000000000000000005401516144147600212130ustar00rootroot00000000000000File "./output/smartlocate.v", line 1, characters 11-15: The command has indeed failed with message: Unable to unambiguously interpret "<>" as a reference. Found: Notation "x <> y" := (not (eq x y)) File "./output/smartlocate.v", line 2, characters 11-26: The command has indeed failed with message: Unable to interpret "'nonexistent'" as a reference. rocq-9.2.0/test-suite/output/smartlocate.v000066400000000000000000000000551516144147600206520ustar00rootroot00000000000000Fail Print "<>". Fail Print "'nonexistent'". rocq-9.2.0/test-suite/output/sort_poly_elim_error.out000066400000000000000000000017621516144147600231550ustar00rootroot00000000000000File "./output/sort_poly_elim_error.v", line 8, characters 0-108: The command has indeed failed with message: Incorrect elimination of "p" in the inductive type "sum@{Prop ; sort_poly_elim_error.23 sort_poly_elim_error.24}": the return type has sort "Type" while it should be SProp or Prop. Elimination of an inductive object of sort Prop is not allowed on a predicate in sort "Type" because proofs can be eliminated only to build proofs. File "./output/sort_poly_elim_error.v", line 17, characters 0-106: The command has indeed failed with message: Elimination constraints are not implied by the ones declared: s' -> s File "./output/sort_poly_elim_error.v", line 23, characters 0-37: The command has indeed failed with message: Incorrect elimination of "sC" in the inductive type "sP": the return type has sort "Prop" while it should be SProp. Elimination of an inductive object of sort SProp is not allowed on a predicate in sort "Prop" because strict proofs can be eliminated only to build strict proofs. rocq-9.2.0/test-suite/output/sort_poly_elim_error.v000066400000000000000000000020111516144147600225770ustar00rootroot00000000000000Set Universe Polymorphism. Inductive sum@{s;u v|} (A : Type@{s;u}) (B : Type@{s;v}) : Type@{s;max(u,v)} := | inl : A -> sum A B | inr : B -> sum A B. Arguments inl {A B}. Arguments inr {A B}. Fail Check (fun p : sum@{Prop;_ _} True False => match p return Set with inl a => unit | inr b => bool end). (* Error: The quality constraints are inconsistent: cannot enforce Prop -> Type because it would identify Type and Prop which is inconsistent. This is introduced by the constraints Prop -> Type *) Inductive sBox@{s s';u|} (A:Type@{s;u}) : Type@{s';u} := sbox (_:A). Fail Definition elim@{s s';u|} (A:Type@{s;u}) (x:sBox@{s s';u} A) : A := match x with sbox _ v => v end. (* Error: Elimination constraints are not implied by the ones declared: s' -> s *) Inductive sP : SProp := sC. Fail Check match sC with sC => I end. (* Error: The quality constraints are inconsistent: cannot enforce SProp -> Prop because it would identify Prop and SProp which is inconsistent. This is introduced by the constraints SProp -> Prop *) rocq-9.2.0/test-suite/output/ssr_clear.out000066400000000000000000000002061516144147600206510ustar00rootroot00000000000000File "./output/ssr_clear.v", line 5, characters 5-26: The command has indeed failed with message: No assumption is named NO_SUCH_NAME rocq-9.2.0/test-suite/output/ssr_clear.v000066400000000000000000000001411516144147600203050ustar00rootroot00000000000000Require Import ssreflect. Example foo : True -> True. Proof. Fail move=> {NO_SUCH_NAME}. Abort. rocq-9.2.0/test-suite/output/ssr_error_multiple_intro_after_case.out000066400000000000000000000002131516144147600262140ustar00rootroot00000000000000File "./output/ssr_error_multiple_intro_after_case.v", line 3, characters 5-16: The command has indeed failed with message: x already used rocq-9.2.0/test-suite/output/ssr_error_multiple_intro_after_case.v000066400000000000000000000001251516144147600256540ustar00rootroot00000000000000Require Import ssreflect. Goal forall p : nat * nat , True. Fail case => x x. Abort. rocq-9.2.0/test-suite/output/ssr_explain_match.out000066400000000000000000000047341516144147600224110ustar00rootroot00000000000000File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ - _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ < _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ >= _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ > _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ <= _ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ < _ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ <= _ < _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ < _ < _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ + _" was already used in scope nat_scope. [notation-overridden,parsing,default] File "./output/ssr_explain_match.v", line 12, characters 0-61: Warning: Notation "_ * _" was already used in scope nat_scope. [notation-overridden,parsing,default] BEGIN INSTANCES instance: (x + y + z) matches: (x + y + z) instance: (x + y) matches: (x + y) instance: (x + y) matches: (x + y) END INSTANCES BEGIN INSTANCES instance: (addnC (x + y) z) matches: (x + y + z) instance: (addnC x y) matches: (x + y) instance: (addnC x y) matches: (x + y) END INSTANCES BEGIN INSTANCES instance: (addnA x y z) matches: (x + y + z) END INSTANCES BEGIN INSTANCES instance: (addnA x y z) matches: (x + y + z) instance: (addnC z (x + y)) matches: (x + y + z) instance: (addnC y x) matches: (x + y) instance: (addnC y x) matches: (x + y) END INSTANCES File "./output/ssr_explain_match.v", line 22, characters 5-38: The command has indeed failed with message: Not supported rocq-9.2.0/test-suite/output/ssr_explain_match.v000066400000000000000000000020111516144147600220310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop), (forall x : T1, P1 x) -> {in D1, forall x : T1, P1 x} rocq-9.2.0/test-suite/output/ssr_pred.v000066400000000000000000000000671516144147600201600ustar00rootroot00000000000000Require Import ssreflect ssrfun ssrbool. Check @in1W. rocq-9.2.0/test-suite/output/ssr_under.out000066400000000000000000000001761516144147600207060ustar00rootroot00000000000000'Under[ m - m ] (G (fun _ : nat => 0) n >= 0) 'Under[ r = R0 \/ E r ] (Rbar_le Rbar0 (Lub_Rbar (fun r : R => r = R0 \/ E r))) rocq-9.2.0/test-suite/output/ssr_under.v000066400000000000000000000014521516144147600203420ustar00rootroot00000000000000From Corelib Require Import ssreflect. Axiom subnn : forall n : nat, n - n = 0. Parameter G : (nat -> nat) -> nat -> nat. Axiom eq_G : forall F1 F2 : nat -> nat, (forall n : nat, F1 n = F2 n) -> forall n : nat, G F1 n = G F2 n. Ltac show := match goal with [|-?g] => idtac g end. Lemma example_G (n : nat) : G (fun n => n - n) n >= 0. under eq_G => m do [show; rewrite subnn]. show. Abort. Parameters (R Rbar : Set) (R0 : R) (Rbar0 : Rbar). Parameter Rbar_le : Rbar -> Rbar -> Prop. Parameter Lub_Rbar : (R -> Prop) -> Rbar. Parameter Lub_Rbar_eqset : forall E1 E2 : R -> Prop, (forall x : R, E1 x <-> E2 x) -> Lub_Rbar E1 = Lub_Rbar E2. Lemma test_Lub_Rbar (E : R -> Prop) : Rbar_le Rbar0 (Lub_Rbar (fun x => x = R0 \/ E x)). Proof. under Lub_Rbar_eqset => r do show. show. Abort. rocq-9.2.0/test-suite/output/subst.out000066400000000000000000000011451516144147600200370ustar00rootroot000000000000001 goal y, z : nat Hy : y = 0 Hz : z = 0 H1 : 0 = 1 HA : True H2 : 0 = 2 H3 : y = 3 HB : True H4 : z = 4 ============================ True 1 goal x, z : nat Hx : x = 0 Hz : z = 0 H1 : x = 1 HA : True H2 : x = 2 H3 : 0 = 3 HB : True H4 : z = 4 ============================ True 1 goal x, y : nat Hx : x = 0 Hy : y = 0 H1 : x = 1 HA : True H2 : x = 2 H3 : y = 3 HB : True H4 : 0 = 4 ============================ True 1 goal H1 : 0 = 1 HA : True H2 : 0 = 2 H3 : 0 = 3 HB : True H4 : 0 = 4 ============================ True rocq-9.2.0/test-suite/output/subst.v000066400000000000000000000017351516144147600175020ustar00rootroot00000000000000(* Ensure order of hypotheses is respected after "subst" *) Abbreviation goal := (forall x y z, x = 0 -> y = 0 -> z = 0 -> x = 1 -> True -> x = 2 -> y = 3 -> True -> z = 4 -> True) (only parsing). Ltac do_intros := intros * Hx Hy Hz H1 HA H2 H3 HB H4. Goal goal. do_intros. (* From now on, the order after subst is consistently H1, HA, H2, H3, HB, H4 *) subst x. (* In 8.4 or 8.5 without regular subst tactic mode, the order was HA, H3, HB, H4, H1, H2 *) Show. Abort. Goal goal. do_intros. subst y. (* In 8.4 or 8.5 without regular subst tactic mode, the order was H1, HA, H2, HB, H4, H3 *) Show. Abort. Goal goal. do_intros. subst z. (* In 8.4 or 8.5 without regular subst tactic mode, the order was H1, HA, H2, H3, HB, H4 *) Show. Abort. Goal goal. do_intros. subst. (* In 8.4 or 8.5 without regular subst tactic mode, the order was HA, HB, H4, H3, H1, H2 *) (* In 8.5pl0 and 8.5pl1 with regular subst tactic mode, the order was HA, HB, H1, H2, H3, H4 *) Show. trivial. Qed. rocq-9.2.0/test-suite/output/undeclared_key.out000066400000000000000000000017701516144147600216610ustar00rootroot00000000000000File "./output/undeclared_key.v", line 1, characters 0-28: The command has indeed failed with message: There is no flag, option or table with this name: "Search Blacklists". File "./output/undeclared_key.v", line 2, characters 0-35: The command has indeed failed with message: There is no qualid-valued table with this name: "Search Blacklist". File "./output/undeclared_key.v", line 3, characters 0-22: Warning: There is no flag or option with this name: "Search Blacklists". [unknown-option,default] File "./output/undeclared_key.v", line 4, characters 0-40: The command has indeed failed with message: There is no string-valued table with this name: "Search Blacklists". File "./output/undeclared_key.v", line 5, characters 0-39: The command has indeed failed with message: There is no qualid-valued table with this name: "Search Blacklist". File "./output/undeclared_key.v", line 6, characters 0-36: The command has indeed failed with message: There is no qualid-valued table with this name: "Search Blacklist". rocq-9.2.0/test-suite/output/undeclared_key.v000066400000000000000000000003161516144147600213120ustar00rootroot00000000000000Fail Test Search Blacklists. Fail Test Search Blacklist for foo. Set Search Blacklists. Fail Remove Search Blacklists "bar" foo. Fail Remove Search Blacklist "bar" foo. Fail Add Search Blacklist "bar" foo. rocq-9.2.0/test-suite/output/unidecls.out000066400000000000000000000044541516144147600205130ustar00rootroot00000000000000Set < nat_rect.u0 < decls.a < decls.b < a a < decls.a Type@{a} : Type@{a+1} Type@{decls.a} : Type@{decls.a+1} Type@{decls.b} : Type@{decls.b+1} File "./output/unidecls.v", line 25, characters 17-24: The command has indeed failed with message: Undeclared universe decls.c. File "./output/unidecls.v", line 27, characters 17-18: The command has indeed failed with message: Undeclared universe: i. Type@{foo} : Type@{foo+1} Type@{bar} : Type@{bar+1} Type@{Foo.bar} : Type@{Foo.bar+1} Type@{Foo.foo} : Type@{Foo.foo+1} Type@{foo} : Type@{foo+1} Type@{foo} : Type@{foo+1} File "./output/unidecls.v", line 52, characters 2-23: The command has indeed failed with message: Universe secfoo already exists. File "./output/unidecls.v", line 54, characters 19-31: The command has indeed failed with message: Undeclared universe Foo'.secfoo2. Type@{secfoo2} : Type@{secfoo2+1} Type@{secfoo2} : Type@{secfoo2+1} File "./output/unidecls.v", line 60, characters 21-46: The command has indeed failed with message: Unknown interpretation for notation "_ = _". File "./output/unidecls.v", line 72, characters 19-22: The command has indeed failed with message: Undeclared universe A.u. Type@{Arg.u} : Type@{Arg.u+1} File "./output/unidecls.v", line 79, characters 59-60: The command has indeed failed with message: In environment A : Type@{v} The term "A" has type "Type@{v}" while it is expected to have type "Type@{Arg.u}" (universe inconsistency: Cannot enforce v <= Arg.u because Arg.u < v). File "./output/unidecls.v", line 93, characters 17-24: The command has indeed failed with message: Undeclared universe FnApp.v. Type@{Fn.v} : Type@{Fn.v+1} FnApp.foo : Type@{Fn.v} FnApp.bar : Type@{Arg.u} File "./output/unidecls.v", line 99, characters 17-26: The command has indeed failed with message: Undeclared universe ArgImpl.u. FnApp2.foo : Type@{Fn.v} FnApp2.bar : Type@{Arg.u} File "./output/unidecls.v", line 113, characters 17-21: The command has indeed failed with message: Undeclared universe: poly. Set < nat_rect.u0 < decls.a < decls.b < a < foo < Foo.foo < Foo.bar < bar < secfoo < secfoo2 < Arg.u < Fn.v a < decls.a secfoo2 < a Arg.u < Fn.v id@{Set} nat : nat -> nat id@{Set} : forall A : Set, A -> A rocq-9.2.0/test-suite/output/unidecls.v000066400000000000000000000043411516144147600201440ustar00rootroot00000000000000(* -*- coq-prog-args: ("-noinit" "-top" "unidecls"); -*- *) Require Import Notations Ltac. Notation "a -> b" := (forall _:a, b). Set Printing Universes. Inductive nat := O | S : nat -> nat. Module decls. Universes a b. End decls. Universe a. Constraint a < decls.a. Print Universes. (** These are different universes *) Check Type@{a}. Check Type@{decls.a}. Check Type@{decls.b}. Fail Check Type@{decls.c}. Fail Check Type@{i}. Universe foo. Module Foo. (** Already declared globaly: but universe names are scoped at the module level *) Universe foo. Universe bar. Check Type@{Foo.foo}. Definition bar := O. End Foo. (** Already declared in the module *) Universe bar. (** Accessible outside the module: universe declarations are global *) Check Type@{bar}. Check Type@{Foo.bar}. Check Type@{Foo.foo}. (** The same *) Check Type@{foo}. Check Type@{unidecls.foo}. Universe secfoo. Section Foo'. Fail Universe secfoo. Universe secfoo2. Fail Check Type@{Foo'.secfoo2}. Check Type@{secfoo2}. Constraint secfoo2 < a. End Foo'. Check Type@{secfoo2}. Fail Check eq_refl : Type@{secfoo2} = Type@{a}. (** Below, u and v are global, fixed universes *) Module Type Arg. Universe u. Parameter T: Type@{u}. End Arg. Module Fn(A : Arg). Universes v. (* univ names are not substitutive *) Fail Check Type@{A.u}. Check Type@{Arg.u}. Constraint Arg.u < v. Definition foo : Type@{v} := nat. Definition bar : Type@{Arg.u} := nat. Definition foo'(A : Type@{v}) : Type@{Arg.u}. Fail exact A. Abort. End Fn. Module ArgImpl : Arg. Definition T := nat. End ArgImpl. Module ArgImpl2 : Arg. Definition T := nat. End ArgImpl2. (** Two applications of the functor result in the exact same universes *) Module FnApp := Fn(ArgImpl). Fail Check Type@{FnApp.v}. Check Type@{Fn.v}. Check FnApp.foo. Check FnApp.bar. (* "module M : T" does not produce a universe M.u from T.u *) Fail Check Type@{ArgImpl.u}. Module FnApp2 := Fn(ArgImpl). Check FnApp2.foo. Check FnApp2.bar. Set Universe Polymorphism. Section PS. Universe poly. Definition id (A : Type@{poly}) (a : A) : A := a. End PS. (** The universe is polymorphic and discharged, does not persist *) Fail Check Type@{poly}. Print Universes. Check id nat. Check id@{Set}. rocq-9.2.0/test-suite/output/unifconstraints.out000066400000000000000000000036121516144147600221310ustar00rootroot000000000000003 focused goals (shelved: 1) ============================ ?Goal 0 goal 2 is: forall n : nat, ?Goal n -> ?Goal (S n) goal 3 is: nat unification constraint: ?Goal ?Goal2 <= True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier 3 focused goals (shelved: 1) n, m : nat ============================ ?Goal@{n:=n; m:=m} 0 goal 2 is: forall n0 : nat, ?Goal@{n:=n; m:=m} n0 -> ?Goal@{n:=n; m:=m} (S n0) goal 3 is: nat unification constraint: ?Goal@{n:=n; m:=m} ?Goal2@{n:=n; m:=m} <= True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier 3 focused goals (shelved: 1) m : nat ============================ ?Goal1@{m:=m} 0 goal 2 is: forall n0 : nat, ?Goal1@{m:=m} n0 -> ?Goal1@{m:=m} (S n0) goal 3 is: nat unification constraint: n, m : nat |- ?Goal1@{m:=m} ?Goal0@{n:=n; m:=m} <= True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier 3 focused goals (shelved: 1) m : nat ============================ ?Goal0@{m:=m} 0 goal 2 is: forall n0 : nat, ?Goal0@{m:=m} n0 -> ?Goal0@{m:=m} (S n0) goal 3 is: nat unification constraint: n, m : nat |- ?Goal0@{m:=m} ?Goal2@{n:=n} <= True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier File "./output/unifconstraints.v", line 29, characters 56-57: The command has indeed failed with message: In environment P : nat -> Type x : nat h : P x Unable to unify "P x" with "?P x" (unable to find a well-typed instantiation for "?P": cannot ensure that "nat -> Type" is a subtype of "nat -> Prop"). File "./output/unifconstraints.v", line 37, characters 5-15: The command has indeed failed with message: Tactic failure: congruence failed (cannot build a well-typed proof). rocq-9.2.0/test-suite/output/unifconstraints.v000066400000000000000000000021371516144147600215700ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "no") -*- *) (* Set Printing Existential Instances. *) Unset Solve Unification Constraints. Axiom veeryyyyyyyyyyyyloooooooooooooonggidentifier : nat. Goal True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier. refine (nat_rect _ _ _ _). Show. Admitted. Set Printing Existential Instances. Goal forall n m : nat, True /\ True /\ True \/ veeryyyyyyyyyyyyloooooooooooooonggidentifier = veeryyyyyyyyyyyyloooooooooooooonggidentifier. intros. refine (nat_rect _ _ _ _). Show. clear n. Show. 3:clear m. Show. Admitted. Unset Printing Existential Instances. (* Check non regression of error message (the example can eventually improve though and succeed) *) Fail Check fun (P : _ -> Type) (x:nat) (h:P x) => exist _ x (h : P x). (* A test about universe level unification in congruence *) Set Universe Polymorphism. Section S. Polymorphic Universes i j. Goal Type@{i} -> (Type@{j} : Type@{i}). Fail congruence. Abort. End S. rocq-9.2.0/test-suite/output/unification.out000066400000000000000000000020721516144147600212070ustar00rootroot00000000000000File "./output/unification.v", line 9, characters 35-39: The command has indeed failed with message: In environment x : T T : Type a : T Unable to unify "T" with "?X@{x0:=x; x:=C a}" (cannot instantiate "?X" because "T" is not in its scope: available arguments are "x" "C a"). File "./output/unification.v", line 12, characters 12-14: The command has indeed failed with message: The term "id" has type "ID" while it is expected to have type "Type -> ?T" (cannot instantiate "?T" because "A" is not in its scope). 1 focused goal (shelved: 1) H : forall x : nat, S (S (S x)) = x ============================ ?x = 0 1 focused goal (shelved: 1) H : forall x : nat, S (S (S x)) = x ============================ ?x = 0 1 focused goal (shelved: 1) H : forall x : nat, S (S (S x)) = x ============================ ?x = 0 1 focused goal (shelved: 1) H : forall x : nat, S x = x ============================ ?y = 0 1 focused goal (shelved: 3) T : Prop H : forall Q R S : Prop, (Q /\ R) /\ S -> T ============================ (?Q /\ ?R) /\ ?S rocq-9.2.0/test-suite/output/unification.v000066400000000000000000000016651516144147600206540ustar00rootroot00000000000000(* coq-prog-args: ("-async-proofs" "off") *) (* Unification error tests *) Module A. (* Check regression of an UNBOUND_REL bug *) Inductive T := C : forall {A}, A -> T. Fail Check fun x => match x return ?[X] with C a => a end. (* Bug #3634 *) Fail Check (id:Type -> _). End A. (* Choice of evar names *) Goal (forall x, S (S (S x)) = x) -> exists x, S x = 0. eexists. rewrite H. Show. Abort. Goal (forall x, S (S (S x)) = x) -> exists x, S x = 0. eexists ?[x]. rewrite H. Show. Abort. Goal (forall x, S (S (S x)) = x) -> exists x, S x = 0. eexists ?[y]. rewrite H. Show. reflexivity. Qed. (* Preserve the name if there is one *) Goal (forall x, S x = x) -> exists x, S x = 0. eexists ?[y]. rewrite H. Show. reflexivity. Qed. (* Use names also when instantiating an existing evar *) Lemma L (T : Prop) (H : forall Q R S : Prop, (Q /\ R) /\ S -> T) : exists P:Prop, (P -> T) /\ P. Proof. eexists ?[P]. split. - apply H. - Show. Abort. rocq-9.2.0/test-suite/output/unsat_constraints.out000066400000000000000000000003031516144147600224530ustar00rootroot00000000000000File "./output/unsat_constraints.v", line 22, characters 2-15: The command has indeed failed with message: Unsatisfied constraints: v < w u <= w (maybe a bugged tactic). rocq-9.2.0/test-suite/output/unsat_constraints.v000066400000000000000000000010101516144147600221050ustar00rootroot00000000000000Require Import Ltac2.Ltac2. Import Constr. Import Unsafe. Polymorphic Axiom foo@{u v w | u < v, u <= w, v < w} : Prop. Polymorphic Axiom bar@{u v w | } : Prop. Universes u v w. Constraint u < v. Lemma baz : Prop. Proof. (* easiest way to get unsatisfied constraints *) match kind 'bar@{u v w}, kind 'foo with | Constant _ u, Constant c _ => Std.exact_no_check (make (Constant c u)) | _ => Control.throw Assertion_failure end. (* should mention u <= w and v < w but not u < v *) Fail Defined. Abort. rocq-9.2.0/test-suite/output/wish_17316.out000066400000000000000000000002311516144147600204050ustar00rootroot00000000000000Notation "%" := 0 (default interpretation) (only printing) (from wish_17316) Notation "%" := 0 (default interpretation) (only parsing) (from wish_17316) rocq-9.2.0/test-suite/output/wish_17316.v000066400000000000000000000001211516144147600200410ustar00rootroot00000000000000Notation "%" := 0 (only printing). Notation "%" := 0 (only parsing). Locate "%". rocq-9.2.0/test-suite/output/wish_17985.out000066400000000000000000000002271516144147600204260ustar00rootroot00000000000000File "./output/wish_17985.v", line 2, characters 75-91: The command has indeed failed with message: B is already assigned to an entry or constr level. rocq-9.2.0/test-suite/output/wish_17985.v000066400000000000000000000002111516144147600200550ustar00rootroot00000000000000(* Do not accept B to be declared twice *) Fail Reserved Notation "'<<<' A '>>>' e '<<<' B '>>>'" (A, B at level 200, e, B at level 55). rocq-9.2.0/test-suite/output/wish_18097.out000066400000000000000000000010331516144147600204150ustar00rootroot00000000000000Notation pow := Nat.pow Nat.pow = fix pow (n m : nat) {struct m} : nat := match m with | 0 => 1 | S m0 => n * pow n m0 end : nat -> nat -> nat Arguments Nat.pow (n m)%_nat_scope Notation pow := Nat.pow Expands to: Notation wish_18097.pow Declared in library wish_18097, line 1, characters 0-28 Nat.pow : nat -> nat -> nat Nat.pow is not universe polymorphic Arguments Nat.pow (n m)%_nat_scope Nat.pow is transparent Expands to: Constant Corelib.Init.Nat.pow Declared in library Corelib.Init.Nat, line 143, characters 9-12 rocq-9.2.0/test-suite/output/wish_18097.v000066400000000000000000000000631516144147600200550ustar00rootroot00000000000000Abbreviation pow := Nat.pow. Print pow. About pow. rocq-9.2.0/test-suite/precomputed-time-tests/000077500000000000000000000000001516144147600212305ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem/000077500000000000000000000000001516144147600271475ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem/run.sh000077500000000000000000000021131516144147600303070ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_both_time_files time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-user.log --sort-by-mem diff -u time-of-build-both-user.log.expected time-of-build-both-user.log || exit $? $make_both_time_files --real time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-real.log --sort-by-mem diff -u time-of-build-both-real.log.expected time-of-build-both-real.log || exit $? for sort_kind in auto absolute diff; do $make_both_time_files time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-user-${sort_kind}.log --sort-by-mem --sort-by=${sort_kind} diff -u time-of-build-both-user-${sort_kind}.log.expected time-of-build-both-user-${sort_kind}.log || exit $? $make_both_time_files --real time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-real-${sort_kind}.log --sort-by-mem --sort-by=${sort_kind} diff -u time-of-build-both-real-${sort_kind}.log.expected time-of-build-both-real-${sort_kind}.log || exit $? done time-of-build-after.log.in000066400000000000000000004053341516144147600337450ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-memCOQDEP src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v COQDEP src/Compilers/Z/Bounds/Pipeline/Definition.v /home/jgross/.local64/coq/coq-master/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-old COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C coqprime make[1]: Nothing to be done for 'all'. ECHO > _CoqProject ROCQ compile src/Compilers/Z/Bounds/Pipeline/Definition.v src/Compilers/Z/Bounds/Pipeline/Definition (real: 7.33, user: 7.18, sys: 0.14, mem: 574388 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics (real: 1.93, user: 1.72, sys: 0.20, mem: 544172 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline.v src/Compilers/Z/Bounds/Pipeline (real: 1.38, user: 1.19, sys: 0.16, mem: 539808 ko) ROCQ compile src/Specific/Framework/SynthesisFramework.v src/Specific/Framework/SynthesisFramework (real: 1.85, user: 1.67, sys: 0.17, mem: 646300 ko) ROCQ compile src/Specific/X25519/C64/Synthesis.v src/Specific/X25519/C64/Synthesis (real: 11.15, user: 10.37, sys: 0.18, mem: 687760 ko) ROCQ compile src/Specific/NISTP256/AMD64/Synthesis.v src/Specific/NISTP256/AMD64/Synthesis (real: 13.45, user: 12.55, sys: 0.19, mem: 668216 ko) ROCQ compile src/Specific/X25519/C64/feadd.v Finished transaction in 2.814 secs (2.624u,0.s) (successful) total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s Finished transaction in 5.021 secs (4.636u,0.s) (successful) Closed under the global context total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s src/Specific/X25519/C64/feadd (real: 22.81, user: 20.93, sys: 0.25, mem: 766300 ko) ROCQ compile src/Specific/X25519/C64/fecarry.v Finished transaction in 4.343 secs (4.016u,0.004s) (successful) total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s Finished transaction in 7.078 secs (6.728u,0.s) (successful) Closed under the global context total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s src/Specific/X25519/C64/fecarry (real: 27.11, user: 24.99, sys: 0.21, mem: 786052 ko) ROCQ compile src/Specific/solinas32_2e255m765_12limbs/Synthesis.v src/Specific/solinas32_2e255m765_12limbs/Synthesis (real: 40.13, user: 36.92, sys: 0.26, mem: 728464 ko) ROCQ compile src/Specific/solinas32_2e255m765_13limbs/Synthesis.v src/Specific/solinas32_2e255m765_13limbs/Synthesis (real: 49.44, user: 45.75, sys: 0.18, mem: 744240 ko) ROCQ compile src/Specific/X25519/C64/femul.v Finished transaction in 8.415 secs (7.664u,0.015s) (successful) total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s Finished transaction in 14.616 secs (13.528u,0.008s) (successful) Closed under the global context total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s src/Specific/X25519/C64/femul (real: 39.72, user: 36.32, sys: 0.26, mem: 825448 ko) ROCQ compile src/Specific/X25519/C64/feaddDisplay > src/Specific/X25519/C64/feaddDisplay.log ROCQ compile src/Specific/X25519/C64/fecarryDisplay > src/Specific/X25519/C64/fecarryDisplay.log ROCQ compile src/Specific/X25519/C64/fesub.v Finished transaction in 3.513 secs (3.211u,0.s) (successful) total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s Finished transaction in 6.12 secs (5.64u,0.008s) (successful) Closed under the global context total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s src/Specific/X25519/C64/fesub (real: 24.71, user: 22.65, sys: 0.24, mem: 778792 ko) ROCQ compile src/Specific/X25519/C64/fesquare.v Finished transaction in 6.132 secs (5.516u,0.012s) (successful) total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s Finished transaction in 10.475 secs (9.728u,0.007s) (successful) Closed under the global context total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s src/Specific/X25519/C64/fesquare (real: 33.08, user: 30.13, sys: 0.24, mem: 799620 ko) ROCQ compile src/Specific/X25519/C64/femulDisplay > src/Specific/X25519/C64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/freeze.v Finished transaction in 7.307 secs (6.763u,0.011s) (successful) total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s Finished transaction in 10.495 secs (9.756u,0.s) (successful) Closed under the global context total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s src/Specific/X25519/C64/freeze (real: 34.35, user: 31.50, sys: 0.24, mem: 828104 ko) ROCQ compile src/Specific/NISTP256/AMD64/feadd.v Finished transaction in 8.784 secs (8.176u,0.011s) (successful) total time: 8.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s ─ReflectiveTactics.do_reflective_pipelin 0.0% 43.8% 1 3.568s ─ReflectiveTactics.solve_side_conditions 0.0% 43.2% 1 3.520s ─IntegrationTestTemporaryMiscCommon.fact 1.4% 23.6% 1 1.924s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 22.1% 1 1.796s ─ReflectiveTactics.do_reify ------------ 0.1% 21.7% 1 1.768s ─ReflectiveTactics.solve_post_reified_si 0.6% 21.5% 1 1.752s ─Reify.Reify_rhs_gen ------------------- 1.0% 20.9% 1 1.704s ─op_sig_side_conditions_t -------------- 0.0% 20.0% 1 1.624s ─DestructHyps.do_all_matches_then ------ 0.0% 20.0% 8 0.244s ─DestructHyps.do_one_match_then -------- 0.7% 19.9% 44 0.052s ─do_tac -------------------------------- 0.0% 19.2% 36 0.052s ─destruct H ---------------------------- 19.2% 19.2% 36 0.052s ─rewrite <- (lem : lemT) by by_tac ltac: 0.2% 17.3% 1 1.408s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 17.3% 1 1.408s ─by_tac -------------------------------- 0.0% 17.1% 4 0.504s ─rewrite <- (ZRange.is_bounded_by_None_r 16.7% 16.7% 8 0.344s ─UnifyAbstractReflexivity.unify_transfor 13.3% 16.1% 7 0.360s ─Reify.do_reify_abs_goal --------------- 9.9% 10.1% 2 0.820s ─Reify.do_reifyf_goal ------------------ 9.1% 9.3% 93 0.748s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.6% 1 0.700s ─Glue.zrange_to_reflective ------------- 0.0% 5.3% 1 0.432s ─IntegrationTestTemporaryMiscCommon.do_s 0.0% 4.8% 1 0.388s ─ MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” src/Specific/NISTP256/AMD64/feaddDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fenzDisplay > src/Specific/NISTP256/AMD64/fenzDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_12limbs/femul.v Finished transaction in 50.426 secs (46.528u,0.072s) (successful) total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s Finished transaction in 80.129 secs (74.068u,0.024s) (successful) Closed under the global context total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s src/Specific/solinas32_2e255m765_12limbs/femul (real: 155.79, user: 143.70, sys: 0.32, mem: 1454696 ko) ROCQ compile src/Specific/NISTP256/AMD64/feoppDisplay > src/Specific/NISTP256/AMD64/feoppDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fesubDisplay > src/Specific/NISTP256/AMD64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/fesquareDisplay > src/Specific/X25519/C64/fesquareDisplay.log ROCQ compile src/Specific/X25519/C64/fesubDisplay > src/Specific/X25519/C64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/freezeDisplay > src/Specific/X25519/C64/freezeDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_13limbs/femul.v Finished transaction in 61.854 secs (57.328u,0.079s) (successful) total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s Finished transaction in 94.432 secs (86.96u,0.02s) (successful) Closed under the global context total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s src/Specific/solinas32_2e255m765_13limbs/femul (real: 181.77, user: 168.52, sys: 0.40, mem: 1589516 ko) ROCQ compile src/Specific/NISTP256/AMD64/femul.v Finished transaction in 119.257 secs (109.936u,0.256s) (successful) total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s Finished transaction in 61.452 secs (58.503u,0.055s) (successful) Closed under the global context total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s src/Specific/NISTP256/AMD64/femul (real: 202.96, user: 189.62, sys: 0.64, mem: 3302508 ko) ROCQ compile src/Specific/NISTP256/AMD64/femulDisplay > src/Specific/NISTP256/AMD64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/ladderstep.v total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s Finished transaction in 171.122 secs (161.392u,0.039s) (successful) Closed under the global context total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s src/Specific/X25519/C64/ladderstep (real: 256.77, user: 241.34, sys: 0.45, mem: 1617000 ko) ROCQ compile src/Specific/X25519/C64/ladderstepDisplay > src/Specific/X25519/C64/ladderstepDisplay.log time-of-build-before.log.in000066400000000000000000003664541516144147600341170ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-memCOQDEP src/Compilers/Z/Bounds/Pipeline/Definition.v COQDEP src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v /home/jgross/.local64/coq/coq-master/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-old COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C coqprime make[1]: Nothing to be done for 'all'. ECHO > _CoqProject ROCQ compile src/Compilers/Z/Bounds/Pipeline/Definition.v src/Compilers/Z/Bounds/Pipeline/Definition (real: 7.40, user: 7.22, sys: 0.15, mem: 578344 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics (real: 1.73, user: 1.58, sys: 0.14, mem: 546112 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline.v src/Compilers/Z/Bounds/Pipeline (real: 1.18, user: 1.04, sys: 0.14, mem: 539160 ko) ROCQ compile src/Specific/Framework/SynthesisFramework.v src/Specific/Framework/SynthesisFramework (real: 1.95, user: 1.72, sys: 0.22, mem: 648632 ko) ROCQ compile src/Specific/X25519/C64/Synthesis.v src/Specific/X25519/C64/Synthesis (real: 11.23, user: 10.30, sys: 0.19, mem: 687812 ko) ROCQ compile src/Specific/NISTP256/AMD64/Synthesis.v src/Specific/NISTP256/AMD64/Synthesis (real: 13.74, user: 12.54, sys: 0.23, mem: 667664 ko) ROCQ compile src/Specific/X25519/C64/feadd.v Finished transaction in 2.852 secs (2.699u,0.012s) (successful) total time: 2.664s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s ─ReflectiveTactics.do_reflective_pipelin 0.0% 70.9% 1 1.888s ─ReflectiveTactics.solve_side_conditions 0.0% 69.5% 1 1.852s ─ReflectiveTactics.solve_post_reified_si 1.4% 43.7% 1 1.164s ─UnifyAbstractReflexivity.unify_transfor 27.0% 31.7% 8 0.256s ─Glue.refine_to_reflective_glue' ------- 0.0% 26.6% 1 0.708s ─ReflectiveTactics.do_reify ------------ 0.0% 25.8% 1 0.688s ─Reify.Reify_rhs_gen ------------------- 2.0% 24.0% 1 0.640s ─Glue.zrange_to_reflective ------------- 0.0% 17.9% 1 0.476s ─Glue.zrange_to_reflective_goal -------- 8.1% 13.1% 1 0.348s ─Reify.do_reify_abs_goal --------------- 12.8% 12.9% 2 0.344s ─Reify.do_reifyf_goal ------------------ 11.7% 11.9% 16 0.316s ─ReflectiveTactics.unify_abstract_cbv_in 7.7% 10.2% 1 0.272s ─unify (constr) (constr) --------------- 6.0% 6.0% 7 0.064s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.0% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 4.5% 4.7% 2 0.068s ─Glue.pattern_proj1_sig_in_sig --------- 1.5% 4.7% 1 0.124s ─pose proof (pf : Interpretation.Bo 3.3% 3.3% 1 0.088s ─Glue.split_BoundedWordToZ ------------- 0.2% 3.0% 1 0.080s ─destruct x ---------------------------- 2.7% 2.7% 4 0.032s ─clearbody (ne_var_list) --------------- 2.7% 2.7% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.7% 4 0.040s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─prove_interp_compile_correct ---------- 0.0% 2.4% 1 0.064s ─reflexivity --------------------------- 2.3% 2.3% 7 0.028s ─rewrite ?EtaInterp.InterpExprEta ------ 2.3% 2.3% 1 0.060s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.1% 2 0.056s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 70.9% 1 1.888s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 69.5% 1 1.852s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.4% 43.7% 1 1.164s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 27.0% 31.7% 8 0.256s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 7.7% 10.2% 1 0.272s β”‚ β”‚ β””unify (constr) (constr) --------- 2.4% 2.4% 1 0.064s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 25.8% 1 0.688s β”‚ β””Reify.Reify_rhs_gen --------------- 2.0% 24.0% 1 0.640s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 12.8% 12.9% 2 0.344s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 11.7% 11.9% 16 0.316s β”‚ └─prove_interp_compile_correct ---- 0.0% 2.4% 1 0.064s β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.3% 2.3% 1 0.060s └─Glue.refine_to_reflective_glue' ----- 0.0% 26.6% 1 0.708s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 17.9% 1 0.476s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 8.1% 13.1% 1 0.348s β”‚ β”‚β””pose proof (pf : Interpretat 3.3% 3.3% 1 0.088s β”‚ └─assert (H : is_bounded_by' bounds 4.5% 4.7% 2 0.068s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.0% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.5% 4.7% 1 0.124s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.1% 2 0.056s β”‚β””clearbody (ne_var_list) ----------- 2.1% 2.1% 1 0.056s └─Glue.split_BoundedWordToZ --------- 0.2% 3.0% 1 0.080s β””destruct_sig ---------------------- 0.0% 2.7% 4 0.040s β””destruct x ------------------------ 2.1% 2.1% 2 0.032s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s Finished transaction in 5.46 secs (5.068u,0.003s) (successful) Closed under the global context total time: 2.664s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s ─ReflectiveTactics.do_reflective_pipelin 0.0% 70.9% 1 1.888s ─ReflectiveTactics.solve_side_conditions 0.0% 69.5% 1 1.852s ─ReflectiveTactics.solve_post_reified_si 1.4% 43.7% 1 1.164s ─UnifyAbstractReflexivity.unify_transfor 27.0% 31.7% 8 0.256s ─Glue.refine_to_reflective_glue' ------- 0.0% 26.6% 1 0.708s ─ReflectiveTactics.do_reify ------------ 0.0% 25.8% 1 0.688s ─Reify.Reify_rhs_gen ------------------- 2.0% 24.0% 1 0.640s ─Glue.zrange_to_reflective ------------- 0.0% 17.9% 1 0.476s ─Glue.zrange_to_reflective_goal -------- 8.1% 13.1% 1 0.348s ─Reify.do_reify_abs_goal --------------- 12.8% 12.9% 2 0.344s ─Reify.do_reifyf_goal ------------------ 11.7% 11.9% 16 0.316s ─ReflectiveTactics.unify_abstract_cbv_in 7.7% 10.2% 1 0.272s ─unify (constr) (constr) --------------- 6.0% 6.0% 7 0.064s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.0% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 4.5% 4.7% 2 0.068s ─Glue.pattern_proj1_sig_in_sig --------- 1.5% 4.7% 1 0.124s ─pose proof (pf : Interpretation.Bo 3.3% 3.3% 1 0.088s ─Glue.split_BoundedWordToZ ------------- 0.2% 3.0% 1 0.080s ─destruct x ---------------------------- 2.7% 2.7% 4 0.032s ─clearbody (ne_var_list) --------------- 2.7% 2.7% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.7% 4 0.040s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─prove_interp_compile_correct ---------- 0.0% 2.4% 1 0.064s ─reflexivity --------------------------- 2.3% 2.3% 7 0.028s ─rewrite ?EtaInterp.InterpExprEta ------ 2.3% 2.3% 1 0.060s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.1% 2 0.056s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 70.9% 1 1.888s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 69.5% 1 1.852s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.4% 43.7% 1 1.164s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 27.0% 31.7% 8 0.256s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 7.7% 10.2% 1 0.272s β”‚ β”‚ β””unify (constr) (constr) --------- 2.4% 2.4% 1 0.064s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 25.8% 1 0.688s β”‚ β””Reify.Reify_rhs_gen --------------- 2.0% 24.0% 1 0.640s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 12.8% 12.9% 2 0.344s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 11.7% 11.9% 16 0.316s β”‚ └─prove_interp_compile_correct ---- 0.0% 2.4% 1 0.064s β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.3% 2.3% 1 0.060s └─Glue.refine_to_reflective_glue' ----- 0.0% 26.6% 1 0.708s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 17.9% 1 0.476s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 8.1% 13.1% 1 0.348s β”‚ β”‚β””pose proof (pf : Interpretat 3.3% 3.3% 1 0.088s β”‚ └─assert (H : is_bounded_by' bounds 4.5% 4.7% 2 0.068s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.0% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.5% 4.7% 1 0.124s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.1% 2 0.056s β”‚β””clearbody (ne_var_list) ----------- 2.1% 2.1% 1 0.056s └─Glue.split_BoundedWordToZ --------- 0.2% 3.0% 1 0.080s β””destruct_sig ---------------------- 0.0% 2.7% 4 0.040s β””destruct x ------------------------ 2.1% 2.1% 2 0.032s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s src/Specific/X25519/C64/feadd (real: 23.43, user: 21.41, sys: 0.26, mem: 766168 ko) ROCQ compile src/Specific/solinas32_2e255m765_12limbs/Synthesis.v src/Specific/solinas32_2e255m765_12limbs/Synthesis (real: 39.53, user: 36.64, sys: 0.21, mem: 729464 ko) ROCQ compile src/Specific/X25519/C64/fecarry.v Finished transaction in 4.798 secs (4.375u,0.003s) (successful) total time: 4.332s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 3.864s ─ReflectiveTactics.solve_side_conditions 0.0% 88.1% 1 3.816s ─ReflectiveTactics.do_reify ------------ 0.0% 53.2% 1 2.304s ─Reify.Reify_rhs_gen ------------------- 1.8% 52.6% 1 2.280s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.9% 1 1.512s ─Reify.do_reify_abs_goal --------------- 33.5% 33.9% 2 1.468s ─Reify.do_reifyf_goal ------------------ 32.1% 32.5% 29 1.408s ─UnifyAbstractReflexivity.unify_transfor 22.5% 27.1% 8 0.316s ─Glue.refine_to_reflective_glue' ------- 0.1% 9.7% 1 0.420s ─eexact -------------------------------- 9.3% 9.3% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.0% 1 0.304s ─Glue.zrange_to_reflective ------------- 0.1% 6.2% 1 0.268s ─prove_interp_compile_correct ---------- 0.0% 5.6% 1 0.244s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.228s ─unify (constr) (constr) --------------- 5.3% 5.3% 7 0.076s ─Glue.zrange_to_reflective_goal -------- 4.0% 4.9% 1 0.212s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.148s ─tac ----------------------------------- 1.8% 2.6% 2 0.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 3.864s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.1% 1 3.816s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 53.2% 1 2.304s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 52.6% 1 2.280s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 33.5% 33.9% 2 1.468s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 32.1% 32.5% 29 1.408s β”‚ β”‚ β”‚β””eexact -------------------------- 8.6% 8.6% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.6% 1 0.244s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.3% 5.3% 1 0.228s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.148s β”‚ β”‚ └─tac ----------------------------- 1.8% 2.6% 1 0.112s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.9% 1 1.512s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.5% 27.1% 8 0.316s β”‚ β”‚β””unify (constr) (constr) --------- 3.5% 3.5% 6 0.044s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.0% 1 0.304s └─Glue.refine_to_reflective_glue' ----- 0.1% 9.7% 1 0.420s β””Glue.zrange_to_reflective ----------- 0.1% 6.2% 1 0.268s β””Glue.zrange_to_reflective_goal ------ 4.0% 4.9% 1 0.212s Finished transaction in 8.342 secs (7.604u,0.008s) (successful) Closed under the global context total time: 4.332s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 3.864s ─ReflectiveTactics.solve_side_conditions 0.0% 88.1% 1 3.816s ─ReflectiveTactics.do_reify ------------ 0.0% 53.2% 1 2.304s ─Reify.Reify_rhs_gen ------------------- 1.8% 52.6% 1 2.280s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.9% 1 1.512s ─Reify.do_reify_abs_goal --------------- 33.5% 33.9% 2 1.468s ─Reify.do_reifyf_goal ------------------ 32.1% 32.5% 29 1.408s ─UnifyAbstractReflexivity.unify_transfor 22.5% 27.1% 8 0.316s ─Glue.refine_to_reflective_glue' ------- 0.1% 9.7% 1 0.420s ─eexact -------------------------------- 9.3% 9.3% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.0% 1 0.304s ─Glue.zrange_to_reflective ------------- 0.1% 6.2% 1 0.268s ─prove_interp_compile_correct ---------- 0.0% 5.6% 1 0.244s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.228s ─unify (constr) (constr) --------------- 5.3% 5.3% 7 0.076s ─Glue.zrange_to_reflective_goal -------- 4.0% 4.9% 1 0.212s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.148s ─tac ----------------------------------- 1.8% 2.6% 2 0.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 3.864s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.1% 1 3.816s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 53.2% 1 2.304s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 52.6% 1 2.280s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 33.5% 33.9% 2 1.468s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 32.1% 32.5% 29 1.408s β”‚ β”‚ β”‚β””eexact -------------------------- 8.6% 8.6% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.6% 1 0.244s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.3% 5.3% 1 0.228s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.148s β”‚ β”‚ └─tac ----------------------------- 1.8% 2.6% 1 0.112s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.9% 1 1.512s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.5% 27.1% 8 0.316s β”‚ β”‚β””unify (constr) (constr) --------- 3.5% 3.5% 6 0.044s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.0% 1 0.304s └─Glue.refine_to_reflective_glue' ----- 0.1% 9.7% 1 0.420s β””Glue.zrange_to_reflective ----------- 0.1% 6.2% 1 0.268s β””Glue.zrange_to_reflective_goal ------ 4.0% 4.9% 1 0.212s src/Specific/X25519/C64/fecarry (real: 28.85, user: 26.31, sys: 0.25, mem: 787148 ko) ROCQ compile src/Specific/solinas32_2e255m765_13limbs/Synthesis.v src/Specific/solinas32_2e255m765_13limbs/Synthesis (real: 49.50, user: 45.58, sys: 0.18, mem: 744472 ko) ROCQ compile src/Specific/X25519/C64/femul.v Finished transaction in 9.325 secs (8.62u,0.016s) (successful) total time: 8.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.7% 1 7.524s ─ReflectiveTactics.solve_side_conditions 0.0% 87.0% 1 7.460s ─ReflectiveTactics.do_reify ------------ 0.0% 43.8% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.6% 43.1% 1 3.700s ─Reify.Reify_rhs_gen ------------------- 1.4% 43.0% 1 3.688s ─UnifyAbstractReflexivity.unify_transfor 31.1% 36.7% 8 1.096s ─Reify.do_reify_abs_goal --------------- 26.3% 26.6% 2 2.284s ─Reify.do_reifyf_goal ------------------ 25.3% 25.6% 58 1.440s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.1% 1 0.696s ─eexact -------------------------------- 7.6% 7.6% 60 0.032s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.128s ─Glue.zrange_to_reflective ------------- 0.0% 5.7% 1 0.488s ─ReflectiveTactics.unify_abstract_cbv_in 3.8% 5.5% 1 0.468s ─prove_interp_compile_correct ---------- 0.0% 5.2% 1 0.448s ─rewrite ?EtaInterp.InterpExprEta ------ 4.9% 4.9% 1 0.416s ─Glue.zrange_to_reflective_goal -------- 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s ─rewrite H ----------------------------- 3.2% 3.2% 1 0.276s ─change G' ----------------------------- 3.2% 3.2% 1 0.272s ─tac ----------------------------------- 1.4% 2.1% 2 0.180s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.7% 1 7.524s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 87.0% 1 7.460s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 43.8% 1 3.760s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.4% 43.0% 1 3.688s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 26.3% 26.6% 2 2.284s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 25.3% 25.6% 58 1.440s β”‚ β”‚ β”‚β””eexact -------------------------- 6.9% 6.9% 58 0.032s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.2% 1 0.448s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.9% 4.9% 1 0.416s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.2% 3.2% 1 0.276s β”‚ β”‚ └─tac ----------------------------- 1.4% 2.1% 1 0.180s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 43.1% 1 3.700s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 31.1% 36.7% 8 1.096s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 6 0.092s β”‚ └─ReflectiveTactics.unify_abstract_ 3.8% 5.5% 1 0.468s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.1% 1 0.696s β””Glue.zrange_to_reflective ----------- 0.0% 5.7% 1 0.488s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s β””change G' ----------------------------- 3.2% 3.2% 1 0.272s Finished transaction in 16.611 secs (15.352u,0.s) (successful) Closed under the global context total time: 8.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.7% 1 7.524s ─ReflectiveTactics.solve_side_conditions 0.0% 87.0% 1 7.460s ─ReflectiveTactics.do_reify ------------ 0.0% 43.8% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.6% 43.1% 1 3.700s ─Reify.Reify_rhs_gen ------------------- 1.4% 43.0% 1 3.688s ─UnifyAbstractReflexivity.unify_transfor 31.1% 36.7% 8 1.096s ─Reify.do_reify_abs_goal --------------- 26.3% 26.6% 2 2.284s ─Reify.do_reifyf_goal ------------------ 25.3% 25.6% 58 1.440s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.1% 1 0.696s ─eexact -------------------------------- 7.6% 7.6% 60 0.032s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.128s ─Glue.zrange_to_reflective ------------- 0.0% 5.7% 1 0.488s ─ReflectiveTactics.unify_abstract_cbv_in 3.8% 5.5% 1 0.468s ─prove_interp_compile_correct ---------- 0.0% 5.2% 1 0.448s ─rewrite ?EtaInterp.InterpExprEta ------ 4.9% 4.9% 1 0.416s ─Glue.zrange_to_reflective_goal -------- 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s ─rewrite H ----------------------------- 3.2% 3.2% 1 0.276s ─change G' ----------------------------- 3.2% 3.2% 1 0.272s ─tac ----------------------------------- 1.4% 2.1% 2 0.180s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.7% 1 7.524s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 87.0% 1 7.460s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 43.8% 1 3.760s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.4% 43.0% 1 3.688s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 26.3% 26.6% 2 2.284s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 25.3% 25.6% 58 1.440s β”‚ β”‚ β”‚β””eexact -------------------------- 6.9% 6.9% 58 0.032s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.2% 1 0.448s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.9% 4.9% 1 0.416s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.2% 3.2% 1 0.276s β”‚ β”‚ └─tac ----------------------------- 1.4% 2.1% 1 0.180s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 43.1% 1 3.700s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 31.1% 36.7% 8 1.096s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 6 0.092s β”‚ └─ReflectiveTactics.unify_abstract_ 3.8% 5.5% 1 0.468s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.1% 1 0.696s β””Glue.zrange_to_reflective ----------- 0.0% 5.7% 1 0.488s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s β””change G' ----------------------------- 3.2% 3.2% 1 0.272s src/Specific/X25519/C64/femul (real: 42.98, user: 39.50, sys: 0.29, mem: 839624 ko) ROCQ compile src/Specific/X25519/C64/feaddDisplay > src/Specific/X25519/C64/feaddDisplay.log ROCQ compile src/Specific/X25519/C64/fecarryDisplay > src/Specific/X25519/C64/fecarryDisplay.log ROCQ compile src/Specific/X25519/C64/fesub.v Finished transaction in 3.729 secs (3.48u,0.012s) (successful) total time: 3.444s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s ─ReflectiveTactics.do_reflective_pipelin 0.0% 77.1% 1 2.656s ─ReflectiveTactics.solve_side_conditions 0.0% 75.8% 1 2.612s ─ReflectiveTactics.solve_post_reified_si 1.2% 40.1% 1 1.380s ─ReflectiveTactics.do_reify ------------ 0.0% 35.8% 1 1.232s ─Reify.Reify_rhs_gen ------------------- 1.4% 34.4% 1 1.184s ─UnifyAbstractReflexivity.unify_transfor 25.7% 30.5% 8 0.324s ─Glue.refine_to_reflective_glue' ------- 0.0% 20.9% 1 0.720s ─Reify.do_reify_abs_goal --------------- 18.5% 18.8% 2 0.648s ─Reify.do_reifyf_goal ------------------ 17.3% 17.5% 16 0.604s ─Glue.zrange_to_reflective ------------- 0.0% 14.2% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.5% 10.6% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 5.8% 8.0% 1 0.276s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.076s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 3.8% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 3.6% 3.6% 2 0.064s ─Glue.pattern_proj1_sig_in_sig --------- 1.2% 3.6% 1 0.124s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 0.120s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.116s ─rewrite ?EtaInterp.InterpExprEta ------ 3.1% 3.1% 1 0.108s ─pose proof (pf : Interpretation.Bo 2.7% 2.7% 1 0.092s ─reflexivity --------------------------- 2.6% 2.6% 7 0.032s ─Glue.split_BoundedWordToZ ------------- 0.2% 2.4% 1 0.084s ─tac ----------------------------------- 1.7% 2.2% 2 0.076s ─Reify.transitivity_tt ----------------- 0.1% 2.2% 2 0.040s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s ─clearbody (ne_var_list) --------------- 2.1% 2.1% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.1% 4 0.040s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 77.1% 1 2.656s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 75.8% 1 2.612s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 40.1% 1 1.380s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.7% 30.5% 8 0.324s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.040s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 5.8% 8.0% 1 0.276s β”‚ β”‚ β””unify (constr) (constr) --------- 2.2% 2.2% 1 0.076s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 35.8% 1 1.232s β”‚ β””Reify.Reify_rhs_gen --------------- 1.4% 34.4% 1 1.184s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 18.5% 18.8% 2 0.648s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 17.3% 17.5% 16 0.604s β”‚ β”‚β””eexact -------------------------- 3.8% 3.8% 16 0.012s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.5% 1 0.120s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.1% 3.1% 1 0.108s β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.116s β”‚ β”œβ”€tac ----------------------------- 1.7% 2.2% 1 0.076s β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.2% 2 0.040s └─Glue.refine_to_reflective_glue' ----- 0.0% 20.9% 1 0.720s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 14.2% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.5% 10.6% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.7% 2.7% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.6% 3.6% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 3.8% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.2% 3.6% 1 0.124s └─Glue.split_BoundedWordToZ --------- 0.2% 2.4% 1 0.084s β””destruct_sig ---------------------- 0.0% 2.1% 4 0.040s Finished transaction in 6.763 secs (6.183u,0.s) (successful) Closed under the global context total time: 3.444s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s ─ReflectiveTactics.do_reflective_pipelin 0.0% 77.1% 1 2.656s ─ReflectiveTactics.solve_side_conditions 0.0% 75.8% 1 2.612s ─ReflectiveTactics.solve_post_reified_si 1.2% 40.1% 1 1.380s ─ReflectiveTactics.do_reify ------------ 0.0% 35.8% 1 1.232s ─Reify.Reify_rhs_gen ------------------- 1.4% 34.4% 1 1.184s ─UnifyAbstractReflexivity.unify_transfor 25.7% 30.5% 8 0.324s ─Glue.refine_to_reflective_glue' ------- 0.0% 20.9% 1 0.720s ─Reify.do_reify_abs_goal --------------- 18.5% 18.8% 2 0.648s ─Reify.do_reifyf_goal ------------------ 17.3% 17.5% 16 0.604s ─Glue.zrange_to_reflective ------------- 0.0% 14.2% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.5% 10.6% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 5.8% 8.0% 1 0.276s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.076s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 3.8% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 3.6% 3.6% 2 0.064s ─Glue.pattern_proj1_sig_in_sig --------- 1.2% 3.6% 1 0.124s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 0.120s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.116s ─rewrite ?EtaInterp.InterpExprEta ------ 3.1% 3.1% 1 0.108s ─pose proof (pf : Interpretation.Bo 2.7% 2.7% 1 0.092s ─reflexivity --------------------------- 2.6% 2.6% 7 0.032s ─Glue.split_BoundedWordToZ ------------- 0.2% 2.4% 1 0.084s ─tac ----------------------------------- 1.7% 2.2% 2 0.076s ─Reify.transitivity_tt ----------------- 0.1% 2.2% 2 0.040s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s ─clearbody (ne_var_list) --------------- 2.1% 2.1% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.1% 4 0.040s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 77.1% 1 2.656s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 75.8% 1 2.612s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 40.1% 1 1.380s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.7% 30.5% 8 0.324s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.040s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 5.8% 8.0% 1 0.276s β”‚ β”‚ β””unify (constr) (constr) --------- 2.2% 2.2% 1 0.076s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 35.8% 1 1.232s β”‚ β””Reify.Reify_rhs_gen --------------- 1.4% 34.4% 1 1.184s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 18.5% 18.8% 2 0.648s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 17.3% 17.5% 16 0.604s β”‚ β”‚β””eexact -------------------------- 3.8% 3.8% 16 0.012s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.5% 1 0.120s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.1% 3.1% 1 0.108s β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.116s β”‚ β”œβ”€tac ----------------------------- 1.7% 2.2% 1 0.076s β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.2% 2 0.040s └─Glue.refine_to_reflective_glue' ----- 0.0% 20.9% 1 0.720s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 14.2% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.5% 10.6% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.7% 2.7% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.6% 3.6% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 3.8% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.2% 3.6% 1 0.124s └─Glue.split_BoundedWordToZ --------- 0.2% 2.4% 1 0.084s β””destruct_sig ---------------------- 0.0% 2.1% 4 0.040s src/Specific/X25519/C64/fesub (real: 26.11, user: 23.72, sys: 0.24, mem: 781808 ko) ROCQ compile src/Specific/X25519/C64/fesquare.v Finished transaction in 6.477 secs (6.044u,0.008s) (successful) total time: 6.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 5.764s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.6% 1 5.388s ─ReflectiveTactics.solve_side_conditions 0.0% 88.8% 1 5.340s ─ReflectiveTactics.do_reify ------------ 0.0% 47.0% 1 2.828s ─Reify.Reify_rhs_gen ------------------- 1.5% 46.3% 1 2.784s ─ReflectiveTactics.solve_post_reified_si 0.5% 41.8% 1 2.512s ─UnifyAbstractReflexivity.unify_transfor 28.5% 34.1% 8 0.552s ─Reify.do_reify_abs_goal --------------- 28.7% 29.1% 2 1.752s ─Reify.do_reifyf_goal ------------------ 27.6% 27.9% 47 1.320s ─eexact -------------------------------- 8.4% 8.4% 49 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.412s ─unify (constr) (constr) --------------- 6.3% 6.3% 7 0.104s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.3% 1 0.376s ─prove_interp_compile_correct ---------- 0.0% 5.3% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 4.8% 4.8% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.0% 4.4% 1 0.264s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 3.7% 1 0.224s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.3% 1 0.196s ─change G' ----------------------------- 3.1% 3.1% 1 0.188s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.180s ─tac ----------------------------------- 1.9% 2.7% 2 0.160s ─reflexivity --------------------------- 2.4% 2.4% 7 0.060s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.9% 1 5.764s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 89.6% 1 5.388s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 88.8% 1 5.340s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 47.0% 1 2.828s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 1.5% 46.3% 1 2.784s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 28.7% 29.1% 2 1.752s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 27.6% 27.9% 47 1.320s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 7.7% 7.7% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.3% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 4.8% 4.8% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€rewrite H --------------------- 3.0% 3.0% 1 0.180s β”‚ β”‚ β”‚ └─tac --------------------------- 1.9% 2.7% 1 0.160s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.5% 41.8% 1 2.512s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 28.5% 34.1% 8 0.552s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 4.6% 4.6% 6 0.076s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.412s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 6.3% 1 0.376s β”‚ β””Glue.zrange_to_reflective --------- 0.0% 4.4% 1 0.264s β”‚ β””Glue.zrange_to_reflective_goal ---- 2.6% 3.3% 1 0.196s └─IntegrationTestTemporaryMiscCommon.do 0.1% 3.7% 1 0.224s β””change G' --------------------------- 3.1% 3.1% 1 0.188s Finished transaction in 12.356 secs (11.331u,0.004s) (successful) Closed under the global context total time: 6.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 5.764s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.6% 1 5.388s ─ReflectiveTactics.solve_side_conditions 0.0% 88.8% 1 5.340s ─ReflectiveTactics.do_reify ------------ 0.0% 47.0% 1 2.828s ─Reify.Reify_rhs_gen ------------------- 1.5% 46.3% 1 2.784s ─ReflectiveTactics.solve_post_reified_si 0.5% 41.8% 1 2.512s ─UnifyAbstractReflexivity.unify_transfor 28.5% 34.1% 8 0.552s ─Reify.do_reify_abs_goal --------------- 28.7% 29.1% 2 1.752s ─Reify.do_reifyf_goal ------------------ 27.6% 27.9% 47 1.320s ─eexact -------------------------------- 8.4% 8.4% 49 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.412s ─unify (constr) (constr) --------------- 6.3% 6.3% 7 0.104s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.3% 1 0.376s ─prove_interp_compile_correct ---------- 0.0% 5.3% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 4.8% 4.8% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.0% 4.4% 1 0.264s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 3.7% 1 0.224s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.3% 1 0.196s ─change G' ----------------------------- 3.1% 3.1% 1 0.188s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.180s ─tac ----------------------------------- 1.9% 2.7% 2 0.160s ─reflexivity --------------------------- 2.4% 2.4% 7 0.060s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.9% 1 5.764s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 89.6% 1 5.388s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 88.8% 1 5.340s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 47.0% 1 2.828s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 1.5% 46.3% 1 2.784s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 28.7% 29.1% 2 1.752s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 27.6% 27.9% 47 1.320s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 7.7% 7.7% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.3% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 4.8% 4.8% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€rewrite H --------------------- 3.0% 3.0% 1 0.180s β”‚ β”‚ β”‚ └─tac --------------------------- 1.9% 2.7% 1 0.160s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.5% 41.8% 1 2.512s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 28.5% 34.1% 8 0.552s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 4.6% 4.6% 6 0.076s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.412s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 6.3% 1 0.376s β”‚ β””Glue.zrange_to_reflective --------- 0.0% 4.4% 1 0.264s β”‚ β””Glue.zrange_to_reflective_goal ---- 2.6% 3.3% 1 0.196s └─IntegrationTestTemporaryMiscCommon.do 0.1% 3.7% 1 0.224s β””change G' --------------------------- 3.1% 3.1% 1 0.188s src/Specific/X25519/C64/fesquare (real: 35.23, user: 32.24, sys: 0.26, mem: 802776 ko) ROCQ compile src/Specific/X25519/C64/femulDisplay > src/Specific/X25519/C64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/freeze.v Finished transaction in 7.785 secs (7.139u,0.019s) (successful) total time: 7.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.600s ─ReflectiveTactics.solve_side_conditions -0.0% 91.8% 1 6.532s ─ReflectiveTactics.do_reify ------------ 0.0% 57.1% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 56.4% 1 4.012s ─Reify.do_reify_abs_goal --------------- 40.1% 40.3% 2 2.868s ─Reify.do_reifyf_goal ------------------ 39.1% 39.4% 129 2.800s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.8% 1 2.472s ─UnifyAbstractReflexivity.unify_transfor 25.2% 29.4% 8 0.428s ─eexact -------------------------------- 12.9% 12.9% 131 0.028s ─Glue.refine_to_reflective_glue' ------- 0.1% 6.4% 1 0.456s ─prove_interp_compile_correct ---------- 0.0% 4.7% 1 0.332s ─unify (constr) (constr) --------------- 4.6% 4.6% 7 0.096s ─ReflectiveTactics.unify_abstract_cbv_in 3.1% 4.6% 1 0.324s ─rewrite ?EtaInterp.InterpExprEta ------ 4.3% 4.3% 1 0.308s ─Glue.zrange_to_reflective ------------- 0.0% 4.1% 1 0.292s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.2% 1 0.228s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.212s ─reflexivity --------------------------- 2.3% 2.3% 7 0.064s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.096s ─transitivity -------------------------- 2.1% 2.1% 5 0.084s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.600s β”‚β””ReflectiveTactics.solve_side_conditio -0.0% 91.8% 1 6.532s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 57.1% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 56.4% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 40.1% 40.3% 2 2.868s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 39.1% 39.4% 129 2.800s β”‚ β”‚ β”‚β””eexact -------------------------- 12.4% 12.4% 129 0.028s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 4.7% 1 0.332s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.3% 4.3% 1 0.308s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.212s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.096s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.084s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.8% 1 2.472s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.2% 29.4% 8 0.428s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 6 0.068s β”‚ └─ReflectiveTactics.unify_abstract_ 3.1% 4.6% 1 0.324s └─Glue.refine_to_reflective_glue' ----- 0.1% 6.4% 1 0.456s β””Glue.zrange_to_reflective ----------- 0.0% 4.1% 1 0.292s β””Glue.zrange_to_reflective_goal ------ 2.6% 3.2% 1 0.228s Finished transaction in 12.063 secs (11.036u,0.012s) (successful) Closed under the global context total time: 7.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.600s ─ReflectiveTactics.solve_side_conditions -0.0% 91.8% 1 6.532s ─ReflectiveTactics.do_reify ------------ 0.0% 57.1% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 56.4% 1 4.012s ─Reify.do_reify_abs_goal --------------- 40.1% 40.3% 2 2.868s ─Reify.do_reifyf_goal ------------------ 39.1% 39.4% 129 2.800s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.8% 1 2.472s ─UnifyAbstractReflexivity.unify_transfor 25.2% 29.4% 8 0.428s ─eexact -------------------------------- 12.9% 12.9% 131 0.028s ─Glue.refine_to_reflective_glue' ------- 0.1% 6.4% 1 0.456s ─prove_interp_compile_correct ---------- 0.0% 4.7% 1 0.332s ─unify (constr) (constr) --------------- 4.6% 4.6% 7 0.096s ─ReflectiveTactics.unify_abstract_cbv_in 3.1% 4.6% 1 0.324s ─rewrite ?EtaInterp.InterpExprEta ------ 4.3% 4.3% 1 0.308s ─Glue.zrange_to_reflective ------------- 0.0% 4.1% 1 0.292s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.2% 1 0.228s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.212s ─reflexivity --------------------------- 2.3% 2.3% 7 0.064s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.096s ─transitivity -------------------------- 2.1% 2.1% 5 0.084s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.600s β”‚β””ReflectiveTactics.solve_side_conditio -0.0% 91.8% 1 6.532s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 57.1% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 56.4% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 40.1% 40.3% 2 2.868s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 39.1% 39.4% 129 2.800s β”‚ β”‚ β”‚β””eexact -------------------------- 12.4% 12.4% 129 0.028s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 4.7% 1 0.332s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.3% 4.3% 1 0.308s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.212s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.096s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.084s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.8% 1 2.472s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.2% 29.4% 8 0.428s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 6 0.068s β”‚ └─ReflectiveTactics.unify_abstract_ 3.1% 4.6% 1 0.324s └─Glue.refine_to_reflective_glue' ----- 0.1% 6.4% 1 0.456s β””Glue.zrange_to_reflective ----------- 0.0% 4.1% 1 0.292s β””Glue.zrange_to_reflective_goal ------ 2.6% 3.2% 1 0.228s src/Specific/X25519/C64/freeze (real: 36.42, user: 33.24, sys: 0.26, mem: 826476 ko) ROCQ compile src/Specific/NISTP256/AMD64/feadd.v Finished transaction in 9.065 secs (8.452u,0.004s) (successful) total time: 8.408s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s ─ReflectiveTactics.do_reflective_pipelin 0.0% 47.7% 1 4.012s ─ReflectiveTactics.solve_side_conditions 0.0% 47.1% 1 3.960s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s ─ReflectiveTactics.solve_post_reified_si 0.6% 26.4% 1 2.220s ─UnifyAbstractReflexivity.unify_transfor 18.0% 21.3% 8 0.508s ─IntegrationTestTemporaryMiscCommon.fact 1.3% 21.3% 1 1.788s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 21.0% 1 1.768s ─ReflectiveTactics.do_reify ------------ 0.0% 20.7% 1 1.740s ─Reify.Reify_rhs_gen ------------------- 1.0% 20.0% 1 1.684s ─DestructHyps.do_all_matches_then ------ 0.1% 18.6% 8 0.220s ─DestructHyps.do_one_match_then -------- 0.8% 18.5% 44 0.056s ─op_sig_side_conditions_t -------------- 0.0% 17.9% 1 1.504s ─do_tac -------------------------------- 0.0% 17.7% 43 0.052s ─destruct H ---------------------------- 17.7% 17.7% 36 0.052s ─rewrite <- (lem : lemT) by by_tac ltac: 0.3% 17.3% 1 1.452s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 17.3% 1 1.452s ─by_tac -------------------------------- 0.0% 17.0% 4 0.532s ─rewrite <- (ZRange.is_bounded_by_None_r 15.7% 15.8% 8 0.360s ─Reify.do_reify_abs_goal --------------- 9.1% 9.3% 2 0.780s ─Reify.do_reifyf_goal ------------------ 8.5% 8.6% 93 0.716s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 0.700s ─Glue.zrange_to_reflective ------------- 0.0% 5.3% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.3% 1 0.360s ─Glue.zrange_to_reflective_goal -------- 2.5% 4.0% 1 0.336s ─unify (constr) (constr) --------------- 3.9% 3.9% 9 0.108s ─IntegrationTestTemporaryMiscCommon.do_s 0.0% 3.8% 1 0.316s ─ MapProjections.proj2 2.1% 2.1% 2 0.108s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 47.7% 1 4.012s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 47.1% 1 3.960s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.6% 26.4% 1 2.220s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.0% 21.3% 8 0.508s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 2.6% 2.6% 6 0.064s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.3% 1 0.360s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 20.7% 1 1.740s β”‚ β””Reify.Reify_rhs_gen --------------- 1.0% 20.0% 1 1.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.1% 9.3% 2 0.780s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 8.5% 8.6% 93 0.716s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.4% 1 0.200s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.2% 2.2% 1 0.188s β”‚ └─rewrite H ----------------------- 2.3% 2.3% 1 0.192s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.444s β””Glue.zrange_to_reflective_goal ------ 2.5% 4.0% 1 0.336s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.3% 21.3% 1 1.788s β”‚β””op_sig_side_conditions_t ------------ 0.0% 17.9% 1 1.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.1% 10.1% 4 0.220s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.4% 10.0% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 9.6% 20 0.048s β”‚ β”‚β””destruct H ------------------------ 9.6% 9.6% 20 0.048s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 7.5% 7.6% 4 0.308s └─IntegrationTestTemporaryMiscCommon.do 0.0% 21.0% 1 1.768s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.452s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.3% 17.3% 1 1.452s β”‚β””by_tac ---------------------------- 0.0% 17.0% 4 0.532s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.5% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.056s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.2% 8.3% 4 0.360s └─IntegrationTestTemporaryMiscCommon. 0.0% 3.8% 1 0.316s β”” MapProjections.proj2 2.1% 2.1% 2 0.108s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 47.7% 1 4.012s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 47.1% 1 3.960s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.6% 26.4% 1 2.220s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.0% 21.3% 8 0.508s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 2.6% 2.6% 6 0.064s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.3% 1 0.360s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 20.7% 1 1.740s β”‚ β””Reify.Reify_rhs_gen --------------- 1.0% 20.0% 1 1.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.1% 9.3% 2 0.780s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 8.5% 8.6% 93 0.716s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.4% 1 0.200s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.2% 2.2% 1 0.188s β”‚ └─rewrite H ----------------------- 2.3% 2.3% 1 0.192s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.444s β””Glue.zrange_to_reflective_goal ------ 2.5% 4.0% 1 0.336s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.3% 21.3% 1 1.788s β”‚β””op_sig_side_conditions_t ------------ 0.0% 17.9% 1 1.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.1% 10.1% 4 0.220s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.4% 10.0% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 9.6% 20 0.048s β”‚ β”‚β””destruct H ------------------------ 9.6% 9.6% 20 0.048s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 7.5% 7.6% 4 0.308s └─IntegrationTestTemporaryMiscCommon.do 0.0% 21.0% 1 1.768s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.452s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.3% 17.3% 1 1.452s β”‚β””by_tac ---------------------------- 0.0% 17.0% 4 0.532s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.5% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.056s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.2% 8.3% 4 0.360s └─IntegrationTestTemporaryMiscCommon. 0.0% 3.8% 1 0.316s β”” src/Specific/NISTP256/AMD64/feaddDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fenzDisplay > src/Specific/NISTP256/AMD64/fenzDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/feoppDisplay > src/Specific/NISTP256/AMD64/feoppDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fesubDisplay > src/Specific/NISTP256/AMD64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/fesquareDisplay > src/Specific/X25519/C64/fesquareDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_12limbs/femul.v Finished transaction in 60.265 secs (55.388u,0.103s) (successful) total time: 55.440s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 49.464s ─ReflectiveTactics.solve_side_conditions 0.0% 88.9% 1 49.288s ─ReflectiveTactics.do_reify ------------ -0.0% 49.9% 1 27.684s ─Reify.Reify_rhs_gen ------------------- 1.3% 49.3% 1 27.348s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.0% 1 21.604s ─Reify.do_reify_abs_goal --------------- 36.3% 36.6% 2 20.272s ─UnifyAbstractReflexivity.unify_transfor 30.8% 36.1% 8 8.636s ─Reify.do_reifyf_goal ------------------ 35.7% 35.9% 108 10.356s ─eexact -------------------------------- 11.5% 11.5% 110 0.128s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.7% 1 3.692s ─Glue.zrange_to_reflective ------------- 0.0% 6.2% 1 3.424s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.140s ─Glue.zrange_to_reflective_goal -------- 1.4% 4.7% 1 2.592s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s ─change G' ----------------------------- 3.9% 3.9% 1 2.148s ─pose proof (pf : Interpretation.Bo 3.1% 3.1% 1 1.736s ─rewrite H ----------------------------- 3.1% 3.1% 1 1.692s ─prove_interp_compile_correct ---------- 0.0% 3.0% 1 1.636s ─rewrite ?EtaInterp.InterpExprEta ------ 2.7% 2.7% 1 1.484s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 49.464s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.9% 1 49.288s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 49.9% 1 27.684s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 49.3% 1 27.348s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.3% 36.6% 2 20.272s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.7% 35.9% 108 10.356s β”‚ β”‚ β”‚β””eexact -------------------------- 11.1% 11.1% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.1% 3.1% 1 1.692s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.0% 1 1.636s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.7% 2.7% 1 1.484s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.0% 1 21.604s β”‚ β””UnifyAbstractReflexivity.unify_tran 30.8% 36.1% 8 8.636s β”‚ β””unify (constr) (constr) ----------- 4.4% 4.4% 6 1.140s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.7% 1 3.692s β””Glue.zrange_to_reflective ----------- 0.0% 6.2% 1 3.424s β””Glue.zrange_to_reflective_goal ------ 1.4% 4.7% 1 2.592s β””pose proof (pf : Interpretation. 3.1% 3.1% 1 1.736s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s β””change G' ----------------------------- 3.9% 3.9% 1 2.148s Finished transaction in 92.046 secs (84.315u,0.032s) (successful) Closed under the global context total time: 55.440s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 49.464s ─ReflectiveTactics.solve_side_conditions 0.0% 88.9% 1 49.288s ─ReflectiveTactics.do_reify ------------ -0.0% 49.9% 1 27.684s ─Reify.Reify_rhs_gen ------------------- 1.3% 49.3% 1 27.348s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.0% 1 21.604s ─Reify.do_reify_abs_goal --------------- 36.3% 36.6% 2 20.272s ─UnifyAbstractReflexivity.unify_transfor 30.8% 36.1% 8 8.636s ─Reify.do_reifyf_goal ------------------ 35.7% 35.9% 108 10.356s ─eexact -------------------------------- 11.5% 11.5% 110 0.128s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.7% 1 3.692s ─Glue.zrange_to_reflective ------------- 0.0% 6.2% 1 3.424s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.140s ─Glue.zrange_to_reflective_goal -------- 1.4% 4.7% 1 2.592s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s ─change G' ----------------------------- 3.9% 3.9% 1 2.148s ─pose proof (pf : Interpretation.Bo 3.1% 3.1% 1 1.736s ─rewrite H ----------------------------- 3.1% 3.1% 1 1.692s ─prove_interp_compile_correct ---------- 0.0% 3.0% 1 1.636s ─rewrite ?EtaInterp.InterpExprEta ------ 2.7% 2.7% 1 1.484s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 49.464s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.9% 1 49.288s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 49.9% 1 27.684s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 49.3% 1 27.348s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.3% 36.6% 2 20.272s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.7% 35.9% 108 10.356s β”‚ β”‚ β”‚β””eexact -------------------------- 11.1% 11.1% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.1% 3.1% 1 1.692s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.0% 1 1.636s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.7% 2.7% 1 1.484s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.0% 1 21.604s β”‚ β””UnifyAbstractReflexivity.unify_tran 30.8% 36.1% 8 8.636s β”‚ β””unify (constr) (constr) ----------- 4.4% 4.4% 6 1.140s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.7% 1 3.692s β””Glue.zrange_to_reflective ----------- 0.0% 6.2% 1 3.424s β””Glue.zrange_to_reflective_goal ------ 1.4% 4.7% 1 2.592s β””pose proof (pf : Interpretation. 3.1% 3.1% 1 1.736s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s β””change G' ----------------------------- 3.9% 3.9% 1 2.148s src/Specific/solinas32_2e255m765_12limbs/femul (real: 179.21, user: 164.11, sys: 0.42, mem: 1549104 ko) ROCQ compile src/Specific/X25519/C64/fesubDisplay > src/Specific/X25519/C64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/freezeDisplay > src/Specific/X25519/C64/freezeDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_13limbs/femul.v Finished transaction in 74.548 secs (68.928u,0.079s) (successful) total time: 68.948s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.7% 1 61.172s ─ReflectiveTactics.solve_side_conditions 0.0% 88.4% 1 60.944s ─ReflectiveTactics.do_reify ------------ 0.0% 48.5% 1 33.408s ─Reify.Reify_rhs_gen ------------------- 1.3% 47.9% 1 33.020s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.9% 1 27.536s ─UnifyAbstractReflexivity.unify_transfor 32.0% 37.2% 8 11.528s ─Reify.do_reify_abs_goal --------------- 36.0% 36.2% 2 24.960s ─Reify.do_reifyf_goal ------------------ 35.3% 35.5% 117 12.840s ─eexact -------------------------------- 11.4% 11.4% 119 0.160s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.9% 1 4.784s ─Glue.zrange_to_reflective ------------- 0.0% 6.5% 1 4.512s ─Glue.zrange_to_reflective_goal -------- 1.3% 4.9% 1 3.396s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.524s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s ─change G' ----------------------------- 4.1% 4.1% 1 2.840s ─pose proof (pf : Interpretation.Bo 3.5% 3.5% 1 2.420s ─rewrite H ----------------------------- 3.0% 3.0% 1 2.084s ─prove_interp_compile_correct ---------- 0.0% 2.7% 1 1.856s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 1.692s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 88.7% 1 61.172s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.4% 1 60.944s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 48.5% 1 33.408s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 47.9% 1 33.020s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.0% 36.2% 2 24.960s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.3% 35.5% 117 12.840s β”‚ β”‚ β”‚β””eexact -------------------------- 10.9% 10.9% 117 0.088s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 2.084s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 2.7% 1 1.856s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 1.692s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.9% 1 27.536s β”‚ β””UnifyAbstractReflexivity.unify_tran 32.0% 37.2% 8 11.528s β”‚ β””unify (constr) (constr) ----------- 4.3% 4.3% 6 1.524s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.9% 1 4.784s β””Glue.zrange_to_reflective ----------- 0.0% 6.5% 1 4.512s β””Glue.zrange_to_reflective_goal ------ 1.3% 4.9% 1 3.396s β””pose proof (pf : Interpretation. 3.5% 3.5% 1 2.420s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s β””change G' ----------------------------- 4.1% 4.1% 1 2.840s Finished transaction in 105.62 secs (97.6u,0.02s) (successful) Closed under the global context total time: 68.948s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.7% 1 61.172s ─ReflectiveTactics.solve_side_conditions 0.0% 88.4% 1 60.944s ─ReflectiveTactics.do_reify ------------ 0.0% 48.5% 1 33.408s ─Reify.Reify_rhs_gen ------------------- 1.3% 47.9% 1 33.020s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.9% 1 27.536s ─UnifyAbstractReflexivity.unify_transfor 32.0% 37.2% 8 11.528s ─Reify.do_reify_abs_goal --------------- 36.0% 36.2% 2 24.960s ─Reify.do_reifyf_goal ------------------ 35.3% 35.5% 117 12.840s ─eexact -------------------------------- 11.4% 11.4% 119 0.160s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.9% 1 4.784s ─Glue.zrange_to_reflective ------------- 0.0% 6.5% 1 4.512s ─Glue.zrange_to_reflective_goal -------- 1.3% 4.9% 1 3.396s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.524s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s ─change G' ----------------------------- 4.1% 4.1% 1 2.840s ─pose proof (pf : Interpretation.Bo 3.5% 3.5% 1 2.420s ─rewrite H ----------------------------- 3.0% 3.0% 1 2.084s ─prove_interp_compile_correct ---------- 0.0% 2.7% 1 1.856s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 1.692s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 88.7% 1 61.172s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.4% 1 60.944s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 48.5% 1 33.408s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 47.9% 1 33.020s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.0% 36.2% 2 24.960s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.3% 35.5% 117 12.840s β”‚ β”‚ β”‚β””eexact -------------------------- 10.9% 10.9% 117 0.088s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 2.084s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 2.7% 1 1.856s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 1.692s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.9% 1 27.536s β”‚ β””UnifyAbstractReflexivity.unify_tran 32.0% 37.2% 8 11.528s β”‚ β””unify (constr) (constr) ----------- 4.3% 4.3% 6 1.524s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.9% 1 4.784s β””Glue.zrange_to_reflective ----------- 0.0% 6.5% 1 4.512s β””Glue.zrange_to_reflective_goal ------ 1.3% 4.9% 1 3.396s β””pose proof (pf : Interpretation. 3.5% 3.5% 1 2.420s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s β””change G' ----------------------------- 4.1% 4.1% 1 2.840s src/Specific/solinas32_2e255m765_13limbs/femul (real: 207.94, user: 192.95, sys: 0.48, mem: 1656912 ko) ROCQ compile src/Specific/NISTP256/AMD64/femul.v Finished transaction in 122.29 secs (111.972u,0.239s) (successful) total time: 112.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s ─ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s ─ReflectiveTactics.do_reify ------------ 0.0% 81.8% 1 91.740s ─Reify.Reify_rhs_gen ------------------- 0.7% 81.6% 1 91.504s ─Reify.do_reify_abs_goal --------------- 75.6% 75.7% 2 84.892s ─Reify.do_reifyf_goal ------------------ 75.2% 75.4% 901 84.532s ─eexact -------------------------------- 17.1% 17.1% 903 0.140s ─ReflectiveTactics.solve_post_reified_si 0.2% 14.5% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s β””ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s β”œβ”€ReflectiveTactics.do_reify ---------- 0.0% 81.8% 1 91.740s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 81.6% 1 91.504s β”‚β””Reify.do_reify_abs_goal ------------- 75.6% 75.7% 2 84.892s β”‚β””Reify.do_reifyf_goal ---------------- 75.2% 75.4% 901 84.532s β”‚β””eexact ------------------------------ 16.9% 16.9% 901 0.140s └─ReflectiveTactics.solve_post_reified_ 0.2% 14.5% 1 16.260s β””UnifyAbstractReflexivity.unify_transf 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s Finished transaction in 72.408 secs (68.432u,0.064s) (successful) Closed under the global context total time: 112.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s ─ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s ─ReflectiveTactics.do_reify ------------ 0.0% 81.8% 1 91.740s ─Reify.Reify_rhs_gen ------------------- 0.7% 81.6% 1 91.504s ─Reify.do_reify_abs_goal --------------- 75.6% 75.7% 2 84.892s ─Reify.do_reifyf_goal ------------------ 75.2% 75.4% 901 84.532s ─eexact -------------------------------- 17.1% 17.1% 903 0.140s ─ReflectiveTactics.solve_post_reified_si 0.2% 14.5% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s β””ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s β”œβ”€ReflectiveTactics.do_reify ---------- 0.0% 81.8% 1 91.740s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 81.6% 1 91.504s β”‚β””Reify.do_reify_abs_goal ------------- 75.6% 75.7% 2 84.892s β”‚β””Reify.do_reifyf_goal ---------------- 75.2% 75.4% 901 84.532s β”‚β””eexact ------------------------------ 16.9% 16.9% 901 0.140s └─ReflectiveTactics.solve_post_reified_ 0.2% 14.5% 1 16.260s β””UnifyAbstractReflexivity.unify_transf 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s src/Specific/NISTP256/AMD64/femul (real: 217.80, user: 202.52, sys: 0.53, mem: 3307052 ko) ROCQ compile src/Specific/NISTP256/AMD64/femulDisplay > src/Specific/NISTP256/AMD64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/ladderstep.v total time: 82.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s ─ReflectiveTactics.do_reflective_pipelin 0.0% 96.1% 1 78.784s ─ReflectiveTactics.solve_side_conditions 0.0% 95.9% 1 78.684s ─ReflectiveTactics.solve_post_reified_si 0.1% 72.6% 1 59.540s ─UnifyAbstractReflexivity.unify_transfor 64.6% 68.0% 8 30.740s ─ReflectiveTactics.do_reify ------------ 0.0% 23.3% 1 19.144s ─Reify.Reify_rhs_gen ------------------- 1.2% 14.5% 1 11.860s ─Reify.do_reifyf_goal ------------------ 7.1% 7.2% 138 1.908s ─Compilers.Reify.reify_context_variables 0.0% 5.9% 1 4.828s ─rewrite H ----------------------------- 4.4% 4.4% 1 3.600s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.0% 1 3.288s ─Glue.refine_to_reflective_glue' ------- 0.0% 3.0% 1 2.444s ─Glue.zrange_to_reflective ------------- 0.0% 2.5% 1 2.060s ─reflexivity --------------------------- 2.3% 2.3% 11 0.816s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.968s ─Glue.zrange_to_reflective_goal -------- 1.4% 2.1% 1 1.720s ─clear (var_list) ---------------------- 2.0% 2.0% 159 0.584s ─eexact -------------------------------- 2.0% 2.0% 140 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 96.1% 1 78.784s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 95.9% 1 78.684s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.1% 72.6% 1 59.540s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 64.6% 68.0% 8 30.740s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.0% 1 3.288s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 23.3% 1 19.144s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 1.2% 14.5% 1 11.860s β”‚ β”‚ β”œβ”€rewrite H --------------------- 4.4% 4.4% 1 3.600s β”‚ β”‚ └─Reify.transitivity_tt --------- 0.0% 2.1% 2 0.968s β”‚ └─Compilers.Reify.reify_context_var 0.0% 5.9% 1 4.828s β”‚ β””Reify.do_reifyf_goal ------------ 5.7% 5.8% 113 1.908s └─Glue.refine_to_reflective_glue' ----- 0.0% 3.0% 1 2.444s β””Glue.zrange_to_reflective ----------- 0.0% 2.5% 1 2.060s β””Glue.zrange_to_reflective_goal ------ 1.4% 2.1% 1 1.720s Finished transaction in 194.903 secs (185.732u,0.043s) (successful) Closed under the global context total time: 82.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s ─ReflectiveTactics.do_reflective_pipelin 0.0% 96.1% 1 78.784s ─ReflectiveTactics.solve_side_conditions 0.0% 95.9% 1 78.684s ─ReflectiveTactics.solve_post_reified_si 0.1% 72.6% 1 59.540s ─UnifyAbstractReflexivity.unify_transfor 64.6% 68.0% 8 30.740s ─ReflectiveTactics.do_reify ------------ 0.0% 23.3% 1 19.144s ─Reify.Reify_rhs_gen ------------------- 1.2% 14.5% 1 11.860s ─Reify.do_reifyf_goal ------------------ 7.1% 7.2% 138 1.908s ─Compilers.Reify.reify_context_variables 0.0% 5.9% 1 4.828s ─rewrite H ----------------------------- 4.4% 4.4% 1 3.600s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.0% 1 3.288s ─Glue.refine_to_reflective_glue' ------- 0.0% 3.0% 1 2.444s ─Glue.zrange_to_reflective ------------- 0.0% 2.5% 1 2.060s ─reflexivity --------------------------- 2.3% 2.3% 11 0.816s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.968s ─Glue.zrange_to_reflective_goal -------- 1.4% 2.1% 1 1.720s ─clear (var_list) ---------------------- 2.0% 2.0% 159 0.584s ─eexact -------------------------------- 2.0% 2.0% 140 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 96.1% 1 78.784s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 95.9% 1 78.684s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.1% 72.6% 1 59.540s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 64.6% 68.0% 8 30.740s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.0% 1 3.288s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 23.3% 1 19.144s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 1.2% 14.5% 1 11.860s β”‚ β”‚ β”œβ”€rewrite H --------------------- 4.4% 4.4% 1 3.600s β”‚ β”‚ └─Reify.transitivity_tt --------- 0.0% 2.1% 2 0.968s β”‚ └─Compilers.Reify.reify_context_var 0.0% 5.9% 1 4.828s β”‚ β””Reify.do_reifyf_goal ------------ 5.7% 5.8% 113 1.908s └─Glue.refine_to_reflective_glue' ----- 0.0% 3.0% 1 2.444s β””Glue.zrange_to_reflective ----------- 0.0% 2.5% 1 2.060s β””Glue.zrange_to_reflective_goal ------ 1.4% 2.1% 1 1.720s src/Specific/X25519/C64/ladderstep (real: 316.83, user: 299.49, sys: 0.52, mem: 1621500 ko) ROCQ compile src/Specific/X25519/C64/ladderstepDisplay > src/Specific/X25519/C64/ladderstepDisplay.log time-of-build-both-real-absolute.log.expected000066400000000000000000000076441516144147600375320ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-real-auto.log.expected000066400000000000000000000076441516144147600366640ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp time-of-build-both-real-diff.log.expected000066400000000000000000000076441516144147600366240ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul time-of-build-both-real.log.expected000066400000000000000000000076441516144147600357160ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp time-of-build-both-user-absolute.log.expected000066400000000000000000000076441516144147600375650ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-user-auto.log.expected000066400000000000000000000076441516144147600367170ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp time-of-build-both-user-diff.log.expected000066400000000000000000000076441516144147600366570ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul time-of-build-both-user.log.expected000066400000000000000000000076441516144147600357510ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order-mem After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order/000077500000000000000000000000001516144147600263735ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order/run.sh000077500000000000000000000020231516144147600275330ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_both_time_files time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-user.log diff -u time-of-build-both-user.log.expected time-of-build-both-user.log || exit $? $make_both_time_files --real time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-real.log diff -u time-of-build-both-real.log.expected time-of-build-both-real.log || exit $? for sort_kind in auto absolute diff; do $make_both_time_files time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-user-${sort_kind}.log --sort-by=${sort_kind} diff -u time-of-build-both-user-${sort_kind}.log.expected time-of-build-both-user-${sort_kind}.log || exit $? $make_both_time_files --real time-of-build-after.log.in time-of-build-before.log.in time-of-build-both-real-${sort_kind}.log --sort-by=${sort_kind} diff -u time-of-build-both-real-${sort_kind}.log.expected time-of-build-both-real-${sort_kind}.log || exit $? done rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order/time-of-build-after.log.in000066400000000000000000004053341516144147600332500ustar00rootroot00000000000000COQDEP src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v COQDEP src/Compilers/Z/Bounds/Pipeline/Definition.v /home/jgross/.local64/coq/coq-master/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-old COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C coqprime make[1]: Nothing to be done for 'all'. ECHO > _CoqProject ROCQ compile src/Compilers/Z/Bounds/Pipeline/Definition.v src/Compilers/Z/Bounds/Pipeline/Definition (real: 7.33, user: 7.18, sys: 0.14, mem: 574388 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics (real: 1.93, user: 1.72, sys: 0.20, mem: 544172 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline.v src/Compilers/Z/Bounds/Pipeline (real: 1.38, user: 1.19, sys: 0.16, mem: 539808 ko) ROCQ compile src/Specific/Framework/SynthesisFramework.v src/Specific/Framework/SynthesisFramework (real: 1.85, user: 1.67, sys: 0.17, mem: 646300 ko) ROCQ compile src/Specific/X25519/C64/Synthesis.v src/Specific/X25519/C64/Synthesis (real: 11.15, user: 10.37, sys: 0.18, mem: 687760 ko) ROCQ compile src/Specific/NISTP256/AMD64/Synthesis.v src/Specific/NISTP256/AMD64/Synthesis (real: 13.45, user: 12.55, sys: 0.19, mem: 668216 ko) ROCQ compile src/Specific/X25519/C64/feadd.v Finished transaction in 2.814 secs (2.624u,0.s) (successful) total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s Finished transaction in 5.021 secs (4.636u,0.s) (successful) Closed under the global context total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s src/Specific/X25519/C64/feadd (real: 22.81, user: 20.93, sys: 0.25, mem: 766300 ko) ROCQ compile src/Specific/X25519/C64/fecarry.v Finished transaction in 4.343 secs (4.016u,0.004s) (successful) total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s Finished transaction in 7.078 secs (6.728u,0.s) (successful) Closed under the global context total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s src/Specific/X25519/C64/fecarry (real: 27.11, user: 24.99, sys: 0.21, mem: 786052 ko) ROCQ compile src/Specific/solinas32_2e255m765_12limbs/Synthesis.v src/Specific/solinas32_2e255m765_12limbs/Synthesis (real: 40.13, user: 36.92, sys: 0.26, mem: 728464 ko) ROCQ compile src/Specific/solinas32_2e255m765_13limbs/Synthesis.v src/Specific/solinas32_2e255m765_13limbs/Synthesis (real: 49.44, user: 45.75, sys: 0.18, mem: 744240 ko) ROCQ compile src/Specific/X25519/C64/femul.v Finished transaction in 8.415 secs (7.664u,0.015s) (successful) total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s Finished transaction in 14.616 secs (13.528u,0.008s) (successful) Closed under the global context total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s src/Specific/X25519/C64/femul (real: 39.72, user: 36.32, sys: 0.26, mem: 825448 ko) ROCQ compile src/Specific/X25519/C64/feaddDisplay > src/Specific/X25519/C64/feaddDisplay.log ROCQ compile src/Specific/X25519/C64/fecarryDisplay > src/Specific/X25519/C64/fecarryDisplay.log ROCQ compile src/Specific/X25519/C64/fesub.v Finished transaction in 3.513 secs (3.211u,0.s) (successful) total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s Finished transaction in 6.12 secs (5.64u,0.008s) (successful) Closed under the global context total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s src/Specific/X25519/C64/fesub (real: 24.71, user: 22.65, sys: 0.24, mem: 778792 ko) ROCQ compile src/Specific/X25519/C64/fesquare.v Finished transaction in 6.132 secs (5.516u,0.012s) (successful) total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s Finished transaction in 10.475 secs (9.728u,0.007s) (successful) Closed under the global context total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s src/Specific/X25519/C64/fesquare (real: 33.08, user: 30.13, sys: 0.24, mem: 799620 ko) ROCQ compile src/Specific/X25519/C64/femulDisplay > src/Specific/X25519/C64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/freeze.v Finished transaction in 7.307 secs (6.763u,0.011s) (successful) total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s Finished transaction in 10.495 secs (9.756u,0.s) (successful) Closed under the global context total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s src/Specific/X25519/C64/freeze (real: 34.35, user: 31.50, sys: 0.24, mem: 828104 ko) ROCQ compile src/Specific/NISTP256/AMD64/feadd.v Finished transaction in 8.784 secs (8.176u,0.011s) (successful) total time: 8.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s ─ReflectiveTactics.do_reflective_pipelin 0.0% 43.8% 1 3.568s ─ReflectiveTactics.solve_side_conditions 0.0% 43.2% 1 3.520s ─IntegrationTestTemporaryMiscCommon.fact 1.4% 23.6% 1 1.924s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 22.1% 1 1.796s ─ReflectiveTactics.do_reify ------------ 0.1% 21.7% 1 1.768s ─ReflectiveTactics.solve_post_reified_si 0.6% 21.5% 1 1.752s ─Reify.Reify_rhs_gen ------------------- 1.0% 20.9% 1 1.704s ─op_sig_side_conditions_t -------------- 0.0% 20.0% 1 1.624s ─DestructHyps.do_all_matches_then ------ 0.0% 20.0% 8 0.244s ─DestructHyps.do_one_match_then -------- 0.7% 19.9% 44 0.052s ─do_tac -------------------------------- 0.0% 19.2% 36 0.052s ─destruct H ---------------------------- 19.2% 19.2% 36 0.052s ─rewrite <- (lem : lemT) by by_tac ltac: 0.2% 17.3% 1 1.408s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 17.3% 1 1.408s ─by_tac -------------------------------- 0.0% 17.1% 4 0.504s ─rewrite <- (ZRange.is_bounded_by_None_r 16.7% 16.7% 8 0.344s ─UnifyAbstractReflexivity.unify_transfor 13.3% 16.1% 7 0.360s ─Reify.do_reify_abs_goal --------------- 9.9% 10.1% 2 0.820s ─Reify.do_reifyf_goal ------------------ 9.1% 9.3% 93 0.748s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.6% 1 0.700s ─Glue.zrange_to_reflective ------------- 0.0% 5.3% 1 0.432s ─IntegrationTestTemporaryMiscCommon.do_s 0.0% 4.8% 1 0.388s ─ MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” src/Specific/NISTP256/AMD64/feaddDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fenzDisplay > src/Specific/NISTP256/AMD64/fenzDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_12limbs/femul.v Finished transaction in 50.426 secs (46.528u,0.072s) (successful) total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s Finished transaction in 80.129 secs (74.068u,0.024s) (successful) Closed under the global context total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s src/Specific/solinas32_2e255m765_12limbs/femul (real: 155.79, user: 143.70, sys: 0.32, mem: 1454696 ko) ROCQ compile src/Specific/NISTP256/AMD64/feoppDisplay > src/Specific/NISTP256/AMD64/feoppDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fesubDisplay > src/Specific/NISTP256/AMD64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/fesquareDisplay > src/Specific/X25519/C64/fesquareDisplay.log ROCQ compile src/Specific/X25519/C64/fesubDisplay > src/Specific/X25519/C64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/freezeDisplay > src/Specific/X25519/C64/freezeDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_13limbs/femul.v Finished transaction in 61.854 secs (57.328u,0.079s) (successful) total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s Finished transaction in 94.432 secs (86.96u,0.02s) (successful) Closed under the global context total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s src/Specific/solinas32_2e255m765_13limbs/femul (real: 181.77, user: 168.52, sys: 0.40, mem: 1589516 ko) ROCQ compile src/Specific/NISTP256/AMD64/femul.v Finished transaction in 119.257 secs (109.936u,0.256s) (successful) total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s Finished transaction in 61.452 secs (58.503u,0.055s) (successful) Closed under the global context total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s src/Specific/NISTP256/AMD64/femul (real: 202.96, user: 189.62, sys: 0.64, mem: 3302508 ko) ROCQ compile src/Specific/NISTP256/AMD64/femulDisplay > src/Specific/NISTP256/AMD64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/ladderstep.v total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s Finished transaction in 171.122 secs (161.392u,0.039s) (successful) Closed under the global context total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s src/Specific/X25519/C64/ladderstep (real: 256.77, user: 241.34, sys: 0.45, mem: 1617000 ko) ROCQ compile src/Specific/X25519/C64/ladderstepDisplay > src/Specific/X25519/C64/ladderstepDisplay.log rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order/time-of-build-before.log.in000066400000000000000000003664541516144147600334220ustar00rootroot00000000000000COQDEP src/Compilers/Z/Bounds/Pipeline/Definition.v COQDEP src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v /home/jgross/.local64/coq/coq-master/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-old COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C coqprime make[1]: Nothing to be done for 'all'. ECHO > _CoqProject ROCQ compile src/Compilers/Z/Bounds/Pipeline/Definition.v src/Compilers/Z/Bounds/Pipeline/Definition (real: 7.40, user: 7.22, sys: 0.15, mem: 578344 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics (real: 1.73, user: 1.58, sys: 0.14, mem: 546112 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline.v src/Compilers/Z/Bounds/Pipeline (real: 1.18, user: 1.04, sys: 0.14, mem: 539160 ko) ROCQ compile src/Specific/Framework/SynthesisFramework.v src/Specific/Framework/SynthesisFramework (real: 1.95, user: 1.72, sys: 0.22, mem: 648632 ko) ROCQ compile src/Specific/X25519/C64/Synthesis.v src/Specific/X25519/C64/Synthesis (real: 11.23, user: 10.30, sys: 0.19, mem: 687812 ko) ROCQ compile src/Specific/NISTP256/AMD64/Synthesis.v src/Specific/NISTP256/AMD64/Synthesis (real: 13.74, user: 12.54, sys: 0.23, mem: 667664 ko) ROCQ compile src/Specific/X25519/C64/feadd.v Finished transaction in 2.852 secs (2.699u,0.012s) (successful) total time: 2.664s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s ─ReflectiveTactics.do_reflective_pipelin 0.0% 70.9% 1 1.888s ─ReflectiveTactics.solve_side_conditions 0.0% 69.5% 1 1.852s ─ReflectiveTactics.solve_post_reified_si 1.4% 43.7% 1 1.164s ─UnifyAbstractReflexivity.unify_transfor 27.0% 31.7% 8 0.256s ─Glue.refine_to_reflective_glue' ------- 0.0% 26.6% 1 0.708s ─ReflectiveTactics.do_reify ------------ 0.0% 25.8% 1 0.688s ─Reify.Reify_rhs_gen ------------------- 2.0% 24.0% 1 0.640s ─Glue.zrange_to_reflective ------------- 0.0% 17.9% 1 0.476s ─Glue.zrange_to_reflective_goal -------- 8.1% 13.1% 1 0.348s ─Reify.do_reify_abs_goal --------------- 12.8% 12.9% 2 0.344s ─Reify.do_reifyf_goal ------------------ 11.7% 11.9% 16 0.316s ─ReflectiveTactics.unify_abstract_cbv_in 7.7% 10.2% 1 0.272s ─unify (constr) (constr) --------------- 6.0% 6.0% 7 0.064s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.0% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 4.5% 4.7% 2 0.068s ─Glue.pattern_proj1_sig_in_sig --------- 1.5% 4.7% 1 0.124s ─pose proof (pf : Interpretation.Bo 3.3% 3.3% 1 0.088s ─Glue.split_BoundedWordToZ ------------- 0.2% 3.0% 1 0.080s ─destruct x ---------------------------- 2.7% 2.7% 4 0.032s ─clearbody (ne_var_list) --------------- 2.7% 2.7% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.7% 4 0.040s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─prove_interp_compile_correct ---------- 0.0% 2.4% 1 0.064s ─reflexivity --------------------------- 2.3% 2.3% 7 0.028s ─rewrite ?EtaInterp.InterpExprEta ------ 2.3% 2.3% 1 0.060s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.1% 2 0.056s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 70.9% 1 1.888s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 69.5% 1 1.852s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.4% 43.7% 1 1.164s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 27.0% 31.7% 8 0.256s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 7.7% 10.2% 1 0.272s β”‚ β”‚ β””unify (constr) (constr) --------- 2.4% 2.4% 1 0.064s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 25.8% 1 0.688s β”‚ β””Reify.Reify_rhs_gen --------------- 2.0% 24.0% 1 0.640s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 12.8% 12.9% 2 0.344s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 11.7% 11.9% 16 0.316s β”‚ └─prove_interp_compile_correct ---- 0.0% 2.4% 1 0.064s β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.3% 2.3% 1 0.060s └─Glue.refine_to_reflective_glue' ----- 0.0% 26.6% 1 0.708s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 17.9% 1 0.476s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 8.1% 13.1% 1 0.348s β”‚ β”‚β””pose proof (pf : Interpretat 3.3% 3.3% 1 0.088s β”‚ └─assert (H : is_bounded_by' bounds 4.5% 4.7% 2 0.068s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.0% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.5% 4.7% 1 0.124s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.1% 2 0.056s β”‚β””clearbody (ne_var_list) ----------- 2.1% 2.1% 1 0.056s └─Glue.split_BoundedWordToZ --------- 0.2% 3.0% 1 0.080s β””destruct_sig ---------------------- 0.0% 2.7% 4 0.040s β””destruct x ------------------------ 2.1% 2.1% 2 0.032s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s Finished transaction in 5.46 secs (5.068u,0.003s) (successful) Closed under the global context total time: 2.664s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s ─ReflectiveTactics.do_reflective_pipelin 0.0% 70.9% 1 1.888s ─ReflectiveTactics.solve_side_conditions 0.0% 69.5% 1 1.852s ─ReflectiveTactics.solve_post_reified_si 1.4% 43.7% 1 1.164s ─UnifyAbstractReflexivity.unify_transfor 27.0% 31.7% 8 0.256s ─Glue.refine_to_reflective_glue' ------- 0.0% 26.6% 1 0.708s ─ReflectiveTactics.do_reify ------------ 0.0% 25.8% 1 0.688s ─Reify.Reify_rhs_gen ------------------- 2.0% 24.0% 1 0.640s ─Glue.zrange_to_reflective ------------- 0.0% 17.9% 1 0.476s ─Glue.zrange_to_reflective_goal -------- 8.1% 13.1% 1 0.348s ─Reify.do_reify_abs_goal --------------- 12.8% 12.9% 2 0.344s ─Reify.do_reifyf_goal ------------------ 11.7% 11.9% 16 0.316s ─ReflectiveTactics.unify_abstract_cbv_in 7.7% 10.2% 1 0.272s ─unify (constr) (constr) --------------- 6.0% 6.0% 7 0.064s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.0% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 4.5% 4.7% 2 0.068s ─Glue.pattern_proj1_sig_in_sig --------- 1.5% 4.7% 1 0.124s ─pose proof (pf : Interpretation.Bo 3.3% 3.3% 1 0.088s ─Glue.split_BoundedWordToZ ------------- 0.2% 3.0% 1 0.080s ─destruct x ---------------------------- 2.7% 2.7% 4 0.032s ─clearbody (ne_var_list) --------------- 2.7% 2.7% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.7% 4 0.040s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─prove_interp_compile_correct ---------- 0.0% 2.4% 1 0.064s ─reflexivity --------------------------- 2.3% 2.3% 7 0.028s ─rewrite ?EtaInterp.InterpExprEta ------ 2.3% 2.3% 1 0.060s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.1% 2 0.056s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.4% 1 2.596s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 70.9% 1 1.888s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 69.5% 1 1.852s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.4% 43.7% 1 1.164s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 27.0% 31.7% 8 0.256s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 7.7% 10.2% 1 0.272s β”‚ β”‚ β””unify (constr) (constr) --------- 2.4% 2.4% 1 0.064s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 25.8% 1 0.688s β”‚ β””Reify.Reify_rhs_gen --------------- 2.0% 24.0% 1 0.640s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 12.8% 12.9% 2 0.344s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 11.7% 11.9% 16 0.316s β”‚ └─prove_interp_compile_correct ---- 0.0% 2.4% 1 0.064s β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.3% 2.3% 1 0.060s └─Glue.refine_to_reflective_glue' ----- 0.0% 26.6% 1 0.708s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 17.9% 1 0.476s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 8.1% 13.1% 1 0.348s β”‚ β”‚β””pose proof (pf : Interpretat 3.3% 3.3% 1 0.088s β”‚ └─assert (H : is_bounded_by' bounds 4.5% 4.7% 2 0.068s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.0% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.5% 4.7% 1 0.124s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.1% 2 0.056s β”‚β””clearbody (ne_var_list) ----------- 2.1% 2.1% 1 0.056s └─Glue.split_BoundedWordToZ --------- 0.2% 3.0% 1 0.080s β””destruct_sig ---------------------- 0.0% 2.7% 4 0.040s β””destruct x ------------------------ 2.1% 2.1% 2 0.032s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s src/Specific/X25519/C64/feadd (real: 23.43, user: 21.41, sys: 0.26, mem: 766168 ko) ROCQ compile src/Specific/solinas32_2e255m765_12limbs/Synthesis.v src/Specific/solinas32_2e255m765_12limbs/Synthesis (real: 39.53, user: 36.64, sys: 0.21, mem: 729464 ko) ROCQ compile src/Specific/X25519/C64/fecarry.v Finished transaction in 4.798 secs (4.375u,0.003s) (successful) total time: 4.332s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 3.864s ─ReflectiveTactics.solve_side_conditions 0.0% 88.1% 1 3.816s ─ReflectiveTactics.do_reify ------------ 0.0% 53.2% 1 2.304s ─Reify.Reify_rhs_gen ------------------- 1.8% 52.6% 1 2.280s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.9% 1 1.512s ─Reify.do_reify_abs_goal --------------- 33.5% 33.9% 2 1.468s ─Reify.do_reifyf_goal ------------------ 32.1% 32.5% 29 1.408s ─UnifyAbstractReflexivity.unify_transfor 22.5% 27.1% 8 0.316s ─Glue.refine_to_reflective_glue' ------- 0.1% 9.7% 1 0.420s ─eexact -------------------------------- 9.3% 9.3% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.0% 1 0.304s ─Glue.zrange_to_reflective ------------- 0.1% 6.2% 1 0.268s ─prove_interp_compile_correct ---------- 0.0% 5.6% 1 0.244s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.228s ─unify (constr) (constr) --------------- 5.3% 5.3% 7 0.076s ─Glue.zrange_to_reflective_goal -------- 4.0% 4.9% 1 0.212s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.148s ─tac ----------------------------------- 1.8% 2.6% 2 0.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 3.864s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.1% 1 3.816s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 53.2% 1 2.304s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 52.6% 1 2.280s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 33.5% 33.9% 2 1.468s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 32.1% 32.5% 29 1.408s β”‚ β”‚ β”‚β””eexact -------------------------- 8.6% 8.6% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.6% 1 0.244s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.3% 5.3% 1 0.228s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.148s β”‚ β”‚ └─tac ----------------------------- 1.8% 2.6% 1 0.112s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.9% 1 1.512s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.5% 27.1% 8 0.316s β”‚ β”‚β””unify (constr) (constr) --------- 3.5% 3.5% 6 0.044s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.0% 1 0.304s └─Glue.refine_to_reflective_glue' ----- 0.1% 9.7% 1 0.420s β””Glue.zrange_to_reflective ----------- 0.1% 6.2% 1 0.268s β””Glue.zrange_to_reflective_goal ------ 4.0% 4.9% 1 0.212s Finished transaction in 8.342 secs (7.604u,0.008s) (successful) Closed under the global context total time: 4.332s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 3.864s ─ReflectiveTactics.solve_side_conditions 0.0% 88.1% 1 3.816s ─ReflectiveTactics.do_reify ------------ 0.0% 53.2% 1 2.304s ─Reify.Reify_rhs_gen ------------------- 1.8% 52.6% 1 2.280s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.9% 1 1.512s ─Reify.do_reify_abs_goal --------------- 33.5% 33.9% 2 1.468s ─Reify.do_reifyf_goal ------------------ 32.1% 32.5% 29 1.408s ─UnifyAbstractReflexivity.unify_transfor 22.5% 27.1% 8 0.316s ─Glue.refine_to_reflective_glue' ------- 0.1% 9.7% 1 0.420s ─eexact -------------------------------- 9.3% 9.3% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.0% 1 0.304s ─Glue.zrange_to_reflective ------------- 0.1% 6.2% 1 0.268s ─prove_interp_compile_correct ---------- 0.0% 5.6% 1 0.244s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.228s ─unify (constr) (constr) --------------- 5.3% 5.3% 7 0.076s ─Glue.zrange_to_reflective_goal -------- 4.0% 4.9% 1 0.212s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.148s ─tac ----------------------------------- 1.8% 2.6% 2 0.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.1% 99.0% 1 4.288s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 3.864s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.1% 1 3.816s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 53.2% 1 2.304s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 52.6% 1 2.280s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 33.5% 33.9% 2 1.468s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 32.1% 32.5% 29 1.408s β”‚ β”‚ β”‚β””eexact -------------------------- 8.6% 8.6% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.6% 1 0.244s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.3% 5.3% 1 0.228s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.148s β”‚ β”‚ └─tac ----------------------------- 1.8% 2.6% 1 0.112s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.9% 1 1.512s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.5% 27.1% 8 0.316s β”‚ β”‚β””unify (constr) (constr) --------- 3.5% 3.5% 6 0.044s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.0% 1 0.304s └─Glue.refine_to_reflective_glue' ----- 0.1% 9.7% 1 0.420s β””Glue.zrange_to_reflective ----------- 0.1% 6.2% 1 0.268s β””Glue.zrange_to_reflective_goal ------ 4.0% 4.9% 1 0.212s src/Specific/X25519/C64/fecarry (real: 28.85, user: 26.31, sys: 0.25, mem: 787148 ko) ROCQ compile src/Specific/solinas32_2e255m765_13limbs/Synthesis.v src/Specific/solinas32_2e255m765_13limbs/Synthesis (real: 49.50, user: 45.58, sys: 0.18, mem: 744472 ko) ROCQ compile src/Specific/X25519/C64/femul.v Finished transaction in 9.325 secs (8.62u,0.016s) (successful) total time: 8.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.7% 1 7.524s ─ReflectiveTactics.solve_side_conditions 0.0% 87.0% 1 7.460s ─ReflectiveTactics.do_reify ------------ 0.0% 43.8% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.6% 43.1% 1 3.700s ─Reify.Reify_rhs_gen ------------------- 1.4% 43.0% 1 3.688s ─UnifyAbstractReflexivity.unify_transfor 31.1% 36.7% 8 1.096s ─Reify.do_reify_abs_goal --------------- 26.3% 26.6% 2 2.284s ─Reify.do_reifyf_goal ------------------ 25.3% 25.6% 58 1.440s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.1% 1 0.696s ─eexact -------------------------------- 7.6% 7.6% 60 0.032s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.128s ─Glue.zrange_to_reflective ------------- 0.0% 5.7% 1 0.488s ─ReflectiveTactics.unify_abstract_cbv_in 3.8% 5.5% 1 0.468s ─prove_interp_compile_correct ---------- 0.0% 5.2% 1 0.448s ─rewrite ?EtaInterp.InterpExprEta ------ 4.9% 4.9% 1 0.416s ─Glue.zrange_to_reflective_goal -------- 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s ─rewrite H ----------------------------- 3.2% 3.2% 1 0.276s ─change G' ----------------------------- 3.2% 3.2% 1 0.272s ─tac ----------------------------------- 1.4% 2.1% 2 0.180s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.7% 1 7.524s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 87.0% 1 7.460s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 43.8% 1 3.760s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.4% 43.0% 1 3.688s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 26.3% 26.6% 2 2.284s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 25.3% 25.6% 58 1.440s β”‚ β”‚ β”‚β””eexact -------------------------- 6.9% 6.9% 58 0.032s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.2% 1 0.448s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.9% 4.9% 1 0.416s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.2% 3.2% 1 0.276s β”‚ β”‚ └─tac ----------------------------- 1.4% 2.1% 1 0.180s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 43.1% 1 3.700s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 31.1% 36.7% 8 1.096s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 6 0.092s β”‚ └─ReflectiveTactics.unify_abstract_ 3.8% 5.5% 1 0.468s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.1% 1 0.696s β””Glue.zrange_to_reflective ----------- 0.0% 5.7% 1 0.488s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s β””change G' ----------------------------- 3.2% 3.2% 1 0.272s Finished transaction in 16.611 secs (15.352u,0.s) (successful) Closed under the global context total time: 8.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.7% 1 7.524s ─ReflectiveTactics.solve_side_conditions 0.0% 87.0% 1 7.460s ─ReflectiveTactics.do_reify ------------ 0.0% 43.8% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.6% 43.1% 1 3.700s ─Reify.Reify_rhs_gen ------------------- 1.4% 43.0% 1 3.688s ─UnifyAbstractReflexivity.unify_transfor 31.1% 36.7% 8 1.096s ─Reify.do_reify_abs_goal --------------- 26.3% 26.6% 2 2.284s ─Reify.do_reifyf_goal ------------------ 25.3% 25.6% 58 1.440s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.1% 1 0.696s ─eexact -------------------------------- 7.6% 7.6% 60 0.032s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.128s ─Glue.zrange_to_reflective ------------- 0.0% 5.7% 1 0.488s ─ReflectiveTactics.unify_abstract_cbv_in 3.8% 5.5% 1 0.468s ─prove_interp_compile_correct ---------- 0.0% 5.2% 1 0.448s ─rewrite ?EtaInterp.InterpExprEta ------ 4.9% 4.9% 1 0.416s ─Glue.zrange_to_reflective_goal -------- 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s ─rewrite H ----------------------------- 3.2% 3.2% 1 0.276s ─change G' ----------------------------- 3.2% 3.2% 1 0.272s ─tac ----------------------------------- 1.4% 2.1% 2 0.180s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.8% 1 8.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.7% 1 7.524s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 87.0% 1 7.460s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 43.8% 1 3.760s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.4% 43.0% 1 3.688s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 26.3% 26.6% 2 2.284s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 25.3% 25.6% 58 1.440s β”‚ β”‚ β”‚β””eexact -------------------------- 6.9% 6.9% 58 0.032s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.2% 1 0.448s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.9% 4.9% 1 0.416s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.2% 3.2% 1 0.276s β”‚ β”‚ └─tac ----------------------------- 1.4% 2.1% 1 0.180s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 43.1% 1 3.700s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 31.1% 36.7% 8 1.096s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 6 0.092s β”‚ └─ReflectiveTactics.unify_abstract_ 3.8% 5.5% 1 0.468s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.1% 1 0.696s β””Glue.zrange_to_reflective ----------- 0.0% 5.7% 1 0.488s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.2% 1 0.364s ─synthesize ---------------------------- 0.0% 4.2% 1 0.356s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 3.8% 1 0.328s β””change G' ----------------------------- 3.2% 3.2% 1 0.272s src/Specific/X25519/C64/femul (real: 42.98, user: 39.50, sys: 0.29, mem: 839624 ko) ROCQ compile src/Specific/X25519/C64/feaddDisplay > src/Specific/X25519/C64/feaddDisplay.log ROCQ compile src/Specific/X25519/C64/fecarryDisplay > src/Specific/X25519/C64/fecarryDisplay.log ROCQ compile src/Specific/X25519/C64/fesub.v Finished transaction in 3.729 secs (3.48u,0.012s) (successful) total time: 3.444s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s ─ReflectiveTactics.do_reflective_pipelin 0.0% 77.1% 1 2.656s ─ReflectiveTactics.solve_side_conditions 0.0% 75.8% 1 2.612s ─ReflectiveTactics.solve_post_reified_si 1.2% 40.1% 1 1.380s ─ReflectiveTactics.do_reify ------------ 0.0% 35.8% 1 1.232s ─Reify.Reify_rhs_gen ------------------- 1.4% 34.4% 1 1.184s ─UnifyAbstractReflexivity.unify_transfor 25.7% 30.5% 8 0.324s ─Glue.refine_to_reflective_glue' ------- 0.0% 20.9% 1 0.720s ─Reify.do_reify_abs_goal --------------- 18.5% 18.8% 2 0.648s ─Reify.do_reifyf_goal ------------------ 17.3% 17.5% 16 0.604s ─Glue.zrange_to_reflective ------------- 0.0% 14.2% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.5% 10.6% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 5.8% 8.0% 1 0.276s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.076s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 3.8% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 3.6% 3.6% 2 0.064s ─Glue.pattern_proj1_sig_in_sig --------- 1.2% 3.6% 1 0.124s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 0.120s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.116s ─rewrite ?EtaInterp.InterpExprEta ------ 3.1% 3.1% 1 0.108s ─pose proof (pf : Interpretation.Bo 2.7% 2.7% 1 0.092s ─reflexivity --------------------------- 2.6% 2.6% 7 0.032s ─Glue.split_BoundedWordToZ ------------- 0.2% 2.4% 1 0.084s ─tac ----------------------------------- 1.7% 2.2% 2 0.076s ─Reify.transitivity_tt ----------------- 0.1% 2.2% 2 0.040s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s ─clearbody (ne_var_list) --------------- 2.1% 2.1% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.1% 4 0.040s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 77.1% 1 2.656s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 75.8% 1 2.612s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 40.1% 1 1.380s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.7% 30.5% 8 0.324s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.040s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 5.8% 8.0% 1 0.276s β”‚ β”‚ β””unify (constr) (constr) --------- 2.2% 2.2% 1 0.076s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 35.8% 1 1.232s β”‚ β””Reify.Reify_rhs_gen --------------- 1.4% 34.4% 1 1.184s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 18.5% 18.8% 2 0.648s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 17.3% 17.5% 16 0.604s β”‚ β”‚β””eexact -------------------------- 3.8% 3.8% 16 0.012s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.5% 1 0.120s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.1% 3.1% 1 0.108s β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.116s β”‚ β”œβ”€tac ----------------------------- 1.7% 2.2% 1 0.076s β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.2% 2 0.040s └─Glue.refine_to_reflective_glue' ----- 0.0% 20.9% 1 0.720s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 14.2% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.5% 10.6% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.7% 2.7% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.6% 3.6% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 3.8% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.2% 3.6% 1 0.124s └─Glue.split_BoundedWordToZ --------- 0.2% 2.4% 1 0.084s β””destruct_sig ---------------------- 0.0% 2.1% 4 0.040s Finished transaction in 6.763 secs (6.183u,0.s) (successful) Closed under the global context total time: 3.444s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s ─ReflectiveTactics.do_reflective_pipelin 0.0% 77.1% 1 2.656s ─ReflectiveTactics.solve_side_conditions 0.0% 75.8% 1 2.612s ─ReflectiveTactics.solve_post_reified_si 1.2% 40.1% 1 1.380s ─ReflectiveTactics.do_reify ------------ 0.0% 35.8% 1 1.232s ─Reify.Reify_rhs_gen ------------------- 1.4% 34.4% 1 1.184s ─UnifyAbstractReflexivity.unify_transfor 25.7% 30.5% 8 0.324s ─Glue.refine_to_reflective_glue' ------- 0.0% 20.9% 1 0.720s ─Reify.do_reify_abs_goal --------------- 18.5% 18.8% 2 0.648s ─Reify.do_reifyf_goal ------------------ 17.3% 17.5% 16 0.604s ─Glue.zrange_to_reflective ------------- 0.0% 14.2% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.5% 10.6% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 5.8% 8.0% 1 0.276s ─unify (constr) (constr) --------------- 5.8% 5.8% 7 0.076s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 3.8% 1 0.132s ─assert (H : is_bounded_by' bounds (map' 3.6% 3.6% 2 0.064s ─Glue.pattern_proj1_sig_in_sig --------- 1.2% 3.6% 1 0.124s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 0.120s ─rewrite H ----------------------------- 3.4% 3.4% 1 0.116s ─rewrite ?EtaInterp.InterpExprEta ------ 3.1% 3.1% 1 0.108s ─pose proof (pf : Interpretation.Bo 2.7% 2.7% 1 0.092s ─reflexivity --------------------------- 2.6% 2.6% 7 0.032s ─Glue.split_BoundedWordToZ ------------- 0.2% 2.4% 1 0.084s ─tac ----------------------------------- 1.7% 2.2% 2 0.076s ─Reify.transitivity_tt ----------------- 0.1% 2.2% 2 0.040s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s ─clearbody (ne_var_list) --------------- 2.1% 2.1% 4 0.056s ─destruct_sig -------------------------- 0.0% 2.1% 4 0.040s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 98.0% 1 3.376s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 77.1% 1 2.656s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 75.8% 1 2.612s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 40.1% 1 1.380s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.7% 30.5% 8 0.324s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.6% 3.6% 6 0.040s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 5.8% 8.0% 1 0.276s β”‚ β”‚ β””unify (constr) (constr) --------- 2.2% 2.2% 1 0.076s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 35.8% 1 1.232s β”‚ β””Reify.Reify_rhs_gen --------------- 1.4% 34.4% 1 1.184s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 18.5% 18.8% 2 0.648s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 17.3% 17.5% 16 0.604s β”‚ β”‚β””eexact -------------------------- 3.8% 3.8% 16 0.012s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.5% 1 0.120s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.1% 3.1% 1 0.108s β”‚ β”œβ”€rewrite H ----------------------- 3.4% 3.4% 1 0.116s β”‚ β”œβ”€tac ----------------------------- 1.7% 2.2% 1 0.076s β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.2% 2 0.040s └─Glue.refine_to_reflective_glue' ----- 0.0% 20.9% 1 0.720s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 14.2% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.5% 10.6% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.7% 2.7% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.6% 3.6% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 3.8% 1 0.132s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.2% 3.6% 1 0.124s └─Glue.split_BoundedWordToZ --------- 0.2% 2.4% 1 0.084s β””destruct_sig ---------------------- 0.0% 2.1% 4 0.040s src/Specific/X25519/C64/fesub (real: 26.11, user: 23.72, sys: 0.24, mem: 781808 ko) ROCQ compile src/Specific/X25519/C64/fesquare.v Finished transaction in 6.477 secs (6.044u,0.008s) (successful) total time: 6.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 5.764s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.6% 1 5.388s ─ReflectiveTactics.solve_side_conditions 0.0% 88.8% 1 5.340s ─ReflectiveTactics.do_reify ------------ 0.0% 47.0% 1 2.828s ─Reify.Reify_rhs_gen ------------------- 1.5% 46.3% 1 2.784s ─ReflectiveTactics.solve_post_reified_si 0.5% 41.8% 1 2.512s ─UnifyAbstractReflexivity.unify_transfor 28.5% 34.1% 8 0.552s ─Reify.do_reify_abs_goal --------------- 28.7% 29.1% 2 1.752s ─Reify.do_reifyf_goal ------------------ 27.6% 27.9% 47 1.320s ─eexact -------------------------------- 8.4% 8.4% 49 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.412s ─unify (constr) (constr) --------------- 6.3% 6.3% 7 0.104s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.3% 1 0.376s ─prove_interp_compile_correct ---------- 0.0% 5.3% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 4.8% 4.8% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.0% 4.4% 1 0.264s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 3.7% 1 0.224s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.3% 1 0.196s ─change G' ----------------------------- 3.1% 3.1% 1 0.188s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.180s ─tac ----------------------------------- 1.9% 2.7% 2 0.160s ─reflexivity --------------------------- 2.4% 2.4% 7 0.060s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.9% 1 5.764s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 89.6% 1 5.388s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 88.8% 1 5.340s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 47.0% 1 2.828s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 1.5% 46.3% 1 2.784s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 28.7% 29.1% 2 1.752s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 27.6% 27.9% 47 1.320s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 7.7% 7.7% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.3% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 4.8% 4.8% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€rewrite H --------------------- 3.0% 3.0% 1 0.180s β”‚ β”‚ β”‚ └─tac --------------------------- 1.9% 2.7% 1 0.160s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.5% 41.8% 1 2.512s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 28.5% 34.1% 8 0.552s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 4.6% 4.6% 6 0.076s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.412s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 6.3% 1 0.376s β”‚ β””Glue.zrange_to_reflective --------- 0.0% 4.4% 1 0.264s β”‚ β””Glue.zrange_to_reflective_goal ---- 2.6% 3.3% 1 0.196s └─IntegrationTestTemporaryMiscCommon.do 0.1% 3.7% 1 0.224s β””change G' --------------------------- 3.1% 3.1% 1 0.188s Finished transaction in 12.356 secs (11.331u,0.004s) (successful) Closed under the global context total time: 6.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 5.764s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.6% 1 5.388s ─ReflectiveTactics.solve_side_conditions 0.0% 88.8% 1 5.340s ─ReflectiveTactics.do_reify ------------ 0.0% 47.0% 1 2.828s ─Reify.Reify_rhs_gen ------------------- 1.5% 46.3% 1 2.784s ─ReflectiveTactics.solve_post_reified_si 0.5% 41.8% 1 2.512s ─UnifyAbstractReflexivity.unify_transfor 28.5% 34.1% 8 0.552s ─Reify.do_reify_abs_goal --------------- 28.7% 29.1% 2 1.752s ─Reify.do_reifyf_goal ------------------ 27.6% 27.9% 47 1.320s ─eexact -------------------------------- 8.4% 8.4% 49 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.412s ─unify (constr) (constr) --------------- 6.3% 6.3% 7 0.104s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.3% 1 0.376s ─prove_interp_compile_correct ---------- 0.0% 5.3% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 4.8% 4.8% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.0% 4.4% 1 0.264s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 3.7% 1 0.224s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.3% 1 0.196s ─change G' ----------------------------- 3.1% 3.1% 1 0.188s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.180s ─tac ----------------------------------- 1.9% 2.7% 2 0.160s ─reflexivity --------------------------- 2.4% 2.4% 7 0.060s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- 0.0% 100.0% 1 6.012s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.9% 1 5.764s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 89.6% 1 5.388s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 88.8% 1 5.340s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 47.0% 1 2.828s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 1.5% 46.3% 1 2.784s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 28.7% 29.1% 2 1.752s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 27.6% 27.9% 47 1.320s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 7.7% 7.7% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.3% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 4.8% 4.8% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€rewrite H --------------------- 3.0% 3.0% 1 0.180s β”‚ β”‚ β”‚ └─tac --------------------------- 1.9% 2.7% 1 0.160s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.5% 41.8% 1 2.512s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 28.5% 34.1% 8 0.552s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 4.6% 4.6% 6 0.076s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.412s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 6.3% 1 0.376s β”‚ β””Glue.zrange_to_reflective --------- 0.0% 4.4% 1 0.264s β”‚ β””Glue.zrange_to_reflective_goal ---- 2.6% 3.3% 1 0.196s └─IntegrationTestTemporaryMiscCommon.do 0.1% 3.7% 1 0.224s β””change G' --------------------------- 3.1% 3.1% 1 0.188s src/Specific/X25519/C64/fesquare (real: 35.23, user: 32.24, sys: 0.26, mem: 802776 ko) ROCQ compile src/Specific/X25519/C64/femulDisplay > src/Specific/X25519/C64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/freeze.v Finished transaction in 7.785 secs (7.139u,0.019s) (successful) total time: 7.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.600s ─ReflectiveTactics.solve_side_conditions -0.0% 91.8% 1 6.532s ─ReflectiveTactics.do_reify ------------ 0.0% 57.1% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 56.4% 1 4.012s ─Reify.do_reify_abs_goal --------------- 40.1% 40.3% 2 2.868s ─Reify.do_reifyf_goal ------------------ 39.1% 39.4% 129 2.800s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.8% 1 2.472s ─UnifyAbstractReflexivity.unify_transfor 25.2% 29.4% 8 0.428s ─eexact -------------------------------- 12.9% 12.9% 131 0.028s ─Glue.refine_to_reflective_glue' ------- 0.1% 6.4% 1 0.456s ─prove_interp_compile_correct ---------- 0.0% 4.7% 1 0.332s ─unify (constr) (constr) --------------- 4.6% 4.6% 7 0.096s ─ReflectiveTactics.unify_abstract_cbv_in 3.1% 4.6% 1 0.324s ─rewrite ?EtaInterp.InterpExprEta ------ 4.3% 4.3% 1 0.308s ─Glue.zrange_to_reflective ------------- 0.0% 4.1% 1 0.292s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.2% 1 0.228s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.212s ─reflexivity --------------------------- 2.3% 2.3% 7 0.064s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.096s ─transitivity -------------------------- 2.1% 2.1% 5 0.084s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.600s β”‚β””ReflectiveTactics.solve_side_conditio -0.0% 91.8% 1 6.532s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 57.1% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 56.4% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 40.1% 40.3% 2 2.868s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 39.1% 39.4% 129 2.800s β”‚ β”‚ β”‚β””eexact -------------------------- 12.4% 12.4% 129 0.028s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 4.7% 1 0.332s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.3% 4.3% 1 0.308s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.212s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.096s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.084s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.8% 1 2.472s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.2% 29.4% 8 0.428s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 6 0.068s β”‚ └─ReflectiveTactics.unify_abstract_ 3.1% 4.6% 1 0.324s └─Glue.refine_to_reflective_glue' ----- 0.1% 6.4% 1 0.456s β””Glue.zrange_to_reflective ----------- 0.0% 4.1% 1 0.292s β””Glue.zrange_to_reflective_goal ------ 2.6% 3.2% 1 0.228s Finished transaction in 12.063 secs (11.036u,0.012s) (successful) Closed under the global context total time: 7.112s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.600s ─ReflectiveTactics.solve_side_conditions -0.0% 91.8% 1 6.532s ─ReflectiveTactics.do_reify ------------ 0.0% 57.1% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 56.4% 1 4.012s ─Reify.do_reify_abs_goal --------------- 40.1% 40.3% 2 2.868s ─Reify.do_reifyf_goal ------------------ 39.1% 39.4% 129 2.800s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.8% 1 2.472s ─UnifyAbstractReflexivity.unify_transfor 25.2% 29.4% 8 0.428s ─eexact -------------------------------- 12.9% 12.9% 131 0.028s ─Glue.refine_to_reflective_glue' ------- 0.1% 6.4% 1 0.456s ─prove_interp_compile_correct ---------- 0.0% 4.7% 1 0.332s ─unify (constr) (constr) --------------- 4.6% 4.6% 7 0.096s ─ReflectiveTactics.unify_abstract_cbv_in 3.1% 4.6% 1 0.324s ─rewrite ?EtaInterp.InterpExprEta ------ 4.3% 4.3% 1 0.308s ─Glue.zrange_to_reflective ------------- 0.0% 4.1% 1 0.292s ─Glue.zrange_to_reflective_goal -------- 2.6% 3.2% 1 0.228s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.212s ─reflexivity --------------------------- 2.3% 2.3% 7 0.064s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.096s ─transitivity -------------------------- 2.1% 2.1% 5 0.084s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- -0.0% 100.0% 1 7.112s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.2% 1 7.056s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.600s β”‚β””ReflectiveTactics.solve_side_conditio -0.0% 91.8% 1 6.532s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 57.1% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 56.4% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 40.1% 40.3% 2 2.868s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 39.1% 39.4% 129 2.800s β”‚ β”‚ β”‚β””eexact -------------------------- 12.4% 12.4% 129 0.028s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 4.7% 1 0.332s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.3% 4.3% 1 0.308s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.212s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.096s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.084s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 34.8% 1 2.472s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 25.2% 29.4% 8 0.428s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 6 0.068s β”‚ └─ReflectiveTactics.unify_abstract_ 3.1% 4.6% 1 0.324s └─Glue.refine_to_reflective_glue' ----- 0.1% 6.4% 1 0.456s β””Glue.zrange_to_reflective ----------- 0.0% 4.1% 1 0.292s β””Glue.zrange_to_reflective_goal ------ 2.6% 3.2% 1 0.228s src/Specific/X25519/C64/freeze (real: 36.42, user: 33.24, sys: 0.26, mem: 826476 ko) ROCQ compile src/Specific/NISTP256/AMD64/feadd.v Finished transaction in 9.065 secs (8.452u,0.004s) (successful) total time: 8.408s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s ─ReflectiveTactics.do_reflective_pipelin 0.0% 47.7% 1 4.012s ─ReflectiveTactics.solve_side_conditions 0.0% 47.1% 1 3.960s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s ─ReflectiveTactics.solve_post_reified_si 0.6% 26.4% 1 2.220s ─UnifyAbstractReflexivity.unify_transfor 18.0% 21.3% 8 0.508s ─IntegrationTestTemporaryMiscCommon.fact 1.3% 21.3% 1 1.788s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 21.0% 1 1.768s ─ReflectiveTactics.do_reify ------------ 0.0% 20.7% 1 1.740s ─Reify.Reify_rhs_gen ------------------- 1.0% 20.0% 1 1.684s ─DestructHyps.do_all_matches_then ------ 0.1% 18.6% 8 0.220s ─DestructHyps.do_one_match_then -------- 0.8% 18.5% 44 0.056s ─op_sig_side_conditions_t -------------- 0.0% 17.9% 1 1.504s ─do_tac -------------------------------- 0.0% 17.7% 43 0.052s ─destruct H ---------------------------- 17.7% 17.7% 36 0.052s ─rewrite <- (lem : lemT) by by_tac ltac: 0.3% 17.3% 1 1.452s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 17.3% 1 1.452s ─by_tac -------------------------------- 0.0% 17.0% 4 0.532s ─rewrite <- (ZRange.is_bounded_by_None_r 15.7% 15.8% 8 0.360s ─Reify.do_reify_abs_goal --------------- 9.1% 9.3% 2 0.780s ─Reify.do_reifyf_goal ------------------ 8.5% 8.6% 93 0.716s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 0.700s ─Glue.zrange_to_reflective ------------- 0.0% 5.3% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.3% 1 0.360s ─Glue.zrange_to_reflective_goal -------- 2.5% 4.0% 1 0.336s ─unify (constr) (constr) --------------- 3.9% 3.9% 9 0.108s ─IntegrationTestTemporaryMiscCommon.do_s 0.0% 3.8% 1 0.316s ─ MapProjections.proj2 2.1% 2.1% 2 0.108s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 47.7% 1 4.012s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 47.1% 1 3.960s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.6% 26.4% 1 2.220s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.0% 21.3% 8 0.508s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 2.6% 2.6% 6 0.064s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.3% 1 0.360s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 20.7% 1 1.740s β”‚ β””Reify.Reify_rhs_gen --------------- 1.0% 20.0% 1 1.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.1% 9.3% 2 0.780s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 8.5% 8.6% 93 0.716s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.4% 1 0.200s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.2% 2.2% 1 0.188s β”‚ └─rewrite H ----------------------- 2.3% 2.3% 1 0.192s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.444s β””Glue.zrange_to_reflective_goal ------ 2.5% 4.0% 1 0.336s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.3% 21.3% 1 1.788s β”‚β””op_sig_side_conditions_t ------------ 0.0% 17.9% 1 1.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.1% 10.1% 4 0.220s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.4% 10.0% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 9.6% 20 0.048s β”‚ β”‚β””destruct H ------------------------ 9.6% 9.6% 20 0.048s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 7.5% 7.6% 4 0.308s └─IntegrationTestTemporaryMiscCommon.do 0.0% 21.0% 1 1.768s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.452s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.3% 17.3% 1 1.452s β”‚β””by_tac ---------------------------- 0.0% 17.0% 4 0.532s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.5% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.056s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.2% 8.3% 4 0.360s └─IntegrationTestTemporaryMiscCommon. 0.0% 3.8% 1 0.316s β”” MapProjections.proj2 2.1% 2.1% 2 0.108s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 56.0% 1 4.712s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 47.7% 1 4.012s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 47.1% 1 3.960s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.6% 26.4% 1 2.220s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.0% 21.3% 8 0.508s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 2.6% 2.6% 6 0.064s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.3% 1 0.360s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 20.7% 1 1.740s β”‚ β””Reify.Reify_rhs_gen --------------- 1.0% 20.0% 1 1.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.1% 9.3% 2 0.780s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 8.5% 8.6% 93 0.716s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.4% 1 0.200s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.2% 2.2% 1 0.188s β”‚ └─rewrite H ----------------------- 2.3% 2.3% 1 0.192s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.444s β””Glue.zrange_to_reflective_goal ------ 2.5% 4.0% 1 0.336s ─synthesize_montgomery ----------------- 0.0% 44.0% 1 3.696s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.3% 21.3% 1 1.788s β”‚β””op_sig_side_conditions_t ------------ 0.0% 17.9% 1 1.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.1% 10.1% 4 0.220s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.4% 10.0% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 9.6% 20 0.048s β”‚ β”‚β””destruct H ------------------------ 9.6% 9.6% 20 0.048s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 7.5% 7.6% 4 0.308s └─IntegrationTestTemporaryMiscCommon.do 0.0% 21.0% 1 1.768s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.452s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.3% 17.3% 1 1.452s β”‚β””by_tac ---------------------------- 0.0% 17.0% 4 0.532s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.5% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.056s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.2% 8.3% 4 0.360s └─IntegrationTestTemporaryMiscCommon. 0.0% 3.8% 1 0.316s β”” src/Specific/NISTP256/AMD64/feaddDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fenzDisplay > src/Specific/NISTP256/AMD64/fenzDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/feoppDisplay > src/Specific/NISTP256/AMD64/feoppDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fesubDisplay > src/Specific/NISTP256/AMD64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/fesquareDisplay > src/Specific/X25519/C64/fesquareDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_12limbs/femul.v Finished transaction in 60.265 secs (55.388u,0.103s) (successful) total time: 55.440s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 49.464s ─ReflectiveTactics.solve_side_conditions 0.0% 88.9% 1 49.288s ─ReflectiveTactics.do_reify ------------ -0.0% 49.9% 1 27.684s ─Reify.Reify_rhs_gen ------------------- 1.3% 49.3% 1 27.348s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.0% 1 21.604s ─Reify.do_reify_abs_goal --------------- 36.3% 36.6% 2 20.272s ─UnifyAbstractReflexivity.unify_transfor 30.8% 36.1% 8 8.636s ─Reify.do_reifyf_goal ------------------ 35.7% 35.9% 108 10.356s ─eexact -------------------------------- 11.5% 11.5% 110 0.128s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.7% 1 3.692s ─Glue.zrange_to_reflective ------------- 0.0% 6.2% 1 3.424s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.140s ─Glue.zrange_to_reflective_goal -------- 1.4% 4.7% 1 2.592s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s ─change G' ----------------------------- 3.9% 3.9% 1 2.148s ─pose proof (pf : Interpretation.Bo 3.1% 3.1% 1 1.736s ─rewrite H ----------------------------- 3.1% 3.1% 1 1.692s ─prove_interp_compile_correct ---------- 0.0% 3.0% 1 1.636s ─rewrite ?EtaInterp.InterpExprEta ------ 2.7% 2.7% 1 1.484s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 49.464s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.9% 1 49.288s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 49.9% 1 27.684s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 49.3% 1 27.348s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.3% 36.6% 2 20.272s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.7% 35.9% 108 10.356s β”‚ β”‚ β”‚β””eexact -------------------------- 11.1% 11.1% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.1% 3.1% 1 1.692s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.0% 1 1.636s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.7% 2.7% 1 1.484s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.0% 1 21.604s β”‚ β””UnifyAbstractReflexivity.unify_tran 30.8% 36.1% 8 8.636s β”‚ β””unify (constr) (constr) ----------- 4.4% 4.4% 6 1.140s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.7% 1 3.692s β””Glue.zrange_to_reflective ----------- 0.0% 6.2% 1 3.424s β””Glue.zrange_to_reflective_goal ------ 1.4% 4.7% 1 2.592s β””pose proof (pf : Interpretation. 3.1% 3.1% 1 1.736s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s β””change G' ----------------------------- 3.9% 3.9% 1 2.148s Finished transaction in 92.046 secs (84.315u,0.032s) (successful) Closed under the global context total time: 55.440s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s ─ReflectiveTactics.do_reflective_pipelin 0.0% 89.2% 1 49.464s ─ReflectiveTactics.solve_side_conditions 0.0% 88.9% 1 49.288s ─ReflectiveTactics.do_reify ------------ -0.0% 49.9% 1 27.684s ─Reify.Reify_rhs_gen ------------------- 1.3% 49.3% 1 27.348s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.0% 1 21.604s ─Reify.do_reify_abs_goal --------------- 36.3% 36.6% 2 20.272s ─UnifyAbstractReflexivity.unify_transfor 30.8% 36.1% 8 8.636s ─Reify.do_reifyf_goal ------------------ 35.7% 35.9% 108 10.356s ─eexact -------------------------------- 11.5% 11.5% 110 0.128s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.7% 1 3.692s ─Glue.zrange_to_reflective ------------- 0.0% 6.2% 1 3.424s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.140s ─Glue.zrange_to_reflective_goal -------- 1.4% 4.7% 1 2.592s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s ─change G' ----------------------------- 3.9% 3.9% 1 2.148s ─pose proof (pf : Interpretation.Bo 3.1% 3.1% 1 1.736s ─rewrite H ----------------------------- 3.1% 3.1% 1 1.692s ─prove_interp_compile_correct ---------- 0.0% 3.0% 1 1.636s ─rewrite ?EtaInterp.InterpExprEta ------ 2.7% 2.7% 1 1.484s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.9% 1 53.156s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 89.2% 1 49.464s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.9% 1 49.288s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 49.9% 1 27.684s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 49.3% 1 27.348s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.3% 36.6% 2 20.272s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.7% 35.9% 108 10.356s β”‚ β”‚ β”‚β””eexact -------------------------- 11.1% 11.1% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.1% 3.1% 1 1.692s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.0% 1 1.636s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.7% 2.7% 1 1.484s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.0% 1 21.604s β”‚ β””UnifyAbstractReflexivity.unify_tran 30.8% 36.1% 8 8.636s β”‚ β””unify (constr) (constr) ----------- 4.4% 4.4% 6 1.140s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.7% 1 3.692s β””Glue.zrange_to_reflective ----------- 0.0% 6.2% 1 3.424s β””Glue.zrange_to_reflective_goal ------ 1.4% 4.7% 1 2.592s β””pose proof (pf : Interpretation. 3.1% 3.1% 1 1.736s ─synthesize ---------------------------- 0.0% 4.1% 1 2.284s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.0% 1 2.220s β””change G' ----------------------------- 3.9% 3.9% 1 2.148s src/Specific/solinas32_2e255m765_12limbs/femul (real: 179.21, user: 164.11, sys: 0.42, mem: 1549104 ko) ROCQ compile src/Specific/X25519/C64/fesubDisplay > src/Specific/X25519/C64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/freezeDisplay > src/Specific/X25519/C64/freezeDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_13limbs/femul.v Finished transaction in 74.548 secs (68.928u,0.079s) (successful) total time: 68.948s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.7% 1 61.172s ─ReflectiveTactics.solve_side_conditions 0.0% 88.4% 1 60.944s ─ReflectiveTactics.do_reify ------------ 0.0% 48.5% 1 33.408s ─Reify.Reify_rhs_gen ------------------- 1.3% 47.9% 1 33.020s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.9% 1 27.536s ─UnifyAbstractReflexivity.unify_transfor 32.0% 37.2% 8 11.528s ─Reify.do_reify_abs_goal --------------- 36.0% 36.2% 2 24.960s ─Reify.do_reifyf_goal ------------------ 35.3% 35.5% 117 12.840s ─eexact -------------------------------- 11.4% 11.4% 119 0.160s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.9% 1 4.784s ─Glue.zrange_to_reflective ------------- 0.0% 6.5% 1 4.512s ─Glue.zrange_to_reflective_goal -------- 1.3% 4.9% 1 3.396s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.524s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s ─change G' ----------------------------- 4.1% 4.1% 1 2.840s ─pose proof (pf : Interpretation.Bo 3.5% 3.5% 1 2.420s ─rewrite H ----------------------------- 3.0% 3.0% 1 2.084s ─prove_interp_compile_correct ---------- 0.0% 2.7% 1 1.856s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 1.692s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 88.7% 1 61.172s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.4% 1 60.944s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 48.5% 1 33.408s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 47.9% 1 33.020s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.0% 36.2% 2 24.960s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.3% 35.5% 117 12.840s β”‚ β”‚ β”‚β””eexact -------------------------- 10.9% 10.9% 117 0.088s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 2.084s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 2.7% 1 1.856s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 1.692s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.9% 1 27.536s β”‚ β””UnifyAbstractReflexivity.unify_tran 32.0% 37.2% 8 11.528s β”‚ β””unify (constr) (constr) ----------- 4.3% 4.3% 6 1.524s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.9% 1 4.784s β””Glue.zrange_to_reflective ----------- 0.0% 6.5% 1 4.512s β””Glue.zrange_to_reflective_goal ------ 1.3% 4.9% 1 3.396s β””pose proof (pf : Interpretation. 3.5% 3.5% 1 2.420s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s β””change G' ----------------------------- 4.1% 4.1% 1 2.840s Finished transaction in 105.62 secs (97.6u,0.02s) (successful) Closed under the global context total time: 68.948s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.7% 1 61.172s ─ReflectiveTactics.solve_side_conditions 0.0% 88.4% 1 60.944s ─ReflectiveTactics.do_reify ------------ 0.0% 48.5% 1 33.408s ─Reify.Reify_rhs_gen ------------------- 1.3% 47.9% 1 33.020s ─ReflectiveTactics.solve_post_reified_si 0.1% 39.9% 1 27.536s ─UnifyAbstractReflexivity.unify_transfor 32.0% 37.2% 8 11.528s ─Reify.do_reify_abs_goal --------------- 36.0% 36.2% 2 24.960s ─Reify.do_reifyf_goal ------------------ 35.3% 35.5% 117 12.840s ─eexact -------------------------------- 11.4% 11.4% 119 0.160s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.9% 1 4.784s ─Glue.zrange_to_reflective ------------- 0.0% 6.5% 1 4.512s ─Glue.zrange_to_reflective_goal -------- 1.3% 4.9% 1 3.396s ─unify (constr) (constr) --------------- 4.9% 4.9% 7 1.524s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s ─change G' ----------------------------- 4.1% 4.1% 1 2.840s ─pose proof (pf : Interpretation.Bo 3.5% 3.5% 1 2.420s ─rewrite H ----------------------------- 3.0% 3.0% 1 2.084s ─prove_interp_compile_correct ---------- 0.0% 2.7% 1 1.856s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 1.692s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 65.956s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 88.7% 1 61.172s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 88.4% 1 60.944s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 48.5% 1 33.408s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 47.9% 1 33.020s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.0% 36.2% 2 24.960s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 35.3% 35.5% 117 12.840s β”‚ β”‚ β”‚β””eexact -------------------------- 10.9% 10.9% 117 0.088s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 2.084s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 2.7% 1 1.856s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 1.692s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 39.9% 1 27.536s β”‚ β””UnifyAbstractReflexivity.unify_tran 32.0% 37.2% 8 11.528s β”‚ β””unify (constr) (constr) ----------- 4.3% 4.3% 6 1.524s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.9% 1 4.784s β””Glue.zrange_to_reflective ----------- 0.0% 6.5% 1 4.512s β””Glue.zrange_to_reflective_goal ------ 1.3% 4.9% 1 3.396s β””pose proof (pf : Interpretation. 3.5% 3.5% 1 2.420s ─synthesize ---------------------------- 0.0% 4.3% 1 2.992s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 4.2% 1 2.912s β””change G' ----------------------------- 4.1% 4.1% 1 2.840s src/Specific/solinas32_2e255m765_13limbs/femul (real: 207.94, user: 192.95, sys: 0.48, mem: 1656912 ko) ROCQ compile src/Specific/NISTP256/AMD64/femul.v Finished transaction in 122.29 secs (111.972u,0.239s) (successful) total time: 112.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s ─ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s ─ReflectiveTactics.do_reify ------------ 0.0% 81.8% 1 91.740s ─Reify.Reify_rhs_gen ------------------- 0.7% 81.6% 1 91.504s ─Reify.do_reify_abs_goal --------------- 75.6% 75.7% 2 84.892s ─Reify.do_reifyf_goal ------------------ 75.2% 75.4% 901 84.532s ─eexact -------------------------------- 17.1% 17.1% 903 0.140s ─ReflectiveTactics.solve_post_reified_si 0.2% 14.5% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s β””ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s β”œβ”€ReflectiveTactics.do_reify ---------- 0.0% 81.8% 1 91.740s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 81.6% 1 91.504s β”‚β””Reify.do_reify_abs_goal ------------- 75.6% 75.7% 2 84.892s β”‚β””Reify.do_reifyf_goal ---------------- 75.2% 75.4% 901 84.532s β”‚β””eexact ------------------------------ 16.9% 16.9% 901 0.140s └─ReflectiveTactics.solve_post_reified_ 0.2% 14.5% 1 16.260s β””UnifyAbstractReflexivity.unify_transf 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s Finished transaction in 72.408 secs (68.432u,0.064s) (successful) Closed under the global context total time: 112.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s ─ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s ─ReflectiveTactics.do_reify ------------ 0.0% 81.8% 1 91.740s ─Reify.Reify_rhs_gen ------------------- 0.7% 81.6% 1 91.504s ─Reify.do_reify_abs_goal --------------- 75.6% 75.7% 2 84.892s ─Reify.do_reifyf_goal ------------------ 75.2% 75.4% 901 84.532s ─eexact -------------------------------- 17.1% 17.1% 903 0.140s ─ReflectiveTactics.solve_post_reified_si 0.2% 14.5% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 108.944s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.5% 1 108.236s β””ReflectiveTactics.solve_side_conditions 0.0% 96.3% 1 108.000s β”œβ”€ReflectiveTactics.do_reify ---------- 0.0% 81.8% 1 91.740s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 81.6% 1 91.504s β”‚β””Reify.do_reify_abs_goal ------------- 75.6% 75.7% 2 84.892s β”‚β””Reify.do_reifyf_goal ---------------- 75.2% 75.4% 901 84.532s β”‚β””eexact ------------------------------ 16.9% 16.9% 901 0.140s └─ReflectiveTactics.solve_post_reified_ 0.2% 14.5% 1 16.260s β””UnifyAbstractReflexivity.unify_transf 11.7% 13.3% 8 3.152s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.220s src/Specific/NISTP256/AMD64/femul (real: 217.80, user: 202.52, sys: 0.53, mem: 3307052 ko) ROCQ compile src/Specific/NISTP256/AMD64/femulDisplay > src/Specific/NISTP256/AMD64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/ladderstep.v total time: 82.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s ─ReflectiveTactics.do_reflective_pipelin 0.0% 96.1% 1 78.784s ─ReflectiveTactics.solve_side_conditions 0.0% 95.9% 1 78.684s ─ReflectiveTactics.solve_post_reified_si 0.1% 72.6% 1 59.540s ─UnifyAbstractReflexivity.unify_transfor 64.6% 68.0% 8 30.740s ─ReflectiveTactics.do_reify ------------ 0.0% 23.3% 1 19.144s ─Reify.Reify_rhs_gen ------------------- 1.2% 14.5% 1 11.860s ─Reify.do_reifyf_goal ------------------ 7.1% 7.2% 138 1.908s ─Compilers.Reify.reify_context_variables 0.0% 5.9% 1 4.828s ─rewrite H ----------------------------- 4.4% 4.4% 1 3.600s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.0% 1 3.288s ─Glue.refine_to_reflective_glue' ------- 0.0% 3.0% 1 2.444s ─Glue.zrange_to_reflective ------------- 0.0% 2.5% 1 2.060s ─reflexivity --------------------------- 2.3% 2.3% 11 0.816s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.968s ─Glue.zrange_to_reflective_goal -------- 1.4% 2.1% 1 1.720s ─clear (var_list) ---------------------- 2.0% 2.0% 159 0.584s ─eexact -------------------------------- 2.0% 2.0% 140 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 96.1% 1 78.784s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 95.9% 1 78.684s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.1% 72.6% 1 59.540s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 64.6% 68.0% 8 30.740s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.0% 1 3.288s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 23.3% 1 19.144s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 1.2% 14.5% 1 11.860s β”‚ β”‚ β”œβ”€rewrite H --------------------- 4.4% 4.4% 1 3.600s β”‚ β”‚ └─Reify.transitivity_tt --------- 0.0% 2.1% 2 0.968s β”‚ └─Compilers.Reify.reify_context_var 0.0% 5.9% 1 4.828s β”‚ β””Reify.do_reifyf_goal ------------ 5.7% 5.8% 113 1.908s └─Glue.refine_to_reflective_glue' ----- 0.0% 3.0% 1 2.444s β””Glue.zrange_to_reflective ----------- 0.0% 2.5% 1 2.060s β””Glue.zrange_to_reflective_goal ------ 1.4% 2.1% 1 1.720s Finished transaction in 194.903 secs (185.732u,0.043s) (successful) Closed under the global context total time: 82.012s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s ─ReflectiveTactics.do_reflective_pipelin 0.0% 96.1% 1 78.784s ─ReflectiveTactics.solve_side_conditions 0.0% 95.9% 1 78.684s ─ReflectiveTactics.solve_post_reified_si 0.1% 72.6% 1 59.540s ─UnifyAbstractReflexivity.unify_transfor 64.6% 68.0% 8 30.740s ─ReflectiveTactics.do_reify ------------ 0.0% 23.3% 1 19.144s ─Reify.Reify_rhs_gen ------------------- 1.2% 14.5% 1 11.860s ─Reify.do_reifyf_goal ------------------ 7.1% 7.2% 138 1.908s ─Compilers.Reify.reify_context_variables 0.0% 5.9% 1 4.828s ─rewrite H ----------------------------- 4.4% 4.4% 1 3.600s ─ReflectiveTactics.unify_abstract_cbv_in 2.9% 4.0% 1 3.288s ─Glue.refine_to_reflective_glue' ------- 0.0% 3.0% 1 2.444s ─Glue.zrange_to_reflective ------------- 0.0% 2.5% 1 2.060s ─reflexivity --------------------------- 2.3% 2.3% 11 0.816s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.968s ─Glue.zrange_to_reflective_goal -------- 1.4% 2.1% 1 1.720s ─clear (var_list) ---------------------- 2.0% 2.0% 159 0.584s ─eexact -------------------------------- 2.0% 2.0% 140 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 82.012s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 81.228s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 96.1% 1 78.784s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 95.9% 1 78.684s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.1% 72.6% 1 59.540s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 64.6% 68.0% 8 30.740s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 2.9% 4.0% 1 3.288s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 23.3% 1 19.144s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 1.2% 14.5% 1 11.860s β”‚ β”‚ β”œβ”€rewrite H --------------------- 4.4% 4.4% 1 3.600s β”‚ β”‚ └─Reify.transitivity_tt --------- 0.0% 2.1% 2 0.968s β”‚ └─Compilers.Reify.reify_context_var 0.0% 5.9% 1 4.828s β”‚ β””Reify.do_reifyf_goal ------------ 5.7% 5.8% 113 1.908s └─Glue.refine_to_reflective_glue' ----- 0.0% 3.0% 1 2.444s β””Glue.zrange_to_reflective ----------- 0.0% 2.5% 1 2.060s β””Glue.zrange_to_reflective_goal ------ 1.4% 2.1% 1 1.720s src/Specific/X25519/C64/ladderstep (real: 316.83, user: 299.49, sys: 0.52, mem: 1621500 ko) ROCQ compile src/Specific/X25519/C64/ladderstepDisplay > src/Specific/X25519/C64/ladderstepDisplay.log time-of-build-both-real-absolute.log.expected000066400000000000000000000076441516144147600367560ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-real-auto.log.expected000066400000000000000000000076441516144147600361100ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-real-diff.log.expected000066400000000000000000000076441516144147600360500ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep time-of-build-both-real.log.expected000066400000000000000000000076441516144147600351420ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 20m46.07s | 3302508 ko | 23m06.31s | 3307052 ko || -2m20.24s || -4544 ko | -10.11% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m16.77s | 1617000 ko | 5m16.83s | 1621500 ko || -1m00.06s || -4500 ko | -18.95% | -0.27% | Specific/X25519/C64/ladderstep 3m01.77s | 1589516 ko | 3m27.94s | 1656912 ko || -0m26.17s || -67396 ko | -12.58% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m35.79s | 1454696 ko | 2m59.21s | 1549104 ko || -0m23.42s || -94408 ko | -13.06% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m22.96s | 3302508 ko | 3m37.80s | 3307052 ko || -0m14.84s || -4544 ko | -6.81% | -0.13% | Specific/NISTP256/AMD64/femul 0m39.72s | 825448 ko | 0m42.98s | 839624 ko || -0m03.26s || -14176 ko | -7.58% | -1.68% | Specific/X25519/C64/femul 0m38.19s | 799216 ko | 0m40.48s | 797944 ko || -0m02.29s || 1272 ko | -5.65% | +0.15% | Specific/NISTP256/AMD64/feadd 0m34.35s | 828104 ko | 0m36.42s | 826476 ko || -0m02.07s || 1628 ko | -5.68% | +0.19% | Specific/X25519/C64/freeze 0m33.08s | 799620 ko | 0m35.23s | 802776 ko || -0m02.15s || -3156 ko | -6.10% | -0.39% | Specific/X25519/C64/fesquare 0m31.00s | 765208 ko | 0m32.08s | 765212 ko || -0m01.08s || -4 ko | -3.36% | -0.00% | Specific/NISTP256/AMD64/feopp 0m27.81s | 756080 ko | 0m28.91s | 756216 ko || -0m01.10s || -136 ko | -3.80% | -0.01% | Specific/NISTP256/AMD64/fenz 0m27.11s | 786052 ko | 0m28.85s | 787148 ko || -0m01.74s || -1096 ko | -6.03% | -0.13% | Specific/X25519/C64/fecarry 0m24.71s | 778792 ko | 0m26.11s | 781808 ko || -0m01.40s || -3016 ko | -5.36% | -0.38% | Specific/X25519/C64/fesub 0m49.44s | 744240 ko | 0m49.50s | 744472 ko || -0m00.06s || -232 ko | -0.12% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m43.34s | 793376 ko | 0m43.78s | 799668 ko || -0m00.44s || -6292 ko | -1.00% | -0.78% | Specific/NISTP256/AMD64/fesub 0m40.13s | 728464 ko | 0m39.53s | 729464 ko || +0m00.60s || -1000 ko | +1.51% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m22.81s | 766300 ko | 0m23.43s | 766168 ko || -0m00.62s || 132 ko | -2.64% | +0.01% | Specific/X25519/C64/feadd 0m13.45s | 668216 ko | 0m13.74s | 667664 ko || -0m00.29s || 552 ko | -2.11% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m11.15s | 687760 ko | 0m11.23s | 687812 ko || -0m00.08s || -52 ko | -0.71% | -0.00% | Specific/X25519/C64/Synthesis 0m07.33s | 574388 ko | 0m07.40s | 578344 ko || -0m00.07s || -3956 ko | -0.94% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.93s | 544172 ko | 0m01.73s | 546112 ko || +0m00.20s || -1940 ko | +11.56% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.85s | 646300 ko | 0m01.95s | 648632 ko || -0m00.10s || -2332 ko | -5.12% | -0.35% | Specific/Framework/SynthesisFramework 0m01.38s | 539808 ko | 0m01.18s | 539160 ko || +0m00.20s || 648 ko | +16.94% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-user-absolute.log.expected000066400000000000000000000076441516144147600370110ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-user-auto.log.expected000066400000000000000000000076441516144147600361430ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline time-of-build-both-user-diff.log.expected000066400000000000000000000076441516144147600361030ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep time-of-build-both-user.log.expected000066400000000000000000000076441516144147600351750ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/correct-diff-sorting-order After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name --------------------------------------------------------------------------------------------------------------------------------------------------------- 19m16.05s | 3302508 ko | 21m25.28s | 3307052 ko || -2m09.23s || -4544 ko | -10.05% | -0.13% | Total Time / Peak Mem --------------------------------------------------------------------------------------------------------------------------------------------------------- 4m01.34s | 1617000 ko | 4m59.49s | 1621500 ko || -0m58.15s || -4500 ko | -19.41% | -0.27% | Specific/X25519/C64/ladderstep 2m48.52s | 1589516 ko | 3m12.95s | 1656912 ko || -0m24.43s || -67396 ko | -12.66% | -4.06% | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | 2m44.11s | 1549104 ko || -0m20.41s || -94408 ko | -12.43% | -6.09% | Specific/solinas32_2e255m765_12limbs/femul 3m09.62s | 3302508 ko | 3m22.52s | 3307052 ko || -0m12.90s || -4544 ko | -6.36% | -0.13% | Specific/NISTP256/AMD64/femul 0m36.32s | 825448 ko | 0m39.50s | 839624 ko || -0m03.18s || -14176 ko | -8.05% | -1.68% | Specific/X25519/C64/femul 0m30.13s | 799620 ko | 0m32.24s | 802776 ko || -0m02.11s || -3156 ko | -6.54% | -0.39% | Specific/X25519/C64/fesquare 0m35.40s | 799216 ko | 0m37.21s | 797944 ko || -0m01.81s || 1272 ko | -4.86% | +0.15% | Specific/NISTP256/AMD64/feadd 0m31.50s | 828104 ko | 0m33.24s | 826476 ko || -0m01.74s || 1628 ko | -5.23% | +0.19% | Specific/X25519/C64/freeze 0m24.99s | 786052 ko | 0m26.31s | 787148 ko || -0m01.32s || -1096 ko | -5.01% | -0.13% | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | 0m23.72s | 781808 ko || -0m01.07s || -3016 ko | -4.51% | -0.38% | Specific/X25519/C64/fesub 0m45.75s | 744240 ko | 0m45.58s | 744472 ko || +0m00.17s || -232 ko | +0.37% | -0.03% | Specific/solinas32_2e255m765_13limbs/Synthesis 0m39.59s | 793376 ko | 0m40.09s | 799668 ko || -0m00.50s || -6292 ko | -1.24% | -0.78% | Specific/NISTP256/AMD64/fesub 0m36.92s | 728464 ko | 0m36.64s | 729464 ko || +0m00.28s || -1000 ko | +0.76% | -0.13% | Specific/solinas32_2e255m765_12limbs/Synthesis 0m28.51s | 765208 ko | 0m29.46s | 765212 ko || -0m00.95s || -4 ko | -3.22% | -0.00% | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | 0m26.41s | 756216 ko || -0m00.91s || -136 ko | -3.44% | -0.01% | Specific/NISTP256/AMD64/fenz 0m20.93s | 766300 ko | 0m21.41s | 766168 ko || -0m00.48s || 132 ko | -2.24% | +0.01% | Specific/X25519/C64/feadd 0m12.55s | 668216 ko | 0m12.54s | 667664 ko || +0m00.01s || 552 ko | +0.07% | +0.08% | Specific/NISTP256/AMD64/Synthesis 0m10.37s | 687760 ko | 0m10.30s | 687812 ko || +0m00.07s || -52 ko | +0.67% | -0.00% | Specific/X25519/C64/Synthesis 0m07.18s | 574388 ko | 0m07.22s | 578344 ko || -0m00.04s || -3956 ko | -0.55% | -0.68% | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | 0m01.58s | 546112 ko || +0m00.14s || -1940 ko | +8.86% | -0.35% | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | 0m01.72s | 648632 ko || -0m00.05s || -2332 ko | -2.90% | -0.35% | Specific/Framework/SynthesisFramework 0m01.19s | 539808 ko | 0m01.04s | 539160 ko || +0m00.15s || 648 ko | +14.42% | +0.12% | Compilers/Z/Bounds/Pipeline rocq-9.2.0/test-suite/precomputed-time-tests/no-output-sync/000077500000000000000000000000001516144147600241545ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/no-output-sync/run.sh000077500000000000000000000004701516144147600253200ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_one_time_file time-of-build.log.in time-of-build.log 2>time-of-build.err.log || exit $? diff -u time-of-build.log.expected time-of-build.log || exit $? diff -u time-of-build.err.log.expected time-of-build.err.log || exit $? rocq-9.2.0/test-suite/precomputed-time-tests/no-output-sync/time-of-build.err.log.expected000066400000000000000000000001311516144147600316760ustar00rootroot00000000000000WARNING: Invalid time string: not the right number of dots (.); expected one: '0.240.05' rocq-9.2.0/test-suite/precomputed-time-tests/no-output-sync/time-of-build.log.expected000066400000000000000000000601441516144147600311210ustar00rootroot00000000000000 Time | Peak Mem | File Name ------------------------------------------------------------- 29m02.88s | 1136588 ko | Total Time / Peak Mem ------------------------------------------------------------- 2m19.40s | 1007764 ko | PCUICSafeConversion.vo 1m59.92s | 1136588 ko | PCUICSafeReduce.vo 1m34.58s | 849824 ko | PCUICParallelReductionConfluence.vo 1m26.21s | 1038900 ko | erasure_live_test.vo 1m20.36s | 975764 ko | PCUICSR.vo 0m56.51s | 896928 ko | bugkncst.vo 0m56.17s | 1113548 ko | ErasureCorrectness.vo 0m56.09s | 958816 ko | PCUICSafeChecker.vo 0m51.78s | 809012 ko | Typing.vo 0m42.82s | 727688 ko | PCUICTyping.vo 0m39.21s | 1012876 ko | ErasureFunction.vo 0m39.04s | 790088 ko | PCUICEquality.vo 0m38.12s | 657100 ko | PCUICSigmaCalculus.vo 0m34.44s | 742788 ko | PCUICConfluence.vo 0m29.65s | 750296 ko | PCUICConversion.vo 0m28.26s | 779308 ko | PCUICParallelReduction.vo 0m28.24s | 723216 ko | PCUICPosition.vo 0m27.93s | 621392 ko | Substitution.vo 0m26.28s | 597996 ko | PCUICLiftSubst.vo 0m26.11s | 959132 ko | PCUICPrincipality.vo 0m25.86s | 857128 ko | times_bool_fun.vo 0m25.65s | 673140 ko | PCUICSubstitution.vo 0m23.99s | 654592 ko | PCUICClosed.vo 0m23.42s | 685852 ko | PCUICWeakening.vo 0m23.34s | 854428 ko | SafeErasureFunction.vo 0m22.85s | 706592 ko | PCUICSpine.vo 0m21.55s | 603616 ko | Closed.vo 0m19.93s | 581920 ko | tauto.vo 0m19.08s | 683776 ko | PCUICInductives.vo 0m17.91s | 741808 ko | param_original.vo 0m15.64s | 579100 ko | Weakening.vo 0m14.98s | 623196 ko | PCUICNameless.vo 0m13.39s | 794032 ko | ESubstitution.vo 0m13.16s | 641024 ko | TemplateToPCUICCorrectness.vo 0m11.81s | 532016 ko | LiftSubst.vo 0m11.54s | 589944 ko | PCUICWcbvEval.vo 0m10.41s | 621644 ko | PCUICUnivSubstitution.vo 0m10.39s | 661964 ko | PCUICInductiveInversion.vo 0m10.08s | 521520 ko | ELiftSubst.vo 0m09.58s | 684644 ko | PCUICAlpha.vo 0m09.35s | 622488 ko | PCUICInversion.vo 0m08.74s | 629108 ko | PCUICContextConversion.vo 0m08.61s | 892080 ko | param_generous_packed.vo 0m08.05s | 556676 ko | TypingWf.vo 0m07.84s | 608576 ko | PCUICToTemplateCorrectness.vo 0m07.75s | 625664 ko | PCUICArities.vo 0m07.64s | 646256 ko | PCUICElimination.vo 0m07.23s | 614752 ko | times_bool_fun2.vo 0m06.54s | 667924 ko | PCUICSafeLemmata.vo 0m06.33s | 615568 ko | PCUICContexts.vo 0m06.30s | 733700 ko | PCUICSafeRetyping.vo 0m06.16s | 583116 ko | PCUICReduction.vo 0m06.04s | 529900 ko | utils/MCCompare.vo 0m05.85s | 551516 ko | common/uGraph.vo 0m05.66s | 643396 ko | EArities.vo 0m04.94s | 533768 ko | WcbvEval.vo 0m04.90s | 501352 ko | vs.vo 0m04.72s | 498552 ko | utils/wGraph.vo 0m04.53s | 552364 ko | Reflect.vo 0m04.41s | 348856 ko | MiniHoTT.vo 0m04.38s | 571076 ko | PCUICWeakeningEnv.vo 0m04.23s | 531272 ko | Universes.vo 0m04.11s | 543956 ko | PCUICReflect.vo 0m04.00s | 555748 ko | Checker.vo 0m03.99s | 624912 ko | PCUICValidity.vo 0m03.99s | 806128 ko | SafeTemplateErasure.vo 0m03.85s | 520080 ko | EWcbvEval.vo 0m03.42s | 350716 ko | MiniHoTT_paths.vo 0m03.39s | 741428 ko | Prelim.vo 0m03.34s | 586388 ko | PCUICGeneration.vo 0m03.33s | 533884 ko | PCUICUnivSubst.vo 0m03.11s | 561316 ko | Extraction.vo 0m03.11s | 490756 ko | UnivSubst.vo 0m02.89s | 726228 ko | safechecker_test.vo 0m02.80s | 512292 ko | WeakeningEnv.vo 0m02.78s | 543424 ko | PCUICAstUtils.vo 0m02.78s | 465984 ko | utils/All_Forall.vo 0m02.67s | 729072 ko | EInversion.vo 0m02.42s | 703592 ko | SafeTemplateChecker.vo 0m02.27s | 558304 ko | TypingTests.vo 0m02.12s | 630488 ko | PCUICSN.vo 0m01.93s | 556444 ko | param_binary.vo 0m01.85s | 561876 ko | PCUICCumulativity.vo 0m01.82s | 554420 ko | translation_utils.vo 0m01.77s | 491968 ko | EnvironmentTyping.vo 0m01.75s | 598288 ko | PCUICCtxShape.vo 0m01.69s | 514692 ko | Generation.vo 0m01.62s | 512080 ko | bug5.vo 0m01.58s | 589768 ko | PCUICRetyping.vo 0m01.57s | 617808 ko | Extract.vo 0m01.56s | 527740 ko | demo.vo 0m01.55s | 562424 ko | PCUICCSubst.vo 0m01.49s | 553352 ko | param_cheap_packed.vo 0m01.47s | 527440 ko | PCUICUtils.vo 0m01.47s | 452340 ko | utils/MCList.vo 0m01.44s | 503484 ko | PCUICSize.vo 0m01.42s | 619396 ko | EAll.vo 0m01.37s | 551200 ko | PCUICNormal.vo 0m01.35s | 526276 ko | modules_sections.vo 0m01.34s | 549492 ko | standard_model.vo 0m01.30s | 551364 ko | PCUICPretty.vo 0m01.29s | 545736 ko | All.vo 0m01.21s | 524028 ko | proj.vo 0m01.21s | 513888 ko | test/test.vo 0m01.18s | 486324 ko | Induction.vo 0m01.13s | 524144 ko | add_constructor.vo 0m01.11s | 549776 ko | PCUICChecker.vo 0m01.10s | 487520 ko | EAstUtils.vo 0m01.10s | 484172 ko | Environment.vo 0m01.10s | 543584 ko | erasure_test.vo 0m01.09s | 525128 ko | order_rec.vo 0m01.05s | 512080 ko | ECSubst.vo 0m01.05s | 489932 ko | WfInv.vo 0m01.05s | 522968 ko | issue28.vo 0m01.04s | 527408 ko | PCUICToTemplate.vo 0m01.03s | 510284 ko | bug1.vo 0m01.03s | 522996 ko | run_in_tactic.vo 0m01.03s | 522248 ko | unfold.vo 0m01.02s | 522688 ko | issue27.vo 0m01.01s | 524932 ko | tmVariable.vo 0m01.00s | 485664 ko | AstUtils.vo 0m00.99s | 522992 ko | univ.vo 0m00.98s | 522552 ko | tmInferInstance.vo 0m00.96s | 546928 ko | PCUICMetaTheory.vo 0m00.94s | 510368 ko | castprop.vo 0m00.94s | 500016 ko | opaque.vo 0m00.92s | 522724 ko | tmExistingInstance.vo 0m00.91s | 513348 ko | MyPlugin.vo 0m00.90s | 524140 ko | Retyping.vo 0m00.90s | 500080 ko | letin.vo 0m00.89s | 481312 ko | PCUICInduction.vo 0m00.89s | 500252 ko | bug7.vo 0m00.89s | 500068 ko | mutind.vo 0m00.88s | 500120 ko | case.vo 0m00.88s | 501748 ko | extractable.vo 0m00.87s | 486460 ko | Pretty.vo 0m00.86s | 500064 ko | sigma.vo 0m00.85s | 500408 ko | bug6.vo 0m00.84s | 497360 ko | Normal.vo 0m00.84s | 500436 ko | bug8.vo 0m00.82s | 498504 ko | Constants.vo 0m00.81s | 500380 ko | bug2.vo 0m00.81s | 500192 ko | cofix.vo 0m00.80s | 502088 ko | hnf_ctor.vo 0m00.79s | 479940 ko | Ast.vo 0m00.79s | 500100 ko | evars.vo 0m00.77s | 488076 ko | EPretty.vo 0m00.75s | 450728 ko | BasicAst.vo 0m00.75s | 477372 ko | PCUICAst.vo 0m00.73s | 487644 ko | ETyping.vo 0m00.73s | 481988 ko | TemplateMonad/Core.vo 0m00.72s | 477800 ko | EAst.vo 0m00.71s | 479012 ko | EInduction.vo 0m00.70s | 485084 ko | EWndEval.vo 0m00.70s | 481156 ko | TemplateMonad/Extractable.vo 0m00.69s | 482472 ko | TemplateToPCUIC.vo 0m00.60s | 433064 ko | PCUICCheckerCompleteness.vo 0m00.60s | 437492 ko | TemplateMonad/Common.vo 0m00.56s | 440168 ko | utils/MCOption.vo 0m00.54s | 420452 ko | TemplateMonad.vo 0m00.52s | 385340 ko | utils.vo 0m00.48s | 404556 ko | utils/MCArith.vo 0m00.42s | 339136 ko | utils/LibHypsNaming.vo 0m00.41s | 39160 ko | gen-src/universes0.cmx 0m00.33s | 45284 ko | pCUICSafeChecker.cmx 0m00.30s | 270156 ko | utils/MCString.vo 0m00.29s | 238116 ko | Loader.vo 0m00.27s | 43056 ko | pCUICSafeConversion.cmx 0m00.240s | N/A | denoter.cmx 0m00.19s | 34468 ko | gen-src/quoter.cmx 0m00.17s | 33044 ko | constr_quoter.cmx 0m00.15s | 25208 ko | gen-src/binPos.cmx 0m00.15s | 38520 ko | run_template_monad.cmx 0m00.14s | 31740 ko | constr_denoter.cmx 0m00.14s | 25372 ko | gen-src/all_Forall.cmx 0m00.14s | 149456 ko | monad_utils.vo 0m00.14s | 31636 ko | wGraph.cmx 0m00.13s | 23892 ko | gen-src/binPosDef.cmx 0m00.13s | 20232 ko | metacoq_erasure_plugin.cmxs 0m00.12s | 22784 ko | gen-src/binInt.cmx 0m00.11s | 31208 ko | erasureFunction.cmx 0m00.11s | 31632 ko | gen-src/metacoq_template_plugin.cmx 0m00.11s | 20224 ko | metacoq_safechecker_plugin.cmxs 0m00.11s | 30984 ko | uGraph0.cmx 0m00.10s | 28644 ko | eAst.cmx 0m00.10s | 33140 ko | g_template_coq.cmx 0m00.10s | 27364 ko | gen-src/ast_quoter.cmx 0m00.10s | 20796 ko | gen-src/binNat.cmx 0m00.10s | 18416 ko | gen-src/metacoq_template_plugin.cmxs 0m00.10s | 27228 ko | gen-src/myPlugin.cmx 0m00.10s | 26404 ko | gen-src/quoter.cmo 0m00.09s | 26992 ko | ePretty.cmx 0m00.09s | 35368 ko | g_metacoq_safechecker.cmx 0m00.09s | 24572 ko | gen-src/ast0.cmx 0m00.09s | 20020 ko | gen-src/hexadecimal.cmx 0m00.09s | 30504 ko | gen-src/run_extractable.cmx 0m00.09s | 29148 ko | pCUICPretty.cmx 0m00.09s | 29852 ko | safeErasureFunction.cmx 0m00.09s | 88348 ko | utils/MCProd.vo 0m00.08s | 27288 ko | gen-src/ast_denoter.cmx 0m00.08s | 24324 ko | gen-src/denoter.cmx 0m00.08s | 21352 ko | gen-src/mSetList.cmx 0m00.08s | 22020 ko | gen-src/pretty.cmx 0m00.08s | 32668 ko | metacoq_erasure_plugin.cmx 0m00.08s | 26392 ko | pCUICAstUtils.cmx 0m00.08s | 27752 ko | pCUICTyping.cmx 0m00.07s | 19912 ko | gen-src/peanoNat.cmx 0m00.07s | 27504 ko | gen-src/plugin_core.cmx 0m00.07s | 27792 ko | pCUICSafeReduce.cmx 0m00.07s | 30244 ko | safeTemplateErasure.cmx 0m00.06s | 24684 ko | eTyping.cmx 0m00.06s | 22652 ko | erasureFunction.cmi 0m00.06s | 27844 ko | g_demo_plugin.cmx 0m00.06s | 30052 ko | g_metacoq_erasure.cmx 0m00.06s | 25216 ko | mSetWeakList.cmx 0m00.06s | 30436 ko | metacoq_safechecker_plugin.cmx 0m00.06s | 26256 ko | pCUICEquality.cmx 0m00.06s | 26244 ko | pCUICLiftSubst.cmx 0m00.06s | 26048 ko | pCUICPosition.cmx 0m00.06s | 23232 ko | pCUICSafeConversion.cmi 0m00.06s | 27380 ko | pCUICSafeRetyping.cmx 0m00.06s | 25408 ko | safeTemplateChecker.cmx 0m00.06s | 26384 ko | templateToPCUIC.cmx 0m00.06s | 24780 ko | uGraph0.cmi 0m00.05s | 64048 ko | Lens.vo 0m00.05s | 24800 ko | eAstUtils.cmx 0m00.05s | 25192 ko | eLiftSubst.cmx 0m00.05s | 22440 ko | gen-src/ast_quoter.cmo 0m00.05s | 20324 ko | gen-src/mSetInterface.cmx 0m00.05s | 26032 ko | pCUICAst.cmx 0m00.05s | 25140 ko | pCUICChecker.cmx 0m00.05s | 24336 ko | pCUICReflect.cmx 0m00.05s | 24300 ko | pCUICSafeChecker.cmi 0m00.05s | 21556 ko | pCUICSafeReduce.cmi 0m00.05s | 25180 ko | pCUICUnivSubst.cmx 0m00.05s | 21660 ko | safeErasureFunction.cmi 0m00.05s | 23148 ko | safeTemplateErasure.cmi 0m00.05s | 21328 ko | templateToPCUIC.cmi 0m00.05s | 16040 ko | template_coq.cmxs 0m00.05s | 24076 ko | typing0.cmx 0m00.05s | 63096 ko | utils/MCPrelude.vo 0m00.05s | 68156 ko | utils/MCRelations.vo 0m00.05s | 22824 ko | wGraph.cmi 0m00.04s | 62716 ko | ExtractableLoader.vo 0m00.04s | 61716 ko | config.vo 0m00.04s | 22020 ko | constr_reification.cmx 0m00.04s | 21964 ko | demo_plugin.cmx 0m00.04s | 20540 ko | ePretty.cmi 0m00.04s | 23032 ko | extract.cmx 0m00.04s | 19608 ko | gen-src/astUtils.cmx 0m00.04s | 18780 ko | gen-src/extractable.cmx 0m00.04s | 22124 ko | gen-src/lens.cmx 0m00.04s | 19008 ko | gen-src/liftSubst.cmx 0m00.04s | 19600 ko | gen-src/mSetProperties.cmx 0m00.04s | 20208 ko | gen-src/myPlugin.cmi 0m00.04s | 18464 ko | gen-src/nat0.cmx 0m00.04s | 22136 ko | gen-src/tm_util.cmx 0m00.04s | 18504 ko | gen-src/universes0.cmi 0m00.04s | 20108 ko | mSetWeakList.cmi 0m00.04s | 22452 ko | monad_utils.cmx 0m00.04s | 21244 ko | pCUICAst.cmi 0m00.04s | 20412 ko | pCUICAstUtils.cmi 0m00.04s | 21236 ko | pCUICChecker.cmi 0m00.04s | 20560 ko | pCUICPretty.cmi 0m00.04s | 21400 ko | pCUICTyping.cmi 0m00.04s | 20348 ko | safeTemplateChecker.cmi 0m00.04s | 19228 ko | utils.cmi 0m00.04s | 22212 ko | utils.cmx 0m00.04s | 62924 ko | utils/MCEquality.vo 0m00.04s | 61384 ko | utils/MCSquash.vo 0m00.03s | 19340 ko | classes0.cmi 0m00.03s | 20908 ko | eAst.cmi 0m00.03s | 19496 ko | eAstUtils.cmi 0m00.03s | 20252 ko | eTyping.cmi 0m00.03s | 19268 ko | eqDecInstances.cmi 0m00.03s | 22196 ko | eqDecInstances.cmx 0m00.03s | 19396 ko | eqdepFacts.cmi 0m00.03s | 22072 ko | eqdepFacts.cmx 0m00.03s | 21060 ko | extract.cmi 0m00.03s | 18744 ko | gen-src/basicAst.cmx 0m00.03s | 17936 ko | gen-src/decimal.cmx 0m00.03s | 19716 ko | gen-src/environment.cmx 0m00.03s | 19172 ko | gen-src/lens.cmi 0m00.03s | 17796 ko | gen-src/list0.cmx 0m00.03s | 18548 ko | gen-src/univSubst0.cmx 0m00.03s | 19324 ko | init.cmi 0m00.03s | 22188 ko | init.cmx 0m00.03s | 19272 ko | monad_utils.cmi 0m00.03s | 20372 ko | pCUICEquality.cmi 0m00.03s | 20444 ko | pCUICLiftSubst.cmi 0m00.03s | 22044 ko | pCUICNormal.cmx 0m00.03s | 20488 ko | pCUICPosition.cmi 0m00.03s | 20240 ko | pCUICReflect.cmi 0m00.03s | 19348 ko | pCUICSafeLemmata.cmi 0m00.03s | 21604 ko | pCUICSafeRetyping.cmi 0m00.03s | 20308 ko | pCUICUnivSubst.cmi 0m00.03s | 21812 ko | tm_util.cmx 0m00.03s | 20300 ko | typing0.cmi 0m00.02s | 21960 ko | classes0.cmx 0m00.02s | 19300 ko | eLiftSubst.cmi 0m00.02s | 16900 ko | gen-src/ascii.cmx 0m00.02s | 16836 ko | gen-src/cRelationClasses.cmx 0m00.02s | 16420 ko | gen-src/common0.cmx 0m00.02s | 16472 ko | gen-src/mCString.cmx 0m00.02s | 15244 ko | gen-src/mSetInterface.cmi 0m00.02s | 15212 ko | gen-src/mSetProperties.cmi 0m00.02s | 17196 ko | gen-src/plugin_core.cmi 0m00.02s | 16332 ko | gen-src/specif.cmx 0m00.02s | 16504 ko | gen-src/string0.cmx 0m00.02s | 18448 ko | gen-src/tm_util.cmo 0m00.02s | 19224 ko | pCUICCumulativity.cmi 0m00.02s | 21940 ko | pCUICCumulativity.cmx 0m00.02s | 19304 ko | pCUICNormal.cmi 0m00.02s | 22084 ko | pCUICSafeLemmata.cmx 0m00.02s | 19220 ko | ssrbool.cmi 0m00.02s | 21912 ko | ssrbool.cmx 0m00.02s | 19956 ko | template_coq.cmx 0m00.01s | 14256 ko | demo_plugin.cmxs 0m00.01s | 14992 ko | gen-src/all_Forall.cmi 0m00.01s | 15204 ko | gen-src/ast0.cmi 0m00.01s | 14404 ko | gen-src/basicAst.cmi 0m00.01s | 13564 ko | gen-src/binInt.cmi 0m00.01s | 14264 ko | gen-src/binPos.cmi 0m00.01s | 15772 ko | gen-src/bool.cmx 0m00.01s | 13388 ko | gen-src/cRelationClasses.cmi 0m00.01s | 15536 ko | gen-src/compare_dec.cmx 0m00.01s | 16200 ko | gen-src/datatypes.cmx 0m00.01s | 14988 ko | gen-src/environment.cmi 0m00.01s | 15840 ko | gen-src/equalities.cmx 0m00.01s | 13404 ko | gen-src/list0.cmi 0m00.01s | 15672 ko | gen-src/mCCompare.cmx 0m00.01s | 16712 ko | gen-src/mCList.cmx 0m00.01s | 15708 ko | gen-src/mCProd.cmx 0m00.01s | 13748 ko | gen-src/mSetFacts.cmi 0m00.01s | 17012 ko | gen-src/mSetFacts.cmx 0m00.01s | 15760 ko | gen-src/mSetList.cmi 0m00.01s | 14056 ko | gen-src/metacoq_template_plugin.cmxa 0m00.01s | 15860 ko | gen-src/orderedType0.cmx 0m00.01s | 13748 ko | gen-src/orders.cmi 0m00.01s | 16768 ko | gen-src/orders.cmx 0m00.01s | 16032 ko | gen-src/ordersFacts.cmx 0m00.01s | 15844 ko | gen-src/ordersTac.cmx 0m00.01s | 11760 ko | gen-src/reification.cmo 0m00.01s | 14740 ko | gen-src/reification.cmx 0m00.01s | 13824 ko | gen-src/run_extractable.cmi 0m00.01s | 13460 ko | i 0m00.01s | 17068 ko | plugin_core.cmi 0m00.01s | 14796 ko | reification.cmx 0m00.00s | 13200 ko | demo_plugin.cmxa 0m00.00s | 12228 ko | gen-src/ascii.cmi 0m00.00s | 14040 ko | gen-src/astUtils.cmi 0m00.00s | 11244 ko | gen-src/basics.cmi 0m00.00s | 13444 ko | gen-src/binNat.cmi 0m00.00s | 11340 ko | gen-src/binNums.cmi 0m00.00s | 13536 ko | gen-src/binPosDef.cmi 0m00.00s | 11744 ko | gen-src/bool.cmi 0m00.00s | 13492 ko | gen-src/common0.cmi 0m00.00s | 11720 ko | gen-src/compare_dec.cmi 0m00.00s | 11112 ko | gen-src/config0.cmi 0m00.00s | 14648 ko | gen-src/config0.cmx 0m00.00s | 12948 ko | gen-src/datatypes.cmi 0m00.00s | 12404 ko | gen-src/decimal.cmi 0m00.00s | 13240 ko | gen-src/equalities.cmi 0m00.00s | 13580 ko | gen-src/extractable.cmi 0m00.00s | 13064 ko | gen-src/hexadecimal.cmi 0m00.00s | 13680 ko | gen-src/liftSubst.cmi 0m00.00s | 11524 ko | gen-src/logic0.cmi 0m00.00s | 15516 ko | gen-src/logic0.cmx 0m00.00s | 11644 ko | gen-src/mCCompare.cmi 0m00.00s | 13612 ko | gen-src/mCList.cmi 0m00.00s | 12200 ko | gen-src/mCOption.cmi 0m00.00s | 11228 ko | gen-src/mCPrelude.cmi 0m00.00s | 14368 ko | gen-src/mCPrelude.cmx 0m00.00s | 11620 ko | gen-src/mCProd.cmi 0m00.00s | 11080 ko | gen-src/mCRelations.cmi 0m00.00s | 14184 ko | gen-src/mCRelations.cmx 0m00.00s | 11712 ko | gen-src/mCString.cmi 0m00.00s | 13776 ko | gen-src/mSetDecide.cmi 0m00.00s | 11900 ko | gen-src/numeral.cmi 0m00.00s | 15820 ko | gen-src/numeral.cmx 0m00.00s | 12108 ko | gen-src/orderedType0.cmi 0m00.00s | 13444 ko | gen-src/ordersFacts.cmi 0m00.00s | 11760 ko | gen-src/ordersLists.cmi 0m00.00s | 15096 ko | gen-src/ordersLists.cmx 0m00.00s | 12464 ko | gen-src/ordersTac.cmi 0m00.00s | 15060 ko | gen-src/pretty.cmi 0m00.00s | 13160 ko | gen-src/specif.cmi 0m00.00s | 12236 ko | gen-src/string0.cmi 0m00.00s | 14128 ko | gen-src/univSubst0.cmi 0m00.00s | 13520 ko | metacoq_erasure_plugin.cmxa 0m00.00s | 13624 ko | metacoq_safechecker_plugin.cmxa 0m00.00s | 13148 ko | run_template_monad.cmi 0m00.00s | 13520 ko | template_coq.cmxa 0m00.00s | 15004 ko | template_monad.cmi rocq-9.2.0/test-suite/precomputed-time-tests/no-output-sync/time-of-build.log.in000066400000000000000000011472441516144147600277360ustar00rootroot00000000000000Running with gitlab-runner 11.9.2 (fa86510e)  on roquableu curNbQZR Using Docker executor with image registry.gitlab.com/coq/coq:bionic_coq-V2020-08-28-V92 ... Pulling docker image registry.gitlab.com/coq/coq:bionic_coq-V2020-08-28-V92 ... Using docker image sha256:f232f9802a06400390b5d6afa5fd280d73c89890309a27e840013ef2e9809c91 for registry.gitlab.com/coq/coq:bionic_coq-V2020-08-28-V92 ... section_start:1598963621:prepare_script Running on runner-curNbQZR-project-6138686-concurrent-1 via roquableu... section_end:1598963624:prepare_script section_start:1598963624:get_sources Reinitialized existing Git repository in /builds/coq/coq/.git/ Removing _build_ci/ Removing _install_ci/ Removing config/Makefile Removing config/coq_config.ml Removing config/coq_config.py Removing test-suite/misc/universes/all_stdlib.v Removing time-of-build.log Removing tools/TimeFileMaker.pyc Clean repository Fetching changes with git depth set to 10... fatal: remote origin already exists. Auto packing the repository in background for optimum performance. See "git help gc" for manual housekeeping. Checking out fdbbc0cb as pr-12653... Skipping Git submodules setup section_end:1598963638:get_sources section_start:1598963638:restore_cache section_end:1598963641:restore_cache section_start:1598963641:download_artifacts Downloading artifacts for build:base (713526714)... Downloading artifacts from coordinator... ok  id=713526714 responseStatus=200 OK token=CwEA_cmf Downloading artifacts for plugin:ci-equations (713526793)... Downloading artifacts from coordinator... ok  id=713526793 responseStatus=200 OK token=hxEjzCme section_end:1598963691:download_artifacts section_start:1598963691:build_script $ cat /proc/{cpu,mem}info || true processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.059 cache size : 15360 KB physical id : 0 siblings : 12 core id : 0 cpu cores : 6 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.128 cache size : 15360 KB physical id : 0 siblings : 12 core id : 1 cpu cores : 6 apicid : 2 initial apicid : 2 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 2 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.132 cache size : 15360 KB physical id : 0 siblings : 12 core id : 2 cpu cores : 6 apicid : 4 initial apicid : 4 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 3 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.131 cache size : 15360 KB physical id : 0 siblings : 12 core id : 3 cpu cores : 6 apicid : 6 initial apicid : 6 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 4 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.127 cache size : 15360 KB physical id : 0 siblings : 12 core id : 4 cpu cores : 6 apicid : 8 initial apicid : 8 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 5 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.186 cache size : 15360 KB physical id : 0 siblings : 12 core id : 5 cpu cores : 6 apicid : 10 initial apicid : 10 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 6 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.248 cache size : 15360 KB physical id : 1 siblings : 12 core id : 0 cpu cores : 6 apicid : 32 initial apicid : 32 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 7 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.131 cache size : 15360 KB physical id : 1 siblings : 12 core id : 1 cpu cores : 6 apicid : 34 initial apicid : 34 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 8 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.137 cache size : 15360 KB physical id : 1 siblings : 12 core id : 2 cpu cores : 6 apicid : 36 initial apicid : 36 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 9 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.147 cache size : 15360 KB physical id : 1 siblings : 12 core id : 3 cpu cores : 6 apicid : 38 initial apicid : 38 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 10 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.129 cache size : 15360 KB physical id : 1 siblings : 12 core id : 4 cpu cores : 6 apicid : 40 initial apicid : 40 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 11 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.131 cache size : 15360 KB physical id : 1 siblings : 12 core id : 5 cpu cores : 6 apicid : 42 initial apicid : 42 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 12 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.062 cache size : 15360 KB physical id : 0 siblings : 12 core id : 0 cpu cores : 6 apicid : 1 initial apicid : 1 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 13 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.084 cache size : 15360 KB physical id : 0 siblings : 12 core id : 1 cpu cores : 6 apicid : 3 initial apicid : 3 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 14 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3194.423 cache size : 15360 KB physical id : 0 siblings : 12 core id : 2 cpu cores : 6 apicid : 5 initial apicid : 5 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 15 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.132 cache size : 15360 KB physical id : 0 siblings : 12 core id : 3 cpu cores : 6 apicid : 7 initial apicid : 7 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 16 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.170 cache size : 15360 KB physical id : 0 siblings : 12 core id : 4 cpu cores : 6 apicid : 9 initial apicid : 9 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 17 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3191.946 cache size : 15360 KB physical id : 0 siblings : 12 core id : 5 cpu cores : 6 apicid : 11 initial apicid : 11 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5785.73 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 18 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.131 cache size : 15360 KB physical id : 1 siblings : 12 core id : 0 cpu cores : 6 apicid : 33 initial apicid : 33 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 19 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.134 cache size : 15360 KB physical id : 1 siblings : 12 core id : 1 cpu cores : 6 apicid : 35 initial apicid : 35 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 20 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.123 cache size : 15360 KB physical id : 1 siblings : 12 core id : 2 cpu cores : 6 apicid : 37 initial apicid : 37 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 21 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.131 cache size : 15360 KB physical id : 1 siblings : 12 core id : 3 cpu cores : 6 apicid : 39 initial apicid : 39 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 22 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3192.149 cache size : 15360 KB physical id : 1 siblings : 12 core id : 4 cpu cores : 6 apicid : 41 initial apicid : 41 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: processor : 23 vendor_id : GenuineIntel cpu family : 6 model : 45 model name : Intel(R) Xeon(R) CPU E5-2667 0 @ 2.90GHz stepping : 7 microcode : 0x718 cpu MHz : 3195.640 cache size : 15360 KB physical id : 1 siblings : 12 core id : 5 cpu cores : 6 apicid : 43 initial apicid : 43 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm ida arat pln pts md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit bogomips : 5792.29 clflush size : 64 cache_alignment : 64 address sizes : 46 bits physical, 48 bits virtual power management: MemTotal: 65879492 kB MemFree: 10395980 kB MemAvailable: 59790724 kB Buffers: 12390688 kB Cached: 18542568 kB SwapCached: 37680 kB Active: 20395936 kB Inactive: 14205172 kB Active(anon): 3459064 kB Inactive(anon): 165896 kB Active(file): 16936872 kB Inactive(file): 14039276 kB Unevictable: 48 kB Mlocked: 48 kB SwapTotal: 4194300 kB SwapFree: 3334988 kB Dirty: 13300 kB Writeback: 0 kB AnonPages: 3648112 kB Mapped: 555304 kB Shmem: 784 kB KReclaimable: 19083648 kB Slab: 20438420 kB SReclaimable: 19083648 kB SUnreclaim: 1354772 kB KernelStack: 16012 kB PageTables: 33208 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 37134044 kB Committed_AS: 10963564 kB VmallocTotal: 34359738367 kB VmallocUsed: 161980 kB VmallocChunk: 0 kB Percpu: 137728 kB HardwareCorrupted: 0 kB AnonHugePages: 0 kB ShmemHugePages: 0 kB ShmemPmdMapped: 0 kB FileHugePages: 0 kB FilePmdMapped: 0 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 0 kB DirectMap4k: 10120980 kB DirectMap2M: 56909824 kB DirectMap1G: 0 kB $ ls -a . .. .git .gitattributes .github .gitignore .gitlab-ci.yml .mailmap .merlin.in .ocamlformat .ocamlinit CODE_OF_CONDUCT.md CONTRIBUTING.md CREDITS INSTALL.md LICENSE META.rocq-runtime.in Makefile Makefile.build Makefile.checker Makefile.ci Makefile.common Makefile.dev Makefile.doc Makefile.ide Makefile.install Makefile.make Makefile.vofiles README.md _build_ci _install_ci azure-pipelines.yml checker clib config configure configure.ml coq-doc.opam coq.opam coq.opam.docker coqide-server.opam coqide.opam coqpp default.nix dev doc dune dune-project engine gramlib ide install.sh interp kernel lib library man parsing plugins pretyping printing proofs shell.nix stm tactics test-suite theories tools topbin toplevel user-contrib vernac $ printenv -0 | sort -z | tr '\0' '\n' BASE_ONLY_OPAM=elpi.1.11.0 BASE_OPAM=num zarith.1.9.1 ocamlfind.1.8.1 ounit2.2.2.3 odoc.1.5.0 BASE_OPAM_EDGE=dune.2.5.1 dune-release.1.3.3 ocamlformat.0.14.2 CACHEKEY=bionic_coq-V2020-08-28-V92 CI=true CI_API_V4_URL=https://gitlab.com/api/v4 CI_BUILD_BEFORE_SHA=727d9e5de2b64fd98bc085089b92891bcbad095f CI_BUILD_ID=713656562 CI_BUILD_NAME=plugin:ci-metacoq CI_BUILD_REF=fdbbc0cbc3906704e6e4e92d5bf2f6ffe8476357 CI_BUILD_REF_NAME=pr-12653 CI_BUILD_REF_SLUG=pr-12653 CI_BUILD_STAGE=stage-3 CI_BUILD_TOKEN=[MASKED] CI_COMMIT_BEFORE_SHA=727d9e5de2b64fd98bc085089b92891bcbad095f CI_COMMIT_BRANCH=pr-12653 CI_COMMIT_DESCRIPTION= Bot merge 0d30f79268fea18ef99c040a859956f61c3d978a and 7c1779e124fe4bf2733af12488b18bee92840127 CI_COMMIT_MESSAGE=[CI merge] PR #12653: Syntax for specifying cumulative inductives Bot merge 0d30f79268fea18ef99c040a859956f61c3d978a and 7c1779e124fe4bf2733af12488b18bee92840127 CI_COMMIT_REF_NAME=pr-12653 CI_COMMIT_REF_PROTECTED=false CI_COMMIT_REF_SLUG=pr-12653 CI_COMMIT_SHA=fdbbc0cbc3906704e6e4e92d5bf2f6ffe8476357 CI_COMMIT_SHORT_SHA=fdbbc0cb CI_COMMIT_TITLE=[CI merge] PR #12653: Syntax for specifying cumulative inductives CI_CONFIG_PATH=.gitlab-ci.yml CI_DEFAULT_BRANCH=master CI_DISPOSABLE_ENVIRONMENT=true CI_JOB_ID=713656562 CI_JOB_JWT=[MASKED] CI_JOB_NAME=plugin:ci-metacoq CI_JOB_STAGE=stage-3 CI_JOB_TOKEN=[MASKED] CI_JOB_URL=https://gitlab.com/coq/coq/-/jobs/713656562 CI_NODE_TOTAL=1 CI_OPAM=menhir.20190626 ocamlgraph.1.8.8 CI_PAGES_DOMAIN=gitlab.io CI_PAGES_URL=https://coq.gitlab.io/coq CI_PIPELINE_ID=184301476 CI_PIPELINE_IID=17942 CI_PIPELINE_SOURCE=push CI_PIPELINE_URL=https://gitlab.com/coq/coq/-/pipelines/184301476 CI_PROJECT_DIR=/builds/coq/coq CI_PROJECT_ID=6138686 CI_PROJECT_NAME=coq CI_PROJECT_NAMESPACE=coq CI_PROJECT_PATH=coq/coq CI_PROJECT_PATH_SLUG=coq-coq CI_PROJECT_REPOSITORY_LANGUAGES=ocaml,coq,shell,tex,c CI_PROJECT_ROOT_NAMESPACE=coq CI_PROJECT_TITLE=coq CI_PROJECT_URL=https://gitlab.com/coq/coq CI_PROJECT_VISIBILITY=public CI_REGISTRY=registry.gitlab.com CI_REGISTRY_IMAGE=registry.gitlab.com/coq/coq CI_REGISTRY_PASSWORD=[MASKED] CI_REGISTRY_USER=gitlab-ci-token CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/coq/coq.git CI_RUNNER_DESCRIPTION=roquableu CI_RUNNER_EXECUTABLE_ARCH=linux/amd64 CI_RUNNER_ID=816543 CI_RUNNER_REVISION=fa86510e CI_RUNNER_TAGS= CI_RUNNER_VERSION=11.9.2 CI_SERVER=yes CI_SERVER_HOST=gitlab.com CI_SERVER_NAME=GitLab CI_SERVER_PORT=443 CI_SERVER_PROTOCOL=https CI_SERVER_REVISION=e937f778b66 CI_SERVER_TLS_CA_FILE=/builds/coq/coq.tmp/CI_SERVER_TLS_CA_FILE CI_SERVER_URL=https://gitlab.com CI_SERVER_VERSION=13.4.0-pre CI_SERVER_VERSION_MAJOR=13 CI_SERVER_VERSION_MINOR=4 CI_SERVER_VERSION_PATCH=0 COMPILER=4.05.0 COMPILER_EDGE=4.10.0 COQIDE_OPAM=cairo2.0.6.1 lablgtk3-sourceview3.3.1.0 DEBIAN_FRONTEND=noninteractive FF_K8S_USE_ENTRYPOINT_OVER_COMMAND=true FULL_CI=true GITLAB_CI=true GITLAB_FEATURES=audit_events,blocked_issues,burndown_charts,code_owners,code_review_analytics,contribution_analytics,description_diffs,elastic_search,group_activity_analytics,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,iterations,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,milestone_charts,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,project_merge_request_analytics,protected_refs_for_users,push_rules,repository_mirrors,repository_size_limit,seat_link,send_emails_from_admin_area,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,ci_secrets_management,cluster_agents,cluster_deployments,code_owner_approval_required,commit_committer_check,compliance_framework,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,cycle_analytics_for_groups,db_load_balancing,default_branch_protection_restriction_in_groups,default_project_deletion_protection,dependency_proxy,deploy_board,disable_name_update_for_users,email_additional_text,epics,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,generic_alert_fingerprinting,github_project_service_integration,group_allowed_email_domains,group_coverage_reports,group_forking_protection,group_ip_restriction,group_merge_request_analytics,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,jira_issues_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,admin_merge_request_approvers_rules,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,opsgenie_integration,package_forwarding,pages_size_limit,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,coverage_fuzzing,credentials_inventory,dast,dependency_scanning,enterprise_templates,api_fuzzing,group_level_compliance_dashboard,incident_management,insights,issuable_health_status,license_scanning,personal_access_token_api_management,personal_access_token_expiration_policy,enforce_pat_expiration,prometheus_alerts,pseudonymizer,release_evidence_test_artifacts,report_approver_rules,requirements,sast,secret_detection,security_dashboard,security_on_demand_scans,status_page,subepics,threat_monitoring,tracing,quality_management GITLAB_USER_EMAIL=gaetan.gilbert@skyskimmer.net GITLAB_USER_ID=1343245 GITLAB_USER_LOGIN=SkySkimmer GITLAB_USER_NAME=GaΓ«tan Gilbert GIT_DEPTH=10 HOME=/root HOSTNAME=runner-curNbQZR-project-6138686-concurrent-1 IMAGE=registry.gitlab.com/coq/coq:bionic_coq-V2020-08-28-V92 NJOBS=2 OLDPWD=/ OPAMJOBS=2 OPAMROOT=/root/.opamcache OPAMROOTISOK=true OPAMYES=true OPAM_SWITCH=base OPAM_VARIANT= PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/builds/coq/coq SHLVL=1 SKIP_DOCKER=true UNRELIABLE=enabled WINDOWS=enabled WINDOWS_ALL_ADDONS=disabled _=/usr/bin/printenv $ declare -A switch_table $ switch_table=( ["base"]="$COMPILER" ["edge"]="$COMPILER_EDGE" ) $ opam switch set -y "${switch_table[$OPAM_SWITCH]}$OPAM_VARIANT" # Run eval $(opam env) to update the current shell environment $ eval $(opam env) $ opam list # Packages matching: installed # Name # Installed # Synopsis astring 0.8.5 Alternative String module for OCaml base-bigarray base base-bytes base Bytes library distributed with the OCaml compiler base-num base Num library distributed with the OCaml compiler base-threads base base-unix base cairo2 0.6.1 Binding to Cairo, a 2D Vector Graphics Library camlp5 7.12 Preprocessor-pretty-printer of OCaml cmdliner 1.0.4 Declarative definition of command line interfaces for OCaml conf-cairo 1 Virtual package relying on a Cairo system installation conf-gmp 1 Virtual package relying on a GMP lib system installation conf-gtk3 18 Virtual package relying on GTK+ 3 conf-gtksourceview3 0+2 Virtual package relying on a GtkSourceView-3 system installation conf-m4 1 Virtual package relying on m4 conf-perl 1 Virtual package relying on perl conf-pkg-config 1.3 Virtual package relying on pkg-config installation cppo 1.6.6 Code preprocessor like cpp for OCaml dune 2.7.0 Fast, portable, and opinionated build system dune-configurator 2.7.0 Helper library for gathering system configuration elpi 1.11.0 ELPI - Embeddable Ξ»Prolog Interpreter fpath 0.7.2 File system paths for OCaml lablgtk3 3.1.0 OCaml interface to GTK+3 lablgtk3-sourceview3 3.1.0 OCaml interface to GTK+ gtksourceview library menhir 20190626 An LR(1) parser generator num 0 The Num library for arbitrary-precision integer and rational arithmetic ocaml 4.05.0 The OCaml compiler (virtual package) ocaml-base-compiler 4.05.0 Official 4.05.0 release ocaml-compiler-libs v0.12.1 OCaml compiler libraries repackaged ocaml-config 1 OCaml Switch Configuration ocaml-migrate-parsetree 1.7.3 Convert OCaml parsetrees between different versions ocaml-secondary-compiler 4.08.1-1 OCaml 4.08.1 Secondary Switch Compiler ocamlbuild 0.14.0 OCamlbuild is a build system with builtin rules to easily build most OCaml projects. ocamlfind 1.8.1 A library manager for OCaml ocamlfind-secondary 1.8.1 ocamlfind support for ocaml-secondary-compiler ocamlgraph 1.8.8 A generic graph library for OCaml odoc 1.5.0 OCaml documentation generator ounit2 2.2.3 OUnit testing framework ppx_derivers 1.2.1 Shared [@@deriving] plugin registry ppx_deriving 4.5 Type-driven code generation for OCaml >=4.02.2 ppx_tools 5.0+4.05.0 Tools for authors of ppx rewriters and other syntactic tools ppxfind 1.4 Tool combining ocamlfind and ppx ppxlib 0.15.0 Standard library for ppx rewriters re 1.9.0 RE is a regular expression library for OCaml result 1.5 Compatibility Result module seq 0.2.2 Compatibility package for OCaml's standard iterator type starting from 4.07 sexplib0 v0.14.0 Library containing the definition of S-expressions and some base converters stdlib-shims 0.1.0 Backport some of the new stdlib features to older compiler topkg 1.0.2 The transitory OCaml software packager tyxml 4.4.0 TyXML is a library for building correct HTML and SVG documents uchar 0.0.2 Compatibility library for OCaml's Uchar module uutf 1.0.2 Non-blocking streaming Unicode codec for OCaml zarith 1.9.1 Implements arithmetic and logical operations over arbitrary-precision integers $ opam config list <><> Global opam variables ><><><><><><><><><><><><><><><><><><><><><><><><><><> arch x86_64 # Inferred from system jobs 2 # The number of parallel jobs set up in opam configuration make make # The 'make' command to use opam-version 2.0.6 # The currently running opam version os linux # Inferred from system os-distribution ubuntu # Inferred from system os-family debian # Inferred from system os-version 18.04 # Inferred from system root /root/.opamcache # The current opam root directory switch 4.05.0 # The identifier of the current switch sys-ocaml-version # OCaml version present on your system independently of opam, if any <><> Configuration variables from the current switch ><><><><><><><><><><><><><> prefix /root/.opamcache/4.05.0 lib /root/.opamcache/4.05.0/lib bin /root/.opamcache/4.05.0/bin sbin /root/.opamcache/4.05.0/sbin share /root/.opamcache/4.05.0/share doc /root/.opamcache/4.05.0/doc etc /root/.opamcache/4.05.0/etc man /root/.opamcache/4.05.0/man toplevel /root/.opamcache/4.05.0/lib/toplevel stublibs /root/.opamcache/4.05.0/lib/stublibs user root group root <><> Package variables ('opam config list PKG' to show) <><><><><><><><><><><><> PKG:name # Name of the package PKG:version # Version of the package PKG:depends # Resolved direct dependencies of the package PKG:installed # Whether the package is installed PKG:enable # Takes the value "enable" or "disable" depending on whether the package is installed PKG:pinned # Whether the package is pinned PKG:bin # Binary directory for this package PKG:sbin # System binary directory for this package PKG:lib # Library directory for this package PKG:man # Man directory for this package PKG:doc # Doc directory for this package PKG:share # Share directory for this package PKG:etc # Etc directory for this package PKG:build # Directory where the package was built PKG:hash # Hash of the package archive PKG:dev # True if this is a development package PKG:build-id # A hash identifying the precise package version with all its dependencies $ set -e $ echo 'start:coq.test' start:coq.test $ make -f Makefile.ci -j "$NJOBS" "${CI_JOB_NAME#*:}" ./dev/ci/ci-wrapper.sh equations ++ : 2 ++ export NJOBS ++ '[' -n true ']' ++ export OCAMLPATH=/builds/coq/coq/_install_ci/lib: ++ OCAMLPATH=/builds/coq/coq/_install_ci/lib: ++ export COQBIN=/builds/coq/coq/_install_ci/bin ++ COQBIN=/builds/coq/coq/_install_ci/bin ++ export CI_BRANCH=pr-12653 ++ CI_BRANCH=pr-12653 ++ [[ 12653 =~ ^[0-9]*$ ]] ++ export CI_PULL_REQUEST=12653 ++ CI_PULL_REQUEST=12653 ++ export PATH=/builds/coq/coq/_install_ci/bin:/root/.opamcache/4.05.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ++ PATH=/builds/coq/coq/_install_ci/bin:/root/.opamcache/4.05.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ++ export COQBIN=/builds/coq/coq/_install_ci/bin/ ++ COQBIN=/builds/coq/coq/_install_ci/bin/ ++ ls -l /builds/coq/coq/_install_ci/bin/ total 377964 -rwxr-xr-x 1 root root 1885376 Sep 1 11:46 coq-tex -rwxr-xr-x 1 root root 2500248 Sep 1 11:46 rocq makefile -rwxr-xr-x 1 root root 24673120 Sep 1 11:46 coqc -rwxr-xr-x 1 root root 9648760 Sep 1 11:46 coqchk -rwxr-xr-x 1 root root 5855160 Sep 1 11:46 coqdep -rwxr-xr-x 1 root root 4413792 Sep 1 11:46 coqdoc -rwxr-xr-x 1 root root 11526312 Sep 1 11:47 coqide -rwxr-xr-x 1 root root 25110448 Sep 1 11:47 coqidetop -rwxr-xr-x 1 root root 25110448 Sep 1 11:47 coqidetop.opt -rwxr-xr-x 1 root root 449295 Sep 1 11:46 coqpp -rwxr-xr-x 1 root root 32153472 Sep 1 11:47 coqproofworker.byte -rwxr-xr-x 1 root root 24673424 Sep 1 11:46 coqproofworker.opt -rwxr-xr-x 1 root root 32153472 Sep 1 11:47 coqqueryworker.byte -rwxr-xr-x 1 root root 24673424 Sep 1 11:46 coqqueryworker.opt -rwxr-xr-x 1 root root 32153477 Sep 1 11:47 coqtacticworker.byte -rwxr-xr-x 1 root root 24673448 Sep 1 11:46 coqtacticworker.opt -rwxr-xr-x 1 root root 24673288 Sep 1 11:46 coqtop -rwxr-xr-x 1 root root 41805680 Sep 1 11:47 coqtop.byte -rwxr-xr-x 1 root root 24673288 Sep 1 11:46 coqtop.opt -rwxr-xr-x 1 root root 1821312 Sep 1 11:46 coqwc -rwxr-xr-x 1 root root 2827416 Sep 1 11:46 coqworkmgr -rwxr-xr-x 1 root root 5905992 Sep 1 11:47 fake_ide -rwxr-xr-x 1 root root 1757920 Sep 1 11:46 ocamllibdep -rwxr-xr-x 1 root root 1877056 Sep 1 11:46 votour ++ CI_BUILD_DIR=/builds/coq/coq/_build_ci ++ ls -l /builds/coq/coq/_build_ci total 4 drwxr-xr-x 8 root root 4096 Sep 1 11:51 equations ++ set +x + git_download equations + local PROJECT=equations + local DEST=/builds/coq/coq/_build_ci/equations + local GITURL_VAR=equations_CI_GITURL + local GITURL=https://github.com/SkySkimmer/Coq-Equations + local REF_VAR=equations_CI_REF + local REF=cumul-syntax + '[' -d /builds/coq/coq/_build_ci/equations ']' + echo 'Warning: download and unpacking of equations skipped because /builds/coq/coq/_build_ci/equations already exists.' Warning: download and unpacking of equations skipped because /builds/coq/coq/_build_ci/equations already exists. + cd /builds/coq/coq/_build_ci/equations + ./configure.sh coq Building Coq version (default) + make ci + '[' -z x ']' + command make ci + make ci make[1]: Entering directory '/builds/coq/coq/_build_ci/equations' make[2]: Nothing to be done for 'real-all'. cd test-suite && make cd examples && make make[2]: Entering directory '/builds/coq/coq/_build_ci/equations/test-suite' make[2]: Entering directory '/builds/coq/coq/_build_ci/equations/examples' make[3]: Nothing to be done for 'real-all'. make[2]: Leaving directory '/builds/coq/coq/_build_ci/equations/examples' make[3]: Nothing to be done for 'real-all'. make[2]: Leaving directory '/builds/coq/coq/_build_ci/equations/test-suite' make[1]: Leaving directory '/builds/coq/coq/_build_ci/equations' + make install + '[' -z x ']' + command make install + make install make[1]: Entering directory '/builds/coq/coq/_build_ci/equations' INSTALL theories/Init.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Signature.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/CoreTactics.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Prop/Logic.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Classes.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDec.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDecInstances.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Subterm.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/DepElim.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Tactics.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Constants.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/NoConfusion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/FunctionalInduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Loader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Telescopes.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/TransparentEquations.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/OpaqueEquations.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Equations.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Type/Logic.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalExtensionality.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation_Properties.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFounded.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Classes.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDec.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/DepElim.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Tactics.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Subterm.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Constants.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDecInstances.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/NoConfusion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalInduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Loader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Telescopes.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFoundedInstances.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/All.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Init.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Signature.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/CoreTactics.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Prop/Logic.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Classes.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDec.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDecInstances.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Subterm.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/DepElim.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Tactics.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Constants.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/NoConfusion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/FunctionalInduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Loader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Telescopes.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/TransparentEquations.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/OpaqueEquations.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Equations.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Type/Logic.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalExtensionality.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation_Properties.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFounded.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Classes.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDec.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/DepElim.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Tactics.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Subterm.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Constants.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDecInstances.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/NoConfusion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalInduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Loader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Telescopes.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFoundedInstances.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/All.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Init.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Signature.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/CoreTactics.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Prop/Logic.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Classes.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDec.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/EqDecInstances.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Subterm.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/DepElim.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Tactics.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Constants.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/NoConfusion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/FunctionalInduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Loader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/Telescopes.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/TransparentEquations.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Prop/OpaqueEquations.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Prop INSTALL theories/Equations.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL theories/Type/Logic.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalExtensionality.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Relation_Properties.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFounded.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Classes.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDec.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/DepElim.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Tactics.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Subterm.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Constants.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/EqDecInstances.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/NoConfusion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/FunctionalInduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Loader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/Telescopes.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/WellFoundedInstances.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL theories/Type/All.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations//Type INSTALL src/g_equations.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_common.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/ederive.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/sigma_types.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/subterm.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/eqdec.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/depelim.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/syntax.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/context_map.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/simplify.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/splitting.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/covering.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles_proofs.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf_hom.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/extra_tactics.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_plugin_mod.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_common.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/ederive.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/sigma_types.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/subterm.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/eqdec.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/depelim.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/syntax.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/context_map.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/simplify.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/splitting.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/covering.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles_proofs.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf_hom.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/extra_tactics.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_plugin.cmxa /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/g_equations.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_common.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/ederive.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/sigma_types.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/subterm.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/eqdec.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/depelim.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/syntax.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/context_map.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/simplify.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/splitting.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/covering.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles_proofs.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/principles.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf_hom.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/noconf.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/extra_tactics.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ INSTALL src/equations_plugin_mod.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/Equations/ make[2]: Entering directory '/builds/coq/coq/_build_ci/equations' make[2]: Leaving directory '/builds/coq/coq/_build_ci/equations' make[1]: Leaving directory '/builds/coq/coq/_build_ci/equations' Aggregating timing log... No timing data ./dev/ci/ci-wrapper.sh metacoq ++ : 2 ++ export NJOBS ++ '[' -n true ']' ++ export OCAMLPATH=/builds/coq/coq/_install_ci/lib: ++ OCAMLPATH=/builds/coq/coq/_install_ci/lib: ++ export COQBIN=/builds/coq/coq/_install_ci/bin ++ COQBIN=/builds/coq/coq/_install_ci/bin ++ export CI_BRANCH=pr-12653 ++ CI_BRANCH=pr-12653 ++ [[ 12653 =~ ^[0-9]*$ ]] ++ export CI_PULL_REQUEST=12653 ++ CI_PULL_REQUEST=12653 ++ export PATH=/builds/coq/coq/_install_ci/bin:/root/.opamcache/4.05.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ++ PATH=/builds/coq/coq/_install_ci/bin:/root/.opamcache/4.05.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ++ export COQBIN=/builds/coq/coq/_install_ci/bin/ ++ COQBIN=/builds/coq/coq/_install_ci/bin/ ++ ls -l /builds/coq/coq/_install_ci/bin/ total 377964 -rwxr-xr-x 1 root root 1885376 Sep 1 11:46 coq-tex -rwxr-xr-x 1 root root 2500248 Sep 1 11:46 rocq makefile -rwxr-xr-x 1 root root 24673120 Sep 1 11:46 coqc -rwxr-xr-x 1 root root 9648760 Sep 1 11:46 coqchk -rwxr-xr-x 1 root root 5855160 Sep 1 11:46 coqdep -rwxr-xr-x 1 root root 4413792 Sep 1 11:46 coqdoc -rwxr-xr-x 1 root root 11526312 Sep 1 11:47 coqide -rwxr-xr-x 1 root root 25110448 Sep 1 11:47 coqidetop -rwxr-xr-x 1 root root 25110448 Sep 1 11:47 coqidetop.opt -rwxr-xr-x 1 root root 449295 Sep 1 11:46 coqpp -rwxr-xr-x 1 root root 32153472 Sep 1 11:47 coqproofworker.byte -rwxr-xr-x 1 root root 24673424 Sep 1 11:46 coqproofworker.opt -rwxr-xr-x 1 root root 32153472 Sep 1 11:47 coqqueryworker.byte -rwxr-xr-x 1 root root 24673424 Sep 1 11:46 coqqueryworker.opt -rwxr-xr-x 1 root root 32153477 Sep 1 11:47 coqtacticworker.byte -rwxr-xr-x 1 root root 24673448 Sep 1 11:46 coqtacticworker.opt -rwxr-xr-x 1 root root 24673288 Sep 1 11:46 coqtop -rwxr-xr-x 1 root root 41805680 Sep 1 11:47 coqtop.byte -rwxr-xr-x 1 root root 24673288 Sep 1 11:46 coqtop.opt -rwxr-xr-x 1 root root 1821312 Sep 1 11:46 coqwc -rwxr-xr-x 1 root root 2827416 Sep 1 11:46 coqworkmgr -rwxr-xr-x 1 root root 5905992 Sep 1 11:47 fake_ide -rwxr-xr-x 1 root root 1757920 Sep 1 11:46 ocamllibdep -rwxr-xr-x 1 root root 1877056 Sep 1 11:46 votour ++ CI_BUILD_DIR=/builds/coq/coq/_build_ci ++ ls -l /builds/coq/coq/_build_ci total 4 drwxr-xr-x 8 root root 4096 Sep 1 12:34 equations ++ set +x + git_download metacoq + local PROJECT=metacoq + local DEST=/builds/coq/coq/_build_ci/metacoq + local GITURL_VAR=metacoq_CI_GITURL + local GITURL=https://github.com/SkySkimmer/metacoq + local REF_VAR=metacoq_CI_REF + local REF=cumul-syntax + '[' -d /builds/coq/coq/_build_ci/metacoq ']' + '[' '' = 1 ']' + '[' true = '' ']' + local ARCHIVEURL_VAR=metacoq_CI_ARCHIVEURL + local ARCHIVEURL=https://github.com/SkySkimmer/metacoq/archive + mkdir -p /builds/coq/coq/_build_ci/metacoq + cd /builds/coq/coq/_build_ci/metacoq ++ git ls-remote https://github.com/SkySkimmer/metacoq refs/heads/cumul-syntax ++ cut -f 1 + local COMMIT=130dee007744c0e743d13613a398cfbe15ad95ff + [[ 130dee007744c0e743d13613a398cfbe15ad95ff == '' ]] + wget https://github.com/SkySkimmer/metacoq/archive/130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz --2020-09-01 12:34:56-- https://github.com/SkySkimmer/metacoq/archive/130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz Resolving github.com (github.com)... 140.82.121.3 Connecting to github.com (github.com)|140.82.121.3|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://codeload.github.com/SkySkimmer/metacoq/tar.gz/130dee007744c0e743d13613a398cfbe15ad95ff [following] --2020-09-01 12:34:56-- https://codeload.github.com/SkySkimmer/metacoq/tar.gz/130dee007744c0e743d13613a398cfbe15ad95ff Resolving codeload.github.com (codeload.github.com)... 140.82.121.9 Connecting to codeload.github.com (codeload.github.com)|140.82.121.9|:443... connected. HTTP request sent, awaiting response... 200 OK Length: unspecified [application/x-gzip] Saving to: '130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz' 0K .......... .......... .......... .......... .......... 1.14M 50K .......... .......... .......... .......... .......... 2.37M 100K .......... .......... .......... .......... .......... 10.9M 150K .......... .......... .......... .......... .......... 10.9M 200K .......... .......... .......... .......... .......... 3.08M 250K .......... .......... .......... .......... .......... 10.9M 300K .......... .......... .......... .......... .......... 11.4M 350K .......... .......... .......... .......... .......... 10.9M 400K .......... .......... .......... .......... .......... 7.25M 450K .......... .......... .......... .......... .......... 9.97M 500K .......... .......... .......... .......... .......... 10.9M 550K .......... .......... .......... .......... .......... 3.39M 600K .......... .......... .......... .......... .......... 10.8M 650K .......... .......... .......... .......... .......... 2.57M 700K .......... .......... .......... .......... .......... 11.4M 750K .......... .......... .......... .......... .......... 10.8M 800K .......... .......... .......... .......... ......... 11.3M=0.2s 2020-09-01 12:34:57 (4.92 MB/s) - '130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz' saved [869537] + tar xfz 130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz --strip-components=1 + rm -f 130dee007744c0e743d13613a398cfbe15ad95ff.tar.gz + cd /builds/coq/coq/_build_ci/metacoq + ./configure.sh local make[1]: Entering directory '/builds/coq/coq/_build_ci/metacoq' make -C template-coq mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' rm -f Makefile.coq rm -f Makefile.plugin rm -f Makefile.template make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -C pcuic mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' rm -f metacoq-config rm -f Makefile.plugin _PluginProject rm -f Makefile.pcuic _CoqProject make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -C safechecker mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' rm -f metacoq-config rm -f Makefile.plugin _PluginProject rm -f Makefile.safechecker _CoqProject make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -C erasure mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' rm -f Makefile.plugin rm -f Makefile.erasure make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -C checker mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' rm -f Makefile.coq Makefile.plugin _CoqProject _PluginProject make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make -C examples mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/examples' rm -f Makefile.coq make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/examples' make -C test-suite mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite' rm -f Makefile.coq make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite' make -C translations mrproper make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/translations' rm -f Makefile.coq make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/translations' make[1]: Leaving directory '/builds/coq/coq/_build_ci/metacoq' Building MetaCoq locally + make .merlin + '[' -z x ']' + command make .merlin + make .merlin make[1]: Entering directory '/builds/coq/coq/_build_ci/metacoq' make -C template-coq .merlin make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' rocq makefile -f _PluginProject -o Makefile.plugin `which gsed || which sed` -i -e s/coqdeps/coqdeps.plugin/g Makefile.plugin make -f Makefile.plugin .merlin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' ROCQ DEP VFILES OCAMLLIBDEP gen-src/metacoq_template_plugin.mlpack FILL .merlin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -C pcuic .merlin make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' cat metacoq-config > _PluginProject cat _PluginProject.in >> _PluginProject rocq makefile -f _PluginProject -o Makefile.plugin `which gsed || which sed` -i -e s/coqdeps/coqdeps.plugin/g Makefile.plugin make -f Makefile.plugin .merlin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") OCAMLLIBDEP src/metacoq_pcuic_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") FILL .merlin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") OCAMLLIBDEP src/metacoq_pcuic_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -C safechecker .merlin make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' cat metacoq-config > _PluginProject cat _PluginProject.in >> _PluginProject rocq makefile -f _PluginProject -o Makefile.plugin `which gsed || which sed` -i -e s/coqdeps/coqdeps.plugin/g Makefile.plugin make -f Makefile.plugin .merlin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") COQPP src/g_metacoq_safechecker.mlg OCAMLLIBDEP src/metacoq_safechecker_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_safechecker.ml Bad -I option: ../template-coq/build: No such file or directory FILL .merlin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") OCAMLLIBDEP src/metacoq_safechecker_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_safechecker.ml Bad -I option: ../template-coq/build: No such file or directory make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -C erasure .merlin make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' cat metacoq-config > _PluginProject cat _PluginProject.in >> _PluginProject rocq makefile -f _PluginProject -o Makefile.plugin `which gsed || which sed` -i -e s/coqdeps/coqdeps.plugin/g Makefile.plugin make -f Makefile.plugin .merlin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") COQPP src/g_metacoq_erasure.mlg OCAMLLIBDEP src/metacoq_erasure_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_erasure.ml Bad -I option: ../template-coq/build: No such file or directory FILL .merlin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") OCAMLLIBDEP src/metacoq_erasure_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_erasure.ml Bad -I option: ../template-coq/build: No such file or directory make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -C checker .merlin make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' cat metacoq-config > _PluginProject cat _PluginProject.in >> _PluginProject rocq makefile -f _PluginProject -o Makefile.plugin make -f Makefile.plugin .merlin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make[3]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") COQPP src/g_metacoq_checker.mlg OCAMLLIBDEP src/metacoq_checker_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_checker.ml Bad -I option: ../template-coq/build: No such file or directory FILL .merlin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' ROCQ DEP VFILES Fatal error: exception Sys_error("../template-coq/build: No such file or directory") OCAMLLIBDEP src/metacoq_checker_plugin.mlpack Uncaught exception: Sys_error("../template-coq/build: No such file or directory") CAMLDEP src/g_metacoq_checker.ml Bad -I option: ../template-coq/build: No such file or directory make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[1]: Leaving directory '/builds/coq/coq/_build_ci/metacoq' + make ci-local + '[' -z x ']' + command make ci-local + make ci-local make[1]: Entering directory '/builds/coq/coq/_build_ci/metacoq' make all test-suite make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq' make -C template-coq make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' rocq makefile -f _CoqProject -o Makefile.coq rocq makefile -f _TemplateCoqProject -o Makefile.template `which gsed || which sed` -i -e s/coqdeps/coqdeps.template/g Makefile.template make -f Makefile.coq make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' ROCQ DEP VFILES ROCQ compile theories/utils/MCPrelude.v ROCQ compile theories/utils/MCRelations.v theories/utils/MCPrelude.vo (real: 0.09, user: 0.05, sys: 0.04, mem: 63096 ko) ROCQ compile theories/utils/MCProd.v theories/utils/MCRelations.vo (real: 0.09, user: 0.05, sys: 0.04, mem: 68156 ko) ROCQ compile theories/utils/MCSquash.v theories/utils/MCSquash.vo (real: 0.09, user: 0.04, sys: 0.04, mem: 61384 ko) ROCQ compile theories/utils/MCArith.v theories/utils/MCProd.vo (real: 0.14, user: 0.09, sys: 0.04, mem: 88348 ko) ROCQ compile theories/utils/MCCompare.v theories/utils/MCArith.vo (real: 0.70, user: 0.48, sys: 0.22, mem: 404556 ko) ROCQ compile theories/utils/MCEquality.v theories/utils/MCEquality.vo (real: 0.08, user: 0.04, sys: 0.03, mem: 62924 ko) ROCQ compile theories/utils/LibHypsNaming.v theories/utils/LibHypsNaming.vo (real: 0.60, user: 0.42, sys: 0.18, mem: 339136 ko) ROCQ compile theories/config.v theories/config.vo (real: 0.08, user: 0.04, sys: 0.03, mem: 61716 ko) ROCQ compile theories/monad_utils.v theories/monad_utils.vo (real: 0.22, user: 0.14, sys: 0.08, mem: 149456 ko) ROCQ compile theories/utils/MCList.v theories/utils/MCList.vo (real: 1.71, user: 1.47, sys: 0.22, mem: 452340 ko) ROCQ compile theories/utils/MCOption.v theories/utils/MCOption.vo (real: 0.79, user: 0.56, sys: 0.22, mem: 440168 ko) ROCQ compile theories/utils/All_Forall.v theories/utils/MCCompare.vo (real: 6.40, user: 6.04, sys: 0.32, mem: 529900 ko) ROCQ compile theories/utils/MCString.v theories/utils/MCString.vo (real: 0.44, user: 0.30, sys: 0.13, mem: 270156 ko) theories/utils/All_Forall.vo (real: 3.03, user: 2.78, sys: 0.23, mem: 465984 ko) ROCQ compile theories/utils.v theories/utils.vo (real: 0.71, user: 0.52, sys: 0.18, mem: 385340 ko) ROCQ compile theories/utils/wGraph.v ROCQ compile theories/BasicAst.v theories/BasicAst.vo (real: 0.98, user: 0.75, sys: 0.22, mem: 450728 ko) ROCQ compile theories/Universes.v theories/utils/wGraph.vo (real: 5.22, user: 4.72, sys: 0.47, mem: 498552 ko) theories/Universes.vo (real: 4.54, user: 4.23, sys: 0.28, mem: 531272 ko) ROCQ compile theories/common/uGraph.v ROCQ compile theories/Environment.v theories/Environment.vo (real: 1.35, user: 1.10, sys: 0.24, mem: 484172 ko) ROCQ compile theories/Ast.v theories/Ast.vo (real: 1.04, user: 0.79, sys: 0.24, mem: 479940 ko) ROCQ compile theories/AstUtils.v theories/AstUtils.vo (real: 1.24, user: 1.00, sys: 0.23, mem: 485664 ko) ROCQ compile theories/TemplateMonad/Common.v theories/TemplateMonad/Common.vo (real: 0.82, user: 0.60, sys: 0.22, mem: 437492 ko) ROCQ compile theories/Induction.v theories/Induction.vo (real: 1.45, user: 1.18, sys: 0.26, mem: 486324 ko) ROCQ compile theories/EnvironmentTyping.v theories/common/uGraph.vo (real: 6.23, user: 5.85, sys: 0.35, mem: 551516 ko) ROCQ compile theories/WfInv.v theories/WfInv.vo (real: 1.31, user: 1.05, sys: 0.25, mem: 489932 ko) ROCQ compile theories/TemplateMonad/Core.v theories/EnvironmentTyping.vo (real: 2.05, user: 1.77, sys: 0.27, mem: 491968 ko) ROCQ compile theories/TemplateMonad/Extractable.v theories/TemplateMonad/Core.vo (real: 0.97, user: 0.73, sys: 0.24, mem: 481988 ko) ROCQ compile theories/LiftSubst.v theories/TemplateMonad/Extractable.vo (real: 0.95, user: 0.70, sys: 0.23, mem: 481156 ko) ROCQ compile theories/TemplateMonad.v theories/TemplateMonad.vo (real: 0.79, user: 0.54, sys: 0.24, mem: 420452 ko) ROCQ compile theories/Constants.v theories/Constants.vo (real: 1.08, user: 0.82, sys: 0.25, mem: 498504 ko) theories/LiftSubst.vo (real: 12.60, user: 11.81, sys: 0.72, mem: 532016 ko) ROCQ compile theories/UnivSubst.v ROCQ compile theories/Pretty.v theories/Pretty.vo (real: 1.11, user: 0.87, sys: 0.24, mem: 486460 ko) theories/UnivSubst.vo (real: 3.38, user: 3.11, sys: 0.24, mem: 490756 ko) ROCQ compile theories/Typing.v ROCQ compile theories/Extraction.v theories/Extraction.vo (real: 9.78, user: 9.33, sys: 0.41, mem: 571876 ko) theories/Typing.vo (real: 53.00, user: 51.78, sys: 0.98, mem: 809012 ko) ROCQ compile theories/TypingWf.v theories/TypingWf.vo (real: 8.46, user: 8.05, sys: 0.36, mem: 556676 ko) ./update_plugin.sh Updating gen-src from src Copying from src to gen-src Renaming files to camelCase Moving All_Forall.ml to all_Forall.ml Moving All_Forall.mli to all_Forall.mli Moving Ascii.ml to ascii.ml Moving Ascii.mli to ascii.mli Moving Ast0.ml to ast0.ml Moving Ast0.mli to ast0.mli Moving AstUtils.ml to astUtils.ml Moving AstUtils.mli to astUtils.mli Moving BasicAst.ml to basicAst.ml Moving BasicAst.mli to basicAst.mli Moving Basics.ml to basics.ml Moving Basics.mli to basics.mli Moving BinInt.ml to binInt.ml Moving BinInt.mli to binInt.mli Moving BinNat.ml to binNat.ml Moving BinNat.mli to binNat.mli Moving BinNums.ml to binNums.ml Moving BinNums.mli to binNums.mli Moving BinPos.ml to binPos.ml Moving BinPos.mli to binPos.mli Moving BinPosDef.ml to binPosDef.ml Moving BinPosDef.mli to binPosDef.mli Moving Bool.ml to bool.ml Moving Bool.mli to bool.mli Moving Byte.ml to byte.ml Moving Byte.mli to byte.mli Moving CRelationClasses.ml to cRelationClasses.ml Moving CRelationClasses.mli to cRelationClasses.mli Moving Common0.ml to common0.ml Moving Common0.mli to common0.mli Moving Compare_dec.ml to compare_dec.ml Moving Compare_dec.mli to compare_dec.mli Moving Datatypes.ml to datatypes.ml Moving Datatypes.mli to datatypes.mli Moving Decimal.ml to decimal.ml Moving Decimal.mli to decimal.mli Moving Environment.ml to environment.ml Moving Environment.mli to environment.mli Moving Equalities.ml to equalities.ml Moving Equalities.mli to equalities.mli Moving Extractable.ml to extractable.ml Moving Extractable.mli to extractable.mli Moving Hexadecimal.ml to hexadecimal.ml Moving Hexadecimal.mli to hexadecimal.mli Moving Induction.ml to induction.ml Moving Induction.mli to induction.mli Moving LiftSubst.ml to liftSubst.ml Moving LiftSubst.mli to liftSubst.mli Moving List0.ml to list0.ml Moving List0.mli to list0.mli Moving Logic0.ml to logic0.ml Moving Logic0.mli to logic0.mli Moving MCCompare.ml to mCCompare.ml Moving MCCompare.mli to mCCompare.mli Moving MCList.ml to mCList.ml Moving MCList.mli to mCList.mli Moving MCOption.ml to mCOption.ml Moving MCOption.mli to mCOption.mli Moving MCPrelude.ml to mCPrelude.ml Moving MCPrelude.mli to mCPrelude.mli Moving MCProd.ml to mCProd.ml Moving MCProd.mli to mCProd.mli Moving MCRelations.ml to mCRelations.ml Moving MCRelations.mli to mCRelations.mli Moving MCString.ml to mCString.ml Moving MCString.mli to mCString.mli Moving MSetDecide.ml to mSetDecide.ml Moving MSetDecide.mli to mSetDecide.mli Moving MSetFacts.ml to mSetFacts.ml Moving MSetFacts.mli to mSetFacts.mli Moving MSetInterface.ml to mSetInterface.ml Moving MSetInterface.mli to mSetInterface.mli Moving MSetList.ml to mSetList.ml Moving MSetList.mli to mSetList.mli Moving MSetProperties.ml to mSetProperties.ml Moving MSetProperties.mli to mSetProperties.mli Moving Nat0.ml to nat0.ml Moving Nat0.mli to nat0.mli Moving Numeral.ml to numeral.ml Moving Numeral.mli to numeral.mli Moving OrderedType0.ml to orderedType0.ml Moving OrderedType0.mli to orderedType0.mli Moving Orders.ml to orders.ml Moving Orders.mli to orders.mli Moving OrdersFacts.ml to ordersFacts.ml Moving OrdersFacts.mli to ordersFacts.mli Moving OrdersLists.ml to ordersLists.ml Moving OrdersLists.mli to ordersLists.mli Moving OrdersTac.ml to ordersTac.ml Moving OrdersTac.mli to ordersTac.mli Moving PeanoNat.ml to peanoNat.ml Moving PeanoNat.mli to peanoNat.mli Moving Pretty.ml to pretty.ml Moving Pretty.mli to pretty.mli Moving Specif.ml to specif.ml Moving Specif.mli to specif.mli Moving String0.ml to string0.ml Moving String0.mli to string0.mli Moving UnivSubst0.ml to univSubst0.ml Moving UnivSubst0.mli to univSubst0.mli Moving Universes0.ml to universes0.ml Moving Universes0.mli to universes0.mli patching file gen-src/cRelationClasses.mli make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.template optfiles make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' ROCQ DEP VFILES COQPP src/g_template_coq.mlg CAMLDEP src/plugin_core.mli CAMLDEP src/run_template_monad.mli CAMLDEP src/template_monad.mli OCAMLLIBDEP src/template_coq.mlpack CAMLDEP src/plugin_core.ml CAMLDEP src/run_template_monad.ml CAMLDEP src/template_monad.ml CAMLDEP src/constr_denoter.ml CAMLDEP src/constr_quoter.ml CAMLDEP src/constr_reification.ml CAMLDEP src/denoter.ml CAMLDEP src/quoter.ml CAMLDEP src/reification.ml CAMLDEP src/tm_util.ml CAMLDEP src/g_template_coq.ml CAMLOPT -c -for-pack Template_coq src/tm_util.ml CAMLOPT -c -for-pack Template_coq src/reification.ml src/reification.cmx (real: 0.04, user: 0.01, sys: 0.01, mem: 14796 ko) CAMLOPT -c -for-pack Template_coq src/constr_reification.ml src/tm_util.cmx (real: 0.07, user: 0.03, sys: 0.02, mem: 21812 ko) CAMLC -c src/template_monad.mli src/template_monad.cmi (real: 0.02, user: 0.00, sys: 0.01, mem: 15004 ko) CAMLC -c src/plugin_core.mli src/constr_reification.cmx (real: 0.07, user: 0.04, sys: 0.02, mem: 22020 ko) CAMLOPT -c -for-pack Template_coq src/quoter.ml src/plugin_core.cmi (real: 0.03, user: 0.01, sys: 0.01, mem: 17068 ko) CAMLOPT -c -for-pack Template_coq src/denoter.ml src/denoter.cmx (real: src/quoter.cmx (real: 0.22, user: 0.240.05, ,u sesry:s :0.16 , 0.02sy,s :m em: 0.0224280, mkeom:) 34576 ko) CAMLOPT -c -for-pack Template_coq src/template_monad.ml CAMLOPT -c -for-pack Template_coq src/plugin_core.ml src/templaster_cm/opnaludg.inc_cmoxr e(.rcemaxl :( real: 0.10, user: 0.06, sys: 0.02, mem: 27236 ko) 0.10, user: 0.08, sys: 0.01, mem: 26216 ko) CAMLC -c src/run_template_monad.mli CAMLOPT -c -for-pack Template_coq src/constr_quoter.ml src/run_template_monad.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 13148 ko) CAMLOPT -c -for-pack Template_coq src/constr_denoter.ml src/constr_denoter.cmx (real: 0.18, user: 0.14, sys: 0.01, mem: 31740 ko) src/constr_quoter.cmx (real: 0.24, user: 0.17, sys: 0.03, mem: 33044 ko) CAMLOPT -c -for-pack Template_coq src/run_template_monad.ml src/run_template_monad.cmx (real: 0.28, user: 0.15, sys: 0.03, mem: 38520 ko) CAMLOPT -c -for-pack Template_coq src/g_template_coq.ml src/g_template_coq.cmx (real: 0.25, user: 0.10, sys: 0.02, mem: 33140 ko) CAMLOPT -pack -o src/template_coq.cmx src/template_coq.cmx (real: 0.13, user: 0.02, sys: 0.02, mem: 19956 ko) CAMLOPT -a -o src/template_coq.cmxa src/template_coq.cmxa (real: 0.03, user: 0.00, sys: 0.01, mem: 13520 ko) CAMLOPT -shared -o src/template_coq.cmxs src/template_coq.cmxs (real: 0.08, user: 0.05, sys: 0.03, mem: 16040 ko) make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' cp src/template_coq.cm* build/ make -f Makefile.template make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' ROCQ compile theories/Loader.v theories/Loader.vo (real: 1.04, user: 0.77, sys: 0.26, mem: 500040 ko) ROCQ compile theories/All.v theories/All.vo (real: 1.25, user: 0.95, sys: 0.28, mem: 521596 ko) make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.plugin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' CAMLDEP gen-src/univSubst0.mli CAMLDEP gen-src/universes0.mli CAMLDEP gen-src/string0.mli CAMLDEP gen-src/specif.mli CAMLDEP gen-src/run_extractable.mli CAMLDEP gen-src/pretty.mli CAMLDEP gen-src/plugin_core.mli CAMLDEP gen-src/peanoNat.mli CAMLDEP gen-src/ordersTac.mli CAMLDEP gen-src/ordersLists.mli CAMLDEP gen-src/orders.mli CAMLDEP gen-src/ordersFacts.mli CAMLDEP gen-src/orderedType0.mli CAMLDEP gen-src/numeral.mli CAMLDEP gen-src/nat0.mli CAMLDEP gen-src/mSetProperties.mli CAMLDEP gen-src/mSetList.mli CAMLDEP gen-src/mSetInterface.mli CAMLDEP gen-src/mSetFacts.mli CAMLDEP gen-src/mSetDecide.mli CAMLDEP gen-src/mCString.mli CAMLDEP gen-src/mCRelations.mli CAMLDEP gen-src/mCProd.mli CAMLDEP gen-src/mCOption.mli CAMLDEP gen-src/mCList.mli CAMLDEP gen-src/mCCompare.mli CAMLDEP gen-src/mCPrelude.mli CAMLDEP gen-src/logic0.mli CAMLDEP gen-src/list0.mli CAMLDEP gen-src/liftSubst.mli CAMLDEP gen-src/hexadecimal.mli CAMLDEP gen-src/extractable.mli CAMLDEP gen-src/equalities.mli CAMLDEP gen-src/environment.mli CAMLDEP gen-src/decimal.mli CAMLDEP gen-src/datatypes.mli CAMLDEP gen-src/cRelationClasses.mli CAMLDEP gen-src/config0.mli CAMLDEP gen-src/compare_dec.mli CAMLDEP gen-src/common0.mli CAMLDEP gen-src/bool.mli CAMLDEP gen-src/binPos.mli CAMLDEP gen-src/binPosDef.mli CAMLDEP gen-src/binNums.mli CAMLDEP gen-src/binNat.mli CAMLDEP gen-src/binInt.mli CAMLDEP gen-src/basics.mli CAMLDEP gen-src/basicAst.mli CAMLDEP gen-src/astUtils.mli CAMLDEP gen-src/ast0.mli CAMLDEP gen-src/ascii.mli CAMLDEP gen-src/all_Forall.mli OCAMLLIBDEP gen-src/metacoq_template_plugin.mlpack CAMLDEP gen-src/univSubst0.ml CAMLDEP gen-src/universes0.ml CAMLDEP gen-src/tm_util.ml CAMLDEP gen-src/string0.ml CAMLDEP gen-src/specif.ml CAMLDEP gen-src/run_extractable.ml CAMLDEP gen-src/quoter.ml CAMLDEP gen-src/reification.ml CAMLDEP gen-src/pretty.ml CAMLDEP gen-src/plugin_core.ml CAMLDEP gen-src/peanoNat.ml CAMLDEP gen-src/ordersTac.ml CAMLDEP gen-src/orders.ml CAMLDEP gen-src/ordersLists.ml CAMLDEP gen-src/ordersFacts.ml CAMLDEP gen-src/orderedType0.ml CAMLDEP gen-src/numeral.ml CAMLDEP gen-src/nat0.ml CAMLDEP gen-src/mSetProperties.ml CAMLDEP gen-src/mSetList.ml CAMLDEP gen-src/mSetInterface.ml CAMLDEP gen-src/mSetFacts.ml CAMLDEP gen-src/mSetDecide.ml CAMLDEP gen-src/mCString.ml CAMLDEP gen-src/mCRelations.ml CAMLDEP gen-src/mCProd.ml CAMLDEP gen-src/mCOption.ml CAMLDEP gen-src/mCList.ml CAMLDEP gen-src/mCCompare.ml CAMLDEP gen-src/mCPrelude.ml CAMLDEP gen-src/logic0.ml CAMLDEP gen-src/list0.ml CAMLDEP gen-src/liftSubst.ml CAMLDEP gen-src/hexadecimal.ml CAMLDEP gen-src/extractable.ml CAMLDEP gen-src/equalities.ml CAMLDEP gen-src/environment.ml CAMLDEP gen-src/denoter.ml CAMLDEP gen-src/decimal.ml CAMLDEP gen-src/datatypes.ml CAMLDEP gen-src/cRelationClasses.ml CAMLDEP gen-src/config0.ml CAMLDEP gen-src/compare_dec.ml CAMLDEP gen-src/common0.ml CAMLDEP gen-src/bool.ml CAMLDEP gen-src/binPos.ml CAMLDEP gen-src/binPosDef.ml CAMLDEP gen-src/binNums.ml CAMLDEP gen-src/binNat.ml CAMLDEP gen-src/binInt.ml CAMLDEP gen-src/basics.ml CAMLDEP gen-src/basicAst.ml CAMLDEP gen-src/astUtils.ml CAMLDEP gen-src/ast_quoter.ml CAMLDEP gen-src/ast_denoter.ml CAMLDEP gen-src/ast0.ml CAMLDEP gen-src/ascii.ml CAMLDEP gen-src/all_Forall.ml CAMLC -c gen-src/datatypes.mli CAMLC -c gen-src/basics.mli gen-src/basics.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11244 ko) CAMLC -c gen-src/binNums.mli gen-src/datatypes.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 12948 ko) CAMLC -c gen-src/mCPrelude.mli gen-src/binNums.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11340 ko) CAMLC -c gen-src/mCRelations.mli gen-src/mCPrelude.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11228 ko) CAMLC -c gen-src/mCProd.mli gen-src/mCRelations.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11080 ko) CAMLC -c gen-src/config0.mli gen-src/mCProd.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11620 ko) CAMLC -c gen-src/logic0.mli gen-src/config0.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11112 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/tm_util.ml gen-src/logic0.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11524 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/reification.ml gen-src/reification.cmx (real: 0.02, user: 0.01, sys: 0.00, mem: 14848 ko) CAMLC -c gen-src/plugin_core.mli gen-src/plugin_core.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 17156 ko) CAMLC -c gen-src/tm_util.ml gen-src/tm_util.cmo (real: 0.03, user: 0.02, sys: 0.01, mem: 18388 ko) CAMLC -c gen-src/reification.ml gen-src/reification.cmo (real: 0.01, user: 0.00, sys: 0.00, mem: 11740 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/datatypes.ml gen-src/datatypes.cmx (real: 0.15, user: 0.01, sys: 0.01, mem: 16200 ko) gen-src/tm_util.cmx (real: 0.26, user: 0.03, sys: 0.02, mem: 22128 ko) CAMLC -c gen-src/bool.mli CAMLC -c gen-src/decimal.mli gen-src/decimal.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 12404 ko) gen-src/bool.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11744 ko) CAMLC -c gen-src/specif.mli CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/basics.ml gen-src/specif.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13160 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/binNums.ml ggeenn--ssrrcc//bbaisniNcusm.sc.mcxm x( r(eraela:l : 0.040.05,, uusseerr:: 0.010.00,, ssyyss:: 0.010.01,, mmeemm:: 1566414584 kkoo)) CAMLC -c gen-src/cRelationClasses.mli CAMLC -c gen-src/compare_dec.mli gen-src/compare_dec.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11720 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCPrelude.ml gen-src/cRelationClasses.cmi (real: 0.01, user: 0.01, sys: 0.00, mem: 13388 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCRelations.ml gen-src/mCPrelude.cmx (real: 0.04, user: 0.00, sys: 0.01, mem: 14368 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCProd.ml gen-src/mCRelations.cmx (real: 0.09, user: 0.00, sys: 0.01, mem: 14184 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/config0.ml gen-src/mCProd.cmx (real: 0.07, user: 0.01, sys: 0.01, mem: 15708 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/logic0.ml gen-src/logic0.cmx (real: 0.02, user: 0.00, sys: 0.01, mem: 15516 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/quoter.ml gen-src/config0.cmx (real: 0.09, user: 0.00, sys: 0.01, mem: 14648 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/denoter.ml gen-src/denoter.cmx (real: 0.07, user: 0.05, sys: 0.01, mem: 24396 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/plugin_core.ml gen-src/quoter.cmx (real: 0.17, user: 0.14, sys: 0.02, mem: 34476 ko) CAMLC -c gen-src/quoter.ml gen-src/plugin_core.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 27344 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/bool.ml gen-src/bool.cmx (real: 0.02, user: 0.01, sys: 0.01, mem: 15772 ko) CAMLC -c gen-src/equalities.mli gen-src/equalities.cmi (real: 0.04, user: 0.00, sys: 0.00, mem: 13240 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/decimal.ml gen-src/quoter.cmo (real: 0.16, user: 0.08, sys: 0.01, mem: 26408 ko) CAMLC -c gen-src/hexadecimal.mli gen-src/hexadecimal.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13064 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/specif.ml gen-src/decimal.cmx (real: 0.24, user: 0.03, sys: 0.01, mem: 17936 ko) gen-src/specif.cmx (real: 0.17, user: 0.02, sys: 0.01, mem: 16332 ko) CAMLC -c gen-src/orders.mli CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/cRelationClasses.ml gen-src/orders.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 13748 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/compare_dec.ml gen-src/cRelationClasses.cmx (real: 0.04, user: 0.02, sys: 0.01, mem: 16836 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/equalities.ml gen-src/compare_dec.cmx (real: 0.03, user: 0.01, sys: 0.01, mem: 15536 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/hexadecimal.ml gen-src/equalities.cmx (real: 0.03, user: 0.01, sys: 0.01, mem: 15840 ko) CAMLC -c gen-src/numeral.mli gen-src/numeral.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11900 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/orders.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/orders.cmx (real: 0.04, user: 0.01, sys: 0.01, mem: 16768 ko) CAMLC -c gen-src/ordersTac.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersTac.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 12464 ko) CAMLC -c gen-src/ordersLists.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersLists.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11760 ko) CAMLC -c gen-src/orderedType0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/orderedType0.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 12108 ko) gen-src/hexadecimal.cmx (real: 0.13, user: 0.09, sys: 0.02, mem: 20020 ko) CAMLC -c gen-src/nat0.mli CAMLC -c gen-src/peanoNat.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/peanoNat.cmi (real: 0.01, user: 0.01, sys:g e0.00n,- smrecm/:n at133640 .kco)m i (real: 0.02, user: 0.01, sys: 0.00, mem: 13460 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ordersTac.ml CAMLC -c gen-src/ordersFacts.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersFacts.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 13444 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ordersLists.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersLists.cmx (real: 0.20, user: 0.00, sys: 0.01, mem: 15096 ko) CAMLC -c gen-src/mSetInterface.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetInterface.cmi (real: 0.02, user: 0.02, sys: 0.00, mem: 15244 ko) CAMLC -c gen-src/mCCompare.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCCompare.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11644 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/numeral.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersTac.cmx (real: 0.27, user: 0.01, sys: 0.01, mem: 15844 ko) CAMLC -c gen-src/list0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/list0.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 13404 ko) CAMLC -c gen-src/binPosDef.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/numeral.cmx (real: 0.04, user: 0.00, sys: 0.01, mem: 15820 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ordersFacts.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binPosDef.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 13536 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/orderedType0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ordersFacts.cmx (real: 0.02, user: 0.01, sys: 0.01, mem: 16032 ko) CAMLC -c gen-src/mSetFacts.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetFacts.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 13748 ko) CAMLC -c gen-src/mSetList.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetList.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 15760 ko) CAMLC -c gen-src/mCList.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/orderedType0.cmx (real: 0.07, user: 0.01, sys: 0.01, mem: 15860 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/nat0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCList.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 13612 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/peanoNat.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/nat0.cmx (real: 0.21, user: 0.04, sys: 0.01, mem: 18464 ko) CAMLC -c gen-src/binPos.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binPos.cmi (real: 0.01, user: 0.01, sys: 0.00, mem: 14264 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mSetInterface.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/peanoNat.cmx (real: 0.26, user: 0.07, sys: 0.02, mem: 19912 ko) CAMLC -c gen-src/mSetDecide.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetDecide.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13776 ko) CAMLC -c gen-src/mCOption.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCOption.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 12200 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCCompare.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetInterface.cmx (real: 0.11, user: 0.05, sys: 0.02, mem: 20324 ko) CAMLC -c gen-src/all_Forall.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/all_Forall.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 14992 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/list0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCCompare.cmx (real: 0.08, user: 0.01, sys: 0.01, mem: 15672 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/binPosDef.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/list0.cmx (real: 0.04, user: 0.03, sys: 0.01, mem: 17796 ko) CAMLC -c gen-src/binNat.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binNat.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13444 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mSetFacts.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetFacts.cmx (real: 0.12, user: 0.01, sys: 0.01, mem: 17012 ko) gen-src/binPosDef.cmx (real: 0.18, user: 0.13, sys: 0.03, mem: 23892 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mSetList.ml CAMLC -c gen-src/mSetProperties.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetProperties.cmi (real: 0.07, user: 0.02, sys: 0.00, mem: 15212 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCList.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetList.cmx (real: 0.28, user: 0.08, sys: 0.02, mem: 21352 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/binPos.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCList.cmx (real: 0.25, user: 0.01, sys: 0.01, mem: 16712 ko) CAMLC -c gen-src/binInt.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binInt.cmi (real: 0.02, user: 0.01, sys: 0.01, mem: 13564 ko) CAMLC -c gen-src/ascii.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ascii.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 12228 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mSetDecide.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binPos.cmx (real: 0.19, user: 0.15, sys: 0.03, mem: 25208 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCOption.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetDecide.cmx (real: 0.18g, euns-esrr:c /mC0.01O,p tsiyosn:. cm0.01x, (mreema:l : 17180 ko) 0.08, user: 0.01, sys: 0.01, mem: 16020 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/binNat.ml CAMLC -c gen-src/string0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/string0.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 12236 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mSetProperties.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mSetProperties.cmx (real: 0.10, user: 0.04, sys: 0.01, mem: 19600 ko) CAMLC -c gen-src/mCString.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binNat.cmx (real: 0.13, user: 0.10, sys: 0.02, mem: 20796 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/all_Forall.ml gen-src/mCString.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 11712 ko) findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/binInt.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/binInt.cmx (real: 0.32, user: 0.12, sys: 0.02, mem: 22784 ko) gen-src/all_Forall.cmx (real: 0.33, user: 0.14, sys: 0.02, mem: 25372 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ascii.ml CAMLC -c gen-src/basicAst.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/basicAst.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 14404 ko) CAMLC -c gen-src/universes0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ascii.cmx (real: 0.06, user: 0.02, sys: 0.01, mem: 16900 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/string0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/universes0.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 18504 ko) CAMLC -c gen-src/environment.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/string0.cmx (real: 0.04, user: 0.02, sys: 0.01, mem: 16504 ko) CAMLC -c gen-src/ast0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/environment.cmi (real: 0.02, user: 0.01, sys: 0.01, mem: 14988 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/mCString.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast0.cmi (real: 0.03, user: 0.01, sys: 0.01, mem: 15204 ko) CAMLC -c gen-src/astUtils.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/astUtils.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 14040 ko) CAMLC -c gen-src/liftSubst.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/liftSubst.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13680 ko) CAMLC -c gen-src/univSubst0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/univSubst0.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 14128 ko) CAMLC -c gen-src/pretty.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/pretty.cmi (real: 0.01, user: 0.00, sys: 0.01, mem: 15060 ko) CAMLC -c gen-src/common0.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/common0.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13492 ko) CAMLC -c gen-src/ast_quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_quoter.cmo (real: 0.06, user: 0.04, sys: 0.01, mem: 22660 ko) CAMLC -c gen-src/extractable.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/mCString.cmx (real: 0.24, user: 0.02, sys: 0.01, mem: 16472 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/basicAst.ml gen-src/extractable.cmi (real: 0.07, user: 0.00, sys: 0.00, mem: 13580 ko) CAMLC -c gen-src/run_extractable.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmi (real: 0.01, user: 0.00, sys: 0.00, mem: 13668 ko) gen-src/basicAst.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 18744 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/universes0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/universes0.cmx (real: 0.59, user: 0.41, sys: 0.03, mem: 39160 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/environment.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/environment.cmx (real: 0.16, user: 0.03, sys: 0.01, mem: 19716 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast0.cmx (real: 0.25, user: 0.09, sys: 0.02, mem: 24572 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/astUtils.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/liftSubst.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/astUtils.cmx (real: 0.05, user: 0.04, sys: 0.01, mem: 19608 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/univSubst0.ml gen-src/liftSubst.cmx (real: 0.06, user: 0.04, sys: 0.01, mem: 19008 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/common0.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/common0.cmx (real: 0.05, user: 0.02, sys: 0.01, mem: 16420 ko) gen-src/univSubst0.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 18548 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_quoter.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/pretty.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/pretty.cmx (real: 0.11, user: 0.08, sys: 0.01, mem: 22020 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/extractable.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/extractable.cmx (real: 0.08, user: 0.04, sys: 0.01, mem: 18780 ko) gen-src/ast_quoter.cmx (real: 0.20, user: 0.10, sys: 0.02, mem: 27252 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_denoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_denoter.cmx (real: 0.12, user: 0.07, sys: 0.02, mem: 27180 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/run_extractable.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmx (real: 0.13, user: 0.10, sys: 0.02, mem: 30484 ko) CAMLOPT -pack -o gen-src/metacoq_template_plugin.cmx findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmx (real: 0.15, user: 0.09, sys: 0.04, mem: 31648 ko) CAMLOPT -a -o gen-src/metacoq_template_plugin.cmxa findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxa (real: 0.03, user: 0.01, sys: 0.02, mem: 13896 ko) CAMLOPT -shared -o gen-src/metacoq_template_plugin.cmxs findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxs (real: 0.13, user: 0.09, sys: 0.03, mem: 18540 ko) ROCQ compile theories/ExtractableLoader.v theories/ExtractableLoader.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 62540 ko) cp gen-src/metacoq_template_plugin.cm* build/ make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -C checker make -C pcuic make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' cat metacoq-config > _CoqProject make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' cat metacoq-config > _CoqProject cat _CoqProject.in >> _CoqProject cat _CoqProject.in >> _CoqProject rocq makefile -f _CoqProject -o Makefile.pcuic rocq makefile -f _CoqProject -o Makefile.coq Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.coq Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.pcuic make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' ROCQ DEP VFILES ROCQ DEP VFILES ROCQ compile theories/Reflect.v ROCQ compile theories/PCUICAst.v theories/PCUICAst.vo (real: 0.99, user: 0.75, sys: 0.23, mem: 477372 ko) ROCQ compile theories/PCUICSize.v theories/PCUICSize.vo (real: 1.73, user: 1.44, sys: 0.28, mem: 503484 ko) ROCQ compile theories/PCUICInduction.v theories/PCUICInduction.vo (real: 1.19, user: 0.89, sys: 0.29, mem: 481312 ko) ROCQ compile theories/PCUICCheckerCompleteness.v theories/PCUICCheckerCompleteness.vo (real: 0.85, user: 0.60, sys: 0.24, mem: 433064 ko) ROCQ compile theories/TemplateToPCUIC.v theories/Reflect.vo (real: 5.26, user: 4.53, sys: 0.70, mem: 552364 ko) ROCQ compile theories/WeakeningEnv.v theories/TemplateToPCUIC.vo (real: 0.98, user: 0.69, sys: 0.27, mem: 482472 ko) ROCQ compile theories/PCUICAstUtils.v theories/WeakeningEnv.vo (real: 3.33, user: 2.80, sys: 0.50, mem: 512292 ko) ROCQ compile theories/Checker.v theories/PCUICAstUtils.vo (real: 3.13, user: 2.78, sys: 0.32, mem: 543424 ko) ROCQ compile theories/PCUICReflect.v theories/Checker.vo (real: 4.71, user: 4.00, sys: 0.69, mem: 555748 ko) ROCQ compile theories/WcbvEval.v theories/PCUICReflect.vo (real: 4.46, user: 4.11, sys: 0.32, mem: 543956 ko) ROCQ compile theories/PCUICLiftSubst.v theories/WcbvEval.vo (real: 5.56, user: 4.94, sys: 0.59, mem: 533768 ko) ROCQ compile theories/Retyping.v theories/Retyping.vo (real: 1.16, user: 0.90, sys: 0.26, mem: 524140 ko) ROCQ compile theories/Normal.v theories/Normal.vo (real: 1.10, user: 0.84, sys: 0.25, mem: 497360 ko) ROCQ compile theories/Generation.v theories/Generation.vo (real: 1.95, user: 1.69, sys: 0.25, mem: 514692 ko) ROCQ compile theories/Closed.v File "./theories/Closed.v", line 299, characters 2-42: Warning: Automatically inlined signature for type All_local_env. Use [Derive Signature for All_local_env.] to avoid this. theories/PCUICLiftSubst.vo (real: 27.51, user: 26.28, sys: 0.94, mem: 597996 ko) ROCQ compile theories/PCUICToTemplate.v theories/PCUICToTemplate.vo (real: 1.33, user: 1.04, sys: 0.28, mem: 527408 ko) ROCQ compile theories/PCUICUtils.v theories/PCUICUtils.vo (real: 1.81, user: 1.47, sys: 0.33, mem: 527440 ko) ROCQ compile theories/PCUICUnivSubst.v theories/Closed.vo (real: 22.03, user: 21.55, sys: 0.36, mem: 603616 ko) ROCQ compile theories/Weakening.v theories/PCUICUnivSubst.vo (real: 3.67, user: 3.33, sys: 0.32, mem: 533884 ko) ROCQ compile theories/PCUICEquality.v theories/Weakening.vo (real: 16.17, user: 15.64, sys: 0.43, mem: 579100 ko) ROCQ compile theories/Substitution.v theories/PCUICEquality.vo (real: 40.79, user: 39.04, sys: 1.52, mem: 790088 ko) ROCQ compile theories/PCUICPosition.v theories/Substitution.vo (real: 29.09, user: 27.93, sys: 0.98, mem: 621392 ko) ROCQ compile theories/All.v theories/All.vo (real: 1.65, user: 1.29, sys: 0.34, mem: 545736 ko) ./update_plugin.sh Renaming extracted files make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make -C examples make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/examples' rocq makefile -f _CoqProject -o Makefile.coq Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.coq pretty-timed make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/examples' ROCQ DEP VFILES ROCQ compile demo.v demo.vo (real: 1.94, user: 1.56, sys: 0.36, mem: 527740 ko) ROCQ compile add_constructor.v add_constructor.vo (real: 1.44, user: 1.13, sys: 0.30, mem: 524144 ko) ROCQ compile tauto.v tauto.vo (real: 20.77, user: 19.93, sys: 0.72, mem: 581920 ko) Time | Peak Mem | File Name -------------------------------------------- 0m22.62s | 581920 ko | Total Time / Peak Mem -------------------------------------------- 0m19.93s | 581920 ko | tauto.vo 0m01.56s | 527740 ko | demo.vo 0m01.13s | 524144 ko | add_constructor.vo make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/examples' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/examples' theories/PCUICPosition.vo (real: 29.43, user: 28.24, sys: 1.03, mem: 723216 ko) ROCQ compile theories/PCUICTyping.v Axioms: ind_guard : mutual_inductive_body -> bool fix_guard : mfixpoint term -> bool cofix_guard : mfixpoint term -> bool theories/PCUICTyping.vo (real: 44.26, user: 42.82, sys: 1.17, mem: 727688 ko) ROCQ compile theories/PCUICReduction.v ROCQ compile theories/PCUICWeakeningEnv.v theories/PCUICWeakeningEnv.vo (real: 5.17, user: 4.38, sys: 0.74, mem: 571076 ko) ROCQ compile theories/PCUICGeneration.v theories/PCUICReduction.vo (real: 6.98, user: 6.16, sys: 0.78, mem: 583116 ko) ROCQ compile theories/PCUICNormal.v theories/PCUICNormal.vo (real: 1.72, user: 1.37, sys: 0.33, mem: 551200 ko) ROCQ compile theories/PCUICNameless.v theories/PCUICGeneration.vo (real: 3.72, user: 3.34, sys: 0.36, mem: 586388 ko) ROCQ compile theories/PCUICMetaTheory.v theories/PCUICMetaTheory.vo (real: 1.26, user: 0.96, sys: 0.29, mem: 546928 ko) ROCQ compile theories/PCUICChecker.v theories/PCUICChecker.vo (real: 1.41, user: 1.11, sys: 0.29, mem: 549776 ko) ROCQ compile theories/PCUICToTemplateCorrectness.v theories/PCUICToTemplateCorrectness.vo (real: 8.69, user: 7.84, sys: 0.79, mem: 608576 ko) ROCQ compile theories/PCUICCumulativity.v theories/PCUICCumulativity.vo (real: 2.17, user: 1.85, sys: 0.30, mem: 561876 ko) ROCQ compile theories/PCUICClosed.v theories/PCUICNameless.vo (real: 15.98, user: 14.98, sys: 0.89, mem: 623196 ko) ROCQ compile theories/PCUICPretty.v theories/PCUICPretty.vo (real: 1.64, user: 1.30, sys: 0.33, mem: 551364 ko) theories/PCUICClosed.vo (real: 24.65, user: 23.99, sys: 0.51, mem: 654592 ko) ROCQ compile theories/PCUICWeakening.v ROCQ compile theories/PCUICCSubst.v theories/PCUICCSubst.vo (real: 1.93, user: 1.55, sys: 0.36, mem: 562424 ko) ROCQ compile theories/PCUICWcbvEval.v theories/PCUICWcbvEval.vo (real: 12.05, user: 11.54, sys: 0.43, mem: 589944 ko) theories/PCUICWeakening.vo (real: 24.20, user: 23.42, sys: 0.64, mem: 685852 ko) ROCQ compile theories/PCUICSigmaCalculus.v ROCQ compile theories/PCUICUnivSubstitution.v theories/PCUICUnivSubstitution.vo (real: 10.93, user: 10.41, sys: 0.45, mem: 621644 ko) theories/PCUICSigmaCalculus.vo (real: 39.32, user: 38.12, sys: 0.96, mem: 657100 ko) ROCQ compile theories/PCUICSubstitution.v theories/PCUICSubstitution.vo (real: 26.54, user: 25.65, sys: 0.68, mem: 673140 ko) ROCQ compile theories/PCUICParallelReduction.v ROCQ compile theories/TemplateToPCUICCorrectness.v theories/TemplateToPCUICCorrectness.vo (real: 13.77, user: 13.16, sys: 0.52, mem: 641024 ko) theories/PCUICParallelReduction.vo (real: 29.43, user: 28.26, sys: 0.87, mem: 779308 ko) ROCQ compile theories/PCUICParallelReductionConfluence.v Axioms: ind_guard : mutual_inductive_body β†’ bool FunctionalExtensionality.functional_extensionality_dep : βˆ€ (A : Type) (B : A β†’ Type) (f g : βˆ€ x : A, B x), (βˆ€ x : A, f x = g x) β†’ f = g fix_guard : mfixpoint term β†’ bool cofix_guard : mfixpoint term β†’ bool theories/PCUICParallelReductionConfluence.vo (real: 96.83, user: 94.58, sys: 1.69, mem: 849824 ko) ROCQ compile theories/PCUICConfluence.v theories/PCUICConfluence.vo (real: 35.96, user: 34.44, sys: 1.27, mem: 742788 ko) ROCQ compile theories/PCUICContextConversion.v theories/PCUICContextConversion.vo (real: 9.28, user: 8.74, sys: 0.48, mem: 629108 ko) ROCQ compile theories/PCUICConversion.v File "./theories/PCUICConversion.v", line 2097, characters 4-13: Warning: Automatically inlined signature for type clos_refl_trans_1n. Use [Derive Signature for clos_refl_trans_1n.] to avoid this. File "./theories/PCUICConversion.v", line 2234, characters 4-37: Warning: Cannot remove s'. [cannot-remove-as-expected,tactics] theories/PCUICConversion.vo (real: 30.61, user: 29.65, sys: 0.79, mem: 750296 ko) ROCQ compile theories/PCUICInversion.v ROCQ compile theories/PCUICRetyping.v theories/PCUICRetyping.vo (real: 1.94, user: 1.58, sys: 0.34, mem: 589768 ko) theories/PCUICInversion.vo (real: 10.19, user: 9.35, sys: 0.77, mem: 622488 ko) ROCQ compile theories/PCUICCtxShape.v theories/PCUICCtxShape.vo (real: 2.23, user: 1.75, sys: 0.38, mem: 598288 ko) ROCQ compile theories/PCUICContexts.v theories/PCUICContexts.vo (real: 6.83, user: 6.33, sys: 0.45, mem: 615568 ko) ROCQ compile theories/PCUICArities.v theories/PCUICArities.vo (real: 8.61, user: 7.75, sys: 0.80, mem: 625664 ko) ROCQ compile theories/PCUICSpine.v theories/PCUICSpine.vo (real: 23.61, user: 22.85, sys: 0.63, mem: 706592 ko) ROCQ compile theories/PCUICInductives.v theories/PCUICInductives.vo (real: 19.89, user: 19.08, sys: 0.66, mem: 683776 ko) ROCQ compile theories/PCUICValidity.v theories/PCUICValidity.vo (real: 4.40, user: 3.99, sys: 0.36, mem: 624912 ko) ROCQ compile theories/PCUICAlpha.v ROCQ compile theories/PCUICInductiveInversion.v theories/PCUICAlpha.vo (real: 10.12, user: 9.58, sys: 0.47, mem: 684644 ko) theories/PCUICInductiveInversion.vo (real: 10.95, user: 10.39, sys: 0.48, mem: 661964 ko) ROCQ compile theories/PCUICSR.v Axioms: todounivs : forall A : Type, A todoeta : forall A : Type, A ind_guard : mutual_inductive_body -> bool FunctionalExtensionality.functional_extensionality_dep : forall (A : Type) (B : A -> Type) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g fix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), fix_guard mfix -> fix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) fix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (subst s k) (subst s k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> red1 Ξ£ Ξ“ (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (lift n k) (lift n k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard : mfixpoint term -> bool cofix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), cofix_guard mfix -> cofix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) cofix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (subst s k) (subst s k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> red1 Ξ£ Ξ“ (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (lift n k) (lift n k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard : mfixpoint term -> bool theories/PCUICSR.vo (real: 82.63, user: 80.36, sys: 1.84, mem: 975764 ko) ROCQ compile theories/PCUICPrincipality.v Axioms: todounivs : forall A : Type@{todounivs.u0}, A todoeta : forall A : Type@{todoeta.u0}, A ind_guard : mutual_inductive_body -> bool FunctionalExtensionality.functional_extensionality_dep : forall (A : Type@{FunctionalExtensionality.functional_extensionality_dep.u0}) (B : A -> Type@{FunctionalExtensionality.functional_extensionality_dep.u1}) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g PCUICUnivSubstitution.fix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), fix_guard mfix -> fix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) fix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (subst s k) (subst s k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> red1 Ξ£ Ξ“ (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (lift n k) (lift n k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> tFix mfix idx ≑ tFix mfix' idx -> fix_guard mfix' fix_guard : mfixpoint term -> bool PCUICUnivSubstitution.cofix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), cofix_guard mfix -> cofix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) cofix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (subst s k) (subst s k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> red1 Ξ£ Ξ“ (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (lift n k) (lift n k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> tCoFix mfix idx ≑ tCoFix mfix' idx -> cofix_guard mfix' cofix_guard : mfixpoint term -> bool theories/PCUICPrincipality.vo (real: 27.66, user: 26.11, sys: 1.08, mem: 959132 ko) ROCQ compile theories/PCUICSafeLemmata.v theories/PCUICSafeLemmata.vo (real: 7.45, user: 6.54, sys: 0.85, mem: 667924 ko) ROCQ compile theories/PCUICSN.v ROCQ compile theories/PCUICElimination.v theories/PCUICSN.vo (real: 2.47, user: 2.12, sys: 0.33, mem: 630488 ko) theories/PCUICElimination.vo (real: 8.12, user: 7.64, sys: 0.44, mem: 646256 ko) # echo "All done, moving extraction files!" # ./clean_extraction.sh make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -C safechecker make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' cat metacoq-config > _CoqProject cat _CoqProject.in >> _CoqProject rocq makefile -f _CoqProject -o Makefile.safechecker Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.safechecker make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' ROCQ DEP VFILES ROCQ compile theories/PCUICSafeReduce.v theories/PCUICSafeReduce.vo (real: 121.19, user: 119.92, sys: 0.74, mem: 1136588 ko) ROCQ compile theories/PCUICSafeConversion.v theories/PCUICSafeConversion.vo (real: 140.66, user: 139.40, sys: 0.64, mem: 1007764 ko) ROCQ compile theories/PCUICSafeChecker.v File "./theories/PCUICSafeChecker.v", line 1035, characters 4-15: Warning: Automatically inlined signature for type Forall. Use [Derive Signature for Forall.] to avoid this. File "./theories/PCUICSafeChecker.v", line 1039, characters 4-19: Warning: Automatically inlined signature for type Forall. Use [Derive Signature for Forall.] to avoid this. Axioms: todounivs : forall A : Type, A todoeta : forall A : Type, A todo : string -> forall A : Type, A proof_irrelevance : forall (P : Prop) (p1 p2 : P), p1 = p2 normalisation' : forall (cf : checker_flags) (Ξ£ : global_env_ext) (Ξ“ : context) (t : term), wf Ξ£ -> wellformed Ξ£ Ξ“ t -> Acc (cored Ξ£.1 Ξ“) t ind_guard : mutual_inductive_body -> bool functional_extensionality_dep : forall (A : Type) (B : A -> Type) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g PCUICUnivSubstitution.fix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), fix_guard mfix -> fix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) fix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (subst s k) (subst s k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> red1 Ξ£ Ξ“ (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (lift n k) (lift n k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> tFix mfix idx ≑ tFix mfix' idx -> fix_guard mfix' fix_guard : mfixpoint term -> bool PCUICUnivSubstitution.cofix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), cofix_guard mfix -> cofix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) cofix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (subst s k) (subst s k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> red1 Ξ£ Ξ“ (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (lift n k) (lift n k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> tCoFix mfix idx ≑ tCoFix mfix' idx -> cofix_guard mfix' cofix_guard : mfixpoint term -> bool theories/PCUICSafeChecker.vo (real: 56.94, user: 56.09, sys: 0.61, mem: 958816 ko) ROCQ compile theories/SafeTemplateChecker.v ROCQ compile theories/PCUICSafeRetyping.v theories/SafeTemplateChecker.vo (real: 2.78, user: 2.42, sys: 0.35, mem: 703592 ko) ROCQ compile theories/Extraction.v theories/PCUICSafeRetyping.vo (real: 6.81, user: 6.30, sys: 0.48, mem: 733700 ko) theories/Extraction.vo (real: 4.93, user: 4.47, sys: 0.43, mem: 749140 ko) echo "Done extracting the safe checker, moving extraction files!" Done extracting the safe checker, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Moving All_Forall.ml to all_Forall.ml Moving All_Forall.mli to all_Forall.mli Moving Ascii.ml to ascii.ml Moving Ascii.mli to ascii.mli Moving Ast0.ml to ast0.ml Moving Ast0.mli to ast0.mli Moving BasicAst.ml to basicAst.ml Moving BasicAst.mli to basicAst.mli Moving Basics.ml to basics.ml Moving Basics.mli to basics.mli Moving BinInt.ml to binInt.ml Moving BinInt.mli to binInt.mli Moving BinNat.ml to binNat.ml Moving BinNat.mli to binNat.mli Moving BinNums.ml to binNums.ml Moving BinNums.mli to binNums.mli Moving BinPos.ml to binPos.ml Moving BinPos.mli to binPos.mli Moving Bool.ml to bool.ml Moving Bool.mli to bool.mli Moving Byte.ml to byte.ml Moving Byte.mli to byte.mli Moving Classes0.ml to classes0.ml Moving Classes0.mli to classes0.mli Moving Compare_dec.ml to compare_dec.ml Moving Compare_dec.mli to compare_dec.mli Moving Datatypes.ml to datatypes.ml Moving Datatypes.mli to datatypes.mli Moving Environment.ml to environment.ml Moving Environment.mli to environment.mli Moving EqDecInstances.ml to eqDecInstances.ml Moving EqDecInstances.mli to eqDecInstances.mli Moving EqdepFacts.ml to eqdepFacts.ml Moving EqdepFacts.mli to eqdepFacts.mli Moving Equalities.ml to equalities.ml Moving Equalities.mli to equalities.mli Moving List0.ml to list0.ml Moving List0.mli to list0.mli Moving MCCompare.ml to mCCompare.ml Moving MCCompare.mli to mCCompare.mli Moving MCList.ml to mCList.ml Moving MCList.mli to mCList.mli Moving MCOption.ml to mCOption.ml Moving MCOption.mli to mCOption.mli Moving MCProd.ml to mCProd.ml Moving MCProd.mli to mCProd.mli Moving MCString.ml to mCString.ml Moving MCString.mli to mCString.mli Moving MSetDecide.ml to mSetDecide.ml Moving MSetDecide.mli to mSetDecide.mli Moving MSetFacts.ml to mSetFacts.ml Moving MSetFacts.mli to mSetFacts.mli Moving MSetInterface.ml to mSetInterface.ml Moving MSetInterface.mli to mSetInterface.mli Moving MSetList.ml to mSetList.ml Moving MSetList.mli to mSetList.mli Moving MSetProperties.ml to mSetProperties.ml Moving MSetProperties.mli to mSetProperties.mli Moving MSetWeakList.ml to mSetWeakList.ml Moving MSetWeakList.mli to mSetWeakList.mli Moving Nat0.ml to nat0.ml Moving Nat0.mli to nat0.mli Moving Orders.ml to orders.ml Moving Orders.mli to orders.mli Moving OrdersFacts.ml to ordersFacts.ml Moving OrdersFacts.mli to ordersFacts.mli Moving OrdersLists.ml to ordersLists.ml Moving OrdersLists.mli to ordersLists.mli Moving OrdersTac.ml to ordersTac.ml Moving OrdersTac.mli to ordersTac.mli Moving PCUICAst.ml to pCUICAst.ml Moving PCUICAst.mli to pCUICAst.mli Moving PCUICAstUtils.ml to pCUICAstUtils.ml Moving PCUICAstUtils.mli to pCUICAstUtils.mli Moving PCUICChecker.ml to pCUICChecker.ml Moving PCUICChecker.mli to pCUICChecker.mli Moving PCUICCumulativity.ml to pCUICCumulativity.ml Moving PCUICCumulativity.mli to pCUICCumulativity.mli Moving PCUICEquality.ml to pCUICEquality.ml Moving PCUICEquality.mli to pCUICEquality.mli Moving PCUICLiftSubst.ml to pCUICLiftSubst.ml Moving PCUICLiftSubst.mli to pCUICLiftSubst.mli Moving PCUICNormal.ml to pCUICNormal.ml Moving PCUICNormal.mli to pCUICNormal.mli Moving PCUICPosition.ml to pCUICPosition.ml Moving PCUICPosition.mli to pCUICPosition.mli Moving PCUICPretty.ml to pCUICPretty.ml Moving PCUICPretty.mli to pCUICPretty.mli Moving PCUICReflect.ml to pCUICReflect.ml Moving PCUICReflect.mli to pCUICReflect.mli Moving PCUICSafeChecker.ml to pCUICSafeChecker.ml Moving PCUICSafeChecker.mli to pCUICSafeChecker.mli Moving PCUICSafeConversion.ml to pCUICSafeConversion.ml Moving PCUICSafeConversion.mli to pCUICSafeConversion.mli Moving PCUICSafeLemmata.ml to pCUICSafeLemmata.ml Moving PCUICSafeLemmata.mli to pCUICSafeLemmata.mli Moving PCUICSafeReduce.ml to pCUICSafeReduce.ml Moving PCUICSafeReduce.mli to pCUICSafeReduce.mli Moving PCUICTyping.ml to pCUICTyping.ml Moving PCUICTyping.mli to pCUICTyping.mli Moving PCUICUnivSubst.ml to pCUICUnivSubst.ml Moving PCUICUnivSubst.mli to pCUICUnivSubst.mli Moving PeanoNat.ml to peanoNat.ml Moving PeanoNat.mli to peanoNat.mli Moving SafeTemplateChecker.ml to safeTemplateChecker.ml Moving SafeTemplateChecker.mli to safeTemplateChecker.mli Moving Specif.ml to specif.ml Moving Specif.mli to specif.mli Moving String0.ml to string0.ml Moving String0.mli to string0.mli Moving TemplateToPCUIC.ml to templateToPCUIC.ml Moving TemplateToPCUIC.mli to templateToPCUIC.mli Moving Typing0.ml to typing0.ml Moving Typing0.mli to typing0.mli Moving UnivSubst0.ml to univSubst0.ml Moving UnivSubst0.mli to univSubst0.mli Moving Universes0.ml to universes0.ml Moving Universes0.mli to universes0.mli Moving config0.ml to config0.ml mv: 'config0.ml' and 'config0.ml' are the same file Moving config0.mli to config0.mli mv: 'config0.mli' and 'config0.mli' are the same file Moving g_metacoq_safechecker.ml to g_metacoq_safechecker.ml mv: 'g_metacoq_safechecker.ml' and 'g_metacoq_safechecker.ml' are the same file Moving g_metacoq_safechecker.mlg to g_metacoq_safechecker.mlg mv: 'g_metacoq_safechecker.mlg' and 'g_metacoq_safechecker.mlg' are the same file Moving metacoq_safechecker_plugin.mlpack to metacoq_safechecker_plugin.mlpack mv: 'metacoq_safechecker_plugin.mlpack' and 'metacoq_safechecker_plugin.mlpack' are the same file Moving monad_utils.ml to monad_utils.ml mv: 'monad_utils.ml' and 'monad_utils.ml' are the same file Moving monad_utils.mli to monad_utils.mli mv: 'monad_utils.mli' and 'monad_utils.mli' are the same file Moving ssrbool.ml to ssrbool.ml mv: 'ssrbool.ml' and 'ssrbool.ml' are the same file Moving ssrbool.mli to ssrbool.mli mv: 'ssrbool.mli' and 'ssrbool.mli' are the same file Moving uGraph0.ml to uGraph0.ml mv: 'uGraph0.ml' and 'uGraph0.ml' are the same file Moving uGraph0.mli to uGraph0.mli mv: 'uGraph0.mli' and 'uGraph0.mli' are the same file Moving utils.ml to utils.ml mv: 'utils.ml' and 'utils.ml' are the same file Moving utils.mli to utils.mli mv: 'utils.mli' and 'utils.mli' are the same file Moving wGraph.ml to wGraph.ml mv: 'wGraph.ml' and 'wGraph.ml' are the same file Moving wGraph.mli to wGraph.mli mv: 'wGraph.mli' and 'wGraph.mli' are the same file Removing: src/all_Forall.ml src/all_Forall.mli src/ascii.ml src/ascii.mli src/ast0.ml src/ast0.mli src/ast_denoter.ml src/ast_quoter.ml src/astUtils.ml src/astUtils.mli src/basicAst.ml src/basicAst.mli src/basics.ml src/basics.mli src/binInt.ml src/binInt.mli src/binNat.ml src/binNat.mli src/binNums.ml src/binNums.mli src/binPosDef.ml src/binPosDef.mli src/binPos.ml src/binPos.mli src/bool.ml src/bool.mli src/common0.ml src/common0.mli src/compare_dec.ml src/compare_dec.mli src/config0.ml src/config0.mli src/cRelationClasses.ml src/cRelationClasses.mli src/datatypes.ml src/datatypes.mli src/decimal.ml src/decimal.mli src/denoter.ml src/environment.ml src/environment.mli src/equalities.ml src/equalities.mli src/extractable.ml src/extractable.mli src/hexadecimal.ml src/hexadecimal.mli src/liftSubst.ml src/liftSubst.mli src/list0.ml src/list0.mli src/logic0.ml src/logic0.mli src/mCPrelude.mli src/mCPrelude.ml src/mCCompare.ml src/mCCompare.mli src/mCList.ml src/mCList.mli src/mCOption.ml src/mCOption.mli src/mCProd.ml src/mCProd.mli src/mCRelations.ml src/mCRelations.mli src/mCString.ml src/mCString.mli src/mSetDecide.ml src/mSetDecide.mli src/mSetFacts.ml src/mSetFacts.mli src/mSetInterface.ml src/mSetInterface.mli src/mSetList.ml src/mSetList.mli src/mSetProperties.ml src/mSetProperties.mli src/nat0.ml src/nat0.mli src/numeral.ml src/numeral.mli src/orderedType0.ml src/orderedType0.mli src/ordersFacts.ml src/ordersFacts.mli src/ordersLists.ml src/ordersLists.mli src/orders.ml src/orders.mli src/ordersTac.ml src/ordersTac.mli src/peanoNat.ml src/peanoNat.mli src/plugin_core.ml src/plugin_core.mli src/pretty.ml src/pretty.mli src/reification.ml src/quoter.ml src/run_extractable.ml src/run_extractable.mli src/specif.ml src/specif.mli src/string0.ml src/string0.mli src/tm_util.ml src/universes0.ml src/universes0.mli src/univSubst0.ml src/univSubst0.mli make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.plugin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' ROCQ DEP VFILES CAMLDEP src/safeTemplateChecker.mli CAMLDEP src/pCUICSafeChecker.mli CAMLDEP src/pCUICSafeConversion.mli CAMLDEP src/pCUICSafeReduce.mli CAMLDEP src/pCUICPretty.mli CAMLDEP src/pCUICChecker.mli CAMLDEP src/templateToPCUIC.mli CAMLDEP src/pCUICSafeLemmata.mli CAMLDEP src/pCUICNormal.mli CAMLDEP src/pCUICCumulativity.mli CAMLDEP src/pCUICPosition.mli CAMLDEP src/pCUICUnivSubst.mli CAMLDEP src/pCUICTyping.mli CAMLDEP src/pCUICEquality.mli CAMLDEP src/pCUICReflect.mli CAMLDEP src/eqDecInstances.mli CAMLDEP src/pCUICLiftSubst.mli CAMLDEP src/pCUICAstUtils.mli CAMLDEP src/pCUICAst.mli CAMLDEP src/typing0.mli CAMLDEP src/wGraph.mli CAMLDEP src/uGraph0.mli CAMLDEP src/utils.mli CAMLDEP src/monad_utils.mli CAMLDEP src/ssrbool.mli CAMLDEP src/eqdepFacts.mli CAMLDEP src/mSetWeakList.mli CAMLDEP src/classes0.mli OCAMLLIBDEP src/metacoq_safechecker_plugin.mlpack CAMLDEP src/safeTemplateChecker.ml CAMLDEP src/pCUICSafeChecker.ml CAMLDEP src/pCUICSafeConversion.ml CAMLDEP src/pCUICSafeReduce.ml CAMLDEP src/pCUICPretty.ml CAMLDEP src/pCUICChecker.ml CAMLDEP src/templateToPCUIC.ml CAMLDEP src/pCUICSafeLemmata.ml CAMLDEP src/pCUICNormal.ml CAMLDEP src/pCUICPosition.ml CAMLDEP src/pCUICCumulativity.ml CAMLDEP src/pCUICUnivSubst.ml CAMLDEP src/pCUICTyping.ml CAMLDEP src/pCUICEquality.ml CAMLDEP src/pCUICReflect.ml CAMLDEP src/eqDecInstances.ml CAMLDEP src/pCUICLiftSubst.ml CAMLDEP src/pCUICAstUtils.ml CAMLDEP src/pCUICAst.ml CAMLDEP src/typing0.ml CAMLDEP src/wGraph.ml CAMLDEP src/uGraph0.ml CAMLDEP src/utils.ml CAMLDEP src/monad_utils.ml CAMLDEP src/ssrbool.ml CAMLDEP src/eqdepFacts.ml CAMLDEP src/classes0.ml CAMLDEP src/mSetWeakList.ml CAMLDEP src/g_metacoq_safechecker.ml CAMLC -c src/monad_utils.mli CAMLC -c src/mSetWeakList.mli src/monad_utils.cmi (real: 0.10, user: 0.03, sys: 0.01, mem: 19196 ko) CAMLC -c src/eqdepFacts.mli src/mSetWeakList.cmi (real: 0.10, user: 0.03, sys: 0.01, mem: 20008 ko) CAMLC -c src/utils.mli src/utils.cmi (real: src/eqdep0.04Fac,t s.ucsmie r(:re al:0.03 , sys: 0.01, mem: 19340 ko) 0.04, user: 0.03, sys: 0.01, mem: 19268 ko) CAMLC -c src/ssrbool.mli CAMLC -c src/typing0.mli src/typing0.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 20364 ko) CAMLC -c src/classes0.mli src/ssrbool.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 19332 ko) CAMLC -c src/pCUICAst.mli src/classes0.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 19328 ko) CAMLC -c src/pCUICNormal.mli src/pCUICAst.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 21440 ko) CAMLC -c src/pCUICCumulativity.mli src/pCUICNormal.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19372 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/monad_utils.ml src/pCUICCumulativity.cmi (real: 0.03, user: 0.02, sys: 0.01, mem: 19220 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/mSetWeakList.ml src/monad_utils.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 21960 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/eqdepFacts.ml src/mSetWeakList.cmx (real: 0.07, user: 0.05, sys: 0.01, mem: 25168 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/utils.ml src/eqdepFacts.cmx (real: 0.04, user: 0.02, sys: 0.02, mem: 22016 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/ssrbool.ml src/utils.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 22096 ko) CAMLC -c src/wGraph.mli src/ssrbool.cmx (real: 0.04, user: 0.02, sys: 0.01, mem: 22104 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/typing0.ml src/wGraph.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 22812 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/classes0.ml src/typing0.cmx (real: 0.07, user: 0.04, sys: 0.02, mem: 24164 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICAst.ml src/classes0.cmx (real: 0.04, user: 0.03, sys: 0.01, mem: 22056 ko) CAMLC -c src/pCUICAstUtils.mli src/pCUICAstUtils.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20292 ko) CAMLC -c src/pCUICUnivSubst.mli src/pCUICAst.cmx (real: 0.08, user: 0.05, sys: 0.02, mem: 26084 ko) CAMLC -c src/pCUICLiftSubst.mli src/pCUICUnivSubst.cmi (real: 0.04, user: 0.04, sys: 0.00, mem: 20452 ko) CAMLC -c src/eqDecInstances.mli src/pCUICLiftSubst.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 20432 ko) CAMLC -c src/pCUICReflect.mli src/eqDecInstances.cmi (real: 0.03, user: 0.02, sys: 0.01, mem: 19260 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICNormal.ml src/pCUICReflect.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 20232 ko) CAMLC -c src/pCUICPosition.mli src/pCUICNormal.cmx (real: 0.04, user: 0.03, sys: 0.01, mem: 22004 ko) CAMLC -c src/templateToPCUIC.mli src/pCUICPosition.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 20460 ko) CAMLC -c src/pCUICSafeLemmata.mli src/pCUICSafeLemmata.cmi (real: 0.03, user: 0.02, sys: 0.01, mem: 19172 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICCumulativity.ml src/templateToPCUIC.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 20348 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/wGraph.ml src/pCUICCumulativity.cmx (real: 0.04, user: 0.03, sys: 0.01, mem: 22036 ko) CAMLC -c src/uGraph0.mli src/uGraph0.cmi (real: 0.07, user: 0.05, sys: 0.01, mem: 24772 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICAstUtils.ml src/wGraph.cmx (real: 0.14, user: 0.12, sys: 0.02, mem: 31828 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICUnivSubst.ml src/pCUICAstUtils.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 25948 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICLiftSubst.ml src/pCUICUnivSubst.cmx (real: 0.06, user: 0.04, sys: 0.01, mem: 25096 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/eqDecInstances.ml src/eqDecInstances.cmx (real: 0.05, user: 0.03, sys: 0.02, mem: 22024 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICReflect.ml src/pCUICLiftSubst.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 26296 ko) CAMLC -c src/pCUICEquality.mli src/pCUICReflect.cmx (real: 0.06, user: 0.05, sys: 0.01, mem: 24360 ko) CAMLC -c src/pCUICTyping.mli src/pCUICEquality.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20432 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICPosition.ml src/pCUICTyping.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 21428 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/templateToPCUIC.ml src/pCUICPosition.cmx (real: 0.09, user: 0.07, sys: 0.01, mem: 26028 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICSafeLemmata.ml src/templateToPCUIC.cmx (real: 0.07, user: 0.06, sys: 0.01, mem: 25572 ko) CAMLC -c src/pCUICSafeReduce.mli src/pCUICSafeLemmata.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 22056 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/uGraph0.ml src/pCUICSafeReduce.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 21588 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICEquality.ml src/pCUICEquality.cmx (real: 0.07, user: 0.05, sys: 0.02, mem: 26416 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICTyping.ml src/uGraph0.cmx (real: 0.13, user: 0.11, sys: 0.02, mem: 30828 ko) CAMLC -c src/pCUICChecker.mli src/pCUICChecker.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 21248 ko) CAMLC -c src/pCUICSafeConversion.mli src/pCUICTyping.cmx (real: 0.10, user: 0.08, sys: 0.02, mem: 27292 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICChecker.ml src/pCUICSafeConversion.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 23348 ko) CAMLC -c src/pCUICPretty.mli src/pCUICChecker.cmx (real: 0.06, user: 0.04, sys: 0.02, mem: 25104 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICSafeReduce.ml src/pCUICPretty.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20340 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICPretty.ml src/pCUICSafeReduce.cmx (real: 0.10, user: 0.07, sys: 0.02, mem: 27680 ko) CAMLC -c src/pCUICSafeChecker.mli src/pCUICPretty.cmx (real: 0.11, user: 0.09, sys: 0.02, mem: 28948 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICSafeConversion.ml src/pCUICSafeChecker.cmi (real: 0.06, user: 0.06, sys: 0.00, mem: 24128 ko) CAMLC -c src/safeTemplateChecker.mli src/safeTemplateChecker.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 21632 ko) src/pCUICSafeConversion.cmx (real: 0.27, user: 0.24, sys: 0.03, mem: 43304 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/pCUICSafeChecker.ml src/pCUICSafeChecker.cmx (real: 0.34, user: 0.29, sys: 0.04, mem: 43492 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/safeTemplateChecker.ml src/safeTemplateChecker.cmx (real: 0.07, user: 0.05, sys: 0.01, mem: 27148 ko) CAMLOPT -c -for-pack Metacoq_safechecker_plugin src/g_metacoq_safechecker.ml src/g_metacoq_safechecker.cmx (real: 0.11, user: 0.09, sys: 0.02, mem: 35368 ko) CAMLOPT -pack -o src/metacoq_safechecker_plugin.cmx src/metacoq_safechecker_plugin.cmx (real: 0.10, user: 0.06, sys: 0.03, mem: 30436 ko) CAMLOPT -a -o src/metacoq_safechecker_plugin.cmxa src/metacoq_safechecker_plugin.cmxa (real: 0.05, user: 0.00, sys: 0.01, mem: 13624 ko) CAMLOPT -shared -o src/metacoq_safechecker_plugin.cmxs src/metacoq_safechecker_plugin.cmxs (real: 0.14, user: 0.11, sys: 0.03, mem: 20224 ko) ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 63536 ko) make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -C erasure make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' cat metacoq-config > _CoqProject cat _CoqProject.in >> _CoqProject rocq makefile -f _CoqProject -o Makefile.erasure Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.erasure make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' ROCQ DEP VFILES ROCQ compile theories/EAst.v theories/EAst.vo (real: 0.97, user: 0.72, sys: 0.24, mem: 477800 ko) ROCQ compile theories/EAstUtils.v ROCQ compile theories/EInduction.v theories/EInduction.vo (real: 0.97, user: 0.71, sys: 0.25, mem: 479012 ko) ROCQ compile theories/Extract.v theories/EAstUtils.vo (real: 1.36, user: 1.10, sys: 0.26, mem: 487520 ko) ROCQ compile theories/ELiftSubst.v theories/Extract.vo (real: 1.89, user: 1.57, sys: 0.32, mem: 617808 ko) ROCQ compile theories/EArities.v theories/EArities.vo (real: 6.12, user: 5.66, sys: 0.42, mem: 643396 ko) theories/ELiftSubst.vo (real: 10.89, user: 10.08, sys: 0.75, mem: 521520 ko) ROCQ compile theories/ETyping.v ROCQ compile theories/ECSubst.v theories/ETyping.vo (real: 1.01, user: 0.73, sys: 0.27, mem: 487644 ko) ROCQ compile theories/EPretty.v theories/ECSubst.vo (real: 1.31, user: 1.05, sys: 0.25, mem: 512080 ko) ROCQ compile theories/EWndEval.v theories/EPretty.vo (real: 1.02, user: 0.77, sys: 0.24, mem: 488076 ko) ROCQ compile theories/EWcbvEval.v theories/EWndEval.vo (real: 0.97, user: 0.70, sys: 0.26, mem: 485084 ko) theories/EWcbvEval.vo (real: 4.15, user: 3.85, sys: 0.28, mem: 520080 ko) ROCQ compile theories/EAll.v ROCQ compile theories/Prelim.v theories/EAll.vo (real: 1.76, user: 1.42, sys: 0.32, mem: 619396 ko) theories/Prelim.vo (real: 3.82, user: 3.39, sys: 0.40, mem: 741428 ko) ROCQ compile theories/ESubstitution.v ROCQ compile theories/EInversion.v theories/EInversion.vo (real: 3.19, user: 2.67, sys: 0.50, mem: 729072 ko) theories/ESubstitution.vo (real: 14.12, user: 13.39, sys: 0.67, mem: 794032 ko) ROCQ compile theories/ErasureCorrectness.v Axioms: todounivs : forall A : Type, A todoeta : forall A : Type, A todo : string -> forall A : Type, A ind_guard : mutual_inductive_body -> bool functional_extensionality_dep : forall (A : Type) (B : A -> Type) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g fix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), fix_guard mfix -> fix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) fix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (PCUICLiftSubst.subst s k) (PCUICLiftSubst.subst s k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> red1 Ξ£ Ξ“ (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (PCUICLiftSubst.lift n k) (PCUICLiftSubst.lift n k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> PCUICEquality.upto_names (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard : mfixpoint term -> bool erases_closed : forall (Ξ£ : global_env_ext) (Ξ“ : list context_decl) (a : term) (e : E.term), PCUICLiftSubst.closedn #|Ξ“| a -> Ξ£;;; Ξ“ |- a ⇝ℇ e -> closedn #|Ξ“| e cofix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), cofix_guard mfix -> cofix_guard (map (map_def (subst_instance_constr u) (subst_instance_constr u)) mfix) cofix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (PCUICLiftSubst.subst s k) (PCUICLiftSubst.subst s k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> red1 Ξ£ Ξ“ (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := #|mfix| + k in let mfix' := map (map_def (PCUICLiftSubst.lift n k) (PCUICLiftSubst.lift n k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> PCUICEquality.upto_names (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard : mfixpoint term -> bool theories/ErasureCorrectness.vo (real: 58.09, user: 56.17, sys: 1.60, mem: 1113548 ko) ROCQ compile theories/ErasureFunction.v ROCQ compile theories/SafeErasureFunction.v theories/SafeErasureFunction.vo (real: 24.59, user: 23.34, sys: 1.11, mem: 854428 ko) Axioms: todounivs : forall A : Type, A todoeta : forall A : Type, A todo : string -> forall A : Type, A proof_irrelevance : forall (P : Prop) (p1 p2 : P), p1 = p2 normalisation' : forall (cf : checker_flags) (Ξ£ : global_env_ext) (Ξ“ : context) (t : term), wf Ξ£ -> wellformed Ξ£ Ξ“ t -> Acc (cored Ξ£.1 Ξ“) t ind_guard : mutual_inductive_body -> bool functional_extensionality_dep : forall (A : Type) (B : A -> Type) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g PCUICUnivSubstitution.fix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), fix_guard mfix -> fix_guard (map (map_def (PCUICUnivSubst.subst_instance_constr u) (PCUICUnivSubst.subst_instance_constr u)) mfix) fix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (subst s k) (subst s k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> red1 Ξ£ Ξ“ (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (lift n k) (lift n k')) mfix in fix_guard mfix -> fix_guard mfix' fix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), fix_guard mfix -> PCUICEquality.upto_names (tFix mfix idx) (tFix mfix' idx) -> fix_guard mfix' fix_guard : mfixpoint term -> bool PCUICUnivSubstitution.cofix_guard_subst_instance : forall (mfix : mfixpoint term) (u : Instance.t), cofix_guard mfix -> cofix_guard (map (map_def (PCUICUnivSubst.subst_instance_constr u) (PCUICUnivSubst.subst_instance_constr u)) mfix) cofix_guard_subst : forall (mfix : list (def term)) (s : list term) (k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (subst s k) (subst s k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_red1 : forall (Ξ£ : global_env) (Ξ“ : context) (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> red1 Ξ£ Ξ“ (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard_lift : forall (mfix : list (def term)) (n k : nat), let k' := (#|mfix| + k)%nat in let mfix' := map (map_def (lift n k) (lift n k')) mfix in cofix_guard mfix -> cofix_guard mfix' cofix_guard_eq_term : forall (mfix mfix' : mfixpoint term) (idx : nat), cofix_guard mfix -> PCUICEquality.upto_names (tCoFix mfix idx) (tCoFix mfix' idx) -> cofix_guard mfix' cofix_guard : mfixpoint term -> bool theories/ErasureFunction.vo (real: 40.61, user: 39.21, sys: 1.22, mem: 1012876 ko) ROCQ compile theories/SafeTemplateErasure.v theories/SafeTemplateErasure.vo (real: 4.47, user: 3.99, sys: 0.45, mem: 806128 ko) ROCQ compile theories/Extraction.v theories/Extraction.vo (real: 6.38, user: 5.74, sys: 0.59, mem: 872556 ko) echo "Done extracting the erasure, moving extraction files!" Done extracting the erasure, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Moving All_Forall.ml to all_Forall.ml Moving All_Forall.mli to all_Forall.mli Moving Ascii.ml to ascii.ml Moving Ascii.mli to ascii.mli Moving Ast0.ml to ast0.ml Moving Ast0.mli to ast0.mli Moving AstUtils.ml to astUtils.ml Moving AstUtils.mli to astUtils.mli Moving BasicAst.ml to basicAst.ml Moving BasicAst.mli to basicAst.mli Moving Basics.ml to basics.ml Moving Basics.mli to basics.mli Moving BinInt.ml to binInt.ml Moving BinInt.mli to binInt.mli Moving BinNat.ml to binNat.ml Moving BinNat.mli to binNat.mli Moving BinNums.ml to binNums.ml Moving BinNums.mli to binNums.mli Moving BinPos.ml to binPos.ml Moving BinPos.mli to binPos.mli Moving Bool.ml to bool.ml Moving Bool.mli to bool.mli Moving Byte.ml to byte.ml Moving Byte.mli to byte.mli Moving Classes0.ml to classes0.ml Moving Classes0.mli to classes0.mli Moving Compare_dec.ml to compare_dec.ml Moving Compare_dec.mli to compare_dec.mli Moving Datatypes.ml to datatypes.ml Moving Datatypes.mli to datatypes.mli Moving EAst.ml to eAst.ml Moving EAst.mli to eAst.mli Moving EAstUtils.ml to eAstUtils.ml Moving EAstUtils.mli to eAstUtils.mli Moving ELiftSubst.ml to eLiftSubst.ml Moving ELiftSubst.mli to eLiftSubst.mli Moving EPretty.ml to ePretty.ml Moving EPretty.mli to ePretty.mli Moving ETyping.ml to eTyping.ml Moving ETyping.mli to eTyping.mli Moving Environment.ml to environment.ml Moving Environment.mli to environment.mli Moving EqDecInstances.ml to eqDecInstances.ml Moving EqDecInstances.mli to eqDecInstances.mli Moving EqdepFacts.ml to eqdepFacts.ml Moving EqdepFacts.mli to eqdepFacts.mli Moving Equalities.ml to equalities.ml Moving Equalities.mli to equalities.mli Moving ErasureFunction.ml to erasureFunction.ml Moving ErasureFunction.mli to erasureFunction.mli Moving Extract.ml to extract.ml Moving Extract.mli to extract.mli Moving Init.ml to init.ml Moving Init.mli to init.mli Moving LiftSubst.ml to liftSubst.ml Moving LiftSubst.mli to liftSubst.mli Moving List0.ml to list0.ml Moving List0.mli to list0.mli Moving MCCompare.ml to mCCompare.ml Moving MCCompare.mli to mCCompare.mli Moving MCList.ml to mCList.ml Moving MCList.mli to mCList.mli Moving MCOption.ml to mCOption.ml Moving MCOption.mli to mCOption.mli Moving MCProd.ml to mCProd.ml Moving MCProd.mli to mCProd.mli Moving MCString.ml to mCString.ml Moving MCString.mli to mCString.mli Moving MSetDecide.ml to mSetDecide.ml Moving MSetDecide.mli to mSetDecide.mli Moving MSetFacts.ml to mSetFacts.ml Moving MSetFacts.mli to mSetFacts.mli Moving MSetInterface.ml to mSetInterface.ml Moving MSetInterface.mli to mSetInterface.mli Moving MSetList.ml to mSetList.ml Moving MSetList.mli to mSetList.mli Moving MSetProperties.ml to mSetProperties.ml Moving MSetProperties.mli to mSetProperties.mli Moving MSetWeakList.ml to mSetWeakList.ml Moving MSetWeakList.mli to mSetWeakList.mli Moving Nat0.ml to nat0.ml Moving Nat0.mli to nat0.mli Moving Orders.ml to orders.ml Moving Orders.mli to orders.mli Moving OrdersFacts.ml to ordersFacts.ml Moving OrdersFacts.mli to ordersFacts.mli Moving OrdersLists.ml to ordersLists.ml Moving OrdersLists.mli to ordersLists.mli Moving OrdersTac.ml to ordersTac.ml Moving OrdersTac.mli to ordersTac.mli Moving PCUICAst.ml to pCUICAst.ml Moving PCUICAst.mli to pCUICAst.mli Moving PCUICAstUtils.ml to pCUICAstUtils.ml Moving PCUICAstUtils.mli to pCUICAstUtils.mli Moving PCUICChecker.ml to pCUICChecker.ml Moving PCUICChecker.mli to pCUICChecker.mli Moving PCUICCumulativity.ml to pCUICCumulativity.ml Moving PCUICCumulativity.mli to pCUICCumulativity.mli Moving PCUICEquality.ml to pCUICEquality.ml Moving PCUICEquality.mli to pCUICEquality.mli Moving PCUICLiftSubst.ml to pCUICLiftSubst.ml Moving PCUICLiftSubst.mli to pCUICLiftSubst.mli Moving PCUICNormal.ml to pCUICNormal.ml Moving PCUICNormal.mli to pCUICNormal.mli Moving PCUICPosition.ml to pCUICPosition.ml Moving PCUICPosition.mli to pCUICPosition.mli Moving PCUICPretty.ml to pCUICPretty.ml Moving PCUICPretty.mli to pCUICPretty.mli Moving PCUICReflect.ml to pCUICReflect.ml Moving PCUICReflect.mli to pCUICReflect.mli Moving PCUICSafeChecker.ml to pCUICSafeChecker.ml Moving PCUICSafeChecker.mli to pCUICSafeChecker.mli Moving PCUICSafeConversion.ml to pCUICSafeConversion.ml Moving PCUICSafeConversion.mli to pCUICSafeConversion.mli Moving PCUICSafeLemmata.ml to pCUICSafeLemmata.ml Moving PCUICSafeLemmata.mli to pCUICSafeLemmata.mli Moving PCUICSafeReduce.ml to pCUICSafeReduce.ml Moving PCUICSafeReduce.mli to pCUICSafeReduce.mli Moving PCUICSafeRetyping.ml to pCUICSafeRetyping.ml Moving PCUICSafeRetyping.mli to pCUICSafeRetyping.mli Moving PCUICTyping.ml to pCUICTyping.ml Moving PCUICTyping.mli to pCUICTyping.mli Moving PCUICUnivSubst.ml to pCUICUnivSubst.ml Moving PCUICUnivSubst.mli to pCUICUnivSubst.mli Moving PeanoNat.ml to peanoNat.ml Moving PeanoNat.mli to peanoNat.mli Moving Pretty.ml to pretty.ml Moving Pretty.mli to pretty.mli Moving SafeErasureFunction.ml to safeErasureFunction.ml Moving SafeErasureFunction.mli to safeErasureFunction.mli Moving SafeTemplateChecker.ml to safeTemplateChecker.ml Moving SafeTemplateChecker.mli to safeTemplateChecker.mli Moving SafeTemplateErasure.ml to safeTemplateErasure.ml Moving SafeTemplateErasure.mli to safeTemplateErasure.mli Moving Specif.ml to specif.ml Moving Specif.mli to specif.mli Moving String0.ml to string0.ml Moving String0.mli to string0.mli Moving TemplateToPCUIC.ml to templateToPCUIC.ml Moving TemplateToPCUIC.mli to templateToPCUIC.mli Moving Typing0.ml to typing0.ml Moving Typing0.mli to typing0.mli Moving UnivSubst0.ml to univSubst0.ml Moving UnivSubst0.mli to univSubst0.mli Moving Universes0.ml to universes0.ml Moving Universes0.mli to universes0.mli Moving config0.ml to config0.ml mv: 'config0.ml' and 'config0.ml' are the same file Moving config0.mli to config0.mli mv: 'config0.mli' and 'config0.mli' are the same file Moving g_metacoq_erasure.ml to g_metacoq_erasure.ml mv: 'g_metacoq_erasure.ml' and 'g_metacoq_erasure.ml' are the same file Moving g_metacoq_erasure.mlg to g_metacoq_erasure.mlg mv: 'g_metacoq_erasure.mlg' and 'g_metacoq_erasure.mlg' are the same file Moving metacoq_erasure_plugin.mlpack to metacoq_erasure_plugin.mlpack mv: 'metacoq_erasure_plugin.mlpack' and 'metacoq_erasure_plugin.mlpack' are the same file Moving monad_utils.ml to monad_utils.ml mv: 'monad_utils.ml' and 'monad_utils.ml' are the same file Moving monad_utils.mli to monad_utils.mli mv: 'monad_utils.mli' and 'monad_utils.mli' are the same file Moving ssrbool.ml to ssrbool.ml mv: 'ssrbool.ml' and 'ssrbool.ml' are the same file Moving ssrbool.mli to ssrbool.mli mv: 'ssrbool.mli' and 'ssrbool.mli' are the same file Moving uGraph0.ml to uGraph0.ml mv: 'uGraph0.ml' and 'uGraph0.ml' are the same file Moving uGraph0.mli to uGraph0.mli mv: 'uGraph0.mli' and 'uGraph0.mli' are the same file Moving utils.ml to utils.ml mv: 'utils.ml' and 'utils.ml' are the same file Moving utils.mli to utils.mli mv: 'utils.mli' and 'utils.mli' are the same file Moving wGraph.ml to wGraph.ml mv: 'wGraph.ml' and 'wGraph.ml' are the same file Moving wGraph.mli to wGraph.mli mv: 'wGraph.mli' and 'wGraph.mli' are the same file Removing: src/all_Forall.ml src/all_Forall.mli src/ascii.ml src/ascii.mli src/ast0.ml src/ast0.mli src/ast_denoter.ml src/ast_quoter.ml src/astUtils.ml src/astUtils.mli src/basicAst.ml src/basicAst.mli src/basics.ml src/basics.mli src/binInt.ml src/binInt.mli src/binNat.ml src/binNat.mli src/binNums.ml src/binNums.mli src/binPosDef.ml src/binPosDef.mli src/binPos.ml src/binPos.mli src/bool.ml src/bool.mli src/common0.ml src/common0.mli src/compare_dec.ml src/compare_dec.mli src/config0.ml src/config0.mli src/cRelationClasses.ml src/cRelationClasses.mli src/datatypes.ml src/datatypes.mli src/decimal.ml src/decimal.mli src/denoter.ml src/environment.ml src/environment.mli src/equalities.ml src/equalities.mli src/extractable.ml src/extractable.mli src/hexadecimal.ml src/hexadecimal.mli src/liftSubst.ml src/liftSubst.mli src/list0.ml src/list0.mli src/logic0.ml src/logic0.mli src/mCPrelude.mli src/mCPrelude.ml src/mCCompare.ml src/mCCompare.mli src/mCList.ml src/mCList.mli src/mCOption.ml src/mCOption.mli src/mCProd.ml src/mCProd.mli src/mCRelations.ml src/mCRelations.mli src/mCString.ml src/mCString.mli src/mSetDecide.ml src/mSetDecide.mli src/mSetFacts.ml src/mSetFacts.mli src/mSetInterface.ml src/mSetInterface.mli src/mSetList.ml src/mSetList.mli src/mSetProperties.ml src/mSetProperties.mli src/nat0.ml src/nat0.mli src/numeral.ml src/numeral.mli src/orderedType0.ml src/orderedType0.mli src/ordersFacts.ml src/ordersFacts.mli src/ordersLists.ml src/ordersLists.mli src/orders.ml src/orders.mli src/ordersTac.ml src/ordersTac.mli src/peanoNat.ml src/peanoNat.mli src/plugin_core.ml src/plugin_core.mli src/pretty.ml src/pretty.mli src/reification.ml src/quoter.ml src/run_extractable.ml src/run_extractable.mli src/specif.ml src/specif.mli src/string0.ml src/string0.mli src/tm_util.ml src/universes0.ml src/universes0.mli src/univSubst0.ml src/univSubst0.mli make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' ./clean_extraction.sh Cleaning result of extraction Moving byte.ml to byte.ml mv: 'byte.ml' and 'byte.ml' are the same file Moving byte.mli to byte.mli mv: 'byte.mli' and 'byte.mli' are the same file Moving classes0.ml to classes0.ml mv: 'classes0.ml' and 'classes0.ml' are the same file Moving classes0.mli to classes0.mli mv: 'classes0.mli' and 'classes0.mli' are the same file Moving eAst.ml to eAst.ml mv: 'eAst.ml' and 'eAst.ml' are the same file Moving eAst.mli to eAst.mli mv: 'eAst.mli' and 'eAst.mli' are the same file Moving eAstUtils.ml to eAstUtils.ml mv: 'eAstUtils.ml' and 'eAstUtils.ml' are the same file Moving eAstUtils.mli to eAstUtils.mli mv: 'eAstUtils.mli' and 'eAstUtils.mli' are the same file Moving eLiftSubst.ml to eLiftSubst.ml mv: 'eLiftSubst.ml' and 'eLiftSubst.ml' are the same file Moving eLiftSubst.mli to eLiftSubst.mli mv: 'eLiftSubst.mli' and 'eLiftSubst.mli' are the same file Moving ePretty.ml to ePretty.ml mv: 'ePretty.ml' and 'ePretty.ml' are the same file Moving ePretty.mli to ePretty.mli mv: 'ePretty.mli' and 'ePretty.mli' are the same file Moving eTyping.ml to eTyping.ml mv: 'eTyping.ml' and 'eTyping.ml' are the same file Moving eTyping.mli to eTyping.mli mv: 'eTyping.mli' and 'eTyping.mli' are the same file Moving eqDecInstances.ml to eqDecInstances.ml mv: 'eqDecInstances.ml' and 'eqDecInstances.ml' are the same file Moving eqDecInstances.mli to eqDecInstances.mli mv: 'eqDecInstances.mli' and 'eqDecInstances.mli' are the same file Moving eqdepFacts.ml to eqdepFacts.ml mv: 'eqdepFacts.ml' and 'eqdepFacts.ml' are the same file Moving eqdepFacts.mli to eqdepFacts.mli mv: 'eqdepFacts.mli' and 'eqdepFacts.mli' are the same file Moving erasureFunction.ml to erasureFunction.ml mv: 'erasureFunction.ml' and 'erasureFunction.ml' are the same file Moving erasureFunction.mli to erasureFunction.mli mv: 'erasureFunction.mli' and 'erasureFunction.mli' are the same file Moving extract.ml to extract.ml mv: 'extract.ml' and 'extract.ml' are the same file Moving extract.mli to extract.mli mv: 'extract.mli' and 'extract.mli' are the same file Moving g_metacoq_erasure.ml to g_metacoq_erasure.ml mv: 'g_metacoq_erasure.ml' and 'g_metacoq_erasure.ml' are the same file Moving g_metacoq_erasure.mlg to g_metacoq_erasure.mlg mv: 'g_metacoq_erasure.mlg' and 'g_metacoq_erasure.mlg' are the same file Moving init.ml to init.ml mv: 'init.ml' and 'init.ml' are the same file Moving init.mli to init.mli mv: 'init.mli' and 'init.mli' are the same file Moving mSetWeakList.ml to mSetWeakList.ml mv: 'mSetWeakList.ml' and 'mSetWeakList.ml' are the same file Moving mSetWeakList.mli to mSetWeakList.mli mv: 'mSetWeakList.mli' and 'mSetWeakList.mli' are the same file Moving metacoq_erasure_plugin.mlpack to metacoq_erasure_plugin.mlpack mv: 'metacoq_erasure_plugin.mlpack' and 'metacoq_erasure_plugin.mlpack' are the same file Moving monad_utils.ml to monad_utils.ml mv: 'monad_utils.ml' and 'monad_utils.ml' are the same file Moving monad_utils.mli to monad_utils.mli mv: 'monad_utils.mli' and 'monad_utils.mli' are the same file Moving pCUICAst.ml to pCUICAst.ml mv: 'pCUICAst.ml' and 'pCUICAst.ml' are the same file Moving pCUICAst.mli to pCUICAst.mli mv: 'pCUICAst.mli' and 'pCUICAst.mli' are the same file Moving pCUICAstUtils.ml to pCUICAstUtils.ml mv: 'pCUICAstUtils.ml' and 'pCUICAstUtils.ml' are the same file Moving pCUICAstUtils.mli to pCUICAstUtils.mli mv: 'pCUICAstUtils.mli' and 'pCUICAstUtils.mli' are the same file Moving pCUICChecker.ml to pCUICChecker.ml mv: 'pCUICChecker.ml' and 'pCUICChecker.ml' are the same file Moving pCUICChecker.mli to pCUICChecker.mli mv: 'pCUICChecker.mli' and 'pCUICChecker.mli' are the same file Moving pCUICCumulativity.ml to pCUICCumulativity.ml mv: 'pCUICCumulativity.ml' and 'pCUICCumulativity.ml' are the same file Moving pCUICCumulativity.mli to pCUICCumulativity.mli mv: 'pCUICCumulativity.mli' and 'pCUICCumulativity.mli' are the same file Moving pCUICEquality.ml to pCUICEquality.ml mv: 'pCUICEquality.ml' and 'pCUICEquality.ml' are the same file Moving pCUICEquality.mli to pCUICEquality.mli mv: 'pCUICEquality.mli' and 'pCUICEquality.mli' are the same file Moving pCUICLiftSubst.ml to pCUICLiftSubst.ml mv: 'pCUICLiftSubst.ml' and 'pCUICLiftSubst.ml' are the same file Moving pCUICLiftSubst.mli to pCUICLiftSubst.mli mv: 'pCUICLiftSubst.mli' and 'pCUICLiftSubst.mli' are the same file Moving pCUICNormal.ml to pCUICNormal.ml mv: 'pCUICNormal.ml' and 'pCUICNormal.ml' are the same file Moving pCUICNormal.mli to pCUICNormal.mli mv: 'pCUICNormal.mli' and 'pCUICNormal.mli' are the same file Moving pCUICPosition.ml to pCUICPosition.ml mv: 'pCUICPosition.ml' and 'pCUICPosition.ml' are the same file Moving pCUICPosition.mli to pCUICPosition.mli mv: 'pCUICPosition.mli' and 'pCUICPosition.mli' are the same file Moving pCUICPretty.ml to pCUICPretty.ml mv: 'pCUICPretty.ml' and 'pCUICPretty.ml' are the same file Moving pCUICPretty.mli to pCUICPretty.mli mv: 'pCUICPretty.mli' and 'pCUICPretty.mli' are the same file Moving pCUICReflect.ml to pCUICReflect.ml mv: 'pCUICReflect.ml' and 'pCUICReflect.ml' are the same file Moving pCUICReflect.mli to pCUICReflect.mli mv: 'pCUICReflect.mli' and 'pCUICReflect.mli' are the same file Moving pCUICSafeChecker.ml to pCUICSafeChecker.ml mv: 'pCUICSafeChecker.ml' and 'pCUICSafeChecker.ml' are the same file Moving pCUICSafeChecker.mli to pCUICSafeChecker.mli mv: 'pCUICSafeChecker.mli' and 'pCUICSafeChecker.mli' are the same file Moving pCUICSafeConversion.ml to pCUICSafeConversion.ml mv: 'pCUICSafeConversion.ml' and 'pCUICSafeConversion.ml' are the same file Moving pCUICSafeConversion.mli to pCUICSafeConversion.mli mv: 'pCUICSafeConversion.mli' and 'pCUICSafeConversion.mli' are the same file Moving pCUICSafeLemmata.ml to pCUICSafeLemmata.ml mv: 'pCUICSafeLemmata.ml' and 'pCUICSafeLemmata.ml' are the same file Moving pCUICSafeLemmata.mli to pCUICSafeLemmata.mli mv: 'pCUICSafeLemmata.mli' and 'pCUICSafeLemmata.mli' are the same file Moving pCUICSafeReduce.ml to pCUICSafeReduce.ml mv: 'pCUICSafeReduce.ml' and 'pCUICSafeReduce.ml' are the same file Moving pCUICSafeReduce.mli to pCUICSafeReduce.mli mv: 'pCUICSafeReduce.mli' and 'pCUICSafeReduce.mli' are the same file Moving pCUICSafeRetyping.ml to pCUICSafeRetyping.ml mv: 'pCUICSafeRetyping.ml' and 'pCUICSafeRetyping.ml' are the same file Moving pCUICSafeRetyping.mli to pCUICSafeRetyping.mli mv: 'pCUICSafeRetyping.mli' and 'pCUICSafeRetyping.mli' are the same file Moving pCUICTyping.ml to pCUICTyping.ml mv: 'pCUICTyping.ml' and 'pCUICTyping.ml' are the same file Moving pCUICTyping.mli to pCUICTyping.mli mv: 'pCUICTyping.mli' and 'pCUICTyping.mli' are the same file Moving pCUICUnivSubst.ml to pCUICUnivSubst.ml mv: 'pCUICUnivSubst.ml' and 'pCUICUnivSubst.ml' are the same file Moving pCUICUnivSubst.mli to pCUICUnivSubst.mli mv: 'pCUICUnivSubst.mli' and 'pCUICUnivSubst.mli' are the same file Moving safeErasureFunction.ml to safeErasureFunction.ml mv: 'safeErasureFunction.ml' and 'safeErasureFunction.ml' are the same file Moving safeErasureFunction.mli to safeErasureFunction.mli mv: 'safeErasureFunction.mli' and 'safeErasureFunction.mli' are the same file Moving safeTemplateChecker.ml to safeTemplateChecker.ml mv: 'safeTemplateChecker.ml' and 'safeTemplateChecker.ml' are the same file Moving safeTemplateChecker.mli to safeTemplateChecker.mli mv: 'safeTemplateChecker.mli' and 'safeTemplateChecker.mli' are the same file Moving safeTemplateErasure.ml to safeTemplateErasure.ml mv: 'safeTemplateErasure.ml' and 'safeTemplateErasure.ml' are the same file Moving safeTemplateErasure.mli to safeTemplateErasure.mli mv: 'safeTemplateErasure.mli' and 'safeTemplateErasure.mli' are the same file Moving ssrbool.ml to ssrbool.ml mv: 'ssrbool.ml' and 'ssrbool.ml' are the same file Moving ssrbool.mli to ssrbool.mli mv: 'ssrbool.mli' and 'ssrbool.mli' are the same file Moving templateToPCUIC.ml to templateToPCUIC.ml mv: 'templateToPCUIC.ml' and 'templateToPCUIC.ml' are the same file Moving templateToPCUIC.mli to templateToPCUIC.mli mv: 'templateToPCUIC.mli' and 'templateToPCUIC.mli' are the same file Moving typing0.ml to typing0.ml mv: 'typing0.ml' and 'typing0.ml' are the same file Moving typing0.mli to typing0.mli mv: 'typing0.mli' and 'typing0.mli' are the same file Moving uGraph0.ml to uGraph0.ml mv: 'uGraph0.ml' and 'uGraph0.ml' are the same file Moving uGraph0.mli to uGraph0.mli mv: 'uGraph0.mli' and 'uGraph0.mli' are the same file Moving utils.ml to utils.ml mv: 'utils.ml' and 'utils.ml' are the same file Moving utils.mli to utils.mli mv: 'utils.mli' and 'utils.mli' are the same file Moving wGraph.ml to wGraph.ml mv: 'wGraph.ml' and 'wGraph.ml' are the same file Moving wGraph.mli to wGraph.mli mv: 'wGraph.mli' and 'wGraph.mli' are the same file Removing: src/all_Forall.ml src/all_Forall.mli src/ascii.ml src/ascii.mli src/ast0.ml src/ast0.mli src/ast_denoter.ml src/ast_quoter.ml src/astUtils.ml src/astUtils.mli src/basicAst.ml src/basicAst.mli src/basics.ml src/basics.mli src/binInt.ml src/binInt.mli src/binNat.ml src/binNat.mli src/binNums.ml src/binNums.mli src/binPosDef.ml src/binPosDef.mli src/binPos.ml src/binPos.mli src/bool.ml src/bool.mli src/common0.ml src/common0.mli src/compare_dec.ml src/compare_dec.mli src/config0.ml src/config0.mli src/cRelationClasses.ml src/cRelationClasses.mli src/datatypes.ml src/datatypes.mli src/decimal.ml src/decimal.mli src/denoter.ml src/environment.ml src/environment.mli src/equalities.ml src/equalities.mli src/extractable.ml src/extractable.mli src/hexadecimal.ml src/hexadecimal.mli src/liftSubst.ml src/liftSubst.mli src/list0.ml src/list0.mli src/logic0.ml src/logic0.mli src/mCPrelude.mli src/mCPrelude.ml src/mCCompare.ml src/mCCompare.mli src/mCList.ml src/mCList.mli src/mCOption.ml src/mCOption.mli src/mCProd.ml src/mCProd.mli src/mCRelations.ml src/mCRelations.mli src/mCString.ml src/mCString.mli src/mSetDecide.ml src/mSetDecide.mli src/mSetFacts.ml src/mSetFacts.mli src/mSetInterface.ml src/mSetInterface.mli src/mSetList.ml src/mSetList.mli src/mSetProperties.ml src/mSetProperties.mli src/nat0.ml src/nat0.mli src/numeral.ml src/numeral.mli src/orderedType0.ml src/orderedType0.mli src/ordersFacts.ml src/ordersFacts.mli src/ordersLists.ml src/ordersLists.mli src/orders.ml src/orders.mli src/ordersTac.ml src/ordersTac.mli src/peanoNat.ml src/peanoNat.mli src/plugin_core.ml src/plugin_core.mli src/pretty.ml src/pretty.mli src/reification.ml src/quoter.ml src/run_extractable.ml src/run_extractable.mli src/specif.ml src/specif.mli src/string0.ml src/string0.mli src/tm_util.ml src/universes0.ml src/universes0.mli src/univSubst0.ml src/univSubst0.mli make -f Makefile.plugin make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' ROCQ DEP VFILES CAMLDEP src/safeTemplateErasure.mli CAMLDEP src/ePretty.mli CAMLDEP src/safeErasureFunction.mli CAMLDEP src/extract.mli CAMLDEP src/erasureFunction.mli CAMLDEP src/eTyping.mli CAMLDEP src/eLiftSubst.mli CAMLDEP src/eAstUtils.mli CAMLDEP src/eAst.mli CAMLDEP src/safeTemplateChecker.mli CAMLDEP src/pCUICSafeRetyping.mli CAMLDEP src/pCUICSafeChecker.mli CAMLDEP src/pCUICSafeConversion.mli CAMLDEP src/pCUICSafeReduce.mli CAMLDEP src/templateToPCUIC.mli CAMLDEP src/pCUICSafeLemmata.mli CAMLDEP src/pCUICPretty.mli CAMLDEP src/pCUICChecker.mli CAMLDEP src/pCUICNormal.mli CAMLDEP src/pCUICPosition.mli CAMLDEP src/pCUICCumulativity.mli CAMLDEP src/pCUICUnivSubst.mli CAMLDEP src/pCUICTyping.mli CAMLDEP src/pCUICReflect.mli CAMLDEP src/pCUICEquality.mli CAMLDEP src/eqDecInstances.mli CAMLDEP src/pCUICLiftSubst.mli CAMLDEP src/pCUICAstUtils.mli CAMLDEP src/pCUICAst.mli CAMLDEP src/typing0.mli CAMLDEP src/wGraph.mli CAMLDEP src/uGraph0.mli CAMLDEP src/monad_utils.mli CAMLDEP src/utils.mli CAMLDEP src/ssrbool.mli CAMLDEP src/eqdepFacts.mli CAMLDEP src/mSetWeakList.mli CAMLDEP src/classes0.mli CAMLDEP src/init.mli OCAMLLIBDEP src/metacoq_erasure_plugin.mlpack CAMLDEP src/safeTemplateErasure.ml CAMLDEP src/ePretty.ml CAMLDEP src/safeErasureFunction.ml CAMLDEP src/erasureFunction.ml CAMLDEP src/extract.ml CAMLDEP src/eTyping.ml CAMLDEP src/eLiftSubst.ml CAMLDEP src/eAstUtils.ml CAMLDEP src/eAst.ml CAMLDEP src/safeTemplateChecker.ml CAMLDEP src/pCUICSafeRetyping.ml CAMLDEP src/pCUICSafeChecker.ml CAMLDEP src/pCUICSafeConversion.ml CAMLDEP src/pCUICSafeReduce.ml CAMLDEP src/templateToPCUIC.ml CAMLDEP src/pCUICSafeLemmata.ml CAMLDEP src/pCUICPretty.ml CAMLDEP src/pCUICChecker.ml CAMLDEP src/pCUICNormal.ml CAMLDEP src/pCUICPosition.ml CAMLDEP src/pCUICCumulativity.ml CAMLDEP src/pCUICUnivSubst.ml CAMLDEP src/pCUICTyping.ml CAMLDEP src/pCUICEquality.ml CAMLDEP src/pCUICReflect.ml CAMLDEP src/eqDecInstances.ml CAMLDEP src/pCUICLiftSubst.ml CAMLDEP src/pCUICAstUtils.ml CAMLDEP src/pCUICAst.ml CAMLDEP src/typing0.ml CAMLDEP src/wGraph.ml CAMLDEP src/uGraph0.ml CAMLDEP src/monad_utils.ml CAMLDEP src/utils.ml CAMLDEP src/ssrbool.ml CAMLDEP src/eqdepFacts.ml CAMLDEP src/mSetWeakList.ml CAMLDEP src/classes0.ml CAMLDEP src/init.ml CAMLDEP src/g_metacoq_erasure.ml CAMLC -c src/mSetWeakList.mli CAMLC -c src/monad_utils.mli src/monad_utils.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19272 ko) CAMLC -c src/eqdepFacts.mli src/mSetWeakList.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 20108 ko) CAMLC -c src/ssrbool.mli src/eqdepFacts.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19396 ko) CAMLC -c src/utils.mli src/ssrbool.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 19220 ko) CAMLC -c src/typing0.mli src/typing0.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20300 ko) CAMLC -c src/init.mli src/utils.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 19228 ko) CAMLC -c src/classes0.mli src/init.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19324 ko) CAMLC -c src/pCUICAst.mli src/classes0.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 19340 ko) CAMLC -c src/pCUICNormal.mli src/pCUICNormal.cmi (real: 0.03, user: 0.02, sys: 0.01, mem: 19304 ko) CAMLC -c src/pCUICCumulativity.mli src/pCUICAst.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 21244 ko) CAMLC -c src/safeTemplateChecker.mli src/pCUICCumulativity.cmi (real: 0.03, user: 0.02, sys: 0.01, mem: 19224 ko) CAMLC -c src/eAst.mli src/safeTemplateChecker.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 20348 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/monad_utils.ml src/eAst.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 20908 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/mSetWeakList.ml src/monad_utils.cmx (real: 0.07, user: 0.04, sys: 0.02, mem: 22452 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eqdepFacts.ml src/mSetWeakList.cmx (real: 0.08, user: 0.06, sys: 0.01, mem: 25216 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/ssrbool.ml src/eqdepFacts.cmx (real: 0.05, user: 0.03, sys: 0.01, mem: 22072 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/utils.ml src/ssrbool.cmx (real: 0.05, user: 0.02, sys: 0.02, mem: 21912 ko) CAMLC -c src/wGraph.mli src/utils.cmx (real: 0.06, user: 0.04, sys: 0.02, mem: 22212 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/typing0.ml src/wGraph.cmi (real: 0.06, user: 0.05, sys: 0.00, mem: 22824 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/init.ml src/typing0.cmx (real: 0.07, user: 0.05, sys: 0.01, mem: 24076 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/classes0.ml src/init.cmx (real: 0.05, user: 0.03, sys: 0.02, mem: 22188 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICAst.ml src/classes0.cmx (real: 0.05, user: 0.02, sys: 0.02, mem: 21960 ko) CAMLC -c src/pCUICAstUtils.mli src/pCUICAst.cmx (real: 0.07, user: 0.05, sys: 0.01, mem: 26032 ko) CAMLC -c src/pCUICUnivSubst.mli src/pCUICAstUtils.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 20412 ko) CAMLC -c src/pCUICLiftSubst.mli src/pCUICUnivSubst.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20308 ko) CAMLC -c src/eqDecInstances.mli src/pCUICLiftSubst.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 20444 ko) CAMLC -c src/pCUICReflect.mli src/eqDecInstances.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19268 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICNormal.ml src/pCUICReflect.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20240 ko) CAMLC -c src/pCUICPosition.mli src/pCUICNormal.cmx (real: 0.05, user: 0.03, sys: 0.02, mem: 22044 ko) CAMLC -c src/templateToPCUIC.mli src/pCUICPosition.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 20488 ko) CAMLC -c src/pCUICSafeLemmata.mli src/pCUICSafeLemmata.cmi (real: 0.04, user: 0.03, sys: 0.00, mem: 19348 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICCumulativity.ml src/templateToPCUIC.cmi (real: 0.06, user: 0.05, sys: 0.01, mem: 21328 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/safeTemplateChecker.ml src/pCUICCumulativity.cmx (real: 0.04, user: 0.02, sys: 0.02, mem: 21940 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eAst.ml src/safeTemplateChecker.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 25408 ko) CAMLC -c src/eAstUtils.mli src/eAstUtils.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19496 ko) CAMLC -c src/eLiftSubst.mli src/eAst.cmx (real: 0.12, user: 0.10, sys: 0.02, mem: 28644 ko) CAMLC -c src/extract.mli src/eLiftSubst.cmi (real: 0.04, user: 0.02, sys: 0.01, mem: 19300 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/wGraph.ml src/extract.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 21060 ko) CAMLC -c src/uGraph0.mli src/uGraph0.cmi (real: 0.08, user: 0.06, sys: 0.01, mem: 24780 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICAstUtils.ml src/wGraph.cmx (real: 0.17, user: 0.14, sys: 0.02, mem: 31636 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICUnivSubst.ml src/pCUICAstUtils.cmx (real: 0.11, user: 0.08, sys: 0.02, mem: 26392 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICLiftSubst.ml src/pCUICUnivSubst.cmx (real: 0.08, user: 0.05, sys: 0.02, mem: 25180 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eqDecInstances.ml src/eqDecInstances.cmx (real: 0.06, user: 0.03, sys: 0.02, mem: 22196 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICReflect.ml src/pCUICLiftSubst.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 26244 ko) CAMLC -c src/pCUICEquality.mli src/pCUICEquality.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 20372 ko) CAMLC -c src/pCUICTyping.mli src/pCUICReflect.cmx (real: 0.07, user: 0.05, sys: 0.02, mem: 24336 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICPosition.ml src/pCUICTyping.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 21400 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/templateToPCUIC.ml src/pCUICPosition.cmx (real: 0.08, user: 0.06, sys: 0.01, mem: 26048 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICSafeLemmata.ml src/templateToPCUIC.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 26384 ko) src/pCUICSafeLemmata.cmx (real: 0.05, user: 0.02, sys: 0.02, mem: 22084 ko) CAMLC -c src/pCUICSafeReduce.mli CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eAstUtils.ml src/pCUICSafeReduce.cmi (real: 0.06, user: 0.05, sys: 0.01, mem: 21556 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eLiftSubst.ml src/eAstUtils.cmx (real: 0.08, user: 0.05, sys: 0.02, mem: 24800 ko) CAMLC -c src/eTyping.mli src/eTyping.cmi (real: 0.04, user: 0.03, sys: 0.00, mem: 20252 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/extract.ml src/eLiftSubst.cmx (real: 0.07, user: 0.05, sys: 0.02, mem: 25192 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/uGraph0.ml src/extract.cmx (real: 0.07, user: 0.04, sys: 0.02, mem: 23032 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICEquality.ml src/uGraph0.cmx (real: 0.13, user: 0.11, sys: 0.02, mem: 30984 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICTyping.ml src/pCUICEquality.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 26256 ko) CAMLC -c src/pCUICChecker.mli src/pCUICChecker.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 21236 ko) CAMLC -c src/pCUICSafeConversion.mli src/pCUICTyping.cmx (real: 0.11, user: 0.08, sys: 0.03, mem: 27752 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/eTyping.ml src/pCUICSafeConversion.cmi (real: 0.08, user: 0.06, sys: 0.02, mem: 23232 ko) CAMLC -c src/ePretty.mli src/eTyping.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 24684 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICChecker.ml src/ePretty.cmi (real: 0.06, user: 0.04, sys: 0.01, mem: 20540 ko) CAMLC -c src/pCUICPretty.mli src/pCUICPretty.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 20560 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICSafeReduce.ml src/pCUICChecker.cmx (real: 0.07, user: 0.05, sys: 0.02, mem: 25140 ko) CAMLC -c src/pCUICSafeChecker.mli src/pCUICSafeChecker.cmi (real: 0.07, user: 0.05, sys: 0.01, mem: 24300 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/ePretty.ml src/pCUICSafeReduce.cmx (real: 0.09, user: 0.07, sys: 0.02, mem: 27792 ko) CAMLC -c src/erasureFunction.mli src/erasureFunction.cmi (real: 0.08, user: 0.06, sys: 0.01, mem: 22652 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICPretty.ml src/ePretty.cmx (real: 0.11, user: 0.09, sys: 0.02, mem: 26992 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICSafeConversion.ml src/pCUICPretty.cmx (real: 0.11, user: 0.09, sys: 0.02, mem: 29148 ko) CAMLC -c src/pCUICSafeRetyping.mli src/pCUICSafeRetyping.cmi (real: 0.05, user: 0.03, sys: 0.01, mem: 21604 ko) CAMLC -c src/safeErasureFunction.mli src/safeErasureFunction.cmi (real: 0.07, user: 0.05, sys: 0.01, mem: 21660 ko) CAMLC -c src/safeTemplateErasure.mli src/safeTemplateErasure.cmi (real: 0.07, user: 0.05, sys: 0.01, mem: 23148 ko) src/pCUICSafeConversion.cmx (real: 0.31, user: 0.27, sys: 0.03, mem: 43056 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICSafeChecker.ml src/pCUICSafeChecker.cmx (real: 0.37, user: 0.33, sys: 0.03, mem: 45284 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/pCUICSafeRetyping.ml CAMLOPT -c -for-pack Metacoq_erasure_plugin src/erasureFunction.ml src/pCUICSafeRetyping.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 27380 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/safeErasureFunction.ml src/erasureFunction.cmx (real: 0.14, user: 0.11, sys: 0.02, mem: 31208 ko) src/safeErasureFunction.cmx (real: 0.12, user: 0.09, sys: 0.01, mem: 29852 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/safeTemplateErasure.ml src/safeTemplateErasure.cmx (real: 0.09, user: 0.07, sys: 0.02, mem: 30244 ko) CAMLOPT -c -for-pack Metacoq_erasure_plugin src/g_metacoq_erasure.ml src/g_metacoq_erasure.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 30052 ko) CAMLOPT -pack -o src/metacoq_erasure_plugin.cmx src/metacoq_erasure_plugin.cmx (real: 0.12, user: 0.08, sys: 0.03, mem: 32668 ko) CAMLOPT -a -o src/metacoq_erasure_plugin.cmxa src/metacoq_erasure_plugin.cmxa (real: 0.02, user: 0.00, sys: 0.01, mem: 13520 ko) CAMLOPT -shared -o src/metacoq_erasure_plugin.cmxs src/metacoq_erasure_plugin.cmxs (real: 0.17, user: 0.13, sys: 0.03, mem: 20232 ko) ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.41, user: 0.30, sys: 0.11, mem: 237756 ko) make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -C test-suite make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite' rocq makefile -f _CoqProject -o Makefile.coq make -C plugin-demo make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' rocq makefile -f _CoqProject -o Makefile.coq Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.coq pretty-timed make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite' Warning: ../../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.coq make[5]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' ROCQ DEP VFILES ROCQ DEP VFILES *** Warning: in file theories/MyPlugin.v, required library Loader matches several files in path (found Loader.v in ../../template-coq/theories and theories; used the latter) ROCQ compile theories/Lens.v theories/Lens.vo (real: 0.10, user: 0.05, sys: 0.04, mem: 64048 ko) ROCQ compile theories/MyPlugin.v ROCQ compile bug1.v File "./theories/MyPlugin.v", line 10, characters 0-24: Warning: Interpreting this declaration as if a global declaration prefixed by "Local", i.e. as a global declaration which shall not be available without qualification when imported. [local-declaration,scope] theories/MyPlugin.vo (real: 1.20, user: 0.91, sys: 0.28, mem: 513348 ko) ROCQ compile theories/Extraction.v bug1.vo (real: 1.30, user: 1.03, sys: 0.26, mem: 510284 ko) ROCQ compile bug2.v bug2.vo (real: 1.09, user: 0.81, sys: 0.26, mem: 500380 ko) ROCQ compile bug5.v File "./theories/Extraction.v", line 7, characters 0-28: Warning: The extraction is currently set to bypass opacity, the following opaque constant bodies have been accessed : All_Forall.All2_firstn All_Forall.All2_All_mix_right CRelationClasses.PartialOrder_inverse All_Forall.All_All2_All2_mix fold_rec_bis cardinal_inv_2b All_Forall.All_rev All_Forall.All_mix All_Forall.All_map All_Forall.All_app All_Forall.OnOne2_impl_exist_and_All_r Universes.fresh_universe All_Forall.Alli_rev All_Forall.Alli_mix All_Forall.Alli_app All_Forall.Alli_All All_Forall.All_prod All_Forall.All_mapi All_Forall.All_impl All_Forall.All_Alli All_Forall.All_All2 List.Forall_rect All_Forall.All2_sym All_Forall.All2_rev All_Forall.All2_nth All_Forall.All2_mix All_Forall.All2_map All_Forall.All2_app All_Forall.All2_All fold_rec_nodep Universes.Level.eqb_spec All_Forall.Alli_shiftn_inv Universes.fresh_level All_Forall.All2_All_mix_left All_Forall.All2_nth_error_Some_r All_Forall.Alli_nth_error All_Forall.forall_nth_error_All All_Forall.forall_nth_error_Alli All_Forall.All2_nth_error All_Forall.nth_error_all All_Forall.All2_prod_inv All_Forall.Alli_mapi List.nth_in_or_default All_Forall.forallb_nth' CRelationClasses.partial_order_antisym All_Forall.All_skipn CRelationClasses.flip_PreOrder All_Forall.Alli_shiftn All_Forall.Forall_All CRelationClasses.relation_implication_preorder All_Forall.OnOne2_impl_exist_and_All All_Forall.All2i_rev All_Forall.All2i_app All_Forall.All2_symP All_Forall.All2_swap All_Forall.All2_same All_Forall.All2_mapi All_Forall.All2_impl All_Forall.All2_app_inv String.eqb_spec All_Forall.OnOne2_All_mix_left List.exists_last All_Forall.All2i_mapi All_Forall.All2i_impl All_Forall.All_nth_error All_Forall.All_repeat All_Forall.Alli_app_inv All_Forall.All2_trans All_Forall.All2_skipn All_Forall.All2_right All_Forall.All2_eq_eq All_Forall.All2_app_r All_Forall.All_firstn All_Forall.All2_All_right All_Forall.All2_map_left MCOption.option_map_Some CRelationClasses.flip_Reflexive All_Forall.All2_map_right All_Forall.All2_map_left' All_Forall.forallb2_All2 All_Forall.All_app_inv MCList.rev_case CRelationClasses.flip_StrictOrder MCList.nth_error_spec List.destruct_list CRelationClasses.relation_equivalence_equivalence All_Forall.OnOne2_split All_Forall.OnOne2_ind_l All_Forall.OnOne2_exist cardinal_inv_2 All_Forall.All2_All_left All_Forall.OnOne2_mapP All_Forall.OnOne2_impl All_Forall.nth_error_alli Universes.ConstraintType.eq_dec MCList.rev_list_ind In_dec Ascii.eqb_spec All_Forall.All_prod_inv set_induction_min set_induction_max MCCompare.string_Compare All_Forall.All2_nth_error_Some_right MCList.nth_error_Some' All_Forall.map_option_out_All All_Forall.All_rev_map All_Forall.All_rev_inv All_Forall.All_All2_refl CRelationClasses.flip_Antisymmetric All_Forall.All2_app_inv_r fold_rel fold_rec MCCompare.ascii_Compare CRelationClasses.flip_PER All_Forall.Alli_All_mix set_induction All_Forall.All2_mix_inv CRelationClasses.flip_Equivalence All_Forall.forallb_All All_Forall.All2_map_inv MCList.rev_ind All_Forall.All2_right_triv set_induction_bis MCList.list_rect_rev fold_rec_weak BasicAst.ident_eq_spec All_Forall.OnOne2_sym All_Forall.OnOne2_map All_Forall.OnOne2_app All_Forall.All2_from_nth_error All_Forall.map_eq_inj All_Forall.Alli_rev_nth_error All_Forall.All2_map_right' All_Forall.All2_nth_error_Some All_Forall.OnOne2_nth_error All_Forall.All2_All_left_pack All_Forall.All_safe_nth CRelationClasses.subrelation_symmetric MCOption.nth_map_option_out All_Forall.All_map_inv All_Forall.Alli_shift All_Forall.All2_impl_In. [extraction-opaque-accessed,extraction] bug5.vo (real: 1.92, user: 1.62, sys: 0.29, mem: 512080 ko) ROCQ compile bug6.v File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier __top_assumption_ contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier __top_assumption_ contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rect contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rec contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rect contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rec contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rect contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rec contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rect contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] File "./theories/Extraction.v", line 7, characters 0-28: Warning: The identifier t__rec contains __ which is reserved for the extraction [extraction-reserved-identifier,extraction] theories/Extraction.vo (real: 3.67, user: 3.11, sys: 0.54, mem: 561316 ko) make[5]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' cd gen-src && ./to-lower.sh Moving Lens.ml to lens.ml Moving Lens.mli to lens.mli Moving MyPlugin.ml to myPlugin.ml Moving MyPlugin.mli to myPlugin.mli make -f Makefile.plugin make[5]: Entering directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' Makefile.plugin:20: Makefile.plugin.conf: No such file or directory ROCQ DEP VFILES *** Warning: in file test/test.v, required library Loader matches several files in path (found Loader.v in ../../template-coq/theories and theories; used the latter) rocq makefile -f _PluginProject -o Makefile.plugin Warning: ../../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory COQPP src/g_demo_plugin.mlg CAMLDEP gen-src/lens.mli CAMLDEP gen-src/myPlugin.mli OCAMLLIBDEP src/demo_plugin.mlpack CAMLDEP gen-src/lens.ml CAMLDEP gen-src/myPlugin.ml CAMLDEP src/g_demo_plugin.ml CAMLC -c gen-src/lens.mli gen-src/lens.cmi (real: 0.04, user: 0.03, sys: 0.01, mem: 19172 ko) CAMLC -c gen-src/myPlugin.mli gen-src/myPlugin.cmi (real: 0.05, user: 0.04, sys: 0.01, mem: 20208 ko) CAMLOPT -c -for-pack Demo_plugin gen-src/lens.ml gen-src/lens.cmx (real: 0.07, user: 0.04, sys: 0.02, mem: 22124 ko) CAMLOPT -c -for-pack Demo_plugin gen-src/myPlugin.ml bug6.vo (real: 1.11, user: 0.85, sys: 0.25, mem: 500408 ko) ROCQ compile bug7.v gen-src/myPlugin.cmx (real: 0.12, user: 0.10, sys: 0.02, mem: 27228 ko) CAMLOPT -c -for-pack Demo_plugin src/g_demo_plugin.ml src/g_demo_plugin.cmx (real: 0.09, user: 0.06, sys: 0.02, mem: 27844 ko) CAMLOPT -pack -o src/demo_plugin.cmx src/demo_plugin.cmx (real: 0.06, user: 0.04, sys: 0.02, mem: 21964 ko) CAMLOPT -a -o src/demo_plugin.cmxa src/demo_plugin.cmxa (real: 0.02, user: 0.00, sys: 0.01, mem: 13200 ko) CAMLOPT -shared -o src/demo_plugin.cmxs src/demo_plugin.cmxs (real: 0.04, user: 0.01, sys: 0.02, mem: 14256 ko) ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.10, user: 0.05, sys: 0.04, mem: 62308 ko) ROCQ compile test/test.v bug7.vo (real: 1.21, user: 0.89, sys: 0.31, mem: 500252 ko) ROCQ compile bug8.v Notation plus := Nat.add Expands to: Notation Coq.Init.Peano.plus (1 + 2) File "./test/test.v", line 19, characters 0-16: Warning: SSReflect's Search command has been moved to the ssrsearch module; please Require that module if you still want to use SSReflect's Search command [ssr-search-moved,deprecated] x: Point -> nat y: Point -> nat Build_Point: nat -> nat -> Point _y: Lens Point Point nat nat _x: Lens Point Point nat nat test/test.vo (real: 1.51, user: 1.21, sys: 0.29, mem: 513888 ko) make[5]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite/plugin-demo' ROCQ compile bugkncst.v bug8.vo (real: 1.10, user: 0.84, sys: 0.25, mem: 500436 ko) ROCQ compile case.v File "./bugkncst.v", line 12, characters 21-36: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] case.vo (real: 1.12, user: 0.88, sys: 0.23, mem: 500120 ko) ROCQ compile castprop.v castprop.vo (real: 1.23, user: 0.94, sys: 0.28, mem: 510368 ko) ROCQ compile cofix.v cofix.vo (real: 1.11, user: 0.81, sys: 0.29, mem: 500192 ko) ROCQ compile erasure_live_test.v bugkncst.vo (real: 57.89, user: 56.51, sys: 1.14, mem: 896928 ko) ROCQ compile vs.v File "./vs.v", line 91, characters 0-145: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] File "./vs.v", line 1065, characters 1-7: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] File "./vs.v", line 1066, characters 1-7: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] File "./vs.v", line 1486, characters 0-143: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] File "./vs.v", line 1519, characters 0-4: Warning: Cannot define graph(s) for main [funind-cannot-define-graph,funind] File "./vs.v", line 1519, characters 0-4: Warning: Cannot build inversion information [funind-cannot-build-inversion,funind] File "./vs.v", line 1870, characters 0-758: Warning: Not a truly recursive fixpoint. [non-recursive,fixpoints] File "./vs.v", line 2020, characters 0-145: Warning: omega is deprecated since 8.12; use β€œlia” instead. [omega-is-deprecated,deprecated] File "./vs.v", line 2347, characters 0-27: Warning: The extraction is currently set to bypass opacity, the following opaque constant bodies have been accessed : the_loop_terminate main_terminate. [extraction-opaque-accessed,extraction] File "./vs.v", line 2370, characters 0-21: Warning: The extraction is currently set to bypass opacity, the following opaque constant bodies have been accessed : the_loop_terminate main_terminate. [extraction-opaque-accessed,extraction] vs.vo (real: 5.44, user: 4.90, sys: 0.51, mem: 501352 ko) ROCQ compile evars.v evars.vo (real: 1.10, user: 0.79, sys: 0.29, mem: 500100 ko) ROCQ compile extractable.v extractable.vo (real: 1.17, user: 0.88, sys: 0.29, mem: 501748 ko) ROCQ compile hnf_ctor.v hnf_ctor.vo (real: 1.11, user: 0.80, sys: 0.30, mem: 502088 ko) ROCQ compile issue27.v issue27.vo (real: 1.35, user: 1.02, sys: 0.31, mem: 522688 ko) ROCQ compile issue28.v File "./issue28.v", line 31, characters 0-282: Warning: Interpreting this declaration as if a global declaration prefixed by "Local", i.e. as a global declaration which shall not be available without qualification when imported. [local-declaration,scope] issue28.vo (real: 1.35, user: 1.05, sys: 0.29, mem: 522968 ko) ROCQ compile letin.v letin.vo (real: 1.21, user: 0.90, sys: 0.29, mem: 500080 ko) ROCQ compile modules_sections.v modules_sections.vo (real: 1.73, user: 1.35, sys: 0.35, mem: 526276 ko) ROCQ compile mutind.v mutind.vo (real: 1.19, user: 0.89, sys: 0.29, mem: 500068 ko) ROCQ compile opaque.v opaque.vo (real: 1.26, user: 0.94, sys: 0.31, mem: 500016 ko) ROCQ compile proj.v proj.vo (real: 1.52, user: 1.21, sys: 0.29, mem: 524028 ko) ROCQ compile run_in_tactic.v run_in_tactic.vo (real: 1.34, user: 1.03, sys: 0.29, mem: 522996 ko) ROCQ compile safechecker_test.v File "./safechecker_test.v", line 39, characters 0-27: Warning: To avoid stack overflow, large numbers in nat are interpreted as applications of Nat.of_num_uint. [abstract-large-number,numbers] File "./safechecker_test.v", line 54, characters 0-44: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] File "./safechecker_test.v", line 70, characters 0-50: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./safechecker_test.v", line 72, characters 0-45: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] File "./safechecker_test.v", line 88, characters 0-68: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./safechecker_test.v", line 432, characters 0-221: Warning: Ignored instance declaration for β€œe_inv”: β€œforall (A : Type@{Var(0)}) (B : Type@{Var(1)}) (f : A -> B), IsEquiv@{Var(0) Var(1)} f -> B -> A” is not a class [not-a-class,typeclasses] File "./safechecker_test.v", line 440, characters 0-83: Warning: Ignored instance declaration for β€œe_fun”: β€œforall (A : Type@{Var(0)}) (B : Type@{Var(1)}), Equiv@{Var(0) Var(1)} A B -> A -> B” is not a class [not-a-class,typeclasses] safechecker_test.vo (real: 3.34, user: 2.89, sys: 0.44, mem: 726228 ko) ROCQ compile tmExistingInstance.v tmExistingInstance.vo (real: 1.21, user: 0.92, sys: 0.28, mem: 522724 ko) ROCQ compile tmInferInstance.v tmInferInstance.vo (real: 1.30, user: 0.98, sys: 0.31, mem: 522552 ko) ROCQ compile TypingTests.v TypingTests.vo (real: 2.62, user: 2.27, sys: 0.34, mem: 558304 ko) ROCQ compile unfold.v unfold.vo (real: 1.35, user: 1.03, sys: 0.31, mem: 522248 ko) ROCQ compile univ.v univ.vo (real: 1.28, user: 0.99, sys: 0.28, mem: 522992 ko) ROCQ compile tmVariable.v tmVariable.vo (real: 1.31, user: 1.01, sys: 0.29, mem: 524932 ko) ROCQ compile order_rec.v order_rec.vo (real: 1.41, user: 1.09, sys: 0.30, mem: 525128 ko) ROCQ compile erasure_test.v erasure_live_test.vo (real: 88.03, user: 86.21, sys: 1.46, mem: 1038900 ko) File "./erasure_test.v", line 44, characters 0-27: Warning: To avoid stack overflow, large numbers in nat are interpreted as applications of Nat.of_num_uint. [abstract-large-number,numbers] erasure_test.vo (real: 1.42, user: 1.10, sys: 0.31, mem: 543584 ko) Time | Peak Mem | File Name --------------------------------------------- 2m59.43s | 1038900 ko | Total Time / Peak Mem --------------------------------------------- 1m26.21s | 1038900 ko | erasure_live_test.vo 0m56.51s | 896928 ko | bugkncst.vo 0m04.90s | 501352 ko | vs.vo 0m02.89s | 726228 ko | safechecker_test.vo 0m02.27s | 558304 ko | TypingTests.vo 0m01.62s | 512080 ko | bug5.vo 0m01.35s | 526276 ko | modules_sections.vo 0m01.21s | 524028 ko | proj.vo 0m01.10s | 543584 ko | erasure_test.vo 0m01.09s | 525128 ko | order_rec.vo 0m01.05s | 522968 ko | issue28.vo 0m01.03s | 510284 ko | bug1.vo 0m01.03s | 522996 ko | run_in_tactic.vo 0m01.03s | 522248 ko | unfold.vo 0m01.02s | 522688 ko | issue27.vo 0m01.01s | 524932 ko | tmVariable.vo 0m00.99s | 522992 ko | univ.vo 0m00.98s | 522552 ko | tmInferInstance.vo 0m00.94s | 510368 ko | castprop.vo 0m00.94s | 500016 ko | opaque.vo 0m00.92s | 522724 ko | tmExistingInstance.vo 0m00.90s | 500080 ko | letin.vo 0m00.89s | 500252 ko | bug7.vo 0m00.89s | 500068 ko | mutind.vo 0m00.88s | 500120 ko | case.vo 0m00.88s | 501748 ko | extractable.vo 0m00.85s | 500408 ko | bug6.vo 0m00.84s | 500436 ko | bug8.vo 0m00.81s | 500380 ko | bug2.vo 0m00.81s | 500192 ko | cofix.vo 0m00.80s | 502088 ko | hnf_ctor.vo 0m00.79s | 500100 ko | evars.vo make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/test-suite' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq' make[1]: Leaving directory '/builds/coq/coq/_build_ci/metacoq' + make install + '[' -z x ']' + command make install + make install make[1]: Entering directory '/builds/coq/coq/_build_ci/metacoq' make -C template-coq make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.coq make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Nothing to be done for 'real-all'. ./update_plugin.sh Updating gen-src from src Copying from src to gen-src Renaming files to camelCase patching file gen-src/cRelationClasses.mli Reversed (or previously applied) patch detected! Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file gen-src/cRelationClasses.mli.rej make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.template optfiles make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Nothing to be done for 'optfiles'. make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' cp src/template_coq.cm* build/ make -f Makefile.template make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Nothing to be done for 'real-all'. make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' CAMLDEP gen-src/univSubst0.mli CAMLDEP gen-src/universes0.mli CAMLDEP gen-src/string0.mli CAMLDEP gen-src/run_extractable.mli CAMLDEP gen-src/specif.mli CAMLDEP gen-src/pretty.mli CAMLDEP gen-src/plugin_core.mli CAMLDEP gen-src/peanoNat.mli CAMLDEP gen-src/ordersTac.mli CAMLDEP gen-src/orders.mli CAMLDEP gen-src/ordersLists.mli CAMLDEP gen-src/ordersFacts.mli CAMLDEP gen-src/orderedType0.mli CAMLDEP gen-src/numeral.mli CAMLDEP gen-src/nat0.mli CAMLDEP gen-src/mSetProperties.mli CAMLDEP gen-src/mSetList.mli CAMLDEP gen-src/mSetInterface.mli CAMLDEP gen-src/mSetFacts.mli CAMLDEP gen-src/mSetDecide.mli CAMLDEP gen-src/mCString.mli CAMLDEP gen-src/mCRelations.mli CAMLDEP gen-src/mCProd.mli CAMLDEP gen-src/mCOption.mli CAMLDEP gen-src/mCList.mli CAMLDEP gen-src/mCCompare.mli CAMLDEP gen-src/mCPrelude.mli CAMLDEP gen-src/logic0.mli CAMLDEP gen-src/list0.mli CAMLDEP gen-src/liftSubst.mli CAMLDEP gen-src/hexadecimal.mli CAMLDEP gen-src/extractable.mli CAMLDEP gen-src/equalities.mli CAMLDEP gen-src/environment.mli CAMLDEP gen-src/decimal.mli CAMLDEP gen-src/datatypes.mli CAMLDEP gen-src/cRelationClasses.mli CAMLDEP gen-src/config0.mli CAMLDEP gen-src/compare_dec.mli CAMLDEP gen-src/common0.mli CAMLDEP gen-src/bool.mli CAMLDEP gen-src/binPos.mli CAMLDEP gen-src/binPosDef.mli CAMLDEP gen-src/binNums.mli CAMLDEP gen-src/binNat.mli CAMLDEP gen-src/binInt.mli CAMLDEP gen-src/basics.mli CAMLDEP gen-src/basicAst.mli CAMLDEP gen-src/astUtils.mli CAMLDEP gen-src/ast0.mli CAMLDEP gen-src/ascii.mli CAMLDEP gen-src/all_Forall.mli OCAMLLIBDEP gen-src/metacoq_template_plugin.mlpack CAMLDEP gen-src/univSubst0.ml CAMLDEP gen-src/universes0.ml CAMLDEP gen-src/tm_util.ml CAMLDEP gen-src/string0.ml CAMLDEP gen-src/specif.ml CAMLDEP gen-src/run_extractable.ml CAMLDEP gen-src/quoter.ml CAMLDEP gen-src/reification.ml CAMLDEP gen-src/pretty.ml CAMLDEP gen-src/plugin_core.ml CAMLDEP gen-src/peanoNat.ml CAMLDEP gen-src/ordersTac.ml CAMLDEP gen-src/orders.ml CAMLDEP gen-src/ordersLists.ml CAMLDEP gen-src/ordersFacts.ml CAMLDEP gen-src/orderedType0.ml CAMLDEP gen-src/numeral.ml CAMLDEP gen-src/nat0.ml CAMLDEP gen-src/mSetProperties.ml CAMLDEP gen-src/mSetList.ml CAMLDEP gen-src/mSetInterface.ml CAMLDEP gen-src/mSetFacts.ml CAMLDEP gen-src/mSetDecide.ml CAMLDEP gen-src/mCString.ml CAMLDEP gen-src/mCRelations.ml CAMLDEP gen-src/mCProd.ml CAMLDEP gen-src/mCOption.ml CAMLDEP gen-src/mCList.ml CAMLDEP gen-src/mCCompare.ml CAMLDEP gen-src/mCPrelude.ml CAMLDEP gen-src/logic0.ml CAMLDEP gen-src/list0.ml CAMLDEP gen-src/liftSubst.ml CAMLDEP gen-src/hexadecimal.ml CAMLDEP gen-src/extractable.ml CAMLDEP gen-src/equalities.ml CAMLDEP gen-src/environment.ml CAMLDEP gen-src/denoter.ml CAMLDEP gen-src/decimal.ml CAMLDEP gen-src/datatypes.ml CAMLDEP gen-src/cRelationClasses.ml CAMLDEP gen-src/config0.ml CAMLDEP gen-src/compare_dec.ml CAMLDEP gen-src/common0.ml CAMLDEP gen-src/bool.ml CAMLDEP gen-src/binPos.ml CAMLDEP gen-src/binPosDef.ml CAMLDEP gen-src/binNums.ml CAMLDEP gen-src/binNat.ml CAMLDEP gen-src/binInt.ml CAMLDEP gen-src/basics.ml CAMLDEP gen-src/basicAst.ml CAMLDEP gen-src/astUtils.ml CAMLDEP gen-src/ast_quoter.ml CAMLDEP gen-src/ast_denoter.ml CAMLDEP gen-src/ast0.ml CAMLDEP gen-src/ascii.ml CAMLDEP gen-src/all_Forall.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/tm_util.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/reification.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/reification.cmx (real: 0.03, user: 0.01, sys: 0.01, mem: 14744 ko) CAMLC -c gen-src/plugin_core.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/plugin_core.cmi (real: 0.02, user: 0.01, sys: 0.01, mem: 17304 ko) CAMLC -c gen-src/tm_util.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/tm_util.cmx (real: 0.08, user: 0.04, sys: 0.03, mem: 21988 ko) CAMLC -c gen-src/reification.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/reification.cmo (real: 0.01, user: 0.00, sys: 0.01, mem: 11896 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/tm_util.cmo (real: 0.04, user: 0.03, sys: 0.01, mem: 18588 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/denoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/denoter.cmx (real: 0.08, user: 0.06, sys: 0.02, mem: 24368 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/plugin_core.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/plugin_core.cmx (real: 0.10, user: 0.07, sys: 0.02, mem: 27576 ko) gen-src/quoter.cmx (real: 0.20, user: 0.16, sys: 0.03, mem: 34528 ko) CAMLC -c gen-src/quoter.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/quoter.cmo (real: 0.12, user: 0.09, sys: 0.02, mem: 26444 ko) CAMLC -c gen-src/ast_quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_quoter.cmx (real: 0.12, user: 0.09, sys: 0.03, mem: 27268 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_denoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_quoter.cmo (real: 0.07, user: 0.05, sys: 0.02, mem: 22532 ko) CAMLC -c gen-src/run_extractable.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 13788 ko) gen-src/ast_denoter.cmx (real: 0.09, user: 0.07, sys: 0.02, mem: 27192 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/run_extractable.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmx (real: 0.14, user: 0.11, sys: 0.02, mem: 30592 ko) CAMLOPT -pack -o gen-src/metacoq_template_plugin.cmx findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmx (real: 0.21, user: 0.09, sys: 0.04, mem: 31480 ko) CAMLOPT -a -o gen-src/metacoq_template_plugin.cmxa findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxa (real: 0.03, user: 0.01, sys: 0.02, mem: 13916 ko) CAMLOPT -shared -o gen-src/metacoq_template_plugin.cmxs findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxs (real: 0.14, user: 0.10, sys: 0.03, mem: 18520 ko) ROCQ compile theories/ExtractableLoader.v theories/ExtractableLoader.vo (real: 0.10, user: 0.06, sys: 0.04, mem: 62624 ko) cp gen-src/metacoq_template_plugin.cm* build/ make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -C checker make -C pcuic make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make -f Makefile.coq make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -f Makefile.pcuic make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[4]: Nothing to be done for 'real-all'. ./update_plugin.sh Renaming extracted files make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make -C examples make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/examples' make -f Makefile.coq pretty-timed make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/examples' make[4]: Nothing to be done for 'real-all'. # echo "All done, moving extraction files!" # ./clean_extraction.sh make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -C safechecker make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.safechecker make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[6]: Nothing to be done for 'real-all'. make[4]: Nothing to be done for 'real-all'. echo "Done extracting the safe checker, moving extraction files!" Done extracting the safe checker, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' Time | Peak Mem | File Name -------------------------------------------- 0m22.62s | 581920 ko | Total Time / Peak Mem -------------------------------------------- 0m19.93s | 581920 ko | tauto.vo 0m01.56s | 527740 ko | demo.vo 0m01.13s | 524144 ko | add_constructor.vo make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/examples' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/examples' ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.11, user: 0.07, sys: 0.03, mem: 63372 ko) make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -C erasure make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -f Makefile.erasure make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[4]: Nothing to be done for 'real-all'. echo "Done extracting the erasure, moving extraction files!" Done extracting the erasure, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.44, user: 0.28, sys: 0.15, mem: 237408 ko) make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -C template-coq install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.coq make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Nothing to be done for 'real-all'. ./update_plugin.sh Updating gen-src from src Copying from src to gen-src Renaming files to camelCase patching file gen-src/cRelationClasses.mli Reversed (or previously applied) patch detected! Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file gen-src/cRelationClasses.mli.rej make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.template optfiles make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Nothing to be done for 'optfiles'. make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' cp src/template_coq.cm* build/ make -f Makefile.template make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Nothing to be done for 'real-all'. make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' CAMLDEP gen-src/univSubst0.mli CAMLDEP gen-src/universes0.mli CAMLDEP gen-src/string0.mli CAMLDEP gen-src/specif.mli CAMLDEP gen-src/run_extractable.mli CAMLDEP gen-src/pretty.mli CAMLDEP gen-src/plugin_core.mli CAMLDEP gen-src/peanoNat.mli CAMLDEP gen-src/ordersTac.mli CAMLDEP gen-src/orders.mli CAMLDEP gen-src/ordersLists.mli CAMLDEP gen-src/ordersFacts.mli CAMLDEP gen-src/orderedType0.mli CAMLDEP gen-src/numeral.mli CAMLDEP gen-src/nat0.mli CAMLDEP gen-src/mSetProperties.mli CAMLDEP gen-src/mSetList.mli CAMLDEP gen-src/mSetFacts.mli CAMLDEP gen-src/mSetInterface.mli CAMLDEP gen-src/mSetDecide.mli CAMLDEP gen-src/mCString.mli CAMLDEP gen-src/mCRelations.mli CAMLDEP gen-src/mCProd.mli CAMLDEP gen-src/mCOption.mli CAMLDEP gen-src/mCList.mli CAMLDEP gen-src/mCCompare.mli CAMLDEP gen-src/mCPrelude.mli CAMLDEP gen-src/logic0.mli CAMLDEP gen-src/list0.mli CAMLDEP gen-src/liftSubst.mli CAMLDEP gen-src/hexadecimal.mli CAMLDEP gen-src/extractable.mli CAMLDEP gen-src/equalities.mli CAMLDEP gen-src/environment.mli CAMLDEP gen-src/decimal.mli CAMLDEP gen-src/datatypes.mli CAMLDEP gen-src/cRelationClasses.mli CAMLDEP gen-src/config0.mli CAMLDEP gen-src/compare_dec.mli CAMLDEP gen-src/common0.mli CAMLDEP gen-src/bool.mli CAMLDEP gen-src/binPos.mli CAMLDEP gen-src/binPosDef.mli CAMLDEP gen-src/binNums.mli CAMLDEP gen-src/binNat.mli CAMLDEP gen-src/binInt.mli CAMLDEP gen-src/basics.mli CAMLDEP gen-src/basicAst.mli CAMLDEP gen-src/astUtils.mli CAMLDEP gen-src/ast0.mli CAMLDEP gen-src/ascii.mli CAMLDEP gen-src/all_Forall.mli OCAMLLIBDEP gen-src/metacoq_template_plugin.mlpack CAMLDEP gen-src/univSubst0.ml CAMLDEP gen-src/universes0.ml CAMLDEP gen-src/tm_util.ml CAMLDEP gen-src/string0.ml CAMLDEP gen-src/specif.ml CAMLDEP gen-src/run_extractable.ml CAMLDEP gen-src/quoter.ml CAMLDEP gen-src/reification.ml CAMLDEP gen-src/pretty.ml CAMLDEP gen-src/plugin_core.ml CAMLDEP gen-src/peanoNat.ml CAMLDEP gen-src/ordersTac.ml CAMLDEP gen-src/orders.ml CAMLDEP gen-src/ordersLists.ml CAMLDEP gen-src/ordersFacts.ml CAMLDEP gen-src/orderedType0.ml CAMLDEP gen-src/numeral.ml CAMLDEP gen-src/nat0.ml CAMLDEP gen-src/mSetProperties.ml CAMLDEP gen-src/mSetList.ml CAMLDEP gen-src/mSetInterface.ml CAMLDEP gen-src/mSetFacts.ml CAMLDEP gen-src/mSetDecide.ml CAMLDEP gen-src/mCString.ml CAMLDEP gen-src/mCRelations.ml CAMLDEP gen-src/mCProd.ml CAMLDEP gen-src/mCOption.ml CAMLDEP gen-src/mCList.ml CAMLDEP gen-src/mCCompare.ml CAMLDEP gen-src/mCPrelude.ml CAMLDEP gen-src/logic0.ml CAMLDEP gen-src/list0.ml CAMLDEP gen-src/liftSubst.ml CAMLDEP gen-src/hexadecimal.ml CAMLDEP gen-src/extractable.ml CAMLDEP gen-src/equalities.ml CAMLDEP gen-src/environment.ml CAMLDEP gen-src/denoter.ml CAMLDEP gen-src/decimal.ml CAMLDEP gen-src/datatypes.ml CAMLDEP gen-src/cRelationClasses.ml CAMLDEP gen-src/config0.ml CAMLDEP gen-src/compare_dec.ml CAMLDEP gen-src/common0.ml CAMLDEP gen-src/bool.ml CAMLDEP gen-src/binPos.ml CAMLDEP gen-src/binPosDef.ml CAMLDEP gen-src/binNums.ml CAMLDEP gen-src/binNat.ml CAMLDEP gen-src/binInt.ml CAMLDEP gen-src/basics.ml CAMLDEP gen-src/astUtils.ml CAMLDEP gen-src/basicAst.ml CAMLDEP gen-src/ast_denoter.ml CAMLDEP gen-src/ast_quoter.ml CAMLDEP gen-src/ast0.ml CAMLDEP gen-src/ascii.ml CAMLDEP gen-src/all_Forall.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/reification.ml CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/tm_util.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/reification.cmx (real: 0.02, user: 0.01, sys: 0.01, mem: 14740 ko) CAMLC -c gen-src/plugin_core.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/plugin_core.cmi (real: 0.03, user: 0.02, sys: 0.00, mem: 17196 ko) CAMLC -c gen-src/tm_util.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/tm_util.cmx (real: 0.08, user: 0.04, sys: 0.02, mem: 22136 ko) CAMLC -c gen-src/reification.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/reification.cmo (real: 0.02, user: 0.01, sys: 0.00, mem: 11760 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/quoter.ml gen-src/tm_util.cmo (real: 0.04, user: 0.02, sys: 0.01, mem: 18448 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/denoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/denoter.cmx (real: 0.12, user: 0.08, sys: 0.02, mem: 24324 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/plugin_core.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/quoter.cmx (real: 0.22, user: 0.19, sys: 0.03, mem: 34468 ko) CAMLC -c gen-src/quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/quoter.cmo (real: 0.12, user: 0.10, sys: 0.01, mem: 26404 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/plugin_core.cmx (real: 0.28, user: 0.07, sys: 0.03, mem: 27504 ko) CAMLC -c gen-src/ast_quoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_quoter.cmo (real: 0.09, user: 0.05, sys: 0.02, mem: 22440 ko) CAMLC -c gen-src/run_extractable.mli findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmi (real: 0.02, user: 0.01, sys: 0.00, mem: 13824 ko) gen-src/ast_quoter.cmx (real: 0.20, user: 0.10, sys: 0.03, mem: 27364 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/ast_denoter.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/ast_denoter.cmx (real: 0.19, user: 0.08, sys: 0.03, mem: 27288 ko) CAMLOPT -c -for-pack Metacoq_template_plugin gen-src/run_extractable.ml findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/run_extractable.cmx (real: 0.18, user: 0.09, sys: 0.03, mem: 30504 ko) CAMLOPT -pack -o gen-src/metacoq_template_plugin.cmx findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmx (real: 0.18, user: 0.11, sys: 0.04, mem: 31632 ko) CAMLOPT -a -o gen-src/metacoq_template_plugin.cmxa findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxa (real: 0.05, user: 0.01, sys: 0.02, mem: 14056 ko) CAMLOPT -shared -o gen-src/metacoq_template_plugin.cmxs findlib: [WARNING] Interface numeral.cmi occurs in several directories: /builds/coq/coq/_install_ci/lib/coq/plugins/syntax, gen-src gen-src/metacoq_template_plugin.cmxs (real: 0.15, user: 0.10, sys: 0.04, mem: 18416 ko) ROCQ compile theories/ExtractableLoader.v theories/ExtractableLoader.vo (real: 0.09, user: 0.04, sys: 0.04, mem: 62716 ko) cp gen-src/metacoq_template_plugin.cm* build/ make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.coq install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' INSTALL theories/utils/MCPrelude.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/All_Forall.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCArith.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCCompare.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCEquality.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/LibHypsNaming.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCList.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCOption.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCProd.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCRelations.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCSquash.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCString.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/wGraph.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/common/uGraph.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//common INSTALL theories/utils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/config.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Universes.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/BasicAst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Environment.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Ast.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/AstUtils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Induction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/LiftSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/UnivSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Pretty.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/EnvironmentTyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/WfInv.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Typing.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TypingWf.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad/Common.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Core.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Extractable.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/monad_utils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Constants.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Extraction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/utils/MCPrelude.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/All_Forall.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCArith.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCCompare.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCEquality.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/LibHypsNaming.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCList.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCOption.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCProd.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCRelations.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCSquash.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCString.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/wGraph.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/common/uGraph.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//common INSTALL theories/utils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/config.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Universes.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/BasicAst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Environment.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Ast.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/AstUtils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Induction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/LiftSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/UnivSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Pretty.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/EnvironmentTyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/WfInv.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Typing.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TypingWf.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad/Common.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Core.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Extractable.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/monad_utils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Constants.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Extraction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/utils/MCPrelude.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/All_Forall.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCArith.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCCompare.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCEquality.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/LibHypsNaming.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCList.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCOption.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCProd.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCRelations.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCSquash.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/MCString.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/utils/wGraph.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//utils INSTALL theories/common/uGraph.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//common INSTALL theories/utils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/config.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Universes.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/BasicAst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Environment.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Ast.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/AstUtils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Induction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/LiftSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/UnivSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Pretty.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/EnvironmentTyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/WfInv.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Typing.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TypingWf.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/TemplateMonad/Common.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Core.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/TemplateMonad/Extractable.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template//TemplateMonad INSTALL theories/monad_utils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Constants.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Extraction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.template install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' INSTALL theories/Loader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/All.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Loader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/All.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/Loader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/All.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL src/template_coq.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL src/template_coq.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL src/template_coq.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL src/template_coq.cmxa /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL src/template_coq.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -f Makefile.plugin install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' INSTALL theories/ExtractableLoader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/ExtractableLoader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL theories/ExtractableLoader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/mCPrelude.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/metacoq_template_plugin.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/mCPrelude.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/metacoq_template_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/metacoq_template_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/metacoq_template_plugin.cmxa /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/mCPrelude.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ INSTALL gen-src/metacoq_template_plugin.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Template/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/template-coq' make -C checker install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make -f Makefile.coq make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make[4]: Nothing to be done for 'real-all'. ./update_plugin.sh Renaming extracted files make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make -f Makefile.coq install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' INSTALL theories/Reflect.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Generation.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WeakeningEnv.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Closed.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Weakening.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Substitution.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Checker.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WcbvEval.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Retyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Normal.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/All.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Reflect.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Generation.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WeakeningEnv.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Closed.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Weakening.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Substitution.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Checker.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WcbvEval.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Retyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Normal.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/All.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Reflect.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Generation.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WeakeningEnv.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Closed.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Weakening.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Substitution.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Checker.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/WcbvEval.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Retyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/Normal.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ INSTALL theories/All.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Checker/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/checker' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' # make -f Makefile.plugin install make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/checker' make -C pcuic install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -f Makefile.pcuic make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[4]: Nothing to be done for 'real-all'. # echo "All done, moving extraction files!" # ./clean_extraction.sh make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -f Makefile.pcuic install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' INSTALL theories/PCUICUtils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSize.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAstUtils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReflect.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICLiftSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICTyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPosition.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNormal.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNameless.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICEquality.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakeningEnv.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICClosed.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakening.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubstitution.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSubstitution.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCumulativity.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReductionConfluence.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConfluence.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContextConversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICGeneration.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAlpha.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPrincipality.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCtxShape.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContexts.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICArities.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSpine.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductives.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICValidity.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductiveInversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSR.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICMetaTheory.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWcbvEval.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICChecker.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPretty.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCheckerCompleteness.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICRetyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICElimination.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSN.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSigmaCalculus.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSafeLemmata.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUIC.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUICCorrectness.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplate.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplateCorrectness.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUtils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSize.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAstUtils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReflect.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICLiftSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICTyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPosition.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNormal.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNameless.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICEquality.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakeningEnv.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICClosed.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakening.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubstitution.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSubstitution.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCumulativity.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReductionConfluence.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConfluence.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContextConversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICGeneration.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAlpha.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPrincipality.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCtxShape.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContexts.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICArities.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSpine.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductives.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICValidity.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductiveInversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSR.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICMetaTheory.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWcbvEval.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICChecker.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPretty.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCheckerCompleteness.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICRetyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICElimination.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSN.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSigmaCalculus.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSafeLemmata.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUIC.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUICCorrectness.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplate.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplateCorrectness.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUtils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSize.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAstUtils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReflect.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICLiftSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICTyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPosition.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNormal.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICNameless.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICEquality.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakeningEnv.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICClosed.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWeakening.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICUnivSubstitution.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSubstitution.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCumulativity.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICReduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICParallelReductionConfluence.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConfluence.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContextConversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICConversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICGeneration.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICAlpha.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPrincipality.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCtxShape.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICContexts.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICArities.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSpine.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductives.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICValidity.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICInductiveInversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSR.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICMetaTheory.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICWcbvEval.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICChecker.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICPretty.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICCheckerCompleteness.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICRetyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICElimination.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSN.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSigmaCalculus.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICSafeLemmata.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUIC.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/TemplateToPCUICCorrectness.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplate.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ INSTALL theories/PCUICToTemplateCorrectness.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/PCUIC/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' # make -f Makefile.plugin install make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/pcuic' make -C safechecker install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.safechecker make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[4]: Nothing to be done for 'real-all'. echo "Done extracting the safe checker, moving extraction files!" Done extracting the safe checker, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.12, user: 0.07, sys: 0.04, mem: 63996 ko) make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.safechecker install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' INSTALL theories/PCUICSafeReduce.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeConversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeChecker.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/SafeTemplateChecker.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeRetyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/Extraction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeReduce.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeConversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeChecker.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/SafeTemplateChecker.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeRetyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/Extraction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeReduce.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeConversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeChecker.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/SafeTemplateChecker.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/PCUICSafeRetyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/Extraction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -f Makefile.plugin install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' INSTALL theories/Loader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/Loader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL theories/Loader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL src/metacoq_safechecker_plugin.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL src/metacoq_safechecker_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL src/metacoq_safechecker_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL src/metacoq_safechecker_plugin.cmxa /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ INSTALL src/metacoq_safechecker_plugin.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/SafeChecker/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/safechecker' make -C erasure install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -f Makefile.erasure make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[4]: Nothing to be done for 'real-all'. echo "Done extracting the erasure, moving extraction files!" Done extracting the erasure, moving extraction files! ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' ./clean_extraction.sh Cleaning result of extraction Extraction up-to date make -f Makefile.plugin make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' ROCQ compile theories/Loader.v theories/Loader.vo (real: 0.45, user: 0.29, sys: 0.15, mem: 238116 ko) make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -f Makefile.erasure install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' INSTALL theories/EAst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAstUtils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInduction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ELiftSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EPretty.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ECSubst.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWcbvEval.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWndEval.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ETyping.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extract.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAll.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extraction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Prelim.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ESubstitution.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInversion.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EArities.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureCorrectness.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureFunction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeErasureFunction.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeTemplateErasure.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAstUtils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInduction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ELiftSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EPretty.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ECSubst.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWcbvEval.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWndEval.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ETyping.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extract.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAll.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extraction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Prelim.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ESubstitution.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInversion.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EArities.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureCorrectness.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureFunction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeErasureFunction.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeTemplateErasure.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAstUtils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInduction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ELiftSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EPretty.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ECSubst.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWcbvEval.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EWndEval.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ETyping.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extract.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EAll.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Extraction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Prelim.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ESubstitution.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EInversion.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/EArities.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureCorrectness.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/ErasureFunction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeErasureFunction.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/SafeTemplateErasure.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -f Makefile.plugin install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' INSTALL theories/Loader.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Loader.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL theories/Loader.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL src/metacoq_erasure_plugin.cmi /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL src/metacoq_erasure_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL src/metacoq_erasure_plugin.cmxs /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL src/metacoq_erasure_plugin.cmxa /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ INSTALL src/metacoq_erasure_plugin.cmx /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Erasure/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/erasure' make -C translations install make[2]: Entering directory '/builds/coq/coq/_build_ci/metacoq/translations' cat metacoq-config > _CoqProject cat _CoqProject.in >> _CoqProject rocq makefile -f _CoqProject -o Makefile.coq Warning: ../template-coq/theories (used in -R or -Q) is not a subdirectory of the current directory make -f Makefile.coq pretty-timed make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/translations' ROCQ DEP VFILES *** Warning: in file sigma.v, required library Loader matches several files in path (found Loader.v in ../template-coq/theories and ../checker/theories; used the latter) ROCQ compile sigma.v ROCQ compile MiniHoTT.v File "./MiniHoTT.v", line 37, characters 0-198: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT.v", line 41, characters 0-64: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT.v", line 96, characters 0-37: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope equiv_scope.". [undeclared-scope,deprecated] File "./MiniHoTT.v", line 98, characters 0-35: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope path_scope.". [undeclared-scope,deprecated] File "./MiniHoTT.v", line 99, characters 0-45: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope fibration_scope.". [undeclared-scope,deprecated] File "./MiniHoTT.v", line 100, characters 0-37: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope trunc_scope.". [undeclared-scope,deprecated] File "./MiniHoTT.v", line 136, characters 0-21: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./MiniHoTT.v", line 139, characters 0-52: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT.v", line 140, characters 0-45: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] sigma.vo (real: 1.17, user: 0.86, sys: 0.30, mem: 500064 ko) ROCQ compile MiniHoTT_paths.v File "./MiniHoTT_paths.v", line 41, characters 0-198: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT_paths.v", line 45, characters 0-64: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT_paths.v", line 100, characters 0-37: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope equiv_scope.". [undeclared-scope,deprecated] File "./MiniHoTT_paths.v", line 102, characters 0-35: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope path_scope.". [undeclared-scope,deprecated] File "./MiniHoTT_paths.v", line 103, characters 0-45: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope fibration_scope.". [undeclared-scope,deprecated] File "./MiniHoTT_paths.v", line 104, characters 0-37: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope trunc_scope.". [undeclared-scope,deprecated] File "./MiniHoTT_paths.v", line 140, characters 0-21: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./MiniHoTT_paths.v", line 143, characters 0-52: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./MiniHoTT_paths.v", line 144, characters 0-45: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] MiniHoTT_paths.vo (real: 3.65, user: 3.42, sys: 0.20, mem: 350716 ko) ROCQ compile translation_utils.v MiniHoTT.vo (real: 4.94, user: 4.41, sys: 0.50, mem: 348856 ko) translation_utils.vo (real: 2.16, user: 1.82, sys: 0.33, mem: 554420 ko) ROCQ compile param_original.v ROCQ compile param_cheap_packed.v Coq.Init.Datatypes.nat has been translated. Coq.Init.Datatypes.list has been translated. listα΅— : forall A : TYPE, list A.1 -> Type : forall A : TYPE, list A.1 -> Type nilα΅— : forall A : TYPE, listα΅— A [] : forall A : TYPE, listα΅— A [] consα΅— : forall (A : TYPE) (x : El A) (lH : βˆƒ l : list A.1, listα΅— A l), listα΅— A (x.1 :: lH.1) : forall (A : TYPE) (x : El A) (lH : βˆƒ l : list A.1, listα΅— A l), listα΅— A (x.1 :: lH.1) param_cheap_packed.vo (real: 1.82, user: 1.49, sys: 0.32, mem: 553352 ko) ROCQ compile param_generous_packed.v "T has been translated as Tα΅—" "tm has been translated as tmα΅—" Coq.Init.Datatypes.nat has been translated. Coq.Init.Datatypes.bool has been translated. "pred has been translated as predα΅—" "ID has been translated as IDα΅—" "toto has been translated as totoα΅—" "my_id has been translated as my_idα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq has been translated." "Translating MetaCoq.Translations.param_original.Id2.ID" "ID has been translated as IDα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating Coq.Init.Logic.eq_trans" "eq_trans has been translated as eq_transα΅—" "Translating Coq.Init.Logic.eq_sym" "eq_sym has been translated as eq_symα΅—" "Translating MetaCoq.Translations.param_original.Id2.ID" "MetaCoq.Translations.param_original.Id2.ID was already translated" "Translating MetaCoq.Translations.param_original.Id2.myf" "myf has been translated as myfα΅—" Coq.Vectors.VectorDef.t has been translated. Coq.Arith.Even.even has been translated. File "./param_generous_packed.v", line 7, characters 0-30: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./param_generous_packed.v", line 7, characters 0-30: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./param_generous_packed.v", line 7, characters 0-30: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./param_generous_packed.v", line 7, characters 0-30: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] Coq.Init.Datatypes.list has been translated. "rev_type has been translated as rev_typeα΅—" Fresh universe MetaCoq.Translations.param_generous_packed.603 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.604 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.605 was added to the context. "Ty has been translated as Tyα΅—" Tyα΅— : El Tyα΅— : El Tyα΅— File "./param_original.v", line 261, characters 0-24: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./param_original.v", line 261, characters 0-24: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./param_original.v", line 261, characters 0-24: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./param_original.v", line 261, characters 0-24: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] "sigT has been translated as sigTα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq has been translated." "Translating MetaCoq.Translations.MiniHoTT.paths" "paths has been translated as pathsα΅—" "existT has been translated as existTα΅—" "Translating MetaCoq.Translations.param_original.Axioms.UIP" "UIP has been translated as UIPα΅—" "wFunext has been translated as wFunextα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.MiniHoTT.Sect" "Sect has been translated as Sectα΅—" "Translating MetaCoq.Translations.MiniHoTT.idpath" "idpath has been translated as idpathα΅—" "Translating MetaCoq.Translations.MiniHoTT.paths_ind" "paths_ind has been translated as paths_indα΅—" "Translating MetaCoq.Translations.MiniHoTT.transport" "transport has been translated as transportα΅—" Finished transaction in 1.071 secs (0.906u,0.16s) (successful) "Translating MetaCoq.Translations.MiniHoTT.ap" "ap has been translated as apα΅—" "sigT_ind has been translated as sigT_indα΅—" "Translating MetaCoq.Translations.MiniHoTT.IsEquiv" "MetaCoq.Translations.MiniHoTT.IsEquiv has been translated." "paths has been translated as pathsα΅—" "idpath has been translated as idpathα΅—" "Translating MetaCoq.Translations.MiniHoTT.Equiv" "MetaCoq.Translations.MiniHoTT.Equiv has been translated." "paths_ind has been translated as paths_indα΅—" "Translating MetaCoq.Translations.param_original.Axioms.wUnivalence" "wUnivalence has been translated as wUnivalenceα΅—" Fresh universe MetaCoq.Translations.param_generous_packed.696 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.697 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.698 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.699 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.700 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.701 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.702 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.703 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.704 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.705 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.706 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.707 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.708 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.709 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.710 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.711 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.712 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.713 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.714 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.715 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.716 was added to the context. "Funext has been translated as Funextα΅—" Fresh universe MetaCoq.Translations.param_generous_packed.728 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.729 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.730 was added to the context. "FALSE has been translated as FALSEα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.MiniHoTT.Sect" "MetaCoq.Translations.MiniHoTT.Sect was already translated" "Translating MetaCoq.Translations.MiniHoTT.idpath" "MetaCoq.Translations.MiniHoTT.idpath was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths_ind" "MetaCoq.Translations.MiniHoTT.paths_ind was already translated" "Translating MetaCoq.Translations.MiniHoTT.transport" "MetaCoq.Translations.MiniHoTT.transport was already translated" "Translating MetaCoq.Translations.MiniHoTT.ap" "MetaCoq.Translations.MiniHoTT.ap was already translated" "UIP has been translated as UIPα΅—" "Translating MetaCoq.Translations.MiniHoTT.IsEquiv" "MetaCoq.Translations.MiniHoTT.IsEquiv was already translated" "Translating MetaCoq.Translations.param_original.Axioms.coe" "coe has been translated as coeα΅—" "False has been translated as Falseα΅—" "Translating MetaCoq.Translations.param_original.Axioms.Univalence'" "Univalence' has been translated as Univalence'α΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.MiniHoTT.Sect" "MetaCoq.Translations.MiniHoTT.Sect was already translated" "Translating MetaCoq.Translations.MiniHoTT.idpath" "MetaCoq.Translations.MiniHoTT.idpath was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths_ind" "MetaCoq.Translations.MiniHoTT.paths_ind was already translated" "Translating MetaCoq.Translations.MiniHoTT.transport" "MetaCoq.Translations.MiniHoTT.transport was already translated" "Translating MetaCoq.Translations.MiniHoTT.ap" "MetaCoq.Translations.MiniHoTT.ap was already translated" "Translating MetaCoq.Translations.MiniHoTT.IsEquiv" "MetaCoq.Translations.MiniHoTT.IsEquiv was already translated" "Translating MetaCoq.Translations.param_original.Axioms.coe" "MetaCoq.Translations.param_original.Axioms.coe was already translated" "Translating MetaCoq.Translations.param_original.Axioms.Univalence'" "MetaCoq.Translations.param_original.Axioms.Univalence' was already translated" "Translating MetaCoq.Translations.MiniHoTT.Equiv" "MetaCoq.Translations.MiniHoTT.Equiv was already translated" "Translating MetaCoq.Translations.MiniHoTT.equiv_fun" "equiv_fun has been translated as equiv_funα΅—" Fresh universe MetaCoq.Translations.param_generous_packed.764 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.765 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.766 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.767 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.768 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.769 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.770 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.771 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.772 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.773 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.774 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.775 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.776 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.777 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.778 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.779 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.780 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.781 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.782 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.783 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.784 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.785 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.786 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.787 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.788 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.789 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.790 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.791 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.792 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.793 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.794 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.795 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.796 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.797 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.798 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.799 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.800 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.801 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.802 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.803 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.804 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.805 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.806 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.807 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.808 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.809 was added to the context. Fresh universe MetaCoq.Translations.param_generous_packed.810 was added to the context. "equiv has been translated as equivα΅—" "Translating MetaCoq.Translations.MiniHoTT.isequiv_idmap" "isequiv_idmap has been translated as isequiv_idmapα΅—" param_generous_packed.vo (real: 9.61, user: 8.61, sys: 0.95, mem: 892080 ko) ROCQ compile times_bool_fun.v "Translating MetaCoq.Translations.MiniHoTT.equiv_idmap" "equiv_idmap has been translated as equiv_idmapα΅—" File "./times_bool_fun.v", line 2, characters 0-68: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun.v", line 2, characters 0-68: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun.v", line 2, characters 0-68: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun.v", line 2, characters 0-68: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun.v", line 15, characters 0-48: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope prod_scope.". [undeclared-scope,deprecated] "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Translating MetaCoq.Translations.param_original.Axioms.equiv_paths" "Coq.Init.Logic.eq has been translated." "Translating MetaCoq.Translations.MiniHoTT.paths" "paths has been translated as pathsα΅—" "Translating Coq.Init.Logic.False" "Coq.Init.Logic.False has been translated." "Translating MetaCoq.Translations.times_bool_fun.NotFunext" "NotFunext has been translated as NotFunextα΅—" "equiv_paths has been translated as equiv_pathsα΅—" "notFunext has been translated as notFunextα΅—" "notΞ· has been translated as notΞ·α΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.times_bool_fun.UIP" "UIP has been translated as UIPα΅—" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.times_bool_fun.wFunext" "wFunext has been translated as wFunextα΅—" "Translating Coq.Init.Logic.False" "Coq.Init.Logic.False was already translated" "Translating MetaCoq.Translations.param_original.Axioms.Univalence" "notwFunext has been translated as notwFunextα΅—" "Univalence has been translated as Univalenceα΅—" "idpath has been translated as idpathα΅—" "paths_ind has been translated as paths_indα΅—" "Translating MetaCoq.Translations.param_original.Axioms.UU'" "~~~~~~~~~~~~~~~~~~" "Translating Coq.Init.Logic.eq" "Coq.Init.Logic.eq was already translated" "Translating MetaCoq.Translations.MiniHoTT.paths" "MetaCoq.Translations.MiniHoTT.paths was already translated" "Translating MetaCoq.Translations.MiniHoTT.Sect" Fresh universe MetaCoq.Translations.times_bool_fun.576 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.577 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.578 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.579 was added to the context. "Sect has been translated as Sectα΅—" "Translating MetaCoq.Translations.MiniHoTT.idpath" "MetaCoq.Translations.MiniHoTT.idpath was already translated" "UU' has been translated as UU'α΅—" "Translating MetaCoq.Translations.MiniHoTT.paths_ind" "MetaCoq.Translations.MiniHoTT.paths_ind was already translated" "Translating MetaCoq.Translations.MiniHoTT.transport" "transport has been translated as transportα΅—" "Translating MetaCoq.Translations.MiniHoTT.ap" "ap has been translated as apα΅—" "Translating MetaCoq.Translations.MiniHoTT.IsEquiv" "MetaCoq.Translations.MiniHoTT.IsEquiv has been translated." "Translating MetaCoq.Translations.MiniHoTT.Equiv" param_original.vo (real: 18.98, user: 17.91, sys: 0.96, mem: 741808 ko) ROCQ compile param_binary.v "MetaCoq.Translations.MiniHoTT.Equiv has been translated." File "./param_binary.v", line 207, characters 23-24: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax] File "./param_binary.v", line 207, characters 25-26: Warning: Ignoring implicit binder declaration in unexpected position. [unexpected-implicit-declaration,syntax] Coq.Init.Datatypes.nat has been translated. Coq.Init.Datatypes.bool has been translated. Coq.Init.Datatypes.list has been translated. "HD has been translated as HDα΅—" "MAP has been translated as MAPα΅—" param_binary.vo (real: 2.24, user: 1.93, sys: 0.29, mem: 556444 ko) ROCQ compile standard_model.v "Translating MetaCoq.Translations.times_bool_fun.wUnivalence" "wUnivalence has been translated as wUnivalenceα΅—" check_guarded: true check_positive: true check_universes: true cumulative sprop: false definitional uip: false "toto has been translated as totoα΅—" totoα΅— : unit -> (forall A : Type, A -> A) -> Type -> Type : unit -> (forall A : Type, A -> A) -> Type -> Type "FALSE has been translated as FALSEα΅—" "toto" "a has been translated as aα΅—" "T has been translated as Tα΅—" "tm has been translated as tmα΅—" standard_model.vo (real: 1.63, user: 1.34, sys: 0.28, mem: 549492 ko) Fresh universe MetaCoq.Translations.times_bool_fun.631 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.632 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.633 was added to the context. "isequiv_idmap has been translated as isequiv_idmapα΅—" Fresh universe MetaCoq.Translations.times_bool_fun.635 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.636 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.637 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.638 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.639 was added to the context. "equiv_idmap has been translated as equiv_idmapα΅—" Fresh universe MetaCoq.Translations.times_bool_fun.641 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.642 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.643 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.644 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.645 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.646 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.647 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.648 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun.649 was added to the context. "UA has been translated as UAα΅—" "notUA has been translated as notUAα΅—" times_bool_fun.vo (real: 27.19, user: 25.86, sys: 1.20, mem: 857128 ko) ROCQ compile times_bool_fun2.v File "./times_bool_fun2.v", line 4, characters 0-83: Warning: Notation "exists _ .. _ , _" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun2.v", line 4, characters 0-83: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun2.v", line 4, characters 0-83: Warning: Notation "_ = _ :> _" was already used in scope type_scope. [notation-overridden,parsing] File "./times_bool_fun2.v", line 4, characters 0-83: Warning: Notation "_ = _" was already used in scope type_scope. [notation-overridden,parsing] "paths has been translated as pathsα΅—" "idpath has been translated as idpathα΅—" "paths_ind has been translated as paths_indα΅—" "transport has been translated as transportα΅—" Fresh universe MetaCoq.Translations.times_bool_fun2.269 was added to the context. "sigT has been translated as sigTα΅—" "projT1 has been translated as projT1α΅—" "projT2 has been translated as projT2α΅—" "existT has been translated as existTα΅—" Fresh universe MetaCoq.Translations.times_bool_fun2.377 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.378 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.379 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.380 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.381 was added to the context. "isequiv has been translated as isequivα΅—" Fresh universe MetaCoq.Translations.times_bool_fun2.383 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.384 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.385 was added to the context. "equiv has been translated as equivα΅—" "eq has been translated as eqα΅—" "inverse has been translated as inverseα΅—" Fresh universe MetaCoq.Translations.times_bool_fun2.416 was added to the context. Fresh universe MetaCoq.Translations.times_bool_fun2.417 was added to the context. "contr has been translated as contrα΅—" "weakFunext has been translated as weakFunextα΅—" times_bool_fun2.vo (real: 7.77, user: 7.23, sys: 0.50, mem: 614752 ko) Time | Peak Mem | File Name ----------------------------------------------- 1m14.87s | 892080 ko | Total Time / Peak Mem ----------------------------------------------- 0m25.86s | 857128 ko | times_bool_fun.vo 0m17.91s | 741808 ko | param_original.vo 0m08.61s | 892080 ko | param_generous_packed.vo 0m07.23s | 614752 ko | times_bool_fun2.vo 0m04.41s | 348856 ko | MiniHoTT.vo 0m03.42s | 350716 ko | MiniHoTT_paths.vo 0m01.93s | 556444 ko | param_binary.vo 0m01.82s | 554420 ko | translation_utils.vo 0m01.49s | 553352 ko | param_cheap_packed.vo 0m01.34s | 549492 ko | standard_model.vo 0m00.86s | 500064 ko | sigma.vo make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/translations' make -f Makefile.coq install make[3]: Entering directory '/builds/coq/coq/_build_ci/metacoq/translations' INSTALL sigma.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT_paths.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL translation_utils.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_original.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_cheap_packed.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_generous_packed.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun2.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_binary.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL standard_model.vo /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL sigma.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT_paths.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL translation_utils.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_original.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_cheap_packed.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_generous_packed.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun2.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_binary.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL standard_model.v /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL sigma.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL MiniHoTT_paths.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL translation_utils.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_original.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_cheap_packed.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_generous_packed.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL times_bool_fun2.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL param_binary.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ INSTALL standard_model.glob /builds/coq/coq/_install_ci/lib/coq//user-contrib/MetaCoq/Translations/ make[4]: Entering directory '/builds/coq/coq/_build_ci/metacoq/translations' make[4]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/translations' make[3]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/translations' make[2]: Leaving directory '/builds/coq/coq/_build_ci/metacoq/translations' make[1]: Leaving directory '/builds/coq/coq/_build_ci/metacoq' Aggregating timing log... Traceback (most recent call last): File "./tools/make-one-time-file.py", line 13, in stats_dict = get_times_and_mems(args.FILE_NAME, use_real=args.real, include_mem=args.include_mem) File "/builds/coq/coq/tools/TimeFileMaker.py", line 161, in get_times_and_mems return merge_dicts(get_times_of_lines(lines, use_real=use_real), File "/builds/coq/coq/tools/TimeFileMaker.py", line 156, in get_times_of_lines return dict((name, {TIME_KEY:reformat_time_string(time)}) for name, time in times) File "/builds/coq/coq/tools/TimeFileMaker.py", line 156, in return dict((name, {TIME_KEY:reformat_time_string(time)}) for name, time in times) File "/builds/coq/coq/tools/TimeFileMaker.py", line 104, in reformat_time_string seconds, milliseconds = time.split('.') ValueError: too many values to unpack Makefile.ci:90: recipe for target 'ci-metacoq' failed make: *** [ci-metacoq] Error 1 section_end:1598965182:build_script section_start:1598965182:after_script section_end:1598965184:after_script section_start:1598965184:upload_artifacts_on_failure section_end:1598965189:upload_artifacts_on_failure ERROR: Job failed: exit code 1  rocq-9.2.0/test-suite/precomputed-time-tests/non-utf8/000077500000000000000000000000001516144147600227065ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/non-utf8/run.sh000077500000000000000000000010651516144147600240530ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_one_time_file time-of-build.log.in time-of-build-pretty.log || exit $? diff -u time-of-build-pretty.log.expected time-of-build-pretty.log || exit $? cat time-of-build.log.in | $make_one_time_file - time-of-build-pretty.log || exit $? diff -u time-of-build-pretty.log.expected time-of-build-pretty.log || exit $? ($make_one_time_file time-of-build.log.in - || exit $?) > time-of-build-pretty.log diff -u time-of-build-pretty.log.expected time-of-build-pretty.log || exit $? rocq-9.2.0/test-suite/precomputed-time-tests/non-utf8/time-of-build-pretty.log.expected000066400000000000000000000627641516144147600312120ustar00rootroot00000000000000 Time | Peak Mem | File Name ------------------------------------------------------------------------------------ 39m02.52s | 1980772 ko | Total Time / Peak Mem ------------------------------------------------------------------------------------ 3m26.96s | 1980772 ko | Kami/Ex/Multiplier64 3m22.44s | 899104 ko | bedrock2/compiler/src/FlatToRiscv 2m19.56s | 1730872 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI 2m11.59s | 1411224 ko | Kami/Ex/Divider64 1m44.22s | 997556 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeCSR 1m44.11s | 1131272 ko | Kami/Ex/Multiplier32 1m41.50s | 564436 ko | bedrock2/bedrock2/src/Examples/bsearch 1m08.57s | 1312068 ko | Kami/Ex/ProcFDInl 1m07.92s | 590104 ko | bedrock2/deps/riscv-coq/src/Platform/MinimalMMIO 1m01.07s | 798376 ko | Kami/Ex/FifoCorrect 1m00.73s | 847228 ko | Kami/Ex/Divider32 0m50.15s | 573560 ko | bedrock2/deps/riscv-coq/src/Proofs/EncodeBound 0m40.64s | 588832 ko | bedrock2/bedrock2/src/Examples/FE310CompilerDemo 0m40.29s | 668564 ko | Kami/InlineFacts 0m39.12s | 563328 ko | Kami/Renaming 0m37.44s | 672092 ko | Kami/Ex/SimpleFifoCorrect 0m37.08s | 601836 ko | Kami/SemFacts 0m36.08s | 562540 ko | ─preprbedrock2/deps/coqutil/src/Map/TestGoals 0m32.76s | 885880 ko | Kami/ModularFacts 0m28.68s | 639092 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA 0m26.60s | 741048 ko | Kami/Lib/Word 0m26.55s | 632108 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_SB 0m26.45s | 605916 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA64 0m25.80s | 650288 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI64 0m25.47s | 729768 ko | bedrock2/processor/src/KamiRiscv 0m23.66s | 610544 ko | bedrock2/compiler/src/EmitsValid 0m22.68s | 653084 ko | Kami/Ex/InDepthTutorial 0m22.60s | 589708 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM 0m21.68s | 506640 ko | Kami/Specialize 0m21.59s | 525428 ko | bedrock2/bedrock2/src/Examples/lightbulb 0m19.20s | 526372 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_66 0m19.19s | 580040 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_UJ 0m17.33s | 724164 ko | Kami/Ex/ProcDecInl 0m15.63s | 555732 ko | bedrock2/compiler/src/examples/MMIO 0m14.78s | 561068 ko | Kami/ParametricSyntax 0m12.11s | 518652 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_S 0m11.74s | 501100 ko | bedrock2/deps/riscv-coq/src/Platform/MetricMinimal 0m09.95s | 568468 ko | bedrock2/deps/coqutil/src/Word/Properties 0m09.77s | 523092 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM64 0m09.56s | 537308 ko | Kami/Lib/FMap 0m09.35s | 496100 ko | bedrock2/bedrock2/src/Examples/ipow 0m09.26s | 504428 ko | Kami/StepDet 0m09.19s | 663884 ko | bedrock2/bedrock2/src/WeakestPreconditionProperties 0m09.16s | 495544 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_Fence 0m08.98s | 511956 ko | Kami/RefinementFacts 0m08.68s | 494004 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R_atomic 0m08.26s | 505664 ko | bedrock2/compiler/src/FlatToRiscv32 0m07.55s | 534616 ko | Kami/Ex/Fifo 0m07.54s | 454624 ko | ─ensbedrock2/deps/coqutil/src/Map/SlowGoals 0m06.99s | 482444 ko | bedrock2/deps/riscv-coq/src/Platform/Minimal 0m06.89s | 480324 ko | bedrock2/compiler/src/GoFlatToRiscv 0m06.82s | 485168 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I 0m06.72s | 485544 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_FenceI 0m06.50s | 501300 ko | Kami/Semantics 0m06.36s | 478692 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_57 0m06.32s | 478812 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R 0m06.24s | 509232 ko | Kami/PartialInlineFacts 0m06.02s | 486764 ko | bedrock2/deps/coqutil/src/Map/Properties 0m05.62s | 535096 ko | Kami/Ex/ProcThreeStage 0m05.56s | 507520 ko | Kami/Decomposition 0m05.12s | 505436 ko | Kami/Amortization 0m05.07s | 561800 ko | Kami/Ex/SCMMInl 0m04.71s | 470712 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_system 0m04.46s | 468412 ko | bedrock2/deps/riscv-coq/src/Proofs/invert_encode_U 0m04.19s | 509168 ko | Kami/ParametricInline 0m04.13s | 512264 ko | Kami/Ex/ProcDec 0m03.88s | 478956 ko | bedrock2/bedrock2/src/Examples/swap 0m03.81s | 510132 ko | Kami/Ex/SC 0m03.64s | 472892 ko | bedrock2/bedrock2/src/FE310CSemantics 0m03.39s | 517872 ko | Kami/Tutorial 0m03.30s | 510956 ko | bedrock2/compiler/src/examples/Fibonacci 0m03.17s | 486656 ko | Kami/Label 0m03.17s | 492768 ko | Kami/ModuleBoundEx 0m03.10s | 492424 ko | Kami/ParametricEquiv 0m03.06s | 499932 ko | Kami/Wf 0m02.50s | 505076 ko | bedrock2/compiler/src/Pipeline 0m02.42s | 526316 ko | Kami/Ex/ProcFDInv 0m02.42s | 489812 ko | Kami/ParamDup 0m02.39s | 487424 ko | Kami/Duplicate 0m02.19s | 489072 ko | Kami/ParametricWf 0m02.11s | 508168 ko | Kami/Ex/ProcFetchDecode 0m02.06s | 465924 ko | bedrock2/bedrock2/src/Examples/ARPResponder 0m01.94s | 494008 ko | Kami/MapReifyEx 0m01.89s | 479116 ko | Kami/Syntax 0m01.88s | 521816 ko | Kami/Ex/IsaRv32/PgmGcd 0m01.87s | 522776 ko | Kami/Ex/IsaRv32/PgmBankerWorker1 0m01.87s | 519908 ko | Kami/Ex/IsaRv32/PgmMatMulReport 0m01.85s | 520188 ko | Kami/Ex/IsaRv32/PgmBankerWorker3 0m01.83s | 524584 ko | Kami/Ex/IsaRv32/PgmDekker2 0m01.83s | 522312 ko | Kami/Ex/IsaRv32/PgmFact 0m01.83s | 519240 ko | Kami/Ex/IsaRv32/PgmMatMulNormal1 0m01.81s | 522124 ko | Kami/Ex/IsaRv32/PgmBankerInit 0m01.81s | 521416 ko | Kami/Ex/IsaRv32/PgmMatMulInit 0m01.81s | 519724 ko | Kami/Ex/IsaRv32/PgmMatMulNormal2 0m01.81s | 495792 ko | Kami/Ex/RegFile 0m01.80s | 520460 ko | Kami/Ex/IsaRv32/PgmBankerWorker2 0m01.80s | 519680 ko | Kami/Ex/IsaRv32/PgmPeterson1 0m01.80s | 519696 ko | Kami/Ex/IsaRv32/PgmPeterson2 0m01.80s | 461200 ko | bedrock2/bedrock2/src/ptsto_bytes 0m01.78s | 520604 ko | Kami/Ex/IsaRv32/PgmDekker1 0m01.78s | 495196 ko | Kami/Ex/ProcDecInv 0m01.76s | 433996 ko | bedrock2/bedrock2/src/Map/SeparationLogic 0m01.75s | 521896 ko | Kami/Ex/IsaRv32/PgmBsort 0m01.74s | 522080 ko | Kami/Ex/IsaRv32/PgmHanoi 0m01.70s | 490720 ko | Kami/Ex/NativeFifo 0m01.52s | 429812 ko | Kami/Lib/NatLib 0m01.51s | 473632 ko | bedrock2/processor/src/Test 0m01.48s | 476176 ko | Kami/SymEval 0m01.47s | 497260 ko | Kami/Ex/MemAtomic 0m01.44s | 498104 ko | Kami/Ex/ProcThreeStInv 0m01.35s | 457132 ko | bedrock2/bedrock2/src/Array 0m01.34s | 461368 ko | bedrock2/bedrock2/src/TailRecursion 0m01.30s | 509008 ko | Kami/Ex/IsaRv32 0m01.29s | 485936 ko | Kami/ModuleBound 0m01.29s | 418180 ko | bedrock2/bedrock2/src/Byte 0m01.25s | 435736 ko | bedrock2/bedrock2/src/Examples/chacha20 0m01.19s | 495240 ko | Kami/Ex/ProcThreeStDec 0m01.18s | 457564 ko | bedrock2/bedrock2/src/Scalars 0m01.17s | 444076 ko | bedrock2/deps/riscv-coq/src/Utility/ListLib 0m01.15s | 487776 ko | Kami/Ex/OneEltFifo 0m01.14s | 449412 ko | bedrock2/bedrock2/src/Examples/Trace 0m01.13s | 457912 ko | bedrock2/bedrock2/src/TODO_absint 0m01.10s | 419492 ko | bedrock2/compiler/lib/LibTactics 0m01.08s | 421756 ko | Kami/Lib/StringAsList 0m01.00s | 442912 ko | bedrock2/deps/coqutil/src/Z/ZLib 0m00.99s | 435576 ko | Kami/Lib/Struct 0m00.98s | 426872 ko | bedrock2/compiler/src/examples/toposort 0m00.95s | 441452 ko | bedrock2/deps/riscv-coq/src/Utility/prove_Zeq_bitwise 0m00.94s | 450352 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeProver 0m00.94s | 454504 ko | bedrock2/deps/riscv-coq/src/Spec/ExecuteI 0m00.93s | 493232 ko | Kami/Ex/ProcDecSC 0m00.92s | 550756 ko | Kami/Ex/IsaRv32PgmExt 0m00.90s | 421100 ko | Kami/Lib/Indexer 0m00.89s | 484828 ko | Kami/Tactics 0m00.88s | 427540 ko | bedrock2/compiler/src/util/ListLib 0m00.87s | 460284 ko | Kami/Notations 0m00.84s | 443020 ko | bedrock2/bedrock2/src/Memory 0m00.83s | 526908 ko | Kami/Ex/ProcFDCorrect 0m00.83s | 439724 ko | bedrock2/deps/riscv-coq/src/Utility/ZBitOps 0m00.82s | 507796 ko | Kami/Ex/IsaRv32Pgm 0m00.82s | 422368 ko | Kami/Lib/ilist 0m00.81s | 488468 ko | Kami/Ex/ProcDecSCN 0m00.81s | 439216 ko | bedrock2/deps/coqutil/src/Z/BitOps 0m00.80s | 527136 ko | Kami/Ex/ProcFourStDec 0m00.80s | 499980 ko | bedrock2/compiler/src/examples/EditDistExample 0m00.79s | 477872 ko | Kami/Ext/BSyntax 0m00.79s | 488532 ko | Kami/Ext/Extraction 0m00.77s | 486708 ko | Kami/ParametricInlineLtac 0m00.76s | 409784 ko | bedrock2/deps/riscv-coq/src/Platform/Example64Literal 0m00.76s | 459200 ko | bedrock2/deps/riscv-coq/src/Spec/MetricPrimitives 0m00.75s | 490144 ko | Kami/Ex/ProcThreeStInl 0m00.74s | 485920 ko | Kami/Kami 0m00.74s | 501084 ko | bedrock2/compiler/src/examples/CompileExamples 0m00.74s | 505316 ko | bedrock2/compiler/src/examples/swap_bytes_over_uart_hexdump 0m00.74s | 460380 ko | bedrock2/deps/riscv-coq/src/Platform/MinimalLogging 0m00.72s | 473852 ko | Kami/Substitute 0m00.72s | 458732 ko | bedrock2/compiler/src/examples/TestExprImp 0m00.72s | 457772 ko | bedrock2/deps/riscv-coq/src/Spec/Primitives 0m00.71s | 452980 ko | Kami/Ex/MemTypes 0m00.71s | 483356 ko | bedrock2/compiler/src/examples/InlineAssemblyMacro 0m00.71s | 459820 ko | bedrock2/compiler/src/examples/TestFlatImp 0m00.71s | 449484 ko | bedrock2/deps/riscv-coq/src/Platform/Memory 0m00.71s | 446048 ko | bedrock2/deps/riscv-coq/src/Spec/Decode 0m00.70s | 469696 ko | Kami/Inline 0m00.70s | 423260 ko | Kami/Lib/StringAsOT 0m00.69s | 466532 ko | bedrock2/compiler/src/FlatToRiscvDef 0m00.68s | 447424 ko | bedrock2/compiler/src/Rem4 0m00.67s | 474056 ko | Kami/SymEvalTac 0m00.67s | 446424 ko | bedrock2/compiler/src/SimplWordExpr 0m00.67s | 446648 ko | bedrock2/deps/riscv-coq/src/Utility/Encode 0m00.66s | 441912 ko | bedrock2/bedrock2/src/Semantics 0m00.63s | 420276 ko | Kami/Lib/StringStringAsOT 0m00.63s | 426168 ko | bedrock2/deps/coqutil/src/Datatypes/PropSet 0m00.61s | 446012 ko | bedrock2/compiler/src/UnmappedMemForExtSpec 0m00.61s | 357880 ko | bedrock2/deps/riscv-coq/src/Utility/Monads 0m00.60s | 426440 ko | bedrock2/deps/coqutil/src/Map/SortedList 0m00.59s | 442252 ko | Kami/Synthesize 0m00.59s | 371952 ko | bedrock2/compiler/src/util/Common 0m00.59s | 440596 ko | bedrock2/deps/coqutil/src/Map/SortedListWord 0m00.58s | 415316 ko | bedrock2/deps/coqutil/src/Word/Naive 0m00.58s | 408744 ko | bedrock2/deps/riscv-coq/src/Utility/runsToNonDet_Run 0m00.57s | 403188 ko | bedrock2/bedrock2/src/BasicC64Semantics 0m00.57s | 358716 ko | bedrock2/deps/riscv-coq/src/Utility/Utility 0m00.56s | 432120 ko | Kami/Lib/WordSupport 0m00.56s | 410516 ko | bedrock2/bedrock2/src/WeakestPrecondition 0m00.55s | 413664 ko | Kami/Lib/StringEq 0m00.55s | 387552 ko | bedrock2/bedrock2/src/BasicC32Semantics 0m00.55s | 420416 ko | bedrock2/compiler/src/examples/highlevel/FuncMut 0m00.55s | 401008 ko | bedrock2/deps/riscv-coq/src/Spec/ExecuteI64 0m00.55s | 376020 ko | bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl32 0m00.54s | 310296 ko | bedrock2/bedrock2/src/Examples/MultipleReturnValues 0m00.53s | 386872 ko | bedrock2/compiler/src/RegAlloc2 0m00.53s | 387416 ko | bedrock2/deps/riscv-coq/src/Spec/ExecuteM 0m00.52s | 371960 ko | bedrock2/bedrock2/src/ProgramLogic 0m00.52s | 374676 ko | bedrock2/deps/riscv-coq/src/Platform/Run 0m00.52s | 375816 ko | bedrock2/deps/riscv-coq/src/Spec/ExecuteM64 0m00.52s | 375840 ko | bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl64 0m00.52s | 346660 ko | bedrock2/deps/riscv-coq/src/Utility/Words32Naive 0m00.50s | 322924 ko | bedrock2/bedrock2/src/BasicCSyntax 0m00.50s | 385968 ko | bedrock2/compiler/src/Basic32Semantics 0m00.50s | 389304 ko | bedrock2/compiler/src/RegAlloc3 0m00.49s | 411496 ko | bedrock2/bedrock2/src/BytedumpTest 0m00.49s | 411496 ko | bedrock2/bedrock2/src/BytedumpTestΞ± 0m00.49s | 365272 ko | bedrock2/deps/coqutil/src/Map/Z_keyed_SortedListMap 0m00.49s | 375808 ko | bedrock2/deps/riscv-coq/src/Spec/Machine 0m00.49s | 360632 ko | bedrock2/deps/riscv-coq/src/Utility/MkMachineWidth 0m00.49s | 346980 ko | bedrock2/deps/riscv-coq/src/Utility/Words64Naive 0m00.48s | 276676 ko | bedrock2/bedrock2/src/ToCString 0m00.48s | 352200 ko | bedrock2/compiler/src/SeparationLogic 0m00.48s | 375156 ko | bedrock2/deps/coqutil/src/Decidable 0m00.48s | 362608 ko | bedrock2/deps/riscv-coq/src/Platform/MetricRiscvMachine 0m00.48s | 370692 ko | bedrock2/deps/riscv-coq/src/Platform/RiscvMachine 0m00.47s | 321560 ko | bedrock2/bedrock2/src/BasicC64Syntax 0m00.47s | 338992 ko | bedrock2/deps/riscv-coq/src/Spec/PseudoInstructions 0m00.46s | 351756 ko | bedrock2/compiler/src/ZNameGen 0m00.46s | 344552 ko | bedrock2/deps/riscv-coq/src/Platform/MetricLogging 0m00.45s | 350576 ko | bedrock2/compiler/src/RegAllocAnnotatedNotations 0m00.45s | 358800 ko | bedrock2/processor/src/KamiWord 0m00.44s | 305528 ko | bedrock2/deps/coqutil/src/Map/SortedListString_test 0m00.44s | 321736 ko | bedrock2/deps/coqutil/src/Tactics/Tactics 0m00.44s | 336624 ko | bedrock2/deps/riscv-coq/src/Spec/Execute 0m00.44s | 340268 ko | bedrock2/deps/riscv-coq/src/Utility/InstructionNotations 0m00.43s | 289244 ko | bedrock2/bedrock2/src/Map/Separation 0m00.43s | 362292 ko | bedrock2/compiler/src/RiscvWordProperties 0m00.43s | 321032 ko | bedrock2/deps/riscv-coq/src/Spec/VirtualMemory 0m00.43s | 313976 ko | bedrock2/deps/riscv-coq/src/Utility/InstructionCoercions 0m00.42s | 374624 ko | bedrock2/deps/riscv-coq/src/Proofs/DecodeEncode 0m00.40s | 282384 ko | bedrock2/compiler/src/util/Tactics 0m00.40s | 323944 ko | bedrock2/deps/coqutil/src/Map/Interface 0m00.39s | 303504 ko | bedrock2/deps/coqutil/src/Z/HexNotation 0m00.38s | 319992 ko | Kami/Lib/CommonTactics 0m00.38s | 363832 ko | Kami/Lib/Nomega 0m00.38s | 294268 ko | bedrock2/bedrock2/src/ZNamesSyntax 0m00.37s | 316400 ko | bedrock2/deps/coqutil/src/Map/Funext 0m00.37s | 295668 ko | bedrock2/deps/riscv-coq/src/Utility/div_mod_to_quot_rem 0m00.36s | 271052 ko | Kami/Ex/Names 0m00.36s | 338456 ko | Kami/Lib/Concat 0m00.36s | 272052 ko | bedrock2/bedrock2/src/string2ident 0m00.36s | 298624 ko | bedrock2/compiler/src/Simp 0m00.36s | 312496 ko | bedrock2/deps/coqutil/src/Map/Solver 0m00.36s | 298516 ko | bedrock2/deps/riscv-coq/src/Utility/nat_div_mod_to_quot_rem 0m00.35s | 299684 ko | Kami/Lib/Misc 0m00.35s | 272888 ko | bedrock2/bedrock2/src/Examples/StructAccess 0m00.35s | 267768 ko | bedrock2/bedrock2/src/StructNotations 0m00.35s | 295952 ko | bedrock2/deps/coqutil/src/Map/Empty_set_keyed_map 0m00.35s | 289456 ko | bedrock2/deps/coqutil/src/Map/SortedListString 0m00.34s | 328692 ko | Kami/Lib/Reflection 0m00.34s | 272812 ko | bedrock2/bedrock2/src/Bytedump 0m00.34s | 294376 ko | bedrock2/deps/riscv-coq/src/Utility/Tactics 0m00.33s | 301112 ko | bedrock2/bedrock2/src/NotationsCustomEntry 0m00.33s | 289700 ko | bedrock2/compiler/src/util/MyOmega 0m00.32s | 274924 ko | bedrock2/bedrock2/src/Hexdump 0m00.32s | 286108 ko | bedrock2/compiler/src/NameGen 0m00.31s | 301996 ko | bedrock2/compiler/lib/LibTacticsMin 0m00.30s | 252388 ko | bedrock2/bedrock2/src/StringNamesSyntax 0m00.30s | 282580 ko | bedrock2/compiler/src/util/Set 0m00.30s | 290132 ko | bedrock2/compiler/src/util/SetSolverTests 0m00.29s | 252176 ko | bedrock2/deps/coqutil/src/Datatypes/String 0m00.27s | 227732 ko | bedrock2/deps/coqutil/src/Word/LittleEndian 0m00.27s | 255852 ko | bedrock2/deps/riscv-coq/src/Utility/MonadTests 0m00.26s | 238732 ko | bedrock2/deps/coqutil/src/Z/div_mod_to_equations 0m00.23s | 212520 ko | bedrock2/deps/riscv-coq/src/Utility/MonadT 0m00.19s | 172428 ko | bedrock2/bedrock2/src/NotationsInConstr 0m00.19s | 180476 ko | bedrock2/deps/coqutil/src/Datatypes/HList 0m00.17s | 180940 ko | Kami/Lib/VectorFacts 0m00.17s | 184664 ko | bedrock2/deps/riscv-coq/src/Utility/JMonad 0m00.14s | 160816 ko | Kami/Lib/DepEq 0m00.13s | 142092 ko | Kami/Lib/FinNotations 0m00.13s | 144616 ko | bedrock2/bedrock2/src/ListPred 0m00.13s | 149744 ko | bedrock2/bedrock2/src/Variables 0m00.13s | 142420 ko | bedrock2/deps/coqutil/src/Datatypes/List 0m00.12s | 146976 ko | bedrock2/deps/riscv-coq/src/Utility/MonadNotations 0m00.09s | 116312 ko | bedrock2/bedrock2/src/Lift1Prop 0m00.09s | 108600 ko | bedrock2/deps/coqutil/src/Datatypes/Option 0m00.09s | 93184 ko | bedrock2/deps/coqutil/src/Datatypes/Prod 0m00.07s | 87856 ko | Kami/Lib/BasicLogic 0m00.07s | 93508 ko | bedrock2/bedrock2/src/Syntax 0m00.06s | 76484 ko | Kami/Lib/DepEqNat 0m00.06s | 67708 ko | bedrock2/deps/coqutil/src/Macros/symmetry 0m00.05s | 56680 ko | bedrock2/compiler/lib/fiat_crypto_tactics/Not 0m00.05s | 70976 ko | bedrock2/compiler/src/util/Misc 0m00.05s | 65768 ko | bedrock2/deps/riscv-coq/src/Utility/PowerFunc 0m00.05s | 65120 ko | bedrock2/deps/riscv-coq/src/Utility/runsToNonDet 0m00.04s | 57444 ko | bedrock2/bedrock2/src/Markers 0m00.04s | 56396 ko | bedrock2/bedrock2/src/Notations 0m00.04s | 55660 ko | bedrock2/compiler/lib/fiat_crypto_tactics/Test 0m00.04s | 57340 ko | bedrock2/compiler/lib/fiat_crypto_tactics/UniquePose 0m00.04s | 57364 ko | bedrock2/compiler/src/NoActionSyntaxParams 0m00.04s | 56364 ko | bedrock2/compiler/src/eqexact 0m00.04s | 55764 ko | bedrock2/compiler/src/examples/highlevel/For 0m00.04s | 56680 ko | bedrock2/compiler/src/on_hyp_containing 0m00.04s | 58420 ko | bedrock2/compiler/src/util/Learning 0m00.04s | 56232 ko | bedrock2/deps/coqutil/src/Datatypes/PrimitivePair 0m00.04s | 54100 ko | bedrock2/deps/coqutil/src/Macros/subst 0m00.04s | 54384 ko | bedrock2/deps/coqutil/src/Macros/unique 0m00.04s | 55016 ko | bedrock2/deps/coqutil/src/Tactics/eabstract 0m00.04s | 55296 ko | bedrock2/deps/coqutil/src/Tactics/letexists 0m00.04s | 54916 ko | bedrock2/deps/coqutil/src/Tactics/rdelta 0m00.04s | 56184 ko | bedrock2/deps/coqutil/src/Tactics/syntactic_unify 0m00.04s | 54440 ko | bedrock2/deps/coqutil/src/dlet 0m00.04s | 54804 ko | bedrock2/deps/coqutil/src/sanity 0m00.04s | 56096 ko | bedrock2/deps/riscv-coq/src/Utility/MMIOTrace 0m00.03s | 54716 ko | bedrock2/compiler/src/util/LogGoal rocq-9.2.0/test-suite/precomputed-time-tests/non-utf8/time-of-build.log.in000066400000000000000000006667351516144147600265020ustar00rootroot00000000000000bedrock2/deps/coqutil/src/Tactics/eabstract (real: 0.17, user: 0.04, sys: 0.03, mem: 55016 ko) bedrock2/deps/coqutil/src/sanity (real: 0.18, user: 0.04, sys: 0.03, mem: 54804 ko) bedrock2/deps/coqutil/src/Tactics/letexists (real: 0.17, user: 0.04, sys: 0.03, mem: 55296 ko) bedrock2/deps/coqutil/src/Tactics/rdelta (real: 0.17, user: 0.04, sys: 0.04, mem: 54916 ko) bedrock2/deps/coqutil/src/Macros/subst (real: 0.16, user: 0.04, sys: 0.03, mem: 54100 ko) bedrock2/deps/coqutil/src/dlet (real: 0.17, user: 0.04, sys: 0.03, mem: 54440 ko) File "bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v", line 9, characters 2-67: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v", line 11, characters 2-63: Warning: Notation "{ _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v", line 14, characters 2-67: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] bedrock2/deps/coqutil/src/Macros/unique (real: 0.16, user: 0.04, sys: 0.03, mem: 54384 ko) File "bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v", line 15, characters 2-73: Warning: Notation "{ ' _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v", line 17, characters 2-70: Warning: Notation "( _ , _ , .. , _ )" was already used in scope core_scope. [notation-overridden,parsing] bedrock2/deps/coqutil/src/Datatypes/PrimitivePair (real: 0.17, user: 0.04, sys: 0.03, mem: 56232 ko) bedrock2/deps/coqutil/src/Datatypes/List (real: 0.58, user: 0.13, sys: 0.09, mem: 142420 ko) bedrock2/deps/coqutil/src/Datatypes/String (real: 0.85, user: 0.29, sys: 0.16, mem: 252176 ko) bedrock2/deps/coqutil/src/Datatypes/Option (real: 0.37, user: 0.09, sys: 0.06, mem: 108600 ko) make[1]: Entering directory 'bedrock2' make -C bedrock2/deps/coqutil make[2]: Entering directory 'bedrock2/deps/coqutil' /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = coqutil -arg "-async-proofs-tac-j 1" bedrock2/deps/coqutil/src/Tactics/Tactics.v bedrock2/deps/coqutil/src/Tactics/eabstract.v bedrock2/deps/coqutil/src/Tactics/letexists.v bedrock2/deps/coqutil/src/Tactics/rdelta.v bedrock2/deps/coqutil/src/Tactics/syntactic_unify.v bedrock2/deps/coqutil/src/dlet.v bedrock2/deps/coqutil/src/Map/Funext.v bedrock2/deps/coqutil/src/Map/Empty_set_keyed_map.v bedrock2/deps/coqutil/src/Map/SortedListString.v bedrock2/deps/coqutil/src/Map/Z_keyed_SortedListMap.v bedrock2/deps/coqutil/src/Map/SortedListWord.v bedrock2/deps/coqutil/src/Map/Properties.v bedrock2/deps/coqutil/src/Map/TestLemmas.v bedrock2/deps/coqutil/src/Map/Interface.v bedrock2/deps/coqutil/src/Map/TestGoals.v bedrock2/deps/coqutil/src/Map/SlowGoals.v bedrock2/deps/coqutil/src/Map/SortedListString_test.v bedrock2/deps/coqutil/src/Map/Solver.v bedrock2/deps/coqutil/src/Map/SortedList.v bedrock2/deps/coqutil/src/Z/div_mod_to_equations.v bedrock2/deps/coqutil/src/Z/ZLib.v bedrock2/deps/coqutil/src/Z/HexNotation.v bedrock2/deps/coqutil/src/Z/BitOps.v bedrock2/deps/coqutil/src/Datatypes/String.v bedrock2/deps/coqutil/src/Datatypes/List.v bedrock2/deps/coqutil/src/Datatypes/PropSet.v bedrock2/deps/coqutil/src/Datatypes/Option.v bedrock2/deps/coqutil/src/Datatypes/Prod.v bedrock2/deps/coqutil/src/Datatypes/HList.v bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v bedrock2/deps/coqutil/src/Word/Naive.v bedrock2/deps/coqutil/src/Word/Properties.v bedrock2/deps/coqutil/src/Word/Interface.v bedrock2/deps/coqutil/src/Word/LittleEndian.v bedrock2/deps/coqutil/src/sanity.v bedrock2/deps/coqutil/src/Decidable.v bedrock2/deps/coqutil/src/Macros/subst.v bedrock2/deps/coqutil/src/Macros/symmetry.v bedrock2/deps/coqutil/src/Macros/unique.v -o Makefile.coq.all make -f Makefile.coq.all make[3]: Entering directory 'bedrock2/deps/coqutil' ROCQ DEP VFILES ROCQ compile bedrock2/deps/coqutil/src/Tactics/eabstract.v ROCQ compile bedrock2/deps/coqutil/src/sanity.v ROCQ compile bedrock2/deps/coqutil/src/Tactics/letexists.v ROCQ compile bedrock2/deps/coqutil/src/Tactics/rdelta.v ROCQ compile bedrock2/deps/coqutil/src/dlet.v ROCQ compile bedrock2/deps/coqutil/src/Macros/subst.v ROCQ compile bedrock2/deps/coqutil/src/Macros/unique.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/PrimitivePair.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/List.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/String.v ROCQ compile bedrock2/deps/coqutil/src/Word/Interface.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/Option.v ROCQ compile bedbedrock2/deps/coqutil/src/Word/Interface (real: 1.40, user: 0.31, sys: 0.22, mem: 293000 ko) bedrock2/deps/coqutil/src/Z/div_mod_to_equations (real: 0.92, user: 0.26, sys: 0.17, mem: 238732 ko) bedrock2/deps/coqutil/src/Z/HexNotation (real: 1.24, user: 0.39, sys: 0.18, mem: 303504 ko) bedrock2/deps/coqutil/src/Z/ZLib (real: 2.83, user: 1.00, sys: 0.28, mem: 442912 ko) bedrock2/deps/coqutil/src/Datatypes/Prod (real: 0.32, user: 0.09, sys: 0.06, mem: 93184 ko) bedrock2/deps/coqutil/src/Z/BitOps (real: 2.25, user: 0.81, sys: 0.26, mem: 439216 ko) bedrock2/deps/coqutil/src/Word/Naive (real: 1.75, user: 0.58, sys: 0.27, mem: 415316 ko) bedrock2/deps/coqutil/src/Macros/symmetry (real: 0.23, user: 0.06, sys: 0.04, mem: 67708 ko) bedrock2/deps/coqutil/src/Decidable (real: 1.50, user: 0.48, sys: 0.23, mem: 375156 ko) bedrock2/deps/coqutil/src/Tactics/syntactic_unify (real: 0.18, user: 0.04, sys: 0.04, mem: 56184 ko) File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 2, characters 48-60: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 2, characters 48-60: Warning: Notation "{ _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 2, characters 48-60: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 2, characters 48-60: Warning: Notation "{ ' _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 2, characters 48-60: Warning: Notation "( _ , _ , .. , _ )" was already used in scope core_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 90, characters 2-19: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/deps/coqutil/src/Datatypes/HList.v", line 90, characters 2-19: Warning: Notation "( _ , _ , .. , _ )" was already used in scope core_scope. [notation-overridden,parsing] bedrock2/deps/coqutil/src/Datatypes/HList (real: 0.63, user: 0.19, sys: 0.12, mem: 180476 ko) bedrock2/deps/coqutil/src/Tactics/Tactics (real: 1.35, user: 0.44, sys: 0.19, mem: 321736 ko) bedrock2/deps/coqutil/src/Word/LittleEndian (real: 0.89, user: 0.27, sys: 0.16, mem: 227732 ko) bedrock2/deps/coqutil/src/Datatypes/PropSet (real: 1.93, user: 0.63, sys: 0.29, mem: 426168 ko) bedrock2/deps/coqutil/src/Map/Interface (real: 1.32, user: 0.40, sys: 0.23, mem: 323944 ko) bedrock2/deps/coqutil/src/Map/Funext (real: 1.24, user: 0.37, sys: 0.23, mem: 316400 ko) bedrock2/deps/coqutil/src/Map/Empty_set_keyed_map (real: 1.17, user: 0.35, sys: 0.21, mem: 295952 ko) File "bedrock2/deps/coqutil/src/Map/SortedList.v", line 110, characters 2-28: Warning: Use of β€œRequire” inside a section is deprecated. [require-in-section,deprecated] bedrock2/deps/coqutil/src/Map/SortedList (real: 1.86, user: 0.60, sys: 0.29, mem: 426440 ko) bedrock2/deps/coqutil/src/Word/Properties (real: 21.22, user: 9.95, sys: 0.38, mem: 568468 ko) bedrock2/deps/coqutil/src/Map/SortedListString (real: 1.20, user: 0.35, sys: 0.22, mem: 289456 ko) bedrock2/deps/coqutil/src/Map/Z_keyed_SortedListMap (real: 1.56, user: 0.49, sys: 0.26, mem: 365272 ko) bedrock2/deps/coqutil/src/Map/SortedListWord (real: 1.88, user: 0.59, sys: 0.30, mem: 440596 ko) bedrock2/deps/coqutil/src/Map/Properties (real: 13.04, user: 6.02, sys: 0.32, mem: 486764 ko) bedrock2/deps/coqutil/src/Map/SortedListString_test (real: 1.34, user: 0.44, sys: 0.21, mem: 305528 ko) bedrock2/deps/coqutil/src/Map/Solver (real: 0.80, user: 0.36, sys: 0.21, mem: 312496 ko) rock2/deps/coqutil/src/Z/div_mod_to_equations.v ROCQ compile bedrock2/deps/coqutil/src/Z/ZLib.v ROCQ compile bedrock2/deps/coqutil/src/Z/HexNotation.v ROCQ compile bedrock2/deps/coqutil/src/Z/BitOps.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/Prod.v ROCQ compile bedrock2/deps/coqutil/src/Word/Naive.v ROCQ compile bedrock2/deps/coqutil/src/Word/Properties.v ROCQ compile bedrock2/deps/coqutil/src/Macros/symmetry.v ROCQ compile bedrock2/deps/coqutil/src/Decidable.v ROCQ compile bedrock2/deps/coqutil/src/Tactics/syntactic_unify.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/HList.v ROCQ compile bedrock2/deps/coqutil/src/Tactics/Tactics.v ROCQ compile bedrock2/deps/coqutil/src/Word/LittleEndian.v ROCQ compile bedrock2/deps/coqutil/src/Datatypes/PropSet.v ROCQ compile bedrock2/deps/coqutil/src/Map/Interface.v ROCQ compile bedrock2/deps/coqutil/src/Map/Funext.v ROCQ compile bedrock2/deps/coqutil/src/Map/Empty_set_keyed_map.v ROCQ compile bedrock2/deps/coqutil/src/Map/SortedList.v ROCQ compile bedrock2/deps/coqutil/src/Map/Properties.v ROCQ compile bedrock2/deps/coqutil/src/Map/SortedListString.v ROCQ compile bedrock2/deps/coqutil/src/Map/Z_keyed_SortedListMap.v ROCQ compile bedrock2/deps/coqutil/src/Map/SortedListWord.v ROCQ compile bedrock2/deps/coqutil/src/Map/SortedListString_test.v ROCQ compile bedrock2/deps/coqutil/src/Map/Solver.v ROCQ compile bedrock2/deps/coqutil/src/Map/TestGoals.v ROCQ compile bedrock2/deps/coqutil/src/Map/TestLemmas.v Finished transaction in 0.297 secs (0.095u,0.05s) (successful) Part 1a: Small goals (originally took <5s each) Finished transaction in 0.35 secs (0.143u,0.032s) (successful) Finished transaction in 0.438 secs (0.204u,0.008s) (successful) End of TestLemmas.v total time: 1.147s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.1% 99.9% 15 0.252s ─map_solver_core ----------------------- 1.0% 69.6% 15 0.209s ─map_solver_core_impl ------------------ 0.9% 68.2% 0 0.207s ─map_specialize ------------------------ 0.2% 54.9% 15 0.199s ─map_specialize_step ------------------- 24.9% 54.7% 42 0.146s ─preprocess_impl ----------------------- 1.8% 30.1% 15 0.043s ─abstract_unrecogs --------------------- 3.2% 19.8% 15 0.030s ─unrecogs_in_prop ---------------------- 15.2% 15.2% 0 0.017s ─specialize (constr_with_bindings) ----- 12.3% 12.3% 769 0.081s ─canonicalize_map_hyp ------------------ 2.3% 8.9% 316 0.011s ─unrecogs_in_option_value -------------- 3.6% 8.3% 0 0.013s ─maps_propositional -------------------- 0.3% 6.5% 15 0.009s ─ensure_no_body ------------------------ 2.1% 5.3% 602 0.006s ─assert_fails -------------------------- 1.9% 4.4% 756 0.006s ─rew_map_specs_in ---------------------- 1.3% 4.4% 316 0.010s ─canonicalize_all ---------------------- 0.6% 4.2% 15 0.006s ─maps_leaf_tac ------------------------- 0.3% 3.8% 32 0.003s ─one_rew_map_specs --------------------- 2.6% 3.5% 0 0.010s ─unrecogs_in_key ----------------------- 1.6% 2.9% 0 0.001s ─pose proof H as H' -------------------- 2.8% 2.8% 448 0.000s ─tac ----------------------------------- 1.8% 2.5% 756 0.000s ─revert_all_Props bedrock2/deps/coqutil/src/Map/TestLemmas (real: 3.68, user: 1.47, sys: 0.32, mem: 435336 ko) ---------------------- 2.1% 2.2% 15 0.003s ─autounfold (hintbases) (clause_dft_conc 2.2% 2.2% 62 0.001s ─unrecogs_in_map ----------------------- 1.4% 2.0% 0 0.002s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.1% 99.9% 15 0.252s β”œβ”€map_solver_core --------------------- 1.0% 69.6% 15 0.209s β”‚β””map_solver_core_impl ---------------- 0.9% 68.2% 0 0.207s β”‚ β”œβ”€map_specialize -------------------- 0.2% 54.9% 15 0.199s β”‚ β”‚β””map_specialize_step --------------- 24.9% 54.7% 42 0.146s β”‚ β”‚ β”œβ”€specialize (constr_with_bindings) 10.7% 10.7% 448 0.081s β”‚ β”‚ β”œβ”€canonicalize_map_hyp ------------ 1.2% 5.9% 154 0.011s β”‚ β”‚ β”‚β””rew_map_specs_in ---------------- 0.8% 3.3% 154 0.010s β”‚ β”‚ β”‚β””one_rew_map_specs --------------- 1.9% 2.5% 0 0.010s β”‚ β”‚ β”œβ”€ensure_no_body ------------------ 2.1% 5.3% 602 0.006s β”‚ β”‚ β”‚β””assert_fails -------------------- 1.6% 3.1% 602 0.006s β”‚ β”‚ └─pose proof H as H' -------------- 2.8% 2.8% 448 0.000s β”‚ β”œβ”€maps_propositional ---------------- 0.3% 6.5% 15 0.009s β”‚ β”‚β””maps_leaf_tac --------------------- 0.3% 3.8% 32 0.003s β”‚ └─canonicalize_all ------------------ 0.6% 4.2% 15 0.006s β”‚ β””canonicalize_map_hyp -------------- 1.1% 3.0% 162 0.001s └─preprocess_impl --------------------- 1.8% 30.1% 15 0.043s β”œβ”€abstract_unrecogs ----------------- 3.2% 19.8% 15 0.030s β”‚β””unrecogs_in_prop ------------------ 15.2% 15.2% 0 0.017s β”‚β””unrecogs_in_option_value ---------- 3.6% 8.3% 0 0.013s β”‚ β”œβ”€unrecogs_in_key ----------------- 1.1% 2.0% 0 0.001s β”‚ └─unrecogs_in_map ----------------- 1.4% 2.0% 0 0.002s └─revert_all_Props ------------------ 2.1% 2.2% 15 0.003s ROCQ compile bedrock2/deps/coqutil/src/Map/SlowGoals.v Finished transaction in 3.949 secs (1.835u,0.093s) (successful) Finished transaction in 6.898 secs (3.179u,0.177s) (successful) Finished transaction in 6.138 secs (2.811u,0.154s) (successful) Finished transaction in 15.112 secs (7.09u,0.222s) (successful) Finished transaction in 0.047 secs (0.024u,0.s) (successful) End of SlowGoals.v total time: 7.313s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver_core ----------------------- 0.0% 100.0% 1 7.312s ─map_solver_core_impl ------------------ 0.0% 100.0% 0 7.310s ─maps_propositional -------------------- 0.6% 61.3% 33 4.485s ─map_specialize ------------------------ 0.0% 38.0% 1 2.779s ─map_specialize_step ------------------- 15.8% 38.0% 37 1.817s ─maps_leaf_tac ------------------------- 0.7% 32.8% 228 0.018s ─propositional_cheap_step -------------- 25.2% 25.6% 427 0.013s ─congruence ---------------------------- 16.9% 16.9% 228 0.010s ─maps_choice_step ---------------------- 0.1% 15.7% 0 0.040s ─next ---------------------------------- 15.7% 15.7% 32 0.040s ─auto (int_or_var_opt) (auto_using) (hin 14.8% 14.8% 358 0.008s ─unify (constr) (constr) --------------- 5.5% 5.5% 4416 0.006s ─canonicalize_map_hyp ------------------ 1.0% 4.4% 822 0.008s ─specialize (constr_with_bindings) ----- 4.2% 4.2% 3293 0.008s ─ensbedrock2/deps/coqutil/src/Map/SlowGoals (real: 16.46, user: 7.54, sys: 0.41, mem: 454624 ko) ure_no_body ------------------------ 1.5% 3.6% 3220 0.008s ─assert_fails -------------------------- 0.9% 3.2% 4005 0.008s ─pose proof H as H' -------------------- 3.0% 3.0% 2405 0.009s ─tac ----------------------------------- 1.4% 2.3% 4005 0.008s ─maps_split_step ----------------------- 0.3% 2.2% 260 0.006s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver_core ----------------------- 0.0% 100.0% 1 7.312s β””map_solver_core_impl ------------------ 0.0% 100.0% 0 7.310s β”œβ”€maps_propositional ------------------ 0.6% 61.3% 33 4.485s β”‚ β”œβ”€maps_leaf_tac --------------------- 0.7% 32.8% 228 0.018s β”‚ β”‚ β”œβ”€congruence ---------------------- 16.9% 16.9% 228 0.010s β”‚ β”‚ └─auto (int_or_var_opt) (auto_using 14.8% 14.8% 358 0.008s β”‚ β”œβ”€propositional_cheap_step ---------- 25.0% 25.4% 424 0.013s β”‚ β”œβ”€maps_choice_step ------------------ 0.1% 15.7% 0 0.040s β”‚ β”‚β””next ------------------------------ 15.7% 15.7% 32 0.040s β”‚ └─maps_split_step ------------------- 0.3% 2.2% 260 0.006s └─map_specialize ---------------------- 0.0% 38.0% 1 2.779s β””map_specialize_step ----------------- 15.8% 38.0% 37 1.817s β”œβ”€unify (constr) (constr) ----------- 5.5% 5.5% 4413 0.006s β”œβ”€canonicalize_map_hyp -------------- 0.9% 4.2% 785 0.008s β”œβ”€ensure_no_body -------------------- 1.5% 3.6% 3220 0.008s β”‚β””assert_fails ---------------------- 0.7% 2.1% 3220 0.008s β”œβ”€pose proof H as H' ---------------- 3.0% 3.0% 2405 0.009s └─specialize (constr_with_bindings) - 2.5% 2.5% 2405 0.007s Finished transaction in 2.274 secs (1.721u,0.068s) (successful) Finished transaction in 1.891 secs (1.771u,0.084s) (successful) Finished transaction in 1.713 secs (1.599u,0.076s) (successful) Finished transaction in 0.196 secs (0.185u,0.008s) (successful) Part 1b: Medium goals (originally took >5s each) Finished transaction in 1.398 secs (1.318u,0.055s) (successful) Finished transaction in 3.691 secs (3.403u,0.173s) (successful) Finished transaction in 3.279 secs (3.017u,0.167s) (successful) Finished transaction in 1.982 secs (1.851u,0.083s) (successful) Finished transaction in 1.932 secs (1.8u,0.097s) (successful) Finished transaction in 3.391 secs (3.136u,0.144s) (successful) Finished transaction in 3.23 secs (3.024u,0.138s) (successful) Part 1c: Large goals (originally took >50s each) Finished transaction in 4.687 secs (4.34u,0.215s) (successful) End of TestGoals.v total time: 37.262s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.0% 100.0% 18 4.555s ─map_solver_core ----------------------- 0.0% 96.9% 18 4.483s ─map_solver_core_impl ------------------ 0.0% 96.8% 0 4.482s ─map_specialize ------------------------ 0.0% 93.4% 18 4.351s ─map_specialize_step ------------------- 43.0% 93.3% 428 1.253s ─ensure_no_body ------------------------ 5.8% 13.2% 62635 0.014s ─specialize (constr_with_bindings) ----- 12.8% 12.8% 63060 0.013s ─pose proof H as H' -------------------- 11.4% 11.4% 55172 0.009s ─assert_fails -------------------------- 3.3% 9.5% 69963 0.014s ─canonicalize_map_hyp ------------------ 1.8% 7.6% 7811 0.014s ─tac ----------------------------------- 4.2% 6.2% 69963 0.014s ─preprbedrock2/deps/coqutil/src/Map/TestGoals (real: 49.22, user: 36.08, sys: 2.04, mem: 562540 ko) ocess_impl ----------------------- 0.1% 3.1% 18 0.116s ─Tactics.ensure_new -------------------- 1.1% 3.1% 7328 0.014s ─rew_map_specs_in ---------------------- 1.0% 3.0% 7812 0.014s ─maps_propositional -------------------- 0.0% 2.8% 22 0.231s ─abstract_unrecogs --------------------- 0.4% 2.4% 18 0.107s ─unify (constr) (constr) --------------- 2.2% 2.2% 75932 0.009s ─one_rew_map_specs --------------------- 1.4% 2.1% 0 0.014s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.0% 100.0% 18 4.555s β”œβ”€map_solver_core --------------------- 0.0% 96.9% 18 4.483s β”‚β””map_solver_core_impl ---------------- 0.0% 96.8% 0 4.482s β”‚ β”œβ”€map_specialize -------------------- 0.0% 93.4% 18 4.351s β”‚ β”‚β””map_specialize_step --------------- 43.0% 93.3% 428 1.253s β”‚ β”‚ β”œβ”€ensure_no_body ------------------ 5.8% 13.2% 62635 0.014s β”‚ β”‚ β”‚β””assert_fails -------------------- 2.9% 7.5% 62635 0.014s β”‚ β”‚ β”‚β””tac ----------------------------- 3.3% 4.6% 62635 0.011s β”‚ β”‚ β”œβ”€pose proof H as H' -------------- 11.4% 11.4% 55172 0.009s β”‚ β”‚ β”œβ”€specialize (constr_with_bindings) 10.5% 10.5% 55172 0.010s β”‚ β”‚ β”œβ”€canonicalize_map_hyp ------------ 1.7% 7.3% 7328 0.014s β”‚ β”‚ β”‚ β”œβ”€rew_map_specs_in -------------- 0.9% 2.9% 7328 0.014s β”‚ β”‚ β”‚ └─specialize (constr_with_binding 2.2% 2.2% 7328 0.013s β”‚ β”‚ β”œβ”€Tactics.ensure_new -------------- 1.1% 3.1% 7328 0.014s β”‚ β”‚ β”‚β””assert_fails -------------------- 0.4% 2.0% 7328 0.014s β”‚ β”‚ └─unify (constr) (constr) --------- 2.2% 2.2% 75866 0.009s β”‚ └─maps_propositional ---------------- 0.0% 2.8% 22 0.231s └─preprocess_impl --------------------- 0.1% 3.1% 18 0.116s β””abstract_unrecogs ------------------- 0.4% 2.4% 18 0.107s make[3]: Leaving directory 'bedrock2/deps/coqutil' make[2]: Leaving directory 'bedrock2/deps/coqutil' make -C bedrock2/deps/riscv-coq all make -C bedrock2/bedrock2 make[2]: Entering directory 'bedrock2/deps/riscv-coq' /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = riscv -arg "-async-proofs-tac-j 1" bedrock2/deps/riscv-coq/src/Spec/Primitives.v bedrock2/deps/riscv-coq/src/Spec/ExecuteI.v bedrock2/deps/riscv-coq/src/Spec/ExecuteI64.v bedrock2/deps/riscv-coq/src/Spec/MetricPrimitives.v bedrock2/deps/riscv-coq/src/Spec/Machine.v bedrock2/deps/riscv-coq/src/Spec/ExecuteM.v bedrock2/deps/riscv-coq/src/Spec/ExecuteM64.v bedrock2/deps/riscv-coq/src/Spec/PseudoInstructions.v bedrock2/deps/riscv-coq/src/Spec/Execute.v bedrock2/deps/riscv-coq/src/Spec/Decode.v bedrock2/deps/riscv-coq/src/Spec/VirtualMemory.v bedrock2/deps/riscv-coq/src/Utility/MMIOTrace.v bedrock2/deps/riscv-coq/src/Utility/InstructionNotations.v bedrock2/deps/riscv-coq/src/Utility/nat_div_mod_to_quot_rem.v bedrock2/deps/riscv-coq/src/Utility/prove_Zeq_bitwise.v bedrock2/deps/riscv-coq/src/Utility/InstructionCoercions.v bedrock2/deps/riscv-coq/src/Utility/Words32Naive.v bedrock2/deps/riscv-coq/src/Utility/JMonad.v bedrock2/deps/riscv-coq/src/Utility/Utility.v bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl64.v bedrock2/deps/riscv-coq/src/Utility/runsToNonDet_Run.v bedrock2/deps/riscv-coq/src/Utility/ZBitOps.v bedrock2/deps/riscv-coq/src/Utility/MonadNotations.v bedrock2/deps/riscv-coq/src/Utility/Tactics.v bedrock2/deps/riscv-coq/src/Utility/MonadTests.v bedrock2/deps/riscv-coq/src/Utility/Words64Naive.v bedrock2/deps/riscv-coq/src/Utility/Encode.v bedrock2/deps/riscv-coq/src/Utility/MkMachineWidth.v bedrock2/deps/riscv-coq/src/Utility/MonadT.v bedrock2/deps/riscv-coq/src/Utility/div_mod_to_quot_rem.v bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl32.v bedrock2/deps/riscv-coq/src/Utility/PowerFunc.v bedrock2/deps/riscv-coq/src/Utility/ListLib.v bedrock2/deps/riscv-coq/src/Utility/runsToNonDet.v bedrock2/deps/riscv-coq/src/Utility/Monads.v bedrock2/deps/riscv-coq/src/Platform/MetricLogging.v bedrock2/deps/riscv-coq/src/Platform/Example64Literal.v bedrock2/deps/riscv-coq/src/Platform/RiscvMachine.v bedrock2/deps/riscv-coq/src/Platform/MetricMinimal.v bedrock2/deps/riscv-coq/src/Platform/Example.v bedrock2/deps/riscv-coq/src/Platform/Memory.v bedrock2/deps/riscv-coq/src/Platform/MinimalLogging.v bedrock2/deps/riscv-coq/src/Platform/Run.v bedrock2/deps/riscv-coq/src/Platform/MetricRiscvMachine.v bedrock2/deps/riscv-coq/src/Platform/Minimal.v bedrock2/deps/riscv-coq/src/Platform/MinimalMMIO.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_Fence.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA64.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeCSR.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_SB.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI64.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_U.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeProver.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_FenceI.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R_atomic.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM64.v bedrock2/deps/riscv-coq/src/Proofs/EncodeBound.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_S.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncode.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_system.v bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_UJ.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_57.v bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_66.v -o Makefile.coq.all make[2]: Entering directory 'bedrock2/bedrock2' printf -- '-Q src bedrock2\n-Q /builds/coq/coWarning: ../coqutil/src (used in -R or -Q) is not a subdirectory of the current directory bedrock2/bedrock2/src/Syntax (real: 0.28, user: 0.07, sys: 0.04, mem: 93508 ko) bedrock2/deps/riscv-coq/src/Utility/Monads (real: 1.74, user: 0.61, sys: 0.22, mem: 357880 ko) bedrock2/deps/riscv-coq/src/Utility/Tactics (real: 1.14, user: 0.34, sys: 0.21, mem: 294376 ko) bedrock2/bedrock2/src/Byte (real: 3.14, user: 1.29, sys: 0.27, mem: 418180 ko) bedrock2/bedrock2/src/Notations (real: 0.16, user: 0.04, sys: 0.03, mem: 56396 ko) bedrock2/deps/riscv-coq/src/Platform/MetricLogging (real: 1.44, user: 0.46, sys: 0.23, mem: 344552 ko) bedrock2/deps/riscv-coq/src/Utility/MMIOTrace (real: 0.17, user: 0.04, sys: 0.03, mem: 56096 ko) q/_build_ci/bedrock2/deps/coqutil/src coqutil\n' > _CoqProject /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = bedrock2 -arg "-async-proofs-tac-j 1" bedrock2/bedrock2/src/BasicCSyntax.v bedrock2/bedrock2/src/ToCString.v bedrock2/bedrock2/src/BytedumpTest.v bedrock2/bedrock2/src/BasicC32Semantics.v bedrock2/bedrock2/src/Byte.v bedrock2/bedrock2/src/Variables.v bedrock2/bedrock2/src/Semantics.v bedrock2/bedrock2/src/div10.v bedrock2/bedrock2/src/NotationsCustomEntry.v bedrock2/bedrock2/src/ListPred.v bedrock2/bedrock2/src/BasicC64Semantics.v bedrock2/bedrock2/src/Map/SeparationLogic.v bedrock2/bedrock2/src/Map/Separation.v bedrock2/bedrock2/src/Syntax.v bedrock2/bedrock2/src/WeakestPreconditionProperties.v bedrock2/bedrock2/src/NotationsInConstr.v bedrock2/bedrock2/src/WeakestPrecondition.v bedrock2/bedrock2/src/TODO_absint.v bedrock2/bedrock2/src/Bytedump.v bedrock2/bedrock2/src/FE310CSemantics.v bedrock2/bedrock2/src/StructNotations.v bedrock2/bedrock2/src/Examples/lightbulb.v bedrock2/bedrock2/src/Examples/MultipleReturnValues.v bedrock2/bedrock2/src/Examples/ARPResponder.v bedrock2/bedrock2/src/Examples/swap.v bedrock2/bedrock2/src/Examples/chacha20.v bedrock2/bedrock2/src/Examples/Demos.v bedrock2/bedrock2/src/Examples/bsearch.v bedrock2/bedrock2/src/Examples/Trace.v bedrock2/bedrock2/src/Examples/StructAccess.v bedrock2/bedrock2/src/Examples/FE310CompilerDemo.v bedrock2/bedrock2/src/Examples/ipow.v bedrock2/bedrock2/src/Markers.v bedrock2/bedrock2/src/Memory.v bedrock2/bedrock2/src/Structs.v bedrock2/bedrock2/src/Notations.v bedrock2/bedrock2/src/ProgramLogic.v bedrock2/bedrock2/src/Hexdump.v bedrock2/bedrock2/src/BasicC64Syntax.v bedrock2/bedrock2/src/Scalars.v bedrock2/bedrock2/src/string2ident.v bedrock2/bedrock2/src/ptsto_bytes.v bedrock2/bedrock2/src/StringNamesSyntax.v bedrock2/bedrock2/src/Lift1Prop.v bedrock2/bedrock2/src/ZNamesSyntax.v bedrock2/bedrock2/src/TailRecursion.v bedrock2/bedrock2/src/Array.v -o Makefile.coq.all make -f Makefile.coq.all make -f Makefile.coq.all make[3]: Entering directory 'bedrock2/deps/riscv-coq' make[3]: Entering directory 'bedrock2/bedrock2' ROCQ DEP VFILES ROCQ DEP VFILES ROCQ compile bedrock2/bedrock2/src/Syntax.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Monads.v ROCQ compile bedrock2/bedrock2/src/Byte.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Tactics.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/MetricLogging.v ROCQ compile bedrock2/bedrock2/src/Notations.v ROCQ compile bedrock2/bedrock2/src/div10.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/MMIOTrace.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/nat_div_mbedrock2/bedrock2/src/div10 (real: 1.82, user: 0.61, sys: 0.29, mem: 437628 ko) bedrock2/deps/riscv-coq/src/Utility/nat_div_mod_to_quot_rem (real: 1.14, user: 0.36, sys: 0.19, mem: 298516 ko) File "bedrock2/bedrock2/src/NotationsCustomEntry.v", line 50, characters 0-51: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_nontail.". [undeclared-scope,deprecated] File "bedrock2/bedrock2/src/NotationsCustomEntry.v", line 142, characters 0-45: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_tail.". [undeclared-scope,deprecated] File "bedrock2/deps/riscv-coq/src/Utility/JMonad.v", line 13, characters 0-102: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope monad_scope.". [undeclared-scope,deprecated] bedrock2/bedrock2/src/NotationsCustomEntry (real: 1.07, user: 0.33, sys: 0.18, mem: 301112 ko) bedrock2/deps/riscv-coq/src/Utility/JMonad (real: 0.64, user: 0.17, sys: 0.13, mem: 184664 ko) bedrock2/bedrock2/src/ListPred (real: 0.47, user: 0.13, sys: 0.09, mem: 144616 ko) File "bedrock2/deps/riscv-coq/src/Utility/MonadNotations.v", line 3, characters 0-102: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope monad_scope.". [undeclared-scope,deprecated] bedrock2/deps/riscv-coq/src/Utility/MonadNotations (real: 0.48, user: 0.12, sys: 0.11, mem: 146976 ko) bedrock2/deps/riscv-coq/src/Utility/PowerFunc (real: 0.20, user: 0.05, sys: 0.04, mem: 65768 ko) bedrock2/bedrock2/src/Lift1Prop (real: 0.32, user: 0.09, sys: 0.06, mem: 116312 ko) File "bedrock2/deps/riscv-coq/src/Utility/MonadTests.v", line 10, characters 0-102: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope monad_scope.". [undeclared-scope,deprecated] File "bedrock2/bedrock2/src/NotationsInConstr.v", line 5, characters 0-43: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_var.". [undeclared-scope,deprecated] File "bedrock2/bedrock2/src/NotationsInConstr.v", line 7, characters 0-45: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_expr.". [undeclared-scope,deprecated] File "bedrock2/bedrock2/src/NotationsInConstr.v", line 21, characters 0-43: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_cmd.". [undeclared-scope,deprecated] File "bedrock2/bedrock2/src/NotationsInConstr.v", line 46, characters 0-55: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bedrock_func_body.". [undeclared-scope,deprecated] bedrock2/bedrock2/src/NotationsInConstr (real: 0.66, user: 0.19, sys: 0.10, mem: 172428 ko) bedrock2/deps/riscv-coq/src/Utility/MonadTests (real: 0.93, user: 0.27, sys: 0.16, mem: 255852 ko) File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 17, characters 0-102: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope monad_scope.". [undeclared-scope,deprecated] File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 265, characters 2-23: Warning: State is declared as a local axiom [local-declaration,scope] File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 266, characters 2-37: Warning: step is declared as a local axiom [local-declaration,scope] File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 280, characters 2-23: Warning: State is declared as a local axiom [local-declaration,scope] File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 281, characters 2-37: Warning: step is declared as a local axiom [local-declaration,scope] File "bedrock2/deps/riscv-coq/src/Utility/MonadT.v", line 311, characters 2-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] bedrock2/deps/riscv-coq/src/Utility/MonadT (real: 0.78, user: 0.23, sys: 0.15, mem: 212520 ko) od_to_quot_rem.v ROCQ compile bedrock2/bedrock2/src/NotationsCustomEntry.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/JMonad.v ROCQ compile bedrock2/bedrock2/src/ListPred.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/MonadNotations.v ROCQ compile bedrock2/bedrock2/src/Lift1Prop.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/PowerFunc.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/MonadTests.v ROCQ compile bedrock2/bedrock2/src/NotationsInConstr.v = [(3, true); (3, false); (4, true); (4, false)] : Id (list (nat * bool)) = None : Id (option (list nat)) = [Some 3; Some 4; None] : Id (list (option nat)) = (tt, 5) : Id (unit * nat) = [(tt, 6); (tt, 7)] : Id (list (unit * nat)) = [0; 1; 2; 3] : list nat = [(tt, 0); (tt, 1); (tt, 2); (tt, 3)] : Id (list (unit * nat)) ROCQ compile bedrock2/bedrock2/src/Structs.v = ([(0, 1); (0, 0)], (0, 0)) : Id (list (nat * nat) * (nat * nat)) = [(0, 1, (0, 1)); (1, 0, (1, 0))] : Id (list (nat * nat * (nat * nat))) = ([0; 1; 2; 3], 3) : Id (list nat * nat) = ([0; 5; 6; 15], 15) : Id (list nat * nat) = (tt, <<20,10,10>>) : Id (unit * Regs) = ([<<0,20,30>>; <<1,20,30>>; <<2,20,30>>], <<2,20,30>>) : Id (list Regs * Regs) = ([<<0,11,11>>; <<1,11,11>>; <<2,11,11>>; <<3,11,11>>], <<3,11,11>>) : Id (list Regs * Regs) ROCQ compile bedrock2/deps/riscv-coq/src/Utility/MonadT.v = list (option nat) : Type = fun (A : Type) (aset : (A -> Prop) -> Prop) (f : (A -> Prop) -> A) (b : A) => exists a : A -> Prop, aset a /\ f a = b : forall A : Type, ((A -> Prop) -> Prop) -> ((A -> Prop) -> A) -> A -> Prop runsTo_ind : forall (initial : State) (P : State -> Prop) (P0 : Prop), (P initial -> P0) -> ((forall omid : option State, step initial omid -> exists mid : State, omid = Some mid /\ runsTo mid P) -> P0) -> runsTo initial P -> P0 runsTo_ind = fun (initial : State) (P : State -> Prop) (P0 : Prop) (f : P initial -> P0) (f0 : (forall omid : option (option unit * State), step initial omid -> exists mid : State, omid = Some (Some tt, mid) /\ runsTo mid P) -> P0) (r : runsTo initial P) => match r with | runsToDone _ _ x => f x | runsToStep _ _ x => f0 x end : forall (initial : State) (P : State -> Prop) (P0 : Prop), (P initial -> P0) -> ((forall omid : option (option unit * State), step initial omid -> exists mid : State, omid = Some (Some tt, mid) /\ runsTo mid P) -> P0) -> runsTo initial P -> P0 Argument scopes are [_ function_scope type_scope function_scope function_scope _] Closed under the global context ROCQ compile bedrock2/deps/riscv-coq/src/Utility/ListLib.v = 4%Z : Z = 20%Z : Z = 30%Z : Z = 90%Z : Z = inr (Struct (("first", Array 15 (Bytes 1)) :: ("last", Array 15 (Bytes 1)) :: nil), 30%Z) : PathError Z + type * Z = inr (Array 15 (Bytes 1), 45%Z) : PathError Z + type * Z = inr (Bytes 1, 47%Z) : PathError Z + type * Z = fun (p : parameters) (add mul : bopname) (base : expr) => inr (Struct (("first", Array 15 (Bytes 1)) :: ("last", Array 15 (Bytes 1)) :: nil), expr.op add base (expr.op mul (expr.literal 1) (expr.literal 30))) : forall p : parameters, bopname -> bopname -> expr -> PathError expr + type * expr = fun (p : parameters) (add mul : bopname) (base : expr) => inr (Array 15 (Bytes 1), expr.op add (expr.op add base (expr.op mul (expr.literal 1) (expr.literal 30))) (expr.literal 15)) : forall p : parameters, bopname -> bopname -> expr -> PathError expr + type * bedrock2/bedrock2/src/Structs (real: 1.31, user: 0.44, sys: 0.20, mem: 308516 ko) File "bedrock2/bedrock2/src/Markers.v", line 19, characters 2-71: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope hide_markers.". [undeclared-scope,deprecated] bedrock2/bedrock2/src/Markers (real: 0.18, user: 0.04, sys: 0.04, mem: 57444 ko) bedrock2/bedrock2/src/string2ident (real: 1.15, user: 0.36, sys: 0.20, mem: 272052 ko) File "bedrock2/bedrock2/src/Hexdump.v", line 16, characters 0-41: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope hexdump_scope.". [undeclared-scope,deprecated] bedrock2/bedrock2/src/Hexdump (real: 1.06, user: 0.32, sys: 0.19, mem: 274924 ko) bedrock2/deps/riscv-coq/src/Utility/ListLib (real: 2.96, user: 1.17, sys: 0.28, mem: 444076 ko) bedrock2/bedrock2/src/ZNamesSyntax (real: 1.16, user: 0.38, sys: 0.18, mem: 294268 ko) bedrock2/deps/riscv-coq/src/Utility/div_mod_to_quot_rem (real: 1.14, user: 0.37, sys: 0.18, mem: 295668 ko) File "bedrock2/deps/riscv-coq/src/Utility/runsToNonDet.v", line 20, characters 2-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/deps/riscv-coq/src/Utility/runsToNonDet.v", line 30, characters 2-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] bedrock2/deps/riscv-coq/src/Utility/runsToNonDet (real: 0.20, user: 0.05, sys: 0.03, mem: 65120 ko) bedrock2/bedrock2/src/Variables (real: 0.46, user: 0.13, sys: 0.09, mem: 149744 ko) bedrock2/bedrock2/src/StringNamesSyntax (real: 1.02, user: 0.30, sys: 0.18, mem: 252388 ko) File "bedrock2/bedrock2/src/Bytedump.v", line 2, characters 0-43: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bytedump_scope.". [undeclared-scope,deprecated] bedrock2/bedrock2/src/Bytedump (real: 1.08, user: 0.34, sys: 0.18, mem: 272812 ko) bedrock2/deps/riscv-coq/src/Utility/ZBitOps (real: 2.28, user: 0.83, sys: 0.28, mem: 439724 ko) File "bedrock2/deps/riscv-coq/src/Utility/Utility.v", line 120, characters 0-78: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope alu_scope.". [undeclared-scope,deprecated] bedrock2/deps/riscv-coq/src/Utility/Utility (real: 1.69, user: 0.57, sys: 0.25, mem: 358716 ko) bedrock2/bedrock2/src/Memory (real: 2.40, user: 0.84, sys: 0.30, mem: 443020 ko) bedrock2/bedrock2/src/Map/Separation (real: 1.31, user: 0.43, sys: 0.20, mem: 289244 ko) bedrock2/deps/riscv-coq/src/Utility/prove_Zeq_bitwise (real: 2.66, user: 0.95, sys: 0.32, mem: 441452 ko) bedrock2/bedrock2/src/StructNotations (real: 1.10, user: 0.35, sys: 0.18, mem: 267768 ko) bedrock2/deps/riscv-coq/src/Utility/Words32Naive (real: 1.51, user: 0.52, sys: 0.21, mem: 346660 ko) bedrock2/bedrock2/src/ToCString (real: 1.34, user: 0.48, sys: 0.17, mem: 276676 ko) bedrock2/deps/riscv-coq/src/Utility/Words64Naive (real: 1.41, user: 0.49, sys: 0.19, mem: 346980 ko) bedrock2/bedrock2/src/BytedumpTest (real: 1.52, user: 0.49, sys: 0.25, mem: 411496 ko) bedrock2/bedrock2/src/BytedumpTestΞ± (real: 1.52, user: 0.49, sys: 0.25, mem: 411496 ko) bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl32 (real: 1.64, user: 0.55, sys: 0.23, mem: 376020 ko) bedrock2/bedrock2/src/Semantics (real: 1.81, user: 0.66, sys: 0.26, mem: 441912 ko) bedrock2/deps/riscv-coq/src/Spec/Decode (real: 2.09, user: 0.71, sys: 0.28, mem: 446048 ko) bedrock2/deps/riscv-coq/src/Platform/Memory (real: 2.06, user: 0.71, sys: 0.27, mem: 449484 ko) bedrock2/bedrock2/src/Map/SeparationLogic (real: 4.20, user: 1.76, sys: 0.27, mem: 433996 ko) bedrock2/deps/riscv-coq/src/Spec/Machine (real: 1.50, user: 0.49, sys: 0.24, mem: 375808 ko) bedrock2/bedrock2/src/WeakestPrecondition (real: 1.67, user: 0.56, sys: 0.24, mem: 410516 ko) bedrock2/deps/riscv-coq/src/Platform/RiscvMachine (real: 1.48, user: 0.48, sys: 0.24, mem: 370692 ko) bedrock2/deps/riscv-coq/src/Utility/MkMachineWidth (real: 1.44, user: 0.49, sys: 0.21, mem: 360632 ko) bedrock2/bedrock2/src/Array (real: 3.30, user: 1.35, sys: 0.27, mem: 457132 ko) bedrock2/deps/riscv-coq/src/Spec/VirtualMemory (real: 1.33, user: 0.43, sys: 0.22, mem: 321032 ko) bedrock2/bedrock2/src/BasicC64Syntax (real: 1.40, user: 0.47, sys: 0.21, mem: 321560 ko) bedrock2/deps/riscv-coq/src/Platform/MetricRiscvMachine (real: 1.49, user: 0.48, sys: 0.24, mem: 362608 ko) bedrock2/deps/riscv-coq/src/Spec/ExecuteM (real: 1.62, user: 0.53, sys: 0.26, mem: 387416 ko) bedrock2/bedrock2/src/Examples/Trace (real: 2.96, user: 1.14, sys: 0.29, mem: 449412 ko) bedrock2/deps/riscv-coq/src/Spec/ExecuteM64 (real: 1.64, user: 0.52, sys: 0.25, mem: 375816 ko) bedrock2/bedrock2/src/Examples/StructAccess (real: 1.12, user: 0.35, sys: 0.19, mem: 272888 ko) bedrock2/deps/riscv-coq/src/Spec/PseudoInstructions (real: 1.40, user: 0.47, sys: 0.21, mem: 338992 ko) bedrock2/bedrock2/src/BasicCSyntax (real: 1.40, user: 0.50, sys: 0.18, mem: 322924 ko) expr = fun (p : parameters) (add mul : bopname) (base : expr) => inr (Bytes 1, expr.op add (expr.op add (expr.op add base (expr.op mul (expr.literal 1) (expr.literal 30))) (expr.literal 15)) (expr.op mul (expr.literal 2) (expr.literal 1))) : forall p : parameters, bopname -> bopname -> expr -> PathError expr + type * expr ROCQ compile bedrock2/bedrock2/src/Markers.v ROCQ compile bedrock2/bedrock2/src/string2ident.v ROCQ compile bedrock2/bedrock2/src/Hexdump.v ROCQ compile bedrock2/bedrock2/src/ZNamesSyntax.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/div_mod_to_quot_rem.v ROCQ compile bedrock2/bedrock2/src/Variables.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/runsToNonDet.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/ZBitOps.v ROCQ compile bedrock2/bedrock2/src/StringNamesSyntax.v ROCQ compile bedrock2/bedrock2/src/Bytedump.v ROCQ compile bedrock2/bedrock2/src/Memory.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Utility.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/prove_Zeq_bitwise.v ROCQ compile bedrock2/bedrock2/src/Map/Separation.v ROCQ compile bedrock2/bedrock2/src/StructNotations.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Words32Naive.v ROCQ compile bedrock2/bedrock2/src/ToCString.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Words64Naive.v ROCQ compile bedrock2/bedrock2/src/BytedumpTest.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl32.v   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ ROCQ compile bedrock2/bedrock2/src/Semantics.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/Decode.v ROCQ compile bedrock2/bedrock2/src/Map/SeparationLogic.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/Memory.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/Machine.v ROCQ compile bedrock2/bedrock2/src/WeakestPrecondition.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/RiscvMachine.v ROCQ compile bedrock2/bedrock2/src/Array.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/MkMachineWidth.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/VirtualMemory.v ROCQ compile bedrock2/bedrock2/src/BasicC64Syntax.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/MetricRiscvMachine.v ROCQ compile bedrock2/bedrock2/src/Examples/Trace.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/ExecuteM.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/ExecuteM64.v squarer_correct : forall (m : Semantics.mem) (l : Semantics.locals), exec map.empty squarer [] m l (fun (t' : trace) (_ : Semantics.mem) (_ : Semantics.locals) => squarer_trace t') squarer_correct : forall (m : Semantics.mem) (l : Semantics.locals), exec map.empty squarer [] m l (fun (t' : trace) (_ : Semantics.mem) (_ : Semantics.locals) => squarer_trace t') ROCQ compile bedrock2/bedrock2/src/Examples/StructAccess.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/PseudoInstructions.v ROCQ compile bedrock2/bedrock2/src/BasicCSyntax.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/InstructionCoercions.v ROCQ compile bedrock2/bedrock2/src/WeakestPreconditionFile "bedrock2/deps/riscv-coq/src/Utility/InstructionCoercions.v", line 10, characters 0-70: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope ilist_scope.". [undeclared-scope,deprecated] bedrock2/deps/riscv-coq/src/Utility/InstructionCoercions (real: 1.33, user: 0.43, sys: 0.21, mem: 313976 ko) bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl64 (real: 1.59, user: 0.52, sys: 0.25, mem: 375840 ko) bedrock2/deps/riscv-coq/src/Utility/Encode (real: 2.03, user: 0.67, sys: 0.31, mem: 446648 ko) bedrock2/deps/riscv-coq/src/Spec/Primitives (real: 2.21, user: 0.72, sys: 0.34, mem: 457772 ko) bedrock2/deps/riscv-coq/src/Spec/ExecuteI (real: 2.60, user: 0.94, sys: 0.32, mem: 454504 ko) bedrock2/deps/riscv-coq/src/Spec/ExecuteI64 (real: 1.85, user: 0.55, sys: 0.28, mem: 401008 ko) bedrock2/deps/riscv-coq/src/Spec/MetricPrimitives (real: 2.20, user: 0.76, sys: 0.30, mem: 459200 ko) bedrock2/deps/riscv-coq/src/Spec/Execute (real: 1.43, user: 0.44, sys: 0.24, mem: 336624 ko) bedrock2/deps/riscv-coq/src/Utility/InstructionNotations (real: 1.41, user: 0.44, sys: 0.24, mem: 340268 ko) bedrock2/deps/riscv-coq/src/Platform/Run (real: 1.69, user: 0.52, sys: 0.27, mem: 374676 ko) File "bedrock2/bedrock2/src/WeakestPreconditionProperties.v", line 193, characters 2-41: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] bedrock2/bedrock2/src/WeakestPreconditionProperties (real: 19.56, user: 9.19, sys: 0.41, mem: 663884 ko) bedrock2/bedrock2/src/FE310CSemantics (real: 8.23, user: 3.64, sys: 0.34, mem: 472892 ko) File "bedrock2/bedrock2/src/TailRecursion.v", line 16, characters 2-67: Warning: Notation "_ /\ _" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 47, characters 2-14: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 47, characters 2-14: Warning: Notation "{ _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 47, characters 2-14: Warning: Notation "{ _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 47, characters 2-14: Warning: Notation "{ ' _ : _ & _ }" was already used in scope type_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 47, characters 2-14: Warning: Notation "( _ , _ , .. , _ )" was already used in scope core_scope. [notation-overridden,parsing] File "bedrock2/bedrock2/src/TailRecursion.v", line 138, characters 2-49: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] bedrock2/bedrock2/src/TailRecursion (real: 3.43, user: 1.34, sys: 0.32, mem: 461368 ko) bedrock2/deps/riscv-coq/src/Platform/Minimal (real: 14.97, user: 6.99, sys: 0.33, mem: 482444 ko) File "bedrock2/bedrock2/src/ptsto_bytes.v", line 151, characters 6-173: Warning: Unused introduction patterns: R IH [unused-intro-pattern,tactics] File "bedrock2/bedrock2/src/ptsto_bytes.v", line 163, characters 6-132: Warning: Unused introduction patterns: R IH [unused-intro-pattern,tactics] bedrock2/bedrock2/src/ptsto_bytes (real: 4.33, user: 1.80, sys: 0.31, mem: 461200 ko) bedrock2/bedrock2/src/Examples/MultipleReturnValues (real: 1.64, user: 0.54, sys: 0.23, mem: 310296 ko) bedrock2/bedrock2/src/Examples/ARPResponder (real: 4.88, user: 2.06, sys: 0.33, mem: 465924 ko) bedrock2/bedrock2/src/Examples/chacha20 (real: 3.11, user: 1.25, sys: 0.26, mem: 435736 ko) Properties.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/DefaultMemImpl64.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/Encode.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/Primitives.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/ExecuteI.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/ExecuteI64.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/MetricPrimitives.v ROCQ compile bedrock2/deps/riscv-coq/src/Spec/Execute.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/InstructionNotations.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/Run.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/Minimal.v ROCQ compile bedrock2/bedrock2/src/FE310CSemantics.v ROCQ compile bedrock2/bedrock2/src/TailRecursion.v ROCQ compile bedrock2/bedrock2/src/ptsto_bytes.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/MinimalMMIO.v ROCQ compile bedrock2/bedrock2/src/Examples/MultipleReturnValues.v ROCQ compile bedrock2/bedrock2/src/Examples/ARPResponder.v ROCQ compile bedrock2/bedrock2/src/Examples/chacha20.v ROCQ compile bedrock2/bedrock2/src/Examples/Demos.v allProgs@{bedrock2.Examples.Demos.686 bedrock2.Examples.Demos.687} = [("bsearch", ([left; right; target], [left], (while (right - left) {{ mid = left + (right - left) >> 4 << 3;; (if (*(uintptr_t*) mid < target) {{ left = mid + 8 }} else {{ right = mid }});; cmd.unset mid }})%bedrock_cmd)); ("listsum", ([], [sumreg], (sumreg = 0;; n = *(uint32_t*) 1024;; ListSum.i = 0;; while (ListSum.i < n) {{ ListSum.a = *(uint32_t*) (1024 + 4 + 4 * ListSum.i);; sumreg = sumreg + ListSum.a;; ListSum.i = ListSum.i + 1 }})%bedrock_cmd)); ("fibonacci", ([], [b], (a = 0;; b = 1;; i = 0;; while (i < 6) {{ c = a + b;; a = b;; b = c;; i = i + 1 }})%bedrock_cmd))] : list Prog allProgs@{bedrock2.Examples.Demos.135 bedrock2.Examples.Demos.136 bedrock2.Examples.Demos.137 bedrock2.Examples.Demos.146 bedrock2.Examples.Demos.171 bedrock2.Examples.Demos.345 bedrock2.Examples.Demos.515 bedrock2.Examples.Demos.686 bedrock2.Examples.Demos.687} = fun (p : Syntax.parameters) (bsearchNames : BinarySearch.Names) (listsumNames : ListSum.Names) (fibonacciNames : Fibonacci.Names) => [("bsearch", ([BinarySearch.left; BinarySearch.right; BinarySearch.target], [BinarySearch.left], cmd.while (expr.op bopname.sub (var BinarySearch.right) (var BinarySearch.left)) (cmd.seq (cmd.set BinarySearch.mid (expr.op bopname.add (var BinarySearch.left) (expr.op bopname.slu (expr.op bopname.sru (expr.op bopname.sub (var BinarySearch.right) (var BinarySearch.left)) (literal 4)) (literal 3)))) (cmd.seq (cmd.cond (expr.op bopname.ltu (expr.load access_size.word (var BinarySearch.mid)) (var BinarySearch.target)) (cmd.set BinarySearch.left (expr.op bopname.add (var BinarySearch.mid) (literal 8))) (cmd.set BinarySearch.right (var BinarySearch.mid))) (cmd.unset BinarySearch.mid))))); ("listsum", ([], [ListSum.sumreg], cmd.seq (cmd.set ListSum.sumreg (literal 0)) (cmd.seq (cmd.set ListSum.n (expr.load access_size.four (literal 1024))) (cmd.seq (cmd.set ListSum.i (literal 0)) (cmd.while (expr.op bopname.ltu (var ListSum.i) (var ListSum.n)) (cmd.seq (cmd.set ListSum.a (expr.load access_size.four (expr.op bopname.add (literal (1024 + 4)) (expr.op bopname.mul (literal 4) (var ListSum.i))))) (cmd.seq (cmd.set ListSum.sumreg (expr.op bopname.add (var ListSum.sumreg) (var ListSum.a))) bedrock2/bedrock2/src/Examples/Demos (real: 1.93, user: 0.69, sys: 0.23, mem: 353168 ko) bedrock2/bedrock2/src/BasicC32Semantics (real: 1.66, user: 0.55, sys: 0.25, mem: 387552 ko) bedrock2/bedrock2/src/BasicC64Semantics (real: 1.74, user: 0.57, sys: 0.27, mem: 403188 ko) bedrock2/bedrock2/src/Scalars (real: 3.04, user: 1.18, sys: 0.30, mem: 457564 ko) bedrock2/bedrock2/src/TODO_absint (real: 2.93, user: 1.13, sys: 0.30, mem: 457912 ko) (cmd.set ListSum.i (expr.op bopname.add (var ListSum.i) (literal 1)))))))))); ("fibonacci", ([], [Fibonacci.b], cmd.seq (cmd.set Fibonacci.a (literal 0)) (cmd.seq (cmd.set Fibonacci.b (literal 1)) (cmd.seq (cmd.set Fibonacci.i (literal 0)) (cmd.while (expr.op bopname.ltu (var Fibonacci.i) (literal 6)) (cmd.seq (cmd.set Fibonacci.c (expr.op bopname.add (var Fibonacci.a) (var Fibonacci.b))) (cmd.seq (cmd.set Fibonacci.a (var Fibonacci.b)) (cmd.seq (cmd.set Fibonacci.b (var Fibonacci.c)) (cmd.set Fibonacci.i (expr.op bopname.add (var Fibonacci.i) (literal 1)))))))))))] : forall p : Syntax.parameters, BinarySearch.Names -> ListSum.Names -> Fibonacci.Names -> list Prog Arguments p, bsearchNames, listsumNames, fibonacciNames are implicit and maximally inserted allProgsAsCStrings@{} = ["uintptr_t bsearch(uintptr_t left, uintptr_t right, uintptr_t target) { uintptr_t mid; while ((right)-(left)) { mid = (left)+((((right)-(left))>>((uintptr_t)4ULL))<<((uintptr_t)3ULL)); if ((*(uintptr_t*)(mid))<(target)) { left = (mid)+((uintptr_t)8ULL); } else { right = mid; } // unset mid } return left; } "; "uintptr_t listsum() { uintptr_t n, sumreg, a, i; sumreg = (uintptr_t)0ULL; n = *(uint32_t*)((uintptr_t)1024ULL); i = (uintptr_t)0ULL; while ((i)<(n)) { a = *(uint32_t*)(((uintptr_t)1028ULL)+(((uintptr_t)4ULL)*(i))); sumreg = (sumreg)+(a); i = (i)+((uintptr_t)1ULL); } return sumreg; } "; "uintptr_t fibonacci() { uintptr_t a, b, c, i; a = (uintptr_t)0ULL; b = (uintptr_t)1ULL; i = (uintptr_t)0ULL; while ((i)<((uintptr_t)6ULL)) { c = (a)+(b); a = b; b = c; i = (i)+((uintptr_t)1ULL); } return b; } "] : list string allProgsWithZNames@{bedrock2.Examples.Demos.721} = [("bsearch", ([1; 2; 3], [1], cmd.while (expr.op bopname.sub (expr.var 2) (expr.var 1)) (cmd.seq (cmd.set 4 (expr.op bopname.add (expr.var 1) (expr.op bopname.slu (expr.op bopname.sru (expr.op bopname.sub (expr.var 2) (expr.var 1)) (expr.literal 4)) (expr.literal 3)))) (cmd.seq (cmd.cond (expr.op bopname.ltu (expr.load access_size.word (expr.var 4)) (expr.var 3)) (cmd.set 1 (expr.op bopname.add (expr.var 4) (expr.literal 8))) (cmd.set 2 (expr.var 4))) (cmd.unset 4))))); ("listsum", ([], [3], cmd.seq (cmd.set 3 (expr.literal 0)) (cmd.seq (cmd.set 1 (expr.load access_size.four (expr.literal 1024))) (cmd.seq (cmd.set 2 (expr.literal 0)) (cmd.while (expr.op bopname.ltu (expr.var 2) (expr.var 1)) (cmd.seq (cmd.set 4 (expr.load access_size.four (expr.op bopname.add (expr.literal 1028) (expr.op bopname.mul (expr.literal 4) (expr.var 2))))) (cmd.seq (cmd.set 3 (expr.op bopname.add (expr.var 3) (expr.var 4))) (cmd.set 2 (expr.op bopname.add (expr.var 2) (expr.literal 1)))))))))); ("fibonacci", ([], [2], cmd.seq (cmd.set 1 (expr.literal 0)) (cmd.seq (cmd.set 2 (expr.literal 1)) (cmd.seq (cmd.set 4 (expr.literal 0)) (cmd.while (expr.op bopname.ltu (expr.var 4) (expr.literal 6)) (cmd.seq (cmd.set 3 (expr.op bopname.add (expr.var 1) (expr.var 2))) (cmd.seq (cmd.set 1 (expr.var 2)) (cmd.seq (cmd.set 2 (expr.var 3)) (cmd.set 4 (expr.op bopname.add (expr.var 4) (expr.literal 1)))))))))))] : list (string * (list Z * list Z * cmd)) ROCQ compile bedrock2/bedrock2/src/BasicC32Semantics.v ROCQ compile bedrock2/bedrock2/src/BasicC64Semantics.v ROCQ compile bedrock2/bedrock2/src/Scalars.v ROCQ compile bedrock2/bedrock2/src/TODO_absint.v bedrock2/bedrock2/src/ProgramLogic (real: 1.65, user: 0.52, sys: 0.25, mem: 371960 ko) File "bedrock2/bedrock2/src/Examples/lightbulb.v", line 48, characters 0-36: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] bedrock2/bedrock2/src/Examples/lightbulb (real: 44.98, user: 21.59, sys: 0.37, mem: 525428 ko) File "bedrock2/bedrock2/src/Examples/swap.v", line 31, characters 24-60: Warning: Notation "_ * _" was already used in scope type_scope. [notation-overridden,parsing] bedrock2/bedrock2/src/Examples/swap (real: 8.68, user: 3.88, sys: 0.33, mem: 478956 ko) bedrock2/deps/riscv-coq/src/Platform/MinimalMMIO (real: 140.04, user: 67.92, sys: 0.50, mem: 590104 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_Fence (real: 19.81, user: 9.16, sys: 0.36, mem: 495544 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R (real: 13.71, user: 6.32, sys: 0.36, mem: 478812 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R_atomic (real: 18.82, user: 8.68, sys: 0.36, mem: 494004 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I (real: 14.67, user: 6.82, sys: 0.30, mem: 485168 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_57 (real: 13.83, user: 6.36, sys: 0.32, mem: 478692 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_66 (real: 40.12, user: 19.20, sys: 0.36, mem: 526372 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_system (real: 10.48, user: 4.71, sys: 0.33, mem: 470712 ko) bedrock2/bedrock2/src/Examples/bsearch (real: 208.32, user: 101.50, sys: 0.51, mem: 564436 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_S (real: 25.56, user: 12.11, sys: 0.34, mem: 518652 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_SB (real: 55.25, user: 26.55, sys: 0.40, mem: 632108 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_U (real: 9.99, user: 4.46, sys: 0.31, mem: 468412 ko) bedrock2/bedrock2/src/Examples/FE310CompilerDemo (real: 83.94, user: 40.64, sys: 0.41, mem: 588832 ko) bedrock2/bedrock2/src/Examples/ipow (real: 19.97, user: 9.35, sys: 0.30, mem: 496100 ko) /bin/sh: 1: hexdump: not found bedrock2/deps/riscv-coq/src/Proofs/invert_encode_UJ (real: 39.56, user: 19.19, sys: 0.35, mem: 580040 ko) bedrock2/deps/riscv-coq/src/Proofs/invert_encode_FenceI (real: 14.48, user: 6.72, sys: 0.31, mem: 485544 ko) bedrock2/deps/riscv-coq/src/Utility/runsToNonDet_Run (real: 1.66, user: 0.58, sys: 0.23, mem: 408744 ko) bedrock2/deps/riscv-coq/src/Platform/MinimalLogging (real: 2.10, user: 0.74, sys: 0.27, mem: 460380 ko) bedrock2/deps/riscv-coq/src/Platform/MetricMinimal (real: 24.74, user: 11.74, sys: 0.31, mem: 501100 ko) ROCQ compile bedrock2/bedrock2/src/ProgramLogic.v ROCQ compile bedrock2/bedrock2/src/Examples/lightbulb.v = "uintptr_t lightbulb(uintptr_t packet, uintptr_t len) { uintptr_t ethertype, protocol, mmio_val, command, r; ethertype = ((*(uint8_t*)((packet)+((uintptr_t)12ULL)))<<((uintptr_t)8ULL))|(*(uint8_t*)((packet)+((uintptr_t)13ULL))); if (((uintptr_t)1535ULL)<(ethertype)) { protocol = *(uint8_t*)((packet)+((uintptr_t)23ULL)); if ((protocol)==((uintptr_t)17ULL)) { command = *(uint8_t*)((packet)+((uintptr_t)42ULL)); mmio_val = MMIOREAD((uintptr_t)268509192ULL); MMIOWRITE((uintptr_t)268509192ULL, (mmio_val)|(((uintptr_t)1ULL)<<((uintptr_t)23ULL))); mmio_val = MMIOREAD((uintptr_t)268509196ULL); MMIOWRITE((uintptr_t)268509196ULL, (mmio_val)|((command)<<((uintptr_t)23ULL))); r = (uintptr_t)0ULL; } else { r = (uintptr_t)-1ULL; } } else { r = (uintptr_t)-1ULL; } return r; } " : string ROCQ compile bedrock2/bedrock2/src/Examples/swap.v static void swap(uintptr_t a, uintptr_t b); void swap_swap(uintptr_t a, uintptr_t b) { swap(a, b); swap(a, b); return; } static void swap(uintptr_t a, uintptr_t b) { uintptr_t t; t = *(uintptr_t*)(b); *(uintptr_t*)(b) = *(uintptr_t*)(a); *(uintptr_t*)(a) = t; return; } ROCQ compile bedrock2/bedrock2/src/Examples/bsearch.v H19 H13 ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_Fence.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_R_atomic.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_57.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_shift_66.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_I_system.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_S.v ROCQ compile bedrock2/bedrock2/src/Examples/FE310CompilerDemo.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_SB.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_U.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_UJ.v ROCQ compile bedrock2/bedrock2/src/Examples/ipow.v make[3]: Leaving directory 'bedrock2/bedrock2' make src/BytedumpTest.out make[3]: Entering directory 'bedrock2/bedrock2' coqc -q -Q src bedrock2 -Q bedrock2/deps/coqutil/src coqutil src/BytedumpTest.v | head --bytes -1 > src/BytedumpTest.out.tmp hexdump < /dev/null && \ hexdump -C src/BytedumpTest.golden.bin > src/BytedumpTest.golden.hex && \ hexdump -C src/BytedumpTest.out.tmp > src/BytedumpTest.out.hex && \ diff -u src/BytedumpTest.golden.hex src/BytedumpTest.out.hex && \ rm src/BytedumpTest.golden.hex src/BytedumpTest.out.hex || true diff -u src/BytedumpTest.golden.bin src/BytedumpTest.out.tmp mv src/BytedumpTest.out.tmp src/BytedumpTest.out make[3]: Leaving directory 'bedrock2/bedrock2' make[2]: Leaving directory 'bedrock2/bedrock2' ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/invert_encode_FenceI.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/EncodeBound.v ROCQ compile bedrock2/deps/riscv-coq/src/Utility/runsToNonDet_Run.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/MinimalLogging.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/MetricMinimal.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/Example.v = [({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; Sbedrock2/deps/riscv-coq/src/Platform/Example (real: 4.13, user: 1.62, sys: 0.27, mem: 468188 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeProver (real: 2.54, user: 0.94, sys: 0.29, mem: 450352 ko) bedrock2/deps/riscv-coq/src/Platform/Example64Literal (real: 2.12, user: 0.76, sys: 0.28, mem: 409784 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA64 (real: 55.42, user: 26.45, sys: 0.45, mem: 605916 ko) bedrock2/deps/riscv-coq/src/Proofs/EncodeBound (real: 103.45, user: 50.15, sys: 0.41, mem: 573560 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI64 (real: 53.82, user: 25.80, sys: 0.43, mem: 650288 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA (real: 60.04, user: 28.68, sys: 0.44, mem: 639092 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeCSR (real: 215.18, user: 104.22, sys: 0.79, mem: 997556 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM64 (real: 21.95, user: 9.77, sys: 0.34, mem: 523092 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM (real: 47.35, user: 22.60, sys: 0.37, mem: 589708 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI (real: 226.75, user: 139.56, sys: 1.26, mem: 1730872 ko) bedrock2/deps/riscv-coq/src/Proofs/DecodeEncode (real: 0.81, user: 0.42, sys: 0.18, mem: 374624 ko) ortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 32 (IInstruction (Addi 9 9 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 28 (IInstruction (Addi 18 21 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 24 (IInstruction (Addi 20 18 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 20 (IInstruction (Add 21 20 18)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 36 (IInstruction (Blt 9 19 (-16))), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 16 (IInstruction (Jal 0 20)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 12 (IInstruction (Addi 9 0 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 8 (IInstruction (Addi 18 0 1)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 4 (IInstruction (Addi 20 0 0)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, [])); ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, EvLoadWord 0 (IInstruction (Addi 19 0 6)), [], ({| SortedList.value := []; SortedList._value_ok := eq_refl |}, []))] : list (LogItem LogEvent) ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeProver.v ROCQ compile bedrock2/deps/riscv-coq/src/Platform/Example64Literal.v = {| unsigned := 1073745919; _unsigned_in_range := eq_refl |} : word64 ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA64.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeCSR.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI64.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeA.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeI.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM64.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncodeM.v ROCQ compile bedrock2/deps/riscv-coq/src/Proofs/DecodeEncode.v make[3]: Leaving directory 'bedrock2/deps/riscv-coq' make[2]: Leaving directory 'bedrock2/deps/riscv-coq' make -C bedrock2/compiler make -C bedrock2/deps/kami make[2]: Entering directory 'bedrock2/compiler' printf -- '-Q ../bedrock2/src bedrock2\n-Q bedrock2/deps/coqutil/src coqutil\n-Q bedrock2/deps/riscv-coq/src riscv\n-Q ./lib lib\n-Q ./src compiler\n' > _CoqProject /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = bedrock2 -arg "-async-proofs-tac-j 1" bedrock2/compiler/src/EmitsValid.v bedrock2/compiler/src/util/Misc.v bedrock2/compiler/src/util/Learning.v bedrock2/compiler/src/util/Tactics.v bedrock2/compiler/src/util/MyOmega.v bedrock2/compiler/src/util/ListLib.v bedrock2/compiler/src/util/Set.v bedrock2/compiler/src/util/SetSolverTests.v bedrock2/compiler/src/util/Common.v bedrock2/compiler/src/util/LogGoal.v bedrock2/compiler/src/SeparationLogic.v bedrock2/compiler/src/ExprImp.v bedrock2/compiler/src/FlatToRiscv32.v bedrock2/compiler/src/FlatToRiscv.v bedrock2/compiler/src/on_hyp_containing.v bedrock2/compiler/src/Basic32Semantics.v bedrock2/compiler/src/Simp.v bedrock2/compiler/src/FlatToRiscvDef.v bedrock2/compiler/src/RegAlloc3.v bedrock2/compiler/src/RegAllocAnnotatedNotations.v bedrock2/compiler/src/UnmappedMemForExtSpec.v bedrock2/compiler/src/RegAlloc2.v bedrock2/compiler/src/NoActionSyntaxParams.v bedrock2/compiler/src/Pipeline.v bedrock2/compiler/src/RiscvWordProperties.v bedrock2/compiler/src/GoFlatToRiscv.v bedrock2/compiler/src/Rem4.v bedrock2/compiler/src/SimplWordExpr.v bedrock2/compiler/src/ZNameGen.v bedrock2/compiler/src/NameGen.v bedrock2/compiler/src/FlatImp.v bedrock2/compiler/src/FlattenExpr.v bedrock2/compiler/src/eqexact.v bedrock2/compiler/src/examples/swap_bytes_over_uart_hexdump.v bedrock2/compiler/src/examples/TestExprImp.v bedrock2/compiler/src/examples/highlevel/FuncMut.v bedrock2/compiler/src/examples/highlevel/For.v bedrock2/compiler/src/examples/InlineAssemblyMacro.v bedrock2/compiler/src/examples/CompileExamples.v bedrock2/compiler/src/examples/toposort.v bedrock2/compiler/src/examples/FE310Compiler.v bedrock2/compiler/src/examples/EditDistExample.v bedrock2/compiler/src/examples/Fibonacci.v bedrock2/compiler/src/examples/TestFlatImp.v bedrock2/compiler/src/examples/MMIO.v bedrock2/compiler/lib/LibTacticsMin.v bedrock2/compiler/lib/fiat_crypto_tactics/Not.v bedrock2/compiler/lib/fiat_crypto_tactics/Test.v bedrock2/compiler/lib/fiat_crypto_tactics/UniquePose.v bedrock2/compiler/lib/LibTactics.v -o Makefile.coq.all make[2]: Entering directory 'bedrock2/deps/kami' printf -- '-R Kami Kami\n-Q bedrock2/deps/Warning: ../bedrock2/src (used in -R or -Q) is not a subdirectory of the current directory Warning: bedrock2/deps/riscv-coq/src (used in -R or -Q) is not a subdirectory of the current directory Warning: no common logical root Warning: in such case INSTALLDEFAULTROOT must be defined Warning: the install-doc target is going to install files Warning: in orphan_riscv_coqutil_Kami bedrock2/compiler/lib/fiat_crypto_tactics/Test (real: 0.17, user: 0.04, sys: 0.04, mem: 55660 ko) File "bedrock2/compiler/lib/LibTacticsMin.v", line 76, characters 0-32: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/compiler/lib/LibTacticsMin.v", line 121, characters 0-42: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope ltac_scope.". [undeclared-scope,deprecated] File "bedrock2/compiler/lib/LibTacticsMin.v", line 463, characters 0-16: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] bedrock2/compiler/lib/LibTacticsMin (real: 0.92, user: 0.31, sys: 0.14, mem: 301996 ko) bedrock2/compiler/src/NoActionSyntaxParams (real: 0.17, user: 0.04, sys: 0.03, mem: 57364 ko) bedrock2/compiler/lib/fiat_crypto_tactics/UniquePose (real: 0.16, user: 0.04, sys: 0.03, mem: 57340 ko) File "./Kami/Lib/StringAsOT.v", line 86, characters 2-38: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/StringAsOT (real: 1.80, user: 0.70, sys: 0.19, mem: 423260 ko) bedrock2/compiler/src/Simp (real: 1.02, user: 0.36, sys: 0.13, mem: 298624 ko) bedrock2/compiler/src/util/Misc (real: 0.19, user: 0.05, sys: 0.04, mem: 70976 ko) bedrock2/compiler/src/util/Learning (real: 0.16, user: 0.04, sys: 0.03, mem: 58420 ko) File "./Kami/Lib/CommonTactics.v", line 276, characters 0-39: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/CommonTactics.v", line 277, characters 0-92: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/CommonTactics (real: 1.03, user: 0.38, sys: 0.13, mem: 319992 ko) bedrock2/compiler/src/util/MyOmega (real: 0.97, user: 0.33, sys: 0.14, mem: 289700 ko) bedrock2/compiler/src/util/LogGoal (real: 0.15, user: 0.03, sys: 0.03, mem: 54716 ko) Kami/Lib/StringEq (real: 1.50, user: 0.55, sys: 0.18, mem: 413664 ko) File "bedrock2/compiler/src/SeparationLogic.v", line 10, characters 0-29: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope sep_scope.". [undeclared-scope,deprecated] bedrock2/compiler/src/SeparationLogic (real: 1.37, user: 0.48, sys: 0.16, mem: 352200 ko) Kami/Lib/Nomega (real: 1.17, user: 0.38, sys: 0.19, mem: 363832 ko) Kami/Lib/DepEq (real: 0.46, user: 0.14, sys: 0.08, mem: 160816 ko) Kami/Lib/VectorFacts (real: 0.56, user: 0.17, sys: 0.09, mem: 180940 ko) bedrock2/compiler/src/Rem4 (real: 1.86, user: 0.68, sys: 0.21, mem: 447424 ko) bedrock2/compiler/src/SimplWordExpr (real: 1.85, user: 0.67, sys: 0.22, mem: 446424 ko) Kami/Lib/StringAsList (real: 2.62, user: 1.08, sys: 0.20, mem: 421756 ko) Kami/Lib/FinNotations (real: 0.43, user: 0.13, sys: 0.07, mem: 142092 ko) bedrock2/compiler/src/RiscvWordProperties (real: 1.24, user: 0.43, sys: 0.18, mem: 362292 ko) bedrock2/compiler/src/eqexact (real: 0.15, user: 0.04, sys: 0.03, mem: 56364 ko) bedrock2/compiler/src/on_hyp_containing (real: 0.15, user: 0.04, sys: 0.03, mem: 56680 ko) Kami/Lib/Reflection (real: 1.00, user: 0.34, sys: 0.15, mem: 328692 ko) Kami/Lib/Concat (real: 1.06, user: 0.36, sys: 0.16, mem: 338456 ko) bedrock2/compiler/src/Basic32Semantics (real: 1.46, user: 0.50, sys: 0.20, mem: 385968 ko) riscv-coq/src riscv\n-Q bedrock2/deps/coqutil/src coqutil\n' > _CoqProject make -f Makefile.coq.all make[3]: Entering directory 'bedrock2/compiler' /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject Kami/Lib/StringStringAsOT.v Kami/Lib/FMap.v Kami/Lib/ilist.v Kami/Lib/Indexer.v Kami/Lib/DepEq.v Kami/Lib/Nomega.v Kami/Lib/StringEq.v Kami/Lib/Misc.v Kami/Lib/Word.v Kami/Lib/FinNotations.v Kami/Lib/Reflection.v Kami/Lib/NatLib.v Kami/Lib/StringAsList.v Kami/Lib/Concat.v Kami/Lib/ListSupport.v Kami/Lib/VectorFacts.v Kami/Lib/StringAsOT.v Kami/Lib/CommonTactics.v Kami/Lib/WordSupport.v Kami/Lib/BasicLogic.v Kami/Lib/DepEqNat.v Kami/Lib/Struct.v Kami/SemFacts.v Kami/ParametricInlineLtac.v Kami/PartialInlineFacts.v Kami/Wf.v Kami/Semantics.v Kami/ParametricSyntax.v Kami/Inline.v Kami/StepDet.v Kami/InlineFacts.v Kami/Amortization.v Kami/Tutorial.v Kami/Label.v Kami/MapReifyEx.v Kami/ParametricEquiv.v Kami/ParametricInline.v Kami/Notations.v Kami/Substitute.v Kami/ParametricWf.v Kami/ParamDup.v Kami/SymEval.v Kami/Syntax.v Kami/ModuleBoundEx.v Kami/Tactics.v Kami/SymEvalTac.v Kami/ModularFacts.v Kami/Synthesize.v Kami/RefinementFacts.v Kami/Decomposition.v Kami/Renaming.v Kami/Kami.v Kami/Duplicate.v Kami/ModuleBound.v Kami/Specialize.v Kami/Ex/ProcThreeStage.v Kami/Ex/SimpleFifoCorrect.v Kami/Ex/IsaRv32PgmExt.v Kami/Ex/ProcThreeStInv.v Kami/Ex/Divider32.v Kami/Ex/SC.v Kami/Ex/Names.v Kami/Ex/OneEltFifo.v Kami/Ex/Multiplier64.v Kami/Ex/Multiplier32.v Kami/Ex/ProcFDInv.v Kami/Ex/ProcDec.v Kami/Ex/ProcFourStDec.v Kami/Ex/IsaRv32.v Kami/Ex/MemAtomic.v Kami/Ex/ProcFDInl.v Kami/Ex/IsaRv32Pgm.v Kami/Ex/Divider64.v Kami/Ex/Fifo.v Kami/Ex/ProcThreeStInl.v Kami/Ex/ProcDecSC.v Kami/Ex/ProcDecSCN.v Kami/Ex/NativeFifo.v Kami/Ex/FifoCorrect.v Kami/Ex/ProcThreeStDec.v Kami/Ex/RegFile.v Kami/Ex/InDepthTutorial.v Kami/Ex/ProcDecInv.v Kami/Ex/ProcFetchDecode.v Kami/Ex/SCMMInl.v Kami/Ex/ProcFDCorrect.v Kami/Ex/MemTypes.v Kami/Ex/ProcDecInl.v Kami/Ex/IsaRv32/PgmFact.v Kami/Ex/IsaRv32/PgmMatMulReport.v Kami/Ex/IsaRv32/PgmBankerWorker3.v Kami/Ex/IsaRv32/PgmGcd.v Kami/Ex/IsaRv32/PgmMatMulInit.v Kami/Ex/IsaRv32/PgmPeterson2.v Kami/Ex/IsaRv32/PgmHanoi.v Kami/Ex/IsaRv32/PgmBankerWorker1.v Kami/Ex/IsaRv32/PgmPeterson1.v Kami/Ex/IsaRv32/PgmBankerInit.v Kami/Ex/IsaRv32/PgmMatMulNormal1.v Kami/Ex/IsaRv32/PgmDekker1.v Kami/Ex/IsaRv32/PgmBankerWorker2.v Kami/Ex/IsaRv32/PgmBsort.v Kami/Ex/IsaRv32/PgmMatMulNormal2.v Kami/Ex/IsaRv32/PgmDekker2.v Kami/Ext/Extraction.v Kami/Ext/BSyntax.v -o Makefile.coq.all make -f Makefile.coq.all make[3]: Entering directory 'bedrock2/deps/kami' ROCQ DEP VFILES ROCQ DEP VFILES ROCQ compile bedrock2/compiler/lib/fiat_crypto_tactics/Test.v ROCQ compile bedrock2/compiler/lib/LibTacticsMin.v ROCQ compile Kami/Lib/StringAsOT.v ROCQ compile bedrock2/compiler/src/NoActionSyntaxParams.v ROCQ compile bedrock2/compiler/lib/fiat_crypto_tactics/UniquePose.v ROCQ compile bedrock2/compiler/src/Simp.v ROCQ compile Kami/Lib/CommonTactics.v ROCQ compile bedrock2/compiler/src/util/Misc.v ROCQ compile bedrock2/compiler/src/util/Learning.v ROCQ compile bedrock2/compiler/src/util/MyOmega.v ROCQ compile Kami/Lib/StringEq.v ROCQ compile bedrock2/compiler/src/util/LogGoal.v ROCQ compile bedrock2/compiler/src/SeparationLogic.v ROCQ compile Kami/Lib/Nomega.v ROCQ compile bedrock2/compiler/src/Rem4.v ROCQ compile Kami/Lib/DepEq.v ROCQ compile Kami/Lib/VectorFacts.v ROCQ compile Kami/Lib/StringAsList.v ROCQ compile bedrock2/compiler/src/SimplWordExpr.v ROCQ compile bedrock2/compiler/src/RiscvWordProperties.v ROCQ compile Kami/Lib/FinNotations.v ROCQ compile Kami/Lib/Reflection.v ROCQ compile bedrock2/compiler/src/eqexact.v ROCQ compile bedrock2/compiler/src/on_hyp_containing.v ROCQ compile bedrock2/compiler/src/Basic32Semantics.v ROCQ compile Kami/Lib/Concat.v ROCQ compile Kami/LKami/Lib/ListSupport (real: 1.09, user: 0.37, sys: 0.15, mem: 353524 ko) File "bedrock2/compiler/src/UnmappedMemForExtSpec.v", line 45, characters 2-49: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/compiler/src/UnmappedMemForExtSpec.v", line 47, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/BasicLogic (real: 0.24, user: 0.07, sys: 0.03, mem: 87856 ko) Kami/Lib/DepEqNat (real: 0.22, user: 0.06, sys: 0.03, mem: 76484 ko) bedrock2/compiler/src/UnmappedMemForExtSpec (real: 1.68, user: 0.61, sys: 0.21, mem: 446012 ko) Kami/Ex/Names (real: 1.02, user: 0.36, sys: 0.13, mem: 271052 ko) bedrock2/compiler/src/NameGen (real: 0.95, user: 0.32, sys: 0.15, mem: 286108 ko) bedrock2/compiler/src/examples/highlevel/For (real: 0.15, user: 0.04, sys: 0.02, mem: 55764 ko) Kami/Lib/StringStringAsOT (real: 1.73, user: 0.63, sys: 0.19, mem: 420276 ko) bedrock2/compiler/src/examples/toposort (real: 2.47, user: 0.98, sys: 0.21, mem: 426872 ko) File "bedrock2/compiler/lib/LibTactics.v", line 55, characters 0-32: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/compiler/lib/LibTactics.v", line 100, characters 0-42: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope ltac_scope.". [undeclared-scope,deprecated] File "bedrock2/compiler/lib/LibTactics.v", line 581, characters 0-16: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/compiler/lib/LibTactics.v", line 4771, characters 0-28: Warning: skip_axiom is declared as a local axiom [local-declaration,scope] File "bedrock2/compiler/lib/LibTactics.v", line 4998, characters 0-196: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope let_scope.". [undeclared-scope,deprecated] Kami/Lib/NatLib (real: 3.58, user: 1.52, sys: 0.22, mem: 429812 ko) bedrock2/compiler/lib/LibTactics (real: 2.73, user: 1.10, sys: 0.23, mem: 419492 ko) bedrock2/compiler/lib/fiat_crypto_tactics/Not (real: 0.17, user: 0.05, sys: 0.03, mem: 56680 ko) bedrock2/compiler/src/util/Tactics (real: 1.16, user: 0.40, sys: 0.17, mem: 282384 ko) Kami/Lib/ilist (real: 2.17, user: 0.82, sys: 0.23, mem: 422368 ko) bedrock2/compiler/src/util/Common (real: 1.69, user: 0.59, sys: 0.22, mem: 371952 ko) Kami/Lib/Indexer (real: 2.29, user: 0.90, sys: 0.21, mem: 421100 ko) bedrock2/compiler/src/util/ListLib (real: 2.24, user: 0.88, sys: 0.22, mem: 427540 ko) Kami/Lib/Misc (real: 1.05, user: 0.35, sys: 0.16, mem: 299684 ko) bedrock2/compiler/src/util/Set (real: 0.96, user: 0.30, sys: 0.14, mem: 282580 ko) File "./Kami/Lib/Word.v", line 19, characters 0-35: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope word_scope.". [undeclared-scope,deprecated] File "./Kami/Lib/Word.v", line 147, characters 0-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/Word.v", line 400, characters 0-45: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/Word.v", line 1090, characters 0-43: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/Word.v", line 1217, characters 0-42: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 407, characters 4-639: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 464, characters 4-57: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 464, characters 4-57: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 491, characters 4-95: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 491, characters 4-95: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 491, characters 4-95: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 533, characters 4-108: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 533, characters 4-108: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/ExprImp.v", line 533, characters 4-108: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] ib/ListSupport.v ROCQ compile bedrock2/compiler/src/UnmappedMemForExtSpec.v ROCQ compile Kami/Lib/BasicLogic.v ROCQ compile Kami/Lib/DepEqNat.v ROCQ compile Kami/Ex/Names.v ROCQ compile bedrock2/compiler/src/NameGen.v ROCQ compile Kami/Lib/StringStringAsOT.v ROCQ compile bedrock2/compiler/src/examples/highlevel/For.v ROCQ compile bedrock2/compiler/src/examples/toposort.v ROCQ compile Kami/Lib/NatLib.v ROCQ compile bedrock2/compiler/lib/LibTactics.v ROCQ compile Kami/Lib/ilist.v ROCQ compile bedrock2/compiler/lib/fiat_crypto_tactics/Not.v ROCQ compile bedrock2/compiler/src/util/Tactics.v ROCQ compile bedrock2/compiler/src/util/Common.v ROCQ compile Kami/Lib/Indexer.v ROCQ compile bedrock2/compiler/src/util/ListLib.v ROCQ compile Kami/Lib/Misc.v ROCQ compile bedrock2/compiler/src/util/Set.v ROCQ compile Kami/Lib/Word.v ROCQ compile bedrock2/compiler/src/ExprImp.v End of ExprImp.v total time: 8.389s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.0% 49.5% 44 0.222s ─preprocess_impl ----------------------- 0.7% 39.2% 44 0.177s ─abstract_unrecogs --------------------- 16.3% 34.8% 44 0.161s ─set_solver_generic -------------------- 0.2% 15.1% 30 0.405s ─ --- 0.0% 14.9% 34 0.400s ─t_tauto_intuit ------------------------ 3.0% 14.9% 93 0.400s ─remember_unrecogs --------------------- 3.1% 12.3% 548 0.016s ─ -------------- 9.4% 12.1% 93 0.334s ─map_solver_core ----------------------- 0.5% 10.2% 29 0.085s ─map_solver_core_impl ------------------ 0.3% 9.6% 2 0.084s ─inversion H --------------------------- 9.4% 9.4% 74 0.061s ─inversion_lemma ----------------------- 0.1% 6.2% 9 0.217s ─inversionss --------------------------- 0.1% 6.0% 10 0.226s ─inverts (var) ------------------------- 0.1% 5.9% 63 0.030s ─inverts_tactic ------------------------ 0.2% 5.8% 63 0.030s ─unrecogs_in_prop ---------------------- 5.7% 5.7% 0 0.027s ─map_specialize ------------------------ 0.0% 5.1% 29 0.041s ─map_specialize_step ------------------- 3.7% 5.1% 35 0.036s ─congruence ---------------------------- 4.5% 4.5% 117 0.027s ─invert keep (var) --------------------- 0.1% 4.5% 63 0.028s ─remember P as name eqn:a -------------- 4.5% 4.5% 197 0.012s ─eauto (int_or_var_opt) (int_or_var_opt) 4.3% 4.5% 53 0.055s ─apply mk_Abstracted in a -------------- 3.8% 3.8% 264 0.002s ─replace (uconstr) with (constr) (clause 0.8% 3.6% 21 0.032s ─econstructor -------------------------- 2.8% 2.8% 49 0.010s ─maps_propositional -------------------- 0.1% 2.8% 45 0.043s ─pose proof IH as IH' ------------------ 2.6% 2.6% 3724 0.006s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─map_solver ---------------------------- 0.0% 49.5% 44 0.222s β”œβ”€preprocess_impl --------------------- 0.7% 39.2% 44 0.177s β”‚β””abstract_unrecogs ------------------- 16.3% 34.8% 44 0.161s β”‚ β”œβ”€remember_unrecogs ----------------- 3.1% 12.3% 548 0.016s β”‚ β”‚ β”œβ”€remember P as name eqn:a -------- 4.5% 4.5% 197 0.012s β”‚ β”‚ └─apply mk_Abstracted in a -------- bedrock2/compiler/src/ExprImp (real: 23.40, user: 10.90, sys: 0.52, mem: 540624 ko) bedrock2/compiler/src/ZNameGen (real: 1.33, user: 0.46, sys: 0.18, mem: 351756 ko) bedrock2/compiler/src/examples/TestExprImp (real: 2.02, user: 0.72, sys: 0.26, mem: 458732 ko) bedrock2/compiler/src/examples/highlevel/FuncMut (real: 1.61, user: 0.55, sys: 0.23, mem: 420416 ko) File "bedrock2/compiler/src/FlatImp.v", line 418, characters 6-59: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "./Kami/Lib/Word.v", line 2154, characters 0-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/Word (real: 55.47, user: 26.60, sys: 0.45, mem: 741048 ko) File "./Kami/Lib/Struct.v", line 151, characters 0-57: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/Struct (real: 2.57, user: 0.99, sys: 0.21, mem: 435576 ko) File "bedrock2/compiler/src/FlatImp.v", line 474, characters 6-210: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/FlatImp.v", line 474, characters 6-210: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/FlatImp.v", line 474, characters 6-210: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] Kami/Lib/WordSupport (real: 1.56, user: 0.56, sys: 0.20, mem: 432120 ko) File "./Kami/Lib/FMap.v", line 563, characters 2-19: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 567, characters 2-51: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 595, characters 2-43: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 618, characters 2-44: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 626, characters 2-41: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 876, characters 2-45: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 913, characters 2-46: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 1328, characters 2-43: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 1475, characters 2-45: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 2482, characters 0-44: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope fmap_scope.". [undeclared-scope,deprecated] File "./Kami/Lib/FMap.v", line 2681, characters 0-41: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Lib/FMap.v", line 2682, characters 0-48: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Lib/FMap (real: 20.44, user: 9.56, sys: 0.30, mem: 537308 ko) File "bedrock2/compiler/src/FlatImp.v", line 624, characters 4-95: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "bedrock2/compiler/src/FlatImp.v", line 624, characters 4-95: Warning: Ltac Profiler cannot yet handle backtracking into multi-success tactics; profiling results may be wildly inaccurate. [profile-backtracking,ltac] File "./Kami/Syntax.v", line 1139, characters 2-33: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Syntax.v", line 1309, characters 0-121: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Syntax.v", line 1315, characters 0-84: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_struct_scope.". [undeclared-scope,deprecated] File "./Kami/Syntax.v", line 1317, characters 0-54: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_scope.". [undeclared-scope,deprecated] Kami/Syntax (real: 4.38, user: 1.89, sys: 0.23, mem: 479116 ko) 3.8% 3.8% 264 0.002s β”‚ └─unrecogs_in_prop ------------------ 5.7% 5.7% 0 0.027s └─map_solver_core --------------------- 0.5% 10.2% 29 0.085s β””map_solver_core_impl ---------------- 0.3% 9.6% 2 0.084s β”œβ”€map_specialize -------------------- 0.0% 5.1% 29 0.041s β”‚β””map_specialize_step --------------- 3.7% 5.1% 35 0.036s └─maps_propositional ---------------- 0.1% 2.8% 45 0.043s ─set_solver_generic -------------------- 0.2% 15.1% 30 0.405s β”” --- 0.0% 14.0% 30 0.400s β””t_tauto_intuit ------------------------ 3.0% 14.0% 89 0.400s β”” -------------- 8.8% 11.3% 89 0.334s ─inversion_lemma ----------------------- 0.1% 6.2% 9 0.217s β””inversionss --------------------------- 0.0% 3.3% 9 0.084s β””inverts (var) ------------------------- 0.0% 3.2% 32 0.020s β””inverts_tactic ------------------------ 0.1% 3.2% 32 0.020s β””invert keep (var) --------------------- 0.0% 2.5% 32 0.018s ─inversion H --------------------------- 6.0% 6.0% 11 0.061s ─replace (uconstr) with (constr) (clause 0.8% 3.6% 21 0.032s β””congruence ---------------------------- 2.8% 2.8% 21 0.027s ─eauto (int_or_var_opt) (int_or_var_opt) 3.2% 3.3% 44 0.023s ─econstructor -------------------------- 2.8% 2.8% 49 0.010s ─inversionss --------------------------- 0.1% 2.7% 1 0.226s β””inverts (var) ------------------------- 0.0% 2.6% 31 0.030s β””inverts_tactic ------------------------ 0.1% 2.6% 31 0.030s β””invert keep (var) --------------------- 0.0% 2.0% 31 0.028s ─pose proof IH as IH' ------------------ 2.6% 2.6% 3724 0.006s ROCQ compile bedrock2/compiler/src/ZNameGen.v ROCQ compile bedrock2/compiler/src/examples/TestExprImp.v ROCQ compile bedrock2/compiler/src/examples/highlevel/FuncMut.v ROCQ compile bedrock2/compiler/src/FlatImp.v ROCQ compile Kami/Lib/Struct.v ROCQ compile Kami/Lib/WordSupport.v ROCQ compile Kami/Lib/FMap.v ROCQ compile Kami/Syntax.v ROCQ compile Kami/Semantics.v End of FlatImp.v total time: 26.926s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─simp ---------------------------------- 0.0% 71.8% 97 2.046s ─simp_step ----------------------------- 0.1% 71.8% 209 0.530s ─unique_inversion ---------------------- 71.4% 71.4% 3388 0.529s ─inversion H --------------------------- 66.5% 66.5% 686 0.199s ─equalities ---------------------------- 0.3% 57.3% 3 10.539s ─map_solver ---------------------------- 0.0% 11.2% 30 0.277s ─preprocess_impl ----------------------- 0.2% 8.1% 30 0.215s ─abstract_unrecogs --------------------- 2.9% 7.0% 30 0.198s ─protect_equalities -------------------- 2.0% 3.8% 593 0.011s ─congruence ---------------------------- 3.6% 3.6% 187 0.043s ─map_solver_core ----------------------- 0.1% 3.1% 25 0.077s ─map_solver_core_impl ------------------ 0.1% 3.0% 2 0.076s ─pose proof IH as IH' ------------------ 2.5% 2.5% 11247 0.004s ─remember_unrecogs --------------------- 0.6% 2.5% 303 0.016s ─inversion_lemma ----------------------- 0.0% 2.3% 11 0.208s ─inversionss --------------------------- 0.0% 2.2% 12 0.246s ─inverts (var) ------------------------- 0.0% 2.2% 81 0.023s ─inverts_tactic ------------------------ 0.1% 2.1% 81 0.023s ─assert (H : e1 = e2) by congruence ---- 0.1% 2.1% 80 0.026s tactic bedrock2/compiler/src/FlatImp (real: 62.83, user: 30.21, sys: 0.60, mem: 608088 ko) bedrock2/compiler/src/util/SetSolverTests (real: 1.00, user: 0.30, sys: 0.15, mem: 290132 ko) bedrock2/compiler/src/RegAlloc2 (real: 1.61, user: 0.53, sys: 0.21, mem: 386872 ko) File "./Kami/Semantics.v", line 947, characters 2-35: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Semantics (real: 13.71, user: 6.50, sys: 0.26, mem: 501300 ko) Kami/Inline (real: 1.93, user: 0.70, sys: 0.23, mem: 469696 ko) Kami/SymEval (real: 3.58, user: 1.48, sys: 0.24, mem: 476176 ko) File "./Kami/Wf.v", line 16, characters 2-22: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Wf (real: 6.87, user: 3.06, sys: 0.29, mem: 499932 ko) File "./Kami/SemFacts.v", line 1666, characters 0-20: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/SemFacts (real: 76.97, user: 37.08, sys: 0.39, mem: 601836 ko) File "./Kami/ModularFacts.v", line 42, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/ModularFacts (real: 68.49, user: 32.76, sys: 0.55, mem: 885880 ko) Kami/StepDet (real: 19.67, user: 9.26, sys: 0.28, mem: 504428 ko) Kami/Label (real: 7.13, user: 3.17, sys: 0.27, mem: 486656 ko) Kami/RefinementFacts (real: 18.99, user: 8.98, sys: 0.27, mem: 511956 ko) Kami/InlineFacts (real: 83.55, user: 40.29, sys: 0.46, mem: 668564 ko) File "./Kami/Renaming.v", line 16, characters 0-25: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Renaming.v", line 185, characters 2-44: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Renaming.v", line 203, characters 2-58: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Renaming (real: 81.06, user: 39.12, sys: 0.38, mem: 563328 ko) Kami/Substitute (real: 2.10, user: 0.72, sys: 0.26, mem: 473852 ko) Kami/Decomposition (real: 11.95, user: 5.56, sys: 0.26, mem: 507520 ko) Kami/Amortization (real: 11.22, user: 5.12, sys: 0.29, mem: 505436 ko) Kami/SymEvalTac (real: 1.93, user: 0.67, sys: 0.23, mem: 474056 ko) Kami/PartialInlineFacts (real: 13.41, user: 6.24, sys: 0.29, mem: 509232 ko) Kami/ParametricSyntax (real: 31.00, user: 14.78, sys: 0.34, mem: 561068 ko) File "./Kami/Specialize.v", line 858, characters 2-44: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Specialize.v", line 1194, characters 0-130: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Specialize (real: 45.09, user: 21.68, sys: 0.30, mem: 506640 ko) Kami/ParametricWf (real: 5.32, user: 2.19, sys: 0.29, mem: 489072 ko) File "./Kami/ParametricEquiv.v", line 10, characters 2-22: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/ParametricEquiv (real: 6.90, user: 3.10, sys: 0.28, mem: 492424 ko) File "./Kami/Notations.v", line 28, characters 0-81: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_expr_scope.". [undeclared-scope,deprecated] File "./Kami/Notations.v", line 89, characters 0-169: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope init_scope.". [undeclared-scope,deprecated] File "./Kami/Notations.v", line 110, characters 0-190: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_action_scope.". [undeclared-scope,deprecated] File "./Kami/Notations.v", line 263, characters 0-212: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_sin_scope.". [undeclared-scope,deprecated] File "./Kami/Notations.v", line 404, characters 0-247: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_gen_scope.". [undeclared-scope,deprecated] File "./Kami/Notations.v", line 663, characters 0-260: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope kami_meta_scope.". [undeclared-scope,deprecated] Kami/Notations (real: 2.42, user: 0.87, sys: 0.28, mem: 460284 ko) Kami/Duplicate (real: 5.46, user: 2.39, sys: 0.28, mem: 487424 ko) Kami/Synthesize (real: 1.72, user: 0.59, sys: 0.24, mem: 442252 ko) Kami/Ex/MemTypes (real: 1.99, user: 0.71, sys: 0.23, mem: 452980 ko) Kami/Ext/BSyntax (real: 2.19, user: 0.79, sys: 0.27, mem: 477872 ko) Kami/ParametricInline (real: 9.22, user: 4.19, sys: 0.30, mem: 509168 ko) Kami/ModuleBound (real: 3.21, user: 1.29, sys: 0.27, mem: 485936 ko) File "./Kami/ModuleBoundEx.v", line 25, characters 2-71: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope namebound_scope.". [undeclared-scope,deprecated] File "./Kami/ModuleBoundEx.v", line 332, characters 2-71: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope namebound_scope.". [undeclared-scope,deprecated] Kami/ModuleBoundEx (real: 7.16, user: 3.17, sys: 0.30, mem: 492768 ko) Kami/ParamDup (real: 5.47, user: 2.42, sys: 0.25, mem: 489812 ko) File "./Kami/Tactics.v", line 923, characters 0-59: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Tactics.v", line 924, characters 0-77: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Tactics.v", line 984, characters 0-543: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope mapping_scope.". [undeclared-scope,deprecated] Kami/Tactics (real: 2.58, user: 0.89, sys: 0.26, mem: 484828 ko) Kami/ParametricInlineLtac (real: 2.11, user: 0.77, sys: 0.26, mem: 486708 ko) Kami/MapReifyEx (real: 4.56, user: 1.94, sys: 0.29, mem: 494008 ko) File "./Kami/Ex/SC.v", line 432, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/SC.v", line 441, characters 2-33: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/SC.v", line 460, characters 0-72: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/SC (real: 8.37, user: 3.81, sys: 0.27, mem: 510132 ko) File "./Kami/Ex/OneEltFifo.v", line 85, characters 0-50: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/OneEltFifo.v", line 86, characters 0-56: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/OneEltFifo.v", line 87, characters 0-56: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/OneEltFifo (real: 2.92, user: 1.15, sys: 0.26, mem: 487776 ko) File "./Kami/Ex/Fifo.v", line 197, characters 2-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/Fifo.v", line 202, characters 2-35: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/Fifo.v", line 207, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/Fifo.v", line 212, characters 2-36: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/Fifo.v", line 266, characters 0-167: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/Fifo.v", line 270, characters 0-175: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/Fifo (real: 16.06, user: 7.55, sys: 0.28, mem: 534616 ko) File "./Kami/Ex/NativeFifo.v", line 174, characters 2-35: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/NativeFifo.v", line 181, characters 2-41: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/NativeFifo.v", line 188, characters 2-36: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/NativeFifo.v", line 195, characters 2-42: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/NativeFifo.v", line 273, characters 0-215: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/NativeFifo.v", line 277, characters 0-223: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/NativeFifo (real: 4.03, user: 1.70, sys: 0.27, mem: 490720 ko) File "./Kami/Ex/IsaRv32.v", line 88, characters 0-79: Warning: Notation "$ _" was already used in scope kami_expr_scope. [notation-overridden,parsing] Kami/Ex/IsaRv32 (real: 3.31, user: 1.30, sys: 0.26, mem: 509008 ko) File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiXq cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiXq cannot be defined because the projection ndiXq was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiX cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiX cannot be defined because the projection ndiX was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiD cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiD cannot be defined because the projection ndiD was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiDp cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiDp cannot be defined because the projection ndiDp was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiDn cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiDn cannot be defined because the projection ndiDn was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: ndiCnt cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiCnt cannot be defined because the projection ndiCnt was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiDdp cannot be defined because the projections ndiDp, ndiD were not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiDdn cannot be defined because the projections ndiDn, ndiDp were not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider32.v", line 1058, characters 2-1168: Warning: HndiInv cannot be defined because the projections ndiD, ndiCnt, ndiXq, ndiX, ndiD were not defined. [cannot-define-projection,records] Kami/Ex/Divider32 (real: 125.49, user: 60.73, sys: 0.58, mem: 847228 ko) File "./Kami/Ex/Multiplier64.v", line 399, characters 2-24: Warning: Use of β€œRequire” inside a section is deprecated. [require-in-section,deprecated] File "./Kami/Ex/Multiplier64.v", line 431, characters 4-143: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bword_scope.". [undeclared-scope,deprecated] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiM cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiM cannot be defined because the projection bsiM was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiR cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiR cannot be defined because the projection bsiR was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiMp cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiMp cannot be defined because the projection bsiMp was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiMn cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiMn cannot be defined because the projection bsiMn was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiP cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiP cannot be defined because the projection bsiP was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: bsiCnt cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiCnt cannot be defined because the projection bsiCnt was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiMmp cannot be defined because the projections bsiMp, bsiM were not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiMmn cannot be defined because the projections bsiMn, bsiM were not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HmInv cannot be defined because the projection bsiM was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier64.v", line 1125, characters 2-1192: Warning: HbsiInv cannot be defined because the projections bsiCnt, bsiP, bsiM, bsiR were not defined. [cannot-define-projection,records] Kami/Ex/Multiplier64 (real: 430.88, user: 206.96, sys: 1.70, mem: 1980772 ko) File "./Kami/Ex/Multiplier32.v", line 399, characters 2-24: Warning: Use of β€œRequire” inside a section is deprecated. [require-in-section,deprecated] File "./Kami/Ex/Multiplier32.v", line 431, characters 4-143: Warning: Declaring a scope implicitly is deprecated; use in advance an explicit "Declare Scope bword_scope.". [undeclared-scope,deprecated] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiM cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiM cannot be defined because the projection bsiM was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiR cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiR cannot be defined because the projection bsiR was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiMp cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiMp cannot be defined because the projection bsiMp was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiMn cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiMn cannot be defined because the projection bsiMn was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiP cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiP cannot be defined because the projection bsiP was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: bsiCnt cannot be defined because it is informative and BoothMultiplierInv is not. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiCnt cannot be defined because the projection bsiCnt was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiMmp cannot be defined because the projections bsiMp, bsiM were not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiMmn cannot be defined because the projections bsiMn, bsiM were not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HmInv cannot be defined because the projection bsiM was not defined. [cannot-define-projection,records] File "./Kami/Ex/Multiplier32.v", line 1125, characters 2-1192: Warning: HbsiInv cannot be defined because the projections bsiCnt, bsiP, bsiM, bsiR were not defined. [cannot-define-projection,records] local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─equalities ---------------------------- 0.3% 57.3% 3 10.539s β”œβ”€simp -------------------------------- 0.0% 54.9% 77 2.046s β”‚β””simp_step --------------------------- 0.0% 54.9% 160 0.530s β”‚β””unique_inversion -------------------- 54.6% 54.6% 2632 0.529s β”‚ β”œβ”€inversion H ----------------------- 47.8% 47.8% 454 0.170s β”‚ └─protect_equalities ---------------- 1.7% 3.3% 454 0.010s └─assert (H : e1 = e2) by congruence -- 0.1% 2.1% 80 0.026s β””congruence -------------------------- 2.0% 2.0% 80 0.025s ─simp ---------------------------------- 0.0% 17.0% 20 0.417s β””simp_step ----------------------------- 0.0% 17.0% 49 0.396s β””unique_inversion ---------------------- 16.8% 16.8% 756 0.395s β””inversion H --------------------------- 15.4% 15.4% 139 0.199s ─map_solver ---------------------------- 0.0% 11.2% 30 0.277s β”œβ”€preprocess_impl --------------------- 0.2% 8.1% 30 0.215s β”‚β””abstract_unrecogs ------------------- 2.9% 7.0% 30 0.198s β”‚β””remember_unrecogs ------------------- 0.6% 2.5% 303 0.016s └─map_solver_core --------------------- 0.1% 3.1% 25 0.077s β””map_solver_core_impl ---------------- 0.1% 3.0% 2 0.076s ─pose proof IH as IH' ------------------ 2.5% 2.5% 11247 0.004s ─inversion_lemma ----------------------- 0.0% 2.3% 11 0.208s ROCQ compile bedrock2/compiler/src/util/SetSolverTests.v ROCQ compile bedrock2/compiler/src/RegAlloc2.v ROCQ compile bedrock2/compiler/src/FlattenExpr.v ROCQ compile Kami/Inline.v ROCQ compile Kami/SymEval.v ROCQ compile Kami/Wf.v ROCQ compile Kami/SemFacts.v ROCQ compile Kami/ModularFacts.v ROCQ compile Kami/StepDet.v ROCQ compile Kami/Label.v ROCQ compile Kami/RefinementFacts.v ROCQ compile Kami/InlineFacts.v ROCQ compile Kami/Renaming.v ROCQ compile Kami/Substitute.v ROCQ compile Kami/Decomposition.v ROCQ compile Kami/Amortization.v ROCQ compile Kami/SymEvalTac.v ROCQ compile Kami/PartialInlineFacts.v ROCQ compile Kami/ParametricSyntax.v ROCQ compile Kami/Specialize.v ROCQ compile Kami/ParametricWf.v ROCQ compile Kami/ParametricEquiv.v ROCQ compile Kami/Notations.v ROCQ compile Kami/Duplicate.v ROCQ compile Kami/Synthesize.v ROCQ compile Kami/Ex/MemTypes.v ROCQ compile Kami/Ext/BSyntax.v ROCQ compile Kami/ParametricInline.v ROCQ compile Kami/ModuleBound.v ROCQ compile Kami/ModuleBoundEx.v ROCQ compile Kami/ParamDup.v ROCQ compile Kami/Tactics.v ROCQ compile Kami/ParametricInlineLtac.v ROCQ compile Kami/MapReifyEx.v ROCQ compile Kami/Ex/SC.v ROCQ compile Kami/Ex/OneEltFifo.v ROCQ compile Kami/Ex/Fifo.v ROCQ compile Kami/Ex/NativeFifo.v ROCQ compile Kami/Ex/IsaRv32.v ROCQ compile Kami/Ex/Divider32.v ROCQ compile Kami/Ex/Multiplier64.v ROCQ compile Kami/Ex/Multiplier32.v End of FlattenExpr.v total time: 587.422s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─maps ---------------------------------- 0.0% 88.3% 84 17.968s ─map_solver ---------------------------- 0.0% 54.8% 95 9.899s ─map_solver_core ----------------------- 0.1% 42.7% 92 9.552s ─map_solver_core_impl ------------------ 0.0% 42.6% 13 9.549s ─default_flattenBooleanExpr ------------ 0.0% 37.3% 21 36.430s ─map_specialize ------------------------ 0.0% 36.3% 92 7.801s ─map_specialize_step ------------------- 24.9% 36.3% 1911 5.056s ─pose_flatten_var_ineqs ---------------- 4.0% 34.0% 86 10.352s ─unique eapply (constr) in copy of (iden 1.0% 30.1% 59814 0.049s ─unshelve (tactic1) -------------------- 0.7% 26.8% 59814 0.048s ─eapply p in H' ------------------------ 26.2% 26.2% 59814 0.048s ─preprocess_impl ----------------------- 0.0% 12.1% 95 2.152s ─abstract_unrecogs --------------------- 7.0% 11.1% 95 2.057s ─simp ---------------------------------- 0.0% 6.3% 78 3.196s ─simp_step ----------------------------- 0.0% 6.3% 644 1.145s ─maps_propositional -------------------- 0.0% 6.0% 480 7.295s ─unique_inversion ---------------------- 3.9% 3.9% 5338 1.144s ─maps_leaf_tac ------------------------- 0.1% 3.5% 2100 0.035s ─inversion H --------------------------- 3.4% 3.4% 1097 1.070s ─congruence ---------------------------- 3.2% 3.2% 2495 0.085s ─pose proof H as H' -------------------- 3.1% 3.1% 185783 0.026s ─canonicalize_map_hyp ------------------ 0.6% 2.9% 37401 0.022s ─specialize (constr_with_bindings) ----- 2.5% 2.5% 166250 0.022s ─destruct_unique_match ----------------- 2.4% 2.4% 821 0.389s ─remember_unrecogs --------------------- 0.9% 2.4% 2727 0.644s ─ensure_no_body ------------------------ 1.0% 2.3% 161949 0.015s ─propositional_cheap_step -------------- 2.2% 2.3% 3800 0.016s ─auto (int_or_var_opt) (auto_using) (hin 1.8% 2.1% 3290 0.023s ─assert_fails -------------------------- 0.6% 2.0% 196767 0.023s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─maps ---------------------------------- 0.0% 52.5% 53 17.968s β”œβ”€map_solver -------------------------- 0.0% 30.3% 64 9.899s β”‚ β”œβ”€map_solver_core ------------------- 0.0% 22.4% 64 9.552s β”‚ β”‚β””map_solver_core_impl -------------- 0.0% 22.4% 1 9.549s β”‚ β”‚ β”œβ”€map_specialize ------------------ 0.0% 17.8% 64 5.088s β”‚ β”‚ β”‚β””map_specialize_step ------------- 12.7% 17.8% 1057 4.472s β”‚ β”‚ └─maps_propositional -------------- 0.0% 4.4% 350 7.295s β”‚ β”‚ β””maps_leaf_tac ------------------- 0.0% 2.5% 1634 0.025s β”‚ └─preprocess_impl ------------------- 0.0% 7.9% 64 2.152s β”‚ β””abstract_unrecogs ----------------- 4.6% 7.3% 64 2.057s └─pose_flatten_var_ineqs -------------- 2.5% 22.1% 53 10.352s β””unique eapply (constr) in copy of (id 0.6% 19.7% 36953 0.049s β””unshelve (tactic1) ------------------ 0.4% 17.8% 36953 0.048s β””eapply p in H' ---------------------- 17.4% 17.4% 36953 0.048s ─default_flattenBooleanExpr ------------ 0.0% 37.3% 21 36.430s β”œβ”€maps -------------------------------- 0.0% 35.0% 30 12.207s β”‚ β”œβ”€map_solver ------------------------ 0.0% 24.0% 30 9.184s β”‚ β”‚ β”œβ”€map_solver_core ----------------- 0.0% 20.1% 27 7.870s β”‚ β”‚ β”‚β””map_solver_core_impl ------------ 0.0% 20.1% 12 7.859s β”‚ β”‚ β”‚β””map_specialize ------------------ 0.0% 18.3% 27 7.801s β”‚ β”‚ β”‚β””map_specialize_step ------------- 12.1% 18.3% 845 5.056s β”‚ β”‚ └─preprocess_impl ----------------- 0.0% 3.9% 30 1.349s β”‚ β”‚ β””abstract_unrecogs --------------- 2.3% 3.6% 30 1.238s β”‚ └─pose_flatten_var_ineqs ------------ 1.4% 11.0% 30 3.250s β”‚ β””unique eapply (constr) in copy of ( 0.4% 9.6% 21011 0.027s β”‚ β””unshelve (tactic1) ---------------- 0.2% 8.3% 21011 0.027s β”‚ β””eapply p in H' -------------------- 8.1% 8.1% 21011 0.027s └─simp -------------------------------- 0.0% 2.2% 21 1.839s β””simp_step --------------------------- 0.0% 2.1% 243 0.174s ─simp ---------------------------------- 0.0% 4.2% 57 3.196s β””simp_step ----------------------------- 0.0% 4.2% 401 1.145s β””unique_inversion --------bedrock2/compiler/src/FlattenExpr (real: 1225.77, user: 593.01, sys: 9.58, mem: 1060368 ko) bedrock2/compiler/src/examples/TestFlatImp (real: 4.39, user: 0.71, sys: 0.28, mem: 459820 ko) bedrock2/compiler/src/FlatToRiscvDef (real: 2.44, user: 0.69, sys: 0.24, mem: 466532 ko) bedrock2/compiler/src/RegAlloc3 (real: 1.44, user: 0.50, sys: 0.18, mem: 389304 ko) bedrock2/compiler/src/EmitsValid (real: 49.36, user: 23.66, sys: 0.35, mem: 610544 ko) bedrock2/compiler/src/RegAllocAnnotatedNotations (real: 1.73, user: 0.45, sys: 0.18, mem: 350576 ko) bedrock2/compiler/src/GoFlatToRiscv (real: 15.43, user: 6.89, sys: 0.27, mem: 480324 ko) bedrock2/compiler/src/FlatToRiscv32 (real: 17.62, user: 8.26, sys: 0.29, mem: 505664 ko) Kami/Ex/Multiplier32 (real: 214.00, user: 104.11, sys: 0.86, mem: 1131272 ko) File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiXq cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiXq cannot be defined because the projection ndiXq was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiX cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiX cannot be defined because the projection ndiX was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiD cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiD cannot be defined because the projection ndiD was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiDp cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiDp cannot be defined because the projection ndiDp was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiDn cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiDn cannot be defined because the projection ndiDn was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: ndiCnt cannot be defined because it is informative and NrDividerInv is not. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiCnt cannot be defined because the projection ndiCnt was not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiDdp cannot be defined because the projections ndiDp, ndiD were not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiDdn cannot be defined because the projections ndiDn, ndiDp were not defined. [cannot-define-projection,records] File "./Kami/Ex/Divider64.v", line 1058, characters 2-1168: Warning: HndiInv cannot be defined because the projections ndiD, ndiCnt, ndiXq, ndiX, ndiD were not defined. [cannot-define-projection,records] Kami/Ex/Divider64 (real: 271.33, user: 131.59, sys: 1.01, mem: 1411224 ko) bedrock2/compiler/src/FlatToRiscv (real: 415.73, user: 202.44, sys: 0.75, mem: 899104 ko) bedrock2/compiler/src/Pipeline (real: 5.85, user: 2.50, sys: 0.27, mem: 505076 ko) Kami/Ex/FifoCorrect (real: 125.57, user: 61.07, sys: 0.56, mem: 798376 ko) File "./Kami/Ex/RegFile.v", line 132, characters 0-66: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/RegFile.v", line 133, characters 0-69: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/RegFile (real: 4.25, user: 1.81, sys: 0.24, mem: 495792 ko) Kami/Ex/SCMMInl (real: 11.10, user: 5.07, sys: 0.30, mem: 561800 ko) Kami/Kami (real: 2.25, user: 0.74, sys: 0.24, mem: 485920 ko) File "./Kami/Ex/MemAtomic.v", line 121, characters 2-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] bedrock2/compiler/src/examples/MMIO (real: 32.79, user: 15.63, sys: 0.31, mem: 555732 ko) File "./Kami/Ex/MemAtomic.v", line 128, characters 2-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/MemAtomic.v", line 137, characters 2-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/MemAtomic.v", line 144, characters 2-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/MemAtomic.v", line 166, characters 0-146: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/MemAtomic (real: 3.50, user: 1.47, sys: 0.24, mem: 497260 ko) bedrock2/compiler/src/examples/InlineAssemblyMacro (real: 1.97, user: 0.71, sys: 0.26, mem: 483356 ko) bedrock2/compiler/src/examples/CompileExamples (real: 2.52, user: 0.74, sys: 0.21, mem: 501084 ko) bedrock2/compiler/src/examples/Fibonacci (real: 7.21, user: 3.30, sys: 0.23, mem: 510956 ko) -------------- 3.2% 3.2% 3570 1.144s β””inversion H --------------------------- 2.7% 2.7% 626 1.070s ROCQ compile bedrock2/compiler/src/examples/TestFlatImp.v ROCQ compile bedrock2/compiler/src/FlatToRiscvDef.v ROCQ compile bedrock2/compiler/src/RegAlloc3.v ROCQ compile bedrock2/compiler/src/EmitsValid.v ROCQ compile bedrock2/compiler/src/RegAllocAnnotatedNotations.v ROCQ compile bedrock2/compiler/src/GoFlatToRiscv.v ROCQ compile bedrock2/compiler/src/FlatToRiscv32.v ROCQ compile bedrock2/compiler/src/FlatToRiscv.v ROCQ compile Kami/Ex/Divider64.v ROCQ compile Kami/Ex/FifoCorrect.v ROCQ compile bedrock2/compiler/src/Pipeline.v ROCQ compile bedrock2/compiler/src/examples/MMIO.v compiled@{} = [[Lui addr 268582912; Addi addr addr 0; Lw i addr 0; Beq i 0 16; Mul s i i; Sw addr s 0; Jal 0 (-16)]] : list Instruction ROCQ compile Kami/Ex/RegFile.v ROCQ compile Kami/Ex/SCMMInl.v ROCQ compile Kami/Kami.v ROCQ compile Kami/Ex/MemAtomic.v ROCQ compile bedrock2/compiler/src/examples/InlineAssemblyMacro.v ROCQ compile Kami/Ex/SimpleFifoCorrect.v compiled@{} = [[Lw 9 1 0; Mul 4 2 3; Add 5 2 3; Sub 6 2 3; Auipc 31 0; Add 31 31 9; Jalr 0 31 8; Addi 7 4 0; Jal 0 20; Addi 7 5 0; Jal 0 12; Addi 7 6 0; Jal 0 4]] : list Instruction ROCQ compile bedrock2/compiler/src/examples/CompileExamples.v ROCQ compile bedrock2/compiler/src/examples/Fibonacci.v fib_ExprImp@{compiler.examples.Fibonacci.17} = fun n : Z => cmd.seq (cmd.set 1 (expr.literal 0)) (cmd.seq (cmd.set 2 (expr.literal 1)) (cmd.seq (cmd.set 4 (expr.literal 0)) (cmd.while (expr.op ltu (expr.var 4) (expr.literal n)) (cmd.seq (cmd.set 3 (expr.op add (expr.var 1) (expr.var 2))) (cmd.seq (cmd.set 1 (expr.var 2)) (cmd.seq (cmd.set 2 (expr.var 3)) (cmd.set 4 (expr.op add (expr.var 4) (expr.literal 1))))))))) : Z -> cmd Argument scope is [Z_scope] = SSeq (SLit 1 0) (SSeq (SLit 2 1) (SSeq (SLit 4 0) (SLoop (SSeq SSkip (SLit 5 6)) (CondBinary BLtu 4 5) (SSeq (SSeq SSkip (SSeq SSkip (SOp 3 add 1 2))) (SSeq (SSet 1 2) (SSeq (SSet 2 3) (SSeq SSkip (SSeq (SLit 6 1) (SOp 4 add 4 6))))))))) : stmt Finished transaction in 0.012 secs (0.007u,0.s) (successful) fib6_riscv@{} = [Addi 1 0 0; Addi 2 0 1; Addi 4 0 0; Addi 5 0 6; Bgeu 4 5 28; Add 3 1 2; Add 1 0 2; Add 2 0 3; Addi 6 0 1; Add 4 4 6; Jal 0 (-28)] : list Instruction fib6_riscv@{} = RISCV: addi x1, x0, 0 addi x2, x0, 1 addi x4, x0, 0 addi x5, x0, 6 bgeu x4, x5, 28 add x3, x1, x2 add x1, x0, x2 add x2, x0, x3 addi x6, x0, 1 add x4, x4, x6 jal x0, -28 : list Instruction 93000000 13011000 13020000 93026000 637e5200 b3812000 b3002000 33013000 13031000 33026200 6ff05ffe = {| Naive.unsigned := 13; Naive._unsigned_in_range := eq_refl |} : word ROCQ compile bedrock2/compiler/src/examples/FE310Compiler.v Finished transaction in 0.063 secs (0.028u,0.001s) (successful) Axioms: AdmitAxiom.proof_admitted : False used in map_ok_subproof5 to prove: forall (m1 m2 : map p ok) (k : parameters.key) (v : parameters.value), map.get m2 k = Some v -> map.get (map.putmany m1 m2) k = Some v used in map_ok_subproof4 to prove: forall (m1 m2 : map p ok) (k : parameters.key), map.get m2 k = None -> map.get (map.putmany m1 m2) k = map.get m1 k used in map_ok_subproof3 to prove: forall (m : map p ok) (k k' : parameters.key), k <> k' -> map.get (map.remove m k') k = map.get m k used in map_ok_subproof2 to prove: forall (m : map p ok) (k : parameters.key), map.get (map.remove m k) k = None used in map_ok_subproof1 to prove: forall (m : map p ok) (k : parameters.key) (v : parameters.value) (k' : parameters.key), k <> k' -> map.get (map.put m k' v) k = map.get m k used in map_ok_subproof0 to prove: forall (m : map p ok) (k : parameters.key) (v : parameters.value), map.get (map.put m k v) k = Some v used in map_ok_subproof to prove: forall m1 m2 : map p ok, (forall k : parameters.key, map.get m1 k = map.get m2 k) -> m1 = m2 ext_spec_Proper : forall (trace : list (mem * actname * list Semantics.word * (mem * list Semantics.word))) (m : mem) (act : actname) (args : list Semantics.word), Morphisms.Proper (Morphisms.respectful (Morphisms.pointwise_relation mem (Morphisms.pointwise_relation (list Semantics.word) Basics.impl)) Basics.impl) (ext_spec trace m act args) Axioms: FlatToRiscv.word_eq_dec : forall p : FlatToRiscv.FlatToRiscv.parameters, FlatToRiscv.FlatToRiscv.assumptions -> DecidableEq word undef_on_unchecked_store_byte_tuple_list : forall (n : nat) (l : list (HList.tuple word8 n)) (start : word32), map.undef_on (unchecked_store_byte_tuple_list start l map.empty) (fun x : word32 => ~ word.unsigned start <= word.unsigned x < word.unsigned start + Z.of_nat n * Zlength l) store_program_empty : forall (prog : list Instruction) (addr : word), GoFlatToRiscv.program addr prog (unchecked_store_program addr prog map.empty) FlatToRiscv.reduce_eq_to_sub_and_lt : forall p : FlatToRiscv.FlatToRiscv.parameters, FlatToRiscv.FlatToRiscv.assumptions -> forall (y z : word) (T : Type) (thenVal elseVal : T), (if word.eqb y z then thenVal else elseVal) = (if word.ltu (word.sub y z) (word.of_Z 1) then thenVal else elseVal) real_ext_spec_implies_simple_ext_spec : forall (p : MMIO.parameters) (t : trace) (m : MMIO.mem) (a : MMIOAction) (args : list MMIO.word) (post : MMIO.mem -> list MMIO.word -> Prop), real_ext_spec t m a args post -> simple_ext_spec t m a args post FlatToRiscv.put_put_same : forall (K V : Type) (M : map.map K V) (k : K) (v1 v2 : V) (m : M), map.put (map.put m k v1) k v2 = map.put m k v2 PropExtensionality.propositional_extensionality : forall P Q : Prop, P <-> Q -> P = Q AdmitAxiom.proof_admitted : False used in map_ok_subproof5 to prove: forall (m1 m2 : map p ok) (k : parameters.key) (v : parameters.value), map.get m2 k = Some v -> map.get (map.putmany m1 m2) k = Some v used in map_ok_subproof4 to prove: forall (m1 m2 : map p ok) (k : parameters.key), map.get m2 k = None -> map.get (map.putmany m1 m2) k = map.get m1 k used in map_ok_subproof3 to prove: forall (m : map p ok) (k k' : parameters.key), k <> k' -> map.get (map.remove m k') k = map.get m k used in map_ok_subproof2 to prove: forall (m : map p ok) (k : parameters.key), map.get (map.remove m k) k = None used in map_ok_subproof1 to prove: forall (m : map p ok) (k : parameters.key) (v : parameters.value) (k' : parameters.key), k <> k' -> map.get (map.put m k' v) k = map.get m k used in map_ok_subproof0 to prove: forall (m : map p ok) (k : parameters.key) (v : parameters.value), map.get (map.put m k v) k = Some v used in map_ok_subproof to prove: forall m1 m2 : map p ok, (forall k : parameters.key, map.get m1 k = map.get m2 k) -> m1 = m2 max_ext_call_code_size_bound : forall (p : FlattenExpr.parameters) (f : FlattenExpr.actname), 0 <= FlattenExpr.max_ext_call_code_size f <= 7 map_undef_on_weaken : forall (P Q : PropSet.set word32) (m : Mem), map.undef_on m Q -> PropSet.subset P Q -> map.undef_on m P FlatImp.exec.map_split_diff : forall pp : Semantics.parameters, FlatImp.env -> forall m m1 m2 m3 : mem, map.split m m2 m1 -> map.split m m3 m1 -> m2 = m3 load4bytes_in_MMIO_is_None : forall (p : MMIO.parameters) (m : MMIO.mem) (addr : MMIO.word), map.undef_on m isMMIOAddr -> isMMIOAddr addr -> load_bytes 4 m addr = None FunctionalExtensionality.functional_extensionality_dep : forall (A : Type) (B : A -> Type) (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g FlatImp.exec.ext_spec_intersect : forall (pp : Semantics.parameters) (t : list (mem * actname * list Semantics.word * (mem * list Semantics.word))) (mGive1 mGive2 : mem) (a : actname) (args : list Semantics.word) (post1 post2 : mem -> list Semantics.word -> Prop), ext_spec t mGive1 a args post1 -> ext_spec t mGive2 a args post2 -> mGive1 = mGive2 /\ ext_spec t mGive1 a args (fun (mReceive : mem) (resvals : list Semantics.word) => post1 mReceive resvals /\ post2 mReceive resvals) ext_spec_Proper : forall (trace : list (mem * actname * list Semantics.word * (mem * list Semantics.word))) (m : mem) (act : actname) (args : list Semantics.word), Morphisms.Proper (Morphisms.respectful (Morphisms.pointwise_relation mem (Morphisms.pointwise_relation (list Semantics.word) Basics.impl)) Basics.impl) (ext_spec trace m act args) FlatToRiscv.divisibleBy4_admit : forall p : FlatToRiscv.FlatToRiscv.parameters, FlatToRiscv.FlatToRiscv.assumptions -> forall x y : word, FlatToRiscv.divisibleBy4 x -> FlatToRiscv.divisibleBy4 y compile_lit_new_size : forall iset : InstructionSet, FlatToRiscvDef.FlatToRiscvDef.parameters -> forall (x : Register) (v : Z), 0 <= Zlength (FlatToRiscvDef.compile_lit_new iset x v) <= 15 FlatToRiscv.compile_lit_correct_full : forall p : FlatToRiscv.FlatToRiscv.parameters, FlatToRiscv.FlatToRiscv.assumptions -> forall (initialL : RiscvMachine.RiscvMachine Syntax.varname FlatToRiscvDef.FlatToRiscvDef.actname) (post : RiscvMachine.RiscvMachine Register FlatToRiscvDef.FlatToRiscvDef.actname -> Prop) (x : Syntax.varname) (v : Z) (R : FlatToRiscv.FlatToRiscv.mem -> Prop), getNextPc initialL = add (getPc initialL) (ZToReg 4) -> let insts := FlatToRiscvDef.compile_stmt FlatToRiscv.FlatToRiscv.iset (FlatImp.SLit x v) in let d := mul (ZToReg 4) (ZToReg (Zlength insts)) in Separation.sep (GoFlatToRiscv.program (getPc initialL) insts) R (getMem initialL) -> FlatToRiscvDef.valid_registers (FlatImp.SLit x v) -> FlatToRiscv.runsTo (withRegs (map.put (getRegs inibedrock2/compiler/src/examples/FE310Compiler (real: 42.80, user: 20.27, sys: 0.35, mem: 610324 ko) bedrock2/compiler/src/examples/EditDistExample (real: 2.19, user: 0.80, sys: 0.26, mem: 499980 ko) bedrock2/compiler/src/examples/swap_bytes_over_uart_hexdump (real: 2.04, user: 0.74, sys: 0.23, mem: 505316 ko) Kami/Ex/IsaRv32Pgm (real: 2.28, user: 0.82, sys: 0.26, mem: 507796 ko) File "./Kami/Ex/ProcDec.v", line 279, characters 2-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcDec.v", line 289, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcDec.v", line 301, characters 2-31: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcDec.v", line 314, characters 0-76: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcDec (real: 9.01, user: 4.13, sys: 0.26, mem: 512264 ko) Kami/Ext/Extraction (real: 2.36, user: 0.79, sys: 0.24, mem: 488532 ko) Kami/Ex/SimpleFifoCorrect (real: 74.95, user: 37.44, sys: 0.37, mem: 672092 ko) File "./Kami/Tutorial.v", line 72, characters 0-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 801, characters 2-32: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Tutorial (real: 7.47, user: 3.39, sys: 0.25, mem: 517872 ko) File "./Kami/Ex/ProcThreeStage.v", line 806, characters 2-35: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 811, characters 2-35: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 816, characters 2-38: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 821, characters 2-38: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 831, characters 2-36: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 839, characters 2-33: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 844, characters 2-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/IsaRv32/PgmGcd (real: 4.45, user: 1.88, sys: 0.27, mem: 521816 ko) File "./Kami/Ex/ProcThreeStage.v", line 855, characters 2-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStage.v", line 871, characters 0-251: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcThreeStage (real: 12.09, user: 5.62, sys: 0.28, mem: 535096 ko) Kami/Ex/IsaRv32/PgmFact (real: 4.26, user: 1.83, sys: 0.25, mem: 522312 ko) Kami/Ex/IsaRv32/PgmBsort (real: 4.09, user: 1.75, sys: 0.23, mem: 521896 ko) Kami/Ex/IsaRv32/PgmHanoi (real: 4.05, user: 1.74, sys: 0.23, mem: 522080 ko) Kami/Ex/IsaRv32/PgmDekker1 (real: 4.24, user: 1.78, sys: 0.27, mem: 520604 ko) Kami/Ex/IsaRv32/PgmDekker2 (real: 4.29, user: 1.83, sys: 0.25, mem: 524584 ko) Kami/Ex/IsaRv32/PgmPeterson1 (real: 4.23, user: 1.80, sys: 0.27, mem: 519680 ko) Kami/Ex/IsaRv32/PgmPeterson2 (real: 4.14, user: 1.80, sys: 0.24, mem: 519696 ko) Kami/Ex/IsaRv32/PgmMatMulInit (real: 4.29, user: 1.81, sys: 0.25, mem: 521416 ko) Kami/Ex/IsaRv32/PgmMatMulNormal1 (real: 4.30, user: 1.83, sys: 0.26, mem: 519240 ko) Kami/Ex/IsaRv32/PgmMatMulNormal2 (real: 4.21, user: 1.81, sys: 0.24, mem: 519724 ko) Kami/Ex/IsaRv32/PgmMatMulReport (real: 4.32, user: 1.87, sys: 0.25, mem: 519908 ko) Kami/Ex/IsaRv32/PgmBankerInit (real: 4.21, user: 1.81, sys: 0.24, mem: 522124 ko) Kami/Ex/IsaRv32/PgmBankerWorker1 (real: 4.43, user: 1.87, sys: 0.27, mem: 522776 ko) Kami/Ex/IsaRv32/PgmBankerWorker2 (real: 4.24, user: 1.80, sys: 0.25, mem: 520460 ko) Kami/Ex/ProcThreeStInl (real: 2.03, user: 0.75, sys: 0.23, mem: 490144 ko) Kami/Ex/IsaRv32/PgmBankerWorker3 (real: 4.25, user: 1.85, sys: 0.24, mem: 520188 ko) File "./Kami/Ex/ProcFetchDecode.v", line 333, characters 2-32: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcFetchDecode.v", line 342, characters 2-32: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcFetchDecode.v", line 356, characters 0-68: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcFetchDecode (real: 4.85, user: 2.11, sys: 0.24, mem: 508168 ko) tialL) x (ZToReg v)) (withPc (add (getPc initialL) d) (withNextPc (add (getNextPc initialL) d) initialL))) post -> FlatToRiscv.runsTo initialL post assume_riscv_word_properties : forall p : MMIO.parameters, RiscvWordProperties.word.riscv_ok MMIO.word ROCQ compile bedrock2/compiler/src/examples/EditDistExample.v ROCQ compile bedrock2/compiler/src/examples/swap_bytes_over_uart_hexdump.v 37250200 1305c5fe 03210500 b7850010 93850500 37060040 13060600 9306f001 3377d100 93070001 3318f700 b3680601 23a01501 13031000 37390110 13098901 93090027 23203901 373a0110 130a8a00 23206a00 b73a0110 938aca00 23a06a00 372b0110 130b8b03 b70b0300 938b0b00 23207b01 9303e002 b3007000 33027340 630c0206 b7020080 93820200 33015000 b3047340 33fc2400 b37c5c00 638c0c00 373d0110 130d4d00 03210d00 b3846440 6ff05ffe 37340110 13040400 b3015000 b3047340 b3fd3400 33fe5d00 63080e00 83210400 b3846440 6ff0dffe 23201400 b3002000 33026240 63967000 33424200 6f004000 6ff0dff8 make[3]: Leaving directory 'bedrock2/compiler' make[2]: Leaving directory 'bedrock2/compiler' ROCQ compile Kami/Ex/IsaRv32Pgm.v ROCQ compile Kami/Ex/ProcDec.v ROCQ compile Kami/Ext/Extraction.v ROCQ compile Kami/Tutorial.v ROCQ compile Kami/Ex/ProcThreeStage.v ROCQ compile Kami/Ex/IsaRv32/PgmGcd.v ROCQ compile Kami/Ex/IsaRv32/PgmFact.v ROCQ compile Kami/Ex/IsaRv32/PgmBsort.v ROCQ compile Kami/Ex/IsaRv32/PgmHanoi.v ROCQ compile Kami/Ex/IsaRv32/PgmDekker1.v ROCQ compile Kami/Ex/IsaRv32/PgmDekker2.v ROCQ compile Kami/Ex/IsaRv32/PgmPeterson1.v ROCQ compile Kami/Ex/IsaRv32/PgmPeterson2.v ROCQ compile Kami/Ex/IsaRv32/PgmMatMulInit.v ROCQ compile Kami/Ex/IsaRv32/PgmMatMulNormal1.v ROCQ compile Kami/Ex/IsaRv32/PgmMatMulNormal2.v ROCQ compile Kami/Ex/IsaRv32/PgmMatMulReport.v ROCQ compile Kami/Ex/IsaRv32/PgmBankerInit.v ROCQ compile Kami/Ex/IsaRv32/PgmBankerWorker1.v ROCQ compile Kami/Ex/IsaRv32/PgmBankerWorker2.v ROCQ compile Kami/Ex/IsaRv32/PgmBankerWorker3.v ROCQ compile Kami/Ex/ProcThreeStInl.v ROCQ compile Kami/Ex/ProcFetchDecode.v ROCQ compile Kami/Ex/ProcDecInl.v ROCQ compile Kami/Ex/InDepthTutorial.v Inductive Modules : Type := RegFile : string -> list string -> string -> forall (IdxBits : nat) (Data : Kind), ConstT (Vector Data IdxBits) -> Modules | Mod : list RegInitT -> list (Struct.Attribute (Action Void)) -> list DefMethT -> Modules | ConcatMod : Modules -> Modules -> Modules For RegFile: Arguments IdxBits, Data are implicit For RegFile: Argument scopes are [string_scope list_scope string_scope nat_scope _ _] For Mod: Argument scopes are [list_scope list_scope list_scope] Inductive ActionT (ty : Kind -> Type) (lretT : Kind) : Type := MCall : string -> forall s : SignatureT, (arg s) @ (ty) -> (ty (ret s) -> ActionT ty lretT) -> ActionT ty lretT | Let_ : forall lretT' : FullKind, Expr ty lretT' -> (fullType ty lretT' -> ActionT ty lretT) -> ActionT ty lretT | ReadNondet : forall k : FullKind, (fullType ty k -> ActionT ty lretT) -> ActionT ty lretT | ReadReg : string -> forall k : FullKind, (fullType ty k -> ActionT ty lretT) -> ActionT ty lretT | WriteReg : string -> forall k : FullKind, Expr ty k -> ActionT ty lretT -> ActionT ty lretT | IfElse : (Bool) @ (ty) -> forall k : Kind, ActionT ty k -> ActionT ty k -> (ty k -> ActionT ty lretT) -> ActionT ty lretT | Assert_ : (Bool) @ (ty) -> ActionT ty lretT -> ActionT ty lretT | Displ : list (Disp ty) -> ActionT ty lretT -> ActionT ty lretT | Return : (lretT) @ (ty) -> ActionT ty lretT For MCall: Arguments ty, lretT are implicit For Let_: Arguments ty, lretT, lretT' are implicit For ReadNondet: Arguments ty, lretT are implicit For ReadReg: Arguments ty, lretT are implicit For WriteReg: Arguments ty, lretT, k are implicit For IfElse: Arguments ty, lretT, k are implicit For Assert_: Arguments ty, lretT are implicit For Displ: Arguments ty, lretT are implicit For Return: Arguments ty, lretT are implicit For ActionT: Argument scopes are [function_scope _] For MCall: Argument scopes are [function_scope _ string_scope _ _ function_scope] For Let_: Argument scopes are [function_scope _ _ _ function_scope] For ReadNondet: Argument scopes are [function_scope _ _ function_scope] For ReadReg: Argument scopes are [function_scope _ string_scope _ function_scope] For WriteReg: Argument scopes are [function_scope _ string_scope _ _ _] For IfElse: Argument scopes are [function_scope _ _ _ _ _ function_scope] For Assert_: Argument scopes are [function_scope _ _ _] For Displ: Argument scopes are [function_scope _ list_scope _] For Return: Argument scopes are [function_scope _ _] Inductive Expr (ty : Kind -> Type) : FullKind -> Type := Var : forall k : FullKind, fullType ty k -> Expr ty k | Const : forall k : Kind, ConstT k -> (k) @ (ty) | UniBool : UniBoolOp -> (Bool) @ (ty) -> (Bool) @ (ty) | BinBool : BinBoolOp -> (Bool) @ (ty) -> (Bool) @ (ty) -> (Bool) @ (ty) | UniBit : forall n1 n2 : nat, UniBitOp n1 n2 -> (Bit n1) @ (ty) -> (Bit n2) @ (ty) | BinBit : forall n1 n2 n3 : nat, BinBitOp n1 n2 n3 -> (Bit n1) @ (ty) -> (Bit n2) @ (ty) -> (Bit n3) @ (ty) | BinBitBool : forall n1 n2 : nat, BinBitBoolOp n1 n2 -> (Bit n1) @ (ty) -> (Bit n2) @ (ty) -> (Bool) @ (ty) | ITE : forall k : FullKind, (Bool) @ (ty) -> Expr ty k -> Expr ty k -> Expr ty k | Eq : forall k : Kind, (k) @ (ty) -> (k) @ (ty) -> (Bool) @ (ty) | ReadIndex : forall (i : nat) (k : Kind), (Bit i) @ (ty) -> (Vector k i) @ (ty) -> (k) @ (ty) | ReadField : forall (n : nat) (ls : Vector.t (Struct.Attribute Kind) n) (i : Fin.t n), (Struct ls) @ (ty) -> (Vector.nth (Vector.map (Struct.attrType (A:=Kind)) ls) i) @ (ty) | BuildVector : forall (n : Kind) (k : nat), Vec (n) @ (ty) k -> (Vector n k) @ (ty) | BuildStruct : forall (n : nat) (attrs : Vector.t (Struct.Attribute Kind) n), ilist.ilist (fun a : Struct.Attribute Kind => (Struct.attrType a) @ (ty)) attrs -> (Struct attrs) @ (ty) | UpdateVector : forall (i : nat) (k : Kind), (Vector k i) @ (ty) -> (Bit i) @ (ty) -> (k) @ (ty) -> (Vector k i) @ (ty) | ReadArrayIndex : forall (i : nat) (k : Kind), (Bit (Nat.log2 (2 * i))) @ (ty) -> (Array k i) @ (ty) -> (k) @ (ty) | BuildArray : forall (n : Kind) (k : nat), Vector.t (n) @ (ty) (S k) -> (Array n k) @ (ty) | UpdateArray : forall (i : nat) (k : Kind), (Array k i) @ (ty) -> (Bit (Nat.log2 (2 * i))) @ (ty) -> (k) @ (ty) -> (Array k i) @ (ty) For Const: Argument k is implicit For UniBool: Argument ty is implicit For BinBool: Argument ty is implicit For UniBit: Arguments ty, n1, n2 are implicit For BinBit: Arguments ty, n1, n2, n3 are implicit For BinBitBool: Arguments ty, n1, n2 are implicit For ITE: Arguments ty, k are implicit For Eq: Arguments ty, k are implicit For ReadIndex: Arguments ty, i, k are implicit For ReadField: Arguments ty, n, ls are implicit For BuildVector: Arguments ty, n, k are implicit For BuildStruct: Arguments ty, n, attrs are implicit For UpdateVector: Arguments ty, i, k are implicit For ReadArrayIndex: Arguments ty, i, k are implicit For BuildArray: Arguments ty, n, k are implicit For UpdateArray: Arguments ty, i, k are implicit For Expr: Argument scopes are [function_scope _] For Var: Argument scopes are [function_scope _ _] For Const: Argument scopes are [function_scope _ _] For UniBool: Argument scopes are [function_scope _ _] For BinBool: Argument scopes are [function_scope _ _ _] For UniBit: Argument scopes are [function_scope nat_scope nat_scope _ _] For BinBit: Argument scopes are [function_scope nat_scope nat_scope nat_scope _ _ _] For BinBitBool: Argument scopes are [function_scope nat_scope nat_scope _ _ _] For ITE: Argument scopes are [function_scope _ _ _ _] For Eq: Argument scopes are [function_scope _ _ _] For ReadIndex: Argument scopes are [function_scope nat_scope _ _ _] For ReadField: Argument scopes are [function_scope nat_scope _ _ _] For BuildVector: Argument scopes are [function_scope _ nat_scope _] For BuildStruct: Argument scopes are [function_scope nat_scope _ _] For UpdateVector: Argument scopes are [function_scope nat_scope _ _ _ _] For ReadArrayIndex: Argument scopes are [function_scope nat_scope _ _ _] For BuildArray: Argument scopes are [function_scope _ nat_scope _] For UpdateArray: Argument scopes are [function_scope nat_scope _ _ _ _] evalExpr = fix evalExpr (exprT : FullKind) (e : Expr type exprT) {struct e} : fullType type exprT := match e in (Expr _ exprT0) return (fullType type exprT0) with | @Var _ _ v => v | @Const _ k v => evalConstT v | UniBool op e1 => evalUniBool op (evalExpr (SyntaxKind Bool) e1) | BinBool op e1 e2 => evalBinBool op (evalExpr (SyntaxKind Bool) e1) (evalExpr (SyntaxKind Bool) e2) | @UniBit _ n1 n2 op e1 => evalUniBit op (evalExpr (SyntaxKind (Bit n1)) e1) | @BinBit _ n1 n2 n3 op e1 e2 => evalBinBit op (evalExpr (SyntaxKind (Bit n1)) e1) (evalExpr (SyntaxKind (Bit n2)) e2) | @BinBitBool _ n1 n2 op e1 e2 => evalBinBitBool op (evalExpr (SyntaxKind (Bit n1)) e1) (evalExpr (SyntaxKind (Bit n2)) e2) | @ITE _ k p e1 e2 => if evalExpr (SyntaxKind Bool) p then evalExpr k e1 else evalExpr k e2 | @Eq _ k e1 e2 => if isEq k (evalExpr (SyntaxKind k) e1) (evalExpr (SyntaxKind k) e2) then true else false | @ReadIndex _ i0 k i f => evalExpr (SyntaxKind (Vector k i0)) f (evalExpr (SyntaxKind (Bit i0)) i) | @ReadField _ n ls i e0 => VectorFacts.Vector_nth_map (Struct.attrType (A:=Kind)) type ls (evalExpr (SyntaxKind (Struct ls)) e0) i | @BuildVector _ n k vec => evalVec (mapVec (evalExpr (SyntaxKind n)) vec) | @BuildStruct _ n attrs ils => ilist.ilist_to_fun_m (Expr type) (fullType type) (fun sk : Struct.Attribute Kind => SyntaxKind (Struct.attrType sk)) evalExpr ils | @UpdateVector _ i0 k fn i v => fun w : word i0 => if weq w (evalExpr (SyntaxKind (Bit i0)) i) then evalExpr (SyntaxKind k) v else evalExpr (SyntaxKind (Vector k i0)) fn w | @ReadArrayIndex _ i k idx vec => evalExpr (SyntaxKind (Array k i)) vec (natToFin i # (evalExpr (SyntaxKind (Bit (Nat.log2 (2 * i)))) idx)) | @BuildArray _ i k vecVal => evalArray (Vector.map (evalExpr (SyntaxKind i)) vecVal) | @UpdateArray _ i k arr idx val => fun fini : Fin.t (S i) => if Fin.eq_dec fini (natToFin i # (evalExpr (SyntaxKind (Bit (Nat.log2 (2 * i)))) idx)) then evalExpr (SyntaxKind k) val else evalExpr (SyntaxKind (Array k i)) arr fini end : forall exprT : FullKind, Expr type exprT -> fullType type exprT Argument exprT is implicit Inductive SemAction (oldRegs : RegsT) : forall k : Kind, ActionT type k -> UpdatesT -> MethsT -> type k -> Prop := SemMCall : forall (meth : M.key) (s : SignatureT) (marg : (arg s) @ (type)) (mret : type (ret s)) (retK : Kind) (fret : type retK) (cont : type (ret s) -> ActionT type retK) (newRegs : UpdatesT) (calls : MethsT) (acalls : M.t {x : SignatureT & SignT x}), (calls) @[ meth]%fmap = None -> acalls = (calls) #[ meth |-> (evalExpr marg, mret)]%fmap -> SemAction oldRegs (cont mret) newRegs calls fret -> SemAction oldRegs (MCall meth s marg cont) newRegs acalls fret | SemLet : forall (k : FullKind) (e : Expr type k) (retK : Kind) (fret : type retK) (cont : fullType type k -> ActionT type retK) (newRegs : UpdatesT) (calls : MethsT), SemAction oldRegs (cont (evalExpr e)) newRegs calls fret -> SemAction oldRegs (LET name <- e; cont name)%kami_action newRegs calls fret | SemReadNondet : forall (valueT : FullKind) (valueV : fullType type valueT) (retK : Kind) (fret : type retK) (cont : fullType type valueT -> ActionT type retK) (newRegs : UpdatesT) (calls : MethsT), SemAction oldRegs (cont valueV) newRegs calls fret -> SemAction oldRegs (Nondet name : valueT; cont name)%kami_action newRegs calls fret | SemReadReg : forall (r : string) (regT : FullKind) (regV : fullType type regT) (retK : Kind) (fret : type retK) (cont : fullType type regT -> ActionT type retK) (newRegs : UpdatesT) (calls : MethsT), (oldRegs) @[ r]%fmap = Some (existT (fullType type) regT regV) -> SemAction oldRegs (cont regV) newRegs calls fret -> SemAction oldRegs (Read name <- r; cont name)%kami_action newRegs calls fret | SemWriteReg : forall (r : string) (k : FullKind) (e : Expr type k) (retK : Kind) (fret : type retK) (cont : ActionT type retK) (newRegs : M.t {x : FullKind & fullType type x}) (calls : MethsT) (anewRegs : M.t {x : FullKind & fullType type x}), (newRegs) @[ r]%fmap = None -> anewRegs = (newRegs) #[ r |-> evalExpr e]%fmap -> SemAction oldRegs cont newRegs calls fret -> SemAction oldRegs (Write r <- e; cont)%kami_action anewRegs calls fret | SemIfElseTrue : forall (p : (Bool) @ (type)) (k1 : Kind) (a a' : ActionT type k1) (r1 : type k1) (k2 : Kind) (cont : type k1 -> ActionT type k2) (newRegs1 newRegs2 : M.Map.t {x : FullKind & fullType type x}) (calls1 calls2 : M.Map.t {x : SignatureT & SignT x}) (r2 : type k2), M.Disj newRegs1 newRegs2 -> M.Disj calls1 calls2 -> evalExpr p = true -> SemAction oldRegs a newRegs1 calls1 r1 -> SemAction oldRegs (cont r1) newRegs2 calls2 r2 -> forall (unewRegs : M.Map.t {x : FullKind & fullType type x}) (ucalls : M.Map.t {x : SignatureT & SignT x}), unewRegs = M.union newRegs1 newRegs2 -> ucalls = M.union calls1 calls2 -> SemAction oldRegs (If p then a else a' as name; cont name)%kami_action unewRegs ucalls r2 | SemIfElseFalse : forall (p : (Bool) @ (type)) (k1 : Kind) (a a' : ActionT type k1) (r1 : type k1) (k2 : Kind) (cont : type k1 -> ActionT type k2) (newRegs1 newRegs2 : M.Map.t {x : FullKind & fullType type x}) (calls1 calls2 : M.Map.t {x : SignatureT & SignT x}) (r2 : type k2), M.Disj newRegs1 newRegs2 -> M.Disj calls1 calls2 -> evalExpr p = false -> SemAction oldRegs a' newRegs1 calls1 r1 -> SemAction oldRegs (cont r1) newRegs2 calls2 r2 -> forall (unewRegs : M.Map.t {x : FullKind & fullType type x}) (ucalls : M.Map.t {x : SignatureT & SignT x}), unewRegs = M.union newRegs1 newRegs2 -> ucalls = M.union calls1 calls2 -> SemAction oldRegs (If p then a else a' as name; cont name)%kami_action unewRegs ucalls r2 | SemAssertTrue : forall (p : (Bool) @ (type)) (k2 : Kind) (cont : ActionT type k2) (newRegs2 : UpdatesT) (calls2 : MethsT) (r2 : type k2), evalExpr p = true -> SemAction oldRegs cont newRegs2 calls2 r2 -> SemAction oldRegs (Assert p; cont)%kami_action newRegs2 calls2 r2 | SemDispl : forall (ls : list (Disp type)) (k2 : Kind) (cont : ActionT type k2) (newRegs2 : UpdatesT) (calls2 : MethsT) (r2 : type k2), SemAction oldRegs cont newRegs2 calls2 r2 -> SemAction oldRegs (Displ ls cont) newRegs2 calls2 r2 | SemReturn : forall (k : Kind) (e : (k) @ (type)) (evale : fullType type (SyntaxKind k)), evale = evalExpr e -> SemAction oldRegs (Ret e)%kami_action []%fmap []%fmap evale For SemAction: Argument k is implicit For SemMCall: Arguments oldRegs, meth, s, mret, retK, fret, newRegs, calls, acalls are implicit For SemLet: Arguments oldRegs, k, retK, fret, newRegs, calls are implicit For SemReadNondet: Arguments oldRegs, retK, fret, newRegs, calls are implicit For SemReadReg: Arguments oldRegs, regT, regV, retK, fret, newRegs, calls are implicit For SemWriteReg: Arguments oldRegs, r, k, retK, fret, cont, newRegs, calls, anewRegs are implicit For SemIfElseTrue: Arguments oldRegs, k1, a, r1, k2, newRegs1, newRegs2, calls1, calls2, r2, unewRegs, ucalls are implicit For SemIfElseFalse: Arguments oldRegs, k1, a', r1, k2, newRegs1, newRegs2, calls1, calls2, r2, unewRegs, ucalls are implicit For SemAssertTrue: Arguments oldRegs, k2, cont, newRegs2, calls2, r2 are implicit For SemDispl: Arguments oldRegs, k2, cont, newRegs2, calls2, r2 are implicit For SemReturn: Arguments k, evale are implicit For SemMCall: Argument scopes are [_ _ _ _ _ _ _ function_scope _ _ _ _ _ _] For SemLet: Argument scopes are [_ _ _ _ _ function_scope _ _ _] For SemReadNondet: Argument scopes are [_ _ _ _ _ function_scope _ _ _] For SemReadReg: Argument scopes are [_ string_scope _ _ _ _ function_scope _ _ _ _] For SemWriteReg: Argument scopes are [_ string_scope _ _ _ _ _ _ _ _ _ _ _] For SemIfElseTrue: Argument scopes are [_ _ _ _ _ _ _ function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _] For SemIfElseFalse: Argument scopes are [_ _ _ _ _ _ _ function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _] For SemDispl: Argument scopes are [_ list_scope _ _ _ _ _ _] Record LabelT : Type := Build_LabelT { annot : option (option string); defs : MethsT; calls : MethsT } Inductive Substep (m : Modules) (o : RegsT) : UpdatesT -> UnitLabel -> MethsT -> Prop := EmptyRule : Substep m o []%fmap (Rle None) []%fmap | EmptyMeth : Substep m o []%fmap (Meth None) []%fmap | SingleRule : forall (k : string) (a : Action Void), In (k :: a)%struct (getRules m) -> forall (u : UpdatesT) (cs : MethsT), SemAction o (a type) u cs WO -> Substep m o u (Rle (Some k)) cs | SingleMeth : forall f : DefMethT, In f (getDefsBodies m) -> forall (u : UpdatesT) (cs : MethsT) (argV : type (arg (projT1 (Struct.attrType f)))) (retV : type (ret (projT1 (Struct.attrType f)))), SemAction o (projT2 (Struct.attrType f) type argV) u cs retV -> forall sig : Struct.Attribute {x : SignatureT & SignT x}, sig = (Struct.attrName f :: existT SignT (projT1 (Struct.attrType f)) (argV, retV))%struct -> Substep m o u (Meth (Some sig)) cs For SingleRule: Arguments o, u, cs are implicit For SingleMeth: Arguments o, u, cs, argV, retV, sig are implicit For SingleRule: Argument scopes are [_ _ string_scope _ _ _ _ _] Inductive SubstepsInd (m : Modules) (o : RegsT) : UpdatesT -> LabelT -> Prop := SubstepsNil : SubstepsInd m o []%fmap {| annot := None; defs := []%fmap; calls := []%fmap |} | SubstepsCons : forall (u : UpdatesT) (l : LabelT), SubstepsInd m o u l -> forall (su : UpdatesT) (scs : MethsT) (sul : UnitLabel), Substep m o su sul scs -> CanCombineUUL u l su scs sul -> forall (uu : M.Map.t {x : FullKind & fullType type x}) (ll : LabelT), uu = M.union u su -> ll = mergeLabel (getLabel sul scs) l -> SubstepsInd m o uu ll For SubstepsCons: Arguments m, o, u, l, su, scs, sul, uu, ll are implicit Inductive StepInd (m : Modules) (o : RegsT) : UpdatesT -> LabelT -> Prop := StepIndIntro : forall (u : UpdatesT) (l : LabelT), SubstepsInd m o u l -> wellHidden m (hide l) -> StepInd m o u (hide l) For StepIndIntro: Arguments m, o, u, l are implicit Inductive Multistep (m : Modules) : RegsT -> RegsT -> list LabelT -> Prop := NilMultistep : forall o1 o2 : RegsT, o1 = o2 -> Multistep m o1 o2 nil | Multi : forall (o : RegsT) (a : list LabelT) (n : RegsT), Multistep m o n a -> forall (u : UpdatesT) (l : LabelT), Step m n u l -> Multistep m o (M.union u n) (l :: a) For NilMultistep: Arguments o1, o2 are implicit For Multi: Arguments m, o, a, n, u, l are implicit For Multistep: Argument scopes are [_ _ _ list_scope] For Multi: Argument scopes are [_ _ list_scope _ _ _ _ _] Inductive Behavior (m : Modules) : RegsT -> LabelSeqT -> Prop := BehaviorIntro : forall (a : list LabelT) (n : RegsT), Multistep m (initRegs (getRegInits m)) n a -> Behavior m n a For BehaviorIntro: Arguments m, a, n are implicit For BehaviorIntro: Argument scopes are [_ list_scope _ _] traceRefines = fun (p : MethsT -> MethsT) (m1 m2 : Modules) => forall (s1 : RegsT) (sig1 : LabelSeqT), Behavior m1 s1 sig1 -> exists (s2 : RegsT) (sig2 : LabelSeqT), Behavior m2 s2 sig2 /\ equivalentLabelSeq p sig1 sig2 : (MethsT -> MethsT) -> Modules -> Modules -> Prop Argument scopes are [function_scope _ _] traceRefines_refl : forall m : Modules, traceRefines id m m traceRefines_trans : forall (ma mb mc : Modules) (p q : MethsT -> MethsT), traceRefines p ma mb -> traceRefines q mb mc -> traceRefines (fun f : MethsT => q (p f)) ma mc traceRefines_comm : forall ma mb : Modules, NoDup (Struct.namesOf (getRegInits (ma ++ mb)%kami)) -> traceRefines id (ma ++ mb)%kami (mb ++ ma)%kami traceRefines_assoc_1 : forall ma mb mc : Modules, traceRefines id ((ma ++ mb) ++ mc)%kami (ma ++ mb ++ mc)%kami traceRefines_assoc_2 : forall ma mb mc : Modules, traceRefines id (ma ++ mb ++ mc)%kami ((ma ++ mb) ++ mc)%kami traceRefines_modular_noninteracting : forall ma mb mc md : Modules, ModEquiv type typeUT ma -> ModEquiv type typeUT mb -> ModEquiv type typeUT mc -> ModEquiv type typeUT md -> DisjList (Struct.namesOf (getRegInits ma)) (Struct.namesOf (getRegInits mc)) -> DisjList (Struct.namesOf (getRegInits mb)) (Struct.namesOf (getRegInits md)) -> ValidRegsModules type (ma ++ mc)%kami -> ValidRegsModules type (mb ++ md)%kami -> DisjList (getDefs ma) (getDefs mc) -> DisjList (getCalls ma) (getCalls mc) -> DisjList (getDefs mb) (getDefs md) -> DisjList (getCalls mb) (getCalls md) -> forall vp : M.key -> {x : SignatureT & SignT x} -> option {x : SignatureT & SignT x}, NonInteracting ma mc -> NonInteracting mb md -> (ma <<=[ vp ] mb) -> (mc <<=[File "./Kami/Ex/InDepthTutorial.v", line 229, characters 0-58: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 232, characters 0-26: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 241, characters 0-55: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 245, characters 0-25: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 274, characters 0-30: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 277, characters 0-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 357, characters 0-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 360, characters 0-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 379, characters 0-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 382, characters 0-27: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 408, characters 0-334: Warning: datav cannot be defined because it is informative and impl12_inv is not. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 408, characters 0-334: Warning: Hdatav cannot be defined because the projection datav was not defined. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 408, characters 0-334: Warning: eltv cannot be defined because it is informative and impl12_inv is not. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 408, characters 0-334: Warning: Heltv cannot be defined because the projection eltv was not defined. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 408, characters 0-334: Warning: Hinv cannot be defined because the projections eltv, datav were not defined. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 527, characters 0-29: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 530, characters 0-28: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 554, characters 0-33: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/InDepthTutorial.v", line 557, characters 0-343: Warning: datav cannot be defined because it is informative and impl123_inv is not. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 557, characters 0-343: Warning: Hdatav cannot be defined because the projection datav was not defined. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 557, characters 0-343: Warning: eltv cannot be defined because it is informative and impl123_inv is not. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 557, characters 0-343: Warning: Heltv cannot be defined because the projection eltv was not defined. [cannot-define-projection,records] File "./Kami/Ex/InDepthTutorial.v", line 557, characters 0-343: Warning: Hinv cannot be defined because the projections eltv, datav were not defined. [cannot-define-projection,records] Kami/Ex/ProcDecInl (real: 36.23, user: 17.33, sys: 0.37, mem: 724164 ko) Kami/Ex/IsaRv32PgmExt (real: 2.54, user: 0.92, sys: 0.31, mem: 550756 ko) File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: sbv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hsbv0 cannot be defined because the projection sbv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: d2eeltv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hd2eeltv0 cannot be defined because the projection d2eeltv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: d2efullv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hd2efullv0 cannot be defined because the projection d2efullv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: e2weltv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: He2weltv0 cannot be defined because the projection e2weltv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: e2wfullv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: He2wfullv0 cannot be defined because the projection e2wfullv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: stallv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hstallv0 cannot be defined because the projection stallv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: stalledv0 cannot be defined because it is informative and p3st_scoreboard_waw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hstalledv0 cannot be defined because the projection stalledv0 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 155, characters 2-1108: Warning: Hinv0 cannot be defined because the projections d2efullv0, d2eeltv0, e2wfullv0, e2weltv0, stallv0, stalledv0, sbv0 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: d2eeltv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hd2eeltv1 cannot be defined because the projection d2eeltv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: d2efullv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hd2efullv1 cannot be defined because the projection d2efullv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: e2weltv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: He2weltv1 cannot be defined because the projection e2weltv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: e2wfullv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: He2wfullv1 cannot be defined because the projection e2wfullv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: stallv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hstallv1 cannot be defined because the projection stallv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: stalledv1 cannot be defined because it is informative and p3st_raw_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hstalledv1 cannot be defined because the projection stalledv1 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hd2einv1 cannot be defined because the projections d2efullv1, stallv1, d2eeltv1, stalledv1 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: He2winv1 cannot be defined because the projections e2wfullv1, stallv1, e2weltv1, stalledv1 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 192, characters 2-1091: Warning: Hd2winv1 cannot be defined because the projections d2efullv1, e2wfullv1, d2eeltv1, e2weltv1 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: pgmv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: Hpgmv2 cannot be defined because the projection pgmv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: rfv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: Hrfv2 cannot be defined because the projection rfv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: d2eeltv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: Hd2eeltv2 cannot be defined because the projection d2eeltv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: d2efullv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: Hd2efullv2 cannot be defined because the projection d2efullv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: e2weltv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: He2weltv2 cannot be defined because the projection e2weltv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: e2wfullv2 cannot be defined because it is informative and p3st_decode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: He2wfullv2 cannot be defined because the projection e2wfullv2 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: Hd2einv2 cannot be defined because the projections pgmv2, rfv2, d2eeltv2, d2efullv2 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 238, characters 2-1015: Warning: He2winv2 cannot be defined because the projections pgmv2, rfv2, e2weltv2, e2wfullv2 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: pgmv3 cannot be defined because it is informative and p3st_stalled_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: Hpgmv3 cannot be defined because the projection pgmv3 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: rfv3 cannot be defined because it is informative and p3st_stalled_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: Hrfv3 cannot be defined because the projection rfv3 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: stallv3 cannot be defined because it is informative and p3st_stalled_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: Hstallv3 cannot be defined because the projection stallv3 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: stalledv3 cannot be defined because it is informative and p3st_stalled_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: Hstalledv3 cannot be defined because the projection stalledv3 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 272, characters 2-641: Warning: Hinv3 cannot be defined because the projections pgmv3, rfv3, stallv3, stalledv3 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: pcv4 cannot be defined because it is informative and p3st_exec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: Hpcv4 cannot be defined because the projection pcv4 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: rfv4 cannot be defined because it is informative and p3st_exec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: Hrfv4 cannot be defined because the projection rfv4 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: e2weltv4 cannot be defined because it is informative and p3st_exec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: He2weltv4 cannot be defined because the projection e2weltv4 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: e2wfullv4 cannot be defined because it is informative and p3st_exec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: He2wfullv4 cannot be defined because the projection e2wfullv4 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 299, characters 2-621: Warning: Hinv4 cannot be defined because the projections pcv4, rfv4, e2wfullv4, e2weltv4 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: pcv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hpcv5 cannot be defined because the projection pcv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: fepochv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hfepochv5 cannot be defined because the projection fepochv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: d2eeltv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hd2eeltv5 cannot be defined because the projection d2eeltv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: d2efullv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hd2efullv5 cannot be defined because the projection d2efullv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: w2deltv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hw2deltv5 cannot be defined because the projection w2deltv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: w2dfullv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hw2dfullv5 cannot be defined because the projection w2dfullv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: e2weltv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: He2weltv5 cannot be defined because the projection e2weltv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: e2wfullv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: He2wfullv5 cannot be defined because the projection e2wfullv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: stallv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hstallv5 cannot be defined because the projection stallv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: stalledv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hstalledv5 cannot be defined because the projection stalledv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: eepochv5 cannot be defined because it is informative and p3st_epochs_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Heepochv5 cannot be defined because the projection eepochv5 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 340, characters 2-1704: Warning: Hinv5 cannot be defined because the projections fepochv5, eepochv5, d2efullv5, e2wfullv5, w2dfullv5, stallv5, pcv5, d2eeltv5, e2weltv5, stalledv5 were not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: pcv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hpcv6 cannot be defined because the projection pcv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: fepochv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hfepochv6 cannot be defined because the projection fepochv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: d2eeltv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hd2eeltv6 cannot be defined because the projection d2eeltv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: d2efullv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hd2efullv6 cannot be defined because the projection d2efullv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: w2dfullv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hw2dfullv6 cannot be defined because the projection w2dfullv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: e2weltv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: He2weltv6 cannot be defined because the projection e2weltv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: e2wfullv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: He2wfullv6 cannot be defined because the projection e2wfullv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: stallv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hstallv6 cannot be defined because the projection stallv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: stalledv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hstalledv6 cannot be defined because the projection stalledv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: eepochv6 cannot be defined because it is informative and p3st_pc_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Heepochv6 cannot be defined because the projection eepochv6 was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcThreeStInv.v", line 398, characters 2-1469: Warning: Hinv6 cannot be defined because the projections fepochv6, eepochv6, d2efullv6, e2wfullv6, w2dfullv6, stallv6, pcv6, d2eeltv6, e2weltv6, stalledv6 were not defined. [cannot-define-projection,records] Kami/Ex/ProcThreeStInv (real: 3.48, user: 1.44, sys: 0.25, mem: 498104 ko) File "./Kami/Ex/InDepthTutorial.v", line 680, characters 0-16: Warning: The spelling "OCaml" should be used instead of "Ocaml". [deprecated-ocaml-spelling,deprecated] Kami/Ex/InDepthTutorial (real: 47.16, user: 22.68, sys: 0.34, mem: 653084 ko) File "./Kami/Ex/ProcThreeStDec.v", line 120, characters 2-59: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcThreeStDec.v", line 121, characters 2-59: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcThreeStDec (real: 2.97, user: 1.19, sys: 0.25, mem: 495240 ko) File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: pcv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hpcv cannot be defined because the projection pcv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: rfv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hrfv cannot be defined because the projection rfv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: pgmv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hpgmv cannot be defined because the projection pgmv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: stallv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hstallv cannot be defined because the projection stallv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: iev cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hiev cannot be defined because the projection iev was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: ifv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hifv cannot be defined because the projection ifv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: ienqpv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hienqpv cannot be defined because the projection ienqpv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: ideqpv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hideqpv cannot be defined because the projection ideqpv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: ieltv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hieltv cannot be defined because the projection ieltv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: oev cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hoev cannot be defined because the projection oev was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: ofv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hofv cannot be defined because the projection ofv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: oenqpv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hoenqpv cannot be defined because the projection oenqpv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: odeqpv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hodeqpv cannot be defined because the projection odeqpv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: oeltv cannot be defined because it is informative and procDec_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hoeltv cannot be defined because the projection oeltv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcDecInv.v", line 82, characters 2-2422: Warning: Hinv cannot be defined because the projections stallv, iev, ienqpv, ideqpv, oev, oenqpv, odeqpv, stallv, iev, ienqpv, ideqpv, oev, oenqpv, odeqpv, pgmv, pcv, rfv, iev, ieltv, ideqpv, stallv, iev, ienqpv, ideqpv, oev, oenqpv, odeqpv were not defined. [cannot-define-projection,records] Kami/Ex/ProcDecInv (real: 4.24, user: 1.78, sys: 0.26, mem: 495196 ko) File "./Kami/Ex/ProcDecSC.v", line 46, characters 2-59: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcDecSC.v", line 47, characters 2-61: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcDecSC (real: 4.07, user: 0.93, sys: 0.30, mem: 493232 ko) Kami/Ex/ProcDecSCN (real: 2.30, user: 0.81, sys: 0.29, mem: 488468 ko) Kami/Ex/ProcFDInl (real: 81.62, user: 68.57, sys: 0.68, mem: 1312068 ko) File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: pcv cannot be defined because it is informative and fetchDecode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hpcv cannot be defined because the projection pcv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: pgmv cannot be defined because it is informative and fetchDecode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hpgmv cannot be defined because the projection pgmv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: fepochv cannot be defined because it is informative and fetchDecode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hfepochv cannot be defined because the projection fepochv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: f2dfullv cannot be defined because it is informative and fetchDecode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hf2dfullv cannot be defined because the projection f2dfullv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: f2deltv cannot be defined because it is informative and fetchDecode_inv is not. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hf2deltv cannot be defined because the projection f2deltv was not defined. [cannot-define-projection,records] File "./Kami/Ex/ProcFDInv.v", line 103, characters 2-743: Warning: Hinv cannot be defined because the projections pcv, pgmv, fepochv, f2dfullv, f2deltv were not defined. [cannot-define-projection,records] Kami/Ex/ProcFDInv (real: 2.76, user: 2.42, sys: 0.23, mem: 526316 ko) File "./Kami/Ex/ProcFDCorrect.v", line 96, characters 2-73: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] File "./Kami/Ex/ProcFDCorrect.v", line 97, characters 2-75: Warning: Adding and removing hints in the core database implicitly is deprecated. Please specify a hint database. [implicit-core-hint-db,deprecated] Kami/Ex/ProcFDCorrect (real: 1.11, user: 0.83, sys: 0.23, mem: 526908 ko) Kami/Ex/ProcFourStDec (real: 1.06, user: 0.80, sys: 0.23, mem: 527136 ko) Warning: bedrock2/deps/coqutil/src (used in -R or -Q) is not a subdirectory of the current directory bedrock2/processor/src/KamiWord (real: 1.30, user: 0.45, sys: 0.16, mem: 358800 ko) bedrock2/processor/src/Test (real: 3.56, user: 1.51, sys: 0.22, mem: 473632 ko) bedrock2/processor/src/KamiRiscv (real: 27.54, user: 25.47, sys: 0.35, mem: 729768 ko) vp ] md) -> (ma ++ mc)%kami <<=[ vp ] (mb ++ md)%kami simpleFifo : string -> nat -> Kind -> Modules = Mod [("data" :: RegInitDefault (SyntaxKind (Bit dataSize)))%struct; ("elt.fifo1" :: RegInitCustom (existT ConstFullT (list (word dataSize)) #< (nil)%kami_expr (NativeConst nil nil)))%struct] [("produce" :: (fun type : Kind -> Type => (Read a : Bit dataSize <- "data"; LET a0 : Bit dataSize <- # (a); Read a1 <- "elt.fifo1"; Write "elt.fifo1" <- Var type (list (type (Bit dataSize))) #< (nil) ((fix app (l m : list (type (Bit dataSize))) {struct l} : list (type (Bit dataSize)) := match l with | nil => m | a2 :: l1 => a2 :: app l1 m end) a1 [a0]); LET _ : Void <- $$ (WO); Write "data" : Bit dataSize <- # (a) + $$ ($ (1)); Ret $$ (WO))%kami_action))%struct; ("doDouble" :: (fun type : Kind -> Type => (LET _ : Void <- $$ (WO); Read a0 <- "elt.fifo1"; Assert ! $$ (match a0 with | nil => true | _ :: _ => false end); Write "elt.fifo1" <- Var type (list (type (Bit dataSize))) #< (nil) match a0 with | nil => nil | _ :: t => t end; LET ak : Bit dataSize <- match a0 with | nil => $$ (getDefaultConstBit dataSize) | h :: _ => # (h) end; LET a1 : Bit dataSize <- $$ ($ (2)) * # (ak); CallM _ : Void <- "enq.fifo2" (# (a1) : Bit dataSize); Ret $$ (WO))%kami_action))%struct] nil : Modules ROCQ compile Kami/Ex/IsaRv32PgmExt.v ROCQ compile Kami/Ex/ProcThreeStInv.v ROCQ compile Kami/Ex/ProcFDInl.v impl = fun dataSize : nat => (stage1 dataSize ++ fifo1 dataSize ++ stage2 dataSize ++ fifo2 dataSize ++ stage3 dataSize)%kami : nat -> Modules Argument scope is [nat_scope] ROCQ compile Kami/Ex/ProcThreeStDec.v ROCQ compile Kami/Ex/ProcDecInv.v ROCQ compile Kami/Ex/ProcDecSC.v ROCQ compile Kami/Ex/ProcDecSCN.v ROCQ compile Kami/Ex/ProcFDInv.v ROCQ compile Kami/Ex/ProcFDCorrect.v ROCQ compile Kami/Ex/ProcFourStDec.v make[3]: Leaving directory 'bedrock2/deps/kami' make[2]: Leaving directory 'bedrock2/deps/kami' make -C bedrock2/processor make[2]: Entering directory 'bedrock2/processor' printf -- '-Q bedrock2/deps/coqutil/src coqutil\n-Q bedrock2/deps/riscv-coq/src riscv\n-R bedrock2/deps/kami/Kami/ Kami\n-Q ./src processor\n' > _CoqProject /builds/coq/coq/_install_ci/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = bedrock2 -arg "-async-proofs-tac-j 1" bedrock2/processor/src/Test.v bedrock2/processor/src/KamiWord.v bedrock2/processor/src/KamiRiscv.v -o Makefile.coq.all make -f Makefile.coq.all make[3]: Entering directory 'bedrock2/processor' ROCQ DEP VFILES ROCQ compile bedrock2/processor/src/Test.v ROCQ compile bedrock2/processor/src/KamiWord.v ROCQ compile bedrock2/processor/src/KamiRiscv.v make[3]: Leaving directory 'bedrock2/processor' make[2]: Leaving directory 'bedrock2/processor' make[1]: Leaving directory 'bedrock2' rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/000077500000000000000000000000001516144147600237275ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo-real.v.timing.diff.expected000066400000000000000000000060741516144147600316260ustar00rootroot00000000000000 After | Before || Change | % Change | Code ----------------------------------------------------------------------------------------------------------- 0m01.24s | 0m01.28s || -0m00.04s | -3.50% | Total ----------------------------------------------------------------------------------------------------------- 0m00.53s | 0m00.566s || -0m00.04s | -6.36% | Chars 260-284 ~ 280-304 [(vm_compute;~reflexivity).] 0m00.4s | 0m00.411s || -0m00.01s | -2.67% | Chars 285-289 ~ 305-309 [Qed.] 0m00.194s | 0m00.192s || +0m00.00s | +1.04% | Chars 031-064 ~ 031-064 [Require~Import~Coq.ZArith.ZArith.] 0m00.114s | 0m00.114s || +0m00.00s | +0.00% | Chars 000-030 ~ 000-030 [Require~Import~Coq.Lists.List.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 065-075 ~ 065-075 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 078-086 ~ 078-086 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 078-090 ~ 078-090 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 087-091 ~ 091-095 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 092-102 ~ 096-106 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 105-113 ~ 109-117 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 105-117 ~ 109-121 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 114-118 ~ 122-126 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 119-129 ~ 127-137 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 132-140 ~ 140-148 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 132-144 ~ 140-152 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 141-145 ~ 153-157 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 146-156 ~ 158-168 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 159-167 ~ 171-179 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 159-171 ~ 171-183 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 168-172 ~ 184-188 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 173-183 ~ 189-199 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 186-194 ~ 202-210 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 186-198 ~ 202-214 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 195-199 ~ 215-219 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 200-257 ~ 220-277 [Goal~_~List.repeat~Z.div_eucl~...] rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo-user.v.timing.diff.expected000066400000000000000000000060761516144147600316630ustar00rootroot00000000000000 After | Before || Change | % Change | Code ----------------------------------------------------------------------------------------------------------- 0m01.15s | 0m01.16s || -0m00.01s | -0.77% | Total ----------------------------------------------------------------------------------------------------------- 0m00.504s | 0m00.528s || -0m00.02s | -4.54% | Chars 260-284 ~ 280-304 [(vm_compute;~reflexivity).] 0m00.384s | 0m00.4s || -0m00.02s | -4.00% | Chars 285-289 ~ 305-309 [Qed.] 0m00.172s | 0m00.156s || +0m00.02s | +10.25% | Chars 031-064 ~ 031-064 [Require~Import~Coq.ZArith.ZArith.] 0m00.083s | 0m00.072s || +0m00.01s | +15.27% | Chars 000-030 ~ 000-030 [Require~Import~Coq.Lists.List.] 0m00.004s | 0m00.s || +0m00.00s | ∞ | Chars 200-257 ~ 220-277 [Goal~_~List.repeat~Z.div_eucl~...] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 065-075 ~ 065-075 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 078-086 ~ 078-086 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 078-090 ~ 078-090 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 087-091 ~ 091-095 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 092-102 ~ 096-106 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 105-113 ~ 109-117 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 105-117 ~ 109-121 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 114-118 ~ 122-126 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 119-129 ~ 127-137 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 132-140 ~ 140-148 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 132-144 ~ 140-152 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 141-145 ~ 153-157 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 146-156 ~ 158-168 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 159-167 ~ 171-179 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 159-171 ~ 171-183 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 168-172 ~ 184-188 [Qed.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 173-183 ~ 189-199 [Goal~_~True.] 0m00.s | N/A || +0m00.00s | N/A | Chars 186-194 ~ 202-210 [exact~I.] N/A | 0m00.s || +0m00.00s | N/A | Chars 186-198 ~ 202-214 [constructor.] 0m00.s | 0m00.s || +0m00.00s | N/A | Chars 195-199 ~ 215-219 [Qed.] rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo.v.after-timing.in000066400000000000000000000017621516144147600277010ustar00rootroot00000000000000Chars 0 - 30 [Require~Import~Coq.Lists.List.] 0.114 secs (0.083u,0.032s) Chars 31 - 64 [Require~Import~Coq.ZArith.ZArith.] 0.194 secs (0.172u,0.023s) Chars 65 - 75 [Goal~_~True.] 0. secs (0.u,0.s) Chars 78 - 86 [exact~I.] 0. secs (0.u,0.s) Chars 87 - 91 [Qed.] 0. secs (0.u,0.s) Chars 92 - 102 [Goal~_~True.] 0. secs (0.u,0.s) Chars 105 - 113 [exact~I.] 0. secs (0.u,0.s) Chars 114 - 118 [Qed.] 0. secs (0.u,0.s) Chars 119 - 129 [Goal~_~True.] 0. secs (0.u,0.s) Chars 132 - 140 [exact~I.] 0. secs (0.u,0.s) Chars 141 - 145 [Qed.] 0. secs (0.u,0.s) Chars 146 - 156 [Goal~_~True.] 0. secs (0.u,0.s) Chars 159 - 167 [exact~I.] 0. secs (0.u,0.s) Chars 168 - 172 [Qed.] 0. secs (0.u,0.s) Chars 173 - 183 [Goal~_~True.] 0. secs (0.u,0.s) Chars 186 - 194 [exact~I.] 0. secs (0.u,0.s) Chars 195 - 199 [Qed.] 0. secs (0.u,0.s) Chars 200 - 257 [Goal~_~List.repeat~Z.div_eucl~...] 0. secs (0.004u,0.s) Chars 260 - 284 [(vm_compute;~reflexivity).] 0.53 secs (0.504u,0.024s) Chars 285 - 289 [Qed.] 0.4 secs (0.384u,0.016s) rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo.v.before-timing.in000066400000000000000000000020071516144147600300330ustar00rootroot00000000000000Chars 0 - 30 [Require~Import~Coq.Lists.List.] 0.114 secs (0.072u,0.044s) Chars 31 - 64 [Require~Import~Coq.ZArith.ZArith.] 0.192 secs (0.156u,0.035s) Chars 65 - 75 [Goal~_~True.] 0. secs (0.u,0.s) Chars 78 - 90 [constructor.] 0. secs (0.u,0.s) Chars 91 - 95 [Qed.] 0. secs (0.u,0.s) Chars 96 - 106 [Goal~_~True.] 0. secs (0.u,0.s) Chars 109 - 121 [constructor.] 0. secs (0.u,0.s) Chars 122 - 126 [Qed.] 0. secs (0.u,0.s) Chars 127 - 137 [Goal~_~True.] 0. secs (0.u,0.s) Chars 140 - 152 [constructor.] 0. secs (0.u,0.004s) Chars 153 - 157 [Qed.] 0. secs (0.u,0.s) Chars 158 - 168 [Goal~_~True.] 0. secs (0.u,0.s) Chars 171 - 183 [constructor.] 0. secs (0.u,0.s) Chars 184 - 188 [Qed.] 0. secs (0.u,0.s) Chars 189 - 199 [Goal~_~True.] 0. secs (0.u,0.s) Chars 202 - 214 [constructor.] 0. secs (0.u,0.s) Chars 215 - 219 [Qed.] 0. secs (0.u,0.s) Chars 220 - 277 [Goal~_~List.repeat~Z.div_eucl~...] 0. secs (0.u,0.s) Chars 280 - 304 [(vm_compute;~reflexivity).] 0.566 secs (0.528u,0.039s) Chars 305 - 309 [Qed.] 0.411 secs (0.4u,0.008s) rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo_after.v000066400000000000000000000004521516144147600260630ustar00rootroot00000000000000Require Import Corelib.Lists.List. Require Import Corelib.ZArith.ZArith. Goal True. exact I. Qed. Goal True. exact I. Qed. Goal True. exact I. Qed. Goal True. exact I. Qed. Goal True. exact I. Qed. Goal List.repeat Z.div_eucl 5 = List.repeat Z.div_eucl 5. vm_compute; reflexivity. Qed. rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/foo_before.v000066400000000000000000000004761516144147600262320ustar00rootroot00000000000000Require Import Corelib.Lists.List. Require Import Corelib.ZArith.ZArith. Goal True. constructor. Qed. Goal True. constructor. Qed. Goal True. constructor. Qed. Goal True. constructor. Qed. Goal True. constructor. Qed. Goal List.repeat Z.div_eucl 5 = List.repeat Z.div_eucl 5. vm_compute; reflexivity. Qed. rocq-9.2.0/test-suite/precomputed-time-tests/per-file-fuzz/run.sh000077500000000000000000000007371516144147600251010ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_both_single_timing_files --fuzz=20 foo.v.after-timing.in foo.v.before-timing.in foo-real.v.timing.diff || exit $? diff -u foo-real.v.timing.diff.expected foo-real.v.timing.diff || exit $? $make_both_single_timing_files --fuzz=20 --user foo.v.after-timing.in foo.v.before-timing.in foo-user.v.timing.diff || exit $? diff -u foo-user.v.timing.diff.expected foo-user.v.timing.diff || exit $? rocq-9.2.0/test-suite/precomputed-time-tests/single-file-sorting/000077500000000000000000000000001516144147600251115ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/single-file-sorting/run.sh000077500000000000000000000006221516144147600262540ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_one_time_file time-of-build.log.in time-of-build-pretty-user.log diff -u time-of-build-pretty-user.log.expected time-of-build-pretty-user.log || exit $? $make_one_time_file time-of-build.log.in time-of-build-pretty-real.log diff -u time-of-build-pretty-real.log.expected time-of-build-pretty-real.log || exit $? time-of-build-pretty-real.log.expected000066400000000000000000000035201516144147600342400ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/single-file-sorting Time | Peak Mem | File Name ----------------------------------------------------------------------- 19m16.05s | 3302508 ko | Total Time / Peak Mem ----------------------------------------------------------------------- 4m01.34s | 1617000 ko | Specific/X25519/C64/ladderstep 3m09.62s | 3302508 ko | Specific/NISTP256/AMD64/femul 2m48.52s | 1589516 ko | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | Specific/solinas32_2e255m765_12limbs/femul 0m45.75s | 744240 ko | Specific/solinas32_2e255m765_13limbs/Synthesis 0m39.59s | 793376 ko | Specific/NISTP256/AMD64/fesub 0m36.92s | 728464 ko | Specific/solinas32_2e255m765_12limbs/Synthesis 0m36.32s | 825448 ko | Specific/X25519/C64/femul 0m35.40s | 799216 ko | Specific/NISTP256/AMD64/feadd 0m31.50s | 828104 ko | Specific/X25519/C64/freeze 0m30.13s | 799620 ko | Specific/X25519/C64/fesquare 0m28.51s | 765208 ko | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | Specific/NISTP256/AMD64/fenz 0m24.99s | 786052 ko | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | Specific/X25519/C64/fesub 0m20.93s | 766300 ko | Specific/X25519/C64/feadd 0m12.55s | 668216 ko | Specific/NISTP256/AMD64/Synthesis 0m10.37s | 687760 ko | Specific/X25519/C64/Synthesis 0m07.18s | 574388 ko | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | Specific/Framework/SynthesisFramework 0m01.19s | 539808 ko | Compilers/Z/Bounds/Pipeline time-of-build-pretty-user.log.expected000066400000000000000000000035201516144147600342730ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/single-file-sorting Time | Peak Mem | File Name ----------------------------------------------------------------------- 19m16.05s | 3302508 ko | Total Time / Peak Mem ----------------------------------------------------------------------- 4m01.34s | 1617000 ko | Specific/X25519/C64/ladderstep 3m09.62s | 3302508 ko | Specific/NISTP256/AMD64/femul 2m48.52s | 1589516 ko | Specific/solinas32_2e255m765_13limbs/femul 2m23.70s | 1454696 ko | Specific/solinas32_2e255m765_12limbs/femul 0m45.75s | 744240 ko | Specific/solinas32_2e255m765_13limbs/Synthesis 0m39.59s | 793376 ko | Specific/NISTP256/AMD64/fesub 0m36.92s | 728464 ko | Specific/solinas32_2e255m765_12limbs/Synthesis 0m36.32s | 825448 ko | Specific/X25519/C64/femul 0m35.40s | 799216 ko | Specific/NISTP256/AMD64/feadd 0m31.50s | 828104 ko | Specific/X25519/C64/freeze 0m30.13s | 799620 ko | Specific/X25519/C64/fesquare 0m28.51s | 765208 ko | Specific/NISTP256/AMD64/feopp 0m25.50s | 756080 ko | Specific/NISTP256/AMD64/fenz 0m24.99s | 786052 ko | Specific/X25519/C64/fecarry 0m22.65s | 778792 ko | Specific/X25519/C64/fesub 0m20.93s | 766300 ko | Specific/X25519/C64/feadd 0m12.55s | 668216 ko | Specific/NISTP256/AMD64/Synthesis 0m10.37s | 687760 ko | Specific/X25519/C64/Synthesis 0m07.18s | 574388 ko | Compilers/Z/Bounds/Pipeline/Definition 0m01.72s | 544172 ko | Compilers/Z/Bounds/Pipeline/ReflectiveTactics 0m01.67s | 646300 ko | Specific/Framework/SynthesisFramework 0m01.19s | 539808 ko | Compilers/Z/Bounds/Pipeline rocq-9.2.0/test-suite/precomputed-time-tests/single-file-sorting/time-of-build.log.in000066400000000000000000004053341516144147600306670ustar00rootroot00000000000000COQDEP src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v COQDEP src/Compilers/Z/Bounds/Pipeline/Definition.v /home/jgross/.local64/coq/coq-master/bin/rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-old COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C coqprime make[1]: Nothing to be done for 'all'. ECHO > _CoqProject ROCQ compile src/Compilers/Z/Bounds/Pipeline/Definition.v src/Compilers/Z/Bounds/Pipeline/Definition (real: 7.33, user: 7.18, sys: 0.14, mem: 574388 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics.v src/Compilers/Z/Bounds/Pipeline/ReflectiveTactics (real: 1.93, user: 1.72, sys: 0.20, mem: 544172 ko) ROCQ compile src/Compilers/Z/Bounds/Pipeline.v src/Compilers/Z/Bounds/Pipeline (real: 1.38, user: 1.19, sys: 0.16, mem: 539808 ko) ROCQ compile src/Specific/Framework/SynthesisFramework.v src/Specific/Framework/SynthesisFramework (real: 1.85, user: 1.67, sys: 0.17, mem: 646300 ko) ROCQ compile src/Specific/X25519/C64/Synthesis.v src/Specific/X25519/C64/Synthesis (real: 11.15, user: 10.37, sys: 0.18, mem: 687760 ko) ROCQ compile src/Specific/NISTP256/AMD64/Synthesis.v src/Specific/NISTP256/AMD64/Synthesis (real: 13.45, user: 12.55, sys: 0.19, mem: 668216 ko) ROCQ compile src/Specific/X25519/C64/feadd.v Finished transaction in 2.814 secs (2.624u,0.s) (successful) total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s Finished transaction in 5.021 secs (4.636u,0.s) (successful) Closed under the global context total time: 2.576s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s ─ReflectiveTactics.do_reflective_pipelin 0.0% 66.9% 1 1.724s ─ReflectiveTactics.solve_side_conditions 0.0% 65.5% 1 1.688s ─ReflectiveTactics.solve_post_reified_si 1.2% 37.0% 1 0.952s ─Glue.refine_to_reflective_glue' ------- 0.0% 30.3% 1 0.780s ─ReflectiveTactics.do_reify ------------ 0.0% 28.6% 1 0.736s ─Reify.Reify_rhs_gen ------------------- 2.2% 26.6% 1 0.684s ─UnifyAbstractReflexivity.unify_transfor 20.3% 24.1% 7 0.164s ─Glue.zrange_to_reflective ------------- 0.0% 20.3% 1 0.524s ─Glue.zrange_to_reflective_goal -------- 9.5% 15.2% 1 0.392s ─Reify.do_reify_abs_goal --------------- 13.7% 13.8% 2 0.356s ─Reify.do_reifyf_goal ------------------ 12.4% 12.6% 16 0.324s ─ReflectiveTactics.unify_abstract_cbv_in 8.4% 11.2% 1 0.288s ─unify (constr) (constr) --------------- 5.7% 5.7% 6 0.072s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 5.4% 1 0.140s ─assert (H : is_bounded_by' bounds (map' 4.8% 5.1% 2 0.072s ─Glue.pattern_proj1_sig_in_sig --------- 1.7% 5.1% 1 0.132s ─pose proof (pf : Interpretation.Bo 3.7% 3.7% 1 0.096s ─Glue.split_BoundedWordToZ ------------- 0.3% 3.7% 1 0.096s ─destruct_sig -------------------------- 0.2% 3.3% 4 0.044s ─destruct x ---------------------------- 3.1% 3.1% 4 0.036s ─eexact -------------------------------- 3.0% 3.0% 18 0.008s ─clearbody (ne_var_list) --------------- 3.0% 3.0% 4 0.060s ─prove_interp_compile_correct ---------- 0.0% 2.8% 1 0.072s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s ─rewrite ?EtaInterp.InterpExprEta ------ 2.5% 2.5% 1 0.064s ─ClearbodyAll.clearbody_all ------------ 0.0% 2.3% 2 0.060s ─rewrite H ----------------------------- 2.2% 2.2% 1 0.056s ─reflexivity --------------------------- 2.2% 2.2% 7 0.032s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.032s ─transitivity -------------------------- 2.0% 2.0% 5 0.024s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.2% 97.4% 1 2.508s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 66.9% 1 1.724s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 65.5% 1 1.688s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 1.2% 37.0% 1 0.952s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 20.3% 24.1% 7 0.164s β”‚ β”‚ β”‚β””unify (constr) (constr) --------- 3.0% 3.0% 5 0.028s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 8.4% 11.2% 1 0.288s β”‚ β”‚ β””unify (constr) (constr) --------- 2.8% 2.8% 1 0.072s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 28.6% 1 0.736s β”‚ β””Reify.Reify_rhs_gen --------------- 2.2% 26.6% 1 0.684s β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 13.7% 13.8% 2 0.356s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 12.4% 12.6% 16 0.324s β”‚ β”‚β””eexact -------------------------- 2.6% 2.6% 16 0.008s β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.8% 1 0.072s β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 2.5% 2.5% 1 0.064s β”‚ β”œβ”€rewrite H ----------------------- 2.2% 2.2% 1 0.056s β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.032s └─Glue.refine_to_reflective_glue' ----- 0.0% 30.3% 1 0.780s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 20.3% 1 0.524s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 9.5% 15.2% 1 0.392s β”‚ β”‚β””pose proof (pf : Interpretat 3.7% 3.7% 1 0.096s β”‚ └─assert (H : is_bounded_by' bounds 4.8% 5.1% 2 0.072s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 5.4% 1 0.140s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.7% 5.1% 1 0.132s β”‚β””ClearbodyAll.clearbody_all -------- 0.0% 2.3% 2 0.060s β”‚β””clearbody (ne_var_list) ----------- 2.3% 2.3% 1 0.060s └─Glue.split_BoundedWordToZ --------- 0.3% 3.7% 1 0.096s β””destruct_sig ---------------------- 0.2% 3.3% 4 0.044s β””destruct x ------------------------ 2.5% 2.5% 2 0.036s ─synthesize ---------------------------- 0.0% 2.6% 1 0.068s src/Specific/X25519/C64/feadd (real: 22.81, user: 20.93, sys: 0.25, mem: 766300 ko) ROCQ compile src/Specific/X25519/C64/fecarry.v Finished transaction in 4.343 secs (4.016u,0.004s) (successful) total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s Finished transaction in 7.078 secs (6.728u,0.s) (successful) Closed under the global context total time: 3.976s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.9% 1 3.496s ─ReflectiveTactics.solve_side_conditions 0.0% 86.9% 1 3.456s ─ReflectiveTactics.do_reify ------------ 0.0% 56.9% 1 2.264s ─Reify.Reify_rhs_gen ------------------- 1.8% 56.2% 1 2.236s ─Reify.do_reify_abs_goal --------------- 36.1% 36.5% 2 1.452s ─Reify.do_reifyf_goal ------------------ 34.8% 35.1% 29 1.396s ─ReflectiveTactics.solve_post_reified_si 0.6% 30.0% 1 1.192s ─UnifyAbstractReflexivity.unify_transfor 17.7% 21.7% 7 0.240s ─Glue.refine_to_reflective_glue' ------- 0.0% 11.1% 1 0.440s ─eexact -------------------------------- 10.9% 10.9% 31 0.024s ─ReflectiveTactics.unify_abstract_cbv_in 5.2% 7.3% 1 0.292s ─Glue.zrange_to_reflective ------------- 0.0% 7.1% 1 0.284s ─prove_interp_compile_correct ---------- 0.0% 5.7% 1 0.228s ─Glue.zrange_to_reflective_goal -------- 4.3% 5.5% 1 0.220s ─unify (constr) (constr) --------------- 5.3% 5.3% 6 0.084s ─rewrite ?EtaInterp.InterpExprEta ------ 5.2% 5.2% 1 0.208s ─rewrite H ----------------------------- 3.5% 3.5% 1 0.140s ─tac ----------------------------------- 1.9% 2.6% 2 0.104s ─reflexivity --------------------------- 2.2% 2.2% 7 0.028s ─Reify.transitivity_tt ----------------- 0.0% 2.2% 2 0.056s ─transitivity -------------------------- 2.0% 2.0% 5 0.048s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.0% 1 0.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 99.0% 1 3.936s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.9% 1 3.496s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.9% 1 3.456s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 56.9% 1 2.264s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 56.2% 1 2.236s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 36.1% 36.5% 2 1.452s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 34.8% 35.1% 29 1.396s β”‚ β”‚ β”‚β””eexact -------------------------- 10.1% 10.1% 29 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.7% 1 0.228s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.2% 5.2% 1 0.208s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.5% 3.5% 1 0.140s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.6% 1 0.104s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.2% 2 0.056s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.048s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 30.0% 1 1.192s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 17.7% 21.7% 7 0.240s β”‚ β”‚β””unify (constr) (constr) --------- 3.2% 3.2% 5 0.048s β”‚ └─ReflectiveTactics.unify_abstract_ 5.2% 7.3% 1 0.292s β”‚ β””unify (constr) (constr) --------- 2.1% 2.1% 1 0.084s └─Glue.refine_to_reflective_glue' ----- 0.0% 11.1% 1 0.440s β”œβ”€Glue.zrange_to_reflective --------- 0.0% 7.1% 1 0.284s β”‚β””Glue.zrange_to_reflective_goal ---- 4.3% 5.5% 1 0.220s └─Glue.split_BoundedWordToZ --------- 0.1% 2.0% 1 0.080s src/Specific/X25519/C64/fecarry (real: 27.11, user: 24.99, sys: 0.21, mem: 786052 ko) ROCQ compile src/Specific/solinas32_2e255m765_12limbs/Synthesis.v src/Specific/solinas32_2e255m765_12limbs/Synthesis (real: 40.13, user: 36.92, sys: 0.26, mem: 728464 ko) ROCQ compile src/Specific/solinas32_2e255m765_13limbs/Synthesis.v src/Specific/solinas32_2e255m765_13limbs/Synthesis (real: 49.44, user: 45.75, sys: 0.18, mem: 744240 ko) ROCQ compile src/Specific/X25519/C64/femul.v Finished transaction in 8.415 secs (7.664u,0.015s) (successful) total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s Finished transaction in 14.616 secs (13.528u,0.008s) (successful) Closed under the global context total time: 7.616s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s ─ReflectiveTactics.do_reflective_pipelin 0.0% 85.0% 1 6.476s ─ReflectiveTactics.solve_side_conditions 0.0% 84.2% 1 6.416s ─ReflectiveTactics.do_reify ------------ 0.0% 50.3% 1 3.832s ─Reify.Reify_rhs_gen ------------------- 1.8% 49.4% 1 3.760s ─ReflectiveTactics.solve_post_reified_si 0.5% 33.9% 1 2.584s ─Reify.do_reify_abs_goal --------------- 31.1% 31.4% 2 2.392s ─Reify.do_reifyf_goal ------------------ 30.0% 30.3% 58 1.528s ─UnifyAbstractReflexivity.unify_transfor 22.1% 27.3% 7 0.600s ─Glue.refine_to_reflective_glue' ------- 0.0% 9.8% 1 0.744s ─eexact -------------------------------- 8.2% 8.2% 60 0.024s ─Glue.zrange_to_reflective ------------- 0.1% 6.8% 1 0.516s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.124s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.444s ─ReflectiveTactics.unify_abstract_cbv_in 3.9% 5.7% 1 0.432s ─rewrite ?EtaInterp.InterpExprEta ------ 5.4% 5.4% 1 0.408s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s ─Glue.zrange_to_reflective_goal -------- 3.0% 5.0% 1 0.384s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s ─change G' ----------------------------- 3.9% 3.9% 1 0.300s ─rewrite H ----------------------------- 3.0% 3.0% 1 0.232s ─tac ----------------------------------- 1.5% 2.3% 2 0.176s ─Reify.transitivity_tt ----------------- 0.0% 2.1% 2 0.092s ─reflexivity --------------------------- 2.0% 2.0% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.8% 1 7.220s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 85.0% 1 6.476s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 84.2% 1 6.416s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 50.3% 1 3.832s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.8% 49.4% 1 3.760s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 31.1% 31.4% 2 2.392s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 30.0% 30.3% 58 1.528s β”‚ β”‚ β”‚β””eexact -------------------------- 7.6% 7.6% 58 0.020s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.8% 1 0.444s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 5.4% 5.4% 1 0.408s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.0% 3.0% 1 0.232s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.5% 2.3% 1 0.176s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.0% 2.1% 2 0.092s β”‚ └─ReflectiveTactics.solve_post_reifie 0.5% 33.9% 1 2.584s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 22.1% 27.3% 7 0.600s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 0.096s β”‚ └─ReflectiveTactics.unify_abstract_ 3.9% 5.7% 1 0.432s └─Glue.refine_to_reflective_glue' ----- 0.0% 9.8% 1 0.744s β””Glue.zrange_to_reflective ----------- 0.1% 6.8% 1 0.516s β””Glue.zrange_to_reflective_goal ------ 3.0% 5.0% 1 0.384s ─synthesize ---------------------------- 0.0% 5.2% 1 0.396s β””IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.8% 1 0.364s β””change G' ----------------------------- 3.9% 3.9% 1 0.300s src/Specific/X25519/C64/femul (real: 39.72, user: 36.32, sys: 0.26, mem: 825448 ko) ROCQ compile src/Specific/X25519/C64/feaddDisplay > src/Specific/X25519/C64/feaddDisplay.log ROCQ compile src/Specific/X25519/C64/fecarryDisplay > src/Specific/X25519/C64/fecarryDisplay.log ROCQ compile src/Specific/X25519/C64/fesub.v Finished transaction in 3.513 secs (3.211u,0.s) (successful) total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s Finished transaction in 6.12 secs (5.64u,0.008s) (successful) Closed under the global context total time: 3.164s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s ─ReflectiveTactics.do_reflective_pipelin 0.0% 74.1% 1 2.344s ─ReflectiveTactics.solve_side_conditions 0.0% 72.9% 1 2.308s ─ReflectiveTactics.do_reify ------------ 0.0% 38.6% 1 1.220s ─Reify.Reify_rhs_gen ------------------- 1.5% 37.2% 1 1.176s ─ReflectiveTactics.solve_post_reified_si 0.9% 34.4% 1 1.088s ─UnifyAbstractReflexivity.unify_transfor 19.2% 23.9% 7 0.204s ─Glue.refine_to_reflective_glue' ------- 0.0% 23.5% 1 0.744s ─Reify.do_reify_abs_goal --------------- 19.2% 19.5% 2 0.616s ─Reify.do_reifyf_goal ------------------ 18.0% 18.3% 16 0.580s ─Glue.zrange_to_reflective ------------- 0.1% 15.4% 1 0.488s ─Glue.zrange_to_reflective_goal -------- 6.8% 11.5% 1 0.364s ─ReflectiveTactics.unify_abstract_cbv_in 6.2% 9.0% 1 0.284s ─unify (constr) (constr) --------------- 5.9% 5.9% 6 0.080s ─Glue.pattern_sig_sig_assoc ------------ 0.0% 4.6% 1 0.144s ─eexact -------------------------------- 4.4% 4.4% 18 0.012s ─Glue.pattern_proj1_sig_in_sig --------- 1.4% 4.3% 1 0.136s ─prove_interp_compile_correct ---------- 0.0% 3.9% 1 0.124s ─rewrite H ----------------------------- 3.8% 3.8% 1 0.120s ─assert (H : is_bounded_by' bounds (map' 3.8% 3.8% 2 0.064s ─rewrite ?EtaInterp.InterpExprEta ------ 3.5% 3.5% 1 0.112s ─pose proof (pf : Interpretation.Bo 2.9% 2.9% 1 0.092s ─Glue.split_BoundedWordToZ ------------- 0.1% 2.8% 1 0.088s ─tac ----------------------------------- 1.9% 2.5% 2 0.080s ─reflexivity --------------------------- 2.4% 2.4% 7 0.028s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s ─destruct_sig -------------------------- 0.0% 2.4% 4 0.040s ─destruct x ---------------------------- 2.4% 2.4% 4 0.032s ─clearbody (ne_var_list) --------------- 2.3% 2.3% 4 0.060s ─Reify.transitivity_tt ----------------- 0.1% 2.3% 2 0.036s ─transitivity -------------------------- 2.1% 2.1% 5 0.032s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.6% 1 3.088s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 74.1% 1 2.344s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 72.9% 1 2.308s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 38.6% 1 1.220s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 37.2% 1 1.176s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 19.2% 19.5% 2 0.616s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 18.0% 18.3% 16 0.580s β”‚ β”‚ β”‚β””eexact -------------------------- 3.9% 3.9% 16 0.012s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.9% 1 0.124s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.5% 3.5% 1 0.112s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 0.120s β”‚ β”‚ β”œβ”€tac ----------------------------- 1.9% 2.5% 1 0.080s β”‚ β”‚ └─Reify.transitivity_tt ----------- 0.1% 2.3% 2 0.036s β”‚ β”‚ β””transitivity -------------------- 2.0% 2.0% 4 0.032s β”‚ └─ReflectiveTactics.solve_post_reifie 0.9% 34.4% 1 1.088s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.2% 23.9% 7 0.204s β”‚ β”‚β””unify (constr) (constr) --------- 3.4% 3.4% 5 0.036s β”‚ └─ReflectiveTactics.unify_abstract_ 6.2% 9.0% 1 0.284s β”‚ β””unify (constr) (constr) --------- 2.5% 2.5% 1 0.080s └─Glue.refine_to_reflective_glue' ----- 0.0% 23.5% 1 0.744s β”œβ”€Glue.zrange_to_reflective --------- 0.1% 15.4% 1 0.488s β”‚ β”œβ”€Glue.zrange_to_reflective_goal -- 6.8% 11.5% 1 0.364s β”‚ β”‚β””pose proof (pf : Interpretat 2.9% 2.9% 1 0.092s β”‚ └─assert (H : is_bounded_by' bounds 3.8% 3.8% 2 0.064s β”œβ”€Glue.pattern_sig_sig_assoc -------- 0.0% 4.6% 1 0.144s β”‚β””Glue.pattern_proj1_sig_in_sig ----- 1.4% 4.3% 1 0.136s └─Glue.split_BoundedWordToZ --------- 0.1% 2.8% 1 0.088s β””destruct_sig ---------------------- 0.0% 2.4% 4 0.040s ─synthesize ---------------------------- 0.0% 2.4% 1 0.076s src/Specific/X25519/C64/fesub (real: 24.71, user: 22.65, sys: 0.24, mem: 778792 ko) ROCQ compile src/Specific/X25519/C64/fesquare.v Finished transaction in 6.132 secs (5.516u,0.012s) (successful) total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s Finished transaction in 10.475 secs (9.728u,0.007s) (successful) Closed under the global context total time: 5.480s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s ─Pipeline.refine_reflectively_gen ------ 0.0% 95.7% 1 5.244s ─ReflectiveTactics.do_reflective_pipelin 0.0% 88.6% 1 4.856s ─ReflectiveTactics.solve_side_conditions 0.0% 87.7% 1 4.804s ─ReflectiveTactics.do_reify ------------ 0.0% 53.3% 1 2.920s ─Reify.Reify_rhs_gen ------------------- 2.0% 52.5% 1 2.876s ─ReflectiveTactics.solve_post_reified_si 0.6% 34.4% 1 1.884s ─Reify.do_reify_abs_goal --------------- 33.2% 33.6% 2 1.844s ─Reify.do_reifyf_goal ------------------ 31.5% 32.0% 47 1.392s ─UnifyAbstractReflexivity.unify_transfor 21.9% 26.6% 7 0.400s ─eexact -------------------------------- 10.0% 10.0% 49 0.028s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.1% 1 0.388s ─ReflectiveTactics.unify_abstract_cbv_in 5.0% 6.9% 1 0.380s ─unify (constr) (constr) --------------- 5.8% 5.8% 6 0.104s ─prove_interp_compile_correct ---------- 0.0% 5.8% 1 0.316s ─rewrite ?EtaInterp.InterpExprEta ------ 5.3% 5.3% 1 0.288s ─Glue.zrange_to_reflective ------------- 0.1% 5.1% 1 0.280s ─IntegrationTestTemporaryMiscCommon.do_r 0.1% 4.0% 1 0.220s ─Glue.zrange_to_reflective_goal -------- 3.1% 3.9% 1 0.212s ─change G' ----------------------------- 3.4% 3.4% 1 0.184s ─tac ----------------------------------- 2.0% 2.8% 2 0.156s ─rewrite H ----------------------------- 2.8% 2.8% 1 0.156s ─reflexivity --------------------------- 2.8% 2.8% 7 0.064s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize ---------------------------- -0.0% 100.0% 1 5.480s β”œβ”€Pipeline.refine_reflectively_gen ---- 0.0% 95.7% 1 5.244s β”‚ β”œβ”€ReflectiveTactics.do_reflective_pip 0.0% 88.6% 1 4.856s β”‚ β”‚β””ReflectiveTactics.solve_side_condit 0.0% 87.7% 1 4.804s β”‚ β”‚ β”œβ”€ReflectiveTactics.do_reify ------ 0.0% 53.3% 1 2.920s β”‚ β”‚ β”‚β””Reify.Reify_rhs_gen ------------- 2.0% 52.5% 1 2.876s β”‚ β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal ------- 33.2% 33.6% 2 1.844s β”‚ β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ---------- 31.5% 32.0% 47 1.392s β”‚ β”‚ β”‚ β”‚β””eexact ------------------------ 9.1% 9.1% 47 0.024s β”‚ β”‚ β”‚ β”œβ”€prove_interp_compile_correct -- 0.0% 5.8% 1 0.316s β”‚ β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEt 5.3% 5.3% 1 0.288s β”‚ β”‚ β”‚ β”œβ”€tac --------------------------- 2.0% 2.8% 1 0.156s β”‚ β”‚ β”‚ └─rewrite H --------------------- 2.8% 2.8% 1 0.156s β”‚ β”‚ └─ReflectiveTactics.solve_post_reif 0.6% 34.4% 1 1.884s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_ 21.9% 26.6% 7 0.400s β”‚ β”‚ β”‚β””unify (constr) (constr) ------- 3.9% 3.9% 5 0.072s β”‚ β”‚ └─ReflectiveTactics.unify_abstrac 5.0% 6.9% 1 0.380s β”‚ └─Glue.refine_to_reflective_glue' --- 0.0% 7.1% 1 0.388s β”‚ β””Glue.zrange_to_reflective --------- 0.1% 5.1% 1 0.280s β”‚ β””Glue.zrange_to_reflective_goal ---- 3.1% 3.9% 1 0.212s └─IntegrationTestTemporaryMiscCommon.do 0.1% 4.0% 1 0.220s β””change G' --------------------------- 3.4% 3.4% 1 0.184s src/Specific/X25519/C64/fesquare (real: 33.08, user: 30.13, sys: 0.24, mem: 799620 ko) ROCQ compile src/Specific/X25519/C64/femulDisplay > src/Specific/X25519/C64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/freeze.v Finished transaction in 7.307 secs (6.763u,0.011s) (successful) total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s Finished transaction in 10.495 secs (9.756u,0.s) (successful) Closed under the global context total time: 6.732s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s ─Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s ─ReflectiveTactics.do_reflective_pipelin 0.0% 92.8% 1 6.248s ─ReflectiveTactics.solve_side_conditions 0.0% 92.0% 1 6.192s ─ReflectiveTactics.do_reify ------------ -0.0% 60.3% 1 4.060s ─Reify.Reify_rhs_gen ------------------- 1.5% 59.6% 1 4.012s ─Reify.do_reify_abs_goal --------------- 42.4% 42.7% 2 2.876s ─Reify.do_reifyf_goal ------------------ 41.3% 41.7% 129 2.804s ─ReflectiveTactics.solve_post_reified_si 0.6% 31.7% 1 2.132s ─UnifyAbstractReflexivity.unify_transfor 21.7% 25.8% 7 0.424s ─eexact -------------------------------- 13.7% 13.7% 131 0.036s ─Glue.refine_to_reflective_glue' ------- 0.0% 6.5% 1 0.436s ─prove_interp_compile_correct ---------- 0.0% 5.1% 1 0.344s ─ReflectiveTactics.unify_abstract_cbv_in 3.4% 5.0% 1 0.336s ─rewrite ?EtaInterp.InterpExprEta ------ 4.7% 4.7% 1 0.316s ─unify (constr) (constr) --------------- 4.6% 4.6% 6 0.100s ─Glue.zrange_to_reflective ------------- 0.0% 4.2% 1 0.280s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 0.220s ─Reify.transitivity_tt ----------------- 0.1% 2.6% 2 0.116s ─rewrite H ----------------------------- 2.6% 2.6% 1 0.172s ─tac ----------------------------------- 1.5% 2.3% 2 0.156s ─reflexivity --------------------------- 2.3% 2.3% 7 0.052s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_freeze --------------------- 0.0% 100.0% 1 6.732s β””Pipeline.refine_reflectively_gen ------ 0.0% 99.3% 1 6.684s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 92.8% 1 6.248s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 92.0% 1 6.192s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 60.3% 1 4.060s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.5% 59.6% 1 4.012s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 42.4% 42.7% 2 2.876s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 41.3% 41.7% 129 2.804s β”‚ β”‚ β”‚β””eexact -------------------------- 13.0% 13.0% 129 0.036s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 5.1% 1 0.344s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 4.7% 4.7% 1 0.316s β”‚ β”‚ β”œβ”€Reify.transitivity_tt ----------- 0.1% 2.6% 2 0.116s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 2.6% 2.6% 1 0.172s β”‚ β”‚ └─tac ----------------------------- 1.5% 2.3% 1 0.156s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 31.7% 1 2.132s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 21.7% 25.8% 7 0.424s β”‚ β”‚β””unify (constr) (constr) --------- 3.1% 3.1% 5 0.084s β”‚ └─ReflectiveTactics.unify_abstract_ 3.4% 5.0% 1 0.336s └─Glue.refine_to_reflective_glue' ----- 0.0% 6.5% 1 0.436s β””Glue.zrange_to_reflective ----------- 0.0% 4.2% 1 0.280s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 0.220s src/Specific/X25519/C64/freeze (real: 34.35, user: 31.50, sys: 0.24, mem: 828104 ko) ROCQ compile src/Specific/NISTP256/AMD64/feadd.v Finished transaction in 8.784 secs (8.176u,0.011s) (successful) total time: 8.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s ─ReflectiveTactics.do_reflective_pipelin 0.0% 43.8% 1 3.568s ─ReflectiveTactics.solve_side_conditions 0.0% 43.2% 1 3.520s ─IntegrationTestTemporaryMiscCommon.fact 1.4% 23.6% 1 1.924s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 22.1% 1 1.796s ─ReflectiveTactics.do_reify ------------ 0.1% 21.7% 1 1.768s ─ReflectiveTactics.solve_post_reified_si 0.6% 21.5% 1 1.752s ─Reify.Reify_rhs_gen ------------------- 1.0% 20.9% 1 1.704s ─op_sig_side_conditions_t -------------- 0.0% 20.0% 1 1.624s ─DestructHyps.do_all_matches_then ------ 0.0% 20.0% 8 0.244s ─DestructHyps.do_one_match_then -------- 0.7% 19.9% 44 0.052s ─do_tac -------------------------------- 0.0% 19.2% 36 0.052s ─destruct H ---------------------------- 19.2% 19.2% 36 0.052s ─rewrite <- (lem : lemT) by by_tac ltac: 0.2% 17.3% 1 1.408s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 17.3% 1 1.408s ─by_tac -------------------------------- 0.0% 17.1% 4 0.504s ─rewrite <- (ZRange.is_bounded_by_None_r 16.7% 16.7% 8 0.344s ─UnifyAbstractReflexivity.unify_transfor 13.3% 16.1% 7 0.360s ─Reify.do_reify_abs_goal --------------- 9.9% 10.1% 2 0.820s ─Reify.do_reifyf_goal ------------------ 9.1% 9.3% 93 0.748s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.6% 1 0.700s ─Glue.zrange_to_reflective ------------- 0.0% 5.3% 1 0.432s ─IntegrationTestTemporaryMiscCommon.do_s 0.0% 4.8% 1 0.388s ─ MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” MapProjections.proj2 2.4% 2.4% 2 0.120s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 52.4% 1 4.268s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 43.8% 1 3.568s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 43.2% 1 3.520s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.1% 21.7% 1 1.768s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.0% 20.9% 1 1.704s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 9.9% 10.1% 2 0.820s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.1% 9.3% 93 0.748s β”‚ β”‚ β”‚β””eexact -------------------------- 2.3% 2.3% 93 0.024s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 2.5% 1 0.204s β”‚ β”‚ └─rewrite H ----------------------- 2.4% 2.4% 1 0.196s β”‚ └─ReflectiveTactics.solve_post_reifie 0.6% 21.5% 1 1.752s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 13.3% 16.1% 7 0.360s β”‚ β”‚β””unify (constr) (constr) --------- 2.2% 2.2% 5 0.064s β”‚ └─ReflectiveTactics.unify_abstract_ 3.3% 4.5% 1 0.368s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.6% 1 0.700s β””Glue.zrange_to_reflective ----------- 0.0% 5.3% 1 0.432s β””Glue.zrange_to_reflective_goal ------ 2.6% 4.0% 1 0.324s ─synthesize_montgomery ----------------- 0.0% 47.6% 1 3.872s β”œβ”€IntegrationTestTemporaryMiscCommon.fa 1.4% 23.6% 1 1.924s β”‚β””op_sig_side_conditions_t ------------ 0.0% 20.0% 1 1.624s β”‚ β”œβ”€DestructHyps.do_all_matches_then -- 0.0% 11.4% 4 0.244s β”‚ β”‚β””DestructHyps.do_one_match_then ---- 0.3% 11.4% 24 0.052s β”‚ β”‚β””do_tac ---------------------------- 0.0% 11.1% 20 0.052s β”‚ β”‚β””destruct H ------------------------ 11.1% 11.1% 20 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_No 8.4% 8.4% 4 0.328s └─IntegrationTestTemporaryMiscCommon.do 0.0% 22.1% 1 1.796s β”œβ”€IntegrationTestTemporaryMiscCommon. 0.0% 17.3% 1 1.408s β”‚β””rewrite <- (lem : lemT) by by_tac l 0.2% 17.3% 1 1.408s β”‚β””by_tac ---------------------------- 0.0% 17.1% 4 0.504s β”‚ β”œβ”€DestructHyps.do_all_matches_then 0.0% 8.6% 4 0.184s β”‚ β”‚β””DestructHyps.do_one_match_then -- 0.3% 8.5% 20 0.052s β”‚ β”‚β””do_tac -------------------------- 0.0% 8.2% 16 0.052s β”‚ β”‚β””destruct H ---------------------- 8.2% 8.2% 16 0.052s β”‚ └─rewrite <- (ZRange.is_bounded_by_ 8.3% 8.3% 4 0.344s └─IntegrationTestTemporaryMiscCommon. 0.0% 4.8% 1 0.388s β”” src/Specific/NISTP256/AMD64/feaddDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fenzDisplay > src/Specific/NISTP256/AMD64/fenzDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_12limbs/femul.v Finished transaction in 50.426 secs (46.528u,0.072s) (successful) total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s Finished transaction in 80.129 secs (74.068u,0.024s) (successful) Closed under the global context total time: 46.544s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s ─ReflectiveTactics.do_reflective_pipelin 0.0% 87.1% 1 40.552s ─ReflectiveTactics.solve_side_conditions 0.0% 86.7% 1 40.372s ─ReflectiveTactics.do_reify ------------ 0.0% 59.6% 1 27.740s ─Reify.Reify_rhs_gen ------------------- 1.6% 58.9% 1 27.432s ─Reify.do_reify_abs_goal --------------- 43.3% 43.6% 2 20.312s ─Reify.do_reifyf_goal ------------------ 42.5% 42.8% 108 10.328s ─ReflectiveTactics.solve_post_reified_si 0.1% 27.1% 1 12.632s ─UnifyAbstractReflexivity.unify_transfor 18.6% 23.5% 7 3.552s ─eexact -------------------------------- 13.7% 13.7% 110 0.136s ─Glue.refine_to_reflective_glue' ------- 0.0% 7.8% 1 3.612s ─Glue.zrange_to_reflective ------------- 0.0% 7.2% 1 3.332s ─Glue.zrange_to_reflective_goal -------- 1.7% 5.5% 1 2.544s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s ─unify (constr) (constr) --------------- 5.1% 5.1% 6 1.068s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s ─change G' ----------------------------- 4.8% 4.8% 1 2.252s ─rewrite H ----------------------------- 3.8% 3.8% 1 1.748s ─pose proof (pf : Interpretation.Bo 3.6% 3.6% 1 1.664s ─prove_interp_compile_correct ---------- 0.0% 3.5% 1 1.616s ─rewrite ?EtaInterp.InterpExprEta ------ 3.2% 3.2% 1 1.468s ─ReflectiveTactics.unify_abstract_cbv_in 1.6% 2.4% 1 1.124s ─reflexivity --------------------------- 2.1% 2.1% 7 0.396s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ -0.0% 94.9% 1 44.164s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 87.1% 1 40.552s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 86.7% 1 40.372s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- 0.0% 59.6% 1 27.740s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.6% 58.9% 1 27.432s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.3% 43.6% 2 20.312s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.5% 42.8% 108 10.328s β”‚ β”‚ β”‚β””eexact -------------------------- 13.2% 13.2% 108 0.072s β”‚ β”‚ β”œβ”€rewrite H ----------------------- 3.8% 3.8% 1 1.748s β”‚ β”‚ └─prove_interp_compile_correct ---- 0.0% 3.5% 1 1.616s β”‚ β”‚ β””rewrite ?EtaInterp.InterpExprEta 3.2% 3.2% 1 1.468s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 27.1% 1 12.632s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 18.6% 23.5% 7 3.552s β”‚ β”‚β””unify (constr) (constr) --------- 4.3% 4.3% 5 1.068s β”‚ └─ReflectiveTactics.unify_abstract_ 1.6% 2.4% 1 1.124s └─Glue.refine_to_reflective_glue' ----- 0.0% 7.8% 1 3.612s β””Glue.zrange_to_reflective ----------- 0.0% 7.2% 1 3.332s β””Glue.zrange_to_reflective_goal ------ 1.7% 5.5% 1 2.544s β””pose proof (pf : Interpretation. 3.6% 3.6% 1 1.664s ─synthesize ---------------------------- 0.0% 5.1% 1 2.380s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.0% 1 2.320s β””change G' ----------------------------- 4.8% 4.8% 1 2.252s src/Specific/solinas32_2e255m765_12limbs/femul (real: 155.79, user: 143.70, sys: 0.32, mem: 1454696 ko) ROCQ compile src/Specific/NISTP256/AMD64/feoppDisplay > src/Specific/NISTP256/AMD64/feoppDisplay.log ROCQ compile src/Specific/NISTP256/AMD64/fesubDisplay > src/Specific/NISTP256/AMD64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/fesquareDisplay > src/Specific/X25519/C64/fesquareDisplay.log ROCQ compile src/Specific/X25519/C64/fesubDisplay > src/Specific/X25519/C64/fesubDisplay.log ROCQ compile src/Specific/X25519/C64/freezeDisplay > src/Specific/X25519/C64/freezeDisplay.log ROCQ compile src/Specific/solinas32_2e255m765_13limbs/femul.v Finished transaction in 61.854 secs (57.328u,0.079s) (successful) total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s Finished transaction in 94.432 secs (86.96u,0.02s) (successful) Closed under the global context total time: 57.348s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s ─ReflectiveTactics.do_reflective_pipelin 0.0% 86.2% 1 49.452s ─ReflectiveTactics.solve_side_conditions 0.0% 85.9% 1 49.264s ─ReflectiveTactics.do_reify ------------ -0.0% 57.6% 1 33.004s ─Reify.Reify_rhs_gen ------------------- 1.3% 56.9% 1 32.608s ─Reify.do_reify_abs_goal --------------- 43.1% 43.3% 2 24.840s ─Reify.do_reifyf_goal ------------------ 42.3% 42.6% 117 12.704s ─ReflectiveTactics.solve_post_reified_si 0.1% 28.4% 1 16.260s ─UnifyAbstractReflexivity.unify_transfor 19.6% 25.0% 7 4.824s ─eexact -------------------------------- 13.9% 13.9% 119 0.144s ─Glue.refine_to_reflective_glue' ------- 0.0% 8.3% 1 4.772s ─Glue.zrange_to_reflective ------------- 0.0% 7.8% 1 4.484s ─Glue.zrange_to_reflective_goal -------- 1.7% 6.0% 1 3.464s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s ─unify (constr) (constr) --------------- 5.4% 5.4% 6 1.540s ─IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s ─change G' ----------------------------- 5.2% 5.2% 1 2.964s ─pose proof (pf : Interpretation.Bo 4.2% 4.2% 1 2.416s ─prove_interp_compile_correct ---------- 0.0% 3.3% 1 1.904s ─rewrite H ----------------------------- 3.3% 3.3% 1 1.896s ─rewrite ?EtaInterp.InterpExprEta ------ 3.0% 3.0% 1 1.732s ─ReflectiveTactics.unify_abstract_cbv_in 1.4% 2.1% 1 1.212s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 94.6% 1 54.224s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 86.2% 1 49.452s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 85.9% 1 49.264s β”‚ β”œβ”€ReflectiveTactics.do_reify -------- -0.0% 57.6% 1 33.004s β”‚ β”‚β””Reify.Reify_rhs_gen --------------- 1.3% 56.9% 1 32.608s β”‚ β”‚ β”œβ”€Reify.do_reify_abs_goal --------- 43.1% 43.3% 2 24.840s β”‚ β”‚ β”‚β””Reify.do_reifyf_goal ------------ 42.3% 42.6% 117 12.704s β”‚ β”‚ β”‚β””eexact -------------------------- 13.4% 13.4% 117 0.084s β”‚ β”‚ β”œβ”€prove_interp_compile_correct ---- 0.0% 3.3% 1 1.904s β”‚ β”‚ β”‚β””rewrite ?EtaInterp.InterpExprEta 3.0% 3.0% 1 1.732s β”‚ β”‚ └─rewrite H ----------------------- 3.3% 3.3% 1 1.896s β”‚ └─ReflectiveTactics.solve_post_reifie 0.1% 28.4% 1 16.260s β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 19.6% 25.0% 7 4.824s β”‚ β”‚β””unify (constr) (constr) --------- 4.8% 4.8% 5 1.540s β”‚ └─ReflectiveTactics.unify_abstract_ 1.4% 2.1% 1 1.212s └─Glue.refine_to_reflective_glue' ----- 0.0% 8.3% 1 4.772s β””Glue.zrange_to_reflective ----------- 0.0% 7.8% 1 4.484s β””Glue.zrange_to_reflective_goal ------ 1.7% 6.0% 1 3.464s β””pose proof (pf : Interpretation. 4.2% 4.2% 1 2.416s ─synthesize ---------------------------- 0.0% 5.4% 1 3.124s β””IntegrationTestTemporaryMiscCommon.do_r 0.0% 5.3% 1 3.040s β””change G' ----------------------------- 5.2% 5.2% 1 2.964s src/Specific/solinas32_2e255m765_13limbs/femul (real: 181.77, user: 168.52, sys: 0.40, mem: 1589516 ko) ROCQ compile src/Specific/NISTP256/AMD64/femul.v Finished transaction in 119.257 secs (109.936u,0.256s) (successful) total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s Finished transaction in 61.452 secs (58.503u,0.055s) (successful) Closed under the global context total time: 110.140s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s ─ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s ─ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s ─ReflectiveTactics.do_reify ------------ -0.0% 83.7% 1 92.208s ─Reify.Reify_rhs_gen ------------------- 0.7% 83.5% 1 91.960s ─Reify.do_reify_abs_goal --------------- 77.7% 77.8% 2 85.708s ─Reify.do_reifyf_goal ------------------ 77.4% 77.5% 901 85.364s ─eexact -------------------------------- 17.9% 17.9% 903 0.136s ─ReflectiveTactics.solve_post_reified_si 0.3% 12.5% 1 13.784s ─UnifyAbstractReflexivity.unify_transfor 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─Pipeline.refine_reflectively_gen ------ 0.0% 97.1% 1 106.964s β””ReflectiveTactics.do_reflective_pipelin -0.0% 96.4% 1 106.196s β””ReflectiveTactics.solve_side_conditions 0.0% 96.2% 1 105.992s β”œβ”€ReflectiveTactics.do_reify ---------- -0.0% 83.7% 1 92.208s β”‚β””Reify.Reify_rhs_gen ----------------- 0.7% 83.5% 1 91.960s β”‚β””Reify.do_reify_abs_goal ------------- 77.7% 77.8% 2 85.708s β”‚β””Reify.do_reifyf_goal ---------------- 77.4% 77.5% 901 85.364s β”‚β””eexact ------------------------------ 17.7% 17.7% 901 0.136s └─ReflectiveTactics.solve_post_reified_ 0.3% 12.5% 1 13.784s β””UnifyAbstractReflexivity.unify_transf 9.8% 11.2% 7 3.356s ─synthesize_montgomery ----------------- 0.0% 2.9% 1 3.176s src/Specific/NISTP256/AMD64/femul (real: 202.96, user: 189.62, sys: 0.64, mem: 3302508 ko) ROCQ compile src/Specific/NISTP256/AMD64/femulDisplay > src/Specific/NISTP256/AMD64/femulDisplay.log ROCQ compile src/Specific/X25519/C64/ladderstep.v total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s Finished transaction in 171.122 secs (161.392u,0.039s) (successful) Closed under the global context total time: 52.080s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s ─Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s ─ReflectiveTactics.do_reflective_pipelin 0.0% 93.8% 1 48.872s ─ReflectiveTactics.solve_side_conditions 0.0% 93.7% 1 48.776s ─ReflectiveTactics.solve_post_reified_si 0.2% 56.5% 1 29.412s ─UnifyAbstractReflexivity.unify_transfor 44.7% 49.1% 7 6.968s ─ReflectiveTactics.do_reify ------------ 0.0% 37.2% 1 19.364s ─Reify.Reify_rhs_gen ------------------- 2.1% 23.4% 1 12.200s ─Reify.do_reifyf_goal ------------------ 11.2% 11.3% 138 1.884s ─Compilers.Reify.reify_context_variables 0.1% 9.2% 1 4.808s ─rewrite H ----------------------------- 7.3% 7.3% 1 3.816s ─ReflectiveTactics.unify_abstract_cbv_in 4.7% 6.4% 1 3.336s ─Glue.refine_to_reflective_glue' ------- 0.0% 4.7% 1 2.448s ─Glue.zrange_to_reflective ------------- 0.0% 4.0% 1 2.068s ─Reify.transitivity_tt ----------------- 0.1% 3.7% 2 0.984s ─transitivity -------------------------- 3.5% 3.5% 10 0.880s ─reflexivity --------------------------- 3.4% 3.4% 11 0.772s ─Glue.zrange_to_reflective_goal -------- 2.4% 3.3% 1 1.728s ─eexact -------------------------------- 3.2% 3.2% 140 0.032s ─unify (constr) (constr) --------------- 3.1% 3.1% 6 0.852s ─clear (var_list) ---------------------- 3.1% 3.1% 98 0.584s ─UnfoldArg.unfold_second_arg ----------- 0.4% 3.0% 2 1.576s ─tac ----------------------------------- 2.1% 3.0% 2 1.564s ─ClearAll.clear_all -------------------- 0.2% 2.8% 7 0.584s ─ChangeInAll.change_with_compute_in_all 0.0% 2.6% 221 0.012s ─change c with c' in * ----------------- 2.5% 2.5% 221 0.012s ─Reify.do_reify_abs_goal --------------- 2.4% 2.5% 2 1.276s tactic local total calls max β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ─synthesize_xzladderstep --------------- 0.0% 100.0% 1 52.080s β””Pipeline.refine_reflectively_gen ------ 0.0% 98.5% 1 51.320s β”œβ”€ReflectiveTactics.do_reflective_pipel 0.0% 93.8% 1 48.872s β”‚β””ReflectiveTactics.solve_side_conditio 0.0% 93.7% 1 48.776s β”‚ β”œβ”€ReflectiveTactics.solve_post_reifie 0.2% 56.5% 1 29.412s β”‚ β”‚ β”œβ”€UnifyAbstractReflexivity.unify_tr 44.7% 49.1% 7 6.968s β”‚ β”‚ β”‚β””ClearAll.clear_all -------------- 0.2% 2.8% 7 0.584s β”‚ β”‚ β”‚β””clear (var_list) ---------------- 2.7% 2.7% 65 0.584s β”‚ β”‚ └─ReflectiveTactics.unify_abstract_ 4.7% 6.4% 1 3.336s β”‚ └─ReflectiveTactics.do_reify -------- 0.0% 37.2% 1 19.364s β”‚ β”œβ”€Reify.Reify_rhs_gen ------------- 2.1% 23.4% 1 12.200s β”‚ β”‚ β”œβ”€rewrite H --------------------- 7.3% 7.3% 1 3.816s β”‚ β”‚ β”œβ”€Reify.transitivity_tt --------- 0.1% 3.7% 2 0.984s β”‚ β”‚ β”‚β””transitivity ------------------ 3.4% 3.4% 4 0.880s β”‚ β”‚ β”œβ”€tac --------------------------- 2.1% 3.0% 1 1.564s β”‚ β”‚ └─Reify.do_reify_abs_goal ------- 2.4% 2.5% 2 1.276s β”‚ β”‚ β””Reify.do_reifyf_goal ---------- 2.2% 2.2% 25 1.148s β”‚ β”œβ”€Compilers.Reify.reify_context_var 0.1% 9.2% 1 4.808s β”‚ β”‚β””Reify.do_reifyf_goal ------------ 9.0% 9.1% 113 1.884s β”‚ β”‚β””eexact -------------------------- 2.4% 2.4% 113 0.032s β”‚ └─UnfoldArg.unfold_second_arg ----- 0.4% 3.0% 2 1.576s β”‚ β””ChangeInAll.change_with_compute_i 0.0% 2.6% 221 0.012s β”‚ β””change c with c' in * ----------- 2.5% 2.5% 221 0.012s └─Glue.refine_to_reflective_glue' ----- 0.0% 4.7% 1 2.448s β””Glue.zrange_to_reflective ----------- 0.0% 4.0% 1 2.068s β””Glue.zrange_to_reflective_goal ------ 2.4% 3.3% 1 1.728s src/Specific/X25519/C64/ladderstep (real: 256.77, user: 241.34, sys: 0.45, mem: 1617000 ko) ROCQ compile src/Specific/X25519/C64/ladderstepDisplay > src/Specific/X25519/C64/ladderstepDisplay.log rocq-9.2.0/test-suite/precomputed-time-tests/strip-leading-pwd/000077500000000000000000000000001516144147600245625ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/strip-leading-pwd/run.sh000077500000000000000000000010361516144147600257250ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" /usr/bin/env python3 -c 'import os; open("time-of-build.log", "w").write(open("time-of-build.log.in", "r").read().replace("$PWD", os.getcwd()))' $make_one_time_file time-of-build.log time-of-build-pretty-user.log diff -u time-of-build-pretty-user.log.expected time-of-build-pretty-user.log || exit $? $make_one_time_file time-of-build.log time-of-build-pretty-real.log diff -u time-of-build-pretty-real.log.expected time-of-build-pretty-real.log || exit $? time-of-build-pretty-real.log.expected000066400000000000000000000276641516144147600337300ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/strip-leading-pwd Time | Peak Mem | File Name ---------------------------------------------------------------------- 2m02.85s | 575776 ko | Total Time / Peak Mem ---------------------------------------------------------------------- 0m16.08s | 435484 ko | coqutil/Map/TestGoals.vo 0m08.38s | 575776 ko | coqutil/Word/Properties.vo 0m06.40s | 452836 ko | coqutil/Map/Properties.vo 0m06.20s | 444256 ko | coqutil/Tactics/ident_of_string.vo 0m04.95s | 413708 ko | coqutil/Map/SlowGoals.vo 0m04.85s | 434980 ko | coqutil/Datatypes/List.vo 0m02.50s | 421756 ko | coqutil/Word/LittleEndianList.vo 0m02.23s | 406924 ko | coqutil/Datatypes/PropSet.vo 0m02.22s | 420764 ko | coqutil/Map/MapEauto.vo 0m01.65s | 420928 ko | coqutil/Word/LittleEndian.vo 0m01.45s | 417760 ko | coqutil/Word/BigEndian.vo 0m01.39s | 416228 ko | coqutil/Z/BitOps.vo 0m01.28s | 418272 ko | coqutil/Map/SortedList.vo 0m01.09s | 415560 ko | coqutil/Datatypes/OperatorOverloading.vo 0m01.05s | 102644 ko | coqutil/Map/Interface.vo.native 0m01.03s | 407636 ko | coqutil/Z/PushPullMod.vo 0m00.97s | 415948 ko | coqutil/Datatypes/ListSet.vo 0m00.95s | 103212 ko | coqutil/Datatypes/OperatorOverloading.vo.native 0m00.94s | 78484 ko | coqutil/Word/Interface.vo.native 0m00.92s | 414256 ko | coqutil/Z/bitblast.vo 0m00.89s | 101560 ko | coqutil/Sorting/OrderToPermutation.vo.native 0m00.88s | 102424 ko | coqutil/Map/SortedList.vo.native 0m00.85s | 101692 ko | coqutil/Datatypes/Inhabited.vo.native 0m00.84s | 103096 ko | coqutil/Map/Empty_set_keyed_map.vo.native 0m00.80s | 102372 ko | coqutil/Map/Funext.vo.native 0m00.78s | 412576 ko | coqutil/Word/Naive.vo 0m00.78s | 408248 ko | coqutil/Z/ZLib.vo 0m00.77s | 100032 ko | coqutil/Map/Properties.vo.native 0m00.75s | 417728 ko | coqutil/Map/OfFunc.vo 0m00.74s | 421844 ko | coqutil/Map/OfListWord.vo 0m00.74s | 419828 ko | coqutil/Word/ZifyLittleEndian.vo 0m00.73s | 104180 ko | coqutil/Tactics/fwd_word_hints.vo.native 0m00.72s | 103220 ko | coqutil/Map/SortedListString.vo.native 0m00.72s | 103964 ko | coqutil/Map/Z_keyed_SortedListMap.vo.native 0m00.69s | 102576 ko | coqutil/Tactics/SafeSimpl.vo.native 0m00.69s | 102316 ko | coqutil/Word/Naive.vo.native 0m00.66s | 101836 ko | coqutil/Datatypes/ListSet.vo.native 0m00.66s | 103320 ko | coqutil/Word/Properties.vo.native 0m00.66s | 104132 ko | coqutil/Word/ZifyLittleEndian.vo.native 0m00.64s | 104208 ko | coqutil/Tactics/fwd.vo.native 0m00.64s | 419144 ko | coqutil/Word/SimplWordExpr.vo 0m00.63s | 101324 ko | coqutil/Map/OfFunc.vo.native 0m00.63s | 104700 ko | coqutil/Map/Solver.vo.native 0m00.63s | 104004 ko | coqutil/Word/LittleEndianList.vo.native 0m00.63s | 102316 ko | coqutil/Z/BitOps.vo.native 0m00.62s | 104040 ko | coqutil/Map/SortedListWord.vo.native 0m00.62s | 101924 ko | coqutil/Tactics/fwd_list_hints.vo.native 0m00.62s | 101904 ko | coqutil/Tactics/rewr.vo.native 0m00.61s | 101844 ko | coqutil/Datatypes/PropSet.vo.native 0m00.60s | 103528 ko | coqutil/Map/SortedListString_test.vo.native 0m00.60s | 104064 ko | coqutil/Word/LittleEndian.vo.native 0m00.59s | 103836 ko | coqutil/Word/BigEndian.vo.native 0m00.58s | 319092 ko | coqutil/Map/Z_keyed_SortedListMap.vo 0m00.58s | 103300 ko | coqutil/Word/DebugWordEq.vo.native 0m00.58s | 413136 ko | coqutil/Z/prove_Zeq_bitwise.vo 0m00.57s | 54340 ko | coqutil/Datatypes/HList.vo.native 0m00.57s | 99024 ko | coqutil/Datatypes/List.vo.native 0m00.57s | 288536 ko | coqutil/Map/Empty_set_keyed_map.vo 0m00.57s | 311552 ko | coqutil/Map/Funext.vo 0m00.56s | 104332 ko | coqutil/Map/OfListWord.vo.native 0m00.56s | 88000 ko | coqutil/Tactics/ident_of_string.vo.native 0m00.56s | 103836 ko | coqutil/Z/bitblast.vo.native 0m00.55s | 101296 ko | coqutil/Word/Bitwidth.vo.native 0m00.55s | 101360 ko | coqutil/Word/Bitwidth32.vo.native 0m00.55s | 104148 ko | coqutil/Word/SimplWordExpr.vo.native 0m00.53s | 100712 ko | coqutil/Byte.vo.native 0m00.53s | 100992 ko | coqutil/Z/PushPullMod.vo.native 0m00.52s | 99996 ko | coqutil/Z/Lia.vo.native 0m00.51s | 284324 ko | coqutil/Datatypes/Inhabited.vo 0m00.51s | 100544 ko | coqutil/Tactics/Simp.vo.native 0m00.51s | 100016 ko | coqutil/Tactics/Tactics.vo.native 0m00.51s | 88936 ko | coqutil/Tactics/destr.vo.native 0m00.50s | 88688 ko | coqutil/Decidable.vo.native 0m00.50s | 363816 ko | coqutil/Map/SortedListWord.vo 0m00.50s | 102472 ko | coqutil/Word/Bitwidth64.vo.native 0m00.50s | 361320 ko | coqutil/Word/DebugWordEq.vo 0m00.49s | 87608 ko | coqutil/Datatypes/String.vo.native 0m00.49s | 87980 ko | coqutil/Tactics/fwd_core.vo.native 0m00.48s | 87324 ko | coqutil/Macros/ident_to_string.vo.native 0m00.48s | 79096 ko | coqutil/Tactics/fwd_arith_hints.vo.native 0m00.48s | 100668 ko | coqutil/Z/ZLib.vo.native 0m00.47s | 312492 ko | coqutil/Map/SortedListString_test.vo 0m00.47s | 78704 ko | coqutil/Z/div_to_equations.vo.native 0m00.46s | 100708 ko | coqutil/Datatypes/ToConversion.vo.native 0m00.46s | 101892 ko | coqutil/Map/MapEauto.vo.native 0m00.46s | 102724 ko | coqutil/Tactics/fwd_map_hints.vo.native 0m00.45s | 101768 ko | coqutil/Map/MapKeys.vo.native 0m00.44s | 326076 ko | coqutil/Map/Interface.vo 0m00.43s | 392964 ko | coqutil/Map/MapKeys.vo 0m00.43s | 317964 ko | coqutil/Sorting/OrderToPermutation.vo 0m00.42s | 299108 ko | coqutil/Tactics/rewr.vo 0m00.42s | 102696 ko | coqutil/Z/prove_Zeq_bitwise.vo.native 0m00.41s | 278808 ko | coqutil/Tactics/SafeSimpl.vo 0m00.40s | 352920 ko | coqutil/Datatypes/String.vo 0m00.40s | 310528 ko | coqutil/Tactics/fwd_word_hints.vo 0m00.39s | 304396 ko | coqutil/Map/Solver.vo 0m00.39s | 279768 ko | coqutil/Map/SortedListString.vo 0m00.39s | 291400 ko | coqutil/Z/Lia.vo 0m00.38s | 297656 ko | coqutil/Tactics/fwd.vo 0m00.37s | 292180 ko | coqutil/Word/Bitwidth32.vo 0m00.36s | 101432 ko | coqutil/Map/SlowGoals.vo.native 0m00.36s | 295528 ko | coqutil/Tactics/Tactics.vo 0m00.36s | 274956 ko | coqutil/Tactics/fwd_list_hints.vo 0m00.36s | 291996 ko | coqutil/Word/Bitwidth64.vo 0m00.36s | 77596 ko | coqutil/Z/div_mod_to_equations.vo.native 0m00.35s | 269884 ko | coqutil/Decidable.vo 0m00.34s | 301660 ko | coqutil/Datatypes/ToConversion.vo 0m00.34s | 102636 ko | coqutil/Map/TestGoals.vo.native 0m00.33s | 283128 ko | coqutil/Tactics/fwd_map_hints.vo 0m00.32s | 345240 ko | coqutil/Byte.vo 0m00.32s | 293652 ko | coqutil/Tactics/Simp.vo 0m00.32s | 329896 ko | coqutil/Word/Interface.vo 0m00.31s | 214876 ko | coqutil/Tactics/fwd_arith_hints.vo 0m00.31s | 291312 ko | coqutil/Word/Bitwidth.vo 0m00.27s | 29464 ko | coqutil/Datatypes/Prod.vo.native 0m00.27s | 240248 ko | coqutil/Tactics/fwd_core.vo 0m00.26s | 27288 ko | coqutil/Datatypes/Option.vo.native 0m00.24s | 56896 ko | coqutil/Sorting/Permutation.vo.native 0m00.24s | 208528 ko | coqutil/Z/div_mod_to_equations.vo 0m00.23s | 227492 ko | coqutil/Macros/ident_to_string.vo 0m00.23s | 54316 ko | coqutil/Tactics/Records.vo.native 0m00.21s | 174320 ko | coqutil/Datatypes/HList.vo 0m00.21s | 221288 ko | coqutil/Tactics/destr.vo 0m00.18s | 201096 ko | coqutil/Z/div_to_equations.vo 0m00.17s | 138328 ko | coqutil/Sorting/Permutation.vo 0m00.17s | 149096 ko | coqutil/Tactics/Records.vo 0m00.14s | 109820 ko | coqutil/Datatypes/Option.vo 0m00.11s | 23276 ko | coqutil/Ltac2Lib/Log.vo.native 0m00.10s | 22064 ko | coqutil/Macros/subst.vo.native 0m00.10s | 22936 ko | coqutil/Macros/symmetry.vo.native 0m00.10s | 21952 ko | coqutil/Macros/unique.vo.native 0m00.10s | 73372 ko | coqutil/Tactics/ParamRecords.vo 0m00.10s | 79672 ko | coqutil/Tactics/eplace.vo 0m00.10s | 22032 ko | coqutil/Tactics/ltac_list_ops.vo.native 0m00.09s | 73944 ko | coqutil/Macros/symmetry.vo 0m00.09s | 22416 ko | coqutil/Tactics/fwd_bool_hints.vo.native 0m00.09s | 65792 ko | coqutil/Tactics/simpl_rewrite.vo 0m00.08s | 94084 ko | coqutil/Datatypes/Prod.vo 0m00.08s | 71232 ko | coqutil/Ltac2Lib/Log.vo 0m00.08s | 63624 ko | coqutil/Tactics/eabstract.vo 0m00.08s | 22032 ko | coqutil/Tactics/eabstract.vo.native 0m00.08s | 22228 ko | coqutil/Tactics/forward.vo.native 0m00.08s | 63820 ko | coqutil/Tactics/rdelta.vo 0m00.08s | 22092 ko | coqutil/Tactics/syntactic_unify.vo.native 0m00.07s | 23256 ko | coqutil/Ltac2Lib/Constr.vo.native 0m00.07s | 22004 ko | coqutil/Tactics/autoforward.vo.native 0m00.07s | 22100 ko | coqutil/Tactics/eplace.vo.native 0m00.07s | 65820 ko | coqutil/Tactics/fwd_bool_hints.vo 0m00.07s | 65508 ko | coqutil/Tactics/ltac_list_ops.vo 0m00.07s | 21888 ko | coqutil/dlet.vo.native 0m00.06s | 66532 ko | coqutil/Datatypes/PrimitivePair.vo 0m00.06s | 22040 ko | coqutil/Datatypes/PrimitivePair.vo.native 0m00.06s | 23220 ko | coqutil/Ltac2Lib/Msg.vo.native 0m00.06s | 64172 ko | coqutil/Tactics/letexists.vo 0m00.06s | 22076 ko | coqutil/Tactics/rdelta.vo.native 0m00.06s | 22100 ko | coqutil/Tactics/simpl_rewrite.vo.native 0m00.06s | 65768 ko | coqutil/Tactics/syntactic_unify.vo 0m00.06s | 63768 ko | coqutil/dlet.vo 0m00.06s | 64964 ko | coqutil/sanity.vo 0m00.05s | 69124 ko | coqutil/Ltac2Lib/Msg.vo 0m00.05s | 63844 ko | coqutil/Macros/subst.vo 0m00.05s | 63500 ko | coqutil/Macros/unique.vo 0m00.05s | 64908 ko | coqutil/Tactics/autoforward.vo 0m00.05s | 68064 ko | coqutil/Tactics/forward.vo 0m00.05s | 22024 ko | coqutil/Tactics/letexists.vo.native 0m00.04s | 71420 ko | coqutil/Ltac2Lib/Constr.vo 0m00.04s | 23244 ko | coqutil/Tactics/ParamRecords.vo.native 0m00.04s | 21960 ko | coqutil/sanity.vo.native time-of-build-pretty-user.log.expected000066400000000000000000000276641516144147600337630ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/strip-leading-pwd Time | Peak Mem | File Name ---------------------------------------------------------------------- 2m02.85s | 575776 ko | Total Time / Peak Mem ---------------------------------------------------------------------- 0m16.08s | 435484 ko | coqutil/Map/TestGoals.vo 0m08.38s | 575776 ko | coqutil/Word/Properties.vo 0m06.40s | 452836 ko | coqutil/Map/Properties.vo 0m06.20s | 444256 ko | coqutil/Tactics/ident_of_string.vo 0m04.95s | 413708 ko | coqutil/Map/SlowGoals.vo 0m04.85s | 434980 ko | coqutil/Datatypes/List.vo 0m02.50s | 421756 ko | coqutil/Word/LittleEndianList.vo 0m02.23s | 406924 ko | coqutil/Datatypes/PropSet.vo 0m02.22s | 420764 ko | coqutil/Map/MapEauto.vo 0m01.65s | 420928 ko | coqutil/Word/LittleEndian.vo 0m01.45s | 417760 ko | coqutil/Word/BigEndian.vo 0m01.39s | 416228 ko | coqutil/Z/BitOps.vo 0m01.28s | 418272 ko | coqutil/Map/SortedList.vo 0m01.09s | 415560 ko | coqutil/Datatypes/OperatorOverloading.vo 0m01.05s | 102644 ko | coqutil/Map/Interface.vo.native 0m01.03s | 407636 ko | coqutil/Z/PushPullMod.vo 0m00.97s | 415948 ko | coqutil/Datatypes/ListSet.vo 0m00.95s | 103212 ko | coqutil/Datatypes/OperatorOverloading.vo.native 0m00.94s | 78484 ko | coqutil/Word/Interface.vo.native 0m00.92s | 414256 ko | coqutil/Z/bitblast.vo 0m00.89s | 101560 ko | coqutil/Sorting/OrderToPermutation.vo.native 0m00.88s | 102424 ko | coqutil/Map/SortedList.vo.native 0m00.85s | 101692 ko | coqutil/Datatypes/Inhabited.vo.native 0m00.84s | 103096 ko | coqutil/Map/Empty_set_keyed_map.vo.native 0m00.80s | 102372 ko | coqutil/Map/Funext.vo.native 0m00.78s | 412576 ko | coqutil/Word/Naive.vo 0m00.78s | 408248 ko | coqutil/Z/ZLib.vo 0m00.77s | 100032 ko | coqutil/Map/Properties.vo.native 0m00.75s | 417728 ko | coqutil/Map/OfFunc.vo 0m00.74s | 421844 ko | coqutil/Map/OfListWord.vo 0m00.74s | 419828 ko | coqutil/Word/ZifyLittleEndian.vo 0m00.73s | 104180 ko | coqutil/Tactics/fwd_word_hints.vo.native 0m00.72s | 103220 ko | coqutil/Map/SortedListString.vo.native 0m00.72s | 103964 ko | coqutil/Map/Z_keyed_SortedListMap.vo.native 0m00.69s | 102576 ko | coqutil/Tactics/SafeSimpl.vo.native 0m00.69s | 102316 ko | coqutil/Word/Naive.vo.native 0m00.66s | 101836 ko | coqutil/Datatypes/ListSet.vo.native 0m00.66s | 103320 ko | coqutil/Word/Properties.vo.native 0m00.66s | 104132 ko | coqutil/Word/ZifyLittleEndian.vo.native 0m00.64s | 104208 ko | coqutil/Tactics/fwd.vo.native 0m00.64s | 419144 ko | coqutil/Word/SimplWordExpr.vo 0m00.63s | 101324 ko | coqutil/Map/OfFunc.vo.native 0m00.63s | 104700 ko | coqutil/Map/Solver.vo.native 0m00.63s | 104004 ko | coqutil/Word/LittleEndianList.vo.native 0m00.63s | 102316 ko | coqutil/Z/BitOps.vo.native 0m00.62s | 104040 ko | coqutil/Map/SortedListWord.vo.native 0m00.62s | 101924 ko | coqutil/Tactics/fwd_list_hints.vo.native 0m00.62s | 101904 ko | coqutil/Tactics/rewr.vo.native 0m00.61s | 101844 ko | coqutil/Datatypes/PropSet.vo.native 0m00.60s | 103528 ko | coqutil/Map/SortedListString_test.vo.native 0m00.60s | 104064 ko | coqutil/Word/LittleEndian.vo.native 0m00.59s | 103836 ko | coqutil/Word/BigEndian.vo.native 0m00.58s | 319092 ko | coqutil/Map/Z_keyed_SortedListMap.vo 0m00.58s | 103300 ko | coqutil/Word/DebugWordEq.vo.native 0m00.58s | 413136 ko | coqutil/Z/prove_Zeq_bitwise.vo 0m00.57s | 54340 ko | coqutil/Datatypes/HList.vo.native 0m00.57s | 99024 ko | coqutil/Datatypes/List.vo.native 0m00.57s | 288536 ko | coqutil/Map/Empty_set_keyed_map.vo 0m00.57s | 311552 ko | coqutil/Map/Funext.vo 0m00.56s | 104332 ko | coqutil/Map/OfListWord.vo.native 0m00.56s | 88000 ko | coqutil/Tactics/ident_of_string.vo.native 0m00.56s | 103836 ko | coqutil/Z/bitblast.vo.native 0m00.55s | 101296 ko | coqutil/Word/Bitwidth.vo.native 0m00.55s | 101360 ko | coqutil/Word/Bitwidth32.vo.native 0m00.55s | 104148 ko | coqutil/Word/SimplWordExpr.vo.native 0m00.53s | 100712 ko | coqutil/Byte.vo.native 0m00.53s | 100992 ko | coqutil/Z/PushPullMod.vo.native 0m00.52s | 99996 ko | coqutil/Z/Lia.vo.native 0m00.51s | 284324 ko | coqutil/Datatypes/Inhabited.vo 0m00.51s | 100544 ko | coqutil/Tactics/Simp.vo.native 0m00.51s | 100016 ko | coqutil/Tactics/Tactics.vo.native 0m00.51s | 88936 ko | coqutil/Tactics/destr.vo.native 0m00.50s | 88688 ko | coqutil/Decidable.vo.native 0m00.50s | 363816 ko | coqutil/Map/SortedListWord.vo 0m00.50s | 102472 ko | coqutil/Word/Bitwidth64.vo.native 0m00.50s | 361320 ko | coqutil/Word/DebugWordEq.vo 0m00.49s | 87608 ko | coqutil/Datatypes/String.vo.native 0m00.49s | 87980 ko | coqutil/Tactics/fwd_core.vo.native 0m00.48s | 87324 ko | coqutil/Macros/ident_to_string.vo.native 0m00.48s | 79096 ko | coqutil/Tactics/fwd_arith_hints.vo.native 0m00.48s | 100668 ko | coqutil/Z/ZLib.vo.native 0m00.47s | 312492 ko | coqutil/Map/SortedListString_test.vo 0m00.47s | 78704 ko | coqutil/Z/div_to_equations.vo.native 0m00.46s | 100708 ko | coqutil/Datatypes/ToConversion.vo.native 0m00.46s | 101892 ko | coqutil/Map/MapEauto.vo.native 0m00.46s | 102724 ko | coqutil/Tactics/fwd_map_hints.vo.native 0m00.45s | 101768 ko | coqutil/Map/MapKeys.vo.native 0m00.44s | 326076 ko | coqutil/Map/Interface.vo 0m00.43s | 392964 ko | coqutil/Map/MapKeys.vo 0m00.43s | 317964 ko | coqutil/Sorting/OrderToPermutation.vo 0m00.42s | 299108 ko | coqutil/Tactics/rewr.vo 0m00.42s | 102696 ko | coqutil/Z/prove_Zeq_bitwise.vo.native 0m00.41s | 278808 ko | coqutil/Tactics/SafeSimpl.vo 0m00.40s | 352920 ko | coqutil/Datatypes/String.vo 0m00.40s | 310528 ko | coqutil/Tactics/fwd_word_hints.vo 0m00.39s | 304396 ko | coqutil/Map/Solver.vo 0m00.39s | 279768 ko | coqutil/Map/SortedListString.vo 0m00.39s | 291400 ko | coqutil/Z/Lia.vo 0m00.38s | 297656 ko | coqutil/Tactics/fwd.vo 0m00.37s | 292180 ko | coqutil/Word/Bitwidth32.vo 0m00.36s | 101432 ko | coqutil/Map/SlowGoals.vo.native 0m00.36s | 295528 ko | coqutil/Tactics/Tactics.vo 0m00.36s | 274956 ko | coqutil/Tactics/fwd_list_hints.vo 0m00.36s | 291996 ko | coqutil/Word/Bitwidth64.vo 0m00.36s | 77596 ko | coqutil/Z/div_mod_to_equations.vo.native 0m00.35s | 269884 ko | coqutil/Decidable.vo 0m00.34s | 301660 ko | coqutil/Datatypes/ToConversion.vo 0m00.34s | 102636 ko | coqutil/Map/TestGoals.vo.native 0m00.33s | 283128 ko | coqutil/Tactics/fwd_map_hints.vo 0m00.32s | 345240 ko | coqutil/Byte.vo 0m00.32s | 293652 ko | coqutil/Tactics/Simp.vo 0m00.32s | 329896 ko | coqutil/Word/Interface.vo 0m00.31s | 214876 ko | coqutil/Tactics/fwd_arith_hints.vo 0m00.31s | 291312 ko | coqutil/Word/Bitwidth.vo 0m00.27s | 29464 ko | coqutil/Datatypes/Prod.vo.native 0m00.27s | 240248 ko | coqutil/Tactics/fwd_core.vo 0m00.26s | 27288 ko | coqutil/Datatypes/Option.vo.native 0m00.24s | 56896 ko | coqutil/Sorting/Permutation.vo.native 0m00.24s | 208528 ko | coqutil/Z/div_mod_to_equations.vo 0m00.23s | 227492 ko | coqutil/Macros/ident_to_string.vo 0m00.23s | 54316 ko | coqutil/Tactics/Records.vo.native 0m00.21s | 174320 ko | coqutil/Datatypes/HList.vo 0m00.21s | 221288 ko | coqutil/Tactics/destr.vo 0m00.18s | 201096 ko | coqutil/Z/div_to_equations.vo 0m00.17s | 138328 ko | coqutil/Sorting/Permutation.vo 0m00.17s | 149096 ko | coqutil/Tactics/Records.vo 0m00.14s | 109820 ko | coqutil/Datatypes/Option.vo 0m00.11s | 23276 ko | coqutil/Ltac2Lib/Log.vo.native 0m00.10s | 22064 ko | coqutil/Macros/subst.vo.native 0m00.10s | 22936 ko | coqutil/Macros/symmetry.vo.native 0m00.10s | 21952 ko | coqutil/Macros/unique.vo.native 0m00.10s | 73372 ko | coqutil/Tactics/ParamRecords.vo 0m00.10s | 79672 ko | coqutil/Tactics/eplace.vo 0m00.10s | 22032 ko | coqutil/Tactics/ltac_list_ops.vo.native 0m00.09s | 73944 ko | coqutil/Macros/symmetry.vo 0m00.09s | 22416 ko | coqutil/Tactics/fwd_bool_hints.vo.native 0m00.09s | 65792 ko | coqutil/Tactics/simpl_rewrite.vo 0m00.08s | 94084 ko | coqutil/Datatypes/Prod.vo 0m00.08s | 71232 ko | coqutil/Ltac2Lib/Log.vo 0m00.08s | 63624 ko | coqutil/Tactics/eabstract.vo 0m00.08s | 22032 ko | coqutil/Tactics/eabstract.vo.native 0m00.08s | 22228 ko | coqutil/Tactics/forward.vo.native 0m00.08s | 63820 ko | coqutil/Tactics/rdelta.vo 0m00.08s | 22092 ko | coqutil/Tactics/syntactic_unify.vo.native 0m00.07s | 23256 ko | coqutil/Ltac2Lib/Constr.vo.native 0m00.07s | 22004 ko | coqutil/Tactics/autoforward.vo.native 0m00.07s | 22100 ko | coqutil/Tactics/eplace.vo.native 0m00.07s | 65820 ko | coqutil/Tactics/fwd_bool_hints.vo 0m00.07s | 65508 ko | coqutil/Tactics/ltac_list_ops.vo 0m00.07s | 21888 ko | coqutil/dlet.vo.native 0m00.06s | 66532 ko | coqutil/Datatypes/PrimitivePair.vo 0m00.06s | 22040 ko | coqutil/Datatypes/PrimitivePair.vo.native 0m00.06s | 23220 ko | coqutil/Ltac2Lib/Msg.vo.native 0m00.06s | 64172 ko | coqutil/Tactics/letexists.vo 0m00.06s | 22076 ko | coqutil/Tactics/rdelta.vo.native 0m00.06s | 22100 ko | coqutil/Tactics/simpl_rewrite.vo.native 0m00.06s | 65768 ko | coqutil/Tactics/syntactic_unify.vo 0m00.06s | 63768 ko | coqutil/dlet.vo 0m00.06s | 64964 ko | coqutil/sanity.vo 0m00.05s | 69124 ko | coqutil/Ltac2Lib/Msg.vo 0m00.05s | 63844 ko | coqutil/Macros/subst.vo 0m00.05s | 63500 ko | coqutil/Macros/unique.vo 0m00.05s | 64908 ko | coqutil/Tactics/autoforward.vo 0m00.05s | 68064 ko | coqutil/Tactics/forward.vo 0m00.05s | 22024 ko | coqutil/Tactics/letexists.vo.native 0m00.04s | 71420 ko | coqutil/Ltac2Lib/Constr.vo 0m00.04s | 23244 ko | coqutil/Tactics/ParamRecords.vo.native 0m00.04s | 21960 ko | coqutil/sanity.vo.native rocq-9.2.0/test-suite/precomputed-time-tests/strip-leading-pwd/time-of-build.log.in000066400000000000000000000767071516144147600303500ustar00rootroot00000000000000printf -- '-R $PWD/src/coqutil/ coqutil\n-arg -w -arg unsupported-attributes\n' > _CoqProject Generating Makefile.coq.all make -f Makefile.coq.all make[1]: Entering directory '/home/jgross/Documents/GitHub/coqutil' ROCQ DEP VFILES make[1]: Leaving directory '/home/jgross/Documents/GitHub/coqutil' ROCQ compile $PWD/src/coqutil/Byte.v ROCQ compile $PWD/src/coqutil/sanity.v ROCQ compile $PWD/src/coqutil/Tactics/autoforward.v ROCQ compile $PWD/src/coqutil/dlet.v ROCQ compile $PWD/src/coqutil/Ltac2Lib/Constr.v ROCQ compile $PWD/src/coqutil/Ltac2Lib/Msg.v $PWD/src/coqutil/dlet.vo (real: 0.08, user: 0.06, sys: 0.01, mem: 63768 ko) COQNATIVE $PWD/src/coqutil/dlet.vo $PWD/src/coqutil/Tactics/autoforward.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 64908 ko) $PWD/src/coqutil/sanity.vo (real: 0.09, user: 0.06, sys: 0.02, mem: 64964 ko) COQNATIVE $PWD/src/coqutil/Tactics/autoforward.vo COQNATIVE $PWD/src/coqutil/sanity.vo $PWD/src/coqutil/Ltac2Lib/Msg.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 69124 ko) COQNATIVE $PWD/src/coqutil/Ltac2Lib/Msg.vo $PWD/src/coqutil/Ltac2Lib/Constr.vo (real: 0.09, user: 0.04, sys: 0.04, mem: 71420 ko) COQNATIVE $PWD/src/coqutil/Ltac2Lib/Constr.vo $PWD/src/coqutil/Ltac2Lib/Msg.vo.native (real: 0.16, user: 0.06, sys: 0.02, mem: 23220 ko) ROCQ compile $PWD/src/coqutil/Ltac2Lib/Log.v $PWD/src/coqutil/dlet.vo.native (real: 0.18, user: 0.07, sys: 0.01, mem: 21888 ko) $PWD/src/coqutil/Tactics/autoforward.vo.native (real: 0.17, user: 0.07, sys: 0.01, mem: 22004 ko) $PWD/src/coqutil/sanity.vo.native (real: 0.17, user: 0.04, sys: 0.04, mem: 21960 ko) $PWD/src/coqutil/Ltac2Lib/Constr.vo.native (real: 0.17, user: 0.07, sys: 0.01, mem: 23256 ko) ROCQ compile $PWD/src/coqutil/Macros/unique.v ROCQ compile $PWD/src/coqutil/Macros/subst.v ROCQ compile $PWD/src/coqutil/Macros/ident_to_string.v ROCQ compile $PWD/src/coqutil/Tactics/forward.v $PWD/src/coqutil/Macros/unique.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 63500 ko) $PWD/src/coqutil/Macros/subst.vo (real: 0.09, user: 0.05, sys: 0.03, mem: 63844 ko) COQNATIVE $PWD/src/coqutil/Macros/unique.vo COQNATIVE $PWD/src/coqutil/Macros/subst.vo $PWD/src/coqutil/Tactics/forward.vo (real: 0.10, user: 0.05, sys: 0.04, mem: 68064 ko) $PWD/src/coqutil/Ltac2Lib/Log.vo (real: 0.11, user: 0.08, sys: 0.03, mem: 71232 ko) COQNATIVE $PWD/src/coqutil/Tactics/forward.vo COQNATIVE $PWD/src/coqutil/Ltac2Lib/Log.vo $PWD/src/coqutil/Macros/subst.vo.native (real: 0.18, user: 0.10, sys: 0.01, mem: 22064 ko) $PWD/src/coqutil/Macros/unique.vo.native (real: 0.18, user: 0.10, sys: 0.01, mem: 21952 ko) $PWD/src/coqutil/Tactics/forward.vo.native (real: 0.17, user: 0.08, sys: 0.01, mem: 22228 ko) ROCQ compile $PWD/src/coqutil/Z/Lia.v ROCQ compile $PWD/src/coqutil/Datatypes/Option.v ROCQ compile $PWD/src/coqutil/Sorting/Permutation.v $PWD/src/coqutil/Byte.vo (real: 0.59, user: 0.32, sys: 0.10, mem: 345240 ko) COQNATIVE $PWD/src/coqutil/Byte.vo $PWD/src/coqutil/Ltac2Lib/Log.vo.native (real: 0.21, user: 0.11, sys: 0.01, mem: 23276 ko) ROCQ compile $PWD/src/coqutil/Datatypes/PrimitivePair.v $PWD/src/coqutil/Macros/ident_to_string.vo (real: 0.33, user: 0.23, sys: 0.08, mem: 227492 ko) COQNATIVE $PWD/src/coqutil/Macros/ident_to_string.vo $PWD/src/coqutil/Datatypes/PrimitivePair.vo (real: 0.10, user: 0.06, sys: 0.03, mem: 66532 ko) COQNATIVE $PWD/src/coqutil/Datatypes/PrimitivePair.vo $PWD/src/coqutil/Datatypes/Option.vo (real: 0.15, user: 0.14, sys: 0.01, mem: 109820 ko) COQNATIVE $PWD/src/coqutil/Datatypes/Option.vo $PWD/src/coqutil/Sorting/Permutation.vo (real: 0.20, user: 0.17, sys: 0.03, mem: 138328 ko) COQNATIVE $PWD/src/coqutil/Sorting/Permutation.vo $PWD/src/coqutil/Datatypes/PrimitivePair.vo.native (real: 0.19, user: 0.06, sys: 0.03, mem: 22040 ko) ROCQ compile $PWD/src/coqutil/Word/Interface.v $PWD/src/coqutil/Datatypes/Option.vo.native (real: 0.43, user: 0.26, sys: 0.07, mem: 27288 ko) ROCQ compile $PWD/src/coqutil/Datatypes/Prod.v $PWD/src/coqutil/Z/Lia.vo (real: 0.60, user: 0.39, sys: 0.06, mem: 291400 ko) COQNATIVE $PWD/src/coqutil/Z/Lia.vo $PWD/src/coqutil/Sorting/Permutation.vo.native (real: 0.40, user: 0.24, sys: 0.05, mem: 56896 ko) ROCQ compile $PWD/src/coqutil/Z/div_mod_to_equations.v $PWD/src/coqutil/Macros/ident_to_string.vo.native (real: 0.67, user: 0.48, sys: 0.06, mem: 87324 ko) ROCQ compile $PWD/src/coqutil/Z/PushPullMod.v $PWD/src/coqutil/Datatypes/Prod.vo (real: 0.13, user: 0.08, sys: 0.04, mem: 94084 ko) COQNATIVE $PWD/src/coqutil/Datatypes/Prod.vo $PWD/src/coqutil/Byte.vo.native (real: 0.74, user: 0.53, sys: 0.07, mem: 100712 ko) ROCQ compile $PWD/src/coqutil/Tactics/fwd_bool_hints.v $PWD/src/coqutil/Word/Interface.vo (real: 0.43, user: 0.32, sys: 0.10, mem: 329896 ko) COQNATIVE $PWD/src/coqutil/Word/Interface.vo $PWD/src/coqutil/Tactics/fwd_bool_hints.vo (real: 0.10, user: 0.07, sys: 0.02, mem: 65820 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_bool_hints.vo $PWD/src/coqutil/Z/div_mod_to_equations.vo (real: 0.29, user: 0.24, sys: 0.04, mem: 208528 ko) COQNATIVE $PWD/src/coqutil/Z/div_mod_to_equations.vo $PWD/src/coqutil/Tactics/fwd_bool_hints.vo.native (real: 0.20, user: 0.09, sys: 0.01, mem: 22416 ko) ROCQ compile $PWD/src/coqutil/Tactics/eabstract.v $PWD/src/coqutil/Tactics/eabstract.vo (real: 0.11, user: 0.08, sys: 0.03, mem: 63624 ko) COQNATIVE $PWD/src/coqutil/Tactics/eabstract.vo $PWD/src/coqutil/Datatypes/Prod.vo.native (real: 0.47, user: 0.27, sys: 0.08, mem: 29464 ko) ROCQ compile $PWD/src/coqutil/Tactics/fwd_arith_hints.v $PWD/src/coqutil/Z/Lia.vo.native (real: 0.68, user: 0.52, sys: 0.05, mem: 99996 ko) ROCQ compile $PWD/src/coqutil/Tactics/simpl_rewrite.v $PWD/src/coqutil/Tactics/simpl_rewrite.vo (real: 0.13, user: 0.09, sys: 0.04, mem: 65792 ko) COQNATIVE $PWD/src/coqutil/Tactics/simpl_rewrite.vo $PWD/src/coqutil/Tactics/eabstract.vo.native (real: 0.25, user: 0.08, sys: 0.03, mem: 22032 ko) ROCQ compile $PWD/src/coqutil/Tactics/rdelta.v $PWD/src/coqutil/Z/div_mod_to_equations.vo.native (real: 0.63, user: 0.36, sys: 0.14, mem: 77596 ko) ROCQ compile $PWD/src/coqutil/Tactics/syntactic_unify.v $PWD/src/coqutil/Tactics/rdelta.vo (real: 0.14, user: 0.08, sys: 0.05, mem: 63820 ko) COQNATIVE $PWD/src/coqutil/Tactics/rdelta.vo $PWD/src/coqutil/Tactics/fwd_arith_hints.vo (real: 0.40, user: 0.31, sys: 0.09, mem: 214876 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_arith_hints.vo $PWD/src/coqutil/Tactics/syntactic_unify.vo (real: 0.14, user: 0.06, sys: 0.08, mem: 65768 ko) COQNATIVE $PWD/src/coqutil/Tactics/syntactic_unify.vo $PWD/src/coqutil/Tactics/simpl_rewrite.vo.native (real: 0.29, user: 0.06, sys: 0.06, mem: 22100 ko) ROCQ compile $PWD/src/coqutil/Tactics/ident_of_string.v $PWD/src/coqutil/Tactics/rdelta.vo.native (real: 0.23, user: 0.06, sys: 0.05, mem: 22076 ko) ROCQ compile $PWD/src/coqutil/Tactics/ParamRecords.v $PWD/src/coqutil/Tactics/syntactic_unify.vo.native (real: 0.21, user: 0.08, sys: 0.02, mem: 22092 ko) ROCQ compile $PWD/src/coqutil/Tactics/eplace.v $PWD/src/coqutil/Word/Interface.vo.native (real: 1.19, user: 0.94, sys: 0.12, mem: 78484 ko) ROCQ compile $PWD/src/coqutil/Tactics/letexists.v $PWD/src/coqutil/Tactics/ParamRecords.vo (real: 0.13, user: 0.10, sys: 0.02, mem: 73372 ko) COQNATIVE $PWD/src/coqutil/Tactics/ParamRecords.vo $PWD/src/coqutil/Z/PushPullMod.vo (real: 1.27, user: 1.03, sys: 0.09, mem: 407636 ko) COQNATIVE $PWD/src/coqutil/Z/PushPullMod.vo $PWD/src/coqutil/Tactics/eplace.vo (real: 0.12, user: 0.10, sys: 0.00, mem: 79672 ko) COQNATIVE $PWD/src/coqutil/Tactics/eplace.vo $PWD/src/coqutil/Tactics/letexists.vo (real: 0.09, user: 0.06, sys: 0.02, mem: 64172 ko) COQNATIVE $PWD/src/coqutil/Tactics/letexists.vo $PWD/src/coqutil/Tactics/eplace.vo.native (real: 0.16, user: 0.07, sys: 0.02, mem: 22100 ko) ROCQ compile $PWD/src/coqutil/Tactics/Simp.v $PWD/src/coqutil/Tactics/ParamRecords.vo.native (real: 0.22, user: 0.04, sys: 0.06, mem: 23244 ko) ROCQ compile $PWD/src/coqutil/Z/div_to_equations.v $PWD/src/coqutil/Tactics/fwd_arith_hints.vo.native (real: 0.59, user: 0.48, sys: 0.04, mem: 79096 ko) ROCQ compile $PWD/src/coqutil/Decidable.v $PWD/src/coqutil/Tactics/letexists.vo.native (real: 0.19, user: 0.05, sys: 0.04, mem: 22024 ko) ROCQ compile $PWD/src/coqutil/Macros/symmetry.v $PWD/src/coqutil/Macros/symmetry.vo (real: 0.12, user: 0.09, sys: 0.02, mem: 73944 ko) COQNATIVE $PWD/src/coqutil/Macros/symmetry.vo $PWD/src/coqutil/Z/div_to_equations.vo (real: 0.32, user: 0.18, sys: 0.13, mem: 201096 ko) COQNATIVE $PWD/src/coqutil/Z/div_to_equations.vo $PWD/src/coqutil/Macros/symmetry.vo.native (real: 0.24, user: 0.10, sys: 0.01, mem: 22936 ko) ROCQ compile $PWD/src/coqutil/Datatypes/HList.v $PWD/src/coqutil/Decidable.vo (real: 0.44, user: 0.35, sys: 0.08, mem: 269884 ko) COQNATIVE $PWD/src/coqutil/Decidable.vo $PWD/src/coqutil/Z/PushPullMod.vo.native (real: 0.70, user: 0.53, sys: 0.05, mem: 100992 ko) ROCQ compile $PWD/src/coqutil/Datatypes/ToConversion.v $PWD/src/coqutil/Tactics/Simp.vo (real: 0.66, user: 0.32, sys: 0.18, mem: 293652 ko) COQNATIVE $PWD/src/coqutil/Tactics/Simp.vo $PWD/src/coqutil/Datatypes/HList.vo (real: 0.24, user: 0.21, sys: 0.03, mem: 174320 ko) COQNATIVE $PWD/src/coqutil/Datatypes/HList.vo $PWD/src/coqutil/Z/div_to_equations.vo.native (real: 0.64, user: 0.47, sys: 0.05, mem: 78704 ko) ROCQ compile $PWD/src/coqutil/Word/Bitwidth.v $PWD/src/coqutil/Datatypes/ToConversion.vo (real: 0.65, user: 0.34, sys: 0.14, mem: 301660 ko) COQNATIVE $PWD/src/coqutil/Datatypes/ToConversion.vo $PWD/src/coqutil/Decidable.vo.native (real: 0.72, user: 0.50, sys: 0.10, mem: 88688 ko) ROCQ compile $PWD/src/coqutil/Z/bitblast.v $PWD/src/coqutil/Tactics/Simp.vo.native (real: 0.73, user: 0.51, sys: 0.12, mem: 100544 ko) ROCQ compile $PWD/src/coqutil/Z/ZLib.v $PWD/src/coqutil/Datatypes/HList.vo.native (real: 0.75, user: 0.57, sys: 0.08, mem: 54340 ko) ROCQ compile $PWD/src/coqutil/Tactics/ltac_list_ops.v $PWD/src/coqutil/Tactics/ltac_list_ops.vo (real: 0.13, user: 0.07, sys: 0.05, mem: 65508 ko) COQNATIVE $PWD/src/coqutil/Tactics/ltac_list_ops.vo $PWD/src/coqutil/Word/Bitwidth.vo (real: 0.61, user: 0.31, sys: 0.15, mem: 291312 ko) COQNATIVE $PWD/src/coqutil/Word/Bitwidth.vo $PWD/src/coqutil/Tactics/ltac_list_ops.vo.native (real: 0.20, user: 0.10, sys: 0.01, mem: 22032 ko) ROCQ compile $PWD/src/coqutil/Tactics/destr.v $PWD/src/coqutil/Datatypes/ToConversion.vo.native (real: 0.65, user: 0.46, sys: 0.10, mem: 100708 ko) ROCQ compile $PWD/src/coqutil/Datatypes/String.v $PWD/src/coqutil/Tactics/destr.vo (real: 0.39, user: 0.21, sys: 0.18, mem: 221288 ko) COQNATIVE $PWD/src/coqutil/Tactics/destr.vo $PWD/src/coqutil/Z/bitblast.vo (real: 1.15, user: 0.92, sys: 0.07, mem: 414256 ko) COQNATIVE $PWD/src/coqutil/Z/bitblast.vo $PWD/src/coqutil/Datatypes/String.vo (real: 0.54, user: 0.40, sys: 0.14, mem: 352920 ko) COQNATIVE $PWD/src/coqutil/Datatypes/String.vo $PWD/src/coqutil/Word/Bitwidth.vo.native (real: 0.76, user: 0.55, sys: 0.08, mem: 101296 ko) ROCQ compile $PWD/src/coqutil/Tactics/Records.v $PWD/src/coqutil/Z/ZLib.vo (real: 1.09, user: 0.78, sys: 0.16, mem: 408248 ko) COQNATIVE $PWD/src/coqutil/Z/ZLib.vo $PWD/src/coqutil/Tactics/Records.vo (real: 0.20, user: 0.17, sys: 0.03, mem: 149096 ko) COQNATIVE $PWD/src/coqutil/Tactics/Records.vo $PWD/src/coqutil/Tactics/destr.vo.native (real: 0.67, user: 0.51, sys: 0.05, mem: 88936 ko) ROCQ compile $PWD/src/coqutil/Tactics/Tactics.v $PWD/src/coqutil/Tactics/Records.vo.native (real: 0.43, user: 0.23, sys: 0.09, mem: 54316 ko) ROCQ compile $PWD/src/coqutil/Word/Bitwidth32.v $PWD/src/coqutil/Datatypes/String.vo.native (real: 0.69, user: 0.49, sys: 0.09, mem: 87608 ko) $PWD/src/coqutil/Z/bitblast.vo.native (real: 0.71, user: 0.56, sys: 0.05, mem: 103836 ko) ROCQ compile $PWD/src/coqutil/Word/Bitwidth64.v ROCQ compile $PWD/src/coqutil/Tactics/fwd_core.v $PWD/src/coqutil/Z/ZLib.vo.native (real: 0.71, user: 0.48, sys: 0.12, mem: 100668 ko) ROCQ compile $PWD/src/coqutil/Word/Properties.v $PWD/src/coqutil/Tactics/fwd_core.vo (real: 0.34, user: 0.27, sys: 0.06, mem: 240248 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_core.vo $PWD/src/coqutil/Tactics/Tactics.vo (real: 0.60, user: 0.36, sys: 0.07, mem: 295528 ko) COQNATIVE $PWD/src/coqutil/Tactics/Tactics.vo $PWD/src/coqutil/Word/Bitwidth32.vo (real: 0.63, user: 0.37, sys: 0.08, mem: 292180 ko) COQNATIVE $PWD/src/coqutil/Word/Bitwidth32.vo $PWD/src/coqutil/Word/Bitwidth64.vo (real: 0.63, user: 0.36, sys: 0.10, mem: 291996 ko) COQNATIVE $PWD/src/coqutil/Word/Bitwidth64.vo $PWD/src/coqutil/Tactics/fwd_core.vo.native (real: 0.67, user: 0.49, sys: 0.08, mem: 87980 ko) ROCQ compile $PWD/src/coqutil/Z/BitOps.v $PWD/src/coqutil/Tactics/Tactics.vo.native (real: 0.69, user: 0.51, sys: 0.07, mem: 100016 ko) ROCQ compile $PWD/src/coqutil/Datatypes/PropSet.v $PWD/src/coqutil/Word/Bitwidth32.vo.native (real: 0.78, user: 0.55, sys: 0.09, mem: 101360 ko) ROCQ compile $PWD/src/coqutil/Datatypes/List.v $PWD/src/coqutil/Word/Bitwidth64.vo.native (real: 0.80, user: 0.50, sys: 0.13, mem: 102472 ko) ROCQ compile $PWD/src/coqutil/Tactics/SafeSimpl.v $PWD/src/coqutil/Tactics/SafeSimpl.vo (real: 0.79, user: 0.41, sys: 0.18, mem: 278808 ko) COQNATIVE $PWD/src/coqutil/Tactics/SafeSimpl.vo $PWD/src/coqutil/Tactics/ident_of_string.vo (real: 6.32, user: 6.20, sys: 0.11, mem: 444256 ko) COQNATIVE $PWD/src/coqutil/Tactics/ident_of_string.vo $PWD/src/coqutil/Z/BitOps.vo (real: 1.76, user: 1.39, sys: 0.19, mem: 416228 ko) COQNATIVE $PWD/src/coqutil/Z/BitOps.vo $PWD/src/coqutil/Tactics/SafeSimpl.vo.native (real: 0.87, user: 0.69, sys: 0.07, mem: 102576 ko) $PWD/src/coqutil/Tactics/ident_of_string.vo.native (real: 0.77, user: 0.56, sys: 0.08, mem: 88000 ko) $PWD/src/coqutil/Z/BitOps.vo.native (real: 0.80, user: 0.63, sys: 0.05, mem: 102316 ko) ROCQ compile $PWD/src/coqutil/Z/prove_Zeq_bitwise.v $PWD/src/coqutil/Datatypes/PropSet.vo (real: 2.52, user: 2.23, sys: 0.17, mem: 406924 ko) COQNATIVE $PWD/src/coqutil/Datatypes/PropSet.vo $PWD/src/coqutil/Z/prove_Zeq_bitwise.vo (real: 0.84, user: 0.58, sys: 0.10, mem: 413136 ko) COQNATIVE $PWD/src/coqutil/Z/prove_Zeq_bitwise.vo $PWD/src/coqutil/Datatypes/PropSet.vo.native (real: 0.82, user: 0.61, sys: 0.08, mem: 101844 ko) $PWD/src/coqutil/Z/prove_Zeq_bitwise.vo.native (real: 0.56, user: 0.42, sys: 0.06, mem: 102696 ko) File "$PWD/src/coqutil/Datatypes/List.v", line 1021, characters 37-53: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1021, characters 37-53: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1021, characters 37-53: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1040, characters 34-50: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1040, characters 34-50: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1040, characters 34-50: Warning: Notation Minus.minus_plus is deprecated since 8.16. The Arith.Minus file is obsolete. Use Nat.add_sub (together with Nat.add_com) instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1789, characters 13-26: Warning: Notation Zdiv.div_Zdiv is deprecated since 8.14. Use Nat2Z.inj_div instead. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Datatypes/List.v", line 1789, characters 29-42: Warning: Notation Zdiv.mod_Zmod is deprecated since 8.14. Use Nat2Z.inj_mod instead. [deprecated-syntactic-definition,deprecated] $PWD/src/coqutil/Datatypes/List.vo (real: 5.28, user: 4.85, sys: 0.24, mem: 434980 ko) COQNATIVE $PWD/src/coqutil/Datatypes/List.vo $PWD/src/coqutil/Datatypes/List.vo.native (real: 0.72, user: 0.57, sys: 0.07, mem: 99024 ko) ROCQ compile $PWD/src/coqutil/Datatypes/ListSet.v ROCQ compile $PWD/src/coqutil/Map/Interface.v ROCQ compile $PWD/src/coqutil/Tactics/rewr.v ROCQ compile $PWD/src/coqutil/Tactics/fwd_list_hints.v ROCQ compile $PWD/src/coqutil/Sorting/OrderToPermutation.v $PWD/src/coqutil/Tactics/fwd_list_hints.vo (real: 0.64, user: 0.36, sys: 0.15, mem: 274956 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_list_hints.vo $PWD/src/coqutil/Sorting/OrderToPermutation.vo (real: 0.71, user: 0.43, sys: 0.16, mem: 317964 ko) COQNATIVE $PWD/src/coqutil/Sorting/OrderToPermutation.vo $PWD/src/coqutil/Map/Interface.vo (real: 0.73, user: 0.44, sys: 0.14, mem: 326076 ko) $PWD/src/coqutil/Tactics/rewr.vo (real: 0.73, user: 0.42, sys: 0.15, mem: 299108 ko) COQNATIVE $PWD/src/coqutil/Map/Interface.vo COQNATIVE $PWD/src/coqutil/Tactics/rewr.vo $PWD/src/coqutil/Datatypes/ListSet.vo (real: 1.29, user: 0.97, sys: 0.15, mem: 415948 ko) COQNATIVE $PWD/src/coqutil/Datatypes/ListSet.vo $PWD/src/coqutil/Word/Properties.vo (real: 8.70, user: 8.38, sys: 0.18, mem: 575776 ko) COQNATIVE $PWD/src/coqutil/Word/Properties.vo $PWD/src/coqutil/Tactics/fwd_list_hints.vo.native (real: 0.87, user: 0.62, sys: 0.11, mem: 101924 ko) $PWD/src/coqutil/Tactics/rewr.vo.native (real: 0.88, user: 0.62, sys: 0.11, mem: 101904 ko) $PWD/src/coqutil/Sorting/OrderToPermutation.vo.native (real: 1.11, user: 0.89, sys: 0.09, mem: 101560 ko) $PWD/src/coqutil/Map/Interface.vo.native (real: 1.29, user: 1.05, sys: 0.11, mem: 102644 ko) ROCQ compile $PWD/src/coqutil/Datatypes/Inhabited.v ROCQ compile $PWD/src/coqutil/Map/Properties.v ROCQ compile $PWD/src/coqutil/Map/SortedList.v ROCQ compile $PWD/src/coqutil/Map/Empty_set_keyed_map.v $PWD/src/coqutil/Datatypes/ListSet.vo.native (real: 0.91, user: 0.66, sys: 0.09, mem: 101836 ko) ROCQ compile $PWD/src/coqutil/Map/Funext.v $PWD/src/coqutil/Word/Properties.vo.native (real: 0.87, user: 0.66, sys: 0.08, mem: 103320 ko) ROCQ compile $PWD/src/coqutil/Word/LittleEndianList.v $PWD/src/coqutil/Datatypes/Inhabited.vo (real: 0.77, user: 0.51, sys: 0.10, mem: 284324 ko) COQNATIVE $PWD/src/coqutil/Datatypes/Inhabited.vo $PWD/src/coqutil/Map/Empty_set_keyed_map.vo (real: 0.79, user: 0.57, sys: 0.07, mem: 288536 ko) COQNATIVE $PWD/src/coqutil/Map/Empty_set_keyed_map.vo $PWD/src/coqutil/Map/Funext.vo (real: 1.01, user: 0.57, sys: 0.18, mem: 311552 ko) COQNATIVE $PWD/src/coqutil/Map/Funext.vo $PWD/src/coqutil/Map/SortedList.vo (real: 1.60, user: 1.28, sys: 0.18, mem: 418272 ko) COQNATIVE $PWD/src/coqutil/Map/SortedList.vo $PWD/src/coqutil/Map/Empty_set_keyed_map.vo.native (real: 1.08, user: 0.84, sys: 0.11, mem: 103096 ko) ROCQ compile $PWD/src/coqutil/Word/BigEndian.v $PWD/src/coqutil/Datatypes/Inhabited.vo.native (real: 1.13, user: 0.85, sys: 0.14, mem: 101692 ko) ROCQ compile $PWD/src/coqutil/Word/DebugWordEq.v $PWD/src/coqutil/Map/Funext.vo.native (real: 1.03, user: 0.80, sys: 0.08, mem: 102372 ko) ROCQ compile $PWD/src/coqutil/Word/Naive.v $PWD/src/coqutil/Map/SortedList.vo.native (real: 1.16, user: 0.88, sys: 0.15, mem: 102424 ko) ROCQ compile $PWD/src/coqutil/Word/SimplWordExpr.v $PWD/src/coqutil/Word/DebugWordEq.vo (real: 0.86, user: 0.50, sys: 0.17, mem: 361320 ko) COQNATIVE $PWD/src/coqutil/Word/DebugWordEq.vo $PWD/src/coqutil/Word/LittleEndianList.vo (real: 2.85, user: 2.50, sys: 0.14, mem: 421756 ko) COQNATIVE $PWD/src/coqutil/Word/LittleEndianList.vo $PWD/src/coqutil/Word/Naive.vo (real: 1.14, user: 0.78, sys: 0.17, mem: 412576 ko) COQNATIVE $PWD/src/coqutil/Word/Naive.vo $PWD/src/coqutil/Word/DebugWordEq.vo.native (real: 0.79, user: 0.58, sys: 0.08, mem: 103300 ko) ROCQ compile $PWD/src/coqutil/Tactics/fwd_word_hints.v $PWD/src/coqutil/Word/SimplWordExpr.vo (real: 0.93, user: 0.64, sys: 0.13, mem: 419144 ko) COQNATIVE $PWD/src/coqutil/Word/SimplWordExpr.vo $PWD/src/coqutil/Word/BigEndian.vo (real: 1.82, user: 1.45, sys: 0.18, mem: 417760 ko) COQNATIVE $PWD/src/coqutil/Word/BigEndian.vo $PWD/src/coqutil/Word/LittleEndianList.vo.native (real: 0.85, user: 0.63, sys: 0.11, mem: 104004 ko) ROCQ compile $PWD/src/coqutil/Map/SortedListString.v $PWD/src/coqutil/Tactics/fwd_word_hints.vo (real: 0.66, user: 0.40, sys: 0.07, mem: 310528 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_word_hints.vo $PWD/src/coqutil/Word/Naive.vo.native (real: 0.99, user: 0.69, sys: 0.17, mem: 102316 ko) ROCQ compile $PWD/src/coqutil/Map/SortedListWord.v $PWD/src/coqutil/Word/SimplWordExpr.vo.native (real: 0.78, user: 0.55, sys: 0.11, mem: 104148 ko) ROCQ compile $PWD/src/coqutil/Map/Z_keyed_SortedListMap.v $PWD/src/coqutil/Word/BigEndian.vo.native (real: 0.82, user: 0.59, sys: 0.10, mem: 103836 ko) ROCQ compile $PWD/src/coqutil/Datatypes/OperatorOverloading.v $PWD/src/coqutil/Map/SortedListString.vo (real: 0.68, user: 0.39, sys: 0.08, mem: 279768 ko) COQNATIVE $PWD/src/coqutil/Map/SortedListString.vo $PWD/src/coqutil/Tactics/fwd_word_hints.vo.native (real: 0.99, user: 0.73, sys: 0.11, mem: 104180 ko) ROCQ compile $PWD/src/coqutil/Word/LittleEndian.v $PWD/src/coqutil/Map/SortedListWord.vo (real: 0.92, user: 0.50, sys: 0.23, mem: 363816 ko) COQNATIVE $PWD/src/coqutil/Map/SortedListWord.vo $PWD/src/coqutil/Map/Z_keyed_SortedListMap.vo (real: 0.90, user: 0.58, sys: 0.12, mem: 319092 ko) COQNATIVE $PWD/src/coqutil/Map/Z_keyed_SortedListMap.vo $PWD/src/coqutil/Map/SortedListString.vo.native (real: 1.00, user: 0.72, sys: 0.16, mem: 103220 ko) ROCQ compile $PWD/src/coqutil/Map/SortedListString_test.v $PWD/src/coqutil/Datatypes/OperatorOverloading.vo (real: 1.53, user: 1.09, sys: 0.24, mem: 415560 ko) COQNATIVE $PWD/src/coqutil/Datatypes/OperatorOverloading.vo $PWD/src/coqutil/Map/SortedListWord.vo.native (real: 0.92, user: 0.62, sys: 0.15, mem: 104040 ko) $PWD/src/coqutil/Map/Z_keyed_SortedListMap.vo.native (real: 1.08, user: 0.72, sys: 0.15, mem: 103964 ko) $PWD/src/coqutil/Map/SortedListString_test.vo (real: 0.80, user: 0.47, sys: 0.13, mem: 312492 ko) COQNATIVE $PWD/src/coqutil/Map/SortedListString_test.vo $PWD/src/coqutil/Map/Properties.vo (real: 6.71, user: 6.40, sys: 0.16, mem: 452836 ko) COQNATIVE $PWD/src/coqutil/Map/Properties.vo $PWD/src/coqutil/Word/LittleEndian.vo (real: 1.93, user: 1.65, sys: 0.12, mem: 420928 ko) COQNATIVE $PWD/src/coqutil/Word/LittleEndian.vo $PWD/src/coqutil/Datatypes/OperatorOverloading.vo.native (real: 1.25, user: 0.95, sys: 0.17, mem: 103212 ko) $PWD/src/coqutil/Map/SortedListString_test.vo.native (real: 0.82, user: 0.60, sys: 0.08, mem: 103528 ko) $PWD/src/coqutil/Map/Properties.vo.native (real: 0.96, user: 0.77, sys: 0.08, mem: 100032 ko) ROCQ compile $PWD/src/coqutil/Tactics/fwd_map_hints.v ROCQ compile $PWD/src/coqutil/Map/Solver.v ROCQ compile $PWD/src/coqutil/Map/MapKeys.v $PWD/src/coqutil/Word/LittleEndian.vo.native (real: 0.80, user: 0.60, sys: 0.08, mem: 104064 ko) ROCQ compile $PWD/src/coqutil/Word/ZifyLittleEndian.v $PWD/src/coqutil/Tactics/fwd_map_hints.vo (real: 0.50, user: 0.33, sys: 0.06, mem: 283128 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd_map_hints.vo $PWD/src/coqutil/Map/MapKeys.vo (real: 0.61, user: 0.43, sys: 0.08, mem: 392964 ko) COQNATIVE $PWD/src/coqutil/Map/MapKeys.vo $PWD/src/coqutil/Map/Solver.vo (real: 0.62, user: 0.39, sys: 0.08, mem: 304396 ko) COQNATIVE $PWD/src/coqutil/Map/Solver.vo $PWD/src/coqutil/Tactics/fwd_map_hints.vo.native (real: 0.70, user: 0.46, sys: 0.09, mem: 102724 ko) ROCQ compile $PWD/src/coqutil/Tactics/fwd.v File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 11, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 11, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 15, characters 9-29: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 21, characters 47-67: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 25, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 25, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 29, characters 9-29: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 35, characters 47-67: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 39, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 39, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 43, characters 9-29: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 49, characters 47-67: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 53, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 53, characters 41-61: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 57, characters 9-29: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 63, characters 47-67: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 82, characters 4-24: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 82, characters 43-63: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 83, characters 4-24: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 83, characters 43-63: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 84, characters 4-24: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 84, characters 43-63: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 85, characters 4-24: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] File "$PWD/src/coqutil/Word/ZifyLittleEndian.v", line 85, characters 43-63: Warning: Notation combine is deprecated. Use coqutil.Word.LittleEndianList.le_combine. [deprecated-syntactic-definition,deprecated] $PWD/src/coqutil/Word/ZifyLittleEndian.vo (real: 0.94, user: 0.74, sys: 0.08, mem: 419828 ko) COQNATIVE $PWD/src/coqutil/Word/ZifyLittleEndian.vo $PWD/src/coqutil/Map/MapKeys.vo.native (real: 0.67, user: 0.45, sys: 0.11, mem: 101768 ko) ROCQ compile $PWD/src/coqutil/Map/OfFunc.v $PWD/src/coqutil/Map/Solver.vo.native (real: 0.80, user: 0.63, sys: 0.06, mem: 104700 ko) ROCQ compile $PWD/src/coqutil/Map/SlowGoals.v ROCQ compile $PWD/src/coqutil/Map/TestGoals.v ROCQ compile $PWD/src/coqutil/Map/MapEauto.v $PWD/src/coqutil/Tactics/fwd.vo (real: 0.66, user: 0.38, sys: 0.10, mem: 297656 ko) COQNATIVE $PWD/src/coqutil/Tactics/fwd.vo $PWD/src/coqutil/Word/ZifyLittleEndian.vo.native (real: 0.85, user: 0.66, sys: 0.05, mem: 104132 ko) $PWD/src/coqutil/Map/OfFunc.vo (real: 1.05, user: 0.75, sys: 0.12, mem: 417728 ko) COQNATIVE $PWD/src/coqutil/Map/OfFunc.vo $PWD/src/coqutil/Tactics/fwd.vo.native (real: 0.95, user: 0.64, sys: 0.16, mem: 104208 ko) $PWD/src/coqutil/Map/OfFunc.vo.native (real: 0.78, user: 0.63, sys: 0.06, mem: 101324 ko) ROCQ compile $PWD/src/coqutil/Map/OfListWord.v $PWD/src/coqutil/Map/MapEauto.vo (real: 2.65, user: 2.22, sys: 0.23, mem: 420764 ko) COQNATIVE $PWD/src/coqutil/Map/MapEauto.vo $PWD/src/coqutil/Map/OfListWord.vo (real: 1.03, user: 0.74, sys: 0.12, mem: 421844 ko) COQNATIVE $PWD/src/coqutil/Map/OfListWord.vo $PWD/src/coqutil/Map/MapEauto.vo.native (real: 0.69, user: 0.46, sys: 0.11, mem: 101892 ko) $PWD/src/coqutil/Map/OfListWord.vo.native (real: 0.75, user: 0.56, sys: 0.07, mem: 104332 ko) Finished transaction in 4.513 secs (4.448u,0.065s) (successful) Finished transaction in 0.014 secs (0.013u,0.s) (successful) $PWD/src/coqutil/Map/SlowGoals.vo (real: 5.25, user: 4.95, sys: 0.18, mem: 413708 ko) COQNATIVE $PWD/src/coqutil/Map/SlowGoals.vo $PWD/src/coqutil/Map/SlowGoals.vo.native (real: 0.52, user: 0.36, sys: 0.07, mem: 101432 ko) Finished transaction in 0.046 secs (0.026u,0.019s) (successful) Finished transaction in 0.207 secs (0.125u,0.082s) (successful) Part 1a: Small goals (originally took <5s each) Finished transaction in 0.087 secs (0.087u,0.s) (successful) Finished transaction in 0.156 secs (0.156u,0.s) (successful) Finished transaction in 1.197 secs (1.188u,0.s) (successful) Finished transaction in 1.63 secs (1.63u,0.s) (successful) Finished transaction in 1.229 secs (1.225u,0.004s) (successful) Finished transaction in 0.761 secs (0.761u,0.s) (successful) Finished transaction in 0.762 secs (0.762u,0.s) (successful) Finished transaction in 0.685 secs (0.685u,0.s) (successful) Finished transaction in 0.082 secs (0.082u,0.s) (successful) Part 1b: Medium goals (originally took >5s each) Finished transaction in 0.524 secs (0.524u,0.s) (successful) Finished transaction in 1.414 secs (1.414u,0.s) (successful) Finished transaction in 1.143 secs (1.142u,0.s) (successful) Finished transaction in 0.718 secs (0.718u,0.s) (successful) Finished transaction in 0.73 secs (0.73u,0.s) (successful) Finished transaction in 1.299 secs (1.299u,0.s) (successful) Finished transaction in 1.242 secs (1.242u,0.s) (successful) Part 1c: Large goals (originally took >50s each) Finished transaction in 1.681 secs (1.681u,0.s) (successful) $PWD/src/coqutil/Map/TestGoals.vo (real: 16.41, user: 16.08, sys: 0.20, mem: 435484 ko) COQNATIVE $PWD/src/coqutil/Map/TestGoals.vo $PWD/src/coqutil/Map/TestGoals.vo.native (real: 0.43, user: 0.34, sys: 0.02, mem: 102636 ko) rocq-9.2.0/test-suite/precomputed-time-tests/template/000077500000000000000000000000001516144147600230435ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/template/init.sh000066400000000000000000000011321516144147600243370ustar00rootroot00000000000000#!/usr/bin/env bash set -x set -e set -o pipefail export PATH="$COQBIN:$PATH" export LC_ALL=C # tools TTOOLSDIR="$COQPREFIX/lib/rocq-runtime/tools" export make_both_time_files="$TTOOLSDIR"/make-both-time-files.py export make_one_time_file="$TTOOLSDIR"/make-one-time-file.py export make_both_single_timing_files="$TTOOLSDIR"/make-both-single-timing-files.py # native stack overflows too easily, see eg # https://gitlab.com/coq/coq/-/jobs/3250939810 export COQEXTRAFLAGS='-native-compiler no' # reset MAKEFLAGS so that, e.g., `make -C test-suite -B coq-makefile` doesn't give us issues MAKEFLAGS= rocq-9.2.0/test-suite/precomputed-time-tests/zero-before/000077500000000000000000000000001516144147600234475ustar00rootroot00000000000000rocq-9.2.0/test-suite/precomputed-time-tests/zero-before/run.sh000077500000000000000000000004001516144147600246040ustar00rootroot00000000000000#!/usr/bin/env bash . ../template/init.sh cd "$(dirname "${BASH_SOURCE[0]}")" $make_both_time_files time-of-build-after.log.in time-of-build-before.log.in time-of-build-both.log diff -u time-of-build-both.log.expected time-of-build-both.log || exit $? rocq-9.2.0/test-suite/precomputed-time-tests/zero-before/time-of-build-after.log.in000066400000000000000000000050311516144147600303120ustar00rootroot00000000000000./src/Rewriter/PerfTesting/Specific/make.py primes.txt make --no-print-directory -C rewriter make[2]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/deps/coqutil Generating Makefile.coq.all make -f Makefile.coq.all make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/bedrock2 noex Generating Makefile.coq.noex rm -f .coqdeps.d make -f Makefile.coq.noex make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C coqprime src/Coqprime/PrimalityTest/Zp.vo make[1]: 'src/Coqprime/PrimalityTest/Zp.vo' is up to date. rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-coq COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C rewriter make[2]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/deps/coqutil Generating Makefile.coq.all make -f Makefile.coq.all make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/bedrock2 noex Generating Makefile.coq.noex rm -f .coqdeps.d make -f Makefile.coq.noex make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C coqprime src/Coqprime/PrimalityTest/Zp.vo make[1]: 'src/Coqprime/PrimalityTest/Zp.vo' is up to date. ROCQ DEP VFILES make --no-print-directory -C rewriter make[2]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/deps/coqutil Generating Makefile.coq.all make -f Makefile.coq.all make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/bedrock2 noex Generating Makefile.coq.noex rm -f .coqdeps.d make -f Makefile.coq.noex make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C coqprime src/Coqprime/PrimalityTest/Zp.vo make[1]: 'src/Coqprime/PrimalityTest/Zp.vo' is up to date. ROCQ compile src/UnsaturatedSolinasHeuristics/Tests.v Finished transaction in 25.269 secs (24.869u,0.051s) (successful) src/UnsaturatedSolinasHeuristics/Tests.vo (real: 26.27, user: 25.97, sys: 0.27, mem: 566428 ko) DIFF Crypto.Fancy.Montgomery256.Prod.MontRed256 DIFF Crypto.Fancy.Montgomery256.prod_montred256_correct DIFF Crypto.Fancy.Montgomery256.prod_montred256_correct.Assumptions DIFF Crypto.Fancy.Montgomery256.montred256 DIFF Crypto.Fancy.Barrett256.Prod.MulMod DIFF Crypto.Fancy.Barrett256.prod_barrett_red256_correct DIFF Crypto.Fancy.Barrett256.prod_barrett_red256_correct.Assumptions DIFF Crypto.Fancy.Barrett256.barrett_red256 DIFF Crypto.UnsaturatedSolinasHeuristics.Tests.get_possible_limbs cp -f AUTHORS fiat-rust/AUTHORS cp -f CONTRIBUTORS fiat-rust/CONTRIBUTORS cp -f LICENSE fiat-rust/LICENSE rocq-9.2.0/test-suite/precomputed-time-tests/zero-before/time-of-build-before.log.in000066400000000000000000000033371516144147600304620ustar00rootroot00000000000000./src/Rewriter/PerfTesting/Specific/make.py primes.txt make --no-print-directory -C rewriter make[2]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/deps/coqutil Generating Makefile.coq.all make -f Makefile.coq.all make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/bedrock2 noex Generating Makefile.coq.noex rm -f .coqdeps.d make -f Makefile.coq.noex make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C coqprime src/Coqprime/PrimalityTest/Zp.vo make[1]: 'src/Coqprime/PrimalityTest/Zp.vo' is up to date. rocq makefile -f _CoqProject INSTALLDEFAULTROOT = Crypto -o Makefile-coq COQ_MAKEFILE -f _CoqProject > Makefile.coq make --no-print-directory -C rewriter make[2]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/deps/coqutil Generating Makefile.coq.all make -f Makefile.coq.all make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C bedrock2/bedrock2 noex Generating Makefile.coq.noex rm -f .coqdeps.d make -f Makefile.coq.noex make[3]: Nothing to be done for 'real-all'. make --no-print-directory -C coqprime src/Coqprime/PrimalityTest/Zp.vo make[1]: 'src/Coqprime/PrimalityTest/Zp.vo' is up to date. DIFF Crypto.Fancy.Montgomery256.Prod.MontRed256 DIFF Crypto.Fancy.Montgomery256.prod_montred256_correct DIFF Crypto.Fancy.Montgomery256.prod_montred256_correct.Assumptions DIFF Crypto.Fancy.Montgomery256.montred256 DIFF Crypto.Fancy.Barrett256.Prod.MulMod DIFF Crypto.Fancy.Barrett256.prod_barrett_red256_correct DIFF Crypto.Fancy.Barrett256.prod_barrett_red256_correct.Assumptions DIFF Crypto.Fancy.Barrett256.barrett_red256 cp -f AUTHORS fiat-rust/AUTHORS cp -f CONTRIBUTORS fiat-rust/CONTRIBUTORS cp -f LICENSE fiat-rust/LICENSE rocq-9.2.0/test-suite/precomputed-time-tests/zero-before/time-of-build-both.log.expected000066400000000000000000000013021516144147600313350ustar00rootroot00000000000000 After | Peak Mem | Before | Peak Mem || Change || Change (mem) | % Change | % Change (mem) | File Name ------------------------------------------------------------------------------------------------------------------------------------------- 0m25.97s | 566428 ko | 0m00.00s | 0 ko || +0m25.97s || 566428 ko | N/A | ∞ | Total Time / Peak Mem ------------------------------------------------------------------------------------------------------------------------------------------- 0m25.97s | 566428 ko | N/A | N/A || +0m25.97s || 566428 ko | ∞ | ∞ | UnsaturatedSolinasHeuristics/Tests.vo rocq-9.2.0/test-suite/prerequisite/000077500000000000000000000000001516144147600173265ustar00rootroot00000000000000rocq-9.2.0/test-suite/prerequisite/admit.v000066400000000000000000000001011516144147600206030ustar00rootroot00000000000000Axiom proof_admitted : False. Ltac admit := case proof_admitted. rocq-9.2.0/test-suite/prerequisite/arith.v000066400000000000000000000005031516144147600206220ustar00rootroot00000000000000Axiom eq_nat_dec : forall n m : nat, {n = m} + {n <> m}. Module Nat. Axiom add_0_l : forall n : nat, 0 + n = n. Axiom add_0_r : forall n : nat, n + 0 = n. Axiom nlt_0_r : forall n : nat, ~ n < 0. Axiom succ_lt_mono : forall n m : nat, n < m <-> S n < S m. Axiom lt_lt_succ_r : forall n m : nat, n < m -> n < S m. End Nat. rocq-9.2.0/test-suite/prerequisite/bind_univs.v000066400000000000000000000002331516144147600216530ustar00rootroot00000000000000(* Used in output/UnivBinders.v *) Monomorphic Definition mono@{u} := Type@{u}. Polymorphic Definition poly@{u} := Type@{u}. Monomorphic Universe reqU. rocq-9.2.0/test-suite/prerequisite/binpos.v000066400000000000000000000001471516144147600210110ustar00rootroot00000000000000Inductive positive : Set := | xI : positive -> positive | xO : positive -> positive | xH : positive. rocq-9.2.0/test-suite/prerequisite/bool.v000066400000000000000000000002011516144147600204410ustar00rootroot00000000000000Module Bool. Definition eqb (b1 b2 : bool) := if b1 then if b2 then true else false else if b2 then false else true. End Bool. rocq-9.2.0/test-suite/prerequisite/deprecated_library.v000066400000000000000000000003601516144147600233400ustar00rootroot00000000000000Attributes deprecated(note="This library is useless.", since="XX YY"). Attributes warn(note="This library is dangerous.", cats="dangerous library"). Attributes warn(note="This library is tricky.", cats="dangerous library, tricky library"). rocq-9.2.0/test-suite/prerequisite/extra_dep.txt000066400000000000000000000000001516144147600220300ustar00rootroot00000000000000rocq-9.2.0/test-suite/prerequisite/for_vos.v000066400000000000000000000002431516144147600211710ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-vos") -*- *) Axiom axiom : nat. Lemma foo : nat. Proof. exact axiom. Qed. Lemma bar : nat. Proof. exact axiom. Defined. rocq-9.2.0/test-suite/prerequisite/funext.v000066400000000000000000000004521516144147600210270ustar00rootroot00000000000000Axiom functional_extensionality_dep : forall {A : Type} {B : A -> Type} (f g : forall x : A, B x), (forall x : A, f x = g x) -> f = g. Lemma functional_extensionality {A B} (f g : A -> B) : (forall x, f x = g x) -> f = g. Proof. intros ; eauto using @functional_extensionality_dep. Qed. rocq-9.2.0/test-suite/prerequisite/funind.v000066400000000000000000000013661516144147600210060ustar00rootroot00000000000000(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A]) cannot be a retract of a modal proposition. It is an example of use of the paradox where the universes of system U- are not mapped to universes of Coq. - The [NoRetractToNegativeProp] module is the specialisation of the [NoRetractFromSmallPropositionToProp] module where the modality is double-negation. This result implies that the principle of weak excluded middle ([forall A, ~~A\/~A]) implies a weak variant of proof irrelevance. - The [NoRetractFromTypeToProp] module proves that [Prop] cannot be a retract of a larger type. - The [TypeNeqSmallType] module proves that [Type] is different from any smaller type. - The [PropNeqType] module proves that [Prop] is different from any larger [Type]. It is an instance of the previous result. References: - [[Coquand90]] T. Coquand, "Metamathematical Investigations of a Calculus of Constructions", Proceedings of Logic in Computer Science (LICS'90), 1990. - [[Hurkens95]] A. J. Hurkens, "A simplification of Girard's paradox", Proceedings of the 2nd international conference Typed Lambda-Calculi and Applications (TLCA'95), 1995. - [[Geuvers01]] H. Geuvers, "Inconsistency of Classical Logic in Type Theory", 2001, revised 2007 (see external link {{http://www.cs.ru.nl/~herman/PUBS/newnote.ps.gz}}). *) Set Universe Polymorphism. (* begin show *) (** * A modular proof of Hurkens's paradox. *) (** It relies on an axiomatisation of a shallow embedding of system U- (i.e. types of U- are interpreted by types of Coq). The universes are encoded in a style, due to Martin-LΓΆf, where they are given by a set of names and a family [El:Name->Type] which interprets each name into a type. This allows the encoding of universe to be decoupled from Coq's universes. Dependent products and abstractions are similarly postulated rather than encoded as Coq's dependent products and abstractions. *) Module Generic. (* begin hide *) (* Notations used in the proof. Hidden in coqdoc. *) Reserved Notation "'βˆ€β‚' x : A , B" (at level 200, x name, A at level 200,right associativity). Reserved Notation "A 'βŸΆβ‚' B" (at level 99, right associativity, B at level 200). Reserved Notation "'λ₁' x , u" (at level 200, x name, right associativity). Reserved Notation "f '·₁' x" (at level 5, left associativity). Reserved Notation "'βˆ€β‚‚' A , F" (at level 200, A name, right associativity). Reserved Notation "'Ξ»β‚‚' x , u" (at level 200, x name, right associativity). #[warning="-postfix-notation-not-level-1"] Reserved Notation "f '·₁' [ A ]" (at level 5, left associativity). Reserved Notation "'βˆ€β‚€' x : A , B" (at level 200, x name, A at level 200,right associativity). Reserved Notation "A 'βŸΆβ‚€' B" (at level 99, right associativity, B at level 200). Reserved Notation "'Ξ»β‚€' x , u" (at level 200, x name, right associativity). Reserved Notation "f 'Β·β‚€' x" (at level 5, left associativity). Reserved Notation "'βˆ€β‚€ΒΉ' A : U , F" (at level 200, A name, right associativity). Reserved Notation "'Ξ»β‚€ΒΉ' x , u" (at level 200, x name, right associativity). #[warning="-postfix-notation-not-level-1"] Reserved Notation "f 'Β·β‚€' [ A ]" (at level 5, left associativity). (* end hide *) Section Paradox. (** ** Axiomatisation of impredicative universes in a Martin-LΓΆf style *) (** System U- has two impredicative universes. In the proof of the paradox they are slightly asymmetric (in particular the reduction rules of the small universe are not needed). Therefore, the axioms are duplicated allowing for a weaker requirement than the actual system U-. *) (** *** Large universe *) Variable U1 : Type. Variable El1 : U1 -> Type. (** **** Closure by small product *) Variable Forall1 : forall u:U1, (El1 u -> U1) -> U1. Notation "'βˆ€β‚' x : A , B" := (Forall1 A (fun x => B)). Notation "A 'βŸΆβ‚' B" := (Forall1 A (fun _ => B)). Variable lam1 : forall u B, (forall x:El1 u, El1 (B x)) -> El1 (βˆ€β‚ x:u, B x). Notation "'λ₁' x , u" := (lam1 _ _ (fun x => u)). Variable app1 : forall u B (f:El1 (Forall1 u B)) (x:El1 u), El1 (B x). Notation "f '·₁' x" := (app1 _ _ f x). Variable beta1 : forall u B (f:forall x:El1 u, El1 (B x)) x, (λ₁ y, f y) ·₁ x = f x. (** **** Closure by large products *) (** [U1] only needs to quantify over itself. *) Variable ForallU1 : (U1->U1) -> U1. Notation "'βˆ€β‚‚' A , F" := (ForallU1 (fun A => F)). Variable lamU1 : forall F, (forall A:U1, El1 (F A)) -> El1 (βˆ€β‚‚ A, F A). Notation "'Ξ»β‚‚' x , u" := (lamU1 _ (fun x => u)). Variable appU1 : forall F (f:El1(βˆ€β‚‚ A,F A)) (A:U1), El1 (F A). Notation "f '·₁' [ A ]" := (appU1 _ f A). Variable betaU1 : forall F (f:forall A:U1, El1 (F A)) A, (Ξ»β‚‚ x, f x) ·₁ [ A ] = f A. (** *** Small universe *) (** The small universe is an element of the large one. *) Variable u0 : U1. Notation U0 := (El1 u0). Variable El0 : U0 -> Type. (** **** Closure by small product *) (** [U0] does not need reduction rules *) Variable Forall0 : forall u:U0, (El0 u -> U0) -> U0. Notation "'βˆ€β‚€' x : A , B" := (Forall0 A (fun x => B)). Notation "A 'βŸΆβ‚€' B" := (Forall0 A (fun _ => B)). Variable lam0 : forall u B, (forall x:El0 u, El0 (B x)) -> El0 (βˆ€β‚€ x:u, B x). Notation "'Ξ»β‚€' x , u" := (lam0 _ _ (fun x => u)). Variable app0 : forall u B (f:El0 (Forall0 u B)) (x:El0 u), El0 (B x). Notation "f 'Β·β‚€' x" := (app0 _ _ f x). (** **** Closure by large products *) Variable ForallU0 : forall u:U1, (El1 u->U0) -> U0. Notation "'βˆ€β‚€ΒΉ' A : U , F" := (ForallU0 U (fun A => F)). Variable lamU0 : forall U F, (forall A:El1 U, El0 (F A)) -> El0 (βˆ€β‚€ΒΉ A:U, F A). Notation "'Ξ»β‚€ΒΉ' x , u" := (lamU0 _ _ (fun x => u)). Variable appU0 : forall U F (f:El0(βˆ€β‚€ΒΉ A:U,F A)) (A:El1 U), El0 (F A). Notation "f 'Β·β‚€' [ A ]" := (appU0 _ _ f A). (** ** Automating the rewrite rules of our encoding. *) Local Ltac simplify := (* spiwack: ideally we could use [rewrite_strategy] here, but I am a tad scared of the idea of depending on setoid rewrite in such a simple file. *) (repeat rewrite ?beta1, ?betaU1); lazy beta. Local Ltac simplify_in h := (repeat rewrite ?beta1, ?betaU1 in h); lazy beta in h. (** ** Hurkens's paradox. *) (** An inhabitant of [U0] standing for [False]. *) Variable F:U0. (** *** Preliminary definitions *) Definition V : U1 := βˆ€β‚‚ A, ((A βŸΆβ‚ u0) βŸΆβ‚ A βŸΆβ‚ u0) βŸΆβ‚ A βŸΆβ‚ u0. Definition U : U1 := V βŸΆβ‚ u0. Definition sb (z:El1 V) : El1 V := Ξ»β‚‚ A, λ₁ r, λ₁ a, r ·₁ (z·₁[A]·₁r) ·₁ a. Definition le (i:El1 (UβŸΆβ‚u0)) (x:El1 U) : U0 := x ·₁ (Ξ»β‚‚ A, λ₁ r, λ₁ a, i ·₁ (λ₁ v, (sb v) ·₁ [A] ·₁ r ·₁ a)). Definition le' : El1 ((UβŸΆβ‚u0) βŸΆβ‚ U βŸΆβ‚ u0) := λ₁ i, λ₁ x, le i x. Definition induct (i:El1 (UβŸΆβ‚u0)) : U0 := βˆ€β‚€ΒΉ x:U, le i x βŸΆβ‚€ i ·₁ x. Definition WF : El1 U := λ₁ z, (induct (z·₁[U] ·₁ le')). Definition I (x:El1 U) : U0 := (βˆ€β‚€ΒΉ i:UβŸΆβ‚u0, le i x βŸΆβ‚€ i ·₁ (λ₁ v, (sb v) ·₁ [U] ·₁ le' ·₁ x)) βŸΆβ‚€ F . (** *** Proof *) Lemma Omega : El0 (βˆ€β‚€ΒΉ i:UβŸΆβ‚u0, induct i βŸΆβ‚€ i ·₁ WF). Proof. refine (Ξ»β‚€ΒΉ i, Ξ»β‚€ y, _). refine (yΒ·β‚€[_]Β·β‚€_). unfold le,WF,induct. simplify. refine (Ξ»β‚€ΒΉ x, Ξ»β‚€ h0, _). simplify. refine (yΒ·β‚€[_]Β·β‚€_). unfold le. simplify. unfold sb at 1. simplify. unfold le' at 1. simplify. exact h0. Qed. Lemma lemma1 : El0 (induct (λ₁ u, I u)). Proof. unfold induct. refine (Ξ»β‚€ΒΉ x, Ξ»β‚€ p, _). simplify. refine (Ξ»β‚€ q,_). assert (El0 (I (λ₁ v, (sb v)·₁[U]·₁le'·₁x))) as h. { generalize (qΒ·β‚€[λ₁ u, I u]Β·β‚€p). simplify. intros q'. exact q'. } refine (hΒ·β‚€_). refine (Ξ»β‚€ΒΉ i,_). refine (Ξ»β‚€ h', _). generalize (qΒ·β‚€[λ₁ y, i ·₁ (λ₁ v, (sb v)·₁[U] ·₁ le' ·₁ y)]). simplify. intros q'. refine (q'Β·β‚€_). clear q'. unfold le at 1 in h'. simplify_in h'. unfold sb at 1 in h'. simplify_in h'. unfold le' at 1 in h'. simplify_in h'. exact h'. Qed. Lemma lemma2 : El0 ((βˆ€β‚€ΒΉi:UβŸΆβ‚u0, induct i βŸΆβ‚€ i·₁WF) βŸΆβ‚€ F). Proof. refine (Ξ»β‚€ x, _). assert (El0 (I WF)) as h. { generalize (xΒ·β‚€[λ₁ u, I u]Β·β‚€lemma1). simplify. intros q. exact q. } refine (hΒ·β‚€_). clear h. refine (Ξ»β‚€ΒΉ i, Ξ»β‚€ h0, _). generalize (xΒ·β‚€[λ₁ y, i·₁(λ₁ v, (sb v)·₁[U]·₁le'·₁y)]). simplify. intros q. refine (qΒ·β‚€_). clear q. unfold le in h0. simplify_in h0. unfold WF in h0. simplify_in h0. exact h0. Qed. Theorem paradox : El0 F. Proof. exact (lemma2Β·β‚€Omega). Qed. End Paradox. (** The [paradox] tactic can be called as a shortcut to use the paradox. *) Ltac paradox h := unshelve (refine ((fun h => _) (paradox _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ))). End Generic. (** * Impredicative universes are not retracts. *) (** There can be no retract to an impredicative Coq universe from a smaller type. In this version of the proof, the impredicativity of the universe is postulated with a pair of functions from the universe to its type and back which commute with dependent product in an appropriate way. *) Module NoRetractToImpredicativeUniverse. Section Paradox. Let U2 := Type. Let U1:U2 := Type. Variable U0:U1. (** *** [U1] is impredicative *) Variable u22u1 : U2 -> U1. Hypothesis u22u1_unit : forall (c:U2), c -> u22u1 c. (** [u22u1_counit] and [u22u1_coherent] only apply to dependent product so that the equations happen in the smaller [U1] rather than [U2]. Indeed, it is not generally the case that one can project from a large universe to an impredicative universe and then get back the original type again. It would be too strong a hypothesis to require (in particular, it is not true of [Prop]). The formulation is reminiscent of the monadic characteristic of the projection from a large type to [Prop].*) Hypothesis u22u1_counit : forall (F:U1->U1), u22u1 (forall A,F A) -> (forall A,F A). Hypothesis u22u1_coherent : forall (F:U1 -> U1) (f:forall x:U1, F x) (x:U1), u22u1_counit _ (u22u1_unit _ f) x = f x. (** *** [U0] is a retract of [U1] *) Variable u02u1 : U0 -> U1. Variable u12u0 : U1 -> U0. Hypothesis u12u0_unit : forall (b:U1), b -> u02u1 (u12u0 b). Hypothesis u12u0_counit : forall (b:U1), u02u1 (u12u0 b) -> b. (** ** Paradox *) Theorem paradox : forall F:U1, F. Proof. intros F. Generic.paradox h. (** Large universe *) + exact U1. + exact (fun X => X). + cbn. exact (fun u F => forall x:u, F x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun F => u22u1 (forall x, F x)). + cbn. exact (fun _ x => u22u1_unit _ x). + cbn. exact (fun _ x => u22u1_counit _ x). (** Small universe *) + exact U0. (** The interpretation of the small universe is the image of [U0] in [U1]. *) + cbn. exact (fun X => u02u1 X). + cbn. exact (fun u F => u12u0 (forall x:(u02u1 u), u02u1 (F x))). + cbn. exact (fun u F => u12u0 (forall x:u, u02u1 (F x))). + cbn. exact (u12u0 F). + cbn in h. exact (u12u0_counit _ h). + cbn. easy. + cbn. intros **. now rewrite u22u1_coherent. + cbn. intros * x. exact (u12u0_unit _ x). + cbn. intros * x. exact (u12u0_counit _ x). + cbn. intros * x. exact (u12u0_unit _ x). + cbn. intros * x. exact (u12u0_counit _ x). Qed. End Paradox. End NoRetractToImpredicativeUniverse. (** * Modal fragments of [Prop] are not retracts *) (** In presence of a a monadic modality on [Prop], we can define a subset of [Prop] of modal propositions which is also a complete Heyting algebra. These cannot be a retract of a modal proposition. This is a case where the universe in system U- are not encoded as Coq universes. *) Module NoRetractToModalProposition. (** ** Monadic modality *) Section Paradox. Variable M : Prop -> Prop. Hypothesis incr : forall A B:Prop, (A->B) -> M A -> M B. Lemma strength: forall A (P:A->Prop), M(forall x:A,P x) -> forall x:A,M(P x). Proof. intros A P h x. eapply incr in h; eauto. Qed. (** ** The universe of modal propositions *) Definition MProp := { P:Prop | M P -> P }. Definition El : MProp -> Prop := @proj1_sig _ _. Lemma modal : forall P:MProp, M(El P) -> El P. Proof. intros [P m]. cbn. exact m. Qed. Definition Forall {A:Type} (P:A->MProp) : MProp. Proof. unshelve (refine (exist _ _ _)). + exact (forall x:A, El (P x)). + intros h x. eapply strength in h. eauto using modal. Defined. (** ** Retract of the modal fragment of [Prop] in a small type *) (** The retract is axiomatized using logical equivalence as the equality on propositions. *) Variable bool : MProp. Variable p2b : MProp -> El bool. Variable b2p : El bool -> MProp. Hypothesis p2p1 : forall A:MProp, El (b2p (p2b A)) -> El A. Hypothesis p2p2 : forall A:MProp, El A -> El (b2p (p2b A)). (** ** Paradox *) Theorem paradox : forall B:MProp, El B. Proof. intros B. Generic.paradox h. (** Large universe *) + exact MProp. + exact El. + exact (fun _ => Forall). + cbn. exact (fun _ _ f => f). + cbn. exact (fun _ _ f => f). + exact Forall. + cbn. exact (fun _ f => f). + cbn. exact (fun _ f => f). (** Small universe *) + exact bool. + exact (fun b => El (b2p b)). + cbn. exact (fun _ F => p2b (Forall (fun x => b2p (F x)))). + exact (fun _ F => p2b (Forall (fun x => b2p (F x)))). + apply p2b. exact B. + cbn in h. auto. + cbn. easy. + cbn. easy. + cbn. auto. + cbn. intros * f. apply p2p1 in f. cbn in f. exact f. + cbn. auto. + cbn. intros * f. apply p2p1 in f. cbn in f. exact f. Qed. End Paradox. End NoRetractToModalProposition. (** * The negative fragment of [Prop] is not a retract *) (** The existence in the pure Calculus of Constructions of a retract from the negative fragment of [Prop] into a negative proposition is inconsistent. This is an instance of the previous result. *) Module NoRetractToNegativeProp. (** ** The universe of negative propositions. *) Definition NProp := { P:Prop | ~~P -> P }. Definition El : NProp -> Prop := @proj1_sig _ _. Section Paradox. (** ** Retract of the negative fragment of [Prop] in a small type *) (** The retract is axiomatized using logical equivalence as the equality on propositions. *) Variable bool : NProp. Variable p2b : NProp -> El bool. Variable b2p : El bool -> NProp. Hypothesis p2p1 : forall A:NProp, El (b2p (p2b A)) -> El A. Hypothesis p2p2 : forall A:NProp, El A -> El (b2p (p2b A)). (** ** Paradox *) Theorem paradox : forall B:NProp, El B. Proof. intros B. unshelve (refine ((fun h => _) (NoRetractToModalProposition.paradox _ _ _ _ _ _ _ _))). + exact (fun P => ~~P). + exact bool. + exact p2b. + exact b2p. + exact B. + exact h. + cbn. auto. + cbn. auto. + cbn. auto. Qed. End Paradox. End NoRetractToNegativeProp. (** * Prop is not a retract *) (** The existence in the pure Calculus of Constructions of a retract from [Prop] into a small type of [Prop] is inconsistent. This is a special case of the previous result. *) Module NoRetractFromSmallPropositionToProp. (** ** The universe of propositions. *) Definition NProp := { P:Prop | P -> P}. Definition El : NProp -> Prop := @proj1_sig _ _. Section MParadox. (** ** Retract of [Prop] in a small type, using the identity modality. *) Variable bool : NProp. Variable p2b : NProp -> El bool. Variable b2p : El bool -> NProp. Hypothesis p2p1 : forall A:NProp, El (b2p (p2b A)) -> El A. Hypothesis p2p2 : forall A:NProp, El A -> El (b2p (p2b A)). (** ** Paradox *) Theorem mparadox : forall B:NProp, El B. Proof. intros B. unshelve (refine ((fun h => _) (NoRetractToModalProposition.paradox _ _ _ _ _ _ _ _))). + exact (fun P => P). + exact bool. + exact p2b. + exact b2p. + exact B. + exact h. + cbn. auto. + cbn. auto. + cbn. auto. Qed. End MParadox. Section Paradox. (** ** Retract of [Prop] in a small type *) (** The retract is axiomatized using logical equivalence as the equality on propositions. *) Variable bool : Prop. Variable p2b : Prop -> bool. Variable b2p : bool -> Prop. Hypothesis p2p1 : forall A:Prop, b2p (p2b A) -> A. Hypothesis p2p2 : forall A:Prop, A -> b2p (p2b A). (** ** Paradox *) Theorem paradox : forall B:Prop, B. Proof. intros B. unshelve (refine (mparadox (exist _ bool (fun x => x)) _ _ _ _ (exist _ B (fun x => x)))). + intros p. red. red. exact (p2b (El p)). + cbn. intros b. red. exists (b2p b). exact (fun x => x). + cbn. intros [A H]. cbn. apply p2p1. + cbn. intros [A H]. cbn. apply p2p2. Qed. End Paradox. End NoRetractFromSmallPropositionToProp. (** * Large universes are not retracts of [Prop]. *) (** The existence in the Calculus of Constructions with universes of a retract from some [Type] universe into [Prop] is inconsistent. *) (* Note: Assuming the context [down:Type->Prop; up:Prop->Type; forth: forall (A:Type), A -> up (down A); back: forall (A:Type), up (down A) -> A; H: forall (A:Type) (P:A->Type) (a:A), P (back A (forth A a)) -> P a] is probably enough. *) Module NoRetractFromTypeToProp. Definition Type2 := Type. Definition Type1 := Type : Type2. Section Paradox. (** ** Assumption of a retract from Type into Prop *) Variable down : Type1 -> Prop. Variable up : Prop -> Type1. Hypothesis up_down : forall (A:Type1), up (down A) = A :> Type1. (** ** Paradox *) Theorem paradox : forall P:Prop, P. Proof. intros P. Generic.paradox h. (** Large universe. *) + exact Type1. + exact (fun X => X). + cbn. exact (fun u F => forall x, F x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). + exact (fun F => forall A:Prop, F(up A)). + cbn. exact (fun F f A => f (up A)). + cbn. intros F f A. specialize (f (down A)). rewrite up_down in f. exact f. + exact Prop. + cbn. exact (fun X => X). + cbn. exact (fun A P => forall x:A, P x). + cbn. exact (fun A P => forall x:A, P x). + cbn. exact P. + exact h. + cbn. easy. + cbn. intros F f A. destruct (up_down A). cbn. reflexivity. + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). Qed. End Paradox. End NoRetractFromTypeToProp. (** * [A<>Type] *) (** No Coq universe can be equal to one of its elements. *) Module TypeNeqSmallType. Unset Universe Polymorphism. Section Paradox. (** ** Universe [U] is equal to one of its elements. *) Let U := Type. Variable A:U. Hypothesis h : U=A. (** ** Universe [U] is a retract of [A] *) (** The following context is actually sufficient for the paradox to hold. The hypothesis [h:U=A] is only used to define [down], [up] and [up_down]. *) Let down (X:U) : A := @eq_rect _ _ (fun X => X) X _ h. Let up (X:A) : U := @eq_rect_r _ _ (fun X => X) X _ h. Lemma up_down : forall (X:U), up (down X) = X. Proof. unfold up,down. rewrite <- h. reflexivity. Qed. Theorem paradox : False. Proof. Generic.paradox p. (** Large universe *) + exact U. + exact (fun X=>X). + cbn. exact (fun X F => forall x:X, F x). + cbn. exact (fun _ _ x => x). + cbn. exact (fun _ _ x => x). + exact (fun F => forall x:A, F (up x)). + cbn. exact (fun _ f => fun x:A => f (up x)). + cbn. intros * f X. specialize (f (down X)). rewrite up_down in f. exact f. (** Small universe *) + exact A. (** The interpretation of [A] as a universe is [U]. *) + cbn. exact up. + cbn. exact (fun _ F => down (forall x, up (F x))). + cbn. exact (fun _ F => down (forall x, up (F x))). + cbn. exact (down False). + rewrite up_down in p. exact p. + cbn. easy. + cbn. intros ? f X. destruct (up_down X). cbn. reflexivity. + cbn. intros ? ? f. rewrite up_down. exact f. + cbn. intros ? ? f. rewrite up_down in f. exact f. + cbn. intros ? ? f. rewrite up_down. exact f. + cbn. intros ? ? f. rewrite up_down in f. exact f. Qed. End Paradox. End TypeNeqSmallType. (** * [Prop<>Type]. *) (** Special case of [TypeNeqSmallType]. *) Module PropNeqType. Theorem paradox : Prop <> Type. Proof. intros h. unshelve (refine (TypeNeqSmallType.paradox _ _)). + exact Prop. + easy. Qed. End PropNeqType. (* end show *) rocq-9.2.0/test-suite/prerequisite/jmeq.v000066400000000000000000000001511516144147600204460ustar00rootroot00000000000000Inductive JMeq [A] (x : A) : forall [B], B -> Prop := JMeq_refl : JMeq x x. Scheme Rewriting for JMeq. rocq-9.2.0/test-suite/prerequisite/list.v000066400000000000000000000050271516144147600204740ustar00rootroot00000000000000Section Lists. Context [A : Type]. Fixpoint In (a : A) (l : list A) : Prop := match l with | nil => False | cons b m => b = a \/ In a m end. Fixpoint concat (l : list (list A)) : list A := match l with | nil => nil | cons x l => x ++ concat l end. Definition hd (default : A) (l : list A) := match l with | nil => default | cons x _ => x end. Axiom app_nil_r : forall (l : list A), app l nil = l. Axiom app_inj_tail : forall (x y : list A) (a b : A), app x (cons a nil) = app y (cons b nil) -> x = y /\ a = b. End Lists. Section Fold_Left_Recursor. Context [A B : Type]. Variable f : A -> B -> A. Fixpoint fold_left (l:list B) (a0:A) : A := match l with | nil => a0 | cons b t => fold_left t (f a0 b) end. Lemma fold_left_app : forall (l l':list B)(i:A), fold_left (l++l') i = fold_left l' (fold_left l i). Proof. now intro l; induction l; cbn. Qed. End Fold_Left_Recursor. Section Fold_Right_Recursor. Context [A B : Type]. Variable f : B -> A -> A. Variable a0 : A. Fixpoint fold_right (l : list B) : A := match l with | nil => a0 | cons b t => f b (fold_right t) end. End Fold_Right_Recursor. Section Map. Context [A B : Type]. Variable f : A -> B. Fixpoint map (l : list A) : list B := match l with | nil => nil | cons a t => (f a) :: (map t) end. Lemma in_map : forall (l:list A) (x:A), In x l -> In (f x) (map l). Proof. intro l; induction l; firstorder (subst; auto). Qed. End Map. Section FlatMap. Context [A B : Type]. Variable f : A -> list B. Fixpoint flat_map (l : list A) : list B := match l with | nil => nil | cons x t => app (f x) (flat_map t) end. End FlatMap. Section Elts. Context [A : Type]. Fixpoint nth (n : nat) (l : list A) (default : A) {struct l} : A := match n, l with | O, cons x l' => x | O, nil => default | S m, nil => default | S m, cons x t => nth m t default end. End Elts. Section Cutting. Context [A : Type]. Fixpoint skipn (n : nat)(l : list A) : list A := match n with | 0 => l | S n => match l with | nil => nil | cons a l => skipn n l end end. End Cutting. Module ListNotations. Notation "[ ]" := nil (format "[ ]") : list_scope. Notation "[ x ]" := (cons x nil) : list_scope. Notation "[ x ; y ; .. ; z ]" := (cons x (cons y .. (cons z nil) ..)) (format "[ '[' x ; '/' y ; '/' .. ; '/' z ']' ]") : list_scope. Open Scope list_scope. End ListNotations. rocq-9.2.0/test-suite/prerequisite/make_local.v000066400000000000000000000003641516144147600216070ustar00rootroot00000000000000(* Used in Import.v to test the locality flag *) Definition f (A:Type) (a:A) := a. Local Arguments f [A]%_type_scope _%_type_scope. (* Used in ImportedCoercion.v to test the locality flag *) Local Coercion g (b:bool) := if b then 0 else 1. rocq-9.2.0/test-suite/prerequisite/make_notation.v000066400000000000000000000005611516144147600223470ustar00rootroot00000000000000(* Used in Notation.v to test import of notations from files in sections *) Notation "'Z'" := O (at level 9). Notation plus := plus. Notation succ := S. Notation mult := mult (only parsing). Notation less := le (only parsing). (* Test bug 2168: ending section of some name was removing objects of the same name *) Notation add2 n:=(S n). Section add2. End add2. rocq-9.2.0/test-suite/prerequisite/module_bug7192.v000066400000000000000000000005031516144147600221600ustar00rootroot00000000000000(* Variant of #7192 to be tested in a file requiring this file *) (* #7192 is about Print Assumptions not entering implementation of submodules *) Definition a := True. Module Type B. Axiom f : Prop. End B. Module Type C. Declare Module D : B. End C. Module M7192: C. Module D <: B. Definition f := a. End D. End M7192. rocq-9.2.0/test-suite/prerequisite/module_bug8416.v000066400000000000000000000001261516144147600221610ustar00rootroot00000000000000Module Type A. Axiom f : True. End A. Module M8416 : A. Definition f := I. End M8416. rocq-9.2.0/test-suite/prerequisite/proof_irrelevance.v000066400000000000000000000001021516144147600232120ustar00rootroot00000000000000Axiom proof_irrelevance : forall (P : Prop) (p1 p2 : P), p1 = p2. rocq-9.2.0/test-suite/prerequisite/relationclasses.v000066400000000000000000000024511516144147600227120ustar00rootroot00000000000000Section Relation_Definition. Variable A : Type. Definition relation := A -> A -> Prop. Variable R : relation. Definition reflexive : Prop := forall x:A, R x x. Definition transitive : Prop := forall x y z:A, R x y -> R y z -> R x z. Definition symmetric : Prop := forall x y:A, R x y -> R y x. Definition antisymmetric : Prop := forall x y:A, R x y -> R y x -> x = y. End Relation_Definition. Section Defs. Context {A : Type}. Class Reflexive (R : relation A) := reflexivity : forall x : A, R x x. Class Symmetric (R : relation A) := symmetry : forall {x y}, R x y -> R y x. Class Transitive (R : relation A) := transitivity : forall {x y z}, R x y -> R y z -> R x z. Class PreOrder (R : relation A) : Prop := { #[global] PreOrder_Reflexive :: Reflexive R | 2 ; #[global] PreOrder_Transitive :: Transitive R | 2 }. Class Equivalence (R : relation A) : Prop := { #[global] Equivalence_Reflexive :: Reflexive R ; #[global] Equivalence_Symmetric :: Symmetric R ; #[global] Equivalence_Transitive :: Transitive R }. #[global] Instance eq_Reflexive : Reflexive (@eq A) := @eq_refl A. #[global] Instance eq_Symmetric : Symmetric (@eq A) := @eq_sym A. #[global] Instance eq_Transitive : Transitive (@eq A) := @eq_trans A. #[global] Program Instance eq_equivalence : Equivalence (@eq A) | 10. End Defs. rocq-9.2.0/test-suite/prerequisite/requires_deprecated_library.v000066400000000000000000000000461516144147600252600ustar00rootroot00000000000000Require TestSuite.deprecated_library. rocq-9.2.0/test-suite/prerequisite/sint63.v000066400000000000000000000012031516144147600206370ustar00rootroot00000000000000Require Export PrimInt63. Require Import Uint63Axioms. Declare Scope sint63_scope. Delimit Scope sint63_scope with sint63. Definition printer (x : int_wrapper) : pos_neg_int63 := if (ltb (int_wrap x) 4611686018427387904)%uint63 then (* 2^62 *) Pos (int_wrap x) else Neg (add (lxor (int_wrap x) max_int) 1)%uint63. Definition parser (x : pos_neg_int63) : option int := match x with | Pos p => if (ltb p 4611686018427387904)%uint63 then Some p else None | Neg n => if (leb n 4611686018427387904)%uint63 then Some (lxor (sub n 1) max_int)%uint63 else None end. Number Notation int parser printer : sint63_scope. rocq-9.2.0/test-suite/prerequisite/ssr_mini_mathcomp.v000066400000000000000000001352651516144147600232440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* -> Sortclass. Variables (T : Type) (cT : type). Definition class := let: Pack _ c _ := cT return class_of cT in c. Definition pack c := @Pack T c T. Definition clone := fun c & cT -> T & phant_id (pack c) cT => pack c. End ClassDef. Module Exports. Coercion sort : type >-> Sortclass. Notation eqType := type. Notation EqMixin := Mixin. Notation EqType T m := (@pack T m). Notation "[ 'eqMixin' 'of' T ]" := (class _ : mixin_of T) (at level 0, format "[ 'eqMixin' 'of' T ]") : form_scope. Notation "[ 'eqType' 'of' T 'for' C ]" := (@clone T C _ idfun id) (at level 0, format "[ 'eqType' 'of' T 'for' C ]") : form_scope. Notation "[ 'eqType' 'of' T ]" := (@clone T _ _ id id) (at level 0, format "[ 'eqType' 'of' T ]") : form_scope. End Exports. End Equality. Export Equality.Exports. Definition eq_op T := Equality.op (Equality.class T). Lemma eqE T x : eq_op x = Equality.op (Equality.class T) x. Proof. by []. Qed. Lemma eqP T : Equality.axiom (@eq_op T). Proof. by case: T => ? []. Qed. Arguments eqP {T x y}. Declare Scope eq_scope. Delimit Scope eq_scope with EQ. Open Scope eq_scope. Notation "x == y" := (eq_op x y) (at level 70, no associativity) : bool_scope. Notation "x == y :> T" := ((x : T) == (y : T)) (at level 70, y at next level) : bool_scope. Notation "x != y" := (~~ (x == y)) (at level 70, no associativity) : bool_scope. Notation "x != y :> T" := (~~ (x == y :> T)) (at level 70, y at next level) : bool_scope. Notation "x =P y" := (eqP : reflect (x = y) (x == y)) (at level 70, no associativity) : eq_scope. Notation "x =P y :> T" := (eqP : reflect (x = y :> T) (x == y :> T)) (at level 70, y at next level, no associativity) : eq_scope. Prenex Implicits eq_op eqP. Lemma eq_refl (T : eqType) (x : T) : x == x. Proof. exact/eqP. Qed. Notation eqxx := eq_refl. Lemma eq_sym (T : eqType) (x y : T) : (x == y) = (y == x). Proof. exact/eqP/eqP. Qed. #[global] Hint Resolve eq_refl eq_sym : core. Definition eqb b := addb (~~ b). Lemma eqbP : Equality.axiom eqb. Proof. by do 2!case; constructor. Qed. Canonical bool_eqMixin := EqMixin eqbP. Canonical bool_eqType := Eval hnf in EqType bool bool_eqMixin. Section ProdEqType. Variable T1 T2 : eqType. Definition pair_eq := [rel u v : T1 * T2 | (u.1 == v.1) && (u.2 == v.2)]. Lemma pair_eqP : Equality.axiom pair_eq. Proof. move=> [x1 x2] [y1 y2] /=; apply: (iffP andP) => [[]|[<- <-]] //=. by do 2!move/eqP->. Qed. Definition prod_eqMixin := EqMixin pair_eqP. Canonical prod_eqType := Eval hnf in EqType (T1 * T2) prod_eqMixin. End ProdEqType. Section OptionEqType. Variable T : eqType. Definition opt_eq (u v : option T) : bool := oapp (fun x => oapp (eq_op x) false v) (~~ v) u. Lemma opt_eqP : Equality.axiom opt_eq. Proof. case=> [x|] [y|] /=; by [constructor | apply: (iffP eqP) => [|[]] ->]. Qed. Canonical option_eqMixin := EqMixin opt_eqP. Canonical option_eqType := Eval hnf in EqType (option T) option_eqMixin. End OptionEqType. Notation xpred1 := (fun a1 x => x == a1). Notation xpredU1 := (fun a1 (p : pred _) x => (x == a1) || p x). Section EqPred. Variable T : eqType. Definition pred1 (a1 : T) := SimplPred (xpred1 a1). Definition predU1 (a1 : T) p := SimplPred (xpredU1 a1 p). End EqPred. Section TransferEqType. Variables (T : Type) (eT : eqType) (f : T -> eT). Lemma inj_eqAxiom : injective f -> Equality.axiom (fun x y => f x == f y). Proof. by move=> f_inj x y; apply: (iffP eqP) => [|-> //]; apply: f_inj. Qed. Definition InjEqMixin f_inj := EqMixin (inj_eqAxiom f_inj). Definition PcanEqMixin g (fK : pcancel f g) := InjEqMixin (pcan_inj fK). Definition CanEqMixin g (fK : cancel f g) := InjEqMixin (can_inj fK). End TransferEqType. (* We use the module system to circumvent a silly limitation that *) (* forbids using the same constant to coerce to different targets. *) Module Type EqTypePredSig. Parameter sort : eqType -> predArgType. End EqTypePredSig. Module MakeEqTypePred (eqmod : EqTypePredSig). Coercion eqmod.sort : eqType >-> predArgType. End MakeEqTypePred. Module Export EqTypePred := MakeEqTypePred Equality. Section SubType. Variables (T : Type) (P : pred T). Structure subType : Type := SubType { sub_sort :> Type; val : sub_sort -> T; Sub : forall x, P x -> sub_sort; _ : forall K (_ : forall x Px, K (@Sub x Px)) u, K u; _ : forall x Px, val (@Sub x Px) = x }. Arguments Sub [s]. Lemma vrefl : forall x, P x -> x = x. Proof. by []. Qed. Definition vrefl_rect := vrefl. Definition clone_subType U v := fun sT & sub_sort sT -> U => fun c Urec cK (sT' := @SubType U v c Urec cK) & phant_id sT' sT => sT'. Variable sT : subType. Variant Sub_spec : sT -> Type := SubSpec x Px : Sub_spec (Sub x Px). Lemma SubP u : Sub_spec u. Proof. by case: sT Sub_spec SubSpec u => T' _ C rec /= _. Qed. Lemma SubK x Px : @val sT (Sub x Px) = x. Proof. by case: sT. Qed. Definition insub x := if @idP (P x) is ReflectT Px then @Some sT (Sub x Px) else None. Definition insubd u0 x := odflt u0 (insub x). Variant insub_spec x : option sT -> Type := | InsubSome u of P x & val u = x : insub_spec x (Some u) | InsubNone of ~~ P x : insub_spec x None. Lemma insubP x : insub_spec x (insub x). Proof. by rewrite /insub; case: {-}_ / idP; [left; rewrite ?SubK | right; apply/negP]. Qed. Lemma insubT x Px : insub x = Some (Sub x Px). Admitted. Lemma insubF x : P x = false -> insub x = None. Proof. by move/idP; case: insubP. Qed. Lemma insubN x : ~~ P x -> insub x = None. Proof. by move/negPf/insubF. Qed. Lemma isSome_insub : ([eta insub] : pred T) =1 P. Proof. by apply: fsym => x; case: insubP => // /negPf. Qed. Lemma insubK : ocancel insub (@val _). Proof. by move=> x; case: insubP. Qed. Lemma valP (u : sT) : P (val u). Proof. by case/SubP: u => x Px; rewrite SubK. Qed. Lemma valK : pcancel (@val _) insub. Proof. by case/SubP=> x Px; rewrite SubK; apply: insubT. Qed. Lemma val_inj : injective (@val sT). Proof. exact: pcan_inj valK. Qed. Lemma valKd u0 : cancel (@val _) (insubd u0). Proof. by move=> u; rewrite /insubd valK. Qed. Lemma val_insubd u0 x : val (insubd u0 x) = if P x then x else val u0. Proof. by rewrite /insubd; case: insubP => [u -> | /negPf->]. Qed. Lemma insubdK u0 : {in P, cancel (insubd u0) (@val _)}. Proof. by move=> x Px; rewrite /= val_insubd [P x]Px. Qed. Definition insub_eq x := let Some_sub Px := Some (Sub x Px : sT) in let None_sub _ := None in (if P x as Px return P x = Px -> _ then Some_sub else None_sub) (erefl _). Lemma insub_eqE : insub_eq =1 insub. Proof. rewrite /insub_eq /insub => x; case: {2 3}_ / idP (erefl _) => // Px Px'. by congr (Some _); apply: val_inj; rewrite !SubK. Qed. End SubType. Arguments SubType [T P]. Arguments Sub [T P s]. Arguments vrefl [T P]. Arguments vrefl_rect [T P]. Arguments clone_subType [T P] U v [sT] _ [c Urec cK]. Arguments insub [T P sT]. Arguments insubT [T] P [sT x]. Arguments val_inj [T P sT]. Prenex Implicits val Sub vrefl vrefl_rect insub insubd val_inj. Local Notation inlined_sub_rect := (fun K K_S u => let (x, Px) as u return K u := u in K_S x Px). Local Notation inlined_new_rect := (fun K K_S u => let (x) as u return K u := u in K_S x). Notation "[ 'subType' 'for' v ]" := (SubType _ v _ inlined_sub_rect vrefl_rect) (at level 0, only parsing) : form_scope. Notation "[ 'sub' 'Type' 'for' v ]" := (SubType _ v _ _ vrefl_rect) (at level 0, format "[ 'sub' 'Type' 'for' v ]") : form_scope. Notation "[ 'subType' 'for' v 'by' rec ]" := (SubType _ v _ rec vrefl) (at level 0, format "[ 'subType' 'for' v 'by' rec ]") : form_scope. Notation "[ 'subType' 'of' U 'for' v ]" := (clone_subType U v id idfun) (at level 0, format "[ 'subType' 'of' U 'for' v ]") : form_scope. (* Notation "[ 'subType' 'for' v ]" := (clone_subType _ v id idfun) (at level 0, format "[ 'subType' 'for' v ]") : form_scope. *) Notation "[ 'subType' 'of' U ]" := (clone_subType U _ id id) (at level 0, format "[ 'subType' 'of' U ]") : form_scope. Definition NewType T U v c Urec := let Urec' P IH := Urec P (fun x : T => IH x isT : P _) in SubType U v (fun x _ => c x) Urec'. Arguments NewType [T U]. Notation "[ 'newType' 'for' v ]" := (NewType v _ inlined_new_rect vrefl_rect) (at level 0, only parsing) : form_scope. Notation "[ 'new' 'Type' 'for' v ]" := (NewType v _ _ vrefl_rect) (at level 0, format "[ 'new' 'Type' 'for' v ]") : form_scope. Notation "[ 'newType' 'for' v 'by' rec ]" := (NewType v _ rec vrefl) (at level 0, format "[ 'newType' 'for' v 'by' rec ]") : form_scope. Definition innew T nT x := @Sub T predT nT x (erefl true). Arguments innew [T nT]. Prenex Implicits innew. Lemma innew_val T nT : cancel val (@innew T nT). Proof. by move=> u; apply: val_inj; apply: SubK. Qed. (* Prenex Implicits and renaming. *) Notation sval := (@proj1_sig _ _). Notation "@ 'sval'" := (@proj1_sig) (at level 10, format "@ 'sval'"). Section SubEqType. Variables (T : eqType) (P : pred T) (sT : subType P). Local Notation ev_ax := (fun T v => @Equality.axiom T (fun x y => v x == v y)). Lemma val_eqP : ev_ax sT val. Proof. exact: inj_eqAxiom val_inj. Qed. Definition sub_eqMixin := EqMixin val_eqP. Canonical sub_eqType := Eval hnf in EqType sT sub_eqMixin. Definition SubEqMixin := (let: SubType _ v _ _ _ as sT' := sT return ev_ax sT' val -> Equality.class_of sT' in fun vP : ev_ax _ v => EqMixin vP ) val_eqP. Lemma val_eqE (u v : sT) : (val u == val v) = (u == v). Proof. by []. Qed. End SubEqType. Arguments val_eqP {T P sT x y}. Prenex Implicits val_eqP. Notation "[ 'eqMixin' 'of' T 'by' <: ]" := (SubEqMixin _ : Equality.class_of T) (at level 0, format "[ 'eqMixin' 'of' T 'by' <: ]") : form_scope. (* ssrnat ---------------------------------------------------------- *) Notation succn := Datatypes.S. Notation predn := Peano.pred. Notation "n .+1" := (succn n) (at level 2, left associativity, format "n .+1") : nat_scope. Notation "n .+2" := n.+1.+1 (at level 2, left associativity, format "n .+2") : nat_scope. Notation "n .+3" := n.+2.+1 (at level 2, left associativity, format "n .+3") : nat_scope. Notation "n .+4" := n.+2.+2 (at level 2, left associativity, format "n .+4") : nat_scope. Notation "n .-1" := (predn n) (at level 2, left associativity, format "n .-1") : nat_scope. Notation "n .-2" := n.-1.-1 (at level 2, left associativity, format "n .-2") : nat_scope. Fixpoint eqn m n {struct m} := match m, n with | 0, 0 => true | m'.+1, n'.+1 => eqn m' n' | _, _ => false end. Lemma eqnP : Equality.axiom eqn. Proof. move=> n m; apply: (iffP idP) => [|<-]; last by elim n. by elim: n m => [|n IHn] [|m] //= /IHn->. Qed. Canonical nat_eqMixin := EqMixin eqnP. Canonical nat_eqType := Eval hnf in EqType nat nat_eqMixin. Arguments eqnP {x y}. Prenex Implicits eqnP. Coercion nat_of_bool (b : bool) := if b then 1 else 0. Fixpoint odd n := if n is n'.+1 then ~~ odd n' else false. Lemma oddb (b : bool) : odd b = b. Proof. by case: b. Qed. Declare Scope nat_rec_scope. Set Warnings "-notation-overridden". Definition subn_rec := minus. Notation "m - n" := (subn_rec m n) : nat_rec_scope. Definition subn := nosimpl subn_rec. Notation "m - n" := (subn m n) : nat_scope. Definition leq m n := m - n == 0. Notation "m <= n" := (leq m n) : nat_scope. Notation "m < n" := (m.+1 <= n) : nat_scope. Notation "m >= n" := (n <= m) (only parsing) : nat_scope. Notation "m > n" := (n < m) (only parsing) : nat_scope. Notation "m <= n <= p" := ((m <= n) && (n <= p)) : nat_scope. Notation "m < n <= p" := ((m < n) && (n <= p)) : nat_scope. Notation "m <= n < p" := ((m <= n) && (n < p)) : nat_scope. Notation "m < n < p" := ((m < n) && (n < p)) : nat_scope. Open Scope nat_scope. Lemma ltnS m n : (m < n.+1) = (m <= n). Proof. by []. Qed. Lemma leq0n n : 0 <= n. Proof. by []. Qed. Lemma ltn0Sn n : 0 < n.+1. Proof. by []. Qed. Lemma ltn0 n : (n < 0) = false. Proof. by []. Qed. Lemma leqnn n : n <= n. Proof. by elim: n. Qed. #[global] Hint Resolve leqnn : core. Lemma leqnSn n : n <= n.+1. Proof. by elim: n. Qed. Lemma leq_trans n m p : m <= n -> n <= p -> m <= p. Admitted. Lemma leq_ltn_trans n m p : m <= n -> n < p -> m < p. Admitted. Lemma leqW m n : m <= n -> m <= n.+1. Admitted. #[global] Hint Resolve leqnSn : core. Lemma ltnW m n : m < n -> m <= n. Proof. exact: leq_trans. Qed. #[global] Hint Resolve ltnW : core. Definition addn_rec := plus. Notation "m + n" := (addn_rec m n) : nat_rec_scope. Definition addn := nosimpl addn_rec. Notation "m + n" := (addn m n) : nat_scope. Lemma addn0 : right_id 0 addn. Proof. by move=> n; apply/eqP; elim: n. Qed. Lemma add0n : left_id 0 addn. Proof. by []. Qed. Lemma addSn m n : m.+1 + n = (m + n).+1. Proof. by []. Qed. Lemma addnS m n : m + n.+1 = (m + n).+1. Proof. by elim: m. Qed. Lemma addnCA : left_commutative addn. Proof. by move=> m n p; elim: m => //= m; rewrite addnS => <-. Qed. Lemma addnC : commutative addn. Proof. by move=> m n; rewrite -{1}[n]addn0 addnCA addn0. Qed. Lemma addnA : associative addn. Proof. by move=> m n p; rewrite (addnC n) addnCA addnC. Qed. Lemma subnK m n : m <= n -> (n - m) + m = n. Admitted. Definition muln_rec := mult. Notation "m * n" := (muln_rec m n) : nat_rec_scope. Definition muln := nosimpl muln_rec. Notation "m * n" := (muln m n) : nat_scope. Lemma mul0n : left_zero 0 muln. Proof. by []. Qed. Lemma muln0 : right_zero 0 muln. Proof. by elim. Qed. Lemma mul1n : left_id 1 muln. Proof. exact: addn0. Qed. Lemma mulSn m n : m.+1 * n = n + m * n. Proof. by []. Qed. Lemma mulSnr m n : m.+1 * n = m * n + n. Proof. exact: addnC. Qed. Lemma mulnS m n : m * n.+1 = m + m * n. Proof. by elim: m => // m; rewrite !mulSn !addSn addnCA => ->. Qed. Lemma mulnSr m n : m * n.+1 = m * n + m. Proof. by rewrite addnC mulnS. Qed. Lemma muln1 : right_id 1 muln. Proof. by move=> n; rewrite mulnSr muln0. Qed. Lemma mulnC : commutative muln. Proof. by move=> m n; elim: m => [|m]; rewrite (muln0, mulnS) // mulSn => ->. Qed. Lemma mulnDl : left_distributive muln addn. Proof. by move=> m1 m2 n; elim: m1 => //= m1 IHm; rewrite -addnA -IHm. Qed. Lemma mulnDr : right_distributive muln addn. Proof. by move=> m n1 n2; rewrite !(mulnC m) mulnDl. Qed. Lemma mulnA : associative muln. Proof. by move=> m n p; elim: m => //= m; rewrite mulSn mulnDl => ->. Qed. Lemma mulnCA : left_commutative muln. Proof. by move=> m n1 n2; rewrite !mulnA (mulnC m). Qed. Lemma mulnAC : right_commutative muln. Proof. by move=> m n p; rewrite -!mulnA (mulnC n). Qed. Lemma mulnACA : interchange muln muln. Proof. by move=> m n p q; rewrite -!mulnA (mulnCA n). Qed. (* seq ------------------------------------------------------------- *) Declare Scope seq_scope. Delimit Scope seq_scope with SEQ. Open Scope seq_scope. (* Inductive seq (T : Type) : Type := Nil | Cons of T & seq T. *) Notation seq := list. Prenex Implicits cons. Notation Cons T := (@cons T) (only parsing). Notation Nil T := (@nil T) (only parsing). Bind Scope seq_scope with list. Arguments cons _%_type _ _%_SEQ. (* As :: and ++ are (improperly) declared in Init.datatypes, we only rebind *) (* them here. *) Infix "::" := cons : seq_scope. (* GG - this triggers a camlp4 warning, as if this Notation had been Reserved *) Notation "[ :: ]" := nil (at level 0, format "[ :: ]") : seq_scope. Notation "[ :: x1 ]" := (x1 :: [::]) (at level 0, format "[ :: x1 ]") : seq_scope. Notation "[ :: x & s ]" := (x :: s) (at level 0, only parsing) : seq_scope. Notation "[ :: x1 , x2 , .. , xn & s ]" := (x1 :: x2 :: .. (xn :: s) ..) (at level 0, format "'[hv' [ :: '[' x1 , '/' x2 , '/' .. , '/' xn ']' '/ ' & s ] ']'" ) : seq_scope. Notation "[ :: x1 ; x2 ; .. ; xn ]" := (x1 :: x2 :: .. [:: xn] ..) (at level 0, format "[ :: '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]" ) : seq_scope. Section Sequences. Variable n0 : nat. (* numerical parameter for take, drop et al *) Variable T : Type. (* must come before the implicit Type *) Variable x0 : T. (* default for head/nth *) Implicit Types x y z : T. Implicit Types m n : nat. Implicit Type s : seq T. Fixpoint size s := if s is _ :: s' then (size s').+1 else 0. Fixpoint cat s1 s2 := if s1 is x :: s1' then x :: s1' ++ s2 else s2 where "s1 ++ s2" := (cat s1 s2) : seq_scope. Lemma cat0s s : [::] ++ s = s. Proof. by []. Qed. Lemma cats0 s : s ++ [::] = s. Proof. by elim: s => //= x s ->. Qed. Lemma catA s1 s2 s3 : s1 ++ s2 ++ s3 = (s1 ++ s2) ++ s3. Proof. by elim: s1 => //= x s1 ->. Qed. Fixpoint nth s n {struct n} := if s is x :: s' then if n is n'.+1 then @nth s' n' else x else x0. Fixpoint rcons s z := if s is x :: s' then x :: rcons s' z else [:: z]. Variant last_spec : seq T -> Type := | LastNil : last_spec [::] | LastRcons s x : last_spec (rcons s x). Lemma lastP s : last_spec s. Proof using. Admitted. Lemma last_ind P : P [::] -> (forall s x, P s -> P (rcons s x)) -> forall s, P s. Proof using. Admitted. Section Map. Variables (T2 : Type) (f : T -> T2). Fixpoint map s := if s is x :: s' then f x :: map s' else [::]. End Map. Section SeqFind. Variable a : pred T. Fixpoint count s := if s is x :: s' then a x + count s' else 0. Fixpoint filter s := if s is x :: s' then if a x then x :: filter s' else filter s' else [::]. End SeqFind. End Sequences. Infix "++" := cat : seq_scope. Notation count_mem x := (count (pred_of_simpl (pred1 x))). Section EqSeq. Variables (n0 : nat) (T : eqType) (x0 : T). Local Notation nth := (nth x0). Implicit Type s : seq T. Implicit Types x y z : T. Fixpoint eqseq s1 s2 {struct s2} := match s1, s2 with | [::], [::] => true | x1 :: s1', x2 :: s2' => (x1 == x2) && eqseq s1' s2' | _, _ => false end. Lemma eqseqP : Equality.axiom eqseq. Proof. move; elim=> [|x1 s1 IHs] [|x2 s2]; do [by constructor | simpl]. case: (x1 =P x2) => [<-|neqx]; last by right; case. by apply: (iffP (IHs s2)) => [<-|[]]. Qed. Canonical seq_eqMixin := EqMixin eqseqP. Canonical seq_eqType := Eval hnf in EqType (seq T) seq_eqMixin. Fixpoint mem_seq (s : seq T) := if s is y :: s' then xpredU1 y (mem_seq s') else xpred0. Definition eqseq_class := seq T. Identity Coercion seq_of_eqseq : eqseq_class >-> seq. Coercion pred_of_eq_seq (s : eqseq_class) : {pred T} := [eta mem_seq s]. Canonical seq_predType := @PredType T (seq T) pred_of_eq_seq. Fixpoint uniq s := if s is x :: s' then (x \notin s') && uniq s' else true. End EqSeq. Definition bitseq := seq bool. Canonical bitseq_eqType := Eval hnf in [eqType of bitseq]. Canonical bitseq_predType := Eval hnf in [predType of bitseq]. Section Pmap. Variables (aT rT : Type) (f : aT -> option rT) (g : rT -> aT). Fixpoint pmap s := if s is x :: s' then let r := pmap s' in oapp (cons^~ r) r (f x) else [::]. End Pmap. Fixpoint iota m n := if n is n'.+1 then m :: iota m.+1 n' else [::]. Section FoldRight. Variables (T : Type) (R : Type) (f : T -> R -> R) (z0 : R). Fixpoint foldr s := if s is x :: s' then f x (foldr s') else z0. End FoldRight. Lemma mem_iota m n i : (i \in iota m n) = (m <= i) && (i < m + n). Admitted. (* choice ------------------------------------------------------------- *) Module Choice. Section ClassDef. Record mixin_of T := Mixin { find : pred T -> nat -> option T; _ : forall P n x, find P n = Some x -> P x; _ : forall P : pred T, (exists x, P x) -> exists n, find P n; _ : forall P Q : pred T, P =1 Q -> find P =1 find Q }. Record class_of T := Class {base : Equality.class_of T; mixin : mixin_of T}. Local Coercion base : class_of >-> Equality.class_of. Structure type := Pack {sort; _ : class_of sort; _ : Type}. Local Coercion sort : type >-> Sortclass. Variables (T : Type) (cT : type). Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c. Definition clone c of phant_id class c := @Pack T c T. Let xT := let: Pack T _ _ := cT in T. Notation xclass := (class : class_of xT). Definition pack m := fun b bT & phant_id (Equality.class bT) b => Pack (@Class T b m) T. (* Inheritance *) Definition eqType := @Equality.Pack cT xclass xT. End ClassDef. Module Import Exports. Coercion base : class_of >-> Equality.class_of. Coercion sort : type >-> Sortclass. Coercion eqType : type >-> Equality.type. Canonical eqType. Notation choiceType := type. Notation choiceMixin := mixin_of. Notation ChoiceType T m := (@pack T m _ _ id). Notation "[ 'choiceType' 'of' T 'for' cT ]" := (@clone T cT _ idfun) (at level 0, format "[ 'choiceType' 'of' T 'for' cT ]") : form_scope. Notation "[ 'choiceType' 'of' T ]" := (@clone T _ _ id) (at level 0, format "[ 'choiceType' 'of' T ]") : form_scope. End Exports. End Choice. Export Choice.Exports. Section ChoiceTheory. Variable T : choiceType. Section CanChoice. Variables (sT : Type) (f : sT -> T). Lemma PcanChoiceMixin f' : pcancel f f' -> choiceMixin sT. Admitted. Definition CanChoiceMixin f' (fK : cancel f f') := PcanChoiceMixin (can_pcan fK). End CanChoice. Section SubChoice. Variables (P : pred T) (sT : subType P). Definition sub_choiceMixin := PcanChoiceMixin (@valK T P sT). Definition sub_choiceClass := @Choice.Class sT (sub_eqMixin sT) sub_choiceMixin. Canonical sub_choiceType := Choice.Pack sub_choiceClass sT. End SubChoice. Fact seq_choiceMixin : choiceMixin (seq T). Admitted. Canonical seq_choiceType := Eval hnf in ChoiceType (seq T) seq_choiceMixin. End ChoiceTheory. Fact nat_choiceMixin : choiceMixin nat. Proof. pose f := [fun (P : pred nat) n => if P n then Some n else None]. exists f => [P n m | P [n Pn] | P Q eqPQ n] /=; last by rewrite eqPQ. by case: ifP => // Pn [<-]. by exists n; rewrite Pn. Qed. Canonical nat_choiceType := Eval hnf in ChoiceType nat nat_choiceMixin. Definition bool_choiceMixin := CanChoiceMixin oddb. Canonical bool_choiceType := Eval hnf in ChoiceType bool bool_choiceMixin. Canonical bitseq_choiceType := Eval hnf in [choiceType of bitseq]. Notation "[ 'choiceMixin' 'of' T 'by' <: ]" := (sub_choiceMixin _ : choiceMixin T) (at level 0, format "[ 'choiceMixin' 'of' T 'by' <: ]") : form_scope. Module Countable. Record mixin_of (T : Type) : Type := Mixin { pickle : T -> nat; unpickle : nat -> option T; pickleK : pcancel pickle unpickle }. Definition EqMixin T m := PcanEqMixin (@pickleK T m). Definition ChoiceMixin T m := PcanChoiceMixin (@pickleK T m). Section ClassDef. Record class_of T := Class { base : Choice.class_of T; mixin : mixin_of T }. Local Coercion base : class_of >-> Choice.class_of. Structure type : Type := Pack {sort : Type; _ : class_of sort; _ : Type}. Local Coercion sort : type >-> Sortclass. Variables (T : Type) (cT : type). Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c. Definition clone c of phant_id class c := @Pack T c T. Let xT := let: Pack T _ _ := cT in T. Notation xclass := (class : class_of xT). Definition pack m := fun bT b & phant_id (Choice.class bT) b => Pack (@Class T b m) T. Definition eqType := @Equality.Pack cT xclass xT. Definition choiceType := @Choice.Pack cT xclass xT. End ClassDef. Module Exports. Coercion base : class_of >-> Choice.class_of. Coercion mixin : class_of >-> mixin_of. Coercion sort : type >-> Sortclass. Coercion eqType : type >-> Equality.type. Canonical eqType. Coercion choiceType : type >-> Choice.type. Canonical choiceType. Notation countType := type. Notation CountType T m := (@pack T m _ _ id). Notation CountMixin := Mixin. Notation CountChoiceMixin := ChoiceMixin. Notation "[ 'countType' 'of' T 'for' cT ]" := (@clone T cT _ idfun) (at level 0, format "[ 'countType' 'of' T 'for' cT ]") : form_scope. Notation "[ 'countType' 'of' T ]" := (@clone T _ _ id) (at level 0, format "[ 'countType' 'of' T ]") : form_scope. End Exports. End Countable. Export Countable.Exports. Definition unpickle T := Countable.unpickle (Countable.class T). Definition pickle T := Countable.pickle (Countable.class T). Arguments unpickle [T]. Prenex Implicits pickle unpickle. Section CountableTheory. Variable T : countType. Lemma pickleK : @pcancel nat T pickle unpickle. Proof. exact: Countable.pickleK. Qed. Definition pickle_inv n := obind (fun x : T => if pickle x == n then Some x else None) (unpickle n). Lemma pickle_invK : ocancel pickle_inv pickle. Proof. by rewrite /pickle_inv => n; case def_x: (unpickle n) => //= [x]; case: eqP. Qed. Lemma pickleK_inv : pcancel pickle pickle_inv. Proof. by rewrite /pickle_inv => x; rewrite pickleK /= eqxx. Qed. Lemma pcan_pickleK sT f f' : @pcancel T sT f f' -> pcancel (pickle \o f) (pcomp f' unpickle). Proof. by move=> fK x; rewrite /pcomp pickleK /= fK. Qed. Definition PcanCountMixin sT f f' (fK : pcancel f f') := @CountMixin sT _ _ (pcan_pickleK fK). Definition CanCountMixin sT f f' (fK : cancel f f') := @PcanCountMixin sT _ _ (can_pcan fK). Definition sub_countMixin P sT := PcanCountMixin (@valK T P sT). End CountableTheory. Notation "[ 'countMixin' 'of' T 'by' <: ]" := (sub_countMixin _ : Countable.mixin_of T) (at level 0, format "[ 'countMixin' 'of' T 'by' <: ]") : form_scope. Section SubCountType. Variables (T : choiceType) (P : pred T). Import Countable. Structure subCountType : Type := SubCountType {subCount_sort :> subType P; _ : mixin_of subCount_sort}. Coercion sub_countType (sT : subCountType) := Eval hnf in pack (let: SubCountType _ m := sT return mixin_of sT in m) id. Canonical sub_countType. Definition pack_subCountType U := fun sT cT & sub_sort sT * sort cT -> U * U => fun b m & phant_id (Class b m) (class cT) => @SubCountType sT m. End SubCountType. (* This assumes that T has both countType and subType structures. *) Notation "[ 'subCountType' 'of' T ]" := (@pack_subCountType _ _ T _ _ id _ _ id) (at level 0, format "[ 'subCountType' 'of' T ]") : form_scope. Lemma nat_pickleK : pcancel id (@Some nat). Proof. by []. Qed. Definition nat_countMixin := CountMixin nat_pickleK. Canonical nat_countType := Eval hnf in CountType nat nat_countMixin. (* fintype --------------------------------------------------------- *) Module Finite. Section RawMixin. Variable T : eqType. Definition axiom e := forall x : T, count_mem x e = 1. Lemma uniq_enumP e : uniq e -> e =i T -> axiom e. Admitted. Record mixin_of := Mixin { mixin_base : Countable.mixin_of T; mixin_enum : seq T; _ : axiom mixin_enum }. End RawMixin. Section Mixins. Variable T : countType. Definition EnumMixin := let: Countable.Pack _ (Countable.Class _ m) _ as cT := T return forall e : seq cT, axiom e -> mixin_of cT in @Mixin (EqType _ _) m. Definition UniqMixin e Ue eT := @EnumMixin e (uniq_enumP Ue eT). Variable n : nat. End Mixins. Section ClassDef. Record class_of T := Class { base : Choice.class_of T; mixin : mixin_of (Equality.Pack base T) }. Definition base2 T c := Countable.Class (@base T c) (mixin_base (mixin c)). Local Coercion base : class_of >-> Choice.class_of. Structure type : Type := Pack {sort; _ : class_of sort; _ : Type}. Local Coercion sort : type >-> Sortclass. Variables (T : Type) (cT : type). Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c. Definition clone c of phant_id class c := @Pack T c T. Let xT := let: Pack T _ _ := cT in T. Notation xclass := (class : class_of xT). Definition pack b0 (m0 : mixin_of (EqType T b0)) := fun bT b & phant_id (Choice.class bT) b => fun m & phant_id m0 m => Pack (@Class T b m) T. Definition eqType := @Equality.Pack cT xclass xT. Definition choiceType := @Choice.Pack cT xclass xT. Definition countType := @Countable.Pack cT (base2 xclass) xT. End ClassDef. Module Import Exports. Coercion mixin_base : mixin_of >-> Countable.mixin_of. Coercion base : class_of >-> Choice.class_of. Coercion mixin : class_of >-> mixin_of. Coercion base2 : class_of >-> Countable.class_of. Coercion sort : type >-> Sortclass. Coercion eqType : type >-> Equality.type. Canonical eqType. Coercion choiceType : type >-> Choice.type. Canonical choiceType. Coercion countType : type >-> Countable.type. Canonical countType. Notation finType := type. Notation FinType T m := (@pack T _ m _ _ id _ id). Notation FinMixin := EnumMixin. Notation UniqFinMixin := UniqMixin. Notation "[ 'finType' 'of' T 'for' cT ]" := (@clone T cT _ idfun) (at level 0, format "[ 'finType' 'of' T 'for' cT ]") : form_scope. Notation "[ 'finType' 'of' T ]" := (@clone T _ _ id) (at level 0, format "[ 'finType' 'of' T ]") : form_scope. End Exports. Module Type EnumSig. Parameter enum : forall cT : type, seq cT. Axiom enumDef : enum = fun cT => mixin_enum (class cT). End EnumSig. Module EnumDef : EnumSig. Definition enum cT := mixin_enum (class cT). Definition enumDef := erefl enum. End EnumDef. Notation enum := EnumDef.enum. End Finite. Export Finite.Exports. Section SubFinType. Variables (T : choiceType) (P : pred T). Import Finite. Structure subFinType := SubFinType { subFin_sort :> subType P; _ : mixin_of (sub_eqType subFin_sort) }. Definition pack_subFinType U := fun cT b m & phant_id (class cT) (@Class U b m) => fun sT m' & phant_id m' m => @SubFinType sT m'. Implicit Type sT : subFinType. Definition subFin_mixin sT := let: SubFinType _ m := sT return mixin_of (sub_eqType sT) in m. Coercion subFinType_subCountType sT := @SubCountType _ _ sT (subFin_mixin sT). Canonical subFinType_subCountType. Coercion subFinType_finType sT := Pack (@Class sT (sub_choiceClass sT) (subFin_mixin sT)) sT. Canonical subFinType_finType. Definition enum_mem T (mA : mem_pred _) := filter mA (Finite.enum T). Definition image_mem T T' f mA : seq T' := map f (@enum_mem T mA). Definition codom T T' f := @image_mem T T' f (mem T). Lemma codom_val sT x : (x \in codom (val : sT -> T)) = P x. Admitted. End SubFinType. (* This assumes that T has both finType and subCountType structures. *) Notation "[ 'subFinType' 'of' T ]" := (@pack_subFinType _ _ T _ _ _ id _ _ id) (at level 0, format "[ 'subFinType' 'of' T ]") : form_scope. Section OrdinalSub. Variable n : nat. Inductive ordinal : predArgType := Ordinal m of m < n. Coercion nat_of_ord i := let: Ordinal m _ := i in m. Canonical ordinal_subType := [subType for nat_of_ord]. Definition ordinal_eqMixin := Eval hnf in [eqMixin of ordinal by <:]. Canonical ordinal_eqType := Eval hnf in EqType ordinal ordinal_eqMixin. Definition ordinal_choiceMixin := [choiceMixin of ordinal by <:]. Canonical ordinal_choiceType := Eval hnf in ChoiceType ordinal ordinal_choiceMixin. Definition ordinal_countMixin := [countMixin of ordinal by <:]. Canonical ordinal_countType := Eval hnf in CountType ordinal ordinal_countMixin. Canonical ordinal_subCountType := [subCountType of ordinal]. Lemma ltn_ord (i : ordinal) : i < n. Proof. exact: valP i. Qed. Lemma ord_inj : injective nat_of_ord. Proof. exact: val_inj. Qed. Definition ord_enum : seq ordinal := pmap insub (iota 0 n). Lemma val_ord_enum : map val ord_enum = iota 0 n. Admitted. Lemma ord_enum_uniq : uniq ord_enum. Admitted. Lemma mem_ord_enum i : i \in ord_enum. Admitted. Definition ordinal_finMixin := Eval hnf in UniqFinMixin ord_enum_uniq mem_ord_enum. Canonical ordinal_finType := Eval hnf in FinType ordinal ordinal_finMixin. Canonical ordinal_subFinType := Eval hnf in [subFinType of ordinal]. End OrdinalSub. Notation "''I_' n" := (ordinal n) (at level 8, n at level 2, format "''I_' n"). (* bigop ----------------------------------------------------------------- *) Reserved Notation "\big [ op / idx ]_ i F" (at level 36, F at level 36, op, idx at level 10, i at level 0, right associativity, format "'[' \big [ op / idx ]_ i '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i <- r | P ) F" (at level 36, F at level 36, op, idx at level 10, i, r at level 50, format "'[' \big [ op / idx ]_ ( i <- r | P ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i <- r ) F" (at level 36, F at level 36, op, idx at level 10, i, r at level 50, format "'[' \big [ op / idx ]_ ( i <- r ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" (at level 36, F at level 36, op, idx at level 10, m, i, n at level 50, format "'[' \big [ op / idx ]_ ( m <= i < n | P ) F ']'"). Reserved Notation "\big [ op / idx ]_ ( m <= i < n ) F" (at level 36, F at level 36, op, idx at level 10, i, m, n at level 50, format "'[' \big [ op / idx ]_ ( m <= i < n ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i | P ) F" (at level 36, F at level 36, op, idx at level 10, i at level 50, format "'[' \big [ op / idx ]_ ( i | P ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i : t | P ) F" (at level 36, F at level 36, op, idx at level 10, i at level 50, format "'[' \big [ op / idx ]_ ( i : t | P ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i : t ) F" (at level 36, F at level 36, op, idx at level 10, i at level 50, format "'[' \big [ op / idx ]_ ( i : t ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i < n | P ) F" (at level 36, F at level 36, op, idx at level 10, i, n at level 50, format "'[' \big [ op / idx ]_ ( i < n | P ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i < n ) F" (at level 36, F at level 36, op, idx at level 10, i, n at level 50, format "'[' \big [ op / idx ]_ ( i < n ) F ']'"). Reserved Notation "\big [ op / idx ]_ ( i 'in' A | P ) F" (at level 36, F at level 36, op, idx at level 10, i, A at level 50, format "'[' \big [ op / idx ]_ ( i 'in' A | P ) '/ ' F ']'"). Reserved Notation "\big [ op / idx ]_ ( i 'in' A ) F" (at level 36, F at level 36, op, idx at level 10, i, A at level 50, format "'[' \big [ op / idx ]_ ( i 'in' A ) '/ ' F ']'"). Module Monoid. Section Definitions. Variables (T : Type) (idm : T). Structure law := Law { operator : T -> T -> T; _ : associative operator; _ : left_id idm operator; _ : right_id idm operator }. Local Coercion operator : law >-> Funclass. Structure com_law := ComLaw { com_operator : law; _ : commutative com_operator }. Local Coercion com_operator : com_law >-> law. Structure mul_law := MulLaw { mul_operator : T -> T -> T; _ : left_zero idm mul_operator; _ : right_zero idm mul_operator }. Local Coercion mul_operator : mul_law >-> Funclass. Structure add_law (mul : T -> T -> T) := AddLaw { add_operator : com_law; _ : left_distributive mul add_operator; _ : right_distributive mul add_operator }. Local Coercion add_operator : add_law >-> com_law. Let op_id (op1 op2 : T -> T -> T) := phant_id op1 op2. Definition clone_law op := fun (opL : law) & op_id opL op => fun opmA op1m opm1 (opL' := @Law op opmA op1m opm1) & phant_id opL' opL => opL'. Definition clone_com_law op := fun (opL : law) (opC : com_law) & op_id opL op & op_id opC op => fun opmC (opC' := @ComLaw opL opmC) & phant_id opC' opC => opC'. Definition clone_mul_law op := fun (opM : mul_law) & op_id opM op => fun op0m opm0 (opM' := @MulLaw op op0m opm0) & phant_id opM' opM => opM'. Definition clone_add_law mop aop := fun (opC : com_law) (opA : add_law mop) & op_id opC aop & op_id opA aop => fun mopDm mopmD (opA' := @AddLaw mop opC mopDm mopmD) & phant_id opA' opA => opA'. End Definitions. Module Import Exports. Coercion operator : law >-> Funclass. Coercion com_operator : com_law >-> law. Coercion mul_operator : mul_law >-> Funclass. Coercion add_operator : add_law >-> com_law. Notation "[ 'law' 'of' f ]" := (@clone_law _ _ f _ id _ _ _ id) (at level 0, format"[ 'law' 'of' f ]") : form_scope. Notation "[ 'com_law' 'of' f ]" := (@clone_com_law _ _ f _ _ id id _ id) (at level 0, format "[ 'com_law' 'of' f ]") : form_scope. Notation "[ 'mul_law' 'of' f ]" := (@clone_mul_law _ _ f _ id _ _ id) (at level 0, format"[ 'mul_law' 'of' f ]") : form_scope. Notation "[ 'add_law' m 'of' a ]" := (@clone_add_law _ _ m a _ _ id id _ _ id) (at level 0, format "[ 'add_law' m 'of' a ]") : form_scope. End Exports. Section CommutativeAxioms. Variable (T : Type) (zero one : T) (mul add : T -> T -> T) (inv : T -> T). Hypothesis mulC : commutative mul. Lemma mulC_id : left_id one mul -> right_id one mul. Proof. by move=> mul1x x; rewrite mulC. Qed. Lemma mulC_zero : left_zero zero mul -> right_zero zero mul. Proof. by move=> mul0x x; rewrite mulC. Qed. Lemma mulC_dist : left_distributive mul add -> right_distributive mul add. Proof. by move=> mul_addl x y z; rewrite !(mulC x). Qed. End CommutativeAxioms. Module Theory. Section Theory. Variables (T : Type) (idm : T). Section Plain. Variable mul : law idm. Lemma mul1m : left_id idm mul. Proof. by case mul. Qed. Lemma mulm1 : right_id idm mul. Proof. by case mul. Qed. Lemma mulmA : associative mul. Proof. by case mul. Qed. (*Lemma iteropE n x : iterop n mul x idm = iter n (mul x) idm.*) End Plain. Section Commutative. Variable mul : com_law idm. Lemma mulmC : commutative mul. Proof. by case mul. Qed. Lemma mulmCA : left_commutative mul. Proof. by move=> x y z; rewrite !mulmA (mulmC x). Qed. Lemma mulmAC : right_commutative mul. Proof. by move=> x y z; rewrite -!mulmA (mulmC y). Qed. Lemma mulmACA : interchange mul mul. Proof. by move=> x y z t; rewrite -!mulmA (mulmCA y). Qed. End Commutative. Section Mul. Variable mul : mul_law idm. Lemma mul0m : left_zero idm mul. Proof. by case mul. Qed. Lemma mulm0 : right_zero idm mul. Proof. by case mul. Qed. End Mul. Section Add. Variables (mul : T -> T -> T) (add : add_law idm mul). Lemma addmA : associative add. Proof. exact: mulmA. Qed. Lemma addmC : commutative add. Proof. exact: mulmC. Qed. Lemma addmCA : left_commutative add. Proof. exact: mulmCA. Qed. Lemma addmAC : right_commutative add. Proof. exact: mulmAC. Qed. Lemma add0m : left_id idm add. Proof. exact: mul1m. Qed. Lemma addm0 : right_id idm add. Proof. exact: mulm1. Qed. Lemma mulm_addl : left_distributive mul add. Proof. by case add. Qed. Lemma mulm_addr : right_distributive mul add. Proof. by case add. Qed. End Add. Definition simpm := (mulm1, mulm0, mul1m, mul0m, mulmA). End Theory. End Theory. Include Theory. End Monoid. Export Monoid.Exports. Section PervasiveMonoids. Import Monoid. Canonical andb_monoid := Law andbA andTb andbT. Canonical andb_comoid := ComLaw andbC. Canonical andb_muloid := MulLaw andFb andbF. Canonical orb_monoid := Law orbA orFb orbF. Canonical orb_comoid := ComLaw orbC. Canonical orb_muloid := MulLaw orTb orbT. Canonical addb_monoid := Law addbA addFb addbF. Canonical addb_comoid := ComLaw addbC. Canonical orb_addoid := AddLaw andb_orl andb_orr. Canonical andb_addoid := AddLaw orb_andl orb_andr. Canonical addb_addoid := AddLaw andb_addl andb_addr. Canonical addn_monoid := Law addnA add0n addn0. Canonical addn_comoid := ComLaw addnC. Canonical muln_monoid := Law mulnA mul1n muln1. Canonical muln_comoid := ComLaw mulnC. Canonical muln_muloid := MulLaw mul0n muln0. Canonical addn_addoid := AddLaw mulnDl mulnDr. Canonical cat_monoid T := Law (@catA T) (@cat0s T) (@cats0 T). End PervasiveMonoids. Declare Scope big_scope. Delimit Scope big_scope with BIG. Open Scope big_scope. (* The bigbody wrapper is a workaround for a quirk of the Coq pretty-printer, *) (* which would fail to redisplay the \big notation when the or *) (* do not depend on the bound index. The BigBody constructor *) (* packages both in in a term in which i occurs; it also depends on the *) (* iterated , as this can give more information on the expected type of *) (* the , thus allowing for the insertion of coercions. *) Variant bigbody R I := BigBody of I & (R -> R -> R) & bool & R. Definition applybig {R I} (body : bigbody R I) x := let: BigBody _ op b v := body in if b then op v x else x. Definition reducebig R I idx r (body : I -> bigbody R I) := foldr (applybig \o body) idx r. Module Type BigOpSig. Parameter bigop : forall R I, R -> seq I -> (I -> bigbody R I) -> R. Axiom bigopE : bigop = reducebig. End BigOpSig. Module BigOp : BigOpSig. Definition bigop := reducebig. Lemma bigopE : bigop = reducebig. Proof. by []. Qed. End BigOp. Notation bigop := BigOp.bigop (only parsing). Canonical bigop_unlock := Unlockable BigOp.bigopE. Definition index_iota m n := iota m (n - m). Definition index_enum (T : finType) := Finite.enum T. Lemma mem_index_iota m n i : (i \in index_iota m n) = (m <= i < n). Admitted. Lemma mem_index_enum T i : i \in index_enum T. Admitted. #[global] Hint Resolve mem_index_enum : core. (* Lemma filter_index_enum T P : filter P (index_enum T) = enum P. Proof. by []. Qed. *) Notation "\big [ op / idx ]_ ( i <- r | P ) F" := (bigop idx r (fun i => BigBody i op P%B F)) : big_scope. Notation "\big [ op / idx ]_ ( i <- r ) F" := (bigop idx r (fun i => BigBody i op true F)) : big_scope. Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" := (bigop idx (index_iota m n) (fun i : nat => BigBody i op P%B F)) : big_scope. Notation "\big [ op / idx ]_ ( m <= i < n ) F" := (bigop idx (index_iota m n) (fun i : nat => BigBody i op true F)) : big_scope. Notation "\big [ op / idx ]_ ( i | P ) F" := (bigop idx (index_enum _) (fun i => BigBody i op P%B F)) : big_scope. Notation "\big [ op / idx ]_ i F" := (bigop idx (index_enum _) (fun i => BigBody i op true F)) : big_scope. Notation "\big [ op / idx ]_ ( i : t | P ) F" := (bigop idx (index_enum _) (fun i : t => BigBody i op P%B F)) (only parsing) : big_scope. Notation "\big [ op / idx ]_ ( i : t ) F" := (bigop idx (index_enum _) (fun i : t => BigBody i op true F)) (only parsing) : big_scope. Notation "\big [ op / idx ]_ ( i < n | P ) F" := (\big[op/idx]_(i : ordinal n | P%B) F) : big_scope. Notation "\big [ op / idx ]_ ( i < n ) F" := (\big[op/idx]_(i : ordinal n) F) : big_scope. Notation "\big [ op / idx ]_ ( i 'in' A | P ) F" := (\big[op/idx]_(i | (i \in A) && P) F) : big_scope. Notation "\big [ op / idx ]_ ( i 'in' A ) F" := (\big[op/idx]_(i | i \in A) F) : big_scope. Notation BIG_F := (F in \big[_/_]_(i <- _ | _) F i)%pattern. Notation BIG_P := (P in \big[_/_]_(i <- _ | P i) _)%pattern. (* Induction loading *) Lemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F : K (\big[op/idx]_(i <- r | P i) F i) * K' (\big[op/idx]_(i <- r | P i) F i) -> K' (\big[op/idx]_(i <- r | P i) F i). Proof. by case. Qed. Arguments big_load [R] K [K'] idx op [I]. Section Elim3. Variables (R1 R2 R3 : Type) (K : R1 -> R2 -> R3 -> Type). Variables (id1 : R1) (op1 : R1 -> R1 -> R1). Variables (id2 : R2) (op2 : R2 -> R2 -> R2). Variables (id3 : R3) (op3 : R3 -> R3 -> R3). Hypothesis Kid : K id1 id2 id3. Lemma big_rec3 I r (P : pred I) F1 F2 F3 (K_F : forall i y1 y2 y3, P i -> K y1 y2 y3 -> K (op1 (F1 i) y1) (op2 (F2 i) y2) (op3 (F3 i) y3)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i) (\big[op3/id3]_(i <- r | P i) F3 i). Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: K_F. Qed. Hypothesis Kop : forall x1 x2 x3 y1 y2 y3, K x1 x2 x3 -> K y1 y2 y3-> K (op1 x1 y1) (op2 x2 y2) (op3 x3 y3). Lemma big_ind3 I r (P : pred I) F1 F2 F3 (K_F : forall i, P i -> K (F1 i) (F2 i) (F3 i)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i) (\big[op3/id3]_(i <- r | P i) F3 i). Proof. by apply: big_rec3 => i x1 x2 x3 /K_F; apply: Kop. Qed. End Elim3. Arguments big_rec3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ [I r P F1 F2 F3]. Arguments big_ind3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ _ [I r P F1 F2 F3]. Section Elim2. Variables (R1 R2 : Type) (K : R1 -> R2 -> Type) (f : R2 -> R1). Variables (id1 : R1) (op1 : R1 -> R1 -> R1). Variables (id2 : R2) (op2 : R2 -> R2 -> R2). Hypothesis Kid : K id1 id2. Lemma big_rec2 I r (P : pred I) F1 F2 (K_F : forall i y1 y2, P i -> K y1 y2 -> K (op1 (F1 i) y1) (op2 (F2 i) y2)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i). Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: K_F. Qed. Hypothesis Kop : forall x1 x2 y1 y2, K x1 x2 -> K y1 y2 -> K (op1 x1 y1) (op2 x2 y2). Lemma big_ind2 I r (P : pred I) F1 F2 (K_F : forall i, P i -> K (F1 i) (F2 i)) : K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i). Proof. by apply: big_rec2 => i x1 x2 /K_F; apply: Kop. Qed. Hypotheses (f_op : {morph f : x y / op2 x y >-> op1 x y}) (f_id : f id2 = id1). Lemma big_morph I r (P : pred I) F : f (\big[op2/id2]_(i <- r | P i) F i) = \big[op1/id1]_(i <- r | P i) f (F i). Proof. by rewrite unlock; elim: r => //= i r <-; rewrite -f_op -fun_if. Qed. End Elim2. Arguments big_rec2 [R1 R2] K [id1 op1 id2 op2] _ [I r P F1 F2]. Arguments big_ind2 [R1 R2] K [id1 op1 id2 op2] _ _ [I r P F1 F2]. Arguments big_morph [R1 R2] f [id1 op1 id2 op2] _ _ [I]. Section Elim1. Variables (R : Type) (K : R -> Type) (f : R -> R). Variables (idx : R) (op op' : R -> R -> R). Hypothesis Kid : K idx. Lemma big_rec I r (P : pred I) F (Kop : forall i x, P i -> K x -> K (op (F i) x)) : K (\big[op/idx]_(i <- r | P i) F i). Proof. by rewrite unlock; elim: r => //= i r; case: ifP => //; apply: Kop. Qed. Hypothesis Kop : forall x y, K x -> K y -> K (op x y). Lemma big_ind I r (P : pred I) F (K_F : forall i, P i -> K (F i)) : K (\big[op/idx]_(i <- r | P i) F i). Proof. by apply: big_rec => // i x /K_F /Kop; apply. Qed. Hypothesis Kop' : forall x y, K x -> K y -> op x y = op' x y. Lemma eq_big_op I r (P : pred I) F (K_F : forall i, P i -> K (F i)) : \big[op/idx]_(i <- r | P i) F i = \big[op'/idx]_(i <- r | P i) F i. Proof. by elim/(big_load K): _; elim/big_rec2: _ => // i _ y Pi [Ky <-]; auto. Qed. Hypotheses (fM : {morph f : x y / op x y}) (f_id : f idx = idx). Lemma big_endo I r (P : pred I) F : f (\big[op/idx]_(i <- r | P i) F i) = \big[op/idx]_(i <- r | P i) f (F i). Proof. exact: big_morph. Qed. End Elim1. Arguments big_rec [R] K [idx op] _ [I r P F]. Arguments big_ind [R] K [idx op] _ _ [I r P F]. Arguments eq_big_op [R] K [idx op] op' _ _ _ [I]. Arguments big_endo [R] f [idx op] _ _ [I]. (* zmodp -------------------------------------------------------------------- *) Lemma ord1 : all_equal_to (@Ordinal 1 0 is_true_true : 'I_1). Admitted. rocq-9.2.0/test-suite/prerequisite/ssr_ssrsyntax1.v000066400000000000000000000021331516144147600225420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Type := | nil : t A 0 | cons : A -> forall n : nat, t A n -> t A (S n). Fixpoint map {A B} (f : A -> B) {n} (v : t A n) : t B n := match v in (Vector.t _ n0) return (Vector.t B n0) with | nil _ => nil B | cons _ a n0 v' => cons B (f a) n0 (map f v') end. Definition caseS {A} (P : forall {n}, t A (S n) -> Type) (H : forall h {n} t, @P n (cons _ h _ t)) {n} (v: t A (S n)) : P v := match v with | cons _ h _ t => H h t | _ => fun devil => False_ind (@IDProp) devil (* subterm !!! *) end. Definition tl {A} := @caseS _ (fun n v => t A n) (fun h n t => t). End Vector. rocq-9.2.0/test-suite/primitive/000077500000000000000000000000001516144147600166155ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/arrays/000077500000000000000000000000001516144147600201165ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/arrays/copy.v000066400000000000000000000013571516144147600212650ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. Definition t : array nat := [| 1; 5; 2 | 4 |]. Definition t' : array nat := PrimArray.copy t. Definition foo1 := (eq_refl : t'.[1] = 5). Definition foo2 := (eq_refl 5 <: t'.[1] = 5). Definition foo3 := (eq_refl 5 <<: t'.[1] = 5). Definition x1 := Eval compute in t'.[1]. Definition foo4 := (eq_refl : x1 = 5). Definition x2 := Eval cbn in t'.[1]. Definition foo5 := (eq_refl : x2 = 5). Definition foo6 := (eq_refl : t.[1] = 5). Definition foo7 := (eq_refl 5 <: t.[1] = 5). Definition foo8 := (eq_refl 5 <<: t.[1] = 5). Definition x3 := Eval compute in t.[1]. Definition foo9 := (eq_refl : x3 = 5). Definition x4 := Eval cbn in t.[1]. Definition foo10 := (eq_refl : x4 = 5). rocq-9.2.0/test-suite/primitive/arrays/default.v000066400000000000000000000006241516144147600217330ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Definition t : array nat := [| 1; 3; 2 | 4 |]. Definition foo1 := (eq_refl : default t = 4). Definition foo2 := (eq_refl 4 <: default t = 4). Definition foo3 := (eq_refl 4 <<: default t = 4). Definition x1 := Eval compute in default t. Definition foo4 := (eq_refl : x1 = 4). Definition x2 := Eval cbn in default t. Definition foo5 := (eq_refl : x2 = 4). rocq-9.2.0/test-suite/primitive/arrays/get.v000066400000000000000000000067311516144147600210730ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. (* Test reduction of primitives on array with kernel conversion, vm_compute, native_compute, cbv, cbn *) (* Immediate values *) Definition t : array nat := [| 1; 3; 2 | 4 |]. Definition foo1 := (eq_refl : t.[0] = 1). Definition foo2 := (eq_refl 1 <: t.[0] = 1). Definition foo3 := (eq_refl 1 <<: t.[0] = 1). Definition x1 := Eval compute in t.[0]. Definition foo4 := (eq_refl : x1 = 1). Definition x2 := Eval cbn in t.[0]. Definition foo5 := (eq_refl : x2 = 1). Definition foo6 := (eq_refl : t.[2] = 2). Definition foo7 := (eq_refl 2 <: t.[2] = 2). Definition foo8 := (eq_refl 2 <<: t.[2] = 2). Definition x3 := Eval compute in t.[2]. Definition foo9 := (eq_refl : x3 = 2). Definition x4 := Eval cbn in t.[2]. Definition foo10 := (eq_refl : x4 = 2). Definition foo11 := (eq_refl : t.[99] = 4). Definition foo12 := (eq_refl 4 <: t.[99] = 4). Definition foo13 := (eq_refl 4 <<: t.[99] = 4). Definition x5 := Eval compute in t.[4]. Definition foo14 := (eq_refl : x5 = 4). Definition x6 := Eval cbn in t.[4]. Definition foo15 := (eq_refl : x6 = 4). (* Computations inside the array *) Definition t2 : array nat := [| 1 + 3 | 5 |]. Definition foo16 := (eq_refl : t2.[0] = 4). Definition foo17 := (eq_refl 4 <: t2.[0] = 4). Definition foo18 := (eq_refl 4 <<: t2.[0] = 4). Definition x7 := Eval compute in t2.[0]. Definition foo19 := (eq_refl : x7 = 4). Definition x8 := Eval cbn in t2.[0]. Definition foo20 := (eq_refl : x8 = 4). (* Functions inside the array *) Definition t3 : array (nat -> nat) := [| fun x => x | fun x => O |]. Definition foo21 := (eq_refl : t3.[0] 2 = 2). Definition foo22 := (eq_refl 2 <: t3.[0] 2 = 2). Definition foo23 := (eq_refl 2 <<: t3.[0] 2 = 2). Definition x9 := Eval compute in t3.[0] 2. Definition foo24 := (eq_refl : x9 = 2). Definition x10 := Eval cbn in t3.[0] 2. Definition foo25 := (eq_refl : x10 = 2). Ltac check_const_eq name constr := let v := (eval cbv delta [name] in name) in tryif constr_eq v constr then idtac else fail 0 "Not syntactically equal:" name ":=" v "<>" constr. Notation check_const_eq name constr := (ltac:(check_const_eq name constr; exact constr)) (only parsing). (* Stuck primitive *) Definition lazy_stuck_get := Eval lazy in (fun A (t : array A) => t.[0]). Definition vm_stuck_get := Eval vm_compute in (fun A (t : array A) => t.[0]). Definition native_stuck_get := Eval native_compute in (fun A (t : array A) => t.[0]). Definition compute_stuck_get := Eval compute in (fun A (t : array A) => t.[0]). Definition cbn_stuck_get := Eval cbn in (fun A (t : array A) => t.[0]). Check check_const_eq lazy_stuck_get (fun A (t : array A) => t.[0]). Check check_const_eq vm_stuck_get (fun A (t : array A) => t.[0]). Check check_const_eq native_stuck_get (fun A (t : array A) => t.[0]). Check check_const_eq compute_stuck_get (fun A (t : array A) => t.[0]). Check check_const_eq cbn_stuck_get (fun A (t : array A) => t.[0]). (* Under-application *) Definition lazy_get := Eval lazy in @PrimArray.get. Definition vm_get := Eval vm_compute in @PrimArray.get. Definition native_get := Eval native_compute in @PrimArray.get. Definition compute_get := Eval compute in @PrimArray.get. Definition cbn_get := Eval cbn in @PrimArray.get. Check check_const_eq lazy_get (@PrimArray.get). Check check_const_eq vm_get (fun A (t : array A) i => t.[i]). Check check_const_eq native_get (fun A (t : array A) i => t.[i]). Check check_const_eq compute_get (@PrimArray.get). Check check_const_eq cbn_get (@PrimArray.get). rocq-9.2.0/test-suite/primitive/arrays/length.v000066400000000000000000000007371516144147600215750ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope uint63_scope. Definition t : array nat := [| 1; 3; 2 | 4 |]%nat. Definition foo1 := (eq_refl : PrimArray.length t = 3). Definition foo2 := (eq_refl 3 <: PrimArray.length t = 3). Definition foo3 := (eq_refl 3 <<: PrimArray.length t = 3). Definition x1 := Eval compute in PrimArray.length t. Definition foo4 := (eq_refl : x1 = 3). Definition x2 := Eval cbn in PrimArray.length t. Definition foo5 := (eq_refl : x2 = 3). rocq-9.2.0/test-suite/primitive/arrays/literal.v000066400000000000000000000002361516144147600217420ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. Definition t1 : array nat := [| 3; 3; 3; 3 | 3 |]. Definition t2 := [|Type|Type|]. rocq-9.2.0/test-suite/primitive/arrays/make.v000066400000000000000000000012011516144147600212140ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. (* Immediate values *) Definition t1 : array nat := [| 3; 3; 3; 3 | 3 |]. Definition t2 := PrimArray.make 4 3. Definition foo1 := (eq_refl : t1 = t2). Definition foo2 := (eq_refl t1 <: t1 = t2). Definition foo3 := (eq_refl t1 <<: t1 = t2). Definition x1 := Eval compute in t2. Definition foo4 := (eq_refl : x1 = t1). Definition x2 := Eval cbn in t2. Definition foo5 := (eq_refl : x2 = t1). Definition partial1 := Eval lazy in @PrimArray.make. Definition partial2 := Eval vm_compute in @PrimArray.make. Definition partial3 := Eval native_compute in @PrimArray.make. rocq-9.2.0/test-suite/primitive/arrays/max_length.v000066400000000000000000000011071516144147600224320ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope uint63_scope. Definition max_length := 4194303. Definition foo1 := (eq_refl max_length : PrimArray.max_length = max_length). Definition foo2 := (eq_refl max_length <: PrimArray.max_length = max_length). Definition foo3 := (eq_refl max_length <<: PrimArray.max_length = max_length). Definition max_length2 := Eval compute in PrimArray.max_length. Definition foo4 := (eq_refl : max_length = max_length2). Definition max_length3 := Eval cbn in PrimArray.max_length. Definition foo5 := (eq_refl : max_length = max_length3). rocq-9.2.0/test-suite/primitive/arrays/nested.v000066400000000000000000000015001516144147600215630ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. Module OneLevel. Inductive foo : Set := C : array foo -> foo. Fixpoint f1 (x : foo) {struct x} : False := match x with | C t => f1 (t.[0]) end. Fixpoint f2 (x : foo) {struct x} : False := f2 match x with | C t => t.[0] end. Fixpoint f3 (x : foo) {struct x} : False := match x with | C t => f3 (PrimArray.default t) end. End OneLevel. Module TwoLevels. Inductive foo : Set := C : array (array foo) -> foo. Fixpoint f1 (x : foo) {struct x} : False := match x with | C t => f1 (t.[0].[0]) end. Fixpoint f2 (x : foo) {struct x} : False := f2 match x with | C t => t.[0].[0] end. Fixpoint f3 (x : foo) {struct x} : False := match x with | C t => f3 (PrimArray.default (PrimArray.default t)) end. End TwoLevels. rocq-9.2.0/test-suite/primitive/arrays/set.v000066400000000000000000000061741516144147600211100ustar00rootroot00000000000000From Corelib Require Import PrimInt63 PrimArray. Open Scope array_scope. Definition t : array nat := [| 1; 3; 2 | 4 |]. Definition t' : array nat := t.[1 <- 5]. Definition foo1 := (eq_refl : t'.[1] = 5). Definition foo2 := (eq_refl 5 <: t'.[1] = 5). Definition foo3 := (eq_refl 5 <<: t'.[1] = 5). Definition x1 := Eval compute in t'.[1]. Definition foo4 := (eq_refl : x1 = 5). Definition x2 := Eval cbn in t'.[1]. Definition foo5 := (eq_refl : x2 = 5). Definition foo6 := (eq_refl : t.[1] = 3). Definition foo7 := (eq_refl 3 <: t.[1] = 3). Definition foo8 := (eq_refl 3 <<: t.[1] = 3). Definition x3 := Eval compute in t.[1]. Definition foo9 := (eq_refl : x3 = 3). Definition x4 := Eval cbn in t.[1]. Definition foo10 := (eq_refl : x4 = 3). Ltac check_const_eq name constr := let v := (eval cbv delta [name] in name) in tryif constr_eq v constr then idtac else fail 0 "Not syntactically equal:" name ":=" v "<>" constr. Notation check_const_eq name constr := (ltac:(check_const_eq name constr; exact constr)) (only parsing). (* Stuck primitive *) Definition lazy_stuck_set := Eval lazy in (fun A (t : array A) v => t.[1 <- v]). Definition vm_stuck_set := Eval vm_compute in (fun A (t : array A) v => t.[1 <- v]). Definition native_stuck_set := Eval native_compute in (fun A (t : array A) v => t.[1 <- v]). Definition compute_stuck_set := Eval compute in (fun A (t : array A) v => t.[1 <- v]). Definition cbn_stuck_set := Eval cbn in (fun A (t : array A) v => t.[1 <- v]). Check check_const_eq lazy_stuck_set (fun A (t : array A) v => t.[1 <- v]). Check check_const_eq vm_stuck_set (fun A (t : array A) v => t.[1 <- v]). Check check_const_eq native_stuck_set (fun A (t : array A) v => t.[1 <- v]). Check check_const_eq compute_stuck_set (fun A (t : array A) v => t.[1 <- v]). Check check_const_eq cbn_stuck_set (fun A (t : array A) v => t.[1 <- v]). (* Not stuck primitive, but with an accumulator as last argument *) Definition lazy_accu_set := Eval lazy in (fun v => t.[1 <- v]). Definition vm_accu_set := Eval vm_compute in (fun v => t.[1 <- v]). Definition native_accu_set := Eval native_compute in (fun v => t.[1 <- v]). Definition compute_accu_set := Eval compute in (fun v => t.[1 <- v]). Definition cbn_accu_set := Eval cbn in (fun v => t.[1 <- v]). Check check_const_eq lazy_accu_set (fun v => [| 1; v; 2 | 4 |]). Check check_const_eq vm_accu_set (fun v => [| 1; v; 2 | 4 |]). Check check_const_eq native_accu_set (fun v => [| 1; v; 2 | 4 |]). Check check_const_eq compute_accu_set (fun v => [| 1; v; 2 | 4 |]). Check check_const_eq cbn_accu_set (fun v => [| 1; v; 2 | 4 |]). (* Under-application *) Definition lazy_set := Eval lazy in @PrimArray.set. Definition vm_set := Eval vm_compute in @PrimArray.set. Definition native_set := Eval native_compute in @PrimArray.set. Definition compute_set := Eval compute in @PrimArray.set. Definition cbn_set := Eval cbn in @PrimArray.set. Check check_const_eq lazy_set (@PrimArray.set). Check check_const_eq vm_set (fun A (t : array A) i v => t.[i <- v]). Check check_const_eq native_set (fun A (t : array A) i v => t.[i <- v]). Check check_const_eq compute_set (@PrimArray.set). Check check_const_eq cbn_set (@PrimArray.set). rocq-9.2.0/test-suite/primitive/arrays/univs.v000066400000000000000000000002001516144147600214410ustar00rootroot00000000000000Primitive array := #array_type. Fail Check [| | nat : Set |]@{Set}. Check [| | nat : Set |]@{_}. Check [| | 0 : nat |]@{Set}. rocq-9.2.0/test-suite/primitive/float/000077500000000000000000000000001516144147600177225ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/float/classify.v000066400000000000000000000010051516144147600217220ustar00rootroot00000000000000Require Import FloatClass PrimFloat. Definition epsilon := 0x0.4p-1022%float. (* Z.ldexp_one (-1024)%Z *) Check (eq_refl : classify one = PNormal). Check (eq_refl : classify (- one)%float = NNormal). Check (eq_refl : classify epsilon = PSubn). Check (eq_refl : classify (- epsilon)%float = NSubn). Check (eq_refl : classify zero = PZero). Check (eq_refl : classify neg_zero = NZero). Check (eq_refl : classify infinity = PInf). Check (eq_refl : classify neg_infinity = NInf). Check (eq_refl : classify nan = NaN). rocq-9.2.0/test-suite/primitive/float/compare.v000066400000000000000000000125631516144147600215460ustar00rootroot00000000000000(* DO NOT EDIT THIS FILE: automatically generated by ./gen_compare.sh *) Require Import PrimFloat. Local Open Scope float_scope. Definition min_denorm := 0x0.0000000000001p-1022%float. (* Z.ldexp one (-1074)%Z *) Definition min_norm := 0x0.4p-1022%float. (* Z.ldexp_one (-1024)%Z *) Check (eq_refl : (nan =? nan) = false). Check (eq_refl : (nan =? nan) = false). Check (eq_refl : (nan compare.v cat <&2 "genTest expects 10 arguments" fi OPS=("=?" " int | FLOAT => float | SPEC_FLOAT => spec_float end. (** ** Fully-instantiated ("bare") specifications *) (** (Perhaps we want a better name than "bare" meaning "no binders"? *) (** As we'll see later, we check for [EQ l r] that [l] and [r] are [Constr.equal], and we'll check for [IFF (x = y) (x' = y')] that [Constr.equal x y] and [Constr.equal x' y'] are the same. (We don't currently support reporting results about [IFF A B] for [A] and [B] not equalities. *) Inductive BARE_SPEC := | EQ {T1 T2} (lhs : T1) (rhs : T2) | IFF {T1 T2} (lhs : T1) (rhs : T2). (** A [SPEC] is a [BARE_SPEC] prenex-quanified over known variable types. We hold the original proposition here so that we can pretty-print it easily *) Inductive SPEC := | BARE {U : Prop} (spec : U) (* for printing purposes *) (s : BARE_SPEC) | FORALL (T : SPEC_VAR_TYPE) (s : T -> SPEC). (** An [ANNOTATED_BARE_SPEC] holds the [BARE_SPEC] and also the propositional spec for pretty-printing of results. *) Definition ANNOTATED_BARE_SPEC : Type := BARE_SPEC * {P : Prop | P}. (* missing list functions *) Section FlatMap. Variables (A : Type) (B : Type). Variable f : A -> list B. Definition flat_map := fix flat_map (l:list A) : list B := match l with | nil => nil | cons x t => (f x)++(flat_map t) end. End FlatMap. Arguments flat_map [_ _]. Section ListPairs. Variables (A : Type) (B : Type). Fixpoint combine (l : list A) (l' : list B) : list (A*B) := match l,l' with | x::tl, y::tl' => (x,y)::(combine tl tl') | _, _ => nil end. End ListPairs. Arguments combine [_ _]. (** ** Machinery for instantiating specifications with all examples *) Fixpoint instantiate1_all_ways (s : SPEC) : list ANNOTATED_BARE_SPEC := match s with | @BARE U spec s => cons (s, exist _ U spec) nil | @FORALL T s => flat_map (fun v => instantiate1_all_ways (s v)) match T with | INT => tricky_ints | FLOAT => tricky_floats | SPEC_FLOAT => tricky_spec_floats end end. Definition instantiate_all_ways_nored (ls : list SPEC) : list ANNOTATED_BARE_SPEC := flat_map instantiate1_all_ways ls. Definition instantiate_all_ways (ls : list SPEC) : list ANNOTATED_BARE_SPEC := Eval cbv in instantiate_all_ways_nored ls. (** ** Some General Ltac2 Machinery *) Import Ltac2.Constr. Import Constr.Unsafe. Ltac2 Type exn ::= [ PrimFloat_Test_InternalError (message) | PrimFloat_SpecTest_Failed (message) ]. Ltac2 Type exn ::= [ Reification_error (message) | Reification_unhandled_kind (message, kind) ]. Ltac2 unify_bool (x : constr) (y : constr) : bool := match Control.case (fun () => Std.unify x y) with | Val _ => true | Err _ => false end. Ltac2 lf () := String.make 1 (Char.of_int 10). Ltac2 rec count_prod (x : constr) : int := match kind x with | Cast x _ _ => count_prod x | Prod _ x => Int.add 1 (count_prod x) | _ => 0 end. Ltac2 mkApp f x := Unsafe.make (App f (Array.of_list x)). Ltac2 mkRel i := Unsafe.make (Rel i). Ltac2 mkLambda b body := Unsafe.make (Lambda b body). (** ** Reification of known variable types *) Ltac2 reify_var_type (t : constr) : constr := match List.assoc_opt Constr.equal t [('spec_float, 'SPEC_FLOAT) ; ('float, 'FLOAT) ; ('int, 'INT)] with | Some v => v | None => Control.throw (Reification_error (fprintf "Unhandled type %t" t)) end. (** ** A kludgy hack we have to do to support some specifications that aren't equalities but have case statements out front *) (** turns [let '(x, y) := z in w = q] into [(let '(x, y) := z in w) = (let '(x, y) := z in q)] *) (** Does not run typechecking, and therefore works on open terms (with unbound rels) *) Ltac2 rec push_case_eq (tag : constr) (mkCase : constr (* retty *) -> constr -> constr) (branch : constr) : constr := match kind branch with | Lambda b body => push_case_eq tag (fun retty body => mkCase retty (mkLambda b body)) body | App f args => if Constr.equal f '@eq then let ty := Array.get args 0 in let x := Array.get args 1 in let y := Array.get args 2 in mkApp f [ty; mkCase ty x; mkCase ty y] else Control.throw (Reification_error (fprintf "Unrecognized under case %t (from %t from %t)" f branch tag)) | _ => Control.throw (Reification_error (fprintf "Unrecognized kind under case %t (from %t)" branch tag)) end. Ltac2 swap_case_eq (x : constr) : constr := match kind x with | Case c (retty, rel) ci discr branches => if Int.equal 1 (Array.length branches) then match kind retty with | Lambda retty_b rtProp => if Constr.equal rtProp 'Prop then push_case_eq x (fun retty b => Unsafe.make (Case c (mkLambda retty_b (liftn 1 1 retty), rel) ci discr (Array.of_list [b]))) (Array.get branches 0) else x | _ => x end else x | _ => x end. (** ** Reification of specifications after binders have been removed *) (** Does not run typechecking, and therefore works on open terms (with unbound rels) *) Ltac2 reify_bare_spec (ty : constr) : constr := let ty := swap_case_eq ty in match kind ty with | App f args => if Constr.equal f '@eq then Unsafe.make (App (mkApp '@EQ [Array.get args 0]) args) else if Constr.equal f '@iff then Unsafe.make (App (mkApp '@IFF ['Prop; 'Prop]) args) else Control.throw (Reification_error (fprintf "Unhandled base spec app %t" ty)) | k => Control.throw (Reification_unhandled_kind (fprintf "Unhandled base spec %t" ty) k) end. (** ** Reification of specs, including binders *) (** [n] is how many binders are left to remove in [spec], and therefore which [Rel] the [spec] should be eventually applied to *) Ltac2 rec reify_spec' (ty : constr) (spec : constr) (n : int) : constr := match kind ty with | Cast ty _ _ => reify_spec' ty spec n | Prod b body => let ty := reify_var_type (Binder.type b) in let body := reify_spec' body (mkApp spec [mkRel n]) (Int.sub n 1) in mkApp 'FORALL [ty; mkLambda b body] | _ => let r := reify_bare_spec ty in mkApp '@BARE [ty; spec; r] end. Ltac2 reify_spec (spec : constr) : constr := let ty := Constr.type spec in reify_spec' ty spec (count_prod ty). Notation "` x" := (ltac2:(let v := reify_spec (pretype x) in exact $v)) (only parsing, at level 10). (** * Machinery for reporting results *) Ltac2 report_result (red : string) (result : constr) (specTy : constr) (spec : constr) : message option := let msg := lazy_match! result with | EQ ?x ?y => if Constr.equal x y then None else (* if unify_bool x y (* commented out because of https://github.com/rocq-prover/rocq/pull/17899 *) then Some (fprintf "%s failed to fully reduce, leaving over %t (expected: %t), in %t %t" red x y spec specTy) else *) Some (fprintf "%s failed!%sGot: %t%sExpected: %t%sIn %t %t" red (lf ()) x (lf ()) y (lf ()) spec specTy) | IFF (?x = ?x') (?y = ?y') => let (lhs, rhs) := lazy_match! result with | IFF ?lhs ?rhs => (lhs, rhs) | _ => Control.throw (PrimFloat_Test_InternalError (fprintf "Impossible! Result branch mismatch %t" result)) end in let descr := if unify_bool y y' then "should" else "should not" in if Bool.and (Bool.equal (Constr.equal x x') (Constr.equal y y')) (Bool.equal (unify_bool x x') (unify_bool y y')) then None else (* if Bool.equal (unify_bool x x') (unify_bool y y') (* commented out because of https://github.com/rocq-prover/rocq/pull/17899 *) then Some (fprintf "%s failed to fully reduce, leaving over %t (expected something equivalent to: %t), in %t %t" red lhs rhs spec specTy) else *) Some (fprintf "%s failed!%sGot: %t%sExpected something equivalent to: %t%s(both sides %s unify)%sIn %t %t" red (lf ()) lhs (lf ()) rhs (lf ()) descr (lf ()) spec specTy) | _ => Control.throw (PrimFloat_Test_InternalError (fprintf "Unhandled result %t (on %t : %t with %s)" result spec specTy red)) end in match msg with | Some msg => Message.print (Message.concat (Message.of_string "Test Error: ") msg) | None => () end; msg. Ltac2 rec report_results_gen (error_early : bool) (red : string) (results : constr) : unit := lazy_match! results with | nil => () | cons (?res, exist _ ?specTy ?spec) ?results => let err := report_result red res specTy spec in let check_rest () := report_results_gen error_early red results in let zero_err () := match err with | Some err => Control.zero (PrimFloat_SpecTest_Failed err) | None => () end in if error_early then (zero_err (); check_rest ()) else (check_rest (); zero_err ()) | cons ?v _ => Control.throw (PrimFloat_Test_InternalError (fprintf "Invalid result format %t" v)) | _ => let results' := Std.eval_hnf results in if Constr.equal results results' then Control.throw (PrimFloat_Test_InternalError (fprintf "Results must be a literal list, not %t" results)) else report_results_gen error_early red results' end. Ltac2 report_results red results := report_results_gen false red results. Ltac2 report_results_fast red results := report_results_gen true red results. (** *************************************************************************) (** * List of (reified) specifications *) (** EDIT HERE TO ADD MORE TESTS *) (* [Prim2SF_SF2Prim] has an hypothesis not handled by the above machinery so let's check something stronger in theory but equivalent in practice, since all test cases satisfy the hypothesis by construction. *) Axiom Prim2SF_SF2Prim' : forall x, (* valid_binary x = true -> *) Prim2SF (SF2Prim x) = x. Definition spec_list : list SPEC := [ `Prim2SF_valid ; `SF2Prim_Prim2SF ; `Prim2SF_SF2Prim' ; `opp_spec ; `abs_spec ; `eqb_spec ; `ltb_spec ; `leb_spec ; `compare_spec ; `Leibniz.eqb_spec ; `classify_spec ; `mul_spec ; `add_spec ; `sub_spec ; `div_spec ; `sqrt_spec ; `of_uint63_spec ; `normfr_mantissa_spec ; `frshiftexp_spec ; `ldshiftexp_spec ; `next_up_spec ; `next_down_spec ]. (* Spec to check that evaluation mechanisms agree for each operator. *) #[local] Notation reflspec1 f := (fun x => @eq_refl _ (f x)). #[local] Notation reflspec2 f := (fun x y => @eq_refl _ (f x y)). Definition op_spec_list : list SPEC := [ ` (reflspec1 PrimFloat.classify) ; ` (reflspec1 PrimFloat.abs) ; ` (reflspec1 PrimFloat.sqrt) ; ` (reflspec1 PrimFloat.opp) ; ` (reflspec2 PrimFloat.eqb) ; ` (reflspec2 PrimFloat.ltb) ; ` (reflspec2 PrimFloat.leb) ; ` (reflspec2 PrimFloat.compare) ; ` (reflspec2 PrimFloat.Leibniz.eqb) ; ` (reflspec2 PrimFloat.mul) ; ` (reflspec2 PrimFloat.add) ; ` (reflspec2 PrimFloat.sub) ; ` (reflspec2 PrimFloat.div) ; ` (reflspec1 PrimFloat.of_uint63) ; ` (reflspec1 PrimFloat.normfr_mantissa) ; ` (reflspec1 PrimFloat.frshiftexp) ; ` (reflspec2 PrimFloat.ldshiftexp) ; ` (reflspec1 PrimFloat.next_up) ; ` (reflspec1 PrimFloat.next_down) ]. (** *************************************************************************) (** * Utility definitions for managing lists specifications *) (** We unfold standard library constants early to guarantee that we won't run afoul of constants that show up in the specs themselves *) Definition map_fst : list ANNOTATED_BARE_SPEC -> list BARE_SPEC := Eval cbv in ListDef.map (@fst _ _). Definition combine_annotations (orig : list ANNOTATED_BARE_SPEC) (result : list BARE_SPEC) : list ANNOTATED_BARE_SPEC := Eval cbv in ListDef.map (fun '((_, anno), v) => (v, anno)) (combine orig result). (** The native compiler is much slower if we feed it the precomputed instantiations of specs, whereas we want to make sure that [simpl] and [cbn] have as few places to take the wrong path as possible. Reductions like [cbv] and [lazy] and the [vm] are mostly indifferent. So we maintain both [_red] versions for [simpl] and [cbn] and non-[_red] versions for [native_compute]. *) (** We make [_red] definitions [Let] statements, to work around COQBUG(https://github.com/rocq-prover/rocq/issues/4790) and avoid stack overflows in COQNATIVE *) (** * 1. Test the specs *) Section TestSpecs. Time Let specs_red : list ANNOTATED_BARE_SPEC := Eval cbv [spec_list instantiate_all_ways] in instantiate_all_ways spec_list. (* 0.911 secs *) Let bare_specs_red : list BARE_SPEC := Eval cbv [map_fst specs_red] in map_fst specs_red. Time Let bare_specs_vm : list BARE_SPEC := Eval vm_compute in bare_specs_red. (* 1.934 secs *) (** ** Fuse in the annotations so that we can report errors nicely *) Time Let results_vm : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations bare_specs_vm specs_red] in combine_annotations specs_red bare_specs_vm. (* 1.374 secs *) (** ** Report results *) Time Ltac2 Eval report_results "vm" 'results_vm. (* 0.634 secs *) End TestSpecs. (** Check that the machinery indeed fail, providing useful error messages, on some purposely-wrong spec. *) Section NegativeTest. Axiom wrong_spec : forall x, (- x)%float = PrimFloat.abs x. Definition wrong_spec_list : list SPEC := cons ( `wrong_spec ) nil. Let wrong_specs : list ANNOTATED_BARE_SPEC := Eval cbv [wrong_spec_list instantiate_all_ways] in instantiate_all_ways wrong_spec_list. Let wrong_bare_specs : list BARE_SPEC := Eval cbv [map_fst wrong_specs] in map_fst wrong_specs. Let wrong_bare_specs_vm : list BARE_SPEC := Eval vm_compute in wrong_bare_specs. (** ** Fuse in the annotations so that we can report errors nicely *) Let wrong_results_vm : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations wrong_bare_specs_vm wrong_specs] in combine_annotations wrong_specs wrong_bare_specs_vm. (** ** Report results *) Fail Ltac2 Eval report_results "vm" 'wrong_results_vm. (* Test Error: vm failed! Got: neg_infinity Expected: infinity In (wrong_spec infinity) (- infinity = abs infinity) ... *) End NegativeTest. (** * 2. Test the evaluation mechanisms *) Definition op_specs : list ANNOTATED_BARE_SPEC := instantiate_all_ways_nored op_spec_list. Time Let op_specs_red : list ANNOTATED_BARE_SPEC := Eval cbv [instantiate_all_ways op_spec_list] in instantiate_all_ways op_spec_list. (* 0.883 secs *) Definition op_bare_specs : list BARE_SPEC := map fst op_specs. Let op_bare_specs_red : list BARE_SPEC := Eval cbv [map_fst op_specs_red] in map_fst op_specs_red. (** Machinery for evaluating independently the LHS of specs *) (** To check that all evaluation mechanism agree, we will then 0. evaluate [op_specs] with [vm_compute] 1. [extract_lhs] of [op_specs] 2. evaluate LHS with each mechanism 3. [merge_lhs] with results of 2. and 0. *) Inductive hlist := hnil | hcons {T} (x : T) (_ : hlist). Fixpoint extract_lhs (ls : list BARE_SPEC) : hlist := match ls with | nil => hnil | x :: xs => let rest := extract_lhs xs in match x with EQ v _ | IFF v _ => hcons v rest end end. Fixpoint merge_lhs (ls : list BARE_SPEC) (result : hlist) : list BARE_SPEC := match ls, result with | nil, _ | _, hnil => nil | x :: xs, hcons v vs => match x with | EQ _ x' => EQ v x' | IFF _ x' => IFF v x' end :: merge_lhs xs vs end. (** 0. evaluate [op_specs] with [vm_compute] *) Let op_bare_specs_vm : list BARE_SPEC := Eval vm_compute in op_bare_specs_red. (** 1. [extract_lhs] of [op_specs] *) Definition LHS_op : hlist := extract_lhs op_bare_specs. Let LHS_op_red : hlist := Eval cbv [op_bare_specs_red extract_lhs] in extract_lhs op_bare_specs_red. (** 2. evaluate LHS with each mechanism *) (** *************************************************************************) (** * Computing reduced expressions *) (** EDIT HERE TO ADD MORE REDUCTION STRATEGIES *) (** ** [vm_compute] is ommited as it is the reference *) (** ** [native_compute] *) (** Native is slow at compiling big code, so we start from smaller code *) Let LHS_op_native := Eval native_compute in extract_lhs op_bare_specs. (** ** [hnf] *) (** recursively applies hnf to all elements of the list *) Ltac2 rec eval_hnf_hlist (c : constr) : constr := lazy_match! c with | hcons ?h ?t => let h := Std.eval_hnf h in let t := eval_hnf_hlist t in '(hcons $h $t) | hnil => 'hnil end. Time Let LHS_op_hnf := ltac2:(let l := Std.eval_hnf 'LHS_op_red in let x := eval_hnf_hlist l in exact $x). (* 16.309 secs *) (** ** [cbn] *) Time Let LHS_op_cbn := Eval cbn in ltac2:(let l := Std.eval_hnf 'LHS_op_red in exact $l). (* 0.25 secs *) (** ** [simpl] *) Time Let LHS_op_simpl := Eval simpl in ltac2:(let l := Std.eval_hnf 'LHS_op_red in exact $l). (* 0.296 secs *) (** ** [cbv] *) Time Let LHS_op_cbv := Eval cbv in ltac2:(let l := Std.eval_hnf 'LHS_op_red in exact $l). (* 0.292 secs *) (** ** [lazy] *) Time Let LHS_op_lazy := Eval lazy in ltac2:(let l := Std.eval_hnf 'LHS_op_red in exact $l). (* 0.259 secs *) (** 3. [merge_lhs] with results of 2. and 0. *) (** ** fuse the results of vm RHS (vm because it's fast) back into cbn/hnf/simpl LHS for comparison *) Let op_bare_specs_native : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_native] in merge_lhs op_bare_specs_vm LHS_op_native. Let op_bare_specs_hnf : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_hnf] in merge_lhs op_bare_specs_vm LHS_op_hnf. Let op_bare_specs_cbn : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_cbn] in merge_lhs op_bare_specs_vm LHS_op_cbn. Let op_bare_specs_simpl : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_simpl] in merge_lhs op_bare_specs_vm LHS_op_simpl. Let op_bare_specs_cbv : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_cbv] in merge_lhs op_bare_specs_vm LHS_op_cbv. Let op_bare_specs_lazy : list BARE_SPEC := Eval cbv [merge_lhs op_bare_specs_vm LHS_op_lazy] in merge_lhs op_bare_specs_vm LHS_op_lazy. (** ** Fuse in the annotations so that we can report errors nicely *) Time Let op_results_native : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_native] in combine_annotations op_specs_red op_bare_specs_native. (* 0.826 secs *) Time Let op_results_hnf : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_hnf] in combine_annotations op_specs_red op_bare_specs_hnf. (* 0.83 secs *) Time Let op_results_cbn : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_cbn] in combine_annotations op_specs_red op_bare_specs_cbn. (* 0.83 secs *) Time Let op_results_simpl : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_simpl] in combine_annotations op_specs_red op_bare_specs_simpl. (* 0.865 secs *) Time Let op_results_cbv : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_cbv] in combine_annotations op_specs_red op_bare_specs_cbv. (* 0.845 secs *) Time Let op_results_lazy : list ANNOTATED_BARE_SPEC := Eval cbv [combine_annotations op_specs_red op_bare_specs_lazy] in combine_annotations op_specs_red op_bare_specs_lazy. (* 0.812 secs *) (** ** Report results *) Set Printing Depth 100000000. Ltac2 Eval report_results "native" 'op_results_native. Ltac2 Eval report_results "hnf" 'op_results_hnf. Ltac2 Eval report_results "cbn" 'op_results_cbn. Ltac2 Eval report_results "simpl" 'op_results_simpl. Ltac2 Eval report_results "cbv" 'op_results_cbv. Ltac2 Eval report_results "lazy" 'op_results_lazy. End __WORK_AROUND_COQBUG_4790. rocq-9.2.0/test-suite/primitive/float/sqrt.v000066400000000000000000000007021516144147600211010ustar00rootroot00000000000000Require Import PrimInt63 PrimFloat. Open Scope float_scope. Definition three := Eval compute in of_uint63 3%uint63. Definition nine := Eval compute in of_uint63 9%uint63. Check (eq_refl : sqrt nine = three). Check (eq_refl : sqrt zero = zero). Check (eq_refl : sqrt neg_zero = neg_zero). Check (eq_refl : sqrt one = one). Check (eq_refl : sqrt (-one) = nan). Check (eq_refl : sqrt infinity = infinity). Check (eq_refl : sqrt neg_infinity = nan). rocq-9.2.0/test-suite/primitive/float/sub.v000066400000000000000000000011561516144147600207050ustar00rootroot00000000000000Require Import PrimFloat. Open Scope float_scope. Definition huge := 0x1p+1023%float. (* Z.ldexp one 1023%Z. *) Definition tiny := 0x0.8p-1022%float. (* Z.ldexp one (-1023)%Z. *) Check (eq_refl : huge - tiny = huge). Check (eq_refl : huge - huge = zero). Check (eq_refl : one - nan = nan). Check (eq_refl : infinity - infinity = nan). Check (eq_refl : infinity - neg_infinity = infinity). Check (eq_refl : zero - zero = zero). Check (eq_refl : neg_zero - zero = neg_zero). Check (eq_refl : neg_zero - neg_zero = zero). Check (eq_refl : zero - neg_zero = zero). Check (eq_refl : huge - neg_infinity = infinity). rocq-9.2.0/test-suite/primitive/float/syntax.v000066400000000000000000000005711516144147600214420ustar00rootroot00000000000000Require Import PrimFloat. Open Scope float_scope. Definition two := Eval compute in one + one. Definition half := Eval compute in one / two. Check (eq_refl : 1.5 = one + half). Check (eq_refl : 15e-1 = one + half). Check (eq_refl : 150e-2 = one + half). Check (eq_refl : 0.15e+1 = one + half). Check (eq_refl : 0.15e1 = one + half). Check (eq_refl : 0.0015e3 = one + half). rocq-9.2.0/test-suite/primitive/float/zero.v000066400000000000000000000002571516144147600210740ustar00rootroot00000000000000Require Import PrimFloat. Open Scope float_scope. Fail Check (eq_refl : zero = neg_zero). Fail Check (eq_refl <: zero = neg_zero). Fail Check (eq_refl <<: zero = neg_zero). rocq-9.2.0/test-suite/primitive/sint63/000077500000000000000000000000001516144147600177435ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/sint63/add.v000066400000000000000000000015311516144147600206620ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : add 2 3 = 5). Check (eq_refl 5 <: add 2 3 = 5). Check (eq_refl 5 <<: add 2 3 = 5). Definition compute1 := Eval compute in add 2 3. Check (eq_refl compute1 : 5 = 5). Check (eq_refl : add 4611686018427387903 1 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <: add 4611686018427387903 1 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <<: add 4611686018427387903 1 = -4611686018427387904). Definition compute2 := Eval compute in add 4611686018427387903 1. Check (eq_refl compute2 : -4611686018427387904 = -4611686018427387904). Check (eq_refl : sub 2 3 = -1). Check (eq_refl (-1) <: sub 2 3 = -1). Check (eq_refl (-1) <<: sub 2 3 = -1). Definition compute3 := Eval compute in sub 2 3. Check (eq_refl compute3 : -1 = -1). rocq-9.2.0/test-suite/primitive/sint63/asr.v000066400000000000000000000031441516144147600207210ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : asr (-2305843009213693952)%sint63 61 = -1). Check (eq_refl (-1) <: asr (-2305843009213693952)%sint63 61 = -1). Check (eq_refl (-1) <<: asr (-2305843009213693952)%sint63 61 = -1). Definition compute1 := Eval compute in asr (-2305843009213693952)%sint63 61. Check (eq_refl compute1 : -1 = -1). Check (eq_refl : asr 2305843009213693952 62 = 0). Check (eq_refl 0 <: asr 2305843009213693952 62 = 0). Check (eq_refl 0 <<: asr 2305843009213693952 62 = 0). Definition compute2 := Eval compute in asr 2305843009213693952 62. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : asr 4611686018427387903 63 = 0). Check (eq_refl 0 <: asr 4611686018427387903 63 = 0). Check (eq_refl 0 <<: asr 4611686018427387903 63 = 0). Definition compute3 := Eval compute in asr 4611686018427387903 63. Check (eq_refl compute3 : 0 = 0). Check (eq_refl : asr (-1)%sint63 1 = -1). Check (eq_refl (-1) <: asr (-1)%sint63 1 = -1). Check (eq_refl (-1) <<: asr (-1)%sint63 1 = -1). Definition compute4 := Eval compute in asr (-1)%sint63 1. Check (eq_refl compute4 : -1 = -1). Check (eq_refl : asr (-1)%sint63 (-1)%sint63 = 0). Check (eq_refl 0 <: asr (-1)%sint63 (-1)%sint63 = 0). Check (eq_refl 0 <<: asr (-1)%sint63 (-1)%sint63 = 0). Definition compute5 := Eval compute in asr (-1)%sint63 (-1)%sint63. Check (eq_refl compute5 : 0 = 0). Check (eq_refl : asr 73 (-2)%sint63 = 0). Check (eq_refl 0 <: asr 73 (-2)%sint63 = 0). Check (eq_refl 0 <<: asr 73 (-2)%sint63 = 0). Definition compute6 := Eval compute in asr 73 (-2)%sint63. Check (eq_refl compute6 : 0 = 0). rocq-9.2.0/test-suite/primitive/sint63/compare.v000066400000000000000000000026301516144147600215610ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : compares 1 1 = Eq). Check (eq_refl Eq <: compares 1 1 = Eq). Check (eq_refl Eq <<: compares 1 1 = Eq). Definition compute1 := Eval compute in compares 1 1. Check (eq_refl compute1 : Eq = Eq). Check (eq_refl : compares 1 2 = Lt). Check (eq_refl Lt <: compares 1 2 = Lt). Check (eq_refl Lt <<: compares 1 2 = Lt). Definition compute2 := Eval compute in compares 1 2. Check (eq_refl compute2 : Lt = Lt). Check (eq_refl : compares 4611686018427387903 0 = Gt). Check (eq_refl Gt <: compares 4611686018427387903 0 = Gt). Check (eq_refl Gt <<: compares 4611686018427387903 0 = Gt). Definition compute3 := Eval compute in compares 4611686018427387903 0. Check (eq_refl compute3 : Gt = Gt). Check (eq_refl : compares (-1)%sint63 1 = Lt). Check (eq_refl Lt <: compares (-1)%sint63 1 = Lt). Check (eq_refl Lt <<: compares (-1)%sint63 1 = Lt). Definition compute4 := Eval compute in compares (-1)%sint63 1. Check (eq_refl compute4 : Lt = Lt). Check (eq_refl : compares 4611686018427387903 (-4611686018427387904)%sint63 = Gt). Check (eq_refl Gt <: compares 4611686018427387903 (-4611686018427387904)%sint63 = Gt). Check (eq_refl Gt <<: compares 4611686018427387903 (-4611686018427387904)%sint63 = Gt). Definition compute5 := Eval compute in compares 4611686018427387903 (-4611686018427387904)%sint63. Check (eq_refl compute5 : Gt = Gt). rocq-9.2.0/test-suite/primitive/sint63/div.v000066400000000000000000000045701516144147600207220ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : divs 6 3 = 2). Check (eq_refl 2 <: divs 6 3 = 2). Check (eq_refl 2 <<: divs 6 3 = 2). Definition compute1 := Eval compute in divs 6 3. Check (eq_refl compute1 : 2 = 2). Check (eq_refl : divs (-6)%sint63 3 = -2). Check (eq_refl (-2) <: divs (-6)%sint63 3 = -2). Check (eq_refl (-2) <<: divs (-6)%sint63 3 = -2). Definition compute2 := Eval compute in divs (-6)%sint63 3. Check (eq_refl compute2 : -2 = -2). Check (eq_refl : divs 6 (-3)%sint63 = -2). Check (eq_refl (-2) <: divs 6 (-3)%sint63 = -2). Check (eq_refl (-2) <<: divs 6 (-3)%sint63 = -2). Definition compute3 := Eval compute in divs 6 (-3)%sint63. Check (eq_refl compute3 : -2 = -2). Check (eq_refl : divs (-6)%sint63 (-3)%sint63 = 2). Check (eq_refl 2 <: divs (-6)%sint63 (-3)%sint63 = 2). Check (eq_refl 2 <<: divs (-6)%sint63 (-3)%sint63 = 2). Definition compute4 := Eval compute in divs (-6)%sint63 (-3)%sint63. Check (eq_refl compute4 : 2 = 2). Check (eq_refl : divs 3 2 = 1). Check (eq_refl 1 <: divs 3 2 = 1). Check (eq_refl 1 <<: divs 3 2 = 1). Definition compute5 := Eval compute in divs 3 2. Check (eq_refl compute5 : 1 = 1). Check (eq_refl : divs (-3)%sint63 2 = -1). Check (eq_refl (-1) <: divs (-3)%sint63 2 = -1). Check (eq_refl (-1) <<: divs (-3)%sint63 2 = -1). Definition compute6 := Eval compute in divs (-3)%sint63 2. Check (eq_refl compute6 : -1 = -1). Check (eq_refl : divs 3 (-2)%sint63 = -1). Check (eq_refl (-1) <: divs 3 (-2)%sint63 = -1). Check (eq_refl (-1) <<: divs 3 (-2)%sint63 = -1). Definition compute7 := Eval compute in divs 3 (-2)%sint63. Check (eq_refl compute7 : -1 = -1). Check (eq_refl : divs (-3)%sint63 (-2)%sint63 = 1). Check (eq_refl 1 <: divs (-3)%sint63 (-2)%sint63 = 1). Check (eq_refl 1 <<: divs (-3)%sint63 (-2)%sint63 = 1). Definition compute8 := Eval compute in divs (-3)%sint63 (-2)%sint63. Check (eq_refl compute8 : 1 = 1). Check (eq_refl : divs (-4611686018427387904)%sint63 (-1)%sint63 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <: divs (-4611686018427387904)%sint63 (-1)%sint63 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <<: divs (-4611686018427387904)%sint63 (-1)%sint63 = -4611686018427387904). Definition compute9 := Eval compute in divs (-4611686018427387904)%sint63 (-1)%sint63. Check (eq_refl compute9 : -4611686018427387904 = -4611686018427387904). rocq-9.2.0/test-suite/primitive/sint63/eqb.v000066400000000000000000000010731516144147600207020ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : eqb 1 1 = true). Check (eq_refl true <: eqb 1 1 = true). Check (eq_refl true <<: eqb 1 1 = true). Definition compute1 := Eval compute in eqb 1 1. Check (eq_refl compute1 : true = true). Check (eq_refl : eqb 4611686018427387903 0 = false). Check (eq_refl false <: eqb 4611686018427387903 0 = false). Check (eq_refl false <<: eqb 4611686018427387903 0 = false). Definition compute2 := Eval compute in eqb 4611686018427387903 0. Check (eq_refl compute2 : false = false). rocq-9.2.0/test-suite/primitive/sint63/isint.v000066400000000000000000000036441516144147600212670ustar00rootroot00000000000000(* 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 TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Section test. Variable m n : int. Check (eq_refl : (fun x => add x 3) m = add m 3). Check (eq_refl (add m 3) <: (fun x => add x 3) m = add m 3). Check (eq_refl (add m 3) <<: (fun x => add x 3) m = add m 3). Definition compute1 := Eval compute in (fun x => add x 3) m. Check (eq_refl compute1 : add m 3 = add m 3). Check (eq_refl : (fun x => add 3 x) m = add 3 m). Check (eq_refl (add 3 m) <: (fun x => add 3 x) m = add 3 m). Check (eq_refl (add 3 m) <<: (fun x => add 3 x) m = add 3 m). Definition compute2 := Eval compute in (fun x => add 3 x) m. Check (eq_refl compute2 : add 3 m = add 3 m). Check (eq_refl : (fun x y => add x y) m n = add m n). Check (eq_refl (add m n) <: (fun x y => add x y) m n = add m n). Check (eq_refl (add m n) <<: (fun x y => add x y) m n = add m n). Definition compute3 := Eval compute in (fun x y => add x y) m n. Check (eq_refl compute3 : add m n = add m n). Check (eq_refl : (fun x y => add x y) 2 3 = 5). Check (eq_refl 5 <: (fun x y => add x y) 2 3 = 5). Check (eq_refl 5 <<: (fun x y => add x y) 2 3 = 5). Definition compute4 := Eval compute in (fun x y => add x y) 2 3. Check (eq_refl compute4 : 5 = 5). Check (eq_refl : (fun x => add x x) m = add m m). Check (eq_refl (add m m) <: (fun x => add x x) m = add m m). Check (eq_refl (add m m) <<: (fun x => add x x) m = add m m). Definition compute5 := Eval compute in (fun x => add x x) m. Check (eq_refl compute5 : add m m = add m m). Check (eq_refl : (fun x => add x x) 2 = 4). Check (eq_refl 4 <: (fun x => add x x) 2 = 4). Check (eq_refl 4 <<: (fun x => add x x) 2 = 4). Definition compute6 := Eval compute in (fun x => add x x) 2. Check (eq_refl compute6 : 4 = 4). End test. rocq-9.2.0/test-suite/primitive/sint63/leb.v000066400000000000000000000020221516144147600206700ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : lesb 1 1 = true). Check (eq_refl true <: lesb 1 1 = true). Check (eq_refl true <<: lesb 1 1 = true). Definition compute1 := Eval compute in lesb 1 1. Check (eq_refl compute1 : true = true). Check (eq_refl : lesb 1 2 = true). Check (eq_refl true <: lesb 1 2 = true). Check (eq_refl true <<: lesb 1 2 = true). Definition compute2 := Eval compute in lesb 1 2. Check (eq_refl compute2 : true = true). Check (eq_refl : lesb 4611686018427387903 0 = false). Check (eq_refl false <: lesb 4611686018427387903 0 = false). Check (eq_refl false <<: lesb 4611686018427387903 0 = false). Definition compute3 := Eval compute in lesb 4611686018427387903 0. Check (eq_refl compute3 : false = false). Check (eq_refl : lesb 1 (-1)%sint63 = false). Check (eq_refl false <: lesb 1 (-1)%sint63 = false). Check (eq_refl false <<: lesb 1 (-1)%sint63 = false). Definition compute4 := Eval compute in lesb 1 (-1)%sint63. Check (eq_refl compute4 : false = false). rocq-9.2.0/test-suite/primitive/sint63/lsl.v000066400000000000000000000034241516144147600207270ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : lsl 3 61 = -2305843009213693952). Check (eq_refl (-2305843009213693952) <: lsl 3 61 = -2305843009213693952). Check (eq_refl (-2305843009213693952) <<: lsl 3 61 = -2305843009213693952). Definition compute1 := Eval compute in lsl 3 61. Check (eq_refl compute1 : -2305843009213693952 = -2305843009213693952). Check (eq_refl : lsl 2 62 = 0). Check (eq_refl 0 <: lsl 2 62 = 0). Check (eq_refl 0 <<: lsl 2 62 = 0). Definition compute2 := Eval compute in lsl 2 62. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : lsl 4611686018427387903 63 = 0). Check (eq_refl 0 <: lsl 4611686018427387903 63 = 0). Check (eq_refl 0 <<: lsl 4611686018427387903 63 = 0). Definition compute3 := Eval compute in lsl 4611686018427387903 63. Check (eq_refl compute3 : 0 = 0). Check (eq_refl : lsl 4611686018427387903 62 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <: lsl 4611686018427387903 62 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <<: lsl 4611686018427387903 62 = -4611686018427387904). Definition compute4 := Eval compute in lsl 4611686018427387903 62. Check (eq_refl compute4 : -4611686018427387904 = -4611686018427387904). Check (eq_refl : lsl 1 62 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <: lsl 1 62 = -4611686018427387904). Check (eq_refl (-4611686018427387904) <<: lsl 1 62 = -4611686018427387904). Definition compute5 := Eval compute in lsl 1 62. Check (eq_refl compute5 : -4611686018427387904 = -4611686018427387904). Check (eq_refl : lsl (-1)%sint63 1 = -2). Check (eq_refl (-2) <: lsl (-1)%sint63 1 = -2). Check (eq_refl (-2) <<: lsl (-1)%sint63 1 = -2). Definition compute6 := Eval compute in lsl (-1)%sint63 1. Check (eq_refl compute6 : -2 = -2). rocq-9.2.0/test-suite/primitive/sint63/ltb.v000066400000000000000000000020311516144147600207070ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : ltsb 1 1 = false). Check (eq_refl false <: ltsb 1 1 = false). Check (eq_refl false <<: ltsb 1 1 = false). Definition compute1 := Eval compute in ltsb 1 1. Check (eq_refl compute1 : false = false). Check (eq_refl : ltsb 1 2 = true). Check (eq_refl true <: ltsb 1 2 = true). Check (eq_refl true <<: ltsb 1 2 = true). Definition compute2 := Eval compute in ltsb 1 2. Check (eq_refl compute2 : true = true). Check (eq_refl : ltsb 4611686018427387903 0 = false). Check (eq_refl false <: ltsb 4611686018427387903 0 = false). Check (eq_refl false <<: ltsb 4611686018427387903 0 = false). Definition compute3 := Eval compute in ltsb 4611686018427387903 0. Check (eq_refl compute3 : false = false). Check (eq_refl : ltsb 1 (-1)%sint63 = false). Check (eq_refl false <: ltsb 1 (-1)%sint63 = false). Check (eq_refl false <<: ltsb 1 (-1)%sint63 = false). Definition compute4 := Eval compute in ltsb 1 (-1)%sint63. Check (eq_refl compute4 : false = false). rocq-9.2.0/test-suite/primitive/sint63/mod.v000066400000000000000000000036021516144147600207120ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : mods 6 3 = 0). Check (eq_refl 0 <: mods 6 3 = 0). Check (eq_refl 0 <<: mods 6 3 = 0). Definition compute1 := Eval compute in mods 6 3. Check (eq_refl compute1 : 0 = 0). Check (eq_refl : mods (-6)%sint63 3 = 0). Check (eq_refl 0 <: mods (-6)%sint63 3 = 0). Check (eq_refl 0 <<: mods (-6)%sint63 3 = 0). Definition compute2 := Eval compute in mods (-6)%sint63 3. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : mods 6 (-3)%sint63 = 0). Check (eq_refl 0 <: mods 6 (-3)%sint63 = 0). Check (eq_refl 0 <<: mods 6 (-3)%sint63 = 0). Definition compute3 := Eval compute in mods 6 (-3)%sint63. Check (eq_refl compute3 : 0 = 0). Check (eq_refl : mods (-6)%sint63 (-3)%sint63 = 0). Check (eq_refl 0 <: mods (-6)%sint63 (-3)%sint63 = 0). Check (eq_refl 0 <<: mods (-6)%sint63 (-3)%sint63 = 0). Definition compute4 := Eval compute in mods (-6)%sint63 (-3)%sint63. Check (eq_refl compute4 : 0 = 0). Check (eq_refl : mods 5 3 = 2). Check (eq_refl 2 <: mods 5 3 = 2). Check (eq_refl 2 <<: mods 5 3 = 2). Definition compute5 := Eval compute in mods 5 3. Check (eq_refl compute5 : 2 = 2). Check (eq_refl : mods (-5)%sint63 3 = -2). Check (eq_refl (-2) <: mods (-5)%sint63 3 = -2). Check (eq_refl (-2) <<: mods (-5)%sint63 3 = -2). Definition compute6 := Eval compute in mods (-5)%sint63 3. Check (eq_refl compute6 : -2 = -2). Check (eq_refl : mods 5 (-3)%sint63 = 2). Check (eq_refl 2 <: mods 5 (-3)%sint63 = 2). Check (eq_refl 2 <<: mods 5 (-3)%sint63 = 2). Definition compute7 := Eval compute in mods 5 (-3)%sint63. Check (eq_refl compute7 : 2 = 2). Check (eq_refl : mods (-5)%sint63 (-3)%sint63 = -2). Check (eq_refl (-2) <: mods (-5)%sint63 (-3)%sint63 = -2). Check (eq_refl (-2) <<: mods (-5)%sint63 (-3)%sint63 = -2). Definition compute8 := Eval compute in mods (-5)%sint63 (-3)%sint63. Check (eq_refl compute8 : -2 = -2). rocq-9.2.0/test-suite/primitive/sint63/mul.v000066400000000000000000000023601516144147600207300ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : mul 2 3 = 6). Check (eq_refl 6 <: mul 2 3 = 6). Check (eq_refl 6 <<: mul 2 3 = 6). Definition compute1 := Eval compute in mul 2 3. Check (eq_refl compute1 : 6 = 6). Check (eq_refl : mul (-2)%sint63 3 = -6). Check (eq_refl (-6) <: mul (-2)%sint63 3 = -6). Check (eq_refl (-6) <<: mul (-2)%sint63 3 = -6). Definition compute2 := Eval compute in mul (-2)%sint63 3. Check (eq_refl compute2 : -6 = -6). Check (eq_refl : mul 2 (-3)%sint63 = -6). Check (eq_refl (-6) <: mul 2 (-3)%sint63 = -6). Check (eq_refl (-6) <<: mul 2 (-3)%sint63 = -6). Definition compute3 := Eval compute in mul 2 (-3)%sint63. Check (eq_refl compute3 : -6 = -6). Check (eq_refl : mul (-2)%sint63 (-3)%sint63 = 6). Check (eq_refl 6 <: mul (-2)%sint63 (-3)%sint63 = 6). Check (eq_refl 6 <<: mul (-2)%sint63 (-3)%sint63 = 6). Definition compute4 := Eval compute in mul (-2)%sint63 (-3)%sint63. Check (eq_refl compute4 : 6 = 6). Check (eq_refl : mul 4611686018427387903 2 = -2). Check (eq_refl (-2) <: mul 4611686018427387903 2 = -2). Check (eq_refl (-2) <<: mul 4611686018427387903 2 = -2). Definition compute5 := Eval compute in mul 4611686018427387903 2. Check (eq_refl compute5 : -2 = -2). rocq-9.2.0/test-suite/primitive/sint63/signed.v000066400000000000000000000011751516144147600214070ustar00rootroot00000000000000(* This file checks that operations over sint63 are signed. *) Require Import TestSuite.sint63. Open Scope sint63_scope. (* (0-1) must be negative 1 and not the maximum integer value *) Check (eq_refl : divs 1 (sub 0 1) = -1). Check (eq_refl (-1) <: divs 1 (sub 0 1) = -1). Check (eq_refl (-1) <<: divs 1 (sub 0 1) = -1). Definition compute1 := Eval compute in divs 1 (sub 0 1). Check (eq_refl compute1 : -1 = -1). Check (eq_refl : mods 3 (sub 0 1) = 0). Check (eq_refl 0 <: mods 3 (sub 0 1) = 0). Check (eq_refl 0 <<: mods 3 (sub 0 1) = 0). Definition compute2 := Eval compute in mods 3 (sub 0 1). Check (eq_refl compute2 : 0 = 0). rocq-9.2.0/test-suite/primitive/sint63/sub.v000066400000000000000000000015661516144147600207330ustar00rootroot00000000000000Require Import TestSuite.sint63. Set Implicit Arguments. Open Scope sint63_scope. Check (eq_refl : sub 3 2 = 1). Check (eq_refl 1 <: sub 3 2 = 1). Check (eq_refl 1 <<: sub 3 2 = 1). Definition compute1 := Eval compute in sub 3 2. Check (eq_refl compute1 : 1 = 1). Check (eq_refl : sub 0 1 = -1). Check (eq_refl (-1) <: sub 0 1 = -1). Check (eq_refl (-1) <<: sub 0 1 = -1). Definition compute2 := Eval compute in sub 0 1. Check (eq_refl compute2 : -1 = -1). Check (eq_refl : sub (-4611686018427387904)%sint63 1 = 4611686018427387903). Check (eq_refl 4611686018427387903 <: sub (-4611686018427387904)%sint63 1 = 4611686018427387903). Check (eq_refl 4611686018427387903 <<: sub (-4611686018427387904)%sint63 1 = 4611686018427387903). Definition compute3 := Eval compute in sub (-4611686018427387904)%sint63 1. Check (eq_refl compute3 : 4611686018427387903 = 4611686018427387903). rocq-9.2.0/test-suite/primitive/string/000077500000000000000000000000001516144147600201235ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/string/test.v000066400000000000000000000143111516144147600212710ustar00rootroot00000000000000Require Import PrimInt63 PrimString. Open Scope uint63_scope. Open Scope pstring_scope. Check (eq_refl : length (make 0 "a") = 0 ). Check (eq_refl : length (make 42 "a") = 42 ). Check (eq_refl : length (make max_length "a") = max_length). Check (eq_refl : length (make (PrimInt63.add max_length 1) "a") = max_length). Check (eq_refl : make 0 "a" = ""). Check (eq_refl : make 5 "a" = "aaaaa"). Check (eq_refl : get "abcdefg" 0 = "a"%char63). Check (eq_refl : get "abcdefg" 5 = "f"%char63). Check (eq_refl : get "abcdefg" 6 = "g"%char63). (* Invalid index. *) Check (eq_refl : get "abcdefg" 7 = 0%uint63). Check (eq_refl : sub "abcdefg" 0 0 = ""). Check (eq_refl : sub "abcdefg" 0 7 = "abcdefg"). Check (eq_refl : sub "abcdefg" 0 6 = "abcdef"). Check (eq_refl : sub "abcdefg" 1 6 = "bcdefg"). Check (eq_refl : sub "abcdefg" 6 1 = "g"). Check (eq_refl : sub "abcdefg" 6 0 = ""). Check (eq_refl : sub "abcdefg" 7 0 = ""). (* When there are not enough characters, take as many as are available. *) Check (eq_refl : sub "abcdefg" 4 10 = "efg"). (* Invalid ranges. *) Check (eq_refl : sub "abcdefg" 7 2 = ""). Check (eq_refl : sub "abcdefg" 73 42 = ""). Check (eq_refl : cat "" "" = "" ). Check (eq_refl : cat "a" "b" = "ab"). Check (eq_refl : cat "aa" "" = "aa"). Check (eq_refl : cat "" "bb" = "bb"). Check (eq_refl : compare "" "" = Eq). Check (eq_refl : compare "a" "" = Gt). Check (eq_refl : compare "" "a" = Lt). Check (eq_refl : compare "a" "b" = Lt). Check (eq_refl : compare "b" "a" = Gt). Check (eq_refl : compare "a" "ab" = Lt). Check (eq_refl : compare "ab" "a" = Gt). (* Dropping a suffix on length overflow. *) Check (eq_refl : cat (make max_length "a") "b" = make max_length "a"). Ltac syntactic_refl := lazymatch goal with | |- ?x = ?x => apply (@eq_refl _ x) end. (* [lazy] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. lazy. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. lazy. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. lazy. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. lazy. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. lazy. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. lazy. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. lazy. syntactic_refl. Qed. (* [cbn] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. cbn. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. cbn. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. cbn. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. cbn. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. cbn. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. cbn. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. cbn. syntactic_refl. Qed. (* [cbv] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. cbv. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. cbv. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. cbv. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. cbv. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. cbv. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. cbv. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. cbv. syntactic_refl. Qed. (* [simpl] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. simpl. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. simpl. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. simpl. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. simpl. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. simpl. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. simpl. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. simpl. syntactic_refl. Qed. (* [hnf] *) (* Reduce with [hnf] on either side of an equality. *) Ltac hnf_eq := lazymatch goal with | |- ?lhs = ?rhs => let lhs := eval hnf in lhs in let rhs := eval hnf in rhs in assert (lhs = rhs) as H; [|exact H] end. Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. hnf_eq. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. hnf_eq. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. hnf_eq. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. hnf_eq. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. hnf_eq. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. hnf_eq. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. hnf_eq. syntactic_refl. Qed. (* [vm_compute] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. vm_compute. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. vm_compute. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. vm_compute. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. vm_compute. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. vm_compute. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. vm_compute. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. vm_compute. syntactic_refl. Qed. Check (eq_refl "aaaaa" <: make 5 "a" = cat (make 2 "a") (make 3 "a")). Check (eq_refl (char63_wrap "a"%char63) <: get "aaa" 0 = "a"%char63). Check (eq_refl "c" <: sub "abcd" 2 1 = "c"). Check (eq_refl "abba" <: cat "ab" "ba" = "abba"). Check (eq_refl Eq <: compare "ab" "ab" = Eq). Check (eq_refl Gt <: compare "ab" "a" = Gt). Check (eq_refl Lt <: compare "a" "ab" = Lt). (* [native_compute] *) Goal make 5 "a" = cat (make 2 "a") (make 3 "a"). Proof. native_compute. syntactic_refl. Qed. Goal get "aaa" 0 = "a"%char63. Proof. native_compute. syntactic_refl. Qed. Goal sub "abcd" 2 1 = "c". Proof. native_compute. syntactic_refl. Qed. Goal cat "ab" "ba" = "abba". Proof. native_compute. syntactic_refl. Qed. Goal compare "ab" "ab" = Eq. Proof. native_compute. syntactic_refl. Qed. Goal compare "ab" "a" = Gt. Proof. native_compute. syntactic_refl. Qed. Goal compare "a" "ab" = Lt. Proof. native_compute. syntactic_refl. Qed. Check (eq_refl "aaaaa" <<: make 5 "a" = cat (make 2 "a") (make 3 "a")). Check (eq_refl (char63_wrap "a"%char63) <<: get "aaa" 0 = "a"%char63). Check (eq_refl "c" <<: sub "abcd" 2 1 = "c"). Check (eq_refl "abba" <<: cat "ab" "ba" = "abba"). Check (eq_refl Eq <<: compare "ab" "ab" = Eq). Check (eq_refl Gt <<: compare "ab" "a" = Gt). Check (eq_refl Lt <<: compare "a" "ab" = Lt). rocq-9.2.0/test-suite/primitive/uint63/000077500000000000000000000000001516144147600177455ustar00rootroot00000000000000rocq-9.2.0/test-suite/primitive/uint63/add.v000066400000000000000000000010041516144147600206570ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : add 2 3 = 5). Check (eq_refl 5 <: add 2 3 = 5). Check (eq_refl 5 <<: add 2 3 = 5). Definition compute1 := Eval compute in add 2 3. Check (eq_refl compute1 : 5 = 5). Check (eq_refl : add 9223372036854775807 1 = 0). Check (eq_refl 0 <: add 9223372036854775807 1 = 0). Check (eq_refl 0 <<: add 9223372036854775807 1 = 0). Definition compute2 := Eval compute in add 9223372036854775807 1. Check (eq_refl compute2 : 0 = 0). rocq-9.2.0/test-suite/primitive/uint63/addc.v000066400000000000000000000010751516144147600210320ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : addc 2 3 = C0 5). Check (eq_refl (C0 5) <: addc 2 3 = C0 5). Check (eq_refl (C0 5) <<: addc 2 3 = C0 5). Definition compute1 := Eval compute in addc 2 3. Check (eq_refl compute1 : C0 5 = C0 5). Check (eq_refl : addc 9223372036854775807 2 = C1 1). Check (eq_refl (C1 1) <: addc 9223372036854775807 2 = C1 1). Check (eq_refl (C1 1) <<: addc 9223372036854775807 2 = C1 1). Definition compute2 := Eval compute in addc 9223372036854775807 2. Check (eq_refl compute2 : C1 1 = C1 1). rocq-9.2.0/test-suite/primitive/uint63/addcarryc.v000066400000000000000000000011451516144147600220710ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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). rocq-9.2.0/test-suite/primitive/uint63/addmuldiv.v000066400000000000000000000020511516144147600221030ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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). Check (eq_refl : addmuldiv 0 256 9223372036854775807 = 256). Check (eq_refl 256 <: addmuldiv 0 256 9223372036854775807 = 256). Check (eq_refl 256 <<: addmuldiv 0 256 9223372036854775807 = 256). Check (eq_refl : addmuldiv 63 9223372036854775807 256 = 256). Check (eq_refl 256 <: addmuldiv 63 9223372036854775807 256 = 256). Check (eq_refl 256 <<: addmuldiv 63 9223372036854775807 256 = 256). Check (eq_refl : addmuldiv 65536 9223372036854775807 9223372036854775807 = 0). Check (eq_refl 0 <: addmuldiv 65536 9223372036854775807 9223372036854775807 = 0). Check (eq_refl 0 <<: addmuldiv 65536 9223372036854775807 9223372036854775807 = 0). rocq-9.2.0/test-suite/primitive/uint63/compare.v000066400000000000000000000013771516144147600215720ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : compare 1 1 = Eq). Check (eq_refl Eq <: compare 1 1 = Eq). Check (eq_refl Eq <<: compare 1 1 = Eq). Definition compute1 := Eval compute in compare 1 1. Check (eq_refl compute1 : Eq = Eq). Check (eq_refl : compare 1 2 = Lt). Check (eq_refl Lt <: compare 1 2 = Lt). Check (eq_refl Lt <<: compare 1 2 = Lt). Definition compute2 := Eval compute in compare 1 2. Check (eq_refl compute2 : Lt = Lt). Check (eq_refl : compare 9223372036854775807 0 = Gt). Check (eq_refl Gt <: compare 9223372036854775807 0 = Gt). Check (eq_refl Gt <<: compare 9223372036854775807 0 = Gt). Definition compute3 := Eval compute in compare 9223372036854775807 0. Check (eq_refl compute3 : Gt = Gt). rocq-9.2.0/test-suite/primitive/uint63/div.v000066400000000000000000000006731516144147600207240ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : div 6 3 = 2). Check (eq_refl 2 <: div 6 3 = 2). Check (eq_refl 2 <<: div 6 3 = 2). Definition compute1 := Eval compute in div 6 3. Check (eq_refl compute1 : 2 = 2). Check (eq_refl : div 3 2 = 1). Check (eq_refl 1 <: div 3 2 = 1). Check (eq_refl 1 <<: div 3 2 = 1). Definition compute2 := Eval compute in div 3 2. Check (eq_refl compute2 : 1 = 1). rocq-9.2.0/test-suite/primitive/uint63/diveucl.v000066400000000000000000000010231516144147600215630ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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)). rocq-9.2.0/test-suite/primitive/uint63/diveucl_21.v000066400000000000000000000027421516144147600220760ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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 = (0, 0)). Check (eq_refl (0, 0) <: diveucl_21 3 1 2 = (0, 0)). Check (eq_refl (0, 0) <<: diveucl_21 3 1 2 = (0, 0)). Definition compute2 := Eval compute in diveucl_21 3 1 2. Check (eq_refl compute2 : (0, 0) = (0, 0)). Check (eq_refl : diveucl_21 1 1 0 = (0,0)). Check (eq_refl (0,0) <: diveucl_21 1 1 0 = (0,0)). Check (eq_refl (0,0) <<: diveucl_21 1 1 0 = (0,0)). Check (eq_refl : diveucl_21 9223372036854775807 0 1 = (0,0)). Check (eq_refl (0,0) <: diveucl_21 9223372036854775807 0 1 = (0,0)). Check (eq_refl (0,0) <<: diveucl_21 9223372036854775807 0 1 = (0,0)). Check (eq_refl : diveucl_21 9305446873517 1793572051078448654 4930380657631323783 = (17407905077428, 3068214991893055266)). Check (eq_refl (17407905077428, 3068214991893055266) <: diveucl_21 9305446873517 1793572051078448654 4930380657631323783 = (17407905077428, 3068214991893055266)). Check (eq_refl (17407905077428, 3068214991893055266) <<: diveucl_21 9305446873517 1793572051078448654 4930380657631323783 = (17407905077428, 3068214991893055266)). rocq-9.2.0/test-suite/primitive/uint63/eqb.v000066400000000000000000000010641516144147600207040ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : eqb 1 1 = true). Check (eq_refl true <: eqb 1 1 = true). Check (eq_refl true <<: eqb 1 1 = true). Definition compute1 := Eval compute in eqb 1 1. Check (eq_refl compute1 : true = true). Check (eq_refl : eqb 9223372036854775807 0 = false). Check (eq_refl false <: eqb 9223372036854775807 0 = false). Check (eq_refl false <<: eqb 9223372036854775807 0 = false). Definition compute2 := Eval compute in eqb 9223372036854775807 0. Check (eq_refl compute2 : false = false). rocq-9.2.0/test-suite/primitive/uint63/head0.v000066400000000000000000000013101516144147600211100ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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). rocq-9.2.0/test-suite/primitive/uint63/isint.v000066400000000000000000000036351516144147600212710ustar00rootroot00000000000000(* 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 PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Section test. Variable m n : int. Check (eq_refl : (fun x => add x 3) m = add m 3). Check (eq_refl (add m 3) <: (fun x => add x 3) m = add m 3). Check (eq_refl (add m 3) <<: (fun x => add x 3) m = add m 3). Definition compute1 := Eval compute in (fun x => add x 3) m. Check (eq_refl compute1 : add m 3 = add m 3). Check (eq_refl : (fun x => add 3 x) m = add 3 m). Check (eq_refl (add 3 m) <: (fun x => add 3 x) m = add 3 m). Check (eq_refl (add 3 m) <<: (fun x => add 3 x) m = add 3 m). Definition compute2 := Eval compute in (fun x => add 3 x) m. Check (eq_refl compute2 : add 3 m = add 3 m). Check (eq_refl : (fun x y => add x y) m n = add m n). Check (eq_refl (add m n) <: (fun x y => add x y) m n = add m n). Check (eq_refl (add m n) <<: (fun x y => add x y) m n = add m n). Definition compute3 := Eval compute in (fun x y => add x y) m n. Check (eq_refl compute3 : add m n = add m n). Check (eq_refl : (fun x y => add x y) 2 3 = 5). Check (eq_refl 5 <: (fun x y => add x y) 2 3 = 5). Check (eq_refl 5 <<: (fun x y => add x y) 2 3 = 5). Definition compute4 := Eval compute in (fun x y => add x y) 2 3. Check (eq_refl compute4 : 5 = 5). Check (eq_refl : (fun x => add x x) m = add m m). Check (eq_refl (add m m) <: (fun x => add x x) m = add m m). Check (eq_refl (add m m) <<: (fun x => add x x) m = add m m). Definition compute5 := Eval compute in (fun x => add x x) m. Check (eq_refl compute5 : add m m = add m m). Check (eq_refl : (fun x => add x x) 2 = 4). Check (eq_refl 4 <: (fun x => add x x) 2 = 4). Check (eq_refl 4 <<: (fun x => add x x) 2 = 4). Definition compute6 := Eval compute in (fun x => add x x) 2. Check (eq_refl compute6 : 4 = 4). End test. rocq-9.2.0/test-suite/primitive/uint63/land.v000066400000000000000000000023271516144147600210560ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : land 0 0 = 0). Check (eq_refl 0 <: land 0 0 = 0). Check (eq_refl 0 <<: land 0 0 = 0). Definition compute1 := Eval compute in land 0 0. Check (eq_refl compute1 : 0 = 0). Check (eq_refl : land 9223372036854775807 0 = 0). Check (eq_refl 0 <: land 9223372036854775807 0 = 0). Check (eq_refl 0 <<: land 9223372036854775807 0 = 0). Definition compute2 := Eval compute in land 9223372036854775807 0. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : land 0 9223372036854775807 = 0). Check (eq_refl 0 <: land 0 9223372036854775807 = 0). Check (eq_refl 0 <<: land 0 9223372036854775807 = 0). Definition compute3 := Eval compute in land 0 9223372036854775807. Check (eq_refl compute3 : 0 = 0). Check (eq_refl : land 9223372036854775807 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: land 9223372036854775807 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: land 9223372036854775807 9223372036854775807 = 9223372036854775807). Definition compute4 := Eval compute in land 9223372036854775807 9223372036854775807. Check (eq_refl compute4 : 9223372036854775807 = 9223372036854775807). rocq-9.2.0/test-suite/primitive/uint63/leb.v000066400000000000000000000014001516144147600206710ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : leb 1 1 = true). Check (eq_refl true <: leb 1 1 = true). Check (eq_refl true <<: leb 1 1 = true). Definition compute1 := Eval compute in leb 1 1. Check (eq_refl compute1 : true = true). Check (eq_refl : leb 1 2 = true). Check (eq_refl true <: leb 1 2 = true). Check (eq_refl true <<: leb 1 2 = true). Definition compute2 := Eval compute in leb 1 2. Check (eq_refl compute2 : true = true). Check (eq_refl : leb 9223372036854775807 0 = false). Check (eq_refl false <: leb 9223372036854775807 0 = false). Check (eq_refl false <<: leb 9223372036854775807 0 = false). Definition compute3 := Eval compute in leb 9223372036854775807 0. Check (eq_refl compute3 : false = false). rocq-9.2.0/test-suite/primitive/uint63/lor.v000066400000000000000000000027031516144147600207320ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : lor 0 0 = 0). Check (eq_refl 0 <: lor 0 0 = 0). Check (eq_refl 0 <<: lor 0 0 = 0). Definition compute1 := Eval compute in lor 0 0. Check (eq_refl compute1 : 0 = 0). Check (eq_refl : lor 9223372036854775807 0 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: lor 9223372036854775807 0 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: lor 9223372036854775807 0 = 9223372036854775807). Definition compute2 := Eval compute in lor 9223372036854775807 0. Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807). Check (eq_refl : lor 0 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: lor 0 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: lor 0 9223372036854775807 = 9223372036854775807). Definition compute3 := Eval compute in lor 0 9223372036854775807. Check (eq_refl compute3 : 9223372036854775807 = 9223372036854775807). Check (eq_refl : lor 9223372036854775807 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: lor 9223372036854775807 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: lor 9223372036854775807 9223372036854775807 = 9223372036854775807). Definition compute4 := Eval compute in lor 9223372036854775807 9223372036854775807. Check (eq_refl compute4 : 9223372036854775807 = 9223372036854775807). rocq-9.2.0/test-suite/primitive/uint63/lsl.v000066400000000000000000000015041516144147600207260ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : lsl 3 61 = 6917529027641081856). Check (eq_refl 6917529027641081856 <: lsl 3 61 = 6917529027641081856). Check (eq_refl 6917529027641081856 <<: lsl 3 61 = 6917529027641081856). Definition compute1 := Eval compute in lsl 3 61. Check (eq_refl compute1 : 6917529027641081856 = 6917529027641081856). Check (eq_refl : lsl 2 62 = 0). Check (eq_refl 0 <: lsl 2 62 = 0). Check (eq_refl 0 <<: lsl 2 62 = 0). Definition compute2 := Eval compute in lsl 2 62. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : lsl 9223372036854775807 64 = 0). Check (eq_refl 0 <: lsl 9223372036854775807 64 = 0). Check (eq_refl 0 <<: lsl 9223372036854775807 64 = 0). Definition compute3 := Eval compute in lsl 9223372036854775807 64. Check (eq_refl compute3 : 0 = 0). rocq-9.2.0/test-suite/primitive/uint63/lsr.v000066400000000000000000000015261516144147600207400ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : lsr 6917529027641081856 61 = 3). Check (eq_refl 3 <: lsr 6917529027641081856 61 = 3). Check (eq_refl 3 <<: lsr 6917529027641081856 61 = 3). Definition compute1 := Eval compute in lsr 6917529027641081856 61. Check (eq_refl compute1 : 3 = 3). Check (eq_refl : lsr 2305843009213693952 62 = 0). Check (eq_refl 0 <: lsr 2305843009213693952 62 = 0). Check (eq_refl 0 <<: lsr 2305843009213693952 62 = 0). Definition compute2 := Eval compute in lsr 2305843009213693952 62. Check (eq_refl compute2 : 0 = 0). Check (eq_refl : lsr 9223372036854775807 64 = 0). Check (eq_refl 0 <: lsr 9223372036854775807 64 = 0). Check (eq_refl 0 <<: lsr 9223372036854775807 64 = 0). Definition compute3 := Eval compute in lsr 9223372036854775807 64. Check (eq_refl compute3 : 0 = 0). rocq-9.2.0/test-suite/primitive/uint63/ltb.v000066400000000000000000000014071516144147600207170ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : ltb 1 1 = false). Check (eq_refl false <: ltb 1 1 = false). Check (eq_refl false <<: ltb 1 1 = false). Definition compute1 := Eval compute in ltb 1 1. Check (eq_refl compute1 : false = false). Check (eq_refl : ltb 1 2 = true). Check (eq_refl true <: ltb 1 2 = true). Check (eq_refl true <<: ltb 1 2 = true). Definition compute2 := Eval compute in ltb 1 2. Check (eq_refl compute2 : true = true). Check (eq_refl : ltb 9223372036854775807 0 = false). Check (eq_refl false <: ltb 9223372036854775807 0 = false). Check (eq_refl false <<: ltb 9223372036854775807 0 = false). Definition compute3 := Eval compute in ltb 9223372036854775807 0. Check (eq_refl compute3 : false = false). rocq-9.2.0/test-suite/primitive/uint63/lxor.v000066400000000000000000000025251516144147600211240ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : lxor 0 0 = 0). Check (eq_refl 0 <: lxor 0 0 = 0). Check (eq_refl 0 <<: lxor 0 0 = 0). Definition compute1 := Eval compute in lxor 0 0. Check (eq_refl compute1 : 0 = 0). Check (eq_refl : lxor 9223372036854775807 0 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: lxor 9223372036854775807 0 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: lxor 9223372036854775807 0 = 9223372036854775807). Definition compute2 := Eval compute in lxor 9223372036854775807 0. Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807). Check (eq_refl : lxor 0 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: lxor 0 9223372036854775807 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: lxor 0 9223372036854775807 = 9223372036854775807). Definition compute3 := Eval compute in lxor 0 9223372036854775807. Check (eq_refl compute3 : 9223372036854775807 = 9223372036854775807). Check (eq_refl : lxor 9223372036854775807 9223372036854775807 = 0). Check (eq_refl 0 <: lxor 9223372036854775807 9223372036854775807 = 0). Check (eq_refl 0 <<: lxor 9223372036854775807 9223372036854775807 = 0). Definition compute4 := Eval compute in lxor 9223372036854775807 9223372036854775807. Check (eq_refl compute4 : 0 = 0). rocq-9.2.0/test-suite/primitive/uint63/mod.v000066400000000000000000000006731516144147600207210ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : mod 6 3 = 0). Check (eq_refl 0 <: mod 6 3 = 0). Check (eq_refl 0 <<: mod 6 3 = 0). Definition compute1 := Eval compute in mod 6 3. Check (eq_refl compute1 : 0 = 0). Check (eq_refl : mod 5 3 = 2). Check (eq_refl 2 <: mod 5 3 = 2). Check (eq_refl 2 <<: mod 5 3 = 2). Definition compute2 := Eval compute in mod 5 3. Check (eq_refl compute2 : 2 = 2). rocq-9.2.0/test-suite/primitive/uint63/mul.v000066400000000000000000000012011516144147600207230ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : mul 2 3 = 6). Check (eq_refl 6 <: mul 2 3 = 6). Check (eq_refl 6 <<: mul 2 3 = 6). Definition compute1 := Eval compute in mul 2 3. Check (eq_refl compute1 : 6 = 6). Check (eq_refl : mul 9223372036854775807 2 = 9223372036854775806). Check (eq_refl 9223372036854775806 <: mul 9223372036854775807 2 = 9223372036854775806). Check (eq_refl 9223372036854775806 <<: mul 9223372036854775807 2 = 9223372036854775806). Definition compute2 := Eval compute in mul 9223372036854775807 2. Check (eq_refl compute2 : 9223372036854775806 = 9223372036854775806). rocq-9.2.0/test-suite/primitive/uint63/mulc.v000066400000000000000000000015521516144147600210770ustar00rootroot00000000000000Require Import BinNums IntDef PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : mulc 2 3 = (0, 6)). Check (eq_refl ((0, 6)) <: mulc 2 3 = (0, 6)). Check (eq_refl ((0, 6)) <<: mulc 2 3 = (0, 6)). Definition compute1 := Eval compute in mulc 2 3. Check (eq_refl compute1 : (0, 6) = (0, 6)). Check (eq_refl : mulc 9223372036854775807 2 = (1, 9223372036854775806)). Check (eq_refl ((1, 9223372036854775806)) <: mulc 9223372036854775807 2 = (1, 9223372036854775806)). Check (eq_refl ((1, 9223372036854775806)) <<: mulc 9223372036854775807 2 = (1, 9223372036854775806)). Definition compute2 := Eval compute in mulc 9223372036854775807 2. Check (eq_refl compute2 : (1, 9223372036854775806) = (1, 9223372036854775806)). Check (eq_refl : mulc 0 0 = (0, 0)). Check (eq_refl (0, 0) <: mulc 0 0 = (0, 0)). Check (eq_refl ((0, 0)) <<: mulc 0 0 = (0, 0)). rocq-9.2.0/test-suite/primitive/uint63/reduction.v000066400000000000000000000012741516144147600221340ustar00rootroot00000000000000Require Import PrimInt63. Open Scope uint63_scope. Definition div_eucl_plus_one i1 i2 := let (q,r) := diveucl i1 i2 in (add q 1, add r 1)%uint63. 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 (compare n 42)%uint63 with | Lt => add n m | _ => mul 2 m end. Goal forall n, (compare n 42)%uint63 = Gt -> f n 256 = 512%uint63. intros. unfold f. cbn. Undo. cbv. (* Test reductions under match clauses *) rewrite H. reflexivity. Qed. rocq-9.2.0/test-suite/primitive/uint63/sub.v000066400000000000000000000010711516144147600207240ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : sub 3 2 = 1). Check (eq_refl 1 <: sub 3 2 = 1). Check (eq_refl 1 <<: sub 3 2 = 1). Definition compute1 := Eval compute in sub 3 2. Check (eq_refl compute1 : 1 = 1). Check (eq_refl : sub 0 1 = 9223372036854775807). Check (eq_refl 9223372036854775807 <: sub 0 1 = 9223372036854775807). Check (eq_refl 9223372036854775807 <<: sub 0 1 = 9223372036854775807). Definition compute2 := Eval compute in sub 0 1. Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807). rocq-9.2.0/test-suite/primitive/uint63/subc.v000066400000000000000000000011631516144147600210710ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_scope. Check (eq_refl : subc 3 2 = C0 1). Check (eq_refl (C0 1) <: subc 3 2 = C0 1). Check (eq_refl (C0 1) <<: subc 3 2 = C0 1). Definition compute1 := Eval compute in subc 3 2. Check (eq_refl compute1 : C0 1 = C0 1). Check (eq_refl : subc 0 1 = C1 9223372036854775807). Check (eq_refl (C1 9223372036854775807) <: subc 0 1 = C1 9223372036854775807). Check (eq_refl (C1 9223372036854775807) <<: subc 0 1 = C1 9223372036854775807). Definition compute2 := Eval compute in subc 0 1. Check (eq_refl compute2 : C1 9223372036854775807 = C1 9223372036854775807). rocq-9.2.0/test-suite/primitive/uint63/subcarryc.v000066400000000000000000000012331516144147600221300ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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). rocq-9.2.0/test-suite/primitive/uint63/tail0.v000066400000000000000000000013101516144147600211400ustar00rootroot00000000000000Require Import PrimInt63. Set Implicit Arguments. Open Scope uint63_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). rocq-9.2.0/test-suite/primitive/uint63/unsigned.v000066400000000000000000000011441516144147600217500ustar00rootroot00000000000000(* This file checks that operations over int63 are unsigned. *) Require Import PrimInt63. Open Scope uint63_scope. (* (0-1) must be the maximum integer value and not negative 1 *) Check (eq_refl : div 1 (sub 0 1) = 0). Check (eq_refl 0 <: div 1 (sub 0 1) = 0). Check (eq_refl 0 <<: div 1 (sub 0 1) = 0). Definition compute1 := Eval compute in div 1 (sub 0 1). Check (eq_refl compute1 : 0 = 0). Check (eq_refl : mod 3 (sub 0 1) = 3). Check (eq_refl 3 <: mod 3 (sub 0 1) = 3). Check (eq_refl 3 <<: mod 3 (sub 0 1) = 3). Definition compute2 := Eval compute in mod 3 (sub 0 1). Check (eq_refl compute2 : 3 = 3). rocq-9.2.0/test-suite/report.sh000077500000000000000000000020771516144147600164650ustar00rootroot00000000000000#!/usr/bin/env bash # save failed logs to logs/, then print failure information # returns failure code if any failed logs exist # save step SAVEDIR="logs" # reset for local builds rm -rf "$SAVEDIR" mkdir "$SAVEDIR" FAILED=$(mktemp) grep -F 'Error!' -r . -l --null --include="*.log" > "$FAILED" rsync -a --from0 --files-from="$FAILED" . "$SAVEDIR" cp summary.log "$SAVEDIR"/ # cleanup rm "$FAILED" # print info if [ -n "$CI" ] || [ -n "$PRINT_LOGS" ]; then find logs/ -name '*.log' -not -name 'summary.log' -print0 | while IFS= read -r -d '' file; do printf '%s\n' "$file" cat "$file" printf '\n' done printed_logs=1 fi if grep -q -F 'Error!' summary.log ; then echo FAILURES; grep -F 'Error!' summary.log; if [ -z "$printed_logs" ]; then echo 'To print details of failed tests, rerun with environment variable PRINT_LOGS=1' echo 'eg "make report PRINT_LOGS=1" from the test suite directory"' echo 'See README.md in the test suite directory for more information.' fi false else echo NO FAILURES; fi rocq-9.2.0/test-suite/ssr/000077500000000000000000000000001516144147600154145ustar00rootroot00000000000000rocq-9.2.0/test-suite/ssr/absevarprop.v000066400000000000000000000066441516144147600201410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* val x = y -> Some x = insub y. move=> y x le_1 defx; rewrite insubT ?(leq_trans le_1) // => ?. by congr (Some _); apply: val_inj=> /=; exact: defx. Qed. Axiom P : nat -> Prop. Axiom Q : forall n, P n -> Prop. Definition R := fun (x : nat) (p : P x) m (q : P (x+1)) => m > 0. Inductive myEx : Type := ExI : forall n (pn : P n) pn', Q n pn -> R n pn n pn' -> myEx. Parameter P1 : P 1. Parameter P11 : P (1 + 1). Parameter Q1 : forall P1, Q 1 P1. Lemma testmE1 : myEx. Proof. apply: ExI 1 _ _ _ _. match goal with |- P 1 => exact: P1 | _ => fail end. match goal with |- P (1+1) => exact: P11 | _ => fail end. match goal with |- forall p : P 1, Q 1 p => move=> *; exact: Q1 | _ => fail end. match goal with |- forall (p : P 1) (q : P (1+1)), is_true (R 1 p 1 q) => done | _ => fail end. Qed. Lemma testE2 : exists y : { x | P x }, sval y = 1. Proof. apply: ex_intro (exist _ 1 _) _. match goal with |- P 1 => exact: P1 | _ => fail end. match goal with |- forall p : P 1, @sval _ _ (@exist _ _ 1 p) = 1 => done | _ => fail end. Qed. Lemma testE3 : exists y : { x | P x }, sval y = 1. Proof. have := (ex_intro _ (exist _ 1 _) _); apply. match goal with |- P 1 => exact: P1 | _ => fail end. match goal with |- forall p : P 1, @sval _ _ (@exist _ _ 1 p) = 1 => done | _ => fail end. Qed. Lemma testE4 : P 2 -> exists y : { x | P x }, sval y = 2. Proof. move=> P2; apply: ex_intro (exist _ 2 _) _. match goal with |- @sval _ _ (@exist _ _ 2 P2) = 2 => done | _ => fail end. Qed. #[export] Hint Resolve P1. Lemma testmE12 : myEx. Proof. apply: ExI 1 _ _ _ _. match goal with |- P (1+1) => exact: P11 | _ => fail end. match goal with |- Q 1 P1 => exact: Q1 | _ => fail end. match goal with |- forall (q : P (1+1)), is_true (R 1 P1 1 q) => done | _ => fail end. Qed. Create HintDb SSR. #[export] Hint Resolve P11 : SSR. Ltac ssrautoprop := trivial with SSR. Lemma testmE13 : myEx. Proof. apply: ExI 1 _ _ _ _. match goal with |- Q 1 P1 => exact: Q1 | _ => fail end. match goal with |- is_true (R 1 P1 1 P11) => done | _ => fail end. Qed. Definition R1 := fun (x : nat) (p : P x) m (q : P (x+1)) (r : Q x p) => m > 0. Inductive myEx1 : Type := ExI1 : forall n (pn : P n) pn' (q : Q n pn), R1 n pn n pn' q -> myEx1. #[export] Hint Extern 0 (Q 1 P1) => apply (Q1 P1) : SSR. (* tests that goals in prop are solved in the right order, propagating instantiations, thus the goal Q 1 ?p1 is faced by trivial after ?p1, and is thus evar free *) Lemma testmE14 : myEx1. Proof. apply: ExI1 1 _ _ _ _. match goal with |- is_true (R1 1 P1 1 P11 (Q1 P1)) => done | _ => fail end. Qed. rocq-9.2.0/test-suite/ssr/abstract_var2.v000066400000000000000000000017111516144147600203400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* nat -> Prop. Axiom tr : forall x y z, P x y -> P y z -> P x z. Lemma test a b c : P a c -> P a b. Proof. intro H. Fail have [: s1 s2] H1 : P a b := @tr _ _ _ s1 s2. have [: w s1 s2] H1 : P a b := @tr _ w _ s1 s2. Abort. rocq-9.2.0/test-suite/ssr/autoclean.v000066400000000000000000000001731516144147600175570ustar00rootroot00000000000000Require Import ssreflect. Lemma view_disappears A B (AB : A -> B) : A -> False. Proof. move=> {}/(AB). have := AB. Abort. rocq-9.2.0/test-suite/ssr/bang_rewrite.v000066400000000000000000000005101516144147600202470ustar00rootroot00000000000000Set Universe Polymorphism. Require Import ssreflect. Axiom mult@{i} : nat -> nat -> nat. Notation "m * n" := (mult m n). Axiom multA : forall a b c, (a * b) * c = a * (b * c). (* Previously the following gave a universe error: *) Lemma multAA a b c d : ((a * b) * c) * d = a * (b * (c * d)). Proof. by rewrite !multA. Qed. rocq-9.2.0/test-suite/ssr/binders.v000066400000000000000000000035371516144147600172410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* H2. have H3 T (x : T) := x. have ? : bool := H1 _ x. have ? : bool := H2 _ x. have ? : bool := H3 _ x. have ? (z : bool) : forall y : bool, z = z := fun y => refl_equal _. have ? w : w = w := @refl_equal nat w. have ? y : true by []. have ? (z : bool) : z = z. exact: (@refl_equal _ z). have ? (z w : bool) : z = z by exact: (@refl_equal _ z). have H w (a := 3) (_ := 4) : w && true = w. by rewrite andbT. exact I. Qed. Lemma test1 : True. suff (x : bool): x = x /\ True. by move/(_ true); case=> _. split; first by exact: (@refl_equal _ x). suff H y : y && true = y /\ True. by case: (H true). suff H1 /= : true && true /\ True. by rewrite andbT; split; [exact: (@refl_equal _ y) | exact: I]. match goal with |- is_true true /\ True => idtac end. by split. Qed. Lemma foo n : n >= 0. have f i (j := i + n) : j < n. match goal with j := i + n |- _ => idtac end. Undo 2. suff f i (j := i + n) : j < n. done. match goal with j := i + n |- _ => idtac end. Undo 3. done. Qed. rocq-9.2.0/test-suite/ssr/binders_of.v000066400000000000000000000017221516144147600177170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* true | EFin r1, EFin r2 => true | ENInf, _ | _, EPInf => true | EPInf, _ | _, ENInf => false end. Axiom lee_pinfty : forall (x : extended), is_true (le_ereal x (EPInf)). Definition adde_subdef (x y : extended) := match x, y with | EFin _, EFin _ => x | ENInf, _ => ENInf | _ , ENInf => ENInf | EPInf, _ => EPInf | _ , EPInf => EPInf end. Definition adde := nosimpl adde_subdef. Goal forall (x : R), (forall e : R, is_true (le_ereal (EFin x) (adde (EPInf) (EFin e)))) -> True. Proof. intros x. Fail rewrite (lee_pinfty (EFin x)). constructor. Qed. rocq-9.2.0/test-suite/ssr/bug_15753_2.v000066400000000000000000000003541516144147600173470ustar00rootroot00000000000000Require Import Corelib.ssr.ssreflect. Class FromPureT (Ο† : Type) := from_pureT : exists ψ : Prop, Ο† = ψ. Lemma into_forall_impl_pure Ο† : FromPureT Ο† -> Ο† -> True. Proof. rewrite /FromPureT => -[Ο†' ->]. constructor. Qed. rocq-9.2.0/test-suite/ssr/bug_15770.v000066400000000000000000000005401516144147600171220ustar00rootroot00000000000000Require Import Corelib.ssr.ssreflect. Axiom xget : forall {T} (P : T -> Prop), T. Variant xget_spec {T} (P : T -> Prop) : T -> Prop -> Type := | XGetSome x of P x : xget_spec P x True. Axiom xgetP : forall {T} (P : T -> Prop), xget_spec P (xget P) (P (xget P)). Lemma xgetPex {T} (P : T -> Prop) : P (xget P). Proof. case: xgetP. constructor. Qed. rocq-9.2.0/test-suite/ssr/bug_16720.v000066400000000000000000000002421516144147600171150ustar00rootroot00000000000000From Corelib Require Import ssreflect. Class Trivial := trivial {}. #[local] Existing Instance trivial. Goal Trivial. Succeed assert True. have: True. Abort. rocq-9.2.0/test-suite/ssr/bug_19229.v000066400000000000000000000160041516144147600171270ustar00rootroot00000000000000From Corelib.ssr Require Import ssreflect ssrfun ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Module isSub. (* val_subdef being a primitive projections is what makes it fail *) #[projections(primitive)] Record axioms_ T (P : pred T) sub_sort : Type := Axioms_ { val_subdef : sub_sort -> T }. Definition phant_Build T (P : pred T) sub_sort (val_subdef : sub_sort -> T) := @isSub.Axioms_ T P sub_sort val_subdef. End isSub. Module SubType. Record axioms_ T (P : pred T) S : Type := Class { ssralg_isSub_mixin : isSub.axioms_ P S }. Record type T (P : pred T) : Type := Pack { sort : Type; class : @SubType.axioms_ T P sort }. Definition phant_on_ T (P : pred T) (S : type P) (_ : phant (sort S)) := class S. Notation on elpi_ctx_entry_1_was_T_ := (phant_on_ (Phant _) : axioms_ _ elpi_ctx_entry_1_was_T_). Module Exports. Coercion sort : type >-> Sortclass. Coercion ssralg_isSub_mixin : axioms_ >-> isSub.axioms_. Definition val_subdef T (P : pred T) (s : type P) := isSub.val_subdef (SubType.ssralg_isSub_mixin (class s)). End Exports. End SubType. Export SubType.Exports. (* We need a canonical projection so that rewrite can do keyd matching modulo CS inference *) Notation val := ((SubType.on _).(isSub.val_subdef)). Notation "\val" := ((SubType.on _).(isSub.val_subdef)) (only parsing). Notation "\val" := ((_).(isSub.val_subdef)) (only printing). Module isNmodule. Record axioms_ V : Type := Axioms_ { add : V -> V -> V }. Definition phant_Build V (add : V -> V -> V) := Axioms_ add. End isNmodule. Module Nmodule. Record axioms_ (V : Type) : Type := Class { ssralg_isNmodule_mixin : isNmodule.axioms_ V } as record. Record type : Type := Pack { sort : Type; class : Nmodule.axioms_ sort }. Module Exports. Notation nmodType := Nmodule.type. Coercion sort : type >-> Sortclass. Definition add (s : Nmodule.type) := isNmodule.add (Nmodule.ssralg_isNmodule_mixin (Nmodule.class s)). End Exports. End Nmodule. Export Nmodule.Exports. Module isSemiAdditive. Variant axioms_ (U V : Nmodule.type) (apply : forall _ : Nmodule.sort U, Nmodule.sort V) : Type := Axioms_. Definition phant_Build (U V : Nmodule.type) (apply : forall _ : Nmodule.sort U, Nmodule.sort V) := @isSemiAdditive.Axioms_ U V apply. End isSemiAdditive. Module Additive. Record axioms_ (U V : nmodType) (f : U -> V) : Type := Class { ssralg_isSemiAdditive_mixin : isSemiAdditive.axioms_ f } as record. Record type (U V : nmodType) : Type := Pack { sort : U -> V; class : Additive.axioms_ sort }. Module Exports. Coercion sort : type >-> Funclass. End Exports. End Additive. Export Additive.Exports. Lemma raddfD U V (f : Additive.type U V) : {morph f : x y / add x y}. Admitted. Module isAddClosed. Variant axioms_ (V : Nmodule.type) (S : @pred_sort (Nmodule.sort V) (predPredType (Nmodule.sort V))) : Type := Axioms_. Definition phant_Build (V : Nmodule.type) (S : pred_sort (predPredType (Nmodule.sort V))) := Axioms_ S. End isAddClosed. Module AddClosed. Record axioms_ (V : Nmodule.type) (S : pred_sort (predPredType (Nmodule.sort V))) : Type := Class { ssralg_isAddClosed_mixin : isAddClosed.axioms_ S }. Record type (V : Nmodule.type) : Type := Pack { sort : pred_sort (predPredType (Nmodule.sort V)); _ : AddClosed.axioms_ sort }. End AddClosed. Module isSubNmodule. Definition isSubNmodule_U__canonical__ssralg_SubType (V : nmodType) (S : pred V) (U : Type) (local_mixin_ssralg_isSub : isSub.axioms_ S U) := {| SubType.sort := U; SubType.class := {| SubType.ssralg_isSub_mixin := local_mixin_ssralg_isSub |} |}. Definition isSubNmodule_U__canonical__ssralg_Nmodule (U : Type) (local_mixin_ssralg_isNmodule : isNmodule.axioms_ U) := {| Nmodule.sort := U; Nmodule.class := {| Nmodule.ssralg_isNmodule_mixin := local_mixin_ssralg_isNmodule |} |}. Record axioms_ (V : nmodType) (S : pred V) (U : Type) (local_mixin_ssralg_isSub : isSub.axioms_ S U) (local_mixin_ssralg_isNmodule : isNmodule.axioms_ U) : Type := Axioms_ { }. Definition phant_Build (V : nmodType) (S : pred V) (U : Type) (m : isSub.axioms_ S U) (m0 : isNmodule.axioms_ U) := Axioms_ m m0. End isSubNmodule. Module SubNmodule. Record axioms_ (V : nmodType) (S : pred V) (U : Type) : Type := Class { ssralg_isSub_mixin :> isSub.axioms_ S U; ssralg_isNmodule_mixin :> isNmodule.axioms_ U; ssralg_isSubNmodule_mixin :> isSubNmodule.axioms_ ssralg_isSub_mixin ssralg_isNmodule_mixin }. Record type (V : nmodType) (S : pred V) : Type := Pack { sort :> Type; class : SubNmodule.axioms_ S sort }. Module Exports. Coercion ssralg_SubNmodule_class__to__ssralg_Nmodule_class (V : nmodType) (S : pred V) (U : Type) (c : SubNmodule.axioms_ S U) := {| Nmodule.ssralg_isNmodule_mixin := c |}. Coercion ssralg_SubNmodule__to__ssralg_Nmodule (V : nmodType) (S : pred V) (s : SubNmodule.type S) := {| Nmodule.sort := s; Nmodule.class := SubNmodule.class s |}. Coercion ssralg_SubNmodule_class__to__ssralg_SubType_class (V : nmodType) (S : pred V) (U : Type) (c : SubNmodule.axioms_ S U) := {| SubType.ssralg_isSub_mixin := c |}. Coercion ssralg_SubNmodule__to__ssralg_SubType (V : nmodType) (S : pred V) (s : SubNmodule.type S) := {| SubType.sort := s; SubType.class := SubNmodule.class s |}. Canonical join_ssralg_SubNmodule_between_ssralg_Nmodule_and_ssralg_SubType (V : nmodType) (S : pred V) (U : SubNmodule.type S) := {| SubType.sort := U; SubType.class := SubType.class U |}. End Exports. End SubNmodule. Export SubNmodule.Exports. Definition HB_unnamed_factory_0 (V : Nmodule.type) (S : pred (Nmodule.sort V)) (U : @SubNmodule.type V S) := @isSemiAdditive.Axioms_ U V (@isSub.val_subdef _ _ _ (SubType.ssralg_isSub_mixin (SubType.phant_on_ (Phant _)))). Canonical isSub_val_subdef__canonical__ssralg_Additive (V : Nmodule.type) (S : pred (Nmodule.sort V)) (U : @SubNmodule.type V S) := @Additive.Pack (@ssralg_SubNmodule__to__ssralg_Nmodule V S U) V (isSub.val_subdef _) (Additive.Class (HB_unnamed_factory_0 U)). Parameter V : Nmodule.type. Parameter S : pred (Nmodule.sort V). Parameter U : Type. Parameter local_mixin_ssralg_isSub : isSub.axioms_ S U. Canonical Builders_18_U__canonical__ssralg_SubType := @SubType.Pack (Nmodule.sort V) S U (@SubType.Class (Nmodule.sort V) S U local_mixin_ssralg_isSub). Definition HB_unnamed_factory_1 := @isAddClosed.phant_Build V S. Canonical Builders_4_S__canonical__ssralg_AddClosed := @AddClosed.Pack V S (AddClosed.Class HB_unnamed_factory_1). Parameter addU : U -> U -> U. Definition HB_unnamed_factory_2 := @isNmodule.phant_Build U addU. Canonical Builders_4_U__canonical__ssralg_Nmodule := @Nmodule.Pack U (Nmodule.Class HB_unnamed_factory_2). Definition HB_unnamed_factory_3 := @isSubNmodule.phant_Build V S U local_mixin_ssralg_isSub HB_unnamed_factory_2. Canonical Builders_4_U__canonical__ssralg_SubNmodule := @SubNmodule.Pack V S U (SubNmodule.Class HB_unnamed_factory_3). Lemma mulrDl (x y : U) : \val (add x y) = \val (add y x). Proof. rewrite raddfD. (* but "rewrite [LHS]raddfD." works *) Abort. rocq-9.2.0/test-suite/ssr/case_TC.v000066400000000000000000000005241516144147600171050ustar00rootroot00000000000000From Corelib Require Import ssreflect. From Corelib Require Import ssrbool. Set Printing All. Set Debug Ssreflect. Class Class := { sort : Type ; op : sort -> bool }. Coercion sort : Class >-> Sortclass. Arguments op [_] _. Section Section. Context (A B: Class) (a: A). Goal op a || ~~ op a. by case: op. Abort. End Section. rocq-9.2.0/test-suite/ssr/case_TC2.v000066400000000000000000000005641516144147600171730ustar00rootroot00000000000000From Corelib Require Import ssreflect. Set Printing All. Set Debug Ssreflect. Class Class := { sort : Type ; op : sort -> bool }. Coercion sort : Class >-> Sortclass. Arguments op [_] _. Lemma opP (A: Class) (a: A) : reflect True (op a). Proof. Admitted. Section Section. Context (A B: Class) (a: A). Goal is_true (op a). by case: opP. Abort. End Section. rocq-9.2.0/test-suite/ssr/case_TC3.v000066400000000000000000000006201516144147600171650ustar00rootroot00000000000000From Corelib Require Import ssreflect. Set Printing All. Set Debug Ssreflect. Class Class sort := { op : sort -> bool }. Arguments op {_ _}. #[export] Hint Mode Class !. Lemma opP A (C: Class A) (a: A) : reflect True (op a). Proof. Admitted. Arguments op {_ _}. Section Section. Context A B (CA : Class A) (CB : Class B) (a: A). Goal is_true (op a). by case: opP. Abort. End Section. rocq-9.2.0/test-suite/ssr/case_polyuniv.v000066400000000000000000000004131516144147600204610ustar00rootroot00000000000000Require Import ssreflect. Set Universe Polymorphism. Cumulative Variant paths {A} (x:A) : A -> Type := idpath : paths x x. Register paths as core.eq.type. Register idpath as core.eq.refl. Lemma case_test (b:bool) : paths b b. Proof. case B:b; reflexivity. Qed. rocq-9.2.0/test-suite/ssr/caseeqltac.v000066400000000000000000000001721516144147600177100ustar00rootroot00000000000000Require Import ssreflect. Goal (1 + 2 = 3). Proof. let E := fresh "F" in move E: (2 in LHS) => n. rewrite F. by []. Qed. rocq-9.2.0/test-suite/ssr/caseview.v000066400000000000000000000015321516144147600174120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* True. Proof. by case=> _ /id _. Qed. rocq-9.2.0/test-suite/ssr/congr.v000066400000000000000000000033131516144147600167130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* a == 0 -> b == 0. Proof. move=> a b Eab Eac; congr (_ == 0) : Eac; exact: eqP Eab. Qed. Definition arrow A B := A -> B. Lemma test2 : forall a b : nat, a == b -> arrow (a == 0) (b == 0). Proof. move=> a b Eab; congr (_ == 0); exact: eqP Eab. Qed. Definition equals T (A B : T) := A = B. Lemma test3 : forall a b : nat, a = b -> equals nat (a + b) (b + b). Proof. move=> a b E; congr (_ + _); exact E. Qed. Parameter S : eqType. Parameter f : nat -> S. Coercion f : nat >-> Equality.sort. Lemma test4 : forall a b : nat, b = a -> @eq S (b + b) (a + a). Proof. move=> a b Eba; congr (_ + _); exact: Eba. Qed. Open Scope type_scope. Lemma test5 : forall (P Q Q' : Type) (h : Q = Q'), P * Q = P * Q'. Proof. move=>*; by congr (_ * _). Qed. Lemma test6 : forall (P Q Q' : Type) (h : Q = Q'), P * Q -> P * Q'. Proof. move=> P Q Q' h; by congr (_ * _). Qed. rocq-9.2.0/test-suite/ssr/deferclear.v000066400000000000000000000023611516144147600177010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* a b {a} a c; exact I. Qed. Parameter P : T -> Prop. Lemma test1 : forall a b c : T, P a -> forall d : T, True. Proof. move=> a b {a} a _ d; exact I. Qed. Definition Q := forall x y : nat, x = y. Axiom L : 0 = 0 -> Q. Axiom L' : 0 = 0 -> forall x y : nat, x = y. Lemma test3 : Q. by apply/L. Undo. rewrite /Q. by apply/L. Undo 2. by apply/L'. Qed. rocq-9.2.0/test-suite/ssr/delayed_clear_rename.v000066400000000000000000000002001516144147600216770ustar00rootroot00000000000000Require Import ssreflect. Example foo (t t1 t2 : True) : True /\ True -> True -> True. Proof. move=>[{t1 t2 t} t1 t2] t. Abort. rocq-9.2.0/test-suite/ssr/dependent_type_err.v000066400000000000000000000020441516144147600214620ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* n <= p -> m < p. move=> n m p Hmn Hnp; rewrite -ltnS. Fail rewrite (_ : forall n0 m0 p0 : nat, m0 <= n0 -> n0 < p0 -> m0 < p0). Fail rewrite leq_ltn_trans. Admitted. rocq-9.2.0/test-suite/ssr/derive_inversion.v000066400000000000000000000021641516144147600211600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* option T -> Type := | wf_f : wf false None | wf_t : forall x, wf true (Some x). Derive Inversion wf_inv with (forall T b (o : option T), wf b o) Sort Prop. Lemma Problem T b (o : option T) : wf b o -> match b with | true => exists x, o = Some x | false => o = None end. Proof. by case: b; elim/wf_inv=> //; case: o=> // a *; exists a. Qed. rocq-9.2.0/test-suite/ssr/elim.v000066400000000000000000000236641516144147600165440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A s; elim branch: s => [|x xs _]. match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end. match goal with _ : _ = _ :: _ |- _ :: _ = _ :: _ => move: branch => // | _ => fail end. Qed. (* The same but with explicit eliminator and a conflict in the intro pattern *) Lemma testL2 : forall A (s : seq A), s = s. Proof. move=> A s; elim/last_ind branch: s => [|x s _]. match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end. match goal with _ : _ = rcons _ _ |- rcons _ _ = rcons _ _ => move: branch => // | _ => fail end. Qed. (* The same but without names for variables involved in the generated eq *) Lemma testL3 : forall A (s : seq A), s = s. Proof. move=> A s; elim branch: s. match goal with _ : _ = [::] |- [::] = [::] => move: branch => // | _ => fail end. move=> _; match goal with _ : _ = _ :: _ |- _ :: _ = _ :: _ => move: branch => // | _ => fail end. Qed. Inductive foo : Type := K1 : foo | K2 : foo -> foo -> foo | K3 : (nat -> foo) -> foo. (* The same but with more intros to be done *) Lemma testL4 : forall (o : foo), o = o. Proof. move=> o; elim branch: o. match goal with _ : _ = K1 |- K1 = K1 => move: branch => // | _ => fail end. move=> _; match goal with _ : _ = K2 _ _ |- K2 _ _ = K2 _ _ => move: branch => // | _ => fail end. move=> _; match goal with _ : _ = K3 _ |- K3 _ = K3 _ => move: branch => // | _ => fail end. Qed. (* Occurrence counting *) Lemma testO1: forall (b : bool), b = b. Proof. move=> b; case: (b) / idP. match goal with |- is_true b -> true = true => done | _ => fail end. match goal with |- ~ is_true b -> false = false => done | _ => fail end. Qed. (* The same but only the second occ *) Lemma testO2: forall (b : bool), b = b. Proof. move=> b; case: {2}(b) / idP. match goal with |- is_true b -> b = true => done | _ => fail end. match goal with |- ~ is_true b -> b = false => move/(introF idP) => // | _ => fail end. Qed. (* The same but with eq generation *) Lemma testO3: forall (b : bool), b = b. Proof. move=> b; case E: {2}(b) / idP. match goal with _ : is_true b, _ : b = true |- b = true => move: E => _; done | _ => fail end. match goal with H : ~ is_true b, _ : b = false |- b = false => move: E => _; move/(introF idP): H => // | _ => fail end. Qed. (* Views *) Lemma testV1 : forall A (s : seq A), s = s. Proof. move=> A s; case/lastP E: {1}s => [| x xs]. match goal with _ : s = [::] |- [::] = s => symmetry; exact E | _ => fail end. match goal with _ : s = rcons x xs |- rcons _ _ = s => symmetry; exact E | _ => fail end. Qed. Lemma testV2 : forall A (s : seq A), s = s. Proof. move=> A s; case/lastP E: s => [| x xs]. match goal with _ : s = [::] |- [::] = [::] => done | _ => fail end. match goal with _ : s = rcons x xs |- rcons _ _ = rcons _ _ => done | _ => fail end. Qed. Lemma testV3 : forall A (s : seq A), s = s. Proof. move=> A s; case/lastP: s => [| x xs]. match goal with |- [::] = [::] => done | _ => fail end. match goal with |- rcons _ _ = rcons _ _ => done | _ => fail end. Qed. (* Patterns *) Lemma testP1: forall (x y : nat), (y == x) && (y == x) -> y == x. move=> x y; elim: {2}(_ == _) / eqP. match goal with |- (y = x -> is_true ((y == x) && true) -> is_true (y == x)) => move=> -> // | _ => fail end. match goal with |- (y <> x -> is_true ((y == x) && false) -> is_true (y == x)) => move=> _; rewrite andbC // | _ => fail end. Qed. (* The same but with an implicit pattern *) Lemma testP2 : forall (x y : nat), (y == x) && (y == x) -> y == x. move=> x y; elim: {2}_ / eqP. match goal with |- (y = x -> is_true ((y == x) && true) -> is_true (y == x)) => move=> -> // | _ => fail end. match goal with |- (y <> x -> is_true ((y == x) && false) -> is_true (y == x)) => move=> _; rewrite andbC // | _ => fail end. Qed. (* The same but with an eq generation switch *) Lemma testP3 : forall (x y : nat), (y == x) && (y == x) -> y == x. move=> x y; elim E: {2}_ / eqP. match goal with _ : y = x |- (is_true ((y == x) && true) -> is_true (y == x)) => rewrite E; reflexivity | _ => fail end. match goal with _ : y <> x |- (is_true ((y == x) && false) -> is_true (y == x)) => rewrite E => /= H; exact H | _ => fail end. Qed. Inductive spec : nat -> nat -> nat -> Prop := | specK : forall a b c, a = 0 -> b = 2 -> c = 4 -> spec a b c. Lemma specP : spec 0 2 4. Proof. by constructor. Qed. Lemma testP4 : (1+1) * 4 = 2 + (1+1) + (2 + 2). Proof. case: specP => a b c defa defb defc. match goal with |- (a.+1 + a.+1) * c = b + (a.+1 + a.+1) + (b + b) => subst; done | _ => fail end. Qed. Lemma testP5 : (1+1) * 4 = 2 + (1+1) + (2 + 2). Proof. case: (1 + 1) _ / specP => a b c defa defb defc. match goal with |- b * c = a.+2 + b + (a.+2 + a.+2) => subst; done | _ => fail end. Qed. Lemma testP6 : (1+1) * 4 = 2 + (1+1) + (2 + 2). Proof. case: {2}(1 + 1) _ / specP => a b c defa defb defc. match goal with |- (a.+1 + a.+1) * c = a.+2 + b + (a.+2 + a.+2) => subst; done | _ => fail end. Qed. Lemma testP7 : (1+1) * 4 = 2 + (1+1) + (2 + 2). Proof. case: _ (1 + 1) (2 + _) / specP => a b c defa defb defc. match goal with |- b * a.+4 = c + c => subst; done | _ => fail end. Qed. Lemma testP8 : (1+1) * 4 = 2 + (1+1) + (2 + 2). Proof. case E: (1 + 1) (2 + _) / specP=> [a b c defa defb defc]. match goal with |- b * a.+4 = c + c => subst; done | _ => fail end. Qed. Parameters (T : Type) (tr : T -> T). Inductive exec (cf0 cf1 : T) : seq T -> Prop := | exec_step : tr cf0 = cf1 -> exec cf0 cf1 [::] | exec_star : forall cf2 t, tr cf0 = cf2 -> exec cf2 cf1 t -> exec cf0 cf1 (cf2 :: t). Inductive execr (cf0 cf1 : T) : seq T -> Prop := | execr_step : tr cf0 = cf1 -> execr cf0 cf1 [::] | execr_star : forall cf2 t, execr cf0 cf2 t -> tr cf2 = cf1 -> execr cf0 cf1 (t ++ [:: cf2]). Lemma execP : forall cf0 cf1 t, exec cf0 cf1 t <-> execr cf0 cf1 t. Proof. move=> cf0 cf1 t; split => [] Ecf. elim: Ecf. match goal with |- forall cf2 cf3 : T, tr cf2 = cf3 -> execr cf2 cf3 [::] => myadmit | _ => fail end. match goal with |- forall (cf2 cf3 cf4 : T) (t0 : seq T), tr cf2 = cf4 -> exec cf4 cf3 t0 -> execr cf4 cf3 t0 -> execr cf2 cf3 (cf4 :: t0) => myadmit | _ => fail end. elim: Ecf. match goal with |- forall cf2 : T, tr cf0 = cf2 -> exec cf0 cf2 [::] => myadmit | _ => fail end. match goal with |- forall (cf2 cf3 : T) (t0 : seq T), execr cf0 cf3 t0 -> exec cf0 cf3 t0 -> tr cf3 = cf2 -> exec cf0 cf2 (t0 ++ [:: cf3]) => myadmit | _ => fail end. Qed. Fixpoint plus (m n : nat) {struct n} : nat := match n with | 0 => m | S p => S (plus m p) end. Definition plus_equation : forall m n : nat, plus m n = match n with | 0 => m | p.+1 => (plus m p).+1 end := fun m n : nat => match n as n0 return (forall m0 : nat, plus m0 n0 = match n0 with | 0 => m0 | p.+1 => (plus m0 p).+1 end) with | 0 => @erefl nat | n0.+1 => fun m0 : nat => erefl (plus m0 n0).+1 end m. Definition plus_rect : forall (m : nat) (P : nat -> nat -> Type), (forall n : nat, n = 0 -> P 0 m) -> (forall n p : nat, n = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) -> forall n : nat, P n (plus m n) := fun (m : nat) (P : nat -> nat -> Type) (f0 : forall n : nat, n = 0 -> P 0 m) (f : forall n p : nat, n = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) => fix plus0 (n : nat) : P n (plus m n) := eq_rect_r [eta P n] (let f1 := f0 n in let f2 := f n in match n as n0 return (n = n0 -> (forall p : nat, n0 = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) -> (n0 = 0 -> P 0 m) -> P n0 match n0 with | 0 => m | p.+1 => (plus m p).+1 end) with | 0 => fun (_ : n = 0) (_ : forall p : nat, 0 = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) (f4 : 0 = 0 -> P 0 m) => unkeyed (f4 (erefl 0)) | n0.+1 => fun (_ : n = n0.+1) (f3 : forall p : nat, n0.+1 = p.+1 -> P p (plus m p) -> P p.+1 (plus m p).+1) (_ : n0.+1 = 0 -> P 0 m) => let f5 := let p := n0 in let H := erefl n0.+1 : n0.+1 = p.+1 in f3 p H in unkeyed (let Hrec := plus0 n0 in f5 Hrec) end (erefl n) f2 f1) (plus_equation m n). Definition plus_ind := plus_rect. Lemma exF x y z: plus (plus x y) z = plus x (plus y z). elim/plus_ind: z / (plus _ z). match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end. Undo 2. elim/plus_ind: (plus _ z). match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end. Undo 2. elim/plus_ind: {z}(plus _ z). match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end. Undo 2. elim/plus_ind: {z}_. match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end. Undo 2. elim/plus_ind: z / _. match goal with |- forall n : nat, n = 0 -> plus x y = plus x (plus y 0) => idtac end. done. by move=> _ p _ ->. Qed. (* BUG elim-False *) Lemma testeF : False -> 1 = 0. Proof. by elim. Qed. rocq-9.2.0/test-suite/ssr/elim2.v000066400000000000000000000051721516144147600166200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Type) idx op I r (P : pred I) F : let s := \big[op/idx]_(i <- r | P i) F i in K s * K' s -> K' s. Proof. by move=> /= [_]. Qed. Arguments big_load [R] K [K' idx op I r P F]. Section Elim1. Variables (R : Type) (K : R -> Type) (f : R -> R). Variables (idx : R) (op op' : R -> R -> R). Hypothesis Kid : K idx. Ltac ASSERT1 := match goal with |- (K idx) => myadmit end. Ltac ASSERT2 K := match goal with |- (forall x1 : R, R -> forall y1 : R, R -> K x1 -> K y1 -> K (op x1 y1)) => myadmit end. Lemma big_rec I r (P : pred I) F (Kop : forall i x, P i -> K x -> K (op (F i) x)) : K (\big[op/idx]_(i <- r | P i) F i). Proof. elim/big_ind2: {-}_. ASSERT1. ASSERT2 K. match goal with |- (forall i : I, is_true (P i) -> K (F i)) => myadmit end. Undo 4. elim/big_ind2: _ / {-}_. ASSERT1. ASSERT2 K. match goal with |- (forall i : I, is_true (P i) -> K (F i)) => myadmit end. Undo 4. elim/big_rec2: (\big[op/idx]_(i <- r | P i) op idx (F i)) / (\big[op/idx]_(i <- r | P i) F i). ASSERT1. match goal with |- (forall i : I, R -> forall y2 : R, is_true (P i) -> K y2 -> K (op (F i) y2)) => myadmit end. Undo 3. elim/(big_load (phantom R)): _. Undo. Fail elim/big_rec2: {2}_. elim/big_rec2: (\big[op/idx]_(i <- r | P i) F i) / {1}(\big[op/idx]_(i <- r | P i) F i). Undo. elim/(big_load (phantom R)): _. Undo. Fail elim/big_rec2: _ / {2}(\big[op/idx]_(i <- r | P i) F i). Admitted. Definition morecomplexthannecessary A (P : A -> A -> Prop) x y := P x y. Lemma grab A (P : A -> A -> Prop) n m : (n = m) -> (P n n) -> morecomplexthannecessary A P n m. by move->. Qed. Goal forall n m, m + (n + m) = m + (n * 1 + m). Proof. move=> n m; elim/grab : (_ * _) / {1}n => //; exact: muln1. Qed. End Elim1. rocq-9.2.0/test-suite/ssr/elim_noquant.v000066400000000000000000000012701516144147600202760ustar00rootroot00000000000000Require Import ssreflect. Axiom app : forall T, list T -> list T -> list T. Arguments app {_}. Infix "++" := app. Lemma test (aT rT : Type) (pmap : (aT -> option rT) -> list aT -> list rT) (perm_eq : list rT -> list rT -> Prop) (f : aT -> option rT) (g : rT -> aT) (s t : list aT) (E : forall T : list aT -> Type, (forall s1 s2 s3 : list aT, T (s1 ++ s2 ++ s3) -> T (s2 ++ s1 ++ s3)) -> T s -> T t) : perm_eq (pmap f s) (pmap f t). Proof. elim/E: (t). Admitted. Lemma test2 (a b : nat) : a = b -> b = 1. Proof. elim. match goal with |- a = 1 => idtac end. Admitted. rocq-9.2.0/test-suite/ssr/elim_pattern.v000066400000000000000000000023741516144147600202740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* _. match goal with |- (x == x) = true => myadmit end. match goal with |- (x == x) = false => myadmit end. Qed. Lemma test1 x : (x == x) = (x + x.+1 == 2 * x + 1). elim: (x in RHS). match goal with |- (x == x) = _ => myadmit end. match goal with |- forall n, (x == x) = _ -> (x == x) = _ => myadmit end. Qed. rocq-9.2.0/test-suite/ssr/first_n.v000066400000000000000000000017221516144147600172510ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (bool -> False -> True -> True) -> True. move=> F; let w := constr:(2) in apply; last w first. - by apply: F. - by apply: I. - by apply: true. Qed. rocq-9.2.0/test-suite/ssr/gen_have.v000066400000000000000000000124121516144147600173570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop. Lemma clear_test (b1 b2 : bool) : b2 = b2. Proof. (* wlog gH : (b3 := b2) / b2 = b3. myadmit. *) gen have {b1} H, gH : (b3 := b2) (w := erefl 3) / b2 = b3. myadmit. Fail exact (H b1). exact (H b2 (erefl _)). Qed. Lemma test1 n (ngt0 : 0 < n) : P n. gen have lt2le, /andP[H1 H2] : n ngt0 / (0 <= n) && (n != 0). match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end. Check (lt2le : forall n : nat, 0 < n -> (0 <= n) && (n != 0)). Check (H1 : 0 <= n). Check (H2 : n != 0). myadmit. Qed. Lemma test2 n (ngt0 : 0 < n) : P n. gen have _, /andP[H1 H2] : n ngt0 / (0 <= n) && (n != 0). match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end. lazymatch goal with | lt2le : forall n : nat, is_true(0 < n) -> is_true((0 <= n) && (n != 0)) |- _ => fail "not cleared" | _ => idtac end. Check (H1 : 0 <= n). Check (H2 : n != 0). myadmit. Qed. Lemma test3 n (ngt0 : 0 < n) : P n. gen have H : n ngt0 / (0 <= n) && (n != 0). match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end. Check (H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)). myadmit. Qed. Lemma test4 n (ngt0 : 0 < n) : P n. gen have : n ngt0 / (0 <= n) && (n != 0). match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end. move=> H. Check(H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)). myadmit. Qed. Lemma test4bis n (ngt0 : 0 < n) : P n. wlog suff : n ngt0 / (0 <= n) && (n != 0); last first. match goal with |- is_true((0 <= n) && (n != 0)) => myadmit end. move=> H. Check(H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)). myadmit. Qed. Lemma test5 n (ngt0 : 0 < n) : P n. Fail gen have : / (0 <= n) && (n != 0). Abort. Lemma test6 n (ngt0 : 0 < n) : P n. gen have : n ngt0 / (0 <= n) && (n != 0) by myadmit. Abort. Lemma test7 n (ngt0 : 0 < n) : P n. Fail gen have : n / (0 <= n) && (n != 0). Abort. Lemma test3wlog2 n (ngt0 : 0 < n) : P n. gen have H : (m := n) ngt0 / (0 <= m) && (m != 0). match goal with ngt0 : is_true(0 < m) |- is_true((0 <= m) && (m != 0)) => myadmit end. Check (H : forall n : nat, 0 < n -> (0 <= n) && (n != 0)). myadmit. Qed. Lemma test3wlog3 n (ngt0 : 0 < n) : P n. gen have H : {n} (m := n) (n := 0) ngt0 / (0 <= m) && (m != n). match goal with ngt0 : is_true(n < m) |- is_true((0 <= m) && (m != n)) => myadmit end. Check (H : forall m n : nat, n < m -> (0 <= m) && (m != n)). myadmit. Qed. Lemma testw1 n (ngt0 : 0 < n) : n <= 0. wlog H : (z := 0) (m := n) ngt0 / m != 0. match goal with |- (forall z m, is_true(z < m) -> is_true(m != 0) -> is_true(m <= z)) -> is_true(n <= 0) => myadmit end. Check(n : nat). Check(m : nat). Check(z : nat). Check(ngt0 : z < m). Check(H : m != 0). myadmit. Qed. Lemma testw2 n (ngt0 : 0 < n) : n <= 0. wlog H : (m := n) (z := (X in n <= X)) ngt0 / m != z. match goal with |- (forall m z : nat, is_true(0 < m) -> is_true(m != z) -> is_true(m <= z)) -> is_true(n <= 0) => idtac end. Restart. wlog H : (m := n) (one := (X in X <= _)) ngt0 / m != one. match goal with |- (forall m one : nat, is_true(one <= m) -> is_true(m != one) -> is_true(m <= 0)) -> is_true(n <= 0) => idtac end. Restart. wlog H : {n} (m := n) (z := (X in _ <= X)) ngt0 / m != z. match goal with |- (forall m z : nat, is_true(0 < z) -> is_true(m != z) -> is_true(m <= 0)) -> is_true(n <= 0) => idtac end. myadmit. Fail Check n. myadmit. Qed. Section Test. Variable x : nat. Definition addx y := y + x. Lemma testw3 (m n : nat) (ngt0 : 0 < n) : n <= addx x. wlog H : (n0 := n) (y := x) (@twoy := (id _ as X in _ <= X)) / twoy = 2 * y. myadmit. myadmit. Qed. Definition twox := x + x. Definition bis := twox. Lemma testw3x n (ngt0 : 0 < n) : n + x <= twox. wlog H : (y := x) (@twoy := (X in _ <= X)) / twoy = 2 * y. match goal with |- (forall y : nat, let twoy := y + y in twoy = 2 * y -> is_true(n + y <= twoy)) -> is_true(n + x <= twox) => myadmit end. Restart. wlog H : (y := x) (@twoy := (id _ as X in _ <= X)) / twoy = 2 * y. match goal with |- (forall y : nat, let twoy := twox in twoy = 2 * y -> is_true(n + y <= twoy)) -> is_true(n + x <= twox) => myadmit end. myadmit. Qed. End Test. Lemma test_in n k (def_k : k = 0) (ngtk : k < n) : P n. rewrite -(add0n n) in {def_k k ngtk} (m := k) (def_m := def_k) (ngtm := ngtk). rewrite def_m add0n in {ngtm} (e := erefl 0 ) (ngt0 := ngtm) => {def_m}. myadmit. Qed. rocq-9.2.0/test-suite/ssr/gen_pattern.v000066400000000000000000000026571516144147600201230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* idtac end. Admitted. Lemma bar x y : x + x.+1 = x.+1 + y. move E: ((x.+1 in y)) => w. match goal with |- x + x.+1 = w => rewrite -{w}E end. move E: (x.+1 in y)%myscope => w. match goal with |- x + x.+1 = w => rewrite -{w}E end. move E: ((x + y).+1 as RHS) => w. match goal with |- x + x.+1 = w => rewrite -{}E -addSn end. Admitted. rocq-9.2.0/test-suite/ssr/have_TC.v000066400000000000000000000030661516144147600171210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* _. exact I. Qed. Set SsrHave NoTCResolution. Lemma a' : True. set toto := bar _ 8. have titi : bar _ 5. Fail reflexivity. by myadmit. have titi2 : bar _ 5 := . Fail reflexivity. by myadmit. have totoc (H : bar _ 5) : 3 = 3 := eq_refl. move/totoc: nat => _. exact I. Qed. Unset SsrHave NoTCResolution. #[export] Instance test : foo bool. Proof. have : foo nat. Abort. rocq-9.2.0/test-suite/ssr/have_transp.v000066400000000000000000000031171516144147600201170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* = 0. Proof. have [:s1] @h m : 'I_(n+m).+1. apply: Sub 0 _. abstract: s1 m. by auto. cut (forall m, 0 < (n+m).+1); last assumption. rewrite [_ 1 _]/= in s1 h *. by []. Qed. Lemma test2 n : n >= 0. Proof. have [:s1] @h m : 'I_(n+m).+1 := Sub 0 (s1 m). move=> m; reflexivity. cut (forall m, 0 < (n+m).+1); last assumption. by []. Qed. Lemma test3 n : n >= 0. Proof. Fail have [:s1] @h m : 'I_(n+m).+1 by apply: (Sub 0 (s1 m)); auto. have [:s1] @h m : 'I_(n+m).+1 by apply: (Sub 0); abstract: s1 m; auto. cut (forall m, 0 < (n+m).+1); last assumption. by []. Qed. Lemma test4 n : n >= 0. Proof. have @h m : 'I_(n+m).+1 by apply: (Sub 0); abstract auto. by []. Qed. Lemma test5 : True. Proof. have @t : nat := 3. have : t = 3 by []. by []. Qed. rocq-9.2.0/test-suite/ssr/have_view_idiom.v000066400000000000000000000016261516144147600207460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* //] /= : true && (a && b) := pab. Qed. rocq-9.2.0/test-suite/ssr/havesuff.v000066400000000000000000000045451516144147600174220ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* G) -> P -> G. Proof. move=> pg p. have suff {pg} H : P. match goal with |- P -> G => move=> _; exact: pg p | _ => fail end. match goal with H : P -> G |- G => exact: H p | _ => fail end. Qed. Lemma test2 : (P -> G) -> P -> G. Proof. move=> pg p. have suffices {pg} H : P. match goal with |- P -> G => move=> _; exact: pg p | _ => fail end. match goal with H : P -> G |- G => exact: H p | _ => fail end. Qed. Lemma test3 : (P -> G) -> P -> G. Proof. move=> pg p. suff have {pg} H : P. match goal with H : P |- G => exact: pg H | _ => fail end. match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end. Qed. Lemma test4 : (P -> G) -> P -> G. Proof. move=> pg p. suffices have {pg} H: P. match goal with H : P |- G => exact: pg H | _ => fail end. match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end. Qed. (* Lemma test5 : (P -> G) -> P -> G. Proof. move=> pg p. suff have {pg} H : P := pg H. match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end. Qed. *) (* Lemma test6 : (P -> G) -> P -> G. Proof. move=> pg p. suff have {pg} H := pg H. match goal with |- (P -> G) -> G => move=> H; exact: H p | _ => fail end. Qed. *) Lemma test7 : (P -> G) -> P -> G. Proof. move=> pg p. have suff {pg} H : P := pg. match goal with H : P -> G |- G => exact: H p | _ => fail end. Qed. Lemma test8 : (P -> G) -> P -> G. Proof. move=> pg p. have suff {pg} H := pg. match goal with H : P -> G |- G => exact: H p | _ => fail end. Qed. Goal forall x y : bool, x = y -> x = y. move=> x y E. by have {x E} -> : x = y by []. Qed. rocq-9.2.0/test-suite/ssr/if_isnt.v000066400000000000000000000017541516144147600172450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop) := forall x, P x. Axiom P : T -> T -> Prop. Lemma foo : C (fun x => forall y, let z := x in P y x). move=> a b. match goal with |- (let y := _ in _) => idtac end. Admitted. rocq-9.2.0/test-suite/ssr/intro_noop.v000066400000000000000000000026321516144147600177740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool -> bool. Proof. by []. Qed. Reserved Notation " a -/ b " (at level 1). Reserved Notation " a -// b " (at level 1). Reserved Notation " a -/= b " (at level 1). Reserved Notation " a -//= b " (at level 1). Lemma test : forall a b c, a || b || c. Proof. move=> ---a--- - -/=- -//- -/=- -//=- b [|-]. move: {-}a => /v/v-H; have _ := H I I. Fail move: {-}a {H} => /v-/v-H. have - -> : a = (id a) by []. have --> : a = (id a) by []. have - - _ : a = (id a) by []. have -{1}-> : a = (id a) by []. by myadmit. move: a. case: b => -[] //. by myadmit. Qed. rocq-9.2.0/test-suite/ssr/ipat_apply.v000066400000000000000000000002571516144147600177510ustar00rootroot00000000000000Require Import ssreflect. Section Apply. Variable P : nat -> Prop. Lemma test_apply A B : forall (f : A -> B) (a : A), B. Proof. move=> /[apply] b. exact. Qed. End Apply. rocq-9.2.0/test-suite/ssr/ipat_clear_if_id.v000066400000000000000000000010271516144147600210400ustar00rootroot00000000000000Require Import ssreflect. Axiom v1 : nat -> bool. Section Foo. Variable v2 : nat -> bool. Lemma test (v3 : nat -> bool) (v4 : bool -> bool) (v5 : bool -> bool) : nat -> nat -> nat -> nat -> True. Proof. Set Debug Ssreflect. move=> {}/v1 b1 {}/v2 b2 {}/v3 b3 {}/v2/v4/v5 b4. Check b1 : bool. Check b2 : bool. Check b3 : bool. Check b4 : bool. Fail Check v3. Fail Check v4. Fail Check v5. Check v2 : nat -> bool. by []. Qed. Lemma test2 (v : True <-> False) : True -> False. Proof. move=> {}/v. Fail Check v. by []. Qed. End Foo. rocq-9.2.0/test-suite/ssr/ipat_dup.v000066400000000000000000000010121516144147600174020ustar00rootroot00000000000000Require Import ssreflect. Section Dup. Section withP. Variable P : nat -> Prop. Lemma test_dup1 : forall n : nat, P n. Proof. move=> /[dup] m n; suff: P n by []. Abort. Lemma test_dup2 : let n := 1 in False. Proof. move=> /[dup] m n; have : m = n := eq_refl. Abort. End withP. Lemma test_dup_plus P Q : P -> Q -> False. Proof. move=> + /[dup] q. suff: P -> Q -> False by []. Abort. Lemma test_dup_plus2 P : P -> let x := 0 in False. Proof. move=> + /[dup] y. suff: P -> let x := 0 in False by []. Abort. End Dup. rocq-9.2.0/test-suite/ssr/ipat_fast_any.v000066400000000000000000000006601516144147600204260ustar00rootroot00000000000000Require Import ssreflect. Goal forall y x : nat, x = y -> x = x. Proof. move=> + > ->. match goal with |- forall y, y = y => by [] end. Qed. Goal forall y x : nat, le x y -> x = y. Proof. move=> > [|]. by []. match goal with |- forall a, _ <= a -> _ = S a => admit end. Admitted. Goal forall y x : nat, le x y -> x = y. Proof. move=> y x. case E: x => >. admit. match goal with |- S _ <= y -> S _ = y => admit end. Admitted. rocq-9.2.0/test-suite/ssr/ipat_fastid.v000066400000000000000000000015731516144147600201000ustar00rootroot00000000000000Require Import ssreflect. Axiom odd : nat -> Prop. Lemma simple : forall x, 3 <= x -> forall y, odd (y+x) -> x = y -> True. Proof. move=> >x_ge_3 >xy_odd. lazymatch goal with | |- ?x = ?y -> True => done end. Qed. Lemma simple2 : forall x, 3 <= x -> forall y, odd (y+x) -> x = y -> True. Proof. move=> >; move=>x_ge_3; move=> >; move=>xy_odd. lazymatch goal with | |- ?x = ?y -> True => done end. Qed. Definition stuff x := 3 <= x -> forall y, odd (y+x) -> x = y -> True. Lemma harder : forall x, stuff x. Proof. move=> >x_ge_3 >xy_odd. lazymatch goal with | |- ?x = ?y -> True => done end. Qed. Lemma harder2 : forall x, stuff x. Proof. move=> >; move=>x_ge_3;move=> >; move=>xy_odd. lazymatch goal with | |- ?x = ?y -> True => done end. Qed. Lemma homotop : forall x : nat, forall e : x = x, e = e -> True. Proof. move=> >eq_ee. lazymatch goal with | |- True => done end. Qed. rocq-9.2.0/test-suite/ssr/ipat_replace.v000066400000000000000000000003431516144147600202330ustar00rootroot00000000000000Require 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. rocq-9.2.0/test-suite/ssr/ipat_seed.v000066400000000000000000000022271516144147600175430ustar00rootroot00000000000000Require Import ssreflect. Section foo. Variable A : Type. Record bar (X : Type) := mk_bar { a : X * A; b : A; c := (a,7); _ : X; _ : X }. Inductive baz (X : Type) (Y : Type) : nat -> Type := | K1 x (e : 0=1) (f := 3) of x=x:>X : baz X Y O | K2 n of n=n & baz X nat 0 : baz X Y (n+1). Axiom Q : nat -> Prop. Axiom Qx : forall x, Q x. Axiom my_ind : forall P : nat -> Prop, P O -> (forall n m (w : P n /\ P m), P (n+m)) -> forall w, P w. Lemma test x : bar nat -> baz nat nat x -> forall n : nat, Q n. Proof. (* record *) move => [^~ _ccc ]. Check (refl_equal _ : c_ccc = (a_ccc, 7)). (* inductive *) move=> [^ xxx_ ]. Check (refl_equal _ : xxx_f = 3). by []. Check (refl_equal _ : xxx_n = xxx_n). (* eliminator *) elim/my_ind => [^ wow_ ]. exact: Qx 0. Check (wow_w : Q wow_n /\ Q wow_m). exact: Qx (wow_n + wow_m). Qed. Arguments mk_bar A x y z w : rename. Arguments K1 A B a b c : rename. Lemma test2 x : bar nat -> baz nat nat x -> forall n : nat, Q n. Proof. move=> [^~ _ccc ]. Check (refl_equal _ : c_ccc = (x_ccc, 7)). move=> [^ xxx_ ]. Check (refl_equal _ : xxx_f = 3). by []. Check (refl_equal _ : xxx_n = xxx_n). Abort. End foo. rocq-9.2.0/test-suite/ssr/ipat_swap.v000066400000000000000000000011451516144147600175730ustar00rootroot00000000000000Require Import ssreflect. Section Swap. Definition P n := match n with 1 => true | _ => false end. Lemma test_swap1 : forall (n : nat) (b : bool), P n = b. Proof. move=> /[swap] b n; suff: P n = b by []. Abort. Lemma test_swap2 : let n := 1 in let b := true in False. Proof. move=> /[swap] b n; have : P n = b := eq_refl. Abort. Lemma test_swap_plus P Q R : P -> Q -> R -> False. Proof. move=> + /[swap]. suff: P -> R -> Q -> False by []. Abort. Lemma test_swap_plus2 P : P -> let x := 0 in let y := 1 in False. Proof. move=> + /[swap]. suff: P -> let y := 1 in let x := 0 in False by []. Abort. End Swap. rocq-9.2.0/test-suite/ssr/ipat_tac.v000066400000000000000000000015071516144147600173720ustar00rootroot00000000000000Require Import ssreflect. Ltac fancy := case; last first. Notation fancy := (ltac:( fancy )). Ltac replicate n := let what := fresh "_replicate_" in move=> what; do n! [ have := what ]; clear what. Notation replicate n := (ltac:( replicate n )). Lemma foo x (w : nat) (J : bool -> nat -> nat) : exists y, x=0+y. Proof. move: (w) => /ltac:(idtac) _. move: w => /(replicate 6) w1 w2 w3 w4 w5 w6. move: w1 => /J/fancy [w'||];last exact: false. move: w' => /J/fancy[w''||]; last exact: false. by exists x. by exists x. by exists x. Qed. Ltac unfld what := rewrite /what. Notation "% n" := (ltac:( unfld n )) (at level 1) : ssripat_scope. Notation "% n" := n : nat_scope. Open Scope nat_scope. Definition def := 4. Lemma test : True -> def = 4. Proof. move=> _ /(% def). match goal with |- 4 = 4 => reflexivity end. Qed. rocq-9.2.0/test-suite/ssr/ipat_tmp.v000066400000000000000000000010511516144147600174150ustar00rootroot00000000000000Require Import ssreflect ssrbool. Axiom eqn : nat -> nat -> bool. Infix "==" := eqn (at level 40). Axiom eqP : forall x y : nat, reflect (x = y) (x == y). Lemma test1 : forall x y : nat, x = y -> forall z : nat, y == z -> x = z. Proof. by move=> x y + z /eqP <-; apply. Qed. Lemma test2 : forall (x y : nat) (e : x = y), e = e -> x = y. Proof. move=> + y + _ => x def_x; exact: (def_x : x = y). Qed. Lemma test3 : forall x y : nat, x = y -> forall z : nat, y == z -> x = z. Proof. move=> ++++ /eqP <- => x y e z; exact: e. Qed. rocq-9.2.0/test-suite/ssr/ipatalternation.v000066400000000000000000000016531516144147600210060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop -> Prop -> Prop -> Prop -> True = False -> Prop -> True \/ True. by move=> A /= /= /= B C {A} {B} ? _ {C} {1}-> *; right. Qed. rocq-9.2.0/test-suite/ssr/ltac_have.v000066400000000000000000000025341516144147600175350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* H. Ltac subst2 H := rewrite addnC in H. Goal ( forall a b: nat, b+a = 0 -> b+a=0). Proof. move=> a b hyp. subst1 hyp. subst2 hyp. done. Qed. rocq-9.2.0/test-suite/ssr/misc_extended.v000066400000000000000000000043121516144147600204160ustar00rootroot00000000000000Require Import ssreflect. (* Require Import List. *) Lemma test_elim_pattern_1 : forall A (l:list A), app l nil = l. Proof. intros A. elim/list_ind => [^~ 1 ]. by []. match goal with |- app (cons a1 l1) nil = cons a1 l1 => idtac end. Abort. Lemma test_elim_pattern_2 : forall A (l:list A), app l nil = l. Proof. intros. elim: l => [^~ 1 ]. by []. match goal with |- app (cons a1 l1) nil = cons a1 l1 => idtac end. Abort. Lemma test_elim_pattern_3 : forall A (l:list A), app l nil = l. Proof. intros. elim: l => [ | x l' IH ]. by []. match goal with |- app (cons x l') nil = cons x l' => idtac end. Abort. Generalizable Variables A. Class Inhab (A:Type) : Type := { arbitrary : A }. Lemma test_intro_typeclass_1 : forall A `{Inhab A} (l1 l2:list A), l2 = nil -> app l1 l2 = l1. Proof. move =>> H. match goal with |- _ = _ => idtac end. Abort. Lemma test_intro_typeclass_2 : forall A `{Inhab A} (x:A), x = arbitrary -> x = arbitrary. Proof. move =>> H. match goal with |- _ = _ => idtac end. Abort. Lemma test_intro_temporary_1 : forall A (l1 l2:list A), l2 = nil -> app l1 l2 = l1. Proof. move => A + l2. match goal with |- forall l1, l2 = nil -> app l1 l2 = l1 => idtac end. Abort. Lemma test_intro_temporary_2 : forall A `{Inhab A} (l1 l2:list A), l2 = nil -> app l1 l2 = l1. Proof. move => > E. match goal with |- _ = _ => idtac end. Abort. Lemma test_dispatch : (forall x:nat, x= x )/\ (forall y:nat, y = y). Proof. intros. split => [ a | b ]. match goal with |- a = a => by [] end. match goal with |- b = b => by [] end. Abort. Lemma test_tactics_as_view_1 : forall A (l1:list A), app nil l1 = l1. Proof. move => /ltac:(simpl). Abort. Lemma test_tactics_as_view_2 : forall A, (forall (l1:list A), app nil l1 = l1) /\ (app nil nil = @nil A). Proof. move => A. (* TODO: I want to do [split =>.] as a temporary step in setting up my script, but this syntax does not seem to be supported. Can't we have an empty ipat? Note that I can do [split => [ | ]]*) split => [| /ltac:(simpl)]. Abort. Notation "%%" := (ltac:(simpl)) (only parsing) : ssripat_scope. Lemma test_tactics_as_view_3 : forall A, (forall (l1:list A), app nil l1 = l1) /\ (app nil nil = @nil A). Proof. move => /ltac:(split) [ | /%% ]. Abort. rocq-9.2.0/test-suite/ssr/misc_tc.v000066400000000000000000000020551516144147600172260ustar00rootroot00000000000000Require Import ssreflect. Generalizable Variables A B. Class Inhab (A:Type) : Type := { arbitrary : A }. Lemma test_intro_typeclass_1 : forall A `{Inhab A} (x:A), x = arbitrary -> x = arbitrary. Proof. move =>> H. (* introduces [H:x=arbitrary] because first non dependent hypothesis *) Abort. Lemma test_intro_typeclass_2 : forall A `{Inhab A} (l1 l2:list A), l2 = nil -> app l1 l2 = l1. Proof. move =>> H. (* introduces [Inhab A] automatically because it is a typeclass instance *) Abort. Lemma test_intro_typeclass_3 : forall `{Inhab A, Inhab B} (x:A) (y:B), True -> x = x. Proof. (* Above types [A] and [B] are implicitly quantified *) move =>> y H. (* introduces the two typeclass instances automatically *) Abort. Class Foo `{Inhab A} : Type := { foo : A }. Lemma test_intro_typeclass_4 : forall `{Foo A}, True -> True. Proof. (* Above, [A] and [{Inhab A}] are implicitly quantified *) move =>> H. (* introduces [A] and [Inhab A] because they are dependently used, and introduce [Foo A] automatically because it is an instance. *) Abort. rocq-9.2.0/test-suite/ssr/move_after.v000066400000000000000000000015261516144147600177360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* True -> True. move=> H1 H2. move H1 after H2. Admitted. rocq-9.2.0/test-suite/ssr/multiview.v000066400000000000000000000037031516144147600176330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* m <= n -> m <= p. by move=> m n p le_n_p /leq_trans; apply. Undo 1. by move=> m n p le_n_p /leq_trans /(_ le_n_p) le_m_p; exact: le_m_p. Undo 1. by move=> m n p le_n_p /leq_trans ->. Qed. Goal forall P Q X : Prop, Q -> (True -> X -> Q = P) -> X -> P. by move=> P Q X q V /V <-. Qed. Lemma test0: forall a b, a && a && b -> b. by move=> a b; repeat move=> /andP []; move=> *. Qed. Lemma test1 : forall a b, a && b -> b. by move=> a b /andP /andP /andP [] //. Qed. Lemma test2 : forall a b, a && b -> b. by move=> a b /andP /andP /(@andP a) [] //. Qed. Lemma test3 : forall a b, a && (b && b) -> b. by move=> a b /andP [_ /andP [_ //]]. Qed. Lemma test4: forall a b, a && b = b && a. by move=> a b; apply/andP/andP=> ?; apply/andP/andP/andP; rewrite andbC; apply/andP. Qed. Lemma test5: forall C I A O, (True -> O) -> (O -> A) -> (True -> A -> I) -> (I -> C) -> C. by move=> c i a o O A I C; apply/C/I/A/O. Qed. Lemma test6: forall A B, (A -> B) -> A -> B. move=> A B A_to_B a; move/A_to_B in a; exact: a. Qed. Lemma test7: forall A B, (A -> B) -> A -> B. move=> A B A_to_B a; apply A_to_B in a; exact: a. Qed. rocq-9.2.0/test-suite/ssr/nonPropType.v000066400000000000000000000011711516144147600201000ustar00rootroot00000000000000Require Import ssreflect. (** Test the nonPropType interface and its application to prevent unwanted instantiations in views. **) Lemma raw_flip {T} (x y : T) : x = y -> y = x. Proof. by []. Qed. Lemma flip {T : nonPropType} (x y : T) : x = y -> y = x. Proof. by []. Qed. Lemma testSet : true = false -> True. Proof. Fail move/raw_flip. have flip_true := @flip _ true. (* flip_true : forall y : notProp bool, x = y -> y = x *) simpl in flip_true. (* flip_true : forall y : bool, x = y -> y = x *) by move/flip. Qed. Lemma override (t1 t2 : True) : t1 = t2 -> True. Proof. Fail move/flip. by move/(@flip (notProp True)). Qed. rocq-9.2.0/test-suite/ssr/noting_to_inject.v000066400000000000000000000003031516144147600211330ustar00rootroot00000000000000Require Import ssreflect ssrfun ssrbool. Goal forall b : bool, b -> False. Set Warnings "+spurious-ssr-injection". Fail move=> b []. Set Warnings "-spurious-ssr-injection". move=> b []. Abort. rocq-9.2.0/test-suite/ssr/occarrow.v000066400000000000000000000021271516144147600174240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* m * m + n * n = n * n + n * n. move=> n m E; have [{2}-> _] : n * n = m * n /\ True by move: E => {1}<-. by move: E => {3}->. Qed. Lemma test2 : forall n m : nat, True /\ (n = m -> n * n = n * m). by move=> n m; constructor=> [|{2}->]. Qed. rocq-9.2.0/test-suite/ssr/over.v000066400000000000000000000027241516144147600165630ustar00rootroot00000000000000Require Import ssreflect. Axiom daemon : False. Ltac myadmit := case: daemon. (** Testing over for the 1-var case *) Lemma test_over_1_1 : False. intros. evar (I : Type); evar (R : Type); evar (x2 : I -> R). assert (H : forall i : nat, i + 2 * i - i = x2 i). intros i. unfold x2 in *; clear x2; unfold R in *; clear R; unfold I in *; clear I. apply Under_rel_from_rel. Fail done. over. myadmit. Qed. Lemma test_over_1_2 : False. intros. evar (I : Type); evar (R : Type); evar (x2 : I -> R). assert (H : forall i : nat, i + 2 * i - i = x2 i). intros i. unfold x2 in *; clear x2; unfold R in *; clear R; unfold I in *; clear I. apply Under_rel_from_rel. Fail done. by rewrite over. myadmit. Qed. (** Testing over for the 2-var case *) Lemma test_over_2_1 : False. intros. evar (I : Type); evar (J : Type); evar (R : Type); evar (x2 : I -> J -> R). assert (H : forall i j, i + 2 * j - i = x2 i j). intros i j. unfold x2 in *; clear x2; unfold R in *; clear R; unfold J in *; clear J; unfold I in *; clear I. apply Under_rel_from_rel. Fail done. over. myadmit. Qed. Lemma test_over_2_2 : False. intros. evar (I : Type); evar (J : Type); evar (R : Type); evar (x2 : I -> J -> R). assert (H : forall i j : nat, i + 2 * j - i = x2 i j). intros i j. unfold x2 in *; clear x2; unfold R in *; clear R; unfold J in *; clear J; unfold I in *; clear I. apply Under_rel_from_rel. Fail done. rewrite over. done. myadmit. Qed. rocq-9.2.0/test-suite/ssr/patnoX.v000066400000000000000000000015711516144147600170600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* x. Fail (rewrite [X in _ && _]andbT). Abort. rocq-9.2.0/test-suite/ssr/pattern.v000066400000000000000000000022461516144147600172640ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* True -> 3 = 7) : 28 = 3 * 4. Proof. at [ X in X * 4 ] ltac:(fun place => rewrite -> H in place). - reflexivity. - trivial. - trivial. Qed. rocq-9.2.0/test-suite/ssr/predRewrite.v000066400000000000000000000022661516144147600201050ustar00rootroot00000000000000Require Import ssreflect ssrfun ssrbool. (** Test the various idioms that control rewriting in boolean predicate. **) Definition simpl_P := [pred a | ~~ a]. Definition nosimpl_P : pred bool := [pred a | ~~ a]. Definition coll_P : collective_pred bool := [pred a | ~~ a]. Definition appl_P : applicative_pred bool := [pred a | ~~ a]. Definition can_appl_P : pred bool := [pred a | ~~ a]. Canonical register_can_appl_P := ApplicativePred can_appl_P. Ltac see_neg := (let x := fresh "x" in set x := {-}(~~ _); clear x). Lemma test_pred_rewrite (f := false) : True. Proof. have _: f \in simpl_P by rewrite inE; see_neg. have _ a: simpl_P (a && f) by simpl; see_neg; rewrite andbF. have _ a: simpl_P (a && f) by rewrite inE; see_neg; rewrite andbF. have _: f \in nosimpl_P by rewrite inE; see_neg. have _: nosimpl_P f. simpl. Fail see_neg. Fail rewrite inE. done. have _: f \in coll_P. Fail rewrite inE. by rewrite in_collective; see_neg. have _: f \in appl_P. rewrite inE. Fail see_neg. Fail rewrite inE. simpl. Fail see_neg. Fail rewrite app_predE. done. have _: f \in can_appl_P. rewrite inE. Fail see_neg. Fail rewrite inE. simpl. Fail see_neg. by rewrite app_predE in_simpl; see_neg. done. Qed. rocq-9.2.0/test-suite/ssr/primproj.v000066400000000000000000000063571516144147600174600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A. Parameter e : @foo_car = alias. Goal foo_car _ bar = alias _ bar. Proof. (* Coq equally fails *) Fail rewrite -> e. Fail rewrite e at 1. Fail setoid_rewrite e. Fail setoid_rewrite e at 1. Set Keyed Unification. Fail rewrite -> e. Fail rewrite e at 1. Fail setoid_rewrite e. Fail setoid_rewrite e at 1. Admitted. End CoqBug. (* ----------------------------------------------- *) Require Import ssreflect. Set Primitive Projections. Module T1. Record foo A := Foo { foo_car : A }. Definition bar : foo _ := Foo nat 10. Goal foo_car _ bar = 10. Proof. match goal with | |- foo_car _ bar = 10 => idtac end. rewrite /foo_car. (* Fail match goal with | |- foo_car _ bar = 10 => idtac end. *) Admitted. End T1. Module T2. Record foo {A} := Foo { foo_car : A }. Definition bar : foo := Foo nat 10. Goal foo_car bar = 10. match goal with | |- foo_car bar = 10 => idtac end. rewrite /foo_car. (* Fail match goal with | |- foo_car bar = 10 => idtac end. *) Admitted. End T2. Module T3. Record foo {A} := Foo { foo_car : A }. Definition bar : foo := Foo nat 10. Goal foo_car bar = 10. Proof. rewrite -[foo_car _]/(id _). match goal with |- id _ = 10 => idtac end. Admitted. Goal foo_car bar = 10. Proof. set x := foo_car _. match goal with |- x = 10 => idtac end. Admitted. End T3. Module T4. Inductive seal {A} (f : A) := { unseal : A; seal_eq : unseal = f }. Arguments unseal {_ _} _. Arguments seal_eq {_ _} _. Record uPred : Type := IProp { uPred_holds :> Prop }. Definition uPred_or_def (P Q : uPred) : uPred := {| uPred_holds := P \/ Q |}. Definition uPred_or_aux : seal (@uPred_or_def). by eexists. Qed. Definition uPred_or := unseal uPred_or_aux. Definition uPred_or_eq: @uPred_or = @uPred_or_def := seal_eq uPred_or_aux. Lemma foobar (P1 P2 Q : uPred) : (P1 <-> P2) -> (uPred_or P1 Q) <-> (uPred_or P2 Q). Proof. rewrite uPred_or_eq. (* This fails. *) Admitted. End T4. Module DesignFlaw. Record foo A := Foo { foo_car : A }. Definition bar : foo _ := Foo nat 10. Definition app (f : foo nat -> nat) x := f x. Goal app (foo_car _) bar = 10. Proof. unfold app. (* mkApp should produce a Proj *) Fail set x := (foo_car _ _). Admitted. End DesignFlaw. Module Bug. Record foo A := Foo { foo_car : A }. Definition bar : foo _ := Foo nat 10. Parameter alias : forall A, foo A -> A. Parameter e : @foo_car = alias. Goal foo_car _ bar = alias _ bar. Proof. Fail rewrite e. (* Issue: #86 *) Admitted. End Bug. rocq-9.2.0/test-suite/ssr/rew_FO.v000066400000000000000000000015741516144147600167730ustar00rootroot00000000000000From Corelib Require Import ssreflect. Axiom R : Type. Axiom op : nat -> R -> R -> R. Axiom lemma : forall n x y z, op n (op n x y) z = z. Arguments op {_} _ _. Goal forall a b c : R, @op (0+1) (@op 1 a b) c = @op 2 (@op 2 a b) c. intros a b c. Show. rewrite lemma. Show. match goal with | |- c = _ => idtac "ok" end. Abort. Record foo := F { f : nat }. Definition c := F (1 + 2). Goal (forall x, 1 + (1 + x) = 5) -> 1 + f c = 1 + (1 + 7) . Show. move->. Show. match goal with |- 5 = 1 + (1 + 7) => idtac "ok" end. Abort. Goal (forall x, 1 + (1 + x) = 5) -> 1 + f c = 1 + (1 + 7) . Show. Set SsrMatching LegacyFoUnif. move->. Unset SsrMatching LegacyFoUnif. Show. match goal with |- 1 + f c = 5 => idtac "ok" end. Abort. Goal (forall x, 1 + (S x) = 5) -> 1 + f c = 1 + (1 + 7) . Show. move->. Show. match goal with |- 1 + f c = 1 + 5 => idtac "ok" end. Abort. rocq-9.2.0/test-suite/ssr/rew_polyuniv.v000066400000000000000000000061231516144147600203470ustar00rootroot00000000000000From Corelib Require Import Setoid ssreflect. Set Default Proof Using "Type". Local Set Universe Polymorphism. (** Telescopes *) Inductive tele : Type := | TeleO : tele | TeleS {X} (binder : X -> tele) : tele. Arguments TeleS {_} _. (** The telescope version of Coq's function type *) Fixpoint tele_fun (TT : tele) (T : Type) : Type := match TT with | TeleO => T | TeleS b => forall x, tele_fun (b x) T end. Notation "TT -t> A" := (tele_fun TT A) (at level 99, A at level 200, right associativity). (** A sigma-like type for an "element" of a telescope, i.e. the data it takes to get a [T] from a [TT -t> T]. *) Inductive tele_arg : tele -> Type := | TargO : tele_arg TeleO (* the [x] is the only relevant data here *) | TargS {X} {binder} (x : X) : tele_arg (binder x) -> tele_arg (TeleS binder). Definition tele_app {TT : tele} {T} (f : TT -t> T) : tele_arg TT -> T := fun a => (fix rec {TT} (a : tele_arg TT) : (TT -t> T) -> T := match a in tele_arg TT return (TT -t> T) -> T with | TargO => fun t : T => t | TargS x a => fun f => rec a (f x) end) TT a f. Arguments tele_app {!_ _} _ !_ /. Coercion tele_arg : tele >-> Sortclass. Coercion tele_app : tele_fun >-> Funclass. (** Inversion lemma for [tele_arg] *) Lemma tele_arg_inv {TT : tele} (a : TT) : match TT as TT return TT -> Prop with | TeleO => fun a => a = TargO | TeleS f => fun a => exists x a', a = TargS x a' end a. Proof. induction a; eauto. Qed. Lemma tele_arg_O_inv (a : TeleO) : a = TargO. Proof. exact (tele_arg_inv a). Qed. Lemma tele_arg_S_inv {X} {f : X -> tele} (a : TeleS f) : exists x a', a = TargS x a'. Proof. exact (tele_arg_inv a). Qed. (** Operate below [tele_fun]s with argument telescope [TT]. *) Fixpoint tele_bind {U} {TT : tele} : (TT -> U) -> TT -t> U := match TT as TT return (TT -> U) -> TT -t> U with | TeleO => fun F => F TargO | @TeleS X b => fun (F : TeleS b -> U) (x : X) => (* b x -t> U *) tele_bind (fun a => F (TargS x a)) end. Arguments tele_bind {_ !_} _ /. (* Show that tele_app ∘ tele_bind is the identity. *) Lemma tele_app_bind {U} {TT : tele} (f : TT -> U) x : (tele_app (tele_bind f)) x = f x. Proof. induction TT as [|X b IH]; simpl in *. - rewrite (tele_arg_O_inv x). auto. - destruct (tele_arg_S_inv x) as [x' [a' ->]]. simpl. rewrite IH. auto. Qed. (** Notation-compatible telescope mapping *) (* This adds (tele_app ∘ tele_bind), which is an identity function, around every binder so that, after simplifying, this matches the way we typically write notations involving telescopes. *) Notation "'Ξ»..' x .. y , e" := (tele_app (tele_bind (fun x => .. (tele_app (tele_bind (fun y => e))) .. ))) (at level 200, x binder, y binder, right associativity, format "'[ ' 'Ξ»..' x .. y ']' , e"). (* The testcase *) Lemma test {TA TB : tele} {X} (Ξ±' Ξ²' Ξ³' : X -> Prop) (Ξ¦ : TA -> TB -> Prop) x' : (forall P Q, ((P /\ Q) = Q) * ((P -> Q) = Q)) -> forall a b, Ξ¦ a b = tele_bind (fun x : TA => tele_bind (fun y : TB => Ξ²' x' /\ (Ξ³' x' -> Ξ¦ x y))) a b. Proof. intros cheat a b. rewrite !tele_app_bind. by rewrite !cheat. Qed. rocq-9.2.0/test-suite/ssr/rewpatterns.v000066400000000000000000000127351516144147600201710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* nat), f (x + y).+1 = f (y + x.+1). by move=> x y f; rewrite [_.+1](addnC x.+1). Qed. Lemma test2 : forall x y f, x + y + f (y + x) + f (y + x) = x + y + f (y + x) + f (x + y). by move=> x y f; rewrite {2}[in f _]addnC. Qed. Lemma test2' : forall x y f, true && f (x * (y + x)) = true && f(x * (x + y)). by move=> x y f; rewrite [in f _](addnC y). Qed. Lemma test2'' : forall x y f, f (y + x) + f(y + x) + f(y + x) = f(x + y) + f(y + x) + f(x + y). by move=> x y f; rewrite {1 3}[in f _](addnC y). Qed. (* patterns catching bound vars not supported *) Lemma test2_1 : forall x y f, true && (let z := x in f (z * (y + x))) = true && f(x * (x + y)). by move=> x y f; rewrite [in f _](addnC x). (* put y when bound var will be OK *) Qed. Lemma test3 : forall x y f, x + f (x + y) (f (y + x) x) = x + f (x + y) (f (x + y) x). by move=> x y f; rewrite [in X in (f _ X)](addnC y). Qed. Lemma test3' : forall x y f, x = y -> x + f (x + x) x + f (x + x) x = x + f (x + y) x + f (y + x) x. by move=> x y f E; rewrite {2 3}[in X in (f X _)]E. Qed. Lemma test3'' : forall x y f, x = y -> x + f (x + y) x + f (x + y) x = x + f (x + y) x + f (y + y) x. by move=> x y f E; rewrite {2}[in X in (f X _)]E. Qed. Lemma test4 : forall x y f, x = y -> x + f (fun _ : nat => x + x) x + f (fun _ => x + x) x = x + f (fun _ => x + y) x + f (fun _ => y + x) x. by move=> x y f E; rewrite {2 3}[in X in (f X _)]E. Qed. Lemma test4' : forall x y f, x = y -> x + f (fun _ _ _ : nat => x + x) x = x + f (fun _ _ _ => x + y) x. by move=> x y f E; rewrite {2}[in X in (f X _)]E. Qed. Lemma test5 : forall x y f, x = y -> x + f (y + x) x + f (y + x) x = x + f (x + y) x + f (y + x) x. by move=> x y f E; rewrite {1}[X in (f X _)]addnC. Qed. Lemma test3''' : forall x y f, x = y -> x + f (x + y) x + f (x + y) (x + y) = x + f (x + y) x + f (y + y) (x + y). by move=> x y f E; rewrite {1}[in X in (f X X)]E. Qed. Lemma test3'''' : forall x y f, x = y -> x + f (x + y) x + f (x + y) (x + y) = x + f (x + y) x + f (y + y) (y + y). by move=> x y f E; rewrite [in X in (f X X)]E. Qed. Lemma test3x : forall x y f, y+y = x+y -> x + f (x + y) x + f (x + y) (x + y) = x + f (x + y) x + f (y + y) (y + y). by move=> x y f E; rewrite -[X in (f X X)]E. Qed. Lemma test6 : forall x y (f : nat -> nat), f (x + y).+1 = f (y.+1 + x). by move=> x y f; rewrite [(x + y) in X in (f X)]addnC. Qed. Lemma test7 : forall x y (f : nat -> nat), f (x + y).+1 = f (y + x.+1). by move=> x y f; rewrite [(x.+1 + y) as X in (f X)]addnC. Qed. Lemma manual x y z (f : nat -> nat -> nat) : (x + y).+1 + f (x.+1 + y) (z + (x + y).+1) = 0. Proof. rewrite [in f _]addSn. match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 => idtac end. rewrite -[X in _ = X]addn0. match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 + 0 => idtac end. rewrite -{2}[in X in _ = X](addn0 0). match goal with |- (x + y).+1 + f (x + y).+1 (z + (x + y).+1) = 0 + (0 + 0) => idtac end. rewrite [_.+1 in X in f _ X](addnC x.+1). match goal with |- (x + y).+1 + f (x + y).+1 (z + (y + x.+1)) = 0 + (0 + 0) => idtac end. rewrite [x.+1 + y as X in f X _]addnC. match goal with |- (x + y).+1 + f (y + x.+1) (z + (y + x.+1)) = 0 + (0 + 0) => idtac end. Admitted. Goal (exists x : 'I_3, x > 0). apply: (ex_intro _ (@Ordinal _ 2 _)). Admitted. Goal (forall y, 1 < y < 2 -> exists x : 'I_3, x > 0). move=> y; case/andP=> y_gt1 y_lt2; apply: (ex_intro _ (@Ordinal _ y _)). by apply: leq_trans y_lt2 _. by move=> y_lt3; apply: leq_trans _ y_gt1. Qed. Goal (forall x y : nat, forall P : nat -> Prop, x = y -> True). move=> x y P E. have: P x -> P y by suff: x = y by move=> ?; congr (P _). Admitted. Goal forall a : bool, a -> true && a || false && a. by move=> a ?; rewrite [true && _]/= [_ && a]/= orbC [_ || _]//=. Qed. Goal forall a : bool, a -> true && a || false && a. by move=> a ?; rewrite [X in X || _]/= [X in _ || X]/= orbC [false && a as X in X || _]//=. Qed. Parameter a : bool. Definition f x := x || a. Definition g x := f x. Goal a -> g false. by move=> Ha; rewrite [g _]/f orbC Ha. Qed. Goal a -> g false || g false. move=> Ha; rewrite {2}[g _]/f orbC Ha. match goal with |- (is_true (false || true || g false)) => done end. Qed. Goal a -> (a && a || true && a) && true. by move=> Ha; rewrite -[_ || _]/(g _) andbC /= Ha [g _]/f. Qed. Goal a -> (a || a) && true. by move=> Ha; rewrite -[in _ || _]/(f _) Ha andbC /f. Qed. rocq-9.2.0/test-suite/ssr/rewrite_illtyped.v000066400000000000000000000003041516144147600211670ustar00rootroot00000000000000From Corelib Require Import ssreflect Setoid. Structure SEProp := {prop_of : Prop; _ : prop_of <-> True}. Fact anomaly: forall P : SEProp, prop_of P. Proof. move=> [P E]. Fail rewrite E. Abort. rocq-9.2.0/test-suite/ssr/rewrtite_err_msg.v000066400000000000000000000017611516144147600211730ustar00rootroot00000000000000Require Import ssreflect ssrbool. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom finGroupType : Type. Axiom group : finGroupType -> Type. Axiom abelian : forall gT : finGroupType, group gT -> Prop. Arguments abelian {_} _. Axiom carrier : finGroupType -> Type. Coercion carrier : finGroupType >-> Sortclass. Axiom mem : forall gT : finGroupType, gT -> group gT -> Prop. Arguments mem {_} _ _. Axiom mul : forall gT : finGroupType, gT -> gT -> gT. Arguments mul {_} _ _. Definition centralised gT (G : group gT) (x : gT) := forall y, mul x y = mul y x. Arguments centralised {gT} _. Axiom b : bool. Axiom centsP : forall (gT : finGroupType) (A B : group gT), reflect (forall a, mem a A -> centralised B a) b. Arguments centsP {_ _ _}. Lemma commute_abelian (gT : finGroupType) (G : group gT) (G_abelian : abelian G) (g g' : gT) (gG : mem g G) (g'G : mem g' G) : mul g g' = mul g' g. Proof. Fail rewrite (centsP _). (* fails but without an anomaly *) Abort. rocq-9.2.0/test-suite/ssr/set_lamda.v000066400000000000000000000021531516144147600175350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* nat, f nat = 0). Proof. set (f:= fun _:Set =>0). by exists f. Qed. Goal (exists f: Set -> nat, f nat = 0). Proof. set f := (fun _:Set =>0). by exists f. Qed. rocq-9.2.0/test-suite/ssr/set_pattern.v000066400000000000000000000062521516144147600201400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* set t := (x in X in _ = X) end. Ltac T2 x := first [set t := (x in RHS)]. Ltac T3 x := first [set t := (x in Y in _ = Y)|idtac]. Ltac T4 x := set t := (x in RHS); idtac. Ltac T5 x := match goal with |- _ => set t := (x in RHS) | |- _ => idtac end. Require Import ssrbool TestSuite.ssr_mini_mathcomp. Open Scope nat_scope. Lemma foo x y : x.+1 = y + x.+1. set t := (_.+1 in RHS). match goal with |- x.+1 = y + t => rewrite /t {t} end. set t := (x in RHS). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end. set t := (x in _ = x). match goal with |- x.+1 = t => rewrite /t {t} end. set t := (x in X in _ = X). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end. set t := (x in RHS). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end. set t := (y + (1 + x) as X in _ = X). match goal with |- x.+1 = t => rewrite /t addSn add0n {t} end. set t := x.+1. match goal with |- t = y + t => rewrite /t {t} end. set t := (x).+1. match goal with |- t = y + t => rewrite /t {t} end. set t := ((x).+1 in X in _ = X). match goal with |- x.+1 = y + t => rewrite /t {t} end. set t := (x.+1 in RHS). match goal with |- x.+1 = y + t => rewrite /t {t} end. T1 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end. T2 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end. T3 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end. T4 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end. T5 (x.+1). match goal with |- x.+1 = y + t => rewrite /t {t} end. rewrite [RHS]addnC. match goal with |- x.+1 = x.+1 + y => rewrite -[RHS]addnC end. rewrite -[in RHS](@subnK 1 x.+1) //. match goal with |- x.+1 = y + (x.+1 - 1 + 1) => rewrite subnK // end. have H : x.+1 = y by myadmit. set t := _.+1 in H |- *. match goal with H : t = y |- t = y + t => rewrite /t {t} in H * end. set t := (_.+1 in X in _ + X) in H |- *. match goal with H : x.+1 = y |- x.+1 = y + t => rewrite /t {t} in H * end. set t := 0. match goal with t := 0 |- x.+1 = y + x.+1 => clear t end. set t := y + _. match goal with |- x.+1 = t => rewrite /t {t} end. set t : nat := 0. clear t. set t : nat := (x in RHS). match goal with |- x.+1 = y + t.+1 => rewrite /t {t} end. set t : nat := RHS. match goal with |- x.+1 = t => rewrite /t {t} end. (* set t := 0 + _. *) (* set t := (x).+1 in X in _ + X in H |-. *) (* set t := (x).+1 in X in _ = X.*) Admitted. rocq-9.2.0/test-suite/ssr/set_polyuniv.v000066400000000000000000000003331516144147600203420ustar00rootroot00000000000000From Corelib Require Import ssreflect. Set Default Proof Using "Type". Local Set Universe Polymorphism. Axiom foo : Type -> Prop. Lemma test : foo nat. Proof. set x := foo _. (* key @foo{i} matches @foo{j} *) Abort. rocq-9.2.0/test-suite/ssr/simpl_done.v000066400000000000000000000010431516144147600177320ustar00rootroot00000000000000Require Import ssreflect. Inductive lit : Set := | LitP : lit | LitL : lit . Inductive val : Set := | Val : lit -> val. Definition tyref := fun (vl : list val) => match vl with | cons (Val LitL) (cons (Val LitP) _) => False | _ => False end. (** Check that simplification and resolution are performed in the right order by "//=" when several goals are under focus. *) Goal exists vl1 : list val, cons (Val LitL) (cons (Val LitL) nil) = vl1 /\ (tyref vl1) . Proof. eexists (cons _ (cons _ _)). split =>//=. Fail progress simpl. Abort. rocq-9.2.0/test-suite/ssr/ssr_sProp.v000066400000000000000000000001671516144147600176010ustar00rootroot00000000000000Require Import ssreflect. Inductive sEmpty : SProp :=. Goal True. have h := (fun x : sEmpty => x). constructor. Qed. rocq-9.2.0/test-suite/ssr/ssrpattern.v000066400000000000000000000002371516144147600200120ustar00rootroot00000000000000Require Import ssrmatching. Goal forall n, match n with 0 => 0 | _ => 0 end = 0. Proof. intro n. ssrpattern (match _ with 0 => _ | S n' => _ end). Abort. rocq-9.2.0/test-suite/ssr/ssrsyntax2.v000066400000000000000000000015611516144147600177460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* id x = 0. Proof. Fail move=> _; reflexivity. Timeout 2 rewrite E => _; reflexivity. Qed. Definition P {A} (x : A) : Prop := x = x. Axiom V : forall A {f : foo A} (x:A), P x -> P (id x). Lemma test1 (x : nat) : P x -> P (id x). Proof. move=> px. Timeout 2 Fail move/V: px. Timeout 2 move/V : (px) => _. move/(V nat) : px => H; exact H. Qed. rocq-9.2.0/test-suite/ssr/tcfwd.v000066400000000000000000000003741516144147600167160ustar00rootroot00000000000000Require Import ssreflect. Axioms A B D : Type. Class C := {}. Axiom f : C -> A -> B. Axiom g : D -> C. Local Hint Extern 0 C => apply g;shelve : typeclass_instances. Lemma foo : A -> Type. Proof. move=> /f. (* Not_found *) intro;exact nat. Qed. rocq-9.2.0/test-suite/ssr/try_case.v000066400000000000000000000003551516144147600174170ustar00rootroot00000000000000From Corelib Require Import ssreflect. Axiom T : Type. Axiom R : T -> T -> Type. (** Check that internal exceptions are correctly caught in the monad *) Goal forall (a b : T) (Hab : R a b), True. Proof. intros. try (case: Hab). Abort. rocq-9.2.0/test-suite/ssr/typeof.v000066400000000000000000000016201516144147600171100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* [ x | ]; [ exact x | exact I ]. Qed. rocq-9.2.0/test-suite/ssr/under.v000066400000000000000000000267511516144147600167330ustar00rootroot00000000000000Require Import ssreflect. Require Import ssrbool TestSuite.ssr_mini_mathcomp. Global Unset SsrOldRewriteGoalsOrder. (* under : {occs}[patt]. under : {occs}[patt] by tac1. under : {occs}[patt] by [tac1 | ...]. *) Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Axiom daemon : False. Ltac myadmit := case: daemon. Module Mocks. (* Mock bigop.v definitions to test the behavior of under with bigops without requiring mathcomp *) Definition eqfun := fun (A B : Type) (f g : forall _ : B, A) => forall x : B, @eq A (f x) (g x). Section Defix. Variables (T : Type) (n : nat) (f : forall _ : T, T) (x : T). Fixpoint loop (m : nat) : T := match m return T with | O => x | S i => f (loop i) end. Definition iter := loop n. End Defix. Parameter eq_bigl : forall (R : Type) (idx : R) (op : forall (_ : R) (_ : R), R) (I : Type) (r : list I) (P1 P2 : pred I) (F : forall _ : I, R) (_ : @eqfun bool I P1 P2), @eq R (@bigop R I idx r (fun i : I => @BigBody R I i op (P1 i) (F i))) (@bigop R I idx r (fun i : I => @BigBody R I i op (P2 i) (F i))). Parameter eq_big : forall (R : Type) (idx : R) (op : forall (_ : R) (_ : R), R) (I : Type) (r : list I) (P1 P2 : pred I) (F1 F2 : forall _ : I, R) (_ : @eqfun bool I P1 P2) (_ : forall (i : I) (_ : is_true (P1 i)), @eq R (F1 i) (F2 i)), @eq R (@bigop R I idx r (fun i : I => @BigBody R I i op (P1 i) (F1 i))) (@bigop R I idx r (fun i : I => @BigBody R I i op (P2 i) (F2 i))). Parameter eq_bigr : forall (R : Type) (idx : R) (op : forall (_ : R) (_ : R), R) (I : Type) (r : list I) (P : pred I) (F1 F2 : forall _ : I, R) (_ : forall (i : I) (_ : is_true (P i)), @eq R (F1 i) (F2 i)), @eq R (@bigop R I idx r (fun i : I => @BigBody R I i op (P i) (F1 i))) (@bigop R I idx r (fun i : I => @BigBody R I i op (P i) (F2 i))). Parameter big_const_nat : forall (R : Type) (idx : R) (op : forall (_ : R) (_ : R), R) (m n : nat) (x : R), @eq R (@bigop R nat idx (index_iota m n) (fun i : nat => @BigBody R nat i op true x)) (@iter R (subn n m) (op x) idx). Delimit Scope N_scope with num. Delimit Scope nat_scope with N. Reserved Notation "\sum_ ( m <= i < n | P ) F" (at level 41, F at level 41, i, m, n at level 50, format "'[' \sum_ ( m <= i < n | P ) '/ ' F ']'"). Reserved Notation "\sum_ ( m <= i < n ) F" (at level 41, F at level 41, i, m, n at level 50, format "'[' \sum_ ( m <= i < n ) '/ ' F ']'"). Local Notation "+%N" := addn (at level 0, only parsing). Notation "\sum_ ( m <= i < n | P ) F" := (\big[+%N/0%N]_(m <= i < n | P%B) F%N) : (*nat_scope*) big_scope. Notation "\sum_ ( m <= i < n ) F" := (\big[+%N/0%N]_(m <= i < n) F%N) : (*nat_scope*) big_scope. Parameter iter_addn_0 : forall m n : nat, @eq nat (@iter nat n (addn m) O) (muln m n). End Mocks. Import Mocks. (*****************************************************************************) Lemma test_big_nested_1 (F G : nat -> nat) (m n : nat) : \sum_(0 <= i < m) \sum_(0 <= j < n | odd (j * 1)) (i + j) = \sum_(0 <= i < m) \sum_(0 <= j < n | odd j) (j + i). Proof. (* in interactive mode *) under eq_bigr => i Hi. under eq_big => [j|j Hj]. { rewrite muln1. over. } { rewrite addnC. over. } simpl. (* or: cbv beta. *) over. by []. Qed. Lemma test_big_nested_2 (F G : nat -> nat) (m n : nat) : \sum_(0 <= i < m) \sum_(0 <= j < n | odd (j * 1)) (i + j) = \sum_(0 <= i < m) \sum_(0 <= j < n | odd j) (j + i). Proof. (* in one-liner mode *) under eq_bigr => i Hi do under eq_big => [j|j Hj] do [rewrite muln1 | rewrite addnC ]. done. Qed. Lemma test_big_2cond_0intro (F : nat -> nat) (m : nat) : \sum_(0 <= i < m | odd (i + 1)) (i + 2) >= 0. Proof. (* in interactive mode *) under eq_big. { move=> n; rewrite (addnC n 1); over. } { move=> i Hi; rewrite (addnC i 2); over. } done. Qed. Lemma test_big_2cond_1intro (F : nat -> nat) (m : nat) : \sum_(0 <= i < m | odd (i + 1)) (i + 2) >= 0. Proof. (* in interactive mode *) Fail under eq_big => i. (* as it amounts to [under eq_big => [i]] *) Abort. Lemma test_big_2cond_all (F : nat -> nat) (m : nat) : \sum_(0 <= i < m | odd (i + 1)) (i + 2) >= 0. Proof. (* in interactive mode *) Fail under eq_big => *. (* as it amounts to [under eq_big => [*]] *) Abort. Lemma test_big_2cond_all_implied (F : nat -> nat) (m : nat) : \sum_(0 <= i < m | odd (i + 1)) (i + 2) >= 0. Proof. (* in one-liner mode *) under eq_big do [rewrite addnC |rewrite addnC]. (* amounts to [under eq_big => [*|*] do [...|...]] *) done. Qed. Lemma test_big_patt1 (F G : nat -> nat) (n : nat) : \sum_(0 <= i < n) (F i + G i) = \sum_(0 <= i < n) (G i + F i) + 0. Proof. under [in RHS]eq_bigr => i Hi. by rewrite addnC over. done. Qed. Lemma test_big_patt2 (F G : nat -> nat) (n : nat) : \sum_(0 <= i < n) (F i + F i) = \sum_(0 <= i < n) 0 + \sum_(0 <= i < n) (F i * 2). Proof. under [X in _ = _ + X]eq_bigr => i Hi do rewrite mulnS muln1. by rewrite big_const_nat iter_addn_0. Qed. Lemma test_big_occs (F G : nat -> nat) (n : nat) : \sum_(0 <= i < n) (i * 0) = \sum_(0 <= i < n) (i * 0) + \sum_(0 <= i < n) (i * 0). Proof. under {2}[in RHS]eq_bigr => i Hi do rewrite muln0. by rewrite big_const_nat iter_addn_0 mul0n addn0. Qed. Lemma test_big_occs_inH (F G : nat -> nat) (n : nat) : \sum_(0 <= i < n) (i * 0) = \sum_(0 <= i < n) (i * 0) + \sum_(0 <= i < n) (i * 0) -> True. Proof. move=> H. do [under {2}[in RHS]eq_bigr => i Hi do rewrite muln0] in H. by rewrite big_const_nat iter_addn_0 mul0n addn0 in H. Qed. (* Solely used, one such renaming is useless in practice, but it works anyway *) Lemma test_big_cosmetic (F G : nat -> nat) (m n : nat) : \sum_(0 <= i < m) \sum_(0 <= j < n | odd (j * 1)) (i + j) = \sum_(0 <= i < m) \sum_(0 <= j < n | odd j) (j + i). Proof. under [RHS]eq_bigr => a A do under eq_bigr => b B do []. (* renaming bound vars *) myadmit. Qed. Lemma test_big_andb (F : nat -> nat) (m n : nat) : \sum_(0 <= i < 5 | odd i && (i == 1)) i = 1. Proof. under eq_bigl => i do [rewrite andb_idl; first by move/eqP->]. under eq_bigr => i do move/eqP=>{1}->. (* the 2nd occ should not be touched *) myadmit. Qed. Lemma test_foo (f1 f2 : nat -> nat) (f_eq : forall n, f1 n = f2 n) (G : (nat -> nat) -> nat) (Lem : forall f1 f2 : nat -> nat, True -> (forall n, f1 n = f2 n) -> False = False -> G f1 = G f2) : G f1 = G f2. Proof. (* under x: Lem. - done. - rewrite f_eq; over. - done. *) under Lem => [|x|] do [done|rewrite f_eq|done]. done. Qed. (* Inspired From Coquelicot.Lub. *) (* http://coquelicot.saclay.inria.fr/html/Coquelicot.Lub.html#Lub_Rbar_eqset *) Parameters (R Rbar : Set) (R0 : R) (Rbar0 : Rbar). Parameter Rbar_le : Rbar -> Rbar -> Prop. Parameter Lub_Rbar : (R -> Prop) -> Rbar. Parameter Lub_Rbar_eqset : forall E1 E2 : R -> Prop, (forall x : R, E1 x <-> E2 x) -> Lub_Rbar E1 = Lub_Rbar E2. Lemma test_Lub_Rbar (E : R -> Prop) : Rbar_le Rbar0 (Lub_Rbar (fun x => x = R0 \/ E x)). Proof. under Lub_Rbar_eqset => r. by rewrite over. Abort. Lemma ex_iff R (P1 P2 : R -> Prop) : (forall x : R, P1 x <-> P2 x) -> ((exists x, P1 x) <-> (exists x, P2 x)). Proof. by move=> H; split; move=> [x Hx]; exists x; apply H. Qed. Arguments ex_iff [R P1] P2 iffP12. (** Load the [setoid_rewrite] machinery *) Require Setoid. (** Replay the tactics from [test_Lub_Rbar] in this new environment *) Lemma test_Lub_Rbar_again (E : R -> Prop) : Rbar_le Rbar0 (Lub_Rbar (fun x => x = R0 \/ E x)). Proof. under Lub_Rbar_eqset => r. by rewrite over. Abort. Lemma test_ex_iff (P : nat -> Prop) : (exists x, P x) -> True. under ex_iff => n. (* this requires [Setoid] *) by rewrite over. by move=> _. Qed. Section TestGeneric. Context {A B : Type} {R : nat -> B -> B -> Prop} `{!forall n : nat, RelationClasses.Equivalence (R n)}. Variables (F : (A -> A -> B) -> B). Hypothesis ex_gen : forall (n : nat) (P1 P2 : A -> A -> B), (forall x y : A, R n (P1 x y) (P2 x y)) -> (R n (F P1) (F P2)). Arguments ex_gen [n P1] P2 _. Lemma test_ex_gen (P1 P2 : A -> A -> B) (n : nat) : (forall x y : A, P2 x y = P2 y x) -> R n (F P1) (F P2) /\ True -> True. Proof. move=> P2C. under [X in R _ _ X]ex_gen => a b. by rewrite P2C over. by move => _. Qed. End TestGeneric. Import Setoid. (* to expose [Coq.Relations.Relation_Definitions.reflexive], [Coq.Classes.RelationClasses.RewriteRelation], and so on. *) Section TestGeneric2. (* Some toy abstract example with a parameterized setoid type *) Record Setoid (m n : nat) : Type := { car : Type ; Rel : car -> car -> Prop ; refl : reflexive _ Rel ; sym : symmetric _ Rel ; trans : transitive _ Rel }. Context {m n : nat}. Add Parametric Relation (s : Setoid m n) : (car s) (@Rel _ _ s) reflexivity proved by (@refl _ _ s) symmetry proved by (@sym _ _ s) transitivity proved by (@trans _ _ s) as eq_rel. Context {A : Type} {s1 s2 : Setoid m n}. Let B := @car m n s1. Let C := @car m n s2. Variable (F : C -> (A -> A -> B) -> C). Hypothesis rel2_gen : forall (c1 c2 : C) (P1 P2 : A -> A -> B), Rel c1 c2 -> (forall a b : A, Rel (P1 a b) (P2 a b)) -> Rel (F c1 P1) (F c2 P2). Arguments rel2_gen [c1] c2 [P1] P2 _ _. Lemma test_rel2_gen (c : C) (P : A -> A -> B) (toy_hyp : forall a b, P a b = P b a) : Rel (F c P) (F c (fun a b => P b a)). Proof. under [here in Rel _ here]rel2_gen. - over. - by move=> a b; rewrite toy_hyp over. - reflexivity. Qed. End TestGeneric2. Section TestPreOrder. (* inspired by https://github.com/rocq-prover/rocq/pull/10022#issuecomment-530101950 *) Require Import Morphisms. (** Tip to tell rewrite that the LHS of [leq' x y (:= leq x y = true)] is x, not [leq x y] *) Definition rel_true {T} (R : rel T) x y := is_true (R x y). Definition leq' : nat -> nat -> Prop := rel_true leq. Parameter leq_add : forall m1 m2 n1 n2 : nat, m1 <= n1 -> m2 <= n2 -> m1 + m2 <= n1 + n2. Parameter leq_mul : forall m1 m2 n1 n2 : nat, m1 <= n1 -> m2 <= n2 -> m1 * m2 <= n1 * n2. Local Notation "+%N" := addn (at level 0, only parsing). (** Context lemma *) Lemma leq'_big : forall I (F G : I -> nat) (r : seq I), (forall i : I, leq' (F i) (G i)) -> (leq' (\big[+%N/0%N]_(i <- r) F i) (\big[+%N/0%N]_(i <- r) G i)). Proof. red=> F G m n HFG. apply: (big_ind2 leq _ _ (P := xpredT) (op1 := addn) (op2 := addn)) =>//. move=> *; exact: leq_add. move=> *; exact: HFG. Qed. (** Instances for [setoid_rewrite] *) Instance leq'_rr : RewriteRelation leq' := {}. Instance leq'_proper_addn : Proper (leq' ==> leq' ==> leq') addn. Proof. move=> a1 b1 le1 a2 b2 le2; exact/leq_add. Qed. Instance leq'_proper_muln : Proper (leq' ==> leq' ==> leq') muln. Proof. move=> a1 b1 le1 a2 b2 le2; exact/leq_mul. Qed. Instance leq'_preorder : PreOrder leq'. (** encompasses [Reflexive] *) Proof. rewrite /leq' /rel_true; split =>// ??? A B; exact: leq_trans A B. Qed. Instance leq'_reflexive : Reflexive leq'. Proof. by rewrite /leq' /rel_true. Qed. Parameter leq_add2l : forall p m n : nat, (p + m <= p + n) = (m <= n). Lemma test : forall n : nat, (1 + 2 * (\big[+%N/0]_(i < n) (3 + i)) * 4 + 5 <= 6 + 24 * n + 8 * n * n)%N. Proof. move=> n; rewrite -[is_true _]/(rel_true _ _ _) -/leq'. have lem : forall (i : nat), i < n -> leq' (3 + i) (3 + n). { by move=> i Hi; rewrite /leq' /rel_true leq_add2l; apply/ltnW. } under leq'_big => i. { rewrite UnderE. (* instantiate the evar with the bound "3 + n" *) apply: lem; exact: ltn_ord. } cbv beta. now_show (leq' (1 + 2 * \big[+%N/0]_(i < n) (3 + n) * 4 + 5) (6 + 24 * n + 8 * n * n)). (* uninteresting end of proof, omitted *) Abort. End TestPreOrder. rocq-9.2.0/test-suite/ssr/unfold_Opaque.v000066400000000000000000000014041516144147600204030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Type := idpath : paths x x. Register paths as core.eq.type. Register idpath as core.eq.refl. Structure type := Pack {sort; op : rel sort}. Example unfold_fold (T : type) (x : sort T) (a : op T x x) : op T x x. Proof. rewrite /op. rewrite -/(op _ _ _). assumption. Qed. Example pattern_unfold_fold (b:bool) (a := b) : paths a b. Proof. rewrite [in X in paths X _]/a. rewrite -[in X in paths X _]/a. constructor. Qed. Example unfold_in_hyp (b:bool) (a := b) : unit. Proof. assert (paths a a) as A by reflexivity. rewrite [in X in paths X _]/a in A. rewrite /a in (B := idpath a). rewrite [in X in paths _ X]/a in (C := idpath a). constructor. Qed. Example fold_in_hyp (b:bool) (p := idpath b) : unit. Proof. assert (paths (idpath b) (idpath b)) as A by reflexivity. rewrite -[in X in paths X _]/p in A. rewrite -[in X in paths _ X]/p in (C := idpath (idpath b)). constructor. Qed. rocq-9.2.0/test-suite/ssr/unkeyed.v000066400000000000000000000024011516144147600172440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop. Goal (forall T (s : seq T), P _ s). move=> T s. elim: s => [| x /lastP [| s] IH]. Admitted. Goal forall x : 'I_1, x = 0 :> nat. move=> /ord1 -> /=; exact: refl_equal. Qed. Goal forall x : 'I_1, x = 0 :> nat. move=> x. move=> /ord1 -> in x |- *. exact: refl_equal. Qed. rocq-9.2.0/test-suite/ssr/wlog_suff.v000066400000000000000000000020431516144147600175750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop. Definition f := fun x y : T => x. Lemma test1 : forall x y : T, P (f x y) -> P x. Proof. move=> x y; set fxy := f x y; move=> Pfxy. wlog H : @fxy Pfxy / P x. match goal with |- (let fxy0 := f x y in P fxy0 -> P x -> P x) -> P x => by auto | _ => fail end. exact: H. Qed. Lemma test2 : forall x y : T, P (f x y) -> P x. Proof. move=> x y; set fxy := f x y; move=> Pfxy. wlog H : fxy Pfxy / P x. match goal with |- (forall fxy, P fxy -> P x -> P x) -> P x => by auto | _ => fail end. exact: H. Qed. Lemma test3 : forall x y : T, P (f x y) -> P x. Proof. move=> x y; set fxy := f x y; move=> Pfxy. move: {1}@fxy (Pfxy) (Pfxy). match goal with |- (let fxy0 := f x y in P fxy0 -> P fxy -> P x) => by auto | _ => fail end. Qed. Lemma test4 : forall n m z: bool, n = z -> let x := n in x = m && n -> x = m && n. move=> n m z E x H. case: true. by rewrite {1 2}E in (x) H |- *. by rewrite {1}E in x H |- *. Qed. rocq-9.2.0/test-suite/ssr/wlong_intro.v000066400000000000000000000016421516144147600201470ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* x y. wlog suff: x y / x <= y. Admitted. rocq-9.2.0/test-suite/stm/000077500000000000000000000000001516144147600154105ustar00rootroot00000000000000rocq-9.2.0/test-suite/stm/abstract.v000066400000000000000000000002251516144147600174010ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "on"); -*- *) Definition dummy := tt. Definition delayed_abstract : unit. Proof. abstract constructor. Qed. rocq-9.2.0/test-suite/stm/arg_filter_1.v000066400000000000000000000002511516144147600201330ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "on" "-async-proofs-tac-j" "1"); -*- *) Lemma foo (A B : Prop) n : n + 0 = n /\ (A -> B -> A). Proof. split. par: now auto. Qed. rocq-9.2.0/test-suite/stm/classify_set_proof_mode_9093.v000066400000000000000000000002561516144147600231670ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "on" "-noinit"); -*- *) Declare ML Module "rocq-runtime.plugins.ltac". Set Default Proof Mode "Classic". Goal Prop. idtac. Abort. rocq-9.2.0/test-suite/stm/delayed_restrict_univs_9093.v000066400000000000000000000005271516144147600230410ustar00rootroot00000000000000(* -*- coq-prog-args: ("-async-proofs" "on"); -*- *) Unset Universe Polymorphism. Ltac exact0 := let x := constr:(Type) in exact 0. Lemma lemma_restrict_abstract@{} : (nat * nat)%type. Proof. split;[exact 0|abstract exact0]. Qed. (* Debug: 10237:proofworker:0:0 STM: sending back a fat state Error: Universe {polymorphism.1} is unbound. *) rocq-9.2.0/test-suite/success/000077500000000000000000000000001516144147600162555ustar00rootroot00000000000000rocq-9.2.0/test-suite/success/AdvancedCanonicalStructure.v000066400000000000000000000064451516144147600237130ustar00rootroot00000000000000Require Import TestSuite.admit. Section group_morphism. (* An example with default canonical structures *) Variable A B : Type. Variable plusA : A -> A -> A. Variable plusB : B -> B -> B. Variable zeroA : A. Variable zeroB : B. Variable eqA : A -> A -> Prop. Variable eqB : B -> B -> Prop. Variable phi : A -> B. Record img := { ia : A; ib :> B; prf : phi ia = ib }. Parameter eq_img : forall (i1:img) (i2:img), eqB (ib i1) (ib i2) -> eqA (ia i1) (ia i2). Lemma phi_img (a:A) : img. exists a (phi a). refine ( refl_equal _). Defined. Canonical Structure phi_img. Lemma zero_img : img. exists zeroA zeroB. admit. Defined. Canonical Structure zero_img. Lemma plus_img : img -> img -> img. intros i1 i2. exists (plusA (ia i1) (ia i2)) (plusB (ib i1) (ib i2)). admit. Defined. Canonical Structure plus_img. (* Print Canonical Projections. *) Goal forall a1 a2, eqA (plusA a1 zeroA) a2. intros a1 a2. refine (eq_img _ _ _). change (eqB (plusB (phi a1) zeroB) (phi a2)). Admitted. Variable foo : A -> Type. Definition local0 := fun (a1 : A) (a2 : A) (a3 : A) => (eq_refl : plusA a1 (plusA zeroA a2) = ia _). Definition local1 := fun (a1 : A) (a2 : A) (f : A -> A) => (eq_refl : plusA a1 (plusA zeroA (f a2)) = ia _). Definition local2 := fun (a1 : A) (f : A -> A) => (eq_refl : (f a1) = ia _). Goal forall a1 a2, eqA (plusA a1 zeroA) a2. intros a1 a2. refine (eq_img _ _ _). change (eqB (plusB (phi a1) zeroB) (phi a2)). Admitted. End group_morphism. Open Scope type_scope. Section type_reification. Inductive term :Type := Fun : term -> term -> term | Prod : term -> term -> term | Bool : term | SET :term | PROP :term | TYPE :term | Var : Type -> term. Fixpoint interp (t:term) := match t with Bool => bool | SET => Set | PROP => Prop | TYPE => Type | Fun a b => interp a -> interp b | Prod a b => interp a * interp b | Var x => x end. Record interp_pair :Type := { repr:>term; abs:>Type; link: abs = interp repr }. Lemma prod_interp :forall (a b:interp_pair),a * b = interp (Prod a b) . Proof. intros a b. change (a * b = interp a * interp b). rewrite (link a), (link b); reflexivity. Qed. Lemma fun_interp :forall (a b:interp_pair), (a -> b) = interp (Fun a b). Proof. intros a b. change ((a -> b) = (interp a -> interp b)). rewrite (link a), (link b); reflexivity. Qed. Canonical Structure ProdCan (a b:interp_pair) := Build_interp_pair (Prod a b) (a * b) (prod_interp a b). Canonical Structure FunCan (a b:interp_pair) := Build_interp_pair (Fun a b) (a -> b) (fun_interp a b). Canonical Structure BoolCan := Build_interp_pair Bool bool (refl_equal _). Canonical Structure VarCan (x:Type) := Build_interp_pair (Var x) x (refl_equal _). Canonical Structure SetCan := Build_interp_pair SET Set (refl_equal _). Canonical Structure PropCan := Build_interp_pair PROP Prop (refl_equal _). Canonical Structure TypeCan := Build_interp_pair TYPE Type (refl_equal _). (* Print Canonical Projections. *) Variable A:Type. Variable Inhabited: term -> Prop. Variable Inhabited_correct: forall p, Inhabited (repr p) -> abs p. Lemma L : Prop * A -> bool * (Type -> Set) . refine (Inhabited_correct _ _). change (Inhabited (Fun (Prod PROP (Var A)) (Prod Bool (Fun TYPE SET)))). Admitted. Check L : abs _ . End type_reification. rocq-9.2.0/test-suite/success/AdvancedTypeClasses.v000066400000000000000000000042651516144147600223400ustar00rootroot00000000000000Generalizable All Variables. Open Scope type_scope. Section type_reification. Inductive term :Type := Fun : term -> term -> term | Prod : term -> term -> term | Bool : term | SET :term | PROP :term | TYPE :term | Var : Type -> term. Fixpoint interp (t:term) := match t with Bool => bool | SET => Set | PROP => Prop | TYPE => Type | Fun a b => interp a -> interp b | Prod a b => interp a * interp b | Var x => x end. Class interp_pair (abs : Type) := { repr : term; link: abs = interp repr }. Arguments repr _ {interp_pair}. Arguments link _ {interp_pair}. Lemma prod_interp `{interp_pair a, interp_pair b} : a * b = interp (Prod (repr a) (repr b)). simpl. intros. rewrite <- link. rewrite <- (link b). reflexivity. Qed. Lemma fun_interp :forall `{interp_pair a, interp_pair b}, (a -> b) = interp (Fun (repr a) (repr b)). simpl. intros. rewrite <- link. rewrite <- (link b). reflexivity. Qed. Coercion repr : interp_pair >-> term. Definition abs `{interp_pair a} : Type := a. Coercion abs : interp_pair >-> Sortclass. Lemma fun_interp' :forall `{ia : interp_pair, ib : interp_pair}, (ia -> ib) = interp (Fun ia ib). simpl. intros a ia b ib. rewrite <- link. rewrite <- (link b). reflexivity. Qed. Instance ProdCan `(interp_pair a, interp_pair b) : interp_pair (a * b) := { repr := Prod (repr a) (repr b) ; link := prod_interp }. Instance FunCan `(interp_pair a, interp_pair b) : interp_pair (a -> b) := { link := fun_interp }. Instance BoolCan : interp_pair bool := { repr := Bool ; link := refl_equal _ }. Instance VarCan x : interp_pair x | 10 := { repr := Var x ; link := refl_equal _ }. Instance SetCan : interp_pair Set := { repr := SET ; link := refl_equal _ }. Instance PropCan : interp_pair Prop := { repr := PROP ; link := refl_equal _ }. Instance TypeCan : interp_pair Type := { repr := TYPE ; link := refl_equal _ }. (* Print Canonical Projections. *) Variable A:Type. Variable Inhabited: term -> Prop. Variable Inhabited_correct: forall `{interp_pair p}, Inhabited (repr p) -> p. Lemma L : Prop * A -> bool * (Type -> Set) . apply Inhabited_correct. change (Inhabited (Fun (Prod PROP (Var A)) (Prod Bool (Fun TYPE SET)))). Admitted. End type_reification. rocq-9.2.0/test-suite/success/Assumptions.v000066400000000000000000000034051516144147600207730ustar00rootroot00000000000000(* Test about assumptions *) (* Test instances *) Module Instances. Class C' := { f' : unit }. Class D := { g : unit }. Module Type T. #[warning="context-outside-section"] Context (c':={|f':=tt|}). Fail Definition a'' := _ : C'. End T. (* Not instance *) Module Type U. Definition d':={|g:=tt|}. Fail Definition b'' := _ : D. End U. (* Not instance *) (* Local assumptions are always instances by default *) (* Global assumptions are instances if using Context *) Class C := { f : unit }. Section A. Context (c:C). Definition a := _ : C. End A. (* Instance *) Section B. Variable d:D. Definition b := _ : D. End B. (* Instance *) #[warning="context-outside-section"] Context (c:C). Definition a0 := _ : C. (* Instance *) Parameter d:D. Fail Definition b0 := _ : D. (* Not instance *) (* Local/global definitions are never instances by default, using Context or not *) Section A'. Context (c':={|f':=tt|}). Fail Definition a' := _ : C'. End A'. (* Not instance *) Section B'. Let d:={|g:=tt|}. Fail Definition b' := _ : D. End B'. (* Not instance *) #[warning="context-outside-section"] Context (c':={|f':=tt|}). Fail Definition a0' := _ : C'. (* Not instance *) Definition d':={|g:=tt|}. Fail Definition b0' := _ : D. (* Not instance *) End Instances. (* Type factorization *) Module TypeSharing. (* How to observe it? *) Section S. Context (A B : Type). End S. (* Distinct universes *) Section T. Variables A B : Type. End T. (* Same universe *) Section S. Fail Context (a b : _) (e : a = 0). End S. (* not shared *) Section S. Fail Variables (a b : _) (e : a = 0). End S. (* not shared *) End TypeSharing. rocq-9.2.0/test-suite/success/AutoPropLowering.v000066400000000000000000000002251516144147600217230ustar00rootroot00000000000000 Inductive foo : Type := . Fail Check foo : Prop. Inductive bar := . Check bar : Prop. Inductive baz := Baz (_:True) (_:baz). Check baz : Prop. rocq-9.2.0/test-suite/success/BidirectionalityHints.v000066400000000000000000000073371516144147600227620ustar00rootroot00000000000000Set Default Proof Using "Type". Module SimpleExamples. Axiom c : bool -> nat. Coercion c : bool >-> nat. Inductive Boxed A := Box (a : A). Arguments Box {A} & a. Check Box true : Boxed nat. (* Here we check that there is no regression due e.g. to refining arguments in the wrong order *) Axiom f : forall b : bool, (if b then bool else nat) -> Type. Check f true true : Type. Arguments f & _ _. Check f true true : Type. End SimpleExamples. Module Issue7910. Local Set Universe Polymorphism. (** Telescopes *) Inductive tele : Type := | TeleO : tele | TeleS {X} (binder : X -> tele) : tele. Arguments TeleS {_} _. (** The telescope version of Coq's function type *) Fixpoint tele_fun (TT : tele) (T : Type) : Type := match TT with | TeleO => T | TeleS b => forall x, tele_fun (b x) T end. Notation "TT -t> A" := (tele_fun TT A) (at level 99, A at level 200, right associativity). (** An eliminator for elements of [tele_fun]. We use a [fix] because, for some reason, that makes stuff print nicer in the proofs in iris:bi/lib/telescopes.v *) Definition tele_fold {X Y} {TT : tele} (step : forall {A : Type}, (A -> Y) -> Y) (base : X -> Y) : (TT -t> X) -> Y := (fix rec {TT} : (TT -t> X) -> Y := match TT as TT return (TT -t> X) -> Y with | TeleO => fun x : X => base x | TeleS b => fun f => step (fun x => rec (f x)) end) TT. Arguments tele_fold {_ _ !_} _ _ _ /. (** A sigma-like type for an "element" of a telescope, i.e. the data it takes to get a [T] from a [TT -t> T]. *) Inductive tele_arg : tele -> Type := | TargO : tele_arg TeleO (* the [x] is the only relevant data here *) | TargS {X} {binder} (x : X) : tele_arg (binder x) -> tele_arg (TeleS binder). Definition tele_app {TT : tele} {T} (f : TT -t> T) : tele_arg TT -> T := fun a => (fix rec {TT} (a : tele_arg TT) : (TT -t> T) -> T := match a in tele_arg TT return (TT -t> T) -> T with | TargO => fun t : T => t | TargS x a => fun f => rec a (f x) end) TT a f. Arguments tele_app {!_ _} & _ !_ /. Coercion tele_arg : tele >-> Sortclass. Coercion tele_app : tele_fun >-> Funclass. (** Operate below [tele_fun]s with argument telescope [TT]. *) Fixpoint tele_bind {U} {TT : tele} : (TT -> U) -> TT -t> U := match TT as TT return (TT -> U) -> TT -t> U with | TeleO => fun F => F TargO | @TeleS X b => fun (F : TeleS b -> U) (x : X) => (* b x -t> U *) tele_bind (fun a => F (TargS x a)) end. Arguments tele_bind {_ !_} _ /. (** Telescopic quantifiers *) Definition tforall {TT : tele} (Ξ¨ : TT -> Prop) : Prop := tele_fold (fun (T : Type) (b : T -> Prop) => forall x : T, b x) (fun x => x) (tele_bind Ξ¨). Arguments tforall {!_} _ /. Definition texist {TT : tele} (Ξ¨ : TT -> Prop) : Prop := tele_fold ex (fun x => x) (tele_bind Ξ¨). Arguments texist {!_} _ /. Notation "'βˆ€..' x .. y , P" := (tforall (fun x => .. (tforall (fun y => P)) .. )) (at level 200, x binder, y binder, right associativity, format "βˆ€.. x .. y , P"). Notation "'βˆƒ..' x .. y , P" := (texist (fun x => .. (texist (fun y => P)) .. )) (at level 200, x binder, y binder, right associativity, format "βˆƒ.. x .. y , P"). (** The actual test case *) Definition test {TT : tele} (t : TT -> Prop) : Prop := βˆ€.. x, t x /\ t x. Notation "'[TEST' x .. z , P ']'" := (test (TT:=(TeleS (fun x => .. (TeleS (fun z => TeleO)) ..))) (tele_app (fun x => .. (fun z => P) ..))) (x binder, z binder). Notation "'[TEST2' x .. z , P ']'" := (test (TT:=(TeleS (fun x => .. (TeleS (fun z => TeleO)) ..))) (tele_app (TT:=(TeleS (fun x => .. (TeleS (fun z => TeleO)) ..))) (fun x => .. (fun z => P) ..))) (x binder, z binder). Check [TEST (x y : nat), x = y]. Check [TEST2 (x y : nat), x = y]. End Issue7910. rocq-9.2.0/test-suite/success/BracketsWithGoalSelector.v000066400000000000000000000010131516144147600233350ustar00rootroot00000000000000Goal forall A B, B \/ A -> A \/ B. Proof. intros * [HB | HA]. 2: { left. exact HA. Fail right. (* No such goal. Try unfocusing with "}". *) } Fail 2: { (* Non-existent goal. *) idtac. (* The idtac is to get a dot, so that IDEs know to stop there. *) 1:{ (* Syntactic test: no space before bracket. *) right. exact HB. Fail Qed. } Qed. Lemma foo (n: nat) (P : nat -> Prop): P n. Proof. intros. refine (nat_ind _ ?[Base] ?[Step] _). [Base]: { admit. } [Step]: { admit. } Abort. rocq-9.2.0/test-suite/success/CanonicalStructure.v000066400000000000000000000162471516144147600222660ustar00rootroot00000000000000(* Bug #1172 *) Structure foo : Type := Foo { A : Set; Aopt := option A; unopt : Aopt -> A }. Canonical Structure unopt_nat := @Foo nat (fun _ => O). (* Granted wish #1187 *) Record Silly (X : Set) : Set := mkSilly { x : X }. Definition anotherMk := mkSilly. Definition struct := anotherMk nat 3. Canonical Structure struct. (* Intertwinning canonical structures and delta-expansion *) (* Assia's short example *) Open Scope bool_scope. Set Implicit Arguments. Structure test_struct : Type := mk_test {dom :> Type; f : dom -> dom -> bool}. Notation " x != y":= (f _ x y)(at level 10). Canonical Structure bool_test := mk_test (fun x y => x || y). Definition b := bool. Check (fun x : b => x != x). Inductive four := x0 | x1 | x2 | x3. Structure local := MKL { l : four }. Module X. Definition s0 := MKL x0. #[local] Canonical Structure s0. Check (refl_equal _ : l _ = x0). #[local] Canonical Structure s1 := MKL x1. Check (refl_equal _ : l _ = x1). Local Canonical Structure s2 := MKL x2. Check (refl_equal _ : l _ = x2). End X. Fail Check (refl_equal _ : l _ = x0). Fail Check (refl_equal _ : l _ = x1). Fail Check (refl_equal _ : l _ = x2). Check X.s0. Check X.s1. Check X.s2. Module Y. Definition s3 := MKL x3. Canonical Structure s3. Check (refl_equal _ : l _ = x3). End Y. Fail Check (refl_equal _ : l _ = x3). Fail Check s3. Module V. #[canonical] Definition s3 := MKL x3. Check (refl_equal _ : l _ = x3). End V. Module W. #[canonical, local] Definition s2' := MKL x2. Check (refl_equal _ : l _ = x2). End W. Fail Check (refl_equal _ : l _ = x2). (* Lambda keys *) Module LambdaKeys. Structure cs_lambda := { cs_lambda_key : nat -> nat }. Module L1. #[local] Canonical Structure cs_lambda_func := {| cs_lambda_key := fun x => x + 1 |}. Check (refl_equal _ : cs_lambda_key _ = fun _ => _ + _). End L1. Module L2. #[local] Canonical Structure cs_lambda_func2 := {| cs_lambda_key := fun x => 1 + x |}. Check (refl_equal _ : cs_lambda_key _ = fun x => 1 + x). End L2. Module L3. #[local] Canonical Structure cs_lambda_func3 := {| cs_lambda_key := fun x => 1 + x |}. Check (refl_equal _ : cs_lambda_key _ = Nat.add 1). End L3. Module L4. #[local] Canonical Structure cs_lambda_func4 := {| cs_lambda_key := Nat.add 1 |}. Check (refl_equal _ : cs_lambda_key _ = Nat.add 1). End L4. Module L5. #[local] Canonical Structure cs_lambda_func5 := {| cs_lambda_key := Nat.add 1 |}. Check (refl_equal _ : cs_lambda_key _ = fun x => 1 + x). End L5. End LambdaKeys. Module DepProd. Structure hello := { hello_key : Type }. Module FixedTypes. Local Canonical Structure hello_dep1 := {| hello_key := forall x : nat, x = x |}. Example ex_hello2 := let h := _ in fun f : hello_key h => (f : forall x : nat, x = x) 1. End FixedTypes. Module VariableTypes. Local Canonical Structure hello_dep2 v1 v2 := {| hello_key := forall x : list v1, x = v2 |}. Example ex_hello1 : _ -> _ = nil := let h := _ in fun f : hello_key h => (f : forall x : list _, _ = _) (@nil nat). End VariableTypes. End DepProd. (* Testing that canonical projections equipped with function type instances ([forall _, _]) or default instances ([_]) can be used in places where functions/function types are expected. This feature triggers CS search in two typing cases: 1. [f x : _] when [f : proj _] 2. [(fun x => _) : proj _]. *) Module NoCasts. Module Basic. Structure r1 (useless_param: bool) := { #[canonical=no] r1_pre : unit ; #[canonical=yes] r1_key : Type ; #[canonical=no] r1_post: nat }. Canonical Structure r1_func b : r1 b := {| r1_pre:= tt; r1_key := nat -> nat; r1_post:= 0|}. Example ex_r1_1 p := let b := _ in fun f : @r1_key p b => f 1. Example ex_r1_2 p := let b := _ in (fun x => x) : @r1_key p b. End Basic. Module Primitive. Local Set Primitive Projections. Structure r2 (useless_param: bool) := { #[canonical=no] r2_pre : unit ; #[canonical=yes] r2_key : Type ; #[canonical=no] r2_post: nat; }. Canonical Structure r2_func b : r2 b := {| r2_pre:= tt; r2_key := nat -> nat; r2_post:= 0|}. Example ex_r2_1 p := let b := _ in fun f : @r2_key p b => f 1. Example ex_r2_2 p := let b := _ in (fun x => x) : @r2_key p b. End Primitive. Module UsedParameters. Structure r3 (useless_param: bool) (T : Type) := { #[canonical=no] r3_pre : unit ; #[canonical=yes] r3_key : Type ; #[canonical=no] r3_post: T }. Canonical Structure r3_func b : r3 b nat := {| r3_pre:= tt; r3_key := nat -> nat; r3_post:= 0|}. Example ex_r3_1 p := let b := _ in fun f : @r3_key p _ b => f 1. Example ex_r3_2 p := let b := _ in (fun x => x) : @r3_key p _ b. End UsedParameters. Module LetBoundFieldBefore. Structure r4 (useless_param: bool) := { #[canonical=no] r4_pre : unit ; #[canonical=no] r4_let := true ; #[canonical=yes] r4_key : Type ; #[canonical=no] r4_post: nat; }. Canonical Structure r4_func b : r4 b := {| r4_pre:= tt; r4_key := nat -> nat; r4_post:= 0|}. Example ex_r4_1 p := let b := _ in fun f : @r4_key p b => f 1. Example ex_r4_2 p := let b := _ in (fun x => x) : @r4_key p b. End LetBoundFieldBefore. Module LetBoundFieldAfter. Structure r4 (useless_param: bool) := { #[canonical=no] r4_pre : unit ; #[canonical=yes] r4_key : Type ; #[canonical=no] r4_let := true ; #[canonical=no] r4_post: nat; }. Canonical Structure r4_func b : r4 b := {| r4_pre:= tt; r4_key := nat -> nat; r4_post:= 0|}. Example ex_r4_1 p := let b := _ in fun f : @r4_key p b => f 1. Example ex_r4_2 p := let b := _ in (fun x => x) : @r4_key p b. End LetBoundFieldAfter. Module Tele. Inductive tele : Type := | TeleO : tele | TeleS {X} : (X -> tele) -> tele. #[local] Set Primitive Projections. Structure tele_of := { tele_term : Type; #[canonical=no] tele_tele : tele; }. Canonical Structure tele_of_prod {X} {t : X -> tele_of} := {| tele_term := forall x, (tele_term (t x)); tele_tele := TeleS (fun x => tele_tele (t x))|}. Canonical Structure tele_of_base {T} := {| tele_term := T; tele_tele := TeleO |}. Check let t : tele_of := _ in fun f : tele_term t => (f 0). (* Was Error: Ill-typed evar instance in #12383/#14715 original version *) End Tele. End NoCasts. (* Testing that we find coherent surrounding stacks for CS problems. *) Module ExtraArgs. Structure Fun := {apply : nat -> nat}. Canonical S_Fun := {| apply := S |}. Check eq_refl : apply _ = S. Check eq_refl : apply _ 0 = S 0. Canonical generic_Fun (f : nat -> nat) := {| apply := f |}. Set Debug "unification". Set Printing All. Check fun (f : nat -> nat) => eq_refl : apply _ = f. Check fun (f : nat -> nat) => eq_refl : apply _ 0 = f 0. End ExtraArgs. (* Testing that we unfold keys that match but do not unify *) Module TestKeys. Structure Dummy (b : bool) := {T : Type}. Definition boolF := bool. Canonical Dummy_boolF : Dummy false := {| T := boolF |}. Definition boolT := boolF. Canonical Dummy_boolT : Dummy true := {| T := boolT |}. Set Debug "unification". Check eq_refl : id (@T false _) = boolT. End TestKeys. rocq-9.2.0/test-suite/success/Case1.v000066400000000000000000000005171516144147600174030ustar00rootroot00000000000000(* Testing eta-expansion of elimination predicate *) Section NATIND2. Variable P : nat -> Type. Variable H0 : P 0. Variable H1 : P 1. Variable H2 : forall n : nat, P n -> P (S (S n)). Fixpoint nat_ind2 (n : nat) : P n := match n as x return (P x) with | O => H0 | S O => H1 | S (S n) => H2 n (nat_ind2 n) end. End NATIND2. rocq-9.2.0/test-suite/success/Case10.v000066400000000000000000000013421516144147600174600ustar00rootroot00000000000000(* ============================================== *) (* To test compilation of dependent case *) (* Multiple Patterns *) (* ============================================== *) Inductive skel : Type := | PROP : skel | PROD : skel -> skel -> skel. Parameter Can : skel -> Type. Parameter default_can : forall s : skel, Can s. Type (fun s1 s2 : skel => match s1, s2 return (Can s1) with | PROP, PROP => default_can PROP | s1, _ => default_can s1 end). Type (fun s1 s2 : skel => match s1, s2 return (Can s1) with | PROP, PROP => default_can PROP | PROP as s, _ => default_can s | PROD s1 s2 as s, PROP => default_can s | PROD s1 s2 as s, _ => default_can s end). rocq-9.2.0/test-suite/success/Case11.v000066400000000000000000000005351516144147600174640ustar00rootroot00000000000000(* L'algo d'infΓ©rence du prΓ©dicat doit gΓ©rer le K-rΓ©dex dans le type de b *) (* ProblΓ¨me rapportΓ© par Solange Coupet *) Section A. Variables (Alpha : Set) (Beta : Set). Definition nodep_prod_of_dep (c : sigT (fun a : Alpha => Beta)) : Alpha * Beta := match c with | existT _ a b => (a, b) end. End A. rocq-9.2.0/test-suite/success/Case12.v000066400000000000000000000040151516144147600174620ustar00rootroot00000000000000(* This example was proposed by Cuihtlauac ALVARADO *) Fixpoint mult2 (n : nat) : nat := match n with | O => 0 | S n => S (S (mult2 n)) end. Inductive list : nat -> Set := | nil : list 0 | cons : forall n : nat, list (mult2 n) -> list (S (S (mult2 n))). Type (fun (P : forall n : nat, list n -> Prop) (f : P 0 nil) (f0 : forall (n : nat) (l : list (mult2 n)), P (mult2 n) l -> P (S (S (mult2 n))) (cons n l)) => fix F (n : nat) (l : list n) {struct l} : P n l := match l as x0 in (list x) return (P x x0) with | nil => f | cons n0 l0 => f0 n0 l0 (F (mult2 n0) l0) end). Inductive list' : nat -> Set := | nil' : list' 0 | cons' : forall n : nat, let m := mult2 n in list' m -> list' (S (S m)). Fixpoint length n (l : list' n) {struct l} : nat := match l with | nil' => 0 | cons' _ m l0 => S (length m l0) end. Type (fun (P : forall n : nat, list' n -> Prop) (f : P 0 nil') (f0 : forall n : nat, let m := mult2 n in forall l : list' m, P m l -> P (S (S m)) (cons' n l)) => fix F (n : nat) (l : list' n) {struct l} : P n l := match l as x0 in (list' x) return (P x x0) with | nil' => f | cons' n0 m l0 => f0 n0 l0 (F m l0) end). (* Check on-the-fly insertion of let-in patterns for compatibility *) Inductive list'' : nat -> Set := | nil'' : list'' 0 | cons'' : forall n : nat, let m := mult2 n in list'' m -> let p := S (S m) in list'' p. Check (fix length n (l : list'' n) {struct l} : nat := match l with | nil'' => 0 | cons'' n l0 => S (length (mult2 n) l0) end). (* Check let-in in both parameters and in constructors *) Inductive list''' (A:Set) (B:=(A*A)%type) (a:A) : B -> Set := | nil''' : list''' A a (a,a) | cons''' : forall a' : A, let m := (a',a) in list''' A a m -> list''' A a (a,a). Fixpoint length''' (A:Set) (B:=(A*A)%type) (a:A) (m:B) (l:list''' A a m) {struct l} : nat := match l with | nil''' _ _ => 0 | @cons''' _ _ _ _ m l0 => S (length''' A a m l0) end. rocq-9.2.0/test-suite/success/Case13.v000066400000000000000000000073351516144147600174730ustar00rootroot00000000000000(* Check coercions in patterns *) Inductive I : Set := | C1 : nat -> I | C2 : I -> I. Coercion C1 : nat >-> I. (* Coercion at the root of pattern *) Check (fun x => match x with | C2 n => 0 | O => 0 | S n => n end). (* Coercion not at the root of pattern *) Check (fun x => match x with | C2 O => 0 | _ => 0 end). (* Unification and coercions inside patterns *) Check (fun x : option nat => match x with | None => 0 | Some O => 0 | _ => 0 end). (* Coercion up to delta-conversion, and unification *) Coercion somenat := Some (A:=nat). Check (fun x => match x with | None => 0 | O => 0 | S n => n end). (* Coercions with parameters *) Inductive listn : nat -> Set := | niln : listn 0 | consn : forall n : nat, nat -> listn n -> listn (S n). Inductive I' : nat -> Set := | C1' : forall n : nat, listn n -> I' n | C2' : forall n : nat, I' n -> I' n. Coercion C1' : listn >-> I'. Check (fun x : I' 0 => match x with | C2' _ _ => 0 | niln => 0 | _ => 0 end). Check (fun x : I' 0 => match x with | C2' _ niln => 0 | _ => 0 end). (* This one could eventually be solved, the "Fail" is just to ensure *) (* that it does not fail with an anomaly, as it did at some time *) Fail Check (fun x : I' 0 => match x return _ x with | C2' _ _ => 0 | niln => 0 | _ => 0 end). (* Check insertion of coercions around matched subterm *) Parameter A:Set. Parameter f:> A -> nat. Inductive J : Set := D : A -> J. Check (fun x => match x with | D 0 => 0 | D _ => 1 end). (* Check coercions against the type of the term to match *) (* Used to fail in V8.1beta *) Inductive C : Set := c : C. Inductive E : Set := e :> C -> E. Check fun (x : E) => match x with c => e c end. (* Check coercions with uniform parameters (cf bug #1168) *) Inductive C' : bool -> Set := c' : C' true. Inductive E' (b : bool) : Set := e' :> C' b -> E' b. Check fun (x : E' true) => match x with c' => e' true c' end. (* Check use of the no-dependency strategy when a type constraint is given (and when the "inversion-and-dependencies-as-evars" strategy is not strong enough because of a constructor with a type whose pattern structure is not refined enough for it to be captured by the inversion predicate) *) Inductive K : bool -> bool -> Type := F : K true true | G x : K x x. Check fun z P Q (y:K true z) (H1 H2:P y) (f:forall y, P y -> Q y z) => match y with | F => f y H1 | G _ => f y H2 end : Q y z. (* Check use of the maximal-dependency-in-variable strategy even when no explicit type constraint is given (and when the "inversion-and-dependencies-as-evars" strategy is not strong enough because of a constructor with a type whose pattern structure is not refined enough for it to be captured by the inversion predicate) *) Check fun z P Q (y:K true z) (H1 H2:P y) (f:forall y z, P y -> Q y z) => match y with | F => f y true H1 | G b => f y b H2 end. (* Check use of the maximal-dependency-in-variable strategy for "Var" variables *) Goal forall z P Q (y:K true z) (H1 H2:P y) (f:forall y z, P y -> Q y z), Q y z. intros z P Q y H1 H2 f. Show. refine (match y with | F => f y true H1 | G b => f y b H2 end). Qed. rocq-9.2.0/test-suite/success/Case14.v000066400000000000000000000007761516144147600174760ustar00rootroot00000000000000(* Test of inference of elimination predicate for "if" *) (* submitted by Robert R Schneck *) Axiom bad : false = true. Definition try1 : False := match bad in (_ = b) return (if b then False else True) with | refl_equal => I end. Definition try2 : False := match bad in (_ = b) return ((if b then False else True):Prop) with | refl_equal => I end. Definition try3 : False := match bad in (_ = b) return ((fun b' : bool => if b' then False else True) b) with | refl_equal => I end. rocq-9.2.0/test-suite/success/Case15.v000066400000000000000000000024431516144147600174700ustar00rootroot00000000000000(* Check compilation of multiple pattern-matching on terms non apparently of inductive type *) (* Check that the non dependency in y is OK both in V7 and V8 *) Check (fun x (y : Prop) z => match x, y, z return (x = x \/ z = z) with | O, y, z' => or_introl (z' = z') (refl_equal 0) | _, y, O => or_intror _ (refl_equal 0) | x, y, _ => or_introl _ (refl_equal x) end). (* Suggested by Pierre Letouzey (PR#207) *) Inductive Boite : Set := boite : forall b : bool, (if b then nat else (nat * nat)%type) -> Boite. Definition test (B : Boite) := match B return nat with | boite true n => n | boite false (n, m) => n + m end. (* Check laziness of compilation ... future work Inductive I : Set := c : (b:bool)(if b then bool else nat)->I. Check [x] Cases x of (c (true as y) (true as x)) => (if x then y else true) | (c false O) => true | _ => false end. Check [x] Cases x of (c true true) => true | (c false O) => true | _ => false end. (* Devrait produire ceci mais trouver le type intermediaire est coton ! *) Check [x:I] Cases x of (c b y) => (<[b:bool](if b then bool else nat)->bool>if b then [y](if y then true else false) else [y]Cases y of O => true | (S _) => false end y) end. *) rocq-9.2.0/test-suite/success/Case16.v000066400000000000000000000006311516144147600174660ustar00rootroot00000000000000(**********************************************************************) (* Test dependencies in constructors *) (**********************************************************************) Check (fun x : {b : bool | if b then True else False} => match x return (let (b, _) := x in if b then True else False) with | exist _ true y => y | exist _ false z => z end). rocq-9.2.0/test-suite/success/Case17.v000066400000000000000000000034671516144147600175010ustar00rootroot00000000000000(* Check the synthesis of predicate from a cast in case of matching of the first component (here [list bool]) of a dependent type (here [sigT]) (Simplification of an example from file parsing2.v of the Coq'Art exercises) *) Parameter parse_rel : list bool -> list bool -> nat -> Prop. Parameter (l0 : list bool) (rec : forall l' : list bool, length l' <= S (length l0) -> {l'' : list bool & {t : nat | parse_rel l' l'' t /\ length l'' <= length l'}} + {(forall (l'' : list bool) (t : nat), ~ parse_rel l' l'' t)}). Axiom HHH : forall A : Prop, A. Check (match rec l0 (HHH _) with | inleft (existT _ (cons false l1) _) => inright _ (HHH _) | inleft (existT _ (cons true l1) (exist _ t1 (conj Hp Hl))) => inright _ (HHH _) | inleft (existT _ _ _) => inright _ (HHH _) | inright Hnp => inright _ (HHH _) end :{l'' : list bool & {t : nat | parse_rel (true :: l0) l'' t /\ length l'' <= S (length l0)}} + {(forall (l'' : list bool) (t : nat), ~ parse_rel (true :: l0) l'' t)}). (* The same but with relative links to l0 and rec *) Check (fun (l0 : list bool) (rec : forall l' : list bool, length l' <= S (length l0) -> {l'' : list bool & {t : nat | parse_rel l' l'' t /\ length l'' <= length l'}} + {(forall (l'' : list bool) (t : nat), ~ parse_rel l' l'' t)}) => match rec l0 (HHH _) with | inleft (existT _ (cons false l1) _) => inright _ (HHH _) | inleft (existT _ (cons true l1) (exist _ t1 (conj Hp Hl))) => inright _ (HHH _) | inleft (existT _ _ _) => inright _ (HHH _) | inright Hnp => inright _ (HHH _) end :{l'' : list bool & {t : nat | parse_rel (true :: l0) l'' t /\ length l'' <= S (length l0)}} + {(forall (l'' : list bool) (t : nat), ~ parse_rel (true :: l0) l'' t)}). rocq-9.2.0/test-suite/success/Case18.v000066400000000000000000000011441516144147600174700ustar00rootroot00000000000000(* Check or-patterns *) (* Non-interference with Numbers divisibility. *) Reserved Notation "( p | q )" (at level 0). Definition g x := match x with ((((1 as x),_) | (_,x)), ((_,(2 as y)) | (y,_))) => (x,y) end. Check (refl_equal _ : g ((1,2),(3,4)) = (1,3)). Check (refl_equal _ : g ((1,4),(3,2)) = (1,2)). Fixpoint max (n m:nat) {struct m} : nat := match n, m with | S n', S m' => S (max n' m') | 0, p | p, 0 => p end. (* Check bug #1477 *) Inductive I : Set := | A : nat -> nat -> I | B : nat -> nat -> I. Definition foo (x:I) : nat := match x with | A a b | B b a => S b end. rocq-9.2.0/test-suite/success/Case19.v000066400000000000000000000017141516144147600174740ustar00rootroot00000000000000(* This used to fail in Coq version 8.1 beta due to a non variable universe (issued by template polymorphism) being sent by pretyping to the kernel (bug #1182) *) Parameter T : Type. Parameter x : nat*nat. Check let (_, _) := x in sigT (fun _ : T => nat). (* This used to raise an anomaly in V8.4, up to pl2 *) Goal {x: nat & x=x}. Fail exists (fun x => match projT2 (projT2 x) as e in (_ = y) return _ = existT _ (projT1 x) (existT _ y e) with | eq_refl => eq_refl end). Abort. (* Some tests with ltac matching on building "if" and "let" *) Goal forall b c d, (if negb b then c else d) = 0. intros. match goal with |- (if ?b then ?c else ?d) = 0 => transitivity (if b then d else c) end. Abort. Definition swap {A} {B} '((x,y):A*B) := (y,x). Goal forall p, (let '(x,y) := swap p in x + y) = 0. intros. match goal with |- (let '(x,y) := ?p in x + y) = 0 => transitivity (let (x,y) := p in x+y) end. Abort. rocq-9.2.0/test-suite/success/Case2.v000066400000000000000000000004621516144147600174030ustar00rootroot00000000000000(* ============================================== *) (* To test compilation of dependent case *) (* Nested patterns *) (* ============================================== *) Type match 0 as n return (n = n) with | O => refl_equal 0 | m => refl_equal m end. rocq-9.2.0/test-suite/success/Case20.v000066400000000000000000000021331516144147600174600ustar00rootroot00000000000000(* Example taken from RelationAlgebra *) (* Was failing from r16205 up to now *) Require Import TestSuite.binpos. Section A. Context (A:Type) {X: A} (tst:A->Type) (top:forall X, X). Inductive v: (positive -> A) -> Type := | v_L: forall f', v f' | v_N: forall f', v (fun n => f' (xO n)) -> (positive -> tst (f' xH)) -> v (fun n => f' (xI n)) -> v f'. Fixpoint v_add f' (t: v f') n: (positive -> tst (f' n)) -> v f' := match t in (v o) return ((positive -> (tst (o n))) -> v o) with | v_L f' => match n return ((positive -> (tst (f' n))) -> v f') with | xH => fun x => v_N _ (v_L _) x (v_L _) | xO n => fun x => v_N _ (v_add (fun n => f' (xO n)) (v_L _) n x) (fun _ => top _) (v_L _) | xI n => fun x => v_N _ (v_L _) (fun _ => top _) (v_add (fun n => f' (xI n)) (v_L _) n x) end | v_N f' l y r => match n with | xH => fun x => v_N _ l x r | xO n => fun x => v_N _ (v_add (fun n => f' (xO n)) l n x) y r | xI n => fun x => v_N _ l y (v_add (fun n => f' (xI n)) r n x) end end. End A. rocq-9.2.0/test-suite/success/Case21.v000066400000000000000000000007341516144147600174660ustar00rootroot00000000000000(* Check insertion of impossible case when there is no branch at all *) Inductive eq_true : bool -> Prop := is_eq_true : eq_true true. Check fun H:eq_true false => match H with end : False. Inductive I : bool -> bool -> Prop := C : I true true. Check fun x (H:I x false) => match H with end : False. Check fun x (H:I false x) => match H with end : False. Inductive I' : bool -> Type := C1 : I' true | C2 : I' true. Check fun x : I' false => match x with end : False. rocq-9.2.0/test-suite/success/Case22.v000066400000000000000000000062431516144147600174700ustar00rootroot00000000000000(* Check typing in the presence of let-in in inductive arity *) Inductive I : let a := 1 in a=a -> let b := 2 in Type := C : I (eq_refl). Lemma a : forall x:I eq_refl, match x in I a b c return b = b with C => eq_refl end = eq_refl. intro. match goal with |- ?c => let x := eval cbv in c in change x end. Abort. Check forall x:I eq_refl, match x in I x return x = x with C => eq_refl end = eq_refl. (* This is bug #3210 *) Inductive I' : let X := Set in X := | C' : I'. Definition foo (x : I') : bool := match x with C' => true end. (* Bug found in november 2015: was wrongly failing in 8.5beta2 and 8.5beta3 *) Inductive I2 (A:Type) : let B:=A in forall C, let D:=(C*B)%type in Type := E2 : I2 A nat. Check fun x:I2 nat nat => match x in I2 _ X Y Z return X*Y*Z with E2 _ => (0,0,(0,0)) end. (* This used to succeed in 8.3, 8.4 and 8.5beta1 *) Inductive IND : forall X:Type, let Y:=X in Type := CONSTR : IND True. Definition F (x:IND True) (A:Type) := (* This failed in 8.5beta2 though it should have been accepted *) match x in IND X Y return Y with CONSTR => Logic.I end. Theorem paradox : False. (* This succeeded in 8.3, 8.4 and 8.5beta1 because F had wrong type *) Fail Proof (F C False). Abort. (* Another bug found in November 2015 (a substitution was wrongly reversed at pretyping level) *) Inductive Ind (A:Type) : let X:=A in forall Y:Type, let Z:=(X*Y)%type in Type := Constr : Ind A nat. Check fun x:Ind bool nat => match x in Ind _ X Y Z return Z with | Constr _ => (true,0) end. (* A vm_compute bug (the type of constructors was not supposed to contain local definitions before proper parameters) *) Inductive Ind2 (b:=1) (c:nat) : Type := Constr2 : Ind2 c. Eval vm_compute in Constr2 2. (* A bug introduced in ade2363 (similar to #5322 and #5324). This commit started to see that some List.rev was wrong in the "var" case of a pattern-matching problem but it failed to see that a transformation from a list of arguments into a substitution was still needed. *) (* The order of real arguments was made wrong by ade2363 in the "var" case of the compilation of "match" *) Inductive IND2 : forall X Y:Type, Type := CONSTR2 : IND2 unit Empty_set. Check fun x:IND2 bool nat => match x in IND2 a b return a with | y => _ end = true. (* From January 2017, using the proper function to turn arguments into a substitution up to a context possibly containing let-ins, so that the following, which was wrong also before ade2363, now works correctly *) Check fun x:Ind bool nat => match x in Ind _ X Y Z return Z with | y => (true,0) end. (* A check that multi-implicit arguments work *) Check fun x : {True}+{False} => match x with left _ _ => 0 | right _ _ => 1 end. Check fun x : {True}+{False} => match x with left _ => 0 | right _ => 1 end. (* Check that Asymmetric Patterns does not apply to the in clause *) Inductive expr {A} : A -> Type := intro : forall {n:nat} (a:A), n=n -> expr a. Check fun (x:expr true) => match x in expr n return n=n with intro _ _ => eq_refl end. Set Asymmetric Patterns. Check fun (x:expr true) => match x in expr n return n=n with intro _ a _ => eq_refl a end. Unset Asymmetric Patterns. rocq-9.2.0/test-suite/success/Case3.v000066400000000000000000000013201516144147600173760ustar00rootroot00000000000000Inductive Le : nat -> nat -> Set := | LeO : forall n : nat, Le 0 n | LeS : forall n m : nat, Le n m -> Le (S n) (S m). Parameter discr_l : forall n : nat, S n <> 0. Type (fun n : nat => match n return (n = 0 \/ n <> 0) with | O => or_introl (0 <> 0) (refl_equal 0) | S O => or_intror (1 = 0) (discr_l 0) | S (S x) => or_intror (S (S x) = 0) (discr_l (S x)) end). Parameter iguales : forall (n m : nat) (h : Le n m), Prop. Type match LeO 0 as h in (Le n m) return Prop with | LeO O => True | LeS (S x) (S y) H => iguales (S x) (S y) H | _ => False end. Type match LeO 0 as h in (Le n m) return Prop with | LeO O => True | LeS (S x) O H => iguales (S x) 0 H | _ => False end. rocq-9.2.0/test-suite/success/Case4.v000066400000000000000000000022611516144147600174040ustar00rootroot00000000000000Inductive listn : nat -> Set := | niln : listn 0 | consn : forall n : nat, nat -> listn n -> listn (S n). Inductive empty : forall n : nat, listn n -> Prop := intro_empty : empty 0 niln. Parameter inv_empty : forall (n a : nat) (l : listn n), ~ empty (S n) (consn n a l). Type (fun (n : nat) (l : listn n) => match l in (listn n) return (empty n l \/ ~ empty n l) with | niln => or_introl (~ empty 0 niln) intro_empty | consn n O y as b => or_intror (empty (S n) b) (inv_empty n 0 y) | consn n a y as b => or_intror (empty (S n) b) (inv_empty n a y) end). Type (fun (n : nat) (l : listn n) => match l in (listn n) return (empty n l \/ ~ empty n l) with | niln => or_introl (~ empty 0 niln) intro_empty | consn n O y => or_intror (empty (S n) (consn n 0 y)) (inv_empty n 0 y) | consn n a y => or_intror (empty (S n) (consn n a y)) (inv_empty n a y) end). Type (fun (n : nat) (l : listn n) => match l in (listn n) return (empty n l \/ ~ empty n l) with | niln => or_introl (~ empty 0 niln) intro_empty | consn O a y as b => or_intror (empty 1 b) (inv_empty 0 a y) | consn n a y as b => or_intror (empty (S n) b) (inv_empty n a y) end). rocq-9.2.0/test-suite/success/Case5.v000066400000000000000000000005551516144147600174110ustar00rootroot00000000000000 Parameter ff : forall n m : nat, n <> m -> S n <> S m. Parameter discr_r : forall n : nat, 0 <> S n. Parameter discr_l : forall n : nat, S n <> 0. Type (fun n : nat => match n return (n = 0 \/ n <> 0) with | O => or_introl (0 <> 0) (refl_equal 0) | S O => or_intror (1 = 0) (discr_l 0) | S (S x) => or_intror (S (S x) = 0) (discr_l (S x)) end). rocq-9.2.0/test-suite/success/Case6.v000066400000000000000000000011071516144147600174040ustar00rootroot00000000000000Parameter ff : forall n m : nat, n <> m -> S n <> S m. Parameter discr_r : forall n : nat, 0 <> S n. Parameter discr_l : forall n : nat, S n <> 0. Fixpoint eqdec (n m : nat) {struct n} : n = m \/ n <> m := match n, m return (n = m \/ n <> m) with | O, O => or_introl (0 <> 0) (refl_equal 0) | O, S x => or_intror (0 = S x) (discr_r x) | S x, O => or_intror _ (discr_l x) | S x as N, S y as M => match eqdec x y return (N = M \/ N <> M) with | or_introl h => or_introl (N <> M) (f_equal S h) | or_intror h => or_intror (N = M) (ff x y h) end end. rocq-9.2.0/test-suite/success/Case7.v000066400000000000000000000007361516144147600174140ustar00rootroot00000000000000Inductive List (A : Set) : Set := | Nil : List A | Cons : A -> List A -> List A. Inductive Empty (A : Set) : List A -> Prop := intro_Empty : Empty A (Nil A). Parameter inv_Empty : forall (A : Set) (a : A) (x : List A), ~ Empty A (Cons A a x). Type (fun (A : Set) (l : List A) => match l return (Empty A l \/ ~ Empty A l) with | Nil _ => or_introl (~ Empty A (Nil A)) (intro_Empty A) | Cons _ a y as b => or_intror (Empty A b) (inv_Empty A a y) end). rocq-9.2.0/test-suite/success/Case8.v000066400000000000000000000005221516144147600174060ustar00rootroot00000000000000(* Check dependencies in the matching predicate (was failing in V8.0pl1) *) Inductive t : forall x : 0 = 0, x = x -> Prop := c : forall x : 0 = 0, t x (refl_equal x). Definition a (x : t _ (refl_equal (refl_equal 0))) := match x return match x with | c y => Prop end with | c y => y = y end. rocq-9.2.0/test-suite/success/Case9.v000066400000000000000000000043351516144147600174150ustar00rootroot00000000000000Inductive List (A : Set) : Set := | Nil : List A | Cons : A -> List A -> List A. Inductive eqlong : List nat -> List nat -> Prop := | eql_cons : forall (n m : nat) (x y : List nat), eqlong x y -> eqlong (Cons nat n x) (Cons nat m y) | eql_nil : eqlong (Nil nat) (Nil nat). Parameter V1 : eqlong (Nil nat) (Nil nat) \/ ~ eqlong (Nil nat) (Nil nat). Parameter V2 : forall (a : nat) (x : List nat), eqlong (Nil nat) (Cons nat a x) \/ ~ eqlong (Nil nat) (Cons nat a x). Parameter V3 : forall (a : nat) (x : List nat), eqlong (Cons nat a x) (Nil nat) \/ ~ eqlong (Cons nat a x) (Nil nat). Parameter V4 : forall (a : nat) (x : List nat) (b : nat) (y : List nat), eqlong (Cons nat a x) (Cons nat b y) \/ ~ eqlong (Cons nat a x) (Cons nat b y). Parameter nff : forall (n m : nat) (x y : List nat), ~ eqlong x y -> ~ eqlong (Cons nat n x) (Cons nat m y). Parameter inv_r : forall (n : nat) (x : List nat), ~ eqlong (Nil nat) (Cons nat n x). Parameter inv_l : forall (n : nat) (x : List nat), ~ eqlong (Cons nat n x) (Nil nat). Fixpoint eqlongdec (x y : List nat) {struct x} : eqlong x y \/ ~ eqlong x y := match x, y return (eqlong x y \/ ~ eqlong x y) with | Nil _, Nil _ => or_introl (~ eqlong (Nil nat) (Nil nat)) eql_nil | Nil _, Cons _ a x as L => or_intror (eqlong (Nil nat) L) (inv_r a x) | Cons _ a x as L, Nil _ => or_intror (eqlong L (Nil nat)) (inv_l a x) | Cons _ a x as L1, Cons _ b y as L2 => match eqlongdec x y return (eqlong L1 L2 \/ ~ eqlong L1 L2) with | or_introl h => or_introl (~ eqlong L1 L2) (eql_cons a b x y h) | or_intror h => or_intror (eqlong L1 L2) (nff a b x y h) end end. Type match Nil nat as x, Nil nat as y return (eqlong x y \/ ~ eqlong x y) with | Nil _, Nil _ => or_introl (~ eqlong (Nil nat) (Nil nat)) eql_nil | Nil _, Cons _ a x as L => or_intror (eqlong (Nil nat) L) (inv_r a x) | Cons _ a x as L, Nil _ => or_intror (eqlong L (Nil nat)) (inv_l a x) | Cons _ a x as L1, Cons _ b y as L2 => match eqlongdec x y return (eqlong L1 L2 \/ ~ eqlong L1 L2) with | or_introl h => or_introl (~ eqlong L1 L2) (eql_cons a b x y h) | or_intror h => or_intror (eqlong L1 L2) (nff a b x y h) end end. rocq-9.2.0/test-suite/success/CaseAlias.v000066400000000000000000000050461516144147600202760ustar00rootroot00000000000000(*********************************************) (* This has been a bug reported by Y. Bertot *) Inductive expr : Set := | b : expr -> expr -> expr | u : expr -> expr | a : expr | var : nat -> expr. Fixpoint f (t : expr) : expr := match t with | b t1 t2 => b (f t1) (f t2) | a => a | x => b t a end. Fixpoint f2 (t : expr) : expr := match t with | b t1 t2 => b (f2 t1) (f2 t2) | a => a | x => b x a end. (*********************************************) (* Test expansion of aliases *) (* Originally taken from NMake_gen.v *) Local Notation SizePlus n := (S (S (S (S (S (S n)))))). Local Notation Size := (SizePlus O). Parameter zn2z : Type -> Type. Parameter w0 : Type. Fixpoint word (w : Type) (n : nat) {struct n} : Type := match n with | 0 => w | S n0 => zn2z (word w n0) end. Definition w1 := zn2z w0. Definition w2 := zn2z w1. Definition w3 := zn2z w2. Definition w4 := zn2z w3. Definition w5 := zn2z w4. Definition w6 := zn2z w5. Definition dom_t n := match n with | 0 => w0 | 1 => w1 | 2 => w2 | 3 => w3 | 4 => w4 | 5 => w5 | 6 => w6 | SizePlus n => word w6 n end. Parameter plus_t : forall n m : nat, word (dom_t n) m -> dom_t (m + n). (* This used to fail because of a bug in expansion of SizePlus wrongly reusing n as an alias for the subpattern *) Definition plus_t1 n : forall m, word (dom_t n) m -> dom_t (m+n) := match n return (forall m, word (dom_t n) m -> dom_t (m+n)) with | SizePlus (S n') as n => plus_t n | _ as n => fun m => match m return (word (dom_t n) m -> dom_t (m+n)) with | SizePlus (S (S m')) as m => plus_t n m | _ => fun x => x end end. (* Test (useless) intermediate alias *) Definition plus_t2 n : forall m, word (dom_t n) m -> dom_t (m+n) := match n return (forall m, word (dom_t n) m -> dom_t (m+n)) with | S (S (S (S (S (S (S n'))))) as n) as n'' => plus_t n'' | _ as n => fun m => match m return (word (dom_t n) m -> dom_t (m+n)) with | SizePlus (S (S m')) as m => plus_t n m | _ => fun x => x end end. (*****************************************************************************) (* Check that alias expansion behaves consistently from versions to versions *) Definition g m := match pred m with | 0 => 0 | n => n (* For compatibility, right-hand side should be (S n), not (pred m) *) end. Goal forall m, g m = match pred m with 0 => 0 | S n => S n end. intro; reflexivity. Abort. rocq-9.2.0/test-suite/success/CaseCumul.v000066400000000000000000000003651516144147600203310ustar00rootroot00000000000000Inductive boolΞ΅ : bool -> Type := | trueΞ΅ : boolΞ΅ true | falseΞ΅ : boolΞ΅ false. (* Check branch sort inference with implicit Prop βŠ† Type cumulativity *) Definition test (x : boolΞ΅ true) := match x with | trueΞ΅ => I | falseΞ΅ => tt end. rocq-9.2.0/test-suite/success/CaseInClause.v000066400000000000000000000020251516144147600207420ustar00rootroot00000000000000(* in clause pattern *) Require Import TestSuite.vector. Check (fun n (x: Vector.t True (S n)) => match x in Vector.t _ (S m) return True with |Vector.cons _ h _ _ => h end). (* Notation *) Notation "A \dots n" := (Vector.t A n) (at level 200). Check (fun m (x: Vector.t nat m) => match x in _ \dots k return Vector.t nat (S k) with | Vector.nil _ => Vector.cons _ 0 _ (Vector.nil _) | Vector.cons _ h _ t => Vector.cons _ h _ (Vector.cons _ h _ t) end). (* N should be a variable and not the inductiveRef *) Inductive N := Constr. Theorem foo : forall (n m : nat) (pf : n = m), match pf in _ = N with | eq_refl => unit end. Abort. (* Check redundant clause is removed *) Inductive I : nat * nat -> Type := C : I (0,0). Check fun x : I (1,1) => match x in I (y,z) return y = z with C => eq_refl end. (* An example of non-local inference of the type of an impossible case *) Check (fun y n (x:Vector.t nat (S n)) => match x with Vector.cons _ a _ _ => a | _ => y end) 2. rocq-9.2.0/test-suite/success/Cases.v000066400000000000000000001227301516144147600175070ustar00rootroot00000000000000(****************************************************************************) (* Pattern-matching when non inductive terms occur *) (* Dependent form of annotation *) Type match 0 as n, @eq return nat with | O, x => 0 | S x, y => x end. Type match 0, 0, @eq return nat with | O, x, y => 0 | S x, y, z => x end. Type match 0, @eq, 0 return _ with | O, x, y => 0 | S x, y, z => x end. (* Non dependent form of annotation *) Type match 0, @eq return nat with | O, x => 0 | S x, y => x end. (* Combining dependencies and non inductive arguments *) Type (fun (A : Set) (a : A) (H : 0 = 0) => match H in (_ = x), a return (H = H) with | _, _ => refl_equal H end). (* Interaction with coercions *) Parameter bool2nat : bool -> nat. Coercion bool2nat : bool >-> nat. Definition foo : nat -> nat := fun x => match x with | O => true | S _ => 0 end. (****************************************************************************) (* All remaining examples come from Cristina Cornes' V6 TESTS/MultCases.v *) Inductive IFExpr : Set := | Var : nat -> IFExpr | Tr : IFExpr | Fa : IFExpr | IfE : IFExpr -> IFExpr -> IFExpr -> IFExpr. Inductive List (A : Set) : Set := | Nil : List A | Cons : A -> List A -> List A. Inductive listn : nat -> Set := | niln : listn 0 | consn : forall n : nat, nat -> listn n -> listn (S n). Inductive Listn (A : Set) : nat -> Set := | Niln : Listn A 0 | Consn : forall n : nat, nat -> Listn A n -> Listn A (S n). Inductive Le : nat -> nat -> Set := | LeO : forall n : nat, Le 0 n | LeS : forall n m : nat, Le n m -> Le (S n) (S m). Inductive LE (n : nat) : nat -> Set := | LE_n : LE n n | LE_S : forall m : nat, LE n m -> LE n (S m). Inductive PropForm : Set := | Fvar : nat -> PropForm | Or : PropForm -> PropForm -> PropForm. Section testIFExpr. Definition Assign := nat -> bool. Parameter Prop_sem : Assign -> PropForm -> bool. Type (fun (A : Assign) (F : PropForm) => match F return bool with | Fvar n => A n | Or F G => orb (Prop_sem A F) (Prop_sem A G) end). Type (fun (A : Assign) (H : PropForm) => match H return bool with | Fvar n => A n | Or F G => orb (Prop_sem A F) (Prop_sem A G) end). End testIFExpr. Type (fun x : nat => match x return nat with | O => 0 | x => x end). Module Type testlist. Parameter A : Set. Inductive list : Set := | nil : list | cons : A -> list -> list. Parameter inf : A -> A -> Prop. Definition list_Lowert2 (a : A) (l : list) := match l return Prop with | nil => True | cons b l => inf a b end. Definition titi (a : A) (l : list) := match l return list with | nil => l | cons b l => l end. End testlist. (* To test translation *) (* ------------------- *) Type match 0 return nat with | O => 0 | _ => 0 end. Type match 0 return nat with | O as b => b | S O => 0 | S (S x) => x end. Type match 0 with | O as b => b | S O => 0 | S (S x) => x end. Type (fun x : nat => match x return nat with | O as b => b | S x => x end). Type (fun x : nat => match x with | O as b => b | S x => x end). Type match 0 return nat with | O as b => b | S x => x end. Type match 0 return nat with | x => x end. Type match 0 with | x => x end. Type match 0 return nat with | O => 0 | S x as b => b end. Type (fun x : nat => match x return nat with | O => 0 | S x as b => b end). Type (fun x : nat => match x with | O => 0 | S x as b => b end). Type match 0 return nat with | O => 0 | S x => 0 end. Type match 0 return (nat * nat) with | O => (0, 0) | S x => (x, 0) end. Type match 0 with | O => (0, 0) | S x => (x, 0) end. Type match 0 return (nat -> nat) with | O => fun n : nat => 0 | S x => fun n : nat => 0 end. Type match 0 with | O => fun n : nat => 0 | S x => fun n : nat => 0 end. Type match 0 return (nat -> nat) with | O => fun n : nat => 0 | S x => fun n : nat => x + n end. Type match 0 with | O => fun n : nat => 0 | S x => fun n : nat => x + n end. Type match 0 return nat with | O => 0 | S x as b => b + x end. Type match 0 return nat with | O => 0 | S a as b => b + a end. Type match 0 with | O => 0 | S a as b => b + a end. Type match 0 with | O => 0 | _ => 0 end. Type match 0 return nat with | O => 0 | x => x end. Type match 0, 1 return nat with | x, y => x + y end. Type match 0, 1 with | x, y => x + y end. Type match 0, 1 return nat with | O, y => y | S x, y => x + y end. Type match 0, 1 with | O, y => y | S x, y => x + y end. Type match 0, 1 return nat with | O, x => x | S y, O => y | x, y => x + y end. Type match 0, 1 with | O, x => x + 0 | S y, O => y + 0 | x, y => x + y end. Type match 0, 1 return nat with | O, x => x + 0 | S y, O => y + 0 | x, y => x + y end. Type match 0, 1 return nat with | O, x => x | S x as b, S y => b + x + y | x, y => x + y end. Type match 0, 1 with | O, x => x | S x as b, S y => b + x + y | x, y => x + y end. Type (fun l : List nat => match l return (List nat) with | Nil _ => Nil nat | Cons _ a l => l end). Type (fun l : List nat => match l with | Nil _ => Nil nat | Cons _ a l => l end). Type match Nil nat return nat with | Nil _ => 0 | Cons _ a l => S a end. Type match Nil nat with | Nil _ => 0 | Cons _ a l => S a end. Type match Nil nat return (List nat) with | Cons _ a l => l | x => x end. Type match Nil nat with | Cons _ a l => l | x => x end. Type match Nil nat return (List nat) with | Nil _ => Nil nat | Cons _ a l => l end. Type match Nil nat with | Nil _ => Nil nat | Cons _ a l => l end. Type match 0 return nat with | O => 0 | S x => match Nil nat return nat with | Nil _ => x | Cons _ a l => x + a end end. Type match 0 with | O => 0 | S x => match Nil nat with | Nil _ => x | Cons _ a l => x + a end end. Type (fun y : nat => match y with | O => 0 | S x => match Nil nat with | Nil _ => x | Cons _ a l => x + a end end). Type match 0, Nil nat return nat with | O, x => 0 | S x, Nil _ => x | S x, Cons _ a l => x + a end. Type (fun (n : nat) (l : listn n) => match l return nat with | niln => 0 | x => 0 end). Type (fun (n : nat) (l : listn n) => match l with | niln => 0 | x => 0 end). Type match niln return nat with | niln => 0 | x => 0 end. Type match niln with | niln => 0 | x => 0 end. Type match niln return nat with | niln => 0 | consn n a l => a end. Type match niln with | niln => 0 | consn n a l => a end. Type match niln in (listn n) return nat with | consn m _ niln => m | _ => 1 end. Type (fun (n x : nat) (l : listn n) => match x, l return nat with | O, niln => 0 | y, x => 0 end). Type match 0, niln return nat with | O, niln => 0 | y, x => 0 end. Type match niln, 0 return nat with | niln, O => 0 | y, x => 0 end. Type match niln, 0 with | niln, O => 0 | y, x => 0 end. Type match niln, niln return nat with | niln, niln => 0 | x, y => 0 end. Type match niln, niln with | niln, niln => 0 | x, y => 0 end. Type match niln, niln, niln return nat with | niln, niln, niln => 0 | x, y, z => 0 end. Type match niln, niln, niln with | niln, niln, niln => 0 | x, y, z => 0 end. Type match niln return nat with | niln => 0 | consn n a l => 0 end. Type match niln with | niln => 0 | consn n a l => 0 end. Type match niln, niln return nat with | niln, niln => 0 | niln, consn n a l => n | consn n a l, x => a end. Type match niln, niln with | niln, niln => 0 | niln, consn n a l => n | consn n a l, x => a end. Type (fun (n : nat) (l : listn n) => match l return nat with | niln => 0 | x => 0 end). Type (fun (c : nat) (s : bool) => match c, s return nat with | O, _ => 0 | _, _ => c end). Type (fun (c : nat) (s : bool) => match c, s return nat with | O, _ => 0 | S _, _ => c end). (* Rows of pattern variables: some tricky cases *) Axioms (P : nat -> Prop) (f : forall n : nat, P n). Type (fun i : nat => match true, i as n return (P n) with | true, k => f k | _, k => f k end). Type (fun i : nat => match i as n, true return (P n) with | k, true => f k | k, _ => f k end). (* Nested Cases: the SYNTH of the Cases on n used to make Multcase believe * it has to synthesize the predicate on O (which he can't) *) Type match 0 as n return match n with | O => bool | S _ => nat end with | O => true | S _ => 0 end. Type (fun (n : nat) (l : listn n) => match l with | niln => 0 | x => 0 end). Type (fun (n : nat) (l : listn n) => match l return nat with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end). Type (fun (n : nat) (l : listn n) => match l with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end). Type (fun (n : nat) (l : listn n) => match l return nat with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end). Type (fun (n : nat) (l : listn n) => match l with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l return nat with | Niln _ => 0 | Consn _ n a (Niln _) => 0 | Consn _ n a (Consn _ m b l) => n + m end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l with | Niln _ => 0 | Consn _ n a (Niln _) => 0 | Consn _ n a (Consn _ m b l) => n + m end). Type (fun (A:Set) (n:nat) (l:Listn A n) => match l return Listn A O with | Niln _ as b => b | Consn _ n a (Niln _ as b) => (Niln A) | Consn _ n a (Consn _ m b l) => (Niln A) end). (* Type (fun (A:Set) (n:nat) (l:Listn A n) => match l with | Niln _ as b => b | Consn _ n a (Niln _ as b) => (Niln A) | Consn _ n a (Consn _ m b l) => (Niln A) end). *) Type (fun (A:Set) (n:nat) (l:Listn A n) => match l return Listn A (S 0) with | Niln _ as b => Consn A O O b | Consn _ n a (Niln _) as L => L | Consn _ n a _ => Consn A O O (Niln A) end). Type (fun (A:Set) (n:nat) (l:Listn A n) => match l return Listn A (S 0) with | Niln _ as b => Consn A O O b | Consn _ n a (Niln _) as L => L | Consn _ n a _ => Consn A O O (Niln A) end). (* To test treatment of as-patterns in depth *) Type (fun (A : Set) (l : List A) => match l with | Nil _ as b => Nil A | Cons _ a (Nil _) as L => L | Cons _ a (Cons _ b m) as L => L end). Type (fun (n : nat) (l : listn n) => match l return (listn n) with | niln => l | consn n a c => l end). Type (fun (n : nat) (l : listn n) => match l with | niln => l | consn n a c => l end). Type (fun (n : nat) (l : listn n) => match l return (listn n) with | niln as b => l | _ => l end). Type (fun (n : nat) (l : listn n) => match l with | niln as b => l | _ => l end). Type (fun (n : nat) (l : listn n) => match l return (listn n) with | niln as b => l | x => l end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l with | Niln _ as b => l | _ => l end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l return (Listn A n) with | Niln _ => l | Consn _ n a (Niln _) => l | Consn _ n a (Consn _ m b c) => l end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l with | Niln _ => l | Consn _ n a (Niln _) => l | Consn _ n a (Consn _ m b c) => l end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l return (Listn A n) with | Niln _ as b => l | Consn _ n a (Niln _ as b) => l | Consn _ n a (Consn _ m b _) => l end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l with | Niln _ as b => l | Consn _ n a (Niln _ as b) => l | Consn _ n a (Consn _ m b _) => l end). Type match niln return nat with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end. Type match niln with | niln => 0 | consn n a niln => 0 | consn n a (consn m b l) => n + m end. Type match LeO 0 return nat with | LeO x => x | LeS n m h => n + m end. Type match LeO 0 with | LeO x => x | LeS n m h => n + m end. Type (fun (n : nat) (l : Listn nat n) => match l return nat with | Niln _ => 0 | Consn _ n a l => 0 end). Type (fun (n : nat) (l : Listn nat n) => match l with | Niln _ => 0 | Consn _ n a l => 0 end). Type match Niln nat with | Niln _ => 0 | Consn _ n a l => 0 end. Type match LE_n 0 return nat with | LE_n _ => 0 | LE_S _ m h => 0 end. Type match LE_n 0 with | LE_n _ => 0 | LE_S _ m h => 0 end. Type match LE_n 0 with | LE_n _ => 0 | LE_S _ m h => 0 end. Type match niln return nat with | niln => 0 | consn n a niln => n | consn n a (consn m b l) => n + m end. Type match niln with | niln => 0 | consn n a niln => n | consn n a (consn m b l) => n + m end. Type match Niln nat return nat with | Niln _ => 0 | Consn _ n a (Niln _ ) => n | Consn _ n a (Consn _ m b l) => n + m end. Type match Niln nat with | Niln _ => 0 | Consn _ n a (Niln _) => n | Consn _ n a (Consn _ m b l) => n + m end. Type match LeO 0 return nat with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + x end. Type match LeO 0 with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + x end. Type match LeO 0 return nat with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => m end. Type match LeO 0 with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => m end. Type (fun (n m : nat) (h : Le n m) => match h return nat with | LeO x => x | x => 0 end). Type (fun (n m : nat) (h : Le n m) => match h with | LeO x => x | x => 0 end). Type (fun (n m : nat) (h : Le n m) => match h return nat with | LeS n m h => n | x => 0 end). Type (fun (n m : nat) (h : Le n m) => match h with | LeS n m h => n | x => 0 end). Type (fun (n m : nat) (h : Le n m) => match h return (nat * nat) with | LeO n => (0, n) | LeS n m _ => (S n, S m) end). Type (fun (n m : nat) (h : Le n m) => match h with | LeO n => (0, n) | LeS n m _ => (S n, S m) end). Module Type F_v1. Fixpoint F (n m : nat) (h : Le n m) {struct h} : Le n (S m) := match h in (Le n m) return (Le n (S m)) with | LeO m' => LeO (S m') | LeS n' m' h' => LeS n' (S m') (F n' m' h') end. End F_v1. Module Type F_v2. Fixpoint F (n m : nat) (h : Le n m) {struct h} : Le n (S m) := match h in (Le n m) return (Le n (S m)) with | LeS n m h => LeS n (S m) (F n m h) | LeO m => LeO (S m) end. End F_v2. (* Rend la longueur de la liste *) Module Type L1. Definition length (n : nat) (l : listn n) := match l return nat with | consn n _ (consn m _ _) => S (S m) | consn n _ _ => 1 | _ => 0 end. End L1. Module Type L1'. Definition length (n : nat) (l : listn n) := match l with | consn n _ (consn m _ _) => S (S m) | consn n _ _ => 1 | _ => 0 end. End L1'. Module Type L2. Definition length (n : nat) (l : listn n) := match l return nat with | consn n _ (consn m _ _) => S (S m) | consn n _ _ => S n | _ => 0 end. End L2. Module Type L2'. Definition length (n : nat) (l : listn n) := match l with | consn n _ (consn m _ _) => S (S m) | consn n _ _ => S n | _ => 0 end. End L2'. Module Type L3. Definition length (n : nat) (l : listn n) := match l return nat with | consn n _ (consn m _ l) => S n | consn n _ _ => 1 | _ => 0 end. End L3. Module Type L3'. Definition length (n : nat) (l : listn n) := match l with | consn n _ (consn m _ l) => S n | consn n _ _ => 1 | _ => 0 end. End L3'. Type match LeO 0 return nat with | LeS n m h => n + m | x => 0 end. Type match LeO 0 with | LeS n m h => n + m | x => 0 end. Type (fun (n m : nat) (h : Le n m) => match h return nat with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + (m + (x + y)) end). Type (fun (n m : nat) (h : Le n m) => match h with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + (m + (x + y)) end). Type match LeO 0 return nat with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + (m + (x + y)) end. Type match LeO 0 with | LeO x => x | LeS n m (LeO x) => x + m | LeS n m (LeS x y h) => n + (m + (x + y)) end. Type match LE_n 0 return nat with | LE_n _ => 0 | LE_S _ m (LE_n _) => 0 + m | LE_S _ m (LE_S _ y h) => 0 + m end. Type match LE_n 0 with | LE_n _ => 0 | LE_S _ m (LE_n _) => 0 + m | LE_S _ m (LE_S _ y h) => 0 + m end. Type (fun (n m : nat) (h : Le n m) => match h with | x => x end). Type (fun (n m : nat) (h : Le n m) => match h return nat with | LeO n => n | x => 0 end). Type (fun (n m : nat) (h : Le n m) => match h with | LeO n => n | x => 0 end). Type (fun n : nat => match niln return (nat -> nat) with | niln => fun _ : nat => 0 | consn n a niln => fun _ : nat => 0 | consn n a (consn m b l) => fun _ : nat => n + m end). Type (fun n : nat => match niln with | niln => fun _ : nat => 0 | consn n a niln => fun _ : nat => 0 | consn n a (consn m b l) => fun _ : nat => n + m end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l return (nat -> nat) with | Niln _ => fun _ : nat => 0 | Consn _ n a (Niln _) => fun _ : nat => n | Consn _ n a (Consn _ m b l) => fun _ : nat => n + m end). Type (fun (A : Set) (n : nat) (l : Listn A n) => match l with | Niln _ => fun _ : nat => 0 | Consn _ n a (Niln _) => fun _ : nat => n | Consn _ n a (Consn _ m b l) => fun _ : nat => n + m end). (* Also tests for multiple _ patterns *) Type (fun (A : Set) (n : nat) (l : Listn A n) => match l in (Listn _ n) return (Listn A n) with | Niln _ as b => b | Consn _ _ _ _ as b => b end). (** This one was said to raised once an "Horrible error message!" *) Type (fun (A:Set) (n:nat) (l:Listn A n) => match l with | Niln _ as b => b | Consn _ _ _ _ as b => b end). Type match niln in (listn n) return (listn n) with | niln as b => b | consn _ _ _ as b => b end. Type match niln in (listn n) return (listn n) with | niln as b => b | x => x end. Type (fun (n m : nat) (h : LE n m) => match h return (nat -> nat) with | LE_n _ => fun _ : nat => n | LE_S _ m (LE_n _) => fun _ : nat => n + m | LE_S _ m (LE_S _ y h) => fun _ : nat => m + y end). Type (fun (n m : nat) (h : LE n m) => match h with | LE_n _ => fun _ : nat => n | LE_S _ m (LE_n _) => fun _ : nat => n + m | LE_S _ m (LE_S _ y h) => fun _ : nat => m + y end). Type (fun (n m : nat) (h : LE n m) => match h return nat with | LE_n _ => n | LE_S _ m (LE_n _) => n + m | LE_S _ m (LE_S _ y (LE_n _)) => n + m + y | LE_S _ m (LE_S _ y (LE_S _ y' h)) => n + m + (y + y') end). Type (fun (n m : nat) (h : LE n m) => match h with | LE_n _ => n | LE_S _ m (LE_n _) => n + m | LE_S _ m (LE_S _ y (LE_n _)) => n + m + y | LE_S _ m (LE_S _ y (LE_S _ y' h)) => n + m + (y + y') end). Type (fun (n m : nat) (h : LE n m) => match h return nat with | LE_n _ => n | LE_S _ m (LE_n _) => n + m | LE_S _ m (LE_S _ y h) => n + m + y end). Type (fun (n m : nat) (h : LE n m) => match h with | LE_n _ => n | LE_S _ m (LE_n _) => n + m | LE_S _ m (LE_S _ y h) => n + m + y end). Type (fun n m : nat => match LeO 0 return nat with | LeS n m h => n + m | x => 0 end). Type (fun n m : nat => match LeO 0 with | LeS n m h => n + m | x => 0 end). Parameter test : forall n : nat, {0 <= n} + {False}. Type (fun n : nat => match test n return nat with | left _ => 0 | _ => 0 end). Type (fun n : nat => match test n return nat with | left _ => 0 | _ => 0 end). Type (fun n : nat => match test n with | left _ => 0 | _ => 0 end). Parameter compare : forall n m : nat, {n < m} + {n = m} + {n > m}. Type match compare 0 0 return nat with (* k 0 (* k=i *) | inleft _ => 0 (* k>i *) | inright _ => 0 end. Type match compare 0 0 with (* k 0 (* k=i *) | inleft _ => 0 (* k>i *) | inright _ => 0 end. CoInductive SStream (A : Set) : (nat -> A -> Prop) -> Type := scons : forall (P : nat -> A -> Prop) (a : A), P 0 a -> SStream A (fun n : nat => P (S n)) -> SStream A P. Parameter B : Set. Type (fun (P : nat -> B -> Prop) (x : SStream B P) => match x return B with | scons _ _ a _ _ => a end). Type (fun (P : nat -> B -> Prop) (x : SStream B P) => match x with | scons _ _ a _ _ => a end). Type match (0, 0) return (nat * nat) with | (x, y) => (S x, S y) end. Type match (0, 0) return (nat * nat) with | (b, y) => (S b, S y) end. Type match (0, 0) return (nat * nat) with | (x, y) => (S x, S y) end. Type match (0, 0) with | (x, y) => (S x, S y) end. Type match (0, 0) with | (b, y) => (S b, S y) end. Type match (0, 0) with | (x, y) => (S x, S y) end. Module Type test_concat. Parameter concat : forall A : Set, List A -> List A -> List A. Type match Nil nat, Nil nat return (List nat) with | Nil _ as b, x => concat nat b x | Cons _ _ _ as d, Nil _ as c => concat nat d c | _, _ => Nil nat end. Type match Nil nat, Nil nat with | Nil _ as b, x => concat nat b x | Cons _ _ _ as d, Nil _ as c => concat nat d c | _, _ => Nil nat end. End test_concat. Inductive redexes : Set := | VAR : nat -> redexes | Fun : redexes -> redexes | Ap : bool -> redexes -> redexes -> redexes. Fixpoint regular (U : redexes) : Prop := match U return Prop with | VAR n => True | Fun V => regular V | Ap true (Fun _ as V) W => regular V /\ regular W | Ap true _ W => False | Ap false V W => regular V /\ regular W end. Type (fun n : nat => match n with | O => 0 | S (S n as V) => V | _ => 0 end). Parameter concat : forall n : nat, listn n -> forall m : nat, listn m -> listn (n + m). Type (fun (n : nat) (l : listn n) (m : nat) (l' : listn m) => match l in (listn n), l' return (listn (n + m)) with | niln, x => x | consn n a l'', x => consn (n + m) a (concat n l'' m x) end). Type (fun (x y z : nat) (H : x = y) (H0 : y = z) => match H return (x = z) with | refl_equal => match H0 in (_ = n) return (x = n) with | refl_equal => H end end). Type (fun h : False => match h return False with end). Type (fun h : False => match h return True with end). Definition is_zero (n : nat) := match n with | O => True | _ => False end. Type (fun (n : nat) (h : 0 = S n) => match h in (_ = n) return (is_zero n) with | refl_equal => I end). Definition disc (n : nat) (h : 0 = S n) : False := match h in (_ = n) return (is_zero n) with | refl_equal => I end. Definition nlength3 (n : nat) (l : listn n) := match l with | niln => 0 | consn O _ _ => 1 | consn (S n) _ _ => S (S n) end. (* == Testing strategy elimintation predicate synthesis == *) Section titi. Variable h : False. Type match 0 with | O => 0 | _ => except h end. End titi. Type match niln with | consn _ a niln => a | consn n _ x => 0 | niln => 0 end. Inductive wsort : Set := | ws : wsort | wt : wsort. Inductive TS : wsort -> Set := | id : TS ws | lift : TS ws -> TS ws. Type (fun (b : wsort) (M N : TS b) => match M, N with | lift M1, id => False | _, _ => True end). (* ===================================================================== *) (* To test pattern matching over a non-dependent inductive type, but *) (* having constructors with some arguments that depend on others *) (* I.e. to test manipulation of elimination predicate *) (* ===================================================================== *) Module Type test_term. Parameter LTERM : nat -> Set. Inductive TERM : Type := | var : TERM | oper : forall op : nat, LTERM op -> TERM. Parameter t1 t2 : TERM. Type match t1, t2 with | var, var => True | oper op1 l1, oper op2 l2 => False | _, _ => False end. End test_term. Require Import TestSuite.arith. Parameter n : nat. Definition eq_prf := exists m : _, n = m. Parameter p : eq_prf. Type match p with | ex_intro _ c eqc => match eq_nat_dec c n with | right _ => refl_equal n | left y => (* c=n*) refl_equal n end end. Parameter ordre_total : nat -> nat -> Prop. Parameter N_cla : forall N : nat, {N = 0} + {N = 1} + {N >= 2}. Parameter exist_U2 : forall N : nat, N >= 2 -> {n : nat | forall m : nat, 0 < m /\ m <= N /\ ordre_total n m /\ 0 < n /\ n < N}. Type (fun N : nat => match N_cla N with | inright H => match exist_U2 N H with | exist _ a b => a end | _ => 0 end). (* ============================================== *) (* To test compilation of dependent case *) (* Nested patterns *) (* ============================================== *) (* == To test that terms named with AS are correctly absolutized before substitution in rhs == *) Type (fun n : nat => match n return nat with | O => 0 | S O => 0 | S (S n1) as N => N end). (* ========= *) Type match niln in (listn n) return Prop with | niln => True | consn (S O) _ _ => False | _ => True end. Type match niln in (listn n) return Prop with | niln => True | consn (S (S O)) _ _ => False | _ => True end. Type match LeO 0 as h in (Le n m) return nat with | LeO _ => 0 | LeS (S x) _ _ => x | _ => 1 end. Type match LeO 0 as h in (Le n m) return nat with | LeO _ => 0 | LeS (S x) (S y) _ => x | _ => 1 end. Type match LeO 0 as h in (Le n m) return nat with | LeO _ => 0 | LeS (S x as b) (S y) _ => b | _ => 1 end. Module Type ff. Parameter ff : forall n m : nat, n <> m -> S n <> S m. Parameter discr_r : forall n : nat, 0 <> S n. Parameter discr_l : forall n : nat, S n <> 0. Type (fun n : nat => match n return (n = 0 \/ n <> 0) with | O => or_introl (0 <> 0) (refl_equal 0) | S x => or_intror (S x = 0) (discr_l x) end). Module Type eqdec. Fixpoint eqdec (n m : nat) {struct n} : n = m \/ n <> m := match n, m return (n = m \/ n <> m) with | O, O => or_introl (0 <> 0) (refl_equal 0) | O, S x => or_intror (0 = S x) (discr_r x) | S x, O => or_intror _ (discr_l x) | S x, S y => match eqdec x y return (S x = S y \/ S x <> S y) with | or_introl h => or_introl (S x <> S y) (f_equal S h) | or_intror h => or_intror (S x = S y) (ff x y h) end end. End eqdec. Module Type eqdec'. Fixpoint eqdec (n : nat) : forall m : nat, n = m \/ n <> m := match n return (forall m : nat, n = m \/ n <> m) with | O => fun m : nat => match m return (0 = m \/ 0 <> m) with | O => or_introl (0 <> 0) (refl_equal 0) | S x => or_intror (0 = S x) (discr_r x) end | S x => fun m : nat => match m return (S x = m \/ S x <> m) with | O => or_intror (S x = 0) (discr_l x) | S y => match eqdec x y return (S x = S y \/ S x <> S y) with | or_introl h => or_introl (S x <> S y) (f_equal S h) | or_intror h => or_intror (S x = S y) (ff x y h) end end end. End eqdec'. Inductive empty : forall n : nat, listn n -> Prop := intro_empty : empty 0 niln. Parameter inv_empty : forall (n a : nat) (l : listn n), ~ empty (S n) (consn n a l). Type (fun (n : nat) (l : listn n) => match l in (listn n) return (empty n l \/ ~ empty n l) with | niln => or_introl (~ empty 0 niln) intro_empty | consn n a y as b => or_intror (empty (S n) b) (inv_empty n a y) end). End ff. Module Type ff'. Parameter ff : forall n m : nat, n <> m -> S n <> S m. Parameter discr_r : forall n : nat, 0 <> S n. Parameter discr_l : forall n : nat, S n <> 0. Type (fun n : nat => match n return (n = 0 \/ n <> 0) with | O => or_introl (0 <> 0) (refl_equal 0) | S x => or_intror (S x = 0) (discr_l x) end). Module Type eqdec. Fixpoint eqdec (n m : nat) {struct n} : n = m \/ n <> m := match n, m return (n = m \/ n <> m) with | O, O => or_introl (0 <> 0) (refl_equal 0) | O, S x => or_intror (0 = S x) (discr_r x) | S x, O => or_intror _ (discr_l x) | S x, S y => match eqdec x y return (S x = S y \/ S x <> S y) with | or_introl h => or_introl (S x <> S y) (f_equal S h) | or_intror h => or_intror (S x = S y) (ff x y h) end end. End eqdec. Module Type eqdec'. Fixpoint eqdec (n : nat) : forall m : nat, n = m \/ n <> m := match n return (forall m : nat, n = m \/ n <> m) with | O => fun m : nat => match m return (0 = m \/ 0 <> m) with | O => or_introl (0 <> 0) (refl_equal 0) | S x => or_intror (0 = S x) (discr_r x) end | S x => fun m : nat => match m return (S x = m \/ S x <> m) with | O => or_intror (S x = 0) (discr_l x) | S y => match eqdec x y return (S x = S y \/ S x <> S y) with | or_introl h => or_introl (S x <> S y) (f_equal S h) | or_intror h => or_intror (S x = S y) (ff x y h) end end end. End eqdec'. End ff'. (* ================================================== *) (* Pour tester parametres *) (* ================================================== *) Inductive Empty (A : Set) : List A -> Prop := intro_Empty : Empty A (Nil A). Parameter inv_Empty : forall (A : Set) (a : A) (x : List A), ~ Empty A (Cons A a x). Type match Nil nat as l return (Empty nat l \/ ~ Empty nat l) with | Nil _ => or_introl (~ Empty nat (Nil nat)) (intro_Empty nat) | Cons _ a y => or_intror (Empty nat (Cons nat a y)) (inv_Empty nat a y) end. (* ================================================== *) (* Sur les listes *) (* ================================================== *) Inductive empty : forall n : nat, listn n -> Prop := intro_empty : empty 0 niln. Parameter inv_empty : forall (n a : nat) (l : listn n), ~ empty (S n) (consn n a l). Type (fun (n : nat) (l : listn n) => match l in (listn n) return (empty n l \/ ~ empty n l) with | niln => or_introl (~ empty 0 niln) intro_empty | consn n a y as b => or_intror (empty (S n) b) (inv_empty n a y) end). (* ===================================== *) (* Test parametros: *) (* ===================================== *) Inductive eqlong : List nat -> List nat -> Prop := | eql_cons : forall (n m : nat) (x y : List nat), eqlong x y -> eqlong (Cons nat n x) (Cons nat m y) | eql_nil : eqlong (Nil nat) (Nil nat). Parameter V1 : eqlong (Nil nat) (Nil nat) \/ ~ eqlong (Nil nat) (Nil nat). Parameter V2 : forall (a : nat) (x : List nat), eqlong (Nil nat) (Cons nat a x) \/ ~ eqlong (Nil nat) (Cons nat a x). Parameter V3 : forall (a : nat) (x : List nat), eqlong (Cons nat a x) (Nil nat) \/ ~ eqlong (Cons nat a x) (Nil nat). Parameter V4 : forall (a : nat) (x : List nat) (b : nat) (y : List nat), eqlong (Cons nat a x) (Cons nat b y) \/ ~ eqlong (Cons nat a x) (Cons nat b y). Type match Nil nat as x, Nil nat as y return (eqlong x y \/ ~ eqlong x y) with | Nil _, Nil _ => V1 | Nil _, Cons _ a x => V2 a x | Cons _ a x, Nil _ => V3 a x | Cons _ a x, Cons _ b y => V4 a x b y end. Type (fun x y : List nat => match x, y return (eqlong x y \/ ~ eqlong x y) with | Nil _, Nil _ => V1 | Nil _, Cons _ a x => V2 a x | Cons _ a x, Nil _ => V3 a x | Cons _ a x, Cons _ b y => V4 a x b y end). (* ===================================== *) Inductive Eqlong : forall n : nat, listn n -> forall m : nat, listn m -> Prop := | Eql_cons : forall (n m : nat) (x : listn n) (y : listn m) (a b : nat), Eqlong n x m y -> Eqlong (S n) (consn n a x) (S m) (consn m b y) | Eql_niln : Eqlong 0 niln 0 niln. Parameter W1 : Eqlong 0 niln 0 niln \/ ~ Eqlong 0 niln 0 niln. Parameter W2 : forall (n a : nat) (x : listn n), Eqlong 0 niln (S n) (consn n a x) \/ ~ Eqlong 0 niln (S n) (consn n a x). Parameter W3 : forall (n a : nat) (x : listn n), Eqlong (S n) (consn n a x) 0 niln \/ ~ Eqlong (S n) (consn n a x) 0 niln. Parameter W4 : forall (n a : nat) (x : listn n) (m b : nat) (y : listn m), Eqlong (S n) (consn n a x) (S m) (consn m b y) \/ ~ Eqlong (S n) (consn n a x) (S m) (consn m b y). Type match niln as x in (listn n), niln as y in (listn m) return (Eqlong n x m y \/ ~ Eqlong n x m y) with | niln, niln => W1 | niln, consn n a x => W2 n a x | consn n a x, niln => W3 n a x | consn n a x, consn m b y => W4 n a x m b y end. Type (fun (n m : nat) (x : listn n) (y : listn m) => match x in (listn n), y in (listn m) return (Eqlong n x m y \/ ~ Eqlong n x m y) with | niln, niln => W1 | niln, consn n a x => W2 n a x | consn n a x, niln => W3 n a x | consn n a x, consn m b y => W4 n a x m b y end). Parameter Inv_r : forall (n a : nat) (x : listn n), ~ Eqlong 0 niln (S n) (consn n a x). Parameter Inv_l : forall (n a : nat) (x : listn n), ~ Eqlong (S n) (consn n a x) 0 niln. Parameter Nff : forall (n a : nat) (x : listn n) (m b : nat) (y : listn m), ~ Eqlong n x m y -> ~ Eqlong (S n) (consn n a x) (S m) (consn m b y). Fixpoint Eqlongdec (n : nat) (x : listn n) (m : nat) (y : listn m) {struct x} : Eqlong n x m y \/ ~ Eqlong n x m y := match x in (listn n), y in (listn m) return (Eqlong n x m y \/ ~ Eqlong n x m y) with | niln, niln => or_introl (~ Eqlong 0 niln 0 niln) Eql_niln | niln, consn n a x as L => or_intror (Eqlong 0 niln (S n) L) (Inv_r n a x) | consn n a x as L, niln => or_intror (Eqlong (S n) L 0 niln) (Inv_l n a x) | consn n a x as L1, consn m b y as L2 => match Eqlongdec n x m y return (Eqlong (S n) L1 (S m) L2 \/ ~ Eqlong (S n) L1 (S m) L2) with | or_introl h => or_introl (~ Eqlong (S n) L1 (S m) L2) (Eql_cons n m x y a b h) | or_intror h => or_intror (Eqlong (S n) L1 (S m) L2) (Nff n a x m b y h) end end. (* ============================================== *) (* To test compilation of dependent case *) (* Multiple Patterns *) (* ============================================== *) Inductive skel : Type := | PROP : skel | PROD : skel -> skel -> skel. Parameter Can : skel -> Type. Parameter default_can : forall s : skel, Can s. Type (fun s1 s2 s1 s2 : skel => match s1, s2 return (Can s1) with | PROP, PROP => default_can PROP | PROD x y, PROP => default_can (PROD x y) | PROD x y, _ => default_can (PROD x y) | PROP, _ => default_can PROP end). (* to test bindings in nested Cases *) (* ================================ *) Inductive Pair : Set := | pnil : Pair | pcons : Pair -> Pair -> Pair. Type (fun p q : Pair => match p with | pcons _ x => match q with | pcons _ (pcons _ x) => True | _ => False end | _ => False end). Type (fun p q : Pair => match p with | pcons _ x => match q with | pcons _ (pcons _ x) => match q with | pcons _ (pcons _ (pcons _ x)) => x | _ => pnil end | _ => pnil end | _ => pnil end). Type (fun (n : nat) (l : listn (S n)) => match l in (listn z) return (listn (pred z)) with | niln => niln | consn n _ l => match l in (listn m) return (listn m) with | niln => niln | b => b end end). (* Test de la syntaxe avec nombres *) Type (fun n => match n with | S (S O) => true | _ => false end). Require Import TestSuite.binpos. Inductive Z := Z0 | Zpos : positive -> Z | Zneg : positive -> Z. Type (fun n => match n with | Z0 => true | _ => false end). (* Check that types with unknown sort, as A below, are not fatal to the pattern-matching compilation *) Definition transport {A} (P : A->Type) {x y : A} (p : x=y) (u : P x) : P y := match p with eq_refl => u end. (* Check in-pattern clauses with constant constructors, which were previously interpreted as variables (before 8.5) *) Check match eq_refl 0 in _=O return O=O with eq_refl => eq_refl end. Check match niln in listn O return O=O with niln => eq_refl end. (* A test about nested "as" clauses *) (* (was failing up to May 2017) *) Check fun x => match x with (y,z) as t as w => (y+z,t) = (0,w) end. (* A test about binding variables of "in" clause of "match" *) (* (was failing from 8.5 to Dec 2018) *) Check match O in nat return nat with O => O | _ => O end. (* Checking that aliases are substituted in the correct order *) Check match eq_refl (1,0) in _ = (y as z, y' as z) return z = z with eq_refl => eq_refl end : 0=0. (* Checking use of argument scopes *) Module Intern. Inductive I (A:Type) := C : nat -> let a:=0 in bool -> list bool -> bool -> I A. Close Scope nat_scope. Notation "0" := true : bool_scope. Notation "0" := nil : list_scope. Notation C' := @C (only parsing). Notation C'' := C (only parsing). Notation C''' := (C _ 0) (only parsing). Set Asymmetric Patterns. Check fun x => match x with C 0 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C 0 _ 0 0 0 => O | _ => O end. (* was not supported *) Check fun x => match x with C' 0 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C' _ 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C' 0 _ 0 0 0 => O | _ => O end. (* was not supported *) Check fun x => match x with C' _ _ 0 0 0 => O | _ => O end. (* was pre 8.5 bug *) Check fun x => match x with C'' 0 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C'' _ 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C'' 0 _ 0 0 0 => O | _ => O end. (* was not supported *) Check fun x => match x with C'' _ _ 0 0 0 => O | _ => O end. (* was pre 8.5 bug *) Check fun x => match x with C''' 0 0 0 => O | _ => O end. (* 8.5 regression *) Check fun x => match x with C''' _ 0 0 0 => O | _ => O end. (* was not supported *) Unset Asymmetric Patterns. Arguments C {A} _ {x} _ _. Check fun x => match x with C 0 0 0 => O | _ => O end. (* was ok *) Check fun x => match x with C 0 _ 0 0 => O | _ => O end. (* was wrong scope on last argument with let-in *) Check fun x => match x with C' _ 0 _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with C' _ 0 _ 0 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with C'' _ 0 0 => O | _ => O end. (* was ok *) Check fun x => match x with C'' _ _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with C''' 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with C''' _ 0 0 => O | _ => O end. (* works by miscount compensating *) Check fun x => match x with (@C _ 0) _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with (@C _ 0) _ _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with @C _ 0 _ 0 0 => O | _ => O end. (* was ok *) Check fun x => match x with @C _ 0 _ _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with (@C) _ O _ 0 0 => O | _ => O end. (* was wrong scope *) Check fun x => match x with (@C) _ O _ _ 0 0 => O | _ => O end. (* was wrong scope *) End Intern. rocq-9.2.0/test-suite/success/CasesDep.v000066400000000000000000000342331516144147600201400ustar00rootroot00000000000000(* Check forward dependencies *) Check (fun (P : nat -> Prop) Q (A : P 0 -> Q) (B : forall n : nat, P (S n) -> Q) x => match x return Q with | exist _ O H => A H | exist _ (S n) H => B n H end). (* Check dependencies in anonymous arguments (from FTA/listn.v) *) Inductive listn (A : Set) : nat -> Set := | niln : listn A 0 | consn : forall (a : A) (n : nat), listn A n -> listn A (S n). Section Folding. Variable B C : Set. Variable g : B -> C -> C. Variable c : C. Fixpoint foldrn (n : nat) (bs : listn B n) {struct bs} : C := match bs with | niln _ => c | consn _ b _ tl => g b (foldrn _ tl) end. End Folding. (** Testing post-processing of nested dependencies *) Check fun x:{x|x=0}*nat+nat => match x with | inl ((exist _ 0 eq_refl),0) => None | _ => Some 0 end. Check fun x:{_:{x|x=0}|True}+nat => match x with | inl (exist _ (exist _ 0 eq_refl) I) => None | _ => Some 0 end. Check fun x:{_:{x|x=0}|True}+nat => match x with | inl (exist _ (exist _ 0 eq_refl) I) => None | _ => Some 0 end. Check fun x:{_:{x|x=0}|True}+nat => match x return option nat with | inl (exist _ (exist _ 0 eq_refl) I) => None | _ => Some 0 end. (* the next two examples were failing from r14703 (Nov 22 2011) to r14732 *) (* due to a bug in dependencies postprocessing (revealed by CoLoR) *) Check fun x:{x:nat*nat|fst x = 0 & True} => match x return option nat with | exist2 _ _ (x,y) eq_refl I => None end. Check fun x:{_:{x:nat*nat|fst x = 0 & True}|True}+nat => match x return option nat with | inl (exist _ (exist2 _ _ (x,y) eq_refl I) I) => None | _ => Some 0 end. (* -------------------------------------------------------------------- *) (* Example to test patterns matching on dependent families *) (* This exemple extracted from the development done by Nacira Chabane *) (* (equipe Paris 6) *) (* -------------------------------------------------------------------- *) Require Import Prelude. Section Orderings. Variable U : Type. Definition Relation := U -> U -> Prop. Variable R : Relation. Definition Reflexive : Prop := forall x : U, R x x. Definition Transitive : Prop := forall x y z : U, R x y -> R y z -> R x z. Definition Symmetric : Prop := forall x y : U, R x y -> R y x. Definition Antisymmetric : Prop := forall x y : U, R x y -> R y x -> x = y. Definition contains (R R' : Relation) : Prop := forall x y : U, R' x y -> R x y. Definition same_relation (R R' : Relation) : Prop := contains R R' /\ contains R' R. Inductive Equivalence : Prop := Build_Equivalence : Reflexive -> Transitive -> Symmetric -> Equivalence. Inductive PER : Prop := Build_PER : Symmetric -> Transitive -> PER. End Orderings. (***** Setoid *******) Inductive Setoid : Type := Build_Setoid : forall (S : Type) (R : Relation S), Equivalence _ R -> Setoid. Definition elem (A : Setoid) := let (S, R, e) := A in S. Definition equal (A : Setoid) := let (S, R, e) as s return (Relation (elem s)) := A in R. Axiom prf_equiv : forall A : Setoid, Equivalence (elem A) (equal A). Axiom prf_refl : forall A : Setoid, Reflexive (elem A) (equal A). Axiom prf_sym : forall A : Setoid, Symmetric (elem A) (equal A). Axiom prf_trans : forall A : Setoid, Transitive (elem A) (equal A). Section Maps. Variable A B : Setoid. Definition Map_law (f : elem A -> elem B) := forall x y : elem A, equal _ x y -> equal _ (f x) (f y). Inductive Map : Type := Build_Map : forall (f : elem A -> elem B) (p : Map_law f), Map. Definition explicit_ap (m : Map) := match m return (elem A -> elem B) with | Build_Map f p => f end. Axiom pres : forall m : Map, Map_law (explicit_ap m). Definition ext (f g : Map) := forall x : elem A, equal _ (explicit_ap f x) (explicit_ap g x). Axiom Equiv_map_eq : Equivalence Map ext. Definition Map_setoid := Build_Setoid Map ext Equiv_map_eq. End Maps. Notation ap := (explicit_ap _ _). (* : Grammar is replaced by Notation *) Definition ap2 (A B C : Setoid) (f : elem (Map_setoid A (Map_setoid B C))) (a : elem A) := ap (ap f a). (***** posint ******) Inductive posint : Type := | Z : posint | Suc : posint -> posint. Axiom f_equal : forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y. Axiom eq_Suc : forall n m : posint, n = m -> Suc n = Suc m. (* The predecessor function *) Definition pred (n : posint) : posint := match n return posint with | Z => (* Z *) Z (* Suc u *) | Suc u => u end. Axiom pred_Sucn : forall m : posint, m = pred (Suc m). Axiom eq_add_Suc : forall n m : posint, Suc n = Suc m -> n = m. Axiom not_eq_Suc : forall n m : posint, n <> m -> Suc n <> Suc m. Definition IsSuc (n : posint) : Prop := match n return Prop with | Z => (* Z *) False (* Suc p *) | Suc p => True end. Definition IsZero (n : posint) : Prop := match n with | Z => True | Suc _ => False end. Axiom Z_Suc : forall n : posint, Z <> Suc n. Axiom Suc_Z : forall n : posint, Suc n <> Z. Axiom n_Sucn : forall n : posint, n <> Suc n. Axiom Sucn_n : forall n : posint, Suc n <> n. Axiom eqT_symt : forall a b : posint, a <> b -> b <> a. (******* Dsetoid *****) Definition Decidable (A : Type) (R : Relation A) := forall x y : A, R x y \/ ~ R x y. Record DSetoid : Type := {Set_of : Setoid; prf_decid : Decidable (elem Set_of) (equal Set_of)}. (* example de Dsetoide d'entiers *) Axiom eqT_equiv : Equivalence posint (eq (A:=posint)). Axiom Eq_posint_deci : Decidable posint (eq (A:=posint)). (* Dsetoide des posint*) Definition Set_of_posint := Build_Setoid posint (eq (A:=posint)) eqT_equiv. Definition Dposint := Build_DSetoid Set_of_posint Eq_posint_deci. (**************************************) (* Definition des signatures *) (* une signature est un ensemble d'operateurs muni de l'arite de chaque operateur *) Module Sig. Record Signature : Type := {Sigma : DSetoid; Arity : Map (Set_of Sigma) (Set_of Dposint)}. Parameter S : Signature. Parameter Var : DSetoid. Inductive TERM : Type := | var : elem (Set_of Var) -> TERM | oper : forall op : elem (Set_of (Sigma S)), LTERM (ap (Arity S) op) -> TERM with LTERM : posint -> Type := | nil : LTERM Z | cons : TERM -> forall n : posint, LTERM n -> LTERM (Suc n). (* -------------------------------------------------------------------- *) (* Examples *) (* -------------------------------------------------------------------- *) Parameter t1 t2 : TERM. Type match t1, t2 with | var v1, var v2 => True | oper op1 l1, oper op2 l2 => False | _, _ => False end. Parameter n2 : posint. Parameter l1 l2 : LTERM n2. Type match l1, l2 with | nil, nil => True | cons v m y, nil => False | _, _ => False end. Type match l1, l2 with | nil, nil => True | cons u n x, cons v m y => False | _, _ => False end. Module Type Version1. Definition equalT (t1 t2 : TERM) : Prop := match t1, t2 with | var v1, var v2 => True | oper op1 l1, oper op2 l2 => False | _, _ => False end. Definition EqListT (n1 : posint) (l1 : LTERM n1) (n2 : posint) (l2 : LTERM n2) : Prop := match l1, l2 with | nil, nil => True | cons t1 n1' l1', cons t2 n2' l2' => False | _, _ => False end. End Version1. (* ------------------------------------------------------------------*) (* Initial example (without patterns) *) (*-------------------------------------------------------------------*) Module Version2. Fixpoint equalT (t1 : TERM) : TERM -> Prop := match t1 return (TERM -> Prop) with | var v1 => (*var*) fun t2 : TERM => match t2 return Prop with | var v2 => (*var*) equal _ v1 v2 (*oper*) | oper op2 _ => False end (*oper*) | oper op1 l1 => fun t2 : TERM => match t2 return Prop with | var v2 => (*var*) False (*oper*) | oper op2 l2 => equal _ op1 op2 /\ EqListT (ap (Arity S) op1) l1 (ap (Arity S) op2) l2 end end with EqListT (n1 : posint) (l1 : LTERM n1) {struct l1} : forall n2 : posint, LTERM n2 -> Prop := match l1 in (LTERM _) return (forall n2 : posint, LTERM n2 -> Prop) with | nil => (*nil*) fun (n2 : posint) (l2 : LTERM n2) => match l2 in (LTERM _) return Prop with | nil => (*nil*) True (*cons*) | cons t2 n2' l2' => False end (*cons*) | cons t1 n1' l1' => fun (n2 : posint) (l2 : LTERM n2) => match l2 in (LTERM _) return Prop with | nil => (*nil*) False (*cons*) | cons t2 n2' l2' => equalT t1 t2 /\ EqListT n1' l1' n2' l2' end end. End Version2. (* ---------------------------------------------------------------- *) (* Version with simple patterns *) (* ---------------------------------------------------------------- *) Module Version3. Fixpoint equalT (t1 : TERM) : TERM -> Prop := match t1 with | var v1 => fun t2 : TERM => match t2 with | var v2 => equal _ v1 v2 | oper op2 _ => False end | oper op1 l1 => fun t2 : TERM => match t2 with | var _ => False | oper op2 l2 => equal _ op1 op2 /\ EqListT (ap (Arity S) op1) l1 (ap (Arity S) op2) l2 end end with EqListT (n1 : posint) (l1 : LTERM n1) {struct l1} : forall n2 : posint, LTERM n2 -> Prop := match l1 return (forall n2 : posint, LTERM n2 -> Prop) with | nil => fun (n2 : posint) (l2 : LTERM n2) => match l2 with | nil => True | _ => False end | cons t1 n1' l1' => fun (n2 : posint) (l2 : LTERM n2) => match l2 with | nil => False | cons t2 n2' l2' => equalT t1 t2 /\ EqListT n1' l1' n2' l2' end end. End Version3. Module Version4. Fixpoint equalT (t1 : TERM) : TERM -> Prop := match t1 with | var v1 => fun t2 : TERM => match t2 with | var v2 => equal _ v1 v2 | oper op2 _ => False end | oper op1 l1 => fun t2 : TERM => match t2 with | var _ => False | oper op2 l2 => equal _ op1 op2 /\ EqListT (ap (Arity S) op1) l1 (ap (Arity S) op2) l2 end end with EqListT (n1 : posint) (l1 : LTERM n1) (n2 : posint) (l2 : LTERM n2) {struct l1} : Prop := match l1 with | nil => match l2 with | nil => True | _ => False end | cons t1 n1' l1' => match l2 with | nil => False | cons t2 n2' l2' => equalT t1 t2 /\ EqListT n1' l1' n2' l2' end end. End Version4. (* ---------------------------------------------------------------- *) (* Version with multiple patterns *) (* ---------------------------------------------------------------- *) Module Version5. Fixpoint equalT (t1 t2 : TERM) {struct t1} : Prop := match t1, t2 with | var v1, var v2 => equal _ v1 v2 | oper op1 l1, oper op2 l2 => equal _ op1 op2 /\ EqListT (ap (Arity S) op1) l1 (ap (Arity S) op2) l2 | _, _ => False end with EqListT (n1 : posint) (l1 : LTERM n1) (n2 : posint) (l2 : LTERM n2) {struct l1} : Prop := match l1, l2 with | nil, nil => True | cons t1 n1' l1', cons t2 n2' l2' => equalT t1 t2 /\ EqListT n1' l1' n2' l2' | _, _ => False end. End Version5. (* ------------------------------------------------------------------ *) End Sig. (* Exemple soumis par Bruno *) Definition bProp (b : bool) : Prop := if b then True else False. Definition f0 (F : False) (ty : bool) : bProp ty := match ty as _, ty return (bProp ty) with | true, true => I | _, false => F | _, true => I end. (* Simplification of bug/wish #1671 *) Inductive I : unit -> Type := | C : forall a, I a -> I tt. (* Definition F (l:I tt) : l = l := match l return l = l with | C tt (C _ l') => refl_equal (C tt (C _ l')) end. one would expect that the compilation of F (this involves some kind of pattern-unification) would produce: *) Definition F (l:I tt) : l = l := match l return l = l with | C tt l' => match l' return C _ l' = C _ l' with C _ l'' => refl_equal (C tt (C _ l'')) end end. Inductive J : nat -> Type := | D : forall a, J (S a) -> J a. (* Definition G (l:J O) : l = l := match l return l = l with | D O (D 1 l') => refl_equal (D O (D 1 l')) | D _ _ => refl_equal _ end. one would expect that the compilation of G (this involves inversion) would produce: *) Definition G (l:J O) : l = l := match l return l = l with | D 0 l'' => match l'' as _l'' in J n return match n return forall l:J n, Prop with | O => fun _ => l = l | S p => fun l'' => D p l'' = D p l'' end _l'' with | D 1 l' => refl_equal (D O (D 1 l')) | _ => refl_equal _ end | _ => refl_equal _ end. Fixpoint app {A} {n m} (v : listn A n) (w : listn A m) : listn A (n + m) := match v with | niln _ => w | consn _ a n' v' => consn _ a _ (app v' w) end. (* Testing regression of bug 2106 *) Set Implicit Arguments. Inductive nt := E. Definition root := E. Inductive ctor : list nt -> nt -> Type := Plus : ctor (cons E (cons E nil)) E. Inductive term : nt -> Type := | Term : forall s n, ctor s n -> spine s -> term n with spine : list nt -> Type := | EmptySpine : spine nil | ConsSpine : forall n s, term n -> spine s -> spine (n :: s). Inductive step : nt -> nt -> Type := | Step : forall l n r n' (c:ctor (l++n::r) n'), spine l -> spine r -> step n n'. Definition test (s:step E E) := match s with | @Step nil _ (cons E nil) _ Plus l l' => true | _ => false end. (* Testing regression of bug 2454 ("get" used not be type-checkable when defined with its type constraint) *) Inductive K : nat -> Type := KC : forall (p q:nat), K p. Definition get : K O -> nat := fun x => match x with KC p q => q end. (* Checking correct order of substitution of realargs *) (* (was broken from revision 14664 to 14669) *) (* Example extracted from contrib CoLoR *) Inductive EQ : nat -> nat -> Prop := R x y : EQ x y. Check fun e t (d1 d2:EQ e t) => match d1 in EQ e1 t1, d2 in EQ e2 t2 return (e1,t1) = (e2,t2) -> (e1,t1) = (e,t) -> 0=0 with | R _ _, R _ _ => fun _ _ => eq_refl end. rocq-9.2.0/test-suite/success/Cases_bug1834.v000066400000000000000000000005761516144147600206670ustar00rootroot00000000000000(* Bug in the computation of generalization *) (* The following bug, elaborated by Bruno Barras, is solved from r11083 *) Parameter P : unit -> Prop. Definition T := sig P. Parameter Q : T -> Prop. Definition U := sig Q. Parameter a : U. Check (match a with exist _ (exist _ tt e2) e3 => e3=e3 end). (* There is still a form submitted by Pierre Corbineau (#1834) which fails *) rocq-9.2.0/test-suite/success/Cases_bug3758.v000066400000000000000000000005311516144147600206650ustar00rootroot00000000000000(* There used to be an evar leak in the to_nat example *) Fixpoint Idx {A:Type} (l:list A) : Type := match l with | nil => False | cons _ l => True + Idx l end. Fixpoint to_nat {A:Type} (l:list A) (i:Idx l) : nat := match l,i with | nil , i => match i with end | cons _ _, inl _ => 0 | cons _ l, inr i => S (to_nat l i) end. rocq-9.2.0/test-suite/success/Check.v000066400000000000000000000017041516144147600174630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Type := | evenO : even x 0 | evenS : forall n, odd x n -> even x (S n) with odd (x : bool) : nat -> Type := | oddS : forall n, even x n -> odd x (S n). Scheme even_ind_prop := Induction for even Sort Prop with odd_ind_prop := Induction for odd Sort Prop. Combined Scheme even_cprop from even_ind_prop, odd_ind_prop. Check even_cprop : forall (x : bool) (P : forall n : nat, even x n -> Prop) (P0 : forall n : nat, odd x n -> Prop), P 0 (evenO x) -> (forall (n : nat) (o : odd x n), P0 n o -> P (S n) (evenS x n o)) -> (forall (n : nat) (e : even x n), P n e -> P0 (S n) (oddS x n e)) -> (forall (n : nat) (e : even x n), P n e) /\ (forall (n : nat) (o : odd x n), P0 n o). Scheme even_ind_type := Induction for even Sort Type with odd_ind_type := Induction for odd Sort Type. (* This didn't work in v8.7 *) Combined Scheme even_ctype from even_ind_type, odd_ind_type. Check even_ctype : forall (x : bool) (P : forall n : nat, even x n -> Prop) (P0 : forall n : nat, odd x n -> Prop), P 0 (evenO x) -> (forall (n : nat) (o : odd x n), P0 n o -> P (S n) (evenS x n o)) -> (forall (n : nat) (e : even x n), P n e -> P0 (S n) (oddS x n e)) -> (forall (n : nat) (e : even x n), P n e) * (forall (n : nat) (o : odd x n), P0 n o). rocq-9.2.0/test-suite/success/Conjecture.v000066400000000000000000000003471516144147600205510ustar00rootroot00000000000000(* Check keywords Conjecture and Admitted are recognized *) Conjecture c : forall n : nat, n = 0. Check c. Theorem d : forall n : nat, n = 0. Proof. induction n. reflexivity. assert (H : False). 2: destruct H. Admitted. rocq-9.2.0/test-suite/success/ConversionOrder.v000066400000000000000000000010011516144147600215550ustar00rootroot00000000000000(* The kernel may convert application arguments right to left, resulting in ill-typed terms, but should be robust to them. *) Inductive Hide := hide : forall A, A -> Hide. Lemma foo : (hide Type Type) = (hide (nat -> Type) (fun x : nat => Type)). Proof. Fail reflexivity. match goal with |- ?l = _ => exact_no_check (eq_refl l) end. Fail Defined. Abort. Definition HideMore (_:Hide) := 0. Definition foo : HideMore (hide Type Type) = HideMore (hide (nat -> Type) (fun x : nat => Type)) := eq_refl. rocq-9.2.0/test-suite/success/CumulInd.v000066400000000000000000000033671516144147600201750ustar00rootroot00000000000000 (* variances other than Invariant are forbidden for non-cumul inductives *) Fail Inductive foo@{+u} : Prop := . Fail Polymorphic Inductive foo@{*u} : Prop := . Inductive foo@{=u} : Prop := . (* Cumulative attr forbidden without univ poly on *) Fail Cumulative Inductive bar@{u} : Prop := . (* option allowed but does nothing until univ poly is on *) Set Polymorphic Inductive Cumulativity. Fail Inductive bar@{*u} : Prop := . Succeed Polymorphic Inductive bar@{*u} : Prop := . Set Universe Polymorphism. Set Polymorphic Inductive Cumulativity. Inductive force_invariant@{=u} : Prop := . Fail Definition lift@{u v | u < v} (x:force_invariant@{u}) : force_invariant@{v} := x. Inductive force_covariant@{+u} : Prop := . Fail Definition lift@{u v | v < u} (x:force_covariant@{u}) : force_covariant@{v} := x. Definition lift@{u v | u < v} (x:force_covariant@{u}) : force_covariant@{v} := x. Fail Inductive not_irrelevant@{*u} : Prop := nirr (_ : Type@{u}). Inductive check_covariant@{+u} : Prop := cov (_ : Type@{u}). Fail Inductive not_covariant@{+u} : Prop := ncov (_ : Type@{u} -> nat). Inductive must_unfold@{+u *v} : Prop := cmust (_ : @id Type@{v} Type@{u}). Inductive actually_default_unfold@{u v} : Prop := cnodef (_ : @id Type@{v} Type@{u}). Inductive actually_default_unfold_check@{+u *v} : Prop := cnodef_check (_ : actually_default_unfold@{u v}). Inductive irrelevant@{*u} : Prop := . (* weak constraints help minimization *) Definition irrelevant_with_weak@{u} : irrelevant@{u} -> irrelevant := fun x => x. Unset Cumulativity Weak Constraints. Fail Definition irrelevant_without_weak@{u} : irrelevant@{u} -> irrelevant := fun x => x. Definition irrelevant_without_weak@{u+} : irrelevant@{u} -> irrelevant := fun x => x. Check irrelevant_without_weak@{_ _}. rocq-9.2.0/test-suite/success/DHyp.v000066400000000000000000000000011516144147600172770ustar00rootroot00000000000000 rocq-9.2.0/test-suite/success/Decompose.v000066400000000000000000000003321516144147600203600ustar00rootroot00000000000000(* This was a Decompose bug reported by Randy Pollack (29 Mar 2000) *) Goal 0 = 0 /\ (forall x : nat, x = x -> x = x /\ (forall y : nat, y = y -> y = y)) -> True. intro H. decompose [and] H. (* Was failing *) Abort. rocq-9.2.0/test-suite/success/DependentPropositionEliminators.v000066400000000000000000000002401516144147600250230ustar00rootroot00000000000000 Set Dependent Proposition Eliminators. Inductive bar : Prop := XBAR | YBAR. Check bar_ind : forall P : bar -> Prop, P XBAR -> P YBAR -> forall b : bar, P b. rocq-9.2.0/test-suite/success/Derive.v000066400000000000000000000023411516144147600176620ustar00rootroot00000000000000Module M. (* The encapsulation in a module tests that the grammar rules and keywords are correctly registered *) Require Derive. End M. (* Tests when x is refined by typechecking *) Derive x in (eq_refl x = eq_refl 0) as x_ok. reflexivity. Qed. Derive s in (forall z, eq_refl (s z) = eq_refl (S z)) as s_ok. reflexivity. Qed. Derive foo : nat in (foo = foo) as bar. Proof. reflexivity. Unshelve. exact 0. Qed. Derive id : (forall {A}, A -> A) in (forall {A} (a:A), id a = a) as spec. Proof. unfold id. reflexivity. Qed. About id. Check id 0. Set Universe Polymorphism. (* An example with no polymorphic universe constraints in the witness *) Derive id' : (forall {A}, A -> A) in (forall {A} (a:A), id' a = a) as spec'. Proof. Unshelve. 2: exact (fun A a => a). reflexivity. Qed. (* An example with polymorphic universe constraints in the witness *) Derive id'' : (forall {A}, A -> A) in (forall {A} (a:A), id'' a = a) as spec''. Proof. unfold id''. reflexivity. Qed. Check id'@{Set} 0. (* Test dependent types - issue fix *) Derive (X : Type) (l : list X) in (l = l) as foo_dep. exact (eq_refl (@nil unit)). Defined. (* goal naming *) Derive (X' : Type) in X' as X'_val. Proof. [X']: exact nat. Fail exact true. exact 0. Defined. rocq-9.2.0/test-suite/success/DisableVM.v000066400000000000000000000002421516144147600202500ustar00rootroot00000000000000(* -*- coq-prog-args: ("-bytecode-compiler" "no"); -*- *) Eval lazy in 0. Eval vm_compute in 0. Set Warnings "+vm-compute-disabled". Fail Eval vm_compute in 0. rocq-9.2.0/test-suite/success/Discriminate.v000066400000000000000000000014661516144147600210660ustar00rootroot00000000000000(* Check the behaviour of Discriminate *) (* Check that Discriminate tries Intro until *) Lemma l1 : 0 = 1 -> False. discriminate 1. Qed. Lemma l2 : forall H : 0 = 1, H = H. discriminate H. Qed. (* Check the variants of discriminate *) Goal O = S O -> True. discriminate 1. Undo. intros. discriminate H. Undo. Ltac g x := discriminate x. g H. Abort. Goal (forall x y : nat, x = y -> x = S y) -> True. intros. try discriminate (H O) || exact I. Qed. Goal (forall x y : nat, x = y -> x = S y) -> True. intros. ediscriminate (H O). instantiate (1:=O). Abort. (* Check discriminate on identity *) Goal ~ identity 0 1. discriminate. Qed. (* Check discriminate on types with local definitions *) Inductive A := B (T := unit) (x y : bool) (z := x). Goal forall x y, B x true = B y false -> False. discriminate. Qed. rocq-9.2.0/test-suite/success/Discriminate_HoTT.v000066400000000000000000000053631516144147600217640ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-noinit" "-indices-matter") -*- *) (* This file tests the discriminate tactic compatibility with HoTT. The first part of the file will setup a mini HoTT environment. Afterwards a number of tests are performed. The tests are basically copied from the Discriminate.v test file. *) Unset Elimination Schemes. Set Universe Polymorphism. Require Import Equality. Declare ML Module "rocq-runtime.plugins.ltac". Global Set Default Proof Mode "Classic". Notation "x -> y" := (forall (_:x), y) (at level 99, right associativity, y at level 200). Cumulative Variant paths {A} (a:A) : A -> Type := idpath : paths a a. Arguments idpath {A a} , [A] a. Scheme paths_ind := Induction for paths Sort Type. Arguments paths_ind [A] a P f y p : rename. Notation "x = y :> A" := (@paths A x y) (at level 70, y at next level, no associativity). Notation "x = y" := (x = y :>_) (at level 70, no associativity). Register paths as core.identity.type. Register idpath as core.identity.refl. Register paths_ind as core.identity.ind. Scheme paths_ind_nodep := Minimality for paths Sort Type. Definition inverse {A : Type} {x y : A} (p : x = y) : y = x := match p with idpath => idpath end. Arguments inverse {A x y} p : simpl nomatch. Register inverse as core.identity.sym. Definition concat {A : Type} {x y z : A} (p : x = y) (q : y = z) : x = z := match p, q with idpath, idpath => idpath end. Arguments concat {A x y z} p q : simpl nomatch. Register concat as core.identity.trans. Definition ap {A B:Type} (f:A -> B) {x y:A} (p:x = y) : f x = f y := match p with idpath => idpath end. Arguments ap {A B} f {x y} p. Register ap as core.identity.congr. Definition paths_Has_Leibniz_elim@{l l' l''} : Has_Leibniz@{Type Type Type;l l' l''} (@paths) := fun A x P t y e => match e with idpath => t end. Hint Resolve paths_Has_Leibniz_elim : rewrite_instances. Variant Empty : Type :=. Register Empty as core.False.type. Variant Unit : Type := tt. Register Unit as core.True.type. Register tt as core.True.I. Variant Bool : Type := true | false. Inductive nat : Type := O | S (n:nat). (*********** Test discriminate tactic below. ***************) Goal O = S O -> Empty. discriminate 1. Qed. Goal forall H : O = S O, H = H. discriminate H. Qed. Goal O = S O -> Unit. intros. discriminate H. Qed. Goal O = S O -> Unit. intros. Ltac g x := discriminate x. g H. Qed. Goal (forall x y : nat, x = y -> x = S y) -> Unit. intros. try discriminate (H O) || exact tt. Qed. Goal (forall x y : nat, x = y -> x = S y) -> Unit. intros. ediscriminate (H O). instantiate (1:=O). Abort. (* Check discriminate on types with local definitions *) Inductive A := B (T := Unit) (x y : Bool) (z := x). Goal forall x y, B x true = B y false -> Empty. discriminate. Qed. rocq-9.2.0/test-suite/success/FinalObligation.v000066400000000000000000000012171516144147600215060ustar00rootroot00000000000000Require Import Program.Tactics. Program Definition foo : nat := _. Program Definition bar : nat * nat := (_, _). Final Obligation. exact 0. Fail Defined. Abort. Next Obligation. exact 0. Defined. Final Obligation. exact 1. Fail Defined. Abort. Final Obligation of bar. exact 1. Defined. Final Obligation. exact 2. Defined. Obligation Tactic := try constructor. Program Definition baz := _ : _. Final Obligation. exact True. Defined. Obligation Tactic := idtac. Program Definition boz : nat := _. Module M. Program Definition mboz : nat := _. Final Obligation. exact 0. Qed. End M. Final Obligation. exact 0. Qed. rocq-9.2.0/test-suite/success/FixStronglyWf.v000066400000000000000000000040031516144147600212260ustar00rootroot00000000000000(* Examples of fixpoints with loops in erasable subterms *) (* Loop in erasable local definition *) Fail Fixpoint foo (n : nat) := let g := foo n in 0. (* Loop in erasable branch *) Fail Fixpoint foo (n : nat) := match 0 with | 0 => 0 | S x => foo n end. (* Loop in inert type *) Fail Fixpoint foo (n : nat) := forall x : foo n, True. (* Loop in erasable (and inert) types *) Fail Fixpoint foo (n : nat) := let _ := fun x : foo n => 0 in True. Fail Fixpoint foo (n : nat) := (fun _ : foo n = foo n => True) eq_refl. Fail Fixpoint foo (n : nat) := 0 : id (fun _ => nat) (foo n). (* Competition between an internally bound recursive argument and an invalid argument; also checks that it does not depend on order *) Fail Fixpoint foo p (n : nat) := match n with | 0 => 0 | S x => foo p (id (fun y => match p with | true => y | false => n end) x) end. Fail Fixpoint foo p (n : nat) := match n with | 0 => 0 | S x => foo p (id (fun y => match p with | true => n | false => y end) x) end. (* These one are presumably inoffensive but we continue to reject them *) Fail Fixpoint foo1 (n : nat) := forall x : foo1 = foo1, True. Fail Fixpoint foo2 (n : nat) := eq foo2 foo2. (* Should we allow the following? This is practically uninteresting but a priori ok *) Fail Fixpoint foo (n : nat) := forall n, forall x : foo n = foo n, True. Fail Fixpoint foo (n : nat) := forall n, eq (foo n) (foo n). (* Loop after one step of reduction *) Fail Fixpoint foo (n : nat) := (fun f p => (fun _ => True) (foo p)) n. Fail Fixpoint foo (n : nat) := (if true then fun p => if true then True else foo n else fun p => True) n. (* Loop in dead branch *) Fail Fixpoint foo n := match n with | 0 => 0 | S n => (fix aux n := match n with | 0 => foo n | S n => aux n end) (S n) end. (* Loop in inert erasable subterm *) Fail Fixpoint g (n:nat) : Prop := (fun x : g n -> True => True) (fun y : g n => I). rocq-9.2.0/test-suite/success/Fixpoint.v000066400000000000000000000345341516144147600202550ustar00rootroot00000000000000(* Playing with (co-)fixpoints with local definitions *) Inductive listn : nat -> Set := niln : listn 0 | consn : forall n:nat, nat -> listn n -> listn (S n). Fixpoint f (n:nat) (m:=pred n) (l:listn m) (p:=S n) {struct l} : nat := match n with O => p | _ => match l with niln => p | consn q _ l => f (S q) l end end. Eval compute in (f 2 (consn 0 0 niln)). CoInductive Stream : nat -> Set := Consn : forall n, nat -> Stream n -> Stream (S n). CoFixpoint g (n:nat) (m:=pred n) (l:Stream m) (p:=S n) : Stream p := match n return (let m:=pred n in forall l:Stream m, let p:=S n in Stream p) with | O => fun l:Stream 0 => Consn O 0 l | S n' => fun l:Stream n' => let l' := match l in Stream q return Stream (pred q) with Consn _ _ l => l end in let a := match l with Consn _ a l => a end in Consn (S n') (S a) (g n' l') end l. Eval compute in (fun l => match g 2 (Consn 0 6 l) with Consn _ a _ => a end). (* Check inference of simple types in presence of non ambiguous dependencies (needs revision 10125) *) Section folding. Inductive vector (A:Type) : nat -> Type := | Vnil : vector A 0 | Vcons : forall (a:A) (n:nat), vector A n -> vector A (S n). Variables (B C : Set) (g : B -> C -> C) (c : C). Fixpoint foldrn n bs := match bs with | Vnil _ => c | Vcons _ b _ tl => g b (foldrn _ tl) end. End folding. (* Check definition by tactics *) Inductive even : nat -> Type := | even_O : even 0 | even_S : forall n, odd n -> even (S n) with odd : nat -> Type := odd_S : forall n, even n -> odd (S n). Fixpoint even_div2 n (H:even n) : nat := match H with | even_O => 0 | even_S n H => S (odd_div2 n H) end with odd_div2 n H : nat. destruct H. apply even_div2 with n. assumption. Qed. Fixpoint even_div2' n (H:even n) : nat with odd_div2' n (H:odd n) : nat. destruct H. exact 0. apply odd_div2' with n. assumption. destruct H. apply even_div2' with n. assumption. Qed. CoInductive Stream1 (A B:Type) := Cons1 : A -> Stream2 A B -> Stream1 A B with Stream2 (A B:Type) := Cons2 : B -> Stream1 A B -> Stream2 A B. CoFixpoint ex1 (n:nat) (b:bool) : Stream1 nat bool with ex2 (n:nat) (b:bool) : Stream2 nat bool. apply Cons1. exact n. apply (ex2 n b). apply Cons2. exact b. apply (ex1 (S n) (negb b)). Defined. Section visibility. Let Fixpoint imm (n:nat) : True := I. Let Fixpoint by_proof (n:nat) : True. Proof. exact I. Defined. Let Fixpoint foo (n:nat) : bool with bar (n:nat) : bool. Proof. - destruct n as [|n]. + exact true. + exact (bar n). - destruct n as [|n]. + exact false. + exact (foo n). Qed. Let Fixpoint bla (n:nat) : Type with bli (n:nat) : bool. Admitted. End visibility. Fail Check imm. Fail Check by_proof. Check bla. Check bli. Module Import mod_local. Fixpoint imm_importable (n:nat) : True := I. Local Fixpoint imm_local (n:nat) : True := I. Fixpoint by_proof_importable (n:nat) : True. Proof. exact I. Defined. Local Fixpoint by_proof_local (n:nat) : True. Proof. exact I. Defined. End mod_local. Check imm_importable. Fail Check imm_local. Check mod_local.imm_local. Check by_proof_importable. Fail Check by_proof_local. Check mod_local.by_proof_local. (* Miscellaneous tests *) Module IotaRedex. Fixpoint minus (n m:nat) {struct n} : nat := match (n, m) with | (O , _) => O | (S _ , O) => n | (S n', S m') => minus n' m' end. End IotaRedex. Module ReturningInductive. Fail Fixpoint geneq s (x: list nat) {struct s} : Prop := match x with | cons a t => geneq (S a) t /\ geneq (S a) t | _ => False end. End ReturningInductive. Module NestingAndUnfolding. Fail Fixpoint f (x:nat) := id (fix g x : nat := f x) 0. Fixpoint f x := match x with | 0 => 0 | S n => id (fix g x := f x) n end. End NestingAndUnfolding. Module NestingAndConstructedUnfolding. Definition fold_left {A B : Type} (f : A -> B -> A) := fix fold_left (l : list B) (a0 : A) {struct l} : A := match l with | nil => a0 | cons b t => fold_left t (f a0 b) end. Record t A : Type := mk { elt: A }. Arguments elt {A} t. Inductive LForm : Type := | LIMPL : t LForm -> list (t LForm) -> LForm. Fixpoint hcons (m : unit) (f : LForm) := match f with | LIMPL f l => fold_left (fun m f => hcons m f.(elt) ) (cons f l) m end. End NestingAndConstructedUnfolding. Module CofixRedex. CoInductive Stream := {hd : nat; tl : Stream}. Definition zeros := cofix zeros := {|hd := 0; tl := zeros|}. Fixpoint f n := match n with | 0 => 0 | S n => match zeros with | {|hd:=_|} => fun f => f n end f end. End CofixRedex. Module CofixRedexPrimProj. Set Primitive Projections. CoInductive Stream A := {hd : A; tl : Stream A}. Arguments hd {A} s. Fixpoint f n := match n with | 0 => 0 | S n => (cofix cst := {|hd := (fun f => f n); tl := cst|}).(hd) f end. End CofixRedexPrimProj. Module ArgumentsAcrossMatch. (* large subterm passed across match *) Fail Fixpoint f n p {struct n} := match n with | 0 => fun _ => 0 | S q => fun r => f q (f r 0) end n. (* strict subterm passed across match *) Fixpoint f n p {struct n} := match n with | 0 => 0 | S q => match q with | 0 => fun _ => 0 | S q' => fun r => f q (f r 0) end q end. End ArgumentsAcrossMatch. Module LetToExpand. Fixpoint h n := let f n := (fun x : h n -> True => True) (fun y : h n => I) in match n with | 0 => True | S n => f n end. End LetToExpand. Module RecursiveCallInsideCoFix. CoInductive I := { field : I }. Fail Fixpoint f (n:nat) := (cofix g n := {| field := f n |}) 0. End RecursiveCallInsideCoFix. Module NestedRedexes. Fixpoint f n := match n with | 0 => 0 | S n => id (fun x => id (fun _ => id (f x)) 0) n end. End NestedRedexes. Module NestedRedexesWithCofix. CoInductive I := { field : nat -> nat }. Fail Fixpoint f n := ((cofix g h := {| field := h |}) f).(field) n. Fixpoint f n := match n with | 0 => 0 | S p => ((cofix g h := {| field := h |}) f).(field) p end. End NestedRedexesWithCofix. Module NestedApplicationsWithVariables. Section S. Variable h : (nat -> nat) -> nat. Fixpoint f n := match n with | 0 => 0 | S p => (fun _ => 0) (h f) end. End S. End NestedApplicationsWithVariables. Module NestedApplicationsWithParameters. Parameter h : (nat -> nat) -> nat. Fixpoint f n := match n with | 0 => 0 | S p => (fun _ => 0) (h f) end. End NestedApplicationsWithParameters. Module NestedApplicationsWithLocalVariables. Fixpoint f (h:(nat->nat)->nat) n := match n with | 0 => 0 | S p => (fun _ => 0) (h (f h)) end. End NestedApplicationsWithLocalVariables. Module NestedApplicationsWithProjections. Set Primitive Projections. Record R := { field : (nat -> nat) -> nat }. Fixpoint f x n := match n with | 0 => 0 | S p => (fun _ => 0) (x.(field) (f x)) end. End NestedApplicationsWithProjections. Module NestedRedexesWithFix. Fixpoint f n := match n with | 0 => 0 | S p => (fun _ => 0) ((fix h k (q:nat) {struct q} := k) f) end. (* inner fix fully applied with a match subterm *) Fixpoint f' n := match n with | 0 => 0 | S p => (fun _ => 0) ((fix h k (q:nat) {struct q} := k) f' p) end. (* inner fix fully applied with an arbitrary term *) Fixpoint f'' o n := match n with | 0 => 0 | S p => (fun _ => 0) ((fix h k (q:nat) {struct q} := k o) f'' o) end. End NestedRedexesWithFix. Module NestedRedexesWithMatch. Fixpoint f o n := match n with | 0 => 0 | S p => (fun _ => 0) (match o with tt => f o end) end. Fixpoint f' o n := match n with | 0 => 0 | S p => (fun _ => 0) ((match o with tt => fun x => x o end) f') end. End NestedRedexesWithMatch. Module ErasableInertSubterm. Fixpoint P (n:nat) := (fun _ => True) (forall a : (forall p, P p), True). End ErasableInertSubterm. Module WithLetInLift. Fixpoint f (n : nat) : nat := match n with | 0 => 0 | S n => (let x := 0 in fun n => f n) n end. End WithLetInLift. Module WithLateCaseReduction. Definition B := true. Fixpoint f (n : nat) := match n with | 0 => 0 | S n => (if B as b return if b then nat -> nat else unit then fun n => f n else tt) n end. End WithLateCaseReduction. Module NtnInteractiveFixpoint. Reserved Notation "# n" (at level 2, right associativity). Fixpoint f (n:nat) : nat where "# n" := (f n). exact (match n with 0 => 0 | S n => # n end). Defined. Check eq_refl : # 0 = f 0. End NtnInteractiveFixpoint. Module NoArgumentFixpoint. Fail Fixpoint f : nat. (* was an anomaly at some time *) End NoArgumentFixpoint. Module FixpointRelevance. (* Check that the recursive reference to a fixpoint name has correct relevance, in different execution paths *) Inductive STrue : SProp := SI. Inductive seq (a:STrue) : STrue -> SProp := srefl : seq a a. Fixpoint g1 (n:nat) : STrue := match n with | 0 => SI | S n => let x := srefl (g1 n) : seq (g1 n) (g2 n) in g2 n end with g2 (n:nat) : STrue := match n with | 0 => SI | S n => let x := srefl (g1 n) : seq (g1 n) (g2 n) in g1 n end. Fixpoint h1 (n:nat) : STrue with h2 (n:nat) : STrue. exact (match n with | 0 => SI | S n => let x := srefl (h1 n) : seq (h1 n) (h2 n) in h2 n end). exact (match n with | 0 => SI | S n => let x := srefl (h1 n) : seq (h1 n) (h2 n) in h1 n end). Defined. Theorem k1 (n:nat) : STrue with k2 (n:nat) : STrue. exact (match n with | 0 => SI | S n => let x := srefl (k1 n) : seq (k1 n) (k2 n) in k2 n end). exact (match n with | 0 => SI | S n => let x := srefl (k1 n) : seq (k1 n) (k2 n) in k1 n end). Defined. End FixpointRelevance. Module ClearFixBody. CoInductive Stream : Set := Cons : nat -> Stream -> Stream. Section S. #[clearbody] Let CoFixpoint f : Stream := Cons 1 f. #[clearbody] Let Fixpoint g n := match n with 0 => 0 | S n => g n end. Goal True. Fail Check eq_refl : f = cofix f := Cons 1 f. Fail Check eq_refl : g = fix g n := match n with 0 => 0 | S n => g n end. Abort. End S. End ClearFixBody. Module TheoremWithUnivs. Fail Fixpoint f@{u} (n:nat) : nat with g@{v} (n:nat) : nat. Fail Theorem f@{u} (n:nat) : nat with g@{v} (n:nat) : nat. Fail CoFixpoint f@{u} (n:nat) : Stream 0 with g@{v} (n:nat) : Stream 0. Succeed Fixpoint f@{u} (n:nat) : nat with g@{u} (n:nat) : nat. Succeed Theorem f@{u} (n:nat) : nat with g@{u} (n:nat) : nat. Succeed CoFixpoint f@{u} (n:nat) : Stream 0 with g@{u} (n:nat) : Stream 0. Succeed Fixpoint f@{u} (n:nat) : nat with g (n:nat) : nat. (* Accepted *) Succeed Theorem f@{u} (n:nat) : nat with g (n:nat) : nat. (* Accepted *) Succeed CoFixpoint f@{u} (n:nat) : Stream 0 with g (n:nat) : Stream 0. (* Accepted *) End TheoremWithUnivs. Module DependMutualFix. Inductive tree (A : Type) := Node : A -> list (tree A) -> tree A. Definition lmap' {A B} (f : A -> B) : list A -> list B := fix F l := match l with | nil => nil | cons x l => cons (f x) (G l) end with G l := match l with | nil => nil | cons x l => cons (f x) (F l) end for F. (* Not yet able to accept this *) Fail Fixpoint map {A B} (f : A -> B) (t : tree A) {struct t} : tree B := match t with | Node _ x l => Node _ (f x) (lmap' (map f) l) end. End DependMutualFix. Module Wish16040. Inductive tree (A : Type) := Node : A -> list (tree A) -> tree A. Fixpoint lmap {A B} (f : A -> B) (l : list A) : list B := match l with | nil => nil | cons x l => cons (f x) (lmap f l) end. Fixpoint map {A B} (f : A -> B) (t : tree A) {struct t} : tree B := match t with | Node _ x l => Node _ (f x) (lmap (map f) l) end. (* Check that we don't find too much uniform parameters *) Fixpoint lmap' {A} (f g : A -> A) (l : list A) : list A := match l with | nil => nil | cons x l => cons (f x) (lmap' g f l) end. (* Not supposed to be detected guarded, as only A is uniform in lmap' *) Fail Fixpoint map' {A} (f : A -> A) (t : tree A) {struct t} : tree A := match t with | Node _ x l => Node _ (f x) (lmap' (map' f) (map' f) l) end. (* Uniform arguments after a non-uniform one *) Fixpoint lmap'' {A} n (f : A -> A) (l : list A) : list A := match l with | nil => nil | cons x l => cons (f x) (lmap'' (S n) f l) end. (* The current guard supports extrusion of uniform arguments only in prefix position *) Fail Fixpoint map'' {A} (f : A -> A) (t : tree A) {struct t} : tree A := match t with | Node _ x l => Node _ (f x) (lmap'' 0 (map'' f) l) end. End Wish16040. Module TheoremWith. CoInductive Stream : Set := Cons : nat -> Stream -> Stream. (* Support for mutually recursive theorems in non-mutual types *) Theorem a : Stream with b : Stream. Proof. apply (Cons 0), b. apply (Cons 0), a. Defined. Theorem c (n:nat) : Stream with d (n:nat) : Stream. (* corecursive *) Proof. apply (Cons n), (d n). apply (Cons n), (c n). Defined. Theorem c' (n:nat) : Stream with d' (n:nat) : Stream. (* recursive *) Proof. destruct n as [|n']. apply a. apply (d' n'). destruct n as [|n']. apply a. apply (c' n'). Defined. End TheoremWith. Module HighlyNested. Inductive T A := E : A * list A * list (list A) -> T A. Inductive U := H : T (T U) -> U. Definition map {A B : Type} (f : A -> B) := fix map (l : list A) : list B := match l with | nil => nil | cons a t => cons (f a) (map t) end. Definition mapT {A B} (f:A -> B) t := match t with E _ (a, l, ll) => E _ (f a, map f l, map (map f) ll) end. Fixpoint mapU (f:U->U) u := match u with | H t => H (mapT (mapT (mapU f)) t) end. End HighlyNested. Module TestIntersection. (* This example used to stress rtree.inter (3 nested types) *) Inductive Pmap_ne (A : Type) := | PNode010 : A -> Pmap_ne A | PNode110 : Pmap_ne A -> A -> Pmap_ne A. Arguments PNode010 {A} _ : assert. Arguments PNode110 {A} _ _ : assert. Variant Pmap (A : Type) := PEmpty : Pmap A | PNodes : Pmap_ne A -> Pmap A. Arguments PEmpty {A}. Arguments PNodes {A} _. Definition Pmap_ne_case {A B} (t : Pmap_ne A) (f : Pmap A -> option A -> Pmap A -> B) : B := match t with | PNode010 x => f PEmpty (Some x) PEmpty | PNode110 l x => f (PNodes l) (Some x) PEmpty end. Definition Pmap_fold_aux {A B} (go : B -> Pmap_ne A -> B) (y : B) (mt : Pmap A) : B := match mt with PEmpty => y | PNodes t => go y t end. Definition Pmap_ne_fold {A B} (f : A -> B -> B) : B -> Pmap_ne A -> B := fix go y t := Pmap_ne_case t (fun ml mx mr => Pmap_fold_aux go (Pmap_fold_aux go match mx with None => y | Some x => f x y end ml) mr). Definition Pmap_fold {A} {B} (f : A -> B -> B) := Pmap_fold_aux (Pmap_ne_fold f). Inductive test := Test : Pmap test -> test. Fixpoint test_size (t : test) : nat := let 'Test ts := t in S (Pmap_fold (fun t' => plus (test_size t')) 0%nat ts). End TestIntersection. rocq-9.2.0/test-suite/success/Generalization.v000066400000000000000000000007521516144147600214230ustar00rootroot00000000000000Generalizable All Variables. Check `(a = 0). Check `(a = 0)%type. Definition relation A := A -> A -> Prop. Definition equivalence `(R : relation A) := True. Check (`(@equivalence A R)). Definition a_eq_b : `( a = 0 /\ a = b /\ b > c \/ d = e /\ d = 1). Admitted. Print a_eq_b. Require Import Morphisms. Class Equiv A := equiv : A -> A -> Prop. Class Setoid A `{Equiv A} := setoid_equiv :: Equivalence (equiv). Lemma vcons_proper A `[Equiv A] `[!Setoid A] (x : True) : True. Admitted. rocq-9.2.0/test-suite/success/Generalize.v000066400000000000000000000002601516144147600205270ustar00rootroot00000000000000(* Check Generalize Dependent *) Lemma l1 : let a := 0 in let b := a in forall (c : b = b) (d : True -> b = b), d = d. intros. generalize dependent a. intros a b c d. Abort. rocq-9.2.0/test-suite/success/GenerateGoalNames.v000066400000000000000000000006621516144147600217710ustar00rootroot00000000000000(* -*- mode: coq -*- *) Set Generate Goal Names. Axiom A : forall (x : nat) P, x = x -> P. (* eapply *) Goal 0 = 0. Proof. eapply A. [x]: exact 0. reflexivity. Qed. (* destruct *) Goal forall A, A \/ A -> A. Proof. intros A H. destruct H. [or_introl]: assumption. [or_intror]: assumption. Qed. (* induction *) Goal forall x : list nat, x = x. Proof. induction x. [nil]: reflexivity. [cons]: reflexivity. Qed. rocq-9.2.0/test-suite/success/HintMode.v000066400000000000000000000054331516144147600201600ustar00rootroot00000000000000Module Postponing. Class In A T := { IsIn : A -> T -> Prop }. Class Empty T := { empty : T }. Class EmptyIn (A T : Type) `{In A T} `{Empty T} := { isempty : forall x, IsIn x empty -> False }. #[export] Hint Mode EmptyIn ! ! - - : typeclass_instances. #[export] Hint Mode Empty ! : typeclass_instances. #[export] Hint Mode In ! - : typeclass_instances. Existing Class IsIn. Goal forall A T `{In A T} `{Empty T} `{EmptyIn A T}, forall x : A, IsIn x empty -> False. Proof. intros. eapply @isempty. (* Second goal needs to be solved first, to un-stuck the first one (hence the Existing Class IsIn to allow finding the assumption of IsIn here) *) all:typeclasses eauto. Qed. End Postponing. Module Heads. Set Primitive Projections. Class A (X : Type) := { somex : X }. Local Hint Mode A ! : typeclass_instances. Record foo := { car : Type; obj : car }. Local Instance foo_A (f : foo) : A (car f) := { somex := obj f }. Definition onef := {| car := nat; obj := 0 |}. Goal {f : foo & A (car f)}. Proof. unshelve eexists; cycle 1. solve [typeclasses eauto]. exact onef. Defined. End Heads. Module BestEffort. Class A (T : Type). Global Hint Mode A + : typeclass_instances. Class B (T : Type). Global Hint Mode B + : typeclass_instances. #[export] Instance a_imp_b T : A T -> B T := {}. #[export] Instance anat : B nat := {}. Lemma b : B nat * A nat. Proof. Fail split; typeclasses eauto. Set Typeclasses Debug Verbosity 2. Fail split; solve [typeclasses eauto best_effort]. (* Here typeclasses eauto best_effort, when run on the 2 goals at once, can solve the B goal which has a nat instance nd whose mode is + (this morally assumes that there is only one instance matching B nat) *) split; typeclasses eauto best_effort. admit. Admitted. End BestEffort. Module Plus. Parameter plus : nat -> nat -> nat -> Prop. Axiom plus0l : forall m : nat, plus 0 m m. Axiom plus0r : forall n : nat, plus n 0 n. Axiom plusSl : forall n m r : nat, plus n m r -> plus (S n) m (S r). Axiom plusSr : forall n m r : nat, plus n m r -> plus m (S m) (S r). Hint Resolve plus0l plus0r plusSl plusSr : plus. Hint Mode plus ! - - : plus. Hint Mode plus - ! - : plus. Require Corelib.derive.Derive. Derive r SuchThat (plus 1 4 r) As r_proof. Proof. subst r. typeclasses eauto with plus. Qed. Goal exists x y, plus x y 12. Proof. eexists ?[x], ?[y]. Set Typeclasses Debug. Fail typeclasses eauto with plus. instantiate (y := 1). typeclasses eauto with plus. Defined. End Plus. Module ModeAttr. Fail #[mode="+"] Inductive foo (A : Type) : Set :=. Fail #[mode=""] Class Foo (A : Type) := {}. #[mode="+"] Class Foo (A : Type) := {}. Fail #[mode="+ +"] Class Foo' (A : Type) := {}. End ModeAttr. rocq-9.2.0/test-suite/success/Hints.v000066400000000000000000000150711516144147600175350ustar00rootroot00000000000000(* Checks syntax of Hints commands *) (* Old-style syntax *) #[export] Hint Resolve eq_refl eq_sym. #[export] Hint Resolve eq_refl eq_sym: foo. #[export] Hint Immediate eq_refl eq_sym. #[export] Hint Immediate eq_refl eq_sym: foo. #[export] Hint Unfold fst eq_sym. #[export] Hint Unfold fst eq_sym: foo. (* Checks that qualified names are accepted *) (* New-style syntax *) #[export] Hint Resolve eq_refl: core arith. #[export] Hint Immediate eq_trans. #[export] Hint Unfold eq_sym: core. #[export] Hint Constructors eq: foo bar. #[export] Hint Extern 3 (_ = _) => apply eq_refl: foo bar. (* Extended new syntax with patterns *) #[export] Hint Resolve eq_refl | 4 (_ = _) : baz. #[export] Hint Resolve eq_sym eq_trans : baz. #[export] Hint Extern 3 (_ = _) => apply eq_sym : baz. Parameter pred : nat -> Prop. Parameter pred0 : pred 0. Parameter f : nat -> nat. Parameter predf : forall n, pred n -> pred (f n). (* No conversion on let-bound variables and constants in pred (the default) *) #[export] Hint Resolve pred0 | 1 (pred _) : pred. #[export] Hint Resolve predf | 0 : pred. (* Allow full conversion on let-bound variables and constants *) Create HintDb predconv discriminated. #[export] Hint Resolve pred0 | 1 (pred _) : predconv. #[export] Hint Resolve predf | 0 : predconv. Parameter predconv : forall n, pred n -> pred (0 + S n). (* The inferred pattern contains 0 + ?n, syntactic match will fail to see convertible terms *) #[export] Hint Resolve pred0 : pred2. #[export] Hint Resolve predconv : pred2. (** In this database we allow predconv to apply to pred (S _) goals, more generally than the inferred pattern (pred (0 + S _)). *) Create HintDb pred2conv discriminated. #[export] Hint Resolve pred0 : pred2conv. #[export] Hint Resolve predconv | 1 (pred (S _)) : pred2conv. Goal pred 3. Fail typeclasses eauto with pred2. typeclasses eauto with pred2conv. Abort. Set Typeclasses Debug Verbosity 2. #[export] Hint Resolve predconv | 1 (pred _) : pred. #[export] Hint Resolve predconv | 1 (pred (S _)) : predconv. Test Typeclasses Limit Intros. Goal pred 3. (* predf is not tried as it doesn't match the goal *) (* predconv is tried but fails as the transparent state doesn't allow unfolding + *) Fail typeclasses eauto with pred. (* Here predconv succeeds as it matches (pred (S _)) and then full unification is allowed *) typeclasses eauto with predconv. Qed. (* Checks that local names are accepted *) Section A. Remark Refl : forall (A : Set) (x : A), x = x. Proof. exact @eq_refl. Defined. Definition Sym := eq_sym. Let Trans := eq_trans. Hint Resolve Refl: foo. Hint Resolve Sym: bar. Hint Resolve Trans: foo2. Hint Immediate Refl. Hint Immediate Sym. Hint Immediate Trans. Hint Unfold Refl. Hint Unfold Sym. Hint Unfold Trans. Hint Resolve Sym Trans Refl. Hint Immediate Sym Trans Refl. Hint Unfold Sym Trans Refl. End A. Axiom a : forall n, n=0 <-> n<=0. #[export] Hint Resolve -> a. Goal forall n, n=0 -> n<=0. auto. Qed. (* This example comes from Chlipala's ltamer *) (* It used to fail from r12902 to r13112 since type_of started to call *) (* e_cumul (instead of conv_leq) which was not able to unify "?id" and *) (* "(fun x => x) ?id" *) Notation "e :? pf" := (eq_rect _ (fun X : Set => X) e _ pf) (no associativity, at level 90). Axiom cast_coalesce : forall (T1 T2 T3 : Set) (e : T1) (pf1 : T1 = T2) (pf2 : T2 = T3), ((e :? pf1) :? pf2) = (e :? trans_eq pf1 pf2). #[export] Hint Rewrite cast_coalesce : ltamer. Definition id := fun {A : Type} (x : A) => x. Definition compose := fun {A B C : Type} (g : B -> C) (f : A -> B) (x : A) => g (f x). Notation "g ∘ f " := (compose g f) (at level 10). Module HintCut. Class A (f : nat -> nat) := a : True. Class B (f : nat -> nat) := b : True. Class C (f : nat -> nat) := c : True. Class D (f : nat -> nat) := d : True. Class E (f : nat -> nat) := e : True. #[export] Instance a_is_b f : A f -> B f. Proof. easy. Qed. #[export] Instance b_is_c f : B f -> C f. Proof. easy. Qed. #[export] Instance c_is_d f : C f -> D f. Proof. easy. Qed. #[export] Instance d_is_e f : D f -> E f. Proof. easy. Qed. #[export] Instance a_compose f g : A f -> A g -> A (compose f g). Proof. easy. Qed. #[export] Instance b_compose f g : B f -> B g -> B (compose f g). Proof. easy. Qed. #[export] Instance c_compose f g : C f -> C g -> C (compose f g). Proof. easy. Qed. #[export] Instance d_compose f g : D f -> D g -> D (compose f g). Proof. easy. Qed. #[export] Instance e_compose f g : E f -> E g -> E (compose f g). Proof. easy. Qed. #[export] Instance a_id : A id. Proof. easy. Qed. #[export] Instance foo f : E (id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ f ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id ∘ id). Proof. #[export] Hint Cut [_* (a_is_b | b_is_c | c_is_d | d_is_e) (a_compose | b_compose | c_compose | d_compose | e_compose)] : typeclass_instances. Timeout 1 Fail apply _. (* 0.06s *) Abort. End HintCut. (* Check that auto-like tactics do not prefer "eq_refl" over more complex solutions, *) (* e.g. those tactics when considering a goal with existential variables *) (* like "m = ?n" won't pick "plus_n_O" hint over "eq_refl" hint. *) (* See this Coq club post for more detail: *) (* https://sympa.inria.fr/sympa/arc/coq-club/2017-12/msg00103.html *) Goal forall (m : nat), exists n, m = n /\ m = n. intros m; eexists; split; [trivial | reflexivity]. Qed. Section HintTransparent. Definition fn (x : nat) := S x. Create HintDb trans. Hint Resolve eq_refl | (_ = _) : trans. (* No reduction *) Hint Variables Opaque : trans. Hint Constants Opaque : trans. Goal forall x : nat, fn x = S x. Proof. intros. Fail typeclasses eauto with trans. unfold fn. typeclasses eauto with trans. Qed. (** Now allow unfolding fn *) Hint Constants Transparent : trans. Goal forall x : nat, fn x = S x. Proof. intros. typeclasses eauto with trans. Qed. End HintTransparent. Module RepeatCreat. Axiom T : Type. Axiom v : T. Set Warnings "+mismatched-hint-db". (* if this fails it means the db already exists as a discriminated db *) Succeed Create HintDb repeated. Create HintDb repeated discriminated. Fail Definition foo : T := ltac:(eauto with foo). Hint Resolve v : foo. Definition foo : T := ltac:(eauto with foo). Create HintDb repeated discriminated. (* hint is still there *) Definition foo' : T := ltac:(eauto with foo). Fail Create HintDb repeated. (* implicit hint db *) Fail Create HintDb foo discriminated. End RepeatCreat. rocq-9.2.0/test-suite/success/ImplicitArguments.v000066400000000000000000000054301516144147600221060ustar00rootroot00000000000000 Axiom foo : forall (x y z t : nat), nat. Arguments foo {_} _ [z] t. Check (foo 1). Arguments foo {_} _ {z} {t}. Fail Arguments foo {_} _ [z] {t}. Check (foo 1). Definition foo1 [m] n := n + m. Check (foo1 1). Inductive vector {A : Type} : nat -> Type := | vnil : vector 0 | vcons : A -> forall {n'}, vector n' -> vector (S n'). Arguments vector A : clear implicits. Require Import TestSuite.jmeq. Definition head_subproof A n (v : vector A (S n)) (a : A) n' (v' : vector A n') (eqn : S n' = S n) (eqv : JMeq (vcons a v') v) := let H : S n = S n -> n' = n := match eqn in _ = n'' return n'' = S n -> n' = n with | eq_refl => fun eqSn' : S n' = S n => let eqn' : n' = n := f_equal (fun e => match e with 0 => n' | S n0 => n0 end) eqSn' in eq_ind_r (fun n'' => n'' = n) (eq_ind_r (fun n' => forall v', S n' = S n -> JMeq (vcons a v') v -> n = n) (fun (v' : vector A n) _ _ => eq_refl) eqn' v' eqn eqv) eqn' end in H eq_refl. Definition head {A : Type} {n : nat} (v : vector A (S n)) := let case_nil (eqn : O = S n) _ := False_rect (vector A n) (False_ind False (eq_ind O (fun e => match e with O => True | S _ => False end) I (S n) eqn)) in let case_cons (a : A) n' (v' : vector A n') (eqn : eq (S n') (S n)) (eqv : JMeq (vcons a v') v) := eq_rect n' (vector A) v' n (head_subproof A n v a n' v' eqn eqv) in match v as v' in vector _ n' return eq n' (S n) -> JMeq v' v -> vector A n with | vnil => case_nil | @vcons _ a n' v' => case_cons a n' v' end (eq_refl (S n)) (JMeq_refl v). Fixpoint app {A : Type} {n m : nat} (v : vector A n) (w : vector A m) : vector A (n + m) := match v in vector _ n return vector A (n + m) with | vnil => w | vcons a v' => vcons a (app v' w) end. (* Test sharing information between different hypotheses *) Parameters (a:_) (b:a=0). (* These examples were failing due to a lifting wrongly taking let-in into account *) Definition foo6 (x:=1) : forall {n:nat}, n=n := fun n => eq_refl. Fixpoint foo7 (x:=1) (n:nat) {p:nat} {struct n} : nat. Abort. (* Some example which should succeed with local implicit arguments *) Inductive A {P:forall m {n}, n=m -> Prop} := C : P 0 eq_refl -> A. Inductive B (P:forall m {n}, n=m -> Prop) := D : P 0 eq_refl -> B P. Inductive A' {P:forall m [n], n=m -> Prop} := C' : P 0 eq_refl -> A'. Inductive A'' [P:forall m {n}, n=m -> Prop] (b : bool):= C'' : P 0 eq_refl -> A'' b. Inductive A''' (P:forall m [n], n=m -> Prop) (b : bool):= C''' : P 0 eq_refl -> A''' P b. Definition F (id: forall [A] [x : A], A) := id. Definition G := let id := (fun [A] (x : A) => x) in id. Fail Definition G' := let id := (fun {A} (x : A) => x) in id. rocq-9.2.0/test-suite/success/Import.v000066400000000000000000000003321516144147600177140ustar00rootroot00000000000000(* Test visibility of imported objects *) Require Import make_local. (* Check local implicit arguments are not imported *) Check (f nat 0). (* Check local arguments scopes are not imported *) Check (f nat (0*0)). rocq-9.2.0/test-suite/success/ImportCat.v000066400000000000000000000027431516144147600203540ustar00rootroot00000000000000Axioms A B C D : Type. Axiom a : A. Module M. Axiom AB : A -> B. Coercion AB : A >-> B. Module Inner. Axiom BC : B -> C. Coercion BC : B >-> C. End Inner. Export Inner. Module Alt. Axiom BD : B -> D. Coercion BD : B >-> D. End Alt. Notation "x <<< y" := (x + y) (at level 22). Reserved Notation "@@". Tactic Notation "@@" := idtac. End M. Module N. Notation "x <<< y" := (x - y) (at level 23). End N. Fail Import(coercions) M(AB). Module Test1. Import(coercions) M. Check a : B. Check a : C. Fail Check a : D. (* names not imported *) Fail Import Alt. Fail Check AB. Check M.AB. Import M.Alt. Check a : D. Import N. (* notations didn't get imported *) End Test1. Module Test2. Import -(coercions) M. Fail Check a : B. Check AB. Fail Check AB a : C. Fail Import N. Check Inner.BC. Import Inner. Check AB a : C. Fail Check a : C. End Test2. Module TestExport. Import M(AB). Module Import(notations) X. Module Y. Definition bla := 0. Coercion AB : A >-> B. End Y. Export(coercions) Y. End X. Fail Check a : B. Import X. Check a : B. Fail Check bla. Check Y.bla. End TestExport. Module Notas. Import -(ltac.notations,notations) M. Import N. Check eq_refl : 1 <<< 1 = 0. Module X. Tactic Notation "@@" := fail. Lemma foo : False. Proof. Fail @@. Abort. End X. Import (ltac.notations) M. Lemma foo : False. Proof. @@. Abort. End Notas. rocq-9.2.0/test-suite/success/Inductive.v000066400000000000000000000144251516144147600204040ustar00rootroot00000000000000(* Test des definitions inductives imbriquees *) Inductive X : Set := cons1 : list X -> X. Inductive Y : Set := cons2 : list (Y * Y) -> Y. (* Test inductive types with local definitions (arity) *) Inductive eq1 : forall A:Type, let B:=A in A -> Prop := refl1 : eq1 True I. Check fun (P : forall A : Type, let B := A in A -> Type) (f : P True I) (A : Type) => let B := A in fun (a : A) (e : eq1 A a) => match e in (@eq1 A0 B0 a0) return (P A0 a0) with | refl1 => f end. Inductive eq2 (A:Type) (a:A) : forall B C:Type, let D:=(A*B*C)%type in D -> Prop := refl2 : eq2 A a unit bool (a,tt,true). (* Check inductive types with local definitions (parameters) *) Inductive A (C D : Prop) (E:=C) (F:=D) (x y : E -> F) : E -> Set := I : forall z : E, A C D x y z. Check (fun C D : Prop => let E := C in let F := D in fun (x y : E -> F) (P : forall c : C, A C D x y c -> Type) (f : forall z : C, P z (I C D x y z)) (y0 : C) (a : A C D x y y0) => match a as a0 in (A _ _ _ _ y1) return (P y1 a0) with | I _ _ _ _ x0 => f x0 end). Record B (C D : Set) (E:=C) (F:=D) (x y : E -> F) : Set := {p : C; q : E}. Check (fun C D : Set => let E := C in let F := D in fun (x y : E -> F) (P : B C D x y -> Type) (f : forall p0 q0 : C, P (Build_B C D x y p0 q0)) (b : B C D x y) => match b as b0 return (P b0) with | Build_B _ _ _ _ x0 x1 => f x0 x1 end). (* Check inductive types with local definitions (constructors) *) Inductive I1 : Set := C1 (_:I1) (_:=0). Check (fun x:I1 => match x with | C1 i n => (i,n) end). (* Check implicit parameters of inductive types (submitted by Pierre Casteran and also implicit in BZ#338) *) Set Implicit Arguments. Unset Strict Implicit. CoInductive LList (A : Set) : Set := | LNil : LList A | LCons : A -> LList A -> LList A. Arguments LNil {A}. Inductive Finite (A : Set) : LList A -> Prop := | Finite_LNil : Finite LNil | Finite_LCons : forall (a : A) (l : LList A), Finite l -> Finite (LCons a l). (* Check positivity modulo reduction (cf bug BZ#983) *) Record P:Type := {PA:Set; PB:Set}. Definition F (p:P) := (PA p) -> (PB p). Inductive I_F:Set := c : (F (Build_P nat I_F)) -> I_F. (* Check that test for binders capturing implicit arguments is not stronger than needed (problem raised by Cedric Auger) *) Set Implicit Arguments. Inductive bool_comp2 (b: bool): bool -> Prop := | Opp2: forall q, (match b return Prop with | true => match q return Prop with true => False | false => True end | false => match q return Prop with true => True | false => False end end) -> bool_comp2 b q. (* This one is still to be made acceptable... Set Implicit Arguments. Inductive I A : A->Prop := C a : (forall A, A) -> I a. *) (* Test recursively non-uniform parameters (was formerly in params_ind.v) *) Inductive list (A : Set) : Set := | nil : list A | cons : A -> list (A -> A) -> list A. (* Check inference of evars in arity using information from constructors *) Inductive foo1 : forall p, Prop := cc1 : foo1 0. (* Check cross inference of evars from constructors *) Inductive foo2 : forall p, Prop := cc2 : forall q, foo2 q | cc3 : foo2 0. (* An example with reduction removing an occurrence of the inductive type in one of its argument *) Inductive IND1 (A:Type) := CONS1 : IND1 ((fun x => A) IND1). (* These types were considered as ill-formed before March 2015, while they could be accepted considering that the type IND1 above was accepted *) Inductive IND2 (A:Type) (T:=fun _ : Type->Type => A) := CONS2 : IND2 A -> IND2 (T IND2). Inductive IND3 (A:Type) (T:=fun _ : Type->Type => A) := CONS3 : IND3 (T IND3) -> IND3 A. Inductive IND4 (A:Type) := CONS4 : IND4 ((fun x => A) IND4) -> IND4 A. (* This type was ok before March 2015 *) Inductive IND5 (A : Type) (T := A) : Type := CONS5 : IND5 ((fun _ => A) 0) -> IND5 A. (* An example of nested positivity which was rejected by the kernel before 24 March 2015 (even with Unset Elimination Schemes to avoid the _rect bug) due to the wrong computation of non-recursively uniform parameters in list' *) Inductive list' (A:Type) (B:=A) := | nil' : list' A | cons' : A -> list' B -> list' A. Inductive tree := node : list' tree -> tree. (* This type was raising an anomaly when building the _rect scheme, because of a bug in Inductiveops.get_arity in the presence of let-ins and recursively non-uniform parameters. *) Inductive L (A:Type) (T:=A) : Type := C : L nat -> L A. (* This type was raising an anomaly when building the _rect scheme, because of a wrong computation of the number of non-recursively uniform parameters when conversion is needed, leading the example to hit the Inductiveops.get_arity bug mentioned above (see #3491) *) Inductive IND6 (A:Type) (T:=A) := CONS6 : IND6 T -> IND6 A. Module TemplateProp. (** Check lowering of a template universe polymorphic inductive to Prop *) Inductive Foo (A : Type) : Type := foo : A -> Foo A. Check Foo True : Prop. End TemplateProp. Module PolyNoLowerProp. (** Check lowering of a general universe polymorphic inductive to Prop is _failing_ *) Polymorphic Inductive Foo (A : Type) : Type := foo : A -> Foo A. Fail Check Foo True : Prop. End PolyNoLowerProp. (* Test building of elimination scheme with noth let-ins and non-recursively uniform parameters *) Module NonRecLetIn. Unset Implicit Arguments. Inductive Ind (b:=2) (a:nat) (c:=1) : Type := | Base : Ind a | Rec : Ind (S a) -> Ind a. Check Ind_rect (fun n (b:Ind n) => b = b) (fun n => eq_refl) (fun n b c => f_equal (Rec n) eq_refl) 0 (Rec 0 (Base 1)). End NonRecLetIn. (* Test treatment of let-in in the definition of Records *) (* Should fail with "Sort expected" *) Fail Inductive foo (T : Type) : let T := Type in T := { r : forall x : T, x = x }. Module Discharge. (* discharge test *) Section S. Let x := Prop. Inductive foo : x := bla : foo. End S. Check bla:foo. Section S. Variables (A:Type). (* ensure params are scanned for needed section variables even with template arity *) #[universes(template)] Inductive bar (d:A) := . End S. Check @bar nat 0. End Discharge. rocq-9.2.0/test-suite/success/InductiveVsImplicitsVsTC.v000066400000000000000000000012741516144147600233310ustar00rootroot00000000000000Module NoConv. Class C := {}. Definition useC {c:C} := nat. Inductive foo {a b : C} := CC : useC -> foo. (* If TC search runs before parameter unification it will pick the wrong instance for the first parameter. useC makes sure we don't completely skip TC search. *) End NoConv. Module ForConv. Class Bla := { bla : Type }. #[export] Instance bli : Bla := { bla := nat }. Inductive vs := C : forall x : bla, x = 2 -> vs. (* here we need to resolve TC to pass the conversion problem if we combined with the previous example it would fail as TC resolution for conversion is unrestricted and so would resolve the conclusion too early. *) End ForConv. rocq-9.2.0/test-suite/success/Inversion.v000066400000000000000000000123761516144147600204310ustar00rootroot00000000000000Axiom magic : False. (* Submitted by Dachuan Yu (BZ#220) *) Fixpoint T (n : nat) : Type := match n with | O => nat -> Prop | S n' => T n' end. Inductive R : forall n : nat, T n -> nat -> Prop := | RO : forall (Psi : T 0) (l : nat), Psi l -> R 0 Psi l | RS : forall (n : nat) (Psi : T (S n)) (l : nat), R n Psi l -> R (S n) Psi l. Definition Psi00 (n : nat) : Prop := False. Definition Psi0 : T 0 := Psi00. Lemma Inversion_RO : forall l : nat, R 0 Psi0 l -> Psi00 l. inversion 1. Abort. (* Submitted by Pierre Casteran (BZ#540) *) Set Implicit Arguments. Unset Strict Implicit. Parameter rule : Set -> Type. Inductive extension (I : Set) : Type := | NL : extension I | add_rule : rule I -> extension I -> extension I. Inductive in_extension (I : Set) (r : rule I) : extension I -> Type := | in_first : forall e, in_extension r (add_rule r e) | in_rest : forall e r', in_extension r e -> in_extension r (add_rule r' e). Arguments NL {I}. Inductive super_extension (I : Set) (e : extension I) : extension I -> Type := | super_NL : super_extension e NL | super_add : forall r (e' : extension I), in_extension r e -> super_extension e e' -> super_extension e (add_rule r e'). Lemma super_def : forall (I : Set) (e1 e2 : extension I), super_extension e2 e1 -> forall ru, in_extension ru e1 -> in_extension ru e2. Proof. simple induction 1. inversion 1; auto. elim magic. Qed. (* Example from Norbert Schirmer on Coq-Club, Sep 2000 *) Set Strict Implicit. Unset Implicit Arguments. Definition Q (n m : nat) (prf : n <= m) := True. Goal forall (n m : nat) (H : S n <= m), Q (S n) m H = True. intros. dependent inversion_clear H. elim magic. elim magic. Qed. (* Submitted by Boris Yakobowski (BZ#529) *) (* Check that Inversion does not fail due to unnormalized evars *) Set Implicit Arguments. Unset Strict Implicit. Require Import TestSuite.vector. Inductive I : nat -> Set := | C1 : I 1 | C2 : forall k i : nat, Vector.t (I i) k -> I i. Inductive SI : forall k : nat, I k -> Vector.t nat k -> nat -> Prop := SC2 : forall (k i vf : nat) (v : Vector.t (I i) k) (xi : Vector.t nat i), SI (C2 v) xi vf. Theorem SUnique : forall (k : nat) (f : I k) (c : Vector.t nat k) v v', SI f c v -> SI f c v' -> v = v'. Proof. induction 1. intros H; inversion H. Admitted. (* Used to failed at some time *) Set Strict Implicit. Unset Implicit Arguments. Parameter bar : forall p q : nat, p = q -> Prop. Inductive foo : nat -> nat -> Prop := C : forall (a b : nat) (Heq : a = b), bar a b Heq -> foo a b. Lemma depinv : forall a b, foo a b -> True. intros a b H. inversion H. Abort. (* Check non-regression of BZ#1968 *) Inductive foo2 : option nat -> Prop := Foo : forall t, foo2 (Some t). Goal forall o, foo2 o -> 0 = 1. intros. eapply trans_eq. inversion H. Abort. (* Check that the part of "injection" that is called by "inversion" does the same number of intros as the number of equations introduced, even in presence of dependent equalities that "injection" renounces to split *) Fixpoint prodn (n : nat) := match n with | O => unit | (S m) => prod (prodn m) nat end. Inductive U : forall n : nat, prodn n -> bool -> Prop := | U_intro : U 0 tt true. Lemma foo3 : forall n (t : prodn n), U n t true -> False. Proof. (* used to fail because dEqThen thought there were 2 new equations but inject_at_positions actually introduced only one; leading then to an inconsistent state that disturbed "inversion" *) intros. inversion H. Abort. (* BZ#2314 (simplified): check that errors do not show as anomalies *) Goal True -> True. intro. Fail inversion H using False. Fail inversion foo using True_ind. Abort. (* Was failing at some time between 7 and 10 September 2014 *) (* even though, it is not clear that the resulting context is interesting *) Parameter P:nat*nat->Prop. Inductive IND : nat * nat -> { x : nat * nat | P x } * nat -> Prop := CONSTR a b (H:P (a,b)) c : IND (a,b) (exist _ (a,b) H, c). Goal forall x y z t u (H':P (z,t)), IND (x,y) (exist _ (z,t) H', u) -> x = z. intros * Hyp. inversion Hyp. (* By the way, why is "H" removed even in non-clear mode ? *) reflexivity. Qed. Goal forall x y z t u (H':P (z,t)), IND (x,y) (exist _ (z,t) H', u) -> x = z. intros * Hyp. inversion Hyp as (a,b,H,c,(H1_1,H1_2),(H2_1,H2_2,H2_3)). reflexivity. Qed. (* Up to September 2014, Mapp below was called MApp0 because of a bug in intro_replacing (short version of BZ#2164.v) (example taken from CoLoR) *) Parameter Term : Type. Parameter isApp : Term -> Prop. Parameter appBodyL : forall M, isApp M -> Prop. Parameter lower : forall M Mapp, appBodyL M Mapp -> Term. Inductive BetaStep : Term -> Term -> Prop := Beta M Mapp Mabs : BetaStep M (lower M Mapp Mabs). Goal forall M N, BetaStep M N -> True. intros M N H. inversion H as (P,Mapp,Mabs,H0,H1). clear Mapp Mabs H0 H1. exact Logic.I. Qed. (* Up to September 2014, H0 below was renamed called H1 because of a collision with the automatically generated names for equations. (example taken from CoLoR) *) Inductive term := Var | Fun : term -> term -> term. Inductive lt : term -> term -> Prop := mpo f g ss ts : lt Var (Fun f ts) -> lt (Fun f ss) (Fun g ts). Goal forall f g ss ts, lt (Fun f ss) (Fun g ts) -> lt Var (Fun f ts). intros. inversion H as (f',g',ss',ts',H0). exact H0. Qed. rocq-9.2.0/test-suite/success/InversionSigma.v000066400000000000000000000232771516144147600214140ustar00rootroot00000000000000Section inversion_sigma. Local Unset Implicit Arguments. Context A (B B' : A -> Prop) (C C' : forall a, B a -> Prop) (D : forall a b, C a b -> Prop) (E : forall a b c, D a b c -> Prop). Context (AP : Prop) (BP BP' : AP -> Prop) (CP CP' : forall a, BP a -> Prop) (DP : forall a b, CP a b -> Prop) (EP : forall a b c, DP a b c -> Prop). (* Require that, after destructing sigma types and inverting equalities, we can subst equalities of variables only, and reduce down to [eq_refl = eq_refl]. *) Local Ltac destr_sigma := repeat match goal with | [ H : ex _ |- _ ] => destruct H | [ H : sig _ |- _ ] => destruct H | [ H : sigT _ |- _ ] => destruct H | [ H : ex2 _ _ |- _ ] => destruct H | [ H : sig2 _ _ |- _ ] => destruct H | [ H : sigT2 _ _ |- _ ] => destruct H end; simpl in *. Local Ltac fin_test_inversion_sigma := match goal with | [ |- eq_refl = eq_refl ] => reflexivity end. Local Ltac test_inversion_sigma := intros; destr_sigma; inversion_sigma; repeat match goal with | [ H : ?x = ?y |- _ ] => is_var x; is_var y; subst x; simpl in * end; fin_test_inversion_sigma. Local Ltac test_inversion_sigma_in_H := intros; destr_sigma; repeat match goal with H : _ = _ |- _ => inversion_sigma H end; repeat match goal with | [ H : ?x = ?y |- _ ] => is_var x; is_var y; subst x; simpl in * end; fin_test_inversion_sigma. Goal forall (x y : { a : A & { b : { b : B a & C a b } & { d : D a (projT1 b) (projT2 b) & E _ _ _ d } } }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [-> p]; cbn [eq_rect] in *. lazymatch type of p with | existT _ (existT _ ?a ?b) (existT _ ?c ?d) = existT _ (existT _ ?e ?f) (existT _ ?g ?h) => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f; is_var g; is_var h end. inversion_sigma p as [p1 p2]. lazymatch type of p1 with existT _ ?a ?b = existT _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p1 as [-> <-]; cbn [eq_rect eq_existT_uncurried eq_sigT eq_existT_curried eq_sigT_uncurried] in * |- . lazymatch type of p2 with existT _ ?a ?b = existT _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p2 as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : A | { b : { b : B a | C a b } | { d : D a (proj1_sig b) (proj2_sig b) | E _ _ _ d } } }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [-> p]; cbn [eq_rect] in *. lazymatch type of p with | exist _ (exist _ ?a ?b) (exist _ ?c ?d) = exist _ (exist _ ?e ?f) (exist _ ?g ?h) => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f; is_var g; is_var h end. inversion_sigma p as [p1 p2]. lazymatch type of p1 with exist _ ?a ?b = exist _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p1 as [-> <-]; cbn [eq_rect eq_exist_uncurried eq_sig eq_exist_curried eq_sig_uncurried] in * |- . lazymatch type of p2 with exist _ ?a ?b = exist _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p2 as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : exists a : AP, exists b : exists b : BP a, CP a b, exists d : DP a (ex_proj1 b) (ex_proj2 b), EP _ _ _ d) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [-> p]; cbn [eq_rect] in *. lazymatch type of p with | ex_intro _ (ex_intro _ ?a ?b) (ex_intro _ ?c ?d) = ex_intro _ (ex_intro _ ?e ?f) (ex_intro _ ?g ?h) => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f; is_var g; is_var h end. inversion_sigma p as [p1 p2]. lazymatch type of p1 with ex_intro _ ?a ?b = ex_intro _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p1 as [-> <-]; cbn [eq_rect eq_ex_intro_uncurried eq_ex_intro eq_ex eq_ex_uncurried] in * |- . lazymatch type of p2 with ex_intro _ ?a ?b = ex_intro _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p2 as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a } & C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with existT _ ?a ?b = existT _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a } | C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with existT _ ?a ?b = existT _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : exists2 a : exists a : AP, BP a, CP _ (ex_proj2 a) & CP' _ (ex_proj2 a)) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with ex_intro _ ?a ?b = ex_intro _ ?c ?d => is_var a; is_var b; is_var c; is_var d end. inversion_sigma p as [-> <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a & B' a } & C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with existT2 _ _ ?a ?b ?c = existT2 _ _ ?d ?e ?f => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f end. inversion_sigma p as [-> <- <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a & B' a } | C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with existT2 _ _ ?a ?b ?c = existT2 _ _ ?d ?e ?f => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f end. inversion_sigma p as [-> <- <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : exists2 a : exists2 a : AP, BP a & BP' a, CP _ (ex_proj2 (ex_of_ex2 a)) & CP' _ (ex_proj2 (ex_of_ex2 a))) (p : x = y), p = p. Proof. intros x y p; destr_sigma. inversion_sigma p as [p <- <-]; cbn [eq_rect] in *. lazymatch type of p with ex_intro2 _ _ ?a ?b ?c = ex_intro2 _ _ ?d ?e ?f => is_var a; is_var b; is_var c; is_var d; is_var e; is_var f end. inversion_sigma p as [-> <- <-]. cbn. fin_test_inversion_sigma. Qed. Goal forall (x y : { a : A & { b : { b : B a & C a b } & { d : D a (projT1 b) (projT2 b) & E _ _ _ d } } }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : A | { b : { b : B a | C a b } | { d : D a (proj1_sig b) (proj2_sig b) | E _ _ _ d } } }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : exists a : AP, exists b : exists b : BP a, CP a b, exists d : DP a (ex_proj1 b) (ex_proj2 b), EP _ _ _ d) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a } & C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a } | C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a & B' a } | C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : { a : A & B a & B' a } | C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : exists2 a : exists2 a : AP, BP a & BP' a, CP _ (ex_proj2 (ex_of_ex2 a)) & CP' _ (ex_proj2 (ex_of_ex2 a))) (p : x = y), p = p. Proof. test_inversion_sigma. Qed. Goal forall (x y : { a : A & { b : { b : B a & C a b } & { d : D a (projT1 b) (projT2 b) & E _ _ _ d } } }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : { a : A | { b : { b : B a | C a b } | { d : D a (proj1_sig b) (proj2_sig b) | E _ _ _ d } } }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : exists a : AP, exists b : exists b : BP a, CP a b, exists d : DP a (ex_proj1 b) (ex_proj2 b), EP _ _ _ d) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : { a : { a : A & B a } & C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : { a : { a : A & B a } | C _ (projT2 a) & C' _ (projT2 a) }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : { a : { a : A & B a & B' a } | C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : { a : { a : A & B a & B' a } | C _ (projT2 (sigT_of_sigT2 a)) & C' _ (projT2 (sigT_of_sigT2 a)) }) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. Goal forall (x y : exists2 a : exists2 a : AP, BP a & BP' a, CP _ (ex_proj2 (ex_of_ex2 a)) & CP' _ (ex_proj2 (ex_of_ex2 a))) (p : x = y), p = p. Proof. test_inversion_sigma_in_H. Qed. End inversion_sigma. rocq-9.2.0/test-suite/success/LetIn.v000066400000000000000000000005441516144147600174620ustar00rootroot00000000000000(* Simple let-in's *) Definition l1 := let P := 0 in P. Definition l2 := let P := nat in P. Definition l3 := let P := True in P. Definition l4 := let P := Prop in P. Definition l5 := let P := Type in P. (* Check casting of let-in *) Definition l6 := let P := 0:nat in P. Definition l7 := let P := True:Prop in P. Definition l8 := let P := True:Type in P. rocq-9.2.0/test-suite/success/LetPat.v000066400000000000000000000033411516144147600176360ustar00rootroot00000000000000(* Simple let-patterns *) Parameter A B : Type. Definition l1 (t : A * B * B) : A := let '(x, y, z) := t in x. Print l1. Definition l2 (t : (A * B) * B) : A := let '((x, y), z) := t in x. Definition l3 (t : A * (B * B)) : A := let '(x, (y, z)) := t in x. Print l3. Record someT (A : Type) := mkT { a : nat; b: A }. Definition l4 A (t : someT A) : nat := let 'mkT _ x y := t in x. Print l4. Print sigT. Definition l5 A (B : A -> Type) (t : sigT B) : B (projT1 t) := let 'existT _ x y := t return B (projT1 t) in y. Definition l6 A (B : A -> Type) (t : sigT B) : B (projT1 t) := let 'existT _ x y as t' := t return B (projT1 t') in y. Definition l7 A (B : A -> Type) (t : sigT B) : B (projT1 t) := let 'existT _ x y as t' in sigT _ := t return B (projT1 t') in y. Definition l8 A (B : A -> Type) (t : sigT B) : B (projT1 t) := match t with existT _ x y => y end. (** An example from algebra, using let' and inference of return clauses to deconstruct contexts. *) Record a_category (A : Type) (hom : A -> A -> Type) := { }. Definition category := { A : Type & { hom : A -> A -> Type & a_category A hom } }. Record a_functor (A : Type) (hom : A -> A -> Type) (C : a_category A hom) := { }. Notation " x :& y " := (@existT _ _ x y) (right associativity, at level 55) : core_scope. Definition functor (c d : category) := let ' A :& homA :& CA := c in let ' B :& homB :& CB := d in A -> B. Definition identity_functor (c : category) : functor c c := let 'A :& homA :& CA := c in fun x => x. Definition functor_composition (a b c : category) : functor a b -> functor b c -> functor a c := let 'A :& homA :& CA := a in let 'B :& homB :& CB := b in let 'C :& homB :& CB := c in fun f g => fun x => g (f x). rocq-9.2.0/test-suite/success/LocalDefinition.v000066400000000000000000000024561516144147600215160ustar00rootroot00000000000000(* Test consistent behavior of Local Definition (#8722) *) (* Test consistent behavior of Local Definition wrt Admitted *) Module TestAdmittedVisibility. Module A. #[warning="declaration-outside-section"] Let a1 : nat. Admitted. (* Suppose to behave like a "Local Definition" *) Local Definition b1 : nat. Admitted. (* Told to be a "Local Definition" *) Local Definition c1 := 0. Local Parameter d1 : nat. Section S. Let a2 : nat. Admitted. (* Told to be turned into a toplevel assumption *) Local Definition b2 : nat. Admitted. (* Told to be a "Local Definition" *) Local Definition c2 := 0. Local Parameter d2 : nat. End S. End A. Import A. Fail Check a1. (* used to be accepted *) Fail Check b1. (* used to be accepted *) Fail Check c1. Fail Check d1. Fail Check a2. (* used to be accepted *) Fail Check b2. (* used to be accepted *) Fail Check c2. Fail Check d2. End TestAdmittedVisibility. Module TestVariableAsInstances. Class U. Local Parameter b : U. Fail Definition testU := _ : U. (* _ unresolved *) Class T. #[warning="declaration-outside-section"] Variable a : T. (* warned to be the same as "Local Parameter" thus should not be an instance *) Fail Definition testT := _ : T. (* used to succeed *) End TestVariableAsInstances. rocq-9.2.0/test-suite/success/LtacDeprecation.v000066400000000000000000000007311516144147600215060ustar00rootroot00000000000000Set Warnings "+deprecated". #[deprecated(since = "8.8", note = "Use idtac instead")] Ltac foo x := idtac. Goal True. Fail (foo true). Abort. Fail Ltac bar := foo. Fail Tactic Notation "bar" := foo. #[deprecated(since = "8.8", note = "Use idtac instead")] Tactic Notation "bar" := idtac. Goal True. Fail bar. Abort. Fail Ltac zar := bar. Set Warnings "-deprecated". Ltac zar := foo. Ltac zarzar := bar. Set Warnings "+deprecated". Goal True. zar x. zarzar. Abort. rocq-9.2.0/test-suite/success/MangleNamesLight.v000066400000000000000000000010721516144147600216230ustar00rootroot00000000000000Axiom X : Type. Goal forall (x y z : X), X. intro. Check x. Set Mangle Names. intro. Fail Check y. Check _0. Set Mangle Names Light. intro. Fail Check z. Fail Check _1. Check _z. Abort. Fixpoint Lots (n : nat) : Type := match n with | 0 => X | S k => forall (x : X), Lots k end. Goal Lots 10. assert (_x8 : X) by admit. cbv; intros. Check _x9. Abort. Fixpoint Lots' (x : X) (n : nat) : Type := match n with | 0 => X | S k => forall _x, Lots' _x k end. Goal forall _x0, Lots' _x0 10. assert (_x8 : X) by admit. cbv; intros. Check __x9. simpl. Abort. rocq-9.2.0/test-suite/success/Mod_ltac.v000066400000000000000000000004561516144147600201730ustar00rootroot00000000000000(* Submitted by Houda Anoun *) Module toto. Ltac titi := auto. End toto. Module ti. Import toto. Ltac equal := match goal with | |- (?X1 = ?X1) => titi | |- _ => idtac end. End ti. Import ti. Definition simple : forall a : nat, a = a. intro. equal. Qed. rocq-9.2.0/test-suite/success/Mod_params.v000066400000000000000000000025371516144147600205350ustar00rootroot00000000000000(* Syntax test - all possible kinds of module parameters *) Module Type SIG. End SIG. Module Type FSIG (X: SIG). End FSIG. Module F (X: SIG). End F. Module Q. End Q. (* #trace Nametab.push;; #trace Nametab.push_short_name;; #trace Nametab.freeze;; #trace Nametab.unfreeze;; #trace Nametab.exists_cci;; *) Module M01. End M01. Module M02 (X: SIG). End M02. Module M03 (X Y: SIG). End M03. Module M04 (X: SIG) (Y: SIG). End M04. Module M05 (X Y: SIG) (Z1 Z: SIG). End M05. Module M06 (X: SIG) (Y: SIG). End M06. Module M07 (X Y: SIG) (Z1 Z: SIG). End M07. Module M08 : SIG. End M08. Module M09 (X: SIG) : SIG. End M09. Module M10 (X Y: SIG) : SIG. End M10. Module M11 (X: SIG) (Y: SIG) : SIG. End M11. Module M12 (X Y: SIG) (Z1 Z: SIG) : SIG. End M12. Module M13 (X: SIG) (Y: SIG) : SIG. End M13. Module M14 (X Y: SIG) (Z1 Z: SIG) : SIG. End M14. Module M15 := F Q. Module M16 (X: FSIG) := X Q. Module M17 (X Y: FSIG) := X Q. Module M18 (X: FSIG) (Y: SIG) := X Y. Module M19 (X Y: FSIG) (Z1 Z: SIG) := X Z. Module M20 (X: FSIG) (Y: SIG) := X Y. Module M21 (X Y: FSIG) (Z1 Z: SIG) := X Z. Module M22 : SIG := F Q. Module M23 (X: FSIG) : SIG := X Q. Module M24 (X Y: FSIG) : SIG := X Q. Module M25 (X: FSIG) (Y: SIG) : SIG := X Y. Module M26 (X Y: FSIG) (Z1 Z: SIG) : SIG := X Z. Module M27 (X: FSIG) (Y: SIG) : SIG := X Y. Module M28 (X Y: FSIG) (Z1 Z: SIG) : SIG := X Z. rocq-9.2.0/test-suite/success/Mod_strengthen.v000066400000000000000000000017031516144147600214250ustar00rootroot00000000000000Module Type Sub. Axiom Refl1 : forall x : nat, x = x. Axiom Refl2 : forall x : nat, x = x. Axiom Refl3 : forall x : nat, x = x. Inductive T : Set := A : T. End Sub. Module Type Main. Declare Module M: Sub. End Main. Module A <: Main. Module M <: Sub. Lemma Refl1 : forall x : nat, x = x. intros; reflexivity. Qed. Axiom Refl2 : forall x : nat, x = x. Lemma Refl3 : forall x : nat, x = x. intros; reflexivity. Defined. Inductive T : Set := A : T. End M. End A. (* first test *) Module F (S: Sub). Module M := S. End F. Module B <: Main with Module M:=A.M := F A.M. (* second test *) Lemma r1 : (A.M.Refl1 = B.M.Refl1). Proof. reflexivity. Qed. Lemma r2 : (A.M.Refl2 = B.M.Refl2). Proof. reflexivity. Qed. Lemma r3 : (A.M.Refl3 = B.M.Refl3). Proof. reflexivity. Qed. Lemma t : (A.M.T = B.M.T). Proof. reflexivity. Qed. Lemma a : (A.M.A = B.M.A). Proof. reflexivity. Qed. rocq-9.2.0/test-suite/success/Mod_type.v000066400000000000000000000010031516144147600202160ustar00rootroot00000000000000(* Check BZ#1025 submitted by Pierre-Luc Carmel Biron *) Module Type FOO. Parameter A : Type. End FOO. Module Type BAR. Declare Module Foo : FOO. End BAR. Module Bar : BAR. Module Fu : FOO. Definition A := Prop. End Fu. Module Foo := Fu. End Bar. (* Check BZ#2809: correct printing of modules with notations *) Module C. Inductive test : Type := | c1 : test | c2 : nat -> test. Notation "! x" := (c2 x) (at level 50). End C. Print C. (* Should print test_rect without failing *) rocq-9.2.0/test-suite/success/NestedInd.v000066400000000000000000000134051516144147600203240ustar00rootroot00000000000000Unset Elimination Schemes. Definition Decision (P : Prop) := {P} + {~ P}. Definition RelDecision {A B : Type} (R : A -> B -> Prop) := forall (x : A) (y : B), Decision (R x y) : Type. Inductive gmap_dep_ne (A : Type) : Type := GNode001 : gmap_dep_ne A -> gmap_dep_ne A | GNode010 : A -> gmap_dep_ne A | GNode011 : A -> gmap_dep_ne A -> gmap_dep_ne A | GNode100 : gmap_dep_ne A -> gmap_dep_ne A | GNode101 : gmap_dep_ne A -> gmap_dep_ne A -> gmap_dep_ne A | GNode110 : gmap_dep_ne A -> A -> gmap_dep_ne A | GNode111 : gmap_dep_ne A -> A -> gmap_dep_ne A -> gmap_dep_ne A. Variant gmap_dep (A : Type) : Type := GEmpty : gmap_dep A | GNodes : gmap_dep_ne A -> gmap_dep A. Arguments GEmpty {A}. Arguments GNodes {A}. Record gmap {K : Type} (EqDecision0 : RelDecision (@eq K)) (A : Type) : Type := GMap { gmap_car : gmap_dep A }. Inductive gtest {K : Type} (H : RelDecision (@eq K)) := GTest : gmap H (gtest H) -> gtest H. Arguments GTest {_ _} _. Definition option_union_with (A : Type) (f : A -> A -> option A) (mx my : option A) := match mx with | Some x => match my with | Some y => f x y | None => Some x end | None => match my with | Some y => Some y | None => None end end. Definition gmap_dep_ne_case (A : Type) (B : Type) (t : gmap_dep_ne A) (f : gmap_dep A -> option A -> gmap_dep A -> B) := match t with | GNode001 _ r => f GEmpty None (GNodes r) | GNode010 _ x => f GEmpty (Some (x)) GEmpty | GNode011 _ x r => f GEmpty (Some (x)) (GNodes r) | GNode100 _ l => f (GNodes l) None GEmpty | GNode101 _ l r => f (GNodes l) None (GNodes r) | GNode110 _ l x => f (GNodes l) (Some (x)) GEmpty | GNode111 _ l x r => f (GNodes l) (Some (x)) (GNodes r) end. Definition gmap_dep_omap_aux {A B : Type} (go : gmap_dep_ne A -> gmap_dep B) (tm : gmap_dep A) := match tm with | GEmpty => GEmpty | GNodes t' => go t' end. Definition option_bind {A B : Type} (f : A -> option B) (mx : option A) := match mx with | Some x => f x | None => None end. Definition GNode (A : Type) (ml : gmap_dep A) (mx : option (A)) (mr : gmap_dep A) := match ml with | GEmpty => match mx with | Some x => match mr with | GEmpty => GNodes (GNode010 _ x) | GNodes r => GNodes (GNode011 _ x r) end | None => match mr with | GEmpty => GEmpty | GNodes r => GNodes (GNode001 _ r) end end | GNodes l => match mx with | Some (x) => match mr with | GEmpty => GNodes (GNode110 _ l x) | GNodes r => GNodes (GNode111 _ l x r) end | None => match mr with | GEmpty => GNodes (GNode100 _ l) | GNodes r => GNodes (GNode101 _ l r) end end end. Definition gmap_dep_ne_omap (A B : Type) (f : A -> option B) := fix go (t : gmap_dep_ne A) {struct t} : gmap_dep B := gmap_dep_ne_case _ _ t (fun (ml : gmap_dep A) (mx : option A) (mr : gmap_dep A) => GNode _ (gmap_dep_omap_aux (go) ml) (option_bind f mx) (gmap_dep_omap_aux (go) mr)). Definition gmap_merge_aux (A B C : Type) (go : gmap_dep_ne A -> gmap_dep_ne B -> gmap_dep C) (f : option A -> option B -> option C) (mt1 : gmap_dep A) (mt2 : gmap_dep B) := match mt1 with | GEmpty => match mt2 with | GEmpty => GEmpty | GNodes t2' => gmap_dep_ne_omap _ _ (fun x : B => f None (Some x)) t2' end | GNodes t1' => match mt2 with | GEmpty => gmap_dep_ne_omap _ _ (fun x : A => f (Some x) None) t1' | GNodes t2' => go t1' t2' end end. Definition diag_None' {A B C : Type} (f : option A -> option B -> option C) (mx : option (A)) (my : option (B)) := match mx with | Some (x) => match my with | Some (y) => f (Some x) (Some y) | None => f (Some x) None end | None => match my with | Some (y) => f None (Some y) | None => None end end. Definition gmap_dep_ne_merge {A B C : Type} (f : option A -> option B -> option C) := fix go (t1 : gmap_dep_ne A) (t2 : gmap_dep_ne B) {struct t1} : gmap_dep C := gmap_dep_ne_case _ _ t1 (fun (ml1 : gmap_dep A) (mx1 : option (A)) (mr1 : gmap_dep A) => gmap_dep_ne_case _ _ t2 (fun (ml2 : gmap_dep B) (mx2 : option (B)) (mr2 : gmap_dep B) => GNode _ (gmap_merge_aux _ _ _ go f ml1 ml2) (diag_None' f mx1 mx2) (gmap_merge_aux _ _ _ go f mr1 mr2))). Definition gmap_dep_merge {A B C : Type} (f : option A -> option B -> option C) := gmap_merge_aux _ _ _ (gmap_dep_ne_merge f) f : gmap_dep A -> gmap_dep B -> gmap_dep C. Definition gmap_merge (K : Type) (H : RelDecision (@eq K)) (A B C : Type) (f : option A -> option B -> option C) := (fun '{| gmap_car := mt1 |} '{| gmap_car := mt2 |} => {| gmap_car := gmap_dep_merge f mt1 mt2 |}) : (gmap H A) -> (gmap H B) -> (gmap H C). Fixpoint gtest_merge {K : Type} (H : RelDecision (@eq K)) (t1 t2 : gtest H) {struct t1} : gtest H := match t1, t2 with | GTest ts1, GTest ts2 => GTest (gmap_merge K H _ _ _ (@option_union_with _ (fun t1 t2 => Some (gtest_merge H t1 t2))) ts1 ts2) end. (* An example from metacoq (simplified) *) Notation "x .Ο€2" := (projT2 x) (at level 0). Parameter term : Type. Inductive All (P : term -> Type) : Type := | All_cons : {x:term & P x} -> All P -> All P. Inductive inferring (Ξ£ : unit) : term -> Type := | infer x : All (inferring Ξ£) -> inferring Ξ£ x. Fixpoint inferring_size {Ξ£ t} (d : inferring Ξ£ t) {struct d} : nat := match d with | infer _ _ (All_cons _ p _) => inferring_size p.Ο€2 end. rocq-9.2.0/test-suite/success/NotationDeprecation.v000066400000000000000000000012131516144147600224120ustar00rootroot00000000000000Module Syndefs. #[deprecated(since = "8.9", note = "Do not use.")] Notation foo := Prop. Fail #[deprecated(since = "8.9", note = "Do not use."), deprecated(since = "8.10", note = "Duplicated deprecation.")] Notation foo := Prop. Check foo. Set Warnings "+deprecated". Fail Check foo. End Syndefs. Module Notations. #[deprecated(since = "8.9", note = "Do not use.")] Notation "!!" := Prop. Check !!. Set Warnings "+deprecated". Fail Check !!. End Notations. Module Infix. #[deprecated(since = "8.9", note = "Do not use.")] Infix "!!" := plus (at level 1). Check (_ !! _). Set Warnings "+deprecated". Fail Check (_ !! _). End Infix. rocq-9.2.0/test-suite/success/Notations.v000066400000000000000000000122341516144147600204240ustar00rootroot00000000000000(* Check that "where" clause behaves as if given independently of the *) (* definition (variant of BZ#1132 submitted by Assia Mahboubi) *) Fixpoint plus1 (n m:nat) {struct n} : nat := match n with | O => m | S p => S (p+m) end where "n + m" := (plus1 n m) : nat_scope. (* Check behaviour wrt yet empty levels (see Stephane's bug #1850) *) Parameter P : Type -> Type -> Type -> Type. Notation "e |= t --> v" := (P e t v) (at level 100, t at level 54). Check (nat |= nat --> nat). (* Check that first non empty definition at an empty level can be of any associativity *) Module Type v1. Notation "x +1" := (S x) (at level 8, left associativity). End v1. Module Type v2. Notation "x +1" := (S x) (at level 8, right associativity). End v2. (* Check that empty levels (here 8 and 2 in pattern) are added in the right order *) Notation "' 'C_' G ( A )" := (A,G) (at level 8, G at level 2). (* Check import of notations from within a section *) Notation "+1 x" := (S x) (at level 25, x at level 9). Section A. Require Import make_notation. End A. (* Check use of "$" (see bug #1961) *) Notation "$ x" := (id x) (at level 30). Check ($ 5). (* Check regression of bug #2087 *) Notation "'exists' x , P" := (x, P) (at level 200, x ident, right associativity, only parsing). Definition foo P := let '(exists x, Q) := P in x = Q :> nat. (* Check empty levels when extending binder_constr *) Notation "'exists' x >= y , P" := (exists x, x >= y /\ P)%nat (at level 200, x ident, right associativity, y at level 69). (* This used to loop at some time before r12491 *) Notation R x := (@pair _ _ x). Check (fun x:nat*nat => match x with R x y => (x,y) end). (* Check multi-tokens recursive notations *) Local Notation "[ a # ; .. # ; b ]" := (a + .. (b + 0) ..). Check [ 0 ]. Check [ 0 # ; 1 ]. (* Check well-scoping of alpha-renaming of private binders *) (* see bug #2248 (thanks to Marc Lasson) *) Notation "{ q , r | P }" := (fun (p:nat*nat) => let (q, r) := p in P). Check (fun p => {q,r| q + r = p}). (* Check that declarations of empty levels are correctly backtracked *) Section B. Notation "*" := 5 (at level 0) : nat_scope. Notation "[ h ] p" := (h + p) (at level 8, p at level 9, h at level 7) : nat_scope. End B. (* Should succeed *) Definition n := 5 * 5. (* Check that lonely notations (here FOO) do not modify the visibility of scoped interpretations (bug #2634 fixed in r14819) *) Notation "x ++++ y" := (mult x y) (at level 40). Notation "x ++++ y" := (plus x y) : A_scope. Open Scope A_scope. Notation "'FOO' x" := (S x) (at level 40). Goal (2 ++++ 3) = 5. reflexivity. Abort. (* Check correct failure handling when a non-constructor notation is used in cases pattern (bug #2724 in 8.3 and 8.4beta) *) Notation "'FORALL' x .. y , P" := (forall x, .. (forall y, P) ..) (at level 200, x binder, y binder, right associativity) : type_scope. Fail Check fun x => match x with S (FORALL x, _) => 0 end. (* Bug #2708: don't check for scope of variables used as binder *) Parameter traverse : (nat -> unit) -> (nat -> unit). Notation traverse_var f l := (traverse (fun l => f l) l). (* Check that when an ident become a keyword, it does not break previous rules relying on the string to be classified as an ident *) Notation "'intros' x" := (S x) (at level 0). Goal True -> True. intros H. exact H. Qed. (* Check absence of collision on ".." in nested notations with ".." *) Notation "[ a , .. , b ]" := (a, (.. (b,tt) ..)). (* Check that vector notations do not break Ltac [] (bugs #4785, #4733) *) Notation "[ ]" := (nil _) (format "[ ]") : vector_scope. Goal True. idtac; []. (* important for test: no space here *) constructor. Qed. (* Check parsing of { and } is not affected by notations #3479 *) Notation " |- {{ a }} b" := (a=b) (no associativity, at level 10). Goal True. {{ exact I. }} Qed. Check |- {{ 0 }} 0. (* Check parsing of { and } is not affected by notations #3479 *) Notation " |- {{ a }} b" := (a=b) (no associativity, at level 10). Goal True. {{ exact I. }} Qed. (* Check that we can have notations without any symbol iff they are "only printing". *) Fail Notation "" := (@nil). Notation "" := (@nil) (only printing). (* Check that a notation cannot be neither parsing nor printing. *) Fail Notation "'foobarkeyword'" := (@nil) (only parsing, only printing). (* Check "where" clause for inductive types with parameters *) Reserved Notation "x === y" (at level 50). Inductive EQ {A} (x:A) : A -> Prop := REFL : x === x where "x === y" := (EQ x y). (* Check that strictly ident or _ are coerced to a name *) Fail Check {x@{u},y|x=x}. Fail Check {?[n],y|0=0}. (* Check that 10 is well declared left associative *) Section C. Notation "f $$$ x" := (id f x) (at level 10, left associativity). End C. (* Scope names should not start with an underscore *) Fail Declare Scope _scope_start_underscore. (* Scope delimiters should not start with an underscore *) Fail Delimit Scope type_scope with _type. Module ImplicitArgumentsPrimToken. (* Check that implicit arguments of number notations are taken into account *) Class T (A:Type). Parameter (a:T nat). Axiom f : forall A, T A -> A. Arguments f {A} {_}. Notation "0" := f. Check 0 = 1. End ImplicitArgumentsPrimToken. rocq-9.2.0/test-suite/success/Notations2.v000066400000000000000000000212031516144147600205020ustar00rootroot00000000000000(* This file is giving some examples about how implicit arguments and scopes are treated when using abbreviations or notations, in terms or patterns, or when using @ and parentheses in terms and patterns. The convention is: Constant foo with implicit arguments and scopes used in a term or a pattern: foo do not deactivate further arguments and scopes @foo deactivate further arguments and scopes (foo x) deactivate further arguments and scopes (@foo x) deactivate further arguments and scopes Notations binding to foo: # := foo do not deactivate further arguments and scopes # := @foo deactivate further arguments and scopes # x := foo x do not deactivate further arguments and scopes # x := @foo x do not deactivate further arguments and scopes Abbreviations binding to foo: f := foo do not deactivate further arguments and scopes f := @foo deactivate further arguments and scopes f x := foo x do not deactivate further arguments and scopes f x := @foo x do not deactivate further arguments and scopes *) (* One checks that abbreviations and notations in patterns now behave like in terms *) Inductive prod' A : Type -> Type := | pair' (a:A) B (b:B) (c:bool) : prod' A B. Arguments pair' [A] a%_bool_scope [B] b%_bool_scope c%_bool_scope. Notation "0" := true : bool_scope. (* 1. Abbreviations do not stop implicit arguments to be inserted and scopes to be used *) Notation c1 x := (pair' x). Check pair' 0 0 0 : prod' bool bool. Check (pair' 0) _ 0%bool 0%bool : prod' bool bool. (* parentheses are blocking implicit and scopes *) Check c1 0 0 0 : prod' bool bool. Check fun x : prod' bool bool => match x with c1 0 y 0 => 2 | _ => 1 end. (* 2. Abbreviations do not stop implicit arguments to be inserted and scopes to be used *) Notation c2 x := (@pair' _ x). Check (@pair' _ 0) _ 0%bool 0%bool : prod' bool bool. (* parentheses are blocking implicit and scopes *) Check c2 0 0 0 : prod' bool bool. Check fun A (x : prod' bool A) => match x with c2 0 y 0 => 2 | _ => 1 end. Check fun A (x : prod' bool A) => match x with (@pair' _ 0) _ y 0%bool => 2 | _ => 1 end. (* 3. Abbreviations do not stop implicit arguments to be inserted and scopes to be used *) Notation c3 x := ((@pair') _ x). Check (@pair') _ 0%bool _ 0%bool 0%bool : prod' bool bool. (* @ is blocking implicit and scopes *) Check ((@pair') _ 0%bool) _ 0%bool 0%bool : prod' bool bool. (* parentheses and @ are blocking implicit and scopes *) Check c3 0 0 0 : prod' bool bool. Check fun A (x :prod' bool A) => match x with c3 0 y 0 => 2 | _ => 1 end. (* 4. Abbreviations do not stop implicit arguments to be inserted and scopes to be used *) (* unless an atomic @ is given *) Notation c4 := (@pair'). Check (@pair') _ 0%bool _ 0%bool 0%bool : prod' bool bool. Check c4 _ 0%bool _ 0%bool 0%bool : prod' bool bool. Check fun A (x :prod' bool A) => match x with c4 _ 0%bool _ y 0%bool => 2 | _ => 1 end. Check fun A (x :prod' bool A) => match x with (@pair') _ 0%bool _ y 0%bool => 2 | _ => 1 end. (* 5. Non-@id notations inherit implicit arguments to be inserted and scopes to be used *) Notation "# x" := (pair' x) (at level 0, x at level 1). Check pair' 0 0 0 : prod' bool bool. Check # 0 0 0 : prod' bool bool. Check fun A (x :prod' bool A) => match x with # 0 y 0 => 2 | _ => 1 end. (* 6. Non-@id notations inherit implicit arguments to be inserted and scopes to be used *) Notation "## x" := ((@pair') _ x) (at level 0, x at level 1). Check (@pair') _ 0%bool _ 0%bool 0%bool : prod' bool bool. Check ((@pair') _ 0%bool) _ 0%bool 0%bool : prod' bool bool. Check ## 0%bool 0 0 : prod' bool bool. Check fun A (x :prod' bool A) => match x with ## 0%bool y 0 => 2 | _ => 1 end. (* 7. Notations stop further implicit arguments to be inserted and scopes to be used *) Notation "###" := (@pair') (at level 0). Check (@pair') _ 0%bool _ 0%bool 0%bool : prod' bool bool. Check ### _ 0%bool _ 0%bool 0%bool : prod' bool bool. Check fun A (x :prod' bool A) => match x with ### _ 0%bool _ y 0%bool => 2 | _ => 1 end. (* 8. Notations w/o @ preserves implicit arguments and scopes *) Notation "####" := pair' (at level 0). Check #### 0 0 0 : prod' bool bool. Check fun A (x :prod' bool A) => match x with #### 0 y 0 => 2 | _ => 1 end. (* 9. Non-@id notations inherit implicit arguments and scopes *) Notation "##### x" := (pair' x) (at level 0, x at level 1). Check ##### 0 0 0 : prod' bool bool. Check fun A (x :prod' bool A) => match x with ##### 0 y 0 => 2 | _ => 1 end. (* 10. Check computation of binding variable through other notations *) (* it should be detected as binding variable and the scopes not being checked *) Notation "'FUNNAT' i => t" := (fun i : nat => i = t) (at level 200). Notation "'Funnat' i => t" := (FUNNAT i => t + i%nat) (at level 200). (* 11. Notations with needed factorization of a recursive pattern *) (* See https://github.com/rocq-prover/rocq/issues/6078#issuecomment-342287412 *) Module M11. Notation "[:: x1 ; .. ; xn & s ]" := (cons x1 .. (cons xn s) ..). Notation "[:: x1 ; .. ; xn ]" := (cons x1 .. (cons xn nil) ..). Check [:: 1 ; 2 ; 3 ]. Check [:: 1 ; 2 ; 3 & nil ]. (* was failing *) End M11. (* 12. Preventively check that a variable which does not occur can be instantiated *) (* by any term. In particular, it should not be restricted to a binder *) Module M12. Notation "N ++ x" := (S x) (only parsing). Check 2 ++ 0. End M12. (* 13. Check that internal data about associativity are not used in comparing levels *) Module M13. Notation "x ;; z" := (x + z) (at level 100, z at level 200, only parsing, right associativity). Notation "x ;; z" := (x * z) (at level 100, z at level 200, only parsing) : foo_scope. End M13. (* 14. Check that a notation with a "ident" binder does not include a pattern *) Module M14. Notation "'myexists' x , p" := (ex (fun x => p)) (at level 200, x ident, p at level 200, right associativity) : type_scope. Check myexists I, I = 0. (* Should not be seen as a constructor *) End M14. (* 15. Testing different ways to give the same levels without failing *) Module M15. Local Notation "###### x" := (S x) (right associativity, at level 79, x at next level). Fail Local Notation "###### x" := (S x) (right associativity, at level 79, x at level 79). Local Notation "###### x" := (S x) (at level 79). End M15. (* 16. Some test about custom entries *) Module M16. (* Test locality *) Local Declare Custom Entry foo. Fail Notation "#" := 0 (in custom foo). (* Should be local *) Local Notation "#" := 0 (in custom foo). (* Test import *) Module A. Declare Custom Entry foo2. End A. Notation "##" := 0 (in custom foo2). Import A. Local Notation "####" := 0 (in custom foo2). (* Test Print Grammar *) Print Custom Grammar foo. Print Custom Grammar foo2. End M16. Fail Local Notation "###" := 0 (in custom foo). Fail Print Custom Grammar foo. Notation "####" := 0 (in custom foo2). (* Example showing the need for strong evaluation of cases_pattern_of_glob_constr (this used to raise Not_found at some time) *) Module M17. Notation "# x ## t & u" := ((fun x => (x,t)),(fun x => (x,u))) (at level 1, x pattern). Check fun y : nat => # (x,z) ## y & y. End M17. Module Bug10750. Notation "#" := 0 (only printing). Print Visibility. End Bug10750. Module M18. Module A. Module B. Infix "+++" := Nat.add (at level 70). End B. End A. Import A. (* Check that the notation in module B is not visible *) Infix "+++" := Nat.add (at level 80). End M18. Module InheritanceArgumentScopes. Axiom p : forall (A:Type) (b:nat), A = A /\ b = b. Check fun A n => p (A * A) (n * n). (* safety check *) Notation q := @p. Check fun A n => q (A * A) (n * n). (* check that argument scopes are propagated *) End InheritanceArgumentScopes. Module InheritanceMaximalImplicitPureNotation. Definition id {A B:Type} (a:B) := a. Notation "#" := (@id nat). Check # = (fun a:nat => a). (* # should inherit its maximal implicit argument *) End InheritanceMaximalImplicitPureNotation. Module TreeLikeLookAhead. Notation "6 ^" := true (at level 0, format "6 ^"). Notation "6 ?" := false (at level 0, format "6 ?"). Check 6. End TreeLikeLookAhead. Module FactorizationListSeparators. Notation "[ a + + .. + + c | d ]" := (cons a .. (cons c d) ..) (a at level 10). Notation "[ a + + .. + + c ]" := (cons a .. (cons c nil) ..) (a at level 10). Check [0 + + 1 | nil]. Check [0 + + 1]. End FactorizationListSeparators. Module TestNonExistentCustomOnlyPrinting. Fail Notation "[ x ]" := (id x) (x custom doesntexist, only printing). Fail Notation "# x" := (id x) (in custom doesntexist, only printing). End TestNonExistentCustomOnlyPrinting. Module NotationClauseIn. Notation "1" := unit. Check fun x => match x in 1 with tt => 0 end. End NotationClauseIn. rocq-9.2.0/test-suite/success/NotationsAndLtac.v000066400000000000000000000027711516144147600216600ustar00rootroot00000000000000(* Test that adding notations that overlap with the tactic grammar does not * interfere with Ltac parsing. *) Module test1. Notation "x [ y ]" := (fst (id x, id y)) (at level 11). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test1. Module test2. Notation "x [ y ]" := (fst (id x, id y)) (at level 100). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test2. Module test3. Notation "x [ y ]" := (fst (id x, id y)) (at level 1). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test3. Module test1'. Notation "x [ [ y ] ] " := (fst (id x, id y)) (at level 11). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test1'. Module test2'. Notation "x [ [ y ] ]" := (fst (id x, id y)) (at level 100). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test2'. Module test3'. Notation "x [ [ y ] ]" := (fst (id x, id y)) (at level 1). Goal True \/ (exists x : nat, True /\ True) -> True. Proof. intros [|[a [y z]]]; [idtac|idtac]; try solve [eauto | trivial; [trivial]]. Qed. End test3'. rocq-9.2.0/test-suite/success/NumberNotationsNoLocal.v000066400000000000000000000006421516144147600230450ustar00rootroot00000000000000(* Test that number notations don't work on proof-local variables, especially not ones containing evars *) Inductive unit11 := tt11. Declare Scope unit11_scope. Delimit Scope unit11_scope with unit11. Goal True. evar (to_uint : unit11 -> Decimal.uint). evar (of_uint : Decimal.uint -> unit11). Fail Number Notation unit11 of_uint to_uint : uint11_scope. exact I. Unshelve. all: solve [ constructor ]. Qed. rocq-9.2.0/test-suite/success/Observational.v000066400000000000000000000060041516144147600212540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* SProp := obseq_refl : x ~ x where "x ~ y" := (@obseq _ x y) : type_scope. Arguments obseq {A} x _. Arguments obseq_refl {A x} , [A] x. Instance obseq_Has_refl@{Ξ±;l} : Has_refl@{Ξ± SProp;l Set} (@obseq) := fun A x => obseq_refl. Instance obseq_Has_J_elim_SProp@{Ξ±;l} : Has_J@{Ξ± SProp SProp;l Set Set} (@obseq) _ := @obseq_sind. Hint Resolve obseq_Has_J_elim_SProp : rewrite_instances. Instance obseq_Has_Leibniz_elim_SProp@{Ξ±;l} : Has_Leibniz@{Ξ± SProp SProp;l Set Set} (@obseq) := fun A x P t y e => @obseq_sind A x (fun x _ => P x) t y e. Hint Resolve obseq_Has_Leibniz_elim_SProp : rewrite_instances. Instance obseq_Has_Leibniz_r_elim_SProp@{Ξ±;l +} : Has_Leibniz_r@{Ξ± SProp SProp;l Set Set} (@obseq) := fun A x P t y e => @obseq_sind A x (fun x _ => P x) t y (sym@{Ξ± SProp;l Set} e). Hint Resolve obseq_Has_Leibniz_r_elim_SProp : rewrite_instances. Parameter cast@{Ξ±;u u' | u A -> B. Notation "e # a" := (cast _ _ e a) (at level 55, only parsing). Instance obseq_Has_Leibniz_elim@{Ξ± Ξ²;l l' +} : Has_Leibniz@{Ξ± SProp Ξ²;l Set l'} (@obseq) := { leibniz := fun A x P px y e => cast (P x) (P y) (ap P e) px}. Hint Resolve obseq_Has_Leibniz_elim : rewrite_instances. Instance obseq_Has_Leibniz_r_elim@{Ξ± Ξ²;l l' +} : Has_Leibniz_r@{Ξ± SProp Ξ²;l Set l'} (@obseq) := { leibniz_r := fun A x P px y e => cast (P x) (P y) (ap P (sym e)) px}. Hint Resolve obseq_Has_Leibniz_r_elim : rewrite_instances. Definition obseq_apd@{sa sb; la lb lb' +} {A : Type@{sa;la}} {a} (P : forall b : A, a ~ b -> Type@{sb ; lb}) (b : A) (e : a ~ b) : @obseq _ (P a (refl A a)) (P b e) := J_eliminator _ a (fun b e => @obseq _ (P a (refl _ _)) (P b e)) (refl _ _) b e. Instance obseq_Has_J_elim@{Ξ± Ξ²;l l' +} : Has_J@{Ξ± SProp Ξ²;l l l'} (@obseq) _ := fun A a P t b e => cast (P a (refl _ _)) (P b e) (obseq_apd@{Ξ± Ξ² ;l l' _ _} P b e) t. Hint Resolve obseq_Has_J_elim : rewrite_instances. Lemma test {A:Type} (a b : A) (P : A -> Type) : a ~ b -> P a -> P b. Proof. intros e Pa. rewrite <- e. auto. Defined. Lemma test2 {A:Type} (a b : A) (P : A -> Type) : a ~ b -> P a -> P b. Proof. intros e Pa. symmetry in e. rewrite e. auto. Defined. rocq-9.2.0/test-suite/success/PCase.v000066400000000000000000000027531516144147600174460ustar00rootroot00000000000000 (** Some tests of patterns containing matchs ending with joker branches. Cf. the new form of the [constr_pattern] constructor [PCase] in [pretyping/pattern.ml] *) (* A universal match matcher *) Ltac kill_match := match goal with |- context [ match ?x with _ => _ end ] => destruct x end. (* A match matcher restricted to a given type : nat *) Ltac kill_match_nat := match goal with |- context [ match ?x in nat with _ => _ end ] => destruct x end. (* Another way to restrict to a given type : give a branch *) Ltac kill_match_nat2 := match goal with |- context [ match ?x with S _ => _ | _ => _ end ] => destruct x end. (* This should act only on empty match *) Ltac kill_match_empty := match goal with |- context [ match ?x with end ] => destruct x end. Lemma test1 (b:bool) : if b then True else O=O. Proof. Fail kill_match_nat. Fail kill_match_nat2. Fail kill_match_empty. kill_match. exact I. exact eq_refl. Qed. Lemma test2a (n:nat) : match n with O => True | S n => (n = n) end. Proof. Fail kill_match_empty. kill_match_nat. exact I. exact eq_refl. Qed. Lemma test2b (n:nat) : match n with O => True | S n => (n = n) end. Proof. kill_match_nat2. exact I. exact eq_refl. Qed. Lemma test2c (n:nat) : match n with O => True | S n => (n = n) end. Proof. kill_match. exact I. exact eq_refl. Qed. Lemma test3a (f:False) : match f return Prop with end. Proof. kill_match_empty. Qed. Lemma test3b (f:False) : match f return Prop with end. Proof. kill_match. Qed. rocq-9.2.0/test-suite/success/PPFix.v000066400000000000000000000003661516144147600174370ustar00rootroot00000000000000 (* To test PP of fixpoints *) Require Import TestSuite.arith. Check fix a(n: nat): n<5 -> nat := match n return n<5 -> nat with | 0 => fun _ => 0 | S n => fun h => S (a n (proj2 (Nat.succ_lt_mono _ _) (Nat.lt_lt_succ_r _ _ h))) end. rocq-9.2.0/test-suite/success/PartialImport.v000066400000000000000000000040021516144147600212270ustar00rootroot00000000000000Module M. Definition a := 0. Definition b := 1. Module N. Notation c := (a + b). End N. Inductive even : nat -> Prop := | even_0 : even 0 | even_S n : odd n -> even (S n) with odd : nat -> Set := odd_S n : even n -> odd (S n). End M. Module Simple. Import M(a). Check a. Fail Check b. Fail Check N.c. (* todo output test: this prints a+M.b since the notation isn't imported *) Check M.N.c. Fail Import M(c). Fail Import M(M.b). Import M(N.c). Check N.c. (* interestingly prints N.c (also does with unfiltered Import M) *) Import M(even(..)). Check even. Check even_0. Check even_S. Check even_sind. Check even_ind. Fail Check even_rect. (* doesn't exist *) Fail Check odd. Check M.odd. Fail Check odd_S. Fail Check odd_sind. End Simple. Module WithExport. Module X. Export M(a, N.c). End X. Import X. Check a. Check N.c. (* also prints N.c *) Fail Check b. End WithExport. Module IgnoreLocals. Module X. Local Definition x := 0. Definition y := 1. End X. Set Warnings "+not-importable". Fail Import X(x,y). Set Warnings "-not-importable". Import X(x,y). Check y. Fail Check x. Check X.x. End IgnoreLocals. Module FancyFunctor. (* A fancy behaviour with functors, not sure if we want to keep it but at least the test will ensure changes are deliberate. *) Module Type T. Parameter x : nat. End T. Module X. Definition x := 0. Definition y := 1. End X. Module Y. Local Definition x := 2. End Y. Module F(A:T). Export A(x). End F. Module Import M := F X. Check x. Fail Check y. Module N := F Y. Set Warnings "+not-importable". Fail Import N. Set Warnings "-not-importable". Import N. Check eq_refl : x = 0. End FancyFunctor. Require Import Sumbool(sumbool_of_bool). Check sumbool_of_bool. Check Sumbool.bool_eq_rec. Fail Require Sumbool(sumbool_of_bool). Fail Require Import Sumbool(not_a_real_definition). Fail Require Import(notations) Sumbool(sumbool_of_bool). rocq-9.2.0/test-suite/success/PatternsInBinders.v000066400000000000000000000026221516144147600220440ustar00rootroot00000000000000(** The purpose of this file is to test functional properties of the destructive patterns used in binders ([fun] and [forall]). *) Definition swap {A B} '((x,y) : A*B) := (y,x). (** Tests the use of patterns in [fun] and [Definition] *) Section TestFun. Variables A B : Type. Goal forall (x:A) (y:B), swap (x,y) = (y,x). Proof. reflexivity. Qed. Goal forall u:A*B, swap (swap u) = u. Proof. destruct u. reflexivity. Qed. Goal @swap A B = fun '(x,y) => (y,x). Proof. reflexivity. Qed. End TestFun. (** Tests the use of patterns in [forall] *) Section TestForall. Variables A B : Type. Goal forall '((x,y) : A*B), swap (x,y) = (y,x). Proof. intros [x y]. reflexivity. Qed. Goal forall x0:A, exists '((x,y) : A*A), swap (x,y) = (x,y). Proof. intros x0. exists (x0,x0). reflexivity. Qed. End TestForall. (** Tests the use of patterns in dependent definitions. *) Section TestDependent. Inductive Fin (n:nat) := Z : Fin n. Definition F '(n,p) : Type := (Fin n * Fin p)%type. Definition both_z '(n,p) : F (n,p) := (Z _,Z _). End TestDependent. (** Tests with a few other types just to make sure parsing is robust. *) Section TestExtra. Definition proj_informative {A P} '(exist _ x _ : { x:A | P x }) : A := x. Inductive Foo := Bar : nat -> bool -> unit -> nat -> Foo. Definition foo '(Bar n b tt p) := if b then n+p else n-p. End TestExtra. rocq-9.2.0/test-suite/success/Print.v000066400000000000000000000004411516144147600175370ustar00rootroot00000000000000Print Tables. Print ML Path. Print ML Modules. Print LoadPath. Print Graph. Print Coercions. Print Classes. Print nat. Print Term O. Print All. Print Grammar constr. Inspect 10. Section A. Coercion f (x : nat) : Prop := True. Print Coercion Paths nat Sortclass. Print Section A. End A. rocq-9.2.0/test-suite/success/PrivateInd.v000066400000000000000000000014131516144147600205100ustar00rootroot00000000000000 Module M. Private Inductive foo := . Definition bar (A:Prop) (_:A=True) (x:foo) : A := match x with end. End M. Goal M.foo -> False. Proof. Fail let c := eval cbv in c in match c with context c [True] => (* ltac context instantiation calls Typing *) let c := context c [False] in exact c end. let c := open_constr:(M.bar False (ltac:(exact_no_check (eq_refl True)))) in let c := eval cbv in c in exact c. (* check no goals remain *) Unshelve. all:fail. Fail Qed. Abort. Fail Definition bar := Eval cbv in M.bar. Module N. Private Inductive foo := C : nat -> nat -> foo. Definition use x := match x with C a b => a + b end. End N. Definition five := N.C 2 3. Definition five' := Eval cbv in N.use five. Check eq_refl : five' = 5. rocq-9.2.0/test-suite/success/ProgramFixpoint.v000066400000000000000000000006711516144147600216000ustar00rootroot00000000000000Require Import Program.Basics Program.Tactics. Module ProgramFixProto. (* Check the presence of [fix_proto] so that a preliminary work done on obligations can be done automatically *) Program Fixpoint do_bug m : { k : nat | exists u : nat, k = m } := match m with | 0 => 0 | S m' => S (do_bug m') end. Next Obligation. exists 0. reflexivity. Qed. Next Obligation. exists 0. reflexivity. Defined. End ProgramFixProto. rocq-9.2.0/test-suite/success/Projection.v000066400000000000000000000023761516144147600205700ustar00rootroot00000000000000Record foo (A : Type) := { B :> Type }. Lemma bar (f : foo nat) (x : f) : x = x. destruct f. simpl B. simpl B in x. Abort. Structure S : Type := {Dom : Type; Op : Dom -> Dom -> Dom}. Check (fun s : S => Dom s). Check (fun s : S => Op s). Check (fun (s : S) (a b : Dom s) => Op s a b). (* v8 Check fun s:S => s.(Dom). Check fun s:S => s.(Op). Check fun (s:S) (a b:s.(Dom)) => s.(Op) a b. *) Set Implicit Arguments. Unset Strict Implicit. Unset Strict Implicit. Structure S' (A : Set) : Type := {Dom' : Type; Op' : A -> Dom' -> Dom'}. Check (fun s : S' nat => Dom' s). Check (fun s : S' nat => Op' (s:=s)). Check (fun s : S' nat => Op' (A:=nat) (s:=s)). Check (fun (s : S' nat) (a : nat) (b : Dom' s) => Op' a b). Check (fun (s : S' nat) (a : nat) (b : Dom' s) => Op' (A:=nat) (s:=s) a b). (* v8 Check fun s:S' => s.(Dom'). Check fun s:S' => s.(Op'). Check fun (s:S') (a b:s.(Dom')) => _.(Op') a b. Check fun (s:S') (a b:s.(Dom')) => s.(Op') a b. Set Implicit Arguments. Unset Strict Implicits. Structure S' (A:Set) : Type := {Dom' : Type; Op' : A -> Dom' -> Dom'}. Check fun s:S' nat => s.(Dom'). Check fun s:S' nat => s.(Op'). Check fun (s:S' nat) (a:nat) (b:s.(Dom')) => _.(@Op' nat) a b. Check fun (s:S' nat) (a:nat) (b:s.(Dom')) => s.(Op') a b. *) rocq-9.2.0/test-suite/success/QualifiedGoalNames.v000066400000000000000000000015671516144147600221470ustar00rootroot00000000000000(* -*- mode: coq -*- *) Set Generate Goal Names. Goal forall a b : bool, a = a. Proof. intros. destruct a. [true]: destruct b. [true.true]: reflexivity. [true.false]: reflexivity. [false]: reflexivity. Qed. Goal forall a b c : bool, a = a. Proof. intros. destruct a. all: destruct b. all: destruct c. [true.true.true]: reflexivity. [true.true.false]: reflexivity. [true.false.true]: reflexivity. [true.false.false]: reflexivity. [false.true.true]: reflexivity. [false.true.false]: reflexivity. [false.false.true]: reflexivity. [false.false.false]: reflexivity. Qed. Goal forall n m : nat, n + m = m + n. Proof. intros. induction m; simpl. [O]: { induction n. [O.O]: reflexivity. [O.S]: { simpl. congruence. } } [S]: { induction n. [S.O]: { rewrite <- IHm. reflexivity. } [S.S]: { rewrite <- IHm. auto. } } Qed. rocq-9.2.0/test-suite/success/RefineInstance.v000066400000000000000000000007371516144147600213500ustar00rootroot00000000000000 Class Foo := foo { a : nat; b : bool }. Fail #[export] Instance bla : Foo := { b:= true }. #[refine, export] Instance bla : Foo := { b:= true }. Proof. exact 0. Defined. #[export] Instance bli : Foo := { a:=1; b := false}. Check bli. Fail #[program, refine] Instance bla : Foo := {b := true}. #[program, export] Instance blo : Foo := {b := true}. Next Obligation. exact 2. Qed. Check blo. #[refine, export] Instance xbar : Foo := {a:=4; b:=true}. Proof. Qed. Check xbar. rocq-9.2.0/test-suite/success/RegisterScheme.v000066400000000000000000000034421516144147600213600ustar00rootroot00000000000000Set Universe Polymorphism. Definition paths_rew_r_dep (A : Type) (x y : A) (P : forall y0 : A, y0 = y -> Type) (u : P y eq_refl) (H : x = y) : P x H. Proof. destruct H;assumption. Defined. Module TestLocal. Local Register Scheme paths_rew_r_dep as rew_r_dep for eq. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. subst. exact H. Qed. End GenMem. End TestLocal. Module TestExport. #[export] Register Scheme paths_rew_r_dep as rew_r_dep for eq. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. subst. exact H. Qed. End GenMem. End TestExport. Module Test1. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. (* The problem does not appear anymore *) (* neither TestLocal or TestExport registered the scheme *) subst. exact H. Qed. End GenMem. End Test1. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. (* The problem does not appear anymore *) (* Export reverted by section end *) subst. Abort. End GenMem. Module TestGlobal. Global Register Scheme paths_rew_r_dep as rew_r_dep for eq. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. subst. exact H. Qed. End GenMem. End TestGlobal. Section GenMem. Variable A : Type. Theorem upd_nop (a : A) (x : A) (e : a = x) (H: e = e) : eq_refl a = eq_refl. Proof. subst. exact H. Qed. End GenMem. rocq-9.2.0/test-suite/success/Remark.v000066400000000000000000000002541516144147600176660ustar00rootroot00000000000000(* Test obsolete, Remark est maintenant global Section A. Section B. Section C. Remark t : True. Proof I. End C. Locate C.t. End B. Locate B.C.t. End A. Locate A.B.C.t. *) rocq-9.2.0/test-suite/success/RemoteUnivs.v000066400000000000000000000005611516144147600207260ustar00rootroot00000000000000 Goal Type * Type. Proof. split. par: exact Type. Qed. Goal Type. Proof. exact Type. Qed. (* (* rocqide test, note the delegated proofs seem to get an empty dirpath? or I got confused because I had lemma foo in file foo *) Definition U := Type. Lemma foo : U. Proof. exact Type. Qed. Lemma foo1 : Type. Proof. exact (U:Type). Qed. Print foo. *) rocq-9.2.0/test-suite/success/Rename.v000066400000000000000000000003361516144147600176550ustar00rootroot00000000000000Goal forall n : nat, n = 0 -> n = 0. intros. rename n into p. induction p; auto. Qed. (* Submitted by Iris Loeb (BZ#842) *) Section rename. Variable A:Prop. Lemma Tauto: A->A. rename A into B. tauto. Qed. End rename. rocq-9.2.0/test-suite/success/Reordering.v000066400000000000000000000005731516144147600205510ustar00rootroot00000000000000(* Testing the reordering of hypothesis required by pattern, fold and change. *) Goal forall (A:Set) (x:A) (A':=A), True. intros. fold A' in x. (* succeeds: x is moved after A' *) Undo. pattern A' in x. Undo. change A' in x. Abort. (* p and m should be moved before H *) Goal forall n:nat, n=n -> forall m:nat, let p := (m,n) in True. intros. change n with (snd p) in H. Abort. rocq-9.2.0/test-suite/success/Require.v000066400000000000000000000003121516144147600200540ustar00rootroot00000000000000(* -*- coq-prog-args: ("-noinit"); -*- *) Require Import Corelib.Init.Logic. Locate Library Corelib.Init.Logic. (* Check that Init.Datatypes didn't get exported by the import above *) Fail Check nat. rocq-9.2.0/test-suite/success/RewriteRegisteredElim.v000066400000000000000000000016731516144147600227210ustar00rootroot00000000000000 Set Universe Polymorphism. Cumulative Inductive EQ {A} (x : A) : A -> Type := EQ_refl : EQ x x. Register EQ as core.eq.type. Lemma renamed_EQ_rect {A} (x:A) (P : A -> Type) (c : P x) (y : A) (e : EQ x y) : P y. Proof. destruct e. assumption. Qed. Lemma renamed_EQ_rect_r {A} (x:A) (P : A -> Type) (c : P x) (y : A) (e : EQ y x) : P y. Proof. destruct e. assumption. Qed. Module Registers. #[export] Register renamed_EQ_rect as core.eq.rect. Register renamed_EQ_rect_r as core.eq.rect_r. End Registers. Lemma EQ_sym1 {A} {x y : A} (e : EQ x y) : EQ y x. Proof. rewrite e. reflexivity. Qed. Lemma EQ_sym2 {A} {x y : A} (e : EQ x y) : EQ y x. Proof. Fail rewrite <- e. Import Registers. rewrite <- e. reflexivity. Qed. Require Import ssreflect. Lemma ssr_EQ_sym1 {A} {x y : A} (e : EQ x y) : EQ y x. Proof. rewrite e. reflexivity. Qed. Lemma ssr_EQ_sym2 {A} {x y : A} (e : EQ x y) : EQ y x. Proof. rewrite -e. reflexivity. Qed. rocq-9.2.0/test-suite/success/Scheme.v000066400000000000000000000044311516144147600176520ustar00rootroot00000000000000(* This failed in 8.3pl2 *) Scheme Induction for eq Sort Prop. Check eq_ind_dep. (* This was broken in v8.5 *) Set Rewriting Schemes. Inductive myeq A (a:A) : A -> Prop := myrefl : myeq A a a. Unset Rewriting Schemes. Check myeq_rect. Check myeq_ind. Check myeq_rec. Check myeq_congr. Check myeq_sym. Check myeq_rew. Check myeq_rew_dep. Check myeq_rew_fwd_dep. Check myeq_rew_r. Check myeq_sym_involutive. Check myeq_rew_r_dep. Check myeq_rew_fwd_r_dep. Set Rewriting Schemes. Inductive myeq_true : bool -> Prop := myrefl_true : myeq_true true. Unset Rewriting Schemes. (* check that the scheme doesn't minimize itself into something non general *) Polymorphic Inductive foo@{u v|u<=v} : Type@{u}:= . Lemma bla@{u v|u < v} : foo@{u v} -> False. Proof. induction 1. Qed. Set Warnings "+deprecated-lookup-elim-by-name". Unset Elimination Schemes. Inductive bar := A | B (_:bar). Scheme bar_myind := Induction for bar Sort Prop. Scheme bar_myind_nodep := Minimality for bar Sort Prop. (* ignored *) Definition bar_ind := bar_myind. Lemma a_or_b : forall f:bar, f = A \/ exists f', f = B f'. Proof. intros f. induction f. - left;reflexivity. - right;eexists;reflexivity. Qed. Fixpoint bar_rec (P : Set) (f : P) (f0 : bar -> P -> P) b := match b with | A => f | B b0 => f0 b0 (bar_rec P f f0 b0) end. Lemma to_bool : bar -> bool. Proof. intros f. Fail induction f. Abort. Module Attribute. (* test schemes attribute *) Set Elimination Schemes. #[schemes=none] Inductive foo1 := Foo1. Fail Check foo1_ind. #[schemes=default] Inductive foo2 := Foo2. Check foo2_ind. Unset Elimination Schemes. #[schemes=none] Inductive foo3 := Foo3. Fail Check foo3_ind. (* XXX should default ignore Elimination Schemes? *) #[schemes=default] Inductive foo4 := Foo4. Fail Check foo4_ind. Set Elimination Schemes. Set Rewriting Schemes. #[schemes=default] Inductive foo5 : bool -> Prop := Foo5 : foo5 true. Check foo5_ind. Check foo5_rew. #[schemes=none] Inductive foo6 : bool -> Prop := Foo6 : foo6 true. Fail Check foo6_ind. Fail Check foo6_rew. (* can't do rewriting schemes for this *) Fail Inductive foo7 := Foo7. (* but disabling schemes doesn't try rewriting schemes *) #[schemes=none] Inductive foo7 := Foo7. End Attribute. rocq-9.2.0/test-suite/success/SchemeEquality.v000066400000000000000000000241041516144147600213670ustar00rootroot00000000000000(* -*- coq-prog-args: ("-native-compiler" "no"); -*- *) (* Examples of use of Scheme Equality *) Module A. Definition N := nat. Inductive list := nil | cons : N -> list -> list. Scheme Equality for list. End A. Module B. Section A. Context A (eq_A:A->A->bool) (A_bl : forall x y, eq_A x y = true -> x = y) (A_lb : forall x y, x = y -> eq_A x y = true). Inductive I := C : A -> I. Scheme Equality for I. End A. End B. Module C. Parameter A : Type. Parameter eq_A : A->A->bool. Parameter A_bl : forall x y, eq_A x y = true -> x = y. Parameter A_lb : forall x y, x = y -> eq_A x y = true. #[export] Hint Resolve A_bl A_lb : core. Inductive I := C : A -> I. Scheme Equality for I. Inductive J := D : list A -> J. Scheme Equality for J. End C. (* Universe polymorphism *) Module D. Set Universe Polymorphism. Inductive unit := tt. Scheme Equality for unit. Inductive prod (A B:Type) := pair : A -> B -> prod A B. Scheme Equality for prod. (* With an indirection *) Inductive box A := c : A -> box A. Inductive prodbox (A B:Type) := pairbox : box A -> box B -> prodbox A B. Scheme Equality for prodbox. Check eq_refl : prodbox_beq @{Set Set} = fun (A B : Type@{Set}) eq_A eq_B (X Y : prodbox A B) => match X, Y with | pairbox _ _ x x0, pairbox _ _ x1 x2 => (internal_box_beq A eq_A x x1 && internal_box_beq B eq_B x0 x2)%bool end. End D. (* With hidden "X" and "Y" (was formerly cause of collisions) *) Module E. Section S. Variables X Y : Type. Variable eq_X : X -> X -> bool. Variable eq_Y : Y -> Y -> bool. Inductive EI := EC : X -> Y -> EI. Scheme Boolean Equality for EI. End S. End E. (* With inductive parameters instantiated by non-variable types *) Module F. Inductive FI := FC : list nat -> FI. Scheme Boolean Equality for FI. Inductive tree := node : list tree -> tree. Scheme Boolean Equality for tree. Inductive rose A := Leaf : A -> rose A | Node : list (rose A) -> rose A. Scheme Boolean Equality for rose. Print rose_beq. Check eq_refl : rose_beq = fun (A : Type) (eq_A : A -> A -> bool) => fix rose_eqrec (X Y : rose A) {struct X} : bool := match X with | Leaf _ x => match Y with | Leaf _ x0 => eq_A x x0 | Node _ _ => false end | Node _ x => match Y with | Leaf _ _ => false | Node _ x0 => C.internal_list_beq (rose A) rose_eqrec x x0 end end. End F. (* With higher-order parameters and non-Type parameters *) Module G. Inductive GI (F:Type->Type) A := GC : F A -> F nat -> GI F A. Scheme Boolean Equality for GI. Inductive GJ (F:nat->(nat->Type->Type)->Type) (f:nat->nat) (n:nat) (A:nat->Type->Type) := GD : F 0 (fun n => list) -> F 1 A -> GJ F f n A. Scheme Boolean Equality for GJ. End G. (* With local definitions in constructors *) Module H. Inductive HJ A : Type := HD : let a := 0 in nat -> list A -> HJ A. Scheme Boolean Equality for HJ. End H. (* With recursively non-uniform arguments *) Module I. Inductive T A := C : A -> T (option A) -> T A. Scheme Boolean Equality for T. Check eq_refl : T_beq = fix T_eqrec (A : Type) (eq_A : A -> A -> bool) (X Y : T A) {struct X} : bool := match X, Y with | C _ x x0, C _ x1 x2 => (eq_A x x1 && T_eqrec (option A) (internal_option_beq A eq_A) x0 x2)%bool end. End I. (* With mutual definitions *) Module J. Inductive tree A := node : forest A -> tree A with forest A := nil : forest A | cons : A -> tree A -> forest A. Scheme Boolean Equality for tree. Inductive K (F:nat->(nat->Type->Type)->Type) (A:nat->Type->Type) := D : L F A -> F 1 A -> K F A with L (F:nat->(nat->Type->Type)->Type) (A:nat->Type->Type) := E : F 0 (fun n => list) -> K F A -> L F A. Scheme Boolean Equality for K. End J. (* With "match" or "fix" *) Module K. Inductive K1 (b:bool) (F : if b then Type else Type->Type) : Type := C1 : nat -> K1 b F. Scheme Boolean Equality for K1. Inductive K2 (b:bool) (F : if b then Type else Type->Type) : Type := C2 : (if b return (if b then Type else Type->Type) -> Type then fun A => A else fun F => F nat) F -> K2 b F. Scheme Boolean Equality for K2. (* Almost work *) Inductive K3 (n:nat) (A : Type) : Type := C3 : (fix mkprod n := match n with 0 => A | S n => (mkprod n * A)%type end) n -> K3 n A. Fail Scheme Boolean Equality for K3. End K. Require PrimInt63 PrimFloat. Module ElpiTestSuite. Inductive empty := . Scheme Equality for empty. Inductive unit := tt. Scheme Equality for unit. Inductive peano := Zero | Succ (n : peano). Scheme Equality for peano. Inductive option A := None | Some (_ : A). Scheme Equality for option. Inductive pair A B := Comma (a : A) (b : B). Scheme Equality for pair. Inductive seq A := Nil | Cons (x : A) (xs : seq A). Scheme Equality for seq. Inductive nest A := NilN | ConsN (x : A) (xs : nest (pair A A)). Scheme Boolean Equality for nest. Inductive zeta Sender (Receiver := Sender) := Envelope (a : Sender) (ReplyTo := a) (c : Receiver). Scheme Boolean Equality for zeta. Inductive beta (A : (fun x : Type => x) Type) := Redex (a : (fun x : Type => x) A). Scheme Boolean Equality for beta. Inductive large := | K1 (_ : bool) | K2 (_ : bool) (_ : bool) | K3 (_ : bool) (_ : bool) (_ : bool) | K4 (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K5 (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K6 (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K7 (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K8 (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K9 (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K10(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K11(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K12(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K13(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K14(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K15(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K16(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K17(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K18(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K19(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K20(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K21(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K22(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K23(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K24(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K25(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) | K26(_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool) (_ : bool). Scheme Equality for large. Inductive prim_int := PI (i : PrimInt63.int). Scheme Boolean Equality for prim_int. Inductive prim_float := PF (f : PrimFloat.float). Scheme Boolean Equality for prim_float. Record fo_record := { f1 : peano; f2 : bool; }. Scheme Equality for fo_record. Record pa_record A := { f3 : peano; f4 : A; }. Scheme Equality for pa_record. Set Primitive Projections. Record pr_record A := { pf3 : peano; pf4 : A; }. Unset Primitive Projections. Scheme Boolean Equality for pr_record. Variant enum := E1 | E2 | E3. Scheme Equality for enum. End ElpiTestSuite. (* Ignoring SProp/Prop subterms *) Module L. Inductive seq {A} (x:A) : A -> SProp := seq_refl : seq x x. Inductive A := C : forall n, seq n 0 -> A. Scheme Boolean Equality for A. Check eq_refl : A_beq = fun (X Y : A) => match X, Y with | C n _, C n0 _ => A.internal_nat_beq n n0 end. End L. rocq-9.2.0/test-suite/success/Scopes.v000066400000000000000000000023131516144147600176770ustar00rootroot00000000000000(* Check exportation of Argument Scopes even without import of modules *) Declare Scope Z_scope. Module Z. Definition Z := unit. Definition opp (x : Z) := x. End Z. Bind Scope Z_scope with Z.Z. Notation "3" := tt : Z_scope. Module A. Definition opp := Z.opp. End A. Check (A.opp 3). (* Test extra scopes to be used in the presence of coercions *) Record B := { f :> Z.Z -> Z.Z }. Parameter a:B. Arguments a _%_Z_scope : extra scopes. Check a 3. (* Check that casts activate scopes if ever possible *) Inductive U := A. Bind Scope u with U. Notation "'Ξ΅'" := A : u. Definition c := Ξ΅ : U. (* Check activation of type scope for tactics such as assert *) Goal True. assert (nat * nat). Abort. (* Check propagation of scopes in indirect applications to references *) Module PropagateIndirect. Notation "0" := true : bool_scope. Axiom f : bool -> bool -> nat. Check (@f 0) 0. Record R := { p : bool -> nat }. Check fun r => r.(@p) 0. End PropagateIndirect. Module ScopeProjNotation. Declare Scope foo_scope. Delimit Scope foo_scope with foo. Record prod A B := pair { fst : A ; snd : B }. Notation "[[ t , u ]]" := (pair _ _ t u) : foo_scope. Arguments fst {A B} p%_foo. Check [[2,3]].(fst). End ScopeProjNotation. rocq-9.2.0/test-suite/success/Section.v000066400000000000000000000002101516144147600200410ustar00rootroot00000000000000(* Test bug 2168: ending section of some name was removing objects of the same name *) Require Import make_notation. Check add2 3. rocq-9.2.0/test-suite/success/ShowExtraction.v000066400000000000000000000011231516144147600214220ustar00rootroot00000000000000 Require Extraction. Require Import ListDef. Section Test. Variable A : Type. Variable decA : forall (x y:A), {x=y}+{x<>y}. (** Should fail when no proofs are started *) Fail Show Extraction. Lemma decListA : forall (xs ys : list A), {xs=ys}+{xs<>ys}. Proof. Show Extraction. fix decListA 1. destruct xs as [|x xs], ys as [|y ys]. Show Extraction. - now left. - now right. - now right. - Show Extraction. destruct (decA x y). + destruct (decListA xs ys). * left; now f_equal. * Show Extraction. right. congruence. + right. congruence. Show Extraction. Defined. End Test. rocq-9.2.0/test-suite/success/Simplify_eq.v000066400000000000000000000003741516144147600207310ustar00rootroot00000000000000(* Check the behaviour of Simplify_eq *) (* Check that Simplify_eq tries Intro until *) Lemma l1 : 0 = 1 -> False. simplify_eq 1. Qed. Lemma l2 : forall (x : nat) (H : S x = S (S x)), H = H -> False. simplify_eq H. intros. apply (n_Sn x H0). Qed. rocq-9.2.0/test-suite/success/StuckHintMode.v000066400000000000000000000013651516144147600211720ustar00rootroot00000000000000 Require Import Corelib.Setoids.Setoid Corelib.Classes.Morphisms. Class PartialOrder {A} (R : relation A) : Prop := { partial_order_pre :: PreOrder R; }. Global Hint Mode PartialOrder - ! : typeclass_instances. Axiom Permutation : forall {A:Type}, list A -> list A -> Prop. Infix "β‰‘β‚š" := Permutation (at level 70, no associativity). Global Declare Instance Permutation_cons A : Proper (Logic.eq ==> @Permutation A ==> @Permutation A) (@cons A) | 7. (* priority < 7 does not trigger the bug *) Global Declare Instance Permutation_Equivalence A : Equivalence (@Permutation A). Lemma bla A (x:A) (lc lc' lac lbc : list A) (Hc: lac ++ lbc β‰‘β‚š lc') (HH:x :: lc' β‰‘β‚š lc) : True /\ x :: lac ++ lbc β‰‘β‚š lc. Proof. rewrite Hc. auto. Qed. rocq-9.2.0/test-suite/success/TCbacktrack.v000066400000000000000000000051331516144147600206220ustar00rootroot00000000000000(* Set Typeclasses Unique Instances *) (** This lets typeclass search assume that instance heads are unique, so if one matches no other need to be tried, avoiding backtracking (even in unique solutions mode) This is on a class-by-class basis. *) (* Non unique *) Class B. Class A. Set Typeclasses Unique Instances. (* Unique *) Class D. Class C (A : Type) := c : A. #[export] Hint Mode C +. Fail Definition test := c. Unset Typeclasses Unique Instances. #[export] Instance cN1 : B -> D -> C nat := fun _ _ => 0. #[export] Instance cN2 : A -> D -> C nat := fun _ _ => 1. #[export] Instance cB : B -> C bool := fun _ => true. #[export] Instance Copt : forall A, C A -> C (option A) := fun A _ => None. Set Typeclasses Debug. Set Typeclasses Unique Solutions. (** This forces typeclass resolution to fail if at least two solutions exist to a given set of constraints. This is a global setting. For constraints involving assumed unique instances, it will not fail if two such instances could apply, however it will fail if two different instances of a unique class could apply. *) Succeed Definition foo (d d' : D) (b b' : B) (a' a'' : A) := c : nat. Definition foo (d d' : D) (b b' : B) (a' : A) := c : nat. Succeed Definition foo' (b b' : B) := _ : B. Unset Typeclasses Unique Solutions. Definition foo' (b b' : B) := _ : B. Set Typeclasses Unique Solutions. Definition foo'' (d d' : D) := _ : D. (** Cut backtracking *) Module BacktrackGreenCut. Unset Typeclasses Unique Solutions. Class C (A : Type) := c : A. Class D (A : Type) : Type := { c_of_d :: C A }. #[export] Instance D1 : D unit. Admitted. #[export] Instance D2 : D unit. Admitted. (** Two instances of D unit, but when searching for [C unit], no backtracking on the second instance should be needed except in dependent cases. Check by adding an unresolvable constraint. *) Parameter f : D unit -> C bool -> True. Fail Definition foo := f _ _. Fail Definition foo' := let y := _ : D unit in let x := _ : C bool in f _ x. Unset Typeclasses Strict Resolution. Class Transitive (A : Type) := { trans : True }. Class PreOrder (A : Type) := { preorder_trans :: Transitive A }. Class PartialOrder (A : Type) := { partialorder_trans :: Transitive A }. Class PartialOrder' (A : Type) := { partialorder_trans' :: Transitive A }. #[export] Instance: PreOrder nat. Admitted. #[export] Instance: PartialOrder nat. Admitted. Class NoInst (A : Type) := {}. Parameter foo : forall `{ T : Transitive nat } `{ NoInst (let x:=@trans _ T in nat) }, nat. Fail Definition bar := foo. End BacktrackGreenCut. rocq-9.2.0/test-suite/success/TacticNotation1.v000066400000000000000000000003061516144147600214470ustar00rootroot00000000000000Module Type S. End S. Module F (E : S). Tactic Notation "foo" := idtac. Ltac bar := foo. End F. Module G (E : S). Module M := F E. Lemma Foo : True. Proof. M.bar. Abort. End G. rocq-9.2.0/test-suite/success/TacticNotation2.v000066400000000000000000000004661516144147600214570ustar00rootroot00000000000000Tactic Notation "complete" tactic(tac) := tac; fail. Ltac f0 := complete (intuition idtac). (** FIXME: This is badly printed because of bug #3079. At least we check that it does not fail anomalously. *) Print Ltac f0. Ltac f1 := complete f1. Print Ltac f1. Ltac f2 := complete intuition. Print Ltac f2. rocq-9.2.0/test-suite/success/Tauto.v000066400000000000000000000122571516144147600175470ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop. Parameter P : nat -> Prop. Lemma Ex_Wallen : (A -> B /\ C) -> (A -> B) \/ (A -> C). Proof. tauto. Qed. Lemma Ex_Klenne : ~ ~ (A \/ ~ A). Proof. tauto. Qed. Lemma Ex_Klenne' : forall n : nat, ~ ~ (even n \/ ~ even n). Proof. tauto. Qed. Lemma Ex_Klenne'' : ~ ~ ((forall n : nat, even n) \/ ~ (forall m : nat, even m)). Proof. tauto. Qed. Lemma tauto : (forall x : nat, P x) -> forall y : nat, P y. Proof. tauto. Qed. Lemma tauto1 : A -> A. Proof. tauto. Qed. Lemma tauto2 : (A -> B -> C) -> (A -> B) -> A -> C. Proof. tauto. Qed. Lemma a : forall (x0 : A \/ B) (x1 : B /\ C), A -> B. Proof. tauto. Qed. Lemma a2 : (A -> B /\ C) -> (A -> B) \/ (A -> C). Proof. tauto. Qed. Lemma a4 : ~ A -> ~ A. Proof. tauto. Qed. Lemma e2 : ~ ~ (A \/ ~ A). Proof. tauto. Qed. Lemma e4 : ~ ~ (A \/ B -> A \/ B). Proof. tauto. Qed. Lemma y0 : forall (x0 : A) (x1 : ~ A) (x2 : A -> B) (x3 : A \/ B) (x4 : A /\ B), A -> False. Proof. tauto. Qed. Lemma y1 : forall x0 : (A /\ B) /\ C, B. Proof. tauto. Qed. Lemma y2 : forall (x0 : A) (x1 : B), C \/ B. Proof. tauto. Qed. Lemma y3 : forall x0 : A /\ B, B /\ A. Proof. tauto. Qed. Lemma y5 : forall x0 : A \/ B, B \/ A. Proof. tauto. Qed. Lemma y6 : forall (x0 : A -> B) (x1 : A), B. Proof. tauto. Qed. Lemma y7 : forall (x0 : A /\ B -> C) (x1 : B) (x2 : A), C. Proof. tauto. Qed. Lemma y8 : forall (x0 : A \/ B -> C) (x1 : A), C. Proof. tauto. Qed. Lemma y9 : forall (x0 : A \/ B -> C) (x1 : B), C. Proof. tauto. Qed. Lemma y10 : forall (x0 : (A -> B) -> C) (x1 : B), C. Proof. tauto. Qed. (* This example took much time with the old version of Tauto *) Lemma critical_example0 : (~ ~ B -> B) -> (A -> B) -> ~ ~ A -> B. Proof. tauto. Qed. (* Same remark as previously *) Lemma critical_example1 : (~ ~ B -> B) -> (~ B -> ~ A) -> ~ ~ A -> B. Proof. tauto. Qed. (* This example took very much time (about 3mn on a PIII 450MHz in bytecode) with the old Tauto. Now, it's immediate (less than 1s). *) Lemma critical_example2 : (~ A <-> B) -> (~ B <-> A) -> (~ ~ A <-> A). Proof. tauto. Qed. (* This example was a bug *) Lemma old_bug0 : (~ A <-> B) -> (~ (C \/ E) <-> D /\ F) -> (~ (C \/ A \/ E) <-> D /\ B /\ F). Proof. tauto. Qed. (* Another bug *) Lemma old_bug1 : ((A -> B -> False) -> False) -> (B -> False) -> False. Proof. tauto. Qed. (* A bug again *) Lemma old_bug2 : ((((C -> False) -> A) -> ((B -> False) -> A) -> False) -> False) -> (((C -> B -> False) -> False) -> False) -> ~ A -> A. Proof. tauto. Qed. (* A bug from CNF form *) Lemma old_bug3 : ((~ A \/ B) /\ (~ B \/ B) /\ (~ A \/ ~ B) /\ (~ B \/ ~ B) -> False) -> ~ ((A -> B) -> B) -> False. Proof. tauto. Qed. (* sometimes, the behaviour of Tauto depends on the order of the hyps *) Lemma old_bug3bis : ~ ((A -> B) -> B) -> ((~ B \/ ~ B) /\ (~ B \/ ~ A) /\ (B \/ ~ B) /\ (B \/ ~ A) -> False) -> False. Proof. tauto. Qed. (* A bug found by Freek Wiedijk *) Lemma new_bug : ((A <-> B) -> (B <-> C)) -> ((B <-> C) -> (C <-> A)) -> ((C <-> A) -> (A <-> B)) -> (A <-> B). Proof. tauto. Qed. (* A private club has the following rules : * * . rule 1 : Every non-scottish member wears red socks * . rule 2 : Every member wears a kilt or doesn't wear red socks * . rule 3 : The married members don't go out on sunday * . rule 4 : A member goes out on sunday if and only if he is scottish * . rule 5 : Every member who wears a kilt is scottish and married * . rule 6 : Every scottish member wears a kilt * * Actually, no one can be accepted ! *) Section club. Variable Scottish RedSocks WearKilt Married GoOutSunday : Prop. Hypothesis rule1 : ~ Scottish -> RedSocks. Hypothesis rule2 : WearKilt \/ ~ RedSocks. Hypothesis rule3 : Married -> ~ GoOutSunday. Hypothesis rule4 : GoOutSunday <-> Scottish. Hypothesis rule5 : WearKilt -> Scottish /\ Married. Hypothesis rule6 : Scottish -> WearKilt. Lemma NoMember : False. tauto. Qed. End club. (**** Use of Intuition ****) Lemma intu0 : (forall x : nat, P x) /\ B -> (forall y : nat, P y) /\ P 0 \/ B /\ P 0. Proof. intuition. Qed. Lemma intu1 : (forall A : Prop, A \/ ~ A) -> forall x y : nat, x = y \/ x <> y. Proof. intuition. Qed. rocq-9.2.0/test-suite/success/Template.v000066400000000000000000000214041516144147600202200ustar00rootroot00000000000000Set Printing Universes. Module AutoYes. Inductive Box (A:Type) : Type := box : A -> Box A. About Box. (* This checks that Box is template poly, see module No for how it fails *) Universe i j. Constraint i < j. Definition j_lebox (A:Type@{j}) := Box A. Definition box_lti A := Box A : Type@{i}. End AutoYes. Module AutoNo. Unset Auto Template Polymorphism. Inductive Box (A:Type) : Type := box : A -> Box A. About Box. Universe i j. Constraint i < j. Definition j_lebox (A:Type@{j}) := Box A. Fail Definition box_lti A := Box A : Type@{i}. End AutoNo. Module Yes. #[universes(template)] Inductive Box@{i} (A:Type@{i}) : Type@{i} := box : A -> Box A. About Box. Universe i j. Constraint i < j. Definition j_lebox (A:Type@{j}) := Box A. Definition box_lti A := Box A : Type@{i}. End Yes. Module No. #[universes(template=no)] Inductive Box (A:Type) : Type := box : A -> Box A. About Box. Universe i j. Constraint i < j. Definition j_lebox (A:Type@{j}) := Box A. Fail Definition box_lti A := Box A : Type@{i}. End No. Module ExplicitTemplate. #[universes(template)] Inductive identity@{i} (A : Type@{i}) (a : A) : A -> Type@{i} := id_refl (_:A) : identity A a a. (* There used to be a weird interaction of template polymorphism and inductive types which fall in Prop due to kernel sort inference. This inductive is template polymorphic, but the universe annotation Type@{i} was ignored by the kernel which infered it lived in any universe and thus put it in Prop. This is not the case anymore since return sort inference has been removed from the kernel. Now the universe annotation is respected by the kernel. *) Fail Check (identity Type nat nat : Prop). Check (identity True I I : Prop). Check identity nat 0 0 : Set. Fail Check identity Type nat nat : Set. Check identity Type nat nat : Type. End ExplicitTemplate. Module ExplicitTemplate2. #[universes(template)] Inductive identity@{i} (A : Type@{i}) (a : A) : A -> Type@{i} := id_refl : identity A a a. (* we generate fresh qualities for A and the conclusion, and they end up unrelated therefore the conclusion quality has no binders, we can't make it a template poly quality and instead collapse to Type *) Fail Check (identity Type nat nat : Prop). Fail Check (identity True I I : Prop). Check identity nat 0 0 : Set. Fail Check identity Type nat nat : Set. Check identity Type nat nat : Type. End ExplicitTemplate2. Polymorphic Definition f@{i} : Type@{i} := nat. Polymorphic Definition baz@{i} : Type@{i} -> Type@{i} := fun x => x. Section Foo. Universe u. Context (A : Type@{u}). Inductive Bar := | bar : A -> Bar. Set Universe Minimization ToSet. Inductive Baz := | cbaz : A -> baz Baz -> Baz. Inductive Baz' := | cbaz' : A -> baz@{Set} nat -> Baz'. (* 2 constructors, at least in Set *) Inductive Bazset@{v} := | cbaz1 : A -> baz@{v} Bazset -> Bazset | cbaz2 : Bazset. Eval compute in ltac:(let T := type of A in exact T). Inductive Foo : Type := | foo : A -> f -> Foo. End Foo. Set Printing Universes. (* Cannot fall back to Prop or Set anymore as baz is no longer template-polymorphic *) Fail Check Bar True : Prop. Fail Check Bar nat : Set. About Baz. Check cbaz True I. (** Neither can it be Set *) Fail Check Baz nat : Set. (** No longer possible for Baz' which contains a type in Set *) Fail Check Baz' True : Prop. Fail Check Baz' nat : Set. Fail Check Bazset True : Prop. Fail Check Bazset True : Set. (** We can force the universe instantiated in [baz Bazset] to be [u], so Bazset lives in max(Set, u). *) Constraint u = Bazset.v. (** As u is global it is already > Set, so: *) Definition bazsetex@{i | i < u} : Type@{u} := Bazset Type@{i}. (* Bazset is closed for universes u = u0, cannot be instantiated with Prop *) Definition bazseetpar (X : Type@{u}) : Type@{u} := Bazset X. (** Would otherwise break singleton elimination and extraction. *) Fail Check Foo True : Prop. Fail Check Foo True : Set. Definition foo_proj {A} (f : Foo A) : nat := match f with foo _ _ n => n end. Definition ex : Foo True := foo _ I 0. Check foo_proj ex. (** See failure/Template.v for a test of the unsafe Unset Template Check usage *) Module AutoTemplateTest. Set Warnings "+auto-template". Section Foo. Universe u'. Context (A : Type@{u'}). (* Not failing as Bar cannot be made template polymorphic at all *) Inductive Bar := | bar : A -> Bar. End Foo. End AutoTemplateTest. Module TestTemplateAttribute. Section Foo. Universe u. Context (A : Type@{u}). Set Warnings "+no-template-universe". (* Failing as Bar cannot be made template polymorphic at all *) Fail #[universes(template)] Inductive Bar := | bar : A -> Bar. End Foo. End TestTemplateAttribute. Module SharingWithoutSection. Inductive Foo A (S:= fun _ => Set : ltac:(let ty := type of A in exact ty)) := foo : S A -> Foo A. Fail Check Foo True : Prop. End SharingWithoutSection. Module OkNotCovered. (* Here it happens that box is safe but we don't see it *) Section S. Universe u. Variable A : Type@{u}. Inductive box (A:Type@{u}) := Box : A -> box A. Definition B := Set : Type@{u}. End S. Fail Check box True : Prop. End OkNotCovered. Module BoxBox. Inductive Box (A:Type) := box (_:A). Inductive Box' (A:Type) := box' (_:Box A). Check Box' True : Prop. End BoxBox. Module TemplateUnit. Set Warnings "-no-template-universe". (* This is marked as template without any actual template universe. *) #[universes(template)] Inductive foo := Foo. Check (foo : Prop). End TemplateUnit. Module TemplateParamUnit. (* template where the univ doesn't appear in the conclusion (here Prop) *) Set Warnings "+no-template-universe". Inductive foo (A : Type) := Foo. Polymorphic Definition foo'@{u|} (A:Type@{u}) : Prop := foo A. Check (foo unit : Prop). End TemplateParamUnit. Module TemplateAlg. Inductive foo (A:Type) (B :Type) := C (_:A). Check foo True nat : Prop. Check fun A => foo A nat : Prop. Fail Check fun A:Set => foo A nat : Prop. Goal Prop. let c := constr:(forall A, prod A A) in exact c. Defined. Universes u v. Axiom U : Type@{u}. Axiom V : Type@{v}. Check foo (U * V) True : Type@{max(u,v)}. End TemplateAlg. Module TemplateNoExtraCsts. Polymorphic Definition opt'@{u|} (A:Type@{u}) := option A. Polymorphic Definition some@{u|} (A:Type@{u}) (x:A) : opt' A := Some x. End TemplateNoExtraCsts. Module BoundedQuality. Inductive dumb' (b:bool) (B : Type) := cons' : B -> (b = true -> dumb' false nat) -> dumb' b B. (* dumb' true _ contains a nat *) Fail Check dumb' true True : Prop. Check dumb' true nat : Set. Fail Check dumb' true Set : Set. Check dumb' true Set. End BoundedQuality. Module BoundedQuality2. Inductive dumb' (A:Type) (b:bool) (B : Type) := cons' : A -> (b = true -> dumb' A false nat) -> dumb' A b B. Check dumb' True true Set : Prop. Fail Check dumb' nat true Set : Prop. Check dumb' nat true Set : Set. Fail Check dumb' Set true Set : Set. Check dumb' Set true Set. End BoundedQuality2. Module UnminimizedOption. Unset Universe Minimization ToSet. Inductive option A := None | Some (_:A). Fail Check option True : Prop. Check option nat : Set. Fail Check option Set : Set. Check option Set : Type. End UnminimizedOption. Module UnminimizedFunction. Unset Universe Minimization ToSet. Inductive Foo (T:Type) := foo (_:nat -> T). Check Foo True : Prop. Fail Check Foo nat : Prop. Check Foo nat : Set. Fail Check Foo Set : Set. Check Foo Set : Type. End UnminimizedFunction. Module ExplicitOption. Inductive option@{u} (A:Type@{u}) : Type@{u} := None | Some (_:A). Fail Check option True : Prop. Check option nat : Set. Fail Check option Set : Set. Check option Set : Type. End ExplicitOption. Module QvarInCtor. (* this could be sort polymorphic: Record Foo@{q|u v|} (A:Type@{q|u}) : Type@{q|max(u,v+1)} := { foo1 : A; foo2 : forall P : Type@{q|v}, P }. but qvar "q" (and univ "v") cannot be template poly due to appearing in the constructor (even if we generalized template poly to allow conversion-irrelevant appearances, this one isn't irrelevant) so we need to collapse q := Type and can be template poly on u *) Record Foo A := { foo1 : A ; foo2 : forall P, P }. Fail Check Foo True : Prop. Fail Check Foo nat : Set. Polymorphic Definition test@{|} : Type@{Foo.u1+1} := Foo nat. Polymorphic Definition test'@{u|} (A:Type@{u}) : Type@{max(u,Foo.u1+1)} := Foo A. End QvarInCtor. Module SemiPoly. Universe u. (* u cannot be template poly (it's global) but we could be template sort polymorphic *) Inductive foo (A:Type@{u}) (B:Type@{u}) C := pair (_:A) (_:B) (_:C). Fail Check foo True True True : Prop. (* maybe will be allowed someday *) Fail Check foo nat nat nat : Set. (* must not be allowed *) End SemiPoly. rocq-9.2.0/test-suite/success/Try.v000066400000000000000000000002541516144147600172230ustar00rootroot00000000000000(* To shorten interactive scripts, it is better that Try catches non-existent names in Unfold [cf BZ#263] *) Lemma lem1 : True. try unfold i_dont_exist. trivial. Qed. rocq-9.2.0/test-suite/success/Typeclasses.v000066400000000000000000000220271516144147600207460ustar00rootroot00000000000000(* coq-prog-args: ("-async-proofs" "off") *) Module applydestruct. Class Foo (A : Type) := { bar : nat -> A; baz : A -> nat }. #[export] Hint Mode Foo + : typeclass_instances. Class C (A : Type). #[export] Hint Mode C + : typeclass_instances. Parameter fool : forall {A} {F : Foo A} (x : A), C A -> bar 0 = x. (* apply leaves non-dependent subgoals of typeclass type alone *) Goal forall {A} {F : Foo A} (x : A), bar 0 = x. Proof. intros. apply fool. match goal with |[ |- C A ] => idtac end. Abort. Parameter fooli : forall {A} {F : Foo A} {c : C A} (x : A), bar 0 = x. (* apply tries to resolve implicit argument typeclass constraints. *) Goal forall {A} {F : Foo A} (x : A), bar 0 = x. Proof. intros. Fail apply fooli. Fail unshelve eapply fooli; solve [typeclasses eauto]. eapply fooli. Abort. (* It applies resolution after unification of the goal *) Goal forall {A} {F : Foo A} {C : C A} (x : A), bar 0 = x. Proof. intros. apply fooli. Abort. Set Typeclasses Debug Verbosity 2. Inductive bazdestr {A} (F : Foo A) : nat -> Prop := | isbas : bazdestr F 1. Parameter fooinv : forall {A} {F : Foo A} (x : A), bazdestr F (baz x). (* Destruct applies resolution early, before finding occurrences to abstract. *) Goal forall {A} {F : Foo A} {C : C A} (x : A), baz x = 0. Proof. intros. Fail destruct (fooinv _). destruct (fooinv x). Abort. Goal forall {A} {F : Foo A} (x y : A), x = y. Proof. intros. rewrite <- (fool x). rewrite <- (fool y). reflexivity. match goal with |[ |- C A ] => idtac end. Abort. End applydestruct. Module onlyclasses. (* In 8.6 we still allow non-class subgoals *) Parameter Foo : Type. Parameter foo : Foo. #[export] Hint Extern 0 Foo => exact foo : typeclass_instances. Goal Foo * Foo. split. shelve. Set Typeclasses Debug. typeclasses eauto. Unshelve. typeclasses eauto. Qed. Module RJung. Class Foo (x : nat). #[export] Instance foo x : x = 2 -> Foo x := {}. #[export] Hint Extern 0 (_ = _) => reflexivity : typeclass_instances. Typeclasses eauto := debug. Check (_ : Foo 2). Fail Definition foo := (_ : 0 = 0). End RJung. End onlyclasses. Module shelve_non_class_subgoals. Parameter Foo : Type. Parameter foo : Foo. #[export] Hint Extern 0 Foo => exact foo : typeclass_instances. Class Bar := {}. #[export] Instance bar1 (f:Foo) : Bar := {}. Typeclasses eauto := debug. Set Typeclasses Debug Verbosity 2. Goal Bar. (* Solution has shelved subgoals (of non typeclass type) *) typeclasses eauto. Abort. End shelve_non_class_subgoals. Module RefineVsNoTceauto. Class Foo (A : Type) := foo : A. #[export] Instance: Foo nat := { foo := 0 }. #[export] Instance: Foo nat := { foo := 42 }. #[export] Hint Extern 0 (_ = _) => refine eq_refl : typeclass_instances. Goal exists (f : Foo nat), @foo _ f = 0. Proof. unshelve (notypeclasses refine (ex_intro _ _ _)). Set Typeclasses Debug. Set Printing All. all:once (typeclasses eauto). Fail idtac. (* Check no subgoals are left *) Undo 3. (** In this case, the (_ = _) subgoal is not considered by typeclass resolution *) refine (ex_intro _ _ _). Fail reflexivity. Abort. End RefineVsNoTceauto. Module Leivantex2PR339. (** Was a bug preventing to find hints associated with no pattern *) Class Bar := {}. #[export] Instance bar1 (t:Type) : Bar := {}. Local Hint Extern 0 => exact True : typeclass_instances. Typeclasses eauto := debug. Goal Bar. Set Typeclasses Debug Verbosity 2. typeclasses eauto. (* Relies on resolution of a non-class subgoal *) Undo 1. typeclasses eauto with typeclass_instances. Qed. End Leivantex2PR339. Module HintMode_NonStuck_Failure_Refine_DoNotShelve. Class test (x : nat) := testv : True. Local Hint Mode test ! : typeclass_instances. Record foo := { n : nat ; t : test n ; h : t = t }. Goal True. (* This tests that non-stuck classes whose resolution fails are left as proper subgoals and not shelved if failure is allowed. *) simple refine (let name := (_ : test 5) in _); [|]. Abort. End HintMode_NonStuck_Failure_Refine_DoNotShelve. Module bt. Require Import Classes.Init. Record Equ (A : Type) (R : A -> A -> Prop). Definition equiv {A} R (e : Equ A R) := R. Record Refl (A : Type) (R : A -> A -> Prop). Axiom equ_refl : forall A R (e : Equ A R), Refl _ (@equiv A R e). #[export] Hint Extern 0 (Refl _ _) => unshelve class_apply @equ_refl; [shelve|] : foo. Parameter R : nat -> nat -> Prop. Lemma bas : Equ nat R. Admitted. #[export] Hint Resolve bas : foo. #[export] Hint Extern 1 => match goal with |- (_ -> _ -> Prop) => shelve end : foo. Goal exists R, @Refl nat R. eexists. solve [typeclasses eauto with foo]. Qed. End bt. Generalizable All Variables. Module mon. Reserved Notation "'return' t" (at level 1). Reserved Notation "x >>= y" (at level 65, left associativity). Record Monad {m : Type -> Type} := { unit : forall {Ξ±}, Ξ± -> m Ξ± where "'return' t" := (unit t) ; bind : forall {Ξ± Ξ²}, m Ξ± -> (Ξ± -> m Ξ²) -> m Ξ² where "x >>= y" := (bind x y) ; bind_unit_left : forall {Ξ± Ξ²} (a : Ξ±) (f : Ξ± -> m Ξ²), return a >>= f = f a }. Print Visibility. Print unit. Arguments unit {m _ Ξ±}. Arguments Monad : clear implicits. Notation "'return' t" := (unit t). (* Test correct handling of existentials and defined fields. *) Class A `(e: T) := { a := True }. Class B `(e_: T) := { e := e_; sg_ass :: A e }. (* Set Typeclasses Debug. *) (* Set Typeclasses Debug Verbosity 2. *) Goal forall `{B T}, Prop. intros. apply a. Defined. Goal forall `{B T}, Prop. intros. refine (@a _ _ _). Defined. Class B' `(e_: T) := { e' := e_; sg_ass' :: A e_ }. Goal forall `{B' T}, a. intros. exact I. Defined. End mon. Module deftwice. Class C (A : Type) := c : A -> Type. Record Inhab (A : Type) := { witness : A }. #[export] Instance inhab_C : C Type := Inhab. Axiom full : forall A (X : C A), forall x : A, c x. Definition truc {A : Type} : Inhab A := (full _ _ _). End deftwice. (* Correct treatment of dependent goals *) (* First some preliminaries: *) Section sec. Context {N: Type}. Class C (f: N->N) := {}. Class E := { e: N -> N }. Context (g: N -> N) `(E) `(C e) `(forall (f: N -> N), C f -> C (fun x => f x)) (U: forall f: N -> N, C f -> False). (* Now consider the following: *) Let foo := U (fun x => e x). Check foo _. (* This type checks fine, so far so good. But now let's try to get rid of the intermediate constant foo. Surely we can just expand it inline, right? Wrong!: *) Check U (fun x => e x) _. End sec. Module UniqueSolutions. Set Typeclasses Unique Solutions. Class Eq (A : Type) : Set. #[export] Instance eqa : Eq nat := {}. #[export] Instance eqb : Eq nat := {}. Goal Eq nat. try apply _. Fail exactly_once typeclasses eauto. Abort. End UniqueSolutions. Module UniqueInstances. (** Optimize proof search on this class by never backtracking on (closed) goals for it. *) Set Typeclasses Unique Instances. Class Eq (A : Type) : Set. #[export] Instance eqa : Eq nat. Qed. #[export] Instance eqb : Eq nat := {}. Class Foo (A : Type) (e : Eq A) : Set. #[export] Instance fooa : Foo _ eqa := {}. Tactic Notation "refineu" open_constr(c) := unshelve refine c. Set Typeclasses Debug. Goal { e : Eq nat & Foo nat e }. unshelve refineu (existT _ _ _). all:simpl. (** Does not backtrack on the (wrong) solution eqb *) Fail all:typeclasses eauto. Abort. End UniqueInstances. Module IterativeDeepening. Class A. Class B. Class C. #[export] Instance: B -> A | 0 := {}. #[export] Instance: C -> A | 0 := {}. #[export] Instance: C -> B -> A | 0 := {}. #[export] Instance: A -> A | 0 := {}. Goal C -> A. intros. Fail Timeout 1 typeclasses eauto. Set Typeclasses Iterative Deepening. Fail typeclasses eauto 1. typeclasses eauto 2. Undo. Unset Typeclasses Iterative Deepening. Fail Timeout 1 typeclasses eauto. Set Typeclasses Iterative Deepening. typeclasses eauto. Qed. End IterativeDeepening. Module AxiomsAreNotInstances. Class TestClass2 := {}. Axiom testax2 : TestClass2. Fail Definition testdef2 : TestClass2 := _. (* we didn't break typeclasses *) #[export] Existing Instance testax2. Definition testdef2 : TestClass2 := _. End AxiomsAreNotInstances. Module InternalHintBacktracking. Class A (T : Type) := mkA { ofA : T }. Definition a0 : A nat := {| ofA := 0 |}. Definition a1 : A bool := {| ofA := true |}. (** This defines an instance that returns an A bool on first success and A nat on second success *) Local Hint Extern 0 (A _) => exact a1 + exact a0 : typeclass_instances. Class B (T : Type). #[export] Instance b0 : B nat := {}. Definition foo {T} {x : A T} {b : B T} : T := ofA. (* This definition only passes because we backtrack on [exact a1] above and try a0 : A nat *) Definition test := foo. Check test : nat. End InternalHintBacktracking. rocq-9.2.0/test-suite/success/TypeclassesOpaque.v000066400000000000000000000042041516144147600221160ustar00rootroot00000000000000 (** Testing the Typeclasses Opaque hints. We create two identical typeclasses [P] and [Q] and compare the behaviour of Typeclasses Opaque and Hint Opaque. They should be the same. *) Axiom A : Type. Axiom P : A -> Type. Axiom Q : A -> Type. Existing Class P. Existing Class Q. Axiom a : A. Axiom pa : P a. Axiom qa : Q a. #[local] Existing Instance pa. #[local] Existing Instance qa. Definition b := a. Definition c := a. (** b is transparent so typeclass search should find it. *) Goal P b. Proof. Succeed typeclasses eauto. Abort. (** c is transparent so typeclass search should find it. *) Goal Q c. Proof. Succeed typeclasses eauto. Abort. (** Creating a local hint in a module or a section *) Section Foo. #[local] Hint Opaque b : typeclass_instances. #[local] Typeclasses Opaque c. End Foo. (** Closing the module/section should get rid of the hint, so we expect the same behaviour as before. *) (** b is transparent so typeclass search should find it. *) Goal P b. Proof. Succeed typeclasses eauto. Abort. (** c is transparent so typeclass search should find it. *) Goal Q c. Proof. Succeed typeclasses eauto. Abort. (** Now setting the locality as export *) Module Foo. #[export] Hint Opaque b : typeclass_instances. #[export] Typeclasses Opaque c. (** Things should fail inside *) Goal P b. Proof. Fail typeclasses eauto. Abort. Goal Q c. Proof. Fail typeclasses eauto. Abort. End Foo. (** But succeed outside *) Goal P b. Proof. Succeed typeclasses eauto. Abort. Goal Q c. Proof. Succeed typeclasses eauto. Abort. (** Until of course we export the module *) Export Foo. Goal P b. Proof. Fail typeclasses eauto. Abort. Goal Q c. Proof. Fail typeclasses eauto. Abort. (** Finally we test the localities for this alias *) Succeed #[local] Typeclasses Opaque b. Succeed #[global] Typeclasses Opaque b. Succeed #[export] Typeclasses Opaque b. Succeed #[local] Typeclasses Transparent b. Succeed #[global] Typeclasses Transparent b. Succeed #[export] Typeclasses Transparent b. Notation bar := (0 + 0). Fail Local Typeclasses Transparent bar. Notation baz := b. Succeed Local Typeclasses Transparent baz. rocq-9.2.0/test-suite/success/Typeclasses_eauto_dfs_bfs.v000066400000000000000000000022031516144147600236230ustar00rootroot00000000000000Class A := a : nat. Class B := b : nat. Class C := c : nat. Class D := d : nat. #[local] Instance CtoA : C -> A := fun x => x. #[local] Instance BtoA : B -> A := fun x => x. #[local] Instance DtoB : D -> B := fun x => x. #[local] Instance someC : C := 2. #[local] Instance someD : D := 3. (** Here is our class structure: *) (* A / \ B C* / D* *) (** In a dfs (depth-first search) the instance at D* should be found. In a bfs (breadth-first search) the instance at C* should be found. *) Set Typeclasses Debug. (** We test that [typeclasses eauto] is really using bfs or dfs. *) Goal exists x : A, x = 3. simple notypeclasses refine (ex_intro _ _ _). 1: typeclasses eauto. reflexivity. Qed. Goal exists x : A, x = 2. simple notypeclasses refine (ex_intro _ _ _). 1: typeclasses eauto bfs. reflexivity. Qed. Set Typeclasses Iterative Deepening. Goal exists x : A, x = 3. simple notypeclasses refine (ex_intro _ _ _). 1: typeclasses eauto dfs. reflexivity. Qed. Goal exists x : A, x = 2. simple notypeclasses refine (ex_intro _ _ _). 1: typeclasses eauto. reflexivity. Qed. rocq-9.2.0/test-suite/success/ValidateProof.v000066400000000000000000000004241516144147600212030ustar00rootroot00000000000000 Module M. Private Inductive foo := . Definition to_nat (f:foo) : nat := match f with end. End M. Lemma bar : False. Proof. exact_no_check I. Fail Validate Proof. Abort. Lemma bar f : M.to_nat f = 0. Proof. Validate Proof. cbv. Fail Validate Proof. Abort. rocq-9.2.0/test-suite/success/abstract_chain.v000066400000000000000000000015651516144147600214200ustar00rootroot00000000000000Lemma foo1 : nat -> True. Proof. intros _. assert (H : True -> True). { abstract (exact (fun x => x)) using bar. } assert (H' : True). { abstract (exact (bar I)) using qux. } exact H'. Qed. Lemma foo2 : True. Proof. assert (H : True -> True). { abstract (exact (fun x => x)) using bar. } assert (H' : True). { abstract (exact (bar I)) using qux. } assert (H'' : True). { abstract (exact (bar qux)) using quz. } exact H''. Qed. Set Universe Polymorphism. Lemma foo3 : nat -> True. Proof. intros _. assert (H : True -> True). { abstract (exact (fun x => x)) using bar. } assert (H' : True). { abstract (exact (bar I)) using qux. } exact H'. Qed. Lemma foo4 : True. Proof. assert (H : True -> True). { abstract (exact (fun x => x)) using bar. } assert (H' : True). { abstract (exact (bar I)) using qux. } assert (H'' : True). { abstract (exact (bar qux)) using quz. } exact H''. Qed. rocq-9.2.0/test-suite/success/abstract_poly.v000066400000000000000000000010351516144147600213110ustar00rootroot00000000000000Set Universe Polymorphism. Inductive path@{i} {A : Type@{i}} (x : A) : A -> Type@{i} := refl : path x x. Inductive unit@{i} : Type@{i} := tt. Scheme Rewriting for path. Lemma foo@{i j} : forall (m n : unit@{i}) (P : unit -> Type@{j}), path m n -> P m -> P n. Proof. intros m n P e p. abstract (rewrite e in p; exact p). Defined. Check foo_subproof@{Set Set}. Lemma bar : forall (m n : unit) (P : unit -> Type), path m n -> P m -> P n. Proof. intros m n P e p. abstract (rewrite e in p; exact p). Defined. Check bar_subproof@{Set Set}. rocq-9.2.0/test-suite/success/abstract_with_evars.v000066400000000000000000000011171516144147600225020ustar00rootroot00000000000000 Goal unit. let x := open_constr:(_) in let _ := open_constr:(eq_refl : x = tt) in abstract (exact x). Qed. Goal unit. let x := open_constr:(_) in let tac := exact x in (* <- this is a closure *) let _ := open_constr:(eq_refl : x = tt) in abstract tac. Qed. Goal unit. Fail let x := open_constr:(_) in abstract exact x. Abort. Require Import Ltac2.Ltac2. Goal unit. let x := '_ in let _ := '(eq_refl : $x = tt) in abstract (exact $x). Qed. Goal unit. let x := '_ in let tac () := exact $x in let _ := '(eq_refl : $x = tt) in abstract (tac ()). Qed. rocq-9.2.0/test-suite/success/all_check.v000066400000000000000000000000441516144147600203470ustar00rootroot00000000000000Goal True. Fail all:Check _. Abort. rocq-9.2.0/test-suite/success/applyTC.v000066400000000000000000000004531516144147600200220ustar00rootroot00000000000000Axiom P : nat -> Prop. Class class (A : Type) := { val : A }. Lemma usetc {t : class nat} : P (@val nat t). Admitted. Notation "{val:= v }" := (@val _ v). #[export] Instance zero : class nat := {| val := 0 |}. Lemma test : P 0. Fail apply usetc. pose (tmp := usetc); apply tmp; clear tmp. Qed. rocq-9.2.0/test-suite/success/apply_template.v000066400000000000000000000002741516144147600214670ustar00rootroot00000000000000Inductive T (A : Type) := tt. Universe u. Lemma dummy : forall (A : Type@{u}), T A. Proof. intros; apply tt. Qed. Constraint T.u0 < u. (* Check that there is no constraint u <= T.u0 *) rocq-9.2.0/test-suite/success/attribute_syntax.v000066400000000000000000000021221516144147600220520ustar00rootroot00000000000000From Corelib Require Program.Wf. Section Scope. #[local] Coercion nat_of_bool (b: bool) : nat := if b then 0 else 1. Check (refl_equal : true = 0 :> nat). End Scope. Fail Check 0 = true :> nat. #[universes(polymorphic)] Definition ΞΉ T (x: T) := x. Check ΞΉ _ ΞΉ. #[universes(polymorphic=no)] Definition ΞΉΞΉ T (x: T) := x. Fail Check ΞΉΞΉ _ ΞΉΞΉ. #[program] Fixpoint f (n: nat) {wf lt n} : nat := _. Reset f. #[program=yes] Fixpoint f (n: nat) {wf lt n} : nat := _. Reset f. #[deprecated(since="8.9.0")] Ltac foo := foo. Module M. #[local] #[universes(polymorphic)] Definition zed := Type. #[local, universes(polymorphic)] Definition kats := Type. End M. Check M.zed@{_}. Fail Check zed. Check M.kats@{_}. Fail Check kats. Export Set Foo. #[ export ] Set Foo. Fail #[ export ] Export Foo. (* Attribute for Locality specified twice *) (* Tests for deprecated attribute syntax *) Set Warnings "-deprecated-attribute-syntax". #[program=yes] Fixpoint f (n: nat) {wf lt n} : nat := _. Reset f. #[universes(polymorphic=no)] Definition ΞΉΞΉΞΉ T (x: T) := x. Fail Check ΞΉΞΉΞΉ _ ΞΉΞΉΞΉ. rocq-9.2.0/test-suite/success/auto.v000066400000000000000000000066141516144147600174230ustar00rootroot00000000000000(* coq-prog-args: ("-async-proofs" "off") *) (* Wish #2154 by E. van der Weegen *) (* auto was not using f_equal-style lemmas with metavariables occurring only in the type of an evar of the concl, but not directly in the concl itself *) Parameters (F: Prop -> Prop) (G: forall T, (T -> Prop) -> Type) (L: forall A (P: A -> Prop), G A P -> forall x, F (P x)) (Q: unit -> Prop). #[export] Hint Resolve L. Goal G unit Q -> F (Q tt). intro. eauto. Qed. (* Test implicit arguments in "using" clause *) Goal forall n:nat, nat * nat. epose (H := pair O). auto using H. Undo. eauto using H. Qed. Create HintDb test discriminated. Parameter foo : forall x, x = x + 0. #[export] Hint Resolve foo : test. Parameter C : nat -> Type -> Prop. Parameter c_inst : C 0 nat. #[export] Hint Resolve c_inst : test. #[export] Hint Mode C - + : test. #[export] Hint Resolve c_inst : test2. #[export] Hint Mode C + + : test2. Goal exists n, C n nat. Proof. eexists. Fail progress debug eauto with test2. progress eauto with test. Qed. (** Patterns of Extern have a "matching" semantics. It is not so for apply/exact hints *) Class B (A : Type). Class I. #[export] 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). 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 := {}. (* pattern_of_constr -> B nat *) (* exact hint *) Check (_ : B nat). (* map_eauto -> B_instance0 *) (* NO Constr_matching.matches !!! *) Check (_ : B _). Goal exists T, B T. eexists. eauto with typeclass_instances. Qed. Local Instance: D ftest := {}. Local Hint Resolve flipD | 0 : typeclass_instances. (* pattern: D (flip _) *) Fail Timeout 1 Check (_ : D _). (* loops applying flipD *) End Instnopat. Module InstnopatApply. Local Instance: I -> B nat := {}. (* pattern_of_constr -> B nat *) (* apply hint *) Check (_ : B nat). (* map_eauto -> B_instance0 *) (* NO Constr_matching.matches !!! *) Check (_ : B _). Goal exists T, B T. eexists. eauto with typeclass_instances. Qed. End InstnopatApply. Module InstPat. #[export] Hint Extern 3 (B nat) => split : typeclass_instances. (* map_eauto -> Extern hint *) (* Constr_matching.matches -> true *) Check (_ : B nat). (* map_eauto -> Extern hint *) (* Constr_matching.matches -> false: Because an inductive in the pattern does not match an evar in the goal *) Check (_ : B _). Goal exists T, B T. eexists. (* map_existential -> Extern hint *) (* Constr_matching.matches -> false *) Fail progress eauto with typeclass_instances. (* map_eauto -> Extern hint *) (* Constr_matching.matches -> false *) Fail typeclasses eauto. Abort. #[export] Hint Extern 0 (D (flip _)) => apply flipD : typeclass_instances. Module withftest. Local Instance: D ftest := {}. Check (_ : D _). (* D_instance_0 : D ftest *) Check (_ : D (flip _)). (* ... : D (flip ftest) *) End withftest. Module withoutftest. #[export] Hint Extern 0 (D ftest) => split : typeclass_instances. Check (_ : D _). (* ? : D ?, _not_ looping *) Check (_ : D (flip _)). (* ? : D (flip ?), _not_ looping *) Check (_ : D (flip ftest)). (* flipD ftest {| |} : D (flip ftest) *) End withoutftest. End InstPat. rocq-9.2.0/test-suite/success/autointros.v000066400000000000000000000006611516144147600206560ustar00rootroot00000000000000Inductive even : nat -> Prop := | even_0 : even 0 | even_odd : forall n, odd n -> even (S n) with odd : nat -> Prop := | odd_1 : odd 1 | odd_even : forall n, even n -> odd (S n). Lemma foo {n : nat} (E : even n) : even (S (S n)) with bar {n : nat} (O : odd n) : odd (S (S n)). Proof. destruct E. constructor. constructor. apply even_odd. apply (bar _ H). destruct O. repeat constructor. apply odd_even. apply (foo _ H). Defined. rocq-9.2.0/test-suite/success/autorewrite.v000066400000000000000000000016661516144147600210270ustar00rootroot00000000000000Parameter Ack : nat -> nat -> nat. Axiom Ack0 : forall m : nat, Ack 0 m = S m. Axiom Ack1 : forall n : nat, Ack (S n) 0 = Ack n 1. Axiom Ack2 : forall n m : nat, Ack (S n) (S m) = Ack n (Ack (S n) m). Module M. #[export] Hint Rewrite Ack0 Ack1 Ack2 : base0. Lemma ResAck0 : (Ack 2 2 = 7 -> False) -> False. Proof. intros. autorewrite with base0 in H using try (apply H; reflexivity). Qed. End M. Lemma ResAck1 : forall H:(Ack 2 2 = 7 -> False), True -> False. Proof. intros. Fail autorewrite with base0 in *. Abort. Import M. Lemma ResAck1 : forall H:(Ack 2 2 = 7 -> False), True -> False. Proof. intros. autorewrite with base0 in *. apply H;reflexivity. Qed. (* Check autorewrite does not solve existing evars *) (* See discussion started by A. Chargueraud in Oct 2010 on coqdev *) Global Hint Rewrite <- plus_n_O : base1. Goal forall y, exists x, y+x = y. eexists. autorewrite with base1. Fail reflexivity. Abort. rocq-9.2.0/test-suite/success/bnet.v000066400000000000000000000132161516144147600173770ustar00rootroot00000000000000Set Printing All. (* Set Typeclasses Debug Verbosity 2. *) Create HintDb test discriminated. Definition id {X} (x:X) := x. Hint Transparent id : test. Definition opq {X} (x:X) := x. Hint Opaque opq : test. Definition const {X} (x y : X) := x. Hint Transparent const : test. Class C {X:Type} (x : X) := MKC {}. Module M1. Definition f1 (_ : unit) := tt. Hint Opaque f1 : test. Definition C1 : C (fun x => f1 x) := MKC _ _. Hint Resolve C1 : test. Goal C (fun x => f1 x). Proof. Print HintDb test. typeclasses eauto with test. Qed. Goal C (fun x => id (f1) x). Proof. Print HintDb test. typeclasses eauto with test. Qed. Goal C (fun x => opq (f1) x). Proof. Print HintDb test. Fail typeclasses eauto with test. Abort. Goal C f1. Proof. Print HintDb test. typeclasses eauto with test. Qed. End M1. Module M2. Definition f2 (_ _ : unit) := tt. Hint Opaque f2 : test. Definition C2 : C (fun x y : unit => f2 x y) := MKC _ _. Hint Resolve C2 : test. Goal C (fun x y : unit => f2 x y). Proof. Print HintDb test. typeclasses eauto with test. Abort. Goal C (fun x y : unit => id f2 x y). Proof. Print HintDb test. typeclasses eauto with test. Abort. Goal C f2. Proof. Print HintDb test. typeclasses eauto with test. Abort. Definition C2f : C (fun z x y : unit => f2 x y) := MKC _ _. Hint Resolve C2f : test. Goal C (fun z : unit => f2). Proof. Print HintDb test. typeclasses eauto with test. Abort. End M2. Module const. Inductive option (X : Type) := None | Some (x : X). Definition C_constant {X Y} (c : Y) : C (fun _ : X => c) := MKC _ _. Hint Resolve C_constant : test. Goal C (fun _ : nat => @None unit). Proof. Print HintDb test. typeclasses eauto with test. Qed. End const. Module PrimProjParamsNoArgs. #[projections(primitive)] Record r (dummy : unit) := v { f : unit }. Hint Opaque f : test. (* Proj hint, Proj goal *) Module M1. Definition C_pproj dummy : C (fun r : r dummy => r.(f _)) := MKC _ _. Hint Resolve C_pproj : test. Goal forall dummy, C (fun r : r dummy => r.(f _)). Proof. intros dummy. Print HintDb test. typeclasses eauto with test. Qed. End M1. (* Proj hint, Compat constant goal *) Module M2. Definition C_pproj (dummy : unit) : C (fun r => f dummy r) := MKC _ _. Hint Resolve C_pproj : test. Goal forall dummy, C (fun r : r dummy => ltac:(exact (f dummy)) r). Proof. intros dummy. Print HintDb test. typeclasses eauto with test. Qed. End M2. (* Compat constant hint, Proj goal *) Module M3. Definition C_pproj (dummy : unit) : C (fun r => ltac:(exact (f dummy)) r) := MKC _ _. Hint Resolve C_pproj : test. Goal forall dummy, C (fun r : r dummy => r.(f _ )). Proof. intros dummy. Print HintDb test. typeclasses eauto with test. Qed. End M3. (* Compat constant hint, compat constant goal *) Module M4. Definition C_pproj (dummy : unit) : C (fun r => ltac:(exact (f dummy)) r) := MKC _ _. Hint Resolve C_pproj : test. Goal forall dummy, C (fun r => ltac:(exact (f dummy)) r). Proof. intros dummy. Print HintDb test. typeclasses eauto with test. Qed. End M4. End PrimProjParamsNoArgs. Module PrimProjParamsArgs. #[projections(primitive)] Record r (dummy : unit) := v { f : nat }. Hint Opaque f : test. Axiom (P : (unit -> unit -> unit -> nat) -> Prop). Axiom (x : r tt). (* Proj hint, Proj goal *) Module M1. Definition C_pproj : C (P (fun _ _ _ : unit => x.(f _))) := MKC _ _. Hint Resolve C_pproj : test. Goal C (P (fun _ _ _ : unit => x.(f _))). Proof. Print HintDb test. typeclasses eauto with test. Qed. End M1. (* Proj hint, Compat constant goal *) Module M2. Definition C_pproj : C (P (fun _ _ _ : unit => x.(f _))) := MKC _ _. Hint Resolve C_pproj : test. Goal C (P (fun _ _ _ : unit => ltac:(exact (f _ x)))). Proof. Print HintDb test. typeclasses eauto with test. Qed. End M2. (* Compat constant hint, Proj goal *) Module M3. Definition C_pproj : C (P (fun _ _ _ : unit => ltac:(exact (f _ x)))) := MKC _ _. Hint Resolve C_pproj : test. Goal C (P (fun _ _ _ : unit => x.(f _))). Proof. Print HintDb test. typeclasses eauto with test. Qed. End M3. (* Compat constant hint, compat constant goal *) Module M4. Definition C_pproj : C (P (fun _ _ _ : unit => ltac:(exact (f _ x)))) := MKC _ _. Hint Resolve C_pproj : test. Goal C (P (fun _ _ _ : unit => ltac:(exact (f _ x)))). Proof. Print HintDb test. typeclasses eauto with test. Qed. End M4. End PrimProjParamsArgs. Module Negative. (* To test the discriminating power of the bnet we construct a hint that always succeeds. Then, we manually restrict it to interesting patterns and ensure that the application is never attempted by asserting that the overall search fails. *) Definition CA {X} x : @C X x := MKC _ _. Definition f (_ _ : unit) := tt. Definition g (_ _ : unit) := tt. Hint Opaque f g : test. Module M1. Hint Resolve CA | (@C _ (fun x => f x)) : test. Goal C (fun x => g x). Proof. Fail typeclasses eauto with test. Abort. End M1. Module M1i. Hint Resolve CA | (@C _ (fun x => f (id x))) : test. Goal C (fun x => g x). Proof. Fail typeclasses eauto with test. Abort. End M1i. Module M1o. Hint Resolve CA | (@C _ (fun x => f (opq x))) : test. Goal C (fun x => g x). Proof. Fail typeclasses eauto with test. Abort. End M1o. End Negative. rocq-9.2.0/test-suite/success/boundvars.v000066400000000000000000000011551516144147600204510ustar00rootroot00000000000000(* An example showing a bug in the detection of free variables *) (* "x" is not free in the common type of "x" and "y" *) Check forall (x z:unit) (x y : match z as x return x=x with tt => eq_refl end = eq_refl), x=x. (* An example showing a bug in the detection of bound variables *) Goal forall x, match x return x = x with 0 => eq_refl | _ => eq_refl end = eq_refl. intro. match goal with |- (match x as y in nat return y = y with O => _ | S n => _ end) = _ => assert (forall y, y = 0) end. intro. Check x0. (* Check that "y" has been bound to "x0" while matching "match x as x0 return x0=x0 with ... end" *) Abort. rocq-9.2.0/test-suite/success/bteauto.v000066400000000000000000000103331516144147600201070ustar00rootroot00000000000000(* coq-prog-args: ("-async-proofs" "off") *) Module Backtracking. Class A := { foo : nat }. #[global] Instance A_1 : A | 2 := { foo := 42 }. #[global] Instance A_0 : A | 1 := { foo := 0 }. Lemma aeq (a : A) : foo = foo. reflexivity. Qed. Arguments foo A : clear implicits. Example find42 : exists n, n = 42. Proof. eexists. eapply eq_trans. evar (a : A). subst a. refine (@aeq ?a). Unshelve. all:cycle 1. typeclasses eauto. Fail reflexivity. Undo 2. (* Without multiple successes it fails *) Set Typeclasses Debug Verbosity 2. Fail all:((once (typeclasses eauto with typeclass_instances)) + apply eq_refl). (* Does backtrack if other goals fail *) all:[> typeclasses eauto + reflexivity .. ]. Undo 1. all:(typeclasses eauto + reflexivity). (* Note "+" is a focussing combinator *) Show Proof. Qed. Print find42. #[global] Hint Extern 0 (_ = _) => reflexivity : equality. Goal exists n, n = 42. eexists. eapply eq_trans. evar (a : A). subst a. refine (@aeq ?a). Unshelve. all:cycle 1. typeclasses eauto. Fail reflexivity. Undo 2. (* Does backtrack between individual goals *) Set Typeclasses Debug. all:(typeclasses eauto with typeclass_instances equality). Qed. Unset Typeclasses Debug. Module Leivant. Axiom A : Type. Existing Class A. Axioms a b c d e: A. #[global] Existing Instances a b c d e. Ltac get_value H := eval cbv delta [H] in H. Goal True. Fail refine (let H := _ : A in _); let v := get_value H in idtac v; fail. Admitted. Goal exists x:A, x=a. unshelve evar (t : A). all:cycle 1. refine (@ex_intro _ _ t _). all:cycle 1. all:(typeclasses eauto + reflexivity). Qed. End Leivant. End Backtracking. #[export] Hint Resolve eq_sym eq_trans | 100 : core. #[export] Hint Cut [(_)* eq_sym eq_sym] : core. #[export] Hint Cut [_* eq_trans eq_trans] : core. #[export] Hint Cut [_* eq_trans eq_sym eq_trans] : core. Goal forall x y z : nat, x = y -> z = y -> x = z. Proof. intros. typeclasses eauto with core. Qed. Module Hierarchies. Class A := mkA { data : nat }. Class B := mkB { aofb :: A }. #[export] Existing Instance mkB. Definition makeB (a : A) : B := _. Definition makeA (a : B) : A := _. (* Fail Timeout 1 Definition makeA' : A := _. *) #[export] Hint Cut [_* mkB aofb] : typeclass_instances. Fail Definition makeA' : A := _. Fail Definition makeB' : B := _. End Hierarchies. (** Hint modes *) Class Equality (A : Type) := { eqp : A -> A -> Prop }. Check (eqp 0%nat 0). #[export] Instance nat_equality : Equality nat := { eqp := eq }. #[export] Instance default_equality A : Equality A | 1000 := { eqp := eq }. Check (eqp 0%nat 0). (* Defaulting *) Check (fun x y => eqp x y). (* No more defaulting, reduce "trigger-happiness" *) Definition ambiguous x y := eqp x y. #[export] Hint Mode Equality ! : typeclass_instances. Fail Definition ambiguous' x y := eqp x y. Definition nonambiguous (x y : nat) := eqp x y. (** Typical looping instances with defaulting: *) Definition flip {A B C} (f : A -> B -> C) := fun x y => f y x. Class SomeProp {A : Type} (f : A -> A -> A) := { prf : forall x y, f x y = f x y }. #[export] Instance propflip (A : Type) (f : A -> A -> A) : SomeProp f -> SomeProp (flip f). Proof. intros []. constructor. reflexivity. Qed. (* Fail Timeout 1 Check prf. *) #[export] Hint Mode SomeProp + + : typeclass_instances. Check prf. Check (fun H : SomeProp plus => _ : SomeProp (flip plus)). (** Iterative deepening / breadth-first search *) Module IterativeDeepening. Class A. Class B. Class C. #[export] Instance: B -> A | 0 := {}. #[export] Instance: C -> A | 0 := {}. #[export] Instance: C -> B -> A | 0 := {}. #[export] Instance: A -> A | 0 := {}. Goal C -> A. intros. (* Fail Timeout 1 typeclasses eauto. *) Set Typeclasses Iterative Deepening. Fail typeclasses eauto 1. typeclasses eauto 2. Undo. Unset Typeclasses Iterative Deepening. (* Fail Timeout 1 typeclasses eauto. *) Set Typeclasses Iterative Deepening. Typeclasses eauto := debug 3. typeclasses eauto. Qed. End IterativeDeepening. rocq-9.2.0/test-suite/success/bullet.v000066400000000000000000000000651516144147600177340ustar00rootroot00000000000000Goal True /\ True. split. - exact I. - exact I. Qed. rocq-9.2.0/test-suite/success/case_let_conversion.v000066400000000000000000000014551516144147600224750ustar00rootroot00000000000000Axiom checker_flags : Set. Inductive Box (R : Type) : Type := box : Box R. Inductive typing (H : checker_flags) : Type := | type_Rel : typing H -> typing H | type_Case : let i := tt in Box (typing H) -> typing H. Definition unbox (P : Type) (b : Box P) := match b with box _ => 0 end. Definition size (H : checker_flags) (d : typing H) : nat. Proof. revert d. fix size 1. destruct 1. - exact (size d). - exact (unbox _ b). Defined. Definition foo (H : checker_flags) (a : typing H) : size H (type_Rel H a) = size H a. Proof. simpl. reflexivity. Qed. Definition bar (H : checker_flags) (a : typing H) : size H (type_Rel H a) = size H a. Proof. vm_compute. reflexivity. Qed. Definition qux (H : checker_flags) (a : typing H) : size H (type_Rel H a) = size H a. Proof. native_compute. reflexivity. Qed. rocq-9.2.0/test-suite/success/case_let_param.v000066400000000000000000000004311516144147600214010ustar00rootroot00000000000000Inductive foo (x := tt) := Foo : forall (y := x), foo. Definition get (t : foo) := match t with Foo _ y => y end. Goal get Foo = tt. Proof. reflexivity. Qed. Goal forall x : foo, match x with Foo _ y => y end = match x with Foo _ _ => tt end. Proof. intros. reflexivity. Qed. rocq-9.2.0/test-suite/success/cbn.v000066400000000000000000000032151516144147600172070ustar00rootroot00000000000000(* cbn is able to refold mutual recursive calls *) Fixpoint foo (n : nat) := match n with | 0 => true | S n => g n end with g (n : nat) : bool := match n with | 0 => true | S n => foo n end. Goal forall n, foo (S n) = g n. intros. cbn. match goal with |- g _ = g _ => reflexivity end. Qed. (* simpl nomatch *) Definition thing n := match n with 0 => True | S n => False end. Arguments thing _ / : simpl nomatch. Goal forall x, thing x. intros. cbn. match goal with |- thing x => idtac end. Abort. Definition thing' n := n + n. Arguments thing' !_ / : simpl nomatch. Lemma bar n : thing' n = 0. Proof. cbn. match goal with |- thing' _ = _ => idtac end. Arguments thing' _ / : simpl nomatch. cbn. match goal with |- _ + _ = _ => idtac end. Abort. Module MutualFixCoFixInSection. Section S. Variable p:nat. Fixpoint f n := match n with 0 => p | S n => f n + g n end with g n := match n with 0 => p | S n => f n + g n end. End S. Goal forall n, f n (S n) = g 0 (S n). intros. cbn. match goal with [ |- f n n + g n n = f 0 n + g 0 n ] => idtac end. Abort. CoInductive stream {A:Type} : Type := | scons: A->stream->stream. Definition stream_unfold {A} (s: @ stream A) := match s with | scons a s' => (a, scons a s') end. Section C. Variable (x:nat). CoFixpoint mut_stream1 (n:nat) := scons n (mut_stream2 (n+x)) with mut_stream2 (n:nat) := scons n (mut_stream1 (n+x)). End C. Goal (forall x n, stream_unfold (mut_stream1 x n) = stream_unfold (mut_stream2 x n)). intros. cbn. match goal with [ |- (n, scons n (mut_stream2 x (n + x))) = (n, scons n (mut_stream1 x (n + x))) ] => idtac end. Abort. End MutualFixCoFixInSection. rocq-9.2.0/test-suite/success/cbv_let.v000066400000000000000000000012311516144147600200570ustar00rootroot00000000000000Record T : Type := Build_T { f : unit; g := pair f f; }. Definition t : T := {| f := tt; |}. Goal match t return unit with Build_T f g => f end = tt. Proof. cbv. reflexivity. Qed. Goal match t return prod unit unit with Build_T f g => g end = pair tt tt. Proof. cbv. reflexivity. Qed. Goal forall (x : T), match x return prod unit unit with Build_T f g => g end = pair match x return unit with Build_T f g => fst g end match x return unit with Build_T f g => snd g end. Proof. cbv. destruct x. reflexivity. Qed. Record U : Type := Build_U { h := tt }. Definition u : U := Build_U. Goal match u with Build_U h => h end = tt. Proof. cbv. reflexivity. Qed. rocq-9.2.0/test-suite/success/cc.v000066400000000000000000000066201516144147600170350ustar00rootroot00000000000000 Theorem t1 : forall (A : Set) (a : A) (f : A -> A), f a = a -> f (f a) = a. intros. congruence. Qed. Theorem t2 : forall (A : Set) (a b : A) (f : A -> A) (g : A -> A -> A), a = f a -> g b (f a) = f (f a) -> g a b = f (g b a) -> g a b = a. intros. congruence. Qed. (* 15=0 /\ 10=0 /\ 6=0 -> 0=1 *) Theorem t3 : forall (N : Set) (o : N) (s d : N -> N), s (s (s (s (s (s (s (s (s (s (s (s (s (s (s o)))))))))))))) = o -> s (s (s (s (s (s (s (s (s (s o))))))))) = o -> s (s (s (s (s (s o))))) = o -> o = s o. intros. congruence. Qed. (* Examples that fail due to dependencies *) (* yields transitivity problem *) Theorem dep : forall (A : Set) (P : A -> Set) (f g : forall x : A, P x) (x y : A) (e : x = y) (e0 : f y = g y), f x = g x. intros; dependent rewrite e; exact e0. Qed. (* yields congruence problem *) Theorem dep2 : forall (A B : Set) (f : forall (A : Set) (b : bool), if b then unit else A -> unit) (e : A = B), f A true = f B true. intros; rewrite e; reflexivity. Qed. (* example that Congruence. can solve (dependent function applied to the same argument)*) Theorem dep3 : forall (A : Set) (P : A -> Set) (f g : forall x : A, P x), f = g -> forall x : A, f x = g x. intros. congruence. Qed. (* Examples with injection rule *) Theorem inj1 : forall (A : Set) (a b c d : A), (a, c) = (b, d) -> a = b /\ c = d. intros. split; congruence. Qed. Theorem inj2 : forall (A : Set) (a c d : A) (f : A -> A * A), f = pair (B:=A) a -> Some (f c) = Some (f d) -> c = d. intros. congruence. Qed. (* Examples with discrimination rule *) Theorem discr1 : true = false -> False. intros. congruence. Qed. Theorem discr2 : Some true = Some false -> False. intros. congruence. Qed. (* example with implications *) Theorem arrow : forall (A B: Prop) (C D:Set) , A=B -> C=D -> (A -> C) = (B -> D). congruence. Qed. Set Implicit Arguments. Parameter elt: Set. Parameter elt_eq: forall (x y: elt), {x = y} + {x <> y}. Definition t (A: Set) := elt -> A. Definition get (A: Set) (x: elt) (m: t A) := m x. Definition set (A: Set) (x: elt) (v: A) (m: t A) := fun (y: elt) => if elt_eq y x then v else m y. Lemma gsident: forall (A: Set) (i j: elt) (m: t A), get j (set i (get i m) m) = get j m. Proof. intros. unfold get, set. case (elt_eq j i); intro. congruence. auto. Qed. (* bug 2447 is now closed (PC, 2014) *) Section bug_2447. Variable T:Type. Record R := mkR {x:T;y:T;z:T}. Variables a a' b b' c c':T. Lemma bug_2447: mkR a b c = mkR a' b c -> a = a'. congruence. Qed. Lemma bug_2447_variant1: mkR a b c = mkR a b' c -> b = b'. congruence. Qed. Lemma bug_2447_variant2: mkR a b c = mkR a b c' -> c = c'. congruence. Qed. End bug_2447. (* congruence was supposed to do discriminate but it was bugged for types with indices *) Inductive I : nat -> Type := C : I 0 | D : I 0. Goal ~C=D. congruence. Qed. (* Example by Jonathan Leivant, congruence up to universes *) Section JLeivant. Variables S1 S2 : Set. Definition T1 : Type := S1. Definition T2 : Type := S2. Goal T1 = T1. congruence. Undo. unfold T1. congruence. Qed. End JLeivant. (* An example with primitive projections *) Module PrimitiveProjections. Set Primitive Projections. Record t (A:Type) := { f : A }. Goal forall g (a:t nat), @f nat = g -> f a = 0 -> g a = 0. congruence. Undo. intros. unfold f in H0. (* internally turn the projection to unfolded form *) congruence. Qed. End PrimitiveProjections. rocq-9.2.0/test-suite/success/change.v000066400000000000000000000040561516144147600176760ustar00rootroot00000000000000(* A few tests of the syntax of clauses and of the interpretation of change *) Goal let a := 0+0 in a=a. intro. change 0 in (value of a). change ((fun A:Type => A) nat) in (type of a). Abort. Goal forall x, 2 + S x = 1 + S x. intro. change (?u + S x) with (S (u + x)). Abort. (* Check the combination of at, with and in (see bug #2146) *) Goal 3=3 -> 3=3. intro H. change 3 with (1+2) at 2. change 3 with (1+2) in H at 2 |-. change 3 with (1+2) in H at 1 |- * at 1. (* Now check that there are no more 3's *) change 3 with (1+2) in * || reflexivity. Qed. (* Note: the following is invalid and must fail change 3 at 1 with (1+2) at 3. change 3 at 1 with (1+2) in *. change 3 at 1 with (1+2) in H at 2 |-. change 3 at 1 with (1+2) at 3. change 3 at 1 with (1+2) in H |- *. change 3 at 1 with (1+2) in H, H|-. change 3 at 1. *) (* Test that pretyping checks allowed elimination sorts *) Goal True. Fail change True with (let (x,a) := ex_intro _ True (eq_refl True) in x). Fail change True with match ex_intro _ True (eq_refl True) with ex_intro x _ => x end. Abort. (* Check absence of loop in identity substitution (was failing up to Sep 2014, see #3641) *) Goal True. change ?x with x. Abort. (* Check typability after change of type subterms *) Goal nat = nat :> Set. Fail change nat with (@id Type nat). (* would otherwise be ill-typed *) Abort. (* Check typing env for rhs is the correct one *) Goal forall n, let x := n in id (fun n => n + x) 0 = 0. intros. unfold x. (* check that n in 0+n is not interpreted as the n from "fun n" *) change n with (0+n). Abort. (* Check non-collision of non-normalized defined evars with pattern variables *) Goal exists x, 1=1 -> x=1/\x=1. eexists ?[n]; intros; split. eassumption. match goal with |- ?x=1 => change (x=1) with (0+x=1) end. match goal with |- 0+1=1 => trivial end. Qed. (* Mini-check that no_check does not check *) Goal True -> False. intro H. change_no_check nat. apply S. change_no_check nat with bool. change_no_check nat in H. change_no_check nat with (bool->bool) in H. exact (H true). Fail Qed. Abort. rocq-9.2.0/test-suite/success/change_case.v000066400000000000000000000006411516144147600206650ustar00rootroot00000000000000Inductive box (A : Type) := Box : A -> box A. Axiom PRED : unit -> Prop. Axiom FUN : forall (u : unit), box (PRED u). Axiom U : unit. Definition V := U. Goal match FUN U with Box _ _ => True end. Proof. repeat match goal with | [ |- context G[ U ] ] => let e := context G [ V ] in change e end. set (Z := V). clearbody Z. (* This fails if change misses the case parameters *) destruct (FUN Z). constructor. Qed. rocq-9.2.0/test-suite/success/change_pattern.v000066400000000000000000000023431516144147600214300ustar00rootroot00000000000000Set Implicit Arguments. Unset Strict Implicit. Axiom vector : Type -> nat -> Type. Record KleeneStore i j a := kleeneStore { dim : nat ; peek : vector j dim -> a ; pos : vector i dim }. Definition KSmap i j a b (f : a -> b) (s : KleeneStore i j a) : KleeneStore i j b := kleeneStore (fun v => f (peek v)) (pos s). Record KleeneCoalg (i o : Type -> Type) := kleeneCoalg { coalg :> forall a b, (o a) -> KleeneStore (i a) (i b) (o b) }. Axiom free_b_dim : forall i o (k : KleeneCoalg i o) a b b' (x : o a), dim (coalg k b x) = dim (coalg k b' x). Axiom t : Type -> Type. Axiom traverse : KleeneCoalg (fun x => x) t. Definition size a (x:t a) : nat := dim (traverse a a x). Lemma iso1_iso2_2 a (y : {x : t unit & vector a (size x)}) : False. Proof. destruct y. pose (X := KSmap (traverse a unit) (traverse unit a x)). set (e :=(eq_sym (free_b_dim traverse (a:=unit) a unit x))). clearbody e. (** The pattern generated by change must have holes where there were implicit arguments in the original user-provided term. This particular example fails if this is not the case because the inferred argument does not coincide with the one in the considered term. *) progress (change (dim (traverse unit a x)) with (dim X) in e). Abort. rocq-9.2.0/test-suite/success/clear.v000066400000000000000000000010701516144147600175300ustar00rootroot00000000000000Goal forall x:nat, (forall x, x=0 -> True)->True. intros; eapply H. instantiate (1:=(fun y => _) (S x)). simpl. clear x. trivial. Qed. Goal forall y z, (forall x:nat, x=y -> True) -> y=z -> True. intros; eapply H. rename z into z'. clear H0. clear z'. reflexivity. Qed. Class A. Section Foo. Variable a : A. Goal A. solve [typeclasses eauto]. Undo 1. clear a. try typeclasses eauto. assert(a:=Build_A). solve [ typeclasses eauto ]. Undo 2. assert(b:=Build_A). solve [ typeclasses eauto ]. Qed. End Foo. rocq-9.2.0/test-suite/success/coercions.v000066400000000000000000000143251516144147600204350ustar00rootroot00000000000000Module InitialTest. (* Interaction between coercions and casts *) (* Example provided by Eduardo Gimenez *) Parameter Z S : Set. Parameter f : S -> Z. Coercion f : S >-> Z. Parameter g : Z -> Z. Check (fun s => g (s:S)). (* Check uniform inheritance condition *) Parameter h : nat -> nat -> Prop. Parameter i : forall n m : nat, h n m -> nat. Coercion i : h >-> nat. (* Check coercion to funclass when the source occurs in the target *) Parameter C : nat -> nat -> nat. Coercion C : nat >-> Funclass. (* Remark: in the following example, it cannot be decided whether C is from nat to Funclass or from A to nat. An explicit Coercion command is expected Parameter A : nat -> Prop. Parameter C:> forall n:nat, A n -> nat. *) (* Check coercion between products based on eta-expansion *) (* (there was a de Bruijn bug until rev 9254) *) Section P. Variable E : Set. Variables C D : E -> Prop. Variable G :> forall x, C x -> D x. Check fun (H : forall y:E, y = y -> C y) => (H : forall y:E, y = y -> D y). End P. (* Check that class arguments are computed the same when looking for a coercion and when applying it (class_args_of) (failed until rev 9255) *) Section Q. Variable bool : Set. Variables C D : bool -> Prop. Variable G :> forall x, C x -> D x. Variable f : nat -> bool. Definition For_all (P : nat -> Prop) := forall x, P x. Check fun (H : For_all (fun x => C (f x))) => H : forall x, D (f x). Check fun (H : For_all (fun x => C (f x))) x => H x : D (f x). Check fun (H : For_all (fun x => C (f x))) => H : For_all (fun x => D (f x)). End Q. (* Combining class lookup and path lookup so that if a lookup fails, another descent in the class can be found (see wish #1934) *) Record Setoid : Type := { car :> Type }. Record Morphism (X Y:Setoid) : Type := {evalMorphism :> X -> Y}. Definition extSetoid (X Y:Setoid) : Setoid. constructor. exact (Morphism X Y). Defined. Definition ClaimA := forall (X Y:Setoid) (f: extSetoid X Y) x, f x= f x. Coercion irrelevant := (fun _ => I) : True -> car (Build_Setoid True). Definition ClaimB := forall (X Y:Setoid) (f: extSetoid X Y) (x:X), f x= f x. (* Check that coercions are made visible only when modules are imported *) Module A. Module B. Coercion b2n (b:bool) := if b then 0 else 1. End B. Fail Check S true. End A. Import A. Fail Check S true. (* Tests after the inheritance condition constraint is relaxed *) Inductive list (A : Type) : Type := nil : list A | cons : A -> list A -> list A. Inductive vect (A : Type) : nat -> Type := vnil : vect A 0 | vcons : forall n, A -> vect A n -> vect A (1+n). Fixpoint size A (l : list A) : nat := match l with nil _ => 0 | cons _ _ tl => 1+size _ tl end. Section test_non_unif_but_complete. Fixpoint l2v A (l : list A) : vect A (size A l) := match l as l return vect A (size A l) with | nil _ => vnil A | cons _ x xs => vcons A (size A xs) x (l2v A xs) end. Local Coercion l2v : list >-> vect. Check (fun l : list nat => (l : vect _ _)). End test_non_unif_but_complete. Section what_we_could_do. Variables T1 T2 : Type. Variable c12 : T1 -> T2. Class coercion (A B : Type) : Type := cast : A -> B. Instance atom : coercion T1 T2 := c12. Instance pair A B C D (c1 : coercion A B) (c2 : coercion C D) : coercion (A * C) (B * D) := fun x => (c1 (fst x), c2 (snd x)). Fixpoint l2v2 {A B} {c : coercion A B} (l : list A) : (vect B (size A l)) := match l as l return vect B (size A l) with | nil _ => vnil B | cons _ x xs => vcons _ _ (c x) (l2v2 xs) end. Local Coercion l2v2 : list >-> vect. Check (fun l : list (T1 * T1) => (l : vect _ _)). Check (fun l : list (T1 * T1) => (l2v2 l : vect _ _)). End what_we_could_do. End InitialTest. (** Unit test for Prop as source class *) Module TestPropAsSourceCoercion. Parameter heap : Prop. Parameter heap_empty : heap. Definition hprop := heap -> Prop. Coercion hpure (P:Prop) : hprop := fun h => h = heap_empty /\ P. Parameter heap_single : nat -> nat -> hprop. Parameter hstar : hprop -> hprop -> hprop. Notation "H1 \* H2" := (hstar H1 H2) (at level 69, left associativity). Definition test := heap_single 4 5 \* (5 <> 4) \* heap_single 2 4 \* (True). (* Print test. -- reveals [hpure] coercions *) End TestPropAsSourceCoercion. (** Unit test for Type as source class *) Module TestTypeAsSourceCoercion. Definition relation A := A -> A -> Prop. Record setoid := { A : Type ; R : relation A }. Definition default_setoid (T : Type) : setoid := {| A := T ; R := eq |}. Coercion default_setoid : Sortclass >-> setoid. Definition foo := Type : setoid. Inductive type := U | Nat. Inductive term : type -> Type := | ty (_ : Type) : term U | nv (_ : nat) : term Nat. Coercion ty : Sortclass >-> term. Definition ty1 := Type : term _. Definition ty2 := Prop : term _. Definition ty3 := Set : term _. Definition ty4 := (Type : Type) : term _. End TestTypeAsSourceCoercion. Module NonUniformInheritance. Parameters (C : nat -> bool-> Type) (D : nat -> Type). Parameter c : C O true. Parameter T : D O -> nat. Section Test0. Parameter f0 : forall (b : bool) (n : nat), C n b -> D n. Local Coercion f0 : C >-> D. Check T c. End Test0. Section Test1. Parameter f1 : forall (n : nat), C n true -> D n. Local Coercion f1 : C >-> D. Check T c. End Test1. Section Test2. Parameter f2 : forall (b : bool) (n : nat) (_ : unit), C n b -> D n. Local Coercion f2 : C >-> D. Check T c. End Test2. Section Test3. Class TC := tc : unit. Instance i : TC := tt. Parameter f3 : forall (b : bool) (n : nat) (_ : TC), C n b -> D n. Local Coercion f3 : C >-> D. Check T c. End Test3. End NonUniformInheritance. Module PhantType. Variant phant (p : Type) : Prop := Phant : phant p. Section SetType. Variable T : Type. Variant set_type : Type := FinSet : T -> set_type. Definition set_of (_ : phant T) := set_type. Identity Coercion type_of_set_of : set_of >-> set_type. End SetType. Definition sort (gT : Type) := set_of _ (Phant gT). Identity Coercion GroupSet_of_sort : sort >-> set_of. Structure group_type (gT : Type) : Type := Group { gval : sort gT; }. Coercion gval : group_type >-> sort. Section GroupProp. Variable G : group_type unit. Check G : @set_type unit. Lemma group1 : let y := G : @set_type unit in True. Abort. End GroupProp. End PhantType. rocq-9.2.0/test-suite/success/cofixtac.v000066400000000000000000000003211516144147600202400ustar00rootroot00000000000000CoInductive stream := | C : content -> stream with content := | D : nat -> stream -> content. Lemma one : stream. cofix c with (d : content). - constructor. apply d. - constructor. exact 1. apply c. Defined. rocq-9.2.0/test-suite/success/coindprim.v000066400000000000000000000053611516144147600204350ustar00rootroot00000000000000Set Primitive Projections. CoInductive Stream (A : Type) := mkStream { hd : A; tl : Stream A}. Arguments mkStream [A] hd tl. Arguments hd [A] s. Arguments tl [A] s. Definition eta {A} (s : Stream A) := {| hd := s.(hd); tl := s.(tl) |}. CoFixpoint ones := {| hd := 1; tl := ones |}. CoFixpoint ticks := {| hd := tt; tl := ticks |}. CoInductive stream_equiv {A} (s : Stream A) (s' : Stream A) : Prop := mkStreamEq { hdeq : s.(hd) = s'.(hd); tleq : stream_equiv s.(tl) s'.(tl) }. Arguments hdeq {A} {s} {s'}. Arguments tleq {A} {s} {s'}. CoFixpoint ones_eq : stream_equiv ones ones.(tl) := {| hdeq := @eq_refl _ (hd ones); tleq := ones_eq |}. CoFixpoint stream_equiv_refl {A} (s : Stream A) : stream_equiv s s := {| hdeq := eq_refl; tleq := stream_equiv_refl (tl s) |}. CoFixpoint stream_equiv_sym {A} (s s' : Stream A) (H : stream_equiv s s') : stream_equiv s' s := {| hdeq := eq_sym H.(hdeq); tleq := stream_equiv_sym _ _ H.(tleq) |}. CoFixpoint stream_equiv_trans {A} {s s' s'' : Stream A} (H : stream_equiv s s') (H' : stream_equiv s' s'') : stream_equiv s s'' := {| hdeq := eq_trans H.(hdeq) H'.(hdeq); tleq := stream_equiv_trans H.(tleq) H'.(tleq) |}. Definition eta_eq {A} (s : Stream A) : stream_equiv s (eta s) := mkStreamEq _ _ (@eta A s) (@eq_refl _ (hd s)) (stream_equiv_refl (tl (eta s))). Section Parks. Variable A : Type. Variable R : Stream A -> Stream A -> Prop. Hypothesis bisim1 : forall s1 s2:Stream A, R s1 s2 -> hd s1 = hd s2. Hypothesis bisim2 : forall s1 s2:Stream A, R s1 s2 -> R (tl s1) (tl s2). CoFixpoint park_ppl : forall s1 s2:Stream A, R s1 s2 -> stream_equiv s1 s2 := fun s1 s2 (p : R s1 s2) => mkStreamEq _ _ _ (bisim1 s1 s2 p) (park_ppl (tl s1) (tl s2) (bisim2 s1 s2 p)). End Parks. CoFixpoint iterate {A} (f : A -> A) (x : A) : Stream A := {| hd := x; tl := iterate f (f x) |}. CoFixpoint map {A B} (f : A -> B) (s : Stream A) : Stream B := {| hd := f s.(hd); tl := map f s.(tl) |}. Theorem map_iterate A (f : A -> A) (x : A) : stream_equiv (iterate f (f x)) (map f (iterate f x)). Proof. apply park_ppl with (R:= fun s1 s2 => exists x : A, s1 = iterate f (f x) /\ s2 = map f (iterate f x)). now intros s1 s2 (x0,(->,->)). intros s1 s2 (x0,(->,->)). now exists (f x0). now exists x. Qed. Fail Check (fun A (s : Stream A) => eq_refl : s = eta s). Notation convertible x y := (eq_refl x : x = y). Fail Check convertible ticks {| hd := hd ticks; tl := tl ticks |}. CoInductive U := inU { outU : U }. CoFixpoint u : U := inU u. CoFixpoint force (u : U) : U := inU (outU u). Lemma eq (x : U) : x = force x. Proof. Fail destruct x. Abort. (* Impossible *) rocq-9.2.0/test-suite/success/compat.v000066400000000000000000000003651516144147600177330ustar00rootroot00000000000000(* -*- coq-prog-args: ("-compat-from" "TestSuite" "admit"); -*- *) (* Check that TestSuite.admit was required *) Goal False. Proof. exact TestSuite.admit.proof_admitted. Qed. (* and also imported *) Goal False. Proof. exact proof_admitted. Qed. rocq-9.2.0/test-suite/success/congruence.v000066400000000000000000000060021516144147600205720ustar00rootroot00000000000000Inductive Inner : Type := | innerI_nat : forall (x:nat), Inner | innerI_fun : forall (f:nat->Type), Inner | innerI_inner : forall (i:Inner), Inner | innerI_Type : forall (T:Type), Inner | innerI_extra : Inner. Inductive ExtractTest (A:Type) (F:nat->Type) (I:Inner): Inner -> Inner -> unit -> Type := | extract_f_x_from_index : forall (x:nat) (f:nat->Type) (t:f x), ExtractTest A F I (innerI_inner (innerI_nat x)) (innerI_fun f) tt | extract_F_from_param_x_from_index : forall (x:nat) (f:nat->Type) (t:F x), ExtractTest A F I (innerI_inner (innerI_nat x)) innerI_extra tt | extract_fail : forall (x y: nat) (f : nat -> Type) (t : f x), ExtractTest A F I (innerI_nat y) (innerI_fun f) tt | extract_fx_from_index : forall (x:nat) (f:nat->Type) (t:f x), ExtractTest A F I (innerI_Type (f x)) innerI_extra tt | extract_t_match : forall (b:bool) (t:if b then unit else nat), ExtractTest A F I (innerI_Type (if b then unit else nat)) innerI_extra tt . Lemma test_extract_f_x_from_index A F x f t1 t2 : extract_f_x_from_index A F innerI_extra x f t1 = extract_f_x_from_index A F innerI_extra x f t2 -> t1 = t2. Proof. intros H. congruence. Qed. Lemma test_extract_F_from_param_x_from_index A F x f t1 t2 : extract_F_from_param_x_from_index A F innerI_extra x f t1 = extract_F_from_param_x_from_index A F innerI_extra x f t2 -> t1 = t2. Proof. intros H. congruence. Qed. Lemma test_extract_fx_from_index A F x f t1 t2 : extract_fx_from_index A F innerI_extra x f t1 = extract_fx_from_index A F innerI_extra x f t2 -> t1 = t2. Proof. intros H. congruence. Qed. Inductive Vector (A : Type) : nat -> Type := | nil : Vector A 0 | cons : forall (h : A) (n : nat) (t : Vector A n), Vector A (S n). Local Notation "[ ]" := (nil _) (format "[ ]"). Local Notation "h :: t" := (cons _ h _ t) (at level 60, right associativity). Lemma test_vec_eq (A:Type) (x:A) (n:nat) (v v' : Vector A n) : (x::v = x::v') -> v = v'. Proof. congruence. Qed. Inductive Fin : nat -> Set := | F1 : forall {n}, Fin (S n) | FS : forall {n}, Fin n -> Fin (S n). Lemma test_fin_eq (n:nat) (f f': Fin n) : FS f = FS f' -> f = f'. Proof. congruence. Qed. Record R (A : Type) (B : A -> Type) : Type := RI { a : A; b : B a }. Goal forall A B (x : A) (y1 y2 : B), y1 <> y2 -> RI _ _ x y1 <> RI _ _ x y2. Proof. intros. congruence. Qed. Inductive wrap1 (X : unit -> Type) : unit -> forall (v : unit), X v -> Type := | wrap1_zero (x : X tt) : wrap1 X tt tt x | wrap1_succ u v x : wrap1 X u v x -> wrap1 X u v x. Lemma test_wrap1 (x y : unit) (p q : wrap1 (fun _ : unit => unit) tt y x) : wrap1_succ (fun _ => unit) tt y x p = wrap1_succ (fun _ => unit) tt y x q -> p = q. Proof. congruence. Qed. Inductive wrap2 (X : unit -> Type) : unit -> forall (v : unit), X tt -> Type := | wrap2_zero (x : X tt) : wrap2 X tt tt x | wrap2_succ u v x : wrap2 X u v x -> wrap2 X u v x. Lemma test_wrap2 (y : unit) (X : unit -> Type) (x : X tt) (p q : wrap2 X tt y x) : wrap2_succ X tt y x p = wrap2_succ X tt y x q -> p = q. Proof. congruence. Qed. rocq-9.2.0/test-suite/success/congruence_prim.v000066400000000000000000000006531516144147600216270ustar00rootroot00000000000000Require Import Corelib.Numbers.Cyclic.Int63.PrimInt63. Require Import Corelib.Strings.PrimString. Require Import Corelib.Floats.PrimFloat. Inductive Box (A : Type) := box : A -> Box A. Arguments box {A}. Goal box 0%uint63 = box 1%uint63 -> False. Proof. congruence. Abort. Goal box "true"%pstring = box "false"%pstring -> False. Proof. congruence. Qed. Goal box 1.0%float = box 2.0%float -> False. Proof. congruence. Qed. rocq-9.2.0/test-suite/success/contradiction.v000066400000000000000000000010631516144147600213040ustar00rootroot00000000000000(* Some tests for contradiction *) Lemma L1 : forall A B : Prop, A -> ~A -> B. Proof. intros; contradiction. Qed. Lemma L2 : forall A B : Prop, ~A -> A -> B. Proof. intros; contradiction. Qed. Lemma L3 : forall A : Prop, ~True -> A. Proof. intros; contradiction. Qed. Lemma L4 : forall A : Prop, forall x : nat, ~x=x -> A. Proof. intros; contradiction. Qed. Lemma L5 : forall A : Prop, forall x y : nat, ~x=y -> x=y -> A. Proof. intros; contradiction. Qed. Lemma L6 : forall A : Prop, forall x y : nat, x=y -> ~x=y -> A. Proof. intros; contradiction. Qed. rocq-9.2.0/test-suite/success/cumulativity.v000066400000000000000000000113021516144147600212000ustar00rootroot00000000000000Polymorphic Cumulative Inductive T1 := t1 : T1. Fail Monomorphic Cumulative Inductive T2 := t2 : T2. Polymorphic Cumulative Record R1 := { r1 : T1 }. Fail Monomorphic Cumulative Inductive R2 := {r2 : T1}. Set Universe Polymorphism. Set Polymorphic Inductive Cumulativity. Set Printing Universes. Inductive List (A: Type) := nil | cons : A -> List A -> List A. Definition LiftL@{k i j|k <= i, k <= j} {A:Type@{k}} : List@{i} A -> List@{j} A := fun x => x. Lemma LiftL_Lem A (l : List A) : l = LiftL l. Proof. reflexivity. Qed. Inductive Tp := tp : Type -> Tp. Definition LiftTp@{i j|i <= j} : Tp@{i} -> Tp@{j} := fun x => x. Fail Definition LowerTp@{i j|j < i} : Tp@{i} -> Tp@{j} := fun x => x. Record Tp' := { tp' : Tp }. Definition CTp := Tp. (* here we have to reduce a constant to infer the correct subtyping. *) Record Tp''@{+u} := { tp'' : CTp@{u} }. Definition LiftTp'@{i j|i <= j} : Tp'@{i} -> Tp'@{j} := fun x => x. Definition LiftTp''@{i j|i <= j} : Tp''@{i} -> Tp''@{j} := fun x => x. Lemma LiftC_Lem (t : Tp) : LiftTp t = t. Proof. reflexivity. Qed. Section subtyping_test. Universe i j. Constraint i < j. Inductive TP2 := tp2 : Type@{i} -> Type@{j} -> TP2. End subtyping_test. Record A : Type := { a :> Type; }. Record B (X : A) : Type := { b : X; }. NonCumulative Inductive NCList (A: Type) := ncnil | nccons : A -> NCList A -> NCList A. Fail Definition LiftNCL@{k i j|k <= i, k <= j} {A:Type@{k}} : NCList@{i} A -> NCList@{j} A := fun x => x. Inductive eq@{i} {A : Type@{i}} (x : A) : A -> Type@{i} := eq_refl : eq x x. Definition funext_type@{a b e} (A : Type@{a}) (B : A -> Type@{b}) := forall f g : (forall a, B a), (forall x, eq@{e} (f x) (g x)) -> eq@{e} f g. Section down. Universes a b e e'. Constraint e' < e. Lemma funext_down {A B} : @funext_type@{a b e} A B -> @funext_type@{a b e'} A B. Proof. intros H f g Hfg. exact (H f g Hfg). Defined. End down. Record Arrow@{i j} := { arrow : Type@{i} -> Type@{j} }. Fail Definition arrow_lift@{i i' j j' | i' < i, j < j'} : Arrow@{i j} -> Arrow@{i' j'} := fun x => x. Definition arrow_lift@{i i' j j' | i' = i, j <= j'} : Arrow@{i j} -> Arrow@{i' j'} := fun x => x. Inductive Mut1 A := | Base1 : Type -> Mut1 A | Node1 : (A -> Mut2 A) -> Mut1 A with Mut2 A := | Base2 : Type -> Mut2 A | Node2 : Mut1 A -> Mut2 A. (* If we don't reduce T while inferring cumulativity for the constructor we will see a Rel and believe i is irrelevant. *) Inductive withparams@{i j} (T:=Type@{i}:Type@{j}) := mkwithparams : T -> withparams. Definition withparams_co@{i i' j|i < i', i' < j} : withparams@{i j} -> withparams@{i' j} := fun x => x. Fail Definition withparams_not_irr@{i i' j|i' < i, i' < j} : withparams@{i j} -> withparams@{i' j} := fun x => x. (** Cumulative constructors *) Record twotys@{u v w} : Type@{w} := twoconstr { fstty : Type@{u}; sndty : Type@{v} }. Monomorphic Universes i j k l. Monomorphic Constraint i < j. Monomorphic Constraint j < k. Monomorphic Constraint k < l. Parameter Tyi : Type@{i}. Definition checkcumul := eq_refl _ : @eq twotys@{k k l} (twoconstr@{i j k} Tyi Tyi) (twoconstr@{j i k} Tyi Tyi). (* They can only be compared at the highest type *) Fail Definition checkcumul' := eq_refl _ : @eq twotys@{i k l} (twoconstr@{i j k} Tyi Tyi) (twoconstr@{j i k} Tyi Tyi). (* An inductive type with an irrelevant universe *) Inductive foo@{i} : Type@{i} := mkfoo { }. Definition bar := foo. (* The universe on mkfoo is flexible and should be unified with i. *) Definition foo1@{i} : foo@{i} := let x := mkfoo in x. (* fast path for conversion *) Definition foo2@{i} : bar@{i} := let x := mkfoo in x. (* must reduce *) (* Rigid universes however should not be unified unnecessarily. *) Definition foo3@{i j|} : foo@{i} := let x := mkfoo@{j} in x. Definition foo4@{i j|} : bar@{i} := let x := mkfoo@{j} in x. (* Constructors for an inductive with indices *) Module WithIndex. Inductive foo@{i} : (Prop -> Prop) -> Prop := mkfoo: foo (fun x => x). Monomorphic Universes i j. Monomorphic Constraint i < j. Definition bar : eq mkfoo@{i} mkfoo@{j} := eq_refl _. End WithIndex. Module CumulApp. (* i is covariant here, and we have one parameter *) Inductive foo@{i} (A : nat) : Type@{i+1} := mkfoo (B : Type@{i}). Definition bar@{i j|i<=j} := fun x : foo@{i} 0 => x : foo@{j} 0. End CumulApp. Module InSection. Section S. Polymorphic Cumulative Structure T : Type := {sort : Type}. Polymorphic Universe u. Polymorphic Cumulative Structure T' : Type := {sort' : Type -> Type@{u}}. Polymorphic Cumulative Structure T'' : Type := {sort'' : Type}. End S. Check T@{Set}. Check T'@{Set Set}. (* T'' expects two universes, that is also u; do we really want it? *) Fail Check T''@{Set}. End InSection. rocq-9.2.0/test-suite/success/custom_entry.v000066400000000000000000000003541516144147600212010ustar00rootroot00000000000000Declare Custom Entry foo. Print Custom Grammar foo. Notation "[ e ]" := e (e custom foo at level 0). Print Custom Grammar foo. Notation "1" := O (in custom foo at level 0). Print Custom Grammar foo. Fail Declare Custom Entry foo. rocq-9.2.0/test-suite/success/definition_using.v000066400000000000000000000053641516144147600220110ustar00rootroot00000000000000Axiom bogus : Type. Section A. Variable x : bogus. #[using="All"] Definition c1 : bool := true. #[using="All"] Fixpoint c2 n : bool := match n with | O => true | S p => c3 p end with c3 n : bool := match n with | O => true | S p => c2 p end. #[using="All"] Definition c4 : bool. Proof. exact true. Qed. #[using="All"] Fixpoint c5 (n : nat) {struct n} : bool. Proof. destruct n as [|p]. exact true. exact (c5 p). Qed. #[using="All"] Definition c6 : bool. Proof. exact true. Qed. #[using="All"] Fixpoint c7 (n : nat) {struct n} : bool := match n with | O => true | S p => c7 p end. Fail #[using="dummy", program] Fixpoint c7' (n : nat) {struct n} : bool := match n with | O => true | S p => c7' p end. Fail #[using="c7'", program] Fixpoint c7' (n : nat) {struct n} : bool := match n with | O => true | S p => c7' p end. End A. Check c1 : bogus -> bool. Check c2 : bogus -> nat -> bool. Check c3 : bogus -> nat -> bool. Check c4 : bogus -> bool. Check c5 : bogus -> nat -> bool. Check c6 : bogus -> bool. Check c7 : bogus -> nat -> bool. Section B. Variable a : bogus. Variable h : c1 a = true. #[using="a*"] Definition c8 : bogus := a. Collection ccc := a h. #[using="ccc"] Definition c9 : bogus := a. #[using="ccc - h"] Definition c10 : bogus := a. End B. Check c8 : forall a, c1 a = true -> bogus. Check c9 : forall a, c1 a = true -> bogus. Check c10: bogus -> bogus. Module TypeBehavior. Section S. Variables a : nat. #[using="Type", warning="-non-recursive"] Program Fixpoint b1 (n:nat) : nat := (fun _ => 0) a. Program Fixpoint b2 (n:nat) : (fun X _ => X) nat a := 0. Program Fixpoint b3 (n:nat) : (fun X _ => X) nat a := (fun _ => 0) a. Program Definition c1 : nat := (fun _ => 0) a. Program Definition c2 : (fun X _ => X) nat a := 0. Program Definition c3 : (fun X _ => X) nat a := (fun _ => 0) a. Fixpoint d1 (n:nat) : nat := (fun _ => 0) a. Fixpoint d2 (n:nat) : (fun X _ => X) nat a := 0. Fixpoint d3 (n:nat) : (fun X _ => X) nat a := (fun _ => 0) a. Definition e1 : nat := (fun _ => 0) a. Definition e2 : (fun X _ => X) nat a := 0. Definition e3 : (fun X _ => X) nat a := (fun _ => 0) a. End S. (* Not clear what is most expected below... *) (* Dependency in a with Program Fixpoint: the body is not reduced. *) (* As of now, we don't seem to have such a case. *) (* No dependency in a with Program Fixpoint, because both body and type are beta-reduced *) Check b1 0 : nat. Check b2 0 : nat. Check b3 0 : nat. (* With Program Definition, type is beta-reduced but not the body *) Check c1 0 : nat. Check c2 : nat. Check c3 0 : nat. (* With Definition/Fixpoint, neither body nor type are beta-reduced *) Check d1 0 0 : nat. Check d2 0 0 : nat. Check d3 0 0 : nat. Check e1 0 : nat. Check e2 0 : nat. Check e3 0 : nat. End TypeBehavior. rocq-9.2.0/test-suite/success/destruct.v000066400000000000000000000232461516144147600203100ustar00rootroot00000000000000(* Submitted by Robert Schneck *) Parameters A B C D : Prop. Axiom X : A -> B -> C /\ D. Lemma foo : A -> B -> C. Proof. intros. destruct X. (* Should find axiom X and should handle arguments of X *) assumption. assumption. assumption. Qed. (* Simplification of BZ#711 *) Parameter f : true = false. Goal let p := f in True. intro p. set (b := true) in *. (* Check that it doesn't fail with an anomaly *) (* Ultimately, adapt destruct to make it succeeding *) try destruct b. Abort. (* Used to fail with error "n is used in conclusion" before revision 9447 *) Goal forall n, n = S n. induction S. Abort. (* Check that elimination with remaining evars do not raise an bad error message *) Theorem Refl : forall P, P <-> P. tauto. Qed. Goal True. case Refl || ecase Refl. Abort. (* Submitted by B. Baydemir (BZ#1882) *) Definition alist R := list (nat * R)%type. Section Properties. Variable A : Type. Variable a : A. Variable E : alist A. Lemma silly : E = E. Proof. clear. induction E. (* this fails. *) Abort. End Properties. (* This used not to work before revision 11944 *) Goal forall P:(forall n, 0=n -> Prop), forall H: 0=0, P 0 H. destruct H. Abort. (* The calls to "destruct" below did not work before revision 12356 *) Parameter A0:Type. Parameter P:A0->Type. Require Import TestSuite.jmeq. Goal forall a b (p:P a) (q:P b), forall H:a = b, eq_rect a P p b H = q -> JMeq (existT _ a p) (existT _ b q). intros. destruct H. destruct H0. reflexivity. Qed. (* These did not work before 8.4 *) Goal (exists x, x=0) -> True. destruct 1 as (_,_); exact I. Abort. Goal (exists x, x=0 /\ True) -> True. destruct 1 as (_,(_,H)); exact H. Abort. Goal (exists x, x=0 /\ True) -> True. destruct 1 as (_,(_,x)); exact x. Abort. Goal let T:=nat in forall (x:nat) (g:T -> nat), g x = 0. intros. destruct (g _). (* This was failing in at least r14571 *) Abort. (* Check that subterm selection does not solve existing evars *) Goal exists x, S x = S 0. eexists ?[x]. Show x. (* Incidentally test Show on a named goal *) destruct (S _). (* Incompatible occurrences but takes the first one since Oct 2014 *) change (0 = S 0). Abort. Goal exists x, S 0 = S x. eexists ?[x]. destruct (S _). (* Incompatible occurrences but takes the first one since Oct 2014 *) change (0 = S ?x). [x]: exact 0. (* Incidentally test applying a tactic to a goal on the shelve *) Abort. Goal exists n p:nat, (S n,S n) = (S p,S p) /\ p = n. eexists ?[n]; eexists ?[p]. destruct (_, S _). (* Was unifying at some time in trunk, now takes the first occurrence *) change ((n, n0) = (S ?p, S ?p) /\ ?p = ?n). Abort. (* An example with incompatible but convertible occurrences *) Goal id (id 0) = 0. Fail destruct (id _) at 1 2. Abort. (* Avoid unnatural selection of a subterm larger than expected *) Goal let g := fun x:nat => x in g (S 0) = 0. intro. destruct S. (* Check that it is not the larger subterm "g (S 0)" which is selected, as it was the case in 8.4 *) unfold g at 1. Abort. (* Some tricky examples convenient to support *) Goal forall x, nat_rect (fun _ => nat) O (fun x y => S x) x = nat_rect (fun _ => nat) O (fun x y => S x) x. intros. destruct (nat_rect _ _ _ _). Abort. (* Check compatibility in selecting what is open or "shelved" *) Goal (forall x, x=0 -> nat) -> True. intros. Fail destruct H. edestruct H. - reflexivity. - exact Logic.I. - exact Logic.I. Qed. (* Check an example which was working with case/elim in 8.4 but not with destruct/induction *) Goal forall x, (True -> x = 0) -> 0=0. intros. destruct H. - trivial. - apply (eq_refl x). Qed. (* Check an example which was working with case/elim in 8.4 but not with destruct/induction (not the different order between induction/destruct) *) Goal forall x, (True -> x = 0) -> 0=0. intros. induction H. - apply (eq_refl x). - trivial. Qed. (* This test assumes that destruct/induction on non-dependent hypotheses behave the same when using holes or not Goal forall x, (True -> x = 0) -> 0=0. intros. destruct (H _). - apply I. - apply (eq_refl x). Qed. *) (* Check destruct vs edestruct *) Goal forall x, (forall y, y = 0 -> x = 0) -> 0=0. intros. Fail destruct H. edestruct H. - trivial. - apply (eq_refl x). Qed. Goal forall x, (forall y, y = 0 -> x = 0) -> 0=0. intros. Fail destruct (H _ _). (* Now a test which assumes that edestruct on non-dependent hypotheses accept unresolved subterms in the induction argument. edestruct (H _ _). - trivial. - apply (eq_refl x). Qed. *) Abort. (* Test selection when not in an inductive type *) Parameter T:Type. Axiom elim: forall P, T -> P. Goal forall a:T, a = a. induction a using elim. Qed. Goal forall a:nat -> T, a 0 = a 1. intro a. induction (a 0) using elim. Qed. (* From Oct 2014, a subterm is found, as if without "using"; in 8.4, it did not find a subterm *) Goal forall a:nat -> T, a 0 = a 1. intro a. induction a using elim. Qed. Goal forall a:nat -> T, forall b, a 0 = b. intros a b. induction a using elim. Qed. (* From Oct 2014, first subterm is found; in 8.4, it failed because it found "a 0" and wanted to clear a *) Goal forall a:nat -> nat, a 0 = a 1. intro a. destruct a. change (0 = a 1). Abort. (* This example of a variable not fully applied in the goal was working in 8.4*) Goal forall H : 0<>0, H = H. destruct H. reflexivity. Qed. (* Check that variables not fully applied in the goal are not erased (this example was failing in 8.4 because of a forbidden "clear H" in the code of "destruct H" *) Goal forall H : True -> True, H = H. destruct H. - exact I. - reflexivity. Qed. (* Check destruct on idents with maximal implicit arguments - which did not work in 8.4 *) Parameter g : forall {n:nat}, n=n -> nat. Goal g (eq_refl 0) = 0. destruct g. Abort. (* This one was working in 8.4 (because of full conv on closed arguments) *) Class E. #[export] Instance a:E := {}. Goal forall h : E -> nat -> nat, h (id a) 0 = h a 0. intros. destruct (h _). change (0=0). Abort. (* This one was not working in 8.4 because an occurrence of f was remaining, blocking the "clear f" *) Goal forall h : E -> nat -> nat, h a 0 = h a 1. intros. destruct h. Abort. (* This was not working in 8.4 *) Section S1. Variables x y : Type. Variable H : x = y. Goal True. destruct H. (* Was not working in 8.4 *) (* Now check that H statement has itself be subject of the rewriting *) change (x=x) in H. Abort. End S1. (* This was not working in 8.4 because of untracked dependencies *) Goal forall y, forall h:forall x, x = y, h 0 = h 0. intros. destruct (h 0). Abort. (* Check absence of useless local definitions *) Section S2. Variable H : 1=1. Goal 0=1. destruct H. Fail clear n. (* Check that there is no n as it was in Coq <= 8.4 *) Abort. End S2. Goal forall x:nat, x=x->x=1. intros x H. destruct H. Fail clear n. (* Check that there is no n as it was in Coq <= 8.4 *) Fail clear H. (* Check that H has been removed *) Abort. (* Check support for induction arguments which do not expose an inductive type rightaway *) Definition U := nat -> nat. Definition S' := S : U. Goal forall n, S' n = 0. intro. destruct S'. Abort. (* This was working by chance in 8.4 thanks to "accidental" use of select subterms _syntactically_ equal to the first matching one. Parameter f2:bool -> unit. Parameter r2:f2 true=f2 true. Goal forall (P: forall b, b=b -> Prop), f2 (id true) = tt -> P (f2 true) r2. intros. destruct f2. Abort. *) (* This did not work in 8.4, because of a clear failing *) Inductive IND : forall x y:nat, x=y -> Type := CONSTR : IND 0 0 eq_refl. Goal forall x y e (h:x=y -> y=x) (z:IND y x (h e)), e = e /\ z = z. intros. destruct z. Abort. (* The two following examples show how the variables occurring in the term being destruct affects the generalization; don't know if these behaviors are "good". None of them was working in 8.4. *) Goal forall x y e (t:x=y) (z:x=y -> IND y x e), e = e. intros. destruct (z t). change (0=0) in t. (* Generalization made *) Abort. Goal forall x y e (t:x=y) (z:x=y -> IND y x e), e = e /\ z t = z t. intros. destruct (z t). change (0=0) in t. (* Generalization made *) Abort. (* Check that destruct on a scheme with a functional argument works *) Goal (forall P:Prop, (nat->nat) -> P) -> forall h:nat->nat, h 0 = h 0. intros. destruct h using H. Qed. Goal (forall P:Prop, (nat->nat) -> P) -> forall h:nat->nat->nat, h 0 0 = h 1 0. intros. induction (h 1) using H. Qed. (* Check blocking generalization is not too strong (failed at some time) *) Goal (E -> 0=1) -> 1=0 -> True. intros. destruct (H _). change (0=0) in H0. (* Check generalization on H0 was made *) Abort. (* Check absence of anomaly (failed at some time) *) Goal forall A (a:A) (P Q:A->Prop), (forall a, P a -> Q a) -> True. intros. Fail destruct H. Abort. (* Check keep option (BZ#3791) *) Goal forall b:bool, True. intro b. destruct (b). clear b. (* b has to be here *) Abort. (* Check clearing of names *) Inductive IND2 : nat -> Prop := CONSTR2 : forall y, y = y -> IND2 y. Goal forall x y z:nat, y = z -> x = y -> y = x -> x = y. intros * Heq H Heq'. destruct H. Abort. Goal 2=1 -> 1=0. intro H. destruct H. Fail (match goal with n:nat |- _ => unfold n end). (* Check that no let-in remains *) Abort. (* Check clearing of names *) Inductive eqnat (x : nat) : nat -> Prop := reflnat : forall y, x = y -> eqnat x y. Goal forall x z:nat, x = z -> eqnat x z -> True. intros * H1 H. destruct H. Fail clear z. (* Should not be here *) Abort. (* Check ok in the presence of an equation *) Goal forall b:bool, b = b. intros. destruct b eqn:H. Abort. (* Check natural instantiation behavior when the goal has already an evar *) Goal exists x, S x = x. eexists ?[x]. destruct (S _). change (0 = ?x). Abort. Goal (forall P, P 0 -> True/\True) -> True. intro H. destruct (H (fun x => True)). match goal with |- True => idtac end. Abort. rocq-9.2.0/test-suite/success/disc_uses_patterns.v000066400000000000000000000005741516144147600223530ustar00rootroot00000000000000(* discriminated uses head const and patterns *) Theorem bar: 1=1. reflexivity. Qed. Theorem bar2: 2=2. reflexivity. Qed. Create HintDb db discriminated . Hint Resolve bar : db. Hint Resolve bar2 : db. Set Typeclasses Debug Verbosity 2. Goal 3=3. (* neither theorem matches the goal *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. rocq-9.2.0/test-suite/success/disc_with_transparent.v000066400000000000000000000026071516144147600230470ustar00rootroot00000000000000(* discriminated database with transparent items in hints *) From Corelib Require Import Nat. Theorem bar: 1+1+1=3. reflexivity. Qed. Theorem bar2: 3+1+1=5. reflexivity. Qed. Definition one := 1. Definition two := 2. Definition one_plus_one_plus_one := 1+1+1. Create HintDb db discriminated. Hint Resolve bar | 2 : db. Hint Resolve bar2 | 1 : db. Hint Opaque Nat.add : db. Set Typeclasses Debug Verbosity 2. Goal two+1+1=5. (* matches bar2, which fails in the tactic*) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. Goal 1+1+1=one. (* matches bar, which fails in the tactic *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. Goal two+1+1=one. (* matches both bar and bar2, which both fail in the tactic *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. Goal 1+1+1=1+1+1. (* no match, fails *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. Goal 1+1+1=one_plus_one_plus_one. (* matches bar, succeeds because tactic uses conversion *) Succeed progress debug auto with db nocore. Succeed exact bar. Succeed simple apply bar. Fail autoapply bar with db. (* a bug or poor documentation? *) Set Typeclasses Debug Verbosity 2. (* fails because tc eauto uses autoapply, copying that Nat.add is opaque *) Fail typeclasses eauto with db nocore. Abort. rocq-9.2.0/test-suite/success/dtauto_let_deps.v000066400000000000000000000014321516144147600216230ustar00rootroot00000000000000(* This test is sensitive to changes in which let-ins are expanded when checking for dependencies in constructors. If the (x := X) is not reduced, Foo1 won't be recognized as a conjunction, and if the (y := X) is reduced, Foo2 will be recognized as a conjunction. This tests the behavior of engine/termops.ml : prod_applist_assum, which is currently specified to reduce exactly the parameters. If dtauto is changed to reduce lets in constructors before checking dependency, this test will need to be changed. *) Parameter (P Q : Type). Inductive Foo1 (X : Type) (x := X) := foo1 : let y := X in P -> Q -> Foo1 x. Inductive Foo2 (X : Type) (x := X) := foo2 : let y := X in P -> Q -> Foo2 y. Goal P -> Q -> Foo1 nat. solve [dtauto]. Qed. Goal P -> Q -> Foo2 nat. Fail solve [dtauto]. Abort. rocq-9.2.0/test-suite/success/eapply_evar.v000066400000000000000000000004341516144147600207540ustar00rootroot00000000000000(* Test propagation of evars from subgoal to brother subgoals *) (* This does not work (oct 2008) because "match goal" sees "?evar = O" and not "O = O" *) Lemma eapply_evar : O=O -> 0=O. intro H; eapply eq_trans; [apply H | match goal with |- ?x = ?x => reflexivity end]. Qed. rocq-9.2.0/test-suite/success/eauto.v000066400000000000000000000175531516144147600175740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* constructor : typeclass_instances. Existing Class and. Goal exists (T : Type) (t : T), A T /\ B T t. Proof. eexists. eexists. typeclasses eauto. Defined. #[export] Instance ab: A bool := {}. (* Backtrack on A instance *) Goal exists (T : Type) (t : T), A T /\ B T t. Proof. eexists. eexists. typeclasses eauto. Defined. Class C {T} `(a : A T) (t : T). Require Import Classes.Init. #[export] Hint Extern 0 { x : ?A & _ } => unshelve class_apply @existT : typeclass_instances. Existing Class sigT. Set Typeclasses Debug. #[export] Instance can: C an 0 := {}. (* Backtrack on instance implementation *) Goal exists (T : Type) (t : T), { x : A T & C x t }. Proof. eexists. eexists. typeclasses eauto. Defined. Class D T `(a: A T). #[export] Instance: D _ an := {}. Goal exists (T : Type), { x : A T & D T x }. Proof. eexists. typeclasses eauto. Defined. (* Example from Nicolas Magaud on coq-club - Jul 2000 *) Definition Nat : Set := nat. Parameter S' : Nat -> Nat. Parameter plus' : Nat -> Nat -> Nat. Lemma simpl_plus_l_rr1 : (forall n0 : Nat, (forall m p : Nat, plus' n0 m = plus' n0 p -> m = p) -> forall m p : Nat, S' (plus' n0 m) = S' (plus' n0 p) -> m = p) -> forall n : Nat, (forall m p : Nat, plus' n m = plus' n p -> m = p) -> forall m p : Nat, S' (plus' n m) = S' (plus' n p) -> m = p. intros. apply H0. apply f_equal_nat. Time info_eauto. Undo. Set Typeclasses Debug. Set Typeclasses Iterative Deepening. Time typeclasses eauto 6 with nocore. Show Proof. Undo. Time eauto. (* does EApply H *) Qed. (* Example from Nicolas Tabareau on coq-club - Feb 2016. Full backtracking on dependent subgoals. *) Require Import Corelib.Classes.Init. Module NTabareau. Set Typeclasses Dependency Order. Unset Typeclasses Iterative Deepening. Notation "x .1" := (projT1 x). Notation "x .2" := (projT2 x). Parameter myType: Type. Class Foo (a:myType) := {}. Class Bar (a:myType) := {}. Class Qux (a:myType) := {}. Parameter fooTobar : forall a (H : Foo a), {b: myType & Bar b}. Parameter barToqux : forall a (H : Bar a), {b: myType & Qux b}. #[export] Hint Extern 5 (Bar ?D.1) => destruct D; simpl : typeclass_instances. #[export] Hint Extern 5 (Qux ?D.1) => destruct D; simpl : typeclass_instances. #[export] Hint Extern 1 myType => unshelve refine (fooTobar _ _).1 : typeclass_instances. #[export] Hint Extern 1 myType => unshelve refine (barToqux _ _).1 : typeclass_instances. #[export] Hint Extern 0 { x : _ & _ } => simple refine (existT _ _ _) : typeclass_instances. Unset Typeclasses Debug. Definition trivial a (H : Foo a) : {b : myType & Qux b}. Proof. Time typeclasses eauto 10 with typeclass_instances. Undo. Set Typeclasses Iterative Deepening. Time typeclasses eauto with typeclass_instances. Defined. End NTabareau. Module NTabareauClasses. Set Typeclasses Dependency Order. Unset Typeclasses Iterative Deepening. Notation "x .1" := (projT1 x). Notation "x .2" := (projT2 x). Parameter myType: Type. Existing Class myType. Class Foo (a:myType) := {}. Class Bar (a:myType) := {}. Class Qux (a:myType) := {}. Parameter fooTobar : forall a (H : Foo a), {b: myType & Bar b}. Parameter barToqux : forall a (H : Bar a), {b: myType & Qux b}. #[export] Hint Extern 5 (Bar ?D.1) => destruct D; simpl : typeclass_instances. #[export] Hint Extern 5 (Qux ?D.1) => destruct D; simpl : typeclass_instances. #[export] Hint Extern 1 myType => unshelve notypeclasses refine (fooTobar _ _).1 : typeclass_instances. #[export] Hint Extern 1 myType => unshelve notypeclasses refine (barToqux _ _).1 : typeclass_instances. #[export] Hint Extern 0 { x : _ & _ } => unshelve notypeclasses refine (existT _ _ _) : typeclass_instances. Unset Typeclasses Debug. Definition trivial a (H : Foo a) : {b : myType & Qux b}. Proof. Time typeclasses eauto 10 with typeclass_instances. Undo. Set Typeclasses Iterative Deepening. (* Much faster in iteratove deepening mode *) Time typeclasses eauto with typeclass_instances. Defined. End NTabareauClasses. Require Import ListDef. Parameter in_list : list (nat * nat) -> nat -> Prop. Definition not_in_list (l : list (nat * nat)) (n : nat) : Prop := ~ in_list l n. (* Hints Unfold not_in_list. *) Axiom lem1 : forall (l1 l2 : list (nat * nat)) (n : nat), not_in_list (l1 ++ l2) n -> not_in_list l1 n. Axiom lem2 : forall (l1 l2 : list (nat * nat)) (n : nat), not_in_list (l1 ++ l2) n -> not_in_list l2 n. Axiom lem3 : forall (l : list (nat * nat)) (n p q : nat), not_in_list ((p, q) :: l) n -> not_in_list l n. Axiom lem4 : forall (l1 l2 : list (nat * nat)) (n : nat), not_in_list l1 n -> not_in_list l2 n -> not_in_list (l1 ++ l2) n. #[export] Hint Resolve lem1 lem2 lem3 lem4: essai. Goal forall (l : list (nat * nat)) (n p q : nat), not_in_list ((p, q) :: l) n -> not_in_list l n. intros. eauto with essai. Qed. Module StrictlyUnique. Inductive thing := | List. Module Problem. Class WhatIsThis (T : Type) (t : T) : Type := what_is : thing. Arguments what_is {T} t _. Instance WhatIsThis_list {X} ls : @WhatIsThis (list X) ls := List. Class DynamicType := { dyn_type : Type }. (* [WhatIsThis ls] cannot be resolved despite having a clear answer. The fact that the [DynamicType] instance cannot be found makes Coq abandon the search for [WhatIsThis] entirely. *) Fail Example test := Eval lazy in (fun (ls : list dyn_type) => what_is ls _) _. End Problem. Module Solution. (* Inform Coq that [WhatIsThis] will not/must not instantiate evars. *) #[local] Set Typeclasses Strict Resolution. (* Inform Coq that [WhatIsThis] should not backtrack. *) #[local] Set Typeclasses Unique Instances. Class WhatIsThis (T : Type) (t : T) : Type := what_is : thing. Arguments what_is {T} t _. #[local] Unset Typeclasses Strict Resolution. #[local] Unset Typeclasses Unique Instances. Instance WhatIsThis_list {X} ls : @WhatIsThis (list X) ls := List. Class DynamicType := { dyn_type : Type }. (* We can now resolve [WhatIsThis] even though we don't have a [DynamicType] *) Example test := Eval lazy in (fun (ls : list dyn_type) => what_is ls _) _. End Solution. Module Dependencies. (* Other evars can still depend on strictly unique evars by using them directly in their type. We must make sure to not forget those dependencies. *) #[local] Set Typeclasses Strict Resolution. #[local] Set Typeclasses Unique Instances. Class SU : Type := su : unit. Arguments su : clear implicits. #[local] Unset Typeclasses Strict Resolution. #[local] Unset Typeclasses Unique Instances. Instance SU_inst : SU := tt. Class Depends (t : unit) := {}. Hint Mode Depends + : typeclass_instances. Instance Depends_inst {t} : Depends t := {}. Example test := Eval lazy in (fun (s : SU) (d : Depends (su s)) => d) _ _. End Dependencies. End StrictlyUnique. rocq-9.2.0/test-suite/success/eqdecide.v000066400000000000000000000022441516144147600202110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* T. Lemma lem1 : forall x y : T, {x = y} + {x <> y}. decide equality. Qed. Lemma lem1' : forall x y : T, x = y \/ x <> y. decide equality. Qed. Lemma lem1'' : forall x y : T, {x <> y} + {x = y}. decide equality. Qed. Lemma lem1''' : forall x y : T, x <> y \/ x = y. decide equality. Qed. Lemma lem2 : forall x y : T, {x = y} + {x <> y}. intros x y. decide equality. Qed. Lemma lem4 : forall x y : T, {x = y} + {x <> y}. intros x y. compare x y; auto. Qed. rocq-9.2.0/test-suite/success/eqtacticsnois.v000066400000000000000000000005751516144147600213240ustar00rootroot00000000000000(* coq-prog-args: ("-nois") *) Inductive eq {A : Type} (x : A) : forall a:A, Prop := eq_refl : eq x x. Axiom sym : forall A (x y : A) (_ : eq x y), eq y x. Require Import Ltac. Register eq as core.eq.type. Register sym as core.eq.sym. Scheme Rewriting for eq. Goal forall A (x y:A) (_ : forall z, eq y z), eq x x. intros * H. replace x with y. - reflexivity. - apply H. Qed. rocq-9.2.0/test-suite/success/eta.v000066400000000000000000000011231516144147600172120ustar00rootroot00000000000000(* Kernel test (head term is a constant) *) Check (fun a : S = S => a : S = fun x => S x). (* Kernel test (head term is a variable) *) Check (fun (f:nat->nat) (a : f = f) => a : f = fun x => f x). (* Test type inference (head term is syntactically rigid) *) Check (fun (a : list = list) => a : list = fun A => _ A). (* Test type inference (head term is a variable) *) (* This one is still to be done... Check (fun (f:nat->nat) (a : f = f) => a : f = fun x => _ x). *) (* Test tactic unification *) Goal (forall f:nat->nat, (fun x => f x) = (fun x => f x)) -> S = S. intro H; apply H. Qed. rocq-9.2.0/test-suite/success/evars.v000066400000000000000000000332631516144147600175730ustar00rootroot00000000000000Module ListTest. (* The "?" of cons and eq should be inferred *) Parameter list : Set -> Set. Parameter cons : forall T : Set, T -> list T -> list T. Check (forall n : list nat, exists l : _, (exists x : _, n = cons _ x l)). End ListTest. (* Examples provided by Eduardo Gimenez *) Definition c A (Q : (nat * A -> Prop) -> Prop) P := Q (fun p : nat * A => let (i, v) := p in P i v). (* What does this test ? *) Require Import TestSuite.list. Definition list_forall_bool (A : Set) (p : A -> bool) (l : list A) : bool := fold_right (fun a r => if p a then r else false) true l. (* Checks that solvable ? in the lambda prefix of the definition are harmless*) Parameter A1 A2 F B C : Set. Parameter f : F -> A1 -> B. Definition f1 frm0 a1 : B := f frm0 a1. (* Checks that solvable ? in the type part of the definition are harmless *) Definition f2 frm0 a1 : B := f frm0 a1. (* Checks that sorts that are evars are handled correctly (BZ#705) *) Fixpoint build (nl : list nat) : match nl with | nil => True | _ => False end -> unit := match nl return (match nl with | nil => True | _ => False end -> unit) with | nil => fun _ => tt | cons n rest => match n with | O => fun _ => tt | S m => fun a => build rest (False_ind _ a) end end. (* Checks that disjoint contexts are correctly set by restrict_hyp *) (* Bug de 1999 corrigΓ© en dΓ©c 2004 *) Check (let p := fun (m : nat) f (n : nat) => match f m n with | exist _ a b => exist _ a b end in p :forall x : nat, (forall y n : nat, {q : nat | y = q * n}) -> forall n : nat, {q : nat | x = q * n}). (* Check instantiation of nested evars (BZ#1089) *) Check (fun f:(forall (v:Type->Type), v (v nat) -> nat) => f _ (Some (Some O))). (* This used to fail with anomaly (Pp.str "evar was not declared.") in V8.0pl3 *) Theorem contradiction : forall p, ~ p -> p -> False. Proof. trivial. Qed. #[export] Hint Resolve contradiction. Goal False. eauto. Abort. (* This used to fail in V8.1beta because first-order unification was used before using type information *) Check (exist _ O (refl_equal 0) : {n:nat|n=0}). Check (exist _ O I : {n:nat|True}). (* An example (initially from Marseille/Fairisle) that involves an evar with different solutions (Input, Output or bool) that may or may not be considered distinct depending on which kind of conversion is used *) Section A. Definition STATE := (nat * bool)%type. Let Input := bool. Let Output := bool. Parameter Out : STATE -> Output. Check fun (s : STATE) (reg : Input) => reg = Out s. End A. (* The return predicate found should be: "in _=U return U" *) (* (feature already available in V8.0) *) Definition g (T1 T2:Type) (x:T1) (e:T1=T2) : T2 := match e with | refl_equal => x end. (* An example extracted from FMapAVL which (may) test restriction on evars problems of the form ?n[args1]=?n[args2] with distinct args1 and args2 *) Set Implicit Arguments. Parameter t:Set->Set. Parameter map:forall elt elt' : Set, (elt -> elt') -> t elt -> t elt'. Parameter avl: forall elt : Set, t elt -> Prop. Parameter bst: forall elt : Set, t elt -> Prop. Parameter map_avl: forall (elt elt' : Set) (f : elt -> elt') (m : t elt), avl m -> avl (map f m). Parameter map_bst: forall (elt elt' : Set) (f : elt -> elt') (m : t elt), bst m -> bst (map f m). Record bbst (elt:Set) : Set := Bbst {this :> t elt; is_bst : bst this; is_avl: avl this}. Definition t' := bbst. Section B. Variables elt elt': Set. Definition map' f (m:t' elt) : t' elt' := Bbst (map_bst f m.(is_bst)) (map_avl f m.(is_avl)). End B. Unset Implicit Arguments. (* An example from Lexicographic_Exponentiation that tests the contraction of reducible fixpoints in type inference *) Check (fun (A:Set) (a b x:A) (l:list A) (H : app l (cons x nil) = cons b (cons a nil)) => app_inj_tail l (cons b nil) _ _ H). (* An example from NMake (simplified), that uses restriction in solve_refl *) Parameter h:(nat->nat)->(nat->nat). Fixpoint G p cont {struct p} := h (fun n => match p with O => cont | S p => G p cont end n). (* An example from Bordeaux/Cantor that applies evar restriction below a binder *) Require Import TestSuite.relationclasses. Parameter lex : forall (A B : Set), (forall (a1 a2:A), {a1=a2}+{a1<>a2}) -> relation A -> relation B -> A * B -> A * B -> Prop. Check forall (A B : Set) eq_A_dec o1 o2, antisymmetric A o1 -> transitive A o1 -> transitive B o2 -> transitive _ (lex _ _ eq_A_dec o1 o2). (* Another example from Julien Forest that tests unification below binders *) Set Implicit Arguments. Parameter merge : forall (A B : Set) (eqA : forall (a1 a2 : A), {a1=a2}+{a1<>a2}) (eqB : forall (b1 b2 : B), {b1=b2}+{b1<>b2}) (partial_res l : list (A*B)), option (list (A*B)). Axiom merge_correct : forall (A B : Set) eqA eqB (l1 l2 : list (A*B)), (forall a2 b2 c2, In (a2,b2) l2 -> In (a2,c2) l2 -> b2 = c2) -> match merge eqA eqB l1 l2 with _ => True end. Unset Implicit Arguments. (* An example from Bordeaux/Additions that tests restriction below binders *) Section Additions_while. Variable A : Set. Variables P Q : A -> Prop. Variable le : A -> A -> Prop. Hypothesis Q_dec : forall s : A, P s -> {Q s} + {~ Q s}. Hypothesis le_step : forall s : A, ~ Q s -> P s -> {s' | P s' /\ le s' s}. Hypothesis le_wf : well_founded le. Lemma loopexec : forall s : A, P s -> {s' : A | P s' /\ Q s'}. refine (well_founded_induction_type le_wf (fun s => _ -> {s' : A | _ /\ _}) (fun s hr i => match Q_dec s i with | left _ => _ | right _ => match le_step s _ _ with | exist _ s' h' => match hr s' _ _ with | exist _ s'' _ => exist _ s'' _ end end end)). Abort. End Additions_while. (* Two examples from G. Melquiond (BZ#1878 and BZ#1884) *) Parameter F1 G1 : nat -> Prop. Goal forall x : nat, F1 x -> G1 x. refine (fun x H => proj2 (_ x H)). Abort. Goal forall x : nat, F1 x -> G1 x. refine (fun x H => proj2 (_ x H) _). Abort. (* An example from y-not that was failing in 8.2rc1 *) Fixpoint filter (A:nat->Set) (l:list (sigT A)) : list (sigT A) := match l with | nil => nil | cons (existT _ k v) l' => (existT _ k v):: (filter A l') end. (* BZ#2000: used to raise Out of memory in 8.2 while it should fail by lack of information on the conclusion of the type of j *) Goal True. set (p:=fun j => j (or_intror _ (fun a:True => j (or_introl _ a)))) || idtac. Abort. (* Remark: the following example stopped succeeding at some time in the development of 8.2 but it works again (this was because 8.2 algorithm was more general and did not exclude a solution that it should have excluded for typing reason; handling of types and backtracking is still to be done) *) Section S. Variables A B : nat -> Prop. Goal forall x : nat, A x -> B x. refine (fun x H => proj2 (_ x H) _). Abort. End S. (* Check that constraints are taken into account by tactics that instantiate *) Lemma inj : forall n m, S n = S m -> n = m. intros n m H. eapply f_equal with (* should fail because ill-typed *) (f := fun n => match n return match n with S _ => nat | _ => unit end with | S n => n | _ => tt end) in H || injection H. Abort. (* A legitimate simple eapply that was failing in coq <= 8.3. Cf. in Unification.w_merge the addition of an extra pose_all_metas_as_evars on 30/9/2010 *) Lemma simple_eapply_was_failing : (forall f:nat->nat, exists g, f = g) -> True. Proof. assert (modusponens : forall P Q, P -> (P->Q) -> Q) by auto. intros. eapply modusponens. simple eapply H. (* error message with V8.3 : Impossible to unify "?18" with "fun g : nat -> nat => ?6 = g". *) Abort. (* Regression test *) Definition fo : option nat -> nat := option_rec _ (fun a => 0) 0. (* This example revealed an incorrect evar restriction at some time around October 2011 *) Goal forall (A:Type) (a:A) (P:forall A, A -> Prop), (P A a) /\ (P A a). intros. refine ((fun H => conj (proj1 H) (proj2 H)) _). Abort. (* The argument of e below failed to be inferred from r14219 (Oct 2011) to *) (* r14753 after the restrictions made on detecting Miller's pattern in the *) (* presence of alias, only the second-order unification procedure was *) (* able to solve this problem but it was deactivated for 8.4 in r14219 *) Definition k0 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, n = a) o := match o with (* note: match introduces an alias! *) | Some a => e _ (j a) | None => O end. Definition k1 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, n = a) a (b:=a) := e _ (j a). Definition k2 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, n = a) a (b:=a) := e _ (j b). (* Other examples about aliases involved in pattern unification *) Definition k3 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, let a' := a in n = a') a (b:=a) := e _ (j b). Definition k4 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, let a' := S a in n = a') a (b:=a) := e _ (j b). Definition k5 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, let a' := S a in exists n : nat, n = a') a (b:=a) := e _ (j b). Definition k6 (e:forall P : nat -> Prop, (exists n : nat, P n) -> nat) (j : forall a, exists n : nat, let n' := S n in n' = a) a (b:=a) := e _ (j b). Definition k7 (e:forall P : nat -> Prop, (exists n : nat, let n' := n in P n') -> nat) (j : forall a, exists n : nat, n = a) a (b:=a) := e _ (j b). (* An example that uses materialize_evar under binders *) (* Extracted from bigop.v in the mathematical components library *) Section Bigop. Variable bigop : forall R I: Type, R -> (R -> R -> R) -> list I -> (I->Prop) -> (I -> R) -> R. Hypothesis eq_bigr : forall (R : Type) (idx : R) (op : R -> R -> R) (I : Type) (r : list I) (P : I -> Prop) (F1 F2 : I -> R), (forall i : I, P i -> F1 i = F2 i) -> bigop R I idx op r (fun i : I => P i) (fun i : I => F1 i) = idx. Hypothesis big_tnth : forall (R : Type) (idx : R) (op : R -> R -> R) (I : Type) (r : list I) (P : I -> Prop) (F : I -> R), bigop R I idx op r (fun i : I => P i) (fun i : I => F i) = idx. Hypothesis big_tnth_with_letin : forall (R : Type) (idx : R) (op : R -> R -> R) (I : Type) (r : list I) (P : I -> Prop) (F : I -> R), bigop R I idx op r (fun i : I => let i:=i in P i) (fun i : I => F i) = idx. Variable R : Type. Variable idx : R. Variable op : R -> R -> R. Variable I : Type. Variable J : Type. Variable rI : list I. Variable rJ : list J. Variable xQ : J -> Prop. Variable P : I -> Prop. Variable Q : I -> J -> Prop. Variable F : I -> J -> R. (* Check unification under binders *) Check (eq_bigr _ _ _ _ _ _ _ _ (fun _ _ => big_tnth _ _ _ _ rI _ _)) : (bigop R J idx op rJ (fun j : J => let k:=j in xQ k) (fun j : J => let k:=j in bigop R I idx op rI (fun i : I => P i /\ Q i k) (fun i : I => let k:=j in F i k))) = idx. (* Check also with let-in *) Check (eq_bigr _ _ _ _ _ _ _ _ (fun _ _ => big_tnth_with_letin _ _ _ _ rI _ _)) : (bigop R J idx op rJ (fun j : J => let k:=j in xQ k) (fun j : J => let k:=j in bigop R I idx op rI (fun i : I => P i /\ Q i k) (fun i : I => let k:=j in F i k))) = idx. End Bigop. (* Check the use of (at least) an heuristic to solve problems of the form "?x[t] = ?y" where ?y occurs in t without easily knowing if ?y can eventually be erased in t *) Section evar_evar_occur. Variable id : nat -> nat. Variable f : forall x, id x = 0 -> id x = 0 -> x = 1 /\ x = 2. Variable g : forall y, id y = 0 /\ id y = 0. (* Still evars in the resulting type, but constraints should be solved *) Check match g _ with conj a b => f _ a b end. End evar_evar_occur. (* Eta expansion (BZ#2936) *) Record iffT (X Y:Type) : Type := mkIff { iffLR : X->Y; iffRL : Y->X }. Record tri (R:Type->Type->Type) (S:Type->Type->Type) (T:Type->Type->Type) := mkTri { tri0 : forall a b c, R a b -> S a c -> T b c }. Arguments mkTri [R S T]. Definition tri_iffT : tri iffT iffT iffT := (mkTri (fun X0 X1 X2 E01 E02 => (mkIff _ _ (fun x1 => iffLR _ _ E02 (iffRL _ _ E01 x1)) (fun x2 => iffLR _ _ E01 (iffRL _ _ E02 x2))))). (* Check that local defs names are preserved if possible during unification *) Goal forall x (x':=x) (f:forall y, y=y:>nat -> Prop), f _ (eq_refl x'). intros. unfold x' at 2. (* A way to check that there are indeed 2 occurrences of x' *) Abort. (* A simple example we would like not to fail (it used to fail because of not strict enough evar restriction) *) Check match Some _ with None => _ | _ => _ end. (* Used to fail for a couple of days in Nov 2014 *) Axiom test : forall P1 P2, P1 = P2 -> P1 -> P2. (* Check use of candidates *) Import EqNotations. Definition test2 {A B:Type} {H:A=B} (a:A) : B := rew H in a. (* Check that pre-existing evars are not counted as newly undefined in "set" *) (* Reported by ThΓ©o *) Goal exists n : nat, n = n -> True. eexists. set (H := _ = _). Abort. (* Check interpretation of default evar instance in pretyping *) (* (reported as bug #7356) *) Check fun (P : nat -> Prop) (x:nat) (h:P x) => exist _ ?[z] (h : P ?z). (* A printing check in passing *) Axiom abs : forall T, T. Fail Type let x := _ in ltac:( let t := type of x in unify x (abs t); exact 0). (* Check that evars are instantiated with least unfolded terms *) Module TestFold. Structure S := {T : Type}. Definition nat' : Type := nat. Canonical nat'_S := {| T := nat' |}. Check (eq_refl : (fun x => (id x, x)) _ = (nat', T _)). End TestFold. rocq-9.2.0/test-suite/success/export_hint.v000066400000000000000000000003131516144147600210040ustar00rootroot00000000000000Create HintDb foo. Module Foo. Axiom F : False. #[export] Hint Immediate F : foo. End Foo. Goal False. Proof. Fail solve [auto with foo]. Abort. Import Foo. Goal False. Proof. auto with foo. Qed. rocq-9.2.0/test-suite/success/export_inst.v000066400000000000000000000010421516144147600210170ustar00rootroot00000000000000Class Foo. Module Foo. #[export] Instance F : Foo := {}. End Foo. Fail Definition foo_test := let _ : Foo := _ in tt. Import Foo. Definition foo_test := let _ : Foo := _ in tt. Class Bar. Module Bar. Section Bar. Variable b : Bar. #[export] Instance B : Bar := {}. (* Cannot declare variables as export instances *) Fail #[export] Existing Instance b. End Bar. Definition bar_test := let _ : Bar := _ in tt. End Bar. Fail Definition bar_test := let _ : Bar := _ in tt. Import Bar. Definition bar_test := let _ : Bar := _ in tt. rocq-9.2.0/test-suite/success/extern_no_pattern.v000066400000000000000000000006261516144147600222060ustar00rootroot00000000000000(* Hint Extern with no pattern always selected *) Theorem bar: 3=3. reflexivity. Qed. Create HintDb db discriminated. Hint Extern 1 => idtac "1"; fail : db. Hint Extern 1 => idtac "2"; fail : db. Hint Extern 2 => apply bar : db. Set Typeclasses Debug Verbosity 2. Goal 3=3. (* all 3 Hint Extern are tried *) Succeed progress debug auto with db nocore. Succeed typeclasses eauto with db nocore. Abort. rocq-9.2.0/test-suite/success/extra_dep.v000066400000000000000000000003361516144147600204210ustar00rootroot00000000000000From TestSuite Extra Dependency "extra_dep.txt". From TestSuite Extra Dependency "extra_dep.txt" as d1. Fail From TestSuite Extra Dependency "extra_dep.txt" as d1. From TestSuite Extra Dependency "extra_dep.txt" as d2. rocq-9.2.0/test-suite/success/extra_dep2.v000066400000000000000000000002321516144147600204760ustar00rootroot00000000000000(* coq-prog-args: ("-Q" "prerequisite/subdir" "TestSuite") *) Set Warnings "+ambiguous-extra-dep". Fail From TestSuite Extra Dependency "extra_dep.txt". rocq-9.2.0/test-suite/success/extraction_dep.v000066400000000000000000000017421516144147600214600ustar00rootroot00000000000000 (** Examples of code elimination inside modules during extraction *) Require Corelib.extraction.Extraction. (** NB: we should someday check the produced code instead of extracting and just compiling. *) (** 1) Without signature ... *) Module A. Definition u := 0. Definition v := 1. Module B. Definition w := 2. Definition x := 3. End B. End A. Definition testA := A.u + A.B.x. Recursive Extraction testA. (* without: v w *) Extraction TestCompile testA. (** 1b) Same with an Include *) Module Abis. Include A. Definition y := 4. End Abis. Definition testAbis := Abis.u + Abis.y. Recursive Extraction testAbis. (* without: A B v w x *) Extraction TestCompile testAbis. (** 2) With signature, we only keep elements mentioned in signature. *) Module Type SIG. Parameter u : nat. Parameter v : nat. End SIG. Module Ater : SIG. Include A. End Ater. Definition testAter := Ater.u. Recursive Extraction testAter. (* with only: u v *) Extraction TestCompile testAter. rocq-9.2.0/test-suite/success/extraction_impl.v000066400000000000000000000036061516144147600216520ustar00rootroot00000000000000 (** Examples of extraction with manually-declared implicit arguments *) (** NB: we should someday check the produced code instead of extracting and just compiling. *) Require Corelib.extraction.Extraction. (** Bug #4243, part 1 *) Inductive dnat : nat -> Type := | d0 : dnat 0 | ds : forall n m, n = m -> dnat n -> dnat (S n). Extraction Implicit ds [m]. Lemma dnat_nat: forall n, dnat n -> nat. Proof. intros n d. induction d as [| n m Heq d IHn]. exact 0. exact (S IHn). Defined. Recursive Extraction dnat_nat. Extraction TestCompile dnat_nat. Extraction Implicit dnat_nat [n]. Recursive Extraction dnat_nat. Extraction TestCompile dnat_nat. (** Same, with a Fixpoint *) Fixpoint dnat_nat' n (d:dnat n) := match d with | d0 => 0 | ds n m _ d => S (dnat_nat' n d) end. Recursive Extraction dnat_nat'. Extraction TestCompile dnat_nat'. Extraction Implicit dnat_nat' [n]. Recursive Extraction dnat_nat'. Extraction TestCompile dnat_nat'. (** Bug #4243, part 2 *) Inductive enat: nat -> Type := e0: enat 0 | es: forall n, enat n -> enat (S n). Lemma enat_nat: forall n, enat n -> nat. Proof. intros n e. induction e as [| n e IHe]. exact (O). exact (S IHe). Defined. Extraction Implicit es [n]. Extraction Implicit enat_nat [n]. Recursive Extraction enat_nat. Extraction TestCompile enat_nat. (** Same, with a Fixpoint *) Fixpoint enat_nat' n (e:enat n) : nat := match e with | e0 => 0 | es n e => S (enat_nat' n e) end. Extraction Implicit enat_nat' [n]. Recursive Extraction enat_nat'. Extraction TestCompile enat_nat'. (** Bug #4228 *) Module Food. Inductive Course := | main: nat -> Course | dessert: nat -> Course. Inductive Meal : Course -> Type := | one_course : forall n:nat, Meal (main n) | two_course : forall n m, Meal (main n) -> Meal (dessert m). Extraction Implicit two_course [n]. End Food. Recursive Extraction Food.Meal. Extraction TestCompile Food.Meal. rocq-9.2.0/test-suite/success/extraction_polyprop.v000066400000000000000000000005771516144147600226010ustar00rootroot00000000000000(* The current extraction cannot handle this situation, and shouldn't try, otherwise it might produce some Ocaml code that segfaults. See Table.error_singleton_become_prop or S. Glondu's thesis for more details. *) Require Extraction. Definition f {X} (p : (nat -> X) * True) : X * nat := (fst p 0, 0). Definition f_prop := f ((fun _ => I),I). Fail Extraction f_prop. rocq-9.2.0/test-suite/success/forward.v000066400000000000000000000013161516144147600201110ustar00rootroot00000000000000(* Testing forward reasoning *) Goal 0=0. Fail assert (_ = _). eassert (_ = _)by reflexivity. eassumption. Qed. Goal 0=0. Fail set (S ?[nl]). eset (S ?[n]). remember (S ?n) as x. instantiate (n:=0). Fail remember (S (S _)). eremember (S (S ?[x])). instantiate (x:=0). reflexivity. Qed. (* Don't know if it is good or not but the compatibility tells that the asserted goal to prove is subject to beta-iota but not the asserted hypothesis *) Goal True. assert ((fun x => x) False). Fail match goal with |- (?f ?a) => idtac end. (* should be beta-iota reduced *) 2:match goal with _: (?f ?a) |- _ => idtac end. (* should not be beta-iota reduced *) Abort. Goal nat. assert nat as J%S by exact 0. exact J. Qed. rocq-9.2.0/test-suite/success/freshness.v000066400000000000000000000003131516144147600204410ustar00rootroot00000000000000Definition bar := 0. Section S. Let bar := bar. Definition foo := 0. Let foo := foo. End S. Section S'. Let bar : nat. exact 0. Defined. Definition foo' := 0. Let foo' : nat. exact 0. Defined. End S'. rocq-9.2.0/test-suite/success/global_inst.v000066400000000000000000000006621516144147600207450ustar00rootroot00000000000000 Class Foo := foo : nat. Module X. Module Y. Global Instance n_0 : Foo := 0. End Y. End X. Definition inferred_0 : nat := foo. Check eq_refl : inferred_0 = 0. Instance n_1 : Foo := 1. Definition inferred_1 : nat := foo. Check eq_refl : inferred_1 = 1. Import X. Definition inferred_1' : nat := foo. Check eq_refl : inferred_1' = 1. Import Y. Definition inferred_1'' : nat := foo. Check eq_refl : inferred_1'' = 1. rocq-9.2.0/test-suite/success/goal_selector.v000066400000000000000000000037721516144147600212770ustar00rootroot00000000000000Inductive two : bool -> Prop := | Zero : two false | One : two true. Ltac dup := let H := fresh in assert (forall (P : Prop), P -> P -> P) as H by (intros; trivial); apply H; clear H. Lemma transform : two false <-> two true. Proof. split; intros _; constructor. Qed. Goal two false /\ two true /\ two false /\ two true /\ two true /\ two true. Proof. do 2 dup. - repeat split. Fail 7:idtac. Fail 2-1:idtac. 1,2,4-6:idtac. 2-5:exact One. par:exact Zero. - repeat split. 3-6:swap 1 4. 1-5:swap 1 5. 1-4:exact One. all:exact Zero. - repeat split. 1, 3:exact Zero. 1, 2, 3, 4: exact One. - repeat split. all:apply transform. 2, 4, 6:apply transform. all:apply transform. 1-5:apply transform. 1-6:exact One. Qed. Goal True -> True. Proof. intros y. 1-1:match goal with y : _ |- _ => let x := y in idtac x end. Fail 1-1:let x := y in idtac x. 1:let x := y in idtac x. exact I. Qed. Goal True /\ (True /\ True). Proof. dup. - split; only 2: (split; exact I). exact I. - split; only 2: split; exact I. Qed. Goal True -> exists (x : Prop), x. Proof. intro H; eexists ?[x]; only [x]: exact True. 1: assumption. Qed. Goal Prop. refine ?[x]. [x]: refine _. exact True. Qed. Goal True /\ True /\ True. Proof. split. 2: split. 1: refine ?[A]. 2: refine ?[B]. 3: refine ?[C]. (* Success because all A, B, and C are on the shelf. *) [A], [B], [C]: shelve. Succeed [A], [B], [C]: exact I. (* Fails because C is shelved, but A and B are not. *) Unshelve. [C]: shelve. Fail [A], [C]: exact I. Fail [B], [C]: exact I. Fail 1, [C]: exact I. Fail 1-2, [C]: exact I. Fail [C], 2: exact I. Fail [C], 1-2: exact I. (* Success because A, B and C are unshelved. *) Unshelve. [A], [B], [C]: exact I. Qed. (* Strict focusing! *) Set Default Goal Selector "!". Goal True -> True /\ True /\ True. Proof. intro. split;only 2:split. Fail exact I. Fail !:exact I. 1:exact I. - !:exact H. - exact I. Qed. rocq-9.2.0/test-suite/success/guard.v000066400000000000000000000014741516144147600175540ustar00rootroot00000000000000(* Specific tests about guard condition *) (* f must unfold to x, not F (de Bruijn mix-up!) *) Check let x (f:nat->nat) k := f k in fun (y z:nat->nat) => let f:=x in (* f := Rel 3 *) fix F (n:nat) : nat := match n with | 0 => 0 | S k => f F k (* here Rel 3 = F ! *) end. (** Commutation of guard condition allows recursive calls on functional arguments, despite rewriting in their domain types. *) Inductive foo : Type -> Type := | End A : foo A | Next A : (A -> foo A) -> foo A. Definition nat : Type := nat. Fixpoint bar (A : Type) (e : nat = A) (f : foo A) {struct f} : nat := match f with | End _ => fun _ => O | Next A g => fun e => match e in (_ = B) return (B -> foo A) -> nat with | eq_refl => fun (g' : nat -> foo A) => bar A e (g' O) end g end e. rocq-9.2.0/test-suite/success/hint_discr_unfold.v000066400000000000000000000011741516144147600221440ustar00rootroot00000000000000Create HintDb foo discriminated. Definition myid (A : Prop) := A. Section Test1. #[local] Hint Constructors True : foo. Lemma test1 : myid True. Proof. Fail typeclasses eauto with foo. Abort. End Test1. Section Test2. Definition hide (A : Prop) := A. #[local] Hint Extern 1 => match goal with [ |- hide True ] => constructor end : foo. #[local] Hint Unfold myid : foo. Lemma test2 : hide (myid True). Proof. Fail typeclasses eauto with foo. Abort. End Test2. Section Test3. #[local] Hint Constructors True : foo. #[local] Hint Unfold myid : foo. Lemma test3 : myid True. Proof. typeclasses eauto with foo. Qed. End Test3. rocq-9.2.0/test-suite/success/hint_extern_syntactic_unify.v000066400000000000000000000005521516144147600242700ustar00rootroot00000000000000(* Hint Extern uses syntactic unification *) Definition one := 1. Theorem bar: 1=one. reflexivity. Qed. Create HintDb db discriminated. Hint Extern 1 (1=one) => apply bar : db. Set Typeclasses Debug Verbosity 2. Goal one=1. (* fail as expected; "one" is not expanded *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. rocq-9.2.0/test-suite/success/hintdb_in_ltac.v000066400000000000000000000004351516144147600214070ustar00rootroot00000000000000Definition x := 0. #[export] Hint Unfold x : mybase. Ltac autounfoldify base := autounfold with base. Tactic Notation "autounfoldify_bis" ident(base) := autounfold with base. Goal x = 0. progress autounfoldify mybase. Undo. progress autounfoldify_bis mybase. trivial. Qed. rocq-9.2.0/test-suite/success/hintdb_in_ltac_bis.v000066400000000000000000000003671516144147600222500ustar00rootroot00000000000000Parameter Foo : Prop. Axiom H : Foo. #[export] Hint Resolve H : mybase. Ltac foo base := eauto with base. Tactic Notation "bar" ident(base) := typeclasses eauto with base. Goal Foo. progress foo mybase. Undo. progress bar mybase. Qed. rocq-9.2.0/test-suite/success/hyps_inclusion.v000066400000000000000000000022101516144147600215050ustar00rootroot00000000000000(* Simplified example for bug #1325 *) (* Explanation: the proof engine see section variables as goal variables; especially, it can change their types so that, at type-checking, the section variables are not recognized (Typeops.check_hyps_inclusion raises "types do no match"). It worked before the introduction of polymorphic inductive types because tactics were using Typing.type_of and not Typeops.typing; the former was not checking hyps inclusion so that the discrepancy in the types of section variables seen as goal variables was not a problem (at the end, when the proof is completed, the section variable recovers its original type and all is correct for Typeops) *) Section A. Variable H:not True. Lemma f:nat->nat. destruct H. exact I. Defined. Goal f 0=f 1. red in H. (* next tactic was failing wrt bug #1325 because type-checking the goal detected a syntactically different type for the section variable H *) case 0. Abort. End A. (* Variant with polymorphic inductive types for bug #1325 *) Section B. Variable H:not True. Inductive I (n:nat) : Type := C : H=H -> I n. Goal I 0. red in H. case 0. Abort. End B. rocq-9.2.0/test-suite/success/if.v000066400000000000000000000005561516144147600170500ustar00rootroot00000000000000(* The synthesis of the elimination predicate may fail if algebraic *) (* universes are not cautiously treated *) Check (fun b : bool => if b then Type else nat). (* Check correct use of if-then-else predicate annotation (cf BZ#690) *) Check fun b : bool => if b as b0 return (if b0 then b0 = true else b0 = false) then refl_equal true else refl_equal false. rocq-9.2.0/test-suite/success/implicit.v000066400000000000000000000112021516144147600202520ustar00rootroot00000000000000(* Testing the behavior of implicit arguments *) (* Implicit on section variables *) Set Implicit Arguments. Unset Strict Implicit. (* Example submitted by David Nowak *) Section Spec. Variable A : Set. Variable op : forall A : Set, A -> A -> Set. Infix "#" := op (at level 70). Check (forall x : A, x # x). (* Example submitted by Christine *) Record stack : Type := {type : Set; elt : type; empty : type -> bool; proof : empty elt = true}. Check (forall (type : Set) (elt : type) (empty : type -> bool), empty elt = true -> stack). (* Nested sections and manual/automatic implicit arguments *) Variable op' : forall A : Set, A -> A -> Set. Variable op'' : forall A : Set, A -> A -> Set. Section B. Definition eq1 := fun (A:Type) (x y:A) => x=y. Definition eq2 := fun (A:Type) (x y:A) => x=y. Definition eq3 := fun (A:Type) (x y:A) => x=y. Arguments op' : clear implicits. Global Arguments op'' : clear implicits. Arguments eq2 : clear implicits. Global Arguments eq3 : clear implicits. Check (op 0 0). Check (op' nat 0 0). Check (op'' nat 0 0). Check (eq1 0 0). Check (eq2 nat 0 0). Check (eq3 nat 0 0). End B. Check (op 0 0). Check (op' 0 0). Check (op'' nat 0 0). Check (eq1 0 0). Check (eq2 0 0). Check (eq3 nat 0 0). End Spec. Check (eq1 0 0). Check (eq2 0 0). Check (eq3 nat 0 0). (* Example submitted by FrΓ©dΓ©ric (interesting in v8 syntax) *) Parameter f : nat -> nat * nat. Notation lhs := fst. Check (fun x => fst (f x)). Check (fun x => fst (f x)). Notation rhs := snd. Check (fun x => snd (f x)). Check (fun x => @ rhs _ _ (f x)). (* Implicit arguments in fixpoints and inductive declarations *) Fixpoint g n := match n with O => true | S n => g n end. Inductive P n : nat -> Prop := c : P n n. (* Avoid evars in the computation of implicit arguments (cf r9827) *) Fixpoint plus n m {struct n} := match n with | 0 => m | S p => S (plus p m) end. (* Check multiple implicit arguments signatures *) Arguments eq_refl {A x}, {A}. Check eq_refl : 0 = 0. (* Check that notations preserve implicit (since 8.3) *) Parameter p : forall A, A -> forall n, n = 0 -> True. Arguments p [A] _ [n]. Notation Q := (p 0). Check Q eq_refl. (* Check implicits with Context *) Section C. Context {A:Set}. Definition h (a:A) := a. End C. Check h 0. (* Check implicit arguments in arity of inductive types. The three following examples used to fail before r13671 *) Inductive I {A} (a:A) : forall {n:nat}, Prop := | C : I a (n:=0). Inductive I' [A] (a:A) : forall [n:nat], n =0 -> Prop := | C' : I' a eq_refl. Inductive I2 (x:=0) : Prop := | C2 {p:nat} : p = 0 -> I2 | C2' [p:nat] : p = 0 -> I2. Check C2' eq_refl. Inductive I3 {A} (x:=0) (a:A) : forall {n:nat}, Prop := | C3 : I3 a (n:=0). (* Check global implicit declaration over ref not in section *) Section D. Global Arguments eq [A] _ _. End D. (* Check local manual implicit arguments *) (* Gives a warning and make the second x anonymous *) (* Isn't the name "arg_1" a bit fragile though? *) Check fun f : forall {x:nat} {x:bool} (x:unit), unit => f (x:=1) (arg_2:=true) tt. (* Check the existence of a shadowing warning *) Set Warnings "+syntax". Fail Check fun f : forall {x:nat} {x:bool} (x:unit), unit => f (x:=1) (arg_2:=true) tt. Set Warnings "syntax". (* Test failure when implicit arguments are mentioned in subterms which are not types of variables *) Set Warnings "+syntax". Fail Check (id (forall {a}, a)). Set Warnings "syntax". (* Miscellaneous tests *) Check let f := fun {x:nat} y => y=true in f false. Check let f := fun [x:nat] y => y=true in f false. (* Isn't the name "arg_1" a bit fragile, here? *) Check fun f : forall {_:nat}, nat => f (arg_1:=0). (* This test was wrongly warning/failing at some time *) Set Warnings "+syntax". Check id (fun x => let f c {a} (b:a=a) := b in f true (eq_refl 0)). Set Warnings "syntax". Axiom eq0le0 : forall (n : nat) (x : n = 0), n <= 0. Parameter eq0le0' : forall (n : nat) {x : n = 0}, n <= 0. Axiom eq0le0'' : forall (n : nat) {x : n = 0}, n <= 0. Definition eq0le0''' : forall (n : nat) {x : n = 0}, n <= 0. Admitted. Fail Axiom eq0le0'''' : forall [n : nat] {x : n = 0}, n <= 0. Module TestUnnamedImplicit. Axiom foo : forall A, A -> A. Arguments foo {A} {_}. Check foo (arg_2:=true) : bool. Check foo (1:=true) : bool. Check foo : bool. Arguments foo {A} {x}. Check foo (x:=true) : bool. Axiom bar : forall A, A -> nat -> forall B, B -> A * B. Arguments bar {A} {x} _ {B} {y}. Check bar (1:=true) 0 (3:=false). End TestUnnamedImplicit. Module NotationAppliedConstantMultipleImplicit. Axiom f : nat -> nat -> nat -> nat. Arguments f {_} _ _, {_ _} _. Notation "#" := (@f 0). Check # 0 : nat. End NotationAppliedConstantMultipleImplicit. rocq-9.2.0/test-suite/success/import_mod.v000066400000000000000000000017411516144147600206200ustar00rootroot00000000000000 Definition p := 0. Definition m := 0. Module Test_Import. Module P. Definition p := 1. End P. Module M. Import P. Definition m := p. End M. Module N. Import M. Lemma th0 : p = 0. reflexivity. Qed. End N. (* M and P should be closed *) Lemma th1 : m = 0 /\ p = 0. split; reflexivity. Qed. Import N. (* M and P should still be closed *) Lemma th2 : m = 0 /\ p = 0. split; reflexivity. Qed. End Test_Import. (********************************************************************) Module Test_Export. Module P. Definition p := 1. End P. Module M. Export P. Definition m := p. End M. Module N. Export M. Lemma th0 : p = 1. reflexivity. Qed. End N. (* M and P should be closed *) Lemma th1 : m = 0 /\ p = 0. split; reflexivity. Qed. Import N. (* M and P should now be opened *) Lemma th2 : m = 1 /\ p = 1. split; reflexivity. Qed. End Test_Export. rocq-9.2.0/test-suite/success/indelim.v000066400000000000000000000025201516144147600200640ustar00rootroot00000000000000Inductive boolP : Prop := | trueP : boolP | falseP : boolP. Fail Check boolP_rect. Inductive True : Prop := I : True. Inductive False : Prop :=. Inductive Empty_set : Set :=. Fail Inductive Large_set : Set := large_constr : forall A : Set, A -> Large_set. Inductive smallunitProp : Prop := | onlyProps : True -> smallunitProp. Check smallunitProp_rect. Inductive nonsmallunitProp : Prop := | notonlyProps : nat -> nonsmallunitProp. Fail Check nonsmallunitProp_rect. Set Printing Universes. Inductive inferProp := | hasonlyProps : True -> nonsmallunitProp -> inferProp. Check (inferProp : Prop). Inductive inferSet := | hasaset : nat -> True -> nonsmallunitProp -> inferSet. Fail Check (inferSet : Prop). Check (inferSet : Set). Inductive inferLargeSet := | hasalargeset : Set -> True -> nonsmallunitProp -> inferLargeSet. Fail Check (inferLargeSet : Set). Inductive largeProp : Prop := somelargeprop : Set -> largeProp. Inductive comparison : Set := | Eq : comparison | Lt : comparison | Gt : comparison. Inductive CompareSpecT (Peq Plt Pgt : Prop) : comparison -> Type := | CompEqT : Peq -> CompareSpecT Peq Plt Pgt Eq | CompLtT : Plt -> CompareSpecT Peq Plt Pgt Lt | CompGtT : Pgt -> CompareSpecT Peq Plt Pgt Gt. Inductive color := Red | Black. Inductive option (A : Type) : Type := | None : option A | Some : A -> option A. rocq-9.2.0/test-suite/success/inds_type_sec.v000066400000000000000000000013501516144147600212730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* T U. End S. rocq-9.2.0/test-suite/success/induct.v000066400000000000000000000102641516144147600177350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* X. Inductive Y : Set := cons2 : list (Y * Y) -> Y. (* Test inductive types with local definitions *) Inductive eq1 : forall A:Type, let B:=A in A -> Prop := refl1 : eq1 True I. Check fun (P : forall A : Type, let B := A in A -> Type) (f : P True I) (A : Type) => let B := A in fun (a : A) (e : eq1 A a) => match e in (eq1 A0 a0) return (P A0 a0) with | refl1 => f end. Inductive eq2 (A:Type) (a:A) : forall B C:Type, let D:=(A*B*C)%type in D -> Prop := refl2 : eq2 A a unit bool (a,tt,true). (* Check that induction variables are cleared even with in clause *) Lemma foo : forall n m : nat, n + m = n + m. Proof. intros; induction m as [|m] in n |- *. auto. auto. Qed. (* Check selection of occurrences by pattern *) Goal forall x, S x = S (S x). intros. induction (S _) in |- * at -2. now_show (0=1). Undo 2. induction (S _) in |- * at 1 3. now_show (0=1). Undo 2. induction (S _) in |- * at 1. now_show (0=S (S x)). Undo 2. induction (S _) in |- * at 2. now_show (S x=0). Undo 2. induction (S _) in |- * at 3. now_show (S x=1). Undo 2. Fail induction (S _) in |- * at 4. Abort. (* Check use of "as" clause *) Inductive I := C : forall x, x<0 -> I -> I. Goal forall x:I, x=x. intros. induction x as [y * IHx]. change (x = x) in IHx. (* We should have IHx:x=x *) Abort. (* This was not working in 8.4 *) Goal forall h:nat->nat, h 0 = h 1 -> h 1 = h 2 -> h 0 = h 2. intros. induction h. 2:change (n = h 1 -> n = h 2) in IHn. Abort. (* This was not working in 8.4 *) Goal forall h:nat->nat, h 0 = h 1 -> h 1 = h 2 -> h 0 = h 2. intros h H H0. induction h in H |- *. Abort. (* "at" was not granted in 8.4 in the next two examples *) Goal forall h:nat->nat, h 0 = h 1 -> h 1 = h 2 -> h 0 = h 2. intros h H H0. induction h in H at 2, H0 at 1. change (h 0 = 0) in H. Abort. Goal forall h:nat->nat, h 0 = h 1 -> h 1 = h 2 -> h 0 = h 2. intros h H H0. Fail induction h in H at 2 |- *. (* Incompatible occurrences *) Abort. (* Check generalization with dependencies in section variables *) Section S3. Variables x : nat. Definition cond := x = x. Goal cond -> x = 0. intros H. induction x as [|n IHn]. 2:change (n = 0) in IHn. (* We don't want a generalization over cond *) Abort. End S3. (* These examples show somehow arbitrary choices of generalization wrt to indices, when those indices are not linear. We check here 8.4 compatibility: when an index is a subterm of a parameter of the inductive type, it is not generalized. *) Inductive repr (x:nat) : nat -> Prop := reprc z : repr x z -> repr x z. Goal forall x, 0 = x -> repr x x -> True. intros x H1 H. induction H. change True in IHrepr. Abort. Goal forall x, 0 = S x -> repr (S x) (S x) -> True. intros x H1 H. induction H. change True in IHrepr. Abort. Inductive repr' (x:nat) : nat -> Prop := reprc' z : repr' x (S z) -> repr' x z. Goal forall x, 0 = x -> repr' x x -> True. intros x H1 H. induction H. change True in IHrepr'. Abort. (* In this case, generalization was done in 8.4 and we preserve it; this is arbitrary choice *) Inductive repr'' : nat -> nat -> Prop := reprc'' x z : repr'' x z -> repr'' x z. Goal forall x, 0 = x -> repr'' x x -> True. intros x H1 H. induction H. change (0 = z -> True) in IHrepr''. Abort. (* Mentioned as part of bug #12944 *) Inductive test : Set := cons : forall (IHv : nat) (v : test), test. Goal test -> test. induction 1 as [? IHv]. Undo. destruct 1 as [? IHv]. exact IHv. (* Check that the name is granted *) Qed. rocq-9.2.0/test-suite/success/instantiate.v000066400000000000000000000002131516144147600207630ustar00rootroot00000000000000Goal True. Proof. refine (let ev := (fun (n : nat) => _) in _). revert ev. instantiate (1 := nat). instantiate (1 := n). constructor. Qed. rocq-9.2.0/test-suite/success/intros.v000066400000000000000000000072111516144147600177630ustar00rootroot00000000000000(* Thinning introduction hypothesis must be done after all introductions *) (* Submitted by Guillaume Melquiond (BZ#1000) *) Goal forall A, A -> True. intros _ _. Abort. (* This did not work until March 2013, because of underlying "red" *) Goal (fun x => True -> True) 0. intro H. Abort. (* This should still work, with "intro" calling "hnf" *) Goal (fun f => True -> f 0 = f 0) (fun x => x). intro H. match goal with [ |- 0 = 0 ] => reflexivity end. Abort. (* Somewhat related: This did not work until March 2013 *) Goal (fun f => f 0 = f 0) (fun x => x). hnf. match goal with [ |- 0 = 0 ] => reflexivity end. Abort. (* Fixing behavior of "*" and "**" in branches, so that they do not introduce more than what the branch expects them to introduce at most *) Goal forall n p, n + p = 0. intros [|*]; intro p. Abort. (* Check non-interference of "_" with name generation *) Goal True -> True -> True. intros _ ?. exact H. Qed. (* A short test about introduction pattern pat%c *) Goal (True -> 0=0) -> True /\ False -> 0=0. intros H (H1%H,_). exact H1. Qed. (* A test about bugs in 8.5beta2 *) Goal (True -> 0=0) -> True /\ False -> False -> 0=0. intros H H0 H1. destruct H0 as (a%H,_). (* Check that H0 is removed (was bugged in 8.5beta2) *) Fail clear H0. (* Check position of newly created hypotheses when using pat%c (was left at top in 8.5beta2) *) match goal with H:_ |- _ => clear H end. (* clear H1:False *) match goal with H:_ |- _ => exact H end. (* check that next hyp shows 0=0 *) Qed. Goal (True -> 0=0) -> True -> 0=0. intros H H1%H. exact H1. Qed. Goal forall n, n = S n -> 0=0. intros n H%n_Sn. destruct H. Qed. (* Another check about generated names and cleared hypotheses with pat%c patterns *) Goal (True -> 0=0 /\ 1=1) -> True -> 0=0. intros H (H1,?)%H. change (1=1) in H0. exact H1. Qed. (* Checking iterated pat%c1...%cn introduction patterns and side conditions *) Goal forall A B C D:Prop, (A -> B -> C) -> (C -> D) -> B -> A -> D. intros * H H0 H1. intros H2%H%H0. - exact H2. - exact H1. Qed. (* Bug found by Enrico *) Goal forall x : nat, True. intros y%(fun x => x). Abort. (* Fixing a bug in the order of side conditions of a "->" step *) Goal (True -> 1=0) -> 1=1. intros ->. - reflexivity. - exact I. Qed. Goal forall x, (True -> x=0) -> 0=x. intros x ->. - reflexivity. - exact I. Qed. (* Fixing a bug when destructing a type with let-ins in the constructor *) Inductive I := C : let x:=1 in x=1 -> I. Goal I -> True. intros [x H]. (* Was failing in 8.5 *) Abort. (* Ensuring that the (pat1,...,patn) intropatterns has the expected size, up to skipping let-ins *) Goal I -> 1=1. intros (H). (* This skips x *) exact H. Qed. Goal I -> 1=1. Fail intros (x,H,H'). Fail intros [|]. intros (x,H). exact H. Qed. Goal Acc le 0 -> True. Fail induction 1 as (n,H). (* Induction hypothesis is missing *) induction 1 as (n,H,IH). exact Logic.I. Qed. (* Make "intro"/"intros" progress on existential variables *) Module Evar. Goal exists (A:Prop), A. eexists. unshelve (intro y). - exact nat. - exact (y=y). - auto. Qed. Goal exists (A:Prop), A. eexists. unshelve (intros x). - exact nat. - exact (x=x). - auto. Qed. Definition d := ltac:(let x := fresh in intro x; exact (x*x)). Definition d' : nat -> _ := ltac:(intros;exact 0). End Evar. Module Wildcard. (* We check that the wildcard internal name does not interfere with user fresh names (currently the prefix is "_H") *) Goal nat -> bool -> nat -> bool. intros _ ?_H ?_H. exact _H. Qed. End Wildcard. Module SimplNever. Fixpoint arrow n X := match n with | 0 => X | S n => X -> arrow n X end. Arguments arrow : simpl never. Goal arrow 1 False. intro H. exact H. Qed. End SimplNever. rocq-9.2.0/test-suite/success/keyedrewrite.v000066400000000000000000000025031516144147600211470ustar00rootroot00000000000000Set Keyed Unification. Section foo. Variable f : nat -> nat. Definition g := f. Variable lem : g 0 = 0. Goal f 0 = 0. Proof. Fail rewrite lem. Abort. Declare Equivalent Keys @g @f. (** Now f and g are considered equivalent heads for subterm selection *) Goal f 0 = 0. Proof. rewrite lem. reflexivity. Qed. Print Equivalent Keys. End foo. Require Import TestSuite.list. Definition G {A} (f : A -> A -> A) (x : A) := f x x. Lemma list_foo A (l : list A) : G (@app A) (app l nil) = G (@app A) l. Proof. unfold G; rewrite app_nil_r; reflexivity. Qed. (* Bundled version of a magma *) Structure magma := Magma { b_car :> Type; op : b_car -> b_car -> b_car }. Arguments op {_} _ _. (* Instance for lists *) Canonical Structure list_magma A := Magma (list A) (@app A). (* Basically like list_foo, but now uses the op projection instead of app for the argument of G *) Lemma test1 A (l : list A) : G op (app l nil) = G op l. (* Ensure that conversion of terms with evars is allowed once a keyed candidate unifier is found *) rewrite -> list_foo. reflexivity. Qed. (* Basically like list_foo, but now uses the op projection for everything *) Lemma test2 A (l : list A) : G op (op l nil) = G op l. Proof. rewrite ->list_foo. reflexivity. Qed. Set Keyed Unification. Lemma test b : andb b true = b. Fail rewrite andb_true_l. Admitted. rocq-9.2.0/test-suite/success/let_pattern_mismatch.v000066400000000000000000000011201516144147600226440ustar00rootroot00000000000000(* Weird corner case accepted by the pattern-matching algorithm. Destructuring let-bindings in patterns can actually be shorter than the case they match. *) Inductive ascii : Set := | Ascii : bool -> bool -> bool -> bool -> bool -> bool -> bool -> bool -> ascii. Definition dummy (a : ascii) : unit := let (a0,a1,a2,a3,a4,a5,a6,a7) := a in tt. Goal forall (a : ascii) (H : tt = dummy a), True. Proof. intros a H. unfold dummy in *. (* Two bound variables in the pattern, eight in the term. *) match goal with | H:context [ let (x, y) := ?X in _ ] |- _ => destruct X eqn:? end. Abort. rocq-9.2.0/test-suite/success/let_universes.v000066400000000000000000000001301516144147600213250ustar00rootroot00000000000000Section S. Let bla@{} := Prop. Let bli@{u} := Type@{u}. Fail Let blo@{} := Type. End S. rocq-9.2.0/test-suite/success/letproj.v000066400000000000000000000004631516144147600201260ustar00rootroot00000000000000Set Primitive Projections. Set Nonrecursive Elimination Schemes. Record Foo (A : Type) := { bar : A -> A; baz : A }. Definition test (A : Type) (f : Foo A) := let (x, y) := f in x. Scheme foo_case := Case for Foo Sort Type. Definition test' (A : Type) (f : Foo A) := let 'Build_Foo _ x y := f in x. rocq-9.2.0/test-suite/success/locality_attributes_modules.v000066400000000000000000000250551516144147600242710ustar00rootroot00000000000000(** This file tests how locality attributes affect usual vernacular commands. PLEASE, when this file fails to compute following a voluntary change in Coq's behaviour, modify accordingly the tables in [sections.rst] and [modules.rst] in [doc/sphinx/language/core]. Also look at the corresponding discussions about locality attributes in the refman (directory doc/sphinx) - For Definition, Lemma, ..., look at language/core/definitions.rst - For Axiom, Conjecture, ..., look at language/core/assumptions.rst - For abbreviations, look at user-extensions/syntax-extensions.rst - For Notations, look at user-extensions/syntax-extensions.rst - For Tactic Notations, look at user-extensions/syntax-extensions.rst - For Ltac, look at proof-engine/ltac.rst - For Canonical Structures, look at language/extensions/canonical.rst - For Hints, look at proofs/automatic-tactics/auto.rst - For Coercions, look at addendum/implicit-coercions.rst - For Ltac2, look at proof-engine/ltac2.rst - For Ltac2 Notations, look at proof-engine/ltac2.rst - For Set, look at language/core/basic.rst *) (** This structure is used to test availability or not of a [Canonical Structure]. *) Structure PointedType : Type := { Carrier :> Set; point : Carrier }. (** This HintDb is used to test availability or not of a [Hint] command. *) Create HintDb plop. (** ** Tests for modules and visibility attributes *) (** *** Without attribute (default) *) Module InModuleDefault. Module Bar. (* A parameter: *) Parameter (secret : nat). (* An axiom: *) Axiom secret_is_42 : secret = 42. (* A custom tactic: *) Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) Notation add_42 := (Nat.add 42). (* A tactic notation: *) Tactic Notation "rfl" := reflexivity. (* A notation: *) Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) Lemma secret_42 : secret = 42. Proof. find_secret. rfl. Qed. (* A Canonical Structure: *) Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion: *) Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting: *) Set Universe Polymorphism. (* A Hint: *) Hint Resolve secret_42 : plop. End Bar. (** **** Without importing: *) (* Availability of the parameter *) Check Bar.secret. Fail Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Fail Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. Print Bar.find_secret. (* Availability of the abbreviation *) Fail Check add_42. Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Fail Check (point nat). (* Availability of the coercion *) Fail Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Fail Check foo_ni@{_}. (* Availability of the [Hint] *) Lemma hop_ni : Bar.secret = 42. Proof. Fail solve [auto with plop]. Admitted. (** **** After importing: *) Import Bar. (* Availability of the parameter *) Check Bar.secret. Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Check secret_is_42. (* Availability of the tactic *) Print find_secret. Print Bar.find_secret. (* Availability of the abbreviation *) Check add_42. Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. rfl. Qed. (* Availability of the notation *) Check (2 +p 3). (* Availability of the canonical structure *) Check (point nat). (* Availability of the coercion *) Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Fail Check foo_i@{_}. (* Availability of the [Hint] *) Lemma hop_i : Bar.secret = 42. Proof. solve [auto with plop]. Qed. End InModuleDefault. Module InModuleLocal. Module Bar. (* A parameter: *) #[local] Parameter (secret : nat). (* An axiom: *) #[local] Axiom secret_is_42 : secret = 42. (* A custom tactic: *) #[local] Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) #[local] Notation add_42 := (Nat.add 42). (* A tactic notation: *) #[local] Tactic Notation "rfl" := reflexivity. (* A notation: *) #[local] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) #[local] Lemma secret_42 : secret = 42. Proof. find_secret. rfl. Qed. (* A Canonical Structure *) #[local] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) #[local] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[local] Set Universe Polymorphism. (* A Hint *) #[local] Hint Resolve secret_42 : plop. End Bar. (** **** Without importing: *) (* Availability of the parameter *) Check Bar.secret. Fail Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Fail Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. Fail Print Bar.find_secret. (* Availability of the abbreviation *) Fail Check add_42. Fail Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Fail Check (point nat). (* Availability of the coercion *) Fail Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Fail Check foo_ni@{_}. (* Availability of the [Hint] *) Lemma hop_ni : Bar.secret = 42. Proof. Fail solve [auto with plop]. Admitted. (** **** After importing: *) Import Bar. (* Availability of the parameter *) Check Bar.secret. Fail Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Fail Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. Fail Print Bar.find_secret. (* Availability of the abbreviation *) Fail Check add_42. Fail Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Check (point nat). (* Availability of the coercion *) Fail Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Fail Check foo_i@{_}. (* Availability of the [Hint] *) Lemma hop_i : Bar.secret = 42. Proof. Fail solve [auto with plop]. Admitted. End InModuleLocal. Module InModuleExport. Module Bar. (* A parameter: *) Fail #[export] Parameter (secret : nat). (* An axiom: *) Fail #[export] Axiom plop : 0 = 0. (* A custom tactic: *) Fail #[export] Ltac find_secret := reflexivity. (* An abbreviation: *) #[export] Notation add_42 := (Nat.add 42). (* A tactic notation: *) Fail #[export] Tactic Notation "rfl" := reflexivity. (* A notation: *) Fail #[export] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) Fail #[export] Lemma secret_42 : secret = 42. (* A Canonical Structure *) Fail #[export] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) Fail#[export] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[export] Set Universe Polymorphism. (* A Hint *) Parameter (secret : nat). Axiom secret_42 : secret = 42. #[export] Hint Resolve secret_42 : plop. End Bar. (** **** Without importing: *) (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Fail Check foo_ni@{_}. (* Availability of the [Hint] *) Lemma hop_ni : Bar.secret = 42. Proof. Fail solve [auto with plop]. Admitted. (** **** After importing: *) Import Bar. (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Check foo_i@{_}. (* Availability of the [Hint] *) Lemma hop_i : Bar.secret = 42. Proof. solve [auto with plop]. Qed. End InModuleExport. Module InModuleGlobal. Module Bar. (* A parameter: *) #[global] Parameter (secret : nat). (* An axiom: *) #[global] Axiom secret_is_42 : secret = 42. (* A custom tactic: *) #[global] Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) #[global] Notation add_42 := (Nat.add 42). (* A tactic notation: *) #[global] Tactic Notation "rfl" := reflexivity. (* A notation: *) #[global] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) #[global] Lemma secret_42 : secret = 42. Proof. find_secret. rfl. Qed. (* A Canonical Structure *) #[global] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) #[global] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[global] Set Universe Polymorphism. (* A Hint *) #[global] Hint Resolve secret_42 : plop. End Bar. (** **** Without importing: *) (* Availability of the parameter *) Check Bar.secret. Fail Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Fail Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. Print Bar.find_secret. (* Availability of the abbreviation *) Fail Check add_42. Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Fail Check (point nat). (* Availability of the coercion *) Fail Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Check foo_ni@{_}. (* Availability of the [Hint] *) Lemma hop_ni : Bar.secret = 42. Proof. solve [auto with plop]. Admitted. (** **** After importing: *) Import Bar. (* Availability of the parameter *) Check Bar.secret. Check secret. (* Availability of the axiom *) Check Bar.secret_is_42. Check secret_is_42. (* Availability of the tactic *) Print find_secret. Print Bar.find_secret. (* Availability of the abbreviation *) Check add_42. Check Bar.add_42. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. rfl. Qed. (* Availability of the notation *) Check (2 +p 3). (* Availability of the canonical structure *) Check (point nat). (* Availability of the coercion *) Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Check foo_i@{_}. (* Availability of the [Hint] *) Lemma hop_i : Bar.secret = 42. Proof. solve [auto with plop]. Qed. End InModuleGlobal. (** Since I have some global Hints and Settings, the corresponding tests for Sections are in the file locality_attributes_sections.v *) rocq-9.2.0/test-suite/success/locality_attributes_modules_ltac2.v000066400000000000000000000066331516144147600253570ustar00rootroot00000000000000(** This file tests how locality attributes affect usual vernacular commands. PLEASE, when this file fails to compute following a voluntary change in Coq's behaviour, modify accordingly the tables in [sections.rst] and [modules.rst] in [doc/sphinx/language/core] Also look at the corresponding discussions about locality attributes in the refman (directory doc/sphinx) - For Definition, Lemma, ..., look at language/core/definitions.rst - For Axiom, Conjecture, ..., look at language/core/assumptions.rst - For abbreviations, look at user-extensions/syntax-extensions.rst - For Notations, look at user-extensions/syntax-extensions.rst - For Tactic Notations, look at user-extensions/syntax-extensions.rst - For Ltac, look at proof-engine/ltac.rst - For Canonical Structures, look at language/extensions/canonical.rst - For Hints, look at proofs/automatic-tactics/auto.rst - For Coercions, look at addendum/implicit-coercions.rst - For Ltac2, look at proof-engine/ltac2.rst - For Ltac2 Notations, look at proof-engine/ltac2.rst - For Set, look at language/core/basic.rst *) From Ltac2 Require Import Ltac2. (** ** Tests for modules and visibility attributes with Ltac2 *) (* A parameter: *) Parameter (secret : nat). (* An axiom: *) Axiom secret_is_42 : secret = 42. (** *** Without attribute (default) *) Module InModuleDefault. Module Bar. (* A custom tactic: *) Ltac2 find_secret () := rewrite secret_is_42. Ltac2 Notation "rfl" := reflexivity. End Bar. (** **** Without importing: *) (* Availability of the tactic *) Fail Print find_secret. Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (** **** After importing: *) Import Bar. (* Availability of the tactic *) Print find_secret. Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. rfl. Qed. End InModuleDefault. Module InModuleLocal. Module Bar. #[local] Ltac2 find_secret () := rewrite secret_is_42. #[local] Ltac2 Notation "rfl" := reflexivity. End Bar. (** **** Without importing: *) (* Availability of the tactic *) Fail Print find_secret. Fail Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (** **** After importing: *) Import Bar. (* Availability of the tactic *) Fail Print find_secret. Fail Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. Fail rfl. Admitted. End InModuleLocal. Module InModuleExport. Module Bar. (* A custom tactic: *) Fail #[export] Ltac2 find_secret := reflexivity. (* A tactic notation: *) Fail #[export] Ltac2 Notation "rfl" := reflexivity. End Bar. (** Nothing to check, Ltac2 and Ltac2 Notation do not support the [export] attribute. *) End InModuleExport. Module InModuleGlobal. Module Bar. #[global] Ltac2 find_secret () := rewrite secret_is_42. (* A tactic notation: *) #[global] Ltac2 Notation "rfl" := reflexivity. End Bar. (** **** Without importing: *) (* Availability of the tactic *) Fail Print find_secret. Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (** **** After importing: *) Import Bar. Print find_secret. Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. rfl. Qed. End InModuleGlobal. rocq-9.2.0/test-suite/success/locality_attributes_sections.v000066400000000000000000000156341516144147600244520ustar00rootroot00000000000000(** This file tests how locality attributes affect usual vernacular commands. PLEASE, when this file fails to compute following a voluntary change in Coq's behaviour, modify accordingly the tables in [sections.rst] and [modules.rst] in [doc/sphinx/language/core]. Also look at the corresponding discussions about locality attributes in the refman (directory doc/sphinx) - For Definition, Lemma, ..., look at language/core/definitions.rst - For Axiom, Conjecture, ..., look at language/core/assumptions.rst - For abbreviations, look at user-extensions/syntax-extensions.rst - For Notations, look at user-extensions/syntax-extensions.rst - For Tactic Notations, look at user-extensions/syntax-extensions.rst - For Ltac, look at proof-engine/ltac.rst - For Canonical Structures, look at language/extensions/canonical.rst - For Hints, look at proofs/automatic-tactics/auto.rst - For Coercions, look at addendum/implicit-coercions.rst - For Ltac2, look at proof-engine/ltac2.rst - For Ltac2 Notations, look at proof-engine/ltac2.rst - For Set, look at language/core/basic.rst *) (** This structure is used to test availability or not of a [Canonical Structure]. *) Structure PointedType : Type := { Carrier :> Set; point : Carrier }. (** This HintDb is used to test availability or not of a [Hint] command. *) Create HintDb plop. (** ** Tests for sections and visibility attributes *) (** *** Without attribute (default) *) Module InSectionDefault. Section Bar. (* A parameter: *) Parameter (secret : nat). (* An axiom: *) Axiom secret_is_42 : secret = 42. (* A custom tactic: *) Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) Notation add_42 := (Nat.add 42). (* A tactic notation: *) Tactic Notation "rfl" := reflexivity. (* A notation: *) Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) Lemma secret_42 : secret = 42. Proof. find_secret. rfl. Qed. (* A Canonical Structure: *) Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion: *) Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting: *) Set Universe Polymorphism. (* A Hint: *) Hint Resolve secret_42 : plop. End Bar. (* Availability of the parameter *) Check secret. (* Availability of the axiom *) Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. (* Availability of the abbreviation *) Fail Check add_42. (* Availability of the tactic notation *) Lemma plop_i : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Check (point nat). (* Availability of the coercion *) Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Check foo_i@{_}. (* Availability of the [Hint] *) Lemma hop_i : secret = 42. Proof. Fail solve [auto with plop]. Admitted. End InSectionDefault. Module InSectionLocal. Section Bar. (* A parameter: *) #[local] Parameter (secret : nat). (* An axiom: *) #[local] Axiom secret_is_42 : secret = 42. (* A custom tactic: *) #[local] Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) #[local] Notation add_42 := (Nat.add 42). (* A tactic notation: *) #[local] Tactic Notation "rfl" := reflexivity. (* A notation: *) #[local] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) #[local] Lemma secret_42 : secret = 42. Proof. find_secret. rfl. Qed. (* A Canonical Structure *) #[local] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) #[local] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[local] Set Universe Polymorphism. (* A Hint *) #[local] Hint Resolve secret_42 : plop. End Bar. (** **** Without importing: *) (* Availability of the parameter *) Check secret. (* Availability of the axiom *) Check secret_is_42. (* Availability of the tactic *) Fail Print find_secret. (* Availability of the abbreviation *) Fail Check add_42. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. (* Availability of the notation *) Fail Check (2 +p 3). (* Availability of the canonical structure *) Fail Check (point nat). (* Availability of the coercion *) Fail Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Fail Check foo_ni@{_}. (* Availability of the [Hint] *) Lemma hop_ni : secret = 42. Proof. Fail solve [auto with plop]. Admitted. End InSectionLocal. Module InSectionExport. Section Bar. (* A parameter: *) Fail #[export] Parameter (secret : nat). (* An axiom: *) Fail #[export] Axiom plop : 0 = 0. (* A custom tactic: *) Fail #[export] Ltac find_secret := reflexivity. (* An abbreviation: *) Fail #[export] Notation add_42 := (Nat.add 42). (* A tactic notation: *) Fail #[export] Tactic Notation "rfl" := reflexivity. (* A notation: *) Fail #[export] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A lemma: *) Fail #[export] Lemma secret_42 : secret = 42. (* A Canonical Structure *) Fail #[export] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) Fail#[export] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[export] Set Universe Polymorphism. (* A Hint *) Parameter (secret : nat). Axiom secret_42 : secret = 42. Fail #[export] Hint Resolve secret_42 : plop. End Bar. (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Check foo_ni@{_}. End InSectionExport. Module InSectionGlobal. Section Bar. (* A parameter: *) #[global] Parameter (secret : nat). (* An axiom: *) #[global] Axiom secret_is_42 : secret = 42. (* A custom tactic: *) Fail #[global] Ltac find_secret := rewrite secret_is_42. (* An abbreviation: *) Fail #[global] Notation add_42 := (Nat.add 42). (* A tactic notation: *) Fail #[global] Tactic Notation "rfl" := reflexivity. (* A notation: *) Fail #[global] Infix "+p" := Nat.add (only parsing, at level 30, right associativity) : nat_scope. (* A Canonical Structure *) #[global] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Coercion *) #[global] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Setting *) #[global] Set Universe Polymorphism. (* A Hint *) Fail #[global] Hint Resolve secret_is_42 : plop. End Bar. (** **** Without importing: *) (* Availability of the parameter *) Check secret. (* Availability of the axiom *) Check secret_is_42. (* Availability of the canonical structure *) Check (point nat). (* Availability of the coercion *) Check (true + 2). (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Check foo_ni@{_}. End InSectionGlobal. rocq-9.2.0/test-suite/success/locality_attributes_sections_in_modules.v000066400000000000000000000121751516144147600266650ustar00rootroot00000000000000(** This file tests how locality attributes affect usual vernacular commands. PLEASE, when this file fails to compute following a voluntary change in Coq's behaviour, modify accordingly the tables in [sections.rst] and [modules.rst] in [doc/sphinx/language/core]. Also look at the corresponding discussions about locality attributes in the refman (directory doc/sphinx) - For Definition, Lemma, ..., look at language/core/definitions.rst - For Axiom, Conjecture, ..., look at language/core/assumptions.rst - For abbreviations, look at user-extensions/syntax-extensions.rst - For Notations, look at user-extensions/syntax-extensions.rst - For Tactic Notations, look at user-extensions/syntax-extensions.rst - For Ltac, look at proof-engine/ltac.rst - For Canonical Structures, look at language/extensions/canonical.rst - For Hints, look at proofs/automatic-tactics/auto.rst - For Coercions, look at addendum/implicit-coercions.rst - For Ltac2, look at proof-engine/ltac2.rst - For Ltac2 Notations, look at proof-engine/ltac2.rst - For Set, look at language/core/basic.rst *) (** This structure is used to test availability or not of a [Canonical Structure]. *) Structure PointedType : Type := { Carrier :> Set; point : Carrier }. (** ** Tests of visibility attributes in a section inside a module *) (** We only test [Definition], [Coercion], [Canonical] and [Set], the other commands only support the [local] attribute in sections, which is also the default visibility, making them unavailable outside the section. *) (** *** Without attribute (default) *) Module InSectionDefault. Module M. Section Bar. (* A definition: *) Definition foo := 42. (* A Coercion: *) Coercion to_nat (b : bool) := if b then 1 else 0. (* A Canonical Structure: *) Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Setting: *) Set Universe Polymorphism. End Bar. End M. Module M_not_imported. (** First, we do not import M. *) (* Availability of the definition *) Fail Check foo. (* not imported *) (* Availability of the coercion *) Fail Check (true + 2). (* not imported *) (* Availability of the canonical structure *) Fail Check (point nat). (* not imported *) (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Fail Check foo_i@{_}. End M_not_imported. Module M_imported. (** Now we import M. *) Import M. (* Availability of the definition *) Check foo. (* Availability of the coercion *) Check (true + 2). (* Availability of the canonical structure *) Check (point nat). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Fail Check foo_i@{_}. End M_imported. End InSectionDefault. (** *** With the [local] attribute *) (** We only need to test a definition, we know the other commands have no effect outside the section (hence outside the module containing the section). *) Module InSectionLocal. Module M. Section Bar. (* A definition: *) #[local] Definition foo := 42. End Bar. End M. Module M_not_imported. (** First, we do not import M. *) (* Availability of the definition *) Fail Check foo. (* not imported *) Check M.foo. End M_not_imported. Module M_imported. (** Now we import M. *) Import M. (* Availability of the definition *) Fail Check foo. (* /!\ notice the local attribute has been passed to the module! *) Check M.foo. End M_imported. End InSectionLocal. (** *** With the [export] attribute *) (** We only need to test a setting, it is the only command for which [export] is supported inside a [Section]. *) Module InSectionExport. Module M. Section Bar. (* A Setting *) #[export] Set Universe Polymorphism. End Bar. End M. Module M_not_imported. (** **** Without importing: *) (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Fail Check foo_ni@{_}. End M_not_imported. Module M_imported. Import M. (* Availability of [Set Universe Polymorphism] *) Definition foo_ni@{u} := nat. Check foo_ni@{_}. End M_imported. End InSectionExport. (** *** With the [export] attribute *) (** We only need to test [Coercion], [Canonical] and [Set]. *) Module InSectionGlobal. Module M. Section Bar. (* A Coercion: *) #[global] Coercion to_nat (b : bool) := if b then 1 else 0. (* A Canonical Structure: *) #[global] Canonical natPointed : PointedType := {| Carrier := nat; point := 42 |}. (* A Setting: *) #[global] Set Universe Polymorphism. End Bar. End M. Module M_not_imported. (** First, we do not import M. *) (* Availability of the coercion *) Fail Check (true + 2). (* not imported *) (* Availability of the canonical structure *) Fail Check (point nat). (* not imported *) (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Check foo_i@{_}. (* available *) (* /!\ global for [Set] in a section is passed to the module! *) End M_not_imported. Module M_imported. (** Now we import M. *) Import M. (* Availability of the coercion *) Check (true + 2). (* Availability of the canonical structure *) Check (point nat). (* Availability of [Set Universe Polymorphism] *) Definition foo_i@{u} := nat. Check foo_i@{_}. End M_imported. End InSectionGlobal. rocq-9.2.0/test-suite/success/locality_attributes_sections_ltac2.v000066400000000000000000000053401516144147600255300ustar00rootroot00000000000000(** This file tests how locality attributes affect usual vernacular commands. PLEASE, when this file fails to compute following a voluntary change in Coq's behaviour, modify accordingly the tables in [sections.rst] and [modules.rst] in [doc/sphinx/language/core]. Also look at the corresponding discussions about locality attributes in the refman (directory doc/sphinx) - For Definition, Lemma, ..., look at language/core/definitions.rst - For Axiom, Conjecture, ..., look at language/core/assumptions.rst - For abbreviations, look at user-extensions/syntax-extensions.rst - For Notations, look at user-extensions/syntax-extensions.rst - For Tactic Notations, look at user-extensions/syntax-extensions.rst - For Ltac, look at proof-engine/ltac.rst - For Canonical Structures, look at language/extensions/canonical.rst - For Hints, look at proofs/automatic-tactics/auto.rst - For Coercions, look at addendum/implicit-coercions.rst - For Ltac2, look at proof-engine/ltac2.rst - For Ltac2 Notations, look at proof-engine/ltac2.rst - For Set, look at language/core/basic.rst *) From Ltac2 Require Import Ltac2. (** ** Tests for sections and visibility attributes with Ltac2 *) (* A parameter: *) Parameter (secret : nat). (* An axiom: *) Axiom secret_is_42 : secret = 42. (** *** Without attribute (default) *) Module InSectionDefault. Section Bar. (* A custom tactic: *) Ltac2 find_secret () := rewrite secret_is_42. Ltac2 Notation "rfl" := reflexivity. End Bar. (* Availability of the tactic *) Fail Print find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. End InSectionDefault. Module InSectionLocal. Section Bar. #[local] Ltac2 find_secret () := rewrite secret_is_42. #[local] Ltac2 Notation "rfl" := reflexivity. End Bar. (* Availability of the tactic *) Fail Print find_secret. Fail Print Bar.find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. End InSectionLocal. Module InSectionExport. Section Bar. (* A custom tactic: *) Fail #[export] Ltac2 find_secret := reflexivity. (* A tactic notation: *) Fail #[export] Ltac2 Notation "rfl" := reflexivity. End Bar. (** Nothing to check, Ltac2 and Ltac2 Notation do not support the [export] attribute. *) End InSectionExport. Module InSectionGlobal. Section Bar. (* A custom tactic: *) #[global] Ltac2 find_secret () := rewrite secret_is_42. (* A tactic notation: *) #[global] Ltac2 Notation "rfl" := reflexivity. End Bar. (* Availability of the tactic *) Fail Print find_secret. (* Availability of the tactic notation *) Lemma plop_ni : 2 + 2 = 4. Proof. Fail rfl. Admitted. End InSectionGlobal. rocq-9.2.0/test-suite/success/ltac.v000066400000000000000000000231271516144147600173740ustar00rootroot00000000000000(* The tactic language *) (* Submitted by Pierre CrΓ©gut *) (* Checks substitution of x *) Ltac f x := unfold x; idtac. Lemma lem1 : 0 + 0 = 0. f plus. reflexivity. Qed. (* Submitted by Pierre CrΓ©gut *) (* Check syntactic correctness *) Ltac F x := idtac; G x with G y := idtac; F y. (* Check that Match Context keeps a closure *) Ltac U := let a := constr:(I) in match goal with | |- _ => apply a end. Lemma lem2 : True. U. Qed. (* Check that Match giving non-tactic arguments are evaluated at Let-time *) Ltac B := let y := (match goal with | z:_ |- _ => z end) in (intro H1; exact y). Lemma lem3 : True -> False -> True -> False. intros H H0. B. (* y is H0 if at let-time, H1 otherwise *) Qed. (* Checks the matching order of hypotheses *) Ltac Y := match goal with | x:_,y:_ |- _ => apply x end. Ltac Z := match goal with | y:_,x:_ |- _ => apply x end. Lemma lem4 : (True -> False) -> (False -> False) -> False. intros H H0. Z. (* Apply H0 *) Y. (* Apply H *) exact I. Qed. (* Check backtracking *) Lemma back1 : 0 = 1 -> 0 = 0 -> 1 = 1 -> 0 = 0. intros; match goal with | _:(0 = ?X1),_:(1 = 1) |- _ => exact (refl_equal X1) end. Qed. Lemma back2 : 0 = 0 -> 0 = 1 -> 1 = 1 -> 0 = 0. intros; match goal with | _:(0 = ?X1),_:(1 = 1) |- _ => exact (refl_equal X1) end. Qed. Lemma back3 : 0 = 0 -> 1 = 1 -> 0 = 1 -> 0 = 0. intros; match goal with | _:(0 = ?X1),_:(1 = 1) |- _ => exact (refl_equal X1) end. Qed. (* Check context binding *) Ltac sym t := match constr:(t) with | context C[(?X1 = ?X2)] => context C [X1 = X2] end. Lemma sym : 0 <> 1 -> 1 <> 0. intro H. let t := sym type of H in assert t. exact H. intro H1. apply H. symmetry . assumption. Qed. (* Check context binding in match goal *) (* This wasn't working in V8.0pl1, as the list of matched hyps wasn't empty *) Ltac sym' := match goal with | _:True |- context C[(?X1 = ?X2)] => let t := context C [X2 = X1] in assert t end. Lemma sym' : True -> 0 <> 1 -> 1 <> 0. intros Ht H. sym'. exact H. intro H1. apply H. symmetry . assumption. Qed. (* Check that fails abort the current match context *) Lemma decide : True \/ False. match goal with | _ => fail 1 | _ => right end || left. exact I. Qed. (* Check that "match c with" backtracks on subterms *) Lemma refl : 1 = 1. let t := (match constr:(1 = 2) with | context [(S ?X1)] => constr:(refl_equal X1:1 = 1) end) in assert (H := t). assumption. Qed. (* Note that backtracking in "match c with" is only on type-checking not on evaluation of tactics. E.g., this does not work Lemma refl : (1)=(1). Match (1)=(2) With [[(S ?1)]] -> Apply (refl_equal nat ?1). Qed. *) (* Check the precedences of rel context, ltac context and vars context *) (* (was wrong in V8.0) *) Ltac check_binding y := cut ((fun y => y) = S). Goal True. check_binding ipattern:(H). Abort. (* Check that variables explicitly parsed as ltac variables are not seen as intro pattern or constr (BZ#984) *) Ltac afi tac := intros; tac. Goal 1 = 2. afi ltac:(auto). Abort. (* Tactic Notation avec listes *) Tactic Notation "pat" hyp(id) "occs" integer_list(l) := pattern id at l. Goal forall x, x=0 -> x=x. intro x. pat x occs 1 3. Abort. Tactic Notation "revert" ne_hyp_list(l) := generalize l; clear l. Goal forall a b c, a=0 -> b=c+a. intros. revert a b c H. Abort. (* Used to fail until revision 9280 because of a parasitic App node with empty args *) Goal True. match constr:(@None) with @None => exact I end. Abort. (* Check second-order pattern unification *) Ltac to_exist := match goal with |- forall x y, @?P x y => let Q := eval lazy beta in (exists x, forall y, P x y) in assert (Q->Q) end. Goal forall x y : nat, x = y. to_exist. exact (fun H => H). Abort. (* Used to fail in V8.1 *) Tactic Notation "test" constr(t) integer(n) := set (k := t) at n. Goal forall x : nat, x = 1 -> x + x + x = 3. intros x H. test x 2. Abort. (* Utilisation de let rec sans arguments *) Ltac is := let rec i := match goal with |- ?A -> ?B => intro; i | _ => idtac end in i. Goal True -> True -> True. is. exact I. Abort. (* InterfΓ©rence entre espaces des noms *) Ltac O := intro. Ltac Z1 t := set (x:=t). Ltac Z2 t := t. Goal True -> True. Z1 O. Z2 ltac:(O). exact I. Qed. (* Illegal application used to make Ltac loop. *) Section LtacLoopTest. Ltac g x := idtac. Goal True. Timeout 1 try g()(). Abort. End LtacLoopTest. (* Test binding of open terms *) Ltac test_open_match z := match z with (forall y x, ?h = 0) => assert (forall x y, h = x + y) end. Goal True. test_open_match (forall z y, y + z = 0). reflexivity. apply I. Qed. (* Test binding of open terms with non linear matching *) Ltac f_non_linear t := match t with (forall x y, ?u = 0) -> (forall y x, ?u = 0) => assert (forall x y:nat, u = u) end. Goal True. f_non_linear ((forall x y, x+y = 0) -> (forall x y, y+x = 0)). reflexivity. f_non_linear ((forall a b, a+b = 0) -> (forall a b, b+a = 0)). reflexivity. f_non_linear ((forall a b, a+b = 0) -> (forall x y, y+x = 0)). reflexivity. f_non_linear ((forall x y, x+y = 0) -> (forall a b, b+a = 0)). reflexivity. f_non_linear ((forall x y, x+y = 0) -> (forall y x, x+y = 0)). reflexivity. f_non_linear ((forall x y, x+y = 0) -> (forall y x, y+x = 0)) (* should fail *) || exact I. Qed. (* Test regular failure when clear/intro breaks soundness of the interpretation of terms in current environment *) Ltac g y := clear y; assert (y=y). Goal forall x:nat, True. intro x. Fail g x. Abort. Ltac h y := assert (y=y). Goal forall x:nat, True. intro x. Fail clear x; f x. Abort. (* Do not consider evars as unification holes in Ltac matching (and at least not as holes unrelated to the original evars) [Example adapted from Ynot code] *) Ltac not_eq e1 e2 := match e1 with | e2 => fail 1 | _ => idtac end. Goal True. evar(foo:nat). let evval := eval compute in foo in not_eq evval 1. let evval := eval compute in foo in not_eq 1 evval. Abort. (* Check instantiation of binders using ltac names *) Goal True. let x := ipattern:(y) in assert (forall x y, x = y + 0). intro. destruct y. (* Check that the name is y here *) Abort. (* An example suggested by Jason (see #4317) showing the intended semantics *) (* Order of binders is reverted because y is just told to depend on x *) Goal 1=1. let T := constr:(fun a b : nat => a) in lazymatch T with | (fun x z => ?y) => pose ((fun x x => y) 2 1) end. exact (eq_refl n). Qed. (* A variant of #2602 which was wrongly succeeding because "a", bound to "?m", was then internally turned into a "_" in the second matching *) Goal exists m, S m > 0. eexists. Fail match goal with | |- context [ S ?a ] => match goal with | |- S a > a => idtac end end. Abort. (* Test evar syntax *) Goal True. evar (0=0). Abort. (* Test location of hypothesis in "symmetry in H". This was broken in 8.6 where H, when the oldest hyp, was moved at the place of most recent hypothesis *) Goal 0=1 -> True -> True. intros H H0. symmetry in H. (* H should be the first hypothesis *) match goal with h:_ |- _ => assert (h=h) end. (* h should be H0 *) exact (eq_refl H0). Abort. (* Check that internal names used in "match" compilation to push "term to match" on the environment are not interpreted as ltac variables *) Module ToMatchNames. Ltac g c := let r := constr:(match c return _ with a => 1 end) in idtac. Goal True. g 1. Abort. End ToMatchNames. (* An example where internal names used to build the return predicate (here "n" because "a" is bound to "nil" and "n" is the first letter of "nil") by small inversion should be taken distinct from Ltac names. *) Module LtacNames. Inductive t (A : Type) : nat -> Type := nil : t A 0 | cons : A -> forall n : nat, t A n -> t A (S n). Ltac f a n := let x := constr:(match a with nil _ => true | cons _ _ _ _ => I end) in assert (x=x/\n=n). Goal forall (y:t nat 0), True. intros. f y true. Abort. End LtacNames. (* Test binding of the name of existential variables in Ltac *) Module EvarNames. Ltac pick x := eexists ?[x]. Goal exists y, y = 0. pick foo. [foo]:exact 0. auto. Qed. Ltac goal x := refine ?[x]. Goal forall n, n + 0 = n. Proof. induction n; [ goal Base | goal Rec ]. [Base]: { easy. } [Rec]: { simpl. now f_equal. } Qed. End EvarNames. Module LocalRedef. Ltac thetac := idtac. Ltac thetac' := idtac. Module Inner. Ltac thetac ::= fail. Local Ltac thetac' ::= fail. Goal False. Fail thetac. Fail thetac'. Abort. End Inner. Goal False. Fail thetac. thetac'. Abort. Section S. Variable f : False. Fail Global Ltac thetac' ::= exact f. Ltac thetac' ::= exact f. Goal False. Proof. thetac'. Qed. End S. Goal False. Proof. thetac'. Fail Qed. Abort. End LocalRedef. Module MatchCastInPattern. Goal let x := True in True. Proof. intro x. lazymatch goal with | [ H := ?v : ?T |- _ ] => constr_eq T Prop end. Fail lazymatch goal with | [ H := ?v <: ?T |- _ ] => constr_eq T Prop end. (* Warning: Casts are ignored in patterns [cast-in-pattern,automation] *) Set Warnings "+cast-in-pattern". Fail lazymatch goal with | [ H := ?v <: _ |- _ ] => idtac end. Fail lazymatch goal with | [ H := [ ?v : _ ] : _ |- _ ] => idtac end. Abort. End MatchCastInPattern. Module StrictModeConfusion. Goal True. Fail let x := constr:(match _ with x x => _ end) in idtac. (* for_grammar does not reset the ref when an exception is raised *) Abort. Fail Ltac bad := exact x. (* was wrongly accepted *) End StrictModeConfusion. rocq-9.2.0/test-suite/success/ltac_match_pattern_names.v000066400000000000000000000011341516144147600234620ustar00rootroot00000000000000(* example from bug 5345 *) Ltac break_tuple := match goal with | [ H: context[let '(n, m) := ?a in _] |- _ ] => let n := fresh n in let m := fresh m in destruct a as [n m] end. (* desugared version of break_tuple *) Ltac break_tuple' := match goal with | [ H: context[match ?a with | pair n m => _ end] |- _ ] => let n := fresh n in let m := fresh m in idtac end. Ltac multiple_branches := match goal with | [ H: match _ with | left P => _ | right Q => _ end |- _ ] => let P := fresh P in let Q := fresh Q in idtac end. rocq-9.2.0/test-suite/success/ltac_plus.v000066400000000000000000000005451516144147600204360ustar00rootroot00000000000000(** Checks that Ltac's '+' tactical works as intended. *) Goal forall (A B C D:Prop), (A->C) -> (B->C) -> (D->C) -> B -> C. Proof. intros A B C D h0 h1 h2 h3. (* backtracking *) (apply h0 + apply h1);apply h3. Undo. Fail ((apply h0+apply h2) || apply h1); apply h3. (* interaction with || *) ((apply h0+apply h1) || apply h2); apply h3. Qed. rocq-9.2.0/test-suite/success/ltacprof.v000066400000000000000000000013741516144147600202630ustar00rootroot00000000000000(** Some LtacProf tests *) Set Ltac Profiling. Ltac multi := (idtac + idtac). Goal True. try (multi; fail). (* Used to result in: Anomaly: Uncaught exception Failure("hd"). Please report. *) Admitted. Show Ltac Profile. (* backtracking across profiler manipulation *) Unset Ltac Profiling. Reset Ltac Profile. Fixpoint slow (n : nat) : unit := match n with | 0 => tt | S n => fst (slow n, slow n) end. Ltac slow := idtac; let v := eval cbv in (slow 16) in idtac. Ltac multi2 := try (((idtac; slow) + (start ltac profiling; slow) + (idtac; slow) + (slow; stop ltac profiling; slow) + slow + (start ltac profiling; (idtac + slow); ((stop ltac profiling + idtac); fail))); slow; fail); slow; show ltac profile. Goal True. multi2. Admitted. rocq-9.2.0/test-suite/success/match_case_pattern_variables.v000066400000000000000000000014251516144147600243220ustar00rootroot00000000000000(** Check that bound variables in case patterns are handled correctly. *) Goal forall (ch : unit) (t : list unit) (s : list unit), match s with | nil => False | cons a l => ch = a /\ l = t end. Proof. intros. match goal with | |- match ?e with | nil => ?N | cons a b => ?P end => let f := constr:((fun (e' : list unit) => match e' with | nil => N | cons a b => P end)) in change (f e) end. Abort. Goal forall (ch : unit) (n : nat) (s : prod unit nat), let (a, l) := s in ch = a /\ l = n. Proof. intros. match goal with | [ |- let (a, b) := ?e in ?P ] => let f := constr:((fun (e' : prod unit nat) => match e' with pair a b => P end)) in change (f e) end. Abort. rocq-9.2.0/test-suite/success/module_with_def_univ_poly.v000066400000000000000000000012351516144147600237070ustar00rootroot00000000000000 (* When doing Module Foo with Definition bar := ..., bar must be generated with the same polymorphism as Foo.bar. *) Module Mono. Unset Universe Polymorphism. Module Type T. Parameter foo : Type. End T. Module Type F(A:T). End F. Set Universe Polymorphism. Module M : T with Definition foo := Type. Monomorphic Definition foo := Type. End M. End Mono. Module Poly. Set Universe Polymorphism. Module Type T. Parameter foo@{i|Set < i} : Type@{i}. End T. Module Type F(A:T). End F. Unset Universe Polymorphism. Module M : T with Definition foo := Set : Type. Polymorphic Definition foo := Set : Type. End M. End Poly. rocq-9.2.0/test-suite/success/mutual_ind.v000066400000000000000000000033021516144147600206030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* sort -> bool; sort_beq_refl : forall f : sort, true = sort_beq f f; sort_beq_eq : forall f1 f2 : sort, true = sort_beq f1 f2 -> f1 = f2; fsym :> Set; fsym_type : fsym -> list sort * sort; fsym_beq : fsym -> fsym -> bool; fsym_beq_refl : forall f : fsym, true = fsym_beq f f; fsym_beq_eq : forall f1 f2 : fsym, true = fsym_beq f1 f2 -> f1 = f2}. Parameter F : signature. Definition vsym := (sort F * nat)%type. Definition vsym_sort := fst (A:=sort F) (B:=nat). Definition vsym_nat := snd (A:=sort F) (B:=nat). Inductive term : sort F -> Set := | term_var : forall v : vsym, term (vsym_sort v) | term_app : forall f : F, list_term (fst (fsym_type F f)) -> term (snd (fsym_type F f)) with list_term : list (sort F) -> Set := | term_nil : list_term nil | term_cons : forall (s : sort F) (l : list (sort F)), term s -> list_term l -> list_term (s :: l). rocq-9.2.0/test-suite/success/mutual_record.v000066400000000000000000000013611516144147600213120ustar00rootroot00000000000000Module M0. Inductive foo (A : Type) := Foo { foo0 : option (bar A); foo1 : nat; foo2 := foo1 = 0; foo3 : foo2; } with bar (A : Type) := Bar { bar0 : A; bar1 := 0; bar2 : bar1 = 0; bar3 : nat -> foo A; }. End M0. Module M1. Set Primitive Projections. Inductive foo (A : Type) := Foo { foo0 : option (bar A); foo1 : nat; foo2 := foo1 = 0; foo3 : foo2; } with bar (A : Type) := Bar { bar0 : A; bar1 := 0; bar2 : bar1 = 0; bar3 : nat -> foo A; }. End M1. Module M2. Set Primitive Projections. CoInductive foo (A : Type) := Foo { foo0 : option (bar A); foo1 : nat; foo2 := foo1 = 0; foo3 : foo2; } with bar (A : Type) := Bar { bar0 : A; bar1 := 0; bar2 : bar1 = 0; bar3 : nat -> foo A; }. End M2. rocq-9.2.0/test-suite/success/name_mangling.v000066400000000000000000000061431516144147600212440ustar00rootroot00000000000000Set Mangle Names. (* Check that refine policy of redefining previous names make these names private *) Goal True -> True. intro. Fail exact H. exact _0. Abort. Unset Mangle Names. Goal True -> True. intro; exact H. Abort. Set Mangle Names. Set Mangle Names Prefix "baz". Goal True -> True. intro. Fail exact H. Fail exact _0. exact baz0. Abort. Goal True -> True. intro; assumption. Abort. Goal True -> True. intro x; exact x. Abort. Goal forall x y, x+y=0. intro x. refine (fun x => _). Fail Check x0. Check x. Abort. (* Example from Emilio *) Goal forall b : False, b = b. intro b. refine (let b := I in _). Fail destruct b0. Abort. (* Example from Cyprien *) Goal True -> True. Proof. refine (fun _ => _). Fail exact t. Abort. (* Example from Jason *) Goal False -> False. intro H. abstract exact H. Abort. (* Variant *) Goal False -> False. intro. Fail abstract exact H. Abort. (* Example from Jason *) Lemma lem1 : False -> False. intro H. (* Name H' is from Ltac here, so it preserves the privacy *) (* But abstract messes everything up *) let H' := H in abstract exact H'. Qed. (* Variant *) Goal False -> False. intro. Fail let H' := H in abstract exact H'. Abort. (* Indirectly testing preservation of names by move (derived from Jason) *) Inductive nat2 := S2 (_ _ : nat2). Goal forall t : nat2, True. intro t. let IHt1 := fresh "IHt1" in let IHt2 := fresh "IHt2" in induction t as [? IHt1 ? IHt2]. Fail exact IHt1. Abort. (* Example on "pose proof" (from Jason) *) Goal False -> False. intro; pose proof I as H0. Fail exact H. Abort. (* Testing the approach for which non alpha-renamed quantified names are user-generated *) Section foo. Context (b : True). Goal forall b : False, b = b. Fail destruct b0. Abort. Lemma lem2 : forall b : False, b = b. now destruct b. Qed. End foo. (* Test stability of "fix" *) Lemma a : forall n, n = 0. Proof. fix a 1. Check a. Fail fix a 1. Abort. (* Test stability of "induction" *) Lemma a : forall n : nat, n = n. Proof. intro n; induction n as [ | n IHn ]. - auto. - Check n. Check IHn. Abort. Inductive I := C : I -> I -> I. Lemma a : forall n : I, n = n. Proof. intro n; induction n as [ n1 IHn1 n2 IHn2 ]. Check n1. Check n2. apply f_equal2. + apply IHn1. + apply IHn2. Qed. (* Testing remember *) Lemma c : 0 = 0. Proof. remember 0 as x eqn:Heqx. Check Heqx. Abort. Lemma c : forall Heqx, Heqx -> 0 = 0. Proof. intros Heqx X. remember 0 as x. Fail Check Heqx0. (* Heqx0 is not canonical *) Abort. (* An example by Jason from the discussion for PR #268 *) Goal nat -> Set -> True. intros x y. match goal with | [ x : _, y : _ |- _ ] => let z := fresh "z" in rename y into z, x into y; let x' := fresh "x" in rename z into x' end. revert y. (* x has been explicitly moved to y *) Fail revert x. (* x comes from "fresh" *) Abort. Goal nat -> Set -> True. intros. match goal with | [ x : _, y : _ |- _ ] => let z := fresh "z" in rename y into z, x into y; let x' := fresh "x" in rename z into x' end. Fail revert y. (* generated by intros *) Fail revert x. (* generated by intros *) Abort. rocq-9.2.0/test-suite/success/namedunivs.v000066400000000000000000000054111516144147600206160ustar00rootroot00000000000000(* Inductive paths {A} (x : A) : A -> Type := idpath : paths x x where "x = y" := (@paths _ x y) : type_scope. *) (* Goal forall A B : Set, @paths Type A B -> @paths Set A B. *) (* intros A B H. *) (* Fail exact H. *) (* Section . *) Unset Strict Universe Declaration. #[universes(polymorphic)] Section lift_strict. Polymorphic Definition liftlt := let t := Type@{i} : Type@{k} in fun A : Type@{i} => A : Type@{k}. Polymorphic Definition liftle := fun A : Type@{i} => A : Type@{k}. End lift_strict. Set Universe Polymorphism. (* Inductive option (A : Type) : Type := *) (* | None : option A *) (* | Some : A -> option A. *) Inductive option (A : Type@{i}) : Type@{i} := | None : option A | Some : A -> option A. Definition foo' {A : Type@{i}} (o : option@{i} A) : option@{i} A := o. Definition foo'' {A : Type@{i}} (o : option@{j} A) : option@{k} A := o. Definition testm (A : Type@{i}) : Type@{max(i,j)} := A. (* Inductive prod (A : Type@{i}) (B : Type@{j}) := *) (* | pair : A -> B -> prod A B. *) (* Definition snd {A : Type@{i}} (B : Type@{j}) (p : prod A B) : B := *) (* match p with *) (* | pair _ _ a b => b *) (* end. *) (* Definition snd' {A : Type@{i}} (B : Type@{i}) (p : prod A B) : B := *) (* match p with *) (* | pair _ _ a b => b *) (* end. *) (* Inductive paths {A : Type} : A -> A -> Type := *) (* | idpath (a : A) : paths a a. *) Inductive paths {A : Type@{i}} : A -> A -> Type@{i} := | idpath (a : A) : paths a a. Definition Funext := forall (A : Type) (B : A -> Type), forall f g : (forall a, B a), (forall x : A, paths (f x) (g x)) -> paths f g. Definition paths_lift_closed (A : Type@{i}) (x y : A) : paths x y -> @paths (liftle@{j Type} A) x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition paths_lift (A : Type@{i}) (x y : A) : paths x y -> paths@{j} x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition paths_lift_closed_strict (A : Type@{i}) (x y : A) : paths x y -> @paths (liftlt@{j Type} A) x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition paths_downward_closed_le (A : Type@{i}) (x y : A) : paths@{j} (A:=liftle@{i j} A) x y -> paths@{i} x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition paths_downward_closed_lt (A : Type@{i}) (x y : A) : @paths (liftlt@{j i} A) x y -> paths x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition paths_downward_closed_lt_nolift (A : Type@{i}) (x y : A) : paths@{j} x y -> paths x y. Proof. intros. destruct X. exact (idpath _). Defined. Definition funext_downward_closed (F : Funext@{i' j' k'}) : Funext@{i j k}. Proof. intros A B f g H. red in F. pose (F A B f g (fun x => paths_lift _ _ _ (H x))). apply paths_downward_closed_lt_nolift. apply p. Defined. rocq-9.2.0/test-suite/success/nativecompute.v000066400000000000000000000001771516144147600213340ustar00rootroot00000000000000(* An example with local definitions *) Inductive I (a:=0) (b:nat) (c:=1) := C : I b. Eval native_compute in (fun x => C) 0. rocq-9.2.0/test-suite/success/nondisc_ignores_pattern.v000066400000000000000000000006221516144147600233640ustar00rootroot00000000000000(* nondiscriminated uses head const, ignores patterns *) Theorem bar: 1=1. reflexivity. Qed. Theorem bar2: 2=2. reflexivity. Qed. Create HintDb db. (* not discriminated *) Hint Resolve bar : db. Hint Resolve bar2 : db. Set Typeclasses Debug Verbosity 2. Goal 3=3. (* no matching; both theorems are tried. *) Fail progress debug auto with db nocore. Fail typeclasses eauto with db nocore. Abort. rocq-9.2.0/test-suite/success/onlyprinting.v000066400000000000000000000002261516144147600212000ustar00rootroot00000000000000Notation "x ++ y" := (plus x y) (only printing). Fail Check 0 ++ 0. Notation "x + y" := (max x y) (only printing). Check (eq_refl : 42 + 18 = 60). rocq-9.2.0/test-suite/success/options.v000066400000000000000000000012621516144147600201400ustar00rootroot00000000000000(* Check that the syntax for options works *) Set Implicit Arguments. Unset Strict Implicit. Set Strict Implicit. Unset Implicit Arguments. Test Implicit Arguments. Set Printing Coercions. Unset Printing Coercions. Test Printing Coercions. Set Silent. Unset Silent. Test Silent. Set Printing Depth 100. Test Printing Depth. Parameter i : bool -> nat. Coercion i : bool >-> nat. Add Printing Coercion i. Remove Printing Coercion i. Test Printing Coercion for i. Test Printing Let. Test Printing If. Remove Printing Let sig. Remove Printing If bool. Unset Printing Synth. Set Printing Synth. Test Printing Synth. Unset Printing Wildcard. Set Printing Wildcard. Test Printing Wildcard. rocq-9.2.0/test-suite/success/par_abstract.v000066400000000000000000000007251516144147600211150ustar00rootroot00000000000000Axiom T : Type. Lemma foo : True * Type. Proof. split. par: abstract (exact I || exact T). Defined. (* Yes, these names are generated hence the test is fragile. I want to assert that abstract was correctly handled by par: *) Check foo_subproof. Check foo_subproof0. Check (refl_equal _ : foo = pair foo_subproof foo_subproof0). Lemma bar : True * Type. Proof. split. par: (exact I || exact T). Defined. Check (refl_equal _ : bar = pair I T). rocq-9.2.0/test-suite/success/paralleltac.v000066400000000000000000000022711516144147600207320ustar00rootroot00000000000000Lemma test_nofail_like_all1 : True /\ False. Proof. split. all: trivial. Admitted. Lemma test_nofail_like_all2 : True /\ False. Proof. split. par: trivial. Admitted. Fixpoint fib n := match n with | O => 1 | S m => match m with | O => 1 | S o => fib o + fib m end end. Ltac sleep n := try (assert (fib n = S (fib n)) by reflexivity). (* Tune that depending on your PC *) #[local] Definition time := 18. Axiom P : nat -> Prop. Axiom P_triv : Type -> forall x, P x. Ltac solve_P := match goal with |- P (S ?X) => sleep time; exact (P_triv Type _) end. Lemma test_old x : P (S x) /\ P (S x) /\ P (S x) /\ P (S x). Proof. repeat split. idtac "T1: linear". Time all: solve [solve_P]. Qed. Lemma test_ok x : P (S x) /\ P (S x) /\ P (S x) /\ P (S x). Proof. repeat split. idtac "T2: parallel". Time par: solve [solve_P]. Qed. Lemma test_fail x : P (S x) /\ P x /\ P (S x) /\ P (S x). Proof. repeat split. idtac "T3: linear failure". Fail Time all: solve solve_P. all: solve [apply (P_triv Type)]. Qed. Lemma test_fail2 x : P (S x) /\ P x /\ P (S x) /\ P (S x). Proof. repeat split. idtac "T4: parallel failure". Fail Time par: solve [solve_P]. all: solve [apply (P_triv Type)]. Qed. rocq-9.2.0/test-suite/success/parsing.v000066400000000000000000000003321516144147600201050ustar00rootroot00000000000000Section A. Notation "*" := O (at level 8). Notation "**" := O (at level 99). Notation "***" := O (at level 9). End A. Notation "*" := O (at level 8). Notation "**" := O (at level 99). Notation "***" := O (at level 9). rocq-9.2.0/test-suite/success/pattern.v000066400000000000000000000025701516144147600201250ustar00rootroot00000000000000(* Test pattern with dependent occurrences; Note that it does not behave as the succession of three generalize because each quantification introduces new occurrences that are automatically abstracted with the numbering still based on the original statement *) Goal (id true,id false)=(id true,id true). generalize bool at 2 4 6 8 10 as B, true at 3 as tt, false as ff. Abort. (* Check use of occurrences in hypotheses for a reduction tactic such as pattern *) (* Did not work in 8.2 *) Goal 0=0->True. intro H. pattern 0 in H at 2. set (f n := 0 = n) in H. (* check pattern worked correctly *) Abort. (* Syntactic variant which was working in 8.2 *) Goal 0=0->True. intro H. pattern 0 at 2 in H. set (f n := 0 = n) in H. (* check pattern worked correctly *) Abort. (* Ambiguous occurrence selection *) Goal 0=0->True. intro H. pattern 0 at 1 in H at 2 || exact I. (* check pattern fails *) Qed. (* Ambiguous occurrence selection *) Goal 0=1->True. intro H. pattern 0, 1 in H at 1 2 || exact I. (* check pattern fails *) Qed. (* Occurrence selection shared over hypotheses is difficult to advocate and hence no longer allowed *) Goal 0=1->1=0->True. intros H1 H2. pattern 0 at 1, 1 in H1, H2 || exact I. (* check pattern fails *) Qed. (* Test catching of reduction tactics errors (was not the case in 8.2) *) Goal eq_refl 0 = eq_refl 0. pattern 0 at 1 || reflexivity. Qed. rocq-9.2.0/test-suite/success/pattern_genarg.v000066400000000000000000000002021516144147600214360ustar00rootroot00000000000000 Succeed Hint Resolve O | nat : core. Fail Hint Resolve O | ltac:(idtac) : core. Fail Hint Resolve O | ltac:(exact nat) : core. rocq-9.2.0/test-suite/success/polymorphism.v000066400000000000000000000332611516144147600212130ustar00rootroot00000000000000Unset Strict Universe Declaration. Module ParseSet. Check eq_refl : Type@{0} = Set. Check Set : Type@{1}. Fail Check Type@{1} : Type@{2}. (* it parses but +2 is currently not allowed *) Polymorphic Definition id A (a:A) := a. Check eq_refl : id@{0} = id@{Set}. (* currently does not parse *) (* Check id@{1}. *) Sort s. Check Type@{s; 0} : Type@{1}. Polymorphic Definition apply A B (f:A -> B) x := f x. Check eq_refl : apply@{0 0} = apply@{Set Set}. End ParseSet. Module withoutpoly. Inductive empty :=. Inductive emptyt : Type :=. Inductive singleton : Type := single. Inductive singletoninfo : Type := singleinfo : unit -> singletoninfo. Inductive singletonset : Set := singleset. Inductive singletonnoninfo : Type := singlenoninfo : empty -> singletonnoninfo. Inductive singletoninfononinfo : Prop := singleinfononinfo : unit -> singletoninfononinfo. Inductive bool : Type := | true | false. Inductive smashedbool : Prop := | trueP | falseP. End withoutpoly. Set Universe Polymorphism. Inductive empty :=. Inductive emptyt : Type :=. Inductive singleton : Type := single. Inductive singletoninfo : Type := singleinfo : unit -> singletoninfo. Inductive singletonset : Set := singleset. Inductive singletonnoninfo : Type := singlenoninfo : empty -> singletonnoninfo. Inductive singletoninfononinfo : Prop := singleinfononinfo : unit -> singletoninfononinfo. Inductive bool : Type := | true | false. Inductive smashedbool : Prop := | trueP | falseP. Section foo. Let T := Type. Inductive polybool : T := | trueT | falseT. End foo. Inductive list (A: Type) : Type := | nil : list A | cons : A -> list A -> list A. Module ftypSetSet. Inductive ftyp : Type := | Funit : ftyp | Ffun : list ftyp -> ftyp | Fref : area -> ftyp with area : Type := | Stored : ftyp -> area . End ftypSetSet. Module ftypSetProp. Inductive ftyp : Type := | Funit : ftyp | Ffun : list ftyp -> ftyp | Fref : area -> ftyp with area : Type := | Stored : (* ftyp -> *)area . End ftypSetProp. Module ftypSetSetForced. Inductive ftyp : Type := | Funit : ftyp | Ffun : list ftyp -> ftyp | Fref : area -> ftyp with area : Set (* Type *) := | Stored : (* ftyp -> *)area . End ftypSetSetForced. Unset Universe Polymorphism. Set Printing Universes. Module Easy. Polymorphic Inductive prod (A : Type) (B : Type) : Type := pair : A -> B -> prod A B. Check prod nat nat. Print Universes. Polymorphic Inductive sum (A B:Type) : Type := | inl : A -> sum A B | inr : B -> sum A B. Print sum. Check (sum nat nat). End Easy. Section Hierarchy. Definition Type3 := Type. Definition Type2 := Type : Type3. Definition Type1 := Type : Type2. Definition id1 := ((forall A : Type1, A) : Type2). Definition id2 := ((forall A : Type2, A) : Type3). Definition id1' := ((forall A : Type1, A) : Type3). Fail Definition id1impred := ((forall A : Type1, A) : Type1). End Hierarchy. Record hypo : Type := mkhypo { hypo_type : Type; hypo_proof : hypo_type }. Definition typehypo (A : Type) : hypo := {| hypo_proof := A |}. Polymorphic Record dyn : Type := mkdyn { dyn_type : Type; dyn_proof : dyn_type }. Definition monotypedyn (A : Type) : dyn := {| dyn_proof := A |}. Polymorphic Definition typedyn (A : Type) : dyn := {| dyn_proof := A |}. Definition atypedyn : dyn := typedyn Type. Definition projdyn := dyn_type atypedyn. Definition nested := {| dyn_type := dyn; dyn_proof := atypedyn |}. Definition nested2 := {| dyn_type := dyn; dyn_proof := nested |}. Definition projnested2 := dyn_type nested2. Polymorphic Definition nest (d : dyn) := {| dyn_proof := d |}. Polymorphic Definition twoprojs (d : dyn) := dyn_proof d = dyn_proof d. Module binders. Definition mynat@{|} := nat. Definition foo@{i j | i < j, i < j} (A : Type@{i}) : Type@{j}. exact A. Defined. Polymorphic Lemma hidden_strict_type : Type. Proof. exact Type. Qed. Check hidden_strict_type@{_}. Fail Check hidden_strict_type@{Set}. Fail Definition morec@{i j|} (A : Type@{i}) : Type@{j} := A. (* By default constraints are extensible *) Polymorphic Definition morec@{i j} (A : Type@{i}) : Type@{j} := A. Check morec@{_ _}. (* Handled in proofs as well *) Lemma bar@{i j | } : Type@{i}. exact Type@{j}. Fail Defined. Abort. Fail Lemma bar@{u v | } : let x := (fun x => x) : Type@{u} -> Type@{v} in nat. Fail Fixpoint fbar@{u v | } (n:nat) : let x := (fun x => x) : Type@{u} in nat. Lemma bar@{i j| i < j} : Type@{j}. Proof. exact Type@{i}. Qed. Lemma barext@{i j|+} : Type@{j}. Proof. exact Type@{i}. Qed. Monomorphic Universe M. Fail Definition with_mono@{u|} : Type@{M} := Type@{u}. Definition with_mono@{u|u < M} : Type@{M} := Type@{u}. End binders. #[universes(polymorphic)] Section cats. Local Set Universe Polymorphism. Definition fibration (A : Type) := A -> Type. Definition Hom (A : Type) := A -> A -> Type. Record sigma (A : Type) (P : fibration A) := { proj1 : A; proj2 : P proj1} . Class Identity {A} (M : Hom A) := identity : forall x, M x x. Class Inverse {A} (M : Hom A) := inverse : forall x y:A, M x y -> M y x. Class Composition {A} (M : Hom A) := composition : forall {x y z:A}, M x y -> M y z -> M x z. Notation "g Β° f" := (composition f g) (at level 50). Class Equivalence T (Eq : Hom T):= { Equivalence_Identity :: Identity Eq ; Equivalence_Inverse :: Inverse Eq ; Equivalence_Composition :: Composition Eq }. Class EquivalenceType (T : Type) : Type := { m2: Hom T; equiv_struct :: Equivalence T m2 }. Polymorphic Record cat (T : Type) := { cat_hom : Hom T; cat_equiv : forall x y, EquivalenceType (cat_hom x y) }. Definition catType := sigma Type cat. Notation "[ T ]" := (proj1 T). From Corelib.Program Require Import Basics Tactics Wf. Program Definition small_cat : cat Empty_set := {| cat_hom x y := unit |}. Next Obligation. refine ({|m2:=fun x y => True|}). constructor; red; intros; trivial. Defined. Record iso (T U : Set) := { f : T -> U; g : U -> T }. Program Definition Set_cat : cat Set := {| cat_hom := iso |}. Next Obligation. refine ({|m2:=fun x y => True|}). constructor; red; intros; trivial. Defined. Record isoT (T U : Type) := { isoT_f : T -> U; isoT_g : U -> T }. Program Definition Type_cat : cat Type := {| cat_hom := isoT |}. Next Obligation. refine ({|m2:=fun x y => True|}). constructor; red; intros; trivial. Defined. Polymorphic Record cat1 (T : Type) := { cat1_car : Type; cat1_hom : Hom cat1_car; cat1_hom_cat : forall x y, cat (cat1_hom x y) }. End cats. Polymorphic Definition id {A : Type} (a : A) : A := a. Definition typeid := (@id Type). Fail Check (Prop : Set). Fail Check (Set : Set). Check (Set : Type). Check (Prop : Type). Definition setType := ltac:(let t := type of Set in exact t). Definition foo (A : Prop) := A. Fail Check foo Set. Check fun A => foo A. Fail Check fun A : Type => foo A. Check fun A : Prop => foo A. Fail Definition bar := fun A : Set => foo A. Fail Check (let A := Type in foo (id A)). Definition fooS (A : Set) := A. Check (let A := nat in fooS (id A)). Fail Check (let A := Set in fooS (id A)). Fail Check (let A := Prop in fooS (id A)). (* Some tests of sort-polymorphisme *) #[universes(polymorphic)] Section S. Polymorphic Variable A:Type. (* Definition f (B:Type) := (A * B)%type. *) Polymorphic Inductive I (B:Type) : Type := prod : A->B->I B. Check I nat. End S. (* Check f nat nat : Set. *) Definition foo' := I nat nat. Print Universes. Print foo. Set Printing Universes. Print foo. (* Polymorphic axioms: *) Polymorphic Axiom funext : forall (A B : Type) (f g : A -> B), (forall x, f x = g x) -> f = g. (* Check @funext. *) (* Check funext. *) Polymorphic Definition fun_ext (A B : Type) := forall (f g : A -> B), (forall x, f x = g x) -> f = g. Polymorphic Class Funext A B := extensional : fun_ext A B. Section foo2. Context `{forall A B, Funext A B}. Print Universes. End foo2. Module eta. Set Universe Polymorphism. Set Printing Universes. Axiom admit : forall A, A. Record R := {O : Type}. Definition RL (x : R@{i}) : ltac:(let u := constr:(Type@{i}:Type@{j}) in exact (R@{j}) ) := {|O := @O x|}. Definition RLRL : forall x : R, RL x = RL (RL x) := fun x => eq_refl. Definition RLRL' : forall x : R, RL x = RL (RL x). intros. apply eq_refl. Qed. End eta. Module Hurkens'. Require Import TestSuite.hurkens. Polymorphic Record box (X : Type) (T := Type) : Type := wrap { unwrap : T }. Definition unwrap' := fun (X : Type) (b : box X) => let (unw) := b in unw. Fail Definition bad : False := TypeNeqSmallType.paradox (unwrap' Type (wrap _ Type)) eq_refl. End Hurkens'. Module Anonymous. Set Universe Polymorphism. Definition defaultid := (fun x => x) : Type -> Type. Definition collapseid := defaultid@{_ _}. Check collapseid@{_}. Definition anonid := (fun x => x) : Type -> Type@{_}. Check anonid@{_}. Definition defaultalg := (fun x : Type => x) (Type : Type). Definition usedefaultalg := defaultalg@{_ _ _}. Check usedefaultalg@{_ _}. Definition anonalg := (fun x : Type@{_} => x) (Type : Type). Check anonalg@{_ _}. Definition unrelated@{i j} := nat. Definition useunrelated := unrelated@{_ _}. Check useunrelated@{_ _}. Definition inthemiddle@{i j k} := let _ := defaultid@{i j} in anonalg@{k j}. (* i <= j < k *) Definition collapsethemiddle := inthemiddle@{i _ j}. Check collapsethemiddle@{_ _}. End Anonymous. Module Restrict. (* Universes which don't appear in the term should be pruned, unless they have names *) Set Universe Polymorphism. Ltac exact0 := let x := constr:(Type) in exact 0. Definition dummy_pruned@{} : nat := ltac:(exact0). Definition named_not_pruned@{u} : nat := 0. Check named_not_pruned@{_}. Definition named_not_pruned_nonstrict : nat := ltac:(let x := constr:(Type@{u}) in exact 0). Check named_not_pruned_nonstrict@{_}. Lemma lemma_restrict_poly@{} : nat. Proof. exact0. Defined. Unset Universe Polymorphism. Lemma lemma_restrict_mono_qed@{} : nat. Proof. exact0. Qed. Lemma lemma_restrict_abstract@{} : nat. Proof. abstract exact0. Qed. End Restrict. Module F. #[warning="context-outside-section"] Context {A B : Type}. Definition foo : Type := B. End F. Set Universe Polymorphism. Cumulative Record box (X : Type) (T := Type) : Type := wrap { unwrap : T }. Section test_letin_subtyping. Universe i j k i' j' k'. Constraint j < j'. Context (W : Type) (X : box@{i j k} W). Definition Y := X : box@{i' j' k'} W. Universe i1 j1 k1 i2 j2 k2. Constraint i1 < i2. Constraint k2 < k1. Context (V : Type). Definition Z : box@{i1 j1 k1} V := {| unwrap := V |}. Definition Z' : box@{i2 j2 k2} V := {| unwrap := V |}. Lemma ZZ' : @eq (box@{i2 j2 k2} V) Z Z'. Proof. Set Printing All. Set Printing Universes. cbv. reflexivity. Qed. End test_letin_subtyping. Module ObligationRegression. (** Test for a regression encountered when fixing obligations for stronger restriction of universe context. *) Require Import CMorphisms. Check trans_co_eq_inv_arrow_morphism@{_ _ _ _ _ _ _}. End ObligationRegression. Axiom poly@{i} : forall(A : Type@{i}) (a : A), unit. Definition nonpoly := @poly True Logic.I. Definition check := nonpoly@{}. Module ProgramFixpoint. Local Set Universe Polymorphism. Program Fixpoint f@{u} (A:Type@{u}) (n:nat) : Type@{u} := match n with 0 => A | S n => f (A->A) n end. Check f@{Set}. (* Check that it depends on only one universe *) End ProgramFixpoint. Module EarlyPolyUniverseDeclarationCheck. Local Set Universe Polymorphism. Fail Definition f@{u} n : match n return Type@{v} with 0 => Type@{u} | _ => Type@{u} end. Definition f@{u v} n : match n return Type@{v} with 0 => Type@{u} | _ => Type@{u} end. exact (match n with 0 => nat | _ => nat end). Defined. Program Fixpoint f'@{u} (A:Type@{u}) (n:nat) : Type@{u} := match n with 0 => _ | S n => f' (A->A) n end. Next Obligation. exact nat. Defined. Fail Program Fixpoint f''@{u} (A:Type@{u}) (n:nat) {measure n} : Type@{u} := match n with 0 => _ | S n => f'' (Type->A) n end. Local Set Universe Polymorphism. Program Fixpoint f''@{u} (A:Type@{u}) (n:nat) {measure n} : Type@{u} := match n with 0 => _ | S n => f'' (A->A) n end. Next Obligation. Show. exact nat. Defined. Next Obligation. Show. Admitted. End EarlyPolyUniverseDeclarationCheck. Module EarlyMonoUniverseDeclarationCheck. Local Unset Universe Polymorphism. Fail Definition f@{u} n : match n return Type@{v} with 0 => Type@{u} | _ => Type@{u} end. Definition f@{u v} n : match n return Type@{v} with 0 => Type@{u} | _ => Type@{u} end. exact (match n with 0 => nat | _ => nat end). Defined. Fail Program Fixpoint f'@{u} (A:Type@{u}) (n:nat) : Type@{u} := (* By convention, we require extensibility for Program *) match n with 0 => _ | S n => f' (A->A) n end. Program Fixpoint f'@{u +} (A:Type@{u}) (n:nat) : Type@{u} := match n with 0 => _ | S n => f' (A->A) n end. Next Obligation. exact nat. Defined. Fail Program Fixpoint f''@{u} (A:Type@{u}) (n:nat) {measure n} : Type@{u} := match n with 0 => _ | S n => f'' (Type->A) n end. Fail Program Fixpoint f''@{u} (A:Type@{u}) (n:nat) {measure n} : Type@{u} := (* By convention, we require extensibility for Program *) match n with 0 => _ | S n => f'' (A->A) n end. Program Fixpoint f''@{u +} (A:Type@{u}) (n:nat) {measure n} : Type@{u} := match n with 0 => _ | S n => f'' (A->A) n end. Next Obligation. Show. exact nat. Defined. Next Obligation. Show. Admitted. End EarlyMonoUniverseDeclarationCheck. rocq-9.2.0/test-suite/success/pose.v000066400000000000000000000002151516144147600174100ustar00rootroot00000000000000(* Test syntax *) Goal 0=0. pose proof (a := I). Fail clearbody a. epose proof (b := fun _ => eq_refl). Fail clearbody b. exact (b a). Qed. rocq-9.2.0/test-suite/success/primitive.v000066400000000000000000000042201516144147600204520ustar00rootroot00000000000000(* This file mostly tests for the error paths in declaring primitives. Successes are tested in the various test-suite/primitive/* directories *) (* [Primitive] should be forbidden in sections, otherwise its type after cooking will be incorrect. *) Section S. Variable A : Type. Fail Primitive int : let x := A in Set := #int63_type. Fail Primitive int := #int63_type. (* we fail even if section variable not used *) End S. Section S. Fail Primitive int := #int63_type. (* we fail even if no section variables *) End S. (* can't declare primitives with nonsense types *) Fail Primitive xx : nat := #int63_type. (* non-cumulative conversion *) Fail Primitive xx : Type := #int63_type. (* check evars *) Fail Primitive xx : let x := _ in Set := #int63_type. (* explicit type is unified with expected type, not just converted extra universes are OK for monomorphic primitives (even though their usefulness is questionable, there's no difference compared with predeclaring them) *) Primitive xx : let x := Type in _ := #int63_type. (* double declaration *) Fail Primitive yy := #int63_type. Module DoubleCarry. (* XXX maybe should be an output test: this is the case where the new declaration is already in the nametab so can be nicely printed *) Module M. Variant carry (A : Type) := | C0 : A -> carry A | C1 : A -> carry A. Register carry as kernel.ind_carry. End M. Module N. Variant carry (A : Type) := | C0 : A -> carry A | C1 : A -> carry A. Fail Register carry as kernel.ind_carry. End N. End DoubleCarry. (* univ polymorphic primitives *) (* universe count must be as expected *) Fail Primitive array@{u v} : Type@{u} -> Type@{v} := #array_type. (* use a phantom universe to ensure we check conversion not just the universe count *) Fail Primitive array@{u} : Set -> Set := #array_type. (* no constraints allowed! *) Fail Primitive array@{u | Set < u} : Type@{u} -> Type@{u} := #array_type. (* unification works for polymorphic primitives too (although universe counts mean it's not enough) *) Fail Primitive array : let x := Type in _ -> Type := #array_type. Primitive array : _ -> Type := #array_type. rocq-9.2.0/test-suite/success/primitive_strategy.v000066400000000000000000000010151516144147600223730ustar00rootroot00000000000000#[projections(primitive)] Record r := R { f : unit }. Definition rv := {| f := tt |}. Module Reduction. Ltac syn_eq := lazymatch goal with |- tt = tt => reflexivity end. Goal rv.(f) = tt. Proof. Succeed lazy; syn_eq. Fail with_strategy opaque [f] lazy; syn_eq. Succeed cbn; syn_eq. Fail with_strategy opaque [f] cbn; syn_eq. Succeed simpl; syn_eq. Fail with_strategy opaque [f] simpl; syn_eq. Succeed cbv; syn_eq. Fail with_strategy opaque [f] cbv; syn_eq. Abort. End Reduction. rocq-9.2.0/test-suite/success/primitive_tc.v000066400000000000000000000062151516144147600211460ustar00rootroot00000000000000Create HintDb test discriminated. (* Testing that projections can be made hint opaque. *) Module ProjOpaque. #[projections(primitive)] Record bla := { x : unit }. Definition bli := {| x := tt |}. Class C (p : unit) := {}. Definition I : C (x bli) := Build_C _. #[local] Hint Resolve I : test. #[local] Hint Opaque x : test. Goal C tt. Proof. Fail typeclasses eauto with test. Abort. End ProjOpaque. (* Testing that compatibility constants are equated with their projections in the bnet. *) Module CompatConstants. Class T (p : Prop) : Prop := {}. Axiom prod : Prop -> Prop -> Prop. Axiom T_prod : forall p1 p2, T p1 -> T p2 -> T (prod p1 p2). Axiom T_True : T True. Class F (f : unit -> Prop) : Prop := { F_T :: forall u, T (f u) }. #[projections(primitive)] Record R (useless : unit) : Type := { v : unit -> Prop; v_F : F (v); }. Hint Opaque v : test. Hint Resolve v_F F_T T_prod T_True : test. (* Notation constant := (@v tt). *) Goal forall (a : R tt) q, T (prod (v _ a q) (True)). Proof. intros a. (* [v _ a] gets turned into its compatibility constant by the application of [T_prod]. The application of [v_F] after [F_T] only works if the bnet correctly equates the compatibility constant with the projection used in the type and pattern of [v_F] *) typeclasses eauto with test. Qed. End CompatConstants. (* Testing that projection opacity settings are properly discharged at the end of sections. *) Module Sections. #[local] Hint Constants Opaque : test. #[local] Hint Projections Opaque : test. Class C (u : unit) := {}. Definition i : C tt := Build_C _. #[global] Hint Resolve i : test. Section S. Context (P : Prop). (* Load bearing [Context] but content does not matter! *) #[projections(primitive)] Record r := R { v : unit; prf : P }. (* Load bearing use of the [Context] *) #[global] Hint Transparent v : test. Definition x (p: P) := {| v := tt; prf := p|}. #[global] Hint Transparent x : test. Print HintDb test. (* [v] is transparent *) Goal forall p, C (v (x p)). Proof. intros. typeclasses eauto with test. (* [i] is a candidate, [v] must be transparent *) Qed. End S. Print HintDb test. (* [v] is reportedly transparent *) Goal forall P (p : P), C (v P (x P p)). Proof. intros. typeclasses eauto with test. (* This will fail if [Hint Transparent v] is improperly discharged. *) Qed. End Sections. Module HintExtern. #[projections(primitive)] Record bi (x : True) : Type := BI {car : Type; foo : car}. Axiom x : True. Axiom PROP:bi x. Inductive Fwd (P : car x PROP) : Prop := MKFWD. Create HintDb db discriminated. #[local] Hint Opaque foo : test. Module ConstantPattern. #[local] Hint Extern 0 (Fwd (@foo x PROP)) => constructor : test. Goal Fwd (@foo x PROP). Proof. intros. typeclasses eauto with test. Qed. End ConstantPattern. Module ProjPattern. #[local] Hint Extern 0 (Fwd (PROP.(@foo x))) => constructor : test. Goal Fwd (@foo x PROP). Proof. intros. typeclasses eauto with test. Qed. End ProjPattern. End HintExtern. rocq-9.2.0/test-suite/success/primitiveproj.v000066400000000000000000000146631516144147600213610ustar00rootroot00000000000000Set Primitive Projections. Set Nonrecursive Elimination Schemes. Module Prim. Record F := { a : nat; b : a = a }. Record G (A : Type) := { c : A; d : F }. Check c. End Prim. Module Univ. Set Universe Polymorphism. Set Implicit Arguments. Record Foo (A : Type) := { foo : A }. Record G (A : Type) := { c : A; d : c = c; e : Foo A }. Definition Foon : Foo nat := {| foo := 0 |}. Definition Foonp : nat := Foon.(foo). Definition Gt : G nat := {| c:= 0; d:=eq_refl; e:= Foon |}. Check (Gt.(e)). Section bla. Record bar := { baz : nat; def := 0; baz' : forall x, x = baz \/ x = def }. End bla. End Univ. Set Primitive Projections. Unset Elimination Schemes. Set Implicit Arguments. Check nat. Inductive X (U:Type) := { k : nat; a: k = k -> X U; b : let x := a eq_refl in X U }. Parameter x:X nat. Check (a x : forall _ : @eq nat (k x) (k x), X nat). Check (b x : X nat). Inductive Y := { next : option Y }. Check _.(next) : option Y. Lemma eta_ind (y : Y) : y = Build_Y y.(next). Proof. Fail reflexivity. Abort. Inductive Fdef := { Fa : nat ; Fb := Fa; Fc : Fdef }. Fail Scheme Fdef_rec := Induction for Fdef Sort Prop. (* Rules for parsing and printing of primitive projections and their eta expansions. If r : R A where R is a primitive record with implicit parameter A. If p : forall {A} (r : R A) {A : Set}, list (A * B). *) Record R {A : Type} := { p : forall {X : Set}, A * X }. Arguments R : clear implicits. Record R' {A : Type} := { p' : forall X : Set, A * X }. Arguments R' : clear implicits. Unset Printing All. Parameter r : R nat. Check (r.(p)). Set Printing Projections. Check (r.(p)). Unset Printing Projections. Set Printing All. Check (r.(p)). Unset Printing All. (* Check (r.(p)). Elaborates to a primitive application, X arg implicit. Of type nat * ?ex No Printing All: p r Set Printing Projections.: r.(p) Printing All: r.(@p) ?ex *) Check p r. Set Printing Projections. Check p r. Unset Printing Projections. Set Printing All. Check p r. Unset Printing All. Check p r (X:=nat). Set Printing Projections. Check p r (X:=nat). Unset Printing Projections. Set Printing All. Check p r (X:=nat). Unset Printing All. (* Same elaboration, printing for p r *) (** Explicit version of the primitive projection, under applied w.r.t implicit arguments can be printed only using projection notation. r.(@p) *) Check r.(@p _). Set Printing Projections. Check r.(@p _). Unset Printing Projections. Set Printing All. Check r.(@p _). Unset Printing All. (** Explicit version of the primitive projection, applied to its implicit arguments can be printed using application notation r.(p), r.(@p) in fully explicit form *) Check r.(@p _) nat. Set Printing Projections. Check r.(@p _) nat. Unset Printing Projections. Set Printing All. Check r.(@p _) nat. Unset Printing All. Parameter r' : R' nat. Check (r'.(p')). Set Printing Projections. Check (r'.(p')). Unset Printing Projections. Set Printing All. Check (r'.(p')). Unset Printing All. (* Check (r'.(p')). Elaborates to a primitive application, X arg explicit. Of type forall X : Set, nat * X No Printing All: p' r' Set Printing Projections.: r'.(p') Printing All: r'.(@p') *) Check p' r'. Set Printing Projections. Check p' r'. Unset Printing Projections. Set Printing All. Check p' r'. Unset Printing All. (* Same elaboration, printing for p r *) (** Explicit version of the primitive projection, under applied w.r.t implicit arguments can be printed only using projection notation. r.(@p) *) Check r'.(@p' _). Set Printing Projections. Check r'.(@p' _). Unset Printing Projections. Set Printing All. Check r'.(@p' _). Unset Printing All. (** Explicit version of the primitive projection, applied to its implicit arguments can be printed only using projection notation r.(p), r.(@p) in fully explicit form *) Check p' r' nat. Set Printing Projections. Check p' r' nat. Unset Printing Projections. Set Printing All. Check p' r' nat. Unset Printing All. Check (@p' nat). Check p'. Set Printing All. Check (@p' nat). Check p'. Unset Printing All. Record wrap (A : Type) := { unwrap : A; unwrap2 : A }. Definition term (x : wrap nat) := x.(unwrap). Definition term' (x : wrap nat) := let f := (@unwrap2 nat) in f x. Require Corelib.extraction.Extraction. Recursive Extraction term term'. Extraction TestCompile term term'. (*Unset Printing Primitive Projection Parameters.*) (* Primitive projections in the presence of let-ins (was not failing in beta3)*) Set Primitive Projections. Record s (x:nat) (y:=S x) := {c:=x; d:x=c}. Lemma f : 0=1. Proof. Fail apply d. (* split. reflexivity. Qed. *) Abort. (* Primitive projection match compilation *) Set Primitive Projections. Record prod (A B : Type) := pair { fst : A ; snd : B }. Arguments pair {_ _} _ _. Definition snd' := @snd. (* a match which is just a projection doesn't produce a bunch of letins *) Goal True. assert (v : prod nat bool) by admit. let unfolded_snd := eval cbv beta delta [snd' snd] in (snd' v) in let matched_snd := constr:(let 'pair _ x := v in x) in constr_eq unfolded_snd matched_snd. Abort. Fixpoint split_at {A} (l : list A) (n : nat) : prod (list A) (list A) := match n with | 0 => pair nil l | S n => match l with | nil => pair nil nil | cons x l => let 'pair l1 l2 := split_at l n in pair (cons x l1) l2 end end. Section Repeat. Variable A : Type. Fixpoint repeat (x : A) (n: nat ) := match n with | O => nil | S k => cons x (repeat x k) end. End Repeat. Time Eval vm_compute in split_at (repeat 0 20) 10. (* Takes 0s *) Time Eval vm_compute in split_at (repeat 0 40) 20. (* Takes 0.001s *) Timeout 1 Time Eval vm_compute in split_at (repeat 0 60) 30. (* Used to take 60s, now takes 0.001s *) Check (@eq_refl _ 0 <: 0 = fst (pair 0 1)). Fail Check (@eq_refl _ 0 <: 0 = snd (pair 0 1)). Check (@eq_refl _ 0 <<: 0 = fst (pair 0 1)). Fail Check (@eq_refl _ 0 <<: 0 = snd (pair 0 1)). (* [unfold] tactic *) Module Unfold. Record rec (P: Prop) := REC { v: unit }. Set Printing All. Set Printing Unfolded Projection As Match. (* Testing that [unfold] can unfold compatibility constants. *) Goal forall r: rec True, @v True r = tt. Proof. intros. lazymatch goal with | |- context C [@v _ ?r] => (* Carefully construct a term that definitely contains the compatibility constant. *) let t := constr:(@v True) in let g := context C [t r] in change g end. progress unfold v. Abort. End Unfold. rocq-9.2.0/test-suite/success/primproj_evarconv.v000066400000000000000000000036731516144147600222220ustar00rootroot00000000000000Module S. #[local] Set Printing Unfolded Projection As Match. #[projections(primitive=yes)] Record r (u : unit) := { r_car : Type }. Axiom u : unit. Definition rO : r u -> r u := fun o => {| r_car := option (r_car u o) |}. Goal forall o, exists M, M (r_car u o)= r_car u (rO o). Proof. intros. eexists _. Timeout 1 refine (eq_refl _). Qed. End S. Module T. #[local] Set Printing Unfolded Projection As Match. #[projections(primitive=yes)] Record r (u : unit) := { r_car : Type }. Axiom u : unit. Axiom v : forall i : nat, r u. Goal forall i, exists P, P (v i) = r_car u (v i). Proof. intros. eexists _. (* Unable to unify "r (v i)" with "?P (v i)". *) refine (eq_refl _). Qed. End T. (* Here we test that CS inference happens even if the projection is primitive and the projected term has a type that is not an inductive (but rather an evar). We exploit the fact that Coq considers are well typed terms containing evars for which a suspended unif problem exists. *) Require Import Ltac2.Ltac2 Ltac2.Unification Ltac2.Constr Ltac2.Printf. Module U. #[projections(primitive=yes)] Record r := R { r_car : Type }. #[projections(primitive=yes)] Record s := S { s_car : Type }. (* The type of the CS instance will help unification make a choice for the (_ : _ r) problem below *) Canonical Structure foo (x : s): (fun x=>x) r := R (s_car x). Axiom a : s. Goal True. Ltac2 Eval let t1 := open_constr:( ( _ : _ r ).(r_car) ) in (* the problem mentioned above *) let t2 := constr:( (a).(s_car) ) in (* safeguard against parser *) match (Constr.Unsafe.kind t1) with | Constr.Unsafe.Proj _ _ _ => () | _ => fail end; match (Constr.Unsafe.kind t2) with | Constr.Unsafe.Proj _ _ _ => () | _ => fail end; (* printf "%t = %t" t1 t2; *) unify_with_full_ts t1 t2; (* fails before #19358 *) (* printf "%t = %t" t1 t2. *) (). Abort. End U. rocq-9.2.0/test-suite/success/primproj_ssreflect.v000066400000000000000000000025501516144147600223620ustar00rootroot00000000000000From Corelib Require Import ssreflect. Module R. #[local] Set Printing Unfolded Projections As Match. Record seal {A : Type} (f : A) : Type := Build_seal { unseal : A; seal_eq : @eq A unseal f }. Global Arguments unseal {_ _} _ : assert. Global Arguments seal_eq {_ _} _ : assert. #[projections(primitive=yes)] Structure bi := Bi { bi_car :> Type; bi_forall : forall A : Type, (A -> bi_car) -> bi_car; }. Bind Scope bi_scope with bi_car. Global Arguments bi_car : simpl never. Global Arguments bi_forall {PROP _} _ : simpl never, rename. Record heapProp := HeapProp { heapProp_holds :> Prop }. Global Arguments heapProp_holds : simpl never. Definition heapProp_forall_def {A} (Ξ¨ : A -> heapProp) : heapProp := {| heapProp_holds := forall a, Ξ¨ a |}. Definition heapProp_forall_aux : seal (@heapProp_forall_def). Proof. by eexists. Qed. Definition heapProp_forall {A} := unseal heapProp_forall_aux A. Definition heapProp_forall_unseal : @heapProp_forall = @heapProp_forall_def := seal_eq heapProp_forall_aux. Definition heapPropI : bi := {| bi_car := heapProp; bi_forall := @heapProp_forall |}. Axiom P : heapPropI. Goal forall (A : Type) (Ο† : A -> Prop), (bi_forall (fun a : A => P)). Proof. intros A Ο†. Succeed (progress unfold bi_forall); (progress simpl). progress rewrite /bi_forall. Abort. End R. rocq-9.2.0/test-suite/success/primproj_tactic_unif.v000066400000000000000000000057471516144147600226730ustar00rootroot00000000000000Module S. #[local] Set Printing Unfolded Projection As Match. #[projections(primitive=yes)] Record state (u : unit) := { p : nat -> nat }. Parameter (u : unit). Parameter (s1 s2 : state u). (* Unifying the compatibility constant with the primitive projection *) Goal exists n, ltac:(exact (p u)) s1 n = p _ s1 1. Proof. eexists _. (* Testing both orientations of the unification problem *) lazymatch goal with |- ?a = ?b => unify a b end. lazymatch goal with |- ?a = ?b => unify b a end. Succeed apply eq_refl. symmetry. apply eq_refl. Qed. (* Unifying primitive projections with [?h ?a1 .. ?aN] when [N] is bigger than the number of parameters plus 1. This must fail. *) Axiom H : forall (B : Type) (f : forall (_ : nat) (_ : nat) (_ : nat), B) (x1 y1 x2 y2 x3 y3 : nat), @eq B (f x1 x2 x3) (f y1 y2 y3). Goal p _ s1 = p _ s2. Proof. (* [apply H] never succeeds. The test below only makes sure that it does not loop endlessly or overflow the stack. *) Timeout 1 (first [apply H | idtac]). Abort. (* Unifying primitive projections with [?h ?a1 .. ?aN] when [N] is exactly the number of parameters plus 1. This must succeed. *) Goal exists (a : forall u, state u -> nat -> nat) (b : unit) c, a b c = p u s1. Proof. eexists _, _, _. (* Testing both orientations of the unification problem *) Succeed apply eq_refl. symmetry. apply eq_refl. Qed. (* Unifying primitive projections with [?h ?a1 .. ?aN] when [N] is exactly the number of parameters plus 1 plus the number of proper arguments to the projection. This must succeed. *) Goal exists (a : forall u, state u -> nat -> nat) (b : unit) c d, a b c d = p u s1 0. Proof. eexists _, _, _, _. (* Testing both orientations of the unification problem *) Succeed apply eq_refl. symmetry. apply eq_refl. Qed. (* Unifying primitive projections with [?h ?a1 .. ?aN] when [N] is less than the number of parameters plus 1 plus the number of proper arguments to the projection. The head evar [?h] is unified with a partial application of the projection. This must succeed. *) Goal exists (a : state u -> nat -> nat) (b : state u), a b = p u s1. Proof. eexists _, _. (* Testing both orientations of the unification problem *) Succeed apply eq_refl. symmetry. apply eq_refl. Qed. End S. Module I. #[local] Set Printing Unfolded Projection As Match. Record cmra := Cmra { cmra_car : Type }. Record ucmra := { ucmra_car : Type }. #[projections(primitive=yes)] Record ofe (n : nat) := Ofe { ofe_car : Type }. Axiom n : nat. Definition ucmra_ofeO := fun A : ucmra => @Ofe n (ucmra_car A). (* Canonical Structure cmra_ofeO := fun A : cmra => @Ofe n (cmra_car A). *) Canonical Structure ucmra_cmraR := fun A : ucmra => Cmra (ucmra_car A). Axiom A : ucmra. Axiom bla : forall (A : cmra), cmra_car A. Goal ofe_car n (ucmra_ofeO A). Proof. apply @bla. Qed. End I. rocq-9.2.0/test-suite/success/private_univs.v000066400000000000000000000023161516144147600213440ustar00rootroot00000000000000Set Universe Polymorphism. Set Printing Universes. Definition internal_defined@{i j | i < j +} (A : Type@{i}) : Type@{j}. pose(foo:=Type). (* 1 universe for the let body + 1 for the type *) exact A. Fail Defined. Abort. Definition internal_defined@{i j +} (A : Type@{i}) : Type@{j}. pose(foo:=Type). exact A. Defined. Check internal_defined@{_ _ _ _}. Module M. Lemma internal_qed@{i j|i<=j} (A:Type@{i}) : Type@{j}. Proof. pose (foo := Type). exact A. Qed. Check internal_qed@{_ _}. End M. Include M. (* be careful to remove const_private_univs in Include! will be coqchk'd *) Unset Strict Universe Declaration. Lemma private_transitivity@{i j} (A:Type@{i}) : Type@{j}. Proof. pose (bar := Type : Type@{j}). pose (foo := Type@{i} : bar). exact bar. Qed. Definition private_transitivity'@{i j|i < j} := private_transitivity@{i j}. Fail Definition dummy@{i j|j <= i +} := private_transitivity@{i j}. Unset Private Polymorphic Universes. Lemma internal_noprivate_qed@{i j|i<=j} (A:Type@{i}) : Type@{j}. Proof. pose (foo := Type). exact A. Fail Qed. Abort. Lemma internal_noprivate_qed@{i j +} (A:Type@{i}) : Type@{j}. Proof. pose (foo := Type). exact A. Qed. Check internal_noprivate_qed@{_ _ _ _}. rocq-9.2.0/test-suite/success/proof_using.v000066400000000000000000000105251516144147600210010ustar00rootroot00000000000000Require Import TestSuite.admit. Section Foo. Variable a : nat. Lemma l1 : True. Fail Proof using non_existing. Proof using a. exact I. Qed. Lemma l2 : True. Proof using a. Admitted. Lemma l3 : True. Proof using a. admit. Qed. End Foo. Check (l1 3). Check (l2 3). Check (l3 3). Section Bar. Variable T : Type. Variable a b : T. Variable H : a = b. Lemma l4 : a = b. Proof using H. exact H. Qed. End Bar. Check (l4 _ 1 1 _ : 1 = 1). Section S1. Variable v1 : nat. Section S2. Variable v2 : nat. Lemma deep : v1 = v2. Proof using v1 v2. admit. Qed. Lemma deep2 : v1 = v2. Proof using v1 v2. Admitted. End S2. Check (deep 3 : v1 = 3). Check (deep2 3 : v1 = 3). End S1. Check (deep 3 4 : 3 = 4). Check (deep2 3 4 : 3 = 4). Section P1. Variable x : nat. Variable y : nat. Variable z : nat. Collection TOTO := x y. Collection TITI := TOTO - x. Lemma t1 : True. Proof using TOTO. trivial. Qed. Lemma t2 : True. Proof using TITI. trivial. Qed. Section P2. Collection TOTO := x. Lemma t3 : True. Proof using TOTO. trivial. Qed. End P2. Lemma t4 : True. Proof using TOTO. trivial. Qed. End P1. Lemma t5 : True. Fail Proof using TOTO. trivial. Qed. Check (t1 1 2 : True). Check (t2 1 : True). Check (t3 1 : True). Check (t4 1 2 : True). Section T1. Variable x : nat. Hypothesis px : 1 = x. Let w := x + 1. Set Suggest Proof Using. Set Default Proof Using "Type". Lemma bla : 2 = w. Proof. admit. Qed. End T1. Check (bla 7 : 2 = 8). Section A. Variable a : nat. Variable b : nat. Variable c : nat. Variable H1 : a = 3. Variable H2 : a = 3 -> b = 7. Variable H3 : c = 3. Lemma foo : a = a. Proof using Type*. pose H1 as e1. pose H2 as e2. reflexivity. Qed. Lemma bar : a = 3 -> b = 7. Proof using b*. exact H2. Qed. Lemma baz : c=3. Proof using c*. exact H3. Qed. Lemma baz2 : c=3. Proof using c* a. exact H3. Qed. End A. Check (foo 3 7 (refl_equal 3) (fun _ => refl_equal 7)). Check (bar 3 7 (refl_equal 3) (fun _ => refl_equal 7)). Check (baz2 99 3 (refl_equal 3)). Check (baz 3 (refl_equal 3)). Section Let. Variables a b : nat. Let pa : a = a. Proof. reflexivity. Qed. Unset Default Proof Using. Set Suggest Proof Using. Lemma test_let : a = a. Proof using a. exact pa. Qed. Let ppa : pa = pa. Proof. reflexivity. Qed. Lemma test_let2 : pa = pa. Proof using Type. exact ppa. Qed. End Let. Check (test_let 3). (* Disabled Section Clear. Variable a: nat. Hypotheses H : a = 4. Set Proof Using Clear Unused. Lemma test_clear : a = a. Proof using a. Fail rewrite H. trivial. Qed. End Clear. *) Module InteractiveUsing. Section S. Variable m : nat. Variable e : m = m. #[using="e"] Definition a := 0. #[using="e"] Definition a' : nat. exact 0. Defined. #[using="e"] Fixpoint f (n:nat) : nat := match n with 0 => 0 | S n => f n end. #[using="e"] Fixpoint f' (n:nat) : nat. exact (match n with 0 => 0 | S n => f n end). Defined. #[using="Type"] Fixpoint f1 (n:nat) : nat := match n with 0 => 0 | S n => match f2 n with eq_refl => n end end with f2 (n:nat) : m = m := match n with 0 => eq_refl | S n => match f1 n with 0 => eq_refl | S _ => eq_refl end end. #[using="Type"] Fixpoint f1' (n:nat) : nat with f2' (n:nat) : m = m. exact (match n with 0 => 0 | S n => match f2' n with eq_refl => n end end). exact (match n with 0 => eq_refl | S n => match f1' n with 0 => eq_refl | S _ => eq_refl end end). Defined. CoInductive Stream : Set := Cons : Stream -> Stream. #[using="e"] CoFixpoint g : Stream := Cons g. #[using="e"] CoFixpoint g' : Stream. exact (Cons g). Defined. #[using="e"] Lemma g1 (n:nat) : nat with g2 (n:nat) : m = m. exact (match n with 0 => 0 | S n => match g2 n with eq_refl => n end end). exact (match n with 0 => eq_refl | S n => match g1 n with 0 => eq_refl | S _ => eq_refl end end). Defined. #[using="Type"] Lemma g1' (n:nat) : nat with g2' (n:nat) : m = m. exact (match n with 0 => 0 | S n => match g2' n with eq_refl => n end end). exact (match n with 0 => eq_refl | S n => match g1' n with 0 => eq_refl | S _ => eq_refl end end). Defined. End S. Check eq_refl : a 0 (eq_refl 0) = 0. Check eq_refl : a' 0 (eq_refl 0) = 0. Check eq_refl : f 10 (eq_refl 10) 2 = 0. Check eq_refl : f' 10 (eq_refl 10) 2 = 0. Check eq_refl : f1 10 2 = 1. Check eq_refl : f1' 10 2 = 1. Check g 0 eq_refl : Stream. Check g' 0 eq_refl : Stream. Check eq_refl : g1 10 (eq_refl 10) 2 = 1. Check eq_refl : g1' 10 2 = 1. End InteractiveUsing. rocq-9.2.0/test-suite/success/proof_using_noinit.v000066400000000000000000000002101516144147600223470ustar00rootroot00000000000000(* -*- coq-prog-args: ("-noinit"); -*- *) Section A. Variable A : Prop. Hypothesis a : A. Lemma b : A. Proof using a. Admitted. End A. rocq-9.2.0/test-suite/success/rapply.v000066400000000000000000000016001516144147600177500ustar00rootroot00000000000000Require Import Corelib.Program.Tactics. (** We make a version of [rapply] that takes [uconstr]; we do not currently test what scope [rapply] interprets terms in. *) Tactic Notation "urapply" uconstr(p) := rapply p. Ltac test n := (*let __ := match goal with _ => idtac n end in*) lazymatch n with | O => let __ := match goal with _ => assert True by urapply I; clear end in uconstr:(fun _ => I) | S ?n' => let lem := test n' in let __ := match goal with _ => assert True by (unshelve urapply lem; try exact I); clear end in uconstr:(fun _ : True => lem) end. Goal True. assert True by urapply I. assert True by (unshelve urapply (fun _ => I); try exact I). assert True by (unshelve urapply (fun _ _ => I); try exact I). assert True by (unshelve urapply (fun _ _ _ => I); try exact I). clear. Time let __ := test 50 in idtac. urapply I. Qed. rocq-9.2.0/test-suite/success/record_field_coercion_tc.v000066400000000000000000000030371516144147600234370ustar00rootroot00000000000000Module RecordNothing. Class B. Record A := { ab : B }. Parameter a : A. Fail Check a : B. (* no coercion *) Existing Class A. Existing Instance a. Fail Type _ : B. (* no typeclass instance *) End RecordNothing. Module RecordCoercion. Class B. Record A := { ab :> B }. Parameter a : A. Check a : B. (* coercion *) Existing Class A. Existing Instance a. Fail Type _ : B. (* no typeclass instance *) End RecordCoercion. Module RecordTC. Class B. Record A := { ab :: B }. Parameter a : A. Fail Check a : B. (* no coercion *) Existing Class A. Existing Instance a. Type _ : B. (* typeclass instance *) End RecordTC. Module RecordCoercionTC. Class B. Record A := { ab ::> B }. Parameter a : A. Check a : B. (* coercion *) Existing Class A. Existing Instance a. Type _ : B. (* typeclass instance *) End RecordCoercionTC. Module ClassNothing. Class B. Class A := { ab : B }. Parameter a : A. Fail Check a : B. (* no coercion *) Existing Instance a. Fail Type _ : B. (* no typeclass instance *) End ClassNothing. Module ClassCoercion. Class B. Class A := { ab :> B }. Parameter a : A. Check a : B. (* coercion *) Existing Instance a. Fail Type _ : B. (* no typeclass instance *) End ClassCoercion. Module ClassTC. Class B. Class A := { ab :: B }. Parameter a : A. Fail Check a : B. (* no coercion *) Existing Instance a. Type _ : B. (* typeclass instance *) End ClassTC. Module ClassCoercionTC. Class B. Class A := { ab ::> B }. Parameter a : A. Check a : B. (* coercion *) Existing Instance a. Type _ : B. (* typeclass instance *) End ClassCoercionTC. rocq-9.2.0/test-suite/success/record_postponed_eta.v000066400000000000000000000110321516144147600226430ustar00rootroot00000000000000Set Primitive Projections. Record RTypeToSProp (A : SProp) : Type := { f1 : A }. (* Conversion when record is in Type and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RTypeToSProp A), eq r2 {| f1 := r2.(f1 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : SProp r2 : RTypeToSProp A Unable to unify "{| f1 := f1 _ r2 |}" with "r2" *) Record RPropToSProp (A : SProp) : Prop := { f2 : A }. (* Conversion when record is in Prop and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RPropToSProp A), eq r2 {| f2 := r2.(f2 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : SProp r2 : RPropToSProp A Unable to unify "{| f2 := f2 _ r2 |}" with "r2". *) Set Universe Polymorphism. Record RSToSProp@{s;u|s -> SProp} (A : SProp) : Type@{s;u} := { f3 : A }. Inductive eq@{s s'; u} (A : Type@{s;u}) (a : A) : A -> Prop := eq_refl : eq A a a. Arguments eq {_}. Arguments eq_refl {_ _}. (* Conversion when record is in Type and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RSToSProp@{Type;0} A), eq r2 {| f3 := r2.(f3 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : SProp r2 : RSToProp A Unable to unify "{| f3 := f3 _ r2 |}" with "r2". *) Set Debug "cClosure". (* Conversion when record and field are instantiated to SProp checks correctly *) Goal forall (A:SProp) (r2 : RSToSProp@{SProp;0} A), eq r2 {| f3 := r2.(f3 A) |}. Proof. intros A r2. reflexivity. Qed. Record RSToS'@{s1 s2;u1 u2| s2 -> s1 +} (A : Type@{s1;u1}): Type@{s2;u2} := { f4 : A }. (* Conversion when record is in Type and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RSToS'@{SProp Type;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : SProp r2 : RSToS' A Unable to unify "{| f4 := f4 _ r2 |}" with "r2". *) (* Conversion when record is in Prop and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RSToS'@{SProp Prop;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. (* The command has indeed failed with message: In environment A : SProp r2 : RSToS' A Unable to unify "{| f4 := f4 _ r2 |}" with "r2". *) Fail destruct r2. (* prim record must have eta for dependent elim *) Abort. (* Conversion when record and field are instantiated to SProp checks correctly *) Goal forall (A:SProp) (r2 : RSToS'@{SProp SProp;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. reflexivity. Qed. (* Conversion when record and field are instantiated to the same sort (Type) still fails correctly because we haven't implemented it *) Goal forall (A:Set) (r2 : RSToS'@{Type Type;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* Conversion when record and field are instantiated to the same sort (Prop) still fails correctly because we haven't implemented it *) Goal forall (A:Prop) (r2 : RSToS'@{Prop Prop;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* Conversion when record is in Type and field is in Prop still fails correctly because we haven't implemented it *) Goal forall (A:Prop) (r2 : RSToS'@{Prop Type;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. Section Sorts. Sort s s'. Constraint s -> SProp. (* Conversion when record is in Type and field in SProp fails correctly *) Goal forall (A:SProp) (r2 : RSToSProp@{s;0} A), eq r2 {| f3 := r2.(f3 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : SProp r2 : RSToProp A Unable to unify "{| f3 := f3 _ r2 |}" with "r2". *) Constraint s' -> s. (* Conversion when record and field are instantiated to the different sorts fails correctly *) Goal forall (A:Type@{s;0}) (r2 : RSToS'@{s s';0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. (* The command has indeed failed with message: In environment A : Type@{s ; _} r2 : RSToS' A Unable to unify "{| f4 := f4 _ r2 |}" with "r2". *) (* Conversion when record and field are instantiated to the same sort (Type) still fails correctly because we haven't implemented it *) Goal forall (A:Type@{s;0}) (r2 : RSToS'@{s s;0 0} A), eq r2 {| f4 := r2.(f4 A) |}. Proof. intros A r2. Fail reflexivity. Abort. End Sorts. rocq-9.2.0/test-suite/success/record_syntax.v000066400000000000000000000016301516144147600213300ustar00rootroot00000000000000Module A. Record Foo := { foo : unit; bar : unit }. Definition foo_ := {| foo := tt; bar := tt |}. Definition foo0 (p : Foo) := match p with {| |} => tt end. Definition foo1 (p : Foo) := match p with {| foo := f |} => f end. Definition foo2 (p : Foo) := match p with {| foo := f; |} => f end. Definition foo3 (p : Foo) := match p with {| foo := f; bar := g |} => (f, g) end. Definition foo4 (p : Foo) := match p with {| foo := f; bar := g; |} => (f, g) end. End A. Module B. Record Foo := { }. End B. Module C. Record Foo := { foo : unit; bar : unit; }. Definition foo_ := {| foo := tt; bar := tt; |}. End C. Module D. Record Foo := { foo : unit }. Definition foo_ := {| foo := tt |}. End D. Module E. Record Foo := { foo : unit; }. Definition foo_ := {| foo := tt; |}. End E. Module F. Record Foo := { foo : nat * nat -> nat -> nat }. Definition foo_ := {| foo '(x,y) n := x+y+n |}. End F. rocq-9.2.0/test-suite/success/refine.v000066400000000000000000000056461516144147600177270ustar00rootroot00000000000000 (* Refine and let-in's *) Goal exists x : nat, x = 0. refine (let y := 0 + 0 in _). exists y; auto. Save test1. Goal exists x : nat, x = 0. refine (let y := 0 + 0 in ex_intro _ (y + y) _). auto. Save test2. Goal nat. refine (let y := 0 in 0 + _). exact 1. Save test3. (* Example submitted by Yves on coqdev *) Goal forall l : list nat, l = l. Proof. refine (fun l => match l return (l = l) with | nil => _ | cons O l0 => _ | cons (S _) l0 => _ end). Abort. (* Submitted by Roland Zumkeller (BZ#888) *) (* The Fix and CoFix rules expect a subgoal even for closed components of the (co-)fixpoint *) Goal nat -> nat. refine (fix f (n : nat) : nat := S _ with pred (n : nat) : nat := n for f). exact 0. Qed. (* Submitted by Roland Zumkeller (BZ#889) *) (* The types of metas were in metamap and they were not updated when passing through a binder *) Goal forall n : nat, nat -> n = 0. refine (fun n => fix f (i : nat) : n = 0 := match i with | O => _ | S _ => _ end). Abort. (* Submitted by Roland Zumkeller (BZ#931) *) (* Don't turn dependent evar into metas *) Goal (forall n : nat, n = 0 -> Prop) -> Prop. intro P. refine (P _ _). reflexivity. Abort. (* Submitted by Jacek Chrzaszcz (BZ#1102) *) (* le problΓ¨me a Γ©tΓ© rΓ©solu ici par normalisation des evars prΓ©sentes dans les types d'evars, mais le problΓ¨me reste a priori ouvert dans le cas plus gΓ©nΓ©ral d'evars non instanciΓ©es dans les types d'autres evars *) Goal exists n:nat, n=n. refine (ex_intro _ _ _). Abort. (* Used to failed with error not clean *) Definition div : forall x:nat, (forall y:nat, forall n:nat, {q:nat | y = q*n}) -> forall n:nat, {q:nat | x = q*n}. refine (fun m div_rec n => match div_rec m n with | exist _ _ _ => _ end). Abort. (* Use to fail because sigma was not propagated to get_type_of *) (* Revealed by r9310, fixed in r9359 *) Goal forall f : forall a (H:a=a), Prop, (forall a (H:a = a :> nat), f a H -> True /\ True) -> True. intros. refine (@proj1 _ _ (H 0 _ _)). Abort. (* Use to fail because let-in with metas in the body where rejected because a priori considered as dependent *) Require Import TestSuite.arith. Definition fact_F : forall (n:nat), (forall m, m nat) -> nat. refine (fun n fact_rec => if eq_nat_dec n 0 then 1 else let fn := fact_rec (n-1) _ in n * fn). Abort. (* Wish 1988: that fun forces unfold in refine *) Goal (forall A : Prop, A -> ~~A). Proof. refine(fun A a f => _). Abort. (* Checking beta-iota normalization of hypotheses in created evars *) Goal {x|x=0} -> True. refine (fun y => let (x,a) := y in _). match goal with a:_=0 |- _ => idtac end. Abort. Goal (forall P, {P 0}+{P 1}) -> True. refine (fun H => if H (fun x => x=x) then _ else _). match goal with _:0=0 |- _ => idtac end. Abort. rocq-9.2.0/test-suite/success/refine_definition.v000066400000000000000000000010771516144147600221310ustar00rootroot00000000000000 #[refine] Definition test : { x : nat | x < 4 } := exist _ 3 _. Proof. constructor. Defined. #[refine] Fixpoint fixtest (n : nat) := match n with | 0 => _ | S k => _ end. Proof. 1: shelve. - exact 1. - refine (n * _). apply fixtest. apply k. Defined. #[refine] Definition infer_test := 1 + _. Proof. apply fixtest, 1. Qed. #[refine] Definition true_infer_test := _. Proof. 2: exact (if true as b return if b then _ else _ then 0 else false). Qed. (* Cannot use Eval with #[refine]. *) Fail #[refine] Definition notest := Eval lazy in 0 + 0. rocq-9.2.0/test-suite/success/remember.v000066400000000000000000000011621516144147600202420ustar00rootroot00000000000000(* Testing remember and co *) Lemma A : forall (P: forall X, X -> Prop), P nat 0 -> P nat 0. intros. Fail remember nat as X. Fail remember nat as X in H. (* This line used to succeed in 8.3 *) Fail remember nat as X. Abort. (* Testing Ltac interpretation of remember (was not working up to r16181) *) Goal (1 + 2 + 3 = 6). let name := fresh "fresh" in remember (1 + 2) as x eqn:name. rewrite fresh. Abort. (* An example which was working in 8.4 but failing in 8.5 and 8.5pl1 *) Module A. Axiom N : nat. End A. Module B. Include A. End B. Goal id A.N = B.N. reflexivity. Qed. rocq-9.2.0/test-suite/success/replace.v000066400000000000000000000011731516144147600200610ustar00rootroot00000000000000Goal forall x, x = 0 -> S x = 7 -> x = 22 . Proof. replace 0 with 33. Undo. intros x H H0. replace x with 0. Undo. replace x with 0 in |- *. Undo. replace x with 1 in *. Undo. replace x with 0 in *|- *. Undo. replace x with 0 in *|-. Undo. replace x with 0 in H0 . Undo. replace x with 0 in H0 |- * . Undo. replace x with 0 in H,H0 |- * . Undo. Admitted. (* This failed at some point when "replace" started to support arguments with evars but "abstract" did not supported any evars even defined ones *) Class U. Lemma l (u : U) (f : U -> nat) (H : 0 = f u) : f u = 0. replace (f _) with 0 by abstract apply H. reflexivity. Qed. rocq-9.2.0/test-suite/success/resolve_tc.v000066400000000000000000000007561516144147600206210ustar00rootroot00000000000000Class C := c {}. Local Existing Instance c. Require Ltac2.Ltac2. Ltac resolve_tc := ltac2:(x |- Std.resolve_tc (Option.get (Ltac1.to_constr x))). (* check that exact doesn't do the resolution *) Lemma bad : C. Proof. let x := open_constr:(_:C) in exact x. Fail Qed. Unshelve. exact _. Qed. Lemma foo : C. Proof. let x := open_constr:(_:C) in resolve_tc x; exact x. Qed. (* resolve_tc doesn't focus *) Lemma bar : C. Proof. let x := open_constr:(_:C) in exact x; resolve_tc x. Qed. rocq-9.2.0/test-suite/success/reverse_coercions.v000066400000000000000000000067401516144147600221720ustar00rootroot00000000000000Module Test0. (* By default all coercions from a Structure/Record are also reversible, unless: Structure foo := { .. #[reversible=no] bla :> blu } is given *) (* Declaring/undeclaring a reverse coercion after the facts: #[reversible] Coercion sort. #[reversible=yes] Coercion sort. #[reversible=no] Coercion sort. *) Structure S := { ssort :> Type; sstuff : ssort; }. Definition test1 (s : S) (x : s) := sstuff s. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. Set Printing All. Check test1 _ (0 : nat). (* old hack *) Definition test' {s : S} (t : Type) (f : ssort s -> t) := sstuff s. Notation test t := (test' t (fun x => x)). Check test nat. (* new *) Check test2 (nat : Type). Definition nat' (x:unit) := nat. Arguments nat' &. (* checks that reapply_coercions gets the right trace *) Check test2 (nat' tt). Check (nat : S). Structure R := { rsort :> Type; rstuff : rsort; srstuff : rsort; }. Coercion RtoS (r : R) := {| ssort := rsort r ; sstuff := srstuff r|}. Canonical RtoS. Canonical Structure R_nat := {| rsort := nat; rstuff := 1; srstuff := 0 |}. Definition test3 (r : R) := rstuff r. Set Printing All. Check test3 nat. Check test3 S_nat. Structure T := { tsort :> Type; }. Canonical T_nat (x : unit) := {| tsort := nat |}. Check test2 (T_nat tt). Structure A := { }. Structure A' := { }. Structure B := { ba :> A; #[canonical=no] ba' :> A' }. Structure C := { ca :> A; #[canonical=no] ca' :> A' }. Axiom f : A -> A'. Coercion f : A >-> A'. Canonical b : B := {| ba := Build_A; ba' := Build_A' |}. Canonical c : C := {| ca := Build_A; ca' := Build_A' |}. Definition test4 (x : B) := 1. Check test4 c. (* ~~> test S_nat : S_nat.sort Type ==?== S : f : nat ---> S_nat sort : S >-> Type f := nat ----> ?x sort ?x ==?== nat *) End Test0. (* Test the reverse attribute *) Module Test1. Structure S := { ssort : Type; sstuff : ssort; }. #[reversible=no] Coercion ssort : S >-> Sortclass. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. Fail Check test2 (nat : Type). End Test1. (* Test the reverse attribute *) Module Test1'. Structure S := { ssort : Type; sstuff : ssort; }. Coercion ssort : S >-> Sortclass. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. Fail Check test2 (nat : Type). End Test1'. (* Test the reverse attribute *) Module Test2. Structure S := { #[reversible=no] ssort :> Type; sstuff : ssort; }. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. Fail Check test2 (nat : Type). End Test2. (* Test the reverse attribute *) Module Test3. Structure S := { #[reversible=no] ssort :> Type; sstuff : ssort; }. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. #[reversible] Coercion ssort. Check test2 (nat : Type). End Test3. (* Test the reverse attribute *) Module Test4. Structure S := { ssort :> Type; sstuff : ssort; }. Definition test2 (s : S) := sstuff s. Canonical Structure S_nat := {| ssort := nat; sstuff := 0; |}. #[reversible=no] Coercion ssort. Fail Check test2 (nat : Type). End Test4. rocq-9.2.0/test-suite/success/reverse_coercions_ac.v000066400000000000000000000026031516144147600226270ustar00rootroot00000000000000Set Implicit Arguments. Class Inhab (A:Type) : Prop := { inhab: exists (x:A), True }. Record IType : Type := IType_make { IType_type :> Type; IType_inhab : Inhab IType_type }. Canonical default_IType t ct : IType := @IType_make t ct. Arguments IType_make IType_type {IType_inhab}. Global Instance Inhab_IType : forall (A:IType), Inhab A. Proof using. constructor. apply IType_inhab. Defined. Parameter P : Type -> Prop. (** A [IType] can be provided where an type [A] with a proof of [Inhab A] is expected. *) Parameter K : forall (A:Type) (IA:Inhab A), P A. Lemma testK : forall (A:IType), P A. Proof using. intros. eapply K. eauto with typeclass_instances. Qed. (** A type [A] can be provided where a [IType] is expected, by wrapping it with [IType_make]. *) Parameter T : forall (A:IType), P A. Lemma testT : forall (A:Type) (IA:Inhab A), P A. Proof using. intros. eapply (T A). Qed. (* Above, it would be nice to write [eapply (T A)], or just [eapply T]. For that, we'd need to coerce [A:Type] to the type [IType] by applying on-the-fly the operation [IType_make A _]. Thus, we need something like: [Coercion (fun (A:Type) => IType_make A _) : Sortclass >-> IType.] Would that be possible? I understand that [IType_type] is already a reverse coercion from [IType] to [Type], but I don't see why it would necessarily cause trouble to have cycles in the coercion graphs. *) rocq-9.2.0/test-suite/success/reverse_coercions_typeclasses_and_canonical.v000066400000000000000000000016521516144147600274370ustar00rootroot00000000000000Set Primitive Projections. Class IsPointed (A : Type) := point : A. Record pType : Type := { pointed_type : Type ; ispointed_pointed_type : IsPointed pointed_type ; }. #[reversible] Coercion pointed_type : pType >-> Sortclass. Fail Canonical Build_pType. Canonical Structure Build_pType' (A : Type) (a : IsPointed A) := Build_pType A a. Axiom A : Type. #[export] Instance a : IsPointed A. Proof. Admitted. Axiom lemma_about_ptype : forall (X : pType), Type. Type (A : pType). Type (lemma_about_ptype A). (* Ok, so here is what happens: * you give `A : Type` where `?x : pType` is expected * no coercion `Sortclass >-> pType` but (according to `Print Graph`) we have `[pointed_type] : pType ↣ Sortclass (reversible)` * so reversible coercions look for `?x : pType` such that `pointed_type ?x = A` * and canonical structure mechanism infers `?x = Build_pType' A _` * finally, typeclass resolution fills the last `_` with `a` *) rocq-9.2.0/test-suite/success/rewrite.v000066400000000000000000000110461516144147600201270ustar00rootroot00000000000000(* Check that dependent rewrite applies on arbitrary terms *) Inductive listn : nat -> Set := | niln : listn 0 | consn : forall n : nat, nat -> listn n -> listn (S n). Axiom ax : forall (n n' : nat) (l : listn (n + n')) (l' : listn (n' + n)), existT _ (n + n') l = existT _ (n' + n) l'. Lemma lem : forall (n n' : nat) (l : listn (n + n')) (l' : listn (n' + n)), n + n' = n' + n /\ existT _ (n + n') l = existT _ (n' + n) l'. Proof. intros n n' l l'. dependent rewrite (ax n n' l l'). split; reflexivity. Qed. (* Used to raise an anomaly instead of an error in 8.1 *) (* Submitted by Y. Makarov *) Parameter N : Set. Parameter E : N -> N -> Prop. Axiom e : forall (A : Set) (EA : A -> A -> Prop) (a : A), EA a a. Theorem th : forall x : N, E x x. intro x. try rewrite e. Abort. (* Behavior of rewrite wrt conversion *) Require Import TestSuite.arith. Goal forall n, 0 + n = n -> True. intros n H. rewrite Nat.add_0_l in H. Abort. (* Rewrite dependent proofs from left-to-right *) Lemma l1 : forall x y (H:x = y:>nat) (P:forall x y, x=y -> Type), P x y H -> P x y H. intros x y H P H0. rewrite H. rewrite H in H0. assumption. Qed. (* Rewrite dependent proofs from right-to-left *) Lemma l2 : forall x y (H:x = y:>nat) (P:forall x y, x=y -> Type), P x y H -> P x y H. intros x y H P H0. rewrite <- H. rewrite <- H in H0. assumption. Qed. (* Check rewriting dependent proofs with non-symmetric equalities *) Lemma l3:forall x (H:eq_true x) (P:forall x, eq_true x -> Type), P x H -> P x H. intros x H P H0. rewrite H. rewrite H in H0. assumption. Qed. (* Dependent rewrite *) Require Import TestSuite.jmeq. Goal forall A B (a:A) (b:B), JMeq a b -> JMeq b a -> True. inversion 1; (* Goal is now [JMeq a a -> True] *) dependent rewrite H3. Undo. intros; inversion H; dependent rewrite H4 in H0. Undo. intros; inversion H; dependent rewrite <- H4 in H0. Abort. (* Test conversion between terms with evars that both occur in K-redexes and are elsewhere solvable. This is quite an artificial example, but it used to work in 8.2. Since rewrite supports conversion on terms without metas, it was successively unifying (id 0 ?y) and 0 where ?y was not a meta but, because coming from a "_", an evar. After commit r12440 which unified the treatment of metas and evars, it stopped to work. Chung-Kil Hur's Heq package used this feature. Solved in r13... *) Parameter g : nat -> nat -> nat. Definition K (x y:nat) := x. Goal (forall y, g y (K 0 y) = 0) -> g 0 0 = 0. intros. rewrite (H _). reflexivity. Qed. Goal (forall y, g (K 0 y) y = 0) -> g 0 0 = 0. intros. rewrite (H _). reflexivity. Qed. (* Example of rewriting of a degenerated pattern using the right-most argument of the goal. This is sometimes used in contribs, even if ad hoc. Here, we have the extra requirement that checking types needs delta-conversion *) Axiom s : forall (A B : Type) (p : A * B), p = (fst p, snd p). Definition P := (nat * nat)%type. Goal forall x:P, x = x. intros. rewrite s. Abort. (* Test second-order unification and failure of pattern-unification *) Goal forall (P: forall Y, Y -> Prop) Y a, Y = nat -> (True -> P Y a) -> False. intros. (* The next line used to succeed between June and November 2011 *) (* causing ill-typed rewriting *) Fail rewrite H in H0. Abort. (* Test subst in the presence of a dependent let-in *) (* Was not working prior to May 2014 *) Goal forall x y, x=y+0 -> let z := x+1 in x+1=y -> z=z -> z=x. intros. subst x. (* was failing *) subst z. rewrite H0. rewrite Nat.add_0_r. reflexivity. Qed. (* Check that evars are instantiated when the term to rewrite is closed, like in the case it is open *) Goal exists x, S 0 = 0 -> S x = 0. eexists. intro H. rewrite H. reflexivity. Abort. (* Check that rewriting within evars still work (was broken in 8.5beta1) *) Goal forall (a: unit) (H: a = tt), exists x y:nat, x = y. intros; eexists; eexists. rewrite H. Undo. subst. Abort. (* Check that iterated rewriting does not rewrite in the side conditions *) (* Example from Sigurd Schneider, extracted from contrib containers *) Lemma EQ : forall (e e' : nat), True -> e = e'. Admitted. Lemma test (v1 v2 v3: nat) (v' : v1 = v2) : v2 = v1. Proof. rewrite <- (EQ v1 v2) in *. exact v'. (* There should be only two side conditions *) exact I. exact I. Qed. (* test that "try rewrite" / "rewrite ?h" catches the error from mssing-scheme *) Set Warnings "+missing-scheme". Inductive myeq A x : A -> Prop := myrefl : myeq A x x. Goal forall x y, myeq nat x y -> x = y. Proof. intros x y H. Fail rewrite H. try rewrite H. rewrite ?H. Abort. rocq-9.2.0/test-suite/success/rewrite_closed.v000066400000000000000000000023341516144147600214600ustar00rootroot00000000000000From Corelib Require Import Setoid Morphisms. Axiom lattice_for : Type -> Type. Axiom constant : forall {T : Type}, T -> lattice_for T. Axiom lattice_for_rect : forall [T : Type] (P : Type), (forall t : T, P) -> forall l : lattice_for T, P. #[local] Declare Instance lattice_for_rect_Proper_85 : forall {A}, Proper (forall_relation (fun _ => eq) ==> eq ==> Basics.flip Basics.impl) (@lattice_for_rect A Prop) | 3. Axiom lattice_rewrite : forall (A T T' : Type) (x : T -> T') (c : A -> lattice_for T) (v : lattice_for A), lattice_for_rect T' x (lattice_for_rect (lattice_for T) c v) = lattice_for_rect T' (fun x0 : A => lattice_for_rect T' x (c x0)) v. Axiom collapse_might_be_empty : bool. Axiom PosSet : Type. Axiom PosSet_inter : PosSet -> PosSet -> PosSet. Goal forall (l2 : lattice_for PosSet) (l0 : lattice_for PosSet), lattice_for_rect Prop (fun x : PosSet => lattice_for_rect Prop (fun _ : PosSet => True) (lattice_for_rect (lattice_for PosSet) (fun y' : PosSet => constant (if collapse_might_be_empty then PosSet_inter x y' else y')) l0)) l2 . Proof. intros. (* This should not capture a variable *) Fail rewrite lattice_rewrite. Abort. rocq-9.2.0/test-suite/success/rewrite_evar.v000066400000000000000000000006031516144147600211410ustar00rootroot00000000000000Require Import Corelib.Setoids.Setoid. Goal forall (T2 MT1 MT2 : Type) (x : T2) (M2 m2 : MT2) (M1 m1 : MT1) (F : T2 -> MT1 -> MT2 -> Prop), (forall (defaultB : T2) (m3 : MT1) (m4 : MT2), F defaultB m3 m4 <-> True) -> F x M1 M2 -> F x m1 m2. intros ????????? H' H. rewrite (H' _) in *. (** The above rewrite should also rewrite in H. *) Fail progress rewrite H' in H. Abort. rocq-9.2.0/test-suite/success/rewrite_in.v000066400000000000000000000004341516144147600206140ustar00rootroot00000000000000Require Import Setoid. Goal forall (P Q : Prop) (f:P->Prop) (p:P), (P<->Q) -> f p -> True. intros P Q f p H. rewrite H in p || trivial. Qed. Goal 1 = 0 -> 0 = 1. intro H. Fail rewrite H at 1 2 3. (* bug #13566 *) Fail rewrite H at 0. rewrite H at 1. reflexivity. Qed. rocq-9.2.0/test-suite/success/rewrite_iterated.v000066400000000000000000000007501516144147600220100ustar00rootroot00000000000000Axiom test : forall p:nat, p<>0 -> p-1+1=p. (** Test of new syntax for rewrite : ! ? and so on... *) Lemma but : forall a b c, a<>0 -> b<>0 -> c<>0 -> (a-1+1)+(b-1+1)+(c-1+1)=a+b+c. Proof. intros. rewrite test. Undo. rewrite test,test. Undo. rewrite 2 test. (* or rewrite 2test or rewrite 2!test *) Undo. rewrite 2!test,2?test. Undo. (*rewrite 4!test. --> error *) rewrite 3!test. Undo. rewrite <- 3?test. Undo. (*rewrite <-?test. --> loops*) rewrite !test by auto. reflexivity. Qed. rocq-9.2.0/test-suite/success/rewrite_strat.v000066400000000000000000000033001516144147600213360ustar00rootroot00000000000000Require Import Setoid. Parameter X : Set. Parameter f : X -> X. Parameter g : X -> X -> X. Parameter h : nat -> X -> X. Parameter lem0 : forall x, f (f x) = f x. Parameter lem1 : forall x, g x x = f x. Parameter lem2 : forall n x, h (S n) x = g (h n x) (h n x). Parameter lem3 : forall x, h 0 x = x. #[export] Hint Rewrite lem0 lem1 lem2 lem3 : rew. Goal forall x, h 10 x = f x. Proof. intros. Time autorewrite with rew. (* 0.586 *) reflexivity. Time Qed. (* 0.53 *) Goal forall x, h 6 x = f x. intros. Time rewrite_strat topdown lem2. Time rewrite_strat topdown lem1. Time rewrite_strat topdown lem0. Time rewrite_strat topdown lem3. reflexivity. Undo 5. Time rewrite_strat topdown (choice lem2 lem1). Time rewrite_strat topdown (choice lem0 lem3). reflexivity. Undo 3. Time rewrite_strat (topdown (choice lem2 lem1); topdown (choice lem0 lem3)). reflexivity. Undo 2. Time rewrite_strat (topdown (choice (choice lem2 lem1) (choice lem0 lem3))). reflexivity. Undo 2. Time rewrite_strat (topdown (choice lem2 (choice lem1 (choice lem0 lem3)))). reflexivity. Undo 2. Time rewrite_strat (topdown (choice lem2 lem1 lem0 lem3)). reflexivity. Undo 2. Time rewrite_strat fix f := (choice lem2 lem1 lem0 lem3 (progress subterms f) ; try f). reflexivity. Qed. Goal forall x, h 10 x = f x. Proof. intros. Time rewrite_strat topdown (hints rew). (* 0.38 *) reflexivity. Time Qed. (* 0.06 s *) Set Printing All. Set Printing Depth 100000. Tactic Notation "my_rewrite_strat" constr(x) := rewrite_strat topdown x. Tactic Notation "my_rewrite_strat2" uconstr(x) := rewrite_strat topdown x. Goal (forall x, S x = 0) -> 1=0. intro H. my_rewrite_strat H. Undo. my_rewrite_strat2 H. Abort. rocq-9.2.0/test-suite/success/rewrule.v000066400000000000000000000220531516144147600201330ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-allow-rewrite-rules") -*- *) (* Simple first example *) Symbol pplus : nat -> nat -> nat. Notation "a ++ b" := (pplus a b). Rewrite Rules plus_rew := | ?n ++ 0 => ?n | ?n ++ S ?n' => S (?n ++ ?n') | 0 ++ ?n => ?n | S ?n ++ ?n' => S (?n ++ ?n'). Check eq_refl : 5 ++ 10 = 15. Check (fun _ _ => eq_refl) : forall n n', 2 + n ++ 3 + n' = 5 + (n ++ n'). (* Test deep pattern matching *) Eval lazy in fun n n' => 2 + n ++ 3 + n'. Eval cbv in fun n n' => 2 + n ++ 3 + n'. Eval cbn in fun n n' => 2 + n ++ 3 + n'. Eval simpl in fun n n' => 2 + n ++ 3 + n'. (* Does not reduce *) (* Example with more pattern constructions and higher-order in patterns *) #[unfold_fix] Symbol raise : forall P: Type, P. Rewrite Rules raise_rew := raise (forall (x : ?A), ?P) => fun x => raise ?P | raise (?A * ?B) => (raise ?A, raise ?B) | raise unit => tt | match raise bool as b return ?P with true => _ | false => _ end => raise ?P@{b := raise bool} | match raise nat as n return ?P with 0 => ?p | S n => ?p' end => raise ?P@{n := raise nat} | match raise (@eq ?A ?a ?b) as e in _ = b return ?P with | eq_refl => _ end => raise ?P@{b := _; e := raise (?a = ?b)} | match raise (list ?A) as l return ?P with | nil => _ | cons _ _ => _ end => raise ?P@{l := raise (list ?A)} | match raise False as e return ?P with end => raise ?P@{e := raise False} | match raise (?A + ?B) as e return ?P with | inl _ => _ | inr _ => _ end => raise ?P@{e := raise (?A + ?B)}. (* There is currently no way to write these rules without the universe inconcistency *) Eval simpl in match raise bool with true | false => 0 end. (* Does not reduce *) Eval lazy in match (raise nat * 5 + 3 :: 0 :: nil)%list with cons 0 l => tt | _ => tt end. Eval lazy in raise nat + 5. Eval cbv in raise nat + 5. Eval cbn in raise nat + 5. Eval simpl in raise nat + 5. (* Does not reduce *) Set Primitive Projections. Record primprod (A B : Type) := { fst: A; snd: B }. (* Example with even more pattern constructions, mostly for terms *) Universe idu. #[unfold_fix, universes(polymorphic)] Symbol id@{q; } : forall A : Type@{q;idu}, A -> A. Rewrite Rules id_rew := | @{q;u+|+} |- id _ Type@{q;u} => Type@{q;u} | @{q;u+|+} |- id Type@{q;u} (forall (x : ?A), ?P) => forall x, id Type@{q;u} ?P | id (forall (x : ?A), ?P) ?f => fun (x : ?A) => id ?P (?f x) | @{u+} |- id Type@{u} (?A * ?B)%type => (id Type@{u} ?A * id Type@{u} ?B)%type | id (?A * ?B) (?a, ?b) => (id _ ?a, id _ ?b) | id _ unit => unit | id _ tt => tt | id _ nat => nat | id _ 0 => 0 | id _ (S ?n) => S (id _ ?n) | id _ (fun (n : ?A) => S ?n) => fun n => S (id _ ?n) | id (primprod ?A ?B) {| fst := ?a; snd := ?b |} => {| fst := id _ ?a; snd := id _ ?b |}. Fail Rewrite Rule id_rew_fail := Datatypes.id _ ?x => ?x. (* Subterm not recognised as pattern: Datatypes.id *) Fail Rewrite Rule id_rew_fail := 0 => 0. (* Head head-pattern is not a symbol. *) Fail Rewrite Rule id_rew_fail := id _ (?x ?y) => ?x ?y. (* Subterm not recognised as pattern: ?x *) Fail Rewrite Rule id_rew_fail := id _ _ => ?x. (* Unknown existential variable. *) Fail Rewrite Rule id_rew_fail := @{u} |- id _ ?x => ?x. (* Not all universe level variables appear in the pattern. *) Fail Rewrite Rule id_rew_fail := id _ (?x, ?x) => ?x. (* Variable ?x is bound multiple times in the pattern (holes number 1 and 2). *) Fail Rewrite Rule id_rew_fail := @{u+} |- id _ (Type@{u}, Type@{u}) => ?x. (* Universe variable u is bound multiple times in the pattern (holes number 0 and 1). *) Fail Rewrite Rule id_rew_fail := id _ (?x, ?y) => (?x, ?y). (* The replacement term contains unresolved implicit arguments: (?x, ?y) *) Fail Rewrite Rule id_rew_fail := id _ Type => Type. (* Universe rewrule.xxx is unbound. *) Fail Rewrite Rule id_rew_fail := id _ (forall x, ?P) => ?P. (* Cannot interpret ?P in current context: no binding for x. *) Symbol idS : forall (A : SProp), A -> A. Inductive unitS : SProp := ttS. Rewrite Rule id_rew' := idS _ ttS => ttS. (* Warning: This subpattern is irrelevant and can never be matched against. *) Symbol vararity : forall n, (fix f n := match n with 0 => unit | S n => unit -> f n end) n. Check vararity (4 + _) tt tt tt _. Rewrite Rule vararity_rew := id _ (vararity _) => 0. (* Warning: This subpattern has a yet unknown type, which may be a product type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times *) Module MLTTmap. Symbol map : forall A B, (A -> B) -> list A -> list B. Rewrite Rule map_rew := | map _ _ (fun x => x) ?l => ?l | map _ ?C ?f (map ?A _ ?g ?l) => map ?A ?C (fun x => ?f (?g x)) ?l | map ?A ?B ?f (@nil _) => @nil ?B | map ?A ?B ?f (@cons _ ?a ?l) => @cons ?B (?f ?a) (map _ _ ?f ?l). Definition idA {A: Type} := fun (x : A) => x. Eval lazy in fun l => (map _ _ idA l). Eval cbv in fun l => (map _ _ idA l). Eval cbn in fun l => (map _ _ idA l). Eval simpl in fun l => (map _ _ idA l). (* Does not reduce *) Eval lazy in fun l => (map _ _ (fun f x => f x) l). (* Does not reduce because there is no support for eta *) End MLTTmap. (* Example where ignore holes are necessary *) Symbol J : forall (A : Type) (a : A) (P : A -> Type), P a -> forall (a' : A), @eq A a a' -> P a'. Rewrite Rule a := J _ _ _ ?H _ (@eq_refl _ _) => ?H. Module omega. (* Example of a broken extension *) #[unfold_fix] Symbol omega : nat. Rewrite Rule omega_rew := match omega with S n => ?P | 0 => _ end => ?P@{n := omega}. Theorem omega_spec : S omega = omega. Proof. symmetry. change omega with (Nat.pred omega) at 2. remember omega as omeg eqn:e. destruct omeg. 2: reflexivity. apply (f_equal (fun n => match n with 0 => 0 | S _ => 1 end)) in e. apply e. Qed. Theorem omega_contradiction : False. Proof. assert (forall n, S n = n -> False) as X. 2: eapply X, omega_spec. induction n. 1: discriminate. now intros [=]. Qed. End omega. Module stream. (* Subtle interaction between rewriting and the guard-checker *) Inductive stream := T (_ : stream). Fixpoint f s : False := f match s with T s' => s' end. Fixpoint g s : False := match s with T s' => g s' end. Rewrite Rule raise_rew_stream := | match raise _ as s return ?P with T _ => _ end => raise ?P@{s := raise _}. Goal forall s, f s = g s. unfold f, g. induction s. assumption. Defined. Eval lazy in g (raise _). End stream. Module context. (* Test whether context extensions work correctly (here, with constructor arrguments)*) Symbol id : forall A, A -> A. Axioms (aa ee : nat). Inductive A := C (a := aa) (b : unit) (c := (a, b)) (d : True) (e := ee). Rewrite Rule raise_rew_C := match raise _ with C a b c d e => id (_ * _) ?P end => ?P@{a := _; b := raise _; c := _; d := raise _; e := _}. Eval lazy in match raise _ with C a b c d e => id _ (a, b, c, d, e) end. Eval cbv in match raise _ with C a b c d e => id _ (a, b, c, d, e) end. Eval cbn in match raise _ with C a b c d e => id _ (a, b, c, d, e) end. Eval simpl in match raise _ with C a b c d e => id _ (a, b, c, d, e) end. End context. (* Non-confluent rules prove False *) Symbol Devil : bool -> bool. Rewrite Rule devil := | Devil ?b => false | Devil true => true. Lemma Devil_false b : Devil b = false. Proof. reflexivity. Defined. Lemma Devil_true : Devil true = true. Proof. reflexivity. Defined. Lemma ministry_of_truth : true = false. Proof. transitivity (Devil true). - symmetry;exact Devil_true. - apply Devil_false. Defined. Corollary contradiction : False. Proof. pose proof ministry_of_truth; discriminate. Defined. Definition successor_of_nothing : nat := match ministry_of_truth in eq _ b return if b then bool else nat with eq_refl => false end. (* Such mistyped terms would break the VM, hence why it must be disabled *) Eval vm_compute in pred successor_of_nothing. Definition ignore {A} (x:A) := tt. Definition beginning_of_the_world : ignore (pred successor_of_nothing) = tt. Proof. lazy;reflexivity. Qed. Lemma end_of_the_world : tt = tt. Proof. vm_compute. exact beginning_of_the_world. Defined. (* This computation would run in the VM from the kernel, which is dangerous *) (* Having a common supertype is not enough to preserve SR *) Universe u. Symbol idTy@{i} : Type@{i} -> Type@{u}. Rewrite Rule idTy_id := idTy ?t => ?t. (* Warning: This rewrite rule breaks subject reduction (universe inconsistency). *) Definition U : Type@{u} := idTy Type@{u}. Check U : U. Definition id'@{i} : Type@{i} -> Type@{u} := fun (t: Type@{i}) => t. Fail Definition U' : Type@{u} := id' Type@{u}. Require Import TestSuite.hurkens. Goal False. apply (TypeNeqSmallType.paradox U eq_refl). Defined. (* Test substitution on context extensions *) Definition a : 0 = 0. set (test := let n := 0 in @eq_trans _ n n n (raise _) (raise _)). lazy delta in test. lazy beta in test. set (test_lazy := test). lazy delta zeta in test_lazy. set (test_cbv := test). cbv delta zeta in test_cbv. set (test_cbn := test). cbn delta zeta in test_cbn. set (test_simpl := test). unfold test in test_simpl. simpl in test_simpl. Abort. Definition test_subst_context := Eval cbv delta zeta in let n := 0 in match raise (n = n) in (_ = a) return (n = a) with | eq_refl => raise _ end. rocq-9.2.0/test-suite/success/rewrule_quality_match.v000066400000000000000000000013051516144147600230540ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-allow-rewrite-rules") -*- *) #[universes(polymorphic)] Symbol irrel@{q;u} : forall {A : Type@{q;u}}, A -> bool. Rewrite Rule id_rew := | irrel@{SProp|_} _ => true | irrel@{Type|_} _ => false. Inductive STrue : SProp := SI. Goal True. let c := constr:((irrel SI, irrel tt)) in let cl := eval lazy in c in constr_eq cl (true, false). let c := constr:((irrel SI, irrel tt)) in let cl := eval cbv in c in constr_eq cl (true, false). let c := constr:((irrel SI, irrel tt)) in let cl := eval cbn in c in constr_eq cl (true, false). let c := constr:((irrel SI, irrel tt)) in let cl := eval simpl in c in constr_eq cl (true, false). exact I. Qed. rocq-9.2.0/test-suite/success/search.v000066400000000000000000000011431516144147600177100ustar00rootroot00000000000000 (** Test of the different syntaxes of Search *) Search plus. Search plus mult. Search "plus_n". Search plus "plus_n". Search "*". Search "*" "+". Search plus inside Peano. Search plus mult in Peano. Search "plus_n" inside Peano. Search plus "plus_n" inside Peano. Search "*" inside Peano. Search "*" "+" inside Peano. Search plus outside Peano Logic. Search plus mult outside Peano Logic. Search "plus_n" outside Peano Logic. Search plus "plus_n" outside Peano Logic. Search "*" outside Peano Logic. Search "*" "+" outside Peano Logic. Search -"*" "+" outside Logic. Search -"*"%nat "+"%nat outside Logic. rocq-9.2.0/test-suite/success/section_poly.v000066400000000000000000000025721516144147600211610ustar00rootroot00000000000000 Section Foo. Variable X : Type. Polymorphic Section Bar. Variable A : Type. Definition id (a:A) := a. End Bar. Check id@{_}. End Foo. Check id@{_}. Polymorphic Section Foo. Variable A : Type. Section Bar. Variable B : Type. Inductive prod := Prod : A -> B -> prod. End Bar. Check prod@{_}. End Foo. Check prod@{_ _}. Section Foo. Universe K. Inductive bla := Bla : Type@{K} -> bla. Polymorphic Definition bli@{j} := Type@{j} -> bla. Definition bloo := bli@{_}. Polymorphic Universe i. Fail Definition x := Type. Fail Inductive x : Type := . Polymorphic Definition x := Type. Polymorphic Inductive y : x := . Variable A : Type. (* adds a mono univ for the Type, which is unrelated to the others *) Fail Variable B : (y : Type@{i}). (* not allowed: mono constraint (about a fresh univ for y) regarding poly univ i *) Polymorphic Variable B : Type. (* new polymorphic stuff always OK *) Variable C : Type@{i}. (* no new univs so no problems *) Polymorphic Definition thing := bloo -> y -> A -> B. End Foo. Check bli@{_}. Check bloo@{}. Check thing@{_ _ _}. Section Foo. Polymorphic Universes i k. Universe j. Fail Constraint i < j. Fail Constraint i < k. (* referring to mono univs in poly constraints is OK. *) Polymorphic Constraint i < j. Polymorphic Constraint j < k. Polymorphic Definition foo := Type@{j}. End Foo. rocq-9.2.0/test-suite/success/set.v000066400000000000000000000013451516144147600172420ustar00rootroot00000000000000(* This used to fail in 8.0pl1 *) Goal forall n, n+n=0->0=n+n. intros. set n in * |-. Abort. (* This works from 8.4pl1, since merging of different instances of the same metavariable in a pattern is done modulo conversion *) Notation "p .+1" := (S p) (at level 1, left associativity, format "p .+1"). Goal forall (f:forall n, n=0 -> Prop) n (H:(n+n).+1=0), f (n.+1+n) H. intros. set (f _ _). Abort. Module UsingSProp. Inductive STrue : SProp := I. Inductive SBool : SProp := T | F. Axiom f : forall {A B:SProp}, A -> B -> unit. Goal f (fun _ : nat => F) (fun _:nat => I) = f (fun _ : nat => F) (fun _:nat => I). set (x := fun _ => _). reflexivity. Qed. (* Was failing because all 4 "fun _ => ..." were identified *) End UsingSProp. rocq-9.2.0/test-suite/success/setoid_rewrite_proj.v000066400000000000000000000014771516144147600225370ustar00rootroot00000000000000Require Export Corelib.Setoids.Setoid. Module Test1. #[projections(primitive=yes)] Structure Test := { test : unit }. Axiom tst : Test. Axiom tst' : Test. Axiom H : tst = tst'. Theorem a : test tst = test tst'. Proof. setoid_rewrite H. exact eq_refl. Qed. End Test1. Module Test2. #[projections(primitive=yes)] Structure Test (n : nat) := { test : unit }. Axiom tst : Test 0. Axiom tst' : Test 0. Axiom H : tst = tst'. Theorem a : test _ tst = test _ tst'. Proof. setoid_rewrite H. exact eq_refl. Qed. End Test2. Module Test3. #[projections(primitive=yes)] Structure Test (n : nat) := { test : unit }. Axiom n : nat. Axiom tst : Test n. Axiom tst' : Test n. Axiom H : n = 0. Theorem a : test _ tst = test _ tst'. Proof. Fail setoid_rewrite H. (* no rewriting in parameters *) Abort. End Test3. rocq-9.2.0/test-suite/success/setoid_test.v000066400000000000000000000205301516144147600207720ustar00rootroot00000000000000Require Import TestSuite.admit. Require Import Setoid. Parameter A : Set. Axiom eq_dec : forall a b : A, {a = b} + {a <> b}. Inductive set : Set := | Empty : set | Add : A -> set -> set. Fixpoint In (a : A) (s : set) {struct s} : Prop := match s with | Empty => False | Add b s' => a = b \/ In a s' end. Definition same (s t : set) : Prop := forall a : A, In a s <-> In a t. Lemma setoid_set : Setoid_Theory set same. unfold same; split ; red. red; auto. red. intros. elim (H a); auto. intros. elim (H a); elim (H0 a). split; auto. Qed. Add Setoid set same setoid_set as setsetoid. Add Morphism In with signature (eq ==> same ==> iff) as In_ext. Proof. unfold same; intros a s t H; elim (H a); auto. Qed. Lemma add_aux : forall s t : set, same s t -> forall a b : A, In a (Add b s) -> In a (Add b t). unfold same; simple induction 2; intros. rewrite H1. simpl; left; reflexivity. elim (H a). intros. simpl; right. apply (H2 H1). Qed. Add Morphism Add with signature (eq ==> same ==> same) as Add_ext. split; apply add_aux. assumption. rewrite H. reflexivity. Qed. Fixpoint remove (a : A) (s : set) {struct s} : set := match s with | Empty => Empty | Add b t => match eq_dec a b with | left _ => remove a t | right _ => Add b (remove a t) end end. Lemma in_rem_not : forall (a : A) (s : set), ~ In a (remove a (Add a Empty)). intros. setoid_replace (remove a (Add a Empty)) with Empty. auto. unfold same. split. simpl. case (eq_dec a a). intros e ff; elim ff. intros; absurd (a = a); trivial. simpl. intro H; elim H. Qed. Parameter P : set -> Prop. Parameter P_ext : forall s t : set, same s t -> P s -> P t. Add Morphism P with signature (same ==> iff) as P_extt. intros; split; apply P_ext; (assumption || apply (Seq_sym _ _ setoid_set); assumption). Qed. Lemma test_rewrite : forall (a : A) (s t : set), same s t -> P (Add a s) -> P (Add a t). intros. rewrite <- H. rewrite H. setoid_rewrite <- H. setoid_rewrite H. setoid_rewrite <- H. trivial. Qed. (* Unifying the domain up to delta-conversion (example from emakarov) *) Definition id: Set -> Set := fun A => A. Definition rel : forall A : Set, relation (id A) := @eq. Definition f: forall A : Set, A -> A := fun A x => x. Add Relation (id A) (rel A) as eq_rel. Add Morphism (@f A) with signature (eq ==> eq) as f_morph. Proof. unfold rel, f. trivial. Qed. (* Submitted by Nicolas Tabareau *) (* Needs unification.ml to support environments with de Bruijn *) Goal forall (f : Prop -> Prop) (Q : (nat -> Prop) -> Prop) (H : forall (h : nat -> Prop), Q (fun x : nat => f (h x)) <-> True) (h:nat -> Prop), Q (fun x : nat => f (Q (fun b : nat => f (h x)))) <-> True. intros f0 Q H. setoid_rewrite H. tauto. Qed. (** Check proper refreshing of the lemma application for multiple different instances in a single setoid rewrite. *) Section mult. Context (fold : forall {A} {B}, (A -> B) -> A -> B). Context (add : forall A, A -> A). Context (fold_lemma : forall {A B f} {eqA : relation B} x, eqA (fold A B f (add A x)) (fold _ _ f x)). Context (ab : forall B, A -> B). Context (anat : forall A, nat -> A). Goal forall x, (fold _ _ (fun x => ab A x) (add A x) = anat _ (fold _ _ (ab nat) (add _ x))). Proof. intros. setoid_rewrite fold_lemma. change (fold A A (fun x0 : A => ab A x0) x = anat A (fold A nat (ab nat) x)). Abort. End mult. (** Current semantics for rewriting with typeclass constraints in the lemma does not fix the instance at the first unification, use [at], or simply rewrite for this semantics. *) Parameter beq_nat : forall x y : nat, bool. Class Foo (A : Type) := {foo_neg : A -> A ; foo_prf : forall x : A, x = foo_neg x}. #[export] Instance: Foo nat. admit. Defined. #[export] Instance: Foo bool. admit. Defined. Goal forall (x : nat) (y : bool), beq_nat (foo_neg x) 0 = foo_neg y. Proof. intros. setoid_rewrite <- foo_prf. change (beq_nat x 0 = y). Abort. Goal forall (x : nat) (y : bool), beq_nat (foo_neg x) 0 = foo_neg y. Proof. intros. setoid_rewrite <- @foo_prf at 1. change (beq_nat x 0 = foo_neg y). Abort. (* This should not raise an anomaly as it did for some time in early 2016 *) Definition t := nat -> bool. Definition h (a b : t) := forall n, a n = b n. #[export] Instance subrelh : subrelation h (Morphisms.pointwise_relation nat eq). Proof. intros x y H; assumption. Qed. Goal forall a b, h a b -> a 0 = b 0. intros. setoid_rewrite H. (* Fallback on ordinary rewrite without anomaly *) reflexivity. Qed. Module InType. Require Import CRelationClasses CMorphisms. Inductive All {A : Type} (P : A -> Type) : list A -> Type := | All_nil : All P nil | All_cons x (px : P x) xs (pxs : All P xs) : All P (x :: xs). Lemma All_impl {A} (P Q : A -> Type) l : (forall x, P x -> Q x) -> All P l -> All Q l. Proof. intros HP. induction 1; constructor; eauto. Qed. Axiom add_0_r_peq : forall x : nat, eq (x + 0)%nat x. #[export] Instance All_proper {A} : CMorphisms.Proper ((pointwise_relation A iffT) ==> eq ==> iffT) All. Proof. intros f g Hfg x y e. destruct e. split; apply All_impl, Hfg. Qed. Lemma rewrite_all {l : list nat} (Q : nat -> Type) : All (fun x => Q x) l -> All (fun x => Q (x + 0)) l. Proof. intros a. setoid_rewrite add_0_r_peq. exact a. Qed. Lemma rewrite_all_in {l : list nat} (Q : nat -> Type) : All (fun x => Q (x + 0)) l -> All (fun x => Q x) l. Proof. intros a. setoid_rewrite add_0_r_peq in a. exact a. Qed. Lemma rewrite_all_in2 {l : list nat} (Q : nat -> Type) (R : nat -> Type) : All (fun x => prod (Q (x + 0)%nat) (R x))%type l -> All (fun x => prod (Q x) (R x))%type l. Proof. intros a. setoid_rewrite add_0_r_peq in a. exact a. Qed. End InType. Module Polymorphism. Require Import CRelationClasses CMorphisms. #[universes(polymorphic, cumulative)] Inductive plist@{i} (A : Type@{i}) : Type@{i} := | pnil : plist A | pcons : A -> plist A -> plist A. Arguments pnil {A}. Arguments pcons {A}. #[universes(polymorphic, cumulative)] Record pprod@{i j} (A : Type@{i}) (B : Type@{j}) : Type@{max(i, j)} := { pfst : A; psnd : B }. Arguments pfst {A B}. Arguments psnd {A B}. Notation "x :: xs" := (pcons x xs). #[universes(polymorphic)] Fixpoint All@{i j} {A : Type@{i}} (P : A -> Type@{j}) (l : plist A) : Type@{j} := match l with | pnil => unit | x :: xs => pprod (P x) (All P xs) end. (* #[universes(polymorphic, cumulative)] Inductive All {A : Type} (P : A -> Type) : list A -> Type := | All_nil : All P nil | All_cons x (px : P x) xs (pxs : All P xs) : All P (x :: xs). *) #[universes(polymorphic)] Lemma All_impl {A} (P Q : A -> Type) l : (forall x, P x -> Q x) -> All P l -> All Q l. Proof. intros HP. induction l; [intros|intros []]; constructor; eauto. Qed. Check pointwise_relation. #[universes(polymorphic)] Inductive peq@{i} (A : Type@{i}) (a : A) : A -> Type@{i} := peq_refl : peq A a a. Arguments peq {A}. Arguments peq_refl {A a}. #[universes(polymorphic)] Axiom add_0_r_peq : forall x : nat, peq (x + 0)%nat x. #[universes(polymorphic), export] Instance peq_left {A : Type} {B : Type} {R : crelation B} (f : A -> B) `{Reflexive B R} : Proper (peq ==> R) f. Admitted. #[export] Instance reflexive_eq_dom_reflexive@{i j jr mij mijr} {A : Type@{i}} {B : Type@{j}} (R : crelation@{j jr} B) : Reflexive@{j jr} R -> Reflexive@{mij mijr} (@peq A ==> R)%signatureT. Proof. intros hr x ? ? e. destruct e. apply hr. Qed. #[universes(polymorphic), export] Instance All_proper {A} : CMorphisms.Proper ((pointwise_relation A iffT) ==> peq ==> iffT) All. Proof. intros f g Hfg x y e. destruct e. split; apply All_impl, Hfg. Qed. #[universes(polymorphic), export] Instance eq_proper_proxy@{i} {A : Type@{i}} (x : A) : ProperProxy@{i i} peq x. Proof. red. exact peq_refl. Defined. #[universes(polymorphic), export] Instance peq_equiv {A} : Equivalence (@peq A). Proof. split. Admitted. Lemma rewrite_all {l : plist nat} (Q : nat -> Type) : All (fun x => Q x) l -> All (fun x => Q (x + 0)) l. Proof. intros a. setoid_rewrite add_0_r_peq. exact a. Qed. Lemma rewrite_all_in {l : plist nat} (Q : nat -> Type) : All (fun x => Q (x + 0)) l -> All (fun x => Q x) l. Proof. intros a. Show Universes. setoid_rewrite add_0_r_peq in a. exact a. Qed. Lemma rewrite_all_in2 {l : plist nat} (Q : nat -> Type) (R : nat -> Type) : All (fun x => pprod (Q (x + 0)%nat) (R x))%type l -> All (fun x => pprod (Q x) (R x))%type l. Proof. intros a. setoid_rewrite add_0_r_peq in a. exact a. Qed. End Polymorphism. rocq-9.2.0/test-suite/success/setoid_test2.v000066400000000000000000000205671516144147600210660ustar00rootroot00000000000000Require Export Setoid. (* Testare: +1. due setoidi con ugualianza diversa sullo stesso tipo +2. due setoidi sulla stessa uguaglianza +3. due morfismi sulla stessa funzione ma setoidi diversi +4. due morfismi sulla stessa funzione e stessi setoidi +5. setoid_replace +6. solo cammini mal tipati +7. esempio (f (g (h E1))) dove h:(T1,=1) -> T2, g:T2->(T3,=3), f:(T3,=3)->Prop +8. test con occorrenze non lineari del pattern +9. test in cui setoid_replace fa direttamente fallback su replace 10. sezioni +11. goal con impl +12. testare *veramente* setoid_replace (ora testato solamente il caso di fallback su replace) Incompatibilita': 1. full_trivial in setoid_replace 2. "as ..." per "Add Setoid" 3. ipotesi permutate in lemma di "Add Morphism" 4. iff invece di if in "Add Morphism" nel caso di predicati 5. setoid_replace poteva riscrivere sia c1 in c2 che c2 in c1 (???? o poteva farlo da destra a sinitra o viceversa? ????) ### Come evitare di dover fare "Require Setoid" prima di usare la tattica? ??? scelta: quando ci sono piu' scelte dare un warning oppure fallire? difficile quando la tattica e' rewrite ed e' usata in tattiche automatiche ??? in test4.v il setoid_rewrite non si puo' sostituire con rewrite perche' questo ultimo fallisce per via dell'unificazione ??? ??? <-> non e' sottorelazione di ->. Quindi ora puo' capitare di non riuscire a provare goal del tipo A /\ B dove (A, <->) e (B, ->) (per esempio) ### Nota: il parsing e pretty printing delle relazioni non e' in synch! eq contro (ty,eq). Uniformare ### diminuire la taglia dei proof term ??? il messaggio di errore non e' assolutamente significativo quando nessuna marcatura viene trovata ### fare in modo che uscendo da una sezione vengano quantificate le relazioni e i morfismi. Hugo: paciugare nel discharge.ml ### implementare relazioni/morfismi quantificati con dei LetIn (che palle...) decompose_prod da far diventare simile a un Reduction.dest_arity? (ma senza riduzione??? e perche' li' c'e' riduzione?) Soluzione da struzzo: fare zeta-conversione. ### fare in modo che impl sia espanso nel lemma di compatibilita' del morfismo (richiesta di Marco per poter fare Add Hing) ??? snellire la sintassi omettendo "proved by" come proposto da Marco? ;-( ### non capisce piu' le riscritture con uguaglianze quantificate (almeno nell'esempio di Marco) ### Bas Spitters: poter dichiarare che ogni variabile nel contesto di tipo un setoid_function e' un morfismo ### unificare le varie check_... ### sostituire a Use_* una sola eccezione Optimize Implementare: -2. user-defined subrelations && user-proved subrelations -1. trucco di Bruno Sorgenti di inefficacia: 1. scelta del setoide di default per un sostegno: per farlo velocemente ci vorrebbe una tabella hash; attualmente viene fatta una ricerca lineare sul range della setoid_table Vantaggi rispetto alla vecchia tattica: 1. permette di avere setoidi differenti con lo stesso sostegno, ma equivalenza differente 2. accetta setoidi differenti con lo stesso sostegno e stessa equivalenza, scegliendo a caso quello da usare (proof irrelevance) 3. permette di avere morfismi differenti sulla stessa funzione se hanno dominio o codominio differenti 4. accetta di avere morfismi differenti sulla stessa funzione e con lo stesso dominio e codominio, scegliendo a caso quello da usare (proof irrelevance) 5. quando un morfismo viene definito, se la scelta del dominio o del codominio e' ambigua l'utente puo' esplicitamente disambiguare la scelta fornendo esplicitamente il "tipo" del morfismo 6. permette di gestire riscritture ove ad almeno una funzione venga associato piu' di un morfismo. Vengono automaticamente calcolate le scelte globali che rispettano il tipaggio. 7. se esistono piu' scelte globali che rispettano le regole di tipaggio l'utente puo' esplicitamente disambiguare la scelta globale fornendo esplicitamente la scelta delle side conditions generate. 8. nel caso in cui la setoid_replace sia stata invocata al posto della replace la setoid_replace invoca direttamente la replace. Stessa cosa per la setoid_rewrite. 9. permette di gestire termini in cui il prefisso iniziale dell'albero (fino a trovare il termine da riscrivere) non sia formato esclusivamente da morfismi il cui dominio e codominio sia un setoide. Ovvero ammette anche morfismi il cui dominio e/o codominio sia l'uguaglianza di Leibniz. (Se entrambi sono uguaglianze di Leibniz allora il setoide e' una semplice funzione). 10. [setoid_]rewrite ... in ... setoid_replace ... in ... [setoid_]reflexivity [setoid_]transitivity ... [setoid_]symmetry [setoid_]symmetry in ... 11. permette di dichiarare dei setoidi/relazioni/morfismi in un module type 12. relazioni, morfismi e setoidi quantificati *) Axiom S1: Set. Axiom eqS1: S1 -> S1 -> Prop. Axiom SetoidS1 : Setoid_Theory S1 eqS1. Add Setoid S1 eqS1 SetoidS1 as S1setoid. #[export] Instance eqS1_default : DefaultRelation eqS1 := {}. Axiom eqS1': S1 -> S1 -> Prop. Axiom SetoidS1' : Setoid_Theory S1 eqS1'. Axiom SetoidS1'_bis : Setoid_Theory S1 eqS1'. Add Setoid S1 eqS1' SetoidS1' as S1setoid'. Add Setoid S1 eqS1' SetoidS1'_bis as S1setoid''. Axiom S2: Set. Axiom eqS2: S2 -> S2 -> Prop. Axiom SetoidS2 : Setoid_Theory S2 eqS2. Add Setoid S2 eqS2 SetoidS2 as S2setoid. Axiom f : S1 -> nat -> S2. Add Morphism f with signature (eqS1 ==> eq ==> eqS2) as f_compat. Admitted. Add Morphism f with signature (eqS1 ==> eq ==> eqS2) as f_compat2. Admitted. Theorem test1: forall x y, (eqS1 x y) -> (eqS2 (f x 0) (f y 0)). intros. rewrite H. reflexivity. Qed. Theorem test1': forall x y, (eqS1 x y) -> (eqS2 (f x 0) (f y 0)). intros. setoid_replace x with y. reflexivity. assumption. Qed. Axiom g : S1 -> S2 -> nat. Add Morphism g with signature (eqS1 ==> eqS2 ==> eq) as g_compat. Admitted. Axiom P : nat -> Prop. Theorem test2: forall x x' y y', (eqS1 x x') -> (eqS2 y y') -> (P (g x' y')) -> (P (g x y)). intros. rewrite H. rewrite H0. assumption. Qed. Theorem test3: forall x x' y y', (eqS1 x x') -> (eqS2 y y') -> (P (S (g x' y'))) -> (P (S (g x y))). intros. rewrite H. rewrite H0. assumption. Qed. Theorem test4: forall x x' y y', (eqS1 x x') -> (eqS2 y y') -> (S (g x y)) = (S (g x' y')). intros. rewrite H. rewrite H0. reflexivity. Qed. Theorem test5: forall x x' y y', (eqS1 x x') -> (eqS2 y y') -> (S (g x y)) = (S (g x' y')). intros. setoid_replace (g x y) with (g x' y'). reflexivity. rewrite <- H0. rewrite H. reflexivity. Qed. Axiom f_test6 : S2 -> Prop. Add Morphism f_test6 with signature (eqS2 ==> iff) as f_test6_compat. Admitted. Axiom g_test6 : bool -> S2. Add Morphism g_test6 with signature (eq ==> eqS2) as g_test6_compat. Admitted. Axiom h_test6 : S1 -> bool. Add Morphism h_test6 with signature (eqS1 ==> eq) as h_test6_compat. Admitted. Theorem test6: forall E1 E2, (eqS1 E1 E2) -> (f_test6 (g_test6 (h_test6 E2))) -> (f_test6 (g_test6 (h_test6 E1))). intros. rewrite H. assumption. Qed. Theorem test7: forall E1 E2 y y', (eqS1 E1 E2) -> (eqS2 y y') -> (f_test6 (g_test6 (h_test6 E2))) -> (f_test6 (g_test6 (h_test6 E1))) /\ (S (g E1 y')) = (S (g E2 y')). intros. rewrite H. split; [assumption | reflexivity]. Qed. Axiom S1_test8: Set. 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. #[export] 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. 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'. (*CSC: for test8 to be significant I want to choose the setoid (S1_test8, eqS1_test8'). However this does not happen and there is still no syntax for it ;-( *) Axiom g_test8 : S1_test8 -> S2. Add Morphism g_test8 with signature (eqS1_test8 ==> eqS2) as g_compat_test8. Admitted. Theorem test8: forall x x': S2, (eqS2 x x') -> (eqS2 (g_test8 (f_test8 x)) (g_test8 (f_test8 x'))). intros. rewrite H. Abort. (*Print Setoids.*) rocq-9.2.0/test-suite/success/setoid_test_function_space.v000066400000000000000000000021631516144147600240540ustar00rootroot00000000000000Require Export Setoid. Set Implicit Arguments. Section feq. Variables A B:Type. Definition feq (f g: A -> B):=forall a, (f a)=(g a). Infix "=f":= feq (at level 80, right associativity). Hint Unfold feq. Lemma feq_refl: forall f, f =f f. intuition. Qed. Lemma feq_sym: forall f g, f =f g-> g =f f. intuition. Qed. Lemma feq_trans: forall f g h, f =f g-> g =f h -> f =f h. unfold feq. intuition. rewrite H. auto. Qed. End feq. Infix "=f":= feq (at level 80, right associativity). #[export] Hint Unfold feq. #[export] Hint Resolve feq_refl feq_sym feq_trans. Parameter K:(nat -> nat)->Prop. Parameter K_ext:forall a b, (K a)->(a =f b)->(K b). Add Parametric Relation (A B : Type) : (A -> B) (@feq A B) reflexivity proved by (@feq_refl A B) symmetry proved by (@feq_sym A B) transitivity proved by (@feq_trans A B) as funsetoid. Add Morphism K with signature (@feq nat nat) ==> iff as K_ext1. intuition. apply (K_ext H0 H). intuition. assert (y =f x);auto. apply (K_ext H0 H1). Qed. Lemma three:forall n, forall a, (K a)->(a =f (fun m => (a (n+m))))-> (K (fun m => (a (n+m)))). intuition. setoid_rewrite <- H0. assumption. Qed. rocq-9.2.0/test-suite/success/setoid_unif.v000066400000000000000000000016261516144147600207610ustar00rootroot00000000000000(* An example of unification in rewrite which uses eager substitution of metas (provided by Pierre-Marie). Put in the test suite as an indication of what the use metas eagerly flag provides, even though the concrete cases that use it are seldom. Today supported thanks to a new flag for using evars eagerly, after this variant of setoid rewrite started to use clause environments based on evars (fbbe491cfa157da627) *) Require Import Setoid. Parameter elt : Type. Parameter T : Type -> Type. Parameter empty : forall A, T A. Parameter MapsTo : forall A : Type, elt -> A -> T A -> Prop. (* Definition In A x t := exists e, MapsTo A x e t. *) Axiom In : forall A, A -> T A -> Prop. Axiom foo : forall A x, In A x (empty A) <-> False. Record R := { t : T unit; s : unit }. Definition Empty := {| t := empty unit; s := tt |}. Goal forall x, ~ In _ x (t Empty). Proof. intros x. rewrite foo. Abort. rocq-9.2.0/test-suite/success/shrink_abstract.v000066400000000000000000000003061516144147600216240ustar00rootroot00000000000000Definition foo : forall (n m : nat), bool. Proof. pose (p := 0). intros n. pose (q := n). intros m. pose (r := m). abstract (destruct m; [left|right]). Defined. Check (foo_subproof : nat -> bool). rocq-9.2.0/test-suite/success/shrink_obligations.v000066400000000000000000000011331516144147600223320ustar00rootroot00000000000000Require Program.Basics Program.Tactics. Obligation Tactic := idtac. Program Definition foo (m : nat) (p := S m) (n : nat) (q := S n) : unit := let bar : {r | n < r} := _ in let qux : {r | p < r} := _ in let quz : m = n -> True := _ in tt. Next Obligation. intros m p n q. exists (S n); constructor. Qed. Next Obligation. intros m p n q. exists (S (S m)); constructor. Qed. Next Obligation. intros m p n q ? ? H. destruct H. constructor. Qed. Check (foo_obligation_1 : forall n, {r | n < r}). Check (foo_obligation_2 : forall m, {r | (S m) < r}). Check (foo_obligation_3 : forall m n, m = n -> True). rocq-9.2.0/test-suite/success/sideff.v000066400000000000000000000005101516144147600177000ustar00rootroot00000000000000Definition idw (A : Type) := A. Lemma foobar : unit. Proof. Require Import Program.Basics Program.Tactics. apply (const tt tt). Qed. Set Nested Proofs Allowed. Lemma foobar' : unit. Lemma aux : forall A : Type, A -> unit. Proof. intros. pose (foo := idw A). exact tt. Show Universes. Qed. apply (@aux unit tt). Qed. rocq-9.2.0/test-suite/success/simpl.v000066400000000000000000000254621516144147600176010ustar00rootroot00000000000000Require Import TestSuite.admit. (* Check that inversion of names of mutual inductive fixpoints works *) (* (cf BZ#1031) *) Inductive tree : Set := | node : nat -> forest -> tree with forest : Set := | leaf : forest | cons : tree -> forest -> forest . Definition copy_of_compute_size_forest := fix copy_of_compute_size_forest (f:forest) : nat := match f with | leaf => 1 | cons t f0 => copy_of_compute_size_forest f0 + copy_of_compute_size_tree t end with copy_of_compute_size_tree (t:tree) : nat := match t with | node _ f => 1 + copy_of_compute_size_forest f end for copy_of_compute_size_forest . Eval simpl in (copy_of_compute_size_forest leaf). (* Another interesting case: Hrec has two occurrences: one cannot be folded back to f while the second can. *) Parameter g : (nat->nat)->nat->nat->nat. Definition f (n n':nat) := nat_rec (fun _ => nat -> nat) (fun x => x) (fun k Hrec => g Hrec (Hrec k)) n n'. Goal forall a b, f (S a) b = b. intros. simpl. match goal with [ |- g (f a) (f a a) b = b ] => idtac end. admit. Qed. (* Yet another example. *) Require Import TestSuite.list. Goal forall A B (a:A) l f (i:B), fold_right f i ((a :: l))=i. intros. simpl. match goal with [ |- f0 a (fold_right f0 i l) = i ] => idtac end. admit. Qed. (* Qed will fail if simplification is incorrect (de Bruijn!) *) (* Check that maximally inserted arguments do not break interpretation of references in simpl, vm_compute etc. *) Arguments fst {A} {B} p. Goal fst (0,0) = 0. simpl fst. Fail set (fst _). Abort. Goal fst (0,0) = 0. vm_compute fst. Fail set (fst _). Abort. Goal let f x := x + 0 in f 0 = 0. intro. vm_compute f. Fail set (f _). Abort. (* This is a change wrt 8.4 (waiting to know if it breaks script a lot or not)*) Goal 0+0=0. Fail simpl @eq. Abort. (* Check reference by notation in simpl *) Goal 0+0 = 0. simpl "+". Fail set (_ + _). Abort. (* Check occurrences *) Record box A := Box { unbox : A }. Goal unbox _ (unbox _ (unbox _ (Box _ (Box _ (Box _ True))))) = unbox _ (unbox _ (unbox _ (Box _ (Box _ (Box _ True))))). simpl (unbox _ (unbox _ _)) at 1. match goal with |- True = unbox _ (unbox _ (unbox _ (Box _ (Box _ (Box _ True))))) => idtac end. Undo 2. Fail simpl (unbox _ (unbox _ _)) at 5. simpl (unbox _ (unbox _ _)) at 1 4. match goal with |- True = unbox _ (Box _ True) => idtac end. Undo 2. Fail simpl (unbox _ (unbox _ _)) at 3 4. (* Nested and even overlapping *) simpl (unbox _ (unbox _ _)) at 2 4. match goal with |- unbox _ (Box _ True) = unbox _ (Box _ True) => idtac end. Abort. (* Check interpretation of ltac variables (was broken in 8.5 beta 1 and 2 *) Goal 2=1+1. match goal with |- (_ = ?c) => simpl c end. match goal with |- 2 = 2 => idtac end. (* Check that it reduced *) Abort. Module FurtherAppliedPrimitiveProjections. Set Primitive Projections. Record T := { u : nat -> nat }. Goal {| u:= fun x => x |}.(u) 0 = 0. simpl u. match goal with |- 0 = 0 => idtac end. (* Check that it reduced *) Abort. End FurtherAppliedPrimitiveProjections. Module BugUniverseMutualFix. Set Universe Polymorphism. Fixpoint foo1@{u v} (A : Type@{u}) n : Type@{v} := match n with 0 => A | S n => (foo2 A n * A)%type end with foo2@{u v} (A : Type@{u}) n : Type@{v} := match n with 0 => A | S n => (foo1 A n * A)%type end. Set Printing Universes. Definition bar@{u} (A : Type@{u}) n := foo1@{u u} A n. Goal forall n, bar unit (S n) = unit. simpl. Abort. End BugUniverseMutualFix. Module PolyUniverses. (* An example showing that the cache needs to take universes into account *) Set Universe Polymorphism. Record cell T S := Cell { hd : T; tl : S }. Arguments Cell {_ _}. Arguments hd {_ _}. Arguments tl {_ _}. Notation "x ::: y" := (Cell x y) (at level 60). Definition ilist T n := @Nat.iter n Type (cell T) unit. Fixpoint imap@{u u0 u1 u2} (T:Type@{u}) (S:Type@{u0}) (f : T -> S) n : ilist@{u2 u1} T n -> ilist@{u0 u1} S n := match n with | 0 => fun l => tt | S n => fun l => f l.(hd) ::: imap _ _ f _ l.(tl) end. Lemma imap_eq (T S : Type) (f g : T -> S) : forall n, forall x, @imap _ _ f n x = @imap _ _ g n x. induction n. intro; auto. intros []. Abort. End PolyUniverses. Module WithLet. Section S. Variable a : nat. Let b := 0. Variable c : nat. Fixpoint f n := match n with | 0 => a + b + c | S n => f n end. End S. Definition f' a c n := f a c n. Lemma L a c n : f' a c (S n) = f a c (S n). simpl. match goal with [ |- f' a c n = f a c n ] => idtac end. Abort. End WithLet. Module WithLetMutual. Section S. Context (a : nat) (b := 0) (c : nat). Fixpoint f n := match n with 0 => a + b + c | S n => g n end with g n := match n with 0 => a + b + c | S n => f n end. End S. Definition f' a c n := f a c n. Lemma L a c n : f' a c (S n) = f a c (S n). simpl. match goal with [ |- g a c n = g a c n ] => idtac end. Abort. End WithLetMutual. Module IotaTrigger1. Definition a x := match x with true => tt | false => tt end. Definition b x (y : unit) := a x. Definition c x := b x tt. Goal a true = tt. simpl. match goal with [ |- tt = tt ] => idtac end. Abort. Goal b true = fun _ => tt. simpl. match goal with [ |- b true = _ ] => idtac end. Abort. Goal c true = tt. simpl. match goal with [ |- tt = tt ] => idtac end. Abort. End IotaTrigger1. Module IotaTrigger2. Definition a x := match x with true => fun _ => tt | false => fun _ => tt end tt. Definition b x (y : unit) := a x. Definition c x := b x tt. Goal a true = tt. simpl. match goal with [ |- tt = tt ] => idtac end. Abort. Goal b true = fun _ => tt. simpl. match goal with [ |- b true = _ ] => idtac end. Abort. Goal c true = tt. simpl. match goal with [ |- tt = tt ] => idtac end. Abort. End IotaTrigger2. Module IotaTrigger3. Fixpoint f_fix_fun n := match n with 0 => fun _ : unit => true | S n => f_fix_fun n end. Definition test_fix_fun n := f_fix_fun n. Goal test_fix_fun 2 = fun _ => true. simpl. match goal with [ |- (fun _ => true) = _ ] => idtac end. Abort. Goal forall x, test_fix_fun (S x) = fun _ => true. intro. simpl. match goal with [ |- test_fix_fun x = _ ] => idtac end. Abort. (* REDUCED *) Definition test_fix_fun_partial n (x:unit) := f_fix_fun n. Goal test_fix_fun_partial 2 = fun _ _ => true. simpl. match goal with [ |- test_fix_fun_partial 2 = _ ] => idtac end. Abort. Goal forall x, test_fix_fun_partial (S x) = fun _ _ => true. intro. simpl. match goal with [ |- test_fix_fun_partial (S x) = _ ] => idtac end. Abort. (* NOT REDUCED: design choice that it is not enough fully applied to trigger the reduction *) (* remark: the presence of an inner "fun" does not matter *) Fixpoint f_fix n := match n with 0 => fun _ : unit => true | S n => f_fix n end. Definition test_fix n := f_fix n tt. Goal test_fix 2 = true. simpl. match goal with [ |- test_fix 2 = _ ] => idtac end. Abort. Goal forall x, test_fix (S x) = true. intro. simpl. match goal with [ |- test_fix (S x) = _ ] => idtac end. Abort. (* NOT REDUCED: design choice that we couldn't refold to test_fix after reduction *) Fixpoint f_mutual_fix n := match n with 0 => true | S n => g n end with g n := match n with 0 => true | S n => f_mutual_fix n end. Definition test_mutual_fix n := f_mutual_fix n. Goal test_mutual_fix 2 = true. simpl. match goal with [ |- true = _ ] => idtac end. Abort. Goal forall x, test_mutual_fix (S x) = true. intro. simpl. match goal with [ |- g x = _ ] => idtac end. Abort. (* REDUCED: design choice that mutual fixpoints refold to last encapsulating name *) Definition test_mutual_fix_partial n (x:unit) := f_mutual_fix n. Goal test_mutual_fix_partial 2 = fun _ => true. simpl. match goal with [ |- test_mutual_fix_partial 2 = _ ] => idtac end. Abort. Goal forall x, test_mutual_fix_partial (S x) = fun _ => true. intro. simpl. match goal with [ |- test_mutual_fix_partial (S x) = _ ] => idtac end. Abort. (* NOT REDUCED: design choice that it is not enough fully applied to trigger the reduction *) (* Moreover, was failing between #17993 and #18243 (see #18239) *) Fixpoint f_mutual_fix_cut n := match n with 0 => fun _ : unit => true | S n => g_cut n end with g_cut n := match n with 0 => fun _ : unit => true | S n => f_mutual_fix_cut n end. Definition test_mutual_fix_cut n := f_mutual_fix_cut n tt. Goal test_mutual_fix_cut 2 = true. simpl. match goal with [ |- true = _ ] => idtac end. Abort. Goal forall x, test_mutual_fix_cut (S x) = true. intro. simpl. match goal with [ |- g_cut x tt = _ ] => idtac end. Abort. (* REDUCED: by consistency with test_mutual_fix, which itself already differs from the case of a unary fix (new behavior from #18243) *) Definition test_mutual_fix_cut_partial n (x:unit) := f_mutual_fix_cut n x. Goal test_mutual_fix_cut_partial 2 = fun _ => true. simpl. match goal with [ |- test_mutual_fix_cut_partial 2 = _ ] => idtac end. Abort. Goal forall x, test_mutual_fix_cut_partial (S x) = fun _ => true. intro. simpl. match goal with [ |- test_mutual_fix_cut_partial (S x) = _ ] => idtac end. Abort. (* NOT REDUCED: by consistency with test_fix_fun_partial and test_mutual_fix_cut_partial *) (* Moreover was failing before #18243 (see #18239) *) Definition f_case n := match n with 0 => fun _ : unit => true | S n => fun _ => true end. Definition test_case n := f_case n tt. Goal test_case 2 = true. simpl. match goal with [ |- true = _ ] => idtac end. Abort. (* REDUCED *) End IotaTrigger3. Module Bug4056. CoInductive stream {A:Type} : Type := | scons: A->stream->stream. Definition stream_unfold {A} (s: @ stream A) := match s with | scons a s' => (a, scons a s') end. Section A. CoFixpoint inf_stream1 (x:nat) (n:nat) := scons n (inf_stream1 x (n+x)). End A. Section B. Variable (x:nat). CoFixpoint inf_stream2 (n:nat) := scons n (inf_stream2 (n+x)). End B. Goal (forall x n, stream_unfold (inf_stream1 x n) = stream_unfold (inf_stream2 x n)). (* simpl was exposing the cofix on the rhs but not the lhs *) intros. simpl. match goal with [ |- (n, scons n (inf_stream1 x (n + x))) = (n, scons n (inf_stream2 x (n + x))) ] => idtac end. Abort. Section C. Variable (x:nat). CoFixpoint mut_stream1 (n:nat) := scons n (mut_stream2 (n+x)) with mut_stream2 (n:nat) := scons n (mut_stream1 (n+x)). End C. Goal (forall x n, stream_unfold (mut_stream1 x n) = stream_unfold (mut_stream2 x n)). intros. simpl. match goal with [ |- (n, scons n (mut_stream2 x (n + x))) = (n, scons n (mut_stream1 x (n + x))) ] => idtac end. Abort. Definition inf_stream2_copy n := inf_stream2 n. (* inversible *) Definition mut_stream2_copy n := mut_stream2 n. (* inversible only towards mut_stream1/mut_stream2 *) Goal (forall x n, stream_unfold (inf_stream2_copy x n) = stream_unfold (mut_stream2_copy x n)). intros. simpl. match goal with [ |- (n, scons n (inf_stream2_copy x (n + x))) = (n, scons n (mut_stream1 x (n + x))) ] => idtac end. Abort. End Bug4056. Module RefoldingOfNeverConstantInArgOfDestructor. Arguments Nat.add : simpl never. Goal forall n, (S n + 1) * n = 0. intros. simpl. match goal with [ |- n + (n + 1) * n = 0 ] => idtac end. Abort. End RefoldingOfNeverConstantInArgOfDestructor. rocq-9.2.0/test-suite/success/simpl_tuning.v000066400000000000000000000103501516144147600211530ustar00rootroot00000000000000(* as it is dynamically inferred by simpl *) Arguments minus !n / m. Lemma foo x y : S (S x) - S y = 0. simpl. match goal with |- (match y with O => S x | S _ => _ end = 0) => idtac end. Abort. (* we avoid exposing a match *) Arguments minus n m : simpl nomatch. Lemma foo x : minus 0 x = 0. simpl. match goal with |- (0 = 0) => idtac end. Abort. Lemma foo x y : S (S x) - S y = 0. simpl. match goal with |- (S x - y = 0) => idtac end. Abort. Lemma foo x y : S (S x) - (S (match y with O => O | S z => S z end)) = 0. simpl. match goal with |-(S x - (match y with O => _ | S _ => _ end) = 0) => idtac end. Abort. (* we unfold as soon as we have 1 args, but we avoid exposing a match *) Arguments minus n / m : simpl nomatch. Lemma foo : minus 0 = fun x => 0. simpl. match goal with |- minus 0 = _ => idtac end. Abort. (* This does not work as one may expect. The point is that simpl is implemented as "strong (whd_simpl_state)" and after unfolding minus you have (fun m => match 0 => 0 | S n => ...) that is already in whd and exposes a match, that of course "strong" would reduce away but at that stage we don't know, and reducing by hand under the lambda is against whd *) (* extra tuning for the usual heuristic *) Arguments minus !n / m : simpl nomatch. Lemma foo x y : S (S x) - S y = 0. simpl. match goal with |- (S x - y = 0) => idtac end. Abort. Lemma foo x y : S (S x) - (S (match y with O => O | S z => S z end)) = 0. simpl. match goal with |-(S x - (match y with O => _ | S _ => _ end) = 0) => idtac end. Abort. (* full control *) Arguments minus !n !m /. Lemma foo x y : S (S x) - S y = 0. simpl. match goal with |- (S x - y = 0) => idtac end. Abort. Lemma foo x y : S (S x) - (S (match y with O => O | S z => S z end)) = 0. simpl. match goal with |-(S x - (match y with O => _ | S _ => _ end) = 0) => idtac end. Abort. (* omitting /, that being immediately after the last ! is irrelevant *) Arguments minus !n !m. Lemma foo x y : S (S x) - S y = 0. simpl. match goal with |- (S x - y = 0) => idtac end. Abort. Lemma foo x y : S (S x) - (S (match y with O => O | S z => S z end)) = 0. simpl. match goal with |-(S x - (match y with O => _ | S _ => _ end) = 0) => idtac end. Abort. Definition pf (D1 C1 : Type) (f : D1 -> C1) (D2 C2 : Type) (g : D2 -> C2) := fun x => (f (fst x), g (snd x)). Delimit Scope foo_scope with F. Notation "@@" := nat (only parsing) : foo_scope. Notation "@@" := (fun x => x) (only parsing). Arguments pf {D1%_F C1%_type} f [D2 C2] g x : simpl never. Lemma foo x : @pf @@ nat @@ nat nat @@ x = pf @@ @@ x. Abort. Definition fcomp A B C f (g : A -> B) (x : A) : C := f (g x). (* fcomp is unfolded if applied to 6 args *) Arguments fcomp {A B C}%_type f g x /. Notation "f \o g" := (fcomp f g) (at level 50). Lemma foo (f g h : nat -> nat) x : pf (f \o g) h x = pf f h (g (fst x), snd x). simpl. match goal with |- (pf (f \o g) h x = _) => idtac end. case x; intros x1 x2. simpl. match goal with |- (pf (f \o g) h _ = pf f h _) => idtac end. unfold pf; simpl. match goal with |- (f (g x1), h x2) = (f (g x1), h x2) => idtac end. Abort. Definition volatile := fun x : nat => x. Arguments volatile / _. Lemma foo : volatile = volatile. simpl. match goal with |- (fun _ => _) = _ => idtac end. Abort. Set Implicit Arguments. Section S1. Variable T1 : Type. Section S2. Variable T2 : Type. Fixpoint f (x : T1) (y : T2) n (v : unit) m {struct n} : nat := match n, m with | 0,_ => 0 | S _, 0 => n | S n', S m' => f x y n' v m' end. Global Arguments f x y !n !v !m. Lemma foo x y n m : f x y (S n) tt m = f x y (S n) tt (S m). simpl. match goal with |- (f _ _ _ _ _ = f _ _ _ _ _) => idtac end. Abort. End S2. Lemma foo T x y n m : @f T x y (S n) tt m = @f T x y (S n) tt (S m). simpl. match goal with |- (f _ _ _ _ _ = f _ _ _ _ _) => idtac end. Abort. End S1. Arguments f : clear implicits and scopes. Module TestClearSimpl. Fail Arguments id _ x / : clear simpl. Fail Arguments id _ ! x : clear simpl. Fail Arguments id _ : simpl never, clear simpl. Fail Arguments id _ : simpl nomatch, clear simpl. Arguments id _ x /. Lemma foo : id 0 = 0. simpl. match goal with |- 0 = 0 => idtac end. Abort. Arguments id _ x : clear simpl. Lemma foo : id 0 = 0. simpl. match goal with |- id 0 = 0 => idtac end. Abort. End TestClearSimpl. rocq-9.2.0/test-suite/success/simple_congruence.v000066400000000000000000000042161516144147600221500ustar00rootroot00000000000000Axiom P : Prop. Definition Q := True -> P. (* bug 13778, 5394 *) Goal Q -> Q. Proof. intro. Fail congruence. simple congruence. Qed. Goal (not P) -> P -> False. Proof. simple congruence. Qed. Goal (P -> False) -> not P. Proof. simple congruence. Qed. Fixpoint slow (n: nat): bool := match n with | O => true | S m => andb (slow m) (slow (pred m)) end. Parameter f: nat -> nat. Definition foo(n b: nat): Prop := if slow n then (forall a, f a = f b) else True. (* fail fast symbolically *) (* bug 13189 *) Goal forall a b, foo 27 b -> f a = f b. Proof. Timeout 1 Fail Time simple congruence. (* Fail Timeout 1 Time congruence. *) Admitted. (* succeed fast symbolically *) (* bug 13189 *) Goal forall a b, foo 29 b -> f b = f a -> f a = f b. Proof. (* Fail Timeout 1 Time congruence. *) Timeout 1 simple congruence. Qed. Goal True -> not True -> P. Proof. simple congruence. Qed. (* consider final not *) Goal False -> not True. Proof. simple congruence. Qed. (* consider final not *) Goal not (true = false). Proof. simple congruence. Qed. Fixpoint stupid (n : nat) : unit := match n with | 0 => tt | S n => let () := stupid n in let () := stupid n in tt end. (* do not try to unify 23 with stupid 23 *) Goal 23 = 23 -> stupid 23 = stupid 23. Proof. Timeout 1 simple congruence. Qed. Inductive Fin : nat -> Set := | F1 : forall n : nat, Fin (S n) | FS : forall n : nat, Fin n -> Fin (S n). (* indexed inductives *) Goal forall n (f : Fin n), FS n f = F1 n -> False. Proof. intros n f H. simple congruence. Qed. Axiom R : Prop. Axiom R' : Prop. Goal (not P) -> not P. Proof. simple congruence. Qed. Goal (P -> False) -> P -> False. Proof. simple congruence. Qed. Goal (not (true = true)) -> P. Proof. simple congruence. Qed. Goal Q -> (Q = R) -> R. Proof. simple congruence. Qed. (* unfortunately, common usecase *) Goal P -> Q. Proof. Fail simple congruence. repeat intro. simple congruence. Qed. (* bug 13778 *) Goal R -> (R = not P) -> not P. Proof. Fail congruence. simple congruence. Qed. Definition per_unit := forall u, match u with tt => True end. (* bug 5394 *) Goal per_unit -> per_unit. Proof. simple congruence. Qed. rocq-9.2.0/test-suite/success/somatching.v000066400000000000000000000027761516144147600206140ustar00rootroot00000000000000Goal forall A B C (p : forall (x : A) (y : B), C x y) (x : A) (y : B), True. Proof. intros A B C p x y. match type of p with | forall x y, @?F x y => pose F as C1 end. match type of p with | forall x y, @?F y x => pose F as C2 end. assert (C1 x y) as ?. assert (C2 y x) as ?. Abort. Goal forall A B C D (p : forall (x : A) (y : B) (z : C), D x y) (x : A) (y : B), True. Proof. intros A B C D p x y. match type of p with | forall x y z, @?F x y => pose F as C1 end. assert (C1 x y) as ?. Abort. Goal forall A B C D (p : forall (z : C) (x : A) (y : B), D x y) (x : A) (y : B), True. Proof. intros A B C D p x y. match type of p with | forall z x y, @?F x y => pose F as C1 end. assert (C1 x y) as ?. Abort. (** Those should fail *) Goal forall A B C (p : forall (x : A) (y : B), C x y) (x : A) (y : B), True. Proof. intros A B C p x y. Fail match type of p with | forall x, @?F x y => pose F as C1 end. Fail match type of p with | forall x y, @?F x x y => pose F as C1 end. Fail match type of p with | forall x y, @?F x => pose F as C1 end. Abort. (** This one is badly typed *) Goal forall A (B : A -> Type) (C : forall x, B x -> Type), (forall x y, C x y) -> True. Proof. intros A B C p. Fail match type of p with | forall x y, @?F y x => idtac end. Abort. Goal forall A (B : A -> Type) (C : Type) (D : forall x, B x -> Type), (forall x (z : C) y, D x y) -> True. Proof. intros A B C D p. match type of p with | forall x z y, @?F x y => idtac end. Abort. rocq-9.2.0/test-suite/success/sort_poly.v000066400000000000000000000226051516144147600205030ustar00rootroot00000000000000Set Universe Polymorphism. Module Syntax. Fail Definition foo@{| Set < Set } := Set. Definition foo@{u| Set < u} := Type@{u}. Definition bar@{s ; u | Set < u} := Type@{u}. Set Printing Universes. Print bar. Definition baz@{s ; } := Type@{s ; Set}. Print baz. Definition potato@{s ; + } := Type. Check eq_refl : Prop = baz@{Prop ; }. Inductive bob@{s ; } : Prop := . End Syntax. Module Reduction. Definition qsort@{s ; u } := Type@{s ; u}. Monomorphic Universe U. Definition tU := Type@{U}. Definition qU := qsort@{Type ; U}. Definition q1 := Eval lazy in qU. Check eq_refl : q1 = tU. Definition q2 := Eval vm_compute in qU. Check eq_refl : q2 = tU. Definition q3 := Eval native_compute in qU. Check eq_refl : q3 = tU. Definition exfalso@{s;u|} (A:Type@{s;u}) (H:False) : A := match H with end. Definition exfalsoVM := Eval vm_compute in exfalso@{Type;Set}. Definition exfalsoNative := Eval native_compute in exfalso@{Type;Set}. Fixpoint iter@{s;u|} (A:Type@{s;u}) (f:A -> A) n x := match n with | 0 => x | S k => iter A f k (f x) end. Definition iterType := Eval lazy in iter@{Type;_}. Definition iterSProp := Eval lazy in iter@{SProp;_}. End Reduction. Module Conversion. Inductive Box@{s;u|} (A:Type@{s;u}) := box (_:A). Definition t1@{s;u|} (A:Type@{s;u}) (x y : A) := box _ x. Definition t2@{s;u|} (A:Type@{s;u}) (x y : A) := box _ y. Definition t1'@{s;u|} (A:Type@{s;u}) (x y : A) := x. Definition t2'@{s;u|} (A:Type@{s;u}) (x y : A) := y. Fail Check eq_refl : t1 nat = t2 nat. Fail Check eq_refl : t1' nat = t2' nat. Check fun A:SProp => eq_refl : t1 A = t2 A. Check fun A:SProp => eq_refl : box _ (t1' A) = box _ (t2' A). Fail Definition equi_eliminable@{s1 s2;|s1 -> s2, s2 -> s1} (A : Type@{s1;Set}) : Type@{s2;Set} := A. Fail Definition equi_eliminable@{s1 s2;|s1 -> s2, s2 -> s1} (A : Type@{s2;Set}) : Type@{s1;Set} := A. Definition ignore@{s;u|} {A:Type@{s;u}} (x:A) := tt. Definition unfold_ignore@{s;u|} (A:Type@{s;u}) : ignore (t1 A) = ignore (t2 A) := eq_refl. Definition t (A:SProp) := Eval lazy in t1 A. Axiom v@{s; |} : forall (A:Type@{s;Set}), bool -> A. Fail Check fun P (x:P (v@{Type;} nat true)) => x : P (v nat false). Check fun (A:SProp) P (x:P (v A true)) => x : P (v A false). End Conversion. Module Inference. Definition zog@{s; |} (A:Type@{s;Set}) := A. (* implicit instance of zog gets a variable which then gets unified with s from the type of A *) Definition zag@{s; |} (A:Type@{s;Set}) := zog A. (* implicit type of A gets unified to Type@{s|Set} *) Definition zig@{s; |} A := zog@{s;} A. (* Unfortunately casting a hole to a sort (while typing A on the left of the arrow) produces a rigid univ level. It gets a constraint "= Set" but rigids don't get substituted away for (bad) reasons. This is why we need the 2 "+". *) Definition zig'@{s; + | +} A := A -> zog@{s;} A. (* different manually bound sort variables don't unify *) Fail Definition zog'@{s s'; |} (A:Type@{s;Set}) := zog@{s';} A. End Inference. Module Inductives. Inductive foo1@{s; |} : Type@{s;Set} := . Fail Check foo1_sind. Definition foo1_False@{s;+|+} (x:foo1@{s;}) : False := match x return False with end. (* s ; |= s -> Prop *) Inductive foo2@{s; |} := Foo2 : Type@{s;Set} -> foo2. Check foo2_rect. Inductive foo3@{s; |} (A:Type@{s;Set}) := Foo3 : A -> foo3 A. Check foo3_rect. Fail Inductive foo4@{s;u v|v < u} : Type@{v} := C (_:Type@{s;u}). Inductive foo5@{s; |} (A:Type@{s;Set}) : Prop := Foo5 (_ : A). Definition foo5_ind'@{s; |} : forall (A : Type@{s;Set}) (P : Prop), (A -> P) -> foo5 A -> P := foo5_ind. (* TODO unify sort variable instead of failing *) Fail Definition foo5_Prop_rect (A:Prop) (P:foo5 A -> Type) (H : forall a, P (Foo5 A a)) (f : foo5 A) : P f := match f with Foo5 _ a => H a end. (* Error: The quality constraints are inconsistent: cannot enforce Prop -> Type because it would identify Type and Prop which is inconsistent. This is introduced by the constraints Prop -> Type *) Definition foo5_Prop_rect (A:Prop) (P:foo5 A -> Type) (H : forall a, P (Foo5 A a)) (f : foo5@{Prop;} A) : P f := match f with Foo5 _ a => H a end. (* all sort poly output with nonzero contructors are squashed (avoid interfering with uip) *) Inductive foo6@{s; |} : Type@{s;Set} := Foo6. Fail Check foo6_sind. Definition foo6_rect@{s;+|+} (P:foo6@{s;} -> Type) (H : P Foo6) (f : foo6) : P f := match f with Foo6 => H end. (* s ; u |= s -> Type *) Definition foo6_prop_rect (P:foo6 -> Type) (H : P Foo6) (f : foo6@{Prop;}) : P f := match f with Foo6 => H end. Definition foo6_type_rect (P:foo6 -> Type) (H : P Foo6) (f : foo6@{Type;}) : P f := match f with Foo6 => H end. Definition foo6_qsort_rect@{s;u|} (P:foo6 -> Type@{s;u}) (H : P Foo6) (f : foo6@{s;}) : P f := match f with Foo6 => H end. Fail Definition foo6_2qsort_rect@{s s';u|} (P:foo6 -> Type@{s;u}) (H : P Foo6) (f : foo6@{s';}) : P f := match f with Foo6 => H end. Inductive foo7@{s; |} : Type@{s;Set} := Foo7_1 | Foo7_2. Fail Check foo7_sind. Fail Check foo7_ind. Definition foo7_prop_ind (P:foo7 -> Prop) (H : P Foo7_1) (H' : P Foo7_2) (f : foo7@{Prop;}) : P f := match f with Foo7_1 => H | Foo7_2 => H' end. Fail Definition foo7_prop_rect (P:foo7 -> Type) (H : P Foo7_1) (H' : P Foo7_2) (f : foo7@{Prop;}) : P f := match f with Foo7_1 => H | Foo7_2 => H' end. Set Primitive Projections. Set Warnings "+records". (* the SProp instantiation may not be primitive so the whole thing must be nonprimitive *) Fail Record R1@{s; |} : Type@{s;Set} := {}. (* the Type instantiation may not be primitive *) Fail Record R2@{s; |} (A:SProp) : Type@{s;Set} := { R2f1 : A }. (* R3@{SProp Type|} may not be primitive *) Fail Record R3@{s s'; |} (A:Type@{s;Set}) : Type@{s';Set} := { R3f1 : A }. Record R4@{s; |} (A:Type@{s;Set}) : Type@{s;Set} := { R4f1 : A}. (* non SProp instantiation must be squashed *) Fail Record R5@{s; |} (A:Type@{s;Set}) : SProp := { R5f1 : A}. Fail #[warnings="-non-primitive-record"] Record R5@{s; |} (A:Type@{s;Set}) : SProp := { R5f1 : A}. #[warnings="-non-primitive-record,-cannot-define-projection"] Record R5@{s; |} (A:Type@{s;Set}) : SProp := { R5f1 : A}. Fail Check R5f1. Definition R5f1_sprop (A:SProp) (r:R5 A) : A := let (f) := r in f. Fail Definition R5f1_prop (A:Prop) (r:R5 A) : A := let (f) := r in f. Record R6@{s; |} (A:Type@{s;Set}) := { R6f1 : A; R6f2 : nat }. Check fun (A:SProp) (x y : R6 A) => eq_refl : Conversion.box _ x.(R6f1 _) = Conversion.box _ y.(R6f1 _). Fail Check fun (A:Prop) (x y : R6 A) => eq_refl : Conversion.box _ x.(R6f1 _) = Conversion.box _ y.(R6f1 _). Fail Check fun (A:SProp) (x y : R6 A) => eq_refl : Conversion.box _ x.(R6f2 _) = Conversion.box _ y.(R6f2 _). #[projections(primitive=no)] Record R7@{s; |} (A:Type@{s;Set}) := { R7f1 : A; R7f2 : nat }. Check R7@{SProp;} : SProp -> Set. Check R7@{Type;} : Set -> Set. Inductive sigma@{s;u v|} (A:Type@{s;u}) (B:A -> Type@{s;v}) : Type@{s;max(u,v)} := pair : forall x : A, B x -> sigma A B. Definition sigma_srect@{s;k +|} A B (P : sigma@{s;_ _} A B -> Type@{s;k}) (H : forall x b, P (pair _ _ x b)) (s:sigma A B) : P s := match s with pair _ _ x b => H x b end. (* squashed because positive type with >0 constructors *) Fail Definition sigma_srect'@{s sk;k +|} A B (P : sigma@{s;_ _} A B -> Type@{sk;k}) (H : forall x b, P (pair _ _ x b)) (s:sigma A B) : P s := match s with pair _ _ x b => H x b end. (* even though it's squashed, we can still define the projections *) Definition pr1@{s;+|} {A B} (s:sigma@{s;_ _} A B) : A := match s with pair _ _ x _ => x end. Definition pr2@{s;+|} {A B} (s:sigma@{s;_ _} A B) : B (pr1 s) := match s with pair _ _ _ y => y end. (* And we can prove eta with implicit elaboration of elimination constraints. We can't prove eta without the constraints. *) Inductive seq@{s;u|} (A:Type@{s;u}) (a:A) : A -> Prop := seq_refl : seq A a a. Arguments seq_refl {_ _}. Definition eta@{s;+|+} A B (s:sigma@{s;_ _} A B) : seq _ s (pair A B (pr1 s) (pr2 s)). Proof. destruct s. simpl. reflexivity. Qed. (* sigma as a primitive record works better *) Record Rsigma@{s;u v|} (A:Type@{s;u}) (B:A -> Type@{s;v}) : Type@{s;max(u,v)} := Rpair { Rpr1 : A; Rpr2 : B Rpr1 }. (* match desugared to primitive projections using definitional eta *) Definition Rsigma_srect@{s sk;k +|} A B (P : Rsigma@{s;_ _} A B -> Type@{sk;k}) (H : forall x b, P (Rpair _ _ x b)) (s:Rsigma A B) : P s := match s with Rpair _ _ x b => H x b end. (* sort polymorphic exists (we could also make B sort poly) can't be a primitive record since the first projection isn't defined at all sorts *) Inductive sexists@{s;u|} (A:Type@{s;u}) (B:A -> Prop) : Prop := sexist : forall a:A, B a -> sexists A B. (* we can eliminate to Prop *) Check sexists_ind. Inductive sigma3@{s s' s'';u v| } (A:Type@{s;u}) (P:A -> Type@{s';v}) : Type@{s'';max(u,v)} := exist3 : forall x:A, P x -> sigma3 A P. Arguments exist3 {_ _}. Definition Ο€1@{s s';u v|} {A:Type@{s;u}} {P:A -> Type@{s';v}} (p : sigma3@{_ _ Type;_ _} A P) : A := match p return A with exist3 a _ => a end. End Inductives. rocq-9.2.0/test-suite/success/sort_poly_destruct.v000066400000000000000000000015331516144147600224150ustar00rootroot00000000000000Set Universe Polymorphism. Inductive sum@{sl sr s;ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) : Type@{s;max(ul,ur)} := | inl : A -> sum A B | inr : B -> sum A B. Arguments inl {_} {_} _. Arguments inr {_} {_} _. Inductive sig@{s s' s'';u v|} (A : Type@{s;u}) (P : A -> Type@{s';v}) : Type@{s'';max(u,v)} := | existsS : forall x, P x -> sig A P. Arguments existsS {_} {_} _ _. Set Printing Universes. Lemma testElim@{s s';u v|s -> s'} : forall (A B : Prop) (P : sum@{Prop Prop s;0 0} A B -> Type@{s';0}) (Q : sum@{Prop Prop s';0 0} A B -> Type@{s';0}) (x : sum@{Prop Prop s;0 0} A B), P x -> sig (sum@{Prop Prop s';0 0} A B) Q. Proof. intros ????? HP. refine (existsS (match x return sum@{Prop Prop s';0 0} A B with | inl x => inl x | inr y => inr y end) _). destruct x. Abort. rocq-9.2.0/test-suite/success/sort_poly_elab.v000066400000000000000000000133051516144147600214630ustar00rootroot00000000000000Set Universe Polymorphism. Inductive sum@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) : Type@{s;max(ul,ur)} := | inl : A -> sum A B | inr : B -> sum A B. Arguments inl {A B} _ , [A] B _. Arguments inr {A B} _ , A [B] _. (* Elimination constraint left explicitly empty. Definition fails because of missing constraint. *) Fail Definition sum_elim@{sl sr s0 s0';ul ur v|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (P : sum@{sl sr s0;ul ur} A B -> Type@{s0';v}) (fl : forall a, P (inl a)) (fr : forall b, P (inr b)) (x : sum@{sl sr s0;ul ur} A B) := match x with | inl a => fl a | inr b => fr b end. (* The command has indeed failed with message: Elimination constraints are not implied by the ones declared: s0->s0' *) (* Using + to elaborate missing constraints. Definition passes *) Definition sum_elim@{sl sr s0 s0';ul ur v|+} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (P : sum@{sl sr s0;ul ur} A B -> Type@{s0';v}) (fl : forall a, P (inl a)) (fr : forall b, P (inr b)) (x : sum@{sl sr s0;ul ur} A B) := match x with | inl a => fl a | inr b => fr b end. (* sl sr s0 s0' ; ul ur v |= s0->s0' *) Definition sum_sind := sum_elim@{Type Type Type SProp;_ _ _}. Definition sum_rect := sum_elim@{Type Type Type Type;_ _ _}. Definition sum_ind := sum_elim@{Type Type Type Prop;_ _ _}. Definition or_ind := sum_elim@{Prop Prop Prop Prop;_ _ _}. Definition or_sind := sum_elim@{Prop Prop Prop SProp;_ _ _}. Fail Definition or_rect := sum_elim@{Prop Prop Prop Type;_ _ _}. (* The command has indeed failed with message: The quality constraints are inconsistent: cannot enforce Prop -> Type because it would identifyType and Prop which is inconsistent. This is introduced by the constraints Type -> Prop *) Definition sumor := sum@{Type Prop Type;_ _}. Definition sumor_sind := sum_elim@{Type Prop Type SProp;_ _ _}. Definition sumor_rect := sum_elim@{Type Prop Type Type;_ _ _}. Definition sumor_ind := sum_elim@{Type Prop Type Prop;_ _ _}. (* Implicit constraints are elaborated *) Definition idT@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Type;ul ur} A B := match x return sum@{sl sr Type;ul ur} A B with | inl a => inl a | inr b => inr b end. (* sl sr s ; ul ur |= s->Type *) (* Implicit constraints are elaborated *) Definition idP@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Prop;ul ur} A B := match x return sum@{sl sr Prop;ul ur} A B with | inl a => inl a | inr b => inr b end. (* sl sr s ; ul ur |= s->Prop *) (* Implicit constraints are elaborated *) Definition idS@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr SProp;ul ur} A B := match x return sum@{sl sr SProp;ul ur} A B with | inl a => inl a | inr b => inr b end. (* sl sr s ; ul ur |= s->SProp *) (* Implicit constraints are elaborated *) Definition idV@{sl sr s s';ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr s';ul ur} A B := match x return sum@{sl sr s';ul ur} A B with | inl a => inl a | inr b => inr b end. (* sl sr s s' ; ul ur |= s->s' *) Inductive List'@{s s';l} (A : Type@{s;l}) : Type@{s';l} := | nil' : List' A | cons' : A -> List' A -> List' A. Arguments nil' {A}. Arguments cons' {A} _ _. Definition list'_elim@{s s0 s';l l'} (A : Type@{s;l}) (P : List'@{s s0;l} A -> Type@{s';l'}) (fn : P nil') (fc : forall (x : A) (l : List' A), P l -> P (cons' x l)) := fix F (l : List'@{s s0;l} A) : P l := match l with | nil' => fn | cons' x l => fc x l (F l) end. (* s s0 s' ; l l' |= s0->s' *) Fixpoint list'_idT@{s s';l} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s Type;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idT l) end. (* s s' ; l |= s'->Type *) Fixpoint list'_idP@{s s';l} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s Prop;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idP l) end. (* s s' ; l |= s'->Prop *) Fixpoint list'_idS@{s s';l} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s SProp;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idS l) end. (* s s' ; l |= s'->SProp *) (* Elimination constraint left explicitly empty. Definition fails because of missing constraint. *) Fail Fixpoint list'_idV@{s s0 s';l l'|l <= l'} {A : Type@{s;l}} (l : List'@{s s0;l} A) : List'@{s s';l'} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idV l) end. (* The command has indeed failed with message: Elimination constraints are not implied by the ones declared: s0->s' *) (* Using + to elaborate missing constraints. Definition passes *) Fixpoint list'_idV@{s s0 s';l l'|l <= l' + } {A : Type@{s;l}} (l : List'@{s s0;l} A) : List'@{s s';l'} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idV l) end. (* s s0 s' ; l l' |= s0->s', l <= l' *) Inductive False'@{s;u} : Type@{s;u} :=. Definition False'_False@{s; +|+} (x : False'@{s;_}) : False := match x return False with end. (* s ; u |= s->Prop *) Inductive bool@{s;u} : Type@{s;u} := true | false. Definition bool_to_Prop@{s;u} (b : bool@{s;u}) : Prop. Proof. destruct b. - exact True. - exact False. Defined. (* s ; u |= s->Type *) Definition bool_to_True_conj@{s;u} (b : bool@{s;u}) : True \/ True. Proof. destruct b. - exact (or_introl I). - exact (or_intror I). Defined. (* s ; u |= s->Prop *) Program Definition bool_to_Prop'@{s;u} (b : bool@{s;u}) : Prop := _. Next Obligation. intro b; destruct b. - exact True. - exact False. Defined. (* s ; u |= s->Type *) Inductive unit@{s;u} : Type@{s;u} := tt. #[universes(polymorphic=no)] Sort Test. Check (match true@{Test;Set} return ?[P] with true => tt | false => tt end). rocq-9.2.0/test-suite/success/sort_poly_elim_csts.v000066400000000000000000000136211516144147600225430ustar00rootroot00000000000000Set Universe Polymorphism. Section Global. Sort s s'. Fail Constraint Prop -> Type. Fail Constraint Type -> Prop. Fail Constraint SProp -> s. Constraint Prop -> s. Constraint s -> Prop. Constraint s -> SProp. Polymorphic Axiom ad@{s;u} : forall A : Type@{s;u}, A. Polymorphic Definition t@{s s';u v|s -> s'} (A : Type@{s;u}) (B : Type@{s';v}) : A := ad A. Fail Check t@{s s';Set Set}. Check t@{s Prop;Set Set}. Check t@{Prop s;Set Set}. Check t@{Type s;Set Set}. Check t@{s' s';Set Set}. Fail Check t@{s Type;Set Set}. End Global. Section Dominant. Sort Exn. Sort Test. Constraint Prop -> Test. Fail Constraint Exn -> Test. Fail Polymorphic Definition test@{s;l|Prop -> s, Exn -> s} (A : Type@{s;l}) : A := ad A. End Dominant. Module Syntax. Fail Definition foo@{u|Type -> Prop} := Type@{u}. Fail Definition foo'@{|Prop -> SProp} := Prop. Definition bar@{s;u|s -> Type} := Type@{s;u}. Definition bar'@{s;u|Prop -> s} := Type@{s;u}. Definition bar''@{s s';|s -> s', s' -> Prop} := Prop. Fail Definition bar'''@{s;|s -> Type, Prop -> s} := Prop. End Syntax. Inductive sum@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) : Type@{s;max(ul,ur)} := | inl : A -> sum A B | inr : B -> sum A B. Arguments inl {A B} _ , [A] B _. Arguments inr {A B} _ , A [B] _. Definition sum_elim@{sl sr s0 s0';ul ur v|s0 -> s0'} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (P : sum@{sl sr s0;ul ur} A B -> Type@{s0';v}) (fl : forall a, P (inl a)) (fr : forall b, P (inr b)) (x : sum@{sl sr s0;ul ur} A B) := match x with | inl a => fl a | inr b => fr b end. Definition sum_sind := sum_elim@{Type Type Type SProp;_ _ _}. Definition sum_rect := sum_elim@{Type Type Type Type;_ _ _}. Definition sum_ind := sum_elim@{Type Type Type Prop;_ _ _}. Definition or_ind := sum_elim@{Prop Prop Prop Prop;_ _ _}. Definition or_sind := sum_elim@{Prop Prop Prop SProp;_ _ _}. Fail Definition or_rect := sum_elim@{Prop Prop Prop Type;_ _ _}. Definition sumor := sum@{Type Prop Type;_ _}. Definition sumor_sind := sum_elim@{Type Prop Type SProp;_ _ _}. Definition sumor_rect := sum_elim@{Type Prop Type Type;_ _ _}. Definition sumor_ind := sum_elim@{Type Prop Type Prop;_ _ _}. Fail Definition idT@{sl sr s;ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Type;ul ur} A B := match x return sum@{sl sr Type;ul ur} A B with | inl a => inl a | inr b => inr b end. Fail Definition idP@{sl sr s;ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Prop;ul ur} A B := match x return sum@{sl sr Prop;ul ur} A B with | inl a => inl a | inr b => inr b end. Fail Definition idS@{sl sr s;ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr SProp;ul ur} A B := match x return sum@{sl sr SProp;ul ur} A B with | inl a => inl a | inr b => inr b end. Fail Definition idV@{sl sr s s';ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr s';ul ur} A B := match x return sum@{sl sr s';ul ur} A B with | inl a => inl a | inr b => inr b end. Definition idT@{sl sr s;ul ur|s -> Type} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Type;ul ur} A B := match x return sum@{sl sr Type;ul ur} A B with | inl a => inl a | inr b => inr b end. Definition idP@{sl sr s;ul ur|s -> Prop} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr Prop;ul ur} A B := match x return sum@{sl sr Prop;ul ur} A B with | inl a => inl a | inr b => inr b end. Definition idS@{sl sr s;ul ur|s -> SProp} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr SProp;ul ur} A B := match x return sum@{sl sr SProp;ul ur} A B with | inl a => inl a | inr b => inr b end. Definition idV@{sl sr s;ul ur} (A : Type@{sl;ul}) (B : Type@{sr;ur}) (x : sum@{sl sr s;ul ur} A B) : sum@{sl sr s;ul ur} A B := match x return sum@{sl sr s;ul ur} A B with | inl a => inl a | inr b => inr b end. Inductive List'@{s s';l} (A : Type@{s;l}) : Type@{s';l} := | nil' : List' A | cons' : A -> List' A -> List' A. Arguments nil' {A}. Arguments cons' {A} _ _. Definition list'_elim@{s s0 s';l l'|s0 -> s'} (A : Type@{s;l}) (P : List'@{s s0;l} A -> Type@{s';l'}) (fn : P nil') (fc : forall (x : A) (l : List' A), P l -> P (cons' x l)) := fix F (l : List'@{s s0;l} A) : P l := match l with | nil' => fn | cons' x l => fc x l (F l) end. Fail Fixpoint list'_idT@{s s';l|} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s Type;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idT l) end. Fail Fixpoint list'_idP@{s s';l|} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s Prop;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idP l) end. Fail Fixpoint list'_idS@{s s';l|} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s SProp;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idS l) end. Fail Fixpoint list'_idV@{s s0 s';l l'|l <= l'} {A : Type@{s;l}} (l : List'@{s s0;l} A) : List'@{s s';l'} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idV l) end. Fixpoint list'_idT@{s s';l|s' -> Type} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s Type;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idT l) end. Fixpoint list'_idP@{s s';l|s' -> Prop} {A : Type@{s;l}} (l : List'@{s s';l} A) {struct l} : List'@{s Prop;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idP l) end. Fixpoint list'_idS@{s s';l|s' -> SProp} {A : Type@{s;l}} (l : List'@{s s';l} A) : List'@{s SProp;l} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idS l) end. Fixpoint list'_idV@{s s0 s';l l'|l <= l', s0 -> s'} {A : Type@{s;l}} (l : List'@{s s0;l} A) : List'@{s s';l'} A := match l with | nil' => nil' | cons' x l => cons' x (list'_idV l) end. rocq-9.2.0/test-suite/success/sort_poly_elim_rigid_paths.v000066400000000000000000000010561516144147600240630ustar00rootroot00000000000000Sort s s' s''. Constraint s -> s'. Constraint s' -> s''. Polymorphic Axiom ad@{s;u} : forall A : Type@{s;u}, A. Polymorphic Definition t@{s s';u v|s -> s'} (A : Type@{s;u}) (B : Type@{s';v}) : A := ad A. (* This should succeed even though [s -> s''] is not declared *) Check t@{s s'';Set Set}. (* This should fail though as we don't have [s'' -> s'] or [s'' -> s] declared. *) Fail Check t@{s'' s';Set Set}. Fail Check t@{s'' s;Set Set}. (* But if we do this, both should work. *) Constraint s'' -> s. Check t@{s'' s';Set Set}. Check t@{s'' s;Set Set}. rocq-9.2.0/test-suite/success/sort_poly_elim_tactics.v000066400000000000000000000021511516144147600232150ustar00rootroot00000000000000Set Universe Polymorphism. Inductive Acc@{s s';u v} {A : Type@{s;u}} (R : A -> A -> Prop) (x : A) : Type@{s';v} := | Acc_intro : (forall y : A, R y x -> Acc R y) -> Acc R x. (* We should be able to define (with tactics) a fixpoint from [s'] to [Type] if [s' -> Prop]. *) Fixpoint Acc_elim@{s s' ; u v w | s' -> Prop, u <= w} {A : Type@{s;u}} {R : A -> A -> Prop} {P : A -> Type@{w}} (f : forall x : A, (forall y : A, R y x -> Acc@{s s';u w} R y) -> (forall y : A, R y x -> P y) -> P x) (x : A) (a : Acc@{s s';u w} R x) {struct a} : P x. Proof. refine (f x (fun y r => _) (fun y r => _)). - destruct a. now apply a. - unshelve eapply Acc_elim; eauto. destruct a. now apply a. Defined. Inductive sum@{sl sr s;ul ur|} (A : Type@{sl;ul}) (B : Type@{sr;ur}) : Type@{s;max(ul,ur)} := | inl : A -> sum A B | inr : B -> sum A B. Arguments inl {_ _} _. Arguments inr {_ _} _. (* Likewise but with an opaque proof. *) Lemma test@{sl sr s;ul ur|s -> Prop} {A : Type@{sl;ul}} {B : Type@{sr;ur}} (u : sum@{sl sr s;ul ur} A B) : sum@{sl sr Prop;ul ur} A B. Proof. destruct u. - exact (inl a). - exact (inr b). Qed. rocq-9.2.0/test-suite/success/sort_poly_extraction.v000066400000000000000000000024661516144147600227460ustar00rootroot00000000000000Require Extraction. Set Universe Polymorphism. Definition foo@{s; |} := tt. Definition bar := foo@{Prop;}. Extraction bar. (* the actual problem only appears once we have inductives with sort poly output: *) Inductive Pair@{s;u|} (A:Type@{s;u}) : Type@{s;u} := pair : A -> A -> Pair A. Definition use_pair@{s;+|} A (k:A->nat) (x:Pair@{s;_} A) := k (match x with pair _ x _ => x end). Definition make_pair := pair@{Prop;_} _ I I. Definition hell := use_pair True (fun _ => 0) make_pair. Extraction TestCompile hell. (* Some tests *) Module Foo. Definition foo@{s1 s2| |} := fun (A : Type@{s1|Set}) (x : A) => x. Definition foo0 := foo@{SProp Type|}. Definition foo1 := foo@{Type SProp|}. Inductive T@{s| |} : Type@{s|Set} := O : T | S : T -> T. Inductive box@{s1 s2| |} (A : Type@{s1|Set}) (B : Type@{s2|Set}) : Type@{Set} := Box : A -> B -> box A B. Definition bar (A : Type) (x : A) := 0. Definition qux := bar (forall A : Prop, A -> A) foo@{Prop Type|}. End Foo. Extraction TestCompile Foo. (* Check module subtyping *) Module Type S. Inductive box@{s1 s2| |} (A : Type@{s1|Set}) (B : Type@{s2|Set}) : Type@{Set} := Box : A -> B -> box A B. End S. Module Bar : S. Inductive box@{s1 s2| |} (A : Type@{s1|Set}) (B : Type@{s2|Set}) : Type@{Set} := Box : A -> B -> box A B. End Bar. Extraction TestCompile Bar. rocq-9.2.0/test-suite/success/specialize.v000066400000000000000000000130521516144147600205750ustar00rootroot00000000000000 Goal forall a b c : nat, a = b -> b = c -> forall d, a+d=c+d. intros. (* "compatibility" mode: specializing a global name means a kind of generalize *) specialize eq_trans. intros _. specialize eq_trans with (1:=H)(2:=H0). intros _. specialize eq_trans with (x:=a)(y:=b)(z:=c). intros _. specialize eq_trans with (1:=H)(z:=c). intros _. specialize eq_trans with nat a b c. intros _. specialize (@eq_trans nat). intros _. specialize (@eq_trans _ a b c). intros _. specialize (eq_trans (x:=a)). intros _. specialize (eq_trans (x:=a)(y:=b)). intros _. specialize (eq_trans H H0). intros _. specialize (eq_trans H0 (z:=b)). intros _. (* incomplete bindings: y is left quantified and z is instantiated. *) specialize eq_trans with (x:=a)(z:=c). intro h. (* y can be instantiated now *) specialize h with (y:=b). (* z was instantiated above so this must fail. *) Fail specialize h with (z:=c). clear h. (* incomplete bindings: 1st dep hyp is instantiated thus A, x and y instantiated too. *) specialize eq_trans with (1:=H). intro h. (* 2nd dep hyp can be instantiated now, which instatiates z too. *) specialize h with (1:=H0). (* checking that there is no more products in h. *) match type of h with | _ = _ => idtac | _ => fail "specialize test failed: hypothesis h should be an equality at this point" end. clear h. (* local "in place" specialization *) assert (Eq:=eq_trans). specialize Eq. specialize Eq with (1:=H)(2:=H0). Undo. specialize Eq with (x:=a)(y:=b)(z:=c). Undo. specialize Eq with (1:=H)(z:=c). Undo. specialize Eq with nat a b c. Undo. specialize (Eq nat). Undo. specialize (Eq _ a b c). Undo. (* no implicit argument for Eq, hence no (Eq (x:=a)) *) specialize (Eq _ _ _ _ H H0). Undo. specialize (Eq _ _ _ b H0). Undo. (* incomplete binding *) specialize Eq with (y:=b). (* A and y have been instantiated so this works *) specialize (Eq _ _ H H0). Undo 2. (* incomplete binding (dependent) *) specialize Eq with (1:=H). (* A, x and y have been instantiated so this works *) specialize (Eq _ H0). Undo 2. (* incomplete binding (dependent) *) specialize Eq with (1:=H) (2:=H0). (* A, x and y have been instantiated so this works *) match type of Eq with | _ = _ => idtac | _ => fail "specialize test failed: hypothesis Eq should be an equality at this point" end. Undo 2. (* (** strange behavior to inspect more precisely *) (* 1) proof aspect : let H:= ... in (fun H => ..) H presque ok... *) (* 2) echoue moins lorsque zero premise de mangΓ© *) specialize eq_trans with (1:=Eq). (* mal typΓ© !! *) (* 3) Seems fixed.*) specialize eq_trans with _ a b c. intros _. (* Anomaly: Evar ?88 was not declared. Please report. *) *) Abort. (* Test use of pose proof and assert as a specialize *) Goal True -> (True -> 0=0) -> False -> 0=0. intros H0 H H1. pose proof (H I) as H. (* Check that the hypothesis is in 2nd position by removing the top one *) match goal with H:_ |- _ => clear H end. match goal with H:_ |- _ => exact H end. Qed. Goal True -> (True -> 0=0) -> False -> 0=0. intros H0 H H1. assert (H:=H I). (* Check that the hypothesis is in 2nd position by removing the top one *) match goal with H:_ |- _ => clear H end. match goal with H:_ |- _ => exact H end. Qed. (* let ins should be supported int he type of the specialized hypothesis *) Axiom foo: forall (m1:nat) (m2: nat), let n := 2 * m1 in (m1 = m2 -> False). Goal False. pose proof foo as P. assert (2 = 2) as A by reflexivity. (* specialize P with (m2:= 2). *) specialize P with (1 := A). match type of P with | let n := 2 * 2 in False => idtac | _ => fail "test failed" end. assumption. Qed. (* Another more subtle test on letins: they should not interfere with foralls. *) Goal forall (P: forall a c:nat, let b := c in let d := 1 in forall n : a = d, a = c+1), True. intros P. specialize P with (1:=eq_refl). match type of P with | forall c : nat, let f := c in let d := 1 in 1 = c + 1 => idtac | _ => fail "test failed" end. constructor. Qed. (* Test specialize as *) Goal (forall x, x=0) -> 1=0. intros. specialize (H 1) as ->. reflexivity. Qed. (* A test from corn *) Goal (forall x y, x=0 -> y=0 -> True) -> True. intros. specialize (fun z => H 0 z eq_refl). exact (H 0 eq_refl). Qed. Module bug_17322. Axiom key : Type. Axiom value : Type. Axiom eqb : key -> key -> bool. Axiom remove : list value -> key -> list value. Axiom sorted : list value -> bool. Axiom lookup : list value -> key -> value. Goal forall (l : list value) (k : key), (sorted l = true -> forall k' : key, eqb k k' = false -> lookup (remove l k') k = lookup l k) -> sorted l = true -> False . Proof. intros l k IHl ST. specialize IHl with (1 := ST). Abort. End bug_17322. Module bug_17322_2. Axiom tuple : Type. Axiom mem : Type. Axiom unchecked_store_bytes : tuple -> mem. Axiom load_bytes : mem -> Prop. Goal forall (IHn : forall (m' : mem) (w : tuple), unchecked_store_bytes w = m' -> load_bytes m' -> True), True. Proof. intros. Fail specialize IHn with (1 := eq_refl). (* After #17322 this fails with In environment IHn : forall (m' : mem) (w : tuple), unchecked_store_bytes w = m' -> load_bytes m' -> True m' : mem w : tuple Unable to unify "?t" with "w" (cannot instantiate "?t" because "w" is not in its scope: available arguments are "IHn"). Previously it was leaving w as an unresolved evar, producing the hypothesis IHn : load_bytes (unchecked_store_bytes ?w) -> True The correct behaviour should probably to requantify on w as IHn : forall w, load_bytes (unchecked_store_bytes w) -> True *) Abort. End bug_17322_2. rocq-9.2.0/test-suite/success/sprop.v000066400000000000000000000125221516144147600176110ustar00rootroot00000000000000(* -*- mode: coq; coq-prog-args: ("-allow-sprop") -*- *) Set Primitive Projections. Set Warnings "+non-primitive-record". Set Warnings "+bad-relevance". Check SProp. Definition iUnit : SProp := forall A : SProp, A -> A. Definition itt : iUnit := fun A a => a. Definition iUnit_irr (P : iUnit -> Type) (x y : iUnit) : P x -> P y := fun v => v. Definition iSquash (A:Type) : SProp := forall P : SProp, (A -> P) -> P. Definition isquash A : A -> iSquash A := fun a P f => f a. Definition iSquash_rect A (P : iSquash A -> SProp) (H : forall x : A, P (isquash A x)) : forall x : iSquash A, P x := fun x => x (P x) (H : A -> P x). Fail Check (fun A : SProp => A : Type). Lemma foo : Prop. Proof. pose (fun A : SProp => ltac:(exact_no_check A): Type); exact True. Fail Qed. Abort. (* define evar as product *) Check (fun (f:(_:SProp)) => f _). Inductive sBox (A:SProp) : Prop := sbox : A -> sBox A. Definition uBox := sBox iUnit. Definition sBox_irr A (x y : sBox A) : x = y. Proof. Fail reflexivity. destruct x as [x], y as [y]. reflexivity. Defined. (* Primitive record in Prop with all fields in SProp does not have the eta property of SProp but can be defined regardless. *) Record rBox (A:SProp) : Prop := rmkbox { runbox : A }. (* Check that defining record without eta *) Check runbox. (* Check that it doesn't have eta *) Fail Check (fun (A : SProp) (x : rBox A) => eq_refl : x = @rmkbox _ (@runbox _ x)). Inductive sEmpty : SProp := . Inductive sUnit : SProp := stt. Inductive BIG : SProp := foo | bar. Inductive Squash (A:Type) : SProp := squash : A -> Squash A. Definition BIG_flip : BIG -> BIG. Proof. intros [|]. exact bar. exact foo. Defined. Inductive pb : Prop := pt | pf. Definition pb_big : pb -> BIG. Proof. intros [|]. exact foo. exact bar. Defined. Fail Definition big_pb (b:BIG) : pb := match b return pb with foo => pt | bar => pf end. Inductive which_pb : pb -> SProp := | is_pt : which_pb pt | is_pf : which_pb pf. Fail Definition pb_which b (w:which_pb b) : bool := match w with | is_pt => true | is_pf => false end. (* Non primitive because no arguments, but maybe we should allow it for sprops? *) Fail Record UnitRecord : SProp := {}. Section Opt. Local Unset Primitive Projections. Record UnitRecord' : SProp := {}. End Opt. Fail Scheme Induction for UnitRecord' Sort Set. Record sProd (A B : SProp) : SProp := sPair { sFst : A; sSnd : B }. Scheme Induction for sProd Sort Set. Unset Primitive Projections. Record sProd' (A B : SProp) : SProp := sPair' { sFst' : A; sSnd' : B }. Set Primitive Projections. Fail Scheme Induction for sProd' Sort Set. Inductive Istrue : bool -> SProp := istrue : Istrue true. Definition Istrue_sym (b:bool) := if b then sUnit else sEmpty. Definition Istrue_to_sym b (i:Istrue b) : Istrue_sym b := match i with istrue => stt end. (* We don't need primitive elimination to relevant types for this *) Definition Istrue_rec (P:forall b, Istrue b -> Set) (H:P true istrue) b (i:Istrue b) : P b i. Proof. destruct b. - exact_no_check H. - apply sEmpty_rec. apply Istrue_to_sym in i. exact i. Defined. Check (fun P v (e:Istrue true) => eq_refl : Istrue_rec P v _ e = v). Record Truepack := truepack { trueval :> bool; trueprop : Istrue trueval }. Definition Truepack_eta (x : Truepack) (i : Istrue x) : x = truepack x i := @eq_refl Truepack x. Class emptyclass : SProp := emptyinstance : forall A:SProp, A. (** Sigma in SProp can be done through Squash and relevant sigma. *) Definition sSigma (A:SProp) (B:A -> SProp) : SProp := Squash (@sigT (rBox A) (fun x => rBox (B (runbox _ x)))). Definition spair (A:SProp) (B:A->SProp) (x:A) (y:B x) : sSigma A B := squash _ (existT _ (rmkbox _ x) (rmkbox _ y)). Definition spr1 (A:SProp) (B:A->SProp) (p:sSigma A B) : A := let 'squash _ (existT _ x y) := p in runbox _ x. Definition spr2 (A:SProp) (B:A->SProp) (p:sSigma A B) : B (spr1 A B p) := let 'squash _ (existT _ x y) := p return B (spr1 A B p) in runbox _ y. (* it's SProp so it computes properly *) (** Fixpoints on SProp values are only allowed to produce SProp results *) Inductive sAcc (x:nat) : SProp := sAcc_in : (forall y, y < x -> sAcc y) -> sAcc x. Definition sAcc_inv x (s:sAcc x) : forall y, y < x -> sAcc y. Proof. destruct s as [H]. exact H. Defined. Section sFix_fail. Variable P : nat -> Type. Variable F : forall x:nat, (forall y:nat, y < x -> P y) -> P x. Fail Fixpoint sFix (x:nat) (a:sAcc x) {struct a} : P x := F x (fun (y:nat) (h: y < x) => sFix y (sAcc_inv x a y h)). End sFix_fail. Section sFix. Variable P : nat -> SProp. Variable F : forall x:nat, (forall y:nat, y < x -> P y) -> P x. Fixpoint sFix (x:nat) (a:sAcc x) {struct a} : P x := F x (fun (y:nat) (h: y < x) => sFix y (sAcc_inv x a y h)). End sFix. (** Relevance repairs *) Definition fix_relevance : _ -> nat := fun _ : iUnit => 0. Definition relevance_unfixed := fun (A:SProp) (P:A -> Prop) x y (v:P x) => v : P y. (* The kernel is fine *) Definition relevance_unfixed_bypass := fun (A:SProp) (P:A -> Prop) x y (v:P x) => ltac:(exact_no_check v) : P y. (* Check that VM/native properly keep the relevance of the predicate in the case info (bad-relevance warning as error otherwise) *) Definition vm_rebuild_case := Eval vm_compute in eq_sind. Require Import ssreflect. Goal forall T : SProp, T -> True. Proof. move=> T +. intros X;exact I. Qed. rocq-9.2.0/test-suite/success/sprop_fast.v000066400000000000000000000007701516144147600206300ustar00rootroot00000000000000Fixpoint big n : unit := match n with 0 => tt | S n => match big n with tt => big n end end. Inductive squash (A : Type) : SProp := Squash : A -> squash A. Inductive box (A : SProp) : Type := Box : A -> box A. (* If this is ever unfolded, this will explode *) Goal Box _ (Squash _ (big 50)) = Box _ (Squash _ tt). Proof. reflexivity. Qed. Definition SquashC := Squash. (* If this is ever unfolded, this will explode *) Goal Box _ (SquashC _ (big 50)) = Box _ (SquashC _ tt). Proof. reflexivity. Qed. rocq-9.2.0/test-suite/success/sprop_hcons.v000066400000000000000000000025421516144147600210040ustar00rootroot00000000000000(* -*- coq-prog-args: ("-allow-sprop"); -*- *) (* A bug due to bad hashconsing of case info *) Inductive sBox (A : SProp) : Type := sbox : A -> sBox A. Definition ubox {A : SProp} (bA : sBox A) : A := match bA with sbox _ X => X end. Inductive sle : nat -> nat -> SProp := sle_0 : forall n, sle 0 n | sle_S : forall n m : nat, sle n m -> sle (S n) (S m). Definition sle_Sn (n : nat) : sle n (S n). Proof. induction n; constructor; auto. Defined. Definition sle_trans {n m p} (H : sle n m) (H': sle m p) : sle n p. Proof. revert H'. revert p. induction H. - intros p H'. apply sle_0. - intros p H'. inversion H'. apply ubox. subst. apply sbox. apply sle_S. apply IHsle;auto. Defined. Lemma sle_Sn_m {n m} : sle n m -> sle n (S m). Proof. intros H. destruct n. - constructor. - constructor;auto. assert (H1 : sle n (S n)) by apply sle_Sn. exact (sle_trans H1 H ). Defined. Definition sle_Sn_Sm {n m} : sle (S n) (S m) -> sle n m. Proof. intros H. inversion H. apply ubox. subst. apply sbox. exact H2. Qed. Notation "g ∘ f" := (sle_trans g f) (at level 40). Lemma bazz q0 m (f : sle (S q0) (S m)) : sbox _ (sle_Sn q0 ∘ f) = sbox _ (sle_Sn_m (sle_Sn_Sm f)). Proof. reflexivity. (* used to fail *) (* NB: exact eq_refl succeeded even with the bug so no guarantee that this test will continue to test the right thing. *) Qed. rocq-9.2.0/test-suite/success/sprop_uip.v000066400000000000000000000101241516144147600204620ustar00rootroot00000000000000 Set Allow StrictProp. Set Definitional UIP. Set Warnings "+bad-relevance". (** Case inversion, conversion and universe polymorphism. *) Set Universe Polymorphism. Inductive IsTy@{i j} : Type@{j} -> SProp := isty : IsTy Type@{i}. Definition IsTy_rec_red@{i j+} (P:forall T : Type@{j}, IsTy@{i j} T -> Set) v (e:IsTy@{i j} Type@{i}) : IsTy_rec P v _ e = v := eq_refl. (** Identity! Currently we have UIP. *) Inductive seq {A} (a:A) : A -> SProp := srefl : seq a a. Definition transport {A} (P:A -> Type) {x y} (e:seq x y) (v:P x) : P y := match e with srefl _ => v end. Definition transport_refl {A} (P:A -> Type) {x} (e:seq x x) v : transport P e v = v := @eq_refl (P x) v. Definition id_unit (x : unit) := x. Definition transport_refl_id {A} (P : A -> Type) {x : A} (u : P x) : P (transport (fun _ => A) (srefl _ : seq (id_unit tt) tt) x) := u. (** We don't ALWAYS reduce (this uses a constant transport so that the equation is well-typed) *) Fail Definition transport_block A B (x y:A) (e:seq x y) v : transport (fun _ => B) e v = v := @eq_refl B v. Inductive sBox (A:SProp) : Prop := sbox : A -> sBox A. Definition transport_refl_box (A:SProp) P (x y:A) (e:seq (sbox A x) (sbox A y)) v : transport P e v = v := eq_refl. (** TODO? add tests for binders which aren't lambda. *) Definition transport_box := Eval lazy in (fun (A:SProp) P (x y:A) (e:seq (sbox A x) (sbox A y)) v => transport P e v). Lemma transport_box_ok : transport_box = fun A P x y e v => v. Proof. unfold transport_box. match goal with |- ?x = ?x => reflexivity end. Qed. (** Play with UIP *) Lemma of_seq {A:Type} {x y:A} (p:seq x y) : x = y. Proof. destruct p. reflexivity. Defined. Lemma to_seq {A:Type} {x y:A} (p: x = y) : seq x y. Proof. destruct p. reflexivity. Defined. Lemma eq_srec (A:Type) (x y:A) (P:x=y->Type) : (forall e : seq x y, P (of_seq e)) -> forall e, P e. Proof. intros H e. destruct e. apply (H (srefl _)). Defined. Lemma K : forall {A x} (p:x=x:>A), p = eq_refl. Proof. intros A x. apply eq_srec. intros;reflexivity. Defined. Definition K_refl : forall {A x}, @K A x eq_refl = eq_refl := fun A x => eq_refl. Section funext. Variable sfunext : forall {A B} (f g : A -> B), (forall x, seq (f x) (g x)) -> seq f g. Lemma funext {A B} (f g : A -> B) (H:forall x, (f x) = (g x)) : f = g. Proof. apply of_seq,sfunext;intros x;apply to_seq,H. Defined. Definition funext_refl A B (f : A -> B) : funext f f (fun x => eq_refl) = eq_refl := eq_refl. End funext. (* test reductions on inverted cases *) (* first check production of correct blocked cases *) Definition lazy_seq_rect := Eval lazy in seq_rect. Definition vseq_rect := Eval vm_compute in seq_rect. Definition native_seq_rect := Eval native_compute in seq_rect. Definition cbv_seq_rect := Eval cbv in seq_rect. (* check it reduces according to indices *) Ltac reset := match goal with H : _ |- _ => change (match H with srefl _ => False end) end. Ltac check := match goal with |- False => idtac end. Lemma foo (H:seq 0 0) : False. Proof. reset. Fail check. (* check that "reset" and "check" actually do something *) lazy; check; reset. (* TODO *) vm_compute. Fail check. native_compute. Fail check. cbv. Fail check. cbn. Fail check. simpl. Fail check. Abort. Module HoTTStyle. (* a small proof which tests destruct in a tricky case *) Definition ap {A B} (f:A -> B) {x y} (e : seq x y) : seq (f x) (f y). Proof. destruct e. reflexivity. Defined. Section S. Context (A : Type) (B : Type) (f : A -> B) (g : B -> A) (section : forall a, seq (g (f a)) a) (retraction : forall b, seq (f (g b)) b). Lemma bla (P : B -> Type) (a : A) (F : forall a, P (f a)) : seq_rect _ (f (g (f a))) (fun a _ => P a) (F (g (f a))) (f a) (retraction (f a)) = F a. Proof. lazy. change (retraction (f a)) with (ap f (section a)). destruct (section a). reflexivity. Qed. End S. End HoTTStyle. (* check that extraction doesn't fall apart on matches with special reduction *) Require Extraction. Extraction seq_rect. rocq-9.2.0/test-suite/success/ssrpattern.v000066400000000000000000000010021516144147600206420ustar00rootroot00000000000000Require Import ssrmatching. (*Set Debug SsrMatching.*) Tactic Notation "at" "[" ssrpatternarg(pat) "]" tactic(t) := let name := fresh in let def_name := fresh in ssrpattern pat; intro name; pose proof (refl_equal name) as def_name; unfold name at 1 in def_name; t def_name; [ rewrite <- def_name | idtac.. ]; clear name def_name. Lemma test (H : True -> True -> 3 = 7) : 28 = 3 * 4. Proof. at [ X in X * 4 ] ltac:(fun place => rewrite -> H in place). - reflexivity. - trivial. - trivial. Qed. rocq-9.2.0/test-suite/success/strategy.v000066400000000000000000000037151516144147600203140ustar00rootroot00000000000000Notation aid := (@id) (only parsing). Notation idn := id (only parsing). Ltac unfold_id := unfold id. Fixpoint fact (n : nat) := match n with | 0 => 1 | S n => (S n) * fact n end. Opaque id. Goal id (fact 100) = fact 100. Strategy expand [id]. Time Timeout 5 reflexivity. (* should be instant *) (* Finished transaction in 0. secs (0.u,0.s) (successful) *) Time Timeout 5 Defined. (* Finished transaction in 0.001 secs (0.u,0.s) (successful) *) Goal True. let x := smart_global:(id) in unfold x. let x := smart_global:(aid) in unfold x. let x := smart_global:(idn) in unfold x. Abort. Goal id 0 = 0. Opaque id. assert_fails unfold_id. Transparent id. assert_succeeds unfold_id. Opaque id. Strategy 0 [id]. assert_succeeds unfold_id. Strategy 1 [id]. assert_succeeds unfold_id. Strategy -1 [id]. assert_succeeds unfold_id. Strategy opaque [id]. assert_fails unfold_id. Strategy transparent [id]. assert_succeeds unfold_id. Opaque id. Strategy expand [id]. assert_succeeds unfold_id. reflexivity. Qed. Goal id 0 = 0. Opaque aid. assert_fails unfold_id. Transparent aid. assert_succeeds unfold_id. Opaque aid. Strategy 0 [aid]. assert_succeeds unfold_id. Strategy 1 [aid]. assert_succeeds unfold_id. Strategy -1 [aid]. assert_succeeds unfold_id. Strategy opaque [aid]. assert_fails unfold_id. Strategy transparent [aid]. assert_succeeds unfold_id. Opaque aid. Strategy expand [aid]. assert_succeeds unfold_id. reflexivity. Qed. Goal id 0 = 0. Opaque idn. assert_fails unfold_id. Transparent idn. assert_succeeds unfold_id. Opaque idn. Strategy 0 [idn]. assert_succeeds unfold_id. Strategy 1 [idn]. assert_succeeds unfold_id. Strategy -1 [idn]. assert_succeeds unfold_id. Strategy opaque [idn]. assert_fails unfold_id. Strategy transparent [idn]. assert_succeeds unfold_id. Opaque idn. Strategy expand [idn]. assert_succeeds unfold_id. reflexivity. Qed. rocq-9.2.0/test-suite/success/subprf_commands.v000066400000000000000000000003311516144147600216230ustar00rootroot00000000000000Check True. Goal True /\ True. Check True. 1:Check True. 1: idtac. 1:{ admit. } Abort. Require Import Ltac2.Ltac2. Check True. Goal True /\ True. Check True. 1:Check True. 1: (). 1:{ admit. } Abort. rocq-9.2.0/test-suite/success/subst.v000066400000000000000000000017301516144147600176050ustar00rootroot00000000000000(* Test various subtleties of the "subst" tactics *) (* Should proceed from left to right (see #4222) *) Goal forall x y, x = y -> x = 3 -> y = 2 -> x = y. intros. subst. change (3 = 2) in H1. change (3 = 3). Abort. (* Should work with "x = y" and "x = t" equations (see #4214, failed in 8.4) *) Goal forall x y, x = y -> x = 3 -> x = y. intros. subst. change (3 = 3). Abort. (* Should substitute cycles once, until a recursive equation is obtained *) (* (failed in 8.4) *) Goal forall x y, x = S y -> y = S x -> x = y. intros. subst. change (y = S (S y)) in H0. change (S y = y). Abort. (* A bug revealed by OCaml 4.03 warnings *) (* fixes in 4e3d464 and 89ec88f for v8.5, 4e3d4646 and 89ec88f1e for v8.6 *) Goal forall y, let x:=0 in y=x -> y=y. intros * H; (* This worked as expected *) subst. Fail clear H. Abort. Goal forall y, let x:=0 in x=y -> y=y. intros * H; (* Before the fix, this unfolded x instead of substituting y and erasing H *) subst. Fail clear H. Abort. rocq-9.2.0/test-suite/success/tac_wit_ref.v000066400000000000000000000001641516144147600207330ustar00rootroot00000000000000Tactic Notation "foo" reference(n) := idtac n. Goal forall n : nat, n = 0. Proof. intros n. foo nat. foo n. Abort. rocq-9.2.0/test-suite/success/tceauto_nocore.v000066400000000000000000000002011516144147600214460ustar00rootroot00000000000000(* tc eauto doesn't automatically include core *) Goal True. Fail typeclasses eauto. Succeed typeclasses eauto with core. Abort. rocq-9.2.0/test-suite/success/telescope_canonical.v000066400000000000000000000045241516144147600224430ustar00rootroot00000000000000Structure Inner := mkI { is :> Type }. Structure Outer := mkO { os :> Inner }. Canonical Structure natInner := mkI nat. Canonical Structure natOuter := mkO natInner. Definition hidden_nat := nat. Axiom P : forall S : Outer, is (os S) -> Prop. Lemma test1 (n : hidden_nat) : P _ n. Admitted. Structure Pnat := mkP { getp : nat }. Definition my_getp := getp. Axiom W : nat -> Prop. (* Fix *) Canonical Structure add1Pnat n := mkP (plus n 1). Definition test_fix n := (refl_equal _ : W (my_getp _) = W (n + 1)). (* Case *) Definition pred n := match n with 0 => 0 | S m => m end. Canonical Structure predSS n := mkP (pred n). Definition test_case x := (refl_equal _ : W (my_getp _) = W (pred x)). Definition test_case' := (refl_equal _ : W (my_getp _) = W (pred 0)). Canonical Structure letPnat' := mkP 0. Definition letin := (let n := 0 in n). Definition test4 := (refl_equal _ : W (getp _) = W letin). Definition test41 := (refl_equal _ : W (my_getp _) = W letin). Definition letin2 (x : nat) := (let n := x in n). Canonical Structure letPnat'' x := mkP (letin2 x). Definition test42 x := (refl_equal _ : W (my_getp _) = W (letin2 x)). Fail Definition test42' x := (refl_equal _ : W (my_getp _) = W x). Structure Morph := mkM { f :> nat -> nat }. Definition my_f := f. Axiom Q : (nat -> nat) -> Prop. (* Lambda *) Canonical Structure addMorh x := mkM (plus x). Definition test_lam x := (refl_equal _ : Q (my_f _) = Q (plus x)). Definition test_lam' := (refl_equal _ : Q (my_f _) = Q (plus 0)). (* Simple tests to justify Sort and Prod as "named". They are already normal, so they cannot loose their names, but still... *) Structure Sot := mkS { T : Type }. Axiom R : Type -> Prop. Canonical Structure tsot := mkS (Type). Definition test_sort := (refl_equal _ : R (T _) = R Type). Canonical Structure tsot2 := mkS (nat -> nat). Definition test_prod := (refl_equal _ : R (T _) = R (nat -> nat)). (* Var *) Section Foo. Variable v : nat. Definition my_v := v. Canonical Structure vP := mkP my_v. Definition test_var := (refl_equal _ : W (getp _) = W my_v). Canonical Structure vP' := mkP v. Definition test_var' := (refl_equal _ : W (my_getp _) = W my_v). End Foo. (* Rel *) Definition test_rel v := (refl_equal _ : W (my_getp _) = W (my_v v)). Goal True. pose (x := test_rel 2). match goal with x := _ : W (my_getp (vP 2)) = _ |- _ => idtac end. apply I. Qed. rocq-9.2.0/test-suite/success/transparency_multi_hintdb.v000066400000000000000000000007311516144147600237200ustar00rootroot00000000000000(* constant transparent in one hintdb but not the other *) Definition one := 1. Theorem thm : one = 1. reflexivity. Qed. Create HintDb db1 discriminated. Hint Opaque one : db1. Hint Resolve thm | 1 : db1. Create HintDb db2 discriminated. Goal 1 = 1. Fail typeclasses eauto with db1 db2 nocore. Succeed eauto with db1 db2 nocore. (* bug! *) Succeed auto with db1 db2 nocore. (* bug! *) Hint Resolve thm | 2 : db2. Succeed typeclasses eauto with db1 db2 nocore. Abort. rocq-9.2.0/test-suite/success/transparent_abstract.v000066400000000000000000000014521516144147600226720ustar00rootroot00000000000000Class by_transparent_abstract {T} (x : T) := make_by_transparent_abstract : T. #[export] Hint Extern 0 (@by_transparent_abstract ?T ?x) => change T; transparent_abstract exact_no_check x : typeclass_instances. Goal True /\ True. Proof. split. transparent_abstract exact I using foo. let x := (eval hnf in foo) in constr_eq x I. let x := constr:(ltac:(constructor) : True) in let T := type of x in let x := constr:(_ : by_transparent_abstract x) in let x := (eval cbv delta [by_transparent_abstract] in (let y : T := x in y)) in pose x as x'. simpl in x'. let v := eval cbv [x'] in x' in tryif constr_eq v I then fail 0 else idtac. hnf in x'. let v := eval cbv [x'] in x' in tryif constr_eq v I then idtac else fail 0. exact x'. Defined. Check eq_refl : I = foo. Eval compute in foo. rocq-9.2.0/test-suite/success/tryif.v000066400000000000000000000024631516144147600176060ustar00rootroot00000000000000Require Import TestSuite.admit. (** [not tac] is equivalent to [fail tac "succeeds"] if [tac] succeeds, and is equivalent to [idtac] if [tac] fails *) Tactic Notation "not" tactic3(tac) := (tryif tac then fail 0 tac "succeeds" else idtac); (* error if the tactic solved all goals *) []. (** Test if a tactic succeeds, but always roll-back the results *) Tactic Notation "test" tactic3(tac) := tryif not tac then fail 0 tac "fails" else idtac. Goal Set. Proof. not fail. not not idtac. not fail 0. (** Would be nice if we could get [not fail 1] to pass, maybe *) not not admit. not not test admit. not progress test admit. (* test grouping *) not (not idtac; fail). assert True. all:not fail. 2:not fail. all:admit. Defined. Goal Set. Proof. test idtac. test try fail. test admit. test match goal with |- Set => idtac end. test (idtac; match goal with |- Set => idtac end). (* test grouping *) first [ (test idtac; fail); fail 1 | idtac ]. try test fail. try test test fail. test test idtac. test test admit. Fail test fail. test (idtac; []). test (assert True; [|]). (* would be nice, perhaps, if we could catch [fail 1] and not just [fail 0] this *) try ((test fail); fail 1). assert True. all:test idtac. all:test admit. 2:test admit. all:admit. Defined. rocq-9.2.0/test-suite/success/typing_flags.v000066400000000000000000000052021516144147600211310ustar00rootroot00000000000000From Corelib Require Import Program.Tactics. (* Part using attributes *) #[bypass_check(guard)] Fixpoint att_f' (n : nat) : nat := att_f' n. #[bypass_check(guard)] Program Fixpoint p_att_f' (n : nat) : nat := p_att_f' n. #[bypass_check(universes)] Definition att_T := let t := Type in (t : t). #[bypass_check(universes)] Program Definition p_att_T := let t := Type in (t : t). #[bypass_check(positivity)] Inductive att_Cor := | att_Over : att_Cor | att_Next : ((att_Cor -> list nat) -> list nat) -> att_Cor. Fail #[bypass_check(guard=no)] Fixpoint f_att_f' (n : nat) : nat := f_att_f' n. Fail #[bypass_check(universes=no)] Definition f_att_T := let t := Type in (t : t). Fail #[bypass_check(positivity=no)] Inductive f_att_Cor := | f_att_Over : f_att_Cor | f_att_Next : ((f_att_Cor -> list nat) -> list nat) -> f_att_Cor. Print Assumptions att_f'. Print Assumptions att_T. Print Assumptions att_Cor. (* Interactive + atts *) #[bypass_check(universes=yes)] Definition i_att_T' : Type. Proof. exact (let t := Type in (t : t)). Defined. #[bypass_check(universes=yes)] Definition d_att_T' : Type. Proof. exact (let t := Type in (t : t)). Qed. #[bypass_check(universes=yes)] Program Definition pi_att_T' : Type. Proof. exact (let t := Type in (t : t)). Qed. (* Note: be aware of tactics invoking [Global.env()] if this test fails. *) #[bypass_check(guard=yes)] Fixpoint i_att_f' (n : nat) : nat. Proof. exact (i_att_f' n). Defined. #[bypass_check(guard=yes)] Fixpoint d_att_f' (n : nat) : nat. Proof. exact (d_att_f' n). Qed. (* check regular mode is still safe *) Fail Fixpoint f_att_f' (n : nat) : nat := f_att_f' n. Fail Definition f_att_T := let t := Type in (t : t). Fail Inductive f_att_Cor := | f_att_Over : f_att_Cor | f_att_Next : ((f_att_Cor -> list nat) -> list nat) -> f_att_Cor. (* Part using Set/Unset *) Print Typing Flags. Unset Guard Checking. Fixpoint f' (n : nat) : nat := f' n. Fixpoint f (n : nat) : nat. Proof. exact (f n). Defined. Fixpoint bla (A:Type) (n:nat) := match n with 0 =>0 | S n => n end. Print Typing Flags. Set Guard Checking. Print Assumptions f. Unset Universe Checking. Definition T := Type. Fixpoint g (n : nat) : T := T. Print Typing Flags. Set Universe Checking. Fail Definition g2 (n : nat) : T := T. Fail Definition e := fix e (n : nat) : nat := e n. Unset Positivity Checking. Inductive Cor := | Over : Cor | Next : ((Cor -> list nat) -> list nat) -> Cor. Set Positivity Checking. Print Assumptions Cor. Inductive Box := | box : forall n, f n = n -> g 2 -> Box. Print Assumptions Box. (** CoFixpoint *) CoInductive Stream : Type := Cons : nat -> Stream -> Stream. #[bypass_check(guard)] CoFixpoint f2 : Stream := f2. rocq-9.2.0/test-suite/success/unfold.v000066400000000000000000000040551516144147600177370ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 | S _ => 1 end = 0. N.f. match goal with |- 0=0 => idtac end. Abort. End B. Module C. (* We reject inductive types and constructors *) Fail Ltac g := unfold nat. Fail Ltac g := unfold S. End C. Module D. (* In interactive mode, we delay the interpretation of short names *) Notation x := Nat.add. Goal let x := 0 in x = 0+0. unfold x. match goal with |- 0 = 0 => idtac end. Abort. Goal let x := 0 in x = 0+0. intro; unfold x. (* dynamic binding (but is it really the most natural?) *) match goal with |- 0 = 0+0 => idtac end. Abort. Goal let fst := 0 in fst = Datatypes.fst (0,0). unfold fst. match goal with |- 0 = 0 => idtac end. Abort. Goal let fst := 0 in fst = Datatypes.fst (0,0). intro; unfold fst. (* dynamic binding *) match goal with |- 0 = Datatypes.fst (0,0) => idtac end. Abort. End D. rocq-9.2.0/test-suite/success/unification.v000066400000000000000000000144451516144147600207640ustar00rootroot00000000000000#[local] Definition test_stack_unification_interaction_with_delta A : (if negb _ then true else false) = if orb false (negb A) then true else false := eq_refl. (* Test patterns unification *) Lemma l1 : (forall P, (exists x:nat, P x) -> False) -> forall P, (exists x:nat, P x /\ P x) -> False. Proof. intros; apply (H _ H0). Qed. Lemma l2 : forall A:Set, forall Q:A->Set, (forall (P: forall x:A, Q x -> Prop), (exists x:A, exists y:Q x, P x y) -> False) -> forall (P: forall x:A, Q x -> Prop), (exists x:A, exists y:Q x, P x y /\ P x y) -> False. Proof. intros; apply (H _ H0). Qed. Lemma l3 : (forall P, ~(exists x:nat, P x)) -> forall P:nat->Prop, ~(exists x:nat, P x -> P x). Proof. intros; apply H. Qed. (* Feature introduced June 2011 *) Lemma l7 : forall x (P:nat->Prop), (forall f, P (f x)) -> P (x+x). Proof. intros x P H; apply H. Qed. (* Example submitted for Zenon *) Axiom zenon_noteq : forall T : Type, forall t : T, ((t <> t) -> False). Axiom zenon_notall : forall T : Type, forall P : T -> Prop, (forall z : T, (~(P z) -> False)) -> (~(forall x : T, (P x)) -> False). (* Must infer "P := fun x => x=x" in zenon_notall *) Check (fun _h1 => (zenon_notall nat _ (fun _T_0 => (fun _h2 => (zenon_noteq _ _T_0 _h2))) _h1)). (* Core of an example submitted by Ralph Matthes (BZ#849) It used to fail because of the K-variable x in the type of "sum_rec ..." which was not in the scope of the evar ?B. Solved by a head beta-reduction of the type "(fun _ : unit + unit => L unit) x" of "sum_rec ...". Shall we used more reduction when solving evars (in real_clean)?? Is there a risk of starting too long reductions? Note that the example originally came from a non re-typable pretty-printed term (the checked term is actually re-printed the same form it is checked). *) Set Implicit Arguments. Inductive L (A:Set) : Set := c : A -> L A. Parameter f: forall (A:Set)(B:Set), (A->B) -> L A -> L B. Parameter t: L (unit + unit). Check (f (fun x : unit + unit => sum_rec (fun _ : unit + unit => L unit) (fun y => c y) (fun y => c y) x) t). (* Test patterns unification in apply *) Require Import TestSuite.arith. Parameter x y : nat. Parameter G:x=y->x=y->Prop. Parameter K:x<>y->x<>y->Prop. Lemma l4 : (forall f:x=y->Prop, forall g:x<>y->Prop, match eq_nat_dec x y with left a => f a | right a => g a end) -> match eq_nat_dec x y with left a => G a a | right a => K a a end. Proof. intros. apply H. Qed. (* Test unification modulo eta-expansion (if possible) *) (* In this example, two instances for ?P (argument of hypothesis H) can be inferred (one is by unifying the type [Q true] and [?P true] of the goal and type of [H]; the other is by unifying the argument of [f]); we need to unify both instances up to allowed eta-expansions of the instances (eta is allowed if the meta was applied to arguments) This used to fail before revision 9389 in trunk *) Lemma l5 : forall f : (forall P, P true), (forall P, f P = f P) -> forall Q, f (fun x => Q x) = f (fun x => Q x). Proof. intros. apply H. Qed. (* Feature deactivated in commit 14189 (see commit log) (* Test instantiation of evars by unification *) Goal (forall x, 0 + x = 0 -> True) -> True. intros; eapply H. rewrite <- plus_n_Sm. (* should refine ?x with S ?x' *) Abort. *) (* Check handling of identity equation between evars *) (* The example failed to pass until revision 10623 *) Lemma l6 : (forall y, (forall x, (forall z, y = 0 -> y + z = 0) -> y + x = 0) -> True) -> True. intros. eapply H. intros. apply H0. (* Check that equation ?n[H] = ?n[H] is correctly considered true *) reflexivity. Qed. (* Check treatment of metas erased by K-redexes at the time of turning them to evas *) Inductive nonemptyT (t : Type) : Prop := nonemptyT_intro : t -> nonemptyT t. Goal True. try case nonemptyT_intro. (* check that it fails w/o anomaly *) Abort. (* Test handling of return type and when it is decided to make the predicate dependent or not - see "bug" BZ#1851 *) Goal forall X (a:X) (f':nat -> X), (exists f : nat -> X, True). intros. exists (fun n => match n with O => a | S n' => f' n' end). constructor. Qed. (* Check use of types in unification (see Andrej Bauer's mail on coq-club, June 1 2009; it did not work in 8.2, probably started to work after Sozeau improved support for the use of types in unification) *) Goal (forall (A B : Set) (f : A -> B), (fun x => f x) = f) -> forall (A B C : Set) (g : (A -> B) -> C) (f : A -> B), g (fun x => f x) = g f. Proof. intros. rewrite H with (f:=f0). Abort. (* Three tests provided by Dan Grayson as part of a custom patch he made for a more powerful "destruct" for handling Voevodsky's Univalent Foundations. The test checks if second-order matching in tactic unification is able to guess by itself on which dependent terms to abstract so that the elimination predicate is well-typed *) Definition test1 (X : Type) (x : X) (fxe : forall x1 : X, identity x1 x1) : identity (fxe x) (fxe x). Proof. destruct (fxe x). apply identity_refl. Defined. (* a harder example *) Definition UU := Type . Inductive paths {T:Type}(t:T): T -> UU := idpath: paths t t. Inductive foo (X0:UU) (x0:X0) : forall (X:UU)(x:X), UU := newfoo : foo x0 x0. Definition idonfoo {X0:UU} {x0:X0} {X1:UU} {x1:X1} : foo x0 x1 -> foo x0 x1. Proof. intros t. exact t. Defined. Lemma test2 (T:UU) (t:T) (k : foo t t) : paths k (idonfoo k). Proof. destruct k. apply idpath. Defined. (* an example with two constructors *) Inductive foo' (X0:UU) (x0:X0) : forall (X:UU)(x:X), UU := | newfoo1 : foo' x0 x0 | newfoo2 : foo' x0 x0 . Definition idonfoo' {X0:UU} {x0:X0} {X1:UU} {x1:X1} : foo' x0 x1 -> foo' x0 x1. Proof. intros t. exact t. Defined. Lemma test3 (T:UU) (t:T) (k : foo' t t) : paths k (idonfoo' k). Proof. destruct k. apply idpath. apply idpath. Defined. (* An example where it is necessary to evar-normalize the instance of an evar to evaluate if it is a pattern *) Check let a := ?[P] in fun (H : forall y (P : nat -> Prop), y = 0 -> P y) x (p:x=0) => H ?[y] a p : x = 0. (* We have to solve "?P ?y[x] == x = 0" knowing from "p : (x=0) == (?y[x] = 0)" that "?y := x" *) (* An example involving SProp *) Check fun (A:SProp) (f g:A->A) (P:A->Type) a (x : P (f a)) => x : P (g _). rocq-9.2.0/test-suite/success/uniform_inductive_parameters.v000066400000000000000000000012251516144147600244200ustar00rootroot00000000000000Set Uniform Inductive Parameters. Inductive list (A : Type) := | nil : list | cons : A -> list -> list. Check (list : Type -> Type). Check (cons : forall A, A -> list A -> list A). Inductive list2 (A : Type) (A' := prod A A) := | nil2 : list2 | cons2 : A' -> list2 -> list2. Check (list2 : Type -> Type). Check (cons2 : forall A (A' := prod A A), A' -> list2 A -> list2 A). Inductive list3 | A := nil3 | cons3 : A -> list3 (A * A)%type -> list3 A. Unset Uniform Inductive Parameters. Inductive list4 A | := nil4 | cons4 : A -> list4 -> list4. Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop := Acc_in : (forall y, R y x -> Acc y) -> Acc x. rocq-9.2.0/test-suite/success/univers.v000066400000000000000000000036471516144147600201510ustar00rootroot00000000000000(* This requires cumulativity *) Definition Type2 := Type. Definition Type1 : Type2 := Type. Lemma lem1 : (True -> Type1) -> Type2. intro H. apply H. exact I. Qed. Lemma lem2 : forall (A : Type) (P : A -> Type) (x : A), (forall y : A, x = y -> P y) -> P x. auto. Qed. Lemma lem3 : forall P : Prop, P. intro P; pattern P. apply lem2. Abort. (* Check managing of universe constraints in inversion (BZ#855) *) Inductive dep_eq : forall X : Type, X -> X -> Prop := | intro_eq : forall (X : Type) (f : X), dep_eq X f f | intro_feq : forall (A : Type) (B : A -> Type), let T := forall x : A, B x in forall (f g : T) (x : A), dep_eq (B x) (f x) (g x) -> dep_eq T f g. Require Import TestSuite.relationclasses. Theorem dep_eq_trans : forall X : Type, transitive X (dep_eq X). Proof. unfold transitive. intros X f g h H1 H2. inversion H1. Abort. (* Submitted by Bas Spitters (BZ#935) *) (* This is a problem with the status of the type in LetIn: is it a user-provided one or an inferred one? At the current time, the kernel type-check the type in LetIn, which means that it must be considered as user-provided when calling the kernel. However, in practice it is inferred so that a universe refresh is needed to set its status as "user-provided". Especially, universe refreshing was not done for "set/pose" *) Lemma ind_unsec : forall Q : nat -> Type, True. intro. set (C := forall m, Q m -> Q m). exact I. Qed. (* Submitted by Danko Ilik (bug report #1507); related to LetIn *) Record U : Type := { A:=Type; a:A }. (** Check assignment of sorts to inductives and records. *) Parameter sh : list nat. Definition is_box_in_shape (b :nat * nat) := True. Definition myType := Type. Module Ind. Inductive box_in : myType := myBox (coord : nat * nat) (_ : is_box_in_shape coord) : box_in. End Ind. Module Rec. Record box_in : myType := BoxIn { coord :> nat * nat; _ : is_box_in_shape coord }. End Rec. rocq-9.2.0/test-suite/success/universes_coercion.v000066400000000000000000000016221516144147600223510ustar00rootroot00000000000000(* This example used to emphasize the absence of LEGO-style universe polymorphism; Matthieu's improvements of typing on 2011/3/11 now makes (apparently) that Amokrane's automatic eta-expansion in the coercion mechanism works; this makes its illustration as a "weakness" of universe polymorphism obsolete (example submitted by Randy Pollack). Note that this example is not an evidence that the current non-kernel eta-expansion behavior is the most expected one. *) Parameter K : forall T : Type, T -> T. Check (K (forall T : Type, T -> T) K). (* note that the inferred term is "(K (forall T (* u1 *) : Type, T -> T) (fun T:Type (* u1 *) => K T))" which is not eta-equivalent to "(K (forall T : Type, T -> T) K" because the eta-expansion of the latter "(K (forall T : Type, T -> T) (fun T:Type (* u2 *) => K T)" assuming K of type "forall T (* u2 *) : Type, T -> T" *) rocq-9.2.0/test-suite/success/univnames.v000066400000000000000000000016461516144147600204600ustar00rootroot00000000000000Set Universe Polymorphism. Definition foo@{i j} (A : Type@{i}) (B : Type@{j}) := A. Set Printing Universes. Fail Definition bar@{i} (A : Type@{i}) (B : Type) := A. Definition baz@{i j} (A : Type@{i}) (B : Type@{j}) := (A * B)%type. Fail Definition bad@{i j} (A : Type@{i}) (B : Type@{j}) : Type := (A * B)%type. Fail Definition bad@{i} (A : Type@{i}) (B : Type@{j}) : Type := (A * B)%type. Definition shuffle@{i j} (A : Type@{j}) (B : Type@{i}) := (A * B)%type. Definition nothing (A : Type) := A. Inductive bla@{l k} : Type@{k} := blaI : Type@{l} -> bla. Inductive blacopy@{k l} : Type@{k} := blacopyI : Type@{l} -> blacopy. Class Wrap A := wrap : A. Fail #[export] Instance bad@{} : Wrap Type := Type. #[export] Instance bad@{} : Wrap Type. Fail Proof Type. Abort. #[export] Instance bar@{u} : Wrap@{u} Set. Proof nat. Monomorphic Universe g. Inductive blacopy'@{l} : Type@{g} := blacopy'I : Type@{l} -> blacopy'. rocq-9.2.0/test-suite/success/univpoly_cs_unif.v000066400000000000000000000007401516144147600220400ustar00rootroot00000000000000Set Universe Polymorphism. Set Primitive Projections. Structure S := { carrier :> Type; val : carrier }. Canonical Structure default@{i j} : S@{j} := {| carrier := Type@{i}; val := nat |}. Definition test (s : S) : carrier s := val s. (** We want to force a CS resolution for default, so a problem carrier ?S = Type *) Axiom fn : forall x : Type, True. Lemma foo@{i} : True. apply fn. apply (test@{i} _). Qed. Lemma foo'@{i} : True. apply fn. refine (test@{i} _). Qed. rocq-9.2.0/test-suite/success/univscompute.v000066400000000000000000000013211516144147600212020ustar00rootroot00000000000000Set Universe Polymorphism. Polymorphic Definition id {A : Type} (a : A) := a. Eval vm_compute in id 1. Polymorphic Inductive ind (A : Type) := cons : A -> ind A. Eval vm_compute in ind unit. Check ind unit. Eval vm_compute in ind unit. Definition bar := Eval vm_compute in ind unit. Definition bar' := Eval vm_compute in id (cons _ tt). Definition bar'' := Eval native_compute in id 1. Definition bar''' := Eval native_compute in id (cons _ tt). Definition barty := Eval native_compute in id (cons _ Set). Definition one := @id. Monomorphic Definition sec := one. Eval native_compute in sec. Definition sec' := Eval native_compute in sec. Eval vm_compute in sec. Definition sec'' := Eval vm_compute in sec. rocq-9.2.0/test-suite/success/unknown_warning.v000066400000000000000000000010141516144147600216640ustar00rootroot00000000000000Set Warnings "+unknown-warning". Set Warnings "-foo". Fail Set Warnings "foo". Fail Set Warnings "+foo". #[warnings="-foo"] Check True. Fail #[warnings="foo"] Check True. (* debatable: even though "all" overrides "+foo" we still warn *) Fail Set Warnings "+foo,-all". (* debatable: changing unknown-warning has no effect for the current check *) Fail Set Warnings "-unknown-warning,foo". Fail #[warnings="-unknown-warning,foo"] Check True. Set Warnings "-unknown-warning". #[warnings="+unknown-warning,foo"] Check True. rocq-9.2.0/test-suite/success/unshelve.v000066400000000000000000000014341516144147600202770ustar00rootroot00000000000000Axiom F : forall (b : bool), b = true -> forall (i : unit), i = i -> True. Goal True. Proof. unshelve (refine (F _ _ _ _)). + exact true. + exact tt. + exact (@eq_refl bool true). + exact (@eq_refl unit tt). Qed. (* This was failing in 8.6, because of ?a:nat being wrongly duplicated *) Goal (forall a : nat, a = 0 -> True) -> True. intros F. unshelve (eapply (F _);clear F). 2:reflexivity. Qed. (* same think but using Ltac2 refine *) Require Import Ltac2.Ltac2. Goal True. Proof. (* Ltac2 refine is more like simple_refine *) unshelve (refine '(F _ _ _ _); Control.shelve_unifiable ()). + exact true. + exact tt. + exact (@eq_refl bool true). + exact (@eq_refl unit tt). Qed. Goal (forall a : nat, a = 0 -> True) -> True. intros F. unshelve (eapply (&F _);clear F). 2:reflexivity. Qed. rocq-9.2.0/test-suite/success/vm_evars.v000066400000000000000000000005341516144147600202700ustar00rootroot00000000000000Fixpoint iter {A} (n : nat) (f : A -> A) (x : A) := match n with | 0 => x | S n => iter n f (f x) end. Goal nat -> True. Proof. intros n. evar (f : nat -> nat). cut (iter 10 f 0 = 0). vm_compute. intros; constructor. instantiate (f := (fun x => x)). reflexivity. Qed. Goal exists x, x = 5 + 5. Proof. eexists. vm_compute. reflexivity. Qed. rocq-9.2.0/test-suite/success/vm_norm_records.v000066400000000000000000000022551516144147600216460ustar00rootroot00000000000000Set Primitive Projections. (** Variant of VM conversion that exercises the reification part of the VM *) Ltac norm := match goal with [ |- ?P ] => let Q := eval vm_compute in P in change Q end. Module T. Record prod (A : Type) (B : A -> Type) := pair { fst : A; snd : B fst }. Arguments fst {_ _}. Arguments snd {_ _}. Goal forall (p : prod nat (fun n => n = 0)), fst p = 0. Proof. intros p. norm. apply (snd p). Qed. End T. Module M. CoInductive foo := Foo { foo0 : foo; foo1 : bar; } with bar := Bar { bar0 : foo; bar1 : bar; }. CoFixpoint f : foo := Foo f g with g : bar := Bar f g. Goal f.(foo0).(foo0) = g.(bar0). Proof. norm. match goal with [ |- ?t = ?t ] => idtac end. reflexivity. Qed. Goal g.(bar1).(bar0).(foo1) = g. Proof. norm. match goal with [ |- ?t = ?t ] => idtac end. reflexivity. Qed. End M. Module N. Inductive foo := Foo { foo0 : option foo; foo1 : list bar; } with bar := Bar { bar0 : option bar; bar1 : list foo; }. Definition f_0 := Foo None nil. Definition g_0 := Bar None nil. Definition f := Foo (Some f_0) (cons g_0 nil). Goal f.(foo1) = cons g_0 nil. Proof. norm. match goal with [ |- ?t = ?t ] => idtac end. reflexivity. Qed. End N. rocq-9.2.0/test-suite/success/vm_records.v000066400000000000000000000011731516144147600206110ustar00rootroot00000000000000Set Primitive Projections. Module M. CoInductive foo := Foo { foo0 : foo; foo1 : bar; } with bar := Bar { bar0 : foo; bar1 : bar; }. CoFixpoint f : foo := Foo f g with g : bar := Bar f g. Check (@eq_refl _ g.(bar0) <: f.(foo0).(foo0) = g.(bar0)). Check (@eq_refl _ g <: g.(bar1).(bar0).(foo1) = g). End M. Module N. Inductive foo := Foo { foo0 : option foo; foo1 : list bar; } with bar := Bar { bar0 : option bar; bar1 : list foo; }. Definition f_0 := Foo None nil. Definition g_0 := Bar None nil. Definition f := Foo (Some f_0) (cons g_0 nil). Check (@eq_refl _ f.(foo1) <: f.(foo1) = cons g_0 nil). End N. rocq-9.2.0/test-suite/success/vm_univ_poly.v000066400000000000000000000101421516144147600211700ustar00rootroot00000000000000(* Basic tests *) Polymorphic Definition pid {T : Type} (x : T) : T := x. (* Definition _1 : pid true = true := @eq_refl _ true <: pid true = true. Polymorphic Definition a_type := Type. Definition _2 : a_type@{i} = Type@{i} := @eq_refl _ Type@{i} <: a_type@{i} = Type@{i}. Polymorphic Definition FORALL (T : Type) (P : T -> Prop) : Prop := forall x : T, P x. Polymorphic Axiom todo : forall {T:Type}, T -> T. Polymorphic Definition todo' (T : Type) := @todo T. Definition _3 : @todo'@{Set} = @todo@{Set} := @eq_refl _ (@todo@{Set}) <: @todo'@{Set} = @todo@{Set}. *) (* Inductive Types *) Inductive sumbool (A B : Prop) : Set := | left : A -> sumbool A B | right : B -> sumbool A B. Definition x : sumbool True False := left _ _ I. Definition sumbool_copy {A B : Prop} (H : sumbool A B) : sumbool A B := match H with | left _ _ x => left _ _ x | right _ _ x => right _ _ x end. Definition _4 : sumbool_copy x = x := @eq_refl _ x <: sumbool_copy x = x. (* Polymorphic Inductive Types *) Polymorphic Inductive poption@{i} (T : Type@{i}) : Type@{i} := | PSome : T -> poption T | PNone : poption T. Polymorphic Definition poption_default@{i} {T : Type@{i}} (p : poption@{i} T) (x : T) : T := match p with | @PSome _ y => y | @PNone _ => x end. Polymorphic Inductive plist@{i} (T : Type@{i}) : Type@{i} := | pnil | pcons : T -> plist T -> plist T. Arguments pnil {_}. Arguments pcons {_} _ _. Polymorphic Definition pmap@{i j} {T : Type@{i}} {U : Type@{j}} (f : T -> U) := fix pmap (ls : plist@{i} T) : plist@{j} U := match ls with | @pnil _ => @pnil _ | @pcons _ l ls => @pcons@{j} U (f l) (pmap ls) end. Universe Ubool. Inductive tbool : Type@{Ubool} := ttrue | tfalse. Eval vm_compute in pmap pid (pcons true (pcons false pnil)). Eval vm_compute in pmap (fun x => match x with | pnil => true | pcons _ _ => false end) (pcons pnil (pcons (pcons false pnil) pnil)). Eval vm_compute in pmap (fun x => x -> Type) (pcons tbool (pcons (plist tbool) pnil)). Polymorphic Inductive Tree@{i} (T : Type@{i}) : Type@{i} := | Empty | Branch : plist@{i} (Tree T) -> Tree T. Polymorphic Definition pfold@{i u} {T : Type@{i}} {U : Type@{u}} (f : T -> U -> U) := fix pfold (acc : U) (ls : plist@{i} T) : U := match ls with | pnil => acc | pcons a b => pfold (f a acc) b end. Polymorphic Inductive nat@{i} : Type@{i} := | O | S : nat -> nat. Polymorphic Fixpoint nat_max@{i} (a b : nat@{i}) : nat@{i} := match a , b with | O , b => b | a , O => a | S a , S b => S (nat_max a b) end. Polymorphic Fixpoint height@{i} {T : Type@{i}} (t : Tree@{i} T) : nat@{i} := match t return nat@{i} with | Empty _ => O | Branch _ ls => S@{i} (pfold@{i i} nat_max O (pmap height ls)) end. Polymorphic Fixpoint repeat@{i} {T : Type@{i}} (n : nat@{i}) (v : T) : plist@{i} T := match n return plist@{i} T with | O => pnil | S n => pcons@{i} v (repeat n v) end. Polymorphic Fixpoint big_tree@{i} (n : nat@{i}) : Tree@{i} nat@{i} := match n with | O => @Empty nat@{i} | S n' => Branch@{i} nat@{i} (repeat@{i} n' (big_tree n')) end. Eval compute in height (big_tree (S (S (S O)))). #[local] Definition big := S (S (S (S (S O)))). Polymorphic Definition really_big@{i} := (S@{i} (S (S (S (S (S (S (S (S (S O)))))))))). Time Definition _5 : height (@Empty nat) = O := @eq_refl nat O <: height (@Empty nat) = O. Time Definition _6 : height@{Set} (@Branch nat pnil) = S O := @eq_refl nat@{Set} (S@{Set} O@{Set}) <: @eq nat@{Set} (height@{Set} (@Branch@{Set} nat@{Set} (@pnil@{Set} (Tree@{Set} nat@{Set})))) (S@{Set} O@{Set}). Time Definition _7 : height (big_tree big) = big := @eq_refl nat big <: height (big_tree big) = big. Time Definition _8 : height (big_tree really_big) = really_big := @eq_refl nat@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} (S@{Set} O@{Set})))))))))) <: @eq nat@{Set} (@height nat@{Set} (big_tree really_big@{Set})) really_big@{Set}. rocq-9.2.0/test-suite/success/vm_univ_poly_match.v000066400000000000000000000011361516144147600223470ustar00rootroot00000000000000Set Dump Bytecode. Set Printing Universes. Set Printing All. Polymorphic Class Applicative@{d c} (T : Type@{d} -> Type@{c}) := { pure : forall {A : Type@{d}}, A -> T A ; ap : forall {A B : Type@{d}}, T (A -> B) -> T A -> T B }. Universes Uo Ua. Eval compute in @pure@{Uo Ua}. Global Instance Applicative_option : Applicative@{Uo Ua} option := {| pure := @Some ; ap := fun _ _ f x => match f , x with | Some f , Some x => Some (f x) | _ , _ => None end |}. Definition foo := ap (ap (pure plus) (pure 1)) (pure 1). Print foo. Eval vm_compute in foo. rocq-9.2.0/test-suite/success/warnings_attribute.v000066400000000000000000000002611516144147600223560ustar00rootroot00000000000000 Set Primitive Projections. Fail #[warnings="+non-primitive-record"] Record foo : Prop := { _ : nat }. #[warnings="-non-primitive-record"] Record foo : Prop := { _ : nat }. rocq-9.2.0/test-suite/success/with_strategy.v000066400000000000000000000547141516144147600213540ustar00rootroot00000000000000Notation aid := (@id) (only parsing). Notation idn := id (only parsing). Ltac unfold_id := unfold id. Fixpoint fact (n : nat) := match n with | 0 => 1 | S n => (S n) * fact n end. Opaque id. Goal id 0 = 0. with_strategy opaque [id] (with_strategy opaque [id id] (assert_fails unfold_id; with_strategy transparent [id] (assert_succeeds unfold_id; with_strategy opaque [id] (with_strategy 0 [id] (assert_succeeds unfold_id; with_strategy 1 [id] (assert_succeeds unfold_id; with_strategy -1 [id] (assert_succeeds unfold_id; with_strategy opaque [id] (assert_fails unfold_id; with_strategy transparent [id] (assert_succeeds unfold_id; with_strategy opaque [id] (with_strategy expand [id] (assert_succeeds unfold_id; let l := strategy_level:(expand) in with_strategy l [id] (let idx := smart_global:(id) in cbv [idx]; (* This should succeed, but doesn't, basically due to https://github.com/rocq-prover/rocq/issues/11202 *) assert_fails (let idx := smart_global:(id) in with_strategy expand [idx] idtac); reflexivity)))))))))))). Qed. Goal id 0 = 0. with_strategy opaque [aid] (assert_fails unfold_id; with_strategy transparent [aid] (assert_succeeds unfold_id; with_strategy opaque [aid] (with_strategy 0 [aid] (assert_succeeds unfold_id; with_strategy 1 [aid] (assert_succeeds unfold_id; with_strategy -1 [aid] (assert_succeeds unfold_id; with_strategy opaque [aid] (assert_fails unfold_id; with_strategy transparent [aid] (assert_succeeds unfold_id; with_strategy opaque [aid] (with_strategy expand [aid] (assert_succeeds unfold_id; reflexivity)))))))))). Qed. Goal id 0 = 0. with_strategy opaque [idn] (assert_fails unfold_id; with_strategy transparent [idn] (assert_succeeds unfold_id; with_strategy opaque [idn] (with_strategy 0 [idn] (assert_succeeds unfold_id; with_strategy 1 [idn] (assert_succeeds unfold_id; with_strategy -1 [idn] (assert_succeeds unfold_id; with_strategy opaque [idn] (assert_fails unfold_id; with_strategy transparent [idn] (assert_succeeds unfold_id; with_strategy opaque [idn] (with_strategy expand [idn] (assert_succeeds unfold_id; reflexivity)))))))))). Qed. (* test that strategy tactic does not persist after the execution of the tactic *) Opaque id. Goal id 0 = 0. assert_fails unfold_id; (with_strategy transparent [id] assert_succeeds unfold_id); assert_fails unfold_id. assert_fails unfold_id. with_strategy transparent [id] assert_succeeds unfold_id. assert_fails unfold_id. reflexivity. Qed. (* test that the strategy tactic does persist through abstract *) Opaque id. Goal id 0 = 0. Time Timeout 5 with_strategy expand [id] assert (id (fact 100) = fact 100) by abstract reflexivity. reflexivity. Time Timeout 5 Defined. (* test that it works even with [Qed] *) Goal id 0 = 0. Proof using Type. Time Timeout 5 abstract (with_strategy expand [id] assert (id (fact 100) = fact 100) by abstract reflexivity; reflexivity). Time Timeout 5 Qed. (* test that the strategy is correctly reverted after closing the goal completely *) Goal id 0 = 0. assert (id 0 = 0) by with_strategy expand [id] reflexivity. Fail unfold id. reflexivity. Qed. (* test that the strategy is correctly reverted after failure *) Goal id 0 = 0. let id' := id in (try with_strategy expand [id] fail); assert_fails unfold id'. Fail unfold id. (* a more complicated test involving a success and then a failure after backtracking *) let id' := id in ((with_strategy expand [id] (unfold id' + fail)) + idtac); lazymatch goal with |- id 0 = 0 => idtac end; assert_fails unfold id'. Fail unfold id. reflexivity. Qed. (* test multi-success *) Goal id (fact 100) = fact 100. Timeout 1 (with_strategy -1 [id] (((idtac + (abstract reflexivity))); fail)). Undo. Timeout 1 let id' := id in (with_strategy -1 [id] (((idtac + (unfold id'; reflexivity))); fail)). Undo. Timeout 1 (with_strategy -1 [id] (idtac + (abstract reflexivity))); fail. (* should not time out *) Undo. with_strategy -1 [id] abstract reflexivity. Defined. (* check that module substitutions happen correctly *) Module F. Definition id {T} := @id T. Opaque id. Ltac with_transparent_id tac := with_strategy transparent [id] tac. End F. Opaque F.id. Goal F.id 0 = F.id 0. Fail unfold F.id. F.with_transparent_id ltac:(progress unfold F.id). Undo. F.with_transparent_id ltac:(let x := constr:(@F.id) in progress unfold x). Abort. Module Type Empty. End Empty. Module E. End E. Module F2F (E : Empty). Definition id {T} := @id T. Opaque id. Ltac with_transparent_id tac := with_strategy transparent [id] tac. End F2F. Module F2 := F2F E. Opaque F2.id. Goal F2.id 0 = F2.id 0. Fail unfold F2.id. F2.with_transparent_id ltac:(progress unfold F2.id). Undo. F2.with_transparent_id ltac:(let x := constr:(@F2.id) in progress unfold x). Abort. (* test the tactic notation entries *) Tactic Notation "with_strategy0" strategy_level(l) "[" ne_smart_global_list(v) "]" tactic3(tac) := with_strategy l [ v ] tac. Tactic Notation "with_strategy1" strategy_level_or_var(l) "[" ne_smart_global_list(v) "]" tactic3(tac) := with_strategy l [ v ] tac. Tactic Notation "with_strategy2" strategy_level(l) "[" constr(v) "]" tactic3(tac) := with_strategy l [ v ] tac. Tactic Notation "with_strategy3" strategy_level_or_var(l) "[" constr(v) "]" tactic3(tac) := with_strategy l [ v ] tac. (* [with_strategy0] should work, but it doesn't, due to a combination of https://github.com/rocq-prover/rocq/issues/11202 and https://github.com/rocq-prover/rocq/issues/11209 *) Opaque id. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy0 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy0 opaque [id id] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy0 0 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 1 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 -1 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [id] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy0 expand [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. (* This should succeed, but doesn't, basically due to https://github.com/rocq-prover/rocq/issues/11202 *) Fail let idx := smart_global:(id) in with_strategy0 expand [idx] idtac. reflexivity. Qed. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy0 opaque [aid] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [aid] idtac. Fail (* should work, not Fail *) with_strategy0 0 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 1 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 -1 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [aid] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [aid] idtac. Fail (* should work, not Fail *) with_strategy0 expand [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. reflexivity. Qed. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy0 opaque [idn] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [idn] idtac. Fail (* should work, not Fail *) with_strategy0 0 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 1 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 -1 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [idn] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy0 transparent [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy0 opaque [idn] idtac. Fail (* should work, not Fail *) with_strategy0 expand [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. reflexivity. Qed. (* [with_strategy1] should work, but it doesn't, due to a combination of https://github.com/rocq-prover/rocq/issues/11202 and https://github.com/rocq-prover/rocq/issues/11209 *) Opaque id. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy1 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy1 opaque [id id] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy1 0 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 1 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 -1 [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [id] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [id] idtac. Fail (* should work, not Fail *) with_strategy1 expand [id] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) let l := strategy_level:(expand) in with_strategy1 l [id] idtac. (* This should succeed, but doesn't, basically due to https://github idtac.com/coq/coq/issues/11202 *) Fail let idx := smart_global:(id) in with_strategy1 expand [idx] idtac. reflexivity. Qed. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy1 opaque [aid] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [aid] idtac. Fail (* should work, not Fail *) with_strategy1 0 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 1 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 -1 [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [aid] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [aid] idtac. Fail (* should work, not Fail *) with_strategy1 expand [aid] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. reflexivity. Qed. Goal id 0 = 0. Fail (* should work, not Fail *) with_strategy1 opaque [idn] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [idn] idtac. Fail (* should work, not Fail *) with_strategy1 0 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 1 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 -1 [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [idn] idtac. assert_fails unfold_id. Fail (* should work, not Fail *) with_strategy1 transparent [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. Fail (* should work, not Fail *) with_strategy1 opaque [idn] idtac. Fail (* should work, not Fail *) with_strategy1 expand [idn] idtac. Fail (* should work, not Fail *) assert_succeeds unfold_id idtac. reflexivity. Qed. Opaque id. Goal id 0 = 0. with_strategy2 opaque [id] (with_strategy2 opaque [id] (assert_fails unfold_id; with_strategy2 transparent [id] (assert_succeeds unfold_id; with_strategy2 opaque [id] (with_strategy2 0 [id] (assert_succeeds unfold_id; with_strategy2 1 [id] (assert_succeeds unfold_id; with_strategy2 -1 [id] (assert_succeeds unfold_id; with_strategy2 opaque [id] (assert_fails unfold_id; with_strategy2 transparent [id] (assert_succeeds unfold_id; with_strategy2 opaque [id] (with_strategy2 expand [id] (assert_succeeds unfold_id))))))))))). (* This should succeed, but doesn't, basically due to https://github.com/rocq-prover/rocq/issues/11202 *) Fail let idx := smart_global:(id) in with_strategy2 expand [idx] idtac. reflexivity. Qed. Goal id 0 = 0. with_strategy2 opaque [aid] (with_strategy2 opaque [aid] (assert_fails unfold_id; with_strategy2 transparent [aid] (assert_succeeds unfold_id; with_strategy2 opaque [aid] (with_strategy2 0 [aid] (assert_succeeds unfold_id; with_strategy2 1 [aid] (assert_succeeds unfold_id; with_strategy2 -1 [aid] (assert_succeeds unfold_id; with_strategy2 opaque [aid] (assert_fails unfold_id; with_strategy2 transparent [aid] (assert_succeeds unfold_id; with_strategy2 opaque [aid] (with_strategy2 expand [aid] (assert_succeeds unfold_id))))))))))). reflexivity. Qed. Goal id 0 = 0. with_strategy2 opaque [idn] (with_strategy2 opaque [idn] (assert_fails unfold_id; with_strategy2 transparent [idn] (assert_succeeds unfold_id; with_strategy2 opaque [idn] (with_strategy2 0 [idn] (assert_succeeds unfold_id; with_strategy2 1 [idn] (assert_succeeds unfold_id; with_strategy2 -1 [idn] (assert_succeeds unfold_id; with_strategy2 opaque [idn] (assert_fails unfold_id; with_strategy2 transparent [idn] (assert_succeeds unfold_id; with_strategy2 opaque [idn] (with_strategy2 expand [idn] (assert_succeeds unfold_id))))))))))). reflexivity. Qed. Opaque id. Goal id 0 = 0. with_strategy3 opaque [id] (with_strategy3 opaque [id] (assert_fails unfold_id; with_strategy3 transparent [id] (assert_succeeds unfold_id; with_strategy3 opaque [id] (with_strategy3 0 [id] (assert_succeeds unfold_id; with_strategy3 1 [id] (assert_succeeds unfold_id; with_strategy3 -1 [id] (assert_succeeds unfold_id; with_strategy3 opaque [id] (assert_fails unfold_id; with_strategy3 transparent [id] (assert_succeeds unfold_id; with_strategy3 opaque [id] (with_strategy3 expand [id] (assert_succeeds unfold_id))))))))))). (* This should succeed, but doesn't, basically due to https://github.com/rocq-prover/rocq/issues/11202 *) Fail let idx := smart_global:(id) in with_strategy3 expand [idx] idtac. reflexivity. Qed. Goal id 0 = 0. with_strategy3 opaque [aid] (with_strategy3 opaque [aid] (assert_fails unfold_id; with_strategy3 transparent [aid] (assert_succeeds unfold_id; with_strategy3 opaque [aid] (with_strategy3 0 [aid] (assert_succeeds unfold_id; with_strategy3 1 [aid] (assert_succeeds unfold_id; with_strategy3 -1 [aid] (assert_succeeds unfold_id; with_strategy3 opaque [aid] (assert_fails unfold_id; with_strategy3 transparent [aid] (assert_succeeds unfold_id; with_strategy3 opaque [aid] (with_strategy3 expand [aid] (assert_succeeds unfold_id))))))))))). reflexivity. Qed. Goal id 0 = 0. with_strategy3 opaque [idn] (with_strategy3 opaque [idn] (assert_fails unfold_id; with_strategy3 transparent [idn] (assert_succeeds unfold_id; with_strategy3 opaque [idn] (with_strategy3 0 [idn] (assert_succeeds unfold_id; with_strategy3 1 [idn] (assert_succeeds unfold_id; with_strategy3 -1 [idn] (assert_succeeds unfold_id; with_strategy3 opaque [idn] (assert_fails unfold_id; with_strategy3 transparent [idn] (assert_succeeds unfold_id; with_strategy3 opaque [idn] (with_strategy3 expand [idn] (assert_succeeds unfold_id))))))))))). reflexivity. Qed. (* Fake out coqchk to work around what is essentially COQBUG(https://github.com/rocq-prover/rocq/issues/12200) *) Reset Initial. rocq-9.2.0/test-suite/tools/000077500000000000000000000000001516144147600157455ustar00rootroot00000000000000rocq-9.2.0/test-suite/tools/coq_config_to_make.ml000066400000000000000000000062231516144147600221100ustar00rootroot00000000000000(* Flags used to compile Coq but _not_ plugins (via rocq makefile) *) module Prefs = struct type t = { warn_error : bool } let default = { warn_error = true } end let die fmt = Printf.kfprintf (fun _ -> exit 1) stderr (fmt^^"\n%!") (** This Makefile is only used in the test-suite now, remove eventually. *) let write_makefile coqprefix coqlibinstall best_compiler ocamlfind caml_flags coq_caml_flags o () = let pr s = Printf.fprintf o s in pr "###### Coq Test suite configuration ##############################\n"; pr "# #\n"; pr "# This file is generated by the script \"coq_config_to_make\" #\n"; pr "# DO NOT EDIT IT !! DO NOT EDIT IT !! DO NOT EDIT IT !! #\n"; pr "# #\n"; pr "##################################################################\n\n"; pr "# Paths where Coq is installed\n"; pr "COQPREFIX='%s'\n" coqprefix; pr "COQLIBINSTALL='%s'\n\n" coqlibinstall; pr "# The best compiler: native (=opt) or bytecode (=byte)\n"; pr "BEST=%s\n\n" best_compiler; pr "# Findlib command\n"; pr "OCAMLFIND=%S\n" ocamlfind; pr "# Caml flags\n"; pr "CAMLFLAGS=%s %s\n" caml_flags coq_caml_flags; pr "# coqc was said to be '%s'\n" Sys.argv.(1); pr "ARCH=%s\n" Coq_config.arch; () let coq_warn_error (prefs : Prefs.t) = if prefs.warn_error then "-warn-error +a" else "" let canonical_path_name p = let current = Sys.getcwd () in try Sys.chdir p; let p' = Sys.getcwd () in Sys.chdir current; p' with Sys_error _ -> (* We give up to find a canonical name and just simplify it... *) Filename.concat current p let find_in_PATH f = if Filename.basename f <> f then Some f else match Sys.getenv_opt "PATH" with | None -> None | Some paths -> let sep = if Coq_config.arch_is_win32 then ';' else ':' in let paths = String.split_on_char sep paths in paths |> List.map (fun path -> if path = "" then f else Filename.concat path f) |> List.find_opt Sys.file_exists let main () = if Array.length Sys.argv < 2 then die "usage: %s ROCQ_EXE [OUT_FILE]" Sys.argv.(0); let coqc = Sys.argv.(1) in let coqc = match find_in_PATH coqc with | Some f -> f | None -> die "Could not find %s in PATH." coqc in let coqbin = canonical_path_name (Filename.dirname coqc) in let coqroot = Filename.dirname coqbin in let relocate = function | Coq_config.NotRelocatable p -> p | Coq_config.Relocatable p -> Filename.concat coqroot p in let prefs = Prefs.default in let coqprefix = relocate Coq_config.install_prefix in let coqlibinstall = relocate Coq_config.coqlib in (* EJGA: Good enough approximation *) let best_compiler = if Coq_config.has_natdynlink then "opt" else "byte" in let ocamlfind = Coq_config.ocamlfind in let caml_flags = Coq_config.caml_flags in let coq_caml_flags = coq_warn_error prefs in let out = if Array.length Sys.argv = 2 then stdout else open_out Sys.argv.(2) in Printf.fprintf out "%a\n%!" (write_makefile coqprefix coqlibinstall best_compiler ocamlfind caml_flags coq_caml_flags) (); () let () = main () rocq-9.2.0/test-suite/tools/coq_config_to_make.mli000066400000000000000000000000001516144147600222440ustar00rootroot00000000000000rocq-9.2.0/test-suite/tools/dune000066400000000000000000000001111516144147600166140ustar00rootroot00000000000000(executable (name coq_config_to_make) (libraries rocq-runtime.config)) rocq-9.2.0/test-suite/unit-tests/000077500000000000000000000000001516144147600167245ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/.merlin.in000066400000000000000000000000331516144147600206140ustar00rootroot00000000000000REC S ** B ** PKG ounit2 rocq-9.2.0/test-suite/unit-tests/clib/000077500000000000000000000000001516144147600176355ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/clib/clist.ml000066400000000000000000000031141516144147600213040ustar00rootroot00000000000000open Utest let log_out_ch = open_log_out_ch __FILE__ let reference_filter = let rec filter f = function | [] -> [] | x :: tl as l -> if f x then let tl' = filter f tl in if tl == tl' then l else x :: tl' else filter f tl in filter let () = let () = Random.self_init () in let seed = Random.bits() in Printf.fprintf log_out_ch "seed = %d\n" seed; Random.init seed let lists = List.init 100 (fun _ -> let len = Random.int 100 in List.init len (fun _ -> let b = Random.bool() in let v = Random.bits() in b,v)) let t1 = mk_bool_test "clib-clist0" "filter produces correct values" (List.for_all (fun l -> let expected : (bool * int) list = reference_filter fst l in let generated = CList.filter fst l in expected = generated) lists) let lists' = List.init 100 (fun _ -> let len = Random.int 100 in let keepafter = if len = 0 then 0 else Random.int len in let l = List.init len (fun i -> let b = i >= keepafter || Random.bool () in let v = Random.bits() in b, v) in keepafter, l) let t2 = mk_bool_test "clib-clist1" "filter correctly preserves physical equality of tails" (List.for_all (fun (keepafter,l) -> flush log_out_ch; let generated = CList.filter fst l in let tl = CList.skipn keepafter l in let generated_tl = CList.lastn (List.length tl) generated in tl == generated_tl) lists') let tests = [ t1; t2 ] let _ = run_tests __FILE__ log_out_ch tests rocq-9.2.0/test-suite/unit-tests/clib/inteq.ml000066400000000000000000000005031516144147600213050ustar00rootroot00000000000000open Utest let log_out_ch = open_log_out_ch __FILE__ let eq0 = mk_bool_test "clib-inteq0" "Int.equal on 0" (Int.equal 0 0) let eq42 = mk_bool_test "clib-inteq42" "Int.equal on 42" (Int.equal 42 42) let tests = [ eq0; eq42 ] let _ = run_tests __FILE__ log_out_ch tests rocq-9.2.0/test-suite/unit-tests/clib/unicode_tests.ml000066400000000000000000000010271516144147600230370ustar00rootroot00000000000000open Utest let log_out_ch = open_log_out_ch __FILE__ let unicode0 = mk_eq_test "clib-unicode0" "split_at_first_letter, first letter is character" None (Unicode.split_at_first_letter "ident") let unicode1 = mk_eq_test "clib-unicode1" "split_at_first_letter, first letter not character" (Some ("__","ident")) (Unicode.split_at_first_letter "__ident") let tests = [ unicode0; unicode1 ] let _ = run_tests __FILE__ log_out_ch tests rocq-9.2.0/test-suite/unit-tests/lib/000077500000000000000000000000001516144147600174725ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/lib/coqProject.ml000066400000000000000000000035601516144147600221410ustar00rootroot00000000000000open OUnit open Utest open CoqProject_file let tests = ref [] let add_test name test = tests := (mk_test name (TestCase test)) :: !tests let sourced_file x = { thing = x; source = ProjectFile } (* Implicit argument for `read_project_file` *) let warning_fn _ = () let t () = let project_file_contents = "" in bracket_tmpfile (fun (project_file_path, project_file_channel) -> output_string project_file_channel project_file_contents; flush project_file_channel; let expected : unit project = { project_file = Some project_file_path; makefile = None; native_compiler = None; docroot = None; files = []; cmd_line_files = []; meta_file = Absent; ml_includes = []; r_includes = []; q_includes = []; extra_args = []; defs = []; extra_data = (); } in assert_equal expected (read_project_file ~warning_fn project_file_path) ) () let _ = add_test "empty file" t let t () = let project_file_contents = "-arg \"-w default\" -arg -w -arg foo -arg \"-set 'Default Goal Selector=!'\"" in bracket_tmpfile (fun (project_file_path, project_file_channel) -> output_string project_file_channel project_file_contents; flush project_file_channel; let expected : unit project = { project_file = Some project_file_path; makefile = None; native_compiler = None; docroot = None; files = []; cmd_line_files = []; meta_file = Absent; ml_includes = []; r_includes = []; q_includes = []; extra_args = List.map sourced_file ["-w"; "default"; "-w"; "foo"; "-set"; "Default Goal Selector=!"]; defs = []; extra_data = (); } in assert_equal expected (read_project_file ~warning_fn project_file_path) ) () let _ = add_test "-arg separation" t let _ = run_tests __FILE__ (open_log_out_ch __FILE__) (List.rev !tests) rocq-9.2.0/test-suite/unit-tests/lib/pp_big_vect.ml000066400000000000000000000005321516144147600223050ustar00rootroot00000000000000open OUnit open Pp let pr_big_vect = let n = "pr_big_vect" in n >:: (fun () -> let v = Array.make (1 lsl 20) () in let pp = prvecti_with_sep spc (fun _ _ -> str"x") v in let str = string_of_ppcmds pp in ignore(str)) let tests = [pr_big_vect] let () = Utest.run_tests __FILE__ (Utest.open_log_out_ch __FILE__) tests rocq-9.2.0/test-suite/unit-tests/parsing/000077500000000000000000000000001516144147600203675ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/parsing/lexer_recovery.ml000066400000000000000000000037231516144147600237630ustar00rootroot00000000000000(* The idea of this test is to have the lexer crash at a new line, with the βˆ€ symbol in line 2; then we test that we can recover correctly. *) let doc = "Definition map_union_weak `{Ξ² A, Insert K A (M A), βˆ€ A, Empty (M A), βˆ€ A, Lookup K A (M A), βˆ€ A, FinMapToList K A (M A)} {A} (m1 m2 : M A) := map_imap (Ξ» l v, Some (default v (m1 !! l))) m2." let parse pa n = let entry = Pvernac.Vernac_.main_entry in let rec loop res n = if n = 0 then res else match Procq.Entry.parse entry pa with | None -> res | Some r -> loop (r :: res) (n-1) in loop [] n |> List.rev let raw_pr_loc fmt (l : Loc.t) = let { Loc.fname=_; line_nb; bol_pos; line_nb_last; bol_pos_last; bp; ep } = l in Format.fprintf fmt "| line_nb: %d | bol_pos: %d | line_nb_last: %d | bol_pos_last: %d | bp: %d | ep: %d |" line_nb bol_pos line_nb_last bol_pos_last bp ep let print_locs fmt { CAst.loc; _ } = Option.iter (Format.fprintf fmt "@[%a@]" raw_pr_loc) loc let setup_pa () = let text = doc in Procq.Parsable.make (Gramlib.Stream.of_string text) let parse_whole pa = parse pa 10 (* Use junk *) let log_file = __FILE__ ^ ".log" let main () = let pa = setup_pa () in let res, loc = try let _ = parse_whole pa in false, Procq.Parsable.loc pa with (* should be `E Undefined_token` but type is private *) | CLexer.Error.E _ -> (* We now consume a single token and check that the location is correct for "A" *) let () = Procq.Parsable.consume pa 1 in let loc = Procq.Parsable.loc pa in let res = (loc.line_nb = 2) && (loc.bol_pos = 52) && (loc.bp = 58) && (loc.ep = 59) in res, loc | _ -> false, Procq.Parsable.loc pa in let oc = Stdlib.open_out log_file in let outf = Format.formatter_of_out_channel oc in Format.fprintf outf "fail lexer test passed: %a@\n%!" raw_pr_loc loc; Format.pp_print_flush outf (); Stdlib.close_out oc; if res then exit 0 else exit 1 let () = main () rocq-9.2.0/test-suite/unit-tests/parsing/resumption.ml000066400000000000000000000045421516144147600231330ustar00rootroot00000000000000let doc = "Definition a := Type. Definition b := Prop. Definition c := b. Definition d := c. (* this is a comment *) Definition m := forall (x : Type), x. " let parse pa n = let entry = Pvernac.Vernac_.main_entry in let rec loop res n = if n = 0 then res else match Procq.Entry.parse entry pa with | None -> res | Some r -> loop (r :: res) (n-1) in loop [] n |> List.rev let raw_pr_loc fmt (l : Loc.t) = let { Loc.fname=_; line_nb; bol_pos; line_nb_last; bol_pos_last; bp; ep } = l in Format.fprintf fmt "| line_nb: %d | bol_pos: %d | line_nb_last: %d | bol_pos_last: %d | bp: %d | ep: %d |" line_nb bol_pos line_nb_last bol_pos_last bp ep let print_locs fmt { CAst.loc; _ } = Option.iter (Format.fprintf fmt "@[%a@]" raw_pr_loc) loc let parse_whole () = let text = doc in let pa = Procq.Parsable.make (Gramlib.Stream.of_string text) in parse pa 10 (* Use junk *) let parse_n n = let pa = Procq.Parsable.make (Gramlib.Stream.of_string doc) in let res1 = parse pa n in let loc = Procq.Parsable.loc pa |> CLexer.after in let str = Gramlib.Stream.of_string doc in Gramlib.Stream.njunk () loc.bp str; let pa = Procq.Parsable.make ~loc str in let res2 = parse pa 10 in res1 @ res2 (* Use offset to set count and avoid the junk *) let parse_n_offset n = let pa = Procq.Parsable.make (Gramlib.Stream.of_string doc) in let res1 = parse pa n in let loc = Procq.Parsable.loc pa |> CLexer.after in let doc = String.sub doc loc.bp (String.length doc - loc.bp) in let str = Gramlib.Stream.of_string ~offset:loc.bp doc in let pa = Procq.Parsable.make ~loc str in let res2 = parse pa 10 in res1 @ res2 let log_file = __FILE__ ^ ".log" let main () = let reference = parse_whole () in let test1 = [parse_n 1; parse_n 2; parse_n 3; parse_n 4; parse_n 5] in let test2 = [parse_n_offset 1; parse_n_offset 2; parse_n_offset 3; parse_n_offset 4; parse_n_offset 5] in let tests = test1 @ test2 in let res = List.for_all (fun t -> t = reference) tests in let oc = Stdlib.open_out log_file in let outf = Format.formatter_of_out_channel oc in Format.fprintf outf "split parsing test passed: %b@\n%!" res; List.iter (Format.fprintf outf "locs@\n@[%a@]@\n@\n" (Format.pp_print_list print_locs)) tests; Format.pp_print_flush outf (); Stdlib.close_out oc; if res then exit 0 else exit 1 let () = main () rocq-9.2.0/test-suite/unit-tests/printing/000077500000000000000000000000001516144147600205565ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/printing/proof_diffs_test.ml000066400000000000000000000350431516144147600244540ustar00rootroot00000000000000open OUnit open Utest open Pp_diff open Proof_diffs (* Needed to be able to set through goptions *) let () = let open Names in Lib.start_compilation DirPath.dummy (ModPath.MPfile DirPath.dummy) let tokenize_string = Proof_diffs.tokenize_string let diff_pp = diff_pp ~tokenize_string let diff_str = diff_str ~tokenize_string let tests = ref [] let add_test name test = tests := (mk_test name (TestCase test)) :: !tests let log_out_ch = open_log_out_ch __FILE__ let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "") oc) let cprintf s = cfprintf log_out_ch s let _ = Proof_diffs.log_out_ch := log_out_ch let string_of_string s : string = "\"" ^ s ^ "\"" (* todo: OCaml: why can't the body of the test function be given in the add_test line? *) let t () = let expected : diff_list = [] in let diffs = diff_str "" " " in assert_equal ~msg:"empty" ~printer:string_of_diffs expected diffs; let (has_added, has_removed) = has_changes diffs in assert_equal ~msg:"has `Added" ~printer:string_of_bool false has_added; assert_equal ~msg:"has `Removed" ~printer:string_of_bool false has_removed let _ = add_test "diff_str empty" t let t () = let expected : diff_list = [ `Common (0, 0, "a"); `Common (1, 1, "b"); `Common (2, 2, "c")] in let diffs = diff_str "a b c" " a b\t c\n" in assert_equal ~msg:"white space" ~printer:string_of_diffs expected diffs; let (has_added, has_removed) = has_changes diffs in assert_equal ~msg:"no `Added" ~printer:string_of_bool false has_added; assert_equal ~msg:"no `Removed" ~printer:string_of_bool false has_removed let _ = add_test "diff_str white space" t let t () = let expected : diff_list = [ `Removed (0, "a"); `Added (0, "b")] in let diffs = diff_str "a" "b" in assert_equal ~msg:"add/remove" ~printer:string_of_diffs expected diffs; let (has_added, has_removed) = has_changes diffs in assert_equal ~msg:"has `Added" ~printer:string_of_bool true has_added; assert_equal ~msg:"has `Removed" ~printer:string_of_bool true has_removed let _ = add_test "diff_str add/remove" t (* lexer tweaks: comments are lexed as multiple tokens strings tokens include begin/end quotes and embedded "" single multibyte characters returned even if they're not keywords inputs that give a lexer failure (but no use case needs them yet): ".12" unterminated string invalid UTF-8 sequences *) let t () = let str = "(* comment.field *) ?id () \"str\"\"ing\" \\ := Π– > βˆƒ 'c' xx" in let toks = tokenize_string str in (*List.iter (fun x -> cprintf "'%s' " x) toks;*) (*cprintf "\n";*) let str_no_white = String.concat "" (String.split_on_char ' ' str) in assert_equal ~printer:(fun x -> x) str_no_white (String.concat "" toks); List.iter (fun s -> assert_equal ~msg:("'" ^ s ^ "' is a single token") ~printer:string_of_bool true (List.mem s toks)) [ "(*"; "()"; ":="] let _ = add_test "tokenize_string/diff_mode in lexer" t open Pp let write_diffs_option s = Goptions.set_string_option_value Proof_diffs.opt_name s (* example that was failing from #8922 *) let t () = write_diffs_option "removed"; ignore (diff_str "X : ?Goal" "X : forall x : ?Goal0, ?Goal1"); write_diffs_option "on" let _ = add_test "shorten_diff_span failure from #8922" t (* note pp_to_string concatenates adjacent strings, could become one token, e.g. str " a" ++ str "b " will give a token "ab" *) (* checks background is present and correct *) let t () = let o_pp = str "a" ++ str "!" ++ str "c" in let n_pp = str "a" ++ str "?" ++ str "c" in let (o_exp, n_exp) = (wrap_in_bg "diff.removed" (str "a" ++ (tag "diff.removed" (str "!")) ++ str "c"), wrap_in_bg "diff.added" (str "a" ++ (tag "diff.added" (str "?")) ++ str "c")) in let (o_diff, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"removed" ~printer:db_string_of_pp o_exp o_diff; assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp n_diff let _ = add_test "diff_pp/add_diff_tags add/remove" t let t () = (*Printf.printf "%s\n" (string_of_diffs (diff_str "a d" "a b c d"));*) let o_pp = str "a" ++ str " d" in let n_pp = str "a" ++ str " b " ++ str " c " ++ str "d" ++ str " e " in let n_exp = flatten (wrap_in_bg "diff.added" (seq [ str "a"; str " "; (tag "start.diff.added" (str "b ")); (tag "end.diff.added" (str " c")); str " "; (str "d"); str " "; (tag "diff.added" (str "e")); str " " ])) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags a span with spaces" t let t () = let o_pp = str " " in let n_pp = tag "sometag" (str "a") in let n_exp = flatten (wrap_in_bg "diff.added" (tag "diff.added" (tag "sometag" (str "a")))) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags diff tags outside existing tags" t let t () = let o_pp = str " " in let n_pp = seq [(tag "sometag" (str " a ")); str "b"] in let n_exp = flatten (wrap_in_bg "diff.added" (seq [tag "sometag" (str " "); (tag "start.diff.added" (tag "sometag" (str "a "))); (tag "end.diff.added" (str "b"))]) ) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags existing tagged values with spaces" t let t () = let o_pp = str " " in let n_pp = str " a b " in let n_exp = flatten (wrap_in_bg "diff.added" (seq [str " "; tag "diff.added" (str "a b"); str " "])) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags multiple tokens in pp" t let t () = let o_pp = str "a d" in let n_pp = seq [str "a b"; str "c d"] in let n_exp = flatten (wrap_in_bg "diff.added" (seq [str "a "; tag "start.diff.added" (str "b"); tag "end.diff.added" (str "c"); str " d"])) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags token spanning multiple Ppcmd_strs" t let t () = let o_pp = seq [str ""; str "a"] in let n_pp = seq [str ""; str "a b"] in let n_exp = flatten (wrap_in_bg "diff.added" (seq [str ""; str "a "; tag "diff.added" (str "b")])) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = add_test "diff_pp/add_diff_tags empty string preserved" t (* todo: awaiting a change in the lexer to return the quotes of the string token *) let t () = let s = "\"a b\"" in let o_pp = seq [str s] in let n_pp = seq [str "\"a b\" "] in cprintf "ppcmds: %s\n" (string_of_ppcmds n_pp); let n_exp = flatten (wrap_in_bg "diff.added" (seq [str ""; str "a "; tag "diff.added" (str "b")])) in let (_, n_diff) = diff_pp o_pp n_pp in assert_equal ~msg:"string" ~printer:string_of_string "a b" (List.hd (tokenize_string s)); assert_equal ~msg:"added" ~printer:db_string_of_pp n_exp (flatten n_diff) let _ = if false then add_test "diff_pp/add_diff_tags token containing white space" t let add_entries map idents rhs_pp = let make_entry() = { idents; rhs_pp } in List.iter (fun ident -> map := CString.Map.add ident (make_entry ()) !map) idents let print_list hyps = List.iter (fun x -> cprintf "%s\n" (string_of_ppcmds (flatten x))) hyps let db_print_list hyps = List.iter (fun x -> cprintf "%s\n" (db_string_of_pp (flatten x))) hyps (* a : uint b : int car -> b : car a : uint int DIFFS b : car (remove int) b : car (added bg only) a: uint int (add int) *) let t () = write_diffs_option "removed"; (* turn on "removed" option *) let o_line_idents = [ ["a"]; ["b"]] in let o_hyp_map = ref CString.Map.empty in add_entries o_hyp_map ["a"] (str " : uint"); add_entries o_hyp_map ["b"] (str " : int car"); let n_line_idents = [ ["b"]; ["a"]] in let n_hyp_map = ref CString.Map.empty in add_entries n_hyp_map ["b"] (str " : car"); add_entries n_hyp_map ["a"] (str " : uint int"); let expected = [flatten (wrap_in_bg "diff.removed" (seq [str "b"; str " : "; (tag "diff.removed" (str "int")); str " car" ])); flatten (wrap_in_bg "diff.added" (seq [str "b"; str " : car"])); flatten (wrap_in_bg "diff.added" (seq [str "a"; str " : uint "; (tag "diff.added" (str "int")) ])) ] in let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in (*print_list hyps_diff_list;*) (*db_print_list hyps_diff_list;*) List.iter2 (fun exp act -> assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act)) expected hyps_diff_list let _ = add_test "diff_hyps simple diffs" t (* a : nat c, d : int -> a, b : nat d : int DIFFS c, d : int (remove c,) a, b : nat (add ,b) d : int *) let t () = write_diffs_option "removed"; (* turn on "removed" option *) let o_line_idents = [ ["a"]; ["c"; "d"]] in let o_hyp_map = ref CString.Map.empty in add_entries o_hyp_map ["a"] (str " : nat"); add_entries o_hyp_map ["c"; "d"] (str " : int"); let n_line_idents = [ ["a"; "b"]; ["d"]] in let n_hyp_map = ref CString.Map.empty in add_entries n_hyp_map ["a"; "b"] (str " : nat"); add_entries n_hyp_map ["d"] (str " : int"); let expected = [flatten (wrap_in_bg "diff.added" (seq [str "a"; (tag "start.diff.added" (str ", ")); (tag "end.diff.added" (str "b")); str " : nat" ])); flatten (wrap_in_bg "diff.removed" (seq [(tag "start.diff.removed" (str "c")); (tag "end.diff.removed" (str ",")); str " "; str "d"; str " : int" ])); flatten (seq [str "d"; str " : int" ]) ] in let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in (*print_list hyps_diff_list;*) (*print_list expected;*) (*db_print_list hyps_diff_list;*) (*db_print_list expected;*) List.iter2 (fun exp act -> assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act)) expected hyps_diff_list let _ = add_test "diff_hyps compacted" t (* a : uint b : int c : nat -> b, a, c : nat DIFFS a : uint (remove) b : int (remove) b, a, c : nat (add b, a,) is this a realistic use case? *) let t () = write_diffs_option "removed"; (* turn on "removed" option *) let o_line_idents = [ ["a"]; ["b"]; ["c"]] in let o_hyp_map = ref CString.Map.empty in add_entries o_hyp_map ["a"] (str " : uint"); add_entries o_hyp_map ["b"] (str " : int"); add_entries o_hyp_map ["c"] (str " : nat"); let n_line_idents = [ ["b"; "a"; "c"] ] in let n_hyp_map = ref CString.Map.empty in add_entries n_hyp_map ["b"; "a"; "c"] (str " : nat"); let expected = [flatten (wrap_in_bg "diff.removed" (seq [str "a"; str " : "; (tag "diff.removed" (str "uint"))])); flatten (wrap_in_bg "diff.removed" (seq [str "b"; str " : "; (tag "diff.removed" (str "int"))])); flatten (wrap_in_bg "diff.added" (seq [(tag "start.diff.added" (str "b")); str ", "; str "a"; (tag "end.diff.added" (str ",")); str " "; str "c"; str " : nat"])) ] in let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in (*print_list hyps_diff_list;*) (*db_print_list hyps_diff_list;*) List.iter2 (fun exp act -> assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act)) expected hyps_diff_list let _ = add_test "diff_hyps compacted with join" t (* b, a, c : nat -> a : uint b : int c : nat DIFFS b, a, c : nat (remove b,a,) a : uint (add uint) b : int (add int) c : nat is this a realistic use case? *) let t () = write_diffs_option "removed"; (* turn on "removed" option *) let o_line_idents = [ ["b"; "a"; "c"] ] in let o_hyp_map = ref CString.Map.empty in add_entries o_hyp_map ["b"; "a"; "c"] (str " : nat"); let n_line_idents = [ ["a"]; ["b"]; ["c"]] in let n_hyp_map = ref CString.Map.empty in add_entries n_hyp_map ["a"] (str " : uint"); add_entries n_hyp_map ["b"] (str " : int"); add_entries n_hyp_map ["c"] (str " : nat"); let expected = [flatten (wrap_in_bg "diff.removed" (seq [(tag "start.diff.removed" (str "b")); str ", "; str "a"; (tag "end.diff.removed" (str ",")); str " "; str "c"; str " : nat"])); flatten (wrap_in_bg "diff.added" (seq [str "a"; str " : "; (tag "diff.added" (str "uint"))])); flatten (wrap_in_bg "diff.added" (seq [str "b"; str " : "; (tag "diff.added" (str "int"))])); flatten (seq [str "c"; str " : nat"]) ] in let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in (*print_list hyps_diff_list;*) (*db_print_list hyps_diff_list;*) List.iter2 (fun exp act -> assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act)) expected hyps_diff_list let _ = add_test "diff_hyps compacted with split" t (* i : nat b : bool j : nat -> i, j : nat DIFFS b : bool (removed) i, j : nat *) let t () = write_diffs_option "removed"; (* turn on "removed" option *) let o_line_idents = [ ["i"]; ["b"]; ["j"] ] in let o_hyp_map = ref CString.Map.empty in add_entries o_hyp_map ["i"] (str " : nat"); add_entries o_hyp_map ["b"] (str " : bool"); add_entries o_hyp_map ["j"] (str " : nat"); let n_line_idents = [ ["i"; "j"]] in let n_hyp_map = ref CString.Map.empty in add_entries n_hyp_map ["i"; "j"] (str " : nat"); let expected = [flatten (wrap_in_bg "diff.removed" (seq [tag "start.diff.removed" (str "b"); tag "end.diff.removed" (str " : bool")])); flatten (seq [str "i"; str ", "; str "j"; str " : nat"]) ] in let hyps_diff_list = diff_hyps o_line_idents !o_hyp_map n_line_idents !n_hyp_map in (* print_list hyps_diff_list; *) (* db_print_list hyps_diff_list; *) List.iter2 (fun exp act -> assert_equal ~msg:"added" ~printer:db_string_of_pp exp (flatten act)) expected hyps_diff_list let _ = add_test "diff_hyps removal causes compaction from #14577" t (* other potential tests coqtop/terminal formatting BLOCKED: CAN'T GET TAGS IN FORMATTER white space at end of line spanning diffs shorten_diff_span MAYBE NOT WORTH IT diff_pp/add_diff_tags add/remove - show it preserves, recurs and processes: nested in boxes breaks, etc. preserved diff_pp_combined with/without removed *) let _ = run_tests __FILE__ log_out_ch (List.rev !tests) rocq-9.2.0/test-suite/unit-tests/printing/proof_diffs_test_cases.v000066400000000000000000000016041516144147600254630ustar00rootroot00000000000000(* additional test cases for manual testing *) Goal 1 + 1 = 3 -> False -> True. intro. clear H; intro. Abort. Goal nat -> bool -> nat -> True. intros i b j. revert b. cbn. Abort. Require Import Corelib.Init.Number. Goal int -> uint -> nat -> nat -> nat -> nat ->True. intros a b c. clear a b c; intros b a c. Abort. Goal int -> nat -> uint -> nat -> nat -> nat -> True. intros a b c. clear a b c; intros c a b. Abort. Goal uint -> int -> nat -> nat -> nat -> nat -> True. intros a b c. clear a b c; intros b a c. Abort. Goal nat -> int -> int -> nat -> nat -> int -> True. intros a c d. clear a c d; intros a b d. Abort. Goal 1 = 0 -> True -> False -> True. intros X H. clear H; intro. Abort. Goal True -> True -> False -> False -> True. intros H H0. clear H H0; intros H H0. Abort. Goal True -> True -> False -> False -> False -> True. intros H H0. clear H H0; intros H H0 H1. Abort. rocq-9.2.0/test-suite/unit-tests/src/000077500000000000000000000000001516144147600175135ustar00rootroot00000000000000rocq-9.2.0/test-suite/unit-tests/src/utest.ml000066400000000000000000000044301516144147600212120ustar00rootroot00000000000000open OUnit (* general case to build a test *) let mk_test nm test = nm >: test (* common cases for building tests *) let mk_eq_test nm descr expected actual = mk_test nm (TestCase (fun _ -> assert_equal ~msg:descr expected actual)) let mk_bool_test nm descr actual = mk_test nm (TestCase (fun _ -> assert_bool descr actual)) let cfprintf oc = Printf.(kfprintf (fun oc -> fprintf oc "\n%!") oc) (* given test result, print message, return success boolean *) let logger out_ch result = let cprintf s = cfprintf out_ch s in match result with | RSuccess path -> cprintf "TEST SUCCEEDED: %s" (string_of_path path); true | RError (path,msg) | RFailure (path,msg) -> cprintf "TEST FAILED: %s (%s)" (string_of_path path) msg; false | RSkip (path,msg) | RTodo (path,msg) -> cprintf "TEST DID NOT SUCCEED: %s (%s)" (string_of_path path) msg; false (* run one OUnit test case, return successes, no. of tests *) (* notionally one test, which might be a TestList *) let run_one logit test = let rec process_results rs = match rs with [] -> (0,0) | (r::rest) -> let succ = if logit r then 1 else 0 in let succ_results,tot_results = process_results rest in (succ + succ_results,tot_results + 1) in let results = perform_test (fun _ -> ()) test in process_results results let open_log_out_ch ml_fn = let log_fn = ml_fn ^ ".log" in open_out log_fn (* run list of OUnit test cases, log results *) let run_tests ml_fn out_ch tests = let cprintf s = cfprintf out_ch s in let ceprintf s = cfprintf stderr s in let logit = logger out_ch in let rec run_some tests succ tot = match tests with [] -> (succ,tot) | (t::ts) -> let succ_one,tot_one = run_one logit t in run_some ts (succ + succ_one) (tot + tot_one) in (* format for test-suite summary to find status success if all tests succeeded, else failure *) let succ,tot = run_some tests 0 0 in cprintf "*** Ran %d tests, with %d successes and %d failures ***" tot succ (tot - succ); if succ = tot then cprintf "==========> SUCCESS <==========\n %s ... Ok" ml_fn else begin cprintf "==========> FAILURE <==========\n %s ... Error!" ml_fn; ceprintf "FAILED %s.log" ml_fn end; close_out out_ch rocq-9.2.0/test-suite/unit-tests/src/utest.mli000066400000000000000000000012171516144147600213630ustar00rootroot00000000000000(** give a name to a unit test *) val mk_test : string -> OUnit.test -> OUnit.test (** simple ways to build a test *) val mk_eq_test : string -> string -> 'a -> 'a -> OUnit.test val mk_bool_test : string -> string -> bool -> OUnit.test (** run unit tests *) (* the string argument should be the name of the .ml file containing the tests; use __FILE__ for that purpose. *) val run_tests : string -> out_channel -> OUnit.test list -> unit (** open output channel for the test log file *) (* the string argument should be the name of the .ml file containing the tests; use __FILE__ for that purpose. *) val open_log_out_ch : string -> out_channel rocq-9.2.0/theories/000077500000000000000000000000001516144147600143215ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/000077500000000000000000000000001516144147600157005ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Array/000077500000000000000000000000001516144147600167565ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Array/ArrayAxioms.v000066400000000000000000000024011516144147600214010ustar00rootroot00000000000000From Corelib Require Import PrimArray. Set Universe Polymorphism. Local Abbreviation in_bounds i t := (PrimInt63.ltb i (length t)). Axiom get_out_of_bounds@{u} : forall (A:Type@{u}) (t:array A) i, in_bounds i t = false -> t.[i] = default t. Axiom get_set_same@{u} : forall (A:Type@{u}) t i (a:A), in_bounds i t = true -> t.[i<-a].[i] = a. Axiom get_set_other@{u} : forall (A:Type@{u}) t i j (a:A), i <> j -> t.[i<-a].[j] = t.[j]. Axiom default_set@{u} : forall (A:Type@{u}) t i (a:A), default t.[i<-a] = default t. Axiom get_make@{u} : forall (A:Type@{u}) (a:A) size i, (make size a).[i] = a. Axiom leb_length@{u} : forall (A:Type@{u}) (t:array A), PrimInt63.leb (length t) max_length = true. Axiom length_make@{u} : forall (A:Type@{u}) size (a:A), length (make size a) = if PrimInt63.leb size max_length then size else max_length. Axiom length_set@{u} : forall (A:Type@{u}) t i (a:A), length t.[i<-a] = length t. Axiom get_copy@{u} : forall (A:Type@{u}) (t:array A) i, (copy t).[i] = t.[i]. Axiom length_copy@{u} : forall (A:Type@{u}) (t:array A), length (copy t) = length t. Axiom array_ext@{u} : forall (A:Type@{u}) (t1 t2:array A), length t1 = length t2 -> (forall i, in_bounds i t1 = true -> t1.[i] = t2.[i]) -> default t1 = default t2 -> t1 = t2. rocq-9.2.0/theories/Corelib/Array/PrimArray.v000066400000000000000000000024031516144147600210520ustar00rootroot00000000000000From Corelib Require Import PrimInt63. Set Universe Polymorphism. Primitive array := #array_type. Primitive make : forall A, int -> A -> array A := #array_make. Arguments make {_} _ _. Primitive get : forall A, array A -> int -> A := #array_get. Arguments get {_} _ _. Primitive default : forall A, array A -> A:= #array_default. Arguments default {_} _. Primitive set : forall A, array A -> int -> A -> array A := #array_set. Arguments set {_} _ _ _. Primitive length : forall A, array A -> int := #array_length. Arguments length {_} _. Primitive copy : forall A, array A -> array A := #array_copy. Arguments copy {_} _. Module Export PArrayNotations. Declare Scope array_scope. Delimit Scope array_scope with array. (* Temporary dummy notation to keep level 2 left associative as done by the old notations at level 2 (changed to level 1 in Rocq 9.2). *) #[warning="-postfix-notation-not-level-1"] Reserved Notation "x #####_dummy_PrimArray_notation_to_make_level_2_left_assoc#" (at level 2, left associativity). Notation "t .[ i ]" := (get t i) (at level 1, left associativity, format "t .[ i ]"). Notation "t .[ i <- a ]" := (set t i a) (at level 1, left associativity, format "t .[ i <- a ]"). End PArrayNotations. Primitive max_length := #array_max_length. rocq-9.2.0/theories/Corelib/BinNums/000077500000000000000000000000001516144147600172535ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/BinNums/IntDef.v000066400000000000000000000231661516144147600206230ustar00rootroot00000000000000From Corelib Require Import BinNums PosDef NatDef. Local Open Scope Z_scope. Local Notation "0" := Z0. Local Notation "1" := (Zpos 1). Local Notation "2" := (Zpos 2). (***********************************************************) (** * Binary Integers, Definitions of Operations *) (***********************************************************) (** Initial author: Pierre CrΓ©gut, CNET, Lannion, France *) Module Z. (** ** Doubling and variants *) Definition double x := match x with | 0 => 0 | Zpos p => Zpos p~0 | Zneg p => Zneg p~0 end. Definition succ_double x := match x with | 0 => 1 | Zpos p => Zpos p~1 | Zneg p => Zneg (Pos.pred_double p) end. Definition pred_double x := match x with | 0 => Zneg 1 | Zneg p => Zneg p~1 | Zpos p => Zpos (Pos.pred_double p) end. (** ** Subtraction of positive into Z *) Fixpoint pos_sub (x y:positive) {struct y} : Z := match x, y with | p~1, q~1 => double (pos_sub p q) | p~1, q~0 => succ_double (pos_sub p q) | p~1, xH => Zpos p~0 | p~0, q~1 => pred_double (pos_sub p q) | p~0, q~0 => double (pos_sub p q) | p~0, xH => Zpos (Pos.pred_double p) | xH, q~1 => Zneg q~0 | xH, q~0 => Zneg (Pos.pred_double q) | xH, xH => Z0 end%positive. (** ** Addition *) Definition add x y := match x, y with | 0, y => y | x, 0 => x | Zpos x', Zpos y' => Zpos (Pos.add x' y') | Zpos x', Zneg y' => pos_sub x' y' | Zneg x', Zpos y' => pos_sub y' x' | Zneg x', Zneg y' => Zneg (Pos.add x' y') end. Infix "+" := add : Z_scope. (** ** Opposite *) Definition opp x := match x with | 0 => 0 | Zpos x => Zneg x | Zneg x => Zpos x end. Notation "- x" := (opp x) : Z_scope. (** ** Subtraction *) Definition sub m n := m + -n. Infix "-" := sub : Z_scope. (** ** Multiplication *) Definition mul x y := match x, y with | 0, _ => 0 | _, 0 => 0 | Zpos x', Zpos y' => Zpos (Pos.mul x' y') | Zpos x', Zneg y' => Zneg (Pos.mul x' y') | Zneg x', Zpos y' => Zneg (Pos.mul x' y') | Zneg x', Zneg y' => Zpos (Pos.mul x' y') end. Infix "*" := mul : Z_scope. (** ** Power function *) Definition pow_pos (z:Z) := Pos.iter (mul z) 1. Definition pow x y := match y with | Zpos p => pow_pos x p | 0 => 1 | Zneg _ => 0 end. Infix "^" := pow : Z_scope. (** ** Comparison *) Definition compare x y := match x, y with | 0, 0 => Eq | 0, Zpos y' => Lt | 0, Zneg y' => Gt | Zpos x', 0 => Gt | Zpos x', Zpos y' => Pos.compare x' y' | Zpos x', Zneg y' => Gt | Zneg x', 0 => Lt | Zneg x', Zpos y' => Lt | Zneg x', Zneg y' => CompOpp (Pos.compare x' y') end. Infix "?=" := compare (at level 70, no associativity) : Z_scope. Definition lt x y := (x ?= y) = Lt. Definition gt x y := (x ?= y) = Gt. Definition le x y := (x ?= y) <> Gt. Definition ge x y := (x ?= y) <> Lt. Infix "<=" := le : Z_scope. Infix "<" := lt : Z_scope. Infix ">=" := ge : Z_scope. Infix ">" := gt : Z_scope. (** Boolean equality and comparisons *) Definition leb x y := match compare x y with | Gt => false | _ => true end. Definition ltb x y := match compare x y with | Lt => true | _ => false end. Definition eqb x y := match x, y with | 0, 0 => true | Zpos p, Zpos q => Pos.eqb p q | Zneg p, Zneg q => Pos.eqb p q | _, _ => false end. (** ** Minimum and maximum *) Definition max n m := match compare n m with | Eq | Gt => n | Lt => m end. Definition min n m := match compare n m with | Eq | Lt => n | Gt => m end. (** ** Conversions *) (** From [Z] to [nat] by rounding negative numbers to 0 *) Definition to_nat (z:Z) : nat := match z with | Zpos p => Pos.to_nat p | _ => O end. (** From [nat] to [Z] *) Definition of_nat (n:nat) : Z := match n with | O => 0 | S n => Zpos (Pos.of_succ_nat n) end. (** From [N] to [Z] *) Definition of_N (n:N) : Z := match n with | N0 => 0 | Npos p => Zpos p end. (** From [Z] to [positive] by rounding nonpositive numbers to 1 *) Definition to_pos (z:Z) : positive := match z with | Zpos p => p | _ => 1%positive end. (** ** Euclidean divisions for binary integers *) (** ** Floor division *) (** [div_eucl] provides a Truncated-Toward-Bottom (a.k.a Floor) Euclidean division. Its projections are named [div] (noted "/") and [modulo] (noted with an infix "mod"). These functions correspond to the `div` and `mod` of Haskell. This is the historical convention of Rocq. The main properties of this convention are : - we have [sgn (a mod b) = sgn (b)] - [div a b] is the greatest integer smaller or equal to the exact fraction [a/b]. - there is no easy sign rule. In addition, note that we take [a/0 = 0] and [a mod 0 = a]. This choice is motivated by the div-mod equation [a = (a / b) * b + (a mod b)] for [b = 0]. *) (** First, a division for positive numbers. Even if the second argument is a Z, the answer is arbitrary if it isn't a Zpos. *) Fixpoint pos_div_eucl (a:positive) (b:Z) : Z * Z := match a with | xH => if leb 2 b then (0, 1) else (1, 0) | xO a' => let (q, r) := pos_div_eucl a' b in let r' := 2 * r in if ltb r' b then (2 * q, r') else (2 * q + 1, r' - b) | xI a' => let (q, r) := pos_div_eucl a' b in let r' := 2 * r + 1 in if ltb r' b then (2 * q, r') else (2 * q + 1, r' - b) end. (** Then the general euclidean division *) Definition div_eucl (a b:Z) : Z * Z := match a, b with | 0, _ => (0, 0) | _, 0 => (0, a) | Zpos a', Zpos _ => pos_div_eucl a' b | Zneg a', Zpos _ => let (q, r) := pos_div_eucl a' b in match r with | 0 => (- q, 0) | _ => (- (q + 1), b - r) end | Zneg a', Zneg b' => let (q, r) := pos_div_eucl a' (Zpos b') in (q, - r) | Zpos a', Zneg b' => let (q, r) := pos_div_eucl a' (Zpos b') in match r with | 0 => (- q, 0) | _ => (- (q + 1), b + r) end end. Definition div (a b:Z) : Z := let (q, _) := div_eucl a b in q. Definition modulo (a b:Z) : Z := let (_, r) := div_eucl a b in r. (** ** Trunc Division *) (** [quotrem] provides a Truncated-Toward-Zero Euclidean division. Its projections are named [quot] (noted "Γ·") and [rem]. These functions correspond to the `quot` and `rem` of Haskell. This division convention is used in most programming languages, e.g. Ocaml. With this convention: - we have [sgn(a rem b) = sgn(a)] - sign rule for division: [quot (-a) b = quot a (-b) = -(quot a b)] - and for modulo: [a rem (-b) = a rem b] and [(-a) rem b = -(a rem b)] Note that we take here [quot a 0 = 0] and [a rem 0 = a]. This choice is motivated by the quot-rem equation [a = (quot a b) * b + (a rem b)] for [b = 0]. *) Definition quotrem (a b:Z) : Z * Z := match a, b with | 0, _ => (0, 0) | _, 0 => (0, a) | Zpos a, Zpos b => let (q, r) := N.pos_div_eucl a (Npos b) in (of_N q, of_N r) | Zneg a, Zpos b => let (q, r) := N.pos_div_eucl a (Npos b) in (-of_N q, - of_N r) | Zpos a, Zneg b => let (q, r) := N.pos_div_eucl a (Npos b) in (-of_N q, of_N r) | Zneg a, Zneg b => let (q, r) := N.pos_div_eucl a (Npos b) in (of_N q, - of_N r) end. Definition quot a b := fst (quotrem a b). Definition rem a b := snd (quotrem a b). Infix "Γ·" := quot (at level 40, left associativity) : Z_scope. (** No infix notation for rem, otherwise it becomes a keyword *) (** ** Parity functions *) Definition even z := match z with | 0 => true | Zpos (xO _) => true | Zneg (xO _) => true | _ => false end. (** ** Division by two *) (** [div2] performs rounding toward bottom, it is hence a particular case of [div], and for all relative number [n] we have: [n = 2 * div2 n + if odd n then 1 else 0]. *) Definition div2 z := match z with | 0 => 0 | Zpos 1 => 0 | Zpos p => Zpos (Pos.div2 p) | Zneg p => Zneg (Pos.div2_up p) end. (** ** Square root *) Definition sqrtrem n := match n with | 0 => (0, 0) | Zpos p => match Pos.sqrtrem p with | (s, Pos.IsPos r) => (Zpos s, Zpos r) | (s, _) => (Zpos s, 0) end | Zneg _ => (0,0) end. (** Shifts Nota: a shift to the right by [-n] will be a shift to the left by [n], and vice-versa. For fulfilling the two's complement convention, shifting to the right a negative number should correspond to a division by 2 with rounding toward bottom, hence the use of [div2] instead of [quot2]. *) Definition shiftl a n := match n with | 0 => a | Zpos p => Pos.iter (mul 2) a p | Zneg p => Pos.iter div2 a p end. Definition shiftr a n := shiftl a (-n). (** Bitwise operations [lor] [land] [ldiff] [lxor] *) Definition lor a b := match a, b with | 0, _ => b | _, 0 => a | Zpos a, Zpos b => Zpos (Pos.lor a b) | Zneg a, Zpos b => Zneg (N.succ_pos (N.ldiff (Pos.pred_N a) (Npos b))) | Zpos a, Zneg b => Zneg (N.succ_pos (N.ldiff (Pos.pred_N b) (Npos a))) | Zneg a, Zneg b => Zneg (N.succ_pos (N.land (Pos.pred_N a) (Pos.pred_N b))) end. Definition land a b := match a, b with | 0, _ => 0 | _, 0 => 0 | Zpos a, Zpos b => of_N (Pos.land a b) | Zneg a, Zpos b => of_N (N.ldiff (Npos b) (Pos.pred_N a)) | Zpos a, Zneg b => of_N (N.ldiff (Npos a) (Pos.pred_N b)) | Zneg a, Zneg b => Zneg (N.succ_pos (N.lor (Pos.pred_N a) (Pos.pred_N b))) end. Definition lxor a b := match a, b with | 0, _ => b | _, 0 => a | Zpos a, Zpos b => of_N (Pos.lxor a b) | Zneg a, Zpos b => Zneg (N.succ_pos (N.lxor (Pos.pred_N a) (Npos b))) | Zpos a, Zneg b => Zneg (N.succ_pos (N.lxor (Npos a) (Pos.pred_N b))) | Zneg a, Zneg b => of_N (N.lxor (Pos.pred_N a) (Pos.pred_N b)) end. End Z. rocq-9.2.0/theories/Corelib/BinNums/NatDef.v000066400000000000000000000055631516144147600206140ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 2*x+1] *) Definition succ_double x := match x with | N0 => Npos 1 | Npos p => Npos p~1 end. (** ** Operation [x -> 2*x] *) Definition double n := match n with | N0 => N0 | Npos p => Npos p~0 end. (** ** The successor of a [N] can be seen as a [positive] *) Definition succ_pos (n : N) : positive := match n with | N0 => xH | Npos p => Pos.succ p end. (** Subtraction *) Definition sub n m := match n, m with | N0, _ => N0 | n, N0 => n | Npos n', Npos m' => match Pos.sub_mask n' m' with | Pos.IsPos p => Npos p | _ => N0 end end. (** Order *) Definition compare n m := match n, m with | N0, N0 => Eq | N0, Npos m' => Lt | Npos n', N0 => Gt | Npos n', Npos m' => Pos.compare n' m' end. (** Boolean equality and comparison *) Definition leb x y := match compare x y with Gt => false | _ => true end. (** Euclidean division *) Fixpoint pos_div_eucl (a:positive)(b:N) : N * N := match a with | xH => match b with Npos 1 => (Npos 1, N0) | _ => (N0, Npos 1) end | xO a' => let (q, r) := pos_div_eucl a' b in let r' := double r in if leb b r' then (succ_double q, sub r' b) else (double q, r') | xI a' => let (q, r) := pos_div_eucl a' b in let r' := succ_double r in if leb b r' then (succ_double q, sub r' b) else (double q, r') end. (** Operation over bits of a [N] number. *) (** Logical [or] *) Definition lor n m := match n, m with | N0, _ => m | _, N0 => n | Npos p, Npos q => Npos (Pos.lor p q) end. (** Logical [and] *) Definition land n m := match n, m with | N0, _ => N0 | _, N0 => N0 | Npos p, Npos q => Pos.land p q end. (** Logical [diff] *) Definition ldiff n m := match n, m with | N0, _ => N0 | _, N0 => n | Npos p, Npos q => Pos.ldiff p q end. (** [xor] *) Definition lxor n m := match n, m with | N0, _ => m | _, N0 => n | Npos p, Npos q => Pos.lxor p q end. End N. rocq-9.2.0/theories/Corelib/BinNums/PosDef.v000066400000000000000000000213031516144147600206210ustar00rootroot00000000000000(* -*- coding: utf-8 -*- *) (************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (succ p)~0 | p~0 => p~1 | 1 => 1~0 end. (** ** Addition *) Fixpoint add x y := match x, y with | p~1, q~1 => (add_carry p q)~0 | p~1, q~0 => (add p q)~1 | p~1, 1 => (succ p)~0 | p~0, q~1 => (add p q)~1 | p~0, q~0 => (add p q)~0 | p~0, 1 => p~1 | 1, q~1 => (succ q)~0 | 1, q~0 => q~1 | 1, 1 => 1~0 end with add_carry x y := match x, y with | p~1, q~1 => (add_carry p q)~1 | p~1, q~0 => (add_carry p q)~0 | p~1, 1 => (succ p)~1 | p~0, q~1 => (add_carry p q)~0 | p~0, q~0 => (add p q)~1 | p~0, 1 => (succ p)~0 | 1, q~1 => (succ q)~1 | 1, q~0 => (succ q)~0 | 1, 1 => 1~1 end. (** ** Operation [x -> 2*x-1] *) Fixpoint pred_double x := match x with | p~1 => p~0~1 | p~0 => (pred_double p)~1 | 1 => 1 end. (** ** The predecessor of a positive number can be seen as a [N] *) Definition pred_N x := match x with | p~1 => Npos (p~0) | p~0 => Npos (pred_double p) | 1 => N0 end. (** ** An auxiliary type for subtraction *) Inductive mask : Set := | IsNul : mask | IsPos : positive -> mask | IsNeg : mask. (** ** Operation [x -> 2*x+1] *) Definition succ_double_mask (x:mask) : mask := match x with | IsNul => IsPos 1 | IsNeg => IsNeg | IsPos p => IsPos p~1 end. (** ** Operation [x -> 2*x] *) Definition double_mask (x:mask) : mask := match x with | IsNul => IsNul | IsNeg => IsNeg | IsPos p => IsPos p~0 end. (** ** Operation [x -> 2*x-2] *) Definition double_pred_mask x : mask := match x with | p~1 => IsPos p~0~0 | p~0 => IsPos (pred_double p)~0 | 1 => IsNul end. (** ** Subtraction, result as a mask *) Fixpoint sub_mask (x y:positive) {struct y} : mask := match x, y with | p~1, q~1 => double_mask (sub_mask p q) | p~1, q~0 => succ_double_mask (sub_mask p q) | p~1, 1 => IsPos p~0 | p~0, q~1 => succ_double_mask (sub_mask_carry p q) | p~0, q~0 => double_mask (sub_mask p q) | p~0, 1 => IsPos (pred_double p) | 1, 1 => IsNul | 1, _ => IsNeg end with sub_mask_carry (x y:positive) {struct y} : mask := match x, y with | p~1, q~1 => succ_double_mask (sub_mask_carry p q) | p~1, q~0 => double_mask (sub_mask p q) | p~1, 1 => IsPos (pred_double p) | p~0, q~1 => double_mask (sub_mask_carry p q) | p~0, q~0 => succ_double_mask (sub_mask_carry p q) | p~0, 1 => double_pred_mask p | 1, _ => IsNeg end. (** ** Subtraction, result as a positive, returning 1 if [x<=y] *) Definition sub x y := match sub_mask x y with | IsPos z => z | _ => 1 end. (** ** Multiplication *) Fixpoint mul x y := match x with | p~1 => add y (mul p y)~0 | p~0 => (mul p y)~0 | 1 => y end. (** ** Iteration over a positive number *) Definition iter {A} (f:A -> A) : A -> positive -> A := fix iter_fix x n := match n with | xH => f x | xO n' => iter_fix (iter_fix x n') n' | xI n' => f (iter_fix (iter_fix x n') n') end. (** ** Division by 2 rounded below but for 1 *) Definition div2 p := match p with | 1 => 1 | p~0 => p | p~1 => p end. (** Division by 2 rounded up *) Definition div2_up p := match p with | 1 => 1 | p~0 => p | p~1 => succ p end. (** ** Comparison on binary positive numbers *) Fixpoint compare_cont (r:comparison) (x y:positive) {struct y} : comparison := match x, y with | p~1, q~1 => compare_cont r p q | p~1, q~0 => compare_cont Gt p q | p~1, 1 => Gt | p~0, q~1 => compare_cont Lt p q | p~0, q~0 => compare_cont r p q | p~0, 1 => Gt | 1, q~1 => Lt | 1, q~0 => Lt | 1, 1 => r end. Definition compare := compare_cont Eq. (** ** Boolean equality and comparisons *) Fixpoint eqb p q {struct q} := match p, q with | p~1, q~1 => eqb p q | p~0, q~0 => eqb p q | 1, 1 => true | _, _ => false end. Definition leb x y := match compare x y with Gt => false | _ => true end. (** ** A Square Root function for positive numbers *) (** We proceed by blocks of two digits : if p is written qbb' then sqrt(p) will be sqrt(q)~0 or sqrt(q)~1. For deciding easily in which case we are, we store the remainder (as a mask, since it can be null). Instead of copy-pasting the following code four times, we factorize as an auxiliary function, with f and g being either xO or xI depending of the initial digits. NB: (sub_mask (g (f 1)) 4) is a hack, morally it's g (f 0). *) Definition sqrtrem_step (f g:positive->positive) p := match p with | (s, IsPos r) => let s' := s~0~1 in let r' := g (f r) in if leb s' r' then (s~1, sub_mask r' s') else (s~0, IsPos r') | (s,_) => (s~0, sub_mask (g (f 1)) 1~0~0) end. Fixpoint sqrtrem p : positive * mask := match p with | 1 => (1,IsNul) | 1~0 => (1,IsPos 1) | 1~1 => (1,IsPos 1~0) | p~0~0 => sqrtrem_step xO xO (sqrtrem p) | p~0~1 => sqrtrem_step xO xI (sqrtrem p) | p~1~0 => sqrtrem_step xI xO (sqrtrem p) | p~1~1 => sqrtrem_step xI xI (sqrtrem p) end. Definition sqrt p := fst (sqrtrem p). Definition Nsucc_double x := match x with | N0 => Npos 1 | Npos p => Npos p~1 end. Definition Ndouble n := match n with | N0 => N0 | Npos p => Npos p~0 end. (** Operation over bits. *) (** Logical [or] *) Fixpoint lor (p q : positive) : positive := match p, q with | 1, q~0 => q~1 | 1, _ => q | p~0, 1 => p~1 | _, 1 => p | p~0, q~0 => (lor p q)~0 | p~0, q~1 => (lor p q)~1 | p~1, q~0 => (lor p q)~1 | p~1, q~1 => (lor p q)~1 end. (** Logical [and] *) Fixpoint land (p q : positive) : N := match p, q with | 1, q~0 => N0 | 1, _ => Npos 1 | p~0, 1 => N0 | _, 1 => Npos 1 | p~0, q~0 => Ndouble (land p q) | p~0, q~1 => Ndouble (land p q) | p~1, q~0 => Ndouble (land p q) | p~1, q~1 => Nsucc_double (land p q) end. (** Logical [diff] *) Fixpoint ldiff (p q:positive) : N := match p, q with | 1, q~0 => Npos 1 | 1, _ => N0 | _~0, 1 => Npos p | p~1, 1 => Npos (p~0) | p~0, q~0 => Ndouble (ldiff p q) | p~0, q~1 => Ndouble (ldiff p q) | p~1, q~1 => Ndouble (ldiff p q) | p~1, q~0 => Nsucc_double (ldiff p q) end. (** [xor] *) Fixpoint lxor (p q:positive) : N := match p, q with | 1, 1 => N0 | 1, q~0 => Npos (q~1) | 1, q~1 => Npos (q~0) | p~0, 1 => Npos (p~1) | p~0, q~0 => Ndouble (lxor p q) | p~0, q~1 => Nsucc_double (lxor p q) | p~1, 1 => Npos (p~0) | p~1, q~0 => Nsucc_double (lxor p q) | p~1, q~1 => Ndouble (lxor p q) end. (** ** From binary positive numbers to Peano natural numbers *) Definition iter_op {A}(op:A->A->A) := fix iter (p:positive)(a:A) : A := match p with | 1 => a | p~0 => iter p (op a a) | p~1 => op a (iter p (op a a)) end. Definition to_nat (x:positive) : nat := iter_op plus x (S O). Arguments to_nat x: simpl never. (** ** From Peano natural numbers to binary positive numbers *) (* A version that converts [n] into [n+1] *) Fixpoint of_succ_nat (n:nat) : positive := match n with | O => 1 | S x => succ (of_succ_nat x) end. End Pos. rocq-9.2.0/theories/Corelib/Classes/000077500000000000000000000000001516144147600172755ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Classes/CMorphisms.v000066400000000000000000000566521516144147600215660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* B) _ _] goal, making proof-search much slower. A cleaner solution would be to be able to set different priorities in different hint bases and select a particular hint database for resolution of a type class constraint. *) Class ProperProxy (R : crelation A) (m : A) := proper_proxy : R m m. Lemma eq_proper_proxy (x : A) : ProperProxy (@eq A) x. Proof. firstorder. Qed. Lemma reflexive_proper_proxy `(Reflexive A R) (x : A) : ProperProxy R x. Proof. firstorder. Qed. Lemma proper_proper_proxy x `(Proper R x) : ProperProxy R x. Proof. firstorder. Qed. (** Respectful morphisms. *) (** The fully dependent version, not used yet. *) Definition respectful_hetero (A B : Type) (C : A -> Type) (D : B -> Type) (R : A -> B -> Type) (R' : forall (x : A) (y : B), C x -> D y -> Type) : (forall x : A, C x) -> (forall x : B, D x) -> Type := fun f g => forall x y, R x y -> R' x y (f x) (g y). (** The non-dependent version is an instance where we forget dependencies. *) Definition respectful {B} (R : crelation A) (R' : crelation B) : crelation (A -> B) := Eval compute in @respectful_hetero A A (fun _ => B) (fun _ => B) R (fun _ _ => R'). End Proper. (** We favor the use of Leibniz equality or a declared reflexive crelation when resolving [ProperProxy], otherwise, if the crelation is given (not an evar), we fall back to [Proper]. *) #[global] Hint Extern 1 (ProperProxy _ _) => class_apply @eq_proper_proxy || class_apply @reflexive_proper_proxy : typeclass_instances. #[global] Hint Extern 2 (ProperProxy ?R _) => not_evar R; class_apply @proper_proper_proxy : typeclass_instances. (** Notations reminiscent of the old syntax for declaring morphisms. *) Declare Scope signatureT_scope. Delimit Scope signatureT_scope with signatureT. Module ProperNotations. Notation " R ++> R' " := (@respectful _ _ (R%signatureT) (R'%signatureT)) (right associativity, at level 55) : signatureT_scope. Notation " R ==> R' " := (@respectful _ _ (R%signatureT) (R'%signatureT)) (right associativity, at level 55) : signatureT_scope. Notation " R --> R' " := (@respectful _ _ (flip (R%signatureT)) (R'%signatureT)) (right associativity, at level 55) : signatureT_scope. End ProperNotations. Arguments Proper {A}%_type R%_signatureT m. Arguments respectful {A B}%_type (R R')%_signatureT _ _. Export ProperNotations. Local Open Scope signatureT_scope. (** [solve_proper] try to solve the goal [Proper (?==> ... ==>?) f] by repeated introductions and setoid rewrites. It should work fine when [f] is a combination of already known morphisms and quantifiers. *) Ltac solve_respectful t := match goal with | |- respectful _ _ _ _ => let H := fresh "H" in intros ? ? H; solve_respectful ltac:(setoid_rewrite H; t) | _ => t; reflexivity end. Ltac solve_proper := unfold Proper; solve_respectful ltac:(idtac). (** [f_equiv] is a clone of [f_equal] that handles setoid equivalences. For example, if we know that [f] is a morphism for [E1==>E2==>E], then the goal [E (f x y) (f x' y')] will be transformed by [f_equiv] into the subgoals [E1 x x'] and [E2 y y']. *) Ltac f_equiv := match goal with | |- ?R (?f ?x) (?f' _) => let T := type of x in let Rx := fresh "R" in evar (Rx : crelation T); let H := fresh in assert (H : (Rx==>R)%signatureT f f'); unfold Rx in *; clear Rx; [ f_equiv | apply H; clear H; try reflexivity ] | |- ?R ?f ?f' => solve [change (Proper R f); eauto with typeclass_instances | reflexivity ] | _ => idtac end. Section Relations. Context {A : Type}. (** [forall_def] reifies the dependent product as a definition. *) Definition forall_def (P : A -> Type) : Type := forall x : A, P x. (** Dependent pointwise lifting of a crelation on the range. *) Definition forall_relation (P : A -> Type) (sig : forall a, crelation (P a)) : crelation (forall x, P x) := fun f g => forall a, sig a (f a) (g a). (** Non-dependent pointwise lifting *) Definition pointwise_relation {B} (R : crelation B) : crelation (A -> B) := fun f g => forall a, R (f a) (g a). Lemma pointwise_pointwise {B} (R : crelation B) : relation_equivalence (pointwise_relation R) (@eq A ==> R). Proof. intros. split. - simpl_crelation. - firstorder. Qed. (** Subcrelations induce a morphism on the identity. *) Global Instance subrelation_id_proper `(subrelation A RA RA') : Proper (RA ==> RA') id. Proof. firstorder. Qed. (** The subrelation property goes through products as usual. *) Lemma subrelation_respectful `(subl : subrelation A RA' RA, subr : subrelation B RB RB') : subrelation (RA ==> RB) (RA' ==> RB'). Proof. simpl_crelation. Qed. (** And of course it is reflexive. *) Lemma subrelation_refl R : @subrelation A R R. Proof. simpl_crelation. Qed. (** [Proper] is itself a covariant morphism for [subrelation]. We use an unconvertible premise to avoid looping. *) Lemma subrelation_proper `(mor : Proper A R' m) `(unc : Unconvertible (crelation A) R R') `(sub : subrelation A R' R) : Proper R m. Proof. intros. apply sub. apply mor. Qed. Global Instance proper_subrelation_proper_arrow : Proper (subrelation ++> eq ==> arrow) (@Proper A). Proof. reduce. subst. firstorder. Qed. Global Instance pointwise_subrelation `(sub : subrelation B R R') : subrelation (pointwise_relation R) (pointwise_relation R') | 4. Proof. reduce. unfold pointwise_relation in *. apply sub. auto. Qed. (** For dependent function types. *) Lemma forall_subrelation (P : A -> Type) (R S : forall x : A, crelation (P x)) : (forall a, subrelation (R a) (S a)) -> subrelation (forall_relation P R) (forall_relation P S). Proof. reduce. firstorder. Qed. End Relations. Global Typeclasses Opaque respectful pointwise_relation forall_relation. Arguments forall_relation {A P}%_type sig%_signatureT _ _. Arguments pointwise_relation A%_type {B}%_type R%_signatureT _ _. #[global] Hint Unfold Reflexive : core. #[global] Hint Unfold Symmetric : core. #[global] Hint Unfold Transitive : core. (** Resolution with subrelation: favor decomposing products over applying reflexivity for unconstrained goals. *) Ltac subrelation_tac T U := (is_ground T ; is_ground U ; class_apply @subrelation_refl) || class_apply @subrelation_respectful || class_apply @subrelation_refl. #[global] Hint Extern 3 (@subrelation _ ?T ?U) => subrelation_tac T U : typeclass_instances. CoInductive apply_subrelation : Prop := do_subrelation. Ltac proper_subrelation := match goal with [ H : apply_subrelation |- _ ] => clear H ; class_apply @subrelation_proper end. #[global] Hint Extern 5 (@Proper _ ?H _) => proper_subrelation : typeclass_instances. (** Essential subrelation instances for [iff], [impl] and [pointwise_relation]. *) #[global] Instance iff_impl_subrelation : subrelation iff impl | 2. Proof. firstorder. Qed. #[global] Instance iff_flip_impl_subrelation : subrelation iff (flip impl) | 2. Proof. firstorder. Qed. (** Essential subrelation instances for [iffT] and [arrow]. *) #[global] Instance iffT_arrow_subrelation : subrelation iffT arrow | 2. Proof. firstorder. Qed. #[global] Instance iffT_flip_arrow_subrelation : subrelation iffT (flip arrow) | 2. Proof. firstorder. Qed. (** We use an extern hint to help unification. *) #[global] Hint Extern 4 (subrelation (@forall_relation ?A ?B ?R) (@forall_relation _ _ ?S)) => apply (@forall_subrelation A B R S) ; intro : typeclass_instances. Section GenericInstances. (* Share universes *) Implicit Types A B C : Type. (** We can build a PER on the Rocq function space if we have PERs on the domain and codomain. *) Program Instance respectful_per `(PER A R, PER B R') : PER (R ==> R'). Next Obligation. Proof. intros A R H B R' H0 x y z X X0 x0 y0 X1. assert(R x0 x0). - eapply transitivity with y0; auto. now apply symmetry. - eapply transitivity with (y x0); auto. Qed. Unset Strict Universe Declaration. (** The complement of a crelation conserves its proper elements. *) (** The [flip] too, actually the [flip] instance is a bit more general. *) Program Definition flip_proper `(mor : Proper (A -> B -> C) (RA ==> RB ==> RC) f) : Proper (RB ==> RA ==> RC) (flip f) := _. Next Obligation. Proof. intros A B C RA RB RC f mor x y X x0 y0 X0. apply mor ; auto. Qed. (** Every Transitive crelation gives rise to a binary morphism on [impl], contravariant in the first argument, covariant in the second. *) Global Program Instance trans_contra_co_type_morphism `(Transitive A R) : Proper (R --> R ++> arrow) R. Next Obligation. Proof. intros A R H x y X x0 y0 X0 X1. apply transitivity with x; auto. apply transitivity with x0; auto. Qed. (** Proper declarations for partial applications. *) Global Program Instance trans_contra_inv_impl_type_morphism `(Transitive A R) {x} : Proper (R --> flip arrow) (R x) | 3. Next Obligation. Proof. intros A R H x x0 y X X0. apply transitivity with y; auto. Qed. Global Program Instance trans_co_impl_type_morphism `(Transitive A R) {x} : Proper (R ++> arrow) (R x) | 3. Next Obligation. Proof. intros A R H x x0 y X X0. apply transitivity with x0; auto. Qed. Global Program Instance trans_sym_co_inv_impl_type_morphism `(PER A R) {x} : Proper (R ++> flip arrow) (R x) | 3. Next Obligation. Proof. intros A R H x x0 y X X0. apply transitivity with y; auto. apply symmetry; auto. Qed. Global Program Instance trans_sym_contra_arrow_morphism `(PER A R) {x} : Proper (R --> arrow) (R x) | 3. Next Obligation. Proof. intros A R H x x0 y X X0. apply transitivity with x0; auto. apply symmetry; auto. Qed. Global Program Instance per_partial_app_type_morphism `(PER A R) {x} : Proper (R ==> iffT) (R x) | 2. Next Obligation. Proof. intros A R H x x0 y X. split. - intros ; apply transitivity with x0; auto. - intros. apply transitivity with y; auto. apply symmetry; auto. 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. *) Global Program Instance trans_co_eq_inv_arrow_morphism `(Transitive A R) : Proper (R ==> (@eq A) ==> flip arrow) R | 2. Next Obligation. Proof. intros A R H x y X y0 y1 e X0; destruct e. apply transitivity with y; auto. Qed. (** Every Symmetric and Transitive crelation gives rise to an equivariant morphism. *) Global Program Instance PER_type_morphism `(PER A R) : Proper (R ==> R ==> iffT) R | 1. Next Obligation. Proof. intros A R H x y X x0 y0 X0. split ; intros. - apply transitivity with x0; auto. apply transitivity with x; auto. apply symmetry; auto. - apply transitivity with y; auto. apply transitivity with y0; auto. apply symmetry; auto. Qed. Lemma symmetric_equiv_flip `(Symmetric A R) : relation_equivalence R (flip R). Proof. firstorder. Qed. Global Program Instance compose_proper A B C RA RB RC : Proper ((RB ==> RC) ==> (RA ==> RB) ==> (RA ==> RC)) (@compose A B C). Next Obligation. Proof. simpl_crelation. unfold compose. firstorder. Qed. (** Rocq functions are morphisms for Leibniz equality, applied only if really needed. *) Global Instance reflexive_eq_dom_reflexive `(Reflexive B R') {A} : Reflexive (@Logic.eq A ==> R'). Proof. simpl_crelation. Qed. (** [respectful] is a morphism for crelation equivalence . *) Global Instance respectful_morphism {A B} : Proper (relation_equivalence ++> relation_equivalence ++> relation_equivalence) (@respectful A B). Proof. intros 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' _ _)). Qed. (** [R] is Reflexive, hence we can build the needed proof. *) Lemma Reflexive_partial_app_morphism `(Proper (A -> B) (R ==> R') m, ProperProxy A R x) : Proper R' (m x). Proof. simpl_crelation. Qed. Class Params {A} (of : A) (arity : nat). Lemma flip_respectful {A B} (R : crelation A) (R' : crelation B) : relation_equivalence (flip (R ==> R')) (flip R ==> flip R'). Proof. intros. unfold flip, respectful. split ; intros ; intuition. Qed. (** Treating flip: can't make them direct instances as we need at least a [flip] present in the goal. *) Lemma flip1 `(subrelation A R' R) : subrelation (flip (flip R')) R. Proof. firstorder. Qed. Lemma flip2 `(subrelation A R R') : subrelation R (flip (flip R')). Proof. firstorder. Qed. (** That's if and only if *) Lemma eq_subrelation `(Reflexive A R) : subrelation (@eq A) R. Proof. simpl_crelation. Qed. (** Once we have normalized, we will apply this instance to simplify the problem. *) Definition proper_flip_proper `(mor : Proper A R m) : Proper (flip R) m := mor. (** Every reflexive crelation gives rise to a morphism, only for immediately solving goals without variables. *) Lemma reflexive_proper `{Reflexive A R} (x : A) : Proper R x. Proof. firstorder. Qed. Lemma proper_eq {A} (x : A) : Proper (@eq A) x. Proof. intros. apply reflexive_proper. Qed. End GenericInstances. Class PartialApplication. CoInductive normalization_done : Prop := did_normalization. Ltac partial_application_tactic := let rec do_partial_apps H m cont := match m with | ?m' ?x => class_apply @Reflexive_partial_app_morphism ; [(do_partial_apps H m' ltac:(idtac))|clear H] | _ => cont end in let rec do_partial H ar m := lazymatch ar with | 0%nat => do_partial_apps H m ltac:(fail 1) | S ?n' => match m with ?m' ?x => do_partial H n' m' end end in let params m sk fk := (let m' := fresh in Ltac.Internal.head_of_constr m' m ; let n := fresh in evar (n:nat) ; let v := eval compute in n in clear n ; let H := fresh in assert(H:Params m' v) by (subst m'; once typeclasses eauto) ; let v' := eval compute in v in subst m'; (sk H v' || fail 1)) || fk in let on_morphism m cont := params m ltac:(fun H n => do_partial H n m) ltac:(cont) in match goal with | [ _ : normalization_done |- _ ] => fail 1 | [ _ : @Params _ _ _ |- _ ] => fail 1 | [ |- @Proper ?T _ (?m ?x) ] => match goal with | [ H : PartialApplication |- _ ] => class_apply @Reflexive_partial_app_morphism; [|clear H] | _ => on_morphism (m x) ltac:(class_apply @Reflexive_partial_app_morphism) end end. (** Bootstrap !!! *) #[global] Instance proper_proper {A} : Proper (relation_equivalence ==> eq ==> iffT) (@Proper A). Proof. intros R R' HRR' x y <-. red in HRR'. split ; red ; intros. - now apply (fst (HRR' _ _)). - now apply (snd (HRR' _ _)). Qed. Ltac proper_reflexive := match goal with | [ _ : normalization_done |- _ ] => fail 1 | _ => class_apply proper_eq || class_apply @reflexive_proper end. #[global] Hint Extern 1 (subrelation (flip _) _) => class_apply @flip1 : typeclass_instances. #[global] Hint Extern 1 (subrelation _ (flip _)) => class_apply @flip2 : typeclass_instances. (* Hint Extern 1 (Proper _ (complement _)) => apply @complement_proper *) (* : typeclass_instances. *) #[global] Hint Extern 1 (Proper _ (flip _)) => apply @flip_proper : typeclass_instances. #[global] Hint Extern 2 (@Proper _ (flip _) _) => class_apply @proper_flip_proper : typeclass_instances. #[global] Hint Extern 4 (@Proper _ _ _) => partial_application_tactic : typeclass_instances. #[global] Hint Extern 7 (@Proper _ _ _) => proper_reflexive : typeclass_instances. (** Special-purpose class to do normalization of signatures w.r.t. flip. *) Section Normalize. Context (A : Type). Class Normalizes (m : crelation A) (m' : crelation A) := normalizes : relation_equivalence m m'. (** Current strategy: add [flip] everywhere and reduce using [subrelation] afterwards. *) Lemma proper_normalizes_proper `(Normalizes R0 R1, Proper A R1 m) : Proper R0 m. Proof. apply (_ : Normalizes R0 R1). assumption. Qed. Lemma flip_atom R : Normalizes R (flip (flip R)). Proof. firstorder. Qed. End Normalize. Lemma flip_arrow `(NA : Normalizes A R (flip R'''), NB : Normalizes B R' (flip R'')) : Normalizes (A -> B) (R ==> R') (flip (R''' ==> R'')%signatureT). Proof. unfold Normalizes in *. intros. eapply transitivity; [|eapply symmetry, flip_respectful]. now apply respectful_morphism. Qed. Ltac normalizes := match goal with | [ |- Normalizes _ (respectful _ _) _ ] => class_apply @flip_arrow | _ => class_apply @flip_atom end. Ltac proper_normalization := match goal with | [ _ : normalization_done |- _ ] => fail 1 | [ _ : apply_subrelation |- @Proper _ ?R _ ] => let H := fresh "H" in set(H:=did_normalization) ; class_apply @proper_normalizes_proper end. #[global] Hint Extern 1 (Normalizes _ _ _) => normalizes : typeclass_instances. #[global] Hint Extern 6 (@Proper _ _ _) => proper_normalization : typeclass_instances. (** When the crelation on the domain is symmetric, we can flip the crelation on the codomain. Same for binary functions. *) Lemma proper_sym_flip : forall `(Symmetric A R1)`(Proper (A->B) (R1==>R2) f), Proper (R1==>flip R2) f. Proof. intros A R1 Sym B R2 f Hf. intros x x' Hxx'. apply Hf, Sym, Hxx'. Qed. Lemma proper_sym_flip_2 : forall `(Symmetric A R1)`(Symmetric B R2)`(Proper (A->B->C) (R1==>R2==>R3) f), Proper (R1==>R2==>flip R3) f. Proof. intros A R1 Sym1 B R2 Sym2 C R3 f Hf. intros x x' Hxx' y y' Hyy'. apply Hf; auto. Qed. (** When the crelation on the domain is symmetric, a predicate is compatible with [iff] as soon as it is compatible with [impl]. Same with a binary crelation. *) Lemma proper_sym_impl_iff : forall `(Symmetric A R)`(Proper _ (R==>impl) f), Proper (R==>iff) f. Proof. intros A R Sym f Hf x x' Hxx'. repeat red in Hf. split; eauto. Qed. Lemma proper_sym_arrow_iffT : forall `(Symmetric A R)`(Proper _ (R==>arrow) f), Proper (R==>iffT) f. Proof. intros A R Sym f Hf x x' Hxx'. repeat red in Hf. split; eauto. Qed. Lemma proper_sym_impl_iff_2 : forall `(Symmetric A R)`(Symmetric B R')`(Proper _ (R==>R'==>impl) f), Proper (R==>R'==>iff) f. Proof. intros A R Sym B R' Sym' f Hf x x' Hxx' y y' Hyy'. repeat red in Hf. split; eauto. Qed. Lemma proper_sym_arrow_iffT_2 : forall `(Symmetric A R)`(Symmetric B R')`(Proper _ (R==>R'==>arrow) f), Proper (R==>R'==>iffT) f. Proof. intros A R Sym B R' Sym' f Hf x x' Hxx' y y' Hyy'. repeat red in Hf. split; eauto. Qed. (** A [PartialOrder] is compatible with its underlying equivalence. *) Require Import Relation_Definitions. #[global] Instance PartialOrder_proper_type `(PartialOrder A eqA R) : Proper (eqA==>eqA==>iffT) R. Proof. intros. apply proper_sym_arrow_iffT_2. 1-2: typeclasses eauto. intros x x' Hx y y' Hy Hr. apply transitivity with x. - generalize (partial_order_equivalence x x'); compute; intuition. - apply transitivity with y; auto. generalize (partial_order_equivalence y y'); compute; intuition. Qed. (** From a [PartialOrder] to the corresponding [StrictOrder]: [lt = le /\ ~eq]. If the order is total, we could also say [gt = ~le]. *) 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. apply transitivity with z; [assumption|]. now apply H. Qed. (** From a [StrictOrder] to the corresponding [PartialOrder]: [le = lt \/ eq]. If the order is total, we could also say [ge = ~lt]. *) Lemma StrictOrder_PreOrder `(Equivalence A eqA, StrictOrder A R, Proper _ (eqA==>eqA==>iffT) R) : PreOrder (relation_disjunction R eqA). Proof. split. - intros x. right. apply reflexivity. - intros x y z [Hxy|Hxy] [Hyz|Hyz]. + left. apply transitivity with y; auto. + left. eapply H1; try eassumption. * apply reflexivity. * now apply symmetry. + left. eapply H1; [eassumption|apply reflexivity|eassumption]. + right. apply transitivity with y; auto. Qed. #[global] Hint Extern 4 (PreOrder (relation_disjunction _ _)) => class_apply StrictOrder_PreOrder : typeclass_instances. Lemma StrictOrder_PartialOrder `(Equivalence A eqA, StrictOrder A R, Proper _ (eqA==>eqA==>iffT) R) : PartialOrder eqA (relation_disjunction R eqA). Proof. intros. intros x y. compute. intuition auto. - right; now apply symmetry. - elim (StrictOrder_Irreflexive x). eapply transitivity with y; eauto. - now apply symmetry. Qed. #[global] Hint Extern 4 (StrictOrder (relation_conjunction _ _)) => class_apply PartialOrder_StrictOrder : typeclass_instances. #[global] Hint Extern 4 (PartialOrder _ (relation_disjunction _ _)) => class_apply StrictOrder_PartialOrder : typeclass_instances. (* Register bindings for the generalized rewriting tactic *) Register forall_relation as rewrite.type.forall_relation. Register pointwise_relation as rewrite.type.pointwise_relation. Register respectful as rewrite.type.respectful. Register forall_def as rewrite.type.forall_def. Register do_subrelation as rewrite.type.do_subrelation. Register apply_subrelation as rewrite.type.apply_subrelation. Register Proper as rewrite.type.Proper. Register proper_prf as rewrite.type.proper_prf. Register ProperProxy as rewrite.type.ProperProxy. rocq-9.2.0/theories/Corelib/Classes/CRelationClasses.v000066400000000000000000000325301516144147600226650ustar00rootroot00000000000000(* -*- coding: utf-8 -*- *) (************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A -> Type. Definition arrow (A B : Type) := A -> B. Definition flip {A B C : Type} (f : A -> B -> C) := fun x y => f y x. Definition iffT (A B : Type) := ((A -> B) * (B -> A))%type. Global Typeclasses Opaque flip arrow iffT. (** We allow to unfold the [crelation] definition while doing morphism search. *) Section Defs. Context {A : Type}. (** We rebind crelational properties in separate classes to be able to overload each proof. *) Class Reflexive (R : crelation A) := reflexivity : forall x : A, R x x. Definition complement (R : crelation A) : crelation A := fun x y => R x y -> False. (** Opaque for proof-search. *) Typeclasses Opaque complement iffT. (** These are convertible. *) Lemma complement_inverse R : complement (flip R) = flip (complement R). Proof. reflexivity. Qed. Class Irreflexive (R : crelation A) := irreflexivity : Reflexive (complement R). Class Symmetric (R : crelation A) := symmetry : forall {x y}, R x y -> R y x. Class Asymmetric (R : crelation A) := asymmetry : forall {x y}, R x y -> (complement R y x : Type). Class Transitive (R : crelation A) := transitivity : forall {x y z}, R x y -> R y z -> R x z. (** Various combinations of reflexivity, symmetry and transitivity. *) (** A [PreOrder] is both Reflexive and Transitive. *) Class PreOrder (R : crelation A) := { #[global] PreOrder_Reflexive :: Reflexive R | 2 ; #[global] PreOrder_Transitive :: Transitive R | 2 }. (** A [StrictOrder] is both Irreflexive and Transitive. *) Class StrictOrder (R : crelation A) := { #[global] StrictOrder_Irreflexive :: Irreflexive R ; #[global] StrictOrder_Transitive :: Transitive R }. (** By definition, a strict order is also asymmetric *) Global Instance StrictOrder_Asymmetric `(StrictOrder R) : Asymmetric R. Proof. firstorder. Qed. (** A partial equivalence crelation is Symmetric and Transitive. *) Class PER (R : crelation A) := { #[global] PER_Symmetric :: Symmetric R | 3 ; #[global] PER_Transitive :: Transitive R | 3 }. (** Equivalence crelations. *) Class Equivalence (R : crelation A) := { #[global] Equivalence_Reflexive :: Reflexive R ; #[global] Equivalence_Symmetric :: Symmetric R ; #[global] Equivalence_Transitive :: Transitive R }. (** An Equivalence is a PER plus reflexivity. *) Global Instance Equivalence_PER {R} `(Equivalence R) : PER R | 10 := { PER_Symmetric := Equivalence_Symmetric ; PER_Transitive := Equivalence_Transitive }. (** We can now define antisymmetry w.r.t. an equivalence crelation on the carrier. *) Class Antisymmetric eqA `{equ : Equivalence eqA} (R : crelation A) := antisymmetry : forall {x y}, R x y -> R y x -> eqA x y. Class subrelation (R R' : crelation A) := is_subrelation : forall {x y}, R x y -> R' x y. (** Any symmetric crelation is equal to its inverse. *) Lemma subrelation_symmetric R `(Symmetric R) : subrelation (flip R) R. Proof. hnf. intros x y H'. red in H'. apply symmetry. assumption. Qed. Section flip. Lemma flip_Reflexive `{Reflexive R} : Reflexive (flip R). Proof. tauto. Qed. Program Definition flip_Irreflexive `(Irreflexive R) : Irreflexive (flip R) := irreflexivity (R:=R). Program Definition flip_Symmetric `(Symmetric R) : Symmetric (flip R) := fun x y H => symmetry (R:=R) H. Program Definition flip_Asymmetric `(Asymmetric R) : Asymmetric (flip R) := fun x y H H' => asymmetry (R:=R) H H'. Program Definition flip_Transitive `(Transitive R) : Transitive (flip R) := fun x y z H H' => transitivity (R:=R) H' H. Program Lemma flip_Antisymmetric `(Antisymmetric eqA R) : Antisymmetric eqA (flip R). Proof. firstorder. Qed. (** Inversing the larger structures *) Lemma flip_PreOrder `(PreOrder R) : PreOrder (flip R). Proof. firstorder. Qed. Lemma flip_StrictOrder `(StrictOrder R) : StrictOrder (flip R). Proof. firstorder. Qed. Lemma flip_PER `(PER R) : PER (flip R). Proof. firstorder. Qed. Lemma flip_Equivalence `(Equivalence R) : Equivalence (flip R). Proof. firstorder. Qed. End flip. Section complement. Lemma complement_Irreflexive `(Reflexive R) : Irreflexive (complement R). Proof. firstorder. Qed. Lemma complement_Symmetric `(Symmetric R) : Symmetric (complement R). Proof. firstorder. Qed. End complement. (** Rewrite crelation on a given support: declares a crelation as a rewrite crelation for use by the generalized rewriting tactic. It helps choosing if a rewrite should be handled by the generalized or the regular rewriting tactic using leibniz equality. Users can declare an [RewriteRelation A RA] anywhere to declare default crelations. This is also done automatically by the [Declare Relation A RA] commands. *) Class RewriteRelation (RA : crelation A). (** Any [Equivalence] declared in the context is automatically considered a rewrite crelation. *) Global Instance equivalence_rewrite_crelation `(Equivalence eqA) : RewriteRelation eqA. Defined. (** Leibniz equality. *) Section Leibniz. Global Instance eq_Reflexive : Reflexive (@eq A) := @eq_refl A. Global Instance eq_Symmetric : Symmetric (@eq A) := @eq_sym A. Global Instance eq_Transitive : Transitive (@eq A) := @eq_trans A. (** Leibinz equality [eq] is an equivalence crelation. The instance has low priority as it is always applicable if only the type is constrained. *) Global Program Instance eq_equivalence : Equivalence (@eq A) | 10. End Leibniz. End Defs. (** Default rewrite crelations handled by [setoid_rewrite]. *) #[global] Instance: RewriteRelation impl. Defined. #[global] Instance: RewriteRelation iff. Defined. (** Hints to drive the typeclass resolution avoiding loops due to the use of full unification. *) #[global] Hint Extern 1 (Reflexive (complement _)) => class_apply @irreflexivity : typeclass_instances. #[global] Hint Extern 3 (Symmetric (complement _)) => class_apply complement_Symmetric : typeclass_instances. #[global] Hint Extern 3 (Irreflexive (complement _)) => class_apply complement_Irreflexive : typeclass_instances. #[global] Hint Extern 3 (Reflexive (flip _)) => apply flip_Reflexive : typeclass_instances. #[global] Hint Extern 3 (Irreflexive (flip _)) => class_apply flip_Irreflexive : typeclass_instances. #[global] Hint Extern 3 (Symmetric (flip _)) => class_apply flip_Symmetric : typeclass_instances. #[global] Hint Extern 3 (Asymmetric (flip _)) => class_apply flip_Asymmetric : typeclass_instances. #[global] Hint Extern 3 (Antisymmetric (flip _)) => class_apply flip_Antisymmetric : typeclass_instances. #[global] Hint Extern 3 (Transitive (flip _)) => class_apply flip_Transitive : typeclass_instances. #[global] Hint Extern 3 (StrictOrder (flip _)) => class_apply flip_StrictOrder : typeclass_instances. #[global] Hint Extern 3 (PreOrder (flip _)) => class_apply flip_PreOrder : typeclass_instances. #[global] Hint Extern 4 (subrelation (flip _) _) => class_apply @subrelation_symmetric : typeclass_instances. #[global] Create HintDb ord. #[global] Hint Resolve irreflexivity : ord. Unset Implicit Arguments. Ltac solve_crelation := match goal with | [ |- ?R ?x ?x ] => reflexivity | [ H : ?R ?x ?y |- ?R ?y ?x ] => symmetry ; exact H end. #[global] Create HintDb crelations. #[global] Hint Extern 4 => solve_crelation : crelations. (** We can already dualize all these properties. *) (** * Standard instances. *) Ltac reduce_hyp H := match type of H with | context [ _ <-> _ ] => fail 1 | _ => red in H ; try reduce_hyp H end. Ltac reduce_goal := match goal with | [ |- _ <-> _ ] => fail 1 | _ => red ; intros ; try reduce_goal end. Tactic Notation "reduce" "in" hyp(Hid) := reduce_hyp Hid. Ltac reduce := reduce_goal. Tactic Notation "apply" "*" constr(t) := first [ refine t | refine (t _) | refine (t _ _) | refine (t _ _ _) | refine (t _ _ _ _) | refine (t _ _ _ _ _) | refine (t _ _ _ _ _ _) | refine (t _ _ _ _ _ _ _) ]. Ltac simpl_crelation := unfold flip, impl, arrow ; try reduce ; program_simpl ; try ( solve [ dintuition auto with crelations ]). Local Obligation Tactic := simpl_crelation. (** Logical implication. *) #[global] Program Instance impl_Reflexive : Reflexive impl. #[global] Program Instance impl_Transitive : Transitive impl. (** Logical equivalence. *) #[global] Instance iff_Reflexive : Reflexive iff := iff_refl. #[global] Instance iff_Symmetric : Symmetric iff := iff_sym. #[global] Instance iff_Transitive : Transitive iff := iff_trans. (** Logical equivalence [iff] is an equivalence crelation. *) #[global] Program Instance iff_equivalence : Equivalence iff. #[global] Program Instance arrow_Reflexive : Reflexive arrow. #[global] Program Instance arrow_Transitive : Transitive arrow. #[global] Instance iffT_Reflexive : Reflexive iffT. Proof. firstorder. Defined. #[global] Instance iffT_Symmetric : Symmetric iffT. Proof. firstorder. Defined. #[global] Instance iffT_Transitive : Transitive iffT. Proof. firstorder. Defined. (** We now develop a generalization of results on crelations for arbitrary predicates. The resulting theory can be applied to homogeneous binary crelations but also to arbitrary n-ary predicates. *) Local Open Scope list_scope. (** A compact representation of non-dependent arities, with the codomain singled-out. *) (** We define the various operations which define the algebra on binary crelations *) Section Binary. Context {A : Type}. Definition relation_equivalence : crelation (crelation A) := 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). Definition relation_disjunction (R : crelation A) (R' : crelation A) : crelation A := fun x y => sum (R x y) (R' x y). (** Relation equivalence is an equivalence, and subrelation defines a partial order. *) Global Instance relation_equivalence_equivalence : Equivalence relation_equivalence. Proof. split; red; unfold relation_equivalence, iffT. - firstorder. - firstorder. - intros x y z X X0 x0 y0. specialize (X x0 y0). specialize (X0 x0 y0). firstorder. Qed. Global Instance relation_implication_preorder : PreOrder (@subrelation A). Proof. firstorder. Qed. (** *** Partial Order. A partial order is a preorder which is additionally antisymmetric. We give an equivalent definition, up-to an equivalence crelation on the carrier. *) Class PartialOrder eqA `{equ : Equivalence A eqA} R `{preo : PreOrder A R} := partial_order_equivalence : relation_equivalence eqA (relation_conjunction R (flip R)). (** The equivalence proof is sufficient for proving that [R] must be a morphism for equivalence (see Morphisms). It is also sufficient to show that [R] is antisymmetric w.r.t. [eqA] *) Global Instance partial_order_antisym `(PartialOrder eqA R) : Antisymmetric eqA R. Proof with auto. reduce_goal. firstorder. Qed. Lemma PartialOrder_inverse `(PartialOrder eqA R) : PartialOrder eqA (flip R). Proof. firstorder. Qed. End Binary. #[global] Hint Extern 3 (PartialOrder (flip _)) => class_apply PartialOrder_inverse : typeclass_instances. (** The partial order defined by subrelation and crelation equivalence. *) (* Program Instance subrelation_partial_order : *) (* ! PartialOrder (crelation A) relation_equivalence subrelation. *) (* Obligation Tactic := idtac. *) (* Next Obligation. *) (* Proof. *) (* intros x. refine (fun x => x). *) (* Qed. *) Global Typeclasses Opaque relation_equivalence. (* Register bindings for the generalized rewriting tactic *) Register arrow as rewrite.type.arrow. Register flip as rewrite.type.flip. Register crelation as rewrite.type.relation. Register subrelation as rewrite.type.subrelation. Register Reflexive as rewrite.type.Reflexive. Register reflexivity as rewrite.type.reflexivity. Register Symmetric as rewrite.type.Symmetric. Register symmetry as rewrite.type.symmetry. Register Transitive as rewrite.type.Transitive. Register transitivity as rewrite.type.transitivity. Register RewriteRelation as rewrite.type.RewriteRelation. rocq-9.2.0/theories/Corelib/Classes/Equivalence.v000066400000000000000000000117511516144147600217320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* substitute H ; clear H x end. Ltac setoid_subst_nofail := match goal with | [ H : ?x === ?y |- _ ] => setoid_subst H ; setoid_subst_nofail | _ => idtac end. (** [subst*] will try its best at substituting every equality in the goal. *) Tactic Notation "subst" "*" := subst_no_fail ; setoid_subst_nofail. (** Simplify the goal w.r.t. equivalence. *) Ltac equiv_simplify_one := match goal with | [ H : ?x === ?x |- _ ] => clear H | [ H : ?x === ?y |- _ ] => setoid_subst H | [ |- ?x =/= ?y ] => let name:=fresh "Hneq" in intro name | [ |- ~ ?x === ?y ] => let name:=fresh "Hneq" in intro name end. Ltac equiv_simplify := repeat equiv_simplify_one. (** "reify" relations which are equivalences to applications of the overloaded [equiv] method for easy recognition in tactics. *) Ltac equivify_tac := match goal with | [ s : Equivalence ?A ?R, H : ?R ?x ?y |- _ ] => change R with (@equiv A R s) in H | [ s : Equivalence ?A ?R |- context C [ ?R ?x ?y ] ] => change (R x y) with (@equiv A R s x y) end. Ltac equivify := repeat equivify_tac. Section Respecting. (** Here we build an equivalence instance for functions which relates respectful ones only, we do not export it. *) Definition respecting `(eqa : Equivalence A (R : relation A), eqb : Equivalence B (R' : relation B)) : Type := { morph : A -> B | respectful R R' morph morph }. Program Instance respecting_equiv `(eqa : Equivalence A R, eqb : Equivalence B R') : Equivalence (fun (f g : respecting eqa eqb) => forall (x y : A), R x y -> R' (proj1_sig f x) (proj1_sig g y)). Solve Obligations with unfold respecting in * ; simpl_relation ; program_simpl. Next Obligation. Proof. intros. intros f g h H H' x y Rxy. unfold respecting in *. program_simpl. transitivity (g y); auto. firstorder. Qed. End Respecting. (** The default equivalence on function spaces, with higher priority than [eq]. *) #[global] Instance pointwise_reflexive {A} `(reflb : Reflexive B eqB) : Reflexive (pointwise_relation A eqB) | 9. Proof. firstorder. Qed. #[global] Instance pointwise_symmetric {A} `(symb : Symmetric B eqB) : Symmetric (pointwise_relation A eqB) | 9. Proof. firstorder. Qed. #[global] Instance pointwise_transitive {A} `(transb : Transitive B eqB) : Transitive (pointwise_relation A eqB) | 9. Proof. firstorder. Qed. #[global] Instance pointwise_equivalence {A} `(eqb : Equivalence B eqB) : Equivalence (pointwise_relation A eqB) | 9. Proof. split; apply _. Qed. rocq-9.2.0/theories/Corelib/Classes/Init.v000066400000000000000000000031541516144147600203720ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unify x y with typeclass_instances ; fail 1 "Convertible" | |- _ => exact tt end. #[global] Hint Extern 0 (@Unconvertible _ _ _) => unconvertible : typeclass_instances. rocq-9.2.0/theories/Corelib/Classes/Morphisms.v000066400000000000000000000631171516144147600214550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* B) _ _] goal, making proof-search much slower. A cleaner solution would be to be able to set different priorities in different hint bases and select a particular hint database for resolution of a type class constraint. *) Class ProperProxy (R : relation A) (m : A) : Prop := proper_proxy : R m m. Class ReflexiveProxy (R : relation A) : Prop := reflexive_proxy : forall x, R x x. Lemma eq_proper_proxy (x : A) : ProperProxy (@eq A) x. Proof. firstorder. Qed. (** Every reflexive relation gives rise to a morphism. If the relation is not determined (is an evar), then we restrict the solutions to predefined ones (equality, or iff on Prop), using ground instances. If the relation is determined then [ReflexiveProxy] calls back to [Reflexive]. *) Lemma reflexive_proper `{ReflexiveProxy R} (x : A) : Proper R x. Proof. firstorder. Qed. Lemma reflexive_proper_proxy `(ReflexiveProxy R) (x : A) : ProperProxy R x. Proof. firstorder. Qed. Lemma proper_proper_proxy x `(Proper R x) : ProperProxy R x. Proof. firstorder. Qed. Lemma reflexive_reflexive_proxy `(Reflexive A R) : ReflexiveProxy R. Proof. firstorder. Qed. (** Respectful morphisms. *) (** The fully dependent version, not used yet. *) Definition respectful_hetero (A B : Type) (C : A -> Type) (D : B -> Type) (R : A -> B -> Prop) (R' : forall (x : A) (y : B), C x -> D y -> Prop) : (forall x : A, C x) -> (forall x : B, D x) -> Prop := fun f g => forall x y, R x y -> R' x y (f x) (g y). (** The non-dependent version is an instance where we forget dependencies. *) Definition respectful (R : relation A) (R' : relation B) : relation (A -> B) := Eval compute in @respectful_hetero A A (fun _ => B) (fun _ => B) R (fun _ _ => R'). End Proper. (** Non-dependent pointwise lifting *) Definition pointwise_relation A {B} (R : relation B) : relation (A -> B) := fun f g => forall a, R (f a) (g a). (** We let Rocq infer these relations when a default relation should be found on the function space. *) Lemma rewrite_relation_pointwise {A B R} `{RewriteRelation B R}: RewriteRelation (@pointwise_relation A B R). Proof. split. Qed. Lemma rewrite_relation_eq_dom {A B R} `{RewriteRelation B R}: RewriteRelation (respectful (@Logic.eq A) R). Proof. split. Qed. (** Pointwise reflexive *) Ltac rewrite_relation_fun := (* If we're looking for a default rewrite relation on a function type, we favor pointwise equality *) class_apply @rewrite_relation_pointwise || (* The relation might be already determined to be (eq ==> _) instead of a pointwise equality, but we want to treat them the same. No point in backtracking on the previous instance though *) class_apply @rewrite_relation_eq_dom. Global Hint Extern 2 (@RewriteRelation (_ -> _) _) => rewrite_relation_fun : typeclass_instances. Lemma eq_rewrite_relation {A} : RewriteRelation (@eq A). Proof. split. Qed. Ltac eq_rewrite_relation A := solve [unshelve class_apply @eq_rewrite_relation]. Global Hint Extern 100 (@RewriteRelation ?A _) => eq_rewrite_relation A : typeclass_instances. (** We favor the use of Leibniz equality or a declared reflexive relation when resolving [ProperProxy], otherwise, if the relation is given (not an evar), we fall back to [Proper]. *) #[global] Hint Extern 1 (ProperProxy _ _) => class_apply @eq_proper_proxy || class_apply @reflexive_proper_proxy : typeclass_instances. #[global] Hint Extern 2 (ProperProxy ?R _) => not_evar R; class_apply @proper_proper_proxy : typeclass_instances. (* This tactics takes a type and (partially defined) relation and tries to find all instances matching it which completely determine the relation, feeding them to kont. *) Ltac find_rewrite_relation A R kont := assert (@RewriteRelation A R); [solve [unshelve typeclasses eauto]|]; kont R. (** This hint helps infer "generic" reflexive relations, based only on the type of the carrier, when the relation is only partially defined (contains evars). *) Ltac reflexive_proxy_tac A R := tryif has_evar R then (* If the user declared a specific rewrite relation on the type, we favor it. By default, [iff] and and [impl] are favored for Prop, pointwise equality for function types and finally leibniz equality. *) find_rewrite_relation A R ltac:(fun RA => class_apply (@reflexive_reflexive_proxy A RA)) (* The [Reflexive] subgoal produced here will need no backtracking, being a Prop goal without existential variables, but we don't have `cut` to explicitely say it. *) else (* If the relation is determined then we look for a relexivity proof on it *) class_apply @reflexive_reflexive_proxy. #[global] Hint Extern 1 (@ReflexiveProxy ?A ?R) => reflexive_proxy_tac A R : typeclass_instances. (** Notations reminiscent of the old syntax for declaring morphisms. *) Declare Scope signature_scope. Delimit Scope signature_scope with signature. Module ProperNotations. Notation " R ++> R' " := (@respectful _ _ (R%signature) (R'%signature)) (right associativity, at level 55) : signature_scope. Notation " R ==> R' " := (@respectful _ _ (R%signature) (R'%signature)) (right associativity, at level 55) : signature_scope. Notation " R --> R' " := (@respectful _ _ (flip (R%signature)) (R'%signature)) (right associativity, at level 55) : signature_scope. End ProperNotations. Arguments Proper {A}%_type R%_signature m. Arguments respectful {A B}%_type (R R')%_signature _ _. Export ProperNotations. Local Open Scope signature_scope. (** [solve_proper] try to solve the goal [Proper (?==> ... ==>?) f] by repeated introductions and setoid rewrites. It should work fine when [f] is a combination of already known morphisms and quantifiers. *) Ltac solve_respectful t := match goal with | |- respectful _ _ _ _ => let H := fresh "H" in intros ? ? H; solve_respectful ltac:(setoid_rewrite H; t) | _ => t; reflexivity end. Ltac solve_proper := unfold Proper; solve_respectful ltac:(idtac). (** [f_equiv] is a clone of [f_equal] that handles setoid equivalences. For example, if we know that [f] is a morphism for [E1==>E2==>E], then the goal [E (f x y) (f x' y')] will be transformed by [f_equiv] into the subgoals [E1 x x'] and [E2 y y']. *) Ltac f_equiv := match goal with | |- ?R (?f ?x) (?f' _) => let T := type of x in let Rx := fresh "R" in evar (Rx : relation T); let H := fresh in assert (H : (Rx==>R)%signature f f'); unfold Rx in *; clear Rx; [ f_equiv | apply H; clear H; try reflexivity ] | |- ?R ?f ?f' => solve [change (Proper R f); eauto with typeclass_instances | reflexivity ] | _ => idtac end. Section Relations. Let U := Type. Context {A B : U} (P : A -> U). (** [forall_def] reifies the dependent product as a definition. *) Definition forall_def : Type := forall x : A, P x. (** Dependent pointwise lifting of a relation on the range. *) Definition forall_relation (sig : forall a, relation (P a)) : relation (forall x, P x) := fun f g => forall a, sig a (f a) (g a). Lemma pointwise_pointwise (R : relation B) : relation_equivalence (pointwise_relation A R) (@eq A ==> R). Proof. intros. split; reduce; subst; firstorder. Qed. (** Subrelations induce a morphism on the identity. *) Global Instance subrelation_id_proper `(subrelation A RA RA') : Proper (RA ==> RA') id. Proof. firstorder. Qed. (** The subrelation property goes through products as usual. *) Lemma subrelation_respectful `(subl : subrelation A RA' RA, subr : subrelation B RB RB') : subrelation (RA ==> RB) (RA' ==> RB'). Proof. unfold subrelation in *; firstorder. Qed. (** And of course it is reflexive. *) Lemma subrelation_refl R : @subrelation A R R. Proof. unfold subrelation; firstorder. Qed. (** [Proper] is itself a covariant morphism for [subrelation]. We use an unconvertible premise to avoid looping. *) Lemma subrelation_proper `(mor : Proper A R' m) `(unc : Unconvertible (relation A) R R') `(sub : subrelation A R' R) : Proper R m. Proof. intros. apply sub. apply mor. Qed. Global Instance proper_subrelation_proper : Proper (subrelation ++> eq ==> impl) (@Proper A). Proof. reduce. subst. firstorder. Qed. Global Instance pointwise_subrelation `(sub : subrelation B R R') : subrelation (pointwise_relation A R) (pointwise_relation A R') | 4. Proof. intros x y H a. unfold pointwise_relation in *. apply sub. apply H. Qed. (** For dependent function types. *) Lemma forall_subrelation (R S : forall x : A, relation (P x)) : (forall a, subrelation (R a) (S a)) -> subrelation (forall_relation R) (forall_relation S). Proof. intros H x y H0 a. apply H. apply H0. Qed. End Relations. Global Typeclasses Opaque respectful pointwise_relation forall_relation. Arguments forall_relation {A P}%_type sig%_signature _ _. Arguments pointwise_relation A%_type {B}%_type R%_signature _ _. #[global] Hint Unfold Reflexive : core. #[global] Hint Unfold Symmetric : core. #[global] Hint Unfold Transitive : core. (** Resolution with subrelation: favor decomposing products over applying reflexivity for unconstrained goals. *) Ltac subrelation_tac T U := (is_ground T ; is_ground U ; class_apply @subrelation_refl) || class_apply @subrelation_respectful || class_apply @subrelation_refl. #[global] Hint Extern 3 (@subrelation _ ?T ?U) => subrelation_tac T U : typeclass_instances. CoInductive apply_subrelation : Prop := do_subrelation. Ltac proper_subrelation := match goal with [ H : apply_subrelation |- _ ] => clear H ; class_apply @subrelation_proper end. #[global] Hint Extern 5 (@Proper _ ?H _) => proper_subrelation : typeclass_instances. (** Essential subrelation instances for [iff], [impl] and [pointwise_relation]. *) #[global] Instance iff_impl_subrelation : subrelation iff impl | 2. Proof. firstorder. Qed. #[global] Instance iff_flip_impl_subrelation : subrelation iff (flip impl) | 2. Proof. firstorder. Qed. (** We use an extern hint to help unification. *) #[global] Hint Extern 4 (subrelation (@forall_relation ?A ?B ?R) (@forall_relation _ _ ?S)) => apply (@forall_subrelation A B R S) ; intro : typeclass_instances. Section GenericInstances. (* Share universes *) Let U := Type. Context {A B C : U}. (** We can build a PER on the Rocq function space if we have PERs on the domain and codomain. *) Program Instance respectful_per `(PER A R, PER B R') : PER (R ==> R'). Next Obligation. Proof. intros R H R' H0 x y z H1 H2 x0 y0 H3. assert(R x0 x0). - transitivity y0; auto. symmetry; auto. - transitivity (y x0); auto. Qed. (** The complement of a relation conserves its proper elements. *) Program Definition complement_proper `(mR : Proper (A -> A -> Prop) (RA ==> RA ==> iff) R) : Proper (RA ==> RA ==> iff) (complement R) := _. Next Obligation. Proof. intros RA R mR x y H x0 y0 H0. unfold complement. pose (mR x y H x0 y0 H0). intuition. Qed. (** The [flip] too, actually the [flip] instance is a bit more general. *) Program Definition flip_proper `(mor : Proper (A -> B -> C) (RA ==> RB ==> RC) f) : Proper (RB ==> RA ==> RC) (flip f) := _. Next Obligation. Proof. intros RA RB RC f mor x y H x0 y0 H0; apply mor ; auto. Qed. (** Every Transitive relation gives rise to a binary morphism on [impl], contravariant in the first argument, covariant in the second. *) Global Program Instance trans_contra_co_morphism `(Transitive A R) : Proper (R --> R ++> impl) R. Next Obligation. Proof. intros R H x y H0 x0 y0 H1 H2. transitivity x; auto. transitivity x0; auto. Qed. (** Proper declarations for partial applications. *) Global Program Instance trans_contra_inv_impl_morphism `(Transitive A R) {x} : Proper (R --> flip impl) (R x) | 3. Next Obligation. Proof. intros R H x x0 y H0 H1. transitivity y; auto. Qed. Global Program Instance trans_co_impl_morphism `(Transitive A R) {x} : Proper (R ++> impl) (R x) | 3. Next Obligation. Proof. intros R H x x0 y H0 H1. transitivity x0; auto. Qed. Global Program Instance trans_sym_co_inv_impl_morphism `(PER A R) {x} : Proper (R ++> flip impl) (R x) | 3. Next Obligation. Proof. intros R H x x0 y H0 H1. transitivity y; auto. symmetry; auto. Qed. Global Program Instance trans_sym_contra_impl_morphism `(PER A R) {x} : Proper (R --> impl) (R x) | 3. Next Obligation. Proof. intros R H x x0 y H0 H1. transitivity x0; auto. symmetry; auto. Qed. Global Program Instance per_partial_app_morphism `(PER A R) {x} : Proper (R ==> iff) (R x) | 2. Next Obligation. Proof. intros R H x x0 y H0. split. - intros ; transitivity x0; auto. - intros. transitivity y; auto. symmetry; auto. 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. *) Global Program Instance trans_co_eq_inv_impl_morphism `(Transitive A R) : Proper (R ==> (@eq A) ==> flip impl) R | 2. Next Obligation. Proof. intros R H x y H0 y0 y1 e H2; destruct e. transitivity y; auto. Qed. (** Every Symmetric and Transitive relation gives rise to an equivariant morphism. *) Global Program Instance PER_morphism `(PER A R) : Proper (R ==> R ==> iff) R | 1. Next Obligation. Proof. intros R H x y H0 x0 y0 H1. split ; intros. - transitivity x0; auto. transitivity x; auto. symmetry; auto. - transitivity y; auto. transitivity y0; auto. symmetry; auto. Qed. Lemma symmetric_equiv_flip `(Symmetric A R) : relation_equivalence R (flip R). Proof. firstorder. Qed. Global Program Instance compose_proper RA RB RC : Proper ((RB ==> RC) ==> (RA ==> RB) ==> (RA ==> RC)) (@compose A B C). Next Obligation. Proof. intros RA RB RC x y H x0 y0 H0 x1 y1 H1. unfold compose. apply H. apply H0. apply H1. Qed. Global Instance reflexive_eq_dom_reflexive `{Reflexive B R'}: Reflexive (respectful (@Logic.eq A) R'). Proof. simpl_relation. Qed. (** [respectful] is a morphism for relation equivalence. *) Global Instance respectful_morphism : Proper (relation_equivalence ++> relation_equivalence ++> relation_equivalence) (@respectful A B). Proof. intros x y H x0 y0 H0 x1 x2. unfold respectful, relation_equivalence, predicate_equivalence in * ; simpl in *. split ; intros H1 x3 y1 H2. - now apply H0, H1, H. - now apply H0, H1, H. Qed. (** [R] is Reflexive, hence we can build the needed proof. *) Lemma Reflexive_partial_app_morphism `(Proper (A -> B) (R ==> R') m, ProperProxy A R x) : Proper R' (m x). Proof. simpl_relation. Qed. Lemma flip_respectful (R : relation A) (R' : relation B) : relation_equivalence (flip (R ==> R')) (flip R ==> flip R'). Proof. intros. unfold flip, respectful. split ; intros ; intuition. Qed. (** Treating flip: can't make them direct instances as we need at least a [flip] present in the goal. *) Lemma flip1 `(subrelation A R' R) : subrelation (flip (flip R')) R. Proof. firstorder. Qed. Lemma flip2 `(subrelation A R R') : subrelation R (flip (flip R')). Proof. firstorder. Qed. (** That's if and only if *) Lemma eq_subrelation `(Reflexive A R) : subrelation (@eq A) R. Proof. simpl_relation. Qed. (** Once we have normalized, we will apply this instance to simplify the problem. *) Definition proper_flip_proper `(mor : Proper A R m) : Proper (flip R) m := mor. Lemma proper_eq (x : A) : Proper (@eq A) x. Proof. intros. reflexivity. Qed. End GenericInstances. Class PartialApplication. CoInductive normalization_done : Prop := did_normalization. Class Params {A : Type} (of : A) (arity : nat). #[global] Instance eq_pars : Params (@eq) 1 := {}. #[global] Instance iff_pars : Params (@iff) 0 := {}. #[global] Instance impl_pars : Params (@impl) 0 := {}. #[global] Instance flip_pars : Params (@flip) 4 := {}. Ltac partial_application_tactic := let rec do_partial_apps H m cont := match m with | ?m' ?x => class_apply @Reflexive_partial_app_morphism ; [(do_partial_apps H m' ltac:(idtac))|clear H] | _ => cont end in let rec do_partial H ar m := lazymatch ar with | 0%nat => do_partial_apps H m ltac:(fail 1) | S ?n' => match m with ?m' ?x => do_partial H n' m' end end in let params m sk fk := (let m' := fresh in Ltac.Internal.head_of_constr m' m ; let n := fresh in evar (n:nat) ; let v := eval compute in n in clear n ; let H := fresh in assert(H:Params m' v) by (subst m'; once typeclasses eauto) ; let v' := eval compute in v in subst m'; (sk H v' || fail 1)) || fk in let on_morphism m cont := params m ltac:(fun H n => do_partial H n m) ltac:(cont) in match goal with | [ _ : normalization_done |- _ ] => fail 1 | [ _ : @Params _ _ _ |- _ ] => fail 1 | [ |- @Proper ?T _ (?m ?x) ] => match goal with | [ H : PartialApplication |- _ ] => class_apply @Reflexive_partial_app_morphism; [|clear H] | _ => on_morphism (m x) ltac:(class_apply @Reflexive_partial_app_morphism) end end. (** Bootstrap !!! *) #[global] Instance proper_proper {A} : Proper (relation_equivalence ==> eq ==> iff) (@Proper A). Proof. intros x y H y0 y1 e; destruct e. reduce in H. split ; red ; intros H0. - apply H, H0. - apply H, H0. Qed. Ltac proper_reflexive := match goal with | [ _ : normalization_done |- _ ] => fail 1 | _ => class_apply proper_eq || class_apply @reflexive_proper end. #[global] Hint Extern 1 (subrelation (flip _) _) => class_apply @flip1 : typeclass_instances. #[global] Hint Extern 1 (subrelation _ (flip _)) => class_apply @flip2 : typeclass_instances. #[global] Hint Extern 1 (Proper _ (complement _)) => apply @complement_proper : typeclass_instances. #[global] Hint Extern 1 (Proper _ (flip _)) => apply @flip_proper : typeclass_instances. #[global] Hint Extern 2 (@Proper _ (flip _) _) => class_apply @proper_flip_proper : typeclass_instances. #[global] Hint Extern 4 (@Proper _ _ _) => partial_application_tactic : typeclass_instances. #[global] Hint Extern 7 (@Proper _ _ _) => proper_reflexive : typeclass_instances. (** Special-purpose class to do normalization of signatures w.r.t. flip. *) Section Normalize. Context (A : Type). Class Normalizes (m : relation A) (m' : relation A) : Prop := normalizes : relation_equivalence m m'. (** Current strategy: add [flip] everywhere and reduce using [subrelation] afterwards. *) Lemma proper_normalizes_proper `(Normalizes R0 R1, Proper A R1 m) : Proper R0 m. Proof. eapply proper_proper; eauto. Qed. Lemma flip_atom R : Normalizes R (flip (flip R)). Proof. firstorder. Qed. End Normalize. Lemma flip_arrow {A : Type} {B : Type} `(NA : Normalizes A R (flip R'''), NB : Normalizes B R' (flip R'')) : Normalizes (A -> B) (R ==> R') (flip (R''' ==> R'')%signature). Proof. unfold Normalizes in *. unfold relation_equivalence in *. unfold predicate_equivalence in *. simpl in *. unfold respectful. unfold flip in *. intros x x0; split; intros H x1 y H0. - apply NB. apply H. apply NA. apply H0. - apply NB. apply H. apply NA. apply H0. Qed. Ltac normalizes := match goal with | [ |- Normalizes _ (respectful _ _) _ ] => class_apply @flip_arrow | _ => class_apply @flip_atom end. Ltac proper_normalization := match goal with | [ _ : normalization_done |- _ ] => fail 1 | [ _ : apply_subrelation |- @Proper _ ?R _ ] => let H := fresh "H" in set(H:=did_normalization) ; class_apply @proper_normalizes_proper end. #[global] Hint Extern 1 (Normalizes _ _ _) => normalizes : typeclass_instances. #[global] Hint Extern 6 (@Proper _ _ _) => proper_normalization : typeclass_instances. (** When the relation on the domain is symmetric, we can flip the relation on the codomain. Same for binary functions. *) Lemma proper_sym_flip : forall `(Symmetric A R1)`(Proper (A->B) (R1==>R2) f), Proper (R1==>flip R2) f. Proof. intros A R1 Sym B R2 f Hf. intros x x' Hxx'. apply Hf, Sym, Hxx'. Qed. Lemma proper_sym_flip_2 : forall `(Symmetric A R1)`(Symmetric B R2)`(Proper (A->B->C) (R1==>R2==>R3) f), Proper (R1==>R2==>flip R3) f. Proof. intros A R1 Sym1 B R2 Sym2 C R3 f Hf. intros x x' Hxx' y y' Hyy'. apply Hf; auto. Qed. (** When the relation on the domain is symmetric, a predicate is compatible with [iff] as soon as it is compatible with [impl]. Same with a binary relation. *) Lemma proper_sym_impl_iff : forall `(Symmetric A R)`(Proper _ (R==>impl) f), Proper (R==>iff) f. Proof. intros A R Sym f Hf x x' Hxx'. repeat red in Hf. split; eauto. Qed. Lemma proper_sym_impl_iff_2 : forall `(Symmetric A R)`(Symmetric B R')`(Proper _ (R==>R'==>impl) f), Proper (R==>R'==>iff) f. Proof. intros A R Sym B R' Sym' f Hf x x' Hxx' y y' Hyy'. repeat red in Hf. split; eauto. Qed. (** A [PartialOrder] is compatible with its underlying equivalence. *) #[global] Instance PartialOrder_proper `(PartialOrder A eqA R) : Proper (eqA==>eqA==>iff) R. Proof. intros. apply proper_sym_impl_iff_2. 1-2: auto with relations. 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. Qed. (** From a [PartialOrder] to the corresponding [StrictOrder]: [lt = le /\ ~eq]. If the order is total, we could also say [gt = ~le]. *) 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. eapply PartialOrder_proper; eauto. apply reflexivity. Qed. (** From a [StrictOrder] to the corresponding [PartialOrder]: [le = lt \/ eq]. If the order is total, we could also say [ge = ~lt]. *) Lemma StrictOrder_PreOrder `(Equivalence A eqA, StrictOrder A R, Proper _ (eqA==>eqA==>iff) R) : PreOrder (relation_disjunction R eqA). Proof. split. - intros x. right. reflexivity. - intros x y z [Hxy|Hxy] [Hyz|Hyz]. + left. transitivity y; auto. + left. eapply H1; eauto. * apply reflexivity. * now apply symmetry. + left. eapply H1; try eassumption. now apply reflexivity. + right. transitivity y; auto. Qed. #[global] Hint Extern 4 (PreOrder (relation_disjunction _ _)) => class_apply StrictOrder_PreOrder : typeclass_instances. Lemma StrictOrder_PartialOrder `(Equivalence A eqA, StrictOrder A R, Proper _ (eqA==>eqA==>iff) R) : PartialOrder eqA (relation_disjunction R eqA). Proof. intros. intros x y. compute. intuition auto with relations. elim (StrictOrder_Irreflexive x). transitivity y; auto. Qed. #[global] Hint Extern 4 (StrictOrder (relation_conjunction _ _)) => class_apply PartialOrder_StrictOrder : typeclass_instances. #[global] Hint Extern 4 (PartialOrder _ (relation_disjunction _ _)) => class_apply StrictOrder_PartialOrder : typeclass_instances. (* Register bindings for the generalized rewriting tactic *) Register forall_relation as rewrite.prop.forall_relation. Register pointwise_relation as rewrite.prop.pointwise_relation. Register respectful as rewrite.prop.respectful. Register forall_def as rewrite.prop.forall_def. Register do_subrelation as rewrite.prop.do_subrelation. Register apply_subrelation as rewrite.prop.apply_subrelation. Register RewriteRelation as rewrite.prop.RewriteRelation. Register Proper as rewrite.prop.Proper. Register proper_prf as rewrite.prop.proper_prf. Register ProperProxy as rewrite.prop.ProperProxy. rocq-9.2.0/theories/Corelib/Classes/Morphisms_Prop.v000066400000000000000000000067561516144147600224630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* impl) not | 1. #[global] Program Instance not_iff_morphism : Proper (iff ++> iff) not. (** Logical conjunction. *) #[global] Program Instance and_impl_morphism : Proper (impl ==> impl ==> impl) and | 1. #[global] Program Instance and_iff_morphism : Proper (iff ==> iff ==> iff) and. (** Logical disjunction. *) #[global] Program Instance or_impl_morphism : Proper (impl ==> impl ==> impl) or | 1. #[global] Program Instance or_iff_morphism : Proper (iff ==> iff ==> iff) or. (** Logical implication [impl] is a morphism for logical equivalence. *) #[global] Program Instance iff_iff_iff_impl_morphism : Proper (iff ==> iff ==> iff) impl. (** Morphisms for quantifiers *) #[global] Program Instance ex_iff_morphism {A : Type} : Proper (pointwise_relation A iff ==> iff) (@ex A). #[global] Program Instance ex_impl_morphism {A : Type} : Proper (pointwise_relation A impl ==> impl) (@ex A) | 1. #[global] Program Instance ex_flip_impl_morphism {A : Type} : Proper (pointwise_relation A (flip impl) ==> flip impl) (@ex A) | 1. #[global] Program Instance all_iff_morphism {A : Type} : Proper (pointwise_relation A iff ==> iff) (@all A). #[global] Program Instance all_impl_morphism {A : Type} : Proper (pointwise_relation A impl ==> impl) (@all A) | 1. #[global] Program Instance all_flip_impl_morphism {A : Type} : Proper (pointwise_relation A (flip impl) ==> flip impl) (@all A) | 1. (** Equivalent points are simultaneously accessible or not *) #[global] Instance Acc_pt_morphism {A:Type}(E R : A->A->Prop) `(Equivalence _ E) `(Proper _ (E==>E==>iff) R) : Proper (E==>iff) (Acc R). Proof. apply proper_sym_impl_iff. - auto with relations. - intros x y EQ WF. apply Acc_intro; intros z Hz. rewrite <- EQ in Hz. now apply Acc_inv with x. Qed. (** Equivalent relations have the same accessible points *) #[global] 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. Qed. (** Equivalent relations are simultaneously well-founded or not *) #[global] Instance well_founded_morphism {A : Type} : Proper (relation_equivalence ==> iff) (@well_founded A). Proof. unfold well_founded. solve_proper. Qed. rocq-9.2.0/theories/Corelib/Classes/RelationClasses.v000066400000000000000000000444661516144147600225750ustar00rootroot00000000000000(* -*- coding: utf-8 -*- *) (************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* R x y -> False. (** Opaque for proof-search. *) Typeclasses Opaque complement. (** These are convertible. *) Lemma complement_inverse R : complement (flip R) = flip (complement R). Proof. reflexivity. Qed. Class Irreflexive (R : relation A) := irreflexivity : Reflexive (complement R). Class Symmetric (R : relation A) := symmetry : forall {x y}, R x y -> R y x. Class Asymmetric (R : relation A) := asymmetry : forall {x y}, R x y -> R y x -> False. Class Transitive (R : relation A) := transitivity : forall {x y z}, R x y -> R y z -> R x z. (** Various combinations of reflexivity, symmetry and transitivity. *) (** A [PreOrder] is both Reflexive and Transitive. *) Class PreOrder (R : relation A) : Prop := { #[global] PreOrder_Reflexive :: Reflexive R | 2 ; #[global] PreOrder_Transitive :: Transitive R | 2 }. (** A [StrictOrder] is both Irreflexive and Transitive. *) Class StrictOrder (R : relation A) : Prop := { #[global] StrictOrder_Irreflexive :: Irreflexive R ; #[global] StrictOrder_Transitive :: Transitive R }. (** By definition, a strict order is also asymmetric *) Global Instance StrictOrder_Asymmetric `(StrictOrder R) : Asymmetric R. Proof. firstorder. Qed. (** A partial equivalence relation is Symmetric and Transitive. *) Class PER (R : relation A) : Prop := { #[global] PER_Symmetric :: Symmetric R | 3 ; #[global] PER_Transitive :: Transitive R | 3 }. (** Equivalence relations. *) Class Equivalence (R : relation A) : Prop := { #[global] Equivalence_Reflexive :: Reflexive R ; #[global] Equivalence_Symmetric :: Symmetric R ; #[global] Equivalence_Transitive :: Transitive R }. (** An Equivalence is a PER plus reflexivity. *) Global Instance Equivalence_PER {R} `(E:Equivalence R) : PER R | 10 := { }. (** An Equivalence is a PreOrder plus symmetry. *) Global Instance Equivalence_PreOrder {R} `(E:Equivalence R) : PreOrder R | 10 := { }. (** We can now define antisymmetry w.r.t. an equivalence relation on the carrier. *) Class Antisymmetric eqA `{equ : Equivalence eqA} (R : relation A) := antisymmetry : forall {x y}, R x y -> R y x -> eqA x y. Class subrelation (R R' : relation A) : Prop := is_subrelation : forall {x y}, R x y -> R' x y. (** Any symmetric relation is equal to its inverse. *) Lemma subrelation_symmetric R `(Symmetric R) : subrelation (flip R) R. Proof. hnf. intros x y H0. red in H0. apply symmetry. assumption. Qed. Section flip. Lemma flip_Reflexive `{Reflexive R} : Reflexive (flip R). Proof. tauto. Qed. Program Definition flip_Irreflexive `(Irreflexive R) : Irreflexive (flip R) := irreflexivity (R:=R). Program Definition flip_Symmetric `(Symmetric R) : Symmetric (flip R) := fun x y H => symmetry (R:=R) H. Program Definition flip_Asymmetric `(Asymmetric R) : Asymmetric (flip R) := fun x y H H' => asymmetry (R:=R) H H'. Program Definition flip_Transitive `(Transitive R) : Transitive (flip R) := fun x y z H H' => transitivity (R:=R) H' H. Program Lemma flip_Antisymmetric `(Antisymmetric eqA R) : Antisymmetric eqA (flip R). Proof. firstorder. Qed. (** Inversing the larger structures *) Lemma flip_PreOrder `(PreOrder R) : PreOrder (flip R). Proof. firstorder. Qed. Lemma flip_StrictOrder `(StrictOrder R) : StrictOrder (flip R). Proof. firstorder. Qed. Lemma flip_PER `(PER R) : PER (flip R). Proof. firstorder. Qed. Lemma flip_Equivalence `(Equivalence R) : Equivalence (flip R). Proof. firstorder. Qed. End flip. Section complement. Lemma complement_Irreflexive `(Reflexive R) : Irreflexive (complement R). Proof. firstorder. Qed. Lemma complement_Symmetric `(Symmetric R) : Symmetric (complement R). Proof. firstorder. Qed. End complement. (** Rewrite relation on a given support: declares a relation as a rewrite relation for use by the generalized rewriting tactic. It helps choosing if a rewrite should be handled by the generalized or the regular rewriting tactic using leibniz equality. Users can declare an [RewriteRelation A RA] anywhere to declare default relations on a given type `A`. This is also done automatically by the [Declare Relation A RA] commands. It has no mode declaration: it will assign `?A := Prop, ?R := iff` on an entirely unspecified query `RewriteRelation ?A ?R`, or any prefered rewrite relation of priority < 2. *) Class RewriteRelation (RA : relation A). (** Leibniz equality. *) Section Leibniz. Global Instance eq_Reflexive : Reflexive (@eq A) := @eq_refl A. Global Instance eq_Symmetric : Symmetric (@eq A) := @eq_sym A. Global Instance eq_Transitive : Transitive (@eq A) := @eq_trans A. (** Leibinz equality [eq] is an equivalence relation. The instance has low priority as it is always applicable if only the type is constrained. *) Global Program Instance eq_equivalence : Equivalence (@eq A) | 10. End Leibniz. (** Leibniz disequality. *) Section LeibnizNot. (** Disequality is symmetric. *) Global Instance neq_Symmetric : Symmetric (fun x y : A => x <> y) := (@not_eq_sym A). End LeibnizNot. End Defs. (** Default rewrite relations handled by [setoid_rewrite] on Prop. *) #[global] Instance inverse_impl_rewrite_relation : RewriteRelation (flip impl) | 3 := {}. #[global] Instance impl_rewrite_relation : RewriteRelation impl | 3 := {}. #[global] Instance iff_rewrite_relation : RewriteRelation iff | 2 := {}. (** Any [Equivalence] declared in the context is automatically considered a rewrite relation. This only applies if the relation is at least partially defined: setoid_rewrite won't try to infer arbitrary user rewrite relations. *) Definition equivalence_rewrite_relation `(eqa : Equivalence A eqA) : RewriteRelation eqA := Build_RewriteRelation _. Ltac equiv_rewrite_relation R := tryif is_evar R then fail else class_apply equivalence_rewrite_relation. #[global] Hint Extern 10 (@RewriteRelation ?A ?R) => equiv_rewrite_relation R : typeclass_instances. (** Hints to drive the typeclass resolution avoiding loops due to the use of full unification. *) #[global] Hint Extern 1 (Reflexive (complement _)) => class_apply @irreflexivity : typeclass_instances. #[global] Hint Extern 3 (Symmetric (complement _)) => class_apply complement_Symmetric : typeclass_instances. #[global] Hint Extern 3 (Irreflexive (complement _)) => class_apply complement_Irreflexive : typeclass_instances. #[global] Hint Extern 3 (Reflexive (flip _)) => apply flip_Reflexive : typeclass_instances. #[global] Hint Extern 3 (Irreflexive (flip _)) => class_apply flip_Irreflexive : typeclass_instances. #[global] Hint Extern 3 (Symmetric (flip _)) => class_apply flip_Symmetric : typeclass_instances. #[global] Hint Extern 3 (Asymmetric (flip _)) => class_apply flip_Asymmetric : typeclass_instances. #[global] Hint Extern 3 (Antisymmetric (flip _)) => class_apply flip_Antisymmetric : typeclass_instances. #[global] Hint Extern 3 (Transitive (flip _)) => class_apply flip_Transitive : typeclass_instances. #[global] Hint Extern 3 (StrictOrder (flip _)) => class_apply flip_StrictOrder : typeclass_instances. #[global] Hint Extern 3 (PreOrder (flip _)) => class_apply flip_PreOrder : typeclass_instances. #[global] Hint Extern 4 (subrelation (flip _) _) => class_apply @subrelation_symmetric : typeclass_instances. Arguments irreflexivity {A R Irreflexive} [x] _ : rename. Arguments symmetry {A} {R} {_} [x] [y] _. Arguments asymmetry {A} {R} {_} [x] [y] _ _. Arguments transitivity {A} {R} {_} [x] [y] [z] _ _. Arguments Antisymmetric A eqA {_} _. #[global] Create HintDb ord. #[global] Hint Resolve irreflexivity : ord. Unset Implicit Arguments. Ltac solve_relation := match goal with | [ |- ?R ?x ?x ] => reflexivity | [ H : ?R ?x ?y |- ?R ?y ?x ] => symmetry ; exact H end. #[global] Create HintDb relations. #[global] Hint Extern 4 => solve_relation : relations. (** We can already dualize all these properties. *) (** * Standard instances. *) Ltac reduce_hyp H := match type of H with | context [ _ <-> _ ] => fail 1 | _ => red in H ; try reduce_hyp H end. Ltac reduce_goal := match goal with | [ |- _ <-> _ ] => fail 1 | _ => red ; intros ; try reduce_goal end. Tactic Notation "reduce" "in" hyp(Hid) := reduce_hyp Hid. Ltac reduce := reduce_goal. Tactic Notation "apply" "*" constr(t) := first [ refine t | refine (t _) | refine (t _ _) | refine (t _ _ _) | refine (t _ _ _ _) | refine (t _ _ _ _ _) | refine (t _ _ _ _ _ _) | refine (t _ _ _ _ _ _ _) ]. Ltac simpl_relation := unfold flip, impl, arrow ; try reduce ; program_simpl ; try ( solve [ dintuition auto with relations ]). Local Obligation Tactic := try solve [ simpl_relation ]. (** Logical implication. *) #[global] Program Instance impl_Reflexive : Reflexive impl. #[global] Program Instance impl_Transitive : Transitive impl. (** Logical equivalence. *) #[global] Instance iff_Reflexive : Reflexive iff := iff_refl. #[global] Instance iff_Symmetric : Symmetric iff := iff_sym. #[global] Instance iff_Transitive : Transitive iff := iff_trans. (** Logical equivalence [iff] is an equivalence relation. *) #[global] Program Instance iff_equivalence : Equivalence iff. (** We now develop a generalization of results on relations for arbitrary predicates. The resulting theory can be applied to homogeneous binary relations but also to arbitrary n-ary predicates. *) Local Open Scope list_scope. (** A compact representation of non-dependent arities, with the codomain singled-out. *) (* Note, we do not use [list Type] because it imposes unnecessary universe constraints *) Inductive Tlist : Type := Tnil : Tlist | Tcons : Type -> Tlist -> Tlist. Local Infix "::" := Tcons. Fixpoint arrows (l : Tlist) (r : Type) : Type := match l with | Tnil => r | A :: l' => A -> arrows l' r end. (** We can define abbreviations for operation and relation types based on [arrows]. *) Definition unary_operation A := arrows (A::Tnil) A. Definition binary_operation A := arrows (A::A::Tnil) A. Definition ternary_operation A := arrows (A::A::A::Tnil) A. (** We define n-ary [predicate]s as functions into [Prop]. *) Abbreviation predicate l := (arrows l Prop). (** Unary predicates, or sets. *) Definition unary_predicate A := predicate (A::Tnil). (** Homogeneous binary relations, equivalent to [relation A]. *) Definition binary_relation A := predicate (A::A::Tnil). (** We can close a predicate by universal or existential quantification. *) Fixpoint predicate_all (l : Tlist) : predicate l -> Prop := match l with | Tnil => fun f => f | A :: tl => fun f => forall x : A, predicate_all tl (f x) end. Fixpoint predicate_exists (l : Tlist) : predicate l -> Prop := match l with | Tnil => fun f => f | A :: tl => fun f => exists x : A, predicate_exists tl (f x) end. (** Pointwise extension of a binary operation on [T] to a binary operation on functions whose codomain is [T]. For an operator on [Prop] this lifts the operator to a binary operation. *) Fixpoint pointwise_extension {T : Type} (op : binary_operation T) (l : Tlist) : binary_operation (arrows l T) := match l with | Tnil => fun R R' => op R R' | A :: tl => fun R R' => fun x => pointwise_extension op tl (R x) (R' x) end. (** Pointwise lifting, equivalent to doing [pointwise_extension] and closing using [predicate_all]. *) Fixpoint pointwise_lifting (op : binary_relation Prop) (l : Tlist) : binary_relation (predicate l) := match l with | Tnil => fun R R' => op R R' | A :: tl => fun R R' => forall x, pointwise_lifting op tl (R x) (R' x) end. (** The n-ary equivalence relation, defined by lifting the 0-ary [iff] relation. *) Definition predicate_equivalence {l : Tlist} : binary_relation (predicate l) := pointwise_lifting iff l. (** The n-ary implication relation, defined by lifting the 0-ary [impl] relation. *) Definition predicate_implication {l : Tlist} := pointwise_lifting impl l. (** Notations for pointwise equivalence and implication of predicates. *) Declare Scope predicate_scope. Infix "<βˆ™>" := predicate_equivalence (at level 95, no associativity) : predicate_scope. Infix "-βˆ™>" := predicate_implication (at level 70, right associativity) : predicate_scope. Local Open Scope predicate_scope. (** The pointwise liftings of conjunction and disjunctions. Note that these are [binary_operation]s, building new relations out of old ones. *) Definition predicate_intersection := pointwise_extension and. Definition predicate_union := pointwise_extension or. Infix "/βˆ™\" := predicate_intersection (at level 80, right associativity) : predicate_scope. Infix "\βˆ™/" := predicate_union (at level 85, right associativity) : predicate_scope. (** The always [True] and always [False] predicates. *) Fixpoint true_predicate {l : Tlist} : predicate l := match l with | Tnil => True | A :: tl => fun _ => @true_predicate tl end. Fixpoint false_predicate {l : Tlist} : predicate l := match l with | Tnil => False | A :: tl => fun _ => @false_predicate tl end. Notation "βˆ™βŠ€βˆ™" := true_predicate : predicate_scope. Notation "βˆ™βŠ₯βˆ™" := false_predicate : predicate_scope. (** Predicate equivalence is an equivalence, and predicate implication defines a preorder. *) #[global] Program Instance predicate_equivalence_equivalence {l} : Equivalence (@predicate_equivalence l). Next Obligation. intro l; induction l ; firstorder. Qed. Next Obligation. intro l; induction l ; firstorder. Qed. Next Obligation. intro l. fold pointwise_lifting. induction l as [|T l IHl]. - firstorder. - intros x y z H H0 x0. pose (IHl (x x0) (y x0) (z x0)). firstorder. Qed. #[global] Program Instance predicate_implication_preorder {l} : PreOrder (@predicate_implication l). Next Obligation. intro l; induction l ; firstorder. Qed. Next Obligation. intro l. induction l as [|T l IHl]. - firstorder. - intros x y z H H0 x0. pose (IHl (x x0) (y x0) (z x0)). firstorder. Qed. (** We define the various operations which define the algebra on binary relations, from the general ones. *) Section Binary. Context {A : Type}. Definition relation_equivalence : relation (relation A) := @predicate_equivalence (_::_::Tnil). Global Instance relation_equivalence_rewrite_relation: RewriteRelation relation_equivalence := {}. Definition relation_conjunction (R : relation A) (R' : relation A) : relation A := @predicate_intersection (A::A::Tnil) R R'. Definition relation_disjunction (R : relation A) (R' : relation A) : relation A := @predicate_union (A::A::Tnil) R R'. (** Relation equivalence is an equivalence, and subrelation defines a partial order. *) Global Instance relation_equivalence_equivalence : Equivalence relation_equivalence. Proof. exact (@predicate_equivalence_equivalence (A::A::Tnil)). Qed. Global Instance relation_implication_preorder : PreOrder (@subrelation A). Proof. exact (@predicate_implication_preorder (A::A::Tnil)). Qed. (** *** Partial Order. A partial order is a preorder which is additionally antisymmetric. We give an equivalent definition, up-to an equivalence relation on the carrier. *) Class PartialOrder eqA `{equ : Equivalence A eqA} R `{preo : PreOrder A R} := partial_order_equivalence : relation_equivalence eqA (relation_conjunction R (flip R)). (** The equivalence proof is sufficient for proving that [R] must be a morphism for equivalence (see Morphisms). It is also sufficient to show that [R] is antisymmetric w.r.t. [eqA] *) Global Instance partial_order_antisym `(PartialOrder eqA R) : Antisymmetric A eqA R. Proof with auto. reduce_goal. pose proof partial_order_equivalence as poe. do 3 red in poe. apply <- poe. firstorder. Qed. Lemma PartialOrder_inverse `(PartialOrder eqA R) : PartialOrder eqA (flip R). Proof. firstorder. Qed. End Binary. #[global] Hint Extern 3 (PartialOrder (flip _)) => class_apply PartialOrder_inverse : typeclass_instances. (** The partial order defined by subrelation and relation equivalence. *) #[global] Program Instance subrelation_partial_order {A} : PartialOrder (@relation_equivalence A) subrelation. Next Obligation. Proof. unfold relation_equivalence in *. compute; firstorder. Qed. Global Typeclasses Opaque arrows predicate_implication predicate_equivalence relation_equivalence pointwise_lifting. (* Register bindings for the generalized rewriting tactic *) Register relation as rewrite.prop.relation. Register subrelation as rewrite.prop.subrelation. Register Reflexive as rewrite.prop.Reflexive. Register reflexivity as rewrite.prop.reflexivity. Register Symmetric as rewrite.prop.Symmetric. Register symmetry as rewrite.prop.symmetry. Register Transitive as rewrite.prop.Transitive. Register transitivity as rewrite.prop.transitivity. rocq-9.2.0/theories/Corelib/Classes/SetoidTactics.v000066400000000000000000000146271516144147600222400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ?R' => red ; intros ; subst ; red_subst_eq_morphism R' | ?R ==> ?R' => red ; intros ; red_subst_eq_morphism R' | _ => idtac end. Ltac destruct_proper := match goal with | [ |- @Proper ?A ?R ?m ] => red end. Ltac reverse_arrows x := match x with | @Logic.eq ?A ==> ?R' => revert_last ; reverse_arrows R' | ?R ==> ?R' => do 3 revert_last ; reverse_arrows R' | _ => idtac end. Ltac default_add_morphism_tactic := unfold flip ; intros ; (try destruct_proper) ; match goal with | [ |- (?x ==> ?y) _ _ ] => red_subst_eq_morphism (x ==> y) ; reverse_arrows (x ==> y) end. Ltac add_morphism_tactic := default_add_morphism_tactic. #[global] Obligation Tactic := program_simpl. #[export] Obligation Tactic := program_simpl. (* Notation "'Morphism' s t " := (@Proper _ (s%signature) t) (at level 10, s at next level, t at next level). *) rocq-9.2.0/theories/Corelib/Compat/000077500000000000000000000000001516144147600171235ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Compat/Coq818.v000066400000000000000000000015001516144147600202710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prim2SF (SF2Prim x) = x. Theorem Prim2SF_inj : forall x y, Prim2SF x = Prim2SF y -> x = y. intros. rewrite <- SF2Prim_Prim2SF. symmetry. rewrite <- SF2Prim_Prim2SF. now rewrite H. Qed. Theorem SF2Prim_inj : forall x y, SF2Prim x = SF2Prim y -> valid_binary x = true -> valid_binary y = true -> x = y. intros. rewrite <- Prim2SF_SF2Prim by assumption. symmetry. rewrite <- Prim2SF_SF2Prim by assumption. rewrite H. reflexivity. Qed. Axiom opp_spec : forall x, Prim2SF (-x)%float = SFopp (Prim2SF x). Axiom abs_spec : forall x, Prim2SF (abs x) = SFabs (Prim2SF x). Axiom eqb_spec : forall x y, (x =? y)%float = SFeqb (Prim2SF x) (Prim2SF y). Axiom ltb_spec : forall x y, (x FNotComparable | Some Eq => FEq | Some Lt => FLt | Some Gt => FGt end. Axiom compare_spec : forall x y, (x ?= y)%float = flatten_cmp_opt (SFcompare (Prim2SF x) (Prim2SF y)). Module Leibniz. Axiom eqb_spec : forall x y, Leibniz.eqb x y = true <-> x = y. End Leibniz. Axiom classify_spec : forall x, classify x = SF64classify (Prim2SF x). Axiom mul_spec : forall x y, Prim2SF (x * y)%float = SF64mul (Prim2SF x) (Prim2SF y). Axiom add_spec : forall x y, Prim2SF (x + y)%float = SF64add (Prim2SF x) (Prim2SF y). Axiom sub_spec : forall x y, Prim2SF (x - y)%float = SF64sub (Prim2SF x) (Prim2SF y). Axiom div_spec : forall x y, Prim2SF (x / y)%float = SF64div (Prim2SF x) (Prim2SF y). Axiom sqrt_spec : forall x, Prim2SF (sqrt x) = SF64sqrt (Prim2SF x). Axiom of_uint63_spec : forall n, Prim2SF (of_uint63 n) = binary_normalize prec emax (to_Z n) Z0 false. Axiom normfr_mantissa_spec : forall f, to_Z (normfr_mantissa f) = Z.of_N (SFnormfr_mantissa prec (Prim2SF f)). Axiom frshiftexp_spec : forall f, let (m,e) := frshiftexp f in (Prim2SF m, Z.sub (to_Z e) shift) = SFfrexp prec emax (Prim2SF f). Axiom ldshiftexp_spec : forall f e, Prim2SF (ldshiftexp f e) = SFldexp prec emax (Prim2SF f) (Z.sub (to_Z e) shift). Axiom next_up_spec : forall x, Prim2SF (next_up x) = SF64succ (Prim2SF x). Axiom next_down_spec : forall x, Prim2SF (next_down x) = SF64pred (Prim2SF x). rocq-9.2.0/theories/Corelib/Floats/FloatClass.v000066400000000000000000000014141516144147600213520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* S754_finite (get_sign f) p e' | Zneg _ | Z0 => S754_zero false (* must never occur *) end. Definition SF2Prim ef := match ef with | S754_nan => nan | S754_zero false => zero | S754_zero true => neg_zero | S754_infinity false => infinity | S754_infinity true => neg_infinity | S754_finite s m e => let pm := of_uint63 (of_Z (Zpos m)) in let f := Z.ldexp pm e in if s then (-f)%float else f end. rocq-9.2.0/theories/Corelib/Floats/PrimFloat.v000066400000000000000000000124641516144147600212230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* xH | xO p => Pos.succ (digits2_pos p) | xI p => Pos.succ (digits2_pos p) end. Definition Zdigits2 n := match n with | Z0 => n | Zpos p => Zpos (digits2_pos p) | Zneg p => Zpos (digits2_pos p) end. End Zdigits2. Section ValidBinary. Definition canonical_mantissa m e := Z.eqb (fexp (Z.add (Zpos (digits2_pos m)) e)) e. Definition bounded m e := andb (canonical_mantissa m e) (Z.leb e (Z.sub emax prec)). Definition valid_binary x := match x with | S754_finite _ m e => bounded m e | _ => true end. End ValidBinary. Section Iter. Context {A : Type}. Variable (f : A -> A). Fixpoint iter_pos (n : positive) (x : A) {struct n} : A := match n with | xI n' => iter_pos n' (iter_pos n' (f x)) | xO n' => iter_pos n' (iter_pos n' x) | xH => f x end. End Iter. Section Rounding. Inductive location := loc_Exact | loc_Inexact : comparison -> location. Record shr_record := { shr_m : Z ; shr_r : bool ; shr_s : bool }. Definition shr_1 mrs := let '(Build_shr_record m r s) := mrs in let s := orb r s in match m with | Z0 => Build_shr_record Z0 false s | Zpos xH => Build_shr_record Z0 true s | Zpos (xO p) => Build_shr_record (Zpos p) false s | Zpos (xI p) => Build_shr_record (Zpos p) true s | Zneg xH => Build_shr_record Z0 true s | Zneg (xO p) => Build_shr_record (Zneg p) false s | Zneg (xI p) => Build_shr_record (Zneg p) true s end. Definition loc_of_shr_record mrs := match mrs with | Build_shr_record _ false false => loc_Exact | Build_shr_record _ false true => loc_Inexact Lt | Build_shr_record _ true false => loc_Inexact Eq | Build_shr_record _ true true => loc_Inexact Gt end. Definition shr_record_of_loc m l := match l with | loc_Exact => Build_shr_record m false false | loc_Inexact Lt => Build_shr_record m false true | loc_Inexact Eq => Build_shr_record m true false | loc_Inexact Gt => Build_shr_record m true true end. Definition shr mrs e n := match n with | Zpos p => (iter_pos shr_1 p mrs, Z.add e n) | _ => (mrs, e) end. Definition shr_fexp m e l := shr (shr_record_of_loc m l) e (Z.sub (fexp (Z.add (Zdigits2 m) e)) e). Definition round_nearest_even mx lx := match lx with | loc_Exact => mx | loc_Inexact Lt => mx | loc_Inexact Eq => if Z.even mx then mx else Z.add mx (Zpos 1) | loc_Inexact Gt => Z.add mx (Zpos 1) end. Definition binary_round_aux sx mx ex lx := let '(mrs', e') := shr_fexp mx ex lx in let '(mrs'', e'') := shr_fexp (round_nearest_even (shr_m mrs') (loc_of_shr_record mrs')) e' loc_Exact in match shr_m mrs'' with | Z0 => S754_zero sx | Zpos m => if Z.leb e'' (Z.sub emax prec) then S754_finite sx m e'' else S754_infinity sx | _ => S754_nan end. Definition shl_align mx ex ex' := match Z.sub ex' ex with | Zneg d => (Pos.iter xO mx d, ex') | _ => (mx, ex) end. Definition binary_round sx mx ex := let '(mz, ez) := shl_align mx ex (fexp (Z.add (Zpos (digits2_pos mx)) ex))in binary_round_aux sx (Zpos mz) ez loc_Exact. Definition binary_normalize m e szero := match m with | Z0 => S754_zero szero | Zpos m => binary_round false m e | Zneg m => binary_round true m e end. End Rounding. (** ** Define operations *) Definition SFopp x := match x with | S754_nan => S754_nan | S754_infinity sx => S754_infinity (negb sx) | S754_finite sx mx ex => S754_finite (negb sx) mx ex | S754_zero sx => S754_zero (negb sx) end. Definition SFabs x := match x with | S754_nan => S754_nan | S754_infinity sx => S754_infinity false | S754_finite sx mx ex => S754_finite false mx ex | S754_zero sx => S754_zero false end. Definition SFcompare f1 f2 := match f1, f2 with | S754_nan , _ | _, S754_nan => None | S754_infinity s1, S754_infinity s2 => Some match s1, s2 with | true, true => Eq | false, false => Eq | true, false => Lt | false, true => Gt end | S754_infinity s, _ => Some (if s then Lt else Gt) | _, S754_infinity s => Some (if s then Gt else Lt) | S754_finite s _ _, S754_zero _ => Some (if s then Lt else Gt) | S754_zero _, S754_finite s _ _ => Some (if s then Gt else Lt) | S754_zero _, S754_zero _ => Some Eq | S754_finite s1 m1 e1, S754_finite s2 m2 e2 => Some match s1, s2 with | true, false => Lt | false, true => Gt | false, false => match Z.compare e1 e2 with | Lt => Lt | Gt => Gt | Eq => Pos.compare_cont Eq m1 m2 end | true, true => match Z.compare e1 e2 with | Lt => Gt | Gt => Lt | Eq => CompOpp (Pos.compare_cont Eq m1 m2) end end end. Definition SFeqb f1 f2 := match SFcompare f1 f2 with | Some Eq => true | _ => false end. Definition SFltb f1 f2 := match SFcompare f1 f2 with | Some Lt => true | _ => false end. Definition SFleb f1 f2 := match SFcompare f1 f2 with | Some (Lt | Eq) => true | _ => false end. Definition SFclassify f := match f with | S754_nan => NaN | S754_infinity false => PInf | S754_infinity true => NInf | S754_zero false => PZero | S754_zero true => NZero | S754_finite false m _ => if Z.eqb (Zpos (digits2_pos m)) prec then PNormal else PSubn | S754_finite true m _ => if Z.eqb (Zpos (digits2_pos m)) prec then NNormal else NSubn end. Definition SFmul x y := match x, y with | S754_nan, _ | _, S754_nan => S754_nan | S754_infinity sx, S754_infinity sy => S754_infinity (xorb sx sy) | S754_infinity sx, S754_finite sy _ _ => S754_infinity (xorb sx sy) | S754_finite sx _ _, S754_infinity sy => S754_infinity (xorb sx sy) | S754_infinity _, S754_zero _ => S754_nan | S754_zero _, S754_infinity _ => S754_nan | S754_finite sx _ _, S754_zero sy => S754_zero (xorb sx sy) | S754_zero sx, S754_finite sy _ _ => S754_zero (xorb sx sy) | S754_zero sx, S754_zero sy => S754_zero (xorb sx sy) | S754_finite sx mx ex, S754_finite sy my ey => binary_round_aux (xorb sx sy) (Zpos (Pos.mul mx my)) (Z.add ex ey) loc_Exact end. Definition cond_Zopp (b : bool) m := if b then Z.opp m else m. Definition SFadd x y := match x, y with | S754_nan, _ | _, S754_nan => S754_nan | S754_infinity sx, S754_infinity sy => match sx, sy with true, true | false, false => x | _, _ => S754_nan end | S754_infinity _, _ => x | _, S754_infinity _ => y | S754_zero sx, S754_zero sy => match sx, sy with true, true | false, false => x | _, _ => S754_zero false end | S754_zero _, _ => y | _, S754_zero _ => x | S754_finite sx mx ex, S754_finite sy my ey => let ez := Z.min ex ey in binary_normalize (Z.add (cond_Zopp sx (Zpos (fst (shl_align mx ex ez)))) (cond_Zopp sy (Zpos (fst (shl_align my ey ez))))) ez false end. Definition SFsub x y := match x, y with | S754_nan, _ | _, S754_nan => S754_nan | S754_infinity sx, S754_infinity sy => match sx, sy with true, false | false, true => x | _, _ => S754_nan end | S754_infinity _, _ => x | _, S754_infinity sy => S754_infinity (negb sy) | S754_zero sx, S754_zero sy => match sx, sy with true, false | false, true => x | _, _ => S754_zero false end | S754_zero _, S754_finite sy my ey => S754_finite (negb sy) my ey | _, S754_zero _ => x | S754_finite sx mx ex, S754_finite sy my ey => let ez := Z.min ex ey in binary_normalize (Z.sub (cond_Zopp sx (Zpos (fst (shl_align mx ex ez)))) (cond_Zopp sy (Zpos (fst (shl_align my ey ez))))) ez false end. Definition new_location_even nb_steps k := if Z.eqb k Z0 then loc_Exact else loc_Inexact (Z.compare (Z.mul (Zpos 2) k) nb_steps). Definition new_location_odd nb_steps k := if Z.eqb k Z0 then loc_Exact else loc_Inexact match Z.compare (Z.add (Z.mul (Zpos 2) k) (Zpos 1)) nb_steps with | Lt => Lt | Eq => Lt | Gt => Gt end. Definition new_location nb_steps := if Z.even nb_steps then new_location_even nb_steps else new_location_odd nb_steps. Definition SFdiv_core_binary m1 e1 m2 e2 := let d1 := Zdigits2 m1 in let d2 := Zdigits2 m2 in let e' := Z.min (fexp (Z.sub (Z.add d1 e1) (Z.add d2 e2))) (Z.sub e1 e2) in let s := Z.sub (Z.sub e1 e2) e' in let m' := match s with | Zpos _ => Z.shiftl m1 s | Z0 => m1 | Zneg _ => Z0 end in let '(q, r) := Z.div_eucl m' m2 in (q, e', new_location m2 r). Definition SFdiv x y := match x, y with | S754_nan, _ | _, S754_nan => S754_nan | S754_infinity sx, S754_infinity sy => S754_nan | S754_infinity sx, S754_finite sy _ _ => S754_infinity (xorb sx sy) | S754_finite sx _ _, S754_infinity sy => S754_zero (xorb sx sy) | S754_infinity sx, S754_zero sy => S754_infinity (xorb sx sy) | S754_zero sx, S754_infinity sy => S754_zero (xorb sx sy) | S754_finite sx _ _, S754_zero sy => S754_infinity (xorb sx sy) | S754_zero sx, S754_finite sy _ _ => S754_zero (xorb sx sy) | S754_zero sx, S754_zero sy => S754_nan | S754_finite sx mx ex, S754_finite sy my ey => let '(mz, ez, lz) := SFdiv_core_binary (Zpos mx) ex (Zpos my) ey in binary_round_aux (xorb sx sy) mz ez lz end. Definition SFsqrt_core_binary m e := let d := Zdigits2 m in let e' := Z.min (fexp (Z.div2 (Z.add (Z.add d e) (Zpos 1)))) (Z.div2 e) in let s := Z.sub e (Z.mul (Zpos 2) e') in let m' := match s with | Zpos p => Z.shiftl m s | Z0 => m | Zneg _ => Z0 end in let (q, r) := Z.sqrtrem m' in let l := if Z.eqb r Z0 then loc_Exact else loc_Inexact (if Z.leb r q then Lt else Gt) in (q, e', l). Definition SFsqrt x := match x with | S754_nan => S754_nan | S754_infinity false => x | S754_infinity true => S754_nan | S754_finite true _ _ => S754_nan | S754_zero _ => x | S754_finite false mx ex => let '(mz, ez, lz) := SFsqrt_core_binary (Zpos mx) ex in binary_round_aux false mz ez lz end. Definition SFnormfr_mantissa f := match f with | S754_finite _ mx ex => if Z.eqb ex (Z.opp prec) then Npos mx else N0 | _ => N0 end. Definition SFldexp f e := match f with | S754_finite sx mx ex => binary_round sx mx (Z.add ex e) | _ => f end. Definition SFfrexp f := match f with | S754_finite sx mx ex => if Z.leb prec (Zpos (digits2_pos mx)) then (S754_finite sx mx (Z.opp prec), Z.add ex prec) else let d := Z.sub prec (Zpos (digits2_pos mx)) in (S754_finite sx (Pos.iter xO mx (Z.to_pos d)) (Z.opp prec), Z.sub (Z.add ex prec) d) | _ => (f, Z.sub (Z.mul (Zneg 2) emax) prec) end. Definition SFone := binary_round false 1 Z0. Definition SFulp x := SFldexp SFone (fexp (snd (SFfrexp x))). Definition SFpred_pos x := match x with | S754_finite _ mx _ => let d := if Pos.eqb mx~0 (Pos.iter xO xH (Z.to_pos prec)) then SFldexp SFone (fexp (Z.sub (snd (SFfrexp x)) (Zpos 1))) else SFulp x in SFsub x d | _ => x end. Definition SFmax_float := S754_finite false (Pos.sub (Pos.iter xO xH (Z.to_pos prec)) 1) (Z.sub emax prec). Definition SFsucc x := match x with | S754_zero _ => SFldexp SFone emin | S754_infinity false => x | S754_infinity true => SFopp SFmax_float | S754_nan => x | S754_finite false _ _ => SFadd x (SFulp x) | S754_finite true _ _ => SFopp (SFpred_pos (SFopp x)) end. Definition SFpred f := SFopp (SFsucc (SFopp f)). End FloatOps. rocq-9.2.0/theories/Corelib/Init/000077500000000000000000000000001516144147600166035ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Init/Byte.v000066400000000000000000000631061516144147600177030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* x00 | (1,(0,(0,(0,(0,(0,(0,0))))))) => x01 | (0,(1,(0,(0,(0,(0,(0,0))))))) => x02 | (1,(1,(0,(0,(0,(0,(0,0))))))) => x03 | (0,(0,(1,(0,(0,(0,(0,0))))))) => x04 | (1,(0,(1,(0,(0,(0,(0,0))))))) => x05 | (0,(1,(1,(0,(0,(0,(0,0))))))) => x06 | (1,(1,(1,(0,(0,(0,(0,0))))))) => x07 | (0,(0,(0,(1,(0,(0,(0,0))))))) => x08 | (1,(0,(0,(1,(0,(0,(0,0))))))) => x09 | (0,(1,(0,(1,(0,(0,(0,0))))))) => x0a | (1,(1,(0,(1,(0,(0,(0,0))))))) => x0b | (0,(0,(1,(1,(0,(0,(0,0))))))) => x0c | (1,(0,(1,(1,(0,(0,(0,0))))))) => x0d | (0,(1,(1,(1,(0,(0,(0,0))))))) => x0e | (1,(1,(1,(1,(0,(0,(0,0))))))) => x0f | (0,(0,(0,(0,(1,(0,(0,0))))))) => x10 | (1,(0,(0,(0,(1,(0,(0,0))))))) => x11 | (0,(1,(0,(0,(1,(0,(0,0))))))) => x12 | (1,(1,(0,(0,(1,(0,(0,0))))))) => x13 | (0,(0,(1,(0,(1,(0,(0,0))))))) => x14 | (1,(0,(1,(0,(1,(0,(0,0))))))) => x15 | (0,(1,(1,(0,(1,(0,(0,0))))))) => x16 | (1,(1,(1,(0,(1,(0,(0,0))))))) => x17 | (0,(0,(0,(1,(1,(0,(0,0))))))) => x18 | (1,(0,(0,(1,(1,(0,(0,0))))))) => x19 | (0,(1,(0,(1,(1,(0,(0,0))))))) => x1a | (1,(1,(0,(1,(1,(0,(0,0))))))) => x1b | (0,(0,(1,(1,(1,(0,(0,0))))))) => x1c | (1,(0,(1,(1,(1,(0,(0,0))))))) => x1d | (0,(1,(1,(1,(1,(0,(0,0))))))) => x1e | (1,(1,(1,(1,(1,(0,(0,0))))))) => x1f | (0,(0,(0,(0,(0,(1,(0,0))))))) => x20 | (1,(0,(0,(0,(0,(1,(0,0))))))) => x21 | (0,(1,(0,(0,(0,(1,(0,0))))))) => x22 | (1,(1,(0,(0,(0,(1,(0,0))))))) => x23 | (0,(0,(1,(0,(0,(1,(0,0))))))) => x24 | (1,(0,(1,(0,(0,(1,(0,0))))))) => x25 | (0,(1,(1,(0,(0,(1,(0,0))))))) => x26 | (1,(1,(1,(0,(0,(1,(0,0))))))) => x27 | (0,(0,(0,(1,(0,(1,(0,0))))))) => x28 | (1,(0,(0,(1,(0,(1,(0,0))))))) => x29 | (0,(1,(0,(1,(0,(1,(0,0))))))) => x2a | (1,(1,(0,(1,(0,(1,(0,0))))))) => x2b | (0,(0,(1,(1,(0,(1,(0,0))))))) => x2c | (1,(0,(1,(1,(0,(1,(0,0))))))) => x2d | (0,(1,(1,(1,(0,(1,(0,0))))))) => x2e | (1,(1,(1,(1,(0,(1,(0,0))))))) => x2f | (0,(0,(0,(0,(1,(1,(0,0))))))) => x30 | (1,(0,(0,(0,(1,(1,(0,0))))))) => x31 | (0,(1,(0,(0,(1,(1,(0,0))))))) => x32 | (1,(1,(0,(0,(1,(1,(0,0))))))) => x33 | (0,(0,(1,(0,(1,(1,(0,0))))))) => x34 | (1,(0,(1,(0,(1,(1,(0,0))))))) => x35 | (0,(1,(1,(0,(1,(1,(0,0))))))) => x36 | (1,(1,(1,(0,(1,(1,(0,0))))))) => x37 | (0,(0,(0,(1,(1,(1,(0,0))))))) => x38 | (1,(0,(0,(1,(1,(1,(0,0))))))) => x39 | (0,(1,(0,(1,(1,(1,(0,0))))))) => x3a | (1,(1,(0,(1,(1,(1,(0,0))))))) => x3b | (0,(0,(1,(1,(1,(1,(0,0))))))) => x3c | (1,(0,(1,(1,(1,(1,(0,0))))))) => x3d | (0,(1,(1,(1,(1,(1,(0,0))))))) => x3e | (1,(1,(1,(1,(1,(1,(0,0))))))) => x3f | (0,(0,(0,(0,(0,(0,(1,0))))))) => x40 | (1,(0,(0,(0,(0,(0,(1,0))))))) => x41 | (0,(1,(0,(0,(0,(0,(1,0))))))) => x42 | (1,(1,(0,(0,(0,(0,(1,0))))))) => x43 | (0,(0,(1,(0,(0,(0,(1,0))))))) => x44 | (1,(0,(1,(0,(0,(0,(1,0))))))) => x45 | (0,(1,(1,(0,(0,(0,(1,0))))))) => x46 | (1,(1,(1,(0,(0,(0,(1,0))))))) => x47 | (0,(0,(0,(1,(0,(0,(1,0))))))) => x48 | (1,(0,(0,(1,(0,(0,(1,0))))))) => x49 | (0,(1,(0,(1,(0,(0,(1,0))))))) => x4a | (1,(1,(0,(1,(0,(0,(1,0))))))) => x4b | (0,(0,(1,(1,(0,(0,(1,0))))))) => x4c | (1,(0,(1,(1,(0,(0,(1,0))))))) => x4d | (0,(1,(1,(1,(0,(0,(1,0))))))) => x4e | (1,(1,(1,(1,(0,(0,(1,0))))))) => x4f | (0,(0,(0,(0,(1,(0,(1,0))))))) => x50 | (1,(0,(0,(0,(1,(0,(1,0))))))) => x51 | (0,(1,(0,(0,(1,(0,(1,0))))))) => x52 | (1,(1,(0,(0,(1,(0,(1,0))))))) => x53 | (0,(0,(1,(0,(1,(0,(1,0))))))) => x54 | (1,(0,(1,(0,(1,(0,(1,0))))))) => x55 | (0,(1,(1,(0,(1,(0,(1,0))))))) => x56 | (1,(1,(1,(0,(1,(0,(1,0))))))) => x57 | (0,(0,(0,(1,(1,(0,(1,0))))))) => x58 | (1,(0,(0,(1,(1,(0,(1,0))))))) => x59 | (0,(1,(0,(1,(1,(0,(1,0))))))) => x5a | (1,(1,(0,(1,(1,(0,(1,0))))))) => x5b | (0,(0,(1,(1,(1,(0,(1,0))))))) => x5c | (1,(0,(1,(1,(1,(0,(1,0))))))) => x5d | (0,(1,(1,(1,(1,(0,(1,0))))))) => x5e | (1,(1,(1,(1,(1,(0,(1,0))))))) => x5f | (0,(0,(0,(0,(0,(1,(1,0))))))) => x60 | (1,(0,(0,(0,(0,(1,(1,0))))))) => x61 | (0,(1,(0,(0,(0,(1,(1,0))))))) => x62 | (1,(1,(0,(0,(0,(1,(1,0))))))) => x63 | (0,(0,(1,(0,(0,(1,(1,0))))))) => x64 | (1,(0,(1,(0,(0,(1,(1,0))))))) => x65 | (0,(1,(1,(0,(0,(1,(1,0))))))) => x66 | (1,(1,(1,(0,(0,(1,(1,0))))))) => x67 | (0,(0,(0,(1,(0,(1,(1,0))))))) => x68 | (1,(0,(0,(1,(0,(1,(1,0))))))) => x69 | (0,(1,(0,(1,(0,(1,(1,0))))))) => x6a | (1,(1,(0,(1,(0,(1,(1,0))))))) => x6b | (0,(0,(1,(1,(0,(1,(1,0))))))) => x6c | (1,(0,(1,(1,(0,(1,(1,0))))))) => x6d | (0,(1,(1,(1,(0,(1,(1,0))))))) => x6e | (1,(1,(1,(1,(0,(1,(1,0))))))) => x6f | (0,(0,(0,(0,(1,(1,(1,0))))))) => x70 | (1,(0,(0,(0,(1,(1,(1,0))))))) => x71 | (0,(1,(0,(0,(1,(1,(1,0))))))) => x72 | (1,(1,(0,(0,(1,(1,(1,0))))))) => x73 | (0,(0,(1,(0,(1,(1,(1,0))))))) => x74 | (1,(0,(1,(0,(1,(1,(1,0))))))) => x75 | (0,(1,(1,(0,(1,(1,(1,0))))))) => x76 | (1,(1,(1,(0,(1,(1,(1,0))))))) => x77 | (0,(0,(0,(1,(1,(1,(1,0))))))) => x78 | (1,(0,(0,(1,(1,(1,(1,0))))))) => x79 | (0,(1,(0,(1,(1,(1,(1,0))))))) => x7a | (1,(1,(0,(1,(1,(1,(1,0))))))) => x7b | (0,(0,(1,(1,(1,(1,(1,0))))))) => x7c | (1,(0,(1,(1,(1,(1,(1,0))))))) => x7d | (0,(1,(1,(1,(1,(1,(1,0))))))) => x7e | (1,(1,(1,(1,(1,(1,(1,0))))))) => x7f | (0,(0,(0,(0,(0,(0,(0,1))))))) => x80 | (1,(0,(0,(0,(0,(0,(0,1))))))) => x81 | (0,(1,(0,(0,(0,(0,(0,1))))))) => x82 | (1,(1,(0,(0,(0,(0,(0,1))))))) => x83 | (0,(0,(1,(0,(0,(0,(0,1))))))) => x84 | (1,(0,(1,(0,(0,(0,(0,1))))))) => x85 | (0,(1,(1,(0,(0,(0,(0,1))))))) => x86 | (1,(1,(1,(0,(0,(0,(0,1))))))) => x87 | (0,(0,(0,(1,(0,(0,(0,1))))))) => x88 | (1,(0,(0,(1,(0,(0,(0,1))))))) => x89 | (0,(1,(0,(1,(0,(0,(0,1))))))) => x8a | (1,(1,(0,(1,(0,(0,(0,1))))))) => x8b | (0,(0,(1,(1,(0,(0,(0,1))))))) => x8c | (1,(0,(1,(1,(0,(0,(0,1))))))) => x8d | (0,(1,(1,(1,(0,(0,(0,1))))))) => x8e | (1,(1,(1,(1,(0,(0,(0,1))))))) => x8f | (0,(0,(0,(0,(1,(0,(0,1))))))) => x90 | (1,(0,(0,(0,(1,(0,(0,1))))))) => x91 | (0,(1,(0,(0,(1,(0,(0,1))))))) => x92 | (1,(1,(0,(0,(1,(0,(0,1))))))) => x93 | (0,(0,(1,(0,(1,(0,(0,1))))))) => x94 | (1,(0,(1,(0,(1,(0,(0,1))))))) => x95 | (0,(1,(1,(0,(1,(0,(0,1))))))) => x96 | (1,(1,(1,(0,(1,(0,(0,1))))))) => x97 | (0,(0,(0,(1,(1,(0,(0,1))))))) => x98 | (1,(0,(0,(1,(1,(0,(0,1))))))) => x99 | (0,(1,(0,(1,(1,(0,(0,1))))))) => x9a | (1,(1,(0,(1,(1,(0,(0,1))))))) => x9b | (0,(0,(1,(1,(1,(0,(0,1))))))) => x9c | (1,(0,(1,(1,(1,(0,(0,1))))))) => x9d | (0,(1,(1,(1,(1,(0,(0,1))))))) => x9e | (1,(1,(1,(1,(1,(0,(0,1))))))) => x9f | (0,(0,(0,(0,(0,(1,(0,1))))))) => xa0 | (1,(0,(0,(0,(0,(1,(0,1))))))) => xa1 | (0,(1,(0,(0,(0,(1,(0,1))))))) => xa2 | (1,(1,(0,(0,(0,(1,(0,1))))))) => xa3 | (0,(0,(1,(0,(0,(1,(0,1))))))) => xa4 | (1,(0,(1,(0,(0,(1,(0,1))))))) => xa5 | (0,(1,(1,(0,(0,(1,(0,1))))))) => xa6 | (1,(1,(1,(0,(0,(1,(0,1))))))) => xa7 | (0,(0,(0,(1,(0,(1,(0,1))))))) => xa8 | (1,(0,(0,(1,(0,(1,(0,1))))))) => xa9 | (0,(1,(0,(1,(0,(1,(0,1))))))) => xaa | (1,(1,(0,(1,(0,(1,(0,1))))))) => xab | (0,(0,(1,(1,(0,(1,(0,1))))))) => xac | (1,(0,(1,(1,(0,(1,(0,1))))))) => xad | (0,(1,(1,(1,(0,(1,(0,1))))))) => xae | (1,(1,(1,(1,(0,(1,(0,1))))))) => xaf | (0,(0,(0,(0,(1,(1,(0,1))))))) => xb0 | (1,(0,(0,(0,(1,(1,(0,1))))))) => xb1 | (0,(1,(0,(0,(1,(1,(0,1))))))) => xb2 | (1,(1,(0,(0,(1,(1,(0,1))))))) => xb3 | (0,(0,(1,(0,(1,(1,(0,1))))))) => xb4 | (1,(0,(1,(0,(1,(1,(0,1))))))) => xb5 | (0,(1,(1,(0,(1,(1,(0,1))))))) => xb6 | (1,(1,(1,(0,(1,(1,(0,1))))))) => xb7 | (0,(0,(0,(1,(1,(1,(0,1))))))) => xb8 | (1,(0,(0,(1,(1,(1,(0,1))))))) => xb9 | (0,(1,(0,(1,(1,(1,(0,1))))))) => xba | (1,(1,(0,(1,(1,(1,(0,1))))))) => xbb | (0,(0,(1,(1,(1,(1,(0,1))))))) => xbc | (1,(0,(1,(1,(1,(1,(0,1))))))) => xbd | (0,(1,(1,(1,(1,(1,(0,1))))))) => xbe | (1,(1,(1,(1,(1,(1,(0,1))))))) => xbf | (0,(0,(0,(0,(0,(0,(1,1))))))) => xc0 | (1,(0,(0,(0,(0,(0,(1,1))))))) => xc1 | (0,(1,(0,(0,(0,(0,(1,1))))))) => xc2 | (1,(1,(0,(0,(0,(0,(1,1))))))) => xc3 | (0,(0,(1,(0,(0,(0,(1,1))))))) => xc4 | (1,(0,(1,(0,(0,(0,(1,1))))))) => xc5 | (0,(1,(1,(0,(0,(0,(1,1))))))) => xc6 | (1,(1,(1,(0,(0,(0,(1,1))))))) => xc7 | (0,(0,(0,(1,(0,(0,(1,1))))))) => xc8 | (1,(0,(0,(1,(0,(0,(1,1))))))) => xc9 | (0,(1,(0,(1,(0,(0,(1,1))))))) => xca | (1,(1,(0,(1,(0,(0,(1,1))))))) => xcb | (0,(0,(1,(1,(0,(0,(1,1))))))) => xcc | (1,(0,(1,(1,(0,(0,(1,1))))))) => xcd | (0,(1,(1,(1,(0,(0,(1,1))))))) => xce | (1,(1,(1,(1,(0,(0,(1,1))))))) => xcf | (0,(0,(0,(0,(1,(0,(1,1))))))) => xd0 | (1,(0,(0,(0,(1,(0,(1,1))))))) => xd1 | (0,(1,(0,(0,(1,(0,(1,1))))))) => xd2 | (1,(1,(0,(0,(1,(0,(1,1))))))) => xd3 | (0,(0,(1,(0,(1,(0,(1,1))))))) => xd4 | (1,(0,(1,(0,(1,(0,(1,1))))))) => xd5 | (0,(1,(1,(0,(1,(0,(1,1))))))) => xd6 | (1,(1,(1,(0,(1,(0,(1,1))))))) => xd7 | (0,(0,(0,(1,(1,(0,(1,1))))))) => xd8 | (1,(0,(0,(1,(1,(0,(1,1))))))) => xd9 | (0,(1,(0,(1,(1,(0,(1,1))))))) => xda | (1,(1,(0,(1,(1,(0,(1,1))))))) => xdb | (0,(0,(1,(1,(1,(0,(1,1))))))) => xdc | (1,(0,(1,(1,(1,(0,(1,1))))))) => xdd | (0,(1,(1,(1,(1,(0,(1,1))))))) => xde | (1,(1,(1,(1,(1,(0,(1,1))))))) => xdf | (0,(0,(0,(0,(0,(1,(1,1))))))) => xe0 | (1,(0,(0,(0,(0,(1,(1,1))))))) => xe1 | (0,(1,(0,(0,(0,(1,(1,1))))))) => xe2 | (1,(1,(0,(0,(0,(1,(1,1))))))) => xe3 | (0,(0,(1,(0,(0,(1,(1,1))))))) => xe4 | (1,(0,(1,(0,(0,(1,(1,1))))))) => xe5 | (0,(1,(1,(0,(0,(1,(1,1))))))) => xe6 | (1,(1,(1,(0,(0,(1,(1,1))))))) => xe7 | (0,(0,(0,(1,(0,(1,(1,1))))))) => xe8 | (1,(0,(0,(1,(0,(1,(1,1))))))) => xe9 | (0,(1,(0,(1,(0,(1,(1,1))))))) => xea | (1,(1,(0,(1,(0,(1,(1,1))))))) => xeb | (0,(0,(1,(1,(0,(1,(1,1))))))) => xec | (1,(0,(1,(1,(0,(1,(1,1))))))) => xed | (0,(1,(1,(1,(0,(1,(1,1))))))) => xee | (1,(1,(1,(1,(0,(1,(1,1))))))) => xef | (0,(0,(0,(0,(1,(1,(1,1))))))) => xf0 | (1,(0,(0,(0,(1,(1,(1,1))))))) => xf1 | (0,(1,(0,(0,(1,(1,(1,1))))))) => xf2 | (1,(1,(0,(0,(1,(1,(1,1))))))) => xf3 | (0,(0,(1,(0,(1,(1,(1,1))))))) => xf4 | (1,(0,(1,(0,(1,(1,(1,1))))))) => xf5 | (0,(1,(1,(0,(1,(1,(1,1))))))) => xf6 | (1,(1,(1,(0,(1,(1,(1,1))))))) => xf7 | (0,(0,(0,(1,(1,(1,(1,1))))))) => xf8 | (1,(0,(0,(1,(1,(1,(1,1))))))) => xf9 | (0,(1,(0,(1,(1,(1,(1,1))))))) => xfa | (1,(1,(0,(1,(1,(1,(1,1))))))) => xfb | (0,(0,(1,(1,(1,(1,(1,1))))))) => xfc | (1,(0,(1,(1,(1,(1,(1,1))))))) => xfd | (0,(1,(1,(1,(1,(1,(1,1))))))) => xfe | (1,(1,(1,(1,(1,(1,(1,1))))))) => xff end. Definition to_bits (b : byte) : bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) := match b with | x00 => (0,(0,(0,(0,(0,(0,(0,0))))))) | x01 => (1,(0,(0,(0,(0,(0,(0,0))))))) | x02 => (0,(1,(0,(0,(0,(0,(0,0))))))) | x03 => (1,(1,(0,(0,(0,(0,(0,0))))))) | x04 => (0,(0,(1,(0,(0,(0,(0,0))))))) | x05 => (1,(0,(1,(0,(0,(0,(0,0))))))) | x06 => (0,(1,(1,(0,(0,(0,(0,0))))))) | x07 => (1,(1,(1,(0,(0,(0,(0,0))))))) | x08 => (0,(0,(0,(1,(0,(0,(0,0))))))) | x09 => (1,(0,(0,(1,(0,(0,(0,0))))))) | x0a => (0,(1,(0,(1,(0,(0,(0,0))))))) | x0b => (1,(1,(0,(1,(0,(0,(0,0))))))) | x0c => (0,(0,(1,(1,(0,(0,(0,0))))))) | x0d => (1,(0,(1,(1,(0,(0,(0,0))))))) | x0e => (0,(1,(1,(1,(0,(0,(0,0))))))) | x0f => (1,(1,(1,(1,(0,(0,(0,0))))))) | x10 => (0,(0,(0,(0,(1,(0,(0,0))))))) | x11 => (1,(0,(0,(0,(1,(0,(0,0))))))) | x12 => (0,(1,(0,(0,(1,(0,(0,0))))))) | x13 => (1,(1,(0,(0,(1,(0,(0,0))))))) | x14 => (0,(0,(1,(0,(1,(0,(0,0))))))) | x15 => (1,(0,(1,(0,(1,(0,(0,0))))))) | x16 => (0,(1,(1,(0,(1,(0,(0,0))))))) | x17 => (1,(1,(1,(0,(1,(0,(0,0))))))) | x18 => (0,(0,(0,(1,(1,(0,(0,0))))))) | x19 => (1,(0,(0,(1,(1,(0,(0,0))))))) | x1a => (0,(1,(0,(1,(1,(0,(0,0))))))) | x1b => (1,(1,(0,(1,(1,(0,(0,0))))))) | x1c => (0,(0,(1,(1,(1,(0,(0,0))))))) | x1d => (1,(0,(1,(1,(1,(0,(0,0))))))) | x1e => (0,(1,(1,(1,(1,(0,(0,0))))))) | x1f => (1,(1,(1,(1,(1,(0,(0,0))))))) | x20 => (0,(0,(0,(0,(0,(1,(0,0))))))) | x21 => (1,(0,(0,(0,(0,(1,(0,0))))))) | x22 => (0,(1,(0,(0,(0,(1,(0,0))))))) | x23 => (1,(1,(0,(0,(0,(1,(0,0))))))) | x24 => (0,(0,(1,(0,(0,(1,(0,0))))))) | x25 => (1,(0,(1,(0,(0,(1,(0,0))))))) | x26 => (0,(1,(1,(0,(0,(1,(0,0))))))) | x27 => (1,(1,(1,(0,(0,(1,(0,0))))))) | x28 => (0,(0,(0,(1,(0,(1,(0,0))))))) | x29 => (1,(0,(0,(1,(0,(1,(0,0))))))) | x2a => (0,(1,(0,(1,(0,(1,(0,0))))))) | x2b => (1,(1,(0,(1,(0,(1,(0,0))))))) | x2c => (0,(0,(1,(1,(0,(1,(0,0))))))) | x2d => (1,(0,(1,(1,(0,(1,(0,0))))))) | x2e => (0,(1,(1,(1,(0,(1,(0,0))))))) | x2f => (1,(1,(1,(1,(0,(1,(0,0))))))) | x30 => (0,(0,(0,(0,(1,(1,(0,0))))))) | x31 => (1,(0,(0,(0,(1,(1,(0,0))))))) | x32 => (0,(1,(0,(0,(1,(1,(0,0))))))) | x33 => (1,(1,(0,(0,(1,(1,(0,0))))))) | x34 => (0,(0,(1,(0,(1,(1,(0,0))))))) | x35 => (1,(0,(1,(0,(1,(1,(0,0))))))) | x36 => (0,(1,(1,(0,(1,(1,(0,0))))))) | x37 => (1,(1,(1,(0,(1,(1,(0,0))))))) | x38 => (0,(0,(0,(1,(1,(1,(0,0))))))) | x39 => (1,(0,(0,(1,(1,(1,(0,0))))))) | x3a => (0,(1,(0,(1,(1,(1,(0,0))))))) | x3b => (1,(1,(0,(1,(1,(1,(0,0))))))) | x3c => (0,(0,(1,(1,(1,(1,(0,0))))))) | x3d => (1,(0,(1,(1,(1,(1,(0,0))))))) | x3e => (0,(1,(1,(1,(1,(1,(0,0))))))) | x3f => (1,(1,(1,(1,(1,(1,(0,0))))))) | x40 => (0,(0,(0,(0,(0,(0,(1,0))))))) | x41 => (1,(0,(0,(0,(0,(0,(1,0))))))) | x42 => (0,(1,(0,(0,(0,(0,(1,0))))))) | x43 => (1,(1,(0,(0,(0,(0,(1,0))))))) | x44 => (0,(0,(1,(0,(0,(0,(1,0))))))) | x45 => (1,(0,(1,(0,(0,(0,(1,0))))))) | x46 => (0,(1,(1,(0,(0,(0,(1,0))))))) | x47 => (1,(1,(1,(0,(0,(0,(1,0))))))) | x48 => (0,(0,(0,(1,(0,(0,(1,0))))))) | x49 => (1,(0,(0,(1,(0,(0,(1,0))))))) | x4a => (0,(1,(0,(1,(0,(0,(1,0))))))) | x4b => (1,(1,(0,(1,(0,(0,(1,0))))))) | x4c => (0,(0,(1,(1,(0,(0,(1,0))))))) | x4d => (1,(0,(1,(1,(0,(0,(1,0))))))) | x4e => (0,(1,(1,(1,(0,(0,(1,0))))))) | x4f => (1,(1,(1,(1,(0,(0,(1,0))))))) | x50 => (0,(0,(0,(0,(1,(0,(1,0))))))) | x51 => (1,(0,(0,(0,(1,(0,(1,0))))))) | x52 => (0,(1,(0,(0,(1,(0,(1,0))))))) | x53 => (1,(1,(0,(0,(1,(0,(1,0))))))) | x54 => (0,(0,(1,(0,(1,(0,(1,0))))))) | x55 => (1,(0,(1,(0,(1,(0,(1,0))))))) | x56 => (0,(1,(1,(0,(1,(0,(1,0))))))) | x57 => (1,(1,(1,(0,(1,(0,(1,0))))))) | x58 => (0,(0,(0,(1,(1,(0,(1,0))))))) | x59 => (1,(0,(0,(1,(1,(0,(1,0))))))) | x5a => (0,(1,(0,(1,(1,(0,(1,0))))))) | x5b => (1,(1,(0,(1,(1,(0,(1,0))))))) | x5c => (0,(0,(1,(1,(1,(0,(1,0))))))) | x5d => (1,(0,(1,(1,(1,(0,(1,0))))))) | x5e => (0,(1,(1,(1,(1,(0,(1,0))))))) | x5f => (1,(1,(1,(1,(1,(0,(1,0))))))) | x60 => (0,(0,(0,(0,(0,(1,(1,0))))))) | x61 => (1,(0,(0,(0,(0,(1,(1,0))))))) | x62 => (0,(1,(0,(0,(0,(1,(1,0))))))) | x63 => (1,(1,(0,(0,(0,(1,(1,0))))))) | x64 => (0,(0,(1,(0,(0,(1,(1,0))))))) | x65 => (1,(0,(1,(0,(0,(1,(1,0))))))) | x66 => (0,(1,(1,(0,(0,(1,(1,0))))))) | x67 => (1,(1,(1,(0,(0,(1,(1,0))))))) | x68 => (0,(0,(0,(1,(0,(1,(1,0))))))) | x69 => (1,(0,(0,(1,(0,(1,(1,0))))))) | x6a => (0,(1,(0,(1,(0,(1,(1,0))))))) | x6b => (1,(1,(0,(1,(0,(1,(1,0))))))) | x6c => (0,(0,(1,(1,(0,(1,(1,0))))))) | x6d => (1,(0,(1,(1,(0,(1,(1,0))))))) | x6e => (0,(1,(1,(1,(0,(1,(1,0))))))) | x6f => (1,(1,(1,(1,(0,(1,(1,0))))))) | x70 => (0,(0,(0,(0,(1,(1,(1,0))))))) | x71 => (1,(0,(0,(0,(1,(1,(1,0))))))) | x72 => (0,(1,(0,(0,(1,(1,(1,0))))))) | x73 => (1,(1,(0,(0,(1,(1,(1,0))))))) | x74 => (0,(0,(1,(0,(1,(1,(1,0))))))) | x75 => (1,(0,(1,(0,(1,(1,(1,0))))))) | x76 => (0,(1,(1,(0,(1,(1,(1,0))))))) | x77 => (1,(1,(1,(0,(1,(1,(1,0))))))) | x78 => (0,(0,(0,(1,(1,(1,(1,0))))))) | x79 => (1,(0,(0,(1,(1,(1,(1,0))))))) | x7a => (0,(1,(0,(1,(1,(1,(1,0))))))) | x7b => (1,(1,(0,(1,(1,(1,(1,0))))))) | x7c => (0,(0,(1,(1,(1,(1,(1,0))))))) | x7d => (1,(0,(1,(1,(1,(1,(1,0))))))) | x7e => (0,(1,(1,(1,(1,(1,(1,0))))))) | x7f => (1,(1,(1,(1,(1,(1,(1,0))))))) | x80 => (0,(0,(0,(0,(0,(0,(0,1))))))) | x81 => (1,(0,(0,(0,(0,(0,(0,1))))))) | x82 => (0,(1,(0,(0,(0,(0,(0,1))))))) | x83 => (1,(1,(0,(0,(0,(0,(0,1))))))) | x84 => (0,(0,(1,(0,(0,(0,(0,1))))))) | x85 => (1,(0,(1,(0,(0,(0,(0,1))))))) | x86 => (0,(1,(1,(0,(0,(0,(0,1))))))) | x87 => (1,(1,(1,(0,(0,(0,(0,1))))))) | x88 => (0,(0,(0,(1,(0,(0,(0,1))))))) | x89 => (1,(0,(0,(1,(0,(0,(0,1))))))) | x8a => (0,(1,(0,(1,(0,(0,(0,1))))))) | x8b => (1,(1,(0,(1,(0,(0,(0,1))))))) | x8c => (0,(0,(1,(1,(0,(0,(0,1))))))) | x8d => (1,(0,(1,(1,(0,(0,(0,1))))))) | x8e => (0,(1,(1,(1,(0,(0,(0,1))))))) | x8f => (1,(1,(1,(1,(0,(0,(0,1))))))) | x90 => (0,(0,(0,(0,(1,(0,(0,1))))))) | x91 => (1,(0,(0,(0,(1,(0,(0,1))))))) | x92 => (0,(1,(0,(0,(1,(0,(0,1))))))) | x93 => (1,(1,(0,(0,(1,(0,(0,1))))))) | x94 => (0,(0,(1,(0,(1,(0,(0,1))))))) | x95 => (1,(0,(1,(0,(1,(0,(0,1))))))) | x96 => (0,(1,(1,(0,(1,(0,(0,1))))))) | x97 => (1,(1,(1,(0,(1,(0,(0,1))))))) | x98 => (0,(0,(0,(1,(1,(0,(0,1))))))) | x99 => (1,(0,(0,(1,(1,(0,(0,1))))))) | x9a => (0,(1,(0,(1,(1,(0,(0,1))))))) | x9b => (1,(1,(0,(1,(1,(0,(0,1))))))) | x9c => (0,(0,(1,(1,(1,(0,(0,1))))))) | x9d => (1,(0,(1,(1,(1,(0,(0,1))))))) | x9e => (0,(1,(1,(1,(1,(0,(0,1))))))) | x9f => (1,(1,(1,(1,(1,(0,(0,1))))))) | xa0 => (0,(0,(0,(0,(0,(1,(0,1))))))) | xa1 => (1,(0,(0,(0,(0,(1,(0,1))))))) | xa2 => (0,(1,(0,(0,(0,(1,(0,1))))))) | xa3 => (1,(1,(0,(0,(0,(1,(0,1))))))) | xa4 => (0,(0,(1,(0,(0,(1,(0,1))))))) | xa5 => (1,(0,(1,(0,(0,(1,(0,1))))))) | xa6 => (0,(1,(1,(0,(0,(1,(0,1))))))) | xa7 => (1,(1,(1,(0,(0,(1,(0,1))))))) | xa8 => (0,(0,(0,(1,(0,(1,(0,1))))))) | xa9 => (1,(0,(0,(1,(0,(1,(0,1))))))) | xaa => (0,(1,(0,(1,(0,(1,(0,1))))))) | xab => (1,(1,(0,(1,(0,(1,(0,1))))))) | xac => (0,(0,(1,(1,(0,(1,(0,1))))))) | xad => (1,(0,(1,(1,(0,(1,(0,1))))))) | xae => (0,(1,(1,(1,(0,(1,(0,1))))))) | xaf => (1,(1,(1,(1,(0,(1,(0,1))))))) | xb0 => (0,(0,(0,(0,(1,(1,(0,1))))))) | xb1 => (1,(0,(0,(0,(1,(1,(0,1))))))) | xb2 => (0,(1,(0,(0,(1,(1,(0,1))))))) | xb3 => (1,(1,(0,(0,(1,(1,(0,1))))))) | xb4 => (0,(0,(1,(0,(1,(1,(0,1))))))) | xb5 => (1,(0,(1,(0,(1,(1,(0,1))))))) | xb6 => (0,(1,(1,(0,(1,(1,(0,1))))))) | xb7 => (1,(1,(1,(0,(1,(1,(0,1))))))) | xb8 => (0,(0,(0,(1,(1,(1,(0,1))))))) | xb9 => (1,(0,(0,(1,(1,(1,(0,1))))))) | xba => (0,(1,(0,(1,(1,(1,(0,1))))))) | xbb => (1,(1,(0,(1,(1,(1,(0,1))))))) | xbc => (0,(0,(1,(1,(1,(1,(0,1))))))) | xbd => (1,(0,(1,(1,(1,(1,(0,1))))))) | xbe => (0,(1,(1,(1,(1,(1,(0,1))))))) | xbf => (1,(1,(1,(1,(1,(1,(0,1))))))) | xc0 => (0,(0,(0,(0,(0,(0,(1,1))))))) | xc1 => (1,(0,(0,(0,(0,(0,(1,1))))))) | xc2 => (0,(1,(0,(0,(0,(0,(1,1))))))) | xc3 => (1,(1,(0,(0,(0,(0,(1,1))))))) | xc4 => (0,(0,(1,(0,(0,(0,(1,1))))))) | xc5 => (1,(0,(1,(0,(0,(0,(1,1))))))) | xc6 => (0,(1,(1,(0,(0,(0,(1,1))))))) | xc7 => (1,(1,(1,(0,(0,(0,(1,1))))))) | xc8 => (0,(0,(0,(1,(0,(0,(1,1))))))) | xc9 => (1,(0,(0,(1,(0,(0,(1,1))))))) | xca => (0,(1,(0,(1,(0,(0,(1,1))))))) | xcb => (1,(1,(0,(1,(0,(0,(1,1))))))) | xcc => (0,(0,(1,(1,(0,(0,(1,1))))))) | xcd => (1,(0,(1,(1,(0,(0,(1,1))))))) | xce => (0,(1,(1,(1,(0,(0,(1,1))))))) | xcf => (1,(1,(1,(1,(0,(0,(1,1))))))) | xd0 => (0,(0,(0,(0,(1,(0,(1,1))))))) | xd1 => (1,(0,(0,(0,(1,(0,(1,1))))))) | xd2 => (0,(1,(0,(0,(1,(0,(1,1))))))) | xd3 => (1,(1,(0,(0,(1,(0,(1,1))))))) | xd4 => (0,(0,(1,(0,(1,(0,(1,1))))))) | xd5 => (1,(0,(1,(0,(1,(0,(1,1))))))) | xd6 => (0,(1,(1,(0,(1,(0,(1,1))))))) | xd7 => (1,(1,(1,(0,(1,(0,(1,1))))))) | xd8 => (0,(0,(0,(1,(1,(0,(1,1))))))) | xd9 => (1,(0,(0,(1,(1,(0,(1,1))))))) | xda => (0,(1,(0,(1,(1,(0,(1,1))))))) | xdb => (1,(1,(0,(1,(1,(0,(1,1))))))) | xdc => (0,(0,(1,(1,(1,(0,(1,1))))))) | xdd => (1,(0,(1,(1,(1,(0,(1,1))))))) | xde => (0,(1,(1,(1,(1,(0,(1,1))))))) | xdf => (1,(1,(1,(1,(1,(0,(1,1))))))) | xe0 => (0,(0,(0,(0,(0,(1,(1,1))))))) | xe1 => (1,(0,(0,(0,(0,(1,(1,1))))))) | xe2 => (0,(1,(0,(0,(0,(1,(1,1))))))) | xe3 => (1,(1,(0,(0,(0,(1,(1,1))))))) | xe4 => (0,(0,(1,(0,(0,(1,(1,1))))))) | xe5 => (1,(0,(1,(0,(0,(1,(1,1))))))) | xe6 => (0,(1,(1,(0,(0,(1,(1,1))))))) | xe7 => (1,(1,(1,(0,(0,(1,(1,1))))))) | xe8 => (0,(0,(0,(1,(0,(1,(1,1))))))) | xe9 => (1,(0,(0,(1,(0,(1,(1,1))))))) | xea => (0,(1,(0,(1,(0,(1,(1,1))))))) | xeb => (1,(1,(0,(1,(0,(1,(1,1))))))) | xec => (0,(0,(1,(1,(0,(1,(1,1))))))) | xed => (1,(0,(1,(1,(0,(1,(1,1))))))) | xee => (0,(1,(1,(1,(0,(1,(1,1))))))) | xef => (1,(1,(1,(1,(0,(1,(1,1))))))) | xf0 => (0,(0,(0,(0,(1,(1,(1,1))))))) | xf1 => (1,(0,(0,(0,(1,(1,(1,1))))))) | xf2 => (0,(1,(0,(0,(1,(1,(1,1))))))) | xf3 => (1,(1,(0,(0,(1,(1,(1,1))))))) | xf4 => (0,(0,(1,(0,(1,(1,(1,1))))))) | xf5 => (1,(0,(1,(0,(1,(1,(1,1))))))) | xf6 => (0,(1,(1,(0,(1,(1,(1,1))))))) | xf7 => (1,(1,(1,(0,(1,(1,(1,1))))))) | xf8 => (0,(0,(0,(1,(1,(1,(1,1))))))) | xf9 => (1,(0,(0,(1,(1,(1,(1,1))))))) | xfa => (0,(1,(0,(1,(1,(1,(1,1))))))) | xfb => (1,(1,(0,(1,(1,(1,(1,1))))))) | xfc => (0,(0,(1,(1,(1,(1,(1,1))))))) | xfd => (1,(0,(1,(1,(1,(1,(1,1))))))) | xfe => (0,(1,(1,(1,(1,(1,(1,1))))))) | xff => (1,(1,(1,(1,(1,(1,(1,1))))))) end. Lemma of_bits_to_bits (b : byte) : of_bits (to_bits b) = b. Proof. destruct b; exact eq_refl. Qed. Lemma to_bits_of_bits (b : _) : to_bits (of_bits b) = b. Proof. repeat match goal with | p : prod _ _ |- _ => destruct p | b : bool |- _ => destruct b end; exact eq_refl. Qed. Definition byte_of_byte (b : byte) : byte := b. Module Export ByteSyntaxNotations. String Notation byte byte_of_byte byte_of_byte : byte_scope. End ByteSyntaxNotations. rocq-9.2.0/theories/Corelib/Init/Datatypes.v000066400000000000000000000365241516144147600207420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Set := | ReflectT : P -> reflect P true | ReflectF : ~ P -> reflect P false. #[global] Create HintDb bool. #[global] Hint Constructors reflect : bool. Arguments ReflectT : clear implicits. Arguments ReflectF : clear implicits. (** Interest: a case on a reflect lemma or hyp performs clever unification, and leave the goal in a convenient shape (a bit like case_eq). *) (** Basic boolean operators *) Definition andb (b1 b2:bool) : bool := if b1 then b2 else false. Definition orb (b1 b2:bool) : bool := if b1 then true else b2. Definition implb (b1 b2:bool) : bool := if b1 then b2 else true. Definition xorb (b1 b2:bool) : bool := if b1 then if b2 then false else true else b2. Definition negb (b:bool) := if b then false else true. Infix "||" := orb : bool_scope. Infix "&&" := andb : bool_scope. Register andb as core.bool.andb. Register orb as core.bool.orb. Register implb as core.bool.implb. Register xorb as core.bool.xorb. Register negb as core.bool.negb. (** Basic properties of [andb] *) Lemma andb_prop (a b:bool) : andb a b = true -> a = true /\ b = true. Proof. destruct a, b; repeat split; assumption. Qed. #[global] Hint Resolve andb_prop: bool. Register andb_prop as core.bool.andb_prop. Lemma andb_true_intro (b1 b2:bool) : b1 = true /\ b2 = true -> andb b1 b2 = true. Proof. destruct b1; destruct b2; simpl; intros [? ?]; assumption. Qed. #[global] Hint Resolve andb_true_intro: bool. Register andb_true_intro as core.bool.andb_true_intro. (** Interpretation of booleans as propositions *) Inductive eq_true : bool -> Prop := is_eq_true : eq_true true. #[global] Create HintDb eq_true. #[global] Hint Constructors eq_true : eq_true. Register eq_true as core.eq_true.type. Scheme Rewriting for eq_true. (** Another way of interpreting booleans as propositions *) Definition is_true b := b = true. (** [is_true] can be activated as a coercion by ([Local]) [Coercion is_true : bool >-> Sortclass]. *) (** Additional rewriting lemmas about [eq_true] *) Lemma eq_true_ind_r : forall (P : bool -> Prop) (b : bool), P b -> eq_true b -> P true. Proof. intros P b H H0; destruct H0 in H; assumption. Defined. Lemma eq_true_rec_r : forall (P : bool -> Set) (b : bool), P b -> eq_true b -> P true. Proof. intros P b H H0; destruct H0 in H; assumption. Defined. Lemma eq_true_rect_r : forall (P : bool -> Type) (b : bool), P b -> eq_true b -> P true. Proof. intros P b H H0; destruct H0 in H; assumption. Defined. (** The [BoolSpec] inductive will be used to relate a [boolean] value and two propositions corresponding respectively to the [true] case and the [false] case. Interest: [BoolSpec] behave nicely with [case] and [destruct]. See also [Bool.reflect] when [Q = ~P]. *) Inductive BoolSpec (P Q : Prop) : bool -> Prop := | BoolSpecT : P -> BoolSpec P Q true | BoolSpecF : Q -> BoolSpec P Q false. #[global] Hint Constructors BoolSpec : core. Register BoolSpec as core.BoolSpec.type. Register BoolSpecT as core.BoolSpec.BoolSpecT. Register BoolSpecF as core.BoolSpec.BoolSpecF. (********************************************************************) (** * Peano natural numbers *) (** [nat] is the datatype of natural numbers built from [O] and successor [S]; note that the constructor name is the letter O. Numbers in [nat] can be denoted using a decimal notation; e.g. [3%nat] abbreviates [S (S (S O))] *) Inductive nat : Set := | O : nat | S : nat -> nat. Declare Scope hex_nat_scope. Delimit Scope hex_nat_scope with xnat. Declare Scope nat_scope. Delimit Scope nat_scope with nat. Bind Scope nat_scope with nat. Arguments S _%_nat. Register nat as num.nat.type. Register O as num.nat.O. Register S as num.nat.S. (********************************************************************) (** * Container datatypes *) (* Set Universe Polymorphism. *) (** [option A] is the extension of [A] with an extra element [None] *) #[universes(template)] Inductive option (A:Type) : Type := | Some : A -> option A | None : option A. Arguments Some {A} a. Arguments None {A}. Register option as core.option.type. Register Some as core.option.Some. Register None as core.option.None. Definition option_map (A B:Type) (f:A->B) (o : option A) : option B := match o with | Some a => @Some B (f a) | None => @None B end. (** [sum A B], written [A + B], is the disjoint sum of [A] and [B] *) #[universes(template)] Inductive sum (A B:Type) : Type := | inl : A -> sum A B | inr : B -> sum A B. Notation "x + y" := (sum x y) : type_scope. Arguments inl {A B} _ , [A] B _. Arguments inr {A B} _ , A [B] _. Register sum as core.sum.type. Register inl as core.sum.inl. Register inr as core.sum.inr. Inductive result (A E : Type) := | Ok (_:A) | Error (_:E). Arguments Ok {_ _} _, [_] _ _. Arguments Error {_ _} _, _ [_] _. Register result as core.result.type. (** [prod A B], written [A * B], is the product of [A] and [B]; the pair [pair A B a b] of [a] and [b] is abbreviated [(a,b)] *) #[universes(template)] Inductive prod (A B:Type) : Type := pair : A -> B -> A * B where "x * y" := (prod x y) : type_scope. Add Printing Let prod. Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_scope. Arguments pair {A B} _ _. Register prod as core.prod.type. Register pair as core.prod.intro. Register prod_rect as core.prod.rect. Section projections. Context {A : Type} {B : Type}. Definition fst (p:A * B) := match p with (x, y) => x end. Definition snd (p:A * B) := match p with (x, y) => y end. Register fst as core.prod.proj1. Register snd as core.prod.proj2. End projections. #[global] Hint Resolve pair inl inr: core. Lemma surjective_pairing (A B:Type) (p:A * B) : p = (fst p, snd p). Proof. destruct p; reflexivity. Qed. Lemma injective_projections (A B:Type) (p1 p2:A * B) : fst p1 = fst p2 -> snd p1 = snd p2 -> p1 = p2. Proof. destruct p1; destruct p2; simpl; intros Hfst Hsnd. rewrite Hfst; rewrite Hsnd; reflexivity. Qed. Lemma pair_equal_spec (A B : Type) (a1 a2 : A) (b1 b2 : B) : (a1, b1) = (a2, b2) <-> a1 = a2 /\ b1 = b2. Proof. split; intro H. - split. + replace a1 with (fst (a1, b1)); replace a2 with (fst (a2, b2)); auto. rewrite H; auto. + replace b1 with (snd (a1, b1)); replace b2 with (snd (a2, b2)); auto. rewrite H; auto. - destruct H; subst; auto. Qed. Definition curry {A B C:Type} (f:A * B -> C) (x:A) (y:B) : C := f (x,y). Definition uncurry {A B C:Type} (f:A -> B -> C) (p:A * B) : C := match p with (x, y) => f x y end. Import EqNotations. Lemma rew_pair A (P Q : A->Type) x1 x2 (y1:P x1) (y2:Q x1) (H:x1=x2) : (rew H in y1, rew H in y2) = rew [fun x => (P x * Q x)%type] H in (y1,y2). Proof. destruct H. reflexivity. Defined. (** Polymorphic lists and some operations *) #[universes(template)] Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. Arguments nil {A}. Arguments cons {A} a l. Declare Scope list_scope. Delimit Scope list_scope with list. Bind Scope list_scope with list. Infix "::" := cons (at level 60, right associativity) : list_scope. Register list as core.list.type. Register nil as core.list.nil. Register cons as core.list.cons. Local Open Scope list_scope. Definition length (A : Type) : list A -> nat := fix length l := match l with | nil => O | _ :: l' => S (length l') end. (** Concatenation of two lists *) Definition app (A : Type) : list A -> list A -> list A := fix app l m := match l with | nil => m | a :: l1 => a :: app l1 m end. Infix "++" := app (right associativity, at level 60) : list_scope. (* Unset Universe Polymorphism. *) (********************************************************************) (** * The comparison datatype *) Inductive comparison : Set := | Eq : comparison | Lt : comparison | Gt : comparison. Register comparison as core.comparison.type. Register Eq as core.comparison.Eq. Register Lt as core.comparison.Lt. Register Gt as core.comparison.Gt. Lemma comparison_eq_stable (c c' : comparison) : ~~ c = c' -> c = c'. Proof. destruct c, c'; intro H; reflexivity || destruct H; discriminate. Qed. Definition CompOpp (r:comparison) := match r with | Eq => Eq | Lt => Gt | Gt => Lt end. Lemma CompOpp_involutive c : CompOpp (CompOpp c) = c. Proof. destruct c; reflexivity. Qed. Lemma CompOpp_inj c c' : CompOpp c = CompOpp c' -> c = c'. Proof. destruct c; destruct c'; auto; discriminate. Qed. Lemma CompOpp_iff : forall c c', CompOpp c = c' <-> c = CompOpp c'. Proof. split; intros; apply CompOpp_inj; rewrite CompOpp_involutive; auto. Qed. (** The [CompareSpec] inductive relates a [comparison] value with three propositions, one for each possible case. Typically, it can be used to specify a comparison function via some equality and order predicates. Interest: [CompareSpec] behave nicely with [case] and [destruct]. *) Inductive CompareSpec (Peq Plt Pgt : Prop) : comparison -> Prop := | CompEq : Peq -> CompareSpec Peq Plt Pgt Eq | CompLt : Plt -> CompareSpec Peq Plt Pgt Lt | CompGt : Pgt -> CompareSpec Peq Plt Pgt Gt. #[global] Hint Constructors CompareSpec : core. Register CompareSpec as core.CompareSpec.type. Register CompEq as core.CompareSpec.CompEq. Register CompLt as core.CompareSpec.CompLt. Register CompGt as core.CompareSpec.CompGt. (** For having clean interfaces after extraction, [CompareSpec] is declared in Prop. For some situations, it is nonetheless useful to have a version in Type. Interestingly, these two versions are equivalent. *) Inductive CompareSpecT (Peq Plt Pgt : Prop) : comparison -> Type := | CompEqT : Peq -> CompareSpecT Peq Plt Pgt Eq | CompLtT : Plt -> CompareSpecT Peq Plt Pgt Lt | CompGtT : Pgt -> CompareSpecT Peq Plt Pgt Gt. #[global] Hint Constructors CompareSpecT : core. Register CompareSpecT as core.CompareSpecT.type. Register CompEqT as core.CompareSpecT.CompEqT. Register CompLtT as core.CompareSpecT.CompLtT. Register CompGtT as core.CompareSpecT.CompGtT. Lemma CompareSpec2Type Peq Plt Pgt c : CompareSpec Peq Plt Pgt c -> CompareSpecT Peq Plt Pgt c. Proof. destruct c; intros H; constructor; inversion_clear H; auto. Defined. (** As an alternate formulation, one may also directly refer to predicates [eq] and [lt] for specifying a comparison, rather that fully-applied propositions. This [CompSpec] is now a particular case of [CompareSpec]. *) Definition CompSpec {A} (eq lt : A->A->Prop)(x y:A) : comparison -> Prop := CompareSpec (eq x y) (lt x y) (lt y x). Definition CompSpecT {A} (eq lt : A->A->Prop)(x y:A) : comparison -> Type := CompareSpecT (eq x y) (lt x y) (lt y x). #[global] Hint Unfold CompSpec CompSpecT : core. Lemma CompSpec2Type : forall A (eq lt:A->A->Prop) x y c, CompSpec eq lt x y c -> CompSpecT eq lt x y c. Proof. intros. apply CompareSpec2Type; assumption. Defined. (******************************************************************) (** * Misc Other Datatypes *) (** [identity A a] is the family of datatypes on [A] whose sole non-empty member is the singleton datatype [identity A a a] whose sole inhabitant is denoted [identity_refl A a] *) #[deprecated(since="8.16",note="Use eq instead")] Abbreviation identity := eq (only parsing). #[deprecated(since="8.16",note="Use eq_refl instead")] Abbreviation identity_refl := eq_refl (only parsing). #[deprecated(since="8.16",note="Use eq_ind instead")] Abbreviation identity_ind := eq_ind (only parsing). #[deprecated(since="8.16",note="Use eq_rec instead")] Abbreviation identity_rec := eq_rec (only parsing). #[deprecated(since="8.16",note="Use eq_rect instead")] Abbreviation identity_rect := eq_rect (only parsing). #[deprecated(since="8.16",note="Use eq_sym instead")] Abbreviation identity_sym := eq_sym (only parsing). #[deprecated(since="8.16",note="Use eq_trans instead")] Abbreviation identity_trans := eq_trans (only parsing). #[deprecated(since="8.16",note="Use f_equal instead")] Abbreviation identity_congr := f_equal (only parsing). #[deprecated(since="8.16",note="Use not_eq_sym instead")] Abbreviation not_identity_sym := not_eq_sym (only parsing). #[deprecated(since="8.16",note="Use eq_ind_r instead")] Abbreviation identity_ind_r := eq_ind_r (only parsing). #[deprecated(since="8.16",note="Use eq_rec_r instead")] Abbreviation identity_rec_r := eq_rec_r (only parsing). #[deprecated(since="8.16",note="Use eq_rect_r instead")] Abbreviation identity_rect_r := eq_rect_r (only parsing). Register eq as core.identity.type. Register eq_refl as core.identity.refl. Register eq_ind as core.identity.ind. Register eq_sym as core.identity.sym. Register eq_trans as core.identity.trans. Register f_equal as core.identity.congr. #[deprecated(since="8.16",note="Use eq_refl instead")] Abbreviation refl_id := eq_refl (only parsing). #[deprecated(since="8.16",note="Use eq_sym instead")] Abbreviation sym_id := eq_sym (only parsing). #[deprecated(since="8.16",note="Use eq_trans instead")] Abbreviation trans_id := eq_trans (only parsing). #[deprecated(since="8.16",note="Use not_eq_sym instead")] Abbreviation sym_not_id := not_eq_sym (only parsing). (** Identity type *) Definition ID := forall A:Type, A -> A. Definition id : ID := fun A x => x. Definition IDProp := forall A:Prop, A -> A. Definition idProp : IDProp := fun A x => x. Register idProp as core.IDProp.idProp. (* begin hide *) (* Compatibility *) Abbreviation prodT := prod (only parsing). Abbreviation pairT := pair (only parsing). Abbreviation prodT_rect := prod_rect (only parsing). Abbreviation prodT_rec := prod_rec (only parsing). Abbreviation prodT_ind := prod_ind (only parsing). Abbreviation fstT := fst (only parsing). Abbreviation sndT := snd (only parsing). (* end hide *) rocq-9.2.0/theories/Corelib/Init/Decimal.v000066400000000000000000000153621516144147600203370ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* O | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d => S (nb_digits d) end. (** 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] for unsigned numbers and [Pos (D0 Nil)] for signed numbers). *) (** [nzhead] removes all head zero digits *) Fixpoint nzhead d := match d with | D0 d => nzhead d | _ => d end. (** [unorm] : normalization of unsigned integers *) Definition unorm d := match nzhead d with | Nil => zero | d => d end. (** [norm] : normalization of signed integers *) Definition norm d := match d with | Pos d => Pos (unorm d) | Neg d => match nzhead d with | Nil => Pos zero | d => Neg d end end. (** A few easy operations. For more advanced computations, use the conversions with other Rocq numeral datatypes (e.g. Z) and the operations on them. *) Definition opp (d:int) := match d with | Pos d => Neg d | Neg d => Pos d end. Definition abs (d:int) : uint := match d with | Pos d => d | Neg d => d end. (** For conversions with binary numbers, it is easier to operate on little-endian numbers. *) Fixpoint revapp (d d' : uint) := match d with | Nil => d' | D0 d => revapp d (D0 d') | D1 d => revapp d (D1 d') | D2 d => revapp d (D2 d') | D3 d => revapp d (D3 d') | D4 d => revapp d (D4 d') | D5 d => revapp d (D5 d') | D6 d => revapp d (D6 d') | D7 d => revapp d (D7 d') | D8 d => revapp d (D8 d') | D9 d => revapp d (D9 d') end. Definition rev d := revapp d Nil. Definition app d d' := revapp (rev d) d'. Definition app_int d1 d2 := match d1 with Pos d1 => Pos (app d1 d2) | Neg d1 => Neg (app d1 d2) end. (** [nztail] removes all trailing zero digits and return both the result and the number of removed digits. *) Definition nztail d := let fix aux d_rev := match d_rev with | D0 d_rev => let (r, n) := aux d_rev in pair r (S n) | _ => pair d_rev O end in let (r, n) := aux (rev d) in pair (rev r) n. Definition nztail_int d := match d with | Pos d => let (r, n) := nztail d in pair (Pos r) n | Neg d => let (r, n) := nztail d in pair (Neg r) n end. (** [del_head n d] removes [n] digits at beginning of [d] or returns [zero] if [d] has less than [n] digits. *) Fixpoint del_head n d := match n with | O => d | S n => match d with | Nil => zero | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d => del_head n d end end. Definition del_head_int n d := match d with | Pos d => del_head n d | Neg d => del_head n d end. (** [del_tail n d] removes [n] digits at end of [d] or returns [zero] if [d] has less than [n] digits. *) Definition del_tail n d := rev (del_head n (rev d)). Definition del_tail_int n d := match d with | Pos d => Pos (del_tail n d) | Neg d => Neg (del_tail n d) end. Module Little. (** Successor of little-endian numbers *) Fixpoint succ d := match d with | Nil => D1 Nil | D0 d => D1 d | D1 d => D2 d | D2 d => D3 d | D3 d => D4 d | D4 d => D5 d | D5 d => D6 d | D6 d => D7 d | D7 d => D8 d | D8 d => D9 d | D9 d => D0 (succ d) end. (** Doubling little-endian numbers *) Fixpoint double d := match d with | Nil => Nil | D0 d => D0 (double d) | D1 d => D2 (double d) | D2 d => D4 (double d) | D3 d => D6 (double d) | D4 d => D8 (double d) | D5 d => D0 (succ_double d) | D6 d => D2 (succ_double d) | D7 d => D4 (succ_double d) | D8 d => D6 (succ_double d) | D9 d => D8 (succ_double d) end with succ_double d := match d with | Nil => D1 Nil | D0 d => D1 (double d) | D1 d => D3 (double d) | D2 d => D5 (double d) | D3 d => D7 (double d) | D4 d => D9 (double d) | D5 d => D1 (succ_double d) | D6 d => D3 (succ_double d) | D7 d => D5 (succ_double d) | D8 d => D7 (succ_double d) | D9 d => D9 (succ_double d) end. End Little. (** Pseudo-conversion functions used when declaring Number Notations on [uint] and [int]. *) Definition uint_of_uint (i:uint) := i. Definition int_of_int (i:int) := i. rocq-9.2.0/theories/Corelib/Init/Equality.v000066400000000000000000000132661516144147600205770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A -> Type@{se;le}) := refl : forall A x, eq A x x. (* This class register a Martin-LΓΆf like elimination principle *) Class Has_J@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) (Has_refl : Has_refl eq) := J_eliminator : forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A x y -> Type@{sp ; lp}), P x (refl A x) -> forall y e, P y e. (* This class is for forward dependent rewriting *) Class Has_J_r@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) (Has_refl : Has_refl eq) := J_r_eliminator: forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A y x -> Type@{sp ; lp}), P x (refl A x) -> forall y e, P y e. (* Those two classes are for dependent rewriting in an hypotesis *) Class Has_J_forward@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) (Has_refl : Has_refl eq) := J_forward : forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A x y -> Type@{sp ; lp}) y e, P y e -> P x (refl A x). Class Has_J_r_forward@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) (Has_refl : Has_refl eq) := J_r_forward : forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A y x -> Type@{sp ; lp}) y e, P y e -> P x (refl A x). (* Those two classes are for non-dependent rewriting *) Class Has_Leibniz@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) := leibniz : forall (A : Type@{sa ; la}) (x : A) (P : A -> Type@{sp ; lp}), P x -> forall y, eq A x y -> P y. Class Has_Leibniz_r@{sa se sp;la le lp} (eq : forall A : Type@{sa ; la}, A -> A -> Type@{se;le}) := leibniz_r : forall (A : Type@{sa ; la}) (x : A) (P : A -> Type@{sp ; lp}), P x -> forall y, eq A y x -> P y. Register Has_refl as core.Has_refl. Typeclasses Opaque Has_refl. Register Has_J as core.Has_J. Typeclasses Opaque Has_J. Register Has_J_r as core.Has_J_r. Typeclasses Opaque Has_J_r. Register Has_J_forward as core.Has_J_forward. Typeclasses Opaque Has_J_forward. Register Has_J_r_forward as core.Has_J_r_forward. Typeclasses Opaque Has_J_r_forward. Register Has_Leibniz as core.Has_Leibniz. Typeclasses Opaque Has_Leibniz. Register Has_Leibniz_r as core.Has_Leibniz_r. Typeclasses Opaque Has_Leibniz_r. Definition J_no_dep@{s s' sp;l l' lp} {eq} {refl} (eqr : Has_J@{s s' sp;l l' lp} eq refl) : forall (A : Type@{s ; l}) (x : A) (P : A -> Type@{sp ; lp}), P x -> forall y (e : eq A x y), P y := fun A x P px y e => J_eliminator _ x (fun y _ => P y) px y e. Definition Has_J_Has_Leibniz@{s s' sp;l l' lp} {eq} {refl} (eqr : Has_J@{s s' sp;l l' lp} eq refl) : Has_Leibniz@{s s' sp;l l' lp} eq := fun A x P px y e => J_no_dep eqr A x P px y e. Section ap. Sort sa se sb se'. Universe la le lb le'. Context {eq : forall A : Type@{sa;la}, A -> A -> Type@{se;le} } {eq' : forall A : Type@{sb; lb}, A -> A -> Type@{se';le'} } {_refl: Has_refl@{sb se';lb le'} eq'} {_leibniz: Has_Leibniz@{sa se se';la le le'} eq}. Definition ap [A : Type@{sa;la}] [B:Type@{sb;lb}] (f : A -> B) [x y : A] (e : eq _ x y) : eq' _ (f x) (f y) := leibniz A x (fun y => eq' B (f x) (f y)) (refl _ _) y e. End ap. Register ap as core.ap. Section sym. Sort sa se. Universe la le. Context {eq : forall A : Type@{sa;la}, A -> A -> Type@{se;le} } {A : Type@{sa;la} } {_refl: Has_refl@{sa se;la le} eq} {_leibniz: Has_Leibniz@{sa se se;la le le} eq}. Definition sym {x y : A} (e : eq _ x y) : eq _ y x := leibniz _ _ (fun y => eq A y _) (refl _ _) _ e. End sym. Definition Has_J_Has_J_forward@{sa se sp;la le lp} eq Has_refl {has_J : Has_J@{sa se sp;la le lp} eq Has_refl} : forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A x y -> Type@{sp ; lp}) y e, P y e -> P x (refl A x) := fun A x P y e => J_eliminator _ _ (fun y e => P y e -> P _ _) (fun x => x) _ _. Definition _Has_J_Has_J_forward@{sa se sp;la le lp} eq Has_refl {has_J : Has_J@{sa se sp;la le lp} eq Has_refl} : Has_J_forward@{sa se sp;la le lp} eq Has_refl := Has_J_Has_J_forward _ _. Hint Resolve _Has_J_Has_J_forward : rewrite_instances. Definition Has_J_r_Has_J_r_forward@{sa se sp;la le lp} eq Has_refl {has_J : Has_J_r@{sa se sp;la le lp} eq Has_refl} : forall (A : Type@{sa ; la}) (x : A) (P : forall y : A, eq A y x -> Type@{sp ; lp}) y e, P y e -> P x (refl A x) := fun A x P y e => J_r_eliminator _ _ (fun y e => P y e -> P _ _) (fun x => x) _ _. Definition _Has_J_r_Has_J_r_forward@{sa se sp;la le lp} eq Has_refl {has_J : Has_J_r@{sa se sp;la le lp} eq Has_refl} : Has_J_r_forward@{sa se sp;la le lp} eq Has_refl := Has_J_r_Has_J_r_forward _ _. Hint Resolve _Has_J_r_Has_J_r_forward : rewrite_instances. rocq-9.2.0/theories/Corelib/Init/Hexadecimal.v000066400000000000000000000166721516144147600212120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* O | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d | Da d | Db d | Dc d | Dd d | De d | Df d => S (nb_digits d) end. (** 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] for unsigned numbers and [Pos (D0 Nil)] for signed numbers). *) (** [nzhead] removes all head zero digits *) Fixpoint nzhead d := match d with | D0 d => nzhead d | _ => d end. (** [unorm] : normalization of unsigned integers *) Definition unorm d := match nzhead d with | Nil => zero | d => d end. (** [norm] : normalization of signed integers *) Definition norm d := match d with | Pos d => Pos (unorm d) | Neg d => match nzhead d with | Nil => Pos zero | d => Neg d end end. (** A few easy operations. For more advanced computations, use the conversions with other Rocq numeral datatypes (e.g. Z) and the operations on them. *) Definition opp (d:int) := match d with | Pos d => Neg d | Neg d => Pos d end. Definition abs (d:int) : uint := match d with | Pos d => d | Neg d => d end. (** For conversions with binary numbers, it is easier to operate on little-endian numbers. *) Fixpoint revapp (d d' : uint) := match d with | Nil => d' | D0 d => revapp d (D0 d') | D1 d => revapp d (D1 d') | D2 d => revapp d (D2 d') | D3 d => revapp d (D3 d') | D4 d => revapp d (D4 d') | D5 d => revapp d (D5 d') | D6 d => revapp d (D6 d') | D7 d => revapp d (D7 d') | D8 d => revapp d (D8 d') | D9 d => revapp d (D9 d') | Da d => revapp d (Da d') | Db d => revapp d (Db d') | Dc d => revapp d (Dc d') | Dd d => revapp d (Dd d') | De d => revapp d (De d') | Df d => revapp d (Df d') end. Definition rev d := revapp d Nil. Definition app d d' := revapp (rev d) d'. Definition app_int d1 d2 := match d1 with Pos d1 => Pos (app d1 d2) | Neg d1 => Neg (app d1 d2) end. (** [nztail] removes all trailing zero digits and return both the result and the number of removed digits. *) Definition nztail d := let fix aux d_rev := match d_rev with | D0 d_rev => let (r, n) := aux d_rev in pair r (S n) | _ => pair d_rev O end in let (r, n) := aux (rev d) in pair (rev r) n. Definition nztail_int d := match d with | Pos d => let (r, n) := nztail d in pair (Pos r) n | Neg d => let (r, n) := nztail d in pair (Neg r) n end. (** [del_head n d] removes [n] digits at beginning of [d] or returns [zero] if [d] has less than [n] digits. *) Fixpoint del_head n d := match n with | O => d | S n => match d with | Nil => zero | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d | Da d | Db d | Dc d | Dd d | De d | Df d => del_head n d end end. Definition del_head_int n d := match d with | Pos d => del_head n d | Neg d => del_head n d end. (** [del_tail n d] removes [n] digits at end of [d] or returns [zero] if [d] has less than [n] digits. *) Definition del_tail n d := rev (del_head n (rev d)). Definition del_tail_int n d := match d with | Pos d => Pos (del_tail n d) | Neg d => Neg (del_tail n d) end. Module Little. (** Successor of little-endian numbers *) Fixpoint succ d := match d with | Nil => D1 Nil | D0 d => D1 d | D1 d => D2 d | D2 d => D3 d | D3 d => D4 d | D4 d => D5 d | D5 d => D6 d | D6 d => D7 d | D7 d => D8 d | D8 d => D9 d | D9 d => Da d | Da d => Db d | Db d => Dc d | Dc d => Dd d | Dd d => De d | De d => Df d | Df d => D0 (succ d) end. (** Doubling little-endian numbers *) Fixpoint double d := match d with | Nil => Nil | D0 d => D0 (double d) | D1 d => D2 (double d) | D2 d => D4 (double d) | D3 d => D6 (double d) | D4 d => D8 (double d) | D5 d => Da (double d) | D6 d => Dc (double d) | D7 d => De (double d) | D8 d => D0 (succ_double d) | D9 d => D2 (succ_double d) | Da d => D4 (succ_double d) | Db d => D6 (succ_double d) | Dc d => D8 (succ_double d) | Dd d => Da (succ_double d) | De d => Dc (succ_double d) | Df d => De (succ_double d) end with succ_double d := match d with | Nil => D1 Nil | D0 d => D1 (double d) | D1 d => D3 (double d) | D2 d => D5 (double d) | D3 d => D7 (double d) | D4 d => D9 (double d) | D5 d => Db (double d) | D6 d => Dd (double d) | D7 d => Df (double d) | D8 d => D1 (succ_double d) | D9 d => D3 (succ_double d) | Da d => D5 (succ_double d) | Db d => D7 (succ_double d) | Dc d => D9 (succ_double d) | Dd d => Db (succ_double d) | De d => Dd (succ_double d) | Df d => Df (succ_double d) end. End Little. rocq-9.2.0/theories/Corelib/Init/Logic.v000066400000000000000000001215231516144147600200330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* False. Notation "~ x" := (not x) : type_scope. Register not as core.not.type. (** Negation of a type in [Type] *) Definition notT (A:Type) := A -> False. (** Create the "core" hint database, and set its transparent state for variables and constants explicitly. *) Create HintDb core. #[global] Hint Variables Opaque : core. #[global] Hint Constants Opaque : core. #[global] Hint Unfold not: core. (** [and A B], written [A /\ B], is the conjunction of [A] and [B] [conj p q] is a proof of [A /\ B] as soon as [p] is a proof of [A] and [q] a proof of [B] [proj1] and [proj2] are first and second projections of a conjunction *) Inductive and (A B:Prop) : Prop := conj : A -> B -> A /\ B where "A /\ B" := (and A B) : type_scope. Register and as core.and.type. Register conj as core.and.conj. Section Conjunction. Variables A B : Prop. Theorem proj1 : A /\ B -> A. Proof. destruct 1; trivial. Qed. Theorem proj2 : A /\ B -> B. Proof. destruct 1; trivial. Qed. End Conjunction. (** [or A B], written [A \/ B], is the disjunction of [A] and [B] *) Inductive or (A B:Prop) : Prop := | or_introl : A -> A \/ B | or_intror : B -> A \/ B where "A \/ B" := (or A B) : type_scope. Arguments or_introl [A B] _, [A] B _. Arguments or_intror [A B] _, A [B] _. Register or as core.or.type. (** [iff A B], written [A <-> B], expresses the equivalence of [A] and [B] *) Definition iff (A B:Prop) := (A -> B) /\ (B -> A). Notation "A <-> B" := (iff A B) : type_scope. Register iff as core.iff.type. Register proj1 as core.iff.proj1. Register proj2 as core.iff.proj2. Section Equivalence. Theorem iff_refl : forall A:Prop, A <-> A. Proof. split; auto. Qed. Theorem iff_trans : forall A B C:Prop, (A <-> B) -> (B <-> C) -> (A <-> C). Proof. intros A B C [H1 H2] [H3 H4]; split; auto. Qed. Theorem iff_sym : forall A B:Prop, (A <-> B) -> (B <-> A). Proof. intros A B [H1 H2]; split; auto. Qed. End Equivalence. #[global] Create HintDb extcore. #[global] Hint Unfold iff: extcore. (** Backward direction of the equivalences above does not need assumptions *) Theorem and_iff_compat_l : forall A B C : Prop, (B <-> C) -> (A /\ B <-> A /\ C). Proof. intros ? ? ? [Hl Hr]; split; intros [? ?]; (split; [ assumption | ]); [apply Hl | apply Hr]; assumption. Qed. Theorem and_iff_compat_r : forall A B C : Prop, (B <-> C) -> (B /\ A <-> C /\ A). Proof. intros ? ? ? [Hl Hr]; split; intros [? ?]; (split; [ | assumption ]); [apply Hl | apply Hr]; assumption. Qed. Theorem or_iff_compat_l : forall A B C : Prop, (B <-> C) -> (A \/ B <-> A \/ C). Proof. intros ? ? ? [Hl Hr]; split; (intros [?|?]; [left; assumption| right]); [apply Hl | apply Hr]; assumption. Qed. Theorem or_iff_compat_r : forall A B C : Prop, (B <-> C) -> (B \/ A <-> C \/ A). Proof. intros ? ? ? [Hl Hr]; split; (intros [?|?]; [left| right; assumption]); [apply Hl | apply Hr]; assumption. Qed. Theorem imp_iff_compat_l : forall A B C : Prop, (B <-> C) -> ((A -> B) <-> (A -> C)). Proof. intros ? ? ? [Hl Hr]; split; intros H ?; [apply Hl | apply Hr]; apply H; assumption. Qed. Theorem imp_iff_compat_r : forall A B C : Prop, (B <-> C) -> ((B -> A) <-> (C -> A)). Proof. intros ? ? ? [Hl Hr]; split; intros H ?; [apply H, Hr | apply H, Hl]; assumption. Qed. Theorem not_iff_compat : forall A B : Prop, (A <-> B) -> (~ A <-> ~B). Proof. intros; apply imp_iff_compat_r; assumption. Qed. (** Some equivalences *) Theorem neg_false : forall A : Prop, ~ A <-> (A <-> False). Proof. intro A; unfold not; split. - intro H; split; [exact H | intro H1; elim H1]. - intros [H _]; exact H. Qed. Theorem and_cancel_l : forall A B C : Prop, (B -> A) -> (C -> A) -> ((A /\ B <-> A /\ C) <-> (B <-> C)). Proof. intros A B C Hl Hr. split; [ | apply and_iff_compat_l]; intros [HypL HypR]; split; intros. + apply HypL; split; [apply Hl | ]; assumption. + apply HypR; split; [apply Hr | ]; assumption. Qed. Theorem and_cancel_r : forall A B C : Prop, (B -> A) -> (C -> A) -> ((B /\ A <-> C /\ A) <-> (B <-> C)). Proof. intros A B C Hl Hr. split; [ | apply and_iff_compat_r]; intros [HypL HypR]; split; intros. + apply HypL; split; [ | apply Hl ]; assumption. + apply HypR; split; [ | apply Hr ]; assumption. Qed. Theorem and_comm : forall A B : Prop, A /\ B <-> B /\ A. Proof. intros; split; intros [? ?]; split; assumption. Qed. Theorem and_assoc : forall A B C : Prop, (A /\ B) /\ C <-> A /\ B /\ C. Proof. intros; split; [ intros [[? ?] ?]| intros [? [? ?]]]; repeat split; assumption. Qed. Theorem or_cancel_l : forall A B C : Prop, (B -> ~ A) -> (C -> ~ A) -> ((A \/ B <-> A \/ C) <-> (B <-> C)). Proof. intros ? ? ? Fl Fr; split; [ | apply or_iff_compat_l]; intros [Hl Hr]; split; intros. { destruct Hl; [ right | destruct Fl | ]; assumption. } { destruct Hr; [ right | destruct Fr | ]; assumption. } Qed. Theorem or_cancel_r : forall A B C : Prop, (B -> ~ A) -> (C -> ~ A) -> ((B \/ A <-> C \/ A) <-> (B <-> C)). Proof. intros ? ? ? Fl Fr; split; [ | apply or_iff_compat_r]; intros [Hl Hr]; split; intros. { destruct Hl; [ left | | destruct Fl ]; assumption. } { destruct Hr; [ left | | destruct Fr ]; assumption. } Qed. Theorem or_comm : forall A B : Prop, (A \/ B) <-> (B \/ A). Proof. intros; split; (intros [? | ?]; [ right | left ]; assumption). Qed. Theorem or_assoc : forall A B C : Prop, (A \/ B) \/ C <-> A \/ B \/ C. Proof. intros; split; [ intros [[?|?]|?]| intros [?|[?|?]]]. + left; assumption. + right; left; assumption. + right; right; assumption. + left; left; assumption. + left; right; assumption. + right; assumption. Qed. Lemma iff_and : forall A B : Prop, (A <-> B) -> (A -> B) /\ (B -> A). Proof. intros A B []; split; trivial. Qed. Lemma iff_to_and : forall A B : Prop, (A <-> B) <-> (A -> B) /\ (B -> A). Proof. intros; split; intros [Hl Hr]; (split; intros; [ apply Hl | apply Hr]); assumption. Qed. (** * First-order quantifiers *) (** [ex P], or simply [exists x, P x], or also [exists x:A, P x], expresses the existence of an [x] of some type [A] in [Set] which satisfies the predicate [P]. This is existential quantification. [ex2 P Q], or simply [exists2 x, P x & Q x], or also [exists2 x:A, P x & Q x], expresses the existence of an [x] of type [A] which satisfies both predicates [P] and [Q]. Universal quantification is primitively written [forall x:A, Q]. By symmetry with existential quantification, the construction [all P] is provided too. *) Inductive ex (A:Type) (P:A -> Prop) : Prop := ex_intro : forall x:A, P x -> ex (A:=A) P. Register ex as core.ex.type. Register ex_intro as core.ex.intro. Section Projections. Variables (A:Prop) (P:A->Prop). Definition ex_proj1 (x:ex P) : A := match x with ex_intro _ a _ => a end. Definition ex_proj2 (x:ex P) : P (ex_proj1 x) := match x with ex_intro _ _ b => b end. Register ex_proj1 as core.ex.proj1. Register ex_proj2 as core.ex.proj2. End Projections. Inductive ex2 (A:Type) (P Q:A -> Prop) : Prop := ex_intro2 : forall x:A, P x -> Q x -> ex2 (A:=A) P Q. (** [ex2] of a predicate can be projected to an [ex]. This allows [ex_proj1] and [ex_proj2] to be usable with [ex2]. We have two choices here: either we can set up the definition so that [ex_proj1] of a coerced [X : ex2 P Q] will unify with [let (a, _, _) := X in a] by restricting the first argument of [ex2] to be a [Prop], or we can define a more general [ex_of_ex2] which does not satisfy this conversion rule. We choose the former, under the assumption that there is no reason to turn an [ex2] into an [ex] unless it is to project out the components. *) Definition ex_of_ex2 (A : Prop) (P Q : A -> Prop) (X : ex2 P Q) : ex P := ex_intro P (let (a, _, _) := X in a) (let (x, p, _) as s return (P (let (a, _, _) := s in a)) := X in p). Section ex2_Projections. Variables (A:Prop) (P Q:A->Prop). Definition ex_proj3 (x:ex2 P Q) : Q (ex_proj1 (ex_of_ex2 x)) := match x with ex_intro2 _ _ _ _ b => b end. End ex2_Projections. Definition all (A:Type) (P:A -> Prop) := forall x:A, P x. Register all as core.all. (* Rule order is important to give printing priority to fully typed exists *) Notation "'exists' x .. y , p" := (ex (fun x => .. (ex (fun y => p)) ..)) (at level 200, x binder, right associativity, format "'[' 'exists' '/ ' x .. y , '/ ' p ']'") : type_scope. Notation "'exists2' x , p & q" := (ex2 (fun x => p) (fun x => q)) (at level 200, x name, p at level 200, right associativity) : type_scope. Notation "'exists2' x : A , p & q" := (ex2 (A:=A) (fun x => p) (fun x => q)) (at level 200, x name, A at level 200, p at level 200, right associativity, format "'[' 'exists2' '/ ' x : A , '/ ' '[' p & '/' q ']' ']'") : type_scope. Notation "'exists2' ' x , p & q" := (ex2 (fun x => p) (fun x => q)) (at level 200, x strict pattern, p at level 200, right associativity) : type_scope. Notation "'exists2' ' x : A , p & q" := (ex2 (A:=A) (fun x => p) (fun x => q)) (at level 200, x strict pattern, A at level 200, p at level 200, right associativity, format "'[' 'exists2' '/ ' ' x : A , '/ ' '[' p & '/' q ']' ']'") : type_scope. (** Derived rules for universal quantification *) Section universal_quantification. Variable A : Type. Variable P : A -> Prop. Theorem inst : forall x:A, all (fun x => P x) -> P x. Proof. unfold all; auto. Qed. Theorem gen : forall (B:Prop) (f:forall y:A, B -> P y), B -> all P. Proof. red; auto. Qed. End universal_quantification. (** * Equality *) (** [eq x y], or simply [x=y] expresses the equality of [x] and [y]. Both [x] and [y] must belong to the same type [A]. The definition is inductive and states the reflexivity of the equality. The others properties (symmetry, transitivity, replacement of equals by equals) are proved below. The type of [x] and [y] can be made explicit using the notation [x = y :> A]. This is Leibniz equality as it expresses that [x] and [y] are equal iff every property on [A] which is true of [x] is also true of [y] *) Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : x = x :>A where "x = y :> A" := (@eq A x y) : type_scope. Arguments eq {A} x _. Arguments eq_refl {A x} , [A] x. Arguments eq_ind [A] x P _ y _ : rename. Arguments eq_rec [A] x P _ y _ : rename. Arguments eq_rect [A] x P _ y _ : rename. Notation "x = y" := (eq x y) : type_scope. Notation "x <> y :> T" := (~ x = y :>T) : type_scope. Notation "x <> y" := (~ (x = y)) : type_scope. #[global] Hint Resolve I conj or_introl or_intror : core. #[global] Hint Resolve eq_refl: core. #[global] Hint Resolve ex_intro ex_intro2: core. Register eq as core.eq.type. Register eq_refl as core.eq.refl. Register eq_ind as core.eq.ind. Register eq_sind as core.eq.sind. Register eq_rect as core.eq.rect. Register eq_rec as core.eq.rec. Scheme Rewriting for eq. Register eq_rew_dep as core.eq.rect_dep. Register eq_rew_dep as core.eq.ind_dep. Register eq_rew_r_dep as core.eq.rect_r_dep. Register eq_rew_r_dep as core.eq.ind_r_dep. Arguments eq_sym_involutive [A]%_type_scope [x y] e : rename. Section Logic_lemmas. Theorem absurd : forall A C:Prop, A -> ~ A -> C. Proof. unfold not; intros A C h1 h2. destruct (h2 h1). Qed. Section equality. Variables A B : Type. Variable f : A -> B. Variables x y z : A. Register eq_sym as core.eq.sym. Theorem eq_trans : x = y -> y = z -> x = z. Proof. destruct 2; trivial. Defined. 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. Defined. Register f_equal as core.eq.congr. Theorem not_eq_sym : x <> y -> y <> x. Proof. red; intros h1 h2; apply h1; destruct h2; trivial. Qed. End equality. Definition eq_sind_r : forall (A:Type) (x:A) (P:A -> SProp), P x -> forall y:A, y = x -> P y. Proof. intros A x P H y H0. elim eq_sym with (1 := H0); assumption. Defined. Definition eq_ind_r : forall (A:Type) (x:A) (P:A -> Prop), P x -> forall y:A, y = x -> P y. intros A x P H y H0. elim eq_sym with (1 := H0); assumption. Defined. Register eq_ind_r as core.eq.ind_r. Register eq_sind_r as core.eq.sind_r. Definition eq_rec_r : forall (A:Type) (x:A) (P:A -> Set), P x -> forall y:A, y = x -> P y. intros A x P H y H0; elim eq_sym with (1 := H0); assumption. Defined. Definition eq_rect_r : forall (A:Type) (x:A) (P:A -> Type), P x -> forall y:A, y = x -> P y. intros A x P H y H0; elim eq_sym with (1 := H0); assumption. Defined. Register eq_rect_r as core.eq.rect_r. Register eq_rec_r as core.eq.rec_r. End Logic_lemmas. Module EqNotations. Notation "'rew' H 'in' H'" := (eq_rect _ _ H' _ H) (at level 10, H' at level 10, format "'[' 'rew' H in '/' H' ']'"). Notation "'rew' [ P ] H 'in' H'" := (eq_rect _ P H' _ H) (at level 10, H' at level 10, format "'[' 'rew' [ P ] '/ ' H in '/' H' ']'"). Notation "'rew' <- H 'in' H'" := (eq_rect_r _ H' H) (at level 10, H' at level 10, format "'[' 'rew' <- H in '/' H' ']'"). Notation "'rew' <- [ P ] H 'in' H'" := (eq_rect_r P H' H) (at level 10, H' at level 10, format "'[' 'rew' <- [ P ] '/ ' H in '/' H' ']'"). Notation "'rew' -> H 'in' H'" := (eq_rect _ _ H' _ H) (at level 10, H' at level 10, only parsing). Notation "'rew' -> [ P ] H 'in' H'" := (eq_rect _ P H' _ H) (at level 10, H' at level 10, only parsing). Notation "'rew' 'dependent' H 'in' H'" := (match H with | eq_refl => H' end) (at level 10, H' at level 10, format "'[' 'rew' 'dependent' '/ ' H in '/' H' ']'"). Notation "'rew' 'dependent' -> H 'in' H'" := (match H with | eq_refl => H' end) (at level 10, H' at level 10, only parsing). Notation "'rew' 'dependent' <- H 'in' H'" := (match eq_sym H with | eq_refl => H' end) (at level 10, H' at level 10, format "'[' 'rew' 'dependent' <- '/ ' H in '/' H' ']'"). Notation "'rew' 'dependent' [ 'fun' y p => P ] H 'in' H'" := (match H as p in (_ = y) return P with | eq_refl => H' end) (at level 10, H' at level 10, y name, p name, format "'[' 'rew' 'dependent' [ 'fun' y p => P ] '/ ' H in '/' H' ']'"). Notation "'rew' 'dependent' -> [ 'fun' y p => P ] H 'in' H'" := (match H as p in (_ = y) return P with | eq_refl => H' end) (at level 10, H' at level 10, y name, p name, only parsing). Notation "'rew' 'dependent' <- [ 'fun' y p => P ] H 'in' H'" := (match eq_sym H as p in (_ = y) return P with | eq_refl => H' end) (at level 10, H' at level 10, y name, p name, format "'[' 'rew' 'dependent' <- [ 'fun' y p => P ] '/ ' H in '/' H' ']'"). Notation "'rew' 'dependent' [ P ] H 'in' H'" := (match H as p in (_ = y) return P y p with | eq_refl => H' end) (at level 10, H' at level 10, format "'[' 'rew' 'dependent' [ P ] '/ ' H in '/' H' ']'"). Notation "'rew' 'dependent' -> [ P ] H 'in' H'" := (match H as p in (_ = y) return P y p with | eq_refl => H' end) (at level 10, H' at level 10, only parsing). Notation "'rew' 'dependent' <- [ P ] H 'in' H'" := (match eq_sym H as p in (_ = y) return P y p with | eq_refl => H' end) (at level 10, H' at level 10, format "'[' 'rew' 'dependent' <- [ P ] '/ ' H in '/' H' ']'"). End EqNotations. Import EqNotations. Section equality_dep. Variable A : Type. Variable B : A -> Type. Variable f : forall x, B x. Variables x y : A. Theorem f_equal_dep (H: x = y) : rew H in f x = f y. Proof. destruct H; reflexivity. Defined. End equality_dep. Lemma f_equal_dep2 {A A' B B'} (f : A -> A') (g : forall a:A, B a -> B' (f a)) {x1 x2 : A} {y1 : B x1} {y2 : B x2} (H : x1 = x2) : rew H in y1 = y2 -> rew f_equal f H in g x1 y1 = g x2 y2. Proof. destruct H, 1. reflexivity. Defined. Lemma rew_opp_r A (P:A->Type) (x y:A) (H:x=y) (a:P y) : rew H in rew <- H in a = a. Proof. destruct H. reflexivity. Defined. Lemma rew_opp_l A (P:A->Type) (x y:A) (H:x=y) (a:P x) : rew <- H in rew H in a = a. Proof. destruct H. reflexivity. Defined. Theorem f_equal2 : forall (A1 A2 B:Type) (f:A1 -> A2 -> B) (x1 y1:A1) (x2 y2:A2), x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2. Proof. destruct 1; destruct 1; reflexivity. Qed. Register f_equal2 as core.eq.congr2. Theorem f_equal3 : forall (A1 A2 A3 B:Type) (f:A1 -> A2 -> A3 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3), x1 = y1 -> x2 = y2 -> x3 = y3 -> f x1 x2 x3 = f y1 y2 y3. Proof. destruct 1; destruct 1; destruct 1; reflexivity. Qed. Theorem f_equal4 : forall (A1 A2 A3 A4 B:Type) (f:A1 -> A2 -> A3 -> A4 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3) (x4 y4:A4), x1 = y1 -> x2 = y2 -> x3 = y3 -> x4 = y4 -> f x1 x2 x3 x4 = f y1 y2 y3 y4. Proof. destruct 1; destruct 1; destruct 1; destruct 1; reflexivity. Qed. Theorem f_equal5 : forall (A1 A2 A3 A4 A5 B:Type) (f:A1 -> A2 -> A3 -> A4 -> A5 -> B) (x1 y1:A1) (x2 y2:A2) (x3 y3:A3) (x4 y4:A4) (x5 y5:A5), x1 = y1 -> x2 = y2 -> x3 = y3 -> x4 = y4 -> x5 = y5 -> f x1 x2 x3 x4 x5 = f y1 y2 y3 y4 y5. Proof. destruct 1; destruct 1; destruct 1; destruct 1; destruct 1; reflexivity. Qed. Theorem f_equal_compose A B C (a b:A) (f:A->B) (g:B->C) (e:a=b) : f_equal g (f_equal f e) = f_equal (fun a => g (f a)) e. Proof. destruct e. reflexivity. Defined. (** The groupoid structure of equality *) Theorem eq_trans_refl_l A (x y:A) (e:x=y) : eq_trans eq_refl e = e. Proof. destruct e. reflexivity. Defined. Theorem eq_trans_refl_r A (x y:A) (e:x=y) : eq_trans e eq_refl = e. Proof. destruct e. reflexivity. Defined. Theorem eq_trans_sym_inv_l A (x y:A) (e:x=y) : eq_trans (eq_sym e) e = eq_refl. Proof. destruct e; reflexivity. Defined. Theorem eq_trans_sym_inv_r A (x y:A) (e:x=y) : eq_trans e (eq_sym e) = eq_refl. Proof. destruct e; reflexivity. Defined. Theorem eq_trans_assoc A (x y z t:A) (e:x=y) (e':y=z) (e'':z=t) : eq_trans e (eq_trans e' e'') = eq_trans (eq_trans e e') e''. Proof. destruct e''; reflexivity. Defined. Theorem rew_map A B (P:B->Type) (f:A->B) x1 x2 (H:x1=x2) (y:P (f x1)) : rew [fun x => P (f x)] H in y = rew f_equal f H in y. Proof. destruct H; reflexivity. Defined. Theorem eq_trans_map {A B} {x1 x2 x3:A} {y1:B x1} {y2:B x2} {y3:B x3} (H1:x1=x2) (H2:x2=x3) (H1': rew H1 in y1 = y2) (H2': rew H2 in y2 = y3) : rew eq_trans H1 H2 in y1 = y3. Proof. destruct H2. exact (eq_trans H1' H2'). Defined. Lemma map_subst {A} {P Q:A->Type} (f : forall x, P x -> Q x) {x y} (H:x=y) (z:P x) : rew H in f x z = f y (rew H in z). Proof. destruct H. reflexivity. Defined. Lemma map_subst_map {A B} {P:A->Type} {Q:B->Type} (f:A->B) (g : forall x, P x -> Q (f x)) {x y} (H:x=y) (z:P x) : rew f_equal f H in g x z = g y (rew H in z). Proof. destruct H. reflexivity. Defined. Lemma rew_swap A (P:A->Type) x1 x2 (H:x1=x2) (y1:P x1) (y2:P x2) : rew H in y1 = y2 -> y1 = rew <- H in y2. Proof. destruct H. trivial. Defined. Lemma rew_compose A (P:A->Type) x1 x2 x3 (H1:x1=x2) (H2:x2=x3) (y:P x1) : rew H2 in rew H1 in y = rew (eq_trans H1 H2) in y. Proof. destruct H2. reflexivity. Defined. (** Extra properties of equality *) Theorem eq_id_comm_l A (f:A->A) (Hf:forall a, a = f a) a : f_equal f (Hf a) = Hf (f a). Proof. unfold f_equal. rewrite <- (eq_trans_sym_inv_l (Hf a)). destruct (Hf a) at 1 2. destruct (Hf a). reflexivity. Defined. Theorem eq_id_comm_r A (f:A->A) (Hf:forall a, f a = a) a : f_equal f (Hf a) = Hf (f a). Proof. unfold f_equal. rewrite <- (eq_trans_sym_inv_l (Hf (f (f a)))). set (Hfsymf := fun a => eq_sym (Hf a)). change (eq_sym (Hf (f (f a)))) with (Hfsymf (f (f a))). pattern (Hfsymf (f (f a))). destruct (eq_id_comm_l f Hfsymf (f a)). destruct (eq_id_comm_l f Hfsymf a). unfold Hfsymf. destruct (Hf a). simpl. rewrite eq_trans_refl_l. reflexivity. Defined. Lemma eq_refl_map_distr A B x (f:A->B) : f_equal f (eq_refl x) = eq_refl (f x). Proof. reflexivity. Qed. Lemma eq_trans_map_distr A B x y z (f:A->B) (e:x=y) (e':y=z) : f_equal f (eq_trans e e') = eq_trans (f_equal f e) (f_equal f e'). Proof. destruct e'. reflexivity. Defined. Lemma eq_sym_map_distr A B (x y:A) (f:A->B) (e:x=y) : eq_sym (f_equal f e) = f_equal f (eq_sym e). Proof. destruct e. reflexivity. Defined. Lemma eq_trans_sym_distr A (x y z:A) (e:x=y) (e':y=z) : eq_sym (eq_trans e e') = eq_trans (eq_sym e') (eq_sym e). Proof. destruct e, e'. reflexivity. Defined. Lemma eq_trans_rew_distr A (P:A -> Type) (x y z:A) (e:x=y) (e':y=z) (k:P x) : rew (eq_trans e e') in k = rew e' in rew e in k. Proof. destruct e, e'; reflexivity. Qed. Lemma rew_const A P (x y:A) (e:x=y) (k:P) : rew [fun _ => P] e in k = k. Proof. destruct e; reflexivity. Qed. (* Aliases *) Abbreviation sym_eq := eq_sym (only parsing). Abbreviation trans_eq := eq_trans (only parsing). Abbreviation sym_not_eq := not_eq_sym (only parsing). Abbreviation refl_equal := eq_refl (only parsing). Abbreviation sym_equal := eq_sym (only parsing). Abbreviation trans_equal := eq_trans (only parsing). Abbreviation sym_not_equal := not_eq_sym (only parsing). #[global] Hint Immediate eq_sym not_eq_sym: core. (** Basic definitions about relations and properties *) Definition subrelation (A B : Type) (R R' : A->B->Prop) := forall x y, R x y -> R' x y. Definition unique (A : Type) (P : A->Prop) (x:A) := P x /\ forall (x':A), P x' -> x=x'. Definition uniqueness (A:Type) (P:A->Prop) := forall x y, P x -> P y -> x = y. (** Unique existence *) Notation "'exists' ! x .. y , p" := (ex (unique (fun x => .. (ex (unique (fun y => p))) ..))) (at level 200, x binder, right associativity, format "'[' 'exists' ! '/ ' x .. y , '/ ' p ']'") : type_scope. Lemma unique_existence : forall (A:Type) (P:A->Prop), ((exists x, P x) /\ uniqueness P) <-> (exists! x, P x). Proof. intros A P; split. - intros ((x,Hx),Huni); exists x; red; auto. - intros (x,(Hx,Huni)); split. + exists x; assumption. + intros x' x'' Hx' Hx''; transitivity x. * symmetry; auto. * auto. Qed. Lemma forall_exists_unique_domain_coincide : forall A (P:A->Prop), (exists! x, P x) -> forall Q:A->Prop, (forall x, P x -> Q x) <-> (exists x, P x /\ Q x). Proof. intros A P (x & Hp & Huniq); split. - intro; exists x; auto. - intros (x0 & HPx0 & HQx0) x1 HPx1. assert (H : x0 = x1) by (transitivity x; [symmetry|]; auto). destruct H. assumption. Qed. Lemma forall_exists_coincide_unique_domain : forall A (P:A->Prop), (forall Q:A->Prop, (forall x, P x -> Q x) <-> (exists x, P x /\ Q x)) -> (exists! x, P x). Proof. intros A P H. destruct (H P) as ((x & Hx & _),_); [trivial|]. exists x. split; [trivial|]. destruct (H (fun x'=>x=x')) as (_,Huniq). apply Huniq. exists x; auto. Qed. (** * Being inhabited *) (** The predicate [inhabited] can be used in different contexts. If [A] is thought as a type, [inhabited A] states that [A] is inhabited. If [A] is thought as a computationally relevant proposition, then [inhabited A] weakens [A] so as to hide its computational meaning. The so-weakened proof remains computationally relevant but only in a propositional context. *) Inductive inhabited (A:Type) : Prop := inhabits : A -> inhabited A. #[global] Hint Resolve inhabits: core. Lemma exists_inhabited : forall (A:Type) (P:A->Prop), (exists x, P x) -> inhabited A. Proof. destruct 1; auto. Qed. Lemma inhabited_covariant (A B : Type) : (A -> B) -> inhabited A -> inhabited B. Proof. intros f [x];exact (inhabits (f x)). Qed. (** Declaration of stepl and stepr for eq and iff *) Lemma eq_stepl : forall (A : Type) (x y z : A), x = y -> x = z -> z = y. Proof. intros A x y z H1 H2. rewrite <- H2; exact H1. Qed. Declare Left Step eq_stepl. Declare Right Step eq_trans. Lemma iff_stepl : forall A B C : Prop, (A <-> B) -> (A <-> C) -> (C <-> B). Proof. intros ? ? ? [? ?] [? ?]; split; intros; auto. Qed. Declare Left Step iff_stepl. Declare Right Step iff_trans. (** More properties of [ex] and [ex2] that rely on equality being present *) (** We define restricted versions of [ex_rect] and [ex_rec] which allow elimination into non-Prop sorts when the inductive is not informative *) (** Ξ· Principles *) Definition ex_eta {A : Prop} {P} (p : exists a : A, P a) : p = ex_intro _ (ex_proj1 p) (ex_proj2 p). Proof. destruct p; reflexivity. Defined. Definition ex2_eta {A : Prop} {P Q} (p : exists2 a : A, P a & Q a) : p = ex_intro2 _ _ (ex_proj1 (ex_of_ex2 p)) (ex_proj2 (ex_of_ex2 p)) (ex_proj3 p). Proof. destruct p; reflexivity. Defined. Section ex_Prop. Variables (A:Prop) (P:A->Prop). Definition ex_rect (P0 : ex P -> Type) (f : forall x p, P0 (ex_intro P x p)) : forall e, P0 e := fun e => rew <- ex_eta e in f _ _. Definition ex_rec : forall (P0 : ex P -> Set) (f : forall x p, P0 (ex_intro P x p)), forall e, P0 e := ex_rect. End ex_Prop. (** Equality for [ex] *) Section ex. Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition ex_proj1_eq {A : Prop} {P : A -> Prop} {u v : exists a : A, P a} (p : u = v) : ex_proj1 u = ex_proj1 v := f_equal (@ex_proj1 _ _) p. (** Projecting an equality of a pair to equality of the second components *) Definition ex_proj2_eq {A : Prop} {P : A -> Prop} {u v : exists a : A, P a} (p : u = v) : rew ex_proj1_eq p in ex_proj2 u = ex_proj2 v := rew dependent p in eq_refl. (** Equality of [ex] is itself a [ex] (forwards-reasoning version) *) Definition eq_ex_intro_uncurried {A : Type} {P : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (pq : exists p : u1 = v1, rew p in u2 = v2) : ex_intro _ u1 u2 = ex_intro _ v1 v2. Proof. destruct pq as [p q]. destruct q; simpl in *. destruct p; reflexivity. Defined. (** Equality of [ex] is itself a [ex] (backwards-reasoning version) *) Definition eq_ex_uncurried {A : Prop} {P : A -> Prop} (u v : exists a : A, P a) (pq : exists p : ex_proj1 u = ex_proj1 v, rew p in ex_proj2 u = ex_proj2 v) : u = v. Proof. destruct u as [u1 u2], v as [v1 v2]; simpl in *. apply eq_ex_intro_uncurried; exact pq. Defined. (** Curried version of proving equality of [ex] types *) Definition eq_ex_intro {A : Type} {P : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) (q : rew p in u2 = v2) : ex_intro _ u1 u2 = ex_intro _ v1 v2 := eq_ex_intro_uncurried (ex_intro _ p q). (** Curried version of proving equality of [ex] types *) Definition eq_ex {A : Prop} {P : A -> Prop} (u v : exists a : A, P a) (p : ex_proj1 u = ex_proj1 v) (q : rew p in ex_proj2 u = ex_proj2 v) : u = v := eq_ex_uncurried u v (ex_intro _ p q). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_ex_intro_l {A : Prop} {P : A -> Prop} u1 u2 (v : exists a : A, P a) (p : u1 = ex_proj1 v) (q : rew p in u2 = ex_proj2 v) : ex_intro P u1 u2 = v := eq_ex (ex_intro P u1 u2) v p q. Definition eq_ex_intro_r {A : Prop} {P : A -> Prop} (u : exists a : A, P a) v1 v2 (p : ex_proj1 u = v1) (q : rew p in ex_proj2 u = v2) : u = ex_intro P v1 v2 := eq_ex u (ex_intro P v1 v2) p q. (** Induction principle for [@eq (ex _)] *) Definition eq_ex_eta {A : Prop} {P : A -> Prop} {u v : exists a : A, P a} (p : u = v) : p = eq_ex u v (ex_proj1_eq p) (ex_proj2_eq p). Proof. destruct p, u; reflexivity. Defined. Definition eq_ex_rect {A : Prop} {P : A -> Prop} {u v : exists a : A, P a} (Q : u = v -> Type) (f : forall p q, Q (eq_ex u v p q)) : forall p, Q p := fun p => rew <- eq_ex_eta p in f _ _. Definition eq_ex_rec {A : Prop} {P : A -> Prop} {u v} (Q : u = v :> (exists a : A, P a) -> Set) := eq_ex_rect Q. Definition eq_ex_ind {A : Prop} {P : A -> Prop} {u v} (Q : u = v :> (exists a : A, P a) -> Prop) := eq_ex_rec Q. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_ex_rect_ex_intro_l {A : Prop} {P : A -> Prop} {u1 u2 v} (Q : _ -> Type) (f : forall p q, Q (eq_ex_intro_l (P:=P) u1 u2 v p q)) : forall p, Q p := eq_ex_rect Q f. Definition eq_ex_rect_ex_intro_r {A : Prop} {P : A -> Prop} {u v1 v2} (Q : _ -> Type) (f : forall p q, Q (eq_ex_intro_r (P:=P) u v1 v2 p q)) : forall p, Q p := eq_ex_rect Q f. Definition eq_ex_rect_ex_intro {A : Prop} {P : A -> Prop} {u1 u2 v1 v2} (Q : _ -> Type) (f : forall p q, Q (@eq_ex_intro A P u1 v1 u2 v2 p q)) : forall p, Q p := eq_ex_rect Q f. Definition eq_ex_rect_uncurried {A : Prop} {P : A -> Prop} {u v : exists a : A, P a} (Q : u = v -> Type) (f : forall pq, Q (eq_ex u v (ex_proj1 pq) (ex_proj2 pq))) : forall p, Q p := eq_ex_rect Q (fun p q => f (ex_intro _ p q)). Definition eq_ex_rec_uncurried {A : Prop} {P : A -> Prop} {u v} (Q : u = v :> (exists a : A, P a) -> Set) := eq_ex_rect_uncurried Q. Definition eq_ex_ind_uncurried {A : Prop} {P : A -> Prop} {u v} (Q : u = v :> (exists a : A, P a) -> Prop) := eq_ex_rec_uncurried Q. (** Equality of [ex] when the property is an hProp *) Definition eq_ex_hprop {A : Prop} {P : A -> Prop} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : exists a : A, P a) (p : ex_proj1 u = ex_proj1 v) : u = v := eq_ex u v p (P_hprop _ _ _). Definition eq_ex_intro_hprop {A : Type} {P : A -> Prop} (P_hprop : forall (x : A) (p q : P x), p = q) {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) : ex_intro P u1 u2 = ex_intro P v1 v2 := eq_ex_intro p (P_hprop _ _ _). (** Equivalence of equality of [ex] with a [ex] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_ex_uncurried_iff {A : Prop} {P : A -> Prop} (u v : exists a : A, P a) : u = v <-> exists p : ex_proj1 u = ex_proj1 v, rew p in ex_proj2 u = ex_proj2 v. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_ex_uncurried ]. Defined. (** Equivalence of equality of [ex] involving hProps with equality of the first components *) Definition eq_ex_hprop_iff {A : Prop} {P : A -> Prop} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : exists a : A, P a) : u = v <-> (ex_proj1 u = ex_proj1 v) := conj (fun p => f_equal (@ex_proj1 _ _) p) (eq_ex_hprop P_hprop u v). Lemma rew_ex {A' : Type} {x} {P : A' -> Prop} (Q : forall a, P a -> Prop) (u : exists p : P x, Q x p) {y} (H : x = y) : rew [fun a => exists p : P a, Q a p] H in u = ex_intro (Q y) (rew H in ex_proj1 u) (rew dependent H in ex_proj2 u). Proof. destruct H, u; reflexivity. Defined. End ex. Global Arguments eq_ex_intro A P _ _ _ _ !p !q / . Section ex2_Prop. Variables (A:Prop) (P Q:A->Prop). Definition ex2_rect (P0 : ex2 P Q -> Type) (f : forall x p q, P0 (ex_intro2 P Q x p q)) : forall e, P0 e := fun e => rew <- ex2_eta e in f _ _ _. Definition ex2_rec : forall (P0 : ex2 P Q -> Set) (f : forall x p q, P0 (ex_intro2 P Q x p q)), forall e, P0 e := ex2_rect. End ex2_Prop. (** Equality for [ex2] *) Section ex2. (* We make [ex_of_ex2] a coercion so we can use [proj1], [proj2] on [ex2] *) Local Coercion ex_of_ex2 : ex2 >-> ex. Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition ex_of_ex2_eq {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (p : u = v) : u = v :> exists a : A, P a := f_equal _ p. Definition ex_proj1_of_ex2_eq {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (p : u = v) : ex_proj1 u = ex_proj1 v := ex_proj1_eq (ex_of_ex2_eq p). (** Projecting an equality of a pair to equality of the second components *) Definition ex_proj2_of_ex2_eq {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (p : u = v) : rew ex_proj1_of_ex2_eq p in ex_proj2 u = ex_proj2 v := rew dependent p in eq_refl. (** Projecting an equality of a pair to equality of the third components *) Definition ex_proj3_eq {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (p : u = v) : rew ex_proj1_of_ex2_eq p in ex_proj3 u = ex_proj3 v := rew dependent p in eq_refl. (** Equality of [ex2] is itself a [ex2] (fowards-reasoning version) *) Definition eq_ex_intro2_uncurried {A : Type} {P Q : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (pqr : exists2 p : u1 = v1, rew p in u2 = v2 & rew p in u3 = v3) : ex_intro2 _ _ u1 u2 u3 = ex_intro2 _ _ v1 v2 v3. Proof. destruct pqr as [p q r]. destruct r, q, p; simpl. reflexivity. Defined. (** Equality of [ex2] is itself a [ex2] (backwards-reasoning version) *) Definition eq_ex2_uncurried {A : Prop} {P Q : A -> Prop} (u v : exists2 a : A, P a & Q a) (pqr : exists2 p : ex_proj1 u = ex_proj1 v, rew p in ex_proj2 u = ex_proj2 v & rew p in ex_proj3 u = ex_proj3 v) : u = v. Proof. destruct u as [u1 u2 u3], v as [v1 v2 v3]; simpl in *. apply eq_ex_intro2_uncurried; exact pqr. Defined. (** Curried version of proving equality of [ex] types *) Definition eq_ex2 {A : Prop} {P Q : A -> Prop} (u v : exists2 a : A, P a & Q a) (p : ex_proj1 u = ex_proj1 v) (q : rew p in ex_proj2 u = ex_proj2 v) (r : rew p in ex_proj3 u = ex_proj3 v) : u = v := eq_ex2_uncurried u v (ex_intro2 _ _ p q r). Definition eq_ex_intro2 {A : Type} {P Q : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (p : u1 = v1) (q : rew p in u2 = v2) (r : rew p in u3 = v3) : ex_intro2 P Q u1 u2 u3 = ex_intro2 P Q v1 v2 v3 := eq_ex_intro2_uncurried (ex_intro2 _ _ p q r). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_ex_intro2_l {A : Prop} {P Q : A -> Prop} u1 u2 u3 (v : exists2 a : A, P a & Q a) (p : u1 = ex_proj1 v) (q : rew p in u2 = ex_proj2 v) (r : rew p in u3 = ex_proj3 v) : ex_intro2 P Q u1 u2 u3 = v := eq_ex2 (ex_intro2 P Q u1 u2 u3) v p q r. Definition eq_ex_intro2_r {A : Prop} {P Q : A -> Prop} (u : exists2 a : A, P a & Q a) v1 v2 v3 (p : ex_proj1 u = v1) (q : rew p in ex_proj2 u = v2) (r : rew p in ex_proj3 u = v3) : u = ex_intro2 P Q v1 v2 v3 := eq_ex2 u (ex_intro2 P Q v1 v2 v3) p q r. (** Equality of [ex2] when the second property is an hProp *) Definition eq_ex2_hprop {A : Prop} {P Q : A -> Prop} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : exists2 a : A, P a & Q a) (p : u = v :> exists a : A, P a) : u = v := eq_ex2 u v (ex_proj1_eq p) (ex_proj2_eq p) (Q_hprop _ _ _). Definition eq_ex_intro2_hprop_nondep {A : Type} {P : A -> Prop} {Q : Prop} (Q_hprop : forall (p q : Q), p = q) {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 v3 : Q} (p : ex_intro _ u1 u2 = ex_intro _ v1 v2) : ex_intro2 _ _ u1 u2 u3 = ex_intro2 _ _ v1 v2 v3 := rew [fun v3 => _ = ex_intro2 _ _ _ _ v3] (Q_hprop u3 v3) in f_equal (fun u => match u with ex_intro _ u1 u2 => ex_intro2 _ _ u1 u2 u3 end) p. Definition eq_ex_intro2_hprop {A : Type} {P Q : A -> Prop} (P_hprop : forall x (p q : P x), p = q) (Q_hprop : forall x (p q : Q x), p = q) {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (p : u1 = v1) : ex_intro2 P Q u1 u2 u3 = ex_intro2 P Q v1 v2 v3 := eq_ex_intro2 p (P_hprop _ _ _) (Q_hprop _ _ _). (** Equivalence of equality of [ex2] with a [ex2] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_ex2_uncurried_iff {A : Prop} {P Q : A -> Prop} (u v : exists2 a : A, P a & Q a) : u = v <-> exists2 p : ex_proj1 u = ex_proj1 v, rew p in ex_proj2 u = ex_proj2 v & rew p in ex_proj3 u = ex_proj3 v. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_ex2_uncurried ]. Defined. (** Induction principle for [@eq (ex2 _ _)] *) Definition eq_ex2_eta {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (p : u = v) : p = eq_ex2 u v (ex_proj1_of_ex2_eq p) (ex_proj2_of_ex2_eq p) (ex_proj3_eq p). Proof. destruct p, u; reflexivity. Defined. Definition eq_ex2_rect {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (R : u = v -> Type) (f : forall p q r, R (eq_ex2 u v p q r)) : forall p, R p := fun p => rew <- eq_ex2_eta p in f _ _ _. Definition eq_ex2_rec {A : Prop} {P Q : A -> Prop} {u v} (R : u = v :> (exists2 a : A, P a & Q a) -> Set) := eq_ex2_rect R. Definition eq_ex2_ind {A : Prop} {P Q : A -> Prop} {u v} (R : u = v :> (exists2 a : A, P a & Q a) -> Prop) := eq_ex2_rec R. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_ex2_rect_ex_intro2_l {A : Prop} {P Q : A -> Prop} {u1 u2 u3 v} (R : _ -> Type) (f : forall p q r, R (eq_ex_intro2_l (P:=P) (Q:=Q) u1 u2 u3 v p q r)) : forall p, R p := eq_ex2_rect R f. Definition eq_ex2_rect_ex_intro2_r {A : Prop} {P Q : A -> Prop} {u v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (eq_ex_intro2_r (P:=P) (Q:=Q) u v1 v2 v3 p q r)) : forall p, R p := eq_ex2_rect R f. Definition eq_ex2_rect_ex_intro2 {A : Prop} {P Q : A -> Prop} {u1 u2 u3 v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (@eq_ex_intro2 A P Q u1 v1 u2 v2 u3 v3 p q r)) : forall p, R p := eq_ex2_rect R f. Definition eq_ex2_rect_uncurried {A : Prop} {P Q : A -> Prop} {u v : exists2 a : A, P a & Q a} (R : u = v -> Type) (f : forall pqr : exists2 p : _ = _, _ & _, R (eq_ex2 u v (ex_proj1 pqr) (ex_proj2 pqr) (ex_proj3 pqr))) : forall p, R p := eq_ex2_rect R (fun p q r => f (ex_intro2 _ _ p q r)). Definition eq_ex2_rec_uncurried {A : Prop} {P Q : A -> Prop} {u v} (R : u = v :> (exists2 a : A, P a & Q a) -> Set) := eq_ex2_rect_uncurried R. Definition eq_ex2_ind_uncurried {A : Prop} {P Q : A -> Prop} {u v} (R : u = v :> (exists2 a : A, P a & Q a) -> Prop) := eq_ex2_rec_uncurried R. (** Equivalence of equality of [ex2] involving hProps with equality of the first components *) Definition eq_ex2_hprop_iff {A : Prop} {P Q : A -> Prop} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : exists2 a : A, P a & Q a) : u = v <-> (u = v :> exists a : A, P a) := conj (fun p => f_equal (@ex_of_ex2 _ _ _) p) (eq_ex2_hprop Q_hprop u v). (** Non-dependent classification of equality of [ex] *) Definition eq_ex2_nondep {A : Prop} {B C : Prop} (u v : @ex2 A (fun _ => B) (fun _ => C)) (p : ex_proj1 u = ex_proj1 v) (q : ex_proj2 u = ex_proj2 v) (r : ex_proj3 u = ex_proj3 v) : u = v := @eq_ex2 _ _ _ u v p (eq_trans (rew_const _ _) q) (eq_trans (rew_const _ _) r). (** Classification of transporting across an equality of [ex2]s *) Lemma rew_ex2 {A' : Type} {x} {P : A' -> Prop} (Q R : forall a, P a -> Prop) (u : exists2 p : P x, Q x p & R x p) {y} (H : x = y) : rew [fun a => exists2 p : P a, Q a p & R a p] H in u = ex_intro2 (Q y) (R y) (rew H in ex_proj1 u) (rew dependent H in ex_proj2 u) (rew dependent H in ex_proj3 u). Proof. destruct H, u; reflexivity. Defined. End ex2. Global Arguments eq_ex_intro2 A P Q _ _ _ _ _ _ !p !q !r / . rocq-9.2.0/theories/Corelib/Init/Ltac.v000066400000000000000000000022511516144147600176550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* n | S u => u end. Register pred as num.nat.pred. Fixpoint add n m := match n with | 0 => m | S p => S (p + m) end where "n + m" := (add n m) : nat_scope. Register add as num.nat.add. Definition double n := n + n. Fixpoint mul n m := match n with | 0 => 0 | S p => m + p * m end where "n * m" := (mul n m) : nat_scope. Register mul as num.nat.mul. (** Truncated subtraction: [n-m] is [0] if [n<=m] *) Fixpoint sub n m := match n, m with | S k, S l => k - l | _, _ => n end where "n - m" := (sub n m) : nat_scope. Register sub as num.nat.sub. (** ** Comparisons *) Fixpoint eqb n m : bool := match n, m with | 0, 0 => true | 0, S _ => false | S _, 0 => false | S n', S m' => eqb n' m' end. Fixpoint leb n m : bool := match n, m with | 0, _ => true | _, 0 => false | S n', S m' => leb n' m' end. Definition ltb n m := leb (S n) m. Infix "=?" := eqb (at level 70) : nat_scope. Infix "<=?" := leb (at level 70) : nat_scope. Infix " Eq | 0, S _ => Lt | S _, 0 => Gt | S n', S m' => compare n' m' end. Infix "?=" := compare (at level 70) : nat_scope. (** ** Minimum, maximum *) Fixpoint max n m := match n, m with | 0, _ => m | S n', 0 => n | S n', S m' => S (max n' m') end. Fixpoint min n m := match n, m with | 0, _ => 0 | S n', 0 => 0 | S n', S m' => S (min n' m') end. (** ** Parity tests *) Fixpoint even n : bool := match n with | 0 => true | 1 => false | S (S n') => even n' end. Definition odd n := negb (even n). (** ** Power *) Fixpoint pow n m := match m with | 0 => 1 | S m => n * (n^m) end where "n ^ m" := (pow n m) : nat_scope. (** ** Tail-recursive versions of [add] and [mul] *) Fixpoint tail_add n m := match n with | O => m | S n => tail_add n (S m) end. (** [tail_addmul r n m] is [r + n * m]. *) Fixpoint tail_addmul r n m := match n with | O => r | S n => tail_addmul (tail_add m r) n m end. Definition tail_mul n m := tail_addmul 0 n m. (** ** Conversion with a decimal representation for printing/parsing *) Local Abbreviation ten := (S (S (S (S (S (S (S (S (S (S O)))))))))). Fixpoint of_uint_acc (d:Decimal.uint)(acc:nat) := match d with | Decimal.Nil => acc | Decimal.D0 d => of_uint_acc d (tail_mul ten acc) | Decimal.D1 d => of_uint_acc d (S (tail_mul ten acc)) | Decimal.D2 d => of_uint_acc d (S (S (tail_mul ten acc))) | Decimal.D3 d => of_uint_acc d (S (S (S (tail_mul ten acc)))) | Decimal.D4 d => of_uint_acc d (S (S (S (S (tail_mul ten acc))))) | Decimal.D5 d => of_uint_acc d (S (S (S (S (S (tail_mul ten acc)))))) | Decimal.D6 d => of_uint_acc d (S (S (S (S (S (S (tail_mul ten acc))))))) | Decimal.D7 d => of_uint_acc d (S (S (S (S (S (S (S (tail_mul ten acc)))))))) | Decimal.D8 d => of_uint_acc d (S (S (S (S (S (S (S (S (tail_mul ten acc))))))))) | Decimal.D9 d => of_uint_acc d (S (S (S (S (S (S (S (S (S (tail_mul ten acc)))))))))) end. Definition of_uint (d:Decimal.uint) := of_uint_acc d O. Local Abbreviation sixteen := (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))). Fixpoint of_hex_uint_acc (d:Hexadecimal.uint)(acc:nat) := match d with | Hexadecimal.Nil => acc | Hexadecimal.D0 d => of_hex_uint_acc d (tail_mul sixteen acc) | Hexadecimal.D1 d => of_hex_uint_acc d (S (tail_mul sixteen acc)) | Hexadecimal.D2 d => of_hex_uint_acc d (S (S (tail_mul sixteen acc))) | Hexadecimal.D3 d => of_hex_uint_acc d (S (S (S (tail_mul sixteen acc)))) | Hexadecimal.D4 d => of_hex_uint_acc d (S (S (S (S (tail_mul sixteen acc))))) | Hexadecimal.D5 d => of_hex_uint_acc d (S (S (S (S (S (tail_mul sixteen acc)))))) | Hexadecimal.D6 d => of_hex_uint_acc d (S (S (S (S (S (S (tail_mul sixteen acc))))))) | Hexadecimal.D7 d => of_hex_uint_acc d (S (S (S (S (S (S (S (tail_mul sixteen acc)))))))) | Hexadecimal.D8 d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (tail_mul sixteen acc))))))))) | Hexadecimal.D9 d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc)))))))))) | Hexadecimal.Da d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc))))))))))) | Hexadecimal.Db d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc)))))))))))) | Hexadecimal.Dc d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc))))))))))))) | Hexadecimal.Dd d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc)))))))))))))) | Hexadecimal.De d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc))))))))))))))) | Hexadecimal.Df d => of_hex_uint_acc d (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (tail_mul sixteen acc)))))))))))))))) end. Definition of_hex_uint (d:Hexadecimal.uint) := of_hex_uint_acc d O. Definition of_num_uint (d:Number.uint) := match d with | Number.UIntDecimal d => of_uint d | Number.UIntHexadecimal d => of_hex_uint d end. Fixpoint to_little_uint n acc := match n with | O => acc | S n => to_little_uint n (Decimal.Little.succ acc) end. Definition to_uint n := Decimal.rev (to_little_uint n Decimal.zero). Fixpoint to_little_hex_uint n acc := match n with | O => acc | S n => to_little_hex_uint n (Hexadecimal.Little.succ acc) end. Definition to_hex_uint n := Hexadecimal.rev (to_little_hex_uint n Hexadecimal.zero). Definition to_num_uint n := Number.UIntDecimal (to_uint n). Definition to_num_hex_uint n := Number.UIntHexadecimal (to_hex_uint n). Definition of_int (d:Decimal.int) : option nat := match Decimal.norm d with | Decimal.Pos u => Some (of_uint u) | _ => None end. Definition of_hex_int (d:Hexadecimal.int) : option nat := match Hexadecimal.norm d with | Hexadecimal.Pos u => Some (of_hex_uint u) | _ => None end. Definition of_num_int (d:Number.int) : option nat := match d with | Number.IntDecimal d => of_int d | Number.IntHexadecimal d => of_hex_int d end. Definition to_int n := Decimal.Pos (to_uint n). Definition to_hex_int n := Hexadecimal.Pos (to_hex_uint n). Definition to_num_int n := Number.IntDecimal (to_int n). (** ** Euclidean division *) (** This division is linear and tail-recursive. In [divmod], [y] is the predecessor of the actual divisor, and [u] is [y] minus the real remainder *) Fixpoint divmod x y q u := match x with | 0 => (q,u) | S x' => match u with | 0 => divmod x' y (S q) y | S u' => divmod x' y q u' end end. Definition div x y := match y with | 0 => y | S y' => fst (divmod x y' 0 y') end. Definition modulo x y := match y with | 0 => x | S y' => y' - snd (divmod x y' 0 y') end. Infix "/" := div : nat_scope. Infix "mod" := modulo (at level 40, no associativity) : nat_scope. (** ** Greatest common divisor *) (** We use Euclid algorithm, which is normally not structural, but Rocq is now clever enough to accept this (behind modulo there is a subtraction, which now preserves being a subterm) *) Fixpoint gcd a b := match a with | O => b | S a' => gcd (b mod (S a')) (S a') end. (** ** Square *) Definition square n := n * n. (** ** Square root *) (** The following square root function is linear (and tail-recursive). With Peano representation, we can't do better. For faster algorithm, see Psqrt/Zsqrt/Nsqrt... We search the square root of n = k + p^2 + (q - r) with q = 2p and 0<=r<=q. We start with p=q=r=0, hence looking for the square root of n = k. Then we progressively decrease k and r. When k = S k' and r=0, it means we can use (S p) as new sqrt candidate, since (S k')+p^2+2p = k'+(S p)^2. When k reaches 0, we have found the biggest p^2 square contained in n, hence the square root of n is p. *) Fixpoint sqrt_iter k p q r := match k with | O => p | S k' => match r with | O => sqrt_iter k' (S p) (S (S q)) (S (S q)) | S r' => sqrt_iter k' p q r' end end. Definition sqrt n := sqrt_iter n 0 0 0. (** ** Log2 *) (** This base-2 logarithm is linear and tail-recursive. In [log2_iter], we maintain the logarithm [p] of the counter [q], while [r] is the distance between [q] and the next power of 2, more precisely [q + S r = 2^(S p)] and [r<2^p]. At each recursive call, [q] goes up while [r] goes down. When [r] is 0, we know that [q] has almost reached a power of 2, and we increase [p] at the next call, while resetting [r] to [q]. Graphically (numbers are [q], stars are [r]) : << 10 9 8 7 * 6 * 5 ... 4 3 * 2 * 1 * * 0 * * * >> We stop when [k], the global downward counter reaches 0. At that moment, [q] is the number we're considering (since [k+q] is invariant), and [p] its logarithm. *) Fixpoint log2_iter k p q r := match k with | O => p | S k' => match r with | O => log2_iter k' (S p) (S q) q | S r' => log2_iter k' p (S q) r' end end. Definition log2 n := log2_iter (pred n) 0 1 0. (** Iterator on natural numbers *) Definition iter (n:nat) {A} (f:A->A) (x:A) : A := nat_rect (fun _ => A) x (fun _ => f) n. (** Bitwise operations *) (** We provide here some bitwise operations for unary numbers. Some might be really naive, they are just there for fulfilling the same interface as other for natural representations. As soon as binary representations such as NArith are available, it is clearly better to convert to/from them and use their ops. *) Fixpoint div2 n := match n with | 0 => 0 | S 0 => 0 | S (S n') => S (div2 n') end. Fixpoint testbit a n : bool := match n with | 0 => odd a | S n => testbit (div2 a) n end. Definition shiftl a := nat_rect _ a (fun _ => double). Definition shiftr a := nat_rect _ a (fun _ => div2). Fixpoint bitwise (op:bool->bool->bool) n a b := match n with | 0 => 0 | S n' => (if op (odd a) (odd b) then 1 else 0) + 2*(bitwise op n' (div2 a) (div2 b)) end. Definition land a b := bitwise andb a a b. Definition lor a b := bitwise orb (max a b) a b. Definition ldiff a b := bitwise (fun b b' => andb b (negb b')) a a b. Definition lxor a b := bitwise xorb (max a b) a b. rocq-9.2.0/theories/Corelib/Init/Notations.v000066400000000000000000000130341516144147600207510ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* y" (at level 99, right associativity, y at level 200). Reserved Notation "x <-> y" (at level 95, no associativity). Reserved Notation "x /\ y" (at level 80, right associativity). Reserved Notation "x \/ y" (at level 85, right associativity). Reserved Notation "~ x" (at level 75, right associativity). (** Notations for equality and inequalities *) Reserved Notation "x = y :> T" (at level 70, y at next level, no associativity). Reserved Notation "x = y" (at level 70, no associativity). Reserved Notation "x = y = z" (at level 70, no associativity, y at next level). Reserved Notation "x <> y :> T" (at level 70, y at next level, no associativity). Reserved Notation "x <> y" (at level 70, no associativity). Reserved Notation "x <= y" (at level 70, no associativity). Reserved Notation "x < y" (at level 70, no associativity). Reserved Notation "x >= y" (at level 70, no associativity). Reserved Notation "x > y" (at level 70, no associativity). Reserved Notation "x <= y <= z" (at level 70, y at next level). Reserved Notation "x <= y < z" (at level 70, y at next level). Reserved Notation "x < y < z" (at level 70, y at next level). Reserved Notation "x < y <= z" (at level 70, y at next level). (** Arithmetical notations (also used for type constructors) *) Reserved Notation "x + y" (at level 50, left associativity). Reserved Notation "x - y" (at level 50, left associativity). Reserved Notation "x * y" (at level 40, left associativity). Reserved Notation "x / y" (at level 40, left associativity). Reserved Notation "- x" (at level 35, right associativity). Reserved Notation "/ x" (at level 35, right associativity). Reserved Notation "x ^ y" (at level 30, right associativity). (** Notations for booleans *) Reserved Notation "x || y" (at level 50, left associativity). Reserved Notation "x && y" (at level 40, left associativity). (** Notations for pairs *) Reserved Notation "( x , y , .. , z )" (at level 0, format "( '[' x , '/' y , '/' .. , '/' z ']' )"). (** Notation "{ x }" is reserved and has a special status as component of other notations such as "{ A } + { B }" and "A + { B }" (which are at the same level as "x + y"); "{ x }" is at level 0 to factor with "{ x : A | P }" *) Reserved Notation "{ x }" (at level 0, x at level 99). (** Notations for sigma-types or subsets *) #[warning="-closed-notation-not-level-0"] Reserved Notation "{ A } + { B }" (at level 50, left associativity). #[warning="-postfix-notation-not-level-1"] Reserved Notation "A + { B }" (at level 50, left associativity). Reserved Notation "{ x | P }" (at level 0, x at level 99). Reserved Notation "{ x | P & Q }" (at level 0, x at level 99). Reserved Notation "{ x : A | P }" (at level 0, x at level 99). Reserved Notation "{ x : A | P & Q }" (at level 0, x at level 99). Reserved Notation "{ x & P }" (at level 0, x at level 99). Reserved Notation "{ x & P & Q }" (at level 0, x at level 99). Reserved Notation "{ x : A & P }" (at level 0, x at level 99). Reserved Notation "{ x : A & P & Q }" (at level 0, x at level 99). Reserved Notation "{ ' pat | P }" (at level 0, pat strict pattern, format "{ ' pat | P }"). Reserved Notation "{ ' pat | P & Q }" (at level 0, pat strict pattern, format "{ ' pat | P & Q }"). Reserved Notation "{ ' pat : A | P }" (at level 0, pat strict pattern, format "{ ' pat : A | P }"). Reserved Notation "{ ' pat : A | P & Q }" (at level 0, pat strict pattern, format "{ ' pat : A | P & Q }"). Reserved Notation "{ ' pat & P }" (at level 0, pat strict pattern, format "{ ' pat & P }"). Reserved Notation "{ ' pat & P & Q }" (at level 0, pat strict pattern, format "{ ' pat & P & Q }"). Reserved Notation "{ ' pat : A & P }" (at level 0, pat strict pattern, format "{ ' pat : A & P }"). Reserved Notation "{ ' pat : A & P & Q }" (at level 0, pat strict pattern, format "{ ' pat : A & P & Q }"). (** Support for Gonthier-Ssreflect's "if c is pat then u else v" *) Module IfNotations. Notation "'if' c 'is' p 'then' u 'else' v" := (match c with p => u | _ => v end) (at level 200, p pattern at level 100). End IfNotations. (** Notations for first and second projections *) Reserved Notation "p .1" (at level 1, left associativity, format "p .1"). Reserved Notation "p .2" (at level 1, left associativity, format "p .2"). (** Scopes *) Declare Scope core_scope. Delimit Scope core_scope with core. Declare Scope function_scope. Delimit Scope function_scope with function. Bind Scope function_scope with Funclass. Declare Scope type_scope. Delimit Scope type_scope with type. Bind Scope type_scope with Sortclass. Open Scope core_scope. Open Scope function_scope. Open Scope type_scope. Notation "A -> B" := (forall (_ : A), B) : type_scope. Create HintDb typeclass_instances discriminated. rocq-9.2.0/theories/Corelib/Init/Number.v000066400000000000000000000031301516144147600202170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* m -> S n <> S m. Proof. red; auto. Qed. #[global] Hint Resolve not_eq_S: core. Definition IsSucc (n:nat) : Prop := match n with | O => False | S p => True end. (** Zero is not the successor of a number *) Theorem O_S : forall n:nat, 0 <> S n. Proof. discriminate. Qed. #[global] Hint Resolve O_S: core. Theorem n_Sn : forall n:nat, n <> S n. Proof. intro n; induction n; auto. Qed. #[global] Hint Resolve n_Sn: core. (** Addition *) Abbreviation plus := Nat.add (only parsing). Infix "+" := Nat.add : nat_scope. Definition f_equal2_plus := f_equal2 plus. Definition f_equal2_nat := f_equal2 (A1:=nat) (A2:=nat). #[global] Hint Resolve f_equal2_nat: core. Lemma plus_n_O : forall n:nat, n = n + 0. Proof. intro n; induction n; simpl; auto. Qed. #[global] Remove Hints eq_refl : core. #[global] Hint Resolve plus_n_O eq_refl: core. (* We want eq_refl to have higher priority than plus_n_O *) Lemma plus_O_n : forall n:nat, 0 + n = n. Proof. reflexivity. Qed. Lemma plus_n_Sm : forall n m:nat, S (n + m) = n + S m. Proof. intros n m; induction n; simpl; auto. Qed. #[global] Hint Resolve plus_n_Sm: core. Lemma plus_Sn_m : forall n m:nat, S n + m = S (n + m). Proof. reflexivity. Qed. (** Standard associated names *) Abbreviation plus_0_r_reverse := plus_n_O (only parsing). Abbreviation plus_succ_r_reverse := plus_n_Sm (only parsing). (** Multiplication *) Abbreviation mult := Nat.mul (only parsing). Infix "*" := Nat.mul : nat_scope. Definition f_equal2_mult := f_equal2 mult. #[global] Hint Resolve f_equal2_mult: core. Lemma mult_n_O : forall n:nat, 0 = n * 0. Proof. intro n; induction n; simpl; auto. Qed. #[global] Hint Resolve mult_n_O: core. Lemma mult_n_Sm : forall n m:nat, n * m + n = n * S m. Proof. intros n m; induction n as [| p H]; simpl; auto. destruct H; rewrite <- plus_n_Sm; apply eq_S. pattern m at 1 3; elim m; simpl; auto. Qed. #[global] Hint Resolve mult_n_Sm: core. (** Standard associated names *) Abbreviation mult_0_r_reverse := mult_n_O (only parsing). Abbreviation mult_succ_r_reverse := mult_n_Sm (only parsing). (** Truncated subtraction: [m-n] is [0] if [n>=m] *) Abbreviation minus := Nat.sub (only parsing). Infix "-" := Nat.sub : nat_scope. (** Definition of the usual orders, the basic properties of [le] and [lt] can be found in files Le and Lt *) Inductive le (n:nat) : nat -> Prop := | le_n : n <= n | le_S : forall m:nat, n <= m -> n <= S m where "n <= m" := (le n m) : nat_scope. Register le_n as num.nat.le_n. #[global] Hint Constructors le: core. (*i equivalent to : "Hints Resolve le_n le_S : core." i*) Definition lt (n m:nat) := S n <= m. #[global] Hint Unfold lt: core. Infix "<" := lt : nat_scope. Definition ge (n m:nat) := m <= n. #[global] Hint Unfold ge: core. Infix ">=" := ge : nat_scope. Definition gt (n m:nat) := m < n. #[global] Hint Unfold gt: core. Infix ">" := gt : nat_scope. Notation "x <= y <= z" := (x <= y /\ y <= z) : nat_scope. Notation "x <= y < z" := (x <= y /\ y < z) : nat_scope. Notation "x < y < z" := (x < y /\ y < z) : nat_scope. Notation "x < y <= z" := (x < y /\ y <= z) : nat_scope. Register le as num.nat.le. Register lt as num.nat.lt. Register ge as num.nat.ge. Register gt as num.nat.gt. Theorem le_pred : forall n m, n <= m -> pred n <= pred m. Proof. induction 1 as [|m _]; auto. destruct m; simpl; auto. Qed. Theorem le_S_n : forall n m, S n <= S m -> n <= m. Proof. intros n m. exact (le_pred (S n) (S m)). Qed. Theorem le_0_n : forall n, 0 <= n. Proof. intro n; induction n; constructor; trivial. Qed. Theorem le_n_S : forall n m, n <= m -> S n <= S m. Proof. induction 1; constructor; trivial. Qed. (** Case analysis *) Theorem nat_case : forall (n:nat) (P:nat -> Prop), P 0 -> (forall m:nat, P (S m)) -> P n. Proof. intros n P IH0 IHS; case n; auto. Qed. (** Principle of double induction *) Theorem nat_double_ind : forall R:nat -> nat -> Prop, (forall n:nat, R 0 n) -> (forall n:nat, R (S n) 0) -> (forall n m:nat, R n m -> R (S n) (S m)) -> forall n m:nat, R n m. Proof. intros R ? ? ? n. induction n; auto. intro m; destruct m; auto. Qed. (** Maximum and minimum : definitions and specifications *) Abbreviation max := Nat.max (only parsing). Abbreviation min := Nat.min (only parsing). Lemma max_l n m : m <= n -> Nat.max n m = n. Proof. revert m; induction n as [|n IHn]; intro m; destruct m; simpl; trivial. - inversion 1. - intros. apply f_equal, IHn, le_S_n; trivial. Qed. Lemma max_r n m : n <= m -> Nat.max n m = m. Proof. revert m; induction n as [|n IHn]; intro m; destruct m; simpl; trivial. - inversion 1. - intros. apply f_equal, IHn, le_S_n; trivial. Qed. Lemma min_l n m : n <= m -> Nat.min n m = n. Proof. revert m; induction n as [|n IHn]; intro m; destruct m; simpl; trivial. - inversion 1. - intros. apply f_equal, IHn, le_S_n; trivial. Qed. Lemma min_r n m : m <= n -> Nat.min n m = m. Proof. revert m; induction n as [|n IHn]; intro m; destruct m; simpl; trivial. - inversion 1. - intros. apply f_equal, IHn, le_S_n; trivial. Qed. Lemma nat_rect_succ_r {A} (f: A -> A) (x:A) n : nat_rect (fun _ => A) x (fun _ => f) (S n) = nat_rect (fun _ => A) (f x) (fun _ => f) n. Proof. induction n as [|n IHn]; intros; simpl; rewrite <- ?IHn; trivial. Qed. Theorem nat_rect_plus : forall (n m:nat) {A} (f:A -> A) (x:A), nat_rect (fun _ => A) x (fun _ => f) (n + m) = nat_rect (fun _ => A) (nat_rect (fun _ => A) x (fun _ => f) m) (fun _ => f) n. Proof. intro n; induction n as [|n IHn]; intros; simpl; rewrite ?IHn; trivial. Qed. rocq-9.2.0/theories/Corelib/Init/Prelude.v000066400000000000000000000061451516144147600204000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prop) : Type := exist : forall x:A, P x -> sig P. Register sig as core.sig.type. Register exist as core.sig.intro. Register sig_rect as core.sig.rect. #[universes(template)] Inductive sig2 (A:Type) (P Q:A -> Prop) : Type := exist2 : forall x:A, P x -> Q x -> sig2 P Q. (** [(sigT A P)], or more suggestively [{x:A & (P x)}] is a Sigma-type. Similarly for [(sigT2 A P Q)], also written [{x:A & (P x) & (Q x)}]. *) #[universes(template)] Inductive sigT (A:Type) (P:A -> Type) : Type := existT : forall x:A, P x -> sigT P. Register sigT as core.sigT.type. Register existT as core.sigT.intro. Register sigT_rect as core.sigT.rect. #[universes(template)] Inductive sigT2 (A:Type) (P Q:A -> Type) : Type := existT2 : forall x:A, P x -> Q x -> sigT2 P Q. (* Notations *) Arguments sig (A P)%_type. Arguments sig2 (A P Q)%_type. Arguments sigT (A P)%_type. Arguments sigT2 (A P Q)%_type. Notation "{ x | P }" := (sig (fun x => P%_type)) : type_scope. Notation "{ x | P & Q }" := (sig2 (fun x => P%_type) (fun x => Q%_type)) : type_scope. Notation "{ x : A | P }" := (sig (A:=A) (fun x => P%_type)) : type_scope. Notation "{ x : A | P & Q }" := (sig2 (A:=A) (fun x => P%_type) (fun x => Q%_type)) : type_scope. Notation "{ x & P }" := (sigT (fun x => P%_type)) : type_scope. Notation "{ x & P & Q }" := (sigT2 (fun x => P%_type) (fun x => Q%_type)) : type_scope. Notation "{ x : A & P }" := (sigT (A:=A) (fun x => P%_type)) : type_scope. Notation "{ x : A & P & Q }" := (sigT2 (A:=A) (fun x => P%_type) (fun x => Q)) : type_scope. Notation "{ ' pat | P }" := (sig (fun pat => P%_type)) : type_scope. Notation "{ ' pat | P & Q }" := (sig2 (fun pat => P%_type) (fun pat => Q%_type)) : type_scope. Notation "{ ' pat : A | P }" := (sig (A:=A) (fun pat => P%_type)) : type_scope. Notation "{ ' pat : A | P & Q }" := (sig2 (A:=A) (fun pat => P%_type) (fun pat => Q%_type)) : type_scope. Notation "{ ' pat & P }" := (sigT (fun pat => P%_type)) : type_scope. Notation "{ ' pat & P & Q }" := (sigT2 (fun pat => P%_type) (fun pat => Q%_type)) : type_scope. Notation "{ ' pat : A & P }" := (sigT (A:=A) (fun pat => P%_type)) : type_scope. Notation "{ ' pat : A & P & Q }" := (sigT2 (A:=A) (fun pat => P%_type) (fun pat => Q%_type)) : type_scope. Add Printing Let sig. Add Printing Let sig2. Add Printing Let sigT. Add Printing Let sigT2. (** Projections of [sig] An element [y] of a subset [{x:A | (P x)}] is the pair of an [a] of type [A] and of a proof [h] that [a] satisfies [P]. Then [(proj1_sig y)] is the witness [a] and [(proj2_sig y)] is the proof of [(P a)] *) (* Set Universe Polymorphism. *) Section Subset_projections. Variable A : Type. Variable P : A -> Prop. Definition proj1_sig (e:sig P) := match e with | exist _ a b => a end. Definition proj2_sig (e:sig P) := match e return P (proj1_sig e) with | exist _ a b => b end. Register proj1_sig as core.sig.proj1. Register proj2_sig as core.sig.proj2. End Subset_projections. (** [sig2] of a predicate can be projected to a [sig]. This allows [proj1_sig] and [proj2_sig] to be usable with [sig2]. The [let] statements occur in the body of the [exist] so that [proj1_sig] of a coerced [X : sig2 P Q] will unify with [let (a, _, _) := X in a] *) Definition sig_of_sig2 (A : Type) (P Q : A -> Prop) (X : sig2 P Q) : sig P := exist P (let (a, _, _) := X in a) (let (x, p, _) as s return (P (let (a, _, _) := s in a)) := X in p). (** Projections of [sig2] An element [y] of a subset [{x:A | (P x) & (Q x)}] is the triple of an [a] of type [A], a of a proof [h] that [a] satisfies [P], and a proof [h'] that [a] satisfies [Q]. Then [(proj1_sig (sig_of_sig2 y))] is the witness [a], [(proj2_sig (sig_of_sig2 y))] is the proof of [(P a)], and [(proj3_sig y)] is the proof of [(Q a)]. *) Section Subset_projections2. Variable A : Type. Variables P Q : A -> Prop. Definition proj3_sig (e : sig2 P Q) := let (a, b, c) return Q (proj1_sig (sig_of_sig2 e)) := e in c. End Subset_projections2. (** Projections of [sigT] An element [x] of a sigma-type [{y:A & P y}] is a dependent pair made of an [a] of type [A] and an [h] of type [P a]. Then, [(projT1 x)] is the first projection and [(projT2 x)] is the second projection, the type of which depends on the [projT1]. *) Section Projections. Variable A : Type. Variable P : A -> Type. Definition projT1 (x:sigT P) : A := match x with | existT _ a _ => a end. Definition projT2 (x:sigT P) : P (projT1 x) := match x return P (projT1 x) with | existT _ _ h => h end. Register projT1 as core.sigT.proj1. Register projT2 as core.sigT.proj2. End Projections. Module SigTNotations. Notation "( x ; y )" := (existT _ x y) (at level 0, format "( x ; '/ ' y )"). Notation "x .1" := (projT1 x) (at level 1, left associativity, format "x .1"). Notation "x .2" := (projT2 x) (at level 1, left associativity, format "x .2"). End SigTNotations. Import SigTNotations. (** [sigT2] of a predicate can be projected to a [sigT]. This allows [projT1] and [projT2] to be usable with [sigT2]. The [let] statements occur in the body of the [existT] so that [projT1] of a coerced [X : sigT2 P Q] will unify with [let (a, _, _) := X in a] *) Definition sigT_of_sigT2 (A : Type) (P Q : A -> Type) (X : sigT2 P Q) : sigT P := existT P (let (a, _, _) := X in a) (let (x, p, _) as s return (P (let (a, _, _) := s in a)) := X in p). (** Projections of [sigT2] An element [x] of a sigma-type [{y:A & P y & Q y}] is a dependent pair made of an [a] of type [A], an [h] of type [P a], and an [h'] of type [Q a]. Then, [(projT1 (sigT_of_sigT2 x))] is the first projection, [(projT2 (sigT_of_sigT2 x))] is the second projection, and [(projT3 x)] is the third projection, the types of which depends on the [projT1]. *) Section Projections2. Variable A : Type. Variables P Q : A -> Type. Definition projT3 (e : sigT2 P Q) := let (a, b, c) return Q (projT1 (sigT_of_sigT2 e)) := e in c. End Projections2. Local Notation "x .3" := (projT3 x) (at level 1, left associativity, format "x .3"). (** [sigT] of a predicate is equivalent to [sig] *) Definition sig_of_sigT (A : Type) (P : A -> Prop) (X : sigT P) : sig P := exist P (projT1 X) (projT2 X). Definition sigT_of_sig (A : Type) (P : A -> Prop) (X : sig P) : sigT P := existT P (proj1_sig X) (proj2_sig X). (** [sigT2] of a predicate is equivalent to [sig2] *) Definition sig2_of_sigT2 (A : Type) (P Q : A -> Prop) (X : sigT2 P Q) : sig2 P Q := exist2 P Q (projT1 (sigT_of_sigT2 X)) (projT2 (sigT_of_sigT2 X)) (projT3 X). Definition sigT2_of_sig2 (A : Type) (P Q : A -> Prop) (X : sig2 P Q) : sigT2 P Q := existT2 P Q (proj1_sig (sig_of_sig2 X)) (proj2_sig (sig_of_sig2 X)) (proj3_sig X). (** [sig] of a predicate on [Prop]s can be turned into [ex] *) Definition ex_of_sig (A : Type) (P : A -> Prop) (X : sig P) : ex P := ex_intro P (proj1_sig X) (proj2_sig X). (** [sigT] of a predicate on [Prop]s can be turned into [ex] *) Definition ex_of_sigT (A : Type) (P : A -> Prop) (X : sigT P) : ex P := ex_of_sig (sig_of_sigT X). (** [sig2] of a predicate on [Prop]s can be turned into [ex2] *) Definition ex2_of_sig2 (A : Type) (P Q : A -> Prop) (X : sig2 P Q) : ex2 P Q := ex_intro2 P Q (proj1_sig (sig_of_sig2 X)) (proj2_sig (sig_of_sig2 X)) (proj3_sig X). (** [sigT2] of a predicate on [Prop]s can be turned into [ex2] *) Definition ex2_of_sigT2 (A : Type) (P Q : A -> Prop) (X : sigT2 P Q) : ex2 P Q := ex2_of_sig2 (sig2_of_sigT2 X). (** Ξ· Principles *) Definition sigT_eta {A P} (p : { a : A & P a }) : p = existT _ (projT1 p) (projT2 p). Proof. destruct p; reflexivity. Defined. Definition sig_eta {A P} (p : { a : A | P a }) : p = exist _ (proj1_sig p) (proj2_sig p). Proof. destruct p; reflexivity. Defined. Definition sigT2_eta {A P Q} (p : { a : A & P a & Q a }) : p = existT2 _ _ (projT1 (sigT_of_sigT2 p)) (projT2 (sigT_of_sigT2 p)) (projT3 p). Proof. destruct p; reflexivity. Defined. Definition sig2_eta {A P Q} (p : { a : A | P a & Q a }) : p = exist2 _ _ (proj1_sig (sig_of_sig2 p)) (proj2_sig (sig_of_sig2 p)) (proj3_sig p). Proof. destruct p; reflexivity. Defined. (** [exists x : A, B] is equivalent to [inhabited {x : A | B}] *) Lemma exists_to_inhabited_sig {A P} : (exists x : A, P x) -> inhabited {x : A | P x}. Proof. intros [x y]. exact (inhabits (exist _ x y)). Qed. Lemma inhabited_sig_to_exists {A P} : inhabited {x : A | P x} -> exists x : A, P x. Proof. intros [[x y]];exists x;exact y. Qed. (** Subtyping for prod *) Section ProdSigT. Variable A B : Type. Definition sigT_of_prod (p : A * B) := (fst p; snd p). Definition prod_of_sigT (s : { _ : A & B }) := (s.1, s.2). Lemma sigT_prod_sigT p : sigT_of_prod (prod_of_sigT p) = p. Proof. destruct p; reflexivity. Qed. Lemma prod_sigT_prod s : prod_of_sigT (sigT_of_prod s) = s. Proof. destruct s; reflexivity. Qed. End ProdSigT. (** Equality of sigma types *) Import EqNotations. (** Equality for [sigT] *) Section sigT. Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition projT1_eq {A} {P : A -> Type} {u v : { a : A & P a }} (p : u = v) : u.1 = v.1 := f_equal (fun x => x.1) p. (** Projecting an equality of a pair to equality of the second components *) Definition projT2_eq {A} {P : A -> Type} {u v : { a : A & P a }} (p : u = v) : rew projT1_eq p in u.2 = v.2 := rew dependent p in eq_refl. (** Equality of [sigT] is itself a [sigT] (forwards-reasoning version) *) Definition eq_existT_uncurried {A : Type} {P : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (pq : { p : u1 = v1 & rew p in u2 = v2 }) : (u1; u2) = (v1; v2). Proof. destruct pq as [p q]. destruct q; simpl in *. destruct p; reflexivity. Defined. (** Equality of [sigT] is itself a [sigT] (backwards-reasoning version) *) Definition eq_sigT_uncurried {A : Type} {P : A -> Type} (u v : { a : A & P a }) (pq : { p : u.1 = v.1 & rew p in u.2 = v.2 }) : u = v. Proof. destruct u as [u1 u2], v as [v1 v2]; simpl in *. apply eq_existT_uncurried; exact pq. Defined. Lemma eq_existT_curried {A : Type} {P : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) (q : rew p in u2 = v2) : (u1; u2) = (v1; v2). Proof. apply eq_sigT_uncurried; exists p; exact q. Defined. Local Notation "(= u ; v )" := (eq_existT_curried u v) (at level 0, format "(= u ; '/ ' v )"). Lemma eq_existT_curried_map {A A' P P'} (f:A -> A') (g:forall u:A, P u -> P' (f u)) {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) (q : rew p in u2 = v2) : f_equal (fun x => (f x.1; g x.1 x.2)) (= p; q) = (= f_equal f p; f_equal_dep2 f g p q). Proof. destruct p, q. reflexivity. Defined. Lemma eq_existT_curried_trans {A P} {u1 v1 w1 : A} {u2 : P u1} {v2 : P v1} {w2 : P w1} (p : u1 = v1) (q : rew p in u2 = v2) (p' : v1 = w1) (q': rew p' in v2 = w2) : eq_trans (= p; q) (= p'; q') = (= eq_trans p p'; eq_trans_map p p' q q'). Proof. destruct p', q'. reflexivity. Defined. Theorem eq_existT_curried_congr {A P} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {p p' : u1 = v1} {q : rew p in u2 = v2} {q': rew p' in u2 = v2} (r : p = p') : rew [fun H => rew H in u2 = v2] r in q = q' -> (= p; q) = (= p'; q'). Proof. destruct r, 1. reflexivity. Qed. (** Curried version of proving equality of sigma types *) Definition eq_sigT {A : Type} {P : A -> Type} (u v : { a : A & P a }) (p : u.1 = v.1) (q : rew p in u.2 = v.2) : u = v := eq_sigT_uncurried u v (existT _ p q). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_existT_l {A : Type} {P : A -> Type} {u1 : A} {u2 : P u1} {v : { a : A & P a }} (p : u1 = v.1) (q : rew p in u2 = v.2) : (u1; u2) = v := eq_sigT (u1; u2) v p q. Definition eq_existT_r {A : Type} {P : A -> Type} {u : { a : A & P a }} {v1 : A} {v2 : P v1} (p : u.1 = v1) (q : rew p in u.2 = v2) : u = (v1; v2) := eq_sigT u (v1; v2) p q. (** Equality of [sigT] when the property is an hProp *) Definition eq_sigT_hprop {A P} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : { a : A & P a }) (p : u.1 = v.1) : u = v := eq_sigT u v p (P_hprop _ _ _). (** Equivalence of equality of [sigT] with a [sigT] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_sigT_uncurried_iff {A P} (u v : { a : A & P a }) : u = v <-> { p : u.1 = v.1 & rew p in u.2 = v.2 }. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sigT_uncurried ]. Defined. (** Induction principle for [@eq (sigT _)] *) Definition eq_sigT_rect {A P} {u v : { a : A & P a }} (Q : u = v -> Type) (f : forall p q, Q (eq_sigT u v p q)) : forall p, Q p. Proof. intro p; specialize (f (projT1_eq p) (projT2_eq p)); destruct u, p; exact f. Defined. Definition eq_sigT_rec {A P u v} (Q : u = v :> { a : A & P a } -> Set) := eq_sigT_rect Q. Definition eq_sigT_ind {A P u v} (Q : u = v :> { a : A & P a } -> Prop) := eq_sigT_rec Q. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_sigT_rect_existT_l {A P} {u1 u2 v} (Q : _ -> Type) (f : forall p q, Q (@eq_existT_l A P u1 u2 v p q)) : forall p, Q p := eq_sigT_rect Q f. Definition eq_sigT_rect_existT_r {A P} {u v1 v2} (Q : _ -> Type) (f : forall p q, Q (@eq_existT_r A P u v1 v2 p q)) : forall p, Q p := eq_sigT_rect Q f. Definition eq_sigT_rect_existT {A P} {u1 u2 v1 v2} (Q : _ -> Type) (f : forall p q, Q (@eq_existT_curried A P u1 v1 u2 v2 p q)) : forall p, Q p := eq_sigT_rect Q f. (** We want uncurried versions so [inversion_sigma] can accept intropatterns, but we use [ex] types for the induction hypothesis to avoid extraction errors about informative inductive types having Prop instances *) Definition eq_sigT_rect_uncurried {A P} {u v : { a : A & P a }} (Q : u = v -> Type) (f : forall pq : exists p : u.1 = v.1, _, Q (eq_sigT u v (ex_proj1 pq) (ex_proj2 pq))) : forall p, Q p := eq_sigT_rect Q (fun p q => f (ex_intro _ p q)). Definition eq_sigT_rec_uncurried {A P u v} (Q : u = v :> { a : A & P a } -> Set) := eq_sigT_rect_uncurried Q. Definition eq_sigT_ind_uncurried {A P u v} (Q : u = v :> { a : A & P a } -> Prop) := eq_sigT_rec_uncurried Q. (** Equivalence of equality of [sigT] involving hProps with equality of the first components *) Definition eq_sigT_hprop_iff {A P} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : { a : A & P a }) : u = v <-> (u.1 = v.1) := conj (fun p => f_equal (@projT1 _ _) p) (eq_sigT_hprop P_hprop u v). (** Non-dependent classification of equality of [sigT] *) Definition eq_sigT_nondep {A B : Type} (u v : { a : A & B }) (p : u.1 = v.1) (q : u.2 = v.2) : u = v := @eq_sigT _ _ u v p (eq_trans (rew_const _ _) q). (** Classification of transporting across an equality of [sigT]s *) Lemma rew_sigT {A x} {P : A -> Type} (Q : forall a, P a -> Prop) (u : { p : P x & Q x p }) {y} (H : x = y) : rew [fun a => { p : P a & Q a p }] H in u = existT (Q y) (rew H in u.1) (rew dependent H in (u.2)). Proof. destruct H, u; reflexivity. Defined. End sigT. Global Arguments eq_existT_curried A P _ _ _ _ !p !q / . (** Equality for [sig] *) Section sig. (** We define this as a [Let] rather than a [Definition] to avoid extraction errors about informative inductive types having Prop instances *) Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition proj1_sig_eq {A} {P : A -> Prop} {u v : { a : A | P a }} (p : u = v) : proj1_sig u = proj1_sig v := f_equal (@proj1_sig _ _) p. (** Projecting an equality of a pair to equality of the second components *) Definition proj2_sig_eq {A} {P : A -> Prop} {u v : { a : A | P a }} (p : u = v) : rew proj1_sig_eq p in proj2_sig u = proj2_sig v := rew dependent p in eq_refl. (** Equality of [sig] is itself a [sig] (forwards-reasoning version) *) Definition eq_exist_uncurried {A : Type} {P : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (pq : { p : u1 = v1 | rew p in u2 = v2 }) : exist _ u1 u2 = exist _ v1 v2. Proof. destruct pq as [p q]. destruct q; simpl in *. destruct p; reflexivity. Defined. (** Equality of [sig] is itself a [sig] (backwards-reasoning version) *) Definition eq_sig_uncurried {A : Type} {P : A -> Prop} (u v : { a : A | P a }) (pq : { p : proj1_sig u = proj1_sig v | rew p in proj2_sig u = proj2_sig v }) : u = v. Proof. destruct u as [u1 u2], v as [v1 v2]; simpl in *. apply eq_exist_uncurried; exact pq. Defined. Lemma eq_exist_curried {A : Type} {P : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} (p : u1 = v1) (q : rew p in u2 = v2) : exist P u1 u2 = exist P v1 v2. Proof. apply eq_sig_uncurried; exists p; exact q. Defined. (** Curried version of proving equality of sigma types *) Definition eq_sig {A : Type} {P : A -> Prop} (u v : { a : A | P a }) (p : proj1_sig u = proj1_sig v) (q : rew p in proj2_sig u = proj2_sig v) : u = v := eq_sig_uncurried u v (exist _ p q). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_exist_l {A : Type} {P : A -> Prop} {u1 : A} {u2 : P u1} {v : { a : A | P a }} (p : u1 = proj1_sig v) (q : rew p in u2 = proj2_sig v) : exist _ u1 u2 = v := eq_sig (exist _ u1 u2) v p q. Definition eq_exist_r {A : Type} {P : A -> Prop} {u : { a : A | P a }} {v1 : A} {v2 : P v1} (p : proj1_sig u = v1) (q : rew p in proj2_sig u = v2) : u = exist _ v1 v2 := eq_sig u (exist _ v1 v2) p q. (** Induction principle for [@eq (sig _)] *) Definition eq_sig_rect {A P} {u v : { a : A | P a }} (Q : u = v -> Type) (f : forall p q, Q (eq_sig u v p q)) : forall p, Q p. Proof. intro p; specialize (f (proj1_sig_eq p) (proj2_sig_eq p)); destruct u, p; exact f. Defined. Definition eq_sig_rec {A P u v} (Q : u = v :> { a : A | P a } -> Set) := eq_sig_rect Q. Definition eq_sig_ind {A P u v} (Q : u = v :> { a : A | P a } -> Prop) := eq_sig_rec Q. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_sig_rect_exist_l {A P} {u1 u2 v} (Q : _ -> Type) (f : forall p q, Q (@eq_exist_l A P u1 u2 v p q)) : forall p, Q p := eq_sig_rect Q f. Definition eq_sig_rect_exist_r {A P} {u v1 v2} (Q : _ -> Type) (f : forall p q, Q (@eq_exist_r A P u v1 v2 p q)) : forall p, Q p := eq_sig_rect Q f. Definition eq_sig_rect_exist {A P} {u1 u2 v1 v2} (Q : _ -> Type) (f : forall p q, Q (@eq_exist_curried A P u1 v1 u2 v2 p q)) : forall p, Q p := eq_sig_rect Q f. (** We want uncurried versions so [inversion_sigma] can accept intropatterns, but we use [ex] types for the induction hypothesis to avoid extraction errors about informative inductive types having Prop instances *) Definition eq_sig_rect_uncurried {A P} {u v : { a : A | P a }} (Q : u = v -> Type) (f : forall pq : exists p : proj1_sig u = proj1_sig v, _, Q (eq_sig u v (ex_proj1 pq) (ex_proj2 pq))) : forall p, Q p := eq_sig_rect Q (fun p q => f (ex_intro _ p q)). Definition eq_sig_rec_uncurried {A P u v} (Q : u = v :> { a : A | P a } -> Set) := eq_sig_rect_uncurried Q. Definition eq_sig_ind_uncurried {A P u v} (Q : u = v :> { a : A | P a } -> Prop) := eq_sig_rec_uncurried Q. (** Equality of [sig] when the property is an hProp *) Definition eq_sig_hprop {A} {P : A -> Prop} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : { a : A | P a }) (p : proj1_sig u = proj1_sig v) : u = v := eq_sig u v p (P_hprop _ _ _). (** Equivalence of equality of [sig] with a [sig] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_sig_uncurried_iff {A} {P : A -> Prop} (u v : { a : A | P a }) : u = v <-> { p : proj1_sig u = proj1_sig v | rew p in proj2_sig u = proj2_sig v }. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sig_uncurried ]. Defined. (** Equivalence of equality of [sig] involving hProps with equality of the first components *) Definition eq_sig_hprop_iff {A} {P : A -> Prop} (P_hprop : forall (x : A) (p q : P x), p = q) (u v : { a : A | P a }) : u = v <-> (proj1_sig u = proj1_sig v) := conj (fun p => f_equal (@proj1_sig _ _) p) (eq_sig_hprop P_hprop u v). Lemma rew_sig {A x} {P : A -> Type} (Q : forall a, P a -> Prop) (u : { p : P x | Q x p }) {y} (H : x = y) : rew [fun a => { p : P a | Q a p }] H in u = exist (Q y) (rew H in proj1_sig u) (rew dependent H in proj2_sig u). Proof. destruct H, u; reflexivity. Defined. End sig. Global Arguments eq_exist_curried A P _ _ _ _ !p !q / . (** Equality for [sigT2] *) Section sigT2. (* We make [sigT_of_sigT2] a coercion so we can use [projT1], [projT2] on [sigT2] *) Local Coercion sigT_of_sigT2 : sigT2 >-> sigT. Local Coercion ex_of_ex2 : ex2 >-> ex. Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition sigT_of_sigT2_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v) : u = v :> { a : A & P a } := f_equal _ p. Definition projT1_of_sigT2_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v) : u.1 = v.1 := projT1_eq (sigT_of_sigT2_eq p). (** Projecting an equality of a pair to equality of the second components *) Definition projT2_of_sigT2_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v) : rew projT1_of_sigT2_eq p in u.2 = v.2 := rew dependent p in eq_refl. (** Projecting an equality of a pair to equality of the third components *) Definition projT3_eq {A} {P Q : A -> Type} {u v : { a : A & P a & Q a }} (p : u = v) : rew projT1_of_sigT2_eq p in u.3 = v.3 := rew dependent p in eq_refl. (** Equality of [sigT2] is itself a [sigT2] (forwards-reasoning version) *) Definition eq_existT2_uncurried {A : Type} {P Q : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (pqr : { p : u1 = v1 & rew p in u2 = v2 & rew p in u3 = v3 }) : existT2 _ _ u1 u2 u3 = existT2 _ _ v1 v2 v3. Proof. destruct pqr as [p q r]. destruct r, q, p; simpl. reflexivity. Defined. (** Equality of [sigT2] is itself a [sigT2] (backwards-reasoning version) *) Definition eq_sigT2_uncurried {A : Type} {P Q : A -> Type} (u v : { a : A & P a & Q a }) (pqr : { p : u.1 = v.1 & rew p in u.2 = v.2 & rew p in u.3 = v.3 }) : u = v. Proof. destruct u as [u1 u2 u3], v as [v1 v2 v3]; simpl in *. apply eq_existT2_uncurried; exact pqr. Defined. Lemma eq_existT2_curried {A : Type} {P Q : A -> Type} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (p : u1 = v1) (q : rew p in u2 = v2) (r : rew p in u3 = v3) : existT2 P Q u1 u2 u3 = existT2 P Q v1 v2 v3. Proof. apply eq_sigT2_uncurried; exists p; exact q + exact r. Defined. (** Curried version of proving equality of sigma types *) Definition eq_sigT2 {A : Type} {P Q : A -> Type} (u v : { a : A & P a & Q a }) (p : u.1 = v.1) (q : rew p in u.2 = v.2) (r : rew p in u.3 = v.3) : u = v := eq_sigT2_uncurried u v (existT2 _ _ p q r). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_existT2_l {A : Type} {P Q : A -> Type} {u1 : A} {u2 : P u1} {u3 : Q u1} {v : { a : A & P a & Q a }} (p : u1 = v.1) (q : rew p in u2 = v.2) (r : rew p in u3 = v.3) : existT2 P Q u1 u2 u3 = v := eq_sigT2 (existT2 P Q u1 u2 u3) v p q r. Definition eq_existT2_r {A : Type} {P Q : A -> Type} {u : { a : A & P a & Q a }} {v1 : A} {v2 : P v1} {v3 : Q v1} (p : u.1 = v1) (q : rew p in u.2 = v2) (r : rew p in u.3 = v3) : u = existT2 P Q v1 v2 v3 := eq_sigT2 u (existT2 P Q v1 v2 v3) p q r. (** Equality of [sigT2] when the second property is an hProp *) Definition eq_sigT2_hprop {A P Q} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : { a : A & P a & Q a }) (p : u = v :> { a : A & P a }) : u = v := eq_sigT2 u v (projT1_eq p) (projT2_eq p) (Q_hprop _ _ _). (** Equivalence of equality of [sigT2] with a [sigT2] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_sigT2_uncurried_iff {A P Q} (u v : { a : A & P a & Q a }) : u = v <-> { p : u.1 = v.1 & rew p in u.2 = v.2 & rew p in u.3 = v.3 }. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sigT2_uncurried ]. Defined. (** Induction principle for [@eq (sigT2 _ _)] *) Definition eq_sigT2_rect {A P Q} {u v : { a : A & P a & Q a }} (R : u = v -> Type) (f : forall p q r, R (eq_sigT2 u v p q r)) : forall p, R p. Proof. intro p. specialize (f (projT1_of_sigT2_eq p) (projT2_of_sigT2_eq p) (projT3_eq p)). destruct u, p; exact f. Defined. Definition eq_sigT2_rec {A P Q u v} (R : u = v :> { a : A & P a & Q a } -> Set) := eq_sigT2_rect R. Definition eq_sigT2_ind {A P Q u v} (R : u = v :> { a : A & P a & Q a } -> Prop) := eq_sigT2_rec R. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_sigT2_rect_existT2_l {A P Q} {u1 u2 u3 v} (R : _ -> Type) (f : forall p q r, R (@eq_existT2_l A P Q u1 u2 u3 v p q r)) : forall p, R p := eq_sigT2_rect R f. Definition eq_sigT2_rect_existT2_r {A P Q} {u v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (@eq_existT2_r A P Q u v1 v2 v3 p q r)) : forall p, R p := eq_sigT2_rect R f. Definition eq_sigT2_rect_existT2 {A P Q} {u1 u2 u3 v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (@eq_existT2_curried A P Q u1 v1 u2 v2 u3 v3 p q r)) : forall p, R p := eq_sigT2_rect R f. (** We want uncurried versions so [inversion_sigma] can accept intropatterns, but we use [ex2] types for the induction hypothesis to avoid extraction errors about informative inductive types having Prop instances *) Definition eq_sigT2_rect_uncurried {A P Q} {u v : { a : A & P a & Q a }} (R : u = v -> Type) (f : forall pqr : exists2 p : u.1 = v.1, _ & _, R (eq_sigT2 u v (ex_proj1 pqr) (ex_proj2 pqr) (ex_proj3 pqr))) : forall p, R p := eq_sigT2_rect R (fun p q r => f (ex_intro2 _ _ p q r)). Definition eq_sigT2_rec_uncurried {A P Q u v} (R : u = v :> { a : A & P a & Q a } -> Set) := eq_sigT2_rect_uncurried R. Definition eq_sigT2_ind_uncurried {A P Q u v} (R : u = v :> { a : A & P a & Q a } -> Prop) := eq_sigT2_rec_uncurried R. (** Equivalence of equality of [sigT2] involving hProps with equality of the first components *) Definition eq_sigT2_hprop_iff {A P Q} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : { a : A & P a & Q a }) : u = v <-> (u = v :> { a : A & P a }) := conj (fun p => f_equal (@sigT_of_sigT2 _ _ _) p) (eq_sigT2_hprop Q_hprop u v). (** Non-dependent classification of equality of [sigT] *) Definition eq_sigT2_nondep {A B C : Type} (u v : { a : A & B & C }) (p : u.1 = v.1) (q : u.2 = v.2) (r : u.3 = v.3) : u = v := @eq_sigT2 _ _ _ u v p (eq_trans (rew_const _ _) q) (eq_trans (rew_const _ _) r). (** Classification of transporting across an equality of [sigT2]s *) Lemma rew_sigT2 {A x} {P : A -> Type} (Q R : forall a, P a -> Prop) (u : { p : P x & Q x p & R x p }) {y} (H : x = y) : rew [fun a => { p : P a & Q a p & R a p }] H in u = existT2 (Q y) (R y) (rew H in u.1) (rew dependent H in u.2) (rew dependent H in u.3). Proof. destruct H, u; reflexivity. Defined. End sigT2. Global Arguments eq_existT2_curried A P Q _ _ _ _ _ _ !p !q !r / . (** Equality for [sig2] *) Section sig2. (* We make [sig_of_sig2] a coercion so we can use [proj1], [proj2] on [sig2] *) Local Coercion sig_of_sig2 : sig2 >-> sig. Local Coercion ex_of_ex2 : ex2 >-> ex. Local Unset Implicit Arguments. (** Projecting an equality of a pair to equality of the first components *) Definition sig_of_sig2_eq {A} {P Q : A -> Prop} {u v : { a : A | P a & Q a }} (p : u = v) : u = v :> { a : A | P a } := f_equal _ p. Definition proj1_sig_of_sig2_eq {A} {P Q : A -> Prop} {u v : { a : A | P a & Q a }} (p : u = v) : proj1_sig u = proj1_sig v := proj1_sig_eq (sig_of_sig2_eq p). (** Projecting an equality of a pair to equality of the second components *) Definition proj2_sig_of_sig2_eq {A} {P Q : A -> Prop} {u v : { a : A | P a & Q a }} (p : u = v) : rew proj1_sig_of_sig2_eq p in proj2_sig u = proj2_sig v := rew dependent p in eq_refl. (** Projecting an equality of a pair to equality of the third components *) Definition proj3_sig_eq {A} {P Q : A -> Prop} {u v : { a : A | P a & Q a }} (p : u = v) : rew proj1_sig_of_sig2_eq p in proj3_sig u = proj3_sig v := rew dependent p in eq_refl. (** Equality of [sig2] is itself a [sig2] (fowards-reasoning version) *) Definition eq_exist2_uncurried {A} {P Q : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (pqr : { p : u1 = v1 | rew p in u2 = v2 & rew p in u3 = v3 }) : exist2 _ _ u1 u2 u3 = exist2 _ _ v1 v2 v3. Proof. destruct pqr as [p q r]. destruct r, q, p; simpl. reflexivity. Defined. (** Equality of [sig2] is itself a [sig2] (backwards-reasoning version) *) Definition eq_sig2_uncurried {A} {P Q : A -> Prop} (u v : { a : A | P a & Q a }) (pqr : { p : proj1_sig u = proj1_sig v | rew p in proj2_sig u = proj2_sig v & rew p in proj3_sig u = proj3_sig v }) : u = v. Proof. destruct u as [u1 u2 u3], v as [v1 v2 v3]; simpl in *. apply eq_exist2_uncurried; exact pqr. Defined. Lemma eq_exist2_curried {A : Type} {P Q : A -> Prop} {u1 v1 : A} {u2 : P u1} {v2 : P v1} {u3 : Q u1} {v3 : Q v1} (p : u1 = v1) (q : rew p in u2 = v2) (r : rew p in u3 = v3) : exist2 P Q u1 u2 u3 = exist2 P Q v1 v2 v3. Proof. apply eq_sig2_uncurried; exists p; exact q + exact r. Defined. (** Curried version of proving equality of sigma types *) Definition eq_sig2 {A} {P Q : A -> Prop} (u v : { a : A | P a & Q a }) (p : proj1_sig u = proj1_sig v) (q : rew p in proj2_sig u = proj2_sig v) (r : rew p in proj3_sig u = proj3_sig v) : u = v := eq_sig2_uncurried u v (exist2 _ _ p q r). (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_exist2_l {A : Type} {P Q : A -> Prop} {u1 : A} {u2 : P u1} {u3 : Q u1} {v : { a : A | P a & Q a }} (p : u1 = proj1_sig v) (q : rew p in u2 = proj2_sig v) (r : rew p in u3 = proj3_sig v) : exist2 P Q u1 u2 u3 = v := eq_sig2 (exist2 P Q u1 u2 u3) v p q r. Definition eq_exist2_r {A : Type} {P Q : A -> Prop} {u : { a : A | P a & Q a }} {v1 : A} {v2 : P v1} {v3 : Q v1} (p : proj1_sig u = v1) (q : rew p in proj2_sig u = v2) (r : rew p in proj3_sig u = v3) : u = exist2 P Q v1 v2 v3 := eq_sig2 u (exist2 P Q v1 v2 v3) p q r. (** Equality of [sig2] when the second property is an hProp *) Definition eq_sig2_hprop {A} {P Q : A -> Prop} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : { a : A | P a & Q a }) (p : u = v :> { a : A | P a }) : u = v := eq_sig2 u v (proj1_sig_eq p) (proj2_sig_eq p) (Q_hprop _ _ _). (** Equivalence of equality of [sig2] with a [sig2] of equality *) (** We could actually prove an isomorphism here, and not just [<->], but for simplicity, we don't. *) Definition eq_sig2_uncurried_iff {A P Q} (u v : { a : A | P a & Q a }) : u = v <-> { p : proj1_sig u = proj1_sig v | rew p in proj2_sig u = proj2_sig v & rew p in proj3_sig u = proj3_sig v }. Proof. split; [ intro; subst; exists eq_refl; reflexivity | apply eq_sig2_uncurried ]. Defined. (** Induction principle for [@eq (sig2 _ _)] *) Definition eq_sig2_rect {A P Q} {u v : { a : A | P a & Q a }} (R : u = v -> Type) (f : forall p q r, R (eq_sig2 u v p q r)) : forall p, R p. Proof. intro p. specialize (f (proj1_sig_of_sig2_eq p) (proj2_sig_of_sig2_eq p) (proj3_sig_eq p)). destruct u, p; exact f. Defined. Definition eq_sig2_rec {A P Q u v} (R : u = v :> { a : A | P a & Q a } -> Set) := eq_sig2_rect R. Definition eq_sig2_ind {A P Q u v} (R : u = v :> { a : A | P a & Q a } -> Prop) := eq_sig2_rec R. (** In order to have a performant [inversion_sigma], we define specialized versions for when we have constructors on one or both sides of the equality *) Definition eq_sig2_rect_exist2_l {A P Q} {u1 u2 u3 v} (R : _ -> Type) (f : forall p q r, R (@eq_exist2_l A P Q u1 u2 u3 v p q r)) : forall p, R p := eq_sig2_rect R f. Definition eq_sig2_rect_exist2_r {A P Q} {u v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (@eq_exist2_r A P Q u v1 v2 v3 p q r)) : forall p, R p := eq_sig2_rect R f. Definition eq_sig2_rect_exist2 {A P Q} {u1 u2 u3 v1 v2 v3} (R : _ -> Type) (f : forall p q r, R (@eq_exist2_curried A P Q u1 v1 u2 v2 u3 v3 p q r)) : forall p, R p := eq_sig2_rect R f. (** We want uncurried versions so [inversion_sigma] can accept intropatterns, but we use [ex2] types for the induction hypothesis to avoid extraction errors about informative inductive types having Prop instances *) Definition eq_sig2_rect_uncurried {A P Q} {u v : { a : A | P a & Q a }} (R : u = v -> Type) (f : forall pqr : exists2 p : proj1_sig u = proj1_sig v, _ & _, R (eq_sig2 u v (ex_proj1 pqr) (ex_proj2 pqr) (ex_proj3 pqr))) : forall p, R p := eq_sig2_rect R (fun p q r => f (ex_intro2 _ _ p q r)). Definition eq_sig2_rec_uncurried {A P Q u v} (R : u = v :> { a : A | P a & Q a } -> Set) := eq_sig2_rect_uncurried R. Definition eq_sig2_ind_uncurried {A P Q u v} (R : u = v :> { a : A | P a & Q a } -> Prop) := eq_sig2_rec_uncurried R. (** Equivalence of equality of [sig2] involving hProps with equality of the first components *) Definition eq_sig2_hprop_iff {A} {P Q : A -> Prop} (Q_hprop : forall (x : A) (p q : Q x), p = q) (u v : { a : A | P a & Q a }) : u = v <-> (u = v :> { a : A | P a }) := conj (fun p => f_equal (@sig_of_sig2 _ _ _) p) (eq_sig2_hprop Q_hprop u v). (** Non-dependent classification of equality of [sig] *) Definition eq_sig2_nondep {A} {B C : Prop} (u v : @sig2 A (fun _ => B) (fun _ => C)) (p : proj1_sig u = proj1_sig v) (q : proj2_sig u = proj2_sig v) (r : proj3_sig u = proj3_sig v) : u = v := @eq_sig2 _ _ _ u v p (eq_trans (rew_const _ _) q) (eq_trans (rew_const _ _) r). (** Classification of transporting across an equality of [sig2]s *) Lemma rew_sig2 {A x} {P : A -> Type} (Q R : forall a, P a -> Prop) (u : { p : P x | Q x p & R x p }) {y} (H : x = y) : rew [fun a => { p : P a | Q a p & R a p }] H in u = exist2 (Q y) (R y) (rew H in proj1_sig u) (rew dependent H in proj2_sig u) (rew dependent H in proj3_sig u). Proof. destruct H, u; reflexivity. Defined. End sig2. Global Arguments eq_exist2_curried A P Q _ _ _ _ _ _ !p !q !r / . (** [sumbool] is a boolean type equipped with the justification of their value *) Inductive sumbool (A B:Prop) : Set := | left : A -> {A} + {B} | right : B -> {A} + {B} where "{ A } + { B }" := (sumbool A B) : type_scope. Add Printing If sumbool. Arguments left {A B} _, [A] B _. Arguments right {A B} _ , A [B] _. Register sumbool as core.sumbool.type. (** [sumor] is an option type equipped with the justification of why it may not be a regular value *) #[universes(template)] Inductive sumor (A:Type) (B:Prop) : Type := | inleft : A -> A + {B} | inright : B -> A + {B} where "A + { B }" := (sumor A B) : type_scope. Add Printing If sumor. Arguments inleft {A B} _ , [A] B _. Arguments inright {A B} _ , A [B] _. (* Unset Universe Polymorphism. *) (** Various forms of the axiom of choice for specifications *) Section Choice_lemmas. Variables S S' : Set. Variable R : S -> S' -> Prop. Variable R' : S -> S' -> Set. Variables R1 R2 : S -> Prop. Lemma Choice : (forall x:S, {y:S' | R x y}) -> {f:S -> S' | forall z:S, R z (f z)}. Proof. intro H. exists (fun z => proj1_sig (H z)). intro z; destruct (H z); assumption. Defined. Lemma Choice2 : (forall x:S, {y:S' & R' x y}) -> {f:S -> S' & forall z:S, R' z (f z)}. Proof. intro H. exists (fun z => projT1 (H z)). intro z; destruct (H z); assumption. Defined. Lemma bool_choice : (forall x:S, {R1 x} + {R2 x}) -> {f:S -> bool | forall x:S, f x = true /\ R1 x \/ f x = false /\ R2 x}. Proof. intro H. exists (fun z:S => if H z then true else false). intro z; destruct (H z); auto. Defined. End Choice_lemmas. Section Dependent_choice_lemmas. Variable X : Type. Variable R : X -> X -> Prop. Lemma dependent_choice : (forall x:X, {y | R x y}) -> forall x0, {f : nat -> X | f O = x0 /\ forall n, R (f n) (f (S n))}. Proof. 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. - intro n; induction n; simpl; apply proj2_sig. Defined. End Dependent_choice_lemmas. (** A result of type [(Exc A)] is either a normal value of type [A] or an [error] : [Inductive Exc [A:Type] : Type := value : A->(Exc A) | error : (Exc A)]. It is implemented using the option type. *) Section Exc. Variable A : Type. Definition Exc := option A. Definition value := @Some A. Definition error := @None A. End Exc. Arguments error {A}. Definition except := False_rec. (* for compatibility with previous versions *) Arguments except [P] _. Theorem absurd_set : forall (A:Prop) (C:Set), A -> ~ A -> C. Proof. intros A C h1 h2. apply False_rec. apply (h2 h1). Defined. #[global] Hint Resolve left right inleft inright: core. #[global] Hint Resolve exist exist2 existT existT2: core. rocq-9.2.0/theories/Corelib/Init/Sumbool.v000066400000000000000000000057261516144147600204240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Set), (b = true -> P true) -> (b = false -> P false) -> P b := fun b => if b return forall P, (b = true -> P true) -> (b = false -> P false) -> P b then fun _ H _ => H eq_refl else fun _ _ H => H eq_refl. Definition bool_eq_ind : forall (b:bool) (P:bool -> Prop), (b = true -> P true) -> (b = false -> P false) -> P b := fun b => if b return forall P, (b = true -> P true) -> (b = false -> P false) -> P b then fun _ H _ => H eq_refl else fun _ _ H => H eq_refl. (** Logic connectives on type [sumbool] *) Section connectives. Variables A B C D : Prop. Hypothesis H1 : {A} + {B}. Hypothesis H2 : {C} + {D}. Definition sumbool_and : {A /\ C} + {B \/ D} := match H1, H2 with | left a, left c => left (conj a c) | left a, right d => right (or_intror d) | right b, left c => right (or_introl b) | right b, right d => right (or_intror d) end. Definition sumbool_or : {A \/ C} + {B /\ D} := match H1, H2 with | left a, left c => left (or_intror c) | left a, right d => left (or_introl a) | right b, left c => left (or_intror c) | right b, right d => right (conj b d) end. Definition sumbool_not : {B} + {A} := match H1 with | left a => right a | right b => left b end. End connectives. #[global] Hint Resolve sumbool_and sumbool_or: core. #[global] Hint Immediate sumbool_not : core. (** Any decidability function in type [sumbool] can be turned into a function returning a boolean with the corresponding specification: *) Definition bool_of_sumbool (A B : Prop) : {A} + {B} -> {b : bool | if b then A else B} := sumbool_rec _ (exist _ true) (exist _ false). Arguments bool_of_sumbool : default implicits. rocq-9.2.0/theories/Corelib/Init/Tactics.v000066400000000000000000000277521516144147600204010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* negneg H | |- (_->False) => negneg H | |- _ => negpos H end in let pos H := match goal with | |- (~_) => posneg H | |- (_->False) => posneg H | |- _ => pospos H end in match type of H with | (~_) => neg H | (_->False) => neg H | _ => (elim H;fail) || pos H end. (* A useful complement to contradict. Here H:A while G allows concluding ~A *) Ltac false_hyp H G := let T := type of H in absurd T; [ apply G | assumption ]. (* A case with no loss of information. *) Ltac case_eq x := generalize (eq_refl x); pattern x at -1; case x. (* use either discriminate or injection on a hypothesis *) Ltac destr_eq H := discriminate H || (try (injection H as [= H])). (* Similar variants of destruct *) Tactic Notation "destruct_with_eqn" constr(x) := destruct x eqn:?. Tactic Notation "destruct_with_eqn" ident(n) := try intros until n; destruct n eqn:?. Tactic Notation "destruct_with_eqn" ":" ident(H) constr(x) := destruct x eqn:H. Tactic Notation "destruct_with_eqn" ":" ident(H) ident(n) := try intros until n; destruct n eqn:H. (** Break every hypothesis of a certain type *) Ltac destruct_all t := match goal with | x : t |- _ => destruct x; destruct_all t | _ => idtac end. (* Rewriting in all hypothesis several times everywhere *) Tactic Notation "rewrite_all" constr(eq) := repeat rewrite eq in *. Tactic Notation "rewrite_all" "<-" constr(eq) := repeat rewrite <- eq in *. (** Tactics for applying equivalences. The following code provides tactics "apply -> t", "apply <- t", "apply -> t in H" and "apply <- t in H". Here t is a term whose type consists of nested dependent and nondependent products with an equivalence A <-> B as the conclusion. The tactics with "->" in their names apply A -> B while those with "<-" in the name apply B -> A. *) (* The idea of the tactics is to first provide a term in the context whose type is the implication (in one of the directions), and then apply it. The first idea is to produce a statement "forall ..., A -> B" (call this type T) and then do "assert (H : T)" for a fresh H. Thus, T can be proved from the original equivalence and then used to perform the application. However, currently in Ltac it is difficult to produce such T from the original formula. Therefore, we first pose the original equivalence as H. If the type of H is a dependent product, we create an existential variable and apply H to this variable. If the type of H has the form C -> D, then we do a cut on C. Once we eliminate all products, we split (i.e., destruct) the conjunction into two parts and apply the relevant one. *) Ltac find_equiv H := let T := type of H in lazymatch T with | ?A -> ?B => let H1 := fresh in let H2 := fresh in cut A; [intro H1; pose proof (H H1) as H2; clear H H1; rename H2 into H; find_equiv H | clear H] | forall x : ?t, _ => let a := fresh "a" in let H1 := fresh "H" in evar (a : t); pose proof (H a) as H1; unfold a in H1; clear a; clear H; rename H1 into H; find_equiv H | ?A <-> ?B => idtac | _ => fail "The given statement does not seem to end with an equivalence." end. Ltac bapply lemma todo := let H := fresh in pose proof lemma as H; find_equiv H; [todo H; clear H | .. ]. Tactic Notation "apply" "->" constr(lemma) := bapply lemma ltac:(fun H => destruct H as [H _]; apply H). Tactic Notation "apply" "<-" constr(lemma) := bapply lemma ltac:(fun H => destruct H as [_ H]; apply H). Tactic Notation "apply" "->" constr(lemma) "in" hyp(J) := bapply lemma ltac:(fun H => destruct H as [H _]; apply H in J). Tactic Notation "apply" "<-" constr(lemma) "in" hyp(J) := bapply lemma ltac:(fun H => destruct H as [_ H]; apply H in J). (** An experimental tactic simpler than auto that is useful for ending proofs "in one step" *) Ltac easy := let rec use_hyp H := match type of H with | _ /\ _ => exact H || destruct_hyp H | _ => try solve [inversion H] end with do_intro := let H := fresh in intro H; use_hyp H with destruct_hyp H := case H; clear H; do_intro; do_intro in let rec use_hyps := match goal with | H : _ /\ _ |- _ => exact H || (destruct_hyp H; use_hyps) | H : _ |- _ => solve [inversion H] | _ => idtac end in let do_atom := solve [ trivial with eq_true | reflexivity | symmetry; trivial | contradiction ] in let rec do_ccl := try do_atom; repeat (do_intro; try do_atom); solve [ split; do_ccl ] in solve [ do_atom | use_hyps; do_ccl ] || fail "Cannot solve this goal". Ltac Ltac.easy_forward_decl ::= easy. Tactic Notation "now" tactic(t) := t; easy. (** Slightly more than [easy]*) Ltac easy' := repeat split; simpl; easy || now destruct 1. (** A tactic to document or check what is proved at some point of a script *) Ltac now_show c := change c. (** Support for rewriting decidability statements *) 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 C decide H P H0; 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 C decide H P H0; destruct decide. - contradiction. - apply H0. Qed. Tactic Notation "decide" constr(lemma) "with" constr(H) := let try_to_merge_hyps H := try (clear H; intro H) || (let H' := fresh H "bis" in intro H'; try clear H') || (let H' := fresh in intro H'; try clear H') in match type of H with | ~ ?C => apply (decide_right lemma H); try_to_merge_hyps H | ?C -> False => apply (decide_right lemma H); try_to_merge_hyps H | _ => apply (decide_left lemma H); try_to_merge_hyps H end. (** Clear an hypothesis and its dependencies *) Tactic Notation "clear" "dependent" hyp(h) := let rec depclear h := clear h || lazymatch goal with | H : context [ h ] |- _ => depclear H; depclear h | H := context [ h ] |- _ => depclear H; depclear h end || fail "hypothesis to clear is used in the conclusion (maybe indirectly)" in depclear h. (** Revert an hypothesis and its dependencies : this is actually generalize dependent... *) #[deprecated(note="Use ""generalize dependent"" instead (""revert dependent"" is currently an alias)", since="8.18")] Tactic Notation "revert" "dependent" hyp(h) := generalize dependent h. (** Provide an error message for dependent induction/dependent destruction that reports an import is required to use it. Importing Stdlib.Program.Equality will shadow this notation with the actual tactics. *) Tactic Notation "dependent" "induction" ident(H) := fail "To use dependent induction, first [Require Import Stdlib.Program.Equality.]". Tactic Notation "dependent" "destruction" ident(H) := fail "To use dependent destruction, first [Require Import Stdlib.Program.Equality.]". (** *** [inversion_sigma] *) (** The built-in [inversion] will frequently leave equalities of dependent pairs. When the first type in the pair is an hProp or otherwise simplifies, [inversion_sigma] is useful; it will replace the equality of pairs with a pair of equalities, one involving a term casted along the other. This might also prove useful for writing a version of [inversion] / [dependent destruction] which does not lose information, i.e., does not turn a goal which is provable into one which requires axiom K / UIP. *) Ltac lookup_inversion_sigma_rect H := lazymatch type of H with | ex_intro _ _ _ = ex_intro _ _ _ => uconstr:(eq_ex_rect_ex_intro) | exist _ _ _ = exist _ _ _ => uconstr:(eq_sig_rect_exist) | existT _ _ _ = existT _ _ _ => uconstr:(eq_sigT_rect_existT) | _ = ex_intro _ _ _ => uconstr:(eq_ex_rect_ex_intro_r) | _ = exist _ _ _ => uconstr:(eq_sig_rect_exist_r) | _ = existT _ _ _ => uconstr:(eq_sigT_rect_existT_r) | ex_intro _ _ _ = _ => uconstr:(eq_ex_rect_ex_intro_l) | exist _ _ _ = _ => uconstr:(eq_sig_rect_exist_l) | existT _ _ _ = _ => uconstr:(eq_sigT_rect_existT_l) | ex_intro2 _ _ _ _ _ = ex_intro2 _ _ _ _ _ => uconstr:(eq_ex2_rect_ex_intro2) | exist2 _ _ _ _ _ = exist2 _ _ _ _ _ => uconstr:(eq_sig2_rect_exist2) | existT2 _ _ _ _ _ = existT2 _ _ _ _ _ => uconstr:(eq_sigT2_rect_existT2) | _ = ex_intro2 _ _ _ _ _ => uconstr:(eq_ex2_rect_ex_intro2_r) | _ = exist2 _ _ _ _ _ => uconstr:(eq_sig2_rect_exist2_r) | _ = existT2 _ _ _ _ _ => uconstr:(eq_sigT2_rect_existT2_r) | ex_intro2 _ _ _ _ _ = _ => uconstr:(eq_ex2_rect_ex_intro2_l) | exist2 _ _ _ _ _ = _ => uconstr:(eq_sig2_rect_exist2_l) | existT2 _ _ _ _ _ = _ => uconstr:(eq_sigT2_rect_existT2_l) | _ = _ :> ?T => let sig := uconstr:(@sig) in let sig2 := uconstr:(@sig2) in let sigT := uconstr:(@sigT) in let sigT2 := uconstr:(@sigT2) in let ex := uconstr:(@ex) in let ex2 := uconstr:(@ex2) in fail 0 "Type" "of" H "is" "not" "an" "equality" "of" "recognized" "Ξ£" "types:" "expected" "one" "of" sig sig2 sigT sigT2 ex "or" ex2 "but" "got" T | _ => fail 0 H "is" "not" "an" "equality" "of" "Ξ£" "types" end. Ltac inversion_sigma_on_as H ip := let rect := lookup_inversion_sigma_rect H in induction H as ip using rect. Ltac inversion_sigma_on H := inversion_sigma_on_as H ipattern:([]). Ltac inversion_sigma_step := match goal with | [ H : _ |- _ ] => inversion_sigma_on H end. Ltac inversion_sigma := repeat inversion_sigma_step. Tactic Notation "inversion_sigma" := inversion_sigma. Tactic Notation "inversion_sigma" hyp(H) := inversion_sigma_on H. Tactic Notation "inversion_sigma" hyp(H) "as" simple_intropattern(ip) := inversion_sigma_on_as H ip. (** A version of [time] that works for constrs *) Ltac time_constr tac := let eval_early := match goal with _ => restart_timer end in let ret := tac () in let eval_early := match goal with _ => finish_timing ( "Tactic evaluation" ) end in ret. (** Useful combinators *) Ltac assert_fails tac := tryif (once tac) then gfail 0 tac "succeeds" else idtac. Tactic Notation "assert_fails" tactic3(tac) := assert_fails tac. Create HintDb rewrite discriminated. #[global] Hint Variables Opaque : rewrite. (** A variant of [apply] using [refine], doing as much conversion as necessary. *) Ltac rapply p := (** before we try to add more underscores, first ensure that adding such underscores is valid *) (assert_succeeds (idtac; let __ := open_constr:(p _) in idtac); rapply uconstr:(p _)) || refine p. rocq-9.2.0/theories/Corelib/Init/Tauto.v000066400000000000000000000112741516144147600200730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* intro | |- (Corelib.Init.Logic.not _) => unfold Corelib.Init.Logic.not at 1; intro end. Local Ltac axioms flags := match reverse goal with | |- ?X1 => is_unit_or_eq flags X1; constructor 1 | H:?X1 |- _ => is_empty flags X1; elim H | _ => assumption end. Local Ltac simplif flags := not_dep_intros; repeat (match reverse goal with | id: ?X1 |- _ => is_conj flags X1; elim id; do 2 intro; clear id | id: (Corelib.Init.Logic.iff _ _) |- _ => elim id; do 2 intro; clear id | id: (Corelib.Init.Logic.not _) |- _ => red in id | id: ?X1 |- _ => is_disj flags X1; elim id; intro; clear id | _ => (* behaves as matching [ id0: ?X1 -> ?X2, id1: ?X1 |- _ ] with universe-aware conversion *) find_cut ltac:(fun id0 id1 X2 => (* generalize (id0 id1); intro; clear id0 does not work (see Marco Maggiesi's BZ#301) so we instead use Assert and exact. *) assert X2; [exact (id0 id1) | clear id0] ) | id: forall (_ : ?X1), ?X2|- _ => is_unit_or_eq flags X1; cut X2; [ intro; clear id | (* id : forall (_: ?X1), ?X2 |- ?X2 *) cut X1; [exact id| constructor 1; fail] ] | id: forall (_ : ?X1), ?X2|- _ => flatten_contravariant_conj flags X1 X2 id (* moved from "id:(?A/\?B)->?X2|-" to "?A->?B->?X2|-" *) | id: forall (_: Corelib.Init.Logic.iff ?X1 ?X2), ?X3|- _ => assert (forall (_: forall _:X1, X2), forall (_: forall _: X2, X1), X3) by (do 2 intro; apply id; split; assumption); clear id | id: forall (_:?X1), ?X2|- _ => flatten_contravariant_disj flags X1 X2 id (* moved from "id:(?A\/?B)->?X2|-" to "?A->?X2,?B->?X2|-" *) | |- ?X1 => is_conj flags X1; split | |- (Corelib.Init.Logic.iff _ _) => split | |- (Corelib.Init.Logic.not _) => red end; not_dep_intros). Local Ltac tauto_intuit flags t_reduce t_solver := let rec t_tauto_intuit := (simplif flags; axioms flags || match reverse goal with | id:forall(_: forall (_: ?X1), ?X2), ?X3|- _ => cut X3; [ intro; clear id; t_tauto_intuit | cut (forall (_: X1), X2); [ exact id | generalize (fun y:X2 => id (fun x:X1 => y)); intro; clear id; solve [ t_tauto_intuit ]]] | id:forall (_:not ?X1), ?X3|- _ => cut X3; [ intro; clear id; t_tauto_intuit | cut (not X1); [ exact id | clear id; intro; solve [t_tauto_intuit ]]] | |- ?X1 => is_disj flags X1; solve [left;t_tauto_intuit | right;t_tauto_intuit] end || (* NB: [|- _ -> _] matches any product *) match goal with | |- forall (_ : _), _ => intro; t_tauto_intuit | |- _ => t_reduce;t_solver end || t_solver ) in t_tauto_intuit. Local Ltac intuition_gen flags solver := tauto_intuit flags reduction_not_iff solver. Local Ltac tauto_intuitionistic flags := intuition_gen flags fail || fail "tauto failed". Local Ltac tauto_classical flags := (apply_nnpp || fail "tauto failed"); (tauto_intuitionistic flags || fail "Classical tauto failed"). Local Ltac tauto_gen flags := tauto_intuitionistic flags || tauto_classical flags. Ltac tauto := with_uniform_flags ltac:(fun flags => tauto_gen flags). Ltac dtauto := with_power_flags ltac:(fun flags => tauto_gen flags). Ltac intuition_solver := auto. Local Ltac intuition_then tac := with_uniform_flags ltac:(fun flags => intuition_gen flags tac). Ltac intuition := intuition_then ltac:(idtac;intuition_solver). Local Ltac dintuition_then tac := with_power_flags ltac:(fun flags => intuition_gen flags tac). Ltac dintuition := dintuition_then ltac:(idtac;intuition_solver). Tactic Notation "intuition" := intuition. Tactic Notation "intuition" tactic(t) := intuition_then t. Tactic Notation "dintuition" := dintuition. Tactic Notation "dintuition" tactic(t) := dintuition_then t. rocq-9.2.0/theories/Corelib/Init/Wf.v000066400000000000000000000127531516144147600173560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A -> Prop. (** The accessibility predicate is defined to be non-informative *) (** (Acc_rect is automatically defined because Acc is a singleton type) *) Inductive Acc (x: A) : Prop := Acc_intro : (forall y:A, R y x -> Acc y) -> Acc x. Register Acc as core.wf.acc. Lemma Acc_inv : forall x:A, Acc x -> forall y:A, R y x -> Acc y. destruct 1; trivial. Defined. Global Arguments Acc_inv [x] _ [y] _, [x] _ y _. Register Acc_inv as core.wf.acc_inv. (** A relation is well-founded if every element is accessible *) Definition well_founded := forall a:A, Acc a. Register well_founded as core.wf.well_founded. (** Well-founded induction on [Set] and [Prop] *) Hypothesis Rwf : well_founded. Theorem well_founded_induction_type : forall P:A -> Type, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. Proof. intros; apply Acc_rect; auto. Defined. Theorem well_founded_induction : forall P:A -> Set, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. Proof. exact (fun P:A -> Set => well_founded_induction_type P). Defined. Theorem well_founded_ind : forall P:A -> Prop, (forall x:A, (forall y:A, R y x -> P y) -> P x) -> forall a:A, P a. Proof. exact (fun P:A -> Prop => well_founded_induction_type P). Defined. (** Well-founded fixpoints *) Section FixPoint. Variable P : A -> Type. Variable F : forall x:A, (forall y:A, R y x -> P y) -> P x. Fixpoint Fix_F (x:A) (a:Acc x) : P x := F (fun (y:A) (h:R y x) => Fix_F (Acc_inv a h)). Scheme Acc_inv_dep := Induction for Acc Sort Prop. Lemma Fix_F_eq (x:A) (r:Acc x) : F (fun (y:A) (p:R y x) => Fix_F (x:=y) (Acc_inv r p)) = Fix_F (x:=x) r. Proof. destruct r using Acc_inv_dep; auto. Qed. Definition Fix (x:A) := Fix_F (Rwf x). Section FixPointGen. Hypothesis F_ext : forall (x:A) (f g:forall y:A, R y x -> P y), (forall (y:A) (p q:R y x), f y p = g y q) -> F f = F g. Lemma Fix_F_inv_gen : forall (x:A) (r s:Acc x), Fix_F r = Fix_F s. Proof. intro x; induction (Rwf x); intros r s. rewrite <- (Fix_F_eq r); rewrite <- (Fix_F_eq s); intros. apply F_ext; auto. Qed. Lemma Fix_eq_gen : forall x:A, Fix x = F (fun (y:A) (p:R y x) => Fix y). Proof. intro x; unfold Fix. rewrite <- Fix_F_eq. apply F_ext; intros. apply Fix_F_inv_gen. Qed. End FixPointGen. (** Proof that [well_founded_induction] satisfies the fixpoint equation. It requires an extra property of the functional *) Hypothesis F_ext : forall (x:A) (f g:forall y:A, R y x -> P y), (forall (y:A) (p:R y x), f y p = g y p) -> F f = F g. Lemma Fix_F_inv : forall (x:A) (r s:Acc x), Fix_F r = Fix_F s. Proof. auto using Fix_F_inv_gen. Qed. Lemma Fix_eq : forall x:A, Fix x = F (fun (y:A) (p:R y x) => Fix y). Proof. auto using Fix_eq_gen. Qed. End FixPoint. End Well_founded. (** Well-founded fixpoints over pairs *) Section Well_founded_2. Variables A B : Type. Variable R : A * B -> A * B -> Prop. Variable P : A -> B -> Type. Section FixPoint_2. Variable F : forall (x:A) (x':B), (forall (y:A) (y':B), R (y, y') (x, x') -> P y y') -> P x x'. Fixpoint Fix_F_2 (x:A) (x':B) (a:Acc R (x, x')) : P x x' := F (fun (y:A) (y':B) (h:R (y, y') (x, x')) => Fix_F_2 (x:=y) (x':=y') (Acc_inv a (y,y') h)). End FixPoint_2. Hypothesis Rwf : well_founded R. Theorem well_founded_induction_type_2 : (forall (x:A) (x':B), (forall (y:A) (y':B), R (y, y') (x, x') -> P y y') -> P x x') -> forall (a:A) (b:B), P a b. Proof. intros; apply Fix_F_2; auto. Defined. End Well_founded_2. Abbreviation Acc_iter := Fix_F (only parsing). (* compatibility *) Abbreviation Acc_iter_2 := Fix_F_2 (only parsing). (* compatibility *) (* Added by Julien Forest on 13/11/20 This construction is originally by Georges Gonthier, see https://sympa.inria.fr/sympa/arc/coq-club/2007-07/msg00013.html *) Section Acc_generator. Variable A : Type. Variable R : A -> A -> Prop. (* *Lazily* add 2^n - 1 Acc_intro on top of wf. Needed for fast reductions using Function and Program Fixpoint and probably using Fix and Fix_F_2 *) Fixpoint Acc_intro_generator n (wf : well_founded R) := match n with | O => wf | S n => fun x => Acc_intro x (fun y _ => Acc_intro_generator n (Acc_intro_generator n wf) y) end. End Acc_generator. rocq-9.2.0/theories/Corelib/Init/_CoqProject000066400000000000000000000000271516144147600207350ustar00rootroot00000000000000-R .. Coq -arg -noinit rocq-9.2.0/theories/Corelib/Lists/000077500000000000000000000000001516144147600167765ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Lists/ListDef.v000066400000000000000000000064761516144147600205340ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* B. Fixpoint map (l:list A) : list B := match l with | nil => nil | a :: l => (f a) :: (map l) end. End Map. Section NatSeq. (** [seq] computes the sequence of [len] contiguous integers that starts at [start]. For instance, [seq 2 3] is [2::3::4::nil]. *) Fixpoint seq (start len:nat) : list nat := match len with | 0 => nil | S len => start :: seq (S start) len end. End NatSeq. Section Repeat. Variable A : Type. Fixpoint repeat (x : A) (n: nat ) := match n with | O => nil | S k => x :: repeat x k end. End Repeat. Section Elts. Variable A : Type. (*****************************) (** ** Nth element of a list *) (*****************************) Fixpoint nth (n:nat) (l:list A) (default:A) {struct l} : A := match n, l with | O, x :: l' => x | O, nil => default | S m, nil => default | S m, x :: l' => nth m l' default end. End Elts. Section Cutting. Variable A : Type. Fixpoint firstn (n:nat) (l:list A) : list A := match n with | 0 => nil | S n => match l with | nil => nil | a::l => a::(firstn n l) end end. Fixpoint skipn (n:nat) (l:list A) : list A := match n with | 0 => l | S n => match l with | nil => nil | a::l => skipn n l end end. End Cutting. Section Exists_Forall. (** * Existential and universal predicates over lists *) Variable A:Type. Section One_predicate. Variable P : A -> Prop. Inductive Forall : list A -> Prop := | Forall_nil : Forall nil | Forall_cons : forall x l, P x -> Forall l -> Forall (x :: l). End One_predicate. End Exists_Forall. (***********************) (** ** List comparison *) (***********************) Section Compare. Variable A : Type. Variable cmp : A -> A -> comparison. Fixpoint list_compare (xs ys : list A) : comparison := match xs, ys with | nil , nil => Eq | nil , _ => Lt | _ , nil => Gt | x :: xs, y :: ys => match cmp x y with | Eq => list_compare xs ys | c => c end end%list. End Compare. Unset Universe Polymorphism. rocq-9.2.0/theories/Corelib/Numbers/000077500000000000000000000000001516144147600173135ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Numbers/BinNums.v000066400000000000000000000054611516144147600210630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* positive | xO : positive -> positive | xH : positive. Declare Scope positive_scope. Delimit Scope positive_scope with positive. Bind Scope positive_scope with positive. Arguments xO _%_positive. Arguments xI _%_positive. Declare Scope hex_positive_scope. Delimit Scope hex_positive_scope with xpositive. Register positive as num.pos.type. Register xI as num.pos.xI. Register xO as num.pos.xO. Register xH as num.pos.xH. (** [N] is a datatype representing natural numbers in a binary way, by extending the [positive] datatype with a zero. Numbers in [N] will also be denoted using a decimal notation; e.g. [6%N] will abbreviate [Npos (xO (xI xH))] *) Inductive N : Set := | N0 : N | Npos : positive -> N. Declare Scope N_scope. Delimit Scope N_scope with N. Bind Scope N_scope with N. Arguments Npos _%_positive. Declare Scope hex_N_scope. Delimit Scope hex_N_scope with xN. Register N as num.N.type. Register N0 as num.N.N0. Register Npos as num.N.Npos. (** [Z] is a datatype representing the integers in a binary way. An integer is either zero or a strictly positive number (coded as a [positive]) or a strictly negative number (whose opposite is stored as a [positive] value). Numbers in [Z] will also be denoted using a decimal notation; e.g. [(-6)%Z] will abbreviate [Zneg (xO (xI xH))] *) Inductive Z : Set := | Z0 : Z | Zpos : positive -> Z | Zneg : positive -> Z. Declare Scope Z_scope. Delimit Scope Z_scope with Z. Bind Scope Z_scope with Z. Arguments Zpos _%_positive. Arguments Zneg _%_positive. Declare Scope hex_Z_scope. Delimit Scope hex_Z_scope with xZ. Register Z as num.Z.type. Register Z0 as num.Z.Z0. Register Zpos as num.Z.Zpos. Register Zneg as num.Z.Zneg. rocq-9.2.0/theories/Corelib/Numbers/Cyclic/000077500000000000000000000000001516144147600205215ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Numbers/Cyclic/Int63/000077500000000000000000000000001516144147600214245ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Numbers/Cyclic/Int63/CarryType.v000066400000000000000000000016571516144147600235460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* carry A | C1 : A -> carry A. rocq-9.2.0/theories/Corelib/Numbers/Cyclic/Int63/PrimInt63.v000066400000000000000000000060361516144147600233530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int := fun x => x. Record int_wrapper := wrap_int {int_wrap : int}. Register int_wrapper as num.int63.int_wrapper. Register wrap_int as num.int63.wrap_int. Definition printer (x : int_wrapper) : pos_neg_int63 := Pos (int_wrap x). Definition parser (x : pos_neg_int63) : option int := match x with | Pos p => Some p | Neg _ => None end. Declare Scope int63_scope. Module Import Int63NotationsInternalA. Delimit Scope int63_scope with int63. End Int63NotationsInternalA. Number Notation int parser printer : int63_scope. Module Import Uint63NotationsInternalA. Delimit Scope uint63_scope with uint63. Bind Scope uint63_scope with int. End Uint63NotationsInternalA. Number Notation int parser printer : uint63_scope. (* Logical operations *) Primitive lsl := #int63_lsl. Primitive lsr := #int63_lsr. Primitive land := #int63_land. Primitive lor := #int63_lor. Primitive lxor := #int63_lxor. Primitive asr := #int63_asr. (* Arithmetic modulo operations *) Primitive add := #int63_add. Primitive sub := #int63_sub. Primitive mul := #int63_mul. Primitive mulc := #int63_mulc. Primitive div := #int63_div. Primitive mod := #int63_mod. Primitive divs := #int63_divs. Primitive mods := #int63_mods. (* Comparisons *) Primitive eqb := #int63_eq. Register eqb as num.int63.eqb. Primitive ltb := #int63_lt. Primitive leb := #int63_le. Primitive ltsb := #int63_lts. Primitive lesb := #int63_les. (** Exact arithmetic operations *) Primitive addc := #int63_addc. Primitive addcarryc := #int63_addcarryc. Primitive subc := #int63_subc. Primitive subcarryc := #int63_subcarryc. Primitive diveucl := #int63_diveucl. Primitive diveucl_21 := #int63_div21. Primitive addmuldiv := #int63_addmuldiv. (** Comparison *) Primitive compare := #int63_compare. Primitive compares := #int63_compares. (** Exotic operations *) Primitive head0 := #int63_head0. Primitive tail0 := #int63_tail0. Module Export PrimInt63Notations. Export Int63NotationsInternalA. Export Uint63NotationsInternalA. End PrimInt63Notations. rocq-9.2.0/theories/Corelib/Numbers/Cyclic/Int63/Sint63Axioms.v000066400000000000000000000035521516144147600240670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Gt) : Z_scope. Local Notation "x < y" := (Z.compare x y = Lt) : Z_scope. Definition min_int := Eval vm_compute in (lsl 1 62). (** Translation to and from Z *) Definition to_Z (i : int) := if ltb i min_int then to_Z i else Z.opp (to_Z (sub 0 i)). (** Specification of operations that differ on signed and unsigned ints *) Axiom asr_spec : forall x p, to_Z (asr x p) = Z.div (to_Z x) (2 ^ (to_Z p)). Axiom div_spec : forall x y, to_Z x <> to_Z min_int \/ to_Z y <> Zneg 1 -> to_Z (divs x y) = Z.quot (to_Z x) (to_Z y). Axiom mod_spec : forall x y, to_Z (mods x y) = Z.rem (to_Z x) (to_Z y). Axiom ltb_spec : forall x y, ltsb x y = true <-> to_Z x < to_Z y. Axiom leb_spec : forall x y, lesb x y = true <-> to_Z x <= to_Z y. Axiom compare_spec : forall x y, compares x y = Z.compare (to_Z x) (to_Z y). rocq-9.2.0/theories/Corelib/Numbers/Cyclic/Int63/Uint63Axioms.v000066400000000000000000000127731516144147600240760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 | S n => (if is_even i then Z.double else Z.succ_double) (to_Z_rec n (lsr i 1)) end. Definition to_Z := to_Z_rec size. Fixpoint of_pos_rec (n:nat) (p:positive) {struct p} := match n, p with | O, _ => 0%uint63 | S n, xH => 1%uint63 | S n, xO p => lsl (of_pos_rec n p) 1 | S n, xI p => lor (lsl (of_pos_rec n p) 1) 1 end. Definition of_pos := of_pos_rec size. Definition of_Z z := match z with | Zpos p => of_pos p | 0 => 0%uint63 | Zneg p => sub 0 (of_pos p) end. Definition wB := 2 ^ (Z.of_nat size). (* Bijection : uint63 <-> Bvector size *) Axiom of_to_Z : forall x, of_Z (to_Z x) = x. (** Specification of logical operations *) Axiom lsl_spec : forall x p, to_Z (lsl x p) = Z.modulo (to_Z x * 2 ^ to_Z p) wB. Axiom lsr_spec : forall x p, to_Z (lsr x p) = Z.div (to_Z x) (2 ^ to_Z p). Definition bit i n := negb (is_zero (lsl (lsr i n) (sub digits 1))). Axiom land_spec : forall x y i, bit (land x y) i = andb (bit x i) (bit y i). Axiom lor_spec : forall x y i, bit (lor x y) i = orb (bit x i) (bit y i). Axiom lxor_spec : forall x y i, bit (lxor x y) i = xorb (bit x i) (bit y i). (** Specification of basic opetations *) (* Arithmetic modulo operations *) (* Note: axioms would be simpler if we were using of_Z instead: example: add_spec : forall x y, of_Z (x + y) = of_Z x + of_Z y. *) Axiom add_spec : forall x y, to_Z (add x y) = Z.modulo (to_Z x + to_Z y) wB. Axiom sub_spec : forall x y, to_Z (sub x y) = Z.modulo (to_Z x - to_Z y) wB. Axiom mul_spec : forall x y, to_Z (mul x y) = Z.modulo (to_Z x * to_Z y) wB. Axiom mulc_spec : forall x y, to_Z x * to_Z y = to_Z (fst (mulc x y)) * wB + to_Z (snd (mulc x y)). Axiom div_spec : forall x y, to_Z (div x y) = Z.div (to_Z x) (to_Z y). Axiom mod_spec : forall x y, to_Z (PrimInt63.mod x y) = Z.modulo (to_Z x) (to_Z y). (* Comparisons *) Axiom eqb_correct : forall i j, eqb i j = true -> i = j. Axiom eqb_refl : forall x, eqb x x = true. Axiom ltb_spec : forall x y, ltb x y = true <-> to_Z x < to_Z y. Axiom leb_spec : forall x y, leb x y = true <-> to_Z x <= to_Z y. (** Exotic operations *) (** Axioms on operations which are just short cut *) Definition compare_def x y := if ltb x y then Lt else if eqb x y then Eq else Gt. Axiom compare_def_spec : forall x y, compare x y = compare_def x y. Axiom head0_spec : forall x, 0 < to_Z x -> Z.div wB 2 <= 2 ^ (to_Z (head0 x)) * to_Z x < wB. Axiom tail0_spec : forall x, 0 < to_Z x -> exists y, Z0 <= y /\ to_Z x = (2 * y + 1) * (2 ^ to_Z (tail0 x)). Definition addc_def x y := let r := add x y in if ltb r x then C1 r else C0 r. Axiom addc_def_spec : forall x y, addc x y = addc_def x y. Definition addcarry i j := add (add i j) 1. Definition addcarryc_def x y := let r := addcarry x y in if leb r x then C1 r else C0 r. Axiom addcarryc_def_spec : forall x y, addcarryc x y = addcarryc_def x y. Definition subc_def x y := if leb y x then C0 (sub x y) else C1 (sub x y). Axiom subc_def_spec : forall x y, subc x y = subc_def x y. Definition subcarryc_def x y := if ltb y x then C0 (sub (sub x y) 1) else C1 (sub (sub x y) 1). Axiom subcarryc_def_spec : forall x y, subcarryc x y = subcarryc_def x y. Definition diveucl_def x y := (div x y, PrimInt63.mod 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 let (q',r') := Z.div_eucl (to_Z a1 * wB + to_Z a2) (to_Z b) in to_Z a1 < to_Z b -> to_Z q = q' /\ to_Z r = r'. Definition addmuldiv_def p x y := lor (lsl x p) (lsr y (sub digits p)). Axiom addmuldiv_def_spec : forall p x y, addmuldiv p x y = addmuldiv_def p x y. rocq-9.2.0/theories/Corelib/Program/000077500000000000000000000000001516144147600173075ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Program/Basics.v000066400000000000000000000036041516144147600207050ustar00rootroot00000000000000(* -*- coding: utf-8 -*- *) (************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* C) (f : A -> B) := fun x : A => g (f x). #[global] Hint Unfold compose : core. Declare Scope program_scope. Notation " g ∘ f " := (compose g f) (at level 40, left associativity) : program_scope. Local Open Scope program_scope. (** The non-dependent function space between [A] and [B]. *) Definition arrow (A B : Type) := A -> B. Register arrow as core.arrow. (** Logical implication. *) Definition impl (A B : Prop) : Prop := A -> B. Register impl as core.impl. (** The constant function [const a] always returns [a]. *) Definition const {A B} (a : A) := fun _ : B => a. (** The [flip] combinator reverses the first two arguments of a function. *) Definition flip {A B C} (f : A -> B -> C) x y := f y x. Register flip as core.flip. (** Application as a combinator. *) Definition apply {A B} (f : A -> B) (x : A) := f x. rocq-9.2.0/theories/Corelib/Program/Tactics.v000066400000000000000000000222641516144147600210760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* idtac T end. Ltac show_hyp id := match goal with | [ H := ?b : ?T |- _ ] => match H with | id => idtac id ":=" b ":" T end | [ H : ?T |- _ ] => match H with | id => idtac id ":" T end end. Ltac show_hyps := try match reverse goal with | [ H : ?T |- _ ] => show_hyp H ; fail end. (** The [do] tactic but using a Rocq-side nat. *) Ltac do_nat n tac := match n with | 0 => idtac | S ?n' => tac ; do_nat n' tac end. (** Do something on the last hypothesis, or fail *) Ltac on_last_hyp tac := lazymatch goal with [ H : _ |- _ ] => tac H end. (** Destructs one pair, without care regarding naming. *) Ltac destruct_one_pair := match goal with | [H : (_ /\ _) |- _] => destruct H | [H : prod _ _ |- _] => destruct H end. (** Repeateadly destruct pairs. *) Ltac destruct_pairs := repeat (destruct_one_pair). (** Destruct one existential package, keeping the name of the hypothesis for the first component. *) Ltac destruct_one_ex := let tac H := let ph := fresh "H" in (destruct H as [H ph]) in let tac2 H := let ph := fresh "H" in let ph' := fresh "H" in (destruct H as [H ph ph']) in let tacT H := let ph := fresh "X" in (destruct H as [H ph]) in let tacT2 H := let ph := fresh "X" in let ph' := fresh "X" in (destruct H as [H ph ph']) in match goal with | [H : (ex _) |- _] => tac H | [H : (sig ?P) |- _ ] => tac H | [H : (sigT ?P) |- _ ] => tacT H | [H : (ex2 _ _) |- _] => tac2 H | [H : (sig2 ?P _) |- _ ] => tac2 H | [H : (sigT2 ?P _) |- _ ] => tacT2 H end. (** Repeateadly destruct existentials. *) Ltac destruct_exists := repeat (destruct_one_ex). (** Repeateadly destruct conjunctions and existentials. *) Ltac destruct_conjs := repeat (destruct_one_pair || destruct_one_ex). (** Destruct an existential hypothesis [t] keeping its name for the first component and using [Ht] for the second *) Tactic Notation "destruct" "exist" ident(t) ident(Ht) := destruct t as [t Ht]. (** Destruct a disjunction keeping its name in both subgoals. *) Tactic Notation "destruct" "or" ident(H) := destruct H as [H|H]. (** Discriminate that also work on a [x <> x] hypothesis. *) Ltac discriminates := match goal with | [ H : ?x <> ?x |- _ ] => elim H ; reflexivity | _ => discriminate end. (** Revert the last hypothesis. *) Ltac revert_last := match goal with [ H : _ |- _ ] => revert H end. (** Repeatedly reverse the last hypothesis, putting everything in the goal. *) Ltac reverse := repeat revert_last. (** Reverse everything up to hypothesis id (not included). *) Ltac revert_until id := on_last_hyp ltac:(fun id' => match id' with | id => idtac | _ => revert id' ; revert_until id end). (** Clear duplicated hypotheses *) Ltac clear_dup := match goal with | [ H : ?X |- _ ] => match goal with | [ H' : ?Y |- _ ] => match H with | H' => fail 2 | _ => unify X Y ; (clear H' || clear H) end end end. Ltac clear_dups := repeat clear_dup. (** Try to clear everything except some hyp *) Ltac clear_except hyp := repeat match goal with [ H : _ |- _ ] => match H with | hyp => fail 1 | _ => clear H end end. (** A non-failing subst that substitutes as much as possible. *) Ltac subst_no_fail := repeat (match goal with [ H : ?X = ?Y |- _ ] => subst X || subst Y end). Tactic Notation "subst" "*" := subst_no_fail. Ltac on_application f tac T := match T with | context [f ?x ?y ?z ?w ?v ?u ?a ?b ?c] => tac (f x y z w v u a b c) | context [f ?x ?y ?z ?w ?v ?u ?a ?b] => tac (f x y z w v u a b) | context [f ?x ?y ?z ?w ?v ?u ?a] => tac (f x y z w v u a) | context [f ?x ?y ?z ?w ?v ?u] => tac (f x y z w v u) | context [f ?x ?y ?z ?w ?v] => tac (f x y z w v) | context [f ?x ?y ?z ?w] => tac (f x y z w) | context [f ?x ?y ?z] => tac (f x y z) | context [f ?x ?y] => tac (f x y) | context [f ?x] => tac (f x) end. (** Tactical [on_call f tac] applies [tac] on any application of [f] in the hypothesis or goal. *) Ltac on_call f tac := match goal with | |- ?T => on_application f tac T | H : ?T |- _ => on_application f tac T end. (* Destructs calls to f in hypothesis or conclusion, useful if f creates a subset object. *) Ltac destruct_call f := let tac t := (destruct t) in on_call f tac. Ltac destruct_calls f := repeat destruct_call f. Ltac destruct_call_in f H := let tac t := (destruct t) in let T := type of H in on_application f tac T. Ltac destruct_call_as f l := let tac t := (destruct t as l) in on_call f tac. Ltac destruct_call_as_in f l H := let tac t := (destruct t as l) in let T := type of H in on_application f tac T. Tactic Notation "destruct_call" constr(f) := destruct_call f. (** Permit to name the results of destructing the call to [f]. *) Tactic Notation "destruct_call" constr(f) "as" simple_intropattern(l) := destruct_call_as f l. (** Specify the hypothesis in which the call occurs as well. *) Tactic Notation "destruct_call" constr(f) "in" hyp(id) := destruct_call_in f id. Tactic Notation "destruct_call" constr(f) "as" simple_intropattern(l) "in" hyp(id) := destruct_call_as_in f l id. (** A marker for prototypes to destruct. *) Definition fix_proto {A : Type} (a : A) := a. Register fix_proto as program.tactic.fix_proto. Ltac destruct_rec_calls := match goal with | [ H : fix_proto _ |- _ ] => destruct_calls H ; clear H end. Ltac destruct_all_rec_calls := repeat destruct_rec_calls ; unfold fix_proto in *. (** Try to inject any potential constructor equality hypothesis. *) Ltac autoinjection tac := match goal with | [ H : ?f ?a = ?f' ?a' |- _ ] => tac H end. Ltac inject H := progress (inversion H ; subst*; clear_dups) ; clear H. Ltac autoinjections := repeat (clear_dups ; autoinjection ltac:(inject)). (** Destruct an hypothesis by first copying it to avoid dependencies. *) Ltac destruct_nondep H := let H0 := fresh "H" in assert(H0 := H); destruct H0. (** If bang appears in the goal, it means that we have a proof of False and the goal is solved. *) Ltac bang := match goal with | |- ?x => match x with | context [False_rect _ ?p] => elim p end end. (** A tactic to show contradiction by first asserting an automatically provable hypothesis. *) Tactic Notation "contradiction" "by" constr(t) := let H := fresh in assert t as H by auto with * ; contradiction. (** A tactic that adds [H:=p:typeof(p)] to the context if no hypothesis of the same type appears in the goal. Useful to do saturation using tactics. *) Ltac add_hypothesis H' p := match type of p with ?X => match goal with | [ H : X |- _ ] => fail 1 | _ => set (H':=p) ; try (change p with H') ; clearbody H' end end. (** A tactic to replace an hypothesis by another term. *) Ltac replace_hyp H c := let H' := fresh "H" in assert(H' := c) ; clear H ; rename H' into H. (** A tactic to refine an hypothesis by supplying some of its arguments. *) Ltac refine_hyp c := let tac H := replace_hyp H c in match c with | ?H _ => tac H | ?H _ _ => tac H | ?H _ _ _ => tac H | ?H _ _ _ _ => tac H | ?H _ _ _ _ _ => tac H | ?H _ _ _ _ _ _ => tac H | ?H _ _ _ _ _ _ _ => tac H | ?H _ _ _ _ _ _ _ _ => tac H end. (** The default simplification tactic used by Program is defined by [program_simpl], sometimes [auto] is not enough, better rebind using [Obligation Tactic := tac] in this case, possibly using [program_simplify] to use standard goal-cleaning tactics. *) Ltac program_simplify := simpl; intros ; destruct_all_rec_calls ; repeat (destruct_conjs; simpl proj1_sig in * ); subst*; autoinjections ; try discriminates ; try (solve [ red ; intros ; destruct_conjs ; autoinjections ; discriminates ]). (** Restrict automation to propositional obligations. *) Ltac program_solve_wf := match goal with | |- well_founded _ => auto with * | |- ?T => match type of T with Prop => auto end end. Create HintDb program discriminated. Ltac program_simpl := program_simplify ; try typeclasses eauto 10 with program ; try program_solve_wf. #[global] Obligation Tactic := program_simpl. #[export] Obligation Tactic := program_simpl. rocq-9.2.0/theories/Corelib/Program/Utils.v000066400000000000000000000040361516144147600206010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let (x,y) := anonymous in P)) (x name, y name) : type_scope. Declare Scope program_scope. Delimit Scope program_scope with prg. (** Generates an obligation to prove False. *) Notation " ! " := (False_rect _ _) : program_scope. (** Abbreviation for first projection and hiding of proofs of subset objects. *) Notation " ` t " := (proj1_sig t) (at level 10, t at next level) : program_scope. (** Coerces objects to their support before comparing them. *) (** Construct a dependent disjunction from a boolean. *) Abbreviation dec := sumbool_of_bool. (** The notations [in_right] and [in_left] construct objects of a dependent disjunction. *) (** Hide proofs and generates obligations when put in a term. *) Abbreviation in_left := (@left _ _ _). Abbreviation in_right := (@right _ _ _). (** Extraction directives *) (* Extraction Inline proj1_sig. Extract Inductive unit => "unit" [ "()" ]. Extract Inductive bool => "bool" [ "true" "false" ]. Extract Inductive sumbool => "bool" [ "true" "false" ]. (* Extract Inductive prod "'a" "'b" => " 'a * 'b " [ "(,)" ]. *) (* Extract Inductive sigT => "prod" [ "" ]. *) *) rocq-9.2.0/theories/Corelib/Program/Wf.v000066400000000000000000000153361516144147600200620ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A -> Prop. Hypothesis Rwf : well_founded R. Variable P : A -> Type. Variable F_sub : forall x:A, (forall y: { y : A | R y x }, P (proj1_sig y)) -> P x. Fixpoint Fix_F_sub (x : A) (r : Acc R x) : P x := F_sub x (fun y: { y : A | R y x} => Fix_F_sub (proj1_sig y) (Acc_inv r (proj2_sig y))). Definition Fix_sub (x : A) := Fix_F_sub x (Rwf x). Register Fix_sub as program.wf.fix_sub. (* Abbreviation Fix_F := (Fix_F_sub P F_sub) (only parsing). (* alias *) *) (* Definition Fix (x:A) := Fix_F_sub P F_sub x (Rwf x). *) Hypothesis F_ext : forall (x:A) (f g:forall y:{y:A | R y x}, P (`y)), (forall y:{y : A | R y x}, f y = g y) -> F_sub x f = F_sub x g. Lemma Fix_F_eq : forall (x:A) (r:Acc R x), F_sub x (fun y:{y:A | R y x} => Fix_F_sub (`y) (Acc_inv r (proj2_sig y))) = Fix_F_sub x r. Proof. intros x r; destruct r using Acc_inv_dep; auto. Qed. Lemma Fix_F_inv : forall (x:A) (r s:Acc R x), Fix_F_sub x r = Fix_F_sub x s. Proof. intro x; induction (Rwf x); intros. rewrite <- 2 Fix_F_eq; intros. apply F_ext; intros []; auto. Qed. Lemma Fix_eq : forall x:A, Fix_sub x = F_sub x (fun y:{ y:A | R y x} => Fix_sub (proj1_sig y)). Proof. intro x; unfold Fix_sub. rewrite <- (Fix_F_eq ). apply F_ext; intros. apply Fix_F_inv. Qed. Lemma fix_sub_eq : forall x : A, Fix_sub x = let f_sub := F_sub in f_sub x (fun y: {y : A | R y x} => Fix_sub (`y)). Proof. exact Fix_eq. Qed. End Well_founded. Set Implicit Arguments. (** Reasoning about well-founded fixpoints on measures. *) Section Measure_well_founded. (* Measure relations are well-founded if the underlying relation is well-founded. *) Variables T M: Type. Variable R: M -> M -> Prop. Hypothesis wf: well_founded R. Variable m: T -> M. Definition MR (x y: T): Prop := R (m x) (m y). Register MR as program.wf.mr. Lemma measure_wf: well_founded MR. Proof. unfold well_founded. cut (forall (a: M) (a0: T), m a0 = a -> Acc MR a0). + intros H a. apply (H (m a)); auto. + apply (@well_founded_ind M R wf (fun mm => forall a, m a = mm -> Acc MR a)). intros ? H ? H0. apply Acc_intro. intros y H1. unfold MR in H1. rewrite H0 in H1. apply (H (m y)); auto. Defined. End Measure_well_founded. #[global] Hint Resolve measure_wf : core. Section Fix_rects. Variable A: Type. Variable P: A -> Type. Variable R : A -> A -> Prop. Variable Rwf : well_founded R. Variable f: forall (x : A), (forall y: { y: A | R y x }, P (proj1_sig y)) -> P x. Lemma F_unfold x r: Fix_F_sub A R P f x r = f (fun y => Fix_F_sub A R P f (proj1_sig y) (Acc_inv r (proj2_sig y))). Proof. intros. case r; auto. Qed. (* Fix_F_sub_rect lets one prove a property of functions defined using Fix_F_sub by showing that property to be invariant over single application of the function body (f in our case). *) Lemma Fix_F_sub_rect (Q: forall x, P x -> Type) (inv: forall x: A, (forall (y: A) (H: R y x) (a: Acc R y), Q y (Fix_F_sub A R P f y a)) -> forall (a: Acc R x), Q x (f (fun y: {y: A | R y x} => Fix_F_sub A R P f (proj1_sig y) (Acc_inv a (proj2_sig y))))) : forall x a, Q _ (Fix_F_sub A R P f x a). Proof. set (R' := fun (x: A) => forall a, Q _ (Fix_F_sub A R P f x a)). cut (forall x, R' x); auto. apply (well_founded_induction_type Rwf). subst R'. simpl. intros. rewrite F_unfold; auto. Qed. (* Let's call f's second parameter its "lowers" function, since it provides it access to results for inputs with a lower measure. In preparation of lemma similar to Fix_F_sub_rect, but for Fix_sub, we first need an extra hypothesis stating that the function body has the same result for different "lowers" functions (g and h below) as long as those produce the same results for lower inputs, regardless of the lt proofs. *) Hypothesis equiv_lowers: forall x0 (g h: forall x: {y: A | R y x0}, P (proj1_sig x)), (forall x p p', g (exist (fun y: A => R y x0) x p) = h (exist (*FIXME shouldn't be needed *) (fun y => R y x0) x p')) -> f g = f h. (* From equiv_lowers, it follows that [Fix_F_sub A R P f x] applications do not not depend on the Acc proofs. *) Lemma eq_Fix_F_sub x (a a': Acc R x): Fix_F_sub A R P f x a = Fix_F_sub A R P f x a'. Proof. revert a'. pattern x, (Fix_F_sub A R P f x a). apply Fix_F_sub_rect. intros ? H **. rewrite F_unfold. apply equiv_lowers. intros. apply H. assumption. Qed. (* Finally, Fix_F_rect lets one prove a property of functions defined using Fix_F_sub by showing that property to be invariant over single application of the function body (f). *) Lemma Fix_sub_rect (Q: forall x, P x -> Type) (inv: forall (x: A) (H: forall (y: A), R y x -> Q y (Fix_sub A R Rwf P f y)) (a: Acc R x), Q x (f (fun y: {y: A | R y x} => Fix_sub A R Rwf P f (proj1_sig y)))) : forall x, Q _ (Fix_sub A R Rwf P f x). Proof. unfold Fix_sub. intros x. apply Fix_F_sub_rect. intros x0 H a. assert (forall y: A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))) as X0; auto. set (q := inv x0 X0 a). clearbody q. rewrite <- (equiv_lowers (fun y: {y: A | R y x0} => Fix_F_sub A R P f (proj1_sig y) (Rwf (proj1_sig y))) (fun y: {y: A | R y x0} => Fix_F_sub A R P f (proj1_sig y) (Acc_inv a (proj2_sig y)))); auto. intros. apply eq_Fix_F_sub. Qed. End Fix_rects. (** Tactic to fold a definition based on [Fix_measure_sub]. *) Ltac fold_sub f := match goal with | [ |- ?T ] => match T with context C [ @Fix_sub _ _ _ _ _ ?arg ] => let app := context C [ f arg ] in change app end end. rocq-9.2.0/theories/Corelib/Relations/000077500000000000000000000000001516144147600176405ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Relations/Relation_Definitions.v000066400000000000000000000047401516144147600241440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* A -> Prop. Variable R : relation. Section General_Properties_of_Relations. Definition reflexive : Prop := forall x:A, R x x. Definition transitive : Prop := forall x y z:A, R x y -> R y z -> R x z. Definition symmetric : Prop := forall x y:A, R x y -> R y x. Definition antisymmetric : Prop := forall x y:A, R x y -> R y x -> x = y. (* for compatibility with Equivalence in ../PROGRAMS/ALG/ *) Definition equiv := reflexive /\ transitive /\ symmetric. End General_Properties_of_Relations. Section Sets_of_Relations. Record preorder : Prop := { preord_refl : reflexive; preord_trans : transitive}. Record order : Prop := { ord_refl : reflexive; ord_trans : transitive; ord_antisym : antisymmetric}. Record equivalence : Prop := { equiv_refl : reflexive; equiv_trans : transitive; equiv_sym : symmetric}. Record PER : Prop := {per_sym : symmetric; per_trans : transitive}. End Sets_of_Relations. Section Relations_of_Relations. Definition inclusion (R1 R2:relation) : Prop := forall x y:A, R1 x y -> R2 x y. Definition same_relation (R1 R2:relation) : Prop := inclusion R1 R2 /\ inclusion R2 R1. Definition commut (R1 R2:relation) : Prop := forall x y:A, R1 y x -> forall z:A, R2 z y -> exists2 y' : A, R2 y' x & R1 z y'. End Relations_of_Relations. End Relation_Definition. #[global] Create HintDb sets. #[global] Hint Unfold reflexive transitive antisymmetric symmetric: sets. #[global] Hint Resolve Build_preorder Build_order Build_equivalence Build_PER preord_refl preord_trans ord_refl ord_trans ord_antisym equiv_refl equiv_trans equiv_sym per_sym per_trans: sets. #[global] Hint Unfold inclusion same_relation commut: sets. rocq-9.2.0/theories/Corelib/Setoids/000077500000000000000000000000001516144147600173125ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Setoids/Setoid.v000066400000000000000000000044651516144147600207410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Aeq y x. Proof. unfold Setoid_Theory in s. intros ; symmetry ; assumption. Defined. Definition Seq_trans A Aeq (s : Setoid_Theory A Aeq) : forall x y z:A, Aeq x y -> Aeq y z -> Aeq x z. Proof. unfold Setoid_Theory in s. intros x y z H0 H1 ; transitivity y ; assumption. Defined. (** Some tactics for manipulating Setoid Theory not officially declared as Setoid. *) Ltac trans_st x := idtac "trans_st on Setoid_Theory is OBSOLETE"; idtac "use transitivity on Equivalence instead"; match goal with | H : Setoid_Theory _ ?eqA |- ?eqA _ _ => apply (Seq_trans _ _ H) with x; auto end. Ltac sym_st := idtac "sym_st on Setoid_Theory is OBSOLETE"; idtac "use symmetry on Equivalence instead"; match goal with | H : Setoid_Theory _ ?eqA |- ?eqA _ _ => apply (Seq_sym _ _ H); auto end. Ltac refl_st := idtac "refl_st on Setoid_Theory is OBSOLETE"; idtac "use reflexivity on Equivalence instead"; match goal with | H : Setoid_Theory _ ?eqA |- ?eqA _ _ => apply (Seq_refl _ _ H); auto end. Definition gen_st : forall A : Set, Setoid_Theory _ (@eq A). Proof. constructor; congruence. Qed. rocq-9.2.0/theories/Corelib/Strings/000077500000000000000000000000001516144147600173315ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/Strings/PrimString.v000066400000000000000000000033721516144147600216230ustar00rootroot00000000000000Require Import PrimInt63. Definition char63 := int. Primitive string := #string_type. Primitive max_length : int := #string_max_length. Primitive make : int -> char63 -> string := #string_make. Primitive length : string -> int := #string_length. Primitive get : string -> int -> char63 := #string_get. Primitive sub : string -> int -> int -> string := #string_sub. Primitive cat : string -> string -> string := #string_cat. Primitive compare : string -> string -> comparison := #string_compare. Definition eqb (s1 s2 : string) := match compare s1 s2 with | Eq => true | Lt | Gt => false end. Register eqb as strings.pstring.eqb. Module Export PStringNotations. Record string_wrapper := wrap_string {string_wrap : string}. Definition id_string (s : string) : string := s. Register string as strings.pstring.type. Register string_wrapper as strings.pstring.string_wrapper. Register wrap_string as strings.pstring.wrap_string. Declare Scope pstring_scope. Delimit Scope pstring_scope with pstring. Bind Scope pstring_scope with string. String Notation string id_string id_string : pstring_scope. End PStringNotations. Record char63_wrapper := wrap_char63 { char63_wrap : char63 }. Module Export Char63Notations. Coercion char63_wrap : char63_wrapper >-> char63. Definition parse (s : string) : option char63_wrapper := if PrimInt63.eqb (length s) 1%uint63 then Some (wrap_char63 (get s 0)) else None. Definition print (i : char63_wrapper) : option string := if PrimInt63.ltb i.(char63_wrap) 256%uint63 then Some (make 1 i.(char63_wrap)) else None. Declare Scope char63_scope. Delimit Scope char63_scope with char63. Bind Scope char63_scope with char63. String Notation char63_wrapper parse print : char63_scope. End Char63Notations. rocq-9.2.0/theories/Corelib/Strings/PrimStringAxioms.v000066400000000000000000000035051516144147600230020ustar00rootroot00000000000000From Corelib Require Import BinNums PosDef IntDef ListDef. From Corelib Require Export PrimInt63 Uint63Axioms. From Corelib Require Export PrimString. Definition char63_valid (c : char63) := PrimInt63.land c 255%uint63 = c. (** * Conversion to / from lists *) Abbreviation of_nat n := (of_Z (Z.of_nat n)). Abbreviation to_nat i := (Z.to_nat (to_Z i)). Definition to_list (s : string) : list char63 := ListDef.map (fun i => get s (of_nat i)) (ListDef.seq 0 (to_nat (length s))). Fixpoint of_list (cs : list char63) : string := match cs with | nil => ""%pstring | cons c cs => cat (make 1 c) (of_list cs) end. Axiom of_to_list : forall (s : string), of_list (to_list s) = s. Axiom to_list_length : forall (s : string), Datatypes.length (to_list s) <= to_nat max_length. Axiom to_list_char63_valid : forall (s : string), ListDef.Forall char63_valid (to_list s). (** * Axioms relating string operations with list operations *) Axiom length_spec : forall (s : string), to_nat (length s) = Datatypes.length (to_list s). Axiom get_spec : forall (s : string) (i : int), get s i = ListDef.nth (to_nat i) (to_list s) 0%uint63. Axiom make_spec : forall (i : int) (c : char63), to_list (make i c) = ListDef.repeat (PrimInt63.land c 255%uint63) (Nat.min (to_nat i) (to_nat max_length)). Axiom sub_spec : forall (s : string) (off len : int), to_list (sub s off len) = ListDef.firstn (to_nat len) (ListDef.skipn (to_nat off) (to_list s)). Axiom cat_spec : forall (s1 s2 : string), to_list (cat s1 s2) = ListDef.firstn (to_nat max_length) (to_list s1 ++ to_list s2). Abbreviation char63_compare := PrimInt63.compare (only parsing). Axiom compare_spec : forall (s1 s2 : string), compare s1 s2 = ListDef.list_compare char63_compare (to_list s1) (to_list s2). rocq-9.2.0/theories/Corelib/_CoqProject000066400000000000000000000000111516144147600200230ustar00rootroot00000000000000-R . Coq rocq-9.2.0/theories/Corelib/derive/000077500000000000000000000000001516144147600171565ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/derive/Derive.v000066400000000000000000000000611516144147600205600ustar00rootroot00000000000000Declare ML Module "rocq-runtime.plugins.derive". rocq-9.2.0/theories/Corelib/dune.disabled000066400000000000000000000013731516144147600203300ustar00rootroot00000000000000; For now we use coq_dune to generate the rules here (coq.theory (name Corelib) (package rocq-core) (synopsis "Rocq's Core Library") ; Uncomment this to have dune compile native files in release mode ; (mode native) (boot) (plugins rocq-runtime.plugins.ltac rocq-runtime.plugins.tauto rocq-runtime.plugins.cc rocq-runtime.plugins.firstorder rocq-runtime.plugins.number_string_notation rocq-runtime.plugins.btauto rocq-runtime.plugins.rtauto rocq-runtime.plugins.ring rocq-runtime.plugins.nsatz rocq-runtime.plugins.zify rocq-runtime.plugins.micromega rocq-runtime.plugins.funind rocq-runtime.plugins.ssreflect rocq-runtime.plugins.derive)) (include_subdirs qualified) (documentation (package rocq-core)) rocq-9.2.0/theories/Corelib/extraction/000077500000000000000000000000001516144147600200605ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/extraction/ExtrHaskellBasic.v000066400000000000000000000014131516144147600234360ustar00rootroot00000000000000(** Extraction to Haskell : use of basic Haskell types *) Require Corelib.extraction.Extraction. Extract Inductive bool => "Prelude.Bool" [ "Prelude.True" "Prelude.False" ]. Extract Inductive option => "Prelude.Maybe" [ "Prelude.Just" "Prelude.Nothing" ]. Extract Inductive unit => "()" [ "()" ]. Extract Inductive list => "([])" [ "([])" "(:)" ]. Extract Inductive prod => "(,)" [ "(,)" ]. Extract Inductive sumbool => "Prelude.Bool" [ "Prelude.True" "Prelude.False" ]. Extract Inductive sumor => "Prelude.Maybe" [ "Prelude.Just" "Prelude.Nothing" ]. Extract Inductive sum => "Prelude.Either" [ "Prelude.Left" "Prelude.Right" ]. Extract Inlined Constant andb => "(Prelude.&&)". Extract Inlined Constant orb => "(Prelude.||)". Extract Inlined Constant negb => "Prelude.not". rocq-9.2.0/theories/Corelib/extraction/ExtrOcamlBasic.v000066400000000000000000000032771516144147600231200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool [ true false ]. Extract Inductive option => option [ Some None ]. Extract Inductive unit => unit [ "()" ]. Extract Inductive list => list [ "[]" "( :: )" ]. Extract Inductive prod => "( * )" [ "" ]. (** NB: The "" above is a hack, but produce nicer code than "(,)" *) (** Mapping sumbool to bool and sumor to option is not always nicer, but it helps when realizing stuff like [lt_eq_lt_dec] *) Extract Inductive sumbool => bool [ true false ]. Extract Inductive sumor => option [ Some None ]. (** Restore laziness of andb, orb. NB: without these Extract Constant, andb/orb would be inlined by extraction in order to have laziness, producing inelegant (if ... then ... else false) and (if ... then true else ...). *) Extract Inlined Constant andb => "(&&)". Extract Inlined Constant orb => "(||)". (* for the dependent principle of equality*) Extract Inlined Constant eq_rew_r_dep => "(fun _ _ t -> t)". rocq-9.2.0/theories/Corelib/extraction/Extraction.v000066400000000000000000000013311516144147600223650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) Require Import ssreflect ssrfun. (** A theory of boolean predicates and operators. A large part of this file is concerned with boolean reflection. Definitions and notations: is_true b == the coercion of b : bool to Prop (:= b = true). This is just input and displayed as `b''. reflect P b == the reflection inductive predicate, asserting that the logical proposition P : Prop holds iff the formula b : bool is equal to true. Lemmas asserting reflect P b are often referred to as "views". iffP, appP, sameP, rwP :: lemmas for direct manipulation of reflection views: iffP is used to prove reflection from logical equivalence, appP to compose views, and sameP and rwP to perform boolean and setoid rewriting. elimT :: coercion reflect >-> Funclass, which allows the direct application of `reflect' views to boolean assertions. decidable P <-> P is effectively decidable (:= {P} + {~ P}). contra, contraL, ... :: contraposition lemmas. altP my_viewP :: natural alternative for reflection; given lemma myviewP: reflect my_Prop my_formula, have #[#myP | not_myP#]# := altP my_viewP. generates two subgoals, in which my_formula has been replaced by true and false, resp., with new assumptions myP : my_Prop and not_myP: ~~ my_formula. Caveat: my_formula must be an APPLICATION, not a variable, constant, let-in, etc. (due to the poor behaviour of dependent index matching). boolP my_formula :: boolean disjunction, equivalent to altP (idP my_formula) but circumventing the dependent index capture issue; destructing boolP my_formula generates two subgoals with assumptions my_formula and ~~ my_formula. As with altP, my_formula must be an application. \unless C, P <-> we can assume property P when a something that holds under condition C (such as C itself). := forall G : Prop, (C -> G) -> (P -> G) -> G. This is just C \/ P or rather its impredicative encoding, whose usage better fits the above description: given a lemma UCP whose conclusion is \unless C, P we can assume P by writing: wlog hP: / P by apply/UCP; (prove C -> goal). or even apply: UCP id _ => hP if the goal is C. classically P <-> we can assume P when proving is_true b. := forall b : bool, (P -> b) -> b. This is equivalent to ~ (~ P) when P : Prop. implies P Q == wrapper variant type that coerces to P -> Q and can be used as a P -> Q view unambiguously. Useful to avoid spurious insertion of <-> views when Q is a conjunction of foralls, as in Lemma all_and2 below; conversely, avoids confusion in apply views for impredicative properties, such as \unless C, P. Also supports contrapositives. a && b == the boolean conjunction of a and b. a || b == the boolean disjunction of a and b. a ==> b == the boolean implication of b by a. ~~ a == the boolean negation of a. a (+) b == the boolean exclusive or (or sum) of a and b. #[# /\ P1 , P2 & P3 #]# == multiway logical conjunction, up to 5 terms. #[# \/ P1 , P2 | P3 #]# == multiway logical disjunction, up to 4 terms. #[#&& a, b, c & d#]# == iterated, right associative boolean conjunction with arbitrary arity. #[#|| a, b, c | d#]# == iterated, right associative boolean disjunction with arbitrary arity. #[#==> a, b, c => d#]# == iterated, right associative boolean implication with arbitrary arity. and3P, ... == specific reflection lemmas for iterated connectives. andTb, orbAC, ... == systematic names for boolean connective properties (see suffix conventions below). prop_congr == a tactic to move a boolean equality from its coerced form in Prop to the equality in bool. bool_congr == resolution tactic for blindly weeding out like terms from boolean equalities (can fail). This file provides a theory of boolean predicates and relations: pred T == the type of bool predicates (:= T -> bool). simpl_pred T == the type of simplifying bool predicates, based on the simpl_fun type from ssrfun.v. mem_pred T == a specialized form of simpl_pred for "collective" predicates (see below). rel T == the type of bool relations. := T -> pred T or T -> T -> bool. simpl_rel T == type of simplifying relations. := T -> simpl_pred T predType == the generic predicate interface, supported for for lists and sets. pred_sort == the predType >-> Type projection; pred_sort is itself a Coercion target class. Declaring a coercion to pred_sort is an alternative way of equipping a type with a predType structure, which interoperates better with coercion subtyping. This is used, e.g., for finite sets, so that finite groups inherit the membership operation by coercing to sets. {pred T} == a type convertible to pred T, but whose head constant is pred_sort. This type should be used for parameters that can be used as collective predicates (see below), as this will allow passing in directly collections that implement predType by coercion as described above, e.g., finite sets. := pred_sort (predPredType T) If P is a predicate the proposition "x satisfies P" can be written applicatively as (P x), or using an explicit connective as (x \in P); in the latter case we say that P is a "collective" predicate. We use A, B rather than P, Q for collective predicates: x \in A == x satisfies the (collective) predicate A. x \notin A == x doesn't satisfy the (collective) predicate A. The pred T type can be used as a generic predicate type for either kind, but the two kinds of predicates should not be confused. When a "generic" pred T value of one type needs to be passed as the other the following conversions should be used explicitly: SimplPred P == a (simplifying) applicative equivalent of P. mem A == an applicative equivalent of collective predicate A: mem A x simplifies to x \in A, as mem A has in fact type mem_pred T. --> In user notation collective predicates _only_ occur as arguments to mem: A only appears as (mem A). This is hidden by notation, e.g., x \in A := in_mem x (mem A) here, enum A := enum_mem (mem A) in fintype. This makes it possible to unify the various ways in which A can be interpreted as a predicate, for both pattern matching and display. Alternatively one can use the syntax for explicit simplifying predicates and relations (in the following x is bound in E): #[#pred x | E#]# == simplifying (see ssrfun) predicate x => E. #[#pred x : T | E#]# == predicate x => E, with a cast on the argument. #[#pred : T | P#]# == constant predicate P on type T. #[#pred x | E1 & E2#]# == #[#pred x | E1 && E2#]#; an x : T cast is allowed. #[#pred x in A#]# == #[#pred x | x in A#]#. #[#pred x in A | E#]# == #[#pred x | x in A & E#]#. #[#pred x in A | E1 & E2#]# == #[#pred x in A | E1 && E2#]#. #[#predU A & B#]# == union of two collective predicates A and B. #[#predI A & B#]# == intersection of collective predicates A and B. #[#predD A & B#]# == difference of collective predicates A and B. #[#predC A#]# == complement of the collective predicate A. #[#preim f of A#]# == preimage under f of the collective predicate A. predU P Q, ..., preim f P == union, etc of applicative predicates. pred_oapp A == the predicate A lifted to the option type := #[#pred x | oapp (mem A) false x#]#. pred0 == the empty predicate. predT == the total (always true) predicate. if T : predArgType, then T coerces to predT. {: T} == T cast to predArgType (e.g., {: bool * nat}). In the following, x and y are bound in E: #[#rel x y | E#]# == simplifying relation x, y => E. #[#rel x y : T | E#]# == simplifying relation with arguments cast. #[#rel x y in A & B | E#]# == #[#rel x y | #[#&& x \in A, y \in B & E#]# #]#. #[#rel x y in A & B#]# == #[#rel x y | (x \in A) && (y \in B) #]#. #[#rel x y in A | E#]# == #[#rel x y in A & A | E#]#. #[#rel x y in A#]# == #[#rel x y in A & A#]#. relU R S == union of relations R and S. relpre f R == preimage of relation R under f. xpredU, ..., xrelpre == lambda terms implementing predU, ..., etc. Explicit values of type pred T (i.e., lamdba terms) should always be used applicatively, while values of collection types implementing the predType interface, such as sequences or sets should always be used as collective predicates. Defined constants and functions of type pred T or simpl_pred T as well as the explicit simpl_pred T values described below, can generally be used either way. Note however that x \in A will not auto-simplify when A is an explicit simpl_pred T value; the generic simplification rule inE must be used (when A : pred T, the unfold_in rule can be used). Constants of type pred T with an explicit simpl_pred value do not auto-simplify when used applicatively, but can still be expanded with inE. This behavior can be controlled as follows: Let A : collective_pred T := #[#pred x | ... #]#. The collective_pred T type is just an alias for pred T, but this cast stops rewrite inE from expanding the definition of A, thus treating A into an abstract collection (unfold_in or in_collective can be used to expand manually). Let A : applicative_pred T := #[#pred x | ... #]#. This cast causes inE to turn x \in A into the applicative A x form; A will then have to be unfolded explicitly with the /A rule. This will also apply to any definition that reduces to A (e.g., Let B := A). Canonical A_app_pred := ApplicativePred A. This declaration, given after definition of A, similarly causes inE to turn x \in A into A x, but in addition allows the app_predE rule to turn A x back into x \in A; it can be used for any definition of type pred T, which makes it especially useful for ambivalent predicates as the relational transitive closure connect, that are used in both applicative and collective styles. Purely for aesthetics, we provide a subtype of collective predicates: qualifier q T == a pred T pretty-printing wrapper. An A : qualifier q T coerces to pred_sort and thus behaves as a collective predicate, but x \in A and x \notin A are displayed as: x \is A and x \isn't A when q = 0, x \is a A and x \isn't a A when q = 1, x \is an A and x \isn't an A when q = 2, respectively. #[#qualify x | P#]# := Qualifier 0 (fun x => P), constructor for the above. #[#qualify x : T | P#]#, #[#qualify a x | P#]#, #[#qualify an X | P#]#, etc. variants of the above with type constraints and different values of q. We provide an internal interface to support attaching properties (such as being multiplicative) to predicates: pred_key p == phantom type that will serve as a support for properties to be attached to p : {pred _}; instances should be created with Fact/Qed so as to be opaque. KeyedPred k_p == an instance of the interface structure that attaches (k_p : pred_key P) to P; the structure projection is a coercion to pred_sort. KeyedQualifier k_q == an instance of the interface structure that attaches (k_q : pred_key q) to (q : qualifier n T). DefaultPredKey p == a default value for pred_key p; the vernacular command Import DefaultKeying attaches this key to all predicates that are not explicitly keyed. Keys can be used to attach properties to predicates, qualifiers and generic nouns in a way that allows them to be used transparently. The key projection of a predicate property structure such as unsignedPred should be a pred_key, not a pred, and corresponding lemmas will have the form Lemma rpredN R S (oppS : @opprPred R S) (kS : keyed_pred oppS) : {mono -%%R: x / x \in kS}. Because x \in kS will be displayed as x \in S (or x \is S, etc), the canonical instance of opprPred will not normally be exposed (it will also be erased by /= simplification). In addition each predicate structure should have a DefaultPredKey Canonical instance that simply issues the property as a proof obligation (which can be caught by the Prop-irrelevant feature of the ssreflect plugin). Some properties of predicates and relations: A =i B <-> A and B are extensionally equivalent. {subset A <= B} <-> A is a (collective) subpredicate of B. subpred P Q <-> P is an (applicative) subpredicate or Q. subrel R S <-> R is a subrelation of S. In the following R is in rel T: reflexive R <-> R is reflexive. irreflexive R <-> R is irreflexive. symmetric R <-> R (in rel T) is symmetric (equation). pre_symmetric R <-> R is symmetric (implication). antisymmetric R <-> R is antisymmetric. total R <-> R is total. transitive R <-> R is transitive. left_transitive R <-> R is a congruence on its left hand side. right_transitive R <-> R is a congruence on its right hand side. equivalence_rel R <-> R is an equivalence relation. Localization of (Prop) predicates; if P1 is convertible to forall x, Qx, P2 to forall x y, Qxy and P3 to forall x y z, Qxyz : {for y, P1} <-> Qx{y / x}. {in A, P1} <-> forall x, x \in A -> Qx. {in A1 & A2, P2} <-> forall x y, x \in A1 -> y \in A2 -> Qxy. {in A &, P2} <-> forall x y, x \in A -> y \in A -> Qxy. {in A1 & A2 & A3, Q3} <-> forall x y z, x \in A1 -> y \in A2 -> z \in A3 -> Qxyz. {in A1 & A2 &, Q3} := {in A1 & A2 & A2, Q3}. {in A1 && A3, Q3} := {in A1 & A1 & A3, Q3}. {in A &&, Q3} := {in A & A & A, Q3}. {in A, bijective f} <-> f has a right inverse in A. {on C, P1} <-> forall x, (f x) \in C -> Qx when P1 is also convertible to Pf f, e.g., {on C, involutive f}. {on C &, P2} == forall x y, f x \in C -> f y \in C -> Qxy when P2 is also convertible to Pf f, e.g., {on C &, injective f}. {on C, P1' & g} == forall x, (f x) \in cd -> Qx when P1' is convertible to Pf f and P1' g is convertible to forall x, Qx, e.g., {on C, cancel f & g}. {on C, bijective f} == f has a right inverse on C. This file extends the lemma name suffix conventions of ssrfun as follows: A -- associativity, as in andbA : associative andb. AC -- right commutativity. ACA -- self-interchange (inner commutativity), e.g., orbACA : (a || b) || (c || d) = (a || c) || (b || d). b -- a boolean argument, as in andbb : idempotent_op andb. C -- commutativity, as in andbC : commutative andb, or predicate complement, as in predC. CA -- left commutativity. D -- predicate difference, as in predD. E -- elimination, as in negbFE : ~~ b = false -> b. F or f -- boolean false, as in andbF : b && false = false. I -- left/right injectivity, as in addbI : right_injective addb, or predicate intersection, as in predI. l -- a left-hand operation, as andb_orl : left_distributive andb orb. N or n -- boolean negation, as in andbN : a && (~~ a) = false. P -- a characteristic property, often a reflection lemma, as in andP : reflect (a /\ b) (a && b). r -- a right-hand operation, as orb_andr : right_distributive orb andb. T or t -- boolean truth, as in andbT: right_id true andb. U -- predicate union, as in predU. W -- weakening, as in in1W : (forall x, P) -> {in D, forall x, P}. **) Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Abbreviation reflect := Datatypes.reflect. Abbreviation ReflectT := Datatypes.ReflectT. Abbreviation ReflectF := Datatypes.ReflectF. Reserved Notation "~~ b" (at level 35, right associativity). Reserved Notation "b ==> c" (at level 55, right associativity). Reserved Notation "b1 (+) b2" (at level 50, left associativity). Reserved Notation "x \in A" (at level 70, no associativity, format "'[hv' x '/ ' \in A ']'"). Reserved Notation "x \notin A" (at level 70, no associativity, format "'[hv' x '/ ' \notin A ']'"). Reserved Notation "x \is A" (at level 70, no associativity, format "'[hv' x '/ ' \is A ']'"). Reserved Notation "x \isn't A" (at level 70, no associativity, format "'[hv' x '/ ' \isn't A ']'"). Reserved Notation "x \is 'a' A" (at level 70, no associativity, format "'[hv' x '/ ' \is 'a' A ']'"). Reserved Notation "x \isn't 'a' A" (at level 70, no associativity, format "'[hv' x '/ ' \isn't 'a' A ']'"). Reserved Notation "x \is 'an' A" (at level 70, no associativity, format "'[hv' x '/ ' \is 'an' A ']'"). Reserved Notation "x \isn't 'an' A" (at level 70, no associativity, format "'[hv' x '/ ' \isn't 'an' A ']'"). Reserved Notation "p1 =i p2" (at level 70, no associativity, format "'[hv' p1 '/ ' =i p2 ']'"). Reserved Notation "{ 'subset' A <= B }" (at level 0, A, B at level 69, format "'[hv' { 'subset' A '/ ' <= B } ']'"). Reserved Notation "{ : T }" (at level 0, format "{ : T }"). Reserved Notation "{ 'pred' T }" (at level 0, format "{ 'pred' T }"). Reserved Notation "[ 'predType' 'of' T ]" (at level 0, format "[ 'predType' 'of' T ]"). Reserved Notation "[ 'pred' : T | E ]" (at level 0, format "'[hv' [ 'pred' : T | '/ ' E ] ']'"). Reserved Notation "[ 'pred' x | E ]" (at level 0, x name, format "'[hv' [ 'pred' x | '/ ' E ] ']'"). Reserved Notation "[ 'pred' x : T | E ]" (at level 0, x name, format "'[hv' [ 'pred' x : T | '/ ' E ] ']'"). Reserved Notation "[ 'pred' x | E1 & E2 ]" (at level 0, x name, format "'[hv' [ 'pred' x | '/ ' E1 & '/ ' E2 ] ']'"). Reserved Notation "[ 'pred' x : T | E1 & E2 ]" (at level 0, x name, format "'[hv' [ 'pred' x : T | '/ ' E1 & E2 ] ']'"). Reserved Notation "[ 'pred' x 'in' A ]" (at level 0, x name, format "'[hv' [ 'pred' x 'in' A ] ']'"). Reserved Notation "[ 'pred' x 'in' A | E ]" (at level 0, x name, format "'[hv' [ 'pred' x 'in' A | '/ ' E ] ']'"). Reserved Notation "[ 'pred' x 'in' A | E1 & E2 ]" (at level 0, x name, format "'[hv' [ 'pred' x 'in' A | '/ ' E1 & '/ ' E2 ] ']'"). Reserved Notation "[ 'qualify' x | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' x | '/ ' P ] ']'"). Reserved Notation "[ 'qualify' x : T | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' x : T | '/ ' P ] ']'"). Reserved Notation "[ 'qualify' 'a' x | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' 'a' x | '/ ' P ] ']'"). Reserved Notation "[ 'qualify' 'a' x : T | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' 'a' x : T | '/ ' P ] ']'"). Reserved Notation "[ 'qualify' 'an' x | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' 'an' x | '/ ' P ] ']'"). Reserved Notation "[ 'qualify' 'an' x : T | P ]" (at level 0, x at level 99, format "'[hv' [ 'qualify' 'an' x : T | '/ ' P ] ']'"). Reserved Notation "[ 'rel' x y | E ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y | '/ ' E ] ']'"). Reserved Notation "[ 'rel' x y : T | E ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y : T | '/ ' E ] ']'"). Reserved Notation "[ 'rel' x y 'in' A & B | E ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y 'in' A & B | '/ ' E ] ']'"). Reserved Notation "[ 'rel' x y 'in' A & B ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y 'in' A & B ] ']'"). Reserved Notation "[ 'rel' x y 'in' A | E ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y 'in' A | '/ ' E ] ']'"). Reserved Notation "[ 'rel' x y 'in' A ]" (at level 0, x name, y name, format "'[hv' [ 'rel' x y 'in' A ] ']'"). Reserved Notation "[ 'mem' A ]" (at level 0, format "[ 'mem' A ]"). Reserved Notation "[ 'predI' A & B ]" (at level 0, format "[ 'predI' A & B ]"). Reserved Notation "[ 'predU' A & B ]" (at level 0, format "[ 'predU' A & B ]"). Reserved Notation "[ 'predD' A & B ]" (at level 0, format "[ 'predD' A & B ]"). Reserved Notation "[ 'predC' A ]" (at level 0, format "[ 'predC' A ]"). Reserved Notation "[ 'preim' f 'of' A ]" (at level 0, format "[ 'preim' f 'of' A ]"). Reserved Notation "\unless C , P" (at level 200, C at level 100, format "'[hv' \unless C , '/ ' P ']'"). Reserved Notation "{ 'for' x , P }" (at level 0, format "'[hv' { 'for' x , '/ ' P } ']'"). Reserved Notation "{ 'in' d , P }" (at level 0, format "'[hv' { 'in' d , '/ ' P } ']'"). Reserved Notation "{ 'in' d1 & d2 , P }" (at level 0, format "'[hv' { 'in' d1 & d2 , '/ ' P } ']'"). Reserved Notation "{ 'in' d & , P }" (at level 0, format "'[hv' { 'in' d & , '/ ' P } ']'"). Reserved Notation "{ 'in' d1 & d2 & d3 , P }" (at level 0, format "'[hv' { 'in' d1 & d2 & d3 , '/ ' P } ']'"). Reserved Notation "{ 'in' d1 & & d3 , P }" (at level 0, format "'[hv' { 'in' d1 & & d3 , '/ ' P } ']'"). Reserved Notation "{ 'in' d1 & d2 & , P }" (at level 0, format "'[hv' { 'in' d1 & d2 & , '/ ' P } ']'"). Reserved Notation "{ 'in' d & & , P }" (at level 0, format "'[hv' { 'in' d & & , '/ ' P } ']'"). Reserved Notation "{ 'on' cd , P }" (at level 0, format "'[hv' { 'on' cd , '/ ' P } ']'"). Reserved Notation "{ 'on' cd & , P }" (at level 0, format "'[hv' { 'on' cd & , '/ ' P } ']'"). Reserved Notation "{ 'on' cd , P & g }" (at level 0, g at level 8, format "'[hv' { 'on' cd , '/ ' P & g } ']'"). Reserved Notation "{ 'in' d , 'bijective' f }" (at level 0, f at level 8, format "'[hv' { 'in' d , '/ ' 'bijective' f } ']'"). Reserved Notation "{ 'on' cd , 'bijective' f }" (at level 0, f at level 8, format "'[hv' { 'on' cd , '/ ' 'bijective' f } ']'"). (** We introduce a number of n-ary "list-style" notations that share a common format, namely #[#op arg1, arg2, ... last_separator last_arg#]# This usually denotes a right-associative applications of op, e.g., #[#&& a, b, c & d#]# denotes a && (b && (c && d)) The last_separator must be a non-operator token. Here we use &, | or =>; our default is &, but we try to match the intended meaning of op. The separator is a workaround for limitations of the parsing engine; the same limitations mean the separator cannot be omitted even when last_arg can. The Abbreviation declarations are complicated by the separate treatment for some fixed arities (binary for bool operators, and all arities for Prop operators). We also use the square brackets in comprehension-style notations #[#type var separator expr#]# where "type" is the type of the comprehension (e.g., pred) and "separator" is | or => . It is important that in other notations a leading square bracket #[# is always followed by an operator symbol or a fixed identifier. **) Reserved Notation "[ /\ P1 & P2 ]" (at level 0). Reserved Notation "[ /\ P1 , P2 & P3 ]" (at level 0, format "'[hv' [ /\ '[' P1 , '/' P2 ']' '/ ' & P3 ] ']'"). Reserved Notation "[ /\ P1 , P2 , P3 & P4 ]" (at level 0, format "'[hv' [ /\ '[' P1 , '/' P2 , '/' P3 ']' '/ ' & P4 ] ']'"). Reserved Notation "[ /\ P1 , P2 , P3 , P4 & P5 ]" (at level 0, format "'[hv' [ /\ '[' P1 , '/' P2 , '/' P3 , '/' P4 ']' '/ ' & P5 ] ']'"). Reserved Notation "[ \/ P1 | P2 ]" (at level 0). Reserved Notation "[ \/ P1 , P2 | P3 ]" (at level 0, format "'[hv' [ \/ '[' P1 , '/' P2 ']' '/ ' | P3 ] ']'"). Reserved Notation "[ \/ P1 , P2 , P3 | P4 ]" (at level 0, format "'[hv' [ \/ '[' P1 , '/' P2 , '/' P3 ']' '/ ' | P4 ] ']'"). Reserved Notation "[ && b1 & c ]" (at level 0). Reserved Notation "[ && b1 , b2 , .. , bn & c ]" (at level 0, format "'[hv' [ && '[' b1 , '/' b2 , '/' .. , '/' bn ']' '/ ' & c ] ']'"). Reserved Notation "[ || b1 | c ]" (at level 0). Reserved Notation "[ || b1 , b2 , .. , bn | c ]" (at level 0, format "'[hv' [ || '[' b1 , '/' b2 , '/' .. , '/' bn ']' '/ ' | c ] ']'"). Reserved Notation "[ ==> b1 => c ]" (at level 0). Reserved Notation "[ ==> b1 , b2 , .. , bn => c ]" (at level 0, format "'[hv' [ ==> '[' b1 , '/' b2 , '/' .. , '/' bn ']' '/' => c ] ']'"). (** Shorter delimiter **) Delimit Scope bool_scope with B. Open Scope bool_scope. (** An alternative to xorb that behaves somewhat better wrt simplification. **) Definition addb b := if b then negb else id. (** Abbreviation for && and || is declared in Init.Datatypes. **) Notation "~~ b" := (negb b) : bool_scope. Notation "b ==> c" := (implb b c) : bool_scope. Notation "b1 (+) b2" := (addb b1 b2) : bool_scope. (** Constant is_true b := b = true is defined in Init.Datatypes. **) Coercion is_true : bool >-> Sortclass. (* Prop *) Lemma prop_congr : forall b b' : bool, b = b' -> b = b' :> Prop. Proof. by move=> b b' ->. Qed. Ltac prop_congr := apply: prop_congr. (** Lemmas for trivial. **) Lemma is_true_true : true. Proof. by []. Qed. Lemma not_false_is_true : ~ false. Proof. by []. Qed. Lemma is_true_locked_true : locked true. Proof. by unlock. Qed. #[global] Hint Resolve is_true_true not_false_is_true is_true_locked_true : core. (** Shorter names. **) Definition isT := is_true_true. Definition notF := not_false_is_true. (** Negation lemmas. **) (** We generally take NEGATION as the standard form of a false condition: negative boolean hypotheses should be of the form ~~ b, rather than ~ b or b = false, as much as possible. **) Lemma negbT b : b = false -> ~~ b. Proof. by case: b. Qed. Lemma negbTE b : ~~ b -> b = false. Proof. by case: b. Qed. Lemma negbF b : (b : bool) -> ~~ b = false. Proof. by case: b. Qed. Lemma negbFE b : ~~ b = false -> b. Proof. by case: b. Qed. Lemma negbK : involutive negb. Proof. by case. Qed. Lemma negbNE b : ~~ ~~ b -> b. Proof. by case: b. Qed. Lemma negb_inj : injective negb. Proof. exact: can_inj negbK. Qed. Lemma negbLR b c : b = ~~ c -> ~~ b = c. Proof. exact: canLR negbK. Qed. Lemma negbRL b c : ~~ b = c -> b = ~~ c. Proof. exact: canRL negbK. Qed. Lemma contra (c b : bool) : (c -> b) -> ~~ b -> ~~ c. Proof. by case: b => //; case: c. Qed. Definition contraNN := contra. Lemma contraL (c b : bool) : (c -> ~~ b) -> b -> ~~ c. Proof. by case: b => //; case: c. Qed. Definition contraTN := contraL. Lemma contraR (c b : bool) : (~~ c -> b) -> ~~ b -> c. Proof. by case: b => //; case: c. Qed. Definition contraNT := contraR. Lemma contraLR (c b : bool) : (~~ c -> ~~ b) -> b -> c. Proof. by case: b => //; case: c. Qed. Definition contraTT := contraLR. Lemma contraT b : (~~ b -> false) -> b. Proof. by case: b => // ->. Qed. Lemma wlog_neg b : (~~ b -> b) -> b. Proof. by case: b => // ->. Qed. Lemma contraFT (c b : bool) : (~~ c -> b) -> b = false -> c. Proof. by move/contraR=> notb_c /negbT. Qed. Lemma contraFN (c b : bool) : (c -> b) -> b = false -> ~~ c. Proof. by move/contra=> notb_notc /negbT. Qed. Lemma contraTF (c b : bool) : (c -> ~~ b) -> b -> c = false. Proof. by move/contraL=> b_notc /b_notc/negbTE. Qed. Lemma contraNF (c b : bool) : (c -> b) -> ~~ b -> c = false. Proof. by move/contra=> notb_notc /notb_notc/negbTE. Qed. Lemma contraFF (c b : bool) : (c -> b) -> b = false -> c = false. Proof. by move/contraFN=> bF_notc /bF_notc/negbTE. Qed. (* additional contra lemmas involving [P,Q : Prop] *) Lemma contra_not (P Q : Prop) : (Q -> P) -> (~ P -> ~ Q). Proof. by auto. Qed. Lemma contraPnot (P Q : Prop) : (Q -> ~ P) -> (P -> ~ Q). Proof. by auto. Qed. Lemma contraTnot (b : bool) (P : Prop) : (P -> ~~ b) -> (b -> ~ P). Proof. by case: b; auto. Qed. Lemma contraNnot (P : Prop) (b : bool) : (P -> b) -> (~~ b -> ~ P). Proof. rewrite -{1}[b]negbK; exact: contraTnot. Qed. Lemma contraPT (P : Prop) (b : bool) : (~~ b -> ~ P) -> P -> b. Proof. by case: b => //= /(_ isT) nP /nP. Qed. Lemma contra_notT (P : Prop) (b : bool) : (~~ b -> P) -> ~ P -> b. Proof. by case: b => //= /(_ isT) HP /(_ HP). Qed. Lemma contra_notN (P : Prop) (b : bool) : (b -> P) -> ~ P -> ~~ b. Proof. rewrite -{1}[b]negbK; exact: contra_notT. Qed. Lemma contraPN (P : Prop) (b : bool) : (b -> ~ P) -> (P -> ~~ b). Proof. by case: b => //=; move/(_ isT) => HP /HP. Qed. Lemma contraFnot (P : Prop) (b : bool) : (P -> b) -> b = false -> ~ P. Proof. by case: b => //; auto. Qed. Lemma contraPF (P : Prop) (b : bool) : (b -> ~ P) -> P -> b = false. Proof. by case: b => // /(_ isT). Qed. Lemma contra_notF (P : Prop) (b : bool) : (b -> P) -> ~ P -> b = false. Proof. by case: b => // /(_ isT). Qed. (** Coercion of sum-style datatypes into bool, which makes it possible to use ssr's boolean if rather than Rocq's "generic" if. **) Coercion isSome T (u : option T) := if u is Some _ then true else false. Coercion is_inl A B (u : A + B) := if u is inl _ then true else false. Coercion is_left A B (u : {A} + {B}) := if u is left _ then true else false. Coercion is_inleft A B (u : A + {B}) := if u is inleft _ then true else false. Prenex Implicits isSome is_inl is_left is_inleft. Definition decidable P := {P} + {~ P}. (** Lemmas for ifs with large conditions, which allow reasoning about the condition without repeating it inside the proof (the latter IS preferable when the condition is short). Usage : if the goal contains (if cond then ...) = ... case: ifP => Hcond. generates two subgoal, with the assumption Hcond : cond = true/false Rewrite if_same eliminates redundant ifs Rewrite (fun_if f) moves a function f inside an if Rewrite if_arg moves an argument inside a function-valued if **) Section BoolIf. Variables (A B : Type) (x : A) (f : A -> B) (b : bool) (vT vF : A). Variant if_spec (not_b : Prop) : bool -> A -> Set := | IfSpecTrue of b : if_spec not_b true vT | IfSpecFalse of not_b : if_spec not_b false vF. Lemma ifP : if_spec (b = false) b (if b then vT else vF). Proof. by case def_b: b; constructor. Qed. Lemma ifPn : if_spec (~~ b) b (if b then vT else vF). Proof. by case def_b: b; constructor; rewrite ?def_b. Qed. Lemma ifT : b -> (if b then vT else vF) = vT. Proof. by move->. Qed. Lemma ifF : b = false -> (if b then vT else vF) = vF. Proof. by move->. Qed. Lemma ifN : ~~ b -> (if b then vT else vF) = vF. Proof. by move/negbTE->. Qed. Lemma if_same : (if b then vT else vT) = vT. Proof. by case b. Qed. Lemma if_neg : (if ~~ b then vT else vF) = if b then vF else vT. Proof. by case b. Qed. Lemma fun_if : f (if b then vT else vF) = if b then f vT else f vF. Proof. by case b. Qed. Lemma if_arg (fT fF : A -> B) : (if b then fT else fF) x = if b then fT x else fF x. Proof. by case b. Qed. (** Turning a boolean "if" form into an application. **) Definition if_expr := if b then vT else vF. Lemma ifE : (if b then vT else vF) = if_expr. Proof. by []. Qed. End BoolIf. (** Core (internal) reflection lemmas, used for the three kinds of views. **) Section ReflectCore. Variables (P Q : Prop) (b c : bool). Hypothesis Hb : reflect P b. Lemma introNTF : (if c then ~ P else P) -> ~~ b = c. Proof. by case c; case Hb. Qed. Lemma introTF : (if c then P else ~ P) -> b = c. Proof. by case c; case Hb. Qed. Lemma elimNTF : ~~ b = c -> if c then ~ P else P. Proof. by move <-; case Hb. Qed. Lemma elimTF : b = c -> if c then P else ~ P. Proof. by move <-; case Hb. Qed. Lemma equivPif : (Q -> P) -> (P -> Q) -> if b then Q else ~ Q. Proof. by case Hb; auto. Qed. Lemma xorPif : Q \/ P -> ~ (Q /\ P) -> if b then ~ Q else Q. Proof. by case Hb => [? _ H ? | ? H _]; case: H. Qed. End ReflectCore. (** Internal negated reflection lemmas **) Section ReflectNegCore. Variables (P Q : Prop) (b c : bool). Hypothesis Hb : reflect P (~~ b). Lemma introTFn : (if c then ~ P else P) -> b = c. Proof. by move/(introNTF Hb) <-; case b. Qed. Lemma elimTFn : b = c -> if c then ~ P else P. Proof. by move <-; apply: (elimNTF Hb); case b. Qed. Lemma equivPifn : (Q -> P) -> (P -> Q) -> if b then ~ Q else Q. Proof. by rewrite -if_neg; apply: equivPif. Qed. Lemma xorPifn : Q \/ P -> ~ (Q /\ P) -> if b then Q else ~ Q. Proof. by rewrite -if_neg; apply: xorPif. Qed. End ReflectNegCore. (** User-oriented reflection lemmas **) Section Reflect. Variables (P Q : Prop) (b b' c : bool). Hypotheses (Pb : reflect P b) (Pb' : reflect P (~~ b')). Lemma introT : P -> b. Proof. exact: introTF true _. Qed. Lemma introF : ~ P -> b = false. Proof. exact: introTF false _. Qed. Lemma introN : ~ P -> ~~ b. Proof. exact: introNTF true _. Qed. Lemma introNf : P -> ~~ b = false. Proof. exact: introNTF false _. Qed. Lemma introTn : ~ P -> b'. Proof. exact: introTFn true _. Qed. Lemma introFn : P -> b' = false. Proof. exact: introTFn false _. Qed. Lemma elimT : b -> P. Proof. exact: elimTF true _. Qed. Lemma elimF : b = false -> ~ P. Proof. exact: elimTF false _. Qed. Lemma elimN : ~~ b -> ~P. Proof. exact: elimNTF true _. Qed. Lemma elimNf : ~~ b = false -> P. Proof. exact: elimNTF false _. Qed. Lemma elimTn : b' -> ~ P. Proof. exact: elimTFn true _. Qed. Lemma elimFn : b' = false -> P. Proof. exact: elimTFn false _. Qed. Lemma introP : (b -> Q) -> (~~ b -> ~ Q) -> reflect Q b. Proof. by case b; constructor; auto. Qed. Lemma iffP : (P -> Q) -> (Q -> P) -> reflect Q b. Proof. by case: Pb; constructor; auto. Qed. Lemma equivP : (P <-> Q) -> reflect Q b. Proof. by case; apply: iffP. Qed. Lemma sumboolP (decQ : decidable Q) : reflect Q decQ. Proof. by case: decQ; constructor. Qed. Lemma appP : reflect Q b -> P -> Q. Proof. by move=> Qb; move/introT; case: Qb. Qed. Lemma sameP : reflect P c -> b = c. Proof. by case; [apply: introT | apply: introF]. Qed. Lemma decPcases : if b then P else ~ P. Proof. by case Pb. Qed. Definition decP : decidable P. by case: b decPcases; [left | right]. Defined. Lemma rwP : P <-> b. Proof. by split; [apply: introT | apply: elimT]. Qed. Lemma rwP2 : reflect Q b -> (P <-> Q). Proof. by move=> Qb; split=> ?; [apply: appP | apply: elimT; case: Qb]. Qed. (** Predicate family to reflect excluded middle in bool. **) Variant alt_spec : bool -> Type := | AltTrue of P : alt_spec true | AltFalse of ~~ b : alt_spec false. Lemma altP : alt_spec b. Proof. by case def_b: b / Pb; constructor; rewrite ?def_b. Qed. Lemma eqbLR (b1 b2 : bool) : b1 = b2 -> b1 -> b2. Proof. by move->. Qed. Lemma eqbRL (b1 b2 : bool) : b1 = b2 -> b2 -> b1. Proof. by move->. Qed. End Reflect. Hint View for move/ elimTF|3 elimNTF|3 elimTFn|3 introT|2 introTn|2 introN|2. Hint View for apply/ introTF|3 introNTF|3 introTFn|3 elimT|2 elimTn|2 elimN|2. Hint View for apply// equivPif|3 xorPif|3 equivPifn|3 xorPifn|3. (** Allow the direct application of a reflection lemma to a boolean assertion. **) Coercion elimT : reflect >-> Funclass. #[universes(template)] Variant implies P Q := Implies of P -> Q. Lemma impliesP P Q : implies P Q -> P -> Q. Proof. by case. Qed. Lemma impliesPn (P Q : Prop) : implies P Q -> ~ Q -> ~ P. Proof. by case=> iP ? /iP. Qed. Coercion impliesP : implies >-> Funclass. Hint View for move/ impliesPn|2 impliesP|2. Hint View for apply/ impliesPn|2 impliesP|2. (** Impredicative or, which can emulate a classical not-implies. **) Definition unless condition property : Prop := forall goal : Prop, (condition -> goal) -> (property -> goal) -> goal. Notation "\unless C , P" := (unless C P) : type_scope. Lemma unlessL C P : implies C (\unless C, P). Proof. by split=> hC G /(_ hC). Qed. Lemma unlessR C P : implies P (\unless C, P). Proof. by split=> hP G _ /(_ hP). Qed. Lemma unless_sym C P : implies (\unless C, P) (\unless P, C). Proof. by split; apply; [apply/unlessR | apply/unlessL]. Qed. Lemma unlessP (C P : Prop) : (\unless C, P) <-> C \/ P. Proof. by split=> [|[/unlessL | /unlessR]]; apply; [left | right]. Qed. Lemma bind_unless C P {Q} : implies (\unless C, P) (\unless (\unless C, Q), P). Proof. by split; apply=> [hC|hP]; [apply/unlessL/unlessL | apply/unlessR]. Qed. Lemma unless_contra b C : implies (~~ b -> C) (\unless C, b). Proof. by split; case: b => [_ | hC]; [apply/unlessR | apply/unlessL/hC]. Qed. (** Classical reasoning becomes directly accessible for any bool subgoal. Note that we cannot use "unless" here for lack of universe polymorphism. **) Definition classically P : Prop := forall b : bool, (P -> b) -> b. Lemma classicP (P : Prop) : classically P <-> ~ ~ P. Proof. split=> [cP nP | nnP [] // nP]; last by case nnP; move/nP. by have: P -> false; [move/nP | move/cP]. Qed. Lemma classicW P : P -> classically P. Proof. by move=> hP _ ->. Qed. Lemma classic_bind P Q : (P -> classically Q) -> classically P -> classically Q. Proof. by move=> iPQ cP b /iPQ-/cP. Qed. Lemma classic_EM P : classically (decidable P). Proof. by case=> // undecP; apply/undecP; right=> notP; apply/notF/undecP; left. Qed. Lemma classic_pick T P : classically ({x : T | P x} + (forall x, ~ P x)). Proof. case=> // undecP; apply/undecP; right=> x Px. by apply/notF/undecP; left; exists x. Qed. Lemma classic_imply P Q : (P -> classically Q) -> classically (P -> Q). Proof. move=> iPQ []// notPQ; apply/notPQ=> /iPQ-cQ. by case: notF; apply: cQ => hQ; apply: notPQ. Qed. Lemma classic_sigW T (P : T -> Prop) : classically (exists x, P x) <-> classically ({x | P x}). Proof. by split; apply: classic_bind => -[x Px]; apply/classicW; exists x. Qed. Lemma classic_ex T (P : T -> Prop) : ~ (forall x, ~ P x) -> classically (exists x, P x). Proof. move=> NfNP; apply/classicP => exPF; apply: NfNP => x Px. by apply: exPF; exists x. Qed. (** List notations for wider connectives; the Prop connectives have a fixed width so as to avoid iterated destruction (we go up to width 5 for /\, and width 4 for or). The bool connectives have arbitrary widths, but denote expressions that associate to the RIGHT. This is consistent with the right associativity of list expressions and thus more convenient in most proofs. **) Inductive and3 (P1 P2 P3 : Prop) : Prop := And3 of P1 & P2 & P3. Inductive and4 (P1 P2 P3 P4 : Prop) : Prop := And4 of P1 & P2 & P3 & P4. Inductive and5 (P1 P2 P3 P4 P5 : Prop) : Prop := And5 of P1 & P2 & P3 & P4 & P5. Inductive or3 (P1 P2 P3 : Prop) : Prop := Or31 of P1 | Or32 of P2 | Or33 of P3. Inductive or4 (P1 P2 P3 P4 : Prop) : Prop := Or41 of P1 | Or42 of P2 | Or43 of P3 | Or44 of P4. Notation "[ /\ P1 & P2 ]" := (and P1 P2) (only parsing) : type_scope. Notation "[ /\ P1 , P2 & P3 ]" := (and3 P1 P2 P3) : type_scope. Notation "[ /\ P1 , P2 , P3 & P4 ]" := (and4 P1 P2 P3 P4) : type_scope. Notation "[ /\ P1 , P2 , P3 , P4 & P5 ]" := (and5 P1 P2 P3 P4 P5) : type_scope. Notation "[ \/ P1 | P2 ]" := (or P1 P2) (only parsing) : type_scope. Notation "[ \/ P1 , P2 | P3 ]" := (or3 P1 P2 P3) : type_scope. Notation "[ \/ P1 , P2 , P3 | P4 ]" := (or4 P1 P2 P3 P4) : type_scope. Notation "[ && b1 & c ]" := (b1 && c) (only parsing) : bool_scope. Notation "[ && b1 , b2 , .. , bn & c ]" := (b1 && (b2 && .. (bn && c) .. )) : bool_scope. Notation "[ || b1 | c ]" := (b1 || c) (only parsing) : bool_scope. Notation "[ || b1 , b2 , .. , bn | c ]" := (b1 || (b2 || .. (bn || c) .. )) : bool_scope. Notation "[ ==> b1 , b2 , .. , bn => c ]" := (b1 ==> (b2 ==> .. (bn ==> c) .. )) : bool_scope. Notation "[ ==> b1 => c ]" := (b1 ==> c) (only parsing) : bool_scope. Section AllAnd. Variables (T : Type) (P1 P2 P3 P4 P5 : T -> Prop). Local Abbreviation a P := (forall x, P x). Lemma all_and2 : implies (forall x, [/\ P1 x & P2 x]) [/\ a P1 & a P2]. Proof. by split=> haveP; split=> x; case: (haveP x). Qed. Lemma all_and3 : implies (forall x, [/\ P1 x, P2 x & P3 x]) [/\ a P1, a P2 & a P3]. Proof. by split=> haveP; split=> x; case: (haveP x). Qed. Lemma all_and4 : implies (forall x, [/\ P1 x, P2 x, P3 x & P4 x]) [/\ a P1, a P2, a P3 & a P4]. Proof. by split=> haveP; split=> x; case: (haveP x). Qed. Lemma all_and5 : implies (forall x, [/\ P1 x, P2 x, P3 x, P4 x & P5 x]) [/\ a P1, a P2, a P3, a P4 & a P5]. Proof. by split=> haveP; split=> x; case: (haveP x). Qed. End AllAnd. Arguments all_and2 {T P1 P2}. Arguments all_and3 {T P1 P2 P3}. Arguments all_and4 {T P1 P2 P3 P4}. Arguments all_and5 {T P1 P2 P3 P4 P5}. Lemma pair_andP P Q : P /\ Q <-> P * Q. Proof. by split; case. Qed. Section ReflectConnectives. Variable b1 b2 b3 b4 b5 : bool. Lemma idP : reflect b1 b1. Proof. by case b1; constructor. Qed. Lemma boolP : alt_spec b1 b1 b1. Proof. exact: (altP idP). Qed. (* Left-to-right reflection of ~~b1 to (b1 = false), no-op otherwise. *) Lemma idPn : reflect (~~ b1) (~~ b1). Proof. by case b1; constructor. Qed. Lemma negP : reflect (~ b1) (~~ b1). Proof. by case b1; constructor; auto. Qed. Lemma negPn : reflect b1 (~~ ~~ b1). Proof. by case b1; constructor. Qed. (* Right-to-left reflection, no-op otherwise. C.f., https://github.com/math-comp/math-comp/issues/284 To change `b1 = false` into `~~ b1`, use `apply/negbTE` or `apply/idPn` (goal) or `move/negbT` or `move/idPn` (hypothesis). *) Lemma negPf : reflect (b1 = false) (~~ b1). Proof. by case b1; constructor. Qed. Lemma andP : reflect (b1 /\ b2) (b1 && b2). Proof. by case b1; case b2; constructor=> //; case. Qed. Lemma and3P : reflect [/\ b1, b2 & b3] [&& b1, b2 & b3]. Proof. by case b1; case b2; case b3; constructor; try by case. Qed. Lemma and4P : reflect [/\ b1, b2, b3 & b4] [&& b1, b2, b3 & b4]. Proof. by case b1; case b2; case b3; case b4; constructor; try by case. Qed. Lemma and5P : reflect [/\ b1, b2, b3, b4 & b5] [&& b1, b2, b3, b4 & b5]. Proof. by case b1; case b2; case b3; case b4; case b5; constructor; try by case. Qed. Lemma orP : reflect (b1 \/ b2) (b1 || b2). Proof. by case b1; case b2; constructor; auto; case. Qed. Lemma or3P : reflect [\/ b1, b2 | b3] [|| b1, b2 | b3]. Proof. case b1; first by constructor; constructor 1. case b2; first by constructor; constructor 2. case b3; first by constructor; constructor 3. by constructor; case. Qed. Lemma or4P : reflect [\/ b1, b2, b3 | b4] [|| b1, b2, b3 | b4]. Proof. case b1; first by constructor; constructor 1. case b2; first by constructor; constructor 2. case b3; first by constructor; constructor 3. case b4; first by constructor; constructor 4. by constructor; case. Qed. Lemma nandP : reflect (~~ b1 \/ ~~ b2) (~~ (b1 && b2)). Proof. by case b1; case b2; constructor; auto; case; auto. Qed. Lemma norP : reflect (~~ b1 /\ ~~ b2) (~~ (b1 || b2)). Proof. by case b1; case b2; constructor; auto; case; auto. Qed. Lemma implyP : reflect (b1 -> b2) (b1 ==> b2). Proof. by case b1; case b2; constructor; auto. Qed. End ReflectConnectives. Arguments idP {b1}. Arguments idPn {b1}. Arguments negP {b1}. Arguments negPn {b1}. Arguments negPf {b1}. Arguments andP {b1 b2}. Arguments and3P {b1 b2 b3}. Arguments and4P {b1 b2 b3 b4}. Arguments and5P {b1 b2 b3 b4 b5}. Arguments orP {b1 b2}. Arguments or3P {b1 b2 b3}. Arguments or4P {b1 b2 b3 b4}. Arguments nandP {b1 b2}. Arguments norP {b1 b2}. Arguments implyP {b1 b2}. Prenex Implicits idP idPn negP negPn negPf. Prenex Implicits andP and3P and4P and5P orP or3P or4P nandP norP implyP. Section ReflectCombinators. Variables (P Q : Prop) (p q : bool). Hypothesis rP : reflect P p. Hypothesis rQ : reflect Q q. Lemma negPP : reflect (~ P) (~~ p). Proof. by apply:(iffP negP); apply: contra_not => /rP. Qed. Lemma andPP : reflect (P /\ Q) (p && q). Proof. by apply: (iffP andP) => -[/rP ? /rQ ?]. Qed. Lemma orPP : reflect (P \/ Q) (p || q). Proof. by apply: (iffP orP) => -[/rP ?|/rQ ?]; tauto. Qed. Lemma implyPP : reflect (P -> Q) (p ==> q). Proof. by apply: (iffP implyP) => pq /rP /pq /rQ. Qed. End ReflectCombinators. Arguments negPP {P p}. Arguments andPP {P Q p q}. Arguments orPP {P Q p q}. Arguments implyPP {P Q p q}. Prenex Implicits negPP andPP orPP implyPP. (** Shorter, more systematic names for the boolean connectives laws. **) Lemma andTb : left_id true andb. Proof. by []. Qed. Lemma andFb : left_zero false andb. Proof. by []. Qed. Lemma andbT : right_id true andb. Proof. by case. Qed. Lemma andbF : right_zero false andb. Proof. by case. Qed. Lemma andbb : idempotent_op andb. Proof. by case. Qed. Lemma andbC : commutative andb. Proof. by do 2!case. Qed. Lemma andbA : associative andb. Proof. by do 3!case. Qed. Lemma andbCA : left_commutative andb. Proof. by do 3!case. Qed. Lemma andbAC : right_commutative andb. Proof. by do 3!case. Qed. Lemma andbACA : interchange andb andb. Proof. by do 4!case. Qed. Lemma orTb : forall b, true || b. Proof. by []. Qed. Lemma orFb : left_id false orb. Proof. by []. Qed. Lemma orbT : forall b, b || true. Proof. by case. Qed. Lemma orbF : right_id false orb. Proof. by case. Qed. Lemma orbb : idempotent_op orb. Proof. by case. Qed. Lemma orbC : commutative orb. Proof. by do 2!case. Qed. Lemma orbA : associative orb. Proof. by do 3!case. Qed. Lemma orbCA : left_commutative orb. Proof. by do 3!case. Qed. Lemma orbAC : right_commutative orb. Proof. by do 3!case. Qed. Lemma orbACA : interchange orb orb. Proof. by do 4!case. Qed. Lemma andbN b : b && ~~ b = false. Proof. by case: b. Qed. Lemma andNb b : ~~ b && b = false. Proof. by case: b. Qed. Lemma orbN b : b || ~~ b = true. Proof. by case: b. Qed. Lemma orNb b : ~~ b || b = true. Proof. by case: b. Qed. Lemma andb_orl : left_distributive andb orb. Proof. by do 3!case. Qed. Lemma andb_orr : right_distributive andb orb. Proof. by do 3!case. Qed. Lemma orb_andl : left_distributive orb andb. Proof. by do 3!case. Qed. Lemma orb_andr : right_distributive orb andb. Proof. by do 3!case. Qed. Lemma andb_idl (a b : bool) : (b -> a) -> a && b = b. Proof. by case: a; case: b => // ->. Qed. Lemma andb_idr (a b : bool) : (a -> b) -> a && b = a. Proof. by case: a; case: b => // ->. Qed. Lemma andb_id2l (a b c : bool) : (a -> b = c) -> a && b = a && c. Proof. by case: a; case: b; case: c => // ->. Qed. Lemma andb_id2r (a b c : bool) : (b -> a = c) -> a && b = c && b. Proof. by case: a; case: b; case: c => // ->. Qed. Lemma orb_idl (a b : bool) : (a -> b) -> a || b = b. Proof. by case: a; case: b => // ->. Qed. Lemma orb_idr (a b : bool) : (b -> a) -> a || b = a. Proof. by case: a; case: b => // ->. Qed. Lemma orb_id2l (a b c : bool) : (~~ a -> b = c) -> a || b = a || c. Proof. by case: a; case: b; case: c => // ->. Qed. Lemma orb_id2r (a b c : bool) : (~~ b -> a = c) -> a || b = c || b. Proof. by case: a; case: b; case: c => // ->. Qed. Lemma negb_and (a b : bool) : ~~ (a && b) = ~~ a || ~~ b. Proof. by case: a; case: b. Qed. Lemma negb_or (a b : bool) : ~~ (a || b) = ~~ a && ~~ b. Proof. by case: a; case: b. Qed. (** Pseudo-cancellation -- i.e, absorption **) Lemma andbK a b : a && b || a = a. Proof. by case: a; case: b. Qed. Lemma andKb a b : a || b && a = a. Proof. by case: a; case: b. Qed. Lemma orbK a b : (a || b) && a = a. Proof. by case: a; case: b. Qed. Lemma orKb a b : a && (b || a) = a. Proof. by case: a; case: b. Qed. (** Imply **) Lemma implybT b : b ==> true. Proof. by case: b. Qed. Lemma implybF b : (b ==> false) = ~~ b. Proof. by case: b. Qed. Lemma implyFb b : false ==> b. Proof. by []. Qed. Lemma implyTb b : (true ==> b) = b. Proof. by []. Qed. Lemma implybb b : b ==> b. Proof. by case: b. Qed. Lemma negb_imply a b : ~~ (a ==> b) = a && ~~ b. Proof. by case: a; case: b. Qed. Lemma implybE a b : (a ==> b) = ~~ a || b. Proof. by case: a; case: b. Qed. Lemma implyNb a b : (~~ a ==> b) = a || b. Proof. by case: a; case: b. Qed. Lemma implybN a b : (a ==> ~~ b) = (b ==> ~~ a). Proof. by case: a; case: b. Qed. Lemma implybNN a b : (~~ a ==> ~~ b) = b ==> a. Proof. by case: a; case: b. Qed. Lemma implyb_idl (a b : bool) : (~~ a -> b) -> (a ==> b) = b. Proof. by case: a; case: b => // ->. Qed. Lemma implyb_idr (a b : bool) : (b -> ~~ a) -> (a ==> b) = ~~ a. Proof. by case: a; case: b => // ->. Qed. Lemma implyb_id2l (a b c : bool) : (a -> b = c) -> (a ==> b) = (a ==> c). Proof. by case: a; case: b; case: c => // ->. Qed. (** Addition (xor) **) Lemma addFb : left_id false addb. Proof. by []. Qed. Lemma addbF : right_id false addb. Proof. by case. Qed. Lemma addbb : self_inverse false addb. Proof. by case. Qed. Lemma addbC : commutative addb. Proof. by do 2!case. Qed. Lemma addbA : associative addb. Proof. by do 3!case. Qed. Lemma addbCA : left_commutative addb. Proof. by do 3!case. Qed. Lemma addbAC : right_commutative addb. Proof. by do 3!case. Qed. Lemma addbACA : interchange addb addb. Proof. by do 4!case. Qed. Lemma andb_addl : left_distributive andb addb. Proof. by do 3!case. Qed. Lemma andb_addr : right_distributive andb addb. Proof. by do 3!case. Qed. Lemma addKb : left_loop id addb. Proof. by do 2!case. Qed. Lemma addbK : right_loop id addb. Proof. by do 2!case. Qed. Lemma addIb : left_injective addb. Proof. by do 3!case. Qed. Lemma addbI : right_injective addb. Proof. by do 3!case. Qed. Lemma addTb b : true (+) b = ~~ b. Proof. by []. Qed. Lemma addbT b : b (+) true = ~~ b. Proof. by case: b. Qed. Lemma addbN a b : a (+) ~~ b = ~~ (a (+) b). Proof. by case: a; case: b. Qed. Lemma addNb a b : ~~ a (+) b = ~~ (a (+) b). Proof. by case: a; case: b. Qed. Lemma addbP a b : reflect (~~ a = b) (a (+) b). Proof. by case: a; case: b; constructor. Qed. Arguments addbP {a b}. (** Resolution tactic for blindly weeding out common terms from boolean equalities. When faced with a goal of the form (andb/orb/addb b1 b2) = b3 they will try to locate b1 in b3 and remove it. This can fail! **) Ltac bool_congr := match goal with | |- (?X1 && ?X2 = ?X3) => first [ symmetry; rewrite -1?(andbC X1) -?(andbCA X1); congr 1 (andb X1); symmetry | case: (X1); [ rewrite ?andTb ?andbT // | by rewrite ?andbF /= ] ] | |- (?X1 || ?X2 = ?X3) => first [ symmetry; rewrite -1?(orbC X1) -?(orbCA X1); congr 1 (orb X1); symmetry | case: (X1); [ by rewrite ?orbT //= | rewrite ?orFb ?orbF ] ] | |- (?X1 (+) ?X2 = ?X3) => symmetry; rewrite -1?(addbC X1) -?(addbCA X1); congr 1 (addb X1); symmetry | |- (~~ ?X1 = ?X2) => congr 1 negb end. (** Predicates, i.e., packaged functions to bool. - pred T, the basic type for predicates over a type T, is simply an alias for T -> bool. We actually distinguish two kinds of predicates, which we call applicative and collective, based on the syntax used to test them at some x in T: - For an applicative predicate P, one uses prefix syntax: P x Also, most operations on applicative predicates use prefix syntax as well (e.g., predI P Q). - For a collective predicate A, one uses infix syntax: x \in A and all operations on collective predicates use infix syntax as well (e.g., #[#predI A & B#]#). There are only two kinds of applicative predicates: - pred T, the alias for T -> bool mentioned above - simpl_pred T, an alias for simpl_fun T bool with a coercion to pred T that auto-simplifies on application (see ssrfun). On the other hand, the set of collective predicate types is open-ended via - predType T, a Structure that can be used to put Canonical collective predicate interpretation on other types, such as lists, tuples, finite sets, etc. Indeed, we define such interpretations for applicative predicate types, which can therefore also be used with the infix syntax, e.g., x \in predI P Q Moreover these infix forms are convertible to their prefix counterpart (e.g., predI P Q x which in turn simplifies to P x && Q x). The converse is not true, however; collective predicate types cannot, in general, be used applicatively, because of restrictions on implicit coercions. However, we do define an explicit generic coercion - mem : forall (pT : predType), pT -> mem_pred T where mem_pred T is a variant of simpl_pred T that preserves the infix syntax, i.e., mem A x auto-simplifies to x \in A. Indeed, the infix "collective" operators are notation for a prefix operator with arguments of type mem_pred T or pred T, applied to coerced collective predicates, e.g., Notation "x \in A" := (in_mem x (mem A)). This prevents the variability in the predicate type from interfering with the application of generic lemmas. Moreover this also makes it much easier to define generic lemmas, because the simplest type -- pred T -- can be used as the type of generic collective predicates, provided one takes care not to use it applicatively; this avoids the burden of having to declare a different predicate type for each predicate parameter of each section or lemma. In detail, we ensure that the head normal form of mem A is always of the eta-long MemPred (fun x => pA x) form, where pA is the pred interpretation of A following its predType pT, i.e., the _expansion_ of topred A. For a pred T evar ?P, (mem ?P) converts MemPred (fun x => ?P x), whose argument is a Miller pattern and therefore always unify: unifying (mem A) with (mem ?P) always yields ?P = pA, because the rigid constant MemPred aligns the unification. Furthermore, we ensure pA is always either A or toP .... A where toP ... is the expansion of @topred T pT, and toP is declared as a Coercion, so pA will _display_ as A in either case, and the instances of @mem T (predPredType T) pA appearing in the premises or right-hand side of a generic lemma parameterized by ?P will be indistinguishable from @mem T pT A. Users should take care not to inadvertently "strip" (mem A) down to the coerced A, since this will expose the internal toP coercion: Rocq could then display terms A x that cannot be typed as such. The topredE lemma can be used to restore the x \in A syntax in this case. While -topredE can conversely be used to change x \in P into P x for an applicative P, it is safer to use the inE, unfold_in or and memE lemmas instead, as they do not run the risk of exposing internal coercions. As a consequence it is better to explicitly cast a generic applicative predicate to simpl_pred using the SimplPred constructor when it is used as a collective predicate (see, e.g., Lemma eq_big in bigop). We also sometimes "instantiate" the predType structure by defining a coercion to the sort of the predPredType structure, conveniently denoted {pred T}. This works better for types such as {set T} that have subtypes that coerce to them, since the same coercion will be inserted by the application of mem, or of any lemma that expects a generic collective predicates with type {pred T} := pred_sort (predPredType T) = pred T; thus {pred T} should be the preferred type for generic collective predicate parameters. This device also lets us turn any Type aT : predArgType into the total predicate over that type, i.e., fun _: aT => true. This allows us to write, e.g., ##|'I_n| for the cardinal of the (finite) type of integers less than n. **) (** Boolean predicates. *) Definition pred T := T -> bool. Identity Coercion fun_of_pred : pred >-> Funclass. Definition subpred T (p1 p2 : pred T) := forall x : T, p1 x -> p2 x. (* Abbreviation for some manifest predicates. *) Abbreviation xpred0 := (fun=> false). Abbreviation xpredT := (fun=> true). Abbreviation xpredI := (fun (p1 p2 : pred _) x => p1 x && p2 x). Abbreviation xpredU := (fun (p1 p2 : pred _) x => p1 x || p2 x). Abbreviation xpredC := (fun (p : pred _) x => ~~ p x). Abbreviation xpredD := (fun (p1 p2 : pred _) x => ~~ p2 x && p1 x). Abbreviation xpreim := (fun f (p : pred _) x => p (f x)). (** The packed class interface for pred-like types. **) Structure predType T := PredType {pred_sort :> Type; topred : pred_sort -> pred T}. Definition clone_pred T U := fun pT & @pred_sort T pT -> U => fun toP (pT' := @PredType T U toP) & phant_id pT' pT => pT'. Notation "[ 'predType' 'of' T ]" := (@clone_pred _ T _ id _ id) : form_scope. Canonical predPredType T := PredType (@id (pred T)). Set Warnings "-redundant-canonical-projection". Canonical boolfunPredType T := PredType (@id (T -> bool)). Set Warnings "redundant-canonical-projection". (** The type of abstract collective predicates. While {pred T} is convertible to pred T, it presents the pred_sort coercion class, which crucially does _not_ coerce to Funclass. Term whose type P coerces to {pred T} cannot be applied to arguments, but they _can_ be used as if P had a canonical predType instance, as the coercion will be inserted if the unification P =~= pred_sort ?pT fails, changing the problem into the trivial {pred T} =~= pred_sort ?pT (solution ?pT := predPredType P). Additional benefits of this approach are that any type coercing to P will also inherit this behaviour, and that the coercion will be apparent in the elaborated expression. The latter may be important if the coercion is also a canonical structure projector - see mathcomp/fingroup/fingroup.v. The main drawback of implementing predType by coercion in this way is that the type of the value must be known when the unification constraint is imposed: if we only register the constraint and then later discover later that the expression had type P it will be too late to insert a coercion, whereas a canonical instance of predType for P would have solved the deferred constraint. Finally, definitions, lemmas and sections should use type {pred T} for their generic collective type parameters, as this will make it possible to apply such definitions and lemmas directly to values of types that implement predType by coercion to {pred T} (values of types that implement predType without coercing to {pred T} will have to be coerced explicitly using topred). **) Notation "{ 'pred' T }" := (pred_sort (predPredType T)) : type_scope. (** The type of self-simplifying collective predicates. **) Definition simpl_pred T := simpl_fun T bool. Definition SimplPred {T} (p : pred T) : simpl_pred T := SimplFun p. (** Some simpl_pred constructors. **) Definition pred0 {T} := @SimplPred T xpred0. Definition predT {T} := @SimplPred T xpredT. Definition predI {T} (p1 p2 : pred T) := SimplPred (xpredI p1 p2). Definition predU {T} (p1 p2 : pred T) := SimplPred (xpredU p1 p2). Definition predC {T} (p : pred T) := SimplPred (xpredC p). Definition predD {T} (p1 p2 : pred T) := SimplPred (xpredD p1 p2). Definition preim {aT rT} (f : aT -> rT) (d : pred rT) := SimplPred (xpreim f d). Notation "[ 'pred' : T | E ]" := (SimplPred (fun _ : T => E%B)) : function_scope. Notation "[ 'pred' x | E ]" := (SimplPred (fun x => E%B)) : function_scope. Notation "[ 'pred' x | E1 & E2 ]" := [pred x | E1 && E2 ] : function_scope. Notation "[ 'pred' x : T | E ]" := (SimplPred (fun x : T => E%B)) (only parsing) : function_scope. Notation "[ 'pred' x : T | E1 & E2 ]" := [pred x : T | E1 && E2 ] (only parsing) : function_scope. (** Coercions for simpl_pred. As simpl_pred T values are used both applicatively and collectively we need simpl_pred to coerce to both pred T _and_ {pred T}. However it is undesirable to have two distinct constants for what are essentially identical coercion functions, as this confuses the SSReflect keyed matching algorithm. While the Rocq Coercion declarations appear to disallow such Coercion aliasing, it is possible to work around this limitation with a combination of modules and functors, which we do below. In addition we also give a predType instance for simpl_pred, which will be preferred to the {pred T} coercion to solve simpl_pred T =~= pred_sort ?pT constraints; note however that the pred_of_simpl coercion _will_ be used when a simpl_pred T is passed as a {pred T}, since the simplPredType T structure for simpl_pred T is _not_ convertible to predPredType T. **) Module PredOfSimpl. Definition coerce T (sp : simpl_pred T) : pred T := fun_of_simpl sp. End PredOfSimpl. Abbreviation pred_of_simpl := PredOfSimpl.coerce. Coercion pred_of_simpl : simpl_pred >-> pred. Canonical simplPredType T := PredType (@pred_of_simpl T). Module Type PredSortOfSimplSignature. Parameter coerce : forall T, simpl_pred T -> {pred T}. End PredSortOfSimplSignature. Module DeclarePredSortOfSimpl (PredSortOfSimpl : PredSortOfSimplSignature). Coercion PredSortOfSimpl.coerce : simpl_pred >-> pred_sort. End DeclarePredSortOfSimpl. Module Export PredSortOfSimplCoercion := DeclarePredSortOfSimpl PredOfSimpl. (** Type to pred coercion. This lets us use types of sort predArgType as a synonym for their universal predicate. We define this predicate as a simpl_pred T rather than a pred T or a {pred T} so that /= and inE reduce (T x) and x \in T to true, respectively. Unfortunately, this can't be used for existing types like bool whose sort is already fixed (at least, not without redefining bool, true, false and all bool operations and lemmas); we provide syntax to recast a given type in predArgType as a workaround. **) Definition predArgType := Type. Bind Scope type_scope with predArgType. Identity Coercion sort_of_predArgType : predArgType >-> Sortclass. Coercion pred_of_argType (T : predArgType) : simpl_pred T := predT. Notation "{ : T }" := (T%type : predArgType) : type_scope. (** Boolean relations. Simplifying relations follow the coding pattern of 2-argument simplifying functions: the simplifying type constructor is applied to the _last_ argument. This design choice will let the in_simpl component of inE expand membership in simpl_rel as well. We provide an explicit coercion to rel T to avoid eta-expansion during coercion; this coercion self-simplifies so it should be invisible. **) Definition rel T := T -> pred T. Identity Coercion fun_of_rel : rel >-> Funclass. Definition subrel T (r1 r2 : rel T) := forall x y : T, r1 x y -> r2 x y. Definition simpl_rel T := T -> simpl_pred T. Coercion rel_of_simpl T (sr : simpl_rel T) : rel T := fun x : T => sr x. Arguments rel_of_simpl {T} sr x /. Abbreviation xrelU := (fun (r1 r2 : rel _) x y => r1 x y || r2 x y). Abbreviation xrelpre := (fun f (r : rel _) x y => r (f x) (f y)). Definition SimplRel {T} (r : rel T) : simpl_rel T := fun x => SimplPred (r x). Definition relU {T} (r1 r2 : rel T) := SimplRel (xrelU r1 r2). Definition relpre {aT rT} (f : aT -> rT) (r : rel rT) := SimplRel (xrelpre f r). Notation "[ 'rel' x y | E ]" := (SimplRel (fun x y => E%B)) (only parsing) : function_scope. Notation "[ 'rel' x y : T | E ]" := (SimplRel (fun x y : T => E%B)) (only parsing) : function_scope. Lemma subrelUl T (r1 r2 : rel T) : subrel r1 (relU r1 r2). Proof. by move=> x y r1xy; apply/orP; left. Qed. Lemma subrelUr T (r1 r2 : rel T) : subrel r2 (relU r1 r2). Proof. by move=> x y r2xy; apply/orP; right. Qed. (** Variant of simpl_pred specialised to the membership operator. **) Variant mem_pred T := Mem of pred T. (** We mainly declare pred_of_mem as a coercion so that it is not displayed. Similarly to pred_of_simpl, it will usually not be inserted by type inference, as all mem_pred mp =~= pred_sort ?pT unification problems will be solve by the memPredType instance below; pred_of_mem will however be used if a mem_pred T is used as a {pred T}, which is desirable as it will avoid a redundant mem in a collective, e.g., passing (mem A) to a lemma exception a generic collective predicate p : {pred T} and premise x \in P will display a subgoal x \in A rather than x \in mem A. Conversely, pred_of_mem will _not_ if it is used id (mem A) is used applicatively or as a pred T; there the simpl_of_mem coercion defined below will be used, resulting in a subgoal that displays as mem A x by simplifies to x \in A. **) Coercion pred_of_mem {T} mp : {pred T} := let: Mem p := mp in [eta p]. Canonical memPredType T := PredType (@pred_of_mem T). Definition in_mem {T} (x : T) mp := pred_of_mem mp x. Definition eq_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 = in_mem x mp2. Definition sub_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 -> in_mem x mp2. Arguments in_mem {T} x mp : simpl never. Global Typeclasses Opaque eq_mem sub_mem. (** The [simpl_of_mem; pred_of_simpl] path provides a new mem_pred >-> pred coercion, but does _not_ override the pred_of_mem : mem_pred >-> pred_sort explicit coercion declaration above. **) Coercion simpl_of_mem {T} mp := SimplPred (fun x : T => in_mem x mp). Lemma sub_refl T (mp : mem_pred T) : sub_mem mp mp. Proof. by []. Qed. Arguments sub_refl {T mp} [x] mp_x. (** It is essential to interlock the production of the Mem constructor inside the branch of the predType match, to ensure that unifying mem A with Mem [eta ?p] sets ?p := toP A (or ?p := P if toP = id and A = [eta P]), rather than topred pT A, had we put mem A := Mem (topred A). **) Definition mem T (pT : predType T) : pT -> mem_pred T := let: PredType toP := pT in fun A => Mem [eta toP A]. Arguments mem {T pT} A : rename, simpl never. Notation "x \in A" := (in_mem x (mem A)) (only parsing) : bool_scope. Notation "x \in A" := (in_mem x (mem A)) (only printing) : bool_scope. Notation "x \notin A" := (~~ (x \in A)) : bool_scope. Notation "A =i B" := (eq_mem (mem A) (mem B)) : type_scope. Notation "{ 'subset' A <= B }" := (sub_mem (mem A) (mem B)) : type_scope. Notation "[ 'in' A ]" := (in_mem^~ (mem A)) (at level 0, format "[ 'in' A ]") : function_scope. Notation "[ 'mem' A ]" := (pred_of_simpl (simpl_of_mem (mem A))) (only parsing) : function_scope. Notation "[ 'predI' A & B ]" := (predI [in A] [in B]) : function_scope. Notation "[ 'predU' A & B ]" := (predU [in A] [in B]) : function_scope. Notation "[ 'predD' A & B ]" := (predD [in A] [in B]) : function_scope. Notation "[ 'predC' A ]" := (predC [in A]) : function_scope. Notation "[ 'preim' f 'of' A ]" := (preim f [in A]) : function_scope. Notation "[ 'pred' x 'in' A ]" := [pred x | x \in A] : function_scope. Notation "[ 'pred' x 'in' A | E ]" := [pred x | x \in A & E] : function_scope. Notation "[ 'pred' x 'in' A | E1 & E2 ]" := [pred x | x \in A & E1 && E2 ] : function_scope. Notation "[ 'rel' x y 'in' A & B | E ]" := [rel x y | (x \in A) && (y \in B) && E] : function_scope. Notation "[ 'rel' x y 'in' A & B ]" := [rel x y | (x \in A) && (y \in B)] : function_scope. Notation "[ 'rel' x y 'in' A | E ]" := [rel x y in A & A | E] : function_scope. Notation "[ 'rel' x y 'in' A ]" := [rel x y in A & A] : function_scope. (** Aliases of pred T that let us tag instances of simpl_pred as applicative or collective, via bespoke coercions. This tagging will give control over the simplification behaviour of inE and other rewriting lemmas below. For this control to work it is crucial that collective_of_simpl _not_ be convertible to either applicative_of_simpl or pred_of_simpl. Indeed they differ here by a commutative conversion (of the match and lambda). **) Definition applicative_pred T := pred T. Definition collective_pred T := pred T. Coercion applicative_pred_of_simpl T (sp : simpl_pred T) : applicative_pred T := fun_of_simpl sp. Coercion collective_pred_of_simpl T (sp : simpl_pred T) : collective_pred T := let: SimplFun p := sp in p. (** Explicit simplification rules for predicate application and membership. **) Section PredicateSimplification. Variables T : Type. Implicit Types (p : pred T) (pT : predType T) (sp : simpl_pred T). Implicit Types (mp : mem_pred T). (** The following four bespoke structures provide fine-grained control over matching the various predicate forms. While all four follow a common pattern of using a canonical projection to match a particular form of predicate (in pred T, simpl_pred, mem_pred and mem_pred, respectively), and display the matched predicate in the structure type, each is in fact used for a different, specific purpose: - registered_applicative_pred: this user-facing structure is used to declare values of type pred T meant to be used applicatively. The structure parameter merely displays this same value, and is used to avoid undesirable, visible occurrence of the structure in the right hand side of rewrite rules such as app_predE. There is a canonical instance of registered_applicative_pred for values of the applicative_of_simpl coercion, which handles the Definition Apred : applicative_pred T := [pred x | ...] idiom. This instance is mainly intended for the in_applicative component of inE, in conjunction with manifest_mem_pred and applicative_mem_pred. - manifest_simpl_pred: the only instance of this structure matches manifest simpl_pred values of the form SimplPred p, displaying p in the structure type. This structure is used in in_simpl to detect and selectively expand collective predicates of this form. An explicit SimplPred p pattern would _NOT_ work for this purpose, as then the left-hand side of in_simpl would reduce to in_mem ?x (Mem [eta ?p]) and would thus match _any_ instance of \in, not just those arising from a manifest simpl_pred. - manifest_mem_pred: similar to manifest_simpl_pred, the one instance of this structure matches manifest mem_pred values of the form Mem [eta ?p]. The purpose is different however: to match and display in ?p the actual predicate appearing in an ... \in ... expression matched by the left hand side of the in_applicative component of inE; then - applicative_mem_pred is a telescope refinement of manifest_mem_pred p with a default constructor that checks that the predicate p is the value of a registered_applicative_pred; any unfolding occurring during this check does _not_ affect the value of p passed to in_applicative, since that has been fixed earlier by the manifest_mem_pred match. In particular the definition of a predicate using the applicative_pred_of_simpl idiom above will not be expanded - this very case is the reason in_applicative uses a mem_pred telescope in its left hand side. The more straightforward ?x \in applicative_pred_value ?ap (equivalent to in_mem ?x (Mem ?ap)) with ?ap : registered_applicative_pred ?p would set ?p := [pred x | ...] rather than ?p := Apred in the example above. Also note that the in_applicative component of inE must be come before the in_simpl one, as the latter also matches terms of the form x \in Apred. Finally, no component of inE matches x \in Acoll, when Definition Acoll : collective_pred T := [pred x | ...]. as the collective_pred_of_simpl is _not_ convertible to pred_of_simpl. **) Structure registered_applicative_pred p := RegisteredApplicativePred { applicative_pred_value :> pred T; _ : applicative_pred_value = p }. Definition ApplicativePred p := RegisteredApplicativePred (erefl p). Canonical applicative_pred_applicative sp := ApplicativePred (applicative_pred_of_simpl sp). Structure manifest_simpl_pred p := ManifestSimplPred { simpl_pred_value :> simpl_pred T; _ : simpl_pred_value = SimplPred p }. Canonical expose_simpl_pred p := ManifestSimplPred (erefl (SimplPred p)). Structure manifest_mem_pred p := ManifestMemPred { mem_pred_value :> mem_pred T; _ : mem_pred_value = Mem [eta p] }. Canonical expose_mem_pred p := ManifestMemPred (erefl (Mem [eta p])). Structure applicative_mem_pred p := ApplicativeMemPred {applicative_mem_pred_value :> manifest_mem_pred p}. Canonical check_applicative_mem_pred p (ap : registered_applicative_pred p) := [eta @ApplicativeMemPred ap]. Lemma mem_topred pT (pp : pT) : mem (topred pp) = mem pp. Proof. by case: pT pp. Qed. Lemma topredE pT x (pp : pT) : topred pp x = (x \in pp). Proof. by rewrite -mem_topred. Qed. Lemma app_predE x p (ap : registered_applicative_pred p) : ap x = (x \in p). Proof. by case: ap => _ /= ->. Qed. Lemma in_applicative x p (amp : applicative_mem_pred p) : in_mem x amp = p x. Proof. by case: amp => -[_ /= ->]. Qed. Lemma in_collective x p (msp : manifest_simpl_pred p) : (x \in collective_pred_of_simpl msp) = p x. Proof. by case: msp => _ /= ->. Qed. Lemma in_simpl x p (msp : manifest_simpl_pred p) : in_mem x (Mem [eta pred_of_simpl msp]) = p x. Proof. by case: msp => _ /= ->. Qed. (** Because of the explicit eta expansion in the left-hand side, this lemma should only be used in the left-to-right direction. **) Lemma unfold_in x p : (x \in ([eta p] : pred T)) = p x. Proof. by []. Qed. Lemma simpl_predE p : SimplPred p =1 p. Proof. by []. Qed. Definition inE := (in_applicative, in_simpl, simpl_predE). (* to be extended *) Lemma mem_simpl sp : mem sp = sp :> pred T. Proof. by []. Qed. Definition memE := mem_simpl. (* could be extended *) Lemma mem_mem mp : (mem mp = mp) * (mem (mp : simpl_pred T) = mp) * (mem (mp : pred T) = mp). Proof. by case: mp. Qed. End PredicateSimplification. (** Qualifiers and keyed predicates. **) Variant qualifier (q : nat) T := Qualifier of {pred T}. Coercion has_quality n T (q : qualifier n T) : {pred T} := fun x => let: Qualifier _ p := q in p x. Arguments has_quality n {T}. Lemma qualifE n T p x : (x \in @Qualifier n T p) = p x. Proof. by []. Qed. Notation "x \is A" := (x \in has_quality 0 A) (only parsing) : bool_scope. Notation "x \is A" := (x \in has_quality 0 A) (only printing) : bool_scope. Notation "x \is 'a' A" := (x \in has_quality 1 A) (only parsing) : bool_scope. Notation "x \is 'a' A" := (x \in has_quality 1 A) (only printing) : bool_scope. Notation "x \is 'an' A" := (x \in has_quality 2 A) (only parsing) : bool_scope. Notation "x \is 'an' A" := (x \in has_quality 2 A) (only printing) : bool_scope. Notation "x \isn't A" := (x \notin has_quality 0 A) : bool_scope. Notation "x \isn't 'a' A" := (x \notin has_quality 1 A) : bool_scope. Notation "x \isn't 'an' A" := (x \notin has_quality 2 A) : bool_scope. Notation "[ 'qualify' x | P ]" := (Qualifier 0 (fun x => P%B)) : form_scope. Notation "[ 'qualify' x : T | P ]" := (Qualifier 0 (fun x : T => P%B)) (only parsing) : form_scope. Notation "[ 'qualify' 'a' x | P ]" := (Qualifier 1 (fun x => P%B)) : form_scope. Notation "[ 'qualify' 'a' x : T | P ]" := (Qualifier 1 (fun x : T => P%B)) (only parsing) : form_scope. Notation "[ 'qualify' 'an' x | P ]" := (Qualifier 2 (fun x => P%B)) : form_scope. Notation "[ 'qualify' 'an' x : T | P ]" := (Qualifier 2 (fun x : T => P%B)) (only parsing) : form_scope. (** Keyed predicates: support for property-bearing predicate interfaces. **) Section KeyPred. Variable T : Type. Variant pred_key (p : {pred T}) : Prop := DefaultPredKey. Variable p : {pred T}. Structure keyed_pred (k : pred_key p) := PackKeyedPred {unkey_pred :> {pred T}; _ : unkey_pred =i p}. Variable k : pred_key p. Definition KeyedPred := @PackKeyedPred k p (frefl _). Variable k_p : keyed_pred k. Lemma keyed_predE : k_p =i p. Proof. by case: k_p. Qed. (** Instances that strip the mem cast; the first one has "pred_of_mem" as its projection head value, while the second has "pred_of_simpl". The latter has the side benefit of preempting accidental misdeclarations. Note: pred_of_mem is the registered mem >-> pred_sort coercion, while [simpl_of_mem; pred_of_simpl] is the mem >-> pred >=> Funclass coercion. We must write down the coercions explicitly as the Canonical head constant computation does not strip casts. **) Canonical keyed_mem := @PackKeyedPred k (pred_of_mem (mem k_p)) keyed_predE. Canonical keyed_mem_simpl := @PackKeyedPred k (pred_of_simpl (mem k_p)) keyed_predE. End KeyPred. Local Abbreviation in_unkey x S := (x \in @unkey_pred _ S _ _) (only parsing). Notation "x \in S" := (in_unkey x S) (only printing) : bool_scope. Section KeyedQualifier. Variables (T : Type) (n : nat) (q : qualifier n T). Structure keyed_qualifier (k : pred_key q) := PackKeyedQualifier {unkey_qualifier; _ : unkey_qualifier = q}. Definition KeyedQualifier k := PackKeyedQualifier k (erefl q). Variables (k : pred_key q) (k_q : keyed_qualifier k). Fact keyed_qualifier_suproof : unkey_qualifier k_q =i q. Proof. by case: k_q => /= _ ->. Qed. Canonical keyed_qualifier_keyed := PackKeyedPred k keyed_qualifier_suproof. End KeyedQualifier. Notation "x \is A" := (in_unkey x (has_quality 0 A)) (only printing) : bool_scope. Notation "x \is 'a' A" := (in_unkey x (has_quality 1 A)) (only printing) : bool_scope. Notation "x \is 'an' A" := (in_unkey x (has_quality 2 A)) (only printing) : bool_scope. Module DefaultKeying. Canonical default_keyed_pred T p := KeyedPred (@DefaultPredKey T p). Canonical default_keyed_qualifier T n (q : qualifier n T) := KeyedQualifier (DefaultPredKey q). End DefaultKeying. (** Skolemizing with conditions. **) Lemma all_tag_cond_dep I T (C : pred I) U : (forall x, T x) -> (forall x, C x -> {y : T x & U x y}) -> {f : forall x, T x & forall x, C x -> U x (f x)}. Proof. move=> f0 fP; apply: all_tag (fun x y => C x -> U x y) _ => x. by case Cx: (C x); [case/fP: Cx => y; exists y | exists (f0 x)]. Qed. Lemma all_tag_cond I T (C : pred I) U : T -> (forall x, C x -> {y : T & U x y}) -> {f : I -> T & forall x, C x -> U x (f x)}. Proof. by move=> y0; apply: all_tag_cond_dep. Qed. Lemma all_sig_cond_dep I T (C : pred I) P : (forall x, T x) -> (forall x, C x -> {y : T x | P x y}) -> {f : forall x, T x | forall x, C x -> P x (f x)}. Proof. by move=> f0 /(all_tag_cond_dep f0)[f]; exists f. Qed. Lemma all_sig_cond I T (C : pred I) P : T -> (forall x, C x -> {y : T | P x y}) -> {f : I -> T | forall x, C x -> P x (f x)}. Proof. by move=> y0; apply: all_sig_cond_dep. Qed. Lemma all_sig2_cond {I T} (C : pred I) P Q : T -> (forall x, C x -> {y : T | P x y & Q x y}) -> {f : I -> T | forall x, C x -> P x (f x) & forall x, C x -> Q x (f x)}. Proof. by move=> /all_sig_cond/[apply]-[f Pf]; exists f => i Di; have [] := Pf i Di. Qed. Section RelationProperties. (** Caveat: reflexive should not be used to state lemmas, as auto and trivial will not expand the constant. **) Variable T : Type. Variable R : rel T. Definition total := forall x y, R x y || R y x. Definition transitive := forall y x z, R x y -> R y z -> R x z. Definition symmetric := forall x y, R x y = R y x. Definition antisymmetric := forall x y, R x y && R y x -> x = y. Definition pre_symmetric := forall x y, R x y -> R y x. Lemma symmetric_from_pre : pre_symmetric -> symmetric. Proof. by move=> symR x y; apply/idP/idP; apply: symR. Qed. Definition reflexive := forall x, R x x. Definition irreflexive := forall x, R x x = false. Definition left_transitive := forall x y, R x y -> R x =1 R y. Definition right_transitive := forall x y, R x y -> R^~ x =1 R^~ y. Section PER. Hypotheses (symR : symmetric) (trR : transitive). Lemma sym_left_transitive : left_transitive. Proof. by move=> x y Rxy z; apply/idP/idP; apply: trR; rewrite // symR. Qed. Lemma sym_right_transitive : right_transitive. Proof. by move=> x y /sym_left_transitive Rxy z; rewrite !(symR z) Rxy. Qed. End PER. (** We define the equivalence property with prenex quantification so that it can be localized using the {in ..., ..} form defined below. **) Definition equivalence_rel := forall x y z, R z z * (R x y -> R x z = R y z). Lemma equivalence_relP : equivalence_rel <-> reflexive /\ left_transitive. Proof. split=> [eqiR | [Rxx trR] x y z]; last by split=> [|/trR->]. by split=> [x | x y Rxy z]; [rewrite (eqiR x x x) | rewrite (eqiR x y z)]. Qed. End RelationProperties. Lemma rev_trans T (R : rel T) : transitive R -> transitive (fun x y => R y x). Proof. by move=> trR x y z Ryx Rzy; apply: trR Rzy Ryx. Qed. (** Property localization **) Local Notation "{ 'all1' P }" := (forall x, P x : Prop) (at level 0). Local Notation "{ 'all2' P }" := (forall x y, P x y : Prop) (at level 0). Local Notation "{ 'all3' P }" := (forall x y z, P x y z: Prop) (at level 0). Local Abbreviation ph := (phantom _). Section LocalProperties. Variables T1 T2 T3 : Type. Variables (d1 : mem_pred T1) (d2 : mem_pred T2) (d3 : mem_pred T3). Local Abbreviation ph := (phantom Prop). Definition prop_for (x : T1) P & ph {all1 P} := P x. Lemma forE x P phP : @prop_for x P phP = P x. Proof. by []. Qed. Definition prop_in1 P & ph {all1 P} := forall x, in_mem x d1 -> P x. Definition prop_in11 P & ph {all2 P} := forall x y, in_mem x d1 -> in_mem y d2 -> P x y. Definition prop_in2 P & ph {all2 P} := forall x y, in_mem x d1 -> in_mem y d1 -> P x y. Definition prop_in111 P & ph {all3 P} := forall x y z, in_mem x d1 -> in_mem y d2 -> in_mem z d3 -> P x y z. Definition prop_in12 P & ph {all3 P} := forall x y z, in_mem x d1 -> in_mem y d2 -> in_mem z d2 -> P x y z. Definition prop_in21 P & ph {all3 P} := forall x y z, in_mem x d1 -> in_mem y d1 -> in_mem z d2 -> P x y z. Definition prop_in3 P & ph {all3 P} := forall x y z, in_mem x d1 -> in_mem y d1 -> in_mem z d1 -> P x y z. Variable f : T1 -> T2. Definition prop_on1 Pf P & phantom T3 (Pf f) & ph {all1 P} := forall x, in_mem (f x) d2 -> P x. Definition prop_on2 Pf P & phantom T3 (Pf f) & ph {all2 P} := forall x y, in_mem (f x) d2 -> in_mem (f y) d2 -> P x y. End LocalProperties. Definition inPhantom := Phantom Prop. Definition onPhantom {T} P (x : T) := Phantom Prop (P x). Definition bijective_in aT rT (d : mem_pred aT) (f : aT -> rT) := exists2 g, prop_in1 d (inPhantom (cancel f g)) & prop_on1 d (Phantom _ (cancel g)) (onPhantom (cancel g) f). Definition bijective_on aT rT (cd : mem_pred rT) (f : aT -> rT) := exists2 g, prop_on1 cd (Phantom _ (cancel f)) (onPhantom (cancel f) g) & prop_in1 cd (inPhantom (cancel g f)). Notation "{ 'for' x , P }" := (prop_for x (inPhantom P)) : type_scope. Notation "{ 'in' d , P }" := (prop_in1 (mem d) (inPhantom P)) : type_scope. Notation "{ 'in' d1 & d2 , P }" := (prop_in11 (mem d1) (mem d2) (inPhantom P)) : type_scope. Notation "{ 'in' d & , P }" := (prop_in2 (mem d) (inPhantom P)) : type_scope. Notation "{ 'in' d1 & d2 & d3 , P }" := (prop_in111 (mem d1) (mem d2) (mem d3) (inPhantom P)) : type_scope. Notation "{ 'in' d1 & & d3 , P }" := (prop_in21 (mem d1) (mem d3) (inPhantom P)) : type_scope. Notation "{ 'in' d1 & d2 & , P }" := (prop_in12 (mem d1) (mem d2) (inPhantom P)) : type_scope. Notation "{ 'in' d & & , P }" := (prop_in3 (mem d) (inPhantom P)) : type_scope. Notation "{ 'on' cd , P }" := (prop_on1 (mem cd) (inPhantom P) (inPhantom P)) : type_scope. Notation "{ 'on' cd & , P }" := (prop_on2 (mem cd) (inPhantom P) (inPhantom P)) : type_scope. Local Arguments onPhantom : clear scopes. Notation "{ 'on' cd , P & g }" := (prop_on1 (mem cd) (Phantom (_ -> Prop) P) (onPhantom P g)) : type_scope. Notation "{ 'in' d , 'bijective' f }" := (bijective_in (mem d) f) : type_scope. Notation "{ 'on' cd , 'bijective' f }" := (bijective_on (mem cd) f) : type_scope. (** Weakening and monotonicity lemmas for localized predicates. Note that using these lemmas in backward reasoning will force expansion of the predicate definition, as Rocq needs to expose the quantifier to apply these lemmas. We define a few specialized variants to avoid this for some of the ssrfun predicates. **) Section LocalGlobal. Variables T1 T2 T3 : predArgType. Variables (D1 : {pred T1}) (D2 : {pred T2}) (D3 : {pred T3}). Variables (d1 d1' : mem_pred T1) (d2 d2' : mem_pred T2) (d3 d3' : mem_pred T3). Variables (f f' : T1 -> T2) (g : T2 -> T1) (h : T3). Variables (P1 : T1 -> Prop) (P2 : T1 -> T2 -> Prop). Variable P3 : T1 -> T2 -> T3 -> Prop. Variable Q1 : (T1 -> T2) -> T1 -> Prop. Variable Q1l : (T1 -> T2) -> T3 -> T1 -> Prop. Variable Q2 : (T1 -> T2) -> T1 -> T1 -> Prop. Hypothesis sub1 : sub_mem d1 d1'. Hypothesis sub2 : sub_mem d2 d2'. Hypothesis sub3 : sub_mem d3 d3'. Lemma in1W : {all1 P1} -> {in D1, {all1 P1}}. Proof. by move=> ? ?. Qed. Lemma in2W : {all2 P2} -> {in D1 & D2, {all2 P2}}. Proof. by move=> ? ?. Qed. Lemma in3W : {all3 P3} -> {in D1 & D2 & D3, {all3 P3}}. Proof. by move=> ? ?. Qed. Lemma in1T : {in T1, {all1 P1}} -> {all1 P1}. Proof. by move=> ? ?; auto. Qed. Lemma in2T : {in T1 & T2, {all2 P2}} -> {all2 P2}. Proof. by move=> ? ?; auto. Qed. Lemma in3T : {in T1 & T2 & T3, {all3 P3}} -> {all3 P3}. Proof. by move=> ? ?; auto. Qed. Lemma sub_in1 (Ph : ph {all1 P1}) : prop_in1 d1' Ph -> prop_in1 d1 Ph. Proof. by move=> allP x /sub1; apply: allP. Qed. Lemma sub_in11 (Ph : ph {all2 P2}) : prop_in11 d1' d2' Ph -> prop_in11 d1 d2 Ph. Proof. by move=> allP x1 x2 /sub1 d1x1 /sub2; apply: allP. Qed. Lemma sub_in111 (Ph : ph {all3 P3}) : prop_in111 d1' d2' d3' Ph -> prop_in111 d1 d2 d3 Ph. Proof. by move=> allP x1 x2 x3 /sub1 d1x1 /sub2 d2x2 /sub3; apply: allP. Qed. Let allQ1 f'' := {all1 Q1 f''}. Let allQ1l f'' h' := {all1 Q1l f'' h'}. Let allQ2 f'' := {all2 Q2 f''}. Lemma on1W : allQ1 f -> {on D2, allQ1 f}. Proof. by move=> ? ?. Qed. Lemma on1lW : allQ1l f h -> {on D2, allQ1l f & h}. Proof. by move=> ? ?. Qed. Lemma on2W : allQ2 f -> {on D2 &, allQ2 f}. Proof. by move=> ? ?. Qed. Lemma on1T : {on T2, allQ1 f} -> allQ1 f. Proof. by move=> ? ?; auto. Qed. Lemma on1lT : {on T2, allQ1l f & h} -> allQ1l f h. Proof. by move=> ? ?; auto. Qed. Lemma on2T : {on T2 &, allQ2 f} -> allQ2 f. Proof. by move=> ? ?; auto. Qed. Lemma subon1 (Phf : ph (allQ1 f)) (Ph : ph (allQ1 f)) : prop_on1 d2' Phf Ph -> prop_on1 d2 Phf Ph. Proof. by move=> allQ x /sub2; apply: allQ. Qed. Lemma subon1l (Phf : ph (allQ1l f)) (Ph : ph (allQ1l f h)) : prop_on1 d2' Phf Ph -> prop_on1 d2 Phf Ph. Proof. by move=> allQ x /sub2; apply: allQ. Qed. Lemma subon2 (Phf : ph (allQ2 f)) (Ph : ph (allQ2 f)) : prop_on2 d2' Phf Ph -> prop_on2 d2 Phf Ph. Proof. by move=> allQ x y /sub2=> d2fx /sub2; apply: allQ. Qed. Lemma can_in_inj : {in D1, cancel f g} -> {in D1 &, injective f}. Proof. by move=> fK x y /fK{2}<- /fK{2}<- ->. Qed. Lemma canLR_in x y : {in D1, cancel f g} -> y \in D1 -> x = f y -> g x = y. Proof. by move=> fK D1y ->; rewrite fK. Qed. Lemma canRL_in x y : {in D1, cancel f g} -> x \in D1 -> f x = y -> x = g y. Proof. by move=> fK D1x <-; rewrite fK. Qed. Lemma on_can_inj : {on D2, cancel f & g} -> {on D2 &, injective f}. Proof. by move=> fK x y /fK{2}<- /fK{2}<- ->. Qed. Lemma canLR_on x y : {on D2, cancel f & g} -> f y \in D2 -> x = f y -> g x = y. Proof. by move=> fK D2fy ->; rewrite fK. Qed. Lemma canRL_on x y : {on D2, cancel f & g} -> f x \in D2 -> f x = y -> x = g y. Proof. by move=> fK D2fx <-; rewrite fK. Qed. Lemma inW_bij : bijective f -> {in D1, bijective f}. Proof. by case=> g' fK g'K; exists g' => * ? *; auto. Qed. Lemma onW_bij : bijective f -> {on D2, bijective f}. Proof. by case=> g' fK g'K; exists g' => * ? *; auto. Qed. Lemma inT_bij : {in T1, bijective f} -> bijective f. Proof. by case=> g' fK g'K; exists g' => * ? *; auto. Qed. Lemma onT_bij : {on T2, bijective f} -> bijective f. Proof. by case=> g' fK g'K; exists g' => * ? *; auto. Qed. Lemma sub_in_bij (D1' : pred T1) : {subset D1 <= D1'} -> {in D1', bijective f} -> {in D1, bijective f}. Proof. by move=> subD [g' fK g'K]; exists g' => x; move/subD; [apply: fK | apply: g'K]. Qed. Lemma subon_bij (D2' : pred T2) : {subset D2 <= D2'} -> {on D2', bijective f} -> {on D2, bijective f}. Proof. by move=> subD [g' fK g'K]; exists g' => x; move/subD; [apply: fK | apply: g'K]. Qed. Lemma in_on1P : {in D1, {on D2, allQ1 f}} <-> {in [pred x in D1 | f x \in D2], allQ1 f}. Proof. split => allf x; have := allf x; rewrite inE => Q1f; first by case/andP. by move=> ? ?; apply: Q1f; apply/andP. Qed. Lemma in_on1lP : {in D1, {on D2, allQ1l f & h}} <-> {in [pred x in D1 | f x \in D2], allQ1l f h}. Proof. split => allf x; have := allf x; rewrite inE => Q1f; first by case/andP. by move=> ? ?; apply: Q1f; apply/andP. Qed. Lemma in_on2P : {in D1 &, {on D2 &, allQ2 f}} <-> {in [pred x in D1 | f x \in D2] &, allQ2 f}. Proof. split => allf x y; have := allf x y; rewrite !inE => Q2f. by move=> /andP[? ?] /andP[? ?]; apply: Q2f. by move=> ? ? ? ?; apply: Q2f; apply/andP. Qed. Lemma on1W_in : {in D1, allQ1 f} -> {in D1, {on D2, allQ1 f}}. Proof. by move=> D1f ? /D1f. Qed. Lemma on1lW_in : {in D1, allQ1l f h} -> {in D1, {on D2, allQ1l f & h}}. Proof. by move=> D1f ? /D1f. Qed. Lemma on2W_in : {in D1 &, allQ2 f} -> {in D1 &, {on D2 &, allQ2 f}}. Proof. by move=> D1f ? ? ? ? ? ?; apply: D1f. Qed. Lemma in_on1W : allQ1 f -> {in D1, {on D2, allQ1 f}}. Proof. by move=> allf ? ? ?; apply: allf. Qed. Lemma in_on1lW : allQ1l f h -> {in D1, {on D2, allQ1l f & h}}. Proof. by move=> allf ? ? ?; apply: allf. Qed. Lemma in_on2W : allQ2 f -> {in D1 &, {on D2 &, allQ2 f}}. Proof. by move=> allf ? ? ? ? ? ?; apply: allf. Qed. Lemma on1S : (forall x, f x \in D2) -> {on D2, allQ1 f} -> allQ1 f. Proof. by move=> ? fD1 ?; apply: fD1. Qed. Lemma on1lS : (forall x, f x \in D2) -> {on D2, allQ1l f & h} -> allQ1l f h. Proof. by move=> ? fD1 ?; apply: fD1. Qed. Lemma on2S : (forall x, f x \in D2) -> {on D2 &, allQ2 f} -> allQ2 f. Proof. by move=> ? fD1 ? ?; apply: fD1. Qed. Lemma on1S_in : {homo f : x / x \in D1 >-> x \in D2} -> {in D1, {on D2, allQ1 f}} -> {in D1, allQ1 f}. Proof. by move=> fD fD1 ? ?; apply/fD1/fD. Qed. Lemma on1lS_in : {homo f : x / x \in D1 >-> x \in D2} -> {in D1, {on D2, allQ1l f & h}} -> {in D1, allQ1l f h}. Proof. by move=> fD fD1 ? ?; apply/fD1/fD. Qed. Lemma on2S_in : {homo f : x / x \in D1 >-> x \in D2} -> {in D1 &, {on D2 &, allQ2 f}} -> {in D1 &, allQ2 f}. Proof. by move=> fD fD1 ? ? ? ?; apply: fD1 => //; apply: fD. Qed. Lemma in_on1S : (forall x, f x \in D2) -> {in T1, {on D2, allQ1 f}} -> allQ1 f. Proof. by move=> fD2 fD1 ?; apply: fD1. Qed. Lemma in_on1lS : (forall x, f x \in D2) -> {in T1, {on D2, allQ1l f & h}} -> allQ1l f h. Proof. by move=> fD2 fD1 ?; apply: fD1. Qed. Lemma in_on2S : (forall x, f x \in D2) -> {in T1 &, {on D2 &, allQ2 f}} -> allQ2 f. Proof. by move=> fD2 fD1 ? ?; apply: fD1. Qed. End LocalGlobal. Arguments in_on1P {T1 T2 D1 D2 f Q1}. Arguments in_on1lP {T1 T2 T3 D1 D2 f h Q1l}. Arguments in_on2P {T1 T2 D1 D2 f Q2}. Arguments on1W_in {T1 T2 D1} D2 {f Q1}. Arguments on1lW_in {T1 T2 T3 D1} D2 {f h Q1l}. Arguments on2W_in {T1 T2 D1} D2 {f Q2}. Arguments in_on1W {T1 T2} D1 D2 {f Q1}. Arguments in_on1lW {T1 T2 T3} D1 D2 {f h Q1l}. Arguments in_on2W {T1 T2} D1 D2 {f Q2}. Arguments on1S {T1 T2} D2 {f Q1}. Arguments on1lS {T1 T2 T3} D2 {f h Q1l}. Arguments on2S {T1 T2} D2 {f Q2}. Arguments on1S_in {T1 T2 D1} D2 {f Q1}. Arguments on1lS_in {T1 T2 T3 D1} D2 {f h Q1l}. Arguments on2S_in {T1 T2 D1} D2 {f Q2}. Arguments in_on1S {T1 T2} D2 {f Q1}. Arguments in_on1lS {T1 T2 T3} D2 {f h Q1l}. Arguments in_on2S {T1 T2} D2 {f Q2}. Lemma can_in_pcan [rT aT : Type] (A : {pred aT}) [f : aT -> rT] [g : rT -> aT] : {in A, cancel f g} -> {in A, pcancel f (fun y : rT => Some (g y))}. Proof. by move=> fK x Ax; rewrite fK. Qed. Lemma pcan_in_inj [rT aT : Type] [A : {pred aT}] [f : aT -> rT] [g : rT -> option aT] : {in A, pcancel f g} -> {in A &, injective f}. Proof. by move=> fK x y Ax Ay /(congr1 g); rewrite !fK// => -[]. Qed. Lemma in_inj_comp A B C (f : B -> A) (h : C -> B) (P : pred B) (Q : pred C) : {in P &, injective f} -> {in Q &, injective h} -> {homo h : x / Q x >-> P x} -> {in Q &, injective (f \o h)}. Proof. by move=> Pf Qh QP x y xQ yQ xy; apply Qh => //; apply Pf => //; apply QP. Qed. Lemma can_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C}) [f : B -> A] [h : C -> B] [f' : A -> B] [h' : B -> C] : {homo h : x / x \in D' >-> x \in D} -> {in D, cancel f f'} -> {in D', cancel h h'} -> {in D', cancel (f \o h) (h' \o f')}. Proof. by move=> hD fK hK c cD /=; rewrite fK ?hK ?hD. Qed. Lemma pcan_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C}) [f : B -> A] [h : C -> B] [f' : A -> option B] [h' : B -> option C] : {homo h : x / x \in D' >-> x \in D} -> {in D, pcancel f f'} -> {in D', pcancel h h'} -> {in D', pcancel (f \o h) (obind h' \o f')}. Proof. by move=> hD fK hK c cD /=; rewrite fK/= ?hK ?hD. Qed. Definition pred_oapp T (D : {pred T}) : pred (option T) := [pred x | oapp (mem D) false x]. Lemma ocan_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C}) [f : B -> option A] [h : C -> option B] [f' : A -> B] [h' : B -> C] : {homo h : x / x \in D' >-> x \in pred_oapp D} -> {in D, ocancel f f'} -> {in D', ocancel h h'} -> {in D', ocancel (obind f \o h) (h' \o f')}. Proof. move=> hD fK hK c cD /=; rewrite -[RHS]hK/=; case hcE : (h c) => [b|]//=. have bD : b \in D by have := hD _ cD; rewrite hcE inE. by rewrite -[b in RHS]fK; case: (f b) => //=; have /hK := cD; rewrite hcE. Qed. Section in_sig. Variables T1 T2 T3 : Type. Variables (D1 : {pred T1}) (D2 : {pred T2}) (D3 : {pred T3}). Variable P1 : T1 -> Prop. Variable P2 : T1 -> T2 -> Prop. Variable P3 : T1 -> T2 -> T3 -> Prop. Lemma in1_sig : {in D1, {all1 P1}} -> forall x : sig D1, P1 (sval x). Proof. by move=> DP [x Dx]; have := DP _ Dx. Qed. Lemma in2_sig : {in D1 & D2, {all2 P2}} -> forall (x : sig D1) (y : sig D2), P2 (sval x) (sval y). Proof. by move=> DP [x Dx] [y Dy]; have := DP _ _ Dx Dy. Qed. Lemma in3_sig : {in D1 & D2 & D3, {all3 P3}} -> forall (x : sig D1) (y : sig D2) (z : sig D3), P3 (sval x) (sval y) (sval z). Proof. by move=> DP [x Dx] [y Dy] [z Dz]; have := DP _ _ _ Dx Dy Dz. Qed. End in_sig. Arguments in1_sig {T1 D1 P1}. Arguments in2_sig {T1 T2 D1 D2 P2}. Arguments in3_sig {T1 T2 T3 D1 D2 D3 P3}. Lemma sub_in2 T d d' (P : T -> T -> Prop) : sub_mem d d' -> forall Ph : ph {all2 P}, prop_in2 d' Ph -> prop_in2 d Ph. Proof. by move=> /= sub_dd'; apply: sub_in11. Qed. Lemma sub_in3 T d d' (P : T -> T -> T -> Prop) : sub_mem d d' -> forall Ph : ph {all3 P}, prop_in3 d' Ph -> prop_in3 d Ph. Proof. by move=> /= sub_dd'; apply: sub_in111. Qed. Lemma sub_in12 T1 T d1 d1' d d' (P : T1 -> T -> T -> Prop) : sub_mem d1 d1' -> sub_mem d d' -> forall Ph : ph {all3 P}, prop_in12 d1' d' Ph -> prop_in12 d1 d Ph. Proof. by move=> /= sub1 sub; apply: sub_in111. Qed. Lemma sub_in21 T T3 d d' d3 d3' (P : T -> T -> T3 -> Prop) : sub_mem d d' -> sub_mem d3 d3' -> forall Ph : ph {all3 P}, prop_in21 d' d3' Ph -> prop_in21 d d3 Ph. Proof. by move=> /= sub sub3; apply: sub_in111. Qed. Lemma equivalence_relP_in T (R : rel T) (A : pred T) : {in A & &, equivalence_rel R} <-> {in A, reflexive R} /\ {in A &, forall x y, R x y -> {in A, R x =1 R y}}. Proof. split=> [eqiR | [Rxx trR] x y z *]; last by split=> [|/trR-> //]; apply: Rxx. by split=> [x Ax|x y Ax Ay Rxy z Az]; [rewrite (eqiR x x) | rewrite (eqiR x y)]. Qed. Section MonoHomoMorphismTheory. Variables (aT rT sT : Type) (f : aT -> rT) (g : rT -> aT). Variables (aP : pred aT) (rP : pred rT) (aR : rel aT) (rR : rel rT). Lemma monoW : {mono f : x / aP x >-> rP x} -> {homo f : x / aP x >-> rP x}. Proof. by move=> hf x ax; rewrite hf. Qed. Lemma mono2W : {mono f : x y / aR x y >-> rR x y} -> {homo f : x y / aR x y >-> rR x y}. Proof. by move=> hf x y axy; rewrite hf. Qed. Hypothesis fgK : cancel g f. Lemma homoRL : {homo f : x y / aR x y >-> rR x y} -> forall x y, aR (g x) y -> rR x (f y). Proof. by move=> Hf x y /Hf; rewrite fgK. Qed. Lemma homoLR : {homo f : x y / aR x y >-> rR x y} -> forall x y, aR x (g y) -> rR (f x) y. Proof. by move=> Hf x y /Hf; rewrite fgK. Qed. Lemma homo_mono : {homo f : x y / aR x y >-> rR x y} -> {homo g : x y / rR x y >-> aR x y} -> {mono g : x y / rR x y >-> aR x y}. Proof. move=> mf mg x y; case: (boolP (rR _ _))=> [/mg //|]. by apply: contraNF=> /mf; rewrite !fgK. Qed. Lemma monoLR : {mono f : x y / aR x y >-> rR x y} -> forall x y, rR (f x) y = aR x (g y). Proof. by move=> mf x y; rewrite -{1}[y]fgK mf. Qed. Lemma monoRL : {mono f : x y / aR x y >-> rR x y} -> forall x y, rR x (f y) = aR (g x) y. Proof. by move=> mf x y; rewrite -{1}[x]fgK mf. Qed. Lemma can_mono : {mono f : x y / aR x y >-> rR x y} -> {mono g : x y / rR x y >-> aR x y}. Proof. by move=> mf x y /=; rewrite -mf !fgK. Qed. End MonoHomoMorphismTheory. Section MonoHomoMorphismTheory_in. Variables (aT rT : predArgType) (f : aT -> rT) (g : rT -> aT). Variables (aD : {pred aT}) (rD : {pred rT}). Variable (aP : pred aT) (rP : pred rT) (aR : rel aT) (rR : rel rT). Lemma mono1W_in : {in aD, {mono f : x / aP x >-> rP x}} -> {in aD, {homo f : x / aP x >-> rP x}}. Proof. by move=> hf x hx ax; rewrite hf. Qed. #[deprecated(since="Coq 8.16", note="Use mono1W_in instead.")] Abbreviation mono2W_in := mono1W_in. Lemma monoW_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} -> {in aD &, {homo f : x y / aR x y >-> rR x y}}. Proof. by move=> hf x y hx hy axy; rewrite hf. Qed. Hypothesis fgK : {in rD, {on aD, cancel g & f}}. Hypothesis mem_g : {homo g : x / x \in rD >-> x \in aD}. Lemma homoRL_in : {in aD &, {homo f : x y / aR x y >-> rR x y}} -> {in rD & aD, forall x y, aR (g x) y -> rR x (f y)}. Proof. by move=> Hf x y hx hy /Hf; rewrite fgK ?mem_g// ?inE; apply. Qed. Lemma homoLR_in : {in aD &, {homo f : x y / aR x y >-> rR x y}} -> {in aD & rD, forall x y, aR x (g y) -> rR (f x) y}. Proof. by move=> Hf x y hx hy /Hf; rewrite fgK ?mem_g// ?inE; apply. Qed. Lemma homo_mono_in : {in aD &, {homo f : x y / aR x y >-> rR x y}} -> {in rD &, {homo g : x y / rR x y >-> aR x y}} -> {in rD &, {mono g : x y / rR x y >-> aR x y}}. Proof. move=> mf mg x y hx hy; case: (boolP (rR _ _))=> [/mg //|]; first exact. by apply: contraNF=> /mf; rewrite !fgK ?mem_g//; apply. Qed. Lemma monoLR_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} -> {in aD & rD, forall x y, rR (f x) y = aR x (g y)}. Proof. by move=> mf x y hx hy; rewrite -{1}[y]fgK ?mem_g// mf ?mem_g. Qed. Lemma monoRL_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} -> {in rD & aD, forall x y, rR x (f y) = aR (g x) y}. Proof. by move=> mf x y hx hy; rewrite -{1}[x]fgK ?mem_g// mf ?mem_g. Qed. Lemma can_mono_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} -> {in rD &, {mono g : x y / rR x y >-> aR x y}}. Proof. by move=> mf x y hx hy; rewrite -mf ?mem_g// !fgK ?mem_g. Qed. End MonoHomoMorphismTheory_in. Arguments homoRL_in {aT rT f g aD rD aR rR}. Arguments homoLR_in {aT rT f g aD rD aR rR}. Arguments homo_mono_in {aT rT f g aD rD aR rR}. Arguments monoLR_in {aT rT f g aD rD aR rR}. Arguments monoRL_in {aT rT f g aD rD aR rR}. Arguments can_mono_in {aT rT f g aD rD aR rR}. Section HomoMonoMorphismFlip. Variables (aT rT : Type) (aR : rel aT) (rR : rel rT) (f : aT -> rT). Variable (aD aD' : {pred aT}). Lemma homo_sym : {homo f : x y / aR x y >-> rR x y} -> {homo f : y x / aR x y >-> rR x y}. Proof. by move=> fR y x; apply: fR. Qed. Lemma mono_sym : {mono f : x y / aR x y >-> rR x y} -> {mono f : y x / aR x y >-> rR x y}. Proof. by move=> fR y x; apply: fR. Qed. Lemma homo_sym_in : {in aD &, {homo f : x y / aR x y >-> rR x y}} -> {in aD &, {homo f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed. Lemma mono_sym_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} -> {in aD &, {mono f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed. Lemma homo_sym_in11 : {in aD & aD', {homo f : x y / aR x y >-> rR x y}} -> {in aD' & aD, {homo f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed. Lemma mono_sym_in11 : {in aD & aD', {mono f : x y / aR x y >-> rR x y}} -> {in aD' & aD, {mono f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed. End HomoMonoMorphismFlip. Arguments homo_sym {aT rT} [aR rR f]. Arguments mono_sym {aT rT} [aR rR f]. Arguments homo_sym_in {aT rT} [aR rR f aD]. Arguments mono_sym_in {aT rT} [aR rR f aD]. Arguments homo_sym_in11 {aT rT} [aR rR f aD aD']. Arguments mono_sym_in11 {aT rT} [aR rR f aD aD']. Section CancelOn. Variables (aT rT : predArgType) (aD : {pred aT}) (rD : {pred rT}). Variables (f : aT -> rT) (g : rT -> aT). Lemma onW_can : cancel g f -> {on aD, cancel g & f}. Proof. by move=> fgK x xaD; apply: fgK. Qed. Lemma onW_can_in : {in rD, cancel g f} -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fgK x xrD xaD; apply: fgK. Qed. Lemma in_onW_can : cancel g f -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fgK x xrD xaD; apply: fgK. Qed. Lemma onS_can : (forall x, g x \in aD) -> {on aD, cancel g & f} -> cancel g f. Proof. by move=> mem_g fgK x; apply: fgK. Qed. Lemma onS_can_in : {homo g : x / x \in rD >-> x \in aD} -> {in rD, {on aD, cancel g & f}} -> {in rD, cancel g f}. Proof. by move=> mem_g fgK x x_rD; apply/fgK/mem_g. Qed. Lemma in_onS_can : (forall x, g x \in aD) -> {in rT, {on aD, cancel g & f}} -> cancel g f. Proof. by move=> mem_g fgK x; apply/fgK. Qed. End CancelOn. Arguments onW_can {aT rT} aD {f g}. Arguments onW_can_in {aT rT} aD {rD f g}. Arguments in_onW_can {aT rT} aD rD {f g}. Arguments onS_can {aT rT} aD {f g}. Arguments onS_can_in {aT rT} aD {rD f g}. Arguments in_onS_can {aT rT} aD {f g}. Section inj_can_sym_in_on. Variables (aT rT : predArgType) (aD : {pred aT}) (rD : {pred rT}). Variables (f : aT -> rT) (g : rT -> aT). Lemma inj_can_sym_in_on : {homo f : x / x \in aD >-> x \in rD} -> {in aD, {on rD, cancel f & g}} -> {in rD &, {on aD &, injective g}} -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fD fK gI x x_rD gx_aD; apply: gI; rewrite ?inE ?fK ?fD. Qed. Lemma inj_can_sym_on : {in aD, cancel f g} -> {on aD &, injective g} -> {on aD, cancel g & f}. Proof. by move=> fK gI x gx_aD; apply: gI; rewrite ?inE ?fK. Qed. Lemma inj_can_sym_in : {homo f \o g : x / x \in rD} -> {on rD, cancel f & g} -> {in rD &, injective g} -> {in rD, cancel g f}. Proof. by move=> fgD fK gI x x_rD; apply: gI; rewrite ?fK ?fgD. Qed. End inj_can_sym_in_on. Arguments inj_can_sym_in_on {aT rT aD rD f g}. Arguments inj_can_sym_on {aT rT aD f g}. Arguments inj_can_sym_in {aT rT rD f g}. rocq-9.2.0/theories/Corelib/ssr/ssrclasses.v000066400000000000000000000027051516144147600210670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) (** Compatibility layer for [under] and [setoid_rewrite]. Note: this file does not require [ssreflect]; it is both required by [ssrsetoid] and required by [ssrunder]. Redefine [Corelib.Classes.RelationClasses.Reflexive] here, so that doing [Require Import ssreflect] does not [Require Import RelationClasses], and conversely. **) Section Defs. Context {A : Type}. Class Reflexive (R : A -> A -> Prop) := reflexivity : forall x : A, R x x. End Defs. Register Reflexive as plugins.ssreflect.reflexive_type. Register reflexivity as plugins.ssreflect.reflexive_proof. #[global] Instance eq_Reflexive {A : Type} : Reflexive (@eq A) := @eq_refl A. #[global] Instance iff_Reflexive : Reflexive iff := iff_refl. rocq-9.2.0/theories/Corelib/ssr/ssreflect.v000066400000000000000000000750331516144147600207000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) Require Import ssrmatching. Declare ML Module "rocq-runtime.plugins.ssreflect". (** This file is the Gallina part of the ssreflect plugin implementation. Files that use the ssreflect plugin should always Require ssreflect and either Import ssreflect or Import ssreflect.SsrSyntax. Part of the contents of this file is technical and will only interest advanced developers; in addition the following are defined: #[#the str of v by f#]# == the Canonical s : str such that f s = v. #[#the str of v#]# == the Canonical s : str that coerces to v. argumentType c == the T such that c : forall x : T, P x. returnType c == the R such that c : T -> R. {type of c for s} == P s where c : forall x : T, P x. nonPropType == an interface for non-Prop Types: a nonPropType coerces to a Type, and only types that do _not_ have sort Prop are canonical nonPropType instances. This is useful for applied views (see mid-file comment). notProp T == the nonPropType instance for type T. phantom T v == singleton type with inhabitant Phantom T v. phant T == singleton type with inhabitant Phant v. =^~ r == the converse of rewriting rule r (e.g., in a rewrite multirule). unkeyed t == t, but treated as an unkeyed matching pattern by the ssreflect matching algorithm. nosimpl t == t, but on the right-hand side of Definition C := nosimpl disables expansion of C by /=. locked t == t, but locked t is not convertible to t. locked_with k t == t, but not convertible to t or locked_with k' t unless k = k' (with k : unit). Rocq type-checking will be much more efficient if locked_with with a bespoke k is used for sealed definitions. unlockable v == interface for sealed constant definitions of v. Unlockable def == the unlockable that registers def : C = v. #[#unlockable of C#]# == a clone for C of the canonical unlockable for the definition of C (e.g., if it uses locked_with). #[#unlockable fun C#]# == #[#unlockable of C#]# with the expansion forced to be an explicit lambda expression. -> The usage pattern for ADT operations is: Definition foo_def x1 .. xn := big_foo_expression. Fact foo_key : unit. Proof. by #[# #]#. Qed. Definition foo := locked_with foo_key foo_def. Canonical foo_unlockable := #[#unlockable fun foo#]#. This minimizes the comparison overhead for foo, while still allowing rewrite unlock to expose big_foo_expression. #[#elaborate x#]# == triggers Rocq elaboration to fill the holes of the term x The main use case is to trigger typeclass inference in the body of a ssreflect have := #[#elaborate body#]#. Additionally we provide default intro pattern ltac views: - top of the stack actions: => /#[#apply#]# := => hyp {}/hyp => /#[#swap#]# := => x y; move: y x (also swap and preserves let bindings) => /#[#dup#]# := => x; have copy := x; move: copy x (also copies and preserves let bindings) - calling rewrite from an intro pattern, use with parsimony: => /#[#1! rules#]# := rewrite rules => /#[#! rules#]# := rewrite !rules More information about these definitions and their use can be found in the ssreflect manual, and in specific comments below. **) Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Module SsrSyntax. (** Declare Ssr keywords: "is" "isn't" "of" "//" "/=" and "//=". **) Reserved Notation "(* x 'is' y 'of' z 'isn't' // /= //= *)". (** Enable SSR features **) #[export] Set SSR Loaded. Reserved Notation "" (at level 0, n at level 0, format ""). #[warning="-postfix-notation-not-level-1"] Reserved Notation "T (* n *)" (at level 200, format "T (* n *)"). End SsrSyntax. Export SsrMatchingSyntax. Export SsrSyntax. (** Save primitive notation that will be overloaded. **) Local Abbreviation RocqGenericIf c vT vF := (if c then vT else vF) (only parsing). Local Abbreviation RocqGenericDependentIf c x R vT vF := (if c as x return R then vT else vF) (only parsing). (** Reserve notation that introduced in this file. **) Reserved Notation "'if' c 'then' vT 'else' vF" (at level 200, c, vT, vF at level 200). Reserved Notation "'if' c 'return' R 'then' vT 'else' vF" (at level 200, c, R, vT, vF at level 200). Reserved Notation "'if' c 'as' x 'return' R 'then' vT 'else' vF" (at level 200, c, R, vT, vF at level 200, x name). Reserved Notation "[ 'the' sT 'of' v 'by' f ]" (at level 0, format "[ 'the' sT 'of' v 'by' f ]"). Reserved Notation "[ 'the' sT 'of' v ]" (at level 0, format "[ 'the' sT 'of' v ]"). Reserved Notation "{ 'type' 'of' c 'for' s }" (at level 0, format "{ 'type' 'of' c 'for' s }"). Reserved Notation "=^~ r" (at level 100, format "=^~ r"). Reserved Notation "[ 'unlockable' 'of' C ]" (at level 0, format "[ 'unlockable' 'of' C ]"). Reserved Notation "[ 'unlockable' 'fun' C ]" (at level 0, format "[ 'unlockable' 'fun' C ]"). Reserved Notation "[ 'elaborate' x ]" (at level 0). (** To define notations for tactic in intro patterns. When "=> /t" is parsed, "t:%ssripat" is actually interpreted. **) Declare Scope ssripat_scope. Delimit Scope ssripat_scope with ssripat. (** Make the general "if" into a notation, so that we can override it below. The notations are "only parsing" because the Rocq decompiler will not recognize the expansion of the boolean if; using the default printer avoids a spurious trailing %%GEN_IF. **) Declare Scope general_if_scope. Delimit Scope general_if_scope with GEN_IF. Notation "'if' c 'then' vT 'else' vF" := (RocqGenericIf c vT vF) (only parsing) : general_if_scope. Notation "'if' c 'return' R 'then' vT 'else' vF" := (RocqGenericDependentIf c c R vT vF) (only parsing) : general_if_scope. Notation "'if' c 'as' x 'return' R 'then' vT 'else' vF" := (RocqGenericDependentIf c x R vT vF) (only parsing) : general_if_scope. (** Force boolean interpretation of simple if expressions. **) Declare Scope boolean_if_scope. Delimit Scope boolean_if_scope with BOOL_IF. Notation "'if' c 'return' R 'then' vT 'else' vF" := (if c is true as c in bool return R then vT else vF) : boolean_if_scope. Notation "'if' c 'then' vT 'else' vF" := (if c%bool is true as _ in bool return _ then vT else vF) : boolean_if_scope. Notation "'if' c 'as' x 'return' R 'then' vT 'else' vF" := (if c%bool is true as x in bool return R then vT else vF) : boolean_if_scope. Open Scope boolean_if_scope. (** To allow a wider variety of notations without reserving a large number of of identifiers, the ssreflect library systematically uses "forms" to enclose complex mixfix syntax. A "form" is simply a mixfix expression enclosed in square brackets and introduced by a keyword: #[#keyword ... #]# Because the keyword follows a bracket it does not need to be reserved. Non-ssreflect libraries that do not respect the form syntax (e.g., the Rocq Lists library) should be loaded before ssreflect so that their notations do not mask all ssreflect forms. **) Declare Scope form_scope. Delimit Scope form_scope with FORM. Open Scope form_scope. (** Constants for abstract: and #[#: name #]# intro pattern **) Definition abstract_lock := unit. Definition abstract_key := tt. Definition abstract (statement : Type) (id : nat) (lock : abstract_lock) := let: tt := lock in statement. Declare Scope ssr_scope. Notation "" := (abstract _ n _) : ssr_scope. Notation "T (* n *)" := (abstract T n abstract_key) : ssr_scope. Open Scope ssr_scope. Register abstract_lock as plugins.ssreflect.abstract_lock. Register abstract_key as plugins.ssreflect.abstract_key. Register abstract as plugins.ssreflect.abstract. (** Constants for tactic-views **) Inductive external_view : Type := tactic_view of Type. (** Syntax for referring to canonical structures: #[#the struct_type of proj_val by proj_fun#]# This form denotes the Canonical instance s of the Structure type struct_type whose proj_fun projection is proj_val, i.e., such that proj_fun s = proj_val. Typically proj_fun will be A record field accessors of struct_type, but this need not be the case; it can be, for instance, a field of a record type to which struct_type coerces; proj_val will likewise be coerced to the return type of proj_fun. In all but the simplest cases, proj_fun should be eta-expanded to allow for the insertion of implicit arguments. In the common case where proj_fun itself is a coercion, the "by" part can be omitted entirely; in this case it is inferred by casting s to the inferred type of proj_val. Obviously the latter can be fixed by using an explicit cast on proj_val, and it is highly recommended to do so when the return type intended for proj_fun is "Type", as the type inferred for proj_val may vary because of sort polymorphism (it could be Set or Prop). Note when using the #[#the _ of _ #]# form to generate a substructure from a telescopes-style canonical hierarchy (implementing inheritance with coercions), one should always project or coerce the value to the BASE structure, because Rocq will only find a Canonical derived structure for the Canonical base structure -- not for a base structure that is specific to proj_value. **) Module TheCanonical. Variant put vT sT (v1 v2 : vT) (s : sT) : Prop := Put. Definition get vT sT v s (p : @put vT sT v v s) := let: Put _ _ _ := p in s. Definition get_by vT sT of sT -> vT := @get vT sT. End TheCanonical. Import TheCanonical. (* Note: no export. *) Local Arguments get_by _%_type_scope _%_type_scope _ _ _ _. Notation "[ 'the' sT 'of' v 'by' f ]" := (@get_by _ sT f _ _ ((fun v' (s : sT) => Put v' (f s) s) v _)) (only parsing) : form_scope. Notation "[ 'the' sT 'of' v ]" := (get ((fun s : sT => Put v (*coerce*) s s) _)) (only parsing) : form_scope. (** The following are "format only" versions of the above notations. We need to do this to prevent the formatter from being be thrown off by application collapsing, coercion insertion and beta reduction in the right hand side of the notations above. **) Notation "[ 'the' sT 'of' v 'by' f ]" := (@get_by _ sT f v _ _) (only printing) : form_scope. Notation "[ 'the' sT 'of' v ]" := (@get _ sT v _ _) (only printing) : form_scope. (** We would like to recognize Notation " #[# 'the' sT 'of' v : 'Type' #]#" := (@get Type sT v _ _) (at level 0, format " #[# 'the' sT 'of' v : 'Type' #]#") : form_scope. **) (** Helper notation for canonical structure inheritance support. This is a workaround for the poor interaction between delta reduction and canonical projections in Rocq's unification algorithm, by which transparent definitions hide canonical instances, i.e., in Canonical a_type_struct := @Struct a_type ... Definition my_type := a_type. my_type doesn't effectively inherit the struct structure from a_type. Our solution is to redeclare the instance as follows Canonical my_type_struct := Eval hnf in #[#struct of my_type#]#. The special notation #[#str of _ #]# must be defined for each Structure "str" with constructor "Str", typically as follows Definition clone_str s := let: Str _ x y ... z := s return {type of Str for s} -> str in fun k => k _ x y ... z. Notation " #[# 'str' 'of' T 'for' s #]#" := (@clone_str s (@Str T)) (at level 0, format " #[# 'str' 'of' T 'for' s #]#") : form_scope. Notation " #[# 'str' 'of' T #]#" := (repack_str (fun x => @Str T x)) (at level 0, format " #[# 'str' 'of' T #]#") : form_scope. The notation for the match return predicate is defined below; the eta expansion in the second form serves both to distinguish it from the first and to avoid the delta reduction problem. There are several variations on the notation and the definition of the the "clone" function, for telescopes, mixin classes, and join (multiple inheritance) classes. We describe a different idiom for clones in ssrfun; it uses phantom types (see below) and static unification; see fintype and ssralg for examples. **) Definition argumentType T P & forall x : T, P x := T. Definition dependentReturnType T P & forall x : T, P x := P. Definition returnType aT rT & aT -> rT := rT. Notation "{ 'type' 'of' c 'for' s }" := (dependentReturnType c s) : type_scope. (** A generic "phantom" type (actually, a unit type with a phantom parameter). This type can be used for type definitions that require some Structure on one of their parameters, to allow Rocq to infer said structure so it does not have to be supplied explicitly or via the " #[#the _ of _ #]#" notation (the latter interacts poorly with other Notation). The definition of a (co)inductive type with a parameter p : p_type, that needs to use the operations of a structure Structure p_str : Type := p_Str {p_repr :> p_type; p_op : p_repr -> ...} should be given as Inductive indt_type (p : p_str) := Indt ... . Definition indt_of (p : p_str) & phantom p_type p := indt_type p. Notation "{ 'indt' p }" := (indt_of (Phantom p)). Definition indt p x y ... z : {indt p} := @Indt p x y ... z. Notation " #[# 'indt' x y ... z #]#" := (indt x y ... z). That is, the concrete type and its constructor should be shadowed by definitions that use a phantom argument to infer and display the true value of p (in practice, the "indt" constructor often performs additional functions, like "locking" the representation -- see below). We also define a simpler version ("phant" / "Phant") of phantom for the common case where p_type is Type. **) Variant phantom T (p : T) : Prop := Phantom. Arguments phantom : clear implicits. Arguments Phantom : clear implicits. Variant phant (p : Type) : Prop := Phant. (** Internal tagging used by the implementation of the ssreflect elim. **) Definition protect_term (A : Type) (x : A) : A := x. Register protect_term as plugins.ssreflect.protect_term. (** The ssreflect idiom for a non-keyed pattern: - unkeyed t will match any subterm that unifies with t, regardless of whether it displays the same head symbol as t. - unkeyed t a b will match any application of a term f unifying with t, to two arguments unifying with a and b, respectively, regardless of apparent head symbols. - unkeyed x where x is a variable will match any subterm with the same type as x (when x would raise the 'indeterminate pattern' error). **) Abbreviation unkeyed x := (let flex := x in flex). (** Ssreflect converse rewrite rule rule idiom. **) Definition ssr_converse R (r : R) := (Logic.I, r). Notation "=^~ r" := (ssr_converse r) : form_scope. (** Term tagging (user-level). The ssreflect library uses four strengths of term tagging to restrict convertibility during type checking: nosimpl t simplifies to t EXCEPT in a definition; more precisely, given Definition foo := nosimpl bar, foo (or foo t') will NOT be expanded by the /= and //= switches unless it is in a forcing context (e.g., in match foo t' with ... end, foo t' will be reduced if this allows the match to be reduced). Note that nosimpl bar is simply notation for a a term that beta-iota reduces to bar; hence rewrite /foo will replace foo by bar, and rewrite -/foo will replace bar by foo. CAVEAT: nosimpl should not be used inside a Section, because the end of section "cooking" removes the iota redex. locked t is provably equal to t, but is not convertible to t; 'locked' provides support for selective rewriting, via the lock t : t = locked t Lemma, and the ssreflect unlock tactic. locked_with k t is equal but not convertible to t, much like locked t, but supports explicit tagging with a value k : unit. This is used to mitigate a flaw in the term comparison heuristic of the Rocq kernel, which treats all terms of the form locked t as equal and compares their arguments recursively, leading to an exponential blowup of comparison. For this reason locked_with should be used rather than locked when defining ADT operations. The unlock tactic does not support locked_with but the unlock rewrite rule does, via the unlockable interface. we also use Module Type ascription to create truly opaque constants, because simple expansion of constants to reveal an unreducible term doubles the time complexity of a negative comparison. Such opaque constants can be expanded generically with the unlock rewrite rule. See the definition of card and subset in fintype for examples of this. **) Abbreviation nosimpl t := (let: tt := tt in t). Lemma master_key : unit. Proof. exact tt. Qed. Definition locked A := let: tt := master_key in fun x : A => x. Register master_key as plugins.ssreflect.master_key. Register locked as plugins.ssreflect.locked. Lemma lock A x : x = locked x :> A. Proof. unlock; reflexivity. Qed. (** The basic closing tactic "done". **) Ltac done := trivial; hnf; intros; solve [ do ![solve [trivial | simple refine (@sym_equal _ _ _ _); trivial] | discriminate | contradiction | split] | match goal with H : ~ _ |- _ => solve [case H; trivial] end ]. (** Quicker done tactic not including split, syntax: /0/ **) Ltac ssrdone0 := trivial; hnf; intros; solve [ do ![solve [trivial | apply: sym_equal; trivial] | discriminate | contradiction ] | match goal with H : ~ _ |- _ => solve [case H; trivial] end ]. (** To unlock opaque constants. **) #[universes(template)] Structure unlockable T v := Unlockable {unlocked : T; _ : unlocked = v}. Lemma unlock T x C : @unlocked T x C = x. Proof. by case: C. Qed. Notation "[ 'unlockable' 'of' C ]" := (@Unlockable _ _ C (unlock _)) : form_scope. Notation "[ 'unlockable' 'fun' C ]" := (@Unlockable _ (fun _ => _) C (unlock _)) : form_scope. (** Generic keyed constant locking. **) (** The argument order ensures that k is always compared before T. **) Definition locked_with k := let: tt := k in fun T x => x : T. (** This can be used as a cheap alternative to cloning the unlockable instance below, but with caution as unkeyed matching can be expensive. **) Lemma locked_withE T k x : unkeyed (locked_with k x) = x :> T. Proof. by case: k. Qed. (** Intensionaly, this instance will not apply to locked u. **) Canonical locked_with_unlockable T k x := @Unlockable T x (locked_with k x) (locked_withE k x). (** More accurate variant of unlock, and safer alternative to locked_withE. **) Lemma unlock_with T k x : unlocked (locked_with_unlockable k x) = x :> T. Proof. exact: unlock. Qed. (** Abbreviation to trigger Rocq elaboration to fill the holes **) Notation "[ 'elaborate' x ]" := (ltac:(refine x)) (only parsing). (** The internal lemmas for the have tactics. **) Lemma ssr_have (Plemma : Prop) (Pgoal : Prop) (step : Plemma) (rest : Plemma -> Pgoal) : Pgoal. Proof. exact: rest step. Qed. Register ssr_have as plugins.ssreflect.ssr_have. Polymorphic Lemma ssr_have_upoly@{s1 s2;u1 u2} (Plemma : Type@{s1;u1}) (Pgoal : Type@{s2;u2}) (step : Plemma) (rest : Plemma -> Pgoal) : Pgoal. Proof. exact: rest step. Qed. Register ssr_have_upoly as plugins.ssreflect.ssr_have_upoly. (** Internal N-ary congruence lemmas for the congr tactic. **) Fixpoint nary_congruence_statement (n : nat) : (forall B, (B -> B -> Prop) -> Prop) -> Prop := match n with | O => fun k => forall B, k B (fun x1 x2 : B => x1 = x2) | S n' => let k' A B e (f1 f2 : A -> B) := forall x1 x2, x1 = x2 -> (e (f1 x1) (f2 x2) : Prop) in fun k => forall A, nary_congruence_statement n' (fun B e => k _ (k' A B e)) end. Lemma nary_congruence n (k := fun B e => forall y : B, (e y y : Prop)) : nary_congruence_statement n k. Proof. have: k _ _ := _; rewrite {1}/k. elim: n k => [|n IHn] k k_P /= A; first exact: k_P. by apply: IHn => B e He; apply: k_P => f x1 x2 <-. Qed. Lemma ssr_congr_arrow Plemma Pgoal : Plemma = Pgoal -> Plemma -> Pgoal. Proof. by move->. Qed. Arguments ssr_congr_arrow : clear implicits. Register nary_congruence as plugins.ssreflect.nary_congruence. Register ssr_congr_arrow as plugins.ssreflect.ssr_congr_arrow. (** View lemmas that don't use reflection. **) Section ApplyIff. Variables P Q : Prop. Hypothesis eqPQ : P <-> Q. Lemma iffLR : P -> Q. Proof. by case: eqPQ. Qed. Lemma iffRL : Q -> P. Proof. by case: eqPQ. Qed. Lemma iffLRn : ~P -> ~Q. Proof. by move=> nP tQ; case: nP; case: eqPQ tQ. Qed. Lemma iffRLn : ~Q -> ~P. Proof. by move=> nQ tP; case: nQ; case: eqPQ tP. Qed. End ApplyIff. Hint View for move/ iffLRn|2 iffRLn|2 iffLR|2 iffRL|2. Hint View for apply/ iffRLn|2 iffLRn|2 iffRL|2 iffLR|2. (** To focus non-ssreflect tactics on a subterm, eg vm_compute. Usage: elim/abstract_context: (pattern) => G defG. vm_compute; rewrite {}defG {G}. Note that vm_cast are not stored in the proof term for reductions occurring in the context, hence set here := pattern; vm_compute in (value of here) blows up at Qed time. **) Lemma abstract_context T (P : T -> Type) x : (forall Q, Q = P -> Q x) -> P x. Proof. by move=> /(_ P); apply. Qed. (*****************************************************************************) (* Material for under/over (to rewrite under binders using "context lemmas") *) Require Export ssrunder. #[global] Hint Extern 0 (@Under_rel.Over_rel _ _ _ _) => solve [ apply: Under_rel.over_rel_done ] : core. #[global] Hint Resolve Under_rel.over_rel_done : core. Register Under_rel.Under_rel as plugins.ssreflect.Under_rel. Register Under_rel.Under_rel_from_rel as plugins.ssreflect.Under_rel_from_rel. (** Closing rewrite rule *) Definition over := over_rel. (** Closing tactic *) Ltac over := by [ apply: Under_rel.under_rel_done | rewrite over ]. (** Convenience rewrite rule to unprotect evars, e.g., to instantiate them in another way than with reflexivity. *) Definition UnderE := Under_relE. (*****************************************************************************) (** An interface for non-Prop types; used to avoid improper instantiation of polymorphic lemmas with on-demand implicits when they are used as views. For example: Some_inj {T} : forall x y : T, Some x = Some y -> x = y. Using move/Some_inj on a goal of the form Some n = Some 0 will fail: SSReflect will interpret the view as @Some_inj ?T _top_assumption_ since this is the well-typed application of the view with the minimal number of inserted evars (taking ?T := Some n = Some 0), and then will later complain that it cannot erase _top_assumption_ after having abstracted the viewed assumption. Making x and y maximal implicits would avoid this and force the intended @Some_inj nat x y _top_assumption_ interpretation, but is undesirable as it makes it harder to use Some_inj with the many SSReflect and MathComp lemmas that have an injectivity premise. Specifying {T : nonPropType} solves this more elegantly, as then (?T : Type) no longer unifies with (Some n = Some 0), which has sort Prop. **) Module NonPropType. (** Implementation notes: We rely on three interface Structures: - test_of r, the middle structure, performs the actual check: it has two canonical instances whose 'condition' projection are maybeProj (?P : Prop) and tt, and which set r := true and r := false, respectively. Unifying condition (?t : test_of ?r) with maybeProj T will thus set ?r to true if T is in Prop as the test_Prop T instance will apply, and otherwise simplify maybeProp T to tt and use the test_negative instance and set ?r to false. - call_of c r sets up a call to test_of on condition c with expected result r. It has a default instance for its 'callee' projection to Type, which sets c := maybeProj T and r := false when unifying with a type T. - type is a telescope on call_of c r, which checks that unifying test_of ?r1 with c indeed sets ?r1 := r; the type structure bundles the 'test' instance and its 'result' value along with its call_of c r projection. The default instance essentially provides eta-expansion for 'type'. This is only essential for the first 'result' projection to bool; using the instance for other projection merely avoids spurious delta expansions that would spoil the notProp T notation. In detail, unifying T =~= ?S with ?S : nonPropType, i.e., (1) T =~= @callee (@condition (result ?S) (test ?S)) (result ?S) (frame ?S) first uses the default call instance with ?T := T to reduce (1) to (2a) @condition (result ?S) (test ?S) =~= maybeProp T (3) result ?S =~= false (4) frame ?S =~= call T along with some trivial universe-related checks which are irrelevant here. Then the unification tries to use the test_Prop instance to reduce (2a) to (6a) result ?S =~= true (7a) ?P =~= T with ?P : Prop (8a) test ?S =~= test_Prop ?P Now the default 'check' instance with ?result := true resolves (6a) as (9a) ?S := @check true ?test ?frame Then (7a) can be solved precisely if T has sort at most (hence exactly) Prop, and then (8a) is solved by the check instance, yielding ?test := test_Prop T, and completing the solution of (2a), and _committing_ to it. But now (3) is inconsistent with (9a), and this makes the entire problem (1) fails. If on the other hand T does not have sort Prop then (7a) fails and the unification resorts to delta expanding (2a), which gives (2b) @condition (result ?S) (test ?S) =~= tt which is then reduced, using the test_negative instance, to (6b) result ?S =~= false (8b) test ?S =~= test_negative Both are solved using the check default instance, as in the (2a) branch, giving (9b) ?S := @check false test_negative ?frame Then (3) and (4) are similarly solved using check, giving the final assignment (9) ?S := notProp T Observe that we _must_ perform the actual test unification on the arguments of the initial canonical instance, and not on the instance itself as we do in mathcomp/matrix and mathcomp/vector, because we want the unification to fail when T has sort Prop. If both the test_of _and_ the result check unifications were done as part of the structure telescope then the latter would be a sub-problem of the former, and thus failing the check would merely make the test_of unification backtrack and delta-expand and we would not get failure. **) Structure call_of (condition : unit) (result : bool) := Call {callee : Type}. Definition maybeProp (T : Type) := tt. Definition call T := Call (maybeProp T) false T. Structure test_of (result : bool) := Test {condition :> unit}. Definition test_Prop (P : Prop) := Test true (maybeProp P). Definition test_negative := Test false tt. Structure type := Check {result : bool; test : test_of result; frame : call_of test result}. Definition check result test frame := @Check result test frame. Module Exports. Canonical call. Canonical test_Prop. Canonical test_negative. Canonical check. Abbreviation nonPropType := type. Coercion callee : call_of >-> Sortclass. Coercion frame : type >-> call_of. Abbreviation notProp T := (@check false test_negative (call T)). End Exports. End NonPropType. Export NonPropType.Exports. Module Export ipat. Notation "'[' 'apply' ']'" := (ltac:(let f := fresh "_top_" in move=> f {}/f)) (at level 0, only parsing) : ssripat_scope. (* we try to preserve the naming by matching the names from the goal *) (* we do move to perform a hnf before trying to match *) Notation "'[' 'swap' ']'" := (ltac:(move; let x := lazymatch goal with | |- forall (x : _), _ => fresh x | |- let x := _ in _ => fresh x | _ => fresh "_top_" end in intro x; move; let y := lazymatch goal with | |- forall (y : _), _ => fresh y | |- let y := _ in _ => fresh y | _ => fresh "_top_" end in intro y; revert x; revert y)) (at level 0, only parsing) : ssripat_scope. (* we try to preserve the naming by matching the names from the goal *) (* we do move to perform a hnf before trying to match *) Notation "'[' 'dup' ']'" := (ltac:(move; lazymatch goal with | |- forall (x : _), _ => let x := fresh x in intro x; let copy := fresh x in have copy := x; revert x; revert copy | |- let x := _ in _ => let x := fresh x in intro x; let copy := fresh x in pose copy := x; do [unfold x in (value of copy)]; revert x; revert copy | |- _ => let x := fresh "_top_" in move=> x; let copy := fresh "_top" in have copy := x; revert x; revert copy end)) (at level 0, only parsing) : ssripat_scope. Notation "'[' '1' '!' rules ']'" := (ltac:(rewrite rules)) (at level 0, rules at level 200, only parsing) : ssripat_scope. Notation "'[' '!' rules ']'" := (ltac:(rewrite !rules)) (at level 0, rules at level 200, only parsing) : ssripat_scope. End ipat. (* A class to trigger reduction by rewriting. *) (* Usage: rewrite [pattern]vm_compute. *) (* Alternatively one may redefine a lemma as in algebra/rat.v : *) (* Lemma rat_vm_compute n (x : rat) : vm_compute_eq n%:Q x -> n%:Q = x. *) (* Proof. exact. Qed. *) Class vm_compute_eq {T : Type} (x y : T) := vm_compute : x = y. #[global] Hint Extern 0 (@vm_compute_eq _ _ _) => vm_compute; reflexivity : typeclass_instances. rocq-9.2.0/theories/Corelib/ssr/ssrfun.v000066400000000000000000001064101516144147600202200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) Require Import ssreflect. (** This file contains the basic definitions and notations for working with functions. The definitions provide for: - Pair projections: p.1 == first element of a pair p.2 == second element of a pair These notations also apply to p : P /\ Q, via an and >-> pair coercion. - Simplifying functions, beta-reduced by /= and simpl: #[#fun : T => E#]# == constant function from type T that returns E #[#fun x => E#]# == unary function #[#fun x : T => E#]# == unary function with explicit domain type #[#fun x y => E#]# == binary function #[#fun x y : T => E#]# == binary function with common domain type #[#fun (x : T) y => E#]# \ #[#fun (x : xT) (y : yT) => E#]# | == binary function with (some) explicit, #[#fun x (y : T) => E#]# / independent domain types for each argument - Partial functions using option type: oapp f d ox == if ox is Some x returns f x, d otherwise odflt d ox == if ox is Some x returns x, d otherwise obind f ox == if ox is Some x returns f x, None otherwise omap f ox == if ox is Some x returns Some (f x), None otherwise olift f := Some \o f - Singleton types: all_equal_to x0 == x0 is the only value in its type, so any such value can be rewritten to x0. - A generic wrapper type: wrapped T == the inductive type with values Wrap x for x : T. unwrap w == the projection of w : wrapped T on T. wrap x == the canonical injection of x : T into wrapped T; it is equivalent to Wrap x, but is declared as a (default) Canonical Structure, which lets the Rocq HO unification automatically expand x into unwrap (wrap x). The delta reduction of wrap x to Wrap can be exploited to introduce controlled nondeterminism in Canonical Structure inference, as in the implementation of the mxdirect predicate in matrix.v. - The empty type: void == a notation for the Empty_set type of the standard library. of_void T == the canonical injection void -> T. - Sigma types: tag w == the i of w : {i : I & T i}. tagged w == the T i component of w : {i : I & T i}. Tagged T x == the {i : I & T i} with component x : T i. tag2 w == the i of w : {i : I & T i & U i}. tagged2 w == the T i component of w : {i : I & T i & U i}. tagged2' w == the U i component of w : {i : I & T i & U i}. Tagged2 T U x y == the {i : I & T i} with components x : T i and y : U i. sval u == the x of u : {x : T | P x}. s2val u == the x of u : {x : T | P x & Q x}. The properties of sval u, s2val u are given by lemmas svalP, s2valP, and s2valP'. We provide coercions sigT2 >-> sigT and sig2 >-> sig >-> sigT. A suite of lemmas (all_sig, ...) let us skolemize sig, sig2, sigT, sigT2 and pair, e.g., have /all_sig#[#f fP#]# (x : T): {y : U | P y} by ... yields an f : T -> U such that fP : forall x, P (f x). - Identity functions: id == NOTATION for the explicit identity function fun x => x. @id T == notation for the explicit identity at type T. idfun == an expression with a head constant, convertible to id; idfun x simplifies to x. @idfun T == the expression above, specialized to type T. phant_id x y == the function type phantom _ x -> phantom _ y. *** In addition to their casual use in functional programming, identity functions are often used to trigger static unification as part of the construction of dependent Records and Structures. For example, if we need a structure sT over a type T, we take as arguments T, sT, and a "dummy" function T -> sort sT: Definition foo T sT & T -> sort sT := ... We can avoid specifying sT directly by calling foo (@id T), or specify the call completely while still ensuring the consistency of T and sT, by calling @foo T sT idfun. The phant_id type allows us to extend this trick to non-Type canonical projections. It also allows us to sidestep dependent type constraints when building explicit records, e.g., given Record r := R {x; y : T(x)}. if we need to build an r from a given y0 while inferring some x0, such that y0 : T(x0), we pose Definition mk_r .. y .. (x := ...) y' & phant_id y y' := R x y'. Calling @mk_r .. y0 .. id will cause Rocq to use y' := y0, while checking the dependent type constraint y0 : T(x0). - Extensional equality for functions and relations (i.e. functions of two arguments): f1 =1 f2 == f1 x is equal to f2 x for all x. f1 =1 f2 :> A == ... and f2 is explicitly typed. f1 =2 f2 == f1 x y is equal to f2 x y for all x y. f1 =2 f2 :> A == ... and f2 is explicitly typed. - Composition for total and partial functions: f^~ y == function f with second argument specialised to y, i.e., fun x => f x y CAVEAT: conditional (non-maximal) implicit arguments of f are NOT inserted in this context @^~ x == application at x, i.e., fun f => f x #[#eta f#]# == the explicit eta-expansion of f, i.e., fun x => f x CAVEAT: conditional (non-maximal) implicit arguments of f are NOT inserted in this context. fun=> v := the constant function fun _ => v. f1 \o f2 == composition of f1 and f2. Note: (f1 \o f2) x simplifies to f1 (f2 x). f1 \; f2 == categorical composition of f1 and f2. This expands to to f2 \o f1 and (f1 \; f2) x simplifies to f2 (f1 x). pcomp f1 f2 == composition of partial functions f1 and f2. - Properties of functions: injective f <-> f is injective. injective2 f <-> f(x,y) is injective. cancel f g <-> g is a left inverse of f / f is a right inverse of g. pcancel f g <-> g is a left inverse of f where g is partial. ocancel f g <-> g is a left inverse of f where f is partial. bijective f <-> f is bijective (has a left and right inverse). involutive f <-> f is involutive. - Properties for operations. left_id e op <-> e is a left identity for op (e op x = x). right_id e op <-> e is a right identity for op (x op e = x). left_inverse e inv op <-> inv is a left inverse for op wrt identity e, i.e., (inv x) op x = e. right_inverse e inv op <-> inv is a right inverse for op wrt identity e i.e., x op (i x) = e. self_inverse e op <-> each x is its own op-inverse (x op x = e). idempotent_op op <-> op is idempotent for op (x op x = x). idempotent_fun f <-> f is idempotent (i.e., f \o f =1 f). associative op <-> op is associative, i.e., x op (y op z) = (x op y) op z. commutative op <-> op is commutative (x op y = y op x). left_commutative op <-> op is left commutative, i.e., x op (y op z) = y op (x op z). right_commutative op <-> op is right commutative, i.e., (x op y) op z = (x op z) op y. left_zero z op <-> z is a left zero for op (z op x = z). right_zero z op <-> z is a right zero for op (x op z = z). left_distributive op1 op2 <-> op1 distributes over op2 to the left: (x op2 y) op1 z = (x op1 z) op2 (y op1 z). right_distributive op1 op2 <-> op distributes over add to the right: x op1 (y op2 z) = (x op1 z) op2 (x op1 z). interchange op1 op2 <-> op1 and op2 satisfy an interchange law: (x op2 y) op1 (z op2 t) = (x op1 z) op2 (y op1 t). Note that interchange op op is a commutativity property. left_injective op <-> op is injective in its left argument: x op y = z op y -> x = z. right_injective op <-> op is injective in its right argument: x op y = x op z -> y = z. left_loop inv op <-> op, inv obey the inverse loop left axiom: (inv x) op (x op y) = y for all x, y, i.e., op (inv x) is always a left inverse of op x rev_left_loop inv op <-> op, inv obey the inverse loop reverse left axiom: x op ((inv x) op y) = y, for all x, y. right_loop inv op <-> op, inv obey the inverse loop right axiom: (x op y) op (inv y) = x for all x, y. rev_right_loop inv op <-> op, inv obey the inverse loop reverse right axiom: (x op (inv y)) op y = x for all x, y. Note that familiar "cancellation" identities like x + y - y = x or x - y + y = x are respectively instances of right_loop and rev_right_loop The corresponding lemmas will use the K and NK/VK suffixes, respectively. - Morphisms for functions and relations: {morph f : x / a >-> r} <-> f is a morphism with respect to functions (fun x => a) and (fun x => r); if r == R#[#x#]#, this states that f a = R#[#f x#]# for all x. {morph f : x / a} <-> f is a morphism with respect to the function expression (fun x => a). This is shorthand for {morph f : x / a >-> a}; note that the two instances of a are often interpreted at different types. {morph f : x y / a >-> r} <-> f is a morphism with respect to functions (fun x y => a) and (fun x y => r). {morph f : x y / a} <-> f is a morphism with respect to the function expression (fun x y => a). {homo f : x / a >-> r} <-> f is a homomorphism with respect to the predicates (fun x => a) and (fun x => r); if r == R#[#x#]#, this states that a -> R#[#f x#]# for all x. {homo f : x / a} <-> f is a homomorphism with respect to the predicate expression (fun x => a). {homo f : x y / a >-> r} <-> f is a homomorphism with respect to the relations (fun x y => a) and (fun x y => r). {homo f : x y / a} <-> f is a homomorphism with respect to the relation expression (fun x y => a). {mono f : x / a >-> r} <-> f is monotone with respect to projectors (fun x => a) and (fun x => r); if r == R#[#x#]#, this states that R#[#f x#]# = a for all x. {mono f : x / a} <-> f is monotone with respect to the projector expression (fun x => a). {mono f : x y / a >-> r} <-> f is monotone with respect to relators (fun x y => a) and (fun x y => r). {mono f : x y / a} <-> f is monotone with respect to the relator expression (fun x y => a). The file also contains some basic lemmas for the above concepts. Lemmas relative to cancellation laws use some abbreviated suffixes: K - a cancellation rule like esymK : cancel (@esym T x y) (@esym T y x). LR - a lemma moving an operation from the left hand side of a relation to the right hand side, like canLR: cancel g f -> x = g y -> f x = y. RL - a lemma moving an operation from the right to the left, e.g., canRL. Beware that the LR and RL orientations refer to an "apply" (back chaining) usage; when using the same lemmas with "have" or "move" (forward chaining) the directions will be reversed!. **) Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. (** Parsing / printing declarations. *) Reserved Notation "f ^~ y" (at level 10, y at level 8, no associativity, format "f ^~ y"). Reserved Notation "@^~ x" (at level 10, x at level 8, no associativity, format "@^~ x"). Reserved Notation "[ 'eta' f ]" (at level 0, format "[ 'eta' f ]"). Reserved Notation "'fun' => E" (at level 200, format "'fun' => E"). Reserved Notation "[ 'fun' : T => E ]" (at level 0, format "'[hv' [ 'fun' : T => '/ ' E ] ']'"). Reserved Notation "[ 'fun' x => E ]" (at level 0, x name, format "'[hv' [ 'fun' x => '/ ' E ] ']'"). Reserved Notation "[ 'fun' x : T => E ]" (at level 0, x name, format "'[hv' [ 'fun' x : T => '/ ' E ] ']'"). Reserved Notation "[ 'fun' x y => E ]" (at level 0, x name, y name, format "'[hv' [ 'fun' x y => '/ ' E ] ']'"). Reserved Notation "[ 'fun' x y : T => E ]" (at level 0, x name, y name, format "'[hv' [ 'fun' x y : T => '/ ' E ] ']'"). Reserved Notation "[ 'fun' ( x : T ) y => E ]" (at level 0, x name, y name, format "'[hv' [ 'fun' ( x : T ) y => '/ ' E ] ']'"). Reserved Notation "[ 'fun' x ( y : T ) => E ]" (at level 0, x name, y name, format "'[hv' [ 'fun' x ( y : T ) => '/ ' E ] ']'"). Reserved Notation "[ 'fun' ( x : T ) ( y : U ) => E ]" (at level 0, x name, y name, format "[ 'fun' ( x : T ) ( y : U ) => E ]" ). Reserved Notation "f =1 g" (at level 70, no associativity). Reserved Notation "f =1 g :> A" (at level 70, g at next level, A at level 90). Reserved Notation "f =2 g" (at level 70, no associativity). Reserved Notation "f =2 g :> A" (at level 70, g at next level, A at level 90). Reserved Notation "f \o g" (at level 50, format "f \o '/ ' g"). Reserved Notation "f \; g" (at level 60, right associativity, format "f \; '/ ' g"). Reserved Notation "{ 'morph' f : x / a >-> r }" (at level 0, f at level 99, x name, format "{ 'morph' f : x / a >-> r }"). Reserved Notation "{ 'morph' f : x / a }" (at level 0, f at level 99, x name, format "{ 'morph' f : x / a }"). Reserved Notation "{ 'morph' f : x y / a >-> r }" (at level 0, f at level 99, x name, y name, format "{ 'morph' f : x y / a >-> r }"). Reserved Notation "{ 'morph' f : x y / a }" (at level 0, f at level 99, x name, y name, format "{ 'morph' f : x y / a }"). Reserved Notation "{ 'homo' f : x / a >-> r }" (at level 0, f at level 99, x name, format "{ 'homo' f : x / a >-> r }"). Reserved Notation "{ 'homo' f : x / a }" (at level 0, f at level 99, x name, format "{ 'homo' f : x / a }"). Reserved Notation "{ 'homo' f : x y / a >-> r }" (at level 0, f at level 99, x name, y name, format "{ 'homo' f : x y / a >-> r }"). Reserved Notation "{ 'homo' f : x y / a }" (at level 0, f at level 99, x name, y name, format "{ 'homo' f : x y / a }"). Reserved Notation "{ 'homo' f : x y /~ a }" (at level 0, f at level 99, x name, y name, format "{ 'homo' f : x y /~ a }"). Reserved Notation "{ 'mono' f : x / a >-> r }" (at level 0, f at level 99, x name, format "{ 'mono' f : x / a >-> r }"). Reserved Notation "{ 'mono' f : x / a }" (at level 0, f at level 99, x name, format "{ 'mono' f : x / a }"). Reserved Notation "{ 'mono' f : x y / a >-> r }" (at level 0, f at level 99, x name, y name, format "{ 'mono' f : x y / a >-> r }"). Reserved Notation "{ 'mono' f : x y / a }" (at level 0, f at level 99, x name, y name, format "{ 'mono' f : x y / a }"). Reserved Notation "{ 'mono' f : x y /~ a }" (at level 0, f at level 99, x name, y name, format "{ 'mono' f : x y /~ a }"). Reserved Notation "@ 'id' T" (at level 10, T at level 8, format "@ 'id' T"). #[warning="-closed-notation-not-level-0"] Reserved Notation "@ 'sval'" (at level 10, format "@ 'sval'"). (** Syntax for defining auxiliary recursive function. Usage: Section FooDefinition. Variables (g1 : T1) (g2 : T2). (globals) Fixoint foo_auxiliary (a3 : T3) ... := body, using #[#rec e3, ... #]# for recursive calls where " #[# 'rec' a3 , a4 , ... #]#" := foo_auxiliary. Definition foo x y .. := #[#rec e1, ... #]#. + proofs about foo End FooDefinition. **) Reserved Notation "[ 'rec' a ]" (at level 0, format "[ 'rec' a ]"). Reserved Notation "[ 'rec' a , b ]" (at level 0, format "[ 'rec' a , b ]"). Reserved Notation "[ 'rec' a , b , c ]" (at level 0, format "[ 'rec' a , b , c ]"). Reserved Notation "[ 'rec' a , b , c , d ]" (at level 0, format "[ 'rec' a , b , c , d ]"). Reserved Notation "[ 'rec' a , b , c , d , e ]" (at level 0, format "[ 'rec' a , b , c , d , e ]"). Reserved Notation "[ 'rec' a , b , c , d , e , f ]" (at level 0, format "[ 'rec' a , b , c , d , e , f ]"). Reserved Notation "[ 'rec' a , b , c , d , e , f , g ]" (at level 0, format "[ 'rec' a , b , c , d , e , f , g ]"). Reserved Notation "[ 'rec' a , b , c , d , e , f , g , h ]" (at level 0, format "[ 'rec' a , b , c , d , e , f , g , h ]"). Reserved Notation "[ 'rec' a , b , c , d , e , f , g , h , i ]" (at level 0, format "[ 'rec' a , b , c , d , e , f , g , h , i ]"). Reserved Notation "[ 'rec' a , b , c , d , e , f , g , h , i , j ]" (at level 0, format "[ 'rec' a , b , c , d , e , f , g , h , i , j ]"). Declare Scope pair_scope. Delimit Scope pair_scope with PAIR. Open Scope pair_scope. (** Notations for pair/conjunction projections **) Notation "p .1" := (fst p) : pair_scope. Notation "p .2" := (snd p) : pair_scope. Coercion pair_of_and P Q (PandQ : P /\ Q) := (proj1 PandQ, proj2 PandQ). Definition all_pair I T U (w : forall i : I, T i * U i) := (fun i => (w i).1, fun i => (w i).2). (** Complements on the option type constructor, used below to encode partial functions. **) Module Option. Definition apply aT rT (f : aT -> rT) x u := if u is Some y then f y else x. Definition default T := apply (fun x : T => x). Definition bind aT rT (f : aT -> option rT) := apply f None. Definition map aT rT (f : aT -> rT) := bind (fun x => Some (f x)). Definition lift aT rT (f : aT -> rT) := fun x => Some (f x). End Option. Abbreviation oapp := Option.apply. Abbreviation odflt := Option.default. Abbreviation obind := Option.bind. Abbreviation omap := Option.map. Abbreviation olift := Option.lift. Abbreviation some := (@Some _) (only parsing). (** Shorthand for some basic equality lemmas. **) Abbreviation erefl := refl_equal. Abbreviation ecast i T e x := (let: erefl in _ = i := e return T in x). Definition esym := sym_eq. Definition nesym := sym_not_eq. Definition etrans := trans_eq. Definition congr1 := f_equal. Definition congr2 := f_equal2. (** Force at least one implicit when used as a view. **) Prenex Implicits esym nesym. (** A predicate for singleton types. **) Definition all_equal_to T (x0 : T) := forall x, unkeyed x = x0. Lemma unitE : all_equal_to tt. Proof. by case. Qed. (** A generic wrapper type **) #[universes(template)] Structure wrapped T := Wrap {unwrap : T}. Canonical wrap T x := @Wrap T x. Prenex Implicits unwrap wrap Wrap. Delimit Scope function_scope with FUN. Open Scope function_scope. (** Notations for argument transpose **) Notation "f ^~ y" := (fun x => f x y) : function_scope. Notation "@^~ x" := (fun f => f x) : function_scope. (** Definitions and notation for explicit functions with simplification, i.e., which simpl and /= beta expand (this is complementary to nosimpl). **) #[universes(template)] Variant simpl_fun (aT rT : Type) := SimplFun of aT -> rT. Section SimplFun. Variables aT rT : Type. Definition fun_of_simpl (f : simpl_fun aT rT) := fun x => let: SimplFun lam := f in lam x. End SimplFun. Coercion fun_of_simpl : simpl_fun >-> Funclass. Notation "[ 'fun' : T => E ]" := (SimplFun (fun _ : T => E)) : function_scope. Notation "[ 'fun' x => E ]" := (SimplFun (fun x => E)) : function_scope. Notation "[ 'fun' x y => E ]" := (fun x => [fun y => E]) : function_scope. Notation "[ 'fun' x : T => E ]" := (SimplFun (fun x : T => E)) (only parsing) : function_scope. Notation "[ 'fun' x y : T => E ]" := (fun x : T => [fun y : T => E]) (only parsing) : function_scope. Notation "[ 'fun' ( x : T ) y => E ]" := (fun x : T => [fun y => E]) (only parsing) : function_scope. Notation "[ 'fun' x ( y : T ) => E ]" := (fun x => [fun y : T => E]) (only parsing) : function_scope. Notation "[ 'fun' ( x : T ) ( y : U ) => E ]" := (fun x : T => [fun y : U => E]) (only parsing) : function_scope. (** For delta functions in eqtype.v. **) Definition SimplFunDelta aT rT (f : aT -> aT -> rT) := [fun z => f z z]. (** Extensional equality, for unary and binary functions, including syntactic sugar. **) Section ExtensionalEquality. Variables A B C : Type. Definition eqfun (f g : B -> A) : Prop := forall x, f x = g x. Definition eqrel (r s : C -> B -> A) : Prop := forall x y, r x y = s x y. Lemma frefl f : eqfun f f. Proof. by []. Qed. Lemma fsym f g : eqfun f g -> eqfun g f. Proof. by move=> eq_fg x. Qed. Lemma ftrans f g h : eqfun f g -> eqfun g h -> eqfun f h. Proof. by move=> eq_fg eq_gh x; rewrite eq_fg. Qed. Lemma rrefl r : eqrel r r. Proof. by []. Qed. End ExtensionalEquality. Global Typeclasses Opaque eqfun eqrel. #[global] Hint Resolve frefl rrefl : core. Notation "f1 =1 f2" := (eqfun f1 f2) : type_scope. Notation "f1 =1 f2 :> A" := (f1 =1 (f2 : A)) : type_scope. Notation "f1 =2 f2" := (eqrel f1 f2) : type_scope. Notation "f1 =2 f2 :> A" := (f1 =2 (f2 : A)) : type_scope. Section Composition. Variables A B C : Type. Definition comp (f : B -> A) (g : C -> B) x := f (g x). Definition catcomp g f := comp f g. Definition pcomp (f : B -> option A) (g : C -> option B) x := obind f (g x). Lemma eq_comp f f' g g' : f =1 f' -> g =1 g' -> comp f g =1 comp f' g'. Proof. by move=> eq_ff' eq_gg' x; rewrite /comp eq_gg' eq_ff'. Qed. End Composition. Arguments comp {A B C} f g x /. Arguments catcomp {A B C} g f x /. Notation "f1 \o f2" := (comp f1 f2) : function_scope. Notation "f1 \; f2" := (catcomp f1 f2) : function_scope. Lemma compA {A B C D : Type} (f : B -> A) (g : C -> B) (h : D -> C) : f \o (g \o h) = (f \o g) \o h. Proof. by []. Qed. Notation "[ 'eta' f ]" := (fun x => f x) : function_scope. Notation "'fun' => E" := (fun _ => E) : function_scope. Abbreviation id := (fun x => x). Notation "@ 'id' T" := (fun x : T => x) (only parsing) : function_scope. Definition idfun T x : T := x. Arguments idfun {T} x /. Definition phant_id T1 T2 v1 v2 := phantom T1 v1 -> phantom T2 v2. Section OptionTheory. Variables (aT rT sT : Type) (f : aT -> rT) (g : rT -> sT). Lemma obindEapp (fo : aT -> option rT) : obind fo = oapp fo None. Proof. by []. Qed. Lemma omapEbind : omap f = obind (olift f). Proof. by []. Qed. Lemma omap_id (x : option rT) : omap id x = x. Proof. by case: x. Qed. Lemma eq_omap (h : aT -> rT) : f =1 h -> omap f =1 omap h. Proof. by move=> Ef [?|] //=; rewrite Ef. Qed. Lemma omapEapp : omap f = oapp (olift f) None. Proof. by []. Qed. Lemma oappEmap (y0 : rT) x : oapp f y0 x = odflt y0 (omap f x). Proof. by case: x. Qed. Lemma omap_comp : omap (g \o f) =1 omap g \o omap f. Proof. by case. Qed. Lemma oapp_comp x : oapp (g \o f) x =1 (@oapp _ _)^~ x g \o omap f. Proof. by case. Qed. Lemma oapp_comp_f (x : rT) : oapp (g \o f) (g x) =1 g \o oapp f x. Proof. by case. Qed. Lemma olift_comp : olift (g \o f) = olift g \o f. Proof. by []. Qed. End OptionTheory. (** The empty type. **) Abbreviation void := Empty_set. Definition of_void T (x : void) : T := match x with end. (** Strong sigma types. **) Section Tag. Variables (I : Type) (i : I) (T_ U_ : I -> Type). Definition tag := projT1. Definition tagged : forall w, T_(tag w) := @projT2 I [eta T_]. Definition Tagged x := @existT I [eta T_] i x. Definition tag2 (w : @sigT2 I T_ U_) := let: existT2 _ _ i _ _ := w in i. Definition tagged2 w : T_(tag2 w) := let: existT2 _ _ _ x _ := w in x. Definition tagged2' w : U_(tag2 w) := let: existT2 _ _ _ _ y := w in y. Definition Tagged2 x y := @existT2 I [eta T_] [eta U_] i x y. End Tag. Arguments Tagged [I i]. Arguments Tagged2 [I i]. Prenex Implicits tag tagged Tagged tag2 tagged2 tagged2' Tagged2. Coercion tag_of_tag2 I T_ U_ (w : @sigT2 I T_ U_) := Tagged (fun i => T_ i * U_ i)%type (tagged2 w, tagged2' w). Lemma all_tag I T U : (forall x : I, {y : T x & U x y}) -> {f : forall x, T x & forall x, U x (f x)}. Proof. by move=> fP; exists (fun x => tag (fP x)) => x; case: (fP x). Qed. Lemma all_tag2 I T U V : (forall i : I, {y : T i & U i y & V i y}) -> {f : forall i, T i & forall i, U i (f i) & forall i, V i (f i)}. Proof. by case/all_tag=> f /all_pair[]; exists f. Qed. (** Refinement types. **) (** Prenex Implicits and renaming. **) Abbreviation sval := (@proj1_sig _ _). Notation "@ 'sval'" := (@proj1_sig) (only parsing) : function_scope. Section Sig. Variables (T : Type) (P Q : T -> Prop). Lemma svalP (u : sig P) : P (sval u). Proof. by case: u. Qed. Definition s2val (u : sig2 P Q) := let: exist2 _ _ x _ _ := u in x. Lemma s2valP u : P (s2val u). Proof. by case: u. Qed. Lemma s2valP' u : Q (s2val u). Proof. by case: u. Qed. End Sig. Prenex Implicits svalP s2val s2valP s2valP'. Coercion tag_of_sig I P (u : @sig I P) := Tagged P (svalP u). Coercion sig_of_sig2 I P Q (u : @sig2 I P Q) := exist (fun i => P i /\ Q i) (s2val u) (conj (s2valP u) (s2valP' u)). Lemma all_sig I T P : (forall x : I, {y : T x | P x y}) -> {f : forall x, T x | forall x, P x (f x)}. Proof. by case/all_tag=> f; exists f. Qed. Lemma all_sig2 I T P Q : (forall x : I, {y : T x | P x y & Q x y}) -> {f : forall x, T x | forall x, P x (f x) & forall x, Q x (f x)}. Proof. by case/all_sig=> f /all_pair[]; exists f. Qed. Section Morphism. Variables (aT rT sT : Type) (f : aT -> rT). (** Morphism property for unary and binary functions **) Definition morphism_1 aF rF := forall x, f (aF x) = rF (f x). Definition morphism_2 aOp rOp := forall x y, f (aOp x y) = rOp (f x) (f y). (** Homomorphism property for unary and binary relations **) Definition homomorphism_1 (aP rP : _ -> Prop) := forall x, aP x -> rP (f x). Definition homomorphism_2 (aR rR : _ -> _ -> Prop) := forall x y, aR x y -> rR (f x) (f y). (** Stability property for unary and binary relations **) Definition monomorphism_1 (aP rP : _ -> sT) := forall x, rP (f x) = aP x. Definition monomorphism_2 (aR rR : _ -> _ -> sT) := forall x y, rR (f x) (f y) = aR x y. End Morphism. Notation "{ 'morph' f : x / a >-> r }" := (morphism_1 f (fun x => a) (fun x => r)) : type_scope. Notation "{ 'morph' f : x / a }" := (morphism_1 f (fun x => a) (fun x => a)) : type_scope. Notation "{ 'morph' f : x y / a >-> r }" := (morphism_2 f (fun x y => a) (fun x y => r)) : type_scope. Notation "{ 'morph' f : x y / a }" := (morphism_2 f (fun x y => a) (fun x y => a)) : type_scope. Notation "{ 'homo' f : x / a >-> r }" := (homomorphism_1 f (fun x => a) (fun x => r)) : type_scope. Notation "{ 'homo' f : x / a }" := (homomorphism_1 f (fun x => a) (fun x => a)) : type_scope. Notation "{ 'homo' f : x y / a >-> r }" := (homomorphism_2 f (fun x y => a) (fun x y => r)) : type_scope. Notation "{ 'homo' f : x y / a }" := (homomorphism_2 f (fun x y => a) (fun x y => a)) : type_scope. Notation "{ 'homo' f : x y /~ a }" := (homomorphism_2 f (fun y x => a) (fun x y => a)) : type_scope. Notation "{ 'mono' f : x / a >-> r }" := (monomorphism_1 f (fun x => a) (fun x => r)) : type_scope. Notation "{ 'mono' f : x / a }" := (monomorphism_1 f (fun x => a) (fun x => a)) : type_scope. Notation "{ 'mono' f : x y / a >-> r }" := (monomorphism_2 f (fun x y => a) (fun x y => r)) : type_scope. Notation "{ 'mono' f : x y / a }" := (monomorphism_2 f (fun x y => a) (fun x y => a)) : type_scope. Notation "{ 'mono' f : x y /~ a }" := (monomorphism_2 f (fun y x => a) (fun x y => a)) : type_scope. (** In an intuitionistic setting, we have two degrees of injectivity. The weaker one gives only simplification, and the strong one provides a left inverse (we show in `fintype' that they coincide for finite types). We also define an intermediate version where the left inverse is only a partial function. **) Section Injections. Variables (rT aT : Type) (f : aT -> rT). Definition injective := forall x1 x2, f x1 = f x2 -> x1 = x2. Definition cancel g := forall x, g (f x) = x. Definition pcancel g := forall x, g (f x) = Some x. Definition ocancel (g : aT -> option rT) h := forall x, oapp h x (g x) = x. Lemma can_pcan g : cancel g -> pcancel (fun y => Some (g y)). Proof. by move=> fK x; congr (Some _). Qed. Lemma pcan_inj g : pcancel g -> injective. Proof. by move=> fK x y /(congr1 g); rewrite !fK => [[]]. Qed. Lemma can_inj g : cancel g -> injective. Proof. by move/can_pcan; apply: pcan_inj. Qed. Lemma canLR g x y : cancel g -> x = f y -> g x = y. Proof. by move=> fK ->. Qed. Lemma canRL g x y : cancel g -> f x = y -> x = g y. Proof. by move=> fK <-. Qed. End Injections. Definition injective2 (rT aT1 aT2 : Type) (f : aT1 -> aT2 -> rT) := forall (x1 x2 : aT1) (y1 y2 : aT2), f x1 y1 = f x2 y2 -> (x1 = x2) * (y1 = y2). Arguments injective2 [rT aT1 aT2] f. Lemma Some_inj {T : nonPropType} : injective (@Some T). Proof. by move=> x y []. Qed. Lemma inj_omap {aT rT : Type} (f : aT -> rT) : injective f -> injective (omap f). Proof. by move=> injf [?|] [?|] //= [/injf->]. Qed. Lemma omapK {aT rT : Type} (f : aT -> rT) (g : rT -> aT) : cancel f g -> cancel (omap f) (omap g). Proof. by move=> fK [?|] //=; rewrite fK. Qed. Lemma of_voidK T : pcancel (of_void T) [fun _ => None]. Proof. by case. Qed. (** cancellation lemmas for dependent type casts. **) Lemma esymK T x y : cancel (@esym T x y) (@esym T y x). Proof. by case: y /. Qed. Lemma etrans_id T x y (eqxy : x = y :> T) : etrans (erefl x) eqxy = eqxy. Proof. by case: y / eqxy. Qed. Section InjectionsTheory. Variables (A B C : Type) (f g : B -> A) (h : C -> B). Lemma inj_id : injective (@id A). Proof. by []. Qed. Lemma inj_can_sym f' : cancel f f' -> injective f' -> cancel f' f. Proof. by move=> fK injf' x; apply: injf'. Qed. Lemma inj_comp : injective f -> injective h -> injective (f \o h). Proof. by move=> injf injh x y /injf; apply: injh. Qed. Lemma inj_compr : injective (f \o h) -> injective h. Proof. by move=> injfh x y /(congr1 f) /injfh. Qed. Lemma can_comp f' h' : cancel f f' -> cancel h h' -> cancel (f \o h) (h' \o f'). Proof. by move=> fK hK x; rewrite /= fK hK. Qed. Lemma pcan_pcomp f' h' : pcancel f f' -> pcancel h h' -> pcancel (f \o h) (pcomp h' f'). Proof. by move=> fK hK x; rewrite /pcomp fK /= hK. Qed. Lemma ocan_comp [fo : B -> option A] [ho : C -> option B] [f' : A -> B] [h' : B -> C] : ocancel fo f' -> ocancel ho h' -> ocancel (obind fo \o ho) (h' \o f'). Proof. move=> fK hK c /=; rewrite -[RHS]hK/=; case hcE : (ho c) => [b|]//=. by rewrite -[b in RHS]fK; case: (fo b) => //=; have := hK c; rewrite hcE. Qed. Lemma eq_inj : injective f -> f =1 g -> injective g. Proof. by move=> injf eqfg x y; rewrite -2!eqfg; apply: injf. Qed. Lemma eq_can f' g' : cancel f f' -> f =1 g -> f' =1 g' -> cancel g g'. Proof. by move=> fK eqfg eqfg' x; rewrite -eqfg -eqfg'. Qed. Lemma inj_can_eq f' : cancel f f' -> injective f' -> cancel g f' -> f =1 g. Proof. by move=> fK injf' gK x; apply: injf'; rewrite fK. Qed. End InjectionsTheory. Section Bijections. Variables (A B : Type) (f : B -> A). Variant bijective : Prop := Bijective g of cancel f g & cancel g f. Hypothesis bijf : bijective. Lemma bij_inj : injective f. Proof. by case: bijf => g fK _; apply: can_inj fK. Qed. Lemma bij_can_sym f' : cancel f' f <-> cancel f f'. Proof. split=> fK; first exact: inj_can_sym fK bij_inj. by case: bijf => h _ hK x; rewrite -[x]hK fK. Qed. Lemma bij_can_eq f' f'' : cancel f f' -> cancel f f'' -> f' =1 f''. Proof. by move=> fK fK'; apply: (inj_can_eq _ bij_inj); apply/bij_can_sym. Qed. End Bijections. Section BijectionsTheory. Variables (A B C : Type) (f : B -> A) (h : C -> B). Lemma eq_bij : bijective f -> forall g, f =1 g -> bijective g. Proof. by case=> f' fK f'K g eqfg; exists f'; eapply eq_can; eauto. Qed. Lemma bij_comp : bijective f -> bijective h -> bijective (f \o h). Proof. by move=> [f' fK f'K] [h' hK h'K]; exists (h' \o f'); apply: can_comp; auto. Qed. Lemma bij_can_bij : bijective f -> forall f', cancel f f' -> bijective f'. Proof. by move=> bijf; exists f; first by apply/(bij_can_sym bijf). Qed. End BijectionsTheory. Section Involutions. Variables (A : Type) (f : A -> A). Definition involutive := cancel f f. Hypothesis Hf : involutive. Lemma inv_inj : injective f. Proof. exact: can_inj Hf. Qed. Lemma inv_bij : bijective f. Proof. by exists f. Qed. End Involutions. Section OperationProperties. Variables S T R : Type. Section SopTisR. Implicit Type op : S -> T -> R. Definition left_inverse e inv op := forall x, op (inv x) x = e. Definition right_inverse e inv op := forall x, op x (inv x) = e. Definition left_injective op := forall x, injective (op^~ x). Definition right_injective op := forall y, injective (op y). End SopTisR. Section SopTisS. Implicit Type op : S -> T -> S. Definition right_id e op := forall x, op x e = x. Definition left_zero z op := forall x, op z x = z. Definition right_commutative op := forall x y z, op (op x y) z = op (op x z) y. Definition left_distributive op add := forall x y z, op (add x y) z = add (op x z) (op y z). Definition right_loop inv op := forall y, cancel (op^~ y) (op^~ (inv y)). Definition rev_right_loop inv op := forall y, cancel (op^~ (inv y)) (op^~ y). End SopTisS. Section SopTisT. Implicit Type op : S -> T -> T. Definition left_id e op := forall x, op e x = x. Definition right_zero z op := forall x, op x z = z. Definition left_commutative op := forall x y z, op x (op y z) = op y (op x z). Definition right_distributive op add := forall x y z, op x (add y z) = add (op x y) (op x z). Definition left_loop inv op := forall x, cancel (op x) (op (inv x)). Definition rev_left_loop inv op := forall x, cancel (op (inv x)) (op x). End SopTisT. Section SopSisT. Implicit Type op : S -> S -> T. Definition self_inverse e op := forall x, op x x = e. Definition commutative op := forall x y, op x y = op y x. End SopSisT. Section SopSisS. Implicit Type op : S -> S -> S. Definition idempotent_op op := forall x, op x x = x. Definition associative op := forall x y z, op x (op y z) = op (op x y) z. Definition interchange op1 op2 := forall x y z t, op1 (op2 x y) (op2 z t) = op2 (op1 x z) (op1 y t). End SopSisS. End OperationProperties. #[deprecated(since="9.1", use=idempotent_op)] Abbreviation idempotent:= idempotent_op (only parsing). Definition idempotent_fun (U : Type) (f : U -> U) := f \o f =1 f. Lemma inr_inj {A B} : injective (@inr A B). Proof. by move=> ? ? []. Qed. Lemma inl_inj {A B} : injective (@inl A B). Proof. by move=> ? ? []. Qed. rocq-9.2.0/theories/Corelib/ssr/ssrsetoid.v000066400000000000000000000030561516144147600207210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) (** Compatibility layer for [under] and [setoid_rewrite]. This file is intended to be required by [Require Import Setoid]. In particular, we can use the [under] tactic with other relations than [eq] or [iff], e.g. a [RewriteRelation], by doing: [Require Import ssreflect. Require Setoid.] This file's instances have priority 12 > other stdlib instances. (Note: this file could be skipped when porting [under] to stdlib2.) *) Require Import ssrclasses. Require Import ssrunder. Require Import RelationClasses. Require Import Relation_Definitions. (** Reconcile [Corelib.Classes.RelationClasses.Reflexive] with [Corelib.ssr.ssrclasses.Reflexive] *) #[global] Instance compat_Reflexive : forall {A} {R : relation A}, RelationClasses.Reflexive R -> ssrclasses.Reflexive R | 12. Proof. now trivial. Qed. rocq-9.2.0/theories/Corelib/ssr/ssrunder.v000066400000000000000000000056471516144147600205570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* .doc { font-family: monospace; white-space: pre; } # **) (** Constants for under/over, to rewrite under binders using "context lemmas" Note: this file does not require [ssreflect]; it is both required by [ssrsetoid] and *exported* by [ssrunder]. This preserves the following feature: we can use [Setoid] without requiring [ssreflect] and use [ssreflect] without requiring [Setoid]. *) Require Import ssrclasses. Module Type UNDER_REL. Parameter Under_rel : forall (A : Type) (eqA : A -> A -> Prop), A -> A -> Prop. Parameter Under_rel_from_rel : forall (A : Type) (eqA : A -> A -> Prop) (x y : A), @Under_rel A eqA x y -> eqA x y. Parameter Under_relE : forall (A : Type) (eqA : A -> A -> Prop), @Under_rel A eqA = eqA. (** [Over_rel, over_rel, over_rel_done]: for "by rewrite over_rel" *) Parameter Over_rel : forall (A : Type) (eqA : A -> A -> Prop), A -> A -> Prop. Parameter over_rel : forall (A : Type) (eqA : A -> A -> Prop) (x y : A), @Under_rel A eqA x y = @Over_rel A eqA x y. Parameter over_rel_done : forall (A : Type) (eqA : A -> A -> Prop) (EeqA : Reflexive eqA) (x : A), @Over_rel A eqA x x. (** [under_rel_done]: for Ltac-style over *) Parameter under_rel_done : forall (A : Type) (eqA : A -> A -> Prop) (EeqA : Reflexive eqA) (x : A), @Under_rel A eqA x x. Notation "''Under[' x ]" := (@Under_rel _ _ x _) (at level 0, format "''Under[' x ]", only printing). End UNDER_REL. Module Export Under_rel : UNDER_REL. Definition Under_rel (A : Type) (eqA : A -> A -> Prop) := eqA. Lemma Under_rel_from_rel : forall (A : Type) (eqA : A -> A -> Prop) (x y : A), @Under_rel A eqA x y -> eqA x y. Proof. now trivial. Qed. Lemma Under_relE (A : Type) (eqA : A -> A -> Prop) : @Under_rel A eqA = eqA. Proof. now trivial. Qed. Definition Over_rel := Under_rel. Lemma over_rel : forall (A : Type) (eqA : A -> A -> Prop) (x y : A), @Under_rel A eqA x y = @Over_rel A eqA x y. Proof. now trivial. Qed. Lemma over_rel_done : forall (A : Type) (eqA : A -> A -> Prop) (EeqA : Reflexive eqA) (x : A), @Over_rel A eqA x x. Proof. now unfold Over_rel. Qed. Lemma under_rel_done : forall (A : Type) (eqA : A -> A -> Prop) (EeqA : Reflexive eqA) (x : A), @Under_rel A eqA x x. Proof. now trivial. Qed. End Under_rel. rocq-9.2.0/theories/Corelib/ssrmatching/000077500000000000000000000000001516144147600202225ustar00rootroot00000000000000rocq-9.2.0/theories/Corelib/ssrmatching/ssrmatching.v000066400000000000000000000033131516144147600227330ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t) (only parsing) : ssrpatternscope. (* Some shortcuts for recurrent "X in t" parts. *) Abbreviation RHS := (X in _ = X)%pattern. Abbreviation LHS := (X in X = _)%pattern. End SsrMatchingSyntax. Export SsrMatchingSyntax. Tactic Notation "ssrpattern" ssrpatternarg(p) := ssrpattern p . rocq-9.2.0/theories/Ltac2/000077500000000000000000000000001516144147600152665ustar00rootroot00000000000000rocq-9.2.0/theories/Ltac2/Array.v000066400000000000000000000337051516144147600165430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a -> 'a array := "rocq-runtime.plugins.ltac2" "array_make". (** Return the length of an array. *) Ltac2 @external length : 'a array -> int := "rocq-runtime.plugins.ltac2" "array_length". (** [get arr i] returns the [i]-th element of [arr]. *) Ltac2 @external get : 'a array -> int -> 'a := "rocq-runtime.plugins.ltac2" "array_get". (** [set arr i x] replaces [arr[i]] with [x]. This modifies [arr] in place. *) Ltac2 @external set : 'a array -> int -> 'a -> unit := "rocq-runtime.plugins.ltac2" "array_set". (** [lowlevel_blit from fofs to tofs len] copies [from[fofs...fofs+len-1]] to [to[tofs...tofs+len-1]] (bounds included). This modifies [to] in place. Consider using [blit] for nicer error messages. *) Ltac2 @external lowlevel_blit : 'a array -> int -> 'a array -> int -> int -> unit := "rocq-runtime.plugins.ltac2" "array_blit". (** [lowlevel_fill arr ofs len x] replaces [arr[ofs]], [arr[ofs+1]], ..., [arr[ofs+len-1]] with [x]. This modifes [arr] in place. Consider using [fill] for nicer error messages. *) Ltac2 @external lowlevel_fill : 'a array -> int -> int -> 'a -> unit := "rocq-runtime.plugins.ltac2" "array_fill". (** [concat [a1 ; a2 ; ... ; aN]] returns the array [a1 ++ a2 ++ ... ++ an]. *) Ltac2 @external concat : ('a array) list -> 'a array := "rocq-runtime.plugins.ltac2" "array_concat". (** [lowlevel_sub arr ofs len] returns the subarray [arr[ofs...ofs+len-1]]. The result is allocated as a new array, i.e. is not aliased with [arr]. Consider using [sub] for nicer error messages. *) Ltac2 lowlevel_sub (arr : 'a array) (start : int) (len : int) : 'a array := let l := length arr in match Int.equal l 0 with | true => empty | false => let newarr:=make len (get arr 0) in lowlevel_blit arr start newarr 0 len; newarr end. (** [init n f] creates the array [| f 0 ; f 1 ; ... ; f (n-1) |]. *) Ltac2 init (l : int) (f : int -> 'a) : 'a array := let rec init_aux (dst : 'a array) (pos : int) (len : int) (f : int->'a) := match Int.equal len 0 with | true => () | false => set dst pos (f pos); init_aux dst (Int.add pos 1) (Int.sub len 1) f end in match Int.le l 0 with | true => empty | false => let arr:=make l (f 0) in init_aux arr 1 (Int.sub l 1) f; arr end. (** [make_matrix sx sy v] creates an array of size [sx] which contains array of size [sy], filled with [v]. *) Ltac2 make_matrix (sx : int) (sy : int) (v : 'a) : 'a array array := let initr _ := make sy v in init sx initr. (** Copy an array. The copied array can be modified without changing the original array (and vice versa). *) Ltac2 copy (a : 'a array) : 'a array := lowlevel_sub a 0 (length a). (** [append a1 a2] appends [a1] and [a2]. This allocates a new array, even if [a1] or [a2] is empty. *) Ltac2 append (a1 : 'a array) (a2 : 'a array) : 'a array := match Int.equal (length a1) 0 with | true => copy a2 | false => match Int.equal (length a2) 0 with | true => copy a1 | false => let newarr:=make (Int.add (length a1) (length a2)) (get a1 0) in lowlevel_blit a1 0 newarr 0 (length a1); lowlevel_blit a2 0 newarr (length a1) (length a2); newarr end end. (** [sub arr ofs len] returns the subarray [arr[ofs...ofs+len-1]]. The result is allocated as a new array, i.e. is not aliased with [arr]. *) Ltac2 sub (a : 'a array) (ofs : int) (len : int) : 'a array := Control.assert_valid_argument "Array.sub ofs<0" (Int.ge ofs 0); Control.assert_valid_argument "Array.sub len<0" (Int.ge len 0); Control.assert_bounds "Array.sub" (Int.le ofs (Int.sub (length a) len)); lowlevel_sub a ofs len. (** [fill arr ofs len x] replaces [arr[ofs]], [arr[ofs+1]], ..., [arr[ofs+len-1]] with [x]. This modifes [arr] in place. *) Ltac2 fill (a : 'a array) (ofs : int) (len : int) (v : 'a) : unit := Control.assert_valid_argument "Array.fill ofs<0" (Int.ge ofs 0); Control.assert_valid_argument "Array.fill len<0" (Int.ge len 0); Control.assert_bounds "Array.fill" (Int.le ofs (Int.sub (length a) len)); lowlevel_fill a ofs len v. (** [blit from fofs to tofs len] copies [from[fofs...fofs+len-1]] to [to[tofs...tofs+len-1]] (bounds included). This modifies [to] in place. *) Ltac2 blit (a1 : 'a array) (ofs1 : int) (a2 : 'a array) (ofs2 : int) (len : int) : unit := Control.assert_valid_argument "Array.blit ofs1<0" (Int.ge ofs1 0); Control.assert_valid_argument "Array.blit ofs2<0" (Int.ge ofs2 0); Control.assert_valid_argument "Array.blit len<0" (Int.ge len 0); Control.assert_bounds "Array.blit ofs1+len>len a1" (Int.le ofs1 (Int.sub (length a1) len)); Control.assert_bounds "Array.blit ofs2+len>len a2" (Int.le ofs2 (Int.sub (length a2) len)); lowlevel_blit a1 ofs1 a2 ofs2 len. (** Helper function for [iter]. *) Ltac2 rec iter_aux (f : 'a -> unit) (a : 'a array) (pos : int) (len : int) : unit := match Int.equal len 0 with | true => () | false => f (get a pos); iter_aux f a (Int.add pos 1) (Int.sub len 1) end. (** [iter f arr] calls [f] on every element of [arr], from first to last. *) Ltac2 iter (f : 'a -> unit) (a : 'a array) : unit := iter_aux f a 0 (length a). (** Helper function for [iter2]. *) Ltac2 rec iter2_aux (f : 'a -> 'b -> unit) (a : 'a array) (b : 'b array) (pos : int) (len : int) : unit := match Int.equal len 0 with | true => () | false => f (get a pos) (get b pos); iter2_aux f a b (Int.add pos 1) (Int.sub len 1) end. (** Same as [iter] but with two arrays. Throws an exception when the lengths of the arrays differ. *) Ltac2 rec iter2 (f : 'a -> 'b -> unit) (a : 'a array) (b : 'b array) : unit := Control.assert_valid_argument "Array.iter2" (Int.equal (length a) (length b)); iter2_aux f a b 0 (length a). (** Map a function over an array. Elements are processed from first to last. The result is allocated as a new array, i.e. it does not alias the original array. *) Ltac2 map (f : 'a -> 'b) (a : 'a array) : 'b array := init (length a) (fun i => f (get a i)). (** Same as [map] but with two arrays. Throws an exception when the lengths of the arrays differ. *) Ltac2 map2 (f : 'a -> 'b -> 'c) (a : 'a array) (b : 'b array) : 'c array := Control.assert_valid_argument "Array.map2" (Int.equal (length a) (length b)); init (length a) (fun i => f (get a i) (get b i)). (** Helper function for [iteri]. *) Ltac2 rec iteri_aux (f : int -> 'a -> unit) (a : 'a array) (pos : int) (len : int) : unit := match Int.equal len 0 with | true => () | false => f pos (get a pos); iteri_aux f a (Int.add pos 1) (Int.sub len 1) end. (** Iterate a function over an array, passing the index of each argument to the function. Elements are processed from first to last. *) Ltac2 iteri (f : int -> 'a -> unit) (a : 'a array) : unit := iteri_aux f a 0 (length a). (** Map a function over an array, passing the index of each argument to the function. Elements are processed from first to last. The result is allocated as a new array, i.e. it does not alias the original array. *) Ltac2 mapi (f : int -> 'a -> 'b) (a : 'a array) : 'b array := init (length a) (fun i => f i (get a i)). (** Helper function to [to_list]. *) Ltac2 rec to_list_aux (a : 'a array) (pos : int) (len : int) : 'a list := match Int.equal len 0 with | true => [] | false => get a pos :: to_list_aux a (Int.add pos 1) (Int.sub len 1) end. (** Convert an array to a list. *) Ltac2 to_list (a : 'a array) : 'a list := to_list_aux a 0 (length a). (** Helper function to [of_list]. *) Ltac2 rec of_list_aux (ls : 'a list) (dst : 'a array) (pos : int) : unit := match ls with | [] => () | hd::tl => set dst pos hd; of_list_aux tl dst (Int.add pos 1) end. (** Convert a list into an array. *) Ltac2 of_list (ls : 'a list) : 'a array := (* Don't use List.length here because the List module might depend on Array some day *) let rec list_length (ls : 'a list) := match ls with | [] => 0 | _ :: tl => Int.add 1 (list_length tl) end in match ls with | [] => empty | hd :: _ => let anew := make (list_length ls) hd in of_list_aux ls anew 0; anew end. (** Helper function for [fold_left]. *) Ltac2 rec fold_left_aux (f : 'a -> 'b -> 'a) (x : 'a) (a : 'b array) (pos : int) (len : int) : 'a := match Int.equal len 0 with | true => x | false => fold_left_aux f (f x (get a pos)) a (Int.add pos 1) (Int.sub len 1) end. (** Left fold over an array. *) Ltac2 fold_left (f : 'a -> 'b -> 'a) (x : 'a) (a : 'b array) : 'a := fold_left_aux f x a 0 (length a). (** Helper function for [fold_right]. *) Ltac2 rec fold_right_aux (f : 'a -> 'b -> 'b) (a : 'a array) (x : 'b) (pos : int) (len : int) : 'b := (* Note: one could compare pos<0. We keep an extra len parameter so that the function can be used for any sub array *) match Int.equal len 0 with | true => x | false => fold_right_aux f a (f (get a pos) x) (Int.sub pos 1) (Int.sub len 1) end. (** Right fold over an array. *) Ltac2 fold_right (f : 'a -> 'b -> 'b) (a : 'a array) (x : 'b) : 'b := fold_right_aux f a x (Int.sub (length a) 1) (length a). (** Helper function for [exist]. *) Ltac2 rec exist_aux (p : 'a -> bool) (a : 'a array) (pos : int) (len : int) : bool := match Int.equal len 0 with | true => false | false => match p (get a pos) with | true => true | false => exist_aux p a (Int.add pos 1) (Int.sub len 1) end end. (** [exist f arr] checks if [f] is true for _at least one_ element of [arr]. In particular [exist f empty] is [false]. We would call this [exists] a la OCaml's [List.exists], but that would be a syntax error (because it conflicts with the notation for tactic `exists`), so instead we name it exist. *) Ltac2 exist (p : 'a -> bool) (a : 'a array) : bool := exist_aux p a 0 (length a). (** Helper function for [for_all]. *) Ltac2 rec for_all_aux (p : 'a -> bool) (a : 'a array) (pos : int) (len : int) : bool := match Int.equal len 0 with | true => true | false => match p (get a pos) with | true => for_all_aux p a (Int.add pos 1) (Int.sub len 1) | false => false end end. (** [for_all f arr] checks if [f] is true for _all_ elements of [arr]. In particular [for_all f empty] is [true]. *) Ltac2 for_all (p : 'a -> bool) (a : 'a array) : bool := for_all_aux p a 0 (length a). (** [mem eq x arr] checks if an element of [arr] is equal to [x] according to the user-supplied equality function [eq] *) Ltac2 mem (eq : 'a -> 'a -> bool) (x : 'a) (a : 'a array) : bool := exist (eq x) a. (** Helper function for [for_all2]. *) Ltac2 rec for_all2_aux (p : 'a -> 'b -> bool) (a : 'a array) (b : 'b array) (pos : int) (len : int) : bool := if Int.equal len 0 then true else if p (get a pos) (get b pos) then for_all2_aux p a b (Int.add pos 1) (Int.sub len 1) else false. (** Same as [for_all] but for two lists. Throws an exception when the lengths of the lists differ. *) Ltac2 for_all2 (p : 'a -> 'b -> bool) (a : 'a array) (b : 'b array) : bool := let lena := length a in let lenb := length b in if Int.equal lena lenb then for_all2_aux p a b 0 lena else Control.throw_invalid_argument "Array.for_all2". (** Same as [for_all] but for two lists. Returns [false] when the lengths of the lists differ. *) Ltac2 equal (p : 'a -> 'b -> bool) (a : 'a array) (b : 'b array) : bool := let lena := length a in let lenb := length b in if Int.equal lena lenb then for_all2_aux p a b 0 lena else false. (** Reverse an array. The result is allocated as a new array, i.e. it does not alias the original array. *) Ltac2 rev (ar : 'a array) : 'a array := let len := length ar in init len (fun i => get ar (Int.sub (Int.sub len i) 1)). rocq-9.2.0/theories/Ltac2/Bool.v000066400000000000000000000035261516144147600163560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* y | false => false end. Ltac2 or x y := match x with | true => true | false => y end. Ltac2 impl x y := match x with | true => y | false => true end. Ltac2 neg x := match x with | true => false | false => true end. Ltac2 xor x y := match x with | true => match y with | true => false | false => true end | false => match y with | true => true | false => false end end. Ltac2 equal x y := match x with | true => match y with | true => true | false => false end | false => match y with | true => false | false => true end end. (** * Boolean operators with lazy evaluation of the second argument *) (** We place the notations in a separate module so that we can import them separately *) Module Export BoolNotations. Ltac2 Notation x(self) "&&" y(thunk(self)) : 2 := match x with | true => y () | false => false end. Ltac2 Notation x(self) "||" y(thunk(self)) : 3 := match x with | true => true | false => y () end. End BoolNotations. rocq-9.2.0/theories/Ltac2/Char.v000066400000000000000000000021371516144147600163350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* char := "rocq-runtime.plugins.ltac2" "char_of_int". (** Throws if the integer is not a valid char (in range [0-255]). *) Ltac2 @external to_int : char -> int := "rocq-runtime.plugins.ltac2" "char_to_int". Ltac2 equal (x : char) (y : char) : bool := Int.equal (to_int x) (to_int y). Ltac2 compare (x : char) (y : char) : int := Int.compare (to_int x) (to_int y). rocq-9.2.0/theories/Ltac2/Compat/000077500000000000000000000000001516144147600165115ustar00rootroot00000000000000rocq-9.2.0/theories/Ltac2/Compat/Coq818.v000066400000000000000000000003331516144147600176620ustar00rootroot00000000000000Local Set Warnings "-masking-absolute-name". Require Export Ltac2.Compat.Coq819. Require Ltac2.Array. Module Export Ltac2. Module Array. Export Ltac2.Array. Ltac2 empty () := empty. End Array. End Ltac2. rocq-9.2.0/theories/Ltac2/Compat/Coq819.v000066400000000000000000000000741516144147600176650ustar00rootroot00000000000000Require Ltac2.Init. #[export] Unset Ltac2 Typed Notations. rocq-9.2.0/theories/Ltac2/Constant.v000066400000000000000000000022461516144147600172520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* constant -> bool := "rocq-runtime.plugins.ltac2" "constant_equal". (** Constants obtained through module aliases or Include are not considered equal by this function. *) Ltac2 @external print : t -> message := "rocq-runtime.plugins.ltac2" "constant_print". (** Print the constant using the shortest qualified identifier which refers to it. Does not avoid variable names in the current or global environment. *) rocq-9.2.0/theories/Ltac2/Constr.v000066400000000000000000000547271516144147600167440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* constr := "rocq-runtime.plugins.ltac2" "constr_type". (** Return the type of a term *) Ltac2 @ external equal : constr -> constr -> bool := "rocq-runtime.plugins.ltac2" "constr_equal". (** Strict syntactic equality: only up to Ξ±-conversion and evar expansion *) Module Binder. Ltac2 Type relevance_var. Ltac2 Type relevance := [ Relevant | Irrelevant | RelevanceVar (relevance_var) ]. (** This type will eventually be removed in favour of Relevance.t as an abstract type. *) Ltac2 @ external make : ident option -> constr -> binder := "rocq-runtime.plugins.ltac2" "constr_binder_make". (** Create a binder given the name and the type of the bound variable. Fails if the type is not a type in the current goal. *) Ltac2 @ external unsafe_make : ident option -> relevance -> constr -> binder := "rocq-runtime.plugins.ltac2" "constr_binder_unsafe_make". (** Create a binder given the name and the type and relevance of the bound variable. *) Ltac2 @ external name : binder -> ident option := "rocq-runtime.plugins.ltac2" "constr_binder_name". (** Retrieve the name of a binder. *) Ltac2 @ external type : binder -> constr := "rocq-runtime.plugins.ltac2" "constr_binder_type". (** Retrieve the type of a binder. *) Ltac2 @ external relevance : binder -> relevance := "rocq-runtime.plugins.ltac2" "constr_binder_relevance". (** Retrieve the relevance of a binder. *) End Binder. Module Relevance. (** Type of proof relevance: relevant, irrelevant or a variable (either locally rigid variable from sort polymorphism, or unification variable from elaboration). *) Ltac2 Type t := Binder.relevance. (** Test equality of relevances in the current proof state (the proof state matters for unification sort variables, which may be instantiated). *) Ltac2 @external equal : t -> t -> bool := "rocq-runtime.plugins.ltac2" "constr_relevance_equal". Ltac2 @external relevant : t := "rocq-runtime.plugins.ltac2" "constr_relevance_relevant". Ltac2 @external irrelevant : t := "rocq-runtime.plugins.ltac2" "constr_relevance_irrelevant". End Relevance. Module Unsafe. (** Low-level access to kernel terms. Use with care! *) Ltac2 Type case. (** A value of [case] is data carried by a pattern match expression that contains a reference to the inductive type being matched on. Given an inductive type, one can use the [case] function below to construct pattern match expressions on that type, or given a pattern match expression one can use the [Case.inductive] function to get the inductive type associated to the pattern match. *) Ltac2 Type case_invert (** A piece of metadata attached to a pattern match expression which tells Rocq which reduction rule to use for the pattern match *) := [ | NoInvert (** The normal reduction rule: reduce the pattern match exactly when the scrutinee is a constructor. *) | CaseInvert (constr array) (** The special reduction rule for eliminating out of an [SProp] into a non-[SProp]. Normally such elimination is only legal when the [SProp] has no constructors, in which case the match is irreducible. If the [SProp] was defined with the [Definitional UIP] flag on, and the [SProp] has one constructor which takes no non-parameter arguments, then the match is reducible if the indices for the scrutinee are unifiable with the indices for the unique constructor. See the [Definitional UIP] section of the [SProp] documentation in the refman for more information. *) ]. Ltac2 Type kind := [ | Rel (int) (** de Bruijn local variable, bound by a surrounding binder such as [forall], [fun], etc. No [Rel] is bound in a goal's context: the goal context is all [Var]s. *) | Var (ident) (** Named variable (section variables and proof context variables are treated identically) *) | Meta (meta) (** An older, legacy implementation of unification variables. This is probably dead code. *) | Evar (evar, constr array) (** Existential variable (unification variable). In [Evar evar array], [evar] is the existential variable itself and [array] is the local variable instance, i.e. values for each of the variables in the evar's context. For an evar [x : T1, y : T2 |- ?e : Te], [?e@{x:=e1; y:=e2}] gives array [[|e2; e1|]]. See also flag [Printing Existential Instances] in the refman. *) | Sort (sort) (** A sort such as Prop, SProp, Type@{u}, a polymorphic sort Type@{s|u}, etc. (cf. refman Core language > Sorts) *) | Cast (constr, cast, constr) (** [Cast t1 k t2] corresponds to the syntactic term [(t1 : t2)], i.e., the programmer declares that [t1] is of type [t2]. [k] is a flag telling the kernel what strategy should be used to validate this assertion, e.g., VM or native evaluation. *) | Prod (binder, constr) (** Concrete syntax ["forall A:B,C"] is represented as [Prod (A:B) C]. [A] is bound as a [Rel] in [C]. *) | Lambda (binder, constr) (** Concrete syntax ["fun A:B => C"] is represented as [Lambda (A:B) C]. [A] is bound as a [Rel] in [C]. *) | LetIn (binder, constr, constr) (** Concrete syntax ["let A:C := B in D"] is represented as [LetIn (A:C) B D]. [A] is bound as a [Rel] in [D]. *) | App (constr, constr array) (** Application is n-ary. Concrete syntax ["(F P1 P2 ... Pn)"] is represented as [App (F, [|P1; P2; ...; Pn|])]. *) | Constant (constant, instance) (** [Constant c ui] is the constant [c] @ universe instance [ui]. *) | Ind (inductive, instance) (** A name of an inductive or coinductive type. [Ind ind ui] is [ind@[ui]] *) | Constructor (constructor, instance) (** A constructor of an inductive type. [Constructor c ui] is [c@[ui]]. *) | Case (case, (constr * Relevance.t), case_invert, constr, constr array) (** [Case case (fun u1 u2 ... un v => rettype, _) ci scrut [|(fun x1 x2 => t1);(fun y1 y2 y3 => t2));...|]] corresponds to [match scrut in I u1 u2 ... as v return rettype with | c0 _ _ x1 x2 => t1 | c1 _ _ y1 y2 y3 => t2 | (...) end]. [ci] is of interest when [scrut] inhabits an [SProp], see comments on the type [case_invert] above. [case] contains a reference to the inductive type of the scrutinee.*) | Fix (int array, int, binder array, constr array) (** [fix fun0 (b00 : B00) (b01 : B01) (...) {struct b0_k0} : C0 := t0 with fun1 (b10 : B10) (b11 : B11) (...) {struct b1_k1} : C1 := t1 with (...) for funi] is represented as [Fix [|k0;k1;...|] i [| fun0 : forall (b00 : B00) (b01 : B01) (...), C0; fun1 : forall (b10 : B10) (b11 : B11) (...), C1; (...) |] [| fun b00 b01 (...) => t0; fun b00 b01 (...) => t1; (...) |]] *) | CoFix (int, binder array, constr array) | Proj (projection, Relevance.t, constr) (** [Proj p r c] is [c.(p)]. The relevance is the relevance of the whole term. *) | Uint63 (uint63) | Float (float) | String (pstring) | Array (instance, constr array, constr, constr) (** [Array u vals def t] is the primitive array literal [[|vals | def : t|]@{u}]. *) ]. Ltac2 @ external kind : constr -> kind := "rocq-runtime.plugins.ltac2" "constr_kind". Ltac2 rec kind_nocast c := match kind c with | Cast c _ _ => kind_nocast c | k => k end. Ltac2 @ external make : kind -> constr := "rocq-runtime.plugins.ltac2" "constr_make". Ltac2 @ external check : constr -> constr result := "rocq-runtime.plugins.ltac2" "constr_check". (** Checks that a constr generated by unsafe means is indeed safe in the current environment, and returns it, or the error otherwise. Panics if not focused. *) Ltac2 @ external liftn : int -> int -> constr -> constr := "rocq-runtime.plugins.ltac2" "constr_liftn". (** [liftn n k c] lifts by [n] indices greater than or equal to [k] in [c] Note that with respect to substitution calculi's terminology, [n] is the _shift_ and [k] is the _lift_. *) Ltac2 @ external substnl : constr list -> int -> constr -> constr := "rocq-runtime.plugins.ltac2" "constr_substnl". (** [substnl [r₁;...;rβ‚™] k c] substitutes in parallel [Rel(k+1); ...; Rel(k+n)] with [r₁;...;rβ‚™] in [c]. *) Ltac2 @ external closenl : ident list -> int -> constr -> constr := "rocq-runtime.plugins.ltac2" "constr_closenl". (** [closenl [x₁;...;xβ‚™] k c] abstracts over variables [x₁;...;xβ‚™] and replaces them with [Rel(k); ...; Rel(k+n-1)] in [c]. If two names are identical, the one of least index is kept. *) Ltac2 @ external closedn : int -> constr -> bool := "rocq-runtime.plugins.ltac2" "constr_closedn". (** [closedn n c] is true iff [c] is a closed term under [n] binders *) Ltac2 is_closed (c : constr) : bool := closedn 0 c. (** [is_closed c] is true iff [c] is a closed term (contains no [Rel]s) *) Ltac2 @ external noccur_between : int -> int -> constr -> bool := "rocq-runtime.plugins.ltac2" "constr_noccur_between". (** [noccur_between n m c] returns true iff [Rel p] does not occur in term [c] for [n <= p < n+m] *) #[deprecated(since="9.0", note="occur_between currently behaves as noccur_between. Use noccur_between instead if you want [true] for variables which do not occur in the term and its negation if you want [false].")] Ltac2 occur_between := noccur_between. Ltac2 noccurn (n : int) (c : constr) : bool := noccur_between n 1 c. (** [noccurn n c] returns true iff [Rel n] does not occur in term [c] *) #[deprecated(since="9.0", note="occurn currently behaves as noccurn. Use noccurn instead if you want [true] for variables which do not occur in the term and its negation if you want [false].")] Ltac2 occurn (n : int) (c : constr) : bool := noccur_between n 1 c. Ltac2 @ external case : inductive -> case := "rocq-runtime.plugins.ltac2" "constr_case". (** Generate the case information for a given inductive type. *) Ltac2 constructor (ind : inductive) (i : int) : constructor := Ind.get_constructor (Ind.data ind) i. (** Generate the i-th constructor for a given inductive type. Indexing starts at 0. Panics if there is no such constructor. *) Module Case. Ltac2 @ external equal : case -> case -> bool := "rocq-runtime.plugins.ltac2" "constr_case_equal". (** Checks equality of the inductive components of the case info. When comparing the inductives, those obtained through module aliases or Include are not considered equal by this function. *) Ltac2 @ external inductive : case -> inductive := "rocq-runtime.plugins.ltac2" "case_to_inductive". (** Get the inductive type being matched on in a pattern match expression. *) End Case. (** Open recursion combinators *) Local Ltac2 iter_invert (f : constr -> unit) (ci : case_invert) : unit := match ci with | NoInvert => () | CaseInvert indices => Array.iter f indices end. (** [iter f c] iterates [f] on the immediate subterms of [c]; it is not recursive and the order with which subterms are processed is not specified *) Ltac2 iter (f : constr -> unit) (c : constr) : unit := match kind c with | Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _ | Constructor _ _ | Uint63 _ | Float _ | String _ => () | Cast c _ t => f c; f t | Prod b c => f (Binder.type b); f c | Lambda b c => f (Binder.type b); f c | LetIn b t c => f (Binder.type b); f t; f c | App c l => f c; Array.iter f l | Evar _ l => Array.iter f l | Case _ x iv y bl => match x with (x,_) => f x end; iter_invert f iv; f y; Array.iter f bl | Proj _p _ c => f c | Fix _ _ tl bl => Array.iter (fun b => f (Binder.type b)) tl; Array.iter f bl | CoFix _ tl bl => Array.iter (fun b => f (Binder.type b)) tl; Array.iter f bl | Array _u t def ty => f ty; Array.iter f t; f def end. (** [iter_with_binders g f n c] iterates [f n] on the immediate subterms of [c]; it carries an extra data [n] (typically a lift index) which is processed by [g] (which typically add 1 to [n]) at each binder traversal; it is not recursive and the order with which subterms are processed is not specified *) Ltac2 iter_with_binders (g : 'a -> binder -> 'a) (f : 'a -> constr -> unit) (n : 'a) (c : constr) : unit := match kind c with | Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _ | Constructor _ _ | Uint63 _ | Float _ | String _ => () | Cast c _ t => f n c; f n t | Prod b c => f n (Binder.type b); f (g n b) c | Lambda b c => f n (Binder.type b); f (g n b) c | LetIn b t c => f n (Binder.type b); f n t; f (g n b) c | App c l => f n c; Array.iter (f n) l | Evar _ l => Array.iter (f n) l | Case _ x iv y bl => match x with (x,_) => f n x end; iter_invert (f n) iv; f n y; Array.iter (f n) bl | Proj _p _ c => f n c | Fix _ _ tl bl => Array.iter (fun b => f n (Binder.type b)) tl; let n := Array.fold_left g n tl in Array.iter (f n) bl | CoFix _ tl bl => Array.iter (fun b => f n (Binder.type b)) tl; let n := Array.fold_left g n tl in Array.iter (f n) bl | Array _u t def ty => f n ty; Array.iter (f n) t; f n def end. Local Ltac2 binder_map (f : constr -> constr) (b : binder) : binder := Binder.unsafe_make (Binder.name b) (Binder.relevance b) (f (Binder.type b)). Local Ltac2 map_invert (f : constr -> constr) (iv : case_invert) : case_invert := match iv with | NoInvert => NoInvert | CaseInvert indices => CaseInvert (Array.map f indices) end. (** [map f c] maps [f] on the immediate subterms of [c]; it is not recursive and the order with which subterms are processed is not specified *) Ltac2 map (f : constr -> constr) (c : constr) : constr := match kind c with | Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _ | Constructor _ _ | Uint63 _ | Float _ | String _ => c | Cast c k t => let c := f c with t := f t in make (Cast c k t) | Prod b c => let b := binder_map f b with c := f c in make (Prod b c) | Lambda b c => let b := binder_map f b with c := f c in make (Lambda b c) | LetIn b t c => let b := binder_map f b with t := f t with c := f c in make (LetIn b t c) | App c l => let c := f c with l := Array.map f l in make (App c l) | Evar e l => let l := Array.map f l in make (Evar e l) | Case info x iv y bl => let x := match x with (x,x') => (f x, x') end with iv := map_invert f iv with y := f y with bl := Array.map f bl in make (Case info x iv y bl) | Proj p r c => let c := f c in make (Proj p r c) | Fix structs which tl bl => let tl := Array.map (binder_map f) tl with bl := Array.map f bl in make (Fix structs which tl bl) | CoFix which tl bl => let tl := Array.map (binder_map f) tl with bl := Array.map f bl in make (CoFix which tl bl) | Array u t def ty => let ty := f ty with t := Array.map f t with def := f def in make (Array u t def ty) end. (** [map_with_binders g f n c] maps [f n] on the immediate subterms of [c]; it carries an extra data [n] (typically a lift index) which is processed by [g] (which typically add 1 to [n]) at each binder traversal; it is not recursive and the order with which subterms are processed is not specified. *) Ltac2 map_with_binders (lift : 'a -> binder -> 'a) (f : 'a -> constr -> constr) (n : 'a) (c : constr) : constr := match kind c with | Rel _ | Meta _ | Var _ | Sort _ | Constant _ _ | Ind _ _ | Constructor _ _ | Uint63 _ | Float _ | String _ => c | Cast c k t => let c := f n c with t := f n t in make (Cast c k t) | Prod b c => let b := binder_map (f n) b with c := f (lift n b) c in make (Prod b c) | Lambda b c => let b := binder_map (f n) b with c := f (lift n b) c in make (Lambda b c) | LetIn b t c => let b := binder_map (f n) b with t := f n t with c := f (lift n b) c in make (LetIn b t c) | App c l => let c := f n c with l := Array.map (f n) l in make (App c l) | Evar e l => let l := Array.map (f n) l in make (Evar e l) | Case info x iv y bl => let x := match x with (x,x') => (f n x, x') end with iv := map_invert (f n) iv with y := f n y with bl := Array.map (f n) bl in make (Case info x iv y bl) | Proj p r c => let c := f n c in make (Proj p r c) | Fix structs which tl bl => let tl := Array.map (binder_map (f n)) tl in let n_bl := Array.fold_left lift n tl in let bl := Array.map (f n_bl) bl in make (Fix structs which tl bl) | CoFix which tl bl => let tl := Array.map (binder_map (f n)) tl in let n_bl := Array.fold_left lift n tl in let bl := Array.map (f n_bl) bl in make (CoFix which tl bl) | Array u t def ty => let ty := f n ty with t := Array.map (f n) t with def := f n def in make (Array u t def ty) end. End Unsafe. Module Cast. Ltac2 @ external default : cast := "rocq-runtime.plugins.ltac2" "constr_cast_default". Ltac2 @ external vm : cast := "rocq-runtime.plugins.ltac2" "constr_cast_vm". Ltac2 @ external native : cast := "rocq-runtime.plugins.ltac2" "constr_cast_native". Ltac2 @ external equal : cast -> cast -> bool := "rocq-runtime.plugins.ltac2" "constr_cast_equal". End Cast. Ltac2 @ external in_context : ident -> constr -> (unit -> unit) -> constr := "rocq-runtime.plugins.ltac2" "constr_in_context". (** On a focused goal [Ξ“ ⊒ A], [in_context id c tac] evaluates [tac] in a focused goal [Ξ“, id : c ⊒ ?X] and returns [fun (id : c) => t] where [t] is the proof built by the tactic. *) Module Pretype. Module Flags. Ltac2 Type t. Ltac2 @ external constr_flags : t := "rocq-runtime.plugins.ltac2" "constr_flags". (** The flags used by constr:(). *) Ltac2 @external set_use_coercions : bool -> t -> t := "rocq-runtime.plugins.ltac2" "pretype_flags_set_use_coercions". (** Use coercions during pretyping. [true] in [constr_flags]. *) Ltac2 @external set_use_typeclasses : bool -> t -> t := "rocq-runtime.plugins.ltac2" "pretype_flags_set_use_typeclasses". (** Run typeclass inference at the end of pretyping and when needed according to flag "Typeclass Resolution For Conversion". [true] in [constr_flags]. *) Ltac2 @external set_allow_evars : bool -> t -> t := "rocq-runtime.plugins.ltac2" "pretype_flags_set_allow_evars". (** Allow pretyping to produce new unresolved evars. [false] in [constr_flags]. *) Ltac2 @external set_nf_evars : bool -> t -> t := "rocq-runtime.plugins.ltac2" "pretype_flags_set_nf_evars". (** Evar-normalize the result of pretyping. This should not impact anything other than performance. [true] in [constr_flags]. *) Ltac2 Abbreviation open_constr_flags_with_tc := set_nf_evars false (set_allow_evars true constr_flags). Local Ltac2 open_constr_flags_with_tc_kn () := open_constr_flags_with_tc. (** Code generation uses this as using the notation is not convenient. *) Ltac2 Abbreviation open_constr_flags_no_tc := set_use_typeclasses false open_constr_flags_with_tc. (** The flags used by open_constr:() and its alias [']. *) #[deprecated(since="8.20", note="use open_constr_flags_with_tc (or open_constr_flags_no_tc as desired)")] Ltac2 Abbreviation open_constr_flags := open_constr_flags_with_tc. End Flags. Ltac2 Type expected_type. Ltac2 @ external expected_istype : expected_type := "rocq-runtime.plugins.ltac2" "expected_istype". Ltac2 @ external expected_oftype : constr -> expected_type := "rocq-runtime.plugins.ltac2" "expected_oftype". Ltac2 @ external expected_without_type_constraint : expected_type := "rocq-runtime.plugins.ltac2" "expected_without_type_constraint". Ltac2 @ external pretype : Flags.t -> expected_type -> preterm -> constr := "rocq-runtime.plugins.ltac2" "constr_pretype". (** Pretype the provided preterm. Assumes the goal to be focussed. *) End Pretype. Ltac2 pretype (c : preterm) : constr := Pretype.pretype Pretype.Flags.constr_flags Pretype.expected_without_type_constraint c. (** Pretype the provided preterm. Assumes the goal to be focussed. *) Ltac2 decompose_app_list (c : constr) := match Unsafe.kind c with | Unsafe.App f cl => (f, Array.to_list cl) | _ => (c,[]) end. Ltac2 decompose_app (c : constr) := match Unsafe.kind c with | Unsafe.App f cl => (f, cl) | _ => (c,[| |]) end. Ltac2 is_evar(c: constr) := match Unsafe.kind c with | Unsafe.Evar _ _ => true | _ => false end. Ltac2 @ external has_evar : constr -> bool := "rocq-runtime.plugins.ltac2" "constr_has_evar". Ltac2 is_var(c: constr) := match Unsafe.kind c with | Unsafe.Var _ => true | _ => false end. Ltac2 is_fix(c: constr) := match Unsafe.kind c with | Unsafe.Fix _ _ _ _ => true | _ => false end. Ltac2 is_cofix(c: constr) := match Unsafe.kind c with | Unsafe.CoFix _ _ _ => true | _ => false end. Ltac2 is_ind(c: constr) := match Unsafe.kind c with | Unsafe.Ind _ _ => true | _ => false end. Ltac2 is_constructor(c: constr) := match Unsafe.kind c with | Unsafe.Constructor _ _ => true | _ => false end. Ltac2 is_proj(c: constr) := match Unsafe.kind c with | Unsafe.Proj _ _ _ => true | _ => false end. Ltac2 is_const(c: constr) := match Unsafe.kind c with | Unsafe.Constant _ _ => true | _ => false end. Ltac2 is_float(c: constr) := match Unsafe.kind c with | Unsafe.Float _ => true | _ => false end. Ltac2 is_uint63(c: constr) := match Unsafe.kind c with | Unsafe.Uint63 _ => true | _ => false end. Ltac2 is_string(c: constr) := match Unsafe.kind c with | Unsafe.String _ => true | _ => false end. Ltac2 is_array(c: constr) := match Unsafe.kind c with | Unsafe.Array _ _ _ _ => true | _ => false end. Ltac2 is_sort(c: constr) := match Unsafe.kind c with | Unsafe.Sort _ => true | _ => false end. rocq-9.2.0/theories/Ltac2/Constructor.v000066400000000000000000000030551516144147600200050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "constructor_equal". (** Constructors obtained through module aliases or Include are not considered equal by this function. *) Ltac2 @ external inductive : t -> inductive := "rocq-runtime.plugins.ltac2" "constructor_inductive". (** Returns the inductive to which the given constructor belongs. *) Ltac2 @ external index : t -> int := "rocq-runtime.plugins.ltac2" "constructor_index". (** Returns the index of the given constructor (such that [c] is [Ind.get_constructor (Ind.data (inductive c)) (index c)]). *) Ltac2 @external print : t -> message := "rocq-runtime.plugins.ltac2" "constructor_print". (** Print the constructor using the shortest qualified identifier which refers to it. Does not avoid variable names in the current or global environment. *) rocq-9.2.0/theories/Ltac2/Control.v000066400000000000000000000265371516144147600171120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a := "rocq-runtime.plugins.ltac2" "throw". (** Fatal exception throwing. This does not induce backtracking. *) (** Generic backtracking control *) Ltac2 @ external zero : exn -> 'a := "rocq-runtime.plugins.ltac2" "zero". (** [zero e] raises the exception e, passing control to the current backtracking continuation. *) Ltac2 @ external plus : (unit -> 'a) -> (exn -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "plus". (** Backtracking point, cf Backtracking section of the ltac2 refman. *) Ltac2 @ external once : (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "once". (** [once t] behaves like [t], except it has at most one success: [once t] stops after the first success of [t]. If [t] fails with [e], [once t] also fails with [e]. If [once t; t'] fails on [t'], then [once t] will not backtrack and evaluate [t] for another value, and will instead fail. *) Ltac2 @ external case : (unit -> 'a) -> ('a * (exn -> 'a)) result := "rocq-runtime.plugins.ltac2" "case". (** [case] is the most general primitive to control backtracking: - If [t ()] would fail with [e], [case t] returns [Err e]. - If [t ()] would succeed and evaluate to [v] then [case t] returns [Val (v, h)], where [h] is the continuation to execute in case of subsequent failure. [case] reifies a backtracking computation into an inspectable value, it allows the programmer to make explicit the effects which are normally implicit (i.e., they do not appear in the type system). *) Ltac2 once_plus (run : unit -> 'a) (handle : exn -> 'a) : 'a := once (fun () => plus run handle). (** [once_plus run handle] is [once] applied to [plus run handle]. *) (** Proof state manipulation *) Ltac2 @ external numgoals : unit -> int := "rocq-runtime.plugins.ltac2" "numgoals". (** Return the number of goals currently focused. *) Ltac2 @ external dispatch : (unit -> unit) list -> unit := "rocq-runtime.plugins.ltac2" "dispatch". (** The dispatch tactical is used to apply a different tactic to each goal under focus. It works by applying each of the tactics in a focus restricted to the corresponding goal (starting with the first goal). When the length of the tactic list is not equal to the number of focused goals, raises Internal err. *) Ltac2 @ external extend : (unit -> unit) list -> (unit -> unit) -> (unit -> unit) list -> unit := "rocq-runtime.plugins.ltac2" "extend". (** extend is a more flexible variant of dispatch, where the second argument tactic is "repeated" enough times such that every goal has a tactic assigned to it. [extend b r e] applies the tactics in [b] to the first [length b] goals, the tactics in [r] to the last [length r] goals, and [e] to all tactics in between. Raises Internal err if [length b + length r] is greater than the number of goals under focus.*) Ltac2 @ external enter : (unit -> unit) -> unit := "rocq-runtime.plugins.ltac2" "enter". (** [enter] takes a single tactic [t] and applies [t] in each goal under focus independently. *) Ltac2 @ external focus : int -> int -> (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "focus". (** [focus i j tac] focuses a proofview on the goals from index [i] to index [j] (inclusive, goals are indexed from [1]) and runs t with those goals under focus, i.e. goals number [i] to [j] become the only focused goals during the execution of tac. When [focus] returns, the present focus is restored. If the range [i - j] is invalid, fails with a backtrackable "no such goal" error. *) Ltac2 @ external cycle : int -> unit := "rocq-runtime.plugins.ltac2" "cycle". (** If [n] is positive, [cycle n] puts the [n] first goal last. If [n] is negative, then it puts the [n] last goals first.*) Ltac2 @ external shelve : unit -> unit := "rocq-runtime.plugins.ltac2" "shelve". (** Shelve all goals under focus. The goals are placed on the shelf for later use, or to be solved by side-effects.*) Ltac2 @ external shelve_unifiable : unit -> unit := "rocq-runtime.plugins.ltac2" "shelve_unifiable". (** Shelves the unifiable goals under focus, i.e. the goals which appear in other goals under focus (the unfocused goals are not considered). *) Ltac2 @ external new_goal : evar -> unit := "rocq-runtime.plugins.ltac2" "new_goal". (** Adds the given evar to the list of goals as the last one. If it is already defined in the current state, don't do anything. Panics if the evar is not in the current state. *) Ltac2 @ external unshelve : (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "unshelve". (** Runs the closure, then unshelves existential variables added to the shelf by its execution, prepending them to the current goal. Returns the value produced by the closure. *) Ltac2 @ external progress : (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "progress". (** [progress t] checks the state of the proof after [t]. It it is identical to the state before, then [progress t] fails, otherwise it succeeds like [t]. *) (** Goal inspection *) Ltac2 @ external goal : unit -> constr := "rocq-runtime.plugins.ltac2" "goal". (** Panics if there is not exactly one goal under focus. Otherwise returns the conclusion of this goal. *) Ltac2 @ external hyp : ident -> constr := "rocq-runtime.plugins.ltac2" "hyp". (** Panics if there is more than one goal under focus. If there is no goal under focus, looks for the section variable with the given name. If there is one, looks for the hypothesis with the given name. *) Ltac2 @ external hyp_value : ident -> constr option := "rocq-runtime.plugins.ltac2" "hyp_value". (** Panics if there is more than one goal under focus. If there is no goal under focus, looks for the section variable with the given name and return its value ("v" in "H := v") if there is one. If there is one, looks for the hypothesis with the given name and return its value if there is one. *) Ltac2 @ external hyps : unit -> (ident * constr option * constr) list := "rocq-runtime.plugins.ltac2" "hyps". (** Panics if there is more than one goal under focus. If there is no goal under focus, returns the list of section variables. If there is one, returns the list of hypotheses. In both cases, the list is ordered with rightmost values being last introduced. *) (** Refinement *) Ltac2 @ external refine : (unit -> constr) -> unit := "rocq-runtime.plugins.ltac2" "refine". (** [refine t] computes the type of the term [t ()] and unifies the type with the current goal. All unification variables produced while computing [t ()] not solved by this unification process are added as new goals. *) (** Evars *) Ltac2 @ external with_holes : (unit -> 'a) -> ('a -> 'b) -> 'b := "rocq-runtime.plugins.ltac2" "with_holes". (** [with_holes x f] evaluates [x], then apply [f] to the result, and fails if all evars generated by the call to [x] have not been solved when [f] returns. *) (** Misc *) Ltac2 @ external time : string option -> (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "time". (** Displays the time taken by a tactic to evaluate. *) Ltac2 @ external abstract : ident option -> (unit -> unit) -> unit := "rocq-runtime.plugins.ltac2" "abstract". (** Abstract a subgoal. *) Ltac2 @ external check_interrupt : unit -> unit := "rocq-runtime.plugins.ltac2" "check_interrupt". (** For internal use. *) (** Assertions throwing exceptions and short form throws *) Ltac2 throw_invalid_argument (msg : string) := Control.throw (Invalid_argument (Some (Message.of_string msg))). Ltac2 throw_out_of_bounds (msg : string) := Control.throw (Out_of_bounds (Some (Message.of_string msg))). Ltac2 assert_valid_argument (msg : string) (test : bool) := match test with | true => () | false => throw_invalid_argument msg end. Ltac2 assert_bounds (msg : string) (test : bool) := match test with | true => () | false => throw_out_of_bounds msg end. Ltac2 assert_true b := if b then () else throw Assertion_failure. Ltac2 assert_false b := if b then throw Assertion_failure else (). (** Short form backtracks *) Ltac2 backtrack_tactic_failure (msg : string) := Control.zero (Tactic_failure (Some (Message.of_string msg))). (** Backtraces. *) Ltac2 @external current_exninfo : unit -> exninfo := "rocq-runtime.plugins.ltac2" "current_exninfo". (** [throw_bt info e] is similar to [throw e], but raises [e] with the backtrace represented by [info]. *) Ltac2 @ external throw_bt : exn -> exninfo -> 'a := "rocq-runtime.plugins.ltac2" "throw_bt". (** [zero_bt info e] is similar to [zero e], but raises [e] with the backtrace represented by [info]. *) Ltac2 @ external zero_bt : exn -> exninfo -> 'a := "rocq-runtime.plugins.ltac2" "zero_bt". (** [plus_bt run handle] is similar to [plus run handle] (up to the type missmatch for [handle]), but it calls [handle] with an extra argument representing the backtrace at the point of the exception. The [handle] function can thus decide to re-attach that backtrace when using the [throw_bt] or [zero_bt] functions. *) Ltac2 @ external plus_bt : (unit -> 'a) -> (exn -> exninfo -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "plus_bt". (** [once_plus_bt run handle] is a non-backtracking variant of [once_plus] that has backtrace support similar to that of [plus_bt]. *) Ltac2 once_plus_bt (run : unit -> 'a) (handle : exn -> exninfo -> 'a) : 'a := once (fun _ => plus_bt run handle). Ltac2 @ external clear_err_info : err -> err := "rocq-runtime.plugins.ltac2" "clear_err_info". Ltac2 clear_exn_info (e : exn) : exn := match e with | Init.Internal err => Init.Internal (clear_err_info err) | e => e end. (** Timeout. *) (** [timeout t thunk] calls [thunk ()] with a timeout of [t] seconds. *) Ltac2 @ external timeout : int -> (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "timeout". (** [timeoutf t thunk] calls [thunk ()] with a timeout of [t] seconds. *) Ltac2 @ external timeoutf : float -> (unit -> 'a) -> 'a := "rocq-runtime.plugins.ltac2" "timeoutf". (** Error printing *) (** Print internal errors. *) Ltac2 @external print_err : err -> message := "rocq-runtime.plugins.ltac2" "print_err". (** Print exceptions as errors. Used by the runtime when printing uncaught errors. Extensible by mutation, see uses below. IMPORTANT: when called for printing uncaught errors, it is run in an empty state (no goals, empty evar map). Also note that the "Internal" branch is not used when printing uncaught errors as Internal exceptions are not considered as Ltac2 errors. *) Ltac2 mutable print_exn : exn -> message option := fun e => match e with | Internal e => Some (print_err e) | _ => None end. #[global] Ltac2 Set print_exn as print_other := fun e => match e with | Tactic_failure (Some msg) => Some msg | _ => print_other e end. rocq-9.2.0/theories/Ltac2/Env.v000066400000000000000000000031341516144147600162060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Std.reference option := "rocq-runtime.plugins.ltac2" "env_get". (** Returns the global reference corresponding to the absolute name given as argument if it exists. *) Ltac2 @ external expand : ident list -> Std.reference list := "rocq-runtime.plugins.ltac2" "env_expand". (** Returns the list of all global references whose absolute name contains the argument list as a suffix. *) Ltac2 @ external path : Std.reference -> ident list := "rocq-runtime.plugins.ltac2" "env_path". (** Returns the absolute name of the given reference. Panics if the reference does not exist. *) Ltac2 @ external instantiate : Std.reference -> constr := "rocq-runtime.plugins.ltac2" "env_instantiate". (** Returns a fresh instance of the corresponding reference, in particular generating fresh universe variables and constraints when this reference is universe-polymorphic. *) rocq-9.2.0/theories/Ltac2/Evar.v000066400000000000000000000014551516144147600163570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "evar_equal". rocq-9.2.0/theories/Ltac2/FMap.v000066400000000000000000000036001516144147600162770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ('k, 'v) t := "rocq-runtime.plugins.ltac2" "fmap_empty". Ltac2 @ external is_empty : ('k, 'v) t -> bool := "rocq-runtime.plugins.ltac2" "fmap_is_empty". Ltac2 @ external mem : 'k -> ('k, 'v) t -> bool := "rocq-runtime.plugins.ltac2" "fmap_mem". Ltac2 @ external add : 'k -> 'v -> ('k, 'v) t -> ('k, 'v) t := "rocq-runtime.plugins.ltac2" "fmap_add". Ltac2 @ external remove : 'k -> ('k, 'v) t -> ('k, 'v) t := "rocq-runtime.plugins.ltac2" "fmap_remove". Ltac2 @ external find_opt : 'k -> ('k, 'v) t -> 'v option := "rocq-runtime.plugins.ltac2" "fmap_find_opt". Ltac2 @ external mapi : ('k -> 'v -> 'r) -> ('k, 'v) t -> ('k, 'r) t := "rocq-runtime.plugins.ltac2" "fmap_mapi". Ltac2 @ external fold : ('k -> 'v -> 'acc -> 'acc) -> ('k, 'v) t -> 'acc -> 'acc := "rocq-runtime.plugins.ltac2" "fmap_fold". Ltac2 @ external cardinal : ('k, 'v) t -> int := "rocq-runtime.plugins.ltac2" "fmap_cardinal". Ltac2 @ external bindings : ('k, 'v) t -> ('k * 'v) list := "rocq-runtime.plugins.ltac2" "fmap_bindings". Ltac2 @ external domain : ('k, 'v) t -> 'k FSet.t := "rocq-runtime.plugins.ltac2" "fmap_domain". rocq-9.2.0/theories/Ltac2/FSet.v000066400000000000000000000047501516144147600163240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a t := "rocq-runtime.plugins.ltac2" "fset_empty". Ltac2 @ external is_empty : 'a t -> bool := "rocq-runtime.plugins.ltac2" "fset_is_empty". Ltac2 @ external mem : 'a -> 'a t -> bool := "rocq-runtime.plugins.ltac2" "fset_mem". Ltac2 @ external add : 'a -> 'a t -> 'a t := "rocq-runtime.plugins.ltac2" "fset_add". Ltac2 @ external remove : 'a -> 'a t -> 'a t := "rocq-runtime.plugins.ltac2" "fset_remove". Ltac2 @ external union : 'a t -> 'a t -> 'a t := "rocq-runtime.plugins.ltac2" "fset_union". Ltac2 @ external inter : 'a t -> 'a t -> 'a t := "rocq-runtime.plugins.ltac2" "fset_inter". Ltac2 @ external diff : 'a t -> 'a t -> 'a t := "rocq-runtime.plugins.ltac2" "fset_diff". Ltac2 @ external equal : 'a t -> 'a t -> bool := "rocq-runtime.plugins.ltac2" "fset_equal". Ltac2 @ external subset : 'a t -> 'a t -> bool := "rocq-runtime.plugins.ltac2" "fset_subset". Ltac2 @ external cardinal : 'a t -> int := "rocq-runtime.plugins.ltac2" "fset_cardinal". Ltac2 @ external elements : 'a t -> 'a list := "rocq-runtime.plugins.ltac2" "fset_elements". rocq-9.2.0/theories/Ltac2/Float.v000066400000000000000000000014571516144147600165310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "float_equal". rocq-9.2.0/theories/Ltac2/Fresh.v000066400000000000000000000036221516144147600165270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> t := "rocq-runtime.plugins.ltac2" "fresh_free_add". Ltac2 @external union : t -> t -> t := "rocq-runtime.plugins.ltac2" "fresh_free_union". Ltac2 @external of_ids : ident list -> t := "rocq-runtime.plugins.ltac2" "fresh_free_of_ids". Ltac2 @external of_constr : constr -> t := "rocq-runtime.plugins.ltac2" "fresh_free_of_constr". Ltac2 of_goal () := of_ids (List.map (fun (id, _, _) => id) (Control.hyps ())). End Free. (** Generate a fresh identifier with the given base name which is not a member of the provided set of free variables, and update the set. More efficient than composing [fresh] and [Free.add]. *) Ltac2 @external next : Free.t -> ident -> ident * Free.t := "rocq-runtime.plugins.ltac2" "fresh_next". (** Generate a fresh identifier with the given base name which is not a member of the provided set of free variables. *) Ltac2 @external fresh : Free.t -> ident -> ident := "rocq-runtime.plugins.ltac2" "fresh_fresh". Ltac2 in_goal id := Fresh.fresh (Free.of_goal ()) id. rocq-9.2.0/theories/Ltac2/Ident.v000066400000000000000000000021161516144147600165200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "ident_equal". Ltac2 @ external of_string : string -> t option := "rocq-runtime.plugins.ltac2" "ident_of_string". Ltac2 @ external to_string : t -> string := "rocq-runtime.plugins.ltac2" "ident_to_string". Ltac2 @external print : ident -> message := "rocq-runtime.plugins.ltac2" "message_of_ident". rocq-9.2.0/theories/Ltac2/Ind.v000066400000000000000000000110711516144147600161670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "ind_equal". (** Equality test. *) Ltac2 Type data. (** The actual data specified by a concrete declaration of an inductive type, containing, e.g., its constructors and its parameters. A value of type [data] corresponds to one inductive type within a larger mutually inductive block. *) Ltac2 @ external data : t -> data := "rocq-runtime.plugins.ltac2" "ind_data". (** Get the value named by [t] in the current environment. Panics if [t] is not in the current environment. *) Ltac2 @ external repr : data -> t := "rocq-runtime.plugins.ltac2" "ind_repr". (** Returns the name of the inductive type corresponding to the block. Inverse of [data]. *) Ltac2 @ external index : t -> int := "rocq-runtime.plugins.ltac2" "ind_index". (** Returns the index of the inductive type inside its mutual block. Guaranteed to range between [0] and [nblocks data - 1] where [data] was retrieved using the above function. *) Ltac2 @ external nblocks : data -> int := "rocq-runtime.plugins.ltac2" "ind_nblocks". (** Returns the number of inductive types appearing in a mutual block. *) Ltac2 @ external nconstructors : data -> int := "rocq-runtime.plugins.ltac2" "ind_nconstructors". (** Returns the number of constructors appearing in the current block. *) Ltac2 @ external get_block : data -> int -> data := "rocq-runtime.plugins.ltac2" "ind_get_block". (** [get_block data n] is the block corresponding to the nth inductive type in [data]'s parent mutually inductive type. Index must range between [0] and [nblocks data - 1], otherwise the function panics. *) Ltac2 @ external get_constructor : data -> int -> constructor := "rocq-runtime.plugins.ltac2" "ind_get_constructor". (** Returns the nth constructor of the inductive type. Index must range between [0] and [nconstructors data - 1], otherwise the function panics. *) Ltac2 @ external nparams : data -> int := "rocq-runtime.plugins.ltac2" "ind_get_nparams". (** The number of parameters of the inductive type, including both uniform and non-uniform parameters. Does not count local let-ins. *) Ltac2 @ external nparams_uniform : data -> int := "rocq-runtime.plugins.ltac2" "ind_get_nparams_rec". (** The number of recursively uniform (i.e., ordinary) parameters of the inductive type. *) Ltac2 @ external get_projections : data -> projection array option := "rocq-runtime.plugins.ltac2" "ind_get_projections". (** Returns the list of projections for a primitive record, or [None] if the inductive is not a primitive record. *) Ltac2 @ external constructor_nargs : data -> int array := "rocq-runtime.plugins.ltac2" "constructor_nargs". (** [Array.get (constructor_nargs data) n] is the number of non-parameter arguments accepted by the [n]th constructor of this inductive type. Add [Array.get (constructor_nargs data) n] to [Ind.nparams_data] to get the total number of arguments of the constructor. *) Ltac2 @ external constructor_ndecls : data -> int array := "rocq-runtime.plugins.ltac2" "constructor_ndecls". (** [Array.get (constructor_ndecls data) n] is the number of variables bound in a pattern match expression by the [n]th constructor of this inductive type. Can be greater than [constructor_nargs] if the constructors have local let-bindings, e.g., applied to [Inductive Ind (A : Type) (f : A -> A) : Set := Constr (x : A) (y := f x)] it would return [[|2|]], because in [match t with Constr _ _ x y => e end], [x] and [y] are bound in [e]. *) Ltac2 @external print : t -> message := "rocq-runtime.plugins.ltac2" "ind_print". (** Print the inductive using the shortest qualified identifier which refers to it. Does not avoid variable names in the current or global environment. *) rocq-9.2.0/theories/Ltac2/Init.v000066400000000000000000000061331516144147600163630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int -> bool := "rocq-runtime.plugins.ltac2" "int_equal". Ltac2 @ external compare : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_compare". Ltac2 @ external add : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_add". Ltac2 @ external sub : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_sub". Ltac2 @ external mul : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_mul". (* Note: unlike Rocq Z division, Ltac2 matches OCaml division and rounds towards 0, so 1/-2 = 0 *) Ltac2 @ external div : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_div". Ltac2 @ external mod : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_mod". Ltac2 @ external neg : int -> int := "rocq-runtime.plugins.ltac2" "int_neg". Ltac2 @ external abs : int -> int := "rocq-runtime.plugins.ltac2" "int_abs". Ltac2 @ external asr : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_asr". Ltac2 @ external lsl : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_lsl". Ltac2 @ external lsr : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_lsr". Ltac2 @ external land : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_land". Ltac2 @ external lor : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_lor". Ltac2 @ external lxor : int -> int -> int := "rocq-runtime.plugins.ltac2" "int_lxor". Ltac2 @ external lnot : int -> int := "rocq-runtime.plugins.ltac2" "int_lnot". Ltac2 lt (x : int) (y : int) := equal (compare x y) -1. Ltac2 gt (x : int) (y : int) := equal (compare x y) 1. Ltac2 le (x : int) (y : int) := (* we might use [lt x (add y 1)], but that has the wrong behavior on MAX_INT *) match equal x y with | true => true | false => lt x y end. Ltac2 ge (x : int) (y : int) := (* we might use [lt (add x 1) y], but that has the wrong behavior on MAX_INT *) match equal x y with | true => true | false => gt x y end. rocq-9.2.0/theories/Ltac2/Lazy.v000066400000000000000000000076121516144147600164020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a) ]. (** Type of a lazy cell, similar to OCaml's ['a Lazy.t] type. The functions of this module do not have any specific backtracking support, so any function passed to primitives of this module is handled as if it had one success at most (potential other successes are ignored). *) Ltac2 Type 'a t := 'a lazy_data Ref.ref. (** [from_val v] creates a new lazy cell storing (already-computed) value [v]. Forcing (i.e., using the [force] function on) the produced cell gives back value [v], and never gives an exception. *) Ltac2 from_val (v : 'a) : 'a t := Ref.ref (Value v). (** [from_fun f] creates a new lazy cell from the given thunk [f]. There is no specific support for backtracking in the [Lazy] module, so if [f] has more than one success, only the first one will be considered. *) Ltac2 from_fun (f : unit -> 'a) : 'a t := Ref.ref (Thunk f). (** [is_val r] indicates whether the given lazy cell [r] holds a forced value. In particular, [is_val r] always returns [true] if [r] was created via the [from_val] function. If [r] was created using [from_fun], then [true] will only be returned if the value of [r] was previously forced (e.g., with the [force] function), and if no exception was produced by said forcing. *) Ltac2 is_val (r : 'a t) : bool := match Ref.get r with | Value _ => true | Thunk _ => false end. (** Exception raised in case of a "cyclic" lazy cell. *) Ltac2 Type exn ::= [ Undefined ]. (** [force r] gives the value represented by the lazy cell [r], which requires forcing a thunk and updating [r] to the produced value if [r] does not yet have a value. Note that if forcing produces an exception, subsequent calls to [force] will immediately yield the same exception (without re-computing the whole thunk). Additionally, the [Undefined] exception is produced (and set to be produced by [r] on subsequent calls to [force]) if [r] relies on its own value for its definition (i.e., if [r] is "cyclic"). *) Ltac2 force (r : 'a t) : 'a := match Ref.get r with | Value v => v | Thunk f => Ref.set r (Thunk (fun () => Control.throw Undefined)); match Control.case f with | Val (v, _) => Ref.set r (Value v); v | Err e => Ref.set r (Thunk (fun () => Control.zero e)); Control.zero e end end. (** [map f r] is equivalent to [from_fun (fun () => f (force r))]. *) Ltac2 map (f : 'a -> 'b) (r : 'a t) : 'b t := from_fun (fun () => f (force r)). (** [map_val f r] is similar to [map f r], but the function [f] is immediately applied if [r] contains a forced value. If the immediate application gives an exception, then any subsequent forcing of produced lazy cell will raise the same exception. *) Ltac2 map_val (f : 'a -> 'b) (r : 'a t) : 'b t := match Ref.get r with | Value v => match Control.case (fun () => f v) with | Val (v, _) => from_val v | Err e => from_fun (fun () => Control.zero e) end | Thunk t => from_fun (fun () => f (t ())) end. Module Export Notations. Ltac2 Notation "lazy!" f(thunk(self)) := from_fun f. End Notations. rocq-9.2.0/theories/Ltac2/List.v000066400000000000000000000631041516144147600163740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 | _ :: xs => Int.add 1 (length xs) end. (** [compare_lengths ls1 ls2] is equal to [Int.compare (length ls1) (length ls2)], but is more efficient in most cases: it runs in O(min (length ls1) (length ls2)) instead of O(max (length ls1) (length ls2)). *) Ltac2 rec compare_lengths (ls1 : 'a list) (ls2 : 'b list) : int := match ls1 with | [] => match ls2 with | [] => 0 | _ :: _ => -1 end | _ :: ls1 => match ls2 with | [] => 1 | _ :: ls2 => compare_lengths ls1 ls2 end end. (** [compare_length_with ls n] is equal to [Int.compare (length ls) n], but is more efficient in most cases: it runs in O(min (length ls) n) instead of O(length ls). *) Ltac2 rec compare_length_with (ls : 'a list) (n : int) : int := match Int.lt n 0 with | true => 1 | false => match ls with | [] => Int.compare 0 n | _ :: ls => compare_length_with ls (Int.sub n 1) end end. Ltac2 cons (x : 'a) (xs : 'a list) : 'a list := x :: xs. (** Since Ltac2 distinguishes between backtracking and fatal exceptions, we provide option and default variants of functions which throw in the OCaml stdlib. *) (** Return the first element of a list. Returns [None] if the list is empty. *) Ltac2 hd_opt (ls : 'a list) : 'a option := match ls with | [] => None | x :: _ => Some x end. (** Return the first element of a list. Throw an exception if the list is empty. *) Ltac2 hd (ls : 'a list) : 'a := match ls with | [] => Control.throw_invalid_argument "List.hd" | x :: _ => x end. (** Remove the first element from a list. The empty list is returned as is. *) Ltac2 tl (ls : 'a list) : 'a list := match ls with | [] => [] | _ :: xs => xs end. (** Destruct a list into its head and tail. Throws an exception if the list is empty. *) Ltac2 dest (xs : 'a list) : 'a * 'a list := match xs with | x :: xs => (x, xs) | [] => Control.throw_invalid_argument "List.dest: list empty" end. (** Return [true] if the list is empty. *) Ltac2 is_empty (xs : 'a list) : bool := match xs with | _ :: _ => false | _ => true end. (** Return the last element of a list. Returns [None] if the list is empty. *) Ltac2 rec last_opt (ls : 'a list) : 'a option := match ls with | [] => None | x :: xs => match xs with | [] => Some x | _ :: _ => last_opt xs end end. (** Return the last element of a list. Throws an exception if the list is empty. *) Ltac2 last (ls : 'a list) : 'a := match last_opt ls with | None => Control.throw_invalid_argument "List.last" | Some v => v end. (** Remove the last element of a list. The empty list is returned as is. *) Ltac2 rec removelast (ls : 'a list) : 'a list := match ls with | [] => [] | x :: xs => match xs with | [] => [] | _ :: _ => x :: removelast xs end end. (** Helper function for [nth_opt]. *) Ltac2 rec nth_opt_aux (ls : 'a list) (n : int) := match ls with | [] => None | x :: xs => match Int.equal n 0 with | true => Some x | false => nth_opt_aux xs (Int.sub n 1) end end. (** [nth_opt ls n] returns the [n]-th element [ls], starting at [0]. Throws an exception if [n < 0]. Returns [None] if [n >= length ls]. *) Ltac2 nth_opt (ls : 'a list) (n : int) : 'a option := Control.assert_valid_argument "List.nth" (Int.ge n 0); nth_opt_aux ls n. (** [nth ls n] returns the [n]-th element of [ls], starting at [0]. Throws an exception if [n < 0] or [n >= length ls]. *) Ltac2 nth (ls : 'a list) (n : int) : 'a := match nth_opt ls n with | Some v => v | None => Control.throw_out_of_bounds "List.nth" end. (** Reverse [l1], and append it with [l2]: [rev_append l1 l2 = append (rev l1) l2]. *) Ltac2 rec rev_append (l1 : 'a list) (l2 : 'a list) : 'a list := match l1 with | [] => l2 | a :: l => rev_append l (a :: l2) end. (** Reverse a list. *) Ltac2 rev (l : 'a list) : 'a list := rev_append l []. (** Append two lists [ls1] and [ls2]. Complexity: O(length ls1). *) Ltac2 rec append (ls1 : 'a list) (ls2 : 'a list) : 'a list := match ls1 with | [] => ls2 | x :: xs => x :: append xs ls2 end. (** Concatenate a list of lists. *) Ltac2 rec concat (ls : 'a list list) : 'a list := match ls with | [] => [] | x :: xs => append x (concat xs) end. (** Synonym for [concat]. *) Ltac2 flatten (ls : 'a list list) : 'a list := concat ls. (** Iterate a function on each element of a list. Elements are processed from first to last. *) Ltac2 rec iter (f : 'a -> unit) (ls : 'a list) : unit := match ls with | [] => () | l :: ls => f l; iter f ls end. (** Helper function for [iteri]. *) Ltac2 rec iteri_aux (i : int) (f : int -> 'a -> unit) (ls : 'a list) : unit := match ls with | [] => () | l :: ls => f i l; iteri_aux (Int.add i 1) f ls end. (** Iterate a function [f] on each element of a list. [f] is additionally supplied the index of each element, starting at [0]. Elements are processed from first to last. *) Ltac2 iteri (f : int -> 'a -> unit) (ls : 'a list) : unit := iteri_aux 0 f ls. (** [map f [x0 ; x1 ; ... ; xN]] is [f x0 ; f x1 ; ... ; f xN]. Elements are processed from first to last. *) Ltac2 rec map (f : 'a -> 'b) (ls : 'a list) : 'b list := match ls with | [] => [] | l :: ls => f l :: map f ls end. (** Helper function for [mapi]. *) Ltac2 rec mapi_aux (i : int) (f : int -> 'a -> 'b) (ls : 'a list) : 'b list := match ls with | [] => [] | l :: ls => f i l :: mapi_aux (Int.add i 1) f ls end. (** [mapi f [x0 ; x1 ; ... ; xN]] is [f 0 x0 ; f 1 x1 ; ... ; f N xN]. Elements are processed from first to last. *) Ltac2 mapi (f : int -> 'a -> 'b) (ls : 'a list) : 'b list := mapi_aux 0 f ls. (** Map a function over a list, and then concatenate the results. *) Ltac2 rec flat_map (f : 'a -> 'b list) (xs : 'a list) : 'b list := match xs with | [] => [] | x :: xs => append (f x) (flat_map f xs) end. (** [rev_map f l] is equal to [rev (map f l)], but is more efficient in most cases. *) Ltac2 rev_map (f : 'a -> 'b) (ls : 'a list) : 'b list := let rec rmap_f accu ls := match ls with | [] => accu | a::l => rmap_f (f a :: accu) l end in rmap_f [] ls. (** [fold_right f [a1; ...; an] init] is [f a1 (f a2 (... (f an init) ...))]. *) Ltac2 rec fold_right (f : 'a -> 'b -> 'b) (ls : 'a list) (a : 'b) : 'b := match ls with | [] => a | l :: ls => f l (fold_right f ls a) end. (** [fold_left f init [b1; ...; bn]] is [f (... (f (f init b1) b2) ...) bn]. *) Ltac2 rec fold_left (f : 'a -> 'b -> 'a) (a : 'a) (xs : 'b list) : 'a := match xs with | [] => a | x :: xs => fold_left f (f a x) xs end. Ltac2 fold_lefti (f : int -> 'a -> 'b -> 'a) (a : 'a) (xs : 'b list) : 'a := let rec go i a xs := match xs with | [] => a | x :: xs => go (Int.add i 1) (f i a x) xs end in go 0 a xs. (** Iterate a function over two lists. Elements are processed from first to last. Throws an exception if the lengths of the lists differ. *) Ltac2 rec iter2 (f : 'a -> 'b -> unit) (ls1 : 'a list) (ls2 : 'b list) : unit := match ls1 with | [] => match ls2 with | [] => () | _ :: _ => Control.throw_invalid_argument "List.iter2" end | l1 :: ls1 => match ls2 with | [] => Control.throw_invalid_argument "List.iter2" | l2 :: ls2 => f l1 l2; iter2 f ls1 ls2 end end. (** Map a function over two lists. Elements are processed from first to last. Throws an exception if the lengths of the lists differ. *) Ltac2 rec map2 (f : 'a -> 'b -> 'c) (ls1 : 'a list) (ls2 : 'b list) : 'c list := match ls1 with | [] => match ls2 with | [] => [] | _ :: _ => Control.throw_invalid_argument "List.map2" end | l1 :: ls1 => match ls2 with | [] => Control.throw_invalid_argument "List.map2" | l2 :: ls2 => f l1 l2 :: map2 f ls1 ls2 end end. (** [rev_map2 f l1 l2] is equal to [rev (map2 f l1 l2)], but is more efficient in most cases. *) Ltac2 rev_map2 (f : 'a -> 'b -> 'c) (ls1 : 'a list) (ls2 : 'b list) : 'c list := let rec rmap2_f accu ls1 ls2 := match ls1 with | [] => match ls2 with | [] => accu | _ :: _ => Control.throw_invalid_argument "List.rev_map2" end | l1 :: ls1 => match ls2 with | [] => Control.throw_invalid_argument "List.rev_map2" | l2 :: ls2 => rmap2_f (f l1 l2 :: accu) ls1 ls2 end end in rmap2_f [] ls1 ls2. (** Right fold over two lists. Throws an exception if the lengths of the lists differ. *) Ltac2 rec fold_right2 (f : 'a -> 'b -> 'c -> 'c) (ls1 : 'a list) (ls2 : 'b list) (a : 'c) : 'c := match ls1 with | [] => match ls2 with | [] => a | _ :: _ => Control.throw_invalid_argument "List.fold_right2" end | l1 :: ls1 => match ls2 with | [] => Control.throw_invalid_argument "List.fold_right2" | l2 :: ls2 => f l1 l2 (fold_right2 f ls1 ls2 a) end end. (** Left fold over two lists. Throws an exception if the lengths of the lists differ. *) Ltac2 rec fold_left2 (f : 'a -> 'b -> 'c -> 'a) (a : 'a) (ls1 : 'b list) (ls2 : 'c list) : 'a := match ls1 with | [] => match ls2 with | [] => a | _ :: _ => Control.throw_invalid_argument "List.fold_left2" end | l1 :: ls1 => match ls2 with | [] => Control.throw_invalid_argument "List.fold_left2" | l2 :: ls2 => fold_left2 f (f a l1 l2) ls1 ls2 end end. (** [for_all f l] checks that [f] returns true on _all_ elements of the list [l]. In particular [for_all f []] is [true]. *) Ltac2 rec for_all (f : 'a -> bool) (ls : 'a list) : bool := match ls with | [] => true | x :: xs => match f x with | true => for_all f xs | false => false end end. (** [exist f l] checks that [f] returns true on _at least one_ element of the list [l]. In particular [exist f []] is [false]. We would call this [exists] a la OCaml's [List.exists], but that would be a syntax error (because it conflicts with the notation for tactic `exists`), so instead we name it exist. *) Ltac2 rec exist (f : 'a -> bool) (ls : 'a list) : bool := match ls with | [] => false | x :: xs => match f x with | true => true | false => exist f xs end end. (** Helper function for [for_all2]. *) Ltac2 rec for_all2_aux (on_length_mismatch : 'a list -> 'b list -> bool) f xs ys : bool := match xs with | [] => match ys with | [] => true | _ :: _ => on_length_mismatch xs ys end | x :: xs' => match ys with | [] => on_length_mismatch xs ys | y :: ys' => match f x y with | true => for_all2_aux on_length_mismatch f xs' ys' | false => false end end end. (** Same as [for_all] but for two lists. Throws an exception in case the lengths of the lists differ. *) Ltac2 for_all2 (f : 'a -> 'b -> bool) (xs : 'a list) (ys : 'b list) : bool := for_all2_aux (fun _ _ => Control.throw_invalid_argument "List.for_all2") f xs ys. (** Same as [for_all] but for two lists. Returns [false] in case the lengths of the lists differ. *) Ltac2 equal (f : 'a -> 'b -> bool) (xs : 'a list) (ys : 'b list) : bool := for_all2_aux (fun _ _ => false) f xs ys. (** Same as [exist] but for two lists. Throws an exception if the lengths of the lists differ. *) Ltac2 rec exist2 (f : 'a -> 'b -> bool) (xs : 'a list) (ys : 'b list) : bool := match xs with | [] => match ys with | [] => false | _ :: _ => Control.throw_invalid_argument "List.exist2" end | x :: xs' => match ys with | [] => Control.throw_invalid_argument "List.exist2" | y :: ys' => match f x y with | true => true | false => exist2 f xs' ys' end end end. (** [find_opt f xs] returns the _first_ element of the list [xs] satisfying [f]. Returns [None] if no element is found. *) Ltac2 rec find_opt (f : 'a -> bool) (xs : 'a list) : 'a option := match xs with | [] => None | x :: xs => match f x with | true => Some x | false => find_opt f xs end end. (** [find f xs] returns the _first_ element of the list [xs] satisfying [f]. Throws an exception if no element is found. *) Ltac2 find (f : 'a -> bool) (xs : 'a list) : 'a := match find_opt f xs with | Some v => v | None => Control.throw Not_found end. (** [find_rev_opt f xs] returns the _last_ element of the list [xs] satisfying [f]. Returns [None] if no element is found. *) Ltac2 rec find_rev_opt (f : 'a -> bool) (xs : 'a list) : 'a option := match xs with | [] => None | x :: xs => match find_rev_opt f xs with | Some v => Some v | None => match f x with | true => Some x | false => None end end end. (** [find_rev f xs] returns the _last_ element of the list [xs] satisfying [f]. Throws an exception if no element is found. *) Ltac2 find_rev (f : 'a -> bool) (xs : 'a list) : 'a := match find_rev_opt f xs with | Some v => v | None => Control.throw Not_found end. (** [mem eq a ls] checks if an element of [ls] is equal to [a] according to the user-supplied equality function [eq]. *) Ltac2 mem (eq : 'a -> 'a -> bool) (a : 'a) (ls : 'a list) : bool := exist (eq a) ls. (** [filter f xs] removes all the elements of [xs] which do not satisfy [f]. *) Ltac2 rec filter (f : 'a -> bool) (xs : 'a list) : 'a list := match xs with | [] => [] | x :: xs => match f x with | true => x :: filter f xs | false => filter f xs end end. (** [filter_out f xs] removes all the elements of [xs] which satisfy [f]. *) Ltac2 rec filter_out (f : 'a -> bool) (xs : 'a list) : 'a list := filter (fun x => Bool.neg (f x)) xs. (** Synonym for [filter]. *) Ltac2 find_all (f : 'a -> bool) (ls : 'a list) : 'a list := filter f ls. (** [remove eqb x ls] removes all elements of [ls] which are equal to [x], according to the user-supplied equality function [eqb]. *) Ltac2 remove (eqb : 'a -> 'a -> bool) (x : 'a) (ls : 'a list) : 'a list := filter_out (eqb x) ls. (** [count_occ eqb x ls] counts how many elements of [ls] are equal to [x], according to the user-supplied equality function [eqb]. *) Ltac2 count_occ (eqb : 'a -> 'a -> bool) (x : 'a) (ls : 'a list) : int := length (filter (eqb x) ls). (** [list_power ls1 ls2] is [ls2]^[ls1], or the set of sequences of elements of [ls2] indexed by elements of [ls1], sorted in lexicographic order. *) Ltac2 rec list_power (ls1 : 'a list) (ls2 : 'b list) : ('a * 'b) list list := match ls1 with | [] => [] :: [] | x :: t => flat_map (fun f => map (fun y => (x, y) :: f) ls2) (list_power t ls2) end. (** [partition f l] returns two lists [(l_true, l_false)] such that: - [l_true] is the sublist of elements of [l] which satisfy [f]. - [l_false] is the sublist of elements of [l] which do not satisfy [f]. *) Ltac2 rec partition (f : 'a -> bool) (l : 'a list) : 'a list * 'a list := match l with | [] => ([], []) | x :: tl => let (g, d) := partition f tl in match f x with | true => ((x::g), d) | false => (g, (x::d)) end end. (** [list_prod ls1 ls2] returns the cartesian product of [ls1] and [ls2], i.e. the list of _all_ pairs [(x, y)] where [x] is in [ls1] and [y] is in [ls2]. *) Ltac2 rec list_prod (ls1 : 'a list) (ls2 : 'b list) : ('a * 'b) list := match ls1 with | [] => [] | x :: t => append (map (fun y => (x, y)) ls2) (list_prod t ls2) end. (** [fistn n ls] returns the first [n] elements of [ls]. Throws an exception if [n < 0] or [n > length ls]. *) Ltac2 rec firstn (n : int) (ls : 'a list) : 'a list := Control.assert_valid_argument "List.firstn" (Int.ge n 0); match Int.equal n 0 with | true => [] | false => match ls with | [] => Control.throw_out_of_bounds "List.firstn" | x :: xs => x :: firstn (Int.sub n 1) xs end end. (** [skipn n ls] removes the first [n] elements of [ls]. Throws an exception if [n < 0] or [n > length ls]. *) Ltac2 rec skipn (n : int) (ls : 'a list) : 'a list := Control.assert_valid_argument "List.skipn" (Int.ge n 0); match Int.equal n 0 with | true => ls | false => match ls with | [] => Control.throw_out_of_bounds "List.skipn" | _ :: xs => skipn (Int.sub n 1) xs end end. (** [lastn n ls] returns the last [n] elements of [ls]. Throws an exception if [n < 0] or [n > length ls]. *) Ltac2 lastn (n : int) (ls : 'a list) : 'a list := let l := length ls in Control.assert_valid_argument "List.lastn" (Int.ge n 0); Control.assert_bounds "List.lastn" (Int.le n l); skipn (Int.sub l n) ls. (** [nodup eqb ls] removes duplicates from [ls], according to the user-suppplied equality function [eq]. *) Ltac2 rec nodup (eqb : 'a -> 'a -> bool) (ls : 'a list) : 'a list := match ls with | [] => [] | x :: xs => match mem eqb x xs with | true => nodup eqb xs | false => x :: nodup eqb xs end end. (** [seq start step last] returns the list [start ; (start + step) ; (start + 2*step) ; ...], stopping when [start + n*step >= last]. In particular the lower bound [start] is included, whereas the upper bound [last] is excluded. *) Ltac2 rec seq (start : int) (step : int) (last : int) : int list := match Int.lt (Int.sub last start) step with | true => [] | false => start :: seq (Int.add start step) step last end. (** [init n f] returns the list [f 0 ; f 1 ; ... ; f (n-1)]. Throws an exception if [n < 0]. *) Ltac2 init (n : int) (f : int -> 'a) : 'a list := Control.assert_valid_argument "List.init" (Int.ge n 0); map f (seq 0 1 n). (** [repeat x n] returns the list of length [n] with all elements equal to [x]. *) Ltac2 repeat (x : 'a) (n : int) : 'a list := init n (fun _ => x). (** [assoc eqk k l] returns the first value associated to key [k] in an association list [l], using [eqk] to compare keys for equality. Throws an exception if no value is found. *) Ltac2 assoc (eqk : 'k -> 'k -> bool) (k : 'k) (l : ('k * 'v) list) : 'v := let eq_key kv := let (k', _) := kv in eqk k k' in let (_, v) := find eq_key l in v. (** [assoc eqk k l] returns the first value associated to key [k] in an association list [l], using [eqk] to compare keys for equality. Returns [None] if no value is found. *) Ltac2 assoc_opt (eqk : 'k -> 'k -> bool) (k : 'k) (l : ('k * 'v) list) : 'v option := let eq_key kv := let (k', _) := kv in eqk k k' in match find_opt eq_key l with | Some kv => let (_, v) := kv in Some v | None => None end. (** [mem_assoc eqk k l] checks if the key [k] is present in an association list [l], using [eqk] to compare keys for equality. *) Ltac2 mem_assoc (eqk : 'k -> 'k -> bool) (k : 'k) (l : ('k * 'v) list) : bool := let eq_key kv := let (k', _) := kv in eqk k k' in exist eq_key l. (** [remove_assoc eqk k l] removes _all_ key/value pairs associated with key [k] from an association list [l], using [eqk] to compare keys for equality. *) Ltac2 remove_assoc (eqk : 'k -> 'k -> bool) (k : 'k) (l : ('k * 'v) list) : ('k * 'v) list := let eq_key kv := let (k', _) := kv in eqk k k' in filter_out eq_key l. (** Split a list of pairs into a pair of lists. *) Ltac2 rec split (ls : ('a * 'b) list) : 'a list * 'b list := match ls with | [] => ([], []) | xy :: tl => let (x, y) := xy in let (left, right) := split tl in ((x::left), (y::right)) end. (** Combine two lists into a list of pairs. Only pairs of elements at the same position are considered. Throws an exception if the lengths of the lists differ. *) Ltac2 rec combine (ls1 : 'a list) (ls2 : 'b list) : ('a * 'b) list := match ls1 with | [] => match ls2 with | [] => [] | _ :: _ => Control.throw_invalid_argument "List.combine" end | x :: xs => match ls2 with | y :: ys => (x, y) :: combine xs ys | [] => Control.throw_invalid_argument "List.combine" end end. (** [enumerate [x0 ; x1 ; x2 ; ...]] returns the list [(0, x0) ; (1, x1) ; (2, x2) ; ...]. *) Ltac2 enumerate (ls : 'a list) := mapi (fun i v => (i,v)) ls. (** Merge two list sorted in increasing order into a sorted list, using a user-provided comparison function. *) Ltac2 rec merge (cmp : 'a -> 'a -> int) (l1 : 'a list) (l2 : 'a list) : 'a list := let rec merge_aux l2 := match l1 with | [] => l2 | a1 :: l1' => match l2 with | [] => l1 | a2 :: l2' => match Int.le (cmp a1 a2) 0 with | true => a1 :: merge cmp l1' l2 | false => a2 :: merge_aux l2' end end end in merge_aux l2. Ltac2 rec merge_list_to_stack cmp stack l := match stack with | [] => [Some l] | l' :: stack' => match l' with | None => Some l :: stack' | Some l' => None :: merge_list_to_stack cmp stack' (merge cmp l' l) end end. Ltac2 rec merge_stack cmp stack := match stack with | [] => [] | l :: stack' => match l with | None => merge_stack cmp stack' | Some l => merge cmp l (merge_stack cmp stack') end end. Ltac2 rec iter_merge cmp stack l := match l with | [] => merge_stack cmp stack | a::l' => iter_merge cmp (merge_list_to_stack cmp stack [a]) l' end. (** [sort cmp l] sorts the list [l] in increasing order, according to the user-supplied comparison function [cmp]. It is currently implemented using a variant of merge sort. *) Ltac2 sort (cmp : 'a -> 'a -> int) (l : 'a list) : 'a list := iter_merge cmp [] l. (** [sort cmp l] sorts the list [l] in increasing order and removes duplicates, according to the user-supplied comparison function [cmp]. This takes advantage of the fact that removing duplicates from a sorted list is much faster than for an arbitrary list. *) Ltac2 sort_uniq (cmp : 'a -> 'a -> int) (l : 'a list) : 'a list := let rec uniq l := match l with | [] => [] | x1 :: xs => match xs with | [] => x1 :: xs | x2 :: _ => match Int.equal (cmp x1 x2) 0 with | true => uniq xs | false => x1 :: uniq xs end end end in uniq (sort cmp l). (** [inclusive_range lb ub] returns the list [lb ; lb+1 ; lb+2 ; ... ; up]. In particular both the lower bound [lb] and upper bound [ub] are included. *) Ltac2 inclusive_range (lb : int) (ub : int) : int list := seq lb 1 (Int.add ub 1). (** [range lb ub] returns the list [lb ; lb+1 ; lb+2 ; ... ; up-1]. In particular the lower bound [lb] is included, whereas the upper bound [ub] is excluded. *) Ltac2 range (lb : int) (ub : int) : int list := seq lb 1 ub. (** [concat_rev [x1; ..; xN-1; xN]] computes [rev xN ++ rev xN-1 ++ .. ++ x1]. Note that [x1] is not reversed and appears in its original order. [concat_rev] is faster than [concat] and should be preferred over [concat] when the order of items does not matter. *) Ltac2 concat_rev (ls : 'a list list) : 'a list := let rec go ls acc := match ls with | [] => acc | l :: ls => go ls (rev_append l acc) end in match ls with | [] => [] | l :: ls => go ls l end. (** [map_filter f l] maps [f] over [l], then removes all elements that are [None]. *) Ltac2 rec map_filter (f : 'a -> 'b option) (l : 'a list) : 'b list := match l with | [] => [] | x :: l => match f x with | Some y => y :: map_filter f l | None => map_filter f l end end. rocq-9.2.0/theories/Ltac2/Ltac1.v000066400000000000000000000074161516144147600164310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_ref". (** Returns the Ltac1 definition with the given absolute name. *) Ltac2 @ external run : t -> unit := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_run". (** Runs an Ltac1 value, assuming it is a 'tactic', i.e. not returning anything. *) Ltac2 @ external lambda : (t -> t) -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_lambda". (** Embed an Ltac2 function into Ltac1 values. Contrarily to the ltac1:(...) quotation, this function allows both to capture an Ltac2 context inside the closure and to return an Ltac1 value. Returning values in Ltac1 is a intrepid endeavour prone to weird runtime semantics. *) Ltac2 @ external apply : t -> t list -> (t -> unit) -> unit := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_apply". (** Applies an Ltac1 value to a list of arguments, and provides the result in CPS style. It does **not** run the returned value. *) (** Conversion functions *) Ltac2 @ external of_int : int -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_int". (** Converts an Ltac2 int into an Ltac1 value. *) Ltac2 @ external to_int : t -> int option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_int". (** Converts an Ltac1 int into an Ltac2 value. *) Ltac2 @ external of_constr : constr -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_constr". (** Converts an Ltac2 constr into an Ltac1 value. *) Ltac2 @ external to_constr : t -> constr option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_constr". (** Converts an Ltac1 constr (which includes terms created via open_constr) into an Ltac2 value. *) (** [preterm] is called [uconstr] in Ltac1. *) Ltac2 @ external of_preterm : preterm -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_preterm". Ltac2 @ external to_preterm : t -> preterm option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_preterm". Ltac2 @ external of_ident : ident -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_ident". Ltac2 @ external to_ident : t -> ident option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_ident". Ltac2 @ external of_list : t list -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_list". Ltac2 @ external to_list : t -> t list option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_list". Ltac2 @ external of_intro_pattern : intro_pattern -> t := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_of_intro_pattern". Ltac2 @ external to_intro_pattern : t -> intro_pattern option := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_to_intro_pattern". (** Debug information *) Ltac2 @ external tag_name : t -> string := "rocq-runtime.plugins.ltac2_ltac1" "ltac1_tag_name". (** Name of the ltac1 value class the argument belongs to. Should be used only for error printing, typically "expected a constr but got a tag_name". *) rocq-9.2.0/theories/Ltac2/Ltac1CompatNotations.v000066400000000000000000000021601516144147600214630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit := "rocq-runtime.plugins.ltac2" "print". Ltac2 @ external empty : message := "rocq-runtime.plugins.ltac2" "message_empty". Ltac2 @ external of_string : string -> message := "rocq-runtime.plugins.ltac2" "message_of_string". Ltac2 @ external to_string : message -> string := "rocq-runtime.plugins.ltac2" "message_to_string". Ltac2 @ external of_int : int -> message := "rocq-runtime.plugins.ltac2" "message_of_int". Ltac2 @ external of_ident : ident -> message := "rocq-runtime.plugins.ltac2" "message_of_ident". Ltac2 @ external of_constr : constr -> message := "rocq-runtime.plugins.ltac2" "message_of_constr". (** Prints at level 8 (surrounding with parentheses to print syntax above that level such as applications). Panics if there is more than one goal under focus. *) Ltac2 @ external of_lconstr : constr -> message := "rocq-runtime.plugins.ltac2" "message_of_lconstr". (** Prints at level 200 (no surrounding parentheses). Panics if there is more than one goal under focus. *) Ltac2 @external of_preterm : preterm -> message := "rocq-runtime.plugins.ltac2" "message_of_preterm". (** Prints at level 8. Panics if there is more than one goal under focus. *) Ltac2 @external of_lpreterm : preterm -> message := "rocq-runtime.plugins.ltac2" "message_of_lpreterm". (** Prints at level 200. Panics if there is more than one goal under focus. *) Ltac2 @ external of_exn : exn -> message := "rocq-runtime.plugins.ltac2" "message_of_exn". (** Panics if there is more than one goal under focus. *) Ltac2 @external of_exninfo : exninfo -> message := "rocq-runtime.plugins.ltac2" "message_of_exninfo". (** Print the (Ltac2 and OCaml) backtrace info if it was recorded. *) Ltac2 @ external concat : message -> message -> message := "rocq-runtime.plugins.ltac2" "message_concat". (** Boxing primitives. They are translated to OCaml "Format" boxes, see https://ocaml.org/docs/formatting-text **) Ltac2 @external force_new_line : message := "rocq-runtime.plugins.ltac2" "message_force_new_line". (** Force writing on a new line after this. Warning: partially reinitialises the pretty-printing engine, potentially leading to bad printing afterwards. Prefer using a break hint inside a vertical box. *) Ltac2 @external break : int -> int -> message := "rocq-runtime.plugins.ltac2" "message_break". (** General break hint: [break n i] either prints [n] spaces or splits the line adding [i] to the current indentation. *) Ltac2 @external space : message := "rocq-runtime.plugins.ltac2" "message_space". (** Breaking space. Equivalent to [break 1 0]. *) Ltac2 @external hbox : message -> message := "rocq-runtime.plugins.ltac2" "message_hbox". (** Horizontal box. Break hints in a horizontal box never split the line (nested boxes inside the horizontal box may allow line splitting). *) Ltac2 @external vbox : int -> message -> message := "rocq-runtime.plugins.ltac2" "message_vbox". (** Vertical box. Every break hint in a vertical box splits the line. The [int] is added to the current indentation when splitting the line. *) Ltac2 @external hvbox : int -> message -> message := "rocq-runtime.plugins.ltac2" "message_hvbox". (** Horizontal/vertical box. Behaves as a horizontal box if it fits on a single line, otherwise behaves as a vertical box (using the given [int]). *) Ltac2 @external hovbox : int -> message -> message := "rocq-runtime.plugins.ltac2" "message_hovbox". (** Horizonal-or-vertical box. Prints as much as possible on each line, splitting the line at break hints when there is no more room on the line (see "Printing Width" option). The [int] is added to the indentation when splitting the line. *) Module Format. (** Only for internal use. *) Ltac2 @ external stop : ('a, 'b, 'c, 'a) format := "rocq-runtime.plugins.ltac2" "format_stop". Ltac2 @ external string : ('a, 'b, 'c, 'd) format -> (string -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_string". Ltac2 @ external int : ('a, 'b, 'c, 'd) format -> (int -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_int". Ltac2 @ external constr : ('a, 'b, 'c, 'd) format -> (constr -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_constr". Ltac2 @ external ident : ('a, 'b, 'c, 'd) format -> (ident -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_ident". Ltac2 @ external message : ('a, 'b, 'c, 'd) format -> (message -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_message". Ltac2 @ external literal : string -> ('a, 'b, 'c, 'd) format -> ('a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_literal". Ltac2 @ external alpha : ('a, 'b, 'c, 'd) format -> (('b -> 'r -> 'c) -> 'r -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_alpha". Ltac2 @ external alpha0 : ('a, 'b, 'c, 'd) format -> (('r -> 'c) -> 'r -> 'a, 'b, 'c, 'd) format := "rocq-runtime.plugins.ltac2" "format_alpha0". Ltac2 @ external kfprintf : (message -> 'r) -> ('a, unit, message, 'r) format -> 'a := "rocq-runtime.plugins.ltac2" "format_kfprintf". Ltac2 @ external ikfprintf : ('v -> 'r) -> 'v -> ('a, unit, 'v, 'r) format -> 'a := "rocq-runtime.plugins.ltac2" "format_ikfprintf". End Format. rocq-9.2.0/theories/Ltac2/Meta.v000066400000000000000000000014551516144147600163500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "meta_equal". rocq-9.2.0/theories/Ltac2/Module.v000066400000000000000000000123021516144147600167000ustar00rootroot00000000000000(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "module_equal". (** Print a module name. *) Ltac2 @external to_message : t -> message := "rocq-runtime.plugins.ltac2" "module_to_message". (** This returns [true] for both module types and module type functors. *) Ltac2 @external is_modtype : t -> bool := "rocq-runtime.plugins.ltac2" "module_is_modtype". (** This returns [true] for both module functors and module type functors. *) Ltac2 @external is_functor : t -> bool := "rocq-runtime.plugins.ltac2" "module_is_functor". (** This returns [true] for modules which are arguments of a currently open functor ([false] for submodules of bound modules). *) Ltac2 @external is_bound_module : t -> bool := "rocq-runtime.plugins.ltac2" "module_is_bound_module". (** This returns [true] for modules which are libraries (i.e. files). *) Ltac2 @external is_library : t -> bool := "rocq-runtime.plugins.ltac2" "module_is_library". (** This returns [true] if the argument refers to a currently open interactive module (or module type or functor). *) Ltac2 @external is_open : t -> bool := "rocq-runtime.plugins.ltac2" "module_is_open". (** Return the parent module, ie [A] for [A.B]. Toplevel modules (libraries) and bound modules (functor arguments) return [None]. *) Ltac2 @external parent_module : t -> t option := "rocq-runtime.plugins.ltac2" "module_parent_module". (** Throws on [VarRef]. *) Ltac2 @external module_of_reference : Std.reference -> t := "rocq-runtime.plugins.ltac2" "module_of_reference". (** Returns a reference to the current innermost open interactive module. *) Ltac2 @external current_module : unit -> t := "rocq-runtime.plugins.ltac2" "current_module". Ltac2 @external loaded_libraries : unit -> t list := "rocq-runtime.plugins.ltac2" "module_loaded_libraries". Module Field. (** This API is written using a record of functions to implement case analysis instead of exposing [t] as a sum type for forward compatibility: a case analysis can be written as [{ handle_nothing with ...}] and any new field kinds will be handled without error. *) (** Type of module fields. *) Ltac2 Type t. (** Information about rewrite rules. Currently nothing is exposed about it. *) Ltac2 Type rewrule. (** Case analysis over a module field. *) Ltac2 Type 'a handler := { handle_submodule : Module.t -> 'a; handle_reference : Std.reference -> 'a; handle_rewrule : rewrule -> 'a; }. (** Default case analysis. *) Ltac2 handle_nothing := { handle_submodule := (fun _ => None); handle_reference := (fun _ => None); handle_rewrule := (fun _ => None); }. (** Execute a case analysis. *) Ltac2 @external handle : t -> 'a handler -> 'a := "rocq-runtime.plugins.ltac2" "module_field_handle". (** Test whether a module field is a submodule (or sub-module type or sub-functor). *) Ltac2 is_submodule (f:t) : Module.t option := handle f { handle_nothing with handle_submodule := (fun x => Some x) }. (** Test whether a module field is a reference. *) Ltac2 is_reference (f:t) : Std.reference option := handle f { handle_nothing with handle_reference := (fun x => Some x) }. End Field. (** Return the contents of the given module. [None] on closed functors and module types. Inductives are represented only by the first inductive of each mutual block (and no constructors). *) Ltac2 @external module_contents : t -> Field.t list option := "rocq-runtime.plugins.ltac2" "module_contents". (** Deeply fold over references in the given module (e.g. if [mod] is [M] and contains submodule [M.N] which contains reference [M.N.x], [M.N.x] will be passed to [f]). *) Ltac2 rec deep_fold_child_references (f:'a -> Std.reference -> 'a) (acc:'a) (mod:t) : 'a := match module_contents mod with | None => acc | Some contents => List.fold_left (fun acc field => Field.handle field { Field.handle_submodule := (fun mod => deep_fold_child_references f acc mod); Field.handle_reference := (fun r => f acc r); Field.handle_rewrule := (fun _ => acc); }) acc contents end. rocq-9.2.0/theories/Ltac2/Notations.v000066400000000000000000000453101516144147600174360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* f e | Val ans => let (x, k) := ans in Control.plus (fun _ => x) k end. Ltac2 ifcatch t s f := match Control.case t with | Err e => f e | Val ans => let (x, k) := ans in Control.plus (fun _ => s x) (fun e => s (k e)) end. Ltac2 fail0 (_ : unit) := Control.enter (fun _ => Control.zero (Tactic_failure None)). Ltac2 Abbreviation fail := fail0 (). Ltac2 try0 t := Control.enter (fun _ => orelse t (fun _ => ())). Ltac2 Abbreviation try := try0. Ltac2 rec repeat0 (t : unit -> unit) := Control.enter (fun () => ifcatch (fun _ => Control.progress t) (fun _ => Control.check_interrupt (); repeat0 t) (fun _ => ())). Ltac2 Abbreviation repeat := repeat0. Ltac2 dispatch0 t (head, tail) := match tail with | None => Control.enter (fun _ => t (); Control.dispatch head) | Some tacs => let (def, rem) := tacs in Control.enter (fun _ => t (); Control.extend head def rem) end. Ltac2 Notation t(thunk(self)) ">" "[" l(dispatch) "]" : 4 := dispatch0 t l. Ltac2 do0 n t := let rec aux n t := match Int.equal n 0 with | true => () | false => t (); aux (Int.sub n 1) t end in aux (n ()) t. Ltac2 Abbreviation do := do0. Ltac2 Abbreviation once := Control.once. Ltac2 Abbreviation unshelve := Control.unshelve. Ltac2 cycle := Control.cycle. Ltac2 progress0 tac := Control.enter (fun _ => Control.progress tac). Ltac2 Abbreviation progress := progress0. Ltac2 rec first0 tacs := match tacs with | [] => Control.zero (Tactic_failure None) | tac :: tacs => Control.enter (fun _ => orelse tac (fun _ => first0 tacs)) end. Ltac2 Notation "first" "[" tacs(list0(thunk(tactic(6)), "|")) "]" := first0 tacs. Ltac2 complete tac := let ans := tac () in Control.enter (fun () => Control.zero (Tactic_failure None)); ans. Ltac2 rec solve0 tacs := match tacs with | [] => Control.zero (Tactic_failure None) | tac :: tacs => Control.enter (fun _ => orelse (fun _ => complete tac) (fun _ => solve0 tacs)) end. Ltac2 Notation "solve" "[" tacs(list0(thunk(tactic(6)), "|")) "]" := solve0 tacs. Ltac2 time0 tac := Control.time None tac. Ltac2 Abbreviation time := time0. Ltac2 abstract0 tac := Control.abstract None tac. Ltac2 Abbreviation abstract := abstract0. (** Base tactics *) (** Note that we redeclare notations that can be parsed as mere identifiers as abbreviations, so that it allows to parse them as function arguments without having to write them within parentheses. *) (** Enter and check evar resolution *) Ltac2 enter_h ev f arg := match ev with | true => Control.enter (fun () => f ev (arg ())) | false => Control.enter (fun () => Control.with_holes arg (fun x => f ev x)) end. Ltac2 intros0 ev p := Control.enter (fun () => Std.intros ev p). Ltac2 Notation "intros" p(intropatterns) := intros0 false p. Ltac2 Abbreviation intros := intros. Ltac2 Notation "eintros" p(intropatterns) := intros0 true p. Ltac2 Abbreviation eintros := eintros. Ltac2 split0 ev bnd := enter_h ev Std.split bnd. Ltac2 Notation "split" bnd(thunk(with_bindings)) := split0 false bnd. Ltac2 Abbreviation split := split. Ltac2 Notation "esplit" bnd(thunk(with_bindings)) := split0 true bnd. Ltac2 Abbreviation esplit := esplit. Ltac2 exists0 ev bnds := match bnds with | [] => split0 ev (fun () => Std.NoBindings) | _ => let rec aux bnds := match bnds with | [] => () | bnd :: bnds => split0 ev bnd; aux bnds end in aux bnds end. Ltac2 Notation "exists" bnd(list0(thunk(bindings), ",")) := exists0 false bnd. (* Ltac2 Abbreviation exists := exists. *) Ltac2 Notation "eexists" bnd(list0(thunk(bindings), ",")) := exists0 true bnd. Ltac2 Abbreviation eexists := eexists. Ltac2 left0 ev bnd := enter_h ev Std.left bnd. Ltac2 Notation "left" bnd(thunk(with_bindings)) := left0 false bnd. Ltac2 Abbreviation left := left. Ltac2 Notation "eleft" bnd(thunk(with_bindings)) := left0 true bnd. Ltac2 Abbreviation eleft := eleft. Ltac2 right0 ev bnd := enter_h ev Std.right bnd. Ltac2 Notation "right" bnd(thunk(with_bindings)) := right0 false bnd. Ltac2 Abbreviation right := right. Ltac2 Notation "eright" bnd(thunk(with_bindings)) := right0 true bnd. Ltac2 Abbreviation eright := eright. Ltac2 constructor0 ev n bnd := enter_h ev (fun ev bnd => Std.constructor_n ev n bnd) bnd. Local Ltac2 constructor1 ev x := match x with | None => Control.enter (fun () => Std.constructor ev) | Some (tac, bnd) => constructor0 ev tac bnd end. Ltac2 Abbreviation constructor := constructor1 false None. Ltac2 Notation "constructor" x(opt(seq(tactic,thunk(with_bindings)))) := constructor1 false x. Ltac2 Abbreviation econstructor := constructor1 true None. Ltac2 Notation "econstructor" x(opt(seq(tactic,thunk(with_bindings)))) := constructor1 true x. Ltac2 specialize0 c pat := enter_h false (fun _ c => Std.specialize c pat) c. Ltac2 Notation "specialize" c(thunk(seq(constr, with_bindings))) ipat(opt(seq("as", intropattern))) := specialize0 c ipat. Ltac2 elim0 ev c bnd use := let f ev (c, bnd, use) := Std.elim ev (c, bnd) use in enter_h ev f (fun () => c (), bnd (), use ()). Ltac2 Notation "elim" c(thunk(constr)) bnd(thunk(with_bindings)) use(thunk(opt(seq("using", constr, with_bindings)))) := elim0 false c bnd use. Ltac2 Notation "eelim" c(thunk(constr)) bnd(thunk(with_bindings)) use(thunk(opt(seq("using", constr, with_bindings)))) := elim0 true c bnd use. Ltac2 apply0 adv ev cb cl := Std.apply adv ev cb cl. Ltac2 Notation "eapply" cb(list1(thunk(seq(open_constr, with_bindings)), ",")) cl(opt(seq("in", ident, opt(seq("as", intropattern))))) := apply0 true true cb cl. Ltac2 Notation "apply" cb(list1(thunk(seq(open_constr, with_bindings)), ",")) cl(opt(seq("in", ident, opt(seq("as", intropattern))))) := apply0 true false cb cl. Ltac2 default_on_concl cl := match cl with | None => { Std.on_hyps := Some []; Std.on_concl := Std.AllOccurrences } | Some cl => cl end. Ltac2 pose0 ev p := enter_h ev (fun _ (na, p) => Std.pose na p) p. Ltac2 Notation "pose" p(thunk(pose)) := pose0 false p. Ltac2 Notation "epose" p(thunk(pose)) := pose0 true p. Ltac2 Notation "set" p(thunk(pose)) cl(opt(clause)) := Std.set false p (default_on_concl cl). Ltac2 Notation "eset" p(thunk(pose)) cl(opt(clause)) := Std.set true p (default_on_concl cl). Ltac2 assert0 ev ast := enter_h ev (fun _ ast => Std.assert ast) ast. Ltac2 Notation "assert" ast(thunk(assert)) := assert0 false ast. Ltac2 Notation "eassert" ast(thunk(assert)) := assert0 true ast. Ltac2 enough_from_assertion(a : Std.assertion) := match a with | Std.AssertType ip_opt term tac_opt => Std.enough term (Some tac_opt) ip_opt | Std.AssertValue ident constr => Std.pose (Some ident) constr end. Ltac2 enough0 ev ast := enter_h ev (fun _ ast => enough_from_assertion ast) ast. Ltac2 Notation "enough" ast(thunk(assert)) := enough0 false ast. Ltac2 Notation "eenough" ast(thunk(assert)) := enough0 true ast. Ltac2 default_everywhere cl := match cl with | None => { Std.on_hyps := None; Std.on_concl := Std.AllOccurrences } | Some cl => cl end. Ltac2 Notation "remember" c(thunk(open_constr)) na(opt(seq("as", ident))) pat(opt(seq("eqn", ":", intropattern))) cl(opt(clause)) := Std.remember false na c pat (default_everywhere cl). Ltac2 Notation "eremember" c(thunk(open_constr)) na(opt(seq("as", ident))) pat(opt(seq("eqn", ":", intropattern))) cl(opt(clause)) := Std.remember true na c pat (default_everywhere cl). Ltac2 induction0 ev ic use := let f ev use := Std.induction ev ic use in enter_h ev f use. Ltac2 Notation "induction" ic(list1(induction_clause, ",")) use(thunk(opt(seq("using", constr, with_bindings)))) := induction0 false ic use. Ltac2 Notation "einduction" ic(list1(induction_clause, ",")) use(thunk(opt(seq("using", constr, with_bindings)))) := induction0 true ic use. Ltac2 generalize0 gen := enter_h false (fun _ gen => Std.generalize gen) gen. Ltac2 Notation "generalize" gen(thunk(list1(seq (open_constr, occurrences, opt(seq("as", ident))), ","))) := generalize0 gen. Ltac2 destruct0 ev ic use := let f ev use := Std.destruct ev ic use in enter_h ev f use. Ltac2 Notation "destruct" ic(list1(induction_clause, ",")) use(thunk(opt(seq("using", constr, with_bindings)))) := destruct0 false ic use. Ltac2 Notation "edestruct" ic(list1(induction_clause, ",")) use(thunk(opt(seq("using", constr, with_bindings)))) := destruct0 true ic use. Ltac2 Notation "simple" "inversion" arg(destruction_arg) pat(opt(seq("as", intropattern))) ids(opt(seq("in", list1(ident)))) := Std.inversion Std.SimpleInversion arg pat ids. Ltac2 Notation "inversion" arg(destruction_arg) pat(opt(seq("as", intropattern))) ids(opt(seq("in", list1(ident)))) := Std.inversion Std.FullInversion arg pat ids. Ltac2 Notation "inversion_clear" arg(destruction_arg) pat(opt(seq("as", intropattern))) ids(opt(seq("in", list1(ident)))) := Std.inversion Std.FullInversionClear arg pat ids. Ltac2 Abbreviation exfalso := Std.exfalso (). Ltac2 Notation "red" cl(opt(clause)) := Std.red (default_on_concl cl). Ltac2 Abbreviation red := red. Ltac2 Notation "hnf" cl(opt(clause)) := Std.hnf (default_on_concl cl). Ltac2 Abbreviation hnf := hnf. Ltac2 Notation "simpl" s(strategy) pl(opt(seq(pattern, occurrences))) cl(opt(clause)) := Std.simpl s pl (default_on_concl cl). Ltac2 Abbreviation simpl := simpl. Ltac2 Notation "cbv" s(strategy) cl(opt(clause)) := Std.cbv s (default_on_concl cl). Ltac2 Abbreviation cbv := cbv. Ltac2 Notation "cbn" s(strategy) cl(opt(clause)) := Std.cbn s (default_on_concl cl). Ltac2 Abbreviation cbn := cbn. Ltac2 Notation "lazy" s(strategy) cl(opt(clause)) := Std.lazy s (default_on_concl cl). Ltac2 Abbreviation lazy := lazy. Ltac2 Notation "unfold" pl(list1(seq(reference, occurrences), ",")) cl(opt(clause)) := Std.unfold pl (default_on_concl cl). Ltac2 fold0 pl cl := let cl := default_on_concl cl in Control.enter (fun () => Control.with_holes pl (fun pl => Std.fold pl cl)). Ltac2 Notation "fold" pl(thunk(list1(open_constr))) cl(opt(clause)) := fold0 pl cl. Ltac2 Notation "pattern" pl(list1(seq(constr, occurrences), ",")) cl(opt(clause)) := Std.pattern pl (default_on_concl cl). Ltac2 Notation "vm_compute" pl(opt(seq(pattern, occurrences))) cl(opt(clause)) := Std.vm pl (default_on_concl cl). Ltac2 Abbreviation vm_compute := vm_compute. Ltac2 Notation "native_compute" pl(opt(seq(pattern, occurrences))) cl(opt(clause)) := Std.native pl (default_on_concl cl). Ltac2 Abbreviation native_compute := native_compute. Ltac2 Notation "eval" "red" "in" c(constr) := Std.eval_red c. Ltac2 Notation "eval" "hnf" "in" c(constr) := Std.eval_hnf c. Ltac2 Notation "eval" "simpl" s(strategy) pl(opt(seq(pattern, occurrences))) "in" c(constr) := Std.eval_simpl s pl c. Ltac2 Notation "eval" "cbv" s(strategy) "in" c(constr) := Std.eval_cbv s c. Ltac2 Notation "eval" "cbn" s(strategy) "in" c(constr) := Std.eval_cbn s c. Ltac2 Notation "eval" "lazy" s(strategy) "in" c(constr) := Std.eval_lazy s c. Ltac2 Notation "eval" "unfold" pl(list1(seq(reference, occurrences), ",")) "in" c(constr) := Std.eval_unfold pl c. Ltac2 Notation "eval" "fold" pl(thunk(list1(open_constr))) "in" c(constr) := Std.eval_fold (pl ()) c. Ltac2 Notation "eval" "pattern" pl(list1(seq(constr, occurrences), ",")) "in" c(constr) := Std.eval_pattern pl c. Ltac2 Notation "eval" "vm_compute" pl(opt(seq(pattern, occurrences))) "in" c(constr) := Std.eval_vm pl c. Ltac2 Notation "eval" "native_compute" pl(opt(seq(pattern, occurrences))) "in" c(constr) := Std.eval_native pl c. Ltac2 change0 p cl := let (pat, c) := p in Std.change pat c (default_on_concl cl). Ltac2 Notation "change" c(conversion) cl(opt(clause)) := change0 c cl. Ltac2 rewrite0 ev rw cl tac := let cl := default_on_concl cl in Std.rewrite ev rw cl tac. Ltac2 Notation "rewrite" rw(list1(rewriting, ",")) cl(opt(clause)) tac(opt(seq("by", thunk(tactic)))) := rewrite0 false rw cl tac. Ltac2 Notation "setoid_rewrite" ori(orient) c(thunk(seq(open_constr, with_bindings))) occs(occurrences) id(opt(seq("in", ident))) := Std.setoid_rewrite (Option.default Std.LTR ori) c occs id. Ltac2 Notation "erewrite" rw(list1(rewriting, ",")) cl(opt(clause)) tac(opt(seq("by", thunk(tactic)))) := rewrite0 true rw cl tac. (** coretactics *) (** Provided for backwards compat *) #[deprecated(since="8.19")] Ltac2 exact0 ev c := Control.enter (fun _ => match ev with | true => let c := c () in Control.refine (fun _ => c) | false => Control.with_holes c (fun c => Control.refine (fun _ => c)) end ). Ltac2 exact1 ev c := Control.enter (fun () => let c := Constr.Pretype.pretype (if ev then Constr.Pretype.Flags.open_constr_flags_with_tc else Constr.Pretype.Flags.constr_flags) (Constr.Pretype.expected_oftype (Control.goal())) c in Std.exact_no_check c). Ltac2 Notation "exact" c(preterm) := exact1 false c. Ltac2 Notation "eexact" c(preterm) := exact1 true c. (** Like [refine] but new evars are shelved instead of becoming subgoals. *) Ltac2 Notation "intro" id(opt(ident)) mv(opt(move_location)) := Std.intro id mv. Ltac2 Abbreviation intro := intro. Ltac2 Notation "move" id(ident) mv(move_location) := Std.move id mv. Ltac2 Abbreviation reflexivity := Std.reflexivity (). Ltac2 symmetry0 cl := Std.symmetry (default_on_concl cl). Ltac2 Notation "symmetry" cl(opt(clause)) := symmetry0 cl. Ltac2 Abbreviation symmetry := symmetry. Ltac2 Notation "revert" ids(list1(ident)) := Std.revert ids. Ltac2 Abbreviation assumption := Std.assumption (). Ltac2 Abbreviation eassumption := Std.eassumption (). Ltac2 Abbreviation etransitivity := Std.etransitivity (). Ltac2 Abbreviation admit := Std.admit (). Ltac2 clear0 ids := match ids with | [] => Std.keep [] | _ => Std.clear ids end. Ltac2 Notation "clear" ids(list0(ident)) := clear0 ids. Ltac2 Notation "clear" "-" ids(list1(ident)) := Std.keep ids. Ltac2 Abbreviation clear := clear. Ltac2 Abbreviation refine := Control.refine. (** extratactics *) Ltac2 absurd0 c := Control.enter (fun _ => Std.absurd (c ())). Ltac2 Notation "absurd" c(thunk(open_constr)) := absurd0 c. Ltac2 subst0 ids := match ids with | [] => Std.subst_all () | _ => Std.subst ids end. Ltac2 Notation "subst" ids(list0(ident)) := subst0 ids. Ltac2 Abbreviation subst := subst. Ltac2 Notation "discriminate" arg(opt(destruction_arg)) := Std.discriminate false arg. Ltac2 Abbreviation discriminate := discriminate. Ltac2 Notation "ediscriminate" arg(opt(destruction_arg)) := Std.discriminate true arg. Ltac2 Abbreviation ediscriminate := ediscriminate. Ltac2 Notation "injection" arg(opt(destruction_arg)) ipat(opt(seq("as", intropatterns))):= Std.injection false ipat arg. Ltac2 Notation "einjection" arg(opt(destruction_arg)) ipat(opt(seq("as", intropatterns))):= Std.injection true ipat arg. (** Auto *) Ltac2 default_db dbs := match dbs with | None => Some [] | Some dbs => match dbs with | None => None | Some l => Some l end end. Ltac2 default_list use := match use with | None => [] | Some use => use end. Ltac2 trivial0 use dbs := let dbs := default_db dbs in let use := default_list use in Std.trivial Std.Off use dbs. Ltac2 Notation "trivial" use(opt(seq("using", list1(reference, ",")))) dbs(opt(seq("with", hintdb))) := trivial0 use dbs. Ltac2 Abbreviation trivial := trivial. Ltac2 auto0 n use dbs := let dbs := default_db dbs in let use := default_list use in Std.auto Std.Off n use dbs. Ltac2 Notation "auto" n(opt(tactic(0))) use(opt(seq("using", list1(reference, ",")))) dbs(opt(seq("with", hintdb))) := auto0 n use dbs. Ltac2 Abbreviation auto := auto. Ltac2 eauto0 n use dbs := let dbs := default_db dbs in let use := default_list use in Std.eauto Std.Off n use dbs. Ltac2 Notation "eauto" n(opt(tactic(0))) use(opt(seq("using", list1(reference, ",")))) dbs(opt(seq("with", hintdb))) := eauto0 n use dbs. Ltac2 Abbreviation eauto := eauto. Ltac2 Notation "typeclasses_eauto" n(opt(tactic(0))) dbs(opt(seq("with", list1(ident)))) := Std.typeclasses_eauto None n dbs. Ltac2 Notation "typeclasses_eauto" "bfs" n(opt(tactic(0))) dbs(opt(seq("with", list1(ident)))) := Std.typeclasses_eauto (Some Std.BFS) n dbs. Ltac2 Abbreviation typeclasses_eauto := typeclasses_eauto. Ltac2 Notation "unify" x(constr) y(constr) := Std.unify x y. (** Congruence *) Ltac2 Notation "congruence" n(opt(tactic(0))) l(opt(seq("with", list1(constr)))) := Std.congruence n l. Ltac2 Notation "simple" "congruence" n(opt(tactic(0))) l(opt(seq("with", list1(constr)))) := Std.simple_congruence n l. #[deprecated(since="9.1", note="Use Std.f_equal instead.")] Ltac2 f_equal0 := Std.f_equal. Ltac2 Abbreviation f_equal := Std.f_equal (). (** now *) Ltac2 now0 t := t (); ltac1:(easy_forward_decl). Ltac2 Notation "now" t(thunk(tactic(6))) := now0 t. (** profiling *) Ltac2 start_profiling () := ltac1:(start ltac profiling). Ltac2 stop_profiling () := ltac1:(stop ltac profiling). Ltac2 show_profile () := ltac1:(show ltac profile). rocq-9.2.0/theories/Ltac2/Option.v000066400000000000000000000051701516144147600167300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit) (ov : 'a option) := match ov with | Some v => f v | None => () end. Ltac2 map (f : 'a -> 'b) (ov : 'a option) := match ov with | Some v => Some (f v) | None => None end. Ltac2 filter (f : 'a -> bool) (o : 'a option) := match o with | Some x => if f x then Some x else None | None => None end. Ltac2 iter (f : 'a -> unit) (ov : 'a option) := match ov with | Some v => f v | None => () end. Ltac2 default (def : 'a) (ov : 'a option) := match ov with | Some v => v | None => def end. Ltac2 map_default (f : 'a -> 'b) (def : 'b) (ov : 'a option) := match ov with | Some v => f v | None => def end. Ltac2 get (ov : 'a option) := match ov with | Some v => v | None => Control.throw No_value end. Ltac2 get_bt (ov : 'a option) := match ov with | Some v => v | None => Control.zero No_value end. Ltac2 bind (x : 'a option) (f : 'a -> 'b option) := match x with | Some x => f x | None => None end. Ltac2 join (x : 'a option option) := match x with | Some x => x | None => None end. Ltac2 ret (x : 'a) := Some x. Ltac2 lift (f : 'a -> 'b) (x : 'a option) := map f x. Ltac2 equal (eq : 'a -> 'b -> bool) (a : 'a option) (b : 'b option) : bool := match a with | None => match b with | None => true | _ => false end | Some a => match b with | Some b => eq a b | _ => false end end. Ltac2 compare (cmp : 'a -> 'b -> int) (a : 'a option) (b : 'b option) := match a, b with | Some a, Some b => cmp a b | None, None => 0 | None, Some _ => -1 | Some _, None => 1 end. Ltac2 is_some (a : 'a option) := match a with | Some _ => true | None => false end. Ltac2 is_none (a : 'a option) := match a with | Some _ => false | None => true end. rocq-9.2.0/theories/Ltac2/Pattern.v000066400000000000000000000144101516144147600170720ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* constr -> (ident * constr) list := "rocq-runtime.plugins.ltac2" "pattern_matches". (** If the term matches the pattern, returns the bound variables. If it doesn't, fail with [Match_failure]. Panics if not focused. *) Ltac2 @ external matches_subterm : t -> constr -> context * ((ident * constr) list) := "rocq-runtime.plugins.ltac2" "pattern_matches_subterm". (** Returns a stream of results corresponding to all of the subterms of the term that matches the pattern as in [matches]. The stream is encoded as a backtracking value whose last exception is [Match_failure]. The additional value compared to [matches] is the context of the match, to be filled with the instantiate function. *) Ltac2 @ external matches_vect : t -> constr -> constr array := "rocq-runtime.plugins.ltac2" "pattern_matches_vect". (** Internal version of [matches] that does not return the identifiers. *) Ltac2 @ external matches_subterm_vect : t -> constr -> context * constr array := "rocq-runtime.plugins.ltac2" "pattern_matches_subterm_vect". (** Internal version of [matches_subterms] that does not return the identifiers. *) Ltac2 @ external matches_goal : bool -> ((match_kind * t) option * (match_kind * t)) list -> (match_kind * t) -> ident array * context array * context array * constr array * context := "rocq-runtime.plugins.ltac2" "pattern_matches_goal". (** Given a list of patterns [hpats] for hypotheses and one pattern [cpat] for the conclusion, [matches_goal rev hpats cpat] produces (a stream of) tuples of: - An array of idents, whose size is the length of [hpats], corresponding to the name of matched hypotheses. - An array of contexts, whose size is the number of [hpats] which have non empty body pattern, corresponding to the contexts matched for every body pattern. In case the match kind of a body pattern was [MatchPattern], the corresponding context is ensured to be empty. - An array of contexts, whose size is the length of [hpats], corresponding to the contexts matched for every hypothesis pattern. In case the match kind of a hypothesis was [MatchPattern], the corresponding context is ensured to be empty. - An array of terms, whose size is the total number of pattern variables without duplicates. Terms are ordered by identifier order, e.g. ?a comes before ?b. - A context corresponding to the conclusion, which is ensured to be empty if the kind of [cpat] was [MatchPattern]. This produces a backtracking stream of results containing all the possible result combinations. The order of considered hypotheses is reversed if [rev] is true. *) Ltac2 @ external instantiate : context -> constr -> constr := "rocq-runtime.plugins.ltac2" "pattern_instantiate". (** Fill the hole of a context with the given term. *) (** Implementation of Ltac matching over terms and goals *) Ltac2 Type 'a constr_matching := (match_kind * t * (context -> constr array -> 'a)) list. Ltac2 lazy_match0 t (pats:'a constr_matching) := let rec interp m := match m with | [] => Control.zero Match_failure | p :: m => let next _ := interp m in let (knd, pat, f) := p in let p := match knd with | MatchPattern => (fun _ => let context := empty_context in let bind := matches_vect pat t in fun _ => f context bind) | MatchContext => (fun _ => let (context, bind) := matches_subterm_vect pat t in fun _ => f context bind) end in Control.plus p next end in Control.once (fun () => interp pats) (). Ltac2 multi_match0 t (pats:'a constr_matching) := let rec interp e m := match m with | [] => Control.zero e | p :: m => let next e := interp e m in let (knd, pat, f) := p in let p := match knd with | MatchPattern => (fun _ => let context := empty_context in let bind := matches_vect pat t in f context bind) | MatchContext => (fun _ => let (context, bind) := matches_subterm_vect pat t in f context bind) end in Control.plus p next end in interp Match_failure pats. Ltac2 one_match0 t m := Control.once (fun _ => multi_match0 t m). Ltac2 Type 'a goal_matching := ((((match_kind * t) option * (match_kind * t)) list * (match_kind * t)) * (ident array -> context array -> context array -> constr array -> context -> 'a)) list. Ltac2 lazy_goal_match0 rev (pats:'a goal_matching) := let rec interp m := match m with | [] => Control.zero Match_failure | p :: m => let next _ := interp m in let (pat, f) := p in let (phyps, pconcl) := pat in let cur _ := let (hids, hbctx, hctx, subst, cctx) := matches_goal rev phyps pconcl in fun _ => f hids hbctx hctx subst cctx in Control.plus cur next end in Control.once (fun () => interp pats) (). Ltac2 multi_goal_match0 rev (pats:'a goal_matching) := let rec interp e m := match m with | [] => Control.zero e | p :: m => let next e := interp e m in let (pat, f) := p in let (phyps, pconcl) := pat in let cur _ := let (hids, hbctx, hctx, subst, cctx) := matches_goal rev phyps pconcl in f hids hbctx hctx subst cctx in Control.plus cur next end in interp Match_failure pats. Ltac2 one_goal_match0 rev pats := Control.once (fun _ => multi_goal_match0 rev pats). rocq-9.2.0/theories/Ltac2/Printf.v000066400000000000000000000051551516144147600167250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* > where the type value defines which kind of arguments will be accepted and how they will be printed. They can take the following values. - << i >>: takes an argument of type int and behaves as Message.of_int - << I >>: takes an argument of type ident and behaves as Message.of_ident - << s >>: takes an argument of type string and behaves as Message.of_string - << m >>: takes an argument of type message and prints it unmodified - << t >>: takes an argument of type constr and behaves as Message.of_constr - << a >>: takes two arguments << f >> of type << (unit -> 'a -> message) >> and << x >> of type << 'a >> and behaves as << f () x >> - << A >>: takes two arguments << f >> of type << ('a -> message) >> and << x >> of type << 'a >> and behaves as << f x >> - << % >>: outputs << % >> verbatim TODO: add printing modifiers. *) Ltac2 printf fmt := Format.kfprintf print fmt. Ltac2 fprintf fmt := Format.kfprintf (fun x => x) fmt. (** The two following notations are made available when this module is imported. - printf will parse a format and generate a function taking the corresponding arguments ant printing the resulting message as per Message.print. In particular when fully applied it has type unit. - fprintf behaves similarly but return the message as a value instead of printing it. *) Ltac2 Notation "printf" fmt(format) := printf fmt. Ltac2 Notation "fprintf" fmt(format) := fprintf fmt. rocq-9.2.0/theories/Ltac2/Proj.v000066400000000000000000000045631516144147600163770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "projection_equal". (** Projections obtained through module aliases or Include are not considered equal by this function. The unfolding boolean is not ignored. *) Ltac2 @ external ind : t -> inductive := "rocq-runtime.plugins.ltac2" "projection_ind". (** Get the inductive to which the projectin belongs. *) Ltac2 @ external index : t -> int := "rocq-runtime.plugins.ltac2" "projection_index". (** The index of the projection indicates which field it projects. *) Ltac2 @ external unfolded : t -> bool := "rocq-runtime.plugins.ltac2" "projection_unfolded". (** Get the unfolding boolean. *) Ltac2 @ external set_unfolded : t -> bool -> t := "rocq-runtime.plugins.ltac2" "projection_set_unfolded". (** Set the unfolding boolean. *) Ltac2 @ external of_constant : constant -> t option := "rocq-runtime.plugins.ltac2" "projection_of_constant". (** Get the primitive projection associated to the constant. The returned projection is folded. Returns [None] when the constant is not associated to a primitive projection. *) Ltac2 @ external to_constant : t -> constant option := "rocq-runtime.plugins.ltac2" "projection_to_constant". (** Get the constant associated to the primitive projection. Currently always returns [Some] but this may change in the future. *) Ltac2 @external print : t -> message := "rocq-runtime.plugins.ltac2" "projection_print". (** Print the projection using the shortest qualified identifier which refers to it. Does not avoid variable names in the current or global environment. *) rocq-9.2.0/theories/Ltac2/Pstring.v000066400000000000000000000032231516144147600171030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string := "rocq-runtime.plugins.ltac2" "pstring_to_string". Ltac2 @ external of_string : string -> t option := "rocq-runtime.plugins.ltac2" "pstring_of_string". Ltac2 @ external make : uint63 -> char63 -> t := "rocq-runtime.plugins.ltac2" "pstring_make". Ltac2 @ external length : t -> uint63 := "rocq-runtime.plugins.ltac2" "pstring_length". Ltac2 @ external get : t -> uint63 -> char63 := "rocq-runtime.plugins.ltac2" "pstring_get". Ltac2 @ external sub : t -> uint63 -> uint63 -> t := "rocq-runtime.plugins.ltac2" "pstring_sub". Ltac2 @ external cat : t -> t -> t := "rocq-runtime.plugins.ltac2" "pstring_cat". Ltac2 @ external equal : t -> t -> bool := "rocq-runtime.plugins.ltac2" "pstring_equal". Ltac2 @ external compare : t -> t -> int := "rocq-runtime.plugins.ltac2" "pstring_compare". rocq-9.2.0/theories/Ltac2/RedFlags.v000066400000000000000000000027111516144147600171450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a) : unit := r.(contents) := f (r.(contents)). rocq-9.2.0/theories/Ltac2/Reference.v000066400000000000000000000006571516144147600173630ustar00rootroot00000000000000Require Import Ltac2.Init. Require Ltac2.Std Ltac2.Ident Ltac2.Ind Ltac2.Constructor Ltac2.Constant. Ltac2 Type t := Std.reference. Import Ltac2.Std. Ltac2 equal r1 r2 := match r1, r2 with | VarRef i1, VarRef i2 => Ident.equal i1 i2 | ConstRef c1, ConstRef c2 => Constant.equal c1 c2 | IndRef ind1, IndRef ind2 => Ind.equal ind1 ind2 | ConstructRef cstr1, ConstructRef cstr2 => Constructor.equal cstr1 cstr2 | _, _ => false end. rocq-9.2.0/theories/Ltac2/Rewrite.v000066400000000000000000000126251516144147600171040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t := "rocq-runtime.plugins.ltac2" "rewstrat_progress". (** Applies left, and then right if left succeeded. *) Ltac2 @external seq : t -> t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_seq". (** Equivalent to [List.fold_left seq id]. *) Ltac2 @external seqs : t list -> t := "rocq-runtime.plugins.ltac2" "rewstrat_seqs". (** Applies left, and then right if left failed. *) Ltac2 @external choice : t -> t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_choice". (** Equivalent to [List.fold_left choice fail]. *) Ltac2 @external choices : t list -> t := "rocq-runtime.plugins.ltac2" "rewstrat_choices". (** Equivalent to [choice s id]. *) Ltac2 @external try : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_try". (** Applies the argument until it fails. *) Ltac2 @external any : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_any". (** Equivalent to [seq s (any s)]. *) Ltac2 @external repeat : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_repeat". (** Applies the argument to all immediate subterms of the considered term, left-to-right. *) Ltac2 @external subterms : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_all_subterms". (** Applies the argument to the leftmost immediate subterm of the considered term on which progress can be made. *) Ltac2 @external subterm : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_one_subterm". (** Traverses the term bottom-up--left-to-right and applies the argument at each step as many times as possible. *) Ltac2 @external bottomup : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_bottomup". (** Traverses the term top-down--left-to-right and applies the argument at each step as many times as possible. *) Ltac2 @external topdown : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_topdown". (** Traverses the term bottom-up--left-to-right until the argument makes progress. *) Ltac2 @external innermost : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_innermost". (** Traverses the term top-down--left-to-right until the argument makes progress. *) Ltac2 @external outermost : t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_outermost". (** Unifies the one side of the lemma with the current subterm and on success rewrite it to the other side. If the boolean argument is true, rewrites left-to-right; otherwise, rewrites right-to-left. *) Ltac2 @external term : preterm -> bool -> t := "rocq-runtime.plugins.ltac2" "rewstrat_one_lemma". (** Equivalent to [choices (List.map (fun c => term c true)) l]. *) Ltac2 @external terms : preterm list -> t := "rocq-runtime.plugins.ltac2" "rewstrat_lemmas". (* TODO this needs documentation *) Ltac2 @external old_hints : ident -> t := "rocq-runtime.plugins.ltac2" "rewstrat_old_hints". (** Applies hints from rewrite hint database. *) Ltac2 @external hints : ident -> t := "rocq-runtime.plugins.ltac2" "rewstrat_hints". (** Replaces the term under consideration with the argument if they unify. *) Ltac2 @external fold : constr -> t := "rocq-runtime.plugins.ltac2" "rewstrat_fold". (** Converts the term under consideration. *) Ltac2 @external eval : Std.Red.t -> t := "rocq-runtime.plugins.ltac2" "rewstrat_eval". (** Fixed point operation for recursive strategies. [fix (fun f => s)] evaluates to [s[f / fix (fun f => s)]]. The function provided in the argument is executed only _once_ when the strategy is constructed β€” it cannot be used for dynamically manage the rewriting. *) Ltac2 @external fix_ : (t -> t) -> t := "rocq-runtime.plugins.ltac2" "rewstrat_fix". End Strategy. (* Tactics *) (** Runs rewrite strategy on the type of a hypothesis or the goal if the second argument is [None]. *) Ltac2 @external rewrite_strat : Strategy.t -> ident option -> unit := "rocq-runtime.plugins.ltac2" "tac_rewrite_strat". (** Runs rewritings from a hint database on the type of a hypothesis or the goal if the second argument is [None]. The rewritings are applied top-down on all subterms. *) Ltac2 rewrite_db (hintdb : ident) (i : ident option) : unit := rewrite_strat (Strategy.topdown (Strategy.hints hintdb)) i. rocq-9.2.0/theories/Ltac2/Std.v000066400000000000000000000410331516144147600162100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* constr), intro_pattern) | IntroRewrite (bool) ] with or_and_intro_pattern := [ | IntroOrPattern (intro_pattern list list) | IntroAndPattern (intro_pattern list) ]. Ltac2 Type destruction_arg := [ | ElimOnConstr (unit -> constr_with_bindings) | ElimOnIdent (ident) | ElimOnAnonHyp (int) ]. Ltac2 Type induction_clause := { indcl_arg : destruction_arg; indcl_eqn : intro_pattern_naming option; indcl_as : or_and_intro_pattern option; indcl_in : clause option; }. Ltac2 Type assertion := [ | AssertType (intro_pattern option, constr, (unit -> unit) option) | AssertValue (ident, constr) ]. Ltac2 Type repeat := [ | Precisely (int) | UpTo (int) | RepeatStar | RepeatPlus ]. Ltac2 Type orientation := [ LTR | RTL ]. Ltac2 Type rewriting := { rew_orient : orientation option; rew_repeat : repeat; rew_equatn : (unit -> constr_with_bindings); }. Ltac2 Type evar_flag := bool. Ltac2 Type advanced_flag := bool. Ltac2 Type move_location := [ | MoveAfter (ident) | MoveBefore (ident) | MoveFirst | MoveLast ]. Ltac2 Type inversion_kind := [ | SimpleInversion | FullInversion | FullInversionClear ]. (** Standard, built-in tactics. See Ltac1 for documentation. *) Ltac2 @ external intros : evar_flag -> intro_pattern list -> unit := "rocq-runtime.plugins.ltac2" "tac_intros". Ltac2 @ external apply : advanced_flag -> evar_flag -> (unit -> constr_with_bindings) list -> (ident * (intro_pattern option)) option -> unit := "rocq-runtime.plugins.ltac2" "tac_apply". Ltac2 @ external elim : evar_flag -> constr_with_bindings -> constr_with_bindings option -> unit := "rocq-runtime.plugins.ltac2" "tac_elim". Ltac2 @ external case : evar_flag -> constr_with_bindings -> unit := "rocq-runtime.plugins.ltac2" "tac_case". Ltac2 @ external generalize : (constr * occurrences * ident option) list -> unit := "rocq-runtime.plugins.ltac2" "tac_generalize". Ltac2 @ external assert : assertion -> unit := "rocq-runtime.plugins.ltac2" "tac_assert". Ltac2 @ external enough : constr -> (unit -> unit) option option -> intro_pattern option -> unit := "rocq-runtime.plugins.ltac2" "tac_enough". Ltac2 @ external pose : ident option -> constr -> unit := "rocq-runtime.plugins.ltac2" "tac_pose". Ltac2 @ external set : evar_flag -> (unit -> ident option * constr) -> clause -> unit := "rocq-runtime.plugins.ltac2" "tac_set". Ltac2 @ external remember : evar_flag -> ident option -> (unit -> constr) -> intro_pattern option -> clause -> unit := "rocq-runtime.plugins.ltac2" "tac_remember". Ltac2 @ external destruct : evar_flag -> induction_clause list -> constr_with_bindings option -> unit := "rocq-runtime.plugins.ltac2" "tac_destruct". Ltac2 @ external induction : evar_flag -> induction_clause list -> constr_with_bindings option -> unit := "rocq-runtime.plugins.ltac2" "tac_induction". Ltac2 @external exfalso : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_exfalso". (** Constructors for reduction/expansion strategies *) Module Red. Ltac2 Type t. (** Ξ²ΞΉΞΆ-reduction of the _head constant_ of a term. Fails if there is no reducible head constant. *) Ltac2 @external red : t := "rocq-runtime.plugins.ltac2" "red". (** Full βδι΢-reduction the head of a term. Does not recurse into subterms. *) Ltac2 @external hnf : t := "rocq-runtime.plugins.ltac2" "hnf". (** Strong normalization except two key differences: - It unfolds constants only if they lead to an ΞΉ-reduction, i.e. reducing a match or unfolding a fixpoint. - When reducing a constant unfolding to (co)fixpoints, uses the name of the constant the (co)fixpoint comes from instead of the (co)fixpoint definition in recursive calls. Can unfold transparent constants as well as those designated by [Arguments] commands. The second parameter can limit the application of [simpl] to specific subterms matching. If the pattern resolves into a global reference, it will be treated as such. Only the following [red_flags] are relevant: [head], [delta]. *) Ltac2 @external simpl : red_flags -> (pattern * occurrences) option -> t := "rocq-runtime.plugins.ltac2" "simpl". (** Full normalization using provided reduction flags by first evaluating the head of the expression into weak-head normal form in _call-by-value_ order. Once a weak-head normal form is obtained, subterms are recursively reduced using the same strategy. *) Ltac2 @external cbv : red_flags -> t := "rocq-runtime.plugins.ltac2" "cbv". (** [cbn] was intended to be a more principled, faster and more predictable replacement for [simpl]. The main difference is that cbn may unfold constants even when they cannot be reused in recursive calls. Certain modifiers are also not treated the same. See the respective Ltac1 tactic documentation for more details. Setting [Debug "RAKAM"] makes [cbn] print various debugging information.. *) Ltac2 @external cbn : red_flags -> t := "rocq-runtime.plugins.ltac2" "cbn". (** Full normalization using provided reduction flags by first evaluating the head of the expression into weak-head normal form in _call-by-need_ order. Once a weak-head normal form is obtained, subterms are recursively reduced using the same strategy. *) Ltac2 @external lazy : red_flags -> t := "rocq-runtime.plugins.ltac2" "lazy". (** Applies delta-reduction to the constants specified by each [reference * occurrences] and then reduces to Ξ²ΞΉΞΆ-normal form. Use the general reductions if you want to only apply the Ξ΄ rule, for example [cbv] with [delta]. *) Ltac2 @external unfold : (reference * occurrences) list -> t := "rocq-runtime.plugins.ltac2" "unfold". (** First, reduces each [constr] using [red]. Then, every occurrence of the resulting terms will be replaced by its associated [constr]. *) Ltac2 @external fold : constr list -> t := "rocq-runtime.plugins.ltac2" "fold". (** Performs beta-expansion (the inverse of beta-reduction). The [constr]s must be free subterms in the subject of reduction. The expansion is done by: 1. Replacing all selected occurrences of the [constr]s in the term with fresh variables 2. Abstracting these variables 3. Applying the abstracted term to the [constr]s *) Ltac2 @external pattern : (constr * occurrences) list -> t := "rocq-runtime.plugins.ltac2" "pattern". (** Optimized _call-by-value_ evaluation on a bytecode-based virtual machine. This algorithm is dramatically more efficient than the algorithm used for [cbv], but it cannot be fine-tuned. It is especially useful for full evaluation of algebraic objects. This includes the case of reflection-based tactics. *) Ltac2 @external vm : (pattern * occurrences) option -> t := "rocq-runtime.plugins.ltac2" "vm". (** Evaluates the goal by compilation to OCaml. Depending on the configuration, it can either default to [vm], recompile dependencies or fail due to some missing precompiled dependencies. See the [native-compiler] option for details. *) Ltac2 @external native : (pattern * occurrences) option -> t := "rocq-runtime.plugins.ltac2" "native". End Red. (** Reduction/expansion tactics *) Ltac2 @external eval_in : Red.t -> clause -> unit := "rocq-runtime.plugins.ltac2" "reduce_in". Ltac2 red (c : clause) : unit := eval_in Red.red c. Ltac2 hnf (c : clause) : unit := eval_in Red.hnf c. Ltac2 simpl (flags : red_flags) (occs : (pattern * occurrences) option) (c : clause) := eval_in (Red.simpl flags occs) c. Ltac2 cbv (flags : red_flags) (c : clause) : unit := eval_in (Red.cbv flags) c. Ltac2 cbn (flags : red_flags) (c : clause) : unit := eval_in (Red.cbn flags) c. Ltac2 lazy (flags : red_flags) (c : clause) : unit := eval_in (Red.lazy flags) c. Ltac2 unfold (occs : (reference * occurrences) list) (c : clause) : unit := eval_in (Red.unfold occs) c. Ltac2 fold (cs : constr list) (c : clause) : unit := eval_in (Red.fold cs) c. Ltac2 pattern (occs : (constr * occurrences) list) (c : clause) : unit := eval_in (Red.pattern occs) c. Ltac2 vm (ctx : (pattern * occurrences) option) (c : clause) : unit := eval_in (Red.vm ctx) c. Ltac2 native (ctx : (pattern * occurrences) option) (c : clause) : unit := eval_in (Red.native ctx) c. (** Constr reduction/expansion functions *) Ltac2 @external eval : Red.t -> constr -> constr := "rocq-runtime.plugins.ltac2" "reduce_constr". Ltac2 eval_red (c : constr) : constr := eval Red.red c. Ltac2 eval_hnf (c : constr) : constr := eval Red.hnf c. Ltac2 eval_simpl (flags : red_flags) (occs : (pattern * occurrences) option) (c : constr) := eval (Red.simpl flags occs) c. Ltac2 eval_cbv (flags : red_flags) (c : constr) : constr := eval (Red.cbv flags) c. Ltac2 eval_cbn (flags : red_flags) (c : constr) : constr := eval (Red.cbn flags) c. Ltac2 eval_lazy (flags : red_flags) (c : constr) : constr := eval (Red.lazy flags) c. Ltac2 eval_unfold (occs : (reference * occurrences) list) (c : constr) : constr := eval (Red.unfold occs) c. Ltac2 eval_fold (cs : constr list) (c : constr) : constr := eval (Red.fold cs) c. Ltac2 eval_pattern (occs : (constr * occurrences) list) (c : constr) : constr := eval (Red.pattern occs) c. Ltac2 eval_vm (ctx : (pattern * occurrences) option) (c : constr) : constr := eval (Red.vm ctx) c. Ltac2 eval_native (ctx : (pattern * occurrences) option) (c : constr) : constr := eval (Red.native ctx) c. Ltac2 @ external change : pattern option -> (constr array -> constr) -> clause -> unit := "rocq-runtime.plugins.ltac2" "tac_change". Ltac2 @ external rewrite : evar_flag -> rewriting list -> clause -> (unit -> unit) option -> unit := "rocq-runtime.plugins.ltac2" "tac_rewrite". Ltac2 @ external setoid_rewrite : orientation -> (unit -> constr_with_bindings) -> occurrences -> ident option -> unit := "rocq-runtime.plugins.ltac2" "tac_setoid_rewrite". Ltac2 @ external reflexivity : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_reflexivity". Ltac2 @ external assumption : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_assumption". Ltac2 @ external eassumption : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_eassumption". Ltac2 @ external transitivity : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_transitivity". Ltac2 @ external etransitivity : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_etransitivity". Ltac2 @ external cut : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_cut". Ltac2 @ external left : evar_flag -> bindings -> unit := "rocq-runtime.plugins.ltac2" "tac_left". Ltac2 @ external right : evar_flag -> bindings -> unit := "rocq-runtime.plugins.ltac2" "tac_right". Ltac2 @ external constructor : evar_flag -> unit := "rocq-runtime.plugins.ltac2" "tac_constructor". Ltac2 @ external split : evar_flag -> bindings -> unit := "rocq-runtime.plugins.ltac2" "tac_split". Ltac2 @ external constructor_n : evar_flag -> int -> bindings -> unit := "rocq-runtime.plugins.ltac2" "tac_constructorn". Ltac2 @ external intros_until : hypothesis -> unit := "rocq-runtime.plugins.ltac2" "tac_introsuntil". Ltac2 @ external symmetry : clause -> unit := "rocq-runtime.plugins.ltac2" "tac_symmetry". Ltac2 @ external rename : (ident * ident) list -> unit := "rocq-runtime.plugins.ltac2" "tac_rename". Ltac2 @ external revert : ident list -> unit := "rocq-runtime.plugins.ltac2" "tac_revert". Ltac2 @ external admit : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_admit". Ltac2 @ external fix_ : ident -> int -> unit := "rocq-runtime.plugins.ltac2" "tac_fix". Ltac2 @ external cofix_ : ident -> unit := "rocq-runtime.plugins.ltac2" "tac_cofix". Ltac2 @ external clear : ident list -> unit := "rocq-runtime.plugins.ltac2" "tac_clear". Ltac2 @ external keep : ident list -> unit := "rocq-runtime.plugins.ltac2" "tac_keep". Ltac2 @ external clearbody : ident list -> unit := "rocq-runtime.plugins.ltac2" "tac_clearbody". Ltac2 @ external exact_no_check : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_exactnocheck". Ltac2 @ external vm_cast_no_check : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_vmcastnocheck". Ltac2 @ external native_cast_no_check : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_nativecastnocheck". Ltac2 @ external inversion : inversion_kind -> destruction_arg -> intro_pattern option -> ident list option -> unit := "rocq-runtime.plugins.ltac2" "tac_inversion". (** coretactics *) Ltac2 @ external move : ident -> move_location -> unit := "rocq-runtime.plugins.ltac2" "tac_move". Ltac2 @ external intro : ident option -> move_location option -> unit := "rocq-runtime.plugins.ltac2" "tac_intro". Ltac2 @ external specialize : constr_with_bindings -> intro_pattern option -> unit := "rocq-runtime.plugins.ltac2" "tac_specialize". (** extratactics *) Ltac2 @ external discriminate : evar_flag -> destruction_arg option -> unit := "rocq-runtime.plugins.ltac2" "tac_discriminate". Ltac2 @ external injection : evar_flag -> intro_pattern list option -> destruction_arg option -> unit := "rocq-runtime.plugins.ltac2" "tac_injection". Ltac2 @ external absurd : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_absurd". Ltac2 @ external contradiction : constr_with_bindings option -> unit := "rocq-runtime.plugins.ltac2" "tac_contradiction". Ltac2 @ external autorewrite : bool -> (unit -> unit) option -> ident list -> clause -> unit := "rocq-runtime.plugins.ltac2" "tac_autorewrite". Ltac2 @ external subst : ident list -> unit := "rocq-runtime.plugins.ltac2" "tac_subst". Ltac2 @ external subst_all : unit -> unit := "rocq-runtime.plugins.ltac2" "tac_substall". (** auto *) Ltac2 Type debug := [ Off | Info | Debug ]. Ltac2 Type strategy := [ BFS | DFS ]. Ltac2 @ external trivial : debug -> reference list -> ident list option -> unit := "rocq-runtime.plugins.ltac2" "tac_trivial". Ltac2 @ external auto : debug -> int option -> reference list -> ident list option -> unit := "rocq-runtime.plugins.ltac2" "tac_auto". Ltac2 @ external eauto : debug -> int option -> reference list -> ident list option -> unit := "rocq-runtime.plugins.ltac2" "tac_eauto". Ltac2 @ external typeclasses_eauto : strategy option -> int option -> ident list option -> unit := "rocq-runtime.plugins.ltac2" "tac_typeclasses_eauto". Ltac2 @ external resolve_tc : constr -> unit := "rocq-runtime.plugins.ltac2" "tac_resolve_tc". (** Resolve the existential variables appearing in the constr whose types are typeclasses. Fail if any of them cannot be resolved. Does not focus. *) Ltac2 @ external unify : constr -> constr -> unit := "rocq-runtime.plugins.ltac2" "tac_unify". Ltac2 @ external congruence : int option -> constr list option -> unit := "rocq-runtime.plugins.ltac2" "congruence". Ltac2 @ external simple_congruence : int option -> constr list option -> unit := "rocq-runtime.plugins.ltac2" "simple_congruence". Ltac2 @external f_equal : unit -> unit := "rocq-runtime.plugins.ltac2" "f_equal". rocq-9.2.0/theories/Ltac2/String.v000066400000000000000000000031711516144147600167250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* char -> string := "rocq-runtime.plugins.ltac2" "string_make". Ltac2 @external length : string -> int := "rocq-runtime.plugins.ltac2" "string_length". Ltac2 @external get : string -> int -> char := "rocq-runtime.plugins.ltac2" "string_get". Ltac2 @external set : string -> int -> char -> unit := "rocq-runtime.plugins.ltac2" "string_set". Ltac2 @external concat : string -> string list -> string := "rocq-runtime.plugins.ltac2" "string_concat". Ltac2 @external app : string -> string -> string := "rocq-runtime.plugins.ltac2" "string_app". Ltac2 @external sub : string -> int -> int -> string := "rocq-runtime.plugins.ltac2" "string_sub". Ltac2 @external equal : string -> string -> bool := "rocq-runtime.plugins.ltac2" "string_equal". Ltac2 @external compare : string -> string -> int := "rocq-runtime.plugins.ltac2" "string_compare". Ltac2 is_empty s := match s with "" => true | _ => false end. rocq-9.2.0/theories/Ltac2/TransparentState.v000066400000000000000000000025201516144147600207560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t := "rocq-runtime.plugins.ltac2" "current_transparent_state". rocq-9.2.0/theories/Ltac2/Uint63.v000066400000000000000000000020661516144147600165510ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> bool := "rocq-runtime.plugins.ltac2" "uint63_equal". Ltac2 @external compare : t -> t -> int := "rocq-runtime.plugins.ltac2" "uint63_compare". Ltac2 @external of_int : int -> t := "rocq-runtime.plugins.ltac2" "uint63_of_int". Ltac2 @external print : t -> message := "rocq-runtime.plugins.ltac2" "uint63_print". rocq-9.2.0/theories/Ltac2/Unification.v000066400000000000000000000056111516144147600177300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* TransparentState.t -> constr -> constr -> bool := "rocq-runtime.plugins.ltac2" "infer_conv". (** It only unfolds constants that are transparent in the current state *) Ltac2 conv_current : constr -> constr -> bool := fun c1 c2 => conv CONV (TransparentState.current ()) c1 c2. (** All constants are considered as transparents when doing conversion *) Ltac2 conv_full : constr -> constr -> bool := fun c1 c2 => conv CONV TransparentState.full c1 c2. (** Unification **) (** [unify ts c1 c2] unifies [c1] and [c2] (using Evarconv unification), which may have the effect of instantiating evars. If the [c1] and [c2] cannot be unified, an [Internal] exception is raised. *) Ltac2 @ external unify : TransparentState.t -> constr -> constr -> unit := "rocq-runtime.plugins.ltac2" "evarconv_unify". (** [unify_with_full_ts] is like [unify TransparentState.full]. *) Ltac2 unify_with_full_ts : constr -> constr -> unit := fun c1 c2 => unify TransparentState.full c1 c2. (** [unify_with_current_ts] is like [unify (TransparentState.current ())]. *) Ltac2 unify_with_current_ts : constr -> constr -> unit := fun c1 c2 => unify (TransparentState.current ()) c1 c2. (** [solve_constraints ()] solves any delayed unification constraints. *) Ltac2 @external solve_constraints : unit -> unit := "rocq-runtime.plugins.ltac2" "solve_constraints". rocq-9.2.0/theories/Ltac2/_CoqProject000066400000000000000000000000301516144147600174120ustar00rootroot00000000000000-Q . Ltac2 -arg -noinit rocq-9.2.0/theories/Ltac2/dune.disabled000066400000000000000000000003611516144147600177120ustar00rootroot00000000000000(coq.theory (name Ltac2) (package rocq-core) (synopsis "Ltac2 tactic language") (flags -w -deprecated-native-compiler-option) (stdlib no) (theories Corelib) (plugins rocq-runtime.plugins.ltac2_ltac1 rocq-runtime.plugins.ltac2)) rocq-9.2.0/tools/000077500000000000000000000000001516144147600136375ustar00rootroot00000000000000rocq-9.2.0/tools/CoqMakefile.in000066400000000000000000000774711516144147600163670ustar00rootroot00000000000000########################################################################## ## # The Rocq Prover / The Rocq Development Team ## ## v # Copyright INRIA, CNRS and contributors ## ## /dev/null 2>/dev/null; echo $$?)) STDTIME?=command time -f $(TIMEFMT) else ifeq (0,$(shell gtime -f "" true >/dev/null 2>/dev/null; echo $$?)) STDTIME?=gtime -f $(TIMEFMT) else STDTIME?=command time endif endif COQBIN?= ifneq (,$(COQBIN)) # add an ending / COQBIN:=$(COQBIN)/ endif # Coq binaries ROCQ ?= "$(COQBIN)rocq" COQC ?= "$(COQBIN)rocq" c COQTOP ?= "$(COQBIN)rocq" repl COQCHK ?= "$(COQBIN)rocqchk" COQNATIVE ?= "$(COQBIN)rocq" native-precompile COQDEP ?= "$(COQBIN)rocq" dep COQDOC ?= "$(COQBIN)rocq" doc COQPP ?= "$(COQBIN)rocq" pp-mlg COQMKFILE ?= "$(COQBIN)rocq" makefile OCAMLLIBDEP ?= "$(COQBIN)ocamllibdep" # Timing scripts COQMAKE_ONE_TIME_FILE ?= "$(COQCORELIB)/tools/make-one-time-file.py" COQMAKE_BOTH_TIME_FILES ?= "$(COQCORELIB)/tools/make-both-time-files.py" COQMAKE_BOTH_SINGLE_TIMING_FILES ?= "$(COQCORELIB)/tools/make-both-single-timing-files.py" BEFORE ?= AFTER ?= # OCaml binaries CAMLC ?= "$(OCAMLFIND)" ocamlc -c CAMLOPTC ?= "$(OCAMLFIND)" opt -c CAMLLINK ?= "$(OCAMLFIND)" ocamlc -linkall CAMLOPTLINK ?= "$(OCAMLFIND)" opt -linkall CAMLDOC ?= "$(OCAMLFIND)" ocamldoc CAMLDEP ?= "$(OCAMLFIND)" ocamldep -slash -ml-synonym .mlpack # DESTDIR is prepended to all installation paths DESTDIR ?= # Debug builds, typically -g to OCaml, -debug to Rocq. CAMLDEBUG ?= COQDEBUG ?= # Extra packages to be linked in (as in findlib -package) CAMLPKGS ?= FINDLIBPKGS = -package rocq-runtime.plugins.ltac $(CAMLPKGS) # Option for making timing files TIMING?= # Option for changing sorting of timing output file TIMING_SORT_BY ?= auto # Option for changing the fuzz parameter on the output file TIMING_FUZZ ?= 0 # Option for changing whether to use real or user time for timing tables TIMING_REAL?= # Option for including the memory column(s) TIMING_INCLUDE_MEM?= # Option for sorting by the memory column TIMING_SORT_BY_MEM?= # Output file names for timed builds TIME_OF_BUILD_FILE ?= time-of-build.log TIME_OF_BUILD_BEFORE_FILE ?= time-of-build-before.log TIME_OF_BUILD_AFTER_FILE ?= time-of-build-after.log TIME_OF_PRETTY_BUILD_FILE ?= time-of-build-pretty.log TIME_OF_PRETTY_BOTH_BUILD_FILE ?= time-of-build-both.log TIME_OF_PRETTY_BUILD_EXTRA_FILES ?= - # also output to the command line TGTS ?= # Retro compatibility (DESTDIR is standard on Unix, DSTROOT is not) ifdef DSTROOT DESTDIR := $(DSTROOT) endif # Substitution of the path by appending $(DESTDIR) if needed. # The variable $(COQMF_WINDRIVE) can be needed for Cygwin environments. windrive_path = $(if $(COQMF_WINDRIVE),$(subst $(COQMF_WINDRIVE),/,$(1)),$(1)) destination_path = $(if $(DESTDIR),$(DESTDIR)/$(call windrive_path,$(1)),$(1)) # Installation paths of libraries and documentation. COQLIBINSTALL ?= $(call destination_path,$(COQLIB)/user-contrib) COQDOCINSTALL ?= $(call destination_path,$(DOCDIR)/coq/user-contrib) COQPLUGININSTALL ?= $(call destination_path,$(COQCORELIB)/..) COQTOPINSTALL ?= $(call destination_path,$(COQLIB)/toploop) # FIXME: Unused variable? # findlib files installation FINDLIBPREINST= mkdir -p "$(COQPLUGININSTALL)/" FINDLIBDESTDIR= -destdir "$(COQPLUGININSTALL)/" # we need to move out of sight $(METAFILE) otherwise findlib thinks the # package is already installed findlib_install = \ $(HIDE)if [ "$(METAFILE)" ]; then \ $(FINDLIBPREINST) && \ mv "$(METAFILE)" "$(METAFILE).skip" ; \ "$(OCAMLFIND)" install $(2) $(FINDLIBDESTDIR) $(FINDLIBPACKAGE) $(1); \ rc=$$?; \ mv "$(METAFILE).skip" "$(METAFILE)"; \ exit $$rc; \ fi findlib_remove = \ $(HIDE)if [ ! -z "$(METAFILE)" ]; then\ "$(OCAMLFIND)" remove $(FINDLIBDESTDIR) $(FINDLIBPACKAGE); \ fi ########## End of parameters ################################################## # What follows may be relevant to you only if you need to # extend this Makefile. If so, look for 'Extension point' here and # put in @LOCAL_FILE@ double colon rules accordingly. # E.g. to perform some work after the all target completes you can write # # post-all:: # echo "All done!" # # in @LOCAL_FILE@ # ############################################################################### # Flags ####################################################################### # # We define a bunch of variables combining the parameters. # To add additional flags to coq, coqchk or coqdoc, set the # {COQ,COQCHK,COQDOC}EXTRAFLAGS variable to whatever you want to add. # To overwrite the default choice and set your own flags entirely, set the # {COQ,COQCHK,COQDOC}FLAGS variable. SHOW := $(if $(VERBOSE),@true "",@echo "") HIDE := $(if $(VERBOSE),,@) TIMER=$(if $(TIMED), $(STDTIME), $(TIMECMD)) OPT?= # The DYNLIB variable is used by "coqdep -dyndep var" in .v.d ifeq '$(OPT)' '-byte' USEBYTE:=true DYNLIB:=.cma else USEBYTE:= DYNLIB:=.cmxs endif # these variables are meant to be overridden if you want to add *extra* flags COQEXTRAFLAGS?= COQCHKEXTRAFLAGS?= COQDOCEXTRAFLAGS?= # Find the last argument of the form "-native-compiler FLAG" COQUSERNATIVEFLAG:=$(strip \ $(subst -native-compiler-,,\ $(lastword \ $(filter -native-compiler-%,\ $(subst -native-compiler ,-native-compiler-,\ $(strip $(COQEXTRAFLAGS))))))) COQFILTEREDEXTRAFLAGS:=$(strip \ $(filter-out -native-compiler-%,\ $(subst -native-compiler ,-native-compiler-,\ $(strip $(COQEXTRAFLAGS))))) COQACTUALNATIVEFLAG:=$(lastword $(COQMF_COQ_NATIVE_COMPILER_DEFAULT) $(COQMF_COQPROJECTNATIVEFLAG) $(COQUSERNATIVEFLAG)) ifeq '$(COQACTUALNATIVEFLAG)' 'yes' COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "ondemand" COQDONATIVE="yes" else ifeq '$(COQACTUALNATIVEFLAG)' 'ondemand' COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "ondemand" COQDONATIVE="no" else COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "no" COQDONATIVE="no" endif endif # these flags do NOT contain the libraries, to make them easier to overwrite COQFLAGS?=-q $(OTHERFLAGS) $(COQFILTEREDEXTRAFLAGS) $(COQNATIVEFLAG) COQCHKFLAGS?=-silent -o $(COQCHKEXTRAFLAGS) COQDOCFLAGS?=-interpolate -utf8 $(COQDOCEXTRAFLAGS) COQDOCLIBS?=$(COQLIBS_NOML) # The version of Coq being run and the version of rocq makefile that # generated this makefile COQ_VERSION:=$(shell $(ROCQ) --print-version | cut -d " " -f 1) COQMAKEFILE_VERSION:=@COQ_VERSION@ # COQ_SRC_SUBDIRS is for user-overriding, usually to add # `user-contrib/Foo` to the includes, we keep COQCORE_SRC_SUBDIRS for # Coq's own core libraries, which should be replaced by ocamlfind # options at some point. COQ_SRC_SUBDIRS?= COQSRCLIBS?= $(foreach d,$(COQ_SRC_SUBDIRS), -I "$(COQLIB)/$(d)") CAMLFLAGS+=$(OCAMLLIBS) $(COQSRCLIBS) # ocamldoc fails with unknown argument otherwise CAMLDOCFLAGS:=$(filter-out -annot, $(filter-out -bin-annot, $(CAMLFLAGS))) CAMLFLAGS+=$(OCAMLWARN) ifneq (,$(TIMING)) ifeq (after,$(TIMING)) TIMING_EXT=after-timing else ifeq (before,$(TIMING)) TIMING_EXT=before-timing else TIMING_EXT=timing endif endif TIMING_ARG=-time-file $<.$(TIMING_EXT) else TIMING_ARG= endif ifneq (,$(PROFILING)) PROFILE_ARG=-profile $@.prof.json PROFILE_ZIP=gzip -f $@.prof.json else PROFILE_ARG= PROFILE_ZIP=true endif # Files ####################################################################### # # We here define a bunch of variables about the files being part of the # Rocq project in order to ease the writing of build target and build rules VDFILE := @DEP_FILE@ ALLSRCFILES := \ $(MLGFILES) \ $(MLFILES) \ $(MLPACKFILES) \ $(MLLIBFILES) \ $(MLIFILES) # helpers vo_to_obj = $(addsuffix .o,\ $(filter-out Warning: Error:,\ $(shell $(COQTOP) -q -noinit -batch -quiet -print-mod-uid $(1)))) strip_dotslash = $(patsubst ./%,%,$(1)) # without this we get undefined variables in the expansion for the # targets of the [deprecated,use-mllib-or-mlpack] rule with_undef = $(if $(filter-out undefined, $(origin $(1))),$($(1))) VO = vo VOS = vos VOFILES = $(VFILES:.v=.$(VO)) GLOBFILES = $(VFILES:.v=.glob) HTMLFILES = $(VFILES:.v=.html) GHTMLFILES = $(VFILES:.v=.g.html) BEAUTYFILES = $(addsuffix .beautified,$(VFILES)) TEXFILES = $(VFILES:.v=.tex) GTEXFILES = $(VFILES:.v=.g.tex) CMOFILES = \ $(MLGFILES:.mlg=.cmo) \ $(MLFILES:.ml=.cmo) \ $(MLPACKFILES:.mlpack=.cmo) CMXFILES = $(CMOFILES:.cmo=.cmx) OFILES = $(CMXFILES:.cmx=.o) CMAFILES = $(MLLIBFILES:.mllib=.cma) $(MLPACKFILES:.mlpack=.cma) CMXAFILES = $(CMAFILES:.cma=.cmxa) CMIFILES = \ $(CMOFILES:.cmo=.cmi) \ $(MLIFILES:.mli=.cmi) # the /if/ is because old _CoqProject did not list a .ml(pack|lib) but just # a .mlg file CMXSFILES = \ $(MLPACKFILES:.mlpack=.cmxs) \ $(CMXAFILES:.cmxa=.cmxs) \ $(if $(MLPACKFILES)$(CMXAFILES),,\ $(MLGFILES:.mlg=.cmxs) $(MLFILES:.ml=.cmxs)) # files that are packed into a plugin (no extension) PACKEDFILES = \ $(call strip_dotslash, \ $(foreach lib, \ $(call strip_dotslash, \ $(MLPACKFILES:.mlpack=_MLPACK_DEPENDENCIES)),$(call with_undef,$(lib)))) # files that are archived into a .cma (mllib) LIBEDFILES = \ $(call strip_dotslash, \ $(foreach lib, \ $(call strip_dotslash, \ $(MLLIBFILES:.mllib=_MLLIB_DEPENDENCIES)),$(call with_undef,$(lib)))) CMIFILESTOINSTALL = $(filter-out $(addsuffix .cmi,$(PACKEDFILES)),$(CMIFILES)) CMOFILESTOINSTALL = $(filter-out $(addsuffix .cmo,$(PACKEDFILES)),$(CMOFILES)) OBJFILES = $(call vo_to_obj,$(VOFILES)) ALLNATIVEFILES = \ $(OBJFILES:.o=.cmi) \ $(OBJFILES:.o=.cmx) \ $(OBJFILES:.o=.cmxs) FINDLIBPACKAGE=$(patsubst .%,%,$(suffix $(METAFILE))) # trick: wildcard filters out non-existing files, so that `install` doesn't show # warnings and `clean` doesn't pass to rm a list of files that is too long for # the shell. NATIVEFILES = $(wildcard $(ALLNATIVEFILES)) FILESTOINSTALL = \ $(VOFILES) \ $(VFILES) \ $(GLOBFILES) \ $(NATIVEFILES) FINDLIBFILESTOINSTALL = \ $(CMIFILESTOINSTALL) ifeq '$(HASNATDYNLINK)' 'true' DO_NATDYNLINK = yes FINDLIBFILESTOINSTALL += $(CMXSFILES) $(CMXAFILES) $(CMOFILESTOINSTALL:.cmo=.cmx) else DO_NATDYNLINK = endif ALLDFILES = $(addsuffix .d,$(ALLSRCFILES)) $(VDFILE) # Compilation targets ######################################################### all: $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" pre-all $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" real-all $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" post-all .PHONY: all all.timing.diff: $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" pre-all $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" real-all.timing.diff TIME_OF_PRETTY_BUILD_EXTRA_FILES="" $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" post-all .PHONY: all.timing.diff ifeq (0,$(TIMING_REAL)) TIMING_REAL_ARG := TIMING_USER_ARG := --user else ifeq (1,$(TIMING_REAL)) TIMING_REAL_ARG := --real TIMING_USER_ARG := else TIMING_REAL_ARG := TIMING_USER_ARG := endif endif ifeq (0,$(TIMING_INCLUDE_MEM)) TIMING_INCLUDE_MEM_ARG := --no-include-mem else TIMING_INCLUDE_MEM_ARG := endif ifeq (1,$(TIMING_SORT_BY_MEM)) TIMING_SORT_BY_MEM_ARG := --sort-by-mem else TIMING_SORT_BY_MEM_ARG := endif make-pretty-timed-before:: TIME_OF_BUILD_FILE=$(TIME_OF_BUILD_BEFORE_FILE) make-pretty-timed-after:: TIME_OF_BUILD_FILE=$(TIME_OF_BUILD_AFTER_FILE) make-pretty-timed make-pretty-timed-before make-pretty-timed-after:: $(HIDE)rm -f pretty-timed-success.ok $(HIDE)($(MAKE) --no-print-directory -f "$(PARENT)" $(TGTS) TIMED=1 2>&1 && touch pretty-timed-success.ok) | tee -a $(TIME_OF_BUILD_FILE) $(HIDE)rm pretty-timed-success.ok # must not be -f; must fail if the touch failed print-pretty-timed:: $(HIDE)$(COQMAKE_ONE_TIME_FILE) $(TIMING_INCLUDE_MEM_ARG) $(TIMING_SORT_BY_MEM_ARG) $(TIMING_REAL_ARG) $(TIME_OF_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) print-pretty-timed-diff:: $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIMING_INCLUDE_MEM_ARG) $(TIMING_SORT_BY_MEM_ARG) $(TIMING_REAL_ARG) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) ifeq (,$(BEFORE)) print-pretty-single-time-diff:: @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing' $(HIDE)false else ifeq (,$(AFTER)) print-pretty-single-time-diff:: @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing' $(HIDE)false else print-pretty-single-time-diff:: $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --fuzz=$(TIMING_FUZZ) --sort-by=$(TIMING_SORT_BY) $(TIMING_USER_ARG) $(AFTER) $(BEFORE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) endif endif pretty-timed: $(HIDE)$(MAKE) --no-print-directory -f "$(PARENT)" make-pretty-timed $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" print-pretty-timed .PHONY: pretty-timed make-pretty-timed make-pretty-timed-before make-pretty-timed-after print-pretty-timed print-pretty-timed-diff print-pretty-single-time-diff # Extension points for actions to be performed before/after the all target pre-all:: @# Extension point $(HIDE)if [ "$(COQMAKEFILE_VERSION)" != "$(COQ_VERSION)" ]; then\ echo "W: This Makefile was generated by Rocq/Coq $(COQMAKEFILE_VERSION)";\ echo "W: while the current Rocq version is $(COQ_VERSION)";\ fi .PHONY: pre-all post-all:: @# Extension point .PHONY: post-all real-all: $(VOFILES) $(if $(USEBYTE),bytefiles,optfiles) .PHONY: real-all real-all.timing.diff: $(VOFILES:.vo=.v.timing.diff) .PHONY: real-all.timing.diff bytefiles: $(CMOFILES) $(CMAFILES) .PHONY: bytefiles optfiles: $(if $(DO_NATDYNLINK),$(CMXSFILES)) .PHONY: optfiles vos: $(VOFILES:%.vo=%.vos) .PHONY: vos vok: $(VOFILES:%.vo=%.vok) .PHONY: vok validate: $(VOFILES) $(TIMER) $(COQCHK) $(COQCHKFLAGS) $(COQLIBS_NOML) $(PROFILE_ARG) $^ $(HIDE)$(PROFILE_ZIP) .PHONY: validate only: $(TGTS) .PHONY: only # Documentation targets ####################################################### html: $(GLOBFILES) $(VFILES) $(SHOW)'COQDOC -d html $(GAL)' $(HIDE)mkdir -p html $(HIDE)$(COQDOC) \ -toc $(COQDOCFLAGS) -html $(GAL) $(COQDOCLIBS) -d html $(VFILES) mlihtml: $(MLIFILES:.mli=.cmi) $(SHOW)'CAMLDOC -d $@' $(HIDE)mkdir $@ || rm -rf $@/* $(HIDE)$(CAMLDOC) -html \ -d $@ -m A $(CAMLDEBUG) $(CAMLDOCFLAGS) $(MLIFILES) $(FINDLIBPKGS) all-mli.tex: $(MLIFILES:.mli=.cmi) $(SHOW)'CAMLDOC -latex $@' $(HIDE)$(CAMLDOC) -latex \ -o $@ -m A $(CAMLDEBUG) $(CAMLDOCFLAGS) $(MLIFILES) $(FINDLIBPKGS) all.ps: $(VFILES) $(SHOW)'COQDOC -ps $(GAL)' $(HIDE)$(COQDOC) \ -toc $(COQDOCFLAGS) -ps $(GAL) $(COQDOCLIBS) \ -o $@ `$(COQDEP) -sort $(VFILES)` all.pdf: $(VFILES) $(SHOW)'COQDOC -pdf $(GAL)' $(HIDE)$(COQDOC) \ -toc $(COQDOCFLAGS) -pdf $(GAL) $(COQDOCLIBS) \ -o $@ `$(COQDEP) -sort $(VFILES)` # FIXME: not quite right, since the output name is different gallinahtml: GAL=-g gallinahtml: html all-gal.ps: GAL=-g all-gal.ps: all.ps all-gal.pdf: GAL=-g all-gal.pdf: all.pdf # ? beautify: $(BEAUTYFILES) for file in $^; do mv $${file%.beautified} $${file%beautified}old && mv $${file} $${file%.beautified}; done @echo 'Do not do "make clean" until you are sure that everything went well!' @echo 'If there were a problem, execute "for file in $$(find . -name \*.v.old -print); do mv $${file} $${file%.old}; done" in your shell/' .PHONY: beautify # Installation targets ######################################################## # # There rules can be extended in @LOCAL_FILE@ # Extensions can't assume when they run. # We use $(file) to avoid generating a very long command string to pass to the shell # (cf https://coq.zulipchat.com/#narrow/stream/250632-Coq-Platform-devs-.26-users/topic/Strange.20command.20length.20limit.20on.20Linux) # However Apple ships old make which doesn't have $(file) so we need a fallback $(file >.hasfile,1) HASFILE:=$(shell if [ -e .hasfile ]; then echo 1; rm .hasfile; fi) MKFILESTOINSTALL= $(if $(HASFILE),$(file >.filestoinstall,$(FILESTOINSTALL)),\ $(shell rm -f .filestoinstall) \ $(foreach x,$(FILESTOINSTALL),$(shell printf '%s\n' "$x" >> .filestoinstall))) # findlib needs the package to not be installed, so we remove it before # installing it (see the call to findlib_remove) install: META @$(MKFILESTOINSTALL) $(HIDE)code=0; for f in $$(cat .filestoinstall); do\ if ! [ -f "$$f" ]; then >&2 echo $$f does not exist; code=1; fi \ done; exit $$code $(HIDE)for f in $$(cat .filestoinstall); do\ df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`";\ if [ "$$?" != "0" -o -z "$$df" ]; then\ echo SKIP "$$f" since it has no logical path;\ else\ install -d "$(COQLIBINSTALL)/$$df" &&\ install -m 0644 "$$f" "$(COQLIBINSTALL)/$$df" &&\ echo INSTALL "$$f" "$(COQLIBINSTALL)/$$df";\ fi;\ done $(call findlib_remove) $(call findlib_install, META $(FINDLIBFILESTOINSTALL)) $(HIDE)$(MAKE) install-extra -f "$(SELF)" @rm -f .filestoinstall install-extra:: @# Extension point .PHONY: install install-extra META: $(METAFILE) $(HIDE)if [ "$(METAFILE)" ]; then \ cat "$(METAFILE)" | grep -v 'directory.*=.*' > META; \ fi install-byte: $(call findlib_install, $(CMAFILES) $(CMOFILESTOINSTALL), -add) install-doc:: html mlihtml @# Extension point $(HIDE)install -d "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html" $(HIDE)for i in html/*; do \ dest="$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/$$i";\ install -m 0644 "$$i" "$$dest";\ echo INSTALL "$$i" "$$dest";\ done $(HIDE)install -d \ "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml" $(HIDE)for i in mlihtml/*; do \ dest="$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/$$i";\ install -m 0644 "$$i" "$$dest";\ echo INSTALL "$$i" "$$dest";\ done .PHONY: install-doc uninstall:: @# Extension point @$(MKFILESTOINSTALL) $(call findlib_remove) $(HIDE)for f in $$(cat .filestoinstall); do \ df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`" &&\ instf="$(COQLIBINSTALL)/$$df/`basename $$f`" &&\ rm -f "$$instf" &&\ echo RM "$$instf" ;\ done $(HIDE)for f in $$(cat .filestoinstall); do \ df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`" &&\ echo RMDIR "$(COQLIBINSTALL)/$$df/" &&\ (rmdir "$(COQLIBINSTALL)/$$df/" 2>/dev/null || true); \ done @rm -f .filestoinstall .PHONY: uninstall uninstall-doc:: @# Extension point $(SHOW)'RM $(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html' $(HIDE)rm -rf "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html" $(SHOW)'RM $(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml' $(HIDE)rm -rf "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml" $(HIDE) rmdir "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/" || true .PHONY: uninstall-doc # Cleaning #################################################################### # # There rules can be extended in @LOCAL_FILE@ # Extensions can't assume when they run. clean:: @# Extension point $(SHOW)'CLEAN' $(HIDE)rm -f $(CMOFILES) $(HIDE)rm -f $(CMIFILES) $(HIDE)rm -f $(CMAFILES) $(HIDE)rm -f $(CMXFILES) $(HIDE)rm -f $(CMXAFILES) $(HIDE)rm -f $(CMXSFILES) $(HIDE)rm -f $(OFILES) $(HIDE)rm -f $(CMXAFILES:.cmxa=.a) $(HIDE)rm -f $(MLGFILES:.mlg=.ml) $(HIDE)rm -f $(CMXFILES:.cmx=.cmt) $(HIDE)rm -f $(MLIFILES:.mli=.cmti) $(HIDE)rm -f $(ALLDFILES) $(HIDE)rm -f $(NATIVEFILES) $(HIDE)find . -name .coq-native -type d -empty -delete $(HIDE)rm -f $(VOFILES) $(HIDE)rm -f $(VOFILES:.vo=.vos) $(HIDE)rm -f $(VOFILES:.vo=.vok) $(HIDE)rm -f $(VOFILES:.vo=.vo.prof.json) $(HIDE)rm -f $(VOFILES:.vo=.vo.prof.json.gz) $(HIDE)rm -f $(BEAUTYFILES) $(VFILES:=.old) $(HIDE)rm -f all.ps all-gal.ps all.pdf all-gal.pdf all.glob all-mli.tex $(HIDE)rm -f $(VFILES:.v=.glob) $(HIDE)rm -f $(VFILES:.v=.tex) $(HIDE)rm -f $(VFILES:.v=.g.tex) $(HIDE)rm -f pretty-timed-success.ok $(HIDE)rm -f META $(HIDE)rm -rf html mlihtml .PHONY: clean cleanall:: clean @# Extension point $(SHOW)'CLEAN *.aux *.timing' $(HIDE)rm -f $(foreach f,$(VFILES:.v=),$(dir $(f)).$(notdir $(f)).aux) $(HIDE)rm -f $(TIME_OF_BUILD_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(HIDE)rm -f $(VOFILES:.vo=.v.timing) $(HIDE)rm -f $(VOFILES:.vo=.v.before-timing) $(HIDE)rm -f $(VOFILES:.vo=.v.after-timing) $(HIDE)rm -f $(VOFILES:.vo=.v.timing.diff) $(HIDE)rm -f .lia.cache .nia.cache .PHONY: cleanall archclean:: @# Extension point $(SHOW)'CLEAN *.cmx *.o' $(HIDE)rm -f $(NATIVEFILES) $(HIDE)rm -f $(CMOFILES:%.cmo=%.cmx) .PHONY: archclean # Compilation rules ########################################################### $(MLIFILES:.mli=.cmi): %.cmi: %.mli $(SHOW)'CAMLC -c $<' $(HIDE)$(TIMER) $(CAMLC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $< $(MLGFILES:.mlg=.ml): %.ml: %.mlg $(SHOW)'COQPP $<' $(HIDE)$(COQPP) $< # Stupid hack around a deficient syntax: we cannot concatenate two expansions $(filter %.cmo, $(MLFILES:.ml=.cmo) $(MLGFILES:.mlg=.cmo)): %.cmo: %.ml $(SHOW)'CAMLC -c $<' $(HIDE)$(TIMER) $(CAMLC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $< # Same hack $(filter %.cmx, $(MLFILES:.ml=.cmx) $(MLGFILES:.mlg=.cmx)): %.cmx: %.ml $(SHOW)'CAMLOPT -c $(FOR_PACK) $<' $(HIDE)$(TIMER) $(CAMLOPTC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $(FOR_PACK) $< $(MLLIBFILES:.mllib=.cmxs): %.cmxs: %.cmxa $(SHOW)'CAMLOPT -shared -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ -shared -o $@ $< $(MLLIBFILES:.mllib=.cma): %.cma: | %.mllib $(SHOW)'CAMLC -a -o $@' $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ $(MLLIBFILES:.mllib=.cmxa): %.cmxa: | %.mllib $(SHOW)'CAMLOPT -a -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ $(MLPACKFILES:.mlpack=.cmxs): %.cmxs: %.cmxa $(SHOW)'CAMLOPT -shared -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ -shared -o $@ $< $(MLPACKFILES:.mlpack=.cmxa): %.cmxa: %.cmx | %.mlpack $(SHOW)'CAMLOPT -a -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $< $(MLPACKFILES:.mlpack=.cma): %.cma: %.cmo | %.mlpack $(SHOW)'CAMLC -a -o $@' $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ $(MLPACKFILES:.mlpack=.cmo): %.cmo: | %.mlpack $(SHOW)'CAMLC -pack -o $@' $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -pack -o $@ $^ $(MLPACKFILES:.mlpack=.cmx): %.cmx: | %.mlpack $(SHOW)'CAMLOPT -pack -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -pack -o $@ $^ # This rule is for _CoqProject with no .mllib nor .mlpack $(filter-out $(MLLIBFILES:.mllib=.cmxs) $(MLPACKFILES:.mlpack=.cmxs) $(addsuffix .cmxs,$(PACKEDFILES)) $(addsuffix .cmxs,$(LIBEDFILES)),$(MLFILES:.ml=.cmxs) $(MLGFILES:.mlg=.cmxs)): %.cmxs: %.cmx $(SHOW)'[deprecated,use-mllib-or-mlpack] CAMLOPT -shared -o $@' $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ -shared -o $@ $< # can't make # https://www.gnu.org/software/make/manual/make.html#Static-Pattern # work with multiple target rules # so use eval in a loop instead # with grouped targets https://www.gnu.org/software/make/manual/make.html#Multiple-Targets # if available (GNU Make >= 4.3) ifneq (,$(filter grouped-target,$(.FEATURES))) define globvorule= # take care to $$ variables using $< etc $(1).vo $(1).glob &: $(1).v | $$(VDFILE) $$(SHOW)ROCQ compile $(1).v $$(HIDE)$$(TIMER) $$(ROCQ) compile $$(COQDEBUG) $$(TIMING_ARG) $$(PROFILE_ARG) $$(COQFLAGS) $$(COQLIBS) $(1).v $$(HIDE)rm -f $(1).vos $(1).vok && touch $(1).vos $(1).vok # make empty vos and vok files $$(HIDE)$$(PROFILE_ZIP) ifeq ($(COQDONATIVE), "yes") $$(SHOW)COQNATIVE $(1).vo $$(HIDE)$$(call TIMER,$(1).vo.native) $$(COQNATIVE) $$(COQLIBS) $(1).vo endif endef else $(VOFILES): %.vo: %.v | $(VDFILE) $(SHOW)ROCQ compile $< $(HIDE)$(TIMER) $(ROCQ) compile $(COQDEBUG) $(TIMING_ARG) $(PROFILE_ARG) $(COQFLAGS) $(COQLIBS) $< $(HIDE)rm -f $@s $@k && touch $@s $@k # make empty vos and vok files $(HIDE)$(PROFILE_ZIP) ifeq ($(COQDONATIVE), "yes") $(SHOW)COQNATIVE $@ $(HIDE)$(call TIMER,$@.native) $(COQNATIVE) $(COQLIBS) $@ endif # this is broken :( todo fix if we ever find a solution that doesn't need grouped targets $(GLOBFILES): %.glob: %.v $(SHOW)'ROCQ compile $< (for .glob)' $(HIDE)$(TIMER) $(ROCQ) compile $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< endif $(foreach vfile,$(VFILES:.v=),$(eval $(call globvorule,$(vfile)))) $(VFILES:.v=.vos): %.vos: %.v $(SHOW)ROCQ compile -vos $< $(HIDE)$(TIMER) $(ROCQ) compile -vos $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< $(VFILES:.v=.vok): %.vok: %.v $(SHOW)ROCQ compile -vok $< $(HIDE)rm -f $@ && touch $@ # make empty vok file $(HIDE)$(TIMER) $(ROCQ) compile -vok $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< $(addsuffix .timing.diff,$(VFILES)): %.timing.diff : %.before-timing %.after-timing $(SHOW)PYTHON TIMING-DIFF $*.{before,after}-timing $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" print-pretty-single-time-diff BEFORE=$*.before-timing AFTER=$*.after-timing TIME_OF_PRETTY_BUILD_FILE="$@" $(BEAUTYFILES): %.v.beautified: %.v $(SHOW)'BEAUTIFY $<' $(HIDE)$(TIMER) $(ROCQ) compile $(COQDEBUG) $(COQFLAGS) $(COQLIBS) -beautify $< $(TEXFILES): %.tex: %.v $(SHOW)'COQDOC -latex $<' $(HIDE)$(COQDOC) $(COQDOCFLAGS) -latex $< -o $@ $(GTEXFILES): %.g.tex: %.v $(SHOW)'COQDOC -latex -g $<' $(HIDE)$(COQDOC) $(COQDOCFLAGS) -latex -g $< -o $@ $(HTMLFILES): %.html: %.v %.glob $(SHOW)'COQDOC -html $<' $(HIDE)$(COQDOC) $(COQDOCFLAGS) -html $< -o $@ $(GHTMLFILES): %.g.html: %.v %.glob $(SHOW)'COQDOC -html -g $<' $(HIDE)$(COQDOC) $(COQDOCFLAGS) -html -g $< -o $@ # Dependency files ############################################################ ifndef MAKECMDGOALS -include $(ALLDFILES) else ifneq ($(filter-out archclean clean cleanall printenv make-pretty-timed make-pretty-timed-before make-pretty-timed-after print-pretty-timed print-pretty-timed-diff print-pretty-single-time-diff,$(MAKECMDGOALS)),) -include $(ALLDFILES) endif endif .SECONDARY: $(ALLDFILES) redir_if_ok = > "$@" || ( RV=$$?; rm -f "$@"; exit $$RV ) GENMLFILES:=$(MLGFILES:.mlg=.ml) $(addsuffix .d,$(ALLSRCFILES)): $(GENMLFILES) $(addsuffix .d,$(MLIFILES)): %.mli.d: %.mli $(SHOW)'CAMLDEP $<' $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) $(addsuffix .d,$(MLGFILES)): %.mlg.d: %.ml $(SHOW)'CAMLDEP $<' $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) $(addsuffix .d,$(MLFILES)): %.ml.d: %.ml $(SHOW)'CAMLDEP $<' $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) $(addsuffix .d,$(MLLIBFILES)): %.mllib.d: %.mllib $(SHOW)'OCAMLLIBDEP $<' $(HIDE)$(OCAMLLIBDEP) -c $(OCAMLLIBS) "$<" $(redir_if_ok) $(addsuffix .d,$(MLPACKFILES)): %.mlpack.d: %.mlpack $(SHOW)'OCAMLLIBDEP $<' $(HIDE)$(OCAMLLIBDEP) -c $(OCAMLLIBS) "$<" $(redir_if_ok) # If this makefile is created using a _CoqProject we have coqdep get # options from it. This avoids argument length limits for pathological # projects. Note that extra options might be on the command line. VDFILE_FLAGS:=$(if @PROJECT_FILE@,-f @PROJECT_FILE@,) $(CMDLINE_COQLIBS) $(CMDLINE_VFILES) $(VDFILE): @PROJECT_FILE@ $(VFILES) $(SHOW)'ROCQ DEP VFILES' $(HIDE)$(TIMER) $(COQDEP) -vos -dyndep var $(VDFILE_FLAGS) $(redir_if_ok) # Misc ######################################################################## byte: $(HIDE)$(MAKE) all "OPT:=-byte" -f "$(SELF)" .PHONY: byte opt: $(HIDE)$(MAKE) all "OPT:=-opt" -f "$(SELF)" .PHONY: opt # This is deprecated. To extend this makefile use # extension points and @LOCAL_FILE@ printenv:: $(warning printenv is deprecated) $(warning write extensions in @LOCAL_FILE@ or include @CONF_FILE@) @echo 'COQLIB = $(COQLIB)' @echo 'COQCORELIB = $(COQCORELIB)' @echo 'DOCDIR = $(DOCDIR)' @echo 'OCAMLFIND = $(OCAMLFIND)' @echo 'HASNATDYNLINK = $(HASNATDYNLINK)' @echo 'SRC_SUBDIRS = $(SRC_SUBDIRS)' @echo 'COQ_SRC_SUBDIRS = $(COQ_SRC_SUBDIRS)' @echo 'COQCORE_SRC_SUBDIRS = $(COQCORE_SRC_SUBDIRS)' @echo 'OCAMLFIND = $(OCAMLFIND)' @echo 'PP = $(PP)' @echo 'COQFLAGS = $(COQFLAGS)' @echo 'COQLIB = $(COQLIBS)' @echo 'COQLIBINSTALL = $(COQLIBINSTALL)' @echo 'COQDOCINSTALL = $(COQDOCINSTALL)' .PHONY: printenv # Generate a .merlin file. If you need to append directives to this # file you can extend the merlin-hook target in @LOCAL_FILE@ .merlin: $(SHOW)'FILL .merlin' $(HIDE)echo 'FLG $(COQMF_CAMLFLAGS)' > .merlin $(HIDE)echo 'B $(COQCORELIB)' >> .merlin $(HIDE)echo 'S $(COQCORELIB)' >> .merlin $(HIDE)$(foreach d,$(COQCORE_SRC_SUBDIRS), \ echo 'B $(COQCORELIB)$(d)' >> .merlin;) $(HIDE)$(foreach d,$(COQ_SRC_SUBDIRS), \ echo 'S $(COQLIB)$(d)' >> .merlin;) $(HIDE)$(foreach d,$(SRC_SUBDIRS), echo 'B $(d)' >> .merlin;) $(HIDE)$(foreach d,$(SRC_SUBDIRS), echo 'S $(d)' >> .merlin;) $(HIDE)$(MAKE) merlin-hook -f "$(SELF)" .PHONY: merlin merlin-hook:: @# Extension point .PHONY: merlin-hook # prints all variables debug: $(foreach v,\ $(sort $(filter-out $(INITIAL_VARS) INITIAL_VARS,\ $(.VARIABLES))),\ $(info $(v) = $($(v)))) .PHONY: debug .DEFAULT_GOAL := all # Users can create @LOCAL_LATE_FILE@ to hook into double-colon rules # or add other needed Makefile code, using defined # variables if necessary. -include @LOCAL_LATE_FILE@ # Local Variables: # mode: makefile-gmake # End: rocq-9.2.0/tools/TimeFileMaker.py000066400000000000000000000644371516144147600167050ustar00rootroot00000000000000from __future__ import with_statement from __future__ import division from __future__ import unicode_literals from __future__ import print_function import sys import re import argparse import os import math from io import open # This script parses the output of `make TIMED=1` into a dictionary # mapping names of compiled files to the number of minutes and seconds # that they took to compile. STRIP_REG = re.compile('^(?:%s/)?(coq/|contrib/|)(?:theories/|src/)?' % re.escape(os.getcwd())) STRIP_REP = r'\1' INFINITY = '\u221e' TIME_KEY = 'time' MEM_KEY = 'mem' def nonnegative(arg): v = int(arg) if v < 0: raise argparse.ArgumentTypeError("%s is an invalid non-negative int value" % arg) return v def add_sort_by(parser): return parser.add_argument( '--sort-by', type=str, dest='sort_by', choices=('auto', 'absolute', 'diff'), default='auto', help=('How to sort the table entries.\n' + 'The "auto" method sorts by absolute time differences ' + 'rounded towards zero to a whole-number of seconds, then ' + 'by times in the "after" column, and finally ' + 'lexicographically by file name. This will put the ' + 'biggest changes in either direction first, and will ' + 'prefer sorting by build-time over subsecond changes in ' + 'build time (which are frequently noise); lexicographic ' + 'sorting forces an order on files which take effectively ' + 'no time to compile.\n' + 'The "absolute" method sorts by the total time taken.\n' + 'The "diff" method sorts by the signed difference in time.')) def add_sort_by_mem(parser): return parser.add_argument( '--sort-by-mem', action='store_true', dest='sort_by_mem', help=('Sort the table entries by memory rather than time.')) def add_fuzz(parser): return parser.add_argument( '--fuzz', dest='fuzz', metavar='N', type=nonnegative, default=0, help=('By default, two lines are only considered the same if ' + 'the character offsets and initial code strings match. ' 'This option relaxes this constraint by allowing the ' + 'character offsets to differ by up to N characters, as long ' + 'as the total number of characters and initial code strings ' + 'continue to match. This is useful when there are small changes ' + 'to a file, and you want to match later lines that have not ' + 'changed even though the character offsets have changed.')) def add_real(parser, single_timing=False): return parser.add_argument( '--real', action='store_true', help=(r'''Use real times rather than user times. ''' + ('''By default, the input is expected to contain lines in the format: FILE_NAME (...user: NUMBER_IN_SECONDS...mem: NUMBER ko...) If --real is passed, then the lines are instead expected in the format: FILE_NAME (...real: NUMBER_IN_SECONDS...mem: NUMBER ko...)''' if not single_timing else '''The input is expected to contain lines in the format: Chars START - END COMMAND NUMBER secs (NUMBERu...)'''))) def add_user(parser, single_timing=False): return parser.add_argument( '--user', dest='real', action='store_false', help=(r'''Use user times rather than real times. ''' + ('''By default, the input is expected to contain lines in the format: FILE_NAME (...real: NUMBER_IN_SECONDS...mem: NUMBER ko...) If --user is passed, then the lines are instead expected in the format: FILE_NAME (...user: NUMBER_IN_SECONDS...mem: NUMBER ko...)''' if not single_timing else '''The input is expected to contain lines in the format: Chars START - END COMMAND NUMBER secs (NUMBERu...)'''))) def add_include_mem(parser): return parser.add_argument( '--no-include-mem', dest='include_mem', default=True, action='store_false', help=(r'''Don't include memory in the table.''')) # N.B. We need to include default=None for nargs='*', c.f., https://bugs.python.org/issue28609#msg280180 def add_file_name_gen(parser, prefix='', descr='file containing the build log', stddir='in', defaults=None, **kwargs): extra = ('' if defaults is None else ' (defaults to %s if no argument is passed)' % defaults) return parser.add_argument( prefix + 'FILE_NAME', type=str, help=('The name of the %s (use "-" for std%s)%s.' % (descr, stddir, extra)), **kwargs) def add_file_name(parser): return add_file_name_gen(parser) def add_after_file_name(parser): return add_file_name_gen(parser, 'AFTER_', 'file containing the "after" build log') def add_before_file_name(parser): return add_file_name_gen(parser, 'BEFORE_', 'file containing the "before" build log') def add_output_file_name(parser): return add_file_name_gen(parser, 'OUTPUT_', 'file to write the output table to', stddir='out', defaults='-', nargs='*', default=None) def reformat_time_string(time): try: seconds, milliseconds = time.split('.') except ValueError: print('WARNING: Invalid time string: not the right number of dots (.); expected one: %s' % repr(time), file=sys.stderr) seconds, milliseconds = (time + '.').split('.')[:2] if seconds == '': seconds = 0 seconds = int(seconds) minutes, seconds = divmod(seconds, 60) return '%dm%02d.%ss' % (minutes, seconds, milliseconds) def get_file_lines(file_name): if file_name == '-': if hasattr(sys.stdin, 'buffer'): lines = sys.stdin.buffer.readlines() else: lines = sys.stdin.readlines() else: with open(file_name, 'rb') as f: lines = f.readlines() for line in lines: try: # Since we read the files in binary mode, we have to # normalize Windows line endings from \r\n to \n yield line.decode('utf-8').replace('\r\n', '\n') except UnicodeDecodeError: # invalid utf-8 pass def get_file(file_name): return ''.join(get_file_lines(file_name)) def merge_dicts(d1, d2): if d2 is None: return d1 if d1 is None: return d2 assert(isinstance(d1, dict)) assert(isinstance(d2, dict)) ret = {} for k in set(list(d1.keys()) + list(d2.keys())): ret[k] = merge_dicts(d1.get(k), d2.get(k)) return ret def get_mems_of_lines(lines): reg = re.compile(r'^([^\s]+) \([^\)]*?mem: ([0-9]+) ko[^\)]*?\)\s*$', re.MULTILINE) mems = reg.findall(lines) if all(STRIP_REG.search(name.strip()) for name, mem in mems): mems = tuple((STRIP_REG.sub(STRIP_REP, name.strip()), mem) for name, mem in mems) return dict((name, {MEM_KEY:int(mem)}) for name, mem in mems) def get_times_of_lines(lines, use_real=False): reg_user = re.compile(r'^([^\s]+) \([^\)]*?user: ([0-9\.]+)[^\)]*?\)\s*$', re.MULTILINE) reg_real = re.compile(r'^([^\s]+) \([^\)]*?real: ([0-9\.]+)[^\)]*?\)\s*$', re.MULTILINE) reg = reg_real if use_real else reg_user times = reg.findall(lines) if all(time in ('0.00', '0.01') for name, time in times): reg = reg_real times = reg.findall(lines) if all(STRIP_REG.search(name.strip()) for name, time in times): times = tuple((STRIP_REG.sub(STRIP_REP, name.strip()), time) for name, time in times) return dict((name, {TIME_KEY:reformat_time_string(time)}) for name, time in times) def get_times_and_mems(file_name, use_real=False, include_mem=True): # we only get the file once, in case it is a stream like stdin lines = get_file(file_name) return merge_dicts(get_times_of_lines(lines, use_real=use_real), (get_mems_of_lines(lines) if include_mem else None)) def get_mems(file_name): ''' Reads the contents of file_name, which should be the output of 'make TIMED=1', and parses it to construct a dict mapping file names to peak memory usage, as integers. Removes common prefixes using STRIP_REG and STRIP_REP. ''' return get_mems_of_lines(get_file(file_name)) def get_times(file_name, use_real=False): ''' Reads the contents of file_name, which should be the output of 'make TIMED=1', and parses it to construct a dict mapping file names to compile durations, as strings. Removes common prefixes using STRIP_REG and STRIP_REP. ''' return get_times_of_lines(get_file(file_name)) def get_single_file_times(file_name, use_real=False): ''' Reads the contents of file_name, which should be the output of 'coqc -time', and parses it to construct a dict mapping lines to to compile durations, as strings. ''' lines = get_file(file_name) reg = re.compile(r'^Chars ([0-9]+) - ([0-9]+) ([^ ]+) ([0-9\.]+) secs \(([0-9\.]+)u(.*)\)$', re.MULTILINE) times = reg.findall(lines) if len(times) == 0: return dict() longest = max(max((len(start), len(stop))) for start, stop, name, real, user, extra in times) FORMAT = 'Chars %%0%dd - %%0%dd %%s' % (longest, longest) return dict((FORMAT % (int(start), int(stop), name), {TIME_KEY:reformat_time_string(real if use_real else user)}) for start, stop, name, real, user, extra in times) def fuzz_merge(l1, l2, fuzz): '''Takes two iterables of ((start, end, code), times) and a fuzz parameter, and yields a single iterable of ((start, stop, code), times1, times2) We only give both left and right if (a) the codes are the same, (b) the number of characters (stop - start) is the same, and (c) the difference between left and right code locations is <= fuzz. We keep a current guess at the overall offset, and prefer drawing from whichever list is earliest after correcting for current offset. ''' assert(fuzz >= 0) cur_fuzz = 0 l1 = list(l1) l2 = list(l2) cur1, cur2 = None, None while (len(l1) > 0 or cur1 is not None) and (len(l2) > 0 or cur2 is not None): if cur1 is None: cur1 = l1.pop(0) if cur2 is None: cur2 = l2.pop(0) ((s1, e1, c1), t1), ((s2, e2, c2), t2) = cur1, cur2 assert(t1 is not None) assert(t2 is not None) s2_adjusted, e2_adjusted = s2 + cur_fuzz, e2 + cur_fuzz if cur1[0] == cur2[0]: yield (cur1, cur2) cur1, cur2 = None, None cur_fuzz = 0 elif c1 == c2 and e1-s1 == e2-s2 and abs(s1 - s2) <= fuzz: yield (((s1, e1, c1), t1), ((s2, e2, c2), t2)) cur1, cur2 = None, None cur_fuzz = s1 - s2 elif s1 < s2_adjusted or (s1 == s2_adjusted and e1 <= e2): yield (((s1, e1, c1), t1), ((s1 - cur_fuzz, e1 - cur_fuzz, c1), None)) cur1 = None else: yield (((s2 + cur_fuzz, e2 + cur_fuzz, c2), None), ((s2, e2, c2), t2)) cur2 = None if len(l1) > 0: for i in l1: yield (i, (i[0], None)) elif len(l2) > 0: for i in l2: yield ((i[0], None), i) def adjust_fuzz(left_dict, right_dict, fuzz): reg = re.compile(r'Chars ([0-9]+) - ([0-9]+) (.*)$') left_dict_list = sorted(((int(s), int(e), c), v) for ((s, e, c), v) in ((reg.match(k).groups(), v) for k, v in left_dict.items())) right_dict_list = sorted(((int(s), int(e), c), v) for ((s, e, c), v) in ((reg.match(k).groups(), v) for k, v in right_dict.items())) merged = list(fuzz_merge(left_dict_list, right_dict_list, fuzz)) if len(merged) == 0: # assert that both left and right dicts are empty assert(not left_dict) assert(not right_dict) return left_dict, right_dict longest = max(max((len(str(start1)), len(str(stop1)), len(str(start2)), len(str(stop2)))) for ((start1, stop1, code1), t1), ((start2, stop2, code2), t2) in merged) FORMAT1 = 'Chars %%0%dd - %%0%dd %%s' % (longest, longest) FORMAT2 = 'Chars %%0%dd-%%0%dd ~ %%0%dd-%%0%dd %%s' % (longest, longest, longest, longest) if fuzz == 0: left_dict = dict((FORMAT1 % k, t1) for (k, t1), _ in merged if t1 is not None) right_dict = dict((FORMAT1 % k, t2) for _, (k, t2) in merged if t2 is not None) else: left_dict = dict((FORMAT2 % (s1, e1, s2, e2, c1), t1) for ((s1, e1, c1), t1), ((s2, e2, c2), t2) in merged if t1 is not None) right_dict = dict((FORMAT2 % (s1, e1, s2, e2, c1), t2) for ((s1, e1, c1), t1), ((s2, e2, c2), t2) in merged if t2 is not None) return left_dict, right_dict def fix_sign_for_sorting(num, descending=True): return -num if descending else num def make_sorting_key(stats_dict, descending=True, sort_by_mem=False): if sort_by_mem: def get_key(name): if MEM_KEY not in stats_dict[name].keys(): print('WARNING: %s has no mem key: %s' % (name, repr(stats_dict[name])), file=sys.stderr) mem = stats_dict[name].get(MEM_KEY, '0') return (fix_sign_for_sorting(int(mem), descending=descending), name) else: def get_key(name): if TIME_KEY not in stats_dict[name].keys(): print('WARNING: %s has no time key: %s' % (name, repr(stats_dict[name])), file=sys.stderr) minutes, seconds = stats_dict[name].get(TIME_KEY, '0m00s').replace('s', '').split('m') return (fix_sign_for_sorting(int(minutes), descending=descending), fix_sign_for_sorting(float(seconds), descending=descending), name) return get_key def get_sorted_file_list_from_stats_dict(stats_dict, descending=True, sort_by_mem=False): ''' Takes the output dict of get_times and returns the list of keys, sorted by duration. ''' return sorted(stats_dict.keys(), key=make_sorting_key(stats_dict, descending=descending, sort_by_mem=sort_by_mem)) def to_seconds(time): ''' Converts a string time into a number of seconds. ''' minutes, seconds = time.replace('s', '').split('m') sign = -1 if time[0] == '-' else 1 return sign * (abs(int(minutes)) * 60 + float(seconds)) def from_seconds(seconds, signed=False): ''' Converts a number of seconds into a string time. ''' sign = ('-' if seconds < 0 else '+') if signed else '' full_centiseconds = round(abs(seconds) * 100) seconds = int(full_centiseconds) // 100 centiseconds = full_centiseconds - (seconds * 100) minutes = int(seconds) // 60 seconds -= minutes * 60 return sign + '%dm%02d.%02ds' % (minutes, seconds, centiseconds) def sum_times(times, signed=False): ''' Takes the values of an output from get_times, parses the time strings, and returns their sum, in the same string format. ''' # sort the times before summing because floating point addition is not associative return from_seconds(math.fsum(sorted(map(to_seconds, times))), signed=signed) def format_percentage(num, signed=True): sign = ('-' if num < 0 else '+') if signed else '' num = abs(num) whole_part = int(num * 100) frac_part = int(100 * (num * 100 - whole_part)) return sign + '%d.%02d%%' % (whole_part, frac_part) def make_diff_table_string(left_dict, right_dict, sort_by='auto', descending=True, sort_by_mem=False, left_tag='After', tag='File Name', right_tag='Before', with_percent=True, left_mem_tag='Peak Mem', right_mem_tag='Peak Mem', include_mem=False, change_tag='Change', percent_change_tag='% Change', change_mem_tag='Change (mem)', percent_change_mem_tag='% Change (mem)', mem_fmt='%d ko'): # We first get the names of all of the compiled files: all files # that were compiled either before or after. all_names_dict = dict() all_names_dict.update(right_dict) all_names_dict.update(left_dict) # do the left (after) last, so that we give precedence to those ones if len(all_names_dict.keys()) == 0: return 'No timing data' get_time = (lambda d, name: to_seconds(d.get(name, {}).get(TIME_KEY, '0m0.0s'))) prediff_times = tuple((name, get_time(left_dict, name), get_time(right_dict, name)) for name in all_names_dict.keys()) diff_times_dict = dict((name, from_seconds(lseconds - rseconds, signed=True)) for name, lseconds, rseconds in prediff_times) percent_diff_times_dict = dict((name, ((format_percentage((lseconds - rseconds) / rseconds)) if rseconds != 0 else (INFINITY if lseconds > 0 else 'N/A'))) for name, lseconds, rseconds in prediff_times) get_mem = (lambda d, name: d.get(name, {}).get(MEM_KEY, 0)) prediff_mems = tuple((name, get_mem(left_dict, name), get_mem(right_dict, name)) for name in all_names_dict.keys()) diff_mems_dict = dict((name, lmem - rmem) for name, lmem, rmem in prediff_mems) percent_diff_mems_dict = dict((name, ((format_percentage((lmem - rmem) / float(rmem))) if rmem != 0 else (INFINITY if lmem > 0 else 'N/A'))) for name, lmem, rmem in prediff_mems) # update to sort by approximate difference, first if sort_by_mem: get_prekey = (lambda name: diff_mems_dict[name]) else: get_prekey = (lambda name: to_seconds(diff_times_dict[name])) get_key_abs = make_sorting_key(all_names_dict, descending=descending, sort_by_mem=sort_by_mem) get_key_diff_float = (lambda name: fix_sign_for_sorting(get_prekey(name), descending=descending)) get_key_diff_absint = (lambda name: fix_sign_for_sorting(int(abs(get_prekey(name))), descending=descending)) get_key_with_name = (lambda get_key: lambda name: (get_key(name), name)) if sort_by == 'absolute': get_key = get_key_with_name(get_key_abs) elif sort_by == 'diff': get_key = get_key_with_name(get_key_diff_float) else: # sort_by == 'auto' get_key = get_key_with_name((lambda name: (get_key_diff_absint(name), get_key_abs(name)))) names = sorted(all_names_dict.keys(), key=get_key) #names = get_sorted_file_list_from_stats_dict(all_names_dict, descending=descending) # set the widths of each of the columns by the longest thing to go in that column left_sum = sum_times(v[TIME_KEY] for v in left_dict.values() if TIME_KEY in v.keys()) right_sum = sum_times(v[TIME_KEY] for v in right_dict.values() if TIME_KEY in v.keys()) left_sum_float = sum(sorted(to_seconds(v[TIME_KEY]) for v in left_dict.values() if TIME_KEY in v.keys())) right_sum_float = sum(sorted(to_seconds(v[TIME_KEY]) for v in right_dict.values() if TIME_KEY in v.keys())) diff_sum = from_seconds(left_sum_float - right_sum_float, signed=True) percent_diff_sum = (format_percentage((left_sum_float - right_sum_float) / right_sum_float) if right_sum_float > 0 else 'N/A') left_width = max(max(map(len, ['N/A', left_tag] + [v[TIME_KEY] for v in left_dict.values() if TIME_KEY in v.keys()])), len(left_sum)) right_width = max(max(map(len, ['N/A', right_tag] + [v[TIME_KEY] for v in right_dict.values() if TIME_KEY in v.keys()])), len(right_sum)) far_right_width = max(max(map(len, ['N/A', change_tag] + list(diff_times_dict.values()))), len(diff_sum)) far_far_right_width = max(max(map(len, ['N/A', percent_change_tag] + list(percent_diff_times_dict.values()))), len(percent_diff_sum)) total_string = 'Total' if not include_mem else 'Total Time / Peak Mem' filenames_width = max(map(len, names + [tag, total_string])) left_peak = max([0] + [v.get(MEM_KEY, 0) for v in left_dict.values()]) right_peak = max([0] + [v.get(MEM_KEY, 0) for v in right_dict.values()]) diff_peak = left_peak - right_peak percent_diff_peak = (format_percentage((left_peak - right_peak) / float(right_peak)) if right_peak != 0 else (INFINITY if left_peak > 0 else 'N/A')) left_mem_width = max(max(map(len, ['N/A', left_mem_tag] + [mem_fmt % v.get(MEM_KEY, 0) for v in left_dict.values()])), len(mem_fmt % left_peak)) right_mem_width = max(max(map(len, ['N/A', right_mem_tag] + [mem_fmt % v.get(MEM_KEY, 0) for v in right_dict.values()])), len(mem_fmt % right_peak)) far_right_mem_width = max(max(map(len, ['N/A', change_mem_tag] + [mem_fmt % v for v in diff_mems_dict.values()])), len(mem_fmt % diff_peak)) far_far_right_mem_width = max(max(map(len, ['N/A', percent_change_mem_tag] + list(percent_diff_mems_dict.values()))), len(percent_diff_peak)) if include_mem: format_string = ("%%(left)%ds | %%(left_mem)%ds | %%(right)%ds | %%(right_mem)%ds || %%(far_right)%ds || %%(far_right_mem)%ds" % (left_width, left_mem_width, right_width, right_mem_width, far_right_width, far_right_mem_width)) else: format_string = ("%%(left)%ds | %%(right)%ds || %%(far_right)%ds" % (left_width, right_width, far_right_width)) if with_percent: format_string += " | %%(far_far_right)%ds" % far_far_right_width if include_mem: format_string += " | %%(far_far_right_mem)%ds" % far_far_right_mem_width format_string += " | %%(filenames)-%ds" % filenames_width header = format_string % {'left': left_tag, 'left_mem': left_mem_tag, 'right': right_tag, 'right_mem': right_mem_tag, 'far_right': change_tag, 'far_right_mem': change_mem_tag, 'far_far_right': percent_change_tag, 'far_far_right_mem': percent_change_mem_tag, 'filenames': tag} total = format_string % {'left': left_sum, 'left_mem': mem_fmt % left_peak, 'right': right_sum, 'right_mem': mem_fmt % right_peak, 'far_right': diff_sum, 'far_right_mem': mem_fmt % diff_peak, 'far_far_right': percent_diff_sum, 'far_far_right_mem': percent_diff_peak, 'filenames': total_string} # separator to go between headers and body sep = '-' * len(header) # the representation of the default value (0), to get replaced by N/A left_rep, right_rep, far_right_rep, far_far_right_rep = ("%%%ds | " % left_width) % 'N/A', (" | %%%ds |" % right_width) % 'N/A', ("|| %%%ds" % far_right_width) % 'N/A', ("| %%%ds" % far_far_right_width) % 'N/A' left_mem_rep, right_mem_rep, far_right_mem_rep, far_far_right_mem_rep = ("%%%ds | " % left_mem_width) % 'N/A', (" | %%%ds |" % right_mem_width) % 'N/A', ("|| %%%ds" % far_right_mem_width) % 'N/A', ("| %%%ds" % far_far_right_mem_width) % 'N/A' get_formatted_mem = (lambda k, v: (mem_fmt % v[k]) if k in v.keys() else 'N/A') return '\n'.join([header, sep, total, sep] + [format_string % {'left': left_dict.get(name, {}).get(TIME_KEY, 'N/A'), 'left_mem': get_formatted_mem(MEM_KEY, left_dict.get(name, {})), 'right': right_dict.get(name, {}).get(TIME_KEY, 'N/A'), 'right_mem': get_formatted_mem(MEM_KEY, right_dict.get(name, {})), 'far_right': diff_times_dict.get(name, 'N/A'), 'far_right_mem': get_formatted_mem(name, diff_mems_dict), 'far_far_right': percent_diff_times_dict.get(name, 'N/A'), 'far_far_right_mem': percent_diff_mems_dict.get(name, 'N/A'), 'filenames': name} for name in names]).replace(left_rep, 'N/A'.center(len(left_rep) - 3) + ' | ').replace(right_rep, ' | ' + 'N/A'.center(len(right_rep) - 5) + ' |').replace(far_right_rep, '|| ' + 'N/A'.center(len(far_right_rep) - 3)).replace(far_far_right_rep, '| ' + 'N/A'.center(len(far_far_right_rep) - 2)).replace(left_mem_rep, 'N/A'.center(len(left_mem_rep) - 3) + ' | ').replace(right_mem_rep, ' | ' + 'N/A'.center(len(right_mem_rep) - 5) + ' |').replace(far_right_mem_rep, '|| ' + 'N/A'.center(len(far_right_mem_rep) - 3)).replace(far_far_right_mem_rep, '| ' + 'N/A'.center(len(far_far_right_mem_rep) - 2)) def make_table_string(stats_dict, descending=True, sort_by_mem=False, tag="Time", mem_tag="Peak Mem", mem_fmt='%d ko', include_mem=False): if len(stats_dict.keys()) == 0: return 'No timing data' # We first get the names of all of the compiled files, sorted by # duration names = get_sorted_file_list_from_stats_dict(stats_dict, descending=descending, sort_by_mem=sort_by_mem) # compute the widths of the columns times_width = max(len('N/A'), len(tag), max(len(v[TIME_KEY]) for v in stats_dict.values() if TIME_KEY in v.keys()), len(sum_times(v[TIME_KEY] for v in stats_dict.values() if TIME_KEY in v.keys()))) mems_width = max(len('N/A'), len(mem_tag), max(len(mem_fmt % v.get(MEM_KEY, 0)) for v in stats_dict.values()), len(mem_fmt % (max(v.get(MEM_KEY, 0) for v in stats_dict.values())))) total_string = 'Total' if not include_mem else 'Total Time / Peak Mem' names_width = max(map(len, names + ["File Name", total_string])) if include_mem: format_string = "%%(time)%ds | %%(mem)%ds | %%(name)-%ds" % (times_width, mems_width, names_width) else: format_string = "%%(time)%ds | %%(name)-%ds" % (times_width, names_width) get_formatted_mem = (lambda k, v: (mem_fmt % v[k]) if k in v.keys() else 'N/A') header = format_string % {'time': tag, 'mem': mem_tag, 'name': 'File Name'} total = format_string % {'time': sum_times(v[TIME_KEY] for v in stats_dict.values() if TIME_KEY in v.keys()), 'mem': ((mem_fmt % max(v[MEM_KEY] for v in stats_dict.values() if MEM_KEY in v.keys())) if any(MEM_KEY in v.keys() for v in stats_dict.values()) else 'N/A'), 'name': total_string} sep = '-' * len(header) return '\n'.join([header, sep, total, sep] + [format_string % {'time': stats_dict[name].get(TIME_KEY, 'N/A'), 'mem': get_formatted_mem(MEM_KEY, stats_dict[name]), 'name': name} for name in names]) def print_or_write_table(table, files): if table[-1] != '\n': table += '\n' if len(files) == 0 or '-' in files: if hasattr(sys.stdout, 'buffer'): sys.stdout.buffer.write(table.encode("utf-8")) else: sys.stdout.write(table.encode("utf-8")) for file_name in files: if file_name != '-': with open(file_name, 'w', encoding="utf-8") as f: f.write(table) rocq-9.2.0/tools/beautify-archive000077500000000000000000000040431516144147600170150ustar00rootroot00000000000000#!/bin/sh #This script compiles and beautifies an archive, check the correctness #of beautified files, then replace the original files by the #beautified ones, keeping a copy of original files in $OLDARCHIVE. #The script assumes: #- that the archive provides a Makefile built by coq_makefile, #- that coqc is in the path or that variables COQTOP and COQBIN are set. OLDARCHIVE=old_files NEWARCHIVE=beautify_files BEAUTIFYSUFFIX=.beautified if [ -e $OLDARCHIVE ]; then echo "Warning: $OLDARCHIVE directory found, the files are maybe already beautified"; sleep 5; fi echo ---- Producing beautified files in the beautification directory ------- if [ -e $NEWARCHIVE ]; then rm -r $NEWARCHIVE; fi if [ -e /tmp/$OLDARCHIVE.$$ ]; then rm -r /tmp/$OLDARCHIVE.$$; fi cp -pr . /tmp/$OLDARCHIVE.$$ cp -pr /tmp/$OLDARCHIVE.$$ $NEWARCHIVE cd $NEWARCHIVE rm description || true make clean make COQFLAGS='-beautify -q $(OPT) $(COQLIBS) $(OTHERFLAGS)' || \ { echo ---- Failed to beautify; exit 1; } echo -------- Upgrading files in the beautification directory -------------- beaufiles=`find . -name \*.v$BEAUTIFYSUFFIX` for i in $beaufiles; do j=`dirname $i`/`basename $i .v$BEAUTIFYSUFFIX`.v echo Upgrading $j in the beautification directory if [ $i -nt $j ]; then mv -f $i $j; fi done echo ---- Recompiling beautified files in the beautification directory ----- make clean make || { echo ---- Failed to recompile; exit 1; } echo ----- Saving old files in directory $OLDARCHIVE ------------------------- /bin/rm -r ../$OLDARCHIVE mv /tmp/$OLDARCHIVE.$$ ../$OLDARCHIVE echo Saving $OLDARCHIVE files done echo --------- Upgrading files in current directory ------------------------ vfiles=`find . -name \*.v` cd .. for i in $vfiles; do echo Upgrading $i in current directory if [ $NEWARCHIVE/$i -nt $i ]; then mv -f $NEWARCHIVE/$i $i; fi done echo -------- Beautification completed ------------------------------------- echo Old files are in directory '"'$OLDARCHIVE'"' echo New files are in current directory echo You can now remove the beautification directory '"'$NEWARCHIVE'"' rocq-9.2.0/tools/configure/000077500000000000000000000000001516144147600156205ustar00rootroot00000000000000rocq-9.2.0/tools/configure/cmdArgs.ml000066400000000000000000000122101516144147600175260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* true | "false" | "no" | "n" -> false | s -> raise (Arg.Bad ("boolean argument expected instead of "^s)) let get_native = function | "yes" -> NativeYes | "no" -> NativeNo | "ondemand" -> NativeOndemand | s -> raise (Arg.Bad ("(yes|no|ondemand) argument expected instead of "^s)) let prefs = ref default_prefs let arg_bool f = Arg.String (fun s -> prefs := f !prefs (get_bool s)) let arg_string f = Arg.String (fun s -> prefs := f !prefs s) let arg_string_option f = Arg.String (fun s -> prefs := f !prefs (Some s)) let arg_set f = Arg.Unit (fun () -> prefs := f !prefs) let arg_native f = Arg.String (fun s -> prefs := f !prefs (get_native s)) (* TODO : earlier any option -foo was also available as --foo *) let warn_warn_error () = Format.eprintf "****** the -warn-error option is deprecated, \ warnings are not set in the config section of the \ corresponding build tool [coq_makefile, dune]@\n%!" let make_prefix path = if Filename.is_relative path then Prefix (Sys.getcwd() ^ "/" ^ path) else Prefix path let args_options = Arg.align [ "-prefix", arg_string (fun p prefix -> { p with prefix = Some (make_prefix prefix) }), " Set installation directory to "; "-relocatable", arg_set (fun p -> { p with prefix = Some RelocatableInstall } ), " Make a relocatable installation"; "-quiet", arg_set (fun p -> { p with quiet = true }), " Don't print variables during configure"; "-no-ask", arg_set (fun p -> { p with interactive = false }), " Don't ask questions during configure [questions will be filled with defaults]"; "-libdir", arg_string_option (fun p libdir -> { p with libdir }), " Where to install lib files"; "-configdir", arg_string_option (fun p configdir -> { p with configdir }), " Where to install config files"; "-datadir", arg_string_option (fun p datadir -> { p with datadir }), " Where to install data files"; "-docdir", arg_string_option (fun p docdir -> { p with docdir }), " Where to install doc files"; "-arch", arg_string_option (fun p arch -> { p with arch }), " Specifies the architecture"; "-natdynlink", arg_bool (fun p natdynlink -> { p with natdynlink }), "(yes|no) Use dynamic loading of native code or not"; "-browser", arg_string_option (fun p browser -> { p with browser }), " Use to open URL %s"; "-bytecode-compiler", arg_bool (fun p bytecodecompiler -> { p with bytecodecompiler }), "(yes|no) Enable Rocq's bytecode reduction machine (VM)"; "-native-compiler", arg_native (fun p nativecompiler -> { p with nativecompiler }), "(yes|no|ondemand) Compilation to native code for conversion and normalization yes: -native-compiler option of coqc will default to 'yes', stdlib will be precompiled no (default): no native compilation available at all ondemand: -native-compiler option of coqc will default to 'ondemand', stdlib will not be precompiled"; "-warn-error", arg_bool (fun p _warn_error -> warn_warn_error (); p), " Deprecated option: warnings are now adjusted in the corresponding build tool."; "-coqwebsite", arg_string (fun p coqwebsite -> { p with coqwebsite }), " URL of the rocq website"; "-debug", arg_set (fun p -> { p with debug = true }), " Enable debug information for package detection" ] let parse_args () = Arg.parse args_options (fun s -> raise (Arg.Bad ("Unknown option: "^s))) "Available options for configure are:"; !prefs (* Support don't ask *) let cprintf prefs x = if not prefs.quiet then cprintf x else Printf.ifprintf stdout x rocq-9.2.0/tools/configure/cmdArgs.mli000066400000000000000000000036471516144147600177150ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Prefs.t val cprintf : Prefs.t -> ('a, out_channel, unit, unit) format4 -> 'a rocq-9.2.0/tools/configure/configure.ml000066400000000000000000000532531516144147600201430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* b | None when arch_is_win32 arch -> {|start "%s"|} | None when arch = "Darwin" -> {|open "%s"|} | _ -> {|xdg-open "%s"|} (** * OCaml programs *) module CamlConf = struct type t = { camlbin : string ; caml_version : string ; camllib : string ; findlib_version : string } end let resolve_caml () = let () = try reset_caml_find camlexec (which camlexec.find) with Not_found -> die (sprintf "Error: cannot find '%s' in your path!\n" camlexec.find ^ "Please adjust your path or use the -ocamlfind option of ./configure") in if not (is_executable camlexec.find) then die ("Error: cannot find the executable '"^camlexec.find^"'.") else let findlib_version, _ = run camlexec.find ["query"; "findlib"; "-format"; "%v"] in let caml_version, _ = run camlexec.find ["ocamlc";"-version"] in let camllib, _ = run camlexec.find ["printconf";"stdlib"] in let camlbin = (* TODO beurk beurk beurk *) Filename.dirname (Filename.dirname camllib) / "bin/" in { CamlConf.camlbin; caml_version; camllib; findlib_version } (** Caml version as a list of ints [4;0;1] *) let caml_version_nums { CamlConf.caml_version; _ } = generic_version_nums ~name:"the OCaml compiler" caml_version external native_available : unit -> bool = "rocq_native_available" let check_caml_version prefs caml_version caml_version_nums = if prefs.nativecompiler <> NativeNo && not (native_available ()) then let () = cprintf prefs "Your version of OCaml is %s." caml_version in if caml_version_nums >= [5;0;0] then die "You have enabled Rocq's native compiler, however it is not compatible with OCaml >= 5.0.0 on this architecture" else die "You have enabled Rocq's native compiler, however it is not compatible with your OCaml compiler" else if caml_version_nums >= [4;14;0] then cprintf prefs "You have OCaml %s. Good!" caml_version else let () = cprintf prefs "Your version of OCaml is %s." caml_version in die "You need OCaml 4.14.0 or later." let check_findlib_version prefs { CamlConf.findlib_version; _ } = let findlib_version_nums = generic_version_nums ~name:"findlib" findlib_version in if findlib_version_nums >= [1;9;1] then cprintf prefs "You have OCamlfind %s. Good!" findlib_version else let () = cprintf prefs "Your version of OCamlfind is %s." findlib_version in die "You need OCamlfind 1.9.1 or later." (** Note, these warnings are only used in Rocq Makefile *) (** Explanation of enabled/disabled warnings: 4: fragile pattern matching: too common in the code and too annoying to avoid in general 9: missing fields in a record pattern: too common in the code and not worth the bother 27: innocuous unused variable: innocuous 40: constructor or label name used out of scope: gets in the way of putting types in modules 41: ambiguous constructor or label: too common 42: disambiguated counstructor or label: too common 44: "open" shadowing already defined identifier: too common, especially when some are aliases 45: "open" shadowing a label or constructor: see 44 48: implicit elimination of optional arguments: too common 58: "no cmx file was found in path": See https://github.com/ocaml/num/issues/9 67: "unused functor parameter" seems totally bogus 68: "This pattern depends on mutable state" no idea what it means, dune builds don't display it 70: ".ml file without .mli file" bogus warning when used generally *) (* Note, we list all warnings to be complete *) let coq_warnings = "-w -a+1..3-4+5..8-9+10..26-27+28..39-40-41-42+43-44-45+46..47-48+49..57-58+59..66-67-68+69-70" (* Flags used to compile Rocq and plugins (via coq_makefile) *) let caml_flags = Printf.sprintf "-thread -bin-annot -strict-sequence %s" coq_warnings (** * Native compiler *) let msg_byteonly = "Only the bytecode version of Rocq will be available." let msg_no_ocamlopt () = warn "Cannot find the OCaml native-code compiler.\n%s" msg_byteonly let msg_no_dynlink_cmxa prefs = warn "Cannot find native-code dynlink library.\n%s" msg_byteonly; cprintf prefs "For building a native-code Rocq, you may try to first"; cprintf prefs "compile and install a dummy dynlink.cmxa (see dev/dynlink.ml)"; cprintf prefs "and then run ./configure -natdynlink no" let check_native prefs camlenv = let version, _ = tryrun camlexec.find ["opt";"-version"] in if version = "" then let () = msg_no_ocamlopt () in raise Not_found else if fst (tryrun camlexec.find ["query";"dynlink"]) = "" then let () = msg_no_dynlink_cmxa prefs in raise Not_found else let () = let { CamlConf.caml_version; _ } = camlenv in if version <> caml_version then warn "Native and bytecode compilers do not have the same version!" in cprintf prefs "You have native-code compilation. Good!" let best_compiler prefs camlenv = try check_native prefs camlenv; "opt" with Not_found -> "byte" (** * Native dynlink *) let hasnatdynlink prefs best_compiler = prefs.natdynlink && best_compiler = "opt" (** * OS dependent libraries *) (** Zarith library *) let check_for_zarith prefs = let zarith,_ = tryrun camlexec.find ["query";"zarith"] in let zarith_cmai base = Sys.file_exists (base / "z.cmi") && Sys.file_exists (base / "zarith.cma") in let zarith_version, _ = run camlexec.find ["query"; "zarith"; "-format"; "%v"] in match zarith with | "" -> die "Zarith library not installed, required" | _ when not (zarith_cmai zarith) -> die "Zarith library installed but no development files found (try installing the -dev package)" | _ -> let zarith_version_int = generic_version_nums ~name:"Zarith" zarith_version in if zarith_version_int >= [1;11;0] then cprintf prefs "You have the Zarith library %s installed. Good!" zarith_version else die ("Zarith version 1.11 is required, you have " ^ zarith_version) (** * Installation directories : bindir, libdir, docdir, etc *) (* Source code root *) let coqsrc = Sys.getcwd () (** Variable name, description, ref in prefs, default dir, prefix-relative *) type path_style = | Absolute of string (* Should start with a "/" *) | Relative of string (* Should not start with a "/", relative to the prefix *) type relocatable_path = | Relocatable of string | NotRelocatable of string module InstallDir = struct type t = { var : string (** Used as key by [select] (otherwise ignored) *) ; msg : string (** Description of the directory *) ; uservalue : string option (** Value given explictly by the user *) ; selfcontainedlayout : path_style (** Path style when layout is "local" *) ; unixlayout : path_style (** Path style for installation *) } let make var msg uservalue selfcontainedlayout unixlayout = { var; msg; uservalue; selfcontainedlayout; unixlayout } end let install prefs = [ InstallDir.make "COQPREFIX" "Prefix" None (Relative "") (Relative "") ; InstallDir.make "COQLIBINSTALL" "the Rocq library" prefs.libdir (Relative "lib/coq") (Relative "lib/coq") ; InstallDir.make "CONFIGDIR" "the Rocqide configuration files" prefs.configdir (Relative "config") (Absolute "/etc/xdg/coq") ; InstallDir.make "DATADIR" "the Rocqide data files" prefs.datadir (Relative "share/coq") (Relative "share/coq") ; InstallDir.make "DOCDIR" "documentation prefix path for all Rocq packages" prefs.docdir (Relative "share/doc") (Relative "share/doc") ] let strip_trailing_slash_if_any p = if p.[String.length p - 1] = '/' then String.sub p 0 (String.length p - 1) else p let use_suffix prefix suff = match suff with | Absolute path -> NotRelocatable path | Relative suff -> match prefix with | Prefix prefix -> NotRelocatable (if suff = "" then prefix else prefix ^ "/" ^ suff) | RelocatableInstall -> Relocatable suff let relativize = function (* Turn a global layout based on some prefix to a relative layout *) | Relative _ as suffix -> suffix | Absolute path -> Relative (String.sub path 1 (String.length path - 1)) let find_suffix prefix path = match prefix with | None | Some RelocatableInstall -> Absolute path | Some (Prefix p) -> let p = strip_trailing_slash_if_any p in let lpath = String.length path in let lp = String.length p in if lpath > lp && String.sub path 0 lp = p then Relative (String.sub path (lp+1) (lpath - lp - 1)) else Absolute path (* This computes the actual effective path for an install directory, based on the given prefix; if prefix is absent, it is assumed that the profile is "local" *) let do_one_instdir ~interactive ~prefix ~arch InstallDir.{var; msg; uservalue; selfcontainedlayout; unixlayout} = (var,msg), match uservalue, prefix with | Some d, p -> NotRelocatable d, find_suffix p d | None, Some p -> let suffix = if (arch_is_win32 arch) then selfcontainedlayout else relativize unixlayout in use_suffix p suffix, suffix | None, None -> let () = if not interactive then die (Printf.sprintf "No installation path given for %s" msg) in let suffix = if (unix arch) then unixlayout else selfcontainedlayout in let base = if (unix arch) then "/usr/local" else "C:/coq" in let dflt = use_suffix (Prefix base) suffix in let ppdflt = match dflt with NotRelocatable v -> v | Relocatable _ -> assert false in let () = printf "Where should I install %s [%s]? " msg ppdflt in let line = read_line () in if line = "" then (dflt,suffix) else (NotRelocatable line,find_suffix prefix line) let install_dirs prefs arch = let prefix = prefs.prefix in List.map (do_one_instdir ~interactive:prefs.interactive ~prefix ~arch) (install prefs) let select var install_dirs = List.find (fun ((v,_),_) -> v=var) install_dirs |> snd module CoqEnv = struct (** Rocq core paths, for libraries, documentation, configuration, and data *) type t = { coqlib : relocatable_path ; coqlibsuffix : path_style ; docdir : relocatable_path ; docdirsuffix : path_style ; configdir : relocatable_path ; configdirsuffix : path_style ; datadir : relocatable_path ; datadirsuffix : path_style } end let resolve_coqenv install_dirs = let coqlib, coqlibsuffix = select "COQLIBINSTALL" install_dirs in let docdir, docdirsuffix = select "DOCDIR" install_dirs in let configdir, configdirsuffix = select "CONFIGDIR" install_dirs in let datadir,datadirsuffix = select "DATADIR" install_dirs in { CoqEnv.coqlib; coqlibsuffix; docdir; docdirsuffix ; configdir; configdirsuffix; datadir; datadirsuffix } (** * CC runtime flags *) (* Note that Rocq's VM requires at least C99-compliant floating-point arithmetic; this should be ensured by OCaml's own C flags, which set a minimum of [--std=gnu99] ; modern compilers by default assume C11 or later, so no explicit [--std=] flags are added by OCaml *) let cflags_dflt = "-Wall -Wno-unused -g -O2" let cflags_sse2 = "-msse2 -mfpmath=sse" (* cflags, sse2_math = *) let compute_cflags prefs = let cflags = Buffer.create 17 in Buffer.add_string cflags cflags_dflt; let sse2_math = let _, slurp = (* Test SSE2_MATH support *) tryrun camlexec.find ["ocamlc"; "-ccopt"; cflags_dflt ^ " -march=native -dM -E " ^ cflags_sse2; "-c"; coqsrc/"dev/header.c"] in (* any file *) List.exists (fun line -> starts_with line "#define __SSE2_MATH__ 1") slurp in if sse2_math then begin Buffer.add_char cflags ' '; Buffer.add_string cflags cflags_sse2 end; if prefs.nativecompiler = NativeNo then Buffer.add_string cflags " -DNO_NATIVE_COMPUTE"; (Buffer.contents cflags, sse2_math) (** Test at configure time that no harmful double rounding seems to be performed with an intermediate 80-bit representation (x87). If this test fails but SSE2_MATH is available, the build can go further as Rocq's primitive floats will use it through a dedicated external C implementation (instead of relying on OCaml operations) If this test fails and SSE2_MATH is not available, abort. *) let check_fmath sse2_math = let add = (+.) in let b = ldexp 1. 53 in let s = add 1. (ldexp 1. (-52)) in if (add b s <= b || add b 1. <> b || ldexp 1. (-1074) <= 0.) && not sse2_math then die "Detected non IEEE-754 compliant architecture (or wrong \ rounding mode). Use of Float is thus unsafe." let esc s = if String.contains s ' ' then "\"" ^ s ^ "\"" else s (** * Summary of the configuration *) let pr_native = function | NativeYes -> "yes" | NativeNo -> "no" | NativeOndemand -> "ondemand" let print_summary prefs arch camlenv install_dirs browser = let { CamlConf.caml_version; camlbin; camllib; _ } = camlenv in let pr s = printf s in let pr_reloc oc = function | NotRelocatable p -> fprintf oc "%s" (esc p) | Relocatable p -> fprintf oc "(relocatable prefix)/%s" (esc p) in pr "\n"; pr " Architecture : %s\n" arch; pr " Sys.os_type : %s\n" Sys.os_type; pr " OCaml version : %s\n" caml_version; pr " OCaml binaries in : %s\n" (esc camlbin); pr " OCaml library in : %s\n" (esc camllib); pr " Web browser : %s\n" browser; pr " Rocq web site : %s\n" prefs.coqwebsite; pr " Bytecode VM enabled : %B\n" prefs.bytecodecompiler; pr " Native Compiler enabled : %s\n\n" (pr_native prefs.nativecompiler); (pr " Paths where installation is expected by Rocq Makefile:\n"; List.iter (fun ((_,msg),(dir,_)) -> pr " - %s is expected in %a\n" msg pr_reloc dir) install_dirs); pr "\n"; pr "If anything is wrong above, please restart './configure'.\n\n"; pr "*Warning* To compile the system for a new architecture\n"; pr " don't forget to do a 'make clean' before './configure'.\n" (** Build the [config/coq_config.ml] file *) let write_coq_config_ml install_prefix camlenv coqenv caml_flags caml_version_nums arch arch_is_win32 hasnatdynlink browser prefs o = let { CoqEnv.coqlib; coqlibsuffix; configdir; configdirsuffix; docdir; docdirsuffix; datadir; datadirsuffix } = coqenv in let { CamlConf.caml_version; _ } = camlenv in let pr s = fprintf o s in let pr_s = pr "let %s = %S\n" in let pr_b = pr "let %s = %B\n" in let pr_i32 = pr "let %s = %dl\n" in let pr_p s o = pr "let %s = %S\n" s (match o with Relative s -> s | Absolute s -> s) in let pr_reloc s = function | NotRelocatable o -> pr "let %s = NotRelocatable %S\n" s o | Relocatable o -> pr "let %s = Relocatable %S\n" s o in let pr_li n l = pr "let %s = [%s]\n" n (String.concat ";" (List.map string_of_int l)) in pr "(* DO NOT EDIT THIS FILE: automatically generated by ../configure *)\n"; pr "(* Exact command that generated this file: *)\n"; pr "(* %s *)\n\n" (String.concat " " (Array.to_list Sys.argv)); pr "let gc_ramp_up f = %s\n" (if caml_version_nums >= [5;4;0] then "fst (Gc.ramp_up f)" else "f ()"); pr "type relocatable_path = NotRelocatable of string | Relocatable of string\n"; pr_reloc "install_prefix" install_prefix; pr_reloc "coqlib" coqlib; pr_reloc "configdir" configdir; pr_reloc "datadir" datadir; pr_reloc "docdir" docdir; pr_p "coqlibsuffix" coqlibsuffix; pr_p "configdirsuffix" configdirsuffix; pr_p "datadirsuffix" datadirsuffix; pr_p "docdirsuffix" docdirsuffix; pr_s "ocamlfind" camlexec.find; pr_s "caml_flags" caml_flags; pr_s "version" coq_version; pr_s "caml_version" caml_version; pr_li "caml_version_nums" caml_version_nums; pr_s "arch" arch; pr_b "arch_is_win32" arch_is_win32; pr_s "exec_extension" !exe; pr_b "has_natdynlink" hasnatdynlink; pr_i32 "vo_version" vo_magic; pr_s "browser" browser; pr_s "wwwcoq" prefs.coqwebsite; pr_s "wwwbugtracker" (prefs.coqwebsite ^ "bugs/"); pr_s "wwwrefman" (prefs.coqwebsite ^ "doc/V" ^ coq_version ^ "/refman/"); pr_s "wwwstdlib" (prefs.coqwebsite ^ "doc/V" ^ coq_version ^ "/corelib/"); pr_b "bytecode_compiler" prefs.bytecodecompiler; pr "type native_compiler = NativeOff | NativeOn of { ondemand : bool }\n"; pr "let native_compiler = %s\n" (match prefs.nativecompiler with | NativeYes -> "NativeOn {ondemand=false}" | NativeNo -> "NativeOff" | NativeOndemand -> "NativeOn {ondemand=true}"); let core_src_dirs = [ "boot"; "config"; "lib"; "clib"; "kernel"; "library"; "engine"; "pretyping"; "interp"; "gramlib"; "parsing"; "proofs"; "tactics"; "toplevel"; "printing"; "ide"; "stm"; "vernac" ] in let core_src_dirs = List.fold_left (fun acc core_src_subdir -> acc ^ " \"" ^ core_src_subdir ^ "\";\n") "" core_src_dirs in pr "\nlet core_src_dirs = [\n%s]\n" core_src_dirs; pr "\nlet plugins_dirs = [\n"; let plugins = match open_in "config/plugin_list" with | exception Sys_error _ -> let plugins = try Sys.readdir "plugins" with _ -> [||] in Array.sort compare plugins; plugins | ch -> Array.of_list (snd (read_lines_and_close ch)) in Array.iter (fun f -> let f' = "plugins/"^f in if Sys.is_directory f' && f.[0] <> '.' then pr " %S;\n" f') plugins; pr "]\n"; pr "\nlet all_src_dirs = core_src_dirs @ plugins_dirs\n" (** Build the config/coq_byte_config.ml file *) let write_coq_byte_config_ml caml_version_nums o = let pr s = fprintf o s in pr "let toploop_use_silently ppf f = %s\n" (if caml_version_nums >= [4;14;0] then "Toploop.use_silently ppf (Toploop.File f)" else "Toploop.use_silently ppf f"); pr "let compenv_handle_exit_with_status_0 f = %s\n" (if caml_version_nums >= [4;12;0] then "try f () with Compenv.Exit_with_status(0) -> ()" else "f ()"); pr "let toploop_prep_and_loop fmt = %s\n" (if caml_version_nums >= [5;3;0] then "ignore (Toploop.prepare fmt () : bool); Toploop.loop fmt" else "Toploop.loop fmt") (** Build the [config/dune.c_flags] file *) let write_dune_c_flags cflags o = let pr s = fprintf o s in pr "(%s)\n" cflags (** Build the [config/coq_config.py] file *) let write_coq_config_py o = let pr s = fprintf o s in pr "# DO NOT EDIT THIS FILE: automatically generated by ../configure\n"; pr "version = '%s'\n" coq_version; pr "is_a_released_version = %s\n" (if is_a_released_version then "True" else "False") (* Main configure routine *) let main () = let prefs = CmdArgs.parse_args () in Util.debug := prefs.debug; let arch = arch prefs in let arch_is_win32 = arch_is_win32 arch in let exe = resolve_binary_suffix arch in Util.exe := exe; install_precommit_hook prefs; let browser = browser prefs arch in let camlenv = resolve_caml () in let caml_version_nums = caml_version_nums camlenv in check_caml_version prefs camlenv.CamlConf.caml_version caml_version_nums; check_findlib_version prefs camlenv; let best_compiler = best_compiler prefs camlenv in let hasnatdynlink = hasnatdynlink prefs best_compiler in check_for_zarith prefs; let install_dirs = install_dirs prefs arch in let install_prefix = select "COQPREFIX" install_dirs |> fst in let coqenv = resolve_coqenv install_dirs in let cflags, sse2_math = compute_cflags prefs in check_fmath sse2_math; if not prefs.quiet then print_summary prefs arch camlenv install_dirs browser; write_config_file ~file:"config/coq_config.ml" (write_coq_config_ml install_prefix camlenv coqenv caml_flags caml_version_nums arch arch_is_win32 hasnatdynlink browser prefs); write_config_file ~file:"config/coq_byte_config.ml" (write_coq_byte_config_ml caml_version_nums); write_config_file ~file:"config/dune.c_flags" (write_dune_c_flags cflags); write_config_file ~file:"config/coq_config.py" write_coq_config_py; () let _ = main () rocq-9.2.0/tools/configure/configure.mli000066400000000000000000000012431516144147600203040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* /* Keep in sync with rocq_values.c */ #if defined(__GNUC__) && defined(__amd64__) #elif defined(__GNUC__) && defined(__i386__) #elif defined(NO_NAKED_POINTERS) #define no_native_compute #endif value rocq_native_available(value dummy) { #ifdef no_native_compute return Val_int(0); #else return Val_int(1); #endif } rocq-9.2.0/tools/configure/util.ml000066400000000000000000000172621516144147600171370ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* fprintf oc "\n%!") oc let cprintf s = cfprintf stdout s let ceprintf s = cfprintf stderr s let die msg = ceprintf "%s%s%s\nConfiguration script failed!" red msg reset; exit 1 let warn s = kfprintf (fun oc -> cfprintf oc "%s" reset) stdout ("%sWarning: " ^^ s) yellow let i2s = string_of_int let (/) x y = x ^ "/" ^ y (** Remove the final '\r' that may exists on Win32 *) let remove_final_cr s = let n = String.length s in if n<>0 && s.[n-1] = '\r' then String.sub s 0 (n-1) else s let check_exit_code (_,code) = match code with | Unix.WEXITED 0 -> () | Unix.WEXITED 127 -> failwith "no such command" | Unix.WEXITED n -> failwith ("exit code " ^ i2s n) | Unix.WSIGNALED n -> failwith ("killed by signal " ^ i2s n) | Unix.WSTOPPED n -> failwith ("stopped by signal " ^ i2s n) (** As for Unix.close_process, our Unix.waipid will ignore all EINTR *) let rec waitpid_non_intr pid = try Unix.waitpid [] pid with Unix.Unix_error (Unix.EINTR, _, _) -> waitpid_non_intr pid (** Below, we'd better read all lines on a channel before closing it, otherwise a SIGPIPE could be encountered by the sub-process *) let read_lines_and_close cin = let lines = ref [] in begin try while true do lines := remove_final_cr (input_line cin) :: !lines done with End_of_file -> () end; close_in cin; let lines = List.rev !lines in try List.hd lines, lines with Failure _ -> "", [] let read_lines_and_close_fd fd = read_lines_and_close (Unix.in_channel_of_descr fd) (** Run some unix command and read the first line of its output. We avoid Unix.open_process and its non-fully-portable /bin/sh, especially when it comes to quoting the filenames. Error messages: - if err=StdErr, any error message goes in the stderr of our script. - if err=StdOut, we merge stderr and stdout (just as 2>&1). - if err=DevNull, we drop the error messages (same as 2>/dev/null). *) type err = StdErr | StdOut | DevNull let exe = ref "" (* Will be set later on, when the call to uname is done *) let run ?(fatal=true) ?(verbose=false) ?(err=StdErr) prog args = let prog = (* Ensure prog ends with exe *) if Str.string_match (Str.regexp ("^.*" ^ !exe ^ "$")) prog 0 then prog else (prog ^ !exe) in let argv = Array.of_list (prog::args) in try let out_r,out_w = Unix.pipe () in let nul_r,nul_w = Unix.pipe () in let () = Unix.set_close_on_exec out_r in let () = Unix.set_close_on_exec nul_r in let fd_err = match err with | StdErr -> Unix.stderr | StdOut -> out_w | DevNull -> nul_w in let pid = Unix.create_process prog argv Unix.stdin out_w fd_err in let () = Unix.close out_w in let () = Unix.close nul_w in let line, all = read_lines_and_close_fd out_r in let _ = read_lines_and_close_fd nul_r in let () = check_exit_code (waitpid_non_intr pid) in line, all with | _ when not fatal && not verbose -> "", [] | e -> let cmd = String.concat " " (prog::args) in let exn = match e with Failure s -> s | _ -> Printexc.to_string e in let msg = sprintf "Error while running '%s' (%s)" cmd exn in if fatal then die msg else (warn "%s" msg; "", []) let tryrun prog args = run ~fatal:false ~err:DevNull prog args (** Splitting a string at some character *) let string_split c s = let len = String.length s in let rec split n = try let pos = String.index_from s n c in let dir = String.sub s n (pos-n) in dir :: split (succ pos) with | Not_found -> [String.sub s n (len-n)] in if len = 0 then [] else split 0 (** String prefix test : does [s1] starts with [s2] ? *) let starts_with s1 s2 = let l1 = String.length s1 and l2 = String.length s2 in l2 <= l1 && s2 = String.sub s1 0 l2 (** Turn a version string such as "4.01.0+rc2" into the list ["4";"01";"1"], stopping at the first non-digit or "." *) let numeric_prefix_list s = let isnum c = (c = '.' || (c >= '0' && c <= '9')) in let max = String.length s in let i = ref 0 in while !i < max && isnum s.[!i] do incr i done; match string_split '.' (String.sub s 0 !i) with | [v] -> [v;"0";"0"] | [v1;v2] -> [v1;v2;"0"] | [v1;v2;""] -> [v1;v2;"0"] (* e.g. because it ends with ".beta" *) | v -> v let generic_version_nums ~name version_string = let version_list = numeric_prefix_list version_string in if !debug then begin let pp_sep = Format.pp_print_space in Format.(eprintf "Parsing version info for %s: @[raw: %s / split: %a@]@\n%!" name version_string (pp_print_list ~pp_sep pp_print_string) version_list) end; try List.map int_of_string version_list with _ -> "I found " ^ name ^ " but cannot read its version number!\n" ^ "Is it installed properly?" |> die (** Combined existence and directory tests *) let dir_exists f = Sys.file_exists f && Sys.is_directory f (** Does a file exist and is executable ? *) let is_executable f = try let () = Unix.access f [Unix.X_OK] in true with Unix.Unix_error _ -> false (** Equivalent of rm -f *) let safe_remove f = try Unix.chmod f 0o644; Sys.remove f with Unix.Unix_error _ | Sys_error _ -> () (** The PATH list for searching programs *) let os_type_win32 = (Sys.os_type = "Win32") let os_type_cygwin = (Sys.os_type = "Cygwin") let global_path = try string_split (if os_type_win32 then ';' else ':') (Sys.getenv "PATH") with Not_found -> [] (** A "which" command. May raise [Not_found] *) let which prog = let rec search = function | [] -> raise Not_found | dir :: path -> let file = if os_type_win32 then dir/prog^".exe" else dir/prog in if is_executable file then file else search path in search global_path let program_in_path prog = try let _ = which prog in true with Not_found -> false (** * Architecture *) let arch_progs = [("/bin/uname",["-s"]); ("/usr/bin/uname",["-s"]); ("/bin/arch", []); ("/usr/bin/arch", []); ("/usr/ucb/arch", []) ] let query_arch () = cprintf "I can not automatically find the name of your architecture."; cprintf "Give me a name, please [win32 for Win95, Win98 or WinNT]: %!"; read_line () let rec try_archs = function | (prog,args)::rest when is_executable prog -> let arch, _ = tryrun prog args in if arch <> "" then arch else try_archs rest | _ :: rest -> try_archs rest | [] -> query_arch () let arch = function | Some a -> a | None -> let arch,_ = tryrun "uname" ["-s"] in if starts_with arch "CYGWIN" then "win32" else if starts_with arch "MINGW32" then "win32" else if arch <> "" then arch else try_archs arch_progs let write_config_file ~file ?(bin=false) action = safe_remove file; let o = if bin then open_out_bin file else open_out file in try action o; close_out o; Unix.chmod file 0o444 with exn -> close_out o; safe_remove file; raise exn rocq-9.2.0/tools/configure/util.mli000066400000000000000000000032141516144147600173000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a val string_split : char -> string -> string list val starts_with : string -> string -> bool val generic_version_nums : name:string -> string -> int list val warn : ('a, out_channel, unit, unit, unit, unit) format6 -> 'a val die : string -> 'a val is_executable : string -> bool val dir_exists : string -> bool val which : string -> string val program_in_path : string -> bool val exe : string ref type err = StdErr | StdOut | DevNull val run : ?fatal:bool -> ?verbose:bool -> ?err:err -> string -> string list -> string * string list val tryrun : string -> string list -> string * string list val read_lines_and_close : in_channel -> string * string list val arch : string option -> string (* bin is used to avoid adding \r on Cygwin/Windows *) val write_config_file : file:string -> ?bin:bool -> (out_channel -> unit) -> unit (* enable debug mode *) val debug : bool ref rocq-9.2.0/tools/coq_makefile.ml000066400000000000000000000013671516144147600166170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* str "Unknown option \"" ++ str opt ++ str "\".") let usage () = let open Printf in eprintf " usage: rocq dep [options] +\n"; eprintf " options:\n"; eprintf " -boot : For rocq developers, prints dependencies over rocq library files (omitted by default).\n"; eprintf " -sort : output the given file name ordered by dependencies\n"; eprintf " -noglob | -no-glob : \n"; eprintf " -noinit : currently no effect\n"; eprintf " -f file : read -I, -Q, -R and filenames from _CoqProject-formatted file.\n"; eprintf " -I dir : add (non recursively) dir to ocaml path\n"; eprintf " -R dir logname : add and import dir recursively to rocq load path under logical name logname\n"; eprintf " -Q dir logname : add (recursively) and open (non recursively) dir to rocq load path under logical name logname\n"; eprintf " -vos : also output dependencies about .vos files\n"; eprintf " -exclude-dir dir : skip subdirectories named 'dir' during -R/-Q search\n"; eprintf " -coqlib dir : set the rocq core library directory\n"; eprintf " -dyndep (opt|byte|both|no|var) : set how dependencies over ML modules are printed\n"; eprintf " -worker WORKER : output WORKER instead of the rocqworker path\n"; eprintf " -w (w1,..,wn) : configure display of warnings\n"; eprintf "%!"; (* flush *) exit 1 let warn_project_file = let category = CWarnings.CoreCategories.filesystem in CWarnings.create ~name:"project-file" ~category Pp.str let add_ml_path st f = { st with ml_path = f :: st.ml_path } let add_vo_path st (isr,path,logic) = let logic = if String.equal logic "Coq" then "Corelib" else logic in { st with vo_path = (isr,path,logic) :: st.vo_path } let add_file st f = { st with files = f :: st.files } let add_from_coqproject st f = let open CoqProject_file in let fold_sourced f acc l = List.fold_left (fun acc {thing} -> f acc thing) acc l in let project = try read_project_file ~warning_fn:warn_project_file f with | Parsing_error msg -> Error.cannot_parse_project_file f msg | UnableToOpenProjectFile msg -> Error.cannot_open_project_file msg in let st = fold_sourced (fun st { path } -> add_ml_path st path) st project.ml_includes in let st = fold_sourced (fun st ({path}, l) -> add_vo_path st (false,path,l)) st project.q_includes in let st = fold_sourced (fun st ({path}, l) -> add_vo_path st (true,path,l)) st project.r_includes in let st = fold_sourced add_file st (all_files project) in st let parse st args = let rec parse st = function | "-boot" :: ll -> parse { st with boot = true } ll | "-sort" :: ll -> parse { st with sort = true } ll | "-vos" :: ll -> parse { st with vos = true } ll | ("-noglob" | "-no-glob") :: ll -> parse { st with noglob = true } ll | "-noinit" :: ll -> (* do nothing *) parse st ll | "-f" :: f :: ll -> parse (add_from_coqproject st f) ll | "-I" :: r :: ll -> parse (add_ml_path st r) ll | "-I" :: [] -> usage () | "-R" :: r :: ln :: ll -> parse (add_vo_path st (true, r, ln)) ll | "-Q" :: r :: ln :: ll -> parse (add_vo_path st (false, r, ln)) ll | ("-Q"|"-R") :: ([] | [_]) -> usage () | "-exclude-dir" :: r :: ll -> System.exclude_directory r; parse st ll | "-exclude-dir" :: [] -> usage () | "-coqlib" :: r :: ll -> parse { st with coqlib = Some r } ll | "-coqlib" :: [] -> usage () | "-dyndep" :: dyndep :: ll -> parse { st with dyndep } ll | "-worker" :: w :: ll -> parse { st with worker = Some w } ll | "-w" :: w :: ll -> let w = if w = "none" then w else CWarnings.get_flags() ^ "," ^ w in CWarnings.set_flags w; parse st ll | ("-h"|"--help"|"-help") :: _ -> usage () | opt :: ll when String.length opt > 0 && opt.[0] = '-' -> warn_unknown_option opt; parse st ll | f :: ll -> parse (add_file st f) ll | [] -> st in let st = parse st args in { st with ml_path = List.rev st.ml_path ; vo_path = List.rev st.vo_path ; files = List.rev st.files } rocq-9.2.0/tools/coqdep/lib/args.mli000066400000000000000000000017511516144147600173230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t val usage : unit -> 'a val parse : t -> string list -> t rocq-9.2.0/tools/coqdep/lib/common.ml000066400000000000000000000351551516144147600175130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* [] in let map = CString.Map.add f' (f :: old) vAccu.map in { acc; map } let empty_vAccu = { acc = []; map = CString.Map.empty } let filename_concat ~separator_hack dir name = if separator_hack then System.(dir // name) else Filename.concat dir name (* This is used to overcome makefile limitations w.r.t. filenames, (bar/../foo is not the same than ./foo for make) but it is a crude hack and we should remove it, and instead require users to follow the same naming convention *) let canonize ~separator_hack vAccu f = let f' = filename_concat ~separator_hack (Loadpath.absolute_dir (Filename.dirname f)) (Filename.basename f) in match CString.Map.find_opt f' vAccu.map with | None | Some [] -> f | Some (f :: _) -> f type what = Library | External let str_of_what = function Library -> "library" | External -> "external file" let warning_module_notfound = let warn (what, from, f, s) = let open Pp in str "in file " ++ str f ++ str ", " ++ str (str_of_what what) ++ spc () ++ str (String.concat "." s) ++ str " is required" ++ pr_opt (fun pth -> str "from root " ++ str (String.concat "." pth)) from ++ str " and has not been found in the loadpath!" in CWarnings.create ~name:"module-not-found" ~category:CWarnings.CoreCategories.filesystem warn let warn_if_clash ?(what=Library) exact file dir f1 = let open Format in function | f2::fl -> let f = match what with | Library -> Filename.basename f1 ^ ".v" | External -> Filename.basename f1 in let what = str_of_what what in let d1 = Filename.dirname f1 in let d2 = Filename.dirname f2 in let dl = List.rev_map Filename.dirname fl in if exact then begin eprintf "*** Warning: in file %s, \n required %s %s exactly matches several files in path\n (found %s in " file what (String.concat "." dir) f; List.iter (fun s -> eprintf "%s, " s) dl; eprintf "%s and %s; used the latter).\n" d2 d1 end else begin eprintf "*** Warning: in file %s, \n required %s %s matches several files in path\n (found %s in " file what (String.concat "." dir) f; List.iter (fun s -> eprintf "%s, " s) dl; eprintf "%s and %s; Require will fail).\n" d2 d1 end | [] -> () let safe_assoc ?(warn_clashes=true) st ?(what=Library) from file k = let search = match what with | Library -> Loadpath.search_v_known st | External -> Loadpath.search_other_known st in match search ?from k with | None -> None | Some (Loadpath.ExactMatches fs) -> let f = fs.Loadpath.point in let l = Loadpath.FileSet.elements fs.files in let l = List.map Loadpath.Filename.repr l in let l = List.filter (fun f' -> not (String.equal f f')) l in if warn_clashes then warn_if_clash ~what true file k f l; Some [f] | Some (Loadpath.PartialMatchesInSameRoot (root, l)) -> let l = Loadpath.FileSet.elements l.files in let l = List.map Loadpath.Filename.repr l in (match List.sort String.compare l with [] -> assert false | f :: l as all -> (* If several files match, it will fail at Require; To be "fair", in rocq dep, we add dependencies on all matching files *) if warn_clashes then warn_if_clash ~what false file k f l; Some all) let file_name ~separator_hack s = function | None -> s | Some d -> filename_concat ~separator_hack d s module VData = struct type t = string list option * string list let compare = compare end module VCache = Set.Make(VData) (** To avoid reading .v files several times for computing dependencies, once for .vo, and once for .vos extensions, the following code performs a single pass and produces a structured list of dependencies, separating dependencies on compiled Rocq files (those loaded by [Require]) from other dependencies, e.g. dependencies on ".v" files (for [Load]) or ".cmx", ".cmo", etc... (for [Declare]). *) (* Transform "Declare ML %DECL" to a pair of (meta, cmxs). Something very similar is in ML top *) let declare_ml_to_file file (decl : string) = let legacy_decl = String.split_on_char ':' decl in match legacy_decl with | [package] -> Fl.findlib_deep_resolve ~file ~package | [cmxs; package] -> (* rocq compile will warn *) Fl.findlib_deep_resolve ~file ~package | bad_pkg -> CErrors.user_err Pp.(str "Failed to resolve plugin: " ++ str decl) let coq_to_stdlib from strl = let tr_qualid = function | "Coq" :: l -> "Stdlib" :: l | l -> l in match from with | Some from -> Some (tr_qualid from), strl | None -> None, List.map tr_qualid strl let with_in_channel ~fname f = let chan = try open_in fname with Sys_error msg -> Error.cannot_open fname msg in Util.try_finally f chan close_in chan module State = struct type t = { loadpath : Loadpath.State.t; separator_hack : bool; vAccu : vAccu; } let loadpath x = x.loadpath end exception SyntaxErrorInFile of string (* recursive because of Load *) let rec find_dependencies ({State.vAccu; separator_hack; loadpath} as st) basename = (* Visited marks *) let visited_ml = ref CString.Set.empty in let visited_v = ref VCache.empty in let should_visit_v_and_mark from str = if not (VCache.mem (from, str) !visited_v) then begin visited_v := VCache.add (from, str) !visited_v; true end else false in (* Output: dependencies found *) let module DepSet = Dep_info.Dep.Set in let dependencies = ref DepSet.empty in let add_dep dep = dependencies := DepSet.add dep !dependencies in let add_dep_other s = add_dep (Dep_info.Dep.Other s) in (* worker dep *) let () = add_dep_other (Loadpath.get_worker_path loadpath) in (* Reading file contents *) let f = basename ^ ".v" in with_in_channel ~fname:f @@ fun chan -> (* For lexing efficiency purposes, we ignore the positions in this function. This will force us to reparse the file in case of error to get a proper location, but in practice such errors should be exceedingly rare with rocqdep. This lexer is indeed basically able to handle random nonsense thrown at it. *) let buf = Lexing.from_channel ~with_positions:false chan in let open Lexer in let rec loop () = match coq_action buf with | exception Fin_fichier -> DepSet.elements !dependencies | exception Syntax_error _ -> (* The locations are garbage due to with_positions:false, ignore them *) raise (SyntaxErrorInFile f) | tok -> match tok with | Require (from, strl) -> let from, strl = coq_to_stdlib from strl in let decl str = if should_visit_v_and_mark from str then begin let files = safe_assoc loadpath from f str in let files = match from, files with | Some _, _ | None, Some _ -> files | None, None -> safe_assoc loadpath (Some ["Stdlib"]) f str in match files with | Some files -> List.iter (fun file_str -> let file_str = canonize ~separator_hack vAccu file_str in add_dep (Dep_info.Dep.Require file_str)) files | None -> if not (Loadpath.is_in_coqlib loadpath ?from str) then warning_module_notfound (Library, from, f, str) end in List.iter decl strl; loop () | Declare sl -> (* We resolve "pkg_name" to a .cma file, using the META *) let sl = List.map (declare_ml_to_file f) sl in let decl (meta_file, str) = List.iter add_dep_other meta_file; str |> List.iter (fun str -> let plugin_file = Filename.chop_extension str in if not (CString.Set.mem plugin_file !visited_ml) then begin visited_ml := CString.Set.add plugin_file !visited_ml; add_dep (Dep_info.Dep.Ml plugin_file) end) in List.iter decl sl; loop () | Load file -> let canon = match file with | Logical str -> if should_visit_v_and_mark None [str] then safe_assoc loadpath None f [str] else None | Physical str -> if String.equal (Filename.basename str) str then if should_visit_v_and_mark None [str] then safe_assoc loadpath None f [str] else None else Some [canonize ~separator_hack vAccu str] in (match canon with | None -> () | Some l -> let decl canon = add_dep_other (Format.sprintf "%s.v" canon); let deps = find_dependencies st canon in List.iter add_dep deps in List.iter decl l); loop () | External(from,str) -> begin match safe_assoc loadpath ~what:External (Some from) f [str] with | Some (file :: _) -> add_dep (Dep_info.Dep.Other (canonize ~separator_hack vAccu file)) | Some [] -> assert false | None -> if not (Loadpath.is_other_in_coqlib loadpath ~from [str]) then warning_module_notfound (External, Some from, f, [str]) end; loop () in loop () (* Reparse the file to get the error location *) let get_parse_error f = with_in_channel ~fname:f @@ fun chan -> let buf = Lexing.from_channel chan in let rec loop () = match Lexer.coq_action buf with | _tok -> loop () | exception Lexer.Syntax_error (i, j) -> (i, j) | exception Lexer.Fin_fichier -> (* may technically happen due to race conditions, return a dummy value *) (0, 0) in loop () let find_dependencies st basename = try find_dependencies st basename with SyntaxErrorInFile f -> let (i, j) = get_parse_error f in Error.cannot_parse f (i, j) let compute_deps st = let mk_dep (name, _orig_path) = Dep_info.make ~name ~deps:(find_dependencies st name) in st.vAccu.acc |> CList.rev_map mk_dep let rec treat_file ~separator_hack vAccu old_dirname old_name = let name = Filename.basename old_name and new_dirname = Filename.dirname old_name in let dirname = match (old_dirname,new_dirname) with | (d, ".") -> d (* EGJA: We should disable this buggy normalization stuff for "./foo -> foo" but it breaks dune coq.theory! *) | (None,d) -> Some d | (Some d1,d2) -> Some (filename_concat ~separator_hack d1 d2) in let complete_name = file_name ~separator_hack name dirname in let stat_res = try Unix.stat complete_name with Unix.Unix_error(error, _, _) -> Error.cannot_open complete_name (Unix.error_message error) in match stat_res.Unix.st_kind with | Unix.S_DIR -> (if name.[0] = '.' then vAccu else let newdirname = match dirname with | None -> name | Some d -> filename_concat ~separator_hack d name in Array.fold_left (fun vAccu x -> treat_file ~separator_hack vAccu (Some newdirname) x) vAccu (Sys.readdir complete_name)) | Unix.S_REG -> (match Loadpath.get_extension name [".v"] with | base,".v" -> let name = file_name ~separator_hack base dirname in let filename_concat = filename_concat ~separator_hack in let absname = Loadpath.absolute_file_name ~filename_concat base dirname in add_vAccu (name, absname) vAccu | _ -> vAccu) | _ -> vAccu let treat_file_command_line ({State.vAccu; separator_hack} as st) old_name = let vAccu = treat_file ~separator_hack vAccu None old_name in { st with State.vAccu } (* "[sort]" outputs `.v` files required by others *) let sort {State.vAccu; separator_hack; loadpath} = let seen = Hashtbl.create 97 in let rec loop file = let file = canonize ~separator_hack vAccu file in if not (Hashtbl.mem seen file) then begin Hashtbl.add seen file (); let cin = open_in (file ^ ".v") in let lb = Lexing.from_channel cin in try while true do match Lexer.coq_action lb with | Lexer.Require (from, sl) -> List.iter (fun s -> match safe_assoc loadpath from ~warn_clashes:false file s with | None -> () | Some l -> List.iter loop l) sl | _ -> () done with Lexer.Fin_fichier -> close_in cin; Format.printf "%s.v " file end in List.iter (fun (name, _) -> loop name) vAccu.acc let add_include st (rc, r, ln) = if rc then Loadpath.add_r_include st r ln else Loadpath.add_q_include st r ln let findlib_init dirs = let env_ocamlpath = try [Sys.getenv "OCAMLPATH"] with Not_found -> [] in let env_ocamlpath = dirs @ env_ocamlpath in let ocamlpathsep = if Sys.unix then ":" else ";" in let env_ocamlpath = String.concat ocamlpathsep env_ocamlpath in Findlib.init ~env_ocamlpath () let init ~make_separator_hack args = if not Coq_config.has_natdynlink then Makefile.set_dyndep "no"; let loadpath = Loadpath.State.make ~worker:args.Args.worker ~boot:args.Args.boot in Makefile.set_write_vos args.Args.vos; Makefile.set_noglob args.Args.noglob; (* Add to the findlib search path, common with sysinit/coqinit *) let ml_path = args.Args.ml_path in let rocqenv = Boot.Env.maybe_init ~boot:args.boot ~coqlib:args.coqlib ~warn_ignored_coqlib:CWarnings.warn_ignored_coqlib in let ml_path = match rocqenv with | Boot -> ml_path | Env env -> ml_path @ Boot.Env.Path.[to_string @@ relative (Boot.Env.runtimelib env) ".."] in findlib_init ml_path; List.iter (add_include loadpath) args.Args.vo_path; Makefile.set_dyndep args.Args.dyndep; rocqenv, { State.vAccu = empty_vAccu; loadpath; separator_hack = make_separator_hack } rocq-9.2.0/tools/coqdep/lib/common.mli000066400000000000000000000021121516144147600176470ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Loadpath.State.t end (** [init args] Init coqdep, setting arguments from [args]. *) val init : make_separator_hack:bool -> Args.t -> Boot.Env.maybe_env * State.t (** [treat_file_command_line file] Add an input file to be considered *) val treat_file_command_line : State.t -> string -> State.t val sort : State.t -> unit val compute_deps : State.t -> Dep_info.t list rocq-9.2.0/tools/coqdep/lib/dep_info.ml000066400000000000000000000024671516144147600200060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* CString.compare a b | Require _, _ -> -1 | _, Require _ -> 1 | Ml _, _ -> -1 | _, Ml _ -> 1 module Set = CSet.Make(struct type nonrec t = t let compare = compare end) end type t = { name : string (* This should become [module : Coq_module.t] eventually *) ; deps : Dep.t list } let make ~name ~deps = { name; deps } rocq-9.2.0/tools/coqdep/lib/dep_info.mli000066400000000000000000000022111516144147600201420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* deps:Dep.t list -> t rocq-9.2.0/tools/coqdep/lib/dune000066400000000000000000000002251516144147600165350ustar00rootroot00000000000000(library (name coqdeplib) (public_name rocq-runtime.coqdeplib) (libraries rocq-runtime.boot rocq-runtime.lib findlib.internal)) (ocamllex lexer) rocq-9.2.0/tools/coqdep/lib/error.ml000066400000000000000000000033021516144147600173410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some Pp.(str "File \"" ++ str s ++ str "\"," ++ str "characters" ++ spc () ++ int i ++ str "-" ++ int j ++ str ":" ++ spc () ++ str "Syntax error") | CannotParseProjectFile (file, msg) -> Some Pp.(str "Project file" ++ spc () ++ str "\"" ++ str file ++ str "\":" ++ spc () ++ str "Syntax error:" ++ str msg) | CannotOpenFile (s, msg) -> Some Pp.(str s ++ str ":" ++ spc () ++ str msg) | CannotOpenProjectFile msg -> (* TODO: more info? *) Some Pp.(str msg) | _ -> None let cannot_parse s ij = raise @@ CannotParseFile (s, ij) let cannot_open_project_file msg = raise @@ CannotOpenProjectFile msg let cannot_parse_project_file file msg = raise @@ CannotParseProjectFile (file, msg) let cannot_open s msg = raise @@ CannotOpenFile (s, msg) rocq-9.2.0/tools/coqdep/lib/error.mli000066400000000000000000000020321516144147600175110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int * int -> 'a val cannot_open_project_file : string -> 'a val cannot_parse_project_file : string -> string -> 'a val cannot_open : string -> string -> 'a rocq-9.2.0/tools/coqdep/lib/file_util.ml000066400000000000000000000036241516144147600201730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string = fun full_path -> if Filename.is_relative full_path then full_path else let cwd = Str.split_delim re_delim (Sys.getcwd ()) in let path = Str.split_delim re_delim full_path in let rec remove_common_prefix l1 l2 = match (l1, l2) with | (x1 :: l1, x2 :: l2) when x1 = x2 -> remove_common_prefix l1 l2 | (_ , _ ) -> (l1, String.concat "/" l2) in let (cwd, path) = remove_common_prefix cwd path in let add_parent path _ = Filename.concat Filename.parent_dir_name path in List.fold_left add_parent path cwd let normalize_path : string -> string = fun path -> let path = Str.split_delim re_delim path in let rec normalize acc path = match (path, acc) with | ([] , _ ) -> List.rev acc | ("." :: path, _ ) -> normalize acc path | (".." :: path, [] ) -> normalize (".." :: []) path | (".." :: path, ".." :: _ ) -> normalize (".." :: acc) path | (".." :: path, _ :: acc) -> normalize acc path | (dir :: path, _ ) -> normalize (dir :: acc) path in match normalize [] path with | [] -> "." | path -> String.concat "/" path rocq-9.2.0/tools/coqdep/lib/file_util.mli000066400000000000000000000030621516144147600203400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string (** [normalize_path path] takes as input a file path [path], and returns an equivalent path that: (1) does not contain the current directory member ["."] unless the path is to the current directory (in which case ["."] is returned, or ["./"] if [path] has a trailing ["/"]), (2) only uses parent directory members [".."] for a prefix of the path, and (3), has a trailing ["/"] only if and only if [path] does. For example, paths ["dir1/dir2/file.v"], ["."], ["dir1/dir2/dir3/"] and ["../../dir/file.v"] are possible return values, but ["./file.v"] and ["dir1/../dir2"] are not. *) val normalize_path : string -> string rocq-9.2.0/tools/coqdep/lib/fl.ml000066400000000000000000000077161516144147600166260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if i split i (j+1) else if i try fst (Findlib.package_property_2 ("plugin"::coqc_predicates) lib "archive") with Not_found -> "" in fl_split_in_words archive |> List.map (Findlib.resolve_path ~base) (* first string is the v file which triggered the error, rest is Fl_package_base.No_such_package *) exception No_such_package of string * string * string let () = CErrors.register_handler Pp.(function | No_such_package(vfile,p,msg) -> let paths = Findlib.search_path () in Some (hov 0 (str "In file" ++ spc() ++ str vfile ++ spc() ++ str "findlib error: " ++ str p ++ str " not found in:" ++ cut () ++ v 0 (prlist_with_sep cut str paths) ++ fnl() ++ str msg)) | _ -> None ) end let relative_if_dune path = (* relativize the path if inside the current dune workspace if we relativize paths outside the dune workspace it fails so make sure to avoid it *) match Sys.getenv_opt "DUNE_SOURCEROOT" with | Some dune when CString.is_prefix (Filename.concat dune "_build") path -> normalize_path (to_relative_path path) | _ -> normalize_path path let findlib_resolve ~package = let meta_file = Findlib.package_meta_file package in let cmxss = Fl_internals.fl_find_plugins package in let meta_file = relative_if_dune meta_file in let cmxs_file = List.map relative_if_dune cmxss in (meta_file, cmxs_file) let static_libs () = let packages = Findlib.package_deep_ancestors coqc_predicates ["rocq-runtime.toplevel"] in CString.Set.of_list packages let static_libs = Lazy.from_fun static_libs let findlib_deep_resolve ~package = let packages = Findlib.package_deep_ancestors coqc_predicates [package] in let packages = CList.filter (fun package -> not (CString.Set.mem package (Lazy.force static_libs))) packages in List.fold_left (fun (metas,cmxss) package -> let meta, cmxss' = findlib_resolve ~package in meta :: metas, cmxss' @ cmxss) ([],[]) packages let findlib_deep_resolve ~file ~package = try findlib_deep_resolve ~package with Fl_package_base.No_such_package(p,m) -> raise (Fl_internals.No_such_package (file,p,m)) module Internal = struct let get_worker_path () = let top = "rocqworker" in let dir = Findlib.package_directory "rocq-runtime" in let exe = if Sys.(os_type = "Win32" || os_type = "Cygwin") then ".exe" else "" in let file = Filename.concat dir (top^exe) in relative_if_dune file end rocq-9.2.0/tools/coqdep/lib/fl.mli000066400000000000000000000024121516144147600167630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* package:string -> string list * string list module Internal : sig (** Call Loadpath.get_worker_path instead *) val get_worker_path : unit -> string end rocq-9.2.0/tools/coqdep/lib/lexer.mli000066400000000000000000000017431516144147600175070ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* coq_token rocq-9.2.0/tools/coqdep/lib/lexer.mll000066400000000000000000000167521516144147600175200ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* s | Some _ -> syntax_error lexbuf let get_ident lexbuf = let s = Lexing.lexeme lexbuf in check_valid lexbuf s let get_field_name lexbuf = let s = Lexing.lexeme lexbuf in check_valid lexbuf (String.sub s 1 (String.length s - 1)) } let space = [' ' '\t' '\n' '\r'] let lowercase = ['a'-'z'] let uppercase = ['A'-'Z'] let identchar = ['A'-'Z' 'a'-'z' '_' '\'' '0'-'9'] let caml_up_ident = uppercase identchar* let caml_low_ident = lowercase identchar* (* This is an overapproximation, we check correctness afterwards *) let coq_ident = ['A'-'Z' 'a'-'z' '_' '\128'-'\255'] ['A'-'Z' 'a'-'z' '_' '\'' '0'-'9' '\128'-'\255']* let coq_field = '.' coq_ident let coq_qual_id_rex = coq_ident coq_field+ let dot = '.' ( space+ | eof) rule coq_action = parse | "Require" space+ { require_modifiers None lexbuf } | "Local" space+ "Declare" space+ "ML" space+ "Module" space+ { modules [] lexbuf } | "Declare" space+ "ML" space+ "Module" space+ { modules [] lexbuf } | "Load" space+ { load_file lexbuf } | "Time" space+ { coq_action lexbuf } | "Timeout" space+ ['0'-'9']+ space+ { coq_action lexbuf } | "From" space+ { from_rule false lexbuf } | "Comments" space+ "From" space+ { from_rule true lexbuf } | "#[" { skip_attribute lexbuf; coq_action lexbuf } | space+ { coq_action lexbuf } | "(*" { comment lexbuf; coq_action lexbuf } | eof { raise Fin_fichier} | _ { skip_to_dot lexbuf; coq_action lexbuf } and skip_attribute = parse | "(*" { comment lexbuf; skip_attribute lexbuf } | "]" { () } | '"' [^ '"']* '"' { skip_attribute lexbuf } | _ { skip_attribute lexbuf } and from_rule only_extra_dep = parse | "(*" { comment lexbuf; from_rule only_extra_dep lexbuf } | space+ { from_rule only_extra_dep lexbuf } | coq_ident { let from = coq_qual_id_tail [get_ident lexbuf] lexbuf in consume_require_or_extradeps only_extra_dep (Some from) lexbuf } | eof { syntax_error lexbuf } | _ { syntax_error lexbuf } and extra_dep_rule from = parse | "(*" { comment lexbuf; extra_dep_rule from lexbuf } | space+ { extra_dep_rule from lexbuf } | eof { syntax_error lexbuf } | '"' ([^ '"']+ as f) '"' (*'"'*) { skip_to_dot lexbuf; External (from,f) } and require_modifiers from = parse | "(*" { comment lexbuf; require_modifiers from lexbuf } | ("Import" | "Export") space* ("-" space*)? ((space | "(") as p) { if p = '(' then skip_parenthesized lexbuf; require_file from lexbuf } | space+ { require_modifiers from lexbuf } | eof { syntax_error lexbuf } | _ { backtrack lexbuf ; require_file from lexbuf } and consume_require_or_extradeps only_extra_dep from = parse | "(*" { comment lexbuf; consume_require_or_extradeps only_extra_dep from lexbuf } | space+ { consume_require_or_extradeps only_extra_dep from lexbuf } | "Require" space+ { if only_extra_dep then syntax_error lexbuf; require_modifiers from lexbuf } | "Extra" space+ "Dependency" space+ { match from with | None -> syntax_error lexbuf (* Extra Dependency requires From *) | Some from -> extra_dep_rule from lexbuf } | _ { syntax_error lexbuf } and comment = parse | "(*" { comment lexbuf; comment lexbuf } | "*)" { () } | "'" [^ '\\' '\''] "'" { comment lexbuf } | "'" '\\' ['\\' '\'' 'n' 't' 'b' 'r'] "'" { comment lexbuf } | "'" '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" { comment lexbuf } | eof { raise Fin_fichier } | _ { comment lexbuf } and skip_parenthesized = parse | "(*" { comment lexbuf; skip_parenthesized lexbuf } | "(" { skip_parenthesized lexbuf; skip_parenthesized lexbuf } | ")" { () } | eof { raise Fin_fichier } | _ { skip_parenthesized lexbuf } and load_file = parse | '"' [^ '"']* '"' (*'"'*) { let s = lexeme lexbuf in parse_dot lexbuf; Load (Physical (unquote_vfile_string s)) } | coq_ident { let s = get_ident lexbuf in skip_to_dot lexbuf; Load (Logical s) } | eof { syntax_error lexbuf } | _ { syntax_error lexbuf } and require_file from = parse | "(*" { comment lexbuf; require_file from lexbuf } | space+ { require_file from lexbuf } | coq_ident { let name = coq_qual_id_tail [get_ident lexbuf] lexbuf in let qid = coq_qual_id_list [name] lexbuf in parse_dot lexbuf; Require (from, qid) } | eof { syntax_error lexbuf } | _ { syntax_error lexbuf } and skip_to_dot = parse | "(*" { comment lexbuf; skip_to_dot lexbuf } | dot { () } | eof { syntax_error lexbuf } | _ { skip_to_dot lexbuf } and parse_dot = parse | dot { () } | eof { syntax_error lexbuf } | _ { syntax_error lexbuf } and coq_qual_id_tail module_name = parse | "(*" { comment lexbuf; coq_qual_id_tail module_name lexbuf } | space+ { coq_qual_id_tail module_name lexbuf } | coq_field { coq_qual_id_tail (get_field_name lexbuf :: module_name) lexbuf } | eof { syntax_error lexbuf } | _ { backtrack lexbuf; List.rev module_name } and coq_qual_id_list module_names = parse | "(*" { comment lexbuf; coq_qual_id_list module_names lexbuf } | "(" { skip_parenthesized lexbuf; coq_qual_id_list module_names lexbuf } | space+ { coq_qual_id_list module_names lexbuf } | coq_ident { let name = coq_qual_id_tail [get_ident lexbuf] lexbuf in coq_qual_id_list (name :: module_names) lexbuf } | eof { syntax_error lexbuf } | _ { backtrack lexbuf; List.rev module_names } and modules mllist = parse | space+ { modules mllist lexbuf } | "(*" { comment lexbuf; modules mllist lexbuf } | '"' [^'"']* '"' { let lex = (Lexing.lexeme lexbuf) in let str = String.sub lex 1 (String.length lex - 2) in modules (str :: mllist) lexbuf} | eof { syntax_error lexbuf } | _ { Declare (List.rev mllist) } rocq-9.2.0/tools/coqdep/lib/loadpath.ml000066400000000000000000000236471516144147600200220ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* dir | None -> "." in (* XXX: Attention to System.(//) which does weird things and it is not the same than Filename.concat ; using Filename.concat here makes the windows build fail *) filename_concat (absolute_dir dir) basename (** [find_dir_logpath dir] Return the logical path of directory [dir] if it has been given one. Raise [Not_found] otherwise. In particular we can check if "." has been attributed a logical path after processing all options and silently give the default one if it hasn't. We may also use this to warn if a physical path is met twice. *) let register_dir_logpath, find_dir_logpath = let tbl: (string, string list) Hashtbl.t = Hashtbl.create 19 in let reg physdir logpath = Hashtbl.add tbl (absolute_dir physdir) logpath in let fnd physdir = Hashtbl.find tbl (absolute_dir physdir) in reg,fnd (** Visit all the directories under [dir], including [dir], in the same order as for [coqc]/[coqtop] in [System.all_subdirs], that is, assuming Sys.readdir to have this structure: β”œβ”€β”€ B β”‚ └── E.v β”‚ └── C1 β”‚ β”‚ └── E.v β”‚ β”‚ └── D1 β”‚ β”‚ └── E.v β”‚ β”‚ └── F.v β”‚ β”‚ └── D2 β”‚ β”‚ └── E.v β”‚ β”‚ └── G.v β”‚ └── F.v β”‚ └── C2 β”‚ β”‚ └── E.v β”‚ β”‚ └── D1 β”‚ β”‚ └── E.v β”‚ β”‚ └── F.v β”‚ β”‚ └── D2 β”‚ β”‚ └── E.v β”‚ β”‚ └── G.v β”‚ └── G.v it goes in this (reverse) order: B.C2.D1.E, B.C2.D2.E, B.C2.E, B.C2.F, B.C2.G B.C1.D1.E, B.C1.D2.E, B.C1.E, B.C1.F, B.C1.G, B.E, B.F, B.G, (see discussion at PR #14718) *) let add_directory recur add_file phys_dir log_dir = let root = (phys_dir, log_dir) in let stack = ref [] in let curdirfiles = ref [] in let subdirfiles = ref [] in let rec aux phys_dir log_dir = if System.exists_dir phys_dir then begin register_dir_logpath phys_dir log_dir; let f = function | System.FileDir (phys_f,f) -> if recur then begin stack := (!curdirfiles, !subdirfiles) :: !stack; curdirfiles := []; subdirfiles := []; aux phys_f (log_dir @ [f]); let curdirfiles', subdirfiles' = List.hd !stack in subdirfiles := subdirfiles' @ !subdirfiles @ !curdirfiles; curdirfiles := curdirfiles'; stack := List.tl !stack end | System.FileRegular f -> curdirfiles := (phys_dir, log_dir, f) :: !curdirfiles in System.process_directory f phys_dir end else System.warn_cannot_open_dir phys_dir in aux phys_dir log_dir; List.iter (fun (phys_dir, log_dir, f) -> add_file root phys_dir log_dir f) !subdirfiles; List.iter (fun (phys_dir, log_dir, f) -> add_file root phys_dir log_dir f) !curdirfiles (** [get_extension f l] checks whether [f] has one of the extensions listed in [l]. It returns [f] without its extension, alongside with the extension. When no extension match, [(f,"")] is returned *) let rec get_extension f = function | [] -> (f, "") | s :: _ when Filename.check_suffix f s -> (Filename.chop_suffix f s, s) | _ :: l -> get_extension f l (** Compute the suffixes of a logical path together with the length of the missing part *) let rec suffixes full = function | [] -> assert false | [name] -> [full,[name]] | dir::suffix as l -> (full,l)::suffixes false suffix (** Compute all the pairs [(from,suffs)] such that a logical path decomposes into [from @ ... @ suff] for some [suff] in [suffs], i.e. such that once [from] is fixed, [From from Require suff] refers (in the absence of ambiguity) to this logical path for exactly the [suff] in [suffs] *) let rec cuts recur = function | [] -> [] | [dir] -> [[],[true,[dir]]] | dir::tail as l -> ([],if recur then suffixes true l else [true,l]) :: List.map (fun (fromtail,suffixes) -> (dir::fromtail,suffixes)) (cuts true tail) module Filename = struct type t = { user : filename; absolute : filename; } let make s = { user = s; absolute = absolute_file_name ~filename_concat:Filename.concat (Filename.basename s) (Some (Filename.dirname s)); } let compare f1 f2 = String.compare f1.absolute f2.absolute let repr f = f.user end module FileSet = Set.Make(Filename) type fileset = { point : filename; files : FileSet.t; (* guaranteed to contain [point] *) } type result = | ExactMatches of fileset | PartialMatchesInSameRoot of root * fileset module State = struct type t = { vfiles : (dirpath * dirpath, result) Hashtbl.t ; coqlib : (dirpath * dirpath, result) Hashtbl.t ; other : (dirpath * dirpath, result) Hashtbl.t ; coqlibother : (dirpath * dirpath, result) Hashtbl.t ; boot : bool ; mutable worker : string option } let make ~worker ~boot = { vfiles = Hashtbl.create 4101 ; coqlib = Hashtbl.create 19 ; other = Hashtbl.create 17317 ; coqlibother = Hashtbl.create 17317 ; boot ; worker } end let get_worker_path st = match st.State.worker with | Some w -> w | None -> let w = Fl.Internal.get_worker_path () in st.worker <- Some w; w let singleton f = { point = f; files = FileSet.singleton (Filename.make f) } let add_set f l = { point = f; files = FileSet.add (Filename.make f) l.files } let insert_key root (full,f) m = (* An exact match takes precedence over non-exact matches *) match full, m with | true, ExactMatches l -> (* We add a conflict *) ExactMatches (add_set f l) | true, PartialMatchesInSameRoot _ -> (* We give priority to exact match *) ExactMatches (singleton f) | false, ExactMatches l -> (* We keep the exact match *) m | false, PartialMatchesInSameRoot (root',l) -> PartialMatchesInSameRoot (root, if root = root' then add_set f l else (singleton f)) let safe_add_key q root key (full,f as file) = try let l = Hashtbl.find q key in Hashtbl.add q key (insert_key root file l) with Not_found -> Hashtbl.add q key (if full then ExactMatches (singleton f) else PartialMatchesInSameRoot (root, singleton f)) let safe_add q root ((from, suffixes), file) = List.iter (fun (full,suff) -> safe_add_key q root (from,suff) (full,file)) suffixes let search_table table ?(from=[]) s = Hashtbl.find table (from, s) let search_v_known st ?from s = try Some (search_table st.State.vfiles ?from s) with Not_found -> None let search_other_known st ?from s = try Some (search_table st.State.other ?from s) with Not_found -> None let is_in_coqlib st ?from s = try let _ = search_table st.State.coqlib ?from s in true with Not_found -> match from with Some _ -> false | None -> try let _ = search_table st.State.coqlib ~from:["Stdlib"] s in true with Not_found -> false let is_other_in_coqlib st ~from s = try let _ = search_table st.State.coqlibother ~from s in true with Not_found -> false let add_paths recur root table phys_dir log_dir basename = let name = log_dir@[basename] in let file = System.(phys_dir // basename) in let paths = cuts recur name in let iter n = safe_add table root (n, file) in List.iter iter paths let add_coqlib_known st recur root phys_dir log_dir f = let root = (phys_dir, log_dir) in match get_extension f [".vo"; ".vos"] with | (basename, (".vo" | ".vos")) -> add_paths recur root st.State.coqlib phys_dir log_dir basename | (f,_) -> add_paths recur root st.State.coqlibother phys_dir log_dir f let add_known st recur root phys_dir log_dir f = match get_extension f [".v"; ".vo"; ".vos"] with | (basename,".v") -> add_paths recur root st.State.vfiles phys_dir log_dir basename | (basename, (".vo" | ".vos")) when not st.State.boot -> add_paths recur root st.State.vfiles phys_dir log_dir basename | (f,_) -> add_paths recur root st.State.other phys_dir log_dir f (** Simply add this directory and imports it, no subdirs. This is used by the implicit adding of the current path (which is not recursive). *) let add_norec_dir_import add_file phys_dir log_dir = add_directory false (add_file true) phys_dir log_dir (** -Q semantic: go in subdirs but only full logical paths are known. *) let add_rec_dir_no_import add_file phys_dir log_dir = add_directory true (add_file false) phys_dir log_dir (** -R semantic: go in subdirs and suffixes of logical paths are known. *) let add_rec_dir_import add_file phys_dir log_dir = add_directory true (add_file true) phys_dir log_dir let split_period = Str.split (Str.regexp (Str.quote ".")) let add_current_dir st dir = add_norec_dir_import (add_known st) dir [] let add_q_include st path l = add_rec_dir_no_import (add_known st) path (split_period l) let add_r_include st path l = add_rec_dir_import (add_known st) path (split_period l) rocq-9.2.0/tools/coqdep/lib/loadpath.mli000066400000000000000000000062701516144147600201640ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> string * string (* Loadpaths *) type basename = string type dirname = string type dir = string option type filename = string type dirpath = string list type root = filename * dirpath module Filename : sig type t val repr : t -> filename end module FileSet : Set.S with type elt = Filename.t type fileset = private { point : filename; files : FileSet.t; (* guaranteed to contain [point] *) } type result = | ExactMatches of fileset | PartialMatchesInSameRoot of root * fileset module State : sig type t val make : worker:string option -> boot:bool -> t end val get_worker_path : State.t -> string val search_v_known : State.t -> ?from:dirpath -> dirpath -> result option val search_other_known : State.t -> ?from:dirpath -> dirpath -> result option val is_in_coqlib : State.t -> ?from:dirpath -> dirpath -> bool val is_other_in_coqlib : State.t -> from:dirpath -> dirpath -> bool val add_current_dir : State.t -> System.unix_path -> unit val add_q_include : State.t -> System.unix_path -> string -> unit val add_r_include : State.t -> System.unix_path -> string -> unit (* These should disappear in favor of add_q / add_r *) (** Simply add this directory and imports it, no subdirs. This is used by the implicit adding of the current path. *) val add_norec_dir_import : (bool -> root -> dirname -> dirpath -> basename -> unit) -> dirname -> dirpath -> unit (** -Q semantic: go in subdirs but only full logical paths are known. *) val add_rec_dir_no_import : (bool -> root -> dirname -> dirpath -> basename -> unit) -> dirname -> dirpath -> unit (** -R semantic: go in subdirs and suffixes of logical paths are known. *) val add_rec_dir_import : (bool -> root -> dirname -> dirpath -> basename -> unit) -> dirname -> dirpath -> unit val add_known : State.t -> bool -> root -> dirname -> dirpath -> basename -> unit val add_coqlib_known : State.t -> bool -> root -> dirname -> dirpath -> basename -> unit (** [find_dir_logpath phys_dir] Return the logical path of directory [dir] if it has been given one. Raise [Not_found] otherwise. In particular we can check if "." has been attributed a logical path after processing all options and silently give the default one if it hasn't. We may also use this to warn if ap hysical path is met twice.*) val find_dir_logpath : string -> string list (* Used only in "canonize" *) val absolute_dir : string -> string val absolute_file_name : filename_concat:(string -> string -> string) -> string -> string option -> string rocq-9.2.0/tools/coqdep/lib/makefile.ml000066400000000000000000000066441516144147600200010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Buffer.clear s'; for i = 0 to String.length s - 1 do let c = s.[i] in if c = ' ' || c = '#' || c = ':' (* separators and comments *) || c = '%' (* pattern *) || c = '?' || c = '[' || c = ']' || c = '*' (* expansion in filenames *) || i=0 && c = '~' && (String.length s = 1 || s.[1] = '/' || 'A' <= s.[1] && s.[1] <= 'Z' || 'a' <= s.[1] && s.[1] <= 'z') (* homedir expansion *) then begin let j = ref (i-1) in while !j >= 0 && s.[!j] = '\\' do Buffer.add_char s' '\\'; decr j (* escape all preceding '\' *) done; Buffer.add_char s' '\\'; end; if c = '$' then Buffer.add_char s' '$'; Buffer.add_char s' c done; Buffer.contents s' open Format type dynlink = Opt | Byte | Both | No | Variable let option_dynlink = ref Both let set_dyndep = function | "no" -> option_dynlink := No | "opt" -> option_dynlink := Opt | "byte" -> option_dynlink := Byte | "both" -> option_dynlink := Both | "var" -> option_dynlink := Variable | o -> CErrors.user_err Pp.(str "Incorrect -dyndep option: " ++ str o) let mldep_to_make base = match !option_dynlink with | No -> [] | Byte -> [sprintf "%s.cma" base] | Opt -> [sprintf "%s.cmxs" base] | Both -> [sprintf "%s.cma" base; sprintf "%s.cmxs" base] | Variable -> [sprintf "%s%s" base "$(DYNLIB)"] let string_of_dep ~suffix = let open Dep_info.Dep in function | Require basename -> [escape basename ^ suffix] | Ml base -> mldep_to_make (escape base) | Other s -> [escape s] let string_of_dependency_list ~suffix deps = List.map (string_of_dep ~suffix) deps |> List.concat |> String.concat " " let option_noglob = ref false let option_write_vos = ref false let set_noglob glob = option_noglob := glob let set_write_vos vos = option_write_vos := vos let print_dep fmt { Dep_info.name; deps } = let ename = escape name in let glob = if !option_noglob then "" else ename^".glob " in fprintf fmt "%s.vo %s%s.v.beautified %s.required_vo: %s.v %s\n" ename glob ename ename ename (string_of_dependency_list ~suffix:".vo" deps); if !option_write_vos then fprintf fmt "%s.vos %s.vok %s.required_vos: %s.v %s\n" ename ename ename ename (string_of_dependency_list ~suffix:".vos" deps); fprintf fmt "%!" rocq-9.2.0/tools/coqdep/lib/makefile.mli000066400000000000000000000015011516144147600201350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Dep_info.t -> unit val set_dyndep : string -> unit val set_noglob : bool -> unit val set_write_vos : bool -> unit rocq-9.2.0/tools/coqdep/lib/rocqdep_main.ml000066400000000000000000000051461516144147600206610ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Loadpath.add_norec_dir_import (Loadpath.add_known lst) "." []); (* We don't setup any loadpath if the -boot is passed *) let () = match rocqenv with | Boot -> () | Env env -> let corelib = Boot.Env.(corelib env |> Path.to_string) in let user_contrib = Boot.Env.(user_contrib env |> Path.to_string) in Loadpath.add_rec_dir_import (Loadpath.add_coqlib_known lst) corelib ["Corelib"]; if Sys.file_exists user_contrib then Loadpath.add_rec_dir_no_import (Loadpath.add_coqlib_known lst) user_contrib []; let add_dir s = Loadpath.add_rec_dir_no_import (Loadpath.add_coqlib_known lst) s [] in List.iter add_dir (Envars.xdg_dirs ~warn:warn_home_dir); List.iter add_dir (Envars.coqpath()) in if args.Args.sort then sort st else compute_deps st |> List.iter (Makefile.print_dep Format.std_formatter) let main args = try coqdep args with exn -> Format.eprintf "*** Error: @[%a@]@\n%!" Pp.pp_with (CErrors.print exn); exit 1 rocq-9.2.0/tools/coqdep/lib/rocqdep_main.mli000066400000000000000000000013031516144147600210210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit rocq-9.2.0/tools/coqdoc/000077500000000000000000000000001516144147600151075ustar00rootroot00000000000000rocq-9.2.0/tools/coqdoc/alpha.ml000066400000000000000000000032211516144147600165240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'A' | '\199' -> 'C' | '\200'..'\203' -> 'E' | '\204'..'\207' -> 'I' | '\209' -> 'N' | '\210'..'\214' -> 'O' | '\217'..'\220' -> 'U' | '\221' -> 'Y' | c -> c let norm_char_utf8 c = Char.uppercase_ascii c let norm_char c = if !prefs.encoding.utf8 then norm_char_utf8 c else if !prefs.encoding.latin1 then norm_char_latin1 c else Char.uppercase_ascii c let norm_string = String.map (fun s -> norm_char s) let compare_char c1 c2 = match norm_char c1, norm_char c2 with | ('A'..'Z' as c1), ('A'..'Z' as c2) -> compare c1 c2 | 'A'..'Z', _ -> -1 | _, 'A'..'Z' -> 1 | '_', _ -> -1 | _, '_' -> 1 | c1, c2 -> compare c1 c2 let compare_string s1 s2 = let n1 = String.length s1 in let n2 = String.length s2 in let rec cmp i = if i == n1 || i == n2 then n1 - n2 else let c = compare_char s1.[i] s2.[i] in if c == 0 then cmp (succ i) else c in cmp 0 rocq-9.2.0/tools/coqdoc/alpha.mli000066400000000000000000000015631516144147600167040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* char -> int val compare_string : string -> string -> int (* Alphabetic normalization. *) val norm_char : char -> char val norm_string : string -> string rocq-9.2.0/tools/coqdoc/cmdArgs.ml000066400000000000000000000313731516144147600170300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* raise (Arg.Bad (Printf.sprintf "Not a valid filename: %s" fname)) | None -> () in let rec change_prefix = function (* Follow coqc: if in scope of -R, substitute logical name *) (* otherwise, keep only base name *) | [] -> fname | (p, name) :: rem -> try name_of_path p name dirname [fname] with Not_found -> change_prefix rem in change_prefix !prefs.paths let what_file f = FileUtil.check_if_file_exists f; if Filename.check_suffix f ".v" || Filename.check_suffix f ".g" then Vernac_file (f, coq_module f) else if Filename.check_suffix f ".tex" then Latex_file f else raise (Arg.Bad (Printf.sprintf "Expected a .v, .g, or .tex file: %s" f)) let arg_set f = Arg.Unit (fun () -> prefs := f !prefs) let arg_string f = Arg.String (fun s -> prefs := f !prefs s) let arg_file f = Arg.String (fun s -> FileUtil.check_if_file_exists s; prefs := f !prefs s) let arg_int f = Arg.Int (fun d -> prefs := f !prefs d) let current = Arg.current let argv = ref [||] (* TODO: replace these hacks with Arg.Rest_all, when rocq moves to a newer version of OCaml stdlib *) let arg_path f = Arg.String (fun s -> if Array.length !argv < !current + 3 || CString.is_prefix "-" !argv.(!current + 2) then raise (Arg.Bad ("Two arguments expected: and ")) else Arg.current := !current + 1; prefs := f !prefs (normalize_path s, !argv.(!current + 1))) let arg_url_path f = Arg.String (fun s -> if Array.length !argv < !current + 3 || CString.is_prefix "-" !argv.(!current + 2) then raise (Arg.Bad ("Two arguments expected: and ")) else current := !current + 1; f s !argv.(!current + 1)) let args_options = Arg.align [ "--html", arg_set (fun p -> { p with targetlang = HTML }), " Produce a HTML document (default)"; "--latex", arg_set (fun p -> { p with targetlang = LaTeX }), " Produce a LaTeX document"; "--texmacs",arg_set (fun p -> { p with targetlang = TeXmacs }), " Produce a TeXmacs document"; "--raw", arg_set (fun p -> { p with targetlang = Raw }), " Produce a text document"; "--dvi", arg_set (fun p -> { { p with targetlang = LaTeX } with compile_targets = Dvi :: !prefs.compile_targets }), " Output the DVI"; "--ps", arg_set (fun p -> { { p with targetlang = LaTeX } with compile_targets = Ps :: !prefs.compile_targets }), " Output the PostScript"; "--pdf", arg_set (fun p -> { { p with targetlang = LaTeX } with compile_targets = Pdf :: !prefs.compile_targets }), " Output the Pdf"; "--stdout", arg_set (fun p -> { p with out_to = StdOut }), " Write output to stdout"; "-o", arg_string (fun p f -> { { p with out_to = File (Filename.basename f) } with output_dir = Filename.dirname f }), " Write output to file "; "--output", arg_string (fun p f -> { { p with out_to = File (Filename.basename f) } with output_dir = Filename.dirname f }), " Write output to file "; "-d", arg_string (fun p f -> { p with output_dir = f }), " Output files into directory "; "--directory", arg_string (fun p f -> { p with output_dir = f }), " Output files into directory "; "-g", arg_set (fun p -> { p with gallina = true }), " Skip proofs (gallina)"; "--gallina", arg_set (fun p -> { p with gallina = true }), " Skip proofs"; "-s", arg_set (fun p -> { p with short = true }), " No titles for files (short)"; "--short", arg_set (fun p -> { p with short = true }), " No titles for files"; "-l", arg_set (fun p -> { { p with gallina = true } with light = true }), " Light mode (only defs and statements)"; "--light", arg_set (fun p -> { { p with gallina = true } with light = true }), " Light mode (only defs and statements)"; "-t", arg_string (fun p s -> { p with title = s }), " Give a title to the document"; "--title", arg_string (fun p s -> { p with title = s }), " Give a title to the document"; "--body-only", arg_set (fun p -> { p with header_trailer = false }), " Suppress LaTeX/HTML header and trailer"; "--no-preamble", arg_set (fun p -> { p with header_trailer = false }), " Suppress LaTeX/HTML header and trailer"; "--with-header", arg_file (fun p f -> { p with header_trailer = true; header_file = Some f }), " Prepend as html header"; "--with-footer", arg_file (fun p f -> { p with header_trailer = true; footer_file = Some f }), " append as html footer"; "--no-index", arg_set (fun p -> { p with index = false }), " Do not output the index"; "--binder-index", arg_set (fun p -> { p with binder_index = true }), " Include variable binders in index"; "--multi-index", arg_set (fun p -> { p with multi_index = true }), " Index split in multiple files"; "--index", arg_string (fun p s -> { p with index_name = s }), " Set index name to (default is index)"; "--toc", arg_set (fun p -> { p with toc = true }), " Output a table of contents"; "--table-of-contents", arg_set (fun p -> { p with toc = true }), " Output a table of contents"; "--vernac-file", arg_file (fun p f -> { p with files = Vernac_file (f, coq_module f) :: !prefs.files }), " consider as a .v file"; "--tex-file", arg_file (fun p f -> { p with files = Latex_file f :: !prefs.files }), " Consider as a .tex file"; "-p", Arg.String (fun f -> Output.push_in_preamble f), " Insert in LaTeX preamble"; "--preamble", Arg.String (fun f -> Output.push_in_preamble f), " Insert in LaTeX preamble"; "--files-from", arg_file (fun p f -> { p with files = List.append (List.map what_file (FileUtil.files_from_file f)) !prefs.files }), " Read file names to process in "; "--files", arg_file (fun p f -> { p with files = List.append (List.map what_file (FileUtil.files_from_file f)) !prefs.files }), " Read file names to process in "; "--glob-from", arg_file (fun p f -> { p with glob_source = GlobFile f }), " Read globalization information from "; "--no-glob", arg_set (fun p -> { p with glob_source = NoGlob }), " Don't use any globalization information (no links will be inserted at identifiers)"; "-q", arg_set (fun p -> { p with quiet = true }), " Quiet mode (default)"; "--quiet", arg_set (fun p -> { p with quiet = true }), " Quiet mode (default)"; "--verbose", arg_set (fun p -> { p with quiet = false }), " Verbose mode"; "--no-externals", arg_set (fun p -> { p with externals = false }), " No links to Rocq standard library"; "--external", arg_url_path (fun url lp -> Index.add_external_library lp url), "Β  Β Set URL for external library "; "--coqlib_url", arg_string (fun p u -> { p with coqlib_url = u }), " Set URL for Rocq standard library (default: " ^ Coq_config.wwwstdlib ^ ")"; "--coqlib", arg_string (fun p d -> { p with coqlib = Some d }), " Set the path where Rocq files are installed"; "-R", arg_path (fun p l -> { p with paths = l :: !prefs.paths }), "Β  Β Map physical dir to Rocq dir"; "-Q", arg_path (fun p l -> { p with paths = l :: !prefs.paths }), "Β  Β Map physical dir to Rocq dir"; "--latin1", arg_set (fun p -> {p with encoding = { charset = "iso-8859-1"; inputenc = "latin1"; latin1 = true; utf8 = false } }), " Set ISO-8859-1 mode"; "--utf8", arg_set (fun p -> {p with encoding = { charset = "utf-8"; inputenc = "utf8x"; latin1 = false; utf8 = true } }), " Set UTF-8 mode"; "--charset", arg_string (fun p s -> { p with encoding = { !prefs.encoding with charset = s } }), " Set HTML charset"; "--inputenc", arg_string (fun p s -> { p with encoding = { !prefs.encoding with inputenc = s } }), " Set LaTeX input encoding"; "--interpolate", arg_set (fun p -> {p with interpolate = true }), " Try to typeset identifiers in comments using definitions in the same module"; "--raw-comments", arg_set (fun p -> {p with raw_comments = true }), " Raw comments"; "--parse-comments", arg_set (fun p -> {p with parse_comments = true }), " Parse regular comments"; "--plain-comments", arg_set (fun p -> {p with plain_comments = true }), " Consider comments as non-literate text"; "--toc-depth", arg_int (fun p d -> { p with toc_depth = Some d }), " Don't include TOC entries for sections below level "; "--no-lib-name", arg_set (fun p -> { p with lib_name = "" }), " Don't display \"Library\" before library names in the toc"; "--lib-name", arg_string (fun p s -> { p with lib_name = s }), " Call top level toc entries instead of \"Library\""; "--lib-subtitles", arg_set (fun p -> { p with lib_subtitles = true }), " First line comments of the form (** * ModuleName : text *) will be interpreted as subtitles"; "--inline-notmono", arg_set (fun p -> { p with inline_notmono = true }), " Use a proportional width font for inline code (possibly with a different color)"; "--version", Arg.Unit (fun () -> banner()), " Display rocq doc version"; ] let add_input_files f = prefs := { !prefs with files = what_file f :: !prefs.files } let usage_msg = "rocq doc [options] ...\nAvailable options are:" let single_hyphen_opts = ["-html"; "-latex"; "-texmacs"; "-raw"; "-dvi"; "-ps"; "-pdf"; "-stdout"; "-output"; "-directory"; "-gallina"; "-short"; "-light"; "-title"; "-body-only"; "-no-preamble"; "-with-header"; "-with-footer"; "-no-index"; "-multi-index"; "-index"; "-toc"; "-table-of-contents"; "-vernac-file"; "-tex-file"; "-preamble"; "-files-from"; "-files"; "-glob-from"; "-no-glob"; "-quiet"; "-verbose"; "-no-externals"; "-external"; "-coqlib_url"; "-coqlib"; "-latin1"; "-utf8"; "-charset"; "-inputenc"; "-interpolate"; "-raw-comments"; "-parse-comments"; "-plain-comments"; "-toc-depth"; "-no-lib-name"; "-lib-name"; "-lib-subtitles"; "-inline-notmono"; "-version"] let deprecated_mapper_opts = [("-noindex", "--no-index"); ("-nopreamble", "--no-preamble"); ("-noexternals", "--no-externals"); ("-V", "--version")] let translate_arg s = match List.find_opt (fun m -> m = s) single_hyphen_opts with | Some _ -> Printf.sprintf "-%s" s | None -> (match List.assoc_opt s deprecated_mapper_opts with | Some b -> b | None -> s) let parse_args ~prog args = (* Deprecated options *) let new_argv = List.map translate_arg args in let new_argv = Array.of_list (prog::new_argv) in argv := new_argv; current := 0; try Arg.parse_argv new_argv args_options add_input_files usage_msg with | Arg.Bad s -> Printf.eprintf "%s" s | Arg.Help s -> Printf.printf "%s" s rocq-9.2.0/tools/coqdoc/cmdArgs.mli000066400000000000000000000014041516144147600171710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> unit rocq-9.2.0/tools/coqdoc/common.ml000066400000000000000000000072441516144147600167400ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* "" && Filename.is_relative f then if not (Sys.file_exists !prefs.output_dir) then (Printf.eprintf "No such directory: %s\n" !prefs.output_dir; exit 1) else !prefs.output_dir / f else f let open_out_file f = out_channel := try open_out (coqdoc_out f) with Sys_error s -> Printf.eprintf "%s\n" s; exit 1 let close_out_file () = close_out !out_channel (* End little helpers **************************************************************) rocq-9.2.0/tools/coqdoc/common.mli000066400000000000000000000052461516144147600171110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> string val coqdoc_out : string -> string val open_out_file : string -> unit val close_out_file : unit -> unit (* End little helpers **************************************************************) rocq-9.2.0/tools/coqdoc/coqdoc.css000066400000000000000000000137731516144147600171040ustar00rootroot00000000000000body { padding: 0px 0px; margin: 0px 0px; background-color: white } #page { display: block; padding: 0px; margin: 0px; padding-bottom: 10px; } #header { display: block; position: relative; padding: 0; margin: 0; vertical-align: middle; border-bottom-style: solid; border-width: thin } #header h1 { padding: 0; margin: 0;} /* Contents */ #main{ display: block; padding: 10px; font-family: sans-serif; font-size: 100%; line-height: 100% } #main h1 { line-height: 95% } /* allow for multi-line headers */ #main a.idref:visited {color : #416DFF; text-decoration : none; } #main a.idref:link {color : #416DFF; text-decoration : none; } #main a.idref:hover {text-decoration : none; } #main a.idref:active {text-decoration : none; } #main a.modref:visited {color : #416DFF; text-decoration : none; } #main a.modref:link {color : #416DFF; text-decoration : none; } #main a.modref:hover {text-decoration : none; } #main a.modref:active {text-decoration : none; } #main .keyword { color : #cf1d1d } #main { color: black } .section { background-color: rgb(60%,60%,100%); padding-top: 13px; padding-bottom: 13px; padding-left: 3px; margin-top: 5px; margin-bottom: 5px; font-size : 175% } h2.section { background-color: rgb(80%,80%,100%); padding-left: 3px; padding-top: 12px; padding-bottom: 10px; font-size : 130% } h3.section { background-color: rgb(90%,90%,100%); padding-left: 3px; padding-top: 7px; padding-bottom: 7px; font-size : 115% } h4.section { /* background-color: rgb(80%,80%,80%); max-width: 20em; padding-left: 5px; padding-top: 5px; padding-bottom: 5px; */ background-color: white; padding-left: 0px; padding-top: 0px; padding-bottom: 0px; font-size : 100%; font-weight : bold; text-decoration : underline; } #main .doc { margin: 0px; font-family: sans-serif; font-size: 100%; line-height: 125%; max-width: 40em; color: black; padding: 10px; background-color: #90bdff } .inlinecode { display: inline; /* font-size: 125%; */ color: #666666; font-family: monospace } .doc .inlinecode { display: inline; font-size: 120%; color: rgb(30%,30%,70%); font-family: monospace } .doc .inlinecode .id { color: rgb(30%,30%,70%); } .inlinecodenm { display: inline; color: #444444; } .doc .code { display: inline; font-size: 120%; color: rgb(30%,30%,70%); font-family: monospace } .comment { display: inline; font-family: monospace; color: rgb(50%,50%,80%); } .code { display: block; /* padding-left: 15px; */ font-size: 110%; font-family: monospace; } table.infrule { border: 0px; margin-left: 50px; margin-top: 10px; margin-bottom: 10px; } td.infrule { font-family: monospace; text-align: center; /* color: rgb(35%,35%,70%); */ padding: 0px; line-height: 100%; } tr.infrulemiddle hr { margin: 1px 0 1px 0; } .infrulenamecol { color: rgb(60%,60%,60%); font-size: 80%; padding-left: 1em; padding-bottom: 0.1em } /* Pied de page */ #footer { font-size: 65%; font-family: sans-serif; } /* Identifiers: ) */ .id { display: inline; } .id[title="constructor"] { color: rgb(60%,0%,0%); } .id[title="var"] { color: rgb(40%,0%,40%); } .id[title="variable"] { color: rgb(40%,0%,40%); } .id[title="definition"] { color: rgb(0%,40%,0%); } .id[title="abbreviation"] { color: rgb(0%,40%,0%); } .id[title="lemma"] { color: rgb(0%,40%,0%); } .id[title="instance"] { color: rgb(0%,40%,0%); } .id[title="projection"] { color: rgb(0%,40%,0%); } .id[title="method"] { color: rgb(0%,40%,0%); } .id[title="inductive"] { color: rgb(0%,0%,80%); } .id[title="record"] { color: rgb(0%,0%,80%); } .id[title="class"] { color: rgb(0%,0%,80%); } .id[title="keyword"] { color : #cf1d1d; /* color: black; */ } /* Deprecated rules using the 'type' attribute of (not xhtml valid) */ .id[type="constructor"] { color: rgb(60%,0%,0%); } .id[type="var"] { color: rgb(40%,0%,40%); } .id[type="variable"] { color: rgb(40%,0%,40%); } .id[title="binder"] { color: rgb(40%,0%,40%); } .id[type="definition"] { color: rgb(0%,40%,0%); } .id[type="abbreviation"] { color: rgb(0%,40%,0%); } .id[type="lemma"] { color: rgb(0%,40%,0%); } .id[type="instance"] { color: rgb(0%,40%,0%); } .id[type="projection"] { color: rgb(0%,40%,0%); } .id[type="method"] { color: rgb(0%,40%,0%); } .id[type="inductive"] { color: rgb(0%,0%,80%); } .id[type="record"] { color: rgb(0%,0%,80%); } .id[type="class"] { color: rgb(0%,0%,80%); } .id[type="keyword"] { color : #cf1d1d; /* color: black; */ } .inlinecode .id { color: rgb(0%,0%,0%); } /* TOC */ #toc h2 { padding: 10px; background-color: rgb(60%,60%,100%); } #toc li { padding-bottom: 8px; } /* Index */ #index { margin: 0; padding: 0; width: 100%; } #index #frontispiece { margin: 1em auto; padding: 1em; width: 60%; } .booktitle { font-size : 140% } .authors { font-size : 90%; line-height: 115%; } .moreauthors { font-size : 60% } #index #entrance { text-align: center; } #index #entrance .spacer { margin: 0 30px 0 30px; } #index #footer { position: absolute; bottom: 0; } .paragraph { height: 0.75em; } ul.doclist { margin-top: 0em; margin-bottom: 0em; } .code :target { border: 2px solid #D4D4D4; background-color: #e5eecc; } rocq-9.2.0/tools/coqdoc/coqdoc.ml000066400000000000000000000014011516144147600167050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Common.coq_module -> unit val detect_subtitle : string -> Common.coq_module -> string option rocq-9.2.0/tools/coqdoc/cpretty.mll000066400000000000000000001353761516144147600173260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* [] | (l :: ls) -> l :: (take (n-1) ls) (* count the number of spaces at the beginning of a string *) let count_spaces s = let n = String.length s in let rec count c i = if i == n then c,i else match s.[i] with | '\t' -> count (c + (8 - (c mod 8))) (i + 1) | ' ' -> count (c + 1) (i + 1) | _ -> c,i in count 0 0 let count_newlines s = let len = String.length s in let n = ref 0 in String.iteri (fun i c -> match c with (* skip "\r\n" *) | '\r' when i + 1 = len || s.[i+1] = '\n' -> incr n | '\n' -> incr n | _ -> ()) s; !n (* Whether a string starts with a newline (used on strings that might match the [nl] regexp) *) let is_nl s = String.length s = 0 || let c = s.[0] in c = '\n' || c = '\r' let remove_newline s = let n = String.length s in let rec count i = if i == n || s.[i] <> '\n' then i else count (i + 1) in let i = count 0 in i, String.sub s i (n - i) let count_dashes s = let c = ref 0 in for i = 0 to String.length s - 1 do if s.[i] = '-' then incr c done; !c let cut_head_tail_spaces s = let n = String.length s in let rec look_up i = if i == n || s.[i] <> ' ' then i else look_up (i+1) in let rec look_dn i = if i == -1 || s.[i] <> ' ' then i else look_dn (i-1) in let l = look_up 0 in let r = look_dn (n-1) in if l <= r then String.sub s l (r-l+1) else s let sec_title s = let rec count lev i = if s.[i] = '*' then count (succ lev) (succ i) else let t = String.sub s i (String.length s - i) in lev, cut_head_tail_spaces t in count 0 (String.index s '*') let strip_eol s = let eol = s.[String.length s - 1] = '\n' in (eol, if eol then String.sub s 1 (String.length s - 1) else s) let is_none x = match x with | None -> true | Some _ -> false let formatted : position option ref = ref None let brackets = ref 0 let comment_level = ref 0 let in_proof = ref None let in_env start stop = let r = ref false in let start_env () = r := true; start () in let stop_env () = if !r then stop (); r := false in (fun x -> !r), start_env, stop_env let _, start_emph, stop_emph = in_env Output.start_emph Output.stop_emph let in_quote, start_quote, stop_quote = in_env Output.start_quote Output.stop_quote let url_buffer = Buffer.create 40 let url_name_buffer = Buffer.create 40 let backtrack lexbuf = lexbuf.lex_curr_pos <- lexbuf.lex_start_pos; lexbuf.lex_curr_p <- lexbuf.lex_start_p let backtrack_past_newline lexbuf = let buf = lexeme lexbuf in let splits = Str.bounded_split_delim (Str.regexp "['\n']") buf 2 in match splits with | [] -> () | (_ :: []) -> () | (s1 :: rest :: _) -> let length_skip = 1 + String.length s1 in lexbuf.lex_curr_pos <- lexbuf.lex_start_pos + length_skip (* saving/restoring the PP state *) type state = { st_gallina : bool; st_light : bool } let state_stack = Stack.create () let save_state () = Stack.push { st_gallina = !prefs.gallina; st_light = !prefs.light } state_stack let restore_state () = let s = Stack.pop state_stack in prefs := { !prefs with gallina = s.st_gallina }; prefs := { !prefs with light = s.st_light } let begin_show () = save_state (); prefs := { { !prefs with gallina = false } with light = false } let end_show () = restore_state () let begin_details s = save_state (); prefs := { { !prefs with gallina = false } with light = false }; Output.start_details s let end_details () = Output.stop_details (); restore_state () (* Reset the globals *) let reset () = formatted := None; brackets := 0; comment_level := 0 (* erasing of Section/End *) let section_re = Str.regexp "[ \t]*Section" let end_re = Str.regexp "[ \t]*End" let is_section s = Str.string_match section_re s 0 let is_end s = Str.string_match end_re s 0 let sections_to_close = ref 0 let section_or_end s = if is_section s then begin incr sections_to_close; true end else if is_end s then begin if !sections_to_close > 0 then begin decr sections_to_close; true end else false end else true (* for item lists *) type list_compare = | Before | StartLevel of int | InLevel of int * bool (* Before : we're before any levels StartLevel : at the same column as the dash in a level InLevel : after the dash of this level, but before any deeper dashes. bool is true if this is the last level *) let find_level levels cur_indent = match levels with | [] -> Before | (l::ls) -> if cur_indent < l then Before else (* cur_indent will never be less than the head of the list *) let rec findind ls n = match ls with | [] -> InLevel (n,true) | (l :: []) -> if cur_indent = l then StartLevel n else InLevel (n,true) | (l1 :: l2 :: ls) -> if cur_indent = l1 then StartLevel n else if cur_indent < l2 then InLevel (n,false) else findind (l2 :: ls) (n+1) in findind (l::ls) 1 type is_start_list = | Rule | List of int | Neither let check_start_list str = let n_dashes = count_dashes str in let (n_spaces,_) = count_spaces str in if n_dashes >= 4 && not !prefs.plain_comments then Rule else if n_dashes = 1 && not !prefs.plain_comments then List n_spaces else Neither (* examine a string for subtitleness *) let subtitle m s = match Str.split_delim (Str.regexp ":") s with | [] -> false | (name::_) -> if (cut_head_tail_spaces name) = m then true else false (* tokens pretty-print *) let token_buffer = Buffer.create 1024 let token_re = Str.regexp "[ \t]*(\\*\\*[ \t]+printing[ \t]+\\([^ \t]+\\)" let printing_token_re = Str.regexp "[ \t]*\\(\\(%\\([^%]*\\)%\\)\\|\\(\\$[^$]*\\$\\)\\)?[ \t]*\\(#\\(\\(&#\\|[^#]\\)*\\)#\\)?" let add_printing_token toks pps = try if Str.string_match token_re toks 0 then let tok = Str.matched_group 1 toks in if Str.string_match printing_token_re pps 0 then let pp = (try Some (Str.matched_group 3 pps) with _ -> try Some (Str.matched_group 4 pps) with _ -> None), (try Some (Str.matched_group 6 pps) with _ -> None) in Output.add_printing_token tok pp with _ -> () let remove_token_re = Str.regexp "[ \t]*(\\*\\*[ \t]+remove[ \t]+printing[ \t]+\\([^ \t]+\\)[ \t]*\\*)" let remove_printing_token toks = try if Str.string_match remove_token_re toks 0 then let tok = Str.matched_group 1 toks in Output.remove_printing_token tok with _ -> () let output_indented_keyword s lexbuf = let nbsp,isp = count_spaces s in Output.indentation nbsp; let s = String.sub s isp (String.length s - isp) in Output.keyword s (lexeme_start lexbuf + isp) let only_gallina () = !prefs.gallina && !in_proof <> None let parse_comments () = !prefs.parse_comments && not (only_gallina ()) (* Advance lexbuf by n lines. Equivalent to calling [Lexing.new_line lexbuf] n times *) let new_lines n lexbuf = let lcp = lexbuf.lex_curr_p in if lcp != dummy_pos then lexbuf.lex_curr_p <- { lcp with pos_lnum = lcp.pos_lnum + n; pos_bol = lcp.pos_cnum } let print_position_p chan p = Printf.fprintf chan "%s%d, character %d" (if p.pos_fname = "" then "Line " else "File \"" ^ p.pos_fname ^ "\", line ") p.pos_lnum (p.pos_cnum - p.pos_bol) let print_position chan {lex_start_p = p} = print_position_p chan p let warn msg lexbuf = eprintf "%a, warning: %s\n" print_position lexbuf msg; flush stderr exception MismatchPreformatted of position (* let debug lexbuf msg = Printf.printf "%a %s\n" print_position lexbuf.lex_start_p msg *) } (*s Regular expressions *) let space = [' ' '\t'] let nl = "\r\n" | '\n' | '\r' let space_nl = space | nl let firstchar = ['A'-'Z' 'a'-'z' '_'] | (* superscript 1 *) '\194' '\185' | (* utf-8 latin 1 supplement *) '\195' ['\128'-'\150'] | '\195' ['\152'-'\182'] | '\195' ['\184'-'\191'] | (* utf-8 letterlike symbols *) '\206' (['\145'-'\161'] | ['\163'-'\191']) | '\207' (['\145'-'\191']) | '\226' ('\130' [ '\128'-'\137' ] (* subscripts *) | '\129' [ '\176'-'\187' ] (* superscripts *) | '\132' ['\128'-'\191'] | '\133' ['\128'-'\143']) let identchar = firstchar | ['\'' '0'-'9' '@' ] let id = firstchar identchar* let pfx_id = (id '.')* let identifier = id | pfx_id id (* This misses unicode stuff, and it adds "[" and "]". It's only an approximation of idents - used for detecting whether an underscore is part of an identifier or meant to indicate emphasis *) let nonidentchar = [^ 'A'-'Z' 'a'-'z' '_' '[' ']' '\'' '0'-'9' '@' '\"' '\'' '`'] let printing_token = [^ ' ' '\t']* let thm_token = "Theorem" | "Lemma" | "Fact" | "Remark" | "Corollary" | "Proposition" | "Property" | "Goal" let prf_token = "Next" space+ "Obligation" | "Proof" (space* "." | space+ "with" | space+ "using") let immediate_prf_token = (* Approximation of a proof term, if not in the prf_token case *) (* To be checked after prf_token *) "Proof" space* [^ '.' 'w' 'u'] let def_token = "Definition" | "Let" | "Let" space* "Fixpoint" | "Let" space* "CoFixpoint" | "Class" | "SubClass" | "Example" | "Fixpoint" | "Function" | "Boxed" | "CoFixpoint" | "Record" | "Variant" | "Structure" | "Scheme" | "Combined" space+ "Scheme" | "Inductive" | "CoInductive" | "Equations" | "Instance" | "Existing" space+ ("Instance" | "Instances" | "Class") | "Declare" space+ "Instance" | "Functional" space+ "Scheme" let decl_token = "Hypothesis" | "Hypotheses" | "Parameter" 's'? | "Axiom" 's'? | "Conjecture" | "Primitive" | "Constraint" | "Universe" | "Universes" | "Register" let gallina_ext = "Module" | "Include" space+ "Type" | "Include" | "Declare" space+ "Module" | "Transparent" | "Opaque" | "Typeclasses" space+ "Transparent" | "Typeclasses" space+ "Opaque" | "Canonical" | "Coercion" | "Identity" | "Implicit" | "Tactic" space+ "Notation" | "Section" | "Context" | "Variable" 's'? | ("Hypothesis" | "Hypotheses") | "End" let notation_kw = "Notation" | "Infix" | "Reserved" space+ "Notation" | "Reserved" space+ "Infix" | "Number" space+ "Notation" | "String" space+ "Notation" | "Enable" space+ "Notation" | "Disable" space+ "Notation" let commands = "Pwd" | "Cd" | "Drop" | "ProtectedLoop" | "Quit" | "Restart" | "Load" | "Add" | "Remove" space+ "Loadpath" | "Print" | "Inspect" | "About" | "SearchAbout" | "SearchPattern" | "SearchRewrite" | "Search" | "Locate" | "Eval" | "Reset" | "Check" | "Type" | "Section" | "Chapter" | "Variable" 's'? | ("Hypothesis" | "Hypotheses") | "End" let end_kw = immediate_prf_token | "Qed" | "Defined" | "Save" | "Admitted" | "Abort" let extraction = "Extraction" | "Recursive" space+ "Extraction" | "Extract" let gallina_kw = thm_token | def_token | decl_token | gallina_ext | commands | extraction let legacy_attr_kw = "Local" | "Global" | "Polymorphic" | "Monomorphic" | "Cumulative" | "NonCumulative" | "Private" let prog_kw = "Program" space+ (legacy_attr_kw space+)* gallina_kw | "Obligation" | "Obligations" | "Solve" let hint_kw = "Extern" | "Rewrite" | "Resolve" | "Immediate" | "Transparent" | "Opaque" | "Unfold" | "Constructors" let set_kw = "Printing" space+ ("Coercions" | "Universes" | "All") | "Implicit" space+ "Arguments" let gallina_kw_to_hide = "Implicit" space+ "Arguments" | "Arguments" | "Ltac" | "Ltac2" | "From" | "Require" | "Import" | "Export" | "Load" | "Hint" space+ hint_kw | "Create" space+ "HintDb" | "Removed" space+ "Hints" | "Open" | "Close" | "Delimit" | "Undelimit" | "Declare" space+ "Scope" | "Bind" space+ "Scope" | "Format" | "Transparent" | "Opaque" | "Strategy" | "Derive" | "Generalizable" space+ ("All" space+ "Variables" | "No" space+ "Variables" | "Variable" | "Variables") | ("Declare" space+ ("Morphism" | "Step") ) | ("Set" | "Unset") space+ set_kw | "Declare" space+ ("Left" | "Right") space+ "Step" | "Debug" space+ ("On" | "Off") | "Collection" let section = "*" | "**" | "***" | "****" let item_space = " " let begin_hide = "(*" space* "begin" space+ "hide" space* "*)" space* let end_hide = "(*" space* "end" space+ "hide" space* "*)" space* let begin_show = "(*" space* "begin" space+ "show" space* "*)" space* let end_show = "(*" space* "end" space+ "show" space* "*)" space* let begin_details = "(*" space* "begin" space+ "details" space* let end_details = "(*" space* "end" space+ "details" space* "*)" space* (* let begin_verb = "(*" space* "begin" space+ "verb" space* "*)" let end_verb = "(*" space* "end" space+ "verb" space* "*)" *) (*s Scanning Rocq, at beginning of line *) rule coq_bol = parse | space* (nl+ as s) { new_lines (String.length s) lexbuf; if not (!in_proof <> None && (!prefs.gallina || !prefs.light)) then Output.empty_line_of_code (); coq_bol lexbuf } | space* "(**" (space_nl as s) { if is_nl s then new_lines 1 lexbuf; Output.end_coq (); Output.start_doc (); let eol = doc_bol lexbuf in Output.end_doc (); Output.start_coq (); if eol then coq_bol lexbuf else coq lexbuf } | space* "Comments" (space_nl as s) { if is_nl s then new_lines 1 lexbuf; Output.end_coq (); Output.start_doc (); comments lexbuf; Output.end_doc (); Output.start_coq (); coq lexbuf } | space* begin_hide nl { new_lines 1 lexbuf; skip_hide lexbuf; coq_bol lexbuf } | space* begin_show nl { new_lines 1 lexbuf; begin_show (); coq_bol lexbuf } | space* end_show nl { new_lines 1 lexbuf; end_show (); coq_bol lexbuf } | space* begin_details (* At this point, the comment remains open, and will be closed by [details_body] *) { let s = details_body lexbuf in Output.end_coq (); begin_details s; Output.start_coq (); coq_bol lexbuf } | space* end_details nl { new_lines 1 lexbuf; Output.end_coq (); end_details (); Output.start_coq (); coq_bol lexbuf } | space* (legacy_attr_kw space+)* gallina_kw_to_hide { let s = lexeme lexbuf in if !prefs.light && section_or_end s then let eol = skip_to_dot lexbuf in if eol then (coq_bol lexbuf) else coq lexbuf else begin output_indented_keyword s lexbuf; let eol = body lexbuf in if eol then coq_bol lexbuf else coq lexbuf end } | space* (legacy_attr_kw space+)* thm_token { let s = lexeme lexbuf in output_indented_keyword s lexbuf; let eol = body lexbuf in in_proof := Some eol; if eol then coq_bol lexbuf else coq lexbuf } | space* prf_token { in_proof := Some true; let eol = if not !prefs.gallina then begin backtrack lexbuf; body_bol lexbuf end else let s = lexeme lexbuf in if s.[String.length s - 1] = '.' then false else skip_to_dot lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space* end_kw { let eol = if not (only_gallina ()) then begin backtrack lexbuf; body_bol lexbuf end else skip_to_dot lexbuf in in_proof := None; if eol then coq_bol lexbuf else coq lexbuf } | space* (legacy_attr_kw space+)* gallina_kw { in_proof := None; let s = lexeme lexbuf in output_indented_keyword s lexbuf; let eol= body lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space* (legacy_attr_kw space+)* prog_kw { in_proof := None; let s = lexeme lexbuf in output_indented_keyword s lexbuf; let eol= body lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space* (legacy_attr_kw space+)* notation_kw { let s = lexeme lexbuf in output_indented_keyword s lexbuf; let eol= start_notation_string lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space* "(**" space+ "printing" space+ printing_token space+ { let tok = lexeme lexbuf in let s = printing_token_body lexbuf in add_printing_token tok s; coq_bol lexbuf } | space* "(**" space+ "printing" space+ { warn "bad 'printing' command" lexbuf; comment_level := 1; ignore (comment lexbuf); coq_bol lexbuf } | space* "(**" space+ "remove" space+ "printing" space+ printing_token space* "*)" { remove_printing_token (lexeme lexbuf); coq_bol lexbuf } | space* "(**" space+ "remove" space+ "printing" space+ { warn "bad 'remove printing' command" lexbuf; comment_level := 1; ignore (comment lexbuf); coq_bol lexbuf } | space* "(*" { comment_level := 1; let eol = if parse_comments () then begin let s = lexeme lexbuf in let nbsp, isp = count_spaces s in Output.indentation nbsp; Output.start_comment (); comment lexbuf end else skipped_comment lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space* "#[" { let eol = begin backtrack lexbuf; body_bol lexbuf end in if eol then coq_bol lexbuf else coq lexbuf } | eof { () } | _ { let eol = if not !prefs.gallina then begin backtrack lexbuf; body_bol lexbuf end else skip_to_dot_or_brace lexbuf in if eol then coq_bol lexbuf else coq lexbuf } (*s Scanning Rocq elsewhere *) and coq = parse | nl { new_lines 1 lexbuf; if not (only_gallina ()) then Output.line_break(); coq_bol lexbuf } | "(**" (space_nl as s) { if is_nl s then new_lines 1 lexbuf; Output.end_coq (); Output.start_doc (); let eol = doc_bol lexbuf in Output.end_doc (); Output.start_coq (); if eol then coq_bol lexbuf else coq lexbuf } | "(*" { comment_level := 1; let eol = if parse_comments () then begin Output.start_comment (); comment lexbuf end else skipped_comment lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | (nl+ as s) space* "]]" { new_lines (count_newlines s) lexbuf; if is_none !formatted then begin (* Isn't this an anomaly *) let s = lexeme lexbuf in let nlsp,s = remove_newline s in let nbsp,isp = count_spaces s in Output.indentation nbsp; let loc = lexeme_start lexbuf + isp + nlsp in Output.sublexer ']' loc; Output.sublexer ']' (loc+1); coq lexbuf end } | eof { () } | (legacy_attr_kw space+)* gallina_kw_to_hide { let s = lexeme lexbuf in if !prefs.light && section_or_end s then begin let eol = skip_to_dot lexbuf in if eol then coq_bol lexbuf else coq lexbuf end else begin Output.ident s None; let eol=body lexbuf in if eol then coq_bol lexbuf else coq lexbuf end } | prf_token { let eol = if not !prefs.gallina then begin backtrack lexbuf; body lexbuf end else let s = lexeme lexbuf in let eol = if s.[String.length s - 1] = '.' then false else skip_to_dot lexbuf in eol in if eol then coq_bol lexbuf else coq lexbuf } | end_kw { let eol = if not !prefs.gallina then begin backtrack lexbuf; body lexbuf end else let eol = skip_to_dot lexbuf in if !in_proof <> Some true && eol then Output.line_break (); eol in in_proof := None; if eol then coq_bol lexbuf else coq lexbuf } | (legacy_attr_kw space+)* gallina_kw { let s = lexeme lexbuf in Output.ident s None; let eol = body lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | (legacy_attr_kw space+)* notation_kw { let s = lexeme lexbuf in Output.ident s None; let eol= start_notation_string lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | (legacy_attr_kw space+)* prog_kw { let s = lexeme lexbuf in Output.ident s None; let eol = body lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | "#[" { ignore(lexeme lexbuf); Output.char '#'; Output.char '['; let eol = body lexbuf in if eol then coq_bol lexbuf else coq lexbuf } | space+ { Output.char ' '; coq lexbuf } | eof { () } | _ { let eol = if not !prefs.gallina then begin backtrack lexbuf; body lexbuf end else skip_to_dot_or_brace lexbuf in if eol then coq_bol lexbuf else coq lexbuf} (*s Scanning documentation, at beginning of line *) and doc_bol = parse | space* section space+ ([^'\n' '\r' '*'] | '*'+ [^'\n' '\r' ')' '*'])* ('*'+ (nl as s))? { if not (is_none s) then new_lines 1 lexbuf; let eol, lex = strip_eol (lexeme lexbuf) in let lev, s = sec_title lex in if (!prefs.lib_subtitles) && (subtitle (Output.get_module false) s) then () else Output.section lev (fun () -> ignore (doc None (from_string s))); if eol then doc_bol lexbuf else doc None lexbuf } | ((space_nl* nl)? as s) (space* '-'+ as line) { let nl_count = count_newlines s in match check_start_list line with | Neither -> backtrack_past_newline lexbuf; new_lines 1 lexbuf; doc None lexbuf | List n -> new_lines nl_count lexbuf; if nl_count > 0 then Output.paragraph (); Output.item 1; doc (Some [n]) lexbuf | Rule -> new_lines nl_count lexbuf; Output.rule (); doc None lexbuf } | (space_nl* nl) as s { new_lines (count_newlines s) lexbuf; Output.paragraph (); doc_bol lexbuf } | "<<" space* nl { new_lines 1 lexbuf; Output.start_verbatim false; verbatim_block lexbuf; doc_bol lexbuf } | "<<" { Output.start_verbatim true; verbatim_inline lexbuf; doc None lexbuf } | eof { true } | '_' { if !prefs.plain_comments then Output.char '_' else start_emph (); doc None lexbuf } | "" { doc None lexbuf } (*s Scanning lists - using whitespace *) and doc_list_bol indents = parse | space* '-' { let (n_spaces,_) = count_spaces (lexeme lexbuf) in match find_level indents n_spaces with | Before -> backtrack lexbuf; doc_bol lexbuf | StartLevel n -> Output.item n; doc (Some (take n indents)) lexbuf | InLevel (n,true) -> let items = List.length indents in Output.item (items+1); doc (Some (List.append indents [n_spaces])) lexbuf | InLevel (_,false) -> backtrack lexbuf; doc_bol lexbuf } | "<<" space* nl { new_lines 1 lexbuf; Output.start_verbatim false; verbatim_block lexbuf; doc_list_bol indents lexbuf } | "<<" space* { Output.start_verbatim true; verbatim_inline lexbuf; doc (Some indents) lexbuf } | "[[" nl { new_lines 1 lexbuf; formatted := Some lexbuf.lex_start_p; Output.start_inline_coq_block (); ignore(body_bol lexbuf); Output.end_inline_coq_block (); formatted := None; doc_list_bol indents lexbuf } | "[[[" nl { new_lines 1 lexbuf; inf_rules (Some indents) lexbuf } | space* nl space* '-' { (* Like in the doc_bol production, these two productions exist only to deal properly with whitespace *) new_lines 1 lexbuf; Output.paragraph (); backtrack_past_newline lexbuf; doc_list_bol indents lexbuf } | space* nl space* _ { new_lines 1 lexbuf; let buf' = lexeme lexbuf in let buf = let bufs = Str.split_delim (Str.regexp "['\n']") buf' in match bufs with | (_ :: s :: []) -> s | (_ :: _ :: s :: _) -> s | _ -> eprintf "Internal error bad_split2 - please report\n"; exit 1 in let (n_spaces,_) = count_spaces buf in match find_level indents n_spaces with | StartLevel 1 | Before -> (* Here we were at the beginning of a line, and it was blank. The next line started before any list items. So: insert a paragraph for the empty line, rewind to whatever's just after the newline, then toss over to doc_bol for whatever comes next. *) Output.stop_item (); Output.paragraph (); backtrack_past_newline lexbuf; doc_bol lexbuf | StartLevel _ | InLevel _ -> Output.paragraph (); backtrack_past_newline lexbuf; doc_list_bol indents lexbuf } | space* _ { let (n_spaces,_) = count_spaces (lexeme lexbuf) in match find_level indents n_spaces with | Before -> Output.stop_item (); backtrack lexbuf; doc_bol lexbuf | StartLevel n -> Output.reach_item_level (n-1); backtrack lexbuf; doc (Some (take (n-1) indents)) lexbuf | InLevel (n,_) -> Output.reach_item_level n; backtrack lexbuf; doc (Some (take n indents)) lexbuf } (*s Scanning documentation elsewhere *) and doc indents = parse | nl { new_lines 1 lexbuf; Output.char '\n'; match indents with | Some ls -> doc_list_bol ls lexbuf | None -> doc_bol lexbuf } | "[[" nl { new_lines 1 lexbuf; if !prefs.plain_comments then (Output.char '['; Output.char '['; doc indents lexbuf) else (formatted := Some lexbuf.lex_start_p; Output.start_inline_coq_block (); let eol = body_bol lexbuf in Output.end_inline_coq_block (); formatted := None; if eol then match indents with | Some ls -> doc_list_bol ls lexbuf | None -> doc_bol lexbuf else doc indents lexbuf)} | "[[[" nl { new_lines 1 lexbuf; inf_rules indents lexbuf } | "[]" { Output.proofbox (); doc indents lexbuf } | "{{" { url lexbuf; doc indents lexbuf } | "[" { if !prefs.plain_comments then Output.char '[' else (brackets := 1; Output.start_inline_coq (); escaped_coq lexbuf; Output.end_inline_coq ()); doc indents lexbuf } | "(*" { backtrack lexbuf ; let bol_parse = match indents with | Some is -> doc_list_bol is | None -> doc_bol in let eol = if !prefs.parse_comments then comment lexbuf else skipped_comment lexbuf in if eol then bol_parse lexbuf else doc indents lexbuf } | '*'* "*)" (space_nl* as s) "(**" { let nl_count = count_newlines s in new_lines nl_count lexbuf; (match indents with | Some _ -> Output.stop_item () | None -> ()); (* this says - if there is a blank line between the two comments, insert one in the output too *) if nl_count > 1 then Output.paragraph (); doc_bol lexbuf } | '*'* "*)" space* nl { new_lines 1 lexbuf; Output.char '\n'; true } | '*'* "*)" { false } | "$" { if !prefs.plain_comments then Output.char '$' else (Output.start_latex_math (); escaped_math_latex lexbuf); doc indents lexbuf } | "$$" { if !prefs.plain_comments then Output.char '$'; Output.char '$'; doc indents lexbuf } | "%" { if !prefs.plain_comments then Output.char '%' else escaped_latex lexbuf; doc indents lexbuf } | "%%" { if !prefs.plain_comments then Output.char '%'; Output.char '%'; doc indents lexbuf } | "#" { if !prefs.plain_comments then Output.char '#' else escaped_html lexbuf; doc indents lexbuf } | "##" { if !prefs.plain_comments then Output.char '#'; Output.char '#'; doc indents lexbuf } | nonidentchar '_' nonidentchar { List.iter (fun x -> Output.char (lexeme_char lexbuf x)) [0;1;2]; doc indents lexbuf} | nonidentchar '_' { Output.char (lexeme_char lexbuf 0); if !prefs.plain_comments then Output.char '_' else start_emph () ; doc indents lexbuf } | '_' nonidentchar { if !prefs.plain_comments then Output.char '_' else stop_emph () ; Output.char (lexeme_char lexbuf 1); doc indents lexbuf } | "<<" space* { Output.start_verbatim true; verbatim_inline lexbuf; doc indents lexbuf } | '"' { if !prefs.plain_comments then Output.char '"' else if in_quote () then stop_quote () else start_quote (); doc indents lexbuf } | eof { false } | _ { Output.char (lexeme_char lexbuf 0); doc indents lexbuf } (*s Various escapings *) and escaped_math_latex = parse | "$" { Output.stop_latex_math () } | eof { Output.stop_latex_math () } | "*)" { Output.stop_latex_math (); backtrack lexbuf } | _ { Output.latex_char (lexeme_char lexbuf 0); escaped_math_latex lexbuf } and escaped_latex = parse | "%" { () } | eof { () } | "*)" { backtrack lexbuf } | _ { Output.latex_char (lexeme_char lexbuf 0); escaped_latex lexbuf } and escaped_html = parse | "#" { () } | "&#" { Output.html_char '&'; Output.html_char '#'; escaped_html lexbuf } | "##" { Output.html_char '#'; escaped_html lexbuf } | eof { () } | "*)" { backtrack lexbuf } | _ { Output.html_char (lexeme_char lexbuf 0); escaped_html lexbuf } and verbatim_block = parse | nl ">>" space* nl { new_lines 2 lexbuf; Output.verbatim_char false '\n'; Output.stop_verbatim false } | nl ">>" { new_lines 1 lexbuf; warn "missing newline after \">>\" block" lexbuf; Output.verbatim_char false '\n'; Output.stop_verbatim false } | eof { warn "unterminated \">>\" block" lexbuf; Output.stop_verbatim false } | nl { new_lines 1 lexbuf; Output.verbatim_char false (lexeme_char lexbuf 0); verbatim_block lexbuf } | _ { Output.verbatim_char false (lexeme_char lexbuf 0); verbatim_block lexbuf } and verbatim_inline = parse | nl { new_lines 1 lexbuf; warn "unterminated inline \">>\"" lexbuf; Output.char '\n'; Output.stop_verbatim true } | ">>" { Output.stop_verbatim true } | eof { warn "unterminated inline \">>\"" lexbuf; Output.stop_verbatim true } | _ { Output.verbatim_char true (lexeme_char lexbuf 0); verbatim_inline lexbuf } and url = parse | "}}" { Output.url (Buffer.contents url_buffer) None; Buffer.clear url_buffer } | "}" { url_name lexbuf } | _ { Buffer.add_char url_buffer (lexeme_char lexbuf 0); url lexbuf } and url_name = parse | "}" { Output.url (Buffer.contents url_buffer) (Some (Buffer.contents url_name_buffer)); Buffer.clear url_buffer; Buffer.clear url_name_buffer } | _ { Buffer.add_char url_name_buffer (lexeme_char lexbuf 0); url_name lexbuf } (*s Rocq, inside quotations *) and escaped_coq = parse | "]" { decr brackets; if !brackets > 0 then (Output.sublexer_in_doc ']'; escaped_coq lexbuf) else Tokens.flush_sublexer () } | "[" { incr brackets; Output.sublexer_in_doc '['; escaped_coq lexbuf } | "(*" { Tokens.flush_sublexer (); comment_level := 1; ignore (if !prefs.parse_comments then comment lexbuf else skipped_comment lexbuf); escaped_coq lexbuf } | "*)" { (* likely to be a syntax error *) warn "unterminated \"]\"" lexbuf; backtrack lexbuf } | eof { Tokens.flush_sublexer () } | identifier { Tokens.flush_sublexer(); Output.ident (lexeme lexbuf) None; escaped_coq lexbuf } | space_nl* { let str = lexeme lexbuf in Tokens.flush_sublexer(); (if !prefs.inline_notmono then () else Output.end_inline_coq ()); String.iter Output.char str; (if !prefs.inline_notmono then () else Output.start_inline_coq ()); escaped_coq lexbuf } | _ { Output.sublexer_in_doc (lexeme_char lexbuf 0); escaped_coq lexbuf } (*s Rocq "Comments" command. *) and comments = parse | space_nl+ { Output.char ' '; comments lexbuf } | '"' [^ '"']* '"' { let s = lexeme lexbuf in let s = String.sub s 1 (String.length s - 2) in ignore (doc None (from_string s)); comments lexbuf } | ([^ '.' '"'] | '.' [^ ' ' '\t' '\n'])+ { escaped_coq (from_string (lexeme lexbuf)); comments lexbuf } | "." (space_nl | eof) { () } | eof { () } | _ { Output.char (lexeme_char lexbuf 0); comments lexbuf } and skipped_comment = parse | "(*" { incr comment_level; skipped_comment lexbuf } | "*)" space* nl { new_lines 1 lexbuf; decr comment_level; if !comment_level > 0 then skipped_comment lexbuf else true } | "*)" { decr comment_level; if !comment_level > 0 then skipped_comment lexbuf else false } | eof { false } | _ { skipped_comment lexbuf } and comment = parse | "(*" { incr comment_level; Output.start_comment (); comment lexbuf } | "*)" space* nl { new_lines 1 lexbuf; Output.end_comment (); Output.line_break (); decr comment_level; if !comment_level > 0 then comment lexbuf else true } | "*)" { Output.end_comment (); decr comment_level; if !comment_level > 0 then comment lexbuf else false } | "[" { if !prefs.plain_comments then Output.char '[' else (brackets := 1; Output.start_inline_coq (); escaped_coq lexbuf; Output.end_inline_coq ()); comment lexbuf } | "[[" nl { new_lines 1 lexbuf; if !prefs.plain_comments then (Output.char '['; Output.char '[') else (formatted := Some lexbuf.lex_start_p; Output.start_inline_coq_block (); let _ = body_bol lexbuf in Output.end_inline_coq_block (); formatted := None); comment lexbuf } | "$" { if !prefs.plain_comments then Output.char '$' else (Output.start_latex_math (); escaped_math_latex lexbuf); comment lexbuf } | "$$" { if !prefs.plain_comments then Output.char '$'; Output.char '$'; comment lexbuf } | "%" { if !prefs.plain_comments then Output.char '%' else escaped_latex lexbuf; comment lexbuf } | "%%" { if !prefs.plain_comments then Output.char '%'; Output.char '%'; comment lexbuf } | "#" { if !prefs.plain_comments then Output.char '#' else escaped_html lexbuf; comment lexbuf } | "##" { if !prefs.plain_comments then Output.char '#'; Output.char '#'; comment lexbuf } | eof { false } | space+ { Output.indentation (fst (count_spaces (lexeme lexbuf))); comment lexbuf } | nl { new_lines 1 lexbuf; Output.line_break (); comment lexbuf } | _ { Output.char (lexeme_char lexbuf 0); comment lexbuf } and skip_to_dot = parse | '.' space* nl { new_lines 1 lexbuf; true } | eof | '.' space+ { false } | "(*" { comment_level := 1; ignore (skipped_comment lexbuf); skip_to_dot lexbuf } | _ { skip_to_dot lexbuf } and skip_to_dot_or_brace = parse | '.' space* nl { new_lines 1 lexbuf; true } | eof | '.' space+ { false } | "(*" { comment_level := 1; ignore (skipped_comment lexbuf); skip_to_dot_or_brace lexbuf } | "}" space* nl { new_lines 1 lexbuf; true } | "}" { false } | space* { skip_to_dot_or_brace lexbuf } | _ { skip_to_dot lexbuf } and body_bol = parse | space+ { Output.indentation (fst (count_spaces (lexeme lexbuf))); body lexbuf } | "" { Output.indentation 0; body lexbuf } and body = parse | nl { Tokens.flush_sublexer(); Output.line_break(); new_lines 1 lexbuf; body_bol lexbuf} | (nl+ as s) space* "]]" space* nl { new_lines (count_newlines s + 1) lexbuf; Tokens.flush_sublexer(); if is_none !formatted then begin let s = lexeme lexbuf in let nlsp,s = remove_newline s in let _,isp = count_spaces s in let loc = lexeme_start lexbuf + nlsp + isp in Output.sublexer ']' loc; Output.sublexer ']' (loc+1); Tokens.flush_sublexer(); body lexbuf end else begin Output.paragraph (); true end } | "]]" space* nl { Tokens.flush_sublexer(); new_lines 1 lexbuf; if is_none !formatted then begin let loc = lexeme_start lexbuf in Output.sublexer ']' loc; Output.sublexer ']' (loc+1); Tokens.flush_sublexer(); Output.line_break(); body lexbuf end else begin Output.paragraph (); true end } | eof { Tokens.flush_sublexer(); match !formatted with | None -> false | Some p -> raise (MismatchPreformatted p) } | '.' space* (nl as s | eof) { if not (is_none s) then new_line lexbuf; Tokens.flush_sublexer(); Output.char '.'; Output.line_break(); if is_none !formatted then true else body_bol lexbuf } | '.' space* nl "]]" space* nl { new_lines 2 lexbuf; Tokens.flush_sublexer(); Output.char '.'; if is_none !formatted then begin eprintf "Error: stray ]] at %d\n" (lexeme_start lexbuf); flush stderr; exit 1 end else begin Output.paragraph (); true end } | '.' space+ { Tokens.flush_sublexer(); Output.char '.'; Output.char ' '; if is_none !formatted then false else body lexbuf } | "(**" (space_nl as s) { if is_nl s then new_line lexbuf; Tokens.flush_sublexer(); Output.end_coq (); Output.start_doc (); let eol = doc_bol lexbuf in Output.end_doc (); Output.start_coq (); if eol then body_bol lexbuf else body lexbuf } | "(*" { Tokens.flush_sublexer(); comment_level := 1; let eol = if parse_comments () then begin Output.start_comment (); comment lexbuf end else begin let eol = skipped_comment lexbuf in if eol then Output.line_break(); eol end in if eol then body_bol lexbuf else body lexbuf } | "where" { Tokens.flush_sublexer(); Output.ident (lexeme lexbuf) None; start_notation_string lexbuf } | identifier { Tokens.flush_sublexer(); Output.ident (lexeme lexbuf) (Some (lexeme_start lexbuf)); body lexbuf } | ".." { Tokens.flush_sublexer(); Output.char '.'; Output.char '.'; body lexbuf } | '"' { Tokens.flush_sublexer(); Output.char '"'; string lexbuf; body lexbuf } | space { Tokens.flush_sublexer(); Output.char (lexeme_char lexbuf 0); body lexbuf } | _ { let c = lexeme_char lexbuf 0 in Output.sublexer c (lexeme_start lexbuf); body lexbuf } and start_notation_string = parse | space { Tokens.flush_sublexer(); Output.char (lexeme_char lexbuf 0); start_notation_string lexbuf } | '"' (* a true notation *) { Output.sublexer '"' (lexeme_start lexbuf); notation_string lexbuf; body lexbuf } | _ (* an abbreviation *) { backtrack lexbuf; body lexbuf } and notation_string = parse | "\"\"" { Output.char '"'; Output.char '"'; (* Unlikely! *) notation_string lexbuf } | '"' { Tokens.flush_sublexer(); Output.char '"' } | _ { let c = lexeme_char lexbuf 0 in Output.sublexer c (lexeme_start lexbuf); notation_string lexbuf } and string = parse | "\"\"" { Output.char '"'; Output.char '"'; string lexbuf } | '"' { Output.char '"' } | _ { let c = lexeme_char lexbuf 0 in Output.char c; string lexbuf } and skip_hide = parse | eof | end_hide nl { new_lines 1 lexbuf; () } | _ { skip_hide lexbuf } (*s Reading token pretty-print *) and printing_token_body = parse | "*)" (nl as s)? | eof { if not (is_none s) then new_lines 1 lexbuf; let s = Buffer.contents token_buffer in Buffer.clear token_buffer; s } | (nl | _) as s { if is_nl s then new_lines 1 lexbuf; Buffer.add_string token_buffer (lexeme lexbuf); printing_token_body lexbuf } and details_body = parse | "*)" space* (nl as s)? | eof { if not (is_none s) then new_lines 1 lexbuf; None } | ":" space* { details_body_rec lexbuf } and details_body_rec = parse | "*)" space* (nl as s)? | eof { if not (is_none s) then new_lines 1 lexbuf; let s = Buffer.contents token_buffer in Buffer.clear token_buffer; Some s } | _ { Buffer.add_string token_buffer (lexeme lexbuf); details_body_rec lexbuf } (*s These handle inference rules, parsing the body segments of things enclosed in [[[ ]]] brackets *) and inf_rules indents = parse | space* nl (* blank line, before or between definitions *) { new_lines 1 lexbuf; inf_rules indents lexbuf } | "]]]" nl (* end of the inference rules block *) { new_lines 1 lexbuf; match indents with | Some ls -> doc_list_bol ls lexbuf | None -> doc_bol lexbuf } | _ { backtrack lexbuf; (* anything else must be the first line in a rule *) inf_rules_assumptions indents [] lexbuf} (* The inference rule parsing just collects the inference rule and then calls the output function once, instead of doing things incrementally like the rest of the lexer. If only there were a real parsing phase... *) and inf_rules_assumptions indents assumptions = parse | space* "---" '-'* [^ '\n']* nl (* hit the horizontal line *) { new_lines 1 lexbuf; let line = lexeme lexbuf in let (spaces,_) = count_spaces line in let dashes_and_name = cut_head_tail_spaces (String.sub line 0 (String.length line - 1)) in let ldn = String.length dashes_and_name in let (dashes,name) = try (let i = String.index dashes_and_name ' ' in let d = String.sub dashes_and_name 0 i in let n = cut_head_tail_spaces (String.sub dashes_and_name (i+1) (ldn-i-1)) in (d, Some n)) with _ -> (dashes_and_name, None) in inf_rules_conclusion indents (List.rev assumptions) (spaces, dashes, name) [] lexbuf } | [^ '\n']* nl (* if it's not the horizontal line, it's an assumption *) { new_lines 1 lexbuf; let line = lexeme lexbuf in let (spaces,_) = count_spaces line in let assumption = cut_head_tail_spaces (String.sub line 0 (String.length line - 1)) in inf_rules_assumptions indents ((spaces,assumption)::assumptions) lexbuf } (*s The conclusion is required to come immediately after the horizontal bar. It is allowed to contain multiple lines of text, like the assumptions. The conclusion ends when we spot a blank line or a ']]]'. *) and inf_rules_conclusion indents assumptions middle conclusions = parse | space* nl | space* "]]]" nl (* end of conclusions. *) { new_lines 2 lexbuf; backtrack lexbuf; Output.inf_rule assumptions middle (List.rev conclusions); inf_rules indents lexbuf } | space* [^ '\n']+ nl (* this is a line in the conclusion *) { new_lines 1 lexbuf; let line = lexeme lexbuf in let (spaces,_) = count_spaces line in let conc = cut_head_tail_spaces (String.sub line 0 (String.length line - 1)) in inf_rules_conclusion indents assumptions middle ((spaces,conc) :: conclusions) lexbuf } (*s A small scanner to support the chapter subtitle feature *) and st_start m = parse | "(*" "*"+ space+ "*" space+ { st_modname m lexbuf } | _ { None } and st_modname m = parse | identifier space* ":" space* { if subtitle m (lexeme lexbuf) then st_subtitle lexbuf else None } | _ { None } and st_subtitle = parse | [^ '\n']* '\n' { let st = lexeme lexbuf in let i = try Str.search_forward (Str.regexp "\\**)") st 0 with Not_found -> (eprintf "unterminated comment at beginning of file\n"; exit 1) in Some (cut_head_tail_spaces (String.sub st 0 i)) } | _ { None } (*s Applying the scanners to files *) { (* coq_bol with error handling *) let coq_bol' f lb = try coq_bol lb with | MismatchPreformatted p -> Printf.eprintf "%a: mismatched \"[[\"\n" print_position_p p; exit 1 let coq_file f m = reset (); let c = open_in f in let lb = from_channel c in let lb = { lb with lex_curr_p = { lb.lex_curr_p with pos_fname = f }; lex_start_p = { lb.lex_start_p with pos_fname = f } } in (Index.current_library := m; Output.initialize (); Output.start_module (); Output.start_coq (); coq_bol' f lb; Output.end_coq (); close_in c) let detect_subtitle f m = let c = open_in f in let lb = from_channel c in let sub = st_start m lb in close_in c; sub } rocq-9.2.0/tools/coqdoc/dune000066400000000000000000000010471516144147600157670ustar00rootroot00000000000000(install (section lib) (package rocq-runtime) (files (coqdoc.css as tools/coqdoc/coqdoc.css) (coqdoc.sty as tools/coqdoc/coqdoc.sty))) ; File needs to be here too. (install (section share_root) (package rocq-runtime) (files (coqdoc.sty as texmf/tex/latex/misc/coqdoc.sty))) (library (name coqdoclib) (modules :standard \ coqdoc) (libraries str rocq-runtime.boot rocq-runtime.config rocq-runtime.clib)) (executable (name coqdoc) (public_name coqdoc) (package coq-core) (modules coqdoc) (libraries coqdoclib)) (ocamllex cpretty) rocq-9.2.0/tools/coqdoc/fileUtil.ml000066400000000000000000000035141516144147600172210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* close_out cout; close_in cin with Sys_error e -> Printf.eprintf "%s\n" e; exit 1 let check_if_file_exists f = if not (Sys.file_exists f) then begin Printf.eprintf "coqdoc: %s: no such file\n" f; exit 1 end (* [files_from_file f] returns the list of file names contained in the file named [f]. These file names must be separated by spaces, tabulations or newlines. *) let files_from_file f = let files_from_channel ch = let buf = Buffer.create 80 in let l = ref [] in try while true do match input_char ch with | ' ' | '\t' | '\n' -> if Buffer.length buf > 0 then l := Buffer.contents buf :: !l; Buffer.clear buf | c -> Buffer.add_char buf c done; [] with End_of_file -> List.rev !l in try check_if_file_exists f; let ch = open_in f in let l = files_from_channel ch in close_in ch; l with Sys_error s -> Printf.eprintf "coqdoc: cannot read from file %s (%s)\n" f s; exit 1 rocq-9.2.0/tools/coqdoc/fileUtil.mli000066400000000000000000000020031516144147600173620ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> unit (** [files_from_file f] returns the list of file names contained in the file named [f]. These file names must be separated by spaces, tabulations or newlines. *) val files_from_file : string -> string list (** Version of [Sys.file_exists] but will exit on error *) val check_if_file_exists : string -> unit rocq-9.2.0/tools/coqdoc/glob_file.ml000066400000000000000000000072051516144147600173670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Definition | "prf" | "thm" -> Lemma | "ind" | "variant" | "coind" -> Inductive | "constr" -> Constructor | "indrec" | "rec" | "corec" -> Record | "proj" -> Projection | "class" -> Class | "meth" -> Method | "inst" -> Instance | "var" -> Variable | "defax" | "prfax" | "ax" -> Axiom | "abbrev" | "syndef" -> Abbreviation | "not" -> Notation | "lib" -> Library | "mod" | "modtype" -> Module | "tac" -> TacticDefinition | "sec" -> Section | "binder" -> Binder | s -> invalid_arg ("type_of_string:" ^ s) let ill_formed_glob_file f = eprintf "Warning: ill-formed file %s (links will not be available)\n" f let outdated_glob_file f = eprintf "Warning: %s not consistent with corresponding .v file (links will not be \ available)\n" f let correct_file vfile f c = let s = input_line c in if String.length s < 7 || String.sub s 0 7 <> "DIGEST " then ( ill_formed_glob_file f; false ) else let s = String.sub s 7 (String.length s - 7) in match (vfile, s) with | None, "NO" -> true | Some _, "NO" -> ill_formed_glob_file f; false | None, _ -> ill_formed_glob_file f; false | Some vfile, s -> s = Digest.to_hex (Digest.file vfile) || (outdated_glob_file f; false) let read_glob vfile f = let c = open_in f in if correct_file vfile f c then let cur_mod = ref "" in try while true do let s = input_line c in let n = String.length s in if n > 0 then match s.[0] with | 'F' -> cur_mod := String.sub s 1 (n - 1); current_library := !cur_mod | 'R' -> ( try Scanf.sscanf s "R%d:%d %s %s %s %s" (fun loc1 loc2 lib_dp sp id ty -> for loc = loc1 to loc2 do add_ref !cur_mod loc lib_dp sp id (type_of_string ty); (* Also add an entry for each module mentioned in [lib_dp], * to use in interpolation. *) ignore (List.fold_right (fun thisPiece priorPieces -> let newPieces = match priorPieces with | "" -> thisPiece | _ -> thisPiece ^ "." ^ priorPieces in add_ref !cur_mod loc "" "" newPieces Library; newPieces) (Str.split (Str.regexp_string ".") lib_dp) "") done) with _ -> () ) | _ -> ( try Scanf.sscanf s "%s %d:%d %s %s" (fun ty loc1 loc2 sp id -> add_def loc1 loc2 (type_of_string ty) sp id) with Scanf.Scan_failure _ -> () ) done; assert false with End_of_file -> close_in c rocq-9.2.0/tools/coqdoc/glob_file.mli000066400000000000000000000015041516144147600175340ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> unit rocq-9.2.0/tools/coqdoc/index.ml000066400000000000000000000207511516144147600165550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* "<>" then if id <> "<>" then sp ^ "." ^ id else sp else if id <> "<>" then id else "" let hashtbl_append_def t k v = try match Hashtbl.find t k with | Def l -> Hashtbl.replace t k (Def (l @ [v])) | Ref _ -> Hashtbl.add t k (Def [v]) with Not_found -> Hashtbl.add t k (Def [v]) let add_def loc1 loc2 ty sp id = let fullid = full_ident sp id in let def = (fullid, ty) in for loc = loc1 to loc2 do hashtbl_append_def reftable (!current_library, loc) def done; Hashtbl.add deftable !current_library (fullid, ty); Hashtbl.add byidtable id (!current_library, fullid, ty) let add_ref m loc m' sp id ty = let fullid = full_ident sp id in if Hashtbl.mem reftable (m, loc) then () else Hashtbl.add reftable (m, loc) (Ref (m', fullid, ty)); let idx = if id = "<>" then m' else id in if Hashtbl.mem byidtable idx then () else Hashtbl.add byidtable idx (m', fullid, ty) let find m l = Hashtbl.find reftable (m, l) let find_string s = let (m,s,t) = Hashtbl.find byidtable s in Ref (m,s,t) (* Rocq modules *) let split_sp s = try let i = String.rindex s '.' in String.sub s 0 i, String.sub s (i + 1) (String.length s - i - 1) with Not_found -> "", s let modules = Hashtbl.create 97 let local_modules = Hashtbl.create 97 let add_module m = let _,id = split_sp m in Hashtbl.add modules id m; Hashtbl.add local_modules m () type module_kind = Local | External of string | Unknown let external_libraries = ref [] let add_external_library logicalpath url = external_libraries := (logicalpath,url) :: !external_libraries let find_external_library logicalpath = let rec aux = function | [] -> raise Not_found | (l,u)::rest -> if String.length logicalpath > String.length l && String.sub logicalpath 0 (String.length l + 1) = l ^"." then u else aux rest in aux !external_libraries let init_coqlib_library () = add_external_library "Corelib" !prefs.coqlib_url let find_module m = if Hashtbl.mem local_modules m then Local else try External (find_external_library m ^ "/" ^ m) with Not_found -> Unknown (* Building indexes *) type 'a index = { idx_name : string; idx_entries : (char * (string * 'a) list) list; idx_size : int } let map f i = { i with idx_entries = List.map (fun (c,l) -> (c, List.map (fun (s,x) -> (s,f s x)) l)) i.idx_entries } let compare_entries (s1,_) (s2,_) = Alpha.compare_string s1 s2 let sort_entries el = let t = Hashtbl.create 97 in List.iter (fun c -> Hashtbl.add t c []) ['A'; 'B'; 'C'; 'D'; 'E'; 'F'; 'G'; 'H'; 'I'; 'J'; 'K'; 'L'; 'M'; 'N'; 'O'; 'P'; 'Q'; 'R'; 'S'; 'T'; 'U'; 'V'; 'W'; 'X'; 'Y'; 'Z'; '_'; '*']; List.iter (fun ((s,_) as e) -> let c = Alpha.norm_char s.[0] in let c,l = try c,Hashtbl.find t c with Not_found -> '*',Hashtbl.find t '*' in Hashtbl.replace t c (e :: l)) el; let res = ref [] in Hashtbl.iter (fun c l -> res := (c, List.sort compare_entries l) :: !res) t; List.sort (fun (c1,_) (c2,_) -> Alpha.compare_char c1 c2) !res let display_letter c = if c = '*' then "other" else String.make 1 c let type_name = function | Library -> let ln = !prefs.lib_name in if ln <> "" then String.lowercase_ascii ln else "library" | Module -> "module" | Definition -> "definition" | Inductive -> "inductive" | Constructor -> "constructor" | Lemma -> "lemma" | Record -> "record" | Projection -> "projection" | Instance -> "instance" | Class -> "class" | Method -> "method" | Variable -> "variable" | Axiom -> "axiom" | TacticDefinition -> "tactic" | Abbreviation -> "abbreviation" | Notation -> "notation" | Section -> "section" | Binder -> "binder" let prepare_entry s = function | Notation -> (* We decode the encoding done in Dumpglob.cook_notation of coqtop *) (* Encoded notations have the form section:entry:sc:x_'++'_x *) (* where: *) (* - the section, if any, ends with a "." *) (* - the scope can be empty *) (* - tokens are separated with "_" *) (* - non-terminal symbols are conventionally represented by "x" *) (* - terminals are enclosed within simple quotes *) (* - existing simple quotes (that necessarily are parts of *) (* terminals) are doubled *) (* (as a consequence, when a terminal contains "_" or "x", these *) (* necessarily appear enclosed within non-doubled simple quotes) *) (* - non-printable characters < 32 are left encoded so that they *) (* are human-readable in index files *) (* Example: "x ' %x _% y %'x %'_' z" is encoded as *) (* "x_''''_'%x'_'_%'_x_'%''x'_'%''_'''_x" *) let err () = eprintf "Invalid notation in globalization file\n"; exit 1 in let h = try String.index_from s 0 ':' with _ -> err () in let i = try String.index_from s (h+1) ':' with _ -> err () in let m = try String.index_from s (i+1) ':' with _ -> err () in let entry = String.sub s (h+1) (i-h-1) in let sc = String.sub s (i+1) (m-i-1) in let ntn = Bytes.make (String.length s - m) ' ' in let k = ref 0 in let j = ref (m+1) in let quoted = ref false in let l = String.length s - 1 in while !j <= l do if not !quoted then begin (match s.[!j] with | '_' -> Bytes.set ntn !k ' '; incr k | 'x' -> Bytes.set ntn !k '_'; incr k | '\'' -> quoted := true | _ -> assert false) end else if s.[!j] = '\'' then if (!j = l || s.[!j+1] = '_') then quoted := false else (incr j; Bytes.set ntn !k s.[!j]; incr k) else begin Bytes.set ntn !k s.[!j]; incr k end; incr j done; let ntn = Bytes.sub_string ntn 0 !k in let ntn = if sc = "" then ntn else ntn ^ " (" ^ sc ^ ")" in if entry = "" then ntn else entry ^ ":" ^ ntn | _ -> s let include_entry = function | Binder -> !prefs.binder_index | _ -> true let all_entries () = let gl = ref [] in let add_g s m t = gl := (s,(m,t)) :: !gl in let bt = Hashtbl.create 11 in let add_bt t s m = let l = try Hashtbl.find bt t with Not_found -> [] in Hashtbl.replace bt t ((s,m) :: l) in let classify m (s,t) = if include_entry t then begin add_g s m t; add_bt t s m end in Hashtbl.iter classify deftable; Hashtbl.iter (fun id m -> add_g id m Library; add_bt Library id m) modules; { idx_name = "global"; idx_entries = sort_entries !gl; idx_size = List.length !gl }, Hashtbl.fold (fun t e l -> (t, { idx_name = type_name t; idx_entries = sort_entries e; idx_size = List.length e }) :: l) bt [] rocq-9.2.0/tools/coqdoc/index.mli000066400000000000000000000043301516144147600167210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string type index_entry = | Def of (string * entry_type) list | Ref of coq_module * string * entry_type (* Find what symbol coqtop said is located at loc in the source file *) val find : coq_module -> loc -> index_entry (* Find what data is referred to by some string in some rocq module *) val find_string : string -> index_entry (** [add_ref cur_mod loc lib_dp sp id entry_type] *) val add_ref : string -> int -> coq_module -> coq_module -> string -> entry_type -> unit (** [add_def loc1 loc2 entry_type sp id] *) val add_def : int -> int -> entry_type -> coq_module -> string -> unit (* Add a Rocq module *) val add_module : coq_module -> unit type module_kind = Local | External of coq_module | Unknown val find_module : coq_module -> module_kind val init_coqlib_library : unit -> unit val add_external_library : string -> coq_module -> unit (*s Indexes *) type 'a index = { idx_name : string; idx_entries : (char * (string * 'a) list) list; idx_size : int } val current_library : string ref val display_letter : char -> string val prepare_entry : string -> entry_type -> string val all_entries : unit -> (coq_module * entry_type) index * (entry_type * coq_module index) list val map : (string -> 'a -> 'b) -> 'a index -> 'b index rocq-9.2.0/tools/coqdoc/latexCompiler.ml000066400000000000000000000061041516144147600202520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Sys.chdir cwd; raise e let clean_temp_files basefile = let remove f = try Sys.remove f with _ -> () in remove (basefile ^ ".tex"); remove (basefile ^ ".log"); remove (basefile ^ ".aux"); remove (basefile ^ ".toc"); remove (basefile ^ ".dvi"); remove (basefile ^ ".ps"); remove (basefile ^ ".pdf"); remove (basefile ^ ".haux"); remove (basefile ^ ".html") let clean_and_exit file res = clean_temp_files file; exit res let cat file = let c = open_in file in try while true do print_char (input_char c) done with End_of_file -> close_in c let compile ~otypes ~produce_document fl = let texfile = Filename.temp_file "coqdoc" ".tex" in let basefile = Filename.chop_suffix texfile ".tex" in let final_out_to = !prefs.out_to in prefs := { !prefs with out_to = File texfile }; prefs := { !prefs with output_dir = Filename.dirname texfile }; produce_document fl; let latexexe = if List.mem Pdf otypes then "pdflatex" else "latex" in let latexcmd = let file = Filename.basename texfile in let file = if !prefs.quiet then sprintf "'\\nonstopmode\\input{%s}'" file else file in sprintf "%s %s && %s %s 1>&2 %s" latexexe file latexexe file (if !prefs.quiet then "> /dev/null" else "") in let res = locally (Filename.dirname texfile) Sys.command latexcmd in if res <> 0 then begin eprintf "Couldn't run LaTeX successfully\n"; clean_and_exit basefile res end; let dvifile = basefile ^ ".dvi" in ( if List.mem Dvi otypes then match final_out_to with | MultFiles | StdOut -> cat dvifile | File f -> FileUtil.copy dvifile f ); let pdffile = basefile ^ ".pdf" in ( if List.mem Pdf otypes then match final_out_to with | MultFiles | StdOut -> cat pdffile | File f -> FileUtil.copy pdffile f ); if List.mem Ps otypes then begin let psfile = basefile ^ ".ps" in let command = sprintf "dvips %s -o %s %s" dvifile psfile (if !prefs.quiet then "> /dev/null 2>&1" else "") in let res = Sys.command command in if res <> 0 then begin eprintf "Couldn't run dvips successfully\n"; clean_and_exit basefile res end; match final_out_to with | MultFiles | StdOut -> cat psfile | File f -> FileUtil.copy psfile f end; clean_temp_files basefile rocq-9.2.0/tools/coqdoc/latexCompiler.mli000066400000000000000000000014451516144147600204260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* produce_document:(Common.file_t list -> unit) -> Common.file_t list -> unit rocq-9.2.0/tools/coqdoc/output.ml000066400000000000000000001264611516144147600170130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Hashtbl.add h key ()) l; function s -> try Hashtbl.find h s; true with Not_found -> false let is_keyword = build_table [ "About"; "Axiom"; "Abort"; "Chapter"; "Check"; "Coercion"; "Compute"; "CoFixpoint"; "CoInductive"; "Corollary"; "Defined"; "Definition"; "End"; "Eval"; "Example"; "Export"; "Fact"; "Fix"; "Fixpoint"; "From"; "Function"; "Generalizable"; "Global"; "Grammar"; "Guarded"; "Goal"; "Hint"; "Debug"; "On"; "Hypothesis"; "Hypotheses"; "Resolve"; "Unfold"; "Immediate"; "Extern"; "Constructors"; "Rewrite"; "Implicit"; "Import"; "Inductive"; "Infix"; "Lemma"; "Let"; "Load"; "Local"; "Locate"; "Ltac"; "Module"; "Module Type"; "Declare Module"; "Include"; "Mutual"; "Parameter"; "Parameters"; "Print"; "Printing"; "All"; "Proof"; "Proof with"; "Qed"; "Record"; "Recursive"; "Remark"; "Require"; "Save"; "Scheme"; "Assumptions"; "Axioms"; "Universes"; "Induction"; "for"; "Sort"; "Section"; "Show"; "Structure"; "Syntactic"; "Syntax"; "Tactic"; "Theorem"; "Search"; "SearchPattern"; "SearchRewrite"; "Set"; "Types"; "Undo"; "Unset"; "Variable"; "Variables"; "Context"; "Notation"; "Reserved Notation"; "Tactic Notation"; "Number Notation"; "String Notation"; "Enable Notation"; "Disable Notation"; "Delimit"; "Bind"; "Open"; "Scope"; "Inline"; "Implicit Arguments"; "Add"; "Strict"; "Typeclasses"; "Instance"; "Global Instance"; "Class"; "Instantiation"; "goal"; "goals"; "vm_compute"; "Opaque"; "Transparent"; "Time"; "Extraction"; "Extract"; "Variant"; (* Program *) "Program Definition"; "Program Example"; "Program Fixpoint"; "Program Lemma"; "Obligation"; "Obligations"; "Solve"; "using"; "Next Obligation"; "Next"; "Program Instance"; "Equations"; "Equations_nocomp"; (*i (* rocq terms *) *) "forall"; "match"; "as"; "in"; "return"; "with"; "end"; "let"; "fun"; "if"; "then"; "else"; "Prop"; "Set"; "Type"; ":="; "where"; "struct"; "wf"; "measure"; "fix"; "cofix"; "is"; (* Ltac *) "before"; "after"; "constr"; "ltac"; "goal"; "context"; "beta"; "delta"; "iota"; "zeta"; "lazymatch"; "type"; "of"; "rec"; (* Notations *) "level"; "associativity"; "no" ] let is_tactic = build_table [ "intro"; "intros"; "apply"; "rewrite"; "refine"; "case"; "clear"; "injection"; "progress"; "setoid_rewrite"; "left"; "right"; "constructor"; "econstructor"; "decide equality"; "abstract"; "exists"; "cbv"; "simple destruct"; "info"; "field"; "specialize"; "evar"; "solve"; "instantiate"; "info_auto"; "info_eauto"; "quote"; "eexact"; "autorewrite"; "destruct"; "destruction"; "destruct_call"; "dependent"; "elim"; "extensionality"; "f_equal"; "generalize"; "generalize_eqs"; "generalize_eqs_vars"; "induction"; "rename"; "move"; "set"; "assert"; "do"; "repeat"; "cut"; "assumption"; "exact"; "split"; "subst"; "try"; "discriminate"; "simpl"; "unfold"; "red"; "compute"; "at"; "in"; "by"; "reflexivity"; "symmetry"; "transitivity"; "replace"; "setoid_replace"; "inversion"; "inversion_clear"; "pattern"; "intuition"; "congruence"; "fail"; "fresh"; "trivial"; "tauto"; "firstorder"; "ring"; "clapply"; "program_simpl"; "program_simplify"; "eapply"; "auto"; "eauto"; "change"; "fold"; "hnf"; "lazy"; "simple"; "eexists"; "debug"; "idtac"; "first"; "type of"; "pose"; "eval"; "instantiate"; "until" ] (*s Current Rocq module *) let current_module : (string * string option) ref = ref ("",None) let get_module withsub = let (m,sub) = !current_module in if withsub then match sub with | None -> m | Some sub -> m ^ ": " ^ sub else m let set_module m sub = current_module := (m,sub); page_title := get_module true (*s Common to both LaTeX and HTML *) let item_level = ref 0 let in_doc = ref false (*s Customized and predefined pretty-print *) let initialize_texmacs () = let ensuremath x = sprintf ">" x in List.fold_right (fun (s,t) tt -> Tokens.ttree_add tt s t) [ "*", ensuremath "times"; "->", ensuremath "rightarrow"; "<-", ensuremath "leftarrow"; "<->", ensuremath "leftrightarrow"; "=>", ensuremath "Rightarrow"; "<=", ensuremath "le"; ">=", ensuremath "ge"; "<>", ensuremath "noteq"; "~", ensuremath "lnot"; "/\\", ensuremath "land"; "\\/", ensuremath "lor"; "|-", ensuremath "vdash" ] Tokens.empty_ttree let token_tree_texmacs = ref (initialize_texmacs ()) let token_tree_latex = ref Tokens.empty_ttree let token_tree_html = ref Tokens.empty_ttree let initialize_tex_html () = let if_utf8 = if !prefs.encoding.utf8 then fun x -> Some x else fun _ -> None in let (tree_latex, tree_html) = List.fold_right (fun (s,l,l') (tt,tt') -> (Tokens.ttree_add tt s l, match l' with None -> tt' | Some l' -> Tokens.ttree_add tt' s l')) [ "*" , "\\ensuremath{\\times}", if_utf8 "Γ—"; "|", "\\ensuremath{|}", None; "->", "\\ensuremath{\\rightarrow}", if_utf8 "β†’"; "->~", "\\ensuremath{\\rightarrow\\lnot}", None; "->~~", "\\ensuremath{\\rightarrow\\lnot\\lnot}", None; "<-", "\\ensuremath{\\leftarrow}", None; "<->", "\\ensuremath{\\leftrightarrow}", if_utf8 "↔"; "=>", "\\ensuremath{\\Rightarrow}", if_utf8 "β‡’"; "<=", "\\ensuremath{\\le}", if_utf8 "≀"; ">=", "\\ensuremath{\\ge}", if_utf8 "β‰₯"; "<>", "\\ensuremath{\\not=}", if_utf8 "β‰ "; "~", "\\ensuremath{\\lnot}", if_utf8 "Β¬"; "/\\", "\\ensuremath{\\land}", if_utf8 "∧"; "\\/", "\\ensuremath{\\lor}", if_utf8 "∨"; "|-", "\\ensuremath{\\vdash}", None; "forall", "\\ensuremath{\\forall}", if_utf8 "βˆ€"; "exists", "\\ensuremath{\\exists}", if_utf8 "βˆƒ"; "Ξ ", "\\ensuremath{\\Pi}", if_utf8 "Ξ "; "Ξ»", "\\ensuremath{\\lambda}", if_utf8 "Ξ»"; (* "fun", "\\ensuremath{\\lambda}" ? *) ] (Tokens.empty_ttree,Tokens.empty_ttree) in token_tree_latex := tree_latex; token_tree_html := tree_html let add_printing_token s (t1,t2) = (match t1 with None -> () | Some t1 -> token_tree_latex := Tokens.ttree_add !token_tree_latex s t1); (match t2 with None -> () | Some t2 -> token_tree_html := Tokens.ttree_add !token_tree_html s t2) let remove_printing_token s = token_tree_latex := Tokens.ttree_remove !token_tree_latex s; token_tree_html := Tokens.ttree_remove !token_tree_html s (*s Table of contents *) type toc_entry = | Toc_library of string * string option | Toc_section of int * (unit -> unit) * string let (toc_q : toc_entry Queue.t) = Queue.create () let add_toc_entry e = Queue.add e toc_q let new_label = let r = ref 0 in fun () -> incr r; "lab" ^ string_of_int !r (*s LaTeX output *) module Latex = struct let in_title = ref false (*s Latex preamble *) let (preamble : string Queue.t) = Queue.create () let push_in_preamble s = Queue.add s preamble let utf8x_extra_support () = printf "\n"; printf "%%Warning: tipa declares many non-standard macros used by utf8x to\n"; printf "%%interpret utf8 characters but extra packages might have to be added\n"; printf "%%such as \"textgreek\" for Greek letters not already in tipa\n"; printf "%%or \"stmaryrd\" for mathematical symbols.\n"; printf "%%Utf8 codes missing a LaTeX interpretation can be defined by using\n"; printf "%%\\DeclareUnicodeCharacter{code}{interpretation}.\n"; printf "%%Use coqdoc's option -p to add new packages or declarations.\n"; printf "\\usepackage{tipa}\n"; printf "\n" let header () = if !prefs.header_trailer then begin printf "\\documentclass[12pt]{report}\n"; if !prefs.encoding.inputenc != "" then printf "\\usepackage[%s]{inputenc}\n" !prefs.encoding.inputenc; if !prefs.encoding.inputenc = "utf8x" then utf8x_extra_support (); printf "\\usepackage[T1]{fontenc}\n"; printf "\\usepackage{fullpage}\n"; printf "\\usepackage{coqdoc}\n"; printf "\\usepackage{amsmath,amssymb}\n"; printf "\\usepackage{url}\n"; (match !prefs.toc_depth with | None -> () | Some n -> printf "\\setcounter{tocdepth}{%i}\n" n); Queue.iter (fun s -> printf "%s\n" s) preamble; printf "\\begin{document}\n" end; output_string "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; output_string "%% This file has been automatically generated with the command\n"; output_string "%% "; Array.iter (fun s -> printf "%s " s) Sys.argv; printf "\n"; output_string "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" let trailer () = if !prefs.header_trailer then begin printf "\\end{document}\n" end (*s Latex low-level translation *) let nbsp () = output_char '~' let char c = match c with | '\\' -> printf "\\symbol{92}" | '$' | '#' | '%' | '&' | '{' | '}' | '_' -> output_char '\\'; output_char c | '^' | '~' -> output_char '\\'; output_char c; printf "{}" | _ -> output_char c let label_char c = match c with | '_' -> output_char ' ' | '\\' | '$' | '#' | '%' | '&' | '{' | '}' | '^' | '~' -> printf "x%X" (Char.code c) | _ -> if c >= '\x80' then printf "x%X" (Char.code c) else output_char c let label_ident s = for i = 0 to String.length s - 1 do label_char s.[i] done let latex_char = output_char let latex_string = output_string let html_char _ = () let html_string _ = () (*s Latex char escaping *) let escaped = let buff = Buffer.create 5 in fun s -> Buffer.clear buff; for i = 0 to String.length s - 1 do match s.[i] with | '\\' -> Buffer.add_string buff "\\symbol{92}" | '$' | '#' | '%' | '&' | '{' | '}' | '_' as c -> Buffer.add_char buff '\\'; Buffer.add_char buff c | '^' | '~' as c -> Buffer.add_char buff '\\'; Buffer.add_char buff c; Buffer.add_string buff "{}" | '\'' -> if i < String.length s - 1 && s.[i+1] = '\'' then begin Buffer.add_char buff '\''; Buffer.add_char buff '{'; Buffer.add_char buff '}' end else Buffer.add_char buff '\'' | c -> Buffer.add_char buff c done; Buffer.contents buff (*s Latex reference and symbol translation *) let start_module () = let ln = !prefs.lib_name in if not !prefs.short then begin printf "\\coqlibrary{"; label_ident (get_module false); printf "}{"; if ln <> "" then printf "%s " ln; printf "}{%s}\n\n" (escaped (get_module true)) end let start_latex_math () = output_char '$' let stop_latex_math () = output_char '$' let start_quote () = output_char '`'; output_char '`' let stop_quote () = output_char '\''; output_char '\'' let start_verbatim inline = if inline then printf "\\texttt{" else printf "\\begin{verbatim}\n" let stop_verbatim inline = if inline then printf "}" else printf "\\end{verbatim}\n" let url addr name = printf "%s\\footnote{\\url{%s}}" (match name with | None -> "" | Some n -> n) addr let indentation n = if n == 0 then printf "\\coqdocnoindent\n" else let space = 0.5 *. (float n) in printf "\\coqdocindent{%2.2fem}\n" space let ident_ref m fid typ s = let id = if fid <> "" then (m ^ "." ^ fid) else m in match find_module m with | Local -> printf "\\coqref{"; label_ident id; printf "}{\\coqdoc%s{%s}}" (type_name typ) s | External m when !prefs.externals -> printf "\\coqexternalref{"; label_ident fid; printf "}{%s}{\\coqdoc%s{%s}}" (escaped m) (type_name typ) s | External _ | Unknown -> printf "\\coqdoc%s{%s}" (type_name typ) s let defref m id ty s = if ty <> Notation then (printf "\\coqdef{"; label_ident (m ^ "." ^ id); printf "}{%s}{\\coqdoc%s{%s}}" s (type_name ty) s) else (* Glob file still not able to say the exact extent of the definition *) (* so we currently renounce to highlight the notation location *) (printf "\\coqdef{"; label_ident (m ^ "." ^ id); printf "}{%s}{%s}" s s) let reference s = function | Def [] -> assert false | Def ((fullid,typ) :: _) -> defref (get_module false) fullid typ s | Ref (m,fullid,typ) -> ident_ref m fullid typ s (*s The sublexer buffers symbol characters and attached uninterpreted ident and try to apply special translation such as, predefined, translation "->" to "\ensuremath{\rightarrow}" or, virtually, a user-level translation from "=_h" to "\ensuremath{=_{h}}" *) let output_sublexer_string doescape issymbchar tag s = let s = if doescape then escaped s else s in match tag with | Some ref -> reference s ref | None -> if issymbchar then output_string s else printf "\\coqdocvar{%s}" s let last_was_in = ref false let sublexer c loc = if c = '*' && !last_was_in then begin Tokens.flush_sublexer (); output_char '*' end else begin let tag = try Some (Index.find (get_module false) loc) with Not_found -> None in Tokens.output_tagged_symbol_char tag c end; last_was_in := false let sublexer_in_doc c = if c = '*' && !last_was_in then begin Tokens.flush_sublexer (); output_char '*' end else Tokens.output_tagged_symbol_char None c; last_was_in := false let initialize () = initialize_tex_html (); Tokens.token_tree := token_tree_latex; Tokens.outfun := output_sublexer_string (*s Interpreting ident with fallback on sublexer if unknown ident *) let translate s = match Tokens.translate s with Some s -> s | None -> escaped s let keyword s loc = printf "\\coqdockw{%s}" (translate s) let ident s loc = last_was_in := s = "in"; try match loc with | None -> raise Not_found | Some loc -> let tag = Index.find (get_module false) loc in reference (translate s) tag with Not_found -> if is_tactic s then printf "\\coqdoctac{%s}" (translate s) else if is_keyword s then printf "\\coqdockw{%s}" (translate s) else if !prefs.interpolate && !in_doc (* always a var otherwise *) then try let tag = Index.find_string s in reference (translate s) tag with _ -> Tokens.output_tagged_ident_string s else Tokens.output_tagged_ident_string s let ident s l = if !in_title then ( printf "\\texorpdfstring{\\protect"; ident s l; printf "}{%s}" (translate s)) else ident s l (*s Translating structure *) let proofbox () = printf "\\ensuremath{\\Box}" let rec reach_item_level n = if !item_level < n then begin printf "\n\\begin{itemize}\n\\item "; incr item_level; reach_item_level n end else if !item_level > n then begin printf "\n\\end{itemize}\n"; decr item_level; reach_item_level n end let item n = let old_level = !item_level in reach_item_level n; if n <= old_level then printf "\n\\item " let stop_item () = reach_item_level 0 let start_doc () = in_doc := true let end_doc () = in_doc := false; stop_item () (* This is broken if we are in math mode, but coqdoc currently isn't tracking that *) let start_emph () = printf "\\textit{" let stop_emph () = printf "}" let start_details _ = () let stop_details () = () let start_comment () = printf "\\begin{coqdoccomment}\n" let end_comment () = printf "\\end{coqdoccomment}\n" let start_coq () = printf "\\begin{coqdoccode}\n" let end_coq () = printf "\\end{coqdoccode}\n" let section_kind = function | 1 -> "\\section{" | 2 -> "\\subsection{" | 3 -> "\\subsubsection{" | 4 -> "\\paragraph{" | _ -> assert false let section lev f = stop_item (); output_string (section_kind lev); in_title := true; f (); in_title := false; printf "}\n\n" let rule () = printf "\\par\n\\noindent\\hrulefill\\par\n\\noindent{}" let paragraph () = printf "\n\n" let line_break () = printf "\\coqdoceol\n" let empty_line_of_code () = printf "\\coqdocemptyline\n" let start_inline_coq_block () = line_break (); empty_line_of_code () let end_inline_coq_block () = empty_line_of_code () let start_inline_coq () = () let end_inline_coq () = () let make_multi_index () = () let make_index () = () let make_toc () = printf "\\tableofcontents\n" end (*s HTML output *) module Html = struct let title_re = Str.regexp_string "@@TITLE@@" let header () = if !prefs.header_trailer then begin match !prefs.header_file with | None -> printf "\n"; printf "\n\n"; printf "\n" !prefs.encoding.charset; printf "\n"; printf "%s\n\n\n" !page_title; printf "\n\n
\n\n
\n
\n\n"; printf "
\n\n" | Some f -> let cin = open_in f in try while true do let s = input_line cin in let s = Str.global_replace title_re !page_title s in printf "%s\n" s done with End_of_file -> close_in cin end let trailer () = if !prefs.header_trailer then begin match !prefs.footer_file with | None -> if !prefs.index && (get_module false) <> "Index" then printf "
\n\n
\n
Index" !prefs.index_name; printf "
This page has been generated by "; printf "coqdoc\n" Coq_config.wwwcoq; printf "
\n\n
\n\n\n" | Some f -> let cin = open_in f in try while true do let s = input_line cin in printf "%s\n" s done with End_of_file -> close_in cin end let start_module () = let ln = !prefs.lib_name in if not !prefs.short then begin let (m,sub) = !current_module in add_toc_entry (Toc_library (m,sub)); if ln = "" then printf "

%s

\n\n" (get_module true) else printf "

%s %s

\n\n" ln (get_module true) end let indentation n = for _i = 1 to n do printf " " done let line_break () = printf "
\n" let empty_line_of_code () = printf "\n
\n" let nbsp () = printf " " let char = function | '<' -> printf "<" | '>' -> printf ">" | '&' -> printf "&" | c -> output_char c let escaped = let buff = Buffer.create 5 in fun s -> Buffer.clear buff; for i = 0 to String.length s - 1 do match s.[i] with | '<' -> Buffer.add_string buff "<" | '>' -> Buffer.add_string buff ">" | '&' -> Buffer.add_string buff "&" | '\"' -> Buffer.add_string buff """ | c -> Buffer.add_char buff c done; Buffer.contents buff let sanitize_name s = let rec loop esc i = if i < 0 then if esc then escaped s else s else match s.[i] with | 'a'..'z' | 'A'..'Z' | '0'..'9' | '.' | '_' -> loop esc (i-1) | '<' | '>' | '&' | '\'' | '\"' -> loop true (i-1) | '-' | ':' -> loop esc (i-1) (* should be safe in HTML5 attribute name syntax *) | _ -> (* This name contains complex characters: this is probably a notation string, we simply hash it. *) Digest.to_hex (Digest.string s) in loop false (String.length s - 1) let latex_char _ = () let latex_string _ = () let html_char = output_char let html_string = output_string let start_latex_math () = () let stop_latex_math () = () let start_quote () = char '"' let stop_quote () = start_quote () let start_verbatim inline = if inline then printf "" else printf "
\n"

  let stop_verbatim inline =
    if inline then printf ""
    else printf "
\n" let url addr name = printf "%s" addr (match name with | Some n -> n | None -> addr) let ident_ref m fid typ s = match find_module m with | Local -> printf "" m (sanitize_name fid); printf "%s" typ s | External m when !prefs.externals -> printf "" m (sanitize_name fid); printf "%s" typ s | External _ | Unknown -> printf "%s" typ s let reference s r = match r with | Def [] -> assert false | Def [fullid,ty] -> let s' = sanitize_name fullid in printf "" s' s'; printf "%s" (type_name ty) s | Def ((hd_id,_) :: tail as all) -> let hd = sanitize_name hd_id in let all_tys = all |> List.map (fun (_,ty) -> type_name ty) |> CList.sort_uniquize String.compare |> String.concat ", " in printf "" hd hd all_tys; List.iter (fun (fullid,_) -> let s' = sanitize_name fullid in printf "" s') tail; printf "%s" s; List.iter (fun _ -> printf "") tail; printf ""; | Ref (m,fullid,ty) -> ident_ref m fullid (type_name ty) s let output_sublexer_string doescape issymbchar tag s = let s = if doescape then escaped s else s in match tag with | Some ref -> reference s ref | None -> if issymbchar then output_string s else printf "%s" s let sublexer c loc = let tag = try Some (Index.find (get_module false) loc) with Not_found -> None in Tokens.output_tagged_symbol_char tag c let sublexer_in_doc c = Tokens.output_tagged_symbol_char None c let initialize () = initialize_tex_html(); Tokens.token_tree := token_tree_html; Tokens.outfun := output_sublexer_string let translate s = match Tokens.translate s with Some s -> s | None -> escaped s let keyword s loc = printf "%s" (translate s) let ident s loc = try match loc with | None -> raise Not_found | Some loc -> reference (translate s) (Index.find (get_module false) loc) with Not_found -> if is_tactic s then printf "%s" (translate s) else if is_keyword s then printf "%s" (translate s) else if !prefs.interpolate && !in_doc (* always a var otherwise *) then try reference (translate s) (Index.find_string s) with Not_found -> Tokens.output_tagged_ident_string s else Tokens.output_tagged_ident_string s let proofbox () = printf "" let rec reach_item_level n = if !item_level < n then begin printf "
    \n
  • "; incr item_level; reach_item_level n end else if !item_level > n then begin printf "\n
  • \n
\n"; decr item_level; reach_item_level n end let item n = let old_level = !item_level in reach_item_level n; if n <= old_level then printf "\n\n
  • " let stop_item () = reach_item_level 0 let start_coq () = if not !prefs.raw_comments then printf "
    \n" let end_coq () = if not !prefs.raw_comments then printf "
    \n" let start_doc () = in_doc := true; if not !prefs.raw_comments then printf "\n
    \n" let end_doc () = in_doc := false; stop_item (); if not !prefs.raw_comments then printf "
    \n" let start_emph () = printf "" let stop_emph () = printf "" let start_details = function | Some s -> printf "
    %s" s | _ -> printf "
    " let stop_details () = printf "
    " let start_comment () = printf "(*" let end_comment () = printf "*)" let start_inline_coq () = if !prefs.inline_notmono then printf "" else printf "" let end_inline_coq () = printf "" let start_inline_coq_block () = line_break (); start_inline_coq () let end_inline_coq_block () = end_inline_coq () let paragraph () = printf "\n
    \n\n" (* inference rules *) let inf_rule assumptions (_,_,midnm) conclusions = (* this first function replaces any occurrence of 3 or more spaces in a row with " "s. We do this to the assumptions so that people can put multiple rules on a line with nice formatting *) let replace_spaces str = let rec copy a n = match n with 0 -> [] | n -> (a :: copy a (n - 1)) in let results = Str.full_split (Str.regexp "[' '][' '][' ']+") str in let strs = List.map (fun r -> match r with | Str.Text s -> [s] | Str.Delim s -> copy " " (String.length s)) results in String.concat "" (List.concat strs) in let start_assumption line = (printf "\n"; printf " %s\n" (replace_spaces line)) in let end_assumption () = (printf " \n"; printf "\n") in let rec print_assumptions hyps = match hyps with | [] -> start_assumption "  " | [(_,hyp)] -> start_assumption hyp | ((_,hyp) :: hyps') -> (start_assumption hyp; end_assumption (); print_assumptions hyps') in printf "
    \n"; print_assumptions assumptions; printf " " | Some s -> printf " %s  \n " s); printf "\n"; printf "\n"; printf " \n"; printf "\n"; print_assumptions conclusions; end_assumption (); printf "
    \n"; (match midnm with | None -> printf "  \n

    " let section lev f = let lab = new_label () in let r = sprintf "%s.html#%s" (get_module false) lab in (match !prefs.toc_depth with | None -> add_toc_entry (Toc_section (lev, f, r)) | Some n -> if lev <= n then add_toc_entry (Toc_section (lev, f, r)) else ()); stop_item (); printf "" lab lev; f (); printf "\n" lev let rule () = printf "
    \n" (* make a HTML index from a list of triples (name,text,link) *) let index_ref i c = let idxc = sprintf "%s_%c" i.idx_name c in !prefs.index_name ^ (if !prefs.multi_index then "_" ^ idxc ^ ".html" else ".html#" ^ idxc) let letter_index category idx (c,l) = if l <> [] then begin let cat = if category && idx <> "global" then "(" ^ idx ^ ")" else "" in printf "

    %s %s

    \n" idx c (display_letter c) cat; List.iter (fun (id,(text,link,t)) -> let id' = escaped (prepare_entry id t) in printf "%s %s
    \n" link id' text) l; printf "

    " end let all_letters i = List.iter (letter_index false i.idx_name) i.idx_entries (* Construction d'une liste des index (1 index global, puis 1 index par catΓ©gorie) *) let format_global_index = Index.map (fun s (m,t) -> if t = Library then let ln = !prefs.lib_name in if ln <> "" then "[" ^ String.lowercase_ascii ln ^ "]", m ^ ".html", t else "[library]", m ^ ".html", t else sprintf "[%s, in %s]" (type_name t) m m , sprintf "%s.html#%s" m (sanitize_name s), t) let format_bytype_index = function | Library, idx -> Index.map (fun id m -> "", m ^ ".html", Library) idx | (t,idx) -> Index.map (fun s m -> let text = sprintf "[in %s]" m m in (text, sprintf "%s.html#%s" m (sanitize_name s), t)) idx (* Impression de la table d'index *) let print_index_table_item i = printf "\n%s Index\n" (String.capitalize_ascii i.idx_name); List.iter (fun (c,l) -> if l <> [] then printf "%s\n" (index_ref i c) (display_letter c) else printf "%s\n" (display_letter c)) i.idx_entries; let n = i.idx_size in printf "(%d %s)\n" n (if n > 1 then "entries" else "entry"); printf "\n" let print_index_table idxl = printf "\n"; List.iter print_index_table_item idxl; printf "
    \n" let make_one_multi_index prt_tbl i = (* Attn: make_one_multi_index crΓ©e un nouveau fichier... *) let idx = i.idx_name in let one_letter ((c,l) as cl) = open_out_file (sprintf "%s_%s_%c.html" !prefs.index_name idx c); if (!prefs.header_trailer) then header (); prt_tbl (); printf "
    "; letter_index true idx cl; if List.length l > 30 then begin printf "
    "; prt_tbl () end; if (!prefs.header_trailer) then trailer (); close_out_file () in List.iter one_letter i.idx_entries let make_multi_index () = let all_index = let glob,bt = Index.all_entries () in (format_global_index glob) :: (List.map format_bytype_index bt) in let print_table () = print_index_table all_index in List.iter (make_one_multi_index print_table) all_index let make_index () = let all_index = let glob,bt = Index.all_entries () in (format_global_index glob) :: (List.map format_bytype_index bt) in let print_table () = print_index_table all_index in let print_one_index i = if i.idx_size > 0 then begin printf "
    \n

    %s Index

    \n" (String.capitalize_ascii i.idx_name); all_letters i end in set_module "Index" None; if !prefs.title <> "" then printf "

    %s

    \n" !prefs.title; print_table (); if not (!prefs.multi_index) then begin List.iter print_one_index all_index; printf "
    "; print_table () end let make_toc () = let ln = !prefs.lib_name in let make_toc_entry = function | Toc_library (m,sub) -> stop_item (); let ms = match sub with | None -> m | Some s -> m ^ ": " ^ s in if ln = "" then printf "

    %s

    \n" m ms else printf "

    %s %s

    \n" m ln ms | Toc_section (n, f, r) -> item n; printf "" r; f (); printf "\n" in printf "
    \n"; Queue.iter make_toc_entry toc_q; stop_item (); printf "
    \n" end (*s TeXmacs-aware output *) module TeXmacs = struct (*s Latex preamble *) let (_ : string Queue.t) = in_doc := false; Queue.create () let header () = output_string "(*i This file has been automatically generated with the command \n"; output_string " "; Array.iter (fun s -> printf "%s " s) Sys.argv; printf " *)\n" let trailer () = () let nbsp () = output_char ' ' let char_true c = match c with | '\\' -> printf "\\\\" | '<' -> printf "\\<" | '|' -> printf "\\|" | '>' -> printf "\\>" | _ -> output_char c let char c = if !in_doc then char_true c else output_char c let latex_char = char_true let latex_string = String.iter latex_char let html_char _ = () let html_string _ = () let raw_ident s = for i = 0 to String.length s - 1 do char s.[i] done let start_module () = () let start_latex_math () = printf "' let start_verbatim inline = in_doc := true; printf "<\\verbatim>" let stop_verbatim inline = in_doc := false; printf "" let url addr name = printf "%s<\\footnote><\\url>%s" addr (match name with | None -> "" | Some n -> n) let start_quote () = output_char '`'; output_char '`' let stop_quote () = output_char '\''; output_char '\'' let indentation n = () let keyword s = printf "" let ident_true s = if is_keyword s then keyword s else raw_ident s let keyword s loc = keyword s let ident s _ = if !in_doc then ident_true s else raw_ident s let output_sublexer_string doescape issymbchar tag s = if doescape then raw_ident s else output_string s let sublexer c l = if !in_doc then Tokens.output_tagged_symbol_char None c else char c let sublexer_in_doc c = char c let initialize () = Tokens.token_tree := token_tree_texmacs; Tokens.outfun := output_sublexer_string let proofbox () = printf "QED" let rec reach_item_level n = if !item_level < n then begin printf "\n<\\itemize>\n"; incr item_level; reach_item_level n end else if !item_level > n then begin printf "\n"; decr item_level; reach_item_level n end let item n = let old_level = !item_level in reach_item_level n; if n <= old_level then printf "\n\n" let stop_item () = reach_item_level 0 let start_doc () = in_doc := true; printf "(** texmacs: " let end_doc () = stop_item (); in_doc := false; printf " *)" let start_coq () = () let end_coq () = () let start_emph () = printf "" let start_details _ = () let stop_details () = () let start_comment () = () let end_comment () = () let section_kind = function | 1 -> "section" | 2 -> "subsection" | 3 -> "subsubsection" | 4 -> "paragraph" | _ -> assert false let section lev f = stop_item (); printf "<"; output_string (section_kind lev); printf "|"; f (); printf ">\n\n" let rule () = printf "\n\n" let paragraph () = printf "\n\n" let line_break () = printf "\n" let empty_line_of_code () = printf "\n" let start_inline_coq () = printf "" let start_inline_coq_block () = line_break (); start_inline_coq () let end_inline_coq_block () = end_inline_coq () let make_multi_index () = () let make_index () = () let make_toc () = () end (*s Raw output *) module Raw = struct let header () = () let trailer () = () let nbsp () = output_char ' ' let char = output_char let latex_char = output_char let latex_string = output_string let html_char _ = () let html_string _ = () let raw_ident s = for i = 0 to String.length s - 1 do char s.[i] done let start_module () = () let start_latex_math () = () let stop_latex_math () = () let start_verbatim inline = () let stop_verbatim inline = () let url addr name = match name with | Some n -> printf "%s (%s)" n addr | None -> printf "%s" addr let start_quote () = printf "\"" let stop_quote () = printf "\"" let indentation n = for _i = 1 to n do printf " " done let keyword s loc = raw_ident s let ident s loc = raw_ident s let sublexer c l = char c let sublexer_in_doc c = char c let initialize () = Tokens.token_tree := ref Tokens.empty_ttree; Tokens.outfun := (fun _ _ _ _ -> failwith "Useless") let proofbox () = printf "[]" let item n = printf "- " let stop_item () = () let reach_item_level _ = () let start_doc () = printf "(** " let end_doc () = printf " *)\n" let start_emph () = printf "_" let stop_emph () = printf "_" let start_details _ = () let stop_details () = () let start_comment () = printf "(*" let end_comment () = printf "*)" let start_coq () = () let end_coq () = () let section_kind = function | 1 -> "* " | 2 -> "** " | 3 -> "*** " | 4 -> "**** " | _ -> assert false let section lev f = output_string (section_kind lev); f () let rule () = () let paragraph () = printf "\n\n" let line_break () = printf "\n" let empty_line_of_code () = printf "\n" let start_inline_coq () = () let end_inline_coq () = () let start_inline_coq_block () = line_break (); start_inline_coq () let end_inline_coq_block () = end_inline_coq () let make_multi_index () = () let make_index () = () let make_toc () = () end (*s Generic output *) let select f1 f2 f3 f4 x = match !prefs.targetlang with LaTeX -> f1 x | HTML -> f2 x | TeXmacs -> f3 x | Raw -> f4 x let push_in_preamble = Latex.push_in_preamble let header = select Latex.header Html.header TeXmacs.header Raw.header let trailer = select Latex.trailer Html.trailer TeXmacs.trailer Raw.trailer let start_module = select Latex.start_module Html.start_module TeXmacs.start_module Raw.start_module let start_doc = select Latex.start_doc Html.start_doc TeXmacs.start_doc Raw.start_doc let end_doc = select Latex.end_doc Html.end_doc TeXmacs.end_doc Raw.end_doc let start_comment = select Latex.start_comment Html.start_comment TeXmacs.start_comment Raw.start_comment let end_comment = select Latex.end_comment Html.end_comment TeXmacs.end_comment Raw.end_comment let start_coq = select Latex.start_coq Html.start_coq TeXmacs.start_coq Raw.start_coq let end_coq = select Latex.end_coq Html.end_coq TeXmacs.end_coq Raw.end_coq let start_inline_coq = select Latex.start_inline_coq Html.start_inline_coq TeXmacs.start_inline_coq Raw.start_inline_coq let end_inline_coq = select Latex.end_inline_coq Html.end_inline_coq TeXmacs.end_inline_coq Raw.end_inline_coq let start_inline_coq_block = select Latex.start_inline_coq_block Html.start_inline_coq_block TeXmacs.start_inline_coq_block Raw.start_inline_coq_block let end_inline_coq_block = select Latex.end_inline_coq_block Html.end_inline_coq_block TeXmacs.end_inline_coq_block Raw.end_inline_coq_block let indentation = select Latex.indentation Html.indentation TeXmacs.indentation Raw.indentation let paragraph = select Latex.paragraph Html.paragraph TeXmacs.paragraph Raw.paragraph let line_break = select Latex.line_break Html.line_break TeXmacs.line_break Raw.line_break let empty_line_of_code = select Latex.empty_line_of_code Html.empty_line_of_code TeXmacs.empty_line_of_code Raw.empty_line_of_code let section = select Latex.section Html.section TeXmacs.section Raw.section let item = select Latex.item Html.item TeXmacs.item Raw.item let stop_item = select Latex.stop_item Html.stop_item TeXmacs.stop_item Raw.stop_item let reach_item_level = select Latex.reach_item_level Html.reach_item_level TeXmacs.reach_item_level Raw.reach_item_level let rule = select Latex.rule Html.rule TeXmacs.rule Raw.rule let nbsp = select Latex.nbsp Html.nbsp TeXmacs.nbsp Raw.nbsp let char = select Latex.char Html.char TeXmacs.char Raw.char let keyword = select Latex.keyword Html.keyword TeXmacs.keyword Raw.keyword let ident = select Latex.ident Html.ident TeXmacs.ident Raw.ident let sublexer = select Latex.sublexer Html.sublexer TeXmacs.sublexer Raw.sublexer let sublexer_in_doc = select Latex.sublexer_in_doc Html.sublexer_in_doc TeXmacs.sublexer_in_doc Raw.sublexer_in_doc let initialize = select Latex.initialize Html.initialize TeXmacs.initialize Raw.initialize let proofbox = select Latex.proofbox Html.proofbox TeXmacs.proofbox Raw.proofbox let latex_char = select Latex.latex_char Html.latex_char TeXmacs.latex_char Raw.latex_char let latex_string = select Latex.latex_string Html.latex_string TeXmacs.latex_string Raw.latex_string let html_char = select Latex.html_char Html.html_char TeXmacs.html_char Raw.html_char let html_string = select Latex.html_string Html.html_string TeXmacs.html_string Raw.html_string let start_emph = select Latex.start_emph Html.start_emph TeXmacs.start_emph Raw.start_emph let stop_emph = select Latex.stop_emph Html.stop_emph TeXmacs.stop_emph Raw.stop_emph let start_details = select Latex.start_details Html.start_details TeXmacs.start_details Raw.start_details let stop_details = select Latex.stop_details Html.stop_details TeXmacs.stop_details Raw.stop_details let start_latex_math = select Latex.start_latex_math Html.start_latex_math TeXmacs.start_latex_math Raw.start_latex_math let stop_latex_math = select Latex.stop_latex_math Html.stop_latex_math TeXmacs.stop_latex_math Raw.stop_latex_math let start_verbatim = select Latex.start_verbatim Html.start_verbatim TeXmacs.start_verbatim Raw.start_verbatim let stop_verbatim = select Latex.stop_verbatim Html.stop_verbatim TeXmacs.stop_verbatim Raw.stop_verbatim let verbatim_char inline = select (if inline then Latex.char else output_char) Html.char TeXmacs.char Raw.char let hard_verbatim_char = output_char let url = select Latex.url Html.url TeXmacs.url Raw.url let start_quote = select Latex.start_quote Html.start_quote TeXmacs.start_quote Raw.start_quote let stop_quote = select Latex.stop_quote Html.stop_quote TeXmacs.stop_quote Raw.stop_quote let inf_rule_dumb assumptions (midsp,midln,midnm) conclusions = start_verbatim false; let dumb_line = function (sp,ln) -> (String.iter char ((String.make sp ' ') ^ ln); char '\n') in (List.iter dumb_line assumptions; dumb_line (midsp, midln ^ (match midnm with | Some s -> " " ^ s | None -> "")); List.iter dumb_line conclusions); stop_verbatim false let inf_rule = select inf_rule_dumb Html.inf_rule inf_rule_dumb inf_rule_dumb let make_multi_index = select Latex.make_multi_index Html.make_multi_index TeXmacs.make_multi_index Raw.make_multi_index let make_index = select Latex.make_index Html.make_index TeXmacs.make_index Raw.make_index let make_toc = select Latex.make_toc Html.make_toc TeXmacs.make_toc Raw.make_toc rocq-9.2.0/tools/coqdoc/output.mli000066400000000000000000000063241516144147600171570ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val add_printing_token : string -> string option * string option -> unit val remove_printing_token : string -> unit val set_module : coq_module -> string option -> unit val get_module : bool -> string val header : unit -> unit val trailer : unit -> unit val push_in_preamble : string -> unit val start_module : unit -> unit val start_doc : unit -> unit val end_doc : unit -> unit val start_details : string option -> unit val stop_details : unit -> unit val start_emph : unit -> unit val stop_emph : unit -> unit val start_comment : unit -> unit val end_comment : unit -> unit val start_coq : unit -> unit val end_coq : unit -> unit val start_inline_coq : unit -> unit val end_inline_coq : unit -> unit val start_inline_coq_block : unit -> unit val end_inline_coq_block : unit -> unit val indentation : int -> unit val line_break : unit -> unit val paragraph : unit -> unit val empty_line_of_code : unit -> unit val section : int -> (unit -> unit) -> unit val item : int -> unit val stop_item : unit -> unit val reach_item_level : int -> unit val rule : unit -> unit val nbsp : unit -> unit val char : char -> unit val keyword : string -> loc -> unit val ident : string -> loc option -> unit val sublexer : char -> loc -> unit val sublexer_in_doc : char -> unit val proofbox : unit -> unit val latex_char : char -> unit val latex_string : string -> unit val html_char : char -> unit val html_string : string -> unit val verbatim_char : bool -> char -> unit val hard_verbatim_char : char -> unit val start_latex_math : unit -> unit val stop_latex_math : unit -> unit val start_verbatim : bool -> unit val stop_verbatim : bool -> unit val start_quote : unit -> unit val stop_quote : unit -> unit val url : string -> string option -> unit (* this outputs an inference rule in one go. You pass it the list of assumptions, then the middle line info, then the conclusion (which is allowed to span multiple lines). In each case, the int is the number of spaces before the start of the line's text and the string is the text of the line with the leading trailing space trimmed. For the middle rule, you can also optionally provide a name. We need the space info so that in modes where we aren't doing something smart we can just format the rule verbatim like the user did *) val inf_rule : (int * string) list -> (int * string * (string option)) -> (int * string) list -> unit val make_multi_index : unit -> unit val make_index : unit -> unit val make_toc : unit -> unit rocq-9.2.0/tools/coqdoc/rocqdoc_main.ml000066400000000000000000000125121516144147600201000ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* f ^ ".html" | Raw -> f ^ ".txt" | _ -> f ^ ".tex" (*s The following function produces the output. The default output is the \LaTeX\ document: in that case, we just call [Web.produce_document]. If option \verb!-dvi!, \verb!-ps! or \verb!-html! is invoked, then we make calls to \verb!latex! or \verb!dvips! or \verb!pdflatex! accordingly. *) (*s Functions for generating output files *) let gen_one_file l = let file = function | Vernac_file (f,m) -> let sub = if !prefs.lib_subtitles then Cpretty.detect_subtitle f m else None in Output.set_module m sub; Cpretty.coq_file f m | Latex_file _ -> () in if (!prefs.header_trailer) then Output.header (); if !prefs.toc then Output.make_toc (); List.iter file l; if !prefs.index then Output.make_index(); if (!prefs.header_trailer) then Output.trailer () let gen_mult_files l = let file = function | Vernac_file (f,m) -> let sub = if !prefs.lib_subtitles then Cpretty.detect_subtitle f m else None in let hf = target_full_name m in Output.set_module m sub; open_out_file hf; if (!prefs.header_trailer) then Output.header (); Cpretty.coq_file f m; if (!prefs.header_trailer) then Output.trailer (); close_out_file() | Latex_file _ -> () in List.iter file l; if (!prefs.index && !prefs.targetlang=HTML) then begin if (!prefs.multi_index) then Output.make_multi_index (); open_out_file (!prefs.index_name^".html"); page_title := (if !prefs.title <> "" then !prefs.title else "Index"); if (!prefs.header_trailer) then Output.header (); Output.make_index (); if (!prefs.header_trailer) then Output.trailer (); close_out_file() end; if (!prefs.toc && !prefs.targetlang=HTML) then begin open_out_file "toc.html"; page_title := (if !prefs.title <> "" then !prefs.title else "Table of contents"); if (!prefs.header_trailer) then Output.header (); if !prefs.title <> "" then printf "

    %s

    \n" !prefs.title; Output.make_toc (); if (!prefs.header_trailer) then Output.trailer (); close_out_file() end (* NB: for latex and texmacs, a separated toc or index is meaningless... *) let read_glob_file vfile f = try Glob_file.read_glob vfile f with Sys_error s -> eprintf "Warning: %s (links will not be available)\n" s let read_glob_file_of = function | Vernac_file (f,_) -> read_glob_file (Some f) (Filename.chop_extension f ^ ".glob") | Latex_file _ -> () let index_module = function | Vernac_file (f,m) -> Index.add_module m | Latex_file _ -> () module E = Boot.Env let copy_style_file file = (* We give preference to coqlib in case it is overriden *) let env = E.init_with ~coqlib:!prefs.coqlib in let coqdoc = E.tool env "coqdoc" in let sty_file = E.Path.relative coqdoc file in if not (E.Path.exists sty_file) then begin let sty_file = E.Path.to_string sty_file in eprintf "coqdoc: cannot find coqdoc style file: %s\n" sty_file; exit 1 end; let sty_file_s = E.Path.to_string sty_file in let dst = coqdoc_out file in FileUtil.copy sty_file_s dst let produce_document l = if !prefs.targetlang=HTML then copy_style_file "coqdoc.css"; if !prefs.targetlang=LaTeX then copy_style_file "coqdoc.sty"; (match !prefs.glob_source with | NoGlob -> () | DotGlob -> List.iter read_glob_file_of l | GlobFile f -> read_glob_file None f); List.iter index_module l; match !prefs.out_to with | StdOut -> Common.out_channel := stdout; gen_one_file l | File f -> open_out_file f; gen_one_file l; close_out_file() | MultFiles -> gen_mult_files l let produce_output fl = if List.length !prefs.compile_targets = 0 then produce_document fl else let otypes = !prefs.compile_targets in LatexCompiler.compile ~otypes ~produce_document fl (*s \textbf{Main program.} Print the banner, parse the command line, read the files and then call [produce_document] from module [Web]. *) let main ~prog args = CmdArgs.parse_args ~prog args; (* Sets prefs *) let files = List.rev !prefs.files in Index.init_coqlib_library (); if not !prefs.quiet then banner (); if files <> [] then produce_output files rocq-9.2.0/tools/coqdoc/rocqdoc_main.mli000066400000000000000000000013221516144147600202460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> unit rocq-9.2.0/tools/coqdoc/style.css000066400000000000000000000020131516144147600167550ustar00rootroot00000000000000a:visited {color : #416DFF; text-decoration : none; } a:link {color : #416DFF; text-decoration : none; font-weight : bold} a:hover {color : Red; text-decoration : underline; } a:active {color : Red; text-decoration : underline; } .keyword { font-weight : bold ; color : Red } .keywordsign { color : #C04600 } .superscript { font-size : 4 } .subscript { font-size : 4 } .comment { color : Green } .constructor { color : Blue } .string { color : Maroon } .warning { color : Red ; font-weight : bold } .info { margin-left : 3em; margin-right : 3em } .title1 { font-size : 20pt ; background-color : #416DFF } .title2 { font-size : 20pt ; background-color : #418DFF } .title3 { font-size : 20pt ; background-color : #41ADFF } .title4 { font-size : 20pt ; background-color : #41CDFF } .title5 { font-size : 20pt ; background-color : #41EDFF } .title6 { font-size : 20pt ; background-color : #41FFFF } body { background-color : White } tr { background-color : White } # .doc { background-color :#aaeeff } .doc { background-color :#66ff66 } rocq-9.2.0/tools/coqdoc/tokens.ml000066400000000000000000000140021516144147600167410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* None with | Some tt' -> CharMap.add c (insert tt' (i + 1)) (CharMap.remove c tt.branch) | None -> let tt' = {node = None; branch = CharMap.empty} in CharMap.add c (insert tt' (i + 1)) tt.branch in { node = tt.node; branch = br } in insert ttree 0 (* Removes a string from a dictionary: returns an equal dictionary if the word not present. *) let ttree_remove ttree str = let rec remove tt i = if i == String.length str then {node = None; branch = tt.branch} else let c = str.[i] in let br = match try Some (CharMap.find c tt.branch) with Not_found -> None with | Some tt' -> CharMap.add c (remove tt' (i + 1)) (CharMap.remove c tt.branch) | None -> tt.branch in { node = tt.node; branch = br } in remove ttree 0 let ttree_descend ttree c = CharMap.find c ttree.branch let ttree_find ttree str = let rec proc_rec tt i = if i == String.length str then tt else proc_rec (CharMap.find str.[i] tt.branch) (i+1) in proc_rec ttree 0 (*s Parameters of the translation automaton *) type out_function = bool -> bool -> Index.index_entry option -> string -> unit let token_tree = ref (ref empty_ttree) let outfun = ref (fun _ _ _ _ -> failwith "outfun not initialized") (*s Translation automaton *) let buff = Buffer.create 4 let flush_buffer was_symbolchar tag tok = let hastr = String.length tok <> 0 in if hastr then !outfun false was_symbolchar tag tok; if Buffer.length buff <> 0 then !outfun true (if hastr then not was_symbolchar else was_symbolchar) tag (Buffer.contents buff); Buffer.clear buff type sublexer_state = | Neutral | Buffering of bool * Index.index_entry option * string * ttree let translation_state = ref Neutral let buffer_char is_symbolchar ctag c = let rec aux = function | Neutral -> restart_buffering () | Buffering (was_symbolchar,tag,translated,tt) -> if tag <> ctag then (* A strong tag comes from Rocq; if different Rocq tags *) (* hence, we don't try to see the chars as part of a single token *) let translated = match tt.node with | Some tok -> Buffer.clear buff; tok | None -> translated in flush_buffer was_symbolchar tag translated; restart_buffering () else begin (* If we change the category of characters (symbol vs ident) *) (* we accept this as a possible token cut point and remember the *) (* translated token up to that point *) let translated = if is_symbolchar <> was_symbolchar then match tt.node with | Some tok -> Buffer.clear buff; tok | None -> translated else translated in (* We try to make a significant token from the current *) (* buffer and the new character *) try let tt = ttree_descend tt c in Buffer.add_char buff c; Buffering (is_symbolchar,ctag,translated,tt) with Not_found -> (* No existing translation for the given set of chars *) if is_symbolchar <> was_symbolchar then (* If we changed the category of character read, we accept it *) (* as a possible cut point and restart looking for a translation *) (flush_buffer was_symbolchar tag translated; restart_buffering ()) else (* If we did not change the category of character read, we do *) (* not want to cut arbitrarily in the middle of the sequence of *) (* symbol characters or identifier characters *) (Buffer.add_char buff c; Buffering (is_symbolchar,tag,translated,empty_ttree)) end and restart_buffering () = let tt = try ttree_descend !(!token_tree) c with Not_found -> empty_ttree in Buffer.add_char buff c; Buffering (is_symbolchar,ctag,"",tt) in translation_state := aux !translation_state let output_tagged_ident_string s = for i = 0 to String.length s - 1 do buffer_char false None s.[i] done let output_tagged_symbol_char tag c = buffer_char true tag c let flush_sublexer () = match !translation_state with | Neutral -> () | Buffering (was_symbolchar,tag,translated,tt) -> let translated = match tt.node with | Some tok -> Buffer.clear buff; tok | None -> translated in flush_buffer was_symbolchar tag translated; translation_state := Neutral (* Translation not using the automaton *) let translate s = try (ttree_find !(!token_tree) s).node with Not_found -> None rocq-9.2.0/tools/coqdoc/tokens.mli000066400000000000000000000064071516144147600171240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> string -> ttree (* Remove a translation from a dictionary: returns an equal dictionary if the word not present *) val ttree_remove : ttree -> string -> ttree (* Translate a string *) val translate : string -> string option (* Sublexer automaton *) (* The sublexer buffers the chars it receives; if after some time, it recognizes that a sequence of chars has a translation in the current dictionary, it replaces the buffer by the translation *) (* Received chars can come with a "tag" (usually made from informations from the globalization file). A sequence of chars can be considered a word only, if all chars have the same "tag". Rules for cutting words are the following: - in a sequence like "**" where * is in the dictionary but not **, "**" is not translated; otherwise said, to be translated, a sequence must not be surrounded by other symbol-like chars - in a sequence like "<>_h*", where <>_h is in the dictionary, the translation is done because the switch from a letter to a symbol char is an acceptable cutting point - in a sequence like "<>_ha", where <>_h is in the dictionary, the translation is not done because it is considered that h and a are not separable (however, if h and a have different tags, and h has the same tags as <, > and _, the translation happens) - in a sequence like "<>_ha", where <> but not <>_h is in the dictionary, the translation is done for <> and _ha is considered independently because the switch from a symbol char to a letter is considered to be an acceptable cutting point - the longest-word rule applies: if both <> and <>_h are in the dictionary, "<>_h" is one word and gets translated *) (* Warning: do not output anything on output channel in between a call to [output_tagged_*] and [flush_sublexer]!! *) type out_function = bool (* needs escape *) -> bool (* it is a symbol, not a pure ident *) -> Index.index_entry option (* the index type of the token if any *) -> string -> unit (* This must be initialized before calling the sublexer *) val token_tree : ttree ref ref val outfun : out_function ref (* Process an ident part that might be a symbol part *) val output_tagged_ident_string : string -> unit (* Process a non-ident char (possibly equipped with a tag) *) val output_tagged_symbol_char : Index.index_entry option -> char -> unit (* Flush the buffered content of the lexer using [outfun] *) val flush_sublexer : unit -> unit rocq-9.2.0/tools/coqwc.ml000066400000000000000000000013341516144147600153060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* "low" | High -> "high" let priority_of_string = function | "low" -> Low | "high" -> High | _ -> raise (Invalid_argument "priority_of_string") type request = | Hello of priority | Get of int | TryGet of int | GiveBack of int | Ping type response = | Tokens of int | Noluck | Pong of int * int * int exception ParseError (* make it work with telnet: strip trailing \r *) let strip_r s = let len = String.length s in if s.[len - 1] <> '\r' then s else String.sub s 0 (len - 1) let positive_int_of_string n = try let n = int_of_string n in if n <= 0 then raise ParseError else n with Invalid_argument _ | Failure _ -> raise ParseError let parse_request s = if debug then Printf.eprintf "parsing '%s'\n" s; match Str.split (Str.regexp " ") (strip_r s) with | [ "HELLO"; "LOW" ] -> Hello Low | [ "HELLO"; "HIGH" ] -> Hello High | [ "GET"; n ] -> Get (positive_int_of_string n) | [ "TRYGET"; n ] -> TryGet (positive_int_of_string n) | [ "GIVEBACK"; n ] -> GiveBack (positive_int_of_string n) | [ "PING" ] -> Ping | _ -> raise ParseError let parse_response s = if debug then Printf.eprintf "parsing '%s'\n" s; match Str.split (Str.regexp " ") (strip_r s) with | [ "TOKENS"; n ] -> Tokens (positive_int_of_string n) | [ "NOLUCK" ] -> Noluck | [ "PONG"; n; m; p ] -> let n = try int_of_string n with Failure _ -> raise ParseError in let m = try int_of_string m with Failure _ -> raise ParseError in let p = try int_of_string p with Failure _ -> raise ParseError in Pong (n,m,p) | _ -> raise ParseError let print_request = function | Hello Low -> "HELLO LOW\n" | Hello High -> "HELLO HIGH\n" | Get n -> Printf.sprintf "GET %d\n" n | TryGet n -> Printf.sprintf "TRYGET %d\n" n | GiveBack n -> Printf.sprintf "GIVEBACK %d\n" n | Ping -> "PING\n" let print_response = function | Tokens n -> Printf.sprintf "TOKENS %d\n" n | Noluck -> "NOLUCK\n" | Pong (n,m,p) -> Printf.sprintf "PONG %d %d %d\n" n m p let connect s = try match Str.split (Str.regexp ":") s with | [ h; p ] -> let open Unix in let s = socket PF_INET SOCK_STREAM 0 in connect s (ADDR_INET (inet_addr_of_string h,int_of_string p)); Some s | _ -> None with Unix.Unix_error _ -> None let manager = ref None let option_map f = function None -> None | Some x -> Some (f x) let init p = try let sock = try Sys.getenv "ROCQWORKMGR_SOCK" with Not_found -> Sys.getenv "COQWORKMGR_SOCK" in manager := option_map (fun s -> let cout = Unix.out_channel_of_descr s in set_binary_mode_out cout true; let cin = Unix.in_channel_of_descr s in set_binary_mode_in cin true; output_string cout (print_request (Hello p)); flush cout; cin, cout) (connect sock) with Not_found | End_of_file -> () let with_manager f g = try match !manager with | None -> f () | Some (cin, cout) -> g cin cout with | ParseError | End_of_file -> manager := None; f () let get n = with_manager (fun () -> n) (fun cin cout -> output_string cout (print_request (Get n)); flush cout; let l = input_line cin in match parse_response l with | Tokens m -> m | _ -> raise (Failure "coqworkmgr protocol error")) let tryget n = with_manager (fun () -> Some n) (fun cin cout -> output_string cout (print_request (TryGet n)); flush cout; let l = input_line cin in match parse_response l with | Tokens m -> Some m | Noluck -> None | _ -> raise (Failure "coqworkmgr protocol error")) let giveback n = with_manager (fun () -> ()) (fun cin cout -> output_string cout (print_request (GiveBack n)); flush cout) rocq-9.2.0/tools/coqworkmgr/coqworkmgrApi.mli000066400000000000000000000032361516144147600213660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string val priority_of_string : string -> priority (* Default priority *) val default_async_proofs_worker_priority : priority (* Connects to a work manager if any. If no worker manager, then -async-proofs-j and -async-proofs-tac-j are used *) val init : priority -> unit (* blocking *) val get : int -> int (* not blocking *) val tryget : int -> int option val giveback : int -> unit (* Low level *) type request = | Hello of priority | Get of int | TryGet of int | GiveBack of int | Ping type response = | Tokens of int | Noluck | Pong of int * int * int (* cur, max, pid *) val connect : string -> Unix.file_descr option exception ParseError (* Intended to be used with input_line and output_string *) val parse_request : string -> request val parse_response : string -> response val print_request : request -> string val print_response : response -> string rocq-9.2.0/tools/coqworkmgr/dune000066400000000000000000000007141516144147600167120ustar00rootroot00000000000000(library (name coqworkmgrApi) (public_name rocq-runtime.coqworkmgrapi) (modules coqworkmgrApi) (wrapped false) (libraries str unix)) (deprecated_library_name (old_public_name coq-core.coqworkmgrapi) (new_public_name rocq-runtime.coqworkmgrapi)) (library (name rocqworkmgr) (modules rocqworkmgr) (libraries coqworkmgrApi)) (executable (name coqworkmgr) (public_name coqworkmgr) (package coq-core) (modules coqworkmgr) (libraries rocqworkmgr)) rocq-9.2.0/tools/coqworkmgr/rocqworkmgr.ml000066400000000000000000000154431516144147600207500ustar00rootroot00000000000000 open CoqworkmgrApi let debug = ref false type party = { sock : Unix.file_descr; cout : out_channel; mutable tokens : int; priority : priority; } let answer party msg = output_string party.cout (print_response msg); flush party.cout let mk_socket_channel () = let open Unix in let s = socket PF_INET SOCK_STREAM 0 in bind s (ADDR_INET (inet_addr_loopback,0)); listen s 1; match getsockname s with | ADDR_INET(host, port) -> s, string_of_inet_addr host ^":"^ string_of_int port | _ -> assert false module Queue : sig type t val is_empty : t -> bool val push : int * party -> t -> unit val pop : t -> int * party val create : unit -> t end = struct type t = (int * party) list ref let create () = ref [] let is_empty q = !q = [] let rec split acc = function | [] -> List.rev acc, [] | (_, { priority = Low }) :: _ as l -> List.rev acc, l | x :: xs -> split (x :: acc) xs let push (_,{ priority } as item) q = if priority = Low then q := !q @ [item] else let high, low = split [] !q in q := high @ (item :: low) let pop q = match !q with x :: xs -> q := xs; x | _ -> assert false end let read_fd fd s ~off ~len = let rec loop () = try Unix.read fd s off len with Unix.Unix_error(Unix.EAGAIN,_,_) -> loop () in loop () let really_read_fd fd s off len = let i = ref 0 in while !i < len do let off = off + !i in let len = len - !i in let r = read_fd fd s ~off ~len in if r = 0 then raise End_of_file; i := !i + r done let raw_input_line fd = try let b = Buffer.create 80 in let s = Bytes.make 1 '\000' in let endl = Bytes.of_string "\n" in let endr = Bytes.of_string "\r" in while Bytes.compare s endl <> 0 do really_read_fd fd s 0 1; if Bytes.compare s endl <> 0 && Bytes.compare s endr <> 0 then Buffer.add_bytes b s; done; Buffer.contents b with Unix.Unix_error _ -> raise End_of_file let accept s = let cs, _ = Unix.accept s in let cout = Unix.out_channel_of_descr cs in set_binary_mode_out cout true; match parse_request (raw_input_line cs) with | Hello p -> { sock=cs; cout; tokens=0; priority=p } | _ -> (try Unix.close cs with _ -> ()); raise End_of_file let parties = ref [] let max_tokens = ref 2 let cur_tokens = ref 0 let queue = Queue.create () let rec allocate n party = let extra = min n (!max_tokens - !cur_tokens) in cur_tokens := !cur_tokens + extra; party.tokens <- party.tokens + extra; answer party (Tokens extra) and de_allocate n party = let back = min party.tokens n in party.tokens <- party.tokens - back; cur_tokens := min (!cur_tokens - back) !max_tokens; eventually_dequeue () and eventually_dequeue () = if Queue.is_empty queue || !cur_tokens >= !max_tokens then () else let req, party = Queue.pop queue in if List.exists (fun { sock } -> sock = party.sock) !parties then allocate req party else eventually_dequeue () let chat s = let party = try List.find (fun { sock } -> sock = s) !parties with Not_found -> Printf.eprintf "Internal error"; exit 1 in try match parse_request (raw_input_line party.sock) with | Get n -> if !cur_tokens < !max_tokens then allocate n party else Queue.push (n,party) queue | TryGet n -> if !cur_tokens < !max_tokens then allocate n party else answer party Noluck | GiveBack n -> de_allocate n party | Ping -> answer party (Pong (!cur_tokens,!max_tokens,Unix.getpid ())); raise End_of_file | Hello _ -> raise End_of_file with Failure _ | ParseError | Sys_error _ | End_of_file -> (try Unix.close party.sock with _ -> ()); parties := List.filter (fun { sock } -> sock <> s) !parties; de_allocate party.tokens party; eventually_dequeue () let check_alive s = match CoqworkmgrApi.connect s with | Some s -> let cout = Unix.out_channel_of_descr s in set_binary_mode_out cout true; output_string cout (print_request (Hello Low)); flush cout; output_string cout (print_request Ping); flush cout; begin match Unix.select [s] [] [] 1.0 with | [s],_,_ -> let cin = Unix.in_channel_of_descr s in set_binary_mode_in cin true; begin match parse_response (input_line cin) with | Pong (n,m,pid) -> n, m, pid | _ -> raise Not_found end | _ -> raise Not_found end | _ -> raise Not_found let parse_args argv = let args = [ "-j",Arg.Set_int max_tokens, "max number of concurrent jobs"; "-d",Arg.Set debug, "do not detach (debug)"] in let usage = "Prints on stdout an env variable assignment to be picked up by rocq\n"^ "instances in order to limit the maximum number of concurrent workers.\n"^ "The default value is 2.\n"^ "Usage:" in try Arg.parse_argv argv args (fun extra -> Arg.usage args ("Unexpected argument "^extra^".\n"^usage)) usage with | Arg.Bad msg -> Printf.eprintf "%s" msg; exit 2 | Arg.Help msg -> Printf.printf "%s" msg; exit 0 let main ~prog argv = parse_args (Array.of_list (prog::argv)); try let sock = let rocq = "ROCQWORKMGR_SOCK" in let coq = "COQWORKMGR_SOCK" in try Sys.getenv rocq with Not_found -> let s = Sys.getenv coq in Printf.eprintf "Deprecated environment variable %s, use %s instead.\n%!" coq rocq; s in if !debug then Printf.eprintf "Contacting %s\n%!" sock; let cur, max, pid = check_alive sock in Printf.printf "ROCQWORKMGR_SOCK=%s\n%!" sock; Printf.eprintf "rocqworkmgr already up and running (pid=%d, socket=%s, j=%d/%d)\n%!" pid sock cur max; exit 0 with Not_found | Failure _ | Invalid_argument _ | Unix.Unix_error _ -> if !debug then Printf.eprintf "No running instance. Starting a new one\n%!"; let master, str = mk_socket_channel () in if not !debug then begin let pid = Unix.fork () in if pid <> 0 then begin Printf.printf "ROCQWORKMGR_SOCK=%s\n%!" str; exit 0 end else begin ignore(Unix.setsid ()); Unix.close Unix.stdin; Unix.close Unix.stdout; end; end else begin Printf.printf "ROCQWORKMGR_SOCK=%s\n%!" str; end; Sys.catch_break true; try while true do if !debug then Printf.eprintf "Status: #parties=%d tokens=%d/%d \n%!" (List.length !parties) !cur_tokens !max_tokens; let socks = master :: List.map (fun { sock } -> sock) !parties in let r, _, _ = Unix.select socks [] [] (-1.0) in List.iter (fun s -> if s = master then begin try parties := accept master :: !parties with _ -> () end else chat s) r done; exit 0 with Sys.Break -> if !parties <> [] then begin Printf.eprintf "Some rocq processes still need me\n%!"; exit 1; end else exit 0 rocq-9.2.0/tools/coqworkmgr/rocqworkmgr.mli000066400000000000000000000013221516144147600211100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> unit rocq-9.2.0/tools/dune000066400000000000000000000022451516144147600145200ustar00rootroot00000000000000(install (section lib) (package rocq-runtime) (files (CoqMakefile.in as tools/CoqMakefile.in))) (install (section libexec) (package rocq-runtime) (files (TimeFileMaker.py as tools/TimeFileMaker.py) (make-one-time-file.py as tools/make-one-time-file.py) (make-both-time-files.py as tools/make-both-time-files.py) (make-both-single-timing-files.py as tools/make-both-single-timing-files.py))) (library (name rocqmakefile) (modules rocqmakefile) (libraries rocq-runtime.boot rocq-runtime.lib)) (executable (name coq_makefile) (public_name coq_makefile) (package coq-core) (modules coq_makefile) (libraries rocqmakefile)) ; Bare-bones mllib/mlpack parser (executable (name ocamllibdep) (public_name ocamllibdep) (package rocq-runtime) (modules ocamllibdep) (libraries unix)) (ocamllex ocamllibdep) (library (name rocqwc) (modules rocqwc) (libraries)) (executable (name coqwc) (public_name coqwc) (package coq-core) (modules coqwc) (libraries rocqwc)) (ocamllex rocqwc) (library (name rocqtex) (modules rocqtex) (libraries str)) (executables (names coq_tex) (public_names coq-tex) (package coq-core) (modules coq_tex) (libraries rocqtex)) rocq-9.2.0/tools/dune_rule_gen/000077500000000000000000000000001516144147600164525ustar00rootroot00000000000000rocq-9.2.0/tools/dune_rule_gen/LICENSE000066400000000000000000000022061516144147600174570ustar00rootroot00000000000000The MIT License Copyright (c) 2016 Jane Street Group, LLC Copyright (c) 2018-2019 Mines ParisTech Copyright (c) 2019-2022 Inria Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rocq-9.2.0/tools/dune_rule_gen/arg.ml000066400000000000000000000011141516144147600175520ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) type t = A of string | Path of Path.t let adjust ~lvl = function | A arg -> A arg | Path p -> Path (Path.adjust ~lvl p) let to_string = function A arg -> arg | Path p -> Path.to_string p module List = struct let to_string args = List.map to_string args |> String.concat " " end rocq-9.2.0/tools/dune_rule_gen/arg.mli000066400000000000000000000007761516144147600177400ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) type t = A of string | Path of Path.t (** Similar to [Path.adjust] , noop for [A] case *) val adjust : lvl:int -> t -> t val to_string : t -> string module List : sig val to_string : t list -> string end rocq-9.2.0/tools/dune_rule_gen/coq_module.ml000066400000000000000000000056741516144147600211470ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (* (c) MINES ParisTech 2018-2019 *) (* (c) INRIA 2020-2022 *) (* Written by: Emilio JesΓΊs Gallego Arias *) (* Written by: Rudi Grinberg *) (************************************************************************) let with_timing = true type t = { source : Path.t ; prefix : string list ; name : string } let pp fmt { source; prefix; name } = Format.fprintf fmt "@[{%s : %a}@]" (String.concat "." (prefix@[name]) ) Path.pp source let make ~source ~prefix ~name = { source; prefix; name } let source { source; _ } = source let prefix { prefix; _ } = prefix let mod_to_obj ~ext { name; _ } = name ^ ext module Rule_type = struct type native = Disabled | Coqc | CoqNative type t = | Regular of { native : native } let native_coqc = function | Regular { native = Coqc } -> true | Regular { native = CoqNative } | Regular { native = Disabled } -> false end let native_obj_files ~install ~tname { prefix; name; _ } = let base_theory = tname in let native_base = "N" ^ String.concat "_" (base_theory @ prefix @ [name]) in let prefix file = if install then Filename.concat ".coq-native" file else file in [ prefix @@ native_base ^ ".cmi"; prefix @@ native_base ^ ".cmxs" ] let base_obj_files coq_module = [ mod_to_obj coq_module ~ext:".glob" ; mod_to_obj coq_module ~ext:".vo" ] let obj_files ~tname ~rule coq_module = let native = Rule_type.native_coqc rule in let native_objs = if native then native_obj_files ~tname ~install:false coq_module else [] in let timing_objs = if with_timing then [ mod_to_obj coq_module ~ext:".timing" ] else [] in timing_objs @ native_objs @ base_obj_files coq_module let prefix_to_dir = String.concat Filename.dir_sep let native_install_files ~tname ~rule coq_module = match rule with | Rule_type.Regular { native = CoqNative } | Regular { native = Coqc } -> native_obj_files ~tname ~install:false coq_module , native_obj_files ~tname ~install:true coq_module | Regular { native = Disabled } -> [], [] (* quick/vio woes... it does produce a different set of targets than regular compilation *) let base_install_files coq_module = mod_to_obj coq_module ~ext:".v" :: base_obj_files coq_module let install_files ~tname ~rule coq_module = let src_base = base_install_files coq_module in let src_native, dst_native = native_install_files ~tname ~rule coq_module in let src = src_base @ src_native in let ppath = prefix_to_dir (prefix coq_module) in let dst = List.map (Filename.concat ppath) (src_base @ dst_native) in List.combine src dst let native_obj_files = native_obj_files ~install:false rocq-9.2.0/tools/dune_rule_gen/coq_module.mli000066400000000000000000000026261516144147600213120ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (* (c) MINES ParisTech 2018-2019 *) (* (c) INRIA 2020-2022 *) (* Written by: Emilio JesΓΊs Gallego Arias *) (* Written by: Rudi Grinberg *) (************************************************************************) type t val make : source:Path.t -> prefix:string list -> name:string -> t val source : t -> Path.t val prefix : t -> string list val prefix_to_dir : string list -> string (** We support two build modes for now *) module Rule_type : sig type native = Disabled | Coqc | CoqNative type t = | Regular of { native : native } val native_coqc : t -> bool end (** Return the native object files for a module *) val native_obj_files : tname:string list -> t -> string list (** Return the object files for a module *) val obj_files : tname:string list -> rule:Rule_type.t -> t -> string list (** Return pairs of object files and install locations *) val install_files : tname:string list -> rule:Rule_type.t -> t -> (string * string) list val pp : Format.formatter -> t -> unit val with_timing : bool rocq-9.2.0/tools/dune_rule_gen/coq_rules.ml000066400000000000000000000265221516144147600210070ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (* (c) MINES ParisTech 2018-2019 *) (* (c) INRIA 2020-2022 *) (* Written by: Emilio JesΓΊs Gallego Arias *) (* Written by: Rudi Grinberg *) (************************************************************************) (* coq_rules: generate dune build rules for Coq's test-suite and init *) (* Originally written by Emilio JesΓΊs Gallego Arias and Rudi Grinberg for Dune's coq_rules.ml , which followed a first coq_dune.exe implementation by Emilio JesΓΊs Gallego Arias *) (* note that this file closely follows Dune's own coq_rules.ml [and eventually they could be merged], hence the license. Other modules such as Arg or Path are straight copies from Dune's *) let _debug = false module FlagUtil = struct (* Native flag *) let findlib_native_dir () = try Findlib.package_directory ("rocq-runtime.kernel") |> Path.make with Fl_package_base.No_such_package (p,_) -> raise (Invalid_argument ("failed to locate Coq kernel package in split build mode: " ^ p)) let local_native_dir = Path.make "kernel/.kernel.objs/byte" let kernel_cmi_dir ~split () = if split then findlib_native_dir () else local_native_dir end (* dep to vo *) let path_of_dep ~vo_ext dep = let open Coqdeplib.Dep_info in let file = match dep with | Dep.Require dep -> dep ^ vo_ext | Dep.Ml dep-> dep ^ ".cmxs" | Dep.Other dep -> dep in (* when called by dune, the cmxs and META files are in ../install/... relative to cwd (= _build/default) but the generated dune file will be moved to ../theories so adjusting the path to be relative to the .v won't work (it would be relative to the .v in workspace_root/_build/default/theories but dune would read it as relative to the .v in project_root/theories, the number of .. to insert to get to project_root doesn't match) *) let file = if CString.is_prefix ".." file then (Filename.concat "%{workspace_root}" "_build") ^ String.sub file 2 (String.length file - 2) else file in Path.make file (* dep to cmi, this is hacky, cleanup. A better way is to keep a reverse map from files to modules *) let dot_path s = String.equal s "." || String.equal s ".." let not_dot_path s = not (dot_path s) let translate_to_native ~tname dep = let dir = Filename.dirname dep in let components = String.split_on_char '/' dep |> List.filter not_dot_path in let name = String.concat "_" (tname @ components) in Filename.concat dir ("N" ^ name ^ ".cmi") (* Case for prelude.vo *) let not_dot_path_or_coqlib s = not (dot_path s) && not (String.equal "theories" s) let translate_boot_to_native dep = let dep = Path.to_string dep |> Filename.remove_extension in let dir = Filename.dirname dep in let components = String.split_on_char '/' dep |> List.filter not_dot_path_or_coqlib in let name = String.concat "_" ("Corelib"::components) in Filename.concat dir ("N" ^ name ^ ".cmi") |> Path.make let cmi_of_dep ~tname dep = let open Coqdeplib.Dep_info in let file = match dep with | Dep.Require dep -> Some (translate_to_native ~tname dep) | Dep.Ml _dep-> None | Dep.Other _ -> None in Option.map Path.make file module Theory = struct (** A theory binding; directories should be relative to Coq's sources root *) type t = { directory : Path.t (** Directory of the theory *) ; dirname: string list (** Coq's logical path *) ; implicit : bool (** Use -R or -Q *) ; deps : string list; (** Adds as -Q user-contrib/X X *) } let args { directory; dirname; implicit; deps } = let barg = if implicit then "-R" else "-Q" in Arg.[ A barg; Path directory; A (String.concat "." dirname) ] @ List.flatten (deps |> List.map (fun dep -> Arg.[A "-Q"; Path (Path.make @@ "user-contrib"^Filename.dir_sep^dep); A dep])) end (** [Regular _] contains the info about the core theory, see documentation in the .mli file *) module Boot_type = struct type t = Corelib | NoInit | Regular of { corelib : Theory.t; noinit : bool } end (* Context for a Coq theory *) module Context = struct module Flags = struct type t = { user : Arg.t list ; loadpath : Arg.t list ; common : Arg.t list ; native_common : Arg.t list ; native_coqc : Arg.t list } end type t = { theory : Theory.t ; flags : Flags.t (* flags *) ; rule : Coq_module.Rule_type.t (* rule kind *) ; boot : Boot_type.t (* type of library *) ; dep_info : Dep_info.t ; async_deps : string list (* whether coqc needs the workers *) ; root_lvl : int } let native_common ~split () = let path_coq_kernel_cmi = FlagUtil.kernel_cmi_dir ~split () in [ Arg.A "-nI"; Path path_coq_kernel_cmi ; A "-native-output-dir"; A "." ] let native_coqc ~native_common ~native = let native_string = if native then "on" else "off" in (if native then native_common else []) @ Arg.[ A "-w"; A "-deprecated-native-compiler-option" ; A "-native-compiler"; A native_string ] (* XXX: we could put the workers here, but they need a complete OCaml runtime so this is better *) let build_async_deps = ["(package rocq-runtime)"] (* args are for coqdep *) let build_dep_info ~coqdep_args dir_info = Dep_info.make ~args:coqdep_args ~dir_info let make ~root_lvl ~theory ~user_flags ~boot ~rule ~async ~dir_info ~split = let flags = let boot_paths = match boot with | Boot_type.NoInit -> [] | Corelib -> Theory.args theory | Regular { corelib; noinit = _ } -> Theory.args corelib @ Theory.args theory in let loadpath = Arg.(A "-boot") :: boot_paths in let native_common = native_common ~split () in let native_coqc = native_coqc ~native_common ~native:(Coq_module.Rule_type.native_coqc rule) in let common = Arg.[ A "-w"; A "+default"; A "-q" ] in { Flags.user = user_flags; common; loadpath; native_common; native_coqc } in (* coqdep and dep info *) let coqdep_args = flags.loadpath in let dep_info = build_dep_info ~coqdep_args dir_info in let async_deps = if async then build_async_deps else [] in { theory; flags; rule; boot; dep_info; async_deps; root_lvl } end (* Return flags and deps to inject *) let prelude_path = "Init/Prelude.vo" (* Return extra flags and deps for a concrete file; the case of interest is to determine when a file needs [-nonit]. If it doesn't, we must inject the [Init/Prelude] dependency. Note that we can't compute this in Context.make due to the per-file check for "Init" *) let boot_module_setup ~cctx coq_module = match cctx.Context.boot with | Boot_type.NoInit -> [Arg.A "-noinit"], [] | Corelib -> (match Coq_module.prefix coq_module with | ["Init"] -> [ Arg.A "-noinit" ], [] | _ -> [ ], [ Path.relative (Path.relative (Path.make "theories") "Corelib") prelude_path ] ) | Regular { corelib; noinit } -> if noinit then [ Arg.A "-noinit" ], [] else [], [ Path.relative corelib.directory prelude_path ] (* rule generation for a module *) let module_rule ~(cctx : Context.t) coq_module = let tname, rule = cctx.theory.dirname, cctx.rule in (* retrieve deps *) let vfile = Coq_module.source coq_module in let vo_ext = ".vo" in let vfile_deps = Dep_info.lookup ~dep_info:cctx.dep_info vfile |> List.map (path_of_dep ~vo_ext) in (* handle -noinit, inject prelude.vo if needed *) let boot_flags, boot_deps = boot_module_setup ~cctx coq_module in let coqc_flags = cctx.flags.loadpath @ cctx.flags.user @ cctx.flags.common @ cctx.flags.native_coqc in let vfile_deps, flags = boot_deps @ vfile_deps, boot_flags @ coqc_flags in let vfile_base = Path.basename vfile in let timeflags = if Coq_module.with_timing then Arg.[A "-time-file"; Path Path.(replace_ext vfile ~ext:".timing")] else [] in (* Adjust paths *) let lvl = cctx.root_lvl + (Coq_module.prefix coq_module |> List.length) in let flags = (* flags are relative to the root path *) Arg.List.to_string (flags @ timeflags) in let deps = List.map (Path.adjust ~lvl) vfile_deps |> List.map Path.to_string in (* Depend on the workers if async *) let deps = cctx.async_deps @ deps in (* Build rule *) let updir = Path.(to_string (adjust ~lvl (make "."))) in let action = Format.asprintf "(chdir %s (run rocq c %s %%{dep:%s}))" updir flags vfile_base in let targets = Coq_module.obj_files ~tname ~rule coq_module in let alias = None in { Dune_file.Rule.targets; deps; action; alias } (* Helper for Dir_info to Subdir *) let gen_rules ~dir_info ~cctx ~f = let f ~prefix sub_acc mods = let subdir = Coq_module.prefix_to_dir prefix in let payload = List.map (f ~cctx) mods in Dune_file.Subdir.{ subdir; payload } :: sub_acc in Dir_info.fold ~f ~init:[] dir_info (* Has to be called in the current dir *) let vo_rules ~dir_info ~cctx = gen_rules ~dir_info ~cctx ~f:module_rule (* rule generation for .vo -> .{cmi,cmxs} *) let coqnative_module_rule ~(cctx: Context.t) coq_module = let tname = cctx.theory.dirname in (* deps *) let vfile = Coq_module.source coq_module in let vofile_deps = Dep_info.lookup ~dep_info:cctx.dep_info vfile |> List.filter_map (cmi_of_dep ~tname) in (* base [maybe this should go to coq_module] *) let vofile_base = Path.(replace_ext ~ext:".vo" vfile |> basename) in (* handle -noinit, inject prelude.vo if needed *) let boot_flags, boot_deps = boot_module_setup ~cctx coq_module in (* Improve this code *) let boot_deps = List.map translate_boot_to_native boot_deps in (* Should we pass user and common flags here? They are ignored as of today so we don't *) let flags = boot_flags @ cctx.flags.loadpath @ cctx.flags.native_common in let vofile_deps = boot_deps @ vofile_deps in (* Adjust paths *) let lvl = cctx.root_lvl + (Coq_module.prefix coq_module |> List.length) in let flags = (* flags are relative to the root path *) Arg.List.to_string flags in let deps = List.map (Path.adjust ~lvl) vofile_deps |> List.map Path.to_string in (* Build rule *) let updir = Path.(to_string (adjust ~lvl (make "."))) in let action = Format.asprintf "(chdir %s (run coqnative %s %s))" updir flags vofile_base in let targets = Coq_module.native_obj_files ~tname coq_module in let deps = vofile_base :: deps in let alias = None in { Dune_file.Rule.targets; deps; action; alias } let coqnative_rules ~dir_info ~cctx = gen_rules ~dir_info ~cctx ~f:coqnative_module_rule let install_rule ~(cctx : Context.t) coq_module = let tname, rule = cctx.theory.dirname, cctx.rule in let dst_base = match tname with | ["Corelib"] -> Filename.concat "coq" "theories" | _ -> Filename.concat "coq" @@ Filename.concat "user-contrib" @@ (String.concat "." tname) in let files = Coq_module.install_files ~tname ~rule coq_module |> List.map (fun (src,dst) -> src, Filename.concat dst_base dst) in (* May need to woraround invalid empty `(install )` stanza if that happens *) Dune_file.Install.{ section = "lib_root"; package = "rocq-core"; files } let install_rules ~dir_info ~cctx = gen_rules ~dir_info ~cctx ~f:install_rule rocq-9.2.0/tools/dune_rule_gen/coq_rules.mli000066400000000000000000000050251516144147600211530ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (* (c) MINES ParisTech 2018-2019 *) (* (c) INRIA 2020-2022 *) (* Written by: Emilio JesΓΊs Gallego Arias *) (* Written by: Rudi Grinberg *) (************************************************************************) module Theory : sig (** A theory binding; directories should be relative to Coq's sources root *) type t = { directory : Path.t (** Directory of the theory *) ; dirname: string list (** Coq's logical path *) ; implicit : bool (** Use -R or -Q *) ; deps : string list (** Adds as -Q user-contrib/X X *) } end (** theory kind *) module Boot_type : sig type t = Corelib (** Standard library *) | NoInit (** Standalone library (without Coq's core lib, for example the prelude) *) | Regular of { corelib : Theory.t; noinit : bool } (** Regular library, qualified with -Q, [corelib] controls where the Corelib is. [noinit = true] only means there is no implicit dep on the prelude, it may still depend on Corelib (unlike [NoInit]). *) end module Context : sig type t (** *) val make : root_lvl:int -> theory:Theory.t -> user_flags:Arg.t list -> boot:Boot_type.t -> rule:Coq_module.Rule_type.t (* quick, native, etc... *) -> async:bool -> dir_info:Coq_module.t Dir_info.t (* contents of the directory scan *) -> split:bool (* whether we are building rocq-runtime + rocq-core or only rocq-core *) -> t end (** [gen_vo_rules root_lvl rule flags tname boot] Builds dune rules for the *current* directory, assuming that we will do [-R . tname]. The parameter [boot] controls the kind of the current theory. [root_lvl] tells the rule generator how many levels up the root Coq sources are. [flags] add extra flags to coqc, such as `-async on` *) val vo_rules : dir_info :Coq_module.t Dir_info.t -> cctx:Context.t -> Dune_file.Rule.t list Dune_file.Subdir.t list val coqnative_rules : dir_info :Coq_module.t Dir_info.t -> cctx:Context.t -> Dune_file.Rule.t list Dune_file.Subdir.t list val install_rules : dir_info :Coq_module.t Dir_info.t -> cctx:Context.t -> Dune_file.Install.t list Dune_file.Subdir.t list rocq-9.2.0/tools/dune_rule_gen/dep_info.ml000066400000000000000000000041261516144147600205720ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) module CD = Coqdeplib module Dep_map = Map.Make(Path) type t = CD.Dep_info.Dep.t list Dep_map.t (* What a pita OCaml's stdlib missing basic stuff ... *) let from_list l = List.fold_left (fun map { CD.Dep_info.name; deps } -> let name = Path.make name in let path = Path.add_extension ~ext:".v" name in Dep_map.add path deps map) Dep_map.empty l let debug_coqdep = false let debug = false let coqdep_register_file vAccu file = (* if debug then Format.eprintf "cd regfile: %s@\n%!" file; *) CD.Common.treat_file_command_line vAccu (Path.to_string file) (* From dir info + context *) let make ~args ~(dir_info : _ Dir_info.t) = let args = "-dyndep" :: "opt" :: List.map Arg.to_string args in if debug_coqdep then Format.eprintf "coqdep: %s@\n%!" (String.concat " " args); let args = Coqdeplib.Args.parse (Coqdeplib.Args.make ()) args in (* We are sane w.r.t. path separators *) let make_separator_hack = false in let rocqenv, st = CD.Common.init ~make_separator_hack args in (* we always use -boot *) assert (rocqenv = Boot); let st = Dir_info.fold dir_info ~init:st ~f:(fun ~prefix:_ vAccu files -> let files = List.map Coq_module.source files in List.fold_left coqdep_register_file vAccu files) in CD.Common.compute_deps st |> from_list let lookup ~dep_info file = if debug then Format.eprintf "lookup: %a@\n%!" Path.pp file; let file = Path.coqdep_fixup_dir file in Dep_map.find file dep_info let pp_binding fmt (s, _) = Format.fprintf fmt "%a" Path.pp s let lookup ~dep_info x = try lookup ~dep_info x with | Not_found -> if debug then begin Format.eprintf "@[%a@]@\n%!" (Format.pp_print_list pp_binding) (Dep_map.bindings dep_info); Format.eprintf "@[dep: %a@\n%!@]" Path.pp x end; raise Not_found rocq-9.2.0/tools/dune_rule_gen/dep_info.mli000066400000000000000000000011361516144147600207410ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) type t (** [make ~cctx:args ~base_dir ~dir_info] compute dependency information for Coq modules in [dir_info] *) val make : args:Arg.t list -> dir_info:Coq_module.t Dir_info.t -> t (** [lookup di filename] return deps of filename *) val lookup : dep_info:t -> Path.t -> Coqdeplib.Dep_info.Dep.t list rocq-9.2.0/tools/dune_rule_gen/dir_info.ml000066400000000000000000000047601516144147600206040ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) let debug = false (* Information about a directory containing .v files *) type 'a t = { prefix : string list (** prefix of the directory, [] when root *) ; children : 'a t list (** List of children, this could be scanned lazily *) ; modules : 'a list (** modules [without the .v suffix] *) } (* Scan a single directory *) let to_module ~dir ~prefix file = let source = Path.make (Filename.concat dir file) in let name = Filename.remove_extension file in Coq_module.make ~source ~prefix ~name let scan_dir ~prefix dir = let contents = Sys.readdir dir |> Array.to_list in let dirs, files = List.partition (fun f -> Filename.concat dir f |> Sys.is_directory) contents in let files = List.filter (fun f -> Filename.(check_suffix (concat dir f) ".v")) files in let modules = List.map (to_module ~dir ~prefix) files in dirs, modules (* Scan a tree *) let rec scan_subtree ~base_dir ~prefix children = let prefix = prefix @ [children] in scan ~prefix (Filename.concat base_dir children) and scan ~prefix base_dir = if debug then Format.eprintf "[debug] [scan] Enter: %s @\n%!" base_dir; let children, modules = scan_dir ~prefix base_dir in let children = List.map (scan_subtree ~base_dir ~prefix) children in { prefix; children; modules } let rec map ~(f : prefix:string list -> 'a -> 'b) di = { di with children = List.map (map ~f) di.children ; modules = List.map (f ~prefix:di.prefix) di.modules } let rec iter ~(f : prefix:string list -> 'a -> unit) di : unit = f ~prefix:di.prefix di.modules; List.iter (iter ~f) di.children let rec fold ~(f : prefix:string list -> 'b -> 'a list -> 'b) ~init di = let res = List.fold_left (fun init x -> fold ~f ~init x) init di.children in f ~prefix:di.prefix res di.modules let rec coq_modules { modules; children; _ } = modules @ List.concat (List.map coq_modules children) (* let rec fold ~(f : prefix:string list -> 'a -> 'b) di = *) let rec pp pp_module fmt { prefix; children; modules } = let open Format in fprintf fmt "@[ { prefix = %a; children = %a; modules = %a }@]" (pp_print_list pp_print_string) prefix (pp_print_list (pp pp_module)) children (pp_print_list pp_module) modules let pp = pp Coq_module.pp rocq-9.2.0/tools/dune_rule_gen/dir_info.mli000066400000000000000000000017711516144147600207540ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) (** Recursive scan of a directory *) type 'a t (** [scan ~prefix dir] scan for coq modules in dir [prefix] will inject a dir *) val scan : prefix:string list -> string -> Coq_module.t t (** [iter ~f dir_info] iterate contents, [prefix] denotes the sub-tree we are in *) val iter : f:(prefix:string list -> 'a list -> unit) -> 'a t -> unit (** [fold ~f ~init dir_info] fold over each folder's contents *) val fold : f:(prefix:string list -> 'b -> 'a list -> 'b) -> init:'b -> 'a t -> 'b (** Flatten the list of objects of a recursive scan *) val coq_modules : 'a t -> 'a list val pp : Format.formatter -> Coq_module.t t -> unit (* To remove *) val map : f:(prefix:string list -> 'a -> 'b) -> 'a t -> 'b t rocq-9.2.0/tools/dune_rule_gen/dune000066400000000000000000000003611516144147600173300ustar00rootroot00000000000000(library (name coq_dune) (modules :standard \ gen_rules) (flags :standard -w +a-40-42) (libraries rocq-runtime.coqdeplib findlib)) (executable (name gen_rules) (modules gen_rules) (flags :standard -w +a-40-42) (libraries coq_dune)) rocq-9.2.0/tools/dune_rule_gen/dune_file.ml000066400000000000000000000033011516144147600207330ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) module F = Format type 'a pp = Format.formatter -> 'a -> unit module Rule = struct type t = { targets : string list ; deps : string list ; action : string ; alias : string option } let pp_sep fmt () = F.fprintf fmt "@;" let ppl = F.pp_print_list ~pp_sep F.pp_print_string let pp_alias fmt = function | None -> () | Some alias -> F.fprintf fmt "(alias %s)@\n" alias let pp fmt { alias; targets; deps; action } = F.fprintf fmt "@[(rule@\n @[%a(targets @[%a@])@\n(deps @[%a@])@\n(action @[%a@])@])@]@\n" pp_alias alias ppl targets ppl deps F.pp_print_string action end module Install = struct type t = { section : string ; package : string ; files : (string * string) list (* (source as target) *) } let pp_install_file fmt (source, target) = F.fprintf fmt "(%s as %s)" source target let pp fmt { section; package; files } = F.fprintf fmt "@[(install@\n @[(section @[%s@])@\n(package @[%s@])@\n(files @[%a@])@])@]@\n" section package (F.pp_print_list pp_install_file) files end module Subdir = struct type 'a t = { subdir : string; payload : 'a } let pp ppf fmt { subdir; payload } = if String.equal subdir "" then ppf fmt payload else Fun.protect ~finally:(fun () -> F.fprintf fmt "@])@\n") (fun () -> F.fprintf fmt "(subdir %s@\n @[" subdir; ppf fmt payload) end rocq-9.2.0/tools/dune_rule_gen/dune_file.mli000066400000000000000000000014141516144147600211070ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) type 'a pp = Format.formatter -> 'a -> unit module Rule : sig type t = { targets : string list ; deps : string list ; action : string ; alias : string option } val pp : t pp end module Install : sig type t = { section : string ; package : string ; files : (string * string) list (* (source as target) *) } val pp : t pp end module Subdir : sig type 'a t = { subdir : string; payload : 'a } val pp : 'a pp -> 'a t pp end rocq-9.2.0/tools/dune_rule_gen/gen_rules.ml000066400000000000000000000102531516144147600207700ustar00rootroot00000000000000open! Coq_dune (* Coqnative overhead is more than 33% in build time :( :( *) (* in a 16-core system: - coqnative: real 2m29,860s user 19m44,997s sys 2m19,618s real 2m30,940s user 20m6,945s sys 2m22,057s - coqc -native-compiler on real 2m30,567s user 14m17,062s sys 1m47,661s real 2m29,008s user 14m15,293s sys 1m48,194s *) (* let native_mode = Coq_module.Rule_type.CoqNative *) let native_mode = Coq_module.Rule_type.Coqc let native = match Coq_config.native_compiler with | Coq_config.NativeOff -> Coq_module.Rule_type.Disabled | Coq_config.NativeOn _ -> native_mode (** arguments are [gen_rules theory_name dir flags] *) type args = { tname : string list; base_dir : string; async : bool; rule : Coq_module.Rule_type.t; split : bool; noinit : bool; user_flags : Arg.t list; dependencies : string list; } let parse_args () : args = match Array.to_list Sys.argv with | _ :: tname :: base_dir :: args -> let tname = String.split_on_char '.' tname in let _backtrace = [Arg.A "-d"; Arg.A "backtrace"] in let default = { base_dir; tname; async = false; split = false; noinit = false; rule = Coq_module.Rule_type.Regular { native }; user_flags = []; dependencies = []; } in let rec parse a = function | [] -> a | "-async" :: rest -> parse { a with async = true; user_flags = Arg.[A "-async-proofs"; A "on"] } rest | "-split" :: rest -> parse { a with split = true } rest | "-dep" :: d :: rest -> parse { a with dependencies = d :: a.dependencies } rest | "-noinit" :: rest -> parse { a with noinit = true } rest (* Dune will sometimes pass this option as "" *) | "" :: rest -> parse a rest | unknown :: _ -> raise (Invalid_argument unknown) in parse default args | _ -> raise (Invalid_argument "usage: gen_rules theory_name directory") let ppr fmt = List.iter (Dune_file.Rule.pp fmt) let ppi fmt = List.iter (Dune_file.Install.pp fmt) let main () = let { tname; base_dir; async; rule; user_flags; split; noinit; dependencies } = parse_args () in let root_lvl = List.length (String.split_on_char '/' base_dir) in let corelib = let directory = Path.relative (Path.make "theories") "Corelib" in Coq_rules.Theory.{ directory; dirname = ["Corelib"]; implicit = true; deps = [] } in (* usually the else case here is Ltac2, but other libraries could be handled as well *) let boot, implicit = if tname = ["Corelib"] then begin if noinit then CErrors.user_err Pp.(str "Corelib handles -noinit automatically."); Coq_rules.Boot_type.Corelib, true end else Coq_rules.Boot_type.Regular { corelib; noinit }, false in (* Rule generation *) let dir_info = Dir_info.scan ~prefix:[] base_dir in let directory = Path.make base_dir in let theory = Coq_rules.Theory.{ directory; dirname = tname; implicit; deps = dependencies } in let cctx = Coq_rules.Context.make ~root_lvl ~theory ~user_flags ~rule ~boot ~dir_info ~async ~split in let vo_rules = Coq_rules.vo_rules ~dir_info ~cctx in let install_rules = Coq_rules.install_rules ~dir_info ~cctx in (* Rule printing *) let fmt = Format.std_formatter in List.iter (Dune_file.Subdir.pp ppr fmt) vo_rules; List.iter (Dune_file.Subdir.pp ppi fmt) install_rules; (* Rules for coqnative (not always setup for now, need to think about this) *) begin match native_mode with (* cmxs files are already generated in coqc *) | Coq_module.Rule_type.Disabled | Coq_module.Rule_type.Coqc -> () | Coq_module.Rule_type.CoqNative -> let coqnative_rules = Coq_rules.coqnative_rules ~dir_info ~cctx in List.iter (Dune_file.Subdir.pp ppr fmt) coqnative_rules end; Format.pp_print_flush fmt (); () let pr_feedback (fb : Feedback.feedback) = match fb.contents with | Message (_,_,_,msg) -> Format.eprintf "%a" Pp.pp_with msg | _ -> () [@@warning "-4"] let () = Printexc.record_backtrace true; let _ : int = Feedback.add_feeder pr_feedback in try main () with exn -> Format.eprintf "[gen_rules] Fatal error:@ @[<2>%a@]@\n%!" Pp.pp_with (CErrors.print exn); exit 1 rocq-9.2.0/tools/dune_rule_gen/gen_rules.mli000066400000000000000000000000001516144147600211260ustar00rootroot00000000000000rocq-9.2.0/tools/dune_rule_gen/path.ml000066400000000000000000000035121516144147600177410ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) (* We distinguish Path arguments as to adjust for subdirs in Coq theory evaluation *) type t = Rel of string | Abs of string let to_string = function Rel p -> p | Abs p -> p (* paths which begin with a dune variable are considered absolute (eg %{project_root}/bla) *) let is_relative path = not (CString.is_prefix "%{" path) && Filename.is_relative path let make path = if is_relative path then Rel path else Abs path let map ~f = function Rel p -> Rel (f p) | Abs p -> Abs (f p) let fold ~f = function Rel p -> f p | Abs p -> f p let relative dir path = map dir ~f:(fun dir -> Filename.concat dir path) let gen_sub n = String.concat Filename.dir_sep @@ List.init n (fun _ -> "..") let adjust ~lvl = function | Rel path -> Rel (Filename.concat (gen_sub lvl) path) | Abs path -> Abs path let compare p1 p2 = match p1, p2 with | Rel p1, Rel p2 -> String.compare p1 p2 | Abs p1, Abs p2 -> String.compare p1 p2 | Rel _, Abs _ -> -1 | Abs _, Rel _ -> 1 let pp fmt = function | Rel p -> Format.fprintf fmt "%s" p | Abs p -> Format.fprintf fmt "%s" p let basename = fold ~f:Filename.basename let add_extension ~ext = map ~f:(fun p -> p ^ ext) let replace_ext ~ext = map ~f:(fun p -> Filename.remove_extension p ^ ext) (* Coqdep strips files with dirname "." of the basename, so we need to fixup that until we can fix coqdep... [fixing coqdep breaks dune] *) let coqdep_fixup_dir = function | Abs file -> Abs file | Rel file -> match Filename.dirname file with | "." -> Rel (Filename.basename file) | _ -> Rel file rocq-9.2.0/tools/dune_rule_gen/path.mli000066400000000000000000000017771516144147600201250ustar00rootroot00000000000000(************************************************************************) (* This file is licensed under The MIT License *) (* See LICENSE for more information *) (************************************************************************) type t (** [make path] build a path from a string *) val make : string -> t (** [relative path s] append [s] to [path] to build [path/s] *) val relative : t -> string -> t (** [basename path] returns the basename *) val basename : t -> string (** [adjust ~lvl path] adjusts a path to refer to [lvl] lower directories, that is to say [adjust ~lvl:2 p] will do [../../p] *) val adjust : lvl:int -> t -> t (** [add_extension ext p] builds [p^ext] *) val add_extension : ext:string -> t -> t val replace_ext : ext:string -> t -> t val to_string : t -> string val compare : t -> t -> int val pp : Format.formatter -> t -> unit (* Hack for coqdep, see comments in the implementation *) val coqdep_fixup_dir : t -> t rocq-9.2.0/tools/make-both-single-timing-files.py000077500000000000000000000015051516144147600217300ustar00rootroot00000000000000#!/usr/bin/env python3 from TimeFileMaker import * if __name__ == '__main__': parser = argparse.ArgumentParser(description=r'''Formats timing information from the output of two invocations of `coqc -time` into a sorted table''') add_sort_by(parser) add_user(parser, single_timing=True) add_fuzz(parser) add_after_file_name(parser) add_before_file_name(parser) add_output_file_name(parser) args = parser.parse_args() left_dict = get_single_file_times(args.AFTER_FILE_NAME, use_real=args.real) right_dict = get_single_file_times(args.BEFORE_FILE_NAME, use_real=args.real) left_dict, right_dict = adjust_fuzz(left_dict, right_dict, fuzz=args.fuzz) table = make_diff_table_string(left_dict, right_dict, tag="Code", sort_by=args.sort_by) print_or_write_table(table, args.OUTPUT_FILE_NAME) rocq-9.2.0/tools/make-both-time-files.py000077500000000000000000000015561516144147600201260ustar00rootroot00000000000000#!/usr/bin/env python3 from TimeFileMaker import * if __name__ == '__main__': parser = argparse.ArgumentParser(description=r'''Formats timing information from the output of two invocations of `make TIMED=1` into a sorted table.''') add_sort_by(parser) add_real(parser) add_include_mem(parser) add_sort_by_mem(parser) add_after_file_name(parser) add_before_file_name(parser) add_output_file_name(parser) args = parser.parse_args() left_dict = get_times_and_mems(args.AFTER_FILE_NAME, use_real=args.real, include_mem=args.include_mem) right_dict = get_times_and_mems(args.BEFORE_FILE_NAME, use_real=args.real, include_mem=args.include_mem) table = make_diff_table_string(left_dict, right_dict, sort_by=args.sort_by, include_mem=args.include_mem, sort_by_mem=args.sort_by_mem) print_or_write_table(table, args.OUTPUT_FILE_NAME) rocq-9.2.0/tools/make-one-time-file.py000077500000000000000000000012171516144147600175620ustar00rootroot00000000000000#!/usr/bin/env python3 import sys from TimeFileMaker import * if __name__ == '__main__': parser = argparse.ArgumentParser(description=r'''Formats timing information from the output of `make TIMED=1` into a sorted table.''') add_real(parser) add_file_name(parser) add_output_file_name(parser) add_include_mem(parser) add_sort_by_mem(parser) args = parser.parse_args() stats_dict = get_times_and_mems(args.FILE_NAME, use_real=args.real, include_mem=args.include_mem) table = make_table_string(stats_dict, include_mem=args.include_mem, sort_by_mem=args.sort_by_mem) print_or_write_table(table, args.OUTPUT_FILE_NAME) rocq-9.2.0/tools/ocamllibdep.mli000066400000000000000000000000001516144147600166030ustar00rootroot00000000000000rocq-9.2.0/tools/ocamllibdep.mll000066400000000000000000000207201516144147600166210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Buffer.clear s'; for i = 0 to String.length s - 1 do let c = s.[i] in if c = ' ' || c = '#' || c = ':' (* separators and comments *) || c = '%' (* pattern *) || c = '?' || c = '[' || c = ']' || c = '*' (* expansion in filenames *) || i=0 && c = '~' && (String.length s = 1 || s.[1] = '/' || 'A' <= s.[1] && s.[1] <= 'Z' || 'a' <= s.[1] && s.[1] <= 'z') (* homedir expansion *) then begin let j = ref (i-1) in while !j >= 0 && s.[!j] = '\\' do Buffer.add_char s' '\\'; decr j (* escape all preceding '\' *) done; Buffer.add_char s' '\\'; end; if c = '$' then Buffer.add_char s' '$'; Buffer.add_char s' c done; Buffer.contents s' (* Filename.concat but always with a '/' *) let is_dir_sep s i = match Sys.os_type with | "Unix" -> s.[i] = '/' | "Cygwin" | "Win32" -> let c = s.[i] in c = '/' || c = '\\' || c = ':' | _ -> assert false let (//) dirname filename = let l = String.length dirname in if l = 0 || is_dir_sep dirname (l-1) then dirname ^ filename else dirname ^ "/" ^ filename (** [get_extension f l] checks whether [f] has one of the extensions listed in [l]. It returns [f] without its extension, alongside with the extension. When no extension match, [(f,"")] is returned *) let rec get_extension f = function | [] -> (f, "") | s :: _ when Filename.check_suffix f s -> (Filename.chop_suffix f s, s) | _ :: l -> get_extension f l let file_name s = function | None -> s | Some "." -> s | Some d -> d // s type dir = string option let add_directory add_file phys_dir = let open Unix in let files = Sys.readdir phys_dir in Array.iter (fun f -> (* we avoid all files starting by '.' *) if f.[0] <> '.' then let phys_f = if phys_dir = "." then f else phys_dir//f in match try (stat phys_f).st_kind with _ -> S_BLK with | S_REG -> add_file phys_dir f | _ -> ()) files let error_cannot_parse s (i,j) = Printf.eprintf "File \"%s\", characters %i-%i: Syntax error\n" s i j; exit 1 let error_unknown_extension name = Printf.eprintf "Don't know what to do with \"%s\"\n" name; Printf.eprintf "Usage: ocamllibdep [-I dir] [-c] [file.mllib] [file.mlpack]\n"; exit 1 let error_cannot_open msg = Format.eprintf "Error: @[%s@].@\n%!" msg; exit 1 let error_cannot_stat err name = Format.eprintf "Error: @[cannot stat %s (%s)@].@\n%!" name (Unix.error_message err); exit 1 let same_path_opt s s' = let nf s = (* ./foo/a.ml and foo/a.ml are the same file *) if Filename.is_implicit s then "." // s else s in let s = match s with None -> "." | Some s -> nf s in let s' = match s' with None -> "." | Some s' -> nf s' in s = s' let warning_ml_clash x s suff s' suff' = if suff = suff' && not (same_path_opt s s') then eprintf "*** Warning: %s%s already found in %s (discarding %s%s)\n" x suff (match s with None -> "." | Some d -> d) ((match s' with None -> "." | Some d -> d) // x) suff let mkknown () = let h = (Hashtbl.create 19 : (string, dir * string) Hashtbl.t) in let add x s suff = try let s',suff' = Hashtbl.find h x in warning_ml_clash x s' suff' s suff with Not_found -> Hashtbl.add h x (s,suff) and search x = try Some (fst (Hashtbl.find h x)) with Not_found -> None in add, search let add_ml_known, search_ml_known = mkknown () let add_mlpack_known, search_mlpack_known = mkknown () let mllibAccu = ref ([] : (string * dir) list) let mlpackAccu = ref ([] : (string * dir) list) let add_caml_known phys_dir f = let basename,suff = get_extension f [".ml";".mlg";".mlpack"] in match suff with | ".ml"|".mlg" -> add_ml_known basename (Some phys_dir) suff | ".mlpack" -> add_mlpack_known basename (Some phys_dir) suff | _ -> () let add_caml_dir phys_dir = try add_directory add_caml_known phys_dir with | Sys_error msg -> error_cannot_open msg | Unix.Unix_error (e, "stat", a) -> error_cannot_stat e a let treat_file_modules md ext = try let chan = open_in (md ^ ext) in let list = mllib_list (Lexing.from_channel chan) in List.fold_left (fun acc str -> match search_mlpack_known str with | Some mldir -> (file_name str mldir) :: acc | None -> match search_ml_known str with | Some mldir -> (file_name str mldir) :: acc | None -> acc) [] (List.rev list) with | Sys_error _ -> [] | Syntax_error (i,j) -> error_cannot_parse (md^ext) (i,j) let addQueue q v = q := v :: !q let treat_file old_name = let name = Filename.basename old_name in let dirname = Some (Filename.dirname old_name) in match get_extension name [".mllib";".mlpack"] with | (base,".mllib") -> addQueue mllibAccu (base,dirname) | (base,".mlpack") -> addQueue mlpackAccu (base,dirname) | _ -> error_unknown_extension old_name let mllib_dependencies () = List.iter (fun (name,dirname) -> let fullname = file_name name dirname in let deps = treat_file_modules fullname ".mllib" in let sdeps = String.concat " " deps in let efullname = escape fullname in printf "%s_MLLIB_DEPENDENCIES:=%s\n" efullname sdeps; printf "%s.cma:$(addsuffix .cmo,$(%s_MLLIB_DEPENDENCIES))\n" efullname efullname; printf "%s.cmxa:$(addsuffix .cmx,$(%s_MLLIB_DEPENDENCIES))\n" efullname efullname; flush stdout) (List.rev !mllibAccu) let coq_makefile_mode = ref false let print_for_pack modname d = if !coq_makefile_mode then printf "%s.cmx : FOR_PACK=-for-pack %s\n" d modname else printf "%s_FORPACK:= -for-pack %s\n" d modname let mlpack_dependencies () = List.iter (fun (name,dirname) -> let fullname = file_name name dirname in let modname = String.capitalize_ascii name in let deps = treat_file_modules fullname ".mlpack" in let sdeps = String.concat " " deps in let efullname = escape fullname in printf "%s_MLPACK_DEPENDENCIES:=%s\n" efullname sdeps; List.iter (print_for_pack modname) deps; printf "%s.cmo:$(addsuffix .cmo,$(%s_MLPACK_DEPENDENCIES))\n" efullname efullname; printf "%s.cmx:$(addsuffix .cmx,$(%s_MLPACK_DEPENDENCIES))\n" efullname efullname; flush stdout) (List.rev !mlpackAccu) let rec parse = function | "-c" :: r -> coq_makefile_mode := true; parse r | "-I" :: r :: ll -> (* To solve conflict (e.g. same filename in kernel and checker) we allow to state an explicit order *) add_caml_dir r; parse ll | f :: ll -> treat_file f; parse ll | [] -> () let main () = if Array.length Sys.argv < 2 then exit 1; parse (List.tl (Array.to_list Sys.argv)); mllib_dependencies (); mlpack_dependencies () let _ = main () } rocq-9.2.0/tools/rocqmakefile.ml000066400000000000000000000432351516144147600166420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ) f g = fun x -> g (f x) let usage_coq_makefile ~ok = let out = if ok then stdout else stderr in output_string out "Usage summary:\ \n\ \nrocq makefile .... [file.v] ... [file.ml[ig]?] ... [file.ml{lib,pack}]\ \n ... [-I dir] ... [-R physicalpath logicalpath]\ \n ... [-Q physicalpath logicalpath] ... [VARIABLE = value]\ \n ... [-arg opt] ... [-docroot path] [-f file] [-o file]\ \n ... [-generate-meta-for-package project-name]\ \n [-h] [--help] [-v] [--version]\ \n"; output_string out "\ \nFull list of options:\ \n\ \n[file.v]: Rocq file to be compiled\ \n[file.ml[ig]?]: Objective Caml file to be compiled\ \n[file.ml{lib,pack}]: ocamlbuild-style file that describes a Objective Caml\ \n library/module\ \n[-I dir]: look for Objective Caml dependencies in \"dir\"\ \n[-R physicalpath logicalpath]: look for Rocq dependencies recursively\ \n starting from \"physicalpath\". The logical path associated to the\ \n physical path is \"logicalpath\".\ \n[-Q physicalpath logicalpath]: look for Rocq dependencies starting from\ \n \"physicalpath\". The logical path associated to the physical path\ \n is \"logicalpath\".\ \n[-coqlib dir]: set the Rocq Corelib directory\ \n[VARIABLE = value]: Add the variable definition \"VARIABLE=value\"\ \n[-arg opt]: send option \"opt\" to rocq compile\ \n[-docroot path]: Install the documentation in this folder, relative to\ \n \"user-contrib\".\ \n[-f file]: take the contents of file as arguments\ \n[-o file]: output should go in file file (recommended)\ \n Output file outside the current directory is forbidden.\ \n[-generate-meta-for-package project-name]: generate META.project-name.\ \n[-h]: print this usage summary\ \n[--help]: equivalent to [-h]\ \n[-v]: print version information\ \n[--version]: equivalent to [-v]\ \n"; exit (if ok then 0 else 1) let is_prefix dir1 dir2 = let l1 = String.length dir1 in let l2 = String.length dir2 in let sep = Filename.dir_sep in if dir1 = dir2 then true else if l1 + String.length sep <= l2 then let dir1' = String.sub dir2 0 l1 in let sep' = String.sub dir2 l1 (String.length sep) in dir1' = dir1 && sep' = sep else false let physical_dir_of_logical_dir ldir = let ldir = Bytes.of_string ldir in let le = Bytes.length ldir - 1 in let pdir = if le >= 0 && Bytes.get ldir le = '.' then Bytes.sub ldir 0 (le - 1) else Bytes.copy ldir in for i = 0 to le - 1 do if Bytes.get pdir i = '.' then Bytes.set pdir i '/'; done; Bytes.to_string pdir let read_whole_file s = let ic = open_in s in let b = Buffer.create (1 lsl 12) in try while true do let s = input_line ic in Buffer.add_string b s; Buffer.add_char b '\n'; done; assert false; with End_of_file -> close_in ic; Buffer.contents b (* Use this for quoting contents of variables which never appears as target or * pattern. *) let makefile_quote s = let out = Buffer.create 16 in Buffer.add_string out "'"; String.iter (fun c -> match c with | '$' -> Buffer.add_string out "$$" | '#' -> Buffer.add_string out "\\#" | '\'' -> Buffer.add_string out "'\\''" | _ -> Buffer.add_char out c ) s; Buffer.add_string out "'"; Buffer.contents out let quote s = if String.contains s ' ' || CString.is_empty s then "'" ^ s ^ "'" else s let generate_makefile oc env conf_file local_file local_late_file dep_file args project = (* XX coq makefile should ship files on its own dir *) let cmf_dir = Boot.Env.tool env "" in let makefile_template = Boot.Path.relative cmf_dir "CoqMakefile.in" in if not (Boot.Path.exists makefile_template) then begin let makefile_template = Boot.Path.to_string makefile_template in Format.eprintf "Error: cannot find %s" makefile_template; exit 1 end; let makefile_template = Boot.Path.to_string makefile_template in let s = read_whole_file makefile_template in let s = List.fold_left (* We use global_substitute to avoid running into backslash issues due to \1 etc. *) (fun s (k,v) -> Str.global_substitute (Str.regexp_string k) (fun _ -> v) s) s [ "@CONF_FILE@", conf_file; "@LOCAL_FILE@", local_file; "@LOCAL_LATE_FILE@", local_late_file; "@DEP_FILE@", dep_file; "@COQ_VERSION@", Coq_config.version; "@PROJECT_FILE@", (Option.default "" project.project_file); "@COQ_MAKEFILE_INVOCATION@",String.concat " " (List.map quote args); ] in output_string oc s let generate_meta_file p = try match p.meta_file with | Absent -> p | Generate proj -> let cmname = List.map (fun { thing } -> thing) (files_by_suffix p.files [".mllib"; ".mlpack"]) in let dir, cmname = match cmname with | [] -> Printf.eprintf "In order to generate a META file one needs an .mlpack or .mllib file\n"; exit 1 | [x] -> Filename.dirname x, Filename.(basename @@ chop_extension x) | _ -> Printf.eprintf "Automatic META generation only works for one .mlpack or .mllib file, since you have more you need to write the META file by hand\n"; exit 1 in let f = dir ^ "/META." ^ proj in let oc = open_out f in let meta : _ format = {| package "plugin" ( directory = "." requires = "rocq-runtime.plugins.ltac" archive(byte) = "%s.cma" archive(native) = "%s.cmxa" plugin(byte) = "%s.cma" plugin(native) = "%s.cmxs" ) directory = "." |} in let meta = Printf.sprintf meta cmname cmname cmname cmname in output_string oc meta; close_out oc; { p with meta_file = Present f } | Present f -> let ext = Filename.extension f in if ext = ".in" then let meta_file = Filename.chop_extension f in let oc = open_out meta_file in (* META generation is just a renaming for now, we lack some metadata *) output_string oc (read_whole_file f); close_out oc; { p with meta_file = Present meta_file } else p (* already a META.package file *) with Sys_error e -> Printf.eprintf "Error: %s\n" e; exit 1 let section oc s = let pad = String.make (76 - String.length s) ' ' in let sharps = String.make 79 '#' in let spaces = "#" ^ String.make 77 ' ' ^ "#" in fprintf oc "\n%s\n" sharps; fprintf oc "%s\n" spaces; fprintf oc "# %s%s#\n" s pad; fprintf oc "%s\n" spaces; fprintf oc "%s\n\n" sharps ;; let generate_conf_includes oc { ml_includes; r_includes; q_includes } = section oc "Path directives (-I, -R, -Q)."; let module S = String in let map = map_sourced_list in let dash1 opt v = sprintf "-%s %s" opt (quote v) in let dash2 opt v1 v2 = sprintf "-%s %s %s" opt (quote v1) (quote v2) in fprintf oc "COQMF_OCAMLLIBS = %s\n" (S.concat " " (map (fun { path } -> dash1 "I" path) ml_includes)); fprintf oc "COQMF_SRC_SUBDIRS = %s\n" (S.concat " " (map (fun { path } -> quote path) ml_includes)); fprintf oc "COQMF_COQLIBS = %s %s %s\n" (S.concat " " (map (fun { path } -> dash1 "I" path) ml_includes)) (S.concat " " (map (fun ({ path },l) -> dash2 "Q" path l) q_includes)) (S.concat " " (map (fun ({ path },l) -> dash2 "R" path l) r_includes)); fprintf oc "COQMF_COQLIBS_NOML = %s %s\n" (S.concat " " (map (fun ({ path },l) -> dash2 "Q" path l) q_includes)) (S.concat " " (map (fun ({ path },l) -> dash2 "R" path l) r_includes)); fprintf oc "COQMF_CMDLINE_COQLIBS = %s %s %s\n" (S.concat " " (map_cmdline (fun { path } -> dash1 "I" path) ml_includes)) (S.concat " " (map_cmdline (fun ({ path },l) -> dash2 "Q" path l) q_includes)) (S.concat " " (map_cmdline (fun ({ path },l) -> dash2 "R" path l) r_includes)); ;; let windrive s = if Coq_config.arch_is_win32 && Str.(string_match (regexp "^[a-zA-Z]:") s 0) then Str.matched_string s else "" ;; let generate_conf_coq_config oc env = section oc "Rocq configuration."; Boot.Env.print_config ~prefix_var_name:"COQMF_" env oc; let coqlib = Boot.Env.(coqlib env |> Path.to_string) in (* XXX: FIXME, why does this variable needs the root lib *) fprintf oc "COQMF_WINDRIVE=%s\n" (windrive coqlib) ;; let check_metafile p = if files_by_suffix p.files [".mlpack"; ".mllib"] <> [] && p.meta_file = Absent then begin eprintf "Warning: it is recommended you provide a META.package-name file\n"; eprintf "Warning: since you build plugins. See also -generate-meta-for-package.\n"; end let write_coqbin oc = fprintf oc "%s\n" "COQBIN?=\n\ ifneq (,$(COQBIN))\n\ # add an ending /\n\ COQBIN:=$(COQBIN)/\n\ endif\n\ COQMKFILE ?= \"$(COQBIN)rocq\" makefile" let generate_conf_files oc p = let module S = String in let fout varname suffix = fprintf oc "COQMF_%s := $(filter %%%s, $(COQMF_SOURCES))\n" varname suffix; in section oc "Project files."; let cmdline_vfiles = p.cmd_line_files in fprintf oc "COQMF_CMDLINE_VFILES := %s\n" (S.concat " " (map_sourced_list quote cmdline_vfiles)); let proj_arg = match p.project_file with | Some pfile -> Printf.sprintf "-f %s" pfile | None -> "" in fprintf oc "COQMF_SOURCES := $(shell $(COQMKFILE) -sources-of %s $(COQMF_CMDLINE_VFILES))\n" proj_arg; fout "VFILES" ".v"; fout "MLIFILES" ".mli"; fout "MLFILES" ".ml"; fout "MLGFILES" ".mlg"; fout "MLPACKFILES" ".mlpack"; fout "MLLIBFILES" ".mllib"; fprintf oc "COQMF_METAFILE = %s\n" (match p.meta_file with Present x -> x | _ -> "") let rec all_start_with prefix = function | [] -> true | [] :: _ -> false | (x :: _) :: rest -> x = prefix && all_start_with prefix rest let rec logic_gcd acc = function | [] -> acc | [] :: _ -> acc | (hd :: tl) :: rest -> if all_start_with hd rest then logic_gcd (acc @ [hd]) (tl :: List.map List.tl rest) else acc let generate_conf_doc oc { docroot; q_includes; r_includes } = let includes = List.map (forget_source > snd) (q_includes @ r_includes) in let logpaths = List.map (String.split_on_char '.') includes in let gcd = logic_gcd [] logpaths in let root = match docroot with | None -> if gcd = [] then let destination = "orphan_" ^ (String.concat "_" includes) in eprintf "Warning: No common logical root.\n"; eprintf "Warning: In this case the -docroot option should be given.\n"; eprintf "Warning: Otherwise the install-doc target is going to install files\n"; eprintf "Warning: in %s\n" destination; destination else String.concat Filename.dir_sep gcd | Some p -> p in Printf.fprintf oc "COQMF_INSTALLCOQDOCROOT = %s\n" (quote root) let generate_conf_native oc native_compiler = section oc "Native compiler."; let flag = match native_compiler with | None -> "" | Some NativeYes -> "yes" | Some NativeNo -> "no" | Some NativeOndemand -> "ondemand" in Printf.fprintf oc "COQMF_COQPROJECTNATIVEFLAG = %s\n" flag let generate_conf_defs oc { defs; extra_args } = section oc "Extra variables."; List.iter (forget_source > (fun (k,v) -> Printf.fprintf oc "%s = %s\n" k v)) defs; Printf.fprintf oc "COQMF_OTHERFLAGS = %s\n" (String.concat " " (List.map (forget_source > makefile_quote) extra_args)) let generate_conf oc env project args = fprintf oc "# This configuration file was generated by running:\n"; fprintf oc "# %s\n\n" (String.concat " " (List.map quote args)); write_coqbin oc; generate_conf_files oc project; generate_conf_includes oc project; generate_conf_coq_config oc env; generate_conf_native oc project.native_compiler; generate_conf_defs oc project; generate_conf_doc oc project; ;; let ensure_root_dir ({ ml_includes; r_includes; q_includes; files } as project) = let exists f = List.exists (forget_source > f) in let here = Sys.getcwd () in let not_tops = List.for_all (fun s -> s.thing <> Filename.basename s.thing) in if exists (fun { canonical_path = x } -> x = here) ml_includes || exists (fun ({ canonical_path = x },_) -> is_prefix x here) r_includes || exists (fun ({ canonical_path = x },_) -> is_prefix x here) q_includes || not_tops files then project else let source x = {thing=x; source=CmdLine} in let here_path = { path = "."; canonical_path = here } in { project with ml_includes = source here_path :: ml_includes; r_includes = source (here_path, "Top") :: r_includes } ;; let check_overlapping_include { q_includes; r_includes } = let pwd = Sys.getcwd () in let aux = function | [] -> () | {thing = { path; canonical_path }, _} :: l -> if not (is_prefix pwd canonical_path) then eprintf "Warning: %s (used in -R or -Q) is not a subdirectory of the current directory\n\n" path; List.iter (fun {thing={ path = p; canonical_path = cp }, _} -> if is_prefix canonical_path cp || is_prefix cp canonical_path then eprintf "Warning: %s and %s overlap (used in -R or -Q)\n\n" path p) l in aux (q_includes @ r_includes) ;; let check_native_compiler = function | None -> () | Some flag -> match Coq_config.native_compiler, flag with | Coq_config.NativeOff, (NativeYes | NativeOndemand) -> eprintf "Warning: native compilation is globally deactivated by the configure flag\n" | _ -> () let chop_prefix p f = let len_p = String.length p in let len_f = String.length f in String.sub f len_p (len_f - len_p) type extra_opts = { only_destination : string option; only_sources : bool; coqlib : string option; } let empty_extra = { only_destination = None; only_sources = false; coqlib = None; } let parse_extra f r opts = match f, r with | "-destination-of", tgt :: r -> Some (r, { opts with only_destination = Some tgt }) | "-sources-of", r -> Some (r, { opts with only_sources = true }) | "-coqlib", v :: r -> Some (r, { opts with coqlib = Some v }) | ("-h"|"--help"), _ -> usage_coq_makefile ~ok:true | ("-v"|"--version"), _ -> Boot.Usage.version (); exit 0 | _ -> None let destination_of { ml_includes; q_includes; r_includes; } file = let file_dir = CUnix.canonical_path_name (Filename.dirname file) in let includes = q_includes @ r_includes in let mk_destination logic canonical_path = Filename.concat (physical_dir_of_logical_dir logic) (chop_prefix canonical_path file_dir) in let candidates = CList.map_filter (fun {thing={ canonical_path }, logic} -> if is_prefix canonical_path file_dir then Some(mk_destination logic canonical_path) else None) includes in match candidates with | [] -> (* BACKWARD COMPATIBILITY: -I into the only logical root *) begin match r_includes, List.find (fun {thing={ canonical_path = p }} -> is_prefix p file_dir) ml_includes with | [{thing={ canonical_path }, logic}], {thing={ canonical_path = p }} -> let destination = Filename.concat (physical_dir_of_logical_dir logic) (chop_prefix p file_dir) in Printf.printf "%s" (quote destination) | _ -> () (* skip *) | exception Not_found -> () (* skip *) end | [s] -> Printf.printf "%s" (quote s) | _ -> assert false let normal_mode ~coqlib project prog args = if project.makefile = None then eprintf "Warning: Omitting -o is deprecated\n\n"; (* We want to know the name of the Makefile (say m) in order to * generate m.conf and include m.local *) let conf_file = Option.default "CoqMakefile" project.makefile ^ ".conf" in let local_file = Option.default "CoqMakefile" project.makefile ^ ".local" in let local_late_file = Option.default "CoqMakefile" project.makefile ^ ".local-late" in let dep_file = "." ^ Option.default "CoqMakefile" project.makefile ^ ".d" in let project = ensure_root_dir project in check_overlapping_include project; check_native_compiler project.native_compiler; check_metafile project; let project = generate_meta_file project in (* NB: we need a full Boot.Env not just the runtime half because the conf file contains coqlib *) let env = Boot.Env.init_with ~coqlib in let ocm = Option.cata open_out stdout project.makefile in generate_makefile ocm env conf_file local_file local_late_file dep_file (prog @ args) project; close_out ocm; let occ = open_out conf_file in generate_conf occ env project (prog @ args); close_out occ; () let main ~prog args = let _fhandle = Feedback.(add_feeder (console_feedback_listener Format.err_formatter)) in let { extra_data = { only_destination; only_sources; coqlib } } as project = let warning_fn x = Format.eprintf "%s@\n%!" x in try cmdline_args_to_project ~warning_fn ~curdir:Filename.current_dir_name ~parse_extra empty_extra args with Parsing_error s -> prerr_endline s; usage_coq_makefile ~ok:false in match only_destination, only_sources with | None, false -> normal_mode ~coqlib project prog args | Some dest, false -> destination_of project dest | None, true -> let paths = String.concat " " (List.map (fun i -> i.thing) project.files) in Printf.printf "%s" paths | Some _, true -> prerr_endline "Cannot combine -destination-of and -sources-of"; usage_coq_makefile ~ok:false rocq-9.2.0/tools/rocqmakefile.mli000066400000000000000000000015731516144147600170120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> unit rocq-9.2.0/tools/rocqtex.ml000066400000000000000000000237761516144147600156750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (* a dummy command, just in case the last line was a comment *) output_string chan_out "Set Printing Width 78.\n"; close_in chan_in; close_out chan_out (* Second pass: insert the answers of Rocq from [coq_output] into the * TeX file [texfile]. The result goes in file [result]. *) let tex_escaped s = let delims = Str.regexp "[_{}&%#$\\^~ <>'`]" in let adapt_delim = function | "{" | "}" | "&" | "%" | "#" | "$" as c -> "\\"^c | "_" -> "{\\char`\\_}" | "\\" -> "{\\char'134}" | "^" -> "{\\char'136}" | "~" -> "{\\char'176}" | " " -> "~" | "<" -> "{<}" | ">" -> "{>}" | "'" -> "{\\textquotesingle}" | "`" -> "\\`{}" | _ -> assert false in let adapt = function | Str.Text s -> s | Str.Delim s -> adapt_delim s in String.concat "" (List.map adapt (Str.full_split delims s)) let encapsule sl c_out s = if sl then Printf.fprintf c_out "\\texttt{\\textit{%s}}\\\\\n" (tex_escaped s) else Printf.fprintf c_out "\\texttt{%s}\\\\\n" (tex_escaped s) let print_block c_out bl = List.iter (fun s -> if s="" then () else encapsule !slanted c_out s) bl let insert texfile coq_output result = let c_tex = open_in texfile in let c_coq = open_in coq_output in let c_out = open_out result in (* read lines until a prompt is found (starting from the second line), purge prompts on the first line and return their number *) let last_read = ref (input_line c_coq) in let read_output () = let first = !last_read in let nb = ref 0 in (* remove the leading prompts *) let rec skip_prompts pos = if Str.string_match any_prompt first pos then let () = incr nb in skip_prompts (Str.match_end ()) else pos in let first = let start = skip_prompts 0 in String.sub first start (String.length first - start) in (* read and return the following lines until a prompt is found *) let rec read_lines () = let s = input_line c_coq in if Str.string_match any_prompt s 0 then begin last_read := s; [] end else s :: read_lines () in (first :: read_lines (), !nb) in let unhandled_output = ref None in let read_output () = match !unhandled_output with | Some some -> unhandled_output := None; some | None -> read_output () in (* we are inside a \begin{coq_...} ... \end{coq_...} block * show_... tell what kind of block it is *) let rec inside show_answers show_questions not_first discarded = let s = input_line c_tex in if s = "" then inside show_answers show_questions not_first (discarded + 1) else if not (Str.string_match end_coq s 0) then begin let (bl,n) = read_output () in assert (n > discarded); let n = n - discarded in if not_first then output_string c_out "\\medskip\n"; if !verbose then Printf.printf "Rocq < %s\n" s; if show_questions then encapsule false c_out ("Rocq < " ^ s); let rec read_lines k = if k = 0 then [] else let s = input_line c_tex in if Str.string_match end_coq s 0 then [] else s :: read_lines (k - 1) in let al = read_lines (n - 1) in if !verbose then List.iter (Printf.printf " %s\n") al; if show_questions then List.iter (fun s -> encapsule false c_out (" " ^ s)) al; let la = n - 1 - List.length al in if la <> 0 then (* this happens when the block ends with a comment; the output is for the command at the beginning of the next block *) unhandled_output := Some (bl, la) else begin if !verbose then List.iter print_endline bl; if show_answers then print_block c_out bl; inside show_answers show_questions (show_answers || show_questions) 0 end end else if discarded > 0 then begin (* this happens when the block ends with an empty line *) let (bl,n) = read_output () in assert (n > discarded); unhandled_output := Some (bl, n - discarded) end in (* we are outside of a \begin{coq_...} ... \end{coq_...} block *) let rec outside just_after = let start_block () = if !small then output_string c_out "\\begin{small}\n"; output_string c_out "\\begin{flushleft}\n"; if !hrule then output_string c_out "\\hrulefill\\\\\n" in let end_block () = if !hrule then output_string c_out "\\hrulefill\\\\\n"; output_string c_out "\\end{flushleft}\n"; if !small then output_string c_out "\\end{small}\n" in let s = input_line c_tex in if Str.string_match begin_coq s 0 then begin let kind = Str.matched_group 1 s in if kind = "eval" then begin if just_after then end_block (); inside false false false 0; outside false end else begin let show_answers = kind <> "example*" in let show_questions = kind <> "example#" in if not just_after then start_block (); inside show_answers show_questions just_after 0; outside true end end else begin if just_after then end_block (); output_string c_out (s ^ "\n"); outside false end in try let _ = read_output () in (* to skip the Rocq banner *) let _ = read_output () in (* to skip the Rocq answer to Set Printing Width *) outside false with End_of_file -> begin close_in c_tex; close_in c_coq; close_out c_out end (* Process of one TeX file *) let rm f = try Sys.remove f with _ -> () let one_file texfile = let inputv = Filename.temp_file "coq_tex" ".v" in let coq_output = Filename.temp_file "coq_tex" ".coq_output"in let result = if !output_specified then !output else if Filename.check_suffix texfile ".tex" then (Filename.chop_suffix texfile ".tex") ^ ".v.tex" else texfile ^ ".v.tex" in try (* 1. extract Rocq phrases *) extract texfile inputv; (* 2. run Rocq on input *) let _ = Sys.command (Printf.sprintf "%s < %s > %s 2>&1" !image inputv coq_output) in (* 3. insert Rocq output into original file *) insert texfile coq_output result; (* 4. clean up *) rm inputv; rm coq_output with reraise -> begin rm inputv; rm coq_output; raise reraise end (* Parsing of the command line, check of the Rocq command and process * of all the files in the command line, one by one *) let files = ref [] let parse_cl ~prog args = Arg.parse_argv (Array.of_list (prog :: args)) [ "-o", Arg.String (fun s -> output_specified := true; output := s), "output-file Specify the resulting LaTeX file"; "-n", Arg.Int (fun n -> linelen := n), "line-width Set the line width"; "-image", Arg.String (fun s -> image := s), "rocq-image Use rocq-image as Rocq command"; "-w", Arg.Set cut_at_blanks, " Try to cut lines at blanks"; "-v", Arg.Set verbose, " Verbose mode (show Rocq answers on stdout)"; "-sl", Arg.Set slanted, " Rocq answers in slanted font (only with LaTeX2e)"; "-hrule", Arg.Set hrule, " Rocq parts are written between 2 horizontal lines"; "-small", Arg.Set small, " Rocq parts are written in small font"; ] (fun s -> files := s :: !files) "coq-tex [options] file ..." let find_coqtop () = let prog = Sys.executable_name in try let size = String.length prog in let i = Str.search_backward (Str.regexp_string "coq-tex") prog (size-7) in (String.sub prog 0 i)^"coqtop"^(String.sub prog (i+7) (size-i-7)) with Not_found -> begin Printf.printf "Warning: preprocessing with default image \"coqtop\"\n"; "coqtop" end let main ~prog args = parse_cl ~prog args; if !image = "" then image := Filename.quote (find_coqtop ()); if Sys.command (!image ^ " -batch -silent") <> 0 then begin Printf.printf "Error: "; let _ = Sys.command (!image ^ " -batch") in exit 1 end else begin (*Printf.printf "Your version of coqtop seems OK\n";*) flush stdout end; List.iter one_file (List.rev !files) rocq-9.2.0/tools/rocqtex.mli000066400000000000000000000013221516144147600160250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> unit rocq-9.2.0/tools/rocqwc.mli000066400000000000000000000013031516144147600156350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit rocq-9.2.0/tools/rocqwc.mll000066400000000000000000000220171516144147600156450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* printf " %s" f | _ -> ()); if !percentage then begin let s = sl + pl + dl in let p = if s > 0 then 100 * dl / s else 0 in printf " (%d%%)" p end; print_newline () let print_file fo = print_line !slines !plines !dlines fo let print_totals () = print_line !tslines !tplines !tdlines (Some "total") (*i*)}(*i*) (*s Shortcuts for regular expressions. The [rcs] regular expression is used to skip the CVS infos possibly contained in some comments, in order not to consider it as documentation. *) let space = [' ' '\t' '\r'] let character = "'" ([^ '\\' '\''] | '\\' (['\\' '\'' 'n' 't' 'b' 'r'] | ['0'-'9'] ['0'-'9'] ['0'-'9'])) "'" let rcs_keyword = "Author" | "Date" | "Header" | "Id" | "Name" | "Locker" | "Log" | "RCSfile" | "Revision" | "Source" | "State" let rcs = "\036" rcs_keyword [^ '$']* "\036" let stars = "(*" '*'* "*)" let dot = '.' (' ' | '\t' | '\n' | '\r' | eof) let proof_start = "Theorem" | "Lemma" | "Fact" | "Remark" | "Goal" | "Correctness" | "Obligation" space+ (['0' - '9'])+ | "Next" space+ "Obligation" let def_start = "Definition" | "Fixpoint" | "Instance" let proof_end = ("Save" | "Qed" | "Defined" | "Abort" | "Admitted") [^'.']* '.' (*s [spec] scans the specification. *) rule spec = parse | "(*" { comment lexbuf; spec lexbuf } | '"' { let n = string lexbuf in slines := !slines + n; seen_spec := true; spec lexbuf } | '\n' { newline (); spec lexbuf } | space+ | stars { spec lexbuf } | proof_start { seen_spec := true; spec_to_dot lexbuf; proof lexbuf } | def_start { seen_spec := true; definition lexbuf } | character | _ { seen_spec := true; spec lexbuf } | eof { () } (*s [spec_to_dot] scans a spec until a dot is reached and returns. *) and spec_to_dot = parse | "(*" { comment lexbuf; spec_to_dot lexbuf } | '"' { let n = string lexbuf in slines := !slines + n; seen_spec := true; spec_to_dot lexbuf } | '\n' { newline (); spec_to_dot lexbuf } | dot { () } | space+ | stars { spec_to_dot lexbuf } | character | _ { seen_spec := true; spec_to_dot lexbuf } | eof { () } (*s [definition] scans a definition; passes to [proof] if the body is absent, and to [spec] otherwise *) and definition = parse | "(*" { comment lexbuf; definition lexbuf } | '"' { let n = string lexbuf in slines := !slines + n; seen_spec := true; definition lexbuf } | '\n' { newline (); definition lexbuf } | ":=" { seen_spec := true; spec lexbuf } | dot { proof lexbuf } | space+ | stars { definition lexbuf } | character | _ { seen_spec := true; definition lexbuf } | eof { () } (*s Scans a proof, then returns to [spec]. *) and proof = parse | "(*" { comment lexbuf; proof lexbuf } | '"' { let n = string lexbuf in plines := !plines + n; seen_proof := true; proof lexbuf } | space+ | stars { proof lexbuf } | '\n' { newline (); proof lexbuf } | "Proof" space* '.' | "Proof" space+ "with" | "Proof" space+ "using" { seen_proof := true; proof lexbuf } | "Proof" space { proof_term lexbuf } | proof_end { seen_proof := true; spec lexbuf } | character | _ { seen_proof := true; proof lexbuf } | eof { () } and proof_term = parse | "(*" { comment lexbuf; proof_term lexbuf } | '"' { let n = string lexbuf in plines := !plines + n; seen_proof := true; proof_term lexbuf } | space+ | stars { proof_term lexbuf } | '\n' { newline (); proof_term lexbuf } | dot { spec lexbuf } | character | _ { seen_proof := true; proof_term lexbuf } | eof { () } (*s Scans a comment. *) and comment = parse | "(*" { comment lexbuf; comment lexbuf } | "*)" { () } | '"' { let n = string lexbuf in dlines := !dlines + n; seen_comment := true; comment lexbuf } | '\n' { newline (); comment lexbuf } | space+ | stars { comment lexbuf } | character | _ { seen_comment := true; comment lexbuf } | eof { () } (*s The entry [string] reads a string until its end and returns the number of newlines it contains. *) and string = parse | '"' { 0 } | '\\' ('\\' | 'n' | '"') { string lexbuf } | '\n' { succ (string lexbuf) } | _ { string lexbuf } | eof { 0 } (*s The following entry [read_header] is used to skip the possible header at the beginning of files (unless option \texttt{-e} is specified). It stops whenever it encounters an empty line or any character outside a comment. In this last case, it correctly resets the lexer position on that character (decreasing [lex_curr_pos] by 1). *) and read_header = parse | "(*" { skip_comment lexbuf; skip_until_nl lexbuf; read_header lexbuf } | "\n" { () } | space+ { read_header lexbuf } | _ { lexbuf.lex_curr_pos <- lexbuf.lex_curr_pos - 1 } | eof { () } and skip_comment = parse | "*)" { () } | "(*" { skip_comment lexbuf; skip_comment lexbuf } | _ { skip_comment lexbuf } | eof { () } and skip_until_nl = parse | '\n' { () } | _ { skip_until_nl lexbuf } | eof { () } (*i*){(*i*) (*s Processing files and channels. *) let process_channel ch = let lb = Lexing.from_channel ch in reset_counters (); if !skip_header then read_header lb; spec lb let process_file f = try let ch = open_in f in process_channel ch; close_in ch; print_file (Some f); update_totals () with | Sys_error s -> flush stdout; eprintf "rocq wc: %s: %s\n" f s; flush stderr (*s Parsing of the command line. *) let usage () = prerr_endline "usage: rocq wc [options] [files]"; prerr_endline "Options are:"; prerr_endline " -p print percentage of comments"; prerr_endline " -s print only the spec size"; prerr_endline " -r print only the proof size"; prerr_endline " -e (everything) do not skip headers"; exit 1 let rec parse = function | [] -> [] | ("-h" | "-?" | "-help" | "--help") :: _ -> usage () | ("-s" | "--spec-only") :: args -> proof_only := false; spec_only := true; parse args | ("-r" | "--proof-only") :: args -> spec_only := false; proof_only := true; parse args | ("-p" | "--percentage") :: args -> percentage := true; parse args | ("-e" | "--header") :: args -> skip_header := false; parse args | f :: args -> f :: (parse args) (*s Main program. *) let main args = let files = parse args in if not (!spec_only || !proof_only) then printf " spec proof comments\n"; match files with | [] -> process_channel stdin; print_file None | [f] -> process_file f | _ -> List.iter process_file files; print_totals () (*i*)}(*i*) rocq-9.2.0/tools/update-require000077500000000000000000000042621516144147600165250ustar00rootroot00000000000000#!/bin/sh # This script fully qualifies all the 'Require' statements of the given # targets (or the current directory if none). # # It assumes that all the prerequisites are already installed. The # install location is found using the ROCQLIB, COQC, COQBIN variables if # set, 'coqc' otherwise. # # Option --exclude can be used to ignore a given user contribution. In # particular, it can be used to ignore the current set of files if it # happens to be already installed. # # Option --stdlib can be used to also qualify the files from the standard # library. if test ! "$ROCQLIB"; then if test ${COQBIN##*/}; then COQBIN=$COQBIN/; fi if test ! "$COQC"; then COQC=`which ${COQBIN}coqc`; fi ROCQLIB=`"$COQC" -where` fi stdlib=no exclude="" scan_dir () { (cd $1 ; find $3 -name '*.vo' | sed -e "s,^./,$2,;s,\([^./]*\)/,\1.,g;s,\([^.]*\).vo,\1,") } scan_all_dir () { if test $stdlib = yes; then scan_dir "$ROCQLIB/theories" "Coq." scan_dir "$ROCQLIB/plugins" "Coq." fi scan_dir "$ROCQLIB/user-contrib" "" "$exclude" } create_script () { echo "BEGIN {" scan_all_dir | while read file ; do echo $file | sed -e "s,\(.*\)[.]\([^.]*\), t[\"\2\"] = \"\1.\2\"," done cat <&2 exit 1;; *) dir="$dir $1";; esac shift done script=`tempfile` create_script > $script find $dir -name '*.v' | while read file; do mv $file $file.bak awk -f $script $file.bak > $file done rocq-9.2.0/topbin/000077500000000000000000000000001516144147600137725ustar00rootroot00000000000000rocq-9.2.0/topbin/coqc_bin.ml000066400000000000000000000021051516144147600160770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* exit 1) stderr (fmt^^"%!") let with_worker_gen opts ?(package="rocq-runtime") basename args = Rocqshim.init opts args; let prog = Rocqshim.get_worker_path { package; basename } in let () = if opts.debug_shim then Printf.eprintf "Using %s\n%!" prog in let argv = Array.of_list (prog :: args) in Rocqshim.exec_or_create_process prog argv let with_worker opts kind args = with_worker_gen opts "rocqworker" (("--kind="^kind) :: args) let with_sibling_exe opts prog args = let prog = System.get_toplevel_path prog in let () = if opts.Rocqshim.debug_shim then Printf.eprintf "Using %s\n%!" prog in let argv = Array.of_list (prog :: args) in Rocqshim.exec_or_create_process prog argv type subcommand = | Compile | Repl | ReplWithDrop | NativePrecompile | Check | Votour | PpMlg | Dep | Doc | Wc | Workmgr | Tex | Makefile | Timelog2Html let subcommands = [ ("compile", "Compile a Rocq source file", Compile); ("c", "Alias for compile", Compile); ("repl", "Interactive read-eval-print loop", Repl); ("top", "Alias for repl", Repl); ("repl-with-drop", "repl with Drop command", ReplWithDrop); ("top-with-drop", "Alias for repl-with-drop", ReplWithDrop); ("native-precompile", "Preprocess a compiled Rocq file for use by native_compute", NativePrecompile); ("check", "Check a compiled Rocq file (alias for command rocqchk)", Check); ("votour", "Low level debugging of compiled files", Votour); ("preprocess-mlg", "Preprocess Rocq grammar files (.mlg) to produce OCaml sources", PpMlg); ("pp-mlg", "Alias for preprocess-mlg", PpMlg); ("dep", "Print dependencies for compiling Rocq files", Dep); ("doc", "Generate documentation from a Rocq source file", Doc); ("wc", "Count lines of code in a Rocq source file", Wc); ("workmgr", "Control the number of parallel workers used by Rocq", Workmgr); ("tex", "Process Rocq code in a Latex document", Tex); ("makefile", "Generate a Makefile to compile a Rocq project", Makefile); ("timelog2html", "Combine timing information and a Rocq source file", Timelog2Html); ] let print_usage fmt () = let longest_subcmd = List.fold_left (fun acc (cmd,_,_) -> max acc (String.length cmd)) 0 subcommands in let subcommands = List.map (fun (cmd,doc,_) -> let separator = String.make (3 + longest_subcmd - String.length cmd) ' ' in " "^cmd^separator^doc) subcommands in Printf.fprintf fmt "Usage: rocq [-debug-shim] {-v|--version|--print-version|--help|SUBCOMMAND} [ARGUMENTS...]\n\ \n -v, --version: print human readable version info\ \n --print-version: print machine readable version info\ \n\n\ Supported subcommands:\n\n\ %s\n\ \n\ Use \"rocq subcommand --help\" to get more information about a given subcommand.\n" (String.concat "\n" subcommands) let error_usage () = fatal_error "%a" print_usage () let run_subcommand opts args = function | Compile -> with_worker opts "compile" args | Repl -> with_worker opts "repl" args | ReplWithDrop -> with_worker_gen opts "rocqworker_with_drop" args | NativePrecompile -> with_worker_gen opts "rocqnative" args | Check -> with_sibling_exe opts "rocqchk" args | Votour -> with_sibling_exe opts "votour" args | PpMlg -> Coqpp_main.main args | Dep -> Coqdeplib.Rocqdep_main.main args | Doc -> Coqdoclib.Rocqdoc_main.main ~prog:(Sys.argv.(0) ^ " doc") args | Wc -> Rocqwc.main args | Workmgr -> Rocqworkmgr.main ~prog:(Sys.argv.(0) ^ " workmgr") args | Tex -> Rocqtex.main ~prog:(Sys.argv.(0) ^ " tex") args | Makefile -> Rocqmakefile.main ~prog:[Sys.argv.(0); "makefile"] args | Timelog2Html -> with_worker_gen opts ~package:"rocq-devtools" "timelog2html" args let () = if Array.length Sys.argv < 2 then error_usage (); let args = List.tl (Array.to_list Sys.argv) in let opts, args = Rocqshim.parse_opts args in match args with (* help prints *) | ("-h" | "-H" | "-help" | "--help") :: _ -> Printf.printf "%a%!" print_usage (); exit 0 | cmd :: args -> begin match List.find_opt (fun (cmd',_,_) -> String.equal cmd cmd') subcommands with | Some (_,_,cmd) -> run_subcommand opts args cmd | None -> if Rocqshim.try_run_queries opts (cmd::args) then () else fatal_error "Unknown subcommand %s\n%a%!" cmd print_usage () end | [] -> error_usage () rocq-9.2.0/topbin/rocq.mli000066400000000000000000000012741516144147600154450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val default_root_prefix : DirPath.t val dirpath_of_string : string -> DirPath.t val locate_absolute_library : DirPath.t -> string end = struct let pr_dirpath dp = str (DirPath.to_string dp) let default_root_prefix = DirPath.empty let split_dirpath d = let l = DirPath.repr d in (DirPath.make (List.tl l), List.hd l) type logical_path = DirPath.t let load_paths = ref ([],[] : CUnix.physical_path list * logical_path list) let remove_load_path dir = let physical, logical = !load_paths in load_paths := List.filter2 (fun p d -> p <> dir) physical logical let add_load_path (phys_path,rocq_path) = if CDebug.(get_flag misc) then Feedback.msg_notice (str "path: " ++ pr_dirpath rocq_path ++ str " ->" ++ spc() ++ str phys_path); let phys_path = CUnix.canonical_path_name phys_path in let physical, logical = !load_paths in match List.filter2 (fun p d -> p = phys_path) physical logical with | _,[dir] -> if rocq_path <> dir (* If this is not the default -I . to coqtop *) && not (phys_path = CUnix.canonical_path_name Filename.current_dir_name && rocq_path = default_root_prefix) then begin (* Assume the user is concerned by library naming *) if dir <> default_root_prefix then Feedback.msg_warning (str phys_path ++ strbrk " was previously bound to " ++ pr_dirpath dir ++ strbrk "; it is remapped to " ++ pr_dirpath rocq_path); remove_load_path phys_path; load_paths := (phys_path::fst !load_paths, rocq_path::snd !load_paths) end | _,[] -> load_paths := (phys_path :: fst !load_paths, rocq_path :: snd !load_paths) | _ -> anomaly (Pp.str ("Two logical paths are associated to "^phys_path^".")) let load_paths_of_dir_path dir = let physical, logical = !load_paths in fst (List.filter2 (fun p d -> d = dir) physical logical) let locate_absolute_library dir = (* Search in loadpath *) let pref, base = split_dirpath dir in let loadpath = load_paths_of_dir_path pref in if loadpath = [] then CErrors.user_err (str "No loadpath for " ++ DirPath.print pref); let name = Id.to_string base^".vo" in try let _, file = System.where_in_path ~warn:false loadpath name in file with Not_found -> CErrors.user_err (str "File " ++ str name ++ str " not found in loadpath") let dirpath_of_string s = match String.split_on_char '.' s with | [""] -> default_root_prefix | dir -> DirPath.make (List.rev_map Id.of_string dir) end module Library = struct type library_objects type compilation_unit_name = DirPath.t (* The [*_disk] types below must be kept in sync with the vo representation. *) type library_disk = { md_compiled : Safe_typing.compiled_library; md_syntax_objects : library_objects; md_objects : library_objects; } type library_info type summary_disk = { md_name : compilation_unit_name; md_deps : (compilation_unit_name * Safe_typing.vodigest) array; md_ocaml : string; md_info : library_info; } type library_t = { library_name : compilation_unit_name; library_file : string; library_data : Safe_typing.compiled_library; library_deps : (compilation_unit_name * Safe_typing.vodigest) array; library_digests : Safe_typing.vodigest; library_vm : Vmlibrary.on_disk; } let libraries_table : string DirPath.Map.t ref = ref DirPath.Map.empty let register_loaded_library senv libname file = let () = assert (not @@ DirPath.Map.mem libname !libraries_table) in let () = libraries_table := DirPath.Map.add libname file !libraries_table in let prefix = Nativecode.mod_uid_of_dirpath libname ^ "." in let () = Nativecode.register_native_file prefix in senv let mk_library sd f md digests vm = { library_name = sd.md_name; library_file = f; library_data = md; library_deps = sd.md_deps; library_digests = digests; library_vm = vm; } let summary_seg : summary_disk ObjFile.id = ObjFile.make_id "summary" let library_seg : library_disk ObjFile.id = ObjFile.make_id "library" let intern_from_file f = let ch = System.with_magic_number_check (fun file -> ObjFile.open_in ~file) f in let lsd, digest_lsd = ObjFile.marshal_in_segment ch ~segment:summary_seg in let lmd, digest_lmd = ObjFile.marshal_in_segment ch ~segment:library_seg in let vmlib = Vmlibrary.load ~file:f lsd.md_name ch in ObjFile.close_in ch; System.check_caml_version ~caml:lsd.md_ocaml ~file:f; let open Safe_typing in mk_library lsd f lmd.md_compiled (Dvo_or_vi digest_lmd) vmlib let rec intern_library (needed, contents) dir = (* Look if already listed and consequently its dependencies too *) match DirPath.Map.find dir contents with | lib -> lib.library_digests, (needed, contents) | exception Not_found -> let f = Loadpath.locate_absolute_library dir in let m = intern_from_file f in if not (DirPath.equal dir m.library_name) then user_err (str "The file " ++ str f ++ str " contains library" ++ spc () ++ DirPath.print m.library_name ++ spc () ++ str "and not library" ++ spc() ++ DirPath.print dir ++ str "."); let (needed, contents) = intern_library_deps (needed, contents) dir m f in m.library_digests, (dir :: needed, DirPath.Map.add dir m contents) and intern_library_deps libs dir m from = Array.fold_left (intern_mandatory_library dir from) libs m.library_deps and intern_mandatory_library caller from libs (dir,d) = let digest, libs = intern_library libs dir in if not (Safe_typing.digest_match ~actual:digest ~required:d) then user_err (str "Compiled library " ++ DirPath.print caller ++ str " (in file " ++ str from ++ str ") makes inconsistent assumptions \ over library " ++ DirPath.print dir); libs let register_library senv m = let mp = MPfile m.library_name in let mp', senv = Safe_typing.import m.library_data m.library_vm m.library_digests senv in let () = if not (ModPath.equal mp mp') then anomaly (Pp.str "Unexpected disk module name.") in register_loaded_library senv m.library_name m.library_file let save_library_to env dir f lib = let mp = MPfile dir in let ast = Nativelibrary.dump_library mp env lib in let fn = Filename.dirname f ^"/"^ Nativecode.mod_uid_of_dirpath dir in Nativelib.compile_library ast fn let get_used_load_paths () = String.Set.elements (DirPath.Map.fold (fun m f acc -> String.Set.add (Filename.dirname f) acc) !libraries_table String.Set.empty) let _ = Nativelib.get_load_paths := get_used_load_paths end let add_path ~unix_path:dir ~rocq_root:rocq_dirpath = let open System in if exists_dir dir then begin Loadpath.add_load_path (dir,rocq_dirpath) end else Feedback.msg_warning (str "Cannot open " ++ str dir) let convert_string d = try Id.of_string d with CErrors.UserError _ -> Flags.if_verbose Feedback.msg_warning (str "Directory " ++ str d ++ str " cannot be used as a Rocq identifier (skipped)"); raise_notrace Exit let rocq_root = Id.of_string "Corelib" let add_rec_path ~unix_path ~rocq_root = let open System in if exists_dir unix_path then let dirs = all_subdirs ~unix_path in let prefix = DirPath.repr rocq_root in let convert_dirs (lp, cp) = try let path = List.rev_map convert_string cp @ prefix in Some (lp, Names.DirPath.make path) with Exit -> None in let dirs = List.map_filter convert_dirs dirs in List.iter Loadpath.add_load_path dirs; Loadpath.add_load_path (unix_path, rocq_root) else Feedback.msg_warning (str "Cannot open " ++ str unix_path) let init_load_path_std env ~default_ml () = let corelib = Boot.Env.corelib env |> Boot.Path.to_string in let user_contrib = Boot.Env.user_contrib env |> Boot.Path.to_string in let xdg_dirs = Envars.xdg_dirs in let rocqpath = Envars.coqpath in let () = if default_ml then Nativelib.(include_dirs := default_include_dirs env) in (* NOTE: These directories are searched from last to first *) (* first standard library *) add_rec_path ~unix_path:corelib ~rocq_root:(Names.DirPath.make[rocq_root]); (* then user-contrib *) if Sys.file_exists user_contrib then add_rec_path ~unix_path:user_contrib ~rocq_root:Loadpath.default_root_prefix; (* then directories in XDG_DATA_DIRS and XDG_DATA_HOME *) List.iter (fun s -> add_rec_path ~unix_path:s ~rocq_root:Loadpath.default_root_prefix) (xdg_dirs ~warn:(fun x -> Feedback.msg_warning (str x))); (* then directories in ROCQPATH *) List.iter (fun s -> add_rec_path ~unix_path:s ~rocq_root:Loadpath.default_root_prefix) (rocqpath()) let init_load_path ~boot ~coqlib ~vo_path ~ml_path = let default_ml = CList.is_empty ml_path in let coqenv = Boot.Env.maybe_init ~boot ~coqlib ~warn_ignored_coqlib:CWarnings.warn_ignored_coqlib in let () = match coqenv with | Boot -> () | Env env -> init_load_path_std env ~default_ml:(CList.is_empty ml_path) () in let () = if not default_ml then Nativelib.include_dirs := ml_path in (* always add current directory *) add_path ~unix_path:"." ~rocq_root:Loadpath.default_root_prefix; (* additional loadpath, given with -R/-Q options *) List.iter (fun (unix_path, rocq_root) -> add_rec_path ~unix_path ~rocq_root) (List.rev vo_path) let fb_handler = function | Feedback.{ contents; _ } -> match contents with | Feedback.Message(_lvl,_loc,_qf, msg)-> Format.printf "%s@\n%!" Pp.(string_of_ppcmds msg) | _ -> () let init_rocq () = let senv = Safe_typing.empty_environment in let senv = Safe_typing.set_native_compiler true senv in let () = Safe_typing.allow_delayed_constants := false in let dummy = Names.DirPath.make [Names.Id.of_string_soft "@native"] in let _, senv = Safe_typing.start_library dummy senv in senv let compile senv ~in_file = let lib = Library.intern_from_file in_file in let dir = lib.Library.library_name in (* Require the dependencies **only once** *) let deps, contents = Library.intern_library_deps ([], DirPath.Map.empty) dir lib in_file in let fold senv dep = Library.register_library senv (DirPath.Map.find dep contents) in let senv = List.fold_left fold senv (List.rev deps) in (* Extract the native code and compile it *) let modl = Mod_declarations.mod_type (Safe_typing.module_of_library lib.Library.library_data) in let out_vo = Filename.(remove_extension in_file) ^ ".vo" in (* Replay locally the module being extracted *) let env = match modl with | NoFunctor struc -> let reso = Mod_declarations.mod_delta (Safe_typing.module_of_library lib.Library.library_data) in Modops.add_structure (MPfile dir) struc reso (Safe_typing.env_of_safe_env senv) | MoreFunctor _ -> assert false in Library.save_library_to env dir out_vo modl module Usage : sig val usage : unit -> 'a end = struct let print_usage_channel co command = output_string co command; output_string co "rocq native-precompile options are:\n"; output_string co " -Q dir coqdir map physical dir to logical coqdir\ \n -R dir coqdir synonymous for -Q\ \n\ \n\ \n -boot boot mode\ \n -coqlib dir set coqnative's standard library location\ \n -native-output-dir set the output directory for native objects\ \n -nI dir OCaml include directories for the native compiler (default if not set) \ \n\ \n -h, --help print this list of options\ \n" (* print the usage on standard error *) let print_usage = print_usage_channel stderr let print_usage_coqnative () = print_usage "Usage: rocq native-precompile file\n\n" let usage () = print_usage_coqnative (); flush stderr; exit 1 end type opts = { boot : bool; coqlib : string option; vo_path : (string * DirPath.t) list; ml_path : string list; } let rec parse_args (args : string list) accu = match args with | [] -> CErrors.user_err (Pp.str "parse args error: missing argument") | "-boot" :: rem -> parse_args rem { accu with boot = true} (* We ignore as we don't require Prelude explicitly *) | "-noinit" :: rem -> parse_args rem accu | ("-Q" | "-R") :: d :: p :: rem -> let p = if String.equal p "Coq" then "Corelib" else p in (* -R Coq ... is only used by Dune in conjunction with the -boot option. The above line should be removed once we require an updated version of Dune. *) let p = Loadpath.dirpath_of_string p in let accu = { accu with vo_path = (d, p) :: accu.vo_path } in parse_args rem accu | "-I" :: _d :: rem -> (* Ignore *) parse_args rem accu | "-nI" :: dir :: rem -> let accu = { accu with ml_path = dir :: accu.ml_path } in parse_args rem accu |"-native-output-dir" :: dir :: rem -> Nativelib.output_dir := dir; parse_args rem accu | "-coqlib" :: s :: rem -> parse_args rem { accu with coqlib = Some s } | ("-?"|"-h"|"-H"|"-help"|"--help") :: _ -> Usage.usage () | [file] -> accu, file | args -> let args_msg = String.concat " " args in CErrors.user_err Pp.(str "parse args error, too many arguments: " ++ str args_msg) let () = let _ = Feedback.add_feeder fb_handler in try let opts = { boot = false; coqlib = None; vo_path = []; ml_path = [] } in let opts, in_file = parse_args (List.tl @@ Array.to_list Sys.argv) opts in let () = init_load_path ~boot:opts.boot ~coqlib:opts.coqlib ~vo_path:(List.rev opts.vo_path) ~ml_path:(List.rev opts.ml_path) in let senv = init_rocq () in compile senv ~in_file with exn -> Format.eprintf "Error: @[%a@]@\n%!" Pp.pp_with (CErrors.print exn); let exit_code = CErrors.exit_code exn in exit exit_code rocq-9.2.0/topbin/rocqnative.mli000066400000000000000000000000001516144147600166360ustar00rootroot00000000000000rocq-9.2.0/topbin/rocqshim.ml000066400000000000000000000126121516144147600161530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Printf.eprintf "Error: Could not find package %s.\n%!" package; exit 1 in let exe = if Sys.(os_type = "Win32" || os_type = "Cygwin") then ".exe" else "" in Filename.concat dir (basename^exe) type init_opts = { boot : bool; coqlib : string option; ml_includes : string list; queries : Boot.Usage.query list; } let default_opts = { boot = false; coqlib = None; ml_includes = []; queries = []; } let add_query q opts = { opts with queries = q :: opts.queries } let parse_query = let open Boot.Usage in function | "-config"|"--config" -> Some PrintConfig | "-where" -> Some PrintWhere | "-v"|"-version"|"--version" -> Some PrintVersion | "-print-version"|"--print-version" -> Some PrintMachineReadableVersion | _ -> None let rec parse_args opts = function | [] -> opts | "-boot" :: rest -> parse_args {opts with boot = true} rest | "-coqlib" :: lib :: rest -> parse_args {opts with coqlib = Some lib} rest | "-I" :: ml :: rest -> parse_args {opts with ml_includes = ml :: opts.ml_includes} rest | arg :: rest -> match parse_query arg with | Some q -> parse_args (add_query q opts) rest | None -> parse_args opts rest let parse_args args = let opts = parse_args default_opts args in let opts = { opts with ml_includes = List.rev opts.ml_includes; queries = List.rev opts.queries; } in opts let with_ic file f = let ic = open_in file in try let rc = f ic in close_in ic; rc with e -> close_in ic; raise e let parse_env_line l = try Scanf.sscanf l "%[^=]=%S" (fun name value -> Some(name,value)) with Scanf.Scan_failure _ | End_of_file -> None (** We [putenv] instead of wrapping [getenv] calls because the subprocess also needs the updated env, and usually doesn't have the env file next to its binary. *) let putenv_from_file ~debug () = let base = Filename.dirname Sys.executable_name in let f = base ^ "/coq_environment.txt" in try with_ic f (fun ic -> let () = if debug then Printf.eprintf "using env vars from %s\n%!" f in let rec iter () = match input_line ic with | exception End_of_file -> () | l -> let () = match parse_env_line l with | Some(n,v) -> begin match Sys.getenv_opt n with | None -> Unix.putenv n v | Some _ -> () end | None -> () in iter () in iter ()) with | Sys_error s -> () let make_ocamlpath envopt opts = let boot_ml_path = match envopt with | Boot.Env.Boot -> [] | Boot.Env.Env coqenv -> Boot.Env.Path.[to_string (relative (Boot.Env.runtimelib coqenv) "..")] in let env_ocamlpath = try [Sys.getenv "OCAMLPATH"] with Not_found -> [] in let path = List.concat [opts.ml_includes; boot_ml_path; env_ocamlpath] in let ocamlpathsep = if Sys.unix then ":" else ";" in String.concat ocamlpathsep path let exec_or_create_process prog argv = if Sys.os_type <> "Win32" then Unix.execv prog argv else let pid = Unix.create_process prog argv Unix.stdin Unix.stdout Unix.stderr in if pid = 0 then begin Printf.eprintf "coqc shim: create_process failed\n%!"; exit 127 end; let _, status = Unix.waitpid [] pid in match status with | WEXITED n | WSIGNALED n -> exit n | WSTOPPED _ -> (* is there anything sensible to do with WSTOPPED? can it even happen on windows? *) assert false type opts = { debug_shim : bool } let parse_opts = function | "-debug-shim" :: rest -> { debug_shim = true }, rest | args -> { debug_shim = false }, args (* warning will be produced by the worker *) let warn_ignored_coqlib () = () let boot_env opts = match Boot.Env.print_queries_maybe_init ~boot:opts.boot ~coqlib:opts.coqlib ~warn_ignored_coqlib None opts.queries with | Ok env -> env | Error msg -> Printf.eprintf "%s\n%!" msg; exit 1 let init { debug_shim=debug } args = (* important to putenv before reading OCAMLPATH / ROCQLIB *) let () = putenv_from_file ~debug () in let opts = parse_args args in let coqenv = boot_env opts in let () = match opts.queries with [] -> () | _ :: _ -> exit 0 in let env_ocamlpath = make_ocamlpath coqenv opts in let () = if debug then Printf.eprintf "OCAMLPATH = %s\n%!" env_ocamlpath in Findlib.init ~env_ocamlpath () let try_run_queries { debug_shim=debug } args = let () = putenv_from_file ~debug () in let opts = parse_args args in match opts.queries with | [] -> false | _ :: _ -> let _coqenv = boot_env opts in true rocq-9.2.0/topbin/rocqshim.mli000066400000000000000000000027631516144147600163320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string type opts = { debug_shim : bool } val parse_opts : string list -> opts * string list (** Initialize environment and search paths. *) val init : opts -> string list -> unit (** Returns whether there are queries in the argument list, and if there are print their output. Does not handle PrintHelp queries. *) val try_run_queries : opts -> string list -> bool (** On windows [Unix.execv] creates a new process and exits this one. This confuses dune into thinking we are done, so instead we create_process and wait for it. *) val exec_or_create_process : string -> string array -> 'a rocq-9.2.0/topbin/rocqworker.ml000066400000000000000000000035221516144147600165240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit; loop : unit -> unit } | Compile | Repl let start kind args = match kind with | Worker { init; loop } -> WorkerLoop.start ~init ~loop args | Compile -> Coqc.main args | Repl -> Coqtop.(start_coq coqtop_toplevel args) let () = if Array.length Sys.argv < 2 then error "no argument" () else let argv = List.tl (Array.to_list Sys.argv) in let kind = List.hd argv in let argv = List.tl argv in let kind = match kind with | "--kind=compile" -> Compile | "--kind=repl" -> Repl | "--kind=proof" -> Worker { init = WProof.init_stdout; loop = WProof.main_loop } | "--kind=query" -> Worker { init = WQuery.init_stdout; loop = WQuery.main_loop } | "--kind=tactic" -> Worker { init = WTactic.init_stdout; loop = WTactic.main_loop } | s -> error s () in start kind argv rocq-9.2.0/topbin/rocqworker.mli000066400000000000000000000000001516144147600166610ustar00rootroot00000000000000rocq-9.2.0/topbin/rocqworker_with_drop.ml000066400000000000000000000041111516144147600205760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some (Pp.str (Format.asprintf "%a" Symtable.report_error e)) | _ -> None ) (* Another bit of text is printed in the [include_utilities] file, so the default one is not need *) let () = Clflags.noversion := true let load_module fmt name = if not ((Topdirs.load_file [@ocaml.warning "-3"]) fmt name) then CErrors.user_err Pp.(str ("Could not load plugin " ^ name)) let load_plugin fmt ps = let lib = Mltop.PluginSpec.to_package ps in Topfind.load_deeply [lib] let ml_loop fmt ?init_file () = let init_file = ref init_file in Toploop.add_hook (fun event -> if event = Toploop.After_setup then begin match !init_file with | None -> () | Some f -> init_file := None; (* Run the initialization file only once *) ignore (Coq_byte_config.toploop_use_silently fmt f) end ); Coq_byte_config.compenv_handle_exit_with_status_0 (fun () -> Coq_byte_config.toploop_prep_and_loop fmt) let drop_setup () = let ppf = Format.std_formatter in Mltop.set_top { load_plugin = load_plugin ppf ; load_module = load_module ppf ; add_dir = Topdirs.dir_directory ; ml_loop = ml_loop ppf } (* Main coqtop initialization *) let () = drop_setup (); Coqtop.(start_coq coqtop_toplevel (List.tl (Array.to_list Sys.argv))) rocq-9.2.0/topbin/rocqworker_with_drop.mli000066400000000000000000000000001516144147600207400ustar00rootroot00000000000000rocq-9.2.0/toplevel/000077500000000000000000000000001516144147600143315ustar00rootroot00000000000000rocq-9.2.0/toplevel/ccompile.ml000066400000000000000000000112231516144147600164550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* false | NativeOn {ondemand} -> not ondemand in let mode = copts.compilation_mode in let ext_in, ext_out = match mode with | BuildVo -> ".v", ".vo" | BuildVos -> ".v", ".vos" | BuildVok -> ".v", ".vok" in let long_f_dot_in, long_f_dot_out = ensure_exists_with_prefix ~src:f_in ~tgt:f_out ~src_ext:ext_in ~tgt_ext:ext_out in match mode with | BuildVo | BuildVok -> let doc, sid = Topfmt.(in_phase ~phase:LoadingPrelude) Stm.new_doc Stm.{ doc_type = VoDoc long_f_dot_out; injections; } in let state = { doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time } in let state = Load.load_init_vernaculars opts ~state in let ldir = Stm.get_ldir ~doc:state.doc in Aux_file.(start_aux_file ~aux_file:(aux_file_name_for long_f_dot_out) ~v_file:long_f_dot_in); let dump = match copts.glob_out with | None -> Dumpglob.MultFiles { vofile = long_f_dot_out; vfile = long_f_dot_in } | Some NoGlob -> Dumpglob.NoGlob | Some (GlobFile f) -> Dumpglob.File f in Dumpglob.push_output dump; Dumpglob.dump_string ("F" ^ Names.DirPath.to_string ldir ^ "\n"); let wall_clock1 = Unix.gettimeofday () in let check = Stm.AsyncOpts.(stm_options.async_proofs_mode = APoff) in let source = source ldir long_f_dot_in in let state = Vernac.load_vernac ~echo ~check ~state ~source long_f_dot_in in let fullstate = Stm.finish ~doc:state.doc in ensure_no_pending_proofs ~filename:long_f_dot_in fullstate; let () = Stm.join ~doc:state.doc in let wall_clock2 = Unix.gettimeofday () in (* In .vo production, dump a complete .vo file. *) let () = if mode = BuildVo then Library.save_library_to ~output_native_objects Library.ProofsTodoNone ldir long_f_dot_out in let () = Aux_file.record_in_aux_at "vo_compile_time" (Printf.sprintf "%.3f" (wall_clock2 -. wall_clock1)) in let () = Aux_file.stop_aux_file () in () | BuildVos -> let doc, sid = Topfmt.(in_phase ~phase:LoadingPrelude) Stm.new_doc Stm.{ doc_type = VosDoc long_f_dot_out; injections; } in let state = { doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time } in let state = Load.load_init_vernaculars opts ~state in let ldir = Stm.get_ldir ~doc:state.doc in let source = source ldir long_f_dot_in in let state = Vernac.load_vernac ~echo ~check:false ~source ~state long_f_dot_in in let state = Stm.finish ~doc:state.doc in ensure_no_pending_proofs state ~filename:long_f_dot_in; let () = Stm.snapshot_vos ~doc ~output_native_objects ldir long_f_dot_out in Stm.reset_task_queue (); () let compile opts stm_opts copts injections ~echo ~f_in ~f_out = ignore(CoqworkmgrApi.get 1); compile opts stm_opts injections copts ~echo ~f_in ~f_out; CoqworkmgrApi.giveback 1 let compile_file opts stm_opts copts injections (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 stm_opts copts injections ~echo ~f_in ~f_out) f_in else compile opts stm_opts copts injections ~echo ~f_in ~f_out let compile_file opts stm_opts copts injections = Option.iter (compile_file opts stm_opts copts injections) copts.compile_file rocq-9.2.0/toplevel/ccompile.mli000066400000000000000000000015161516144147600166320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Stm.AsyncOpts.stm_opt -> Coqcargs.t -> Coqargs.injection_command list -> unit rocq-9.2.0/toplevel/colors.ml000066400000000000000000000057441516144147600161760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* false | `EMACS -> false | `ON -> true | `AUTO -> Terminal.has_style Unix.stdout && Terminal.has_style Unix.stderr && (* emacs compilation buffer does not support colors by default, its TERM variable is set to "dumb". *) try Sys.getenv "TERM" <> "dumb" with Not_found -> false in let term_color = if has_color then begin match Envars.getenv_rocq "_COLORS" with | None -> Topfmt.default_styles (); true (* Default colors *) | Some "" -> false (* No color output *) | Some s -> Topfmt.parse_color_config s; true (* Overwrite all colors *) end else begin Topfmt.default_styles (); false (* textual markers, no color *) end in if opts = `EMACS then Topfmt.set_emacs_print_strings () else if not term_color then begin Proof_diffs.write_color_enabled term_color; if Proof_diffs.show_diffs () then (prerr_endline "Error: -diffs requires enabling -color"; exit 1) end; Topfmt.init_terminal_output ~color:term_color let print_style_tags opts = let () = init_color opts in let tags = Topfmt.dump_tags () in let iter (t, st) = let opt = Terminal.eval st ^ t ^ Terminal.reset ^ "\n" in print_string opt in let make (t, st) = let tags = List.map string_of_int (Terminal.repr st) in (t ^ "=" ^ String.concat ";" tags) in let repr = List.map make tags in let () = Printf.printf "ROCQ_COLORS=\"%s\"\n" (String.concat ":" repr) in let () = List.iter iter tags in flush_all () let set_color = function | "yes" | "on" -> `ON | "no" | "off" -> `OFF | "auto" ->`AUTO | _ -> Coqargs.error_wrong_arg ("Error: on/off/auto expected after option color") let parse_extra_colors ~emacs extras = let rec parse_extra color_mode = function | "-color" :: next :: rest -> parse_extra (set_color next) rest | x :: rest -> let color_mode, rest = parse_extra color_mode rest in color_mode, x :: rest | [] -> color_mode, [] in let c, extras = parse_extra `AUTO extras in (* we parse -color but ignore it when -emacs maybe should be the other way (ignore -emacs for color printing if -color is given)? *) let c = if emacs then `EMACS else c in c, extras rocq-9.2.0/toplevel/colors.mli000066400000000000000000000016031516144147600163350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit val parse_extra_colors : emacs:bool -> string list -> color * string list val print_style_tags : color -> unit rocq-9.2.0/toplevel/common_compile.ml000066400000000000000000000055011516144147600176640ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* str "File \"" ++ str f ++ strbrk "\" has been implicitly expanded to \"" ++ str f ++ str ext ++ str "\"") let ensure_ext ext f = if Filename.check_suffix f ext then f else begin warn_file_no_extension (f,ext); f ^ ext end let safe_chop_extension f = try Filename.chop_extension f with Invalid_argument _ -> f let ensure_bname src tgt = let src, tgt = Filename.basename src, Filename.basename tgt in let src, tgt = safe_chop_extension src, safe_chop_extension tgt in if src <> tgt then fatal_error (str "Source and target file names must coincide, directories can differ" ++ fnl () ++ str "Source: " ++ str src ++ fnl () ++ str "Target: " ++ str tgt) let ensure ~ext ~src ~tgt = ensure_bname src tgt; ensure_ext ext tgt let ensure_exists f = if not (Sys.file_exists f) then fatal_error (hov 0 (str "Can't find file" ++ spc () ++ str f)) let ensure_exists_with_prefix ~src ~tgt:f_out ~src_ext ~tgt_ext = let long_f_dot_src = ensure ~ext:src_ext ~src ~tgt:src in ensure_exists long_f_dot_src; let long_f_dot_tgt = match f_out with | None -> safe_chop_extension long_f_dot_src ^ tgt_ext | Some f -> ensure ~ext:tgt_ext ~src:long_f_dot_src ~tgt:f in long_f_dot_src, long_f_dot_tgt let ensure_no_pending_proofs ~filename s = match s.Vernacstate.interp.lemmas with | Some lemmas -> let pfs = Vernacstate.LemmaStack.get_all_proof_names lemmas in fatal_error (str "There are pending proofs in file " ++ str filename ++ str": " ++ (pfs |> List.rev |> prlist_with_sep pr_comma Names.Id.print) ++ str "."); | None -> let pm = s.Vernacstate.interp.program in let what_for = Pp.str ("file " ^ filename) in NeList.iter (fun pm -> Declare.Obls.check_solved_obligations ~what_for ~pm) pm rocq-9.2.0/toplevel/common_compile.mli000066400000000000000000000035361516144147600200430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a (* [ensure ext src tgt] checks that, once stripped by ext, both [src] and [tgt] have the same basename, and returns [tgt] with the extension. [ext] is expected to begin with dot, eg [".v"]. *) val ensure : ext:string -> src:string -> tgt:string -> string (* [ensure_exists f] fails if f does not exist *) val ensure_exists : string -> unit (* [ensure_exists_with_prefix src tgt src_ext tgt_ext] checks that [src] exists (if needed adding the extension) and that [tgt] exists (if needed adding the extension) and returns [src] and [tgt] with their respective extensions. If [tgt] is [None], then it defaults to [src] (with [tgt_ext] as extension). [src_ext] and [tgt_ext] are expected to begin with dot, eg [".v"]. *) val ensure_exists_with_prefix : src:string -> tgt:string option -> src_ext:string -> tgt_ext:string -> string * string (* [chop_extension f] is like Filename.chop_extension but fail safe *) val safe_chop_extension : string -> string (* [ensure_no_pending_proofs ~filename] checks that no proof or obligation is open *) val ensure_no_pending_proofs : filename:string -> Vernacstate.t -> unit rocq-9.2.0/toplevel/coqc.ml000066400000000000000000000070501516144147600156120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* flush_all(); Topfmt.print_err_exn exn; flush_all(); let exit_code = CErrors.exit_code exn in exit exit_code let fix_stm_opts opts stm_opts = match opts.Coqcargs.compilation_mode with | BuildVos -> (* We need to disable error resiliency, otherwise some errors will be ignored in batch mode. c.f. #6707 This is not necessary in the vo case as it fully checks the document anyways. *) let open Stm.AsyncOpts in { stm_opts with async_proofs_mode = APon; async_proofs_n_workers = 0; async_proofs_cmd_error_resilience = false; async_proofs_tac_error_resilience = FNone; } | BuildVo | BuildVok -> stm_opts let custom_coqc : ((Coqcargs.t * Colors.color) * Stm.AsyncOpts.stm_opt, 'b) Coqtop.custom_toplevel = Coqtop.{ parse_extra = (fun opts extras -> let color_mode, extras = Colors.parse_extra_colors ~emacs:opts.config.print_emacs extras in let stm_opts, extras = Stmargs.parse_args opts extras in let coqc_opts = Coqcargs.parse extras in let stm_opts = fix_stm_opts coqc_opts stm_opts in ((coqc_opts, color_mode), stm_opts), []); usage = coqc_specific_usage; init_extra = coqc_init; run = coqc_run; initial_args = Coqargs.default; } let main args = let () = Memtrace_init.init () in Coqtop.start_coq custom_coqc args rocq-9.2.0/toplevel/coqc.mli000066400000000000000000000013031516144147600157560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit rocq-9.2.0/toplevel/coqcargs.ml000066400000000000000000000100471516144147600164670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 0 && s.[0] = '-' let add_compile ?echo copts s = if is_dash_argument s then arg_error Pp.(str "Unknown option " ++ str s); (* make the file name explicit; needed not to break up Rocq 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_file = Some (s,echo) } let add_compile ?echo copts v_file = match copts.compile_file with | Some (first,_) -> arg_error Pp.(str "More than one file to compile: " ++ str first ++ spc() ++ str "and " ++ str v_file) | None -> add_compile ?echo copts v_file 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 noval : t = begin match opt with (* Deprecated options *) | "-opt" | "-byte" as opt -> depr opt; oval | "-image" as opt -> depr opt; let _ = next () in oval (* Non deprecated options *) | "-output-context" -> { oval with output_context = true } (* Verbose == echo mode *) | "-verbose" -> echo := true; oval (* Output filename *) | "-o" -> { oval with compilation_output_name = Some (next ()) } |"-vos" -> Loadpath.load_vos_libraries := true; { oval with compilation_mode = BuildVos } |"-vok" -> Loadpath.load_vos_libraries := true; { oval with compilation_mode = BuildVok } (* Glob options *) |"-no-glob" | "-noglob" -> { oval with glob_out = Some NoGlob } |"-dump-glob" -> let file = next () in { oval with glob_out = Some (GlobFile file) } (* Rest *) | s -> extras := s :: !extras; oval end in parse noval in try let opts, extra = parse default in let args = List.fold_left add_compile opts extra in args with any -> fatal_error any rocq-9.2.0/toplevel/coqcargs.mli000066400000000000000000000033401516144147600166360ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t rocq-9.2.0/toplevel/coqloop.ml000066400000000000000000000500161516144147600163410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string; mutable str : Bytes.t; (* buffer of already read characters *) mutable len : int; (* number of chars in the buffer *) mutable bols : int list; (* offsets in str of beginning of lines *) mutable stream : (unit,char) Gramlib.Stream.t; (* stream of chars *) mutable tokens : Procq.Parsable.t; (* stream of tokens *) mutable start : int } (* stream count of the first char of the buffer *) (* Double the size of the buffer. *) let resize_buffer ibuf = let open Bytes in let nstr = create (2 * length ibuf.str + 1) in blit ibuf.str 0 nstr 0 (length ibuf.str); ibuf.str <- nstr let peek_to_newline ibuf = (* peek to see a newline following the latest command cf #19355 *) let rec aux n = let l = Gramlib.Stream.npeek () n ibuf.stream in if List.length l < n then () else match CList.last l with | '\n' -> () | ' ' | '\t' -> aux (n+1) | _ -> (* nonblank character: the latest command is not the last on this line *) () in aux 1 (* Delete all irrelevant lines of the input buffer. Keep the last line in the buffer (useful when there are several commands on the same line). *) let resynch_buffer ibuf = let () = peek_to_newline ibuf in match ibuf.bols with | ll::_ -> let new_len = ibuf.len - ll in Bytes.blit ibuf.str ll ibuf.str 0 new_len; ibuf.len <- new_len; ibuf.bols <- []; ibuf.start <- ibuf.start + ll | _ -> () (* emacs special prompt tag for easy detection. No special character, to avoid interfering with utf8. Compatibility code removed. *) let emacs_prompt_startstring () = if !print_emacs then "" else "" let emacs_prompt_endstring () = if !print_emacs then "" else "" (* Read a char in an input channel, displaying a prompt at every beginning of line. *) let prompt_char doc ic ibuf () = let bol = match ibuf.bols with | ll::_ -> Int.equal ibuf.len ll | [] -> Int.equal ibuf.len 0 in if bol && not !print_emacs then top_stderr (str (ibuf.prompt doc)); try let c = input_char ic in if c == '\n' then ibuf.bols <- (ibuf.len+1) :: ibuf.bols; if ibuf.len == Bytes.length ibuf.str then resize_buffer ibuf; Bytes.set ibuf.str ibuf.len c; ibuf.len <- ibuf.len + 1; Some c with End_of_file -> None (* Functions to print underlined locations from an input buffer. *) module TopErr = struct (* Given a location, returns the list of locations of each line. The last line is returned separately. It also checks the location bounds. *) let get_bols_of_loc ibuf (bp,ep) = let add_line (b,e) lines = if b < 0 || e < b then CErrors.anomaly (Pp.str "Bad location."); match lines with | ([],None) -> ([], Some (b,e)) | (fl,oe) -> ((b,e)::fl, oe) in let rec lines_rec ba after = function | [] -> add_line (0,ba) after | ll::_ when ll <= bp -> add_line (ll,ba) after | ll::fl -> let nafter = if ll < ep then add_line (ll,ba) after else after in lines_rec ll nafter fl in let bols = match ibuf.bols with | [] -> [ibuf.len+1] (* no newline at the end of the command, pretend there was one *) | _ :: _ as bols -> bols in let (fl,ll) = lines_rec ibuf.len ([],None) bols in (fl,Option.get ll) let dotted_location (b,e) = if e-b < 3 then ("", String.make (e-b) ' ') else (String.make (e-b-1) '.', " ") let blanch_utf8_string s bp ep = let open Bytes in let s' = make (ep-bp) ' ' in let j = ref 0 in for i = bp to ep - 1 do let n = Char.code (get s i) in (* Heuristic: assume utf-8 chars are printed using a single fixed-size char and therefore contract all utf-8 code into one space; in any case, preserve tabulation so that its effective interpretation in terms of spacing is preserved *) if get s i == '\t' then set s' !j '\t'; if n < 0x80 || 0xC0 <= n then incr j done; Bytes.sub_string s' 0 !j let adjust_loc_buf ib loc = let open Loc in { loc with ep = loc.ep - ib.start; bp = loc.bp - ib.start } let print_highlight_location ib loc = let (bp,ep) = Loc.unloc loc in let highlight_lines = match get_bols_of_loc ib (bp,ep) with | ([],(bl,el)) -> let shift = blanch_utf8_string ib.str bl bp in let span = String.length (blanch_utf8_string ib.str bp ep) in (str"> " ++ str(Bytes.sub_string ib.str bl (el-bl-1)) ++ fnl () ++ str"> " ++ str(shift) ++ str(String.make span '^')) | ((b1,e1)::ml,(bn,en)) -> let (d1,s1) = dotted_location (b1,bp) in let (dn,sn) = dotted_location (ep,en) in let l1 = (str"> " ++ str d1 ++ str s1 ++ str(Bytes.sub_string ib.str bp (e1-bp))) in let li = prlist (fun (bi,ei) -> (str"> " ++ str(Bytes.sub_string ib.str bi (ei-bi)))) ml in let ln = (str"> " ++ str(Bytes.sub_string ib.str bn (ep-bn)) ++ str sn ++ str dn) in (l1 ++ li ++ ln) in highlight_lines let valid_buffer_loc ib loc = let (b,e) = Loc.unloc loc in b-ib.start >= 0 && e-ib.start <= ib.len && b<=e (* Toplevel error explanation. *) let error_info_for_buffer ?loc buf = match loc with | None -> Topfmt.pr_phase ?loc () | Some loc -> let fname = loc.Loc.fname in (* We are in the toplevel *) match fname with | Loc.ToplevelInput -> let nloc = adjust_loc_buf buf loc in if valid_buffer_loc buf loc then match Topfmt.pr_phase ~loc:nloc () with | None -> None | Some hd -> Some (hd ++ fnl () ++ print_highlight_location buf nloc) (* in the toplevel, but not a valid buffer *) else Topfmt.pr_phase ~loc () (* we are in batch mode, don't adjust location *) | Loc.InFile _ -> Topfmt.pr_phase ~loc () (* Actual printing routine *) let print_error_for_buffer ?loc ?qf lvl msg buf = let pre_hdr = error_info_for_buffer ?loc buf in if !print_emacs then Topfmt.emacs_logger ?pre_hdr lvl msg else Topfmt.std_logger ?pre_hdr ?qf lvl msg (* let print_toplevel_parse_error (e, info) buf = let loc = Loc.get_loc info in let lvl = Feedback.Error in let msg = CErrors.iprint (e, info) in print_error_for_buffer ?loc lvl msg buf *) end (*s The Rocq prompt is the name of the focused proof, if any, and "Rocq" otherwise. We trap all exceptions to prevent the error message printing from cycling. *) let make_prompt () = try (Names.Id.to_string (Vernacstate.Declare.get_current_proof_name ())) ^ " < " with Vernacstate.Declare.NoCurrentProof -> "Rocq < " [@@ocaml.warning "-3"] (* the rocq prompt added to the default one when in emacs mode The prompt contains the current state label [n] (for global backtracking) and the current proof state [p] (for proof backtracking) plus the list of open (nested) proofs (for proof aborting when backtracking). It looks like: "n |lem1|lem2|lem3| p < " *) let make_emacs_prompt doc = let statnum = Stateid.to_string (Stm.get_current_state ~doc) in let dpth = Stm.current_proof_depth ~doc in let pending = Stm.get_all_proof_names ~doc in let pendingprompt = List.fold_left (fun acc x -> acc ^ (if CString.is_empty acc then "" else "|") ^ Names.Id.to_string x) "" pending in let proof_info = if dpth >= 0 then string_of_int dpth else "0" in if !print_emacs then statnum ^ " |" ^ pendingprompt ^ "| " ^ proof_info ^ " < " else "" (* A buffer to store the current command read on stdin. It is * initialized when a vernac command is immediately followed by "\n", * or after a Drop. *) let top_buffer = let pr doc = emacs_prompt_startstring() ^ make_prompt() ^ make_emacs_prompt doc ^ emacs_prompt_endstring() in let stream = Gramlib.Stream.empty () in { prompt = pr; str = Bytes.empty; len = 0; bols = []; stream; tokens = Procq.Parsable.make stream; start = 0 } (* Intialize or reinitialize the char stream *) let reset_input_buffer ~state = let stream = Gramlib.Stream.from (prompt_char state.Vernac.State.doc stdin top_buffer) in top_buffer.str <- Bytes.empty; top_buffer.len <- 0; top_buffer.bols <- []; top_buffer.stream <- stream; top_buffer.tokens <- Procq.Parsable.make stream; top_buffer.start <- 0 let set_prompt prompt = top_buffer.prompt <- (fun doc -> emacs_prompt_startstring() ^ prompt () ^ emacs_prompt_endstring()) (* Read the input stream until a dot is encountered *) let parse_to_dot = let rec dot kwstate st = match Gramlib.LStream.next kwstate st with | Some (Tok.KEYWORD ("."|"...")) -> Ok () | Some Tok.EOI -> Ok () | Some _ -> dot kwstate st | None -> Error () in Procq.Entry.(of_parser "Coqtoplevel.dot" { parser_fun = dot }) (* If an error occurred while parsing, we try to read the input until a dot token is encountered. We assume that when a lexer error occurs, at least one char was eaten *) let rec discard_to_dot () = try Procq.Entry.parse parse_to_dot top_buffer.tokens with | CLexer.Error.E _ -> (* Lexer failed *) discard_to_dot () | e when CErrors.noncritical e -> () let read_sentence ~state input = (* XXX: careful with ignoring the state Eugene!*) let open Vernac.State in try Stm.parse_sentence ~doc:state.doc state.sid ~entry:G_toplevel.vernac_toplevel input with reraise -> let reraise = Exninfo.capture reraise in (* When typing Ctrl-C, two situations may arise: - if a lexer/parsing arrived first, the rest of the ill-formed sentence needs to be discarded, and, if Ctrl-C is found while trying to discarding (in discard_to_dot), let it bypass the reporting of the parsing error and report the Sys.Break instead. - if a Ctrl-C arrives after a valid start of sentence, do not discard_to_dot since Ctrl-C is the last read character and there is nothing left to discard. *) (match fst reraise with | Sys.Break -> Pp.pp_with !Topfmt.err_ft (Pp.fnl ()) | _ -> try discard_to_dot () with Sys.Break -> Pp.pp_with !Topfmt.err_ft (Pp.fnl ()); raise Sys.Break); (* The caller of read_sentence does the error printing now, this should be re-enabled once we rely on the feedback error printer again *) (* TopErr.print_toplevel_parse_error reraise top_buffer; *) Exninfo.iraise reraise let extract_default_loc loc doc_id sid : Loc.t option = match loc with | Some _ -> loc | None -> try let doc = Stm.get_doc doc_id in Option.cata (fun {CAst.loc} -> loc) None Stm.(get_ast ~doc sid) with _ -> loc (** Coqloop Console feedback handler *) let coqloop_feed (fb : Feedback.feedback) = let open Feedback in match fb.contents with | Processed -> () | Incomplete -> () | Complete -> () | ProcessingIn _ -> () | InProgress _ -> () | WorkerStatus (_,_) -> () | AddedAxiom -> () | GlobRef (_,_,_,_,_) -> () | GlobDef (_,_,_,_) -> () | FileDependency (_,_) -> () | FileLoaded (_,_) -> () | Custom (_,_,_) -> () (* Re-enable when we switch back to feedback-based error printing *) | Message (Error,loc,_,msg) -> () (* TopErr.print_error_for_buffer ?loc lvl msg top_buffer *) | Message (Warning,loc,qf,msg) -> let loc = extract_default_loc loc fb.doc_id fb.span_id in TopErr.print_error_for_buffer ?loc ~qf Warning msg top_buffer | Message (lvl,loc,qf,msg) -> TopErr.print_error_for_buffer ?loc ~qf lvl msg top_buffer (** Main rocq loop : read vernacular expressions until Drop is entered. Ctrl-C is handled internally as Sys.Break instead of aborting Rocq. Normally, the only exceptions that can come out of [do_vernac] and exit the loop are Drop and Quit. Any other exception there indicates an issue with [print_toplevel_error] above. *) (* Flush in a compatible order with 8.5 *) (* This mimics the semantics of the old Pp.flush_all *) let loop_flush_all () = flush stderr; flush stdout; Format.pp_print_flush !Topfmt.std_ft (); Format.pp_print_flush !Topfmt.err_ft () (* Goal equality heuristic. *) let pequal cmp1 cmp2 (a1,a2) (b1,b2) = cmp1 a1 b1 && cmp2 a2 b2 let evleq e1 e2 = CList.equal Evar.equal e1 e2 let cproof p1 p2 = let Proof.{goals=a1;stack=a2;sigma=sigma1} = Proof.data p1 in let Proof.{goals=b1;stack=b2;sigma=sigma2} = Proof.data p2 in evleq a1 b1 && CList.equal (pequal evleq evleq) a2 b2 && CList.equal Evar.equal (Evd.shelf sigma1) (Evd.shelf sigma2) && Evar.Set.equal (Evd.given_up sigma1) (Evd.given_up sigma2) (* todo: could add other Set/Unset commands, such as "Printing Universes" *) let print_anyway_opts = [ [ "Diffs" ]; ] let print_anyway c = let open Vernacexpr in match c.expr with | VernacSynterp (VernacSetOption (_, opt, _)) -> List.mem opt print_anyway_opts | _ -> false (* print the proof step, possibly with diffs highlighted, *) let print_and_diff oldp proof = let output = if Proof_diffs.show_diffs () then try Printer.pr_open_subgoals ~oldp proof with Pp_diff.Diff_Failure msg -> begin (* todo: print the unparsable string (if we know it) *) Feedback.msg_warning Pp.(str ("Diff failure: " ^ msg) ++ cut() ++ str "Showing results without diff highlighting" ); Printer.pr_open_subgoals proof end else Printer.pr_open_subgoals proof in Feedback.msg_notice output (* We try to behave better when goal printing raises an exception [usually Ctrl-C] This is mostly a hack as we should protect printing in a more generic way, but that'll do for now *) let top_goal_print ~doc c oldp newp = try let proof_changed = not (Option.equal cproof oldp (Some newp)) in let print_goals = proof_changed && Vernacstate.Declare.there_are_pending_proofs () || print_anyway c in if not !Flags.quiet && print_goals then begin let dproof = Stm.get_prev_proof ~doc (Stm.get_current_state ~doc) in print_and_diff (Some dproof) newp end with | exn -> let (e, info) = Exninfo.capture exn in let loc = Loc.get_loc info in let msg = CErrors.iprint (e, info) in TopErr.print_error_for_buffer ?loc Feedback.Error msg top_buffer [@@ocaml.warning "-3"] let { Goptions.get = exit_on_error } = let open Goptions in declare_bool_option_and_ref ~key:["Rocqtop";"Exit";"On";"Error"] ~value:false () let show_proof_diff_cmd ~state diff_opt = let open Vernac.State in match state.proof with | None -> CErrors.user_err (str "No proofs to diff.") | Some proof -> let old = Stm.get_prev_proof ~doc:state.doc state.sid in Proof_diffs.diff_proofs ~flags:(PrintingFlags.current()) ~diff_opt ?old proof let ml_toplevel_state = ref None let ml_toplevel_include_ran = ref false (* Initialises the Ocaml toplevel before launching it, so that it can find the "include" file in the *source* directory *) let init_ocaml_path () = let corelib = Findlib.package_directory "rocq-runtime" in let add_subdir dl = Mltop.add_ml_dir (Filename.concat corelib dl) in List.iter add_subdir ("dev" :: Coq_config.all_src_dirs) let init_and_run_ml_toploop () = init_ocaml_path (); Flags.with_option Flags.in_ml_toplevel (Mltop.ocaml_toploop ~init_file:"ml_toplevel/include") () (* We return whether the execution should continue and a new state *) let process_toplevel_command ~state stm = let open Vernac.State in let open G_toplevel in match stm with | VernacDrop -> if Mltop.is_ocaml_top() then begin (* Save the last state for [go ()] *) ml_toplevel_state := Some state; (* Initialise and launch the OCaml toplevel *) init_and_run_ml_toploop (); (* Reinitialize the char stream *) reset_input_buffer ~state; (* [go ()] was potentially executed β€” get the new state *) let state = Option.get !ml_toplevel_state in true, state end else begin Feedback.msg_warning (str "There is no ML toplevel."); true, state end | VernacBackTo bid -> let bid = Stateid.of_int bid in let doc, res = Stm.edit_at ~doc:state.doc bid in assert (res = Stm.NewTip); true, { state with doc; sid = bid } | VernacQuit -> false, state | VernacControl { CAst.loc; v=c } -> let nstate = Vernac.process_expr ~state (CAst.make ?loc c) in let () = if not !print_emacs then match nstate.proof with | None -> () | Some proof -> top_goal_print ~doc:state.doc c state.proof proof in true, nstate | VernacShowGoalAt { gid; sid } -> let proof = Stm.get_proof ~doc:state.doc (Stateid.of_int sid) in let goal = Printer.pr_goal_emacs ~proof gid sid in let () = Feedback.msg_notice goal in true, state | VernacShowGoal goalref -> let open Vernac.State in begin match state.proof with | None -> CErrors.user_err (str "This command requires an open proof.") | Some proof -> let oldp = Stm.get_prev_proof ~doc:state.doc state.sid in Feedback.msg_notice @@ Vernacentries.show_goal goalref proof (Some oldp); end; true, state | VernacShowProofDiffs diff_opt -> (* We print nothing if there are no goals left *) if not (Proof_diffs.color_enabled ()) then CErrors.user_err Pp.(str "Show Proof Diffs requires setting the \"-color\" command line argument to \"on\" or \"auto\".") else let out = show_proof_diff_cmd ~state diff_opt in Feedback.msg_notice out; true, state let read_and_execute ~state = try let input = top_buffer.tokens in match read_sentence ~state input with | Some stm -> process_toplevel_command ~state stm (* End of file *) | None -> top_stderr (fnl ()); false, state with (* Exception printing should be done by the feedback listener, however this is not yet ready so we rely on the exception for now. *) | Sys_blocked_io -> (* the parser doesn't like nonblocking mode, cf #10918 *) let msg = Pp.(strbrk "Coqtop needs the standard input to be in blocking mode." ++ spc() ++ str "One way of clearing the non-blocking flag is through Python:" ++ fnl() ++ str " import os" ++ fnl() ++ str " os.set_blocking(0, True)") in TopErr.print_error_for_buffer Feedback.Error msg top_buffer; exit 1 | any -> let (e, info) = Exninfo.capture any in let loc = Loc.get_loc info in let msg = CErrors.iprint (e, info) in TopErr.print_error_for_buffer ?loc Feedback.Error msg top_buffer; if exit_on_error () then exit 1; true, state let loop ~state = (* Initialize buffer *) reset_input_buffer ~state; Flags.without_option Flags.in_ml_toplevel (fun () -> (* The main loop, as a tail-recursive function *) let rec aux state = loop_flush_all (); top_stderr (fnl()); let open Vernac.State in if !print_emacs then top_stderr (str (top_buffer.prompt state.doc)); resynch_buffer top_buffer; let new_running, new_state = read_and_execute ~state:state in if new_running then (aux [@ocaml.tailcall]) new_state else new_state in aux state ) () let run ~opts ~state = let open Coqargs in print_emacs := opts.config.print_emacs; (* We initialize the console only if we run the toploop_run *) let tl_feed = Feedback.add_feeder coqloop_feed in let _ : Vernac.State.t = loop ~state in Feedback.del_feeder tl_feed rocq-9.2.0/toplevel/coqloop.mli000066400000000000000000000026601516144147600165140ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string) -> unit (** Toplevel feedback printer. *) val coqloop_feed : Feedback.feedback -> unit (** State tracked while in the OCaml toplevel *) val ml_toplevel_state : Vernac.State.t option ref (** Whether the "include" file was already run at least once *) val ml_toplevel_include_ran : bool ref (** The main loop *) val loop : state:Vernac.State.t -> Vernac.State.t (** Main entry point of Rocq: read and execute vernac commands. *) val run : opts:Coqargs.t -> state:Vernac.State.t -> unit rocq-9.2.0/toplevel/coqrc.ml000066400000000000000000000037471516144147600160050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if CUnix.file_readable_p rcfile then Vernac.load_vernac ~echo:false ~check:true ~state rcfile else raise (Sys_error ("Cannot read rcfile: "^ rcfile)) | None -> try let warn x = Feedback.msg_warning (Pp.str x) in let inferedrc = List.find CUnix.file_readable_p [ Envars.xdg_config_home warn / rcdefaultname^"."^Coq_config.version; Envars.xdg_config_home warn / rcdefaultname; Envars.home ~warn / "."^rcdefaultname^"."^Coq_config.version; Envars.home ~warn / "."^rcdefaultname ] in Vernac.load_vernac ~echo:false ~check:true ~state inferedrc with Not_found -> state (* Flags.if_verbose mSGNL (str ("No coqrc or coqrc."^Coq_config.version^ " found. Skipping rcfile loading.")) *) with reraise -> let reraise = Exninfo.capture reraise in let () = Feedback.msg_info (Pp.str"Load of rcfile failed.") in Exninfo.iraise reraise rocq-9.2.0/toplevel/coqrc.mli000066400000000000000000000013671516144147600161520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* state:Vernac.State.t -> Vernac.State.t rocq-9.2.0/toplevel/coqtop.ml000066400000000000000000000160211516144147600161700ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Coq_config.version | Some (Env env) -> try let revision = Boot.Env.revision env |> Boot.Path.to_string in let ch = open_in revision in let ver = input_line ch in let rev = input_line ch in let () = close_in ch in Printf.sprintf "%s (%s)" ver rev with Sys_error _ | End_of_file -> Coq_config.version let print_header ~boot () = Feedback.msg_info (str "Welcome to Rocq " ++ str (get_version ~boot)); flush_all () (******************************************************************************) (* Fatal Errors *) (******************************************************************************) (** Prints info which is either an error or an anomaly and then exits with the appropriate error code *) let fatal_error_exn exn = Topfmt.(in_phase ~phase:Initialization print_err_exn exn); flush_all (); let exit_code = CErrors.exit_code exn in exit exit_code type ('a,'b) custom_toplevel = { parse_extra : Coqargs.t -> string list -> 'a * string list ; usage : Boot.Usage.specific_usage ; init_extra : 'a -> Coqargs.injection_command list -> opts:Coqargs.t -> 'b ; initial_args : Coqargs.t ; run : 'a -> opts:Coqargs.t -> 'b -> unit } (** Main init routine *) let init_toplevel { parse_extra; init_extra; usage; initial_args } args = Coqinit.init_ocaml (); let opts, customopts = Coqinit.parse_arguments ~parse_extra ~initial_args args in Stm.init_process (snd customopts); let () = Coqinit.init_runtime ~usage opts in let () = Coqinit.init_document opts in (* This state will be shared by all the documents *) Stm.init_core (); let customstate = init_extra ~opts customopts (Coqargs.injection_commands opts) in opts, customopts, customstate let start_coq custom args = let init_feeder = Feedback.add_feeder Coqloop.coqloop_feed in (* Init phase *) let opts, custom_opts, state = try init_toplevel custom args with any -> flush_all(); fatal_error_exn any in Feedback.del_feeder init_feeder; (* Run phase *) custom.run ~opts custom_opts state (** ****************************************) (** Specific support for rocq repl executable *) let ltac_debug_answer = let open DebugHook.Answer in function | Prompt prompt -> (* No newline *) Format.fprintf !Topfmt.err_ft "@[%a@]%!" Pp.pp_with prompt | Goal g -> Format.fprintf !Topfmt.err_ft "@[%a@]@\n%!" Pp.pp_with g | Output o -> Format.fprintf !Topfmt.err_ft "@[%a@]@\n%!" Pp.pp_with o | Init -> Format.fprintf !Topfmt.err_ft "@[%a@]@\n%!" Pp.pp_with (str "Init") | Stack _ | Vars _ -> CErrors.anomaly (str "ltac_debug_answer: unsupported Answer type") let ltac_debug_parse () = let open DebugHook in let act = try Action.parse (read_line ()) with End_of_file -> Ok Action.Interrupt in match act with | Ok act -> act | Error error -> ltac_debug_answer (Answer.Output (str error)); Action.Failed type query = PrintTags | PrintModUid of string list type run_mode = Interactive | Batch | Query of query type toplevel_options = { run_mode : run_mode; color_mode : Colors.color; } let init_document opts stm_options injections = (* Rocq 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. *) (* Next line allows loading .vos files when in interactive mode *) Loadpath.load_vos_libraries := true; let open Vernac.State in let doc, sid = Stm.(new_doc { doc_type = Interactive opts.config.logic.toplevel_name; injections; }) in { doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time } let init_toploop opts stm_opts injections = let state = init_document opts stm_opts injections in let state = Load.load_init_vernaculars opts ~state in state let coqtop_init ({ run_mode; color_mode }, async_opts) injections ~opts = if run_mode != Interactive then Flags.quiet := true; Colors.init_color color_mode; Flags.if_verbose (print_header ~boot:opts.pre.boot) (); DebugHook.Intf.(set { read_cmd = ltac_debug_parse ; submit_answer = ltac_debug_answer ; isTerminal = true }); init_toploop opts async_opts injections let coqtop_parse_extra opts extras = let rec parse_extra run_mode = function | "-batch" :: rest -> parse_extra Batch rest | "-list-tags" :: rest -> Query PrintTags, [] | "-print-mod-uid" :: rest -> Query (PrintModUid rest), [] | x :: rest -> let run_mode, rest = parse_extra run_mode rest in run_mode, x :: rest | [] -> run_mode, [] in let run_mode, extras = parse_extra Interactive extras in let color_mode, extras = Colors.parse_extra_colors ~emacs:opts.config.print_emacs extras in let async_opts, extras = Stmargs.parse_args opts extras in ({ run_mode; color_mode}, async_opts), extras let fix_windows_dirsep s = if Sys.win32 then Str.(global_replace (regexp "\\(.\\)\\") "\\1/" s) else s let get_native_name s = (* We ignore even critical errors because this mode has to be super silent *) try fix_windows_dirsep @@ Filename.(List.fold_left concat (dirname s) [ !Nativelib.output_dir ; Library.native_name_from_filename s ]) with _ -> "" let coqtop_run ({ run_mode; color_mode },_) ~opts state = match run_mode with | Interactive -> Coqloop.run ~opts ~state; | Query PrintTags -> Colors.print_style_tags color_mode; exit 0 | Query (PrintModUid sl) -> let s = String.concat " " (List.map get_native_name sl) in print_endline s; exit 0 | Batch -> exit 0 let coqtop_specific_usage = Boot.Usage.{ executable_name = "rocq repl"; extra_args = ""; extra_options = "\n\ rocq repl specific options:\n\ \n -batch batch mode (exits after interpretation of command line)\ \n" } let coqtop_toplevel = { parse_extra = coqtop_parse_extra ; usage = coqtop_specific_usage ; init_extra = coqtop_init ; run = coqtop_run ; initial_args = Coqargs.default } rocq-9.2.0/toplevel/coqtop.mli000066400000000000000000000041561516144147600163470ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string list -> 'a * string list ; usage : Boot.Usage.specific_usage ; init_extra : 'a -> Coqargs.injection_command list -> opts:Coqargs.t -> 'b ; initial_args : Coqargs.t ; run : 'a -> opts:Coqargs.t -> 'b -> unit } (** The generic Rocq main module. [start custom] will parse the command line, print the banner, initialize the load path, load the input state, load the files given on the command line, load the resource file, produce the output state if any, and finally will launch [custom.run]. The [string list] argument is typically [List.tl (Array.to_list Sys.argv)]. *) val start_coq : ('a * Stm.AsyncOpts.stm_opt,'b) custom_toplevel -> string list -> unit (** Prepare state for interactive loop *) val init_toploop : Coqargs.t -> Stm.AsyncOpts.stm_opt -> Coqargs.injection_command list -> Vernac.State.t (** The specific characterization of the coqtop_toplevel *) type query = PrintTags | PrintModUid of string list type run_mode = Interactive | Batch | Query of query type toplevel_options = { run_mode : run_mode; color_mode : Colors.color; } val coqtop_toplevel : (toplevel_options * Stm.AsyncOpts.stm_opt,Vernac.State.t) custom_toplevel val ltac_debug_answer : DebugHook.Answer.t -> unit val ltac_debug_parse : unit -> DebugHook.Action.t rocq-9.2.0/toplevel/dune000066400000000000000000000012701516144147600152070ustar00rootroot00000000000000(library (name toplevel) (public_name rocq-runtime.toplevel) (synopsis "Rocq's Interactive Shell [terminal-based]") (wrapped false) ; until ocaml/dune#4892 fixed ; (private_modules g_toplevel) (libraries rocq-runtime.stm (select memtrace_init.ml from (memtrace -> memtrace_init.memtrace.ml) (!memtrace -> memtrace_init.default.ml)))) (deprecated_library_name (old_public_name coq-core.toplevel) (new_public_name rocq-runtime.toplevel)) ; Interp provides the `zarith` library to plugins, we could also use ; -linkall in the plugins file, to be discussed. (rule (targets g_toplevel.ml) (deps (:mlg g_toplevel.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/toplevel/g_toplevel.mlg000066400000000000000000000050131516144147600171710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* > lk_kw "Goal" >> lk_nat end let test_show_natural = let open Procq.Lookahead in to_entry "test_show_natural" begin lk_kw "Show" >> lk_nat end } GRAMMAR EXTEND Gram GLOBAL: vernac_toplevel; vernac_toplevel: FIRST [ [ IDENT "Drop"; "." -> { Some VernacDrop } | IDENT "Quit"; "." -> { Some VernacQuit } | IDENT "BackTo"; n = natural; "." -> { Some (VernacBackTo n) } (* show a goal for the specified proof state *) | test_show_goal; IDENT "Show"; IDENT "Goal"; gid = natural; IDENT "at"; sid = natural; "." -> { Some (VernacShowGoalAt {gid; sid}) } | IDENT "Show"; IDENT "Proof"; IDENT "Diffs"; removed = OPT [ IDENT "removed" -> { () } ]; "." -> { Some (VernacShowProofDiffs (if removed = None then Proof_diffs.DiffOn else Proof_diffs.DiffRemoved)) } | IDENT "Show"; "."-> { Some (VernacShowGoal OpenSubgoals) } | test_show_natural; IDENT "Show"; n = natural; "." -> { Some (VernacShowGoal (NthGoal n)) } | IDENT "Show"; IDENT "Diffs"; id = qualid; "." -> { Some (VernacShowGoal (GoalId id)) } | cmd = Pvernac.Vernac_.main_entry -> { match cmd with | None -> None | Some v -> Some (VernacControl v) } ] ] ; END { let vernac_toplevel pm = Pvernac.Unsafe.set_tactic_entry pm; vernac_toplevel } rocq-9.2.0/toplevel/g_toplevel.mli000066400000000000000000000006231516144147600171750ustar00rootroot00000000000000 type vernac_toplevel = VernacBackTo of int | VernacDrop | VernacQuit | VernacControl of Vernacexpr.vernac_control | VernacShowGoalAt of { gid : int; sid : int; } | VernacShowGoal of Vernacexpr.goal_reference | VernacShowProofDiffs of Proof_diffs.diffOpt val test_show_goal : unit Procq.Entry.t val vernac_toplevel : Pvernac.proof_mode option -> vernac_toplevel option Procq.Entry.t rocq-9.2.0/toplevel/load.ml000066400000000000000000000033551516144147600156100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Coqrc.load_rcfile ~rcfile:opts.config.rcfile ~state) () else begin Flags.if_verbose Feedback.msg_info (str"Skipping rcfile loading."); state end let load_vernacular opts ~state = List.fold_left (fun state (f_in, echo) -> let s = Loadpath.locate_file f_in in (* Should make the beautify logic clearer *) let load_vernac f = Vernac.load_vernac ~echo ~check:true ~state f in if !Flags.beautify then Flags.with_option Flags.beautify_file load_vernac f_in else load_vernac s ) state opts.pre.load_vernacular_list let load_init_vernaculars opts ~state = let state = load_init_file opts ~state in let state = load_vernacular opts ~state in state rocq-9.2.0/toplevel/load.mli000066400000000000000000000015141516144147600157540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* state:Vernac.State.t-> Vernac.State.t rocq-9.2.0/toplevel/memtrace_init.default.ml000066400000000000000000000000211516144147600211170ustar00rootroot00000000000000let init () = () rocq-9.2.0/toplevel/memtrace_init.memtrace.ml000066400000000000000000000000551516144147600212770ustar00rootroot00000000000000let init () = Memtrace.trace_if_requested () rocq-9.2.0/toplevel/memtrace_init.mli000066400000000000000000000000301516144147600176450ustar00rootroot00000000000000val init : unit -> unit rocq-9.2.0/toplevel/vernac.ml000066400000000000000000000203641516144147600161460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let len = loc.ep - loc.bp in seek_in in_chan loc.bp; Feedback.msg_notice @@ str @@ really_input_string in_chan len ) loc type time_output = | ToFeedback | ToChannel of Format.formatter let make_time_output = function | Coqargs.ToFeedback -> ToFeedback | ToFile f -> let ch = open_out f in let fch = Format.formatter_of_out_channel ch in let close () = Format.pp_print_flush fch (); close_out ch in at_exit close; ToChannel fch module State = struct type t = { doc : Stm.doc; sid : Stateid.t; proof : Proof.t option; time : time_output option; } end let emit_time state com tstart tend = match state.State.time with | None -> () | Some time -> let pp = Topfmt.pr_cmd_header com ++ System.fmt_time_difference tstart tend in match time with | ToFeedback -> Feedback.msg_notice pp | ToChannel ch -> Pp.pp_with ch (pp ++ fnl()) let interp_vernac ~check ~state ({CAst.loc;_} as com) = let open State in try let doc, nsid, ntip = Stm.add ~doc:state.doc ~ontop:state.sid (not !Flags.quiet) com in (* Main STM interaction *) if ntip <> Stm.NewAddTip then anomaly (str "vernac.ml: We got an unfocus operation on the toplevel!"); (* Force the command *) let () = if check then Stm.observe ~doc nsid in let new_proof = Vernacstate.Declare.give_me_the_proof_opt () [@ocaml.warning "-3"] in { state with doc; sid = nsid; proof = new_proof; } with reraise -> let (reraise, info) = Exninfo.capture reraise in let info = (* Set the loc to the whole command if no loc *) match Loc.get_loc info, loc with | None, Some loc -> Loc.add_loc info loc | Some _, _ | _, None -> info in Exninfo.iraise (reraise, info) (* Load a vernac file. CErrors are annotated with file and location *) let load_vernac_core ~echo ~check ~state ?source file = (* Keep in sync *) let in_chan = open_utf8_file_in file in 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 source = Option.default (Loc.InFile {dirpath=None; file}) source in let in_pa = Procq.Parsable.make ~loc:Loc.(initial source) (Gramlib.Stream.of_channel in_chan) in let open State in (* ids = For beautify, list of parsed sids *) let rec loop state ids = let tstart = System.get_time () in match NewProfile.profile "parse_command" (fun () -> Stm.parse_sentence ~doc:state.doc ~entry:Pvernac.main_entry state.sid in_pa) () with | None -> input_cleanup (); state, ids, Procq.Parsable.comments in_pa | Some ast -> (* Printing of AST for -compile-verbose *) Option.iter (vernac_echo ?loc:ast.CAst.loc) in_echo; checknav ast; let state = try_finally (fun () -> NewProfile.profile "command" ~args:(fun () -> let lnum = match ast.loc with | None -> "unknown" | Some loc -> string_of_int loc.line_nb in [("cmd", `String (Pp.string_of_ppcmds (Topfmt.pr_cmd_header ast))); ("line", `String lnum)]) (fun () -> Flags.silently (interp_vernac ~check ~state) ast) ()) () (fun () -> let tend = System.get_time () in (* The -time option is only supported from console-based clients due to the way it prints. *) emit_time state ast tstart tend) () in (loop [@ocaml.tailcall]) state (state.sid :: ids) in try loop state [] with any -> (* whatever the exception *) let (e, info) = Exninfo.capture any in input_cleanup (); Exninfo.iraise (e, info) let process_expr ~state loc_ast = try interp_vernac ~check:true ~state loc_ast with reraise -> let reraise, info = Exninfo.capture reraise in (* Exceptions don't carry enough state to print themselves (typically missing the nametab) so we need to print before resetting to an older state. See eg #16745 *) let reraise = UserError (CErrors.iprint (reraise, info)) in (* Keep just the loc in the info as it's printed separately *) let info = Option.cata (Loc.add_loc Exninfo.null) Exninfo.null (Loc.get_loc info) in ignore(Stm.edit_at ~doc:state.doc state.sid); Exninfo.iraise (reraise, info) let process_expr ~state loc_ast = let tstart = System.get_time () in try_finally (fun () -> process_expr ~state loc_ast) () (fun () -> let tend = System.get_time () in emit_time state loc_ast tstart tend) () (******************************************************************************) (* Beautify-specific code *) (******************************************************************************) (* vernac parses the given stream, executes interpfun on the syntax tree it * parses, and is verbose on "primitives" commands if verbosely is true *) let beautify_suffix = ".beautified" let set_formatter_translator ch = let out s b e = output_substring ch s b e in let ft = Format.make_formatter out (fun () -> flush ch) in Format.pp_set_max_boxes ft max_int; ft let pr_new_syntax ?loc ft_beautify ocom = let loc = Option.append loc (Option.bind ocom (fun x -> x.CAst.loc)) in let loc = Option.cata Loc.unloc (0,0) loc in let before = comment (Pputils.extract_comments (fst loc)) in let com = Option.cata (fun com -> Ppvernac.pr_vernac com ++ fnl()) (mt ()) ocom in let after = comment (Pputils.extract_comments (snd loc)) in if !Flags.beautify_file then (Pp.pp_with ft_beautify (hov 0 (before ++ com ++ after)); Format.pp_print_flush ft_beautify ()) else Feedback.msg_info (hov 4 (str"New Syntax:" ++ fnl() ++ (hov 0 com))) (* load_vernac with beautify *) let beautify_pass ~doc ~comments ~ids ~filename = let ft_beautify, close_beautify = if !Flags.beautify_file then let chan_beautify = open_out (filename^beautify_suffix) in set_formatter_translator chan_beautify, fun () -> close_out chan_beautify; else !Topfmt.std_ft, fun () -> () in (* The interface to the comment printer is imperative, so we first set the comments, then we call print. This has to be done for each file. *) Pputils.beautify_comments := comments; List.iter (fun id -> pr_new_syntax ft_beautify (Stm.get_ast ~doc id)) ids; (* Is this called so comments at EOF are printed? *) pr_new_syntax ~loc:(Loc.make_loc (max_int,max_int)) ft_beautify None; close_beautify () (* Main driver for file loading. For now, we only do one beautify pass. *) let load_vernac ~echo ~check ~state ?source filename = let ostate, ids, comments = load_vernac_core ~echo ~check ~state ?source filename in (* Pass for beautify *) if !Flags.beautify then beautify_pass ~doc:ostate.State.doc ~comments ~ids:(List.rev ids) ~filename; (* End pass *) ostate rocq-9.2.0/toplevel/vernac.mli000066400000000000000000000027421516144147600163170ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* time_output (** Parsing of vernacular. *) module State : sig type t = { doc : Stm.doc; sid : Stateid.t; proof : Proof.t option; time : time_output option; } end (** [process_expr sid cmd] Executes vernac command [cmd]. Callers are expected to handle and print errors in form of exceptions, however care is taken so the state machine is left in a consistent state. *) val process_expr : state:State.t -> Vernacexpr.vernac_control -> State.t (** [load_vernac echo sid file] Loads [file] on top of [sid], will echo the commands if [echo] is set. Callers are expected to handle and print errors in form of exceptions. *) val load_vernac : echo:bool -> check:bool -> state:State.t -> ?source:Loc.source -> string -> State.t rocq-9.2.0/toplevel/workerLoop.ml000066400000000000000000000030521516144147600170260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (* the state is not used since the worker will receive one from master *) loop ()); } in start_coq custom args rocq-9.2.0/toplevel/workerLoop.mli000066400000000000000000000014571516144147600172060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit) -> loop:(unit -> unit) -> string list -> unit rocq-9.2.0/vernac/000077500000000000000000000000001516144147600137555ustar00rootroot00000000000000rocq-9.2.0/vernac/assumptions.ml000066400000000000000000000425451516144147600167060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* raise Not_found | (l, SFBmodule mb) :: _ when Id.equal l lab -> mb | _ :: fields -> search_mod_label lab fields let rec search_cst_label lab = function | [] -> raise Not_found | (l, SFBconst cb) :: _ when Id.equal l lab -> cb | _ :: fields -> search_cst_label lab fields let rec search_mind_label lab = function | [] -> raise Not_found | (l, SFBmind mind) :: _ when Id.equal l lab -> mind | _ :: fields -> search_mind_label lab fields (* TODO: using [empty_delta_resolver] below is probably slightly incorrect. But: a) I don't see currently what should be used instead b) this shouldn't be critical for Print Assumption. At worse some constants will have a canonical name which is non-canonical, leading to failures in [Global.lookup_constant], but our own [lookup_constant] should work. *) let rec fields_of_functor f subs mp0 args = function | NoFunctor a -> f subs mp0 args a | MoreFunctor (mbid,_,e) -> let open Mod_subst in match args with | [] -> assert false (* we should only encounter applied functors *) | mpa :: args -> let subs = join (map_mbid mbid mpa (empty_delta_resolver mpa) (*TODO*)) subs in fields_of_functor f subs mp0 args e let rec lookup_module_in_impl mp = match mp with | MPfile _ -> Global.lookup_module mp | MPbound _ -> Global.lookup_module mp | MPdot (mp',lab') -> if ModPath.equal mp' (Global.current_modpath ()) then Global.lookup_module mp else let fields = memoize_fields_of_mp mp' in search_mod_label lab' fields and memoize_fields_of_mp mp = try ModPath.Map.find mp !modcache with Not_found -> let l = fields_of_mp mp in modcache := ModPath.Map.add mp l !modcache; l and fields_of_mp mp = let open Mod_subst in let mb = lookup_module_in_impl mp in let fields,inner_mp,subs = fields_of_mb empty_subst mp mb [] in let delta_mb = mod_delta mb in let subs = (* XXX this code makes little sense, adding a delta_mb to subs if the root does not coincide with mp used to be equivalent to a no-op and now fails with an assertion failure. More likely than not, this means that we have no idea about what we are doing. *) if ModPath.equal inner_mp mp then subs else if has_root_delta_resolver mp delta_mb then add_mp inner_mp mp delta_mb subs else add_mp inner_mp mp (empty_delta_resolver mp) subs in Modops.subst_structure subs mp fields and fields_of_mb subs mp mb args = match Mod_declarations.mod_expr mb with | Algebraic expr -> fields_of_expression subs mp args (mod_type mb) expr | Struct (_, sign) -> let sign = Modops.annotate_struct_body sign (mod_type mb) in fields_of_signature subs mp args sign | Abstract|FullStruct -> fields_of_signature subs mp args (mod_type mb) (** The Abstract case above corresponds to [Declare Module] *) and fields_of_signature x = fields_of_functor (fun subs mp0 args struc -> assert (List.is_empty args); (struc, mp0, subs)) x and fields_of_expr subs mp0 args = function | MEident mp -> let mp = Mod_subst.subst_mp subs mp in let mb = lookup_module_in_impl mp in fields_of_mb subs mp mb args | MEapply (me1,mp2) -> fields_of_expr subs mp0 (mp2::args) me1 | MEwith _ -> assert false (* no 'with' in [mod_expr] *) and fields_of_expression subs mp args mty me = let me = Modops.annotate_module_expression me mty in fields_of_functor fields_of_expr subs mp args me let lookup_constant_in_impl cst fallback = try let mp,lab = KerName.repr (Constant.canonical cst) in let fields = memoize_fields_of_mp mp in (* A module found this way is necessarily closed, in particular our constant cannot be in an opened section : *) search_cst_label lab fields with Not_found -> (* Either: - The module part of the constant isn't registered yet : we're still in it, so the [constant_body] found earlier (if any) was a true axiom. - The label has not been found in the structure. This is an error *) match fallback with | Some cb -> cb | None -> CErrors.anomaly Pp.(str "Print Assumption: unknown constant " ++ Constant.print cst ++ str ".") let lookup_constant cst = let env = Global.env() in if not (Environ.mem_constant cst env) then lookup_constant_in_impl cst None else let cb = Environ.lookup_constant cst env in if Declareops.constant_has_body cb then cb else lookup_constant_in_impl cst (Some cb) let lookup_mind_in_impl mind = try let mp,lab = KerName.repr (MutInd.canonical mind) in let fields = memoize_fields_of_mp mp in search_mind_label lab fields with Not_found -> CErrors.anomaly Pp.(str "Print Assumption: unknown inductive " ++ MutInd.print mind ++ str ".") let lookup_mind mind = let env = Global.env() in if Environ.mem_mind mind env then Environ.lookup_mind mind env else lookup_mind_in_impl mind (** Graph traversal of an object, collecting on the way the dependencies of traversed objects *) let fold_with_full_binders g f n acc c = let open Context.Rel.Declaration in let open Constr in match kind c with | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ | Float _ | String _ -> 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 | LetIn (na,b,t,c) -> f (g (LocalDef (na,b,t)) n) (f n (f n acc b) t) c | App (c,l) -> Array.fold_left (f n) (f n acc c) l | Proj (_,_,c) -> f n acc c | Evar _ -> assert false | Case (ci, u, pms, p, iv, c, bl) -> let mib = lookup_mind (fst ci.ci_ind) in let (ci, (p,_), iv, c, bl) = Inductive.expand_case_specif mib (ci, u, pms, p, iv, c, bl) in Array.fold_left (f n) (f n (fold_invert (f n) (f n acc p) iv) c) bl | Fix (_,(lna,tl,bl)) -> let n' = CArray.fold_left2_i (fun i c n t -> g (LocalAssum (n,lift i t)) c) n lna tl in let fd = Array.map2 (fun t b -> (t,b)) tl bl in Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd | CoFix (_,(lna,tl,bl)) -> let n' = CArray.fold_left2_i (fun i c n t -> g (LocalAssum (n,lift i t)) c) n lna tl in let fd = Array.map2 (fun t b -> (t,b)) tl bl in Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd | Array(_u,t,def,ty) -> f n (f n (Array.fold_left (f n) acc t) def) ty let get_constant_body access kn = let cb = lookup_constant kn in match cb.const_body with | Undef _ | Primitive _ | Symbol _ -> None | Def c -> Some c | OpaqueDef o -> match Global.force_proof access o with | c, _ -> Some c | exception e when CErrors.noncritical e -> None (* missing delayed body, e.g. in vok mode *) let rec traverse access (current:GlobRef.t) ctx accu t = let open GlobRef in let open Constr in match Constr.kind t with | Var id -> let body () = id |> Global.lookup_named |> NamedDecl.get_value in traverse_object access accu body (VarRef id) | Const (kn, _) -> let body () = get_constant_body access kn in traverse_object access accu body (ConstRef kn) | Ind ((mind, _) as ind, _) -> traverse_inductive access accu mind (IndRef ind) | Construct (((mind, _), _) as cst, _) -> traverse_inductive access accu mind (ConstructRef cst) | Meta _ | Evar _ -> assert false | Case (_, _, _, (([|_|], oty),_), _, c, [||]) when Vars.noccurn 1 oty -> (* non dependent match on an inductive with no constructors *) begin match Constr.kind c with | Const (kn, _) when not (Declareops.constant_has_body (lookup_constant kn)) -> let (curr, data, ax2ty) = accu in let obj = ConstRef kn in let already_in = GlobRef.Map_env.mem obj data in let data = if not already_in then GlobRef.Map_env.add obj None data else data in let ty = (current, ctx, Vars.subst1 mkProp oty) in let ax2ty = try let l = GlobRef.Map_env.find obj ax2ty in GlobRef.Map_env.add obj (ty::l) ax2ty with Not_found -> GlobRef.Map_env.add obj [ty] ax2ty in (GlobRef.Set_env.add obj curr, data, ax2ty) | _ -> fold_with_full_binders Context.Rel.add (traverse access current) ctx accu t end | _ -> fold_with_full_binders Context.Rel.add (traverse access current) ctx accu t and traverse_object access (curr, data, ax2ty) body obj = let data, ax2ty = let already_in = GlobRef.Map_env.mem obj data in if already_in then data, ax2ty else match body () (* Beware: this can be very costly *) with | None -> (* This is an axiom. Always traverse its type to find dependencies *) let data = GlobRef.Map_env.add obj None data in begin match obj with | GlobRef.ConstRef kn -> let cb = lookup_constant kn in let typ = cb.Declarations.const_type in let _, data, ax2ty = traverse access obj Context.Rel.empty (GlobRef.Set_env.empty, data, ax2ty) typ in data, ax2ty (* VarRef, IndRef and ConstructRef don't need recursive type traversal. For VarRef (section variables), the dependencies are already tracked. For IndRef and ConstructRef, dependencies are handled by traverse_inductive *) | GlobRef.VarRef _ | GlobRef.IndRef _ | GlobRef.ConstructRef _ -> data, ax2ty end | Some body -> let contents,data,ax2ty = traverse access obj Context.Rel.empty (GlobRef.Set_env.empty,data,ax2ty) body in GlobRef.Map_env.add obj (Some contents) data, ax2ty in (GlobRef.Set_env.add obj curr, data, ax2ty) (** Collects the references occurring in the declaration of mutual inductive definitions. All the constructors and names of a mutual inductive definition share exactly the same dependencies. Also, there is no explicit dependency between mutually defined inductives and constructors. *) and traverse_inductive access (curr, data, ax2ty) mind obj = let firstind_ref = (GlobRef.IndRef (mind, 0)) in let data, ax2ty = (* Invariant : I_0 \in data iff I_i \in data iff c_ij \in data where I_0, I_1, ... are in the same mutual definition and c_ij are all their constructors. *) if (* recursive call: *) GlobRef.Set_env.mem firstind_ref curr || (* already in: *) GlobRef.Map_env.mem firstind_ref data then data, ax2ty else (* Take into account potential recursivity of ind in itself *) let curr = GlobRef.Set_env.add firstind_ref GlobRef.Set_env.empty in let accu = (curr, data, ax2ty) in let mib = lookup_mind mind in (* Collects references of parameters *) let param_ctx = mib.mind_params_ctxt in let nparam = List.length param_ctx in let accu = traverse_context access obj Context.Rel.empty accu param_ctx in (* For each inductive, collects references in their arity and in the type of constructors*) let (contents, data, ax2ty) = Array.fold_left (fun accu oib -> let arity_wo_param = List.rev (List.skipn nparam (List.rev oib.mind_arity_ctxt)) in let accu = traverse_context access obj param_ctx accu arity_wo_param in Array.fold_left (fun accu cst_typ -> let param_ctx, cst_typ_wo_param = Term.decompose_prod_n_decls nparam cst_typ in traverse access obj param_ctx accu cst_typ_wo_param) accu oib.mind_user_lc) accu mib.mind_packets in (* Maps all these dependencies to inductives and constructors*) let data = let contents = GlobRef.Set_env.remove firstind_ref contents in Array.fold_left_i (fun n data oib -> let ind = (mind, n) in let data = GlobRef.Map_env.add (GlobRef.IndRef ind) (Some contents) data in Array.fold_left_i (fun k data _ -> GlobRef.Map_env.add (GlobRef.ConstructRef (ind, k+1)) (Some contents) data ) data oib.mind_consnames) data mib.mind_packets in (data, ax2ty) in (GlobRef.Set_env.add obj curr, data, ax2ty) (** Collects references in a rel_context. *) and traverse_context access current ctx accu ctxt = snd (Context.Rel.fold_outside (fun decl (ctx, accu) -> match decl with | Context.Rel.Declaration.LocalDef (_,c,t) -> let accu = traverse access current ctx (traverse access current ctx accu t) c in let ctx = Context.Rel.add decl ctx in ctx, accu | Context.Rel.Declaration.LocalAssum (_,t) -> let accu = traverse access current ctx accu t in let ctx = Context.Rel.add decl ctx in ctx, accu) ctxt ~init:(ctx, accu)) let traverse access grs = let () = modcache := ModPath.Map.empty in let env = Global.env () in List.fold_left (fun accu gr -> let t, _ = UnivGen.fresh_global_instance env gr in traverse access gr Context.Rel.empty accu t ) (GlobRef.Set_env.empty, GlobRef.Map_env.empty, GlobRef.Map_env.empty) grs (** Hopefully bullet-proof function to recover the type of a constant. It just ignores all the universe stuff. There are many issues that can arise when considering terms out of any valid environment, so use with caution. *) let type_of_constant cb = cb.Declarations.const_type let uses_uip mib = Array.exists (fun mip -> Option.is_empty mip.mind_squashed && mip.mind_relevance == Sorts.Irrelevant && Array.length mip.mind_nf_lc = 1 && List.length (fst mip.mind_nf_lc.(0)) = List.length mib.mind_params_ctxt) mib.mind_packets let assumptions ?(add_opaque=false) ?(add_transparent=false) access st grs = let open Printer in (* Only keep the transitive dependencies *) let (_, graph, ax2ty) = traverse access grs in let open GlobRef in let fold obj contents accu = match obj with | VarRef id -> let decl = Global.lookup_named id in if Context.Named.Declaration.is_local_assum decl then let t = Context.Named.Declaration.get_type decl in ContextObjectMap.add (Variable id) t accu else accu | ConstRef kn -> let cb = lookup_constant kn in let accu = if cb.const_typing_flags.check_guarded then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (Guarded obj, l)) Constr.mkProp accu in let accu = if cb.const_typing_flags.check_universes then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (TypeInType obj, l)) Constr.mkProp accu in if not (Option.has_some contents) then let t = type_of_constant cb in let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (Constant kn,l)) t accu else if add_opaque && (Declareops.is_opaque cb || not (Structures.PrimitiveProjections.is_transparent_constant st kn)) then let t = type_of_constant cb in ContextObjectMap.add (Opaque kn) t accu else if add_transparent then let t = type_of_constant cb in ContextObjectMap.add (Transparent kn) t accu else accu | IndRef (m,_) | ConstructRef ((m,_),_) -> let mind = lookup_mind m in let accu = if mind.mind_typing_flags.check_positive then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (Positive m, l)) Constr.mkProp accu in let accu = if mind.mind_typing_flags.check_guarded then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (Guarded obj, l)) Constr.mkProp accu in let accu = if mind.mind_typing_flags.check_universes then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (TypeInType obj, l)) Constr.mkProp accu in let accu = if not (uses_uip mind) then accu else let l = try GlobRef.Map_env.find obj ax2ty with Not_found -> [] in ContextObjectMap.add (Axiom (UIP m, l)) Constr.mkProp accu in accu in GlobRef.Map_env.fold fold graph ContextObjectMap.empty rocq-9.2.0/vernac/assumptions.mli000066400000000000000000000032571516144147600170540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* GlobRef.t list -> (GlobRef.Set_env.t * GlobRef.Set_env.t option GlobRef.Map_env.t * (GlobRef.t * Constr.rel_context * types) list GlobRef.Map_env.t) (** Collects all the assumptions (optionally including opaque definitions) on which terms rely (together with their type). The above warning of {!traverse} also applies. *) val assumptions : ?add_opaque:bool -> ?add_transparent:bool -> Global.indirect_accessor -> TransparentState.t -> GlobRef.t list -> types ContextObjectMap.t rocq-9.2.0/vernac/attributes.ml000066400000000000000000000414211516144147600164770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.(quote (str s)) | FlagQualid p -> Libnames.pr_qualid p let rec pr_vernac_flag_value = let open Pp in function | VernacFlagEmpty -> mt () | VernacFlagLeaf l -> str "=" ++ pr_vernac_flag_leaf l | VernacFlagList s -> surround (prlist_with_sep pr_comma pr_vernac_flag s) and pr_vernac_flag_r (s, arguments) = let open Pp in str s ++ (pr_vernac_flag_value arguments) and pr_vernac_flag {CAst.v} = pr_vernac_flag_r v let warn_unsupported_attributes = CWarnings.create ~name:"unsupported-attributes" ~category:CWarnings.CoreCategories.parsing ~default:CWarnings.AsError (fun atts -> let keys = List.map (fun x -> fst x.CAst.v) atts in let keys = List.sort_uniq String.compare keys in let conj = match keys with [_] -> "this attribute: " | _ -> "these attributes: " in Pp.(str "This command does not support " ++ str conj ++ prlist_with_sep (fun () -> strbrk ", ") str keys ++ str".")) let unsupported_attributes = function | [] -> () | atts -> let loc = List.fold_left (fun loc att -> Loc.merge_opt loc att.CAst.loc) None atts in warn_unsupported_attributes ?loc atts type 'a key_parser = ?loc:Loc.t -> 'a option -> vernac_flag_value -> 'a type 'a attribute = vernac_flags -> vernac_flags * 'a let parse_with_extra (p:'a attribute) (atts:vernac_flags) : vernac_flags * 'a = p atts let parse_drop_extra att atts = snd (parse_with_extra att atts) let parse (p:'a attribute) atts : 'a = let extra, v = parse_with_extra p atts in unsupported_attributes extra; v let make_attribute x = x module Notations = struct type 'a t = 'a attribute let return x = fun atts -> atts, x let (>>=) att f = fun atts -> let atts, v = att atts in f v atts let (>>) p1 p2 = fun atts -> let atts, () = p1 atts in p2 atts let map f att = fun atts -> let atts, v = att atts in atts, f v let (++) (p1:'a attribute) (p2:'b attribute) : ('a*'b) attribute = fun atts -> let atts, v1 = p1 atts in let atts, v2 = p2 atts in atts, (v1, v2) end open Notations let assert_empty ?loc k v = if v <> VernacFlagEmpty then CErrors.user_err ?loc Pp.(str "Attribute " ++ str k ++ str " does not accept arguments") let error_twice ?loc ~name : 'a = CErrors.user_err ?loc Pp.(str "Attribute for " ++ str name ++ str " specified twice.") let assert_once ?loc ~name prev = if Option.has_some prev then error_twice ?loc ~name let attribute_of_list (l:(string * 'a key_parser) list) : 'a option attribute = let rec p extra v = function | [] -> List.rev extra, v | ({CAst.v=key, attv; loc} as att) :: rem -> (match CList.assoc_f String.equal key l with | exception Not_found -> p (att::extra) v rem | parser -> let v = Some (parser ?loc v attv) in p extra v rem) in p [] None let single_key_parser ~name ~key v ?loc prev args = assert_empty ?loc key args; assert_once ?loc ~name prev; v let pr_possible_values ~values = Pp.(str "{" ++ prlist_with_sep pr_comma str (List.map fst values) ++ str "}") (** [key_value_attribute ~key ~default ~values] parses a attribute [key=value] with possible [key] [value] in [values], [empty] is for compatibility for users doing [qualif(key)] which is parsed as [qualif(key=empty)] *) let key_value_attribute ~key ?empty ~(values : (string * 'a) list) : 'a option attribute = let parser ?loc = function | Some v -> CErrors.user_err ?loc Pp.(str "key '" ++ str key ++ str "' has been already set.") | None -> begin function | VernacFlagLeaf (FlagQualid q) when Libnames.qualid_is_ident q -> let b = Names.Id.to_string @@ Libnames.qualid_basename q in begin match CList.assoc_f String.equal b values with | exception Not_found -> CErrors.user_err ?loc Pp.(str "Invalid value '" ++ str b ++ str "' for key " ++ str key ++ fnl () ++ str "use one of " ++ pr_possible_values ~values) | value -> value end | VernacFlagEmpty when Option.has_some empty -> Option.get empty | err -> CErrors.user_err ?loc Pp.(str "Invalid syntax " ++ pr_vernac_flag_r (key, err) ++ str ", try " ++ str key ++ str "=" ++ pr_possible_values ~values ++ str " instead.") end in attribute_of_list [key, parser] let bool_attribute ~name : bool option attribute = let values = ["yes", true; "no", false] in key_value_attribute ~key:name ~empty:true ~values (* Variant of the [bool] attribute with only two values (bool has three). *) let qualid_is_this_ident fp id = Libnames.qualid_is_ident fp && Names.Id.to_string @@ Libnames.qualid_basename fp = id let get_bool_value ?loc ~key ~default = function | VernacFlagEmpty -> default | VernacFlagLeaf (FlagQualid q) when qualid_is_this_ident q "yes" -> true | VernacFlagLeaf (FlagQualid q) when qualid_is_this_ident q "no" -> false | _ -> CErrors.user_err ?loc Pp.(str "Attribute " ++ str key ++ str " only accepts boolean values.") let enable_attribute ~key ~default : bool attribute = fun atts -> let this, extra = List.partition (fun {CAst.v=k, _} -> String.equal key k) atts in extra, match this with | [] -> default () | [ {CAst.v=_, value; loc} ] -> get_bool_value ?loc ~key ~default:true value | _ :: {CAst.loc} :: _ -> (* We report the location of the 2nd item *) error_twice ?loc ~name:key let qualify_attribute qual (parser:'a attribute) : 'a attribute = fun atts -> let rec extract extra qualified = function | [] -> List.rev extra, List.flatten (List.rev qualified) | {CAst.v=key,attv; loc} :: rem when String.equal key qual -> (match attv with | VernacFlagEmpty | VernacFlagLeaf _ -> CErrors.user_err ?loc Pp.(str "Malformed attribute " ++ str qual ++ str ": attribute list expected.") | VernacFlagList atts -> extract extra (atts::qualified) rem) | att :: rem -> extract (att::extra) qualified rem in let extra, qualified = extract [] [] atts in let rem, v = parser qualified in let rem = List.rev_map (fun rem -> CAst.make ?loc:rem.CAst.loc (qual, VernacFlagList [rem])) rem in let extra = List.rev_append rem extra in extra, v (** [program_mode] tells that Program mode has been activated, either globally via [Set Program] or locally via the Program command prefix. *) let program_mode_option_name = ["Program";"Mode"] let program_mode = ref false let () = let open Goptions in declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = program_mode_option_name; optread = (fun () -> !program_mode); optwrite = (fun b -> program_mode:=b) } let program = enable_attribute ~key:"program" ~default:(fun () -> !program_mode) (* This is a bit complex as the grammar in g_vernac.mlg doesn't distingish between the boolean and ternary case.*) let option_locality_parser = let name = "Locality" in attribute_of_list [ ("local", single_key_parser ~name ~key:"local" Goptions.OptLocal); ("global", single_key_parser ~name ~key:"global" Goptions.OptGlobal); ("export", single_key_parser ~name ~key:"export" Goptions.OptExport); ] let option_locality = option_locality_parser >>= function | None -> return Goptions.OptDefault | Some l -> return l let explicit_hint_locality = let open Hints in let name = "Locality" in attribute_of_list [ ("local", single_key_parser ~name ~key:"local" Local); ("global", single_key_parser ~name ~key:"global" SuperGlobal); ("export", single_key_parser ~name ~key:"export" Export); ] let default_hint_locality () = if Lib.sections_are_opened () then Hints.Local else Hints.Export let hint_locality = explicit_hint_locality >>= function | Some v -> return v | None -> return (default_hint_locality()) let hint_locality_no_sections = explicit_hint_locality >>= function | Some v -> let () = if v <> Local && Lib.sections_are_opened() then CErrors.user_err Pp.(str "This command does not support this locality in sections.") in return v | None -> return (default_hint_locality()) let hint_locality_default_superglobal = explicit_hint_locality >>= function | Some v -> return v | None -> return Hints.SuperGlobal (* locality is supposed to be true when local, false when global *) let locality = let name = "Locality" in attribute_of_list [ ("local", single_key_parser ~name ~key:"local" true); ("global", single_key_parser ~name ~key:"global" false); ] let ukey = "universes" let universe_polymorphism_option_name = ["Universe"; "Polymorphism"] let is_universe_polymorphism = let b = ref false in let () = let open Goptions in declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = universe_polymorphism_option_name; optread = (fun () -> !b); optwrite = ((:=) b) } in fun () -> !b let polymorphic = qualify_attribute ukey (bool_attribute ~name:"polymorphic") >>= function | Some b -> return b | None -> return (is_universe_polymorphism()) let { Goptions.get = is_polymorphic_inductive_cumulativity } = Goptions.declare_bool_option_and_ref ~key:["Polymorphic"; "Inductive"; "Cumulativity"] ~value:false () let cumulative kind = match kind with | PolyFlags.Inductive -> qualify_attribute ukey (bool_attribute ~name:"cumulative") | PolyFlags.Assumption | PolyFlags.Definition -> (* Not yet supported *) return None let poly kind = (polymorphic ++ cumulative kind) >>= fun (univ_poly, cumulative) -> let cumulative = match cumulative with | None -> if univ_poly then is_polymorphic_inductive_cumulativity() else false | Some b -> if b && not univ_poly then CErrors.user_err Pp.(str "Cannot set polymorphic inductive cumulativity status when not in universe polymorphism mode.") else b in return (PolyFlags.make ~univ_poly ~cumulative ~collapse_sort_variables:true) let poly_def = poly PolyFlags.Definition let template = qualify_attribute ukey (bool_attribute ~name:"template") let unfold_fix = enable_attribute ~key:"unfold_fix" ~default:(fun () -> false) let only_locality atts = parse locality atts let only_polymorphism atts = parse polymorphic atts let vernac_polymorphic_flag loc = CAst.make ?loc (ukey, VernacFlagList [CAst.make ?loc ("polymorphic", VernacFlagEmpty)]) let vernac_monomorphic_flag loc = CAst.make ?loc (ukey, VernacFlagList [CAst.make ?loc ("polymorphic", VernacFlagLeaf (FlagQualid (Libnames.qualid_of_string "no")))]) let reversible = bool_attribute ~name:"reversible" let canonical_field = enable_attribute ~key:"canonical" ~default:(fun () -> true) let canonical_instance = enable_attribute ~key:"canonical" ~default:(fun () -> false) let payload_parser ?cat ~name : string key_parser = fun ?loc orig args -> match args with | VernacFlagLeaf (FlagString str) -> begin match orig, cat with | None, _ -> str | Some orig, Some cat -> cat orig str | Some _, None -> error_twice ?loc ~name end | _ -> CErrors.user_err ?loc Pp.(str "Ill formed \"" ++ str name ++ str"\" attribute (string expected)") let qualid_parser ~name : Libnames.qualid key_parser = fun ?loc orig args -> match args with | VernacFlagLeaf (FlagQualid str) -> begin match orig with | None -> str | Some _ -> error_twice ?loc ~name end | _ -> CErrors.user_err ?loc Pp.(str "Ill formed \"" ++ str name ++ str"\" attribute (qualid expected)") let payload_attribute ?cat ~name = attribute_of_list [name, payload_parser ?cat ~name] let using = payload_attribute ?cat:None ~name:"using" let deprecation_parser parse_use : _ key_parser = fun ?loc orig args -> assert_once ?loc ~name:"deprecation" orig; match args with | VernacFlagList l -> let subatt name = payload_attribute ~name in let use_att = attribute_of_list ["use", qualid_parser ~name:"use"] in let (note, since), use = parse (subatt "note" ++ subatt "since" ++ use_att) l in let depr = Deprecation.make ?since ?note () in parse_use depr use | _ -> CErrors.user_err ?loc Pp.(str "Ill formed β€œdeprecated” attribute:" ++ spc() ++ str "expected β€œdeprecated(since = \"since\", note = \"note\")β€œ.") let no_use_allowed depr = function | None -> depr | Some _ -> CErrors.user_err Pp.(str "Attribute use not allowed") let extended_globref_allowed depr = function | None -> Deprecation.make_with_qf depr () | Some p -> let use_instead = try Nametab.locate_extended p with Not_found -> CErrors.user_err ?loc:p.CAst.loc Pp.(Libnames.pr_qualid p ++ str " not found.") in Deprecation.make_with_qf depr ~use_instead () let deprecation_gen parse_use = attribute_of_list ["deprecated",deprecation_parser parse_use] let deprecation = deprecation_gen no_use_allowed let deprecation_with_use_globref_instead = deprecation_gen extended_globref_allowed let user_warn_parser : UserWarn.warn list key_parser = fun ?loc orig args -> let orig = Option.default [] orig in match args with | VernacFlagList l -> let subatt name = payload_attribute ~name in let note, cats = parse (subatt "note" ++ subatt "cats") l in let note = match note with | Some x -> x | None -> CErrors.user_err Pp.(str "Ill formed β€œwarn” attribute (\"note\" is required).") in UserWarn.make_warn ~note ?cats () :: orig | _ -> CErrors.user_err ?loc (Pp.str "Ill formed β€œwarn” attribute (expected \"note\" and optionally \"cats\" sub-attributes).") let user_warn_warn = attribute_of_list ["warn",user_warn_parser] >>= function | None -> return [] | Some l -> return (List.rev l) let user_warns = (deprecation ++ user_warn_warn) >>= function | None, [] -> return None | depr, warn -> return (Some UserWarn.{ depr; warn }) let user_warns_with_use_globref_instead = (deprecation_with_use_globref_instead ++ user_warn_warn) >>= function | None, [] -> return None | depr_qf, warn_qf -> return (Some UserWarn.{ depr_qf; warn_qf }) let process_typing_att ?loc ~typing_flags att disable = let enable = not disable in match att with | "universes" -> { typing_flags with Declarations.check_universes = enable } | "guard" -> { typing_flags with Declarations.check_guarded = enable } | "positivity" -> { typing_flags with Declarations.check_positive = enable } | att -> CErrors.user_err ?loc Pp.(str "Unknown β€œtyping” attribute: " ++ str att) let process_typing_disable ?loc ~key = function | VernacFlagEmpty -> true | VernacFlagLeaf (FlagQualid q) when qualid_is_this_ident q "yes" -> true | VernacFlagLeaf (FlagQualid q) when qualid_is_this_ident q "no" -> false | _ -> CErrors.user_err ?loc Pp.(str "Ill-formed attribute value, must be " ++ str key ++ str "={yes, no}") let typing_flags_parser : Declarations.typing_flags key_parser = fun ?loc orig args -> let rec flag_parser typing_flags = function | [] -> typing_flags | {CAst.v=typing_att, disable; loc} :: rest -> let disable = process_typing_disable ?loc ~key:typing_att disable in let typing_flags = process_typing_att ?loc ~typing_flags typing_att disable in flag_parser typing_flags rest in match args with | VernacFlagList atts -> let typing_flags = Global.typing_flags () in flag_parser typing_flags atts | att -> CErrors.user_err ?loc Pp.(str "Ill-formed β€œtyping” attribute: " ++ pr_vernac_flag_value att) let typing_flags = attribute_of_list ["bypass_check", typing_flags_parser] let bind_scope_where = let name = "where to bind scope" in attribute_of_list [ ("add_top", single_key_parser ~name ~key:"add_top" Notation.AddScopeTop); ("add_bottom", single_key_parser ~name ~key:"add_bottom" Notation.AddScopeBottom); ] let raw_attributes : _ attribute = fun flags -> [], flags rocq-9.2.0/vernac/attributes.mli000066400000000000000000000165621516144147600166600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.t type +'a attribute (** The type of attributes. When parsing attributes if an ['a attribute] is present then an ['a] value will be produced. In the most general case, an attribute transforms the raw flags along with its value. *) val parse : 'a attribute -> vernac_flags -> 'a (** Errors on unsupported attributes. *) val unsupported_attributes : vernac_flags -> unit (** Errors if the list of flags is nonempty. *) module Notations : sig (** Notations to combine attributes. *) include Monad.Def with type 'a t = 'a attribute (** Attributes form a monad. [a1 >>= f] means [f] will be run on the flags transformed by [a1] and using the value produced by [a1]. The trivial attribute [return x] does no action on the flags. *) val (++) : 'a attribute -> 'b attribute -> ('a * 'b) attribute (** Combine 2 attributes. If any keys are in common an error will be raised. *) end (** Definitions for some standard attributes. *) val raw_attributes : vernac_flags attribute val polymorphic : bool attribute val poly : PolyFlags.construction_kind -> PolyFlags.t attribute (** Attributes supported by monomorphic or polymorphic constructions depending on their kind *) val poly_def : PolyFlags.t attribute (** Attributes supported by monomorphic or polymorphic definitions *) val program : bool attribute val template : bool option attribute val unfold_fix : bool attribute val locality : bool option attribute val option_locality : Goptions.option_locality attribute val reversible : bool option attribute val canonical_field : bool attribute val canonical_instance : bool attribute val using : string option attribute val explicit_hint_locality : Hints.hint_locality option attribute val bind_scope_where : Notation.add_scope_where option attribute (** "deprecated" *) val deprecation : Deprecation.t option attribute val deprecation_with_use_globref_instead : Globnames.extended_global_reference Deprecation.with_qf option attribute (** Just the "warn" attribute *) val user_warn_warn : UserWarn.warn list attribute (** "warn" and "deprecated" *) val user_warns : UserWarn.t option attribute val user_warns_with_use_globref_instead : Globnames.extended_global_reference UserWarn.with_qf option attribute (** Default: if sections are opened then Local otherwise Export. Although this is named and uses the type [hint_locality] it may be used as the standard 3-valued locality attribute. *) val hint_locality : Hints.hint_locality attribute (** Like [hint_locality], but errors on explicit non-Local in sections. *) val hint_locality_no_sections : Hints.hint_locality attribute (** Like [hint_locality] but the default in and out of sections is [SuperGlobal]. *) val hint_locality_default_superglobal : Hints.hint_locality attribute (** Enable/Disable universe checking *) val typing_flags : Declarations.typing_flags option attribute val program_mode_option_name : string list (** For internal use when messing with the global option. *) val only_locality : vernac_flags -> bool option (** Parse attributes allowing only locality. *) val only_polymorphism : vernac_flags -> bool (** Parse attributes allowing only polymorphism. Uses the global flag for the default value. *) val parse_drop_extra : 'a attribute -> vernac_flags -> 'a (** Ignores unsupported attributes. *) val parse_with_extra : 'a attribute -> vernac_flags -> vernac_flags * 'a (** Returns unsupported attributes. *) (** * Defining attributes. *) (** [key_value_attribute ~key ~empty ~values] parses a attribute [key=value] with possible [key,value] in [values], if [empty=Some v] it is for compatibility for users doing [qualif(key)] which is parsed as [qualif(key=v)] *) val key_value_attribute : key:string -> ?empty:'a -> values:(string * 'a) list -> 'a option attribute type 'a key_parser = ?loc:Loc.t -> 'a option -> vernac_flag_value -> 'a (** A parser for some key in an attribute. It is given a nonempty ['a option] when the attribute is multiply set for some command. eg in [#[polymorphic] Monomorphic Definition foo := ...], when parsing [Monomorphic] it will be given [Some true]. *) val attribute_of_list : (string * 'a key_parser) list -> 'a option attribute (** Make an attribute from a list of key parsers together with their associated key. *) val payload_parser : ?cat:(string -> string -> string) -> name:string -> string key_parser (** [payload_parser ?cat ~name] parses attributes like [#[name="payload"]]. If the attribute is used multiple times and [cat] is non-None, the payloads are concatenated using it. If [cat] is None, having multiple occurences of the attribute is forbidden. *) val payload_attribute : ?cat:(string -> string -> string) -> name:string -> string option attribute (** This is just [attribute_of_list] for a single [payload_parser]. *) (** Define boolean attribute [name], of the form [name={yes,no}]. The attribute may only be set once for a command. *) val bool_attribute : name:string -> bool option attribute val qualify_attribute : string -> 'a attribute -> 'a attribute (** [qualified_attribute qual att] treats [#[qual(atts)]] like [att] treats [atts]. *) (** Combinators to help define your own parsers. See the implementation of [bool_attribute] for practical use. *) val assert_empty : ?loc:Loc.t -> string -> vernac_flag_value -> unit (** [assert_empty key v] errors if [v] is not empty. [key] is used in the error message as the name of the attribute. *) val assert_once : ?loc:Loc.t -> name:string -> 'a option -> unit (** [assert_once ~name v] errors if [v] is not empty. [name] is used in the error message as the name of the attribute. Used to ensure that a given attribute is not reapeated. *) val single_key_parser : name:string -> key:string -> 'a -> 'a key_parser (** [single_key_parser ~name ~key v] makes a parser for attribute [name] giving the constant value [v] for key [key] taking no arguments. [name] may only be given once. *) val make_attribute : (vernac_flags -> vernac_flags * 'a) -> 'a attribute (** Make an attribute using the internal representation, thus with access to the full power of attributes. Unstable. *) (** Compatibility values for parsing [Polymorphic]. *) val vernac_polymorphic_flag : Loc.t option -> vernac_flag val vernac_monomorphic_flag : Loc.t option -> vernac_flag (** For internal use. *) val universe_polymorphism_option_name : string list val is_universe_polymorphism : unit -> bool rocq-9.2.0/vernac/auto_ind_decl.ml000066400000000000000000002075201516144147600171060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* RelDecl.LocalAssum (Context.map_annot (named_hd env t) na, t) | RelDecl.LocalDef (na,c,t) -> RelDecl.LocalDef (Context.map_annot (named_hd env c) na, c, t) let name_context env ctxt = snd (List.fold_left (fun (env,hyps) d -> let d' = name_assumption env d in (Environ.push_rel d' env, d' :: hyps)) (env,[]) (List.rev ctxt)) (* Some pre declaration of constant we are going to use *) let andb_prop = fun _ -> UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.andb_prop") let andb_true_intro = fun _ -> UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.andb_true_intro") (* We avoid to use lazy as the binding of constants can change *) let bb () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.type") let tt () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.true") let ff () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.false") let eq () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.eq.type") let int63_eqb () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "num.int63.eqb") let float64_eqb () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "num.float.leibniz.eqb") let sumbool () = UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.sumbool.type") let andb = fun _ -> UnivGen.constr_of_monomorphic_global (Global.env ()) (Rocqlib.lib_ref "core.bool.andb") let induct_on c = Induction.induction false None c None None let destruct_on c = Induction.destruct false None c None None let destruct_on_using c id = let open Tactypes in Induction.destruct false None c (Some (CAst.make @@ IntroOrPattern [[CAst.make @@ IntroNaming IntroAnonymous]; [CAst.make @@ IntroNaming (IntroIdentifier id)]])) None let destruct_on_as c l = Induction.destruct false None c (Some (CAst.make l)) None let inj_flags = Some { Equality.keep_proof_equalities = true; (* necessary *) Equality.injection_pattern_l2r_order = true; (* does not matter here *) } let my_discr_tac = Equality.discr_tac false None let my_inj_tac x = Equality.inj inj_flags None false None (EConstr.mkVar x,NoBindings) (* reconstruct the inductive with the correct de Bruijn indexes *) let mkFullInd env (ind,u) n = let mib = Environ.lookup_mind (fst ind) env in mkApp (mkIndU (ind,u), Context.Rel.instance mkRel n mib.mind_params_ctxt) let mkPartialInd env (ind,u) n = let mib = Environ.lookup_mind (fst ind) env in let _, recparams_ctx = Inductive.inductive_nonrec_rec_paramdecls (mib,u) in mkApp (mkIndU (ind,u), Context.Rel.instance mkRel n recparams_ctx) let name_X = Context.make_annot (Name (Id.of_string "X")) Sorts.Relevant let name_Y = Context.make_annot (Name (Id.of_string "Y")) Sorts.Relevant let mk_eqb_over u = mkProd (name_X, u, (mkProd (name_Y, lift 1 u, bb ()))) let check_bool_is_defined () = if not (Rocqlib.has_ref "core.bool.type") then raise (UndefinedCst "bool") let check_no_indices mib = if Array.exists (fun mip -> mip.mind_nrealargs <> 0) mib.mind_packets then raise DecidabilityIndicesNotSupported let is_irrelevant env c = match kind (EConstr.Unsafe.to_constr (Retyping.get_type_of env (Evd.from_env env) (EConstr.of_constr c))) with | Sort SProp -> true | _ -> false let get_scheme handle k ind = match Ind_tables.local_lookup_scheme handle k ind with | None -> assert false | Some c -> c let beq_scheme_kind_aux = ref (fun _ -> failwith "Undefined") let get_inductive_deps ~noprop env kn = (* fetching the mutual inductive body *) let mib = Environ.lookup_mind kn env in (* number of params in the type *) check_no_indices mib; let env = Environ.push_rel_context mib.mind_params_ctxt env in let sigma = Evd.from_env env in let get_deps_one accu i mip = (* This function is only trying to recursively compute the inductive types appearing as arguments of the constructors. This is done to support equality decision over hereditarily first-order types. It could be performed in a much cleaner way, e.g. using the kernel normal form of constructor types and kernel whd_all for the argument types. *) let rec aux env accu c = let (c,a) = Reductionops.whd_all_stack env sigma c in match EConstr.kind sigma c with | Cast (x,_,_) -> aux env accu (EConstr.applist (x,a)) | App _ -> assert false | Ind ((kn', _ as ind), _) -> if Environ.QMutInd.equal env kn kn' then (* Example: Inductive T A := C : T (option A) -> T A. *) List.fold_left (aux env) accu a else let _,mip = Inductive.lookup_mind_specif env ind in (* Types in SProp have trivial equality and are skipped XXX should be substituting polymorphic universes *) if Sorts.is_sprop mip.mind_sort then List.fold_left (aux env) accu a else List.fold_left (aux env) (kn' :: accu) a | Const (kn, u) -> (match Environ.constant_opt_value_in env (kn, EConstr.EInstance.kind sigma u) with | Some c -> aux env accu (EConstr.applist (EConstr.of_constr c,a)) | None -> accu) | Rel _ | Var _ | Sort _ | Prod _ | Lambda _ | LetIn _ | Proj _ | Construct _ | Case _ | CoFix _ | Fix _ | Meta _ | Evar _ | Int _ | Float _ | String _ | Array _ -> Termops.fold_constr_with_full_binders env sigma EConstr.push_rel aux env (List.fold_left (aux env) accu a) c in let fold i accu (constr_ctx,_) = let constr_ctx, _ = List.chop mip.mind_consnrealdecls.(i) constr_ctx in let rec fold env accu = function | [] -> env, accu | decl::ctx -> let env, accu = fold env accu ctx in let t = Context.Rel.Declaration.get_type decl in Environ.push_rel decl env, (if noprop && is_irrelevant env t then accu else aux env accu (EConstr.of_constr t)) in snd (fold env accu constr_ctx) in Array.fold_left_i fold accu mip.mind_nf_lc in Array.fold_left_i (fun i accu mip -> get_deps_one accu i mip) [] mib.mind_packets (** A compact data structure to remember for each declaration of the context if it is a type and comes with a Boolean equality; if it comes with an equality we remember the integer to subtract to the de Bruijn indices of the binder to get the equality *) type eq_status = | End (* int is the number of consecutive declarations without an equality *) | WithoutEq of int * eq_status (* list is the list of shifts for consecutive declarations with an equality *) | WithEq of int list * eq_status let add_eq_status_no = function | WithEq _ | End as s -> WithoutEq (1, s) | WithoutEq (n, s) -> WithoutEq (n+1, s) let set_eq_status_yes n q s = let rec aux n = function | WithoutEq (p,End) when Int.equal n p -> WithoutEq (p-1, WithEq ([q],End)) | WithoutEq (p,WithEq (l,s)) when Int.equal n p -> WithoutEq (p-1, WithEq (q::l,s)) | WithoutEq (p,s) when n < p -> WithoutEq (n-1, WithEq ([q], WithoutEq (p-n, s))) | WithoutEq (p,s) when Int.equal n 1 -> WithEq ([q], WithoutEq (p-1, s)) | WithoutEq (p,s) -> WithoutEq (p, aux (n-p) s) | WithEq (l,s) -> WithEq (l,aux (n-List.length l) s) | End -> assert false in aux n s let rec has_decl_equality n status = match n, status with | p, WithEq (l,s) when p <= List.length l -> Some (List.nth l (p-1)) | p, WithEq (l,s) -> has_decl_equality (p-List.length l) s | p, WithoutEq (n,s) when p <= n -> None | p, WithoutEq (n,s) -> has_decl_equality (p-n) s | _, End -> assert false (** The reallocation of variables to be done during the translation: [env] is the current env at the corresponding step of the translation [lift] is the lift for the original variables [eq_status] tells how to get the equality associated with a variable if any [ind_pos] tells the position of recursive calls (it could have been avoided by replacing the recursive occurrences of ind in an inductive definition by variables *) type env_lift = { env : Environ.env; (* Gamma *) lift : Esubst.lift; (* lift : Gamma + Gamma_eq |- Gamma *) eq_status : eq_status; ind_pos : ((MutInd.t * int * rel_context * int) * int) option; } let lift_ind_pos n = Option.map (fun (ind,k) -> (ind,k+n)) let empty_env_lift env = { env = env; lift = Esubst.el_id; eq_status = End; ind_pos = None; } let push_env_lift decl env_lift = { env = Environ.push_rel decl env_lift.env; lift = Esubst.el_lift env_lift.lift; eq_status = add_eq_status_no env_lift.eq_status; ind_pos = lift_ind_pos 1 env_lift.ind_pos; } let set_replicate n q env_lift = { env = env_lift.env; lift = env_lift.lift; eq_status = set_eq_status_yes n q env_lift.eq_status; ind_pos = env_lift.ind_pos; } let shiftn_env_lift n env_lift = { env_lift with lift = Esubst.el_shft n (Esubst.el_liftn n env_lift.lift); ind_pos = lift_ind_pos n env_lift.ind_pos; } let find_ind_env_lift env_lift (mind,i) = match env_lift.ind_pos with | Some ((mind',nrecparams,recparamsctx,nb_ind),n) when Environ.QMutInd.equal env_lift.env mind mind' -> Some (nrecparams,recparamsctx,n+nb_ind-i) | _ -> None let shift_fix_env_lift ind nrecparams recparamsctx nb_ind env_lift = { env = env_lift.env; lift = Esubst.el_shft nb_ind env_lift.lift; eq_status = env_lift.eq_status; ind_pos = Some ((ind,nrecparams,recparamsctx,nb_ind),0) } let push_rec_env_lift recdef env_lift = let n = Array.length (pi1 recdef) in { env = Environ.push_rec_types recdef env_lift.env; lift = Esubst.el_liftn n env_lift.lift; eq_status = add_eq_status_no env_lift.eq_status; ind_pos = lift_ind_pos n env_lift.ind_pos; } let dest_lam_assum_expand env c = let ctx, c = Reduction.whd_decompose_lambda_decls env c in if List.is_empty ctx then ctx, c else let t = EConstr.Unsafe.to_constr (Retyping.get_type_of (Environ.push_rel_context ctx env) (Evd.from_env env) (EConstr.of_constr c)) in let ctx', _ = Reduction.whd_decompose_prod_decls env t in ctx'@ctx, mkApp (lift (Context.Rel.length ctx') c, Context.Rel.instance mkRel 0 ctx') let pred_context env ci params u nas = let mib, mip = Inductive.lookup_mind_specif env ci.ci_ind in let paramdecl = Vars.subst_instance_context u mib.mind_params_ctxt in let paramsubst = Vars.subst_of_rel_context_instance paramdecl params in let realdecls, _ = List.chop mip.mind_nrealdecls mip.mind_arity_ctxt in let self = let args = Context.Rel.instance mkRel 0 mip.mind_arity_ctxt in let inst = UVars.Instance.(abstract_instance (length u)) in mkApp (mkIndU (ci.ci_ind, inst), args) in let na = Context.make_annot Anonymous mip.mind_relevance in let realdecls = RelDecl.LocalAssum (na, self) :: realdecls in Inductive.instantiate_context u paramsubst nas realdecls let branch_context env ci params u nas i = let mib, mip = Inductive.lookup_mind_specif env ci.ci_ind in let paramdecl = Vars.subst_instance_context u mib.mind_params_ctxt in let paramsubst = Vars.subst_of_rel_context_instance paramdecl params in let ctx, _ = List.chop mip.mind_consnrealdecls.(i) (fst mip.mind_nf_lc.(i)) in Inductive.instantiate_context u paramsubst nas ctx let build_beq_scheme_deps env kn = let inds = get_inductive_deps ~noprop:true env kn in List.map (fun ind -> Ind_tables.SchemeMutualDep (ind, !beq_scheme_kind_aux ())) inds let build_beq_scheme env handle kn = check_bool_is_defined (); (* predef coq's boolean type *) (* here I leave the Naming thingy so that the type of the function is more readable for the user *) let eqName = Context.map_annot (function | Name s -> Name (Id.of_string ("eq_"^(Id.to_string s))) | Anonymous -> Name (Id.of_string "eq_A")) in (* The Boolean equality translation is a parametricity translation where each type T is interpreted as the pair of: - a (possibly degenerate) predicate T_R in Type over T (i.e. T_R : T->Type) - when T is decidable, a Boolean equality T_E over (i.e. T_E : option (T->T->bool) where None means not decidable, that is, at worst, unknown to be decidable) This generalizes into an interpretation of each term M:T as: - an inhabitant [|M|] of T_R M by setting for sort s: - s_R := \T:s.{R:T->s ; E:option (T->T->bool)} and - s_E := None so that types T:s are indeed interpreted as a pair, namely by: - [|T|] := {R:=T_R; E:=T_E} : s_R T and, in particular: - [|Type(n)|] := {R:=Type(n)_R; E:=Type(n)_E) : Type(n+1)_R Type(n) In practice, to have simpler schemes, we won't support here the full hierarchy of sorts. That is, we assume that type parameters of a type will be instantiated only by small types (i.e. not containing sorts). This makes sense since equality on large types is anyway not decidable in the general case [*]. Now, it happens that several parts of the translation are degenerate. For instance, if T is a small type (not containing sorts), then T_R M, which expresses that M realizes T, is a singleton for all M (we assume functional extensionality to treat the case of dependent product types). Therefore, M_T does not need to be defined in this case. Conversely, if T is not small, it is not decidable and T_E will be None. This means that at least T_R is degenerate or T_E is None and this also means that for M:T with degenerate T_R, we don't need to compute [|M|].R This further means that when translating a variable x:T with T small, it can just be translated to x:T without requiring the trivial information that T_R x is inhabited. Similarly for types T of the form [forall X, (forall Y ...) ... Y args] based on the assumption [*] that Y is instantiated only by small functorial types for which (Y args)_R would be degenerate. Similarly, based on the restriction above [*] that parameters are instantiated by small types, when translating a variable x:T with T an arity, i.e. of the form [... -> Type] (or at worst [... -> Type*Type] etc.), we can assume x to be instantiated by a small functorial type whose R translation is degenerate. It remains the declarations of the form X:T for T of the form [forall X, ... X args] where X is in negative position of a dependent product. If such X is instantiated by a large type in the definition, as in [Inductive I (F:forall X:Type, X->X) (B:F Type nat) := C : B -> I F B], we give up. Otherwise said, we support only the case when `X`is instantiated by a small type. Eventually, we thus need two translations: - T_R when T is large and it does not need to go under applicative subterms since subterms [X args] are considered small by assumption [*] - T_E when T is small which needs to go under subterms and which thus needs to be generalized into a translation M_E : T_R.E whenever T is detected as decidable (in which case, T_R.E is typically of the form T->T->bool or of the form (T.1->T.1->bool)*(T.2->T.2->bool), etc.) Below, the first translation is called [translate_type_eq] and the second [translate_term_eq]. Additionally, there is a copy-cat translation called "translate_term" that lifts M in the typing context of M_R. The function [translate_type_eq] takes as input a type T and a term M of type T and it returns T_R M. For M of type T, the function [translate_term_eq M] returns an object of type term T_R M, that is, when M is itself some type U, an object of type U->U->bool. Note that we don't use an option type for non-decidable types but instead raises an exception whenever a type is not detected as decidable. Future work might support: - exotic types such as [Inductive I (F:forall X:Type, X->X) (B:F Type nat) := C : B -> I F B] - types with invertible indices like listn - dependent products over finite types (e.g. over bool->bool), and more generally compact types whose equality is decidable (see Escardo-Oliva) *) let rec translate_type_eq env_lift na c t = let ctx, t = Reduction.whd_decompose_prod_decls env t in let env_lift', ctx_eq = translate_context_eq env_lift ctx in let inst = Array.map (translate_term env_lift') (Context.Rel.instance mkRel 0 ctx) in let env_lift'' = shiftn_env_lift (Context.Rel.length ctx_eq) env_lift in let c = mkApp (translate_term env_lift'' c, inst) in let c = match kind t with | Sort _ -> Some (mk_eqb_over c) | Prod _ | LetIn _ -> assert false (* [s] is necessaritly a sort *) | Cast (t,k,s) -> begin match translate_type_eq env_lift' na c t with | None -> None | Some t -> Some (mkCast (t, k, mkProd (na, t, c))) end (* TODO: take into account situations like (P:Type * Type) which could be translated into (fst P->fst P>bool)*(snd P->snd P->bool); to be done in parallel with preserving the types in Proj/Construct/CoFix *) | Ind _ -> None | Array _ -> None (* We assume references to be references to small types and thus to types with singleton realizability predicate; to support references to large types, see comments above for the full translation *) | App _ | Rel _ | Var _ | Const _ -> None (* The restricted translation translates only types *) | Lambda _ | Construct _ -> assert false | Case (ci, u, pms, ((pnames,p),r), iv, tm, lbr) -> let env_lift_pred = shiftn_env_lift (Array.length pnames) env_lift in let t = mkCase (ci, u, Array.map (translate_term env_lift_pred) pms, (translate_term_with_binders env_lift_pred (pnames,p), r), Constr.map_invert (translate_term env_lift_pred) iv, mkRel 1, Array.map (translate_term_with_binders env_lift_pred) lbr) in (* in the restricted translation, only types are translated and the return predicate is necessarily a type *) let p = mkProd (Context.anonR, t, p) in let lbr = Array.mapi (fun i (names, t) -> let ctx = branch_context env ci pms u names i in let env_lift' = List.fold_right push_env_lift ctx env_lift in match translate_type_eq env_lift' na (mkRel 1) t with | None -> None | Some t_eq -> Some (names, mkLambda (na, t, t_eq))) lbr in if Array.for_all Option.has_some lbr then let lbr = Array.map Option.get lbr in let case = mkCase (ci, u, pms, ((pnames, p), r), iv, translate_term env_lift tm, lbr) in Some (mkApp (case, [|c|])) else None (* TODO: in parallel with traversing Fix in translate_term_eq to look for types, traverse Fix to look for Type here *) | Fix _ -> None (* Not building a type *) | Proj _ | CoFix _ | Int _ | Float _ | String _ -> None | Meta _ | Evar _ -> assert false (* kernel terms *) in Option.map (fun c -> Term.it_mkProd_or_LetIn c ctx_eq) c and translate_term_eq env_lift c = let ctx, c = dest_lam_assum_expand env_lift.env c in let env_lift, ctx = translate_context_eq env_lift ctx in let c = match Constr.kind c with | Rel x -> (match has_decl_equality x env_lift.eq_status with | Some n -> Some (mkRel (Esubst.reloc_rel x env_lift.lift - n)) | None -> None) | Var x -> if Reduction.is_arity env (Typeops.type_of_variable env x) then (* Support for working in a context with "eq_x : x -> x -> bool" *) let eid = Id.of_string ("eq_"^(Id.to_string x)) in let () = try ignore (Environ.lookup_named eid env) with Not_found -> raise (ParameterWithoutEquality (GlobRef.VarRef x)) in Some (mkVar eid) else None | Cast (c,k,t) -> begin match translate_term_eq env_lift c, translate_type_eq env_lift Context.anonR c t with | Some c, Some t -> Some (mkCast (c,k,t)) | None, None -> None | (None | Some _), _ -> assert false end | Lambda _ | LetIn _ -> assert false | App (f,args) -> begin let f, args = match kind f with | Ind (ind',_) -> (match find_ind_env_lift env_lift ind' with | Some (nrecparams,_,n) when Array.length args >= nrecparams -> Some (mkRel n), Array.sub args nrecparams (Array.length args - nrecparams) | _ -> translate_term_eq env_lift f, args) | Const (kn,u) -> (match Environ.constant_opt_value_in env (kn, u) with | Some c -> translate_term_eq env_lift (mkApp (c,args)), [||] | None -> translate_term_eq env_lift f, args) | _ -> translate_term_eq env_lift f, args in match f with | Some f -> Some (mkApp (f, translate_arguments_eq env_lift args)) | None -> None end | Ind (ind',u) -> begin match find_ind_env_lift env_lift ind' with | Some (_,recparamsctx,n) -> Some (Term.it_mkLambda_or_LetIn (mkRel n) (translate_context env_lift recparamsctx)) | None -> try Some (Constr.mkRef (get_scheme handle (!beq_scheme_kind_aux()) ind',u)) with Not_found -> raise(EqNotFound ind') end | Const (kn,u as cst) -> if Environ.is_int63_type env kn then Some (int63_eqb ()) else if Environ.is_float64_type env kn then Some (float64_eqb ()) else if Environ.is_array_type env kn then (* TODO *) raise (ParameterWithoutEquality (GlobRef.ConstRef kn)) else (match Environ.constant_opt_value_in env (kn, u) with | Some c -> translate_term_eq env_lift c | None -> if Reduction.is_arity env (Typeops.type_of_constant_in env cst) then (* Support for working in a context with "eq_x : x -> x -> bool" *) (* Needs Hints, see test suite *) let eq_lbl = Id.of_string ("eq_" ^ Id.to_string (Constant.label kn)) in let kneq = Constant.change_label kn eq_lbl in if Environ.mem_constant kneq env then let _ = Environ.constant_opt_value_in env (kneq, u) in Some (mkConstU (kneq,u)) else raise (ParameterWithoutEquality (GlobRef.ConstRef kn)) else None) (* TODO: in parallel with preserving Type for Ind in translate_type_eq, preserve the types in Construct/CoFix *) | Proj _ | Construct _ | CoFix _ -> None | Case (ci, u, pms, ((pnames,p), r), iv, tm, lbr) -> let pctx = pred_context env ci pms u pnames in let env_lift_pred = List.fold_right push_env_lift pctx env_lift in let n = Array.length pnames in let c = mkCase (ci, u, Array.map (lift n) pms, ((pnames, liftn n (n+1) p), r), Constr.map_invert (lift n) iv, mkRel 1, Array.map (fun (names, br) -> (names, let q = Array.length names in liftn n (n+q+1) br)) lbr) in let p = translate_type_eq env_lift_pred Context.anonR c p in let lbr = Array.mapi (fun i (names, t) -> let ctx = branch_context env ci pms u names i in let env_lift' = List.fold_right push_env_lift ctx env_lift in match translate_term_eq env_lift' t with | None -> None | Some t_eq -> Some (names, t_eq)) lbr in if Array.for_all Option.has_some lbr && Option.has_some p then let lbr = Array.map Option.get lbr in Some (mkCase (ci, u, pms, ((pnames, Option.get p), r), iv, translate_term env_lift tm, lbr)) else None | Fix ((recindxs,i),(names,typarray,bodies as recdef)) -> let _ = (* Almost work: would need: 1. that the generated fix has an eq_status registration telling that an original recursive call should be interpreted as the pair of the whole fix and of the translated recursive call building the equality 2. something to do around either packaging the type with its equality, or begin able for a match to have a return predicate different though convertible to itself, namely here a fix of match (see test-suite) *) let mkfix j = mkFix ((recindxs,j),recdef) in let typarray = Array.mapi (fun i -> translate_type_eq env_lift Context.anonR (mkfix i)) typarray in let env_lift_types = push_rec_env_lift recdef env_lift in let bodies = Array.map (translate_term_eq env_lift_types) bodies in if Array.for_all Option.has_some bodies && Array.for_all Option.has_some typarray then let bodies = Array.map Option.get bodies in let typarray = Array.map Option.get typarray in Some (mkFix ((recindxs,i),(names,typarray,bodies))) else None in None | Sort _ -> raise InductiveWithSort (* would require a more sophisticated translation *) | Prod _ -> raise InductiveWithProduct (* loss of decidable if uncountable domain *) | Meta _ | Evar _ -> None (* assert false! *) | Int _ | Float _ | String _ | Array _ -> None in Option.map (fun c -> Term.it_mkLambda_or_LetIn c ctx) c (* Translate context by adding a context of Boolean equalities for each type argument Example of translated context: (F : (U -> U) -> nat -> U) (eq_F : forall G, (forall A, eq A -> eq (G A)) -> nat -> eq (F G)) *) and translate_context_eq env_lift ctx = let ctx = name_context env_lift.env ctx in let (env_lift_ctx,nctx_eq,ctx_with_eq) = List.fold_right (fun decl (env_lift,n,ctx) -> let env_lift = push_env_lift decl env_lift in let env_lift' = shiftn_env_lift (n-1) env_lift in match decl with | RelDecl.LocalDef (na,c,t) -> (match translate_term_eq env_lift' (lift 1 c), translate_type_eq env_lift' na (mkRel 1) (lift 1 t) with | Some eq_c, Some eq_typ -> (set_replicate 1 n env_lift, n, RelDecl.LocalDef (eqName na,eq_c,eq_typ) :: ctx) | None, None -> (env_lift, n-1, ctx) | (None | Some _), _ -> assert false) | RelDecl.LocalAssum (na,t) -> match translate_type_eq env_lift' na (mkRel 1) (lift 1 t) with | Some eq_typ -> (set_replicate 1 n env_lift, n, RelDecl.LocalAssum (eqName na,eq_typ) :: ctx) | None -> (env_lift, n-1, ctx) ) ctx (env_lift, Context.Rel.length ctx, ctx) in shiftn_env_lift nctx_eq env_lift_ctx, ctx_with_eq (* Translate arguments by adding Boolean equality when relevant Examples of translated applications: F (fun A => A) 0 eq_F (fun A => A) (fun A eq_A => eq_A) 0 F (fun A => list A) 0 eq_F (fun A => list A) (fun A eq_A => eq_list A eq_A) 0 *) and translate_arguments_eq env_lift args = let args' = Array.map (translate_term env_lift) args in let eq_args = Array.of_list (List.map_filter (translate_term_eq env_lift) (Array.to_list args)) in Array.append args' eq_args (* Copy-cat translation with relocation *) and translate_term env_lift c = exliftn env_lift.lift c and translate_context env_lift ctx = Context.Rel.map_with_binders (fun i -> translate_term (shiftn_env_lift i env_lift)) ctx and translate_term_with_binders env_lift (names,c) = (names, translate_term (shiftn_env_lift (Array.length names) env_lift) c) in (* Starting translating the inductive block to Boolean equalities; Morally corresponds to the Ind case of translate_term_eq *) (* fetching the mutual inductive body *) let mib = Environ.lookup_mind kn env in (* Setting universes *) let auctx = Declareops.universes_context mib.mind_universes in let u, ctx = UnivGen.fresh_instance_from auctx None in let uctx = UState.from_env env in let uctx = UState.merge_sort_context ~sideff:false UState.univ_rigid ~src:UState.Internal uctx ctx in (* number of inductives in the mutual *) let nb_ind = Array.length mib.mind_packets in let truly_recursive = let open Declarations in let is_rec ra = match Declareops.dest_recarg ra with Mrec _ -> true | Norec -> false in Array.exists (fun mip -> Array.exists (List.exists is_rec) (Declareops.dest_subterms mip.mind_recargs)) mib.mind_packets in (* params context divided *) let nonrecparams_ctx,recparams_ctx = Inductive.inductive_nonrec_rec_paramdecls (mib,u) in let params_ctx = nonrecparams_ctx @ recparams_ctx in let nparamsdecls = Context.Rel.length params_ctx in check_no_indices mib; let env_lift_recparams, recparams_ctx_with_eqs = translate_context_eq (empty_env_lift env) recparams_ctx in let env_lift_recparams_fix, fix_ctx, names, types = match mib.mind_finite with | CoFinite -> raise NoDecidabilityCoInductive | Finite when truly_recursive || nb_ind > 1 (* Hum, there exist non-recursive mutual types... *) -> (* rec name *) let rec_name i = (Id.to_string (Array.get mib.mind_packets i).mind_typename)^"_eqrec" in let names = Array.init nb_ind (fun i -> Context.make_annot (Name (Id.of_string (rec_name i))) Sorts.Relevant) in let types = Array.init nb_ind (fun i -> Option.get (translate_type_eq env_lift_recparams Context.anonR (mkPartialInd env ((kn,i),u) 0) (Term.it_mkProd_or_LetIn (*any sort:*) mkSet nonrecparams_ctx))) in let fix_ctx = List.rev (Array.to_list (Array.map2 (fun na t -> RelDecl.LocalAssum (na,t)) names types)) in shift_fix_env_lift kn mib.mind_nparams_rec recparams_ctx nb_ind env_lift_recparams, fix_ctx, names, types | Finite | BiFinite -> env_lift_recparams, [], [||], [||] in let env_lift_recparams_fix_nonrecparams, nonrecparams_ctx_with_eqs = translate_context_eq env_lift_recparams_fix nonrecparams_ctx in let make_one_eq cur = (* construct the "fun A B ... N, eqA eqB eqC ... N => fixpoint" part *) let ind = (kn,cur) in let indu = (ind,u) in let tomatch_ctx = RelDecl.[ LocalAssum (name_Y, translate_term (shiftn_env_lift 1 env_lift_recparams_fix_nonrecparams) (mkFullInd env indu 0)); LocalAssum (name_X, translate_term env_lift_recparams_fix_nonrecparams (mkFullInd env indu 0)) ] in let env_lift_recparams_fix_nonrecparams_tomatch = shiftn_env_lift 2 env_lift_recparams_fix_nonrecparams in (* current inductive we are working on *) let open Term in let pred = let cur_packet = mib.mind_packets.(cur) in (* Inductive toto : [rettyp] := *) let rettyp = Inductive.type_of_inductive ((mib,cur_packet),u) in (* split rettyp in a list without the non rec params and the last -> e.g. Inductive vec (A:Set) : nat -> Set := ... will do [nat] *) let _, rettyp = decompose_prod_n_decls nparamsdecls rettyp in let rettyp_l, _ = decompose_prod_decls rettyp in (* construct the predicate for the Case part*) Term.it_mkLambda_or_LetIn (mkLambda (Context.make_annot Anonymous Sorts.Relevant, mkFullInd env indu (List.length rettyp_l), (bb ()))) rettyp_l in (* make_one_eq *) (* do the [| C1 ... => match Y with ... end ... Cn => match Y with ... end |] part *) let rci = EConstr.ERelevance.relevant in (* returning a boolean, hence relevant *) let open Inductiveops in let constrs = let params = Context.Rel.instance_list EConstr.mkRel 0 params_ctx in get_constructors env (make_ind_family (on_snd EConstr.EInstance.make indu, params)) in let make_andb_list = function | [] -> tt () | eq :: eqs -> List.fold_left (fun eqs eq -> mkApp (andb(),[|eq;eqs|])) eq eqs in let body = match Environ.get_projections env ind with | Some projs -> (* A primitive record *) let nb_cstr_args = List.length constrs.(0).cs_args in let _,_,eqs = List.fold_right (fun decl (ndx,env_lift,l) -> let decl = EConstr.Unsafe.to_rel_decl decl in let env_lift' = push_env_lift decl env_lift in match decl with | RelDecl.LocalDef (na,b,t) -> (ndx-1,env_lift',l) | RelDecl.LocalAssum (na,cc) -> if is_irrelevant env_lift.env cc then (ndx-1,env_lift',l) else if Vars.noccur_between 1 (nb_cstr_args-ndx) cc then let cc = lift (ndx-nb_cstr_args) cc in match translate_term_eq env_lift_recparams_fix_nonrecparams_tomatch cc with | None -> raise (EqUnknown "type") (* A supported type should have an eq *) | Some eqA -> let proj, relevance = projs.(nb_cstr_args-ndx) in let proj = Projection.make proj true in (ndx-1,env_lift',mkApp (eqA, [|mkProj (proj, relevance, mkRel 2); mkProj (proj, relevance, mkRel 1)|])::l) else raise InternalDependencies) constrs.(0).cs_args (nb_cstr_args,env_lift_recparams_fix_nonrecparams_tomatch,[]) in make_andb_list eqs | None -> (* An inductive type *) let ci = make_case_info env ind MatchStyle in let nconstr = Array.length constrs in let ar = Array.init nconstr (fun i -> let nb_cstr_args = List.length constrs.(i).cs_args in let env_lift_recparams_fix_nonrecparams_tomatch_csargsi = shiftn_env_lift nb_cstr_args env_lift_recparams_fix_nonrecparams_tomatch in let ar2 = Array.init nconstr (fun j -> let env_lift_recparams_fix_nonrecparams_tomatch_csargsij = shiftn_env_lift nb_cstr_args env_lift_recparams_fix_nonrecparams_tomatch_csargsi in let cc = if Int.equal i j then let _,_,eqs = List.fold_right (fun decl (ndx,env_lift,l) -> let decl = EConstr.Unsafe.to_rel_decl decl in let env_lift' = push_env_lift decl env_lift in match decl with | RelDecl.LocalDef (na,b,t) -> (ndx-1,env_lift',l) | RelDecl.LocalAssum (na,cc) -> if is_irrelevant env_lift.env cc then (ndx-1,env_lift',l) else if Vars.noccur_between 1 (nb_cstr_args-ndx) cc then let cc = lift (ndx-nb_cstr_args) cc in match translate_term_eq env_lift_recparams_fix_nonrecparams_tomatch_csargsij cc with | None -> raise (EqUnknown "type") (* A supported type should have an eq *) | Some eqA -> (ndx-1,env_lift',mkApp (eqA, [|mkRel (ndx+nb_cstr_args);mkRel ndx|])::l) else raise InternalDependencies) constrs.(j).cs_args (nb_cstr_args,env_lift_recparams_fix_nonrecparams_tomatch_csargsij,[]) in make_andb_list eqs else ff () in let cs_argsj = translate_context env_lift_recparams_fix_nonrecparams_tomatch_csargsi (EConstr.Unsafe.to_rel_context constrs.(j).cs_args) in Term.it_mkLambda_or_LetIn cc cs_argsj) in let predj = EConstr.of_constr (translate_term env_lift_recparams_fix_nonrecparams_tomatch_csargsi pred) in let case = simple_make_case_or_project env (Evd.from_env env) ci (predj,rci) NoInvert (EConstr.mkRel (nb_cstr_args + 1)) (EConstr.of_constr_array ar2) in let cs_argsi = translate_context env_lift_recparams_fix_nonrecparams_tomatch (EConstr.Unsafe.to_rel_context constrs.(i).cs_args) in Term.it_mkLambda_or_LetIn (EConstr.Unsafe.to_constr case) cs_argsi) in let predi = EConstr.of_constr (translate_term env_lift_recparams_fix_nonrecparams_tomatch pred) in let case = simple_make_case_or_project env (Evd.from_env env) ci (predi,rci) NoInvert (EConstr.mkRel 2) (EConstr.of_constr_array ar) in EConstr.Unsafe.to_constr case in Term.it_mkLambda_or_LetIn (Term.it_mkLambda_or_LetIn body tomatch_ctx) nonrecparams_ctx_with_eqs in (* build_beq_scheme *) let res = match mib.mind_finite with | CoFinite -> raise NoDecidabilityCoInductive | Finite when truly_recursive || nb_ind > 1 (* Hum... *) -> let cores = Array.init nb_ind make_one_eq in Array.init nb_ind (fun i -> let kelim = Inductiveops.elim_sort (mib,mib.mind_packets.(i)) in if not (Inductive.eliminates_to (Environ.qualities env) kelim Sorts.Quality.qtype) then raise (NonSingletonProp (kn,i)); let decrArg = Context.Rel.length nonrecparams_ctx_with_eqs in let fix = mkFix (((Array.make nb_ind decrArg),i),(names,types,cores)) in Term.it_mkLambda_or_LetIn fix recparams_ctx_with_eqs) | Finite | BiFinite -> assert (Int.equal nb_ind 1); (* If the inductive type is not recursive, the fixpoint is not used, so let's replace it with garbage *) let kelim = Inductiveops.elim_sort (mib,mib.mind_packets.(0)) in if not (Inductive.eliminates_to (Environ.qualities env) kelim Sorts.Quality.qtype) then raise (NonSingletonProp (kn,0)); [|Term.it_mkLambda_or_LetIn (make_one_eq 0) recparams_ctx_with_eqs|] in let uctx = (* infer univ constraints For instance template poly inductive produces a univ monomorphic scheme which when applied needs to constrain the universe of its argument *) let sigma = Evd.from_ctx uctx in let sigma = Array.fold_left (fun sigma c -> fst @@ Typing.type_of env sigma (EConstr.of_constr c)) sigma res in Evd.ustate sigma in res, uctx let beq_scheme_kind = Ind_tables.declare_mutual_scheme_object "beq" ~deps:build_beq_scheme_deps build_beq_scheme let _ = beq_scheme_kind_aux := fun () -> beq_scheme_kind (* This function tryies to get the [inductive] between a constr the constr should be Ind i or App(Ind i,[|args|]) *) let destruct_ind env sigma c = let open EConstr in let (c,v) = Reductionops.whd_all_stack env sigma c in destInd sigma c, Array.of_list v let bl_scheme_kind_aux = ref (fun () -> failwith "Undefined") let lb_scheme_kind_aux = ref (fun () -> failwith "Undefined") (* In the following, avoid is the list of names to avoid. If the args of the Inductive type are A1 ... An then avoid should be [| lb_An ... lb _A1 (resp. bl_An ... bl_A1) eq_An .... eq_A1 An ... A1 |] so from Ai we can find the correct eq_Ai bl_ai or lb_ai *) (* used in the leib -> bool side*) let do_replace_lb handle aavoid narg p q = let open EConstr in let avoid = Array.of_list aavoid in let do_arg env sigma hd v offset = match kind sigma v with | Var s -> let x = narg*offset in let n = Array.length avoid in let rec find i = if Id.equal avoid.(n-i) s then avoid.(n-i-x) else (if i (* Works in specific situations where the args have to be already declared as a Parameter (see example "J" in test file SchemeEquality.v); We assume the parameter to have the same polymorphic arity as cst *) let lbl = Id.to_string (Constant.label cst) in let newlbl = if Int.equal offset 1 then ("eq_" ^ lbl) else (lbl ^ "_lb") in let newcst = Constant.change_label cst (Id.of_string newlbl) in if Environ.mem_constant newcst env then mkConstU (newcst,u) else raise (ConstructorWithNonParametricInductiveType (fst hd)) | _ -> raise (ConstructorWithNonParametricInductiveType (fst hd)) in Proofview.Goal.enter begin fun gl -> let sigma = Proofview.Goal.sigma gl in let env = Proofview.Goal.env gl in let type_of_pq = Retyping.get_type_of env sigma p in let (ind,u as indu),v = destruct_ind env sigma type_of_pq in let c = get_scheme handle (!lb_scheme_kind_aux ()) ind in let sigma , lb_type_of_p = Evd.fresh_global env sigma c in let lb_args = Array.append (Array.append v (Array.Smart.map (fun x -> do_arg env sigma indu x 1) v)) (Array.Smart.map (fun x -> do_arg env sigma indu x 2) v) in let app = if Array.is_empty lb_args then lb_type_of_p else mkApp (lb_type_of_p,lb_args) in Tacticals.tclTHENLIST [ Proofview.Unsafe.tclEVARS sigma; Equality.replace p q ; Tactics.apply app ; Auto.default_auto] end (* used in the bool -> leb side *) let do_replace_bl handle (ind,u as indu) aavoid narg lft rgt = let open EConstr in let avoid = Array.of_list aavoid in let do_arg env sigma hd v offset = match kind sigma v with | Var s -> let x = narg*offset in let n = Array.length avoid in let rec find i = if Id.equal avoid.(n-i) s then avoid.(n-i-x) else (if i (* Works in specific situations where the args have to be already declared as a Parameter (see example "J" in test file SchemeEquality.v) We assume the parameter to have the same polymorphic arith as cst *) let lbl = Id.to_string (Constant.label cst) in let newlbl = if Int.equal offset 1 then ("eq_" ^ lbl) else (lbl ^ "_bl") in let newcst = Constant.change_label cst (Id.of_string newlbl) in if Environ.mem_constant newcst env then mkConstU (newcst,u) else raise (ConstructorWithNonParametricInductiveType (fst hd)) | _ -> raise (ConstructorWithNonParametricInductiveType (fst hd)) in let rec aux l1 l2 = match (l1,l2) with | (t1::q1,t2::q2) -> Proofview.Goal.enter begin fun gl -> let env = Proofview.Goal.env gl in let sigma = Proofview.Goal.sigma gl in if EConstr.eq_constr sigma t1 t2 then aux q1 q2 else ( let tt1 = Retyping.get_type_of env sigma t1 in let (ind',u as indu),v = try destruct_ind env sigma tt1 (* trick so that the good sequence is returned*) with e when CErrors.noncritical e -> indu,[||] in if Environ.QInd.equal env ind' ind then Tacticals.tclTHENLIST [Equality.replace t1 t2; Auto.default_auto ; aux q1 q2 ] else ( let c = get_scheme handle (!bl_scheme_kind_aux ()) ind' in let sigma , bl_t1 = Evd.fresh_global env sigma c in let bl_args = Array.append (Array.append v (Array.Smart.map (fun x -> do_arg env sigma indu x 1) v)) (Array.Smart.map (fun x -> do_arg env sigma indu x 2) v ) in let app = if Array.is_empty bl_args then bl_t1 else mkApp (bl_t1,bl_args) in Tacticals.tclTHENLIST [ Proofview.Unsafe.tclEVARS sigma; Equality.replace_by t1 t2 (Tacticals.tclTHEN (Tactics.apply app) (Auto.default_auto)) ; aux q1 q2 ] ) ) end | ([],[]) -> Proofview.tclUNIT () | _ -> Tacticals.tclZEROMSG Pp.(str "Both side of the equality must have the same arity.") in let open Proofview.Notations in Proofview.tclEVARMAP >>= fun sigma -> begin try Proofview.tclUNIT (destApp sigma lft) with DestKO -> Tacticals.tclZEROMSG Pp.(str "replace failed.") end >>= fun (ind1,ca1) -> begin try Proofview.tclUNIT (destApp sigma rgt) with DestKO -> Tacticals.tclZEROMSG Pp.(str "replace failed.") end >>= fun (ind2,ca2) -> begin try Proofview.tclUNIT (fst (destInd sigma ind1)) with DestKO -> begin try Proofview.tclUNIT (fst (fst (destConstruct sigma ind1))) with DestKO -> Tacticals.tclZEROMSG Pp.(str "The expected type is an inductive one.") end end >>= fun (sp1,i1) -> begin try Proofview.tclUNIT (fst (destInd sigma ind2)) with DestKO -> begin try Proofview.tclUNIT (fst (fst (destConstruct sigma ind2))) with DestKO -> Tacticals.tclZEROMSG Pp.(str "The expected type is an inductive one.") end end >>= fun (sp2,i2) -> Proofview.tclENV >>= fun env -> if not (Environ.QMutInd.equal env sp1 sp2) || not (Int.equal i1 i2) then Tacticals.tclZEROMSG Pp.(str "Eq should be on the same type") else aux (Array.to_list ca1) (Array.to_list ca2) (* create, from a list of ids [i1,i2,...,in] the list [(in,eq_in,in_bl,in_al),,...,(i1,eq_i1,i1_bl_i1_al )] *) let list_id l = List.fold_left ( fun a decl -> let s' = match RelDecl.get_name decl with Name s -> Id.to_string s | Anonymous -> "A" in (Id.of_string s',Id.of_string ("eq_"^s'), Id.of_string (s'^"_bl"), Id.of_string (s'^"_lb")) ::a ) [] l let avoid_of_list_id list_id = List.fold_left (fun avoid (s,seq,sbl,slb) -> List.fold_left (fun avoid id -> Id.Set.add id avoid) avoid [s;seq;sbl;slb]) Id.Set.empty list_id (* build the right eq_I A B.. N eq_A .. eq_N *) let eqI handle (ind,u) list_id = let eA = Array.of_list((List.map (fun (s,_,_,_) -> mkVar s) list_id)@ (List.map (fun (_,seq,_,_)-> mkVar seq) list_id )) and e = Constr.mkRef (get_scheme handle beq_scheme_kind ind,u) in mkApp(e,eA) (**********************************************************************) (* Boolean->Leibniz *) open Namegen let compute_bl_goal env handle (ind,u) lnamesparrec nparrec = let list_id = list_id lnamesparrec in let eqI = eqI handle (ind,u) list_id in let avoid = avoid_of_list_id list_id in let x = next_ident_away (Id.of_string "x") avoid in let y = next_ident_away (Id.of_string "y") (Id.Set.add x avoid) in let open Term in let create_input c = let bl_typ = List.map (fun (s,seq,_,_) -> mkNamedProd (Context.make_annot x Sorts.Relevant) (mkVar s) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkVar s) ( mkArrow ( mkApp(eq (),[|bb (); mkApp(mkVar seq,[|mkVar x;mkVar y|]);tt () |])) Sorts.Relevant ( mkApp(eq (),[|mkVar s;mkVar x;mkVar y|])) )) ) list_id in let bl_input = List.fold_left2 ( fun a (s,_,sbl,_) b -> mkNamedProd (Context.make_annot sbl Sorts.Relevant) b a ) c (List.rev list_id) (List.rev bl_typ) in let eqs_typ = List.map (fun (s,_,_,_) -> mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s,mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s,(bb ()))) ) list_id in let eq_input = List.fold_left2 ( fun a (s,seq,_,_) b -> mkNamedProd (Context.make_annot seq Sorts.Relevant) b a ) bl_input (List.rev list_id) (List.rev eqs_typ) in List.fold_left (fun a decl -> let x = Context.map_annot (function Name s -> s | Anonymous -> next_ident_away (Id.of_string "A") avoid) (RelDecl.get_annot decl) in mkNamedProd x (RelDecl.get_type decl) a) eq_input lnamesparrec in create_input ( mkNamedProd (Context.make_annot x Sorts.Relevant) (mkFullInd env (ind,u) (2*nparrec)) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkFullInd env (ind,u) (2*nparrec+1)) ( mkArrow (mkApp(eq (),[|bb ();mkApp(eqI,[|mkVar x;mkVar y|]);tt ()|])) Sorts.Relevant (mkApp(eq (),[|mkFullInd env (ind,u) (2*nparrec+3);mkVar x;mkVar y|])) ))) let compute_bl_tact handle ind lnamesparrec nparrec = let list_id = list_id lnamesparrec in let first_intros = ( List.map (fun (s,_,_,_) -> s ) list_id ) @ ( List.map (fun (_,seq,_,_ ) -> seq) list_id ) @ ( List.map (fun (_,_,sbl,_ ) -> sbl) list_id ) in let open Tactics in let open Proofview.Notations in Ind_tables.push_handle handle <*> intros_using_then first_intros begin fun fresh_first_intros -> Tacticals.tclTHENLIST [ intro_using_then (Id.of_string "x") (fun freshn -> induct_on (EConstr.mkVar freshn)); intro_using_then (Id.of_string "y") (fun freshm -> destruct_on (EConstr.mkVar freshm)); intro_using_then (Id.of_string "Z") begin fun freshz -> Tacticals.tclTHENLIST [ intros; Tacticals.tclTRY ( Tacticals.tclORELSE reflexivity my_discr_tac ); simpl_in_hyp (freshz,Locus.InHyp); (* repeat ( apply andb_prop in z;let z1:= fresh "Z" in destruct z as [z1 z]). *) Tacticals.tclREPEAT ( Tacticals.tclTHENLIST [ Simple.apply_in freshz (EConstr.of_constr (andb_prop())); let open Tactypes in destruct_on_as (EConstr.mkVar freshz) (IntroOrPattern [[CAst.make @@ IntroNaming (IntroFresh (Id.of_string "Z")); CAst.make @@ IntroNaming (IntroIdentifier freshz)]]) ]); (* Ci a1 ... an = Ci b1 ... bn replace bi with ai; auto || replace bi with ai by apply typeofbi_prod ; auto *) Proofview.Goal.enter begin fun gl -> let env = Proofview.Goal.env gl in let concl = Proofview.Goal.concl gl in let sigma = Proofview.Goal.sigma gl in match EConstr.kind sigma concl with | App (c,ca) -> ( match EConstr.kind sigma c with | Ind (indeq, u) -> if Environ.QGlobRef.equal env (GlobRef.IndRef indeq) Rocqlib.(lib_ref "core.eq.type") then Tacticals.tclTHEN (do_replace_bl handle ind (List.rev fresh_first_intros) nparrec (ca.(2)) (ca.(1))) Auto.default_auto else Tacticals.tclZEROMSG Pp.(str "Failure while solving Boolean->Leibniz.") | _ -> Tacticals.tclZEROMSG Pp.(str" Failure while solving Boolean->Leibniz.") ) | _ -> Tacticals.tclZEROMSG Pp.(str "Failure while solving Boolean->Leibniz.") end ] end ] end let make_bl_scheme env handle mind = let mib = Environ.lookup_mind mind env in if not (Int.equal (Array.length mib.mind_packets) 1) then CErrors.user_err Pp.(str "Automatic building of boolean->Leibniz lemmas not supported"); (* Setting universes *) let auctx = Declareops.universes_context mib.mind_universes in let u, uctx = UnivGen.fresh_instance_from auctx None in let uctx = UState.merge_sort_context ~sideff:false UState.univ_rigid ~src:UState.Internal (UState.from_env env) uctx in let ind = (mind,0) in let nparrec = mib.mind_nparams_rec in let lnonparrec,lnamesparrec = Inductive.inductive_nonrec_rec_paramdecls (mib,u) in let bl_goal = compute_bl_goal env handle (ind,u) lnamesparrec nparrec in let bl_goal = EConstr.of_constr bl_goal in let univ_poly = Declareops.inductive_is_polymorphic mib in let poly = PolyFlags.of_univ_poly univ_poly in (* FIXME cumulativity not handled *) let uctx = if univ_poly then Evd.ustate (fst (Typing.sort_of env (Evd.from_ctx uctx) bl_goal)) else uctx in let (ans, _, _, _, uctx) = Subproof.build_by_tactic ~poly env ~uctx ~typ:bl_goal (compute_bl_tact handle (ind, EConstr.EInstance.make u) lnamesparrec nparrec) in ([|ans|], uctx) let make_bl_scheme_deps env ind = let inds = get_inductive_deps ~noprop:false env ind in let map ind = Ind_tables.SchemeMutualDep (ind, !bl_scheme_kind_aux ()) in Ind_tables.SchemeMutualDep (ind, beq_scheme_kind) :: List.map map inds let bl_scheme_kind = Ind_tables.declare_mutual_scheme_object "dec_bl" ~deps:make_bl_scheme_deps make_bl_scheme let _ = bl_scheme_kind_aux := fun () -> bl_scheme_kind (**********************************************************************) (* Leibniz->Boolean *) let compute_lb_goal env handle (ind,u) lnamesparrec nparrec = let list_id = list_id lnamesparrec in let eq = eq () and tt = tt () and bb = bb () in let avoid = avoid_of_list_id list_id in let eqI = eqI handle (ind,u) list_id in let x = next_ident_away (Id.of_string "x") avoid in let y = next_ident_away (Id.of_string "y") (Id.Set.add x avoid) in let open Term in let create_input c = let lb_typ = List.map (fun (s,seq,_,_) -> mkNamedProd (Context.make_annot x Sorts.Relevant) (mkVar s) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkVar s) ( mkArrow ( mkApp(eq,[|mkVar s;mkVar x;mkVar y|])) Sorts.Relevant ( mkApp(eq,[|bb;mkApp(mkVar seq,[|mkVar x;mkVar y|]);tt|])) )) ) list_id in let lb_input = List.fold_left2 ( fun a (s,_,_,slb) b -> mkNamedProd (Context.make_annot slb Sorts.Relevant) b a ) c (List.rev list_id) (List.rev lb_typ) in let eqs_typ = List.map (fun (s,_,_,_) -> mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s, mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s,bb)) ) list_id in let eq_input = List.fold_left2 ( fun a (s,seq,_,_) b -> mkNamedProd (Context.make_annot seq Sorts.Relevant) b a ) lb_input (List.rev list_id) (List.rev eqs_typ) in List.fold_left (fun a decl -> let x = Context.map_annot (function Name s -> s | Anonymous -> Id.of_string "A") (RelDecl.get_annot decl) in mkNamedProd x (RelDecl.get_type decl) a) eq_input lnamesparrec in create_input ( mkNamedProd (Context.make_annot x Sorts.Relevant) (mkFullInd env (ind,u) (2*nparrec)) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkFullInd env (ind,u) (2*nparrec+1)) ( mkArrow (mkApp(eq,[|mkFullInd env (ind,u) (2*nparrec+2);mkVar x;mkVar y|])) Sorts.Relevant (mkApp(eq,[|bb;mkApp(eqI,[|mkVar x;mkVar y|]);tt|])) ))) let compute_lb_tact handle ind lnamesparrec nparrec = let list_id = list_id lnamesparrec in let first_intros = ( List.map (fun (s,_,_,_) -> s ) list_id ) @ ( List.map (fun (_,seq,_,_) -> seq) list_id ) @ ( List.map (fun (_,_,_,slb) -> slb) list_id ) in let open Tactics in let open Proofview.Notations in Ind_tables.push_handle handle <*> intros_using_then first_intros begin fun fresh_first_intros -> Tacticals.tclTHENLIST [ intro_using_then (Id.of_string "x") (fun freshn -> induct_on (EConstr.mkVar freshn)); intro_using_then (Id.of_string "y") (fun freshm -> destruct_on (EConstr.mkVar freshm)); intro_using_then (Id.of_string "Z") begin fun freshz -> Tacticals.tclTHENLIST [ intros; Tacticals.tclTRY ( Tacticals.tclORELSE reflexivity my_discr_tac ); my_inj_tac freshz; intros; simpl_in_concl; Auto.default_auto; Tacticals.tclREPEAT ( Tacticals.tclTHENLIST [apply (EConstr.of_constr (andb_true_intro())); simplest_split ;Auto.default_auto ] ); Proofview.Goal.enter begin fun gls -> let concl = Proofview.Goal.concl gls in let sigma = Proofview.Goal.sigma gls in (* assume the goal to be eq (eq_type ...) = true *) match EConstr.kind sigma concl with | App(c,ca) -> (match (EConstr.kind sigma ca.(1)) with | App(c',ca') -> let n = Array.length ca' in do_replace_lb handle (List.rev fresh_first_intros) nparrec ca'.(n-2) ca'.(n-1) | _ -> Tacticals.tclZEROMSG Pp.(str "Failure while solving Leibniz->Boolean.") ) | _ -> Tacticals.tclZEROMSG Pp.(str "Failure while solving Leibniz->Boolean.") end ] end ] end let make_lb_scheme env handle mind = let mib = Environ.lookup_mind mind env in if not (Int.equal (Array.length mib.mind_packets) 1) then CErrors.user_err Pp.(str "Automatic building of Leibniz->boolean lemmas not supported"); let ind = (mind,0) in (* Setting universes *) let auctx = Declareops.universes_context mib.mind_universes in let u, uctx = UnivGen.fresh_instance_from auctx None in let uctx = UState.merge_sort_context ~sideff:false UState.univ_rigid ~src:UState.Internal (UState.from_env env) uctx in let nparrec = mib.mind_nparams_rec in let lnonparrec,lnamesparrec = Inductive.inductive_nonrec_rec_paramdecls (mib,u) in let lb_goal = compute_lb_goal env handle (ind,u) lnamesparrec nparrec in let lb_goal = EConstr.of_constr lb_goal in let poly = Declareops.inductive_is_polymorphic mib in let uctx = if poly then Evd.ustate (fst (Typing.sort_of env (Evd.from_ctx uctx) lb_goal)) else uctx in let poly = PolyFlags.of_univ_poly poly (* FIXME cumulativity not handled *) in let (ans, _, _, _, ctx) = Subproof.build_by_tactic ~poly env ~uctx ~typ:lb_goal (compute_lb_tact handle ind lnamesparrec nparrec) in ([|ans|], ctx) let make_lb_scheme_deps env ind = let inds = get_inductive_deps ~noprop:false env ind in let map ind = Ind_tables.SchemeMutualDep (ind, !lb_scheme_kind_aux ()) in Ind_tables.SchemeMutualDep (ind, beq_scheme_kind) :: List.map map inds let lb_scheme_kind = Ind_tables.declare_mutual_scheme_object "dec_lb" ~deps:make_lb_scheme_deps make_lb_scheme let _ = lb_scheme_kind_aux := fun () -> lb_scheme_kind (**********************************************************************) (* Decidable equality *) let check_not_is_defined () = if not (Rocqlib.has_ref "core.not.type") then raise (UndefinedCst "not") (* {n=m}+{n<>m} part *) let compute_dec_goal env ind lnamesparrec nparrec = check_not_is_defined (); let eq = eq () and tt = tt () and bb = bb () in let list_id = list_id lnamesparrec in let avoid = avoid_of_list_id list_id in let x = next_ident_away (Id.of_string "x") avoid in let y = next_ident_away (Id.of_string "y") (Id.Set.add x avoid) in let open Term in let create_input c = let lb_typ = List.map (fun (s,seq,_,_) -> mkNamedProd (Context.make_annot x Sorts.Relevant) (mkVar s) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkVar s) ( mkArrow ( mkApp(eq,[|mkVar s;mkVar x;mkVar y|])) Sorts.Relevant ( mkApp(eq,[|bb;mkApp(mkVar seq,[|mkVar x;mkVar y|]);tt|])) )) ) list_id in let bl_typ = List.map (fun (s,seq,_,_) -> mkNamedProd (Context.make_annot x Sorts.Relevant) (mkVar s) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkVar s) ( mkArrow ( mkApp(eq,[|bb;mkApp(mkVar seq,[|mkVar x;mkVar y|]);tt|])) Sorts.Relevant ( mkApp(eq,[|mkVar s;mkVar x;mkVar y|])) )) ) list_id in let lb_input = List.fold_left2 ( fun a (s,_,_,slb) b -> mkNamedProd (Context.make_annot slb Sorts.Relevant) b a ) c (List.rev list_id) (List.rev lb_typ) in let bl_input = List.fold_left2 ( fun a (s,_,sbl,_) b -> mkNamedProd (Context.make_annot sbl Sorts.Relevant) b a ) lb_input (List.rev list_id) (List.rev bl_typ) in let eqs_typ = List.map (fun (s,_,_,_) -> mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s, mkProd(Context.make_annot Anonymous Sorts.Relevant,mkVar s,bb)) ) list_id in let eq_input = List.fold_left2 ( fun a (s,seq,_,_) b -> mkNamedProd (Context.make_annot seq Sorts.Relevant) b a ) bl_input (List.rev list_id) (List.rev eqs_typ) in List.fold_left (fun a decl -> let x = Context.map_annot (function Name s -> s | Anonymous -> Id.of_string "A") (RelDecl.get_annot decl) in mkNamedProd x (RelDecl.get_type decl) a) eq_input lnamesparrec in let eqnm = mkApp(eq,[|mkFullInd env ind (3*nparrec+2);mkVar x;mkVar y|]) in create_input ( mkNamedProd (Context.make_annot x Sorts.Relevant) (mkFullInd env ind (3*nparrec)) ( mkNamedProd (Context.make_annot y Sorts.Relevant) (mkFullInd env ind (3*nparrec+1)) ( mkApp(sumbool(),[|eqnm;mkApp (UnivGen.constr_of_monomorphic_global (Global.env ()) @@ Rocqlib.lib_ref "core.not.type",[|eqnm|])|]) ) ) ) let compute_dec_tact handle (ind,u) lnamesparrec nparrec = let eq = eq () and tt = tt () and ff = ff () and bb = bb () in let list_id = list_id lnamesparrec in let _ = get_scheme handle beq_scheme_kind ind in (* This is just an assertion? *) let _non_fresh_eqI = eqI handle (ind,u) list_id in let eqtrue x = mkApp(eq,[|bb;x;tt|]) in let eqfalse x = mkApp(eq,[|bb;x;ff|]) in let first_intros = ( List.map (fun (s,_,_,_) -> s ) list_id ) @ ( List.map (fun (_,seq,_,_) -> seq) list_id ) @ ( List.map (fun (_,_,sbl,_) -> sbl) list_id ) @ ( List.map (fun (_,_,_,slb) -> slb) list_id ) in let open Tactics in let fresh_id s gl = fresh_id_in_env (Id.Set.empty) s (Proofview.Goal.env gl) in let open Proofview.Notations in Ind_tables.push_handle handle <*> intros_using_then first_intros begin fun fresh_first_intros -> let eqI = let a = Array.of_list fresh_first_intros in let n = List.length list_id in assert (Int.equal (Array.length a) (4 * n)); let fresh_list_id = List.init n (fun i -> (Array.get a i, Array.get a (i+n), Array.get a (i+2*n), Array.get a (i+3*n))) in eqI handle (ind,u) fresh_list_id in intro_using_then (Id.of_string "x") begin fun freshn -> intro_using_then (Id.of_string "y") begin fun freshm -> Proofview.Goal.enter begin fun gl -> let freshH = fresh_id (Id.of_string "H") gl in let eqbnm = mkApp(eqI,[|mkVar freshn;mkVar freshm|]) in let arfresh = Array.of_list fresh_first_intros in let xargs = Array.sub arfresh 0 (2*nparrec) in (* univ polymorphic schemes may have extra constraints from using univ monomorphic f_equal and the like *) let env, sigma = Proofview.Goal.(env gl, sigma gl) in let c = get_scheme handle bl_scheme_kind ind in let sigma , blI = Evd.fresh_global env sigma c in let c = get_scheme handle lb_scheme_kind ind in let sigma , lbI = Evd.fresh_global env sigma c in Tacticals.tclTHENLIST [ Proofview.Unsafe.tclEVARS sigma; (*we do this so we don't have to prove the same goal twice *) assert_by (Name freshH) (EConstr.of_constr ( mkApp(sumbool(),[|eqtrue eqbnm; eqfalse eqbnm|]) )) (Tacticals.tclTHEN (destruct_on (EConstr.of_constr eqbnm)) Auto.default_auto); Proofview.Goal.enter begin fun gl -> let freshH2 = fresh_id (Id.of_string "H") gl in Tacticals.tclTHENS (destruct_on_using (EConstr.mkVar freshH) freshH2) [ (* left *) Tacticals.tclTHENLIST [ simplest_left; apply (EConstr.mkApp(blI,Array.map EConstr.mkVar xargs)); Auto.default_auto ] ; (*right *) Proofview.Goal.enter begin fun gl -> let freshH3 = fresh_id (Id.of_string "H") gl in Tacticals.tclTHENLIST [ simplest_right ; unfold_constr (Rocqlib.lib_ref "core.not.type"); intro; Equality.subst_all (); assert_by (Name freshH3) (EConstr.of_constr (mkApp(eq,[|bb;mkApp(eqI,[|mkVar freshm;mkVar freshm|]);tt|]))) (Tacticals.tclTHENLIST [ apply (EConstr.mkApp(lbI,Array.map EConstr.mkVar xargs)); Auto.default_auto ]); Equality.general_rewrite ~where:(Some freshH3) ~l2r:true Locus.AllOccurrences ~freeze:true ~dep:false ~with_evars:true ((EConstr.mkVar freshH2), NoBindings ) ; my_discr_tac ] end ] end ] end end end end let make_eq_decidability env handle mind = let mib = Environ.lookup_mind mind env in if not (Int.equal (Array.length mib.mind_packets) 1) then raise DecidabilityMutualNotSupported; let ind = (mind,0) in let nparrec = mib.mind_nparams_rec in (* Setting universes *) let auctx = Declareops.universes_context mib.mind_universes in let u, uctx = UnivGen.fresh_instance_from auctx None in let uctx = UState.merge_sort_context ~sideff:false UState.univ_rigid ~src:UState.Internal (UState.from_env env) uctx in let lnonparrec,lnamesparrec = Inductive.inductive_nonrec_rec_paramdecls (mib,u) in let dec_goal = EConstr.of_constr (compute_dec_goal env (ind,u) lnamesparrec nparrec) in let univ_poly = Declareops.inductive_is_polymorphic mib in (* FIXME: cumulativity not handled *) let poly = PolyFlags.of_univ_poly univ_poly in let uctx = if univ_poly then Evd.ustate (fst (Typing.sort_of env (Evd.from_ctx uctx) dec_goal)) else uctx in let (ans, _, _, _, ctx) = Subproof.build_by_tactic ~poly env ~uctx ~typ:dec_goal (compute_dec_tact handle (ind,u) lnamesparrec nparrec) in ([|ans|], ctx) let eq_dec_scheme_kind = Ind_tables.declare_mutual_scheme_object "eq_dec" ~deps:(fun _ ind -> [SchemeMutualDep (ind, beq_scheme_kind); SchemeMutualDep (ind, bl_scheme_kind); SchemeMutualDep (ind, lb_scheme_kind)]) make_eq_decidability (* The eq_dec_scheme proofs depend on the equality and discr tactics but the inj tactics, that comes with discr, depends on the eq_dec_scheme... *) let _ = Equality.set_eq_dec_scheme_kind eq_dec_scheme_kind rocq-9.2.0/vernac/auto_ind_decl.mli000066400000000000000000000027331516144147600172560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* obj = declare_object {(default_object "CANONICAL-STRUCTURE") with open_function = simple_open ~cat:canon_cat open_canonical_structure; cache_function = cache_canonical_structure; subst_function = (fun (subst,(c,local)) -> Instance.subst subst c, local); classify_function = (fun x -> Substitute); discharge_function = discharge_canonical_structure } let add_canonical_structure x = Lib.add_leaf (inCanonStruc x) let declare_canonical_structure ?(local=false) ref = let env = Global.env () in let sigma = Evd.from_env env in add_canonical_structure (Instance.make env sigma ref, local) rocq-9.2.0/vernac/canonical.mli000066400000000000000000000013621516144147600164110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* GlobRef.t -> unit rocq-9.2.0/vernac/classes.ml000066400000000000000000000576271516144147600157650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* hov 2 (str "Using an inferred default mode: " ++ prlist_with_sep spc Hints.pp_hint_mode m ++ spc () ++ str "for" ++ spc () ++ Printer.pr_global gr)) let set_typeclass_transparency ?typeclasses_db ~locality c b = let db_name = match typeclasses_db with | None -> Class_tactics.typeclasses_db | Some s -> s in let () = check_typeclasses_db () in Hints.add_hints ~locality [db_name] (Hints.HintsTransparencyEntry (Hints.HintsReferences c, b)) let set_typeclass_transparency_com ~locality refs b = let refs = List.map (fun x -> Tacred.evaluable_of_global_reference (Global.env ()) (Smartlocate.global_with_alias x)) refs in set_typeclass_transparency ~locality refs b let set_typeclass_mode ?(typeclasses_db=typeclasses_db) ~locality c b = let () = check_typeclasses_db () in Hints.add_hints ~locality [typeclasses_db] (Hints.HintsModeEntry (c, b)) let add_instance_hint ?(typeclasses_db=typeclasses_db) gr ~locality info = let () = check_typeclasses_db () in Flags.silently (fun () -> Hints.add_hints ~locality [typeclasses_db] (Hints.HintsResolveEntry [info, false, gr])) () (* short names without opening all Hints *) type locality = Hints.hint_locality = Local | Export | SuperGlobal type instance = { class_name : GlobRef.t; instance : GlobRef.t; info : Typeclasses.hint_info; (* Sections where the instance should be redeclared, None for discard, Some 0 for none. *) locality : Hints.hint_locality; } let add_instance_base inst = let locality = (* in a section, declare the hint as local since cache_instance will call add_instance_hint again; don't ask hints to take discharge into account itself *) if Global.sections_are_opened () then Local else inst.locality in add_instance_hint inst.instance ~locality inst.info (* * instances persistent object *) let perform_instance i = let i = { is_class = i.class_name; is_info = i.info; is_impl = i.instance } in Typeclasses.load_instance (Global.env ()) i let cache_instance inst = perform_instance inst; add_instance_base inst let load_instance _ inst = match inst.locality with | Local -> assert false | SuperGlobal -> perform_instance inst | Export -> () let open_instance i inst = match inst.locality with | Local -> assert false | SuperGlobal -> () | Export -> if Int.equal i 1 then perform_instance inst let subst_instance (subst, inst) = { inst with class_name = fst (subst_global subst inst.class_name); instance = fst (subst_global subst inst.instance) } let discharge_instance inst = match inst.locality with | Local -> None | SuperGlobal | Export -> assert (not (isVarRef inst.instance)); Some inst let classify_instance inst = match inst.locality with | Local -> Dispose | SuperGlobal | Export -> Substitute let instance_input : instance -> obj = declare_object { (default_object "type classes instances state") with cache_function = cache_instance; load_function = load_instance; (* can't simple_open: crappy behaviour when superglobal *) open_function = filtered_open ~cat:Hints.hint_cat open_instance; classify_function = classify_instance; discharge_function = discharge_instance; subst_function = subst_instance } module Event = struct type t = | NewClass of typeclass | NewInstance of instance end type observer = string let observers = ref CString.Map.empty let active_observers = Summary.ref ~name:"active typeclass observers" [] let register_observer ~name ?(override=false) o = if not override && CString.Map.mem name !observers then CErrors.anomaly Pp.(str "Typeclass observer " ++ str name ++ str " already registered."); observers := CString.Map.add name o !observers; name let deactivate_observer name = active_observers := List.remove String.equal name !active_observers let activate_observer name = assert (CString.Map.mem name !observers); deactivate_observer name; active_observers := name :: !active_observers let observe event = List.iter (fun name -> (CString.Map.get name !observers) event) !active_observers let add_instance cl info global impl = let () = match global with | Local -> () | SuperGlobal -> if Lib.sections_are_opened () && isVarRef impl then CErrors.user_err (Pp.str "Cannot set Global an instance referring to a section variable.") | Export -> if Lib.sections_are_opened () && isVarRef impl then CErrors.user_err (Pp.str "The export attribute cannot be applied to an instance referring to a section variable.") in let i = { class_name = cl.cl_impl; info = info ; locality = global ; instance = impl; } in Lib.add_leaf (instance_input i); observe (Event.NewInstance { class_name = cl.cl_impl; instance = impl; info; locality = global }) let warning_not_a_class = CWarnings.create ~name:"not-a-class" (fun (n, ty) -> let env = Global.env () in let evd = Evd.from_env env in Pp.(str "Ignored instance declaration for β€œ" ++ Nametab.pr_global_env Id.Set.empty n ++ str "”: β€œ" ++ Termops.Internal.print_constr_env env evd (EConstr.of_constr ty) ++ str "” is not a class") ) let declare_instance ?(warn = false) env sigma info local glob = let ty, _ = Typeops.type_of_global_in_context env glob in let info = Option.default {hint_priority = None; hint_pattern = None} info in match class_of_constr env sigma (EConstr.of_constr ty) with | Some (rels, ((tc,_), args) as _cl) -> add_instance tc info local glob | None -> if warn then warning_not_a_class (glob, ty) (* * classes persistent object *) let cache_class c = load_class (Global.env ()) c let subst_class (subst,cl) = let do_subst_con c = Mod_subst.subst_constant subst c and do_subst c = Mod_subst.subst_mps subst c and do_subst_gr gr = fst (subst_global subst gr) in let do_subst_ctx = List.Smart.map (RelDecl.map_constr do_subst) in let do_subst_meth m = let c = Option.Smart.map do_subst_con m.meth_const in if c == m.meth_const then m else { meth_name = m.meth_name; meth_const = c; } in let do_subst_projs projs = List.Smart.map do_subst_meth projs in { cl_univs = cl.cl_univs; cl_impl = do_subst_gr cl.cl_impl; cl_context = do_subst_ctx cl.cl_context; cl_trivial = cl.cl_trivial; cl_props = do_subst_ctx cl.cl_props; cl_projs = do_subst_projs cl.cl_projs; cl_strict = cl.cl_strict; cl_unique = cl.cl_unique } let discharge_class cl = try let info = Global.section_segment_of_reference cl.cl_impl in let info, _, cl_univs' = Cooking.lift_poly_univs info cl.cl_univs in let nprops = List.length cl.cl_props in let props, context = List.chop nprops (Discharge.cook_rel_context info (cl.cl_props @ cl.cl_context)) in let discharge_proj x = x in { cl_univs = cl_univs'; cl_impl = cl.cl_impl; cl_context = context; cl_trivial = cl.cl_trivial; cl_props = props; cl_projs = List.Smart.map discharge_proj cl.cl_projs; cl_strict = cl.cl_strict; cl_unique = cl.cl_unique } with Not_found -> (* not defined in the current section *) cl let class_input : typeclass -> obj = declare_object { (default_object "type classes state") with cache_function = cache_class; load_function = (fun _ -> cache_class); classify_function = (fun x -> Substitute); discharge_function = (fun a -> Some (discharge_class a)); subst_function = subst_class; } let add_class cl = Lib.add_leaf (class_input cl); observe (Event.NewClass cl) let intern_info {hint_priority;hint_pattern} = let env = Global.env() in let sigma = Evd.from_env env in let hint_pattern = Option.map (Constrintern.interp_constr_pattern env sigma) hint_pattern in {hint_priority;hint_pattern} (** TODO: add subinstances *) let existing_instance ?loc glob c info = let info = Option.default Hints.empty_hint_info info in let info = intern_info info in let env = Global.env() in let sigma = Evd.from_env env in let instance, _ = Typeops.type_of_global_in_context env c in let ctx, r = Term.decompose_prod_decls instance in match class_of_constr (Environ.push_rel_context ctx env) sigma (EConstr.of_constr r) with | Some (_, ((tc,u), _)) -> add_instance tc info glob c | None -> user_err ?loc (Pp.str "Constant does not build instances of a declared type class.") type typeclass_in_univs = { clu_impl : GlobRef.t; clu_univs : EInstance.t; clu_context : EConstr.rel_context; clu_trivial : bool; clu_isstruct : Structures.Structure.t option; clu_props : EConstr.rel_context; clu_projs : class_method list; } (* Declare everything in the parameters as implicit, and the class instance as well *) let type_ctx_instance ~program_mode env sigma ctx inst subst = let open Vars in let rec aux (sigma, subst) l ctx = match ctx, l with | LocalAssum _ :: _, [] | [], _ :: _ -> assert false | LocalAssum (_,t) :: ctx, c :: l -> let t' = substl subst t in let (sigma, c') = interp_casted_constr_evars ~program_mode env sigma c t' in aux (sigma, c' :: subst) l ctx | LocalDef (_,b,_) :: ctx, l -> let c' = substl subst b in aux (sigma, c' :: subst) l ctx | [], [] -> sigma, subst in aux (sigma, subst) inst (List.rev ctx) let instance_hook info global ?hook cst = let info = intern_info info in let env = Global.env () in let sigma = Evd.from_env env in declare_instance env sigma (Some info) global cst; (match hook with Some h -> h cst | None -> ()) let declare_instance_constant iinfo global impargs ?hook (name:lident) udecl poly sigma term termtype = let kind = Decls.(IsDefinition Instance) in let cinfo = Declare.CInfo.make ?loc:name.loc ~name:name.v ~impargs ~typ:(Some termtype) () in let info = Declare.Info.make ~kind ~poly ~udecl () in let kn = Declare.declare_definition ~cinfo ~info ~opaque:false ~body:term sigma in instance_hook iinfo global ?hook kn let instance_type cl args = let lenpars = List.count is_local_assum cl.clu_context in let pars = List.firstn lenpars args in applist (mkRef (cl.clu_impl,cl.clu_univs), pars) let do_declare_instance sigma ~locality ~poly k ctx ctx' pri udecl impargs subst (name:lident) = let subst = List.fold_left2 (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst') [] subst k.clu_context in let ty_constr = instance_type k subst in let termtype = it_mkProd_or_LetIn ty_constr (ctx' @ ctx) in let sigma, entry = Declare.prepare_parameter ~poly sigma ~udecl ~types:termtype in let cst = Declare.declare_constant ?loc:name.loc ~name:name.v ~kind:Decls.(IsAssumption Logical) (Declare.ParameterEntry entry) in let cst = (GlobRef.ConstRef cst) in Impargs.maybe_declare_manual_implicits false cst impargs; instance_hook pri locality cst let declare_instance_program pm env sigma ~locality ~poly {CAst.v=name;loc} pri impargs udecl term termtype = let hook { Declare.Hook.S.scope; dref; _ } = let cst = match dref with GlobRef.ConstRef kn -> kn | _ -> assert false in let pri = intern_info pri in let env = Global.env () in let sigma = Evd.from_env env in declare_instance env sigma (Some pri) locality (GlobRef.ConstRef cst) in let obls, _, body, typ = RetrieveObl.retrieve_obligations env name sigma 0 term termtype in let hook = Declare.Hook.make hook in let uctx = Evd.ustate sigma in let kind = Decls.IsDefinition Decls.Instance in let cinfo = Declare.CInfo.make ?loc ~name ~typ ~impargs () in let info = Declare.Info.make ~udecl ~poly ~kind ~hook () in Declare.Obls.add_definition ~pm ~info ~cinfo ~opaque:false ~uctx ~body obls let declare_instance_open sigma ?hook ~tac ~locality ~poly (id:lident) pri impargs udecl ids term termtype = (* spiwack: it is hard to reorder the actions to do the pretyping after the proof has opened. As a consequence, we use the low-level primitives to code the refinement manually.*) let future_goals, sigma = Evd.pop_future_goals sigma in let gls = List.rev (Evd.FutureGoals.comb future_goals) in let sigma = Evd.push_future_goals sigma in let kind = Decls.(IsDefinition Instance) in let hook = Declare.Hook.(make (fun { S.dref ; _ } -> instance_hook pri locality ?hook dref)) in let info = Declare.Info.make ~hook ~kind ~udecl ~poly () in (* XXX: We need to normalize the type, otherwise Admitted / Qed will fails! This is due to a bug in proof_global :( *) let termtype = Evarutil.nf_evar sigma termtype in let cinfo = Declare.CInfo.make ?loc:id.loc ~name:id.v ~impargs ~typ:termtype () in let lemma = Declare.Proof.start ~cinfo ~info sigma in (* spiwack: I don't know what to do with the status here. *) let lemma = match term with | Some term -> let init_refine = Tacticals.tclTHENLIST [ Refine.refine ~typecheck:false (fun sigma -> sigma, term); Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls); Tactics.reduce_after_refine; ] in let lemma, _ = Declare.Proof.by (Global.env ()) init_refine lemma in lemma | None -> let lemma, _ = Declare.Proof.by (Global.env ()) (Tactics.auto_intros_tac ids) lemma in lemma in match tac with | Some tac -> let lemma, _ = Declare.Proof.by (Global.env ()) tac lemma in lemma | None -> lemma let instance_constructor cl args = match cl.clu_isstruct with | Some s -> applist (mkConstructUi ((s.name,cl.clu_univs), 1), args) | None -> List.last args let do_instance_subst_constructor_and_ty subst k ctx = let subst = List.fold_left2 (fun subst' s decl -> if is_local_assum decl then s :: subst' else subst') [] subst (k.clu_props @ k.clu_context) in let ty_constr = instance_type k subst in let app = instance_constructor k subst in let termtype = it_mkProd_or_LetIn ty_constr ctx in let term = it_mkLambda_or_LetIn app ctx in term, termtype let do_instance_resolve_TC ~poly termtype sigma env = let sigma = Evarutil.nf_evar_map sigma in let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.no_goals_or_obligations ~fail:true env sigma in (* Try resolving fields that are typeclasses automatically. *) let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.all_evars ~fail:false env sigma in let sigma = Evarutil.nf_evar_map_undefined sigma in (* Beware of this step, it is required as to minimize universes. *) let sigma = Evd.minimize_universes sigma in (* Check that the type is free of evars now. *) Pretyping.check_evars env sigma termtype; termtype, sigma let do_instance_type_ctx_instance props k env' ctx' sigma ~program_mode subst = let get_id qid = CAst.make ?loc:qid.CAst.loc @@ qualid_basename qid in let props, rest = List.fold_left (fun (props, rest) decl -> if is_local_assum decl then try let is_id (id', _) = match RelDecl.get_name decl, get_id id' with | Name id, {CAst.v=id'} -> Id.equal id id' | Anonymous, _ -> false in let (loc_mid, c) = List.find is_id rest in let rest' = List.filter (fun v -> not (is_id v)) rest in let {CAst.loc;v=mid} = get_id loc_mid in let opt_proj = List.find_opt (fun m -> Name.equal m.meth_name (Name mid)) k.clu_projs in opt_proj |> Option.iter (fun x -> x.meth_const |> Option.iter (fun x -> Dumpglob.add_glob ?loc (GlobRef.ConstRef x))); c :: props, rest' with Not_found -> ((CAst.make @@ CHole (None)) :: props), rest else props, rest) ([], props) k.clu_props in match rest with | (n, _) :: _ -> unbound_method env' sigma k.clu_impl (get_id n) | [] -> let sigma, res = type_ctx_instance ~program_mode (push_rel_context ctx' env') sigma k.clu_props props subst in res, sigma let interp_props ~program_mode env' cty k ctx ctx' subst sigma = function | (true, { CAst.v = CRecord fs; loc }) -> check_duplicate ?loc fs; let subst, sigma = do_instance_type_ctx_instance fs k env' ctx' sigma ~program_mode subst in let term, termtype = do_instance_subst_constructor_and_ty subst k (ctx' @ ctx) in term, termtype, sigma | (_, term) -> let sigma, def = interp_casted_constr_evars ~program_mode env' sigma term cty in let termtype = it_mkProd_or_LetIn cty ctx in let term = it_mkLambda_or_LetIn def ctx in term, termtype, sigma let do_instance_interactive env env' sigma ?hook ~tac ~locality ~poly cty k ctx ctx' pri decl imps subst id opt_props = let term, termtype, sigma = match opt_props with | Some props -> on_pi1 (fun x -> Some x) (interp_props ~program_mode:false env' cty k ctx ctx' subst sigma props) | None -> let term, termtype = if k.clu_trivial then let term, termtype = do_instance_subst_constructor_and_ty subst k (ctx' @ ctx) in Some term, termtype else None, it_mkProd_or_LetIn cty ctx in let termtype, sigma = do_instance_resolve_TC ~poly termtype sigma env in term, termtype, sigma in Flags.silently (fun () -> declare_instance_open sigma ?hook ~tac ~locality ~poly id pri imps decl (List.map RelDecl.get_name ctx) term termtype) () let do_instance env env' sigma ?hook ~locality ~poly cty k ctx ctx' pri decl imps subst id props = let term, termtype, sigma = interp_props ~program_mode:false env' cty k ctx ctx' subst sigma props in let termtype, sigma = do_instance_resolve_TC ~poly termtype sigma env in Pretyping.check_evars_are_solved ~program_mode:false env sigma; declare_instance_constant pri locality imps ?hook id decl poly sigma term termtype let do_instance_program ~pm env env' sigma ?hook ~locality ~poly cty k ctx ctx' pri decl imps subst id opt_props = let term, termtype, sigma = match opt_props with | Some props -> interp_props ~program_mode:true env' cty k ctx ctx' subst sigma props | None -> let subst, sigma = do_instance_type_ctx_instance [] k env' ctx' sigma ~program_mode:true subst in let term, termtype = do_instance_subst_constructor_and_ty subst k (ctx' @ ctx) in term, termtype, sigma in let termtype, sigma = do_instance_resolve_TC ~poly termtype sigma env in if not (Evd.has_undefined sigma) && not (Option.is_empty opt_props) then let () = declare_instance_constant pri locality imps ?hook id decl poly sigma term termtype in pm else declare_instance_program pm env sigma ~locality ~poly id pri imps decl term termtype let typeclass_univ_instance env (cl, u) = assert (UVars.eq_sizes (UVars.AbstractContext.size cl.cl_univs) (EInstance.length u)); let subst_ctx c = Context.Rel.map (Vars.subst_instance_constr u) (EConstr.of_rel_context c) in let clu_isstruct = match cl.cl_impl with | ConstRef _ -> None | ConstructRef _ | VarRef _ -> assert false | IndRef ind -> match Structures.Structure.find env ind with | exception Not_found -> None | s -> Some s in { clu_impl = cl.cl_impl; clu_univs = u; clu_context = subst_ctx cl.cl_context; clu_props = subst_ctx cl.cl_props; clu_isstruct; clu_trivial = cl.cl_trivial; clu_projs = cl.cl_projs; } let interp_instance_context ~program_mode ~poly env ctx pl tclass = let sigma, decl = interp_univ_decl_opt env pl in let sigma, (impls, ((env', ctx), imps, _locs)) = interp_context_evars ~program_mode ~poly env sigma ctx in let flags = Pretyping.{ all_no_fail_flags with program_mode ; poly } in let sigma, (c', imps') = interp_type_evars_impls ~flags ~impls env' sigma tclass in let imps = imps @ imps' in let ctx', c = decompose_prod_decls sigma c' in let ctx'' = ctx' @ ctx in let (k, u), args = Typeclasses.dest_class_app (push_rel_context ctx'' env) sigma c in let cl = typeclass_univ_instance env (k, u) in let args = List.map of_constr args in let _, args = List.fold_right (fun decl (args, args') -> match decl with | LocalAssum _ -> (List.tl args, List.hd args :: args') | LocalDef (_,b,_) -> (args, Vars.substl args' b :: args')) cl.clu_context (args, []) in let sigma = Evarutil.nf_evar_map sigma in let sigma = resolve_typeclasses ~filter:Typeclasses.all_evars ~fail:true env sigma in sigma, cl, u, c', ctx', ctx, imps, args, decl let id_of_class env ref = let open GlobRef in match ref with | ConstRef kn -> Constant.label kn | IndRef (kn,i) -> let mip = (Environ.lookup_mind kn env).Declarations.mind_packets in mip.(0).Declarations.mind_typename | _ -> assert false let new_instance_common ~program_mode ~poly env instid ctx cl = let (instid, pl) = instid in let sigma, k, u, cty, ctx', ctx, imps, subst, decl = interp_instance_context ~program_mode ~poly env ctx pl cl in (* The name generator should not be here *) let id = instid |> CAst.map (function | Name id -> id | Anonymous -> let i = Nameops.add_suffix (id_of_class env k.clu_impl) "_instance_0" in Namegen.next_global_ident_away (Global.safe_env ()) i (Termops.vars_of_env env)) in let env' = push_rel_context ctx env in id, env', sigma, k, u, cty, ctx', ctx, imps, subst, decl let new_instance_interactive ~locality ~poly instid ctx cl ?(tac:unit Proofview.tactic option) ?hook pri opt_props = let env = Global.env() in let id, env', sigma, k, u, cty, ctx', ctx, imps, subst, decl = new_instance_common ~program_mode:false ~poly env instid ctx cl in id, do_instance_interactive env env' sigma ?hook ~tac ~locality ~poly cty k ctx ctx' pri decl imps subst id opt_props let new_instance_program ~locality ~pm ~poly instid ctx cl opt_props ?hook pri = let env = Global.env() in let id, env', sigma, k, u, cty, ctx', ctx, imps, subst, decl = new_instance_common ~program_mode:true ~poly env instid ctx cl in let pm = do_instance_program ~pm env env' sigma ?hook ~locality ~poly cty k ctx ctx' pri decl imps subst id opt_props in pm, id let new_instance ~locality ~poly instid ctx cl props ?hook pri = let env = Global.env() in let id, env', sigma, k, u, cty, ctx', ctx, imps, subst, decl = new_instance_common ~program_mode:false ~poly env instid ctx cl in do_instance env env' sigma ?hook ~locality ~poly cty k ctx ctx' pri decl imps subst id props; id let declare_new_instance ~locality ~program_mode ~poly instid ctx cl pri = let env = Global.env() in let (instid, pl) = instid in let sigma, k, u, cty, ctx', ctx, imps, subst, decl = interp_instance_context ~program_mode ~poly env ctx pl cl in do_declare_instance sigma ~locality ~poly k ctx ctx' pri decl imps subst instid let refine_att = let open Attributes in let open Notations in attribute_of_list ["refine",single_key_parser ~name:"refine" ~key:"refine" ()] >>= function | None -> return false | Some () -> return true module Internal = struct let add_instance = add_instance end rocq-9.2.0/vernac/classes.mli000066400000000000000000000077031516144147600161240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* env -> Evd.evar_map -> hint_info option -> Hints.hint_locality -> GlobRef.t -> unit (** Declares the given global reference as an instance of its type. Does nothing β€” or emit a β€œnot-a-class” warning if the [warn] argument is set β€” when said type is not a registered type class. *) val existing_instance : ?loc:Loc.t -> Hints.hint_locality -> GlobRef.t -> Vernacexpr.hint_info_expr option -> unit (** globality, reference, optional priority and pattern information *) val new_instance_interactive : locality:Hints.hint_locality -> poly:PolyFlags.t -> name_decl -> local_binder_expr list -> constr_expr -> ?tac:unit Proofview.tactic -> ?hook:(GlobRef.t -> unit) -> Vernacexpr.hint_info_expr -> (bool * constr_expr) option -> lident * Declare.Proof.t val new_instance : locality:Hints.hint_locality -> poly:PolyFlags.t -> name_decl -> local_binder_expr list -> constr_expr -> (bool * constr_expr) -> ?hook:(GlobRef.t -> unit) -> Vernacexpr.hint_info_expr -> lident val new_instance_program : locality:Hints.hint_locality -> pm:Declare.OblState.t -> poly:PolyFlags.t -> name_decl -> local_binder_expr list -> constr_expr -> (bool * constr_expr) option -> ?hook:(GlobRef.t -> unit) -> Vernacexpr.hint_info_expr -> Declare.OblState.t * lident val declare_new_instance : locality:Hints.hint_locality -> program_mode:bool -> poly:PolyFlags.t -> ident_decl -> local_binder_expr list -> constr_expr -> Vernacexpr.hint_info_expr -> unit val add_class : typeclass -> unit type instance = { class_name : GlobRef.t; instance : GlobRef.t; info : Typeclasses.hint_info; locality : Hints.hint_locality; } module Event : sig type t = | NewClass of typeclass | NewInstance of instance end (** Activated observers are called whenever a class or an instance are declared. [register_observer] is to be called once per process for a given string, unless [override] is [true]. The registered observer is not activated. Activation state is part of the summary. It is up to the caller to use libobject for persistence if desired. *) type observer val register_observer : name:string -> ?override:bool -> (Event.t -> unit) -> observer val activate_observer : observer -> unit val deactivate_observer : observer -> unit (** Setting opacity *) val set_typeclass_transparency : ?typeclasses_db:Hints.hint_db_name -> locality:Hints.hint_locality -> Evaluable.t list -> bool -> unit val set_typeclass_transparency_com : locality:Hints.hint_locality -> Libnames.qualid list -> bool -> unit val set_typeclass_mode : ?typeclasses_db:string -> locality:Hints.hint_locality -> GlobRef.t -> Hints.hint_mode list -> unit (** For generation on names based on classes only *) val refine_att : bool Attributes.attribute (** {6 Low level interface used by Add Morphism, do not use } *) module Internal : sig val add_instance : typeclass -> hint_info -> Hints.hint_locality -> GlobRef.t -> unit end (** A configurable warning to output if a default mode is used for a class declaration. *) val warn_default_mode : ?loc:Loc.t -> (GlobRef.t * Hints.hint_mode list) -> unit rocq-9.2.0/vernac/comArguments.ml000066400000000000000000000313111516144147600167520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pretyping.clear_bidirectionality_hint (Global.env ()) gr | Some nargs -> Pretyping.add_bidirectionality_hint (Global.env ()) gr nargs let load_bidi_hints _ r = cache_bidi_hints r let subst_bidi_hints (subst, (gr, ohint as orig)) = let gr' = Globnames.subst_global_reference subst gr in if gr == gr' then orig else (gr', ohint) let discharge_bidi_hints (gr, ohint) = if Globnames.isVarRef gr && Global.is_in_section gr then None else let vars = Global.section_instance gr in let n = Array.length vars in Some (gr, Option.map ((+) n) ohint) let inBidiHints = let open Libobject in declare_object { (default_object "BIDIRECTIONALITY-HINTS" ) with load_function = load_bidi_hints; cache_function = cache_bidi_hints; classify_function = (fun o -> Substitute); subst_function = subst_bidi_hints; discharge_function = discharge_bidi_hints; } let warn_arguments_assert = CWarnings.create ~name:"arguments-assert" ~category:CWarnings.CoreCategories.vernacular Pp.(fun sr -> strbrk "This command is just asserting the names of arguments of " ++ Printer.pr_global sr ++ strbrk". If this is what you want, add " ++ strbrk "': assert' to silence the warning. If you want " ++ strbrk "to clear implicit arguments, add ': clear implicits'. " ++ strbrk "If you want to clear notation scopes, add ': clear scopes'") let warn_scope_delimiter_depth = CWarnings.create ~name:"argument-scope-delimiter" ~category:Deprecation.Version.v8_19 Pp.(fun () -> strbrk "The '%' scope delimiter in 'Arguments' commands is deprecated, " ++ strbrk "use '%_' instead (available since 8.19). The '%' syntax will be " ++ strbrk "reused in a future version with the same semantics as in terms, " ++ strbrk "that is adding scope to the stack for all subterms. " ++ strbrk "Code can be adapted with a script like: " ++ strbrk "for f in $(find . -name '*.v'); do sed '/Arguments/ s/%/%_/g' -i $f ; done") (* [nargs_for_red] is the number of arguments required to trigger reduction, [args] is the main list of arguments statuses, [more_implicits] is a list of extra lists of implicit statuses *) let vernac_arguments ~section_local reference args more_implicits flags = let env = Global.env () in let sigma = Evd.from_env env in let assert_flag = List.mem `Assert flags in let rename_flag = List.mem `Rename flags in let clear_scopes_flag = List.mem `ClearScopes flags in let extra_scopes_flag = List.mem `ExtraScopes flags in let clear_implicits_flag = List.mem `ClearImplicits flags in let default_implicits_flag = List.mem `DefaultImplicits flags in let never_unfold_flag = List.mem `SimplNeverUnfold flags in let nomatch_flag = List.mem `SimplDontExposeCase flags in let clear_red_flag = List.mem `ClearReduction flags in let clear_bidi_hint = List.mem `ClearBidiHint flags in let err_incompat x y = CErrors.user_err Pp.(str ("Options \""^x^"\" and \""^y^"\" are incompatible.")) in if assert_flag && rename_flag then err_incompat "assert" "rename"; if clear_scopes_flag && extra_scopes_flag then err_incompat "clear scopes" "extra scopes"; if clear_implicits_flag && default_implicits_flag then err_incompat "clear implicits" "default implicits"; let args, nargs_for_red, nargs_before_bidi, _i = List.fold_left (fun (args,red,bidi,i) arg -> match arg with | RealArg arg -> (arg::args,red,bidi,i+1) | VolatileArg -> if Option.has_some red then CErrors.user_err Pp.(str "The \"/\" modifier may only occur once."); (args,Some i,bidi,i) | BidiArg -> if Option.has_some bidi then CErrors.user_err Pp.(str "The \"&\" modifier may only occur once."); (args,red,Some i,i)) ([],None,None,0) args in let args = List.rev args in let sr = smart_global reference in let inf_names = let ty, _ = Typeops.type_of_global_in_context env sr in List.map pi1 (Impargs.compute_implicits_names env sigma (EConstr.of_constr ty)) in let prev_names = try Arguments_renaming.arguments_names env sr with Not_found -> inf_names in let num_args = List.length inf_names in assert (Int.equal num_args (List.length prev_names)); let names_of args = List.map (fun a -> a.name) args in (* Checks *) let err_extra_args names = CErrors.user_err Pp.(strbrk "Extra arguments: " ++ prlist_with_sep pr_comma Name.print names ++ str ".") in let err_missing_args names = CErrors.user_err Pp.(strbrk "The following arguments are not declared: " ++ prlist_with_sep pr_comma Name.print names ++ str ".") in let rec check_extra_args extra_args = match extra_args with | [] -> () | { notation_scope = [] } :: _ -> CErrors.user_err Pp.(str"Extra arguments should specify scopes.") | { notation_scope = _ :: _ } :: args -> check_extra_args args in let args, scopes = let scopes = List.map (fun { notation_scope = s } -> s) args in if List.length args > num_args then let args, extra_args = List.chop num_args args in if extra_scopes_flag then (check_extra_args extra_args; (args, scopes)) else err_extra_args (names_of extra_args) else args, scopes in if Option.cata (fun n -> n > num_args) false nargs_for_red then CErrors.user_err Pp.(str "The \"/\" modifier should be put before any extra scope."); if Option.cata (fun n -> n > num_args) false nargs_before_bidi then CErrors.user_err Pp.(str "The \"&\" modifier should be put before any extra scope."); let scopes_specified = List.exists ((<>) []) scopes in if scopes_specified && clear_scopes_flag then CErrors.user_err Pp.(str "The \"clear scopes\" flag is incompatible with scope annotations."); let names = List.map (fun { name } -> name) args in let names = names :: List.map (List.map fst) more_implicits in let rename_flag_required = ref false in let example_renaming = ref None in let save_example_renaming renaming = rename_flag_required := !rename_flag_required || not (Name.equal (fst renaming) Anonymous); if Option.is_empty !example_renaming then example_renaming := Some renaming in let rec names_union names1 names2 = match names1, names2 with | [], [] -> [] | _ :: _, [] -> names1 | [], _ :: _ -> names2 | (Name _ as name) :: names1, Anonymous :: names2 | Anonymous :: names1, (Name _ as name) :: names2 -> name :: names_union names1 names2 | name1 :: names1, name2 :: names2 -> if Name.equal name1 name2 then name1 :: names_union names1 names2 else CErrors.user_err Pp.(str "Argument lists should agree on the names they provide.") in let names = List.fold_left names_union [] names in let rec rename prev_names names = match prev_names, names with | [], [] -> [] | [], _ :: _ -> err_extra_args names | _ :: _, [] when assert_flag -> (* Error messages are expressed in terms of original names, not renamed ones. *) err_missing_args (List.lastn (List.length prev_names) inf_names) | _ :: _, [] -> prev_names | prev :: prev_names, Anonymous :: names -> prev :: rename prev_names names | prev :: prev_names, (Name id as name) :: names -> if not (Name.equal prev name) then save_example_renaming (prev,name); name :: rename prev_names names in let names = rename prev_names names in let renaming_specified = Option.has_some !example_renaming in if !rename_flag_required && not rename_flag then begin let msg = let open Pp in match !example_renaming with | None -> strbrk "To rename arguments the \"rename\" flag must be specified." | Some (o,n) -> strbrk "Flag \"rename\" expected to rename " ++ Name.print o ++ strbrk " into " ++ Name.print n ++ str "." in CErrors.user_err msg end; let implicits = List.map (fun { name; implicit_status = i } -> (name,i)) args in let implicits = implicits :: more_implicits in let implicits_specified = match implicits with | [l] -> List.exists (function _, Glob_term.Explicit -> false | _ -> true) l | _ -> true in if implicits_specified && clear_implicits_flag then CErrors.user_err Pp.(str "The \"clear implicits\" flag must be omitted if implicit annotations are given."); if implicits_specified && default_implicits_flag then CErrors.user_err Pp.(str "The \"default implicits\" flag is incompatible with implicit annotations."); let rargs = Util.List.map_filter (function (n, true) -> Some n | _ -> None) (Util.List.map_i (fun i { recarg_like = b } -> i, b) 0 args) in let red_behavior = let open Reductionops.ReductionBehaviour in match clear_red_flag, never_unfold_flag, nomatch_flag, rargs, nargs_for_red with | true, true, _, _, _ -> err_incompat "clear simpl" "simpl never" | true, false, true, _, _ -> err_incompat "clear simpl" "simpl nomatch" | true, false, false, _ :: _, _ -> err_incompat "clear simpl" "!" | true, false, false, [], Some _ -> err_incompat "clear simpl" "/" | false, true, false, [], None -> Some NeverUnfold | false, true, true, _, _ -> err_incompat "simpl never" "simpl nomatch" | false, true, _, _::_, _ -> err_incompat "simpl never" "!" | false, true, _, _, Some _ -> err_incompat "simpl never" "/" | _, false, false, [], None -> None | false, false, false, _, _ -> Some (UnfoldWhen { nargs = nargs_for_red; recargs = rargs; }) | false, false, true, _, _ -> Some (UnfoldWhenNoMatch { nargs = nargs_for_red; recargs = rargs; }) in let red_modifiers_specified = Option.has_some red_behavior in let bidi_hint_specified = Option.has_some nargs_before_bidi in if bidi_hint_specified && clear_bidi_hint then err_incompat "clear bidirectionality hint" "&"; (* Actions *) if renaming_specified then begin Arguments_renaming.rename_arguments section_local sr names end; if scopes_specified || clear_scopes_flag then begin if List.exists (fun {v=d,_} -> d = Constrexpr.DelimUnboundedScope) (List.flatten scopes) then warn_scope_delimiter_depth (); let scopes = List.map (List.map (fun {loc;v=_d,k} -> try ignore (Notation.find_scope k); k with CErrors.UserError _ -> Notation.find_delimiters_scope ?loc k)) scopes in Notation.declare_arguments_scope section_local (smart_global reference) scopes end; if implicits_specified || clear_implicits_flag then Impargs.set_implicits section_local (smart_global reference) implicits; if default_implicits_flag then Impargs.declare_implicits section_local (smart_global reference); if red_modifiers_specified || clear_red_flag then begin match sr with | GlobRef.ConstRef c -> Reductionops.ReductionBehaviour.set ~local:section_local c red_behavior | _ -> CErrors.user_err Pp.(strbrk "Modifiers of the behavior of the simpl tactic "++ strbrk "are relevant for constants only.") end; if bidi_hint_specified then begin let n = Option.get nargs_before_bidi in if section_local then Pretyping.add_bidirectionality_hint env sr n else Lib.add_leaf (inBidiHints (sr, Some n)) end; if clear_bidi_hint then begin if section_local then Pretyping.clear_bidirectionality_hint env sr else Lib.add_leaf (inBidiHints (sr, None)) end; if not (renaming_specified || implicits_specified || scopes_specified || red_modifiers_specified || bidi_hint_specified) && (List.is_empty flags) then warn_arguments_assert sr rocq-9.2.0/vernac/comArguments.mli000066400000000000000000000016241516144147600171270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Libnames.qualid Constrexpr.or_by_notation -> Vernacexpr.vernac_argument_status list -> (Names.Name.t * Glob_term.binding_kind) list list -> Vernacexpr.arguments_modifier list -> unit rocq-9.2.0/vernac/comAssumption.ml000066400000000000000000000313431516144147600171540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Declare.SectionLocalAssum {typ; impl; univs} | Some b -> Declare.SectionLocalDef {clearbody = (* TODO *) false; entry = Declare.definition_entry ~univs ~types:typ b} in let () = Declare.declare_variable ~name ~kind ~typing_flags:None decl in let () = if body = None then Declare.assumption_message name else Declare.definition_message name in let r = GlobRef.VarRef name in let () = maybe_declare_manual_implicits true r impargs in let _ = if try_assum_as_instance && Option.is_empty body then let env = Global.env () in let sigma = Evd.from_env env in Classes.declare_instance env sigma None Hints.Local r in let () = if coe = Vernacexpr.AddCoercion then ComCoercion.try_add_new_coercion r ~local:true ~reversible:false in (r, UVars.Instance.empty) let declare_variable ~coe ~kind ~univs ~impargs ~impl ~name typ = declare_local ~coe ~try_assum_as_instance:true ~kind:(Decls.IsAssumption kind) ~univs ~impargs ~impl ~name None typ let instance_of_univ_entry = function | UState.Polymorphic_entry univs -> UVars.UContext.instance univs | UState.Monomorphic_entry _ -> UVars.Instance.empty (** Declares a global axiom/parameter, possibly declaring it: - as a coercion - as a type class instance - with implicit arguments - with inlining for functor application - with named universes *) let declare_global ~coe ~try_assum_as_instance ~local ~kind ?user_warns ~univs ~impargs ~inline ~name:{CAst.v=name; loc} body typ = let (uentry, ubinders) = univs in let inl = let open Declaremods in match inline with | NoInline -> None | DefaultInline -> Declaremods.default_inline_level() | InlineAt i -> Some i in let decl = match body with | None -> Declare.ParameterEntry (Declare.parameter_entry ~univs:(uentry, ubinders) ?inline:inl typ) | Some b -> Declare.DefinitionEntry (Declare.definition_entry ~univs ~types:typ b) in let kn = Declare.declare_constant ?loc ~name ~local ~kind ?user_warns decl in let gr = GlobRef.ConstRef kn in let () = maybe_declare_manual_implicits false gr impargs in let () = match body with None -> Declare.assumption_message name | Some _ -> Declare.definition_message name in let local = match local with | Locality.ImportNeedQualified -> true | Locality.ImportDefaultBehavior -> false in let () = if try_assum_as_instance && Option.is_empty body then (* why local when is_modtype? *) let env = Global.env () in let sigma = Evd.from_env env in Classes.declare_instance env sigma None Hints.SuperGlobal gr in let () = if coe = Vernacexpr.AddCoercion then ComCoercion.try_add_new_coercion gr ~local ~reversible:false in let inst = instance_of_univ_entry uentry in (gr,inst) let declare_axiom ~coe ~local ~kind ?user_warns ~univs ~impargs ~inline ~name typ = declare_global ~coe ~try_assum_as_instance:false ~local ~kind:(Decls.IsAssumption kind) ?user_warns ~univs ~impargs ~inline ~name None typ let interp_assumption ~program_mode ~poly env sigma impl_env bl c = let flags = { Pretyping.all_no_fail_flags with program_mode; poly } in let sigma, (impls, ((env_bl, ctx), impls1, _locs)) = interp_context_evars ~program_mode ~poly ~impl_env env sigma bl in let sigma, (ty, impls2) = interp_type_evars_impls ~flags env_bl sigma ~impls c in let ty = EConstr.it_mkProd_or_LetIn ty ctx in sigma, ty, impls1@impls2 let empty_poly_univ_entry = UState.Polymorphic_entry UVars.UContext.empty, UnivNames.empty_binders let empty_mono_univ_entry = UState.Monomorphic_entry Univ.ContextSet.empty, UnivNames.empty_binders let empty_univ_entry poly = if poly then empty_poly_univ_entry else empty_mono_univ_entry let clear_univs scope univ = match scope, univ with | Locality.Global _, (UState.Polymorphic_entry _, _ as univs) -> univs | _, (UState.Monomorphic_entry _, _) -> empty_univ_entry false | Locality.Discharge, (UState.Polymorphic_entry _, _) -> empty_univ_entry true let context_subst subst (id,b,t,infos) = id, Option.map (Vars.replace_vars subst) b, Vars.replace_vars subst t, infos let declare_context ~try_global_assum_as_instance ~scope ~univs ?user_warns ~inline ctx = let fn i subst d = let (name,b,t,(impl,kind,coe,impargs)) = context_subst subst d in let univs = if i = 0 then univs else clear_univs scope univs in let refu = match scope with | Locality.Discharge -> declare_local ~coe ~try_assum_as_instance:true ~kind ~univs ~impargs ~impl ~name:name.CAst.v b t | Locality.Global local -> declare_global ~coe ~try_assum_as_instance:try_global_assum_as_instance ~local ~kind ?user_warns ~univs ~impargs ~inline ~name b t in (name.v, Constr.mkRef refu) :: subst in let _ = List.fold_left_i fn 0 [] ctx in () let error_extra_universe_decl ?loc () = user_err ?loc Pp.(strbrk "When declaring multiple assumptions in one command, " ++ strbrk "only the first name is allowed to mention a universe binder " ++ strbrk "(which will be shared by the whole block).") let extract_assumption_names = function | ({CAst.loc;v=id}, Some _) -> error_extra_universe_decl ?loc () | (id, None) -> id let process_assumptions_udecls = function | (coe, ((id, udecl)::ids, c))::assums -> let ids = List.map extract_assumption_names ids in let assums = List.map (fun (coe, (idl, c)) -> (coe, (List.map extract_assumption_names idl, c))) assums in udecl, (coe,(id::ids,c))::assums | (_, ([], _))::_ | [] -> assert false let error_polymorphic_section_variable ?loc () = user_err ?loc (Pp.str "Section variables cannot be polymorphic.") let process_assumptions_no_udecls l = List.map (fun (coe, (ids, c)) -> (coe, (List.map (function | ({CAst.loc}, Some _) -> error_polymorphic_section_variable ?loc () | (id, None) -> id) ids, c))) l let extract_manual_implicit e = CAst.make (match e with | Some {impl_pos = (na,_,_); impl_expl = Manual; impl_max = max} -> Some (na,max) | Some {impl_expl = (DepFlexAndRigid _ | DepFlex _ | DepRigid _ )} | None -> None) let find_implicits id ienv = try let impls = implicits_of_decl_in_internalization_env id ienv in List.map extract_manual_implicit impls with Not_found -> [] let local_binders_of_decls ~poly l = let coercions, l = List.fold_left_map (fun coercions (is_coe,(idl,c)) -> let coercions = match is_coe with | Vernacexpr.NoCoercion -> coercions | Vernacexpr.AddCoercion -> List.fold_right (fun id -> Id.Set.add id.CAst.v) idl coercions in let make_name id = CAst.make ?loc:id.CAst.loc (Name id.CAst.v) in let make_assum idl = Constrexpr.(CLocalAssum (List.map make_name idl,None,Default Glob_term.Explicit,c)) in let decl = if PolyFlags.univ_poly poly then (* Separate declarations so that A B : Type puts A and B in different levels. *) List.map (fun id -> make_assum [id]) idl else [make_assum idl] in (coercions,decl)) Id.Set.empty l in coercions, List.flatten l let find_binding_kind id impls = let open Glob_term in let find x = match x.CAst.v with | Some (Name id',max) when Id.equal id id' -> Some (if max then MaxImplicit else NonMaxImplicit) | _ -> None in Option.default Explicit (CList.find_map find impls) let interp_context_gen ~program_mode ~poly ~kind ~autoimp_enable ~coercions env sigma l = let initial = sigma in let sigma, (ienv, ((env, ctx), impls, locs)) = interp_named_context_evars ~program_mode ~poly ~autoimp_enable env sigma l in (* Note, we must use the normalized evar from now on! *) let sigma = solve_remaining_evars all_and_fail_flags env ~initial sigma in let sigma, ctx = Evarutil.finalize sigma @@ fun nf -> List.map (NamedDecl.map_constr_het (fun x -> x) nf) ctx in (* reorder, evar-normalize and add implicit status *) let ctx = List.map2 (fun loc d -> let {binder_name=id}, b, t = NamedDecl.to_tuple d in let impl = find_binding_kind id impls in let kind = Decls.(if b = None then IsAssumption kind else IsDefinition (match kind with Context -> LetContext | _ -> Let)) in let is_coe = if Id.Set.mem id coercions then Vernacexpr.AddCoercion else Vernacexpr.NoCoercion in let impls = if autoimp_enable then find_implicits id ienv else [] in let data = (impl,kind,is_coe,impls) in (CAst.make ?loc id,b,t,data)) locs ctx in sigma, List.rev ctx let do_assumptions ~program_mode ~poly ~scope ~kind ?user_warns ~inline l = let sec = Lib.sections_are_opened () in if Dumpglob.dump () then begin List.iter (fun (_,(idl,_)) -> List.iter (fun (lid, _) -> let ty = if sec then "var" else "ax" in Dumpglob.dump_definition lid sec ty) idl) l end; let env = Global.env () in let udecl, l = match scope with | Locality.Global import_behavior -> process_assumptions_udecls l | Locality.Discharge -> None, process_assumptions_no_udecls l in let sigma, udecl = interp_univ_decl_opt env udecl in let coercions, ctx = local_binders_of_decls ~poly l in let sigma, ctx = interp_context_gen ~program_mode ~poly ~kind ~autoimp_enable:true ~coercions env sigma ctx in let univs = Evd.check_univ_decl ~poly sigma udecl in declare_context ~try_global_assum_as_instance:false ~scope ~univs ?user_warns ~inline ctx let warn_context_outside_section = CWarnings.create ~name:"context-outside-section" ~category:CWarnings.CoreCategories.vernacular ~default:CWarnings.AsError Pp.(fun () -> strbrk "Use of \"Context\" outside sections behaves \ as \"#[local] Parameter\" or \"#[local] \ Axiom\" followed by \"Existing Instance\" \ for typeclasses.") let do_context ~program_mode ~poly ctx = let sec = Lib.sections_are_opened () in if not sec then warn_context_outside_section (); if Dumpglob.dump () then begin let l = List.map (function | Constrexpr.CLocalAssum (l, _, _, _) -> let ty = if sec then "var "else "ax" in List.map (fun n -> ty, n) l | Constrexpr.CLocalDef (n, _, _, _) -> let ty = if sec then "var "else "def" in [ty, n] | Constrexpr.CLocalPattern _ -> []) ctx in List.iter (function | ty, {CAst.v = Names.Name.Anonymous; _} -> () | ty, {CAst.v = Names.Name.Name id; loc} -> Dumpglob.dump_definition (CAst.make ?loc id) sec ty) (List.flatten l) end; let env = Global.env() in let sigma = Evd.from_env env in let scope = let open Locality in if sec then Discharge else Global (if Lib.is_modtype () then ImportDefaultBehavior else ImportNeedQualified) in let sigma, ctx = interp_context_gen ~program_mode ~poly ~kind:Context ~autoimp_enable:false ~coercions:Id.Set.empty env sigma ctx in let univs = Evd.univ_entry ~poly sigma in (* No possibility to enforce variances here *) declare_context ~try_global_assum_as_instance:true ~scope ~univs ~inline:Declaremods.NoInline ctx (* API compatibility (used in Elpi) *) let interp_context env sigma ctx = let reverse_rel_context_of_reverse_named_context ctx = List.rev (snd (List.fold_left_i (fun n (subst, ctx) (id,b,t,impl) -> let decl = (id, Option.map (Vars.subst_vars subst) b, Vars.subst_vars subst t, impl) in (id :: subst, decl :: ctx)) 1 ([],[]) ctx)) in let poly = PolyFlags.default in (* FIXME: no poly/sort poly here *) let sigma, ctx = interp_context_gen ~program_mode:false ~poly ~kind:Context ~autoimp_enable:false ~coercions:Id.Set.empty env sigma ctx in let ctx = List.map (fun (id,b,t,(impl,_,_,_)) -> (id.CAst.v,b,t,impl)) ctx in sigma, reverse_rel_context_of_reverse_named_context ctx rocq-9.2.0/vernac/comAssumption.mli000066400000000000000000000071051516144147600173240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* kind:Decls.assumption_object_kind -> univs:UState.named_universes_entry -> impargs:Impargs.manual_implicits -> impl:Glob_term.binding_kind -> name:variable -> Constr.types -> GlobRef.t * UVars.Instance.t (** Declaration of a local construction (Variable/Hypothesis/Let) *) val declare_local : coe:coercion_flag -> try_assum_as_instance:bool (* true = declare a variable of type a class as an instance *) -> kind:Decls.logical_kind -> univs:UState.named_universes_entry -> impargs:Impargs.manual_implicits -> impl:Glob_term.binding_kind -> name:variable -> Constr.constr option -> Constr.types -> GlobRef.t * UVars.Instance.t (** Declaration of a global assumption (Axiom/Parameter) *) val declare_axiom : coe:coercion_flag -> local:Locality.import_status -> kind:Decls.assumption_object_kind -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> univs:UState.named_universes_entry -> impargs:Impargs.manual_implicits -> inline:Declaremods.inline -> name:lident -> Constr.types -> GlobRef.t * UVars.Instance.t (** Declaration of a global construction (Axiom/Parameter/Definition) *) val declare_global : coe:coercion_flag -> try_assum_as_instance:bool (* true = declare a parameter of type a class as an instance *) -> local:Locality.import_status -> kind:Decls.logical_kind -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> univs:UState.named_universes_entry -> impargs:Impargs.manual_implicits -> inline:Declaremods.inline -> name:lident -> Constr.constr option -> Constr.types -> GlobRef.t * UVars.Instance.t (** Interpret the commands Variable/Hypothesis/Axiom/Parameter *) val do_assumptions : program_mode:bool -> poly:PolyFlags.t -> scope:Locality.definition_scope -> kind:Decls.assumption_object_kind -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> inline:Declaremods.inline -> (ident_decl list * constr_expr) with_coercion list -> unit (** Interpret the command Context *) val do_context : program_mode:bool -> poly:PolyFlags.t -> local_binder_expr list -> unit (** Interpret a declaration of the form [binders |- typ] as a type *) val interp_assumption : program_mode:bool -> poly:PolyFlags.t -> Environ.env -> Evd.evar_map -> Constrintern.internalization_env -> Constrexpr.local_binder_expr list -> constr_expr -> Evd.evar_map * EConstr.types * Impargs.manual_implicits (** The first half of the context command, returning the declarations in the same order as [Context], using de Bruijn indices (used by Elpi) *) val interp_context : Environ.env -> Evd.evar_map -> local_binder_expr list -> Evd.evar_map * (Id.t * Constr.t option * Constr.t * Glob_term.binding_kind) list rocq-9.2.0/vernac/comCoercion.ml000066400000000000000000000324731516144147600165600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (Printer.pr_global g ++ str" is already a coercion") | NotAFunction -> (Printer.pr_global g ++ str" is not a function") | NoSource (Some cl) -> (str "Cannot recognize " ++ pr_class cl ++ str " as a source class of " ++ Printer.pr_global g) | NoSource None -> (str ": cannot find the source class of " ++ Printer.pr_global g) | ForbiddenSourceClass cl -> pr_class cl ++ str " cannot be a source class" | NoTarget -> (str"Cannot find the target class") | WrongTarget (clt,cl) -> (str"Found target class " ++ pr_class cl ++ str " instead of " ++ pr_class clt) | NotAClass ref -> (str "Type of " ++ Printer.pr_global ref ++ str " does not end with a sort") (* Verifications pour l'ajout d'une classe *) let check_reference_arity ref = let env = Global.env () in let c, _ = Typeops.type_of_global_in_context env ref in if not (Reductionops.is_arity env (Evd.from_env env) (EConstr.of_constr c)) (* FIXME *) then raise (CoercionError (NotAClass ref)) let check_arity = function | CL_FUN | CL_SORT -> () | CL_CONST cst -> check_reference_arity (GlobRef.ConstRef cst) | CL_PROJ p -> check_reference_arity (GlobRef.ConstRef (Projection.Repr.constant p)) | CL_SECVAR id -> check_reference_arity (GlobRef.VarRef id) | CL_IND kn -> check_reference_arity (GlobRef.IndRef kn) (* Coercions *) (* check that the computed target is the provided one *) let check_target clt = function | Some cl when not (cl_typ_eq cl clt) -> raise (CoercionError (WrongTarget(clt,cl))) | _ -> () (* condition d'heritage uniforme *) let uniform_cond sigma ctx lt = List.for_all2eq (EConstr.eq_constr sigma) lt (Context.Rel.instance_list EConstr.mkRel 0 ctx) let class_of_global = function | GlobRef.ConstRef sp -> (match Structures.PrimitiveProjections.find_opt sp with | Some p -> CL_PROJ p | None -> CL_CONST sp) | GlobRef.IndRef sp -> CL_IND sp | GlobRef.VarRef id -> CL_SECVAR id | GlobRef.ConstructRef _ as c -> user_err (str "Constructors, such as " ++ Printer.pr_global c ++ str ", cannot be used as a class.") (* lp est la liste (inverse'e) des arguments de la coercion ids est le nom de la classe source sps_opt est le sp de la classe source dans le cas des structures retourne: la classe source nbre d'arguments de la classe le constr de la class la liste des variables dont depend la classe source l'indice de la classe source dans la liste lp *) let get_source env lp source = let open Context.Rel.Declaration in match source with | None -> (* Take the latest non let-in argument *) let rec aux = function | [] -> raise Not_found | LocalDef _ :: lt -> aux lt | LocalAssum (_,t1) :: lt -> let cl1,u1,lv1 = find_class_type (push_rel_context lt env) Evd.empty (EConstr.of_constr t1) in cl1,lt,lv1,1 in aux lp | Some cl -> (* Take the first argument that matches *) let rec aux env acc = function | [] -> raise Not_found | LocalDef _ as decl :: lt -> aux (push_rel decl env) (decl::acc) lt | LocalAssum (_,t1) as decl :: lt -> try let cl1,u1,lv1 = find_class_type env Evd.empty (EConstr.of_constr t1) in if cl_typ_eq cl cl1 then cl1,acc,lv1,Context.Rel.nhyps lt+1 else raise Not_found with Not_found -> aux (push_rel decl env) (decl::acc) lt in aux env [] (List.rev lp) let get_target env lp t ind = if (ind > 1) then CL_FUN else match pi1 (find_class_type (push_rel_context lp env) Evd.empty (EConstr.of_constr t)) with | CL_CONST p when Structures.PrimitiveProjections.mem p -> CL_PROJ (Option.get @@ Structures.PrimitiveProjections.find_opt p) | x -> x let strength_of_cl = function | CL_CONST kn -> `GLOBAL | CL_SECVAR id -> `LOCAL | _ -> `GLOBAL let strength_of_global = function | GlobRef.VarRef _ -> `LOCAL | _ -> `GLOBAL let get_strength stre ref cls clt = let stres = strength_of_cl cls in let stret = strength_of_cl clt in let stref = strength_of_global ref in strength_min [stre;stres;stret;stref] let ident_key_of_class = function | CL_FUN -> "Funclass" | CL_SORT -> "Sortclass" | CL_CONST sp -> Id.to_string (Constant.label sp) | CL_PROJ sp -> Id.to_string (Projection.Repr.label sp) | CL_IND (sp,_) -> Id.to_string (MutInd.label sp) | CL_SECVAR id -> Id.to_string id (* Identity coercion *) let error_not_transparent source = user_err (pr_class source ++ str " must be a transparent constant.") let build_id_coercion ?loc idf_opt source poly = let env = Global.env () in let sigma = Evd.from_env env in let sigma, vs = match source with | CL_CONST sp -> Evd.fresh_global env sigma (GlobRef.ConstRef sp) | _ -> error_not_transparent source in let vs = EConstr.Unsafe.to_constr vs in let c = match constant_opt_value_in env (destConst vs) with | Some c -> c | None -> error_not_transparent source in let lams,t = decompose_lambda_decls c in let val_f = Term.it_mkLambda_or_LetIn (mkLambda (make_annot (Name Namegen.default_dependent_ident) Sorts.Relevant, applistc vs (Context.Rel.instance_list mkRel 0 lams), mkRel 1)) lams in let typ_f = List.fold_left (fun d c -> Term.mkProd_wo_LetIn c d) (mkProd (make_annot Anonymous Sorts.Relevant, applistc vs (Context.Rel.instance_list mkRel 0 lams), lift 1 t)) lams in (* juste pour verification *) let sigma, val_t = Typing.type_of env sigma (EConstr.of_constr val_f) in let () = if not (Reductionops.is_conv_leq env sigma val_t (EConstr.of_constr typ_f)) then user_err (strbrk "Cannot be defined as coercion (maybe a bad number of arguments).") in let name = match idf_opt with | Some idf -> idf | None -> let cl,u,_ = find_class_type env sigma (EConstr.of_constr t) in Id.of_string ("Id_"^(ident_key_of_class source)^"_"^ (ident_key_of_class cl)) in let univs = Evd.univ_entry ~poly sigma in let constr_entry = (* Cast is necessary to express [val_f] is identity *) DefinitionEntry (definition_entry ~types:typ_f ~univs ~inline:true (mkCast (val_f, DEFAULTcast, typ_f))) in let kind = Decls.(IsDefinition IdentityCoercion) in let kn = declare_constant ?loc ~name ~kind constr_entry in GlobRef.ConstRef kn let check_source = function | Some (CL_FUN as s) -> raise (CoercionError (ForbiddenSourceClass s)) | _ -> () let cache_coercion ?(update=false) c = let env = Global.env () in let sigma = Evd.from_env env in Coercionops.declare_coercion env sigma ~update c let discharge_coercion c = if c.coe_local then None else let n = try Array.length (Global.section_instance c.coe_value) with Not_found -> 0 in let nc = { c with coe_param = n + c.coe_param; coe_is_projection = Option.map Global.discharge_proj_repr c.coe_is_projection; } in Some nc let classify_coercion obj = if obj.coe_local then Dispose else Substitute let coe_cat = create_category "coercions" let inCoercion : coe_info_typ -> obj = declare_object {(default_object "COERCION") with open_function = simple_open ~cat:coe_cat cache_coercion; cache_function = cache_coercion; subst_function = (fun (subst,c) -> subst_coercion subst c); classify_function = classify_coercion; discharge_function = discharge_coercion; } let declare_coercion coef ?(local = false) ~reversible ~isid ~src:cls ~target:clt ~params:ps () = let isproj = match coef with | GlobRef.ConstRef c -> Structures.PrimitiveProjections.find_opt c | _ -> None in let c = { coe_value = coef; coe_local = local; coe_reversible = reversible; coe_is_identity = isid; coe_is_projection = isproj; coe_source = cls; coe_target = clt; coe_param = ps; } in Lib.add_leaf (inCoercion c) (* nom de la fonction coercion strength de f nom de la classe source (optionnel) sp de la classe source (dans le cas des structures) nom de la classe target (optionnel) booleen "coercion identite'?" lorque source est None alors target est None aussi. *) let warn_uniform_inheritance = CWarnings.create ~name:"uniform-inheritance" ~category:CWarnings.CoreCategories.coercions (fun g -> Printer.pr_global g ++ strbrk" does not respect the uniform inheritance condition.") let add_new_coercion_core coef stre ~reversible source target isid : unit = check_source source; let env = Global.env () in let t, _ = Typeops.type_of_global_in_context env coef in if coercion_exists coef then raise (CoercionError AlreadyExists); let lp,tg = decompose_prod_decls t in let llp = List.length lp in if Int.equal llp 0 then raise (CoercionError NotAFunction); let (cls,ctx,lvs,ind) = try get_source env lp source with Not_found -> raise (CoercionError (NoSource source)) in check_source (Some cls); if not (uniform_cond Evd.empty (* FIXME - for when possibly called with unresolved evars in the future *) ctx lvs) then warn_uniform_inheritance coef; let clt = try get_target env lp tg ind with Not_found -> raise (CoercionError NoTarget) in check_target clt target; check_arity cls; check_arity clt; let local = match get_strength stre coef cls clt with | `LOCAL -> true | `GLOBAL -> false in let params = List.length (Context.Rel.instance_list EConstr.mkRel 0 ctx) in declare_coercion coef ~local ~reversible ~isid ~src:cls ~target:clt ~params () let try_add_new_coercion_core ref ~local c ~reversible d e = try add_new_coercion_core ref (loc_of_bool local) c ~reversible d e with CoercionError e -> user_err (explain_coercion_error ref e ++ str ".") let try_add_new_coercion ref ~local ~reversible = try_add_new_coercion_core ref ~local ~reversible None None false let try_add_new_coercion_subclass ?loc cl ~local ~poly ~reversible = let coe_ref = build_id_coercion ?loc None cl poly in try_add_new_coercion_core coe_ref ~local ~reversible (Some cl) None true let try_add_new_coercion_with_target ref ~local ~reversible ~source ~target = try_add_new_coercion_core ref ~local ~reversible (Some source) (Some target) false let try_add_new_identity_coercion {CAst.v=id; loc} ~local ~poly ~source ~target = let ref = build_id_coercion ?loc (Some id) source poly in try_add_new_coercion_core ref ~local ~reversible:true (Some source) (Some target) true let try_add_new_coercion_with_source ref ~local ~reversible ~source = try_add_new_coercion_core ref ~local ~reversible (Some source) None false let coercion_hook ~reversible = Declare.Hook.make @@ fun { scope; dref; _ } -> let open Locality in let local = match scope with | Discharge -> assert false (* Local Coercion in section behaves like Local Definition *) | Global ImportNeedQualified -> true | Global ImportDefaultBehavior -> false in let () = try_add_new_coercion dref ~local ~reversible in let msg = Nametab.pr_global_env Id.Set.empty dref ++ str " is now a coercion" in Flags.if_verbose Feedback.msg_info msg let subclass_hook ~poly ~reversible = Declare.Hook.make @@ fun { scope; dref; _ } -> let open Locality in let stre = match scope with | Discharge -> assert false (* Local Subclass in section behaves like Local Definition *) | Global ImportNeedQualified -> true | Global ImportDefaultBehavior -> false in let cl = class_of_global dref in let loc = Nametab.cci_src_loc (TrueGlobal dref) in try_add_new_coercion_subclass ?loc cl ~local:stre ~poly ~reversible let nonuniform = Attributes.bool_attribute ~name:"nonuniform" let warn_reverse_no_change = CWarnings.create ~name:"reversible-no-change" ~category:CWarnings.CoreCategories.coercions (fun () -> str "The reversible attribute is unchanged.") let change_reverse ref ~reversible = if not (coercion_exists ref) then user_err (Printer.pr_global ref ++ str" is not a coercion."); let coe_info = coercion_info ref in if reversible = coe_info.coe_reversible then warn_reverse_no_change () else cache_coercion ~update:true { coe_info with coe_reversible = reversible } rocq-9.2.0/vernac/comCoercion.mli000066400000000000000000000047241516144147600167270ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* local:bool -> reversible:bool -> source:cl_typ -> target:cl_typ -> unit (** [try_add_new_coercion ref s] declares [ref], assumed to be of type [(x1:T1)...(xn:Tn)src->tg], as a coercion from [src] to [tg] *) val try_add_new_coercion : GlobRef.t -> local:bool -> reversible:bool -> unit (** [try_add_new_coercion_subclass cst s] expects that [cst] denotes a transparent constant which unfolds to some class [tg]; it declares an identity coercion from [cst] to [tg], named something like ["Id_cst_tg"] *) val try_add_new_coercion_subclass : ?loc:Loc.t -> cl_typ -> local:bool -> poly:PolyFlags.t -> reversible:bool -> unit (** [try_add_new_coercion_with_source ref s src] declares [ref] as a coercion from [src] to [tg] where the target is inferred from the type of [ref] *) val try_add_new_coercion_with_source : GlobRef.t -> local:bool -> reversible:bool -> source:cl_typ -> unit (** [try_add_new_identity_coercion id s src tg] enriches the environment with a new definition of name [id] declared as an identity coercion from [src] to [tg] *) val try_add_new_identity_coercion : lident -> local:bool -> poly:PolyFlags.t -> source:cl_typ -> target:cl_typ -> unit val coercion_hook : reversible:bool -> Declare.Hook.t val subclass_hook : poly:PolyFlags.t -> reversible:bool -> Declare.Hook.t val class_of_global : GlobRef.t -> cl_typ (** Attribute to silence warning for coercions that don't satisfy the uniform inheritance condition. (deprecated in 8.18) *) val nonuniform : bool option Attributes.attribute val change_reverse : GlobRef.t -> reversible:bool -> unit rocq-9.2.0/vernac/comDefinition.ml000066400000000000000000000232451516144147600171040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* sigma, body | Some red -> let red, _ = reduction_of_red_expr env red in red env sigma body let warn_implicits_in_term = CWarnings.create ~name:"implicits-in-term" ~category:CWarnings.CoreCategories.implicits (fun () -> strbrk "Implicit arguments declaration relies on type." ++ spc () ++ strbrk "Discarding incompatible declaration in term.") let check_imps ~impsty ~impsbody = let rec aux impsty impsbody = match impsty, impsbody with | a1 :: impsty, a2 :: impsbody -> let () = match a1.CAst.v, a2.CAst.v with | None , None | Some _, None -> () | Some (_,b1) , Some (_,b2) -> if not ((b1:bool) = b2) then warn_implicits_in_term ?loc:a2.CAst.loc () | None, Some _ -> warn_implicits_in_term ?loc:a2.CAst.loc () in aux impsty impsbody | _ :: _, [] | [], _ :: _ -> (* Information only on one side *) () | [], [] -> () in aux impsty impsbody let protect_pattern_in_binder bl c ctypopt = (* We turn "Definition d binders := body : typ" into *) (* "Definition d := fun binders => body:type" *) (* This is a hack while waiting for LocalPattern in regular environments *) if List.exists (function Constrexpr.CLocalPattern _ -> true | _ -> false) bl then let t = match ctypopt with | None -> CAst.make ?loc:c.CAst.loc (Constrexpr.CHole (None)) | Some t -> t in let loc = Loc.merge_opt c.CAst.loc t.CAst.loc in let c = CAst.make ?loc @@ Constrexpr.CCast (c, Some Constr.DEFAULTcast, t) in let loc = match List.hd bl with | Constrexpr.CLocalAssum (a::_,_,_,_) | Constrexpr.CLocalDef (a,_,_,_) -> a.CAst.loc | Constrexpr.CLocalPattern {CAst.loc} -> loc | Constrexpr.CLocalAssum ([],_,_,_) -> assert false in let apply_under_binders f env evd c = let rec aux env evd c = let open Constr in let open EConstr in let open Context.Rel.Declaration in match kind evd c with | Lambda (x,t,c) -> let evd,c = aux (push_rel (LocalAssum (x,t)) env) evd c in evd, mkLambda (x,t,c) | LetIn (x,b,t,c) -> let evd,c = aux (push_rel (LocalDef (x,b,t)) env) evd c in evd, mkLetIn (x,b,t,c) | Case (ci,u,pms,p,iv,a,bl) -> let (ci, p, iv, a, bl) = EConstr.expand_case env evd (ci, u, pms, p, iv, a, bl) in let evd,bl = Array.fold_left_map (aux env) evd bl in evd, mkCase (EConstr.contract_case env evd (ci, p, iv, a, bl)) | Cast (c,_,_) -> f env evd c (* we remove the cast we had set *) (* This last case may happen when reaching the proof of an impossible case, as when pattern-matching on a vector of length 1 *) | _ -> (evd,c) in aux env evd c in ([], Constrexpr_ops.mkLambdaCN ?loc:(Loc.merge_opt loc c.CAst.loc) bl c, None, apply_under_binders) else (bl, c, ctypopt, fun f env evd c -> f env evd c) let interp_definition ~program_mode ~poly env evd impl_env bl red_option c ctypopt = let flags = Pretyping.{ all_no_fail_flags with program_mode; poly } in let (bl, c, ctypopt, apply_under_binders) = protect_pattern_in_binder bl c ctypopt in (* Build the parameters *) let evd, (impls, ((env_bl, ctx), imps1, _locs)) = interp_context_evars ~program_mode ~impl_env env evd bl in (* Build the type *) let evd, tyopt = Option.fold_left_map (interp_type_evars_impls ~flags ~impls env_bl) evd ctypopt in (* Build the body, and merge implicits from parameters and from type/body *) let evd, c, imps, tyopt = match tyopt with | None -> let evd, (c, impsbody) = interp_constr_evars_impls ~program_mode ~poly ~impls env_bl evd c in evd, c, imps1@impsbody, None | Some (ty, impsty) -> let evd, (c, impsbody) = interp_casted_constr_evars_impls ~program_mode ~poly ~impls env_bl evd c ty in check_imps ~impsty ~impsbody; evd, c, imps1@impsty, Some ty in (* Do the reduction *) let evd, c = apply_under_binders (red_constant_body red_option) env_bl evd c in (* Declare the definition *) let c = EConstr.it_mkLambda_or_LetIn c ctx in let tyopt = Option.map (fun ty -> EConstr.it_mkProd_or_LetIn ty ctx) tyopt in evd, (c, tyopt), imps let interp_statement ~program_mode env evd ~(flags : Pretyping.inference_flags) ~scope name bl typ = let poly = Pretyping.(flags.poly) in let evd, (impls, ((env, ctx), imps, _locs)) = Constrintern.interp_context_evars ~poly ~program_mode env evd bl in let evd, (t', imps') = Constrintern.interp_type_evars_impls ~flags ~impls env evd typ in let ids = List.map Context.Rel.Declaration.get_name ctx in evd, ids, EConstr.it_mkProd_or_LetIn t' ctx, imps @ imps' let do_definition ?loc ?hook ~name ?scope ?clearbody ~poly ?typing_flags ~kind ?using ?user_warns udecl bl red_option c ctypopt = let program_mode = false in let env = Global.env() in let env = Environ.update_typing_flags ?typing_flags env in (* Explicitly bound universes and constraints *) let evd, udecl = interp_univ_decl_opt env udecl in let evd, (body, types), impargs = interp_definition ~program_mode ~poly env evd empty_internalization_env bl red_option c ctypopt in let kind = Decls.IsDefinition kind in let cinfo = Declare.CInfo.make ?loc ~name ~impargs ~typ:types () in let info = Declare.Info.make ?scope ?clearbody ~kind ?hook ~udecl ~poly ?typing_flags ?user_warns () in let _ : Names.GlobRef.t = Declare.declare_definition ~info ~cinfo ~opaque:false ~body ?using evd in () let do_definition_program ?loc ?hook ~pm ~name ~scope ?clearbody ~poly ?typing_flags ~kind ?using ?user_warns udecl bl red_option c ctypopt = let env = Global.env() in let env = Environ.update_typing_flags ?typing_flags env in (* Explicitly bound universes and constraints *) let evd, udecl = interp_univ_decl_opt env udecl in let evd, (body, types), impargs = interp_definition ~program_mode:true ~poly env evd empty_internalization_env bl red_option c ctypopt in let body, typ, uctx, _, obls = Declare.Obls.prepare_obligations ~name poly ~body ?types env evd in Evd.check_univ_decl_early ~poly ~with_obls:true (Evd.from_ctx uctx) udecl [body; typ]; let cinfo = Declare.CInfo.make ?loc ~name ~typ ~impargs () in let info = Declare.Info.make ~udecl ~scope ?clearbody ~poly ~kind ?hook ?typing_flags ?user_warns () in Declare.Obls.add_definition ~pm ~info ~cinfo ~opaque:false ~body ~uctx ?using obls let do_definition_interactive ?loc ~program_mode ?hook ~name ~scope ?clearbody ~poly ~typing_flags ~kind ?using ?user_warns udecl bl t = let env = Global.env () in let env = Environ.update_typing_flags ?typing_flags env in let flags = Pretyping.{ all_no_fail_flags with program_mode; poly } in let evd, udecl = Constrintern.interp_univ_decl_opt env udecl in let evd, args, typ,impargs = interp_statement ~program_mode ~flags ~scope env evd name bl t in let evd = let inference_hook = if program_mode then Some Declare.Obls.program_inference_hook else None in Pretyping.solve_remaining_evars ?hook:inference_hook flags env evd in let evd = Evd.minimize_universes evd in Pretyping.check_evars_are_solved ~program_mode env evd; let typ = EConstr.to_constr evd typ in Evd.check_univ_decl_early ~poly ~with_obls:false evd udecl [typ]; let typ = EConstr.of_constr typ in let info = Declare.Info.make ?hook ~poly ~scope ?clearbody ~kind ~udecl ?typing_flags ?user_warns () in let cinfo = Declare.CInfo.make ?loc ~name ~typ ~args ~impargs () in let evd = if PolyFlags.univ_poly poly then evd else Evd.fix_undefined_variables evd in Declare.Proof.start_definition ~info ~cinfo ?using evd let do_definition_refine ?loc ?hook ~name ~scope ?clearbody ~poly ~typing_flags ~kind ?using ?user_warns udecl bl c ctypopt = let env = Global.env() in let env = Environ.update_typing_flags ?typing_flags env in (* Explicitly bound universes and constraints *) let evd, udecl = interp_univ_decl_opt env udecl in let evd, (body, typ), impargs = interp_definition ~program_mode:false ~poly env evd empty_internalization_env bl None c ctypopt in let typ = match typ with Some typ -> typ | None -> Retyping.get_type_of env evd body in let info = Declare.Info.make ?hook ~poly ~scope ?clearbody ~kind ~udecl ?typing_flags ?user_warns () in let cinfo = Declare.CInfo.make ?loc ~name ~typ ~impargs () in let evd = if PolyFlags.univ_poly poly then evd else Evd.fix_undefined_variables evd in let future_goals, evd = Evd.pop_future_goals evd in let gls = List.rev (Evd.FutureGoals.comb future_goals) in let evd = Evd.push_future_goals evd in let lemma = Declare.Proof.start_definition ~cinfo ~info ?using evd in let init_refine = Tacticals.tclTHENLIST [ Refine.refine ~typecheck:false (fun evd -> evd, body); Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls); Tactics.reduce_after_refine; ] in let lemma, _ = Declare.Proof.by (Global.env ()) init_refine lemma in lemma rocq-9.2.0/vernac/comDefinition.mli000066400000000000000000000057221516144147600172550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* poly:PolyFlags.t -> Environ.env -> Evd.evar_map -> Constrintern.internalization_env -> Constrexpr.local_binder_expr list -> red_expr option -> constr_expr -> constr_expr option -> Evd.evar_map * (EConstr.t * EConstr.t option) * Impargs.manual_implicits val do_definition : ?loc:Loc.t -> ?hook:Declare.Hook.t -> name:Id.t -> ?scope:Locality.definition_scope -> ?clearbody:bool -> poly:PolyFlags.t -> ?typing_flags:Declarations.typing_flags -> kind:Decls.definition_object_kind -> ?using:Vernacexpr.section_subset_expr -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> universe_decl_expr option -> local_binder_expr list -> red_expr option -> constr_expr -> constr_expr option -> unit val do_definition_program : ?loc:Loc.t -> ?hook:Declare.Hook.t -> pm:Declare.OblState.t -> name:Id.t -> scope:Locality.definition_scope -> ?clearbody:bool -> poly:PolyFlags.t -> ?typing_flags:Declarations.typing_flags -> kind:Decls.logical_kind -> ?using:Vernacexpr.section_subset_expr -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> universe_decl_expr option -> local_binder_expr list -> red_expr option -> constr_expr -> constr_expr option -> Declare.OblState.t val do_definition_interactive : ?loc:Loc.t -> program_mode:bool -> ?hook:Declare.Hook.t -> name:Id.t -> scope:Locality.definition_scope -> ?clearbody:bool -> poly:PolyFlags.t -> typing_flags:Declarations.typing_flags option -> kind:Decls.logical_kind -> ?using:Vernacexpr.section_subset_expr -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> universe_decl_expr option -> local_binder_expr list -> constr_expr -> Declare.Proof.t val do_definition_refine : ?loc:Loc.t -> ?hook:Declare.Hook.t -> name:Id.t -> scope:Locality.definition_scope -> ?clearbody:bool -> poly:PolyFlags.t -> typing_flags:Declarations.typing_flags option -> kind:Decls.logical_kind -> ?using:Vernacexpr.section_subset_expr -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> universe_decl_expr option -> local_binder_expr list -> constr_expr -> constr_expr option -> Declare.Proof.t rocq-9.2.0/vernac/comExtraDeps.ml000066400000000000000000000025311516144147600167060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* user_err Pp.(str "Extra dependency " ++ Id.print id ++ str " already bound to " ++ str other ++ pr_opt (fun x -> str " at " ++ Loc.pr x) loc ++ str ".") | None -> extra_deps := Id.Map.add id (path,loc) !extra_deps let declare_extra_dep ?loc ~from ~file id = let file_path = Loadpath.find_extra_dep_with_logical_path ?loc ~from ~file () in Option.iter (bind_extra_dep ?loc file_path) id let query_extra_dep id = fst @@ Id.Map.find id !extra_deps rocq-9.2.0/vernac/comExtraDeps.mli000066400000000000000000000015201516144147600170540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* from:Names.DirPath.t -> file:string -> Names.Id.t option -> unit val query_extra_dep : Names.Id.t -> string (* @raise Not_found *) rocq-9.2.0/vernac/comFixpoint.ml000066400000000000000000000765561516144147600166310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* None | x :: l -> if List.mem_f eq x prefix then Some x else first_dup eq (x :: prefix) l in match first_dup lident_eq [] fixlnames with | None -> () | Some CAst.{ v=na; loc } -> CErrors.user_err ?loc (str "An entry of name " ++ Id.print na ++ str " already exists in the mutual block.") (* An (unoptimized) function that maps preorders to partial orders... Input: a list of associations (x,[y1;...;yn]), all yi distincts and different of x, meaning x<=y1, ..., x<=yn Output: a list of associations (x,Inr [y1;...;yn]), collecting all distincts yi greater than x, _or_, (x, Inl y) meaning that x is in the same class as y (in which case, x occurs nowhere else in the association map) partial_order : ('a * 'a list) list -> ('a * ('a,'a list) union) list *) let rec partial_order cmp = function | [] -> [] | (x,xge)::rest -> let rec browse res xge' = function | [] -> let res = List.map (function | (z, Inr zge) when List.mem_f cmp x zge -> (z, Inr (List.union cmp zge xge')) | r -> r) res in (x,Inr xge')::res | y::xge -> let rec link y = try match List.assoc_f cmp y res with | Inl z -> link z | Inr yge -> if List.mem_f cmp x yge then let res = List.remove_assoc_f cmp y res in let res = List.map (function | (z, Inl t) -> if cmp t y then (z, Inl x) else (z, Inl t) | (z, Inr zge) -> if List.mem_f cmp y zge then (z, Inr (List.add_set cmp x (List.remove cmp y zge))) else (z, Inr zge)) res in browse ((y,Inl x)::res) xge' (List.union cmp xge yge) else browse res (List.add_set cmp y (List.union cmp xge' yge)) xge with Not_found -> browse res (List.add_set cmp y xge') xge in link y in browse (partial_order cmp rest) [] xge let string_of_kind = function | Decls.IsDefinition Fixpoint -> "fixpoint" | IsDefinition CoFixpoint -> "cofixpoint" | _ -> "declaration" let non_full_mutual_message x xge y yge kind rest = let reason = if Id.List.mem x yge then Id.print y ++ str " depends on " ++ Id.print x ++ strbrk " but not conversely" else if Id.List.mem y xge then Id.print x ++ str " depends on " ++ Id.print y ++ strbrk " but not conversely" else Id.print y ++ str " and " ++ Id.print x ++ strbrk " are not mutually dependent" in let e = if List.is_empty rest then reason else strbrk "e.g., " ++ reason in let w = if kind <> Decls.IsDefinition CoFixpoint then strbrk "Well-foundedness check may fail unexpectedly." ++ fnl() else mt () in strbrk "Not a fully mutually defined " ++ str (string_of_kind kind) ++ fnl () ++ str "(" ++ e ++ str ")." ++ fnl () ++ w let warn_non_full_mutual = CWarnings.create ~name:"non-full-mutual" ~category:CWarnings.CoreCategories.fixpoints (fun (x,xge,y,yge,kind,rest) -> non_full_mutual_message x xge y yge kind rest) let warn_non_recursive = CWarnings.create ~name:"non-recursive" ~category:CWarnings.CoreCategories.fixpoints (fun (x,kind) -> strbrk "Not a truly recursive " ++ str (string_of_kind kind) ++ str ".") let check_true_recursivity env evd ~kind fixl = let names = List.map fst fixl in let preorder = List.map (fun (id,def) -> (id.CAst.v, List.filter_map (fun {CAst.v=id'} -> if Termops.occur_var env evd id' def then Some id' else None) names)) fixl in let po = partial_order Id.equal preorder in match List.filter (function (_,Inr _) -> true | _ -> false) po with | (x,Inr xge)::(y,Inr yge)::rest -> warn_non_full_mutual (x,xge,y,yge,kind,rest) | _ -> match po with | [x,Inr []] -> warn_non_recursive (x,kind) | _ -> () (*****************************************************) (* Utilities for Program Fixpoint with wf or measure *) open Rocqlib let init_constant sigma rf = Evd.fresh_global sigma rf let fix_sub_ref () = lib_ref "program.wf.fix_sub" let measure_on_R_ref () = lib_ref "program.wf.mr" let well_founded sigma = init_constant (Global.env ()) sigma (lib_ref "core.wf.well_founded") let mkSubset sigma name typ prop = let open EConstr in let sigma, app_h = Evd.fresh_global (Global.env ()) sigma (delayed_force build_sigma).typ in sigma, mkApp (app_h, [| typ; mkLambda (make_annot name ERelevance.relevant, typ, prop) |]) let ensure_program () = try fix_sub_ref (), measure_on_R_ref () with NotFoundRef r -> CErrors.user_err Pp.(str r ++ spc() ++ str "not registered," ++ spc() ++ str "you should try requiring library Corelib.Program.Wf.") let recproofid = Id.of_string "recproof" let argname = Id.of_string "recarg" let encapsulate_Fix_sub env sigma recname ctx body ccl (extradecl, rel, relargty, measure_body) = let len = Context.Rel.length ctx in let fix_sub_ref, measure_on_R_ref = ensure_program () in (* We curry the binders [x1:A1;...;xn:An] into [x:{x1&...&xn};x1:=x.1;...;xn:=x.2...2] *) (* argtyp is [{x1&...&xn}], letbinders is [x1:=x.1;...;xn:=x.2...2], argvalue is [(x.1,...,x.2...2)] *) let open Combinators in let sigma, letbinders, {telescope_type = tuple_type; telescope_value = tuple_value} = telescope env sigma ctx in let tupled_ctx = letbinders @ [LocalAssum (make_annot (Name argname) ERelevance.relevant, tuple_type)] in (* The function measure has type [tuple_type -> relargty] *) let measure = it_mkLambda_or_LetIn measure_body tupled_ctx in (* The relation wf_rel_measure is [fun x y => rel (measure x) (measure y)] *) let sigma, comb = Evd.fresh_global (Global.env ()) sigma measure_on_R_ref in let rel_measure = mkApp (comb, [| tuple_type; relargty; rel; measure |]) in (* The statement that rel_measure is well-founded *) let sigma, wf_term = well_founded sigma in let wf_type = mkApp (wf_term, [| tuple_type ; rel_measure |]) in (* A combinator building [rel (measure x) (measure y)] *) let tupled_measure_body = it_mkLambda_or_LetIn measure_body letbinders in let make_applied_rel x y = mkApp (rel, [| Vars.subst1 x tupled_measure_body; Vars.subst1 y tupled_measure_body |]) in (* Conclusion of fixpoint in currified context *) let tupled_ccl = it_mkLambda_or_LetIn ccl letbinders in (* Making Fix_sub ready to take the extended body as argument *) let sigma, fix_sub = let sigma, fix_sub_term = Evd.fresh_global (Global.env ()) sigma fix_sub_ref in let typeclass_candidate = Typeclasses.is_maybe_class_type env sigma wf_type in let sigma, wf_proof = Evarutil.new_evar ~typeclass_candidate env sigma ~src:(Loc.tag @@ Evar_kinds.QuestionMark { Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=Evar_kinds.Define false; }) wf_type in let sigma = Evd.set_obligation_evar sigma (fst (destEvar sigma wf_proof)) in let ccl_pred = mkLambda (make_annot (Name argname) ERelevance.relevant, tuple_type, tupled_ccl) in let def = mkApp (fix_sub_term, [| tuple_type ; rel_measure ; wf_proof ; ccl_pred |]) in Typing.solve_evars env sigma def in let arg = RelDecl.LocalAssum (make_annot (Name argname) ERelevance.relevant, tuple_type) in let argid' = Id.of_string (Id.to_string argname ^ "'") in let sigma, wfa = let sigma, ss_term = mkSubset sigma (Name argid') tuple_type (make_applied_rel (mkRel 1) (mkRel 2)) in sigma, RelDecl.LocalAssum (make_annot (Name argid') ERelevance.relevant, ss_term) in let sigma, fix_sub_F_sub_ctx = let sigma, proj = Evd.fresh_global (Global.env ()) sigma (delayed_force build_sigma).Rocqlib.proj1 in let wfargpred = mkLambda (make_annot (Name argid') ERelevance.relevant, tuple_type, make_applied_rel (mkRel 1) (mkRel 3)) in let projection = (* in wfarg :: arg :: before *) mkApp (proj, [| tuple_type ; wfargpred ; mkRel 1 |]) in let ccl_on_smaller_arg = Vars.substl [projection] (it_mkLambda_or_LetIn ccl letbinders) in (* substitute the projection of wfarg for something, now ccl_let is in wfarg :: arg *) let ccl_on_smaller_arg = it_mkProd_or_LetIn ccl_on_smaller_arg [wfa] in let recname' = Nameops.add_suffix recname "'" in let smaller_arg = RelDecl.LocalAssum (make_annot (Name recname') ERelevance.relevant, ccl_on_smaller_arg) in sigma, Vars.lift_rel_context 1 letbinders @ smaller_arg :: [arg] in let sigma, curryfier_body, curryfier_ty = (* In tupled_context where the function argument of Fix_sub (argid'), is inserted, that is, all expanded: [recarg;argid';letbinders], build the curryfying combinator [fun ctx (recproof : rel (measure ctx) (measure tupled_context)) => argid' (tuple_value,recproof)] of type [forall ctx (recproof : rel (measure ctx) (measure tupled_context)) => ccl] *) let sigma, intro = Evd.fresh_global (Global.env ()) sigma (delayed_force build_sigma).Rocqlib.intro in let app = let wfpred = mkLambda (make_annot (Name argid') ERelevance.relevant, tuple_type, make_applied_rel (mkRel 1) (mkRel (2 * len + 4))) in (* Build the sig pair [exist _ tuple_value recproof] *) let arg = mkApp (intro, [| tuple_type; wfpred; Vars.lift 1 tuple_value; mkRel 1 |]) in (* Build the body of combinator *) mkApp (mkRel (2 * len + 2 (* recproof + orig binders + current binders *)), [| arg |]) in let extended_ctx = extradecl :: ctx in let body = it_mkLambda_or_LetIn app extended_ctx in let ty = it_mkProd_or_LetIn (Vars.lift 1 ccl) extended_ctx in sigma, body, ty in (* Rephrase the body of the fixpoint as dependent in the telescope *) let body_ctx = RelDecl.LocalDef (make_annot (Name recname) ERelevance.relevant, curryfier_body, curryfier_ty) :: fix_sub_F_sub_ctx in let intern_body_lam = it_mkLambda_or_LetIn body body_ctx in (* Instantiate the argument Fix_sub_F of Fix_sub with the body of the fixpoint *) let sigma, fix_sub = Typing.solve_evars env sigma fix_sub in sigma, tupled_ctx, tuple_value, mkApp (fix_sub, [|intern_body_lam|]) let build_wellfounded env sigma poly udecl {CAst.v=recname; loc} ctx body ccl impls rel_measure = let len = Context.Rel.length ctx in (* Restore body in the context of binders + extradecl *) let _, body = decompose_lambda_n_decls sigma (len + 1) body in (* Restore ccl in the context of binders *) let ccl = Vars.subst1 (mkRel 1) (snd (decompose_prod_n_decls sigma (len + 1) ccl)) in (* Apply the body to Program.Wf.Fix_sub *) let sigma, tupled_ctx, tuple_value, def = encapsulate_Fix_sub env sigma recname ctx body ccl rel_measure in (* Turn everything to constr *) let ctx = Evarutil.nf_rel_context_evar sigma ctx in let tupled_ctx = Evarutil.nf_rel_context_evar sigma tupled_ctx in let ccl = Evarutil.nf_evar sigma ccl in let tuple_value = Evarutil.nf_evar sigma tuple_value in (* Decide if using a curryfied indirection via recname_func *) let recname_func, typ = if len > 1 then Nameops.add_suffix recname "_func", it_mkProd_or_LetIn ccl tupled_ctx else recname, it_mkProd_or_LetIn ccl ctx in let body, typ, _uctx, evmap, obls = Declare.Obls.prepare_obligations ~name:recname_func poly ~body:def ~types:typ env sigma in let hook, impls = if len > 1 then let hook { Declare.Hook.S.dref; uctx; obls; _ } = let update c = CVars.replace_vars obls (evmap mkVar (Evarutil.nf_evar (Evd.from_ctx uctx) c)) in let tuple_value = update tuple_value in let ccl = update ccl in let ctx = Context.Rel.map_het (ERelevance.kind sigma) update ctx in let univs = UState.check_univ_decl ~poly uctx udecl in let h_body = let inst = UState.(match fst univs with | Polymorphic_entry uctx -> UVars.UContext.instance uctx | Monomorphic_entry _ -> UVars.Instance.empty) in Constr.mkRef (dref, inst) in let body = Term.it_mkLambda_or_LetIn (Constr.mkApp (h_body, [|tuple_value|])) ctx in let ty = Term.it_mkProd_or_LetIn ccl ctx in let ce = Declare.definition_entry ~types:ty ~univs body in (* FIXME: include locality *) let c = Declare.declare_constant ?loc ~name:recname ~kind:Decls.(IsDefinition Definition) (DefinitionEntry ce) in let gr = GlobRef.ConstRef c in if Impargs.is_implicit_args () || not (List.is_empty impls) then Impargs.declare_manual_implicits false gr impls in Some (Declare.Hook.make hook), [] else None, impls in sigma, CAst.make ?loc recname_func, body, typ, impls, obls, hook (*********************************) (* Interpretation of Co/Fixpoint *) let make_qref s = Libnames.qualid_of_string s let lt_ref = make_qref "Init.Peano.lt" let position_of_argument ctx binders na = let exception Found of int in let name = Name na.CAst.v in try Context.Rel.fold_outside (fun decl n -> match Context.Rel.Declaration.(get_value decl, Name.equal (get_name decl) name) with | None, true -> raise (Found n) | Some _, true -> let loc = List.find_map (fun id -> if Name.equal name id.CAst.v then Some id.CAst.loc else None) (Constrexpr_ops.names_of_local_binders binders) in let loc = Option.default na.CAst.loc loc in CErrors.user_err ?loc (Name.print name ++ str" must be a proper parameter and not a local definition.") | None, false -> n + 1 | Some _, false -> n (* let-ins don't count *)) ~init:0 ctx |> ignore; CErrors.user_err ?loc:na.loc (str "No parameter named " ++ Id.print na.v ++ str"."); with Found k -> k (* Interpret the index of a recursion order annotation *) let find_rec_annot ~program_mode ~function_mode env sigma Vernacexpr.{fname={CAst.loc}; binders} ctx typ = function | None -> let ctx', _ = Reductionops.whd_decompose_prod_decls (push_rel_context ctx env) sigma typ in let n = Context.Rel.nhyps ctx + Context.Rel.nhyps ctx' in if Int.equal n 0 then CErrors.user_err ?loc Pp.(str "A fixpoint needs at least one parameter."); None, List.interval 0 (n - 1) | Some CAst.{v=rec_order;loc} -> let default_order r = Option.default (CAst.make @@ CRef (lt_ref,None)) r in match rec_order with | CStructRec na -> None, [position_of_argument ctx binders na] | CWfRec (na,r) -> if function_mode then None, [] else Some (r, Constrexpr_ops.mkIdentC na.CAst.v), [] (* useless for Program: will use Fix_sub *) | CMeasureRec (na, mes, rfel) -> if function_mode then let _ = match binders, na with | [CLocalDef({ CAst.v = Name id },_,_,_) | CLocalAssum([{ CAst.v = Name id }],_,_,_)], None -> () | _, None -> CErrors.user_err ?loc Pp.(str "Decreasing argument must be specified in measure clause.") | _, Some na -> (* check that the name exists *) ignore (position_of_argument ctx binders na) in (* Dummy *) None, [] else let r = match na, rfel with | Some id, None -> let loc = id.CAst.loc in CAst.make ?loc @@ CRef (Libnames.qualid_of_ident ?loc id.CAst.v,None) | Some _, Some _ -> CErrors.user_err ?loc Pp.(str"Measure takes three arguments only in Function.") | None, rfel -> default_order rfel in Some (r, mes), [] (* useless: will use Fix_sub *) let interp_rec_annot ~program_mode ~function_mode env sigma fixl ctxl ccll rec_order = let open Pretyping in let nowf () = List.map (fun _ -> None) fixl in match rec_order with (* If recursive argument was not given by user, we try all args. An earlier approach was to look only for inductive arguments, but doing it properly involves delta-reduction, and it finally doesn't seem to worth the effort (except for huge mutual fixpoints ?) *) | CFixRecOrder fix_orders -> let fixwf, possible_guard = List.split (List.map4 (find_rec_annot ~program_mode ~function_mode env sigma) fixl ctxl ccll fix_orders) in fixwf, {possibly_cofix = false; possible_fix_indices = possible_guard} | CCoFixRecOrder -> nowf (), {possibly_cofix = true; possible_fix_indices = List.map (fun _ -> []) fixl} | CUnknownRecOrder -> nowf (), RecLemmas.find_mutually_recursive_statements sigma ctxl ccll let interp_fix_context ~program_mode ~poly env sigma {Vernacexpr.binders} = let sigma, (impl_env, ((env', ctx), imps, _locs)) = interp_context_evars ~program_mode env sigma binders in sigma, (env', ctx, impl_env, imps) let interp_fix_ccl ~program_mode ~poly sigma impls env fix = let flags = Pretyping.{ all_no_fail_flags with program_mode ; poly } in let sigma, (c, impl) = interp_type_evars_impls ~flags ~impls env sigma fix.Vernacexpr.rtype in let r = Retyping.relevance_of_type env sigma c in sigma, (c, r, impl) let interp_fix_body ~program_mode env_rec ctx sigma impls fix ccl = Option.cata (fun body -> let env_rec_ctx = push_rel_context ctx env_rec in let sigma, body = interp_casted_constr_evars ~program_mode env_rec_ctx sigma ~impls body ccl in sigma, Some (it_mkLambda_or_LetIn body ctx)) (sigma, None) fix.Vernacexpr.body_def let build_fix_type sigma ctx ccl (_, extradecl) = let ccl = it_mkProd_or_LetIn (Vars.lift (Context.Rel.length extradecl) ccl) extradecl in Evarutil.nf_evar sigma (it_mkProd_or_LetIn ccl ctx) let build_dummy_fix_type sigma ctx ccl (_, extradecl) = (* Hack: the extra declarations are smashed to a dummy non-dependent so as not to contribute to the computation of implicit arguments *) let ccl = it_mkProd_or_LetIn (Vars.lift (Context.Rel.length extradecl) ccl) (List.map (RelDecl.map_type (fun _ -> mkProp)) extradecl) in Evarutil.nf_evar sigma (it_mkProd_or_LetIn ccl ctx) (* Wellfounded definition *) let encapsulate env sigma r t = (* Would probably be overkill to use a specific fix_proto in SProp when in SProp?? *) let fix_proto sigma = Evd.fresh_global (Global.env ()) sigma (Rocqlib.lib_ref "program.tactic.fix_proto") in let fix_proto_relevance = EConstr.ERelevance.relevant in let sigma, sort = Typing.type_of ~refresh:true env sigma t in try let sigma, h_term = fix_proto sigma in let app = EConstr.mkApp (h_term, [|sort; t|]) in let sigma, app = Typing.solve_evars env sigma app in sigma, fix_proto_relevance, app with e when CErrors.noncritical e -> sigma, r, t type ('constr, 'relevance) fix_data = { fixnames : Names.lident list; fixrs : 'relevance list; fixdefs : 'constr option list; fixtypes : 'constr list; fixctxs : EConstr.rel_context list; fiximps : (Names.Name.t * bool) option CAst.t list list; fixntns : Metasyntax.notation_interpretation_decl list; fixwfs : (rel_declaration * EConstr.t * EConstr.t * EConstr.t) option list; } let interp_wf ~program_mode env sigma recname ctx ccl = function | None -> sigma, ((false, []), None, []) | Some (r, measure) -> (* We have to insert an argument for the measure/wellfoundedness *) (* The extra implicit argument *) let impl = CAst.make (Some (Name recproofid, true)) in (* The well-founded relation *) let env_ctx = push_rel_context ctx env in let sigma, (rel, _) = interp_constr_evars_impls ~program_mode env sigma r in let relargty = Hipattern.is_homogeneous_relation ?loc:(Constrexpr_ops.constr_loc r) env_ctx sigma rel in (* The measure *) let sigma, measure = interp_casted_constr_evars ~program_mode env_ctx sigma measure relargty in let sigma, after, extradecl = if program_mode then let len = Context.Rel.length ctx in let applied_rel_measure = mkApp (rel, [| measure; Vars.lift len measure |]) in let extradecl = RelDecl.LocalAssum (make_annot (Name recproofid) ERelevance.relevant, applied_rel_measure) in sigma, true, extradecl else let sigma, wf_term = well_founded sigma in let applied_wf = mkApp (wf_term, [| relargty; rel |]) in let extradecl = RelDecl.LocalAssum (make_annot (Name recproofid) ERelevance.relevant, applied_wf) in sigma, false, extradecl in sigma, ((after, [extradecl]), Some (extradecl, rel, relargty, measure), [impl]) let interp_mutual_definition env ~program_mode ~poly ~function_mode rec_order fixl = let open Context.Named.Declaration in let open EConstr in let fixlnames = List.map (fun fix -> fix.Vernacexpr.fname) fixl in let fixnames = List.map (fun na -> na.CAst.v) fixlnames in check_duplicate fixlnames; (* Interp arities allowing for unresolved types *) let sigma, decl = interp_mutual_univ_decl_opt env (List.map (fun Vernacexpr.{univs} -> univs) fixl) in let sigma, (fixenv, fixctxs, fixctximpenvs, fixctximps) = on_snd List.split4 @@ List.fold_left_map (fun sigma -> interp_fix_context ~program_mode ~poly env sigma) sigma fixl in let sigma, (fixccls,fixrs,fixcclimps) = on_snd List.split3 @@ List.fold_left3_map (interp_fix_ccl ~program_mode ~poly) sigma fixctximpenvs fixenv fixl in let fixwfs, possible_guard = interp_rec_annot ~program_mode ~function_mode env sigma fixl fixctxs fixccls rec_order in let sigma, (fixextras, fixwfs, fixwfimps) = on_snd List.split3 @@ (List.fold_left4_map (interp_wf ~program_mode env) sigma fixnames fixctxs fixccls fixwfs) in let fixtypes = List.map3 (build_fix_type sigma) fixctxs fixccls fixextras in let sigma, rec_sign = List.fold_left4 (fun (sigma, rec_sign) id r t (_,extradecl) -> let sigma, r, t = if program_mode && List.is_empty extradecl then encapsulate env sigma r t else sigma, r, t in sigma, LocalAssum (Context.make_annot id r, t) :: rec_sign) (sigma, []) fixnames fixrs fixtypes fixextras in let fixrecimps = List.map3 (fun ctximps wfimps cclimps -> ctximps @ wfimps @ cclimps) fixctximps fixwfimps fixcclimps in let fiximps = List.map2 (fun ctximps cclimps -> ctximps @ cclimps) fixctximps fixcclimps in (* Interp bodies with rollback because temp use of notations/implicit *) let fixntns = List.map_append (fun { Vernacexpr.notations } -> List.map Metasyntax.prepare_where_notation notations ) fixl in let sigma, fixdefs = let force = List.map (fun (_,extra) -> Id.Set.of_list (List.map_filter (fun d -> Nameops.Name.to_option (RelDecl.get_name d)) extra)) fixextras in let dummy_fixtypes = List.map3 (build_dummy_fix_type sigma) fixctxs fixccls fixextras in let impls = compute_internalization_env env sigma ~force Recursive fixnames dummy_fixtypes fixrecimps in Metasyntax.with_syntax_protection (fun () -> List.iter (Metasyntax.set_notation_for_interpretation env impls) fixntns; List.fold_left5_map (fun sigma fixctximpenv (after,extradecl) ctx body ccl -> let impls = Id.Map.fold Id.Map.add fixctximpenv impls in let env', ctx = if after then env, List.map NamedDecl.to_rel_decl rec_sign @ ctx else push_named_context rec_sign env, extradecl@ctx in interp_fix_body ~program_mode env' ctx sigma impls body (Vars.lift (Context.Rel.length extradecl) ccl)) sigma fixctximpenvs fixextras fixctxs fixl fixccls) () in (* Build the fix declaration block *) let fix = {fixnames=fixlnames;fixrs;fixdefs;fixtypes;fixctxs;fiximps;fixntns;fixwfs} in (env, rec_sign, sigma), (fix, possible_guard, decl) let check_recursive ~kind env evd {fixnames;fixdefs;fixwfs} = (* TO MOVE AT FINAL DEFINITION TIME? *) if List.for_all Option.has_some fixdefs && List.for_all Option.is_empty fixwfs then begin let fixdefs = List.map Option.get fixdefs in check_true_recursivity env evd ~kind (List.combine fixnames fixdefs) end let ground_fixpoint env evd {fixnames;fixrs;fixdefs;fixtypes;fixctxs;fiximps;fixntns;fixwfs} = Pretyping.check_evars_are_solved ~program_mode:false env evd; let fixrs = List.map (fun r -> EConstr.ERelevance.kind evd r) fixrs in let fixdefs = List.map (fun c -> Option.map EConstr.(to_constr evd) c) fixdefs in let fixtypes = List.map EConstr.(to_constr evd) fixtypes in {fixnames;fixrs;fixdefs;fixtypes;fixctxs;fiximps;fixntns;fixwfs} (** For Funind *) let interp_fixpoint_short rec_order fixpoint_exprl = let env = Global.env () in let poly = PolyFlags.default in let (_, _, sigma),(fix, _, _) = interp_mutual_definition ~program_mode:false ~poly ~function_mode:true env (CFixRecOrder rec_order) fixpoint_exprl in (* Instantiate evars and check all are resolved *) let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in let sigma = Evd.minimize_universes sigma in let sigma = Pretyping.(solve_remaining_evars all_no_fail_flags env sigma) in let typel = (ground_fixpoint env sigma fix).fixtypes in typel, sigma let build_recthms {fixnames;fixtypes;fixctxs;fiximps} = List.map4 (fun {CAst.v=name; loc} typ ctx impargs -> let args = List.map Context.Rel.Declaration.get_name ctx in Declare.CInfo.make ?loc ~name ~typ ~args ~impargs () ) fixnames fixtypes fixctxs fiximps let collect_evars_of_term evd c ty = Evar.Set.union (Evd.evars_of_term evd c) (Evd.evars_of_term evd ty) let collect_evars env sigma rec_sign recname def typ = (* Generalize by the recursive prototypes *) let deps = collect_evars_of_term sigma def typ in let evars, _, def, typ = RetrieveObl.retrieve_obligations env recname.CAst.v sigma (List.length rec_sign) ~deps def typ in (Some def, typ, evars) let out_def = function | Some def -> def | None -> CErrors.user_err Pp.(str "Program Fixpoint needs defined bodies.") let build_program_fixpoint env sigma rec_sign possible_guard fixnames fixrs fixdefs fixtypes fixwfs = let () = if not @@ List.for_all Option.is_empty fixwfs then CErrors.user_err Pp.(str "Well-founded fixpoints not allowed in mutually recursive blocks.") in (* Get the interesting evars, those that were not instantiated *) let sigma = Typeclasses.resolve_typeclasses ~filter:Typeclasses.no_goals ~fail:true env sigma in (* Solve remaining evars *) let sigma = Evarutil.nf_evar_map_undefined sigma in let fixdefs = List.map out_def fixdefs in (* An early check of guardedness before working on the obligations *) let () = let fixdecls = Array.of_list (List.map2 (fun x r -> Context.make_annot (Name x.CAst.v) r) fixnames fixrs), Array.of_list fixtypes, Array.of_list fixdefs in ignore (Pretyping.esearch_guard env sigma possible_guard fixdecls) in List.split3 (List.map3 (collect_evars env sigma rec_sign) fixnames fixdefs fixtypes) let finish_obligations env sigma rec_sign possible_guard poly udecl = function | {fixnames=[recname];fixrs;fixdefs=[body];fixtypes=[ccl];fixctxs=[ctx];fiximps=[imps];fixntns;fixwfs=[Some wf]} -> let sigma = Evarutil.nf_evar_map sigma in (* use nf_evar_map_undefined?? *) let sigma, recname, body, ccl, impls, obls, hook = build_wellfounded env sigma poly udecl recname ctx (Option.get body) ccl imps wf in let fixrs = List.map (EConstr.ERelevance.kind sigma) fixrs in sigma, {fixnames=[recname];fixrs;fixdefs=[Some body];fixtypes=[ccl];fixctxs=[ctx];fiximps=[impls];fixntns;fixwfs=[Some wf]}, [obls], hook | {fixnames;fixrs;fixdefs;fixtypes;fixctxs;fiximps;fixntns;fixwfs} -> let fixdefs, fixtypes, obls = build_program_fixpoint env sigma rec_sign possible_guard fixnames fixrs fixdefs fixtypes fixwfs in let fixrs = List.map (EConstr.ERelevance.kind sigma) fixrs in sigma, {fixnames;fixrs;fixdefs;fixtypes;fixctxs;fiximps;fixntns;fixwfs}, obls, None let finish_regular env sigma use_inference_hook fix = let inference_hook = if use_inference_hook then Some Declare.Obls.program_inference_hook else None in let sigma = Pretyping.(solve_remaining_evars ?hook:inference_hook all_no_fail_flags env sigma) in sigma, ground_fixpoint env sigma fix, [], None let do_mutually_recursive ?pm ~refine ~program_mode ?(use_inference_hook=false) ?scope ?clearbody ~kind ~poly ?typing_flags ?user_warns ?using (rec_order, fixl) : Declare.OblState.t option * Declare.Proof.t option = let env = Global.env () in let env = Environ.update_typing_flags ?typing_flags env in let (env,rec_sign,sigma),(fix,possible_guard,udecl) = interp_mutual_definition env ~program_mode ~poly ~function_mode:false rec_order fixl in check_recursive ~kind env sigma fix; if refine then let info = Declare.Info.make ?scope ?clearbody ~kind ~poly ~udecl ?typing_flags ?user_warns ~ntns:fix.fixntns () in let cinfo = build_recthms fix in let possible_guard = (possible_guard, fix.fixrs) in let lemma = Declare.Proof.start_mutual_definitions_refine ~info ~cinfo ~bodies:fix.fixdefs ~possible_guard ?using sigma in None, Some lemma else (* Instantiate evars and check all are resolved *) let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in let sigma = Evd.minimize_universes sigma in let sigma, ({fixdefs=bodies;fixrs;fixtypes;fixwfs} as fix), obls, hook = match pm with | Some pm -> finish_obligations env sigma rec_sign possible_guard poly udecl fix | None -> finish_regular env sigma use_inference_hook fix in let info = Declare.Info.make ?scope ?clearbody ~kind ~poly ~udecl ?hook ?typing_flags ?user_warns ~ntns:fix.fixntns () in let cinfo = build_recthms fix in match pm with | Some pm -> (* Program Fixpoint struct *) let bodies = List.map Option.get bodies in Evd.check_univ_decl_early ~poly ~with_obls:true sigma udecl (bodies @ fixtypes); let sigma = if PolyFlags.univ_poly poly then sigma else Evd.fix_undefined_variables sigma in let uctx = Evd.ustate sigma in (* FIXME? something should probably be done with sigma's side-effects here *) (match fixwfs, bodies, cinfo, obls with | [Some _], [body], [cinfo], [obls] -> (* Program Fixpoint wf/measure *) let pm = Declare.Obls.add_definition ~pm ~cinfo ~info ~opaque:false ~body ~uctx ?using obls in Some pm, None | _ -> let possible_guard = (possible_guard, fixrs) in Some (Declare.Obls.add_mutual_definitions ~pm ~cinfo ~info ~opaque:false ~uctx ~bodies ~possible_guard ?using obls), None) | None -> match Option.List.map (fun x -> x) bodies with | Some bodies -> let uctx = Evd.ustate sigma in let eff = Evd.eval_side_effects sigma in (* All bodies are defined *) let possible_guard = (possible_guard, fixrs) in let _ : GlobRef.t list = Declare.declare_mutual_definitions ~cinfo ~info ~opaque:false ~eff ~uctx ~possible_guard ~bodies ?using () in None, None | None -> (* At least one undefined body *) Evd.check_univ_decl_early ~poly ~with_obls:false sigma udecl (Option.List.flatten bodies @ fixtypes); let possible_guard = (possible_guard, fixrs) in let lemma = Declare.Proof.start_mutual_definitions ~info ~cinfo ~bodies ~possible_guard ?using sigma in None, Some lemma rocq-9.2.0/vernac/comFixpoint.mli000066400000000000000000000046601516144147600167650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* refine:bool (* [refine] means definitions are allowed to have holes *) -> program_mode:bool (* [program_mode] means here: - a special treatment of subsets in pretyping - a special treatment of type class inference in pretyping - if a wf/measure fixpoint, encapsulation under a combinator (in which case, it requires [pm]) Note: for turning unresolved evars into obligations, set also [pm] *) -> ?use_inference_hook:bool (* Tell to try the obligation tactic to solve evars *) -> ?scope:Locality.definition_scope (* Local or Global visibility *) -> ?clearbody:bool (* Hide body if in sections *) -> kind:Decls.logical_kind (* Logical kind: Theorem, Definition, Fixpoint, etc.*) -> poly:PolyFlags.t (* Use universe /sort polymorphism and cumulativity *) -> ?typing_flags:Declarations.typing_flags -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf (* Warnings and deprecations *) -> ?using:Vernacexpr.section_subset_expr (* Tell which section variables to use *) -> recursives_expr -> Declare.OblState.t option * Declare.Proof.t option (* Returns open obligations and open proof, if any *) (************************************************************************) (** Internal API *) (************************************************************************) (** Exported for Funind *) val interp_fixpoint_short : Constrexpr.fixpoint_order_expr option list -> recursive_expr_gen list -> Constr.types list * Evd.evar_map rocq-9.2.0/vernac/comHints.ml000066400000000000000000000121511516144147600160730ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (a, b) | _ -> assert false in let p = if l2r then lib_ref "core.iff.proj1" else lib_ref "core.iff.proj2" in let sigma, p = Evd.fresh_global env sigma p in let c = Reductionops.whd_beta env sigma (mkApp (c, Context.Rel.instance mkRel 0 sign)) in let c = it_mkLambda_or_LetIn (mkApp ( p , [| mkArrow a ERelevance.relevant (Vars.lift 1 b) ; mkArrow b ERelevance.relevant (Vars.lift 1 a) ; c |] )) sign in let name = Nameops.add_suffix (Nametab.basename_of_global gr) ("_proj_" ^ if l2r then "l2r" else "r2l") in let ctx = Evd.univ_entry ~poly sigma in let c = EConstr.to_constr sigma c in let cb = Declare.(DefinitionEntry (definition_entry ~univs:ctx ~opaque:false c)) in let c = Declare.declare_constant ~local:Locality.ImportDefaultBehavior ~name ~kind:Decls.(IsDefinition Definition) cb in let info = {Typeclasses.hint_priority = pri; hint_pattern = None} in (info, true, GlobRef.ConstRef c) (* Only error when we have to (axioms may be instantiated if from functors) XXX maybe error if not from a functor argument? *) let soft_evaluable = Tacred.soft_evaluable_of_global_reference (* Slightly more lenient global hint syntax for backwards compatibility *) let rectify_hint_constr h = match h with | Vernacexpr.HintsReference qid -> Some qid | Vernacexpr.HintsConstr c -> let open Constrexpr in match c.CAst.v with | CAppExpl ((qid, None), []) -> Some qid | _ -> None let interp_hints ~poly h = let env = Global.env () in let sigma = Evd.from_env env in let fref r = let gr = Smartlocate.global_with_alias r in Dumpglob.add_glob ?loc:r.CAst.loc gr; gr in let fr r = soft_evaluable ?loc:r.CAst.loc (fref r) in let fi c = match rectify_hint_constr c with | Some c -> Smartlocate.global_with_alias c | None -> CErrors.user_err (Pp.strbrk "Declaring arbitrary terms as hints is forbidden. You must declare a \ toplevel constant instead.") in let fp = Constrintern.interp_constr_pattern env sigma in let fres (info, b, r) = let gr = fi r in let info = { info with Typeclasses.hint_pattern = Option.map fp info.Typeclasses.hint_pattern } in (info, b, gr) in let open Hints in let open Vernacexpr in let ft = function | HintsVariables -> HintsVariables | HintsConstants -> HintsConstants | HintsProjections -> HintsProjections | HintsReferences lhints -> HintsReferences (List.map fr lhints) in let fp = Constrintern.interp_constr_pattern (Global.env ()) in match h with | HintsResolve lhints -> HintsResolveEntry (List.map fres lhints) | HintsResolveIFF (l2r, lc, n) -> HintsResolveEntry (List.map (project_hint ~poly n l2r) lc) | HintsImmediate lhints -> HintsImmediateEntry (List.map fi lhints) | HintsUnfold lhints -> HintsUnfoldEntry (List.map fr lhints) | HintsTransparency (t, b) -> HintsTransparencyEntry (ft t, b) | HintsMode (r, l) -> HintsModeEntry (fref r, l) | HintsConstructors lqid -> let constr_hints_of_ind qid = let ind = Smartlocate.global_inductive_with_alias qid in Dumpglob.dump_reference ?loc:qid.CAst.loc "<>" (Libnames.string_of_qualid qid) "ind"; List.init (Inductiveops.nconstructors env ind) (fun i -> let c = (ind, i + 1) in let gr = GlobRef.ConstructRef c in ( empty_hint_info , true , gr )) in HintsResolveEntry (List.flatten (List.map constr_hints_of_ind lqid)) | HintsExtern (pri, patcom, tacexp) -> let pat = Option.map (fp sigma) patcom in let ltacvars = match pat with None -> Id.Set.empty | Some (l, _) -> l in let tacexp = Gentactic.intern ~ltacvars env tacexp in HintsExternEntry ({Typeclasses.hint_priority = Some pri; hint_pattern = pat}, tacexp) rocq-9.2.0/vernac/comHints.mli000066400000000000000000000013661516144147600162520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Vernacexpr.hints_expr -> Hints.hints_entry rocq-9.2.0/vernac/comInductive.ml000066400000000000000000001173561516144147600167550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.(strbrk "Automatically declaring " ++ Id.print id ++ strbrk " as template polymorphic. Use attributes or " ++ strbrk "disable Auto Template Polymorphism to avoid this warning.")) let should_auto_template = let open Goptions in let auto = ref true in let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Auto";"Template";"Polymorphism"]; optread = (fun () -> !auto); optwrite = (fun b -> auto := b); } in fun id would_auto -> let b = !auto && would_auto in if b then warn_auto_template id; b let push_types env idl rl tl = List.fold_left3 (fun env id r t -> EConstr.push_rel (LocalAssum (make_annot (Name id) r,t)) env) env idl rl tl type structured_one_inductive_expr = { ind_name : Id.t; ind_arity_explicit : bool; ind_arity : constr_expr; ind_lc : (Id.t * constr_expr) list } exception Same of Id.t let check_all_names_different env indl = let rec elements = function | [] -> Id.Set.empty | id :: l -> let s = elements l in if Id.Set.mem id s then raise (Same id) else Id.Set.add id s in let ind_names = List.map (fun ind -> ind.ind_name) indl in let cstr_names = List.map_append (fun ind -> List.map fst ind.ind_lc) indl in let ind_names = match elements ind_names with | s -> s | exception (Same t) -> raise (InductiveError (env, SameNamesTypes t)) in let cstr_names = match elements cstr_names with | s -> s | exception (Same c) -> raise (InductiveError (env, SameNamesConstructors c)) in let l = Id.Set.inter ind_names cstr_names in if not (Id.Set.is_empty l) then raise (InductiveError (env, SameNamesOverlap (Id.Set.elements l))) (** Make the arity conclusion flexible to avoid generating an upper bound universe now, only if the universe does not appear anywhere else. This is really a hack to stay compatible with the semantics of template polymorphic inductives which are recognized when a "Type" appears at the end of the conlusion in the source syntax. *) let rec check_type_conclusion ind = let open Glob_term in match DAst.get ind with | GSort s -> (* not sure what this check is expected to be exactly *) begin match s with | (None, UAnonymous {rigid=UnivRigid}) -> (* should have been made flexible *) assert false | (None, UAnonymous {rigid=UnivFlexible _}) -> false | _ -> true end | GProd (_, _, _, _, e) | GLetIn (_, _, _, _, e) -> check_type_conclusion e | _ -> false let rec make_anonymous_conclusion_flexible ind = let open Glob_term in match DAst.get ind with | GSort (None, UAnonymous {rigid=UnivRigid}) -> Some (DAst.make ?loc:ind.loc (GSort (None, UAnonymous {rigid=UnivFlexible true}))) | GSort _ -> None | GProd (a, b, c, d, e) -> begin match make_anonymous_conclusion_flexible e with | None -> None | Some e -> Some (DAst.make ?loc:ind.loc (GProd (a, b, c, d, e))) end | GLetIn (a, b, c, d, e) -> begin match make_anonymous_conclusion_flexible e with | None -> None | Some e -> Some (DAst.make ?loc:ind.loc (GLetIn (a, b, c, d, e))) end | _ -> None type syntax_allows_template_poly = SyntaxAllowsTemplatePoly | SyntaxNoTemplatePoly let intern_ind_arity env sigma ind = let c = intern_gen IsType env sigma ind.ind_arity in let impls = Implicit_quantifiers.implicits_of_glob_constr ~with_products:true c in let pseudo_poly, c = match make_anonymous_conclusion_flexible c with | None -> check_type_conclusion c, c | Some c -> true, c in let template_syntax = if pseudo_poly then SyntaxAllowsTemplatePoly else SyntaxNoTemplatePoly in (constr_loc ind.ind_arity, c, impls, template_syntax) let pretype_ind_arity ~unconstrained_sorts ~poly env sigma (loc, c, impls, template_syntax) = let flags = { Pretyping.all_no_fail_flags with unconstrained_sorts ; poly } in let sigma,t = understand_tcc ~flags env sigma ~expected_type:IsType c in match Reductionops.sort_of_arity env sigma t with | exception Reduction.NotArity -> user_err ?loc (str "Not an arity") | s -> sigma, (t, Retyping.relevance_of_sort s, template_syntax, impls) (* ind_rel is the Rel for this inductive in the context without params. n is how many arguments there are in the constructor. *) let model_conclusion env sigma ind_rel params n arity_indices = let model_head = EConstr.mkRel (n + Context.Rel.length params + ind_rel) in let model_params = Context.Rel.instance EConstr.mkRel n params in let sigma,model_indices = List.fold_right (fun (_,t) (sigma, subst) -> let t = EConstr.Vars.substl subst (EConstr.Vars.liftn n (List.length subst + 1) t) in let typeclass_candidate = Typeclasses.is_maybe_class_type env sigma t in let sigma, c = Evarutil.new_evar ~typeclass_candidate env sigma t in sigma, c::subst) arity_indices (sigma, []) in sigma, mkApp (mkApp (model_head, model_params), Array.of_list (List.rev model_indices)) let interp_cstrs env (sigma, ind_rel) impls params ind arity = let cnames,ctyps = List.split ind.ind_lc in let arity_indices, cstr_sort = Reductionops.splay_arity env sigma arity in (* Interpret the constructor types *) let interp_cstr sigma ctyp = let flags = Pretyping.{ all_no_fail_flags with use_typeclasses = UseTCForConv; solve_unification_constraints = false } in let sigma, (ctyp, cimpl) = interp_type_evars_impls ~flags env sigma ~impls ctyp in let ctx, concl = Reductionops.whd_decompose_prod_decls env sigma ctyp in let concl_env = EConstr.push_rel_context ctx env in let sigma_with_model_evars, model = model_conclusion concl_env sigma ind_rel params (Context.Rel.length ctx) arity_indices in (* unify the expected with the provided conclusion *) let sigma = try Evarconv.unify concl_env sigma_with_model_evars Conversion.CONV concl model with Evarconv.UnableToUnify (sigma,e) -> user_err (Himsg.explain_pretype_error concl_env sigma (Pretype_errors.CannotUnify (concl, model, (Some e)))) in sigma, (ctyp, cimpl) in let sigma, (ctyps, cimpls) = on_snd List.split @@ List.fold_left_map interp_cstr sigma ctyps in (sigma, pred ind_rel), (cnames, ctyps, cimpls) (***** Generate constraints from constructor arguments *****) let compute_constructor_levels env evd sign = fst (List.fold_right (fun d (lev,env) -> match d with | LocalDef _ -> lev, EConstr.push_rel d env | LocalAssum _ -> let s = Retyping.get_sort_of env evd (RelDecl.get_type d) in (s :: lev, EConstr.push_rel d env)) sign ([],env)) let is_flexible_sort evd s = match ESorts.kind evd s with | Set | Prop | SProp -> false | Type u | QSort (_, u) -> match Univ.Universe.level u with | Some l -> Evd.is_flexible_level evd l | None -> false let prop_lowering_candidates evd ~arities_explicit inds = let less_than_2 = function [] | [_] -> true | _ :: _ :: _ -> false in (* handle automatic lowering to Prop We repeatedly add information about which inductives should not be Prop until no more progress can be made *) let is_prop_candidate_arity (raw_arity,(_,s),indices,ctors) = less_than_2 ctors && EConstr.isArity evd raw_arity && is_flexible_sort evd s && not (Evd.check_leq evd ESorts.set s) in let candidates = List.filter_map (fun (explicit,(_,(_,s),_,_ as ind)) -> if (not explicit) && is_prop_candidate_arity ind then Some s else None) (List.combine arities_explicit inds) in let in_candidates s candidates = List.mem_f (ESorts.equal evd) s candidates in let is_prop_candidate_size candidates (_,_,indices,ctors) = List.for_all (List.for_all (fun s -> match ESorts.kind evd s with | SProp | Prop -> true | Set -> false | Type _ | QSort _ -> not (Evd.check_leq evd ESorts.set s) && in_candidates s candidates)) (Option.List.cons indices ctors) in let rec spread_nonprop candidates = let (changed, candidates) = List.fold_left (fun (changed, candidates as acc) (raw_arity,(_,s),indices,ctors as ind) -> if is_prop_candidate_size candidates ind then acc (* still a Prop candidate *) else if in_candidates s candidates then (true, List.remove (ESorts.equal evd) s candidates) else acc) (false,candidates) inds in if changed then spread_nonprop candidates else candidates in let candidates = spread_nonprop candidates in candidates let include_constructor_argument evd ~poly ~ctor_sort ~inductive_sort = if PolyFlags.univ_poly poly then (* We ignore the quality when comparing the sorts: it has an impact on squashing in the kernel but cannot cause a universe error. *) let univ_of_sort s = match ESorts.kind evd s with | SProp | Prop -> None | Set -> Some Univ.Universe.type0 | Type u | QSort (_,u) -> Some u in match univ_of_sort ctor_sort, univ_of_sort inductive_sort with | _, None -> (* This function is only called when [s] is not impredicative *) assert false | None, Some _ -> evd | Some uctor, Some uind -> let mk u = ESorts.make (Sorts.sort_of_univ u) in Evd.set_leq_sort evd (mk uctor) (mk uind) else match ESorts.kind evd ctor_sort with | SProp | Prop -> evd | Set | Type _ | QSort _ -> Evd.set_leq_sort evd ctor_sort inductive_sort type default_dep_elim = DeclareInd.default_dep_elim = DefaultElim | PropButDepElim let inductive_levels env evd ~poly ~indnames ~arities_explicit arities ctors = let inds = List.map2 (fun x ctors -> let ctx, s = Reductionops.dest_arity env evd x in x, (ctx, s), List.map (compute_constructor_levels env evd) ctors) arities ctors in (* Inductives explicitly put in an impredicative sort can be squashed, so there are no constraints to get from them. *) let is_impredicative_sort evd s = is_impredicative_sort env (ESorts.kind evd s) in (* Inductives with >= 2 constructors are >= Set *) let less_than_2 = function [] | [_] -> true | _ :: _ :: _ -> false in let evd = List.fold_left (fun evd (raw_arity,(_,s),ctors) -> if less_than_2 ctors || is_impredicative_sort evd s then evd else (* >=2 constructors is like having a bool argument *) include_constructor_argument evd ~poly ~ctor_sort:ESorts.set ~inductive_sort:s) evd inds in (* If indices_matter, the index telescope acts like an extra constructor except for constructor count checks. *) let inds = List.map (fun (raw_arity,(ctx,_ as arity),ctors) -> let indices = if indices_matter env then Some (compute_constructor_levels env evd ctx) else None in (raw_arity,arity,indices,ctors)) inds in let candidates = prop_lowering_candidates evd ~arities_explicit inds in (* Do the lowering. We forget about the generated universe for the lowered inductive and rely on universe restriction to get rid of it. NB: it would probably be less hacky to use the sort polymorphism system ie lowering to Prop by setting a qvar equal to prop. However this means we wouldn't lower "Inductive foo : Type := ." as "Type" doesn't produce a qvar. Perhaps someday we can stop lowering these explicit ": Type". *) let inds = List.map3 (fun na explicit (raw_arity,(ctx,s),indices,ctors) -> if List.mem_f (ESorts.equal evd) s candidates then (* NB: is_prop_candidate requires is_flexible_sort so in this branch we know s <> Prop *) ((PropButDepElim, mkArity (ctx, ESorts.prop)),ESorts.prop,indices,ctors) else ((DefaultElim, raw_arity), s, indices, ctors)) indnames arities_explicit inds in (* Add constraints from constructor arguments and indices. We must do this after Prop lowering as otherwise we risk unifying sorts eg on "Box (A:Type)" we risk unifying the parameter sort and the output sort then ESorts.equal would make us believe that the constructor argument is a lowering candidate. *) let evd = List.fold_left (fun evd (_,s,indices,ctors) -> if is_impredicative_sort evd s then evd else List.fold_left (List.fold_left (fun evd ctor_sort -> include_constructor_argument evd ~poly ~ctor_sort ~inductive_sort:s)) evd (Option.List.cons indices ctors)) evd inds in let arities = List.map (fun (arity,_,_,_) -> arity) inds in evd, List.split arities (** Template poly ***) let check_named {CAst.loc;v=na} = match na with | Name _ -> () | Anonymous -> let msg = str "Parameters must be named." in user_err ?loc msg let get_template_binding_arity sigma c = let decls, c = EConstr.decompose_prod_decls sigma c in match EConstr.kind sigma c with | Sort s -> begin match ESorts.kind sigma s with | Type u -> begin match Univ.Universe.level u with | Some l -> Some (decls, None, l) | None -> None end | QSort (q,u) -> begin match Univ.Universe.level u with | Some l -> if Univ.Level.is_set l then None else Some (decls, Some q, l) | None -> None end | _ -> None end | _ -> None let non_template_levels sigma ~params ~arity ~constructors = let (let+) x f = Result.map f x in let ctx, u = EConstr.destArity sigma arity in (* locally making the conclusion qvar above_prop means its appearances in relevance marks aren't counted *) let+ sigma = match ESorts.kind sigma u with | QSort (q, _) -> if Sorts.QVar.is_unif q then Ok (Evd.set_above_prop sigma (QVar q)) else Error "Cannot handle template polymorphism when the conclusion is a global sort." | _ -> Ok sigma in let add_levels c levels = EConstr.universes_of_constr sigma ~init:levels c in let levels = Sorts.QVar.Set.empty, Univ.Level.Set.empty in let fold_params levels = function | LocalDef (_, b, t) -> add_levels b (add_levels t levels) | LocalAssum (_, t) -> match get_template_binding_arity sigma t with | None -> add_levels t levels | Some (decls, _, _) -> add_levels (EConstr.it_mkProd_or_LetIn EConstr.mkProp decls) levels in (* Levels in LocalDef params, on the left of the context in LocalAssum params, in the indices and in the constructor types are not allowed to be template. (partly to guarantee Irrelevant variance, and partly to simplify universe substitution code) *) let levels = List.fold_left fold_params levels params in let levels = add_levels (EConstr.mkArity (ctx,ESorts.prop)) levels in let levels = List.fold_left (fun levels c -> add_levels c levels) levels constructors in let qvars, ulevels = levels in (* levels with nonzero increment in the conclusion may not be template (until constraint checking can handle arbitrary +k, cf #19230) *) let concl_univs = match ESorts.kind sigma u with | QSort (_,u) | Sorts.Type u -> Univ.Universe.repr u | SProp | Prop | Set -> [] in let ulevels = List.fold_left (fun ulevels (u,n) -> if Int.equal n 0 then ulevels else Univ.Level.Set.add u ulevels) ulevels concl_univs in qvars, ulevels type linearity = Linear of Sorts.QVar.t option | NonLinear let pseudo_sort_poly ~non_template_qvars ~template_univs sigma params arity = (* to be pseudo sort poly, every univ in the conclusion must be bound at a free quality *) (* XXX maybe should be anomaly (ie directly call destArity) *) if not @@ isArity sigma arity then None else let ctx, s = destArity sigma arity in match ESorts.kind sigma s with | SProp | Prop | Set -> None | QSort (q,u) -> if not (Sorts.QVar.Set.mem q non_template_qvars) && Univ.Universe.for_all (fun (u,_) -> match Univ.Level.Map.find_opt u template_univs with | None | Some None -> false | Some (Some q') -> QVar.equal q q') u then Some q else None | Type u -> None let unbounded_from_below u cstrs = let open Univ in UnivConstraints.for_all (fun (l, d, r) -> match d with | UnivConstraint.Eq | UnivConstraint.Lt -> not (Level.equal l u) && not (Level.equal r u) | UnivConstraint.Le -> not (Level.equal r u)) cstrs (* Returns the list [x_1, ..., x_n] of levels contributing to template polymorphism. The elements x_k is None if the k-th parameter (starting from the most recent and ignoring let-definitions) is not template or is Some u_k if its level is u_k and is template. *) let template_polymorphic_univs sigma ~params ~arity ~constructors = let (let+) x f = Result.map f x in let+ non_template_qvars, non_template_levels = non_template_levels sigma ~params ~arity ~constructors in let fold_params accu decl = match decl with | LocalAssum (_, p) -> begin match get_template_binding_arity sigma p with | Some (_, qopt, l) -> Univ.Level.Map.update l (function None -> Some (Linear qopt) | Some _ -> Some NonLinear) accu | None -> accu end | LocalDef _ -> accu in let paramslevels = List.fold_left fold_params Univ.Level.Map.empty params in let template_univs = (* already minimized and restricted *) let uctx = Evd.universe_context_set sigma in Univ.Level.Map.filter (fun u -> function | NonLinear -> false | Linear _ -> assert (not @@ Univ.Level.is_set u); Univ.Level.Set.mem u (fst uctx) && unbounded_from_below u (snd uctx) && not (Univ.Level.Set.mem u non_template_levels)) paramslevels in let template_univs = Univ.Level.Map.map (function | NonLinear -> assert false | Linear qopt -> qopt) template_univs in let pseudo_sort_poly = pseudo_sort_poly ~non_template_qvars ~template_univs sigma params arity in let template_univs = Univ.Level.Map.domain template_univs in pseudo_sort_poly, template_univs let split_universe_context subset (univs, univ_csts) = let rem = Univ.Level.Set.diff univs subset in let subfilter (l, _, r) = let () = assert (not @@ Univ.Level.Set.mem r subset) in Univ.Level.Set.mem l subset in let subcst, remcst = Univ.UnivConstraints.partition subfilter univ_csts in (subset, subcst), (rem, remcst) let warn_no_template_universe = CWarnings.create ~name:"no-template-universe" (fun () -> Pp.str "This inductive type has no template universes.") type should_template = | MaybeTemplate of { force_template : bool; } | NotTemplate let nontemplate_univ_entry ~poly sigma udecl = let sigma = Evd.collapse_sort_variables sigma in let uentry, _ as ubinders = Evd.check_univ_decl ~poly sigma udecl in let uentry, global = match uentry with | UState.Polymorphic_entry uctx -> Polymorphic_ind_entry uctx, Univ.ContextSet.empty | UState.Monomorphic_entry uctx -> Monomorphic_ind_entry, uctx in sigma, uentry, ubinders, global let template_univ_entry sigma udecl ~template_univs pseudo_sort_poly = let template_qvars = match pseudo_sort_poly with | Some q -> QVar.Set.singleton q | None -> QVar.Set.empty in let sigma = Evd.collapse_sort_variables ~except:template_qvars sigma in let sigma = QVar.Set.fold (fun q sigma -> Evd.set_above_prop sigma (QVar q)) template_qvars sigma in let uctx = UState.check_template_univ_decl (Evd.ustate sigma) ~template_qvars udecl in let ubinders = UState.Monomorphic_entry uctx, Evd.universe_binders sigma in let template_univs, global = split_universe_context template_univs uctx in let uctx = UVars.UContext.of_context_set (UState.compute_instance_binders @@ Evd.ustate sigma) ((template_qvars, Sorts.ElimConstraints.empty), template_univs) in let default_univs = let inst = UVars.UContext.instance uctx in let qs, us = UVars.Instance.to_array inst in UVars.Instance.of_array (Array.map (fun _ -> Quality.qtype) qs, us) in sigma, Template_ind_entry {uctx; default_univs}, ubinders, global let should_template ~user_template ~poly = match user_template, PolyFlags.univ_poly poly with | Some true, true -> user_err Pp.(strbrk "Template-polymorphism and universe polymorphism are not compatible.") | Some false, _ | None, true -> NotTemplate | Some true, false -> MaybeTemplate { force_template = true; } | None, false -> MaybeTemplate { force_template = false; } let inductive_univs sigma ~user_template ~poly udecl ~indnames ~ctx_params ~arities ~constructors template_syntax = match should_template ~user_template ~poly with | NotTemplate -> nontemplate_univ_entry ~poly sigma udecl | MaybeTemplate { force_template; } -> let info = match List.combine3 arities constructors template_syntax with | [arity, (_cnames, constructors), SyntaxAllowsTemplatePoly] -> template_polymorphic_univs sigma ~params:ctx_params ~arity ~constructors | [_, _, SyntaxNoTemplatePoly] -> Error "Template polymorphism needs a syntactic sort for the inductive's conclusion." | _ :: _ :: _ -> Error "Template-polymorphism not allowed with mutual inductives." | [] -> assert false in match info, force_template with | Error _, false -> nontemplate_univ_entry ~poly sigma udecl | Error msg, true -> CErrors.user_err Pp.(str msg) | Ok (pseudo_sort_poly, template_univs), _ -> let has_template = not @@ Univ.Level.Set.is_empty template_univs in if force_template || should_auto_template (List.hd indnames) has_template then let () = if not has_template then warn_no_template_universe () in template_univ_entry sigma udecl ~template_univs pseudo_sort_poly else nontemplate_univ_entry ~poly sigma udecl let check_param = function | CLocalDef (na, _, _, _) -> check_named na | CLocalAssum (nas, _, Default _, _) -> List.iter check_named nas | CLocalAssum (nas, _, Generalized _, _) -> () | CLocalPattern {CAst.loc} -> Loc.raise ?loc (Gramlib.Grammar.ParseError "pattern with quote not allowed here") let restrict_inductive_universes sigma ctx_params arities constructors = let merge_universes_of_constr c acc = Univ.Level.Set.union acc (snd (EConstr.universes_of_constr sigma c)) in let uvars = Univ.Level.Set.empty in let uvars = List.fold_left (fun acc d -> Context.Rel.Declaration.fold_constr merge_universes_of_constr d acc) uvars ctx_params in let uvars = List.fold_right merge_universes_of_constr arities uvars in let uvars = List.fold_right (fun (_,ctypes) -> List.fold_right merge_universes_of_constr ctypes) constructors uvars in Evd.restrict_universe_context sigma uvars let check_trivial_variances variances = Array.iter (function | None | Some UVars.Variance.Invariant -> () | Some _ -> CErrors.user_err Pp.(strbrk "Universe variance was specified but this inductive will not be cumulative.")) variances let variance_of_entry ~cumulative ~variances uctx = match uctx with | Monomorphic_ind_entry | Template_ind_entry _ -> check_trivial_variances variances; None | Polymorphic_ind_entry uctx -> if not cumulative then begin check_trivial_variances variances; None end else let lvs = Array.length variances in let _, lus = UVars.UContext.size uctx in assert (lvs <= lus); Some (Array.append variances (Array.make (lus - lvs) None)) let interp_mutual_inductive_constr ~sigma ~flags ~udecl ~variances ~ctx_params ~indnames ~arities_explicit ~arities ~template_syntax ~constructors ~env_ar ~private_ind = let { poly; template; finite; } = flags in let env_ar_params = EConstr.push_rel_context ctx_params env_ar in (* Compute renewed arities *) let ctor_args = List.map (fun (_,tys) -> List.map (fun ty -> let ctx = fst (Reductionops.whd_decompose_prod_decls env_ar_params sigma ty) in ctx) tys) constructors in let sigma, (default_dep_elim, arities) = inductive_levels env_ar_params sigma ~poly ~indnames ~arities_explicit arities ctor_args in (* we must minimize before inferring template info. For instance before minimization "option" is "option : Type@{u} -> Type@{v}" with "u <= v". We want to produce "Type@{u} -> Type@{u}" with "u" template poly. Minimization is what gives us "u = v". We also need to restrict to avoid seeing spurious bounds from below (ie v <= template_u with v getting restricted away). *) let sigma = Evd.minimize_universes ~collapse_sort_variables:false sigma in let sigma = restrict_inductive_universes sigma ctx_params arities constructors in let sigma, univ_entry, ubinders, global_univs = inductive_univs sigma ~user_template:template ~poly udecl ~indnames ~ctx_params ~arities ~constructors template_syntax in (* evar-normalize *) let arities = List.map EConstr.(to_constr sigma) arities in let constructors = List.map (on_snd (List.map (EConstr.to_constr sigma))) constructors in let ctx_params = List.map (fun d -> EConstr.to_rel_decl sigma d) ctx_params in (* Build the inductive entries *) let entries = List.map3 (fun indname arity (cnames,ctypes) -> { mind_entry_typename = indname; mind_entry_arity = arity; mind_entry_consnames = cnames; mind_entry_lc = ctypes }) indnames arities constructors in let variance = variance_of_entry ~cumulative:(PolyFlags.cumulative poly) ~variances univ_entry in (* Build the mutual inductive entry *) let mind_ent = { mind_entry_params = ctx_params; mind_entry_record = None; mind_entry_finite = finite; mind_entry_inds = entries; mind_entry_private = if private_ind then Some false else None; mind_entry_universes = univ_entry; mind_entry_variance = variance; } in default_dep_elim, mind_ent, ubinders, global_univs let interp_params ~unconstrained_sorts env udecl uparamsl paramsl = let sigma, udecl, variances = interp_cumul_univ_decl_opt env udecl in let sigma, (uimpls, ((env_uparams, ctx_uparams), useruimpls, _locs)) = interp_context_evars ~program_mode:false ~unconstrained_sorts env sigma uparamsl in let sigma, (impls, ((env_params, ctx_params), userimpls, _locs)) = interp_context_evars ~program_mode:false ~unconstrained_sorts ~impl_env:uimpls env_uparams sigma paramsl in (* Names of parameters as arguments of the inductive type (defs removed) *) sigma, env_params, (ctx_params, env_uparams, ctx_uparams, userimpls, useruimpls, impls, udecl, variances) (* When a hole remains for a param, pretend the param is uniform and do the unification. [env_ar_par] is [uparams; inds; params] *) let maybe_unify_params_in env_ar_par sigma ~ninds ~nparams ~binders:k c = let is_ind sigma k c = match EConstr.kind sigma c with | Constr.Rel n -> (* env is [uparams; inds; params; k other things] *) n > k + nparams && n <= k + nparams + ninds | _ -> false in let rec aux (env,k as envk) sigma c = match EConstr.kind sigma c with | Constr.App (h,args) when is_ind sigma k h -> Array.fold_left_i (fun i sigma arg -> if i >= nparams || not (EConstr.isEvar sigma arg) then sigma else begin try Evarconv.unify_delay env sigma arg (EConstr.mkRel (k+nparams-i)) with Evarconv.UnableToUnify _ -> (* ignore errors, we will get a "Cannot infer ..." error instead *) sigma end) sigma args | _ -> Termops.fold_constr_with_full_binders env sigma (fun d (env,k) -> EConstr.push_rel d env, k+1) aux envk sigma c in aux (env_ar_par,k) sigma c let interp_mutual_inductive_gen env0 ~flags udecl (uparamsl,paramsl,indl) notations ~private_ind = check_all_names_different env0 indl; List.iter check_param paramsl; if not (List.is_empty uparamsl) && not (List.is_empty notations) then user_err (str "Inductives with uniform parameters may not have attached notations."); let indnames = List.map (fun ind -> ind.ind_name) indl in let ninds = List.length indl in (* In case of template polymorphism, we need to compute more constraints *) let unconstrained_sorts = not (PolyFlags.univ_poly flags.poly) in let sigma, env_params, (ctx_params, env_uparams, ctx_uparams, userimpls, useruimpls, impls, udecl, variances) = interp_params ~unconstrained_sorts env0 udecl uparamsl paramsl in (* Interpret the arities *) let arities = List.map (intern_ind_arity env_params sigma) indl in let sigma, arities = List.fold_left_map (pretype_ind_arity ~unconstrained_sorts ~poly:flags.poly env_params) sigma arities in let arities, relevances, template_syntax, indimpls = List.split4 arities in let lift_ctx n ctx = let t = EConstr.it_mkProd_or_LetIn EConstr.mkProp ctx in let t = EConstr.Vars.lift n t in let ctx, _ = EConstr.decompose_prod_decls sigma t in ctx in let ctx_params_lifted, fullarities = lift_ctx ninds ctx_params, CList.map_i (fun i c -> EConstr.Vars.lift i (EConstr.it_mkProd_or_LetIn c ctx_params)) 0 arities in let env_ar = push_types env_uparams indnames relevances fullarities in let env_ar_params = EConstr.push_rel_context ctx_params_lifted env_ar in (* Compute interpretation metadatas *) let indimpls = List.map (fun impls -> userimpls @ impls) indimpls in let impls = compute_internalization_env env_uparams sigma ~impls Inductive indnames fullarities indimpls in let ntn_impls = compute_internalization_env env_uparams sigma Inductive indnames fullarities indimpls in let (sigma, _), constructors = Metasyntax.with_syntax_protection (fun () -> (* Temporary declaration of notations and scopes *) List.iter (Metasyntax.set_notation_for_interpretation env_params ntn_impls) notations; (* Interpret the constructor types *) List.fold_left2_map (fun (sigma, ind_rel) ind arity -> interp_cstrs env_ar_params (sigma, ind_rel) impls ctx_params_lifted ind (EConstr.Vars.liftn ninds (Rel.length ctx_params + 1) arity)) (sigma, ninds) indl arities) () in let nparams = Context.Rel.length ctx_params in let sigma = List.fold_left (fun sigma (_,ctyps,_) -> List.fold_left (fun sigma ctyp -> maybe_unify_params_in env_ar_params sigma ~ninds ~nparams ~binders:0 ctyp) sigma ctyps) sigma constructors in (* generalize over the uniform parameters *) let nuparams = Context.Rel.length ctx_uparams in let uargs = Context.Rel.instance EConstr.mkRel 0 ctx_uparams in let uparam_subst = List.init ninds EConstr.(fun i -> mkApp (mkRel (i + 1 + nuparams), uargs)) @ List.init nuparams EConstr.(fun i -> mkRel (i + 1)) in let generalize_constructor c = EConstr.Vars.substnl uparam_subst nparams c in let cimpls = List.map pi3 constructors in let constructors = List.map (fun (cnames,ctypes,cimpls) -> (cnames,List.map generalize_constructor ctypes)) constructors in let ctx_params = ctx_params @ ctx_uparams in let userimpls = useruimpls @ userimpls in let indimpls = List.map (fun iimpl -> useruimpls @ iimpl) indimpls in let fullarities = List.map (fun c -> EConstr.it_mkProd_or_LetIn c ctx_uparams) fullarities in let env_ar = push_types env0 indnames relevances fullarities in (* Try further to solve evars, and instantiate them *) let sigma = solve_remaining_evars all_and_fail_flags env_params sigma in let impls = List.map2 (fun indimpls cimpls -> indimpls, List.map (fun impls -> userimpls @ impls) cimpls) indimpls cimpls in let arities_explicit = List.map (fun ar -> ar.ind_arity_explicit) indl in let default_dep_elim, mie, binders, ctx = interp_mutual_inductive_constr ~flags ~sigma ~ctx_params ~udecl ~variances ~arities_explicit ~arities ~template_syntax ~constructors ~env_ar ~private_ind ~indnames in (default_dep_elim, mie, binders, impls, ctx) (* Very syntactical equality *) let eq_local_binders bl1 bl2 = List.equal local_binder_eq bl1 bl2 let eq_params (up1,p1) (up2,p2) = eq_local_binders up1 up2 && Option.equal eq_local_binders p1 p2 let extract_coercions indl = let mkqid (_,({CAst.v=id},_)) = qualid_of_ident id in let iscoe (_, coe, inst) = match inst with | Vernacexpr.NoInstance -> coe = Vernacexpr.AddCoercion | _ -> user_err (Pp.str "'::' not allowed in inductives.") in let extract lc = List.filter (fun (coe,_) -> iscoe coe) lc in List.map mkqid (List.flatten(List.map (fun (_,_,_,lc) -> extract lc) indl)) exception DifferingParams of string (* inductive or record *) * (Id.t * Vernacexpr.inductive_params_expr) * (Id.t * Vernacexpr.inductive_params_expr) let explain_differing_params kind (ind,p) (ind',p') = let pr_params = function | ([],None) -> str "no parameters" | (up,p) -> let env = Global.env() in let sigma = Evd.from_env env in let pr_binders = Ppconstr.pr_binders ~flags:(Ppconstr.current_flags()) env sigma in str "parameters" ++ spc() ++ hov 1 (quote (pr_binders up ++ pr_opt (fun p -> str "|" ++ spc() ++ pr_binders p) p)) in v 0 (str "Parameters should be syntactically the same for each " ++ str kind ++ str " type." ++ spc() ++ hov 0 (str "Type " ++ quote (Id.print ind) ++ str " has " ++ pr_params p) ++ spc() ++ hov 0 (str "but type " ++ quote (Id.print ind') ++ str " has " ++ pr_params p') ++ str ".") let () = CErrors.register_handler (function | DifferingParams (kind, a, b) -> Some (explain_differing_params kind a b) | _ -> None) let error_differing_params ~kind (ind,p) (ind',p') = Loc.raise ?loc:ind'.CAst.loc (DifferingParams (kind, (ind.CAst.v,p), (ind'.CAst.v,p'))) let extract_params indl = match indl with | [] -> anomaly (Pp.str "empty list of inductive types.") | (ind,params,_,_)::rest -> match List.find_opt (fun (_,p',_,_) -> not @@ eq_params params p') rest with | None -> params | Some (ind',p',_,_) -> error_differing_params ~kind:"inductive" (ind,params) (ind',p') let extract_inductive indl = List.map (fun ({CAst.v=indname},_,ar,lc) -> { ind_name = indname; ind_arity_explicit = Option.has_some ar; ind_arity = Option.default (CAst.make @@ CSort Constrexpr_ops.expr_Type_sort) ar; ind_lc = List.map (fun (_,({CAst.v=id},t)) -> (id,t)) lc }) indl let extract_mutual_inductive_declaration_components indl = let indl,ntnl = List.split indl in let params = extract_params indl in let coes = extract_coercions indl in let indl = extract_inductive indl in (params,indl), coes, List.flatten ntnl type uniform_inductive_flag = | UniformParameters | NonUniformParameters module Mind_decl = struct type t = { mie : Entries.mutual_inductive_entry; default_dep_elim : default_dep_elim list; nuparams : int option; univ_binders : UState.named_universes_entry; implicits : DeclareInd.one_inductive_impls list; uctx : Univ.ContextSet.t; where_notations : Metasyntax.notation_interpretation_decl list; coercions : Libnames.qualid list; indlocs : DeclareInd.indlocs; } end let rec count_binder_expr = function | [] -> 0 | CLocalAssum(l,_,_,_) :: rest -> List.length l + count_binder_expr rest | CLocalDef _ :: rest -> 1 + count_binder_expr rest | CLocalPattern {CAst.loc} :: _ -> Loc.raise ?loc (Gramlib.Grammar.ParseError "pattern with quote not allowed here") let interp_mutual_inductive ~env ~flags ?typing_flags udecl indl ~private_ind ~uniform = let indlocs = List.map (fun ((n,_,_,constructors),_) -> let conslocs = List.map (fun (_,(c,_)) -> c.CAst.loc) constructors in n.CAst.loc, conslocs) indl in let (params,indl),coercions,ntns = extract_mutual_inductive_declaration_components indl in let where_notations = List.map Metasyntax.prepare_where_notation ntns in (* Interpret the types *) let indl, nuparams = match params with | uparams, Some params -> (uparams, params, indl), Some (count_binder_expr params) | params, None -> match uniform with | UniformParameters -> (params, [], indl), Some 0 | NonUniformParameters -> ([], params, indl), None in let env = Environ.update_typing_flags ?typing_flags env in let default_dep_elim, mie, univ_binders, implicits, uctx = interp_mutual_inductive_gen ~flags env udecl indl where_notations ~private_ind in let open Mind_decl in { mie; default_dep_elim; nuparams; univ_binders; implicits; uctx; where_notations; coercions; indlocs } let do_mutual_inductive ~flags ?typing_flags udecl indl ~private_ind ~uniform = let open Mind_decl in let env = Global.env () in let { mie; default_dep_elim; univ_binders; implicits; uctx; where_notations; coercions; indlocs} = interp_mutual_inductive ~flags ~env udecl indl ?typing_flags ~private_ind ~uniform in (* Declare the global universes *) let () = Global.push_context_set uctx in (* Declare the mutual inductive block with its associated schemes *) ignore (DeclareInd.declare_mutual_inductive_with_eliminations ~default_dep_elim ?typing_flags ~indlocs mie univ_binders implicits ~schemes:flags.schemes); (* Declare the possible notations of inductive types *) List.iter (Metasyntax.add_notation_interpretation ~local:false (Global.env ())) where_notations; (* Declare the coercions *) List.iter (fun qid -> ComCoercion.try_add_new_coercion (Nametab.locate qid) ~local:false ~reversible:true) coercions (** Prepare a "match" template for a given inductive type. For each branch of the match, we list the constructor name followed by enough pattern variables. [Not_found] is raised if the given string isn't the qualid of a known inductive type. *) (* HH notes in PR #679: The Show Match could also be made more robust, for instance in the presence of let in the branch of a constructor. A decompose_prod_decls would probably suffice for that, but then, it is a Context.Rel.Declaration.t which needs to be matched and not just a pair (name,type). Otherwise, this is OK. After all, the API on inductive types is not so canonical in general, and in this simple case, working at the low-level of mind_nf_lc seems reasonable (compared to working at the higher-level of Inductiveops). *) let make_cases ind = let open Declarations in let mib, mip = Global.lookup_inductive ind in Util.Array.fold_right_i (fun i (ctx, _) l -> let al = Util.List.skipn (List.length mib.mind_params_ctxt) (List.rev ctx) in let rec rename avoid = function | [] -> [] | RelDecl.LocalDef _ :: l -> "_" :: rename avoid l | RelDecl.LocalAssum (n, _)::l -> let n' = Namegen.next_name_away_with_default (Id.to_string Namegen.default_dependent_ident) n.Context.binder_name avoid in Id.to_string n' :: rename (Id.Set.add n' avoid) l in let al' = rename Id.Set.empty al in let consref = GlobRef.ConstructRef (ith_constructor_of_inductive ind (i + 1)) in (Libnames.string_of_qualid (Nametab.shortest_qualid_of_global Id.Set.empty consref) :: al') :: l) mip.mind_nf_lc [] module Internal = struct let error_differing_params = error_differing_params end rocq-9.2.0/vernac/comInductive.mli000066400000000000000000000110341516144147600171100ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ?typing_flags:Declarations.typing_flags -> cumul_univ_decl_expr option -> (one_inductive_expr * notation_declaration list) list -> private_ind:bool -> uniform:uniform_inductive_flag -> unit (** User-interface API *) (** Prepare a "match" template for a given inductive type. For each branch of the match, we list the constructor name followed by enough pattern variables. [Not_found] is raised if the given string isn't the qualid of a known inductive type. *) val make_cases : Names.inductive -> string list list module Mind_decl : sig (** inductive_expr at the constr level *) type t = { mie : Entries.mutual_inductive_entry; default_dep_elim : DeclareInd.default_dep_elim list; nuparams : int option; univ_binders : UState.named_universes_entry; implicits : DeclareInd.one_inductive_impls list; uctx : Univ.ContextSet.t; where_notations : Metasyntax.notation_interpretation_decl list; coercions : Libnames.qualid list; indlocs : DeclareInd.indlocs; } end (** elaborates an inductive declaration (the first half of do_mutual_inductive) *) val interp_mutual_inductive : env:Environ.env -> flags:flags -> ?typing_flags:Declarations.typing_flags -> cumul_univ_decl_expr option -> (one_inductive_expr * notation_declaration list) list -> private_ind:bool -> uniform:uniform_inductive_flag -> Mind_decl.t type syntax_allows_template_poly = SyntaxAllowsTemplatePoly | SyntaxNoTemplatePoly (** the post-elaboration part of interp_mutual_inductive, mainly dealing with universe levels *) val interp_mutual_inductive_constr : sigma:Evd.evar_map -> flags:flags -> udecl:UState.universe_decl -> variances:Entries.variance_entry -> ctx_params:EConstr.rel_context -> indnames:Names.Id.t list -> arities_explicit:bool list -> arities:EConstr.t list -> template_syntax:syntax_allows_template_poly list -> constructors:(Names.Id.t list * EConstr.constr list) list (** Names and types of constructors, not including parameters (as in kernel entries) *) -> env_ar:Environ.env (** Environment with the inductives in the rel_context *) -> private_ind:bool -> DeclareInd.default_dep_elim list * Entries.mutual_inductive_entry * (* for global universe names, used by DeclareInd *) UState.named_universes_entry * (* global universes to declare before the inductive (ie without the template univs) *) Univ.ContextSet.t (************************************************************************) (** Internal API, exported for Record *) (************************************************************************) val maybe_unify_params_in : Environ.env -> Evd.evar_map -> ninds:int -> nparams:int -> binders:int -> EConstr.t -> Evd.evar_map (** [nparams] is the number of parameters which aren't treated as uniform, ie the length of params (including letins) where the env is [uniform params, inductives, params, binders]. *) val variance_of_entry : cumulative:bool -> variances:Entries.variance_entry -> Entries.inductive_universes_entry -> Entries.variance_entry option (** Will return None if non-cumulative, and resize if there are more universes than originally specified. If monomorphic, [cumulative] is treated as [false]. *) module Internal : sig val error_differing_params : kind:string -> (Names.lident * Vernacexpr.inductive_params_expr) -> (Names.lident * Vernacexpr.inductive_params_expr) -> 'a end rocq-9.2.0/vernac/comPrimitive.ml000066400000000000000000000053641516144147600167660ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if Option.has_some udecl then CErrors.user_err ?loc Pp.(strbrk "Cannot use a universe declaration without a type when declaring primitives."); let e = Declare.primitive_entry prim in declare ?loc id e | Some typ -> let env = Global.env () in let evd, udecl = Constrintern.interp_univ_decl_opt env udecl in let auctx = CPrimitives.op_or_type_univs prim in let evd, u = Evd.with_sort_context_set UState.univ_flexible ~src:UState.Internal evd (UnivGen.fresh_instance auctx) in let expected_typ = EConstr.of_constr @@ Typeops.type_of_prim_or_type env u prim in let evd, (typ,impls) = Constrintern.(interp_type_evars_impls ~impls:empty_internalization_env) env evd typ in let evd = try Evarconv.unify_delay env evd typ expected_typ with Evarconv.UnableToUnify (evd,e) as exn -> let _, info = Exninfo.capture exn in Exninfo.iraise (Pretype_errors.( PretypeError (env,evd,CannotUnify (typ,expected_typ,Some e)),info)) in Pretyping.check_evars_are_solved ~program_mode:false env evd; let evd = Evd.minimize_universes evd in let _qvars, uvars = EConstr.universes_of_constr evd typ in let evd = Evd.restrict_universe_context evd uvars in let typ = EConstr.to_constr evd typ in let univ_poly = not (UVars.AbstractContext.is_empty auctx) in let poly = PolyFlags.of_univ_poly univ_poly in let univ_entry = Evd.check_univ_decl ~poly evd udecl in let entry = Declare.primitive_entry ~types:(typ, univ_entry) prim in declare ?loc id entry rocq-9.2.0/vernac/comPrimitive.mli000066400000000000000000000014711516144147600171320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Constrexpr.universe_decl_expr option -> CPrimitives.op_or_type -> Constrexpr.constr_expr option -> unit rocq-9.2.0/vernac/comRewriteRule.ml000066400000000000000000000607251516144147600172710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* CErrors.user_err ?loc Pp.(strbrk "When declaring multiple symbols in one command, " ++ strbrk "only the first is allowed a universe binder " ++ strbrk "(which will be shared by the whole block).") | (_, None) -> () let preprocess_symbols l = let open Vernacexpr in if Global.sections_are_opened () then CErrors.user_err Pp.(str "Declaring a symbol is not allowed in sections."); let udecl = match l with | (coe, ((id, udecl)::rest, c))::rest' -> List.iter maybe_error_many_udecls rest; List.iter (fun (coe, (idl, c)) -> List.iter maybe_error_many_udecls idl) rest'; udecl | (_, ([], _))::_ | [] -> assert false in let no_coercion_msg = Pp.(str "Cannot deal with coercions in symbols") in List.iter (function AddCoercion, (({CAst.loc; _}, _) :: _, _) -> CErrors.user_err ?loc no_coercion_msg | AddCoercion, _ -> assert false | _ -> ()) l; udecl, List.concat_map (fun (coe, (idl, c)) -> List.map (fun (id, _) -> id, c) idl) l let do_symbol ~poly ~unfold_fix udecl (id, typ) = if Dumpglob.dump () then Dumpglob.dump_definition id false "symb"; let loc = id.CAst.loc in let id = id.CAst.v in let env = Global.env () in let evd, udecl = Constrintern.interp_univ_decl_opt env udecl in let evd, (typ, impls) = Constrintern.(interp_type_evars_impls ~impls:empty_internalization_env) env evd typ in Pretyping.check_evars_are_solved ~program_mode:false env evd; let evd = Evd.minimize_universes evd in let _qvars, uvars = EConstr.universes_of_constr evd typ in let evd = Evd.restrict_universe_context evd uvars in let typ = EConstr.to_constr evd typ in let univs = Evd.check_univ_decl ~poly evd udecl in let entry = Declare.symbol_entry ~univs ~unfold_fix typ in let kn = Declare.declare_constant ?loc ~name:id ~kind:Decls.IsSymbol (Declare.SymbolEntry entry) in let () = Impargs.maybe_declare_manual_implicits false (GlobRef.ConstRef kn) impls in let () = Declare.assumption_message id in () let do_symbols ~poly ~unfold_fix l = let env = Global.env () in if not @@ Environ.rewrite_rules_allowed env then raise Environ.(RewriteRulesNotAllowed Symb); let udecl, l = preprocess_symbols l in List.iter (do_symbol ~poly ~unfold_fix udecl) l open Util open Constr open Declarations type state = (int * int Evar.Map.t) * (int * int Int.Map.t) * (int * int Int.Map.t) let rec is_rel_inst k = function | SList.Nil -> true | SList.Default _ -> false | SList.Cons (t, l) -> kind t = Rel k && is_rel_inst (succ k) l let update_invtbl ~loc env evd evk (curvar, tbl) = curvar, (succ curvar, tbl |> Evar.Map.update evk @@ function | None -> Some curvar | Some k as c when k = curvar -> c | Some k -> CErrors.user_err ?loc Pp.(str "Variable " ++ Termops.pr_existential_key env evd evk ++ str" is bound multiple times in the pattern (holes number " ++ int k ++ str" and " ++ int curvar ++ str").")) let update_invtblu1 ~loc evd lvlold lvl (curvaru, tbl) = succ curvaru, tbl |> Int.Map.update lvl @@ function | None -> Some curvaru | Some k as c when k = curvaru -> c | Some k -> CErrors.user_err ?loc Pp.(str "Universe variable " ++ Termops.pr_evd_level evd lvlold ++ str" is bound multiple times in the pattern (holes number " ++ int k ++ str" and " ++ int curvaru ++ str").") let update_invtblq1 ~loc evd qold qvar (curvarq, tbl) = succ curvarq, tbl |> Int.Map.update qvar @@ function | None -> Some curvarq | Some k as c when k = curvarq -> c | Some k -> CErrors.user_err ?loc Pp.(str "Sort variable " ++ Sorts.Quality.pr (Termops.pr_evd_qvar evd) qold ++ str" is bound multiple times in the pattern (holes number " ++ int k ++ str" and " ++ int curvarq ++ str").") let safe_quality_pattern_of_quality ~loc evd qsubst stateq q = match Sorts.Quality.(subst (subst_fn qsubst) q) with | QConstant qc -> stateq, PQConstant qc | QVar qv -> let qio = Sorts.QVar.var_index qv in let stateq = Option.fold_right (update_invtblq1 ~loc evd q) qio stateq in stateq, PQVar qio let update_invtblu ~loc evd (qsubst, usubst) (state, stateq, stateu : state) u : state * _ = let (q, u) = u |> UVars.Instance.to_array in let stateq, maskq = Array.fold_left_map (safe_quality_pattern_of_quality ~loc evd qsubst) stateq q in let stateu, masku = Array.fold_left_map (fun stateu lvlold -> let lvlnew = Univ.Level.var_index @@ UVars.subst_univs_level_level usubst lvlold in Option.fold_right (update_invtblu1 ~loc evd lvlold) lvlnew stateu, lvlnew ) stateu u in (state, stateq, stateu), (maskq, masku) let universe_level_subst_var_index usubst u = match Univ.Universe.level u with | None -> None | Some lvlold -> let lvl = UVars.subst_univs_level_level usubst lvlold in Option.map (fun lvl -> lvlold, lvl) @@ Univ.Level.var_index lvl let safe_sort_pattern_of_sort ~loc evd (qsubst, usubst) (st, sq, su as state) s = let open Sorts in match s with | Type u -> begin match universe_level_subst_var_index usubst u with | None -> state, PSType None | Some (lvlold, lvl) -> (st, sq, update_invtblu1 ~loc evd lvlold lvl su), PSType (Some lvl) end | SProp -> state, PSSProp | Prop -> state, PSProp | Set -> state, PSSet | QSort (qold, u) -> let sq, bq = match Sorts.Quality.(var_index @@ subst_fn qsubst qold) with | Some q -> update_invtblq1 ~loc evd (QVar qold) q sq, Some q | None -> sq, None in let su, ba = match universe_level_subst_var_index usubst u with | Some (lvlold, lvl) -> update_invtblu1 ~loc evd lvlold lvl su, Some lvl | None -> su, None in (st, sq, su), PSQSort (bq, ba) let warn_irrelevant_pattern = CWarnings.create ~name:"irrelevant-pattern" ~category:CWarnings.CoreCategories.rewrite_rules Pp.(fun () -> str "This subpattern is irrelevant and can never be matched against.") let warn_eta_in_pattern = CWarnings.create ~name:"eta-in-pattern" ~category:CWarnings.CoreCategories.rewrite_rules Fun.id let warn_redex_in_rewrite_rules = CWarnings.create ~name:"redex-in-rewrite-rules" ~category:CWarnings.CoreCategories.rewrite_rules Pp.(fun redex -> str "This pattern contains a" ++ redex ++ str " which may prevent this rule from being triggered.") let rec check_may_eta ~loc env evd t = match EConstr.kind evd (Reductionops.whd_all env evd t) with | Prod _ -> warn_eta_in_pattern ?loc Pp.(str "This subpattern has a product type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.") | Sort _ -> () | Ind (ind, u) -> let specif = Inductive.lookup_mind_specif env ind in if not @@ Inductive.is_primitive_record specif then () else warn_eta_in_pattern ?loc Pp.(str "This subpattern has a primitive record type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.") | App (i, _) -> check_may_eta ~loc env evd i | _ -> warn_eta_in_pattern ?loc Pp.(str "This subpattern has a yet unknown type, which may be a product type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.") let test_may_eta ~loc env evd constr = let t = Retyping.get_type_of env evd constr in let () = check_may_eta ~loc env evd t in () let rec safe_pattern_of_constr_aux ~loc env evd usubst depth state t = Constr.kind t |> function | App (f, args) -> let state, (head, elims) = safe_pattern_of_constr_aux ~loc env evd usubst depth state f in let state, pargs = Array.fold_left_map (safe_arg_pattern_of_constr ~loc env evd usubst depth) state args in state, (head, elims @ [PEApp pargs]) | Case (ci, u, params, (ret, _), _, c, brs) -> let mib, mip = Inductive.lookup_mind_specif env ci.ci_ind in let state, (head, elims) = safe_pattern_of_constr_aux ~loc env evd usubst depth state c in let paramdecl = Vars.subst_instance_context u mib.mind_params_ctxt in let paramsubst = Vars.subst_of_rel_context_instance paramdecl params in let state, pret = let (nas, p) = ret in let realdecls, _ = List.chop mip.mind_nrealdecls mip.mind_arity_ctxt in let self = let args = Context.Rel.instance mkRel 0 mip.mind_arity_ctxt in let inst = UVars.Instance.(abstract_instance (length u)) in mkApp (mkIndU (ci.ci_ind, inst), args) in let na = Context.make_annot Anonymous mip.mind_relevance in let realdecls = Context.Rel.Declaration.LocalAssum (na, self) :: realdecls in let realdecls = Inductive.instantiate_context u paramsubst nas realdecls in let p_env = Environ.push_rel_context realdecls env in safe_arg_pattern_of_constr ~loc p_env evd usubst (depth + Array.length nas) state p in let do_one_branch i state (nas, br) = let (ctx, cty) = mip.mind_nf_lc.(i) in let bctx, _ = List.chop mip.mind_consnrealdecls.(i) ctx in let bctx = Inductive.instantiate_context u paramsubst nas bctx in let br_env = Environ.push_rel_context bctx env in safe_arg_pattern_of_constr ~loc br_env evd usubst (depth + Array.length nas) state br in let state, pbrs = Array.fold_left_map_i do_one_branch state brs in state, (head, elims @ [PECase (ci.ci_ind, pret, pbrs)]) | Proj (p, _, c) -> let state, (head, elims) = safe_pattern_of_constr_aux ~loc env evd usubst depth state c in state, (head, elims @ [PEProj (Projection.repr p)]) | _ -> let state, head = safe_head_pattern_of_constr ~loc env evd usubst depth state t in state, (head, []) and safe_pattern_of_constr ~loc env evd usubst depth state t = begin match EConstr.ERelevance.kind evd @@ Retyping.relevance_of_term env evd (EConstr.of_constr t) with | Sorts.Irrelevant -> warn_irrelevant_pattern ?loc () | Sorts.RelevanceVar _ -> () (* FIXME *) | Sorts.Relevant -> () end; safe_pattern_of_constr_aux ~loc env evd usubst depth state t and safe_head_pattern_of_constr ~loc env evd usubst depth state t = Constr.kind t |> function | Const (c, u) when Environ.is_symbol env c -> let state, mask = update_invtblu ~loc evd usubst state u in state, PHSymbol (c, mask) | Rel i -> assert (i <= depth); state, PHRel i | Sort s -> let state, ps = safe_sort_pattern_of_sort ~loc evd usubst state s in state, PHSort ps | Ind (ind, u) -> let state, mask = update_invtblu ~loc evd usubst state u in state, PHInd (ind, mask) | Construct (c, u) -> let state, mask = update_invtblu ~loc evd usubst state u in state, PHConstr (c, mask) | Int i -> state, PHInt i | Float f -> state, PHFloat f | String s -> state, PHString s | Lambda _ -> let (ntys, b) = Term.decompose_lambda t in let tys = Array.rev_of_list ntys in let (state, env), ptys = Array.fold_left_map_i (fun i (state, env) (na, ty) -> let state, p = safe_arg_pattern_of_constr ~loc env evd usubst (depth+i) state ty in (state, Environ.push_rel (LocalAssum (na, ty)) env), p) (state, env) tys in let state, pbod = safe_pattern_of_constr ~loc env evd usubst (depth + Array.length tys) state b in state, PHLambda (ptys, pbod) | Prod _ -> let (ntys, b) = Term.decompose_prod t in let tys = Array.rev_of_list ntys in let (state, env), ptys = Array.fold_left_map_i (fun i (state, env) (na, ty) -> let state, p = safe_arg_pattern_of_constr ~loc env evd usubst (depth+i) state ty in (state, Environ.push_rel (LocalAssum (na, ty)) env), p) (state, env) tys in let state, pbod = safe_arg_pattern_of_constr ~loc env evd usubst (depth + Array.length tys) state b in state, PHProd (ptys, pbod) | _ -> CErrors.user_err ?loc Pp.(str "Subterm not recognised as pattern: " ++ Printer.safe_pr_lconstr_env env evd t) and safe_arg_pattern_of_constr ~loc env evd usubst depth (st, stateq, stateu as state) t = Constr.kind t |> function | Evar (evk, inst) -> let EvarInfo evi = Evd.find evd evk in if Evd.is_rewrite_rule_evar evd evk then let holei, st = update_invtbl ~loc env evd evk st in if not @@ is_rel_inst 1 inst then CErrors.user_err ?loc Pp.(str "In " ++ Printer.safe_pr_lconstr_env env evd (of_kind (Evar (evk, inst))) ++ str ", variable " ++ Termops.pr_existential_key env evd evk ++ str" appears with a non-trivial instantiation."); if Evd.evar_hyps evi |> Environ.named_context_of_val |> Context.Named.length <> SList.length inst then CErrors.user_err ?loc Pp.(str "Pattern variable cannot access the whole context: " ++ Printer.safe_pr_lconstr_env env evd t); (st, stateq, stateu), EHole holei else (match snd (Evd.evar_source evi) with | Evar_kinds.RewriteRulePattern _ -> assert false (* Dealt with just above *) | Evar_kinds.NamedHole _ -> CErrors.user_err ?loc Pp.(str "Named holes are not supported, you must use regular evars: " ++ Printer.safe_pr_lconstr_env env evd t) | _ -> if Option.is_empty @@ Evd.evar_ident evk evd then state, EHoleIgnored else CErrors.user_err ?loc Pp.(str "Named evar in unsupported context: " ++ Printer.safe_pr_lconstr_env env evd t) ) | _ -> test_may_eta ~loc env evd (EConstr.of_constr t); let state, p = safe_pattern_of_constr ~loc env evd usubst depth state t in state, ERigid p (* relocation of evars into de Bruijn indices *) let rec evar_subst evmap evd k t = match EConstr.kind evd t with | Evar (evk, inst) -> begin match Evar.Map.find_opt evk evmap with | None -> t | Some (n, vars) -> let head = EConstr.mkRel (n + k) in let Evd.EvarInfo evi = Evd.find evd evk in let body = EConstr.mkApp (head, vars) in let inst = inst |> SList.Smart.map (evar_subst evmap evd k) in Evd.instantiate_evar_array evd evi body inst end | _ -> EConstr.map_with_binders evd succ (evar_subst evmap evd) k t let test_projection_apps env evd ~loc ind args = let specif = Inductive.lookup_mind_specif env ind in if not @@ Inductive.is_primitive_record specif then () else if Array.for_all_i (fun i arg -> match arg with | EHole _ | EHoleIgnored -> true | ERigid (_, []) -> false | ERigid (_, elims) -> match List.last elims with | PEProj p -> Environ.QInd.equal env (Projection.Repr.inductive p) ind && Projection.Repr.arg p = i | _ -> false ) 0 args then warn_redex_in_rewrite_rules ?loc Pp.(str " subpattern compatible with an eta-long form for " ++ Id.print (snd specif).mind_typename ++ str"," ) let rec test_pattern_redex env evd ~loc = function | PHLambda _, PEApp _ :: _ -> warn_redex_in_rewrite_rules ?loc (Pp.str " beta redex") | PHConstr _, (PECase _ | PEProj _) :: _ -> warn_redex_in_rewrite_rules ?loc (Pp.str " iota redex") | PHConstr _, PEApp _ :: (PECase _ | PEProj _) :: _ -> warn_redex_in_rewrite_rules ?loc (Pp.str " iota redex") | PHLambda _, _ -> warn_redex_in_rewrite_rules ?loc (Pp.str " lambda pattern") | PHConstr (c, _) as head, PEApp args :: elims -> test_projection_apps env evd ~loc (fst c) args; Array.iter (test_pattern_redex_aux env evd ~loc) args; test_pattern_redex env evd ~loc (head, elims) | head, PEApp args :: elims -> Array.iter (test_pattern_redex_aux env evd ~loc) args; test_pattern_redex env evd ~loc (head, elims) | head, PECase (_, ret, brs) :: elims -> test_pattern_redex_aux env evd ~loc ret; Array.iter (test_pattern_redex_aux env evd ~loc) brs; test_pattern_redex env evd ~loc (head, elims) | head, PEProj _ :: elims -> test_pattern_redex env evd ~loc (head, elims) | PHProd (tys, bod), [] -> Array.iter (test_pattern_redex_aux env evd ~loc) tys; test_pattern_redex_aux env evd ~loc bod | (PHRel _ | PHInt _ | PHFloat _ | PHString _ | PHSort _ | PHInd _ | PHConstr _ | PHSymbol _), [] -> () and test_pattern_redex_aux env evd ~loc = function | EHole _ | EHoleIgnored -> () | ERigid p -> test_pattern_redex env evd ~loc p let warn_rewrite_rules_break_SR = CWarnings.create ~name:"rewrite-rules-break-SR" ~category:CWarnings.CoreCategories.rewrite_rules Pp.(fun reason -> str "This rewrite rule breaks subject reduction" ++ spc() ++ reason) let interp_rule (udecl, lhs, rhs: Constrexpr.universe_decl_expr option * _ * _) = let env = Global.env () in let evd = Evd.from_env env in (* 1. Read universe level binders, leaving out the constraints for now *) (* Inlined the relevant part of Constrintern.interp_poly_decl *) let evd, udecl = let open CAst in let open UState in match udecl with | None -> evd, default_univ_decl | Some udecl -> let evd, qualities = List.fold_left_map (fun evd lid -> Evd.new_quality_variable ?loc:lid.loc ~name:lid.v evd) evd udecl.univdecl_qualities in let evd, instance = List.fold_left_map (fun evd lid -> Evd.new_univ_level_variable ?loc:lid.loc univ_rigid ~name:lid.v evd) evd udecl.univdecl_instance in let elim_cstrs = udecl.univdecl_elim_constraints |> List.to_seq |> Seq.map (Constrintern.interp_elim_constraint evd) |> Sorts.ElimConstraints.of_seq in let univ_cstrs = udecl.univdecl_univ_constraints |> List.to_seq |> Seq.map (Constrintern.interp_univ_constraint evd) |> Univ.UnivConstraints.of_seq in let decl = { univdecl_qualities = qualities; univdecl_extensible_qualities = udecl.univdecl_extensible_qualities; univdecl_elim_constraints = elim_cstrs; univdecl_instance = instance; univdecl_extensible_instance = udecl.univdecl_extensible_instance; univdecl_univ_constraints = univ_cstrs; univdecl_extensible_constraints = udecl.univdecl_extensible_constraints; } in evd, decl in let nvarqs = List.length udecl.univdecl_qualities in let nvarus = List.length udecl.univdecl_instance in (* 2. Read left hand side, into a pattern *) (* The udecl constraints must be implied by the lhs (and not the reverse) *) let lhs_loc = lhs.CAst.loc in let rhs_loc = rhs.CAst.loc in let lhs = Constrintern.(intern_gen WithoutTypeConstraint env evd lhs) in let poly = PolyFlags.make ~univ_poly:true ~cumulative:false ~collapse_sort_variables:false in let flags = { Pretyping.no_classes_no_fail_inference_flags with undeclared_evars_rr = true; expand_evars = false; solve_unification_constraints = false; poly } in let evd, lhs, typ = Pretyping.understand_tcc_ty ~flags env evd lhs in let evd = Evd.minimize_universes evd in let _qvars, uvars = EConstr.universes_of_constr evd lhs in let evd = Evd.restrict_universe_context evd uvars in let uctx, uctx' = UState.check_univ_decl_rev (Evd.ustate evd) udecl in let usubst = let inst, auctx = UVars.abstract_universes uctx' in UVars.make_instance_subst inst in let ((nvars', invtbl), (nvarqs', invtblq), (nvarus', invtblu)), (head_pat, elims) = safe_pattern_of_constr ~loc:lhs_loc env evd usubst 0 ((1, Evar.Map.empty), (0, Int.Map.empty), (0, Int.Map.empty)) (EConstr.Unsafe.to_constr lhs) in let () = test_pattern_redex env evd ~loc:lhs_loc (head_pat, elims) in let head_symbol, head_umask = match head_pat with PHSymbol (symb, mask) -> symb, mask | _ -> CErrors.user_err ?loc:lhs_loc Pp.(str "Head head-pattern is not a symbol.") in if nvarus <> nvarus' then begin assert (nvarus' < nvarus); CErrors.user_err ?loc:lhs_loc Pp.(str "Not all universe level variables appear in the pattern.") end; if nvarqs <> nvarqs' then begin assert (nvarqs' < nvarqs); CErrors.user_err ?loc:lhs_loc Pp.(str "Not all sort variables appear in the pattern.") end; let update_invtbl evd evk n = let Evd.EvarInfo evi = Evd.find evd evk in let vars = Evd.evar_hyps evi |> Environ.named_context_of_val |> Context.Named.instance EConstr.mkVar in (n, vars) in let invtbl = Evar.Map.mapi (update_invtbl evd) invtbl in (* 3. Read right hand side *) (* The udecl constraints (or, if none, the lhs constraints) must imply those of the rhs *) let evd = Evd.set_universe_context evd uctx in let rhs = Constrintern.(intern_gen WithoutTypeConstraint env evd rhs) in let flags = { Pretyping.no_classes_no_fail_inference_flags with poly } in let evd', rhs = try Pretyping.understand_tcc ~flags env evd ~expected_type:(OfType typ) rhs with Pretype_errors.PretypeError (env', evd', e) -> warn_rewrite_rules_break_SR ?loc:rhs_loc Pp.(surround (str "the replacement term doesn't have the type of the pattern") ++ str "." ++ fnl () ++ Himsg.explain_pretype_error env' evd' e); Pretyping.understand_tcc ~flags env evd rhs in let evd' = Evd.minimize_universes evd' in let _qvars', uvars' = EConstr.universes_of_constr evd' rhs in let evd' = Evd.restrict_universe_context evd' (Univ.Level.Set.union uvars uvars') in let fail pp = warn_rewrite_rules_break_SR ?loc:rhs_loc Pp.(surround (str "universe inconsistency") ++ str"." ++ spc() ++ str "Missing constraints: " ++ pp) in let () = UState.check_uctx_impl ~fail (Evd.ustate evd) (Evd.ustate evd') in let evd = evd' in let rhs = let rhs' = evar_subst invtbl evd 0 rhs in match EConstr.to_constr_opt evd rhs' with | Some rhs -> rhs | None -> let pr_unresolved_evar e = Pp.(hov 2 (str"- " ++ Printer.pr_existential_key env evd e ++ str ": " ++ Himsg.explain_pretype_error env evd (Pretype_errors.UnsolvableImplicit (e,None)))) in CErrors.user_err ?loc:rhs_loc Pp.(hov 0 begin str "The replacement term contains unresolved implicit arguments:"++ fnl () ++ str " " ++ Printer.pr_econstr_env env evd rhs ++ fnl () ++ str "More precisely: " ++ fnl () ++ v 0 (prlist_with_sep cut pr_unresolved_evar (Evar.Set.elements (Evarutil.undefined_evars_of_term evd rhs'))) end) in let rhs = Vars.subst_univs_level_constr usubst rhs in let test_qvar q = match Sorts.QVar.var_index q with | Some -1 -> CErrors.user_err ?loc:rhs_loc Pp.(str "Sort variable " ++ Termops.pr_evd_qvar evd q ++ str " appears in the replacement but does not appear in the pattern.") | Some n when n < 0 || n > nvarqs' -> CErrors.anomaly Pp.(str "Unknown sort variable in rewrite rule.") | Some _ -> () | None -> if not @@ Sorts.QVar.Set.mem q (evd |> Evd.sort_context_set |> fst |> fst) then CErrors.user_err ?loc:rhs_loc Pp.(str "Sort variable " ++ Termops.pr_evd_qvar evd q ++ str " appears in the replacement but does not appear in the pattern.") in let test_level ?(alg_ok=false) lvl = match Univ.Level.var_index lvl with | Some -1 -> CErrors.user_err ?loc:rhs_loc Pp.(str "Universe level variable " ++ Termops.pr_evd_level evd lvl ++ str " appears in the replacement but does not appear in the pattern.") | Some n when n < 0 || n > nvarus' -> CErrors.anomaly Pp.(str "Unknown universe level variable in rewrite rule") | Some _ -> () | None -> match UGraph.check_declared_universes (Environ.universes env) (Univ.Level.Set.singleton lvl) with | Ok () -> () | Error l -> let l = Univ.Level.Set.elements l in CErrors.user_err ?loc:rhs_loc Pp.(str "Universe level " ++ prlist_with_sep spc (Termops.pr_evd_level evd) l ++ str " appears in the replacement but does not appear in the pattern.") in let () = let qs, us = Vars.sort_and_universes_of_constr rhs in Sorts.QVar.Set.iter test_qvar qs; Univ.Level.Set.iter test_level us in head_symbol, { nvars = (nvars' - 1, nvarqs', nvarus'); lhs_pat = head_umask, elims; rhs } let do_rules id rules = let env = Global.env () in if not @@ Environ.rewrite_rules_allowed env then raise Environ.(RewriteRulesNotAllowed Rule); let body = { rewrules_rules = List.map interp_rule rules } in Global.add_rewrite_rules id body rocq-9.2.0/vernac/comRewriteRule.mli000066400000000000000000000005061516144147600174310ustar00rootroot00000000000000val do_symbols : poly:PolyFlags.t -> unfold_fix:bool -> (Vernacexpr.coercion_flag * ((Names.lident * Constrexpr.universe_decl_expr option) list * Constrexpr.constr_expr)) list -> unit val do_rules : Names.Id.t -> (Constrexpr.universe_decl_expr option * Constrexpr.constr_expr * Constrexpr.constr_expr) list -> unit rocq-9.2.0/vernac/comSearch.ml000066400000000000000000000160041516144147600162140ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* try Nametab.full_name_module qid with Not_found -> user_err ?loc:qid.CAst.loc (str "Module/Section " ++ Ppconstr.pr_qualid qid ++ str " not found.") (* let global_module qid = user_err ?loc:qid.CAst.loc (str "Module/Section " ++ Ppconstr.pr_qualid qid ++ str " not found.") *) let interp_search_restriction = function | SearchOutside l -> SearchOutside (List.map open_or_global_module l) | SearchInside l -> SearchInside (List.map open_or_global_module l) let kind_searcher env = Decls.(function (* Kinds referring to the keyword introducing the object *) | IsAssumption _ | IsDefinition (Definition | Example | Fixpoint | CoFixpoint | Method | StructureComponent | Let | LetContext) | IsProof _ | IsPrimitive | IsSymbol as k -> Inl k (* Kinds referring to the status of the object *) | IsDefinition (Coercion | SubClass | IdentityCoercion as k') -> let coercions = Coercionops.coercions () in Inr (fun gr -> List.exists (fun c -> Environ.QGlobRef.equal env c.Coercionops.coe_value gr && (k' <> SubClass && k' <> IdentityCoercion || c.Coercionops.coe_is_identity)) coercions) | IsDefinition CanonicalStructure -> let canonproj = Structures.CSTable.entries () in Inr (fun gr -> List.exists (fun c -> Environ.QGlobRef.equal env c.Structures.CSTable.solution gr) canonproj) | IsDefinition Scheme -> let schemes = DeclareScheme.all_schemes () in let schemes = lazy begin Indmap_env.fold (fun _ schemes acc -> CString.Map.fold (fun _ c acc -> GlobRef.Set_env.add c acc) schemes acc) schemes GlobRef.Set_env.empty end in Inr (fun x -> GlobRef.Set_env.mem x (Lazy.force schemes)) | IsDefinition Instance -> let instances = Typeclasses.all_instances () in Inr (fun gr -> List.exists (fun c -> Environ.QGlobRef.equal env c.Typeclasses.is_impl gr) instances)) let interp_constr_pattern env sigma ?(expected_type=Pretyping.WithoutTypeConstraint) c = let c = Constrintern.intern_gen expected_type ~pattern_mode:true env sigma c in let flags = { Pretyping.no_classes_no_fail_inference_flags with expand_evars = false } in let sigma, c = Pretyping.understand_tcc ~flags env sigma ~expected_type c in (* FIXME: it is necessary to be unsafe here because of the way we handle evars in the pretyper. Sometimes they get solved eagerly. *) Patternops.legacy_bad_pattern_of_constr env sigma c let interp_search_item env sigma = function | SearchSubPattern ((where,head),pat) -> let expected_type = Pretyping.(if head then IsType else WithoutTypeConstraint) in let pat = try interp_constr_pattern env sigma ~expected_type pat with e when CErrors.noncritical e -> (* We cannot ensure (yet?) that a typable pattern will actually be typed, consider e.g. (forall A, A -> A /\ A) which fails, not seeing that A can be Prop; so we use an untyped pattern as a fallback (i.e w/o no insertion of coercions, no compilation of pattern-matching) *) snd (Constrintern.interp_constr_pattern env sigma ~as_type:head pat) in GlobSearchSubPattern (where,head,pat) | SearchString ((Anywhere,false),s,None) when Id.is_valid_ident_part s && String.equal (String.drop_simple_quotes s) s -> GlobSearchString s | SearchString ((where,head),s,sc) -> let sc = Option.map snd sc in let ref = Notation.interp_notation_as_global_reference ~head:false (fun _ -> true) s sc in GlobSearchSubPattern (where,head,Pattern.PRef ref) | SearchKind k -> match kind_searcher env k with | Inl k -> GlobSearchKind k | Inr f -> GlobSearchFilter f let rec interp_search_request env sigma = function | b, SearchLiteral i -> b, GlobSearchLiteral (interp_search_item env sigma i) | b, SearchDisjConj l -> b, GlobSearchDisjConj (List.map (List.map (interp_search_request env sigma)) l) (* 05f22a5d6d5b8e3e80f1a37321708ce401834430 introduced the `search_output_name_only` option to avoid excessive printing when searching. The motivation was to make search usable for IDE completion, however, it is still too slow due to the non-indexed nature of the underlying search mechanism. In the future we should deprecate the option and provide a fast, indexed name-searching interface. *) let search_output_name_only = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Search";"Output";"Name";"Only"]; optread = (fun () -> !search_output_name_only); optwrite = (:=) search_output_name_only } let interp_search env sigma s r = let r = interp_search_restriction r in let get_pattern c = snd (Constrintern.interp_constr_pattern env sigma c) in let warnlist = ref [] in let pr_search ref kind env sigma c = let pr = pr_global ref in let pp = if !search_output_name_only then pr else begin let open Impargs in let impls = implicits_of_global ref in let impargs = select_stronger_impargs impls in let impargs = List.map binding_kind_of_status impargs in if List.length impls > 1 || List.exists Glob_term.(function Explicit -> false | MaxImplicit | NonMaxImplicit -> true) (List.skipn_at_best (Termops.nb_prod_modulo_zeta sigma (EConstr.of_constr c)) impargs) then warnlist := pr :: !warnlist; let pc = pr_ltype_env env sigma ~impargs c in hov 2 (pr ++ str":" ++ spc () ++ pc) end in Feedback.msg_notice pp in (match s with | SearchPattern c -> (Search.search_pattern env sigma (get_pattern c) r |> Search.prioritize_search) pr_search | SearchRewrite c -> (Search.search_rewrite env sigma (get_pattern c) r |> Search.prioritize_search) pr_search | Search sl -> (Search.search env sigma (List.map (interp_search_request env Evd.(from_env env)) sl) r |> Search.prioritize_search) pr_search); if !warnlist <> [] then Feedback.msg_notice (str "(" ++ hov 0 (strbrk "use \"About\" for full details on the implicit arguments of " ++ pr_enum (fun x -> x) !warnlist ++ str ")")) rocq-9.2.0/vernac/comSearch.mli000066400000000000000000000021221516144147600163610ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Evd.evar_map -> bool * Vernacexpr.search_request -> bool * Search.glob_search_request val interp_search_restriction : Libnames.qualid list search_restriction -> Libnames.full_path list search_restriction val interp_search : Environ.env -> Evd.evar_map -> searchable -> Libnames.qualid list search_restriction -> unit rocq-9.2.0/vernac/comTactic.ml000066400000000000000000000102051516144147600162130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* interpretable type 'a tactic_interpreter = Interpreter of ('a -> interpretable) let register_tactic_interpreter na f = let t = Dyn.create na in interp_map := DMap.add t f !interp_map; Interpreter (fun x -> I (t,x)) let interp_tac (I (tag,t)) = let f = DMap.find tag !interp_map in f t type parallel_solver = pstate:Declare.Proof.t -> info:int option -> interpretable -> abstract:bool -> Declare.Proof.t let { Goptions.get = print_info_trace } = declare_intopt_option_and_ref ~key:["Info" ; "Level"] ~value:None () let warn_end_tac = CWarnings.create_warning ~name:"deprecated-end-tac" ~from:[Deprecation.Version.v9_2] () let pp_warn_end_tac = let pptac end_tac = let env = Global.env() in let sigma = Evd.from_env env in let pptac = Gentactic.print_glob env sigma end_tac in Pp.(str ";" ++ spc() ++ pptac ++ str ".") in CWarnings.create_in warn_end_tac ~quickfix:(fun ~loc end_tac -> [Quickfix.make ~loc (pptac end_tac)]) Pp.(fun end_tac -> fmt "Using \"...\" is deprecated, use \"%t\" instead" (fun () -> pptac end_tac)) let warn_end_tac ?loc end_tac = match end_tac with | None -> CErrors.user_err ?loc Pp.(str "This \"...\" is useless, use \".\" instead.") | Some end_tac -> pp_warn_end_tac ?loc end_tac let use_end_tac ~with_end_tac end_tac = if not with_end_tac.CAst.v then None else begin warn_end_tac ?loc:with_end_tac.loc end_tac; Option.map Gentactic.interp end_tac end let solve_core ~pstate n ~info ?(with_end_tac=CAst.make false) t = let pstate, status = Declare.Proof.map_fold_endline ~f:(fun etac p -> let with_end_tac = use_end_tac ~with_end_tac etac in let info = Option.append info (print_info_trace ()) in let (p,status) = Proof.solve (Global.env ()) n info t ?with_end_tac p in (* in case a strict subtree was completed, go back to the top of the prooftree *) let p = Proof.maximal_unfocus Vernacentries.command_focus p in p,status) pstate in let pstate = Declare.Internal.register_side_effects pstate in if not status then Feedback.feedback Feedback.AddedAxiom; pstate let solve ~pstate n ~info ?with_end_tac t = let t = interp_tac t in solve_core ~pstate n ~info t ?with_end_tac let check_par_applicable pstate = Declare.Proof.fold pstate ~f:(fun p -> (Proof.data p).Proof.goals |> List.iter (fun goal -> let is_ground = let { Proof.sigma = sigma0 } = Declare.Proof.fold pstate ~f:Proof.data in let g = Evd.find_undefined sigma0 goal in let concl, hyps = Evd.evar_concl g, Evd.evar_context g in Evarutil.is_ground_term sigma0 concl && List.for_all (Context.Named.Declaration.for_all (Evarutil.is_ground_term sigma0)) hyps in if not is_ground then CErrors.user_err Pp.(strbrk("The par: goal selector does not support goals with existential variables")))) let par_implementation : parallel_solver ref = ref (fun ~pstate ~info t ~abstract -> let t = interp_tac t in let t = Proofview.Goal.enter (fun _ -> if abstract then Abstract.tclABSTRACT None ~opaque:true t else t) in solve_core ~pstate Goal_select.SelectAll ~info t) let set_par_implementation f = par_implementation := f let solve_parallel ~pstate ~info t ~abstract = check_par_applicable pstate; !par_implementation ~pstate ~info t ~abstract rocq-9.2.0/vernac/comTactic.mli000066400000000000000000000042651516144147600163750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* interpretable) (** ['a] should be marshallable if ever used with [par:]. Must be called no more than once per process with a particular string: make sure to use partial application. *) val register_tactic_interpreter : string -> ('a -> unit Proofview.tactic) -> 'a tactic_interpreter (** Entry point for toplevel tactic expression execution. It calls Proof.solve after having interpreted the tactic, and after the tactic runs it unfocus as much as needed to put a goal under focus. *) val solve : pstate:Declare.Proof.t -> Goal_select.t -> info:int option -> ?with_end_tac:bool CAst.t -> interpretable -> Declare.Proof.t (** [par: tac] runs tac on all goals, possibly in parallel using a worker pool. If tac is [abstract tac1], then [abstract] is passed explicitly to the solver and [tac1] passed to worker since it is up to master to opacify the sub proofs produced by the workers. *) type parallel_solver = pstate:Declare.Proof.t -> info:int option -> interpretable -> abstract:bool -> (* the tactic result has to be opacified as per abstract *) Declare.Proof.t (** Entry point when the goal selector is par: *) val solve_parallel : parallel_solver (** By default par: is implemented with all: (sequential). The STM and LSP document manager provide "more parallel" implementations *) val set_par_implementation : parallel_solver -> unit rocq-9.2.0/vernac/debugHook.ml000066400000000000000000000053341516144147600162230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* = 2 && s.[0] == '"' && s.[String.length s - 1] == '"' then String.sub s 1 (String.length s - 2) else s let parse_complex inst : (t, string) result = if 'r' = String.get inst 0 then let arg = String.(trim (sub inst 1 (length inst - 1))) in if arg <> "" then match int_of_string_opt arg with | Some num -> if num < 0 then Error "number must be positive" else Ok (RunCnt num) | None -> Ok (RunBreakpoint (possibly_unquote arg)) else Error ("invalid input: " ^ inst) else Error ("invalid input: " ^ inst) (* XXX: Should be moved to the clients *) let parse inst : (t, string) result = match inst with | "" -> Ok StepIn | "s" -> Ok Skip | "x" -> Ok Interrupt | "h"| "?" -> Ok Help | _ -> parse_complex inst end module Answer = struct type t = | Prompt of Pp.t | Goal of Pp.t | Output of Pp.t | Init | Stack of (string * (string * int list) option) list | Vars of (string * Pp.t) list end module Intf = struct type t = { read_cmd : unit -> Action.t (** request a debugger command from the client *) ; submit_answer : Answer.t -> unit (** receive a debugger answer from Ltac *) ; isTerminal : bool (** whether the debugger is running as a terminal (non-visual) *) } let ltac_debug_ref : t option ref = ref None let set hooks = ltac_debug_ref := Some hooks let get () = !ltac_debug_ref end rocq-9.2.0/vernac/debugHook.mli000066400000000000000000000107571516144147600164010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Rocq sends Answer.Init <- IDE sends zero or more initialization requests such as Action.UpdBpts <- IDE sends Action.Configd Stopping in the debugger generates Answer.Prompt and Answer.Goal messages, at which point the IDE will typically call GetStack and GetVars. When the IDE sends with StepIn..Continue, the debugger will execute more code. At that point, Rocq won't try to read more messages from the IDE until the debugger stops again or exits. *) module Action : sig type t = | StepIn (* execute a single step in the tactic *) | StepOver (* execute steps until DB is back in the current stack frame *) | StepOut (* execute steps until DB exits current stack frame *) | Continue (* execute steps until a breakpoint or the debugger exits *) | Skip (* legacy: continue execution with no further debugging *) | Interrupt (* exit the debugger *) | Help (* legacy: print help text *) | UpdBpts of ((string * int) * bool) list (* sets or clears breakpoints. Values are: - absolute pathname of the the file - byte offset in the UTF-8 representation of the file - true to set, false to clear *) | Configd (* "config done" - indicates that the debugger has been configured, debugger does a Continue *) | GetStack (* request the call stack, returned as Answer.Stack *) | GetVars of int (* request the variables defined for stack frame N, returned as Answer.Vars. 0 is the topmost frame, followed by 1,2,3, ... *) | RunCnt of int (* legacy: run for N steps *) | RunBreakpoint of string (* legacy: run until an idtac prints the string *) | Command of string (* legacy: user-typed command to the debugger *) | Failed (* legacy: user command doesn't parse *) | Ignore (* internal: do nothing, read another command *) (* XXX: Should be moved to the clients *) val parse : string -> (t, string) result end module Answer : sig type t = | Prompt of Pp.t (* output signalling the debugger has stopped Should be printed as a prompt for user input, e.g. in color without a newline at the end *) | Goal of Pp.t (* goal for the current proof state *) | Output of Pp.t (* general output *) | Init (* signals initialization of the debugger *) | Stack of (string * (string * int list) option) list (* The call stack, starting from TOS. Values are: - description of the frame (eg tactic name, line number, module) - absolute pathname of the file - array containing Loc.bp and Loc.ep of the corresponding code *) | Vars of (string * Pp.t) list (* The variable values for the specified stack frame. Values are variable name and variable value *) end module Intf : sig type t = { read_cmd : unit -> Action.t (** request a debugger command from the client *) ; submit_answer : Answer.t -> unit (** receive a debugger answer from Ltac *) ; isTerminal : bool (** whether the debugger is running as a terminal (non-visual) *) } val set : t -> unit val get : unit -> t option end rocq-9.2.0/vernac/declare.ml000066400000000000000000003357221516144147600157220ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a -> 'a) CEphemeron.key type t = unit g let make_g hook = CEphemeron.create hook let make (hook : S.t -> unit) : t = CEphemeron.create (fun x () -> hook x) let hcall hook x s = CEphemeron.default hook (fun _ x -> x) x s let call_g ?hook x s = Option.cata (fun hook -> hcall hook x s) s hook let call ?hook x = Option.iter (fun hook -> hcall hook x ()) hook end let warn_using_fallback_loc = CWarnings.create ~name:"using-fallback-loc" ~category:CWarnings.CoreCategories.internal ~default:Disabled Pp.(fun name -> str "Using fallback loc for " ++ Id.print name ++ str ".") let fallback_loc ?(warn=true) name = function | Some _ as loc -> loc | None -> match Loc.get_current_command_loc () with | None -> None | Some _ as loc -> let () = if warn then warn_using_fallback_loc name in loc module CInfo = struct type 'constr t = { name : Id.t (** Name of theorem *) ; typ : 'constr (** Type of theorem *) ; args : Name.t list (** Names to pre-introduce *) ; impargs : Impargs.manual_implicits (** Explicitily declared implicit arguments *) ; loc : Loc.t option } let make ?loc ~name ~typ ?(args=[]) ?(impargs=[]) () = let loc = fallback_loc name loc in { name; typ; args; impargs; loc } let to_constr sigma thm = { thm with typ = EConstr.to_constr sigma thm.typ } let get_typ { typ; _ } = typ let get_name { name; _ } = name end (** Information for a declaration, interactive or not, includes parameters shared by mutual constants *) module Info = struct type t = { poly : PolyFlags.t ; inline : bool ; kind : Decls.logical_kind ; udecl : UState.universe_decl ; scope : Locality.definition_scope ; clearbody : bool (* always false for non Discharge scope *) ; hook : Hook.t option ; typing_flags : Declarations.typing_flags option ; user_warns : Globnames.extended_global_reference UserWarn.with_qf option ; ntns : Metasyntax.notation_interpretation_decl list } (** Note that [opaque] doesn't appear here as it is not known at the start of the proof in the interactive case. *) let make ?(poly = PolyFlags.default) ?(inline=false) ?(kind=Decls.(IsDefinition Definition)) ?(udecl=UState.default_univ_decl) ?(scope=Locality.default_scope) ?(clearbody=false) ?hook ?typing_flags ?user_warns ?(ntns=[]) () = { poly; inline; kind; udecl; scope; hook; typing_flags; clearbody; user_warns; ntns } end module SideEff : sig type t val empty : t val make : Evd.side_effects -> t val concat : t -> t -> t val get : t -> Safe_typing.private_constants val obj : t -> (Evd.side_effect_role option * UState.named_universes_entry option) Cmap_env.t end = struct type t = { priv : Safe_typing.private_constants; data : (Evd.side_effect_role option * UState.named_universes_entry option) Cmap_env.t; } let empty = { priv = Safe_typing.empty_private_constants; data = Cmap_env.empty; } let make eff = let fold accu c = let role = try Some (Cmap_env.find c (Evd.seff_roles eff)) with Not_found -> None in let univs = try Some (Cmap_env.find c (Evd.seff_univs eff)) with Not_found -> None in Cmap_env.add c (role, univs) accu in let priv = Evd.seff_private eff in let data = List.fold_left fold Cmap_env.empty (Safe_typing.constants_of_private priv) in { priv; data } let concat e1 e2 = { priv = Safe_typing.concat_private e1.priv e2.priv; data = Cmap_env.union (fun _ x y -> Some x) e1.data e2.data; } let get e = e.priv let obj e = e.data end (** Declaration of constants and parameters *) (* Deferred proofs: monomorphic, opaque, and udecl is for body+type *) type 'eff deferred_opaque_proof_body = { body : ((Constr.t * Univ.ContextSet.t) * 'eff) Future.computation; feedback_id : Stateid.t option (* State id on which the completion of type checking is reported *) } (* Opacity of default proofs, possibly with private universes *) type default_body_opacity = | Transparent (* udecl is for body+type; all universes are in proof_entry_universes *) | Opaque of Univ.ContextSet.t * SideEff.t (* if poly, the private uctx, udecl excludes the private uctx *) (* if mono, the body uctx *) (* Default (non-deferred) proofs/definitions, possibly with effects *) type default_proof_body = { body : Constr.t; opaque : default_body_opacity } (* A proof body is either immediate or deferred *) type 'eff proof_body = | DeferredOpaque of 'eff deferred_opaque_proof_body | Default of default_proof_body (* A proof entry, parameterized with its kind of proof body *) type 'body pproof_entry = { proof_entry_body : 'body; proof_entry_secctx : Id.Set.t option; (* List of section variables *) proof_entry_type : Constr.types option; (* the initial type if deferred *) proof_entry_universes : UState.named_universes_entry; (* refers to: - the initial uctx if opaque deferred; - the uctx of type only if opaque private; - the full uctx otherwise *) proof_entry_inline_code : bool; } (* The most general form of proof entry *) type proof_entry = SideEff.t proof_body pproof_entry type parameter_entry = { parameter_entry_secctx : Id.Set.t option; parameter_entry_type : Constr.types; parameter_entry_universes : UState.named_universes_entry; parameter_entry_inline_code : Entries.inline; } type primitive_entry = { prim_entry_type : (Constr.types * UState.named_universes_entry) option; prim_entry_content : CPrimitives.op_or_type; } type symbol_entry = { symb_entry_type : Constr.types; symb_entry_unfold_fix: bool; symb_entry_universes : UState.named_universes_entry; } let default_univ_entry = UState.Monomorphic_entry Univ.ContextSet.empty let default_named_univ_entry = default_univ_entry, UnivNames.empty_binders let extract_monomorphic = function | UState.Monomorphic_entry ctx -> Entries.Monomorphic_entry, ctx | UState.Polymorphic_entry uctx -> Entries.Polymorphic_entry uctx, Univ.ContextSet.empty let instance_of_univs = function | UState.Monomorphic_entry _, _ -> UVars.Instance.empty | UState.Polymorphic_entry uctx, _ -> UVars.UContext.instance uctx let add_mono_uctx uctx = function | UState.Monomorphic_entry ctx, ubinders -> let uctx = UState.check_mono_sort_constraints uctx in UState.Monomorphic_entry (Univ.ContextSet.union uctx ctx), ubinders | UState.Polymorphic_entry _, _ as x -> assert (UnivGen.is_empty_sort_context (UState.sort_context_set uctx)); x let make_ubinders uctx (univs, ubinders as u) = match univs with | UState.Monomorphic_entry _ -> (UState.Monomorphic_entry uctx, ubinders) | UState.Polymorphic_entry _ -> u let { Goptions.get = private_poly_univs } = Goptions.declare_bool_option_and_ref ~key:["Private";"Polymorphic";"Universes"] ~value:true () let universes_of_body_type ~used_univs body typ = let used_univs_typ = Option.cata (Vars.universes_of_constr ~init:used_univs) used_univs typ in let used_univs = Vars.universes_of_constr body ~init:used_univs_typ in used_univs_typ, used_univs let make_univs_deferred_private_mono ~initial_euctx ?feedback_id ~uctx ~udecl body typ = let _, used_univs = universes_of_body_type ~used_univs:Univ.Level.Set.empty body typ in let uctx = UState.constrain_variables (fst (UState.universe_context_set initial_euctx)) uctx in (* For vi2vo compilation proofs are computed now but we need to complement the univ constraints of the typ with the ones of the body. So we keep the two sets distinct. *) let uctx_body = UState.restrict uctx used_univs in UState.check_mono_univ_decl uctx_body udecl let make_univs_immediate_private_mono ~initial_euctx ~uctx ~udecl ~eff ~used_univs body typ = let utyp = UState.univ_entry ~poly:PolyFlags.default initial_euctx in let _, used_univs = universes_of_body_type ~used_univs body typ in let ubody = let uctx = UState.constrain_variables (fst (UState.universe_context_set initial_euctx)) uctx in (* For vi2vo compilation proofs are computed now but we need to complement the univ constraints of the typ with the ones of the body. So we keep the two sets distinct. *) let uctx_body = UState.restrict uctx used_univs in UState.check_mono_univ_decl uctx_body udecl in initial_euctx, utyp, used_univs, Default { body; opaque = Opaque (ubody, eff) } let make_univs_immediate_private_poly ~poly ~uctx ~udecl ~eff ~used_univs body typ = let used_univs_typ, used_univs = universes_of_body_type ~used_univs body typ in let uctx' = UState.restrict uctx used_univs_typ in let utyp = UState.check_univ_decl ~poly uctx' udecl in let ubody = let uctx = UState.restrict uctx used_univs in (* XXX we don't check anything on sort variables *) let (_qs, us), (qcst, ucst) = UState.sort_context_set uctx in let (_qs', us'), (qcst', ucst') = UState.sort_context_set uctx' in let uctx = Univ.ContextSet.diff (us, ucst) (us', ucst') in (* XXX we should have a more principled check somewhere *) let () = assert (Sorts.ElimConstraints.is_empty @@ Sorts.ElimConstraints.diff qcst qcst') in uctx in uctx', utyp, used_univs, Default { body = body; opaque = Opaque (ubody, eff) } let make_univs_immediate_default ~poly ~opaque ~uctx ~udecl ~eff ~used_univs body typ = let _, used_univs = universes_of_body_type ~used_univs body typ in (* Since the proof is computed now, we can simply have 1 set of constraints in which we merge the ones for the body and the ones for the typ. We recheck the declaration after restricting with the actually used universes. TODO: check if restrict is really necessary now. *) let uctx = UState.restrict uctx used_univs in let utyp = UState.check_univ_decl ~poly uctx udecl in let utyp = match fst utyp with | Polymorphic_entry _ -> utyp | Monomorphic_entry uctx -> (* the constraints from the body may depend on universes from the side effects, so merge it all together. Example failure if we don't is "l1" in test-suite/success/rewrite.v. Not sure if it makes more sense to merge them in the ustate before restrict/check_univ_decl or here. Since we only do it when monomorphic it shouldn't really matter. *) let puctx = Safe_typing.universes_of_private (SideEff.get eff) in Monomorphic_entry (Univ.ContextSet.union uctx puctx), snd utyp in uctx, utyp, used_univs, Default { body; opaque = if opaque then Opaque (Univ.ContextSet.empty, eff) else Transparent } let make_univs_immediate ~poly ?keep_body_ucst_separate ~opaque ~uctx ~udecl ~eff ~used_univs body typ = (* allow_deferred case *) match keep_body_ucst_separate with | Some initial_euctx when not (PolyFlags.univ_poly poly) -> make_univs_immediate_private_mono ~initial_euctx ~uctx ~udecl ~eff ~used_univs body typ | _ -> (* private_poly_univs case *) if PolyFlags.univ_poly poly && opaque && private_poly_univs () then make_univs_immediate_private_poly ~poly ~uctx ~udecl ~eff ~used_univs body typ else make_univs_immediate_default ~poly ~opaque ~uctx ~udecl ~eff ~used_univs body typ (** [univsbody] are universe-constraints attached to the body-only, used in vio-delayed opaque constants and private poly universes *) let definition_entry_core ?using ?(inline=false) ?types ?(univs=default_named_univ_entry) body = { proof_entry_body = body; proof_entry_secctx = using; proof_entry_type = types; proof_entry_universes = univs; proof_entry_inline_code = inline} let pure_definition_entry ?(opaque=Transparent) ?using ?inline ?types ?univs body = definition_entry_core ?using ?inline ?types ?univs body let definition_entry ?(opaque=false) ?using ?inline ?types ?univs body = let opaque = if opaque then Opaque (Univ.ContextSet.empty, SideEff.empty) else Transparent in definition_entry_core ?using ?inline ?types ?univs (Default { body; opaque }) let delayed_definition_entry ?feedback_id ?using ~univs ?types body = definition_entry_core ?using ?types ~univs (DeferredOpaque { body; feedback_id }) let parameter_entry ?inline ?(univs=default_named_univ_entry) typ = { parameter_entry_secctx = None; parameter_entry_type = typ; parameter_entry_universes = univs; parameter_entry_inline_code = inline; } let primitive_entry ?types c = { prim_entry_type = types; prim_entry_content = c; } let symbol_entry ?(univs=default_named_univ_entry) ~unfold_fix symb_entry_type = { symb_entry_universes = univs; symb_entry_unfold_fix = unfold_fix; symb_entry_type; } type constant_entry = | DefinitionEntry of proof_entry | ParameterEntry of parameter_entry | PrimitiveEntry of primitive_entry | SymbolEntry of symbol_entry module ProofEntry = struct let map_entry_body ~f = function | Default { body = body; opaque } -> Default { body = f body; opaque } | DeferredOpaque { body; feedback_id } -> let body = Future.chain body (fun ((b,c),eff) -> ((f b, c), eff)) in DeferredOpaque { body; feedback_id } let map_entry ~f entry = { entry with proof_entry_body = map_entry_body ~f entry.proof_entry_body; proof_entry_type = Option.map f entry.proof_entry_type } let get_opacity entry = match entry.proof_entry_body with | Default { body; opaque = Transparent } -> false | Default { body; opaque = Opaque _ } -> true | DeferredOpaque _ -> true let force_entry_body entry = match entry.proof_entry_body with | Default { body; opaque } -> body, opaque | DeferredOpaque { body; feedback_id = Some _ } -> CErrors.anomaly (str "Forcing a proof with feedback") | DeferredOpaque { body; feedback_id = None } -> let (body, uctx), eff = Future.force body in body, Opaque (uctx, eff) let force_extract_body entry = match entry.proof_entry_body with | Default { body; opaque = Transparent } -> ((body, Univ.ContextSet.empty), SideEff.empty), false, None | Default { body; opaque = Opaque (uctx, eff) } -> ((body, uctx), eff), true, None | DeferredOpaque { body; feedback_id } -> Future.force body, true, feedback_id end let local_csts = Summary.ref ~name:"local-csts" Cset_env.empty let is_local_constant c = Cset_env.mem c !local_csts type constant_obj = { cst_kind : Decls.logical_kind; cst_locl : Locality.import_status; cst_warn : Globnames.extended_global_reference UserWarn.with_qf option; cst_loc : Loc.t option; } let load_constant i ((sp,kn), obj) = if Nametab.exists_cci sp then raise (DeclareUniv.AlreadyDeclared (None, Libnames.basename sp)); let con = Global.constant_of_delta_kn kn in let gr = GlobRef.ConstRef con in Nametab.push ?user_warns:obj.cst_warn (Nametab.Until i) sp gr; Dumpglob.add_constant_kind con obj.cst_kind; obj.cst_loc |> Option.iter (fun loc -> Nametab.set_cci_src_loc (TrueGlobal gr) loc); begin match obj.cst_locl with | Locality.ImportNeedQualified -> local_csts := Cset_env.add con !local_csts | Locality.ImportDefaultBehavior -> () end (* Opening means making the name without its module qualification available *) let open_constant i ((sp,kn), obj) = (* Never open a local definition *) match obj.cst_locl with | Locality.ImportNeedQualified -> () | Locality.ImportDefaultBehavior -> let con = Global.constant_of_delta_kn kn in Nametab.push (Nametab.Exactly i) sp (GlobRef.ConstRef con) let exists_name id = Decls.variable_exists id || Global.exists_objlabel id let check_exists id = if exists_name id then raise (DeclareUniv.AlreadyDeclared (None, id)) let cache_constant ((sp,kn), obj) = let kn = Global.constant_of_delta_kn kn in let gr = GlobRef.ConstRef kn in Nametab.push ?user_warns:obj.cst_warn (Nametab.Until 1) sp gr; Dumpglob.add_constant_kind kn obj.cst_kind; obj.cst_loc |> Option.iter (fun loc -> Nametab.set_cci_src_loc (TrueGlobal gr) loc) let discharge_constant obj = Some obj let classify_constant cst = Libobject.Substitute let (objConstant : (Id.t * constant_obj) Libobject.Dyn.tag) = let open Libobject in declare_named_object_full { (default_object "CONSTANT") with cache_function = cache_constant; load_function = load_constant; open_function = filtered_open open_constant; classify_function = classify_constant; subst_function = ident_subst_function; discharge_function = discharge_constant } let inConstant v = Libobject.Dyn.Easy.inj v objConstant (* Register the libobjects attached to the constants *) let register_constant loc cst kind ?user_warns local = (* Register the declaration *) let id = Constant.label cst in let loc = fallback_loc id loc in let o = inConstant (id, { cst_kind = kind; cst_locl = local; cst_warn = user_warns; cst_loc = loc; }) in let () = Lib.add_leaf o in (* Register associated data *) Impargs.declare_constant_implicits cst; Notation.declare_ref_arguments_scope (GlobRef.ConstRef cst) let register_side_effect (c, body, role, univs) = (* Register the body in the opaque table *) let () = match body with | None -> () | Some opaque -> Opaques.declare_private_opaque opaque in let id = Constant.label c in let () = register_constant (fallback_loc ~warn:false id None) c Decls.(IsProof Theorem) Locality.ImportDefaultBehavior in let () = match univs with | None -> () | Some univs -> DeclareUniv.declare_univ_binders (ConstRef c) univs in match role with | None -> () | Some (Evd.Schema (ind, kind)) -> DeclareScheme.declare_scheme SuperGlobal kind (ind, GlobRef.ConstRef c) let get_roles export eff = let eff = SideEff.obj eff in let map (c, body) = let role, univs = try (Cmap_env.find c eff) with Not_found -> None, None in (c, body, role, univs) in List.map map export (* This globally defines the side-effects in the environment and registers their libobjects. *) let export_side_effects eff = let export = Global.export_private_constants (SideEff.get eff) in let export = get_roles export eff in List.iter register_side_effect export (* This is different from [export_side_effects] as the former properly declares the body of opaque constants whereas this function keeps them as axioms, see below. *) let register_side_effects pf = let open Names in let pf, eff = Proof.purge_side_effects pf in let () = Global.Internal.reset_safe_env (Evd.get_senv_side_effects eff) in (* We do not have to register the opaque proofs because opaque private constants have no body in the environment, see {!Safe_typing.add_private_constant}. *) let iter kn = let gr = GlobRef.ConstRef kn in let id = Constant.label kn in let sp = Lib.make_path id in Nametab.push (Nametab.Until 1) sp gr in let () = List.iter iter (Safe_typing.constants_of_private @@ Evd.seff_private eff) in pf, SideEff.make eff let record_aux env s_ty s_bo = let open Environ in let in_ty = keep_hyps env s_ty in let v = String.concat " " (CList.map_filter (fun decl -> let id = NamedDecl.get_id decl in if List.exists (NamedDecl.get_id %> Id.equal id) in_ty then None else Some (Id.to_string id)) (keep_hyps env s_bo)) in Aux_file.record_in_aux "context_used" v let cast_pure_proof_entry (e : Constr.constr pproof_entry) = let univ_entry, ctx = extract_monomorphic (fst (e.proof_entry_universes)) in { Entries.definition_entry_body = e.proof_entry_body; definition_entry_secctx = e.proof_entry_secctx; definition_entry_type = e.proof_entry_type; definition_entry_universes = univ_entry; definition_entry_inline_code = e.proof_entry_inline_code; }, ctx type ('a, 'b) effect_entry = | ImmediateEffectEntry : (private_constants Entries.proof_output, unit) effect_entry | DeferredEffectEntry : (private_constants Entries.proof_output Future.computation, unit) effect_entry | PureEntry : (Constr.constr, Constr.constr) effect_entry let section_context_of_opaque_proof_entry (type a b) (entry : (a, b) effect_entry) (body : a) typ = let open Environ in let env = Global.env () in let hyp_typ, hyp_def = if List.is_empty (Environ.named_context env) then Id.Set.empty, Id.Set.empty else let ids_typ = global_vars_set env typ in let (pf : Constr.constr), env = match entry with | PureEntry -> body, env | ImmediateEffectEntry -> let (pf, _), eff = body in let env = Safe_typing.push_private_constants env eff in pf, env | DeferredEffectEntry -> let (pf, _), eff = Future.force body in let env = Safe_typing.push_private_constants env eff in pf, env in let vars = global_vars_set env pf in ids_typ, vars in let () = if Aux_file.recording () then record_aux env hyp_typ hyp_def in Environ.really_needed env (Id.Set.union hyp_typ hyp_def) let cast_opaque_proof_entry (type a b) (entry : (a, b) effect_entry) (e : a pproof_entry) : b Entries.opaque_entry * _ = let typ = match e.proof_entry_type with | None -> assert false | Some typ -> typ in let secctx = match e.proof_entry_secctx with | None -> section_context_of_opaque_proof_entry entry e.proof_entry_body typ | Some hyps -> hyps in let body : b = match entry with | PureEntry -> e.proof_entry_body | ImmediateEffectEntry -> () | DeferredEffectEntry -> () in let univ_entry, ctx = extract_monomorphic (fst (e.proof_entry_universes)) in { Entries.opaque_entry_body = body; opaque_entry_secctx = secctx; opaque_entry_type = typ; opaque_entry_universes = univ_entry; }, ctx let feedback_axiom () = Feedback.(feedback AddedAxiom) let is_unsafe_typing_flags flags = let flags = Option.default (Global.typing_flags ()) flags in let open Declarations in not (flags.check_universes && flags.check_guarded && flags.check_positive) let declare_constant ~loc ?(local = Locality.ImportDefaultBehavior) ~name ~kind ~typing_flags ?user_warns cd = let before_univs = Global.universes () in let make_constant = function (* Logically define the constant and its subproofs, no libobject tampering *) | DefinitionEntry de -> (* We deal with side effects *) begin match de.proof_entry_body with | Default { body; opaque = Transparent } -> let de = { de with proof_entry_body = body } in let e, ctx = cast_pure_proof_entry de in let ubinders = make_ubinders ctx de.proof_entry_universes in Entries.DefinitionEntry e, false, ubinders, None, ctx | Default { body; opaque = Opaque (body_uctx, eff) } -> let body = ((body, body_uctx), SideEff.get eff) in let de = { de with proof_entry_body = body } in let cd, ctx = cast_opaque_proof_entry ImmediateEffectEntry de in let ubinders = make_ubinders ctx de.proof_entry_universes in Entries.OpaqueEntry cd, false, ubinders, Some (Future.from_val body, None), ctx | DeferredOpaque { body; feedback_id } -> let map (body, eff) = body, SideEff.get eff in let body = Future.chain body map in let de = { de with proof_entry_body = body } in let cd, ctx = cast_opaque_proof_entry DeferredEffectEntry de in let ubinders = make_ubinders ctx de.proof_entry_universes in Entries.OpaqueEntry cd, false, ubinders, Some (body, feedback_id), ctx end | ParameterEntry e -> let univ_entry, ctx = extract_monomorphic (fst e.parameter_entry_universes) in let ubinders = make_ubinders ctx e.parameter_entry_universes in let e = { Entries.parameter_entry_secctx = e.parameter_entry_secctx; Entries.parameter_entry_type = e.parameter_entry_type; Entries.parameter_entry_universes = univ_entry; Entries.parameter_entry_inline_code = e.parameter_entry_inline_code; } in Entries.ParameterEntry e, not (Lib.is_modtype_strict()), ubinders, None, ctx | PrimitiveEntry e -> let typ, univ_entry, ctx = match e.prim_entry_type with | None -> None, (UState.Monomorphic_entry Univ.ContextSet.empty, UnivNames.empty_binders), Univ.ContextSet.empty | Some (typ, entry_univs) -> let univ_entry, ctx = extract_monomorphic (fst entry_univs) in Some (typ, univ_entry), entry_univs, ctx in let e = { Entries.prim_entry_type = typ; Entries.prim_entry_content = e.prim_entry_content; } in let ubinders = make_ubinders ctx univ_entry in Entries.PrimitiveEntry e, false, ubinders, None, ctx | SymbolEntry { symb_entry_type=typ; symb_entry_unfold_fix=un_fix; symb_entry_universes=entry_univs } -> let univ_entry, ctx = extract_monomorphic (fst entry_univs) in let e = { Entries.symb_entry_type = typ; Entries.symb_entry_unfold_fix = un_fix; Entries.symb_entry_universes = univ_entry; } in let ubinders = make_ubinders ctx entry_univs in Entries.SymbolEntry e, false, ubinders, None, ctx in let declare_opaque kn = function | None -> () | Some (body, feedback_id) -> let open Declarations in match (Global.lookup_constant kn).const_body with | OpaqueDef o -> let (_, _, _, i) = Opaqueproof.repr o in Opaques.declare_defined_opaque ?feedback_id i body | Def _ | Undef _ | Primitive _ | Symbol _ -> assert false in let () = check_exists name in let decl, unsafe, ubinders, delayed, ctx = make_constant cd in let () = Global.push_context_set ctx in let kn = Global.add_constant ?typing_flags name decl in let () = let is_new_constraint (u,_,v as c) = match UGraph.check_declared_universes before_univs Univ.Level.Set.(add u (add v empty)) with | Ok () -> not (UGraph.check_constraint before_univs c) | Error _ -> true in let ctx = on_snd (Univ.UnivConstraints.filter is_new_constraint) ctx in DeclareUniv.add_constraint_source (ConstRef kn) ctx in let () = DeclareUniv.declare_univ_binders (GlobRef.ConstRef kn) ubinders in let () = declare_opaque kn delayed in let () = register_constant loc kn kind local ?user_warns in if unsafe || is_unsafe_typing_flags typing_flags then feedback_axiom(); kn let declare_private_constant ?role ?ts ~name ~opaque de effs = let de, ctx = if not opaque then let de, ctx = cast_pure_proof_entry de in DefinitionEff de, ctx else let de, ctx = cast_opaque_proof_entry PureEntry de in OpaqueEff de, ctx in Evd.push_side_effects ?role ?ts name de ctx effs let inline_private_constants ~uctx env (body, eff) = let body, ctx = Safe_typing.inline_private_constants env (body, SideEff.get eff) in let uctx = UState.merge_universe_context ~sideff:true Evd.univ_rigid uctx ctx in body, uctx (** Declaration of section variables and local definitions *) type variable_declaration = | SectionLocalDef of { clearbody : bool; entry : proof_entry; } | SectionLocalAssum of { typ : Constr.types; impl : Glob_term.binding_kind; univs : UState.named_universes_entry; } (* This object is only for things which iterate over objects to find variables (only Prettyp.print_context AFAICT) *) let objVariable : Id.t Libobject.Dyn.tag = let open Libobject in declare_object_full { (default_object "VARIABLE") with classify_function = (fun _ -> Dispose)} let inVariable v = Libobject.Dyn.Easy.inj v objVariable let declare_variable ~name ~kind ~typing_flags d = (* Variables are distinguished by only short names *) if Decls.variable_exists name then raise (DeclareUniv.AlreadyDeclared (None, name)); let impl,opaque = match d with (* Fails if not well-typed *) | SectionLocalAssum {typ;impl;univs} -> let () = match fst univs with | UState.Monomorphic_entry uctx -> (* XXX [snd univs] is ignored, should we use it? *) let () = DeclareUniv.name_mono_section_univs (fst uctx) in Global.push_context_set uctx | UState.Polymorphic_entry uctx -> Global.push_section_context uctx in let () = Global.push_named_assum (name,typ) in impl, true | SectionLocalDef { clearbody; entry = de } -> (* The body should already have been forced upstream because it is a section-local definition, but it's not enforced by typing *) let ((body, body_uctx), eff), opaque, feedback_id = ProofEntry.force_extract_body de in let () = export_side_effects eff in (* We must declare the universe constraints before type-checking the term. *) let univs = match fst de.proof_entry_universes with | UState.Monomorphic_entry uctx -> let () = DeclareUniv.name_mono_section_univs (fst uctx) in let () = Global.push_context_set (Univ.ContextSet.union uctx body_uctx) in UState.Monomorphic_entry Univ.ContextSet.empty, UnivNames.empty_binders | UState.Polymorphic_entry uctx -> Global.push_section_context uctx; let mk_anon_names u = let qs, us = UVars.Instance.to_array u in {UVars.quals = Array.make (Array.length qs) Anonymous; UVars.univs = Array.make (Array.length us) Anonymous} in Global.push_section_context (UVars.UContext.of_context_set mk_anon_names (Sorts.QContextSet.empty, body_uctx)); UState.Polymorphic_entry UVars.UContext.empty, UnivNames.empty_binders in let se = if opaque then let cname = Id.of_string (Id.to_string name ^ "_subproof") in let cname = Namegen.next_global_ident_away (Global.safe_env ()) cname Id.Set.empty in let de = { proof_entry_body = DeferredOpaque { body = Future.from_val ((body, Univ.ContextSet.empty), SideEff.empty); feedback_id }; proof_entry_secctx = None; (* de.proof_entry_secctx is NOT respected *) proof_entry_type = de.proof_entry_type; proof_entry_universes = univs; proof_entry_inline_code = de.proof_entry_inline_code; } in let kn = declare_constant ~name:cname ~loc:None ~local:ImportNeedQualified ~kind:(IsProof Lemma) ~typing_flags (DefinitionEntry de) in { Entries.secdef_body = Constr.mkConstU (kn, UVars.Instance.empty); secdef_type = None; } else { Entries.secdef_body = body; secdef_type = de.proof_entry_type; } in let () = Global.push_named_def (name, se) in (* opaque implies clearbody, so we don't see useless "foo := foo_subproof" in the context *) Glob_term.Explicit, opaque || clearbody in Nametab.push (Nametab.Until 1) (Libnames.make_path DirPath.empty name) (GlobRef.VarRef name); Decls.(add_variable_data name {opaque;kind}); Lib.add_leaf (inVariable name); Impargs.declare_var_implicits ~impl name; Notation.declare_ref_arguments_scope (GlobRef.VarRef name) (* Declaration messages *) let pr_rank i = pr_nth (i+1) let fixpoint_message indexes l = Flags.if_verbose Feedback.msg_info (match l with | [] -> CErrors.anomaly (Pp.str "no recursive definition.") | [id] -> Id.print id ++ str " is recursively defined" ++ (match indexes with | Some [|i|] -> str " (guarded on "++pr_rank i++str " argument)" | _ -> mt ()) | l -> hov 0 (prlist_with_sep pr_comma Id.print l ++ spc () ++ str "are recursively defined" ++ match indexes with | Some a -> spc () ++ str "(guarded respectively on " ++ prvect_with_sep pr_comma pr_rank a ++ str " arguments)" | None -> mt ())) let cofixpoint_message l = Flags.if_verbose Feedback.msg_info (match l with | [] -> CErrors.anomaly (Pp.str "No corecursive definition.") | [id] -> Id.print id ++ str " is corecursively defined" | l -> hov 0 (prlist_with_sep pr_comma Id.print l ++ spc () ++ str "are corecursively defined")) let recursive_message indexes l = match indexes with | None -> cofixpoint_message l | Some indexes -> fixpoint_message (Some indexes) l let definition_message id = Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is defined") let assumption_message id = (* Changing "assumed" to "declared", "assuming" referring more to the type of the object than to the name of the object (see discussion on coqdev: "Chapter 4 of the Reference Manual", 8/10/2015) *) Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is declared") (* The word [proof] is to be understood as [justification] *) (* A possible alternatve would be [evidence]?? *) type closed_proof_output = { output_entries : (Constr.t * Constr.t option) list; output_ustate : UState.t; output_sideff : SideEff.t; } type proof_object = | DefaultProof of { proof : closed_proof_output ; opaque : bool ; using : Names.Id.Set.t option ; keep_body_ucst_separate : UState.t option } | DeferredOpaqueProof of { deferred_proof : closed_proof_output Future.computation ; using : Names.Id.Set.t option ; initial_proof_data : Proof.data ; feedback_id : Stateid.t ; initial_euctx : UState.t } let future_map2_pair_list_distribute p l f = List.map_i (fun i c -> f (Future.chain p (fun p -> (List.nth p.output_entries i, p.output_ustate, p.output_sideff))) c) 0 l let process_proof ~info:Info.({ udecl; poly }) ?(is_telescope=false) = function | DefaultProof { proof; opaque; using; keep_body_ucst_separate } -> let { output_entries = entries; output_ustate = uctx; output_sideff = eff } = proof in (* Force transparency for Derive-like dependent statements *) let opaques = let n = List.length entries in List.init n (fun i -> if i < n-1 && is_telescope then (* waiting for addition of cinfo-based opacity in #19029 *) false else opaque) in (* Multiple entries mean either a recursive block of definitions (as in Co/Fixpoint) or a sequence of dependent definitions (as in "Derive"). In the second case, the dependency in the previous entries requires to accumulate the universes from the previous definitions *) let exported_effects = if List.exists not opaques then eff else SideEff.empty in exported_effects, snd (List.fold_left2_map (fun used_univs (body, typ) opaque -> let uctx, univs, used_univs, body = make_univs_immediate ~poly ?keep_body_ucst_separate ~opaque ~uctx ~udecl ~eff ~used_univs body typ in (used_univs, (definition_entry_core ?using ~univs ?types:typ body, uctx))) Univ.Level.Set.empty entries opaques) | DeferredOpaqueProof { deferred_proof = bodies; using; initial_proof_data; feedback_id; initial_euctx } -> let { Proof.poly; entry; sigma } = initial_proof_data in (* Deferred multiple entries currently assume either a mutual Co/Fixpoint or no dependency (thus no "Derive"); to support "Derive"-like statements, we would need a combinator on futures that fold used universes *) SideEff.empty, future_map2_pair_list_distribute bodies (Proofview.initial_goals entry) (fun body_typ_uctx (_, _, initial_typ) -> (* Testing if evar-closed? *) let initial_typ = Evarutil.nf_evars_universes sigma (EConstr.Unsafe.to_constr initial_typ) in (* The flags keep_body_ucst_separate, opaque, etc. should be consistent with evar-closedness? *) let univs = UState.univ_entry ~poly:PolyFlags.default initial_euctx in let body = Future.chain body_typ_uctx (fun ((body, _typ), uctx, eff) -> let uctx = make_univs_deferred_private_mono ~initial_euctx ~uctx ~udecl body (Some initial_typ) in ((body, uctx), eff)) in (delayed_definition_entry ?using ~univs ~types:initial_typ ~feedback_id body, initial_euctx)) let declare_definition_scheme ~univs ~role ~name ~effs c = let entry = pure_definition_entry ~univs c in declare_private_constant ~role ~name ~opaque:false entry effs let register_definition_scheme ~internal ~name ~const:kn ~univs ?loc () = let kind = Decls.(IsDefinition Scheme) in let () = register_constant (fallback_loc ~warn:false name None) kn kind Locality.ImportDefaultBehavior in let () = DeclareUniv.declare_univ_binders (ConstRef kn) univs in Dumpglob.dump_definition (CAst.make ?loc (Constant.label kn)) false "scheme"; let () = if internal then () else definition_message name in () (* Locality stuff *) let declare_entry ~loc ~name ?(scope=Locality.default_scope) ?(clearbody=false) ~kind ~typing_flags ~user_warns ?hook ?(obls=[]) ~impargs ~uctx entry = let should_suggest = ProofEntry.get_opacity entry && not (List.is_empty (Global.named_context())) && Option.is_empty entry.proof_entry_secctx in let dref = match scope with | Locality.Discharge -> let () = declare_variable ~typing_flags ~name ~kind (SectionLocalDef {clearbody; entry}) in if should_suggest then Proof_using.suggest_variable (Global.env ()) name; Names.GlobRef.VarRef name | Locality.Global local -> assert (not clearbody); let kn = declare_constant ~loc ~name ~local ~kind ~typing_flags ?user_warns (DefinitionEntry entry) in let gr = Names.GlobRef.ConstRef kn in if should_suggest then Proof_using.suggest_constant (Global.env ()) kn; gr in let () = Impargs.maybe_declare_manual_implicits false dref impargs in let () = definition_message name in Hook.call ?hook { Hook.S.uctx; obls; scope; dref }; dref let warn_let_as_axiom = CWarnings.create ~name:"let-as-axiom" ~category:CWarnings.CoreCategories.vernacular Pp.(fun id -> strbrk "Let definition" ++ spc () ++ Names.Id.print id ++ spc () ++ strbrk "declared as an axiom.") (* Declare an assumption when not in a section: Parameter/Axiom but also Variable/Hypothesis seen as Local Parameter/Axiom *) let declare_parameter ~loc ~name ~scope ~hook ~impargs ~uctx pe = let local = match scope with | Locality.Discharge -> warn_let_as_axiom name; Locality.ImportNeedQualified | Locality.Global local -> local in let kind = Decls.(IsAssumption Conjectural) in let decl = ParameterEntry pe in let cst = declare_constant ~loc ~name ~local ~kind ~typing_flags:None decl in let dref = Names.GlobRef.ConstRef cst in let () = Impargs.maybe_declare_manual_implicits false dref impargs in let () = assumption_message name in let () = Hook.(call ?hook { S.uctx; obls = []; scope; dref}) in cst (* Using processing *) let interp_proof_using_gen f env evd cinfo using = let cextract v (fixnames, terms) = let name, new_terms = f v in name :: fixnames, new_terms @ terms in let fixnames, terms = CList.fold_right cextract cinfo ([],[]) in Proof_using.definition_using env evd ~fixnames ~terms ~using let interp_proof_using_cinfo env evd cinfo using = let f { CInfo.name; typ; _ } = name, [typ] in interp_proof_using_gen f env evd cinfo using let gather_mutual_using_data cinfo = List.fold_left2 (fun acc CInfo.{name} (body, typ) -> let l = Option.List.flatten EConstr.[Option.map of_constr typ; Some (of_constr body)] in (name, l) :: acc) [] cinfo let interp_mutual_using env cinfo bodies_types using = let evd = Evd.from_env env in Option.map (fun using -> let cinfos = gather_mutual_using_data cinfo bodies_types in let f x = x in interp_proof_using_gen f env evd cinfos using) using let declare_possibly_mutual_definitions ~info ~cinfo ~obls ?(is_telescope=false) obj = let eff, entries = process_proof ~info ~is_telescope obj in let () = export_side_effects eff in let { Info.hook; scope; clearbody; kind; typing_flags; user_warns; ntns; _ } = info in let _, refs = List.fold_left2_map (fun subst CInfo.{name; impargs; loc} (entry, uctx) -> (* replacing matters for Derive-like statement but it does not hurt otherwise *) let entry = ProofEntry.map_entry entry ~f:(Vars.replace_vars subst) in let gref = declare_entry ~loc ~name ~scope ~clearbody ~kind ?hook ~impargs ~typing_flags ~user_warns ~obls ~uctx entry in let inst = instance_of_univs entry.proof_entry_universes in let const = Constr.mkRef (gref, inst) in ((name, const) :: subst, gref)) [] cinfo entries in let () = (* For the recursive case, we override the temporary notations used while proving, now using the global names *) let local = info.scope=Locality.Discharge in if ntns <> [] then CWarnings.with_warn ("-"^Notation.warning_overridden_name) (List.iter (Metasyntax.add_notation_interpretation ~local (Global.env()))) ntns in refs let declare_possibly_mutual_parameters ~info ~cinfo ?(mono_uctx_extra=UState.empty) ~sec_vars typs = (* Note, if an initial uctx, minimize and restrict have not been done *) (* if the uctx of an abandonned proof, minimize is redundant (see close_proof) *) let { Info.scope; poly; hook; udecl } = info in pi3 (List.fold_left2 ( fun (i, subst, csts) { CInfo.name; loc; impargs } (typ, uctx) -> let uctx' = UState.restrict uctx (Vars.universes_of_constr typ) in let univs = UState.check_univ_decl ~poly uctx' udecl in let univs = if i = 0 then add_mono_uctx mono_uctx_extra univs else univs in let typ = Vars.replace_vars subst typ in let pe = { parameter_entry_secctx = sec_vars; parameter_entry_type = Evarutil.nf_evars_universes (Evd.from_ctx uctx) typ; parameter_entry_universes = univs; parameter_entry_inline_code = None; } in let cst = declare_parameter ~loc ~name ~scope ~hook ~impargs ~uctx pe in let inst = instance_of_univs univs in (i+1, (name, Constr.mkConstU (cst,inst))::subst, (cst, univs)::csts) ) (0, [], []) cinfo typs) let make_recursive_bodies ?elim_to env ~typing_flags ~possible_guard ~rec_declaration = let env = Environ.update_typing_flags ?typing_flags env in let indexes = Pretyping.search_guard ?elim_to env possible_guard rec_declaration in let mkbody i = match indexes with | Some indexes -> Constr.mkFix ((indexes,i), rec_declaration) | None -> Constr.mkCoFix (i, rec_declaration) in List.map_i (fun i typ -> (mkbody i, typ)) 0 (Array.to_list (pi2 rec_declaration)), indexes let prepare_recursive_declaration cinfo fixtypes fixrs fixdefs = let fixnames = List.map (fun CInfo.{name} -> name) cinfo in let names = List.map2 (fun name r -> Context.make_annot (Name name) r) fixnames fixrs in let defs = List.map (Vars.subst_vars (List.rev fixnames)) fixdefs in (Array.of_list names, Array.of_list fixtypes, Array.of_list defs) let prepare_recursive_edeclaration sigma cinfo fixtypes fixrs fixdefs = let fixnames = List.map (fun CInfo.{name} -> name) cinfo in let names = List.map2 (fun name r -> Context.make_annot (Name name) r) fixnames fixrs in let defs = List.map (EConstr.Vars.subst_vars sigma (List.rev fixnames)) fixdefs in (Array.of_list names, Array.of_list fixtypes, Array.of_list defs) let declare_mutual_definitions ~info ~cinfo ~opaque ~eff ~uctx ~bodies ~possible_guard ?using () = (* Note: uctx is supposed to be already minimized *) let { Info.typing_flags; _ } = info in let env = Global.env() in let possible_guard, fixrelevances = possible_guard in let fixtypes = List.map (fun CInfo.{typ} -> typ) cinfo in let rec_declaration = prepare_recursive_declaration cinfo fixtypes fixrelevances bodies in let elim_to = Inductive.eliminates_to @@ UState.elim_graph uctx in let bodies_types, indexes = make_recursive_bodies ~elim_to env ~typing_flags ~rec_declaration ~possible_guard in let entries = List.map (fun (body, typ) -> (body, Some typ)) bodies_types in let entries_for_using = List.map (fun (body, typ) -> (body, Some typ)) bodies_types in let using = interp_mutual_using env cinfo entries_for_using using in let proof = { output_entries = entries; output_ustate = uctx; output_sideff = SideEff.make eff } in let obj = DefaultProof { proof; opaque; using; keep_body_ucst_separate = None } in let refs = declare_possibly_mutual_definitions ~info ~cinfo ~obls:[] obj in let fixnames = List.map (fun { CInfo.name } -> name) cinfo in recursive_message indexes fixnames; refs (* Preparing proof entries *) let error_unresolved_evars env sigma t evars = let pr_unresolved_evar e = hov 2 (str"- " ++ Printer.pr_existential_key env sigma e ++ str ": " ++ Himsg.explain_pretype_error env sigma (Pretype_errors.UnsolvableImplicit (e,None))) in CErrors.user_err (hov 0 begin str "The following term contains unresolved implicit arguments:"++ fnl () ++ str " " ++ Printer.pr_econstr_env env sigma t ++ fnl () ++ str "More precisely: " ++ fnl () ++ v 0 (prlist_with_sep cut pr_unresolved_evar (Evar.Set.elements evars)) end) let check_evars_are_solved env sigma t = let evars = Evarutil.undefined_evars_of_term sigma t in if not (Evar.Set.is_empty evars) then error_unresolved_evars env sigma t evars let declare_definition ~info ~cinfo ~opaque ~obls ~body ?using sigma = let { CInfo.name; typ; _ } = cinfo in let env = Global.env () in Option.iter (check_evars_are_solved env sigma) typ; check_evars_are_solved env sigma body; let sigma = Evd.minimize_universes sigma in let body = EConstr.to_constr sigma body in let typ = Option.map (EConstr.to_constr sigma) typ in let uctx = Evd.ustate sigma in let eff = SideEff.make @@ Evd.eval_side_effects sigma in let using = interp_mutual_using env [cinfo] [body,typ] using in let proof = { output_entries = [(body, typ)]; output_ustate = uctx; output_sideff = eff } in let obj = DefaultProof { proof; opaque; using; keep_body_ucst_separate = None } in let gref = List.hd (declare_possibly_mutual_definitions ~info ~cinfo:[cinfo] ~obls obj) in gref, uctx let prepare_obligations ~name poly ?types ~body env sigma = let env = Global.env () in let types = match types with | Some t -> t | None -> Retyping.get_type_of env sigma body in let sigma, (body, types) = Evarutil.finalize ~abort_on_undefined_evars:false sigma (fun nf -> nf body, nf types) in RetrieveObl.check_evars env sigma; let body, types = EConstr.(of_constr body, of_constr types) in let obls, (_, evmap), body, cty = RetrieveObl.retrieve_obligations env name sigma 0 body types in let uctx = Evd.ustate sigma in body, cty, uctx, evmap, obls let prepare_parameter ~poly ~udecl ~types sigma = let env = Global.env () in Pretyping.check_evars_are_solved ~program_mode:false env sigma; let sigma, typ = Evarutil.finalize ~abort_on_undefined_evars:true sigma (fun nf -> nf types) in let univs = Evd.check_univ_decl ~poly sigma udecl in let pe = { parameter_entry_secctx = None; parameter_entry_type = typ; parameter_entry_universes = univs; parameter_entry_inline_code = None; } in sigma, pe type progress = Remain | Dependent | Defined module Obls_ = struct open Constr type 'a obligation_body = DefinedObl of 'a | TermObl of constr module Obligation = struct type t = { obl_name : Id.t ; obl_type : types ; obl_location : Evar_kinds.t Loc.located ; obl_body : pconstant obligation_body option ; obl_status : bool * Evar_kinds.obligation_definition_status ; obl_deps : Int.Set.t ; obl_tac : unit Proofview.tactic option } let set_type ~typ obl = {obl with obl_type = typ} end type obligations = {obls : Obligation.t array; remaining : int} type fixpoint_kind = IsFixpoint of lident option list | IsCoFixpoint module ProgramDecl = struct type 'a t = { prg_cinfo : constr CInfo.t ; prg_info : Info.t ; prg_using : Vernacexpr.section_subset_expr option ; prg_opaque : bool ; prg_hook : 'a option ; prg_body : constr ; prg_uctx : UState.t ; prg_obligations : obligations ; prg_deps : Id.t list ; prg_possible_guard : (Pretyping.possible_guard * Sorts.relevance list) option (* None = not recursive *) ; prg_reduce : constr -> constr } open Obligation let make ~info ~cinfo ~opaque ~reduce ~deps ~uctx ~body ~possible_guard ?obl_hook ?using obls = let obls', body = match body with | None -> assert (Int.equal (Array.length obls) 0); let n = Nameops.add_suffix cinfo.CInfo.name "_obligation" in ( [| { obl_name = n ; obl_body = None ; obl_location = Loc.tag Evar_kinds.InternalHole ; obl_type = cinfo.CInfo.typ ; obl_status = (false, Evar_kinds.Expand) ; obl_deps = Int.Set.empty ; obl_tac = None } |] , mkVar n ) | Some b -> ( Array.mapi (fun i (n, t, l, o, d, tac) -> { obl_name = n ; obl_body = None ; obl_location = l ; obl_type = t ; obl_status = o ; obl_deps = d ; obl_tac = tac }) obls , b ) in let prg_uctx = if PolyFlags.univ_poly info.Info.poly then uctx else (* declare global univs of the main constant before we do obligations *) let uctx = UState.collapse_sort_variables uctx in let ctx = UState.check_mono_sort_constraints uctx in let () = Global.push_context_set ctx in let cst = Constant.make2 (Lib.current_mp()) cinfo.CInfo.name in let () = DeclareUniv.declare_univ_binders (ConstRef cst) (UState.univ_entry ~poly:info.Info.poly uctx) in UState.Internal.reboot (Global.env()) uctx in { prg_cinfo = { cinfo with CInfo.typ = reduce cinfo.CInfo.typ } ; prg_info = info ; prg_using = using ; prg_hook = obl_hook ; prg_opaque = opaque ; prg_body = body ; prg_uctx ; prg_obligations = {obls = obls'; remaining = Array.length obls'} ; prg_deps = deps ; prg_possible_guard = possible_guard ; prg_reduce = reduce } let show prg = let { CInfo.name; typ; _ } = prg.prg_cinfo in let env = Global.env () in let sigma = Evd.from_env env in Id.print name ++ spc () ++ str ":" ++ spc () ++ Printer.pr_constr_env env sigma typ ++ spc () ++ str ":=" ++ fnl () ++ Printer.pr_constr_env env sigma prg.prg_body module Internal = struct let get_name prg = prg.prg_cinfo.CInfo.name let get_uctx prg = prg.prg_uctx let set_uctx ~uctx prg = {prg with prg_uctx = uctx} let get_poly prg = prg.prg_info.Info.poly let get_obligations prg = prg.prg_obligations let get_using prg = prg.prg_using end end open Obligation open ProgramDecl (* Saving an obligation *) (* XXX: Is this the right place for this? *) let it_mkLambda_or_LetIn_or_clean t ctx = let open Context.Rel.Declaration in let fold t decl = if is_local_assum decl then Term.mkLambda_or_LetIn decl t else if Vars.noccurn 1 t then Vars.subst1 mkProp t else Term.mkLambda_or_LetIn decl t in Context.Rel.fold_inside fold ctx ~init:t (* XXX: Is this the right place for this? *) let decompose_lam_prod c ty = let open Context.Rel.Declaration in let rec aux ctx c ty = match (Constr.kind c, Constr.kind ty) with | LetIn (x, b, t, c), LetIn (x', b', t', ty) when Constr.equal b b' && Constr.equal t t' -> let ctx' = Context.Rel.add (LocalDef (x, b', t')) ctx in aux ctx' c ty | _, LetIn (x', b', t', ty) -> let ctx' = Context.Rel.add (LocalDef (x', b', t')) ctx in aux ctx' (lift 1 c) ty | LetIn (x, b, t, c), _ -> let ctx' = Context.Rel.add (LocalDef (x, b, t)) ctx in aux ctx' c (lift 1 ty) | Lambda (x, b, t), Prod (x', b', t') (* By invariant, must be convertible *) -> let ctx' = Context.Rel.add (LocalAssum (x, b')) ctx in aux ctx' t t' | Cast (c, _, _), _ -> aux ctx c ty | _, _ -> (ctx, c, ty) in aux Context.Rel.empty c ty (* XXX: What's the relation of this with Abstract.shrink ? *) let shrink_body c ty = let ctx, b, ty = match ty with | None -> let ctx, b = Term.decompose_lambda_decls c in (ctx, b, None) | Some ty -> let ctx, b, ty = decompose_lam_prod c ty in (ctx, b, Some ty) in let b', ty', n, args = List.fold_left (fun (b, ty, i, args) decl -> if Vars.noccurn 1 b && Option.cata (Vars.noccurn 1) true ty then (Vars.subst1 mkProp b, Option.map (Vars.subst1 mkProp) ty, succ i, args) else let open Context.Rel.Declaration in let args = if is_local_assum decl then mkRel i :: args else args in ( Term.mkLambda_or_LetIn decl b , Option.map (Term.mkProd_or_LetIn decl) ty , succ i , args )) (b, ty, 1, []) ctx in (ctx, b', ty', Array.of_list args) (***********************************************************************) (* Saving an obligation *) (***********************************************************************) let universes_of_decl body typ = let univs_typ = match typ with None -> Univ.Level.Set.empty | Some ty -> Vars.universes_of_constr ty in let univs_body = Vars.universes_of_constr body in Univ.Level.Set.union univs_body univs_typ let update_global_obligation_uctx prg uctx = let uctx = if PolyFlags.univ_poly prg.prg_info.Info.poly then (* Accumulate the polymorphic constraints *) UState.union prg.prg_uctx uctx else (* The monomorphic universe context of the main constant has been declared by the first obligation; it is now in the global env and we now remove it for the further declarations *) UState.Internal.reboot (Global.env ()) uctx in ProgramDecl.Internal.set_uctx ~uctx prg let declare_obligation prg obl ~uctx ~types ~body = let body = prg.prg_reduce body in let types = Option.map prg.prg_reduce types in match obl.obl_status with | _, Evar_kinds.Expand -> let prg_uctx = UState.union prg.prg_uctx uctx in let prg = ProgramDecl.Internal.set_uctx ~uctx:prg_uctx prg in (prg, {obl with obl_body = Some (TermObl body)}, []) | force, Evar_kinds.Define opaque -> let opaque = (not force) && opaque in let poly = prg.prg_info.Info.poly in let ctx, body, ty, args = if not (PolyFlags.univ_poly poly) then shrink_body body types else ([], body, types, [||]) in let uctx' = UState.restrict uctx (universes_of_decl body types) in let univs = UState.univ_entry ~poly uctx' in let inst = instance_of_univs univs in let ce = definition_entry ?types:ty ~opaque ~univs body in (* ppedrot: seems legit to have obligations as local *) let constant = declare_constant ~loc:(fallback_loc ~warn:false obl.obl_name None) ~name:obl.obl_name ~typing_flags:prg.prg_info.Info.typing_flags ~local:Locality.ImportNeedQualified ~kind:Decls.(IsProof Property) (DefinitionEntry ce) in definition_message obl.obl_name; let prg = update_global_obligation_uctx prg uctx in let body = if PolyFlags.univ_poly poly then DefinedObl (constant, inst) else let const = mkConstU (constant, inst) in TermObl (it_mkLambda_or_LetIn_or_clean (mkApp (const, args)) ctx) in (prg, {obl with obl_body = Some body}, [GlobRef.ConstRef constant]) (* Updating the obligation meta-info on close *) let not_transp_msg = Pp.( str "Obligation should be transparent but was declared opaque." ++ spc () ++ str "Use 'Defined' instead.") let err_not_transp () = CErrors.user_err not_transp_msg module ProgMap = Id.Map module State = struct type t = prg_hook ProgramDecl.t CEphemeron.key ProgMap.t and prg_hook = PrgHook of t Hook.g let call_prg_hook { prg_hook=hook } x pm = let hook = Option.map (fun (PrgHook h) -> h) hook in Hook.call_g ?hook x pm let empty = ProgMap.empty let pending pm = ProgMap.filter (fun _ v -> (CEphemeron.get v).prg_obligations.remaining > 0) pm let num_pending pm = pending pm |> ProgMap.cardinal let first_pending pm = pending pm |> ProgMap.choose_opt |> Option.map (fun (_, v) -> CEphemeron.get v) let get_unique_open_prog pm name : (_, Id.t list) result = match name with | Some n -> Option.cata (fun p -> Ok (CEphemeron.get p)) (Error []) (ProgMap.find_opt n pm) | None -> ( let n = num_pending pm in match n with | 0 -> Error [] | 1 -> Option.cata (fun p -> Ok p) (Error []) (first_pending pm) | _ -> let progs = Id.Set.elements (ProgMap.domain pm) in Error progs ) let add t key prg = ProgMap.add key (CEphemeron.create prg) t let fold t ~f ~init = let f k v acc = f k (CEphemeron.get v) acc in ProgMap.fold f t init let all pm = ProgMap.bindings pm |> List.map (fun (_,v) -> CEphemeron.get v) let find m t = ProgMap.find_opt t m |> Option.map CEphemeron.get module View = struct module Obl = struct type t = { name : Id.t ; loc : Loc.t option ; status : bool * Evar_kinds.obligation_definition_status ; solved : bool } let make (o : Obligation.t) = let { obl_name; obl_location; obl_status; obl_body; _ } = o in { name = obl_name ; loc = fst obl_location ; status = obl_status ; solved = Option.has_some obl_body } end type t = { opaque : bool ; remaining : int ; obligations : Obl.t array } let make { prg_opaque; prg_obligations; _ } = { opaque = prg_opaque ; remaining = prg_obligations.remaining ; obligations = Array.map Obl.make prg_obligations.obls } let make eph = CEphemeron.get eph |> make end let view s = Id.Map.map View.make s end (* In all cases, the use of the map is read-only so we don't expose the ref *) let map_non_empty_keys is_empty m = ProgMap.fold (fun k prg l -> if is_empty prg then l else k :: l) m [] let check_solved_obligations is_empty ~pm ~what_for : unit = if not (ProgMap.is_empty pm) then let keys = map_non_empty_keys is_empty pm in let have_string = if Int.equal (List.length keys) 1 then " has " else " have " in CErrors.user_err Pp.( str "Unsolved obligations when closing " ++ what_for ++ str ":" ++ spc () ++ prlist_with_sep spc (fun x -> Id.print x) keys ++ str have_string ++ str "unsolved obligations." ) let map_replace k v m = ProgMap.add k (CEphemeron.create v) (ProgMap.remove k m) let progmap_remove pm prg = ProgMap.remove prg.prg_cinfo.CInfo.name pm let progmap_replace prg' pm = map_replace prg'.prg_cinfo.CInfo.name prg' pm let obligations_solved prg = Int.equal prg.prg_obligations.remaining 0 let obligations_message rem = Format.asprintf "%s %s remaining" (if rem > 0 then string_of_int rem else "No more") (CString.plural rem "obligation") |> Pp.str |> Flags.if_verbose Feedback.msg_info let get_obligation_body expand obl = match obl.obl_body with | None -> None | Some c -> ( if expand && snd obl.obl_status == Evar_kinds.Expand then match c with | DefinedObl pc -> Some (Environ.constant_value_in (Global.env ()) pc) | TermObl c -> Some c else match c with DefinedObl pc -> Some (mkConstU pc) | TermObl c -> Some c ) let obl_substitution expand obls deps = Int.Set.fold (fun x acc -> let xobl = obls.(x) in match get_obligation_body expand xobl with | None -> acc | Some oblb -> (xobl.obl_name, (xobl.obl_type, oblb)) :: acc) deps [] let rec intset_to = function | -1 -> Int.Set.empty | n -> Int.Set.add n (intset_to (pred n)) let obligation_substitution expand prg = let obls = prg.prg_obligations.obls in let ints = intset_to (pred (Array.length obls)) in obl_substitution expand obls ints let subst_prog subst prg = let subst' = List.map (fun (n, (_, b)) -> (n, b)) subst in ( Vars.replace_vars subst' prg.prg_body , Vars.replace_vars subst' (* Termops.refresh_universes *) prg.prg_cinfo.CInfo.typ ) let declare_definition ~pm prg = let varsubst = obligation_substitution true prg in let sigma = Evd.from_ctx prg.prg_uctx in let body, types = subst_prog varsubst prg in let body, types = EConstr.(of_constr body, of_constr types) in let cinfo = { prg.prg_cinfo with CInfo.typ = Some types } in let name, info, opaque, using = prg.prg_cinfo.CInfo.name, prg.prg_info, prg.prg_opaque, prg.prg_using in let obls = List.map (fun (id, (_, c)) -> (id, c)) varsubst in (* XXX: This is doing normalization twice *) let kn, uctx = declare_definition ~cinfo ~info ~obls ~body ~opaque ?using sigma in (* XXX: We call the obligation hook here, by consistency with the previous imperative behaviour, however I'm not sure this is right *) let pm = State.call_prg_hook prg { Hook.S.uctx; obls; scope = prg.prg_info.Info.scope; dref = kn} pm in let pm = progmap_remove pm prg in pm, kn let declare_mutual_definitions ~pm l = let first = List.hd l in let defobl x = let oblsubst = obligation_substitution true x in let subs, typ = subst_prog oblsubst x in let sigma = Evd.from_ctx x.prg_uctx in let term = EConstr.of_constr subs in let typ = EConstr.of_constr typ in let term = EConstr.to_constr sigma term in let typ = EConstr.to_constr sigma typ in let def = (x.prg_reduce term, x.prg_reduce typ, x.prg_cinfo.CInfo.impargs) in let oblsubst = List.map (fun (id, (_, c)) -> (id, c)) oblsubst in (def, oblsubst) in let defs, obls = List.split (List.map defobl l) in let obls = List.flatten obls in let fixitems = List.map2 (fun (d, typ, impargs) name -> let loc = fallback_loc ~warn:false name None in CInfo.make ?loc ~name ~typ ~impargs ()) defs first.prg_deps in let fixdefs, fixtypes, _ = List.split3 defs in let possible_guard = Option.get first.prg_possible_guard in (* Declare the recursive definitions *) let kns = declare_mutual_definitions ~info:first.prg_info ~eff:Evd.empty_side_effects (* FIXME? *) ~uctx:first.prg_uctx ~bodies:fixdefs ~possible_guard ~opaque:first.prg_opaque ~cinfo:fixitems ?using:first.prg_using () in (* Only for the first constant *) let dref = List.hd kns in let scope = first.prg_info.Info.scope in let s_hook = {Hook.S.uctx = first.prg_uctx; obls; scope; dref} in Hook.call ?hook:first.prg_info.Info.hook s_hook; (* XXX: We call the obligation hook here, by consistency with the previous imperative behaviour, however I'm not sure this is right *) let pm = State.call_prg_hook first s_hook pm in let pm = List.fold_left progmap_remove pm l in pm, dref let update_obls ~pm prg obls rem = let prg_obligations = {obls; remaining = rem} in let prg' = {prg with prg_obligations} in let pm = progmap_replace prg' pm in obligations_message rem; if rem > 0 then pm, Remain else match prg'.prg_deps with | [] -> let pm, kn = declare_definition ~pm prg' in pm, Defined | l -> let progs = List.map (fun x -> CEphemeron.get (ProgMap.find x pm)) prg'.prg_deps in if List.for_all (fun x -> obligations_solved x) progs then let pm, kn = declare_mutual_definitions ~pm progs in pm, Defined else pm, Dependent let dependencies obls n = let res = ref Int.Set.empty in Array.iteri (fun i obl -> if (not (Int.equal i n)) && Int.Set.mem n obl.obl_deps then res := Int.Set.add i !res) obls; !res let update_program_decl_on_defined ~pm prg obls num obl rem ~auto = let obls = Array.copy obls in let () = obls.(num) <- obl in let pm, _progress = update_obls ~pm prg obls (pred rem) in let pm = if pred rem > 0 then let deps = dependencies obls num in if not (Int.Set.is_empty deps) then auto ~pm (Some prg.prg_cinfo.CInfo.name) deps None else pm else pm in pm type obligation_resolver = pm:State.t -> Id.t option -> Int.Set.t -> unit Proofview.tactic option -> State.t type obl_check_final = AllFinal | SpecificFinal of Id.t type obligation_qed_info = { name : Id.t; num : int; auto : obligation_resolver; check_final : obl_check_final option; } let not_final_obligation n = let msg = match n with | AllFinal -> str "This obligation is not final." | SpecificFinal n -> str "This obligation is not final for program " ++ Id.print n ++ str "." in CErrors.user_err msg let do_check_final ~pm = function | None -> () | Some check_final -> let final = match check_final with | AllFinal -> begin match State.first_pending pm with | Some _ -> false | None -> true end | SpecificFinal n -> begin match State.get_unique_open_prog pm (Some n) with | Error _ -> true | Ok _ -> false end in if not final then not_final_obligation check_final let obligation_terminator ~pm ~entry ~eff ~uctx ~oinfo:{name; num; auto; check_final} = let env = Global.env () in let ty = entry.proof_entry_type in let body, opaque = ProofEntry.force_entry_body entry in let body, eff = match opaque with | Transparent -> (body, Univ.ContextSet.empty), eff | Opaque (uctx, eff) -> (body, uctx), eff in (* TODO: we always inline effects here, maybe we could export them when transparent? *) let body, uctx = inline_private_constants ~uctx env (body, eff) in let sigma = Evd.from_ctx uctx in Inductiveops.control_only_guard (Global.env ()) sigma (EConstr.of_constr body); (* Declare the obligation ourselves and drop the hook *) let prg = Option.get (State.find pm name) in let {obls; remaining = rem} = prg.prg_obligations in let obl = obls.(num) in let status = match (obl.obl_status, ProofEntry.get_opacity entry) with | (_, Evar_kinds.Expand), true -> err_not_transp () | (true, _), true -> err_not_transp () | (false, _), true -> Evar_kinds.Define true | (_, Evar_kinds.Define true), false -> Evar_kinds.Define false | (_, status), false -> status in let obl = {obl with obl_status = (false, status)} in let prg, obl, cst = declare_obligation prg obl ~body ~types:ty ~uctx in let pm = update_program_decl_on_defined ~pm prg obls num obl rem ~auto in let () = do_check_final ~pm check_final in pm, cst (* Similar to the terminator but for the admitted path; this assumes the admitted constant was already declared. FIXME: There is duplication of this code with obligation_terminator and Obligations.admit_obligations *) let obligation_admitted_terminator ~pm typ {name; num; auto; check_final} declare_fun sec_vars uctx = let prg = Option.get (State.find pm name) in let {obls; remaining = rem} = prg.prg_obligations in let obl = obls.(num) in let () = match obl.obl_status with | true, Evar_kinds.Expand | true, Evar_kinds.Define true -> err_not_transp () | _ -> () in let mono_uctx_extra = if PolyFlags.univ_poly prg.prg_info.Info.poly then UState.empty else prg.prg_uctx in let cst, univs = declare_fun ~uctx ~mono_uctx_extra typ in let inst = instance_of_univs univs in let obl = {obl with obl_body = Some (DefinedObl (cst, inst))} in let prg = update_global_obligation_uctx prg uctx in let pm = update_program_decl_on_defined ~pm prg obls num obl rem ~auto in let () = do_check_final ~pm check_final in pm end (************************************************************************) (* Handling of interactive proofs *) (************************************************************************) module Proof_ending = struct type t = | Regular | End_obligation of Obls_.obligation_qed_info | End_equations of { hook : pm:Obls_.State.t -> Constant.t list -> Evd.evar_map -> Obls_.State.t ; i : Id.t ; types : (Environ.env * Evar.t * Evd.undefined Evd.evar_info * EConstr.named_context * Evd.econstr) list ; sigma : Evd.evar_map } end module Proof_info = struct type t = { cinfo : unit CInfo.t list (** cinfo contains each individual constant info in a mutual decl *) ; info : Info.t ; proof_ending : Proof_ending.t CEphemeron.key (* This could be improved and the CEphemeron removed *) ; possible_guard : (Pretyping.possible_guard * Evd.erelevance list) option (* None = not recursive *) (** thms and compute guard are specific only to start_definition + regular terminator, so we could make this per-proof kind *) } let make ~cinfo ~info ?possible_guard ?(proof_ending=Proof_ending.Regular) () = { cinfo ; info ; possible_guard ; proof_ending = CEphemeron.create proof_ending } end module Proof_object = struct type t = { proof_object : proof_object ; pinfo : Proof_info.t } end module Proof = struct type nonrec closed_proof_output = closed_proof_output type proof_object = Proof_object.t type t = { endline_tactic : Gentactic.glob_generic_tactic option ; using : Id.Set.t option ; proof : Proof.t ; initial_euctx : UState.t (** The initial universe context (for the statement) *) ; pinfo : Proof_info.t ; sideff : SideEff.t; (** Local constants to replay at the end of the proof. Invariant: the global environment already contains these constants, including non-logical data such as nametab and the like. Note that the evarmap within Proof.t may also contain side-effects, but these ones are not yet globally registered. *) } (*** Proof Global manipulation ***) let get ps = ps.proof let get_name ps = (Proof.data ps.proof).Proof.name let fold ~f p = f p.proof let map ~f p = { p with proof = f p.proof } let map_fold ~f p = let proof, res = f p.proof in { p with proof }, res let map_fold_endline ~f ps = let (newpr,ret) = f ps.endline_tactic ps.proof in let ps = { ps with proof = newpr } in ps, ret let compact pf = map ~f:Proof.compact pf (* Sets the tactic to be used when a tactic line is closed with [...] *) let set_endline_tactic tac ps = { ps with endline_tactic = Some tac } let initialize_named_context_for_proof () = let sign = Global.named_context () in List.fold_right (fun d signv -> let id = NamedDecl.get_id d in let d = if Decls.variable_opacity id then NamedDecl.drop_body d else d in Environ.push_named_context_val d signv) sign Environ.empty_named_context_val let start_proof_core ~name ~pinfo ?using sigma goals = (* In ?sign, we remove the bodies of variables in the named context marked "opaque", this is a hack tho, see #10446, and build_constant_by_tactic uses a different method that would break program_inference_hook *) let { Proof_info.info = { Info.poly; typing_flags; _ }; _ } = pinfo in let goals = List.map (fun (sign, typ) -> let sign = match sign with None -> initialize_named_context_for_proof () | Some sign -> sign in (Global.env_of_context sign, typ)) goals in let proof = Proof.start ~name ~poly ?typing_flags sigma goals in let initial_euctx = Evd.ustate Proof.((data proof).sigma) in { proof ; endline_tactic = None ; using ; initial_euctx ; pinfo ; sideff = SideEff.empty } (** [start_proof ~info ~cinfo sigma] starts a proof of [cinfo]. The proof is started in the evar map [sigma] (which can typically contain universe constraints) *) let start_core ~info ~cinfo ?proof_ending ?using sigma = let { CInfo.name; typ; _ } = cinfo in check_exists name; let cinfo = [{ cinfo with CInfo.typ = () }] in let pinfo = Proof_info.make ~cinfo ~info ?proof_ending () in start_proof_core ~name ~pinfo ?using sigma [None,typ] let start = start_core ?proof_ending:None let start_dependent ~info ~cinfo ~name ~proof_ending goals = let { Info.poly; typing_flags; _ } = info in let proof = Proof.dependent_start ~name ~poly ?typing_flags goals in let initial_euctx = Evd.ustate Proof.((data proof).sigma) in let pinfo = Proof_info.make ~info ~cinfo ~proof_ending () in { proof ; endline_tactic = None ; using = None ; initial_euctx ; pinfo ; sideff = SideEff.empty } let start_derive ~name ~info ~cinfo goals = let proof_ending = Proof_ending.Regular in start_dependent ~info ~cinfo ~name ~proof_ending goals let start_equations ~name ~info ~hook ~types sigma goals = let proof_ending = Proof_ending.End_equations {hook; i=name; types; sigma} in start_dependent ~name ~cinfo:[] ~info ~proof_ending goals let start_definition ~info ~cinfo ?using sigma = let { CInfo.name; typ; args } = cinfo in let init_tac = Tactics.auto_intros_tac args in let pinfo = Proof_info.make ~cinfo:[{cinfo with typ = ()}] ~info () in let env = Global.env () in let using = Option.map (interp_proof_using_cinfo env sigma [cinfo]) using in let lemma = start_proof_core ~name ~pinfo ?using sigma [None, typ] in map lemma ~f:(fun p -> pi1 @@ Proof.run_tactic Global.(env ()) init_tac p) let start_mutual_definitions ~info ~cinfo ~bodies ~possible_guard ?using sigma = let intro_tac { CInfo.args; _ } = Tactics.auto_intros_tac args in let (possible_guard, fixrs) = possible_guard in let fixrs = List.map EConstr.ERelevance.make fixrs in let cinfo' = List.map (fun cinfo -> { cinfo with CInfo.typ = EConstr.of_constr cinfo.CInfo.typ }) cinfo in let init_tac = (* This is the case for hybrid proof mode / definition fixpoint, where terms for some constants are given with := *) let tacl = List.map (Option.cata (EConstr.of_constr %> Tactics.exact_no_check) Tacticals.tclIDTAC) bodies in List.map2 (fun tac thm -> Tacticals.tclTHEN tac (intro_tac thm)) tacl cinfo' in match cinfo' with | [] -> CErrors.anomaly (Pp.str "No proof to start.") | { CInfo.name; _} :: _ as thms -> let pinfo = Proof_info.make ~cinfo:(List.map (fun cinfo -> {cinfo with CInfo.typ = ()}) cinfo) ~info ~possible_guard:(possible_guard, fixrs) () in (* start_lemma has the responsibility to add (name, impargs, typ) to thms, once Info.t is more refined this won't be necessary *) let env = Global.env () in let sign = List.fold_left2 (fun sign CInfo.{name;typ} r -> let decl = Context.Named.Declaration.LocalAssum (Context.make_annot name r, typ) in EConstr.push_named_context_val decl sign) (initialize_named_context_for_proof ()) cinfo' fixrs in let using = Option.map (interp_proof_using_cinfo env sigma cinfo') using in let goals = List.map (function CInfo.{typ} -> (Some sign, typ)) thms in let lemma = start_proof_core ~name ~pinfo ?using sigma goals in let lemma = map lemma ~f:(fun p -> pi1 @@ Proof.run_tactic Global.(env ()) (Proofview.tclFOCUS 1 (List.length thms) (Proofview.tclDISPATCH init_tac)) p) in let () = (* Temporary declaration of notations for the time of the proofs *) let ntn_env = (* We simulate the goal context in which the fixpoint bodies have to be proved (exact relevance does not matter) *) let make_decl CInfo.{name; typ} = Context.Named.Declaration.LocalAssum (Context.annotR name, typ) in Environ.push_named_context (List.map make_decl cinfo) (Global.env()) in List.iter (Metasyntax.add_notation_interpretation ~local:(info.scope=Locality.Discharge) ntn_env) info.ntns in lemma let start_mutual_definitions_refine ~info ~cinfo ~bodies ~possible_guard ?using sigma = let future_goals, sigma = Evd.pop_future_goals sigma in let gls = List.rev (Evd.FutureGoals.comb future_goals) in let sigma = Evd.push_future_goals sigma in let intro_tac { CInfo.args; _ } = Tactics.auto_intros_tac args in let fixrs = snd possible_guard in let init_tac = let tacl = List.map (Option.cata (fun body -> Refine.refine ~typecheck:false (fun sigma -> sigma, body)) Tacticals.tclIDTAC) bodies in List.map2 (fun tac thm -> Tacticals.tclTHEN tac (intro_tac thm)) tacl cinfo in match cinfo with | [] -> CErrors.anomaly (Pp.str "No proof to start.") | { CInfo.name; _} :: _ as thms -> let pinfo = Proof_info.make ~cinfo:(List.map (fun cinfo -> {cinfo with CInfo.typ = ()}) cinfo) ~info ~possible_guard () in (* start_lemma has the responsibility to add (name, impargs, typ) to thms, once Info.t is more refined this won't be necessary *) let env = Global.env () in let sign = List.fold_left2 (fun sign CInfo.{name;typ} r -> let decl = Context.Named.Declaration.LocalAssum (Context.make_annot name r, typ) in EConstr.push_named_context_val decl sign) (initialize_named_context_for_proof ()) cinfo fixrs in let using = Option.map (interp_proof_using_cinfo env sigma cinfo) using in let goals = List.map (function CInfo.{typ} -> (Some sign, typ)) thms in let lemma = start_proof_core ~name ~pinfo ?using sigma goals in let lemma = map lemma ~f:(fun p -> pi1 @@ Proof.run_tactic Global.(env ()) (Tacticals.tclTHENLIST [ Proofview.tclFOCUS 1 (List.length thms) (Proofview.tclDISPATCH init_tac); Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls); Tactics.reduce_after_refine; ]) p) in let () = (* Temporary declaration of notations for the time of the proofs *) let ntn_env = (* We simulate the goal context in which the fixpoint bodies have to be proved (exact relevance does not matter) *) let make_decl CInfo.{name; typ} = Context.Named.Declaration.LocalAssum (Context.annotR name, EConstr.Unsafe.to_constr typ) in Environ.push_named_context (List.map make_decl cinfo) (Global.env()) in List.iter (Metasyntax.add_notation_interpretation ~local:(info.scope=Locality.Discharge) ntn_env) info.ntns in lemma let get_used_variables pf = pf.using let definition_scope ps = ps.pinfo.info.scope let set_used_variables ps ~using = let open Context.Named.Declaration in let env = Global.env () in let ctx = Environ.keep_hyps env using in let ctx_set = List.fold_right Id.Set.add (List.map NamedDecl.get_id ctx) Id.Set.empty in let vars_of = Environ.global_vars_set in let aux env entry (ctx, all_safe as orig) = match entry with | LocalAssum ({Context.binder_name=x},_) -> if Id.Set.mem x all_safe then orig else (ctx, all_safe) | LocalDef ({Context.binder_name=x},bo, ty) as decl -> if Id.Set.mem x all_safe then orig else let vars = Id.Set.union (vars_of env bo) (vars_of env ty) in if Id.Set.subset vars all_safe then (decl :: ctx, Id.Set.add x all_safe) else (ctx, all_safe) in let ctx, _ = Environ.fold_named_context aux env ~init:(ctx,ctx_set) in if not (Option.is_empty ps.using) then CErrors.user_err Pp.(str "Used section variables can be declared only once"); ctx, { ps with using = Some (Context.Named.to_vars ctx) } (* Interprets the expression in the current proof context, from vernacentries *) let get_recnames pf = if Option.has_some pf.pinfo.Proof_info.possible_guard then List.map (fun c -> c.CInfo.name) pf.pinfo.Proof_info.cinfo else [] let interpret_proof_using pstate using = let env = Global.env () in let pf = get pstate in let sigma, _ = Proof.get_proof_context pf in let fixnames = get_recnames pstate in let initial_goals pf = Proofview.initial_goals Proof.((data pf).entry) in let terms = List.map pi3 (initial_goals (get pstate)) in Proof_using.definition_using env sigma ~fixnames ~using ~terms let set_proof_using pstate using = let using = interpret_proof_using pstate using in set_used_variables pstate ~using let get_open_goals ps = let Proof.{ goals; stack; sigma } = Proof.data ps.proof in List.length goals + List.fold_left (+) 0 (List.map (fun (l1,l2) -> List.length l1 + List.length l2) stack) + List.length (Evd.shelf sigma) let warn_remaining_shelved_goals = CWarnings.create ~name:"remaining-shelved-goals" ~category:CWarnings.CoreCategories.tactics (fun () -> Pp.str"The proof has remaining shelved goals.") let warn_given_up = CWarnings.create ~name:"remaining-given-up" ~category:CWarnings.CoreCategories.tactics (fun () -> Pp.str"The proof has given up (admitted) goals." ) let warn_remaining_unresolved_evars = CWarnings.create ~name:"remaining-unresolved-evars" ~category:CWarnings.CoreCategories.tactics (fun () -> Pp.str"The proof has unresolved variables.") type open_proof_kind = | OpenGoals | NonGroundResult of bool (* true = at least some of the evars in the proof term are given up *) exception OpenProof of Names.Id.t * open_proof_kind let () = CErrors.register_handler begin function | OpenProof (pid, reason) -> let open Pp in let ppreason = match reason with | OpenGoals -> str "(there are remaining open goals)" | NonGroundResult has_given_up -> str "(the proof term is not complete" ++ (if has_given_up then str " because of given up (admitted) goals" else mt()) ++ str ")" in let how_to_admit = match reason with | OpenGoals | NonGroundResult false -> mt() | NonGroundResult true -> fnl() ++ str "If this is really what you want to do, use Admitted in place of Qed." in Some (str " (in proof " ++ Names.Id.print pid ++ str "): " ++ str "Attempt to save an incomplete proof" ++ spc() ++ ppreason ++ str "." ++ how_to_admit) | _ -> None end let raise_non_ground_proof evd pid c = let has_given_up = let exception Found in let rec aux c = let () = match EConstr.kind evd c with | Evar (e,_) -> if Evar.Set.mem e (Evd.given_up evd) then raise Found | _ -> () in EConstr.iter evd aux c in try aux c; false with Found -> true in raise (OpenProof (pid, NonGroundResult has_given_up)) let check_incomplete_proof evd = if Evd.has_shelved evd then warn_remaining_shelved_goals () else if Evd.has_given_up evd then warn_given_up () else if Evd.has_undefined evd then warn_remaining_unresolved_evars () (* XXX: This is still separate from close_proof below due to drop_pt in the STM *) let prepare_proof ?(warn_incomplete=true) { proof; pinfo; sideff } = let Proof.{name=pid;entry;poly;sigma=evd} = Proof.data proof in let initial_goals = Proofview.initial_goals entry in let () = if not @@ Proof.is_done proof then raise (OpenProof (pid, OpenGoals)) in let _ : Proof.t = (* checks that we closed all brackets ("}") *) Proof.unfocus_all proof in let eff = SideEff.make @@ Evd.eval_side_effects evd in let evd = Evd.minimize_universes evd in let to_constr c = match EConstr.to_constr_opt evd c with | Some p -> p | None -> raise_non_ground_proof evd pid c in let proofs = List.map (fun (_, body, typ) -> (to_constr body, to_constr typ)) initial_goals in let proofs = match pinfo.possible_guard with | None -> proofs | Some (possible_guard, fixrelevances) -> let env = Safe_typing.push_private_constants (Global.env()) (SideEff.get eff) in let fixbodies, fixtypes = List.split proofs in let fixrelevances = List.map (EConstr.ERelevance.kind evd) fixrelevances in let rec_declaration = prepare_recursive_declaration pinfo.cinfo fixtypes fixrelevances fixbodies in let typing_flags = pinfo.info.typing_flags in fst (make_recursive_bodies ~elim_to:(Inductive.eliminates_to (Evd.elim_graph evd)) env ~typing_flags ~possible_guard ~rec_declaration) in let proofs = List.map (fun (body, typ) -> (body, Some typ)) proofs in let () = if warn_incomplete then check_incomplete_proof evd in { output_entries = proofs; output_ustate = Evd.ustate evd; output_sideff = SideEff.concat eff sideff } exception NotGuarded of Environ.env * Evd.evar_map * (Environ.env * int * EConstr.t Type_errors.pcofix_guard_error) option * (Environ.env * int * int list * EConstr.t Type_errors.pfix_guard_error) list * EConstr.rec_declaration let () = CErrors.register_handler (function | NotGuarded (env, sigma, cofix_err, fix_errs, rec_declaration) -> Some (Himsg.explain_not_guarded env sigma cofix_err fix_errs rec_declaration) | _ -> None) let control_only_guard { proof; pinfo } = let { Proof.entry; Proof.sigma; } = Proof.data proof in let initial_goals = Proofview.initial_goals entry in let proofs = List.map (fun (_, body, typ) -> Evarutil.(nf_evar sigma body, nf_evar sigma typ)) initial_goals in let eff = Evd.eval_side_effects sigma in let env = Safe_typing.push_private_constants (Global.env()) (Evd.seff_private eff) in let open Proof_info in match pinfo.possible_guard with | None -> List.iter (fun (body, _) -> Inductiveops.control_only_guard env sigma body) proofs | Some (possible_guard, fixrelevances) -> let fixbodies, fixtypes = List.split proofs in let rec_declaration = prepare_recursive_edeclaration sigma pinfo.cinfo fixtypes fixrelevances fixbodies in try let cofix_error = if possible_guard.possibly_cofix then try Inductiveops.control_only_guard env sigma (EConstr.mkCoFix (0,rec_declaration)); raise Exit with Pretype_errors.PretypeError (env, sigma, TypingError (IllFormedRecBody (CoFixGuardError why,lna,i,fixenv,vdefj))) -> Some (env,i,why) else None in let combinations = List.combinations possible_guard.possible_fix_indices in let fix_errors = List.map (fun lv -> try Inductiveops.control_only_guard env sigma (EConstr.mkFix ((Array.of_list lv,0),rec_declaration)); raise Exit with Pretype_errors.PretypeError (env, sigma, TypingError (IllFormedRecBody (FixGuardError why,lna,i,fixenv,vdefj))) -> (env,i,lv,why)) combinations in raise (NotGuarded (env, sigma, cofix_error, fix_errors, rec_declaration)) with Exit -> () let return_proof p = (prepare_proof p : closed_proof_output) let close_proof ?warn_incomplete ~opaque ~keep_body_ucst_separate (proof : t) : Proof_object.t = NewProfile.profile "close_proof" (fun () -> let opaque = match opaque with | Vernacexpr.Opaque -> true | Vernacexpr.Transparent -> false in let keep_body_ucst_separate = if keep_body_ucst_separate then Some proof.initial_euctx else None in { Proof_object.proof_object = DefaultProof { proof = prepare_proof ?warn_incomplete proof; opaque; using = proof.using; keep_body_ucst_separate } ; pinfo = proof.pinfo }) () let close_future_proof ~feedback_id proof (fpl : closed_proof_output Future.computation) : Proof_object.t = { Proof_object.proof_object = DeferredOpaqueProof { deferred_proof = fpl; using = proof.using; initial_proof_data = Proof.data proof.proof; feedback_id; initial_euctx = proof.initial_euctx } ; pinfo = proof.pinfo } let update_sigma_univs ugraph p = map ~f:(Proof.update_sigma_univs ugraph) p let by env tac pf = let pf, safe = map_fold ~f:(Proof.solve env (Goal_select.select_nth 1) None tac) pf in let proof, eff = register_side_effects pf.proof in let sideff = SideEff.concat eff pf.sideff in { pf with proof; sideff }, safe let get_goal_context pf i = let p = get pf in Proof.get_goal_context_gen p i let get_current_context pf = let p = get pf in Proof.get_proof_context p (************************************************************************) (* Admitting a lemma-like constant *) (************************************************************************) (* Admitted *) let { Goptions.get = get_keep_admitted_vars } = Goptions.declare_bool_option_and_ref ~key:["Keep"; "Admitted"; "Variables"] ~value:true () let compute_proof_using_for_admitted pinfo proof typs iproof = if not (get_keep_admitted_vars ()) || not (Lib.sections_are_opened()) then None else match get_used_variables proof with | Some _ as x -> x | None -> let pproofs = Proof.partial_proof iproof in let env = Global.env () in let sigma = (Proof.data iproof).Proof.sigma in let ids_def = Id.Set.List.union (List.map (Termops.global_vars_set env sigma) pproofs) in let ids_typ = Id.Set.List.union (List.map (Termops.global_vars_set env sigma) typs) in (* [pproof] is evar-normalized by [partial_proof]. We don't count variables appearing only in the type of evars. *) let vars = Id.Set.union ids_def ids_typ in let vars = match pinfo.Proof_info.possible_guard with | Some _ -> let recvars = Id.Set.of_list (List.map (fun CInfo.{name} -> name) pinfo.cinfo) in Id.Set.diff vars recvars | None -> vars in Some (Environ.really_needed env vars) let check_type_evars_solved env sigma typ = let evars = Evar.Set.elements (Evarutil.undefined_evars_of_term sigma typ) in match evars with | [] -> () | evk::_ -> CErrors.user_err (str "Cannot admit: the statement has unresolved existential variables.") let finish_admitted ~pm ~pinfo ~sec_vars typs = (* If the constant was an obligation we need to update the program map *) let { Proof_info.info; cinfo } = pinfo in match CEphemeron.default pinfo.Proof_info.proof_ending Proof_ending.Regular with | Proof_ending.End_obligation oinfo -> let declare_fun ~uctx ~mono_uctx_extra typ = List.hd (declare_possibly_mutual_parameters ~info ~cinfo ~sec_vars ~mono_uctx_extra [typ, uctx]) in let typ, uctx = match typs with [typ, uctx] -> typ, uctx | _ -> assert false in Obls_.obligation_admitted_terminator ~pm typ oinfo declare_fun sec_vars uctx | _ -> let (_ : 'a list) = declare_possibly_mutual_parameters ~info ~cinfo ~sec_vars typs in pm let save_admitted ~pm ~proof = let iproof = get proof in let Proof.{ entry } = Proof.data iproof in let typs = List.map pi3 (Proofview.initial_goals entry) in let sigma = Evd.from_ctx proof.initial_euctx in List.iter (check_type_evars_solved (Global.env()) sigma) typs; let sec_vars = compute_proof_using_for_admitted proof.pinfo proof typs iproof in let sigma = Evd.minimize_universes sigma in let uctx = Evd.ustate sigma in let typs = List.map (fun typ -> (EConstr.to_constr sigma typ, uctx)) typs in finish_admitted ~pm ~pinfo:proof.pinfo ~sec_vars typs (************************************************************************) (* Saving a lemma-like constant *) (************************************************************************) let finish_proved_equations ~pm ~kind ~hook i entries types sigma0 = let obls = ref 1 in let sigma, recobls = CList.fold_left2_map (fun sigma (_evar_env, ev, _evi, local_context, _type) entry -> let id = match Evd.evar_ident ev sigma0 with | Some id -> Libnames.basename id (* XXX: should deambiguate somehow *) | None -> let n = !obls in let () = incr obls in let id = Nameops.add_suffix i ("_obligation_" ^ string_of_int n) in id in let body, opaque = match entry.proof_entry_body with Default { body; opaque } -> body, opaque | _ -> assert false in let typ = match entry.proof_entry_type with None -> assert false | Some typ -> typ in let body, typ, args = Subproof.shrink_entry local_context body typ in let entry = { entry with proof_entry_body = Default { body; opaque }; proof_entry_type = Some typ } in let cst = declare_constant ~loc:None ~name:id ~kind ~typing_flags:None (DefinitionEntry entry) in let sigma, app = Evd.fresh_global (Global.env ()) sigma (GlobRef.ConstRef cst) in let sigma = Evd.define ev (EConstr.applist (app, args)) sigma in sigma, cst) sigma0 types entries in let pm = hook ~pm recobls sigma in pm, List.map (fun cst -> GlobRef.ConstRef cst) recobls let check_single_entry entries label = match entries with | [entry, uctx] -> entry, uctx | _ -> CErrors.anomaly ~label Pp.(str "close_proof returned more than one proof term") let finish_proof ~pm proof_obj proof_info = let open Proof_ending in let { Proof_info.info; cinfo; possible_guard } = proof_info in match CEphemeron.default proof_info.Proof_info.proof_ending Regular with | Regular -> (* Unless this is a block of mutual fixpoint, we assume the statements, if more than one, to form a telescope, as in Derive *) let is_telescope = Option.is_empty proof_info.possible_guard in pm, declare_possibly_mutual_definitions ~info ~cinfo ~obls:[] ~is_telescope proof_obj | End_obligation oinfo -> let eff, entries = process_proof ~info proof_obj in let entry, uctx = check_single_entry entries "Obligation.save" in Obls_.obligation_terminator ~pm ~entry ~eff ~uctx ~oinfo | End_equations { hook; i; types; sigma } -> let kind = info.Info.kind in let eff, entries = process_proof ~info proof_obj in (* FIXME: this is probably not the right place to declare effects *) let () = export_side_effects eff in let entries = List.map fst entries in finish_proved_equations ~pm ~kind ~hook i entries types sigma let err_save_forbidden_in_place_of_qed () = CErrors.user_err (Pp.str "Cannot use Save with more than one constant or in this proof mode") let process_idopt_for_save ~idopt info = match idopt with | None -> info | Some { CAst.v = save_name } -> (* Save foo was used; we override the info in the first theorem *) let cinfo = match info.Proof_info.cinfo, CEphemeron.default info.Proof_info.proof_ending Proof_ending.Regular with | [ { CInfo.name; _} as decl ], Proof_ending.Regular -> [ { decl with CInfo.name = save_name } ] | _ -> err_save_forbidden_in_place_of_qed () in { info with Proof_info.cinfo } let save ~pm ~proof ~opaque ~idopt = (* Env and sigma are just used for error printing in save_remaining_recthms *) let proof_obj = close_proof ~opaque ~keep_body_ucst_separate:false proof in let proof_info = process_idopt_for_save ~idopt proof.pinfo in finish_proof ~pm proof_obj.proof_object proof_info let save_regular ~(proof : t) ~opaque ~idopt = let open Proof_ending in match CEphemeron.default proof.pinfo.Proof_info.proof_ending Regular with | Regular -> let (_, grs) : Obls_.State.t * _ = save ~pm:Obls_.State.empty ~proof ~opaque ~idopt in grs | _ -> CErrors.anomaly Pp.(str "save_regular: unexpected proof ending") (***********************************************************************) (* Special case to close a lemma without forcing a proof *) (***********************************************************************) let save_lemma_admitted_delayed ~pm ~proof = let { Proof_object.proof_object; pinfo } = proof in (* Drop side-effects, they will not be used anyway *) let _eff, entries = process_proof ~info:pinfo.info proof_object in let typs = List.map (function { proof_entry_type }, uctx -> Option.get proof_entry_type, uctx) entries in (* Note: an alternative would be to compute sec_vars of the partial proof as a Future computation, as in compute_proof_using_for_admitted *) let sec_vars = if get_keep_admitted_vars () then (fst (List.hd entries)).proof_entry_secctx else None in (* If the proof is partial, do we want to take the (restriction on visible uvars of) uctx so far or (as done below) the initial ones that refers to only the types *) finish_admitted ~pm ~pinfo:proof.pinfo ~sec_vars typs let save_lemma_proved_delayed ~pm ~proof ~idopt = (* vio2vo used to call this with invalid [pinfo], now it should work fine. *) let pinfo = process_idopt_for_save ~idopt proof.Proof_object.pinfo in let pm, _ = finish_proof ~pm proof.proof_object pinfo in pm end (* Proof module *) let _ = Ind_tables.declare_definition_scheme := declare_definition_scheme let _ = Ind_tables.register_definition_scheme := register_definition_scheme module Internal = struct module Constant = struct type t = constant_obj let tag = objConstant let kind obj = obj.cst_kind end let objVariable = objVariable let export_side_effects eff = export_side_effects (SideEff.make eff) let register_side_effects pf = let proof, eff = register_side_effects pf.Proof.proof in let sideff = SideEff.concat eff pf.sideff in { pf with proof; sideff } end (* This module could be merged with Obl, and placed before [Proof], however there is a single dependency on [Proof.start] for the interactive case *) module Obls = struct (* For the records fields, opens should go away one these types are private *) open Obls_ open Obls_.Obligation open Obls_.ProgramDecl let reduce c = let env = Global.env () in let sigma = Evd.from_env env in EConstr.Unsafe.to_constr (Reductionops.clos_norm_flags RedFlags.betaiota env sigma (EConstr.of_constr c)) let explain_no_obligations = function Some ident -> str "No obligations for program " ++ Id.print ident | None -> str "No obligations remaining" module Error = struct let no_obligations n = CErrors.user_err (explain_no_obligations n) let ambiguous_program id ids = CErrors.user_err Pp.(str "More than one program with unsolved obligations: " ++ prlist Id.print ids ++ str "; use the \"of\" clause to specify, as in \"Obligation 1 of " ++ Id.print id ++ str "\"") let unknown_obligation num = CErrors.user_err (Pp.str (Printf.sprintf "Unknown obligation number %i" (succ num))) let already_solved num = CErrors.user_err Pp.(str "Obligation " ++ int num ++ str " already solved." ) let depends num rem = CErrors.user_err ( str "Obligation " ++ int num ++ str " depends on obligation(s) " ++ pr_sequence (fun x -> int (succ x)) rem) end let default_tactic = ref (Proofview.tclUNIT ()) let subst_deps expand obls deps t = let osubst = Obls_.obl_substitution expand obls deps in (Vars.replace_vars (List.map (fun (n, (_, b)) -> n, b) osubst) t) let subst_deps_obl obls obl = let t' = subst_deps true obls obl.obl_deps obl.obl_type in Obligation.set_type ~typ:t' obl let is_defined obls x = not (Option.is_empty obls.(x).obl_body) let deps_remaining obls deps = Int.Set.fold (fun x acc -> if is_defined obls x then acc else x :: acc) deps [] let goal_kind = Decls.(IsDefinition Definition) let goal_proof_kind = Decls.(IsProof Lemma) let kind_of_obligation o = match o with | Evar_kinds.Define false | Evar_kinds.Expand -> goal_kind | _ -> goal_proof_kind (* Solve an obligation using tactics, return the corresponding proof term *) let warn_solve_errored = CWarnings.create ~name:"solve_obligation_error" ~category:CWarnings.CoreCategories.tactics (fun err -> Pp.seq [ str "Solve Obligations tactic returned error: " ; err ; fnl () ; str "This will become an error in the future" ]) let solve_by_tac prg obls i tac = let obl = obls.(i) in let obl = subst_deps_obl obls obl in let tac = Option.(default !default_tactic (append tac obl.obl_tac)) in let uctx = Internal.get_uctx prg in let uctx = UState.update_sigma_univs uctx (Global.universes ()) in let poly = Internal.get_poly prg in (* the status of [build_by_tactic] is dropped. *) try let env = Global.env () in let typ = EConstr.of_constr obl.obl_type in (* If the proof is open we absorb the error and leave the obligation open *) match Subproof.build_by_tactic_opt env ~uctx ~poly ~typ tac with | None -> None | Some (body, types, _univs, _, uctx) -> let () = Inductiveops.control_only_guard env (Evd.from_ctx uctx) (EConstr.of_constr body) in Some (body, types, uctx) with | Tacticals.FailError (_, s) as exn -> let _ = Exninfo.capture exn in let loc = fst obl.obl_location in CErrors.user_err ?loc (Lazy.force s) | e when CErrors.noncritical e -> let err = CErrors.print e in let loc = fst obl.obl_location in warn_solve_errored ?loc err; None let solve_and_declare_by_tac prg obls i tac = match solve_by_tac prg obls i tac with | None -> None | Some (t, ty, uctx) -> let obl = obls.(i) in let prg, obl', _cst = declare_obligation prg obl ~body:t ~types:(Some ty) ~uctx in obls.(i) <- obl'; Some prg let solve_obligation_by_tac prg obls i tac = let obl = obls.(i) in match obl.obl_body with | Some _ -> None | None -> if List.is_empty (deps_remaining obls obl.obl_deps) then solve_and_declare_by_tac prg obls i tac else None let get_unique_prog ~pm prg = match State.get_unique_open_prog pm prg with | Ok prg -> prg | Error [] -> Error.no_obligations None | Error ((id :: _) as ids) -> Error.ambiguous_program id ids let solve_prg_obligations ~pm prg ?oblset tac = let { obls; remaining } = Internal.get_obligations prg in let rem = ref remaining in let obls' = Array.copy obls in let set = ref Int.Set.empty in let p = match oblset with | None -> (fun _ -> true) | Some s -> set := s; (fun i -> Int.Set.mem i !set) in let prg = Array.fold_left_i (fun i prg x -> if p i then ( match solve_obligation_by_tac prg obls' i tac with | None -> prg | Some prg -> let deps = dependencies obls i in set := Int.Set.union !set deps; decr rem; prg) else prg) prg obls' in update_obls ~pm prg obls' !rem let auto_solve_obligations ~pm n ?oblset tac : State.t * progress = Flags.if_verbose Feedback.msg_info (str "Solving obligations automatically..."); let prg = get_unique_prog ~pm n in solve_prg_obligations ~pm prg ?oblset tac let solve_obligation ?check_final prg num tac = let user_num = succ num in let { obls; remaining=rem } = Internal.get_obligations prg in let obl = obls.(num) in let remaining = deps_remaining obls obl.obl_deps in let () = if not (Option.is_empty obl.obl_body) then Error.already_solved user_num; if not (List.is_empty remaining) then Error.depends user_num remaining in let obl = subst_deps_obl obls obl in let kind = kind_of_obligation (snd obl.obl_status) in let evd = Evd.from_ctx (Internal.get_uctx prg) in let evd = Evd.update_sigma_univs (Global.universes ()) evd in let auto ~pm n oblset tac = fst (auto_solve_obligations ~pm n ~oblset tac) in let proof_ending = let name = Internal.get_name prg in Proof_ending.End_obligation {name; num; auto; check_final} in let cinfo = CInfo.make ?loc:(fallback_loc ~warn:false obl.obl_name None) ~name:obl.obl_name ~typ:(EConstr.of_constr obl.obl_type) () in let using = let using = Internal.get_using prg in let env = Global.env () in let f {CInfo.name; typ; _} = name, [typ] in Option.map (interp_proof_using_gen f env evd [cinfo]) using in let poly = Internal.get_poly prg in let info = Info.make ~kind ~poly () in let lemma = Proof.start_core ~cinfo ~info ~proof_ending ?using evd in let lemma = fst @@ Proof.by (Global.env ()) !default_tactic lemma in let lemma = Option.cata (fun tac -> Proof.set_endline_tactic tac lemma) lemma tac in lemma (** Implements [Solve Obligations of name with tac] *) let solve_obligations ~pm n tac = let prg = get_unique_prog ~pm n in fst (solve_prg_obligations ~pm prg tac) (** Implements [Solve All Obligations with tac] *) let solve_all_obligations ~pm tac = State.fold pm ~init:pm ~f:(fun k v pm -> solve_prg_obligations ~pm v tac |> fst) (** Implements [Obligation n of name with tac] *) let obligation (user_num, name) ~pm tac = let num = pred user_num in let prg = get_unique_prog ~pm name in let { obls; remaining } = Internal.get_obligations prg in if num >= 0 && num < Array.length obls then let obl = obls.(num) in match obl.obl_body with | None -> solve_obligation prg num tac | Some r -> Error.already_solved user_num else Error.unknown_obligation num (** Implements [Obligations of name] *) let show_single_obligation i name obls x = let x = subst_deps_obl obls x in let env = Global.env () in let sigma = Evd.from_env env in let msg = str "Obligation" ++ spc () ++ int (succ i) ++ spc () ++ str "of" ++ spc () ++ Id.print name ++ str ":" ++ spc () ++ hov 1 (Printer.pr_constr_env env sigma x.obl_type ++ str "." ++ fnl ()) in Feedback.msg_info msg let show_obligations_of_prg ?(msg = true) prg = let name = Internal.get_name prg in let {obls; remaining} = Internal.get_obligations prg in let showed = ref 5 in if msg then Feedback.msg_info (int remaining ++ str " obligation(s) remaining: "); Array.iteri (fun i x -> match x.obl_body with | None -> if !showed > 0 then begin decr showed; show_single_obligation i name obls x end | Some _ -> ()) obls let show_obligations ~pm ?(msg = true) name = let progs = match name with | None -> State.all pm | Some name -> (match State.find pm name with | Some prg -> [prg] | None -> Error.no_obligations (Some name)) in List.iter (fun x -> show_obligations_of_prg ~msg x) progs (** Implementation of the [Preterm of name] command *) let show_term ~pm name = let prg = get_unique_prog ~pm name in ProgramDecl.show prg let msg_generating_obl name obls = let len = Array.length obls in let info = Id.print name ++ str " has type-checked" in Feedback.msg_info (if len = 0 then info ++ str "." else info ++ str ", generating " ++ int len ++ str (String.plural len " obligation")) let add_definition ~pm ~info ~cinfo ~opaque ~uctx ?body ?tactic ?(reduce = reduce) ?using ?obl_hook obls = let obl_hook = Option.map (fun h -> State.PrgHook h) obl_hook in let prg = ProgramDecl.make ~info ~cinfo ~body ~opaque ~uctx ~reduce ~deps:[] ~possible_guard:None ?obl_hook ?using obls in let name = CInfo.get_name cinfo in let {obls;_} = Internal.get_obligations prg in if Int.equal (Array.length obls) 0 then let () = Flags.if_verbose (msg_generating_obl name) obls in let pm, _cst = Obls_.declare_definition ~pm prg in pm else let () = Flags.if_verbose (msg_generating_obl name) obls in let pm = State.add pm name prg in let pm, res = auto_solve_obligations ~pm (Some name) tactic in let () = match res with | Remain -> Flags.if_verbose (show_obligations ~pm ~msg:false) (Some name) | Dependent | Defined -> () in pm let add_mutual_definitions ~pm ~info ~cinfo ~opaque ~uctx ~bodies ~possible_guard ?tactic ?(reduce = reduce) ?using ?obl_hook obls = let obl_hook = Option.map (fun h -> State.PrgHook h) obl_hook in let deps = List.map CInfo.get_name cinfo in let pm = List.fold_left3 (fun pm cinfo body obls -> let prg = ProgramDecl.make ~info ~cinfo ~opaque ~body:(Some body) ~uctx ~deps ~possible_guard:(Some possible_guard) ~reduce ?obl_hook ?using obls in State.add pm (CInfo.get_name cinfo) prg) pm cinfo bodies obls in let pm, _defined = List.fold_left (fun (pm, finished) x -> if finished then (pm, finished) else let pm, res = auto_solve_obligations ~pm (Some x) tactic in match res with | Defined -> (* If one definition is turned into a constant, the whole block is defined. *) (pm, true) | Dependent | Remain -> (pm, false)) (pm, false) deps in pm (** [admit_obligations ~pm name] implements [Admit Obligations of name] *) let rec admit_prog ~pm prg = let {obls} = Internal.get_obligations prg in let is_open _ x = Option.is_empty x.obl_body && List.is_empty (deps_remaining obls x.obl_deps) in let i = match Array.findi is_open obls with | Some i -> i | None -> CErrors.anomaly (Pp.str "Could not find a solvable obligation.") in let proof = solve_obligation prg i None in let pm = Proof.save_admitted ~pm ~proof in match ProgMap.find_opt (Internal.get_name prg) pm with | Some prg -> admit_prog ~pm (CEphemeron.get prg) | None -> pm let rec admit_all_obligations ~pm = let prg = State.first_pending pm in match prg with | None -> pm | Some prg -> let pm = admit_prog ~pm prg in admit_all_obligations ~pm let admit_obligations ~pm name = match name with | None -> admit_all_obligations ~pm | Some _ -> let prg = get_unique_prog ~pm name in let pm = admit_prog ~pm prg in pm (** Implements [Next Obligation of name with tac] and [Final Obligation of name with tac] *) let next_obligation ~pm ?(final=false) name tac = let prg = match name with | None -> begin match State.first_pending pm with | Some prg -> prg | None -> Error.no_obligations None end | Some _ -> get_unique_prog ~pm name in let {obls; remaining} = Internal.get_obligations prg in let is_open _ x = Option.is_empty x.obl_body && List.is_empty (deps_remaining obls x.obl_deps) in let i = match Array.findi is_open obls with | Some i -> i | None -> match name with | None -> CErrors.anomaly (Pp.str "Could not find a solvable obligation.") | Some name -> CErrors.user_err (str "No more obligations for " ++ Id.print name ++ str ".") in let check_final = if not final then None else match name with | None -> Some AllFinal | Some name -> Some (SpecificFinal name) in solve_obligation ?check_final prg i tac let check_program_libraries () = Rocqlib.check_required_library Rocqlib.datatypes_module_name; Rocqlib.check_required_library ["Corelib";"Init";"Specif"] let program_inference_hook env sigma ev = let tac = !default_tactic in let evi = Evd.find_undefined sigma ev in let evi = Evarutil.nf_evar_info sigma evi in let env = Evd.evar_filtered_env env evi in try let concl = Evd.evar_concl evi in if not (Evarutil.is_ground_env sigma env && Evarutil.is_ground_term sigma concl) then None else let c, sigma = Subproof.refine_by_tactic ~name:(Id.of_string "program_subproof") ~poly:PolyFlags.default env sigma concl (Tacticals.tclSOLVE [tac]) in Some (sigma, c) with | (Proof.OpenProof _ as e | Logic_monad.TacticFailure e) when CErrors.noncritical e -> CErrors.user_err Pp.(str "The statement obligations could not be resolved \ automatically, write a statement definition first.") (* aliases *) let prepare_obligations = prepare_obligations let check_solved_obligations = let is_empty prg = let obls = (Internal.get_obligations (CEphemeron.get prg)).obls in let is_open x = Option.is_empty x.obl_body && List.is_empty (deps_remaining obls x.obl_deps) in Array.exists is_open obls in Obls_.check_solved_obligations is_empty type fixpoint_kind = Obls_.fixpoint_kind = | IsFixpoint of lident option list | IsCoFixpoint end module OblState = Obls_.State let declare_constant ?loc ?local ~name ~kind ?typing_flags = declare_constant ~loc ?local ~name ~kind ~typing_flags let declare_entry ?loc ~name ?scope ~kind ?user_warns ?hook ~impargs ~uctx entry = declare_entry ~loc ~name ?scope ~kind ~typing_flags:None ?clearbody:None ~user_warns ?hook ~impargs ~uctx entry let declare_definition_full ~info ~cinfo ~opaque ~body ?using sigma = let c, uctx = declare_definition ~obls:[] ~info ~cinfo ~opaque ~body ?using sigma in c, if PolyFlags.univ_poly info.poly then Univ.ContextSet.empty else UState.universe_context_set uctx let declare_definition ~info ~cinfo ~opaque ~body ?using sigma = declare_definition ~obls:[] ~info ~cinfo ~opaque ~body ?using sigma |> fst rocq-9.2.0/vernac/declare.mli000066400000000000000000000523641516144147600160710ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 'a -> 'a) -> 'a g val make : (S.t -> unit) -> t val call : ?hook:t -> S.t -> unit end (** {2 One-go, non-interactive declaration API } *) (** Information for a single top-level named constant *) module CInfo : sig type 'constr t val make : ?loc:Loc.t -> name:Id.t -> typ:'constr -> ?args:Name.t list -> ?impargs:Impargs.manual_implicits -> unit -> 'constr t (* Used only in Vernacentries, may disappear from public API *) val to_constr : Evd.evar_map -> EConstr.t t -> Constr.t t (* Used only in RecLemmas, may disappear from public API *) val get_typ : 'constr t -> 'constr end (** Information for a declaration, interactive or not, includes parameters shared by mutual constants *) module Info : sig type t (** Note that [opaque] doesn't appear here as it is not known at the start of the proof in the interactive case. *) val make : ?poly:PolyFlags.t -> ?inline : bool -> ?kind : Decls.logical_kind (** Theorem, etc... *) -> ?udecl : UState.universe_decl -> ?scope : Locality.definition_scope (** locality *) -> ?clearbody:bool -> ?hook : Hook.t (** Callback to be executed after saving the constant *) -> ?typing_flags:Declarations.typing_flags -> ?user_warns : Globnames.extended_global_reference UserWarn.with_qf -> ?ntns : Metasyntax.notation_interpretation_decl list -> unit -> t end (** Declares a non-interactive constant; [body] and [types] will be normalized w.r.t. the passed [evar_map] [sigma]. Universes should be handled properly, including minimization and restriction. Note that [sigma] is checked for unresolved evars, thus you should be careful not to submit open terms *) val declare_definition : info:Info.t -> cinfo:EConstr.t option CInfo.t -> opaque:bool -> body:EConstr.t -> ?using:Vernacexpr.section_subset_expr -> Evd.evar_map -> GlobRef.t val declare_mutual_definitions : info:Info.t -> cinfo: Constr.t CInfo.t list -> opaque:bool -> eff:Evd.side_effects -> uctx:UState.t -> bodies:Constr.t list -> possible_guard:Pretyping.possible_guard * Sorts.relevance list -> ?using:Vernacexpr.section_subset_expr -> unit -> Names.GlobRef.t list (** {2 Declaration of interactive constants } *) (** [save] / [save_admitted] can update obligations state, so we need to expose the state here *) module OblState : sig type t val empty : t module View : sig module Obl : sig type t = private { name : Id.t ; loc : Loc.t option ; status : bool * Evar_kinds.obligation_definition_status ; solved : bool } end type t = private { opaque : bool ; remaining : int ; obligations : Obl.t array } end val view : t -> View.t Id.Map.t end (** [Declare.Proof.t] Construction of constants using interactive proofs. *) module Proof : sig type t (** [start_proof ~info ~cinfo sigma] starts a proof of [cinfo]. The proof is started in the evar map [sigma] (which can typically contain universe constraints) *) val start : info:Info.t -> cinfo:EConstr.t CInfo.t -> ?using:Id.Set.t -> Evd.evar_map -> t (** [start_{derive,equations}] are functions meant to handle interactive proofs with multiple goals, they should be considered experimental until we provide a more general API encompassing both of them. Please, get in touch with the developers if you would like to experiment with multi-goal dependent proofs so we can use your input on the design of the new API. *) val start_derive : name:Id.t -> info:Info.t -> cinfo:unit CInfo.t list -> Proofview.telescope -> t val start_equations : name:Id.t -> info:Info.t -> hook:(pm:OblState.t -> Constant.t list -> Evd.evar_map -> OblState.t) -> types:(Environ.env * Evar.t * Evd.undefined Evd.evar_info * EConstr.named_context * Evd.econstr) list -> Evd.evar_map -> Proofview.telescope -> t (** Pretty much internal, used by the Lemma vernaculars *) val start_definition : info:Info.t -> cinfo:EConstr.t CInfo.t -> ?using:Vernacexpr.section_subset_expr -> Evd.evar_map -> t (** Pretty much internal, used by mutual Lemma / Fixpoint vernaculars *) val start_mutual_definitions : info:Info.t -> cinfo:Constr.t CInfo.t list -> bodies:Constr.t option list -> possible_guard:(Pretyping.possible_guard * Sorts.relevance list) -> ?using:Vernacexpr.section_subset_expr -> Evd.evar_map -> t (** Pretty much internal, used by mutual Lemma / Fixpoint vernaculars with #[refine] *) val start_mutual_definitions_refine : info:Info.t -> cinfo:EConstr.t CInfo.t list -> bodies:EConstr.t option list -> possible_guard:(Pretyping.possible_guard * Evd.erelevance list) -> ?using:Vernacexpr.section_subset_expr -> Evd.evar_map -> t (** Qed a proof *) val save : pm:OblState.t -> proof:t -> opaque:Vernacexpr.opacity_flag -> idopt:Names.lident option -> OblState.t * GlobRef.t list (** For proofs known to have [Regular] ending, no need to touch program state. *) val save_regular : proof:t -> opaque:Vernacexpr.opacity_flag -> idopt:Names.lident option -> GlobRef.t list (** Admit a proof *) val save_admitted : pm:OblState.t -> proof:t -> OblState.t (** [by env tac] applies tactic [tac] to the 1st subgoal of the current focused proof. Returns [false] if an unsafe tactic has been used. *) val by : Environ.env -> unit Proofview.tactic -> t -> t * bool (** Operations on ongoing proofs *) val get : t -> Proof.t val get_name : t -> Names.Id.t val fold : f:(Proof.t -> 'a) -> t -> 'a val map : f:(Proof.t -> Proof.t) -> t -> t val map_fold : f:(Proof.t -> Proof.t * 'a) -> t -> t * 'a val map_fold_endline : f:(Gentactic.glob_generic_tactic option -> Proof.t -> Proof.t * 'a) -> t -> t * 'a (** Sets the tactic to be used when a tactic line is closed with [...] *) val set_endline_tactic : Gentactic.glob_generic_tactic -> t -> t val definition_scope : t -> Locality.definition_scope (** Sets the section variables assumed by the proof, returns its closure * (w.r.t. type dependencies and let-ins covered by it) *) val set_proof_using : t -> Vernacexpr.section_subset_expr -> Constr.named_context * t (** Gets the set of variables declared to be used by the proof. None means no "Proof using" or #[using] was given *) val get_used_variables : t -> Id.Set.t option (** Compacts the representation of the proof by pruning all intermediate terms *) val compact : t -> t (** Update the proof's universe information typically after a side-effecting command (e.g. a sublemma definition) has been run inside it. *) val update_sigma_univs : UGraph.t -> t -> t val get_open_goals : t -> int (** Helpers to obtain proof state when in an interactive proof *) (** [get_goal_context n] returns the context of the [n]th subgoal of the current focused proof or raises a [UserError] if there is no focused proof or if there is no more subgoals *) val get_goal_context : t -> int -> Evd.evar_map * Environ.env (** [get_current_context ()] returns the context of the current focused goal. If there is no focused goal but there is a proof in progress, it returns the corresponding evar_map. If there is no pending proof then it returns the current global environment and empty evar_map. *) val get_current_context : t -> Evd.evar_map * Environ.env (** {2 Proof delay API, warning, internal, not stable} *) (* Intermediate step necessary to delegate the future. * Both access the current proof state. The former is supposed to be * chained with a computation that completed the proof *) type closed_proof_output (** Requires a complete proof. *) val return_proof : t -> closed_proof_output (** XXX: This is an internal, low-level API and could become scheduled for removal from the public API, use higher-level declare APIs instead *) type proof_object val close_proof : ?warn_incomplete:bool -> opaque:Vernacexpr.opacity_flag -> keep_body_ucst_separate:bool -> t -> proof_object val close_future_proof : feedback_id:Stateid.t -> t -> closed_proof_output Future.computation -> proof_object (** Special cases for delayed proofs, in this case we must provide the proof information so the proof won't be forced. *) val save_lemma_admitted_delayed : pm:OblState.t -> proof:proof_object -> OblState.t val save_lemma_proved_delayed : pm:OblState.t -> proof:proof_object -> idopt:Names.lident option -> OblState.t exception NotGuarded of Environ.env * Evd.evar_map * (Environ.env * int * EConstr.t Type_errors.pcofix_guard_error) option * (Environ.env * int * int list * EConstr.t Type_errors.pfix_guard_error) list * EConstr.rec_declaration val control_only_guard : t -> unit end (** {2 low-level, internal API, avoid using unless you have special needs } *) (** Proof entries represent a proof that has been finished, but still not registered with the kernel. XXX: This is an internal, low-level API and could become scheduled for removal from the public API, use higher-level declare APIs instead *) type proof_entry type parameter_entry type primitive_entry type symbol_entry val definition_entry : ?opaque:bool -> ?using:Names.Id.Set.t -> ?inline:bool -> ?types:Constr.types -> ?univs:UState.named_universes_entry -> Constr.constr -> proof_entry val parameter_entry : ?inline:int -> ?univs:UState.named_universes_entry -> Constr.constr -> parameter_entry val primitive_entry : ?types:(Constr.types * UState.named_universes_entry) -> CPrimitives.op_or_type -> primitive_entry val symbol_entry : ?univs:UState.named_universes_entry -> unfold_fix:bool -> Constr.types -> symbol_entry (** XXX: This is an internal, low-level API and could become scheduled for removal from the public API, use higher-level declare APIs instead *) val declare_entry : ?loc:Loc.t -> name:Id.t -> ?scope:Locality.definition_scope -> kind:Decls.logical_kind -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> ?hook:Hook.t -> impargs:Impargs.manual_implicits -> uctx:UState.t -> proof_entry -> GlobRef.t (** Declaration of section variables and local definitions *) type variable_declaration = | SectionLocalDef of { clearbody : bool; entry : proof_entry; } | SectionLocalAssum of { typ : Constr.types; impl : Glob_term.binding_kind; univs : UState.named_universes_entry; } (** Declaration of local constructions (Variable/Hypothesis/Local) *) val declare_variable : name:variable -> kind:Decls.logical_kind -> typing_flags:Declarations.typing_flags option -> variable_declaration -> unit (** Declaration of global constructions i.e. Definition/Theorem/Axiom/Parameter/... XXX: This is an internal, low-level API and could become scheduled for removal from the public API, use higher-level declare APIs instead *) type constant_entry = | DefinitionEntry of proof_entry | ParameterEntry of parameter_entry | PrimitiveEntry of primitive_entry | SymbolEntry of symbol_entry val prepare_parameter : poly:PolyFlags.t -> udecl:UState.universe_decl -> types:EConstr.types -> Evd.evar_map -> Evd.evar_map * parameter_entry (** [declare_constant id cd] declares a global declaration (constant/parameter) with name [id] in the current section; it returns the full path of the declaration XXX: This is an internal, low-level API and could become scheduled for removal from the public API, use higher-level declare APIs instead *) val declare_constant : ?loc:Loc.t -> ?local:Locality.import_status -> name:Id.t -> kind:Decls.logical_kind -> ?typing_flags:Declarations.typing_flags -> ?user_warns:Globnames.extended_global_reference UserWarn.with_qf -> constant_entry -> Constant.t (** Like [declare_definition] but also returns the universes and universe constraints added to the global environment *) val declare_definition_full : info:Info.t -> cinfo:EConstr.t option CInfo.t -> opaque:bool -> body:EConstr.t -> ?using:Vernacexpr.section_subset_expr -> Evd.evar_map -> GlobRef.t * Univ.ContextSet.t (** Declaration messages, for internal use *) (** XXX: Scheduled for removal from public API, do not use *) val definition_message : Id.t -> unit val assumption_message : Id.t -> unit val fixpoint_message : int array option -> Id.t list -> unit (** {2 Program mode API} *) (** Rocq's Program mode support. This mode extends declarations of constants and fixpoints with [Program Definition] and [Program Fixpoint] to support incremental construction of terms using delayed proofs, called "obligations" The mode also provides facilities for managing and auto-solving sets of obligations. The basic code flow of programs/obligations is as follows: - [add_definition] / [add_mutual_definitions] are called from the respective [Program] vernacular command interpretation; at this point the only extra work we do is to prepare the new definition [d] using [RetrieveObl], which consists in turning unsolved evars into obligations. [d] is not sent to the kernel yet, as it is not complete and cannot be typchecked, but saved in a special data-structure. Auto-solving of obligations is tried at this stage (see below) - [next_obligation] will retrieve the next obligation ([RetrieveObl] sorts them by topological order) and will try to solve it. When all obligations are solved, the original constant [d] is grounded and sent to the kernel for addition to the global environment. Auto-solving of obligations is also triggered on obligation completion. {2} Solving of obligations: Solved obligations are stored as regular global declarations in the global environment, usually with name [constant_obligation_number] where [constant] is the original [constant] and [number] is the corresponding (internal) number. Solving an obligation can trigger a bit of a complex cascaded callback path; closing an obligation can indeed allow all other obligations to be closed, which in turn may trigged the declaration of the original constant. Care must be taken, as this can modify [Global.env] in arbitrarily ways. Current code takes some care to refresh the [env] in the proper boundaries, but the invariants remain delicate. {2} Saving of obligations: as open obligations use the regular proof mode, a `Qed` will call `Lemmas.save_lemma` first. For this reason obligations code is split in two: this file, [Obligations], taking care of the top-level vernac commands, and [Declare], which is called by `Lemmas` to close an obligation proof and eventually to declare the top-level [Program]ed constant. *) module Obls : sig type fixpoint_kind = IsFixpoint of lident option list | IsCoFixpoint (** Check obligations are properly solved before closing the [what_for] section / module *) val check_solved_obligations : pm:OblState.t -> what_for:Pp.t -> unit val default_tactic : unit Proofview.tactic ref (** Prepare API, to be removed once we provide the corresponding 1-step API *) val prepare_obligations : name:Id.t -> PolyFlags.t -> ?types:EConstr.t -> body:EConstr.t -> Environ.env -> Evd.evar_map -> Constr.constr * Constr.types * UState.t * RetrieveObl.obligation_name_lifter * RetrieveObl.obligation_info (** Start a [Program Definition c] proof. [uctx] [udecl] [impargs] [kind] [scope] [poly] etc... come from the interpretation of the vernacular; `obligation_info` was generated by [RetrieveObl] It will return whether all the obligations were solved; if so, it will also register [c] with the kernel. *) val add_definition : pm:OblState.t -> info:Info.t -> cinfo:Constr.types CInfo.t -> opaque:bool -> uctx:UState.t -> ?body:Constr.t -> ?tactic:unit Proofview.tactic -> ?reduce:(Constr.t -> Constr.t) -> ?using:Vernacexpr.section_subset_expr -> ?obl_hook: OblState.t Hook.g -> RetrieveObl.obligation_info -> OblState.t (* XXX: unify with MutualEntry *) (** Start a [Program Fixpoint] declaration, similar to the above, except it takes a list now. *) val add_mutual_definitions : pm:OblState.t -> info:Info.t -> cinfo:Constr.types CInfo.t list -> opaque:bool -> uctx:UState.t -> bodies:Constr.t list -> possible_guard:(Pretyping.possible_guard * Sorts.relevance list) -> ?tactic:unit Proofview.tactic -> ?reduce:(Constr.t -> Constr.t) -> ?using:Vernacexpr.section_subset_expr -> ?obl_hook: OblState.t Hook.g -> RetrieveObl.obligation_info list -> OblState.t (** Implementation of the [Obligation n of id with tac] command *) val obligation : int * Names.Id.t option -> pm:OblState.t -> Gentactic.glob_generic_tactic option -> Proof.t (** Implementation of the [Next Obligation of id with tac] and [Final Obligation of id with tac] commands *) val next_obligation : pm:OblState.t -> ?final:bool -> Names.Id.t option -> Gentactic.glob_generic_tactic option -> Proof.t (** Implementation of the [Solve Obligations of id with tac] command *) val solve_obligations : pm:OblState.t -> Names.Id.t option -> unit Proofview.tactic option -> OblState.t (** Implementation of the [Solve All Obligations with tac] command *) val solve_all_obligations : pm:OblState.t -> unit Proofview.tactic option -> OblState.t (** Implementation of the [Obligations of id] command *) val show_obligations : pm:OblState.t -> ?msg:bool -> Names.Id.t option -> unit (** Implementation of the [Preterm of id] command *) val show_term : pm:OblState.t -> Names.Id.t option -> Pp.t (** Implementation of the [Admit Obligations of id] command *) val admit_obligations : pm:OblState.t -> Names.Id.t option -> OblState.t val check_program_libraries : unit -> unit val program_inference_hook : Environ.env -> Evd.evar_map -> Evar.t -> (Evd.evar_map * EConstr.t) option end val is_local_constant : Constant.t -> bool (** [true] on constants declared Local and not from the current interactive module (or its parents). *) (** {6 For internal support, do not use} *) module Internal : sig (* Libobject exports *) module Constant : sig type t val tag : (Id.t * t) Libobject.Dyn.tag val kind : t -> Decls.logical_kind end val objVariable : Id.t Libobject.Dyn.tag (** [export_side_effects eff] makes the side effects [eff] global. This usually happens at the end of a proof (during Qed or Defined), but one may need to declare them by hand, for example because the tactic was run as part of a command *) val export_side_effects : Evd.side_effects -> unit val register_side_effects : Proof.t -> Proof.t end rocq-9.2.0/vernac/declareInd.ml000066400000000000000000000257741516144147600163600ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Notation.declare_ref_arguments_scope (GlobRef.IndRef (kn,i)); for j=1 to List.length lc do Notation.declare_ref_arguments_scope (GlobRef.ConstructRef ((kn,i),j)); done) mie.mind_entry_inds type inductive_obj = { ind_names : (lident * lident list) list (* For each block, name of the type + name of constructors *) } let inductive_names sp kn obj = let (dp,_) = Libnames.repr_path sp in let kn = Global.mind_of_delta_kn kn in let names, _ = List.fold_left (fun (names, n) ({CAst.v=typename; loc=typeloc}, consnames) -> let ind_p = (kn,n) in let names, _ = List.fold_left (fun (names, p) {CAst.v=l; loc} -> let sp = Libnames.make_path dp l in ((loc, sp, GlobRef.ConstructRef (ind_p,p)) :: names, p+1)) (names, 1) consnames in let sp = Libnames.make_path dp typename in ((typeloc, sp, GlobRef.IndRef ind_p) :: names, n+1)) ([], 0) obj.ind_names in names let load_inductive i ((sp, kn), names) = let names = inductive_names sp kn names in List.iter (fun (loc, sp, ref) -> Nametab.push (Nametab.Until i) sp ref; Option.iter (Nametab.set_cci_src_loc (TrueGlobal ref)) loc) names let open_inductive i ((sp, kn), names) = let names = inductive_names sp kn names in List.iter (fun (_, sp, ref) -> Nametab.push (Nametab.Exactly i) sp ref) names let cache_inductive o = (* Until 1 and Exactly 1 are equivalent so no need to open_inductive *) load_inductive 1 o let discharge_inductive names = Some names let objInductive : (Id.t * inductive_obj) Libobject.Dyn.tag = let open Libobject in declare_named_object_full {(default_object "INDUCTIVE") with cache_function = cache_inductive; load_function = load_inductive; open_function = filtered_open open_inductive; classify_function = (fun a -> Substitute); subst_function = ident_subst_function; discharge_function = discharge_inductive; } let inInductive v = Libobject.Dyn.Easy.inj v objInductive let cache_prim (p,c) = Structures.PrimitiveProjections.register p c let load_prim _ p = cache_prim p let subst_prim (subst,(p,c)) = Mod_subst.subst_proj_repr subst p, Mod_subst.subst_constant subst c let discharge_prim (p,c) = Some (Global.discharge_proj_repr p, c) let inPrim : (Projection.Repr.t * Constant.t) -> Libobject.obj = let open Libobject in declare_object { (default_object "PRIMPROJS") with cache_function = cache_prim ; load_function = load_prim; subst_function = subst_prim; classify_function = (fun x -> Substitute); discharge_function = discharge_prim } let declare_primitive_projection p c = Lib.add_leaf (inPrim (p,c)) let feedback_axiom () = Feedback.(feedback AddedAxiom) let is_unsafe_typing_flags () = let open Declarations in let flags = Environ.typing_flags (Global.env()) in not (flags.check_universes && flags.check_guarded && flags.check_positive) (* for initial declaration *) let declare_mind ?typing_flags ~indlocs mie = let id = match mie.mind_entry_inds with | ind::_ -> ind.mind_entry_typename | [] -> CErrors.anomaly (Pp.str "cannot declare an empty list of inductives.") in let indlocs = Array.of_list indlocs in let map_names i mip = let typloc, conslocs = if Array.length indlocs <= i then None, [] else indlocs.(i) in let typloc = if Option.has_some typloc then typloc else Loc.get_current_command_loc() in let typ = CAst.make ?loc:typloc mip.mind_entry_typename in let conslocs = Array.of_list conslocs in let map_cons j na = let consloc = if Array.length conslocs <= j then None else conslocs.(j) in let consloc = if Option.has_some consloc then consloc else typloc in CAst.make ?loc:consloc na in let consl = List.mapi map_cons mip.mind_entry_consnames in (typ, consl) in let names = List.mapi map_names mie.mind_entry_inds in let check_exists id = if Decls.variable_exists id || Global.exists_objlabel id then raise (DeclareUniv.AlreadyDeclared (None, id)) in List.iter (fun ({CAst.v=typ}, cons) -> check_exists typ; List.iter (fun {CAst.v} -> check_exists v) cons) names; let mind, why_not_prim_record = Global.add_mind ?typing_flags id mie in let () = Lib.add_leaf (inInductive (id, { ind_names = names })) in let () = UState.add_template_default_univs (Global.env ()) mind in if is_unsafe_typing_flags() then feedback_axiom (); Impargs.declare_mib_implicits mind; declare_inductive_argument_scopes mind mie; mind, why_not_prim_record let is_recursive mie = let open Constr in let rec is_recursive_constructor lift n typ = match Constr.kind typ with | Prod (_,arg,rest) -> not (Vars.noccur_between lift n arg) || is_recursive_constructor (lift+1) n rest | LetIn (na,b,t,rest) -> is_recursive_constructor (lift+1) n rest | _ -> false in let nind = List.length mie.mind_entry_inds in let nparams = List.length mie.mind_entry_params in List.exists (fun ind -> List.exists (fun t -> is_recursive_constructor (nparams+1) nind t) ind.mind_entry_lc) mie.mind_entry_inds let explain_not_prim_record reason = let open IndTyping.NotPrimRecordReason in let open Pp in match reason with | MustNotBeSquashed -> strbrk "it is squashed" | MustHaveRelevantProj -> strbrk "it is not in SProp but all projections may be irrelevant" | MustHaveProj -> strbrk "it has no projections" | MustNotHaveAnonProj -> strbrk "it has an anonymous projection" let warn_non_primitive_record = CWarnings.create ~name:"non-primitive-record" ~category:CWarnings.CoreCategories.records Pp.(fun (mind,why_not_prim_record) -> hov 0 (str "The record " ++ Nametab.pr_global_env Id.Set.empty (GlobRef.IndRef (mind,0)) ++ strbrk" could not be defined as a primitive record because " ++ explain_not_prim_record why_not_prim_record ++ str ".")) let minductive_message = function | [] -> CErrors.user_err Pp.(str "No inductive definition.") | [x] -> Pp.(Id.print x ++ str " is defined") | l -> Pp.(hov 0 (prlist_with_sep pr_comma Id.print l ++ spc () ++ str "are defined")) type one_inductive_impls = Impargs.manual_implicits (* for inds *) * Impargs.manual_implicits list (* for constrs *) let { Goptions.get = default_prop_dep_elim } = Goptions.declare_bool_option_and_ref ~key:["Dependent";"Proposition";"Eliminators"] ~value:false () type default_dep_elim = DefaultElim | PropButDepElim type declare_schemes = None | Default let schemes_attr = let values = [("default", Default); ("none", None)] in Attributes.key_value_attribute ~key:"schemes" ?empty:None ~values |> Attributes.Notations.map (Option.default Default) let rec declare_mutual_inductive_with_eliminations ?typing_flags ?(indlocs=[]) ?default_dep_elim ?(schemes=Default) ?all_depth mie ubinders impls = (* spiwack: raises an error if the structure is supposed to be non-recursive, but isn't *) begin match mie.mind_entry_finite with | Declarations.BiFinite -> if is_recursive mie then if Option.has_some mie.mind_entry_record then CErrors.user_err Pp.(strbrk "Records declared with the keywords Record or Structure cannot be recursive. You can, however, define recursive records using the Inductive or CoInductive command.") else CErrors.user_err Pp.(strbrk "Types declared with the keyword Variant cannot be recursive. Recursive types are defined with the Inductive and CoInductive command."); if not (Int.equal (List.length mie.mind_entry_inds) 1) then if Option.has_some mie.mind_entry_record then CErrors.user_err Pp.(strbrk "Keywords Record and Structure are to define a single type at once.") else CErrors.user_err Pp.(strbrk "Keyword Variant is to define a single type at once.") | _ -> () end; let names = List.map (fun e -> e.mind_entry_typename) mie.mind_entry_inds in let mind, why_not_prim_record = declare_mind ?typing_flags ~indlocs mie in why_not_prim_record |> Option.iter (fun why_not_prim_record -> warn_non_primitive_record (mind,why_not_prim_record)); let () = match fst ubinders with | UState.Polymorphic_entry _ -> () | UState.Monomorphic_entry ctx -> DeclareUniv.add_constraint_source (IndRef (mind,0)) ctx in DeclareUniv.declare_univ_binders (GlobRef.IndRef (mind,0)) ubinders; List.iteri (fun i (indimpls, constrimpls) -> let ind = (mind,i) in let gr = GlobRef.IndRef ind in Impargs.maybe_declare_manual_implicits false gr indimpls; List.iteri (fun j impls -> Impargs.maybe_declare_manual_implicits false (GlobRef.ConstructRef (ind, succ j)) impls) constrimpls) impls; (* Compute which inductive blocks can be eliminated dependently, and store it *) let () = match default_dep_elim with | None -> () | Some defaults -> List.iteri (fun i default -> let prop_but_default_dep_elim = match default with | PropButDepElim -> true | DefaultElim -> default_prop_dep_elim () && let _, mip = Global.lookup_inductive (mind, i) in Sorts.is_prop mip.mind_sort in if prop_but_default_dep_elim then Elimschemes.declare_prop_but_default_dependent_elim (mind, i) ) defaults in Flags.if_verbose Feedback.msg_info (minductive_message names); let indlocs = List.map fst indlocs in let locmap = Ind_tables.Locmap.make mind indlocs in let () = match schemes with | None -> () | Default -> if Option.has_some mie.mind_entry_private then () else let declare_mind ?all_depth entry univs = declare_mutual_inductive_with_eliminations ?typing_flags ?all_depth entry univs [] in Indschemes.declare_default_schemes ?all_depth ~declare_mind mind ~locmap in mind let do_scheme_all id strpos = let declare_mind ?all_depth entry univs = declare_mutual_inductive_with_eliminations ?all_depth entry univs [] in Indschemes.Internal.do_scheme_all ~user_call_scheme:true ~declare_mind id strpos module Internal = struct type nonrec inductive_obj = inductive_obj let objInductive = objInductive end rocq-9.2.0/vernac/declareInd.mli000066400000000000000000000037461516144147600165240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ?indlocs:indlocs -> ?default_dep_elim:default_dep_elim list -> ?schemes:declare_schemes -> ?all_depth:int -> Entries.mutual_inductive_entry (* Inductive types declaration *) -> UState.named_universes_entry (* Global universes, including the template default instance *) -> one_inductive_impls list (* Implicit arguments *) -> Names.MutInd.t (** Create the All predicate with its theorem all_forall. *) val do_scheme_all : Libnames.qualid Constrexpr.or_by_notation -> Names.Id.t list option -> unit (** {6 For legacy support, do not use} *) module Internal : sig type inductive_obj val objInductive : (Names.Id.t * inductive_obj) Libobject.Dyn.tag end val declare_primitive_projection : Names.Projection.Repr.t -> Names.Constant.t -> unit rocq-9.2.0/vernac/declareUniv.ml000066400000000000000000000246561516144147600165650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some Pp.(seq [ Pp.pr_opt_no_spc (fun s -> str s ++ spc ()) kind ; Id.print id; str " already exists."]) | _ -> None) type universe_source = | BoundUniv (* polymorphic universe, bound in a function (this will go away someday) *) | QualifiedUniv of DirPath.t (* global universe introduced by some global value *) | UnqualifiedUniv (* other global universe, todo merge with [QualifiedUniv []] *) type universe_name_decl = universe_source * (Id.t * UGlobal.t) list type sort_source = | BoundQuality | UnqualifiedQuality type sort_name_decl = { sdecl_src : sort_source; (* global sort introduced by some global value *) sdecl_named : (Id.t * Sorts.QGlobal.t) list; } let check_exists_universe sp = if Nametab.exists_universe sp then raise (AlreadyDeclared (Some "Universe", Libnames.basename sp)) else () let qualify_univ i dp src id = match src with | BoundUniv | UnqualifiedUniv -> i, Libnames.add_path_suffix dp id | QualifiedUniv l -> let path = Libnames.append_path dp l in Nametab.map_visibility (fun n -> n + List.length (DirPath.repr l)) i, Libnames.add_path_suffix path id let do_univ_name ~check i dp src (id,univ) = let i, sp = qualify_univ i dp src id in if check then check_exists_universe sp; Nametab.push_universe i sp univ let cache_univ_names (prefix, (src, univs)) = let depth = Lib.sections_depth () in let dp = Libnames.path_pop_n_suffixes depth prefix.Libobject.obj_path in List.iter (do_univ_name ~check:true (Nametab.Until 1) dp src) univs let load_univ_names i (prefix, (src, univs)) = List.iter (do_univ_name ~check:false (Nametab.Until i) prefix.Libobject.obj_path src) univs let open_univ_names i (prefix, (src, univs)) = List.iter (do_univ_name ~check:false (Nametab.Exactly i) prefix.Libobject.obj_path src) univs let discharge_univ_names = function | BoundUniv, _ -> None | (QualifiedUniv _ | UnqualifiedUniv), _ as x -> Some x let input_univ_names : universe_name_decl -> Libobject.obj = let open Libobject in declare_named_object_gen { (default_object "Global universe name state") with cache_function = cache_univ_names; load_function = load_univ_names; open_function = filtered_open open_univ_names; discharge_function = discharge_univ_names; classify_function = (fun _ -> Escape) } let input_univ_names (src, l) = if CList.is_empty l then () else Lib.add_leaf (input_univ_names (src, l)) let invent_name prefix (named,cnt) u = let rec aux i = let na = Id.of_string ("u"^(string_of_int i)) in let sp = Libnames.add_path_suffix prefix na in if Id.Map.mem na named || Nametab.exists_universe sp then aux (i+1) else na, (Id.Map.add na u named, i+1) in aux cnt let check_exists_sort sp = if Nametab.Quality.exists sp then raise (AlreadyDeclared (Some "Sort", Libnames.basename sp)) else () let qualify_sort i dp id = i, Libnames.add_path_suffix dp id let do_sort_name ~check i dp (id,quality) = let i, sp = qualify_sort i dp id in if check then check_exists_sort sp; Nametab.Quality.push i sp quality let cache_sort_names (prefix, decl) = let depth = Lib.sections_depth () in let dp = Libnames.path_pop_n_suffixes depth prefix.Libobject.obj_path in List.iter (do_sort_name ~check:true (Nametab.Until 1) dp) decl.sdecl_named let load_sort_names i (prefix, decl) = List.iter (do_sort_name ~check:false (Nametab.Until i) prefix.Libobject.obj_path) decl.sdecl_named let open_sort_names i (prefix, decl) = List.iter (do_sort_name ~check:false (Nametab.Exactly i) prefix.Libobject.obj_path) decl.sdecl_named let discharge_sort_names decl = match decl.sdecl_src with | BoundQuality -> None | UnqualifiedQuality -> Some decl let input_sort_names : sort_name_decl -> Libobject.obj = let open Libobject in declare_named_object_gen { (default_object "Global sort name state") with cache_function = cache_sort_names; load_function = load_sort_names; open_function = filtered_open open_sort_names; discharge_function = discharge_sort_names; classify_function = (fun a -> Escape) } let input_sort_names (src, l) = if CList.is_empty l then () else Lib.add_leaf (input_sort_names { sdecl_src = src; sdecl_named = l }) let label_of = let open GlobRef in function | ConstRef c -> Constant.label c | IndRef (c,_) -> MutInd.label c | VarRef id -> id | ConstructRef _ -> CErrors.anomaly ~label:"declare_univ_binders" Pp.(str "declare_univ_binders on a constructor reference") let declare_univ_binders gr (univs, pl) = let l = label_of gr in match univs with | UState.Polymorphic_entry _ -> () | UState.Monomorphic_entry (levels, _) -> let qs, pl = pl in assert (Id.Map.is_empty qs); (* First the explicitly named universes *) let named, univs = Id.Map.fold (fun id univ (named,univs) -> let univs = match Level.name univ with | None -> assert false (* having Prop/Set/Var as binders is nonsense *) | Some univ -> (id,univ)::univs in let named = Level.Set.add univ named in named, univs) pl (Level.Set.empty,[]) in (* then invent names for the rest *) let prefix = Libnames.add_path_suffix (Lib.cwd_except_section()) l in let _, univs = Level.Set.fold (fun univ (aux,univs) -> let id, aux = invent_name prefix aux univ in let univ = Option.get (Level.name univ) in aux, (id,univ) :: univs) (Level.Set.diff levels named) ((pl,0),univs) in input_univ_names (QualifiedUniv (DirPath.make [l]), univs) let name_mono_section_univs univs = if Level.Set.is_empty univs then () else let prefix = Lib.cwd () in let sections = let open Libnames in drop_dirpath_prefix (dirpath_of_path @@ Lib.cwd_except_section()) (dirpath_of_path prefix) in let _, univs = Level.Set.fold (fun univ (aux,univs) -> let id, aux = invent_name prefix aux univ in let univ = Option.get (Level.name univ) in aux, (id,univ) :: univs) univs ((Id.Map.empty, 0), []) in input_univ_names (QualifiedUniv sections, univs) let do_universe ~poly l = let in_section = Lib.sections_are_opened () in let () = if poly && not in_section then CErrors.user_err (Pp.str"Cannot declare polymorphic universes outside sections.") in let l = List.map (fun {CAst.v=id} -> (id, UnivGen.new_univ_global ())) l in let src = if poly then BoundUniv else UnqualifiedUniv in let () = input_univ_names (src, l) in match poly with | false -> let ctx = List.fold_left (fun ctx (_,qid) -> Level.Set.add (Level.make qid) ctx) Level.Set.empty l, Univ.UnivConstraints.empty in Global.push_context_set ctx | true -> let names = CArray.map_of_list (fun (na,_) -> Name na) l in let us = CArray.map_of_list (fun (_,l) -> Level.make l) l in let ctx = UVars.UContext.make {quals = [||]; univs = names} (UVars.Instance.of_array ([||],us), PConstraints.empty) in Global.push_section_context ctx let do_sort ~poly l = let in_section = Lib.sections_are_opened () in let () = if poly && not in_section then CErrors.user_err (Pp.str"Cannot declare polymorphic sorts outside sections.") in let l = List.map (fun {CAst.v=id} -> (id, UnivGen.new_sort_global id)) l in let src = if poly then BoundQuality else UnqualifiedQuality in let () = input_sort_names (src, l) in match poly with | false -> let qs = List.fold_left (fun qs (_, qv) -> Sorts.QVar.(Set.add (make_global qv) qs)) Sorts.QVar.Set.empty l in let rigid = false in (* No constraints, rigidity does not matter *) Global.push_qualities ~rigid (qs, Sorts.ElimConstraints.empty) (* XXX *) | true -> let names = CArray.map_of_list (fun (na,_) -> Name na) l in let qs = CArray.map_of_list (fun (_,sg) -> Sorts.Quality.global sg) l in let ctx = UVars.UContext.make {quals=names; univs=[||]} (UVars.Instance.of_array (qs,[||]), PConstraints.empty) in Global.push_section_context ctx let do_constraint ~poly l = let evd = Evd.from_env (Global.env ()) in let constraints = List.fold_left (fun acc cst -> match cst with | Constrexpr.UnivCst (l,d,r as cst) -> let cst = Constrintern.interp_univ_constraint evd cst in PConstraints.add_univ cst acc | Constrexpr.ElimCst (l,d,r as cst) -> let cst = Constrintern.interp_elim_constraint evd cst in PConstraints.add_quality cst acc) PConstraints.empty l in match poly with | false -> let qcst, ucst = constraints in let () = Global.push_qualities ~rigid:true (Sorts.QVar.Set.empty, qcst) in (* XXX *) Global.push_context_set (Univ.Level.Set.empty, ucst) | true -> let uctx = UVars.UContext.make UVars.empty_bound_names (UVars.Instance.empty,constraints) in Global.push_section_context uctx let constraint_sources = Summary.ref ~name:"univ constraint sources" [] let cache_constraint_source x = constraint_sources := x :: !constraint_sources let constraint_sources () = !constraint_sources let constraint_obj = Libobject.declare_object { (Libobject.default_object "univ constraint sources") with cache_function = cache_constraint_source; load_function = (fun _ c -> cache_constraint_source c); discharge_function = (fun x -> Some x); classify_function = (fun _ -> Escape); } (* XXX this seems like it could be merged with declare_univ_binders main issue is the filtering or redundant constraints (needed for perf / smaller vo file sizes) *) let add_constraint_source x ctx = let _, csts = ctx in if Univ.UnivConstraints.is_empty csts then () else let v = x, csts in Lib.add_leaf (constraint_obj v) rocq-9.2.0/vernac/declareUniv.mli000066400000000000000000000032141516144147600167210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* UState.named_universes_entry -> unit (** Internally used to name universes associated with no particular constant in a section. *) val name_mono_section_univs : Univ.Level.Set.t -> unit (** Command [Universes]. *) val do_universe : poly:bool -> lident list -> unit (** Command [Constraint]. *) val do_constraint : poly:bool -> Constrexpr.sort_constraint_expr list -> unit val add_constraint_source : GlobRef.t -> Univ.ContextSet.t -> unit val constraint_sources : unit -> (GlobRef.t * Univ.UnivConstraints.t) list (** Returns constraints associated to globrefs, newest first. *) (** Command [Sort]. *) val do_sort : poly:bool -> lident list -> unit rocq-9.2.0/vernac/declaremods.ml000066400000000000000000001765261516144147600166120ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* None | InlineAt i -> Some i | DefaultInline -> default_inline_level () (** These functions register the visibility of the module and iterates through its components. They are called by plenty of module functions *) let consistency_checks exists dir = if exists then let _ = try Nametab.locate_module (qualid_of_path dir) with Not_found -> user_err (pr_path dir ++ str " should already exist!") in () else if Nametab.exists_module dir then user_err (pr_path dir ++ str " already exists.") let rec get_module_path = function | MEident mp -> mp | MEwith (me,_) -> get_module_path me | MEapply (me,_) -> get_module_path me let type_of_mod mp env = function | true -> mod_type (Environ.lookup_module mp env) | false -> mod_type (Environ.lookup_modtype mp env) (** {6 Name management} Auxiliary functions to transform full_path and kernel_name given by Lib into ModPath.t and DirPath.t needed for modules *) let mp_of_kn kn = let mp,l = KerName.repr kn in MPdot (mp,l) let pop_path sp = path_pop_suffix sp, basename sp let path_of_file dp = match DirPath.repr dp with | x :: dp -> make_path (DirPath.make dp) x | [] -> CErrors.anomaly Pp.(str "Cannot start library with empty dirpath") (* Avoid generating a KeepObject for nothing *) let keep_objects id keep = match keep.keep_objects with | [] -> [] | _ :: _ -> [KeepObject (id, keep)] let escape_objects id escape = match escape.escape_objects with | [] -> [] | _ :: _ -> [EscapeObject (id, escape)] (** The [ModActions] abstraction represent operations on modules that are specific to a given stage. Two instances are defined below, for Synterp and Interp. *) module type ModActions = sig type typexpr type env val stage : Summary.Stage.t val substobjs_table_name : string val modobjs_table_name : string val enter_module : ModPath.t -> full_path -> int -> unit val enter_modtype : ModPath.t -> full_path -> int -> unit val open_module : open_filter -> ModPath.t -> full_path -> int -> unit module Lib : Lib.StagedLibS (** Create the substitution corresponding to some functor applications *) val compute_subst : is_mod:bool -> env -> MBId.t list -> ModPath.t -> ModPath.t list -> Entries.inline -> MBId.t list * substitution end module SynterpActions : ModActions with type env = unit with type typexpr = Constrexpr.universe_decl_expr option * Constrexpr.constr_expr = struct type typexpr = Constrexpr.universe_decl_expr option * Constrexpr.constr_expr type env = unit let stage = Summary.Stage.Synterp let substobjs_table_name = "MODULE-SYNTAX-SUBSTOBJS" let modobjs_table_name = "MODULE-SYNTAX-OBJS" let enter_module obj_mp obj_path i = consistency_checks false obj_path; Nametab.push_module (Until i) obj_path obj_mp let enter_modtype mp sp i = if Nametab.exists_modtype sp then anomaly (pr_path sp ++ str " already exists."); Nametab.push_modtype (Nametab.Until i) sp mp let open_module f obj_mp obj_path i = consistency_checks true obj_path; if in_filter ~cat:None f then Nametab.push_module (Nametab.Exactly i) obj_path obj_mp module Lib = Lib.Synterp let rec compute_subst () mbids mp_l inl = match mbids,mp_l with | _,[] -> mbids,empty_subst | [],r -> user_err Pp.(str "Application of a functor with too few arguments.") | mbid::mbids,mp::mp_l -> let mbid_left,subst = compute_subst () mbids mp_l inl in mbid_left, join (map_mbid mbid mp (empty_delta_resolver mp)) subst let compute_subst ~is_mod () mbids mp1 mp_l inl = compute_subst () mbids mp_l inl end module InterpActions : ModActions with type env = Environ.env with type typexpr = Constr.t * UVars.AbstractContext.t option = struct type typexpr = Constr.t * UVars.AbstractContext.t option type env = Environ.env let stage = Summary.Stage.Interp let substobjs_table_name = "MODULE-SUBSTOBJS" let modobjs_table_name = "MODULE-OBJS" (** {6 Current module type information} This information is stored by each [start_modtype] for use in a later [end_modtype]. *) let enter_module obj_mp obj_path i = () let enter_modtype mp sp i = () let open_module f obj_mp obj_path i = () module Lib = Lib.Interp let rec compute_subst env mbids sign mp_l inl = match mbids,mp_l with | _,[] -> mbids,empty_subst | [],r -> user_err Pp.(str "Application of a functor with too few arguments.") | mbid::mbids,mp::mp_l -> let farg_id, farg_b, fbody_b = Modops.destr_functor sign in let mb = Environ.lookup_module mp env in let mbid_left,subst = compute_subst env mbids fbody_b mp_l inl in let resolver = match mod_global_delta mb with | None -> empty_delta_resolver mp | Some delta -> Modops.inline_delta_resolver env inl mp farg_id farg_b delta in mbid_left,join (map_mbid mbid mp resolver) subst let compute_subst ~is_mod env mbids mp1 mp_l inl = let typ = type_of_mod mp1 env is_mod in compute_subst env mbids typ mp_l inl end type exp_substituted_object = (substitutive_objects, exp_algebraic_objects, Empty.t, Empty.t) object_view and exp_algebraic_objects = { exp_algebraic_objects : exp_substituted_object list } (* and exp_substitutive_objects = Names.MBId.t list * exp_algebraic_objects *) type module_objects = { module_prefix : object_prefix; module_substituted_objects : exp_substituted_object list; module_keep_objects : keep_objects; module_escape_objects : escape_objects; } (** The [StagedModS] abstraction describes module operations at a given stage. *) module type StagedModS = sig type typexpr type env val get_module_sobjs : bool -> env -> Entries.inline -> typexpr module_alg_expr -> substitutive_objects val load_keep : int -> full_path -> ModPath.t -> keep_objects -> unit val load_escape : int -> full_path -> ModPath.t -> escape_objects -> unit val load_module : int -> full_path -> ModPath.t -> substitutive_objects -> unit val import_modules : export:Lib.export_flag -> (open_filter * ModPath.t) list -> unit val add_leaf : Libobject.t -> unit val add_leaves : Libobject.t list -> unit val expand_aobjs : Libobject.algebraic_objects -> Libobject.t list val get_applications : typexpr module_alg_expr -> ModPath.t * ModPath.t list val debug_print_modtab : unit -> Pp.t module ModObjs : sig val all : unit -> module_objects ModPath.Map.t end val close_section : unit -> unit end (** Some utilities about substitutive objects : substitution, expansion *) let sobjs_no_functor (mbids,_) = List.is_empty mbids let subst_filtered sub (f,mp as x) = let mp' = subst_mp sub mp in if mp == mp' then x else f, mp' let rec subst_aobjs sub = function | Objs o as objs -> let o' = subst_objects sub o in if o == o' then objs else Objs o' | Ref (mp, sub0) as r -> let sub0' = join sub0 sub in if sub0' == sub0 then r else Ref (mp, sub0') and subst_sobjs sub (mbids,aobjs as sobjs) = let aobjs' = subst_aobjs sub aobjs in if aobjs' == aobjs then sobjs else (mbids, aobjs') and subst_objects subst seg = let subst_one node = match node with | AtomicObject obj -> let obj' = Libobject.subst_object (subst,obj) in if obj' == obj then node else AtomicObject obj' | ModuleObject (id, sobjs) -> let sobjs' = subst_sobjs subst sobjs in if sobjs' == sobjs then node else ModuleObject (id, sobjs') | ModuleTypeObject (id, sobjs) -> let sobjs' = subst_sobjs subst sobjs in if sobjs' == sobjs then node else ModuleTypeObject (id, sobjs') | IncludeObject aobjs -> let aobjs' = subst_aobjs subst aobjs in if aobjs' == aobjs then node else IncludeObject aobjs' | ExportObject { mpl } -> let mpl' = List.Smart.map (subst_filtered subst) mpl in if mpl'==mpl then node else ExportObject { mpl = mpl' } | KeepObject _ | EscapeObject _ -> assert false in List.Smart.map subst_one seg (** The [StagedMod] abstraction factors out the code dealing with modules that is common to all stages. *) module StagedMod(Actions : ModActions) = struct type typexpr = Actions.typexpr type env = Actions.env (** ModSubstObjs : a cache of module substitutive objects This table is common to modules and module types. - For a Module M:=N, the objects of N will be reloaded with M after substitution. - For a Module M:SIG:=..., the module M gets its objects from SIG Invariants: - A alias (i.e. a module path inside a Ref constructor) should never lead to another alias, but rather to a concrete Objs constructor. We will plug later a handler dealing with missing entries in the cache. Such missing entries may come from inner parts of module types, which aren't registered by the standard libobject machinery. *) module ModSubstObjs : sig val set : ModPath.t -> substitutive_objects -> unit val get : ModPath.t -> substitutive_objects val set_missing_handler : (ModPath.t -> substitutive_objects) -> unit end = struct let table = Summary.ref ~stage:Actions.stage (ModPath.Map.empty : substitutive_objects ModPath.Map.t) ~name:Actions.substobjs_table_name let missing_handler = ref (fun mp -> assert false) let set_missing_handler f = (missing_handler := f) let set mp objs = (table := ModPath.Map.add mp objs !table) let get mp = try ModPath.Map.find mp !table with Not_found -> !missing_handler mp end let expand_aobjs = function | Objs o -> o | Ref (mp, sub) -> match ModSubstObjs.get mp with | (_,Objs o) -> subst_objects sub o | _ -> assert false (* Invariant : any alias points to concrete objs *) let expand_sobjs (_,aobjs) = expand_aobjs aobjs module Expand = struct type exp_object = (substitutive_objects, exp_algebraic_objects, keep_objects, escape_objects) object_view let exp_substituted_view (obj : exp_substituted_object) : exp_object = match obj with | (AtomicObject _ | ModuleObject _ | ModuleTypeObject _ | IncludeObject _ | ExportObject _) as o -> o | EscapeObject (_, o) | KeepObject (_, o) -> Empty.abort o let keep_view (obj : Libobject.t) : exp_object = match obj with | (AtomicObject _ | KeepObject _) as o -> o | ModuleObject _ | ModuleTypeObject _ | IncludeObject _ | ExportObject _ | EscapeObject _ -> assert false (** keep objects only contain atomic / keep *) let escape_view (obj : Libobject.t) : exp_object = match obj with | (AtomicObject _ | EscapeObject _) as o -> o | ModuleObject _ | ModuleTypeObject _ | IncludeObject _ | ExportObject _ | KeepObject _ -> assert false (** escape objects only contain atomic / escape *) let rec substituted_object_view (obj : Libobject.t) : exp_substituted_object = match obj with | (AtomicObject _ | ModuleObject _ | ModuleTypeObject _ | ExportObject _) as o -> o | IncludeObject aobjs -> let aobjs = expand_aobjs aobjs in IncludeObject { exp_algebraic_objects = List.map substituted_object_view aobjs } | EscapeObject _ | KeepObject _ -> (* forbidden in substitutive objects *) assert false let object_view (obj : Libobject.t) : exp_object = match obj with | (AtomicObject _ | EscapeObject _ | ModuleObject _ | ModuleTypeObject _ | ExportObject _ | KeepObject _) as o -> o | IncludeObject aobjs -> let aobjs = expand_aobjs aobjs in IncludeObject { exp_algebraic_objects = List.map substituted_object_view aobjs } end (** {6 ModObjs : a cache of module objects} For each module, we also store a cache of "prefix", "substituted objects", "keep objects". This is used for instance to implement the "Import" command. substituted objects : roughly the objects above after the substitution - we need to keep them to call open_object when the module is opened (imported) keep objects : The list of non-substitutive objects - as above, for each of them we will call open_object when the module is opened (Some) Invariants: * If the module is a functor, it won't appear in this cache. * Module objects in substitutive_objects part have empty substituted objects. * Modules which where created with Module M:=mexpr or with Module M:SIG. ... End M. have the keep list empty. *) module ModObjs : sig val set : ModPath.t -> module_objects -> unit val get : ModPath.t -> module_objects (* may raise Not_found *) val all : unit -> module_objects ModPath.Map.t end = struct let table = Summary.ref ~stage:Actions.stage (ModPath.Map.empty : module_objects ModPath.Map.t) ~name:Actions.modobjs_table_name let set mp objs = (table := ModPath.Map.add mp objs !table) let get mp = ModPath.Map.find mp !table let all () = !table end open Expand (** {6 Declaration of module substitutive objects} *) (** Nota: Interactive modules and module types cannot be recached! This used to be checked here via a flag along the substobjs. *) (** {6 Declaration of module type substitutive objects} *) (** Nota: Interactive modules and module types cannot be recached! This used to be checked more properly here. *) let load_modtype i sp mp sobjs = Actions.enter_modtype mp sp i; ModSubstObjs.set mp sobjs (** {6 Declaration of substitutive objects for Include} *) let rec load_object : type a. (a -> exp_object) -> int -> object_prefix * a -> unit = fun view i (prefix, obj) -> match view obj with | AtomicObject o -> Libobject.load_object i (prefix, o) | ModuleObject (id,sobjs) -> let sp, kn = Lib.make_oname prefix id in load_module i sp (mp_of_kn kn) sobjs | ModuleTypeObject (id,sobjs) -> let name = Lib.make_oname prefix id in let (sp,kn) = name in load_modtype i sp (mp_of_kn kn) sobjs | IncludeObject aobjs -> load_include i (prefix, aobjs) | ExportObject _ -> () | KeepObject (id,objs) -> let sp, kn = Lib.make_oname prefix id in load_keep i sp (mp_of_kn kn) objs | EscapeObject (id,objs) -> let sp, kn = Lib.make_oname prefix id in load_escape i sp (mp_of_kn kn) objs and load_objects : type a. (a -> exp_object) -> int -> object_prefix -> a list -> unit = fun view i prefix objs -> List.iter (fun obj -> load_object view i (prefix, obj)) objs and load_include i (prefix, aobjs) = load_objects exp_substituted_view i prefix aobjs.exp_algebraic_objects and load_keep i obj_path obj_mp kobjs = (* Invariant : seg isn't empty *) let prefix = { obj_path ; obj_mp; } in let modobjs = try ModObjs.get obj_mp with Not_found -> assert false (* a substobjs should already be loaded *) in assert (eq_object_prefix modobjs.module_prefix prefix); assert (List.is_empty modobjs.module_keep_objects.keep_objects); ModObjs.set obj_mp { modobjs with module_keep_objects = kobjs }; load_objects keep_view (i+1) prefix kobjs.keep_objects and load_escape i obj_path obj_mp eobjs = (* Invariant : seg isn't empty *) let prefix = { obj_path ; obj_mp; } in let modobjs = try ModObjs.get obj_mp with Not_found -> (* escape objects can exist even if there is no corresponding real module *) { module_prefix = prefix; module_substituted_objects = []; module_keep_objects = { keep_objects = [] }; module_escape_objects = { escape_objects = [] }; } in assert (eq_object_prefix modobjs.module_prefix prefix); assert (List.is_empty modobjs.module_escape_objects.escape_objects); ModObjs.set obj_mp { modobjs with module_escape_objects = eobjs }; load_objects escape_view (i+1) prefix eobjs.escape_objects and load_module i obj_path obj_mp sobjs = let prefix = { obj_path ; obj_mp; } in Actions.enter_module obj_mp obj_path i; ModSubstObjs.set obj_mp sobjs; (* If we're not a functor, let's iter on the internal components *) if sobjs_no_functor sobjs then begin let objs = expand_sobjs sobjs in let objs = List.map substituted_object_view objs in let module_objects = { module_prefix = prefix; module_substituted_objects = objs; module_keep_objects = { keep_objects = [] }; module_escape_objects = { escape_objects = [] }; } in ModObjs.set obj_mp module_objects; load_objects exp_substituted_view (i+1) prefix objs end (** {6 Implementation of Import and Export commands} *) let mark_object f obj (exports,acc) = (exports, (f,obj)::acc) let rec collect_module (f,mp) acc = try (* May raise Not_found for unknown module and for functors *) let modobjs = ModObjs.get mp in let prefix = modobjs.module_prefix in let acc = collect_objects escape_view f 1 prefix modobjs.module_escape_objects.escape_objects acc in let acc = collect_objects keep_view f 1 prefix modobjs.module_keep_objects.keep_objects acc in collect_objects exp_substituted_view f 1 prefix modobjs.module_substituted_objects acc with Not_found when Actions.stage = Summary.Stage.Synterp -> acc and collect_object : type a. (a -> exp_object) -> _ -> _ -> _ -> a -> _ -> _ = fun view f i prefix obj acc -> match view obj with | ExportObject { mpl } -> collect_exports f i mpl acc | (AtomicObject _ | IncludeObject _ | KeepObject _ | EscapeObject _ | ModuleObject _ | ModuleTypeObject _) as obj -> mark_object f (prefix,obj) acc and collect_objects : type a. (a -> exp_object) -> _ -> _ -> _ -> a list -> _ = fun view f i prefix objs acc -> List.fold_left (fun acc obj -> collect_object view f i prefix obj acc) acc (List.rev objs) and collect_export f (f',mp) (exports,objs as acc) = match filter_and f f' with | None -> acc | Some f -> let exports' = ModPath.Map.update mp (function | None -> Some f | Some f0 -> let f' = filter_or f f0 in if filter_eq f' f0 then Some f0 else Some f') exports in (* If the map doesn't change there is nothing new to export. *) if exports == exports' then acc else collect_module (f,mp) (exports', objs) and collect_exports f i mpl acc = if Int.equal i 1 then List.fold_left (fun acc fmp -> collect_export f fmp acc) acc (List.rev mpl) else acc let collect_modules mpl = List.fold_left (fun acc fmp -> collect_module fmp acc) (ModPath.Map.empty, []) (List.rev mpl) let open_modtype i ((sp,kn),_) = let mp = mp_of_kn kn in let mp' = try Nametab.locate_modtype (qualid_of_path sp) with Not_found -> anomaly (pr_path sp ++ str " should already exist!"); in assert (ModPath.equal mp mp'); Nametab.push_modtype (Nametab.Exactly i) sp mp let rec open_object : type a. (a -> exp_object) -> _ -> _ -> _ * a -> _ = fun view f i (prefix, obj) -> match view obj with | AtomicObject o -> Libobject.open_object f i (prefix, o) | ModuleObject (id,sobjs) -> let sp, kn = Lib.make_oname prefix id in let mp = mp_of_kn kn in open_module f i sp mp sobjs | ModuleTypeObject (id,sobjs) -> let name = Lib.make_oname prefix id in open_modtype i (name, sobjs) | IncludeObject aobjs -> open_include f i (prefix, aobjs) | ExportObject { mpl } -> open_export f i mpl | KeepObject (id,objs) -> let name = Lib.make_oname prefix id in open_keep f i (name, objs) | EscapeObject (id,objs) -> let name = Lib.make_oname prefix id in open_escape f i (name, objs) and open_module f i obj_path obj_mp sobjs = Actions.open_module f obj_mp obj_path i; (* If we're not a functor, let's iter on the internal components *) if sobjs_no_functor sobjs then begin let modobjs = ModObjs.get obj_mp in open_objects exp_substituted_view f (i+1) modobjs.module_prefix modobjs.module_substituted_objects end and open_objects : type a. (a -> exp_object) -> _ -> _ -> _ -> a list -> _ = fun view f i prefix objs -> List.iter (fun obj -> open_object view f i (prefix, obj)) objs and open_include f i (prefix, aobjs) = open_objects exp_substituted_view f i prefix aobjs.exp_algebraic_objects and open_export f i mpl = let _,objs = collect_exports f i mpl (ModPath.Map.empty, []) in List.iter (fun (f,o) -> open_object (fun x -> x) f 1 o) objs and open_keep f i ((sp,kn),kobjs) = let obj_mp = mp_of_kn kn in let prefix = { obj_path=sp; obj_mp; } in open_objects keep_view f (i+1) prefix kobjs.keep_objects and open_escape f i ((sp,kn),kobjs) = let obj_mp = mp_of_kn kn in let prefix = { obj_path=sp; obj_mp; } in open_objects escape_view f (i+1) prefix kobjs.escape_objects let cache_include (prefix, aobjs) = let o = expand_aobjs aobjs in let o = List.map substituted_object_view o in load_objects exp_substituted_view 1 prefix o; open_objects exp_substituted_view unfiltered 1 prefix o let cache_object (prefix, obj) = match obj with | AtomicObject o -> Libobject.cache_object (prefix, o) | ModuleObject _ -> load_object object_view 1 (prefix,obj) | ModuleTypeObject _ -> load_object object_view 0 (prefix,obj) | IncludeObject aobjs -> cache_include (prefix, aobjs) | ExportObject { mpl } -> anomaly Pp.(str "Export should not be cached") | KeepObject _ | EscapeObject _ -> anomaly (Pp.str "This module should not be cached!") (* Adding operations with containers *) let add_leaf_entry = match Actions.stage with | Summary.Stage.Synterp -> Lib.Synterp.add_leaf_entry | Summary.Stage.Interp -> Lib.Interp.add_leaf_entry let add_leaf obj = cache_object (Lib.prefix (),obj); add_leaf_entry obj let add_leaves objs = let add_obj obj = add_leaf_entry obj; load_object object_view 1 (Lib.prefix (),obj) in List.iter add_obj objs let import_modules ~export mpl = let _,objs = collect_modules mpl in List.iter (fun (f,o) -> open_object (fun x -> x) f 1 o) objs; match export with | Lib.Import -> () | Lib.Export -> let entry = ExportObject { mpl } in add_leaf_entry entry (** {6 Handler for missing entries in ModSubstObjs} *) (** Since the inner of Module Types are not added by default to the ModSubstObjs table, we compensate this by explicit traversal of Module Types inner objects when needed. Quite a hack... *) let mp_id mp id = MPdot (mp, id) let rec register_mod_objs mp obj = match obj with | ModuleObject (id,sobjs) -> ModSubstObjs.set (mp_id mp id) sobjs | ModuleTypeObject (id,sobjs) -> ModSubstObjs.set (mp_id mp id) sobjs | IncludeObject aobjs -> List.iter (register_mod_objs mp) (expand_aobjs aobjs) | _ -> () let handle_missing_substobjs mp = match mp with | MPdot (mp',l) -> let objs = expand_sobjs (ModSubstObjs.get mp') in List.iter (register_mod_objs mp') objs; ModSubstObjs.get mp | _ -> assert false (* Only inner parts of module types should be missing *) let () = ModSubstObjs.set_missing_handler handle_missing_substobjs (** {6 From module expression to substitutive objects} *) (** Turn a chain of [MSEapply] into the head ModPath.t and the list of ModPath.t parameters (deepest param coming first). The left part of a [MSEapply] must be either [MSEident] or another [MSEapply]. *) let get_applications mexpr = let rec get params = function | MEident mp -> mp, params | MEapply (fexpr, mp) -> get (mp::params) fexpr | MEwith _ -> user_err Pp.(str "Non-atomic functor application.") in get [] mexpr (** Create the objects of a "with Module" structure. *) let rec replace_module_object idl mp0 objs0 mp1 objs1 = match idl, objs0 with | _,[] -> [] | id::idl,(ModuleObject (id', sobjs))::tail when Id.equal id id' -> begin let mp_id = MPdot(mp0, id) in let objs = match idl with | [] -> subst_objects (map_mp mp1 mp_id (empty_delta_resolver mp_id)) objs1 | _ -> let objs_id = expand_sobjs sobjs in replace_module_object idl mp_id objs_id mp1 objs1 in (ModuleObject (id, ([], Objs objs)))::tail end | idl,lobj::tail -> lobj::replace_module_object idl mp0 tail mp1 objs1 (** Substitutive objects of a module expression (or module type) *) let rec get_module_sobjs is_mod env inl = function | MEident mp -> begin match ModSubstObjs.get mp with | (mbids,Objs _) when not (ModPath.is_bound mp) -> (mbids,Ref (mp, empty_subst)) (* we create an alias *) | sobjs -> sobjs end | MEwith (mty, WithDef _) -> get_module_sobjs is_mod env inl mty | MEwith (mty, WithMod (idl,mp1)) -> assert (not is_mod); let sobjs0 = get_module_sobjs is_mod env inl mty in if not (sobjs_no_functor sobjs0) then user_err Pp.(str "Illegal use of a functor."); (* For now, we expand everything, to be safe *) let mp0 = get_module_path mty in let objs0 = expand_sobjs sobjs0 in let objs1 = expand_sobjs (ModSubstObjs.get mp1) in ([], Objs (replace_module_object idl mp0 objs0 mp1 objs1)) | MEapply _ as me -> let mp1, mp_l = get_applications me in let mbids, aobjs = get_module_sobjs is_mod env inl (MEident mp1) in let mbids_left,subst = Actions.compute_subst ~is_mod env mbids mp1 mp_l inl in (mbids_left, subst_aobjs subst aobjs) let debug_print_modtab () = let pr_seg = function | 0 -> str "[]" | l -> str "[." ++ int l ++ str ".]" in let pr_modinfo mp modobjs s = let objs = List.length modobjs.module_substituted_objects + List.length modobjs.module_keep_objects.keep_objects in s ++ str (ModPath.to_string mp) ++ spc () ++ pr_seg objs in let modules = ModPath.Map.fold pr_modinfo (ModObjs.all ()) (mt ()) in hov 0 modules let add_discharged_item : Lib.discharged_item -> unit = function | DischargedExport { mpl } -> import_modules ~export:Export mpl | DischargedLeaf o -> Lib.add_discharged_leaf o let close_section () = let objs = Actions.Lib.close_section () in List.iter add_discharged_item objs end module SynterpVisitor : StagedModS with type env = SynterpActions.env with type typexpr = Constrexpr.universe_decl_expr option * Constrexpr.constr_expr = StagedMod(SynterpActions) module InterpVisitor : StagedModS with type env = InterpActions.env with type typexpr = Constr.t * UVars.AbstractContext.t option = StagedMod(InterpActions) (** {6 Modules : start, end, declare} *) type current_module_syntax_info = { cur_mp : ModPath.t; cur_typ : ((Constrexpr.universe_decl_expr option * Constrexpr.constr_expr) module_alg_expr * int option) option; cur_mbids : MBId.t list; } let default_module_syntax_info mp = { cur_mp = mp; cur_typ = None; cur_mbids = [] } let openmod_syntax_info = Summary.ref None ~stage:Summary.Stage.Synterp ~name:"MODULE-SYNTAX-INFO" (** {6 Current module information} This information is stored by each [start_module] for use in a later [end_module]. *) type current_module_info = { cur_typ : (module_struct_entry * int option) option; (** type via ":" *) cur_typs : module_type_body list (** types via "<:" *) } let default_module_info = { cur_typ = None; cur_typs = [] } let openmod_info = Summary.ref default_module_info ~name:"MODULE-INFO" let start_library dir = let mp = Global.start_library dir in openmod_info := default_module_info; openmod_syntax_info := Some (default_module_syntax_info mp); Lib.start_compilation dir mp let set_openmod_syntax_info info = match !openmod_syntax_info with | None -> anomaly Pp.(str "bad init of openmod_syntax_info") | Some _ -> openmod_syntax_info := Some info let openmod_syntax_info () = match !openmod_syntax_info with | None -> anomaly Pp.(str "missing init of openmod_syntax_info") | Some v -> v let vm_state = (* VM bytecode is not needed here *) let vm_handler _ _ _ () = (), None in ((), { Mod_typing.vm_handler }) module RawModOps = struct module Synterp = struct let build_subtypes mtys = List.map (fun (m,ann) -> let inl = inl2intopt ann in let mte, base, kind = Modintern.intern_module_ast Modintern.ModType m in (mte, base, kind, inl)) mtys let intern_arg (idl,(typ,ann)) = let inl = inl2intopt ann in let lib_dir = Lib.library_dp() in let (mty, base, kind) = Modintern.intern_module_ast Modintern.ModType typ in let sobjs = SynterpVisitor.get_module_sobjs false () inl mty in let mp0 = get_module_path mty in let map {CAst.v=id} = let sp = Libnames.make_path DirPath.empty id in let mbid = MBId.make lib_dir id in let mp = MPbound mbid in (* We can use an empty delta resolver because we load only syntax objects *) let sobjs = subst_sobjs (map_mp mp0 mp (empty_delta_resolver mp)) sobjs in SynterpVisitor.load_module 1 sp mp sobjs; mbid in List.map map idl, (mty, base, kind, inl) let intern_args params = List.map intern_arg params let start_module_core id args res = (* Loads the parsing objects in arguments *) let args = intern_args args in let mbids = List.flatten @@ List.map (fun (mbidl,_) -> mbidl) args in let res_entry_o, sign = match res with | Enforce (res,ann) -> let inl = inl2intopt ann in let (mte, base, kind) = Modintern.intern_module_ast Modintern.ModType res in Some (mte, inl), Enforce (mte, base, kind, inl) | Check resl -> None, Check (build_subtypes resl) in let mp = ModPath.MPdot((openmod_syntax_info ()).cur_mp, id) in mp, res_entry_o, mbids, sign, args let start_module export id args res = let () = if Option.has_some export && not (CList.is_empty args) then user_err Pp.(str "Cannot import functors.") in let fs = Summary.Synterp.freeze_summaries () in let mp, res_entry_o, mbids, sign, args = start_module_core id args res in set_openmod_syntax_info { cur_mp = mp; cur_typ = res_entry_o; cur_mbids = mbids }; let prefix = Lib.Synterp.start_module export id mp fs in Nametab.(push_dir (Until 1) (prefix.obj_path) (GlobDirRef.DirOpenModule prefix.obj_mp)); mp, args, sign let end_module_core id (m_info : current_module_syntax_info) objects fs = let {Lib.substobjs = substitute; keepobjs = keep; escapeobjs = escape; anticipateobjs = special; } = objects in (* For sealed modules, we use the substitutive objects of their signatures *) let sobjs0, keep = match m_info.cur_typ with | None -> ([], Objs substitute), keep | Some (mty, inline) -> SynterpVisitor.get_module_sobjs false () inline mty, { keep_objects = [] } in Summary.Synterp.unfreeze_summaries fs; let sobjs = let (ms,objs) = sobjs0 in (m_info.cur_mbids@ms,objs) in (* We substitute objects if the module is sealed by a signature *) let sobjs = match m_info.cur_typ with | None -> sobjs | Some (mty, _) -> subst_sobjs (map_mp (get_module_path mty) m_info.cur_mp (empty_delta_resolver m_info.cur_mp)) sobjs in let node = ModuleObject (id,sobjs) in (* We add the keep objects, if any, and if this isn't a functor *) let keep = if not (CList.is_empty m_info.cur_mbids) then [] else keep_objects id keep in let escape = escape_objects id escape in let objects = special@[node]@keep@escape in m_info.cur_mp, objects let end_module () = let oldprefix,fs,objects = Lib.Synterp.end_module () in let m_info = openmod_syntax_info () in let olddp, id = pop_path oldprefix.obj_path in let mp,objects = end_module_core id m_info objects fs in let () = SynterpVisitor.add_leaves objects in assert (eq_full_path (Lib.prefix()).obj_path olddp); mp let get_functor_sobjs is_mod inl (mbids,mexpr) = let (mbids0, aobjs) = SynterpVisitor.get_module_sobjs is_mod () inl mexpr in (mbids @ mbids0, aobjs) let declare_module id args res mexpr_o = let fs = Summary.Synterp.freeze_summaries () in (* We simulate the beginning of an interactive module, then we adds the module parameters to the global env. *) let mp = ModPath.MPdot((openmod_syntax_info ()).cur_mp, id) in let args = intern_args args in let mbids = List.flatten @@ List.map fst args in let mty_entry_o = match res with | Enforce (mty,ann) -> let inl = inl2intopt ann in let (mte, base, kind) = Modintern.intern_module_ast Modintern.ModType mty in Enforce (mte, base, kind, inl) | Check mtys -> Check (build_subtypes mtys) in let mexpr_entry_o = match mexpr_o with | None -> None | Some (mexpr,ann) -> let (mte, base, kind) = Modintern.intern_module_ast Modintern.Module mexpr in Some (mte, base, kind, inl2intopt ann) in let sobjs, mp0 = match mexpr_entry_o, mty_entry_o with | None, Check _ -> assert false (* No body, no type ... *) | _, Enforce (typ,_,_,inl_res) -> get_functor_sobjs false inl_res (mbids,typ), get_module_path typ | Some (body, _, _, inl_expr), Check _ -> get_functor_sobjs true inl_expr (mbids,body), get_module_path body in (* Undo the simulated interactive building of the module and declare the module as a whole *) Summary.Synterp.unfreeze_summaries fs; (* We can use an empty delta resolver on syntax objects *) let sobjs = subst_sobjs (map_mp mp0 mp (empty_delta_resolver mp)) sobjs in ignore (SynterpVisitor.add_leaf (ModuleObject (id,sobjs))); mp, args, mexpr_entry_o, mty_entry_o end module Interp = struct (** {6 Auxiliary functions concerning subtyping checks} *) let check_sub env mp sub_mtb_l = let fold sub_mtb (cst, env) = let state = ((Environ.universes env, cst), Reductionops.inferred_universes) in let ugraph, cst = Subtyping.check_subtypes state env mp mp sub_mtb in (cst, Environ.set_universes ugraph env) in let cst, _ = List.fold_right fold sub_mtb_l (Univ.UnivConstraints.empty, env) in Global.add_univ_constraints cst (** This function checks if the type calculated for the module [mp] is a "<:"-like subtype of all signatures in [sub_mtb_l]. Uses only the global environment. *) let check_subtypes mp sub_mtb_l = check_sub (Global.env ()) mp sub_mtb_l (** Same for module type [mp] *) let check_subtypes_mt mp sub_mtb_l = let mtb = try Global.lookup_modtype mp with Not_found -> assert false in let env = Modops.add_module mp (module_body_of_type mtb) (Global.env ()) in check_sub env mp sub_mtb_l let current_modresolver () = Safe_typing.delta_of_senv @@ Global.safe_env () let current_struct () = let struc = Safe_typing.structure_body_of_safe_env @@ Global.safe_env () in NoFunctor (List.rev struc) (** Prepare the module type list for check of subtypes *) let build_subtypes env mp args mtys = let (ctx, ans) = List.fold_left_map (fun ctx (mte,base,kind,inl) -> let mte, ctx' = Modintern.interp_module_ast env Modintern.ModType base mte in let env = Environ.push_context_set ~strict:true ctx' env in let ctx = Univ.ContextSet.union ctx ctx' in let state = ((Environ.universes env, Univ.UnivConstraints.empty), Reductionops.inferred_universes) in (* functor arguments are already part of the env, we compute the type and requantify over them *) let mtb, (_, cst), _ = Mod_typing.translate_modtype state vm_state env mp inl ([], mte) in let fold (mbid, mtb, _, _) accu = MoreFunctor (mbid, mtb, accu) in (* XXX: parameters will be rechecked for subtyping, even though we statically know they are the same as the ones of the ambient module *) let sign = List.fold_right fold args (mod_type mtb) in let mtb = make_module_type sign (mod_delta mtb) in let ctx = Univ.ContextSet.add_constraints cst ctx in ctx, mtb) Univ.ContextSet.empty mtys in (ans, ctx) (** Process a declaration of functor parameter(s) (Id1 .. Idn : Typ) i.e. possibly multiple names with the same module type. Global environment is updated on the fly. Objects in these parameters are also loaded. Output is accumulated on top of [acc] (in reverse order). *) let intern_arg (acc, cst) (mbidl,(mty, base, kind, inl)) = let env = Global.env() in let (mty, cst') = Modintern.interp_module_ast env kind base mty in let () = Global.push_context_set cst' in let () = let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let _, (_, cst), _ = Mod_typing.translate_modtype state vm_state (Global.env ()) base inl ([], mty) in Global.add_univ_constraints cst in let env = Global.env () in let sobjs = InterpVisitor.get_module_sobjs false env inl mty in let mp0 = get_module_path mty in let fold acc mbid = let id = MBId.to_id mbid in let sp = Libnames.make_path DirPath.empty id in let mp = MPbound mbid in let mtb = Global.add_module_parameter mbid mty inl in let resolver = mod_delta mtb in let sobjs = subst_sobjs (map_mp mp0 mp resolver) sobjs in InterpVisitor.load_module 1 sp mp sobjs; (mbid, mtb, mty, inl) :: acc in let acc = List.fold_left fold acc mbidl in (acc, Univ.ContextSet.union cst cst') (** Process a list of declarations of functor parameters (Id11 .. Id1n : Typ1)..(Idk1 .. Idkm : Typk) Global environment is updated on the fly. The calls to [interp_modast] should be interleaved with these env updates, otherwise some "with Definition" could be rejected. Returns a list of mbids and entries (in reversed order). This used to be a [List.concat (List.map ...)], but this should be more efficient and independent of [List.map] eval order. *) let intern_args params = let args, ctx = List.fold_left intern_arg ([], Univ.ContextSet.empty) params in List.rev args, ctx let start_module_core id args res = let mp = Global.start_module id in let params, ctx = intern_args args in let () = Global.push_context_set ctx in let env = Global.env () in let res_entry_o, subtyps, ctx' = match res with | Enforce (mte, base, kind, inl) -> let (mte, ctx) = Modintern.interp_module_ast env kind base mte in let env = Environ.push_context_set ctx env in (* We check immediately that mte is well-formed *) let state = ((Environ.universes env, Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let _, (_, cst), _ = Mod_typing.translate_modtype state vm_state env mp inl ([], mte) in let ctx = Univ.ContextSet.add_constraints cst ctx in Some (mte, inl), [], ctx | Check resl -> let typs, ctx = build_subtypes env mp params resl in None, typs, ctx in let () = Global.push_context_set ctx' in mp, res_entry_o, subtyps, params, Univ.ContextSet.union ctx ctx' let start_module export id args res = let fs = Summary.Interp.freeze_summaries () in let mp, res_entry_o, subtyps, _, _ = start_module_core id args res in openmod_info := { cur_typ = res_entry_o; cur_typs = subtyps }; let _ : object_prefix = Lib.Interp.start_module export id mp fs in mp let end_module_core id m_info objects fs = let {Lib.substobjs = substitute; keepobjs = keep; escapeobjs = escape; anticipateobjs = special; } = objects in (* For sealed modules, we use the substitutive objects of their signatures *) let sobjs0, keep = match m_info.cur_typ with | None -> ([], Objs substitute), keep | Some (mty, inline) -> InterpVisitor.get_module_sobjs false (Global.env()) inline mty, { keep_objects = [] } in let struc = current_struct () in let restype' = Option.map (fun (ty,inl) -> (([],ty),inl)) m_info.cur_typ in let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let _, (_, cst), _ = Mod_typing.finalize_module state vm_state (Global.env ()) (Global.current_modpath ()) (struc, current_modresolver ()) restype' in let () = Global.add_univ_constraints cst in let mp,mbids,resolver = Global.end_module fs id m_info.cur_typ in let sobjs = let (ms,objs) = sobjs0 in (mbids@ms,objs) in let () = check_subtypes mp m_info.cur_typs in (* We substitute objects if the module is sealed by a signature *) let sobjs = match m_info.cur_typ with | None -> sobjs | Some (mty, _) -> subst_sobjs (map_mp (get_module_path mty) mp resolver) sobjs in let node = ModuleObject (id,sobjs) in (* We add the keep objects, if any, and if this isn't a functor *) let keep = if not (CList.is_empty mbids) then [] else keep_objects id keep in (* NB: escape objects are added even for sealed modules, not sure if want *) let escape = escape_objects id escape in let objects = special@[node]@keep@escape in mp, objects let end_module () = let oldprefix,fs,objects = Lib.Interp.end_module () in let m_info = !openmod_info in let _olddp, id = pop_path oldprefix.obj_path in let mp,objects = end_module_core id m_info objects fs in let () = InterpVisitor.add_leaves objects in (* Name consistency check : kernel vs. library *) assert (ModPath.equal oldprefix.obj_mp mp); mp let get_functor_sobjs is_mod env inl (params,mexpr) = let (mbids, aobjs) = InterpVisitor.get_module_sobjs is_mod env inl mexpr in (List.map pi1 params @ mbids, aobjs) (* TODO cleanup push universes directly to global env *) let declare_module id args res mexpr_o = let fs = Summary.Interp.freeze_summaries () in (* We simulate the beginning of an interactive module, then we adds the module parameters to the global env. *) let mp, mty_entry_o, subs, params, ctx = start_module_core id args res in let env = Global.env () in let mexpr_entry_o, inl_expr, ctx' = match mexpr_o with | None -> None, default_inline_level (), Univ.ContextSet.empty | Some (mte, base, kind, inl) -> let (mte, ctx) = Modintern.interp_module_ast env kind base mte in Some mte, inl, ctx in let env = Environ.push_context_set ctx' env in let ctx = Univ.ContextSet.union ctx ctx' in let params = List.map (fun (mbid, _, mte, b) -> (mbid, mte, b)) params in let entry, inl_res = match mexpr_entry_o, mty_entry_o with | None, None -> assert false (* No body, no type ... *) | None, Some (typ, inl) -> MType (params, typ), inl | Some body, otyp -> MExpr (params, body, Option.map fst otyp), Option.cata snd (default_inline_level ()) otyp in let sobjs, mp0 = match entry with | MType (_,mte) | MExpr (_,_,Some mte) -> get_functor_sobjs false env inl_res (params,mte), get_module_path mte | MExpr (_,me,None) -> get_functor_sobjs true env inl_expr (params,me), get_module_path me in (* Undo the simulated interactive building of the module and declare the module as a whole *) Summary.Interp.unfreeze_summaries fs; let inl = match inl_expr with | None -> None | _ -> inl_res in let () = Global.push_context_set ctx in let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let _, (_, cst), _ = Mod_typing.translate_module state vm_state (Global.env ()) mp inl entry in let () = Global.add_univ_constraints cst in let mp_env,resolver = Global.add_module id entry inl in (* Name consistency check : kernel vs. library *) assert (ModPath.equal mp (mp_of_kn (Lib.make_kn id))); assert (ModPath.equal mp mp_env); let () = check_subtypes mp subs in let sobjs = subst_sobjs (map_mp mp0 mp resolver) sobjs in InterpVisitor.add_leaf (ModuleObject (id,sobjs)); mp end end (** {6 Module types : start, end, declare} *) module RawModTypeOps = struct module Synterp = struct let start_modtype_core id cur_mp args mtys = let mp = ModPath.MPdot(cur_mp, id) in let args = RawModOps.Synterp.intern_args args in let mbids = List.flatten @@ List.map (fun (mbidl,_) -> mbidl) args in let sub_mty_l = RawModOps.Synterp.build_subtypes mtys in mp, mbids, args, sub_mty_l let start_modtype id args mtys = let fs = Summary.Synterp.freeze_summaries () in let mp, mbids, args, sub_mty_l = start_modtype_core id (openmod_syntax_info ()).cur_mp args mtys in set_openmod_syntax_info { cur_mp = mp; cur_typ = None; cur_mbids = mbids }; let prefix = Lib.Synterp.start_modtype id mp fs in Nametab.(push_dir (Until 1) (prefix.obj_path) (GlobDirRef.DirOpenModtype prefix.obj_mp)); mp, args, sub_mty_l let end_modtype_core id mbids objects fs = let {Lib.substobjs = substitute; keepobjs = _; escapeobjs = escape; anticipateobjs = special; } = objects in Summary.Synterp.unfreeze_summaries fs; let modtypeobjs = (mbids, Objs substitute) in special@[ModuleTypeObject (id,modtypeobjs)]@(escape_objects id escape) let end_modtype () = let oldprefix,fs,objects = Lib.Synterp.end_modtype () in let _olddp, id = pop_path oldprefix.obj_path in let objects = end_modtype_core id (openmod_syntax_info ()).cur_mbids objects fs in SynterpVisitor.add_leaves objects; (openmod_syntax_info ()).cur_mp let declare_modtype id args mtys (mty,ann) = let fs = Summary.Synterp.freeze_summaries () in let inl = inl2intopt ann in (* We simulate the beginning of an interactive module, then we adds the module parameters to the global env. *) let mp, mbids, args, sub_mty_l = start_modtype_core id (openmod_syntax_info ()).cur_mp args mtys in let mte, base, kind = Modintern.intern_module_ast Modintern.ModType mty in let entry = mbids, mte in let sobjs = RawModOps.Synterp.get_functor_sobjs false inl entry in let subst = map_mp (get_module_path (snd entry)) mp (empty_delta_resolver mp) in let sobjs = subst_sobjs subst sobjs in (* Undo the simulated interactive building of the module type and declare the module type as a whole *) Summary.Synterp.unfreeze_summaries fs; ignore (SynterpVisitor.add_leaf (ModuleTypeObject (id,sobjs))); mp, args, (mte, base, kind, inl), sub_mty_l end module Interp = struct let openmodtype_info = Summary.ref ([] : module_type_body list) ~name:"MODTYPE-INFO" let start_modtype_core id args mtys = let mp = Global.start_modtype id in let params, params_ctx = RawModOps.Interp.intern_args args in let () = Global.push_context_set params_ctx in let env = Global.env () in let sub_mty_l, sub_mty_ctx = RawModOps.Interp.build_subtypes env mp params mtys in let () = Global.push_context_set sub_mty_ctx in mp, params, sub_mty_l, Univ.ContextSet.union params_ctx sub_mty_ctx let start_modtype id args mtys = let fs = Summary.Interp.freeze_summaries () in let mp, _, sub_mty_l, _ = start_modtype_core id args mtys in openmodtype_info := sub_mty_l; let prefix = Lib.Interp.start_modtype id mp fs in Nametab.(push_dir (Until 1) (prefix.obj_path) (GlobDirRef.DirOpenModtype mp)); mp let end_modtype_core id sub_mty_l objects fs = let {Lib.substobjs = substitute; keepobjs = _; escapeobjs = escape; anticipateobjs = special; } = objects in let mp, mbids = Global.end_modtype fs id in let () = RawModOps.Interp.check_subtypes_mt mp sub_mty_l in let modtypeobjs = (mbids, Objs substitute) in let objects = special@[ModuleTypeObject (id,modtypeobjs)]@(escape_objects id escape) in mp, objects let end_modtype () = let oldprefix,fs,objects = Lib.Interp.end_modtype () in let olddp, id = pop_path oldprefix.obj_path in let sub_mty_l = !openmodtype_info in let mp, objects = end_modtype_core id sub_mty_l objects fs in let () = InterpVisitor.add_leaves objects in (* Check name consistence : start_ vs. end_modtype, kernel vs. library *) assert (eq_full_path (Lib.prefix()).obj_path olddp); assert (ModPath.equal oldprefix.obj_mp mp); mp let declare_modtype id args mtys (mte,base,kind,inl) = let fs = Summary.Interp.freeze_summaries () in (* We simulate the beginning of an interactive module, then we adds the module parameters to the global env. *) let mp, params, sub_mty_l, ctx = start_modtype_core id args mtys in let env = Global.env () in let mte, mte_ctx = Modintern.interp_module_ast env kind base mte in let () = Global.push_context_set mte_ctx in let env = Global.env () in (* We check immediately that mte is well-formed *) let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let _, (_, mte_cst), _ = Mod_typing.translate_modtype state vm_state env mp inl ([], mte) in let () = Global.push_context_set (Univ.Level.Set.empty, mte_cst) in let params = List.map (fun (mbid, _, mte, b) -> (mbid, mte, b)) params in let entry = params, mte in let env = Global.env () in let sobjs = RawModOps.Interp.get_functor_sobjs false env inl entry in let subst = map_mp (get_module_path (snd entry)) mp (empty_delta_resolver mp) in let sobjs = subst_sobjs subst sobjs in (* Undo the simulated interactive building of the module type and declare the module type as a whole *) Summary.Interp.unfreeze_summaries fs; (* We enrich the global environment *) let () = Global.push_context_set ctx in let () = Global.push_context_set mte_ctx in let () = Global.push_context_set (Univ.Level.Set.empty, mte_cst) in let mp_env = Global.add_modtype id entry inl in (* Name consistency check : kernel vs. library *) assert (ModPath.equal mp_env mp); (* Subtyping checks *) let () = RawModOps.Interp.check_subtypes_mt mp sub_mty_l in InterpVisitor.add_leaf (ModuleTypeObject (id, sobjs)); mp end end (** {6 Include} *) module RawIncludeOps = struct exception NoIncludeSelf module Synterp = struct let rec include_subst mp mbids = match mbids with | [] -> empty_subst | mbid::mbids -> let subst = include_subst mp mbids in join (map_mbid mbid mp (empty_delta_resolver mp)) subst let declare_one_include_core cur_mp (me_ast,annot) = let me, base, kind = Modintern.intern_module_ast Modintern.ModAny me_ast in let is_mod = (kind == Modintern.Module) in let inl = inl2intopt annot in let mbids,aobjs = SynterpVisitor.get_module_sobjs is_mod () inl me in let subst_self = try if List.is_empty mbids then raise NoIncludeSelf; include_subst cur_mp mbids with NoIncludeSelf -> empty_subst in let base_mp = get_module_path me in (* We can use an empty delta resolver on syntax objects *) let subst = join subst_self (map_mp base_mp cur_mp (empty_delta_resolver cur_mp)) in let aobjs = subst_aobjs subst aobjs in (me, base, kind, inl), aobjs let declare_one_include (me_ast,annot) = let res, aobjs = declare_one_include_core (openmod_syntax_info ()).cur_mp (me_ast,annot) in SynterpVisitor.add_leaf (IncludeObject aobjs); res let declare_include me_asts = List.map declare_one_include me_asts end module Interp = struct let rec include_subst env mp reso mbids sign inline = match mbids with | [] -> empty_subst | mbid::mbids -> let farg_id, farg_b, fbody_b = Modops.destr_functor sign in let subst = include_subst env mp reso mbids fbody_b inline in let mp_delta = Modops.inline_delta_resolver env inline mp farg_id farg_b reso in join (map_mbid mbid mp mp_delta) subst let rec decompose_functor mpl typ = match mpl, typ with | [], _ -> typ | _::mpl, MoreFunctor(_,_,str) -> decompose_functor mpl str | _ -> user_err Pp.(str "Application of a functor with too much arguments.") let type_of_incl env is_mod = function | MEident mp -> type_of_mod mp env is_mod | MEapply _ as me -> let mp0, mp_l = InterpVisitor.get_applications me in decompose_functor mp_l (type_of_mod mp0 env is_mod) | MEwith _ -> raise NoIncludeSelf (** Implements [Include F] where [F] has parameters [mbids] to be instantiated by fields of the current "self" module, i.e. using subtyping, by the current module itself. *) let declare_one_include_core (me,base,kind,inl) = let env = Global.env() in let me, cst = Modintern.interp_module_ast env kind base me in let () = Global.push_context_set cst in let env = Global.env () in let is_mod = (kind == Modintern.Module) in let cur_mp = Global.current_modpath () in let mbids,aobjs = InterpVisitor.get_module_sobjs is_mod env inl me in let subst_self = try if List.is_empty mbids then raise NoIncludeSelf; let typ = type_of_incl env is_mod me in let reso = RawModOps.Interp.current_modresolver () in include_subst env cur_mp reso mbids typ inl with NoIncludeSelf -> empty_subst in let base_mp = get_module_path me in let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in let sign, (), resolver, (_, cst), _ = Mod_typing.translate_mse_include is_mod state vm_state (Global.env ()) (Global.current_modpath ()) inl me in let () = Global.add_univ_constraints cst in let () = assert (ModPath.equal cur_mp (Global.current_modpath ())) in (* Include Self support *) let mb = make_module_body (RawModOps.Interp.current_struct ()) (RawModOps.Interp.current_modresolver ()) [] in let rec compute_sign sign = match sign with | MoreFunctor(mbid,mtb,str) -> let state = ((Global.universes (), Univ.UnivConstraints.empty), Reductionops.inferred_universes) in (* Module subcomponents are already part of env at this point *) let env = Environ.shallow_add_module cur_mp mb (Global.env ()) in let (_, cst) = Subtyping.check_subtypes state env cur_mp (MPbound mbid) mtb in let () = Global.add_univ_constraints cst in let mpsup_delta = match mod_global_delta mb with | None -> assert false (* mb is guaranteed not to be a functor here *) | Some delta -> Modops.inline_delta_resolver (Global.env ()) inl cur_mp mbid mtb delta in let subst = Mod_subst.map_mbid mbid cur_mp mpsup_delta in compute_sign (Modops.subst_signature subst cur_mp str) | NoFunctor str -> () in let () = compute_sign sign in let resolver = Global.add_include me is_mod inl in let subst = join subst_self (map_mp base_mp cur_mp resolver) in subst_aobjs subst aobjs let declare_one_include (me,base,kind,inl) = let aobjs = declare_one_include_core (me,base,kind,inl) in InterpVisitor.add_leaf (IncludeObject aobjs) let declare_include me_asts = List.iter declare_one_include me_asts end end (** {6 Libraries} *) type library_name = DirPath.t (** A library object is made of some substitutive objects and some "keep" and "escape" objects. *) type library_objects = Libobject.t list * keep_objects * escape_objects module Synterp = struct let start_module export id args res = RawModOps.Synterp.start_module export id args res let end_module = RawModOps.Synterp.end_module (** Declare a module in terms of a list of module bodies, by including them. Typically used for `Module M := N <+ P`. *) let declare_module_includes id args res mexpr_l = let fs = Summary.Synterp.freeze_summaries () in let mp, res_entry_o, mbids, sign, args = RawModOps.Synterp.start_module_core id args res in let mod_info = { cur_mp = mp; cur_typ = res_entry_o; cur_mbids = mbids } in let includes = List.map_left (RawIncludeOps.Synterp.declare_one_include_core mp) mexpr_l in let bodies, incl_objs = List.split includes in let incl_objs = List.map (fun x -> IncludeObject x) incl_objs in let objects = { Lib.substobjs = incl_objs; keepobjs = { keep_objects = [] }; escapeobjs = { escape_objects = [] }; anticipateobjs = []; } in let mp, objects = RawModOps.Synterp.end_module_core id mod_info objects fs in SynterpVisitor.add_leaves objects; mp, args, bodies, sign (** Declare a module type in terms of a list of module bodies, by including them. Typically used for `Module Type M := N <+ P`. *) let declare_modtype_includes id args res mexpr_l = let fs = Summary.Synterp.freeze_summaries () in let mp, mbids, args, subtyps = RawModTypeOps.Synterp.start_modtype_core id (openmod_syntax_info ()).cur_mp args res in let includes = List.map_left (RawIncludeOps.Synterp.declare_one_include_core mp) mexpr_l in let bodies, incl_objs = List.split includes in let incl_objs = List.map (fun x -> IncludeObject x) incl_objs in let objects = { Lib.substobjs = incl_objs; keepobjs = { keep_objects = [] }; escapeobjs = { escape_objects = [] }; anticipateobjs = []; } in let objects = RawModTypeOps.Synterp.end_modtype_core id mbids objects fs in SynterpVisitor.add_leaves objects; mp, args, bodies, subtyps let declare_module id args mtys me_l = match me_l with | [] -> let mp, args, body, sign = RawModOps.Synterp.declare_module id args mtys None in assert (Option.is_empty body); mp, args, [], sign | [me] -> let mp, args, body, sign = RawModOps.Synterp.declare_module id args mtys (Some me) in mp, args, [Option.get body], sign | me_l -> declare_module_includes id args mtys me_l let start_modtype id args mtys = RawModTypeOps.Synterp.start_modtype id args mtys let end_modtype = RawModTypeOps.Synterp.end_modtype let declare_modtype id args mtys mty_l = match mty_l with | [] -> assert false | [mty] -> let mp, args, body, sign = RawModTypeOps.Synterp.declare_modtype id args mtys mty in mp, args, [body], sign | mty_l -> declare_modtype_includes id args mtys mty_l let declare_include = RawIncludeOps.Synterp.declare_include let register_library dir (objs:library_objects) = let mp = MPfile dir in let sp = path_of_file dir in let sobjs,keepobjs,escapeobjs = objs in SynterpVisitor.load_module 1 sp mp ([],Objs sobjs); SynterpVisitor.load_escape 2 sp mp escapeobjs; SynterpVisitor.load_keep 2 sp mp keepobjs let import_modules = SynterpVisitor.import_modules let import_module f ~export mp = import_modules ~export [f,mp] let close_section = SynterpVisitor.close_section end module Interp = struct let start_module = RawModOps.Interp.start_module let end_module = RawModOps.Interp.end_module (** Declare a module in terms of a list of module bodies, by including them. Typically used for `Module M := N <+ P`. *) let declare_module_includes id args res mexpr_l = let fs = Summary.Interp.freeze_summaries () in let mp, res_entry_o, subtyps, _, _ = RawModOps.Interp.start_module_core id args res in let mod_info = { cur_typ = res_entry_o; cur_typs = subtyps } in let incl_objs = List.map_left (fun x -> IncludeObject (RawIncludeOps.Interp.declare_one_include_core x)) mexpr_l in let objects = { Lib.substobjs = incl_objs; keepobjs = { keep_objects = [] }; escapeobjs = { escape_objects = [] }; anticipateobjs = []; } in let mp, objects = RawModOps.Interp.end_module_core id mod_info objects fs in InterpVisitor.add_leaves objects; mp (** Declare a module type in terms of a list of module bodies, by including them. Typically used for `Module Type M := N <+ P`. *) let declare_modtype_includes id args res mexpr_l = let fs = Summary.Interp.freeze_summaries () in let mp, _, subtyps, _ = RawModTypeOps.Interp.start_modtype_core id args res in let incl_objs = List.map_left (fun x -> IncludeObject (RawIncludeOps.Interp.declare_one_include_core x)) mexpr_l in let objects = { Lib.substobjs = incl_objs; keepobjs = { keep_objects = [] }; escapeobjs = { escape_objects = [] }; anticipateobjs = []; } in let mp, objects = RawModTypeOps.Interp.end_modtype_core id subtyps objects fs in InterpVisitor.add_leaves objects; mp let declare_module id args mtys me_l = match me_l with | [] -> RawModOps.Interp.declare_module id args mtys None | [me] -> RawModOps.Interp.declare_module id args mtys (Some me) | me_l -> declare_module_includes id args mtys me_l let start_modtype = RawModTypeOps.Interp.start_modtype let end_modtype = RawModTypeOps.Interp.end_modtype let declare_modtype id args mtys mty_l = match mty_l with | [] -> assert false | [mty] -> RawModTypeOps.Interp.declare_modtype id args mtys mty | mty_l -> declare_modtype_includes id args mtys mty_l let declare_include me_asts = if Lib.sections_are_opened () then user_err Pp.(str "Include is not allowed inside sections."); RawIncludeOps.Interp.declare_include me_asts let register_library dir cenv (objs:library_objects) digest vmtab = let mp = MPfile dir in let sp = path_of_file dir in let () = try (* If the library was loaded inside a module or section, the end_segment will replay the library object for non-kernel effects but the kernel did not forget the library. *) ignore(Global.lookup_module mp); with Not_found -> begin let mp' = Global.import cenv vmtab digest in if not (ModPath.equal mp mp') then anomaly (Pp.str "Unexpected disk module name.") end in let sobjs,keepobjs,escapeobjs = objs in InterpVisitor.load_module 1 sp mp ([],Objs sobjs); InterpVisitor.load_escape 1 sp mp escapeobjs; InterpVisitor.load_keep 1 sp mp keepobjs let import_modules = InterpVisitor.import_modules let import_module f ~export mp = import_modules ~export [f,mp] let close_section = InterpVisitor.close_section end let end_library_hook = ref [] let append_end_library_hook f = end_library_hook := f :: !end_library_hook let end_library_hook () = List.iter (fun f -> f ()) (List.rev !end_library_hook) let end_library ~output_native_objects dir = end_library_hook(); let { Lib.info; interp_objects = lib_stack; synterp_objects = lib_stack_syntax; } = Lib.end_compilation dir in let mp,cenv,vmlib,ast = Global.export ~output_native_objects dir in assert (ModPath.equal mp (MPfile dir)); let drop_anticipate {Lib.substobjs; keepobjs; escapeobjs; anticipateobjs=_} = (substobjs, keepobjs, escapeobjs) in cenv,(drop_anticipate lib_stack),(drop_anticipate lib_stack_syntax),vmlib,ast,info (** {6 Iterators} *) let iter_all_interp_segments f = let rec apply_obj prefix obj = match obj with | IncludeObject aobjs -> let objs = InterpVisitor.expand_aobjs aobjs in List.iter (apply_obj prefix) objs | _ -> f prefix obj in let rec subst_view (obj : exp_substituted_object) : Libobject.t = match obj with | KeepObject (_, o) | EscapeObject (_, o) -> Empty.abort o | (AtomicObject _ | ExportObject _ | ModuleObject _ | ModuleTypeObject _) as o -> o | IncludeObject aobjs -> let aobjs = aobjs.exp_algebraic_objects in IncludeObject (Objs (List.map subst_view aobjs)) in let apply_mod_obj _ modobjs = let prefix = modobjs.module_prefix in List.iter (fun obj -> apply_obj prefix (subst_view obj)) modobjs.module_substituted_objects; List.iter (fun obj -> apply_obj prefix obj) modobjs.module_keep_objects.keep_objects in let apply_nodes (node, os) = List.iter (fun o -> apply_obj (Lib.node_prefix node) o) os in ModPath.Map.iter apply_mod_obj (InterpVisitor.ModObjs.all ()); List.iter apply_nodes (Lib.contents ()) (** {6 Some types used to shorten declaremods.mli} *) type module_params = (lident list * (Constrexpr.module_ast * inline)) list type module_expr = (Modintern.module_struct_expr * ModPath.t * Modintern.module_kind * Entries.inline) type module_params_expr = (MBId.t list * module_expr) list (** {6 Debug} *) let debug_print_modtab () = InterpVisitor.debug_print_modtab () (** For printing modules, [process_module_binding] adds names of bound module (and its components) to Nametab. It also loads objects associated to it. *) let process_module_binding mbid me = let sp = Libnames.make_path DirPath.empty (MBId.to_id mbid) in let mp = MPbound mbid in let sobjs = InterpVisitor.get_module_sobjs false (Global.env()) (default_inline_level ()) me in let subst = map_mp (get_module_path me) mp (empty_delta_resolver mp) in let sobjs = subst_sobjs subst sobjs in SynterpVisitor.load_module 1 sp mp sobjs; InterpVisitor.load_module 1 sp mp sobjs let () = append_end_library_hook Profile_tactic.do_print_results_at_close rocq-9.2.0/vernac/declaremods.mli000066400000000000000000000132031516144147600167410ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* int option (** Kinds of modules *) type module_params = (lident list * (Constrexpr.module_ast * inline)) list type module_expr = (module_struct_expr * ModPath.t * module_kind * Entries.inline) type module_params_expr = (MBId.t list * module_expr) list (** {6 Libraries i.e. modules on disk } *) type library_name = DirPath.t type library_objects module Synterp : sig val declare_module : Id.t -> module_params -> (Constrexpr.module_ast * inline) module_signature -> (Constrexpr.module_ast * inline) list -> ModPath.t * module_params_expr * module_expr list * module_expr module_signature val start_module : Lib.export -> Id.t -> module_params -> (Constrexpr.module_ast * inline) module_signature -> ModPath.t * module_params_expr * module_expr module_signature val end_module : unit -> ModPath.t val declare_include : (Constrexpr.module_ast * inline) list -> module_expr list val declare_modtype : Id.t -> module_params -> (Constrexpr.module_ast * inline) list -> (Constrexpr.module_ast * inline) list -> ModPath.t * module_params_expr * module_expr list * module_expr list val start_modtype : Id.t -> module_params -> (Constrexpr.module_ast * inline) list -> ModPath.t * module_params_expr * module_expr list val end_modtype : unit -> ModPath.t val import_module : Libobject.open_filter -> export:Lib.export_flag -> ModPath.t -> unit val import_modules : export:Lib.export_flag -> (Libobject.open_filter * ModPath.t) list -> unit val register_library : library_name -> library_objects -> unit val close_section : unit -> unit end module Interp : sig (** [declare_module id fargs typ exprs] declares module [id], from functor arguments [fargs], with final type [typ]. [exprs] is usually of length 1 (Module definition with a concrete body), but it could also be empty ("Declare Module", with non-empty [typ]), or multiple (body of the shape M <+ N <+ ...). *) val declare_module : Id.t -> module_params_expr -> module_expr module_signature -> module_expr list -> ModPath.t val start_module : Lib.export -> Id.t -> module_params_expr -> module_expr module_signature -> ModPath.t val end_module : unit -> ModPath.t (** {6 Module types } *) (** [declare_modtype interp_modast id fargs typs exprs] Similar to [declare_module], except that the types could be multiple *) val declare_modtype : Id.t -> module_params_expr -> module_expr list -> module_expr list -> ModPath.t val start_modtype : Id.t -> module_params_expr -> module_expr list -> ModPath.t val end_modtype : unit -> ModPath.t val register_library : library_name -> Safe_typing.compiled_library -> library_objects -> Safe_typing.vodigest -> Vmlibrary.on_disk -> unit (** [import_module export mp] imports the module [mp]. It modifies Nametab and performs the [open_object] function for every object of the module. Raises [Not_found] when [mp] is unknown or when [mp] corresponds to a functor. If [export] is [true], the module is also opened every time the module containing it is. *) val import_module : Libobject.open_filter -> export:Lib.export_flag -> ModPath.t -> unit (** Same as [import_module] but for multiple modules, and more optimized than iterating [import_module]. *) val import_modules : export:Lib.export_flag -> (Libobject.open_filter * ModPath.t) list -> unit (** Include *) val declare_include : module_expr list -> unit val close_section : unit -> unit end val start_library : library_name -> unit val end_library : output_native_objects:bool -> library_name -> Safe_typing.compiled_library * library_objects * library_objects * Vmlibrary.compiled_library * Nativelib.native_library * Library_info.t (** append a function to be executed at end_library *) val append_end_library_hook : (unit -> unit) -> unit (** {6 ... } *) (** [iter_all_interp_segments] iterate over all segments, the modules' segments first and then the current segment. Modules are presented in an arbitrary order. The given function is applied to all leaves (together with their section path). Ignores synterp objects. *) val iter_all_interp_segments : (Libobject.object_prefix -> Libobject.t -> unit) -> unit val debug_print_modtab : unit -> Pp.t (** For printing modules, [process_module_binding] adds names of bound module (and its components) to Nametab. It also loads objects associated to it. It may raise a [Failure] when the bound module hasn't an atomic type. *) val process_module_binding : MBId.t -> (Constr.t * UVars.AbstractContext.t option) Declarations.module_alg_expr -> unit rocq-9.2.0/vernac/dune000066400000000000000000000015551516144147600146410ustar00rootroot00000000000000(library (name vernac) (synopsis "Rocq's Vernacular Language") (public_name rocq-runtime.vernac) (wrapped false) (modules_without_implementation vernacexpr) ; until ocaml/dune#4892 fixed ; (private_modules comProgramFixpoint egramcoq) (libraries tactics parsing findlib.dynload)) (deprecated_library_name (old_public_name coq-core.vernac) (new_public_name rocq-runtime.vernac)) (rule (targets g_proofs.ml) (deps (:mlg g_proofs.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) (rule (targets g_obligations.ml) (deps (:mlg g_obligations.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) (rule (targets g_vernac.ml) (deps (:mlg g_vernac.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) (rule (targets g_redexpr.ml) (deps (:mlg g_redexpr.mlg)) (action (chdir %{project_root} (run rocq pp-mlg %{deps})))) rocq-9.2.0/vernac/egramml.ml000066400000000000000000000117711516144147600157420ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 's grammar_prod_item type 'a ty_arg = ('a -> raw_generic_argument) type ('self, 'tr, _, 'r) ty_rule = | TyStop : ('self, Gramlib.Grammar.norec, 'r, 'r) ty_rule | TyNext : ('self, _, 'a, 'r) ty_rule * ('self, _, 'b) Symbol.t * 'b ty_arg option -> ('self, Gramlib.Grammar.mayrec, 'b -> 'a, 'r) ty_rule type ('self, 'r) any_ty_rule = | AnyTyRule : ('self, _, 'act, Loc.t -> 'r) ty_rule -> ('self, 'r) any_ty_rule let rec ty_rule_of_gram = function | [] -> AnyTyRule TyStop | GramTerminal s :: rem -> let AnyTyRule rem = ty_rule_of_gram rem in let tok = Procq.Symbol.token (CLexer.terminal s) in let r = TyNext (rem, tok, None) in AnyTyRule r | GramNonTerminal (_, (t, tok)) :: rem -> let AnyTyRule rem = ty_rule_of_gram rem in let inj = Some (fun obj -> Genarg.in_gen t obj) in let r = TyNext (rem, tok, inj) in AnyTyRule r let rec ty_erase : type s tr a r. (s, tr, a, r) ty_rule -> (s, tr, a, r) Procq.Rule.t = function | TyStop -> Procq.Rule.stop | TyNext (rem, tok, _) -> Procq.Rule.next (ty_erase rem) tok type 'r gen_eval = Loc.t -> raw_generic_argument list -> 'r let rec ty_eval : type s tr a. (s, tr, a, Loc.t -> s) ty_rule -> s gen_eval -> a = function | TyStop -> fun f loc -> f loc [] | TyNext (rem, tok, None) -> fun f _ -> ty_eval rem f | TyNext (rem, tok, Some inj) -> fun f x -> let f loc args = f loc (inj x :: args) in ty_eval rem f let make_rule f prod = let AnyTyRule ty_rule = ty_rule_of_gram (List.rev prod) in let symb = ty_erase ty_rule in let f loc l = f loc (List.rev l) in let act = ty_eval ty_rule f in Procq.Production.make symb act let rec proj_symbol : type a b c. (a, b, c) ty_user_symbol -> (a, b, c) genarg_type = function | TUentry a -> ExtraArg a | TUentryl (a,l) -> ExtraArg a | TUopt(o) -> OptArg (proj_symbol o) | TUlist1 l -> ListArg (proj_symbol l) | TUlist1sep (l,_) -> ListArg (proj_symbol l) | TUlist0 l -> ListArg (proj_symbol l) | TUlist0sep (l,_) -> ListArg (proj_symbol l) (** Vernac grammar extensions *) let vernac_exts = Hashtbl.create 211 let get_extend_vernac_rule s = snd (Hashtbl.find vernac_exts s) let declare_vernac_command_grammar ~allow_override s nt gl = let () = if not allow_override && Hashtbl.mem vernac_exts s then CErrors.anomaly Pp.(str "bad vernac extend: " ++ str s.ext_entry ++ str ", " ++ int s.ext_index) in let nt = Option.default Pvernac.Vernac_.command nt in Hashtbl.add vernac_exts s (nt, gl) type any_extend_statement = Extend : 'a Entry.t * 'a extend_statement -> any_extend_statement let extend_vernac_command_grammar s = let nt, gl = Hashtbl.find vernac_exts s in let mkact loc l = VernacSynterp (VernacExtend (s, l)) in let rules = [make_rule mkact gl] in if Procq.Entry.is_empty nt then (* Small hack to tolerate empty entries in VERNAC { ... } EXTEND *) Extend (nt, (Procq.Fresh (Gramlib.Gramext.First, [None, None, rules]))) else Extend (nt, (Procq.Reuse (None, rules))) let to_extend_rules (Extend (nt, r)) = [ExtendRule (nt,r)] let extend_vernac = Procq.create_grammar_command "VernacExtend" { gext_fun = (fun s st -> to_extend_rules @@ extend_vernac_command_grammar s, st); gext_eq = (==); (* FIXME *) } let extend_vernac_command_grammar ~undoable ~ignore_kw s = if undoable then Procq.extend_grammar_command ~ignore_kw extend_vernac s else let Extend (nt, r) = extend_vernac_command_grammar s in grammar_extend ~ignore_kw nt r let grammar_exts = Hashtbl.create 21 let declare_grammar_ext ~uid e = let () = if Hashtbl.mem grammar_exts uid then CErrors.anomaly Pp.(str "bad grammar extend uid: " ++ str uid) in Hashtbl.add grammar_exts uid e let extend_grammar = Procq.create_grammar_command "GrammarExtend" { gext_fun = (fun s st -> to_extend_rules @@ Hashtbl.find grammar_exts s, st); gext_eq = (==); (* FIXME *) } let grammar_extend ?plugin_uid ~ignore_kw nt r = match plugin_uid with | None -> Procq.grammar_extend ~ignore_kw nt r | Some (plugin,uid) -> let uid = plugin^":"^uid in declare_grammar_ext ~uid (Extend (nt, r)); Mltop.add_init_function plugin (fun () -> Procq.extend_grammar_command ~ignore_kw extend_grammar uid) rocq-9.2.0/vernac/egramml.mli000066400000000000000000000034011516144147600161020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* 's grammar_prod_item val declare_vernac_command_grammar : allow_override:bool -> extend_name -> vernac_expr Procq.Entry.t option -> vernac_expr grammar_prod_item list -> unit val extend_vernac_command_grammar : undoable:bool -> ignore_kw:bool -> extend_name -> unit val grammar_extend : ?plugin_uid:(string * string) -> ignore_kw:bool -> 'a Procq.Entry.t -> 'a Procq.extend_statement -> unit val get_extend_vernac_rule : extend_name -> vernac_expr grammar_prod_item list val proj_symbol : ('a, 'b, 'c) Extend.ty_user_symbol -> ('a, 'b, 'c) Genarg.genarg_type (** Utility function reused in Egramrocq : *) val make_rule : (Loc.t -> Genarg.raw_generic_argument list -> 'a) -> 'a grammar_prod_item list -> 'a Procq.Production.t rocq-9.2.0/vernac/egramrocq.ml000066400000000000000000000663711516144147600163040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let info = [], [] in ConstrEntryMap.add entry info levels, info let save_levels levels custom lev = ConstrEntryMap.add custom lev levels (* At a same level, LeftA takes precedence over RightA and NoneA *) (* In case, several associativity exists for a level, we make two levels, *) (* first LeftA, then RightA and NoneA together *) let admissible_assoc = function | Gramlib.Gramext.LeftA, Some (Gramlib.Gramext.RightA | Gramlib.Gramext.NonA) -> false | Gramlib.Gramext.RightA, Some Gramlib.Gramext.LeftA -> false | Gramlib.Gramext.BothA, _ | _, Some Gramlib.Gramext.BothA -> assert false | _ -> true let create_assoc = function | None -> Gramlib.Gramext.RightA | Some a -> a exception NotationLevelMismatch of entry_level * Gramlib.Gramext.g_assoc * Gramlib.Gramext.g_assoc let () = CErrors.register_handler (function | NotationLevelMismatch (p, current, expected) -> Some Pp.(str "Level " ++ int p ++ str " is already declared to have " ++ Gramlib.Gramext.pr_assoc current ++ str " while it is now expected to have " ++ Gramlib.Gramext.pr_assoc expected ++ str ".") | _ -> None) let error_level_assoc p current expected = raise @@ NotationLevelMismatch (p, current, expected) type position = NewFirst | NewAfter of int | ReuseFirst | ReuseLevel of int let create_pos = function | None -> NewFirst | Some lev -> NewAfter lev let find_position_gen current ensure assoc lev = match lev with | None -> current, (ReuseFirst, None, None) | Some n -> let rec add_level previous = function | (p,_,_ as pa)::l when p > n -> let updated, res = add_level (Some p) l in pa :: updated, res | (p,a,empty)::l when Int.equal p n -> if empty then (* XXX we ignore preexisting associativity for empty levels, is that what we want? *) let a' = create_assoc assoc in let updated = (p,a',false)::l in updated, (ReuseLevel n, None, None) else if admissible_assoc (a,assoc) then raise_notrace Exit else error_level_assoc p a (Option.get assoc) | l -> let assoc = create_assoc assoc in let updated = (n,assoc,ensure)::l in updated, (create_pos previous, Some assoc, Some (constr_level n)) in try add_level None current with (* Nothing has changed *) Exit -> (* Just inherit the existing associativity and name (None) *) current, (ReuseLevel n, None, None) let rec list_mem_assoc_triple x = function | [] -> false | (a,b,c) :: l -> Int.equal a x || list_mem_assoc_triple x l let register_empty_levels accu forpat levels = let rec filter accu = function | [] -> ([], accu) | (where,n) :: rem -> let rem, accu = filter accu rem in let accu, (clev, plev) = find_levels accu where in let levels = if forpat then plev else clev in if not (list_mem_assoc_triple n levels) then let nlev, ans = find_position_gen levels true None (Some n) in let nlev = if forpat then (clev, nlev) else (nlev, plev) in (where, ans) :: rem, save_levels accu where nlev else rem, accu in let (l,accu) = filter accu levels in List.rev l, accu let find_position accu custom forpat assoc level = let accu, (clev, plev) = find_levels accu custom in let levels = if forpat then plev else clev in let nlev, ans = find_position_gen levels false assoc level in let nlev = if forpat then (clev, nlev) else (nlev, plev) in (ans, save_levels accu custom nlev) (**************************************************************************) (* * --- Note on the mapping of grammar productions to camlp5 actions --- * * Translation of environments: a production * [ nt1(x1) ... nti(xi) ] -> act(x1..xi) * is written (with camlp5 conventions): * (fun vi -> .... (fun v1 -> act(v1 .. vi) )..) * where v1..vi are the values generated by non-terminals nt1..nti. * Since the actions are executed by substituting an environment, * the make_*_action family build the following closure: * * ((fun env -> * (fun vi -> * (fun env -> ... * * (fun v1 -> * (fun env -> gram_action .. env act) * ((x1,v1)::env)) * ...) * ((xi,vi)::env))) * []) *) (**********************************************************************) (** Declare Notations grammar rules *) (**********************************************************************) (* Binding constr entry keys to entries *) (* Camlp5 levels do not treat NonA: use RightA with a NEXT on the left *) let camlp5_assoc = let open Gramlib.Gramext in function | Some NonA | Some RightA -> RightA | None | Some LeftA -> LeftA | Some BothA -> assert false let assoc_eq al ar = let open Gramlib.Gramext in match al, ar with | NonA, NonA | RightA, RightA | LeftA, LeftA -> true | BothA, _ | _, BothA -> assert false | _, _ -> false (** [adjust_level assoc fromlev prod] where [assoc] and [fromlev] are the name and associativity of the level where to add the rule; the meaning of the result is DefaultLevel = entry name NextLevel = NEXT NumLevel n = constr LEVEL n *) let adjust_level custom assoc {notation_entry = custom'; notation_level = fromlev} p = let open Gramlib.Gramext in match p with (* If a level in a different grammar, no other choice than denoting it by absolute level *) | (NumLevel n,_) when not (notation_entry_eq custom custom') -> NumLevel n (* If a default level in a different grammar, the entry name is ok *) | (DefaultLevel,InternalProd) -> if notation_entry_eq custom InConstrEntry then NumLevel 200 else DefaultLevel | (DefaultLevel,BorderProd _) when not (notation_entry_eq custom custom') -> if notation_entry_eq custom InConstrEntry then NumLevel 200 else DefaultLevel (* Associativity is None means force the level *) | (NumLevel n,BorderProd (_,None)) -> NumLevel n | (DefaultLevel,BorderProd (_,None)) -> assert false (* Compute production name on the right side *) (* If NonA or LeftA on the right-hand side, set to NEXT *) | ((NumLevel _ | DefaultLevel),BorderProd (Right,Some (NonA|LeftA))) -> NextLevel (* If RightA on the right-hand side, set to the explicit (current) level *) | (NumLevel n,BorderProd (Right,Some RightA)) -> NumLevel n | (DefaultLevel,BorderProd (Right,Some RightA)) -> NumLevel fromlev (* Compute production name on the left side *) (* If NonA on the left-hand side, adopt the current assoc ?? *) | ((NumLevel _ | DefaultLevel),BorderProd (Left,Some NonA)) -> DefaultLevel (* If the expected assoc is the current one, set to SELF *) | ((NumLevel _ | DefaultLevel),BorderProd (Left,Some a)) when assoc_eq a (camlp5_assoc assoc) -> DefaultLevel (* Otherwise, force the level, n or n-1, according to expected assoc *) | (NumLevel n,BorderProd (Left,Some LeftA)) -> NumLevel n | ((NumLevel _ | DefaultLevel),BorderProd (Left,Some _)) -> NextLevel (* None means NEXT *) | (NextLevel,_) -> assert (notation_entry_eq custom custom'); NextLevel (* Compute production name elsewhere *) | (NumLevel n,InternalProd) -> if fromlev = n + 1 then NextLevel else NumLevel n | (_,BorderProd (_,Some BothA)) -> assert false type _ target = | ForConstr : constr_expr target | ForPattern : cases_pattern_expr target type prod_info = production_level * production_position type (_, _) entry = | TTIdent : ('self, lident) entry | TTName : ('self, lname) entry | TTGlobal : ('r, qualid) entry | TTBigint : ('r, string) entry | TTBinder : bool -> ('self, kinded_cases_pattern_expr) entry | TTConstr : notation_entry * prod_info * 'r target -> ('r, 'r) entry | TTConstrList : notation_entry * prod_info * (bool * string) list * 'r target -> ('r, 'r list) entry | TTPattern : int -> ('self, cases_pattern_expr) entry | TTOpenBinderList : ('self, local_binder_expr list) entry | TTClosedBinderListPure : (bool * string) list -> ('self, local_binder_expr list list) entry | TTClosedBinderListOther : ('self, 'a) entry * (bool * string) list -> ('self, 'a list) entry type _ any_entry = TTAny : ('s, 'r) entry -> 's any_entry let constr_custom_map : Constrexpr.constr_expr Entry.t CustomName.Map.t GramState.field = GramState.field "constr_custom_map" let pattern_custom_map : Constrexpr.cases_pattern_expr Entry.t CustomName.Map.t GramState.field = GramState.field "pattern_custom_map" let make_custom_interp field prefix = { eext_fun = (fun kn e state -> let map = Option.default CustomName.Map.empty (GramState.get state field) in let map = CustomName.Map.add kn e map in GramState.set state field map); eext_name = (fun kn -> prefix^CustomName.to_string kn); eext_eq = CustomName.equal; } let constr_custom_entry : (CustomName.t, Constrexpr.constr_expr) entry_command = create_entry_command "constr" (make_custom_interp constr_custom_map "custom:") let pattern_custom_entry : (CustomName.t, Constrexpr.cases_pattern_expr) entry_command = create_entry_command "pattern" (make_custom_interp pattern_custom_map "pattern:") let create_custom_entry s = let () = extend_entry_command constr_custom_entry s in let () = extend_entry_command pattern_custom_entry s in () let find_custom_entry s = let state = gramstate() in let find_aux field = match GramState.get state field with | None -> raise Not_found | Some m -> CustomName.Map.find s m in try (find_aux constr_custom_map, find_aux pattern_custom_map) with Not_found -> anomaly Pp.(str "Undeclared custom entry: " ++ CustomName.print s ++ str ".") (** This computes the name of the level where to add a new rule *) let interp_constr_entry_key : type r. _ -> r target -> r Entry.t * int option = fun {notation_entry = custom; notation_level = level} forpat -> match custom with | InCustomEntry s -> (let (entry_for_constr, entry_for_patttern) = find_custom_entry s in match forpat with | ForConstr -> entry_for_constr, Some level | ForPattern -> entry_for_patttern, Some level) | InConstrEntry -> match forpat with | ForConstr -> if level = 200 then Constr.binder_constr, None else Constr.term, Some level | ForPattern -> Constr.pattern, Some level let target_entry : type s. notation_entry -> s target -> s Entry.t = function | InConstrEntry -> (function | ForConstr -> Constr.term | ForPattern -> Constr.pattern) | InCustomEntry s -> let (entry_for_constr, entry_for_patttern) = find_custom_entry s in function | ForConstr -> entry_for_constr | ForPattern -> entry_for_patttern let is_self custom {notation_entry = custom'; notation_level = fromlev} e = notation_entry_eq custom custom' && match e with | (NumLevel n, BorderProd (Right, _ (* Some(NonA|LeftA) *))) -> false | (NumLevel n, BorderProd (Left, _)) -> Int.equal fromlev n | _ -> false let is_binder_level custom {notation_entry = custom'; notation_level = fromlev} e = match e with | (NumLevel 200, (BorderProd (Right, _) | InternalProd)) -> custom = InConstrEntry && custom' = InConstrEntry && fromlev = 200 | _ -> false let make_pattern (keyword,s) = if keyword then TPattern (Tok.PKEYWORD s) else match NumTok.Unsigned.parse_string s with | Some n -> TPattern (Tok.PNUMBER (Some n)) | None -> match String.unquote_coq_string s with | Some s -> TPattern (Tok.PSTRING (Some s)) | None -> TPattern (Tok.PIDENT (Some s)) let make_sep_rules tkl = Procq.Symbol.tokens (List.map make_pattern tkl) type ('s, 'a) mayrec_symbol = | MayRecNo : ('s, Gramlib.Grammar.norec, 'a) Symbol.t -> ('s, 'a) mayrec_symbol | MayRecMay : ('s, Gramlib.Grammar.mayrec, 'a) Symbol.t -> ('s, 'a) mayrec_symbol let symbol_of_target : type s. _ -> _ -> _ -> _ -> s target -> (s, s) mayrec_symbol = fun custom p assoc from forpat -> if is_binder_level custom from p then (* Prevent self *) MayRecNo (Procq.Symbol.nterml (target_entry custom forpat) "200") else if is_self custom from p then MayRecMay Procq.Symbol.self else let g = target_entry custom forpat in let lev = adjust_level custom assoc from p in begin match lev with | DefaultLevel -> MayRecNo (Procq.Symbol.nterm g) | NextLevel -> MayRecMay Procq.Symbol.next | NumLevel lev -> MayRecNo (Procq.Symbol.nterml g (string_of_int lev)) end let rec symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) mayrec_symbol = fun assoc from typ -> match typ with | TTConstr (s, p, forpat) -> symbol_of_target s p assoc from forpat | TTConstrList (s, typ', [], forpat) -> begin match symbol_of_target s typ' assoc from forpat with | MayRecNo s -> MayRecNo (Procq.Symbol.list1 s) | MayRecMay s -> MayRecMay (Procq.Symbol.list1 s) end | TTConstrList (s, typ', tkl, forpat) -> begin match symbol_of_target s typ' assoc from forpat with | MayRecNo s -> MayRecNo (Procq.Symbol.list1sep s (make_sep_rules tkl)) | MayRecMay s -> MayRecMay (Procq.Symbol.list1sep s (make_sep_rules tkl)) end | TTPattern p -> MayRecNo (Procq.Symbol.nterml Constr.pattern (string_of_int p)) | TTOpenBinderList -> MayRecNo (Procq.Symbol.nterm Constr.open_binders) | TTClosedBinderListPure [] -> MayRecNo (Procq.Symbol.list1 (Procq.Symbol.nterm Constr.binder)) | TTClosedBinderListPure tkl -> MayRecNo (Procq.Symbol.list1sep (Procq.Symbol.nterm Constr.binder) (make_sep_rules tkl)) | TTClosedBinderListOther (typ,[]) -> begin match symbol_of_entry assoc from typ with | MayRecNo s -> MayRecNo (Procq.Symbol.list1 s) | MayRecMay s -> MayRecMay (Procq.Symbol.list1 s) end | TTClosedBinderListOther (typ,tkl) -> begin match symbol_of_entry assoc from typ with | MayRecNo s -> MayRecNo (Procq.Symbol.list1sep s (make_sep_rules tkl)) | MayRecMay s -> MayRecMay (Procq.Symbol.list1sep s (make_sep_rules tkl)) end | TTIdent -> MayRecNo (Procq.Symbol.nterm Prim.identref) | TTName -> MayRecNo (Procq.Symbol.nterm Prim.name) | TTBinder true -> MayRecNo (Procq.Symbol.nterm Constr.one_open_binder) | TTBinder false -> MayRecNo (Procq.Symbol.nterm Constr.one_closed_binder) | TTBigint -> MayRecNo (Procq.Symbol.nterm Prim.bignat) | TTGlobal -> MayRecNo (Procq.Symbol.nterm Constr.global) let rec interp_entry forpat e = match e with | ETProdIdent -> TTAny TTIdent | ETProdName -> TTAny TTName | ETProdGlobal -> TTAny TTGlobal | ETProdBigint -> TTAny TTBigint | ETProdOneBinder o -> TTAny (TTBinder o) | ETProdConstr (s,p) -> TTAny (TTConstr (s, p, forpat)) | ETProdPattern p -> TTAny (TTPattern p) | ETProdConstrList (s, p, tkl) -> TTAny (TTConstrList (s, p, tkl, forpat)) | ETProdBinderList ETBinderOpen -> TTAny TTOpenBinderList | ETProdBinderList (ETBinderClosed (None, tkl)) -> TTAny (TTClosedBinderListPure tkl) | ETProdBinderList (ETBinderClosed (Some e, tkl)) -> let TTAny e = interp_entry forpat e in TTAny (TTClosedBinderListOther (e, tkl)) let cases_pattern_expr_of_id { CAst.loc; v = id } = CAst.make ?loc @@ CPatAtom (Some (qualid_of_ident ?loc id)) let cases_pattern_expr_of_name { CAst.loc; v = na } = CAst.make ?loc @@ match na with | Anonymous -> CPatAtom None | Name id -> CPatAtom (Some (qualid_of_ident ?loc id)) type 'r env = { constrs : 'r list; constrlists : 'r list list; binders : kinded_cases_pattern_expr list; binderlists : local_binder_expr list list; } let push_constr subst v = { subst with constrs = v :: subst.constrs } let push_item : type s r. s target -> (s, r) entry -> s env -> r -> s env = fun forpat e subst v -> match e with | TTConstr _ -> push_constr subst v | TTIdent -> { subst with binders = (cases_pattern_expr_of_id v, Glob_term.Explicit) :: subst.binders } | TTName -> { subst with binders = (cases_pattern_expr_of_name v, Glob_term.Explicit) :: subst.binders } | TTPattern _ -> { subst with binders = (v, Glob_term.Explicit) :: subst.binders } | TTBinder o -> { subst with binders = v :: subst.binders } | TTOpenBinderList -> { subst with binderlists = v :: subst.binderlists } | TTClosedBinderListPure _ -> { subst with binderlists = List.flatten v :: subst.binderlists } | TTClosedBinderListOther (TTIdent, _) -> { subst with binderlists = List.map (fun a -> CLocalPattern (cases_pattern_expr_of_id a)) v :: subst.binderlists } | TTClosedBinderListOther (TTName, _) -> { subst with binderlists = List.map (fun a -> CLocalPattern (cases_pattern_expr_of_name a)) v :: subst.binderlists } | TTClosedBinderListOther (TTPattern _, _) -> { subst with binderlists = List.map (fun a -> CLocalPattern a) v :: subst.binderlists } | TTClosedBinderListOther _ -> user_err (Pp.str "Invalid binder list entry.") | TTBigint -> begin match forpat with | ForConstr -> push_constr subst (CAst.make @@ CPrim (Number (NumTok.Signed.of_int_string v))) | ForPattern -> push_constr subst (CAst.make @@ CPatPrim (Number (NumTok.Signed.of_int_string v))) end | TTGlobal -> begin match forpat with | ForConstr -> push_constr subst (CAst.make @@ CRef (v, None)) | ForPattern -> push_constr subst (CAst.make @@ CPatAtom (Some v)) end | TTConstrList _ -> { subst with constrlists = v :: subst.constrlists } type (_, _) ty_symbol = | TyTerm : 'a Tok.p -> ('s, 'a) ty_symbol | TyNonTerm : 's target * ('s, 'a) entry * ('s, 'a) mayrec_symbol * bool -> ('s, 'a) ty_symbol type ('self, _, 'r) ty_rule = | TyStop : ('self, 'r, 'r) ty_rule | TyNext : ('self, 'a, 'r) ty_rule * ('self, 'b) ty_symbol -> ('self, 'b -> 'a, 'r) ty_rule | TyMark : int * bool * int * ('self, 'a, 'r) ty_rule -> ('self, 'a, 'r) ty_rule type 'r gen_eval = Loc.t -> 'r env -> 'r let rec ty_eval : type s a. (s, a, Loc.t -> s) ty_rule -> s gen_eval -> s env -> a = function | TyStop -> fun f env loc -> f loc env | TyNext (rem, TyTerm _) -> fun f env _ -> ty_eval rem f env | TyNext (rem, TyNonTerm (_, _, _, false)) -> fun f env _ -> ty_eval rem f env | TyNext (rem, TyNonTerm (forpat, e, _, true)) -> fun f env v -> ty_eval rem f (push_item forpat e env v) | TyMark (n, b, p, rem) -> fun f env -> let heads, constrs = List.chop n env.constrs in let constrlists, constrs = if b then (* We rearrange constrs = c1..cn rem and constrlists = [d1..dr e1..ep] rem' into constrs = e1..ep rem and constrlists [c1..cn d1..dr] rem' *) let constrlist = List.hd env.constrlists in let constrlist, tail = List.chop (List.length constrlist - p) constrlist in (heads @ constrlist) :: List.tl env.constrlists, tail @ constrs else (* We rearrange constrs = c1..cn e1..ep rem into constrs = e1..ep rem and add a constr list [c1..cn] *) let constrlist, tail = List.chop (n - p) heads in constrlist :: env.constrlists, tail @ constrs in ty_eval rem f { env with constrs; constrlists; } type ('s, 'a, 'r) mayrec_rule = | MayRecRNo : ('s, Gramlib.Grammar.norec, 'a, 'r) Rule.t -> ('s, 'a, 'r) mayrec_rule | MayRecRMay : ('s, Gramlib.Grammar.mayrec, 'a, 'r) Rule.t -> ('s, 'a, 'r) mayrec_rule let rec ty_erase : type s a r. (s, a, r) ty_rule -> (s, a, r) mayrec_rule = function | TyStop -> MayRecRNo Rule.stop | TyMark (_, _, _, r) -> ty_erase r | TyNext (rem, TyTerm tok) -> begin match ty_erase rem with | MayRecRNo rem -> MayRecRMay (Rule.next rem (Symbol.token tok)) | MayRecRMay rem -> MayRecRMay (Rule.next rem (Symbol.token tok)) end | TyNext (rem, TyNonTerm (_, _, s, _)) -> begin match ty_erase rem, s with | MayRecRNo rem, MayRecNo s -> MayRecRMay (Rule.next rem s) | MayRecRNo rem, MayRecMay s -> MayRecRMay (Rule.next rem s) | MayRecRMay rem, MayRecNo s -> MayRecRMay (Rule.next rem s) | MayRecRMay rem, MayRecMay s -> MayRecRMay (Rule.next rem s) end type ('self, 'r) any_ty_rule = | AnyTyRule : ('self, 'act, Loc.t -> 'r) ty_rule -> ('self, 'r) any_ty_rule let make_ty_rule assoc from forpat prods = let rec make_ty_rule = function | [] -> AnyTyRule TyStop | GramConstrTerminal (kw,s) :: rem -> let AnyTyRule r = make_ty_rule rem in let TPattern tk = make_pattern (kw,s) in AnyTyRule (TyNext (r, TyTerm tk)) | GramConstrNonTerminal (e, var) :: rem -> let AnyTyRule r = make_ty_rule rem in let TTAny e = interp_entry forpat e in let s = symbol_of_entry assoc from e in let bind = match var with None -> false | Some _ -> true in AnyTyRule (TyNext (r, TyNonTerm (forpat, e, s, bind))) | GramConstrListMark (n, b, p) :: rem -> let AnyTyRule r = make_ty_rule rem in AnyTyRule (TyMark (n, b, p, r)) in make_ty_rule (List.rev prods) let target_to_bool : type r. r target -> bool = function | ForConstr -> false | ForPattern -> true let prepare_empty_levels forpat (where,(pos,p4assoc,name)) = let empty = match pos with | ReuseFirst -> Procq.Reuse (None, []) | ReuseLevel n -> Procq.Reuse (Some (constr_level n), []) | NewFirst -> Procq.Fresh (Gramlib.Gramext.First, [(name, p4assoc, [])]) | NewAfter n -> Procq.Fresh (Gramlib.Gramext.After (constr_level n), [(name, p4assoc, [])]) in ExtendRule (target_entry where forpat, empty) let different_levels (custom,opt_level) (custom',string_level) = match opt_level with | None -> true | Some level -> not (notation_entry_eq custom custom') || level <> int_of_string string_level let rec pure_sublevels' assoc from forpat level = function | [] -> [] | GramConstrNonTerminal (e,_) :: rem -> let rem = pure_sublevels' assoc from forpat level rem in let push where p rem = match symbol_of_target where p assoc from forpat with | MayRecNo sym -> (match Procq.level_of_nonterm sym with | None -> rem | Some i -> if different_levels (from.notation_entry,level) (where,i) then (where,int_of_string i) :: rem else rem) | _ -> rem in (match e with | ETProdPattern i -> push InConstrEntry (NumLevel i,InternalProd) rem | ETProdConstr (s,p) -> push s p rem | _ -> rem) | (GramConstrTerminal _ | GramConstrListMark _) :: rem -> pure_sublevels' assoc from forpat level rem let make_act : type r. r target -> _ -> r gen_eval = function | ForConstr -> fun notation loc env -> let env = (env.constrs, env.constrlists, env.binders, env.binderlists) in CAst.make ~loc @@ CNotation (None, notation, env) | ForPattern -> fun notation loc env -> let env = (env.constrs, env.constrlists, env.binders) in CAst.make ~loc @@ CPatNotation (None, notation, env, []) let extend_constr state forpat ng = let {notation_entry = custom; notation_level = _} as fromlev,_ = ng.notgram_level in let assoc = ng.notgram_assoc in let (entry, level) = interp_constr_entry_key fromlev forpat in let fold (accu, state) pt = let AnyTyRule r = make_ty_rule assoc fromlev forpat pt in let pure_sublevels = pure_sublevels' assoc fromlev forpat level pt in let isforpat = target_to_bool forpat in let needed_levels, state = register_empty_levels state isforpat pure_sublevels in let (pos,p4assoc,name), state = find_position state custom isforpat assoc level in let empty_rules = List.map (prepare_empty_levels forpat) needed_levels in let empty = { constrs = []; constrlists = []; binders = []; binderlists = [] } in let act = ty_eval r (make_act forpat ng.notgram_notation) empty in let rule = let r = match ty_erase r with | MayRecRNo symbs -> Procq.Production.make symbs act | MayRecRMay symbs -> Procq.Production.make symbs act in let rule = name, p4assoc, [r] in match pos with | NewFirst -> Procq.Fresh (Gramlib.Gramext.First, [rule]) | NewAfter n -> Procq.Fresh (Gramlib.Gramext.After (constr_level n), [rule]) | ReuseFirst -> Procq.Reuse (None, [r]) | ReuseLevel n -> Procq.Reuse (Some (constr_level n), [r]) in let r = ExtendRule (entry, rule) in (accu @ empty_rules @ [r], state) in List.fold_left fold ([], state) ng.notgram_prods let constr_levels = GramState.field "constr_levels" let is_disjunctive_pattern_rule ng = String.is_sub "( _ | " (snd ng.notgram_notation) 0 let warn_disj_pattern_notation = let open Pp in let pp ng = str "Use of " ++ Notation.pr_notation ng.notgram_notation ++ str " Notation is deprecated as it is inconsistent with pattern syntax." in CWarnings.create ~name:"disj-pattern-notation" ~category:CWarnings.CoreCategories.syntax ~default:CWarnings.Disabled pp let extend_constr_notation ng state = let levels = match GramState.get state constr_levels with | None -> default_levels | Some lev -> lev in (* Add the notation in constr *) let (r, levels) = extend_constr levels ForConstr ng in (* Add the notation in cases_pattern, unless it would disrupt *) (* parsing nested disjunctive patterns. *) let (r', levels) = if is_disjunctive_pattern_rule ng then begin warn_disj_pattern_notation ng; ([], levels) end else extend_constr levels ForPattern ng in let state = GramState.set state constr_levels levels in (r @ r', state) let constr_grammar : one_notation_grammar grammar_command = create_grammar_command "Notation" { gext_fun = extend_constr_notation; gext_eq = (==) (* FIXME *) } let extend_constr_grammar ntn = extend_grammar_command ~ignore_kw:false constr_grammar ntn rocq-9.2.0/vernac/egramrocq.mli000066400000000000000000000023551516144147600164450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit (** Add a term notation rule to the parsing system. *) val find_custom_entry : Globnames.CustomName.t -> Constrexpr.constr_expr Procq.Entry.t * Constrexpr.cases_pattern_expr Procq.Entry.t val create_custom_entry : Globnames.CustomName.t -> unit (** Add the entry to the grammar. *) rocq-9.2.0/vernac/future.ml000066400000000000000000000136001516144147600156210ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.strbrk("The value you are asking for ("^name^") is not ready yet. "^ "Please wait or pass "^ "the \"-async-proofs off\" option to Rocqide to disable "^ "asynchronous script processing and don't pass \"-vio\" to "^ "rocq compile.")) let not_here_msg = ref (fun name -> Pp.strbrk("The value you are asking for ("^name^") is not available "^ "in this process. If you really need this, pass "^ "the \"-async-proofs off\" option to Rocqide to disable "^ "asynchronous script processing and don't pass \"-vio\" to "^ "rocq compile.")) exception NotReady of string exception NotHere of string let _ = CErrors.register_handler (function | NotReady name -> Some (!not_ready_msg name) | NotHere name -> Some (!not_here_msg name) | _ -> None) type fix_exn = Stateid.exn_info option let eval_fix_exn f (e, info) = match f with | None -> (e, info) | Some { Stateid.id; valid } -> match Stateid.get info with | Some _ -> (e, info) | None -> let loc = Loc.get_loc info in let msg = CErrors.iprint (e, info) in let qf = Result.value ~default:[] (Quickfix.from_exception e) in let () = Feedback.(feedback ~id (Message (Error, loc, qf, msg))) in (e, Stateid.add info ~valid id) module UUID = struct type t = int let invalid = 0 let fresh = let count = ref invalid in fun () -> incr count; !count let compare = compare let equal = (==) end module UUIDMap = Map.Make(UUID) module UUIDSet = Set.Make(UUID) type 'a assignment = [ `Val of 'a | `Exn of Exninfo.iexn | `Comp of (unit -> 'a)] (* Val is not necessarily a final state, so the computation restarts from the state stocked into Val *) and 'a comp = | Delegated of (Mutex.t * Condition.t) option | Closure of (unit -> 'a) | Val of 'a | Exn of Exninfo.iexn (* Invariant: this exception is always "fixed" as in fix_exn *) and 'a computation = | Ongoing of string * (UUID.t * fix_exn * 'a comp ref) CEphemeron.key let unnamed = "unnamed" let create ?(name=unnamed) ?(uuid=UUID.fresh ()) ~fix_exn x = Ongoing (name, CEphemeron.create (uuid, fix_exn, ref x)) let get x = match x with | Ongoing (name, x) -> try let uuid, fix, c = CEphemeron.get x in name, uuid, fix, c with CEphemeron.InvalidKey -> name, UUID.invalid, None, ref (Exn (NotHere name, Exninfo.null)) type 'a value = [ `Val of 'a | `Exn of Exninfo.iexn ] let is_over kx = let _, _, _, x = get kx in match !x with | Val _ | Exn _ -> true | Closure _ | Delegated _ -> false let is_exn kx = let _, _, _, x = get kx in match !x with | Exn _ -> true | Val _ | Closure _ | Delegated _ -> false let peek_val kx = let _, _, _, x = get kx in match !x with | Val v -> Some v | Exn _ | Closure _ | Delegated _ -> None let uuid kx = let _, id, _, _ = get kx in id let from_val v = create ~fix_exn:None (Val v) let create_delegate ?(blocking=true) ~name fix_exn = let sync = if blocking then Some (Mutex.create (), Condition.create ()) else None in let ck = create ~name ~fix_exn (Delegated sync) in let assignment = fun v -> let _, _, fix_exn, c = get ck in let sync = match !c with Delegated s -> s | _ -> assert false in begin match v with | `Val v -> c := Val v | `Exn e -> c := Exn (eval_fix_exn fix_exn e) | `Comp f -> c := Closure f end; let iter (lock, cond) = CThread.with_lock lock ~scope:(fun () -> Condition.broadcast cond) in Option.iter iter sync in ck, assignment (* TODO: get rid of try/catch to be stackless *) let rec compute ck : 'a value = let name, _, fix_exn, c = get ck in match !c with | Val x -> `Val x | Exn (e, info) -> `Exn (e, info) | Delegated None -> raise (NotReady name) | Delegated (Some (lock, cond)) -> CThread.with_lock lock ~scope:(fun () -> Condition.wait cond lock); compute ck | Closure f -> try let data = f () in c := Val data; `Val data with e -> let e = Exninfo.capture e in let e = eval_fix_exn fix_exn e in match e with | (NotReady _, _) -> `Exn e | _ -> c := Exn e; `Exn e let force x = match compute x with | `Val v -> v | `Exn e -> Exninfo.iraise e let chain ck f = let name, uuid, fix_exn, c = get ck in create ~uuid ~name ~fix_exn (match !c with | Closure _ | Delegated _ -> Closure (fun () -> f (force ck)) | Exn _ as x -> x | Val v -> Val (f v)) let create ~fix_exn f = create ~fix_exn (Closure f) let replace kx y = let _, _, _, x = get kx in match !x with | Exn _ -> x := Closure (fun () -> force y) | _ -> CErrors.anomaly (Pp.str "A computation can be replaced only if is_exn holds.") let chain x f = let y = chain x f in if is_over x then ignore(force y); y let print f kx = let open Pp in let name, uid, _, x = get kx in let uid = if UUID.equal uid UUID.invalid then str "[#:" ++ str name ++ str "]" else str "[" ++ int uid ++ str":" ++ str name ++ str "]" in match !x with | Delegated _ -> str "Delegated" ++ uid | Closure _ -> str "Closure" ++ uid | Val x -> str "PureVal" ++ uid ++ spc () ++ hov 0 (f x) | Exn (e, _) -> str "Exn" ++ uid ++ spc () ++ hov 0 (str (Printexc.to_string e)) rocq-9.2.0/vernac/future.mli000066400000000000000000000070571516144147600160030ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> int val equal : t -> t -> bool end module UUIDMap : Map.S with type key = UUID.t module UUIDSet : Set.S with type elt = UUID.t exception NotReady of string type 'a computation type 'a value = [ `Val of 'a | `Exn of Exninfo.iexn ] type fix_exn = Stateid.exn_info option (* Build a computation, no snapshot of the global state is taken. If you need to grab a copy of the state start with from_here () and then chain. fix_exn is used to enrich any exception raised by forcing the computations or any computation that is chained after it. It is used by STM to attach errors to their corresponding states, and to communicate to the code catching the exception a valid state id. *) val create : fix_exn:fix_exn -> (unit -> 'a) -> 'a computation (* Usually from_val is used to create "fake" futures, to use the same API as if a real asynchronous computations was there. *) val from_val : 'a -> 'a computation (* Run remotely, returns the function to assign. If not blocking (the default) it raises NotReady if forced before the delegate assigns it. *) type 'a assignment = [ `Val of 'a | `Exn of Exninfo.iexn | `Comp of (unit -> 'a)] val create_delegate : ?blocking:bool -> name:string -> fix_exn -> 'a computation * ('a assignment -> unit) (* Given a computation that is_exn, replace it by another one *) val replace : 'a computation -> 'a computation -> unit (* Inspect a computation *) val is_over : 'a computation -> bool val is_exn : 'a computation -> bool val peek_val : 'a computation -> 'a option val uuid : 'a computation -> UUID.t (* [chain c f] chains computation [c] with [f]. * [chain] is eager, that is to say, it won't suspend the new computation * if the old one is_over (Exn or Val). *) val chain : 'a computation -> ('a -> 'b) -> 'b computation (* Forcing a computation *) val force : 'a computation -> 'a val compute : 'a computation -> 'a value (** Debug: print a computation given an inner printing function. *) val print : ('a -> Pp.t) -> 'a computation -> Pp.t rocq-9.2.0/vernac/g_obligations.mlg000066400000000000000000000107011516144147600172750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* get_default_tactic () end in Declare.Obls.default_tactic := tac let with_tac f tac = let tac = Option.map (fun tac -> Gentactic.intern (Global.env()) tac) tac in f tac let interp_gen tac = Proofview.Goal.enter begin fun gl -> let tac = Gentactic.intern ~strict:false (Proofview.Goal.env gl) tac in Gentactic.interp tac end (* We define new entries for programs, with the use of this module * Subtac. These entries are named Subtac. *) let pr_withtac env sigma = let open Pp in function | None -> mt () | Some tac -> str "with" ++ spc () ++ Gentactic.print_raw env sigma tac let generic_tactic = Pvernac.Vernac_.generic_tactic } VERNAC ARGUMENT EXTEND withtac PRINTED BY { pr_withtac env sigma } | [ ] -> { None } | [ "with" generic_tactic(tac) ] -> { Some tac } END { open Declare.Obls let obligation ~pm obl tac = with_tac (fun t -> obligation ~pm obl t) tac let next_obligation ~pm ?final obl tac = with_tac (fun t -> next_obligation ~pm ?final obl t) tac let classify_obbl _ = Vernacextend.(VtStartProof (Doesn'tGuaranteeOpacity,[])) } VERNAC COMMAND EXTEND Obligations CLASSIFIED BY { classify_obbl } STATE declare_program | [ "Obligation" natural(num) "of" identref(name) withtac(tac) ] -> { obligation (num, Some name.CAst.v) tac } | [ "Obligation" natural(num) withtac(tac) ] -> { obligation (num, None) tac } | [ "Next" "Obligation" "of" identref(name) withtac(tac) ] -> { next_obligation (Some name.CAst.v) tac } | [ "Next" "Obligation" withtac(tac) ] -> { next_obligation None tac } | [ "Final" "Obligation" "of" identref(name) withtac(tac) ] -> { next_obligation ~final:true (Some name.CAst.v) tac } | [ "Final" "Obligation" withtac(tac) ] -> { next_obligation ~final:true None tac } END VERNAC COMMAND EXTEND Solve_Obligations CLASSIFIED AS SIDEFF STATE program | [ "Solve" "Obligations" "of" identref(name) withtac(t) ] -> { solve_obligations (Some name.CAst.v) (Option.map interp_gen t) } | [ "Solve" "Obligations" withtac(t) ] -> { solve_obligations None (Option.map interp_gen t) } END VERNAC COMMAND EXTEND Solve_All_Obligations CLASSIFIED AS SIDEFF STATE program | [ "Solve" "All" "Obligations" withtac(t) ] -> { solve_all_obligations (Option.map interp_gen t) } END VERNAC COMMAND EXTEND Admit_Obligations CLASSIFIED AS SIDEFF STATE program | [ "Admit" "Obligations" "of" identref(name) ] -> { admit_obligations (Some name.CAst.v) } | [ "Admit" "Obligations" ] -> { admit_obligations None } END VERNAC COMMAND EXTEND Set_Solver CLASSIFIED AS SIDEFF | #[ locality = Tactic_option.tac_option_locality; ] [ "Obligation" "Tactic" ":=" generic_tactic(t) ] -> { set_default_tactic locality (Gentactic.intern (Global.env()) t); } END VERNAC COMMAND EXTEND Show_Solver CLASSIFIED AS QUERY | [ "Show" "Obligation" "Tactic" ] -> { Feedback.msg_notice Pp.(str"Program obligation tactic is " ++ print_default_tactic ()) } END VERNAC COMMAND EXTEND Show_Obligations CLASSIFIED AS QUERY STATE read_program | [ "Obligations" "of" identref(name) ] -> { fun ~pm -> show_obligations ~pm (Some name.CAst.v) } | [ "Obligations" ] -> { fun ~pm -> show_obligations ~pm None } END VERNAC COMMAND EXTEND Show_Preterm CLASSIFIED AS QUERY STATE read_program | [ "Preterm" "of" identref(name) ] -> { fun ~pm -> Feedback.msg_notice (show_term ~pm (Some name.CAst.v)) } | [ "Preterm" ] -> { fun ~pm -> Feedback.msg_notice (show_term ~pm None) } END rocq-9.2.0/vernac/g_obligations.mli000066400000000000000000000014651516144147600173060ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* strbrk "The Focus command is deprecated; use bullets or focusing brackets instead." | Some n -> str "The Focus command is deprecated;" ++ spc () ++ str "use '" ++ int n ++ str ": {' instead.") let warn_deprecated_focus_n ?loc n = warn_deprecated_focus ?loc (Some n) let warn_deprecated_focus ?loc () = warn_deprecated_focus ?loc None let warn_deprecated_unfocus = CWarnings.create ~name:"deprecated-unfocus" ~category:Deprecation.Version.v8_8 (fun () -> Pp.strbrk "The Unfocus command is deprecated") } (* Proof commands *) GRAMMAR EXTEND Gram GLOBAL: hint command; opt_hintbases: [ [ -> { [] } | ":"; l = LIST1 [id = IDENT -> { id } ] -> { l } ] ] ; command: TOP [ [ IDENT "Goal"; c = lconstr -> { VernacSynPure (VernacDefinition (Decls.(NoDischarge, Definition), ((CAst.make ~loc Names.Anonymous), None), ProveBody ([], c))) } | IDENT "Proof" -> { VernacSynPure (VernacProof (None,None)) } | IDENT "Proof"; IDENT "using"; l = G_vernac.section_subset_expr -> { VernacSynPure (VernacProof (None,Some l)) } | IDENT "Proof"; "with"; ta = generic_tactic; l = OPT [ IDENT "using"; l = G_vernac.section_subset_expr -> { l } ] -> { Vernacexpr.VernacSynPure (Vernacexpr.VernacProof (Some ta, l)) } | IDENT "Proof"; IDENT "using"; l = G_vernac.section_subset_expr; "with"; ta = generic_tactic -> { Vernacexpr.VernacSynPure (Vernacexpr.VernacProof (Some ta,Some l)) } | IDENT "Proof" ; IDENT "Mode" ; mn = string -> { VernacSynterp (VernacProofMode mn) } | IDENT "Proof"; c = lconstr -> { VernacSynPure (VernacExactProof c) } | IDENT "Abort" -> { VernacSynPure VernacAbort } | IDENT "Abort"; IDENT "All" -> { VernacSynPure VernacAbortAll } | IDENT "Admitted" -> { VernacSynPure (VernacEndProof Admitted) } | IDENT "Qed" -> { VernacSynPure (VernacEndProof (Proved (Opaque,None))) } | IDENT "Save"; id = identref -> { VernacSynPure (VernacEndProof (Proved (Opaque, Some id))) } | IDENT "Defined" -> { VernacSynPure (VernacEndProof (Proved (Transparent,None))) } | IDENT "Defined"; id=identref -> { VernacSynPure (VernacEndProof (Proved (Transparent,Some id))) } | IDENT "Restart" -> { VernacSynPure VernacRestart } | IDENT "Undo" -> { VernacSynPure (VernacUndo 1) } | IDENT "Undo"; n = natural -> { VernacSynPure (VernacUndo n) } | IDENT "Undo"; IDENT "To"; n = natural -> { VernacSynPure (VernacUndoTo n) } | IDENT "Focus" -> { warn_deprecated_focus ~loc (); VernacSynPure (VernacFocus None) } | IDENT "Focus"; n = natural -> { warn_deprecated_focus_n n ~loc; VernacSynPure (VernacFocus (Some n)) } | IDENT "Unfocus" -> { warn_deprecated_unfocus ~loc (); VernacSynPure VernacUnfocus } | IDENT "Unfocused" -> { VernacSynPure VernacUnfocused } | IDENT "Show" -> { VernacSynPure (VernacShow (ShowGoal OpenSubgoals)) } | IDENT "Show"; n = natural -> { VernacSynPure (VernacShow (ShowGoal (NthGoal n))) } | IDENT "Show"; id = qualid -> { VernacSynPure (VernacShow (ShowGoal (GoalId id))) } | IDENT "Show"; IDENT "Existentials" -> { VernacSynPure (VernacShow ShowExistentials) } | IDENT "Show"; IDENT "Universes" -> { VernacSynPure (VernacShow ShowUniverses) } | IDENT "Show"; IDENT "Conjectures" -> { VernacSynPure (VernacShow ShowProofNames) } | IDENT "Show"; IDENT "Proof" -> { VernacSynPure (VernacShow ShowProof) } | IDENT "Show"; IDENT "Intro" -> { VernacSynPure (VernacShow (ShowIntros false)) } | IDENT "Show"; IDENT "Intros" -> { VernacSynPure (VernacShow (ShowIntros true)) } | IDENT "Show"; IDENT "Match"; id = reference -> { VernacSynPure (VernacShow (ShowMatch id)) } | IDENT "Guarded" -> { VernacSynPure VernacCheckGuard } | IDENT "Validate"; IDENT "Proof" -> { VernacSynPure VernacValidateProof } (* Hints for Auto and EAuto *) | IDENT "Create"; IDENT "HintDb" ; id = IDENT ; b = [ IDENT "discriminated" -> { true } | -> { false } ] -> { VernacSynPure (VernacCreateHintDb (id, b)) } | IDENT "Remove"; IDENT "Hints"; ids = LIST1 global; dbnames = opt_hintbases -> { VernacSynPure (VernacRemoveHints (dbnames, ids)) } | IDENT "Hint"; h = hint; dbnames = opt_hintbases -> { VernacSynPure (VernacHints (dbnames, h)) } ] ]; reference_or_constr: [ [ r = global -> { HintsReference r } | c = constr -> { HintsConstr c } ] ] ; hint: [ [ IDENT "Resolve"; lc = LIST1 reference_or_constr; info = hint_info -> { HintsResolve (List.map (fun x -> (info, true, x)) lc) } | IDENT "Resolve"; "->"; lc = LIST1 global; n = OPT natural -> { HintsResolveIFF (true, lc, n) } | IDENT "Resolve"; "<-"; lc = LIST1 global; n = OPT natural -> { HintsResolveIFF (false, lc, n) } | IDENT "Immediate"; lc = LIST1 reference_or_constr -> { HintsImmediate lc } | IDENT "Variables"; IDENT "Transparent" -> { HintsTransparency (HintsVariables, true) } | IDENT "Variables"; IDENT "Opaque" -> { HintsTransparency (HintsVariables, false) } | IDENT "Constants"; IDENT "Transparent" -> { HintsTransparency (HintsConstants, true) } | IDENT "Constants"; IDENT "Opaque" -> { HintsTransparency (HintsConstants, false) } | IDENT "Projections"; IDENT "Transparent" -> { HintsTransparency (HintsProjections, true) } | IDENT "Projections"; IDENT "Opaque" -> { HintsTransparency (HintsProjections, false) } | IDENT "Transparent"; lc = LIST1 global -> { HintsTransparency (HintsReferences lc, true) } | IDENT "Opaque"; lc = LIST1 global -> { HintsTransparency (HintsReferences lc, false) } | IDENT "Mode"; l = global; m = mode -> { HintsMode (l, m) } | IDENT "Unfold"; lqid = LIST1 global -> { HintsUnfold lqid } | IDENT "Constructors"; lc = LIST1 global -> { HintsConstructors lc } | IDENT "Extern"; n = natural; c = OPT Constr.constr_pattern ; "=>"; tac = generic_tactic -> { Vernacexpr.HintsExtern (n,c, tac) } ] ] ; mode: [ [ l = LIST1 [ "+" -> { ModeInput } | "!" -> { ModeNoHeadEvar } | "-" -> { ModeOutput } ] -> { l } ] ] ; END VERNAC COMMAND EXTEND OptimizeProof | ![ proof ] [ "Optimize" "Proof" ] => { Vernacextend.classify_as_proofstep } -> { fun ~pstate -> Declare.Proof.compact pstate } | [ "Optimize" "Heap" ] => { Vernacextend.classify_as_proofstep } -> { Gc.compact () } END rocq-9.2.0/vernac/g_proofs.mli000066400000000000000000000014051516144147600162760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* { ArgArg n } | id = identref -> { ArgVar id } ] ] ; nat_or_var: [ [ n = natural -> { ArgArg n } | id = identref -> { ArgVar id } ] ] ; occs_nums: [ [ nl = LIST1 nat_or_var -> { OnlyOccurrences nl } | "-"; nl = LIST1 nat_or_var -> { AllOccurrencesBut nl } ] ] ; occs: [ [ "at"; occs = occs_nums -> { occs } | -> { AllOccurrences } ] ] ; pattern_occ: [ [ c = constr; nl = occs -> { (nl,c) } ] ] ; ref_or_pattern_occ: (* If a string, it is interpreted as a ref (anyway a Rocq string does not reduce) *) [ [ c = smart_global; nl = occs -> { nl,Inl c } | c = constr; nl = occs -> { nl,Inr c } ] ] ; unfold_occ: [ [ c = smart_global; nl = occs -> { (nl,c) } ] ] ; red_flag: [ [ IDENT "beta" -> { [FBeta] } | IDENT "iota" -> { [FMatch;FFix;FCofix] } | IDENT "match" -> { [FMatch] } | IDENT "fix" -> { [FFix] } | IDENT "cofix" -> { [FCofix] } | IDENT "zeta" -> { [FZeta] } | IDENT "delta"; d = delta_flag -> { [d] } | IDENT "head" -> { [FHead] } ] ] ; delta_flag: [ [ "-"; "["; idl = LIST1 smart_global; "]" -> { FDeltaBut idl } | "["; idl = LIST1 smart_global; "]" -> { FConst idl } | -> { FDeltaBut [] } ] ] ; strategy_flag: [ [ s = LIST1 red_flag -> { Redops.make_red_flag (List.flatten s) } | h = OPT [ IDENT "head" -> { () } ]; d = delta_flag -> { all_with ~head:(Option.has_some h) d } ] ] ; red_expr: [ [ IDENT "red" -> { Red } | IDENT "hnf" -> { Hnf } | IDENT "simpl"; h = OPT [ IDENT "head" -> { () } ]; d = delta_flag; po = OPT ref_or_pattern_occ -> { Simpl (all_with ~head:(Option.has_some h) d,po) } | IDENT "cbv"; s = strategy_flag -> { Cbv s } | IDENT "cbn"; s = strategy_flag -> { Cbn s } | IDENT "lazy"; s = strategy_flag -> { Lazy s } | IDENT "compute"; delta = delta_flag -> { Cbv (all_with ~head:false delta) } | IDENT "vm_compute"; po = OPT ref_or_pattern_occ -> { CbvVm po } | IDENT "native_compute"; po = OPT ref_or_pattern_occ -> { CbvNative po } | IDENT "unfold"; ul = LIST1 unfold_occ SEP "," -> { Unfold ul } | IDENT "fold"; cl = LIST1 constr -> { Fold cl } | IDENT "pattern"; pl = LIST1 pattern_occ SEP"," -> { Pattern pl } | s = IDENT -> { ExtraRedExpr s } ] ] ; END rocq-9.2.0/vernac/g_redexpr.mli000066400000000000000000000022221516144147600164350ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Dash n | '+' -> Plus n | '*' -> Star n | _ -> assert false let test_hash_ident = let open Procq.Lookahead in to_entry "test_hash_ident" begin lk_kw "#" >> lk_ident >> check_no_space end let test_id_colon = let open Procq.Lookahead in to_entry "test_id_colon" begin lk_ident >> lk_kw ":" end let warn_chdir_pwd = CWarnings.create ~name:"change-dir-pwd-deprecated" ~category:Deprecation.Version.v8_20 (fun () -> strbrk "Command \"Cd\" as a synonym of \"Pwd\" is deprecated." ++ spc () ++ strbrk "Use \"Pwd\" instead.") } GRAMMAR EXTEND Gram GLOBAL: vernac_control quoted_attributes attribute_list gallina_ext noedit_mode subprf subprf_with_selector qualid; vernac_control: FIRST [ [ control = LIST0 control_flag; v = decorated_vernac -> { let (attrs, expr) = v in CAst.make ~loc { control; attrs; expr; } } ] ] ; control_flag: [ [ IDENT "Time" -> { CAst.make ~loc ControlTime } | IDENT "Instructions" -> { CAst.make ~loc ControlInstructions } | IDENT "Profile"; f = OPT STRING -> { CAst.make ~loc (ControlProfile f) } | IDENT "Redirect"; s = ne_string -> { CAst.make ~loc (ControlRedirect s) } | IDENT "Timeout"; n = natural -> { CAst.make ~loc (ControlTimeout n) } | IDENT "Fail" -> { CAst.make ~loc ControlFail } | IDENT "Succeed" -> { CAst.make ~loc ControlSucceed } ] ] ; decorated_vernac: [ [ a = quoted_attributes ; a' = LIST0 legacy_attr; v = vernac_aux -> { (List.append a a', v) } ] ] ; quoted_attributes: [ [ l = LIST0 [ "#[" ; a = attribute_list ; "]" -> { a } ] -> { List.flatten l } ] ] ; attribute_list: [ [ a = LIST1 attribute SEP "," -> { a } ] ] ; attribute: [ [ k = ident ; v = attr_value -> { CAst.make ~loc (Names.Id.to_string k, v) } (* Required because "ident" is declared a keyword when loading Ltac. *) | IDENT "using" ; v = attr_value -> { CAst.make ~loc ("using", v) } ] ] ; attr_value: [ [ "=" ; v = string -> { VernacFlagLeaf (FlagString v) } | "=" ; v = qualid -> { VernacFlagLeaf (FlagQualid v) } | "(" ; a = attribute_list ; ")" -> { VernacFlagList a } | -> { VernacFlagEmpty } ] ] ; legacy_attr: [ [ IDENT "Local" -> { CAst.make ~loc ("local", VernacFlagEmpty) } | IDENT "Global" -> { CAst.make ~loc ("global", VernacFlagEmpty) } | IDENT "Polymorphic" -> { Attributes.vernac_polymorphic_flag (Some loc) } | IDENT "Monomorphic" -> { Attributes.vernac_monomorphic_flag (Some loc) } | IDENT "Cumulative" -> { CAst.make ~loc ("universes", VernacFlagList [CAst.make ~loc ("cumulative", VernacFlagEmpty)]) } | IDENT "NonCumulative" -> { CAst.make ~loc ("universes", VernacFlagList [CAst.make ~loc ("cumulative", VernacFlagLeaf (FlagQualid (Libnames.qualid_of_string "no")))]) } | IDENT "Private" -> { CAst.make ~loc ("private", VernacFlagList [CAst.make ~loc ("matching", VernacFlagEmpty)]) } | IDENT "Program" -> { CAst.make ~loc ("program", VernacFlagEmpty) } ] ] ; vernac_aux: (* Better to parse "." here: in case of failure (e.g. in coerce_to_var), *) (* "." is still in the stream and discard_to_dot works correctly *) [ [ g = gallina; "." -> { VernacSynPure g } | g = gallina_ext; "." -> { g } | c = command; "." -> { c } | c = syntax; "." -> { c } ] ] ; vernac_aux: LAST [ [ prfcom = command_entry -> { prfcom } ] ] ; noedit_mode: [ [ c = query_command -> { VernacSynPure (c None) } ] ] ; subprf: [ [ s = BULLET -> { VernacBullet (make_bullet s) } | "}" -> { VernacEndSubproof } ] ] ; subprf_with_selector: [ [ "{" -> { fun g -> VernacSubproof g } (* query_command needs to be here to factor with VernacSubproof *) | c = query_command -> { c } ] ] ; END { let warn_plural_command = CWarnings.create ~name:"plural-command" ~category:CWarnings.CoreCategories.pedantic ~default:CWarnings.Disabled (fun kwd -> strbrk (Printf.sprintf "Command \"%s\" expects more than one assumption." kwd)) let test_plural_form loc kwd = function | [(_,([_],_))] -> warn_plural_command ~loc kwd | _ -> () let test_plural_form_types loc kwd = function | [([_],_)] -> warn_plural_command ~loc kwd | _ -> () let test_plural_form_rules loc kwd = function | [_] -> warn_plural_command ~loc kwd | _ -> () let lname_of_lident : lident -> lname = CAst.map (fun s -> Name s) let name_of_ident_decl : ident_decl -> name_decl = on_fst lname_of_lident let test_variance_ident = let open Procq.Lookahead in to_entry "test_variance_ident" begin lk_kws ["=";"+";"*"] >> lk_ident end let test_doublepipe_univ_decl = let open Procq.Lookahead in to_entry "test_doublepipe_univ_decl" (lk_ident_list >> lk_kw "|" >> lk_ident_list >> (lk_kw "+" <+> lk_empty) >> (lk_kw "|" <+> lk_kw "|}")) let test_doublepipe_cumul_univ_decl = let open Procq.Lookahead in let lk_list_variance_ident = lk_list (lk_kw "+" <+> lk_kw "*" <+> lk_kw "=" <+> lk_ident) in to_entry "test_doublepipe_cumul_univ_decl" (lk_ident_list >> lk_kw "|" >> lk_list_variance_ident >> (lk_kw "+" <+> lk_empty) >> (lk_kw "|" <+> lk_kw "|}")) let test_semicolon_cumul_univ_decl = let open Procq.Lookahead in to_entry "test_semicolon_cumul_univ_decl" (lk_ident_list >> lk_kw ";") let test_univ_cst = let open Procq.Lookahead in let univ = lk_qualid <+> lk_kws ["Set";"Prop"] in to_entry "test_univ_cst" (univ >> lk_kws ["<"; "="; "<="] >> univ) let rec elim_constraints = function | [] -> [] | ElimCst (q1,k,q2) :: t -> (q1,k,q2) :: elim_constraints t | h :: t -> elim_constraints t let rec univ_constraints = function | [] -> [] | UnivCst (l1,k,l2) :: t -> (l1,k,l2) :: univ_constraints t | h :: t -> univ_constraints t } (* Gallina declarations *) GRAMMAR EXTEND Gram GLOBAL: gallina gallina_ext thm_token def_token assumption_token def_body of_type of_type_inst record_field notation_declaration decl_notations fix_definition ident_decl univ_decl inductive_or_record_definition; gallina: (* Definition, Theorem, Variable, Axiom, ... *) [ [ thm = thm_token; id = ident_decl; bl = binders; ":"; c = lconstr; l = LIST0 [ "with"; id = ident_decl; bl = binders; ":"; c = lconstr -> { (id,(bl,c)) } ] -> { VernacStartTheoremProof (thm, (id,(bl,c))::l) } | stre = assumption_token; nl = inline; bl = assum_list -> { VernacAssumption (stre, nl, bl) } | tk = assumptions_token; nl = inline; bl = assum_list -> { let (kwd,stre) = tk in test_plural_form loc kwd bl; VernacAssumption (stre, nl, bl) } | d = def_token; id = ident_decl; b = def_body -> { VernacDefinition (d, name_of_ident_decl id, b) } | IDENT "Symbol"; bl = assum_list -> { VernacSymbol bl } | IDENT "Symbols"; bl = assum_list -> { test_plural_form loc "Symbols" bl; VernacSymbol bl } | IDENT "Let"; id = ident_decl; b = def_body -> { VernacDefinition ((DoDischarge, Let), name_of_ident_decl id, b) } (* Gallina inductive declarations *) | f = finite_token; ind = inductive_or_record_definition -> { VernacInductive (f, [ind]) } | f = inductive_token; indl = LIST1 inductive_or_record_definition SEP "with" -> { VernacInductive (f, indl) } | "Fixpoint"; recs = LIST1 fix_definition SEP "with" -> { VernacFixpoint (NoDischarge, List.split recs) } | IDENT "Let"; "Fixpoint"; recs = LIST1 fix_definition SEP "with" -> { VernacFixpoint (DoDischarge, List.split recs) } | "CoFixpoint"; corecs = LIST1 cofix_definition SEP "with" -> { VernacCoFixpoint (NoDischarge, corecs) } | IDENT "Let"; "CoFixpoint"; corecs = LIST1 cofix_definition SEP "with" -> { VernacCoFixpoint (DoDischarge, corecs) } | IDENT "Scheme"; IDENT "All"; IDENT "for" ; id = smart_global ; strpos = OPT [IDENT "over" ; l = LIST1 ident SEP "," -> {l}] -> { VernacSchemeAll (id, strpos) } | IDENT "Scheme"; l = LIST1 scheme SEP "with" -> { VernacScheme l } | IDENT "Scheme"; IDENT "Equality"; IDENT "for" ; id = smart_global -> { VernacSchemeEquality (SchemeEquality,id) } | IDENT "Scheme"; IDENT "Boolean"; IDENT "Equality"; IDENT "for" ; id = smart_global -> { VernacSchemeEquality (SchemeBooleanEquality,id) } | IDENT "Scheme"; IDENT "Rewriting"; IDENT "for" ; id = smart_global -> { VernacSchemeEquality (SchemeRewriting,id) } | IDENT "Combined"; IDENT "Scheme"; id = identref; IDENT "from"; l = LIST1 identref SEP "," -> { VernacCombinedScheme (id, l) } | IDENT "Register"; g = global; "as"; quid = qualid -> { VernacRegister(g, RegisterCoqlib quid) } | IDENT "Register"; IDENT "Scheme"; g = global; "as"; qid = qualid; IDENT "for"; g' = global -> { VernacRegister(g, RegisterScheme {inductive = g'; scheme_kind = qid}) } | IDENT "Register"; IDENT "Inline"; g = global -> { VernacRegister(g, RegisterInline) } | IDENT "Primitive"; id = ident_decl; 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 "Sort"; l = LIST1 identref -> { VernacSort l } | IDENT "Sorts"; l = LIST1 identref -> { VernacSort l } | IDENT "Constraint"; l = LIST1 sort_constraint SEP "," -> { VernacConstraint l } | IDENT "Rewrite"; IDENT "Rule"; id = identref; ":="; OPT"|"; rules = LIST1 rewrite_rule SEP "|" -> { VernacAddRewRule (id, rules) } | IDENT "Rewrite"; IDENT "Rules"; id = identref; ":="; OPT"|"; rules = LIST1 rewrite_rule SEP "|" -> { test_plural_form_rules loc "Rewrite Rules" rules; VernacAddRewRule (id, rules) } ] ] ; register_token: [ [ test_hash_ident; "#"; r = IDENT -> { CPrimitives.parse_op_or_type ~loc r } ] ] ; thm_token: [ [ "Theorem" -> { Theorem } | IDENT "Lemma" -> { Lemma } | IDENT "Fact" -> { Fact } | IDENT "Remark" -> { Remark } | IDENT "Corollary" -> { Corollary } | IDENT "Proposition" -> { Proposition } | IDENT "Property" -> { Property } ] ] ; def_token: [ [ "Definition" -> { (NoDischarge,Definition) } | IDENT "Example" -> { (NoDischarge,Example) } | IDENT "SubClass" -> { (NoDischarge,SubClass) } ] ] ; assumption_token: [ [ "Hypothesis" -> { (DoDischarge, Logical) } | "Variable" -> { (DoDischarge, Definitional) } | "Axiom" -> { (NoDischarge, Logical) } | "Parameter" -> { (NoDischarge, Definitional) } | IDENT "Conjecture" -> { (NoDischarge, Conjectural) } ] ] ; assumptions_token: [ [ IDENT "Hypotheses" -> { ("Hypotheses", (DoDischarge, Logical)) } | IDENT "Variables" -> { ("Variables", (DoDischarge, Definitional)) } | IDENT "Axioms" -> { ("Axioms", (NoDischarge, Logical)) } | IDENT "Parameters" -> { ("Parameters", (NoDischarge, Definitional)) } | IDENT "Conjectures" -> { ("Conjectures", (NoDischarge, Conjectural)) } ] ] ; inline: [ [ IDENT "Inline"; "("; i = natural; ")" -> { InlineAt i } | IDENT "Inline" -> { DefaultInline } | -> { NoInline } ] ] ; sort_constraint: [ [ test_univ_cst; l = universe_name; ord = [ "<" -> { Univ.UnivConstraint.Lt } | "=" -> { Univ.UnivConstraint.Eq } | "<=" -> { Univ.UnivConstraint.Le } ]; r = universe_name -> { UnivCst (l, ord, r) } | l = sort_quality_var; "->"; r = sort_quality_var -> { ElimCst (l, Sorts.ElimConstraint.ElimTo, r) } ] ] ; univ_decl_constraints: [ [ "|"; l' = LIST0 sort_constraint SEP ","; ext = [ "+" -> { true } | -> { false } ]; "}" -> { (l',ext) } | ext = [ "}" -> { true } | bar_cbrace -> { false } ] -> { ([], ext) } ] ] ; univ_decl: [ [ "@{" ; test_doublepipe_univ_decl; l0 = LIST0 identref; pipe_loc = [ "|" -> { loc } ]; l = LIST0 identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in G_constr.warn_old_sort_syntax ~loc:pipe_loc (); { univdecl_qualities = l0; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } | "@{" ; l0 = LIST0 identref; ";"; l = LIST0 identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in { univdecl_qualities = l0; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } | "@{" ; l = LIST0 identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in { univdecl_qualities = []; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } ] ] ; variance: [ [ "+" -> { UVars.Variance.Covariant } | "=" -> { UVars.Variance.Invariant } | "*" -> { UVars.Variance.Irrelevant } ] ] ; variance_identref: [ [ id = identref -> { (id, None) } | test_variance_ident; v = variance; id = identref -> { (id, Some v) } (* We need this test to help the parser avoid the conflict between "+" before ident (covariance) and trailing "+" (extra univs allowed) *) ] ] ; cumul_univ_decl: [ [ "@{" ; test_doublepipe_cumul_univ_decl; l0 = LIST0 identref; pipe_loc = [ "|" -> { loc } ]; l = LIST0 variance_identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in G_constr.warn_old_sort_syntax ~loc:pipe_loc (); { univdecl_qualities = l0; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } | "@{" ; test_semicolon_cumul_univ_decl; l0 = LIST0 identref; ";"; l = LIST0 variance_identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in { univdecl_qualities = l0; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } | "@{" ; l = LIST0 variance_identref; ext = [ "+" -> { true } | -> { false } ]; cs = univ_decl_constraints -> { let open UState in { univdecl_qualities = []; univdecl_extensible_qualities = false; univdecl_elim_constraints = elim_constraints @@ fst cs; univdecl_instance = l; univdecl_extensible_instance = ext; univdecl_univ_constraints = univ_constraints @@ fst cs; univdecl_extensible_constraints = snd cs } } ] ] ; ident_decl: [ [ i = identref; l = OPT univ_decl -> { (i, l) } ] ] ; cumul_ident_decl: [ [ i = identref; l = OPT cumul_univ_decl -> { (i, l) } ] ] ; inductive_token: [ [ IDENT "Inductive" -> { Inductive_kw } | IDENT "CoInductive" -> { CoInductive } ] ] ; finite_token: [ [ IDENT "Variant" -> { Variant } | IDENT "Record" -> { Record } | IDENT "Structure" -> { Structure } | IDENT "Class" -> { Class true } ] ] ; (* Simple definitions *) def_body: [ [ bl = binders; ":="; red = reduce; c = lconstr -> { match c.CAst.v with | CCast(c, Some C.DEFAULTcast, t) -> DefineBody (bl, red, c, Some t) | _ -> DefineBody (bl, red, c, None) } | bl = binders; ":"; t = lconstr; ":="; red = reduce; c = lconstr -> { DefineBody (bl, red, c, Some t) } | bl = binders; ":"; t = lconstr -> { ProveBody (bl, t) } ] ] ; reduce: [ [ IDENT "Eval"; r = red_expr; "in" -> { Some r } | -> { None } ] ] ; notation_declaration: [ [ ntn = lstring; ":="; c = constr; modl = syntax_modifiers; scopt = OPT [ ":"; sc = IDENT -> { sc } ] -> { { ntn_decl_string = ntn; ntn_decl_interp = c; ntn_decl_scope = scopt; ntn_decl_modifiers = modl; } } ] ] ; decl_sep: [ [ IDENT "and" -> { () } ] ] ; decl_notations: [ [ "where"; l = LIST1 notation_declaration SEP decl_sep -> { l } | -> { [] } ] ] ; (* Inductives and records *) opt_constructors_or_fields: [ [ ":="; lc = constructors_or_record -> { lc } | ":=" -> { Constructors [] } | -> { RecordDecl (None, [], None) } ] ] ; inductive_or_record_definition: [ [ oc = opt_coercion; id = cumul_ident_decl; indpar = binders; extrapar = OPT [ "|"; p = binders -> { p } ]; c = OPT [ ":"; c = lconstr -> { c } ]; lc=opt_constructors_or_fields; ntn = decl_notations -> { (((oc,id),(indpar,extrapar),c,lc),ntn) } ] ] ; constructors_or_record: [ [ "|"; l = LIST1 constructor SEP "|" -> { Constructors l } | attr = quoted_attributes ; id = identref ; c = constructor_type; "|"; l = LIST1 constructor SEP "|" -> { Constructors ((c attr id)::l) } | attr = quoted_attributes ; id = identref ; c = constructor_type -> { Constructors [ c attr id ] } | attr = quoted_attributes ; cstr = identref; "{"; fs = record_fields; "}"; id = default_inhabitant_ident -> { let () = unsupported_attributes attr in RecordDecl (Some cstr,fs,id) } | "{";fs = record_fields; "}"; id = default_inhabitant_ident -> { RecordDecl (None,fs,id) } ] ] ; default_inhabitant_ident: [ [ "as"; id = identref -> { Some id } | -> { None } ] ] ; (* csort: [ [ s = sort -> CSort (loc,s) ] ] ; *) opt_coercion: [ [ ">" -> { AddCoercion } | -> { NoCoercion } ] ] ; (* (co)-fixpoints *) fix_definition: [ [ id_decl = ident_decl; bl = binders_fixannot; rtype = type_cstr; body_def = OPT [":="; def = lconstr -> { def } ]; notations = decl_notations -> { let binders, rec_order = bl in ((rec_order : Constrexpr.fixpoint_order_expr option), {fname = fst id_decl; univs = snd id_decl; binders; rtype; body_def; notations}) } ] ] ; cofix_definition: [ [ id_decl = ident_decl; binders = binders; rtype = type_cstr; body_def = OPT [":="; def = lconstr -> { def }]; notations = decl_notations -> { {fname = fst id_decl; univs = snd id_decl; binders; rtype; body_def; notations} } ]] ; (* Rewrite Rules *) rw_pattern: [ [ p = lconstr -> { p } ] ]; rewrite_rule: [ [ u = OPT [ u = univ_decl; "|-" -> { u }]; lhs = rw_pattern; "=>" ; rhs = lconstr -> { (u, lhs, rhs) } ] ] ; (* Inductive schemes *) scheme: [ [ kind = scheme_kind -> { (None,kind) } | id = identref; ":="; kind = scheme_kind -> { (Some id,kind) } ] ] ; scheme_kind: [ [sch_type = scheme_type; "for"; sch_qualid = smart_global; IDENT "Sort"; sch_sort = sort_quality_or_set -> { {sch_type; sch_qualid; sch_sort} } ] ] ; scheme_type: [ [ IDENT "Induction" -> { SchemeInduction } | IDENT "Minimality" -> { SchemeMinimality } | IDENT "Elimination" -> { SchemeElimination } | IDENT "Case" -> { SchemeCase } ] ] ; (* Various Binders *) (* (* ... without coercions *) binder_nodef: [ [ b = binder_let -> (match b with CLocalAssum(l,ty) -> (l,ty) | CLocalDef _ -> user_err ~loc (Pp.str"defined binder not allowed here.")) ] ] ; *) (* ... with coercions *) record_field: [ [ rfu_attrs = quoted_attributes ; bd = record_binder; rfu_priority = OPT [ "|"; n = natural -> { n } ]; rfu_notation = decl_notations -> { let (rfu_coercion, rfu_instance), rf_decl = bd in rf_decl, { rfu_attrs ; rfu_coercion ; rfu_instance ; rfu_priority ; rfu_notation } } ] ] ; record_fields: [ RIGHTA [ f = record_field; ";"; fs = record_fields -> { f :: fs } | f = record_field -> { [f] } | -> { [] } ] ] ; field_body: [ [ l = binders; oc = of_type_inst; t = lconstr -> { fun id -> (oc,AssumExpr (id,l,t)) } | l = binders; oc = of_type_inst; t = lconstr; ":="; b = lconstr -> { fun id -> (oc,DefExpr (id,l,b,Some t)) } | l = binders; ":="; b = lconstr -> { fun id -> (* Why are we dropping cast info here? *) match b.CAst.v with | CCast(b', _, t) -> ((NoCoercion,NoInstance),DefExpr(id,l,b',Some t)) | _ -> ((NoCoercion,NoInstance),DefExpr(id,l,b,None)) } ] ] ; record_binder: [ [ id = name -> { ((NoCoercion,NoInstance),AssumExpr(id, [], CAst.make ~loc @@ CHole (None))) } | id = name; f = field_body -> { f id } ] ] ; assum_list: [ [ bl = LIST1 assum_coe -> { bl } | b = assumpt -> { [b] } ] ] ; assum_coe: [ [ "("; a = assumpt; ")" -> { a } ] ] ; assumpt: [ [ idl = LIST1 ident_decl; oc = of_type; c = lconstr -> { (oc,(idl,c)) } ] ] ; constructor_type: [[ l = binders; t= [ coe = of_type_inst; c = lconstr -> { fun l attr id -> ((attr, fst coe, snd coe),(id,mkProdCN ~loc l c)) } | -> { fun l attr id -> ((attr,NoCoercion,NoInstance),(id,mkProdCN ~loc l (CAst.make ~loc @@ CHole (None)))) } ] -> { t l } ]] ; constructor: [ [ attr = quoted_attributes ; id = identref; c=constructor_type -> { c attr id } ] ] ; of_type: [ [ ":>" -> { AddCoercion } | ":"; ">" -> { AddCoercion } | ":" -> { NoCoercion } ] ] ; of_type_inst: [ [ ":>" -> { (AddCoercion, NoInstance) } | ":"; ">" -> { (AddCoercion, NoInstance) } | "::" -> { (NoCoercion, BackInstance) } | "::>" -> { (AddCoercion, BackInstance) } | ":" -> { (NoCoercion, NoInstance) } ] ] ; END { let test_only_starredidentrefs = let open Procq.Lookahead in to_entry "test_only_starredidentrefs" begin lk_list (lk_ident <+> lk_kws ["Type"; "*"]) >> (lk_kws [".";")"]) end let starredidentreflist_to_expr l = match l with | [] -> SsEmpty | x :: xs -> List.fold_right (fun i acc -> SsUnion(i,acc)) xs x let warn_deprecated_include_type = CWarnings.create ~name:"deprecated-include-type" ~category:Deprecation.Version.v8_3 (fun () -> strbrk "Include Type is deprecated; use Include instead") let warn_deprecated_as_ident_kind = CWarnings.create ~name:"deprecated-as-ident-kind" ~category:Deprecation.Version.v8_14 (fun () -> strbrk "grammar kind \"as ident\" no longer accepts \"_\"; use \"as name\" instead to accept \"_\", too, or silence the warning if you actually intended to accept only identifiers.") } (* Modules and Sections *) GRAMMAR EXTEND Gram GLOBAL: gallina_ext module_expr module_type section_subset_expr; gallina_ext: [ [ (* Interactive module declaration *) IDENT "Module"; export = export_token; id = identref; bl = LIST0 module_binder; sign = of_module_type; body = is_module_expr -> { VernacSynterp (VernacDefineModule (export, id, bl, sign, body)) } | IDENT "Module"; "Type"; id = identref; bl = LIST0 module_binder; sign = check_module_types; body = is_module_type -> { VernacSynterp (VernacDeclareModuleType (id, bl, sign, body)) } | IDENT "Declare"; IDENT "Module"; export = export_token; id = identref; bl = LIST0 module_binder; ":"; mty = module_type_inl -> { VernacSynterp (VernacDeclareModule (export, id, bl, mty)) } (* Section beginning *) | IDENT "Section"; id = identref -> { VernacSynterp (VernacBeginSection id) } (* This end a Section a Module or a Module Type *) | IDENT "End"; id = identref -> { VernacSynterp (VernacEndSegment id) } (* Naming a set of section hyps *) | IDENT "Collection"; id = identref; ":="; expr = section_subset_expr -> { VernacSynPure (VernacNameSectionHypSet (id, expr)) } (* Requiring an external file *) | IDENT "From" ; ns = global ; IDENT "Extra"; IDENT "Dependency"; f = ne_string ; id = OPT [ "as"; id = IDENT -> { id } ] -> { VernacSynterp (VernacExtraDependency (ns, f, Option.map Id.of_string id)) } (* Requiring an already compiled module *) | IDENT "Require"; export = export_token; qidl = LIST1 filtered_import -> { VernacSynterp (VernacRequire (None, export, qidl)) } | IDENT "From" ; ns = global ; IDENT "Require"; export = export_token ; qidl = LIST1 filtered_import -> { VernacSynterp (VernacRequire (Some ns, export, qidl)) } | IDENT "Import"; cats = OPT import_categories; qidl = LIST1 filtered_import -> { VernacSynterp (VernacImport ((Import,cats),qidl)) } | IDENT "Export"; cats = OPT import_categories; qidl = LIST1 filtered_import -> { VernacSynterp (VernacImport ((Export,cats),qidl)) } | IDENT "Include"; e = module_type_inl; l = LIST0 ext_module_type -> { VernacSynterp (VernacInclude(e::l)) } | IDENT "Include"; "Type"; e = module_type_inl; l = LIST0 ext_module_type -> { warn_deprecated_include_type ~loc (); VernacSynterp (VernacInclude(e::l)) } ] ] ; import_categories: [ [ negative = OPT "-"; "("; cats = LIST1 qualid SEP ","; ")" -> { let cats = List.map (fun cat -> CAst.make ?loc:cat.CAst.loc (Libnames.string_of_qualid cat)) cats in { negative=Option.has_some negative; import_cats = cats } } ] ] ; filtered_import: [ [ m = global -> { (m, ImportAll) } | m = global; "("; ns = LIST1 one_import_filter_name SEP ","; ")" -> { (m, ImportNames ns) } ] ] ; one_import_filter_name: [ [ n = global; etc = OPT [ "("; ".."; ")" -> { () } ] -> { n, Option.has_some etc } ] ] ; export_token: [ [ IDENT "Import"; cats = OPT import_categories -> { Some (Import,cats) } | IDENT "Export"; cats = OPT import_categories -> { Some (Export,cats) } | -> { None } ] ] ; ext_module_type: [ [ "<+"; mty = module_type_inl -> { mty } ] ] ; ext_module_expr: [ [ "<+"; mexpr = module_expr_inl -> { mexpr } ] ] ; check_module_type: [ [ "<:"; mty = module_type_inl -> { mty } ] ] ; check_module_types: [ [ mtys = LIST0 check_module_type -> { mtys } ] ] ; of_module_type: [ [ ":"; mty = module_type_inl -> { Enforce mty } | mtys = check_module_types -> { Check mtys } ] ] ; is_module_type: [ [ ":="; mty = module_type_inl ; l = LIST0 ext_module_type -> { (mty::l) } | -> { [] } ] ] ; is_module_expr: [ [ ":="; mexpr = module_expr_inl; l = LIST0 ext_module_expr -> { (mexpr::l) } | -> { [] } ] ] ; functor_app_annot: [ [ "["; IDENT "inline"; "at"; IDENT "level"; i = natural; "]" -> { InlineAt i } | "["; IDENT "no"; IDENT "inline"; "]" -> { NoInline } | -> { DefaultInline } ] ] ; module_expr_inl: [ [ "!"; me = module_expr -> { (me,NoInline) } | me = module_expr; a = functor_app_annot -> { (me,a) } ] ] ; module_type_inl: [ [ "!"; me = module_type -> { (me,NoInline) } | me = module_type; a = functor_app_annot -> { (me,a) } ] ] ; (* Module binder *) module_binder: [ [ "("; export = export_token; idl = LIST1 identref; ":"; mty = module_type_inl; ")" -> { (export,idl,mty) } ] ] ; (* Module expressions *) module_expr: [ [ me = module_expr_atom -> { CAst.make ~loc @@ CMident me } | me1 = module_expr; me2 = module_expr_atom -> { CAst.make ~loc @@ CMapply (me1,me2) } ] ] ; module_expr_atom: [ [ qid = qualid -> { qid } | "("; me = module_expr_atom; ")" -> { me } ] ] ; with_declaration: [ [ "Definition"; fqid = fullyqualid; udecl = OPT univ_decl; ":="; c = Constr.lconstr -> { CWith_Definition (fqid,udecl,c) } | IDENT "Module"; fqid = fullyqualid; ":="; qid = qualid -> { CWith_Module (fqid,qid) } ] ] ; module_type: [ [ qid = qualid -> { CAst.make ~loc @@ CMident qid } | "("; mt = module_type; ")" -> { mt } | mty = module_type; me = module_expr_atom -> { CAst.make ~loc @@ CMapply (mty,me) } | mty = module_type; "with"; decl = with_declaration -> { CAst.make ~loc @@ CMwith (mty,decl) } ] ] ; (* Proof using *) section_subset_expr: [ [ test_only_starredidentrefs; l = LIST0 starredidentref -> { starredidentreflist_to_expr l } | e = ssexpr -> { e } ]] ; starredidentref: [ [ i = identref -> { SsSingl i } | i = identref; "*" -> { SsFwdClose(SsSingl i) } | "Type" -> { SsType } | "Type"; "*" -> { SsFwdClose SsType } ]] ; ssexpr: [ "35" [ "-"; e = ssexpr -> { SsCompl e } ] | "50" [ e1 = ssexpr; "-"; e2 = ssexpr-> { SsSubstr(e1,e2) } | e1 = ssexpr; "+"; e2 = ssexpr-> { SsUnion(e1,e2) } ] | "0" [ i = starredidentref -> { i } | "()" -> { SsEmpty } | "("; test_only_starredidentrefs; l = LIST0 starredidentref; ")"-> { starredidentreflist_to_expr l } | "("; test_only_starredidentrefs; l = LIST0 starredidentref; ")"; "*" -> { SsFwdClose(starredidentreflist_to_expr l) } | "("; e = ssexpr; ")"-> { e } | "("; e = ssexpr; ")"; "*" -> { SsFwdClose e } ] ] ; END (* Extensions: implicits, coercions, etc. *) GRAMMAR EXTEND Gram GLOBAL: gallina_ext hint_info scope_delimiter; gallina_ext: TOP [ [ (* Transparent and Opaque *) IDENT "Transparent"; o = OPT [ "!" -> {()} ]; l = LIST1 smart_global -> { VernacSynPure (VernacSetOpacity ((Conv_oracle.transparent, l), o <> None)) } | IDENT "Opaque"; o = OPT [ "!" -> {()} ]; l = LIST1 smart_global -> { VernacSynPure (VernacSetOpacity ((Conv_oracle.Opaque, l), o <> None)) } | IDENT "Strategy"; l = LIST1 [ v=strategy_level; "["; q=LIST1 smart_global; "]" -> { (v,q) } ] -> { VernacSynPure (VernacSetStrategy l) } (* Canonical structure *) | IDENT "Canonical"; OPT [ IDENT "Structure" -> {()} ]; qid = global; ud = OPT [ u = OPT univ_decl; d = def_body -> { (u,d) } ] -> { match ud with | None -> VernacSynPure (VernacCanonical CAst.(make ?loc:qid.CAst.loc @@ AN qid)) | Some (u,d) -> let s = coerce_reference_to_id qid in VernacSynPure (VernacDefinition ((NoDischarge,CanonicalStructure),((CAst.make ?loc:qid.CAst.loc (Name s)),u),d)) } | IDENT "Canonical"; OPT [ IDENT "Structure" -> {()} ]; ntn = by_notation -> { VernacSynPure (VernacCanonical CAst.(make ~loc @@ ByNotation ntn)) } (* Coercions *) | IDENT "Coercion"; qid = global; ud = OPT [ u = OPT univ_decl; d = def_body -> { u, d } ] -> { match ud with Some (u, d) -> let s = coerce_reference_to_id qid in VernacSynPure (VernacDefinition ((NoDischarge,Coercion),((CAst.make ?loc:qid.CAst.loc (Name s)),u),d)) | None -> VernacSynPure (VernacCoercion (CAst.make ~loc @@ AN qid, None)) } | IDENT "Identity"; IDENT "Coercion"; f = identref; ":"; s = coercion_class; ">->"; t = coercion_class -> { VernacSynPure (VernacIdentityCoercion (f, s, t)) } | IDENT "Coercion"; qid = global; ":"; s = coercion_class; ">->"; t = coercion_class -> { VernacSynPure (VernacCoercion (CAst.make ~loc @@ AN qid, Some(s, t))) } | IDENT "Coercion"; ntn = by_notation; ":"; s = coercion_class; ">->"; t = coercion_class -> { VernacSynPure (VernacCoercion (CAst.make ~loc @@ ByNotation ntn, Some (s, t))) } | IDENT "Context"; c = LIST1 binder -> { VernacSynPure (VernacContext (List.flatten c)) } | IDENT "Instance"; namesup = instance_name; ":"; t = term LEVEL "200"; info = hint_info ; props = [ ":="; "{"; r = record_declaration; "}" -> { Some (true,r) } | ":="; c = lconstr -> { Some (false,c) } | -> { None } ] -> { VernacSynPure (VernacInstance (fst namesup,snd namesup,t,props,info)) } | IDENT "Existing"; IDENT "Instance"; id = global; info = hint_info -> { VernacSynPure (VernacExistingInstance [id, info]) } | IDENT "Existing"; IDENT "Instances"; ids = LIST1 global; pri = OPT [ "|"; i = natural -> { i } ] -> { let info = { Typeclasses.hint_priority = pri; hint_pattern = None } in let insts = List.map (fun i -> (i, info)) ids in VernacSynPure (VernacExistingInstance insts) } | IDENT "Existing"; IDENT "Class"; is = global -> { VernacSynPure (VernacExistingClass is) } (* Arguments *) | IDENT "Arguments"; qid = smart_global; args = LIST0 arg_specs; more_implicits = OPT [ ","; impl = LIST1 [ impl = LIST0 implicits_alt -> { List.flatten impl } ] SEP "," -> { impl } ]; mods = OPT [ ":"; l = LIST1 args_modifier SEP "," -> { l } ] -> { let mods = match mods with None -> [] | Some l -> List.flatten l in let more_implicits = Option.default [] more_implicits in VernacSynPure (VernacArguments (qid, List.flatten args, more_implicits, mods)) } | IDENT "Implicit"; "Type"; bl = reserv_list -> { VernacSynPure (VernacReserve bl) } | IDENT "Implicit"; IDENT "Types"; bl = reserv_list -> { test_plural_form_types loc "Implicit Types" bl; VernacSynPure (VernacReserve bl) } | IDENT "Generalizable"; gen = [IDENT "All"; IDENT "Variables" -> { Some [] } | IDENT "No"; IDENT "Variables" -> { None } | ["Variable" -> { () } | IDENT "Variables" -> { () } ]; idl = LIST1 identref -> { Some idl } ] -> { VernacSynPure (VernacGeneralizable gen) } ] ] ; args_modifier: [ [ IDENT "simpl"; IDENT "nomatch" -> { [`SimplDontExposeCase] } | IDENT "simpl"; IDENT "never" -> { [`SimplNeverUnfold] } | IDENT "clear"; IDENT "simpl" -> { [`ClearReduction] } | IDENT "default"; IDENT "implicits" -> { [`DefaultImplicits] } | IDENT "clear"; IDENT "implicits" -> { [`ClearImplicits] } | IDENT "clear"; IDENT "scopes" -> { [`ClearScopes] } | IDENT "clear"; IDENT "bidirectionality"; IDENT "hint" -> { [`ClearBidiHint] } | IDENT "rename" -> { [`Rename] } | IDENT "assert" -> { [`Assert] } | IDENT "extra"; IDENT "scopes" -> { [`ExtraScopes] } | IDENT "clear"; IDENT "scopes"; IDENT "and"; IDENT "implicits" -> { [`ClearImplicits; `ClearScopes] } | IDENT "clear"; IDENT "implicits"; IDENT "and"; IDENT "scopes" -> { [`ClearImplicits; `ClearScopes] } ] ] ; scope_delimiter: [ [ "%"; key = IDENT -> { DelimUnboundedScope, key } | "%_"; key = IDENT -> { DelimOnlyTmpScope, key } ] ] ; argument_spec: [ [ b = OPT "!"; id = name ; s = LIST0 scope_delimiter -> { id.CAst.v, not (Option.is_empty b), List.map (fun x -> CAst.make ~loc x) s } ] ]; (* List of arguments implicit status, scope, modifiers *) arg_specs: [ [ item = argument_spec -> { let name, recarg_like, notation_scope = item in [RealArg { name=name; recarg_like=recarg_like; notation_scope=notation_scope; implicit_status = Explicit}] } | "/" -> { [VolatileArg] } | "&" -> { [BidiArg] } | "("; items = LIST1 argument_spec; ")"; scl = LIST0 scope_delimiter -> { let scl = List.map (CAst.make ~loc) scl in List.map (fun (name,recarg_like,notation_scope) -> RealArg { name=name; recarg_like=recarg_like; notation_scope = notation_scope @ scl; implicit_status = Explicit}) items } | "["; items = LIST1 argument_spec; "]"; scl = LIST0 scope_delimiter -> { let scl = List.map (CAst.make ~loc) scl in List.map (fun (name,recarg_like,notation_scope) -> RealArg { name=name; recarg_like=recarg_like; notation_scope = notation_scope @ scl; implicit_status = NonMaxImplicit}) items } | "{"; items = LIST1 argument_spec; "}"; scl = LIST0 scope_delimiter -> { let scl = List.map (CAst.make ~loc) scl in List.map (fun (name,recarg_like,notation_scope) -> RealArg { name=name; recarg_like=recarg_like; notation_scope = notation_scope @ scl; implicit_status = MaxImplicit}) items } ] ]; (* Same as [arg_specs], but with only implicit status and names *) implicits_alt: [ [ name = name -> { [(name.CAst.v, Explicit)] } | "["; items = LIST1 name; "]" -> { List.map (fun name -> (name.CAst.v, NonMaxImplicit)) items } | "{"; items = LIST1 name; "}" -> { List.map (fun name -> (name.CAst.v, MaxImplicit)) items } ] ]; instance_name: [ [ name = ident_decl; bl = binders -> { (CAst.map (fun id -> Name id) (fst name), snd name), bl } | -> { ((CAst.make ~loc Anonymous), None), [] } ] ] ; hint_info: [ [ "|"; i = OPT natural; pat = OPT constr_pattern -> { { Typeclasses.hint_priority = i; hint_pattern = pat } } | -> { { Typeclasses.hint_priority = None; hint_pattern = None } } ] ] ; reserv_list: [ [ bl = LIST1 reserv_tuple -> { bl } | b = simple_reserv -> { [b] } ] ] ; reserv_tuple: [ [ "("; a = simple_reserv; ")" -> { a } ] ] ; simple_reserv: [ [ idl = LIST1 identref; ":"; c = lconstr -> { (idl,c) } ] ] ; END { (* Hack to parse "[ id" without dropping [ *) let test_bracket_ident = let open Procq.Lookahead in to_entry "test_bracket_ident" begin lk_kw "[" >> lk_ident end } GRAMMAR EXTEND Gram GLOBAL: toplevel_selector goal_selector; range_selector: [ [ n = natural ; "-" ; m = natural -> { Proofview.RangeSelector (n, m) } | n = natural -> { Proofview.NthSelector n } | test_bracket_ident; "["; id = qualid; "]" -> { Proofview.IdSelector id } ] ] ; goal_selector: [ [ l = LIST1 range_selector SEP "," -> { Goal_select.SelectList l } ] ] ; toplevel_selector: [ [ sel = goal_selector; ":" -> { sel } | "!"; ":" -> { Goal_select.SelectAlreadyFocused } | IDENT "all"; ":" -> { Goal_select.SelectAll } ] ] ; END GRAMMAR EXTEND Gram GLOBAL: command query_command coercion_class gallina_ext search_query search_queries; gallina_ext: TOP [ [ IDENT "Export"; "Set"; table = setting_name; v = option_setting -> { VernacSynterp (VernacSetOption (true, table, v)) } | IDENT "Export"; IDENT "Unset"; table = setting_name -> { VernacSynterp (VernacSetOption (true, table, OptionUnset)) } ] ]; command: [ [ IDENT "Comments"; l = LIST0 comment -> { VernacSynPure (VernacComments l) } | IDENT "Attributes"; attr = attribute_list -> { VernacSynPure (VernacAttributes attr) } (* Hack! Should be in grammar_ext, but camlp5 factorizes badly *) | IDENT "Declare"; IDENT "Instance"; id = ident_decl; bl = binders; ":"; t = term LEVEL "200"; info = hint_info -> { VernacSynPure (VernacDeclareInstance (id, bl, t, info)) } (* Should be in syntax, but camlp5 would not factorize *) | IDENT "Declare"; IDENT "Scope"; sc = IDENT -> { VernacSynPure (VernacDeclareScope sc) } (* System directory *) | IDENT "Pwd" -> { VernacSynterp (VernacChdir None) } | IDENT "Cd" -> { warn_chdir_pwd (); VernacSynterp (VernacChdir None) } | IDENT "Cd"; dir = ne_string -> { VernacSynterp (VernacChdir (Some dir)) } | IDENT "Load"; verbosely = [ IDENT "Verbose" -> { true } | -> { false } ]; s = [ s = ne_string -> { s } | s = IDENT -> { s } ] -> { VernacSynterp (VernacLoad (verbosely, s)) } | IDENT "Declare"; IDENT "ML"; IDENT "Module"; l = LIST1 ne_string -> { VernacSynterp (VernacDeclareMLModule l) } | IDENT "Locate"; l = locatable -> { VernacSynPure (VernacLocate l) } (* Type-Checking *) | "Type"; c = lconstr -> { VernacSynPure (VernacGlobalCheck c) } (* Printing (careful factorization of entries) *) | IDENT "Print"; p = printable -> { VernacSynPure (VernacPrint p) } | IDENT "Print"; qid = smart_global; l = OPT univ_name_list -> { VernacSynPure (VernacPrint (PrintName (qid,l))) } | IDENT "Print"; IDENT "Module"; "Type"; qid = global -> { VernacSynPure (VernacPrint (PrintModuleType qid)) } | IDENT "Print"; IDENT "Module"; qid = global -> { VernacSynPure (VernacPrint (PrintModule qid)) } | IDENT "Print"; IDENT "Namespace" ; ns = dirpath -> { VernacSynPure (VernacPrint (PrintNamespace ns)) } | IDENT "Inspect"; n = natural -> { VernacSynPure (VernacPrint (PrintInspect n)) } (* For acting on parameter tables *) | "Set"; table = setting_name; v = option_setting -> { VernacSynterp (VernacSetOption (false, table, v)) } | IDENT "Unset"; table = setting_name -> { VernacSynterp (VernacSetOption (false, table, OptionUnset)) } | IDENT "Print"; IDENT "Table"; table = setting_name -> { VernacSynPure (VernacPrintOption table) } | IDENT "Add"; table = IDENT; field = IDENT; v = LIST1 table_value -> { VernacSynPure (VernacAddOption ([table;field], v)) } (* A global value below will be hidden by a field above! *) (* In fact, we give priority to secondary tables *) (* No syntax for tertiary tables due to conflict *) (* (but they are unused anyway) *) | IDENT "Add"; table = IDENT; v = LIST1 table_value -> { VernacSynPure (VernacAddOption ([table], v)) } | IDENT "Test"; table = setting_name; "for"; v = LIST1 table_value -> { VernacSynPure (VernacMemOption (table, v)) } | IDENT "Test"; table = setting_name -> { VernacSynPure (VernacPrintOption table) } | IDENT "Remove"; table = IDENT; field = IDENT; v= LIST1 table_value -> { VernacSynPure (VernacRemoveOption ([table;field], v)) } | IDENT "Remove"; table = IDENT; v = LIST1 table_value -> { VernacSynPure (VernacRemoveOption ([table], v)) } ]] ; query_command: [ [ IDENT "Eval"; r = red_expr; "in"; c = lconstr; "." -> { fun g -> VernacCheckMayEval (Some r, g, c) } | IDENT "Compute"; c = lconstr; "." -> { fun g -> VernacCheckMayEval (Some (Genredexpr.CbvVm None), g, c) } | IDENT "Check"; c = lconstr; "." -> { fun g -> VernacCheckMayEval (None, g, c) } (* Searching the environment *) | IDENT "About"; qid = smart_global; l = OPT univ_name_list; "." -> { fun g -> VernacPrint (PrintAbout (qid,l,g)) } | IDENT "SearchPattern"; c = constr_pattern; l = in_or_out_modules; "." -> { fun g -> VernacSearch (SearchPattern c,g, l) } | IDENT "SearchRewrite"; c = constr_pattern; l = in_or_out_modules; "." -> { fun g -> VernacSearch (SearchRewrite c,g, l) } | IDENT "Search"; s = search_query; l = search_queries; "." -> { let (sl,m) = l in fun g -> VernacSearch (Search (s::sl),g, m) } ] ] ; printable: [ [ IDENT "Term"; qid = smart_global; l = OPT univ_name_list -> { PrintName (qid,l) } | IDENT "All" -> { PrintFullContext } | IDENT "Section"; s = global -> { PrintSectionContext s } | IDENT "Grammar"; ents = LIST0 IDENT -> (* This should be in "syntax" section but is here for factorization*) { PrintGrammar ents } | IDENT "Custom"; IDENT "Grammar"; ent = qualid -> (* Should also be in "syntax" section *) { PrintCustomGrammar ent } | IDENT "Keywords" -> { PrintKeywords } | IDENT "LoadPath"; dir = OPT dirpath -> { PrintLoadPath dir } | IDENT "Libraries" -> { PrintLibraries } | IDENT "Notation"; ntn = string -> { PrintNotation (Constrexpr.InConstrEntry, ntn) } | IDENT "Notation"; ntn = string; IDENT "in"; IDENT "custom"; ent = qualid -> { PrintNotation (Constrexpr.InCustomEntry ent, ntn) } | IDENT "ML"; IDENT "Path" -> { PrintMLLoadPath } | IDENT "ML"; IDENT "Modules" -> { PrintMLModules } | IDENT "Debug"; IDENT "GC" -> { PrintDebugGC } | IDENT "Graph" -> { PrintGraph } | IDENT "Classes" -> { PrintClasses } | IDENT "Typeclasses" -> { PrintTypeclasses } | IDENT "Instances"; qid = smart_global -> { PrintInstances qid } | IDENT "Coercions" -> { PrintCoercions } | IDENT "Coercion"; IDENT "Paths"; s = coercion_class; t = coercion_class -> { PrintCoercionPaths (s,t) } | IDENT "Canonical"; IDENT "Projections"; qids = LIST0 smart_global -> { PrintCanonicalConversions qids } | IDENT "Typing"; IDENT "Flags" -> { PrintTypingFlags } | IDENT "Tables" -> { PrintTables } | IDENT "Options" -> { PrintTables (* A Synonymous to Tables *) } | IDENT "Hint" -> { PrintHintGoal } | IDENT "Hint"; qid = smart_global -> { PrintHint qid } | IDENT "Hint"; "*" -> { PrintHintDb } | IDENT "HintDb"; s = IDENT -> { PrintHintDbName s } | IDENT "Scopes" -> { PrintScopes } | IDENT "Scope"; s = IDENT -> { PrintScope s } | IDENT "Visibility"; s = OPT IDENT -> { PrintVisibility s } | IDENT "Implicit"; qid = smart_global -> { PrintImplicit qid } | b = [ IDENT "Sorted" -> { true } | -> { false } ]; IDENT "Universes"; g = OPT printunivs_subgraph; with_sources = OPT [ b = [ IDENT "With" -> { true } | IDENT "Without" -> { false } ]; IDENT "Constraint"; IDENT "Sources" -> { b } ]; fopt = OPT ne_string -> { PrintUniverses {sort=b; subgraph=g; with_sources; file=fopt;} } | IDENT "Sorts" -> { PrintSorts } | IDENT "Assumptions"; qids = LIST1 smart_global -> { PrintAssumptions (false, false, qids) } | IDENT "Opaque"; IDENT "Dependencies"; qids = LIST1 smart_global -> { PrintAssumptions (true, false, qids) } | IDENT "Transparent"; IDENT "Dependencies"; qids = LIST1 smart_global -> { PrintAssumptions (false, true, qids) } | IDENT "All"; IDENT "Dependencies"; qids = LIST1 smart_global -> { PrintAssumptions (true, true, qids) } | IDENT "Strategy"; qid = smart_global -> { PrintStrategy (Some qid) } | IDENT "Strategies" -> { PrintStrategy None } | IDENT "Registered" -> { PrintRegistered } | IDENT "Registered"; IDENT "Schemes" -> { PrintRegisteredSchemes } ] ] ; debug_univ_name: [ [ x = reference -> { NamedUniv x } | x = STRING -> { RawUniv (CAst.make ~loc x) } ] ] ; printunivs_subgraph: [ [ IDENT "Subgraph"; "("; l = LIST0 debug_univ_name; ")" -> { l } ] ] ; coercion_class: [ [ IDENT "Funclass" -> { FunClass } | IDENT "Sortclass" -> { SortClass } | qid = smart_global -> { RefClass qid } ] ] ; locatable: [ [ qid = smart_global -> { LocateAny qid } | IDENT "Term"; qid = smart_global -> { LocateTerm qid } | IDENT "File"; f = ne_string -> { LocateFile f } | IDENT "Library"; qid = global -> { LocateLibrary qid } | IDENT "Module"; qid = global -> { LocateModule qid } ] ] ; option_setting: [ [ -> { OptionSetTrue } | n = integer -> { OptionSetInt n } | s = STRING -> { OptionSetString s } ] ] ; table_value: [ [ id = global -> { Goptions.QualidRefValue id } | s = STRING -> { Goptions.StringRefValue s } ] ] ; setting_name: [ [ fl = LIST1 [ x = IDENT -> { x } ] -> { fl } ]] ; ne_in_or_out_modules: [ [ IDENT "inside"; l = LIST1 global -> { SearchInside l } | "in"; l = LIST1 global -> { SearchInside l } | IDENT "outside"; l = LIST1 global -> { SearchOutside l } ] ] ; in_or_out_modules: [ [ m = ne_in_or_out_modules -> { m } | -> { SearchOutside [] } ] ] ; comment: [ [ c = constr -> { CommentConstr c } | s = STRING -> { CommentString s } | n = natural -> { CommentInt n } ] ] ; positive_search_mark: [ [ "-" -> { false } | -> { true } ] ] ; search_query: [ [ b = positive_search_mark; s = search_item -> { (b, SearchLiteral s) } | b = positive_search_mark; "["; l = LIST1 (LIST1 search_query) SEP "|"; "]" -> { (b, SearchDisjConj l) } ] ] ; search_item: [ [ test_id_colon; where = search_where; ":"; s = ne_string; sc = OPT scope_delimiter -> { SearchString (where,s,sc) } | IDENT "is"; ":"; kl = logical_kind -> { SearchKind kl } | s = ne_string; sc = OPT scope_delimiter -> { SearchString ((Anywhere,false),s,sc) } | test_id_colon; where = search_where; ":"; p = constr_pattern -> { SearchSubPattern (where,p) } | p = constr_pattern -> { SearchSubPattern ((Anywhere,false),p) } ] ] ; logical_kind: [ [ k = thm_token -> { IsProof k } | k = assumption_token -> { IsAssumption (snd k) } | k = IDENT "Context" -> { IsAssumption Context } | k = extended_def_token -> { IsDefinition k } | IDENT "Primitive" -> { IsPrimitive } | IDENT "Symbol" -> { IsSymbol } ] ] ; extended_def_token: [ [ k = def_token -> { snd k } | IDENT "Coercion" -> { Coercion } | IDENT "Fixpoint" -> { Fixpoint } | IDENT "CoFixpoint" -> { CoFixpoint } | IDENT "Instance" -> { Instance } | IDENT "Scheme" -> { Scheme } | IDENT "Canonical" -> { CanonicalStructure } | IDENT "Field" -> { StructureComponent } | IDENT "Method" -> { Method } ] ] ; search_where: [ [ IDENT "head" -> { Anywhere, true } | IDENT "hyp" -> { InHyp, false } | IDENT "concl" -> { InConcl, false } | IDENT "headhyp" -> { InHyp, true } | IDENT "headconcl" -> { InConcl, true } ] ] ; search_queries: [ RIGHTA [ m = ne_in_or_out_modules -> { ([],m) } | s = search_query; l = search_queries -> { let (sl,m) = l in (s::sl,m) } | -> { ([],SearchOutside []) } ] ] ; univ_name_list: [ [ "@{" ; l = LIST0 name; "}" -> { [],l } ] ] ; END GRAMMAR EXTEND Gram GLOBAL: command; command: TOP [ [ (* Resetting *) IDENT "Reset"; IDENT "Initial" -> { VernacSynPure (VernacResetInitial) } | IDENT "Reset"; id = identref -> { VernacSynPure (VernacResetName id) } | IDENT "Back" -> { VernacSynPure (VernacBack 1) } | IDENT "Back"; n = natural -> { VernacSynPure (VernacBack n) } (* Tactic Debugger *) | IDENT "Debug"; IDENT "On" -> { VernacSynterp (VernacSetOption (false, ["Ltac";"Debug"], OptionSetTrue)) } | IDENT "Debug"; IDENT "Off" -> { VernacSynterp (VernacSetOption (false, ["Ltac";"Debug"], OptionUnset)) } (* registration of a custom reduction *) | IDENT "Declare"; IDENT "Reduction"; s = IDENT; ":="; r = red_expr -> { VernacSynPure (VernacDeclareReduction (s,r)) } (* factorized here, though relevant for syntax extensions *) | IDENT "Declare"; IDENT "Custom"; IDENT "Entry"; s = ident -> { VernacSynterp (VernacDeclareCustomEntry s) } ] ]; END (* Grammar extensions *) GRAMMAR EXTEND Gram GLOBAL: syntax syntax_modifiers; syntax: [ [ IDENT "Open"; IDENT "Scope"; sc = IDENT -> { VernacSynPure (VernacOpenCloseScope (true,sc)) } | IDENT "Close"; IDENT "Scope"; sc = IDENT -> { VernacSynPure (VernacOpenCloseScope (false,sc)) } | IDENT "Delimit"; IDENT "Scope"; sc = IDENT; "with"; key = IDENT -> { VernacSynPure(VernacDelimiters (sc, Some key)) } | IDENT "Undelimit"; IDENT "Scope"; sc = IDENT -> { VernacSynPure(VernacDelimiters (sc, None)) } | IDENT "Bind"; IDENT "Scope"; sc = IDENT; "with"; refl = LIST1 coercion_class -> { VernacSynPure (VernacBindScope (sc,refl)) } | IDENT "Infix"; ntn_decl = notation_declaration -> { VernacSynterp (VernacNotation (true,ntn_decl)) } | lnot = located_notation; id = identref; idl = LIST0 ident; ":="; c = constr; modl = syntax_modifiers -> { VernacSynPure (VernacAbbreviation (id,(idl,c), modl, Some lnot)) } | IDENT "Abbreviation"; id = identref; idl = LIST0 ident; ":="; c = constr; modl = syntax_modifiers -> { VernacSynPure (VernacAbbreviation (id,(idl,c), modl, None)) } | located_notation; ntn_decl = notation_declaration -> { VernacSynterp (VernacNotation (false,ntn_decl)) } | IDENT "Reserved"; IDENT "Infix"; s = ne_lstring; l = syntax_modifiers -> { VernacSynterp (VernacReservedNotation (true,(s,l))) } | IDENT "Reserved"; IDENT "Notation"; s = ne_lstring; l = syntax_modifiers -> { VernacSynterp (VernacReservedNotation (false,(s,l))) } | on = enable_enable_disable; IDENT "Notation"; rule = enable_notation_rule; interp = enable_notation_interpretation; flags = enable_notation_flags; scope = opt_scope -> { VernacSynPure (VernacEnableNotation (on, rule, interp, flags, scope)) } (* "Print" "Grammar" and "Declare" "Scope" should be here but are in "command" entry in order to factorize with other "Print"-based or "Declare"-based vernac entries *) ] ] ; located_notation: [ [ IDENT "Notation" -> { loc } ] ] ; enable_enable_disable: [ [ IDENT "Enable" -> { true } | IDENT "Disable" -> { false } ] ] ; enable_notation_rule: [ [ s = ne_string -> { Some (Inl s) } | qid = global; idl = LIST0 ident -> { Some (Inr (idl,qid)) } | -> { None } ] ] ; enable_notation_interpretation: [ [ ":="; c = constr -> { Some c } | -> { None } ] ] ; enable_notation_flags: [ [ "("; l = LIST1 enable_notation_flag SEP ","; ")" -> { l } | -> { [] } ] ] ; enable_notation_flag: [ [ IDENT "all" -> { EnableNotationAll } | IDENT "only"; IDENT "parsing" -> { EnableNotationOnly Notationextern.OnlyParsing } | IDENT "only"; IDENT "printing" -> { EnableNotationOnly Notationextern.OnlyPrinting } | "in"; IDENT "custom"; x = qualid -> { EnableNotationEntry (InCustomEntry x) } | "in"; IDENT "constr" -> { EnableNotationEntry InConstrEntry } ] ] ; opt_scope: [ [ ":"; sc = IDENT -> { Some (NotationInScope sc) } | ":"; IDENT "no"; IDENT "scope" -> { Some LastLonelyNotation } | -> { None } ] ] ; level: [ [ IDENT "level"; n = natural -> { NumLevel n } | IDENT "next"; IDENT "level" -> { NextLevel } ] ] ; syntax_modifier: [ [ "at"; IDENT "level"; n = natural -> { SetLevel n } | "in"; IDENT "custom"; x = qualid -> { SetCustomEntry (x,None) } | "in"; IDENT "custom"; x = qualid; "at"; IDENT "level"; n = natural -> { SetCustomEntry (x,Some n) } | IDENT "left"; IDENT "associativity" -> { SetAssoc Gramlib.Gramext.LeftA } | IDENT "right"; IDENT "associativity" -> { SetAssoc Gramlib.Gramext.RightA } | IDENT "no"; IDENT "associativity" -> { SetAssoc Gramlib.Gramext.NonA } | IDENT "only"; IDENT "printing" -> { SetOnlyPrinting } | IDENT "only"; IDENT "parsing" -> { SetOnlyParsing } | IDENT "format"; s = lstring -> { SetFormat (TextFormat s) } | x = IDENT; ","; l = LIST1 IDENT SEP ","; v = [ "at"; lev = level -> { fun x l -> SetItemLevel (x::l,None,lev) } | "in"; IDENT "scope"; k = IDENT -> { fun x l -> SetItemScope(x::l,k) } ] -> { v x l } | x = IDENT; "at"; lev = level; b = OPT binder_interp -> { SetItemLevel ([x],b,lev) } | x = IDENT; "in"; IDENT "scope"; k = IDENT -> { SetItemScope([x],k) } | x = IDENT; b = binder_interp -> { SetItemLevel ([x],Some b,DefaultLevel) } | x = IDENT; typ = explicit_subentry -> { SetEntryType (x,typ) } ] ] ; syntax_modifiers: [ [ "("; l = LIST1 [ s = syntax_modifier -> { CAst.make ~loc s } ] SEP ","; ")" -> { l } | -> { [] } ] ] ; explicit_subentry: [ [ IDENT "ident" -> { ETIdent } | IDENT "name" -> { ETName } | IDENT "global" -> { ETGlobal } | IDENT "bigint" -> { ETBigint } | IDENT "binder" -> { ETBinder true } | IDENT "constr" -> { ETConstr (InConstrEntry,None,DefaultLevel) } | IDENT "constr"; n = at_level_opt; b = OPT binder_interp -> { ETConstr (InConstrEntry,b,n) } | IDENT "pattern" -> { ETPattern (false,None) } | IDENT "pattern"; "at"; IDENT "level"; n = natural -> { ETPattern (false,Some n) } | IDENT "strict"; IDENT "pattern" -> { ETPattern (true,None) } | IDENT "strict"; IDENT "pattern"; "at"; IDENT "level"; n = natural -> { ETPattern (true,Some n) } | IDENT "closed"; IDENT "binder" -> { ETBinder false } | IDENT "custom"; x = qualid; n = at_level_opt; b = OPT binder_interp -> { ETConstr (InCustomEntry x,b,n) } ] ] ; at_level_opt: [ [ "at"; n = level -> { n } | -> { DefaultLevel } ] ] ; binder_interp: [ [ "as"; IDENT "ident" -> { warn_deprecated_as_ident_kind (); Notation_term.AsIdent } | "as"; IDENT "name" -> { Notation_term.AsName } | "as"; IDENT "pattern" -> { Notation_term.AsAnyPattern } | "as"; IDENT "strict"; IDENT "pattern" -> { Notation_term.AsStrictPattern } ] ] ; END rocq-9.2.0/vernac/g_vernac.mli000066400000000000000000000047511516144147600162530ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Vernacexpr.synpure_vernac_expr) Procq.Entry.t val search_query : (bool * Vernacexpr.search_request) Procq.Entry.t val search_queries : ((bool * Vernacexpr.search_request) list * Libnames.qualid list Vernacexpr.search_restriction) Procq.Entry.t val subprf : Vernacexpr.synpure_vernac_expr Procq.Entry.t val subprf_with_selector : (Goal_select.t option -> Vernacexpr.synpure_vernac_expr) Procq.Entry.t val quoted_attributes : Attributes.vernac_flags Procq.Entry.t val coercion_class : Vernacexpr.coercion_class Procq.Entry.t val thm_token : Decls.theorem_kind Procq.Entry.t val def_token : (Vernacexpr.discharge * Decls.definition_object_kind) Procq.Entry.t val assumption_token : (Vernacexpr.discharge * Decls.assumption_object_kind) Procq.Entry.t val def_body : Vernacexpr.definition_expr Procq.Entry.t val notation_declaration : Vernacexpr.notation_declaration Procq.Entry.t val decl_notations : Vernacexpr.notation_declaration list Procq.Entry.t val record_field : (Vernacexpr.local_decl_expr * Vernacexpr.record_field_attr_unparsed) Procq.Entry.t val of_type : Vernacexpr.coercion_flag Procq.Entry.t val of_type_inst : (Vernacexpr.coercion_flag * Vernacexpr.instance_flag) Procq.Entry.t val section_subset_expr : Vernacexpr.section_subset_expr Procq.Entry.t val scope_delimiter : Vernacexpr.scope_delimiter Procq.Entry.t val syntax_modifiers : Vernacexpr.syntax_modifier CAst.t list Procq.Entry.t val make_bullet : string -> Proof_bullet.t val test_hash_ident : unit Procq.Entry.t val test_id_colon : unit Procq.Entry.t val warn_plural_command : ?loc:Loc.t -> string -> unit val test_variance_ident : unit Procq.Entry.t val test_only_starredidentrefs : unit Procq.Entry.t val goal_selector : Goal_select.t Procq.Entry.t val toplevel_selector : Goal_select.t Procq.Entry.t rocq-9.2.0/vernac/himsg.ml000066400000000000000000002375041516144147600154310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* l := (Vars.substl !l c') :: !l; env | _ -> let t = Vars.substl !l (RelDecl.get_type decl) in let decl = decl |> RelDecl.map_name (named_hd env sigma t) |> RelDecl.map_value (Vars.substl !l) |> RelDecl.set_type t in l := (mkRel 1) :: List.map (Vars.lift 1) !l; push_rel decl env in let env = process_rel_context contract_context env in (env, List.map (Vars.substl !l) lc) let contract2 env sigma a b = match contract env sigma [a;b] with | env, [a;b] -> env,a,b | _ -> assert false let contract3 env sigma a b c = match contract env sigma [a;b;c] with | env, [a;b;c] -> env,a,b,c | _ -> assert false let contract4 env sigma a b c d = match contract env sigma [a;b;c;d] with | env, [a;b;c;d] -> (env,a,b,c),d | _ -> assert false let contract1 env sigma a v = match contract env sigma (a :: v) with | env, a::l -> env,a,l | _ -> assert false let rec contract3' env sigma a b c = function | OccurCheck (evk,d) -> let x,d = contract4 env sigma a b c d in x,OccurCheck(evk, d) | NotClean ((evk,args),env',d) -> let args = Evd.expand_existential sigma (evk, args) in let env',d,args = contract1 env' sigma d args in let args = SList.of_full_list args in contract3 env sigma a b c,NotClean((evk,args),env',d) | ConversionFailed (env',t1,t2) -> let (env',t1,t2) = contract2 env' sigma t1 t2 in contract3 env sigma a b c, ConversionFailed (env',t1,t2) | IncompatibleInstances (env',ev,t1,t2) -> let (env',ev,t1,t2) = contract3 env' sigma (EConstr.mkEvar ev) t1 t2 in contract3 env sigma a b c, IncompatibleInstances (env',EConstr.destEvar sigma ev,t1,t2) | NotSameArgSize | NotSameHead | NoCanonicalStructure | MetaOccurInBody _ | InstanceNotSameType _ | InstanceNotFunctionalType _ | ProblemBeyondCapabilities | UnifUnivInconsistency _ as x -> contract3 env sigma a b c, x | CannotSolveConstraint ((pb,env',t,u),x) -> let env',t,u = contract2 env' sigma t u in let y,x = contract3' env sigma a b c x in y,CannotSolveConstraint ((pb,env',t,u),x) (** Ad-hoc reductions *) let j_nf_betaiotaevar env sigma j = { uj_val = j.uj_val; uj_type = Reductionops.nf_betaiota env sigma j.uj_type } let jv_nf_betaiotaevar env sigma jl = Array.Smart.map (fun j -> j_nf_betaiotaevar env sigma j) jl (** Printers *) let pr_lconstr_env e s c = quote (pr_lconstr_env e s c) let pr_leconstr_env e s c = quote (pr_leconstr_env e s c) let pr_ljudge_env e s c = let v,t = pr_ljudge_env e s c in (quote v,quote t) (* Make the printer robust to missing globrefs *) let pr_global gr = try pr_global gr with Not_found -> GlobRef.print gr (** A canonisation procedure for constr such that comparing there externalisation catches more equalities *) let canonize_constr sigma c = (* replaces all the names in binders by [dn] ("default name"), ensures that [alpha]-equivalent terms will have the same externalisation. *) let open EConstr in let dn = Name.Anonymous in let rec canonize_binders c = match EConstr.kind sigma c with | Prod (x,t,b) -> mkProd({x with binder_name=dn},t,b) | Lambda (x,t,b) -> mkLambda({x with binder_name=dn},t,b) | LetIn (x,u,t,b) -> mkLetIn({x with binder_name=dn},u,t,b) | _ -> EConstr.map sigma canonize_binders c in canonize_binders c let rec display_expr_eq c1 c2 = let open Constrexpr in match CAst.(c1.v, c2.v) with | (CHole _ | CEvar _), _ | _, (CEvar _ | CHole _) -> true | _ -> Constrexpr_ops.constr_expr_eq_gen display_expr_eq c1 c2 let safe_extern_constr ~flags env sigma t = Printer.safe_extern_wrapper begin fun env sigma () -> Constrextern.extern_constr ~flags env sigma t end env sigma () (** Tries to realize when the two terms, albeit different are printed the same. *) let display_eq ~flags env sigma t1 t2 = (* terms are canonized, then their externalisation is compared syntactically *) let t1 = canonize_constr sigma t1 in let t2 = canonize_constr sigma t2 in let ct1 = safe_extern_constr ~flags env sigma t1 in let ct2 = safe_extern_constr ~flags env sigma t2 in match ct1, ct2 with | None, None -> false | Some _, None | None, Some _ -> false | Some ct1, Some ct2 -> display_expr_eq ct1 ct2 (** This function adds some explicit printing flags if the two arguments are printed alike. *) let rec pr_explicit_aux env sigma t1 t2 = function | [] -> (* no specified flags: default. *) Printer.pr_leconstr_env env sigma t1, Printer.pr_leconstr_env env sigma t2 | flags :: rem -> let equal = display_eq ~flags env sigma t1 t2 in if equal then (* The two terms are the same from the user point of view *) pr_explicit_aux env sigma t1 t2 rem else let ct1 = safe_extern_constr ~flags env sigma t1 in let ct2 = safe_extern_constr ~flags env sigma t2 in let pr = function | None -> str "??" | Some c -> Ppconstr.pr_lconstr_expr ~flags:(Ppconstr.of_printing_flags flags) env sigma c in pr ct1, pr ct2 let explicit_flags () = let open PrintingFlags in let with_implicits flags = { flags with extern = { flags.extern with implicits = true } } in let with_universes flags = { flags with detype = { flags.detype with universes = true } } in let with_coe_nosymb flags = { flags with extern = { flags.extern with coercions = true; notations = false } } in let flags = PrintingFlags.current() in [ flags; (* First, try with the current flags *) with_implicits flags; (* Then with implicit *) with_universes flags; (* Then with universes *) with_universes @@ with_implicits flags; (* With universes AND implicits *) with_implicits @@ with_coe_nosymb flags; (* Then more! *) with_universes @@ with_implicits @@ with_coe_nosymb flags (* and more! *) ] let with_diffs pm pn = if not (Proof_diffs.show_diffs ()) then pm, pn else try let tokenize_string = Proof_diffs.tokenize_string in Pp_diff.diff_pp ~tokenize_string pm pn with Pp_diff.Diff_Failure msg -> begin try ignore(Sys.getenv("HIDEDIFFFAILUREMSG")) with Not_found -> Proof_diffs.notify_proof_diff_failure msg end; pm, pn let pr_explicit env sigma t1 t2 = let p1, p2 = pr_explicit_aux env sigma t1 t2 (explicit_flags()) in let p1, p2 = with_diffs p1 p2 in quote p1, quote p2 let pr_db env i = try match env |> lookup_rel i |> get_name with | Name id -> Id.print id | Anonymous -> str "<>" with Not_found -> str "UNBOUND_REL_" ++ int i let explain_unbound_rel env sigma n = if n > 0 then let pe = pr_ne_context_of (str "In environment") env sigma in str "Unbound reference: " ++ pe ++ str "The reference " ++ int n ++ str " is free." else str "Invalid Rel " ++ int n ++ (if n = 0 then str ": local references are 1-indexed" else mt()) ++ str " (bugged tactic?)." let explain_unbound_var env v = let var = Id.print v in str "No such section variable or assumption: " ++ var ++ str "." let explain_not_type env sigma j = let pe = pr_ne_context_of (str "In environment") env sigma in let pc,pt = pr_ljudge_env env sigma j in pe ++ str "The term" ++ brk(1,1) ++ pc ++ spc () ++ str "has type" ++ spc () ++ pt ++ spc () ++ str "which should be Set, Prop or Type." let explain_bad_assumption env sigma j = let pe = pr_ne_context_of (str "In environment") env sigma in let pc,pt = pr_ljudge_env env sigma j in pe ++ str "Cannot declare a variable or hypothesis over the term" ++ brk(1,1) ++ pc ++ spc () ++ str "of type" ++ spc () ++ pt ++ spc () ++ str "because this term is not a type." let explain_reference_variables sigma id c = pr_global c ++ strbrk " depends on the variable " ++ Id.print id ++ strbrk " which is not declared in the context." let explain_elim_arity env sigma ind c okinds = let open EConstr in let env = make_all_name_different env sigma in let mib, mip as specif = Inductive.lookup_mind_specif env (fst ind) in let pi = let pp () = pr_pinductive env sigma ind in match mip.mind_squashed with | None | Some AlwaysSquashed -> pp () | Some (SometimesSquashed _) -> (* universe instance matters, so print it regardless of Printing Universes *) Flags.with_option PrintingFlags.print_universes pp () in let pc = Option.map (pr_leconstr_env env sigma) c in let msg = match okinds with | None -> str "ill-formed elimination predicate." | Some sp -> let ppt ?(ppunivs=false) () = let pp () = pr_leconstr_env env sigma (mkSort (ESorts.make sp)) in if ppunivs then Flags.with_option PrintingFlags.print_universes pp () else pp () in let g = QGraph.merge (Environ.qualities env) (Evd.elim_graph sigma) in let env = Environ.set_qualities g env in let squash = Option.get (Inductive.is_squashed env (specif, snd ind)) in match squash with | SquashToSet -> let ppt = ppt () in hov 0 (str "the return type has sort" ++ spc () ++ ppt ++ spc () ++ str "while it should be SProp, Prop or Set.") ++ fnl () ++ hov 0 (str "Elimination of an inductive object of sort Set" ++ spc() ++ str "is not allowed on a predicate in sort " ++ ppt ++ fnl () ++ str "because" ++ spc () ++ str "strong elimination on non-small inductive types leads to paradoxes.") | SquashToQuality (QConstant (QSProp | QProp as squashq)) -> let ppt = ppt () in let inds, sorts, explain = match squashq with | QSProp -> "SProp", "SProp", "strict proofs can be eliminated only to build strict proofs" | QProp -> "Prop", "SProp or Prop", "proofs can be eliminated only to build proofs" | QType -> assert false in hov 0 (str "the return type has sort" ++ spc () ++ ppt ++ spc () ++ str "while it should be " ++ str sorts ++ str ".") ++ fnl () ++ hov 0 (str "Elimination of an inductive object of sort " ++ str inds ++ spc() ++ str "is not allowed on a predicate in sort " ++ ppt ++ fnl () ++ str "because" ++ spc () ++ str explain ++ str ".") | SquashToQuality (QConstant QType) -> let ppt = ppt ~ppunivs:true () in hov 0 (str "the return type has sort" ++ spc () ++ ppt ++ spc () ++ str "while it may not be of a variable sort quality.") ++ fnl () ++ hov 0 (str "Elimination of a sort polymorphic inductive object instantiated to sort Type" ++ spc() ++ (* NB: this restriction is only for forward compat with possible future sort qualities *) str "is not allowed on a predicate in a variable sort quality.") | SquashToQuality (QVar squashq) -> let ppt = ppt ~ppunivs:true () in hov 0 (str "the return type has sort" ++ spc () ++ ppt ++ spc () ++ str "while it should be in a sort " ++ pr_evd_qvar sigma squashq ++ str " eliminates to.") ++ fnl () ++ hov 0 (str "Elimination of a sort polymorphic inductive object instantiated to a variable sort quality" ++ spc() ++ str "is only allowed on itself or with an explicit elimination constraint to the target sort.") in hov 0 ( str "Incorrect elimination" ++ (match pc with None -> mt() | Some pc -> str " of" ++ spc () ++ pc) ++ spc () ++ str "in the inductive type" ++ spc () ++ quote pi ++ str ":") ++ fnl () ++ msg let explain_case_not_inductive env sigma cj = let env = make_all_name_different env sigma in let pc = pr_leconstr_env env sigma cj.uj_val in let pct = pr_leconstr_env env sigma cj.uj_type in match EConstr.kind sigma cj.uj_type with | Evar _ -> str "Cannot infer a type for this expression." | _ -> str "The term" ++ brk(1,1) ++ pc ++ spc () ++ str "has type" ++ brk(1,1) ++ pct ++ spc () ++ str "which is not a (co-)inductive type." let explain_case_on_private_ind env sigma ind = str "Case analysis on private inductive "++ pr_inductive env ind ++ str " is not allowed." let explain_number_branches env sigma cj expn = let env = make_all_name_different env sigma in let pc = pr_leconstr_env env sigma cj.uj_val in let pct = pr_leconstr_env env sigma cj.uj_type in str "Matching on term" ++ brk(1,1) ++ pc ++ spc () ++ str "of type" ++ brk(1,1) ++ pct ++ spc () ++ str "expects " ++ int expn ++ str " branches." let explain_ill_formed_case_params env sigma = str "Ill formed case parameters (bugged tactic?)." let explain_ill_formed_branch env sigma c ci actty expty = let simp t = Reductionops.nf_betaiota env sigma t in let env = make_all_name_different env sigma in let pc = pr_leconstr_env env sigma c in let pa, pe = pr_explicit env sigma (simp actty) (simp expty) in strbrk "In pattern-matching on term" ++ brk(1,1) ++ pc ++ spc () ++ strbrk "the branch for constructor" ++ spc () ++ quote (pr_pconstructor env sigma ci) ++ spc () ++ str "has type" ++ brk(1,1) ++ pa ++ spc () ++ str "which should be" ++ brk(1,1) ++ pe ++ str "." let explain_bad_proj_type env sigma cj p = let pc = pr_leconstr_env env sigma cj.uj_val in let pct = pr_leconstr_env env sigma cj.uj_type in let rcd = pr_global (GlobRef.IndRef (Projection.inductive p)) in str "The term" ++ brk(1,1) ++ pc ++ spc () ++ str "has type" ++ brk(1,1) ++ pct ++ spc () ++ str "which is not an instance of record type " ++ rcd ++ str "." let explain_generalization env sigma (name,var) j = let pe = pr_ne_context_of (str "In environment") env sigma in let pv = pr_letype_env env sigma var in let (pc,pt) = pr_ljudge_env (push_rel_assum (make_annot name EConstr.ERelevance.relevant,var) env) sigma j in pe ++ str "Cannot generalize" ++ brk(1,1) ++ pv ++ spc () ++ str "over" ++ brk(1,1) ++ pc ++ str "," ++ spc () ++ str "it has type" ++ spc () ++ pt ++ spc () ++ str "which should be Set, Prop or Type." let explain_unification_error env sigma p1 p2 = function | None -> mt() | Some e -> let rec aux p1 p2 = function | OccurCheck (evk,rhs) -> [str "cannot define " ++ quote (pr_existential_key env sigma evk) ++ strbrk " with term " ++ pr_leconstr_env env sigma rhs ++ strbrk " that would depend on itself"] | NotClean ((evk,args),env,c) -> let args = Evd.expand_existential sigma (evk, args) in let env = make_all_name_different env sigma in [str "cannot instantiate " ++ quote (pr_existential_key env sigma evk) ++ strbrk " because " ++ pr_leconstr_env env sigma c ++ strbrk " is not in its scope" ++ (if List.is_empty args then mt() else strbrk ": available arguments are " ++ pr_sequence (pr_leconstr_env env sigma) (List.rev args))] | NotSameArgSize | NotSameHead | NoCanonicalStructure -> (* Error speaks from itself *) [] | ConversionFailed (env,t1,t2) -> let t1 = Reductionops.nf_betaiota env sigma t1 in let t2 = Reductionops.nf_betaiota env sigma t2 in if EConstr.eq_constr sigma t1 p1 && EConstr.eq_constr sigma t2 p2 then [] else let env = make_all_name_different env sigma in if not (EConstr.eq_constr sigma t1 p1) || not (EConstr.eq_constr sigma t2 p2) then let t1, t2 = pr_explicit env sigma t1 t2 in [str "cannot unify " ++ t1 ++ strbrk " and " ++ t2] else [] | IncompatibleInstances (env,ev,t1,t2) -> let env = make_all_name_different env sigma in let ev = pr_leconstr_env env sigma (EConstr.mkEvar ev) in let t1 = Reductionops.nf_betaiota env sigma t1 in let t2 = Reductionops.nf_betaiota env sigma t2 in let t1, t2 = pr_explicit env sigma t1 t2 in [ev ++ strbrk " has otherwise to unify with " ++ t1 ++ str " which is incompatible with " ++ t2] | MetaOccurInBody evk -> [str "instance for " ++ quote (pr_existential_key env sigma evk) ++ strbrk " refers to a metavariable - please report your example" ++ strbrk "at " ++ str Coq_config.wwwbugtracker ++ str "."] | InstanceNotSameType (evk,env,Some t,u) -> let t, u = pr_explicit env sigma t u in [str "unable to find a well-typed instantiation for " ++ quote (pr_existential_key env sigma evk) ++ strbrk ": cannot ensure that " ++ t ++ strbrk " is a subtype of " ++ u] | InstanceNotSameType (evk,env,None,u) -> let u = pr_leconstr_env env sigma u in [str "unable to find a well-typed instantiation for " ++ quote (pr_existential_key env sigma evk) ++ strbrk " of type " ++ u] | InstanceNotFunctionalType (evk,env,f,u) -> let env = make_all_name_different env sigma in let f = pr_leconstr_env env sigma f in let u = pr_leconstr_env env sigma u in [str "unable to find a well-typed instantiation for " ++ quote (pr_existential_key env sigma evk) ++ strbrk ": " ++ f ++ strbrk " is expected to have a functional type but it has type " ++ u] | UnifUnivInconsistency p -> [str "universe inconsistency: " ++ UGraph.explain_universe_inconsistency (Termops.pr_evd_qvar sigma) (Termops.pr_evd_level sigma) p] | CannotSolveConstraint ((pb,env,t,u),e) -> let env = make_all_name_different env sigma in (strbrk "cannot satisfy constraint " ++ pr_leconstr_env env sigma t ++ str " == " ++ pr_leconstr_env env sigma u) :: aux t u e | ProblemBeyondCapabilities -> [] in match aux p1 p2 e with | [] -> mt () | l -> spc () ++ str "(" ++ prlist_with_sep pr_semicolon (fun x -> x) l ++ str ")" let explain_actual_type env sigma j t reason = let env = make_all_name_different env sigma in let j = j_nf_betaiotaevar env sigma j in let t = Reductionops.nf_betaiota env sigma t in (* Actually print *) let pe = pr_ne_context_of (str "In environment") env sigma in let pc = pr_leconstr_env env sigma (Environ.j_val j) in let (pt, pct) = pr_explicit env sigma t (Environ.j_type j) in let ppreason = explain_unification_error env sigma j.uj_type t reason in pe ++ hov 0 ( str "The term" ++ brk(1,1) ++ pc ++ spc () ++ str "has type" ++ brk(1,1) ++ pct ++ spc () ++ str "while it is expected to have type" ++ brk(1,1) ++ pt ++ ppreason ++ str ".") let explain_incorrect_primitive env sigma j exp = let env = make_all_name_different env sigma in let {uj_val=p;uj_type=t} = j in let t = Reductionops.nf_betaiota env sigma t in let exp = Reductionops.nf_betaiota env sigma exp in (* Actually print *) let pe = pr_ne_context_of (str "In environment") env sigma in let (pt, pct) = pr_explicit env sigma exp t in pe ++ hov 0 ( str "The primitive" ++ brk(1,1) ++ str (CPrimitives.op_or_type_to_string p) ++ spc () ++ str "has type" ++ brk(1,1) ++ pct ++ spc () ++ str "while it is expected to have type" ++ brk(1,1) ++ pt ++ str ".") let explain_cant_apply_bad_type env sigma ?error (n,exptyp,actualtyp) rator randl = let randl = jv_nf_betaiotaevar env sigma randl in let actualtyp = Reductionops.nf_betaiota env sigma actualtyp in let env = make_all_name_different env sigma in let error = explain_unification_error env sigma actualtyp exptyp error in let actualtyp, exptyp = pr_explicit env sigma actualtyp exptyp in let nargs = Array.length randl in (* let pe = pr_ne_context_of (str "in environment") env sigma in*) let pr,prt = pr_ljudge_env env sigma rator in let term_string1 = str (String.plural nargs "term") in let term_string2 = if nargs>1 then str "The " ++ pr_nth n ++ str " term" else str "This term" in let appl = prvect_with_sep fnl (fun c -> let pc,pct = pr_ljudge_env env sigma c in hov 2 (pc ++ spc () ++ str ": " ++ pct)) randl in str "Illegal application: " ++ (* pe ++ *) fnl () ++ str "The term" ++ brk(1,1) ++ pr ++ spc () ++ str "of type" ++ brk(1,1) ++ prt ++ spc () ++ str "cannot be applied to the " ++ term_string1 ++ fnl () ++ str " " ++ v 0 appl ++ fnl () ++ term_string2 ++ str " has type" ++ brk(1,1) ++ actualtyp ++ spc () ++ str "which should be a subtype of" ++ brk(1,1) ++ exptyp ++ str "." ++ error let explain_cant_apply_not_functional env sigma rator randl = let env = make_all_name_different env sigma in let nargs = Array.length randl in (* let pe = pr_ne_context_of (str "in environment") env sigma in*) let pr = pr_leconstr_env env sigma rator.uj_val in let prt = pr_leconstr_env env sigma rator.uj_type in let appl = prvect_with_sep fnl (fun c -> let pc = pr_leconstr_env env sigma c.uj_val in let pct = pr_leconstr_env env sigma c.uj_type in hov 2 (pc ++ spc () ++ str ": " ++ pct)) randl in str "Illegal application (Non-functional construction): " ++ (* pe ++ *) fnl () ++ str "The expression" ++ brk(1,1) ++ pr ++ spc () ++ str "of type" ++ brk(1,1) ++ prt ++ spc () ++ str "cannot be applied to the " ++ str (String.plural nargs "term") ++ fnl () ++ str " " ++ v 0 appl let explain_unexpected_type env sigma actual_type expected_type e = let pract, prexp = pr_explicit env sigma actual_type expected_type in str "Found type" ++ spc () ++ pract ++ spc () ++ str "where" ++ spc () ++ prexp ++ str " was expected" ++ explain_unification_error env sigma actual_type expected_type (Some e) ++ str"." let explain_not_product env sigma c = let pr = pr_econstr_env env sigma c in str "The type of this term is a product" ++ spc () ++ str "while it is expected to be" ++ (if EConstr.isType sigma c then str " a sort" else (brk(1,1) ++ pr)) ++ str "." let explain_ill_formed_fix_body env sigma names i = function (* Fixpoint guard errors *) | NotEnoughAbstractionInFixBody k -> fmt "Not enough abstractions in the definition:@ expected at least %d according to the \"struct\" annotation" (k+1) | RecursionNotOnInductiveType c -> str "Recursive definition on" ++ spc () ++ pr_leconstr_env env sigma c ++ spc () ++ str "which should be a recursive inductive type" | RecursionOnIllegalTerm(j,(arg_env, arg),le_lt) -> let arg_env = make_all_name_different arg_env sigma in let called = match names.(j).binder_name with Name id -> Id.print id | Anonymous -> str "the " ++ pr_nth i ++ str " definition" in let pr_db x = quote (pr_db env x) in let vars = match Lazy.force le_lt with ([],[]) -> assert false | ([x],[]) -> str "a subterm of " ++ pr_db x | (le,[]) -> str "a subterm of the following variables: " ++ pr_sequence pr_db le | (_,[x]) -> pr_db x | (_,lt) -> str "one of the following variables: " ++ pr_sequence pr_db lt in str "Recursive call to " ++ called ++ spc () ++ strbrk "has principal argument equal to" ++ spc () ++ pr_leconstr_env arg_env sigma arg ++ strbrk " instead of " ++ vars | NotEnoughArgumentsForFixCall j -> let called = match names.(j).binder_name with Name id -> Id.print id | Anonymous -> str "the " ++ pr_nth i ++ str " definition" in str "Recursive call to " ++ called ++ str " has not enough arguments" | FixpointOnNonEliminable (s, s') -> let pr_sort u = quote @@ Flags.with_option PrintingFlags.print_universes (Printer.pr_sort sigma) u in fmt "Cannot define a fixpoint@ with principal argument living in sort %t@ \ to produce a value in sort %t@ because %t does not eliminate to %t" (fun () -> pr_sort s) (fun () -> pr_sort s') (fun () -> pr_sort s) (fun () -> pr_sort s') let explain_ill_formed_cofix_body env sigma = function (* CoFixpoint guard errors *) | CodomainNotInductiveType c -> str "The codomain is" ++ spc () ++ pr_leconstr_env env sigma c ++ spc () ++ str "which should be a coinductive type" | NestedRecursiveOccurrences -> str "Nested recursive occurrences" | UnguardedRecursiveCall c -> str "Unguarded recursive call in" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInTypeOfAbstraction c -> str "Recursive call forbidden in the domain of an abstraction:" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInNonRecArgOfConstructor c -> str "Recursive call on a non-recursive argument of constructor" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInTypeOfDef c -> str "Recursive call forbidden in the type of a recursive definition" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInCaseFun c -> str "Invalid recursive call in a branch of" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInCaseArg c -> str "Invalid recursive call in the argument of \"match\" in" ++ spc () ++ pr_leconstr_env env sigma c | RecCallInCasePred c -> str "Invalid recursive call in the \"return\" clause of \"match\" in" ++ spc () ++ pr_leconstr_env env sigma c | NotGuardedForm c -> str "Sub-expression " ++ pr_leconstr_env env sigma c ++ strbrk " not in guarded form (should be a constructor," ++ strbrk " an abstraction, a match, a cofix or a recursive call)" | ReturnPredicateNotCoInductive c -> str "The return clause of the following pattern matching should be" ++ strbrk " a coinductive type:" ++ spc () ++ pr_leconstr_env env sigma c (* TODO: use the names *) (* (co)fixpoints *) let explain_ill_formed_rec_body env sigma err names i fixenv vdefj = let prt_name i = match names.(i).binder_name with Name id -> str "Recursive definition of " ++ Id.print id | Anonymous -> str "The " ++ pr_nth i ++ str " definition" in let st = match err with | FixGuardError err -> explain_ill_formed_fix_body env sigma names i err | CoFixGuardError err -> explain_ill_formed_cofix_body env sigma err in prt_name i ++ str " is ill-formed." ++ fnl () ++ pr_ne_context_of (str "In environment") env sigma ++ st ++ str "." ++ fnl () ++ (try (* May fail with unresolved globals. *) let fixenv = make_all_name_different fixenv sigma in let pvd = pr_leconstr_env fixenv sigma vdefj.(i).uj_val in str"Recursive definition is:" ++ spc () ++ pvd ++ str "." with e when CErrors.noncritical e -> mt ()) let explain_not_guarded env sigma cofix_err fix_errs (names, typs, defs as recdef) = let nfix = Array.length names in let lnames = Array.map_to_list binder_name names in let prt_names = hov 0 (str "Recursive definition of " ++ pr_enum Name.print lnames) in let st = (match cofix_err with | None -> mt () | Some (env, i, err) -> (if nfix > 1 then str "As a mutual co-fixpoint:" else str "As a co-fixpoint:") ++ fnl() ++ explain_ill_formed_cofix_body env sigma err) in let stl = if List.exists (fun (env, i, nv, err) -> match err with RecursionOnIllegalTerm _ -> true | _ -> false) fix_errs then List.map (fun (env, i, nv, err) -> hov 0 ((if nfix > 1 then str "As a mutual fixpoint" else str "As a fixpoint") ++ str " decreasing on the " ++ pr_enum (fun (n,na) -> pr_nth (n+1) ++ str " argument of " ++ Name.print na) (List.combine nv lnames) ++ str ":") ++ fnl() ++ explain_ill_formed_fix_body env sigma names i err ++ str "." ++ fnl ()) fix_errs else match fix_errs with | [] -> [] | (env, i, nv, err) :: _ -> [hov 0 ((if nfix > 1 then str "As a mutual fixpoint" else str "As a fixpoint") ++ str ":") ++ fnl() ++ explain_ill_formed_fix_body env sigma names i err ++ str "." ++ fnl ()] (* A common error independently on the decreasing argument *) in let fixenv = EConstr.push_rec_types recdef env in let st = prlist (fun x -> x) (st::stl) in prt_names ++ str " is ill-formed." ++ fnl () ++ pr_ne_context_of (str "In environment") env sigma ++ st ++ prvecti_with_sep fnl (fun i v -> try (* May fail with unresolved globals. *) let fixenv = make_all_name_different fixenv sigma in let pvd = pr_leconstr_env fixenv sigma v in if nfix = 1 then str "Recursive definition is:" ++ spc () ++ pvd ++ str "." else str "The " ++ pr_nth (i+1) ++ str " recursive definition is:" ++ spc () ++ pvd ++ str "." with e when CErrors.noncritical e -> mt ()) defs let explain_ill_typed_rec_body env sigma i names vdefj vargs = let env = make_all_name_different env sigma in let pvd = pr_leconstr_env env sigma vdefj.(i).uj_val in let pvdt, pv = pr_explicit env sigma vdefj.(i).uj_type vargs.(i) in str "The " ++ (match vdefj with [|_|] -> mt () | _ -> pr_nth (i+1) ++ spc ()) ++ str "recursive definition" ++ spc () ++ pvd ++ spc () ++ str "has type" ++ spc () ++ pvdt ++ spc () ++ str "while it should be" ++ spc () ++ pv ++ str "." let explain_cant_find_case_type env sigma c = let env = make_all_name_different env sigma in let pe = pr_leconstr_env env sigma c in str "Cannot infer the return type of pattern-matching on" ++ ws 1 ++ pe ++ str "." let explain_occur_check env sigma ev rhs = let env = make_all_name_different env sigma in let pt = pr_leconstr_env env sigma rhs in str "Cannot define " ++ pr_existential_key env sigma ev ++ str " with term" ++ brk(1,1) ++ pt ++ spc () ++ str "that would depend on itself." let pr_trailing_ne_context_of env sigma = if List.is_empty (Environ.rel_context env) && List.is_empty (Environ.named_context env) then str "." else (strbrk " in environment:" ++ pr_context_unlimited env sigma) let rec explain_evar_kind env sigma evk ty = let open Evar_kinds in function | Evar_kinds.NamedHole id -> strbrk "the existential variable named " ++ Id.print id | Evar_kinds.QuestionMark {qm_record_field=None} -> strbrk "this placeholder of type " ++ ty | Evar_kinds.QuestionMark {qm_record_field=Some {fieldname; recordname}} -> str "field " ++ (Printer.pr_constant env fieldname) ++ str " of record " ++ (Printer.pr_inductive env recordname) | Evar_kinds.CasesType false -> strbrk "the type of this pattern-matching problem" | Evar_kinds.CasesType true -> strbrk "a subterm of type " ++ ty ++ strbrk " in the type of this pattern-matching problem" | Evar_kinds.BinderType (Name id) -> strbrk "the type of " ++ Id.print id | Evar_kinds.BinderType Anonymous -> strbrk "the type of this anonymous binder" | Evar_kinds.EvarType (ido,evk) -> let pp = match ido with | Some id -> str "?" ++ Id.print id | None -> try pr_existential_key env sigma evk with (* defined *) Not_found -> strbrk "an internal placeholder" in strbrk "the type of " ++ pp | Evar_kinds.ImplicitArg (c,(n,id),b) -> strbrk "the implicit parameter " ++ Id.print id ++ spc () ++ str "of" ++ spc () ++ Nametab.pr_global_env Id.Set.empty c ++ strbrk " whose type is " ++ ty | Evar_kinds.InternalHole -> strbrk "an internal placeholder of type " ++ ty | Evar_kinds.TomatchTypeParameter (tyi,n) -> strbrk "the " ++ pr_nth n ++ strbrk " argument of the inductive type (" ++ pr_inductive env tyi ++ strbrk ") of this term" | Evar_kinds.GoalEvar -> strbrk "an existential variable of type " ++ ty | Evar_kinds.ImpossibleCase -> strbrk "the type of an impossible pattern-matching clause" | Evar_kinds.MatchingVar _ -> assert false | Evar_kinds.VarInstance id -> strbrk "an instance of type " ++ ty ++ str " for the variable " ++ Id.print id | Evar_kinds.SubEvar (where,evk') -> let rec find_source evk = let EvarInfo evi = Evd.find sigma evk in match snd (Evd.evar_source evi) with | Evar_kinds.SubEvar (_,evk) -> find_source evk | src -> EvarInfo evi, src in let EvarInfo evi, src = find_source evk' in let pc = match Evd.evar_body evi with | Evar_defined c -> pr_leconstr_env env sigma c | Evar_empty -> assert false in let ty' = match Evd.evar_body evi with | Evar_empty -> Evd.evar_concl evi | Evar_defined b -> Retyping.get_type_of env sigma b in pr_existential_key env sigma evk ++ strbrk " in the partial instance " ++ pc ++ strbrk " found for " ++ explain_evar_kind env sigma evk (pr_leconstr_env env sigma ty') src | Evar_kinds.RewriteRulePattern Anonymous -> strbrk "an anonymous pattern variable of type " ++ ty | Evar_kinds.RewriteRulePattern Name id -> strbrk "the pattern variable named " ++ Id.print id let explain_typeclass_resolution env sigma evi k = match Typeclasses.class_of_constr env sigma (Evd.evar_concl evi) with | Some _ -> let env = Evd.evar_filtered_env env evi in str "Could not find an instance for " ++ pr_leconstr_env env sigma (Evd.evar_concl evi) ++ pr_trailing_ne_context_of env sigma | _ -> mt() let explain_placeholder_kind env sigma c e = match e with | Some (SeveralInstancesFound n) -> strbrk " (several distinct possible type class instances found)" | None -> match Typeclasses.class_of_constr env sigma c with | Some _ -> strbrk " (no type class instance found)" | _ -> mt () let explain_unsolvable_implicit env sigma evk explain = let evi = Evarutil.nf_evar_info sigma (Evd.find_undefined sigma evk) in let env = Evd.evar_filtered_env env evi in let type_of_hole = pr_leconstr_env env sigma (Evd.evar_concl evi) in let pe = pr_trailing_ne_context_of env sigma in strbrk "Cannot infer " ++ explain_evar_kind env sigma evk type_of_hole (snd (Evd.evar_source evi)) ++ explain_placeholder_kind env sigma (Evd.evar_concl evi) explain ++ pe let explain_var_not_found env id = str "The variable" ++ spc () ++ Id.print 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 (Global.env ()) sigma ev) 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 QInd.equal env ci.ci_ind ind then str "Pattern-matching expression on an object of inductive type" ++ spc () ++ pi ++ spc () ++ str "has invalid information." else let pc = pr_inductive env ci.ci_ind in str "A term of inductive type" ++ spc () ++ pi ++ spc () ++ str "was given to a pattern-matching expression on the inductive type" ++ spc () ++ pc ++ str "." let explain_cannot_unify env sigma m n e = let env = make_all_name_different env sigma in let pm, pn = pr_explicit env sigma m n in let ppreason = explain_unification_error env sigma m n e in let pe = pr_ne_context_of (str "In environment") env sigma in pe ++ str "Unable to unify" ++ brk(1,1) ++ pm ++ spc () ++ str "with" ++ brk(1,1) ++ pn ++ ppreason ++ str "." let explain_cannot_unify_local env sigma m n subn = let pm = pr_leconstr_env env sigma m in let pn = pr_leconstr_env env sigma n in let psubn = pr_leconstr_env env sigma subn in str "Unable to unify" ++ brk(1,1) ++ pm ++ spc () ++ str "with" ++ brk(1,1) ++ pn ++ spc () ++ str "as" ++ brk(1,1) ++ psubn ++ str " contains local variables." let explain_refiner_cannot_generalize env sigma ty = str "Cannot find a well-typed generalisation of the goal with type: " ++ pr_leconstr_env env sigma ty ++ str "." let explain_no_occurrence_found env sigma c id = str "Found no subterm matching" ++ spc() ++ pr_leconstr_env env sigma c ++ spc() ++ str "in " ++ (match id with | Some id -> Id.print id | None -> str"the current goal") ++ str "." let explain_cannot_unify_binding_type env sigma m n = let pm = pr_leconstr_env env sigma m in let pn = pr_leconstr_env env sigma n in str "This binding has type" ++ brk(1,1) ++ pm ++ spc () ++ str "which should be unifiable with" ++ brk(1,1) ++ pn ++ str "." let explain_cannot_find_well_typed_abstraction env sigma p l e = str "Abstracting over the " ++ str (String.plural (List.length l) "term") ++ spc () ++ hov 0 (pr_enum (fun c -> pr_leconstr_env env sigma c) l) ++ spc () ++ str "leads to a term" ++ spc () ++ pr_letype_env ~goal_concl_style:true env sigma p ++ spc () ++ str "which is ill-typed." ++ (match e with None -> mt () | Some e -> fnl () ++ str "Reason is: " ++ e) let explain_wrong_abstraction_type env sigma na abs expected result = let ppname = match na with Name id -> Id.print id ++ spc () | _ -> mt () in str "Cannot instantiate metavariable " ++ ppname ++ strbrk "of type " ++ pr_leconstr_env env sigma expected ++ strbrk " with abstraction " ++ pr_leconstr_env env sigma abs ++ strbrk " of incompatible type " ++ pr_leconstr_env env sigma result ++ str "." let explain_abstraction_over_meta _ m n = strbrk "Too complex unification problem: cannot find a solution for both " ++ Name.print m ++ spc () ++ str "and " ++ Name.print n ++ str "." let explain_non_linear_unification env sigma m t = strbrk "Cannot unambiguously instantiate " ++ Name.print m ++ str ":" ++ strbrk " which would require to abstract twice on " ++ pr_leconstr_env env sigma t ++ str "." let explain_unsatisfied_poly_constraints env sigma (elim_csts,univ_csts) = let univ_csts = Univ.UnivConstraints.filter (fun cst -> not @@ UGraph.check_constraint (Evd.universes sigma) cst) univ_csts in let elim_csts = Sorts.ElimConstraints.filter (fun cst -> not @@ QGraph.check_constraint (Evd.elim_graph sigma) cst) elim_csts in let univ_str = if Univ.UnivConstraints.is_empty univ_csts then mt() else spc() ++ Univ.UnivConstraints.pr (Termops.pr_evd_level sigma) univ_csts in let elim_str = if Sorts.ElimConstraints.is_empty elim_csts then mt() else spc() ++ Sorts.ElimConstraints.pr (Termops.pr_evd_qvar sigma) elim_csts in strbrk "Unsatisfied constraints:" ++ univ_str ++ elim_str ++ spc () ++ str "(maybe a bugged tactic)." let explain_unsatisfied_univ_constraints env sigma cst = let cst = Univ.UnivConstraints.filter (fun cst -> not @@ UGraph.check_constraint (Evd.universes sigma) cst) cst in strbrk "Unsatisfied constraints: " ++ Univ.UnivConstraints.pr (Termops.pr_evd_level sigma) cst ++ spc () ++ str "(maybe a bugged tactic)." let explain_undeclared_universes env sigma l = let l = Univ.Level.Set.elements l in strbrk "Undeclared " ++ str (CString.lplural l "universe") ++ strbrk ": " ++ prlist_with_sep spc (Termops.pr_evd_level sigma) l ++ spc () ++ str "(maybe a bugged tactic)." let explain_undeclared_qualities env sigma l = let n = Sorts.QVar.Set.cardinal l in strbrk "Undeclared " ++ str (if n = 1 then "quality" else "qualities") ++ strbrk": " ++ prlist_with_sep spc (Termops.pr_evd_qvar sigma) (Sorts.QVar.Set.elements l) ++ spc () ++ str "(maybe a bugged tactic)." let explain_not_allowed_sprop () = Pp.(strbrk "SProp is not allowed because the " ++ str "\"Allow StrictProp\"" ++ strbrk " flag is off.") let explain_not_allowed_dependent_eliminitation env isrec i = let open Pp in str "Dependent " ++ str (if isrec then "induction" else "case analysis") ++ strbrk " is not allowed for " ++ Termops.pr_global_env env (IndRef i) ++ str "." ++ str "Primitive records must have eta conversion to allow dependent elimination." let pr_relevance sigma r = let r = EConstr.ERelevance.kind sigma r in match r with | Sorts.Relevant -> str "relevant" | Sorts.Irrelevant -> str "irrelevant" | Sorts.RelevanceVar q -> str "a variable " ++ (* TODO names *) Sorts.QVar.raw_pr q let pr_binder env sigma = function | LocalAssum (na, t) -> Pp.hov 2 (str "(" ++ (Name.print @@ na.binder_name) ++ str " : " ++ pr_leconstr_env env sigma t ++ str ")") | LocalDef (na, b, t) -> Pp.hov 2 (str "(" ++ (Name.print @@ na.binder_name) ++ str " : " ++ pr_leconstr_env env sigma t ++ str " := " ++ pr_leconstr_env env sigma b ++ str ")") let explain_bad_binder_relevance env sigma rlv decl = strbrk "Binder" ++ spc () ++ pr_binder env sigma decl ++ strbrk " has relevance mark set to " ++ pr_relevance sigma (RelDecl.get_relevance decl) ++ strbrk " but was expected to be " ++ pr_relevance sigma rlv ++ spc () ++ str "(maybe a bugged tactic)." let explain_bad_case_relevance env sigma rlv case = let (_, _, _, (_,badr), _, _, _) = EConstr.destCase sigma case in strbrk "Pattern-matching" ++ spc () ++ pr_leconstr_env env sigma case ++ strbrk " has relevance mark set to " ++ pr_relevance sigma badr ++ strbrk " but was expected to be " ++ pr_relevance sigma rlv ++ spc () ++ str "(maybe a bugged tactic)." let explain_bad_relevance env sigma = function | Typing.BadRelevanceCase (r,c) -> explain_bad_case_relevance env sigma r c | BadRelevanceBinder (r,d) -> explain_bad_binder_relevance env sigma r d let () = CWarnings.register_printer Typing.bad_relevance_msg (fun (env, sigma, b) -> explain_bad_relevance env sigma b) let explain_bad_invert env = strbrk "Bad case inversion (maybe a bugged tactic)." let explain_bad_variance env sigma ~lev ~expected ~actual = fmt "Incorrect variance for universe %t:@ expected %t@ but cannot be less restrictive than %t." (fun () -> Termops.pr_evd_level sigma lev) (fun () -> UVars.Variance.pr expected) (fun () -> UVars.Variance.pr actual) let explain_undeclared_used_variables env sigma ~declared_vars ~inferred_vars = let l = Id.Set.elements (Id.Set.diff inferred_vars declared_vars) in let n = List.length l in let declared_vars = Pp.pr_sequence Id.print (Id.Set.elements declared_vars) in let inferred_vars = Pp.pr_sequence Id.print (Id.Set.elements inferred_vars) in let missing_vars = Pp.pr_sequence Id.print (List.rev l) in Pp.(prlist str ["The following section "; (String.plural n "variable"); " "; (String.conjugate_verb_to_be n); " used but not declared:"] ++ fnl () ++ missing_vars ++ str "." ++ fnl () ++ fnl () ++ str "You can either update your proof to not depend on " ++ missing_vars ++ str ", or you can update your Proof line from" ++ fnl () ++ str "Proof using " ++ declared_vars ++ fnl () ++ str "to" ++ fnl () ++ str "Proof using " ++ inferred_vars) let explain_ill_formed_constant env sigma cst kn = strbrk "Ill-formed constant" ++ spc () ++ pr_constant env cst ++ str ":" ++ spc () ++ strbrk "expected canonical name" ++ spc () ++ KerName.print kn ++ spc () ++ strbrk "but found" ++ spc () ++ KerName.print (Constant.canonical cst) let explain_ill_formed_inductive env sigma mind kn = strbrk "Ill-formed inductive" ++ spc () ++ pr_inductive env (mind, 0) ++ str ":" ++ spc () ++ strbrk "expected canonical name" ++ spc () ++ KerName.print kn ++ spc () ++ strbrk "but found" ++ spc () ++ KerName.print (MutInd.canonical mind) let explain_type_error env sigma err = let env = make_all_name_different env sigma in match err with | UnboundRel n -> explain_unbound_rel env sigma n | UnboundVar v -> explain_unbound_var env v | NotAType j -> explain_not_type env sigma j | BadAssumption c -> explain_bad_assumption env sigma c | ReferenceVariables (id,c) -> explain_reference_variables sigma id c | ElimArity (ind, c, okinds) -> explain_elim_arity env sigma ind (Some c) okinds | CaseNotInductive cj -> explain_case_not_inductive env sigma cj | CaseOnPrivateInd ind -> explain_case_on_private_ind env sigma ind | NumberBranches (cj, n) -> explain_number_branches env sigma cj n | IllFormedCaseParams -> explain_ill_formed_case_params env sigma | IllFormedBranch (c, i, actty, expty) -> explain_ill_formed_branch env sigma c i actty expty | BadProjType (cj, p) -> explain_bad_proj_type env sigma cj p | Generalization (nvar, c) -> explain_generalization env sigma nvar c | ActualType (j, pt) -> explain_actual_type env sigma j pt None | IncorrectPrimitive (j, t) -> explain_incorrect_primitive env sigma j t | CantApplyBadType (t, rator, randl) -> explain_cant_apply_bad_type env sigma t rator randl | CantApplyNonFunctional (rator, randl) -> explain_cant_apply_not_functional env sigma rator randl | IllFormedRecBody (err, lna, i, fixenv, vdefj) -> explain_ill_formed_rec_body env sigma err lna i fixenv vdefj | IllTypedRecBody (i, lna, vdefj, vargs) -> explain_ill_typed_rec_body env sigma i lna vdefj vargs | WrongCaseInfo (ind,ci) -> explain_wrong_case_info env ind ci | UnsatisfiedPConstraints cst -> explain_unsatisfied_poly_constraints env sigma cst | UnsatisfiedUnivConstraints cst -> explain_unsatisfied_univ_constraints env sigma cst | UndeclaredUniverses l -> explain_undeclared_universes env sigma l | UndeclaredQualities l -> explain_undeclared_qualities env sigma l | NotAllowedSProp -> explain_not_allowed_sprop () | BadBinderRelevance (rlv, decl) -> explain_bad_binder_relevance env sigma rlv decl | BadCaseRelevance (rlv, case) -> explain_bad_case_relevance env sigma rlv case | BadInvert -> explain_bad_invert env | BadVariance {lev;expected;actual} -> explain_bad_variance env sigma ~lev ~expected ~actual | UndeclaredUsedVariables {declared_vars;inferred_vars} -> explain_undeclared_used_variables env sigma ~declared_vars ~inferred_vars | IllFormedConstant (cst, kn) -> explain_ill_formed_constant env sigma cst kn | IllFormedInductive (mind, kn) -> explain_ill_formed_inductive env sigma mind kn let pr_position (cl,pos) = let clpos = match cl with | None -> str " of the goal" | Some (id,Locus.InHyp) -> str " of hypothesis " ++ Id.print id | Some (id,Locus.InHypTypeOnly) -> str " of the type of hypothesis " ++ Id.print id | Some (id,Locus.InHypValueOnly) -> str " of the body of hypothesis " ++ Id.print id in int pos ++ clpos let explain_cannot_unify_occurrences env sigma nested ((cl2,pos2),t2) ((cl1,pos1),t1) = if nested then str "Found nested occurrences of the pattern at positions " ++ int pos1 ++ strbrk " and " ++ pr_position (cl2,pos2) ++ str "." else str "Found incompatible occurrences of the pattern" ++ str ":" ++ spc () ++ str "Matched term " ++ pr_leconstr_env env sigma t2 ++ strbrk " at position " ++ pr_position (cl2,pos2) ++ strbrk " is not compatible with matched term " ++ pr_leconstr_env env sigma t1 ++ strbrk " at position " ++ pr_position (cl1,pos1) ++ str "." let pr_constraints printenv msg env sigma evars cstrs = let (ev, evi) = Evar.Map.choose evars in if Evar.Map.for_all (fun ev' evi' -> eq_named_context_val (Evd.evar_hyps evi) (Evd.evar_hyps evi')) evars then let l = Evar.Map.bindings evars in let env' = Evd.evar_env env evi in let pe = if printenv then pr_ne_context_of (str "In environment:") env' sigma else mt () in let env = Global.env () in let evs = prlist_with_sep (fun () -> fnl () ++ fnl ()) (fun (ev, evi) -> hov 2 (pr_existential_key env sigma ev ++ str " :" ++ spc () ++ Printer.pr_leconstr_env env' sigma (Evd.evar_concl evi))) l in h (pe ++ str msg ++ fnl () ++ evs ++ pr_evar_constraints sigma cstrs) else let filter evk _ = Evar.Map.mem evk evars in pr_evar_map_filter ~with_univs:false filter env sigma let explain_unsatisfiable_constraints env sigma constr comp = let (_, constraints) = Evd.extract_all_conv_pbs sigma in let tcs = Evd.get_typeclass_evars sigma in let undef = Evd.undefined_map sigma in (* Only keep evars that are subject to resolution and members of the given component. *) let is_kept evk _ = Evar.Set.mem evk tcs && Evar.Set.mem evk comp in let undef = let m = Evar.Map.filter is_kept undef in if Evar.Map.is_empty m then undef else m in match constr with | None -> if List.is_empty constraints then let msg = "Could not find an instance for the following existential variables:" in pr_constraints true msg env sigma undef constraints else let msg = "Unable to satisfy the following constraints:" in pr_constraints true msg env sigma undef constraints | Some (ev, k) -> let cstr = let remaining = Evar.Map.remove ev undef in if not (Evar.Map.is_empty remaining) then let msg = "With the following constraints:" in pr_constraints false msg env sigma remaining constraints else mt () in let info = Evar.Map.find ev undef in explain_typeclass_resolution env sigma info k ++ fnl () ++ cstr let rec explain_pretype_error env sigma err = let env = Evardefine.env_nf_betaiotaevar sigma env in let env = make_all_name_different env sigma in match err with | CantFindCaseType c -> explain_cant_find_case_type env sigma c | ActualTypeNotCoercible (j,t,e) -> let {uj_val = c; uj_type = actty} = j in let (env, c, actty, expty), e = contract3' env sigma c actty t e in let j = {uj_val = c; uj_type = actty} in explain_actual_type env sigma j expty (Some e) | 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,e) -> let env, actual, expect = contract2 env sigma actual expect in explain_unexpected_type env sigma actual expect e | NotProduct c -> explain_not_product env sigma c | CannotUnify (m,n,e) -> let env, m, n = contract2 env sigma m n in explain_cannot_unify env sigma m n e | CannotUnifyLocal (m,n,sn) -> explain_cannot_unify_local env sigma m n sn | CannotGeneralize ty -> explain_refiner_cannot_generalize env sigma ty | NoOccurrenceFound (c, id) -> explain_no_occurrence_found env sigma c id | CannotUnifyBindingType (m,n) -> explain_cannot_unify_binding_type env sigma m n | CannotFindWellTypedAbstraction (p,l,e) -> explain_cannot_find_well_typed_abstraction env sigma p l (Option.map (fun (env',e) -> explain_pretype_error env' sigma e) e) | WrongAbstractionType (n,a,t,u) -> explain_wrong_abstraction_type env sigma n a t u | AbstractionOverMeta (m,n) -> explain_abstraction_over_meta env m n | NonLinearUnification (m,c) -> explain_non_linear_unification env sigma m c | TypingError t -> explain_type_error env sigma t | CantApplyBadTypeExplained ((t, rator, randl),error) -> explain_cant_apply_bad_type env sigma ~error t rator randl | CannotUnifyOccurrences (b,c1,c2) -> explain_cannot_unify_occurrences env sigma b c1 c2 | UnsatisfiableConstraints (c,comp) -> explain_unsatisfiable_constraints env sigma c comp | NotAllowedSProp -> explain_not_allowed_sprop () | NotAllowedElimination (isrec, k, (ind,u)) -> explain_elim_arity env sigma (ind, (EConstr.EInstance.kind sigma u)) None (Some (EConstr.ESorts.kind sigma k)) | NotAllowedDependentElimination (isrec, i) -> explain_not_allowed_dependent_eliminitation env isrec i (* Module errors *) let pr_modpath mp = Libnames.pr_qualid (Nametab.shortest_qualid_of_module mp) let pr_modtype_subpath upper mp = let rec aux mp = try let (dir,id) = Libnames.repr_qualid (Nametab.shortest_qualid_of_modtype mp) in Libnames.add_dirpath_suffix dir id, [] with Not_found -> match mp with | MPdot (mp',id) -> let mp, suff = aux mp' in mp, id::suff | _ -> assert false in let mp, suff = aux mp in (if suff = [] then mt () else strbrk (if upper then "Module " else "module ") ++ DirPath.print (DirPath.make suff) ++ strbrk " of ") ++ DirPath.print mp let pr_module_or_modtype_subpath mp = match Nametab.shortest_qualid_of_module mp with | qid -> (* [mp] is bound to a proper module *) strbrk "module " ++ Libnames.pr_qualid qid | exception Not_found -> (* [mp] ought to be bound to a submodule of a module type *) pr_modtype_subpath false mp open Modops let explain_not_match_error = function | InductiveFieldExpected _ -> strbrk "an inductive definition is expected" | DefinitionFieldExpected -> strbrk "a definition is expected. Hint: you can rename the \ inductive or constructor and add a definition mapping the \ old name to the new name" | ModuleFieldExpected -> strbrk "a module is expected" | ModuleTypeFieldExpected -> strbrk "a module type is expected" | NotConvertibleInductiveField (id, None) -> str "types given to " ++ Id.print id ++ str " differ" | NotConvertibleInductiveField (id, Some (env, typ1, typ2)) -> let typ1, typ2 = pr_explicit env (Evd.from_env env) (EConstr.of_constr typ1) (EConstr.of_constr typ2) in str "types given to " ++ Id.print id ++ str " differ:" ++ spc () ++ str "expected" ++ spc () ++ typ2 ++ spc () ++ str "but found" ++ spc () ++ typ1 | NotConvertibleConstructorField (id, None) -> str "types given to constructor " ++ Id.print id ++ str " differ" | NotConvertibleConstructorField (id, Some (env, typ1, typ2)) -> let typ1, typ2 = pr_explicit env (Evd.from_env env) (EConstr.of_constr typ1) (EConstr.of_constr typ2) in str "types given to constructor " ++ Id.print id ++ str " differ:" ++ spc () ++ str "expected" ++ spc () ++ typ2 ++ spc () ++ str "but found" ++ spc () ++ typ1 | NotConvertibleBodyField None -> str "the body of definitions differs" | NotConvertibleBodyField (Some (env, c1, c2)) -> let sigma = Evd.from_env env in let c1, c2 = pr_explicit env sigma (EConstr.of_constr c1) (EConstr.of_constr c2) in str "the body of definitions differs:" ++ spc () ++ str "expected" ++ spc () ++ c2 ++ spc () ++ str "but found" ++ spc () ++ c1 | NotConvertibleTypeField (env, typ1, typ2) -> let typ1, typ2 = pr_explicit env (Evd.from_env env) (EConstr.of_constr typ1) (EConstr.of_constr typ2) in str "expected type" ++ spc () ++ typ2 ++ spc () ++ str "but found type" ++ spc () ++ typ1 | NotSameConstructorNamesField (got, expected) -> let pr_names arr = prlist_with_sep pr_comma Id.print (Array.to_list arr) in str "constructor names differ:" ++ spc () ++ str "expected" ++ spc () ++ pr_names expected ++ spc () ++ str "but found" ++ spc () ++ pr_names got | NotSameInductiveNameInBlockField (got, expected) -> str "inductive type names differ:" ++ spc () ++ str "expected" ++ spc () ++ Id.print expected ++ spc () ++ str "but found" ++ spc () ++ Id.print got | FiniteInductiveFieldExpected isfinite -> str "type is expected to be " ++ str (if isfinite then "coinductive" else "inductive") | InductiveNumbersFieldExpected { got; expected } -> str "number of inductive types differs:" ++ spc () ++ str "expected" ++ spc () ++ int expected ++ spc () ++ str "but found" ++ spc () ++ int got | InductiveParamsNumberField { got; expected } -> str "number of parameters differs:" ++ spc () ++ str "expected" ++ spc () ++ int expected ++ spc () ++ str "but found" ++ spc () ++ int got | RecordFieldExpected isrecord -> str "type is expected " ++ str (if isrecord then "" else "not ") ++ str "to be a record" | RecordProjectionsExpected { expected; got } -> let pr_names nal = pr_enum (function Name id -> Id.print id | _ -> str "_") nal in str "projection names differ:" ++ spc () ++ str "expected" ++ spc () ++ pr_names expected ++ spc () ++ str "but found" ++ spc () ++ pr_names got | NotEqualInductiveAliases (got, expected) -> str "aliases to inductive types do not match:" ++ spc () ++ str "expected" ++ spc () ++ MutInd.print expected ++ spc () ++ str "but found" ++ spc () ++ MutInd.print got | CumulativeStatusExpected b -> let status b = if b then str"cumulative" else str"non-cumulative" in str "a " ++ status b ++ str" declaration was expected, but a " ++ status (not b) ++ str" declaration was found" | PolymorphicStatusExpected b -> let status b = if b then str"polymorphic" else str"monomorphic" in str "a " ++ status b ++ str" declaration was expected, but a " ++ status (not b) ++ str" declaration was found" | IncompatibleUniverses { err; env; t1; t2 } -> let sigma = Evd.from_env env in let t1, t2 = pr_explicit env sigma (EConstr.of_constr t1) (EConstr.of_constr t2) in str"the universe constraints are inconsistent:" ++ spc () ++ UGraph.explain_universe_inconsistency Sorts.QVar.raw_pr UnivNames.pr_level_with_global_universes err ++ spc () ++ str "when comparing" ++ spc () ++ t1 ++ spc () ++ str "and" ++ spc () ++ t2 | IncompatibleQualities { err; env; t1; t2 } -> let sigma = Evd.from_env env in let t1, t2 = pr_explicit env sigma (EConstr.of_constr t1) (EConstr.of_constr t2) in QGraph.explain_elimination_error Sorts.QVar.raw_pr err ++ spc () ++ str "when comparing" ++ spc () ++ t1 ++ spc () ++ str "and" ++ spc () ++ t2 | IncompatiblePolymorphism (env, t1, t2) -> let t1, t2 = pr_explicit env (Evd.from_env env) (EConstr.of_constr t1) (EConstr.of_constr t2) in str "conversion of polymorphic values generates additional constraints: " ++ quote t1 ++ spc () ++ str "compared to " ++ spc () ++ quote t2 | IncompatibleUnivConstraints { got; expect } -> let open UVars in let pr_auctx auctx = let sigma = Evd.from_ctx (UState.of_names (Printer.universe_binders_with_opt_names auctx None)) in let uctx = AbstractContext.repr auctx in Printer.pr_universe_instance_binder sigma (UContext.instance uctx) (UContext.univ_constraints uctx) in str "incompatible polymorphic binders: got" ++ spc () ++ h (pr_auctx got) ++ spc() ++ str "but expected" ++ spc() ++ h (pr_auctx expect) ++ (if not (UVars.eq_sizes (AbstractContext.size got) (AbstractContext.size expect)) then mt() else fnl() ++ str "(incompatible constraints)") | IncompatibleVariance -> str "incompatible variance information" | NoRewriteRulesSubtyping -> strbrk "subtyping for rewrite rule blocks is not supported" let rec get_submodules acc = function | [] -> acc, [] | Submodule l :: trace -> get_submodules (l::acc) trace | (FunctorArgument _ :: _) as trace -> acc, trace let get_submodules trace = let submodules, trace = get_submodules [] trace in (String.concat "." (List.map Id.to_string submodules)), trace let rec print_trace = function | [] -> assert false | (Submodule _ :: _) as trace -> let submodules, trace = get_submodules trace in str submodules ++ (if List.is_empty trace then mt() else spc() ++ str "in " ++ print_trace trace) | FunctorArgument n :: trace -> str "the " ++ str (CString.ordinal n) ++ str " functor argument" ++ (if List.is_empty trace then mt() else spc() ++ str "of " ++ print_trace trace) let explain_signature_mismatch trace l why = let submodules, trace = get_submodules trace in let l = if String.is_empty submodules then Id.print l else str submodules ++ str"." ++ Id.print l in str "Signature components for field " ++ l ++ (if List.is_empty trace then mt() else str " in " ++ print_trace trace) ++ str " do not match:" ++ spc () ++ explain_not_match_error why ++ str "." let explain_label_already_declared l = str "The label " ++ Id.print l ++ str " is already declared." let explain_not_a_functor () = str "Application of a non-functor." let explain_is_a_functor mp = pr_modtype_subpath true mp ++ str " not expected to be a functor." let explain_incompatible_module_types mexpr1 mexpr2 = let open Declarations in let open Mod_declarations in let rec get_arg = function | NoFunctor _ -> 0 | MoreFunctor (_, _, ty) -> succ (get_arg ty) in let len1 = get_arg @@ mod_type mexpr1 in let len2 = get_arg @@ mod_type mexpr2 in if len1 <> len2 then str "Incompatible module types: module expects " ++ int len2 ++ str " arguments, found " ++ int len1 ++ str "." else str "Incompatible module types." let explain_not_equal_module_paths mp1 mp2 = str "Module " ++ pr_modpath mp1 ++ strbrk " is not equal to " ++ pr_module_or_modtype_subpath mp2 ++ str "." let explain_no_such_label l mp = str "No field named " ++ Id.print l ++ str " in " ++ pr_modtype_subpath false mp ++ str "." let explain_not_a_module_label l = Id.print l ++ str " is not the name of a module field." let explain_not_a_constant l = quote (Id.print l) ++ str " is not a constant." let explain_with_constraint_error = function | WithSignatureMismatch sig_err -> explain_not_match_error sig_err | WithCannotConstrainPrimitive -> str "cannot constrain a primitive" | WithCannotConstrainSymbol -> str "cannot constrain a symbol" let explain_incorrect_with_constraint l err = str "Incorrect constraint for label " ++ quote (Id.print l) ++ str ": " ++ explain_with_constraint_error err let explain_generative_module_expected l = str "The module " ++ Id.print l ++ str " is not generative." ++ strbrk " Only components of generative modules can be changed" ++ strbrk " using the \"with\" construct." let explain_label_missing l s = str "The field " ++ Id.print l ++ str " is missing in " ++ str s ++ str "." let explain_include_restricted_functor mp = str "Cannot include the functor " ++ pr_modpath mp ++ strbrk " since it has a restricted signature. " ++ strbrk "You may name first an instance of this functor, and include it." let explain_module_error = function | SignatureMismatch (trace,l,err) -> explain_signature_mismatch trace l err | LabelAlreadyDeclared l -> explain_label_already_declared l | NotAFunctor -> explain_not_a_functor () | IsAFunctor mp -> explain_is_a_functor mp | IncompatibleModuleTypes (m1,m2) -> explain_incompatible_module_types m1 m2 | NotEqualModulePaths (mp1,mp2) -> explain_not_equal_module_paths mp1 mp2 | NoSuchLabel (l,mp) -> explain_no_such_label l mp | NotAModuleLabel l -> explain_not_a_module_label l | NotAConstant l -> explain_not_a_constant l | IncorrectWithConstraint (l, err) -> explain_incorrect_with_constraint l err | GenerativeModuleExpected l -> explain_generative_module_expected l | LabelMissing (l,s) -> explain_label_missing l s | IncludeRestrictedFunctor mp -> explain_include_restricted_functor mp (* Module internalization errors *) (* let explain_declaration_not_path _ = str "Declaration is not a path." *) let explain_not_module_nor_modtype qid = Libnames.pr_qualid qid ++ str " is not a module or module type." let explain_not_a_module qid = Libnames.pr_qualid qid ++ str " is not a module." let explain_not_a_module_type qid = Libnames.pr_qualid qid ++ str " is not a module type." let explain_incorrect_with_in_module () = str "The syntax \"with\" is not allowed for modules." let explain_incorrect_module_application () = str "Illegal application to a module type." let explain_module_internalization_error = let open Modintern in function | NotAModuleNorModtype qid -> explain_not_module_nor_modtype qid | NotAModule qid -> explain_not_a_module qid | NotAModuleType qid -> explain_not_a_module_type qid | IncorrectWithInModule -> explain_incorrect_with_in_module () | IncorrectModuleApplication -> explain_incorrect_module_application () (* Typeclass errors *) let explain_not_a_class env sigma c = pr_econstr_env env sigma c ++ str" is not a declared type class." let explain_unbound_method env sigma cid { CAst.v = id } = str "Unbound method name " ++ Id.print (id) ++ spc () ++ str"of class" ++ spc () ++ pr_global cid ++ str "." let explain_typeclass_error env sigma = function | NotAClass c -> explain_not_a_class env sigma c | UnboundMethod (cid, id) -> explain_unbound_method env sigma cid id (* Refiner errors *) let explain_refiner_unresolved_bindings l = str "Unable to find an instance for the " ++ str (String.plural (List.length l) "variable") ++ spc () ++ prlist_with_sep pr_comma Name.print l ++ str"." let explain_refiner_cannot_apply env sigma t harg = str "In refiner, a term of type" ++ brk(1,1) ++ pr_leconstr_env env sigma t ++ spc () ++ str "could not be applied to" ++ brk(1,1) ++ pr_leconstr_env env sigma harg ++ str "." let explain_intro_needs_product () = str "Introduction tactics needs products." let explain_non_linear_proof env sigma c = str "Cannot refine with term" ++ brk(1,1) ++ pr_leconstr_env env sigma c ++ spc () ++ str "because a metavariable has several occurrences." let explain_no_such_hyp id = str "No such hypothesis: " ++ Id.print id let explain_refiner_error env sigma = function | UnresolvedBindings t -> explain_refiner_unresolved_bindings t | CannotApply (t,harg) -> explain_refiner_cannot_apply env sigma t harg | IntroNeedsProduct -> explain_intro_needs_product () | NonLinearProof c -> explain_non_linear_proof env sigma c | NoSuchHyp id -> explain_no_such_hyp id (* Inductive errors *) let error_non_strictly_positive env c v = let pc = pr_lconstr_env env (Evd.from_env env) c in let pv = pr_lconstr_env env (Evd.from_env env) v in str "Non strictly positive occurrence of " ++ pv ++ str " in" ++ brk(1,1) ++ pc ++ str "." let error_ill_formed_inductive env c v = let pc = pr_lconstr_env env (Evd.from_env env) c in let pv = pr_lconstr_env env (Evd.from_env env) v in str "Not enough arguments applied to the " ++ pv ++ str " in" ++ brk(1,1) ++ pc ++ str "." let error_ill_formed_constructor env id c v nparams nargs = let pv = pr_lconstr_env env (Evd.from_env env) v in let atomic = Int.equal (nb_prod Evd.empty (EConstr.of_constr c)) (* FIXME *) 0 in str "The type of constructor" ++ brk(1,1) ++ Id.print id ++ brk(1,1) ++ str "is not valid;" ++ brk(1,1) ++ strbrk (if atomic then "it must be " else "its conclusion must be ") ++ pv ++ (* warning: because of implicit arguments it is difficult to say which parameters must be explicitly given *) (if not (Int.equal nparams 0) then strbrk " applied to its " ++ str (String.plural nparams "parameter") else mt()) ++ (if not (Int.equal nargs 0) then str (if not (Int.equal nparams 0) then " and" else " applied") ++ strbrk " to some " ++ str (String.plural nargs "argument") else mt()) ++ str "." let pr_ltype_using_barendregt_convention_env env c = (* Use goal_concl_style as an approximation of Barendregt's convention (?) *) quote (pr_ltype_env ~goal_concl_style:true env (Evd.from_env env) c) let error_bad_ind_parameters env c n v1 v2 = let pc = pr_ltype_using_barendregt_convention_env env c in let pv1 = pr_lconstr_env env (Evd.from_env env) v1 in let pv2 = pr_lconstr_env env (Evd.from_env env) v2 in str "Last occurrence of " ++ pv2 ++ str " must have " ++ pv1 ++ str " as " ++ pr_nth n ++ str " argument in" ++ brk(1,1) ++ pc ++ str "." let error_same_names_types id = str "The name" ++ spc () ++ Id.print id ++ spc () ++ str "is used more than once." let error_same_names_constructors id = str "The constructor name" ++ spc () ++ Id.print id ++ spc () ++ str "is used more than once." let error_same_names_overlap idl = strbrk "The following names are used both as type names and constructor " ++ str "names:" ++ spc () ++ prlist_with_sep pr_comma Id.print idl ++ str "." let error_not_an_arity env c = str "The type" ++ spc () ++ pr_lconstr_env env (Evd.from_env env) c ++ spc () ++ str "is not an arity." let error_bad_entry () = str "Bad inductive definition." let error_large_non_prop_inductive_not_in_type () = str "Large non-propositional inductive types must be in Type." let error_inductive_missing_constraints env (us,ind_univ) = let sigma = Evd.from_env env in let pr_sort u = Flags.with_option PrintingFlags.print_universes (Printer.pr_sort sigma) u in str "Missing universe constraint declared for inductive type:" ++ spc() ++ v 0 (prlist_with_sep spc (fun u -> hov 0 (pr_sort u ++ str " <= " ++ pr_sort ind_univ)) us) (* Inductive constructions errors *) let explain_inductive_error env = function | NonPos (c,v) -> error_non_strictly_positive env c v | NotEnoughArgs (c,v) -> error_ill_formed_inductive env c v | NotConstructor (id,c,v,n,m) -> error_ill_formed_constructor env id c v n m | NonPar (c,n,v1,v2) -> error_bad_ind_parameters env c n v1 v2 | SameNamesTypes id -> error_same_names_types id | SameNamesConstructors id -> error_same_names_constructors id | SameNamesOverlap idl -> error_same_names_overlap idl | NotAnArity c -> error_not_an_arity env c | BadEntry -> error_bad_entry () | LargeNonPropInductiveNotInType -> error_large_non_prop_inductive_not_in_type () | MissingUnivConstraints csts -> error_inductive_missing_constraints env csts (* Primitive errors *) let explain_incompatible_prim_declarations (type a) (act:a Primred.action_kind) (x:a) (y:a) = let open Primred in let env = Global.env() in (* The newer constant/inductive (either coming from Primitive or a Require) may be absent from the nametab as the error got raised while adding it to the safe_env. In that case we can't use nametab printing. There are still cases where the constant/inductive is added separately from its retroknowledge (using Register), so we still try nametab based printing. *) match act with | IncompatTypes typ -> let px = try pr_constant env x with Not_found -> Constant.print x in str "Cannot declare " ++ px ++ str " as primitive " ++ str (CPrimitives.prim_type_to_string typ) ++ str ": " ++ pr_constant env y ++ str " is already declared." | IncompatInd ind -> let px = try pr_inductive env x with Not_found -> MutInd.print (fst x) in str "Cannot declare " ++ px ++ str " as primitive " ++ str (CPrimitives.prim_ind_to_string ind) ++ str ": " ++ pr_inductive env y ++ str " is already declared." (* Recursion schemes errors *) let error_not_mutual_in_scheme env ind ind' = str "The inductive types " ++ pr_inductive env ind ++ spc () ++ str "and" ++ spc () ++ pr_inductive env ind' ++ spc () ++ str "are not mutually defined." let error_twice_in_scheme env ind = str "The inductive type " ++ pr_inductive env ind ++ str " occurs twice." let explain_recursion_scheme_error env = function | NotMutualInScheme (ind,ind')-> error_not_mutual_in_scheme env ind ind' | DuplicateInductiveBlock ind -> error_twice_in_scheme env ind (* Pattern-matching errors *) let explain_bad_pattern env sigma cstr ty = let env = make_all_name_different env sigma in let pt = pr_leconstr_env env sigma ty in let pc = pr_constructor env cstr in str "Found the constructor " ++ pc ++ brk(1,1) ++ str "while matching a term of type " ++ pt ++ brk(1,1) ++ str "which is not an inductive type." let explain_bad_constructor env cstr ind = let pi = pr_inductive env ind in (* let pc = pr_constructor env cstr in*) let pt = pr_inductive env (inductive_of_constructor cstr) in str "Found a constructor of inductive type " ++ pt ++ brk(1,1) ++ str "while a constructor of " ++ pi ++ brk(1,1) ++ str "is expected." let decline_string n s = if Int.equal n 0 then str "no " ++ str s ++ str "s" else if Int.equal n 1 then str "1 " ++ str s else (int n ++ str " " ++ str s ++ str "s") let explain_wrong_numarg_pattern expanded nargs expected_nassums expected_ndecls pp = (if expanded then strbrk "Once notations are expanded, the resulting " else strbrk "The ") ++ pp ++ strbrk " is expected to be applied to " ++ decline_string expected_nassums "argument" ++ (if expected_nassums = expected_ndecls then mt () else strbrk " (or " ++ decline_string expected_ndecls "argument" ++ strbrk " when including variables for local definitions)") ++ strbrk " while it is actually applied to " ++ decline_string nargs "argument" ++ str "." let explain_wrong_numarg_constructor env cstr expanded nargs expected_nassums expected_ndecls = let pp = strbrk "constructor " ++ pr_constructor env cstr ++ strbrk " (in type " ++ pr_inductive env (inductive_of_constructor cstr) ++ strbrk ")" in explain_wrong_numarg_pattern expanded nargs expected_nassums expected_ndecls pp let explain_wrong_numarg_inductive env ind expanded nargs expected_nassums expected_ndecls = let pp = strbrk "inductive type " ++ pr_inductive env ind in explain_wrong_numarg_pattern expanded nargs expected_nassums expected_ndecls pp let explain_unused_clause env pats = str "Pattern \"" ++ hov 0 (prlist_with_sep pr_comma pr_cases_pattern pats) ++ strbrk "\" is redundant in this clause." let explain_non_exhaustive env pats = str "Non exhaustive pattern-matching: no clause found for " ++ str (String.plural (List.length pats) "pattern") ++ spc () ++ hov 0 (prlist_with_sep pr_comma pr_cases_pattern pats) let explain_cannot_infer_predicate env sigma typs = let typs = Array.to_list typs in let env = make_all_name_different env sigma in let pr_branch (cstr,typ) = let cstr,_ = EConstr.decompose_app sigma cstr in str "For " ++ pr_leconstr_env env sigma cstr ++ str ": " ++ pr_leconstr_env env sigma typ in str "Unable to unify the types found in the branches:" ++ spc () ++ hov 0 (prlist_with_sep fnl pr_branch typs) let explain_pattern_matching_error env sigma = function | BadPattern (c,t) -> explain_bad_pattern env sigma c t | BadConstructor (c,ind) -> explain_bad_constructor env c ind | WrongNumargConstructor {cstr; expanded; nargs; expected_nassums; expected_ndecls} -> explain_wrong_numarg_constructor env cstr expanded nargs expected_nassums expected_ndecls | WrongNumargInductive {ind; expanded; nargs; expected_nassums; expected_ndecls} -> explain_wrong_numarg_inductive env ind expanded nargs expected_nassums expected_ndecls | UnusedClause tms -> explain_unused_clause env tms | NonExhaustive tms -> explain_non_exhaustive env tms | CannotInferPredicate typs -> explain_cannot_infer_predicate env sigma typs let explain_reduction_tactic_error = function | Tacred.InvalidAbstraction (env,sigma,c,(env',e)) -> let e = of_type_error e in str "The abstracted term" ++ spc () ++ quote (pr_letype_env ~goal_concl_style:true env sigma c) ++ spc () ++ str "is not well typed." ++ fnl () ++ explain_type_error env' (Evd.from_env env') e let explain_prim_token_notation_error kind env sigma = function | PrimNotations.UnexpectedTerm c -> (strbrk "Unexpected term " ++ pr_constr_env env sigma c ++ strbrk (" while parsing a "^kind^" notation.")) | PrimNotations.UnexpectedNonOptionTerm c -> (strbrk "Unexpected non-option term " ++ pr_constr_env env sigma c ++ strbrk (" while parsing a "^kind^" notation.")) (* Rewrite rules errors *) let error_not_allowed_rewrite_rules symb_or_rule = str (match symb_or_rule with Rule -> "Rewrite rule" | Symb -> "Symbol") ++ spc () ++ strbrk "declaration requires passing the flag " ++ strbrk "\"-allow-rewrite-rules\"." (** Registration of generic errors Nota: explain_exn does NOT end with a newline anymore! *) exception Unhandled let wrap_unhandled f e = try Some (f e) with Unhandled -> None let explain_exn_default = function (* Basic interaction exceptions *) | Gramlib.Grammar.ParseError txt -> hov 0 (str "Syntax error: " ++ str txt ++ str ".") | CLexer.Error.E err -> hov 0 (str (CLexer.Error.to_string err)) | Sys_error msg -> hov 0 (str "System error: " ++ quote (str msg)) | Out_of_memory -> hov 0 (str "Out of memory.") | Stack_overflow -> hov 0 (str "Stack overflow.") | Sys.Break -> hov 0 (str "User interrupt.") (* Otherwise, not handled here *) | _ -> raise Unhandled let _ = CErrors.register_handler (wrap_unhandled explain_exn_default) let rec vernac_interp_error_handler = function | UGraph.UniverseInconsistency i -> str "Universe inconsistency." ++ spc() ++ UGraph.explain_universe_inconsistency UnivNames.pr_quality_with_global_universes UnivNames.pr_level_with_global_universes i ++ str "." | QGraph.EliminationError i -> QGraph.explain_elimination_error UnivNames.pr_quality_with_global_universes i | TypeError(env,te) -> let te = of_type_error te in explain_type_error env (Evd.from_env env) te | PretypeError(ctx,sigma,te) -> explain_pretype_error ctx sigma te | Clenv.ClenvCannotUnify (env, sigma, clenv, t1, t2, reason) -> let sigma, f = Clenv.replace_clenv_metas env sigma clenv in explain_pretype_error env sigma (CannotUnify (f t1, f t2, reason)) | PrimNotations.PrimTokenNotationError(kind,ctx,sigma,te) -> explain_prim_token_notation_error kind ctx sigma te | Typeclasses_errors.TypeClassError(env, sigma, te) -> explain_typeclass_error env sigma te | InductiveError (env,e) -> explain_inductive_error env e | Primred.IncompatibleDeclarations (act,x,y) -> explain_incompatible_prim_declarations act x y | Modops.ModuleTypingError e -> explain_module_error e | Modintern.ModuleInternalizationError e -> explain_module_internalization_error e | RecursionSchemeError (env,e) -> explain_recursion_scheme_error env e | Cases.PatternMatchingError (env,sigma,e) -> explain_pattern_matching_error env sigma e | Tacred.ReductionTacticError e -> explain_reduction_tactic_error e | Logic.RefinerError (env, sigma, e) -> explain_refiner_error env sigma e | Nametab.GlobalizationError q -> (* XXX also add quickfix handler *) let ppq = Libnames.string_of_qualid q in let others = (* for very small strings results are bad (eg "x not found, did you mean S") *) if String.length ppq <= 2 then [] else (* limit copied from rust (but the distance algorithm isn't exactly the same) *) Nametab.XRefs.locate_upto ~limit:(max 1 (String.length ppq / 3)) q in let ppothers = if CList.is_empty others then mt() else spc() ++ str "Did you mean" ++ spc() ++ pr_choice (fun (q',_) -> Libnames.pr_qualid q') others ++ str "?" in str "The reference" ++ spc () ++ str ppq ++ spc () ++ str "was not found" ++ spc () ++ str "in the current" ++ spc () ++ str "environment." ++ ppothers | Tacticals.FailError (i,s) -> let s = Lazy.force s in str "Tactic failure" ++ (if Pp.ismt s then s else str ": " ++ s) ++ if Int.equal i 0 then str "." else str " (level " ++ int i ++ str")." | Logic_monad.TacticFailure e -> vernac_interp_error_handler e | Environ.RewriteRulesNotAllowed symb_or_rule -> error_not_allowed_rewrite_rules symb_or_rule | _ -> raise Unhandled let _ = CErrors.register_handler (wrap_unhandled vernac_interp_error_handler) (* Locating errors *) let explain_notation_not_reference = function | Notation.AmbiguousNotationAsReference _ -> str "Ambiguous notation." | Notation.NotationNotReference (env,sigma,ntn,ntns) -> match ntns with | [] -> str "Unable to interpret " ++ quote (str ntn) ++ str " as a reference." | ntns -> let f (df, r) = str "Notation" ++ brk (1,2) ++ Notation_ops.pr_notation_info (Printer.pr_notation_interpretation_env env sigma) df r in str "Unable to unambiguously interpret " ++ quote (str ntn) ++ str " as a reference. Found:" ++ fnl () ++ v 0 (hov 0 (prlist_with_sep spc f ntns)) let _ = CErrors.register_handler (function | Notation.NotationAsReferenceError e -> Some (explain_notation_not_reference e) | _ -> None) rocq-9.2.0/vernac/himsg.mli000066400000000000000000000024131516144147600155670ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Evd.evar_map -> Pretype_errors.type_error -> Pp.t val explain_pretype_error : Environ.env -> Evd.evar_map -> Pretype_errors.pretype_error -> Pp.t val explain_refiner_error : Environ.env -> Evd.evar_map -> Logic.refiner_error -> Pp.t val explain_not_guarded : Environ.env -> Evd.evar_map -> (Environ.env * int * EConstr.t Type_errors.pcofix_guard_error) option -> (Environ.env * int * int list * EConstr.t Type_errors.pfix_guard_error) list -> EConstr.rec_declaration -> Pp.t rocq-9.2.0/vernac/indschemes.ml000066400000000000000000000637361516144147600164500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* !elim_flag) ; optwrite = (fun b -> elim_flag := b) } let bifinite_elim_flag = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Nonrecursive";"Elimination";"Schemes"]; optread = (fun () -> !bifinite_elim_flag) ; optwrite = (fun b -> bifinite_elim_flag := b) } let case_flag = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Case";"Analysis";"Schemes"]; optread = (fun () -> !case_flag) ; optwrite = (fun b -> case_flag := b) } let eq_flag = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Boolean";"Equality";"Schemes"]; optread = (fun () -> !eq_flag) ; optwrite = (fun b -> eq_flag := b) } let is_eq_flag () = !eq_flag let eq_dec_flag = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Decidable";"Equality";"Schemes"]; optread = (fun () -> !eq_dec_flag) ; optwrite = (fun b -> eq_dec_flag := b) } let rewriting_flag = ref false let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Rewriting";"Schemes"]; optread = (fun () -> !rewriting_flag) ; optwrite = (fun b -> rewriting_flag := b) } (* Util *) let define ~poly ?loc name sigma c types = let poly = PolyFlags.of_univ_poly poly (* FIXME sortpoly and cumulative not supported *) in let info = Declare.Info.make ~poly () in let cinfo = Declare.CInfo.make ~name ~typ:types () in let fth_ref = Declare.declare_definition ~info:info ~cinfo:cinfo ~opaque:false ~body:c sigma in fth_ref (* Boolean equality *) let declare_beq_scheme_gen ?locmap names kn = ignore (define_mutual_scheme ?locmap beq_scheme_kind names kn) let debug = CDebug.create ~name:"indschemes" () let alarm what internal msg = match internal with | UserAutomaticRequest -> debug Pp.(fun () -> hov 0 msg ++ fnl () ++ what ++ str " not defined."); None | UserIndividualRequest -> Some msg let try_declare_scheme ?locmap what f internal names kn = try f ?locmap names kn with e when CErrors.noncritical e -> let e = Exninfo.capture e in let rec extract_exn = function Logic_monad.TacticFailure e -> extract_exn e | e -> e in let msg = match extract_exn (fst e) with | ParameterWithoutEquality cst -> alarm what internal (str "Boolean equality not found for parameter " ++ Printer.pr_global cst ++ str".") | InductiveWithProduct -> alarm what internal (str "Unable to decide equality of functional arguments.") | InductiveWithSort -> alarm what internal (str "Unable to decide equality of type arguments.") | NonSingletonProp ind -> alarm what internal (str "Cannot extract computational content from proposition " ++ quote (Printer.pr_inductive (Global.env()) ind) ++ str ".") | EqNotFound ind' -> alarm what internal (str "Boolean equality on " ++ quote (Printer.pr_inductive (Global.env()) ind') ++ strbrk " is missing.") | UndefinedCst s -> alarm what internal (strbrk "Required constant " ++ str s ++ str " undefined.") | DeclareUniv.AlreadyDeclared (kind, id) as exn -> let msg = CErrors.print exn in alarm what internal msg | DecidabilityMutualNotSupported -> alarm what internal (str "Decidability lemma for mutual inductive types not supported.") | EqUnknown s -> alarm what internal (str "Found unsupported " ++ str s ++ str " while building Boolean equality.") | NoDecidabilityCoInductive -> alarm what internal (str "Scheme Equality is only for inductive types.") | DecidabilityIndicesNotSupported -> alarm what internal (str "Inductive types with indices not supported.") | ConstructorWithNonParametricInductiveType ind -> alarm what internal (strbrk "Unsupported constructor with an argument whose type is a non-parametric inductive type." ++ strbrk " Type " ++ quote (Printer.pr_inductive (Global.env()) ind) ++ str " is applied to an argument which is not a variable.") | InternalDependencies -> alarm what internal (strbrk "Inductive types with internal dependencies in constructors not supported.") | e -> alarm what internal (str "Unexpected error during scheme creation: " ++ CErrors.print e) in match msg with | None -> () | Some msg -> Exninfo.iraise (CErrors.UserError msg, snd e) let beq_scheme_msg mind = let mib = Global.lookup_mind mind in (* TODO: mutual inductive case *) str "Boolean equality on " ++ pr_enum (fun ind -> quote (Printer.pr_inductive (Global.env()) ind)) (List.init (Array.length mib.mind_packets) (fun i -> (mind,i))) let declare_beq_scheme_with ?locmap l kn = try_declare_scheme (beq_scheme_msg kn) declare_beq_scheme_gen UserIndividualRequest l kn let try_declare_beq_scheme ?locmap kn = (* TODO: handle Fix, eventually handle proof-irrelevance; improve decidability by depending on decidability for the parameters rather than on the bl and lb properties *) try_declare_scheme (beq_scheme_msg kn) declare_beq_scheme_gen UserAutomaticRequest [] kn let declare_beq_scheme ?locmap mi = declare_beq_scheme_with ?locmap [] mi (* Case analysis schemes *) let declare_one_case_analysis_scheme ?loc ind = let (mib, mip) as specif = Global.lookup_inductive ind in let kind = Elimschemes.pseudo_sort_quality_for_elim ind mip in let dep, suff = if Sorts.Quality.is_qprop kind then case_nodep, Some "case" else if not (Inductiveops.has_dependent_elim specif) then case_nodep, None else case_dep, Some "case" in let id = match suff with | None -> None | Some suff -> (* the auto generated eliminator may be called "case" instead of eg "case_nodep" *) Some Names.(Id.of_string (Id.to_string mip.mind_typename ^ "_" ^ suff)) in let kelim = Inductiveops.elim_sort (mib,mip) in if Inductive.raw_eliminates_to kelim Sorts.Quality.qtype then define_individual_scheme ?loc dep id ind (* Induction/recursion schemes *) let declare_one_induction_scheme ?loc ind = let (mib,mip) as specif = Global.lookup_inductive ind in let kind = Elimschemes.pseudo_sort_quality_for_elim ind mip in let from_prop = Sorts.Quality.is_qprop kind in let depelim = Inductiveops.has_dependent_elim specif in let kelim mip = Inductiveops.constant_sorts_below @@ Inductiveops.elim_sort (mib,mip) in let kelim = List.fold_right (fun x acc -> List.intersect UnivGen.QualityOrSet.equal acc x) (List.map kelim (Array.to_list mib.mind_packets)) [UnivGen.QualityOrSet.qtype; UnivGen.QualityOrSet.prop; UnivGen.QualityOrSet.set; UnivGen.QualityOrSet.sprop] in let kelim = if Global.sprop_allowed () then kelim else List.filter (fun s -> not (UnivGen.QualityOrSet.is_sprop s)) kelim in let elims = List.filter (fun (sort,_) -> List.mem_f UnivGen.QualityOrSet.equal sort kelim) [(UnivGen.QualityOrSet.qtype, "rect"); (UnivGen.QualityOrSet.prop, "ind"); (UnivGen.QualityOrSet.set, "rec"); (UnivGen.QualityOrSet.sprop, "sind")] in let elims = List.map (fun (to_kind,dflt_suff) -> if from_prop then elim_scheme ~dep:false ~to_kind, Some dflt_suff else if depelim then elim_scheme ~dep:true ~to_kind, Some dflt_suff else elim_scheme ~dep:false ~to_kind, None) elims in List.iter (fun (kind, suff) -> let id = match suff with | None -> None | Some suff -> (* the auto generated eliminator may be called "rect" instead of eg "rect_dep" *) Some Names.(Id.of_string (Id.to_string mip.mind_typename ^ "_" ^ suff)) in define_individual_scheme ?loc kind id ind) elims let declare_induction_schemes ?(locmap=Locmap.default None) kn = let mib = Global.lookup_mind kn in if mib.mind_finite <> Declarations.CoFinite then begin for i = 0 to Array.length mib.mind_packets - 1 do let loc = Ind_tables.Locmap.lookup ~locmap (kn,i) in declare_one_induction_scheme (kn,i) ?loc; done; end (* Decidable equality *) let declare_eq_decidability_gen ?locmap names kn = let mib = Global.lookup_mind kn in if mib.mind_finite <> Declarations.CoFinite then define_mutual_scheme ?locmap eq_dec_scheme_kind names kn let eq_dec_scheme_msg ind = (* TODO: mutual inductive case *) str "Decidable equality on " ++ quote (Printer.pr_inductive (Global.env()) ind) let declare_eq_decidability_scheme_with ?locmap l kn = try_declare_scheme ?locmap (eq_dec_scheme_msg (kn,0)) declare_eq_decidability_gen UserIndividualRequest l kn let try_declare_eq_decidability ?locmap kn = try_declare_scheme ?locmap (eq_dec_scheme_msg (kn,0)) declare_eq_decidability_gen UserAutomaticRequest [] kn let declare_eq_decidability ?locmap mi = declare_eq_decidability_scheme_with ?locmap [] mi let ignore_error f x = try f x with e when CErrors.noncritical e -> () let declare_rewriting_schemes ?loc ind = if Hipattern.is_inductive_equality (Global.env ()) ind then begin (* Expect the equality to be symmetric *) ignore_error (define_individual_scheme ?loc sym_scheme_kind None) ind; define_individual_scheme ?loc rew_r2l_scheme_kind None ind; define_individual_scheme ?loc rew_r2l_dep_scheme_kind None ind; define_individual_scheme ?loc rew_r2l_forward_dep_scheme_kind None ind; (* These ones expect the equality to be symmetric; the first one also *) (* needs eq *) ignore_error (define_individual_scheme rew_l2r_scheme_kind None) ind; ignore_error (define_individual_scheme ?loc sym_involutive_scheme_kind None) ind; ignore_error (define_individual_scheme ?loc rew_l2r_dep_scheme_kind None) ind; ignore_error (define_individual_scheme ?loc rew_l2r_forward_dep_scheme_kind None) ind end let warn_cannot_build_congruence = CWarnings.create ~name:"cannot-build-congruence" ~category:CWarnings.CoreCategories.automation (fun () -> strbrk "Cannot build congruence scheme because eq is not found") let declare_congr_scheme ?loc ind = let env = Global.env () in if Hipattern.is_inductive_equality env ind then begin match Rocqlib.lib_ref_opt "core.eq.type" with | Some _ -> define_individual_scheme ?loc congr_scheme_kind None ind | None -> warn_cannot_build_congruence () end (* Scheme command *) (* Boolean on scheme_type cheking if it considered dependent *) let sch_isdep = function | SchemeInduction | SchemeElimination -> true | SchemeMinimality | SchemeCase -> false let sch_isrec = function | SchemeInduction | SchemeMinimality -> true | SchemeElimination | SchemeCase -> false (* Generate suffix for scheme given a target sort *) let scheme_suffix_gen {sch_type; sch_sort} sort = let open Quality in (* The _ind/_rec_/case suffix *) let ind_suffix = match sch_isrec sch_type, sch_sort with | true , Qual (QConstant QSProp | QConstant QProp) -> "_ind" | true , _ -> "_rec" | false , _ -> "_case" in (* SProp and Type have an auxillary ending to the _ind suffix *) let aux_suffix = match sch_sort with | Qual (QConstant QSProp) -> "s" | Qual (QConstant QType) -> "t" | _ -> "" in (* Some schemes are deliminated with _dep or no_dep *) let dep_suffix = match sch_isdep sch_type , sort with | true , QConstant QProp -> "_dep" | false , QConstant QType | false , QConstant QSProp -> "_nodep" | _ , _ -> "" in ind_suffix ^ aux_suffix ^ dep_suffix let smart_ind qid = let ind = Smartlocate.smart_global_inductive qid in if Dumpglob.dump() then Dumpglob.add_glob ?loc:qid.loc (IndRef ind); ind (* Resolve the name of a scheme using an environment and extract some important data such as the inductive type involved, whether it is a dependent eliminator and its sort. *) let name_and_process_scheme env = function | (Some id, {sch_type; sch_qualid; sch_sort}) -> (id, sch_isdep sch_type, smart_ind sch_qualid, sch_sort) | (None, ({sch_type; sch_qualid; sch_sort} as sch)) -> (* If no name has been provided, we build one from the types of the ind requested *) let ind = smart_ind sch_qualid in let sort_of_ind = Elimschemes.pseudo_sort_quality_for_elim ind (snd (Inductive.lookup_mind_specif env ind)) in let suffix = scheme_suffix_gen sch sort_of_ind in let newid = Nameops.add_suffix (Nametab.basename_of_global (Names.GlobRef.IndRef ind)) suffix in let newref = CAst.make newid in (newref, sch_isdep sch_type, ind, sch_sort) let do_mutual_induction_scheme ~register ?(force_mutual=false) env ?(isrec=true) l = let sigma = Evd.from_env env in let _,_,ind,_ = match l with | x::_ -> x | [] -> assert false in let sigma, (ind, inst) = Evd.fresh_inductive_instance env sigma ~rigid:UnivRigid ind in let sigma, lrecspec = List.fold_left_map (fun sigma (_,dep,ind,sort) -> let sigma, sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in (sigma, (ind,dep,sort))) sigma l in let sigma, listdecl = if isrec then Indrec.build_mutual_induction_scheme env sigma ~force_mutual lrecspec inst else List.fold_left_map (fun sigma (ind,dep,sort) -> let sigma, c, _ = Indrec.build_case_analysis_scheme env sigma (ind, inst) dep sort in sigma, c) sigma lrecspec in let poly = (* NB: build_mutual_induction_scheme forces nonempty list of mutual inductives (force_mutual is about the generated schemes) *) let _,_,ind,_ = List.hd l in Global.is_polymorphic (Names.GlobRef.IndRef ind) in let is_mutual = isrec && List.length listdecl > 1 in let declare decl ({CAst.v=fi; loc},dep,ind, sort) = let decltype = Retyping.get_type_of env sigma decl in let cst = define ?loc ~poly fi sigma decl (Some decltype) in let kind = let open Elimschemes in let open UnivGen.QualityOrSet in if not register then None else if is_mutual then None (* don't make induction use mutual schemes *) else if isrec then Some (elim_scheme ~dep ~to_kind:sort) else match sort with | Qual (QConstant QType) -> Some (if dep then case_dep else case_nodep) | Qual (QConstant QProp) -> Some (if dep then casep_dep else casep_nodep) | Set | Qual (QConstant QSProp | QVar _) -> (* currently we don't have standard scheme kinds for this *) None in match kind with | None -> () | Some kind -> (* TODO locality *) DeclareScheme.declare_scheme SuperGlobal (Ind_tables.scheme_kind_name kind) (ind, cst) in let () = List.iter2 declare listdecl l in let lrecnames = List.map (fun ({CAst.v},_,_,_) -> v) l in Declare.fixpoint_message None lrecnames let do_scheme ~register env l = let isrec = match l with | [_, sch] -> sch_isrec sch.sch_type | _ -> if List.for_all (fun (_,sch) -> sch_isrec sch.sch_type) l then true else CErrors.user_err Pp.(str "Mutually defined schemes should be recursive.") in let lnamedepindsort = List.map (name_and_process_scheme env) l in do_mutual_induction_scheme ~register env ~isrec lnamedepindsort let do_scheme_equality ?locmap sch id = let mind,_ as ind = smart_ind id in match sch with | SchemeBooleanEquality | SchemeEquality -> declare_beq_scheme ?locmap mind; if sch = SchemeEquality then declare_eq_decidability ?locmap mind | SchemeRewriting -> let loc = Option.bind locmap (fun locmap -> Locmap.lookup ~locmap ind) in declare_rewriting_schemes ?loc ind (**********************************************************************) (* Combined scheme *) (* Matthieu Sozeau, Dec 2006 *) let list_split_rev_at index l = let rec aux i acc = function hd :: tl when Int.equal i index -> acc, tl | hd :: tl -> aux (succ i) (hd :: acc) tl | [] -> failwith "List.split_when: Invalid argument" in aux 0 [] l let fold_left' f = function [] -> invalid_arg "fold_left'" | hd :: tl -> List.fold_left f hd tl let mk_rocq_and sigma = Evd.fresh_global (Global.env ()) sigma (Rocqlib.lib_ref "core.and.type") let mk_rocq_conj sigma = Evd.fresh_global (Global.env ()) sigma (Rocqlib.lib_ref "core.and.conj") let mk_rocq_prod sigma = Evd.fresh_global (Global.env ()) sigma (Rocqlib.lib_ref "core.prod.type") let mk_rocq_pair sigma = Evd.fresh_global (Global.env ()) sigma (Rocqlib.lib_ref "core.prod.intro") let build_combined_scheme env schemes = let sigma = Evd.from_env env in let sigma, defs = List.fold_left_map (fun sigma cst -> let sigma, c = Evd.fresh_constant_instance env sigma cst in let c = on_snd (EConstr.EInstance.kind sigma) c in sigma, (c, Typeops.type_of_constant_in env c)) sigma schemes in let find_inductive ty = let (ctx, arity) = decompose_prod ty in let (_, last) = List.hd ctx in match Constr.kind last with | Constr.App (ind, args) -> let ind = Constr.destInd ind in let (_,spec) = Inductive.lookup_mind_specif env (fst ind) in ctx, ind, spec.mind_nrealargs | _ -> ctx, Constr.destInd last, 0 in let (c, t) = List.hd defs in let ctx, ind, nargs = find_inductive t in (* We check if ALL the predicates are in Prop, if so we use propositional conjunction '/\', otherwise we use the simple product '*'. *) let inprop = let inprop (_,t) = UnivGen.QualityOrSet.is_prop (Retyping.get_sort_quality_of env sigma (EConstr.of_constr t)) in List.for_all inprop defs in let mk_and, mk_conj = if inprop then (mk_rocq_and, mk_rocq_conj) else (mk_rocq_prod, mk_rocq_pair) in (* Number of clauses, including the predicates quantification *) let prods = Termops.nb_prod sigma (EConstr.of_constr t) - (nargs + 1) in let sigma, rocqand = mk_and sigma in let sigma, rocqconj = mk_conj sigma in let relargs = Termops.rel_vect 0 prods in let concls = List.rev_map (fun (cst, t) -> Constr.mkApp(Constr.mkConstU cst, relargs), snd (decompose_prod_n prods t)) defs in let concl_bod, concl_typ = fold_left' (fun (accb, acct) (cst, x) -> Constr.mkApp (EConstr.to_constr sigma rocqconj, [| x; acct; cst; accb |]), Constr.mkApp (EConstr.to_constr sigma rocqand, [| x; acct |])) concls in let ctx, _ = list_split_rev_at prods (List.rev_map (fun (x, y) -> Context.Rel.Declaration.LocalAssum (x, y)) ctx) in let typ = EConstr.of_constr @@ List.fold_left (fun d c -> Term.mkProd_wo_LetIn c d) concl_typ ctx in let body = EConstr.of_constr @@ it_mkLambda_or_LetIn concl_bod ctx in let sigma = Typing.check env sigma body typ in (sigma, body, typ) let do_combined_scheme name csts = let open CAst in let sigma,body,typ = build_combined_scheme (Global.env ()) csts in (* It is possible for the constants to have different universe polymorphism from each other, however that is only when the user manually defined at least one of them (as Scheme would pick the polymorphism of the inductive block). In that case if they want some other polymorphism they can also manually define the combined scheme. *) let poly = Global.is_polymorphic (Names.GlobRef.ConstRef (List.hd csts)) in ignore (define ~poly ?loc:name.loc name.v sigma body (Some typ)); Declare.fixpoint_message None [name.v] (**********************************************************************) (* Scheme for the all predicate and its theorem *) let do_scheme_all_predicate ?all_depth ~declare_mind kn mib strpos sAll keyAll = (* generate all predicate *) let env = Global.env () in let sigma = Evd.from_env env in let sigma, (_, u) = Evd.fresh_inductive_instance ~rigid:UState.univ_rigid env sigma (kn,0) in let (uctx, mentry) = AllScheme.generate_all_predicate env sigma kn u mib strpos sAll in (* declare it *) let poly_flag = PolyFlags.make ~univ_poly:true ~collapse_sort_variables:true ~cumulative:true in let univs = UState.univ_entry ~poly:poly_flag uctx in let kn_nested = declare_mind ?all_depth mentry univs in (* register it *) let () = Array.iteri (fun i _ -> DeclareScheme.declare_scheme SuperGlobal keyAll ((kn,i), GlobRef.IndRef (kn_nested,i)) ) mib.mind_packets in kn_nested let do_scheme_all_theorem kn mib kn_nested focus strpos sAllThm keyAllThm = (* generate all theorem *) let env = Global.env () in let sigma = Evd.from_env env in let sigma, (_, u) = Evd.fresh_inductive_instance ~sort_rigid:true ~rigid:UState.univ_rigid env sigma (kn,focus) in let (sigma, thm) = AllScheme.generate_all_theorem env sigma kn kn_nested focus u mib strpos in (* universe *) let uctx = Evd.ustate sigma in let uctx = UState.collapse_above_prop_sort_variables ~to_prop:true uctx in let uctx = UState.normalize_variables uctx in let uctx = UState.minimize uctx in let sigma = Evd.set_universe_context sigma uctx in let thm = UState.nf_universes uctx (EConstr.to_constr sigma thm) in let uctx = UState.restrict uctx (Vars.universes_of_constr thm) in let sigma = Evd.set_universe_context sigma uctx in (* declare it *) let poly_flag = PolyFlags.make ~univ_poly:true ~collapse_sort_variables:true ~cumulative:true in let info = Declare.Info.make ~poly:poly_flag () in let fth_name = Nameops.add_suffix mib.mind_packets.(focus).mind_typename sAllThm in let cinfo = Declare.CInfo.make ~name:fth_name ~typ:(None : (Evd.econstr option)) () in let fth_ref = Declare.declare_definition ~info:info ~cinfo:cinfo ~opaque:false ~body:(EConstr.of_constr thm) sigma in (* register it *) let () = DeclareScheme.declare_scheme SuperGlobal keyAllThm ((kn,focus), fth_ref) in () let do_all_forall ?(user_call_scheme=false) ?all_depth ~declare_mind kn strpos = let env = Global.env () in let mib = Environ.lookup_mind kn env in let isPrimRecord = Array.exists (fun ind -> match ind.mind_record with PrimRecord _ -> true | _ -> false) mib.mind_packets in if not isPrimRecord then begin let (strpos, (sAll, sAllThm), (keyAll, keyAllThm)) = AllScheme.compute_positive_uparams_and_suffix env kn mib strpos in if List.exists (fun b -> b) strpos then let kn_nested = do_scheme_all_predicate ?all_depth ~declare_mind kn mib strpos sAll keyAll in Array.iteri (fun focus _ -> do_scheme_all_theorem kn mib kn_nested focus strpos sAllThm keyAllThm) mib.mind_packets end else if user_call_scheme then CErrors.user_err Pp.(str "Not implemented for primitive records.") (**********************************************************************) let map_inductive_block ?(locmap=Locmap.default None) f kn n = for i=0 to n-1 do let loc = Ind_tables.Locmap.lookup ~locmap (kn,i) in f ?loc (kn,i) done type declare_mind_function = ?all_depth:int -> Entries.mutual_inductive_entry -> UState.named_universes_entry -> MutInd.t (** Depth Generation of all predicate at definition of a new inductive type *) let { Goptions.get = default_all_depth } = Goptions.declare_int_option_and_ref ~key:["Depth";"Scheme";"All"] ~value:0 () let default_all_depth kn mib = let mib = Global.lookup_mind kn in if Inductiveops.mis_is_nested kn mib then default_all_depth () -1 else default_all_depth () let declare_default_schemes ?locmap ?all_depth ~(declare_mind:declare_mind_function) kn = let mib = Global.lookup_mind kn in let all_depth = Option.default (default_all_depth kn mib) all_depth in let n = Array.length mib.mind_packets in if !elim_flag && (mib.mind_finite <> Declarations.BiFinite || !bifinite_elim_flag) && mib.mind_typing_flags.check_positive then declare_induction_schemes kn ?locmap; if all_depth > 0 && mib.mind_finite <> CoFinite then do_all_forall ~all_depth:(all_depth-1) ~declare_mind:declare_mind kn None; if !case_flag then map_inductive_block ?locmap declare_one_case_analysis_scheme kn n; if is_eq_flag() then try_declare_beq_scheme kn ?locmap; if !eq_dec_flag then try_declare_eq_decidability kn ?locmap; if !rewriting_flag then map_inductive_block ?locmap declare_congr_scheme kn n; if !rewriting_flag then map_inductive_block ?locmap declare_rewriting_schemes kn n module Internal = struct let do_scheme_all ~user_call_scheme ~declare_mind id strpos = let kn,_ = smart_ind id in do_all_forall ~user_call_scheme ~declare_mind kn strpos end rocq-9.2.0/vernac/indschemes.mli000066400000000000000000000054221516144147600166050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* MutInd.t -> unit val declare_eq_decidability : ?locmap:Ind_tables.Locmap.t -> MutInd.t -> unit (** Build and register rewriting schemes for an equality-like inductive type *) val declare_rewriting_schemes : ?loc:Loc.t -> inductive -> unit (** Mutual Minimality/Induction scheme. [force_mutual] forces the construction of eliminators having the same predicates and methods even if some of the inductives are not recursive. By default it is [false] and some of the eliminators are defined as simple case analysis. By default [isrec] is [true]. *) val do_mutual_induction_scheme : register:bool -> ?force_mutual:bool -> Environ.env -> ?isrec:bool -> resolved_scheme list -> unit (** Main calls to interpret the Scheme command *) val do_scheme : register:bool -> Environ.env -> (Id.t CAst.t option * Vernacexpr.scheme) list -> unit (** Main call to Scheme Equality command *) val do_scheme_equality : ?locmap:Ind_tables.Locmap.t -> Vernacexpr.equality_scheme_type -> Libnames.qualid Constrexpr.or_by_notation -> unit (** Combine a list of schemes into a conjunction of them *) val do_combined_scheme : lident -> Constant.t list -> unit type declare_mind_function = ?all_depth:int -> Entries.mutual_inductive_entry -> UState.named_universes_entry -> MutInd.t (** Hook called at each inductive type definition *) val declare_default_schemes : ?locmap:Ind_tables.Locmap.t -> ?all_depth:int -> declare_mind:declare_mind_function -> MutInd.t -> unit module Internal : sig (** Create the All predicate with its theorem all_forall. Use the reexported function in DeclareInd instead to avoid needing to pass [declare_mind]. *) val do_scheme_all : user_call_scheme:bool -> declare_mind:declare_mind_function -> Libnames.qualid Constrexpr.or_by_notation -> Id.t list option -> unit end rocq-9.2.0/vernac/library.ml000066400000000000000000000466401516144147600157650ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ObjFile.open_in ~file) f (************************************************************************) (** Serialized objects loaded on-the-fly *) exception Faulty of string module Delayed : sig type 'a delayed val in_delayed : string -> ObjFile.in_handle -> segment:'a ObjFile.id -> 'a delayed * Digest.t val fetch_delayed : 'a delayed -> 'a end = struct type 'a delayed = { del_file : string; del_off : int64; del_digest : Digest.t; } let in_delayed f ch ~segment = let seg = ObjFile.get_segment ch ~segment in let digest = seg.ObjFile.hash in { del_file = f; del_digest = digest; del_off = seg.ObjFile.pos; }, digest (** Fetching a table of opaque terms at position [pos] in file [f], expecting to find first a copy of [digest]. *) let fetch_delayed del = let { del_digest = digest; del_file = f; del_off = pos; } = del in let ch = open_in_bin f in let obj, digest' = try let () = LargeFile.seek_in ch pos in let obj = System.marshal_in f ch in let digest' = Digest.input ch in obj, digest' with e -> close_in ch; raise e in close_in ch; if not (String.equal digest digest') then raise (Faulty f); obj end open Delayed (************************************************************************) (*s Modules on disk contain the following informations (after the magic number, and before the digest). *) type compilation_unit_name = DirPath.t type library_disk = { md_compiled : Safe_typing.compiled_library; md_syntax_objects : Declaremods.library_objects; md_objects : Declaremods.library_objects; } type summary_disk = { md_name : compilation_unit_name; md_deps : (compilation_unit_name * Safe_typing.vodigest) array; md_ocaml : string; md_info : Library_info.t; } (*s Modules loaded in memory contain the following informations. They are kept in the global table [libraries_table]. *) type library_t = { library_name : compilation_unit_name; library_data : library_disk; library_deps : (compilation_unit_name * Safe_typing.vodigest) array; library_digests : Safe_typing.vodigest; library_info : Library_info.t; library_vm : Vmlibrary.on_disk; } (* This is a map from names to loaded libraries *) let libraries_table : library_t DirPath.Map.t ref = Summary.ref DirPath.Map.empty ~stage:Summary.Stage.Synterp ~name:"LIBRARY" (* This is the map of loaded libraries filename *) (* (not synchronized so as not to be caught in the states on disk) *) let libraries_filename_table = ref DirPath.Map.empty (* These are the _ordered_ sets of loaded, imported and exported libraries *) let libraries_loaded_list = Summary.ref [] ~stage:Summary.Stage.Synterp ~name:"LIBRARY-LOAD" let loaded_native_libraries = Summary.ref DirPath.Set.empty ~stage:Summary.Stage.Interp ~name:"NATIVE-LIBRARY-LOAD" (* Opaque proof tables *) (* various requests to the tables *) let find_library dir = DirPath.Map.find_opt dir !libraries_table let try_find_library dir = match find_library dir with | Some lib -> lib | None -> user_err (str "Unknown library " ++ DirPath.print dir ++ str ".") let library_compiled dir = let lib = Option.get @@ find_library dir in lib.library_data.md_compiled let register_library_filename dir f = (* Not synchronized: overwrite the previous binding if one existed *) (* from a previous play of the session *) libraries_filename_table := DirPath.Map.add dir f !libraries_filename_table let library_full_filename dir = try DirPath.Map.find dir !libraries_filename_table with Not_found -> "" let library_is_loaded dir = try let _ = find_library dir in true with Not_found -> false (* If a library is loaded several time, then the first occurrence must be performed first, thus the libraries_loaded_list ... *) let register_loaded_library ~root m = let libname = m.library_name in let rec aux = function | [] -> [root, libname] | (_, m') ::_ as l when DirPath.equal m' libname -> l | m'::l' -> m' :: aux l' in libraries_loaded_list := aux !libraries_loaded_list; libraries_table := DirPath.Map.add libname m !libraries_table let register_native_library libname = if (Global.typing_flags ()).enable_native_compiler && not (DirPath.Set.mem libname !loaded_native_libraries) then begin let dirname = Filename.dirname (library_full_filename libname) in loaded_native_libraries := DirPath.Set.add libname !loaded_native_libraries; Nativelib.enable_library dirname libname end let loaded_libraries () = List.map snd !libraries_loaded_list (** Delayed / available tables of opaque terms *) type table_status = | ToFetch of Opaques.opaque_disk delayed | Fetched of Opaques.opaque_disk let opaque_tables = ref (DirPath.Map.empty : table_status DirPath.Map.t) let add_opaque_table dp st = opaque_tables := DirPath.Map.add dp st !opaque_tables let access_table what tables dp i = let t = match DirPath.Map.find dp !tables with | Fetched t -> t | ToFetch f -> let dir_path = Names.DirPath.to_string dp in Flags.if_verbose Feedback.msg_info (str"Fetching " ++ str what++str" from disk for " ++ str dir_path); let t = try fetch_delayed f with Faulty f -> user_err (str "The file " ++ str f ++ str " (bound to " ++ str dir_path ++ str ") is corrupted,\ncannot load some " ++ str what ++ str " in it.\n") in tables := DirPath.Map.add dp (Fetched t) !tables; t in Opaques.get_opaque_disk i t let access_opaque_table o = let (sub, ci, dp, i) = Opaqueproof.repr o in let ans = if DirPath.equal dp (Global.current_dirpath ()) then Opaques.get_current_opaque i else let what = "opaque proofs" in access_table what opaque_tables dp i in match ans with | None -> None | Some (c, ctx) -> let (c, ctx) = Discharge.cook_opaque_proofterm ci (c, ctx) in let c = Mod_subst.subst_mps_list sub c in Some (c, ctx) let indirect_accessor = { Global.access_proof = access_opaque_table; } (************************************************************************) (* Internalise libraries *) type seg_sum = summary_disk type seg_lib = library_disk type seg_proofs = Opaques.opaque_disk type seg_vm = Vmlibrary.compiled_library let mk_library sd md digests vm = { library_name = sd.md_name; library_data = md; library_deps = sd.md_deps; library_digests = digests; library_info = sd.md_info; library_vm = vm; } let mk_intern_library sum lib digest_lib proofs vm = add_opaque_table sum.md_name (ToFetch proofs); let open Safe_typing in mk_library sum lib (Dvo_or_vi digest_lib) vm let summary_seg : seg_sum ObjFile.id = ObjFile.make_id "summary" let library_seg : seg_lib ObjFile.id = ObjFile.make_id "library" let opaques_seg : seg_proofs ObjFile.id = ObjFile.make_id "opaques" let vm_seg : seg_vm ObjFile.id = Vmlibrary.vm_segment module Intern = struct module Provenance = struct type t = string * string (** A pair of [kind, object], for example ["file", "/usr/local/foo.vo"], used for error messages. *) end type t = DirPath.t -> (library_t, Exninfo.iexn) Result.t * Provenance.t end let intern_from_file file = let ch = raw_intern_library file in let lsd, digest_lsd = ObjFile.marshal_in_segment ch ~segment:summary_seg in let lmd, digest_lmd = ObjFile.marshal_in_segment ch ~segment:library_seg in let del_opaque, _ = in_delayed file ch ~segment:opaques_seg in let vmlib = Vmlibrary.load lsd.md_name ~file ch in ObjFile.close_in ch; System.check_caml_version ~caml:lsd.md_ocaml ~file; register_library_filename lsd.md_name file; Library_info.warn_library_info ~transitive:true lsd.md_name lsd.md_info; mk_intern_library lsd lmd digest_lmd del_opaque vmlib let intern_from_file file = let provenance = ("file", file) in (* This is a barrier to catch IO / Marshal exceptions in a more structured way, as to provide better error messages. *) (match CErrors.to_result ~f:intern_from_file file with | Ok res -> Ok res | Error iexn -> Error iexn), provenance let check_library_expected_name ~provenance dir library_name = if not (DirPath.equal dir library_name) then let kind, obj = provenance in user_err (str "The " ++ str kind ++ str " " ++ str obj ++ str " contains library" ++ spc () ++ DirPath.print library_name ++ spc () ++ str "and not library" ++ spc() ++ DirPath.print dir ++ str ".") exception InternError of { exn : exn; provenance : Intern.Provenance.t; dir : DirPath.t } let () = CErrors.register_handler (function | InternError { exn; provenance; dir } -> let err = CErrors.print exn in Some (Pp.(str "Error when parsing .vo (from " ++ str (fst provenance) ++ str " " ++ str (snd provenance) ++ str ") for library " ++ Names.DirPath.print dir ++ str ": " ++ err)) | _ -> None) let error_in_intern provenance dir (exn, info) = Exninfo.iraise (InternError { exn; provenance; dir }, info) (* Returns the digest of a library, checks both caches to see what is loaded *) let rec intern_library ~root ~intern (needed, contents as acc) dir = (* Look if in the current logical environment *) match find_library dir with | Some loaded_lib -> loaded_lib, acc | None -> (* Look if already listed in the accumulator *) match DirPath.Map.find_opt dir contents with | Some interned_lib -> interned_lib, acc | None -> (* We intern the library, and then intern the deps *) match intern dir with | Ok m, provenance -> check_library_expected_name ~provenance dir m.library_name; m, intern_library_deps ~root ~intern acc dir m | Error iexn, provenance -> error_in_intern provenance dir iexn and intern_library_deps ~root ~intern libs dir m = let needed, contents = Array.fold_left (intern_mandatory_library ~intern dir) libs m.library_deps in ((root, dir) :: needed, DirPath.Map.add dir m contents ) and intern_mandatory_library ~intern caller libs (dir,d) = let m, libs = intern_library ~root:false ~intern libs dir in let digest = m.library_digests in let () = if not (Safe_typing.digest_match ~actual:digest ~required:d) then let from = library_full_filename caller in user_err (str "Compiled library " ++ DirPath.print caller ++ str " (in file " ++ str from ++ str ") makes inconsistent assumptions over library " ++ DirPath.print dir) in libs let rec_intern_library ~intern libs (loc, dir) = let m, libs = intern_library ~root:true ~intern libs dir in Library_info.warn_library_info m.library_name m.library_info; libs let native_name_from_filename f = let ch = raw_intern_library f in let lmd, digest_lmd = ObjFile.marshal_in_segment ch ~segment:summary_seg in Nativecode.mod_uid_of_dirpath lmd.md_name (**********************************************************************) (*s [require_library] loads and possibly opens a library. This is a synchronized operation. It is performed as follows: preparation phase: (functions require_library* ) the library and its dependencies are read from to disk (using intern_* ) [they are read from disk to ensure that at section/module discharging time, the physical library referred to outside the section/module is the one that was used at type-checking time in the section/module] execution phase: (through add_leaf and cache_require) the library is loaded in the environment and Nametab, the objects are registered etc, using functions from Declaremods (via load_library, which recursively loads its dependencies) *) let register_library m = let l = m.library_data in Declaremods.Interp.register_library m.library_name l.md_compiled l.md_objects m.library_digests m.library_vm ; register_native_library m.library_name let register_library_syntax (root, m) = let l = m.library_data in Declaremods.Synterp.register_library m.library_name l.md_syntax_objects; register_loaded_library ~root m (* Follow the semantics of Anticipate object: - called at module or module type closing when a Require occurs in the module or module type - not called from a library (i.e. a module identified with a file) *) let load_require _ needed = List.iter register_library needed (* [needed] is the ordered list of libraries not already loaded *) let cache_require o = load_require 1 o let discharge_require o = Some o (* open_function is never called from here because an Anticipate object *) type require_obj = library_t list let in_require : require_obj -> obj = declare_object {(default_object "REQUIRE") with cache_function = cache_require; load_function = load_require; open_function = (fun _ _ -> assert false); discharge_function = discharge_require; classify_function = (fun o -> Anticipate) } let load_require_syntax _ needed = List.iter register_library_syntax needed let cache_require_syntax o = load_require_syntax 1 o let discharge_require_syntax o = Some o (* open_function is never called from here because an Anticipate object *) type require_obj_syntax = (bool * library_t) list let in_require_syntax : require_obj_syntax -> obj = declare_object {(default_object "REQUIRE-SYNTAX") with object_stage = Summary.Stage.Synterp; cache_function = cache_require_syntax; load_function = load_require_syntax; open_function = (fun _ _ -> assert false); discharge_function = discharge_require_syntax; classify_function = (fun o -> Anticipate) } (* Require libraries, import them if [export <> None], mark them for export if [export = Some true] *) let warn_require_in_module = CWarnings.create ~name:"require-in-module" ~category:CWarnings.CoreCategories.fragile (fun () -> strbrk "Use of β€œRequire” inside a module is fragile." ++ spc() ++ strbrk "It is not recommended to use this functionality in finished proof scripts.") let require_library_from_dirpath needed = if Lib.is_module_or_modtype () then warn_require_in_module (); Lib.add_leaf (in_require needed) let require_library_syntax_from_dirpath ~intern modrefl = let needed, contents = List.fold_left (rec_intern_library ~intern) ([], DirPath.Map.empty) modrefl in let needed = List.rev_map (fun (root, dir) -> root, DirPath.Map.find dir contents) needed in Lib.add_leaf (in_require_syntax needed); List.map snd needed (************************************************************************) (*s [save_library dir] ends library [dir] and save it to the disk. *) let current_deps () = (* Only keep the roots of the dependency DAG *) let map (root, m) = if root then let m = try_find_library m in Some (m.library_name, m.library_digests) else None in List.map_filter map !libraries_loaded_list let error_recursively_dependent_library dir = user_err (strbrk "Unable to use logical name " ++ DirPath.print dir ++ strbrk " to save current library because" ++ strbrk " it already depends on a library of this name.") type 'doc todo_proofs = | ProofsTodoNone (* for .vo *) | ProofsTodoSomeEmpty of Future.UUIDSet.t (* for .vos *) (* We now use two different digests in a .vo file. The first one only covers half of the file, without the opaque table. It is used for identifying this version of this library : this digest is the one leading to "inconsistent assumptions" messages. The other digest comes at the very end, and covers everything before it. This one is used for integrity check of the whole file when loading the opaque table. *) (* Security weakness: file might have been changed on disk between writing the content and computing the checksum... *) (* EJGA: would be nice maybe to have a version that performs extra cleanup in the case the computation raises? *) let save_library_base f sum lib proofs vmlib = try let open Memprof_coq.Resource_bind in let& ch = Memprof_coq.Masking.with_resource ~acquire:raw_extern_library ~release:ObjFile.close_out f in ObjFile.marshal_out_segment ch ~segment:summary_seg sum; ObjFile.marshal_out_segment ch ~segment:library_seg lib; ObjFile.marshal_out_segment ch ~segment:opaques_seg proofs; ObjFile.marshal_out_segment ch ~segment:vm_seg vmlib with exn -> let iexn = Exninfo.capture exn in Sys.remove f; Exninfo.iraise iexn (* This is the basic vo save structure *) let save_library_struct ~output_native_objects dir = let md_compiled, md_objects, md_syntax_objects, vmlib, ast, info = Declaremods.end_library ~output_native_objects dir in let sd = { md_name = dir ; md_deps = Array.of_list (current_deps ()) ; md_ocaml = Coq_config.caml_version ; md_info = info } in let md = { md_compiled ; md_syntax_objects ; md_objects } in if Array.exists (fun (d,_) -> DirPath.equal d dir) sd.md_deps then error_recursively_dependent_library dir; sd, md, vmlib, ast let save_library dir : library_t = let sd, md, vmlib, _ast = save_library_struct ~output_native_objects:false dir in (* Digest for .vo files is on the md part, for now we also play it safe when we work on-memory and compute the digest for the lib part, even if that's slow. Better safe than sorry. *) let digest = Marshal.to_string md [] |> Digest.string in mk_library sd md (Dvo_or_vi digest) (Vmlibrary.inject vmlib) let save_library_to todo_proofs ~output_native_objects dir f = assert( let expected_extension = match todo_proofs with | ProofsTodoNone -> ".vo" | ProofsTodoSomeEmpty _ -> ".vos" in Filename.check_suffix f expected_extension); let except = match todo_proofs with | ProofsTodoNone -> Future.UUIDSet.empty | ProofsTodoSomeEmpty except -> except in (* Ensure that the call below is performed with all opaques joined *) let () = Opaques.Summary.join ~except () in let opaque_table, f2t_map = Opaques.dump ~except () in let () = assert (not (Future.UUIDSet.is_empty except) || Safe_typing.is_joined_environment (Global.safe_env ())) in let sd, md, vmlib, ast = save_library_struct ~output_native_objects dir in (* Writing vo payload *) save_library_base f sd md opaque_table vmlib; (* Writing native code files *) if output_native_objects then let fn = Filename.dirname f ^"/"^ Nativecode.mod_uid_of_dirpath dir in Nativelib.compile_library ast fn let get_used_load_paths () = String.Set.elements (List.fold_left (fun acc (root, m) -> String.Set.add (Filename.dirname (library_full_filename m)) acc) String.Set.empty !libraries_loaded_list) let _ = Nativelib.get_load_paths := get_used_load_paths rocq-9.2.0/vernac/library.mli000066400000000000000000000057671516144147600161430ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit (** Intern from a .vo file located by libresolver *) module Intern : sig module Provenance : sig type t = string * string (** A pair of [kind, object], for example ["file", "/usr/local/foo.vo"], used for error messages. *) end type t = DirPath.t -> (library_t, Exninfo.iexn) Result.t * Provenance.t end val intern_from_file : CUnix.physical_path -> (library_t, Exninfo.iexn) Result.t * Intern.Provenance.t val require_library_syntax_from_dirpath : intern:Intern.t -> DirPath.t Loc.located list -> library_t list (** {6 Start the compilation of a library } *) (** End the compilation of a library and save it to a ".vo" file, or a ".vos" file, depending on the todo_proofs argument. [output_native_objects]: when producing vo objects, also compile the native-code version. *) type 'doc todo_proofs = | ProofsTodoNone (* for .vo *) | ProofsTodoSomeEmpty of Future.UUIDSet.t (* for .vos *) val save_library_to : 'document todo_proofs -> output_native_objects:bool -> DirPath.t -> string -> unit (** Save library to library_t format, that can be used later in [require_library_syntax_from_dirpath] *) val save_library : DirPath.t -> library_t (** {6 Interrogate the status of libraries } *) (** - Tell if a library is loaded *) val library_is_loaded : DirPath.t -> bool (** - Tell which libraries are loaded, in the order by which they were loaded. *) val loaded_libraries : unit -> DirPath.t list val library_compiled : DirPath.t -> Safe_typing.compiled_library (** {6 Native compiler. } *) val native_name_from_filename : string -> string (** {6 Opaque accessors} *) val indirect_accessor : Global.indirect_accessor [@@deprecated "(8.20) Most commands should not be accessing opaque data. \ Use coqpp's \"opaque_access\" state specifier if you actually need it."] rocq-9.2.0/vernac/loadpath.ml000066400000000000000000000301351516144147600161050ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* raise Not_found | [p] -> p | _ -> anomaly_too_many_paths phys_dir (* get the list of load paths that correspond to a given logical path *) let find_with_logical_path dirpath = List.filter (fun p -> Names.DirPath.equal p.path_logical dirpath) !load_paths let warn_file_found_multiple_times = CWarnings.create ~name:"ambiguous-extra-dep" ~category:CWarnings.CoreCategories.filesystem (fun (file,from,other,extra) -> Pp.(str "File " ++ str file ++ str " found twice in " ++ Names.DirPath.print from ++ str":" ++ spc () ++ str other ++ str " (selected)," ++ spc() ++ str extra ++ str ".") ) let rec first_path_containing ?loc from file acc = function | [] -> begin match acc with | Some x -> x | None -> CErrors.user_err Pp.(str "File " ++ str file ++ str " not found in " ++ Names.DirPath.print from ++ str".") end | x :: xs -> let abspath = x ^ "/" ^ file in if Sys.file_exists abspath then begin match acc with | None -> first_path_containing ?loc from file (Some abspath) xs | Some other -> warn_file_found_multiple_times ?loc (file,from,other,abspath); first_path_containing ?loc from file acc xs end else first_path_containing ?loc from file acc xs let find_extra_dep_with_logical_path ?loc ~from ~file () = match find_with_logical_path from with | _ :: _ as paths -> let paths = List.map physical paths in first_path_containing ?loc from file None paths | [] -> CErrors.user_err Pp.(str "No LoadPath found for " ++ Names.DirPath.print from ++ str".") let remove_load_path dir = let filter p = not (String.equal p.path_physical dir) in load_paths := List.filter filter !load_paths let warn_overriding_logical_loadpath = CWarnings.create ~name:"overriding-logical-loadpath" ~category:CWarnings.CoreCategories.filesystem (fun (phys_path, old_path, rocq_path) -> Pp.(seq [str phys_path; strbrk " was previously bound to " ; DP.print old_path; strbrk "; it is remapped to " ; DP.print rocq_path])) let add_load_path ~installed phys_path rocq_path ~implicit = let phys_path = CUnix.canonical_path_name phys_path in let filter p = String.equal p.path_physical phys_path in let binding = { path_logical = rocq_path; path_physical = phys_path; path_implicit = implicit; path_installed = installed; } in match List.filter filter !load_paths with | [] -> load_paths := binding :: !load_paths | [{ path_logical = old_path; path_implicit = old_implicit }] -> let replace = if DP.equal rocq_path old_path then implicit <> old_implicit else let () = (* Do not warn when overriding the default "-I ." path *) if not (DP.equal old_path Libnames.default_root_prefix) then warn_overriding_logical_loadpath (phys_path, old_path, rocq_path) in true in if replace then begin remove_load_path phys_path; load_paths := binding :: !load_paths; end | _ -> anomaly_too_many_paths phys_path let filter_path f = let rec aux = function | [] -> [] | p :: l -> if f p.path_logical then (p.path_physical, p.path_logical) :: aux l else aux l in aux !load_paths let add_path ~is_installed file (installed, local) = if is_installed then file :: installed, local else installed, file::local let expand_path ?root dir = let exact_path = match root with None -> dir | Some root -> Libnames.append_dirpath root dir in let aux { path_physical = ph; path_logical = lg; path_implicit = implicit; path_installed } (full, others) = if DP.equal exact_path lg then (* Most recent full match comes first *) let full_installed, full_local = full in let v = (ph, lg) in let full = if path_installed then v :: full_installed, full_local else full_installed, v :: full_local in full, others else let success = match root with | None -> implicit && Libnames.is_dirpath_suffix_of dir lg | Some root -> Libnames.(is_dirpath_prefix_of root lg && is_dirpath_suffix_of dir (drop_dirpath_prefix root lg)) in if success then full, add_path ~is_installed:path_installed (ph, lg) others else full, others in let full, others = List.fold_right aux !load_paths (([],[]), ([], [])) in (* Returns the dirpath matching exactly and the ordered list of -R/-Q blocks with subdirectories that matches *) full, others let locate_file fname = let paths = List.map physical !load_paths in let _,longfname = System.find_file_in_path ~warn:(not !Flags.quiet) paths fname in longfname (************************************************************************) (*s Locate absolute or partially qualified library names in the path *) module Error = struct type t = LibUnmappedDir | LibNotFound let unmapped_dir qid = let prefix, _ = Libnames.repr_qualid qid in CErrors.user_err Pp.(seq [ str "Cannot load "; Libnames.pr_qualid qid; str ":"; spc () ; str "no physical path bound to"; spc () ; Names.DirPath.print prefix; fnl () ]) let lib_not_found dir = let vos = !load_vos_libraries in let vos_msg = if vos then [Pp.str " (while searching for a .vos file)"] else [] in CErrors.user_err Pp.(seq ([ str "Cannot find library "; Names.DirPath.print dir; str" in loadpath"]@vos_msg)) let raise dp = function | LibUnmappedDir -> unmapped_dir (Libnames.qualid_of_dirpath dp) | LibNotFound -> lib_not_found dp end (* If [!Flags.load_vos_libraries] and the .vos file exists and this file is not empty Then load this library Else load the .vo file or raise error if both are missing *) let select_vo_file ~find base = let find ext = try let name = Names.Id.to_string base ^ ext in let lpath, file = find name in Some (lpath, file) with Not_found -> None in if !load_vos_libraries then begin match find ".vos" with | Some (_, vos) as resvos when (Unix.stat vos).Unix.st_size > 0 -> resvos | _ -> find ".vo" end else find ".vo" let find_first loadpath base = match System.all_in_path loadpath base with | [] -> raise Not_found | f :: _ -> f let find_unique fullqid loadpath base = match System.all_in_path loadpath base with | [] -> raise Not_found | [f] -> f | _::_ as l -> CErrors.user_err Pp.(str "Required library " ++ Libnames.pr_qualid fullqid ++ strbrk " matches several files in path (found " ++ pr_enum str (List.map snd l) ++ str ").") let locate_absolute_library dir : (CUnix.physical_path, Error.t) Result.t = (* Search in loadpath *) let pref, base = Libnames.split_dirpath dir in let loadpath = filter_path (fun dir -> DP.equal dir pref) in match loadpath with | [] -> Error LibUnmappedDir | _ -> match select_vo_file ~find:(find_first loadpath) base with | Some (_, file) -> Ok file | None -> Error Error.LibNotFound let locate_qualified_library ?root qid : (DP.t * CUnix.physical_path, Error.t) Result.t = (* Search library in loadpath *) let dir, base = Libnames.repr_qualid qid in match expand_path ?root dir with | ([], []), ([], []) -> Error LibUnmappedDir | (full_installed, full_local), (installed, local) -> let result = (* Priority to exact matches, then priority to local matches *) List.find_map (fun block -> select_vo_file ~find:(find_unique qid block) base) [full_local; full_installed; local; installed] in match result with | Some (dir,file) -> let library = Libnames.add_dirpath_suffix dir base in Ok (library, file) | None -> Error Error.LibNotFound let warn_deprecated_missing_stdlib = CWarnings.create ~name:"deprecated-missing-stdlib" ~category:Deprecation.Version.v9_0 (fun qid -> Pp.(str "Loading Stdlib without prefix is deprecated." ++ spc () ++ str "Use \"From Stdlib Require " ++ Libnames.pr_qualid qid ++ str "\"" ++ spc() ++ str "or the deprecated \"From Coq Require " ++ Libnames.pr_qualid qid ++ str "\"" ++ spc () ++ str "for compatibility with older Coq versions.")) (* temporary handling deprecated loading of stdlib without root *) let locate_qualified_library ?root qid = let root_stdlib = Names.(Libnames.add_dirpath_suffix DirPath.empty (Id.of_string "Stdlib")) in match root, locate_qualified_library ?root qid with | Some _, r | None, (Ok _ as r) -> r | None, (Error _ as e) -> match locate_qualified_library ~root:root_stdlib qid with | Error _ -> e | Ok _ as o -> warn_deprecated_missing_stdlib ?loc:qid.loc qid; o (** { 5 Extending the load path } *) type vo_path = { unix_path : string ; coq_path : DP.t ; implicit : bool ; recursive : bool ; installed : bool } let warn_cannot_open_path = CWarnings.create ~name:"cannot-open-path" ~category:CWarnings.CoreCategories.filesystem (fun unix_path -> Pp.(str "Cannot open " ++ str unix_path)) let warn_cannot_use_directory = CWarnings.create ~name:"cannot-use-directory" ~category:CWarnings.CoreCategories.filesystem (fun d -> Pp.(str "Directory " ++ str d ++ strbrk " cannot be used as a Rocq identifier (skipped)")) let convert_string d = try Names.Id.of_string d with | CErrors.UserError _ -> let d = Unicode.escaped_if_non_utf8 d in warn_cannot_use_directory d; raise_notrace Exit let add_vo_path lp = let unix_path = lp.unix_path in let implicit = lp.implicit in let recursive = lp.recursive in let installed = lp.installed in if System.exists_dir unix_path then let dirs = if recursive then System.all_subdirs ~unix_path else [] in let dirs = List.sort (fun a b -> String.compare (fst a) (fst b)) dirs in let prefix = DP.repr lp.coq_path in let convert_dirs (lp, cp) = try let path = List.rev_map convert_string cp @ prefix in Some (lp, DP.make path) with Exit -> None in let dirs = List.map_filter convert_dirs dirs in let add (path, dir) = add_load_path ~installed path ~implicit dir in (* deeper dirs registered first and thus be found last *) let dirs = List.rev dirs in let () = List.iter add dirs in add_load_path ~installed unix_path ~implicit lp.coq_path else warn_cannot_open_path unix_path rocq-9.2.0/vernac/loadpath.mli000066400000000000000000000070631516144147600162620ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* DirPath.t (** Get the logical path (Rocq module hierarchy) of a loadpath. *) val physical : t -> CUnix.physical_path (** Get the physical path of a loadpath *) val pp : t -> Pp.t (** Print a load path *) val get_load_paths : unit -> t list (** Get the current loadpath association. *) val remove_load_path : CUnix.physical_path -> unit (** Remove the current logical path binding associated to a given physical path, if any. *) val find_load_path : CUnix.physical_path -> t (** Get the binding associated with a physical path. Raises [Not_found] if there is none. *) val find_with_logical_path : Names.DirPath.t -> t list (** get the list of load paths that correspond to a given logical path *) val find_extra_dep_with_logical_path : ?loc:Loc.t -> from:Names.DirPath.t -> file:string -> unit -> CUnix.physical_path (** finds a file rooted in from. @raise UserError if the file is not found *) val locate_file : string -> string (** Locate a file among the registered paths. Do not use this function, as it does not respect the visibility of paths. *) (** {6 Locate a library in the load path } *) module Error : sig type t = LibUnmappedDir | LibNotFound (** Raise regular Rocq errors with default informative message; usually document managers that have more information about the workspace than rocq compile will override this with a better mechanism / message. *) val raise : DirPath.t -> t -> 'a end val locate_qualified_library : ?root:DirPath.t -> Libnames.qualid -> (DirPath.t * CUnix.physical_path, Error.t) Result.t (** Locates a library by implicit name. @return LibUnmappedDir if the library is not in the path @return LibNotFound if there is no corresponding file in the path *) val locate_absolute_library : DirPath.t -> (CUnix.physical_path, Error.t) Result.t (** {6 Extending the Load Path } *) (** Adds a path to the Rocq and ML paths *) type vo_path = { unix_path : string (** Filesystem path containing vo/ml files *) ; coq_path : DirPath.t (** Rocq prefix for the path *) ; implicit : bool (** [implicit = true] avoids having to qualify with [coq_path] true for -R, false for -Q in command line *) ; recursive : bool (** [recursive] will determine whether we explore sub-directories *) ; installed : bool (** [installed] is true for automatically added paths (eg user-contrib), which are assumed to be installed files. False is assumed to be local files (ie current development). *) } val add_vo_path : vo_path -> unit (** Flag to indicate that .vos files should be loaded for dependencies instead of .vo files. Used by -vos and -vok options. *) val load_vos_libraries : bool ref rocq-9.2.0/vernac/metasyntax.ml000066400000000000000000002657531516144147600165260ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some Pp.(str "Unknown custom entry: " ++ pr_qualid entry ++ str ".") | _ -> None let compat_custom_names = Summary.ref ~stage:Synterp ~name:"compat-custom-names" Id.Map.empty let add_custom_compat kn = let id = CustomName.label kn in compat_custom_names := Id.Map.update id (fun existing -> Some (kn :: Option.default [] existing)) !compat_custom_names let warn_compat_custom = CWarnings.create ~name:"deprecated-unqualified-custom-entry" ~category:Deprecation.Version.v9_2 ~quickfix:(fun ~loc custom -> [Quickfix.make ~loc (Nametab.CustomEntries.pr custom)]) Pp.(fun custom -> str "Accessing custom entry " ++ Nametab.CustomEntries.pr custom ++ str " by its unqualified name is deprecated.") let intern_custom_name qid = match Nametab.CustomEntries.locate qid with | v -> v | exception Not_found -> let compat = if qualid_is_ident qid then Id.Map.find_opt (qualid_basename qid) !compat_custom_names else None in match compat with | None -> Loc.raise ?loc:qid.loc (UnknownCustomEntry qid) | Some [] -> assert false | Some [custom] -> warn_compat_custom ?loc:qid.loc custom; custom | Some customs -> user_err ?loc:qid.loc Pp.(pr_qualid qid ++ str " is ambiguous: it may refer to any of " ++ pr_choice Nametab.CustomEntries.pr customs ++ str ".") let intern_notation_entry = function | InConstrEntry -> InConstrEntry | InCustomEntry qid -> InCustomEntry (intern_custom_name qid) (** **************************************************************** **) (** Printing grammar entries **) let entry_buf = Buffer.create 64 let pr_entry e = let () = Buffer.clear entry_buf in let ft = Format.formatter_of_buffer entry_buf in let () = Procq.Entry.print ft e in str (Buffer.contents entry_buf) let error_unknown_entry ?loc name = user_err ?loc Pp.(str "Unknown or unprintable grammar entry " ++ str name ++ str".") let pr_grammar_subset grammar = let pp = String.Map.mapi (fun name l -> match l with | [] -> assert false | entries -> str "Entry " ++ str name ++ str " is" ++ fnl() ++ prlist_with_sep (fun () -> str "or" ++ fnl()) (fun (Procq.Entry.Any e) -> pr_entry e) entries) grammar in let pp = CString.Map.bindings pp in prlist_with_sep fnl (fun (_,pp) -> pp) pp let is_known = let open Procq.Entry in function | "constr" | "term" | "binder_constr" -> Some [ Any Procq.Constr.constr; Any Procq.Constr.lconstr; Any Procq.Constr.binder_constr; Any Procq.Constr.term; ] | "vernac" -> Some Pvernac.Vernac_.[ Any vernac_control; (* main_entry="vernac", included not because it's interesting but because otherwise it's shadowed by the "vernac" group defined here *) Any main_entry; Any command; Any syntax; Any gallina; Any gallina_ext; ] | name -> let gram = Procq.find_grammars_by_name name in match gram with | [] -> None | entries -> Some entries let full_grammar () = let open Pvernac.Vernac_ in let open Procq.Entry in let proof_modes = List.map (fun (_,Pvernac.ProofMode e) -> Any e.command_entry) (CString.Map.bindings (Pvernac.list_proof_modes())) in let entries = (Any main_entry) :: (Any noedit_mode) :: proof_modes in Procq.Entry.accumulate_in entries let same_entry (Procq.Entry.Any e) (Procq.Entry.Any e') = (Obj.magic e) == (Obj.magic e') let pr_grammar = function | [] -> let grammar = full_grammar () in pr_grammar_subset grammar | ["Full"] -> let grammar = Procq.Entry.all_in () in pr_grammar_subset grammar | names -> let known, other = List.fold_left (fun (known,other) name -> match is_known name with | Some v -> v @ known, other | None -> known, name::other) ([],[]) names in let grammar = if List.is_empty other then String.Map.empty else full_grammar () in let () = List.iter (fun name -> if not (String.Map.mem name grammar) then error_unknown_entry name) other in let other = String.Set.of_list other in let grammar = String.Map.filter (fun name _ -> String.Set.mem name other) grammar in let grammar = List.fold_left (fun grammar (Procq.Entry.Any e as any) -> String.Map.update (Procq.Entry.name e) (function | None -> Some [any] | Some vl as v -> if List.mem_f same_entry any vl then v else Some (any :: vl)) grammar) grammar known in pr_grammar_subset grammar let custom_grammars = ref [] let register_custom_grammar_for_print h = custom_grammars := h :: !custom_grammars let () = register_custom_grammar_for_print @@ fun name -> try let name = intern_custom_name name in let constr_entry, _ = Egramrocq.find_custom_entry name in Some [Procq.Entry.Any constr_entry] with UnknownCustomEntry _ -> None let get_custom_grammars name = let entries = List.filter_map (fun f -> f name) !custom_grammars in match entries with | [] -> raise (UnknownCustomEntry name) | _ :: _ -> List.flatten entries let pr_custom_grammar name = let entries = get_custom_grammars name in let add_entry map (Procq.Entry.Any e as any) = String.Map.update (Procq.Entry.name e) (fun entries -> Some (any :: Option.default [] entries)) map in let map = List.fold_left add_entry String.Map.empty entries in pr_grammar_subset map let pr_keywords () = Pp.prlist_with_sep Pp.fnl Pp.str (CString.Set.elements (CLexer.keywords (Procq.get_keyword_state()))) (** **************************************************************** **) (** Parse a format (every terminal starting with a letter or a single quote (except a single quote alone) must be quoted) **) let parse_format ({CAst.loc;v=str} : lstring) = let len = String.length str in (* TODO: update the line of the location when the string contains newlines *) let make_loc i j = Option.map (Loc.shift_loc (i+1) (j-len)) loc in let push_token loc a = function | (i,cur)::l -> (i,(loc,a)::cur)::l | [] -> assert false in let push_white i n l = if Int.equal n 0 then l else push_token (make_loc i (i+n)) (UnpTerminal (String.make n ' ')) l in let close_box start stop b = function | (_,a)::(_::_ as l) -> push_token (make_loc start stop) (UnpBox (b,a)) l | [a] -> user_err ?loc:(make_loc start stop) Pp.(str "Non terminated box in format.") | [] -> assert false in let close_quotation start i = if i < len && str.[i] == '\'' then if (Int.equal (i+1) len || str.[i+1] == ' ') then i+1 else user_err ?loc:(make_loc (i+1) (i+1)) Pp.(str "Space expected after quoted expression.") else user_err ?loc:(make_loc start (i-1)) Pp.(str "Beginning of quoted expression expected to be ended by a quote.") in let rec spaces n i = if i < len && str.[i] == ' ' then spaces (n+1) (i+1) else n in let rec nonspaces quoted n i = if i < len && str.[i] != ' ' then if str.[i] == '\'' && quoted && (i+1 >= len || str.[i+1] == ' ') then if Int.equal n 0 then user_err ?loc:(make_loc (i-1) i) Pp.(str "Empty quoted token.") else n else nonspaces quoted (n+1) (i+1) else if quoted then user_err ?loc:(make_loc i i) Pp.(str "Spaces are not allowed in (quoted) symbols.") else n in let rec parse_non_format i = let n = nonspaces false 0 i in push_token (make_loc i (i+n-1)) (UnpTerminal (String.sub str i n)) (parse_token 1 (i+n)) and parse_quoted n k i = if i < len then match str.[i] with (* Parse " // " *) | '/' when i+1 < len && str.[i+1] == '/' -> (* We discard the useless n spaces... *) push_token (make_loc (i-n) (i+1)) (UnpCut PpFnl) (parse_token 1 (close_quotation i (i+2))) (* Parse " .. / .. " *) | '/' when i+1 < len -> let p = spaces 0 (i+1) in push_token (make_loc (i-n) (i+p)) (UnpCut (PpBrk (n,p))) (parse_token 1 (close_quotation i (i+p+1))) | c -> (* The spaces are real spaces *) push_white (i-n-1-k) n (match c with | '[' -> if i+1 < len then match str.[i+1] with (* Parse " [h .. ", *) | 'h' when i+1 <= len && str.[i+2] == 'v' -> (parse_box i (fun n -> PpHVB n) (i+3)) (* Parse " [v .. ", *) | 'v' -> parse_box i (fun n -> PpVB n) (i+2) (* Parse " [ .. ", *) | ' ' | '\'' -> parse_box i (fun n -> PpHOVB n) (i+1) | _ -> user_err ?loc:(make_loc i i) Pp.(str "\"v\", \"hv\", \" \" expected after \"[\" in format.") else user_err ?loc:(make_loc i i) Pp.(str "\"v\", \"hv\" or \" \" expected after \"[\" in format.") (* Parse "]" *) | ']' -> ((i,[]) :: parse_token 1 (close_quotation i (i+1))) (* Parse a non formatting token *) | c -> let n = nonspaces true 0 i in push_token (make_loc i (i+n-1)) (UnpTerminal (String.sub str (i-1) (n+2))) (parse_token 1 (close_quotation i (i+n)))) else if Int.equal n 0 then [] else user_err ?loc:(make_loc (len-n) len) Pp.(str "Ending spaces non part of a format annotation.") and parse_box start box i = let n = spaces 0 i in close_box start (i+n-1) (box n) (parse_token 1 (close_quotation i (i+n))) and parse_token k i = let n = spaces 0 i in let i = i+n in if i < len then match str.[i] with (* Parse a ' *) | '\'' when i+1 >= len || str.[i+1] == ' ' -> push_white (i-n) (n-k) (push_token (make_loc i (i+1)) (UnpTerminal "'") (parse_token 1 (i+1))) (* Parse the beginning of a quoted expression *) | '\'' -> parse_quoted (n-k) k (i+1) (* Otherwise *) | _ -> push_white (i-n) (n-k) (parse_non_format i) else push_white (i-n) n [(len,[])] in if not (String.is_empty str) then match parse_token 0 0 with | [_,l] -> l | (i,_)::_ -> user_err ?loc:(make_loc i i) Pp.(str "Box closed without being opened.") | [] -> assert false else [] (** **************************************************************** **) (** Analyzing notations **) (* Find non-terminal tokens of notation *) (* To protect alphabetic tokens and quotes from being seen as variables *) let quote_notation_token x = let n = String.length x in let norm = CLexer.is_ident x in if (n > 0 && norm) || (n > 2 && x.[0] == '\'') then "'"^x^"'" else x let analyze_notation_tokens ~onlyprinting ~infix entry df = let df = if infix then quote_notation_token df else df in let { recvars; mainvars; symbols } as res = decompose_raw_notation df in (* don't check for nonlinearity if printing only, see Bug 5526 *) (if not onlyprinting then match List.duplicates Id.equal (mainvars @ List.map snd recvars) with | id :: _ -> user_err (str "Variable " ++ Id.print id ++ str " occurs more than once.") | _ -> ()); let is_prim_token = is_prim_token_constant_in_constr (entry, symbols) in res, is_prim_token let adjust_symbols vars notation_symbols = let x = Namegen.next_ident_away (Id.of_string "x") vars in let y = Namegen.next_ident_away (Id.of_string "y") (Id.Set.add x vars) in let notation_symbols = { recvars = notation_symbols.recvars; mainvars = x::notation_symbols.mainvars@[y]; symbols = NonTerminal x :: notation_symbols.symbols @ [NonTerminal y]; } in x, y, notation_symbols let adjust_reserved_infix_notation notation_symbols = let vars = Id.Set.of_list (List.map_filter (function NonTerminal x -> Some x | _ -> None) notation_symbols.symbols) in let _, _, notation_symbols = adjust_symbols vars notation_symbols in notation_symbols let adjust_infix_notation df notation_symbols c = let vars = names_of_constr_expr c in let x, y, notation_symbols = adjust_symbols vars notation_symbols in let df = Id.to_string x ^ " " ^ df ^ " " ^ Id.to_string y in let inject_var x = CAst.make @@ CRef (qualid_of_ident x,None) in let metas = [inject_var x; inject_var y] in let c = mkAppC (c,metas) in df, notation_symbols, c let warn_unexpected_primitive_token_modifier = CWarnings.create ~name:"primitive-token-modifier" ~category:CWarnings.CoreCategories.parsing (fun () -> str "Notations for numbers or strings are primitive; skipping this modifier.") let check_no_syntax_modifiers_for_numeral = function | [] -> () | l -> List.iter (function {CAst.loc} -> warn_unexpected_primitive_token_modifier ?loc ()) l let error_not_same_scope x y = user_err (str "Variables " ++ Id.print x ++ str " and " ++ Id.print y ++ str " must be in the same scope.") (** **************************************************************** **) (** Build pretty-printing rules **) let pr_notation_entry = function | InConstrEntry -> str "constr" | InCustomEntry s -> str "custom " ++ Nametab.CustomEntries.pr s let side = function | BorderProd (b,_) -> Some b | _ -> None let precedence_of_position_and_level from_level = function | NumLevel n, BorderProd (b,Some a) -> let prec = let open Gramlib.Gramext in match a, b with | RightA, Left -> LevelLt n | RightA, Right -> LevelLe n | LeftA, Left -> LevelLe n | LeftA, Right -> LevelLt n | NonA, _ -> LevelLt n | BothA, _ -> assert false in {notation_subentry = InConstrEntry; notation_relative_level = prec; notation_position = Some b} | NumLevel n, b -> {notation_subentry = InConstrEntry; notation_relative_level = LevelLe n; notation_position = side b} | NextLevel, b -> {notation_subentry = InConstrEntry; notation_relative_level = LevelLt from_level; notation_position = side b} | DefaultLevel, b -> {notation_subentry = InConstrEntry; notation_relative_level = LevelSome; notation_position = side b} (** Computing precedences of non-terminals for parsing *) let precedence_of_entry_type { notation_entry = from_custom; notation_level = from_level } = function | ETConstr (custom,_,x) when notation_entry_eq custom from_custom -> (precedence_of_position_and_level from_level x).notation_relative_level | ETConstr (custom,_,(NumLevel n,_)) -> LevelLe n | ETConstr (custom,_,(NextLevel,_)) -> user_err (strbrk "\"next level\" is only for sub-expressions in the same entry as where the notation is (" ++ quote (pr_notation_entry custom) ++ strbrk " is different from " ++ quote (pr_notation_entry from_custom) ++ str ").") | ETPattern (_,n) -> let n = match n with None -> 0 | Some n -> n in LevelLe n | _ -> LevelSome (* should not matter *) let pattern_entry_level = function None -> 0 | Some n -> n (** Computing precedences for future insertion of parentheses at the time of printing using hard-wired constr levels *) let unparsing_precedence_of_entry_type from_level = function | ETConstr (InConstrEntry,_,x) -> (* Possible insertion of parentheses at printing time to deal with precedence in a constr entry is managed using [prec_less] in [ppconstr.ml] *) precedence_of_position_and_level from_level x | ETConstr (custom,_,(_,b)) -> (* Precedence of printing for a custom entry is managed using explicit insertion of entry coercions at the time of building a [constr_expr] *) {notation_subentry = custom; notation_relative_level = LevelSome; notation_position = side b} | ETPattern (_,n) -> (* in constr *) {notation_subentry = InConstrEntry; notation_relative_level = LevelLe (pattern_entry_level n); notation_position = None} | _ -> (* should not matter *) {notation_subentry = InConstrEntry; notation_relative_level = LevelSome; notation_position = None} (** Utilities for building default printing rules *) (* Some breaking examples *) (* "x = y" : "x /1 = y" (breaks before any symbol) *) (* "x =S y" : "x /1 =S /1 y" (protect from confusion; each side for symmetry)*) (* "+ {" : "+ {" may breaks reversibility without space but oth. not elegant *) (* "x y" : "x spc y" *) (* "{ x } + { y }" : "{ x } / + { y }" *) (* "< x , y > { z , t }" : "< x , / y > / { z , / t }" *) let starts_with_left_bracket s = let l = String.length s in not (Int.equal l 0) && (s.[0] == '{' || s.[0] == '[' || s.[0] == '(') let ends_with_right_bracket s = let l = String.length s in not (Int.equal l 0) && (s.[l-1] == '}' || s.[l-1] == ']' || s.[l-1] == ')') let is_left_bracket s = starts_with_left_bracket s && not (ends_with_right_bracket s) let is_right_bracket s = not (starts_with_left_bracket s) && ends_with_right_bracket s let is_comma s = let l = String.length s in not (Int.equal l 0) && (s.[0] == ',' || s.[0] == ';') let is_operator s = let l = String.length s in not (Int.equal l 0) && (s.[0] == '+' || s.[0] == '*' || s.[0] == '=' || s.[0] == '-' || s.[0] == '/' || s.[0] == '<' || s.[0] == '>' || s.[0] == '@' || s.[0] == '\\' || s.[0] == '&' || s.[0] == '~' || s.[0] == '$') let is_non_terminal = function | NonTerminal _ | SProdList _ -> true | _ -> false let is_next_non_terminal b = function | [] -> b | pr :: _ -> is_non_terminal pr let is_next_terminal = function Terminal _ :: _ -> true | _ -> false let is_next_break = function Break _ :: _ -> true | _ -> false let add_break n l = (None,UnpCut (PpBrk(n,0))) :: l let add_break_if_none n b = function | (_,UnpCut (PpBrk _)) :: _ as l -> l | [] when not b -> [] | l -> (None,UnpCut (PpBrk(n,0))) :: l let check_open_binder isopen sl m = let pr_token = function | Terminal s -> str s | Break n -> str "␣" | _ -> assert false in if isopen && not (List.is_empty sl) then user_err (str "as " ++ Id.print m ++ str " is a non-closed binder, no such \"" ++ prlist_with_sep spc pr_token sl ++ strbrk "\" is allowed to occur.") let unparsing_metavar i from typs = let x = List.nth typs (i-1) in let subentry = unparsing_precedence_of_entry_type from x in match x with | ETConstr _ | ETGlobal | ETBigint -> UnpMetaVar subentry | ETPattern _ | ETName | ETIdent -> UnpBinderMetaVar (subentry,NotQuotedPattern) | ETBinder isopen -> UnpBinderMetaVar (subentry,QuotedPattern) (** Heuristics for building default printing rules *) let index_id id l = List.index Id.equal id l let make_hunks etyps symbols from_level = let vars,typs = List.split etyps in let rec make b = function | NonTerminal m :: prods -> let i = index_id m vars in let u = unparsing_metavar i from_level typs in if is_next_non_terminal b prods then (None, u) :: add_break_if_none 1 b (make b prods) else (None, u) :: make_with_space b prods | Terminal s :: prods when (* true to simulate presence of non-terminal *) b || List.exists is_non_terminal prods -> if (is_comma s || is_operator s) then (* Always a breakable space after comma or separator *) (None, UnpTerminal s) :: add_break_if_none 1 b (make b prods) else if is_right_bracket s && is_next_terminal prods then (* Always no space after right bracked, but possibly a break *) (None, UnpTerminal s) :: add_break_if_none 0 b (make b prods) else if is_left_bracket s && is_next_non_terminal b prods then (None, UnpTerminal s) :: make b prods else if not (is_next_break prods) then (* Add rigid space, no break, unless user asked for something *) (None, UnpTerminal (s^" ")) :: make b prods else (* Rely on user spaces *) (None, UnpTerminal s) :: make b prods | Terminal s :: prods -> (* Separate but do not cut a trailing sequence of terminal *) (match prods with | Terminal _ :: _ -> (None,UnpTerminal (s^" ")) :: make b prods | _ -> (None,UnpTerminal s) :: make b prods) | Break n :: prods -> add_break n (make b prods) | SProdList (m,sl) :: prods -> let i = index_id m vars in let typ = List.nth typs (i-1) in let subentry = unparsing_precedence_of_entry_type from_level typ in let sl' = (* If no separator: add a break *) if List.is_empty sl then add_break 1 [] (* We add NonTerminal for simulation but remove it afterwards *) else make true sl in let hunk = match typ with | ETConstr _ -> UnpListMetaVar (subentry,List.map snd sl') | ETBinder isopen -> check_open_binder isopen sl m; UnpBinderListMetaVar (isopen,true,List.map snd sl') | ETName | ETIdent -> UnpBinderListMetaVar (false,true,List.map snd sl') | ETPattern _ -> UnpBinderListMetaVar (false,false,List.map snd sl') | _ -> assert false in (None, hunk) :: make_with_space b prods | [] -> [] and make_with_space b prods = match prods with | Terminal s' :: prods'-> if is_operator s' then (* A rigid space before operator and a breakable after *) (None,UnpTerminal (" "^s')) :: add_break_if_none 1 b (make b prods') else if is_comma s' then (* No space whatsoever before comma *) make b prods else if is_right_bracket s' then make b prods else (* A breakable space between any other two terminals *) add_break_if_none 1 b (make b prods) | (NonTerminal _ | SProdList _) :: _ -> (* A breakable space before a non-terminal *) add_break_if_none 1 b (make b prods) | Break _ :: _ -> (* Rely on user wish *) make b prods | [] -> [] in make false symbols (** Build default printing rules from explicit format *) let error_format ?loc () = user_err ?loc Pp.(str "The format does not match the notation.") let warn_format_break = CWarnings.create ~name:"notation-both-format-and-spaces" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "Discarding format implicitly indicated by multiple spaces in notation because an explicit format modifier is given.") let has_ldots l = List.exists (function (_,UnpTerminal s) -> String.equal s (Id.to_string Notation_ops.ldots_var) | _ -> false) l let rec split_format_at_ldots hd = function | (loc,UnpTerminal s) :: fmt when String.equal s (Id.to_string Notation_ops.ldots_var) -> loc, List.rev hd, fmt | u :: fmt -> check_no_ldots_in_box u; split_format_at_ldots (u::hd) fmt | [] -> raise_notrace Exit and check_no_ldots_in_box = function | (_,UnpBox (_,fmt)) -> (try let loc,_,_ = split_format_at_ldots [] fmt in user_err ?loc Pp.(str ("The special symbol \"..\" must occur at the same formatting depth than the variables of which it is the ellipse.")) with Exit -> ()) | _ -> () let error_not_same ?loc () = user_err ?loc Pp.(str "The format is not the same on the right- and left-hand sides of the special token \"..\".") let find_prod_list_loc sfmt fmt = (* [fmt] is some [UnpTerminal x :: sfmt @ UnpTerminal ".." :: sfmt @ UnpTerminal y :: rest] *) if List.is_empty sfmt then (* No separators; we highlight the sequence "x .." *) Loc.merge_opt (fst (List.hd fmt)) (fst (List.hd (List.tl fmt))) else (* A separator; we highlight the separating sequence *) Loc.merge_opt (fst (List.hd sfmt)) (fst (List.last sfmt)) let is_blank s = let n = String.length s in let rec aux i s = i >= n || s.[i] = ' ' && aux (i+1) s in aux 0 s let is_formatting = function | (_,UnpCut _) -> true | (_,UnpTerminal s) -> is_blank s | _ -> false let rec is_var_in_recursive_format = function | (_,UnpTerminal s) when not (is_blank s) -> true | (loc,UnpBox (b,l)) -> (match List.filter (fun a -> not (is_formatting a)) l with | [a] -> is_var_in_recursive_format a | _ -> error_not_same ?loc ()) | _ -> false let rec check_eq_var_upto_name = function | (_,UnpTerminal s1), (_,UnpTerminal s2) when not (is_blank s1 && is_blank s2) || s1 = s2 -> () | (_,UnpBox (b1,l1)), (_,UnpBox (b2,l2)) when b1 = b2 -> List.iter check_eq_var_upto_name (List.combine l1 l2) | (_,UnpCut b1), (_,UnpCut b2) when b1 = b2 -> () | _, (loc,_) -> error_not_same ?loc () let skip_var_in_recursive_format = function | a :: sl when is_var_in_recursive_format a -> a, sl | (loc,_) :: _ -> error_not_same ?loc () | [] -> assert false let read_recursive_format sl fmt = (* Turn [[UnpTerminal s :: some-list @ UnpTerminal ".." :: same-some-list @ UnpTerminal s' :: rest] *) (* into [(some-list,rest)] *) let get_head fmt = let var,sl = skip_var_in_recursive_format fmt in try var, split_format_at_ldots [] sl with Exit -> error_not_same ?loc:(fst (List.last (if sl = [] then fmt else sl))) () in let rec get_tail = function | (loc,a) :: sepfmt, (_,b) :: fmt when (=) a b -> get_tail (sepfmt, fmt) (* FIXME *) | [], tail -> skip_var_in_recursive_format tail | (loc,_) :: _, ([] | (_,UnpTerminal _) :: _)-> error_not_same ?loc () | _, (loc,_)::_ -> error_not_same ?loc () in let var1, (loc, slfmt, fmt) = get_head fmt in let var2, res = get_tail (slfmt, fmt) in check_eq_var_upto_name (var1,var2); (* To do, though not so important: check that the names match the names in the notation *) slfmt, res let hunks_of_format (from_level,(vars,typs)) symfmt = let rec aux = function | symbs, (_,(UnpTerminal s' as u)) :: fmt when String.equal s' (String.make (String.length s') ' ') -> let symbs, l = aux (symbs,fmt) in symbs, u :: l | Terminal s :: symbs, (_,UnpTerminal s') :: fmt when String.equal s (String.drop_simple_quotes s') -> let symbs, l = aux (symbs,fmt) in symbs, UnpTerminal s :: l | NonTerminal s :: symbs, (_,UnpTerminal s') :: fmt when Id.equal s (Id.of_string s') -> let i = index_id s vars in let symbs, l = aux (symbs,fmt) in symbs, unparsing_metavar i from_level typs :: l | symbs, (_,(UnpCut _ as u)) :: fmt -> let symbs, l = aux (symbs,fmt) in symbs, u :: l | SProdList (m,sl) :: symbs, fmt when has_ldots fmt -> let i = index_id m vars in let typ = List.nth typs (i-1) in let subentry = unparsing_precedence_of_entry_type from_level typ in let loc_slfmt,rfmt = read_recursive_format sl fmt in let sl, slfmt = aux (sl,loc_slfmt) in if not (List.is_empty sl) then error_format ?loc:(find_prod_list_loc loc_slfmt fmt) (); let symbs, l = aux (symbs,rfmt) in let hunk = match typ with | ETConstr _ -> UnpListMetaVar (subentry,slfmt) | ETBinder isopen -> check_open_binder isopen sl m; UnpBinderListMetaVar (isopen,true,slfmt) | ETName | ETIdent -> UnpBinderListMetaVar (false,true,slfmt) | ETPattern _ -> UnpBinderListMetaVar (false,false,slfmt) | _ -> assert false in symbs, hunk :: l | symbs, (_,UnpBox (a,b)) :: fmt -> let symbs', b' = aux (symbs,b) in let symbs', l = aux (symbs',fmt) in symbs', UnpBox (a,List.map (fun x -> (None,x)) b') :: l | symbs, [] -> symbs, [] | Break _ :: symbs, fmt -> warn_format_break (); aux (symbs,fmt) | _, fmt -> error_format ?loc:(fst (List.hd fmt)) () in match aux symfmt with | [], l -> l | _ -> error_format () (** **************************************************************** **) (** Build parsing rules **) let assoc_of_type from n (_,typ) = precedence_of_entry_type {notation_entry = from; notation_level = n} typ let is_not_small_constr = function ETProdConstr _ -> true | _ -> false let distribute a ll = List.map (fun l -> a @ l) ll (* Expand LIST1(t,sep);sep;t;...;t (with the trailing pattern occurring p times, possibly p=0) into the combination of t;sep;t;...;t;sep;t (p+1 times) t;sep;t;...;t;sep;t;sep;t (p+2 times) ... t;sep;t;...;t;sep;t;...;t;sep;t (p+n times) t;sep;t;...;t;sep;t;...;t;sep;t;LIST1(t,sep) *) let expand_list_rule s typ tkl x n p ll = let camlp5_message_name = Some (add_suffix x ("_"^string_of_int n)) in let main = GramConstrNonTerminal (ETProdConstr (s,typ), camlp5_message_name) in let tks = List.map (fun (kw,s) -> GramConstrTerminal (kw, s)) tkl in let rec aux i hds ll = if i < p then aux (i+1) (main :: tks @ hds) ll else if Int.equal i (p+n) then let hds = GramConstrListMark (p+n,true,p) :: hds @ [GramConstrNonTerminal (ETProdConstrList (s, typ,tkl), Some x)] in distribute hds ll else distribute (GramConstrListMark (i+1,false,p) :: hds @ [main]) ll @ aux (i+1) (main :: tks @ hds) ll in aux 0 [] ll let is_constr_typ (s,lev) x etyps = match List.assoc x etyps with (* TODO: factorize these rules with the ones computing the effective sublevel sent to camlp5, so as to include the case of DefaultLevel which are valid *) | ETConstr (s',_,(lev',InternalProd | (NumLevel _ | NextLevel as lev'), _)) -> notation_entry_eq s s' && production_level_eq lev lev' | _ -> false let include_possible_similar_trailing_pattern typ etyps sl l = let rec aux n = function | Terminal s :: sl, Terminal s'::l' when s = s' -> aux n (sl,l') | [], NonTerminal x ::l' when is_constr_typ typ x etyps -> try_aux n l' | Break _ :: sl, l -> aux n (sl,l) | sl, Break _ :: l -> aux n (sl,l) | _ -> raise_notrace Exit and try_aux n l = try aux (n+1) (sl,l) with Exit -> n,l in try_aux 0 l let prod_entry_type = function | ETIdent -> ETProdIdent | ETName -> ETProdName | ETGlobal -> ETProdGlobal | ETBigint -> ETProdBigint | ETBinder o -> ETProdOneBinder o | ETConstr (s,_,p) -> ETProdConstr (s,p) | ETPattern (_,n) -> ETProdPattern (pattern_entry_level n) let keyword_needed need s = (* Ensure that IDENT articulation terminal symbols are keywords *) match CLexer.terminal s with | Tok.PIDENT (Some k) -> if need then Flags.if_verbose Feedback.msg_info (str "Identifier '" ++ str k ++ str "' now a keyword"); need | _ -> match NumTok.Unsigned.parse_string s with | Some n -> if need then Flags.if_verbose Feedback.msg_info (str "Number '" ++ NumTok.Unsigned.print n ++ str "' now a keyword"); need | None -> match String.unquote_coq_string s with | Some _ -> if need then Flags.if_verbose Feedback.msg_info (str "String '" ++ str s ++ str "' now a keyword"); need | _ -> true let make_production ({notation_level = lev}, _) etyps symbols = let rec aux need = function | [] -> [[]] | NonTerminal m :: l -> let typ = prod_entry_type (List.assoc m etyps) in distribute [GramConstrNonTerminal (typ, Some m)] (aux (is_not_small_constr typ) l) | Terminal s :: l -> let keyword = keyword_needed need s in distribute [GramConstrTerminal (keyword,s)] (aux false l) | Break _ :: l -> aux need l | SProdList (x,sl) :: l -> let tkl = List.flatten (List.map (function Terminal s -> [s] | Break _ -> [] | _ -> anomaly (Pp.str "Found a non terminal token in recursive notation separator.")) sl) in let tkl = List.map_i (fun i x -> let need = (i=0) in (keyword_needed need x, x)) 0 tkl in match List.assoc x etyps with | ETConstr (s,_,(lev,_ as typ)) -> let p,l' = include_possible_similar_trailing_pattern (s,lev) etyps sl l in expand_list_rule s typ tkl x 1 p (aux true l') | ETBinder o -> check_open_binder o sl x; let typ = if o then (assert (tkl = []); ETBinderOpen) else ETBinderClosed (None,tkl) in distribute [GramConstrNonTerminal (ETProdBinderList typ, Some x)] (aux false l) | ETIdent -> distribute [GramConstrNonTerminal (ETProdBinderList (ETBinderClosed (Some ETProdIdent,tkl)), Some x)] (aux false l) | ETName -> distribute [GramConstrNonTerminal (ETProdBinderList (ETBinderClosed (Some ETProdName,tkl)), Some x)] (aux false l) | ETPattern (st,n) -> distribute [GramConstrNonTerminal (ETProdBinderList (ETBinderClosed (Some (ETProdPattern (pattern_entry_level n)),tkl)), Some x)] (aux false l) | _ -> user_err Pp.(str "Components of recursive patterns in notation must be terms or binders.") in let need = (* a leading ident/number factorizes iff at level 0 *) lev <> 0 in aux need symbols let rec find_symbols c_current c_next c_last = function | [] -> [] | NonTerminal id :: sl -> let prec = if not (List.is_empty sl) then c_current else c_last in (id, prec) :: (find_symbols c_next c_next c_last sl) | Terminal s :: sl -> find_symbols c_next c_next c_last sl | Break n :: sl -> find_symbols c_current c_next c_last sl | SProdList (x,_) :: sl' -> (x,c_next)::(find_symbols c_next c_next c_last sl') let border = function | (_,(ETConstr(_,_,(_,BorderProd (_,a))))) :: _ -> a | _ -> None let recompute_assoc typs = let open Gramlib.Gramext in match border typs, border (List.rev typs) with | Some LeftA, Some RightA -> assert false | Some LeftA, _ -> Some LeftA | _, Some RightA -> Some RightA | _ -> None (** ******************************************************************** **) (** Registration of syntax extensions **) (** (parsing/printing, no interpretation) **) let pr_arg_level from (lev,typ) = let pplev = function | LevelLt n when Int.equal n from -> spc () ++ str "at next level" | LevelLe n -> spc () ++ str "at level " ++ int n | LevelLt n -> spc () ++ str "at level below " ++ int n | LevelSome -> mt () in Ppvernac.pr_set_entry_type Nametab.CustomEntries.pr (fun _ -> (*TO CHECK*) mt()) typ ++ pplev lev let pr_level ({notation_entry = from; notation_level = fromlevel}, args) typs = (match from with InConstrEntry -> mt () | InCustomEntry s -> str "in " ++ Nametab.CustomEntries.pr s ++ spc()) ++ str "at level " ++ int fromlevel ++ (match args with | [] -> mt () | _ :: _ -> spc () ++ str "with arguments" ++ spc() ++ prlist_with_sep pr_comma (pr_arg_level fromlevel) (List.combine args typs)) let error_incompatible_level ntn oldprec oldtyps prec typs = user_err (str "Notation " ++ pr_notation ntn ++ str " is already defined" ++ spc() ++ pr_level oldprec oldtyps ++ spc() ++ str "while it is now required to be" ++ spc() ++ pr_level prec typs ++ str ".") let error_parsing_incompatible_level ntn ntn' oldprec oldtyps prec typs = user_err (str "Notation " ++ pr_notation ntn ++ str " relies on a parsing rule for " ++ pr_notation ntn' ++ spc() ++ str " which is already defined" ++ spc() ++ pr_level oldprec oldtyps ++ spc() ++ str "while it is now required to be" ++ spc() ++ pr_level prec typs ++ str ".") let warn_incompatible_format = CWarnings.create ~name:"notation-incompatible-format" ~category:CWarnings.CoreCategories.parsing (fun (specific,ntn) -> let head,scope = match specific with | None -> str "Notation", mt () | Some LastLonelyNotation -> str "Lonely notation", mt () | Some (NotationInScope sc) -> str "Notation", strbrk (" in scope " ^ sc) in head ++ spc () ++ pr_notation ntn ++ strbrk " was already defined with a different format" ++ scope ++ str ".") type syntax_extension = { synext_level : level; synext_nottyps : constr_entry_key list; synext_notgram : notation_grammar option; synext_notprint : generic_notation_printing_rules option; } type syntax_rules = | PrimTokenSyntax | SpecificSyntax of syntax_extension let syntax_rules_iter f = function | PrimTokenSyntax -> () | SpecificSyntax synext -> f synext let check_reserved_format ntn rules rules' = try let { notation_printing_reserved = reserved; notation_printing_rules = generic_rules } = rules in if reserved && (not (List.for_all2eq unparsing_eq rules'.notation_printing_unparsing generic_rules.notation_printing_unparsing)) then warn_incompatible_format (None,ntn) with Not_found -> () let specific_format_to_declare (specific,ntn as specific_ntn) rules = try let specific_rules = Ppextend.find_specific_notation_printing_rule specific_ntn in if not (List.for_all2eq unparsing_eq rules.notation_printing_unparsing specific_rules.notation_printing_unparsing) then (warn_incompatible_format (Some specific,ntn); true) else false with Not_found -> true type syntax_extension_obj = locality_flag * (notation * syntax_extension) let check_and_extend_constr_grammar ntn rule = try let ntn_for_grammar = rule.notgram_notation in if notation_eq ntn ntn_for_grammar then raise Not_found; let prec = rule.notgram_level in let typs = rule.notgram_typs in let oldprec = Notation.level_of_notation ntn_for_grammar in let oldparsing = try Some (Notgram_ops.grammar_of_notation ntn_for_grammar) with Not_found -> None in let oldtyps = Notgram_ops.non_terminals_of_notation ntn_for_grammar in if not (level_eq prec oldprec) && oldparsing <> None then error_parsing_incompatible_level ntn ntn_for_grammar oldprec oldtyps prec typs; if oldparsing = None then raise Not_found with Not_found -> Egramrocq.extend_constr_grammar rule let warn_prefix_incompatible_level = CWarnings.create ~name:"notation-incompatible-prefix" ~category:CWarnings.CoreCategories.parsing (fun (pref, ntn, pref_prec, pref_nottyps, prec, nottyps) -> str "Notations " ++ pr_notation pref ++ spc () ++ str "defined " ++ pr_level pref_prec pref_nottyps ++ spc () ++ str "and " ++ pr_notation ntn ++ spc () ++ str "defined " ++ pr_level prec nottyps ++ spc () ++ str "have incompatible prefixes." ++ spc () ++ str "One of them will likely not work.") let level_firstn k (lvl, lvls) = lvl, try CList.firstn k lvls with Failure _ -> [] let check_prefix_incompatible_level ntn prec nottyps = match Notgram_ops.longest_common_prefix ntn with | None -> () | Some (pref, k) -> try let pref_prec = Notation.level_of_notation pref in let pref_prec = level_firstn k pref_prec in let prec = level_firstn k prec in let pref_nottyps = Notgram_ops.non_terminals_of_notation pref in let pref_nottyps = CList.firstn k pref_nottyps in let nottyps = CList.firstn k nottyps in if not (level_eq prec pref_prec && List.for_all2 Extend.constr_entry_key_eq_ignore_binder_kind nottyps pref_nottyps) then warn_prefix_incompatible_level (pref, ntn, pref_prec, pref_nottyps, prec, nottyps); with Not_found | Failure _ -> () let cache_one_syntax_extension (ntn,synext) = let prec = synext.synext_level in (* Check and ensure that the level and the precomputed parsing rule is declared *) let oldparsing = try let oldprec = Notation.level_of_notation ntn in let oldparsing = try Some (Notgram_ops.grammar_of_notation ntn) with Not_found -> None in let oldtyps = Notgram_ops.non_terminals_of_notation ntn in if not (level_eq prec oldprec && List.for_all2 Extend.constr_entry_key_eq synext.synext_nottyps oldtyps) && (oldparsing <> None || synext.synext_notgram = None) then error_incompatible_level ntn oldprec oldtyps prec synext.synext_nottyps; oldparsing with Not_found -> check_prefix_incompatible_level ntn prec synext.synext_nottyps; (* Declare the level and the precomputed parsing rule *) let () = Notation.declare_notation_level ntn prec in let () = Notgram_ops.declare_notation_non_terminals ntn synext.synext_nottyps in let () = Option.iter (Notgram_ops.declare_notation_grammar ntn) synext.synext_notgram in None in (* Declare the parsing rule *) begin match oldparsing, synext.synext_notgram with | None, Some grams -> List.iter (check_and_extend_constr_grammar ntn) grams | _ -> (* The grammars rules are canonically derived from the string and the precedence*) () end; (* Printing *) Option.iter (declare_generic_notation_printing_rules ntn) synext.synext_notprint let cache_syntax_extension (_, sy) = cache_one_syntax_extension sy let subst_syntax_extension (subst, (local, (ntn, synext))) = (local, (ntn, synext)) let classify_syntax_definition (local, _) = if local then Dispose else Substitute let inSyntaxExtension : syntax_extension_obj -> obj = declare_object {(default_object "SYNTAX-EXTENSION") with object_stage = Summary.Stage.Synterp; open_function = simple_open ~cat:notation_cat cache_syntax_extension; cache_function = cache_syntax_extension; subst_function = subst_syntax_extension; classify_function = classify_syntax_definition} (** ******************************************************************** **) (** Precedences **) (* Interpreting user-provided modifiers *) (* XXX: We could move this to the parser itself *) module NotationMods = struct type notation_modifier = { assoc : Gramlib.Gramext.g_assoc option; level : int option; etyps : (Id.t * CustomName.t simple_constr_prod_entry_key) list; (* common to syn_data below *) format : lstring option; } let default = { assoc = None; level = None; etyps = []; format = None; } end let intern_entry_type = function | ETConstr (entry,x,y) -> let entry = intern_notation_entry entry in ETConstr (entry,x,y) | ETPattern _ | ETIdent | ETGlobal | ETBigint | ETName | ETBinder _ as v -> v let interp_modifiers entry modl = let open NotationMods in let rec interp acc = function | [] -> acc | CAst.{loc;v} :: l -> match v with | SetEntryType (s,typ) -> let id = Id.of_string s in let typ = intern_entry_type typ in if Id.List.mem_assoc id acc.etyps then user_err ?loc (str s ++ str " is already assigned to an entry or constr level."); interp { acc with etyps = (id,typ) :: acc.etyps; } l | SetItemLevel ([],bko,n) -> interp acc l | SetItemLevel (s::idl,bko,n) -> let id = Id.of_string s in if Id.List.mem_assoc id acc.etyps then user_err ?loc (str s ++ str " is already assigned to an entry or constr level."); interp { acc with etyps = (id,ETConstr (entry,bko,n)) :: acc.etyps } ((CAst.make ?loc @@ SetItemLevel (idl,bko,n))::l) | SetLevel n -> (match entry with | InCustomEntry s -> if acc.level <> None then user_err ?loc (str ("isolated \"at level " ^ string_of_int n ^ "\" unexpected.")) else (* XXX could we print the qualid used for the custom entry by the user instead of shortest_qualid? *) user_err ?loc (str "use \"in custom " ++ Nametab.CustomEntries.pr s ++ str " at level " ++ int n ++ str "\"" ++ spc () ++ str "rather than" ++ spc () ++ str ("\"at level " ^ string_of_int n ^ "\"") ++ spc () ++ str "isolated.") | InConstrEntry -> if acc.level <> None then user_err ?loc (str "A level is already assigned."); interp { acc with level = Some n; } l) | SetCustomEntry (s,Some n) -> (* Note: name of entry already registered in interp_non_syntax_modifiers *) if acc.level <> None then user_err ?loc (str ("isolated \"at level " ^ string_of_int (Option.get acc.level) ^ "\" unexpected.")); interp { acc with level = Some n } l | SetAssoc a -> if not (Option.is_empty acc.assoc) then user_err ?loc Pp.(str "An associativity is given more than once."); interp { acc with assoc = Some a; } l | SetOnlyParsing | SetOnlyPrinting | SetCustomEntry (_,None) | SetFormat _ | SetItemScope _ -> (* interpreted in interp_non_syntax_modifiers *) assert false in interp default modl let check_useless_entry_types recvars mainvars etyps = let vars = let (l1,l2) = List.split recvars in l1@l2@mainvars in match List.filter (fun (x,etyp) -> not (List.mem x vars)) etyps with | (x,_)::_ -> user_err (Id.print x ++ str " is unbound in the notation.") | _ -> () type notation_main_data = { onlyparsing : bool; onlyprinting : bool; user_warns : UserWarn.t option; entry : notation_entry; format : unparsing Loc.located list option; itemscopes : (Id.t * scope_name) list; } let warn_only_parsing_reserved_notation = CWarnings.create ~name:"irrelevant-reserved-notation-only-parsing" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "The only parsing modifier has no effect in Reserved Notation.") let warn_only_parsing_discarded_format = CWarnings.create ~name:"discarded-format-only-parsing" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "The format modifier has no effect for only-parsing notations.") let error_onlyparsing_onlyprinting ?loc = user_err ?loc (str "A notation cannot be both \"only printing\" and \"only parsing\".") let set_onlyparsing ?loc ~reserved main_data = if reserved then (warn_only_parsing_reserved_notation ?loc (); main_data) else (if main_data.onlyparsing then user_err ?loc (str "\"only parsing\" is given more than once."); if main_data.onlyprinting then error_onlyparsing_onlyprinting ?loc; { main_data with onlyparsing = true }) let set_onlyprinting ?loc main_data = if main_data.onlyprinting then user_err ?loc (str "\"only printing\" is given more than once."); if main_data.onlyparsing then error_onlyparsing_onlyprinting ?loc; { main_data with onlyprinting = true } let set_custom_entry ?loc main_data entry' = let entry' = intern_custom_name entry' in match main_data.entry with | InConstrEntry -> { main_data with entry = InCustomEntry entry' } | _ -> user_err ?loc (str "\"in custom\" is given more than once.") let warn_irrelevant_format = CWarnings.create ~name:"irrelevant-format-only-parsing" ~category:CWarnings.CoreCategories.parsing (fun () -> str "The format modifier is irrelevant for only-parsing rules.") let set_format ?loc main_data format = if not (Option.is_empty main_data.format) then user_err ?loc Pp.(str "A format is given more than once."); let format = if main_data.onlyparsing then (warn_irrelevant_format ?loc (); None) else Some (parse_format format) in { main_data with format } let set_item_scope ?loc main_data ids sc = let itemscopes = List.map (fun id -> (Id.of_string id,sc)) ids @ main_data.itemscopes in match List.duplicates (fun (id1,_) (id2,_) -> Id.equal id1 id2) itemscopes with | (id,_)::_ -> user_err ?loc (str "Notation scope for argument " ++ Id.print id ++ str " can be specified only once.") | [] -> { main_data with itemscopes } let interp_non_syntax_modifiers ~reserved ~infix ~abbrev user_warns mods = let set (main_data,rest) = CAst.with_loc_val (fun ?loc -> function | SetOnlyParsing -> if not (Option.is_empty main_data.format) then (warn_only_parsing_discarded_format ?loc (); (main_data, rest)) else (set_onlyparsing ?loc ~reserved main_data,rest) | SetOnlyPrinting when not abbrev -> (set_onlyprinting ?loc main_data,rest) | SetCustomEntry (entry,None) when not abbrev -> (set_custom_entry ?loc main_data entry,rest) | SetCustomEntry (entry,Some _) as x when not abbrev -> (set_custom_entry main_data entry,CAst.make ?loc x :: rest) | SetEntryType _ when infix -> user_err ?loc Pp.(str "Unexpected entry type in infix notation.") | SetItemLevel _ when infix -> user_err ?loc Pp.(str "Unexpected entry level in infix notation.") | SetFormat (TextFormat s) when not abbrev -> (set_format ?loc main_data s, rest) | SetItemScope (ids,sc) -> (set_item_scope ?loc main_data ids sc, rest) | modif -> (main_data,(CAst.make ?loc modif)::rest)) in let main_data = { onlyparsing = false; onlyprinting = false; user_warns; entry = InConstrEntry; format = None; itemscopes = [] } in let main_data, rest = List.fold_left set (main_data,[]) mods in main_data, List.rev rest (* Compute precedences from modifiers (or find default ones) *) let set_entry_type from n etyps (x,typ) = let make_lev n s = match typ with | BorderProd _ -> NumLevel n | InternalProd -> DefaultLevel in let typ = try match List.assoc x etyps, typ with | ETConstr (s,bko,DefaultLevel), _ -> if notation_entry_eq from s then ETConstr (s,bko,(make_lev n s,typ)) else ETConstr (s,bko,(DefaultLevel,typ)) | ETConstr (s,bko,n), BorderProd (left,_) -> ETConstr (s,bko,(n,BorderProd (left,None))) | ETConstr (s,bko,n), InternalProd -> ETConstr (s,bko,(n,InternalProd)) | ETPattern (b,n), _ -> ETPattern (b,n) | (ETIdent | ETName | ETBigint | ETGlobal | ETBinder _ as x), _ -> x with Not_found -> ETConstr (from,None,(make_lev n from,typ)) in (x,typ) let join_auxiliary_recursive_types recvars etyps = List.fold_right (fun (x,y) typs -> let xtyp = try Some (List.assoc x etyps) with Not_found -> None in let ytyp = try Some (List.assoc y etyps) with Not_found -> None in match xtyp,ytyp with | None, None -> typs | Some _, None -> typs | None, Some ytyp -> (x,ytyp)::typs | Some xtyp, Some ytyp when (=) xtyp ytyp -> typs (* FIXME *) | Some xtyp, Some ytyp -> user_err (strbrk "In " ++ Id.print x ++ str " .. " ++ Id.print y ++ strbrk ", both ends have incompatible types.")) recvars etyps let internalization_type_of_entry_type = function | ETBinder _ | ETConstr (_,Some _,_) -> NtnInternTypeOnlyBinder | ETConstr (_,None,_) | ETBigint | ETGlobal | ETIdent | ETName | ETPattern _ -> NtnInternTypeAny None let make_internalization_vars recvars maintyps = let maintyps = List.map (on_snd internalization_type_of_entry_type) maintyps in let extratyps = List.map (fun (x,y) -> (y,List.assoc x maintyps)) recvars in maintyps @ extratyps let make_interpretation_type isrec isbinding default_if_binding typ = match typ, isrec with (* Parsed as constr, but interpreted as a specific kind of binder *) | ETConstr (_,Some bk,_), true -> NtnTypeBinderList (NtnBinderParsedAsConstr bk) | ETConstr (_,Some bk,_), false -> NtnTypeBinder (NtnBinderParsedAsConstr bk) (* Parsed as constr list but interpreted as the default kind of binder *) | ETConstr (_,None,_), true when isbinding -> NtnTypeBinderList (NtnBinderParsedAsConstr default_if_binding) | ETConstr (_,None,_), false when isbinding -> NtnTypeBinder (NtnBinderParsedAsConstr default_if_binding) (* Parsed as constr, interpreted as constr *) | ETConstr (_,None,_), true -> NtnTypeConstrList | ETConstr (_,None,_), false -> NtnTypeConstr (* Different way of parsing binders, maybe interpreted also as constr, but conventionally internally binders *) | ETIdent, true -> NtnTypeBinderList (NtnBinderParsedAsSomeBinderKind AsIdent) | ETIdent, false -> NtnTypeBinder (NtnBinderParsedAsSomeBinderKind AsIdent) | ETName, true -> NtnTypeBinderList (NtnBinderParsedAsSomeBinderKind AsName) | ETName, false -> NtnTypeBinder (NtnBinderParsedAsSomeBinderKind AsName) (* Parsed as ident/pattern, primarily interpreted as binder; maybe strict at printing *) | ETPattern (ppstrict,_), true -> NtnTypeBinderList (NtnBinderParsedAsSomeBinderKind (if ppstrict then AsStrictPattern else AsAnyPattern)) | ETPattern (ppstrict,_), false -> NtnTypeBinder (NtnBinderParsedAsSomeBinderKind (if ppstrict then AsStrictPattern else AsAnyPattern)) | ETBinder _, true -> NtnTypeBinderList NtnBinderParsedAsBinder | ETBinder _, false -> NtnTypeBinder NtnBinderParsedAsBinder (* Others *) | ETBigint, true | ETGlobal, true -> NtnTypeConstrList | ETBigint, false | ETGlobal, false -> NtnTypeConstr let entry_relative_level_of_constr_prod_entry from_level = function | ETConstr (entry,_,(_,y)) as x -> let side = match y with BorderProd (side,_) -> Some side | _ -> None in { notation_subentry = entry; notation_relative_level = precedence_of_entry_type from_level x; notation_position = side } | _ -> constr_some_level let make_interpretation_vars (* For binders, default is to parse only as an ident *) ?(default_if_binding=AsName) recvars allvars (entry,_) typs = let eq_subscope (sc1, l1) (sc2, l2) = List.equal String.equal sc1 sc2 && List.equal String.equal l1 l2 in let check (x, y) = let (_,scope1,_ntn_binding_ids1) = Id.Map.find x allvars in let (_,scope2,_ntn_binding_ids2) = Id.Map.find y allvars in if not (eq_subscope scope1 scope2) then error_not_same_scope x y (* Note: binding_ids should currently be the same, and even with eventually more complex notations, such as e.g. Notation "!! x .. y , P .. Q" := (fun x => (P, .. (fun y => (Q, True)) ..)). each occurrence of the recursive notation variables may have its own binders *) in let () = List.iter check recvars in let useless_recvars = List.map snd recvars in let mainvars = Id.Map.filter (fun x _ -> not (Id.List.mem x useless_recvars)) allvars in Id.Map.mapi (fun x (isonlybinding, sc, ntn_binding_ids) -> let typ = Id.List.assoc x typs in ((entry_relative_level_of_constr_prod_entry entry typ, sc), ntn_binding_ids, make_interpretation_type (Id.List.mem_assoc x recvars) isonlybinding default_if_binding typ)) mainvars let check_rule_productivity l = if List.for_all (function NonTerminal _ | Break _ -> true | _ -> false) l then user_err Pp.(str "A notation must include at least one symbol."); if (match l with SProdList _ :: _ -> true | _ -> false) then user_err Pp.(str "A recursive notation must start with at least one symbol.") let warn_notation_bound_to_variable = CWarnings.create ~name:"notation-bound-to-variable" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "This notation will not be used for printing as it is bound to a single variable.") let warn_non_reversible_notation = CWarnings.create ~name:"non-reversible-notation" ~category:CWarnings.CoreCategories.parsing (function[@warning "+9"] | APrioriReversible -> assert false | Forgetful { forget_ltac=ltac; forget_volatile_cast=cast; } -> let what = (if ltac then ["Ltac expressions"] else []) @ (if cast then ["volatile casts"] else []) in strbrk "This notation contains " ++ prlist_with_sep (fun () -> strbrk " and ") str what ++ str ":" ++ spc() ++ str "it will not be used for printing." | NonInjective ids -> let n = List.length ids in strbrk (String.plural n "Variable") ++ spc () ++ pr_enum Id.print ids ++ spc () ++ strbrk (if n > 1 then "do" else "does") ++ str " not occur in the right-hand side." ++ spc() ++ strbrk "The notation will not be used for printing as it is not reversible.") let is_coercion level typs = match level, typs with | Some ({notation_entry = custom; notation_level = n} as entry,_), [_,e] -> (match e, custom with | ETConstr _, _ -> let entry_relative = entry_relative_level_of_constr_prod_entry entry e in if is_coercion entry entry_relative then Some (IsEntryCoercion (entry,entry_relative)) else None | ETGlobal, InCustomEntry s -> Some (IsEntryGlobal (s,n)) | ETIdent, InCustomEntry s -> Some (IsEntryIdent (s,n)) | _ -> None) | Some _, _ -> assert false | None, _ -> None let printability level typs vars onlyparsing reversibility = function | NVar id when reversibility = APrioriReversible && List.mem_assoc_f Id.equal id vars -> let coe = is_coercion level typs in let onlyparsing = if not onlyparsing && Option.is_empty coe then (warn_notation_bound_to_variable (); true) else onlyparsing in onlyparsing, coe | _ -> (if not onlyparsing && reversibility <> APrioriReversible then (warn_non_reversible_notation reversibility; true) else onlyparsing),None let warn_closed_notation_not_level_0 = CWarnings.create ~name:"closed-notation-not-level-0" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "Closed notations (i.e. starting and ending with a \ terminal symbol) should usually be at level 0 \ (default).") let warn_level_0_notation_not_closed = CWarnings.create ~name:"level-0-notation-not-closed" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "Notations at level 0 should be closed (first and last \ symbols should be terminal symbols).") let warn_postfix_notation_not_level_1 = CWarnings.create ~name:"postfix-notation-not-level-1" ~category:CWarnings.CoreCategories.parsing (fun () -> strbrk "Postfix notations (i.e. starting with a \ nonterminal symbol and ending with a terminal \ symbol) should usually be at level 1 (default).") let find_precedence custom lev etyps symbols onlyprint = let first_symbol = let rec aux = function | Break _ :: t -> aux t | h :: t -> Some h | [] -> None in aux symbols in let last_is_terminal () = let rec aux b = function | Break _ :: t -> aux b t | Terminal _ :: t -> aux true t | _ :: t -> aux false t | [] -> b in aux false symbols in let msgs, lev = match first_symbol with | None -> [],0 | Some (NonTerminal x) -> let msgs, lev = match last_is_terminal (), lev with | false, _ -> [], lev | true, None -> [fun () -> Flags.if_verbose (Feedback.msg_info ?loc:None) (strbrk "Setting postfix notation at level 1.")], Some 1 | true, Some 1 -> [], Some 1 | true, Some n -> [warn_postfix_notation_not_level_1], Some n in let test () = if onlyprint then if Option.is_empty lev then user_err Pp.(str "Explicit level needed in only-printing mode when the level of the leftmost non-terminal is given.") else msgs,Option.get lev else user_err Pp.(str "The level of the leftmost non-terminal cannot be changed.") in (try match List.assoc x etyps, custom with | ETConstr (s,_,(NumLevel _ | NextLevel)), s' when s = s' -> test () | (ETIdent | ETName | ETBigint | ETGlobal), _ -> begin match lev with | None -> ([fun () -> Flags.if_verbose (Feedback.msg_info ?loc:None) (strbrk "Setting notation at level 0.")],0) | Some 0 -> (msgs,0) | _ -> user_err Pp.(str "A notation starting with an atomic expression must be at level 0.") end | (ETPattern _ | ETBinder _), InConstrEntry when not onlyprint -> (* Don't know exactly if we can make sense of this case *) user_err Pp.(str "Binders or patterns not supported in leftmost position.") | (ETPattern _ | ETBinder _ | ETConstr _), _ -> (* Give a default ? *) if Option.is_empty lev then user_err Pp.(str "Need an explicit level.") else msgs,Option.get lev with Not_found -> if Option.is_empty lev then user_err Pp.(str "A left-recursive notation must have an explicit level.") else msgs,Option.get lev) | Some (Terminal _) when last_is_terminal () -> begin match lev with | None -> [fun () -> Flags.if_verbose (Feedback.msg_info ?loc:None) (strbrk "Setting notation at level 0.")], 0 | Some 0 -> [], 0 | Some n -> [warn_closed_notation_not_level_0], n end | Some _ -> if Option.is_empty lev then user_err Pp.(str "Cannot determine the level."); [],Option.get lev in if lev <> 0 then msgs, lev else match first_symbol, last_is_terminal (), symbols with (* no warning for closed notations *) | Some (Terminal _), true, _ (* nor for particular cases "" and "x" *) | _, _, ([] | [_]) -> msgs, lev | _ -> msgs @ [warn_level_0_notation_not_closed], lev let check_curly_brackets_notation_exists () = try let _ = Notation.level_of_notation (InConstrEntry,"{ _ }") in () with Not_found -> user_err Pp.(str "Notations involving patterns of the form \"{ _ }\" are treated \n\ specially and require that the notation \"{ _ }\" is already reserved.") (* Remove patterns of the form "{ _ }", unless it is the "{ _ }" notation *) let remove_curly_brackets l = let rec skip_break acc = function | Break _ as br :: l -> skip_break (br::acc) l | l -> List.rev acc, l in let rec aux deb = function | [] -> [] | Terminal "{" as t1 :: l -> let br,next = skip_break [] l in (match next with | NonTerminal _ as x :: l' -> let br',next' = skip_break [] l' in (match next' with | Terminal "}" as t2 :: l'' -> if deb && List.is_empty l'' then [t1;x;t2] else begin check_curly_brackets_notation_exists (); x :: aux false l'' end | l1 -> t1 :: br @ x :: br' @ aux false l1) | l0 -> t1 :: aux false l0) | x :: l -> x :: aux false l in aux true l let has_implicit_format symbols = List.exists (function Break _ -> true | _ -> false) symbols (* Because of the special treatment for { }, the grammar rule sent to the parser may be different than what the user sees; e.g. for "{ A } + { B }", it is "A + B" which is sent to the parser *) type syn_pa_data = { ntn_for_grammar : notation; prec_for_grammar : level; typs_for_grammar : constr_entry_key list; need_squash : bool; } module SynData = struct type subentry_types = (Id.t * constr_entry_key) list (* XXX: Document *) type syn_data = { (* XXX: Callback to printing, must remove *) msgs : (unit -> unit) list; (* Notation data for parsing *) level : level; subentries : subentry_types; pa_syntax_data : subentry_types * symbol list; pp_syntax_data : subentry_types * symbol list; not_data : syn_pa_data; } end let find_subentry_types from n assoc etyps symbols = let typs = find_symbols (BorderProd(Left,assoc)) (InternalProd) (BorderProd(Right,assoc)) symbols in let sy_typs = List.map (set_entry_type from n etyps) typs in let prec = List.map (assoc_of_type from n) sy_typs in sy_typs, prec let custom_entry_locality = Summary.ref ~name:"LOCAL-CUSTOM-ENTRY" CustomName.Set.empty (** If the entry is present then local *) let locality_of_custom_entry s = CustomName.Set.mem s !custom_entry_locality let check_locality_compatibility local custom i_typs = if not local then let subcustom = List.map_filter (function _,ETConstr (InCustomEntry s,_,_) -> Some s | _ -> None) i_typs in let allcustoms = match custom with InCustomEntry s -> s::subcustom | _ -> subcustom in List.iter (fun s -> if locality_of_custom_entry s then user_err (strbrk "Notation has to be declared local as it depends on custom entry " ++ Nametab.CustomEntries.pr s ++ strbrk " which is local.")) (List.uniquize allcustoms) let longest_common_prefix_level ntn = Notgram_ops.longest_common_prefix ntn |> Option.map (fun (ntn, sz) -> let level, levels = level_firstn sz (Notation.level_of_notation ntn) in ntn, level.notation_level, levels) let default_prefix_level ntn_prefix = let with_prefix prefix level = Flags.if_verbose Feedback.msg_info (strbrk "Setting notation at level " ++ int level ++ spc () ++ str "to match previous notation with longest common prefix:" ++ spc () ++ str "\"" ++ str (snd prefix) ++ str "\"."); level in function Some n -> Some n | None -> Option.map (fun (prefix, level, _) -> with_prefix prefix level) ntn_prefix let default_prefix_level_subentries ntn ntn_prefix symbols etyps = let with_prefix prefix from_level levels = let default_entry etyps (x, l) = let l' = match l with | LevelLt n when Int.equal n from_level -> NextLevel | LevelLe n | LevelLt n -> NumLevel n | LevelSome -> DefaultLevel in let e = List.assoc_opt x etyps |> Option.default (ETConstr (fst ntn, None, DefaultLevel)) in match l', e with | (NumLevel _ | NextLevel), ETConstr (n, b, DefaultLevel) -> Flags.if_verbose Feedback.msg_info (strbrk "Setting " ++ Id.print x ++ str " " ++ pr_arg_level from_level (l, e) ++ spc () ++ str "to match previous notation with longest common prefix:" ++ spc () ++ str "\"" ++ str (snd prefix) ++ str "\"."); (x, ETConstr (n, b, l')) :: List.remove_assoc x etyps | _ -> etyps in let levels = let rec aux levs symbs = match levs, symbs with | [], _ | _, [] | _, SProdList _ :: _ -> [] (* not handling recursive notations *) | _, (Terminal _ | Break _) :: symbs -> aux levs symbs | l :: levs, NonTerminal x :: symbs -> (x, l) :: aux levs symbs in match levels, symbols with (* don't mess up with level of left border terminal *) | _ :: levs, NonTerminal _ :: symbs | levs, symbs -> aux levs symbs in List.fold_left default_entry etyps levels in match ntn_prefix with | None -> etyps | Some (prefix, from_level, levels) -> with_prefix prefix from_level levels let compute_syntax_data ~local main_data notation_symbols ntn mods = let open SynData in let open NotationMods in if main_data.itemscopes <> [] then user_err (str "General notations don't support 'in scope'."); let {recvars;mainvars;symbols} = notation_symbols in let assoc = Option.append mods.assoc (Some Gramlib.Gramext.NonA) in let _ = check_useless_entry_types recvars mainvars mods.etyps in (* Notations for interp and grammar *) let ntn_prefix = longest_common_prefix_level ntn in let level = default_prefix_level ntn_prefix mods.level in let msgs,n = find_precedence main_data.entry level mods.etyps symbols main_data.onlyprinting in let symbols_for_grammar = if main_data.entry = InConstrEntry then remove_curly_brackets symbols else symbols in let need_squash = not (List.equal Notation.symbol_eq symbols symbols_for_grammar) in let ntn_for_grammar = if need_squash then make_notation_key main_data.entry symbols_for_grammar else ntn in if main_data.entry = InConstrEntry && not main_data.onlyprinting then check_rule_productivity symbols_for_grammar; (* To globalize... *) let etyps = default_prefix_level_subentries ntn ntn_prefix symbols mods.etyps in let etyps = join_auxiliary_recursive_types recvars etyps in let sy_typs, prec = find_subentry_types main_data.entry n assoc etyps symbols in let sy_typs_for_grammar, prec_for_grammar = if need_squash then find_subentry_types main_data.entry n assoc etyps symbols_for_grammar else sy_typs, prec in check_locality_compatibility local main_data.entry sy_typs; let pa_sy_data = (sy_typs_for_grammar,symbols_for_grammar) in let pp_sy_data = (sy_typs,symbols) in let sy_fulldata = { ntn_for_grammar; prec_for_grammar = ({notation_entry = main_data.entry; notation_level = n}, prec_for_grammar); typs_for_grammar = List.map snd sy_typs_for_grammar; need_squash } in (* Return relevant data for interpretation and for parsing/printing *) { msgs; level = ({notation_entry = main_data.entry; notation_level = n}, prec); subentries = sy_typs; pa_syntax_data = pa_sy_data; pp_syntax_data = pp_sy_data; not_data = sy_fulldata; } (** **************************************************************** **) (** Registration of notation interpretation **) type notation_obj = { notobj_local : bool; notobj_scope : scope_name option; notobj_interp : interpretation; notobj_coercion : entry_coercion_kind option; notobj_use : notation_use option; notobj_user_warns : UserWarn.t option; notobj_notation : notation * notation_location; notobj_specific_pp_rules : notation_printing_rules option; } let load_notation_common silently_define_scope_if_undefined _ nobj = (* When the default shall be to require that a scope already exists *) (* the call to ensure_scope will have to be removed *) if silently_define_scope_if_undefined then (* Don't warn if the scope is not defined: *) (* there was already a warning at "cache" time *) Option.iter Notation.declare_scope nobj.notobj_scope else Option.iter Notation.ensure_scope nobj.notobj_scope let load_notation = load_notation_common true let open_notation nobj = let scope = nobj.notobj_scope in let (ntn, df) = nobj.notobj_notation in let pat = nobj.notobj_interp in let user_warns = nobj.notobj_user_warns in let scope = match scope with None -> LastLonelyNotation | Some sc -> NotationInScope sc in (* Declare the notation *) (match nobj.notobj_use with | Some use -> Notation.declare_notation (scope,ntn) pat df ~use nobj.notobj_coercion user_warns | None -> ()); (* Declare specific format if any *) (match nobj.notobj_specific_pp_rules with | Some pp_sy -> if specific_format_to_declare (scope,ntn) pp_sy then Ppextend.declare_specific_notation_printing_rules (scope,ntn) pp_sy | None -> ()) let cache_notation o = load_notation_common false 1 o; open_notation o let subst_notation (subst, nobj) = { nobj with notobj_interp = subst_interpretation subst nobj.notobj_interp; } let classify_notation nobj = if nobj.notobj_local then Dispose else Substitute let inNotation : notation_obj -> obj = declare_object {(default_object "NOTATION") with open_function = simple_open ~cat:notation_cat open_notation; cache_function = cache_notation; subst_function = subst_notation; load_function = load_notation; classify_function = classify_notation} (**********************************************************************) (* Registration of interpretation scopes opening/closing *) let cache_scope (local,op,sc) = if op then Notation.open_scope sc else Notation.close_scope sc let subst_scope (subst,sc) = sc let discharge_scope (local,_,_ as o) = if local then None else Some o let classify_scope (local,_,_) = if local then Dispose else Substitute let inScope : bool * bool * scope_name -> obj = declare_object {(default_object "SCOPE") with cache_function = cache_scope; open_function = simple_open ~cat:notation_cat cache_scope; subst_function = subst_scope; discharge_function = discharge_scope; classify_function = classify_scope } let open_close_scope local ~to_open sc = Lib.add_leaf (inScope (local,to_open,normalize_scope sc)) (**********************************************************************) let with_lib_stk_protection f x = let open Memprof_coq.Resource_bind in let freeze, unfreeze = Lib.Interp.(freeze, unfreeze) in let& () = Util.protect_state ~freeze ~unfreeze in f x let with_syntax_protection f x = with_lib_stk_protection (Procq.with_grammar_rule_protection (with_notation_protection f)) x (** **************************************************************** **) (** Recovering existing syntax **) exception NoSyntaxRule let recover_notation_syntax ntn = try let prec = Notation.level_of_notation ntn in let pa_typs = Notgram_ops.non_terminals_of_notation ntn in let pa_rule = try Some (Notgram_ops.grammar_of_notation ntn) with Not_found -> None in let pp_rule = try Some (find_generic_notation_printing_rule ntn) with Not_found -> None in { synext_level = prec; synext_nottyps = pa_typs; synext_notgram = pa_rule; synext_notprint = pp_rule; } with Not_found -> raise NoSyntaxRule let recover_squash_syntax sy = let sq = recover_notation_syntax (InConstrEntry,"{ _ }") in match sq.synext_notgram with | Some gram -> sy :: gram | None -> raise NoSyntaxRule (** **************************************************************** **) (** Main entry point for building parsing and printing rules **) let make_pa_rule (typs,symbols) parsing_data = let { ntn_for_grammar; prec_for_grammar; typs_for_grammar; need_squash } = parsing_data in let assoc = recompute_assoc typs in let prod = make_production prec_for_grammar typs symbols in let sy = { notgram_level = prec_for_grammar; notgram_assoc = assoc; notgram_notation = ntn_for_grammar; notgram_prods = prod; notgram_typs = typs_for_grammar; } in (* By construction, the rule for "{ _ }" is declared, but we need to redeclare it because the file where it is declared needs not be open when the current file opens (especially in presence of -nois) *) if need_squash then recover_squash_syntax sy else [sy] let make_pp_rule level (typs,symbols) fmt = match fmt with | None -> let hunks = make_hunks typs symbols level in if List.exists (function _,(UnpCut (PpBrk _) | UnpListMetaVar _) -> true | _ -> false) hunks then [UnpBox (PpHOVB 0,hunks)] else (* Optimization to work around what seems an ocaml Format bug (see Mantis #7804/#7807) *) List.map snd hunks (* drop locations which are dummy *) | Some fmt -> hunks_of_format (level, List.split typs) (symbols, fmt) let make_parsing_rules main_data (sd : SynData.syn_data) = let open SynData in if main_data.onlyprinting then None else Some (make_pa_rule sd.pa_syntax_data sd.not_data) (** **************************************************************** **) (** Main functions about notations **) let make_generic_printing_rules reserved main_data ntn sd = let open SynData in let {notation_entry = custom; notation_level = level},_ = sd.level in let make_rule rule = { notation_printing_reserved = reserved; notation_printing_rules = { notation_printing_unparsing = rule; notation_printing_level = level; } } in try let rules = (Ppextend.find_generic_notation_printing_rule ntn) in match main_data.format with | None when not (has_implicit_format (snd sd.pp_syntax_data)) -> (* No intent to define a format, we reuse the existing generic rules *) Some rules | _ -> if not reserved && main_data.onlyprinting then (* No intent to define a generic format *) Some rules else let rules' = make_rule (make_pp_rule level sd.pp_syntax_data main_data.format) in let () = check_reserved_format ntn rules rules'.notation_printing_rules in Some rules' with Not_found -> Some (make_rule (make_pp_rule level sd.pp_syntax_data main_data.format)) let make_syntax_rules reserved main_data ntn sd = let open SynData in List.iter (fun f -> f ()) sd.msgs; (* Prepare the parsing and printing rules *) let pa_rules = make_parsing_rules main_data sd in let pp_rules = make_generic_printing_rules reserved main_data ntn sd in { synext_level = sd.level; synext_nottyps = List.map snd sd.subentries; synext_notgram = pa_rules; synext_notprint = pp_rules; } (**********************************************************************) (* Main entry point for building specific printing rules *) let make_specific_printing_rules etyps symbols level pp_rule format = match level with | None -> None | Some ({ notation_level = level},_) -> match format, pp_rule with | None, Some _ when not (has_implicit_format symbols) -> None | _ -> Some { notation_printing_unparsing = make_pp_rule level (etyps,symbols) format; notation_printing_level = level; } (**********************************************************************) (* Miscellaneous *) let warn_unused_interpretation = CWarnings.create ~name:"unused-notation" ~category:CWarnings.CoreCategories.parsing (fun b -> strbrk "interpretation is used neither for printing nor for parsing, " ++ (if b then strbrk "the declaration could be replaced by \"Reserved Notation\"." else strbrk "the declaration could be removed.")) let make_use reserved onlyparse onlyprint = match onlyparse, onlyprint with | false, false -> Some ParsingAndPrinting | true, false -> Some OnlyParsing | false, true -> Some OnlyPrinting | true, true -> warn_unused_interpretation reserved; None (**********************************************************************) (* Main functions about notations *) let make_notation_interpretation ~local main_data notation_symbols ntn syntax_rules df env ?(impls=empty_internalization_env) c scope = let {recvars;mainvars;symbols} = notation_symbols in (* Recover types of variables and pa/pp rules; redeclare them if needed *) let level, i_typs, main_data, sy_pp_rules = match syntax_rules with | PrimTokenSyntax -> None, [], main_data, None | SpecificSyntax sy -> (* If the only printing flag has been explicitly requested, put it back *) let main_data = { main_data with onlyprinting = main_data.onlyprinting || (sy.synext_notgram = None && not main_data.onlyparsing) } in Some sy.synext_level, List.combine mainvars sy.synext_nottyps, main_data, sy.synext_notprint in (* Declare interpretation *) let sy_pp_rules = make_specific_printing_rules i_typs symbols level sy_pp_rules main_data.format in let path = (Lib.library_dp(), Lib.current_dirpath true) in let df' = ntn, (path,df) in let i_vars = make_internalization_vars recvars i_typs in let nenv = { ninterp_var_type = Id.Map.of_list i_vars; ninterp_rec_vars = Id.Map.of_list recvars; } in let (acvars, ac, reversibility) = interp_notation_constr env ~impls nenv c in let plevel = match level with Some (entry,l) -> (entry,l) | None (* numeral: irrelevant )*) -> (constr_lowest_level,[]) in let interp = make_interpretation_vars recvars acvars plevel i_typs in let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in let vars = List.map_filter map i_vars in (* Order of elements is important here! *) let onlyparsing,coe = printability level i_typs vars main_data.onlyparsing reversibility ac in let main_data = { main_data with onlyparsing } in let use = make_use false onlyparsing main_data.onlyprinting in { notobj_local = local; notobj_scope = scope; notobj_use = use; notobj_interp = (vars, ac); notobj_coercion = coe; notobj_user_warns = main_data.user_warns; notobj_notation = df'; notobj_specific_pp_rules = sy_pp_rules; } (* Notations without interpretation (Reserved Notation) *) let add_reserved_notation ~local ~infix ({CAst.loc;v=df},mods) = let (main_data,mods) = interp_non_syntax_modifiers ~reserved:true ~infix ~abbrev:false None mods in let mods = interp_modifiers main_data.entry mods in let notation_symbols, is_prim_token = analyze_notation_tokens ~onlyprinting:main_data.onlyprinting ~infix main_data.entry df in let notation_symbols = if infix then adjust_reserved_infix_notation notation_symbols else notation_symbols in let ntn = make_notation_key main_data.entry notation_symbols.symbols in if is_prim_token then user_err ?loc (str "Notations for numbers or strings are primitive and need not be reserved."); let sd = compute_syntax_data ~local main_data notation_symbols ntn mods in let synext = make_syntax_rules true main_data ntn sd in Lib.add_leaf (inSyntaxExtension(local,(ntn,synext))) type notation_interpretation_decl = notation_declaration * notation_main_data * notation_symbols * notation * syntax_rules (* Notations associated to a where clause *) let prepare_where_notation ntn_decl = let { ntn_decl_string = { CAst.loc ; v = df }; ntn_decl_interp = c; ntn_decl_modifiers = modifiers; ntn_decl_scope = sc; } = ntn_decl in let (main_data,mods) = interp_non_syntax_modifiers ~reserved:false ~infix:false ~abbrev:false None modifiers in match mods with | _::_ -> CErrors.user_err (str"Only modifiers not affecting parsing are supported here.") | [] -> let notation_symbols, is_prim_token = analyze_notation_tokens ~onlyprinting:main_data.onlyprinting ~infix:false main_data.entry df in let ntn = make_notation_key main_data.entry notation_symbols.symbols in let syntax_rules = if is_prim_token then PrimTokenSyntax else try SpecificSyntax (recover_notation_syntax ntn) with NoSyntaxRule -> user_err Pp.(str "Parsing rule for this notation has to be previously declared.") in (ntn_decl, main_data, notation_symbols, ntn, syntax_rules) let add_notation_interpretation ~local env (ntn_decl, main_data, notation_symbols, ntn, syntax_rules) = let { ntn_decl_string = { CAst.loc ; v = df }; ntn_decl_interp = c; ntn_decl_scope = sc } = ntn_decl in let notation = make_notation_interpretation ~local main_data notation_symbols ntn syntax_rules df env c sc in Lib.add_leaf (inNotation notation); Dumpglob.dump_notation (CAst.make ?loc ntn) sc true (* interpreting a where clause *) let set_notation_for_interpretation env impls (ntn_decl, main_data, notation_symbols, ntn, syntax_rules) = let { ntn_decl_string = { CAst.loc ; v = df }; ntn_decl_interp = c; ntn_decl_scope = sc } = ntn_decl in let notation = make_notation_interpretation ~local:true main_data notation_symbols ntn syntax_rules df env ~impls c sc in Lib.add_leaf (inNotation notation); Option.iter (fun sc -> Lib.add_leaf (inScope (false,true,sc))) sc let build_notation_syntax ~local ~infix user_warns ntn_decl = let { ntn_decl_string = {CAst.loc;v=df}; ntn_decl_modifiers = modifiers; ntn_decl_interp = c } = ntn_decl in (* Extract the modifiers not affecting the parsing rule *) let (main_data,syntax_modifiers) = interp_non_syntax_modifiers ~reserved:false ~infix ~abbrev:false user_warns modifiers in (* Extract the modifiers not affecting the parsing rule *) let notation_symbols, is_prim_token = analyze_notation_tokens ~onlyprinting:main_data.onlyprinting ~infix main_data.entry df in (* Add variables on both sides if an infix notation *) let df, notation_symbols, c = if infix then adjust_infix_notation df notation_symbols c else df, notation_symbols, c in (* Build the canonical identifier of the syntactic part of the notation *) let ntn = make_notation_key main_data.entry notation_symbols.symbols in let syntax_rules = if is_prim_token then (check_no_syntax_modifiers_for_numeral syntax_modifiers; PrimTokenSyntax) else match syntax_modifiers with | [] -> (* No syntax data: try to rely on a previously declared rule *) (try SpecificSyntax (recover_notation_syntax ntn) with NoSyntaxRule -> (* Try to determine a default syntax rule *) let sd = compute_syntax_data ~local main_data notation_symbols ntn NotationMods.default in SpecificSyntax (make_syntax_rules false main_data ntn sd)) | _ -> let mods = interp_modifiers main_data.entry syntax_modifiers in let sd = compute_syntax_data ~local main_data notation_symbols ntn mods in SpecificSyntax (make_syntax_rules false main_data ntn sd) in main_data, notation_symbols, ntn, syntax_rules, c, df let add_notation_syntax ~local ~infix user_warns ntn_decl = (* Build or rebuild the syntax rules *) let main_data, notation_symbols, ntn, syntax_rules, c, df = build_notation_syntax ~local ~infix user_warns ntn_decl in (* Declare syntax *) syntax_rules_iter (fun sy -> Lib.add_leaf (inSyntaxExtension (local,(ntn,sy)))) syntax_rules; let ntn_decl_string = CAst.make ?loc:ntn_decl.ntn_decl_string.CAst.loc df in let ntn_decl = { ntn_decl with ntn_decl_interp = c; ntn_decl_string } in ntn_decl, main_data, notation_symbols, ntn, syntax_rules (** **************************************************************** **) (** Scopes, delimiters and classes bound to scopes **) type scope_command = | ScopeDeclare | ScopeDelimAdd of string | ScopeDelimRemove | ScopeClasses of add_scope_where option * scope_class list let load_scope_command_common silently_define_scope_if_undefined _ (local,scope,o) = let declare_scope_if_needed = if silently_define_scope_if_undefined then Notation.declare_scope else Notation.ensure_scope in match o with | ScopeDeclare -> Notation.declare_scope scope (* When the default shall be to require that a scope already exists *) (* the call to declare_scope_if_needed will have to be removed below *) | ScopeDelimAdd dlm -> declare_scope_if_needed scope | ScopeDelimRemove -> declare_scope_if_needed scope | ScopeClasses _ -> declare_scope_if_needed scope let load_scope_command = load_scope_command_common true let open_scope_command (noexport,scope,o) = match o with | ScopeDeclare -> () | ScopeDelimAdd dlm -> Notation.declare_delimiters scope dlm | ScopeDelimRemove -> Notation.remove_delimiters scope | ScopeClasses (where, cl) -> let local = Lib.sections_are_opened () in List.iter (Notation.declare_scope_class local scope ?where) cl let cache_scope_command o = load_scope_command_common false 1 o; open_scope_command o let subst_scope_command (subst,(noexport,scope,o as x)) = match o with | ScopeClasses (where, cl) -> let env = Global.env () in let cl' = List.map_filter (subst_scope_class env subst) cl in let cl' = if List.for_all2eq (==) cl cl' then cl else cl' in noexport, scope, ScopeClasses (where, cl') | _ -> x let classify_scope_command (noexport, _, _) = if noexport then Dispose else Substitute let inScopeCommand : locality_flag * scope_name * scope_command -> obj = declare_object {(default_object "DELIMITERS") with cache_function = cache_scope_command; open_function = simple_open ~cat:notation_cat open_scope_command; load_function = load_scope_command; subst_function = subst_scope_command; classify_function = classify_scope_command} let declare_scope local scope = Lib.add_leaf (inScopeCommand(local,scope,ScopeDeclare)) let add_delimiters local scope key = Lib.add_leaf (inScopeCommand(local,scope,ScopeDelimAdd key)) let remove_delimiters local scope = Lib.add_leaf (inScopeCommand(local,scope,ScopeDelimRemove)) let add_class_scope local scope where cl = Lib.add_leaf (inScopeCommand(local,scope,ScopeClasses (where, cl))) let interp_abbreviation_modifiers modl = let mods, skipped = interp_non_syntax_modifiers ~reserved:false ~infix:false ~abbrev:true None modl in if skipped <> [] then (let modifier = List.hd skipped in user_err ?loc:modifier.CAst.loc (str "Abbreviations don't support " ++ Ppvernac.pr_syntax_modifier modifier)); (mods.onlyparsing, mods.itemscopes) let add_abbreviation ~local user_warns env ident (vars,c) modl = let (only_parsing, scopes) = interp_abbreviation_modifiers modl in let vars = List.map (fun v -> v, List.assoc_opt v scopes) vars in let acvars,pat,reversibility = match vars, intern_name_alias c with | [], Some(r,u) -> (* Check if abbreviation to a name and avoid early insertion of maximal implicit arguments *) Id.Map.empty, NRef(r, u), APrioriReversible | _ -> let fold accu (id,scope) = Id.Map.add id (NtnInternTypeAny scope) accu in let i_vars = List.fold_left fold Id.Map.empty vars in let nenv = { ninterp_var_type = i_vars; ninterp_rec_vars = Id.Map.empty; } in interp_notation_constr env nenv c in let level_arg = NumLevel 9 (* level of arguments of an application *) in let in_pat (id,_) = (id,ETConstr (Constrexpr.InConstrEntry,None,(level_arg,InternalProd))) in let level = (* not relevant *) (constr_lowest_level,[]) in let interp = make_interpretation_vars ~default_if_binding:AsAnyPattern [] acvars level (List.map in_pat vars) in let vars = List.map (fun (x,_) -> (x, Id.Map.find x interp)) vars in let onlyparsing = only_parsing || fst (printability None [] vars false reversibility pat) in Abbreviation.declare ~local user_warns ident ~onlyparsing (vars,pat) (**********************************************************************) (* Activating/deactivating notations *) let cache_notation_toggle (local,(on,all,pat)) = let env = Global.env () in let sigma = Evd.from_env env in let flags = PrintingFlags.Extern.current() in let flags = { flags with notations = false } in let prglob c = Printer.pr_glob_constr_env ~flags env sigma c in toggle_notations ~on ~all ~verbose:(not !Flags.quiet) prglob pat let subst_notation_toggle (subst,(local,(on,all,pat))) = let {notation_entry_pattern; interp_rule_key_pattern; use_pattern; scope_pattern; interpretation_pattern} = pat in let interpretation_pattern = Option.map (subst_interpretation subst) interpretation_pattern in let interp_rule_key_pattern = interp_rule_key_pattern in (local,(on,all,{notation_entry_pattern; interp_rule_key_pattern; use_pattern; scope_pattern; interpretation_pattern})) let classify_notation_toggle (local,_) = if local then Dispose else Substitute let inNotationActivation : locality_flag * (bool * bool * notation_query_pattern) -> obj = declare_object {(default_object "NOTATION-TOGGLE") with cache_function = cache_notation_toggle; open_function = simple_open cache_notation_toggle; subst_function = subst_notation_toggle; classify_function = classify_notation_toggle} let declare_notation_toggle local ~on ~all s = Lib.add_leaf (inNotationActivation (local,(on,all,s))) (** **************************************************************** **) (** Declaration of custom entries **) let load_custom_entry i ((sp,kn),local) = Nametab.CustomEntries.push (Until i) sp kn; add_custom_compat kn; Egramrocq.create_custom_entry kn; let () = if local then custom_entry_locality := CustomName.Set.add kn !custom_entry_locality in () let import_custom_entry i ((sp,kn),_) = Nametab.CustomEntries.push (Exactly i) sp kn let cache_custom_entry o = load_custom_entry 1 o let subst_custom_entry (subst,x) = x let classify_custom_entry local = if local then Dispose else Substitute let inCustomEntry : Id.t -> locality_flag -> obj = declare_named_object {(default_object "CUSTOM-ENTRIES") with object_stage = Summary.Stage.Synterp; cache_function = cache_custom_entry; load_function = load_custom_entry; open_function = filtered_open import_custom_entry; subst_function = subst_custom_entry; classify_function = classify_custom_entry} let declare_custom_entry local s = let () = if List.mem (Id.to_string s) ["constr";"pattern";"ident";"global";"binder";"bigint"] then user_err Pp.(quote (Id.print s) ++ str " is a reserved entry name.") in let () = if Nametab.CustomEntries.exists (Lib.make_path s) then user_err Pp.(Id.print s ++ str " already exists.") in Lib.add_leaf (inCustomEntry s local) rocq-9.2.0/vernac/metasyntax.mli000066400000000000000000000074241516144147600166640ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* infix:bool -> UserWarn.t option -> notation_declaration -> notation_interpretation_decl (** Add syntax rules for a (constr) notation in the environment *) val add_notation_interpretation : local:bool -> env -> notation_interpretation_decl -> unit (** Declare the interpretation of a notation *) (** Declaring scopes, delimiter keys and default scopes *) val declare_scope : locality_flag -> scope_name -> unit val add_delimiters : locality_flag -> scope_name -> string -> unit val remove_delimiters : locality_flag -> scope_name -> unit val add_class_scope : locality_flag -> scope_name -> add_scope_where option -> scope_class list -> unit (** Scope opening *) val open_close_scope : locality_flag -> to_open:bool -> scope_name -> unit (** Add a notation interpretation associated to a "where" clause (already has pa/pp rules) *) val prepare_where_notation : notation_declaration -> notation_interpretation_decl (** Interpret the modifiers of a where-notation *) val set_notation_for_interpretation : env -> Constrintern.internalization_env -> notation_interpretation_decl -> unit (** Set the interpretation of the where-notation for interpreting a mutual block *) (** Add only the parsing/printing rule of a notation *) val add_reserved_notation : local:bool -> infix:bool -> (lstring * syntax_modifier CAst.t list) -> unit (** Add a syntactic definition (as in "Notation f := ...") *) val add_abbreviation : local:Libobject.locality -> Globnames.extended_global_reference UserWarn.with_qf option -> env -> Id.t -> Id.t list * constr_expr -> syntax_modifier CAst.t list -> unit (** Print the Camlp5 state of a grammar *) val pr_grammar : string list -> Pp.t val pr_custom_grammar : Libnames.qualid -> Pp.t val pr_keywords : unit -> Pp.t (** Register a handler for Print Custom Grammar. The handler should return [None] for unknown entries and [Some] of the associated entries for known entries. *) val register_custom_grammar_for_print : (Libnames.qualid -> Procq.Entry.any_t list option) -> unit val with_syntax_protection : ('a -> 'b) -> 'a -> 'b val declare_notation_toggle : locality_flag -> on:bool -> all:bool -> Notation.notation_query_pattern -> unit val declare_custom_entry : locality_flag -> Id.t -> unit (** Declare given string as a custom grammar entry *) val intern_custom_name : Libnames.qualid -> Globnames.CustomName.t (** Intern custom entry name using compat layer if needed. *) val intern_notation_entry : Libnames.qualid notation_entry_gen -> notation_entry (** Intern notation entry name using compat layer for custom entries if needed. *) val pr_level : notation_entry_level * entry_relative_level list -> Extend.constr_entry_key list -> Pp.t (** Pretty print level information of a notation and all of its arguments *) rocq-9.2.0/vernac/mltop.ml000066400000000000000000000416541516144147600154540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* if i split i (j+1) else if i try fst (Findlib.package_property_2 ("plugin"::preds) lib "archive") with Not_found -> "" in fl_split_in_words archive |> List.map (Findlib.resolve_path ~base) (* We register errors at for Dynlink and Findlib, it is possible to do so Symtable too, as we used to do in the bytecode init code. *) let () = CErrors.register_handler (function | Dynlink.Error msg -> Some (hov 0 (str "Dynlink error: " ++ str (Dynlink.error_message msg))) | Fl_package_base.No_such_package(p,msg) -> let paths = Findlib.search_path () in Some (hov 0 (str "Findlib error: " ++ str p ++ str " not found in:" ++ cut () ++ v 0 (prlist_with_sep cut str paths) ++ fnl() ++ str msg)) | _ -> None ) end let dbg_dynlink = CDebug.create ~name:"dynlink" () module PluginSpec : sig type t (* Main constructor, takes the format used in Declare ML Module. With [usercode:true], warn instead of error on legacy syntax. *) val of_package : ?usercode:bool -> string -> t val to_package : t -> string val is_loaded : t -> bool (* Load a plugin, low-level, that is to say, will directly call the loading mechanism in OCaml/findlib *) val load : t -> unit (* Compute a digest, a findlib library name have more than one plugin .cmxs, however this is not the case in Rocq. Maybe we should strengthen this invariant. *) val digest : t -> Digest.t list (** bool = true for implicit dependencies *) val add_deps : t list -> (bool * t) list val pp : t -> string module Set : CSet.ExtS with type elt = t module Map : CMap.ExtS with type key = t and module Set := Set end = struct type t = { lib : string } let compare { lib = l1 } { lib = l2 } = String.compare l1 l2 module Self = struct type nonrec t = t let compare = compare end module Set = CSet.Make(Self) module Map = CMap.Make(Self) module Errors = struct let warn_legacy_loading = CWarnings.create ~name:"legacy-loading-removed" ~category:Deprecation.Version.v9_0 Pp.(fun name -> str "Legacy loading plugin method has been removed from Rocq, \ and the `:` syntax is deprecated, and its first \ argument ignored; please remove \"" ++ str name ++ str ":\" from your Declare ML") let plugin_name_invalid_format m = CErrors.user_err Pp.(str Format.(asprintf "%s is not a valid plugin name." m) ++ spc () ++ str "It should be a public findlib name, e.g. package-name.foo." ++ spc () ++ str "Legacy names followed by a findlib public name, e.g. "++ spc () ++ str "legacy_plugin:package-name.plugin," ++ spc() ++ str "are not supported anymore.") let warn_coq_core = CWarnings.create ~name:"coq-core-plugin" ~category:Deprecation.Version.v9_0 Pp.(fun () -> str "\"coq-core\" has been renamed to \"rocq-runtime\".") end (* We would properly load the rocq-runtime cmxs because of the virtual coq-core findlib package, but we would not initialize the plugin. eg [Declare ML Module "coq-core.plugins.ltac". Ltac foo := idtac.] would fail as the grammar for Ltac is not activated. *) let compat_coq_core lib = let old_prefix = "coq-core.plugins." in if CString.is_prefix old_prefix lib then begin Errors.warn_coq_core (); let old_len = String.length old_prefix in "rocq-runtime.plugins." ^ (CString.sub lib old_len (String.length lib - old_len)) end else lib let of_package ?(usercode=false) m = let lib = match String.split_on_char ':' m with | [ lib ] -> lib | [cmxs; lib] when usercode -> Errors.warn_legacy_loading cmxs; lib | _ -> Errors.plugin_name_invalid_format m in let lib = if usercode then compat_coq_core lib else lib in { lib } let to_package { lib } = lib let is_loaded { lib } = Findlib.is_recorded_package lib let load = function | { lib } -> if Findlib.is_recorded_package lib then dbg_dynlink Pp.(fun () -> str lib ++ str " already loaded") else begin (* no point in using Fl_dynload since we [add_deps] to get digests *) let plugins = Fl_internals.fl_find_plugins lib in dbg_dynlink Pp.(fun () -> str lib ++ str ": linking" ++ spc() ++ prlist_with_sep spc str plugins); List.iter Dynlink.loadfile plugins; Findlib.record_package Record_load lib end let add_deps plugins = let explicit = Set.of_list plugins in let preds = Findlib.recorded_predicates() in let allplugins = Findlib.package_deep_ancestors preds (List.map to_package plugins) in let deps = List.filter_map (fun lib -> (* comes from findlib so guaranteed valid *) let plugin = { lib } in let explicit = Set.mem plugin explicit in (* only add not-yet-loaded implicit deps *) if not explicit && Findlib.is_recorded_package lib then None else Some (not explicit, plugin)) allplugins in dbg_dynlink Pp.(fun () -> str "for " ++ prlist_with_sep spc (fun {lib} -> str lib) plugins ++ str ":" ++ fnl() ++ v 2 (str "all deps:" ++ spc() ++ prlist_with_sep spc str allplugins) ++ fnl() ++ v 2 (str "filtered deps:" ++ spc() ++ prlist_with_sep spc (fun (_,{lib}) -> str lib) deps)); deps let digest s = match s with | { lib } -> let plugins = Fl_internals.fl_find_plugins lib in List.map Digest.file plugins let pp = function | { lib } -> lib end (* If there is a toplevel under Rocq *) type toplevel = { load_plugin : PluginSpec.t -> unit (** Load a findlib library, given by public name *) ; load_module : string -> unit (** Load a cmxs / cmo module, used by the native compiler to load objects *) ; add_dir : string -> unit (** Adds a dir to the module search path *) ; ml_loop : ?init_file:string -> unit -> unit (** Run the OCaml toplevel with given initialisation file *) } (* Determines the behaviour of Rocq with respect to ML files (compiled or not) *) type kind_load = | WithTop of toplevel | WithoutTop (* Must be always initialized *) let load = ref WithoutTop (* Sets and initializes a toplevel (if any) *) let set_top toplevel = load := WithTop toplevel; Nativelib.load_obj := toplevel.load_module (* Removes the toplevel (if any) *) let remove () = load := WithoutTop; Nativelib.load_obj := (fun x -> () : string -> unit) (* Tests if an Ocaml toplevel runs under Rocq *) let is_ocaml_top () = match !load with | WithTop _ -> true |_ -> false (* Tests if we can load ML files *) let has_dynlink = Coq_config.has_natdynlink || not Sys.(backend_type = Native) (* Runs the toplevel loop of Ocaml *) let ocaml_toploop ?init_file () = match !load with | WithTop t -> t.ml_loop ?init_file () | _ -> () let ml_load p = match !load with | WithTop t -> t.load_plugin p | WithoutTop -> PluginSpec.load p let load_module x = match !load with | WithTop t -> t.load_module x | WithoutTop -> () (* Adds a path to the ML paths *) let add_ml_dir s = match !load with | WithTop t -> t.add_dir s | WithoutTop when has_dynlink -> () | _ -> () (** Init time functions *) let initialized_plugins = Summary.ref ~stage:Synterp ~name:"inited-plugins" PluginSpec.Set.empty let plugin_init_functions : (unit -> unit) list PluginSpec.Map.t ref = ref PluginSpec.Map.empty let add_init_function name f = let name = PluginSpec.of_package name in if PluginSpec.Set.mem name !initialized_plugins then CErrors.anomaly Pp.(str "Not allowed to add init function for already initialized plugin " ++ str (PluginSpec.pp name)); plugin_init_functions := PluginSpec.Map.update name (function | None -> Some [f] | Some g -> Some (f::g)) !plugin_init_functions (** Registering functions to be used at caching time, that is when the Declare ML module command is issued. *) type cache_obj = CacheObj : { synterp : unit -> 'a; interp : 'a -> unit } -> cache_obj let interp_only_obj interp = CacheObj { synterp = (fun () -> ()); interp } let cache_objs = ref PluginSpec.Map.empty let declare_cache_obj_full obj name = let name = PluginSpec.of_package name in let objs = try PluginSpec.Map.find name !cache_objs with Not_found -> [] in let objs = obj :: objs in cache_objs := PluginSpec.Map.add name objs !cache_objs let declare_cache_obj f name = declare_cache_obj_full (CacheObj {synterp = f; interp = (fun () -> ()) }) name (* A little box to avoid getting confused with partially applied functions *) type interp_fun = InterpFun of (unit -> unit) let iter_interp_funs l = InterpFun (fun () -> List.iter (fun (InterpFun f) -> f ()) l) let perform_cache_obj name = let objs = try PluginSpec.Map.find name !cache_objs with Not_found -> [] in let objs = List.rev objs in let v = List.map (fun (CacheObj {synterp; interp}) -> let v = synterp () in InterpFun (fun () -> interp v)) objs in iter_interp_funs v (** ml object = ml module or plugin *) let dinit = CDebug.create ~name:"mltop-init" () let init_ml_object mname = if PluginSpec.Set.mem mname !initialized_plugins then dinit Pp.(fun () -> str "already initialized " ++ str (PluginSpec.pp mname)) else begin dinit Pp.(fun () -> str "initing " ++ str (PluginSpec.pp mname)); let n = match PluginSpec.Map.find mname !plugin_init_functions with | l -> List.iter (fun f -> f()) (List.rev l); List.length l | exception Not_found -> 0 in initialized_plugins := PluginSpec.Set.add mname !initialized_plugins; dinit Pp.(fun () -> str "finished initing " ++ str (PluginSpec.pp mname) ++ str " (" ++ int n ++ str " init functions)") end let load_ml_object mname = ml_load mname (* Summary of declared ML Modules *) (* List and not String.Set because order is important: most recent first. *) let loaded_modules = ref [] let get_loaded_modules () = List.rev !loaded_modules (* XXX: It seems this should be part of trigger_ml_object, and moreover we should check the guard there *) let add_loaded_module md = if not (List.mem md !loaded_modules) then loaded_modules := md :: !loaded_modules let reset_loaded_modules () = loaded_modules := [] type load_request = | Summary | Regular of { implicit : bool } let if_verbose_load req f name = match req with | Regular {implicit} when not !Flags.quiet -> begin let info = str "[Loading ML file " ++ str (PluginSpec.pp name) ++ (if implicit then str " (implicit dependency)" else mt()) ++ str " ..." in try let path = f name in Feedback.msg_info (info ++ str " done]"); path with reraise -> Feedback.msg_info (info ++ str " failed]"); raise reraise end | Summary | Regular _ -> f name (** Load a module for the first time (i.e. dynlink it) *) let trigger_ml_object (req, plugin) = let () = if not @@ PluginSpec.is_loaded plugin then begin if not has_dynlink then CErrors.user_err (str "Dynamic link not supported (module " ++ str (PluginSpec.pp plugin) ++ str ").") else if_verbose_load req load_ml_object plugin end in add_loaded_module plugin let unfreeze_ml_modules x = reset_loaded_modules (); List.iter (fun name -> let name = PluginSpec.of_package name in trigger_ml_object (Summary, name)) x (* Beware of the order to avoid double-locking *) let unfreeze_ml_modules = Util.atomify unfreeze_ml_modules let trigger_ml_object req plugin = Util.atomify trigger_ml_object (req, plugin) let () = Summary.declare_ml_modules_summary { stage = Summary.Stage.Synterp ; Summary.freeze_function = (fun () -> get_loaded_modules () |> List.map PluginSpec.to_package) ; Summary.unfreeze_function = unfreeze_ml_modules ; Summary.init_function = reset_loaded_modules } (* Liboject entries of declared ML Modules *) type ml_module_object = { mlocal : Vernacexpr.locality_flag ; mnames : (bool * PluginSpec.t) list (* bool: if true then implicit dep XXX should we init_ml_object even for implicit deps? *) ; mdigests : Digest.t list } let cache_ml_objects mnames = let map (implicit,obj) = trigger_ml_object (Regular {implicit}) obj; if implicit then None else begin init_ml_object obj; Some (perform_cache_obj obj) end in let v = List.filter_map map mnames in iter_interp_funs v let run_interp_fun (InterpFun f) = f () let load_ml_objects _ {mnames; _} = let iter (implicit,obj) = trigger_ml_object (Regular {implicit}) obj; if not implicit then init_ml_object obj in List.iter iter mnames let classify_ml_objects {mlocal=mlocal} = if mlocal then Libobject.Dispose else Libobject.Substitute let inMLModule : ml_module_object -> Libobject.obj = let open Libobject in declare_object {(default_object "ML-MODULE") with object_stage = Summary.Stage.Synterp; cache_function = (fun _ -> ()); load_function = load_ml_objects; subst_function = (fun (_,o) -> o); classify_function = classify_ml_objects } let declare_ml_modules local mnames = let mnames = List.map (PluginSpec.of_package ~usercode:true) mnames in if Lib.sections_are_opened() then CErrors.user_err Pp.(str "Cannot Declare ML Module while sections are opened."); let mnames = PluginSpec.add_deps mnames in let mdigests = CList.concat_map (fun (_,plugin) -> PluginSpec.digest plugin) mnames in Lib.add_leaf (inMLModule {mlocal=local; mnames; mdigests}); (* We can't put this in cache_function: it may declare other objects, and when the current module is required we want to run the ML-MODULE object before them. *) cache_ml_objects mnames (* Printing of loaded ML modules *) let print_ml_modules () = let l = get_loaded_modules () in str"Loaded ML Modules: " ++ pr_vertical_list str (List.map PluginSpec.pp l) let print_gc () = let stat = Gc.stat () in let msg = str "minor words: " ++ real stat.Gc.minor_words ++ fnl () ++ str "promoted words: " ++ real stat.Gc.promoted_words ++ fnl () ++ str "major words: " ++ real stat.Gc.major_words ++ fnl () ++ str "minor_collections: " ++ int stat.Gc.minor_collections ++ fnl () ++ str "major_collections: " ++ int stat.Gc.major_collections ++ fnl () ++ str "heap_words: " ++ int stat.Gc.heap_words ++ fnl () ++ str "heap_chunks: " ++ int stat.Gc.heap_chunks ++ fnl () ++ str "live_words: " ++ int stat.Gc.live_words ++ fnl () ++ str "live_blocks: " ++ int stat.Gc.live_blocks ++ fnl () ++ str "free_words: " ++ int stat.Gc.free_words ++ fnl () ++ str "free_blocks: " ++ int stat.Gc.free_blocks ++ fnl () ++ str "largest_free: " ++ int stat.Gc.largest_free ++ fnl () ++ str "fragments: " ++ int stat.Gc.fragments ++ fnl () ++ str "compactions: " ++ int stat.Gc.compactions ++ fnl () ++ str "top_heap_words: " ++ int stat.Gc.top_heap_words ++ fnl () ++ str "stack_size: " ++ int stat.Gc.stack_size in hv 0 msg rocq-9.2.0/vernac/mltop.mli000066400000000000000000000074071516144147600156230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string val pp : t -> string end type toplevel = { load_plugin : PluginSpec.t -> unit (** Load a findlib library, given by public name *) ; load_module : string -> unit (** Load a cmxs / cmo module, used by the native compiler to load objects *) ; add_dir : string -> unit (** Adds a dir to the module search path *) ; ml_loop : ?init_file:string -> unit -> unit (** Run the OCaml toplevel with given addtitional initialisation file *) } (** Sets and initializes a toplevel (if any) *) val set_top : toplevel -> unit (** Low level module loading, for the native compiler and similar users. *) val load_module : string -> unit (** Removes the toplevel (if any) *) val remove : unit -> unit (** Tests if an Ocaml toplevel runs under Coq *) val is_ocaml_top : unit -> bool (** Starts the Ocaml toplevel loop *) val ocaml_toploop : ?init_file:string -> unit -> unit (** {5 ML Dynlink} *) (** Adds a dir to the plugin search path, this also extends OCamlfind's search path *) val add_ml_dir : string -> unit (** Tests if we can load ML files *) val has_dynlink : bool (** {5 Initialization functions} *) (** Declare a initialization function. The initialization function is called in Declare ML Module, including reruns after backtracking over it (either interactive backtrack, module closing backtrack, Require of a file with Declare ML Module). *) val add_init_function : string -> (unit -> unit) -> unit (** Register a callback that will be called when the module is declared with the Declare ML Module command. This is useful to define Coq objects at that time only. Several functions can be defined for one module; they will be called in the order of declaration, and after the ML module has been properly initialized. Unlike the init functions it does not run after closing a module or Requiring a file which contains the Declare ML Module. This allows to have effects which depend on the module when command was run in, eg add a named libobject which will use it for the prefix. The callback runs in the synterp phase, use [declare_cache_obj_full] if you also need to interact with Interp state. *) val declare_cache_obj : (unit -> unit) -> string -> unit type cache_obj = CacheObj : { synterp : unit -> 'a; interp : 'a -> unit } -> cache_obj val interp_only_obj : (unit -> unit) -> cache_obj (** Register a callback with an interp phase. *) val declare_cache_obj_full : cache_obj -> string -> unit (** {5 Declaring modules} *) type interp_fun val run_interp_fun : interp_fun -> unit (** Implementation of the [Declare ML Module] vernacular command. *) val declare_ml_modules : Vernacexpr.locality_flag -> string list -> interp_fun (** {5 Utilities} *) val print_ml_modules : unit -> Pp.t val print_gc : unit -> Pp.t rocq-9.2.0/vernac/opaques.ml000066400000000000000000000137611516144147600157740ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* anomaly (Pp.str "Context is used only internally.") let pr_params pr_c (xl,(c,t)) = hov 2 (prlist_with_sep sep pr_lident xl ++ spc() ++ (if c then str":>" else str":" ++ spc() ++ pr_c t)) let rec factorize = function | [] -> [] | (c,(idl,t))::l -> match factorize l with | (xl,((c', t') as r))::l' when (c : bool) == c' && (=) t t' -> (* FIXME: we need equality on constr_expr *) (idl@xl,r)::l' | l' -> (idl,(c,t))::l' let pr_ne_params_list pr_c l = match factorize l with | [p] -> pr_params pr_c p | l -> prlist_with_sep spc (fun p -> hov 1 (str "(" ++ pr_params pr_c p ++ str ")")) l (* prlist_with_sep pr_semicolon (pr_params pr_c) *) let pr_thm_token k = keyword (string_of_theorem_kind k) let pr_syntax_modifier = let open Gramlib.Gramext in CAst.with_val (function | SetItemLevel (l,bko,n) -> prlist_with_sep sep_v2 str l ++ spc () ++ pr_at_level n ++ pr_opt pr_constr_as_binder_kind bko | SetItemScope (l,s) -> prlist_with_sep sep_v2 str l ++ spc () ++ str"in scope" ++ str s | SetLevel n -> pr_at_level (NumLevel n) | SetCustomEntry (s,n) -> keyword "in" ++ spc() ++ keyword "custom" ++ spc() ++ pr_qualid s ++ (match n with None -> mt () | Some n -> pr_at_level (NumLevel n)) | SetAssoc BothA -> assert false | SetAssoc LeftA -> keyword "left associativity" | SetAssoc RightA -> keyword "right associativity" | SetAssoc NonA -> keyword "no associativity" | SetEntryType (x,typ) -> str x ++ spc() ++ pr_set_simple_entry_type typ | SetOnlyPrinting -> keyword "only printing" | SetOnlyParsing -> keyword "only parsing" | SetFormat (TextFormat s) -> keyword "format " ++ pr_ast qs s) let pr_syntax_modifiers = function | [] -> mt() | l -> spc() ++ hov 1 (str"(" ++ prlist_with_sep sep_v2 pr_syntax_modifier l ++ str")") let pr_notation_declaration ntn_decl = let open Vernacexpr in let { ntn_decl_string = {CAst.loc;v=ntn}; ntn_decl_interp = c; ntn_decl_modifiers = modifiers; ntn_decl_scope = scopt } = ntn_decl in qs ntn ++ spc () ++ str ":=" ++ spc () ++ Flags.without_option Flags.beautify pr_constr c ++ pr_syntax_modifiers modifiers ++ pr_opt (fun sc -> spc () ++ str ":" ++ spc () ++ str sc) scopt let pr_where_notation decl_ntn = fnl () ++ keyword "where " ++ pr_notation_declaration decl_ntn let pr_rec_definition (rec_order, { fname; univs; binders; rtype; body_def; notations }) = let pr_pure_lconstr c = Flags.without_option Flags.beautify pr_lconstr c in let annot = pr_guard_annot pr_lconstr_expr binders rec_order in pr_ident_decl (fname,univs) ++ pr_binders_arg binders ++ annot ++ pr_type_option (fun c -> spc() ++ pr_lconstr_expr c) rtype ++ pr_opt (fun def -> str":=" ++ brk(1,2) ++ pr_pure_lconstr def) body_def ++ prlist pr_where_notation notations let pr_statement head (idpl,(bl,c)) = hov 2 (head ++ spc() ++ pr_ident_decl idpl ++ spc() ++ (match bl with [] -> mt() | _ -> pr_binders bl ++ spc()) ++ str":" ++ pr_spc_lconstr c) let pr_rew_rule (ubinders, lhs, rhs) = let binders = match ubinders with None -> mt() | _ -> pr_universe_decl ubinders ++ spc() ++ str"|-" in let pr_pure_lconstr c = Flags.without_option Flags.beautify pr_lconstr c in binders ++ pr_pure_lconstr lhs ++ str"==>" ++ pr_pure_lconstr rhs (**************************************) (* Pretty printer for vernac commands *) (**************************************) let pr_constrarg c = spc () ++ pr_constr c let pr_lconstrarg c = spc () ++ pr_lconstr c let pr_intarg n = spc () ++ int n let pr_vernac_attributes = function | [] -> mt () | flags -> str "#[" ++ prlist_with_sep pr_comma Attributes.pr_vernac_flag flags ++ str "]" ++ spc () let pr_oc coe ins = match coe, ins with | NoCoercion, NoInstance -> str" :" | AddCoercion, NoInstance -> str" :>" | NoCoercion, BackInstance -> str" ::" | AddCoercion, BackInstance -> str" ::>" let pr_record_field (x, { rfu_attrs = attr ; rfu_coercion = coe ; rfu_instance = ins ; rfu_priority = pri ; rfu_notation = ntn }) = let prx = match x with | AssumExpr (id,binders,t) -> hov 1 (pr_vernac_attributes attr ++ pr_lname id ++ pr_binders_arg binders ++ spc() ++ pr_oc coe ins ++ spc() ++ pr_lconstr_expr t) | DefExpr(id,binders,b,opt) -> (match opt with | Some t -> hov 1 (pr_vernac_attributes attr ++ pr_lname id ++ pr_binders_arg binders ++ spc() ++ pr_oc coe ins ++ spc() ++ pr_lconstr_expr t ++ str" :=" ++ pr_lconstr b) | None -> hov 1 (pr_vernac_attributes attr ++ pr_lname id ++ str" :=" ++ spc() ++ pr_lconstr b)) in let prpri = match pri with None -> mt() | Some i -> str "| " ++ int i in prx ++ prpri ++ prlist pr_where_notation ntn let pr_record_decl c fs obinder = pr_opt pr_lident c ++ pr_record "{" "}" pr_record_field fs ++ pr_opt (fun id -> str "as " ++ pr_lident id) obinder let pr_printable = function | PrintFullContext -> keyword "Print All" | PrintSectionContext s -> keyword "Print Section" ++ spc() ++ Libnames.pr_qualid s | PrintGrammar ent -> keyword "Print Grammar" ++ spc() ++ prlist_with_sep spc str ent | PrintCustomGrammar ent -> keyword "Print Custom Grammar" ++ spc() ++ pr_qualid ent | PrintKeywords -> keyword "Print Keywords" | PrintLoadPath dir -> keyword "Print LoadPath" ++ pr_opt DirPath.print dir | PrintLibraries -> keyword "Print Libraries" | PrintMLLoadPath -> keyword "Print ML Path" | PrintMLModules -> keyword "Print ML Modules" | PrintDebugGC -> keyword "Print ML GC" | PrintGraph -> keyword "Print Graph" | PrintClasses -> keyword "Print Classes" | PrintTypeclasses -> keyword "Print Typeclasses" | PrintInstances qid -> keyword "Print Instances" ++ spc () ++ pr_smart_global qid | PrintCoercions -> keyword "Print Coercions" | PrintCoercionPaths (s,t) -> keyword "Print Coercion Paths" ++ spc() ++ pr_class_rawexpr s ++ spc() ++ pr_class_rawexpr t | PrintCanonicalConversions qids -> keyword "Print Canonical Structures" ++ prlist pr_smart_global qids | PrintTypingFlags -> keyword "Print Typing Flags" | PrintTables -> keyword "Print Tables" | PrintHintGoal -> keyword "Print Hint" | PrintHint qid -> keyword "Print Hint" ++ spc () ++ pr_smart_global qid | PrintHintDb -> keyword "Print Hint *" | PrintHintDbName s -> keyword "Print HintDb" ++ spc () ++ str s | PrintUniverses {sort=b; subgraph=g; with_sources; file=fopt;} -> let cmd = if b then "Print Sorted Universes" else "Print Universes" in let pr_debug_univ_name = function | NamedUniv x -> pr_qualid x | RawUniv { CAst.v = x } -> qstring x in let pr_subgraph = prlist_with_sep spc pr_debug_univ_name in let pr_with_src b = if b then str "With Constraint Sources" else str "Without Constraint Sources" in keyword cmd ++ pr_opt pr_subgraph g ++ pr_opt pr_with_src with_sources ++ pr_opt str fopt | PrintSorts -> keyword "Print Sorts" | PrintName (qid,udecl) -> keyword "Print" ++ spc() ++ pr_smart_global qid ++ pr_full_univ_name_list udecl | PrintModuleType qid -> keyword "Print Module Type" ++ spc() ++ pr_qualid qid | PrintModule qid -> keyword "Print Module" ++ spc() ++ pr_qualid qid | PrintInspect n -> keyword "Inspect" ++ spc() ++ int n | PrintScopes -> keyword "Print Scopes" | PrintScope s -> keyword "Print Scope" ++ spc() ++ str s | PrintVisibility s -> keyword "Print Visibility" ++ pr_opt str s | PrintAbout (qid,l,gopt) -> pr_opt (fun g -> Goal_select.pr_goal_selector g ++ str ":"++ spc()) gopt ++ keyword "About" ++ spc() ++ pr_smart_global qid ++ pr_full_univ_name_list l | PrintImplicit qid -> keyword "Print Implicit" ++ spc() ++ pr_smart_global qid (* spiwack: command printing all the axioms and section variables used in a term *) | PrintAssumptions (b, t, qids) -> let cmd = match b, t with | true, true -> "Print All Dependencies" | true, false -> "Print Opaque Dependencies" | false, true -> "Print Transparent Dependencies" | false, false -> "Print Assumptions" in keyword cmd ++ spc() ++ prlist_with_sep spc pr_smart_global qids | PrintNamespace dp -> keyword "Print Namespace" ++ DirPath.print dp | PrintStrategy None -> keyword "Print Strategies" | PrintStrategy (Some qid) -> keyword "Print Strategy" ++ pr_smart_global qid | PrintRegistered -> keyword "Print Registered" | PrintRegisteredSchemes -> keyword "Print Registered Schemes" | PrintNotation (Constrexpr.InConstrEntry, ntn_key) -> keyword "Print Notation" ++ spc() ++ str ntn_key | PrintNotation (Constrexpr.InCustomEntry ent, ntn_key) -> keyword "Print Notation" ++ spc() ++ pr_qualid ent ++ str ntn_key let pr_using e = let rec aux = function | SsEmpty -> "()" | SsType -> "(Type)" | SsSingl { v=id } -> "("^Id.to_string id^")" | SsCompl e -> "-" ^ aux e^"" | SsUnion(e1,e2) -> "("^aux e1 ^" + "^ aux e2^")" | SsSubstr(e1,e2) -> "("^aux e1 ^" - "^ aux e2^")" | SsFwdClose e -> "("^aux e^")*" in Pp.str (aux e) let pr_extend s cl = let pr_arg a = try pr_gen a with Failure _ -> str "" in try let rl = Egramml.get_extend_vernac_rule s in let rec aux rl cl = match rl, cl with | Egramml.GramNonTerminal _ :: rl, arg :: cl -> pr_arg arg :: aux rl cl | Egramml.GramTerminal s :: rl, cl -> str s :: aux rl cl | [], [] -> [] | _ -> assert false in hov 1 (pr_sequence identity (aux rl cl)) with Not_found -> hov 1 (str "TODO(" ++ str s.ext_entry ++ spc () ++ prlist_with_sep sep pr_arg cl ++ str ")") let pr_synpure_vernac_expr v = let return = tag_vernac v in match v with (* Proof management *) | VernacAbortAll -> return (keyword "Abort All") | VernacRestart -> return (keyword "Restart") | VernacUnfocus -> return (keyword "Unfocus") | VernacUnfocused -> return (keyword "Unfocused") | VernacAbort -> return (keyword "Abort") | VernacUndo i -> return ( if Int.equal i 1 then keyword "Undo" else keyword "Undo" ++ pr_intarg i ) | VernacUndoTo i -> return (keyword "Undo" ++ spc() ++ keyword "To" ++ pr_intarg i) | VernacFocus i -> return (keyword "Focus" ++ pr_opt int i) | VernacShow s -> let pr_goal_reference = function | OpenSubgoals -> mt () | NthGoal n -> spc () ++ int n | GoalId id -> spc () ++ pr_qualid id in let pr_showable = function | ShowGoal n -> keyword "Show" ++ pr_goal_reference n | ShowProof -> keyword "Show Proof" | ShowExistentials -> keyword "Show Existentials" | ShowUniverses -> keyword "Show Universes" | ShowProofNames -> keyword "Show Conjectures" | ShowIntros b -> keyword "Show " ++ (if b then keyword "Intros" else keyword "Intro") | ShowMatch id -> keyword "Show Match " ++ pr_qualid id in return (pr_showable s) | VernacCheckGuard -> return (keyword "Guarded") | VernacValidateProof -> return (keyword "Validate Proof") (* Resetting *) | VernacResetName id -> return (keyword "Reset" ++ spc() ++ pr_lident id) | VernacResetInitial -> return (keyword "Reset Initial") | VernacBack i -> return ( if Int.equal i 1 then keyword "Back" else keyword "Back" ++ pr_intarg i ) (* Syntax *) | VernacOpenCloseScope (opening,sc) -> return ( keyword (if opening then "Open " else "Close ") ++ keyword "Scope" ++ spc() ++ str sc ) | VernacDeclareScope sc -> return ( keyword "Declare Scope" ++ spc () ++ str sc ) | VernacDelimiters (sc,Some key) -> return ( keyword "Delimit Scope" ++ spc () ++ str sc ++ spc() ++ keyword "with" ++ spc () ++ str key ) | VernacDelimiters (sc, None) -> return ( keyword "Undelimit Scope" ++ spc () ++ str sc ) | VernacBindScope (sc,cll) -> return ( keyword "Bind Scope" ++ spc () ++ str sc ++ spc() ++ keyword "with" ++ spc () ++ prlist_with_sep spc pr_class_rawexpr cll ) | VernacEnableNotation (on,rule,interp,flags,scope) -> let pr_flag = function | EnableNotationEntry InConstrEntry -> str "in constr" | EnableNotationEntry InCustomEntry s -> str "in custom " ++ pr_qualid s | EnableNotationOnly OnlyParsing -> str "only parsing" | EnableNotationOnly OnlyPrinting -> str "only printing" | EnableNotationOnly ParsingAndPrinting -> assert false | EnableNotationAll -> str "all" in let pr_flags = function | [] -> mt () | l -> str "(" ++ prlist_with_sep pr_comma pr_flag l ++ str ")" in let pr_rule = match rule with | None -> mt () | Some (Inl ntn) -> quote (str ntn) | Some (Inr abbrev) -> pr_abbreviation pr_qualid abbrev in let pr_opt_scope = function | None -> mt () | Some (NotationInScope s) -> spc () ++ str ": " ++ str s | Some LastLonelyNotation -> str ":" ++ spc () ++ str "none" in let pp = pr_rule ++ pr_flags flags ++ pr_opt_scope scope in return ( keyword (if on then "Enable Notation " else "Disable Notation ") ++ pp ) (* Gallina *) | VernacDefinition ((discharge,kind),id,b) -> (* A verifier... *) let isgoal = Name.is_anonymous (fst id).v in let pr_def_token = keyword ( if isgoal then "Goal" else string_of_definition_object_kind kind) in let pr_reduce = function | None -> mt() | Some r -> keyword "Eval" ++ spc() ++ pr_red_expr r ++ keyword " in" ++ spc() in let pr_def_body = match b with | DefineBody (bl,red,body,d) -> let ty = match d with | None -> mt() | Some ty -> spc() ++ str":" ++ pr_spc_lconstr ty in pr_binders_arg bl ++ ty ++ str " :=" ++ spc() ++ pr_reduce red ++ pr_lconstr body | ProveBody (bl,t) -> let typ u = if isgoal then (assert (bl = []); u) else (str" :" ++ u) in pr_binders_arg bl ++ typ (pr_spc_lconstr t) in return ( hov 2 ( pr_def_token ++ (if isgoal then mt() else spc() ++ pr_lname_decl id) ++ pr_def_body) ) | VernacStartTheoremProof (ki,l) -> return ( hov 1 (pr_statement (pr_thm_token ki) (List.hd l) ++ prlist (pr_statement (spc () ++ keyword "with")) (List.tl l)) ) | VernacEndProof Admitted -> return (keyword "Admitted") | VernacEndProof (Proved (opac,o)) -> return ( match o with | None -> (match opac with | Transparent -> keyword "Defined" | Opaque -> keyword "Qed") | Some id -> (if opac <> Transparent then keyword "Save" else keyword "Defined") ++ spc() ++ pr_lident id ) | VernacExactProof c -> return (hov 2 (keyword "Proof" ++ pr_lconstrarg c)) | VernacAssumption ((discharge,kind),t,l) -> let n = List.length (List.flatten (List.map fst (List.map snd l))) in let pr_params (c, (xl, t)) = hov 2 (prlist_with_sep sep pr_ident_decl xl ++ spc() ++ str(match c with AddCoercion -> ":>" | NoCoercion -> ":") ++ spc() ++ pr_lconstr_expr t) in let assumptions = prlist_with_sep spc (fun p -> hov 1 (str "(" ++ pr_params p ++ str ")")) l in return (hov 2 (pr_assumption_token (n > 1) discharge kind ++ pr_non_empty_arg pr_assumption_inline t ++ spc() ++ assumptions)) | VernacSymbol l -> let n = List.length (List.flatten (List.map fst (List.map snd l))) in let pr_params (c, (xl, t)) = hov 2 (prlist_with_sep sep pr_ident_decl xl ++ spc() ++ str(match c with AddCoercion -> ":>" | NoCoercion -> ":") ++ spc() ++ pr_lconstr_expr t) in let assumptions = prlist_with_sep spc (fun p -> hov 1 (str "(" ++ pr_params p ++ str ")")) l in return (hov 2 (keyword (if (n > 1) then "Symbols" else "Symbol") ++ spc() ++ assumptions)) | VernacInductive (f,l) -> let pr_constructor ((attr,coe,ins),(id,c)) = hov 2 (pr_vernac_attributes attr ++ pr_lident id ++ pr_oc coe ins ++ Flags.without_option Flags.beautify pr_spc_lconstr c) in let pr_constructor_list l = match l with | Constructors [] -> mt() | Constructors l -> let fst_sep = match l with [_] -> " " | _ -> " | " in pr_com_at (begin_of_inductive l) ++ fnl() ++ str fst_sep ++ prlist_with_sep (fun _ -> fnl() ++ str" | ") pr_constructor l | RecordDecl (c,fs,obinder) -> pr_record_decl c fs obinder in let pr_oneind key (((coe,iddecl),(indupar,indpar),s,lc),ntn) = hov 0 ( str key ++ spc() ++ str(match coe with AddCoercion -> "> " | NoCoercion -> "") ++ pr_cumul_ident_decl iddecl ++ pr_and_type_binders_arg indupar ++ pr_opt (fun p -> str "|" ++ spc() ++ pr_and_type_binders_arg p) indpar ++ pr_opt (fun s -> str":" ++ spc() ++ pr_lconstr_expr s) s ++ str" :=") ++ pr_constructor_list lc ++ prlist pr_where_notation ntn in let kind = match f with | Record -> "Record" | Structure -> "Structure" | Inductive_kw -> "Inductive" | CoInductive -> "CoInductive" | Class _ -> "Class" | Variant -> "Variant" in return ( hov 1 (pr_oneind kind (List.hd l)) ++ (prlist (fun ind -> fnl() ++ hov 1 (pr_oneind "with" ind)) (List.tl l)) ) | VernacFixpoint (local, (rec_order, recs)) -> let local = match local with | DoDischarge -> "Let " | NoDischarge -> "" in return ( hov 0 (str local ++ keyword "Fixpoint" ++ spc () ++ prlist_with_sep (fun _ -> fnl () ++ keyword "with" ++ spc ()) pr_rec_definition (List.combine rec_order recs)) ) | VernacCoFixpoint (local, corecs) -> let local = match local with | DoDischarge -> keyword "Let" ++ spc () | NoDischarge -> str "" in let pr_onecorec {fname; univs; binders; rtype; body_def; notations } = pr_ident_decl (fname,univs) ++ spc() ++ pr_binders binders ++ spc() ++ str":" ++ spc() ++ pr_lconstr_expr rtype ++ pr_opt (fun def -> str":=" ++ brk(1,2) ++ pr_lconstr def) body_def ++ prlist pr_where_notation notations in return ( hov 0 (local ++ keyword "CoFixpoint" ++ spc() ++ prlist_with_sep (fun _ -> fnl() ++ keyword "with" ++ spc ()) pr_onecorec corecs) ) | VernacSchemeAll (id, lid) -> return ( hov 2 (keyword "Scheme " ++ keyword "All" ++ str " for" ++ spc() ++ pr_smart_global id ++ pr_opt (fun x -> str " over" ++ spc() ++ prlist_with_sep pr_comma Id.print x) lid) ) | VernacScheme l -> return ( hov 2 (keyword "Scheme" ++ spc() ++ prlist_with_sep (fun _ -> fnl() ++ keyword "with" ++ spc ()) pr_onescheme l) ) | VernacSchemeEquality (sch,id) -> return ( hov 2 (keyword "Scheme " ++ pr_equality_scheme_type sch id) ) | VernacCombinedScheme (id, l) -> return ( hov 2 (keyword "Combined Scheme" ++ spc() ++ pr_lident id ++ spc() ++ keyword "from" ++ spc() ++ prlist_with_sep (fun _ -> fnl() ++ str", ") pr_lident l) ) | VernacUniverse v -> return ( hov 2 (keyword "Universe" ++ spc () ++ prlist_with_sep (fun _ -> str",") pr_lident v) ) | VernacSort v -> return ( hov 2 (keyword "Sort" ++ spc () ++ prlist_with_sep (fun _ -> str",") pr_lident v) ) | VernacConstraint v -> return ( hov 2 (keyword "Constraint" ++ spc () ++ prlist_with_sep (fun _ -> str",") pr_pconstraint v) ) (* Gallina extensions *) | VernacNameSectionHypSet (id,set) -> return (hov 2 (keyword "Collection" ++ spc() ++ pr_lident id ++ spc()++ str ":="++spc()++pr_using set)) | VernacCanonical q -> return ( keyword "Canonical Structure" ++ spc() ++ pr_smart_global q ) | VernacCoercion (id,Some(c1,c2)) -> return ( hov 1 ( keyword "Coercion" ++ spc() ++ pr_smart_global id ++ spc() ++ str":" ++ spc() ++ pr_class_rawexpr c1 ++ spc() ++ str">->" ++ spc() ++ pr_class_rawexpr c2) ) | VernacCoercion (id,None) -> return ( hov 1 ( keyword "Coercion" ++ spc() ++ pr_smart_global id) ) | VernacIdentityCoercion (id,c1,c2) -> return ( hov 1 ( keyword "Identity Coercion" ++ spc() ++ pr_lident id ++ spc() ++ str":" ++ spc() ++ pr_class_rawexpr c1 ++ spc() ++ str">->" ++ spc() ++ pr_class_rawexpr c2) ) | VernacInstance (instid, sup, cl, props, info) -> return ( hov 1 ( keyword "Instance" ++ (match instid with | {loc; v = Name id}, l -> spc () ++ pr_ident_decl (CAst.(make ?loc id),l) ++ spc () | { v = Anonymous }, _ -> mt ()) ++ pr_and_type_binders_arg sup ++ str":" ++ spc () ++ pr_constr cl ++ pr_hint_info pr_constr_pattern_expr info ++ (match props with | Some (true, { v = CRecord l}) -> spc () ++ str":=" ++ spc () ++ pr_record_body "{" "}" pr_lconstr l | Some (true,_) -> assert false | Some (false,p) -> spc () ++ str":=" ++ spc () ++ pr_constr p | None -> mt())) ) | VernacDeclareInstance (instid, sup, cl, info) -> return ( hov 1 ( keyword "Declare Instance" ++ spc () ++ pr_ident_decl instid ++ spc () ++ pr_and_type_binders_arg sup ++ str":" ++ spc () ++ pr_constr cl ++ pr_hint_info pr_constr_pattern_expr info) ) | VernacContext l -> return ( hov 1 ( keyword "Context" ++ pr_and_type_binders_arg l) ) | VernacExistingInstance insts -> let pr_inst (id, info) = pr_qualid id ++ pr_hint_info pr_constr_pattern_expr info in return ( hov 1 (keyword "Existing" ++ spc () ++ keyword(String.plural (List.length insts) "Instance") ++ spc () ++ prlist_with_sep spc pr_inst insts) ) | VernacExistingClass id -> return ( hov 1 (keyword "Existing" ++ spc () ++ keyword "Class" ++ spc () ++ pr_qualid id) ) (* Commands *) | VernacCreateHintDb (dbname,b) -> return ( hov 1 (keyword "Create HintDb" ++ spc () ++ str dbname ++ (if b then str" discriminated" else mt ())) ) | VernacRemoveHints (dbnames, ids) -> return ( hov 1 (keyword "Remove Hints" ++ spc () ++ prlist_with_sep spc (fun r -> pr_qualid r) ids ++ pr_opt_hintbases dbnames) ) | VernacHints (dbnames,h) -> return (pr_hints dbnames h pr_constr pr_constr_pattern_expr) | VernacAbbreviation (id,(ids,c),l,_) -> return ( hov 2 (keyword "Abbreviation" ++ spc () ++ pr_abbreviation pr_lident (ids,id) ++ str":=" ++ pr_constrarg c ++ pr_syntax_modifiers l) ) | VernacArguments (q, args, more_implicits, mods) -> return ( hov 2 ( keyword "Arguments" ++ spc() ++ pr_smart_global q ++ let pr_s = prlist (fun {v=s} -> pr_scope_delimiter s) in let pr_if b x = if b then x else str "" in let pr_one_arg (x,k) = pr_if k (str"!") ++ Name.print x in let pr_br imp force x = let left,right = match imp with | Glob_term.NonMaxImplicit -> str "[", str "]" | Glob_term.MaxImplicit -> str "{", str "}" | Glob_term.Explicit -> if force then str"(",str")" else mt(),mt() in left ++ x ++ right in let get_arguments_like s imp tl = if s = [] && imp = Glob_term.Explicit then [], tl else let rec fold extra = function | RealArg arg :: tl when List.equal (fun a b -> let da, a = a.CAst.v in let db, b = b.CAst.v in da = db && String.equal a b) arg.notation_scope s && arg.implicit_status = imp -> fold ((arg.name,arg.recarg_like) :: extra) tl | args -> List.rev extra, args in fold [] tl in let rec print_arguments = function | [] -> mt() | VolatileArg :: l -> spc () ++ str"/" ++ print_arguments l | BidiArg :: l -> spc () ++ str"&" ++ print_arguments l | RealArg { name = id; recarg_like = k; notation_scope = s; implicit_status = imp } :: tl -> let extra, tl = get_arguments_like s imp tl in spc() ++ hov 1 (pr_br imp (extra<>[]) (prlist_with_sep spc pr_one_arg ((id,k)::extra)) ++ pr_s s) ++ print_arguments tl in let rec print_implicits = function | [] -> mt () | (name, impl) :: rest -> spc() ++ pr_br impl false (Name.print name) ++ print_implicits rest in print_arguments args ++ if not (List.is_empty more_implicits) then prlist (fun l -> str"," ++ print_implicits l) more_implicits else (mt ()) ++ (if not (List.is_empty mods) then str" : " else str"") ++ prlist_with_sep (fun () -> str", " ++ spc()) (function | `SimplDontExposeCase -> keyword "simpl nomatch" | `SimplNeverUnfold -> keyword "simpl never" | `DefaultImplicits -> keyword "default implicits" | `Rename -> keyword "rename" | `Assert -> keyword "assert" | `ExtraScopes -> keyword "extra scopes" | `ClearImplicits -> keyword "clear implicits" | `ClearReduction -> keyword "clear simpl" | `ClearScopes -> keyword "clear scopes" | `ClearBidiHint -> keyword "clear bidirectionality hint") mods) ) | VernacReserve bl -> let n = List.length (List.flatten (List.map fst bl)) in return ( hov 2 (tag_keyword (str"Implicit Type" ++ str (if n > 1 then "s " else " ")) ++ pr_ne_params_list pr_lconstr_expr (List.map (fun sb -> false,sb) bl)) ) | VernacGeneralizable g -> return ( hov 1 (tag_keyword ( str"Generalizable Variable" ++ match g with | None -> str "s none" | Some [] -> str "s all" | Some idl -> str (if List.length idl > 1 then "s " else " ") ++ prlist_with_sep spc pr_lident idl) )) | VernacSetOpacity((k,l),b) when Conv_oracle.is_transparent k -> return ( hov 1 (keyword (if b then "Transparent!" else "Transparent") ++ spc() ++ prlist_with_sep sep pr_smart_global l) ) | VernacSetOpacity((Conv_oracle.Opaque,l),b) -> return ( hov 1 (keyword (if b then "Opaque!" else "Opaque") ++ spc() ++ prlist_with_sep sep pr_smart_global l) ) | VernacSetOpacity _ -> return ( CErrors.anomaly (keyword "VernacSetOpacity used to set something else.") ) | VernacSetStrategy l -> let pr_lev = function | Conv_oracle.Opaque -> keyword "opaque" | Conv_oracle.Expand -> keyword "expand" | l when Conv_oracle.is_transparent l -> keyword "transparent" | Conv_oracle.Level n -> int n in let pr_line (l,q) = hov 2 (pr_lev l ++ spc() ++ str"[" ++ prlist_with_sep sep pr_smart_global q ++ str"]") in return ( hov 1 (keyword "Strategy" ++ spc() ++ hv 0 (prlist_with_sep sep pr_line l)) ) | VernacAddOption (na,l) -> return ( hov 2 (keyword "Add" ++ spc() ++ pr_printoption na (Some l)) ) | VernacRemoveOption (na,l) -> return ( hov 2 (keyword "Remove" ++ spc() ++ pr_printoption na (Some l)) ) | VernacMemOption (na,l) -> return ( hov 2 (keyword "Test" ++ spc() ++ pr_printoption na (Some l)) ) | VernacPrintOption na -> return ( hov 2 (keyword "Test" ++ spc() ++ pr_printoption na None) ) | VernacCheckMayEval (r,io,c) -> let pr_mayeval r c = match r with | Some r0 -> hov 2 (keyword "Eval" ++ spc() ++ pr_red_expr r0 ++ spc() ++ keyword "in" ++ spc () ++ pr_lconstr c) | None -> hov 2 (keyword "Check" ++ spc() ++ pr_lconstr c) in let pr_i = match io with None -> mt () | Some i -> Goal_select.pr_goal_selector i ++ str ": " in return (pr_i ++ pr_mayeval r c) | VernacGlobalCheck c -> return (hov 2 (keyword "Type" ++ pr_constrarg c)) | VernacDeclareReduction (s,r) -> return ( keyword "Declare Reduction" ++ spc () ++ str s ++ str " := " ++ pr_red_expr r ) | VernacPrint p -> return (pr_printable p) | VernacSearch (sea,g,sea_r) -> return (pr_search sea g sea_r @@ pr_constr_pattern_expr) | VernacLocate loc -> let pr_locate =function | LocateAny qid -> pr_smart_global qid | LocateTerm qid -> keyword "Term" ++ spc() ++ pr_smart_global qid | LocateFile f -> keyword "File" ++ spc() ++ qs f | LocateLibrary qid -> keyword "Library" ++ spc () ++ pr_module qid | LocateModule qid -> keyword "Module" ++ spc () ++ pr_module qid | LocateOther (s, qid) -> keyword s ++ spc () ++ pr_ltac_ref qid in return (keyword "Locate" ++ spc() ++ pr_locate loc) | VernacRegister (qid, RegisterCoqlib name) -> return ( hov 2 (keyword "Register" ++ spc() ++ pr_qualid qid ++ spc () ++ str "as" ++ spc () ++ pr_qualid name) ) | VernacRegister (qid, RegisterScheme {inductive; scheme_kind}) -> return ( hov 2 (keyword "Register" ++ spc() ++ keyword "Scheme" ++ spc() ++ pr_qualid qid ++ spc () ++ str "as" ++ spc () ++ pr_qualid scheme_kind ++ spc() ++ str "for" ++ spc() ++ pr_qualid inductive) ) | VernacRegister (qid, RegisterInline) -> return ( hov 2 (keyword "Register Inline" ++ spc() ++ pr_qualid qid) ) | VernacPrimitive(id,r,typopt) -> hov 2 (keyword "Primitive" ++ spc() ++ pr_ident_decl 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 (keyword "Comments" ++ spc() ++ prlist_with_sep sep (pr_comment pr_constr) l) ) | VernacAttributes attrs -> return ( hov 2 (keyword "Attributes" ++ spc () ++ pr_vernac_attributes attrs) ) | VernacProof (None, None) -> return (keyword "Proof") | VernacProof (None, Some e) -> return (keyword "Proof " ++ spc () ++ keyword "using" ++ spc() ++ pr_using e) | VernacProof (Some te, None) -> return (keyword "Proof with" ++ spc() ++ pr_gentac te) | VernacProof (Some te, Some e) -> return ( keyword "Proof" ++ spc () ++ keyword "using" ++ spc() ++ pr_using e ++ spc() ++ keyword "with" ++ spc() ++ pr_gentac te ) | VernacBullet b -> (* XXX: Redundant with Proof_bullet.print *) return (let open Proof_bullet in begin match b with | Dash n -> str (String.make n '-') | Star n -> str (String.make n '*') | Plus n -> str (String.make n '+') end) | VernacSubproof None -> return (str "{") | VernacSubproof (Some i) -> return (Goal_select.pr_goal_selector i ++ str ":" ++ spc () ++ str "{") | VernacEndSubproof -> return (str "}") | VernacAddRewRule (id, l) -> return ( hov 0 (keyword (if List.length l > 1 then "Rewrite Rules" else "Rewrite Rule") ++ spc () ++ pr_lident id ++ str ":=" ++ prlist_with_sep (fun _ -> fnl () ++ keyword "with" ++ spc ()) pr_rew_rule l) ) let pr_synterp_vernac_expr v = let return = tag_vernac v in match v with | VernacLoad (f,s) -> return ( keyword "Load" ++ if f then (spc() ++ keyword "Verbose" ++ spc()) else spc() ++ qs s ) | VernacBeginSection id -> return (hov 2 (keyword "Section" ++ spc () ++ pr_lident id)) | VernacEndSegment id -> return (hov 2 (keyword "End" ++ spc() ++ pr_lident id)) | VernacNotation (infix,ntn_decl) -> return ( hov 2 (hov 0 (keyword (if infix then "Infix" else "Notation") ++ spc() ++ pr_notation_declaration ntn_decl)) ) | VernacReservedNotation (_, (s, l)) -> return ( keyword "Reserved Notation" ++ spc() ++ pr_ast qs s ++ pr_syntax_modifiers l ) | VernacDeclareCustomEntry s -> return ( keyword "Declare Custom Entry " ++ Id.print s ) | VernacRequire (from, exp, l) -> let from = match from with | None -> mt () | Some r -> keyword "From" ++ spc () ++ pr_module r ++ spc () in return ( hov 2 (from ++ keyword "Require" ++ spc() ++ pr_require_token exp ++ prlist_with_sep sep pr_import_module l) ) | VernacImport (f,l) -> return ( pr_export_with_cats f ++ spc() ++ prlist_with_sep sep pr_import_module l ) (* Modules and Module Types *) | VernacDefineModule (export,m,bl,tys,bd) -> let b = pr_module_binders bl pr_lconstr in return ( hov 2 (keyword "Module" ++ spc() ++ pr_require_token export ++ pr_lident m ++ b ++ pr_of_module_type pr_lconstr tys ++ (if List.is_empty bd then mt () else str ":= ") ++ prlist_with_sep (fun () -> str " <+") (pr_module_ast_inl true pr_lconstr) bd) ) | VernacDeclareModule (export,id,bl,m1) -> let b = pr_module_binders bl pr_lconstr in return ( hov 2 (keyword "Declare Module" ++ spc() ++ pr_require_token export ++ pr_lident id ++ b ++ str " :" ++ pr_module_ast_inl true pr_lconstr m1) ) | VernacDeclareModuleType (id,bl,tyl,m) -> let b = pr_module_binders bl pr_lconstr in let pr_mt = pr_module_ast_inl true pr_lconstr in return ( hov 2 (keyword "Module Type " ++ pr_lident id ++ b ++ prlist_strict (fun m -> str " <:" ++ pr_mt m) tyl ++ (if List.is_empty m then mt () else str ":= ") ++ prlist_with_sep (fun () -> str " <+ ") pr_mt m) ) | VernacInclude (mexprs) -> let pr_m = pr_module_ast_inl false pr_lconstr in return ( hov 2 (keyword "Include" ++ spc() ++ prlist_with_sep (fun () -> str " <+ ") pr_m mexprs) ) (* Auxiliary file and library management *) | VernacDeclareMLModule (l) -> return ( hov 2 (keyword "Declare ML Module" ++ spc() ++ prlist_with_sep sep qs l) ) | VernacChdir None -> return (keyword "Pwd") | VernacChdir (Some s) -> return (keyword "Cd " ++ qs s) | VernacSetOption (export, na,v) -> let export = if export then keyword "Export" ++ spc () else mt () in let set = if v == OptionUnset then "Unset" else "Set" in return ( hov 2 (export ++ keyword set ++ spc() ++ pr_set_option na v) ) | VernacExtraDependency(from,file,id) -> return ( hov 2 (keyword "From" ++ spc () ++ pr_module from ++ spc () ++ keyword "Extra" ++ spc() ++ keyword "Dependency" ++ spc() ++ qs file ++ pr_opt (fun x -> spc() ++ keyword "as" ++ spc () ++ pr_id x) id) ) | VernacExtend (s,c) -> return (pr_extend s c) | VernacProofMode s -> return (keyword "Proof Mode" ++ str s) let pr_control_flag (p : control_flag) = let w = match p.v with | ControlTime -> keyword "Time" | ControlInstructions -> keyword "Instructions" | ControlProfile f -> keyword "Profile" ++ pr_opt qstring f | ControlRedirect s -> keyword "Redirect" ++ spc() ++ qs s | ControlTimeout n -> keyword "Timeout " ++ int n | ControlFail -> keyword "Fail" | ControlSucceed -> keyword "Succeed" in w ++ spc () let pr_vernac_control flags = Pp.prlist pr_control_flag flags let pr_vernac_expr v = match v with | VernacSynPure e -> pr_synpure_vernac_expr e | VernacSynterp e -> pr_synterp_vernac_expr e let pr_vernac ({v = {control; attrs; expr}} as v) = tag_vernac v (pr_vernac_control control ++ pr_vernac_attributes attrs ++ pr_vernac_expr expr ++ sep_end expr) rocq-9.2.0/vernac/ppvernac.mli000066400000000000000000000031731516144147600163020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Pp.t) -> ('a -> Pp.t) -> ('custom,'a) Extend.constr_entry_key_gen -> Pp.t val pr_syntax_modifier : Vernacexpr.syntax_modifier CAst.t -> Pp.t (** Prints a fixpoint body *) val pr_rec_definition : Constrexpr.fixpoint_order_expr option * Vernacexpr.recursive_expr_gen -> Pp.t (** Prints a scheme *) val pr_onescheme : Names.lident option * Vernacexpr.scheme -> Pp.t (** Prints a vernac expression without dot *) val pr_vernac_expr : Vernacexpr.vernac_expr -> Pp.t (** Prints a "proof using X" clause. *) val pr_using : Vernacexpr.section_subset_expr -> Pp.t (** Prints a vernac expression and closes it with a dot. *) val pr_vernac : Vernacexpr.vernac_control -> Pp.t (** Prints attributes, including surrounding "#[" "]", followed by space (empty on empty list) *) val pr_vernac_attributes : Attributes.vernac_flag list -> Pp.t rocq-9.2.0/vernac/prettyp.ml000066400000000000000000001404061516144147600160230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* on May-June 2006 for implementation of abstraction of pretty-printing of objects. *) open Pp open CErrors open Util open CAst open Names open Termops open Declarations open Environ open Impargs open Libobject open Libnames open Globnames open Printer open Context.Rel.Declaration module RelDecl = Context.Rel.Declaration module NamedDecl = Context.Named.Declaration let print_module mp = Printmod.print_module ~with_body:true mp let print_modtype = Printmod.print_modtype (**************) (** Utilities *) let print_closed_sections = ref false let pr_infos_list l = v 0 (prlist_with_sep cut (fun x -> x) l) let with_line_skip l = if List.is_empty l then mt() else fnl() ++ fnl () ++ pr_infos_list l let blankline = mt() (* add a blank sentence in the list of infos *) let add_colon prefix = if ismt prefix then mt () else prefix ++ str ": " let int_or_no n = if Int.equal n 0 then str "no" else int n (*******************) (** Basic printing *) let print_basename cst = pr_global (GlobRef.ConstRef cst) let print_ref env reduce ref udecl = let typ, univs = Typeops.type_of_global_in_context env ref in let inst = UVars.make_abstract_instance univs in let udecl = Option.map (fun x -> ref, x) udecl in let bl = Printer.universe_binders_with_opt_names (Environ.universes_of_global env ref) udecl in let sigma = Evd.from_ctx (UState.of_names bl) in let typ = if reduce then let ctx,ccl = Reductionops.whd_decompose_prod_decls env sigma (EConstr.of_constr typ) in EConstr.to_constr sigma (EConstr.it_mkProd_or_LetIn ccl ctx) else typ in let typ = Arguments_renaming.rename_type env typ ref in let impargs = select_stronger_impargs (implicits_of_global ref) in let impargs = List.map binding_kind_of_status impargs in let variance = let open GlobRef in match ref with | VarRef _ | ConstRef _ -> None | IndRef (ind,_) | ConstructRef ((ind,_),_) -> let mind = Environ.lookup_mind ind env in mind.Declarations.mind_variance in let inst = if Environ.is_polymorphic env ref then Printer.pr_universe_instance_binder sigma inst Univ.UnivConstraints.empty else mt () in let priv = None in (* We deliberately don't print private univs in About. *) hov 0 (pr_global ref ++ inst ++ str " :" ++ spc () ++ pr_ltype_env env sigma ~impargs typ ++ Printer.pr_abstract_universe_ctx sigma ?variance univs ?priv) (** Command [Print Implicit], somehow subsumed by [About] *) let pr_impl_name imp = Id.print (name_of_implicit imp) let print_impargs_by_name max = function | [] -> [] | impls -> let n = List.length impls in [hov 0 (str (String.plural n "Argument") ++ spc() ++ prlist_with_sep pr_comma pr_impl_name impls ++ spc() ++ str (String.conjugate_verb_to_be n) ++ str" implicit" ++ (if max then strbrk " and maximally inserted" else mt()))] let print_one_impargs_list l = let imps = List.filter is_status_implicit l in let maximps = List.filter Impargs.maximal_insertion_of imps in let nonmaximps = List.subtract (=) imps maximps in (* FIXME *) print_impargs_by_name false nonmaximps @ print_impargs_by_name true maximps let print_impargs_list prefix l = let l = extract_impargs_data l in List.flatten (List.map (fun (cond,imps) -> match cond with | None -> List.map (fun pp -> add_colon prefix ++ pp) (print_one_impargs_list imps) | Some (n1,n2) -> [v 2 (prlist_with_sep cut (fun x -> x) [(if ismt prefix then str "When" else prefix ++ str ", when") ++ str " applied to " ++ (if Int.equal n1 n2 then int_or_no n2 else if Int.equal n1 0 then str "no more than " ++ int n2 else int n1 ++ str " to " ++ int_or_no n2) ++ str (String.plural n2 " argument") ++ str ":"; v 0 (prlist_with_sep cut (fun x -> x) (if List.exists is_status_implicit imps then print_one_impargs_list imps else [str "No implicit arguments"]))])]) l) let need_expansion env impl ref = let typ, _ = Typeops.type_of_global_in_context env ref in let ctx = Term.prod_decls typ in let nprods = List.count is_local_assum ctx in not (List.is_empty impl) && List.length impl >= nprods && let _,lastimpl = List.chop nprods impl in List.exists is_status_implicit lastimpl let print_impargs env ref = let impl = implicits_of_global ref in let has_impl = not (List.is_empty impl) in (* Need to reduce since implicits are computed with products flattened *) pr_infos_list ([ print_ref env (need_expansion env (select_impargs_size 0 impl) ref) ref None; blankline ] @ (if has_impl then print_impargs_list (mt()) impl else [str "No implicit arguments"])) (** Printing reduction behavior *) let print_reduction_behaviour = function | GlobRef.ConstRef ref -> let p = Reductionops.ReductionBehaviour.print ref in if Pp.ismt p then [] else [p] | _ -> [] (** Printing opacity status *) type opacity = | FullyOpaque | TransparentMaybeOpacified of Conv_oracle.level let opacity env = function | GlobRef.VarRef v when NamedDecl.is_local_def (Environ.lookup_named v env) -> Some(TransparentMaybeOpacified (Conv_oracle.get_strategy (Environ.oracle env) (Conv_oracle.EvalVarRef v))) | GlobRef.ConstRef cst -> let cb = Environ.lookup_constant cst env in (match cb.const_body with | Undef _ | Primitive _ | Symbol _ -> None | OpaqueDef _ -> Some FullyOpaque | Def _ -> Some (TransparentMaybeOpacified (Conv_oracle.get_strategy (Environ.oracle env) (Conv_oracle.EvalConstRef cst)))) | _ -> None let print_opacity env ref = match opacity env ref with | None -> [] | Some s -> [pr_global ref ++ str " is " ++ match s with | FullyOpaque -> str "opaque" | TransparentMaybeOpacified Conv_oracle.Opaque -> str "opaque but may be made transparent" | TransparentMaybeOpacified lev when Conv_oracle.is_transparent lev -> str "transparent" | TransparentMaybeOpacified (Conv_oracle.Level n) -> str "transparent (level " ++ int n ++ str ")" | TransparentMaybeOpacified Conv_oracle.Expand -> str "transparent (expand)"] (** Printing coercion status *) let print_if_is_coercion ref = if Coercionops.coercion_exists ref then let i = Coercionops.coercion_info ref in let r = if i.Coercionops.coe_reversible then " reversible" else "" in [pr_global ref ++ str " is a" ++ str r ++ str " coercion"] else [] (** Printing polymorphic status *) (* XXX TODO print based on the actual binders not from the monomorphic data *) let template_poly_variables env ind = let mib, mip = Inductive.lookup_mind_specif env ind in match mib.mind_template with | None -> assert false | Some { template_defaults; template_concl } -> let pseudo_poly = match template_concl with | QSort (q, _) when Option.has_some (Sorts.QVar.var_index q) -> true | _ -> false in let _, vars = UVars.Instance.levels template_defaults in Univ.Level.Set.elements vars, pseudo_poly let get_template_poly_variables env = function | GlobRef.IndRef ind | ConstructRef (ind,_) -> template_poly_variables env ind | VarRef _ | ConstRef _ -> assert false let pr_template_variables env ref = let vars, pseudo_sort_poly = get_template_poly_variables env ref in str " on " ++ prlist_with_sep spc UnivNames.pr_level_with_global_universes vars ++ spc() ++ (if pseudo_sort_poly then str "(can be instantiated to Prop)" else str "(cannot be instantiated to Prop)") let print_polymorphism env ref = let poly = Environ.is_polymorphic env ref in let template_poly = Environ.is_template_polymorphic env ref in [ pr_global ref ++ str " is " ++ (if poly then str "universe polymorphic" else if template_poly then str "template universe polymorphic" ++ if !PrintingFlags.print_universes then h (pr_template_variables env ref) else mt() else str "not universe polymorphic") ] let print_squash env ref udecl = match ref with | GlobRef.IndRef ind -> let _, mip = Inductive.lookup_mind_specif env ind in begin match mip.mind_squashed with | None -> [] | Some squash -> let univs = Environ.universes_of_global env ref in let udecl = Option.map (fun x -> ref, x) udecl in let bl = Printer.universe_binders_with_opt_names univs udecl in let sigma = Evd.from_ctx (UState.of_names bl) in let inst = if fst @@ UVars.AbstractContext.size univs = 0 then mt() else Printer.pr_universe_instance sigma (UVars.make_abstract_instance univs) in let inds = mip.mind_sort in let target = match inds with | SProp -> str "SProp" | Prop -> str "SProp or Prop" | Set -> str "SProp, Prop or Set" | Type _ -> str "not in a variable sort quality" | QSort (q,_) -> str "in sort quality " ++ Termops.pr_evd_qvar sigma q in let unless = match squash with | AlwaysSquashed -> str "." | SometimesSquashed qs -> let target = match inds with | SProp | Prop | Set -> target | Type _ -> str "instantiated to constant qualities" | QSort (q,_) -> let ppq = Termops.pr_evd_qvar sigma q in str "equal to the instantiation of " ++ ppq ++ pr_comma() ++ str "or to qualities smaller" ++ spc() ++ str "(SProp <= Prop <= Type, and all variables <= Type)" ++ spc() ++ str "than the instantiation of " ++ ppq in let qs = Sorts.Quality.Set.elements qs in let quality_s, is_s = match qs with | [_] -> "quality", "is" | _ -> "qualities", "are" in (* this reads kinda weird when qs is singleton of a constant quality, we get eg "quality Prop is equal to the instantiation of q" *) pr_comma () ++ hov 0 (str "unless instantiated such that the " ++ str quality_s ++ str " " ++ pr_enum (Sorts.Quality.pr (Termops.pr_evd_qvar sigma)) qs ++ spc() ++ str is_s ++ str " " ++ target ++ str ".") in [hv 2 (hov 1 (pr_global ref ++ inst) ++ str " may only be eliminated to produce values whose type is " ++ target ++ unless)] end | _ -> [] let print_prop_but_default_dep_elim ref = match ref with | GlobRef.IndRef ind -> if Elimschemes.is_prop_but_default_dependent_elim ind then [pr_global ref ++ str " is in Prop but its eliminators are declared dependent by default"] else [] | _ -> [] (** Print projection status *) let print_projection env ref = match ref with | GlobRef.ConstRef cst -> begin match Structures.PrimitiveProjections.find_opt cst with | Some p -> [pr_global ref ++ str " is a primitive projection of " ++ pr_global (IndRef (Projection.Repr.inductive p))] | None -> try let ind = (Structures.Structure.find_from_projection env cst).name in [pr_global ref ++ str " is a projection of " ++ pr_global (IndRef ind)] with Not_found -> [] end | _ -> [] (** Printing type-in-type status *) let print_type_in_type env ref = let unsafe = Environ.is_type_in_type env ref in if unsafe then [ pr_global ref ++ str " relies on an unsafe universe hierarchy"] else [] (** Printing primitive projection status *) let print_primitive_record recflag mipv = let mipv = Array.to_list mipv in mipv |> List.concat_map @@ fun mip -> match mip.mind_record with | PrimRecord { has_eta; _ } -> let eta = match recflag with | CoFinite | Finite -> str " without eta conversion" | BiFinite -> match has_eta with | NoEta -> str " without eta conversion" | AlwaysEta -> str " with eta conversion" in [Id.print mip.mind_typename ++ str" has primitive projections" ++ eta ++ str"."] | FakeRecord | NotRecord -> [] let print_primitive env ref = match ref with | GlobRef.IndRef ind -> let mib = Environ.lookup_mind (fst ind) env in print_primitive_record mib.mind_finite mib.mind_packets | _ -> [] (** Printing arguments status (scopes, implicit, names) *) let needs_extra_scopes env ref scopes = let open Constr in let rec aux env t = function | [] -> false | _::scopes -> match kind (Reduction.whd_all env t) with | Prod (na,dom,codom) -> aux (push_rel (RelDecl.LocalAssum (na,dom)) env) codom scopes | _ -> true in let ty, _ctx = Typeops.type_of_global_in_context env ref in aux env ty scopes let implicit_kind_of_status = function | None -> Anonymous, Glob_term.Explicit | Some imp -> pi1 imp.impl_pos, if imp.impl_max then Glob_term.MaxImplicit else Glob_term.NonMaxImplicit let extra_implicit_kind_of_status imp = let _,imp = implicit_kind_of_status imp in (Anonymous, imp) let dummy = { Vernacexpr.implicit_status = Glob_term.Explicit; name = Anonymous; recarg_like = false; notation_scope = []; } let is_dummy = function | Vernacexpr.(RealArg {implicit_status; name; recarg_like; notation_scope}) -> name = Anonymous && not recarg_like && notation_scope = [] && implicit_status = Glob_term.Explicit | _ -> false let rec main_implicits i renames recargs scopes impls = if renames = [] && recargs = [] && scopes = [] && impls = [] then [] else let recarg_like, recargs = match recargs with | j :: recargs when i = j -> true, recargs | _ -> false, recargs in let (name, implicit_status) = match renames, impls with | _, (Some _ as i) :: _ -> implicit_kind_of_status i | name::_, _ -> (name,Glob_term.Explicit) | [], (None::_ | []) -> (Anonymous, Glob_term.Explicit) in let notation_scope = match scopes with | scope :: _ -> List.map (fun s -> CAst.make (Constrexpr.DelimOnlyTmpScope, s)) scope | [] -> [] in let status = {Vernacexpr.implicit_status; name; recarg_like; notation_scope} in let tl = function [] -> [] | _::tl -> tl in (* recargs is special -> tl handled above *) let rest = main_implicits (i+1) (tl renames) recargs (tl scopes) (tl impls) in status :: rest let rec insert_fake_args volatile bidi impls = let open Vernacexpr in match volatile, bidi with | Some 0, _ -> VolatileArg :: insert_fake_args None bidi impls | _, Some 0 -> BidiArg :: insert_fake_args volatile None impls | None, None -> List.map (fun a -> RealArg a) impls | _, _ -> let hd, tl = match impls with | impl :: impls -> impl, impls | [] -> dummy, [] in let f = Option.map pred in RealArg hd :: insert_fake_args (f volatile) (f bidi) tl let print_arguments env ref = let qid = Nametab.shortest_qualid_of_global Id.Set.empty ref in let flags, recargs, nargs_for_red = match ref with | ConstRef ref -> begin match Reductionops.ReductionBehaviour.get ref with | None -> [], [], None | Some NeverUnfold -> [`SimplNeverUnfold], [], None | Some (UnfoldWhen { nargs; recargs }) -> [], recargs, nargs | Some (UnfoldWhenNoMatch { nargs; recargs }) -> [`SimplDontExposeCase], recargs, nargs end | _ -> [], [], None in let names, not_renamed = try Arguments_renaming.arguments_names env ref, false with Not_found -> let ty, _ = Typeops.type_of_global_in_context env ref in List.map pi1 (Impargs.compute_implicits_names env (Evd.from_env env) (EConstr.of_constr ty)), true in let scopes = Notation.find_arguments_scope env ref in let flags = if needs_extra_scopes env ref scopes then `ExtraScopes::flags else flags in let impls = Impargs.extract_impargs_data (Impargs.implicits_of_global ref) in let impls, moreimpls = match impls with | (_, impls) :: rest -> impls, rest | [] -> assert false in let impls = main_implicits 0 names recargs scopes impls in let moreimpls = List.map (fun (_,i) -> List.map extra_implicit_kind_of_status i) moreimpls in let bidi = Pretyping.get_bidirectionality_hint env ref in let impls = insert_fake_args nargs_for_red bidi impls in if List.for_all is_dummy impls && moreimpls = [] && flags = [] then [] else let open Constrexpr in let open Vernacexpr in [Ppvernac.pr_vernac_expr (VernacSynPure (VernacArguments (CAst.make (AN qid), impls, moreimpls, flags))) ++ (if not_renamed then mt () else fnl () ++ str " (where some original arguments have been renamed)")] (** Printing dependencies in section variables *) let print_section_deps env ref = let hyps = let open GlobRef in match ref with | VarRef _ -> None | ConstRef c -> let bd = Environ.lookup_constant c env in Some bd.const_hyps | IndRef (mind,_) | ConstructRef ((mind,_),_) -> let mb = Environ.lookup_mind mind env in Some mb.mind_hyps in let hyps = Option.map (List.filter NamedDecl.is_local_assum) hyps in match hyps with | None | Some [] -> [] | Some hyps -> [hov 0 (pr_global ref ++ str (String.plural (List.length hyps) " uses section variable") ++ spc () ++ hv 1 (prlist_with_sep spc (fun d -> Id.print (NamedDecl.get_id d)) (List.rev hyps)) ++ str ".")] (** Printing bidirectionality status *) let print_bidi_hints env gr = match Pretyping.get_bidirectionality_hint env gr with | None -> [] | Some nargs -> [str "Using typing information from context after typing the " ++ int nargs ++ str " first arguments"] (** Printing basic information about references (common to Print and About) *) let print_name_infos env ref = let type_info_for_implicit = if need_expansion env (select_impargs_size 0 (implicits_of_global ref)) ref then (* Need to reduce since implicits are computed with products flattened *) [str "Expanded type for implicit arguments"; print_ref env true ref None; blankline] else [] in print_type_in_type env ref @ print_prop_but_default_dep_elim ref @ print_projection env ref @ print_primitive env ref @ type_info_for_implicit @ print_arguments env ref @ print_section_deps env ref @ print_if_is_coercion ref (******************************************) (**** Printing declarations and judgments *) (**** Gallina layer *****) let print_typed_value_in_env env sigma (trm,typ) = (pr_leconstr_env ~inctx:true env sigma trm ++ fnl () ++ str " : " ++ pr_letype_env env sigma typ) (* To be improved; the type should be used to provide the types in the abstractions. This should be done recursively inside pr_lconstr, so that the pretty-print of a proposition (P:(nat->nat)->Prop)(P [u]u) synthesizes the type nat of the abstraction on u *) let print_named_def env sigma ~impargs name body typ = let pbody = pr_lconstr_env ~inctx:true env sigma body in let ptyp = pr_ltype_env env sigma ~impargs typ in let pbody = if Constr.isCast body then surround pbody else pbody in (str "*** [" ++ str name ++ str " " ++ hov 0 (str ":=" ++ brk (1,2) ++ pbody ++ spc () ++ str ":" ++ brk (1,2) ++ ptyp) ++ str "]") let print_named_assum env sigma ~impargs name typ = str "*** [" ++ str name ++ str " : " ++ pr_ltype_env env sigma ~impargs typ ++ str "]" let print_named_decl env sigma with_implicit id = let open Context.Named.Declaration in let impargs = if with_implicit then select_stronger_impargs (implicits_of_global (VarRef id)) else [] in let impargs = List.map binding_kind_of_status impargs in match lookup_named id env with | LocalAssum (id, typ) -> print_named_assum env sigma ~impargs (Id.to_string id.Context.binder_name) typ | LocalDef (id, body, typ) -> print_named_def env sigma ~impargs (Id.to_string id.Context.binder_name) body typ let assumptions_for_print lna = List.fold_right (fun na env -> add_name na env) lna empty_names_context (*********************) (* *) let print_inductive_args env mind mib = let flatmapi f v = List.flatten (Array.to_list (Array.mapi f v)) in let mips = (* We don't use the PrimRecord field as it misses the projections corresponding to local definition *) try Array.mapi (fun i mip -> let projs = Option.List.flatten (Structures.Structure.find_projections env (mind,i)) in (mip.mind_consnames, Array.of_list projs)) mib.mind_packets with Not_found (* find_projections *) -> Array.map (fun mip -> (mip.mind_consnames,[||])) mib.mind_packets in flatmapi (fun i (constructs, projs) -> print_arguments env (GlobRef.IndRef (mind,i)) @ flatmapi (fun j _ -> print_arguments env (GlobRef.ConstructRef ((mind,i),j+1))) constructs @ flatmapi (fun _ cst -> print_arguments env (GlobRef.ConstRef cst)) projs) mips let print_inductive env mind udecl = let mib = Environ.lookup_mind mind env in Printmod.pr_mutual_inductive_body env mind mib udecl let print_inductive_with_infos env mind udecl = let mib = Environ.lookup_mind mind env in let mipv = mib.mind_packets in Printmod.pr_mutual_inductive_body env mind mib udecl ++ with_line_skip (print_primitive_record mib.mind_finite mipv @ print_inductive_args env mind mib) let print_section_variable_with_infos env sigma id = print_named_decl env sigma true id ++ with_line_skip (print_name_infos env (GlobRef.VarRef id)) let print_instance sigma cb = if Declareops.constant_is_polymorphic cb then let univs = Declareops.constant_polymorphic_context cb in let inst = UVars.make_abstract_instance univs in pr_universe_instance_binder sigma inst Univ.UnivConstraints.empty else mt() let print_constant env ~with_values with_implicit cst udecl = let cb = Environ.lookup_constant cst env in let typ = cb.const_type in let univs = cb.const_universes in let udecl = Option.map (fun x -> GlobRef.ConstRef cst, x) udecl in let uctx = UState.of_names (Printer.universe_binders_with_opt_names (Declareops.constant_polymorphic_context cb) udecl) in let sigma = Evd.from_ctx uctx in let impargs = if with_implicit then select_stronger_impargs (implicits_of_global (ConstRef cst)) else [] in let impargs = List.map binding_kind_of_status impargs in let pptyp = pr_ltype_env env sigma ~impargs typ in let typonly = str " :" ++ spc() ++ pptyp in let sep_body_typ = fnl() ++ str " : " in let withbody c = str " =" ++ spc() ++ pr_lconstr_env ~inctx:true env sigma c ++ sep_body_typ ++ pptyp in let is_axiom, ppdata, priv = match cb.const_body with | Undef _ -> let ex p = CPrimitives.PTE p in let prims = CPrimitives.[ex PT_int63; ex PT_float64; ex PT_string; ex PT_array] in let is_prim (CPrimitives.PTE p) = let test = match p with | PT_int63 -> Environ.is_int63_type | PT_float64 -> Environ.is_float64_type | PT_string -> Environ.is_string_type | PT_array -> Environ.is_array_type in if test env cst then Some (CPrimitives.prim_type_to_string p) else None in let prim = List.find_map is_prim prims in let pp = match prim with | None -> typonly | Some prim -> str " =" ++ spc() ++ str "#" ++ str prim ++ sep_body_typ ++ pptyp in true, pp, None | Symbol _ -> true, typonly, None | Def c -> let pp = if Option.has_some with_values then withbody c else typonly in false, pp, None | OpaqueDef o -> begin match with_values with | None -> false, typonly, None | Some access -> let c, priv = Global.force_proof access o in let priv = match priv with | PrivateMonomorphic () -> None | PrivatePolymorphic priv -> Some priv in false, withbody c, priv end | Primitive prim -> let pp = str " =" ++ spc() ++ str "#" ++ str (CPrimitives.to_string prim) ++ sep_body_typ ++ pptyp in (* do we want to print with is_axiom = false? *) true, pp, None in let ppmain = print_basename cst ++ print_instance sigma cb ++ ppdata in let ppmain = if is_axiom then str"*** [ " ++ ppmain ++ str" ]" else ppmain in hov 0 (ppmain ++ Printer.pr_universes sigma univs ?priv) let print_constant_with_infos env access cst udecl = print_constant env ~with_values:(Some access) true cst udecl ++ with_line_skip (print_name_infos env (GlobRef.ConstRef cst)) let print_global_reference access env sigma gref udecl = let open GlobRef in match gref with | ConstRef cst -> (match Structures.PrimitiveProjections.find_opt cst with | Some p -> print_inductive_with_infos env (fst (Projection.Repr.inductive p)) udecl | None -> print_constant_with_infos env access cst udecl) | IndRef (mind,_) -> print_inductive_with_infos env mind udecl | ConstructRef ((mind,_),_) -> print_inductive_with_infos env mind udecl | VarRef id -> print_section_variable_with_infos env sigma id let glob_constr_of_abbreviation kn = let (vars,a) = Abbreviation.find_interp kn in (List.map fst vars, Notation_ops.glob_constr_of_notation_constr a) let print_abbreviation_body env kn (vars,c) = let qid = Nametab.shortest_qualid_of_abbreviation Id.Set.empty kn in hov 2 (hov 4 (str "Notation " ++ pr_qualid qid ++ prlist (fun id -> spc () ++ Id.print id) vars ++ spc () ++ str ":=") ++ spc () ++ Vernacstate.System.protect (fun () -> Abbreviation.toggle ~on:false ~use:ParsingAndPrinting kn; pr_glob_constr_env env (Evd.from_env env) c) ()) let print_abbreviation access env sigma kn = let (vars,c) = glob_constr_of_abbreviation kn in let pp = match DAst.get c with | GRef (gref,_udecl) -> (* TODO: don't drop universes? *) [print_global_reference access env sigma gref None] | _ -> [] in print_abbreviation_body env kn (vars,c) ++ with_line_skip pp (** Unused outside? *) let pr_prefix_name prefix = Id.print (basename prefix.obj_path) let print_library_node = function | Lib.OpenedSection (prefix, _) -> str " >>>>>>> Section " ++ pr_prefix_name prefix | Lib.OpenedModule (_,_,prefix,_) -> str " >>>>>>> Module " ++ pr_prefix_name prefix | Lib.CompilingLibrary { obj_path; _ } -> str " >>>>>>> Library " ++ pr_path obj_path (** Printing part of command [Check] *) let print_judgment env sigma {uj_val=trm;uj_type=typ} = print_typed_value_in_env env sigma (trm, typ) let print_safe_judgment {Safe_typing.jdg_env=senv; jdg_val=trm; jdg_type=typ} = let env = Safe_typing.env_of_safe_env senv in let sigma = Evd.from_env env in let trm = EConstr.of_constr trm in let typ = EConstr.of_constr typ in print_typed_value_in_env env sigma (trm, typ) (** Command [Print All] *) module DynHandle = Libobject.Dyn.Map(struct type 'a t = 'a -> Pp.t option end) let handle h (Libobject.Dyn.Dyn (tag, o)) = match DynHandle.find tag h with | f -> f o | exception Not_found -> None (* TODO: this kind of feature should not rely on the Libobject stack. There is no reason that an object in the stack corresponds to a user-facing declaration. It may have been so at the time this was written, but this needs to be done in a more principled way. *) let print_library_leaf env sigma ~with_values mp lobj = match lobj with | AtomicObject o -> let handler = DynHandle.add Declare.Internal.objVariable begin fun id -> (* Outside sections, VARIABLES still exist but only with universes constraints *) (try Some(print_named_decl env sigma false id) with Not_found -> None) end @@ DynHandle.add Declare.Internal.Constant.tag begin fun (id,_) -> let kn = Constant.make2 mp id in Some (print_constant env ~with_values false kn None) end @@ DynHandle.add DeclareInd.Internal.objInductive begin fun (id,_) -> let kn = MutInd.make2 mp id in Some (print_inductive env kn None) end @@ DynHandle.empty in handle handler o | ModuleObject (id,_) -> Some (Printmod.print_module ~with_body:(Option.has_some with_values) (MPdot (mp, id))) | ModuleTypeObject (id,_) -> Some (print_modtype (MPdot (mp, id))) | IncludeObject _ | KeepObject _ | EscapeObject _ | ExportObject _ -> None let decr = Option.map ((+) (-1)) let is_done = Option.equal Int.equal (Some 0) let print_leaves env sigma ~with_values mp n leaves = let rec prec n = function | [] -> n, [] | o :: rest -> if is_done n then n, [] else begin match print_library_leaf env sigma ~with_values mp o with | Some pp -> let n, prest = prec (decr n) rest in n, pp :: prest | None -> prec n rest end in let n, l = prec n leaves in n, v 0 (pr_sequence (fun x -> x) (List.rev l)) let print_context env sigma ~with_values = let rec prec n = function | [] -> mt() | (node, leaves) :: rest -> if is_done n then mt() else let mp = (Lib.node_prefix node).obj_mp in let n, pleaves = print_leaves env sigma ~with_values mp n leaves in if is_done n then pleaves else prec n rest ++ pleaves in prec let print_full_context access env sigma = print_context env sigma ~with_values:(Some access) None (Lib.contents ()) let print_full_context_typ env sigma = (* Command [Print All] *) print_context env sigma ~with_values:None None (Lib.contents ()) (** Command line [-output-context] *) module DynHandleF = Libobject.Dyn.Map(struct type 'a t = 'a -> Pp.t end) let handleF h (Libobject.Dyn.Dyn (tag, o)) = match DynHandleF.find tag h with | f -> f o | exception Not_found -> mt () (* TODO: see the comment for {!print_leaf_entry} *) let print_full_pure_atomic access env sigma mp lobj = let handler = DynHandleF.add Declare.Internal.Constant.tag begin fun (id,_) -> let kn = KerName.make mp id in let con = Global.constant_of_delta_kn kn in let cb = Global.lookup_constant con in let typ = cb.const_type in hov 0 ( match cb.const_body with | Undef _ -> str "Parameter " ++ print_basename con ++ str " :" ++ spc () ++ pr_ltype_env env sigma typ | OpaqueDef lc -> str "Theorem " ++ print_basename con ++ cut () ++ str " : " ++ pr_ltype_env env sigma typ ++ str "." ++ fnl () ++ str "Proof " ++ pr_lconstr_env env sigma (fst (Global.force_proof access lc)) | Def c -> str "Definition " ++ print_basename con ++ cut () ++ str " : " ++ pr_ltype_env env sigma typ ++ cut () ++ str " := " ++ pr_lconstr_env env sigma c | Primitive _ -> str "Primitive " ++ print_basename con ++ str " :" ++ spc () ++ pr_ltype_env env sigma typ | Symbol _ -> str "Symbol " ++ print_basename con ++ str " :" ++ spc () ++ pr_ltype_env env sigma typ) ++ str "." ++ fnl () ++ fnl () end @@ DynHandleF.add DeclareInd.Internal.objInductive begin fun (id,_) -> let kn = KerName.make mp id in let mind = Global.mind_of_delta_kn kn in let mib = Global.lookup_mind mind in Printmod.pr_mutual_inductive_body (Global.env()) mind mib None ++ fnl () ++ fnl () end @@ DynHandleF.empty in handleF handler lobj let print_full_pure_leaf access env sigma mp = function | AtomicObject lobj -> print_full_pure_atomic access env sigma mp lobj | ModuleObject (id, _) -> (* TODO: make it reparsable *) print_module (MPdot (mp, id)) ++ str "." ++ fnl () ++ fnl () | ModuleTypeObject (id, _) -> (* TODO: make it reparsable *) print_modtype (MPdot (mp, id)) ++ str "." ++ fnl () ++ fnl () | _ -> mt() let print_full_pure_context access env sigma = let rec prec = function | (node,leaves)::rest -> let mp = (Lib.node_prefix node).obj_mp in let pp = Pp.prlist (print_full_pure_leaf access env sigma mp) leaves in prec rest ++ pp | [] -> mt () in prec (Lib.contents ()) (** Command [Print Section] *) (* For printing an inductive definition with its constructors and elimination, assume that the declaration of constructors and eliminations follows the definition of the inductive type *) (* This is designed to print the contents of an opened section *) let read_sec_context qid = let dir = try Nametab.locate_section qid with Not_found -> user_err ?loc:qid.loc (str "Unknown section.") in let rec get_cxt in_cxt = function | (Lib.OpenedSection ({obj_path;_},_), _ as hd)::rest -> if eq_full_path dir obj_path then (hd::in_cxt) else get_cxt (hd::in_cxt) rest | [] -> [] | hd::rest -> get_cxt (hd::in_cxt) rest in let cxt = Lib.contents () in List.rev (get_cxt [] cxt) let print_sec_context access env sigma sec = print_context env sigma ~with_values:(Some access) None (read_sec_context sec) let print_sec_context_typ env sigma sec = print_context env sigma ~with_values:None None (read_sec_context sec) (** Command [Print] *) type 'a locatable_info = { locate : qualid -> 'a option; locate_all : qualid -> 'a list; shortest_qualid : 'a -> qualid; name : 'a -> Pp.t; print : 'a -> Pp.t; about : 'a -> Pp.t; } type logical_name = | Term of GlobRef.t | Dir of Nametab.GlobDirRef.t | Abbreviation of abbreviation | Module of ModPath.t | ModuleType of ModPath.t | Other : 'a * 'a locatable_info -> logical_name | Undefined of qualid type locatable = Locatable : 'a locatable_info -> locatable (** Generic table for objects that are accessible through a name. *) let locatable_map : locatable String.Map.t ref = ref String.Map.empty let register_locatable name f = locatable_map := String.Map.add name (Locatable f) !locatable_map exception ObjFound of logical_name let locate_any_name qid = try Term (Nametab.locate qid) with Not_found -> try Abbreviation (Nametab.locate_abbreviation qid) with Not_found -> try Dir (Nametab.locate_dir qid) with Not_found -> try Module (Nametab.locate_module qid) with Not_found -> try ModuleType (Nametab.locate_modtype qid) with Not_found -> let iter _ (Locatable info) = match info.locate qid with | None -> () | Some ans -> raise (ObjFound (Other (ans, info))) in try String.Map.iter iter !locatable_map; Undefined qid with ObjFound obj -> obj let canonical_info env ref = let cref = QGlobRef.canonize env ref in if GlobRef.UserOrd.equal ref cref then mt () else match Nametab.path_of_global cref with | path -> spc() ++ str "(syntactically equal to" ++ spc() ++ pr_path path ++ str ")" | exception Not_found -> spc() ++ str "(missing canonical, bug?)" let pr_loc_use_dp loc = match loc.Loc.fname with | Loc.ToplevelInput -> (* NB emacs mangles the message if it contains the capitalized "Toplevel input" of [Loc.pr] *) str "toplevel input, characters " ++ int loc.bp ++ str "-" ++ int loc.ep | InFile { dirpath = None } -> Loc.pr loc | InFile { dirpath = Some dp } -> let f = str "library " ++ str dp in (f ++ str", line " ++ int loc.line_nb ++ str", characters " ++ int (loc.bp-loc.bol_pos) ++ str"-" ++ int (loc.ep-loc.bol_pos)) let loc_info gr = match Nametab.cci_src_loc gr with | None -> mt() | Some loc -> cut() ++ hov 0 (str "Declared in" ++ spc() ++ pr_loc_use_dp loc) let pr_dir dir = let s,mp = let open Nametab in let open GlobDirRef in match dir with | DirOpenModule mp -> "Open Module", ModPath.print mp | DirOpenModtype mp -> "Open Module Type", ModPath.print mp | DirOpenSection dir -> "Open Section", pr_path dir in str s ++ spc () ++ mp let pr_located_qualid env = function | Term ref -> let ref_str = let open GlobRef in match ref with ConstRef _ -> "Constant" | IndRef _ -> "Inductive" | ConstructRef _ -> "Constructor" | VarRef _ -> "Variable" in let extra = canonical_info env ref in v 0 (hov 0 (str ref_str ++ spc () ++ pr_path (Nametab.path_of_global ref) ++ extra)) | Abbreviation kn -> str "Notation" ++ spc () ++ pr_path (Nametab.path_of_abbreviation kn) | Dir dir -> pr_dir dir | Module mp -> str "Module" ++ spc () ++ pr_path (Nametab.path_of_module mp) | ModuleType mp -> str "Module Type" ++ spc () ++ pr_path (Nametab.path_of_modtype mp) | Other (obj, info) -> info.name obj | Undefined qid -> pr_qualid qid ++ spc () ++ str "not a defined object." let maybe_error_reject_univ_decl na udecl = let open GlobRef in match na, udecl with | _, None | Term (ConstRef _ | IndRef _ | ConstructRef _), Some _ -> () | (Term (VarRef _) | Abbreviation _ | Dir _ | Module _ | ModuleType _ | Other _ | Undefined _), Some udecl -> (* TODO Print na somehow *) user_err (str "This object does not support universe names.") let print_any_name access env sigma na udecl = maybe_error_reject_univ_decl na udecl; match na with | Term gref -> print_global_reference access env sigma gref udecl | Abbreviation kn -> print_abbreviation access env sigma kn | Module mp -> print_module mp | Dir dir -> pr_dir dir | ModuleType mp -> print_modtype mp | Other (obj, info) -> info.print obj | Undefined qid -> try (* A goal variable which is not a section variable *) let dir,str = repr_qualid qid in if not (DirPath.is_empty dir) then raise Not_found; print_named_decl env sigma true str with Not_found -> user_err ?loc:qid.loc (pr_qualid qid ++ spc () ++ str "not a defined object.") let print_notation_interpretation env sigma (entry,ntn) df sc c = let filter = Notation.{ notation_entry_pattern = [entry]; interp_rule_key_pattern = Some (Inl ntn); use_pattern = OnlyPrinting; scope_pattern = sc; interpretation_pattern = Some c; } in Vernacstate.System.protect (fun () -> Notation.toggle_notations ~on:false ~all:false ~verbose:false (pr_glob_constr_env env sigma) filter; hov 0 (str "Notation" ++ spc () ++ Notation_ops.pr_notation_info (pr_glob_constr_env env sigma) df (snd c))) () let print_name access env sigma na udecl = match na with | {loc; v=Constrexpr.ByNotation (ntn,sc)} -> let ntn, df, sc, c, ref = Notation.interp_notation_as_global_reference_expanded ?loc ~head:false (fun _ -> true) ntn sc in print_notation_interpretation env sigma ntn df (Some sc) c ++ fnl () ++ fnl () ++ print_any_name access env sigma (Term ref) udecl | {loc; v=Constrexpr.AN ref} -> print_any_name access env sigma (locate_any_name ref) udecl (** Command [Print Notation] *) let print_notation_grammar env sigma ntn = let ng = List.hd (Notgram_ops.grammar_of_notation ntn) in let assoc = ng.Notation_gram.notgram_assoc in let prdf () = Pp.str "no associativity" in Pp.(pr_opt_no_spc_default prdf Gramlib.Gramext.pr_assoc assoc) exception PrintNotationNotFound of Constrexpr.notation_entry * string let () = CErrors.register_handler @@ function | PrintNotationNotFound (entry, ntn_str) -> let entry_string = match entry with | Constrexpr.InConstrEntry -> str "." | Constrexpr.InCustomEntry e -> str " in " ++ Nametab.CustomEntries.pr e ++ str " entry." in Some Pp.(str "\"" ++ str ntn_str ++ str "\"" ++ spc () ++ str "cannot be interpreted as a known notation" ++ entry_string ++ spc () ++ strbrk "Make sure that symbols are surrounded by spaces and that holes are explicitly denoted by \"_\".") | _ -> None let error_print_notation_not_found e s = raise @@ PrintNotationNotFound (e, s) let print_notation env sigma entry raw_ntn = (* make sure entry exists *) let entry = Metasyntax.intern_notation_entry entry in (* convert notation string to key. eg. "x + y" to "_ + _" *) let interp_ntn = Notation.interpret_notation_string raw_ntn in let ntn = (entry, interp_ntn) in try let lvl = Notation.level_of_notation ntn in let args = Notgram_ops.non_terminals_of_notation ntn in let pplvl = Metasyntax.pr_level lvl args in Pp.(str "Notation \"" ++ str interp_ntn ++ str "\"" ++ spc () ++ pplvl ++ pr_comma () ++ print_notation_grammar env sigma ntn ++ str ".") with Not_found -> error_print_notation_not_found entry raw_ntn (** Command [About] *) let print_about_global_reference ?loc env ref udecl = pr_infos_list (print_ref env false ref udecl :: blankline :: print_polymorphism env ref @ print_squash env ref udecl @ print_name_infos env ref @ print_reduction_behaviour ref @ print_opacity env ref @ print_bidi_hints env ref @ [hov 0 (str "Expands to: " ++ pr_located_qualid env (Term ref)) ++ loc_info (TrueGlobal ref)]) let print_about_abbreviation env sigma kn = let (vars,c) = glob_constr_of_abbreviation kn in let pp = match DAst.get c with | GRef (gref,_udecl) -> (* TODO: don't drop universes? *) [print_about_global_reference env gref None] | _ -> [] in print_abbreviation_body env kn (vars,c) ++ fnl () ++ hov 0 (str "Expands to: " ++ pr_located_qualid env (Abbreviation kn)) ++ loc_info (Abbrev kn) ++ with_line_skip pp let print_about_any ?loc env sigma k udecl = maybe_error_reject_univ_decl k udecl; match k with | Term ref -> Dumpglob.add_glob ?loc ref; print_about_global_reference env ref udecl | Abbreviation kn -> v 0 (print_about_abbreviation env sigma kn) | Dir _ | Module _ | ModuleType _ | Undefined _ -> hov 0 (pr_located_qualid env k) | Other (obj, info) -> hov 0 (info.about obj) let print_about env sigma na udecl = match na with | {loc;v=Constrexpr.ByNotation (ntn,sc)} -> let ntn, df, sc, c, ref = Notation.interp_notation_as_global_reference_expanded ?loc ~head:false (fun _ -> true) ntn sc in print_notation_interpretation env sigma ntn df (Some sc) c ++ fnl () ++ fnl () ++ print_about_any ?loc env sigma (Term ref) udecl | {loc;v=Constrexpr.AN ref} -> print_about_any ?loc env sigma (locate_any_name ref) udecl (* Command [Inspect], for debug *) let inspect env sigma depth = print_context env sigma ~with_values:None (Some depth) (Lib.contents ()) (*************************************************************************) (* Pretty-printing functions coming from classops.ml *) (** Command [Print Classes] *) open Coercionops let print_coercion_value v = Printer.pr_global v.coe_value let print_path ((i,j),p) = hov 2 ( str"[" ++ hov 0 (prlist_with_sep pr_semicolon print_coercion_value p) ++ str"] : ") ++ pr_class i ++ str" >-> " ++ pr_class j ++ str (if path_is_reversible p then " (reversible)" else "") let _ = Coercionops.install_path_printer print_path let print_graph () = prlist_with_sep fnl print_path (inheritance_graph()) (** Command [Print Classes] *) let print_classes () = pr_sequence pr_class (classes()) (** Command [Print Coercions] *) let print_coercions () = pr_sequence print_coercion_value (coercions()) (** Command [Print Coercion Paths] *) let print_coercion_paths cls clt = let p = try lookup_path_between_class (cls, clt) with Not_found -> user_err (str"No path between " ++ pr_class cls ++ str" and " ++ pr_class clt ++ str ".") in print_path ((cls, clt), p) (** Command [Print Canonical Projections] *) let print_canonical_projections env sigma grefs = let open Structures in let match_proj_gref { CSTable.projection; value; solution } gr = QGlobRef.equal env projection gr || begin match value with | ValuePattern.Const_cs y -> QGlobRef.equal env y gr | _ -> false end || QGlobRef.equal env solution gr in let projs = List.filter (fun p -> List.for_all (match_proj_gref p) grefs) (CSTable.entries ()) in prlist_with_sep fnl (fun { CSTable.projection; value; solution } -> ValuePattern.print value ++ str " <- " ++ pr_global projection ++ str " ( " ++ pr_global solution ++ str " )") projs (***********************************************) (** Pretty-printing functions for type classes *) (** Command [Print Typeclasses] *) open Typeclasses let pr_typeclass env t = print_ref env false t.cl_impl None let print_typeclasses () = let env = Global.env () in prlist_with_sep fnl (pr_typeclass env) (typeclasses ()) (** Command [Print Instances] *) let pr_instance env i = (* print_constant_with_infos i.is_impl *) (* lighter *) print_ref env false (instance_impl i) None ++ begin match hint_priority i with | None -> mt () | Some i -> spc () ++ str "|" ++ spc () ++ int i end let print_all_instances () = let env = Global.env () in let inst = all_instances () in prlist_with_sep fnl (pr_instance env) inst let print_instances r = let env = Global.env () in let inst = instances_exn env (Evd.from_env env) r in prlist_with_sep fnl (pr_instance env) inst (*********************) (* Commands [Locate] *) let canonize_ref = let open GlobRef in function | ConstRef c -> let kn = Constant.canonical c in if KerName.equal (Constant.user c) kn then None else Some (ConstRef (Constant.make1 kn)) | IndRef (ind,i) -> let kn = MutInd.canonical ind in if KerName.equal (MutInd.user ind) kn then None else Some (IndRef (MutInd.make1 kn, i)) | ConstructRef ((ind,i),j) -> let kn = MutInd.canonical ind in if KerName.equal (MutInd.user ind) kn then None else Some (ConstructRef ((MutInd.make1 kn, i),j)) | VarRef _ -> None let display_alias = function | Term r -> begin match canonize_ref r with | None -> mt () | Some r' -> let q' = Nametab.shortest_qualid_of_global Id.Set.empty r' in spc () ++ str "(alias of " ++ pr_qualid q' ++ str ")" end | _ -> mt () let locate_term qid = let expand = function | TrueGlobal ref -> Term ref, Nametab.shortest_qualid_of_global Id.Set.empty ref | Abbrev kn -> Abbreviation kn, Nametab.shortest_qualid_of_abbreviation Id.Set.empty kn in List.map expand (Nametab.locate_extended_all qid) let locate_module qid = let all = Nametab.locate_extended_all_module qid in let map mp = Module mp, Nametab.shortest_qualid_of_module mp in let mods = List.map map all in (* Don't forget the opened modules: they are not part of the same name tab. *) let all = Nametab.locate_extended_all_dir qid in let map dir = let open Nametab.GlobDirRef in match dir with | DirOpenModule _ -> Some (Dir dir, qid) | _ -> None in mods @ List.map_filter map all let locate_modtype qid = let all = Nametab.locate_extended_all_modtype qid in let map mp = ModuleType mp, Nametab.shortest_qualid_of_modtype mp in let modtypes = List.map map all in (* Don't forget the opened module types: they are not part of the same name tab. *) let all = Nametab.locate_extended_all_dir qid in let map dir = let open Nametab.GlobDirRef in match dir with | DirOpenModtype _ -> Some (Dir dir, qid) | _ -> None in modtypes @ List.map_filter map all let locate_other s qid = let Locatable info = String.Map.find s !locatable_map in let ans = info.locate_all qid in let map obj = (Other (obj, info), info.shortest_qualid obj) in List.map map ans type locatable_kind = | LocTerm | LocModule | LocOther of string | LocAny let print_located_qualid env name flags qid = let located = match flags with | LocTerm -> locate_term qid | LocModule -> locate_modtype qid @ locate_module qid | LocOther s -> locate_other s qid | LocAny -> locate_term qid @ locate_modtype qid @ locate_module qid @ String.Map.fold (fun s _ accu -> locate_other s qid @ accu) !locatable_map [] in match located with | [] -> let (dir,id) = repr_qualid qid in if DirPath.is_empty dir then str "No " ++ str name ++ str " of basename" ++ spc () ++ Id.print id else str "No " ++ str name ++ str " of suffix" ++ spc () ++ pr_qualid qid | l -> prlist_with_sep fnl (fun (o,oqid) -> hov 2 (pr_located_qualid env o ++ (if not (qualid_eq oqid qid) then spc() ++ str "(shorter name to refer to it in current context is " ++ pr_qualid oqid ++ str")" else mt ()) ++ display_alias o)) l let print_located_term env ref = print_located_qualid env "term" LocTerm ref let print_located_other env s ref = print_located_qualid env s (LocOther s) ref let print_located_module env ref = print_located_qualid env "module" LocModule ref let print_located_qualid env ref = print_located_qualid env "object" LocAny ref rocq-9.2.0/vernac/prettyp.mli000066400000000000000000000076531516144147600162020ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Termops.names_context (* unused? *) val print_closed_sections : bool ref val print_context (* unused? *) : env -> Evd.evar_map -> with_values:Global.indirect_accessor option -> int option -> 'a Lib.library_segment -> Pp.t val print_library_leaf : env -> Evd.evar_map -> with_values:Global.indirect_accessor option -> ModPath.t -> Libobject.t -> Pp.t option val print_library_node : Summary.Interp.frozen Lib.node -> Pp.t (* unused? *) val print_full_context : Global.indirect_accessor -> env -> Evd.evar_map -> Pp.t val print_full_context_typ : env -> Evd.evar_map -> Pp.t val print_full_pure_context : Global.indirect_accessor -> env -> Evd.evar_map -> Pp.t val print_sec_context : Global.indirect_accessor -> env -> Evd.evar_map -> qualid -> Pp.t val print_sec_context_typ : env -> Evd.evar_map -> qualid -> Pp.t val print_judgment : env -> Evd.evar_map -> EConstr.unsafe_judgment -> Pp.t val print_safe_judgment : Safe_typing.judgment -> Pp.t val print_name : Global.indirect_accessor -> env -> Evd.evar_map -> qualid Constrexpr.or_by_notation -> UnivNames.full_name_list option -> Pp.t val print_notation : env -> Evd.evar_map -> qualid Constrexpr.notation_entry_gen -> string -> Pp.t val print_abbreviation : Global.indirect_accessor -> env -> Evd.evar_map -> KerName.t -> Pp.t val print_about : env -> Evd.evar_map -> qualid Constrexpr.or_by_notation -> UnivNames.full_name_list option -> Pp.t val print_impargs : env -> GlobRef.t -> Pp.t (** Pretty-printing functions for classes and coercions *) val print_graph : unit -> Pp.t val print_classes : unit -> Pp.t val print_coercions : unit -> Pp.t val print_coercion_paths : Coercionops.cl_typ -> Coercionops.cl_typ -> Pp.t val print_canonical_projections : env -> Evd.evar_map -> GlobRef.t list -> Pp.t (** Pretty-printing functions for type classes and instances *) val print_typeclasses : unit -> Pp.t val print_instances : GlobRef.t -> Pp.t val print_all_instances : unit -> Pp.t val inspect : env -> Evd.evar_map -> int -> Pp.t (** {5 Locate} *) type 'a locatable_info = { locate : qualid -> 'a option; (** Locate the most precise object with the provided name if any. *) locate_all : qualid -> 'a list; (** Locate all objects whose name is a suffix of the provided name *) shortest_qualid : 'a -> qualid; (** Return the shortest name in the current context *) name : 'a -> Pp.t; (** Data as printed by the Locate command *) print : 'a -> Pp.t; (** Data as printed by the Print command *) about : 'a -> Pp.t; (** Data as printed by the About command *) } (** Generic data structure representing locatable objects. *) val register_locatable : string -> 'a locatable_info -> unit (** Define a new type of locatable objects that can be reached via the corresponding generic vernacular commands. The string should be a unique name describing the kind of objects considered and that is added as a grammar command prefix for vernacular commands Locate. *) val print_located_qualid : env -> qualid -> Pp.t val print_located_term : env -> qualid -> Pp.t val print_located_module : env -> qualid -> Pp.t val print_located_other : env -> string -> qualid -> Pp.t rocq-9.2.0/vernac/printmod.ml000066400000000000000000000414741516144147600161550ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* !short) ; optwrite = ((:=) short) } (** Each time we have to print a non-globally visible structure, we place its elements in a fake fresh namespace. *) let mk_fake_top = let r = ref 0 in fun () -> incr r; Id.of_string ("FAKETOP"^(string_of_int !r)) let def s = tag_definition (str s) let keyword s = tag_keyword (str s) let get_new_id avoid id = Namegen.next_ident_away_from id (fun id -> Id.Set.mem id avoid || let dir = Libnames.make_path DirPath.empty id in Nametab.exists_module dir || Nametab.exists_dir dir) (** Inductive declarations *) open Reduction let print_params env sigma params = if List.is_empty params then mt () else Printer.pr_rel_context env sigma params ++ brk(1,2) let print_constructors envpar sigma names types = let pc = prlist_with_sep (fun () -> brk(1,0) ++ str "| ") (fun (id,c) -> Id.print id ++ str " : " ++ Printer.pr_lconstr_env envpar sigma c) (Array.to_list (Array.map2 (fun n t -> (n,t)) names types)) in hv 0 (str " " ++ pc) let build_ind_type mip = Inductive.type_of_inductive mip let get_fields = let rec prodec_rec l subst c = match kind c with | Prod (na,t,c) -> let id = match na.binder_name with Name id -> id | Anonymous -> Id.of_string "_" in prodec_rec ((id,true,Vars.substl subst t)::l) (mkVar id::subst) c | LetIn (na,b,_,c) -> let id = match na.binder_name with Name id -> id | Anonymous -> Id.of_string "_" in prodec_rec ((id,false,Vars.substl subst b)::l) (mkVar id::subst) c | _ -> List.rev l in prodec_rec [] [] let print_fields envpar sigma cstrtypes = let fields = get_fields cstrtypes.(0) in hv 2 (str "{ " ++ prlist_with_sep (fun () -> str ";" ++ brk(2,0)) (fun (id,b,c) -> Id.print id ++ str (if b then " : " else " := ") ++ Printer.pr_lconstr_env envpar sigma c) fields) ++ str" }" let is_canonical_as env ind indname id = (* See record.ml *) let canonical_id = Record.canonical_inhabitant_id ~isclass:(Typeclasses.is_class env (IndRef ind)) indname in Id.equal id canonical_id let print_as env ind indname = function | Anonymous -> mt () (* TODO: get the "as" name also for non-primitive records *) | Name id -> if is_canonical_as env ind indname id then mt () else str " as " ++ Id.print id let print_one_inductive env sigma mib ((_,i) as ind) = let u = UVars.make_abstract_instance (Declareops.inductive_polymorphic_context mib) in let mip = mib.mind_packets.(i) in let paramdecls = Inductive.inductive_paramdecls (mib,u) in let env_params, params = Namegen.make_all_rel_context_name_different env (Evd.from_env env) (EConstr.of_rel_context paramdecls) in let params = EConstr.Unsafe.to_rel_context params in let nparamdecls = Context.Rel.length params in let args = Context.Rel.instance_list mkRel 0 params in let arity = hnf_prod_applist_decls env nparamdecls (build_ind_type ((mib,mip),u)) args in let cstrtypes = Inductive.type_of_constructors (ind,u) (mib,mip) in let cstrtypes = Array.map (fun c -> snd (Term.decompose_prod_n_decls nparamdecls c)) cstrtypes in let isrecord = match mip.mind_record with | NotRecord -> None | FakeRecord -> Some Anonymous | PrimRecord { id; _ } -> Some (Name id) in if Option.has_some isrecord then assert (Array.length cstrtypes = 1); let inst = if Declareops.inductive_is_polymorphic mib then Printer.pr_universe_instance_binder sigma u Univ.UnivConstraints.empty else mt () in hov 0 ( Id.print mip.mind_typename ++ inst ++ brk(1,4) ++ print_params env sigma params ++ str ": " ++ Printer.pr_lconstr_env env_params sigma arity ++ str " :=" ++ if Option.has_some isrecord then str " " ++ Id.print mip.mind_consnames.(0) else mt()) ++ match isrecord with | None -> brk(0,2) ++ print_constructors env_params sigma mip.mind_consnames cstrtypes | Some as_clause -> brk(1,2) ++ print_fields env_params sigma cstrtypes ++ print_as env ind mip.mind_typename as_clause let pr_mutual_inductive_body env mind mib udecl = let inds = List.init (Array.length mib.mind_packets) (fun x -> (mind, x)) in let keyword = let open Declarations in match mib.mind_finite with | Finite -> "Inductive" | CoFinite -> "CoInductive" | BiFinite -> match mib.mind_packets.(0).mind_record with | NotRecord -> "Variant" | FakeRecord -> "Record" | PrimRecord l -> "Record" in let udecl = Option.map (fun x -> GlobRef.IndRef (mind,0), x) udecl in let bl = Printer.universe_binders_with_opt_names (Declareops.inductive_polymorphic_context mib) udecl in let sigma = Evd.from_ctx (UState.of_names bl) in hov 0 (def keyword ++ spc () ++ prlist_with_sep (fun () -> fnl () ++ str" with ") (print_one_inductive env sigma mib) inds ++ str "." ++ Printer.pr_universes sigma ?variance:mib.mind_variance mib.mind_universes) (** Modpaths *) let rec print_local_modpath locals = function | MPbound mbid -> Id.print (Util.List.assoc_f MBId.equal mbid locals) | MPdot(mp,l) -> print_local_modpath locals mp ++ str "." ++ Id.print l | MPfile _ -> raise Not_found let print_modpath locals mp = try (* must be with let because streams are lazy! *) let qid = Nametab.shortest_qualid_of_module mp in pr_qualid qid with | Not_found -> print_local_modpath locals mp let print_kn locals kn = try let qid = Nametab.shortest_qualid_of_modtype kn in pr_qualid qid with Not_found -> try print_local_modpath locals kn with Not_found -> print_modpath locals kn let nametab_register_dir obj_mp = let id = mk_fake_top () in let obj_dir = Libnames.make_path DirPath.empty id in Nametab.(push_module (Until 1) obj_dir obj_mp) (** Nota: the [global_reference] we register in the nametab below might differ from internal ones, since we cannot recreate here the canonical part of constant and inductive names, but only the user names. This works nonetheless since we search now [Nametab.the_globrevtab] modulo user name. *) let nametab_register_body mp dir (l,body) = let push id ref = Nametab.push (Nametab.Until (1+List.length (DirPath.repr dir))) (make_path dir id) ref in match body with | SFBmodule _ -> () (* TODO *) | SFBmodtype _ -> () (* TODO *) | SFBrules _ -> () (* TODO? *) | SFBconst _ -> push l (GlobRef.ConstRef (Constant.make2 mp l)) | SFBmind mib -> let mind = MutInd.make2 mp l in Array.iteri (fun i mip -> push mip.mind_typename (GlobRef.IndRef (mind,i)); Array.iteri (fun j id -> push id (GlobRef.ConstructRef ((mind,i),j+1))) mip.mind_consnames) mib.mind_packets (* TODO only import printing-relevant objects (or find a way to print without importing) *) let import_module = Declaremods.Interp.import_module Libobject.unfiltered let process_module_binding = Declaremods.process_module_binding let nametab_register_module_body mp struc = (* If [mp] is a globally visible module, we simply import it *) try import_module ~export:Lib.Import mp with Not_found -> (* Otherwise we try to emulate an import by playing with nametab *) nametab_register_dir mp; List.iter (nametab_register_body mp DirPath.empty) struc let get_typ_expr_alg mtb = match mod_type_alg mtb with | Some (MENoFunctor me) -> me | _ -> raise Not_found let nametab_register_modparam used mbid mtb = let id = MBId.to_id mbid in match mod_type mtb with | MoreFunctor _ -> id (* functorial param : nothing to register *) | NoFunctor struc -> (* We first try to use the algebraic type expression if any, via a Declaremods function that converts back to module entries *) try let () = process_module_binding mbid (get_typ_expr_alg mtb) in id with e when CErrors.noncritical e -> (* Otherwise, we try to play with the nametab ourselves *) let mp = MPbound mbid in let id = get_new_id used id in let dir = DirPath.make [id] in nametab_register_dir mp; List.iter (nametab_register_body mp dir) struc; id let print_body is_impl extent env mp (l,body) = let name = Id.print l in hov 2 (match body with | SFBmodule _ -> keyword "Module" ++ spc () ++ name | SFBmodtype _ -> keyword "Module Type" ++ spc () ++ name | SFBrules _ -> keyword "Rewrite Rule" ++ spc () ++ name (* TODO: correct? *) | SFBconst cb -> let ctx = Declareops.constant_polymorphic_context cb in (match cb.const_body with | Def _ -> def "Definition" ++ spc () | OpaqueDef _ when is_impl -> def "Theorem" ++ spc () | _ -> def "Parameter" ++ spc ()) ++ name ++ (match extent with | OnlyNames -> mt () | WithContents -> let bl = Printer.universe_binders_with_opt_names ctx None in let sigma = Evd.from_ctx (UState.of_names bl) in str " :" ++ spc () ++ hov 0 (Printer.pr_ltype_env env sigma cb.const_type) ++ (match cb.const_body with | Def l when is_impl -> spc () ++ hov 2 (str ":= " ++ Printer.pr_lconstr_env env sigma l) | _ -> mt ()) ++ str "." ++ Printer.pr_abstract_universe_ctx sigma ctx) | SFBmind mib -> match extent with | WithContents -> pr_mutual_inductive_body env (MutInd.make2 mp l) mib None | OnlyNames -> let keyword = let open Declarations in match mib.mind_finite with | Finite -> def "Inductive" | BiFinite -> def "Variant" | CoFinite -> def "CoInductive" in keyword ++ spc () ++ name) let print_struct is_impl extent env mp struc = prlist_with_sep spc (print_body is_impl extent env mp) struc let print_structure is_type extent env mp locals struc = (* XXX: when printing signatures we overwrite already defined modules *) let env' = Environ.Internal.overwrite_structure mp struc (Mod_subst.empty_delta_resolver mp) env in nametab_register_module_body mp struc; let kwd = if is_type then "Sig" else "Struct" in hv 2 (keyword kwd ++ spc () ++ print_struct false extent env' mp struc ++ brk (1,-2) ++ keyword "End") let rec flatten_app mexpr l = match mexpr with | MEapply (mexpr, arg) -> flatten_app mexpr (arg::l) | MEident mp -> mp::l | MEwith _ -> assert false let rec print_typ_expr extent env mp locals mty = match mty with | MEident kn -> print_kn locals kn | MEapply _ -> let lapp = flatten_app mty [] in let fapp = List.hd lapp in let mapp = List.tl lapp in hov 3 (str"(" ++ (print_kn locals fapp) ++ spc () ++ prlist_with_sep spc (print_modpath locals) mapp ++ str")") | MEwith(me,WithDef(idl,(c, _)))-> let s = String.concat "." (List.map Id.to_string idl) in let body = match extent with | WithContents -> let sigma = Evd.from_env env in spc() ++ str ":=" ++ spc() ++ Printer.pr_lconstr_env env sigma c | OnlyNames -> mt() in hov 2 (print_typ_expr extent env mp locals me ++ spc() ++ str "with" ++ spc() ++ def "Definition"++ spc() ++ str s ++ body) | MEwith(me,WithMod(idl,mp'))-> let s = String.concat "." (List.map Id.to_string idl) in let body = match extent with | WithContents -> spc() ++ str ":="++ spc() ++ print_modpath locals mp' | OnlyNames -> mt () in hov 2 (print_typ_expr extent env mp locals me ++ spc() ++ str "with" ++ spc() ++ keyword "Module"++ spc() ++ str s ++ body) let print_mod_expr env mp locals = function | MEident mp -> print_modpath locals mp | MEapply _ as me -> let lapp = flatten_app me [] in hov 3 (str"(" ++ prlist_with_sep spc (print_modpath locals) lapp ++ str")") | MEwith _ -> assert false (* No 'with' syntax for modules *) let rec print_functor fty fatom is_type extent env mp used locals = function | NoFunctor me -> fatom is_type extent env mp locals me | MoreFunctor (mbid,mtb1,me2) -> let id = nametab_register_modparam !used mbid mtb1 in let () = used := Id.Set.add id !used in let mp1 = MPbound mbid in let pr_mtb1 = fty extent env mp1 used locals mtb1 in let env' = Modops.add_module_parameter mbid mtb1 env in let avoid = List.fold_left (fun accu (_, id) -> Id.Set.add id accu) Id.Set.empty locals in let locals' = (mbid, get_new_id avoid (MBId.to_id mbid))::locals in let kwd = if is_type then "Funsig" else "Functor" in hov 2 (keyword kwd ++ spc () ++ str "(" ++ Id.print id ++ str ":" ++ pr_mtb1 ++ str ")" ++ spc() ++ print_functor fty fatom is_type extent env' mp used locals' me2) let rec print_expression x = print_functor print_modtype (function true -> print_typ_expr | false -> fun _ -> print_mod_expr) x and print_signature x = print_functor print_modtype print_structure x and print_modtype extent env mp used locals mtb = match mod_type_alg mtb with | Some me -> let me = Modops.annotate_module_expression me (mod_type mtb) in print_expression true extent env mp used locals me | None -> print_signature true extent env mp used locals (mod_type mtb) (** Since we might play with nametab above, we should reset to prior state after the printing *) let print_expression' is_type extent env mp me = Vernacstate.System.protect (fun e -> print_expression is_type extent env mp (ref Id.Set.empty) [] e) me let print_signature' is_type extent env mp me = Vernacstate.System.protect (fun e -> print_signature is_type extent env mp (ref Id.Set.empty) [] e) me let unsafe_print_module extent env mp with_body mb = let name = print_modpath [] mp in let pr_equals = spc () ++ str ":= " in let body = match with_body, Mod_declarations.mod_expr mb with | false, _ | true, Abstract -> mt() | _, Algebraic me -> let me = Modops.annotate_module_expression me (mod_type mb) in pr_equals ++ print_expression' false extent env mp me | _, Struct (_, sign) -> let sign = Modops.annotate_struct_body sign (mod_type mb) in pr_equals ++ print_signature' false extent env mp sign | _, FullStruct -> pr_equals ++ print_signature' false extent env mp (mod_type mb) in let modtype = match mod_expr mb, mod_type_alg mb with | FullStruct, _ -> mt () | _, Some ty -> let ty = Modops.annotate_module_expression ty (mod_type mb) in brk (1,1) ++ str": " ++ print_expression' true extent env mp ty | _, _ -> brk (1,1) ++ str": " ++ print_signature' true extent env mp (mod_type mb) in hv 0 (keyword "Module" ++ spc () ++ name ++ modtype ++ body) exception ShortPrinting let print_module ~with_body mp = let me = Global.lookup_module mp in try if !short then raise ShortPrinting; unsafe_print_module WithContents (Global.env ()) mp with_body me with e when CErrors.noncritical e -> unsafe_print_module OnlyNames (Global.env ()) mp with_body me let print_modtype kn = let mtb = Global.lookup_modtype kn in let name = print_kn [] kn in hv 1 (keyword "Module Type" ++ spc () ++ name ++ str " =" ++ spc () ++ try if !short then raise ShortPrinting; print_signature' true WithContents (Global.env ()) kn (mod_type mtb) with e when CErrors.noncritical e -> print_signature' true OnlyNames (Global.env ()) kn (mod_type mtb)) rocq-9.2.0/vernac/printmod.mli000066400000000000000000000016311516144147600163150ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* MutInd.t -> Declarations.mutual_inductive_body -> UnivNames.full_name_list option -> Pp.t val print_module : with_body:bool -> ModPath.t -> Pp.t val print_modtype : ModPath.t -> Pp.t rocq-9.2.0/vernac/proof_using.ml000066400000000000000000000223151516144147600166440ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let vb = match decl with | LocalAssum _ -> Id.Set.empty | LocalDef (_,b,_) -> Termops.global_vars_set env sigma b in let vty = Termops.global_vars_set env sigma (NamedDecl.get_type decl) in let vbty = Id.Set.union vb vty in if Id.Set.exists (fun v -> Id.Set.mem v s) vbty then Id.Set.add (NamedDecl.get_id decl) (Id.Set.union s vbty) else s) s (EConstr.named_context env) in if Id.Set.equal s s' then s else close_fwd env sigma s' let set_of_type env sigma fixnames ty = List.fold_right Id.Set.remove fixnames (List.fold_left (fun acc ty -> Id.Set.union (Termops.global_vars_set env sigma ty) acc) Id.Set.empty ty) let full_set fixnames env = let add id ids = if List.mem_f Id.equal id fixnames then ids else Id.Set.add id ids in List.fold_right add (List.map NamedDecl.get_id (named_context env)) Id.Set.empty let warn_all_collection_precedence = CWarnings.create ~name:"all-collection-precedence" ~category:Deprecation.Version.v8_15 Pp.(fun () -> str "Variable " ++ Id.print all_collection_id ++ str " is shadowed by Collection named " ++ Id.print all_collection_id ++ str " containing all variables.") let warn_collection_precedence = CWarnings.create ~name:"collection-precedence" ~category:Deprecation.Version.v8_15 Pp.(fun id -> Id.print id ++ str " is both name of a Collection and Variable, Collection " ++ Id.print id ++ str " takes precedence over Variable.") let warn_redefine_collection = CWarnings.create ~name:"collection-redefinition" ~category:Deprecation.Version.v8_15 Pp.(fun id -> str "New Collection definition of " ++ Id.print id ++ str " shadows the previous one.") let warn_variable_shadowing = CWarnings.create ~name:"variable-shadowing" ~category:Deprecation.Version.v8_15 Pp.(fun id -> Id.print id ++ str " was already a defined Variable, the name " ++ Id.print id ++ str " will refer to Collection when executing \"Proof using\" command.") let err_redefine_all_collection () = CErrors.user_err Pp.(str "\"" ++ Id.print all_collection_id ++ str "\" is a predefined collection containing all variables. It can't be redefined.") let process_expr env sigma fixnames e v_ty = let variable_exists id = try ignore (lookup_named id env); true with | Not_found -> false in let rec aux = function | SsEmpty -> Id.Set.empty | SsType -> v_ty | SsSingl { CAst.v = id } -> set_of_id id | SsUnion(e1,e2) -> Id.Set.union (aux e1) (aux e2) | SsSubstr(e1,e2) -> Id.Set.diff (aux e1) (aux e2) | SsCompl e -> Id.Set.diff (full_set fixnames env) (aux e) | SsFwdClose e -> close_fwd env sigma (aux e) and set_of_id id = if Id.equal id all_collection_id then begin if variable_exists all_collection_id then warn_all_collection_precedence (); full_set fixnames env end else if is_known_name id then begin if variable_exists id then warn_collection_precedence id; aux (CList.assoc_f Id.equal id !known_names) end else if List.exists (Id.equal id) fixnames then CErrors.user_err Pp.(str "Invalid recursive variable: " ++ Id.print id ++ str ".") else if not (List.exists (NamedDecl.get_id %> Id.equal id) (named_context env)) then CErrors.user_err Pp.(str "Unknown variable: " ++ Id.print id ++ str ".") else Id.Set.singleton id in aux e let process_expr env sigma fixnames e ty = let v_ty = set_of_type env sigma fixnames ty in let s = Id.Set.union v_ty (process_expr env sigma fixnames e v_ty) in Id.Set.elements s type t = Names.Id.Set.t let definition_using env evd ~fixnames ~using ~terms = let l = process_expr env evd fixnames using terms in Names.Id.Set.(CList.fold_right add l empty) let name_set id expr = if Id.equal id all_collection_id then err_redefine_all_collection (); if is_known_name id then warn_redefine_collection id; if Termops.is_section_variable (Global.env ()) id then warn_variable_shadowing id; known_names := (id,expr) :: !known_names let minimize_hyps env ids = let rec aux ids = let ids' = Id.Set.fold (fun id alive -> let impl_by_id = Id.Set.remove id (really_needed env (Id.Set.singleton id)) in if Id.Set.is_empty impl_by_id then alive else Id.Set.diff alive impl_by_id) ids ids in if Id.Set.equal ids ids' then ids else aux ids' in aux ids let remove_ids_and_lets env s ids = let not_ids id = not (Id.Set.mem id ids) in let no_body id = named_body id env = None in let deps id = really_needed env (Id.Set.singleton id) in (Id.Set.filter (fun id -> not_ids id && (no_body id || Id.Set.exists not_ids (Id.Set.filter no_body (deps id)))) s) let record_proof_using expr = Aux_file.record_in_aux "suggest_proof_using" expr let debug_proof_using = CDebug.create ~name:"proof-using" () (* Variables in [skip] come from after the definition, so don't count for "All". Used in the variable case since the env contains the variable itself. *) let suggest_common env ppid used ids_typ skip = let module S = Id.Set in let open Pp in let pr_set parens s = let wrap ppcmds = if parens && S.cardinal s > 1 then str "(" ++ ppcmds ++ str ")" else ppcmds in wrap (prlist_with_sep (fun _ -> str" ") Id.print (S.elements s)) in let needed = minimize_hyps env (remove_ids_and_lets env used ids_typ) in let all_needed = really_needed env needed in let all = List.fold_left (fun all d -> S.add (NamedDecl.get_id d) all) S.empty (named_context env) in let all = S.diff all skip in let fwd_typ = close_fwd env (Evd.from_env env) ids_typ in let () = debug_proof_using (fun () -> str "All " ++ pr_set false all ++ fnl() ++ str "Type " ++ pr_set false ids_typ ++ fnl() ++ str "needed " ++ pr_set false needed ++ fnl() ++ str "all_needed " ++ pr_set false all_needed ++ fnl() ++ str "Type* " ++ pr_set false fwd_typ) in let valid_exprs = ref [] in let valid e = valid_exprs := e :: !valid_exprs in if S.is_empty needed then valid (str "Type"); if S.equal all_needed fwd_typ then valid (str "Type*"); if S.equal all all_needed then valid(str "All"); valid (pr_set false needed); Feedback.msg_info ( str"The proof of "++ ppid ++ spc() ++ str "should start with one of the following commands:"++spc()++ v 0 ( prlist_with_sep cut (fun x->str"Proof using " ++x++ str". ") !valid_exprs)); if Aux_file.recording () then let s = string_of_ppcmds (prlist_with_sep (fun _ -> str";") (fun x->x) !valid_exprs) in record_proof_using s let suggest_proof_using = ref false let () = Goptions.(declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Suggest";"Proof";"Using"]; optread = (fun () -> !suggest_proof_using); optwrite = ((:=) suggest_proof_using) }) let suggest_constant env kn = if !suggest_proof_using then begin let open Declarations in let body = lookup_constant kn env in let used = Id.Set.of_list @@ List.map NamedDecl.get_id body.const_hyps in let ids_typ = global_vars_set env body.const_type in suggest_common env (Printer.pr_constant env kn) used ids_typ Id.Set.empty end let suggest_variable env id = if !suggest_proof_using then begin match lookup_named id env with | LocalDef (_,body,typ) -> let ids_typ = global_vars_set env typ in let ids_body = global_vars_set env body in let used = Id.Set.union ids_body ids_typ in suggest_common env (Id.print id) used ids_typ (Id.Set.singleton id) | LocalAssum _ -> assert false end let value = ref None let using_to_string us = Pp.string_of_ppcmds (Ppvernac.pr_using us) let entry = Procq.eoi_entry G_vernac.section_subset_expr let using_from_string us = Procq.Entry.parse entry (Procq.Parsable.make (Gramlib.Stream.of_string ("( "^us^" )"))) let proof_using_opt_name = ["Default";"Proof";"Using"] let () = Goptions.(declare_stringopt_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = proof_using_opt_name; optread = (fun () -> Option.map using_to_string !value); optwrite = (fun b -> value := Option.map using_from_string b); }) let get_default_proof_using () = !value rocq-9.2.0/vernac/proof_using.mli000066400000000000000000000027741516144147600170240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Evd.evar_map -> fixnames:Names.Id.t list (* names of fixpoint occurring recursively, if any *) -> using:Vernacexpr.section_subset_expr -> terms:EConstr.constr list -> t val name_set : Names.Id.t -> Vernacexpr.section_subset_expr -> unit val suggest_constant : Environ.env -> Names.Constant.t -> unit val suggest_variable : Environ.env -> Names.Id.t -> unit val get_default_proof_using : unit -> Vernacexpr.section_subset_expr option val proof_using_opt_name : string list (** For the stm *) val using_from_string : string -> Vernacexpr.section_subset_expr rocq-9.2.0/vernac/pvernac.ml000066400000000000000000000113441516144147600157500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* proof_mode_entry type proof_mode = string (* Tactic parsing modes *) let register_proof_mode, find_proof_mode, lookup_proof_mode, list_proof_modes = let proof_mode : (string, proof_mode_entry) 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 let list_proof_modes () = Hashtbl.fold CString.Map.add proof_mode CString.Map.empty in register_proof_mode, find_proof_mode, lookup_proof_mode, list_proof_modes let proof_mode_to_string name = name (* Default proof mode, to be set at the beginning of proofs for programs that cannot be statically classified. *) let proof_mode_opt_name = ["Default";"Proof";"Mode"] let noedit_mode = Entry.make "noedit_command" let noedit_tactic_expr = Entry.make "noedit_tactic_expr" let noedit_mode_entry = ProofMode { command_entry = noedit_mode; wit_tactic_expr = Stdarg.wit_unit; tactic_expr_entry = noedit_tactic_expr; } let { Goptions.get = get_default_proof_mode } = Goptions.declare_interpreted_string_option_and_ref ~stage:Summary.Stage.Synterp ~key:proof_mode_opt_name ~value:(register_proof_mode "Noedit" noedit_mode_entry) (fun name -> match lookup_proof_mode name with | Some pm -> pm | None -> CErrors.user_err Pp.(str (Format.sprintf "No proof mode named \"%s\"." name))) proof_mode_to_string () let command_entry_ref = ref None module Vernac_ = struct (* The different kinds of vernacular commands *) let gallina = Entry.make "gallina" let gallina_ext = Entry.make "gallina_ext" let command = Entry.make "command" let syntax = Entry.make "syntax_command" let vernac_control = Entry.make "vernac_control" let inductive_or_record_definition = Entry.make "inductive_or_record_definition" let fix_definition = Entry.make "fix_definition" let red_expr = Entry.make "red_expr" let hint_info = Entry.make "hint_info" (* Main vernac entry *) let main_entry = Entry.make "vernac" let noedit_mode = noedit_mode let () = let act_vernac v loc = Some v in let act_eoi _ loc = None in let rule = [ Procq.(Production.make (Rule.next Rule.stop (Symbol.token Tok.PEOI)) act_eoi); Procq.(Production.make (Rule.next Rule.stop (Symbol.nterm vernac_control)) act_vernac); ] in (* NB ignore_kw doesn't matter, no potential keywords here *) Procq.(grammar_extend ~ignore_kw:true main_entry (Fresh (Gramlib.Gramext.First, [None, None, rule]))) let select_command_entry spec = match spec with | None -> noedit_mode | Some ename -> let ProofMode mode = find_proof_mode ename in mode.command_entry let parse_generic_tactic strm = let (let+) x f = Result.map f x in let mode = get_default_proof_mode () in let ProofMode mode = find_proof_mode mode in let+ v = Procq.Entry.parse_token_stream mode.tactic_expr_entry strm in Gentactic.of_raw_genarg Genarg.(in_gen (rawwit mode.wit_tactic_expr) v) let command_entry = Procq.Entry.(of_parser "command_entry" { parser_fun = (fun _kwstate strm -> Procq.Entry.parse_token_stream (select_command_entry !command_entry_ref) strm) }) let generic_tactic = Procq.Entry.(of_parser "generic_tactic" { parser_fun = (fun _kwstate strm -> parse_generic_tactic strm) }) end module Unsafe = struct let set_tactic_entry oname = command_entry_ref := oname end let main_entry proof_mode = Unsafe.set_tactic_entry proof_mode; Vernac_.main_entry let () = register_grammar Redexpr.wit_red_expr (Vernac_.red_expr); register_grammar Gentactic.wit_generic_tactic Vernac_.generic_tactic rocq-9.2.0/vernac/pvernac.mli000066400000000000000000000050661516144147600161250ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unit end (** The main entry: reads an optional vernac command *) val main_entry : proof_mode option -> 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. *) type proof_mode_entry = ProofMode : { command_entry : Vernacexpr.vernac_expr Entry.t; wit_tactic_expr : ('raw,_,unit) Genarg.genarg_type; tactic_expr_entry : 'raw Entry.t; } -> proof_mode_entry val register_proof_mode : string -> proof_mode_entry -> proof_mode val lookup_proof_mode : string -> proof_mode option val proof_mode_to_string : proof_mode -> string val list_proof_modes : unit -> proof_mode_entry CString.Map.t val get_default_proof_mode : unit -> proof_mode val proof_mode_opt_name : string list rocq-9.2.0/vernac/recLemmas.ml000066400000000000000000000061521516144147600162230ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let (hyps,ccl) = EConstr.decompose_prod_decls sigma ccl in let hyps = hyps @ ctx in let whnf_hyp_hds = EConstr.map_rel_context_in_env (fun env c -> fst (Reductionops.whd_all_stack env sigma c)) (Global.env()) hyps in let ind_hyps = List.flatten (List.map_i (fun i decl -> let t = RelDecl.get_type decl in match EConstr.kind sigma t with | Ind ((kn,_ as ind),u) when let mind = Global.lookup_mind kn in mind.mind_finite <> Declarations.CoFinite -> [ind,i] | _ -> []) 0 (List.rev (List.filter Context.Rel.Declaration.is_local_assum whnf_hyp_hds))) in let ind_ccl = let cclenv = EConstr.push_rel_context hyps (Global.env()) in let whnf_ccl,_ = Reductionops.whd_all_stack cclenv sigma ccl in match EConstr.kind sigma whnf_ccl with | Ind ((kn,_ as ind),u) when (Global.lookup_mind kn).mind_finite == Declarations.CoFinite -> [ind,0] | _ -> [] in ind_hyps,ind_ccl) ctxs ccls in let inds_hyps,ind_ccls = List.split inds in let of_same_mutind ((kn,_),_) = function ((kn',_),_) -> Environ.QMutInd.equal (Global.env ()) kn kn' in (* Check if all conclusions are coinductive in the same type *) (* (degenerated cartesian product since there is at most one coind ccl) *) let same_indccl = List.cartesians_filter (fun hyp oks -> if List.for_all (of_same_mutind hyp) oks then Some (hyp::oks) else None) [] ind_ccls in let common_same_indhyp = List.cartesians_filter (fun hyp oks -> if List.for_all (of_same_mutind hyp) oks then Some (hyp::oks) else None) [] inds_hyps in let possibly_cofix = not (List.is_empty same_indccl) in (* all conclusions are coinductive *) let possible_fix_indices = match common_same_indhyp with | [] -> [] | _::_ -> (* assume the largest indices as possible *) List.map (List.map snd) inds_hyps in if not possibly_cofix && List.is_empty possible_fix_indices then CErrors.user_err Pp.(str ("Cannot find common (mutual) inductive premises or coinductive" ^ " conclusions in the statements.")); Pretyping.{possibly_cofix; possible_fix_indices} rocq-9.2.0/vernac/recLemmas.mli000066400000000000000000000014551516144147600163750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* EConstr.rel_context list -> EConstr.t list -> Pretyping.possible_guard rocq-9.2.0/vernac/record.ml000066400000000000000000001243751516144147600156010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let sigma, (i, b, t), impl, loc = match d with | Vernacexpr.AssumExpr({CAst.v=id; loc},bl,t) -> (* Temporary compatibility with the type-classes heuristics *) (* which are applied after the interpretation of bl and *) (* before the one of t otherwise (see #13166) *) let t = if bl = [] then t else mkCProdN bl t in let sigma, t, impl = ComAssumption.interp_assumption ~program_mode:false ~poly env sigma impls_env [] t in sigma, (id, None, t), impl, loc | Vernacexpr.DefExpr({CAst.v=id; loc},bl,b,t) -> let sigma, (b, t), impl = ComDefinition.interp_definition ~program_mode:false ~poly env sigma impls_env bl None b t in let t = match t with Some t -> t | None -> Retyping.get_type_of env sigma b in sigma, (id, Some b, t), impl, loc in let r = Retyping.relevance_of_type env sigma t in let impls_env = match i with | Anonymous -> impls_env | Name id -> Id.Map.add id (Constrintern.compute_internalization_data env sigma id Constrintern.Method t impl) impls_env in let d = match b with | None -> LocalAssum (make_annot i r,t) | Some b -> LocalDef (make_annot i r,b,t) in List.iter (Metasyntax.set_notation_for_interpretation env impls_env) no; (EConstr.push_rel d env, sigma, impl :: uimpls, loc :: locs, d::params, impls_env)) (env, sigma, [], [], [], impls_env) nots l in let _, _, sigma = Context.Rel.fold_outside ~init:(env,0,sigma) (fun f (env,k,sigma) -> let sigma = RelDecl.fold_constr (fun c sigma -> ComInductive.maybe_unify_params_in env sigma ~ninds ~nparams ~binders:k c) f sigma in EConstr.push_rel f env, k+1, sigma) newfs in sigma, (impls, locs, newfs) let check_anonymous_type ind = match ind with | { CAst.v = CSort s } -> Constrexpr_ops.(sort_expr_eq expr_Type_sort s) | _ -> false let error_parameters_must_be_named bk {CAst.loc; v=name} = match bk, name with | Default _, Anonymous -> CErrors.user_err ?loc (str "Record parameters must be named.") | _ -> () let check_parameters_must_be_named = function | CLocalDef (b, _, _, _) -> error_parameters_must_be_named default_binder_kind b | CLocalAssum (ls, _, bk, _ce) -> List.iter (error_parameters_must_be_named bk) ls | CLocalPattern {CAst.loc} -> Loc.raise ?loc (Gramlib.Grammar.ParseError "pattern with quote not allowed in record parameters") (** [DataI.t] contains the information used in record interpretation, it is a strict subset of [Ast.t] thus this should be eventually removed or merged with [Ast.t] *) module DataI = struct type t = { name : lident ; constructor_name : Id.t ; arity : Constrexpr.constr_expr option (** declared sort for the record *) ; nots : Metasyntax.notation_interpretation_decl list list (** notations for fields *) ; fs : Vernacexpr.local_decl_expr list ; default_inhabitant_id : Id.t option } end module Data = struct (* XXX move coercion_flags to ComCoercion? *) type coercion_flags = { coe_local : bool; coe_reversible : bool; } type instance_flags = { inst_locality : Hints.hint_locality; inst_priority : int option; } type projection_flags = { pf_coercion: coercion_flags option; pf_instance: instance_flags option; pf_canonical: bool; } type t = { is_coercion : Vernacexpr.coercion_flag ; proj_flags : projection_flags list } end (** Is [s] a single local level (type or qsort)? If so return it. *) let is_sort_variable sigma s = match EConstr.ESorts.kind sigma s with | SProp | Prop | Set -> None | Type u | QSort (_, u) -> match Univ.Universe.level u with | None -> None | Some l -> if Univ.Level.Set.mem l (fst (Evd.universe_context_set sigma)) then Some l else None let build_type_telescope ~unconstrained_sorts newps env0 sigma { DataI.arity; _ } = match arity with | None -> let sigma, s = Evd.new_sort_variable Evd.univ_flexible_alg sigma in sigma, (EConstr.mkSort s, s) | Some { CAst.v = CSort s; loc } when Constrexpr_ops.(sort_expr_eq expr_Type_sort s) -> (* special case: the user wrote ": Type". We want to allow it to become algebraic (and Prop but that may change in the future) *) let sigma, s = Evd.new_sort_variable ?loc UState.univ_flexible_alg sigma in sigma, (EConstr.mkSort s, s) | Some t -> let env = EConstr.push_rel_context newps env0 in let impls = Constrintern.empty_internalization_env in let sigma, s = let t = Constrintern.intern_gen IsType ~impls env sigma t in let flags = { Pretyping.all_no_fail_flags with program_mode = false; unconstrained_sorts } in Pretyping.understand_tcc ~flags env sigma ~expected_type:IsType t in let sred = Reductionops.whd_allnolet env sigma s in (match EConstr.kind sigma sred with | Sort s' -> (sigma, (s, s')) | _ -> user_err ?loc:(constr_loc t) (str"Sort expected.")) module DefClassEntry = struct type t = { univs : UState.named_universes_entry; name : lident; projname : lident; params : Constr.rel_context; sort : Sorts.t; typ : Constr.t; (* NB: typ is convertible to sort *) projtyp : Constr.t; inhabitant_id : Id.t; impls : Impargs.manual_implicits; projimpls : Impargs.manual_implicits; } end module RecordEntry = struct type one_ind_info = { (* inhabitant_id not redundant with the entry in non prim record case *) inhabitant_id : Id.t; default_dep_elim : DeclareInd.default_dep_elim; (* implfs includes the param and principal argument info *) implfs : Impargs.manual_implicits list; fieldlocs : Loc.t option list; } let make_ind_infos id elims implfs fieldlocs = { inhabitant_id = id; default_dep_elim = elims; implfs; fieldlocs } type t = { global_univs : Univ.ContextSet.t; ubinders : UState.named_universes_entry; mie : Entries.mutual_inductive_entry; ind_infos : one_ind_info list; param_impls : Impargs.manual_implicits; } end type defclass_or_record = | DefclassEntry of DefClassEntry.t | RecordEntry of RecordEntry.t (* we currently don't check that defclasses are nonrecursive until we try to declare the definition in the kernel so we do need env_ar_params (instead of env_params) to avoid unbound rel anomalies *) let def_class_levels ~def ~env_ar_params sigma aritysorts ctors = let s, ctor = match aritysorts, ctors with | [s], [ctor] -> begin match ctor with | [LocalAssum (na,t)] -> s, t | _ -> assert false end | _ -> CErrors.user_err Pp.(str "Mutual definitional classes are not supported.") in let ctor_sort = Retyping.get_sort_of env_ar_params sigma ctor in let is_prop_ctor = EConstr.ESorts.is_prop sigma ctor_sort in let sigma = Evd.set_leq_sort sigma ctor_sort s in if Option.cata (Evd.is_flexible_level sigma) false (is_sort_variable sigma s) && is_prop_ctor then (* We assume that the level in aritysort is not constrained and clear it, if it is flexible *) let sigma = Evd.set_eq_sort sigma EConstr.ESorts.set s in sigma, EConstr.ESorts.prop, ctor else sigma, s, ctor let finalize_def_class env sigma ~params ~sort ~projtyp = let sigma, (params, sort, typ, projtyp) = Evarutil.finalize ~abort_on_undefined_evars:false sigma (fun nf -> let typ = EConstr.it_mkProd_or_LetIn (EConstr.mkSort sort) params in let typ = nf typ in (* we know the context is exactly the params because we built typ from mkSort *) let params, typ = Term.decompose_prod_decls typ in let projtyp = nf projtyp in let sort = destSort (nf (EConstr.mkSort sort)) in params, sort, typ, projtyp) in let ce t = Pretyping.check_evars env sigma (EConstr.of_constr t) in (* no need to check evars in typ which is guaranteed to be a sort *) let () = Context.Rel.iter ce params in let () = ce projtyp in let () = if not (Vars.closedn (List.length params) projtyp) then CErrors.user_err Pp.(str "Definitional classes cannot be recursive.") in sigma, params, sort, typ, projtyp let adjust_field_implicits ~isclass (params,param_impls) (impls:Impargs.manual_implicits) = let main_arg = if isclass then Some (Anonymous, true) else None in let param_impls = if isclass then List.rev (List.filter_map (fun d -> if RelDecl.is_local_def d then None else Some (CAst.make (Some (RelDecl.get_name d, true)))) params) else param_impls in param_impls @ (CAst.make main_arg :: impls) type kind_class = NotClass | RecordClass | DefClass (** Pick a variable name for a record, avoiding names bound in its fields. *) let canonical_inhabitant_id ~isclass ind_id = if isclass then ind_id else Id.of_string (Unicode.lowercase_first_char (Id.to_string ind_id)) (** Get all names bound at the head of [t]. *) let rec add_bound_names_constr (names : Id.Set.t) (t : constr) : Id.Set.t = match destProd t with | (b, _, t) -> let names = match b.binder_name with | Name.Anonymous -> names | Name.Name n -> Id.Set.add n names in add_bound_names_constr names t | exception DestKO -> names (** Get all names bound in any record field. *) let bound_names_ind_entry (ind:Entries.one_inductive_entry) : Id.Set.t = let ctor = match ind.mind_entry_lc with | [ctor] -> ctor | _ -> assert false in let fields, _ = Term.decompose_prod_decls ctor in let add_names names field = add_bound_names_constr names (RelDecl.get_type field) in List.fold_left add_names Id.Set.empty fields let inhabitant_id ~isclass bound_names ind {DataI.default_inhabitant_id=id; name} = match id with | Some id -> id | None -> let canonical_inhabitant_id = canonical_inhabitant_id ~isclass name.v in (* In the type of every projection, the record is bound to a variable named using the first character of the record type. We rename it to avoid collisions with names already used in the field types. *) Namegen.next_ident_away canonical_inhabitant_id (bound_names ind) let fix_entry_record ~isclass ~primitive_proj records mie = let ids = List.map2 (inhabitant_id ~isclass bound_names_ind_entry) mie.mind_entry_inds records in if not primitive_proj then ids, { mie with mind_entry_record = Some None } else ids, { mie with mind_entry_record = Some (Some (Array.of_list ids)) } let typecheck_params_and_fields ~kind ~(flags:ComInductive.flags) ~primitive_proj udecl params (records : DataI.t list) = let def = kind = DefClass in let isclass = kind != NotClass in let env0 = Global.env () in (* Special case elaboration for template-polymorphic inductives, lower bound on introduced universes is Prop so that we do not miss any Set <= i constraint for universes that might actually be instantiated with Prop. *) let is_template = List.exists (fun { DataI.arity; _} -> Option.cata check_anonymous_type true arity) records in let unconstrained_sorts = not (PolyFlags.univ_poly flags.poly) && not def && is_template in let sigma, udecl, variances = Constrintern.interp_cumul_univ_decl_opt env0 udecl in let () = List.iter check_parameters_must_be_named params in let sigma, (impls_env, ((_env1,params), impls, _paramlocs)) = Constrintern.interp_context_evars ~program_mode:false ~unconstrained_sorts env0 sigma params in let sigma, typs = List.fold_left_map (build_type_telescope ~unconstrained_sorts params env0) sigma records in let typs, aritysorts = List.split typs in let arities = List.map (fun typ -> EConstr.it_mkProd_or_LetIn typ params) typs in let relevances = List.map (fun s -> EConstr.ESorts.relevance_of_sort s) aritysorts in let fold accu { DataI.name; _ } arity r = EConstr.push_rel (LocalAssum (make_annot (Name name.v) r,arity)) accu in let env_ar_params = EConstr.push_rel_context params (List.fold_left3 fold env0 records arities relevances) in let impls_env = let ids = List.map (fun { DataI.name; _ } -> name.v) records in let impls = List.map (fun _ -> impls) arities in Constrintern.compute_internalization_env env0 sigma ~impls:impls_env Constrintern.Inductive ids arities impls in let ninds = List.length arities in let nparams = List.length params in let fold sigma { DataI.nots; fs; _ } = interp_fields_evars ~poly:flags.poly env_ar_params sigma ~ninds ~nparams impls_env nots fs in let (sigma, fields) = List.fold_left_map fold sigma records in let field_impls, locs, fields = List.split3 fields in let field_impls = List.map (List.map (adjust_field_implicits ~isclass (params,impls))) field_impls in let sigma = Pretyping.solve_remaining_evars Pretyping.all_and_fail_flags env_ar_params sigma in if def then (* XXX to fix: if we enter [Class Foo : typ := Bar : nat.], [typ] will get unfolded here *) let sigma, sort, projtyp = def_class_levels ~def ~env_ar_params sigma aritysorts fields in let sigma, params, sort, typ, projtyp = (* named and rel context in the env don't matter here (they will be replaced by the ones of the unsolved evars in the error message which is the env's only use) *) finalize_def_class env_ar_params sigma ~params ~sort ~projtyp in let name, projname = match records with | [{name; fs=[AssumExpr (projname, _, _)]}] -> name, projname | _ -> assert false in let projname = CAst.map Nameops.Name.get_id projname in let univs = Evd.check_univ_decl ~poly:flags.poly sigma udecl in (* definitional classes are encoded as 1 constructor with 1 field whose type is the projection type *) let projimpls = match field_impls with | [[x]] -> x | _ -> assert false in let inhabitant_id = inhabitant_id ~isclass (add_bound_names_constr Id.Set.empty) projtyp (List.hd records) in DefclassEntry { univs; name; projname; params; sort; typ; projtyp; inhabitant_id; impls; projimpls; } else (* each inductive has one constructor *) let ninds = List.length arities in let nparams = List.length params in let constructors = List.map2_i (fun i record fields -> let open EConstr in let nfields = List.length fields in let ind_args = Context.Rel.instance_list mkRel nfields params in let ind = applist (mkRel (ninds - i + nparams + nfields), ind_args) in let ctor = it_mkProd_or_LetIn ind fields in [record.DataI.constructor_name], [ctor]) 0 records fields in let indnames = List.map (fun x -> x.DataI.name.v) records in let arities_explicit = List.map (fun x -> Option.has_some x.DataI.arity) records in let template_syntax = List.map (fun typ -> if EConstr.isArity sigma typ then ComInductive.SyntaxAllowsTemplatePoly else ComInductive.SyntaxNoTemplatePoly) typs in let env_ar = Environ.pop_rel_context nparams env_ar_params in let default_dep_elim, mie, ubinders, global_univs = ComInductive.interp_mutual_inductive_constr ~sigma ~flags ~udecl ~variances ~ctx_params:params ~indnames ~arities_explicit ~arities:typs ~constructors ~template_syntax ~env_ar ~private_ind:false in let ids, mie = fix_entry_record ~isclass ~primitive_proj records mie in RecordEntry { mie; global_univs; ubinders; ind_infos = List.map4 RecordEntry.make_ind_infos ids default_dep_elim field_impls locs; param_impls = impls; } type record_error = | MissingProj of Id.t * Id.t list | BadTypedProj of Id.t * env * Type_errors.type_error let warn_cannot_define_projection = CWarnings.create ~name:"cannot-define-projection" ~category:CWarnings.CoreCategories.records (fun msg -> hov 0 msg) type arity_error = | NonInformativeToInformative let error_elim_explain kp ki = let open Sorts.Quality in match kp,ki with | QConstant QType, QConstant QProp -> Some NonInformativeToInformative | _ -> None (* If a projection is not definable, we throw an error if the user asked it to be a coercion or instance. Otherwise, we just print an info message. The user might still want to name the field of the record. *) let warning_or_error ?loc ~info flags indsp err = let st = match err with | MissingProj (fi,projs) -> let s,have = if List.length projs > 1 then "s","were" else "","was" in (Id.print fi ++ strbrk" cannot be defined because the projection" ++ str s ++ spc () ++ prlist_with_sep pr_comma Id.print projs ++ spc () ++ str have ++ strbrk " not defined.") | BadTypedProj (fi,env,te) -> let err = match te with | ElimArity (_, _, Some s) -> error_elim_explain (Sorts.quality s) (Inductiveops.elim_sort (Global.lookup_inductive indsp)) | _ -> None in match err with | Some NonInformativeToInformative -> (Id.print fi ++ strbrk" cannot be defined because it is informative and " ++ Printer.pr_inductive (Global.env()) indsp ++ strbrk " is not.") | None -> (Id.print fi ++ str " cannot be defined because it is not typable:" ++ spc() ++ Himsg.explain_type_error env (Evd.from_env env) (Pretype_errors.of_type_error te)) in (* XXX flags.pf_canonical? *) if Option.has_some flags.Data.pf_coercion || Option.has_some flags.Data.pf_instance then user_err ?loc ~info st; warn_cannot_define_projection ?loc (hov 0 st) type field_status = | NoProjection of Name.t | Projection of constr exception NotDefinable of record_error (* This replaces previous projection bodies in current projection *) (* Undefined projs are collected and, at least one undefined proj occurs *) (* in the body of current projection then the latter can not be defined *) (* [c] is defined in ctxt [[params;fields]] and [l] is an instance of *) (* [[fields]] defined in ctxt [[params;x:ind]] *) let subst_projection fid l c = let lv = List.length l in let bad_projs = ref [] in let rec substrec depth c = match Constr.kind c with | Rel k -> (* We are in context [[params;fields;x:ind;...depth...]] *) if k <= depth+1 then c else if k-depth-1 <= lv then match List.nth l (k-depth-2) with | Projection t -> lift depth t | NoProjection (Name id) -> bad_projs := id :: !bad_projs; mkRel k | NoProjection Anonymous -> user_err (str "Field " ++ Id.print fid ++ str " depends on the " ++ pr_nth (k-depth-1) ++ str " field which has no name.") else mkRel (k-lv) | _ -> Constr.map_with_binders succ substrec depth c in let c' = lift 1 c in (* to get [c] defined in ctxt [[params;fields;x:ind]] *) let c'' = substrec 0 c' in if not (List.is_empty !bad_projs) then raise (NotDefinable (MissingProj (fid,List.rev !bad_projs))); c'' let instantiate_possibly_recursive_type ind u ntypes paramdecls fields = let subst = List.map_i (fun i _ -> mkRel i) 1 paramdecls in let subst' = List.init ntypes (fun i -> mkIndU ((ind, ntypes - i - 1), u)) in Vars.substl_rel_context (subst @ subst') fields (* We build projections *) (** Declare projection [ref] over [from] a coercion or a typeclass instance according to [flags]. *) let declare_proj_coercion_instance ~flags ref from = let () = match flags.Data.pf_coercion with | None -> () | Some { coe_local=local; coe_reversible=reversible } -> let cl = ComCoercion.class_of_global from in ComCoercion.try_add_new_coercion_with_source ref ~local ~reversible ~source:cl in let () = match flags.Data.pf_instance with | None -> () | Some { inst_locality; inst_priority } -> let env = Global.env () in let sigma = Evd.from_env env in let info = Typeclasses.{ hint_priority = inst_priority; hint_pattern = None } in Classes.declare_instance ~warn:true env sigma (Some info) inst_locality ref in () (* TODO: refactor the declaration part here; this requires some surgery as Evarutil.finalize is called too early in the path *) (** This builds and _declares_ a named projection, the code looks tricky due to the term manipulation. It also handles declaring the implicits parameters, coercion status, etc... of the projection; this could be refactored as noted above by moving to the higher-level declare constant API *) let build_named_proj ~primitive ~flags ~univs ~uinstance ~kind env paramdecls paramargs decl impls {CAst.v=fid; loc} subst nfi ti i indsp mib lifted_fields x rp = let ccl = subst_projection fid subst ti in let body, p_opt = match decl with | LocalDef (_,ci,_) -> subst_projection fid subst ci, None | LocalAssum ({binder_relevance=rci},_) -> (* [ccl] is defined in context [params;x:rp] *) (* [ccl'] is defined in context [params;x:rp;x:rp] *) if primitive then let p = Projection.Repr.make indsp ~proj_npars:mib.mind_nparams ~proj_arg:i fid in mkProj (Projection.make p false, rci, mkRel 1), Some (p,rci) else let ccl' = liftn 1 2 ccl in let p = mkLambda (x, lift 1 rp, ccl') in let branch = it_mkLambda_or_LetIn (mkRel nfi) lifted_fields in let ci = Inductiveops.make_case_info env indsp LetStyle in (* Record projections are always NoInvert because they're at constant relevance *) mkCase (Inductive.contract_case env (ci, (p, rci), NoInvert, mkRel 1, [|branch|])), None in let proj = it_mkLambda_or_LetIn (mkLambda (x,rp,body)) paramdecls in let projtyp = it_mkProd_or_LetIn (mkProd (x,rp,ccl)) paramdecls in let entry = Declare.definition_entry ~univs ~types:projtyp proj in let kind = Decls.IsDefinition kind in let kn = (* XXX more precise loc *) try Declare.declare_constant ?loc ~name:fid ~kind (Declare.DefinitionEntry entry) with Type_errors.TypeError (ctx,te) as exn when not primitive -> let _, info = Exninfo.capture exn in Exninfo.iraise (NotDefinable (BadTypedProj (fid,ctx,te)),info) in Declare.definition_message fid; let term = match p_opt with | Some (p,r) -> let _ = DeclareInd.declare_primitive_projection p kn in mkProj (Projection.make p false, r, mkRel 1) | None -> let proj_args = (*Rel 1 refers to "x"*) paramargs@[mkRel 1] in match decl with | LocalDef _ when primitive -> body | _ -> applist (mkConstU (kn,uinstance),proj_args) in let refi = GlobRef.ConstRef kn in Impargs.maybe_declare_manual_implicits false refi impls; declare_proj_coercion_instance ~flags refi (GlobRef.IndRef indsp); let i = if is_local_assum decl then i+1 else i in (Some kn, i, Projection term::subst) (** [build_proj] will build a projection for each field, or skip if the field is anonymous, i.e. [_ : t] *) let build_proj env mib indsp primitive x rp lifted_fields paramdecls paramargs ~uinstance ~kind ~univs (nfi,i,kinds,subst) flags loc decl impls = let fi = RelDecl.get_name decl in let ti = RelDecl.get_type decl in let (sp_proj,i,subst) = match fi with | Anonymous -> (None,i,NoProjection fi::subst) | Name fid -> let fid = CAst.make ?loc fid in try build_named_proj ~primitive ~flags ~univs ~uinstance ~kind env paramdecls paramargs decl impls fid subst nfi ti i indsp mib lifted_fields x rp with NotDefinable why as exn -> let _, info = Exninfo.capture exn in warning_or_error ?loc ~info flags indsp why; (None,i,NoProjection fi::subst) in (nfi - 1, i, { Structure.proj_name = fi ; proj_true = is_local_assum decl ; proj_canonical = flags.Data.pf_canonical ; proj_body = sp_proj } :: kinds , subst) (** [declare_projections] prepares the common context for all record projections and then calls [build_proj] for each one. *) let declare_projections indsp ~kind ~inhabitant_id flags ?fieldlocs fieldimpls = let env = Global.env() in let (mib,mip) = Global.lookup_inductive indsp in let uinstance = UVars.Instance.abstract_instance @@ UVars.AbstractContext.size @@ Declareops.inductive_polymorphic_context mib in let univs = match mib.mind_universes with | Monomorphic -> UState.Monomorphic_entry Univ.ContextSet.empty | Polymorphic auctx -> UState.Polymorphic_entry (UVars.AbstractContext.repr auctx) in let univs = univs, UnivNames.empty_binders in let fields, _ = mip.mind_nf_lc.(0) in let fields = List.firstn mip.mind_consnrealdecls.(0) fields in let paramdecls = Inductive.inductive_paramdecls (mib, uinstance) in let r = mkIndU (indsp,uinstance) in let rp = applist (r, Context.Rel.instance_list mkRel 0 paramdecls) in let paramargs = Context.Rel.instance_list mkRel 1 paramdecls in (*def in [[params;x:rp]]*) let x = make_annot (Name inhabitant_id) (Inductive.relevance_of_ind_body mip uinstance) in let fields = instantiate_possibly_recursive_type (fst indsp) uinstance (Declareops.mind_ntypes mib) paramdecls fields in let lifted_fields = Vars.lift_rel_context 1 fields in let primitive = match mip.mind_record with | PrimRecord _ -> true | FakeRecord | NotRecord -> false in let fieldlocs = match fieldlocs with | None -> List.make (List.length fields) None | Some fieldlocs -> fieldlocs in let (_,_,canonical_projections,_) = List.fold_left4 (build_proj env mib indsp primitive x rp lifted_fields paramdecls paramargs ~uinstance ~kind ~univs) (List.length fields,0,[],[]) flags (List.rev fieldlocs) (List.rev fields) (List.rev fieldimpls) in List.rev canonical_projections open Typeclasses let load_structure _ structure = Structure.register structure let cache_structure o = load_structure 1 o let subst_structure (subst, obj) = Structure.subst subst obj let discharge_structure x = Some x let rebuild_structure s = Structure.rebuild (Global.env()) s let inStruc : Structure.t -> Libobject.obj = let open Libobject in declare_object {(default_object "STRUCTURE") with cache_function = cache_structure; load_function = load_structure; subst_function = subst_structure; classify_function = (fun _ -> Substitute); discharge_function = discharge_structure; rebuild_function = rebuild_structure; } let declare_structure_entry o = Lib.add_leaf (inStruc o) (** Main record declaration part: The entry point is [definition_structure], which will match on the declared [kind] and then either follow the regular record declaration path to [declare_structure] or handle the record as a class declaration with [declare_class]. *) (** [declare_structure] does two principal things: - prepares and declares the low-level (mutual) inductive corresponding to [record_data] - prepares and declares the corresponding record projections, mainly taken care of by [declare_projections] *) module Record_decl = struct type t = { entry : RecordEntry.t; records : Data.t list; projections_kind : Decls.definition_object_kind; indlocs : DeclareInd.indlocs; poly : PolyFlags.t } end module Ast = struct open Vernacexpr type t = { name : Names.lident ; is_coercion : coercion_flag ; binders: local_binder_expr list ; cfs : (local_decl_expr * Data.projection_flags * notation_declaration list) list ; idbuild : lident ; sort : constr_expr option ; default_inhabitant_id : Id.t option } let to_datai { name; idbuild; cfs; sort; default_inhabitant_id; } = let fs = List.map pi1 cfs in { DataI.name = name ; constructor_name = idbuild.CAst.v ; arity = sort ; nots = List.map (fun (_, _, rf_notation) -> List.map Metasyntax.prepare_where_notation rf_notation) cfs ; fs ; default_inhabitant_id } end let check_unique_names ~def records = let extract_name acc (rf_decl, _, _) = match rf_decl with Vernacexpr.AssumExpr({CAst.v=Name id},_,_) -> id::acc | Vernacexpr.DefExpr ({CAst.v=Name id},_,_,_) -> id::acc | _ -> acc in let indlocs = records |> List.map (fun { Ast.name; idbuild; _ } -> name, idbuild ) in let fields_names = records |> List.fold_left (fun acc { Ast.cfs; _ } -> List.fold_left extract_name acc cfs) [] in let allnames = (* we don't check the name of the constructor when [def] because definitional class are encoded as 1 constructor of 1 field sharing the same name. *) let indnames = indlocs |> List.concat_map (fun (x,y) -> x.CAst.v :: if def then [] else [y.CAst.v]) in fields_names @ indnames in match List.duplicates Id.equal allnames with | [] -> List.map (fun (x,y) -> x.CAst.loc, [y.CAst.loc]) indlocs | id :: _ -> user_err (str "Two objects have the same name" ++ spc () ++ quote (Id.print id) ++ str ".") let kind_class = let open Vernacexpr in function Class true -> DefClass | Class false -> RecordClass | Inductive_kw | CoInductive | Variant | Record | Structure -> NotClass let extract_record_data records = let data = List.map Ast.to_datai records in let decl_data = List.map (fun { Ast.is_coercion; cfs } -> let proj_flags = List.map (fun (_,rf,_) -> rf) cfs in { Data.is_coercion; proj_flags }) records in let ps = match records with | [] -> CErrors.anomaly (str "Empty record block.") | r :: rem -> let eq_local_binders bl1 bl2 = List.equal local_binder_eq bl1 bl2 in match List.find_opt (fun r' -> not @@ eq_local_binders r.Ast.binders r'.Ast.binders) rem with | None -> r.Ast.binders | Some r' -> ComInductive.Internal.error_differing_params ~kind:"record" (r.name, (r.binders,None)) (r'.name, (r'.binders,None)) in ps, data, decl_data let pre_process_structure udecl kind ~flags ~primitive_proj (records : Ast.t list) = let def = (kind = Vernacexpr.Class true) in let indlocs = check_unique_names ~def records in let ps, interp_data, decl_data = extract_record_data records in let entry = (* In theory we should be able to use [Notation.with_notation_protection], due to the call to Metasyntax.set_notation_for_interpretation, however something is messing state beyond that. *) Vernacstate.System.protect (fun () -> typecheck_params_and_fields ~primitive_proj ~kind:(kind_class kind) ~flags udecl ps interp_data) () in let projections_kind = Decls.(match kind_class kind with NotClass -> StructureComponent | _ -> Method) in entry, projections_kind, decl_data, indlocs let interp_structure_core (entry:RecordEntry.t) ~projections_kind ~indlocs ~poly data = let open Record_decl in { entry; projections_kind; records = data; indlocs; poly } let interp_structure ~flags udecl kind ~primitive_proj records = assert (kind <> Vernacexpr.Class true); let entry, projections_kind, data, indlocs = pre_process_structure udecl kind ~flags ~primitive_proj records in match entry with | DefclassEntry _ -> assert false | RecordEntry entry -> interp_structure_core entry ~projections_kind ~indlocs ~poly:flags.poly data module Declared = struct type t = | Defclass of { class_kn : Constant.t; proj_kn : Constant.t; } | Record of MutInd.t end let declare_structure (decl:Record_decl.t) ~schemes = let () = Global.push_context_set decl.entry.global_univs in (* XXX no implicit arguments for constructors? *) let impls = List.make (List.length decl.entry.mie.mind_entry_inds) (decl.entry.param_impls, []) in let default_dep_elim = List.map (fun x -> x.RecordEntry.default_dep_elim) decl.entry.ind_infos in let kn = DeclareInd.declare_mutual_inductive_with_eliminations decl.entry.mie decl.entry.ubinders impls ~indlocs:decl.indlocs ~default_dep_elim ~schemes in let map i ({ RecordEntry.inhabitant_id; implfs; fieldlocs }, { Data.is_coercion; proj_flags; }) = let rsp = (kn, i) in (* This is ind path of idstruc *) let cstr = (rsp, 1) in let kind = decl.projections_kind in let projections = declare_projections rsp ~kind ~inhabitant_id proj_flags ~fieldlocs implfs in let build = GlobRef.ConstructRef cstr in let () = match is_coercion with | NoCoercion -> () | AddCoercion -> ComCoercion.try_add_new_coercion build ~local:false ~reversible:false in let struc = Structure.make (Global.env ()) rsp projections in let () = declare_structure_entry struc in GlobRef.IndRef rsp in let data = List.combine decl.entry.ind_infos decl.records in let inds = List.mapi map data in Declared.Record kn, inds (* declare definitional class (typeclasses that are not record) *) (* [data.is_coercion] must be [NoCoercion] and [data.proj_flags] must have exactly 1 element. *) let declare_class_constant entry (data:Data.t) = let { DefClassEntry.univs; name; projname; params; sort; typ; projtyp; inhabitant_id; impls; projimpls; } = entry in let {Data.is_coercion; proj_flags} = data in let proj_flags = match proj_flags with | [x] -> x | _ -> assert false in let () = (* should be ensured by caller *) match is_coercion with | NoCoercion -> () | AddCoercion -> assert false in let class_body = it_mkLambda_or_LetIn projtyp params in let class_type = it_mkProd_or_LetIn typ params in let class_entry = Declare.definition_entry ~types:class_type ~univs class_body in let cst = Declare.declare_constant ?loc:name.loc ~name:name.v (Declare.DefinitionEntry class_entry) ~kind:Decls.(IsDefinition Definition) in let inst, univs = match univs with | UState.Monomorphic_entry _, ubinders -> UVars.Instance.empty, (UState.Monomorphic_entry Univ.ContextSet.empty, ubinders) | UState.Polymorphic_entry uctx, _ -> UVars.UContext.instance uctx, univs in let cstu = (cst, inst) in let binder = let r = Sorts.relevance_of_sort sort in { Context.binder_name = Name inhabitant_id; binder_relevance = r } in let inst_type = appvectc (mkConstU cstu) (Context.Rel.instance mkRel 0 params) in let proj_type = it_mkProd_or_LetIn (mkProd(binder, inst_type, lift 1 projtyp)) params in let proj_body = it_mkLambda_or_LetIn (mkLambda (binder, inst_type, mkRel 1)) params in let proj_entry = Declare.definition_entry ~types:proj_type ~univs proj_body in let proj_cst = Declare.declare_constant ?loc:projname.loc ~name:projname.v (Declare.DefinitionEntry proj_entry) ~kind:Decls.(IsDefinition Definition) in let cref = GlobRef.ConstRef cst in Impargs.declare_manual_implicits false cref impls; Impargs.declare_manual_implicits false (GlobRef.ConstRef proj_cst) projimpls; Classes.set_typeclass_transparency ~locality:Hints.SuperGlobal [Evaluable.EvalConstRef cst] false; let () = declare_proj_coercion_instance ~flags:proj_flags (GlobRef.ConstRef proj_cst) cref in Declared.Defclass { class_kn = cst; proj_kn = proj_cst }, [cref] let set_class_mode ref mode ctx = let modes = match mode with | Some (Some m) -> Some m | _ -> let ctxl = Context.Rel.nhyps ctx in let def = typeclasses_default_mode () in let mode = match def with | Hints.ModeOutput -> None | Hints.ModeInput -> Some (List.init ctxl (fun _ -> Hints.ModeInput)) | Hints.ModeNoHeadEvar -> Some (List.init ctxl (fun _ -> Hints.ModeNoHeadEvar)) in let wm = List.init ctxl (fun _ -> def) in Classes.warn_default_mode (ref, wm); mode in match modes with | None -> () | Some modes -> Classes.set_typeclass_mode ~locality:Hints.SuperGlobal ref modes (** [declare_class] declares the typeclass information for a [Class] declaration. NB: [Class] syntax does not allow [with]. *) let declare_class ?mode declared = let env = Global.env() in let impl, univs, params, fields, projs = match declared with | Declared.Defclass { class_kn; proj_kn } -> let class_cb = Environ.lookup_constant class_kn env in let proj_cb = Environ.lookup_constant proj_kn env in let univs = Declareops.constant_polymorphic_context class_cb in let class_body = match class_cb.const_body with | Def c -> c | Undef _ | OpaqueDef _ | Primitive _ | Symbol _ -> assert false in let params, field = Term.decompose_lambda_decls class_body in let fname = Name (Constant.label proj_kn) in let frelevance = proj_cb.const_relevance in let fields = [ RelDecl.LocalAssum ({binder_name=fname; binder_relevance=frelevance}, field) ] in let proj = { Typeclasses.meth_name = fname; meth_const = Some proj_kn; } in GlobRef.ConstRef class_kn, univs, params, fields, [proj] | Declared.Record mind -> let mib, mip = Inductive.lookup_mind_specif env (mind,0) in let univs = Declareops.inductive_polymorphic_context mib in let ctor_args, _ = mip.mind_nf_lc.(0) in let fields = List.firstn mip.mind_consnrealdecls.(0) ctor_args in let make_proj decl kn = { Typeclasses.meth_name = RelDecl.get_name decl; meth_const = kn; } in let projs = List.map2 make_proj (List.rev fields) (Structure.find_projections env (mind,0)) in GlobRef.IndRef (mind, 0), univs, mib.mind_params_ctxt, fields, projs in let k = { cl_univs = univs; cl_impl = impl; cl_strict = typeclasses_strict (); cl_unique = typeclasses_unique (); cl_context = params; cl_trivial = CList.is_empty fields; cl_props = fields; cl_projs = projs; } in Classes.add_class k; set_class_mode impl mode params let add_constant_class cst = let env = Global.env () in let ty, univs = Typeops.type_of_global_in_context env (GlobRef.ConstRef cst) in let r = (Environ.lookup_constant cst env).const_relevance in let ctx, _ = decompose_prod_decls ty in let args = Context.Rel.instance Constr.mkRel 0 ctx in let t = mkApp (mkConstU (cst, UVars.make_abstract_instance univs), args) in let tc = { cl_univs = univs; cl_impl = GlobRef.ConstRef cst; cl_context = ctx; cl_trivial = false; cl_props = [LocalAssum (make_annot Anonymous r, t)]; cl_projs = []; cl_strict = typeclasses_strict (); cl_unique = typeclasses_unique () } in Classes.add_class tc; Classes.set_typeclass_transparency ~locality:Hints.SuperGlobal [Evaluable.EvalConstRef cst] false let add_inductive_class ind = let env = Global.env () in let mind, oneind = Inductive.lookup_mind_specif env ind in let ctx = oneind.mind_arity_ctxt in let univs = Declareops.inductive_polymorphic_context mind in let props, projs = match Structure.find env ind with | exception Not_found -> let r = oneind.mind_relevance in let args = Context.Rel.instance mkRel 0 ctx in let ty = mkApp (mkIndU (ind, UVars.make_abstract_instance univs), args) in [LocalAssum (make_annot Anonymous r, ty)], [] | s -> let props, _ = oneind.mind_nf_lc.(0) in let props = List.firstn oneind.mind_consnrealdecls.(0) props in let projs = s.projections |> List.map (fun (p:Structure.projection) -> { meth_name = p.proj_name; meth_const = p.proj_body }) in props, projs in let k = { cl_univs = univs; cl_impl = GlobRef.IndRef ind; cl_context = ctx; cl_trivial = false; cl_props = props; cl_projs = projs; cl_strict = typeclasses_strict (); cl_unique = typeclasses_unique (); } in Classes.add_class k let warn_already_existing_class = CWarnings.create ~name:"already-existing-class" ~category:CWarnings.CoreCategories.automation Pp.(fun g -> Printer.pr_global g ++ str " is already declared as a typeclass.") let declare_existing_class g = if Typeclasses.is_class (Global.env ()) g then warn_already_existing_class g else match g with | GlobRef.ConstRef x -> add_constant_class x | GlobRef.IndRef x -> add_inductive_class x | _ -> user_err (Pp.str"Unsupported class type, only constants and inductives are allowed.") (** [fs] corresponds to fields and [ps] to parameters; [proj_flags] is a list telling if the corresponding fields must me declared as coercions or subinstances. *) let definition_structure ~flags udecl kind ~primitive_proj (records : Ast.t list) : GlobRef.t list = let entry, projections_kind, data, indlocs = pre_process_structure udecl kind ~flags ~primitive_proj records in let declared, inds = match entry with | DefclassEntry entry -> let data = match data with [x] -> x | _ -> assert false in declare_class_constant entry data | RecordEntry entry -> let structure = interp_structure_core entry ~projections_kind ~indlocs ~poly:flags.poly data in declare_structure structure ~schemes:flags.schemes in if kind_class kind <> NotClass then declare_class ~mode:flags.mode declared; inds module Internal = struct let declare_projections = declare_projections let declare_structure_entry = declare_structure_entry end rocq-9.2.0/vernac/record.mli000066400000000000000000000063541516144147600157460ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* cumul_univ_decl_expr option -> inductive_kind -> primitive_proj:bool -> Ast.t list -> GlobRef.t list module RecordEntry : sig type one_ind_info = { (* inhabitant_id not redundant with the entry in non prim record case *) inhabitant_id : Id.t; default_dep_elim : DeclareInd.default_dep_elim; (* implfs includes the param and principal argument info *) implfs : Impargs.manual_implicits list; fieldlocs : Loc.t option list; } type t = { global_univs : Univ.ContextSet.t; ubinders : UState.named_universes_entry; mie : Entries.mutual_inductive_entry; ind_infos : one_ind_info list; param_impls : Impargs.manual_implicits; } end (** A record is an inductive [mie] with extra metadata *) module Record_decl : sig type t = { entry : RecordEntry.t; records : Data.t list; projections_kind : Decls.definition_object_kind; indlocs : DeclareInd.indlocs; poly : PolyFlags.t } end (** Ast.t list at the constr level *) val interp_structure : flags:ComInductive.flags -> cumul_univ_decl_expr option -> inductive_kind -> primitive_proj:bool -> Ast.t list -> Record_decl.t val declare_existing_class : GlobRef.t -> unit val canonical_inhabitant_id : isclass:bool -> Id.t -> Id.t (* Implementation internals, consult Rocq developers before using; current user Elpi, see https://github.com/LPCIC/coq-elpi/pull/151 *) module Internal : sig val declare_projections : Names.inductive -> kind:Decls.definition_object_kind -> inhabitant_id:Names.Id.t -> Data.projection_flags list -> ?fieldlocs:Loc.t option list -> Impargs.manual_implicits list -> Structure.projection list val declare_structure_entry : Structure.t -> unit end rocq-9.2.0/vernac/retrieveObl.ml000066400000000000000000000245251516144147600166010ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* if Evd.is_obligation_evar evm key then () else let loc, k = Evd.evar_source evi in Pretype_errors.error_unsolvable_implicit ?loc env evm key None) (Evd.undefined_map evm) type obligation_info = ( Names.Id.t * Constr.types * Evar_kinds.t Loc.located * (bool * Evar_kinds.obligation_definition_status) * Int.Set.t * unit Proofview.tactic option ) array type oblinfo = { ev_name : int * Id.t ; ev_hyps : EConstr.named_context ; ev_status : bool * Evar_kinds.obligation_definition_status ; ev_chop : int option ; ev_src : Evar_kinds.t Loc.located ; ev_typ : Constr.types ; ev_tac : unit Proofview.tactic option ; ev_deps : Int.Set.t } (** Substitute evar references in t using de Bruijn indices, where n binders were passed through. *) let succfix (depth, fixrels) = (succ depth, List.map succ fixrels) let subst_evar_constr evm evs n idf t = let seen = ref Int.Set.empty in let transparent = ref Id.Set.empty in let evar_info id = CList.assoc_f Evar.equal id evs in let rec substrec (depth, fixrels) c = match EConstr.kind evm c with | Constr.Evar (k, args) -> let {ev_name = id, idstr; ev_hyps = hyps; ev_chop = chop} = try evar_info k with Not_found -> CErrors.anomaly ~label:"eterm" Pp.( str "existential variable " ++ int (Evar.repr k) ++ str " not found.") in seen := Int.Set.add id !seen; (* Evar arguments are created in inverse order, and we must not apply to defined ones (i.e. LetIn's) *) let args = let args = Evd.expand_existential evm (k, args) in let n = match chop with None -> 0 | Some c -> c in let l, r = CList.chop n (List.rev args) in List.rev r in let args = let rec aux hyps args acc = let open Context.Named.Declaration in match (hyps, args) with | LocalAssum _ :: tlh, c :: tla -> aux tlh tla (substrec (depth, fixrels) c :: acc) | LocalDef _ :: tlh, _ :: tla -> aux tlh tla acc | [], [] -> acc | _, _ -> acc (*failwith "subst_evars: invalid argument"*) in aux hyps args [] in if List.exists (fun x -> match EConstr.kind evm x with | Constr.Rel n -> Int.List.mem n fixrels | _ -> false) args then transparent := Id.Set.add idstr !transparent; EConstr.mkApp (idf idstr, Array.of_list args) | Constr.Fix _ -> EConstr.map_with_binders evm succfix substrec (depth, 1 :: fixrels) c | _ -> EConstr.map_with_binders evm succfix substrec (depth, fixrels) c in let t' = substrec (0, []) t in (EConstr.to_constr evm t', !seen, !transparent) (** Substitute variable references in t using de Bruijn indices, where n binders were passed through. *) let subst_vars acc n t = let var_index id = Util.List.index Id.equal id acc in let rec substrec depth c = match Constr.kind c with | Constr.Var v -> ( try Constr.mkRel (depth + var_index v) with Not_found -> c ) | _ -> Constr.map_with_binders succ substrec depth c in substrec 0 t (** Rewrite type of an evar ([ H1 : t1, ... Hn : tn |- concl ]) to a product : forall H1 : t1, ..., forall Hn : tn, concl. Changes evars and hypothesis references to variable references. *) let etype_of_evar evm evs hyps concl = let open Context.Named.Declaration in let rec aux acc n = function | decl :: tl -> ( let t', s, trans = subst_evar_constr evm evs n EConstr.mkVar (Context.Named.Declaration.get_type decl) in let t'' = subst_vars acc 0 t' in let rest, s', trans' = aux (Context.Named.Declaration.get_id decl :: acc) (succ n) tl in let s' = Int.Set.union s s' in let trans' = Id.Set.union trans trans' in match decl with | LocalDef (id, c, _) -> let c', s'', trans'' = subst_evar_constr evm evs n EConstr.mkVar c in let c' = subst_vars acc 0 c' in ( Term.mkNamedProd_or_LetIn (LocalDef (EConstr.Unsafe.to_binder_annot id, c', t'')) rest , Int.Set.union s'' s' , Id.Set.union trans'' trans' ) | LocalAssum (id, _) -> (Term.mkNamedProd_or_LetIn (LocalAssum (EConstr.Unsafe.to_binder_annot id, t'')) rest, s', trans') ) | [] -> let t', s, trans = subst_evar_constr evm evs n EConstr.mkVar concl in (subst_vars acc 0 t', s, trans) in aux [] 0 (List.rev hyps) let trunc_named_context n ctx = let len = List.length ctx in CList.firstn (len - n) ctx let rec chop_product n t = let pop t = Vars.lift (-1) t in if Int.equal n 0 then Some t else match Constr.kind t with | Constr.Prod (_, _, b) -> if Vars.noccurn 1 b then chop_product (pred n) (pop b) else None | _ -> None let evar_dependencies evm oev = let one_step deps = Evar.Set.fold (fun ev s -> let evi = Evd.find_undefined evm ev in let deps' = Evd.evars_of_filtered_evar_info evm evi in if Evar.Set.mem oev deps' then invalid_arg ( "Ill-formed evar map: cycle detected for evar " ^ Pp.string_of_ppcmds @@ Evar.print oev ) else Evar.Set.union deps' s) deps deps in let rec aux deps = let deps' = one_step deps in if Evar.Set.equal deps deps' then deps else aux deps' in aux (Evar.Set.singleton oev) let move_after ((id, ev, deps) as obl) l = let rec aux restdeps = function | ((id', _, _) as obl') :: tl -> let restdeps' = Evar.Set.remove id' restdeps in if Evar.Set.is_empty restdeps' then obl' :: obl :: tl else obl' :: aux restdeps' tl | [] -> [obl] in aux (Evar.Set.remove id deps) l let sort_dependencies evl = let rec aux l found list = match l with | ((id, ev, deps) as obl) :: tl -> let found' = Evar.Set.union found (Evar.Set.singleton id) in if Evar.Set.subset deps found' then aux tl found' (obl :: list) else aux (move_after obl tl) found list | [] -> List.rev list in aux evl Evar.Set.empty [] type obligation_name_lifter = (Names.Id.t -> EConstr.t) -> EConstr.t -> Constr.t let retrieve_obligations env name evm fs ?deps ?status t ty = (* 'Serialize' the evars *) let nc = Environ.named_context env in let nc_len = Context.Named.length nc in let evm = Evarutil.nf_evar_map_undefined evm in let evl = Evd.undefined_map evm in let evl = match deps with | None -> evl | Some deps -> Evar.Map.filter (fun ev _ -> Evar.Set.mem ev deps) evl in let evl = Evar.Map.bindings evl in let evl = List.map (fun (id, ev) -> (id, ev, evar_dependencies evm id)) evl in let sevl = sort_dependencies evl in let evl = List.map (fun (id, ev, _) -> (id, ev)) sevl in let evn = let i = ref (-1) in List.rev_map (fun (id, ev) -> incr i; ( id , ( !i , Id.of_string (Id.to_string name ^ "_obligation_" ^ string_of_int (succ !i)) ) , ev )) evl in let evts = (* Remove existential variables in types and build the corresponding products *) List.fold_right (fun (id, (n, nstr), ev) evs -> let hyps = Evd.evar_filtered_context ev in let hyps = trunc_named_context nc_len hyps in let evtyp, deps, transp = etype_of_evar evm evs hyps (Evd.evar_concl ev) in let evtyp, hyps, chop = match chop_product fs evtyp with | Some t -> (t, trunc_named_context fs hyps, fs) | None -> (evtyp, hyps, 0) in let loc, k = Evd.evar_source (Evd.find_undefined evm id) in let status = match k with | Evar_kinds.QuestionMark {Evar_kinds.qm_obligation = o} -> o | _ -> ( match status with | Some o -> o | None -> Evar_kinds.Define (not (Program.get_proofs_transparency ())) ) in let force_status, status, chop = match status with | Evar_kinds.Define true as stat -> if not (Int.equal chop fs) then (true, Evar_kinds.Define false, None) else (false, stat, Some chop) | s -> (false, s, None) in let info = { ev_name = (n, nstr) ; ev_hyps = hyps ; ev_status = (force_status, status) ; ev_chop = chop ; ev_src = (loc, k) ; ev_typ = evtyp ; ev_deps = deps ; ev_tac = None } in (id, info) :: evs) evn [] in let t', _, transparent = (* Substitute evar refs in the term by variables *) subst_evar_constr evm evts 0 EConstr.mkVar t in let ty, _, _ = subst_evar_constr evm evts 0 EConstr.mkVar ty in let evars = List.map (fun (ev, info) -> let { ev_name = _, name ; ev_status = force_status, status ; ev_src = src ; ev_typ = typ ; ev_deps = deps ; ev_tac = tac } = info in let force_status, status = match status with | Evar_kinds.Define true when Id.Set.mem name transparent -> (true, Evar_kinds.Define false) | _ -> (force_status, status) in (name, typ, src, (force_status, status), deps, tac)) evts in let evnames = List.map (fun (ev, info) -> (ev, snd info.ev_name)) evts in let evmap f c = Util.pi1 (subst_evar_constr evm evts 0 f c) in (Array.of_list (List.rev evars), (evnames, evmap), t', ty) rocq-9.2.0/vernac/retrieveObl.mli000066400000000000000000000036611516144147600167500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* Evd.evar_map -> unit type obligation_info = ( Names.Id.t * Constr.types * Evar_kinds.t Loc.located * (bool * Evar_kinds.obligation_definition_status) * Int.Set.t * unit Proofview.tactic option ) array (** ident, type, location of the original evar, (opaque or transparent, expand or define), dependencies as indexes into the array, tactic to solve it *) type obligation_name_lifter = (Names.Id.t -> EConstr.t) -> EConstr.t -> Constr.t val retrieve_obligations : Environ.env -> Names.Id.t -> Evd.evar_map -> int -> ?deps:Evar.Set.t -> ?status:Evar_kinds.obligation_definition_status -> EConstr.t -> EConstr.types -> obligation_info * ( (Evar.t * Names.Id.t) list * obligation_name_lifter ) * Constr.t * Constr.t (** [retrieve_obligations env id sigma fs ?status body type] returns [obls, (evnames, evmap), nbody, ntype] a list of obligations built from evars in [body, type]. [fs] is the number of function prototypes to try to clear from evars contexts. [evnames, evmap] is the list of names / substitution functions used to program with holes. This is not used in Rocq, but in the equations plugin; [evnames] is actually redundant with the information contained in [obls] *) rocq-9.2.0/vernac/search.ml000066400000000000000000000340411516144147600155560ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Decls.logical_kind option -> env -> Evd.evar_map -> constr -> bool type display_function = GlobRef.t -> Decls.logical_kind option -> env -> Evd.evar_map -> constr -> unit (* This option restricts the output of [SearchPattern ...], etc. to the names of the symbols matching the query, separated by a newline. This type of output is useful for editors (like emacs), to generate a list of completion candidates without having to parse through the types of all symbols. *) type glob_search_item = | GlobSearchSubPattern of glob_search_where * bool * constr_pattern | GlobSearchString of string | GlobSearchKind of Decls.logical_kind | GlobSearchFilter of (GlobRef.t -> bool) type glob_search_request = | GlobSearchLiteral of glob_search_item | GlobSearchDisjConj of (bool * glob_search_request) list list module SearchBlacklist = Goptions.MakeStringTable (struct let key = ["Search";"Blacklist"] let title = "Current search blacklist : " let member_message s b = str "Search blacklist does " ++ (if b then mt () else str "not ") ++ str "include " ++ str s end) let { Goptions.get = blacklist_locals } = Goptions.declare_bool_option_and_ref ~key:["Search";"Blacklist";"Locals"] ~value:true () (* The functions iter_constructors and iter_declarations implement the behavior needed for the Rocq searching commands. These functions take as first argument the procedure that will be called to treat each entry. This procedure receives the name of the object, the assumptions that will make it possible to print its type, and the constr term that represent its type. *) let iter_constructors indsp u fn env sigma nconstr = for i = 1 to nconstr do let typ = Inductive.type_of_constructor ((indsp, i), u) (Inductive.lookup_mind_specif env indsp) in fn (GlobRef.ConstructRef (indsp, i)) None env sigma typ done (* FIXME: this is a Libobject hack that should be replaced with a proper registration mechanism. *) module DynHandle = Libobject.Dyn.Map(struct type 'a t = 'a -> unit end) let handle h (Libobject.Dyn.Dyn (tag, o)) = match DynHandle.find tag h with | f -> f o | exception Not_found -> () (* General search over declarations *) let generic_search env sigma (fn : GlobRef.t -> Decls.logical_kind option -> env -> Evd.evar_map -> constr -> unit) = List.iter (fun d -> fn (GlobRef.VarRef (NamedDecl.get_id d)) None env sigma (NamedDecl.get_type d)) (Environ.named_context env); let iter_obj prefix lobj = match lobj with | AtomicObject o -> let handler = DynHandle.add Declare.Internal.Constant.tag begin fun (id,obj) -> let kn = KerName.make prefix.obj_mp id in let cst = Global.constant_of_delta_kn kn in let gr = GlobRef.ConstRef cst in let (typ, _) = Typeops.type_of_global_in_context (Global.env ()) gr in let kind = Declare.Internal.Constant.kind obj in fn gr (Some kind) env sigma typ end @@ DynHandle.add DeclareInd.Internal.objInductive begin fun (id,_) -> let kn = KerName.make prefix.obj_mp id in let mind = Global.mind_of_delta_kn kn in let mib = Global.lookup_mind mind in let iter_packet i mip = let ind = (mind, i) in let u = UVars.make_abstract_instance (Declareops.inductive_polymorphic_context mib) in let typ = Inductive.type_of_inductive (Inductive.lookup_mind_specif env ind, u) in let () = fn (GlobRef.IndRef ind) None env sigma typ in let len = Array.length mip.mind_user_lc in iter_constructors ind u fn env sigma len in Array.iteri iter_packet mib.mind_packets end @@ DynHandle.empty in handle handler o | _ -> () in try Declaremods.iter_all_interp_segments iter_obj with Not_found -> () (** This module defines a preference on constrs in the form of a [compare] function (preferred constr must be big for this functions, so preferences such as small constr must use a reversed order). This priority will be used to order search results and propose first results which are more likely to be relevant to the query, this is why the type [t] contains the other elements required of a search. *) module ConstrPriority = struct (* The priority is memoised here. Because of the very localised use of this module, it is not worth it making a convenient interface. *) type t = GlobRef.t * Decls.logical_kind option * Environ.env * Evd.evar_map * Constr.t * priority and priority = int (** A measure of the size of a term *) let rec size t = Constr.fold (fun s t -> 1 + s + size t) 0 t (** Set of the "symbols" (definitions, inductives, constructors) which appear in a term. *) let rec symbols acc t = let open Constr in match kind t with | Const _ | Ind _ | Construct _ -> GlobRef.Set_env.add (fst @@ destRef t) acc | _ -> Constr.fold symbols acc t (** The number of distinct "symbols" (see {!symbols}) which appear in a term. *) let num_symbols t = GlobRef.Set_env.(cardinal (symbols empty t)) let priority gref t : priority = -(3*(num_symbols t) + size t) let compare (_,_,_,_,_,p1) (_,_,_,_,_,p2) = Stdlib.compare p1 p2 end module PriorityQueue = Heap.Functional(ConstrPriority) let rec iter_priority_queue q fn = (* Tail-rec! *) match PriorityQueue.maximum q with | (gref,kind,env,sigma,t,_) -> fn gref kind env sigma t; iter_priority_queue (PriorityQueue.remove q) fn | exception Heap.EmptyHeap -> () let prioritize_search seq fn = let acc = ref PriorityQueue.empty in let iter gref kind env sigma t = let p = ConstrPriority.priority gref t in acc := PriorityQueue.add (gref,kind,env,sigma,t,p) !acc in let () = seq iter in iter_priority_queue !acc fn (** Filters *) (** This function tries to see whether the conclusion matches a pattern. FIXME: this is quite dummy, we may find a more efficient algorithm. *) let rec pattern_filter pat env sigma typ = let typ = Termops.strip_outer_cast sigma typ in if Constr_matching.is_matching env sigma pat typ then true else match EConstr.kind sigma typ with | Prod (_, _, typ) | LetIn (_, _, _, typ) -> pattern_filter pat env sigma typ | _ -> false let full_name_of_reference ref = let (dir,id) = repr_path (Nametab.path_of_global ref) in DirPath.to_string dir ^ "." ^ Id.to_string id let is_local_ref : GlobRef.t -> bool = function | ConstRef c -> Declare.is_local_constant c | IndRef _ | ConstructRef _ | VarRef _ -> false (** Whether a reference is blacklisted *) let blacklist_filter : filter_function = fun ref kind env sigma typ -> if blacklist_locals() && is_local_ref ref then false else let name = full_name_of_reference ref in let is_not_bl str = not (String.string_contains ~where:name ~what:str) in CString.Set.for_all is_not_bl (SearchBlacklist.v ()) let module_filter : _ -> filter_function = fun mods ref kind env sigma typ -> let sp = Nametab.path_of_global ref in let sl = pop_dirpath @@ dirpath_of_path sp in let is_inside md = is_dirpath_prefix_of (dirpath_of_path md) sl in match mods with | SearchOutside mods -> let is_outside md = not (is_inside md) in List.for_all is_outside mods | SearchInside mods -> List.is_empty mods || List.exists is_inside mods let name_of_reference ref = Id.to_string (Nametab.basename_of_global ref) let search_filter : _ -> filter_function = fun query gr kind env sigma typ -> match query with | GlobSearchSubPattern (where,head,pat) -> let open Context.Rel.Declaration in let rec collect env hyps typ = match Constr.kind typ with | LetIn (na,b,t,c) -> collect (push_rel (LocalDef (na,b,t)) env) ((env,b) :: (env,t) :: hyps) c | Prod (na,t,c) -> collect (push_rel (LocalAssum (na,t)) env) ((env,t) :: hyps) c | _ -> (hyps,(env,typ)) in let typl= match where with | InHyp -> fst (collect env [] typ) | InConcl -> [snd (collect env [] typ)] | Anywhere -> if head then let hyps, ccl = collect env [] typ in ccl :: hyps else [env,typ] in List.exists (fun (env,typ) -> let f = if head then Constr_matching.is_matching_head else Constr_matching.is_matching_appsubterm ~closed:false in f env sigma pat (EConstr.of_constr typ)) typl | GlobSearchString s -> String.string_contains ~where:(name_of_reference gr) ~what:s | GlobSearchKind k -> (match kind with None -> false | Some k' -> k = k') | GlobSearchFilter f -> f gr (** SearchPattern *) let search_pattern env sigma pat mods pr_search = let filter ref kind env sigma typ = module_filter mods ref kind env sigma typ && pattern_filter pat env sigma (EConstr.of_constr typ) && blacklist_filter ref kind env sigma typ in let iter ref kind env sigma typ = if filter ref kind env sigma typ then pr_search ref kind env sigma typ in generic_search env sigma iter (** SearchRewrite *) let eq () = Rocqlib.(lib_ref "core.eq.type") let rewrite_pat1 pat = PApp (PRef (eq ()), [| PMeta None; pat; PMeta None |]) let rewrite_pat2 pat = PApp (PRef (eq ()), [| PMeta None; PMeta None; pat |]) let search_rewrite env sigma pat mods pr_search = let pat1 = rewrite_pat1 pat in let pat2 = rewrite_pat2 pat in let filter ref kind env sigma typ = module_filter mods ref kind env sigma typ && (pattern_filter pat1 env sigma (EConstr.of_constr typ) || pattern_filter pat2 env sigma (EConstr.of_constr typ)) && blacklist_filter ref kind env sigma typ in let iter ref kind env sigma typ = if filter ref kind env sigma typ then pr_search ref kind env sigma typ in generic_search env sigma iter (** Search *) let search env sigma items mods pr_search = let filter ref kind env sigma typ = let eqb b1 b2 = if b1 then b2 else not b2 in module_filter mods ref kind env sigma typ && let rec aux = function | GlobSearchLiteral i -> search_filter i ref kind env sigma typ | GlobSearchDisjConj l -> List.exists (List.for_all aux') l and aux' (b,s) = eqb b (aux s) in List.for_all aux' items && blacklist_filter ref kind env sigma typ in let iter ref kind env sigma typ = if filter ref kind env sigma typ then pr_search ref kind env sigma typ in generic_search env sigma iter type search_constraint = | Name_Pattern of Str.regexp | Type_Pattern of Pattern.constr_pattern | SubType_Pattern of Pattern.constr_pattern | In_Module of full_path | Include_Blacklist type 'a coq_object = { coq_object_prefix : string list; coq_object_qualid : string list; coq_object_object : 'a; } let interface_search env sigma = let rec extract_flags name tpe subtpe mods blacklist = function | [] -> (name, tpe, subtpe, mods, blacklist) | (Name_Pattern regexp, b) :: l -> extract_flags ((regexp, b) :: name) tpe subtpe mods blacklist l | (Type_Pattern pat, b) :: l -> extract_flags name ((pat, b) :: tpe) subtpe mods blacklist l | (SubType_Pattern pat, b) :: l -> extract_flags name tpe ((pat, b) :: subtpe) mods blacklist l | (In_Module id, b) :: l -> extract_flags name tpe subtpe ((id, b) :: mods) blacklist l | (Include_Blacklist, b) :: l -> extract_flags name tpe subtpe mods b l in fun flags -> let (name, tpe, subtpe, mods, blacklist) = extract_flags [] [] [] [] false flags in let filter_function ref kind env sigma constr = let id = Names.Id.to_string (Nametab.basename_of_global ref) in let path = pop_dirpath @@ dirpath_of_path (Nametab.path_of_global ref) in let toggle x b = if x then b else not b in let match_name (regexp, flag) = toggle (Str.string_match regexp id 0) flag in let match_type (pat, flag) = toggle (Constr_matching.is_matching env sigma pat (EConstr.of_constr constr)) flag in let match_subtype (pat, flag) = toggle (Constr_matching.is_matching_appsubterm ~closed:false env sigma pat (EConstr.of_constr constr)) flag in let match_module (mdl, flag) = toggle (Libnames.is_dirpath_prefix_of (dirpath_of_path mdl) path) flag in List.for_all match_name name && List.for_all match_type tpe && List.for_all match_subtype subtpe && List.for_all match_module mods && (blacklist || blacklist_filter ref kind env sigma constr) in let ans = ref [] in let print_function ref env sigma constr = let fullpath = DirPath.repr (Nametab.dirpath_of_global ref) in let qualid = Nametab.shortest_qualid_of_global Id.Set.empty ref in let (shortpath, basename) = Libnames.repr_qualid qualid in let shortpath = DirPath.repr shortpath in (* [shortpath] is a suffix of [fullpath] and we're looking for the missing prefix *) let rec prefix full short accu = match full, short with | _, [] -> let full = List.rev_map Id.to_string full in (full, accu) | _ :: full, m :: short -> prefix full short (Id.to_string m :: accu) | _ -> assert false in let (prefix, qualid) = prefix fullpath shortpath [Id.to_string basename] in let answer = { coq_object_prefix = prefix; coq_object_qualid = qualid; coq_object_object = constr; } in ans := answer :: !ans; in let iter ref kind env sigma typ = if filter_function ref kind env sigma typ then print_function ref env sigma typ in let () = generic_search env sigma iter in !ans rocq-9.2.0/vernac/search.mli000066400000000000000000000072061516144147600157320ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool) type glob_search_request = | GlobSearchLiteral of glob_search_item | GlobSearchDisjConj of (bool * glob_search_request) list list type filter_function = GlobRef.t -> Decls.logical_kind option -> env -> Evd.evar_map -> constr -> bool type display_function = GlobRef.t -> Decls.logical_kind option -> env -> Evd.evar_map -> constr -> unit (** {6 Generic filter functions} *) val blacklist_filter : filter_function (** Check whether a reference is blacklisted. *) val module_filter : Libnames.full_path list search_restriction -> filter_function (** Check whether a reference pertains or not to a set of modules *) val search_filter : glob_search_item -> filter_function (** {6 Specialized search functions} [search_xxx gl pattern modinout] searches the hypothesis of the [gl]th goal and the global environment for things matching [pattern] and satisfying module exclude/include clauses of [modinout]. *) val search_rewrite : env -> Evd.evar_map -> constr_pattern -> Libnames.full_path list search_restriction -> display_function -> unit val search_pattern : env -> Evd.evar_map -> constr_pattern -> Libnames.full_path list search_restriction -> display_function -> unit val search : env -> Evd.evar_map -> (bool * glob_search_request) list -> Libnames.full_path list search_restriction -> display_function -> unit type search_constraint = | Name_Pattern of Str.regexp (** Whether the name satisfies a regexp (uses Ocaml Str syntax) *) | Type_Pattern of Pattern.constr_pattern (** Whether the object type satisfies a pattern *) | SubType_Pattern of Pattern.constr_pattern (** Whether some subtype of object type satisfies a pattern *) | In_Module of Libnames.full_path (** Whether the object pertains to a module *) | Include_Blacklist (** Bypass the Search blacklist *) type 'a coq_object = { coq_object_prefix : string list; coq_object_qualid : string list; coq_object_object : 'a; } val interface_search : env -> Evd.evar_map -> (search_constraint * bool) list -> constr coq_object list (** {6 Generic search function} *) val generic_search : env -> Evd.evar_map -> display_function -> unit (** This function iterates over all hypothesis of the goal numbered [glnum] (if present) and all known declarations. *) (** {6 Search function modifiers} *) val prioritize_search : (display_function -> unit) -> display_function -> unit (** [prioritize_search iter] iterates over the values of [iter] (seen as a sequence of declarations), in a relevance order. This requires to perform the entire iteration of [iter] before starting streaming. So [prioritize_search] should not be used for low-latency streaming. *) rocq-9.2.0/vernac/synterp.ml000066400000000000000000000500421516144147600160140ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* >= fun l -> return (make_module_locality l)) let with_locality ~atts f = let local = Attributes.(parse locality atts) in f ~local let with_module_locality ~atts f = let module_local = Attributes.(parse module_locality atts) in f ~module_local let warn_legacy_export_set = CWarnings.create ~name:"legacy-export-set" ~category:Deprecation.Version.v8_18 Pp.(fun () -> strbrk "Syntax \"Export Set\" is deprecated, use the attribute syntax \"#[export] Set\" instead.") let deprecated_nonuniform = CWarnings.create ~name:"deprecated-nonuniform-attribute" ~category:Deprecation.Version.v8_18 Pp.(fun () -> strbrk "Attribute '#[nonuniform]' is deprecated, \ use '#[warning=\"-uniform-inheritance\"]' instead.") let warnings_att = Attributes.attribute_of_list [ "warnings", Attributes.payload_parser ~cat:(^) ~name:"warnings"; "warning", Attributes.payload_parser ~cat:(^) ~name:"warning"; ] let with_generic_atts ~check atts f = let atts, warnings = Attributes.parse_with_extra warnings_att atts in let atts, nonuniform = Attributes.parse_with_extra ComCoercion.nonuniform atts in let warnings = let () = if nonuniform <> None && check then deprecated_nonuniform () in if nonuniform <> Some true then warnings else let ui = "-uniform-inheritance" in Some (match warnings with Some w -> w ^ "," ^ ui | None -> ui) in match warnings with | None -> f ~atts | Some warnings -> if check then CWarnings.check_unknown_warnings warnings; CWarnings.with_warn warnings (fun () -> f ~atts) () type module_entry = Modintern.module_struct_expr * Names.ModPath.t * Modintern.module_kind * Entries.inline type synterp_entry = | EVernacNoop | EVernacNotation of { local : bool; decl : Metasyntax.notation_interpretation_decl } | EVernacBeginSection of lident | EVernacEndSegment of lident | EVernacRequire of Library.library_t list * DirPath.t list * export_with_cats option * (qualid * import_filter_expr) list | EVernacImport of (export_flag * Libobject.open_filter) * (Names.ModPath.t CAst.t * import_filter_expr) list | EVernacDeclareMLModule of Mltop.interp_fun | EVernacDeclareModule of Lib.export * lident * Declaremods.module_params_expr * module_entry | EVernacDefineModule of Lib.export * lident * Declaremods.module_params_expr * ((export_flag * Libobject.open_filter) * Names.ModPath.t) list * module_entry Declaremods.module_signature * module_entry list | EVernacDeclareModuleType of lident * Declaremods.module_params_expr * ((export_flag * Libobject.open_filter) * Names.ModPath.t) list * module_entry list * module_entry list | EVernacInclude of Declaremods.module_expr list | EVernacSetOption of { export : bool; key : Goptions.option_name; value : Vernacexpr.option_setting } | EVernacLoad of Vernacexpr.verbose_flag * (vernac_control_entry * Vernacstate.Synterp.t) list | EVernacExtend of Vernactypes.typed_vernac and vernac_entry = synterp_entry Vernacexpr.vernac_expr_gen and vernac_control_entry = (Vernacstate.Synterp.t VernacControl.control_entry, synterp_entry) Vernacexpr.vernac_control_gen_r CAst.t let synterp_reserved_notation ~module_local ~infix l = Metasyntax.add_reserved_notation ~local:module_local ~infix l let synterp_custom_entry ~module_local s = Metasyntax.declare_custom_entry module_local s (* Assumes cats is irrelevant if f is ImportNames *) let import_module_syntax_with_filter ~export cats m f = match f with | ImportAll -> Declaremods.Synterp.import_module cats ~export m | ImportNames ns -> () let synterp_import_mod (export,cats) qid f = let loc = qid.loc in let m = try Nametab.locate_module qid with Not_found -> CErrors.user_err ?loc Pp.(str "Cannot find module " ++ pr_qualid qid) in import_module_syntax_with_filter ~export cats m f; m let synterp_import_cats cats = Option.cata (fun cats -> Libobject.make_filter ~finite:(not cats.negative) cats.import_cats) Libobject.unfiltered cats let check_no_filter_when_using_cats l = List.iter (function | _, ImportAll -> () | q, ImportNames _ -> CErrors.user_err ?loc:q.loc Pp.(str "Cannot combine importing by categories and importing by names.")) l let synterp_import export refl = if Option.has_some (snd export) then check_no_filter_when_using_cats refl; let export = on_snd synterp_import_cats export in export, List.map (fun (qid,f) -> CAst.make ?loc:qid.loc @@ synterp_import_mod export qid f, f) refl let synterp_define_module export {loc;v=id} (binders_ast : module_binder list) mty_ast_o mexpr_ast_l = if Lib.sections_are_opened () then user_err Pp.(str "Modules and Module Types are not allowed inside sections."); let export = Option.map (on_snd synterp_import_cats) export in match mexpr_ast_l with | [] -> let binders_ast,argsexport = List.fold_right (fun (export,idl,ty) (args,argsexport) -> (idl,ty)::args, (List.map (fun {v=i} -> Option.map (on_snd synterp_import_cats) export,i)idl)@argsexport) binders_ast ([],[]) in let mp, args, sign = Declaremods.Synterp.start_module export id binders_ast mty_ast_o in let argsexports = List.map_filter (fun (export,id) -> Option.map (fun export -> export, synterp_import_mod export (qualid_of_ident id) ImportAll ) export ) argsexport in export, args, argsexports, [], sign | _::_ -> let binders_ast = List.map (fun (export,idl,ty) -> if not (Option.is_empty export) then user_err Pp.(str "Arguments of a functor definition can be imported only if the definition is interactive. Remove the \"Export\" and \"Import\" keywords from every functor argument.") else (idl,ty)) binders_ast in let mp, args, expr, sign = Declaremods.Synterp.declare_module id binders_ast mty_ast_o mexpr_ast_l in Option.iter (fun (export,cats) -> ignore (synterp_import_mod (export,cats) (qualid_of_ident id) ImportAll)) export; export, args, [], expr, sign let synterp_declare_module_type_syntax {loc;v=id} binders_ast mty_sign mty_ast_l = if Lib.sections_are_opened () then user_err Pp.(str "Modules and Module Types are not allowed inside sections."); match mty_ast_l with | [] -> let binders_ast,argsexport = List.fold_right (fun (export,idl,ty) (args,argsexport) -> (idl,ty)::args, (List.map (fun {v=i} -> Option.map (on_snd synterp_import_cats) export,i)idl)@argsexport) binders_ast ([],[]) in let mp, args, sign = Declaremods.Synterp.start_modtype id binders_ast mty_sign in let argsexport = List.map_filter (fun (export,id) -> Option.map (fun export -> export, synterp_import_mod export (qualid_of_ident ?loc id) ImportAll) export ) argsexport in args, argsexport, [], sign | _ :: _ -> let binders_ast = List.map (fun (export,idl,ty) -> if not (Option.is_empty export) then user_err Pp.(str "Arguments of a functor definition can be imported only if the definition is interactive. Remove the \"Export\" and \"Import\" keywords from every functor argument.") else (idl,ty)) binders_ast in let mp, args, expr, sign = Declaremods.Synterp.declare_modtype id binders_ast mty_sign mty_ast_l in args, [], expr, sign let synterp_declare_module export {loc;v=id} binders_ast mty_ast = let binders_ast = List.map (fun (export,idl,ty) -> if not (Option.is_empty export) then user_err Pp.(str "Arguments of a functor declaration cannot be exported. Remove the \"Export\" and \"Import\" keywords from every functor argument.") else (idl,ty)) binders_ast in let mp, args, expr, sign = Declaremods.Synterp.declare_module id binders_ast (Declaremods.Enforce mty_ast) [] in assert (List.is_empty expr); let sign = match sign with Declaremods.Enforce x -> x | _ -> assert false in let export = Option.map (on_snd synterp_import_cats) export in Option.iter (fun export -> ignore @@ synterp_import_mod export (qualid_of_ident id) ImportAll) export; mp, export, args, sign let synterp_include l = Declaremods.Synterp.declare_include l let synterp_end_module export {loc;v=id} = let _ = Declaremods.Synterp.end_module () in Option.map (fun export -> synterp_import_mod export (qualid_of_ident ?loc id) ImportAll) export let synterp_end_section {CAst.loc; v} = Dumpglob.dump_reference ?loc (DirPath.to_string (Lib.current_dirpath true)) "<>" "sec"; Declaremods.Synterp.close_section () let synterp_end_segment ({v=id;loc} as lid) = let ss = Lib.Synterp.find_opening_node ?loc id in match ss with | Lib.OpenedModule (false,export,_,_) -> ignore (synterp_end_module export lid) | Lib.OpenedModule (true,_,_,_) -> ignore (Declaremods.Synterp.end_modtype ()) | Lib.OpenedSection _ -> synterp_end_section lid | _ -> assert false let err_unmapped_library ?from qid = let prefix = match from with | None -> mt () | Some from -> str " with prefix " ++ DirPath.print from in strbrk "Cannot find a physical path bound to logical path " ++ pr_qualid qid ++ prefix ++ str "." let err_notfound_library ?from qid = let prefix = match from with | None -> mt () | Some from -> str " with prefix " ++ DirPath.print from in let bonus = if !Loadpath.load_vos_libraries then mt () else str " (while searching for a .vos file)" in strbrk "Unable to locate library " ++ pr_qualid qid ++ prefix ++ bonus ++ str "." exception UnmappedLibrary of Names.DirPath.t option * Libnames.qualid exception NotFoundLibrary of Names.DirPath.t option * Libnames.qualid let _ = CErrors.register_handler begin function | UnmappedLibrary (from, qid) -> Some (err_unmapped_library ?from qid) | NotFoundLibrary (from, qid) -> Some (err_notfound_library ?from qid) | _ -> None end let warn_deprecated_from_Coq = CWarnings.create ~name:"deprecated-from-Coq" ~category:Deprecation.Version.v9_0 ~quickfix:(fun ~loc qid -> [Quickfix.make ~loc (Libnames.pr_qualid qid)]) (fun (_qid : qualid) -> strbrk "\"From Coq\" has been replaced by \"From Stdlib\".") let deprecated_Coq from qidl = let coq_id = Id.of_string "Coq" in let stdlib_id = (* temporary hack to enable HoTT and UniMath to compile with rocq-core *) let qidl = let qid2idl qid = let p, id = Libnames.repr_qualid qid in List.rev (id :: DirPath.repr p) in let from = match from with None -> [] | Some from -> qid2idl from in List.map (fun (qid, _) -> from @ qid2idl qid) qidl in let ids' = List.map Id.of_string ["Init"; "Setoids"; "Ltac"] in let in_rocq idl = match idl with | id :: id' :: _ -> Id.equal id coq_id && (CList.mem_f Id.equal id' ids') | _ -> false in Id.of_string (if List.for_all in_rocq qidl then "Corelib" else "Stdlib") in let repl_id id = if Id.equal id coq_id then true, stdlib_id else false, id in let repl_Coq_qid qid = let p, id = Libnames.repr_qualid qid in let warn, p, id = if DirPath.is_empty p then let w, id = repl_id id in w, p, id else let warn, p = match List.rev (DirPath.repr p) with | id :: p' -> let w, id' = repl_id id in w, (id' :: p') | [] -> false, [] in warn, DirPath.make (List.rev p), id in let qid = Libnames.make_qualid ?loc:qid.loc p id in let warn = if warn then Some qid else None in warn, Libnames.make_qualid ?loc:qid.loc p id in let warn, from, qidl = match from with | Some from -> let w, from = repl_Coq_qid from in w, Some from, qidl | None -> let w, qidl = CList.fold_left_map (fun w (qid, fe) -> let w', qid = repl_Coq_qid qid in Option.append w w', (qid, fe)) None qidl in w, from, qidl in let () = warn |> Option.iter (fun qid -> warn_deprecated_from_Coq ?loc:qid.loc qid) in from, qidl let synterp_require ~intern from export qidl = let from, qidl = deprecated_Coq from qidl in let root = match from with | None -> None | Some from -> let (hd, tl) = Libnames.repr_qualid from in Some (Libnames.add_dirpath_suffix hd tl) in let locate (qid,_) = let open Loadpath in match locate_qualified_library ?root qid with | Ok (dir,_) -> (qid.loc, dir) | Error LibUnmappedDir -> Loc.raise ?loc:qid.loc (UnmappedLibrary (root, qid)) | Error LibNotFound -> Loc.raise ?loc:qid.loc (NotFoundLibrary (root, qid)) in let modrefl = List.map locate qidl in Coq_config.gc_ramp_up @@ fun () -> let filenames = Library.require_library_syntax_from_dirpath ~intern modrefl in Option.iter (fun (export,cats) -> let cats = synterp_import_cats cats in List.iter2 (fun (_, m) (_, f) -> import_module_syntax_with_filter ~export cats (MPfile m) f) modrefl qidl) export; filenames, List.map snd modrefl (*****************************) (* Auxiliary file management *) let expand filename = Envars.expand_path_macros ~warn:(fun x -> Feedback.msg_warning (str x)) filename let synterp_declare_ml_module ~local l = let local = Option.default false local in Mltop.declare_ml_modules local l let warn_chdir = CWarnings.create ~name:"change-dir-deprecated" ~category:Deprecation.Version.v8_20 (fun () -> strbrk "Command \"Cd\" is deprecated." ++ spc () ++ strbrk "Use command-line \"-output-directory dir\" instead, or, alternatively, " ++ strbrk "for extraction, \"Set Extraction Output Directory\".") let synterp_chdir = function | None -> Feedback.msg_notice (str (Sys.getcwd())) | Some path -> warn_chdir (); begin try Sys.chdir (expand path) with Sys_error err -> (* Cd is typically used to control the output directory of extraction. A failed Cd could lead to overwriting .ml files so we make it an error. *) user_err Pp.(str ("Cd failed: " ^ err)) end; Flags.if_verbose Feedback.msg_info (str (Sys.getcwd())) (* External dependencies *) let synterp_extra_dep ?loc from file id = if Lib.sections_are_opened () then user_err ?loc Pp.(str "Extra Dependencies cannot be declared inside sections."); let hd, tl = Libnames.repr_qualid from in let from = Libnames.add_dirpath_suffix hd tl in ComExtraDeps.declare_extra_dep ?loc ~from ~file id let synterp_begin_section ({v=id} as lid) = Dumpglob.dump_definition lid true "sec"; Lib.Synterp.open_section id let with_synterp_state = let with_local_state () f = let st = Vernacstate.Synterp.freeze () in let v = f () in let transient_st = Vernacstate.Synterp.freeze () in Vernacstate.Synterp.unfreeze st; transient_st, v in { VernacControl.with_local_state } let rec synterp ~intern ?loc ~atts v = match v with | VernacSynterp v0 -> let e = begin match v0 with | VernacReservedNotation (infix, sl) -> with_module_locality ~atts synterp_reserved_notation ~infix sl; EVernacNoop | VernacNotation (infix,ntn_decl) -> let local, user_warns = Attributes.(parse Notations.(module_locality ++ user_warns) atts) in let decl = Metasyntax.add_notation_syntax ~local ~infix user_warns ntn_decl in EVernacNotation { local; decl } | VernacDeclareCustomEntry s -> with_module_locality ~atts synterp_custom_entry s; EVernacNoop | VernacDefineModule (export,lid,bl,mtys,mexprl) -> let export, args, argsexport, expr, sign = synterp_define_module export lid bl mtys mexprl in EVernacDefineModule (export,lid,args,argsexport,sign,expr) | VernacDeclareModuleType (lid,bl,mtys,mtyo) -> let args, argsexport, expr, sign = synterp_declare_module_type_syntax lid bl mtys mtyo in EVernacDeclareModuleType (lid,args,argsexport,sign,expr) | VernacDeclareModule (export,lid,bl,mtyo) -> let mp, export, args, sign = synterp_declare_module export lid bl mtyo in EVernacDeclareModule (export,lid,args,sign) | VernacInclude in_asts -> EVernacInclude (synterp_include in_asts) | VernacBeginSection lid -> synterp_begin_section lid; EVernacBeginSection lid | VernacEndSegment lid -> synterp_end_segment lid; EVernacEndSegment lid | VernacRequire (from, export, qidl) -> let needed, modrefl = synterp_require ~intern from export qidl in EVernacRequire (needed, modrefl, export, qidl) | VernacImport (export,qidl) -> let export, mpl = synterp_import export qidl in EVernacImport (export,mpl) | VernacDeclareMLModule l -> let f = with_locality ~atts synterp_declare_ml_module l in EVernacDeclareMLModule f | VernacChdir s -> unsupported_attributes atts; synterp_chdir s; EVernacNoop | VernacExtraDependency(from,file,id) -> unsupported_attributes atts; synterp_extra_dep ?loc from file id; EVernacNoop | VernacSetOption (export,key,value) -> let atts = if export then begin warn_legacy_export_set ?loc (); CAst.make ?loc ("export", VernacFlagEmpty) :: atts end else atts in let locality = parse option_locality atts in Vernacoptions.vernac_set_option ~locality ~stage:Summary.Stage.Synterp key value; EVernacSetOption { export; key; value } | VernacProofMode mn -> unsupported_attributes atts; EVernacNoop | VernacLoad (verbosely, fname) -> unsupported_attributes atts; synterp_load ~intern verbosely fname | VernacExtend (opn,args) -> let f = Vernacextend.type_vernac ?loc ~atts opn args () in EVernacExtend(f) end in VernacSynterp e | VernacSynPure x -> VernacSynPure x and synterp_load ~intern verbosely fname = let fname = Envars.expand_path_macros ~warn:(fun x -> Feedback.msg_warning (Pp.str x)) fname in let fname = CUnix.make_suffix fname ".v" in let input = let longfname = Loadpath.locate_file fname in let in_chan = Util.open_utf8_file_in longfname in Procq.Parsable.make ~loc:Loc.(initial (InFile { dirpath=None; file=longfname})) (Gramlib.Stream.of_channel in_chan) in (* Parsing loop *) let v_mod = if verbosely then Flags.verbosely else Flags.silently in let parse_sentence proof_mode = Procq.Entry.parse (Pvernac.main_entry proof_mode) in let proof_mode = Some (get_default_proof_mode ()) in let rec load_loop entries = match parse_sentence proof_mode input with | None -> entries | Some cmd -> let entry = v_mod (synterp_control ~intern) cmd in let st = Vernacstate.Synterp.freeze () in (load_loop [@ocaml.tailcall]) ((entry,st)::entries) in let entries = List.rev @@ load_loop [] in EVernacLoad(verbosely, entries) and synterp_control ~intern CAst.{ loc; v = cmd } = let fn expr = with_generic_atts ~check:true cmd.attrs (fun ~atts -> synterp ~intern ?loc ~atts cmd.expr) in let control, expr = VernacControl.under_control ~loc ~with_local_state:with_synterp_state (VernacControl.from_syntax cmd.control) ~noop:(VernacSynterp EVernacNoop) (fun () -> fn cmd.expr) in CAst.make ?loc { expr; control; attrs = cmd.attrs } let synterp_control ~intern cmd = Flags.with_modified_ref Flags.in_synterp_phase (fun _ -> Some true) (synterp_control ~intern) cmd rocq-9.2.0/vernac/synterp.mli000066400000000000000000000074171516144147600161750ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (local:bool option -> 'a) -> 'a val with_module_locality : atts:Attributes.vernac_flags -> (module_local:bool -> 'a) -> 'a val with_generic_atts : check:bool -> Attributes.vernac_flags -> (atts:Attributes.vernac_flags -> 'a) -> 'a type module_entry = Modintern.module_struct_expr * Names.ModPath.t * Modintern.module_kind * Entries.inline type synterp_entry = | EVernacNoop | EVernacNotation of { local : bool; decl : Metasyntax.notation_interpretation_decl } | EVernacBeginSection of Names.lident | EVernacEndSegment of Names.lident | EVernacRequire of Library.library_t list * DirPath.t list * Vernacexpr.export_with_cats option * (qualid * Vernacexpr.import_filter_expr) list | EVernacImport of (Vernacexpr.export_flag * Libobject.open_filter) * (Names.ModPath.t CAst.t * Vernacexpr.import_filter_expr) list | EVernacDeclareMLModule of Mltop.interp_fun | EVernacDeclareModule of Lib.export * lident * Declaremods.module_params_expr * module_entry | EVernacDefineModule of Lib.export * lident * Declaremods.module_params_expr * ((Vernacexpr.export_flag * Libobject.open_filter) * Names.ModPath.t) list * module_entry Declaremods.module_signature * module_entry list | EVernacDeclareModuleType of lident * Declaremods.module_params_expr * ((Vernacexpr.export_flag * Libobject.open_filter) * Names.ModPath.t) list * module_entry list * module_entry list | EVernacInclude of Declaremods.module_expr list | EVernacSetOption of { export : bool; key : Goptions.option_name; value : Vernacexpr.option_setting } | EVernacLoad of Vernacexpr.verbose_flag * (vernac_control_entry * Vernacstate.Synterp.t) list | EVernacExtend of Vernactypes.typed_vernac and vernac_entry = synterp_entry Vernacexpr.vernac_expr_gen (** [vernac_control_entry] defines elaborated vernacular expressions, after the syntactic interpretation phase and before full interpretation *) and vernac_control_entry = (Vernacstate.Synterp.t VernacControl.control_entry, synterp_entry) Vernacexpr.vernac_control_gen_r CAst.t exception UnmappedLibrary of Names.DirPath.t option * Libnames.qualid exception NotFoundLibrary of Names.DirPath.t option * Libnames.qualid (** [synterp_require] performs the syntactic interpretation phase of `Require` commands *) val synterp_require : intern:Library.Intern.t -> Libnames.qualid option -> Vernacexpr.export_with_cats option -> (Libnames.qualid * Vernacexpr.import_filter_expr) list -> Library.library_t list * DirPath.t list (** [synterp_control] is the main entry point of the syntactic interpretation phase *) val synterp_control : intern:Library.Intern.t -> Vernacexpr.vernac_control -> vernac_control_entry (** Default proof mode set by `start_proof` *) val get_default_proof_mode : unit -> Pvernac.proof_mode rocq-9.2.0/vernac/tactic_option.ml000066400000000000000000000105211516144147600171450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* >= fun ((local,global),export) -> match local, global, export with | None, None, None -> return Default | Some (), Some (), _ -> CErrors.user_err Pp.(str "Cannot combine local and global.") | Some (), _, Some () -> CErrors.user_err Pp.(str "Cannot combine local and export.") | Some (), None, None -> return Local | None, Some (), None -> return Global | None, None, Some () -> return Export | None, Some (), Some () -> return GlobalAndExport let warn_default_locality = CWarnings.create ~name:"deprecated-tacopt-without-locality" ~category:Deprecation.Version.v8_17 Pp.(fun () -> strbrk "The default and global localities for this command outside \ sections are currently equivalent to the combination of the \ standard meaning of \"global\" (as described in the reference \ manual), \"export\" and re-exporting for every surrounding \ module. It will change to just \"global\" (with the meaning \ used by the \"Set\" command) in a future release." ++ fnl() ++ strbrk "To preserve the current meaning in a forward compatible way, \ use the attribute \"#[global,export]\" and repeat the command \ with just \"#[export]\" in any surrounding modules. If you \ are fine with the change of semantics, disable this warning.") let declare_tactic_option ?default name = let current_tactic : Gentactic.glob_generic_tactic option ref = Summary.ref default ~name:(name^"-default-tactic") in let set_current_tactic t = current_tactic := t in let cache (_, tac) = set_current_tactic tac in let load _ (local, tac) = match local with | Default | Global | GlobalAndExport -> set_current_tactic tac | Export -> () | Local -> assert false (* not allowed by classify *) in let import i (local, tac) = match local with | GlobalAndExport | Export -> if Int.equal i 1 then set_current_tactic tac | Default | Global -> set_current_tactic tac | Local -> assert false (* not allowed by classify *) in let classify (local, _) = match local with | Local -> Dispose | Default | Global | Export | GlobalAndExport -> Substitute in let subst (s, (local, tac)) = (local, Option.map (Gentactic.subst s) tac) in let input : tac_option_locality * Gentactic.glob_generic_tactic option -> obj = declare_object { (default_object name) with cache_function = cache; load_function = load; (* can't simple_open: crappy behaviour when superglobal *) open_function = filtered_open import; classify_function = classify; subst_function = subst} in let put ?loc local tac = let () = match local with | Default -> if not (Lib.sections_are_opened()) then warn_default_locality ?loc () | Local -> () | Export | Global | GlobalAndExport -> if Lib.sections_are_opened() then CErrors.user_err ?loc Pp.(str "This locality is not supported inside sections by this command.") in Lib.add_leaf (input (local, Some tac)) in let get () = match !current_tactic with | None -> Proofview.tclUNIT () | Some tac -> Gentactic.interp tac in let print () = match !current_tactic with | None -> Pp.str "" | Some tac -> let env = Global.env () in let sigma = Evd.from_env env in Gentactic.print_glob env sigma tac in put, get, print rocq-9.2.0/vernac/tactic_option.mli000066400000000000000000000017701516144147600173240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string -> (* put *) (?loc:Loc.t -> tac_option_locality -> Gentactic.glob_generic_tactic -> unit) * (* get *) (unit -> unit Proofview.tactic) * (* print *) (unit -> Pp.t) rocq-9.2.0/vernac/topfmt.ml000066400000000000000000000365311516144147600156300ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* pp_global_params -> unit * set the parameters of a formatter *) let set_gp ft gp = Format.pp_set_margin ft gp.margin ; Format.pp_set_max_indent ft gp.max_indent ; Format.pp_set_max_boxes ft gp.max_depth ; Format.pp_set_ellipsis_text ft gp.ellipsis let set_dflt_gp ft = set_gp ft dflt_gp let get_gp ft = { margin = Format.pp_get_margin ft (); max_indent = Format.pp_get_max_indent ft (); max_depth = Format.pp_get_max_boxes ft (); ellipsis = Format.pp_get_ellipsis_text ft () } (* with_fp : 'a pp_formatter_params -> Format.formatter * returns of formatter for given formatter functions *) let with_fp chan out_function flush_function = let ft = Format.make_formatter out_function flush_function in Format.pp_set_formatter_out_channel ft chan; ft (* Output on a channel ch *) let with_output_to ch = let ft = with_fp ch (output_substring ch) (fun () -> flush ch) in set_gp ft deep_gp; ft let std_ft = ref Format.std_formatter let _ = set_dflt_gp !std_ft let err_ft = ref Format.err_formatter let _ = set_gp !err_ft deep_gp let deep_ft = ref (with_output_to stdout) let _ = set_gp !deep_ft deep_gp (* For parametrization through vernacular *) let default = Format.pp_get_max_boxes !std_ft () let default_margin = Format.pp_get_margin !std_ft () let get_depth_boxes () = Some (Format.pp_get_max_boxes !std_ft ()) let set_depth_boxes v = let v = (match v with None -> default | Some v -> v) in Constrextern.set_max_depth (Some v); Format.pp_set_max_boxes !std_ft v let get_margin0 () = Format.pp_get_margin !std_ft () let () = Profile_tactic.set_get_printing_width get_margin0 let get_margin () = Some (get_margin0()) let set_margin v = let v = match v with None -> default_margin | Some v -> v in Format.pp_set_margin Format.str_formatter v; Format.pp_set_margin !std_ft v; Format.pp_set_margin !deep_ft v; Format.pp_set_margin !err_ft v; (* Heuristic, based on usage: the column on the right of max_indent column is 20% of width, capped to 30 characters *) let m = max (64 * v / 100) (v-30) in Format.pp_set_max_indent Format.str_formatter m; Format.pp_set_max_indent !std_ft m; Format.pp_set_max_indent !deep_ft m; Format.pp_set_max_indent !err_ft m (** Console display of feedback *) (** Default tags *) module Tag = struct let error = "message.error" let warning = "message.warning" let debug = "message.debug" end let msgnl_with fmt strm = pp_with fmt (strm ++ fnl ()); Format.pp_print_flush fmt () module Emacs = struct (* Special chars for emacs, to detect warnings inside goal output *) let quote_warning_start = "" let quote_warning_end = "" let quote_info_start = "" let quote_info_end = "" let quote_emacs q_start q_end msg = hov 0 (seq [str q_start; brk(0,0); msg; brk(0,0); str q_end]) let quote_warning = quote_emacs quote_warning_start quote_warning_end let quote_info = quote_emacs quote_info_start quote_info_end end let dbg_hdr = tag Tag.debug (str "Debug:") ++ spc () let info_hdr = mt () let warn_hdr = tag Tag.warning (str "Warning:") ++ spc () let err_hdr = tag Tag.error (str "Error:") ++ spc () let make_body quoter info ?pre_hdr ?(qf=[]) s = let main = hov 0 (info ++ s) in let main = match qf with | (_ :: _ as qf) when !Flags.test_mode -> v 0 (main ++ cut () ++ Quickfix.print qf) | _ -> main in pr_opt_no_spc (fun x -> x ++ fnl ()) pre_hdr ++ quoter main (* The empty quoter *) let noq x = x (* Generic logger *) let gen_logger dbg warn ?qf ?pre_hdr level msg = let open Feedback in match level with | Debug -> msgnl_with !std_ft (make_body dbg dbg_hdr ?pre_hdr ?qf msg) | Info -> msgnl_with !std_ft (make_body dbg info_hdr ?pre_hdr ?qf msg) | Notice -> msgnl_with !std_ft (make_body noq info_hdr ?pre_hdr ?qf msg) | Warning -> msgnl_with !err_ft (make_body warn warn_hdr ?pre_hdr ?qf msg) | Error -> msgnl_with !err_ft (make_body noq err_hdr ?pre_hdr ?qf msg) (** Standard loggers *) (* We provide a generic clear_log_backend callback for backends wanting to do cleanup after the print. *) let std_logger_cleanup = ref (fun () -> ()) let std_logger ?qf ?pre_hdr level msg = gen_logger (fun x -> x) (fun x -> x) ?qf ?pre_hdr level msg; !std_logger_cleanup () (** Color logging. Moved from Ppstyle, it may need some more refactoring *) (* Tag map for terminal style *) let default_tag_map () = let open Terminal in [ (* Local to console toplevel *) "message.error" , make ~bold:true ~fg_color:`WHITE ~bg_color:`RED () ; "message.warning" , make ~bold:true ~fg_color:`WHITE ~bg_color:`YELLOW () ; "message.debug" , make ~bold:true ~fg_color:`WHITE ~bg_color:`MAGENTA () ; "message.prompt" , make ~fg_color:`GREEN () (* Coming from the printer *) ; "constr.evar" , make ~fg_color:`LIGHT_BLUE () ; "constr.keyword" , make ~bold:true () ; "constr.type" , make ~bold:true ~fg_color:`YELLOW () ; "constr.notation" , make ~fg_color:`WHITE () (* ["constr"; "variable"] is not assigned *) ; "constr.reference" , make ~fg_color:`LIGHT_GREEN () ; "constr.path" , make ~fg_color:`LIGHT_MAGENTA () ; "module.definition", make ~bold:true ~fg_color:`LIGHT_RED () ; "module.keyword" , make ~bold:true () ; "tactic.keyword" , make ~bold:true () ; "tactic.primitive" , make ~fg_color:`LIGHT_GREEN () ; "tactic.string" , make ~fg_color:`LIGHT_RED () ; "diff.added" , make ~bg_color:(`RGB(0,141,0)) ~underline:true () ; "diff.removed" , make ~bg_color:(`RGB(170,0,0)) ~underline:true () ; "diff.added.bg" , make ~bg_color:(`RGB(0,91,0)) () ; "diff.removed.bg" , make ~bg_color:(`RGB(91,0,0)) () ] let tag_map = ref CString.Map.empty let init_tag_map styles = let set accu (name, st) = CString.Map.add name st accu in tag_map := List.fold_left set !tag_map styles let default_styles () = init_tag_map (default_tag_map ()) let set_emacs_print_strings () = let open Terminal in let diff = "diff." in List.iter (fun b -> let (name, attrs) = b in if CString.is_sub diff name 0 then tag_map := CString.Map.add name { attrs with prefix = Some (Printf.sprintf "<%s>" name); suffix = Some (Printf.sprintf "" name) } !tag_map) (CString.Map.bindings !tag_map) let parse_color_config str = let styles = Terminal.parse str in init_tag_map styles let dump_tags () = CString.Map.bindings !tag_map let empty = Terminal.make () let default_style = Terminal.reset_style let get_style tag = try CString.Map.find tag !tag_map with Not_found -> empty;; let get_open_seq tags = let style = List.fold_left (fun a b -> Terminal.merge a (get_style b)) default_style tags in Terminal.eval (Terminal.diff default_style style);; let get_close_seq tags = let style = List.fold_left (fun a b -> Terminal.merge a (get_style b)) default_style tags in Terminal.eval (Terminal.diff style default_style);; let diff_tag_stack = ref [] (* global, just like std_ft *) (** Not thread-safe. We should put a lock somewhere if we print from different threads. Do we? *) let make_style_stack () = (* Default tag is to reset everything *) let style_stack = ref [] in let peek () = match !style_stack with | [] -> default_style (* Anomalous case, but for robustness *) | st :: _ -> st in let open_tag = function | Format.String_tag tag -> let (tpfx, ttag) = split_tag tag in if tpfx = end_pfx then "" else let style = get_style ttag in (* Merge the current settings and the style being pushed. This allows restoring the previous settings correctly in a pop when both set the same attribute. Example: current settings have red FG, the pushed style has green FG. When popping the style, we should set red FG, not default FG. *) let style = Terminal.merge (peek ()) style in let diff = Terminal.diff (peek ()) style in style_stack := style :: !style_stack; if tpfx = start_pfx then diff_tag_stack := ttag :: !diff_tag_stack; Terminal.eval diff | _ -> Terminal.eval default_style in let close_tag = function | Format.String_tag tag -> let (tpfx, _) = split_tag tag in if tpfx = start_pfx then "" else begin if tpfx = end_pfx then diff_tag_stack := (match !diff_tag_stack with _ :: tl -> tl | [] -> []); match !style_stack with | [] -> (* Something went wrong, we fallback *) Terminal.eval default_style | cur :: rem -> style_stack := rem; if cur = (peek ()) then "" else if rem = [] then Terminal.reset else Terminal.eval (Terminal.diff cur (peek ())) end | _ -> Terminal.eval default_style in let clear () = style_stack := [] in open_tag, close_tag, clear let make_printing_functions () = let print_prefix ft = function | Format.String_tag tag -> let (tpfx, ttag) = split_tag tag in if tpfx <> end_pfx then let style = get_style ttag in (match style.Terminal.prefix with Some s -> Format.pp_print_as ft 0 s | None -> ()) | _ -> () in let print_suffix ft = function | Format.String_tag tag -> let (tpfx, ttag) = split_tag tag in if tpfx <> start_pfx then let style = get_style ttag in (match style.Terminal.suffix with Some s -> Format.pp_print_as ft 0 s | None -> ()) | _ -> () in print_prefix, print_suffix let init_output_fns () = let reopen_highlight = ref "" in let open Format in let fns = Format.pp_get_formatter_out_functions !std_ft () in let newline () = if !diff_tag_stack <> [] then begin let close = get_close_seq !diff_tag_stack in fns.out_string close 0 (String.length close); reopen_highlight := get_open_seq (List.rev !diff_tag_stack); end; fns.out_string "\n" 0 1 in let string s off n = if !reopen_highlight <> "" && String.trim (String.sub s off n) <> "" then begin fns.out_string !reopen_highlight 0 (String.length !reopen_highlight); reopen_highlight := "" end; fns.out_string s off n in let new_fns = { fns with out_string = string; out_newline = newline } in Format.pp_set_formatter_out_functions !std_ft new_fns;; let init_terminal_output ~color = let open_tag, close_tag, clear_tag = make_style_stack () in let print_prefix, print_suffix = make_printing_functions () in let tag_handler ft = { Format.mark_open_stag = open_tag; Format.mark_close_stag = close_tag; Format.print_open_stag = print_prefix ft; Format.print_close_stag = print_suffix ft; } in if color then (* Use 0-length markers *) begin std_logger_cleanup := clear_tag; init_output_fns (); Format.pp_set_mark_tags !std_ft true; Format.pp_set_mark_tags !err_ft true end else (* Use textual markers *) begin Format.pp_set_print_tags !std_ft true; Format.pp_set_print_tags !err_ft true end; Format.pp_set_formatter_stag_functions !std_ft (tag_handler !std_ft); Format.pp_set_formatter_stag_functions !err_ft (tag_handler !err_ft) (* Rules for emacs: - Debug/info: emacs_quote_info - Warning/Error: emacs_quote_err - Notice: unquoted *) let emacs_logger = gen_logger Emacs.quote_info Emacs.quote_warning (* This is specific to the toplevel *) type execution_phase = | ParsingCommandLine | Initialization | LoadingPrelude | LoadingRcFile | InteractiveLoop | CompilationPhase let default_phase = ref InteractiveLoop let in_phase ~phase f x = let op = !default_phase in default_phase := phase; try let res = f x in default_phase := op; res with exn -> let iexn = Exninfo.capture exn in default_phase := op; Exninfo.iraise iexn let pr_loc loc = Loc.pr loc ++ str ":" let pr_phase ?loc () = match !default_phase, loc with | LoadingRcFile, loc -> (* For when all errors go through feedback: str "While loading rcfile:" ++ Option.cata (fun loc -> fnl () ++ pr_loc loc) (mt ()) loc *) Option.map pr_loc loc | LoadingPrelude, 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, _ | CompilationPhase, _ -> None | InteractiveLoop, _ -> (* Note: interactive messages such as "foo is defined" are not located *) None let print_err_exn any = let (e, info) = Exninfo.capture any in let loc = Loc.get_loc info in let pre_hdr = pr_phase ?loc () in let msg = CErrors.iprint (e, info) ++ fnl () in std_logger ?pre_hdr Feedback.Error msg let with_output_to_file ~truncate fname func input = let fname = String.concat "." [fname; "out"] in let fullfname = System.get_output_path fname in System.mkdir (Filename.dirname fullfname); let channel = let flags = [Open_wronly; Open_creat; Open_text] in let flags = if truncate then Open_trunc :: flags else flags in open_out_gen flags 0o666 fullfname in let old_fmt = !std_ft, !err_ft, !deep_ft in let new_ft = Format.formatter_of_out_channel channel in set_gp new_ft (get_gp !std_ft); std_ft := new_ft; err_ft := new_ft; deep_ft := new_ft; try let output = func input in std_ft := Util.pi1 old_fmt; err_ft := Util.pi2 old_fmt; deep_ft := Util.pi3 old_fmt; Format.pp_print_flush new_ft (); close_out channel; output with reraise -> let reraise = Exninfo.capture reraise in std_ft := Util.pi1 old_fmt; err_ft := Util.pi2 old_fmt; deep_ft := Util.pi3 old_fmt; Format.pp_print_flush new_ft (); close_out channel; Exninfo.iraise reraise (* For coqtop -time, we display the position in the file, and a glimpse of the executed command *) let pr_cmd_header com = let shorten s = if Unicode.utf8_length s > 33 then (Unicode.utf8_sub s 0 30) ^ "..." else s in let noblank s = String.map (fun c -> match c with | ' ' | '\n' | '\t' | '\r' -> '~' | x -> x ) s in let (start,stop) = Option.cata Loc.unloc (0,0) com.CAst.loc in let safe_pr_vernac x = try Ppvernac.pr_vernac x with e -> str (Printexc.to_string e) in let cmd = noblank (shorten (string_of_ppcmds (safe_pr_vernac com))) in str "Chars " ++ int start ++ str " - " ++ int stop ++ str " [" ++ str cmd ++ str "] " rocq-9.2.0/vernac/topfmt.mli000066400000000000000000000052221516144147600157720ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* pp_global_params -> unit val set_dflt_gp : Format.formatter -> unit val get_gp : Format.formatter -> pp_global_params (** {6 Output functions of pretty-printing. } *) val with_output_to : out_channel -> Format.formatter val std_ft : Format.formatter ref val err_ft : Format.formatter ref val deep_ft : Format.formatter ref (** {6 For parametrization through vernacular. } *) val set_depth_boxes : int option -> unit val get_depth_boxes : unit -> int option val set_margin : int option -> unit val get_margin : unit -> int option (** Console display of feedback, we may add some location information *) val std_logger : ?qf:Quickfix.t list -> ?pre_hdr:Pp.t -> Feedback.level -> Pp.t -> unit val emacs_logger : ?qf:Quickfix.t list -> ?pre_hdr:Pp.t -> Feedback.level -> Pp.t -> unit (** Color output *) val default_styles : unit -> unit val parse_color_config : string -> unit val dump_tags : unit -> (string * Terminal.style) list val set_emacs_print_strings : unit -> unit (** Initialization of interpretation of tags *) val init_terminal_output : color:bool -> unit (** Error printing *) (* To be deprecated when we can fully move to feedback-based error printing. *) type execution_phase = | ParsingCommandLine | Initialization | LoadingPrelude | LoadingRcFile | InteractiveLoop | CompilationPhase val in_phase : phase:execution_phase -> ('a -> 'b) -> 'a -> 'b val pr_phase : ?loc:Loc.t -> unit -> Pp.t option val print_err_exn : exn -> unit (** [with_output_to_file ~truncate file f x] executes [f x] with logging redirected to a file [file] (starting empty if [truncate:true], otherwise appending if it already exists). *) val with_output_to_file : truncate:bool -> string -> ('a -> 'b) -> 'a -> 'b val pr_cmd_header : Vernacexpr.vernac_control -> Pp.t rocq-9.2.0/vernac/vernacControl.ml000066400000000000000000000246761516144147600171450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (* The error has to be printed in the failing state *) let _, info as exn = Exninfo.capture e in (* Don't catch async exceptions, don't turn anomalies into successes *) if CErrors.is_async e || CErrors.is_sync_anomaly e then Exninfo.iraise exn; Ok (Loc.get_loc info, CErrors.iprint exn) type ('st0,'st) with_local_state = { with_local_state : 'a. 'st0 -> (unit -> 'a) -> 'st * 'a } let trivial_state = { with_local_state = fun () f -> (), f () } let with_fail ~loc ~with_local_state st0 f = let transient_st, res = with_local_state.with_local_state st0 (fun () -> with_fail f) in match res with | Error v -> Some (ControlFail { st = transient_st }, v) | Ok (eloc, msg) -> let loc = if !Flags.test_mode then real_error_loc ~cmdloc:loc ~eloc else None in if not !Flags.quiet || !Flags.test_mode then Feedback.msg_notice ?loc Pp.(str "The command has indeed failed with message:" ++ fnl () ++ msg); None let with_succeed ~with_local_state st0 f = let transient_st, v = with_local_state.with_local_state st0 f in Some (ControlSucceed { st = transient_st }, v) let under_one_control ~loc ~with_local_state control f = match control with | ControlTime { duration } -> with_measure System.measure_duration System.duration_add System.fmt_transaction_result (fun duration -> ControlTime {duration}) duration f | ControlInstructions {instructions} -> with_measure System.count_instructions System.instruction_count_add System.fmt_instructions_result (fun instructions -> ControlInstructions {instructions}) instructions f | ControlProfile {to_file; profstate} -> with_measure measure_profile add_profile (fun v -> fmt_profile to_file v) (fun profstate -> ControlProfile {to_file; profstate}) profstate f | ControlRedirect { fname; truncate } -> let v = Topfmt.with_output_to_file ~truncate fname f () in Some (ControlRedirect {fname; truncate=false}, v) | ControlTimeout {remaining} -> with_timeout ~timeout:remaining f | ControlFail {st} -> with_fail ~loc ~with_local_state st f | ControlSucceed {st} -> with_succeed ~with_local_state st f let rec under_control ~loc ~with_local_state controls ~noop f = match controls with | [] -> [], f () | control :: rest -> let f () = under_control ~loc ~with_local_state rest ~noop f in match under_one_control ~loc ~with_local_state control f with | Some (control, (rest,v)) -> control :: rest, v | None -> [], noop let ignore_state = { with_local_state = fun _ f -> (), f () } let rec after_last_phase ~loc = function | [] -> false | control :: rest -> (* don't match on [control] before processing [rest]: correctly handle eg [Fail Fail]. *) let rest () = after_last_phase ~loc rest in match under_one_control ~loc ~with_local_state:ignore_state control rest with | None -> true | Some (control,noop) -> match control with | ControlTime {duration} -> Feedback.msg_notice @@ System.fmt_transaction_result (Ok ((),duration)); noop | ControlInstructions {instructions} -> Feedback.msg_notice @@ System.fmt_instructions_result (Ok ((),instructions)); noop | ControlProfile {to_file; profstate} -> Feedback.msg_notice @@ fmt_profile to_file (Ok ((),profstate)); noop | ControlRedirect _ -> noop | ControlTimeout _ -> noop | ControlFail _ -> CErrors.user_err Pp.(str "The command has not failed!") | ControlSucceed _ -> true (** A global default timeout, controlled by option "Set Default Timeout n". Use "Unset Default Timeout" to deactivate it. *) let default_timeout = ref None let check_timeout n = if n <= 0 then CErrors.user_err Pp.(str "Timeout must be > 0.") let () = let open Goptions in declare_int_option { optstage = Summary.Stage.Synterp; optdepr = None; optkey = ["Default";"Timeout"]; optread = (fun () -> !default_timeout); optwrite = (fun n -> Option.iter check_timeout n; default_timeout := n) } let has_timeout ctrl = ctrl |> List.exists (function | { CAst.v = Vernacexpr.ControlTimeout _ } -> true | _ -> false) let add_default_timeout control = match !default_timeout with | None -> control | Some n -> if has_timeout control then control else CAst.make (Vernacexpr.ControlTimeout n) :: control let from_syntax_one : Vernacexpr.control_flag -> unit control_entry = fun flag -> match flag.v with | ControlTime -> ControlTime { duration = System.empty_duration } | ControlInstructions -> ControlInstructions { instructions = Ok 0L } | ControlProfile to_file -> ControlProfile {to_file; profstate = empty_profstate} | ControlRedirect s -> ControlRedirect { fname = s; truncate = true } | ControlTimeout timeout -> (* don't check_timeout here as the error won't be caught by surrounding Fail *) ControlTimeout { remaining = float_of_int timeout } | ControlFail -> ControlFail { st = () } | ControlSucceed -> ControlSucceed { st = () } let from_syntax control = List.map from_syntax_one (add_default_timeout control) rocq-9.2.0/vernac/vernacControl.mli000066400000000000000000000040741516144147600173040ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* (unit -> 'a) -> 'st * 'a } (** [with_local_state state0 f] should run [f] with [state0] installed, capture the state produced by running [f] and revert the global state afterwards. *) val trivial_state : (unit,unit) with_local_state (** [under_control ~loc ~with_local_state control ~noop f] runs [f ()] in the context given by the [control]. If the [control] cause execution to end with no more work to be done and no error (eg [Fail] when [f] raised an exception) then [noop] is returned. *) val under_control : loc:Loc.t option -> with_local_state:('state0,'state) with_local_state -> 'state0 control_entries -> noop:'b -> (unit -> 'b) -> 'state control_entries * 'b (** Print any final messages (eg from [Time]) and raise final exceptions (eg from [Fail] when the command did not fail). The returned boolean tells if we should be noop ([Fail] where the command failed or [Succeed] where it succeeded). *) val after_last_phase : loc:Loc.t option -> _ control_entries -> bool (** Exposed so that waterproof can change the error message. *) exception CmdTimeout rocq-9.2.0/vernac/vernac_classifier.ml000066400000000000000000000237121516144147600177760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* "Later" | VtNow -> "Now" let string_of_vernac_classification = function | VtStartProof _ -> "StartProof" | VtSideff (_,w) -> "Sideff"^" "^(string_of_vernac_when w) | VtQed (VtKeep VtKeepAxiom) -> "Qed(admitted)" | VtQed (VtKeep (VtKeepOpaque | VtKeepDefined)) -> "Qed(keep)" | VtQed VtDrop -> "Qed(drop)" | VtProofStep { proof_block_detection } -> "ProofStep " ^ Option.default "" proof_block_detection | VtQuery -> "Query" | VtMeta -> "Meta " | VtProofMode _ -> "Proof Mode" let vtkeep_of_opaque = function | Opaque -> VtKeepOpaque | Transparent -> VtKeepDefined let idents_of_name : Names.Name.t -> Names.Id.t list = function | Names.Anonymous -> [] | Names.Name n -> [n] 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; Pvernac.proof_mode_opt_name; Attributes.program_mode_option_name; Proof_using.proof_using_opt_name; ] let classify_vernac e = let static_synterp_classifier ~atts e = match e with (* Univ poly compatibility: we run it now, so that we can just * look at Flags in stm.ml. Would be nicer to have the stm * look at the entire dag to detect this option. *) | VernacSetOption (_, l,_) when CList.exists (CList.equal String.equal l) options_affecting_stm_scheduling -> VtSideff ([], VtNow) | VernacBeginSection {v=id} -> VtSideff ([id], VtLater) | VernacChdir _ | VernacExtraDependency _ | VernacSetOption _ -> VtSideff ([], VtLater) (* (Local) Notations have to disappear *) | VernacEndSegment _ -> VtSideff ([], VtNow) (* Modules with parameters have to be executed: can import notations *) | VernacDeclareModule (exp,{v=id},bl,_) | VernacDefineModule (exp,{v=id},bl,_,_) -> VtSideff ([id], if bl = [] && exp = None then VtLater else VtNow) | VernacDeclareModuleType ({v=id},bl,_,_) -> VtSideff ([id], if bl = [] then VtLater else VtNow) (* These commands alter the parser *) | VernacDeclareCustomEntry _ | VernacNotation _ | VernacReservedNotation _ | VernacRequire _ | VernacImport _ | VernacInclude _ | VernacDeclareMLModule _ -> VtSideff ([], VtNow) | VernacProofMode pm -> (match Pvernac.lookup_proof_mode pm with | None -> CErrors.user_err Pp.(str (Format.sprintf "No proof mode named \"%s\"." pm)) | Some proof_mode -> VtProofMode proof_mode) (* Plugins should classify their commands *) | VernacLoad _ -> VtSideff ([], VtNow) | VernacExtend (s,l) -> try Vernacextend.get_vernac_classifier s ~atts l with Not_found -> anomaly(str"No classifier for"++spc()++str s.ext_entry ++str".") in let static_pure_classifier ~atts e = match e with (* Qed *) | VernacAbort -> VtQed VtDrop | VernacEndProof Admitted -> VtQed (VtKeep VtKeepAxiom) | VernacEndProof (Proved (opaque,_)) -> VtQed (VtKeep (vtkeep_of_opaque opaque)) | VernacExactProof _ -> VtQed (VtKeep VtKeepOpaque) (* Query *) | VernacShow _ | VernacPrint _ | VernacSearch _ | VernacLocate _ | VernacCheckGuard | VernacValidateProof | VernacGlobalCheck _ | VernacCheckMayEval _ -> VtQuery (* ProofStep *) | VernacProof _ | VernacFocus _ | VernacUnfocus | VernacSubproof _ | VernacUnfocused | VernacBullet _ -> VtProofStep { proof_block_detection = Some "bullet" } | VernacEndSubproof -> VtProofStep { proof_block_detection = Some "curly" } (* StartProof *) | VernacDefinition ((DoDischarge,_),({v=i},_),ProveBody _) -> VtStartProof(Doesn'tGuaranteeOpacity, idents_of_name i) | VernacDefinition (_,({v=i},_),ProveBody _) -> let polymorphic = Attributes.(parse_drop_extra polymorphic atts) in let guarantee = if polymorphic then Doesn'tGuaranteeOpacity else GuaranteesOpacity in VtStartProof(guarantee, idents_of_name i) | VernacStartTheoremProof (_,l) -> let polymorphic = Attributes.(parse_drop_extra polymorphic atts) in let ids = List.map (fun (({v=i}, _), _) -> i) l in let guarantee = if polymorphic then Doesn'tGuaranteeOpacity else GuaranteesOpacity in VtStartProof (guarantee,ids) | VernacFixpoint (discharge,(_,l)) -> let refine, polymorphic = Attributes.(parse_drop_extra Notations.(Classes.refine_att ++ polymorphic) atts) in let guarantee = if discharge = DoDischarge || polymorphic || refine then Doesn'tGuaranteeOpacity else GuaranteesOpacity in let ids, open_proof = List.fold_left (fun (l,b) {Vernacexpr.fname={CAst.v=id}; body_def} -> id::l, b || body_def = None) ([],refine) l in if open_proof then VtStartProof (guarantee,ids) else VtSideff (ids, VtLater) | VernacCoFixpoint (discharge,l) -> let refine, polymorphic = Attributes.(parse_drop_extra Notations.(Classes.refine_att ++ polymorphic) atts) in let guarantee = if discharge = DoDischarge || polymorphic || refine then Doesn'tGuaranteeOpacity else GuaranteesOpacity in let ids, open_proof = List.fold_left (fun (l,b) { Vernacexpr.fname={CAst.v=id}; body_def } -> id::l, b || body_def = None) ([],refine) l in if open_proof then VtStartProof (guarantee,ids) 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) | VernacSymbol 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 _) -> let refine = Attributes.(parse_drop_extra Classes.refine_att atts) in if refine then (* Type may still be an evar *) VtStartProof (Doesn'tGuaranteeOpacity, idents_of_name id) else VtSideff (idents_of_name id, VtLater) | VernacInductive (_,l) -> let ids = List.map (fun (((_,({v=id},_)),_,_,cl),_) -> id :: match cl with | Constructors l -> List.map (fun (_,({v=id},_)) -> id) l | RecordDecl (oid,l,obinder) -> (match oid with Some {v=x} -> [x] | _ -> []) @ (match obinder with Some {v=x} -> [x] | _ -> []) @ CList.map_filter (function | AssumExpr({v=Names.Name n},_,_), _ -> Some n | _ -> None) l) l in VtSideff (List.flatten ids, VtLater) | VernacScheme l -> let ids = List.map (fun {v}->v) (CList.map_filter (fun (x,_) -> x) l) in VtSideff (ids, VtLater) | VernacCombinedScheme ({v=id},_) -> VtSideff ([id], VtLater) | VernacUniverse _ | VernacSort _ | VernacConstraint _ | VernacCanonical _ | VernacCoercion _ | VernacIdentityCoercion _ | VernacCreateHintDb _ | VernacRemoveHints _ | VernacHints _ | VernacArguments _ | VernacReserve _ | VernacGeneralizable _ | VernacSetOpacity _ | VernacSetStrategy _ | VernacAddOption _ | VernacRemoveOption _ | VernacMemOption _ | VernacPrintOption _ | VernacDeclareReduction _ | VernacExistingClass _ | VernacExistingInstance _ | VernacRegister _ | VernacNameSectionHypSet _ | VernacComments _ | VernacAttributes _ | VernacSchemeEquality _ | VernacSchemeAll _ | VernacAddRewRule _ | VernacDeclareInstance _ -> VtSideff ([], VtLater) (* Who knows *) | VernacOpenCloseScope _ | VernacDeclareScope _ | VernacDelimiters _ | VernacBindScope _ | VernacEnableNotation _ | VernacAbbreviation _ | VernacContext _ (* TASSI: unsure *) -> VtSideff ([], VtNow) | VernacInstance ((name,_),_,_,props,_) -> let program, refine = Attributes.(parse_drop_extra Notations.(program ++ Classes.refine_att) atts) in if program || (props <> None && not refine) then VtSideff (idents_of_name name.CAst.v, VtLater) else let polymorphic = Attributes.(parse_drop_extra polymorphic atts) in let guarantee = if polymorphic then Doesn'tGuaranteeOpacity else GuaranteesOpacity in VtStartProof (guarantee, idents_of_name name.CAst.v) (* Stm will install a new classifier to handle these *) | VernacBack _ | VernacAbortAll | VernacUndoTo _ | VernacUndo _ | VernacResetName _ | VernacResetInitial | VernacRestart -> VtMeta in let static_classifier ~atts e = match e with | VernacSynPure e -> static_pure_classifier ~atts e | VernacSynterp e -> static_synterp_classifier ~atts e in let static_control_classifier ({ CAst.v ; _ } as cmd) = (* Fail Qed or Fail Lemma must not join/fork the DAG *) (* XXX why is Fail not always Query? *) if Vernacprop.has_query_control cmd then (match static_classifier ~atts:v.attrs v.expr with | VtQuery | VtProofStep _ | VtSideff _ | VtMeta as x -> x | VtQed _ -> VtProofStep { proof_block_detection = None } | VtStartProof _ | VtProofMode _ -> VtQuery) else static_classifier ~atts:v.attrs v.expr in static_control_classifier e rocq-9.2.0/vernac/vernac_classifier.mli000066400000000000000000000016471516144147600201520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* string (** What does a vernacular do *) val classify_vernac : Vernacexpr.vernac_control -> vernac_classification (** *) val stm_allow_nested_proofs_option_name : string list rocq-9.2.0/vernac/vernacentries.ml000066400000000000000000003366521516144147600171760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* let env = Global.env () in Evd.(from_env env, env) | Some p -> Declare.Proof.get_current_context p let get_goal_or_global_context ~pstate glnum = match pstate with | None -> let env = Global.env () in Evd.(from_env env, env) | Some p -> Declare.Proof.get_goal_context p glnum let cl_of_qualid = function | FunClass -> Coercionops.CL_FUN | SortClass -> Coercionops.CL_SORT | RefClass r -> ComCoercion.class_of_global (Smartlocate.smart_global ~head:true r) let scope_class_of_qualid qid = Notation.scope_class_of_class (cl_of_qualid qid) (** Standard attributes for definition-like commands. *) module DefAttributes = struct type t = { hooks : Declare.Hook.t list ; scope : definition_scope; locality : bool option; poly : PolyFlags.t; program : bool; user_warns : Globnames.extended_global_reference UserWarn.with_qf option; canonical_instance : bool; typing_flags : Declarations.typing_flags option; using : Vernacexpr.section_subset_expr option; reversible : bool; clearbody: bool option; } (* [locality] is used for [vernac_definition_hook], the raw Local/Global attribute is also used to generate [scope]. [locality] can't be computed back from [scope] because [Let Coercion] outside section generates [locality = None] but [scope = Global ImportNeedQualified] (which is otherwise associated with [locality = Some true]). Since [Let] (ie discharge = DoDischarge) does not allow explicit locality we could alternatively decide to change the default locality of the coercion from out-of-section [Let Coercion]. *) module Observer = Summary.MakeObservable (struct type value = Declare.Hook.t list attribute let local = false let stage = Summary.Stage.Interp let name = "Definition attribute" end) let active_hooks () : Declare.Hook.t list attribute = let module AttList = Monad.Make(Attributes.Notations) in let active = Observer.all_active () in let open Attributes.Notations in AttList.List.map snd active >>= fun res -> return (List.concat res) let importability_of_bool = function | true -> ImportNeedQualified | false -> ImportDefaultBehavior let warn_declaration_outside_section = CWarnings.create ~name:"declaration-outside-section" ~category:CWarnings.CoreCategories.vernacular ~default:CWarnings.AsError Pp.(fun (unexpected_thing, replacement) -> strbrk "Use of " ++ str unexpected_thing ++ strbrk " outside sections behaves as " ++ str replacement ++ str ".") let scope_of_locality locality_flag discharge deprecated_thing replacement : definition_scope = let open Vernacexpr in match locality_flag, discharge with | Some b, NoDischarge -> Global (importability_of_bool b) | None, NoDischarge -> Global ImportDefaultBehavior | None, DoDischarge when not (Lib.sections_are_opened ()) -> (* If a Let/Variable is defined outside a section, then we consider it as a local definition *) warn_declaration_outside_section (deprecated_thing, replacement); Global ImportNeedQualified | None, DoDischarge -> Discharge | Some true, DoDischarge -> CErrors.user_err Pp.(str "Local not allowed in this case") | Some false, DoDischarge -> CErrors.user_err Pp.(str "Global not allowed in this case") open Attributes open Attributes.Notations let clearbody = bool_attribute ~name:"clearbody" (* [XXX] EJGA: coercion is unused here *) let def_attributes_gen ?(coercion=false) ?(discharge=NoDischarge,"","") () = let discharge, deprecated_thing, replacement = discharge in let clearbody = match discharge with DoDischarge -> clearbody | NoDischarge -> return None in (* It is important because it prevents early evaluation of [active_hooks ()] *) return () >>= fun () -> (locality ++ user_warns_with_use_globref_instead ++ poly PolyFlags.Definition ++ program ++ canonical_instance ++ typing_flags ++ using ++ reversible ++ clearbody ++ active_hooks ()) >>= fun (((((((((locality, user_warns), poly), program), canonical_instance), typing_flags), using), reversible), clearbody), hooks) -> let using = Option.map Proof_using.using_from_string using in let reversible = Option.default false reversible in let () = if Option.has_some clearbody && not (Lib.sections_are_opened()) then CErrors.user_err Pp.(str "Cannot use attribute clearbody outside sections.") in let scope = scope_of_locality locality discharge deprecated_thing replacement in return { hooks; scope; locality; poly; program; user_warns; canonical_instance; typing_flags; using; reversible; clearbody } let parse ?coercion ?discharge f (* : DefAttributes.t *) = Attributes.parse (def_attributes_gen ?coercion ?discharge ()) f let def_attributes = def_attributes_gen () end let with_def_attributes ?coercion ?discharge ~atts f = let atts = DefAttributes.parse ?coercion ?discharge atts in if atts.DefAttributes.program then Declare.Obls.check_program_libraries (); f ~atts let with_section_locality ~atts f = let local = Attributes.(parse locality atts) in let section_local = make_section_locality local in f ~section_local (*******************) (* "Show" commands *) let show_proof ~pstate = (* spiwack: this would probably be cooler with a bit of polishing. *) try let pstate = match pstate with None -> raise Exit | Some s -> s in let p = Declare.Proof.get pstate in let sigma, _ = Declare.Proof.get_current_context pstate in let pprf = Proof.partial_proof p in (* In the absence of an environment explicitly attached to the proof and on top of which side effects of the proof would be pushed, , we take the global environment which in practise should be a superset of the initial environment in which the proof was started *) let env = Global.env() in Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf (* We print nothing if there are no goals left *) with | Proof.NoSuchGoal _ | Exit -> user_err (str "No goals to show.") let show_top_evars ~proof = (* spiwack: new as of Feb. 2010: shows goal evars in addition to non-goal evars. *) let Proof.{goals; sigma} = Proof.data proof in let shelf = Evd.shelf sigma in let given_up = Evar.Set.elements @@ Evd.given_up sigma in pr_evars_int sigma ~shelf ~given_up 1 (Evd.undefined_map sigma) let show_universes ~proof = let Proof.{goals;sigma} = Proof.data proof in let ctx = Evd.sort_context_set (Evd.minimize_universes sigma) in UState.pr (Evd.ustate sigma) ++ fnl () ++ v 1 (str "Normalized constraints:" ++ cut() ++ UnivGen.pr_sort_context (Termops.pr_evd_qvar sigma) (Termops.pr_evd_level sigma) ctx) (* Simulate the Intro(s) tactic *) let show_intro ~proof all = let open EConstr in let Proof.{goals;sigma} = Proof.data proof in if not (List.is_empty goals) then begin let evi = Evd.find_undefined sigma (List.hd goals) in let env = Evd.evar_filtered_env (Global.env ()) evi in let l,_= decompose_prod_decls sigma (Termops.strip_outer_cast sigma (Evd.evar_concl evi)) in if all then let lid = Tactics.find_intro_names env sigma l in hov 0 (prlist_with_sep spc Id.print lid) else if not (List.is_empty l) then let n = List.last l in Id.print (List.hd (Tactics.find_intro_names env sigma [n])) else mt () end else mt () (** Textual display of a generic "match" template *) let show_match id = let patterns = try ComInductive.make_cases (Nametab.global_inductive id) with Not_found -> user_err Pp.(str "Unknown inductive type.") in let pr_branch l = str "| " ++ hov 1 (prlist_with_sep spc str l) ++ str " =>" in v 1 (str "match # with" ++ fnl () ++ prlist_with_sep fnl pr_branch patterns ++ fnl () ++ str "end" ++ fnl ()) (* "Print" commands *) let print_loadpath dir = let l = Loadpath.get_load_paths () in let l = match dir with | None -> l | Some dir -> let filter p = is_dirpath_prefix_of dir (Loadpath.logical p) in List.filter filter l in str "Installed / Logical Path / Physical path:" ++ fnl () ++ prlist_with_sep fnl Loadpath.pp l let print_libraries () = let loaded = Library.loaded_libraries () in str"Loaded library files: " ++ pr_vertical_list DirPath.print loaded let print_module qid = match Nametab.locate_module qid with | mp -> Printmod.print_module ~with_body:true mp | exception Not_found -> user_err (str"Unknown Module " ++ pr_qualid qid ++ str".") let print_modtype qid = try let kn = Nametab.locate_modtype qid in Printmod.print_modtype kn with Not_found -> (* Is there a module of this name ? If yes we display its type *) try let mp = Nametab.locate_module qid in Printmod.print_module ~with_body:false mp with Not_found -> user_err (str"Unknown Module Type or Module " ++ pr_qualid qid ++ str".") let print_namespace ~pstate ns = let ns = List.rev (Names.DirPath.repr ns) in (* [match_dirpath], [match_modulpath] are helpers for [matches] which checks whether a constant is in the namespace [ns]. *) let rec match_dirpath ns = function | [] -> Some ns | id::dir -> begin match match_dirpath ns dir with | Some [] as y -> y | Some (a::ns') -> if Names.Id.equal a id then Some ns' else None | None -> None end in let rec match_modulepath ns = function | MPbound _ -> None (* Not a proper namespace. *) | MPfile dir -> match_dirpath ns (Names.DirPath.repr dir) | MPdot (mp,id) -> begin match match_modulepath ns mp with | Some [] as y -> y | Some (a::ns') -> if Names.Id.equal a id then Some ns' else None | None -> None end in (* [qualified_minus n mp] returns a list of qualifiers representing [mp] except the [n] first (in the concrete syntax order). The idea is that if [mp] matches [ns], then [qualified_minus mp (length ns)] will be the correct representation of [mp] assuming [ns] is imported. *) (* precondition: [mp] matches some namespace of length [n] *) let qualified_minus n mp = let rec list_of_modulepath = function | MPbound _ -> assert false (* MPbound never matches *) | MPfile dir -> Names.DirPath.repr dir | MPdot (mp,lbl) -> lbl::(list_of_modulepath mp) in snd (Util.List.chop n (List.rev (list_of_modulepath mp))) in let print_list pr l = prlist_with_sep (fun () -> str".") pr l in let print_kn kn = let (mp,lbl) = Names.KerName.repr kn in let qn = (qualified_minus (List.length ns) mp)@[lbl] in print_list Id.print qn in let print_constant ~pstate k body = (* FIXME: universes *) let t = body.Declarations.const_type in let sigma, env = get_current_or_global_context ~pstate in print_kn k ++ str":" ++ spc() ++ Printer.pr_type_env env sigma t in let matches mp = match match_modulepath ns mp with | Some [] -> true | _ -> false in let constants_in_namespace = Environ.fold_constants (fun c body acc -> let kn = Constant.user c in if matches (KerName.modpath kn) then acc++fnl()++hov 2 (print_constant ~pstate kn body) else acc) (Global.env ()) (str"") in (print_list Id.print ns)++str":"++fnl()++constants_in_namespace let print_strategy r = let open Conv_oracle in let pr_level = function | Expand -> str "expand" | Level 0 -> str "transparent" | Level n -> str "level" ++ spc() ++ int n | Opaque -> str "opaque" in let pr_strategy (ref, lvl) = pr_global ref ++ str " : " ++ pr_level lvl in let oracle = Environ.oracle (Global.env ()) in match r with | None -> let fold key lvl (vacc, cacc, pacc) = match key with | Conv_oracle.EvalVarRef id -> ((GlobRef.VarRef id, lvl) :: vacc, cacc, pacc) | Conv_oracle.EvalConstRef cst -> (vacc, (GlobRef.ConstRef cst, lvl) :: cacc, pacc) | Conv_oracle.EvalProjectionRef p -> (vacc, cacc, (GlobRef.ConstRef (Projection.Repr.constant p), lvl) :: pacc) in let var_lvl, cst_lvl, prj_lvl = fold_strategy fold oracle ([], [], []) in let var_msg = if List.is_empty var_lvl then mt () else str "Variable strategies" ++ fnl () ++ hov 0 (prlist_with_sep fnl pr_strategy var_lvl) ++ fnl () in let cst_msg = if List.is_empty cst_lvl then mt () else str "Constant strategies" ++ fnl () ++ hov 0 (prlist_with_sep fnl pr_strategy cst_lvl) in let prj_msg = if List.is_empty prj_lvl then mt () else str "Projection strategies" ++ fnl () ++ hov 0 (prlist_with_sep fnl pr_strategy prj_lvl) in var_msg ++ cst_msg ++ prj_msg | Some r -> let r = Smartlocate.smart_global r in let key = let open GlobRef in match r with | VarRef id -> Evaluable.EvalVarRef id | ConstRef cst -> Evaluable.EvalConstRef cst | IndRef _ | ConstructRef _ -> user_err Pp.(str "The reference is not unfoldable.") in let lvl = get_strategy oracle (Evaluable.to_kevaluable key) in pr_strategy (r, lvl) let print_registered () = let pr_lib_ref (s,r) = pr_global r ++ str " registered as " ++ str s in hov 0 (prlist_with_sep fnl pr_lib_ref @@ Rocqlib.get_lib_refs ()) let print_registered_schemes () = let schemes = DeclareScheme.all_schemes() in let pr_one_scheme ind (kind, c) = pr_global c ++ str " registered as " ++ str kind ++ str " for " ++ pr_global (IndRef ind) in let pr_schemes_of_ind (ind, schemes) = prlist_with_sep fnl (pr_one_scheme ind) (CString.Map.bindings schemes) in hov 0 (prlist_with_sep fnl pr_schemes_of_ind (Indmap_env.bindings schemes)) let dump_universes output g = let open Univ in let dump_arc u = function | UGraph.Node ltle -> Univ.Level.Map.iter (fun v strict -> let typ = if strict then UnivConstraint.Lt else UnivConstraint.Le in output typ u v) ltle; | UGraph.Alias v -> output UnivConstraint.Eq u v in Univ.Level.Map.iter dump_arc g let dump_universes_gen prl g s = let fulls = System.get_output_path s in System.mkdir (Filename.dirname fulls); let output = open_out fulls in let output_constraint, close = if Filename.check_suffix s ".dot" || Filename.check_suffix s ".gv" then begin (* the lazy unit is to handle errors while printing the first line *) let init = lazy (Printf.fprintf output "digraph universes {\n") in begin fun kind left right -> let () = Lazy.force init in match kind with | Univ.UnivConstraint.Lt -> Printf.fprintf output " \"%s\" -> \"%s\" [style=bold];\n" right left | Univ.UnivConstraint.Le -> Printf.fprintf output " \"%s\" -> \"%s\" [style=solid];\n" right left | Univ.UnivConstraint.Eq -> Printf.fprintf output " \"%s\" -> \"%s\" [style=dashed];\n" left right end, begin fun () -> if Lazy.is_val init then Printf.fprintf output "}\n"; close_out output end end else begin begin fun kind left right -> let kind = match kind with | Univ.UnivConstraint.Lt -> "<" | Univ.UnivConstraint.Le -> "<=" | Univ.UnivConstraint.Eq -> "=" in Printf.fprintf output "%s %s %s ;\n" left kind right end, (fun () -> close_out output) end in let output_constraint k l r = output_constraint k (prl l) (prl r) in try dump_universes output_constraint g; close (); str "Universes written to file \"" ++ str s ++ str "\"." with reraise -> let reraise = Exninfo.capture reraise in close (); Exninfo.iraise reraise let universe_subgraph kept univ = let open Univ in let parse = function | NamedUniv q -> begin try Level.make (Nametab.locate_universe q) with Not_found -> CErrors.user_err ?loc:q.loc Pp.(str "Undeclared universe " ++ pr_qualid q ++ str".") end | RawUniv { CAst.v = s; loc } -> let parts = String.split_on_char '.' s in let () = if CList.is_empty parts then CErrors.user_err ?loc Pp.(str "Invalid raw universe.") in let i, dp = List.sep_last parts in let dp = Libnames.dirpath_of_string (String.concat "." dp) in let i = match int_of_string_opt i with | Some i -> i | None -> CErrors.user_err ?loc Pp.(str "Invalid raw universe.") in let u = UGlobal.make dp "" i in let u = Level.make u in begin match UGraph.check_declared_universes univ (Level.Set.singleton u) with | Ok () -> u | Error _ -> CErrors.user_err ?loc Pp.(str "Undeclared universe " ++ Level.raw_pr u ++ str".") end in let kept = List.fold_left (fun kept q -> Level.Set.add (parse q) kept) Level.Set.empty kept in let csts = UGraph.constraints_for ~kept univ in let add u newgraph = let strict = UGraph.check_constraint univ (Level.set,Lt,u) in UGraph.add_universe u ~strict newgraph in let univ = Level.Set.fold add kept UGraph.initial_universes in UGraph.merge_constraints csts univ let sort_universes g = let open Univ in let rec normalize u = match Level.Map.find u g with | UGraph.Alias u -> normalize u | UGraph.Node _ -> u in let get_next u = match Level.Map.find u g with | UGraph.Alias u -> assert false (* nodes are normalized *) | UGraph.Node ltle -> ltle in (* Compute the longest chain of Lt constraints from Set to any universe *) let rec traverse accu todo = match todo with | [] -> accu | (u, n) :: todo -> let () = assert (Level.equal (normalize u) u) in let n = match Level.Map.find u accu with | m -> if m < n then Some n else None | exception Not_found -> Some n in match n with | None -> traverse accu todo | Some n -> let accu = Level.Map.add u n accu in let next = get_next u in let fold v lt todo = let v = normalize v in if lt then (v, n + 1) :: todo else (v, n) :: todo in let todo = Level.Map.fold fold next todo in traverse accu todo in (* Only contains normalized nodes *) let levels = traverse Level.Map.empty [normalize Level.set, 0] in let max_level = Level.Map.fold (fun _ n accu -> max n accu) levels 0 in let dummy_mp = Names.DirPath.make [Names.Id.of_string "Type"] in let ulevels = Array.init max_level (fun i -> Level.(make (UGlobal.make dummy_mp "" i))) in (* Add the normal universes *) let fold (cur, ans) u = let ans = Level.Map.add cur (UGraph.Node (Level.Map.singleton u true)) ans in (u, ans) in let _, ans = Array.fold_left fold (Level.set, Level.Map.empty) ulevels in let ulevels = Array.cons Level.set ulevels in (* Add alias pointers *) let fold u _ ans = if Level.is_set u then ans else let n = Level.Map.find (normalize u) levels in Level.Map.add u (UGraph.Alias ulevels.(n)) ans in Level.Map.fold fold g ans type constraint_source = GlobRef of GlobRef.t | Library of DirPath.t (* The [edges] fields give the edges of the graph. For [u <= v] and [u < v] we have [u |-> v |-> gref, k], for [u = v] we have both directions. When there are edges with different constraint types between the same univs (eg [u < v] and [u <= v]) we keep the strictest one (either [<] or [=], NB we can't get both at the same time). *) type constraint_sources = { edges : (constraint_source * Univ.UnivConstraint.kind) Univ.Level.Map.t Univ.Level.Map.t; } let empty_sources = { edges = Univ.Level.Map.empty } let mk_sources () = let open Univ in let open UnivConstraint in let srcs = DeclareUniv.constraint_sources () in let pick_stricter_constraint (_,k as v) (_,k' as v') = match k, k' with | Le, Lt | Le, Eq -> v' | Lt, Le | Eq, Le -> v | Le, Le | Lt, Lt | Eq, Eq -> (* same: prefer [v] (the older refs are encountered last, and fallback libraries first) *) v | Lt, Eq | Eq, Lt -> (* XXX don't assert in case of type in type? *) assert false in let add_edge_unidirectional (u,k,v) ref edges = Level.Map.update u (fun uedges -> let uedges = Option.default Level.Map.empty uedges in Some (Level.Map.update v (function | None -> Some (ref, k) | Some v' -> Some (pick_stricter_constraint (ref, k) v')) uedges)) edges in let add_edge (u,k,v as cst) ref edges = let edges = add_edge_unidirectional cst ref edges in if k = Eq then add_edge_unidirectional (v,k,u) ref edges else edges in let edges = Level.Map.empty in let edges = let libs = Library.loaded_libraries () in List.fold_left (fun edges dp -> let _, (_, univ_csts) = Safe_typing.univs_of_library @@ Library.library_compiled dp in UnivConstraints.fold (fun cst edges -> add_edge cst (Library dp) edges) univ_csts edges) edges libs in let edges = List.fold_left (fun edges (ref, csts) -> UnivConstraints.fold (fun cst edges -> add_edge cst (GlobRef ref) edges) csts edges) edges srcs in { edges; } exception Found of (Univ.UnivConstraint.kind * Univ.Level.t * constraint_source) list (* We are looking for a path from [source] to [target]. If [k] is [Lt] the path must contain at least one [Lt]. If [k] is [Eq] the path must contain no [Lt]. [visited] is a map which for each level we have visited says if the path had enough [Lt] (always true if the original [k] is [Le] or [Eq]). *) let search src ~target k ~source = let module UMap = Univ.Level.Map in let rec loop visited todo next_todo = match todo, next_todo with | [], [] -> () | _, _ :: _ -> loop visited next_todo [] | (source,k,revpath)::todo, _ -> let is_visited = match UMap.find_opt source visited with | None -> false | Some has_enough_lt -> if has_enough_lt then true else (* original k was [Lt], if current k is also [Lt] we have no new info on this path *) k = Univ.UnivConstraint.Lt in if is_visited then loop visited todo next_todo else let visited = UMap.add source (k <> Univ.UnivConstraint.Lt) visited in let visited, next_todo = UMap.fold (fun u (ref,k') (visited,next_todo) -> if k = Univ.UnivConstraint.Eq && k' = Univ.UnivConstraint.Lt then (* no point searching for a loop involving [u] *) (UMap.add u true visited, next_todo) else let next_k = if k = Univ.UnivConstraint.Lt && k' = Univ.UnivConstraint.Lt then Univ.UnivConstraint.Le else k in let revpath = (k',u,ref) :: revpath in if Univ.Level.equal u target && next_k <> Univ.UnivConstraint.Lt then raise (Found revpath) else (visited, (u, next_k, revpath) :: next_todo)) (Option.default UMap.empty (UMap.find_opt source src.edges)) (visited,next_todo) in loop visited todo next_todo in try loop UMap.empty [source,k,[]] []; None with Found l -> Some (List.rev l) let search src (u,k,v) = let path = search src ~source:u k ~target:v in match path with | None -> None | Some path -> if k = Univ.UnivConstraint.Eq && not (List.for_all (fun (k',_,_) -> k' = Univ.UnivConstraint.Eq) path) then let path' = search src ~source:v k ~target:u in begin match path' with | None -> None | Some path' -> Some (path @ path') end else Some path let find_source (u,k,v as cst) src = if Univ.Level.is_set u && k = Univ.UnivConstraint.Lt then [] else Option.default [] (search src cst) let pr_constraint_source = function | GlobRef ref -> begin try pr_global ref with Not_found -> (* global in a module type or functor *) GlobRef.print ref end | Library dp -> str "library " ++ pr_qualid (Nametab.shortest_qualid_of_module (MPfile dp)) let pr_source_path prl u src = if CList.is_empty src then mt() else let open Univ in let pr_rel = function | UnivConstraint.Eq -> str"=" | UnivConstraint.Lt -> str"<" | UnivConstraint.Le -> str"<=" in let pr_one (k,v,ref) = spc() ++ h (pr_rel k ++ surround (str "from " ++ pr_constraint_source ref) ++ spc() ++ prl v) in spc() ++ surround (str"because" ++ spc() ++ prl u ++ prlist_with_sep mt pr_one src) let pr_pmap sep pr map = let cmp (u,_) (v,_) = Univ.Level.compare u v in Pp.prlist_with_sep sep pr (List.sort cmp (Univ.Level.Map.bindings map)) let pr_arc srcs prl = let open Pp in function | u, UGraph.Node ltle -> if Univ.Level.Map.is_empty ltle then mt () else prl u ++ str " " ++ v 0 (pr_pmap spc (fun (v, strict) -> let k = if strict then Univ.UnivConstraint.Lt else Univ.UnivConstraint.Le in let src = find_source (u,k,v) srcs in hov 2 ((if strict then str "< " else str "<= ") ++ prl v ++ pr_source_path prl u src)) ltle) ++ fnl () | u, UGraph.Alias v -> let src = find_source (u,Eq,v) srcs in prl u ++ str " = " ++ prl v ++ pr_source_path prl u src ++ fnl () let pr_universes srcs prl g = pr_pmap Pp.mt (pr_arc srcs prl) g let print_universes { sort; subgraph; with_sources; file; } = let univ = Global.universes () in let univ = match subgraph with | None -> univ | Some g -> universe_subgraph g univ in let univ = UGraph.repr univ in let univ = if sort then sort_universes univ else univ in let pr_remaining = if Global.is_joined_environment () then mt () else str"There may remain asynchronous universe constraints" in let prl = UnivNames.pr_level_with_global_universes in begin match file with | None -> let with_sources = match with_sources, subgraph with | Some b, _ -> b | _, None -> false | _, Some _ -> true in let srcs = if with_sources then mk_sources () else empty_sources in pr_universes srcs prl univ ++ pr_remaining | Some s -> dump_universes_gen (fun u -> Pp.string_of_ppcmds (prl u)) univ s end let print_sorts () = let qualities = Sorts.QVar.Set.elements (Global.qualities ()) in let prq = UnivNames.pr_quality_with_global_universes in Pp.prlist_with_sep Pp.spc prq qualities (*********************) (* "Locate" commands *) let locate_file f = let file = Flags.silently Loadpath.locate_file f in str file let msg_found_library (fulldir, file) = if Library.library_is_loaded fulldir then hov 0 (DirPath.print fulldir ++ strbrk " has been loaded from file " ++ str file) else hov 0 (DirPath.print fulldir ++ strbrk " is bound to file " ++ str file) let print_located_library qid = let open Loadpath in match locate_qualified_library qid with | Ok lib -> msg_found_library lib | Error LibUnmappedDir -> raise (UnmappedLibrary (None, qid)) | Error LibNotFound -> raise (NotFoundLibrary (None, qid)) let smart_global r = let gr = Smartlocate.smart_global r in Dumpglob.add_glob ?loc:r.loc gr; gr let qualid_global id = smart_global (make ?loc:id.loc @@ Constrexpr.AN id) (**********) (* Syntax *) let vernac_declare_scope ~module_local sc = Metasyntax.declare_scope module_local sc let vernac_delimiters ~module_local sc action = match action with | Some lr -> Metasyntax.add_delimiters module_local sc lr | None -> Metasyntax.remove_delimiters module_local sc let vernac_bind_scope ~atts sc cll = let module_local, where = Attributes.(parse Notations.(module_locality ++ bind_scope_where) atts) in Metasyntax.add_class_scope module_local sc where (List.map scope_class_of_qualid cll) let vernac_open_close_scope ~section_local (to_open,s) = Metasyntax.open_close_scope section_local ~to_open s let interp_enable_notation_rule on ntn interp flags scope = let open Notation in let rule = Option.map (function | Inl ntn -> Inl (interpret_notation_string ntn) | Inr (vars,qid) -> Inr qid) ntn in let rec parse_notation_enable_flags all query = function | [] -> all, query | EnableNotationEntry entry :: flags -> let entry = Metasyntax.intern_notation_entry entry in parse_notation_enable_flags all { query with notation_entry_pattern = entry :: query.notation_entry_pattern } flags | EnableNotationOnly use :: flags -> parse_notation_enable_flags all { query with use_pattern = use } flags | EnableNotationAll :: flags -> parse_notation_enable_flags true query flags in let interp = Option.map (fun c -> let vars, recvars = match ntn with | None -> (* We expect the right-hand side to mention "_" in place of proper variables *) (* Or should we instead deactivate the check of free variables? *) ([], []) | Some (Inl ntn) -> let {recvars; mainvars} = decompose_raw_notation ntn in (mainvars, recvars) | Some (Inr (vars,qid)) -> (vars, []) in let ninterp_var_type = Id.Map.of_list (List.map (fun x -> (x, Notation_term.NtnInternTypeAny None)) vars) in let ninterp_rec_vars = Id.Map.of_list recvars in let nenv = Notation_term.{ ninterp_var_type; ninterp_rec_vars } in let (_acvars, ac, _reversibility) = Constrintern.interp_notation_constr (Global.env ()) nenv c in ([], ac)) interp in let default_notation_enable_pattern = { notation_entry_pattern = []; interp_rule_key_pattern = rule; use_pattern = ParsingAndPrinting; scope_pattern = scope; interpretation_pattern = interp; } in let all, notation_pattern = parse_notation_enable_flags false default_notation_enable_pattern flags in on, all, notation_pattern let vernac_enable_notation ~module_local on rule interp flags scope = let () = match rule, interp, scope with | None, None, None -> user_err (str "No notation provided.") | _ -> () in let on, all, notation_pattern = interp_enable_notation_rule on rule interp flags scope in Metasyntax.declare_notation_toggle module_local ~on ~all notation_pattern (***********) (* Gallina *) let check_name_freshness locality {CAst.loc;v=id} : unit = (* We check existence here: it's a bit late at Qed time *) if Termops.is_section_variable (Global.env ()) id || locality <> Discharge && Nametab.exists_cci (Lib.make_path id) || locality <> Discharge && Nametab.exists_cci (Lib.make_path_except_section id) then user_err ?loc (Id.print id ++ str " already exists.") let vernac_definition_hook ~atts ~canonical_instance ~local ~poly ~reversible kind = let hooks = atts.DefAttributes.hooks in let hooks = let open Decls in let open Declare.Hook in match kind with | Coercion -> (ComCoercion.coercion_hook ~reversible) :: hooks | CanonicalStructure -> make (fun { S.dref } -> Canonical.declare_canonical_structure ?local dref) :: hooks | SubClass -> (ComCoercion.subclass_hook ~poly ~reversible) :: hooks | Definition when canonical_instance -> make (fun { S.dref } -> Canonical.declare_canonical_structure ?local dref) :: hooks | Let when canonical_instance -> make (fun { S.dref } -> Canonical.declare_canonical_structure dref) :: hooks | _ -> hooks in match hooks with | [] -> None | _ -> Some (Declare.Hook.make (fun st -> List.iter (fun hook -> Declare.Hook.call ~hook st) hooks)) let default_thm_id = Id.of_string "Unnamed_thm" let fresh_name_for_anonymous_theorem () = Namegen.next_global_ident_away (Global.safe_env ()) default_thm_id Id.Set.empty let vernac_definition_name lid local = let lid = match lid with | { v = Name.Anonymous; loc } -> CAst.make ?loc (fresh_name_for_anonymous_theorem ()) | { v = Name.Name n; loc } -> CAst.make ?loc n in check_name_freshness local lid; let () = if Dumpglob.dump () then match local with | Discharge -> Dumpglob.dump_definition lid true "var" | Global _ -> Dumpglob.dump_definition lid false "def" in lid.v let vernac_definition_interactive ~atts (discharge, kind) (lid, udecl) bl t = let open DefAttributes in let scope, local, poly, program_mode, user_warns, typing_flags, using, clearbody = atts.scope, atts.locality, atts.poly, atts.program, atts.user_warns, atts.typing_flags, atts.using, atts.clearbody in let hook = let canonical_instance, reversible = atts.canonical_instance, atts.reversible in vernac_definition_hook ~atts ~canonical_instance ~local ~poly ~reversible kind in let name = vernac_definition_name lid scope in ComDefinition.do_definition_interactive ?loc:lid.loc ~typing_flags ~program_mode ~name ~poly ~scope ?clearbody:atts.clearbody ~kind:(Decls.IsDefinition kind) ?user_warns ?using:atts.using ?hook udecl bl t let vernac_definition_refine ~atts (discharge, kind) (lid, udecl) bl red_option c typ_opt = if Option.has_some red_option then CErrors.user_err ?loc:c.loc Pp.(str "Cannot use Eval with #[refine]."); let open DefAttributes in let scope, local, poly, program_mode, user_warns, typing_flags, using, clearbody = atts.scope, atts.locality, atts.poly, atts.program, atts.user_warns, atts.typing_flags, atts.using, atts.clearbody in let hook = let canonical_instance, reversible = atts.canonical_instance, atts.reversible in vernac_definition_hook ~atts ~canonical_instance ~local ~poly kind ~reversible in let name = vernac_definition_name lid scope in ComDefinition.do_definition_refine ~name ?loc:lid.loc ?clearbody ~poly ~typing_flags ~scope ~kind:(Decls.IsDefinition kind) ?user_warns ?using udecl bl c typ_opt ?hook let vernac_definition ~atts ~pm (discharge, kind) (lid, udecl) bl red_option c typ_opt = let open DefAttributes in let scope, local, poly, program_mode, user_warns, typing_flags, using, clearbody = atts.scope, atts.locality, atts.poly, atts.program, atts.user_warns, atts.typing_flags, atts.using, atts.clearbody in let hook = let canonical_instance, reversible = atts.canonical_instance, atts.reversible in vernac_definition_hook ~atts ~canonical_instance ~local ~poly kind ~reversible in let name = vernac_definition_name lid scope in let red_option = match red_option with | None -> None | Some r -> let env = Global.env () in let sigma = Evd.from_env env in Some (snd (Redexpr.interp_redexp_no_ltac env sigma r)) in if program_mode then let kind = Decls.IsDefinition kind in ComDefinition.do_definition_program ?loc:lid.loc ~pm ~name ?clearbody ~poly ?typing_flags ~scope ~kind ?user_warns ?using udecl bl red_option c typ_opt ?hook else let () = ComDefinition.do_definition ~name ?loc:lid.loc ?clearbody ~poly ?typing_flags ~scope ~kind ?user_warns ?using udecl bl red_option c typ_opt ?hook in pm (* NB: pstate argument to use combinators easily *) let vernac_start_proof ~atts kind l = let open DefAttributes in if Dumpglob.dump () then List.iter (fun ((id, _), _) -> Dumpglob.dump_definition id false "prf") l; let scope, local, poly, program_mode, user_warns, typing_flags, using, clearbody = atts.scope, atts.locality, atts.poly, atts.program, atts.user_warns, atts.typing_flags, atts.using, atts.clearbody in List.iter (fun ((id, _), _) -> check_name_freshness scope id) l; match l with | [] -> assert false | [({v=name; loc},udecl),(bl,typ)] -> ComDefinition.do_definition_interactive ?loc ~typing_flags ~program_mode ~name ~poly ?clearbody ~scope ~kind:(Decls.IsProof kind) ?user_warns ?using udecl bl typ | ((lid,_),_) :: _ -> let fix = List.map (fun ((fname, univs), (binders, rtype)) -> { fname; binders; rtype; body_def = None; univs; notations = []}) l in let pm, proof = ComFixpoint.do_mutually_recursive ~refine:false ~program_mode ~use_inference_hook:program_mode ~scope ?clearbody ~kind:(Decls.IsProof kind) ~poly ?typing_flags ?user_warns ?using (CUnknownRecOrder, fix) in assert (Option.is_empty pm); Option.get proof let vernac_end_proof ~lemma ~pm = let open Vernacexpr in function | Admitted -> Declare.Proof.save_admitted ~pm ~proof:lemma | Proved (opaque,idopt) -> let pm, _ = Declare.Proof.save ~pm ~proof:lemma ~opaque ~idopt in pm let vernac_abort ~lemma:_ ~pm = pm let deprecated_exact_proof = CWarnings.create ~name:"deprecated-exact-proof" ~category:Deprecation.Version.v9_2 Pp.(fun () -> str "\"Proof term.\" is deprecated. Use \"Proof. exact term. Qed.\" instead.") let vernac_exact_proof ~lemma ~pm c = deprecated_exact_proof (); (* spiwack: for simplicity I do not enforce that "Proof proof_term" is called only at the beginning of a proof. *) let lemma, status = Declare.Proof.by (Global.env ()) (Tactics.exact_proof c) lemma in let pm, _ = Declare.Proof.save ~pm ~proof:lemma ~opaque:Opaque ~idopt:None in if not status then Feedback.feedback Feedback.AddedAxiom; pm let vernac_assumption ~atts kind l inline = let open DefAttributes in let scope, poly, program_mode, using, user_warns = atts.scope, atts.poly, atts.program, atts.using, atts.user_warns in if Option.has_some using then Attributes.unsupported_attributes [CAst.make ("using",VernacFlagEmpty)]; ComAssumption.do_assumptions ~poly ~program_mode ~scope ~kind ?user_warns ~inline l let { Goptions.get = get_uniform_inductive_parameters } = Goptions.declare_bool_option_and_ref ~key:["Uniform"; "Inductive"; "Parameters"] ~value:false () let should_treat_as_uniform () = if get_uniform_inductive_parameters () then ComInductive.UniformParameters else ComInductive.NonUniformParameters (* [XXX] EGJA: several arguments not used here *) let vernac_record records = let map ((is_coercion, name), binders, sort, nameopt, cfs, ido) = let idbuild = match nameopt with | None -> CAst.map (Nameops.add_prefix "Build_") name | Some lid -> lid in let default_inhabitant_id = Option.map (fun CAst.{v=id} -> id) ido in Record.Ast.{ name; is_coercion; binders; cfs; idbuild; sort; default_inhabitant_id } in let records = List.map map records in records let extract_inductive_udecl (indl:(inductive_expr * notation_declaration list) list) = match indl with | [] -> assert false | (((coe,(id,udecl)),b,c,d),e) :: rest -> let rest = List.map (fun (((coe,(id,udecl)),b,c,d),e) -> if Option.has_some udecl then user_err Pp.(strbrk "Universe binders must be on the first inductive of the block.") else (((coe,id),b,c,d),e)) rest in udecl, (((coe,id),b,c,d),e) :: rest let finite_of_kind = let open Declarations in function | Inductive_kw -> Finite | CoInductive -> CoFinite | Variant | Record | Structure | Class _ -> BiFinite let private_ind = let open Attributes in let open Notations in attribute_of_list [ "matching" , single_key_parser ~name:"Private (matching) inductive type" ~key:"matching" () ] |> qualify_attribute "private" >>= function | Some () -> return true | None -> return false (** Flag governing use of primitive projections. Disabled by default. *) let { Goptions.get = primitive_flag } = Goptions.declare_bool_option_and_ref ~key:["Primitive";"Projections"] ~value:false () let primitive_proj = let open Attributes in let open Notations in qualify_attribute "projections" (bool_attribute ~name:"primitive") >>= function | Some t -> return t | None -> return (primitive_flag ()) let mode_attr = let open Attributes in let open Notations in payload_attribute ?cat:None ~name:"mode" >>= function | None -> return None | Some mode -> return (Some (Hints.parse_modes mode)) module Preprocessed_Mind_decl = struct type flags = ComInductive.flags type record = { flags : flags; udecl : Constrexpr.cumul_univ_decl_expr option; primitive_proj : bool; kind : Vernacexpr.inductive_kind; records : Record.Ast.t list; } type inductive = { flags : flags; udecl : Constrexpr.cumul_univ_decl_expr option; typing_flags : Declarations.typing_flags option; private_ind : bool; uniform : ComInductive.uniform_inductive_flag; inductives : (Vernacexpr.one_inductive_expr * Vernacexpr.notation_declaration list) list; } type t = | Record of record | Inductive of inductive end (* Intermediate type while parsing record field flags *) type record_field_attr = { rf_coercion: coercion_flag; (* the projection is an implicit coercion *) rf_reversible: bool option; (* coercion is reversible, if relevant *) rf_instance: instance_flag; (* the projection is an instance *) rf_priority: int option; (* priority of the instance, if relevant *) rf_locality: Goptions.option_locality; (* locality of coercion and instance *) rf_canonical: bool; (* use this projection in the search for canonical instances *) } let check_proj_flags rf = let open Vernacexpr in let open Record.Data in let () = match rf.rf_coercion, rf.rf_instance with | NoCoercion, NoInstance -> if rf.rf_locality <> Goptions.OptDefault then Attributes.(unsupported_attributes [CAst.make ("locality (without :> or ::)",VernacFlagEmpty)]) | AddCoercion, NoInstance -> if rf.rf_locality = Goptions.OptExport then Attributes.(unsupported_attributes [CAst.make ("export (without ::)",VernacFlagEmpty)]) | _ -> () in let pf_coercion = match rf.rf_coercion with | AddCoercion -> Some { coe_local = rf.rf_locality = OptLocal; coe_reversible = Option.default true rf.rf_reversible; } | NoCoercion -> if rf.rf_reversible <> None then Attributes.(unsupported_attributes [CAst.make ("reversible (without :>)",VernacFlagEmpty)]); None in let pf_instance = match rf.rf_instance with | NoInstance -> let () = if Option.has_some rf.rf_priority then CErrors.user_err Pp.(str "Priority not allowed without \"::\".") in None | BackInstance -> let local = match rf.rf_locality with | Goptions.OptLocal -> Hints.Local | Goptions.(OptDefault | OptExport) -> Hints.Export | Goptions.OptGlobal -> Hints.SuperGlobal in Some { inst_locality = local; inst_priority = rf.rf_priority; } in { pf_coercion; pf_instance; pf_canonical = rf.rf_canonical } let preprocess_defclass ~atts udecl (id, bl, c, l) = let poly, mode = Attributes.(parse Notations.(poly PolyFlags.Definition ++ mode_attr) atts) in let flags = { (* flags which don't matter for definitional classes *) ComInductive.template=None; finite=BiFinite; schemes=None; (* real flags *) poly; mode; } in let bl = match bl with | bl, None -> bl | _ -> CErrors.user_err Pp.(str "Definitional classes do not support the \"|\" syntax.") in if fst id = AddCoercion then user_err Pp.(str "Definitional classes do not support the \">\" syntax."); let ((attr, rf_coercion, rf_instance), (lid, ce)) = l in let rf_locality = match rf_coercion, rf_instance with | AddCoercion, _ | _, BackInstance -> parse option_locality attr | _ -> let () = unsupported_attributes attr in Goptions.OptDefault in let f = AssumExpr ((make ?loc:lid.loc @@ Name lid.v), [], ce), check_proj_flags { rf_coercion ; rf_reversible = None ; rf_instance ; rf_priority = None ; rf_locality ; rf_canonical = true }, [] in let recordl = [id, bl, c, None, [f], None] in let kind = Class true in let records = vernac_record recordl in Preprocessed_Mind_decl.(Record { flags; udecl; primitive_proj=false; kind; records }) let preprocess_record ~atts udecl kind indl = let () = match kind with | Variant -> user_err (str "The Variant keyword does not support syntax { ... }.") | Record | Structure | Class _ | Inductive_kw | CoInductive -> () in let check_where ((_, _, _, _), wh) = match wh with | [] -> () | _ :: _ -> user_err (str "\"where\" clause not supported for records.") in let () = List.iter check_where indl in let hint_mode_attr : Hints.hint_mode list option Attributes.attribute = match kind with | Class _ -> mode_attr | _ -> Notations.return None in let (((template, poly), primitive_proj), mode), schemes = Attributes.( parse Notations.( template ++ poly PolyFlags.Inductive ++ primitive_proj ++ hint_mode_attr ++ DeclareInd.schemes_attr) atts) in let finite = finite_of_kind kind in let flags = { ComInductive.template; poly; finite; mode; schemes } in let parse_record_field_attr (x, f) = let attr = let rev = match f.rfu_coercion with | AddCoercion -> reversible | NoCoercion -> Notations.return None in let loc = match f.rfu_coercion, f.rfu_instance with | AddCoercion, _ | _, BackInstance -> option_locality | _ -> Notations.return Goptions.OptDefault in Notations.(rev ++ loc ++ canonical_field) in let (rf_reversible, rf_locality), rf_canonical = parse attr f.rfu_attrs in let flags = check_proj_flags { rf_coercion = f.rfu_coercion; rf_reversible; rf_instance = f.rfu_instance; rf_priority = f.rfu_priority; rf_locality; rf_canonical; } in x, flags, f.rfu_notation in let unpack ((id, bl, c, decl), _) = match decl with | RecordDecl (oc, fs, ido) -> let bl = match bl with | bl, None -> bl | _ -> CErrors.user_err Pp.(str "Records do not support the \"|\" syntax.") in (id, bl, c, oc, List.map parse_record_field_attr fs, ido) | Constructors _ -> assert false (* ruled out above *) in let kind = match kind with Class _ -> Class false | _ -> kind in let recordl = List.map unpack indl in let records = vernac_record recordl in Preprocessed_Mind_decl.(Record { flags; udecl; primitive_proj; kind; records }) let preprocess_inductive ~atts udecl kind indl = let () = match kind with | (Record | Structure) -> user_err (str "The Record keyword is for types defined using the syntax { ... }.") | Class _ -> user_err (str "Inductive classes not supported.") | Variant | Inductive_kw | CoInductive -> () in let check_name ((na, _, _, _), _) = match na with | (AddCoercion, _) -> user_err (str "Variant types do not handle the \"> Name\" \ syntax, which is reserved for records. Use the \":>\" \ syntax on constructors instead.") | _ -> () in let () = List.iter check_name indl in let hint_mode_attr : Hints.hint_mode list option Attributes.attribute = match kind with | Class _ -> mode_attr | _ -> Notations.return None in let ((((template, poly), private_ind), typing_flags), mode), schemes = Attributes.( parse Notations.( template ++ poly PolyFlags.Inductive ++ private_ind ++ typing_flags ++ hint_mode_attr ++ DeclareInd.schemes_attr) atts) in let finite = finite_of_kind kind in let flags = { ComInductive.template; poly; finite; mode; schemes } in let unpack (((_, id) , bl, c, decl), ntn) = match decl with | Constructors l -> (id, bl, c, l), ntn | RecordDecl _ -> assert false (* ruled out above *) in let inductives = List.map unpack indl in let uniform = should_treat_as_uniform () in Preprocessed_Mind_decl.(Inductive { flags; udecl; typing_flags; private_ind; uniform; inductives }) let preprocess_inductive_decl ~atts kind indl = let udecl, indl = extract_inductive_udecl indl in let v = match kind, indl with | Class _, [ ( id , bl , c , Constructors [l]), [] ] -> preprocess_defclass ~atts udecl (id,bl,c,l) | _ -> if List.for_all (function | ((_ , _ , _ , RecordDecl _), _) -> true | _ -> false) indl then preprocess_record ~atts udecl kind indl else if List.for_all (function | ((_ , _ , _ , Constructors _), _) -> true | _ -> false) indl then preprocess_inductive ~atts udecl kind indl else user_err (str "Mixed record-inductive definitions are not allowed.") in indl, v let dump_inductive indl_for_glob decl = let open Preprocessed_Mind_decl in if Dumpglob.dump () then begin List.iter (fun (((coe,lid), _, _, cstrs), _) -> match cstrs with | Constructors cstrs -> Dumpglob.dump_definition lid false "ind"; List.iter (fun (_, (lid, _)) -> Dumpglob.dump_definition lid false "constr") cstrs | _ -> ()) indl_for_glob; match decl with | Record { records } -> let dump_glob_proj (x, _, _) = match x with | Vernacexpr.(AssumExpr ({loc;v=Name id}, _, _) | DefExpr ({loc;v=Name id}, _, _, _)) -> Dumpglob.dump_definition (make ?loc id) false "proj" | _ -> () in records |> List.iter (fun { Record.Ast.cfs; name } -> let () = Dumpglob.dump_definition name false "rec" in List.iter dump_glob_proj cfs) | Inductive _ -> () end let vernac_inductive ~atts kind indl = let open Preprocessed_Mind_decl in let indl_for_glob, decl = preprocess_inductive_decl ~atts kind indl in dump_inductive indl_for_glob decl; match decl with | Record { flags; kind; udecl; primitive_proj; records } -> let _ : _ list = Record.definition_structure ~flags udecl kind ~primitive_proj records in () | Inductive { flags; udecl; typing_flags; private_ind; uniform; inductives } -> ComInductive.do_mutual_inductive ~flags udecl inductives ?typing_flags ~private_ind ~uniform let preprocess_inductive_decl ~atts kind indl = snd @@ preprocess_inductive_decl ~atts kind indl let vernac_fixpoint_common ~atts l = if Dumpglob.dump () then List.iter (fun { fname } -> Dumpglob.dump_definition fname false "def") l; let scope = atts.DefAttributes.scope in List.iter (fun { fname } -> check_name_freshness scope fname) l; scope let with_obligations program_mode f pm = if program_mode then f pm ~program_mode:true else let pm', proof = f None ~program_mode:false in assert (Option.is_empty pm'); pm, proof let vernac_fixpoint ~atts ~refine ~pm (rec_order,fixl) = let open DefAttributes in let scope = vernac_fixpoint_common ~atts fixl in let poly, typing_flags, program_mode, clearbody, using, user_warns = atts.poly, atts.typing_flags, atts.program, atts.clearbody, atts.using, atts.user_warns in let () = if program_mode then (* XXX: Switch to the attribute system and match on ~atts *) let opens = List.exists (fun { body_def } -> Option.is_empty body_def) fixl in if opens then CErrors.user_err Pp.(str"Program Fixpoint requires a body.") in with_obligations program_mode (fun pm -> ComFixpoint.do_mutually_recursive ?pm ~refine ~scope ?clearbody ~kind:(IsDefinition Fixpoint) ~poly ?typing_flags ?user_warns ?using (CFixRecOrder rec_order, fixl)) pm let vernac_cofixpoint_common ~atts l = if Dumpglob.dump () then List.iter (fun { fname } -> Dumpglob.dump_definition fname false "def") l; let scope = atts.DefAttributes.scope in List.iter (fun { fname } -> check_name_freshness scope fname) l; scope let vernac_cofixpoint ~pm ~refine ~atts cofixl = let open DefAttributes in let scope = vernac_cofixpoint_common ~atts cofixl in let poly, typing_flags, program_mode, clearbody, using, user_warns = atts.poly, atts.typing_flags, atts.program, atts.clearbody, atts.using, atts.user_warns in let () = if program_mode then let opens = List.exists (fun { body_def } -> Option.is_empty body_def) cofixl in if opens then CErrors.user_err Pp.(str"Program CoFixpoint requires a body.") in with_obligations program_mode (fun pm -> ComFixpoint.do_mutually_recursive ?pm ~refine ~scope ?clearbody ~kind:(IsDefinition CoFixpoint) ~poly ?typing_flags ?user_warns ?using (CCoFixRecOrder, cofixl)) pm let vernac_scheme atts l = if Dumpglob.dump () then List.iter (fun (lid, sch) -> Option.iter (fun lid -> Dumpglob.dump_definition lid false "def") lid) l; let register = Attributes.(parse (bool_attribute ~name:"register") atts) in let register = Option.default true register in Indschemes.do_scheme ~register (Global.env ()) l let vernac_scheme_equality ?locmap sch id = Indschemes.do_scheme_equality ?locmap sch id (* [XXX] locmap unused here *) let vernac_combined_scheme lid l ~locmap = (* XXX why does this take idents and not qualids *) let l = List.map (fun id -> match qualid_global (qualid_of_ident ?loc:id.loc id.v) with | ConstRef c -> c | _ -> CErrors.user_err ?loc:id.loc Pp.(Pputils.pr_lident id ++ str " is not a constant.")) l in Indschemes.do_combined_scheme lid l let vernac_universe ~poly l = if poly && not (Lib.sections_are_opened ()) then user_err (str"Polymorphic universes can only be declared inside sections, " ++ str "use Monomorphic Universe instead."); DeclareUniv.do_universe ~poly l let vernac_sort ~poly l = if poly && not (Lib.sections_are_opened ()) then user_err (str"Polymorphic sorts can only be declared inside sections, " ++ str "use #[universes(polymorphic=no)] Sort in order to declare a global sort."); DeclareUniv.do_sort ~poly l let vernac_constraint ~poly l = if poly && not (Lib.sections_are_opened ()) then user_err (str"Polymorphic constraints can only be declared" ++ str " inside sections, use Monomorphic Constraint instead."); DeclareUniv.do_constraint ~poly l (**********************) (* Modules *) let warn_not_importable = CWarnings.create ~name:"not-importable" Pp.(fun c -> str "Cannot import local constant " ++ Printer.pr_constant (Global.env()) c ++ str ", it will be ignored.") let importable_extended_global_of_path ?loc path = match Nametab.extended_global_of_path path with | Globnames.TrueGlobal (GlobRef.ConstRef c) as ref -> if Declare.is_local_constant c then begin warn_not_importable ?loc c; None end else Some ref | ref -> Some ref (* [XXX] n unused here *) let add_subnames_of ?loc len n ns full_n ref = let open GlobRef in let add1 r ns = (len, Globnames.TrueGlobal r) :: ns in match ref with | Globnames.Abbrev _ | Globnames.TrueGlobal (ConstRef _ | ConstructRef _ | VarRef _) -> CErrors.user_err ?loc Pp.(str "Only inductive types can be used with Import (...).") | Globnames.TrueGlobal (IndRef (mind,i)) -> let open Declarations in let path_prefix = path_pop_suffix full_n in let mib = Global.lookup_mind mind in let mip = mib.mind_packets.(i) in let ns = add1 (IndRef (mind,i)) ns in let ns = Array.fold_left_i (fun j ns _ -> add1 (ConstructRef ((mind,i),j+1)) ns) ns mip.mind_consnames in List.fold_left (fun ns q -> let s = Elimschemes.elimination_suffix q in let n_elim = Id.of_string (Id.to_string mip.mind_typename ^ s) in match importable_extended_global_of_path ?loc (Libnames.add_path_suffix path_prefix n_elim) with | exception Not_found -> ns | None -> ns | Some ref -> (len, ref) :: ns) ns UnivGen.QualityOrSet.all let interp_names m ns = let dp_m = Nametab.path_of_module m in let ns = List.fold_left (fun ns (n,etc) -> let len, full_n = let dp_n,n = repr_qualid n in List.length (DirPath.repr dp_n), add_path_suffix (append_path dp_m dp_n) n in let ref = try importable_extended_global_of_path ?loc:n.loc full_n with Not_found -> CErrors.user_err ?loc:n.loc Pp.(str "Cannot find name " ++ pr_qualid n ++ spc() ++ str "in module " ++ pr_qualid (Nametab.shortest_qualid_of_module m) ++ str ".") in (* TODO dumpglob? *) match ref with | Some ref -> let ns = (len,ref) :: ns in if etc then add_subnames_of ?loc:n.loc len n ns full_n ref else ns | None -> ns) [] ns in ns let cache_name (len,n) = let open Globnames in let open GlobRef in match n with | Abbrev kn -> Abbreviation.import (len+1) (Nametab.path_of_abbreviation kn) kn | TrueGlobal (VarRef _) -> assert false | TrueGlobal (ConstRef c) when Declare.is_local_constant c -> (* Can happen through functor application *) warn_not_importable c | TrueGlobal gr -> Nametab.(push (Exactly (len+1)) (path_of_global gr) gr) let cache_names ns = List.iter cache_name ns let subst_names (subst,ns) = List.Smart.map (on_snd (Globnames.subst_extended_reference subst)) ns let inExportNames = Libobject.declare_object (Libobject.global_object "EXPORTNAMES" ~cache:cache_names ~subst:(Some subst_names) ~discharge:(fun x -> Some x)) let import_names ~export m ns = let ns = interp_names m ns in match export with | Lib.Export -> Lib.add_leaf (inExportNames ns) | Lib.Import -> cache_names ns let interp_import_cats cats = Option.cata (fun cats -> Libobject.make_filter ~finite:(not cats.negative) cats.import_cats) Libobject.unfiltered cats (* Assumes cats is irrelevant if f is ImportNames *) let import_module_with_filter ~export cats m f = match f with | ImportAll -> Declaremods.Interp.import_module cats ~export m | ImportNames ns -> import_names ~export m ns let check_no_filter_when_using_cats l = List.iter (function | _, ImportAll -> () | q, ImportNames _ -> CErrors.user_err ?loc:q.loc Pp.(str "Cannot combine importing by categories and importing by names.")) l let vernac_import (export, cats) mpl = let import_mod (CAst.{v = mp; loc},f) = try let () = Dumpglob.dump_modref ?loc mp "mod" in let () = if Modops.is_functor @@ Mod_declarations.mod_type (Global.lookup_module mp) then CErrors.user_err ?loc Pp.(str "Cannot import functor " ++ str (ModPath.to_string mp) ++ str".") in import_module_with_filter ~export cats mp f with Not_found -> CErrors.user_err ?loc Pp.(str "Cannot find module " ++ str (ModPath.to_string mp) ++ str ".") in List.iter import_mod mpl let vernac_declare_module export {loc;v=id} binders_ast mty_ast = (* We check the state of the system (in section, in module type) and what module information is supplied *) if Lib.sections_are_opened () then user_err Pp.(str "Modules and Module Types are not allowed inside sections."); let mp = Declaremods.Interp.declare_module id binders_ast (Declaremods.Enforce mty_ast) [] in Dumpglob.dump_moddef ?loc mp "mod"; Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is declared"); Option.iter (fun export -> vernac_import export [CAst.make ?loc mp, ImportAll]) export let vernac_define_module export {loc;v=id} binders_ast argsexport mty_ast_o mexpr_ast_l = (* We check the state of the system (in section, in module type) and what module information is supplied *) if Lib.sections_are_opened () then user_err Pp.(str "Modules and Module Types are not allowed inside sections."); match mexpr_ast_l with | [] -> let mp = Declaremods.Interp.start_module export id binders_ast mty_ast_o in Dumpglob.dump_moddef ?loc mp "mod"; Flags.if_verbose Feedback.msg_info (str "Interactive Module " ++ Id.print id ++ str " started"); List.iter (fun (export,mp) -> vernac_import export [CAst.make mp, ImportAll]) argsexport | _::_ -> let mp = Declaremods.Interp.declare_module id binders_ast mty_ast_o mexpr_ast_l in Dumpglob.dump_moddef ?loc mp "mod"; Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is defined"); Option.iter (fun export -> vernac_import export [CAst.make ?loc mp, ImportAll]) export let vernac_end_module export {loc;v=id} = let mp = Declaremods.Interp.end_module () in Dumpglob.dump_modref ?loc mp "mod"; Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is defined"); Option.iter (fun (export,filter) -> Declaremods.Interp.import_module filter ~export mp) export let vernac_declare_module_type {loc;v=id} binders_ast argsexport mty_sign mty_ast_l = if Lib.sections_are_opened () then user_err Pp.(str "Modules and Module Types are not allowed inside sections."); match mty_ast_l with | [] -> let mp = Declaremods.Interp.start_modtype id binders_ast mty_sign in Dumpglob.dump_moddef ?loc mp "modtype"; Flags.if_verbose Feedback.msg_info (str "Interactive Module Type " ++ Id.print id ++ str " started"); List.iter (fun (export,mp) -> vernac_import export [CAst.make ?loc mp, ImportAll]) argsexport | _ :: _ -> let mp = Declaremods.Interp.declare_modtype id binders_ast mty_sign mty_ast_l in Dumpglob.dump_moddef ?loc mp "modtype"; Flags.if_verbose Feedback.msg_info (str "Module Type " ++ Id.print id ++ str " is defined") let vernac_end_modtype {loc;v=id} = let mp = Declaremods.Interp.end_modtype () in Dumpglob.dump_modref ?loc mp "modtype"; Flags.if_verbose Feedback.msg_info (str "Module Type " ++ Id.print id ++ str " is defined") let vernac_include l = Declaremods.Interp.declare_include l (**********************) (* Gallina extensions *) (* Sections *) let vernac_begin_section ~poly {v=id} = Lib.Interp.open_section id; (* If there was no polymorphism attribute this just sets the option to its current value ie noop. *) set_bool_option_value_gen ~locality:OptLocal ["Universe"; "Polymorphism"] poly let vernac_end_section {CAst.loc; v} = Declaremods.Interp.close_section () let vernac_name_sec_hyp {v=id} set = Proof_using.name_set id set (* Dispatcher of the "End" command *) let msg_of_subsection ss id = let kind = match ss with | Lib.OpenedModule (false,_,_,_) -> "module" | Lib.OpenedModule (true,_,_,_) -> "module type" | Lib.OpenedSection _ -> "section" | _ -> "unknown" in Pp.str kind ++ spc () ++ Id.print id let vernac_end_segment ~pm ~proof ({v=id; loc} as lid) = let ss = Lib.Interp.find_opening_node ?loc id in let what_for = msg_of_subsection ss lid.v in if Option.has_some proof then CErrors.user_err (Pp.str "Command not supported (Open proofs remain)"); Declare.Obls.check_solved_obligations ~pm ~what_for; match ss with | Lib.OpenedModule (false,export,_,_) -> vernac_end_module export lid | Lib.OpenedModule (true,_,_,_) -> vernac_end_modtype lid | Lib.OpenedSection _ -> vernac_end_section lid | _ -> assert false let vernac_end_segment lid = let open Vernactypes in typed_vernac { ignore_state with prog=Pop; proof=ReadOpt; } (fun {proof; prog} -> let () = vernac_end_segment ~pm:prog ~proof lid in no_state) let vernac_begin_segment ~interactive f = let open Vernactypes in let proof = Proof.(if interactive then Reject else Ignore) in let prog = Prog.(if interactive then Push else Ignore) in typed_vernac { ignore_state with prog; proof; } (fun (_:no_state) -> let () = f () in no_state) (* Libraries *) let warn_require_in_section = CWarnings.create ~name:"require-in-section" ~category:CWarnings.CoreCategories.fragile (fun () -> strbrk "Use of β€œRequire” inside a section is fragile." ++ spc() ++ strbrk "It is not recommended to use this functionality in finished proof scripts.") let vernac_require_interp needed modrefl export qidl = if Lib.sections_are_opened () then warn_require_in_section (); let () = match export with | None -> List.iter (function | _, ImportAll -> () | {CAst.loc}, ImportNames _ -> CErrors.user_err ?loc Pp.(str "Used an import filter without importing.")) qidl | Some (_,cats) -> if Option.has_some cats then check_no_filter_when_using_cats qidl in if Dumpglob.dump () then List.iter2 (fun ({CAst.loc},_) dp -> Dumpglob.dump_libref ?loc dp "lib") qidl modrefl; Coq_config.gc_ramp_up @@ fun () -> (* Load *) Library.require_library_from_dirpath needed; (* Import*) Option.iter (fun (export,cats) -> let cats = interp_import_cats cats in List.iter2 (fun m (_,f) -> import_module_with_filter ~export cats (MPfile m) f) modrefl qidl) export let vernac_require ~intern from export qidl = let needed, modrefl = Flags.with_modified_ref Flags.in_synterp_phase (fun _ -> Some true) (fun () -> Synterp.synterp_require ~intern from export qidl) () in Flags.with_modified_ref Flags.in_synterp_phase (fun _ -> Some false) (fun () -> vernac_require_interp needed modrefl export qidl) () (* Coercions and canonical structures *) let vernac_canonical ~local r = Canonical.declare_canonical_structure ?local (smart_global r) let vernac_coercion ~atts ref qidst = let ref' = smart_global ref in match qidst with | Some (qids, qidt) -> let local, reversible = Attributes.parse Notations.(locality ++ reversible) atts in let local = enforce_locality local in let reversible = Option.default false reversible in let target = cl_of_qualid qidt in let source = cl_of_qualid qids in ComCoercion.try_add_new_coercion_with_target ref' ~local ~reversible ~source ~target; Flags.if_verbose Feedback.msg_info (pr_global ref' ++ str " is now a coercion") | None -> match Attributes.parse reversible atts with | None -> user_err (str "Expected `: Sourceclass >-> Targetclass`.") | Some reversible -> ComCoercion.change_reverse ref' ~reversible let vernac_identity_coercion ~atts id qids qidt = let local, poly = Attributes.(parse Notations.(locality ++ polymorphic) atts) in let local = enforce_locality local in let target = cl_of_qualid qidt in let source = cl_of_qualid qids in let poly = PolyFlags.of_univ_poly poly (* FIXME cumulativity not handled *) in ComCoercion.try_add_new_identity_coercion id ~local ~poly ~source ~target (* Type classes *) let vernac_instance_program ~atts ~pm name bl t props info = Dumpglob.dump_constraint (fst name) false "inst"; let locality, poly = Attributes.(parse (Notations.(hint_locality ++ poly PolyFlags.Definition))) atts in let pm, _id = Classes.new_instance_program ~pm ~locality ~poly name bl t props info in pm let vernac_instance_interactive ~atts name bl t info props = Dumpglob.dump_constraint (fst name) false "inst"; let locality, poly = Attributes.(parse (Notations.(hint_locality ++ poly PolyFlags.Definition))) atts in let _id, pstate = Classes.new_instance_interactive ~locality ~poly name bl t info props in pstate let vernac_instance ~atts name bl t props info = Dumpglob.dump_constraint (fst name) false "inst"; let locality, poly = Attributes.(parse (Notations.(hint_locality ++ poly PolyFlags.Definition))) atts in let _id : lident = Classes.new_instance ~locality ~poly name bl t props info in () let vernac_declare_instance ~atts id bl inst pri = Dumpglob.dump_definition (fst id) false "inst"; let ((program, locality), poly) = Attributes.(parse (Notations.(program ++ hint_locality ++ poly PolyFlags.Definition))) atts in Classes.declare_new_instance ~program_mode:program ~locality ~poly id bl inst pri let vernac_context ~atts ctx = let (program_mode, poly) = Attributes.(parse (Notations.(program ++ poly PolyFlags.Assumption))) atts in ComAssumption.do_context ~program_mode ~poly ctx let vernac_existing_instance ~atts insts = let locality = Attributes.parse hint_locality atts in List.iter (fun (id, info) -> let g = qualid_global id in Classes.existing_instance ?loc:id.loc locality g (Some info)) insts let vernac_existing_class id = Record.declare_existing_class (qualid_global id) (***********) (* Solving *) let command_focus = Proof.new_focus_kind "command_focus" let focus_command_cond = Proof.no_cond command_focus let vernac_set_end_tac pstate tac = let tac = Gentactic.intern (Global.env()) tac in Declare.Proof.set_endline_tactic tac pstate (************) (* Commands *) let vernac_create_hintdb ~module_local id b = Hints.create_hint_db module_local id TransparentState.full b let warn_implicit_core_hint_db = CWarnings.create ~name:"implicit-core-hint-db" ~category:Deprecation.Version.v8_10 (fun () -> strbrk "Adding and removing hints in the core database implicitly is deprecated. " ++ strbrk"Please specify a hint database.") let warn_implicit_create_hint_db = CWarnings.create ~name:"implicit-create-hint-db" ~category:Deprecation.Version.v9_2 (fun db -> strbrk "Implicitly declaring hint databases is deprecated. Please explicitly create " ++ quote (str db)) let vernac_remove_hints ~atts dbnames ids = let locality = Attributes.(parse hint_locality atts) in let dbnames = if List.is_empty dbnames then (warn_implicit_core_hint_db (); ["core"]) else dbnames in Hints.remove_hints ~locality dbnames (List.map Smartlocate.global_with_alias ids) let vernac_hints ~atts dbnames h = let dbnames = if List.is_empty dbnames then (warn_implicit_core_hint_db (); ["core"]) else dbnames in let locality, poly = Attributes.(parse Notations.(hint_locality ++ polymorphic) atts) in let check_db db = if String.equal db "nocore" then () else match Hints.searchtable_map db with | _ -> () | exception Not_found -> let () = warn_implicit_create_hint_db db in Hints.create_hint_db false db TransparentState.empty false in let () = List.iter check_db dbnames in let poly = PolyFlags.of_univ_poly poly (* FIXME cumulativity not handled *) in Hints.add_hints ~locality dbnames (ComHints.interp_hints ~poly h) let warn_deprecated_notation_for_abbreviation = CWarnings.create ~name:"notation-for-abbreviation" ~category:Deprecation.Version.v9_2 ~quickfix:(fun ~loc () -> [Quickfix.make ~loc (str "Abbreviation")]) (fun () -> strbrk "Use of \"Notation\" keyword for abbreviations is deprecated, \ use \"Abbreviation\" instead.") let vernac_abbreviation ~warn_old_notation ~atts lid x only_parsing = Option.iter (fun loc -> warn_deprecated_notation_for_abbreviation ~loc ()) warn_old_notation; let local, user_warns = Attributes.(parse Notations.(hint_locality_no_sections ++ user_warns_with_use_globref_instead) atts) in Dumpglob.dump_definition lid false "abbrev"; Metasyntax.add_abbreviation ~local user_warns (Global.env()) lid.v x only_parsing let default_env () = { Notation_term.ninterp_var_type = Id.Map.empty; ninterp_rec_vars = Id.Map.empty; } let vernac_reserve bl = let sb_decl = (fun (idl,c) -> let env = Global.env() in let sigma = Evd.from_env env in let t,ctx = Constrintern.interp_type env sigma c in let t = let flags = { (PrintingFlags.Detype.current()) with universes = false } in Detyping.detype Detyping.Now ~flags env (Evd.from_ctx ctx) t in let t,_ = Notation_ops.notation_constr_of_glob_constr (default_env ()) t in Reserve.declare_reserved_type idl t) in List.iter sb_decl bl let vernac_generalizable ~local = let local = Option.default true local in Implicit_quantifiers.declare_generalizable ~local let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Allow";"StrictProp"]; optread = (fun () -> Global.sprop_allowed()); optwrite = Global.set_allow_sprop } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Silent"]; optread = (fun () -> !Flags.quiet); optwrite = ((:=) Flags.quiet) } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Implicit";"Arguments"]; optread = Impargs.is_implicit_args; optwrite = Impargs.make_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Strict";"Implicit"]; optread = Impargs.is_strict_implicit_args; optwrite = Impargs.make_strict_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Strongly";"Strict";"Implicit"]; optread = Impargs.is_strongly_strict_implicit_args; optwrite = Impargs.make_strongly_strict_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Contextual";"Implicit"]; optread = Impargs.is_contextual_implicit_args; optwrite = Impargs.make_contextual_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Reversible";"Pattern";"Implicit"]; optread = Impargs.is_reversible_pattern_implicit_args; optwrite = Impargs.make_reversible_pattern_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Maximal";"Implicit";"Insertion"]; optread = Impargs.is_maximal_implicit_args; optwrite = Impargs.make_maximal_implicit_args } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Kernel"; "Term"; "Sharing"]; optread = (fun () -> (Global.typing_flags ()).Declarations.share_reduction); optwrite = Global.set_share_reduction } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Printing";"Compact";"Contexts"]; optread = (fun () -> Printer.get_compact_context()); optwrite = (fun b -> Printer.set_compact_context b) } let () = declare_int_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Printing";"Depth"]; optread = Topfmt.get_depth_boxes; optwrite = Topfmt.set_depth_boxes } let () = declare_int_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Printing";"Width"]; optread = Topfmt.get_margin; optwrite = Topfmt.set_margin } let () = (* no summary: handled as part of the debug state *) declare_option ~no_summary:true ~kind:BoolKind { optstage = Summary.Stage.Interp; optdepr = Some (Deprecation.make ~since:"9.1" ~note:"Set Debug \"vmbytecode\" instead." ()); optkey = ["Dump";"Bytecode"]; optread = (fun () -> CDebug.get_flag Vmbytegen.dump_bytecode_flag); optwrite = (fun b -> CDebug.set_flag Vmbytegen.dump_bytecode_flag b); } let () = (* no summary: handled as part of the debug state *) declare_option ~no_summary:true ~kind:BoolKind { optstage = Summary.Stage.Interp; optdepr = Some (Deprecation.make ~since:"9.1" ~note:"Set Debug \"vmlambda\" instead." ()); optkey = ["Dump";"Lambda"]; optread = (fun () -> CDebug.get_flag Vmlambda.dump_lambda_flag); optwrite = (fun b -> CDebug.set_flag Vmlambda.dump_lambda_flag b); } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Parsing";"Explicit"]; optread = (fun () -> !Constrintern.parsing_explicit); optwrite = (fun b -> Constrintern.parsing_explicit := b) } let () = let preprocess flags = CWarnings.check_unknown_warnings flags; CWarnings.normalize_flags_string flags in declare_append_only_option ~preprocess ~sep:"," { optstage = Summary.Stage.Synterp; optdepr = None; optkey = ["Warnings"]; optread = CWarnings.get_flags; optwrite = CWarnings.set_flags } let () = declare_append_only_option ~sep:"," { optstage = Summary.Stage.Synterp; optdepr = None; optkey = ["Debug"]; optread = CDebug.get_flags; optwrite = CDebug.set_flags } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Guard"; "Checking"]; optread = (fun () -> (Global.typing_flags ()).Declarations.check_guarded); optwrite = (fun b -> Global.set_check_guarded b) } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Positivity"; "Checking"]; optread = (fun () -> (Global.typing_flags ()).Declarations.check_positive); optwrite = (fun b -> Global.set_check_positive b) } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Universe"; "Checking"]; optread = (fun () -> (Global.typing_flags ()).Declarations.check_universes); optwrite = (fun b -> Global.set_check_universes b) } let () = declare_bool_option { optstage = Summary.Stage.Interp; optdepr = None; optkey = ["Definitional"; "UIP"]; optread = (fun () -> (Global.typing_flags ()).Declarations.allow_uip); optwrite = (fun b -> Global.set_typing_flags {(Global.typing_flags ()) with Declarations.allow_uip = b}) } let vernac_set_strategy ~local l = let local = Option.default false local in let glob_ref r = match smart_global r with | GlobRef.ConstRef sp -> begin match Structures.PrimitiveProjections.find_opt sp with | None -> Evaluable.EvalConstRef sp | Some p -> Evaluable.EvalProjectionRef p end | GlobRef.VarRef id -> Evaluable.EvalVarRef id | _ -> user_err Pp.(str "Cannot set an inductive type or a constructor as transparent.") in let l = List.map (fun (lev,ql) -> (lev,List.map glob_ref ql)) l in Redexpr.set_strategy local l let vernac_set_opacity ~on_proj_constant ~local (v,l) = let local = Option.default true local in let glob_ref r = match smart_global r with | GlobRef.ConstRef sp -> begin match Structures.PrimitiveProjections.find_opt sp with | None when on_proj_constant -> user_err Pp.(str "Only compatibility constant opacity can be set this way.") | None -> Evaluable.EvalConstRef sp | Some _ when on_proj_constant -> Evaluable.EvalConstRef sp | Some p -> Evaluable.EvalProjectionRef p end | GlobRef.VarRef id -> Evaluable.EvalVarRef id | _ -> user_err Pp.(str "Cannot set an inductive type or a constructor as transparent.") in let l = List.map glob_ref l in Redexpr.set_strategy local [v,l] let get_current_context_of_args ~pstate = match pstate with | None -> fun _ -> let env = Global.env () in Evd.(from_env env, env) | Some lemma -> function | Some n -> Declare.Proof.get_goal_context lemma n | None -> Declare.Proof.get_current_context lemma let query_command_selector ?loc = function | None -> None | Some (Goal_select.SelectList [NthSelector n]) -> Some n | _ -> user_err ?loc (str "Query commands only support the single numbered goal selector.") let check_may_eval env sigma redexp rc = let gc = Constrintern.intern_unknown_if_term_or_type env sigma rc in let sigma, c = Pretyping.understand_tcc env sigma gc in let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in Evarconv.check_problems_are_solved env sigma; let sigma = Evd.minimize_universes sigma in let (qs, us), csts as uctx = Evd.sort_context_set sigma in let { Environ.uj_val=c; uj_type=ty; } = if Evarutil.has_undefined_evars sigma c || List.exists (Context.Named.Declaration.exists (Evarutil.has_undefined_evars sigma)) (EConstr.named_context env) then Evarutil.j_nf_evar sigma (Retyping.get_judgment_of env sigma c) else let env = Evarutil.nf_env_evar sigma env in let env = Environ.push_qualities ~rigid:false (qs, fst csts) env in (* XXX *) let env = Environ.push_context_set (us, snd csts) env in let c = EConstr.to_constr sigma c in let env = Safe_typing.push_private_constants env (Evd.seff_private @@ Evd.eval_side_effects sigma) in (* OK to call kernel which does not support evars *) Environ.on_judgment EConstr.of_constr (Arguments_renaming.rename_typing env c) in let sigma, c = match redexp with | None -> sigma, c | Some r -> let sigma, r = Redexpr.interp_redexp_no_ltac env sigma r in let r, _ = Redexpr.reduction_of_red_expr env r in let sigma, c = r env sigma c in sigma, c in let pp = let evars_of_term c = Evarutil.undefined_evars_of_term sigma c in let l = Evar.Set.union (evars_of_term c) (evars_of_term ty) in let j = { Environ.uj_val = c; uj_type = Reductionops.nf_betaiota env sigma ty } in Prettyp.print_judgment env sigma j ++ pr_ne_evar_set (fnl () ++ str "where" ++ fnl ()) (mt ()) sigma l in let hdr = if Option.has_some redexp then str " = " else mt() in hdr ++ pp ++ Printer.pr_sort_context_set sigma uctx let vernac_check_may_eval ~pstate redexp glopt rc = let glopt = query_command_selector glopt in let sigma, env = get_current_context_of_args ~pstate glopt in check_may_eval env sigma redexp rc let vernac_declare_reduction ~local s r = let local = Option.default false local in let env = Global.env () in let sigma = Evd.from_env env in Redexpr.declare_red_expr local s (snd (Redexpr.interp_redexp_no_ltac env sigma r)) (* The same but avoiding the current goal context if any *) let vernac_global_check c = let env = Global.env() in let sigma = Evd.from_env env in let c = Constrintern.intern_constr env sigma c in let sigma, c = Pretyping.understand_tcc ~flags:Pretyping.all_and_fail_flags env sigma c in let sigma = Evd.collapse_sort_variables sigma in let senv = Global.safe_env() in let (qs, us), (qcst, ucst) as uctx = Evd.sort_context_set sigma in let senv = Safe_typing.push_qualities ~rigid:false (qs, qcst) senv in (* XXX *) let senv = Safe_typing.push_context_set ~strict:false (us, ucst) senv in let c = EConstr.to_constr sigma c in let j = Safe_typing.typing senv c in Prettyp.print_safe_judgment j ++ Printer.pr_sort_context_set sigma uctx (* Printing "About" information of a hypothesis of the current goal. We only print the type and a small statement to this comes from the goal. Precondition: there must be at least one current goal. *) let print_about_hyp_globs ~pstate ?loc ref_or_by_not udecl glopt = let exception NoHyp in let open Context.Named.Declaration in try (* Fallback early to globals *) let pstate = match pstate with | None -> raise Not_found | Some pstate -> pstate in (* FIXME error on non None udecl if we find the hyp. *) let glnumopt = query_command_selector ?loc glopt in let pf = Declare.Proof.get pstate in let Proof.{goals; sigma} = Proof.data pf in let ev, id = let open Constrexpr in match glnumopt, ref_or_by_not.v with | None,AN qid when qualid_is_ident qid -> (* goal number not given, catch any failure *) (match List.nth_opt goals 0 with | None -> raise NoHyp | Some goal -> goal), qualid_basename qid | Some n,AN qid when qualid_is_ident qid -> (* goal number given, catch if wong *) (match List.nth_opt goals (n - 1) with | None -> user_err ?loc (str "No such goal: " ++ int n ++ str ".") | Some goal -> goal), qualid_basename qid | _ , _ -> raise NoHyp in let hyps = Evd.evar_filtered_context (Evd.find_undefined sigma ev) in let decl = Context.Named.lookup id hyps in let natureofid = match decl with | LocalAssum _ -> "Hypothesis" | LocalDef (_,bdy,_) ->"Constant (let in)" in let sigma, env = Declare.Proof.get_current_context pstate in v 0 (Id.print id ++ str":" ++ pr_econstr_env env sigma (NamedDecl.get_type decl) ++ fnl() ++ fnl() ++ str natureofid ++ str " of the goal context.") with (* fallback to globals *) | NoHyp | Not_found -> let sigma, env = get_current_or_global_context ~pstate in Prettyp.print_about env sigma ref_or_by_not udecl let prglob_without_notations env sigma c = let flags = PrintingFlags.Extern.current() in let flags = { flags with notations = false } in pr_glob_constr_env ~flags env sigma c let vernac_print = let no_state f = Vernactypes.(typed_vernac_gen ignore_state (fun _ -> no_state, f ())) in let with_pstate f = let f {Vernactypes.proof} = Vernactypes.no_state, f ~pstate:proof in Vernactypes.(typed_vernac_gen { ignore_state with proof = ReadOpt } f) in let with_proof_env f = with_pstate (fun ~pstate -> let sigma, env = get_current_or_global_context ~pstate in f env sigma) in let with_proof_env_and_opaques f = let open Vernactypes in let f {proof; opaque_access} = let sigma, env = get_current_or_global_context ~pstate:proof in no_state, f ~opaque_access env sigma in typed_vernac_gen { ignore_state with proof = ReadOpt; opaque_access = Access } f in function | PrintTypingFlags -> with_proof_env @@ fun env _sigma -> pr_typing_flags (Environ.typing_flags env) | PrintTables -> no_state print_tables | PrintFullContext -> with_proof_env Prettyp.print_full_context_typ | PrintSectionContext qid -> with_proof_env @@ fun env sigma -> Prettyp.print_sec_context_typ env sigma qid | PrintInspect n -> with_proof_env @@ fun env sigma -> Prettyp.inspect env sigma n | PrintGrammar ent -> no_state @@ fun () -> Metasyntax.pr_grammar ent | PrintCustomGrammar ent -> no_state @@ fun () -> Metasyntax.pr_custom_grammar ent | PrintKeywords -> no_state Metasyntax.pr_keywords | PrintLoadPath dir -> (* For compatibility ? *) no_state @@ fun () -> print_loadpath dir | PrintLibraries -> no_state print_libraries | PrintModule qid -> no_state @@ fun () -> print_module qid | PrintModuleType qid -> no_state @@ fun () -> print_modtype qid | PrintNamespace ns -> with_pstate @@ print_namespace ns | PrintMLLoadPath -> no_state @@ fun () -> let paths = Findlib.search_path () in v 0 (prlist_with_sep cut str paths ) | PrintMLModules -> no_state Mltop.print_ml_modules | PrintDebugGC -> no_state Mltop.print_gc | PrintName (qid,udecl) -> with_proof_env_and_opaques @@ fun ~opaque_access env sigma -> Prettyp.print_name opaque_access env sigma qid udecl | PrintGraph -> no_state Prettyp.print_graph | PrintClasses -> no_state Prettyp.print_classes | PrintTypeclasses -> no_state Prettyp.print_typeclasses | PrintInstances c -> no_state @@ fun () -> Prettyp.print_instances (smart_global c) | PrintCoercions -> no_state Prettyp.print_coercions | PrintNotation (entry, ntnstr) -> with_proof_env @@ fun env sigma -> Prettyp.print_notation env sigma entry ntnstr | PrintCoercionPaths (cls,clt) -> no_state @@ fun () -> Prettyp.print_coercion_paths (cl_of_qualid cls) (cl_of_qualid clt) | PrintCanonicalConversions qids -> with_proof_env @@ fun env sigma -> let grefs = List.map Smartlocate.smart_global qids in Prettyp.print_canonical_projections env sigma grefs | PrintUniverses prunivs -> no_state @@ fun ()-> print_universes prunivs | PrintSorts -> no_state print_sorts | PrintHint r -> with_proof_env @@ fun env sigma -> Hints.pr_hint_ref env sigma (smart_global r) | PrintHintGoal -> with_pstate @@ fun ~pstate -> begin match pstate with | Some pstate -> let pf = Declare.Proof.get pstate in Hints.pr_applicable_hint pf | None -> str "No proof in progress" end | PrintHintDbName s -> with_proof_env @@ fun env sigma -> Hints.pr_hint_db_by_name env sigma s | PrintHintDb -> with_proof_env @@ fun env sigma -> Hints.pr_searchtable env sigma | PrintScopes -> with_proof_env @@ fun env sigma -> Notation.pr_scopes (prglob_without_notations env sigma) | PrintScope s -> with_proof_env @@ fun env sigma -> Notation.pr_scope (prglob_without_notations env sigma) s | PrintVisibility s -> with_proof_env @@ fun env sigma -> Notation.pr_visibility (prglob_without_notations env sigma) s | PrintAbout (ref_or_by_not,udecl,glnumopt) -> with_pstate @@ print_about_hyp_globs ref_or_by_not udecl glnumopt | PrintImplicit qid -> with_proof_env @@ fun env _sigma -> Prettyp.print_impargs env (smart_global qid) | PrintAssumptions (o,t,rs) -> with_proof_env_and_opaques @@ fun ~opaque_access env sigma -> (* Prints all the axioms and section variables used by a term *) let st = Conv_oracle.get_transp_state (Environ.oracle env) in let grs = List.map smart_global rs in let nassums = Assumptions.assumptions opaque_access st ~add_opaque:o ~add_transparent:t grs in Printer.pr_assumptionset env sigma nassums | PrintStrategy r -> no_state @@ fun () -> print_strategy r | PrintRegistered -> no_state print_registered | PrintRegisteredSchemes -> no_state print_registered_schemes let vernac_search ~pstate ~atts s gopt r = let open ComSearch in let gopt = query_command_selector gopt in let sigma, env = match gopt with (* 1st goal by default if it exists, otherwise no goal at all *) | None -> begin try get_goal_or_global_context ~pstate 1 with Proof.NoSuchGoal _ -> let env = Global.env () in Evd.from_env env, env end (* if goal selector is given and wrong, then let exceptions be raised. *) | Some g -> get_goal_or_global_context ~pstate g in interp_search env sigma s r let vernac_locate ~pstate query = let open Constrexpr in let sigma, env = get_current_or_global_context ~pstate in match query with | LocateAny {v=AN qid} -> Prettyp.print_located_qualid env qid | LocateTerm {v=AN qid} -> Prettyp.print_located_term env qid | LocateAny {v=ByNotation (ntn, sc)} (* TODO : handle Ltac notations *) | LocateTerm {v=ByNotation (ntn, sc)} -> Notation.locate_notation (prglob_without_notations env sigma) ntn sc | LocateLibrary qid -> print_located_library qid | LocateModule qid -> Prettyp.print_located_module env qid | LocateOther (s, qid) -> Prettyp.print_located_other env s qid | LocateFile f -> locate_file f let warn_unknown_scheme_kind = CWarnings.create ~name:"unknown-scheme-kind" Pp.(fun sk -> str "Unknown scheme kind " ++ Libnames.pr_qualid sk ++ str ".") let vernac_register ~atts qid r = let gr = Smartlocate.global_with_alias qid in match r with | RegisterInline -> unsupported_attributes atts; begin match gr with | GlobRef.ConstRef c -> Global.register_inline c | _ -> CErrors.user_err ?loc:qid.loc (Pp.str "Register Inline: expecting a constant.") end | RegisterCoqlib n -> let ns, id = Libnames.repr_qualid n in if DirPath.equal (dirpath_of_string "kernel") ns then begin unsupported_attributes atts; if Lib.sections_are_opened () then user_err Pp.(str "Registering a kernel type is not allowed in sections."); let CPrimitives.PIE pind = match Id.to_string id with | "ind_bool" -> CPrimitives.(PIE PIT_bool) | "ind_carry" -> CPrimitives.(PIE PIT_carry) | "ind_pair" -> CPrimitives.(PIE PIT_pair) | "ind_cmp" -> CPrimitives.(PIE PIT_cmp) | "ind_f_cmp" -> CPrimitives.(PIE PIT_f_cmp) | "ind_f_class" -> CPrimitives.(PIE PIT_f_class) | k -> CErrors.user_err ?loc:n.loc Pp.(str "Register: unknown identifier β€œ" ++ str k ++ str "” in the \"kernel\" namespace.") in match gr with | GlobRef.IndRef ind -> Global.register_inductive ind pind | _ -> CErrors.user_err ?loc:qid.loc (Pp.str "Register in kernel: expecting an inductive type.") end else let local = Attributes.parse hint_locality_default_superglobal atts in Rocqlib.register_ref local (Libnames.string_of_qualid n) gr | RegisterScheme { inductive; scheme_kind } -> let local = Attributes.parse hint_locality_default_superglobal atts in let scheme_kind_s = Libnames.string_of_qualid scheme_kind in (* Specific test for the All and AllForall keys, as there are an infinite number of them *) let test_all prefix s = String.starts_with ~prefix s && String.for_all (function '0' | '1' -> true | _ -> false) @@ String.sub s (String.length prefix) (String.length s - String.length prefix) in let () = if not (Ind_tables.is_declared_scheme_object scheme_kind_s || String.equal "All" scheme_kind_s || String.equal "AllForall" scheme_kind_s || test_all "All_" scheme_kind_s || test_all "AllForall_" scheme_kind_s) then warn_unknown_scheme_kind ?loc:scheme_kind.loc scheme_kind in let ind = Smartlocate.global_inductive_with_alias inductive in Dumpglob.add_glob ?loc:inductive.loc (IndRef ind); DeclareScheme.declare_scheme local scheme_kind_s (ind, gr) let vernac_library_attributes atts = if Global.is_curmod_library () && not (Lib.sections_are_opened ()) then let user_warns = Attributes.parse user_warns atts in let user_warns = Option.default UserWarn.empty user_warns in Lib.Synterp.declare_info user_warns else user_err (Pp.str "A library attribute should be at toplevel of the library.") (********************) (* Proof management *) let vernac_focus ~pstate gln = Declare.Proof.map ~f:(fun p -> match gln with | None -> Proof.focus focus_command_cond () 1 p | Some 0 -> user_err Pp.(str "Invalid goal number: 0. Goal numbering starts with 1.") | Some n -> Proof.focus focus_command_cond () n p) pstate (* Unfocuses one step in the focus stack. *) let vernac_unfocus ~pstate = Declare.Proof.map ~f:(fun p -> Proof.unfocus command_focus p ()) pstate (* Checks that a proof is fully unfocused. Raises an error if not. *) let vernac_unfocused ~pstate = let p = Declare.Proof.get pstate in if Proof.unfocused p then str"The proof is indeed fully unfocused." else user_err Pp.(str "The proof is not fully unfocused.") (* "{" focuses on the first goal, "n: {" focuses on the n-th goal "}" unfocuses, provided that the proof of the goal has been completed. *) let subproof_kind = Proof.new_focus_kind "subproof" let subproof_cond = Proof.done_cond subproof_kind let vernac_subproof gln ~pstate = Declare.Proof.map ~f:(fun p -> match gln with | None -> Proof.focus subproof_cond () 1 p | Some (Goal_select.SelectList [NthSelector n]) -> Proof.focus subproof_cond () n p | Some (Goal_select.SelectList [IdSelector id]) -> Proof.focus_id subproof_cond () id p | _ -> user_err (str "Brackets do not support multi-goal selectors.")) pstate let vernac_end_subproof ~pstate = Declare.Proof.map ~f:(fun p -> Proof.unfocus subproof_kind p ()) pstate let vernac_bullet (bullet : Proof_bullet.t) ~pstate = Declare.Proof.map ~f:(fun p -> Proof_bullet.put p bullet) pstate let show_goal goalref proof oldp = match goalref with | OpenSubgoals -> pr_open_subgoals ~oldp proof | NthGoal n -> pr_nth_open_subgoal ~oldp ~proof n | GoalId qid -> pr_goal_by_id ~oldp ~proof qid (* Stack is needed due to show proof names, should deprecate / remove and take pstate *) let vernac_show ~pstate = match pstate with (* Show functions that don't require a proof state *) | None -> begin function | ShowProof -> show_proof ~pstate:None | ShowMatch id -> show_match id | _ -> user_err (str "This command requires an open proof.") end (* Show functions that require a proof state *) | Some pstate -> let proof = Declare.Proof.get pstate in begin function | ShowGoal goalref -> show_goal goalref proof None | ShowExistentials -> show_top_evars ~proof | ShowUniverses -> show_universes ~proof (* Deprecate *) | ShowProofNames -> Id.print (Declare.Proof.get_name pstate) | ShowIntros all -> show_intro ~proof all | ShowProof -> show_proof ~pstate:(Some pstate) | ShowMatch id -> show_match id end let vernac_check_guard ~pstate = Declare.Proof.control_only_guard pstate; str "The condition holds up to here." let vernac_validate_proof ~pstate = let pts = Declare.Proof.get pstate in let { Proof.entry; Proof.sigma } = Proof.data pts in let hyps, pfterm, pftyp = List.hd (Proofview.initial_goals entry) in (* XXX can the initial hyps contain something broken? For now assume they're correct. NB: in the "Lemma foo args : bla." case the args are part of the term and intro'd after the proof is opened. Only the section variables are in the hyps. *) let env = Environ.reset_with_named_context hyps (Global.env ()) in let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in let sigma' = Typing.check env sigma pfterm pftyp in let evar_issues = (* Use Evar.Map.merge as a kind of for_all2 *) Evar.Map.merge (fun e orig now -> match orig, now with | None, None -> assert false | Some _, Some _ -> None (* assume same *) | Some evi, None -> let EvarInfo evi' = Evd.find sigma' e in let body = match Evd.evar_body evi' with | Evar_empty -> assert false | Evar_defined body -> body in Some Pp.(str "Evar " ++ Printer.pr_evar sigma (e, evi) ++ spc() ++ str "was inferred by unification to be" ++ spc() ++ pr_econstr_env (Evd.evar_env env evi') sigma' body) | None, Some _ -> (* ignore new evar *) assert (not (Evd.is_defined sigma e)); None ) (Evd.undefined_map sigma) (Evd.undefined_map sigma') in (* TODO check ustate *) if Evar.Map.is_empty evar_issues then str "No issues found." else prlist_with_sep fnl snd (Evar.Map.bindings evar_issues) let vernac_proof pstate tac using = let is_let = match Declare.Proof.definition_scope pstate with | Discharge -> true | Global _ -> false in let using = if not is_let then Option.append using (Proof_using.get_default_proof_using ()) else let () = if Option.has_some using then CErrors.user_err Pp.(str "Let does not support Proof using.") in None in let tacs = if Option.is_empty tac then "tac:no" else "tac:yes" in let usings = if Option.is_empty using then "using:no" else "using:yes" in Aux_file.record_in_aux_at "VernacProof" (tacs^" "^usings); let pstate = Option.fold_left vernac_set_end_tac pstate tac in let set_proof_using ps using = Declare.Proof.set_proof_using ps using |> snd in let pstate = Option.fold_left set_proof_using pstate using in pstate let translate_vernac_synterp ?loc ~atts v = let open Vernactypes in match v with | EVernacNotation { local; decl } -> vtdefault(fun () -> Metasyntax.add_notation_interpretation ~local (Global.env()) decl) | EVernacDeclareMLModule f -> vtdefault (fun () -> Mltop.run_interp_fun f) | EVernacDefineModule (export,lid,bl,argsexport,mtys,mexprl) -> let i () = unsupported_attributes atts; vernac_define_module export lid bl argsexport mtys mexprl in (* XXX: We should investigate if eventually this should be made VtNoProof in all cases. *) vernac_begin_segment ~interactive:(List.is_empty mexprl) i | EVernacDeclareModuleType (lid,bl,argsexport,mtys,exprl) -> vernac_begin_segment ~interactive:(List.is_empty exprl) (fun () -> unsupported_attributes atts; vernac_declare_module_type lid bl argsexport mtys exprl) (* Modules *) | EVernacDeclareModule (export,lid,bl,mty) -> vtdefault(fun () -> unsupported_attributes atts; vernac_declare_module export lid bl mty) | EVernacInclude in_asts -> vtdefault(fun () -> unsupported_attributes atts; vernac_include in_asts) (* Gallina extensions *) | EVernacBeginSection lid -> vernac_begin_segment ~interactive:true (fun () -> vernac_begin_section ~poly:(only_polymorphism atts) lid) | EVernacEndSegment lid -> unsupported_attributes atts; vernac_end_segment lid | EVernacRequire (needed, modrefl, export, qidl) -> vtdefault(fun () -> unsupported_attributes atts; vernac_require_interp needed modrefl export qidl) | EVernacImport (export,mpl) -> vtdefault(fun () -> unsupported_attributes atts; vernac_import export mpl) | EVernacSetOption { export; key; value } -> vtdefault(fun () -> let atts = if export then CAst.make ?loc ("export", VernacFlagEmpty) :: atts else atts in Vernacoptions.vernac_set_option ~locality:(parse option_locality atts) ~stage:Summary.Stage.Interp key value) | EVernacNoop -> vtdefault(fun () -> ()) | EVernacLoad _ -> anomaly (str "type_vernac") (* Extensions *) | EVernacExtend f -> f let translate_pure_vernac ?loc ~atts v = let open Vernactypes in match v with | VernacAbortAll | VernacRestart | VernacUndo _ | VernacUndoTo _ | VernacResetName _ | VernacResetInitial | VernacBack _ -> anomaly (str "type_vernac") (* Syntax *) | VernacDeclareScope sc -> vtdefault(fun () -> with_module_locality ~atts vernac_declare_scope sc) | VernacDelimiters (sc,lr) -> vtdefault(fun () -> with_module_locality ~atts vernac_delimiters sc lr) | VernacBindScope (sc,rl) -> vtdefault(fun () -> vernac_bind_scope ~atts sc rl) | VernacOpenCloseScope (b, s) -> vtdefault(fun () -> with_section_locality ~atts vernac_open_close_scope (b,s)) | VernacEnableNotation (on,rule,interp,flags,scope) -> vtdefault(fun () -> with_module_locality ~atts vernac_enable_notation on rule interp flags scope) (* Gallina *) | VernacDefinition ((discharge,kind as dkind),lid,DefineBody (bl,red_option,c,typ)) -> let coercion = match kind with Decls.Coercion -> true | _ -> false in let atts, refine = Attributes.(parse_with_extra Classes.refine_att) atts in if refine then vtopenproof(fun () -> with_def_attributes ~coercion ~discharge:(discharge, "\"Let\"", "\"#[local] Definition\"") ~atts vernac_definition_refine dkind lid bl red_option c typ) else vtmodifyprogram (fun ~pm -> with_def_attributes ~coercion ~discharge:(discharge, "\"Let\"", "\"#[local] Definition\"") ~atts vernac_definition ~pm dkind lid bl red_option c typ) | VernacDefinition ((discharge,kind as dkind),lid,ProveBody(bl,typ)) -> let coercion = match kind with Decls.Coercion -> true | _ -> false in vtopenproof(fun () -> with_def_attributes ~coercion ~discharge:(discharge, "\"Let\"", "\"#[local] Definition\"") ~atts vernac_definition_interactive dkind lid bl typ) | VernacStartTheoremProof (k,l) -> vtopenproof(fun () -> with_def_attributes ~atts vernac_start_proof k l) | VernacExactProof c -> vtcloseproof (fun ~lemma -> unsupported_attributes atts; vernac_exact_proof ~lemma c) | VernacAssumption ((discharge,kind),nl,l) -> vtdefault(fun () -> with_def_attributes ~atts ~discharge:(discharge, "\"Variable\" or \"Hypothesis\"", "\"#[local] Parameter\" or \"#[local] Axiom\"") vernac_assumption kind l nl) | VernacSymbol l -> vtdefault (fun () -> let (unfold_fix, poly) = Attributes.(parse Notations.(unfold_fix ++ poly PolyFlags.Assumption)) atts in ComRewriteRule.do_symbols ~poly ~unfold_fix l) | VernacInductive (finite, l) -> vtdefault(fun () -> vernac_inductive ~atts finite l) | VernacFixpoint (discharge, l) -> let atts, refine = Attributes.(parse_with_extra Classes.refine_att) atts in let opens = refine || List.exists (fun { body_def } -> Option.is_empty body_def) (snd l) in let discharge = discharge, "\"Let Fixpoint\"", "\"#[local] Fixpoint\"" in (if opens then vtopenproof (fun () -> let pm, proof = with_def_attributes ~discharge ~atts (vernac_fixpoint ~refine ~pm:None) l in assert (Option.is_empty pm); Option.get proof) else vtmodifyprogram (fun ~pm -> let pm, proof = with_def_attributes ~discharge ~atts (vernac_fixpoint ~refine ~pm:(Some pm)) l in assert (Option.is_empty proof); Option.get pm)) | VernacCoFixpoint (discharge, l) -> let atts, refine = Attributes.(parse_with_extra Classes.refine_att) atts in let opens = refine || List.exists (fun { body_def } -> Option.is_empty body_def) l in let discharge = discharge, "\"Let CoFixpoint\"", "\"#[local] CoFixpoint\"" in (if opens then vtopenproof (fun () -> let pm, proof = with_def_attributes ~discharge ~atts (vernac_cofixpoint ~refine ~pm:None) l in assert (Option.is_empty pm); Option.get proof) else vtmodifyprogram (fun ~pm -> let pm, proof = with_def_attributes ~discharge ~atts (vernac_cofixpoint ~refine ~pm:(Some pm)) l in assert (Option.is_empty proof); Option.get pm)) | VernacScheme l -> vtdefault(fun () -> vernac_scheme atts l) | VernacSchemeAll (id, strpos) -> vtdefault(fun () -> unsupported_attributes atts; DeclareInd.do_scheme_all id strpos) | VernacSchemeEquality (sch,id) -> vtdefault(fun () -> unsupported_attributes atts; vernac_scheme_equality sch id ~locmap:(Ind_tables.Locmap.default loc)) | VernacCombinedScheme (id, l) -> vtdefault(fun () -> unsupported_attributes atts; vernac_combined_scheme id l ~locmap:(Ind_tables.Locmap.default loc)) | VernacUniverse l -> vtdefault(fun () -> vernac_universe ~poly:(only_polymorphism atts) l) | VernacSort l -> vtdefault(fun () -> vernac_sort ~poly:(only_polymorphism atts) l) | VernacConstraint l -> vtdefault(fun () -> vernac_constraint ~poly:(only_polymorphism atts) l) | VernacAddRewRule (id, c) -> vtdefault (fun () -> unsupported_attributes atts; ComRewriteRule.do_rules id.v c) (* Gallina extensions *) | VernacNameSectionHypSet (lid, set) -> vtdefault(fun () -> unsupported_attributes atts; vernac_name_sec_hyp lid set) | VernacCanonical qid -> vtdefault(fun () -> vernac_canonical ~local:(only_locality atts) qid) | VernacCoercion (r,st) -> vtdefault(fun () -> vernac_coercion ~atts r st) | VernacIdentityCoercion (id,s,t) -> vtdefault(fun () -> vernac_identity_coercion ~atts id s t) (* Type classes *) | VernacInstance (name, bl, t, props, info) -> let atts, program = Attributes.(parse_with_extra program) atts in if program then vtmodifyprogram (vernac_instance_program ~atts name bl t props info) else begin match props with | None -> vtopenproof (fun () -> vernac_instance_interactive ~atts name bl t info None) | Some props -> let atts, refine = Attributes.parse_with_extra Classes.refine_att atts in if refine then vtopenproof (fun () -> vernac_instance_interactive ~atts name bl t info (Some props)) else vtdefault (fun () -> vernac_instance ~atts name bl t props info) end | VernacDeclareInstance (id, bl, inst, info) -> vtdefault(fun () -> vernac_declare_instance ~atts id bl inst info) | VernacContext sup -> vtdefault(fun () -> vernac_context ~atts sup) | VernacExistingInstance insts -> vtdefault(fun () -> vernac_existing_instance ~atts insts) | VernacExistingClass id -> vtdefault(fun () -> unsupported_attributes atts; vernac_existing_class id) (* Commands *) | VernacCreateHintDb (dbname,b) -> vtdefault(fun () -> with_module_locality ~atts vernac_create_hintdb dbname b) | VernacRemoveHints (dbnames,ids) -> vtdefault(fun () -> vernac_remove_hints ~atts dbnames ids) | VernacHints (dbnames,hints) -> vtdefault(fun () -> vernac_hints ~atts dbnames hints) | VernacAbbreviation (id,c,b,warn_old_notation) -> vtdefault(fun () -> vernac_abbreviation ~warn_old_notation ~atts id c b) | VernacArguments (qid, args, more_implicits, flags) -> vtdefault(fun () -> with_section_locality ~atts (ComArguments.vernac_arguments qid args more_implicits flags)) | VernacReserve bl -> vtdefault(fun () -> unsupported_attributes atts; vernac_reserve bl) | VernacGeneralizable gen -> vtdefault(fun () -> with_locality ~atts vernac_generalizable gen) | VernacSetOpacity (qidl, on_proj_constant) -> vtdefault(fun () -> with_locality ~atts (vernac_set_opacity ~on_proj_constant) qidl) | VernacSetStrategy l -> vtdefault(fun () -> with_locality ~atts vernac_set_strategy l) | VernacRemoveOption (key,v) -> vtdefault(fun () -> let local = Attributes.parse Attributes.hint_locality atts in Vernacoptions.vernac_remove_option local key v) | VernacAddOption (key,v) -> vtdefault(fun () -> let local = Attributes.parse Attributes.hint_locality atts in Vernacoptions.vernac_add_option local key v) | VernacMemOption (key,v) -> vtdefault(fun () -> unsupported_attributes atts; Vernacoptions.vernac_mem_option key v) | VernacPrintOption key -> vtdefault(fun () -> unsupported_attributes atts; Vernacoptions.vernac_print_option key) | VernacCheckMayEval (r,g,c) -> vtreadproofopt(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_check_may_eval ~pstate r g c) | VernacDeclareReduction (s,r) -> vtdefault(fun () -> with_locality ~atts vernac_declare_reduction s r) | VernacGlobalCheck c -> vtdefault(fun () -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_global_check c) | VernacPrint p -> unsupported_attributes atts; Vernactypes.map_typed_vernac Feedback.msg_notice (vernac_print p) | VernacSearch (s,g,r) -> vtreadproofopt( unsupported_attributes atts; vernac_search ~atts s g r) | VernacLocate l -> vtreadproofopt(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_locate ~pstate l) | VernacRegister (qid, r) -> vtnoproof(fun () -> vernac_register ~atts qid r) | VernacPrimitive ((id, udecl), prim, typopt) -> vtdefault(fun () -> unsupported_attributes atts; ComPrimitive.do_primitive id udecl prim typopt) | VernacComments l -> vtdefault(fun () -> unsupported_attributes atts; Flags.if_verbose Feedback.msg_info (str "Comments ok\n")) | VernacAttributes atts -> vtdefault(fun () -> vernac_library_attributes atts) (* Proof management *) | VernacFocus n -> vtmodifyproof(unsupported_attributes atts;vernac_focus n) | VernacUnfocus -> vtmodifyproof(unsupported_attributes atts;vernac_unfocus) | VernacUnfocused -> vtreadproof(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_unfocused ~pstate) | VernacBullet b -> vtmodifyproof( unsupported_attributes atts; vernac_bullet b) | VernacSubproof n -> vtmodifyproof( unsupported_attributes atts; vernac_subproof n) | VernacEndSubproof -> vtmodifyproof( unsupported_attributes atts; vernac_end_subproof) | VernacShow s -> vtreadproofopt(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_show ~pstate s) | VernacCheckGuard -> vtreadproof(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_check_guard ~pstate) | VernacValidateProof -> vtreadproof(fun ~pstate -> unsupported_attributes atts; Feedback.msg_notice @@ vernac_validate_proof ~pstate) | VernacProof (tac, using) -> vtmodifyproof(fun ~pstate -> unsupported_attributes atts; vernac_proof pstate tac using) | VernacEndProof pe -> unsupported_attributes atts; vtcloseproof (vernac_end_proof pe) | VernacAbort -> unsupported_attributes atts; vtcloseproof vernac_abort let translate_vernac ?loc ~atts v = match v with | VernacSynterp e -> translate_vernac_synterp ?loc ~atts e | VernacSynPure e -> translate_pure_vernac ?loc ~atts e rocq-9.2.0/vernac/vernacentries.mli000066400000000000000000000060321516144147600173310ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Evd.evar_map -> Redexpr.raw_red_expr option -> Constrexpr.constr_expr -> Pp.t (** Vernac Translation into the Vernac DSL *) val translate_vernac : ?loc:Loc.t -> atts:Attributes.vernac_flags -> Synterp.vernac_entry -> Vernactypes.typed_vernac (** Vernacular require command, used by the command line *) val vernac_require : intern:Library.Intern.t -> Libnames.qualid option -> Vernacexpr.export_with_cats option -> (Libnames.qualid * Vernacexpr.import_filter_expr) list -> unit (** Interp phase of the require command *) val vernac_require_interp : Library.library_t list -> Names.DirPath.t list -> Vernacexpr.export_with_cats option -> (Libnames.qualid * Vernacexpr.import_filter_expr) list -> unit (** Miscellaneous stuff *) val command_focus : unit Proof.focus_kind (** pre-processing and validation of VernacInductive *) module Preprocessed_Mind_decl : sig type flags = ComInductive.flags type record = { flags : flags; udecl : Constrexpr.cumul_univ_decl_expr option; primitive_proj : bool; kind : Vernacexpr.inductive_kind; records : Record.Ast.t list; } type inductive = { flags : flags; udecl : Constrexpr.cumul_univ_decl_expr option; typing_flags : Declarations.typing_flags option; private_ind : bool; uniform : ComInductive.uniform_inductive_flag; inductives : (Vernacexpr.one_inductive_expr * Vernacexpr.notation_declaration list) list; } type t = | Record of record | Inductive of inductive end val preprocess_inductive_decl : atts:Attributes.vernac_flags -> Vernacexpr.inductive_kind -> (Vernacexpr.inductive_expr * Vernacexpr.notation_declaration list) list -> Preprocessed_Mind_decl.t module DefAttributes : sig type t = { hooks : Declare.Hook.t list ; scope : Locality.definition_scope; locality : bool option; poly : PolyFlags.t; program : bool; user_warns : Globnames.extended_global_reference UserWarn.with_qf option; canonical_instance : bool; typing_flags : Declarations.typing_flags option; using : Vernacexpr.section_subset_expr option; reversible : bool; clearbody: bool option; } module Observer : Summary.OBSERVABLE with type value = unit Declare.Hook.g list Attributes.attribute val def_attributes : t Attributes.attribute end val show_goal : Vernacexpr.goal_reference -> Proof.t -> Proof.t option option -> Pp.t rocq-9.2.0/vernac/vernacexpr.mli000066400000000000000000000457051516144147600166500ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* {i string}} command. {b ("ExtractionInlinedConstant", 0)} indicates {b Extract Inlined Constant {i qualid} => {i string}} command. {b ("ExtractionInductive", 0)} indicates {b Extract Inductive {i qualid} => {i string} [ {i string} ... {string} ] {i optstring}} command. {b ("ExtractionBlacklist", 0)} indicates {b Extraction Blacklist {i ident{_1}} ... {i ident{_n}}} command. *) (* This type allows registering the inlining of constants in native compiler. It will be extended with primitive inductive types and operators *) type register_kind = | RegisterInline | RegisterCoqlib of qualid | RegisterScheme of { inductive : qualid; scheme_kind : qualid } (** {6 Types concerning the module layer} *) type module_ast_inl = module_ast * Declaremods.inline type module_binder = export_with_cats option * lident list * module_ast_inl (** {6 The type of vernacular expressions} *) type vernac_one_argument_status = { name : Name.t; recarg_like : bool; notation_scope : scope_delimiter CAst.t list; implicit_status : Glob_term.binding_kind; } type vernac_argument_status = | VolatileArg | BidiArg | RealArg of vernac_one_argument_status type arguments_modifier = [ `Assert | `ClearBidiHint | `ClearImplicits | `ClearReduction | `ClearScopes | `DefaultImplicits | `ExtraScopes | `SimplDontExposeCase (* simpl nomatch *) | `SimplNeverUnfold (* simpl never *) | `Rename ] type extend_name = { ext_plugin : string; (** Name of the plugin where the extension is defined as per DECLARE PLUGIN *) ext_entry : string; (** Name of the vernac entry where the tactic is defined, typically found after the VERNAC EXTEND statement in the source. *) ext_index : int; (* Index of the extension in the VERNAC EXTEND statement. Each parsing branch is given an offset, starting from zero. *) } type discharge = DoDischarge | NoDischarge type hint_info_expr = Constrexpr.constr_pattern_expr Typeclasses.hint_info_gen type reference_or_constr = | HintsReference of Libnames.qualid | HintsConstr of Constrexpr.constr_expr type hints_expr = | HintsResolve of (hint_info_expr * bool * reference_or_constr) list | HintsResolveIFF of bool * Libnames.qualid list * int option | HintsImmediate of reference_or_constr list | HintsUnfold of Libnames.qualid list | HintsTransparency of Libnames.qualid Hints.hints_transparency_target * bool | HintsMode of Libnames.qualid * Hints.hint_mode list | HintsConstructors of Libnames.qualid list | HintsExtern of int * Constrexpr.constr_expr option * Gentactic.raw_generic_tactic (** [synterp_vernac_expr] describes the AST of commands which have effects on parsing or parsing extensions *) type synterp_vernac_expr = | VernacLoad of verbose_flag * string | VernacReservedNotation of infix_flag * (lstring * syntax_modifier CAst.t list) | VernacNotation of infix_flag * notation_declaration | VernacDeclareCustomEntry of Id.t | VernacBeginSection of lident | VernacEndSegment of lident | VernacRequire of qualid option * export_with_cats option * (qualid * import_filter_expr) list | VernacImport of export_with_cats * (qualid * import_filter_expr) list (* Modules and Module Types *) | VernacDeclareModule of export_with_cats option * lident * module_binder list * module_ast_inl | VernacDefineModule of export_with_cats option * lident * module_binder list * module_ast_inl Declaremods.module_signature * module_ast_inl list | VernacDeclareModuleType of lident * module_binder list * module_ast_inl list * module_ast_inl list | VernacInclude of module_ast_inl list (* Auxiliary file and library management *) | VernacDeclareMLModule of string list | VernacChdir of string option | VernacExtraDependency of qualid * string * Id.t option | VernacSetOption of bool (* Export modifier? *) * Goptions.option_name * option_setting | VernacProofMode of string (* For extension *) | VernacExtend of extend_name * Genarg.raw_generic_argument list (** [synpure_vernac_expr] describes the AST of commands which have no effect on parsing or parsing extensions. On these ASTs, the syntactic interpretation phase is the identity. *) type nonrec synpure_vernac_expr = (* Syntax *) | VernacOpenCloseScope of bool * scope_name | VernacDeclareScope of scope_name | VernacDelimiters of scope_name * string option | VernacBindScope of scope_name * coercion_class list | VernacEnableNotation of bool * (string, Id.t list * qualid) Util.union option * constr_expr option * notation_enable_modifier list * notation_with_optional_scope option (* Gallina *) | VernacDefinition of (discharge * Decls.definition_object_kind) * name_decl * definition_expr | VernacStartTheoremProof of Decls.theorem_kind * proof_expr list | VernacEndProof of proof_end | VernacExactProof of constr_expr | VernacAssumption of (discharge * Decls.assumption_object_kind) * Declaremods.inline * (ident_decl list * constr_expr) with_coercion list | VernacSymbol of (ident_decl list * constr_expr) with_coercion list | VernacInductive of inductive_kind * (inductive_expr * notation_declaration list) list | VernacFixpoint of discharge * fixpoints_expr | VernacCoFixpoint of discharge * cofixpoints_expr | VernacSchemeAll of Libnames.qualid Constrexpr.or_by_notation * (Id.t list) option | VernacScheme of (lident option * scheme) list | VernacSchemeEquality of equality_scheme_type * Libnames.qualid Constrexpr.or_by_notation | VernacCombinedScheme of lident * lident list | VernacUniverse of lident list | VernacSort of lident list | VernacConstraint of sort_constraint_expr list | VernacAddRewRule of lident * (universe_decl_expr option * constr_expr * constr_expr) list (* Gallina extensions *) | VernacCanonical of qualid or_by_notation | VernacCoercion of qualid or_by_notation * (coercion_class * coercion_class) option | VernacIdentityCoercion of lident * coercion_class * coercion_class | VernacNameSectionHypSet of lident * section_subset_expr (* Type classes *) | VernacInstance of name_decl * (* name *) local_binder_expr list * (* binders *) constr_expr * (* type *) (bool * constr_expr) option * (* body (bool=true when using {}) *) hint_info_expr | VernacDeclareInstance of ident_decl * (* name *) local_binder_expr list * (* binders *) constr_expr * (* type *) hint_info_expr | VernacContext of local_binder_expr list | VernacExistingInstance of (qualid * hint_info_expr) list (* instances names, priorities and patterns *) | VernacExistingClass of qualid (* inductive or definition name *) (* Resetting *) | VernacResetName of lident | VernacResetInitial | VernacBack of int (* Commands *) | VernacCreateHintDb of string * bool | VernacRemoveHints of string list * qualid list | VernacHints of string list * hints_expr | VernacAbbreviation of lident * (Id.t list * constr_expr) * syntax_modifier CAst.t list * Loc.t option (* warn about old deprecated "Notation" keyword, to remove when removing it *) | VernacArguments of qualid or_by_notation * vernac_argument_status list (* Main arguments status list *) * (Name.t * Glob_term.binding_kind) list list (* Extra implicit status lists *) * arguments_modifier list | VernacReserve of simple_binder list | VernacGeneralizable of (lident list) option | VernacSetOpacity of (Conv_oracle.level * qualid or_by_notation list) * bool | VernacSetStrategy of (Conv_oracle.level * qualid or_by_notation list) list | VernacMemOption of Goptions.option_name * Goptions.table_value list | VernacPrintOption of Goptions.option_name | VernacCheckMayEval of Redexpr.raw_red_expr option * Goal_select.t option * constr_expr | VernacGlobalCheck of constr_expr | VernacDeclareReduction of string * Redexpr.raw_red_expr | VernacPrint of printable | VernacSearch of searchable * Goal_select.t option * qualid list search_restriction | VernacLocate of locatable | VernacRegister of qualid * register_kind | VernacPrimitive of ident_decl * CPrimitives.op_or_type * constr_expr option | VernacComments of comment list | VernacAttributes of Attributes.vernac_flags (* Proof management *) | VernacAbort | VernacAbortAll | VernacRestart | VernacUndo of int | VernacUndoTo of int | VernacFocus of int option | VernacUnfocus | VernacUnfocused | VernacBullet of Proof_bullet.t | VernacSubproof of Goal_select.t option | VernacEndSubproof | VernacShow of showable | VernacCheckGuard | VernacValidateProof | VernacProof of Gentactic.raw_generic_tactic option * section_subset_expr option | VernacAddOption of Goptions.option_name * Goptions.table_value list | VernacRemoveOption of Goptions.option_name * Goptions.table_value list (** We classify vernacular expressions in two categories. [VernacSynterp] represents commands which have an effect on parsing or on parsing extensions. [VernacSynPure] represents commands which have no such effects. *) type 'a vernac_expr_gen = | VernacSynterp of 'a | VernacSynPure of synpure_vernac_expr type vernac_expr = synterp_vernac_expr vernac_expr_gen type control_flag_r = | ControlTime | ControlInstructions | ControlProfile of string option | ControlRedirect of string | ControlTimeout of int | ControlFail | ControlSucceed type control_flag = control_flag_r CAst.t type ('a, 'b) vernac_control_gen_r = { control : 'a list ; attrs : Attributes.vernac_flags ; expr : 'b vernac_expr_gen } and 'a vernac_control_gen = (control_flag, 'a) vernac_control_gen_r CAst.t type vernac_control = synterp_vernac_expr vernac_control_gen rocq-9.2.0/vernac/vernacextend.ml000066400000000000000000000245761516144147600170130ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* atts:Attributes.vernac_flags -> unit -> typed_vernac type plugin_args = Genarg.raw_generic_argument list (* Table of vernac entries *) let vernac_tab = (Hashtbl.create 211 : (Vernacexpr.extend_name, bool * (plugin_args -> vernac_command)) Hashtbl.t) let vinterp_add depr s f = Hashtbl.replace vernac_tab s (depr, f) let vinterp_map s = try Hashtbl.find vernac_tab s with Not_found -> user_err (str"Cannot find vernac command " ++ str s.ext_entry ++ str".") let warn_deprecated_command = let open CWarnings in create ~name:"deprecated-command" ~category:CWarnings.CoreCategories.deprecated (fun pr -> str "Deprecated vernacular command: " ++ pr) (* Interpretation of a vernac command *) let type_vernac opn converted_args ?loc ~atts = let depr, callback = vinterp_map opn in let () = if depr then let rules = Egramml.get_extend_vernac_rule opn in let pr_gram = function | Egramml.GramTerminal s -> str s | Egramml.GramNonTerminal _ -> str "_" in let pr = pr_sequence pr_gram rules in warn_deprecated_command pr; in callback converted_args ?loc ~atts (** VERNAC EXTEND registering *) type classifier = Genarg.raw_generic_argument list -> atts:Attributes.vernac_flags -> vernac_classification (** Classifiers *) module StringPair = struct type t = string * string let compare (s1, s2) (t1, t2) = let c = String.compare s1 t1 in if Int.equal c 0 then String.compare s2 t2 else c end module StringPairMap = Map.Make(StringPair) let classifiers : classifier array StringPairMap.t ref = ref StringPairMap.empty let get_vernac_classifier e args = let open Vernacexpr in (StringPairMap.find (e.ext_plugin, e.ext_entry) !classifiers).(e.ext_index) args let declare_vernac_classifier name f = classifiers := StringPairMap.add name f !classifiers let classify_as_query = VtQuery let classify_as_sideeff = VtSideff ([], VtLater) let classify_as_proofstep = VtProofStep { proof_block_detection = None} type (_, _) ty_sig = | TyNil : (vernac_command, atts:Attributes.vernac_flags -> vernac_classification) ty_sig | TyTerminal : string * ('r, 's) ty_sig -> ('r, 's) ty_sig | TyNonTerminal : ('a, 'b, 'c) Extend.ty_user_symbol * ('r, 's) ty_sig -> ('a -> 'r, 'a -> 's) ty_sig type ty_ml = TyML : bool * ('r, 's) ty_sig * 'r * 's option -> ty_ml let type_error () = CErrors.anomaly (Pp.str "Ill-typed VERNAC EXTEND") let rec untype_classifier : type r s. (r, s) ty_sig -> s -> classifier = function | TyNil -> fun f args -> begin match args with | [] -> f | _ :: _ -> type_error () end | TyTerminal (_, ty) -> fun f args -> untype_classifier ty f args | TyNonTerminal (tu, ty) -> fun f args -> let open Genarg in begin match args with | [] -> type_error () | GenArg (Rawwit tag, v) :: args -> match Genarg.genarg_type_eq tag (Egramml.proj_symbol tu) with | None -> type_error () | Some Refl -> untype_classifier ty (f v) args end (** Stupid GADTs forces us to duplicate the definition just for typing *) let rec untype_command : type r s. (r, s) ty_sig -> r -> plugin_args -> vernac_command = function | TyNil -> fun f args -> begin match args with | [] -> f | _ :: _ -> type_error () end | TyTerminal (_, ty) -> fun f args -> untype_command ty f args | TyNonTerminal (tu, ty) -> fun f args -> let open Genarg in begin match args with | [] -> type_error () | GenArg (Rawwit tag, v) :: args -> match genarg_type_eq tag (Egramml.proj_symbol tu) with | None -> type_error () | Some Refl -> untype_command ty (f v) args end let rec untype_user_symbol : type s a b c. (a, b, c) Extend.ty_user_symbol -> (s, Gramlib.Grammar.norec, a) Procq.Symbol.t = let open Extend in function | TUlist1 l -> Procq.Symbol.list1 (untype_user_symbol l) | TUlist1sep (l, s) -> Procq.Symbol.list1sep (untype_user_symbol l) (Procq.Symbol.tokens [Procq.TPattern (CLexer.terminal s)]) | TUlist0 l -> Procq.Symbol.list0 (untype_user_symbol l) | TUlist0sep (l, s) -> Procq.Symbol.list0sep (untype_user_symbol l) (Procq.Symbol.tokens [Procq.TPattern (CLexer.terminal s)]) | TUopt o -> Procq.Symbol.opt (untype_user_symbol o) | TUentry a -> Procq.Symbol.nterm (Procq.genarg_grammar (Genarg.ExtraArg a)) | TUentryl (a, i) -> Procq.Symbol.nterml (Procq.genarg_grammar (Genarg.ExtraArg a)) (string_of_int i) let rec untype_grammar : type r s. (r, s) ty_sig -> 'a Egramml.grammar_prod_item list = function | TyNil -> [] | TyTerminal (tok, ty) -> Egramml.GramTerminal tok :: untype_grammar ty | TyNonTerminal (tu, ty) -> let t = Genarg.rawwit (Egramml.proj_symbol tu) in let symb = untype_user_symbol tu in Egramml.GramNonTerminal (Loc.tag (t, symb)) :: untype_grammar ty let declare_dynamic_vernac_extend ~command ?entry ~depr cl ty f = let cl = untype_classifier ty cl in let f = untype_command ty f in let r = untype_grammar ty in let ext = { command with Vernacexpr.ext_index = 0 } in vinterp_add depr ext f; Egramml.declare_vernac_command_grammar ~allow_override:true ext entry r; declare_vernac_classifier (ext.ext_plugin, ext.ext_entry) [|cl|]; ext let is_static_linking_done = ref false let static_linking_done () = is_static_linking_done := true let static_vernac_extend ~plugin ~command ?classifier ?entry ~ignore_kw ext = let get_classifier (TyML (_, ty, _, cl)) = match cl with | Some cl -> untype_classifier ty cl | None -> match classifier with | Some cl -> fun _ ~atts -> cl ~atts command | None -> let e = match entry with | None -> "COMMAND" | Some e -> Procq.Entry.name e in let msg = Printf.sprintf "\ Vernac entry \"%s\" misses a classifier. \ A classifier is a function that returns an expression \ of type vernac_classification (see Vernacexpr). You can: \n\ - Use '... EXTEND %s CLASSIFIED AS QUERY ...' if the \ new vernacular command does not alter the system state;\n\ - Use '... EXTEND %s CLASSIFIED AS SIDEFF ...' if the \ new vernacular command alters the system state but not the \ parser nor it starts a proof or ends one;\n\ - Use '... EXTEND %s CLASSIFIED BY f ...' to specify \ a global function f. The function f will be called passing\ \"%s\" as the only argument;\n\ - Add a specific classifier in each clause using the syntax:\n\ '[...] => [ f ] -> [...]'.\n\ Specific classifiers have precedence over global \ classifiers. Only one classifier is called." command e e e command in CErrors.user_err (Pp.strbrk msg) in let cl = Array.map_of_list get_classifier ext in let ext_plugin = Option.default "__" plugin in let iter i (TyML (depr, ty, f, _)) = let f = untype_command ty f in let r = untype_grammar ty in let ext = Vernacexpr.{ ext_plugin; ext_entry = command; ext_index = i } in let () = vinterp_add depr ext f in let () = Egramml.declare_vernac_command_grammar ~allow_override:false ext entry r in let () = match plugin with | None -> let () = if !is_static_linking_done then CErrors.anomaly Pp.(str "static_vernac_extend in dynlinked code must pass non-None plugin.") in Egramml.extend_vernac_command_grammar ~ignore_kw ~undoable:false ext | Some plugin -> Mltop.add_init_function plugin (fun () -> Egramml.extend_vernac_command_grammar ~ignore_kw ~undoable:true ext) in () in let () = declare_vernac_classifier (ext_plugin, command) cl in let () = List.iteri iter ext in () (** VERNAC ARGUMENT EXTEND registering *) type 'a argument_rule = | Arg_alias of 'a Procq.Entry.t | Arg_rules of 'a Procq.Production.t list type 'a vernac_argument = { arg_printer : Environ.env -> Evd.evar_map -> 'a -> Pp.t; arg_parsing : 'a argument_rule; } let vernac_argument_extend ~plugin ~name ~ignore_kw arg = let wit = Genarg.create_arg name in let entry = match arg.arg_parsing with | Arg_alias e -> let () = Procq.register_grammar wit e in e | Arg_rules rules -> let e = Procq.create_generic_entry2 name (Genarg.rawwit wit) in let plugin_uid = Option.map (fun plugin -> (plugin, "vernacargextend:"^name)) plugin in let () = Egramml.grammar_extend ?plugin_uid ~ignore_kw e (Procq.Fresh (Gramlib.Gramext.First, [None, Some RightA, rules])) in e in let pr = arg.arg_printer in let pr x = Genprint.PrinterBasic (fun env sigma -> pr env sigma x) in let () = Genprint.register_vernac_print0 wit pr in (wit, entry) rocq-9.2.0/vernac/vernacextend.mli000066400000000000000000000136511516144147600171540ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* atts:Attributes.vernac_flags -> unit -> Vernactypes.typed_vernac type plugin_args = Genarg.raw_generic_argument list val type_vernac : Vernacexpr.extend_name -> plugin_args -> vernac_command (** {5 VERNAC EXTEND} *) type classifier = Genarg.raw_generic_argument list -> atts:Attributes.vernac_flags -> vernac_classification type (_, _) ty_sig = | TyNil : (vernac_command, atts:Attributes.vernac_flags -> vernac_classification) ty_sig | TyTerminal : string * ('r, 's) ty_sig -> ('r, 's) ty_sig | TyNonTerminal : ('a, 'b, 'c) Extend.ty_user_symbol * ('r, 's) ty_sig -> ('a -> 'r, 'a -> 's) ty_sig type ty_ml = TyML : bool (* deprecated *) * ('r, 's) ty_sig * 'r * 's option -> ty_ml (** Statically extend vernacular commands. This is used by coqpp VERNAC EXTEND. It should not be used directly, use [declare_dynamic_vernac_extend] instead. Commands added by plugins at Declare ML Module / Require time should provide [plugin]. Commands added without providing [plugin] cannot be removed from the grammar or modified. Not passing [plugin] is possible for non-plugin rocq-runtime commands and deprecated for all other callers. *) val static_vernac_extend : plugin:string option -> command:string -> ?classifier:(atts:Attributes.vernac_flags -> string -> vernac_classification) -> ?entry:Vernacexpr.vernac_expr Procq.Entry.t -> ignore_kw:bool -> ty_ml list -> unit (** Used to tell the system that all future vernac extends are from plugins. *) val static_linking_done : unit -> unit (** Dynamically extend vernacular commands (for instance when importing some module). Reusing a [command] string will replace previous uses. The result is undefined and probably produces anomalies if the previous grammar rule is still active and was different from the new one. The polymorphic arguments are as in [TyML]. The declared grammar extension is disabled, one needs to call [Egramml.extend_vernac_command_grammar] in order to enable it. That call should use [undoable:true] to make it possible to disable the extension, e.g. by backtracking over the command which enabled it. *) val declare_dynamic_vernac_extend : command:Vernacexpr.extend_name -> ?entry:Vernacexpr.vernac_expr Procq.Entry.t -> depr:bool -> 's (* classifier *) -> ('r, 's) ty_sig (* grammar *) -> 'r (* command interpretation *) -> Vernacexpr.extend_name (** {5 VERNAC ARGUMENT EXTEND} *) type 'a argument_rule = | Arg_alias of 'a Procq.Entry.t (** This is used because CAMLP5 parser can be dumb about rule factorization, which sometimes requires two entries to be the same. *) | Arg_rules of 'a Procq.Production.t list (** There is a discrepancy here as we use directly extension rules and thus entries instead of ty_user_symbol and thus arguments as roots. *) type 'a vernac_argument = { arg_printer : Environ.env -> Evd.evar_map -> 'a -> Pp.t; arg_parsing : 'a argument_rule; } val vernac_argument_extend : plugin:string option -> name:string -> ignore_kw:bool -> 'a vernac_argument -> 'a Genarg.vernac_genarg_type * 'a Procq.Entry.t (** {5 STM classifiers} *) val get_vernac_classifier : Vernacexpr.extend_name -> classifier (** Standard constant classifiers *) val classify_as_query : vernac_classification val classify_as_sideeff : vernac_classification val classify_as_proofstep : vernac_classification rocq-9.2.0/vernac/vernacinterp.ml000066400000000000000000000173371516144147600170220ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Some false) f) in if VernacControl.after_last_phase ~loc control then noop else res (* [loc] is the [Loc.t] of the vernacular command being interpreted. *) let rec interp_expr ?loc ~st cmd = let before_univs = Global.universes () in let pstack, pm = with_generic_atts ~check:false cmd.attrs (fun ~atts -> interp_expr_core ?loc ~atts ~st cmd.expr) in let after_univs = Global.universes () in if before_univs == after_univs then pstack, pm else let f = Declare.Proof.update_sigma_univs after_univs in Option.map (Vernacstate.LemmaStack.map ~f) pstack, pm and interp_expr_core ?loc ~atts ~st c = match c with (* The STM should handle that, but LOAD bypasses the STM... *) | VernacSynPure VernacAbortAll -> CErrors.user_err (Pp.str "AbortAll cannot be used through the Load command") | VernacSynPure VernacRestart -> CErrors.user_err (Pp.str "Restart cannot be used through the Load command") | VernacSynPure VernacUndo _ -> CErrors.user_err (Pp.str "Undo cannot be used through the Load command") | VernacSynPure VernacUndoTo _ -> CErrors.user_err (Pp.str "UndoTo cannot be used through the Load command") (* Resetting *) | VernacSynPure VernacResetName _ -> CErrors.anomaly (Pp.str "VernacResetName not handled by Stm.") | VernacSynPure VernacResetInitial -> CErrors.anomaly (Pp.str "VernacResetInitial not handled by Stm.") | VernacSynPure VernacBack _ -> CErrors.anomaly (Pp.str "VernacBack not handled by Stm.") | VernacSynterp EVernacLoad (verbosely, fname) -> Attributes.unsupported_attributes atts; vernac_load ~verbosely fname | v -> let fv = Vernacentries.translate_vernac ?loc ~atts v in let stack = st.Vernacstate.interp.lemmas in let program = st.Vernacstate.interp.program in let {Vernactypes.prog; proof; opaque_access=(); }, () = Vernactypes.run fv { prog=program; proof=stack; opaque_access=(); } in proof, prog and vernac_load ~verbosely entries = (* Note that no proof should be open here, so the state here is just token for now *) let st = Vernacstate.freeze_full_state () in let v_mod = if verbosely then Flags.verbosely else Flags.silently in let interp_entry (stack, pm) (CAst.{ loc; v = cmd }, synterp_st) = Vernacstate.Synterp.unfreeze synterp_st; let st = Vernacstate.{ synterp = synterp_st; interp = { st.interp with Interp.lemmas = stack; program = pm }} in v_mod (interp_control ~st) (CAst.make ?loc cmd) in let pm = st.Vernacstate.interp.program in let stack = st.Vernacstate.interp.lemmas in let stack, pm = Dumpglob.with_glob_output Dumpglob.NoGlob (fun () -> List.fold_left interp_entry (stack, pm) entries) () in (* If Load left a proof open, we fail too. *) if Option.has_some stack then CErrors.user_err Pp.(str "Files processed by Load cannot leave open proofs."); stack, pm and interp_control ~st ({ CAst.v = cmd; loc }) = Util.try_finally (fun () -> Loc.set_current_command_loc loc; interp_control_gen ~loc ~st cmd.control ~unfreeze_transient:Vernacstate.Synterp.unfreeze (fun () -> interp_expr ?loc ~st cmd)) () (fun () -> Loc.set_current_command_loc None) () (* XXX: This won't properly set the proof mode, as of today, it is controlled by the STM. Thus, we would need access information from the classifier. The proper fix is to move it to the STM, however, the way the proof mode is set there makes the task non trivial without a considerable amount of refactoring. *) (* Interpreting a possibly delayed proof *) let interp_qed_delayed ~proof ~st pe = let stack = st.Vernacstate.interp.lemmas in let pm = st.Vernacstate.interp.program in let stack = Option.cata (fun stack -> snd @@ Vernacstate.LemmaStack.pop stack) None stack in let pm = NeList.map_head (fun pm -> match pe with | Admitted -> Declare.Proof.save_lemma_admitted_delayed ~pm ~proof | Proved (_,idopt) -> let pm = Declare.Proof.save_lemma_proved_delayed ~pm ~proof ~idopt in pm) pm in stack, pm let interp_qed_delayed_control ~proof ~st ~control { CAst.loc; v=pe } = interp_control_gen ~loc ~st control ~unfreeze_transient:(fun () -> ()) (fun () -> interp_qed_delayed ~proof ~st pe) (* General interp with management of state *) (* Be careful with the cache here in case of an exception. *) let interp_gen ~verbosely ~st ~interp_fn cmd = try let v_mod = if verbosely then Flags.verbosely else Flags.silently in let ontop = v_mod (interp_fn ~st) cmd in Vernacstate.Declare.set ontop [@ocaml.warning "-3"]; Vernacstate.Interp.freeze_interp_state () with exn -> let exn = Exninfo.capture exn in let exn = locate_if_not_already ?loc:cmd.CAst.loc exn in Vernacstate.Interp.invalidate_cache (); Exninfo.iraise exn (* Regular interp *) let interp ~intern ?(verbosely=true) ~st cmd = Vernacstate.unfreeze_full_state st; vernac_pperr_endline Pp.(fun () -> str "interpreting: " ++ Ppvernac.pr_vernac_expr cmd.CAst.v.expr); let entry = NewProfile.profile "synterp" (fun () -> Synterp.synterp_control ~intern cmd) () in let interp = NewProfile.profile "interp" (fun () -> interp_gen ~verbosely ~st ~interp_fn:interp_control entry) () in Vernacstate.{ synterp = Vernacstate.Synterp.freeze (); interp } let interp_entry ?(verbosely=true) ~st entry = Vernacstate.unfreeze_full_state st; interp_gen ~verbosely ~st ~interp_fn:interp_control entry module Intern = struct let fs_intern dp = match Loadpath.locate_absolute_library dp with | Ok file -> Feedback.feedback @@ Feedback.FileDependency (Some file, Names.DirPath.to_string dp); let res, provenance = Library.intern_from_file file in Result.iter (fun _ -> Feedback.feedback @@ Feedback.FileLoaded (Names.DirPath.to_string dp, file)) res; res, provenance | Error e -> Loadpath.Error.raise dp e end let fs_intern = Intern.fs_intern let interp_qed_delayed_proof ~proof ~st ~control (CAst.{loc; v = pe } as e) : Vernacstate.Interp.t = NewProfile.profile "interp-delayed-qed" (fun () -> interp_gen ~verbosely:false ~st ~interp_fn:(interp_qed_delayed_control ~proof ~control) e) () rocq-9.2.0/vernac/vernacinterp.mli000066400000000000000000000025331516144147600171630ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ?verbosely:bool -> st:Vernacstate.t -> Vernacexpr.vernac_control -> Vernacstate.t val interp_entry : ?verbosely:bool -> st:Vernacstate.t -> Synterp.vernac_control_entry -> Vernacstate.Interp.t (** Execute a Qed but with a proof_object which may contain a delayed proof and won't be forced *) val interp_qed_delayed_proof : proof:Declare.Proof.proof_object -> st:Vernacstate.t -> control:unit VernacControl.control_entries -> Vernacexpr.proof_end CAst.t -> Vernacstate.Interp.t rocq-9.2.0/vernac/vernacoptions.ml000066400000000000000000000043741516144147600172110ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* unset_option_value_gen ~locality ~stage key | OptionSetString s -> set_string_option_value_gen ~locality ~stage key s | OptionSetInt n -> set_int_option_value_gen ~locality ~stage key (Some n) | OptionSetTrue -> set_bool_option_value_gen ~locality ~stage key true let warn_set_append_deprecated = CWarnings.create ~name:"set-append-deprecated" ~category:Deprecation.Version.v9_1 Pp.(fun () -> str "Set ... Append is not supported.") let vernac_set_option ~locality ~stage table v = let table = if String.equal "Append" (List.last table) then begin let table = List.drop_last table in let () = match table with | ["Warnings"]|["Debug"] -> () | _ -> CErrors.user_err Pp.(str "Set ... Append not allowed with " ++ prlist_with_sep spc str table ++ str ".") in warn_set_append_deprecated (); table end else table in vernac_set_option ~locality ~stage table v let iter_table f k v = Goptions.iter_table (Global.env()) f k v let vernac_add_option local = iter_table { aux = fun table env x -> table.add env local x } let vernac_remove_option local = iter_table { aux = fun table env x -> table.remove env local x } let vernac_mem_option = iter_table { aux = fun table -> table.mem } let vernac_print_option key = try (get_ref_table key).print () with Not_found -> try (get_string_table key).print () with Not_found -> try print_option_value key with Not_found -> error_undeclared_key key rocq-9.2.0/vernac/vernacoptions.mli000066400000000000000000000021341516144147600173520ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* stage:Summary.Stage.t -> option_name -> Vernacexpr.option_setting -> unit val vernac_add_option : Libobject.locality -> option_name -> table_value list -> unit val vernac_remove_option : Libobject.locality -> option_name -> table_value list -> unit val vernac_mem_option : option_name -> table_value list -> unit val vernac_print_option : option_name -> unit rocq-9.2.0/vernac/vernacprop.ml000066400000000000000000000027551516144147600164770ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* true | _ -> false) v.control (* Navigation commands are allowed in a coqtop session but not in a .v file *) let is_navigation_vernac = function | VernacSynPure (VernacResetInitial | VernacResetName _ | VernacBack _) -> true | _ -> false (* NB: Reset is now allowed again as asked by A. Chlipala *) let is_reset = function | VernacSynPure (VernacResetInitial | VernacResetName _) -> true | _ -> false let is_debug = function | VernacSynterp (VernacSetOption (_, ["Ltac";"Debug"], _)) -> true | _ -> false let is_undo = function | VernacSynPure (VernacUndo _ | VernacUndoTo _) -> true | _ -> false rocq-9.2.0/vernac/vernacprop.mli000066400000000000000000000017441516144147600166450ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* bool val is_navigation_vernac : vernac_expr -> bool val is_reset : vernac_expr -> bool val is_debug : vernac_expr -> bool val is_undo : vernac_expr -> bool rocq-9.2.0/vernac/vernacstate.ml000066400000000000000000000220041516144147600166240ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t val unfreeze : t -> unit module Stm : sig val make_shallow : t -> t val lib : t -> Lib.Interp.frozen val summary : t -> Summary.Interp.frozen val replace_summary : t -> Summary.Interp.frozen -> t end end = struct type t = Lib.Interp.frozen * Summary.Interp.frozen let freeze () = (Lib.Interp.freeze (), Summary.Interp.freeze_summaries ()) let unfreeze (fl,fs) = Lib.Interp.unfreeze fl; Summary.Interp.unfreeze_summaries fs module Stm = struct let make_shallow (lib, summary) = Lib.Interp.drop_objects lib, Summary.Interp.make_marshallable summary let lib = fst let summary = snd let replace_summary (lib,_) summary = (lib,summary) end end module System = struct let protect f x = let freeze () = let s = Synterp.freeze () in let i = Interp_system.freeze () in s, i in let unfreeze (s,i) = Synterp.unfreeze s; Interp_system.unfreeze i in let open Memprof_coq.Resource_bind in let& () = Util.protect_state ~freeze ~unfreeze in f x end module LemmaStack = struct type t = Declare.Proof.t NeList.t let map ~f x = NeList.map f x let map_top ~f x = NeList.map_head f x let pop x = NeList.head x, NeList.tail x let get_top = NeList.head let with_top x ~f = f (get_top x) let push ontop a = NeList.push a ontop let get_all_proof_names (pf : t) = let prj x = Declare.Proof.get x in List.map Proof.(function pf -> (data (prj pf)).name) (NeList.to_list pf) let copy_info src tgt = Declare.Proof.map ~f:(fun _ -> Declare.Proof.get tgt) src let copy_info ~(src : t) ~(tgt : t) = NeList.map2 copy_info src tgt end let s_cache = ref None let s_lemmas = ref None let s_program = ref (NeList.singleton Declare.OblState.empty) module Interp = struct module System = Interp_system type t = { system : System.t; (* summary + libstack *) lemmas : LemmaStack.t option; (* proofs of lemmas currently opened *) program : Declare.OblState.t NeList.t; (* obligations table *) opaques : Opaques.Summary.t; (* opaque proof terms *) } let invalidate_cache () = s_cache := None let update_cache rf v = rf := Some v; v let do_if_not_cached rf f v = match !rf with | None -> rf := Some v; f v | Some vc when vc != v -> rf := Some v; f v | Some _ -> () let freeze_interp_state () = { system = update_cache s_cache (System.freeze ()); lemmas = !s_lemmas; program = !s_program; opaques = Opaques.Summary.freeze (); } let make_shallow s = { s with system = System.Stm.make_shallow s.system } let unfreeze_interp_state { system; lemmas; program; opaques } = do_if_not_cached s_cache System.unfreeze system; s_lemmas := lemmas; s_program := program; Opaques.Summary.unfreeze opaques end type t = { synterp: Synterp.t ; interp: Interp.t } let freeze_full_state () = { synterp = Synterp.freeze (); interp = Interp.freeze_interp_state (); } let unfreeze_full_state st = NewProfile.profile "unfreeze_full_state" (fun () -> Synterp.unfreeze st.synterp; Interp.unfreeze_interp_state st.interp) () (* Compatibility module *) module Declare_ = struct let get_program () = !s_program let set (pstate,pm) = s_lemmas := pstate; s_program := pm let get_pstate () = Option.map (LemmaStack.with_top ~f:(fun x -> x)) !s_lemmas let unfreeze x = s_lemmas := Some x exception NoCurrentProof let () = CErrors.register_handler begin function | NoCurrentProof -> Some (Pp.(str "No focused proof (No proof-editing in progress).")) | _ -> None end let cc f = match !s_lemmas with | None -> raise NoCurrentProof | Some x -> LemmaStack.with_top ~f x let cc_stack f = match !s_lemmas with | None -> raise NoCurrentProof | Some x -> f x let dd f = match !s_lemmas with | None -> raise NoCurrentProof | Some x -> s_lemmas := Some (LemmaStack.map_top ~f x) let there_are_pending_proofs () = !s_lemmas <> None let get_open_goals () = cc Declare.Proof.get_open_goals let give_me_the_proof_opt () = Option.map (LemmaStack.with_top ~f:Declare.Proof.get) !s_lemmas let give_me_the_proof () = cc Declare.Proof.get let get_current_proof_name () = cc Declare.Proof.get_name let map_proof f = dd (Declare.Proof.map ~f) let with_current_proof f = match !s_lemmas with | None -> raise NoCurrentProof | Some stack -> let pf, res = LemmaStack.with_top stack ~f:(Declare.Proof.map_fold ~f) in let stack = LemmaStack.map_top stack ~f:(fun _ -> pf) in s_lemmas := Some stack; res let return_proof () = cc Declare.Proof.return_proof let close_future_proof ~feedback_id pf = NewProfile.profile "close_future_proof" (fun () -> cc (fun pt -> Declare.Proof.close_future_proof ~feedback_id pt pf)) () let close_proof ~opaque ~keep_body_ucst_separate = NewProfile.profile "close_proof" (fun () -> cc (fun pt -> Declare.Proof.close_proof ~opaque ~keep_body_ucst_separate pt)) () let discard_all () = s_lemmas := None let update_sigma_univs ugraph = dd (Declare.Proof.update_sigma_univs ugraph) let get_current_context () = cc Declare.Proof.get_current_context let get_all_proof_names () = try cc_stack LemmaStack.get_all_proof_names with NoCurrentProof -> [] let copy_terminators ~src ~tgt = match src, tgt with | None, None -> None | Some _ , None -> None | None, Some x -> Some x | Some src, Some tgt -> Some (LemmaStack.copy_info ~src ~tgt) end (* STM-specific state-handling *) module Stm = struct (* Proof-related state, for workers; ideally the two counters would be contained in the lemmas state themselves, as there is no need for evar / metas to be global among proofs *) type nonrec pstate = LemmaStack.t option * int * (* Evarutil.meta_counter_summary_tag *) int (* Evd.evar_counter_summary_tag *) (* Parts of the system state that are morally part of the proof state *) let pstate { interp = { lemmas; system }} = let st = Interp.System.Stm.summary system in lemmas, Summary.Interp.project_from_summary st Evarutil.meta_counter_summary_tag, Summary.Interp.project_from_summary st Evd.evar_counter_summary_tag let set_pstate ({ interp = { lemmas; system } } as s) (pstate,c1,c2) = { s with interp = { s.interp with lemmas = Declare_.copy_terminators ~src:s.interp.lemmas ~tgt:pstate ; system = Interp.System.Stm.replace_summary s.interp.system begin let st = Interp.System.Stm.summary s.interp.system in let st = Summary.Interp.modify_summary st Evarutil.meta_counter_summary_tag c1 in let st = Summary.Interp.modify_summary st Evd.evar_counter_summary_tag c2 in st end } } type non_pstate = Summary.Synterp.frozen * Lib.Synterp.frozen * Summary.Interp.frozen * Lib.Interp.frozen let non_pstate { synterp; interp } = let system = interp.system in let st = Interp.System.Stm.summary system in let st = Summary.Interp.remove_from_summary st Evarutil.meta_counter_summary_tag in let st = Summary.Interp.remove_from_summary st Evd.evar_counter_summary_tag in Synterp.Stm.summary synterp, Synterp.Stm.lib synterp, st, Interp.System.Stm.lib system let same_env { interp = { system = s1 } } { interp = { system = s2 } } = let s1 = Interp.System.Stm.summary s1 in let e1 = Summary.Interp.project_from_summary s1 Global.global_env_summary_tag in let s2 = Interp.System.Stm.summary s2 in let e2 = Summary.Interp.project_from_summary s2 Global.global_env_summary_tag in e1 == e2 let make_shallow st = { interp = Interp.make_shallow st.interp ; synterp = Synterp.Stm.make_shallow st.synterp } end module Declare = Declare_ rocq-9.2.0/vernac/vernacstate.mli000066400000000000000000000103501516144147600167760ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t val freeze : unit -> t val unfreeze : t -> unit val parsing : t -> Procq.frozen_t end module System : sig (** [protect f x] runs [f x] and discards changes in the system state (both [Synterp.t] and [Interp.System.t]). It doesn't touch the proof functional state in [Interp.t] *) val protect : ('a -> 'b) -> 'a -> 'b end module LemmaStack : sig type t val pop : t -> Declare.Proof.t * t option val push : t option -> Declare.Proof.t -> t val map : f:(Declare.Proof.t -> Declare.Proof.t) -> t -> t val map_top : f:(Declare.Proof.t -> Declare.Proof.t) -> t -> t val with_top : t -> f:(Declare.Proof.t -> 'a ) -> 'a val get_top : t -> Declare.Proof.t val get_all_proof_names : t -> Names.Id.t list end module Interp : sig module System : sig type t end type t = { system : System.t (** summary + libstack *) ; lemmas : LemmaStack.t option (** proofs of lemmas currently opened *) ; program : Declare.OblState.t NeList.t (** program mode table. One per open module/section including the toplevel module. *) ; opaques : Opaques.Summary.t (** qed-terminated proofs *) } val freeze_interp_state : unit -> t val unfreeze_interp_state : t -> unit (* WARNING: Do not use, it will go away in future releases *) val invalidate_cache : unit -> unit end type t = { synterp: Synterp.t ; interp: Interp.t } val freeze_full_state : unit -> t val unfreeze_full_state : t -> unit (** STM-specific state handling *) module Stm : sig (** Proof state + meta/evar counters *) type pstate val pstate : t -> pstate val set_pstate : t -> pstate -> t (** Rest of the state, unfortunately this is used in low-level so we need to expose it *) type non_pstate = Summary.Synterp.frozen * Lib.Synterp.frozen * Summary.Interp.frozen * Lib.Interp.frozen val non_pstate : t -> non_pstate (** Checks if two states have the same Environ.env (physical eq) *) val same_env : t -> t -> bool (** Call [Lib.drop_objects] on the state *) val make_shallow : t -> t end (* Compatibility module: Do Not Use *) module Declare : sig exception NoCurrentProof val there_are_pending_proofs : unit -> bool val get_open_goals : unit -> int val give_me_the_proof : unit -> Proof.t val give_me_the_proof_opt : unit -> Proof.t option val get_current_proof_name : unit -> Names.Id.t val map_proof : (Proof.t -> Proof.t) -> unit val with_current_proof : (Proof.t -> Proof.t * 'a) -> 'a val return_proof : unit -> Declare.Proof.closed_proof_output val close_future_proof : feedback_id:Stateid.t -> Declare.Proof.closed_proof_output Future.computation -> Declare.Proof.proof_object val close_proof : opaque:Vernacexpr.opacity_flag -> keep_body_ucst_separate:bool -> Declare.Proof.proof_object val discard_all : unit -> unit val update_sigma_univs : UGraph.t -> unit val get_current_context : unit -> Evd.evar_map * Environ.env val get_all_proof_names : unit -> Names.Id.t list val copy_terminators : src:LemmaStack.t option -> tgt:LemmaStack.t option -> LemmaStack.t option (* Low-level stuff *) val get_program : unit -> Declare.OblState.t NeList.t val set : LemmaStack.t option * Declare.OblState.t NeList.t -> unit val get_pstate : unit -> Declare.Proof.t option val unfreeze : LemmaStack.t -> unit end [@@ocaml.deprecated "(8.11) This module is internal and should not be used, instead, thread the proof state"] rocq-9.2.0/vernac/vernactypes.ml000066400000000000000000000152171516144147600166600ustar00rootroot00000000000000 (** [('a,'b,'x) runner] means that any function taking ['a] and returning ['b] and some additional data can be interpreted as a function on a state ['x]. The additional return data ['d] is useful when combining runners. We don't need an additional input data as it can just go in the closure. *) type ('a,'b,'x) runner = { run : 'd. 'x -> ('a -> 'b * 'd) -> 'x * 'd } module Prog = struct type state = Declare.OblState.t type stack = state NeList.t type (_,_) t = | Ignore : (unit, unit) t | Modify : (state, state) t | Read : (state, unit) t | Push : (unit, unit) t | Pop : (state, unit) t let runner (type a b) (ty:(a,b) t) : (a,b,stack) runner = { run = fun pm f -> match ty with | Ignore -> let (), v = f () in pm, v | Modify -> let st, pm = NeList.repr pm in let st, v = f st in NeList.of_repr (st,pm), v | Read -> let (), v = f (NeList.head pm) in pm, v | Push -> let (), v = f () in NeList.push Declare.OblState.empty (Some pm), v | Pop -> let st, pm = NeList.repr pm in assert (not (CList.is_empty pm)); let (), v = f st in NeList.of_list pm, v } end module Proof = struct module LStack = Vernacstate.LemmaStack type state = Declare.Proof.t type stack = LStack.t option type (_,_) t = | Ignore : (unit, unit) t | Modify : (state, state) t | Read : (state, unit) t | ReadOpt : (state option, unit) t | Reject : (unit, unit) t | Close : (state, unit) t | Open : (unit, state) t let use = function | None -> CErrors.user_err (Pp.str "Command not supported (No proof-editing in progress).") | Some stack -> LStack.pop stack let runner (type a b) (ty:(a,b) t) : (a,b,stack) runner = { run = fun stack f -> match ty with | Ignore -> let (), v = f () in stack, v | Modify -> let p, rest = use stack in let p, v = f p in Some (LStack.push rest p), v | Read -> let p, _ = use stack in let (), v = f p in stack, v | ReadOpt -> let p = Option.map LStack.get_top stack in let (), v = f p in stack, v | Reject -> let () = if Option.has_some stack then CErrors.user_err (Pp.str "Command not supported (Open proofs remain).") in let (), v = f () in stack, v | Close -> let p, rest = use stack in let (), v = f p in rest, v | Open -> let p, v = f () in Some (LStack.push stack p), v } end module OpaqueAccess = struct (* Modification of opaque tables (by Require registering foreign tables and Qed/abstract/etc adding entries to the local table) is currently not tracked by vernactypes. *) type _ t = | Ignore : unit t | Access : Global.indirect_accessor t let access = Library.indirect_accessor[@@warning "-3"] let runner (type a) (ty:a t) : (a,unit,unit) runner = { run = fun () f -> match ty with | Ignore -> let (), v = f () in (), v | Access -> let (), v = f access in (), v } end (* lots of messing with tuples in there, can we do better? *) let combine_runners (type a b x c d y) (r1:(a,b,x) runner) (r2:(c,d,y) runner) : (a*c, b*d, x*y) runner = { run = fun (x,y) f -> match r1.run x @@ fun x -> match r2.run y @@ fun y -> match f (x,y) with ((b, d), o) -> (d, (b, o)) with (y, (b, o)) -> (b, (y, o)) with (x, (y, o)) -> ((x, y), o) } type ('prog,'proof,'opaque_access) state_gen = { prog : 'prog; proof : 'proof; opaque_access : 'opaque_access; } let tuple { prog; proof; opaque_access } = (prog, proof), opaque_access let untuple ((prog, proof), opaque_access) = { prog; proof; opaque_access } type no_state = (unit, unit, unit) state_gen let no_state = { prog = (); proof = (); opaque_access = (); } let ignore_state = { prog = Prog.Ignore; proof = Proof.Ignore; opaque_access = OpaqueAccess.Ignore } type 'r typed_vernac_gen = TypedVernac : { spec : (('inprog, 'outprog) Prog.t, ('inproof, 'outproof) Proof.t, 'inaccess OpaqueAccess.t) state_gen; run : ('inprog, 'inproof, 'inaccess) state_gen -> ('outprog, 'outproof, unit) state_gen * 'r; } -> 'r typed_vernac_gen let map_typed_vernac f (TypedVernac {spec; run}) = TypedVernac {spec; run = (fun st -> Util.on_snd f (run st)) } type typed_vernac = unit typed_vernac_gen type full_state = (Prog.stack,Vernacstate.LemmaStack.t option,unit) state_gen let run (TypedVernac { spec = { prog; proof; opaque_access }; run }) (st:full_state) : full_state * _ = let ( * ) = combine_runners in let runner = Prog.runner prog * Proof.runner proof * OpaqueAccess.runner opaque_access in let st, v = runner.run (tuple st) @@ fun st -> let st, v= run @@ untuple st in tuple st, v in untuple st, v let typed_vernac_gen spec run = TypedVernac { spec; run } let typed_vernac spec run = TypedVernac { spec; run = (fun st -> run st, () ) } let vtdefault f = typed_vernac ignore_state (fun (_:no_state) -> let () = f () in no_state) let vtnoproof f = typed_vernac { ignore_state with proof = Reject } (fun (_:no_state) -> let () = f () in no_state) let vtcloseproof f = typed_vernac { ignore_state with prog = Modify; proof = Close } (fun {prog; proof} -> let prog = f ~lemma:proof ~pm:prog in { no_state with prog }) let vtopenproof f = typed_vernac { ignore_state with proof = Open } (fun (_:no_state) -> let proof = f () in { no_state with proof }) let vtmodifyproof f = typed_vernac { ignore_state with proof = Modify } (fun {proof} -> let proof = f ~pstate:proof in { no_state with proof }) let vtreadproofopt f = typed_vernac { ignore_state with proof = ReadOpt } (fun {proof} -> let () = f ~pstate:proof in no_state) let vtreadproof f = typed_vernac { ignore_state with proof = Read } (fun {proof} -> let () = f ~pstate:proof in no_state) let vtreadprogram f = typed_vernac { ignore_state with prog = Read } (fun {prog} -> let () = f ~pm:prog in no_state) let vtmodifyprogram f = typed_vernac { ignore_state with prog = Modify } (fun {prog} -> let prog = f ~pm:prog in { no_state with prog }) let vtdeclareprogram f = typed_vernac { ignore_state with prog = Read; proof = Open } (fun {prog} -> let proof = f ~pm:prog in { no_state with proof }) let vtopenproofprogram f = typed_vernac { ignore_state with prog = Modify; proof = Open } (fun {prog} -> let prog, proof = f ~pm:prog in { no_state with prog; proof; }) let vtopaqueaccess f = typed_vernac { ignore_state with opaque_access = Access } (fun {opaque_access} -> let () = f ~opaque_access in no_state) rocq-9.2.0/vernac/vernactypes.mli000066400000000000000000000073271516144147600170340ustar00rootroot00000000000000(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* ('outprog, 'outproof, unit) state_gen * 'r; } -> 'r typed_vernac_gen type typed_vernac = unit typed_vernac_gen val typed_vernac_gen : (('inprog, 'outprog) Prog.t, ('inproof, 'outproof) Proof.t, 'inaccess OpaqueAccess.t) state_gen -> (('inprog, 'inproof, 'inaccess) state_gen -> ('outprog, 'outproof, unit) state_gen * 'r) -> 'r typed_vernac_gen val map_typed_vernac : ('a -> 'b) -> 'a typed_vernac_gen -> 'b typed_vernac_gen val typed_vernac : (('inprog, 'outprog) Prog.t, ('inproof, 'outproof) Proof.t, 'inaccess OpaqueAccess.t) state_gen -> (('inprog, 'inproof, 'inaccess) state_gen -> ('outprog, 'outproof, unit) state_gen) -> typed_vernac type full_state = (Prog.stack, Vernacstate.LemmaStack.t option, unit) state_gen val run : 'r typed_vernac_gen -> full_state -> full_state * 'r (** Some convenient typed_vernac constructors. Used by coqpp. *) val vtdefault : (unit -> unit) -> typed_vernac val vtnoproof : (unit -> unit) -> typed_vernac val vtcloseproof : (lemma:Declare.Proof.t -> pm:Declare.OblState.t -> Declare.OblState.t) -> typed_vernac val vtopenproof : (unit -> Declare.Proof.t) -> typed_vernac val vtmodifyproof : (pstate:Declare.Proof.t -> Declare.Proof.t) -> typed_vernac val vtreadproofopt : (pstate:Declare.Proof.t option -> unit) -> typed_vernac val vtreadproof : (pstate:Declare.Proof.t -> unit) -> typed_vernac val vtreadprogram : (pm:Declare.OblState.t -> unit) -> typed_vernac val vtmodifyprogram : (pm:Declare.OblState.t -> Declare.OblState.t) -> typed_vernac val vtdeclareprogram : (pm:Declare.OblState.t -> Declare.Proof.t) -> typed_vernac val vtopenproofprogram : (pm:Declare.OblState.t -> Declare.OblState.t * Declare.Proof.t) -> typed_vernac val vtopaqueaccess : (opaque_access:Global.indirect_accessor -> unit) -> typed_vernac